summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools')
-rw-r--r--contrib/llvm/tools/bugpoint/BugDriver.cpp6
-rw-r--r--contrib/llvm/tools/bugpoint/BugDriver.h19
-rw-r--r--contrib/llvm/tools/bugpoint/CrashDebugger.cpp265
-rw-r--r--contrib/llvm/tools/bugpoint/ExecutionDriver.cpp41
-rw-r--r--contrib/llvm/tools/bugpoint/ExtractFunction.cpp71
-rw-r--r--contrib/llvm/tools/bugpoint/ListReducer.h12
-rw-r--r--contrib/llvm/tools/bugpoint/Miscompilation.cpp277
-rw-r--r--contrib/llvm/tools/bugpoint/ToolRunner.cpp217
-rw-r--r--contrib/llvm/tools/bugpoint/ToolRunner.h50
-rw-r--r--contrib/llvm/tools/bugpoint/bugpoint.cpp10
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/CXString.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/Index.h130
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTContext.h190
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h122
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Attr.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def25
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CharUnits.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentSema.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DataRecursiveASTVisitor.h2691
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Decl.h316
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclBase.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h75
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h24
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h15
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h40
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h13
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h250
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Expr.h680
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h846
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h203
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h129
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h75
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Mangle.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h1112
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h9
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h9
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h468
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Stmt.h243
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h135
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h80
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h647
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h116
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TemplateName.h53
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Type.h770
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h41
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def1
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h71
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h831
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h89
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h38
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CFG.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h49
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Attr.td204
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td278
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Attributes.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.def48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.h132
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def5
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def24
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def2612
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td10
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td35
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td84
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td80
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td123
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td720
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td25
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/FileManager.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h23
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def10
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Module.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def150
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h51
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h26
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td15
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h67
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h141
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def22
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h73
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td77
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h47
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Action.h69
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td51
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td39
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Compilation.h34
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Driver.h77
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Job.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Options.td218
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h74
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Types.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/Commit.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/Format/Format.h201
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h29
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def30
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h19
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/Utils.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h81
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Pragma.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h42
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/Parser.h73
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h98
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Initialization.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Lookup.h20
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h29
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Overload.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h47
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Sema.h592
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Template.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h42
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h18
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h264
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h167
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h107
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/Module.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h149
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h88
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h24
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h33
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h19
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h33
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h51
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h71
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h29
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h57
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h26
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h36
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h127
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h62
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h93
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Core/Lookup.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h31
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/module.modulemap6
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp52
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransGCAttrs.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTContext.cpp565
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp65
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CXXABI.h12
-rw-r--r--contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp85
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Decl.cpp600
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclBase.cpp67
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp90
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp52
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp148
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Expr.cpp686
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp411
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp709
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp360
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp293
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Mangle.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp522
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NSAPI.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp417
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp86
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp545
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Stmt.cpp1328
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp86
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtObjC.cpp73
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp884
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp209
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp119
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp117
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateName.cpp54
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Type.cpp278
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp324
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h22
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp120
-rw-r--r--contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFG.cpp187
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp127
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp135
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp53
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Attributes.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Builtins.cpp96
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/FileManager.cpp92
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Module.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp168
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp97
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp144
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.cpp3349
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Version.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp648
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h22
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/Address.h126
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp214
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp645
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp899
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h33
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h263
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp1422
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp49
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp64
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h106
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp999
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCall.h26
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp784
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp235
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h125
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp573
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h97
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp373
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp68
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp427
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp1358
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp183
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp400
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp143
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp65
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp351
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp178
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h55
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp347
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp267
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp1417
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp56
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h36
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h5
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp2326
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h317
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp243
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp1126
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp179
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h4
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGValue.h182
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp41
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp209
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp343
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h756
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp717
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h302
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp93
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h6
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h108
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp155
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h21
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp113
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h4
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/EHScopeStack.h29
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp693
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp645
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp166
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp2022
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Action.cpp125
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Compilation.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Driver.cpp527
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/InputInfo.h33
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Job.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp351
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Multilib.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp67
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp233
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp1582
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.h339
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.cpp3433
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.h925
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Types.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/Edit/Commit.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp82
-rw-r--r--contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp127
-rw-r--r--contrib/llvm/tools/clang/lib/Format/Encoding.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Format/Format.cpp620
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatToken.cpp29
-rw-r--r--contrib/llvm/tools/clang/lib/Format/FormatToken.h34
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp452
-rw-r--r--contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h11
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp41
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp255
-rw-r--r--contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h3
-rw-r--r--contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp293
-rw-r--r--contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h21
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp134
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CodeGenOptions.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp254
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp326
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp77
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DiagnosticRenderer.cpp317
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp78
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp64
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp90
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp59
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/LogDiagnosticPrinter.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp69
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp47
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp74
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp123
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.h72
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/Intrin.h34
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__clang_cuda_runtime_wrapper.h216
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h10
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/__wmmintrin_pclmul.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/adxintrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/altivec.h785
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/ammintrin.h108
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/arm_acle.h16
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx2intrin.h451
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h390
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h538
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h26
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h701
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h433
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h606
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h2666
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/avxintrin.h186
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/bmi2intrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/bmiintrin.h18
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/emmintrin.h81
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/f16cintrin.h26
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/fma4intrin.h8
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/fmaintrin.h8
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/ia32intrin.h32
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/immintrin.h97
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/mm3dnow.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/mmintrin.h48
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/module.modulemap25
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/nmmintrin.h5
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/pkuintrin.h48
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/pmmintrin.h10
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/popcntintrin.h18
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/prfchwintrin.h6
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h5
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/rtmintrin.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/shaintrin.h8
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/smmintrin.h181
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/stdint.h14
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/tbmintrin.h14
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/tgmath.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/tmmintrin.h19
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/wmmintrin.h9
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/x86intrin.h24
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xmmintrin.h42
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xopintrin.h91
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xsavecintrin.h48
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xsaveintrin.h58
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xsaveoptintrin.h48
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/xsavesintrin.h58
-rw-r--r--contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h12
-rw-r--r--contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp297
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Lexer.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp46
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp191
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp90
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Pragma.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp113
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp368
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp61
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp55
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp102
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp387
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp55
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp115
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/Parser.cpp89
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp184
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp137
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Sema.cpp84
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp144
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp112
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp444
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp49
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp448
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp1340
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp725
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp622
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp172
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp68
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp1034
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp243
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp83
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp270
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp76
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp115
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp348
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp743
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp2753
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp893
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp323
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp191
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp236
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp75
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp206
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp163
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp57
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp686
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h771
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp201
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h3
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp2068
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp452
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h99
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp360
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp1403
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp252
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp226
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/Module.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ModuleFileExtension.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp122
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h330
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp44
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp77
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp46
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp205
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td118
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp71
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp88
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp213
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp711
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp62
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp1201
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp242
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp134
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp42
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp1066
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp314
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp132
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp45
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp218
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BlockCounter.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp110
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp84
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp120
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp60
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp51
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp221
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp220
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp188
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp42
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp119
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp33
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp196
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp68
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp127
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp40
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp53
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp93
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp192
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp244
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp91
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp67
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h21
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp19
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp22
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp62
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp38
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp12
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Core/Lookup.cpp113
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp198
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp93
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp115
-rw-r--r--contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp43
-rw-r--r--contrib/llvm/tools/clang/tools/driver/driver.cpp171
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp348
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp3
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp83
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp3
-rw-r--r--contrib/llvm/tools/llc/llc.cpp55
-rw-r--r--contrib/llvm/tools/lldb/docs/lldb.180
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/LLDB.h20
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBAttachInfo.h75
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBCommandInterpreter.h30
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBCommandReturnObject.h20
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBDebugger.h36
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBDefines.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBFunction.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBProcess.h54
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBStream.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBTarget.h70
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBType.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBTypeCategory.h9
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBTypeSummary.h15
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SBValue.h12
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/API/SystemInitializerFull.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/Breakpoint.h61
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocation.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationList.h23
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointOptions.h31
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolver.h9
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h17
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverName.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSite.h25
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/Watchpoint.h58
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointOptions.h27
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Address.h23
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/AddressRange.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/AddressResolver.h9
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverFileLine.h17
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverName.h17
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ArchSpec.h44
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Broadcaster.h24
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ClangForward.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Communication.h29
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Connection.h12
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ConnectionSharedMemory.h31
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ConstString.h46
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/DataBufferHeap.h19
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/DataBufferMemoryMap.h20
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/DataEncoder.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/DataExtractor.h104
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Debugger.h111
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Disassembler.h36
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/EmulateInstruction.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Event.h24
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/FileLineResolver.h17
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/FormatEntity.h24
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/History.h39
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/IOHandler.h86
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Language.h117
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Listener.h39
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/LoadedModuleInfoList.h152
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Log.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Logging.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/MappedHash.h47
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Module.h96
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ModuleList.h32
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ModuleSpec.h64
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Opcode.h18
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/PluginManager.h178
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h174
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/RegisterValue.h131
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/RegularExpression.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/STLUtils.h26
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Scalar.h123
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/SearchFilter.h17
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Section.h43
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/SourceManager.h66
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Stream.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/StreamAsynchronousIO.h14
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/StreamCallback.h14
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/StreamFile.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/StreamGDBRemote.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/StreamString.h15
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/StreamTee.h15
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/StringList.h39
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/StructuredData.h228
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseMap.h22
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseSet.h7
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Timer.h43
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/UUID.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/UniqueCStringMap.h30
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/Value.h41
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObject.h173
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectCast.h66
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectChild.h77
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResult.h103
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultCast.h76
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultChild.h39
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultImpl.h29
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectDynamicValue.h135
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectList.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectMemory.h51
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectRegister.h138
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h170
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectVariable.h75
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Core/dwarf.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/CXXFormatterFunctions.h375
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/CXXFunctionPointer.h23
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/DataVisualization.h25
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h185
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatCache.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatClasses.h84
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatManager.h165
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h70
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersHelpers.h279
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/LanguageCategory.h99
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/StringPrinter.h765
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeCategory.h302
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeCategoryMap.h37
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeFormat.h43
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSummary.h190
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSynthetic.h199
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeValidator.h20
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h282
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/DataFormatters/VectorIterator.h53
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/DWARFExpression.h45
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/Expression.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpression.h)64
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionParser.h123
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h54
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionVariable.h320
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/FunctionCaller.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ClangFunction.h)138
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/IRDynamicChecks.h20
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/IRExecutionUnit.h74
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/IRInterpreter.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/IRMemoryMap.h9
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/IRToDWARF.h111
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/LLVMUserExpression.h118
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/Materializer.h73
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/REPL.h211
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/UserExpression.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ClangUserExpression.h)220
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Expression/UtilityFunction.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ClangUtilityFunction.h)93
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Condition.h25
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Config.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Debug.h16
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Endian.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/File.h82
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/FileSpec.h41
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/FileSystem.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/HostGetOpt.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/HostInfo.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/HostNativeThread.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/HostNativeThreadForward.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/MainLoopBase.h12
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/MonitoringProcessLauncher.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Mutex.h39
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/OptionParser.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Predicate.h45
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/ProcessRunLock.h22
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Socket.h63
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/Symbols.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/XML.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/common/GetOptInc.h65
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/common/NativeProcessProtocol.h17
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/common/TCPSocket.h46
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/common/UDPSocket.h35
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/netbsd/Config.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h30
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostThreadNetBSD.h32
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h15
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/posix/DomainSocket.h37
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/posix/HostProcessPosix.h11
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/posix/HostThreadPosix.h7
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/posix/LockFilePosix.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Host/posix/MainLoopPosix.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Initialization/SystemInitializerCommon.h7
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/Args.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandCompletions.h76
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandHistory.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandInterpreter.h82
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObject.h86
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectMultiword.h229
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectRegexCommand.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandOptionValidators.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandReturnObject.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupArchitecture.h35
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupBoolean.h29
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupFile.h56
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupFormat.h30
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupOutputFile.h30
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupPlatform.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupString.h32
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupUInt64.h33
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupUUID.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h47
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupVariable.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupWatchpoint.h32
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValue.h18
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArch.h41
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArgs.h9
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArray.h41
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueBoolean.h41
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueChar.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueDictionary.h53
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueEnumeration.h42
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpec.h41
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpecList.h32
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormat.h27
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueLanguage.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValuePathMappings.h31
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueProperties.h83
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueRegex.h39
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueSInt64.h27
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueString.h53
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUInt64.h27
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUUID.h41
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/Options.h63
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/PythonDataObjects.h280
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreter.h41
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreterNone.h35
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ArmUnwindInfo.h77
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/Block.h70
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTContext.h944
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTImporter.h53
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h38
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ClangNamespaceDecl.h105
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/CompileUnit.h61
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerDecl.h135
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerDeclContext.h149
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerType.h (renamed from contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTType.h)477
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/DebugMacros.h140
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/FuncUnwinders.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/Function.h78
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/GoASTContext.h408
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/LineEntry.h26
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/LineTable.h27
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectContainer.h16
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectFile.h18
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/Symbol.h19
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContext.h73
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContextScope.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolFile.h50
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolVendor.h35
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/TaggedASTType.h18
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/Type.h259
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/TypeList.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/TypeMap.h98
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/TypeSystem.h607
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h40
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindTable.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/Variable.h26
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Symbol/VariableList.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ABI.h12
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/CPPLanguageRuntime.h133
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/DynamicLoader.h21
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContext.h111
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h19
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/JITLoader.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Language.h206
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/LanguageRuntime.h50
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ObjCLanguageRuntime.h269
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/OperatingSystem.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Platform.h280
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Process.h585
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/QueueItem.h20
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/RegisterContext.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadList.h1
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/StackFrame.h58
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/StackFrameList.h22
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/StackID.h20
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/StopInfo.h4
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/SystemRuntime.h23
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Target.h351
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/TargetList.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/Thread.h253
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadList.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlan.h54
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanBase.h32
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunction.h77
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h5
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h31
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanPython.h48
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanRunToAddress.h43
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanShouldStopHere.h16
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepInRange.h26
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepInstruction.h24
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOut.h36
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h35
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverRange.h23
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepRange.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepThrough.h26
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepUntil.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanTracer.h23
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/ThreadSpec.h14
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/UnixSignals.h13
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Target/UnwindAssembly.h7
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/AnsiTerminal.h9
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Either.h154
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Iterable.h25
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/JSON.h127
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/ProcessStructReader.h8
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/PseudoTerminal.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/PythonPointer.h73
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/SharedCluster.h6
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h79
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractor.h3
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/TaskPool.h221
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-defines.h2
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-enumerations.h41
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-forward.h50
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-private-enumerations.h28
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-private-interfaces.h10
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-private-types.h18
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-python.h31
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/lldb-types.h2
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBAttachInfo.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBBreakpoint.cpp48
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBCommandInterpreter.cpp152
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBCommandReturnObject.cpp112
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBDebugger.cpp250
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBFrame.cpp133
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBFunction.cpp30
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBLanguageRuntime.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBModule.cpp24
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBPlatform.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBProcess.cpp55
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBStream.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBTarget.cpp137
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBThread.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBType.cpp148
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBTypeCategory.cpp25
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBTypeEnumMember.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBTypeNameSpecifier.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBTypeSummary.cpp151
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBValue.cpp47
-rw-r--r--contrib/llvm/tools/lldb/source/API/SBValueList.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/API/SystemInitializerFull.cpp84
-rw-r--r--contrib/llvm/tools/lldb/source/API/liblldb.exports3
-rw-r--r--contrib/llvm/tools/lldb/source/API/liblldb.xcode.exports3
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/Breakpoint.cpp55
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointID.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointIDList.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocation.cpp105
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointOptions.cpp29
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverAddress.cpp90
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverName.cpp103
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/BreakpointSite.cpp29
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/StoppointCallbackContext.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/Watchpoint.cpp83
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/WatchpointList.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Breakpoint/WatchpointOptions.cpp26
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectApropos.h13
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp27
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.h28
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.cpp232
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.h5
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp59
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.h8
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectBugreport.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectBugreport.h5
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp171
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.h30
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp100
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h46
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp52
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectGUI.h12
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.h43
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectLanguage.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectLanguage.h10
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.cpp41
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.h5
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.cpp181
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.cpp274
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.h7
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp316
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.h12
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp35
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.h5
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.cpp134
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp699
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.h13
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp335
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.h7
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp182
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp2502
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectType.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectVersion.h12
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.cpp128
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.h6
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp45
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.h7
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Address.cpp32
-rw-r--r--contrib/llvm/tools/lldb/source/Core/AddressResolverName.cpp1
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ArchSpec.cpp174
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ConnectionSharedMemory.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ConstString.cpp145
-rw-r--r--contrib/llvm/tools/lldb/source/Core/CxaDemangle.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Core/DataEncoder.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Core/DataExtractor.cpp97
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Debugger.cpp146
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Disassembler.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Core/DynamicLoader.cpp46
-rw-r--r--contrib/llvm/tools/lldb/source/Core/EmulateInstruction.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Event.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Core/FastDemangle.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Core/FormatEntity.cpp399
-rw-r--r--contrib/llvm/tools/lldb/source/Core/IOHandler.cpp184
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Language.cpp169
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Log.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Logging.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Mangled.cpp37
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Module.cpp222
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ModuleList.cpp83
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Opcode.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Core/PluginManager.cpp716
-rw-r--r--contrib/llvm/tools/lldb/source/Core/RegisterValue.cpp583
-rw-r--r--contrib/llvm/tools/lldb/source/Core/RegularExpression.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Scalar.cpp2514
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Section.cpp19
-rw-r--r--contrib/llvm/tools/lldb/source/Core/SourceManager.cpp25
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Stream.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Core/StreamAsynchronousIO.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Core/StreamString.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Core/StringList.cpp36
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Timer.cpp73
-rw-r--r--contrib/llvm/tools/lldb/source/Core/Value.cpp58
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObject.cpp607
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectCast.cpp27
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp119
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectConstResult.cpp59
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultCast.cpp75
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultChild.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultImpl.cpp66
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectDynamicValue.cpp142
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectMemory.cpp47
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectRegister.cpp51
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectSyntheticFilter.cpp92
-rw-r--r--contrib/llvm/tools/lldb/source/Core/ValueObjectVariable.cpp27
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/CXXFormatterFunctions.cpp1228
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/CXXFunctionPointer.cpp66
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/DataVisualization.cpp34
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/DumpValueObjectOptions.cpp245
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/FormatClasses.cpp47
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/FormatManager.cpp1156
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/FormattersHelpers.cpp336
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/LanguageCategory.cpp271
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/LibStdcpp.cpp160
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/StringPrinter.cpp307
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/TypeCategory.cpp151
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/TypeCategoryMap.cpp105
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/TypeFormat.cpp26
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/TypeSummary.cpp44
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/TypeSynthetic.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/ValueObjectPrinter.cpp444
-rw-r--r--contrib/llvm/tools/lldb/source/DataFormatters/VectorType.cpp128
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/ClangExpressionVariable.cpp142
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp1172
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp659
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/Expression.cpp32
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp145
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/ExpressionVariable.cpp36
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/FunctionCaller.cpp (renamed from contrib/llvm/tools/lldb/source/Expression/ClangFunction.cpp)248
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp100
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp22
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/LLVMUserExpression.cpp363
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/Materializer.cpp303
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/REPL.cpp649
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/UserExpression.cpp348
-rw-r--r--contrib/llvm/tools/lldb/source/Expression/UtilityFunction.cpp124
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/Editline.cpp52
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/File.cpp22
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/FileSpec.cpp26
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/GetOptInc.cpp473
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/Host.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp26
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/Mutex.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/OptionParser.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/Socket.cpp622
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/SocketAddress.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp68
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp288
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/ThisThread.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp158
-rw-r--r--contrib/llvm/tools/lldb/source/Host/common/XML.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Host/freebsd/Host.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Host/netbsd/Host.cpp287
-rw-r--r--contrib/llvm/tools/lldb/source/Host/netbsd/HostInfoNetBSD.cpp112
-rw-r--r--contrib/llvm/tools/lldb/source/Host/netbsd/HostThreadNetBSD.cpp50
-rw-r--r--contrib/llvm/tools/lldb/source/Host/netbsd/ThisThread.cpp30
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp108
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/DomainSocket.cpp133
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/FileSystem.cpp57
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/HostInfoPosix.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/MainLoopPosix.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Host/posix/PipePosix.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp19
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/Args.cpp47
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandHistory.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp126
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h14
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueLanguage.cpp29
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp9
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/Property.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp524
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp42
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py15
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp317
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h81
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp170
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h72
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp397
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h84
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp262
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.h16
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp31
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h17
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp38
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h117
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp495
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.h37
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp327
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.h96
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp550
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h88
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp347
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h98
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp348
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h98
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp475
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h88
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp236
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h57
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp37
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h66
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp211
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h29
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp63
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h76
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h42
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp42
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h25
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp (renamed from contrib/llvm/tools/lldb/source/Expression/ASTDumper.cpp)12
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ASTDumper.h)5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp (renamed from contrib/llvm/tools/lldb/source/Expression/ASTResultSynthesizer.cpp)8
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ASTResultSynthesizer.h)27
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp (renamed from contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp)5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ASTStructExtractor.h)40
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp (renamed from contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp)292
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ClangASTSource.h)47
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp (renamed from contrib/llvm/tools/lldb/source/Expression/ClangExpressionDeclMap.cpp)702
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpressionDeclMap.h)47
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h79
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp (renamed from contrib/llvm/tools/lldb/source/Expression/ClangExpressionParser.cpp)140
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpressionParser.h)36
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp76
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpressionVariable.h)291
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp221
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h173
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp (renamed from contrib/llvm/tools/lldb/source/Expression/ClangModulesDeclVendor.cpp)64
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ClangModulesDeclVendor.h)13
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp (renamed from contrib/llvm/tools/lldb/source/Expression/ClangPersistentVariables.cpp)23
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/ClangPersistentVariables.h)51
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp673
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h218
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp (renamed from contrib/llvm/tools/lldb/source/Expression/ClangUtilityFunction.cpp)43
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h137
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp (renamed from contrib/llvm/tools/lldb/source/Expression/IRForTarget.cpp)74
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h (renamed from contrib/llvm/tools/lldb/include/lldb/Expression/IRForTarget.h)18
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoAST.h3225
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoLexer.cpp402
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoLexer.h201
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp1035
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.h165
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp756
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.h98
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/gen_go_ast.py356
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp406
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h48
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp304
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h93
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp3109
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h174
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp2779
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h210
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp74
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h48
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp77
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.h36
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp808
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h189
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp204
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h41
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/LibCxx.cpp)200
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h141
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/LibCxxInitializerList.cpp)56
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/LibCxxList.cpp)391
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/LibCxxMap.cpp)154
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/LibCxxUnorderedMap.cpp)48
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/LibCxxVector.cpp)60
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp373
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h33
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoFormatterFunctions.cpp173
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoFormatterFunctions.h43
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoLanguage.cpp146
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoLanguage.h66
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CF.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/CF.cpp)51
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CF.h34
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/Cocoa.cpp)450
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.h97
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/CoreMedia.cpp)18
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CoreMedia.h26
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSArray.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/NSArray.cpp)340
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/NSDictionary.cpp)253
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.h48
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSError.cpp218
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSException.cpp219
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/NSIndexPath.cpp)77
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.cpp (renamed from contrib/llvm/tools/lldb/source/DataFormatters/NSSet.cpp)279
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.h40
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.cpp405
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.h42
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp877
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h210
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp68
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h63
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp100
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h80
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp238
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h93
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp573
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h411
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp665
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h55
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp554
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h148
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp459
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h207
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp2224
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h336
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp1144
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h209
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp398
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h81
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp244
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h95
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp3346
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h232
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp108
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h34
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h65
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp594
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h19
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h114
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp559
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h87
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h60
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h13
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp685
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h177
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp185
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h60
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp125
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h33
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp623
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h109
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h8
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXThread.cpp665
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXThread.h132
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp829
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h197
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp939
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessPOSIX.h205
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h (renamed from contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX.h)0
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp35
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/POSIX/CrashReason.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp18
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp132
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryThread.h47
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryUnwind.h20
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h3
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp134
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp134
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp34
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/NetBSDSignals.h31
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp184
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h76
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp114
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h64
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp228
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h55
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp406
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h52
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h56
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h18
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h55
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp122
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h58
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.h1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp14
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h8
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp16
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h2
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp11
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h7
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h57
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h61
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp48
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h30
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h27
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h27
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h29
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h29
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h104
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h663
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h321
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h411
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h22
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h334
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h156
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h73
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h233
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h319
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h14
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h94
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp4
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.h16
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/ThreadMemory.h92
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp86
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.h37
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h28
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h50
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp77
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h32
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h40
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h40
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h40
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h42
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp1
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h40
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h41
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp232
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h77
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp344
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h78
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h8
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp105
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h17
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp600
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h41
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp305
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h52
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp290
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h22
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp1530
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h146
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp115
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h51
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp93
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h66
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp1173
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h535
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp201
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h70
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp (renamed from contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp)1006
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h (renamed from contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h)170
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h31
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp56
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h54
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h65
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp4034
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h213
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp828
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h84
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp90
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h60
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp459
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h124
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp543
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h281
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp18
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h12
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h5
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp230
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h35
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp953
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h138
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp95
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h9
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp128
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h68
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp60
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp54
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h16
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h7
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp114
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h40
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp172
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h24
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp94
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h34
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp747
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h950
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h34
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp34
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h33
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp5987
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h814
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp212
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h45
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp131
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h70
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp49
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h35
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp83
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h129
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp8
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h31
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp56
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h100
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp45
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h51
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/ArmUnwindInfo.cpp445
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Block.cpp33
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp8465
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp130
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/ClangASTType.cpp7057
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp14
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/ClangNamespaceDecl.cpp25
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp55
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/CompilerDecl.cpp76
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/CompilerDeclContext.cpp84
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/CompilerType.cpp1320
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/DebugMacros.cpp65
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp43
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Function.cpp78
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp1519
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/LineEntry.cpp39
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp21
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp50
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp175
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/SymbolFile.cpp75
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/SymbolVendor.cpp51
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp10
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Type.cpp370
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/TypeList.cpp73
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/TypeMap.cpp322
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/TypeSystem.cpp255
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp36
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/Variable.cpp106
-rw-r--r--contrib/llvm/tools/lldb/source/Symbol/VariableList.cpp18
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ABI.cpp19
-rw-r--r--contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp372
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Language.cpp458
-rw-r--r--contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp144
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Memory.cpp26
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp299
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Platform.cpp167
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Process.cpp1097
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ProcessLaunchInfo.cpp3
-rw-r--r--contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp30
-rw-r--r--contrib/llvm/tools/lldb/source/Target/StackFrame.cpp86
-rw-r--r--contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp14
-rw-r--r--contrib/llvm/tools/lldb/source/Target/StopInfo.cpp237
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Target.cpp1088
-rw-r--r--contrib/llvm/tools/lldb/source/Target/TargetList.cpp63
-rw-r--r--contrib/llvm/tools/lldb/source/Target/Thread.cpp329
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadList.cpp38
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlan.cpp38
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunction.cpp32
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunctionUsingABI.cpp13
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanCallUserExpression.cpp6
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp7
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanShouldStopHere.cpp41
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp62
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInstruction.cpp30
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp106
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp70
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp65
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp14
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp211
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp63
-rw-r--r--contrib/llvm/tools/lldb/source/Target/ThreadSpec.cpp24
-rw-r--r--contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp95
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/ARM64_ehframe_Registers.h (renamed from contrib/llvm/tools/lldb/source/Utility/ARM64_GCC_Registers.h)13
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/ARM_GCC_Registers.h146
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/ARM_ehframe_Registers.h38
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/ConvertEnum.cpp12
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/JSON.cpp89
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/ModuleCache.cpp186
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/ModuleCache.h9
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/SharingPtr.cpp2
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp17
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.cpp20
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.h4
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/TaskPool.cpp88
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/UriParser.cpp88
-rw-r--r--contrib/llvm/tools/lldb/source/Utility/UriParser.h12
-rw-r--r--contrib/llvm/tools/lldb/source/lldb.cpp2
-rw-r--r--contrib/llvm/tools/lldb/tools/argdumper/argdumper.exports (renamed from contrib/llvm/tools/lldb/tools/argdumper/exports)0
-rw-r--r--contrib/llvm/tools/lldb/tools/driver/Driver.cpp217
-rw-r--r--contrib/llvm/tools/lldb/tools/driver/Driver.h3
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgContext.cpp24
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgContext.h17
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgSet.cpp46
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgSet.h47
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValBase.cpp30
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValBase.h66
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValConsume.cpp14
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValConsume.h11
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValFile.cpp14
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValFile.h7
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListBase.cpp6
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListBase.h9
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListOfN.cpp6
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListOfN.h9
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValNumber.cpp6
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValNumber.h9
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionLong.cpp18
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionLong.h11
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionShort.cpp6
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionShort.h7
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValPrintValues.cpp6
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValPrintValues.h6
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValString.cpp8
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValString.h7
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValThreadGrp.cpp12
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValThreadGrp.h9
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.cpp59
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.h56
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmd.cpp20
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmd.h26
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp211
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.h98
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.cpp406
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.h156
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdEnviro.cpp16
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdEnviro.h15
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.cpp227
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.h146
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdFile.cpp31
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdFile.h18
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbInfo.cpp20
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbInfo.h19
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.cpp24
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.h16
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbShow.cpp24
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbShow.h15
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbThread.cpp10
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbThread.h13
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdMiscellanous.cpp64
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdMiscellanous.h56
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdStack.cpp139
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdStack.h105
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportInfo.cpp16
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportInfo.h15
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportList.cpp19
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportList.h13
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp130
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.h12
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.cpp50
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.h39
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdThread.cpp16
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdThread.h15
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTrace.cpp10
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTrace.h13
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdVar.cpp230
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdVar.h140
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCommands.cpp6
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCommands.h5
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdData.h9
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdFactory.cpp17
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdFactory.h19
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInterpreter.cpp20
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInterpreter.h11
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInvoker.cpp32
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInvoker.h35
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgr.cpp8
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgr.h11
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp4
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h12
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnBase.cpp10
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnBase.h13
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.cpp8
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.h11
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp110
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h17
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp30
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h31
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp131
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugger.h36
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp179
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h29
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.h3
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp288
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.h40
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLog.cpp16
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLog.h29
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLogMediumFile.cpp62
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLogMediumFile.h33
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp183
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.h37
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp103
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIResultRecord.h35
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValue.cpp8
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValue.h9
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueConst.cpp6
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueConst.h8
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueList.cpp49
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueList.h17
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueResult.cpp28
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueResult.h13
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueTuple.cpp58
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueTuple.h21
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.cpp13
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.h15
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStderr.cpp12
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStderr.h15
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdin.cpp14
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdin.h17
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdout.cpp16
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdout.h17
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnThreadMgrStd.cpp12
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MICmnThreadMgrStd.h13
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIDataTypes.h16
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.cpp72
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.h73
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverBase.cpp14
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverBase.h21
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMain.cpp2
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.cpp38
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.h49
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIExtensions.txt9
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDateTimeStd.cpp10
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDateTimeStd.h13
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDebug.cpp10
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDebug.h16
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilFileStd.cpp12
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilFileStd.h15
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilMapIdToVariant.cpp8
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilMapIdToVariant.h11
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilParse.cpp75
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilParse.h93
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonBase.h14
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonHelper.h7
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilString.cpp118
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilString.h33
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemLinux.cpp111
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemLinux.h45
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemOsx.cpp111
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemOsx.h45
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemWindows.cpp141
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemWindows.h44
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilThreadBaseStd.cpp36
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilThreadBaseStd.h59
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilVariant.cpp18
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilVariant.h49
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-mi/lldb-mi.exports (renamed from contrib/llvm/tools/lldb/tools/lldb-server/exports)0
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/Acceptor.cpp170
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/Acceptor.h68
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/LLDBServerUtilities.cpp2
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp158
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/lldb-platform.cpp95
-rw-r--r--contrib/llvm/tools/lldb/tools/lldb-server/lldb-server.exports0
-rw-r--r--contrib/llvm/tools/lli/ChildTarget/ChildTarget.cpp285
-rw-r--r--contrib/llvm/tools/lli/OrcLazyJIT.cpp64
-rw-r--r--contrib/llvm/tools/lli/OrcLazyJIT.h58
-rw-r--r--contrib/llvm/tools/lli/RPCChannel.h49
-rw-r--r--contrib/llvm/tools/lli/RemoteJITUtils.h131
-rw-r--r--contrib/llvm/tools/lli/RemoteMemoryManager.cpp174
-rw-r--r--contrib/llvm/tools/lli/RemoteMemoryManager.h101
-rw-r--r--contrib/llvm/tools/lli/RemoteTarget.cpp71
-rw-r--r--contrib/llvm/tools/lli/RemoteTarget.h122
-rw-r--r--contrib/llvm/tools/lli/RemoteTargetExternal.cpp327
-rw-r--r--contrib/llvm/tools/lli/RemoteTargetExternal.h143
-rw-r--r--contrib/llvm/tools/lli/RemoteTargetMessage.h85
-rw-r--r--contrib/llvm/tools/lli/Unix/RPCChannel.inc122
-rw-r--r--contrib/llvm/tools/lli/Windows/RPCChannel.inc29
-rw-r--r--contrib/llvm/tools/lli/lli.cpp184
-rw-r--r--contrib/llvm/tools/llvm-ar/llvm-ar.cpp104
-rw-r--r--contrib/llvm/tools/llvm-as/llvm-as.cpp7
-rw-r--r--contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp67
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageReport.cpp31
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageViewOptions.h1
-rw-r--r--contrib/llvm/tools/llvm-cov/gcov.cpp6
-rw-r--r--contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp104
-rw-r--r--contrib/llvm/tools/llvm-diff/DiffLog.cpp3
-rw-r--r--contrib/llvm/tools/llvm-diff/DiffLog.h10
-rw-r--r--contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp4
-rw-r--r--contrib/llvm/tools/llvm-dis/llvm-dis.cpp2
-rw-r--r--contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp107
-rw-r--r--contrib/llvm/tools/llvm-extract/llvm-extract.cpp53
-rw-r--r--contrib/llvm/tools/llvm-link/llvm-link.cpp194
-rw-r--r--contrib/llvm/tools/llvm-lto/llvm-lto.cpp270
-rw-r--r--contrib/llvm/tools/llvm-mc/llvm-mc.cpp14
-rw-r--r--contrib/llvm/tools/llvm-nm/llvm-nm.cpp258
-rw-r--r--contrib/llvm/tools/llvm-objdump/COFFDump.cpp104
-rw-r--r--contrib/llvm/tools/llvm-objdump/ELFDump.cpp32
-rw-r--r--contrib/llvm/tools/llvm-objdump/MachODump.cpp854
-rw-r--r--contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp603
-rw-r--r--contrib/llvm/tools/llvm-objdump/llvm-objdump.h10
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.cpp66
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.h2
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/LinePrinter.cpp104
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/LinePrinter.h13
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp299
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.h3
-rw-r--r--contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp271
-rw-r--r--contrib/llvm/tools/llvm-readobj/ARMAttributeParser.cpp72
-rw-r--r--contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h64
-rw-r--r--contrib/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp5
-rw-r--r--contrib/llvm/tools/llvm-readobj/COFFDumper.cpp162
-rw-r--r--contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp52
-rw-r--r--contrib/llvm/tools/llvm-readobj/ELFDumper.cpp910
-rw-r--r--contrib/llvm/tools/llvm-readobj/MachODumper.cpp240
-rw-r--r--contrib/llvm/tools/llvm-readobj/ObjDumper.h19
-rw-r--r--contrib/llvm/tools/llvm-readobj/StreamWriter.h32
-rw-r--r--contrib/llvm/tools/llvm-readobj/Win64EHDumper.cpp21
-rw-r--r--contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp145
-rw-r--r--contrib/llvm/tools/llvm-readobj/llvm-readobj.h4
-rw-r--r--contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp235
-rw-r--r--contrib/llvm/tools/llvm-stress/llvm-stress.cpp5
-rw-r--r--contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp532
-rw-r--r--contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.h144
-rw-r--r--contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp88
-rw-r--r--contrib/llvm/tools/macho-dump/macho-dump.cpp434
-rw-r--r--contrib/llvm/tools/opt/opt.cpp56
1842 files changed, 181359 insertions, 100535 deletions
diff --git a/contrib/llvm/tools/bugpoint/BugDriver.cpp b/contrib/llvm/tools/bugpoint/BugDriver.cpp
index 43f4c29..030749f 100644
--- a/contrib/llvm/tools/bugpoint/BugDriver.cpp
+++ b/contrib/llvm/tools/bugpoint/BugDriver.cpp
@@ -72,7 +72,7 @@ BugDriver::BugDriver(const char *toolname, bool find_bugs,
LLVMContext& ctxt)
: Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile),
Program(nullptr), Interpreter(nullptr), SafeInterpreter(nullptr),
- gcc(nullptr), run_find_bugs(find_bugs), Timeout(timeout),
+ cc(nullptr), run_find_bugs(find_bugs), Timeout(timeout),
MemoryLimit(memlimit), UseValgrind(use_valgrind) {}
BugDriver::~BugDriver() {
@@ -80,7 +80,7 @@ BugDriver::~BugDriver() {
if (Interpreter != SafeInterpreter)
delete Interpreter;
delete SafeInterpreter;
- delete gcc;
+ delete cc;
}
std::unique_ptr<Module> llvm::parseInputFile(StringRef Filename,
@@ -132,7 +132,7 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
if (!M.get()) return true;
outs() << "Linking in input file: '" << Filenames[i] << "'\n";
- if (Linker::LinkModules(Program, M.get()))
+ if (Linker::linkModules(*Program, std::move(M)))
return true;
}
diff --git a/contrib/llvm/tools/bugpoint/BugDriver.h b/contrib/llvm/tools/bugpoint/BugDriver.h
index 5797812..20efff3 100644
--- a/contrib/llvm/tools/bugpoint/BugDriver.h
+++ b/contrib/llvm/tools/bugpoint/BugDriver.h
@@ -36,7 +36,7 @@ class LLVMContext;
class DebugCrashes;
-class GCC;
+class CC;
extern bool DisableSimplifyCFG;
@@ -52,7 +52,7 @@ class BugDriver {
std::vector<std::string> PassesToRun;
AbstractInterpreter *Interpreter; // How to run the program
AbstractInterpreter *SafeInterpreter; // To generate reference output, etc.
- GCC *gcc;
+ CC *cc;
bool run_find_bugs;
unsigned Timeout;
unsigned MemoryLimit;
@@ -321,16 +321,21 @@ void PrintFunctionList(const std::vector<Function*> &Funcs);
///
void PrintGlobalVariableList(const std::vector<GlobalVariable*> &GVs);
+// DeleteGlobalInitializer - "Remove" the global variable by deleting its
+// initializer, making it external.
+//
+void DeleteGlobalInitializer(GlobalVariable *GV);
+
// DeleteFunctionBody - "Remove" the function by deleting all of it's basic
// blocks, making it external.
//
void DeleteFunctionBody(Function *F);
-/// SplitFunctionsOutOfModule - Given a module and a list of functions in the
-/// module, split the functions OUT of the specified module, and place them in
-/// the new module.
-Module *SplitFunctionsOutOfModule(Module *M, const std::vector<Function*> &F,
- ValueToValueMapTy &VMap);
+/// Given a module and a list of functions in the module, split the functions
+/// OUT of the specified module, and place them in the new module.
+std::unique_ptr<Module>
+SplitFunctionsOutOfModule(Module *M, const std::vector<Function *> &F,
+ ValueToValueMapTy &VMap);
} // End llvm namespace
diff --git a/contrib/llvm/tools/bugpoint/CrashDebugger.cpp b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp
index e2aaf6b..6cdc43ab 100644
--- a/contrib/llvm/tools/bugpoint/CrashDebugger.cpp
+++ b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp
@@ -15,6 +15,7 @@
#include "ListReducer.h"
#include "ToolRunner.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
@@ -49,6 +50,10 @@ namespace {
DontReducePassList("disable-pass-list-reduction",
cl::desc("Skip pass list reduction steps"),
cl::init(false));
+
+ cl::opt<bool> NoNamedMDRM("disable-namedmd-remove",
+ cl::desc("Do not remove global named metadata"),
+ cl::init(false));
}
namespace llvm {
@@ -138,7 +143,7 @@ ReduceCrashingGlobalVariables::TestGlobalVariables(
std::vector<GlobalVariable*> &GVs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap);
+ Module *M = CloneModule(BD.getProgram(), VMap).release();
// Convert list to set for fast lookup...
std::set<GlobalVariable*> GVSet;
@@ -155,11 +160,10 @@ ReduceCrashingGlobalVariables::TestGlobalVariables(
// Loop over and delete any global variables which we aren't supposed to be
// playing with...
- for (Module::global_iterator I = M->global_begin(), E = M->global_end();
- I != E; ++I)
- if (I->hasInitializer() && !GVSet.count(I)) {
- I->setInitializer(nullptr);
- I->setLinkage(GlobalValue::ExternalLinkage);
+ for (GlobalVariable &I : M->globals())
+ if (I.hasInitializer() && !GVSet.count(&I)) {
+ DeleteGlobalInitializer(&I);
+ I.setLinkage(GlobalValue::ExternalLinkage);
}
// Try running the hacked up program...
@@ -235,7 +239,7 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap);
+ Module *M = CloneModule(BD.getProgram(), VMap).release();
// Convert list to set for fast lookup...
std::set<Function*> Functions;
@@ -253,9 +257,9 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
if (!ReplaceFuncsWithNull) {
// Loop over and delete any functions which we aren't supposed to be playing
// with...
- for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
- if (!I->isDeclaration() && !Functions.count(I))
- DeleteFunctionBody(I);
+ for (Function &I : *M)
+ if (!I.isDeclaration() && !Functions.count(&I))
+ DeleteFunctionBody(&I);
} else {
std::vector<GlobalValue*> ToRemove;
// First, remove aliases to functions we're about to purge.
@@ -280,12 +284,12 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
ToRemove.push_back(&Alias);
}
- for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
- if (!I->isDeclaration() && !Functions.count(I)) {
- PointerType *Ty = cast<PointerType>(I->getType());
+ for (Function &I : *M) {
+ if (!I.isDeclaration() && !Functions.count(&I)) {
+ PointerType *Ty = cast<PointerType>(I.getType());
Constant *Replacement = ConstantPointerNull::get(Ty);
- I->replaceAllUsesWith(Replacement);
- ToRemove.push_back(I);
+ I.replaceAllUsesWith(Replacement);
+ ToRemove.push_back(&I);
}
}
@@ -342,7 +346,7 @@ namespace {
bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap);
+ Module *M = CloneModule(BD.getProgram(), VMap).release();
// Convert list to set for fast lookup...
SmallPtrSet<BasicBlock*, 8> Blocks;
@@ -361,20 +365,22 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) {
// Loop over and delete any hack up any blocks that are not listed...
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB)
- if (!Blocks.count(BB) && BB->getTerminator()->getNumSuccessors()) {
+ if (!Blocks.count(&*BB) && BB->getTerminator()->getNumSuccessors()) {
// Loop over all of the successors of this block, deleting any PHI nodes
// that might include it.
- for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI)
- (*SI)->removePredecessor(BB);
+ for (succ_iterator SI = succ_begin(&*BB), E = succ_end(&*BB); SI != E;
+ ++SI)
+ (*SI)->removePredecessor(&*BB);
TerminatorInst *BBTerm = BB->getTerminator();
-
- if (!BB->getTerminator()->getType()->isVoidTy())
+ if (BBTerm->isEHPad())
+ continue;
+ if (!BBTerm->getType()->isVoidTy() && !BBTerm->getType()->isTokenTy())
BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));
// Replace the old terminator instruction.
BB->getInstList().pop_back();
- new UnreachableInst(BB->getContext(), BB);
+ new UnreachableInst(BB->getContext(), &*BB);
}
// The CFG Simplifier pass may delete one of the basic blocks we are
@@ -450,7 +456,7 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*>
&Insts) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
- Module *M = CloneModule(BD.getProgram(), VMap);
+ Module *M = CloneModule(BD.getProgram(), VMap).release();
// Convert list to set for fast lookup...
SmallPtrSet<Instruction*, 64> Instructions;
@@ -468,10 +474,10 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*>
for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI)
for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI)
for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) {
- Instruction *Inst = I++;
+ Instruction *Inst = &*I++;
if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst) &&
- !isa<LandingPadInst>(Inst)) {
- if (!Inst->getType()->isVoidTy())
+ !Inst->isEHPad()) {
+ if (!Inst->getType()->isVoidTy() && !Inst->getType()->isTokenTy())
Inst->replaceAllUsesWith(UndefValue::get(Inst->getType()));
Inst->eraseFromParent();
}
@@ -497,6 +503,149 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*>
return false;
}
+namespace {
+// Reduce the list of Named Metadata nodes. We keep this as a list of
+// names to avoid having to convert back and forth every time.
+class ReduceCrashingNamedMD : public ListReducer<std::string> {
+ BugDriver &BD;
+ bool (*TestFn)(const BugDriver &, Module *);
+
+public:
+ ReduceCrashingNamedMD(BugDriver &bd,
+ bool (*testFn)(const BugDriver &, Module *))
+ : BD(bd), TestFn(testFn) {}
+
+ TestResult doTest(std::vector<std::string> &Prefix,
+ std::vector<std::string> &Kept,
+ std::string &Error) override {
+ if (!Kept.empty() && TestNamedMDs(Kept))
+ return KeepSuffix;
+ if (!Prefix.empty() && TestNamedMDs(Prefix))
+ return KeepPrefix;
+ return NoFailure;
+ }
+
+ bool TestNamedMDs(std::vector<std::string> &NamedMDs);
+};
+}
+
+bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {
+
+ ValueToValueMapTy VMap;
+ Module *M = CloneModule(BD.getProgram(), VMap).release();
+
+ outs() << "Checking for crash with only these named metadata nodes:";
+ unsigned NumPrint = std::min<size_t>(NamedMDs.size(), 10);
+ for (unsigned i = 0, e = NumPrint; i != e; ++i)
+ outs() << " " << NamedMDs[i];
+ if (NumPrint < NamedMDs.size())
+ outs() << "... <" << NamedMDs.size() << " total>";
+ outs() << ": ";
+
+ // Make a StringMap for faster lookup
+ StringSet<> Names;
+ for (const std::string &Name : NamedMDs)
+ Names.insert(Name);
+
+ // First collect all the metadata to delete in a vector, then
+ // delete them all at once to avoid invalidating the iterator
+ std::vector<NamedMDNode *> ToDelete;
+ ToDelete.reserve(M->named_metadata_size() - Names.size());
+ for (auto &NamedMD : M->named_metadata())
+ if (!Names.count(NamedMD.getName()))
+ ToDelete.push_back(&NamedMD);
+
+ for (auto *NamedMD : ToDelete)
+ NamedMD->eraseFromParent();
+
+ // Verify that this is still valid.
+ legacy::PassManager Passes;
+ Passes.add(createVerifierPass());
+ Passes.run(*M);
+
+ // Try running on the hacked up program...
+ if (TestFn(BD, M)) {
+ BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ return true;
+ }
+ delete M; // It didn't crash, try something else.
+ return false;
+}
+
+namespace {
+// Reduce the list of operands to named metadata nodes
+class ReduceCrashingNamedMDOps : public ListReducer<const MDNode *> {
+ BugDriver &BD;
+ bool (*TestFn)(const BugDriver &, Module *);
+
+public:
+ ReduceCrashingNamedMDOps(BugDriver &bd,
+ bool (*testFn)(const BugDriver &, Module *))
+ : BD(bd), TestFn(testFn) {}
+
+ TestResult doTest(std::vector<const MDNode *> &Prefix,
+ std::vector<const MDNode *> &Kept,
+ std::string &Error) override {
+ if (!Kept.empty() && TestNamedMDOps(Kept))
+ return KeepSuffix;
+ if (!Prefix.empty() && TestNamedMDOps(Prefix))
+ return KeepPrefix;
+ return NoFailure;
+ }
+
+ bool TestNamedMDOps(std::vector<const MDNode *> &NamedMDOps);
+};
+}
+
+bool ReduceCrashingNamedMDOps::TestNamedMDOps(
+ std::vector<const MDNode *> &NamedMDOps) {
+ // Convert list to set for fast lookup...
+ SmallPtrSet<const MDNode *, 64> OldMDNodeOps;
+ for (unsigned i = 0, e = NamedMDOps.size(); i != e; ++i) {
+ OldMDNodeOps.insert(NamedMDOps[i]);
+ }
+
+ outs() << "Checking for crash with only " << OldMDNodeOps.size();
+ if (OldMDNodeOps.size() == 1)
+ outs() << " named metadata operand: ";
+ else
+ outs() << " named metadata operands: ";
+
+ ValueToValueMapTy VMap;
+ Module *M = CloneModule(BD.getProgram(), VMap).release();
+
+ // This is a little wasteful. In the future it might be good if we could have
+ // these dropped during cloning.
+ for (auto &NamedMD : BD.getProgram()->named_metadata()) {
+ // Drop the old one and create a new one
+ M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName()));
+ NamedMDNode *NewNamedMDNode =
+ M->getOrInsertNamedMetadata(NamedMD.getName());
+ for (MDNode *op : NamedMD.operands())
+ if (OldMDNodeOps.count(op))
+ NewNamedMDNode->addOperand(cast<MDNode>(MapMetadata(op, VMap)));
+ }
+
+ // Verify that this is still valid.
+ legacy::PassManager Passes;
+ Passes.add(createVerifierPass());
+ Passes.run(*M);
+
+ // Try running on the hacked up program...
+ if (TestFn(BD, M)) {
+ // Make sure to use instruction pointers that point into the now-current
+ // module, and that they don't include any deleted blocks.
+ NamedMDOps.clear();
+ for (const MDNode *Node : OldMDNodeOps)
+ NamedMDOps.push_back(cast<MDNode>(VMap.MD()[Node].get()));
+
+ BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ return true;
+ }
+ delete M; // It didn't crash, try something else.
+ return false;
+}
+
/// DebugACrash - Given a predicate that determines whether a component crashes
/// on a program, try to destructively reduce the program while still keeping
/// the predicate true.
@@ -509,13 +658,13 @@ static bool DebugACrash(BugDriver &BD,
BD.getProgram()->global_begin() != BD.getProgram()->global_end()) {
// Now try to reduce the number of global variable initializers in the
// module to something small.
- Module *M = CloneModule(BD.getProgram());
+ Module *M = CloneModule(BD.getProgram()).release();
bool DeletedInit = false;
for (Module::global_iterator I = M->global_begin(), E = M->global_end();
I != E; ++I)
if (I->hasInitializer()) {
- I->setInitializer(nullptr);
+ DeleteGlobalInitializer(&*I);
I->setLinkage(GlobalValue::ExternalLinkage);
DeletedInit = true;
}
@@ -538,7 +687,7 @@ static bool DebugACrash(BugDriver &BD,
for (Module::global_iterator I = BD.getProgram()->global_begin(),
E = BD.getProgram()->global_end(); I != E; ++I)
if (I->hasInitializer())
- GVs.push_back(I);
+ GVs.push_back(&*I);
if (GVs.size() > 1 && !BugpointIsInterrupted) {
outs() << "\n*** Attempting to reduce the number of global "
@@ -558,10 +707,9 @@ static bool DebugACrash(BugDriver &BD,
// Now try to reduce the number of functions in the module to something small.
std::vector<Function*> Functions;
- for (Module::iterator I = BD.getProgram()->begin(),
- E = BD.getProgram()->end(); I != E; ++I)
- if (!I->isDeclaration())
- Functions.push_back(I);
+ for (Function &F : *BD.getProgram())
+ if (!F.isDeclaration())
+ Functions.push_back(&F);
if (Functions.size() > 1 && !BugpointIsInterrupted) {
outs() << "\n*** Attempting to reduce the number of functions "
@@ -581,10 +729,9 @@ static bool DebugACrash(BugDriver &BD,
//
if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
std::vector<const BasicBlock*> Blocks;
- for (Module::const_iterator I = BD.getProgram()->begin(),
- E = BD.getProgram()->end(); I != E; ++I)
- for (Function::const_iterator FI = I->begin(), E = I->end(); FI !=E; ++FI)
- Blocks.push_back(FI);
+ for (Function &F : *BD.getProgram())
+ for (BasicBlock &BB : F)
+ Blocks.push_back(&BB);
unsigned OldSize = Blocks.size();
ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks, Error);
if (Blocks.size() < OldSize)
@@ -595,14 +742,11 @@ static bool DebugACrash(BugDriver &BD,
// cases with large basic blocks where the problem is at one end.
if (!BugpointIsInterrupted) {
std::vector<const Instruction*> Insts;
- for (Module::const_iterator MI = BD.getProgram()->begin(),
- ME = BD.getProgram()->end(); MI != ME; ++MI)
- for (Function::const_iterator FI = MI->begin(), FE = MI->end(); FI != FE;
- ++FI)
- for (BasicBlock::const_iterator I = FI->begin(), E = FI->end();
- I != E; ++I)
- if (!isa<TerminatorInst>(I))
- Insts.push_back(I);
+ for (const Function &F : *BD.getProgram())
+ for (const BasicBlock &BB : F)
+ for (const Instruction &I : BB)
+ if (!isa<TerminatorInst>(&I))
+ Insts.push_back(&I);
ReduceCrashingInstructions(BD, TestFn).reduceList(Insts, Error);
}
@@ -642,12 +786,12 @@ static bool DebugACrash(BugDriver &BD,
} else {
if (BugpointIsInterrupted) goto ExitLoops;
- if (isa<LandingPadInst>(I))
+ if (I->isEHPad() || I->getType()->isTokenTy())
continue;
outs() << "Checking instruction: " << *I;
std::unique_ptr<Module> M =
- BD.deleteInstructionFromProgram(I, Simplification);
+ BD.deleteInstructionFromProgram(&*I, Simplification);
// Find out if the pass still crashes on this pass...
if (TestFn(BD, M.get())) {
@@ -666,12 +810,37 @@ static bool DebugACrash(BugDriver &BD,
}
} while (Simplification);
+
+ if (!NoNamedMDRM) {
+ BD.EmitProgressBitcode(BD.getProgram(), "reduced-instructions");
+
+ if (!BugpointIsInterrupted) {
+ // Try to reduce the amount of global metadata (particularly debug info),
+ // by dropping global named metadata that anchors them
+ outs() << "\n*** Attempting to remove named metadata: ";
+ std::vector<std::string> NamedMDNames;
+ for (auto &NamedMD : BD.getProgram()->named_metadata())
+ NamedMDNames.push_back(NamedMD.getName().str());
+ ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames, Error);
+ }
+
+ if (!BugpointIsInterrupted) {
+ // Now that we quickly dropped all the named metadata that doesn't
+ // contribute to the crash, bisect the operands of the remaining ones
+ std::vector<const MDNode *> NamedMDOps;
+ for (auto &NamedMD : BD.getProgram()->named_metadata())
+ for (auto op : NamedMD.operands())
+ NamedMDOps.push_back(op);
+ ReduceCrashingNamedMDOps(BD, TestFn).reduceList(NamedMDOps, Error);
+ }
+ }
+
ExitLoops:
// Try to clean up the testcase by running funcresolve and globaldce...
if (!BugpointIsInterrupted) {
outs() << "\n*** Attempting to perform final cleanups: ";
- Module *M = CloneModule(BD.getProgram());
+ Module *M = CloneModule(BD.getProgram()).release();
M = BD.performFinalCleanups(M, true).release();
// Find out if the pass still crashes on the cleaned up program...
diff --git a/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp b/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp
index 25813b3..41b8ccc 100644
--- a/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp
+++ b/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp
@@ -17,6 +17,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/Program.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/raw_ostream.h"
#include <fstream>
@@ -124,11 +125,10 @@ namespace {
cl::ZeroOrMore, cl::PositionalEatsArgs);
cl::opt<std::string>
- GCCBinary("gcc", cl::init("gcc"),
- cl::desc("The gcc binary to use. (default 'gcc')"));
+ CCBinary("gcc", cl::init(""), cl::desc("The gcc binary to use."));
cl::list<std::string>
- GCCToolArgv("gcc-tool-args", cl::Positional,
+ CCToolArgv("gcc-tool-args", cl::Positional,
cl::desc("<gcc-tool arguments>..."),
cl::ZeroOrMore, cl::PositionalEatsArgs);
}
@@ -148,6 +148,13 @@ bool BugDriver::initializeExecutionEnvironment() {
SafeInterpreter = nullptr;
std::string Message;
+ if (CCBinary.empty()) {
+ if (sys::findProgramByName("clang"))
+ CCBinary = "clang";
+ else
+ CCBinary = "gcc";
+ }
+
switch (InterpreterSel) {
case AutoPick:
if (!Interpreter) {
@@ -158,8 +165,8 @@ bool BugDriver::initializeExecutionEnvironment() {
if (!Interpreter) {
InterpreterSel = RunLLC;
Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
- GCCBinary, &ToolArgv,
- &GCCToolArgv);
+ CCBinary, &ToolArgv,
+ &CCToolArgv);
}
if (!Interpreter) {
InterpreterSel = RunLLI;
@@ -179,8 +186,8 @@ bool BugDriver::initializeExecutionEnvironment() {
case RunLLCIA:
case LLC_Safe:
Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
- GCCBinary, &ToolArgv,
- &GCCToolArgv,
+ CCBinary, &ToolArgv,
+ &CCToolArgv,
InterpreterSel == RunLLCIA);
break;
case RunJIT:
@@ -213,9 +220,9 @@ bool BugDriver::initializeExecutionEnvironment() {
SafeInterpreterSel = RunLLC;
SafeToolArgs.push_back("--relocation-model=pic");
SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
- GCCBinary,
+ CCBinary,
&SafeToolArgs,
- &GCCToolArgv);
+ &CCToolArgv);
}
if (!SafeInterpreter &&
@@ -224,9 +231,9 @@ bool BugDriver::initializeExecutionEnvironment() {
SafeInterpreterSel = RunLLC;
SafeToolArgs.push_back("--relocation-model=pic");
SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
- GCCBinary,
+ CCBinary,
&SafeToolArgs,
- &GCCToolArgv);
+ &CCToolArgv);
}
if (!SafeInterpreter) {
SafeInterpreterSel = AutoPick;
@@ -237,8 +244,8 @@ bool BugDriver::initializeExecutionEnvironment() {
case RunLLCIA:
SafeToolArgs.push_back("--relocation-model=pic");
SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
- GCCBinary, &SafeToolArgs,
- &GCCToolArgv,
+ CCBinary, &SafeToolArgs,
+ &CCToolArgv,
SafeInterpreterSel == RunLLCIA);
break;
case Custom:
@@ -252,8 +259,8 @@ bool BugDriver::initializeExecutionEnvironment() {
}
if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); }
- gcc = GCC::create(Message, GCCBinary, &GCCToolArgv);
- if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); }
+ cc = CC::create(Message, CCBinary, &CCToolArgv);
+ if (!cc) { outs() << Message << "\nExiting.\n"; exit(1); }
// If there was an error creating the selected interpreter, quit with error.
return Interpreter == nullptr;
@@ -388,13 +395,13 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile,
std::string OutputFile;
// Using the known-good backend.
- GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile,
+ CC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile,
Error);
if (!Error.empty())
return "";
std::string SharedObjectFile;
- bool Failure = gcc->MakeSharedObject(OutputFile, FT, SharedObjectFile,
+ bool Failure = cc->MakeSharedObject(OutputFile, FT, SharedObjectFile,
AdditionalLinkerArgs, Error);
if (!Error.empty())
return "";
diff --git a/contrib/llvm/tools/bugpoint/ExtractFunction.cpp b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp
index 238cbbc..fe0ab69 100644
--- a/contrib/llvm/tools/bugpoint/ExtractFunction.cpp
+++ b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp
@@ -86,7 +86,7 @@ std::unique_ptr<Module>
BugDriver::deleteInstructionFromProgram(const Instruction *I,
unsigned Simplification) {
// FIXME, use vmap?
- Module *Clone = CloneModule(Program);
+ Module *Clone = CloneModule(Program).release();
const BasicBlock *PBB = I->getParent();
const Function *PF = PBB->getParent();
@@ -100,7 +100,7 @@ BugDriver::deleteInstructionFromProgram(const Instruction *I,
BasicBlock::iterator RI = RBI->begin(); // Get iterator to corresponding inst
std::advance(RI, std::distance(PBB->begin(), BasicBlock::const_iterator(I)));
- Instruction *TheInst = RI; // Got the corresponding instruction!
+ Instruction *TheInst = &*RI; // Got the corresponding instruction!
// If this instruction produces a value, replace any users with null values
if (!TheInst->getType()->isVoidTy())
@@ -179,11 +179,43 @@ std::unique_ptr<Module> BugDriver::extractLoop(Module *M) {
return NewM;
}
+static void eliminateAliases(GlobalValue *GV) {
+ // First, check whether a GlobalAlias references this definition.
+ // GlobalAlias MAY NOT reference declarations.
+ for (;;) {
+ // 1. Find aliases
+ SmallVector<GlobalAlias*,1> aliases;
+ Module *M = GV->getParent();
+ for (Module::alias_iterator I=M->alias_begin(), E=M->alias_end(); I!=E; ++I)
+ if (I->getAliasee()->stripPointerCasts() == GV)
+ aliases.push_back(&*I);
+ if (aliases.empty())
+ break;
+ // 2. Resolve aliases
+ for (unsigned i=0, e=aliases.size(); i<e; ++i) {
+ aliases[i]->replaceAllUsesWith(aliases[i]->getAliasee());
+ aliases[i]->eraseFromParent();
+ }
+ // 3. Repeat until no more aliases found; there might
+ // be an alias to an alias...
+ }
+}
+
+//
+// DeleteGlobalInitializer - "Remove" the global variable by deleting its initializer,
+// making it external.
+//
+void llvm::DeleteGlobalInitializer(GlobalVariable *GV) {
+ eliminateAliases(GV);
+ GV->setInitializer(nullptr);
+}
// DeleteFunctionBody - "Remove" the function by deleting all of its basic
// blocks, making it external.
//
void llvm::DeleteFunctionBody(Function *F) {
+ eliminateAliases(F);
+
// delete the body of the function...
F->deleteBody();
assert(F->isDeclaration() && "This didn't make the function external!");
@@ -271,13 +303,8 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
}
}
-
-/// SplitFunctionsOutOfModule - Given a module and a list of functions in the
-/// module, split the functions OUT of the specified module, and place them in
-/// the new module.
-Module *
-llvm::SplitFunctionsOutOfModule(Module *M,
- const std::vector<Function*> &F,
+std::unique_ptr<Module>
+llvm::SplitFunctionsOutOfModule(Module *M, const std::vector<Function *> &F,
ValueToValueMapTy &VMap) {
// Make sure functions & globals are all external so that linkage
// between the two modules will work.
@@ -291,7 +318,7 @@ llvm::SplitFunctionsOutOfModule(Module *M,
}
ValueToValueMapTy NewVMap;
- Module *New = CloneModule(M, NewVMap);
+ std::unique_ptr<Module> New = CloneModule(M, NewVMap);
// Remove the Test functions from the Safe module
std::set<Function *> TestFunctions;
@@ -306,16 +333,14 @@ llvm::SplitFunctionsOutOfModule(Module *M,
// Remove the Safe functions from the Test module
- for (Module::iterator I = New->begin(), E = New->end(); I != E; ++I)
- if (!TestFunctions.count(I))
- DeleteFunctionBody(I);
-
+ for (Function &I : *New)
+ if (!TestFunctions.count(&I))
+ DeleteFunctionBody(&I);
// Try to split the global initializers evenly
- for (Module::global_iterator I = M->global_begin(), E = M->global_end();
- I != E; ++I) {
- GlobalVariable *GV = cast<GlobalVariable>(NewVMap[I]);
- if (Function *TestFn = globalInitUsesExternalBA(I)) {
+ for (GlobalVariable &I : M->globals()) {
+ GlobalVariable *GV = cast<GlobalVariable>(NewVMap[&I]);
+ if (Function *TestFn = globalInitUsesExternalBA(&I)) {
if (Function *SafeFn = globalInitUsesExternalBA(GV)) {
errs() << "*** Error: when reducing functions, encountered "
"the global '";
@@ -325,18 +350,18 @@ llvm::SplitFunctionsOutOfModule(Module *M,
<< "' and from test function '" << TestFn->getName() << "'.\n";
exit(1);
}
- I->setInitializer(nullptr); // Delete the initializer to make it external
+ DeleteGlobalInitializer(&I); // Delete the initializer to make it external
} else {
// If we keep it in the safe module, then delete it in the test module
- GV->setInitializer(nullptr);
+ DeleteGlobalInitializer(GV);
}
}
// Make sure that there is a global ctor/dtor array in both halves of the
// module if they both have static ctor/dtor functions.
- SplitStaticCtorDtor("llvm.global_ctors", M, New, NewVMap);
- SplitStaticCtorDtor("llvm.global_dtors", M, New, NewVMap);
-
+ SplitStaticCtorDtor("llvm.global_ctors", M, New.get(), NewVMap);
+ SplitStaticCtorDtor("llvm.global_dtors", M, New.get(), NewVMap);
+
return New;
}
diff --git a/contrib/llvm/tools/bugpoint/ListReducer.h b/contrib/llvm/tools/bugpoint/ListReducer.h
index a0bb570..f08bc97 100644
--- a/contrib/llvm/tools/bugpoint/ListReducer.h
+++ b/contrib/llvm/tools/bugpoint/ListReducer.h
@@ -75,6 +75,11 @@ struct ListReducer {
// Maximal number of allowed splitting iterations,
// before the elements are randomly shuffled.
const unsigned MaxIterationsWithoutProgress = 3;
+
+ // Maximal number of allowed single-element trim iterations. We add a
+ // threshhold here as single-element reductions may otherwise take a
+ // very long time to complete.
+ const unsigned MaxTrimIterationsWithoutBackJump = 3;
bool ShufflingEnabled = true;
Backjump:
@@ -157,6 +162,7 @@ Backjump:
if (TheList.size() > 2) {
bool Changed = true;
std::vector<ElTy> EmptyList;
+ unsigned TrimIterations = 0;
while (Changed) { // Trimming loop.
Changed = false;
@@ -186,9 +192,9 @@ Backjump:
if (!Error.empty())
return true;
}
- // This can take a long time if left uncontrolled. For now, don't
- // iterate.
- break;
+ if (TrimIterations >= MaxTrimIterationsWithoutBackJump)
+ break;
+ TrimIterations++;
}
}
diff --git a/contrib/llvm/tools/bugpoint/Miscompilation.cpp b/contrib/llvm/tools/bugpoint/Miscompilation.cpp
index fad1636..16919f5 100644
--- a/contrib/llvm/tools/bugpoint/Miscompilation.cpp
+++ b/contrib/llvm/tools/bugpoint/Miscompilation.cpp
@@ -176,12 +176,15 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
namespace {
class ReduceMiscompilingFunctions : public ListReducer<Function*> {
BugDriver &BD;
- bool (*TestFn)(BugDriver &, Module *, Module *, std::string &);
+ bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
+ std::unique_ptr<Module>, std::string &);
+
public:
ReduceMiscompilingFunctions(BugDriver &bd,
- bool (*F)(BugDriver &, Module *, Module *,
+ bool (*F)(BugDriver &, std::unique_ptr<Module>,
+ std::unique_ptr<Module>,
std::string &))
- : BD(bd), TestFn(F) {}
+ : BD(bd), TestFn(F) {}
TestResult doTest(std::vector<Function*> &Prefix,
std::vector<Function*> &Suffix,
@@ -207,32 +210,24 @@ namespace {
};
}
-/// TestMergedProgram - Given two modules, link them together and run the
-/// program, checking to see if the program matches the diff. If there is
-/// an error, return NULL. If not, return the merged module. The Broken argument
-/// will be set to true if the output is different. If the DeleteInputs
-/// argument is set to true then this function deletes both input
-/// modules before it returns.
+/// Given two modules, link them together and run the program, checking to see
+/// if the program matches the diff. If there is an error, return NULL. If not,
+/// return the merged module. The Broken argument will be set to true if the
+/// output is different. If the DeleteInputs argument is set to true then this
+/// function deletes both input modules before it returns.
///
-static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2,
- bool DeleteInputs, std::string &Error,
- bool &Broken) {
- // Link the two portions of the program back to together.
- if (!DeleteInputs) {
- M1 = CloneModule(M1);
- M2 = CloneModule(M2);
- }
- if (Linker::LinkModules(M1, M2))
+static std::unique_ptr<Module> testMergedProgram(const BugDriver &BD,
+ std::unique_ptr<Module> M1,
+ std::unique_ptr<Module> M2,
+ std::string &Error,
+ bool &Broken) {
+ if (Linker::linkModules(*M1, std::move(M2)))
exit(1);
- delete M2; // We are done with this module.
// Execute the program.
- Broken = BD.diffProgram(M1, "", "", false, &Error);
- if (!Error.empty()) {
- // Delete the linked module
- delete M1;
+ Broken = BD.diffProgram(M1.get(), "", "", false, &Error);
+ if (!Error.empty())
return nullptr;
- }
return M1;
}
@@ -259,7 +254,7 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
// we can conclude that a function triggers the bug when in fact one
// needs a larger set of original functions to do so.
ValueToValueMapTy VMap;
- Module *Clone = CloneModule(BD.getProgram(), VMap);
+ Module *Clone = CloneModule(BD.getProgram(), VMap).release();
Module *Orig = BD.swapProgramIn(Clone);
std::vector<Function*> FuncsOnClone;
@@ -270,12 +265,12 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs,
// Split the module into the two halves of the program we want.
VMap.clear();
- Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap);
- Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, FuncsOnClone,
- VMap);
+ std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
+ std::unique_ptr<Module> ToOptimize =
+ SplitFunctionsOutOfModule(ToNotOptimize.get(), FuncsOnClone, VMap);
- // Run the predicate, note that the predicate will delete both input modules.
- bool Broken = TestFn(BD, ToOptimize, ToNotOptimize, Error);
+ bool Broken =
+ TestFn(BD, std::move(ToOptimize), std::move(ToNotOptimize), Error);
delete BD.swapProgramIn(Orig);
@@ -294,29 +289,29 @@ static void DisambiguateGlobalSymbols(Module *M) {
I->setName("anon_fn");
}
-/// ExtractLoops - Given a reduced list of functions that still exposed the bug,
-/// check to see if we can extract the loops in the region without obscuring the
-/// bug. If so, it reduces the amount of code identified.
+/// Given a reduced list of functions that still exposed the bug, check to see
+/// if we can extract the loops in the region without obscuring the bug. If so,
+/// it reduces the amount of code identified.
///
static bool ExtractLoops(BugDriver &BD,
- bool (*TestFn)(BugDriver &, Module *, Module *,
- std::string &),
- std::vector<Function*> &MiscompiledFunctions,
+ bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
+ std::unique_ptr<Module>, std::string &),
+ std::vector<Function *> &MiscompiledFunctions,
std::string &Error) {
bool MadeChange = false;
while (1) {
if (BugpointIsInterrupted) return MadeChange;
ValueToValueMapTy VMap;
- Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap);
- Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
- MiscompiledFunctions,
- VMap);
- Module *ToOptimizeLoopExtracted = BD.extractLoop(ToOptimize).release();
+ std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
+ Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize.get(),
+ MiscompiledFunctions, VMap)
+ .release();
+ std::unique_ptr<Module> ToOptimizeLoopExtracted =
+ BD.extractLoop(ToOptimize);
if (!ToOptimizeLoopExtracted) {
// If the loop extractor crashed or if there were no extractible loops,
// then this chapter of our odyssey is over with.
- delete ToNotOptimize;
delete ToOptimize;
return MadeChange;
}
@@ -330,13 +325,14 @@ static bool ExtractLoops(BugDriver &BD,
// extraction.
AbstractInterpreter *AI = BD.switchToSafeInterpreter();
bool Failure;
- Module *New = TestMergedProgram(BD, ToOptimizeLoopExtracted,
- ToNotOptimize, false, Error, Failure);
+ std::unique_ptr<Module> New =
+ testMergedProgram(BD, std::move(ToOptimizeLoopExtracted),
+ std::move(ToNotOptimize), Error, Failure);
if (!New)
return false;
// Delete the original and set the new program.
- Module *Old = BD.swapProgramIn(New);
+ Module *Old = BD.swapProgramIn(New.release());
for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
delete Old;
@@ -350,16 +346,15 @@ static bool ExtractLoops(BugDriver &BD,
errs() << " Continuing on with un-loop-extracted version.\n";
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc",
- ToNotOptimize);
+ ToNotOptimize.get());
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc",
ToOptimize);
BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc",
- ToOptimizeLoopExtracted);
+ ToOptimizeLoopExtracted.get());
errs() << "Please submit the "
<< OutputPrefix << "-loop-extract-fail-*.bc files.\n";
delete ToOptimize;
- delete ToNotOptimize;
return MadeChange;
}
delete ToOptimize;
@@ -367,18 +362,20 @@ static bool ExtractLoops(BugDriver &BD,
outs() << " Testing after loop extraction:\n";
// Clone modules, the tester function will free them.
- Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted, VMap);
- Module *TNOBackup = CloneModule(ToNotOptimize, VMap);
+ std::unique_ptr<Module> TOLEBackup =
+ CloneModule(ToOptimizeLoopExtracted.get(), VMap);
+ std::unique_ptr<Module> TNOBackup = CloneModule(ToNotOptimize.get(), VMap);
for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]);
- Failure = TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize, Error);
+ Failure = TestFn(BD, std::move(ToOptimizeLoopExtracted),
+ std::move(ToNotOptimize), Error);
if (!Error.empty())
return false;
- ToOptimizeLoopExtracted = TOLEBackup;
- ToNotOptimize = TNOBackup;
+ ToOptimizeLoopExtracted = std::move(TOLEBackup);
+ ToNotOptimize = std::move(TNOBackup);
if (!Failure) {
outs() << "*** Loop extraction masked the problem. Undoing.\n";
@@ -390,7 +387,8 @@ static bool ExtractLoops(BugDriver &BD,
MisCompFunctions.emplace_back(F->getName(), F->getFunctionType());
}
- if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted))
+ if (Linker::linkModules(*ToNotOptimize,
+ std::move(ToOptimizeLoopExtracted)))
exit(1);
MiscompiledFunctions.clear();
@@ -401,8 +399,7 @@ static bool ExtractLoops(BugDriver &BD,
MiscompiledFunctions.push_back(NewF);
}
- delete ToOptimizeLoopExtracted;
- BD.setNewProgram(ToNotOptimize);
+ BD.setNewProgram(ToNotOptimize.release());
return MadeChange;
}
@@ -418,11 +415,9 @@ static bool ExtractLoops(BugDriver &BD,
// extraction both didn't break the program, and didn't mask the problem.
// Replace the current program with the loop extracted version, and try to
// extract another loop.
- if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted))
+ if (Linker::linkModules(*ToNotOptimize, std::move(ToOptimizeLoopExtracted)))
exit(1);
- delete ToOptimizeLoopExtracted;
-
// All of the Function*'s in the MiscompiledFunctions list are in the old
// module. Update this list to include all of the functions in the
// optimized and loop extracted module.
@@ -434,7 +429,7 @@ static bool ExtractLoops(BugDriver &BD,
MiscompiledFunctions.push_back(NewF);
}
- BD.setNewProgram(ToNotOptimize);
+ BD.setNewProgram(ToNotOptimize.release());
MadeChange = true;
}
}
@@ -442,14 +437,15 @@ static bool ExtractLoops(BugDriver &BD,
namespace {
class ReduceMiscompiledBlocks : public ListReducer<BasicBlock*> {
BugDriver &BD;
- bool (*TestFn)(BugDriver &, Module *, Module *, std::string &);
+ bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
+ std::unique_ptr<Module>, std::string &);
std::vector<Function*> FunctionsBeingTested;
public:
ReduceMiscompiledBlocks(BugDriver &bd,
- bool (*F)(BugDriver &, Module *, Module *,
- std::string &),
- const std::vector<Function*> &Fns)
- : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {}
+ bool (*F)(BugDriver &, std::unique_ptr<Module>,
+ std::unique_ptr<Module>, std::string &),
+ const std::vector<Function *> &Fns)
+ : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {}
TestResult doTest(std::vector<BasicBlock*> &Prefix,
std::vector<BasicBlock*> &Suffix,
@@ -495,7 +491,7 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs,
// Split the module into the two halves of the program we want.
ValueToValueMapTy VMap;
- Module *Clone = CloneModule(BD.getProgram(), VMap);
+ Module *Clone = CloneModule(BD.getProgram(), VMap).release();
Module *Orig = BD.swapProgramIn(Clone);
std::vector<Function*> FuncsOnClone;
std::vector<BasicBlock*> BBsOnClone;
@@ -509,45 +505,37 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs,
}
VMap.clear();
- Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap);
- Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
- FuncsOnClone,
- VMap);
+ std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap);
+ std::unique_ptr<Module> ToOptimize =
+ SplitFunctionsOutOfModule(ToNotOptimize.get(), FuncsOnClone, VMap);
// Try the extraction. If it doesn't work, then the block extractor crashed
// or something, in which case bugpoint can't chase down this possibility.
if (std::unique_ptr<Module> New =
- BD.extractMappedBlocksFromModule(BBsOnClone, ToOptimize)) {
- delete ToOptimize;
- // Run the predicate,
- // note that the predicate will delete both input modules.
- bool Ret = TestFn(BD, New.get(), ToNotOptimize, Error);
+ BD.extractMappedBlocksFromModule(BBsOnClone, ToOptimize.get())) {
+ bool Ret = TestFn(BD, std::move(New), std::move(ToNotOptimize), Error);
delete BD.swapProgramIn(Orig);
return Ret;
}
delete BD.swapProgramIn(Orig);
- delete ToOptimize;
- delete ToNotOptimize;
return false;
}
-
-/// ExtractBlocks - Given a reduced list of functions that still expose the bug,
-/// extract as many basic blocks from the region as possible without obscuring
-/// the bug.
+/// Given a reduced list of functions that still expose the bug, extract as many
+/// basic blocks from the region as possible without obscuring the bug.
///
static bool ExtractBlocks(BugDriver &BD,
- bool (*TestFn)(BugDriver &, Module *, Module *,
+ bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
+ std::unique_ptr<Module>,
std::string &),
- std::vector<Function*> &MiscompiledFunctions,
+ std::vector<Function *> &MiscompiledFunctions,
std::string &Error) {
if (BugpointIsInterrupted) return false;
std::vector<BasicBlock*> Blocks;
for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
- for (Function::iterator I = MiscompiledFunctions[i]->begin(),
- E = MiscompiledFunctions[i]->end(); I != E; ++I)
- Blocks.push_back(I);
+ for (BasicBlock &BB : *MiscompiledFunctions[i])
+ Blocks.push_back(&BB);
// Use the list reducer to identify blocks that can be extracted without
// obscuring the bug. The Blocks list will end up containing blocks that must
@@ -571,10 +559,10 @@ static bool ExtractBlocks(BugDriver &BD,
}
ValueToValueMapTy VMap;
- Module *ProgClone = CloneModule(BD.getProgram(), VMap);
- Module *ToExtract = SplitFunctionsOutOfModule(ProgClone,
- MiscompiledFunctions,
- VMap);
+ Module *ProgClone = CloneModule(BD.getProgram(), VMap).release();
+ Module *ToExtract =
+ SplitFunctionsOutOfModule(ProgClone, MiscompiledFunctions, VMap)
+ .release();
std::unique_ptr<Module> Extracted =
BD.extractMappedBlocksFromModule(Blocks, ToExtract);
if (!Extracted) {
@@ -595,7 +583,7 @@ static bool ExtractBlocks(BugDriver &BD,
if (!I->isDeclaration())
MisCompFunctions.emplace_back(I->getName(), I->getFunctionType());
- if (Linker::LinkModules(ProgClone, Extracted.get()))
+ if (Linker::linkModules(*ProgClone, std::move(Extracted)))
exit(1);
// Set the new program and delete the old one.
@@ -613,14 +601,13 @@ static bool ExtractBlocks(BugDriver &BD,
return true;
}
-
-/// DebugAMiscompilation - This is a generic driver to narrow down
-/// miscompilations, either in an optimization or a code generator.
+/// This is a generic driver to narrow down miscompilations, either in an
+/// optimization or a code generator.
///
-static std::vector<Function*>
+static std::vector<Function *>
DebugAMiscompilation(BugDriver &BD,
- bool (*TestFn)(BugDriver &, Module *, Module *,
- std::string &),
+ bool (*TestFn)(BugDriver &, std::unique_ptr<Module>,
+ std::unique_ptr<Module>, std::string &),
std::string &Error) {
// Okay, now that we have reduced the list of passes which are causing the
// failure, see if we can pin down which functions are being
@@ -628,9 +615,9 @@ DebugAMiscompilation(BugDriver &BD,
// the program.
std::vector<Function*> MiscompiledFunctions;
Module *Prog = BD.getProgram();
- for (Module::iterator I = Prog->begin(), E = Prog->end(); I != E; ++I)
- if (!I->isDeclaration())
- MiscompiledFunctions.push_back(I);
+ for (Function &F : *Prog)
+ if (!F.isDeclaration())
+ MiscompiledFunctions.push_back(&F);
// Do the reduction...
if (!BugpointIsInterrupted)
@@ -699,28 +686,28 @@ DebugAMiscompilation(BugDriver &BD,
return MiscompiledFunctions;
}
-/// TestOptimizer - This is the predicate function used to check to see if the
-/// "Test" portion of the program is misoptimized. If so, return true. In any
-/// case, both module arguments are deleted.
+/// This is the predicate function used to check to see if the "Test" portion of
+/// the program is misoptimized. If so, return true. In any case, both module
+/// arguments are deleted.
///
-static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe,
- std::string &Error) {
+static bool TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test,
+ std::unique_ptr<Module> Safe, std::string &Error) {
// Run the optimization passes on ToOptimize, producing a transformed version
// of the functions being tested.
outs() << " Optimizing functions being tested: ";
- std::unique_ptr<Module> Optimized = BD.runPassesOn(Test, BD.getPassesToRun(),
- /*AutoDebugCrashes*/ true);
+ std::unique_ptr<Module> Optimized =
+ BD.runPassesOn(Test.get(), BD.getPassesToRun(),
+ /*AutoDebugCrashes*/ true);
outs() << "done.\n";
- delete Test;
outs() << " Checking to see if the merged program executes correctly: ";
bool Broken;
- Module *New =
- TestMergedProgram(BD, Optimized.get(), Safe, true, Error, Broken);
+ std::unique_ptr<Module> New = testMergedProgram(
+ BD, std::move(Optimized), std::move(Safe), Error, Broken);
if (New) {
outs() << (Broken ? " nope.\n" : " yup.\n");
// Delete the original and set the new program.
- delete BD.swapProgramIn(New);
+ delete BD.swapProgramIn(New.release());
}
return Broken;
}
@@ -753,10 +740,10 @@ void BugDriver::debugMiscompilation(std::string *Error) {
// Output a bunch of bitcode files for the user...
outs() << "Outputting reduced bitcode files which expose the problem:\n";
ValueToValueMapTy VMap;
- Module *ToNotOptimize = CloneModule(getProgram(), VMap);
- Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize,
- MiscompiledFunctions,
- VMap);
+ Module *ToNotOptimize = CloneModule(getProgram(), VMap).release();
+ Module *ToOptimize =
+ SplitFunctionsOutOfModule(ToNotOptimize, MiscompiledFunctions, VMap)
+ .release();
outs() << " Non-optimized portion: ";
EmitProgressBitcode(ToNotOptimize, "tonotoptimize", true);
@@ -769,13 +756,13 @@ void BugDriver::debugMiscompilation(std::string *Error) {
return;
}
-/// CleanupAndPrepareModules - Get the specified modules ready for code
-/// generator testing.
+/// Get the specified modules ready for code generator testing.
///
-static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
+static void CleanupAndPrepareModules(BugDriver &BD,
+ std::unique_ptr<Module> &Test,
Module *Safe) {
// Clean up the modules, removing extra cruft that we don't need anymore...
- Test = BD.performFinalCleanups(Test).release();
+ Test = BD.performFinalCleanups(Test.get());
// If we are executing the JIT, we have several nasty issues to take care of.
if (!BD.isExecutingJIT()) return;
@@ -788,21 +775,21 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
// Rename it
oldMain->setName("llvm_bugpoint_old_main");
// Create a NEW `main' function with same type in the test module.
- Function *newMain = Function::Create(oldMain->getFunctionType(),
- GlobalValue::ExternalLinkage,
- "main", Test);
+ Function *newMain =
+ Function::Create(oldMain->getFunctionType(),
+ GlobalValue::ExternalLinkage, "main", Test.get());
// Create an `oldmain' prototype in the test module, which will
// corresponds to the real main function in the same module.
Function *oldMainProto = Function::Create(oldMain->getFunctionType(),
GlobalValue::ExternalLinkage,
- oldMain->getName(), Test);
+ oldMain->getName(), Test.get());
// Set up and remember the argument list for the main function.
std::vector<Value*> args;
for (Function::arg_iterator
I = newMain->arg_begin(), E = newMain->arg_end(),
OI = oldMain->arg_begin(); I != E; ++I, ++OI) {
I->setName(OI->getName()); // Copy argument names from oldMain
- args.push_back(I);
+ args.push_back(&*I);
}
// Call the old main function and return its result
@@ -905,9 +892,8 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
// Save the argument list.
std::vector<Value*> Args;
- for (Function::arg_iterator i = FuncWrapper->arg_begin(),
- e = FuncWrapper->arg_end(); i != e; ++i)
- Args.push_back(i);
+ for (Argument &A : FuncWrapper->args())
+ Args.push_back(&A);
// Pass on the arguments to the real function, return its result
if (F->getReturnType()->isVoidTy()) {
@@ -932,15 +918,14 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
}
}
-
-
-/// TestCodeGenerator - This is the predicate function used to check to see if
-/// the "Test" portion of the program is miscompiled by the code generator under
-/// test. If so, return true. In any case, both module arguments are deleted.
+/// This is the predicate function used to check to see if the "Test" portion of
+/// the program is miscompiled by the code generator under test. If so, return
+/// true. In any case, both module arguments are deleted.
///
-static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
+static bool TestCodeGenerator(BugDriver &BD, std::unique_ptr<Module> Test,
+ std::unique_ptr<Module> Safe,
std::string &Error) {
- CleanupAndPrepareModules(BD, Test, Safe);
+ CleanupAndPrepareModules(BD, Test, Safe.get());
SmallString<128> TestModuleBC;
int TestModuleFD;
@@ -951,12 +936,11 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
<< EC.message() << "\n";
exit(1);
}
- if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test)) {
+ if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test.get())) {
errs() << "Error writing bitcode to `" << TestModuleBC.str()
<< "'\nExiting.";
exit(1);
}
- delete Test;
FileRemover TestModuleBCRemover(TestModuleBC.str(), !SaveTemps);
@@ -971,7 +955,7 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
exit(1);
}
- if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe)) {
+ if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe.get())) {
errs() << "Error writing bitcode to `" << SafeModuleBC
<< "'\nExiting.";
exit(1);
@@ -982,7 +966,6 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error);
if (!Error.empty())
return false;
- delete Safe;
FileRemover SharedObjectRemover(SharedObject, !SaveTemps);
@@ -1030,11 +1013,12 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
// Split the module into the two halves of the program we want.
ValueToValueMapTy VMap;
- Module *ToNotCodeGen = CloneModule(getProgram(), VMap);
- Module *ToCodeGen = SplitFunctionsOutOfModule(ToNotCodeGen, Funcs, VMap);
+ std::unique_ptr<Module> ToNotCodeGen = CloneModule(getProgram(), VMap);
+ std::unique_ptr<Module> ToCodeGen =
+ SplitFunctionsOutOfModule(ToNotCodeGen.get(), Funcs, VMap);
// Condition the modules
- CleanupAndPrepareModules(*this, ToCodeGen, ToNotCodeGen);
+ CleanupAndPrepareModules(*this, ToCodeGen, ToNotCodeGen.get());
SmallString<128> TestModuleBC;
int TestModuleFD;
@@ -1046,12 +1030,11 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
exit(1);
}
- if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen)) {
+ if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen.get())) {
errs() << "Error writing bitcode to `" << TestModuleBC
<< "'\nExiting.";
exit(1);
}
- delete ToCodeGen;
// Make the shared library
SmallString<128> SafeModuleBC;
@@ -1064,7 +1047,8 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
exit(1);
}
- if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, ToNotCodeGen)) {
+ if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD,
+ ToNotCodeGen.get())) {
errs() << "Error writing bitcode to `" << SafeModuleBC
<< "'\nExiting.";
exit(1);
@@ -1072,7 +1056,6 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
std::string SharedObject = compileSharedObject(SafeModuleBC.str(), *Error);
if (!Error->empty())
return true;
- delete ToNotCodeGen;
outs() << "You can reproduce the problem with the command line: \n";
if (isExecutingJIT()) {
@@ -1080,7 +1063,7 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
} else {
outs() << " llc " << TestModuleBC << " -o " << TestModuleBC
<< ".s\n";
- outs() << " gcc " << SharedObject << " " << TestModuleBC.str()
+ outs() << " cc " << SharedObject << " " << TestModuleBC.str()
<< ".s -o " << TestModuleBC << ".exe";
#if defined (HAVE_LINK_R)
outs() << " -Wl,-R.";
@@ -1093,7 +1076,7 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
outs() << '\n';
outs() << "The shared object was created with:\n llc -march=c "
<< SafeModuleBC.str() << " -o temporary.c\n"
- << " gcc -xc temporary.c -O2 -o " << SharedObject;
+ << " cc -xc temporary.c -O2 -o " << SharedObject;
if (TargetTriple.getArch() == Triple::sparc)
outs() << " -G"; // Compile a shared library, `-G' for Sparc
else
diff --git a/contrib/llvm/tools/bugpoint/ToolRunner.cpp b/contrib/llvm/tools/bugpoint/ToolRunner.cpp
index 51091e2..2ccd649 100644
--- a/contrib/llvm/tools/bugpoint/ToolRunner.cpp
+++ b/contrib/llvm/tools/bugpoint/ToolRunner.cpp
@@ -64,16 +64,6 @@ static int RunProgramWithTimeout(StringRef ProgramPath,
unsigned MemoryLimit = 0,
std::string *ErrMsg = nullptr) {
const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile };
-
-#if 0 // For debug purposes
- {
- errs() << "RUN:";
- for (unsigned i = 0; Args[i]; ++i)
- errs() << " " << Args[i];
- errs() << "\n";
- }
-#endif
-
return sys::ExecuteAndWait(ProgramPath, Args, nullptr, Redirects,
NumSeconds, MemoryLimit, ErrMsg);
}
@@ -93,15 +83,6 @@ static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath,
unsigned MemoryLimit = 0) {
const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile };
-#if 0 // For debug purposes
- {
- errs() << "RUN:";
- for (unsigned i = 0; Args[i]; ++i)
- errs() << " " << Args[i];
- errs() << "\n";
- }
-#endif
-
// Run the program remotely with the remote client
int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, nullptr,
Redirects, NumSeconds, MemoryLimit);
@@ -152,7 +133,7 @@ static std::string ProcessFailure(StringRef ProgPath, const char** Args,
ErrorFilename.str(), Timeout, MemoryLimit);
// FIXME: check return code ?
- // Print out the error messages generated by GCC if possible...
+ // Print out the error messages generated by CC if possible...
std::ifstream ErrorFile(ErrorFilename.c_str());
if (ErrorFile) {
std::copy(std::istreambuf_iterator<char>(ErrorFile),
@@ -184,7 +165,7 @@ namespace {
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error,
- const std::vector<std::string> &GCCArgs,
+ const std::vector<std::string> &CCArgs,
const std::vector<std::string> &SharedLibs =
std::vector<std::string>(),
unsigned Timeout = 0,
@@ -197,7 +178,7 @@ int LLI::ExecuteProgram(const std::string &Bitcode,
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error,
- const std::vector<std::string> &GCCArgs,
+ const std::vector<std::string> &CCArgs,
const std::vector<std::string> &SharedLibs,
unsigned Timeout,
unsigned MemoryLimit) {
@@ -305,7 +286,7 @@ namespace {
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error,
- const std::vector<std::string> &GCCArgs =
+ const std::vector<std::string> &CCArgs =
std::vector<std::string>(),
const std::vector<std::string> &SharedLibs =
std::vector<std::string>(),
@@ -361,7 +342,7 @@ namespace {
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error,
- const std::vector<std::string> &GCCArgs,
+ const std::vector<std::string> &CCArgs,
const std::vector<std::string> &SharedLibs =
std::vector<std::string>(),
unsigned Timeout = 0,
@@ -374,7 +355,7 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode,
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error,
- const std::vector<std::string> &GCCArgs,
+ const std::vector<std::string> &CCArgs,
const std::vector<std::string> &SharedLibs,
unsigned Timeout,
unsigned MemoryLimit) {
@@ -473,7 +454,7 @@ AbstractInterpreter *AbstractInterpreter::createCustomExecutor(
//===----------------------------------------------------------------------===//
// LLC Implementation of AbstractIntepreter interface
//
-GCC::FileType LLC::OutputCode(const std::string &Bitcode,
+CC::FileType LLC::OutputCode(const std::string &Bitcode,
std::string &OutputAsmFile, std::string &Error,
unsigned Timeout, unsigned MemoryLimit) {
const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s");
@@ -514,7 +495,7 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode,
Timeout, MemoryLimit))
Error = ProcessFailure(LLCPath, &LLCArgs[0],
Timeout, MemoryLimit);
- return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile;
+ return UseIntegratedAssembler ? CC::ObjectFile : CC::AsmFile;
}
void LLC::compileProgram(const std::string &Bitcode, std::string *Error,
@@ -529,22 +510,22 @@ int LLC::ExecuteProgram(const std::string &Bitcode,
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error,
- const std::vector<std::string> &ArgsForGCC,
+ const std::vector<std::string> &ArgsForCC,
const std::vector<std::string> &SharedLibs,
unsigned Timeout,
unsigned MemoryLimit) {
std::string OutputAsmFile;
- GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout,
+ CC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout,
MemoryLimit);
FileRemover OutFileRemover(OutputAsmFile, !SaveTemps);
- std::vector<std::string> GCCArgs(ArgsForGCC);
- GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end());
+ std::vector<std::string> CCArgs(ArgsForCC);
+ CCArgs.insert(CCArgs.end(), SharedLibs.begin(), SharedLibs.end());
- // Assuming LLC worked, compile the result with GCC and run it.
- return gcc->ExecuteProgram(OutputAsmFile, Args, FileKind,
- InputFile, OutputFile, Error, GCCArgs,
+ // Assuming LLC worked, compile the result with CC and run it.
+ return cc->ExecuteProgram(OutputAsmFile, Args, FileKind,
+ InputFile, OutputFile, Error, CCArgs,
Timeout, MemoryLimit);
}
@@ -552,9 +533,9 @@ int LLC::ExecuteProgram(const std::string &Bitcode,
///
LLC *AbstractInterpreter::createLLC(const char *Argv0,
std::string &Message,
- const std::string &GCCBinary,
+ const std::string &CCBinary,
const std::vector<std::string> *Args,
- const std::vector<std::string> *GCCArgs,
+ const std::vector<std::string> *CCArgs,
bool UseIntegratedAssembler) {
std::string LLCPath =
PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t) & createLLC);
@@ -563,13 +544,13 @@ LLC *AbstractInterpreter::createLLC(const char *Argv0,
return nullptr;
}
- GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs);
- if (!gcc) {
+ CC *cc = CC::create(Message, CCBinary, CCArgs);
+ if (!cc) {
errs() << Message << "\n";
exit(1);
}
Message = "Found llc: " + LLCPath + "\n";
- return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler);
+ return new LLC(LLCPath, cc, Args, UseIntegratedAssembler);
}
//===---------------------------------------------------------------------===//
@@ -591,7 +572,7 @@ namespace {
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error,
- const std::vector<std::string> &GCCArgs =
+ const std::vector<std::string> &CCArgs =
std::vector<std::string>(),
const std::vector<std::string> &SharedLibs =
std::vector<std::string>(),
@@ -605,7 +586,7 @@ int JIT::ExecuteProgram(const std::string &Bitcode,
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error,
- const std::vector<std::string> &GCCArgs,
+ const std::vector<std::string> &CCArgs,
const std::vector<std::string> &SharedLibs,
unsigned Timeout,
unsigned MemoryLimit) {
@@ -656,7 +637,7 @@ AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0,
}
//===---------------------------------------------------------------------===//
-// GCC abstraction
+// CC abstraction
//
static bool IsARMArchitecture(std::vector<const char*> Args) {
@@ -672,82 +653,82 @@ static bool IsARMArchitecture(std::vector<const char*> Args) {
return false;
}
-int GCC::ExecuteProgram(const std::string &ProgramFile,
+int CC::ExecuteProgram(const std::string &ProgramFile,
const std::vector<std::string> &Args,
FileType fileType,
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error,
- const std::vector<std::string> &ArgsForGCC,
+ const std::vector<std::string> &ArgsForCC,
unsigned Timeout,
unsigned MemoryLimit) {
- std::vector<const char*> GCCArgs;
+ std::vector<const char*> CCArgs;
- GCCArgs.push_back(GCCPath.c_str());
+ CCArgs.push_back(CCPath.c_str());
if (TargetTriple.getArch() == Triple::x86)
- GCCArgs.push_back("-m32");
+ CCArgs.push_back("-m32");
for (std::vector<std::string>::const_iterator
- I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I)
- GCCArgs.push_back(I->c_str());
+ I = ccArgs.begin(), E = ccArgs.end(); I != E; ++I)
+ CCArgs.push_back(I->c_str());
// Specify -x explicitly in case the extension is wonky
if (fileType != ObjectFile) {
- GCCArgs.push_back("-x");
+ CCArgs.push_back("-x");
if (fileType == CFile) {
- GCCArgs.push_back("c");
- GCCArgs.push_back("-fno-strict-aliasing");
+ CCArgs.push_back("c");
+ CCArgs.push_back("-fno-strict-aliasing");
} else {
- GCCArgs.push_back("assembler");
+ CCArgs.push_back("assembler");
// For ARM architectures we don't want this flag. bugpoint isn't
// explicitly told what architecture it is working on, so we get
- // it from gcc flags
- if (TargetTriple.isOSDarwin() && !IsARMArchitecture(GCCArgs))
- GCCArgs.push_back("-force_cpusubtype_ALL");
+ // it from cc flags
+ if (TargetTriple.isOSDarwin() && !IsARMArchitecture(CCArgs))
+ CCArgs.push_back("-force_cpusubtype_ALL");
}
}
- GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename.
+ CCArgs.push_back(ProgramFile.c_str()); // Specify the input filename.
- GCCArgs.push_back("-x");
- GCCArgs.push_back("none");
- GCCArgs.push_back("-o");
+ CCArgs.push_back("-x");
+ CCArgs.push_back("none");
+ CCArgs.push_back("-o");
SmallString<128> OutputBinary;
std::error_code EC =
- sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.gcc.exe", OutputBinary);
+ sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.cc.exe", OutputBinary);
if (EC) {
errs() << "Error making unique filename: " << EC.message() << "\n";
exit(1);
}
- GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
+ CCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
- // Add any arguments intended for GCC. We locate them here because this is
+ // Add any arguments intended for CC. We locate them here because this is
// most likely -L and -l options that need to come before other libraries but
// after the source. Other options won't be sensitive to placement on the
// command line, so this should be safe.
- for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i)
- GCCArgs.push_back(ArgsForGCC[i].c_str());
+ for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
+ CCArgs.push_back(ArgsForCC[i].c_str());
- GCCArgs.push_back("-lm"); // Hard-code the math library...
- GCCArgs.push_back("-O2"); // Optimize the program a bit...
+ CCArgs.push_back("-lm"); // Hard-code the math library...
+ CCArgs.push_back("-O2"); // Optimize the program a bit...
#if defined (HAVE_LINK_R)
- GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files
+ CCArgs.push_back("-Wl,-R."); // Search this dir for .so files
#endif
if (TargetTriple.getArch() == Triple::sparc)
- GCCArgs.push_back("-mcpu=v9");
- GCCArgs.push_back(nullptr); // NULL terminator
+ CCArgs.push_back("-mcpu=v9");
+ CCArgs.push_back(nullptr); // NULL terminator
- outs() << "<gcc>"; outs().flush();
+ outs() << "<CC>"; outs().flush();
DEBUG(errs() << "\nAbout to run:\t";
- for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i)
- errs() << " " << GCCArgs[i];
+ for (unsigned i = 0, e = CCArgs.size()-1; i != e; ++i)
+ errs() << " " << CCArgs[i];
errs() << "\n";
);
- if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) {
- *Error = ProcessFailure(GCCPath, &GCCArgs[0]);
+ if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", "")) {
+ *Error = ProcessFailure(CCPath, &CCArgs[0]);
return -1;
}
@@ -821,9 +802,9 @@ int GCC::ExecuteProgram(const std::string &ProgramFile,
}
}
-int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
+int CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
std::string &OutputFile,
- const std::vector<std::string> &ArgsForGCC,
+ const std::vector<std::string> &ArgsForCC,
std::string &Error) {
SmallString<128> UniqueFilename;
std::error_code EC = sys::fs::createUniqueFile(
@@ -834,84 +815,84 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
}
OutputFile = UniqueFilename.str();
- std::vector<const char*> GCCArgs;
+ std::vector<const char*> CCArgs;
- GCCArgs.push_back(GCCPath.c_str());
+ CCArgs.push_back(CCPath.c_str());
if (TargetTriple.getArch() == Triple::x86)
- GCCArgs.push_back("-m32");
+ CCArgs.push_back("-m32");
for (std::vector<std::string>::const_iterator
- I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I)
- GCCArgs.push_back(I->c_str());
+ I = ccArgs.begin(), E = ccArgs.end(); I != E; ++I)
+ CCArgs.push_back(I->c_str());
// Compile the C/asm file into a shared object
if (fileType != ObjectFile) {
- GCCArgs.push_back("-x");
- GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
+ CCArgs.push_back("-x");
+ CCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
}
- GCCArgs.push_back("-fno-strict-aliasing");
- GCCArgs.push_back(InputFile.c_str()); // Specify the input filename.
- GCCArgs.push_back("-x");
- GCCArgs.push_back("none");
+ CCArgs.push_back("-fno-strict-aliasing");
+ CCArgs.push_back(InputFile.c_str()); // Specify the input filename.
+ CCArgs.push_back("-x");
+ CCArgs.push_back("none");
if (TargetTriple.getArch() == Triple::sparc)
- GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc
+ CCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc
else if (TargetTriple.isOSDarwin()) {
// link all source files into a single module in data segment, rather than
// generating blocks. dynamic_lookup requires that you set
// MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for
- // bugpoint to just pass that in the environment of GCC.
- GCCArgs.push_back("-single_module");
- GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC
- GCCArgs.push_back("-undefined");
- GCCArgs.push_back("dynamic_lookup");
+ // bugpoint to just pass that in the environment of CC.
+ CCArgs.push_back("-single_module");
+ CCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC
+ CCArgs.push_back("-undefined");
+ CCArgs.push_back("dynamic_lookup");
} else
- GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others
+ CCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others
if (TargetTriple.getArch() == Triple::x86_64)
- GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC
+ CCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC
if (TargetTriple.getArch() == Triple::sparc)
- GCCArgs.push_back("-mcpu=v9");
+ CCArgs.push_back("-mcpu=v9");
- GCCArgs.push_back("-o");
- GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename.
- GCCArgs.push_back("-O2"); // Optimize the program a bit.
+ CCArgs.push_back("-o");
+ CCArgs.push_back(OutputFile.c_str()); // Output to the right filename.
+ CCArgs.push_back("-O2"); // Optimize the program a bit.
- // Add any arguments intended for GCC. We locate them here because this is
+ // Add any arguments intended for CC. We locate them here because this is
// most likely -L and -l options that need to come before other libraries but
// after the source. Other options won't be sensitive to placement on the
// command line, so this should be safe.
- for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i)
- GCCArgs.push_back(ArgsForGCC[i].c_str());
- GCCArgs.push_back(nullptr); // NULL terminator
+ for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
+ CCArgs.push_back(ArgsForCC[i].c_str());
+ CCArgs.push_back(nullptr); // NULL terminator
- outs() << "<gcc>"; outs().flush();
+ outs() << "<CC>"; outs().flush();
DEBUG(errs() << "\nAbout to run:\t";
- for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i)
- errs() << " " << GCCArgs[i];
+ for (unsigned i = 0, e = CCArgs.size()-1; i != e; ++i)
+ errs() << " " << CCArgs[i];
errs() << "\n";
);
- if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) {
- Error = ProcessFailure(GCCPath, &GCCArgs[0]);
+ if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", "")) {
+ Error = ProcessFailure(CCPath, &CCArgs[0]);
return 1;
}
return 0;
}
-/// create - Try to find the `gcc' executable
+/// create - Try to find the CC executable
///
-GCC *GCC::create(std::string &Message,
- const std::string &GCCBinary,
+CC *CC::create(std::string &Message,
+ const std::string &CCBinary,
const std::vector<std::string> *Args) {
- auto GCCPath = sys::findProgramByName(GCCBinary);
- if (!GCCPath) {
- Message = "Cannot find `" + GCCBinary + "' in PATH: " +
- GCCPath.getError().message() + "\n";
+ auto CCPath = sys::findProgramByName(CCBinary);
+ if (!CCPath) {
+ Message = "Cannot find `" + CCBinary + "' in PATH: " +
+ CCPath.getError().message() + "\n";
return nullptr;
}
@@ -926,6 +907,6 @@ GCC *GCC::create(std::string &Message,
RemoteClientPath = *Path;
}
- Message = "Found gcc: " + *GCCPath + "\n";
- return new GCC(*GCCPath, RemoteClientPath, Args);
+ Message = "Found CC: " + *CCPath + "\n";
+ return new CC(*CCPath, RemoteClientPath, Args);
}
diff --git a/contrib/llvm/tools/bugpoint/ToolRunner.h b/contrib/llvm/tools/bugpoint/ToolRunner.h
index 5d67a94..3accd70 100644
--- a/contrib/llvm/tools/bugpoint/ToolRunner.h
+++ b/contrib/llvm/tools/bugpoint/ToolRunner.h
@@ -33,22 +33,22 @@ extern Triple TargetTriple;
class LLC;
//===---------------------------------------------------------------------===//
-// GCC abstraction
+// CC abstraction
//
-class GCC {
- std::string GCCPath; // The path to the gcc executable.
+class CC {
+ std::string CCPath; // The path to the cc executable.
std::string RemoteClientPath; // The path to the rsh / ssh executable.
- std::vector<std::string> gccArgs; // GCC-specific arguments.
- GCC(StringRef gccPath, StringRef RemotePath,
- const std::vector<std::string> *GCCArgs)
- : GCCPath(gccPath), RemoteClientPath(RemotePath) {
- if (GCCArgs) gccArgs = *GCCArgs;
+ std::vector<std::string> ccArgs; // CC-specific arguments.
+ CC(StringRef ccPath, StringRef RemotePath,
+ const std::vector<std::string> *CCArgs)
+ : CCPath(ccPath), RemoteClientPath(RemotePath) {
+ if (CCArgs) ccArgs = *CCArgs;
}
public:
enum FileType { AsmFile, ObjectFile, CFile };
- static GCC *create(std::string &Message,
- const std::string &GCCBinary,
+ static CC *create(std::string &Message,
+ const std::string &CCBinary,
const std::vector<std::string> *Args);
/// ExecuteProgram - Execute the program specified by "ProgramFile" (which is
@@ -64,7 +64,7 @@ public:
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error = nullptr,
- const std::vector<std::string> &GCCArgs =
+ const std::vector<std::string> &CCArgs =
std::vector<std::string>(),
unsigned Timeout = 0,
unsigned MemoryLimit = 0);
@@ -74,7 +74,7 @@ public:
///
int MakeSharedObject(const std::string &InputFile, FileType fileType,
std::string &OutputFile,
- const std::vector<std::string> &ArgsForGCC,
+ const std::vector<std::string> &ArgsForCC,
std::string &Error);
};
@@ -88,9 +88,9 @@ class AbstractInterpreter {
virtual void anchor();
public:
static LLC *createLLC(const char *Argv0, std::string &Message,
- const std::string &GCCBinary,
+ const std::string &CCBinary,
const std::vector<std::string> *Args = nullptr,
- const std::vector<std::string> *GCCArgs = nullptr,
+ const std::vector<std::string> *CCArgs = nullptr,
bool UseIntegratedAssembler = false);
static AbstractInterpreter*
@@ -119,15 +119,15 @@ public:
unsigned Timeout = 0, unsigned MemoryLimit = 0) {}
/// OutputCode - Compile the specified program from bitcode to code
- /// understood by the GCC driver (either C or asm). If the code generator
+ /// understood by the CC driver (either C or asm). If the code generator
/// fails, it sets Error, otherwise, this function returns the type of code
/// emitted.
- virtual GCC::FileType OutputCode(const std::string &Bitcode,
+ virtual CC::FileType OutputCode(const std::string &Bitcode,
std::string &OutFile, std::string &Error,
unsigned Timeout = 0,
unsigned MemoryLimit = 0) {
Error = "OutputCode not supported by this AbstractInterpreter!";
- return GCC::AsmFile;
+ return CC::AsmFile;
}
/// ExecuteProgram - Run the specified bitcode file, emitting output to the
@@ -140,7 +140,7 @@ public:
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error,
- const std::vector<std::string> &GCCArgs =
+ const std::vector<std::string> &CCArgs =
std::vector<std::string>(),
const std::vector<std::string> &SharedLibs =
std::vector<std::string>(),
@@ -154,18 +154,18 @@ public:
class LLC : public AbstractInterpreter {
std::string LLCPath; // The path to the LLC executable.
std::vector<std::string> ToolArgs; // Extra args to pass to LLC.
- GCC *gcc;
+ CC *cc;
bool UseIntegratedAssembler;
public:
- LLC(const std::string &llcPath, GCC *Gcc,
+ LLC(const std::string &llcPath, CC *cc,
const std::vector<std::string> *Args,
bool useIntegratedAssembler)
- : LLCPath(llcPath), gcc(Gcc),
+ : LLCPath(llcPath), cc(cc),
UseIntegratedAssembler(useIntegratedAssembler) {
ToolArgs.clear();
if (Args) ToolArgs = *Args;
}
- ~LLC() override { delete gcc; }
+ ~LLC() override { delete cc; }
/// compileProgram - Compile the specified program from bitcode to executable
/// code. This does not produce any output, it is only used when debugging
@@ -178,7 +178,7 @@ public:
const std::string &InputFile,
const std::string &OutputFile,
std::string *Error,
- const std::vector<std::string> &GCCArgs =
+ const std::vector<std::string> &CCArgs =
std::vector<std::string>(),
const std::vector<std::string> &SharedLibs =
std::vector<std::string>(),
@@ -186,10 +186,10 @@ public:
unsigned MemoryLimit = 0) override;
/// OutputCode - Compile the specified program from bitcode to code
- /// understood by the GCC driver (either C or asm). If the code generator
+ /// understood by the CC driver (either C or asm). If the code generator
/// fails, it sets Error, otherwise, this function returns the type of code
/// emitted.
- GCC::FileType OutputCode(const std::string &Bitcode,
+ CC::FileType OutputCode(const std::string &Bitcode,
std::string &OutFile, std::string &Error,
unsigned Timeout = 0,
unsigned MemoryLimit = 0) override;
diff --git a/contrib/llvm/tools/bugpoint/bugpoint.cpp b/contrib/llvm/tools/bugpoint/bugpoint.cpp
index af6d9fc..48f30e6 100644
--- a/contrib/llvm/tools/bugpoint/bugpoint.cpp
+++ b/contrib/llvm/tools/bugpoint/bugpoint.cpp
@@ -126,7 +126,6 @@ int main(int argc, char **argv) {
initializeVectorization(Registry);
initializeIPO(Registry);
initializeAnalysis(Registry);
- initializeIPA(Registry);
initializeTransformUtils(Registry);
initializeInstCombine(Registry);
initializeInstrumentation(Registry);
@@ -181,19 +180,12 @@ int main(int argc, char **argv) {
Builder.Inliner = createFunctionInliningPass(225);
else
Builder.Inliner = createFunctionInliningPass(275);
-
- // Note that although clang/llvm-gcc use two separate passmanagers
- // here, it shouldn't normally make a difference.
Builder.populateFunctionPassManager(PM);
Builder.populateModulePassManager(PM);
}
- for (std::vector<const PassInfo*>::iterator I = PassList.begin(),
- E = PassList.end();
- I != E; ++I) {
- const PassInfo* PI = *I;
+ for (const PassInfo *PI : PassList)
D.addPass(PI->getPassArgument());
- }
// Bugpoint has the ability of generating a plethora of core files, so to
// avoid filling up the disk, we prevent it
diff --git a/contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h b/contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h
index 068a677..9359abf 100644
--- a/contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h
+++ b/contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h
@@ -126,6 +126,12 @@ CINDEX_LINKAGE CXString
clang_CompileCommand_getDirectory(CXCompileCommand);
/**
+ * \brief Get the filename associated with the CompileCommand.
+ */
+CINDEX_LINKAGE CXString
+clang_CompileCommand_getFilename(CXCompileCommand);
+
+/**
* \brief Get the number of arguments in the compiler invocation.
*
*/
diff --git a/contrib/llvm/tools/clang/include/clang-c/CXString.h b/contrib/llvm/tools/clang/include/clang-c/CXString.h
index a649cdf..68ab7bc 100644
--- a/contrib/llvm/tools/clang/include/clang-c/CXString.h
+++ b/contrib/llvm/tools/clang/include/clang-c/CXString.h
@@ -40,6 +40,11 @@ typedef struct {
unsigned private_flags;
} CXString;
+typedef struct {
+ CXString *Strings;
+ unsigned Count;
+} CXStringSet;
+
/**
* \brief Retrieve the character data associated with the given string.
*/
@@ -51,6 +56,11 @@ CINDEX_LINKAGE const char *clang_getCString(CXString string);
CINDEX_LINKAGE void clang_disposeString(CXString string);
/**
+ * \brief Free the given string set.
+ */
+CINDEX_LINKAGE void clang_disposeStringSet(CXStringSet *set);
+
+/**
* @}
*/
diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h
index fad9cfa..09e2160 100644
--- a/contrib/llvm/tools/clang/include/clang-c/Index.h
+++ b/contrib/llvm/tools/clang/include/clang-c/Index.h
@@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 30
+#define CINDEX_VERSION_MINOR 32
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@@ -285,7 +285,6 @@ CINDEX_LINKAGE unsigned clang_CXIndex_getGlobalOptions(CXIndex);
*/
typedef void *CXFile;
-
/**
* \brief Retrieve the complete file and path name of the given file.
*/
@@ -705,7 +704,6 @@ CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
CINDEX_LINKAGE CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
unsigned Index);
-
/**
* \brief Describes the kind of error that occurred (if any) in a call to
* \c clang_loadDiagnostics.
@@ -1202,7 +1200,15 @@ enum CXTranslationUnit_Flags {
* included into the set of code completions returned from this translation
* unit.
*/
- CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 0x80
+ CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 0x80,
+
+ /**
+ * \brief Used to indicate that the precompiled preamble should be created on
+ * the first parse. Otherwise it will be created on the first reparse. This
+ * trades runtime on the first parse (serializing the preamble takes time) for
+ * reduced runtime on the second parse (can now reuse the preamble).
+ */
+ CXTranslationUnit_CreatePreambleOnFirstParse = 0x100
};
/**
@@ -1289,6 +1295,17 @@ clang_parseTranslationUnit2(CXIndex CIdx,
CXTranslationUnit *out_TU);
/**
+ * \brief Same as clang_parseTranslationUnit2 but requires a full command line
+ * for \c command_line_args including argv[0]. This is useful if the standard
+ * library paths are relative to the binary.
+ */
+CINDEX_LINKAGE enum CXErrorCode clang_parseTranslationUnit2FullArgv(
+ CXIndex CIdx, const char *source_filename,
+ const char *const *command_line_args, int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
+ unsigned options, CXTranslationUnit *out_TU);
+
+/**
* \brief Flags that control how translation units are saved.
*
* The enumerators in this enumeration type are meant to be bitwise
@@ -1573,7 +1590,7 @@ enum CXCursorKind {
CXCursor_ObjCImplementationDecl = 18,
/** \brief An Objective-C \@implementation for a category. */
CXCursor_ObjCCategoryImplDecl = 19,
- /** \brief A typedef */
+ /** \brief A typedef. */
CXCursor_TypedefDecl = 20,
/** \brief A C++ class method. */
CXCursor_CXXMethod = 21,
@@ -1982,7 +1999,11 @@ enum CXCursorKind {
*/
CXCursor_ObjCSelfExpr = 146,
- CXCursor_LastExpr = CXCursor_ObjCSelfExpr,
+ /** \brief OpenMP 4.0 [2.4, Array Section].
+ */
+ CXCursor_OMPArraySectionExpr = 147,
+
+ CXCursor_LastExpr = CXCursor_OMPArraySectionExpr,
/* Statements */
CXCursor_FirstStmt = 200,
@@ -2227,17 +2248,33 @@ enum CXCursorKind {
/** \brief OpenMP taskgroup directive.
*/
- CXCursor_OMPTaskgroupDirective = 254,
+ CXCursor_OMPTaskgroupDirective = 254,
/** \brief OpenMP cancellation point directive.
*/
- CXCursor_OMPCancellationPointDirective = 255,
+ CXCursor_OMPCancellationPointDirective = 255,
/** \brief OpenMP cancel directive.
*/
- CXCursor_OMPCancelDirective = 256,
+ CXCursor_OMPCancelDirective = 256,
- CXCursor_LastStmt = CXCursor_OMPCancelDirective,
+ /** \brief OpenMP target data directive.
+ */
+ CXCursor_OMPTargetDataDirective = 257,
+
+ /** \brief OpenMP taskloop directive.
+ */
+ CXCursor_OMPTaskLoopDirective = 258,
+
+ /** \brief OpenMP taskloop simd directive.
+ */
+ CXCursor_OMPTaskLoopSimdDirective = 259,
+
+ /** \brief OpenMP distribute directive.
+ */
+ CXCursor_OMPDistributeDirective = 260,
+
+ CXCursor_LastStmt = CXCursor_OMPDistributeDirective,
/**
* \brief Cursor that represents the translation unit itself.
@@ -2271,7 +2308,10 @@ enum CXCursorKind {
CXCursor_CUDAGlobalAttr = 414,
CXCursor_CUDAHostAttr = 415,
CXCursor_CUDASharedAttr = 416,
- CXCursor_LastAttr = CXCursor_CUDASharedAttr,
+ CXCursor_VisibilityAttr = 417,
+ CXCursor_DLLExport = 418,
+ CXCursor_DLLImport = 419,
+ CXCursor_LastAttr = CXCursor_DLLImport,
/* Preprocessing */
CXCursor_PreprocessingDirective = 500,
@@ -2287,8 +2327,9 @@ enum CXCursorKind {
* \brief A module import declaration.
*/
CXCursor_ModuleImportDecl = 600,
+ CXCursor_TypeAliasTemplateDecl = 601,
CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl,
- CXCursor_LastExtraDecl = CXCursor_ModuleImportDecl,
+ CXCursor_LastExtraDecl = CXCursor_TypeAliasTemplateDecl,
/**
* \brief A code completion overload candidate.
@@ -2439,6 +2480,32 @@ enum CXLinkageKind {
*/
CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
+enum CXVisibilityKind {
+ /** \brief This value indicates that no visibility information is available
+ * for a provided CXCursor. */
+ CXVisibility_Invalid,
+
+ /** \brief Symbol not seen by the linker. */
+ CXVisibility_Hidden,
+ /** \brief Symbol seen by the linker but resolves to a symbol inside this object. */
+ CXVisibility_Protected,
+ /** \brief Symbol seen by the linker and acts like a normal symbol. */
+ CXVisibility_Default
+};
+
+/**
+ * \brief Describe the visibility of the entity referred to by a cursor.
+ *
+ * This returns the default visibility if not explicitly specified by
+ * a visibility attribute. The default visibility may be changed by
+ * commandline arguments.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \returns The visibility of the cursor.
+ */
+CINDEX_LINKAGE enum CXVisibilityKind clang_getCursorVisibility(CXCursor cursor);
+
/**
* \brief Determine the availability of the entity that this cursor refers to,
* taking the current target platform into account.
@@ -2558,7 +2625,6 @@ CINDEX_LINKAGE enum CXLanguageKind clang_getCursorLanguage(CXCursor cursor);
*/
CINDEX_LINKAGE CXTranslationUnit clang_Cursor_getTranslationUnit(CXCursor);
-
/**
* \brief A fast container representing a set of CXCursors.
*/
@@ -2851,7 +2917,8 @@ enum CXTypeKind {
CXType_IncompleteArray = 114,
CXType_VariableArray = 115,
CXType_DependentSizedArray = 116,
- CXType_MemberPointer = 117
+ CXType_MemberPointer = 117,
+ CXType_Auto = 118
};
/**
@@ -2876,7 +2943,6 @@ enum CXCallingConv {
CXCallingConv_Unexposed = 200
};
-
/**
* \brief The type of an element in the abstract syntax tree.
*
@@ -3314,7 +3380,6 @@ CINDEX_LINKAGE long long clang_Cursor_getOffsetOfField(CXCursor C);
*/
CINDEX_LINKAGE unsigned clang_Cursor_isAnonymous(CXCursor C);
-
enum CXRefQualifierKind {
/** \brief No ref-qualifier was provided. */
CXRefQualifier_None = 0,
@@ -3443,7 +3508,6 @@ CINDEX_LINKAGE CXCursor clang_getOverloadedDecl(CXCursor cursor,
* @{
*/
-
/**
* \brief For cursors representing an iboutletcollection attribute,
* this function returns the collection element type.
@@ -3597,7 +3661,6 @@ CINDEX_LINKAGE CXString
CINDEX_LINKAGE CXString
clang_constructUSR_ObjCProtocol(const char *protocol_name);
-
/**
* \brief Construct a USR for a specified Objective-C instance variable and
* the USR for its containing class.
@@ -3723,7 +3786,6 @@ CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
*/
CINDEX_LINKAGE CXCursor clang_getCanonicalCursor(CXCursor);
-
/**
* \brief If the cursor points to a selector identifier in an Objective-C
* method or message expression, this returns the selector index.
@@ -3854,6 +3916,12 @@ CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C);
CINDEX_LINKAGE CXString clang_Cursor_getMangling(CXCursor);
/**
+ * \brief Retrieve the CXStrings representing the mangled symbols of the C++
+ * constructor or destructor at the cursor.
+ */
+CINDEX_LINKAGE CXStringSet *clang_Cursor_getCXXManglings(CXCursor);
+
+/**
* @}
*/
@@ -3948,6 +4016,11 @@ CXFile clang_Module_getTopLevelHeader(CXTranslationUnit,
*/
/**
+ * \brief Determine if a C++ field is declared 'mutable'.
+ */
+CINDEX_LINKAGE unsigned clang_CXXField_isMutable(CXCursor C);
+
+/**
* \brief Determine if a C++ member function or member function template is
* pure virtual.
*/
@@ -4939,8 +5012,7 @@ enum CXCursorKind clang_codeCompleteGetContainerKind(
*/
CINDEX_LINKAGE
CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *Results);
-
-
+
/**
* \brief Returns the currently-entered selector for an Objective-C message
* send, formatted like "initWithFoo:bar:". Only guaranteed to return a
@@ -4959,7 +5031,6 @@ CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *Results);
* @}
*/
-
/**
* \defgroup CINDEX_MISC Miscellaneous utility functions
*
@@ -4972,7 +5043,6 @@ CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *Results);
*/
CINDEX_LINKAGE CXString clang_getClangVersion(void);
-
/**
* \brief Enable/disable crash recovery.
*
@@ -5659,6 +5729,18 @@ CINDEX_LINKAGE int clang_indexSourceFile(CXIndexAction,
unsigned TU_options);
/**
+ * \brief Same as clang_indexSourceFile but requires a full command line
+ * for \c command_line_args including argv[0]. This is useful if the standard
+ * library paths are relative to the binary.
+ */
+CINDEX_LINKAGE int clang_indexSourceFileFullArgv(
+ CXIndexAction, CXClientData client_data, IndexerCallbacks *index_callbacks,
+ unsigned index_callbacks_size, unsigned index_options,
+ const char *source_filename, const char *const *command_line_args,
+ int num_command_line_args, struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files, CXTranslationUnit *out_TU, unsigned TU_options);
+
+/**
* \brief Index the given translation unit via callbacks implemented through
* #IndexerCallbacks.
*
@@ -5739,7 +5821,6 @@ CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T,
CXFieldVisitor visitor,
CXClientData client_data);
-
/**
* @}
*/
@@ -5752,4 +5833,3 @@ CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T,
}
#endif
#endif
-
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
index a2bd55a..abf9294 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
@@ -28,6 +28,7 @@
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SanitizerBlacklist.h"
@@ -70,6 +71,7 @@ namespace clang {
class VTableContextBase;
namespace Builtin { class Context; }
+ enum BuiltinTemplateKind : int;
namespace comments {
class FullComment;
@@ -129,6 +131,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<AutoType> AutoTypes;
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
llvm::FoldingSet<AttributedType> AttributedTypes;
+ mutable llvm::FoldingSet<PipeType> PipeTypes;
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
@@ -176,8 +179,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
ClassScopeSpecializationPattern;
/// \brief Mapping from materialized temporaries with static storage duration
- /// that appear in constant initializers to their evaluated values.
- llvm::DenseMap<const MaterializeTemporaryExpr*, APValue>
+ /// that appear in constant initializers to their evaluated values. These are
+ /// allocated in a std::map because their address must be stable.
+ llvm::DenseMap<const MaterializeTemporaryExpr *, APValue *>
MaterializedTemporaryValues;
/// \brief Representation of a "canonical" template template parameter that
@@ -215,6 +219,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// __builtin_va_list type.
mutable TypedefDecl *BuiltinVaListDecl;
+ /// The typedef for the predefined \c __builtin_ms_va_list type.
+ mutable TypedefDecl *BuiltinMSVaListDecl;
+
/// \brief The typedef for the predefined \c id type.
mutable TypedefDecl *ObjCIdDecl;
@@ -242,6 +249,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// The identifier 'NSCopying'.
IdentifierInfo *NSCopyingName = nullptr;
+ /// The identifier '__make_integer_seq'.
+ mutable IdentifierInfo *MakeIntegerSeqName = nullptr;
+
QualType ObjCConstantStringType;
mutable RecordDecl *CFConstantStringTypeDecl;
@@ -395,6 +405,7 @@ private:
TranslationUnitDecl *TUDecl;
mutable ExternCContextDecl *ExternCContext;
+ mutable BuiltinTemplateDecl *MakeIntegerSeqDecl;
/// \brief The associated SourceManager object.a
SourceManager &SourceMgr;
@@ -433,6 +444,7 @@ private:
friend class CXXRecordDecl;
const TargetInfo *Target;
+ const TargetInfo *AuxTarget;
clang::PrintingPolicy PrintingPolicy;
public:
@@ -446,10 +458,59 @@ public:
/// \brief Contains parents of a node.
typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 2> ParentVector;
- /// \brief Maps from a node to its parents.
+ /// \brief Maps from a node to its parents. This is used for nodes that have
+ /// pointer identity only, which are more common and we can save space by
+ /// only storing a unique pointer to them.
typedef llvm::DenseMap<const void *,
- llvm::PointerUnion<ast_type_traits::DynTypedNode *,
- ParentVector *>> ParentMap;
+ llvm::PointerUnion4<const Decl *, const Stmt *,
+ ast_type_traits::DynTypedNode *,
+ ParentVector *>> ParentMapPointers;
+
+ /// Parent map for nodes without pointer identity. We store a full
+ /// DynTypedNode for all keys.
+ typedef llvm::DenseMap<
+ ast_type_traits::DynTypedNode,
+ llvm::PointerUnion4<const Decl *, const Stmt *,
+ ast_type_traits::DynTypedNode *, ParentVector *>>
+ ParentMapOtherNodes;
+
+ /// Container for either a single DynTypedNode or for an ArrayRef to
+ /// DynTypedNode. For use with ParentMap.
+ class DynTypedNodeList {
+ typedef ast_type_traits::DynTypedNode DynTypedNode;
+ llvm::AlignedCharArrayUnion<ast_type_traits::DynTypedNode,
+ ArrayRef<DynTypedNode>> Storage;
+ bool IsSingleNode;
+
+ public:
+ DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
+ new (Storage.buffer) DynTypedNode(N);
+ }
+ DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
+ new (Storage.buffer) ArrayRef<DynTypedNode>(A);
+ }
+
+ const ast_type_traits::DynTypedNode *begin() const {
+ if (!IsSingleNode)
+ return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
+ ->begin();
+ return reinterpret_cast<const DynTypedNode *>(Storage.buffer);
+ }
+
+ const ast_type_traits::DynTypedNode *end() const {
+ if (!IsSingleNode)
+ return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
+ ->end();
+ return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1;
+ }
+
+ size_t size() const { return end() - begin(); }
+ bool empty() const { return begin() == end(); }
+ const DynTypedNode &operator[](size_t N) const {
+ assert(N < size() && "Out of bounds!");
+ return *(begin() + N);
+ }
+ };
/// \brief Returns the parents of the given node.
///
@@ -475,13 +536,11 @@ public:
///
/// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
/// NestedNameSpecifier or NestedNameSpecifierLoc.
- template <typename NodeT>
- ArrayRef<ast_type_traits::DynTypedNode> getParents(const NodeT &Node) {
+ template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node) {
return getParents(ast_type_traits::DynTypedNode::create(Node));
}
- ArrayRef<ast_type_traits::DynTypedNode>
- getParents(const ast_type_traits::DynTypedNode &Node);
+ DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node);
const clang::PrintingPolicy &getPrintingPolicy() const {
return PrintingPolicy;
@@ -501,6 +560,9 @@ public:
void *Allocate(size_t Size, unsigned Align = 8) const {
return BumpAlloc.Allocate(Size, Align);
}
+ template <typename T> T *Allocate(size_t Num = 1) const {
+ return static_cast<T *>(Allocate(Num * sizeof(T), llvm::alignOf<T>()));
+ }
void Deallocate(void *Ptr) const { }
/// Return the total amount of physical memory allocated for representing
@@ -516,7 +578,8 @@ public:
}
const TargetInfo &getTargetInfo() const { return *Target; }
-
+ const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
+
/// getIntTypeForBitwidth -
/// sets integer QualTy according to specified details:
/// bitwidth, signed/unsigned.
@@ -812,6 +875,7 @@ public:
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
ExternCContextDecl *getExternCContextDecl() const;
+ BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;
// Builtin Types.
CanQualType VoidTy;
@@ -835,17 +899,21 @@ public:
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
CanQualType ObjCBuiltinBoolTy;
CanQualType OCLImage1dTy, OCLImage1dArrayTy, OCLImage1dBufferTy;
- CanQualType OCLImage2dTy, OCLImage2dArrayTy;
+ CanQualType OCLImage2dTy, OCLImage2dArrayTy, OCLImage2dDepthTy;
+ CanQualType OCLImage2dArrayDepthTy, OCLImage2dMSAATy, OCLImage2dArrayMSAATy;
+ CanQualType OCLImage2dMSAADepthTy, OCLImage2dArrayMSAADepthTy;
CanQualType OCLImage3dTy;
- CanQualType OCLSamplerTy, OCLEventTy;
+ CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
+ CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy;
+ CanQualType OMPArraySectionTy;
// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
mutable QualType AutoDeductTy; // Deduction against 'auto'.
mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'.
- // Type used to help define __builtin_va_list for some targets.
- // The type is built when constructing 'BuiltinVaListDecl'.
- mutable QualType VaListTagTy;
+ // Decl used to help define __builtin_va_list for some targets.
+ // The decl is built when constructing 'BuiltinVaListDecl'.
+ mutable Decl *VaListTagDecl;
ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
SelectorTable &sels, Builtin::Context &builtins);
@@ -881,6 +949,9 @@ public:
void PrintStats() const;
const SmallVectorImpl<Type *>& getTypes() const { return Types; }
+ BuiltinTemplateDecl *buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
+ const IdentifierInfo *II) const;
+
/// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl
/// declaration.
RecordDecl *buildImplicitRecord(StringRef Name,
@@ -955,6 +1026,9 @@ public:
const FunctionType *adjustFunctionType(const FunctionType *Fn,
FunctionType::ExtInfo EInfo);
+ /// Adjust the given function result type.
+ CanQualType getCanonicalFunctionResultType(QualType ResultType) const;
+
/// \brief Change the result type of a function type once it is deduced.
void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);
@@ -1006,6 +1080,9 @@ public:
/// blocks.
QualType getBlockDescriptorType() const;
+ /// \brief Return pipe type for the specified type.
+ QualType getPipeType(QualType T) const;
+
/// Gets the struct used to keep track of the extended descriptor for
/// pointer to blocks.
QualType getBlockDescriptorExtendedType() const;
@@ -1227,7 +1304,7 @@ public:
UnaryTransformType::UTTKind UKind) const;
/// \brief C++11 deduced auto type.
- QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto,
+ QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
bool IsDependent) const;
/// \brief C++11 deduction pattern for 'auto' type.
@@ -1381,6 +1458,12 @@ public:
return NSCopyingName;
}
+ IdentifierInfo *getMakeIntegerSeqName() const {
+ if (!MakeIntegerSeqName)
+ MakeIntegerSeqName = &Idents.get("__make_integer_seq");
+ return MakeIntegerSeqName;
+ }
+
/// \brief Retrieve the Objective-C "instancetype" type, if already known;
/// otherwise, returns a NULL type;
QualType getObjCInstanceType() {
@@ -1569,7 +1652,16 @@ public:
/// \brief Retrieve the C type declaration corresponding to the predefined
/// \c __va_list_tag type used to help define the \c __builtin_va_list type
/// for some targets.
- QualType getVaListTagType() const;
+ Decl *getVaListTagDecl() const;
+
+ /// Retrieve the C type declaration corresponding to the predefined
+ /// \c __builtin_ms_va_list type.
+ TypedefDecl *getBuiltinMSVaListDecl() const;
+
+ /// Retrieve the type of the \c __builtin_ms_va_list type.
+ QualType getBuiltinMSVaListType() const {
+ return getTypeDeclType(getBuiltinMSVaListDecl());
+ }
/// \brief Return a type with additional \c const, \c volatile, or
/// \c restrict qualifiers.
@@ -1774,7 +1866,6 @@ public:
/// record (struct/union/class) \p D, which indicates its size and field
/// position information.
const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;
- const ASTRecordLayout *BuildMicrosoftASTRecordLayout(const RecordDecl *D) const;
/// \brief Get or compute information about the layout of the specified
/// Objective-C interface.
@@ -2170,9 +2261,7 @@ public:
const FunctionProtoType *FromFunctionType,
const FunctionProtoType *ToFunctionType);
- void ResetObjCLayout(const ObjCContainerDecl *CD) {
- ObjCLayouts[CD] = nullptr;
- }
+ void ResetObjCLayout(const ObjCContainerDecl *CD);
//===--------------------------------------------------------------------===//
// Integer Predicates
@@ -2188,25 +2277,19 @@ public:
QualType getCorrespondingUnsignedType(QualType T) const;
//===--------------------------------------------------------------------===//
- // Type Iterators.
- //===--------------------------------------------------------------------===//
- typedef llvm::iterator_range<SmallVectorImpl<Type *>::const_iterator>
- type_const_range;
-
- type_const_range types() const {
- return type_const_range(Types.begin(), Types.end());
- }
-
- //===--------------------------------------------------------------------===//
// Integer Values
//===--------------------------------------------------------------------===//
/// \brief Make an APSInt of the appropriate width and signedness for the
/// given \p Value and integer \p Type.
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const {
- llvm::APSInt Res(getIntWidth(Type),
- !Type->isSignedIntegerOrEnumerationType());
+ // If Type is a signed integer type larger than 64 bits, we need to be sure
+ // to sign extend Res appropriately.
+ llvm::APSInt Res(64, !Type->isSignedIntegerOrEnumerationType());
Res = Value;
+ unsigned Width = getIntWidth(Type);
+ if (Width != Res.getBitWidth())
+ return Res.extOrTrunc(Width);
return Res;
}
@@ -2233,16 +2316,11 @@ public:
/// \brief Get the duplicate declaration of a ObjCMethod in the same
/// interface, or null if none exists.
- const ObjCMethodDecl *getObjCMethodRedeclaration(
- const ObjCMethodDecl *MD) const {
- return ObjCMethodRedecls.lookup(MD);
- }
+ const ObjCMethodDecl *
+ getObjCMethodRedeclaration(const ObjCMethodDecl *MD) const;
void setObjCMethodRedeclaration(const ObjCMethodDecl *MD,
- const ObjCMethodDecl *Redecl) {
- assert(!getObjCMethodRedeclaration(MD) && "MD already has a redeclaration");
- ObjCMethodRedecls[MD] = Redecl;
- }
+ const ObjCMethodDecl *Redecl);
/// \brief Returns the Objective-C interface that \p ND belongs to if it is
/// an Objective-C method/property/ivar etc. that is part of an interface,
@@ -2307,6 +2385,14 @@ public:
Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
unsigned ParmIdx);
+ void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *TND);
+
+ TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD);
+
+ void addDeclaratorForUnnamedTagDecl(TagDecl *TD, DeclaratorDecl *DD);
+
+ DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD);
+
void setManglingNumber(const NamedDecl *ND, unsigned Number);
unsigned getManglingNumber(const NamedDecl *ND) const;
@@ -2388,9 +2474,10 @@ public:
/// This routine may only be invoked once for a given ASTContext object.
/// It is normally invoked after ASTContext construction.
///
- /// \param Target The target
- void InitBuiltinTypes(const TargetInfo &Target);
-
+ /// \param Target The target
+ void InitBuiltinTypes(const TargetInfo &Target,
+ const TargetInfo *AuxTarget = nullptr);
+
private:
void InitBuiltinType(CanQualType &R, BuiltinType::Kind K);
@@ -2429,9 +2516,15 @@ private:
/// \brief A set of deallocations that should be performed when the
/// ASTContext is destroyed.
- typedef llvm::SmallDenseMap<void(*)(void*), llvm::SmallVector<void*, 16> >
- DeallocationMap;
- DeallocationMap Deallocations;
+ // FIXME: We really should have a better mechanism in the ASTContext to
+ // manage running destructors for types which do variable sized allocation
+ // within the AST. In some places we thread the AST bump pointer allocator
+ // into the datastructures which avoids this mess during deallocation but is
+ // wasteful of memory, and here we require a lot of error prone book keeping
+ // in order to track and run destructors while we're tearing things down.
+ typedef llvm::SmallVector<std::pair<void (*)(void *), void *>, 16>
+ DeallocationFunctionsAndArguments;
+ DeallocationFunctionsAndArguments Deallocations;
// FIXME: This currently contains the set of StoredDeclMaps used
// by DeclContext objects. This probably should not be in ASTContext,
@@ -2443,7 +2536,8 @@ private:
void ReleaseDeclContextMaps();
void ReleaseParentMapEntries();
- std::unique_ptr<ParentMap> AllParents;
+ std::unique_ptr<ParentMapPointers> PointerParents;
+ std::unique_ptr<ParentMapOtherNodes> OtherParents;
std::unique_ptr<VTableContextBase> VTContext;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
index f4026e9..cf3b55d 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
@@ -29,6 +29,7 @@ namespace clang {
class ObjCContainerDecl;
class ObjCInterfaceDecl;
class ObjCPropertyDecl;
+ class ParmVarDecl;
class QualType;
class RecordDecl;
class TagDecl;
@@ -88,22 +89,13 @@ public:
/// \brief A function template's definition was instantiated.
virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {}
+ /// \brief A default argument was instantiated.
+ virtual void DefaultArgumentInstantiated(const ParmVarDecl *D) {}
+
/// \brief A new objc category class was added for an interface.
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {}
- /// \brief A objc class extension redeclared or introduced a property.
- ///
- /// \param Prop the property in the class extension
- ///
- /// \param OrigProp the property from the original interface that was declared
- /// or null if the property was introduced.
- ///
- /// \param ClassExt the class extension.
- virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
- const ObjCPropertyDecl *OrigProp,
- const ObjCCategoryDecl *ClassExt) {}
-
/// \brief A declaration is marked used which was not previously marked used.
///
/// \param D the declaration marked used
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h b/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h
index dc3c34f..dcaac80 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h
@@ -106,18 +106,25 @@ public:
}
};
+ /// Check if the given ASTNodeKind identifies a type that offers pointer
+ /// identity. This is useful for the fast path in DynTypedNode.
+ bool hasPointerIdentity() const {
+ return KindId > NKI_LastKindWithoutPointerIdentity;
+ }
+
private:
/// \brief Kind ids.
///
/// Includes all possible base and derived kinds.
enum NodeKindId {
NKI_None,
- NKI_CXXCtorInitializer,
NKI_TemplateArgument,
- NKI_NestedNameSpecifier,
NKI_NestedNameSpecifierLoc,
NKI_QualType,
NKI_TypeLoc,
+ NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
+ NKI_CXXCtorInitializer,
+ NKI_NestedNameSpecifier,
NKI_Decl,
#define DECL(DERIVED, BASE) NKI_##DERIVED##Decl,
#include "clang/AST/DeclNodes.inc"
@@ -238,7 +245,11 @@ public:
/// Note that this is not supported by all AST nodes. For AST nodes
/// that don't have a pointer-defined identity inside the AST, this
/// method returns NULL.
- const void *getMemoizationData() const { return MemoizationData; }
+ const void *getMemoizationData() const {
+ return NodeKind.hasPointerIdentity()
+ ? *reinterpret_cast<void *const *>(Storage.buffer)
+ : nullptr;
+ }
/// \brief Prints the node to the given output stream.
void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
@@ -257,6 +268,32 @@ public:
/// FIXME: Implement comparsion for other node types (currently
/// only Stmt, Decl, Type and NestedNameSpecifier return memoization data).
bool operator<(const DynTypedNode &Other) const {
+ if (!NodeKind.isSame(Other.NodeKind))
+ return NodeKind < Other.NodeKind;
+
+ if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
+ return getUnchecked<QualType>().getAsOpaquePtr() <
+ Other.getUnchecked<QualType>().getAsOpaquePtr();
+
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) {
+ auto TLA = getUnchecked<TypeLoc>();
+ auto TLB = Other.getUnchecked<TypeLoc>();
+ return std::make_pair(TLA.getType().getAsOpaquePtr(),
+ TLA.getOpaqueData()) <
+ std::make_pair(TLB.getType().getAsOpaquePtr(),
+ TLB.getOpaqueData());
+ }
+
+ if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
+ NodeKind)) {
+ auto NNSLA = getUnchecked<NestedNameSpecifierLoc>();
+ auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>();
+ return std::make_pair(NNSLA.getNestedNameSpecifier(),
+ NNSLA.getOpaqueData()) <
+ std::make_pair(NNSLB.getNestedNameSpecifier(),
+ NNSLB.getOpaqueData());
+ }
+
assert(getMemoizationData() && Other.getMemoizationData());
return getMemoizationData() < Other.getMemoizationData();
}
@@ -270,6 +307,13 @@ public:
if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
return getUnchecked<QualType>() == Other.getUnchecked<QualType>();
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind))
+ return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>();
+
+ if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind))
+ return getUnchecked<NestedNameSpecifierLoc>() ==
+ Other.getUnchecked<NestedNameSpecifierLoc>();
+
assert(getMemoizationData() && Other.getMemoizationData());
return getMemoizationData() == Other.getMemoizationData();
}
@@ -278,6 +322,47 @@ public:
}
/// @}
+ /// \brief Hooks for using DynTypedNode as a key in a DenseMap.
+ struct DenseMapInfo {
+ static inline DynTypedNode getEmptyKey() {
+ DynTypedNode Node;
+ Node.NodeKind = ASTNodeKind::DenseMapInfo::getEmptyKey();
+ return Node;
+ }
+ static inline DynTypedNode getTombstoneKey() {
+ DynTypedNode Node;
+ Node.NodeKind = ASTNodeKind::DenseMapInfo::getTombstoneKey();
+ return Node;
+ }
+ static unsigned getHashValue(const DynTypedNode &Val) {
+ // FIXME: Add hashing support for the remaining types.
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(Val.NodeKind)) {
+ auto TL = Val.getUnchecked<TypeLoc>();
+ return llvm::hash_combine(TL.getType().getAsOpaquePtr(),
+ TL.getOpaqueData());
+ }
+
+ if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
+ Val.NodeKind)) {
+ auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>();
+ return llvm::hash_combine(NNSL.getNestedNameSpecifier(),
+ NNSL.getOpaqueData());
+ }
+
+ assert(Val.getMemoizationData());
+ return llvm::hash_value(Val.getMemoizationData());
+ }
+ static bool isEqual(const DynTypedNode &LHS, const DynTypedNode &RHS) {
+ auto Empty = ASTNodeKind::DenseMapInfo::getEmptyKey();
+ auto TombStone = ASTNodeKind::DenseMapInfo::getTombstoneKey();
+ return (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, Empty) &&
+ ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, Empty)) ||
+ (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, TombStone) &&
+ ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, TombStone)) ||
+ LHS == RHS;
+ }
+ };
+
private:
/// \brief Takes care of converting from and to \c T.
template <typename T, typename EnablerT = void> struct BaseConverter;
@@ -286,18 +371,18 @@ private:
template <typename T, typename BaseT> struct DynCastPtrConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
- return cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
+ return &getUnchecked(NodeKind, Storage);
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
- return *cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
+ return *cast<T>(static_cast<const BaseT *>(
+ *reinterpret_cast<const void *const *>(Storage)));
}
static DynTypedNode create(const BaseT &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNode(Node);
- Result.MemoizationData = &Node;
- new (Result.Storage.buffer) const BaseT * (&Node);
+ new (Result.Storage.buffer) const void *(&Node);
return Result;
}
};
@@ -306,18 +391,18 @@ private:
template <typename T> struct PtrConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
- return *reinterpret_cast<T *const *>(Storage);
+ return &getUnchecked(NodeKind, Storage);
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
- return **reinterpret_cast<T *const *>(Storage);
+ return *static_cast<const T *>(
+ *reinterpret_cast<const void *const *>(Storage));
}
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
- Result.MemoizationData = &Node;
- new (Result.Storage.buffer) const T * (&Node);
+ new (Result.Storage.buffer) const void *(&Node);
return Result;
}
};
@@ -336,14 +421,12 @@ private:
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
- Result.MemoizationData = nullptr;
new (Result.Storage.buffer) T(Node);
return Result;
}
};
ASTNodeKind NodeKind;
- const void *MemoizationData;
/// \brief Stores the data of the node.
///
@@ -353,12 +436,9 @@ private:
/// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and
/// \c TemplateArguments on the other hand do not have storage or unique
/// pointers and thus need to be stored by value.
- typedef llvm::AlignedCharArrayUnion<
- Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *>
- KindsByPointer;
- llvm::AlignedCharArrayUnion<KindsByPointer, TemplateArgument,
- NestedNameSpecifierLoc, QualType, TypeLoc>
- Storage;
+ llvm::AlignedCharArrayUnion<const void *, TemplateArgument,
+ NestedNameSpecifierLoc, QualType,
+ TypeLoc> Storage;
};
template <typename T>
@@ -420,6 +500,10 @@ template <>
struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind>
: clang::ast_type_traits::ASTNodeKind::DenseMapInfo {};
+template <>
+struct DenseMapInfo<clang::ast_type_traits::DynTypedNode>
+ : clang::ast_type_traits::DynTypedNode::DenseMapInfo {};
+
} // end namespace llvm
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Attr.h b/contrib/llvm/tools/clang/include/clang/AST/Attr.h
index 4e282d6..8b80e9f 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Attr.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Attr.h
@@ -56,21 +56,21 @@ protected:
bool IsLateParsed : 1;
bool DuplicatesAllowed : 1;
- void* operator new(size_t bytes) throw() {
+ void *operator new(size_t bytes) LLVM_NOEXCEPT {
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
}
- void operator delete(void* data) throw() {
+ void operator delete(void *data) LLVM_NOEXCEPT {
llvm_unreachable("Attrs cannot be released with regular 'delete'.");
}
public:
// Forward so that the regular new and delete do not hide global ones.
- void* operator new(size_t Bytes, ASTContext &C,
- size_t Alignment = 8) throw() {
+ void *operator new(size_t Bytes, ASTContext &C,
+ size_t Alignment = 8) LLVM_NOEXCEPT {
return ::operator new(Bytes, C, Alignment);
}
void operator delete(void *Ptr, ASTContext &C,
- size_t Alignment) throw() {
+ size_t Alignment) LLVM_NOEXCEPT {
return ::operator delete(Ptr, C, Alignment);
}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def b/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def
index 488cace..a08a683 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def
+++ b/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def
@@ -1,4 +1,4 @@
-//===-- BuiltinTypeNodes.def - Metadata about BuiltinTypes ------*- C++ -*-===//
+//===-- BuiltinTypes.def - Metadata about BuiltinTypes ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -160,6 +160,12 @@ BUILTIN_TYPE(OCLImage1dArray, OCLImage1dArrayTy)
BUILTIN_TYPE(OCLImage1dBuffer, OCLImage1dBufferTy)
BUILTIN_TYPE(OCLImage2d, OCLImage2dTy)
BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy)
+BUILTIN_TYPE(OCLImage2dDepth, OCLImage2dDepthTy)
+BUILTIN_TYPE(OCLImage2dArrayDepth, OCLImage2dArrayDepthTy)
+BUILTIN_TYPE(OCLImage2dMSAA, OCLImage2dMSAATy)
+BUILTIN_TYPE(OCLImage2dArrayMSAA, OCLImage2dArrayMSAATy)
+BUILTIN_TYPE(OCLImage2dMSAADepth, OCLImage2dMSAADepthTy)
+BUILTIN_TYPE(OCLImage2dArrayMSAADepth, OCLImage2dArrayMSAADepthTy)
BUILTIN_TYPE(OCLImage3d, OCLImage3dTy)
// OpenCL sampler_t.
@@ -168,6 +174,18 @@ BUILTIN_TYPE(OCLSampler, OCLSamplerTy)
// OpenCL event_t.
BUILTIN_TYPE(OCLEvent, OCLEventTy)
+// OpenCL clk_event_t.
+BUILTIN_TYPE(OCLClkEvent, OCLClkEventTy)
+
+// OpenCL queue_t.
+BUILTIN_TYPE(OCLQueue, OCLQueueTy)
+
+// OpenCL ndrange_t.
+BUILTIN_TYPE(OCLNDRange, OCLNDRangeTy)
+
+// OpenCL reserve_id_t.
+BUILTIN_TYPE(OCLReserveID, OCLReserveIDTy)
+
// This represents the type of an expression whose type is
// totally unknown, e.g. 'T::foo'. It is permitted for this to
// appear in situations where the structure of the type is
@@ -227,8 +245,11 @@ PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy)
// context.
PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy)
+// A placeholder type for OpenMP array sections.
+PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy)
+
#ifdef LAST_BUILTIN_TYPE
-LAST_BUILTIN_TYPE(ARCUnbridgedCast)
+LAST_BUILTIN_TYPE(OMPArraySection)
#undef LAST_BUILTIN_TYPE
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
index f7612f2..8587260 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
@@ -155,17 +155,16 @@ class CXXBasePaths {
/// \brief Array of the declarations that have been found. This
/// array is constructed only if needed, e.g., to iterate over the
/// results within LookupResult.
- NamedDecl **DeclsFound;
+ std::unique_ptr<NamedDecl *[]> DeclsFound;
unsigned NumDeclsFound;
friend class CXXRecordDecl;
void ComputeDeclsFound();
- bool lookupInBases(ASTContext &Context,
- const CXXRecordDecl *Record,
- CXXRecordDecl::BaseMatchesCallback *BaseMatches,
- void *UserData);
+ bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record,
+ CXXRecordDecl::BaseMatchesCallback BaseMatches);
+
public:
typedef std::list<CXXBasePath>::iterator paths_iterator;
typedef std::list<CXXBasePath>::const_iterator const_paths_iterator;
@@ -173,15 +172,12 @@ public:
/// BasePaths - Construct a new BasePaths structure to record the
/// paths for a derived-to-base search.
- explicit CXXBasePaths(bool FindAmbiguities = true,
- bool RecordPaths = true,
+ explicit CXXBasePaths(bool FindAmbiguities = true, bool RecordPaths = true,
bool DetectVirtual = true)
- : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
- DetectVirtual(DetectVirtual), DetectedVirtual(nullptr),
- DeclsFound(nullptr), NumDeclsFound(0) { }
-
- ~CXXBasePaths() { delete [] DeclsFound; }
-
+ : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
+ DetectVirtual(DetectVirtual), DetectedVirtual(nullptr),
+ NumDeclsFound(0) {}
+
paths_iterator begin() { return Paths.begin(); }
paths_iterator end() { return Paths.end(); }
const_paths_iterator begin() const { return Paths.begin(); }
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
index 72ca9f5..1d22bcc 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
@@ -130,6 +130,14 @@ namespace clang {
return (Quantity & -Quantity) == Quantity;
}
+ /// Test whether this is a multiple of the other value.
+ ///
+ /// Among other things, this promises that
+ /// self.RoundUpToAlignment(N) will just return self.
+ bool isMultipleOf(CharUnits N) const {
+ return (*this % N) == 0;
+ }
+
// Arithmetic operators.
CharUnits operator* (QuantityType N) const {
return CharUnits(Quantity * N);
@@ -172,10 +180,20 @@ namespace clang {
/// Given that this is a non-zero alignment value, what is the
/// alignment at the given offset?
- CharUnits alignmentAtOffset(CharUnits offset) {
+ CharUnits alignmentAtOffset(CharUnits offset) const {
+ assert(Quantity != 0 && "offsetting from unknown alignment?");
return CharUnits(llvm::MinAlign(Quantity, offset.Quantity));
}
+ /// Given that this is the alignment of the first element of an
+ /// array, return the minimum alignment of any element in the array.
+ CharUnits alignmentOfArrayElement(CharUnits elementSize) const {
+ // Since we don't track offsetted alignments, the alignment of
+ // the second element (or any odd element) will be minimally
+ // aligned.
+ return alignmentAtOffset(elementSize);
+ }
+
}; // class CharUnit
} // namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h b/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h
index 9b05d39..6a80383 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h
@@ -79,12 +79,8 @@ public:
/// Returns a copy of array, owned by Sema's allocator.
template<typename T>
ArrayRef<T> copyArray(ArrayRef<T> Source) {
- size_t Size = Source.size();
- if (Size != 0) {
- T *Mem = Allocator.Allocate<T>(Size);
- std::uninitialized_copy(Source.begin(), Source.end(), Mem);
- return llvm::makeArrayRef(Mem, Size);
- }
+ if (!Source.empty())
+ return Source.copy(Allocator);
return None;
}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DataRecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/DataRecursiveASTVisitor.h
deleted file mode 100644
index dd167fe..0000000
--- a/contrib/llvm/tools/clang/include/clang/AST/DataRecursiveASTVisitor.h
+++ /dev/null
@@ -1,2691 +0,0 @@
-//===--- DataRecursiveASTVisitor.h - Data-Recursive AST Visitor -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the DataRecursiveASTVisitor interface, which recursively
-// traverses the entire AST, using data recursion for Stmts/Exprs.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_DATARECURSIVEASTVISITOR_H
-#define LLVM_CLANG_AST_DATARECURSIVEASTVISITOR_H
-
-#include "clang/AST/Attr.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclFriend.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclOpenMP.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/ExprObjC.h"
-#include "clang/AST/NestedNameSpecifier.h"
-#include "clang/AST/Stmt.h"
-#include "clang/AST/StmtCXX.h"
-#include "clang/AST/StmtObjC.h"
-#include "clang/AST/StmtOpenMP.h"
-#include "clang/AST/TemplateBase.h"
-#include "clang/AST/TemplateName.h"
-#include "clang/AST/Type.h"
-#include "clang/AST/TypeLoc.h"
-
-// The following three macros are used for meta programming. The code
-// using them is responsible for defining macro OPERATOR().
-
-// All unary operators.
-#define UNARYOP_LIST() \
- OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \
- OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \
- OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \
- OPERATOR(Extension)
-
-// All binary operators (excluding compound assign operators).
-#define BINOP_LIST() \
- OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) \
- OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) \
- OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \
- OPERATOR(NE) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) OPERATOR(LAnd) \
- OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma)
-
-// All compound assign operators.
-#define CAO_LIST() \
- OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \
- OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor)
-
-namespace clang {
-
-// Reduce the diff between RecursiveASTVisitor / DataRecursiveASTVisitor to
-// make it easier to track changes and keep the two in sync.
-#define RecursiveASTVisitor DataRecursiveASTVisitor
-
-// A helper macro to implement short-circuiting when recursing. It
-// invokes CALL_EXPR, which must be a method call, on the derived
-// object (s.t. a user of RecursiveASTVisitor can override the method
-// in CALL_EXPR).
-#define TRY_TO(CALL_EXPR) \
- do { \
- if (!getDerived().CALL_EXPR) \
- return false; \
- } while (0)
-
-/// \brief A class that does preorder depth-first traversal on the
-/// entire Clang AST and visits each node.
-///
-/// This class performs three distinct tasks:
-/// 1. traverse the AST (i.e. go to each node);
-/// 2. at a given node, walk up the class hierarchy, starting from
-/// the node's dynamic type, until the top-most class (e.g. Stmt,
-/// Decl, or Type) is reached.
-/// 3. given a (node, class) combination, where 'class' is some base
-/// class of the dynamic type of 'node', call a user-overridable
-/// function to actually visit the node.
-///
-/// These tasks are done by three groups of methods, respectively:
-/// 1. TraverseDecl(Decl *x) does task #1. It is the entry point
-/// for traversing an AST rooted at x. This method simply
-/// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo
-/// is the dynamic type of *x, which calls WalkUpFromFoo(x) and
-/// then recursively visits the child nodes of x.
-/// TraverseStmt(Stmt *x) and TraverseType(QualType x) work
-/// similarly.
-/// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit
-/// any child node of x. Instead, it first calls WalkUpFromBar(x)
-/// where Bar is the direct parent class of Foo (unless Foo has
-/// no parent), and then calls VisitFoo(x) (see the next list item).
-/// 3. VisitFoo(Foo *x) does task #3.
-///
-/// These three method groups are tiered (Traverse* > WalkUpFrom* >
-/// Visit*). A method (e.g. Traverse*) may call methods from the same
-/// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*).
-/// It may not call methods from a higher tier.
-///
-/// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar
-/// is Foo's super class) before calling VisitFoo(), the result is
-/// that the Visit*() methods for a given node are called in the
-/// top-down order (e.g. for a node of type NamespaceDecl, the order will
-/// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()).
-///
-/// This scheme guarantees that all Visit*() calls for the same AST
-/// node are grouped together. In other words, Visit*() methods for
-/// different nodes are never interleaved.
-///
-/// Stmts are traversed internally using a data queue to avoid a stack overflow
-/// with hugely nested ASTs.
-///
-/// Clients of this visitor should subclass the visitor (providing
-/// themselves as the template argument, using the curiously recurring
-/// template pattern) and override any of the Traverse*, WalkUpFrom*,
-/// and Visit* methods for declarations, types, statements,
-/// expressions, or other AST nodes where the visitor should customize
-/// behavior. Most users only need to override Visit*. Advanced
-/// users may override Traverse* and WalkUpFrom* to implement custom
-/// traversal strategies. Returning false from one of these overridden
-/// functions will abort the entire traversal.
-///
-/// By default, this visitor tries to visit every part of the explicit
-/// source code exactly once. The default policy towards templates
-/// is to descend into the 'pattern' class or function body, not any
-/// explicit or implicit instantiations. Explicit specializations
-/// are still visited, and the patterns of partial specializations
-/// are visited separately. This behavior can be changed by
-/// overriding shouldVisitTemplateInstantiations() in the derived class
-/// to return true, in which case all known implicit and explicit
-/// instantiations will be visited at the same time as the pattern
-/// from which they were produced.
-template <typename Derived> class RecursiveASTVisitor {
-public:
- /// \brief Return a reference to the derived class.
- Derived &getDerived() { return *static_cast<Derived *>(this); }
-
- /// \brief Return whether this visitor should recurse into
- /// template instantiations.
- bool shouldVisitTemplateInstantiations() const { return false; }
-
- /// \brief Return whether this visitor should recurse into the types of
- /// TypeLocs.
- bool shouldWalkTypesOfTypeLocs() const { return true; }
-
- /// \brief Recursively visit a statement or expression, by
- /// dispatching to Traverse*() based on the argument's dynamic type.
- ///
- /// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is NULL).
- bool TraverseStmt(Stmt *S);
-
- /// \brief Recursively visit a type, by dispatching to
- /// Traverse*Type() based on the argument's getTypeClass() property.
- ///
- /// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is a Null type).
- bool TraverseType(QualType T);
-
- /// \brief Recursively visit a type with location, by dispatching to
- /// Traverse*TypeLoc() based on the argument type's getTypeClass() property.
- ///
- /// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is a Null type location).
- bool TraverseTypeLoc(TypeLoc TL);
-
- /// \brief Recursively visit an attribute, by dispatching to
- /// Traverse*Attr() based on the argument's dynamic type.
- ///
- /// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is a Null type location).
- bool TraverseAttr(Attr *At);
-
- /// \brief Recursively visit a declaration, by dispatching to
- /// Traverse*Decl() based on the argument's dynamic type.
- ///
- /// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is NULL).
- bool TraverseDecl(Decl *D);
-
- /// \brief Recursively visit a C++ nested-name-specifier.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
-
- /// \brief Recursively visit a C++ nested-name-specifier with location
- /// information.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
-
- /// \brief Recursively visit a name with its location information.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
-
- /// \brief Recursively visit a template name and dispatch to the
- /// appropriate method.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseTemplateName(TemplateName Template);
-
- /// \brief Recursively visit a template argument and dispatch to the
- /// appropriate method for the argument type.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- // FIXME: migrate callers to TemplateArgumentLoc instead.
- bool TraverseTemplateArgument(const TemplateArgument &Arg);
-
- /// \brief Recursively visit a template argument location and dispatch to the
- /// appropriate method for the argument type.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc);
-
- /// \brief Recursively visit a set of template arguments.
- /// This can be overridden by a subclass, but it's not expected that
- /// will be needed -- this visitor always dispatches to another.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
- bool TraverseTemplateArguments(const TemplateArgument *Args,
- unsigned NumArgs);
-
- /// \brief Recursively visit a constructor initializer. This
- /// automatically dispatches to another visitor for the initializer
- /// expression, but not for the name of the initializer, so may
- /// be overridden for clients that need access to the name.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
-
- /// \brief Recursively visit a lambda capture.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C);
-
- /// \brief Recursively visit the body of a lambda expression.
- ///
- /// This provides a hook for visitors that need more context when visiting
- /// \c LE->getBody().
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseLambdaBody(LambdaExpr *LE);
-
- // ---- Methods on Attrs ----
-
- // \brief Visit an attribute.
- bool VisitAttr(Attr *A) { return true; }
-
-// Declare Traverse* and empty Visit* for all Attr classes.
-#define ATTR_VISITOR_DECLS_ONLY
-#include "clang/AST/AttrVisitor.inc"
-#undef ATTR_VISITOR_DECLS_ONLY
-
-// ---- Methods on Stmts ----
-
-// Declare Traverse*() for all concrete Stmt classes.
-#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S);
-#include "clang/AST/StmtNodes.inc"
- // The above header #undefs ABSTRACT_STMT and STMT upon exit.
-
- // Define WalkUpFrom*() and empty Visit*() for all Stmt classes.
- bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); }
- bool VisitStmt(Stmt *S) { return true; }
-#define STMT(CLASS, PARENT) \
- bool WalkUpFrom##CLASS(CLASS *S) { \
- TRY_TO(WalkUpFrom##PARENT(S)); \
- TRY_TO(Visit##CLASS(S)); \
- return true; \
- } \
- bool Visit##CLASS(CLASS *S) { return true; }
-#include "clang/AST/StmtNodes.inc"
-
-// Define Traverse*(), WalkUpFrom*(), and Visit*() for unary
-// operator methods. Unary operators are not classes in themselves
-// (they're all opcodes in UnaryOperator) but do have visitors.
-#define OPERATOR(NAME) \
- bool TraverseUnary##NAME(UnaryOperator *S) { \
- TRY_TO(WalkUpFromUnary##NAME(S)); \
- StmtQueueAction StmtQueue(*this); \
- StmtQueue.queue(S->getSubExpr()); \
- return true; \
- } \
- bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
- TRY_TO(WalkUpFromUnaryOperator(S)); \
- TRY_TO(VisitUnary##NAME(S)); \
- return true; \
- } \
- bool VisitUnary##NAME(UnaryOperator *S) { return true; }
-
- UNARYOP_LIST()
-#undef OPERATOR
-
-// Define Traverse*(), WalkUpFrom*(), and Visit*() for binary
-// operator methods. Binary operators are not classes in themselves
-// (they're all opcodes in BinaryOperator) but do have visitors.
-#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
- bool TraverseBin##NAME(BINOP_TYPE *S) { \
- TRY_TO(WalkUpFromBin##NAME(S)); \
- StmtQueueAction StmtQueue(*this); \
- StmtQueue.queue(S->getLHS()); \
- StmtQueue.queue(S->getRHS()); \
- return true; \
- } \
- bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
- TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \
- TRY_TO(VisitBin##NAME(S)); \
- return true; \
- } \
- bool VisitBin##NAME(BINOP_TYPE *S) { return true; }
-
-#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator)
- BINOP_LIST()
-#undef OPERATOR
-
-// Define Traverse*(), WalkUpFrom*(), and Visit*() for compound
-// assignment methods. Compound assignment operators are not
-// classes in themselves (they're all opcodes in
-// CompoundAssignOperator) but do have visitors.
-#define OPERATOR(NAME) \
- GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator)
-
- CAO_LIST()
-#undef OPERATOR
-#undef GENERAL_BINOP_FALLBACK
-
-// ---- Methods on Types ----
-// FIXME: revamp to take TypeLoc's rather than Types.
-
-// Declare Traverse*() for all concrete Type classes.
-#define ABSTRACT_TYPE(CLASS, BASE)
-#define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T);
-#include "clang/AST/TypeNodes.def"
- // The above header #undefs ABSTRACT_TYPE and TYPE upon exit.
-
- // Define WalkUpFrom*() and empty Visit*() for all Type classes.
- bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); }
- bool VisitType(Type *T) { return true; }
-#define TYPE(CLASS, BASE) \
- bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \
- TRY_TO(WalkUpFrom##BASE(T)); \
- TRY_TO(Visit##CLASS##Type(T)); \
- return true; \
- } \
- bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
-#include "clang/AST/TypeNodes.def"
-
-// ---- Methods on TypeLocs ----
-// FIXME: this currently just calls the matching Type methods
-
-// Declare Traverse*() for all concrete TypeLoc classes.
-#define ABSTRACT_TYPELOC(CLASS, BASE)
-#define TYPELOC(CLASS, BASE) bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
-#include "clang/AST/TypeLocNodes.def"
- // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit.
-
- // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes.
- bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); }
- bool VisitTypeLoc(TypeLoc TL) { return true; }
-
- // QualifiedTypeLoc and UnqualTypeLoc are not declared in
- // TypeNodes.def and thus need to be handled specially.
- bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) {
- return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
- }
- bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; }
- bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) {
- return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
- }
- bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; }
-
-// Note that BASE includes trailing 'Type' which CLASS doesn't.
-#define TYPE(CLASS, BASE) \
- bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \
- TRY_TO(WalkUpFrom##BASE##Loc(TL)); \
- TRY_TO(Visit##CLASS##TypeLoc(TL)); \
- return true; \
- } \
- bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
-#include "clang/AST/TypeNodes.def"
-
-// ---- Methods on Decls ----
-
-// Declare Traverse*() for all concrete Decl classes.
-#define ABSTRACT_DECL(DECL)
-#define DECL(CLASS, BASE) bool Traverse##CLASS##Decl(CLASS##Decl *D);
-#include "clang/AST/DeclNodes.inc"
- // The above header #undefs ABSTRACT_DECL and DECL upon exit.
-
- // Define WalkUpFrom*() and empty Visit*() for all Decl classes.
- bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); }
- bool VisitDecl(Decl *D) { return true; }
-#define DECL(CLASS, BASE) \
- bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \
- TRY_TO(WalkUpFrom##BASE(D)); \
- TRY_TO(Visit##CLASS##Decl(D)); \
- return true; \
- } \
- bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
-#include "clang/AST/DeclNodes.inc"
-
-private:
- // These are helper methods used by more than one Traverse* method.
- bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
- bool TraverseClassInstantiations(ClassTemplateDecl *D);
- bool TraverseVariableInstantiations(VarTemplateDecl *D);
- bool TraverseFunctionInstantiations(FunctionTemplateDecl *D);
- bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
- unsigned Count);
- bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
- bool TraverseRecordHelper(RecordDecl *D);
- bool TraverseCXXRecordHelper(CXXRecordDecl *D);
- bool TraverseDeclaratorHelper(DeclaratorDecl *D);
- bool TraverseDeclContextHelper(DeclContext *DC);
- bool TraverseFunctionHelper(FunctionDecl *D);
- bool TraverseVarHelper(VarDecl *D);
- bool TraverseOMPExecutableDirective(OMPExecutableDirective *S);
- bool TraverseOMPLoopDirective(OMPLoopDirective *S);
- bool TraverseOMPClause(OMPClause *C);
-#define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C);
-#include "clang/Basic/OpenMPKinds.def"
- /// \brief Process clauses with list of variables.
- template <typename T> bool VisitOMPClauseList(T *Node);
-
- typedef SmallVector<Stmt *, 16> StmtsTy;
- typedef SmallVector<StmtsTy *, 4> QueuesTy;
-
- QueuesTy Queues;
-
- class NewQueueRAII {
- RecursiveASTVisitor &RAV;
-
- public:
- NewQueueRAII(StmtsTy &queue, RecursiveASTVisitor &RAV) : RAV(RAV) {
- RAV.Queues.push_back(&queue);
- }
- ~NewQueueRAII() { RAV.Queues.pop_back(); }
- };
-
- StmtsTy &getCurrentQueue() {
- assert(!Queues.empty() && "base TraverseStmt was never called?");
- return *Queues.back();
- }
-
-public:
- class StmtQueueAction {
- StmtsTy &CurrQueue;
-
- public:
- explicit StmtQueueAction(RecursiveASTVisitor &RAV)
- : CurrQueue(RAV.getCurrentQueue()) {}
-
- void queue(Stmt *S) { CurrQueue.push_back(S); }
- };
-};
-
-#define DISPATCH(NAME, CLASS, VAR) \
- return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
- if (!S)
- return true;
-
- StmtsTy Queue, StmtsToEnqueue;
- Queue.push_back(S);
- NewQueueRAII NQ(StmtsToEnqueue, *this);
-
- while (!Queue.empty()) {
- S = Queue.pop_back_val();
- if (!S)
- continue;
-
- StmtsToEnqueue.clear();
-
-#define DISPATCH_STMT(NAME, CLASS, VAR) \
- TRY_TO(Traverse##NAME(static_cast<CLASS *>(VAR))); \
- break
-
- // If we have a binary expr, dispatch to the subcode of the binop. A smart
- // optimizer (e.g. LLVM) will fold this comparison into the switch stmt
- // below.
- if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
- switch (BinOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case BO_##NAME: \
- DISPATCH_STMT(Bin##NAME, BinaryOperator, S);
-
- BINOP_LIST()
-#undef OPERATOR
-#undef BINOP_LIST
-
-#define OPERATOR(NAME) \
- case BO_##NAME##Assign: \
- DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S);
-
- CAO_LIST()
-#undef OPERATOR
-#undef CAO_LIST
- }
- } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
- switch (UnOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case UO_##NAME: \
- DISPATCH_STMT(Unary##NAME, UnaryOperator, S);
-
- UNARYOP_LIST()
-#undef OPERATOR
-#undef UNARYOP_LIST
- }
- } else {
-
- // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
- switch (S->getStmtClass()) {
- case Stmt::NoStmtClass:
- break;
-#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) \
- case Stmt::CLASS##Class: \
- DISPATCH_STMT(CLASS, CLASS, S);
-#include "clang/AST/StmtNodes.inc"
- }
- }
-
- Queue.append(StmtsToEnqueue.rbegin(), StmtsToEnqueue.rend());
- }
-
- return true;
-}
-
-#undef DISPATCH_STMT
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
- if (T.isNull())
- return true;
-
- switch (T->getTypeClass()) {
-#define ABSTRACT_TYPE(CLASS, BASE)
-#define TYPE(CLASS, BASE) \
- case Type::CLASS: \
- DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr()));
-#include "clang/AST/TypeNodes.def"
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) {
- if (TL.isNull())
- return true;
-
- switch (TL.getTypeLocClass()) {
-#define ABSTRACT_TYPELOC(CLASS, BASE)
-#define TYPELOC(CLASS, BASE) \
- case TypeLoc::CLASS: \
- return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>());
-#include "clang/AST/TypeLocNodes.def"
- }
-
- return true;
-}
-
-// Define the Traverse*Attr(Attr* A) methods
-#define VISITORCLASS RecursiveASTVisitor
-#include "clang/AST/AttrVisitor.inc"
-#undef VISITORCLASS
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
- if (!D)
- return true;
-
- // As a syntax visitor, we want to ignore declarations for
- // implicitly-defined declarations (ones not typed explicitly by the
- // user).
- if (D->isImplicit())
- return true;
-
- switch (D->getKind()) {
-#define ABSTRACT_DECL(DECL)
-#define DECL(CLASS, BASE) \
- case Decl::CLASS: \
- if (!getDerived().Traverse##CLASS##Decl(static_cast<CLASS##Decl *>(D))) \
- return false; \
- break;
-#include "clang/AST/DeclNodes.inc"
- }
-
- // Visit any attributes attached to this declaration.
- for (auto *I : D->attrs()) {
- if (!getDerived().TraverseAttr(I))
- return false;
- }
- return true;
-}
-
-#undef DISPATCH
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
- NestedNameSpecifier *NNS) {
- if (!NNS)
- return true;
-
- if (NNS->getPrefix())
- TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix()));
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- return true;
-
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- TRY_TO(TraverseType(QualType(NNS->getAsType(), 0)));
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
- NestedNameSpecifierLoc NNS) {
- if (!NNS)
- return true;
-
- if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
- TRY_TO(TraverseNestedNameSpecifierLoc(Prefix));
-
- switch (NNS.getNestedNameSpecifier()->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- return true;
-
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- TRY_TO(TraverseTypeLoc(NNS.getTypeLoc()));
- break;
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo(
- DeclarationNameInfo NameInfo) {
- switch (NameInfo.getName().getNameKind()) {
- case DeclarationName::CXXConstructorName:
- case DeclarationName::CXXDestructorName:
- case DeclarationName::CXXConversionFunctionName:
- if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
- TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc()));
-
- break;
-
- case DeclarationName::Identifier:
- case DeclarationName::ObjCZeroArgSelector:
- case DeclarationName::ObjCOneArgSelector:
- case DeclarationName::ObjCMultiArgSelector:
- case DeclarationName::CXXOperatorName:
- case DeclarationName::CXXLiteralOperatorName:
- case DeclarationName::CXXUsingDirective:
- break;
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
- if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
- TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier()));
- else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
- TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier()));
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
- const TemplateArgument &Arg) {
- switch (Arg.getKind()) {
- case TemplateArgument::Null:
- case TemplateArgument::Declaration:
- case TemplateArgument::Integral:
- case TemplateArgument::NullPtr:
- return true;
-
- case TemplateArgument::Type:
- return getDerived().TraverseType(Arg.getAsType());
-
- case TemplateArgument::Template:
- case TemplateArgument::TemplateExpansion:
- return getDerived().TraverseTemplateName(
- Arg.getAsTemplateOrTemplatePattern());
-
- case TemplateArgument::Expression:
- return getDerived().TraverseStmt(Arg.getAsExpr());
-
- case TemplateArgument::Pack:
- return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
- Arg.pack_size());
- }
-
- return true;
-}
-
-// FIXME: no template name location?
-// FIXME: no source locations for a template argument pack?
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
- const TemplateArgumentLoc &ArgLoc) {
- const TemplateArgument &Arg = ArgLoc.getArgument();
-
- switch (Arg.getKind()) {
- case TemplateArgument::Null:
- case TemplateArgument::Declaration:
- case TemplateArgument::Integral:
- case TemplateArgument::NullPtr:
- return true;
-
- case TemplateArgument::Type: {
- // FIXME: how can TSI ever be NULL?
- if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo())
- return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
- else
- return getDerived().TraverseType(Arg.getAsType());
- }
-
- case TemplateArgument::Template:
- case TemplateArgument::TemplateExpansion:
- if (ArgLoc.getTemplateQualifierLoc())
- TRY_TO(getDerived().TraverseNestedNameSpecifierLoc(
- ArgLoc.getTemplateQualifierLoc()));
- return getDerived().TraverseTemplateName(
- Arg.getAsTemplateOrTemplatePattern());
-
- case TemplateArgument::Expression:
- return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
-
- case TemplateArgument::Pack:
- return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
- Arg.pack_size());
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
- const TemplateArgument *Args, unsigned NumArgs) {
- for (unsigned I = 0; I != NumArgs; ++I) {
- TRY_TO(TraverseTemplateArgument(Args[I]));
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
- CXXCtorInitializer *Init) {
- if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo())
- TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
-
- if (Init->isWritten())
- TRY_TO(TraverseStmt(Init->getInit()));
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
- const LambdaCapture *C) {
- if (LE->isInitCapture(C))
- TRY_TO(TraverseDecl(C->getCapturedVar()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) {
- StmtQueueAction StmtQueue(*this);
- StmtQueue.queue(LE->getBody());
- return true;
-}
-
-// ----------------- Type traversal -----------------
-
-// This macro makes available a variable T, the passed-in type.
-#define DEF_TRAVERSE_TYPE(TYPE, CODE) \
- template <typename Derived> \
- bool RecursiveASTVisitor<Derived>::Traverse##TYPE(TYPE *T) { \
- TRY_TO(WalkUpFrom##TYPE(T)); \
- { CODE; } \
- return true; \
- }
-
-DEF_TRAVERSE_TYPE(BuiltinType, {})
-
-DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); })
-
-DEF_TRAVERSE_TYPE(PointerType, { TRY_TO(TraverseType(T->getPointeeType())); })
-
-DEF_TRAVERSE_TYPE(BlockPointerType,
- { TRY_TO(TraverseType(T->getPointeeType())); })
-
-DEF_TRAVERSE_TYPE(LValueReferenceType,
- { TRY_TO(TraverseType(T->getPointeeType())); })
-
-DEF_TRAVERSE_TYPE(RValueReferenceType,
- { TRY_TO(TraverseType(T->getPointeeType())); })
-
-DEF_TRAVERSE_TYPE(MemberPointerType, {
- TRY_TO(TraverseType(QualType(T->getClass(), 0)));
- TRY_TO(TraverseType(T->getPointeeType()));
-})
-
-DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); })
-
-DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); })
-
-DEF_TRAVERSE_TYPE(ConstantArrayType,
- { TRY_TO(TraverseType(T->getElementType())); })
-
-DEF_TRAVERSE_TYPE(IncompleteArrayType,
- { TRY_TO(TraverseType(T->getElementType())); })
-
-DEF_TRAVERSE_TYPE(VariableArrayType, {
- TRY_TO(TraverseType(T->getElementType()));
- TRY_TO(TraverseStmt(T->getSizeExpr()));
-})
-
-DEF_TRAVERSE_TYPE(DependentSizedArrayType, {
- TRY_TO(TraverseType(T->getElementType()));
- if (T->getSizeExpr())
- TRY_TO(TraverseStmt(T->getSizeExpr()));
-})
-
-DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, {
- if (T->getSizeExpr())
- TRY_TO(TraverseStmt(T->getSizeExpr()));
- TRY_TO(TraverseType(T->getElementType()));
-})
-
-DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); })
-
-DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); })
-
-DEF_TRAVERSE_TYPE(FunctionNoProtoType,
- { TRY_TO(TraverseType(T->getReturnType())); })
-
-DEF_TRAVERSE_TYPE(FunctionProtoType, {
- TRY_TO(TraverseType(T->getReturnType()));
-
- for (const auto &A : T->param_types()) {
- TRY_TO(TraverseType(A));
- }
-
- for (const auto &E : T->exceptions()) {
- TRY_TO(TraverseType(E));
- }
-
- if (Expr *NE = T->getNoexceptExpr())
- TRY_TO(TraverseStmt(NE));
-})
-
-DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})
-DEF_TRAVERSE_TYPE(TypedefType, {})
-
-DEF_TRAVERSE_TYPE(TypeOfExprType,
- { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
-
-DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnderlyingType())); })
-
-DEF_TRAVERSE_TYPE(DecltypeType,
- { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
-
-DEF_TRAVERSE_TYPE(UnaryTransformType, {
- TRY_TO(TraverseType(T->getBaseType()));
- TRY_TO(TraverseType(T->getUnderlyingType()));
-})
-
-DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); })
-
-DEF_TRAVERSE_TYPE(RecordType, {})
-DEF_TRAVERSE_TYPE(EnumType, {})
-DEF_TRAVERSE_TYPE(TemplateTypeParmType, {})
-DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, {})
-DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {})
-
-DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
- TRY_TO(TraverseTemplateName(T->getTemplateName()));
- TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
-})
-
-DEF_TRAVERSE_TYPE(InjectedClassNameType, {})
-
-DEF_TRAVERSE_TYPE(AttributedType,
- { TRY_TO(TraverseType(T->getModifiedType())); })
-
-DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); })
-
-DEF_TRAVERSE_TYPE(ElaboratedType, {
- if (T->getQualifier()) {
- TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
- }
- TRY_TO(TraverseType(T->getNamedType()));
-})
-
-DEF_TRAVERSE_TYPE(DependentNameType,
- { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); })
-
-DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
- TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
- TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
-})
-
-DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); })
-
-DEF_TRAVERSE_TYPE(ObjCInterfaceType, {})
-
-DEF_TRAVERSE_TYPE(ObjCObjectType, {
- // We have to watch out here because an ObjCInterfaceType's base
- // type is itself.
- if (T->getBaseType().getTypePtr() != T)
- TRY_TO(TraverseType(T->getBaseType()));
- for (auto typeArg : T->getTypeArgsAsWritten()) {
- TRY_TO(TraverseType(typeArg));
- }
-})
-
-DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
- { TRY_TO(TraverseType(T->getPointeeType())); })
-
-DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
-
-#undef DEF_TRAVERSE_TYPE
-
-// ----------------- TypeLoc traversal -----------------
-
-// This macro makes available a variable TL, the passed-in TypeLoc.
-// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc,
-// in addition to WalkUpFrom* for the TypeLoc itself, such that existing
-// clients that override the WalkUpFrom*Type() and/or Visit*Type() methods
-// continue to work.
-#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \
- template <typename Derived> \
- bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \
- if (getDerived().shouldWalkTypesOfTypeLocs()) \
- TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \
- TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \
- { CODE; } \
- return true; \
- }
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) {
- // Move this over to the 'main' typeloc tree. Note that this is a
- // move -- we pretend that we were really looking at the unqualified
- // typeloc all along -- rather than a recursion, so we don't follow
- // the normal CRTP plan of going through
- // getDerived().TraverseTypeLoc. If we did, we'd be traversing
- // twice for the same type (once as a QualifiedTypeLoc version of
- // the type, once as an UnqualifiedTypeLoc version of the type),
- // which in effect means we'd call VisitTypeLoc twice with the
- // 'same' type. This solves that problem, at the cost of never
- // seeing the qualified version of the type (unless the client
- // subclasses TraverseQualifiedTypeLoc themselves). It's not a
- // perfect solution. A perfect solution probably requires making
- // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a
- // wrapper around Type* -- rather than being its own class in the
- // type hierarchy.
- return TraverseTypeLoc(TL.getUnqualifiedLoc());
-}
-
-DEF_TRAVERSE_TYPELOC(BuiltinType, {})
-
-// FIXME: ComplexTypeLoc is unfinished
-DEF_TRAVERSE_TYPELOC(ComplexType, {
- TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
-})
-
-DEF_TRAVERSE_TYPELOC(PointerType,
- { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-
-DEF_TRAVERSE_TYPELOC(BlockPointerType,
- { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-
-DEF_TRAVERSE_TYPELOC(LValueReferenceType,
- { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-
-DEF_TRAVERSE_TYPELOC(RValueReferenceType,
- { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-
-// FIXME: location of base class?
-// We traverse this in the type case as well, but how is it not reached through
-// the pointee type?
-DEF_TRAVERSE_TYPELOC(MemberPointerType, {
- TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
- TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
-})
-
-DEF_TRAVERSE_TYPELOC(AdjustedType,
- { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); })
-
-DEF_TRAVERSE_TYPELOC(DecayedType,
- { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); })
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
- // This isn't available for ArrayType, but is for the ArrayTypeLoc.
- TRY_TO(TraverseStmt(TL.getSizeExpr()));
- return true;
-}
-
-DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
-})
-
-DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
-})
-
-DEF_TRAVERSE_TYPELOC(VariableArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
-})
-
-DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
-})
-
-// FIXME: order? why not size expr first?
-// FIXME: base VectorTypeLoc is unfinished
-DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, {
- if (TL.getTypePtr()->getSizeExpr())
- TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
- TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
-})
-
-// FIXME: VectorTypeLoc is unfinished
-DEF_TRAVERSE_TYPELOC(VectorType, {
- TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
-})
-
-// FIXME: size and attributes
-// FIXME: base VectorTypeLoc is unfinished
-DEF_TRAVERSE_TYPELOC(ExtVectorType, {
- TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
-})
-
-DEF_TRAVERSE_TYPELOC(FunctionNoProtoType,
- { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); })
-
-// FIXME: location of exception specifications (attributes?)
-DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
- TRY_TO(TraverseTypeLoc(TL.getReturnLoc()));
-
- const FunctionProtoType *T = TL.getTypePtr();
-
- for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) {
- if (TL.getParam(I)) {
- TRY_TO(TraverseDecl(TL.getParam(I)));
- } else if (I < T->getNumParams()) {
- TRY_TO(TraverseType(T->getParamType(I)));
- }
- }
-
- for (const auto &E : T->exceptions()) {
- TRY_TO(TraverseType(E));
- }
-
- if (Expr *NE = T->getNoexceptExpr())
- TRY_TO(TraverseStmt(NE));
-})
-
-DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})
-DEF_TRAVERSE_TYPELOC(TypedefType, {})
-
-DEF_TRAVERSE_TYPELOC(TypeOfExprType,
- { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); })
-
-DEF_TRAVERSE_TYPELOC(TypeOfType, {
- TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
-})
-
-// FIXME: location of underlying expr
-DEF_TRAVERSE_TYPELOC(DecltypeType, {
- TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
-})
-
-DEF_TRAVERSE_TYPELOC(UnaryTransformType, {
- TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_TYPELOC(AutoType, {
- TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
-})
-
-DEF_TRAVERSE_TYPELOC(RecordType, {})
-DEF_TRAVERSE_TYPELOC(EnumType, {})
-DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {})
-DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, {})
-DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, {})
-
-// FIXME: use the loc for the template name?
-DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
- TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName()));
- for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
- TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
- }
-})
-
-DEF_TRAVERSE_TYPELOC(InjectedClassNameType, {})
-
-DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); })
-
-DEF_TRAVERSE_TYPELOC(AttributedType,
- { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); })
-
-DEF_TRAVERSE_TYPELOC(ElaboratedType, {
- if (TL.getQualifierLoc()) {
- TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
- }
- TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc()));
-})
-
-DEF_TRAVERSE_TYPELOC(DependentNameType, {
- TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
-})
-
-DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, {
- if (TL.getQualifierLoc()) {
- TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
- }
-
- for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
- TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
- }
-})
-
-DEF_TRAVERSE_TYPELOC(PackExpansionType,
- { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); })
-
-DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {})
-
-DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
- // We have to watch out here because an ObjCInterfaceType's base
- // type is itself.
- if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
- TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
- for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i)
- TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc()));
-})
-
-DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
- { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-
-DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
-
-#undef DEF_TRAVERSE_TYPELOC
-
-// ----------------- Decl traversal -----------------
-//
-// For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing
-// the children that come from the DeclContext associated with it.
-// Therefore each Traverse* only needs to worry about children other
-// than those.
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) {
- if (!DC)
- return true;
-
- for (auto *Child : DC->decls()) {
- // BlockDecls and CapturedDecls are traversed through BlockExprs and
- // CapturedStmts respectively.
- if (!isa<BlockDecl>(Child) && !isa<CapturedDecl>(Child))
- TRY_TO(TraverseDecl(Child));
- }
-
- return true;
-}
-
-// This macro makes available a variable D, the passed-in decl.
-#define DEF_TRAVERSE_DECL(DECL, CODE) \
- template <typename Derived> \
- bool RecursiveASTVisitor<Derived>::Traverse##DECL(DECL *D) { \
- TRY_TO(WalkUpFrom##DECL(D)); \
- { CODE; } \
- TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \
- return true; \
- }
-
-DEF_TRAVERSE_DECL(AccessSpecDecl, {})
-
-DEF_TRAVERSE_DECL(BlockDecl, {
- if (TypeSourceInfo *TInfo = D->getSignatureAsWritten())
- TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
- TRY_TO(TraverseStmt(D->getBody()));
- for (const auto &I : D->captures()) {
- if (I.hasCopyExpr()) {
- TRY_TO(TraverseStmt(I.getCopyExpr()));
- }
- }
- // This return statement makes sure the traversal of nodes in
- // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
- // is skipped - don't remove it.
- return true;
-})
-
-DEF_TRAVERSE_DECL(CapturedDecl, {
- TRY_TO(TraverseStmt(D->getBody()));
- // This return statement makes sure the traversal of nodes in
- // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
- // is skipped - don't remove it.
- return true;
-})
-
-DEF_TRAVERSE_DECL(EmptyDecl, {})
-
-DEF_TRAVERSE_DECL(FileScopeAsmDecl,
- { TRY_TO(TraverseStmt(D->getAsmString())); })
-
-DEF_TRAVERSE_DECL(ImportDecl, {})
-
-DEF_TRAVERSE_DECL(FriendDecl, {
- // Friend is either decl or a type.
- if (D->getFriendType())
- TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
- else
- TRY_TO(TraverseDecl(D->getFriendDecl()));
-})
-
-DEF_TRAVERSE_DECL(FriendTemplateDecl, {
- if (D->getFriendType())
- TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
- else
- TRY_TO(TraverseDecl(D->getFriendDecl()));
- for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) {
- TemplateParameterList *TPL = D->getTemplateParameterList(I);
- for (TemplateParameterList::iterator ITPL = TPL->begin(), ETPL = TPL->end();
- ITPL != ETPL; ++ITPL) {
- TRY_TO(TraverseDecl(*ITPL));
- }
- }
-})
-
-DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl,
- { TRY_TO(TraverseDecl(D->getSpecialization())); })
-
-DEF_TRAVERSE_DECL(LinkageSpecDecl, {})
-
-DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this
- })
-
-DEF_TRAVERSE_DECL(StaticAssertDecl, {
- TRY_TO(TraverseStmt(D->getAssertExpr()));
- TRY_TO(TraverseStmt(D->getMessage()));
-})
-
-DEF_TRAVERSE_DECL(
- TranslationUnitDecl,
- {// Code in an unnamed namespace shows up automatically in
- // decls_begin()/decls_end(). Thus we don't need to recurse on
- // D->getAnonymousNamespace().
- })
-
-DEF_TRAVERSE_DECL(ExternCContextDecl, {})
-
-DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
- // We shouldn't traverse an aliased namespace, since it will be
- // defined (and, therefore, traversed) somewhere else.
- //
- // This return statement makes sure the traversal of nodes in
- // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
- // is skipped - don't remove it.
- return true;
-})
-
-DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl.
- })
-
-DEF_TRAVERSE_DECL(
- NamespaceDecl,
- {// Code in an unnamed namespace shows up automatically in
- // decls_begin()/decls_end(). Thus we don't need to recurse on
- // D->getAnonymousNamespace().
- })
-
-DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement
- })
-
-DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
- if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) {
- for (auto typeParam : *typeParamList) {
- TRY_TO(TraverseObjCTypeParamDecl(typeParam));
- }
- }
- return true;
-})
-
-DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
- })
-
-DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
- })
-
-DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
- if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) {
- for (auto typeParam : *typeParamList) {
- TRY_TO(TraverseObjCTypeParamDecl(typeParam));
- }
- }
-
- if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
- TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
- }
-})
-
-DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
- })
-
-DEF_TRAVERSE_DECL(ObjCMethodDecl, {
- if (D->getReturnTypeSourceInfo()) {
- TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc()));
- }
- for (ObjCMethodDecl::param_iterator I = D->param_begin(), E = D->param_end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
- if (D->isThisDeclarationADefinition()) {
- TRY_TO(TraverseStmt(D->getBody()));
- }
- return true;
-})
-
-DEF_TRAVERSE_DECL(ObjCTypeParamDecl, {
- if (D->hasExplicitBound()) {
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
- // We shouldn't traverse D->getTypeForDecl(); it's a result of
- // declaring the type alias, not something that was written in the
- // source.
- }
-})
-
-DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
- if (D->getTypeSourceInfo())
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
- else
- TRY_TO(TraverseType(D->getType()));
- return true;
-})
-
-DEF_TRAVERSE_DECL(UsingDecl, {
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
-})
-
-DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
-})
-
-DEF_TRAVERSE_DECL(UsingShadowDecl, {})
-
-DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, {
- for (auto *I : D->varlists()) {
- TRY_TO(TraverseStmt(I));
- }
-})
-
-// A helper method for TemplateDecl's children.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
- TemplateParameterList *TPL) {
- if (TPL) {
- for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
- }
- return true;
-}
-
-// A helper method for traversing the implicit instantiations of a
-// class template.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
- ClassTemplateDecl *D) {
- for (auto *SD : D->specializations()) {
- for (auto *RD : SD->redecls()) {
- // We don't want to visit injected-class-names in this traversal.
- if (cast<CXXRecordDecl>(RD)->isInjectedClassName())
- continue;
-
- switch (
- cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) {
- // Visit the implicit instantiations with the requested pattern.
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- TRY_TO(TraverseDecl(RD));
- break;
-
- // We don't need to do anything on an explicit instantiation
- // or explicit specialization because there will be an explicit
- // node for it elsewhere.
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- case TSK_ExplicitSpecialization:
- break;
- }
- }
- }
-
- return true;
-}
-
-DEF_TRAVERSE_DECL(ClassTemplateDecl, {
- CXXRecordDecl *TempDecl = D->getTemplatedDecl();
- TRY_TO(TraverseDecl(TempDecl));
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-
- // By default, we do not traverse the instantiations of
- // class templates since they do not appear in the user code. The
- // following code optionally traverses them.
- //
- // We only traverse the class instantiations when we see the canonical
- // declaration of the template, to ensure we only visit them once.
- if (getDerived().shouldVisitTemplateInstantiations() &&
- D == D->getCanonicalDecl())
- TRY_TO(TraverseClassInstantiations(D));
-
- // Note that getInstantiatedFromMemberTemplate() is just a link
- // from a template instantiation back to the template from which
- // it was instantiated, and thus should not be traversed.
-})
-
-// A helper method for traversing the implicit instantiations of a
-// class template.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseVariableInstantiations(
- VarTemplateDecl *D) {
- for (auto *SD : D->specializations()) {
- for (auto *RD : SD->redecls()) {
- switch (
- cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) {
- // Visit the implicit instantiations with the requested pattern.
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- TRY_TO(TraverseDecl(RD));
- break;
-
- // We don't need to do anything on an explicit instantiation
- // or explicit specialization because there will be an explicit
- // node for it elsewhere.
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- case TSK_ExplicitSpecialization:
- break;
- }
- }
- }
-
- return true;
-}
-
-DEF_TRAVERSE_DECL(VarTemplateDecl, {
- VarDecl *TempDecl = D->getTemplatedDecl();
- TRY_TO(TraverseDecl(TempDecl));
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-
- // By default, we do not traverse the instantiations of
- // variable templates since they do not appear in the user code. The
- // following code optionally traverses them.
- //
- // We only traverse the variable instantiations when we see the canonical
- // declaration of the template, to ensure we only visit them once.
- if (getDerived().shouldVisitTemplateInstantiations() &&
- D == D->getCanonicalDecl())
- TRY_TO(TraverseVariableInstantiations(D));
-
- // Note that getInstantiatedFromMemberTemplate() is just a link
- // from a template instantiation back to the template from which
- // it was instantiated, and thus should not be traversed.
-})
-
-// A helper method for traversing the instantiations of a
-// function while skipping its specializations.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
- FunctionTemplateDecl *D) {
- for (auto *FD : D->specializations()) {
- for (auto *RD : FD->redecls()) {
- switch (RD->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- // We don't know what kind of FunctionDecl this is.
- TRY_TO(TraverseDecl(RD));
- break;
-
- // No need to visit explicit instantiations, we'll find the node
- // eventually.
- // FIXME: This is incorrect; there is no other node for an explicit
- // instantiation of a function template specialization.
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- break;
-
- case TSK_ExplicitSpecialization:
- break;
- }
- }
- }
-
- return true;
-}
-
-DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
- TRY_TO(TraverseDecl(D->getTemplatedDecl()));
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-
- // By default, we do not traverse the instantiations of
- // function templates since they do not appear in the user code. The
- // following code optionally traverses them.
- //
- // We only traverse the function instantiations when we see the canonical
- // declaration of the template, to ensure we only visit them once.
- if (getDerived().shouldVisitTemplateInstantiations() &&
- D == D->getCanonicalDecl())
- TRY_TO(TraverseFunctionInstantiations(D));
-})
-
-DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
- // D is the "T" in something like
- // template <template <typename> class T> class container { };
- TRY_TO(TraverseDecl(D->getTemplatedDecl()));
- if (D->hasDefaultArgument()) {
- TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
- }
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-})
-
-DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
- // D is the "T" in something like "template<typename T> class vector;"
- if (D->getTypeForDecl())
- TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
- if (D->hasDefaultArgument())
- TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_DECL(TypedefDecl, {
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
- // We shouldn't traverse D->getTypeForDecl(); it's a result of
- // declaring the typedef, not something that was written in the
- // source.
-})
-
-DEF_TRAVERSE_DECL(TypeAliasDecl, {
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
- // We shouldn't traverse D->getTypeForDecl(); it's a result of
- // declaring the type alias, not something that was written in the
- // source.
-})
-
-DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, {
- TRY_TO(TraverseDecl(D->getTemplatedDecl()));
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-})
-
-DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, {
- // A dependent using declaration which was marked with 'typename'.
- // template<class T> class A : public B<T> { using typename B<T>::foo; };
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- // We shouldn't traverse D->getTypeForDecl(); it's a result of
- // declaring the type, not something that was written in the
- // source.
-})
-
-DEF_TRAVERSE_DECL(EnumDecl, {
- if (D->getTypeForDecl())
- TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
-
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- // The enumerators are already traversed by
- // decls_begin()/decls_end().
-})
-
-// Helper methods for RecordDecl and its children.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) {
- // We shouldn't traverse D->getTypeForDecl(); it's a result of
- // declaring the type, not something that was written in the source.
-
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) {
- if (!TraverseRecordHelper(D))
- return false;
- if (D->isCompleteDefinition()) {
- for (const auto &I : D->bases()) {
- TRY_TO(TraverseTypeLoc(I.getTypeSourceInfo()->getTypeLoc()));
- }
- // We don't traverse the friends or the conversions, as they are
- // already in decls_begin()/decls_end().
- }
- return true;
-}
-
-DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); })
-
-DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
-
-DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
- // For implicit instantiations ("set<int> x;"), we don't want to
- // recurse at all, since the instatiated class isn't written in
- // the source code anywhere. (Note the instatiated *type* --
- // set<int> -- is written, and will still get a callback of
- // TemplateSpecializationType). For explicit instantiations
- // ("template set<int>;"), we do need a callback, since this
- // is the only callback that's made for this instantiation.
- // We use getTypeAsWritten() to distinguish.
- if (TypeSourceInfo *TSI = D->getTypeAsWritten())
- TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
-
- if (!getDerived().shouldVisitTemplateInstantiations() &&
- D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
- // Returning from here skips traversing the
- // declaration context of the ClassTemplateSpecializationDecl
- // (embedded in the DEF_TRAVERSE_DECL() macro)
- // which contains the instantiated members of the class.
- return true;
-})
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
- const TemplateArgumentLoc *TAL, unsigned Count) {
- for (unsigned I = 0; I < Count; ++I) {
- TRY_TO(TraverseTemplateArgumentLoc(TAL[I]));
- }
- return true;
-}
-
-DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
- // The partial specialization.
- if (TemplateParameterList *TPL = D->getTemplateParameters()) {
- for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
- }
- // The args that remains unspecialized.
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- D->getTemplateArgsAsWritten()->getTemplateArgs(),
- D->getTemplateArgsAsWritten()->NumTemplateArgs));
-
- // Don't need the ClassTemplatePartialSpecializationHelper, even
- // though that's our parent class -- we already visit all the
- // template args here.
- TRY_TO(TraverseCXXRecordHelper(D));
-
- // Instantiations will have been visited with the primary template.
-})
-
-DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); })
-
-DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, {
- // Like UnresolvedUsingTypenameDecl, but without the 'typename':
- // template <class T> Class A : public Base<T> { using Base<T>::foo; };
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
-})
-
-DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- if (D->getTypeSourceInfo())
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
- else
- TRY_TO(TraverseType(D->getType()));
- return true;
-}
-
-DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); })
-
-DEF_TRAVERSE_DECL(FieldDecl, {
- TRY_TO(TraverseDeclaratorHelper(D));
- if (D->isBitField())
- TRY_TO(TraverseStmt(D->getBitWidth()));
- else if (D->hasInClassInitializer())
- TRY_TO(TraverseStmt(D->getInClassInitializer()));
-})
-
-DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, {
- TRY_TO(TraverseDeclaratorHelper(D));
- if (D->isBitField())
- TRY_TO(TraverseStmt(D->getBitWidth()));
- // FIXME: implement the rest.
-})
-
-DEF_TRAVERSE_DECL(ObjCIvarDecl, {
- TRY_TO(TraverseDeclaratorHelper(D));
- if (D->isBitField())
- TRY_TO(TraverseStmt(D->getBitWidth()));
- // FIXME: implement the rest.
-})
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
-
- // If we're an explicit template specialization, iterate over the
- // template args that were explicitly specified. If we were doing
- // this in typing order, we'd do it between the return type and
- // the function args, but both are handled by the FunctionTypeLoc
- // above, so we have to choose one side. I've decided to do before.
- if (const FunctionTemplateSpecializationInfo *FTSI =
- D->getTemplateSpecializationInfo()) {
- if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared &&
- FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
- // A specialization might not have explicit template arguments if it has
- // a templated return type and concrete arguments.
- if (const ASTTemplateArgumentListInfo *TALI =
- FTSI->TemplateArgumentsAsWritten) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(),
- TALI->NumTemplateArgs));
- }
- }
- }
-
- // Visit the function type itself, which can be either
- // FunctionNoProtoType or FunctionProtoType, or a typedef. This
- // also covers the return type and the function parameters,
- // including exception specifications.
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
-
- if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
- // Constructor initializers.
- for (auto *I : Ctor->inits()) {
- TRY_TO(TraverseConstructorInitializer(I));
- }
- }
-
- if (D->isThisDeclarationADefinition()) {
- TRY_TO(TraverseStmt(D->getBody())); // Function body.
- }
- return true;
-}
-
-DEF_TRAVERSE_DECL(FunctionDecl, {
- // We skip decls_begin/decls_end, which are already covered by
- // TraverseFunctionHelper().
- return TraverseFunctionHelper(D);
-})
-
-DEF_TRAVERSE_DECL(CXXMethodDecl, {
- // We skip decls_begin/decls_end, which are already covered by
- // TraverseFunctionHelper().
- return TraverseFunctionHelper(D);
-})
-
-DEF_TRAVERSE_DECL(CXXConstructorDecl, {
- // We skip decls_begin/decls_end, which are already covered by
- // TraverseFunctionHelper().
- return TraverseFunctionHelper(D);
-})
-
-// CXXConversionDecl is the declaration of a type conversion operator.
-// It's not a cast expression.
-DEF_TRAVERSE_DECL(CXXConversionDecl, {
- // We skip decls_begin/decls_end, which are already covered by
- // TraverseFunctionHelper().
- return TraverseFunctionHelper(D);
-})
-
-DEF_TRAVERSE_DECL(CXXDestructorDecl, {
- // We skip decls_begin/decls_end, which are already covered by
- // TraverseFunctionHelper().
- return TraverseFunctionHelper(D);
-})
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
- TRY_TO(TraverseDeclaratorHelper(D));
- // Default params are taken care of when we traverse the ParmVarDecl.
- if (!isa<ParmVarDecl>(D))
- TRY_TO(TraverseStmt(D->getInit()));
- return true;
-}
-
-DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); })
-
-DEF_TRAVERSE_DECL(VarTemplateSpecializationDecl, {
- // For implicit instantiations, we don't want to
- // recurse at all, since the instatiated class isn't written in
- // the source code anywhere.
- if (TypeSourceInfo *TSI = D->getTypeAsWritten())
- TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
-
- if (!getDerived().shouldVisitTemplateInstantiations() &&
- D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
- // Returning from here skips traversing the
- // declaration context of the VarTemplateSpecializationDecl
- // (embedded in the DEF_TRAVERSE_DECL() macro).
- return true;
-})
-
-DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl, {
- // The partial specialization.
- if (TemplateParameterList *TPL = D->getTemplateParameters()) {
- for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
- }
- // The args that remains unspecialized.
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- D->getTemplateArgsAsWritten()->getTemplateArgs(),
- D->getTemplateArgsAsWritten()->NumTemplateArgs));
-
- // Don't need the VarTemplatePartialSpecializationHelper, even
- // though that's our parent class -- we already visit all the
- // template args here.
- TRY_TO(TraverseVarHelper(D));
-
- // Instantiations will have been visited with the primary
- // template.
-})
-
-DEF_TRAVERSE_DECL(ImplicitParamDecl, { TRY_TO(TraverseVarHelper(D)); })
-
-DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
- // A non-type template parameter, e.g. "S" in template<int S> class Foo ...
- TRY_TO(TraverseDeclaratorHelper(D));
- TRY_TO(TraverseStmt(D->getDefaultArgument()));
-})
-
-DEF_TRAVERSE_DECL(ParmVarDecl, {
- TRY_TO(TraverseVarHelper(D));
-
- if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() &&
- !D->hasUnparsedDefaultArg())
- TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg()));
-
- if (D->hasDefaultArg() && !D->hasUninstantiatedDefaultArg() &&
- !D->hasUnparsedDefaultArg())
- TRY_TO(TraverseStmt(D->getDefaultArg()));
-})
-
-#undef DEF_TRAVERSE_DECL
-
-// ----------------- Stmt traversal -----------------
-//
-// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating
-// over the children defined in children() (every stmt defines these,
-// though sometimes the range is empty). Each individual Traverse*
-// method only needs to worry about children other than those. To see
-// what children() does for a given class, see, e.g.,
-// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
-
-// This macro makes available a variable S, the passed-in stmt.
-#define DEF_TRAVERSE_STMT(STMT, CODE) \
- template <typename Derived> \
- bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \
- TRY_TO(WalkUpFrom##STMT(S)); \
- StmtQueueAction StmtQueue(*this); \
- { CODE; } \
- for (Stmt *SubStmt : S->children()) { \
- StmtQueue.queue(SubStmt); \
- } \
- return true; \
- }
-
-DEF_TRAVERSE_STMT(GCCAsmStmt, {
- StmtQueue.queue(S->getAsmString());
- for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
- StmtQueue.queue(S->getInputConstraintLiteral(I));
- }
- for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
- StmtQueue.queue(S->getOutputConstraintLiteral(I));
- }
- for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
- StmtQueue.queue(S->getClobberStringLiteral(I));
- }
- // children() iterates over inputExpr and outputExpr.
-})
-
-DEF_TRAVERSE_STMT(
- MSAsmStmt,
- {// FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once
- // added this needs to be implemented.
- })
-
-DEF_TRAVERSE_STMT(CXXCatchStmt, {
- TRY_TO(TraverseDecl(S->getExceptionDecl()));
- // children() iterates over the handler block.
-})
-
-DEF_TRAVERSE_STMT(DeclStmt, {
- for (auto *I : S->decls()) {
- TRY_TO(TraverseDecl(I));
- }
- // Suppress the default iteration over children() by
- // returning. Here's why: A DeclStmt looks like 'type var [=
- // initializer]'. The decls above already traverse over the
- // initializers, so we don't have to do it again (which
- // children() would do).
- return true;
-})
-
-// These non-expr stmts (most of them), do not need any action except
-// iterating over the children.
-DEF_TRAVERSE_STMT(BreakStmt, {})
-DEF_TRAVERSE_STMT(CXXTryStmt, {})
-DEF_TRAVERSE_STMT(CaseStmt, {})
-DEF_TRAVERSE_STMT(CompoundStmt, {})
-DEF_TRAVERSE_STMT(ContinueStmt, {})
-DEF_TRAVERSE_STMT(DefaultStmt, {})
-DEF_TRAVERSE_STMT(DoStmt, {})
-DEF_TRAVERSE_STMT(ForStmt, {})
-DEF_TRAVERSE_STMT(GotoStmt, {})
-DEF_TRAVERSE_STMT(IfStmt, {})
-DEF_TRAVERSE_STMT(IndirectGotoStmt, {})
-DEF_TRAVERSE_STMT(LabelStmt, {})
-DEF_TRAVERSE_STMT(AttributedStmt, {})
-DEF_TRAVERSE_STMT(NullStmt, {})
-DEF_TRAVERSE_STMT(ObjCAtCatchStmt, {})
-DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, {})
-DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, {})
-DEF_TRAVERSE_STMT(ObjCAtThrowStmt, {})
-DEF_TRAVERSE_STMT(ObjCAtTryStmt, {})
-DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {})
-DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {})
-DEF_TRAVERSE_STMT(CXXForRangeStmt, {})
-DEF_TRAVERSE_STMT(MSDependentExistsStmt, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
-})
-DEF_TRAVERSE_STMT(ReturnStmt, {})
-DEF_TRAVERSE_STMT(SwitchStmt, {})
-DEF_TRAVERSE_STMT(WhileStmt, {})
-
-DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
- if (S->hasExplicitTemplateArgs()) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
- S->getNumTemplateArgs()));
- }
-})
-
-DEF_TRAVERSE_STMT(DeclRefExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
- TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
- S->getNumTemplateArgs()));
-})
-
-DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
- if (S->hasExplicitTemplateArgs()) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- S->getExplicitTemplateArgs().getTemplateArgs(),
- S->getNumTemplateArgs()));
- }
-})
-
-DEF_TRAVERSE_STMT(MemberExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
- TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
- S->getNumTemplateArgs()));
-})
-
-DEF_TRAVERSE_STMT(
- ImplicitCastExpr,
- {// We don't traverse the cast type, as it's not written in the
- // source code.
- })
-
-DEF_TRAVERSE_STMT(CStyleCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXConstCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXDynamicCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-// InitListExpr is a tricky one, because we want to do all our work on
-// the syntactic form of the listexpr, but this method takes the
-// semantic form by default. We can't use the macro helper because it
-// calls WalkUp*() on the semantic form, before our code can convert
-// to the syntactic form.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
- if (InitListExpr *Syn = S->getSyntacticForm())
- S = Syn;
- TRY_TO(WalkUpFromInitListExpr(S));
- StmtQueueAction StmtQueue(*this);
- // All we need are the default actions. FIXME: use a helper function.
- for (Stmt *SubStmt : S->children()) {
- StmtQueue.queue(SubStmt);
- }
- return true;
-}
-
-// GenericSelectionExpr is a special case because the types and expressions
-// are interleaved. We also need to watch out for null types (default
-// generic associations).
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr(
- GenericSelectionExpr *S) {
- TRY_TO(WalkUpFromGenericSelectionExpr(S));
- StmtQueueAction StmtQueue(*this);
- StmtQueue.queue(S->getControllingExpr());
- for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
- if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
- TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
- StmtQueue.queue(S->getAssocExpr(i));
- }
- return true;
-}
-
-// PseudoObjectExpr is a special case because of the wierdness with
-// syntactic expressions and opaque values.
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) {
- TRY_TO(WalkUpFromPseudoObjectExpr(S));
- StmtQueueAction StmtQueue(*this);
- StmtQueue.queue(S->getSyntacticForm());
- for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(),
- e = S->semantics_end();
- i != e; ++i) {
- Expr *sub = *i;
- if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub))
- sub = OVE->getSourceExpr();
- StmtQueue.queue(sub);
- }
- return true;
-}
-
-DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
- // This is called for code like 'return T()' where T is a built-in
- // (i.e. non-class) type.
- TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXNewExpr, {
- // The child-iterator will pick up the other arguments.
- TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(OffsetOfExpr, {
- // The child-iterator will pick up the expression representing
- // the field.
- // FIMXE: for code like offsetof(Foo, a.b.c), should we get
- // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c?
- TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, {
- // The child-iterator will pick up the arg if it's an expression,
- // but not if it's a type.
- if (S->isArgumentType())
- TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXTypeidExpr, {
- // The child-iterator will pick up the arg if it's an expression,
- // but not if it's a type.
- if (S->isTypeOperand())
- TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(MSPropertyRefExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXUuidofExpr, {
- // The child-iterator will pick up the arg if it's an expression,
- // but not if it's a type.
- if (S->isTypeOperand())
- TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(TypeTraitExpr, {
- for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I)
- TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
- TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(ExpressionTraitExpr,
- { StmtQueue.queue(S->getQueriedExpression()); })
-
-DEF_TRAVERSE_STMT(VAArgExpr, {
- // The child-iterator will pick up the expression argument.
- TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
- // This is called for code like 'return T()' where T is a class type.
- TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
-})
-
-// Walk only the visible parts of lambda expressions.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
- TRY_TO(WalkUpFromLambdaExpr(S));
-
- for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
- CEnd = S->explicit_capture_end();
- C != CEnd; ++C) {
- TRY_TO(TraverseLambdaCapture(S, C));
- }
-
- TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
- FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>();
-
- if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
- // Visit the whole type.
- TRY_TO(TraverseTypeLoc(TL));
- } else {
- if (S->hasExplicitParameters()) {
- // Visit parameters.
- for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
- TRY_TO(TraverseDecl(Proto.getParam(I)));
- }
- } else if (S->hasExplicitResultType()) {
- TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
- }
-
- auto *T = Proto.getTypePtr();
- for (const auto &E : T->exceptions()) {
- TRY_TO(TraverseType(E));
- }
-
- if (Expr *NE = T->getNoexceptExpr())
- TRY_TO(TraverseStmt(NE));
- }
-
- TRY_TO(TraverseLambdaBody(S));
- return true;
-}
-
-DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
- // This is called for code like 'T()', where T is a template argument.
- TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
-})
-
-// These expressions all might take explicit template arguments.
-// We traverse those if so. FIXME: implement these.
-DEF_TRAVERSE_STMT(CXXConstructExpr, {})
-DEF_TRAVERSE_STMT(CallExpr, {})
-DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
-
-// These exprs (most of them), do not need any action except iterating
-// over the children.
-DEF_TRAVERSE_STMT(AddrLabelExpr, {})
-DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
-DEF_TRAVERSE_STMT(BlockExpr, {
- TRY_TO(TraverseDecl(S->getBlockDecl()));
- return true; // no child statements to loop through.
-})
-DEF_TRAVERSE_STMT(ChooseExpr, {})
-DEF_TRAVERSE_STMT(CompoundLiteralExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
-})
-DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, {})
-DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, {})
-DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {})
-DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {})
-DEF_TRAVERSE_STMT(CXXDeleteExpr, {})
-DEF_TRAVERSE_STMT(ExprWithCleanups, {})
-DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {})
-DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {})
-DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
- TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc()));
- if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo())
- TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc()));
-})
-DEF_TRAVERSE_STMT(CXXThisExpr, {})
-DEF_TRAVERSE_STMT(CXXThrowExpr, {})
-DEF_TRAVERSE_STMT(UserDefinedLiteral, {})
-DEF_TRAVERSE_STMT(DesignatedInitExpr, {})
-DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {})
-DEF_TRAVERSE_STMT(ExtVectorElementExpr, {})
-DEF_TRAVERSE_STMT(GNUNullExpr, {})
-DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
-DEF_TRAVERSE_STMT(NoInitExpr, {})
-DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {})
-DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
- if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo())
- TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
-})
-DEF_TRAVERSE_STMT(ObjCIsaExpr, {})
-DEF_TRAVERSE_STMT(ObjCIvarRefExpr, {})
-DEF_TRAVERSE_STMT(ObjCMessageExpr, {
- if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo())
- TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
-})
-DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, {})
-DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, {})
-DEF_TRAVERSE_STMT(ObjCProtocolExpr, {})
-DEF_TRAVERSE_STMT(ObjCSelectorExpr, {})
-DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, {})
-DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-DEF_TRAVERSE_STMT(ParenExpr, {})
-DEF_TRAVERSE_STMT(ParenListExpr, {})
-DEF_TRAVERSE_STMT(PredefinedExpr, {})
-DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
-DEF_TRAVERSE_STMT(ConvertVectorExpr, {})
-DEF_TRAVERSE_STMT(StmtExpr, {})
-DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- if (S->hasExplicitTemplateArgs()) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
- S->getNumTemplateArgs()));
- }
-})
-
-DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- if (S->hasExplicitTemplateArgs()) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
- S->getNumTemplateArgs()));
- }
-})
-
-DEF_TRAVERSE_STMT(SEHTryStmt, {})
-DEF_TRAVERSE_STMT(SEHExceptStmt, {})
-DEF_TRAVERSE_STMT(SEHFinallyStmt, {})
-DEF_TRAVERSE_STMT(SEHLeaveStmt, {})
-DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
-
-DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
-DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
-DEF_TRAVERSE_STMT(TypoExpr, {})
-DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
-
-// These operators (all of them) do not need any action except
-// iterating over the children.
-DEF_TRAVERSE_STMT(BinaryConditionalOperator, {})
-DEF_TRAVERSE_STMT(ConditionalOperator, {})
-DEF_TRAVERSE_STMT(UnaryOperator, {})
-DEF_TRAVERSE_STMT(BinaryOperator, {})
-DEF_TRAVERSE_STMT(CompoundAssignOperator, {})
-DEF_TRAVERSE_STMT(CXXNoexceptExpr, {})
-DEF_TRAVERSE_STMT(PackExpansionExpr, {})
-DEF_TRAVERSE_STMT(SizeOfPackExpr, {})
-DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
-DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
-DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
-DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
-DEF_TRAVERSE_STMT(CXXFoldExpr, {})
-DEF_TRAVERSE_STMT(AtomicExpr, {})
-
-// These literals (all of them) do not need any action.
-DEF_TRAVERSE_STMT(IntegerLiteral, {})
-DEF_TRAVERSE_STMT(CharacterLiteral, {})
-DEF_TRAVERSE_STMT(FloatingLiteral, {})
-DEF_TRAVERSE_STMT(ImaginaryLiteral, {})
-DEF_TRAVERSE_STMT(StringLiteral, {})
-DEF_TRAVERSE_STMT(ObjCStringLiteral, {})
-DEF_TRAVERSE_STMT(ObjCBoxedExpr, {})
-DEF_TRAVERSE_STMT(ObjCArrayLiteral, {})
-DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, {})
-
-// Traverse OpenCL: AsType, Convert.
-DEF_TRAVERSE_STMT(AsTypeExpr, {})
-
-// OpenMP directives.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective(
- OMPExecutableDirective *S) {
- for (auto *C : S->clauses()) {
- TRY_TO(TraverseOMPClause(C));
- }
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) {
- return TraverseOMPExecutableDirective(S);
-}
-
-DEF_TRAVERSE_STMT(OMPParallelDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPSimdDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPForDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPForSimdDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPSectionsDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPSectionDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPSingleDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPMasterDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPCriticalDirective, {
- TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName()));
- TRY_TO(TraverseOMPExecutableDirective(S));
-})
-
-DEF_TRAVERSE_STMT(OMPParallelForDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPParallelForSimdDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTaskDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTaskyieldDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPBarrierDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTaskwaitDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTaskgroupDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPCancellationPointDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPCancelDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPFlushDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPOrderedDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPAtomicDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTargetDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTeamsDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-// OpenMP clauses.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
- if (!C)
- return true;
- switch (C->getClauseKind()) {
-#define OPENMP_CLAUSE(Name, Class) \
- case OMPC_##Name: \
- TRY_TO(Visit##Class(static_cast<Class *>(C))); \
- break;
-#include "clang/Basic/OpenMPKinds.def"
- case OMPC_threadprivate:
- case OMPC_unknown:
- break;
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
- TRY_TO(TraverseStmt(C->getCondition()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) {
- TRY_TO(TraverseStmt(C->getCondition()));
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
- TRY_TO(TraverseStmt(C->getNumThreads()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) {
- TRY_TO(TraverseStmt(C->getSafelen()));
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) {
- TRY_TO(TraverseStmt(C->getNumForLoops()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *) {
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
- TRY_TO(TraverseStmt(C->getChunkSize()));
- TRY_TO(TraverseStmt(C->getHelperChunkSize()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPNowaitClause(OMPNowaitClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPUntiedClause(OMPUntiedClause *) {
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
- return true;
-}
-
-template <typename Derived>
-template <typename T>
-bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
- for (auto *E : Node->varlists()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->private_copies()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause(
- OMPFirstprivateClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->private_copies()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->inits()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause(
- OMPLastprivateClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->private_copies()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->source_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->destination_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->assignment_ops()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
- TRY_TO(TraverseStmt(C->getStep()));
- TRY_TO(TraverseStmt(C->getCalcStep()));
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->inits()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->updates()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->finals()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPAlignedClause(OMPAlignedClause *C) {
- TRY_TO(TraverseStmt(C->getAlignment()));
- TRY_TO(VisitOMPClauseList(C));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->source_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->destination_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->assignment_ops()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
- OMPCopyprivateClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->source_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->destination_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->assignment_ops()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
- TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->lhs_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->rhs_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->reduction_ops()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- return true;
-}
-
-// FIXME: look at the following tricky-seeming exprs to see if we
-// need to recurse on anything. These are ones that have methods
-// returning decls or qualtypes or nestednamespecifier -- though I'm
-// not sure if they own them -- or just seemed very complicated, or
-// had lots of sub-types to explore.
-//
-// VisitOverloadExpr and its children: recurse on template args? etc?
-
-// FIXME: go through all the stmts and exprs again, and see which of them
-// create new types, and recurse on the types (TypeLocs?) of those.
-// Candidates:
-//
-// http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html
-// http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html
-// http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html
-// Every class that has getQualifier.
-
-#undef DEF_TRAVERSE_STMT
-
-#undef TRY_TO
-
-#undef RecursiveASTVisitor
-
-} // end namespace clang
-
-#endif // LLVM_CLANG_LIBCLANG_RECURSIVEASTVISITOR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Decl.h b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
index e06b58b..029c118 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Decl.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
@@ -21,11 +21,13 @@
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Linkage.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/OperatorKinds.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/TrailingObjects.h"
namespace clang {
struct ASTTemplateArgumentListInfo;
@@ -37,7 +39,6 @@ class FunctionTemplateDecl;
class FunctionTemplateSpecializationInfo;
class LabelStmt;
class MemberSpecializationInfo;
-class Module;
class NestedNameSpecifier;
class ParmVarDecl;
class Stmt;
@@ -318,7 +319,8 @@ public:
NamedDecl *getUnderlyingDecl() {
// Fast-path the common case.
if (this->getKind() != UsingShadow &&
- this->getKind() != ObjCCompatibleAlias)
+ this->getKind() != ObjCCompatibleAlias &&
+ this->getKind() != NamespaceAlias)
return this;
return getUnderlyingDeclImpl();
@@ -462,25 +464,15 @@ public:
}
/// \brief Get the original (first) namespace declaration.
- NamespaceDecl *getOriginalNamespace() {
- if (isFirstDecl())
- return this;
-
- return AnonOrFirstNamespaceAndInline.getPointer();
- }
+ NamespaceDecl *getOriginalNamespace();
/// \brief Get the original (first) namespace declaration.
- const NamespaceDecl *getOriginalNamespace() const {
- if (isFirstDecl())
- return this;
-
- return AnonOrFirstNamespaceAndInline.getPointer();
- }
+ const NamespaceDecl *getOriginalNamespace() const;
/// \brief Return true if this declaration is an original (first) declaration
/// of the namespace. This is false for non-original (subsequent) namespace
/// declarations and anonymous namespaces.
- bool isOriginalNamespace() const { return isFirstDecl(); }
+ bool isOriginalNamespace() const;
/// \brief Retrieve the anonymous namespace nested inside this namespace,
/// if any.
@@ -572,8 +564,7 @@ struct QualifierInfo {
/// setTemplateParameterListsInfo - Sets info about "outer" template
/// parameter lists.
void setTemplateParameterListsInfo(ASTContext &Context,
- unsigned NumTPLists,
- TemplateParameterList **TPLists);
+ ArrayRef<TemplateParameterList *> TPLists);
private:
// Copy constructor and copy assignment are disabled.
@@ -658,8 +649,8 @@ public:
assert(index < getNumTemplateParameterLists());
return getExtInfo()->TemplParamLists[index];
}
- void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
- TemplateParameterList **TPLists);
+ void setTemplateParameterListsInfo(ASTContext &Context,
+ ArrayRef<TemplateParameterList *> TPLists);
SourceLocation getTypeSpecStartLoc() const;
@@ -728,17 +719,14 @@ public:
};
protected:
- /// \brief Placeholder type used in Init to denote an unparsed C++ default
- /// argument.
- struct UnparsedDefaultArgument;
-
- /// \brief Placeholder type used in Init to denote an uninstantiated C++
- /// default argument.
- struct UninstantiatedDefaultArgument;
-
- typedef llvm::PointerUnion4<Stmt *, EvaluatedStmt *,
- UnparsedDefaultArgument *,
- UninstantiatedDefaultArgument *> InitType;
+ // A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we
+ // have allocated the auxilliary struct of information there.
+ //
+ // TODO: It is a bit unfortunate to use a PointerUnion inside the VarDecl for
+ // this as *many* VarDecls are ParmVarDecls that don't have default
+ // arguments. We could save some space by moving this pointer union to be
+ // allocated in trailing space when necessary.
+ typedef llvm::PointerUnion<Stmt *, EvaluatedStmt *> InitType;
/// \brief The initializer for this variable or, for a ParmVarDecl, the
/// C++ default argument.
@@ -762,6 +750,13 @@ private:
protected:
enum { NumParameterIndexBits = 8 };
+ enum DefaultArgKind {
+ DAK_None,
+ DAK_Unparsed,
+ DAK_Uninstantiated,
+ DAK_Normal
+ };
+
class ParmVarDeclBitfields {
friend class ParmVarDecl;
friend class ASTDeclReader;
@@ -772,6 +767,12 @@ protected:
/// prior declaration.
unsigned HasInheritedDefaultArg : 1;
+ /// Describes the kind of default argument for this parameter. By default
+ /// this is none. If this is normal, then the default argument is stored in
+ /// the \c VarDecl initalizer expression unless we were unble to parse
+ /// (even an invalid) expression for the default argument.
+ unsigned DefaultArgKind : 2;
+
/// Whether this parameter undergoes K&R argument promotion.
unsigned IsKNRPromoted : 1;
@@ -815,6 +816,9 @@ protected:
/// \brief Whether this variable is (C++0x) constexpr.
unsigned IsConstexpr : 1;
+ /// \brief Whether this variable is a (C++ Concepts TS) concept.
+ unsigned IsConcept : 1;
+
/// \brief Whether this variable is the implicit variable for a lambda
/// init-capture.
unsigned IsInitCapture : 1;
@@ -1062,47 +1066,14 @@ public:
/// declaration it is attached to. Also get that declaration.
const Expr *getAnyInitializer(const VarDecl *&D) const;
- bool hasInit() const {
- return !Init.isNull() && (Init.is<Stmt *>() || Init.is<EvaluatedStmt *>());
- }
+ bool hasInit() const;
const Expr *getInit() const {
- if (Init.isNull())
- return nullptr;
-
- const Stmt *S = Init.dyn_cast<Stmt *>();
- if (!S) {
- if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
- S = ES->Value;
- }
- return (const Expr*) S;
- }
- Expr *getInit() {
- if (Init.isNull())
- return nullptr;
-
- Stmt *S = Init.dyn_cast<Stmt *>();
- if (!S) {
- if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
- S = ES->Value;
- }
-
- return (Expr*) S;
+ return const_cast<VarDecl *>(this)->getInit();
}
+ Expr *getInit();
/// \brief Retrieve the address of the initializer expression.
- Stmt **getInitAddress() {
- if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
- return &ES->Value;
-
- // This union hack tip-toes around strict-aliasing rules.
- union {
- InitType *InitPtr;
- Stmt **StmtPtr;
- };
-
- InitPtr = &Init;
- return StmtPtr;
- }
+ Stmt **getInitAddress();
void setInit(Expr *I);
@@ -1124,33 +1095,18 @@ public:
/// \brief Return the already-evaluated value of this variable's
/// initializer, or NULL if the value is not yet known. Returns pointer
/// to untyped APValue if the value could not be evaluated.
- APValue *getEvaluatedValue() const {
- if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
- if (Eval->WasEvaluated)
- return &Eval->Evaluated;
-
- return nullptr;
- }
+ APValue *getEvaluatedValue() const;
/// \brief Determines whether it is already known whether the
/// initializer is an integral constant expression or not.
- bool isInitKnownICE() const {
- if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
- return Eval->CheckedICE;
-
- return false;
- }
+ bool isInitKnownICE() const;
/// \brief Determines whether the initializer is an integral constant
/// expression, or in C++11, whether the initializer is a constant
/// expression.
///
/// \pre isInitKnownICE()
- bool isInitICE() const {
- assert(isInitKnownICE() &&
- "Check whether we already know that the initializer is an ICE");
- return Init.get<EvaluatedStmt *>()->IsICE;
- }
+ bool isInitICE() const;
/// \brief Determine whether the value of the initializer attached to this
/// declaration is an integral constant expression.
@@ -1238,6 +1194,15 @@ public:
NonParmVarDeclBits.IsConstexpr = IC;
}
+ /// Whether this variable is (C++ Concepts TS) concept.
+ bool isConcept() const {
+ return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConcept;
+ }
+ void setConcept(bool IC) {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.IsConcept = IC;
+ }
+
/// Whether this variable is the implicit variable for a lambda init-capture.
bool isInitCapture() const {
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsInitCapture;
@@ -1342,6 +1307,7 @@ protected:
TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
: VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) {
assert(ParmVarDeclBits.HasInheritedDefaultArg == false);
+ assert(ParmVarDeclBits.DefaultArgKind == DAK_None);
assert(ParmVarDeclBits.IsKNRPromoted == false);
assert(ParmVarDeclBits.IsObjCMethodParam == false);
setDefaultArg(DefArg);
@@ -1416,29 +1382,20 @@ public:
return const_cast<ParmVarDecl *>(this)->getDefaultArg();
}
- void setDefaultArg(Expr *defarg) {
- Init = reinterpret_cast<Stmt *>(defarg);
- }
+ void setDefaultArg(Expr *defarg);
/// \brief Retrieve the source range that covers the entire default
/// argument.
SourceRange getDefaultArgRange() const;
- void setUninstantiatedDefaultArg(Expr *arg) {
- Init = reinterpret_cast<UninstantiatedDefaultArgument *>(arg);
- }
- Expr *getUninstantiatedDefaultArg() {
- return (Expr *)Init.get<UninstantiatedDefaultArgument *>();
- }
+ void setUninstantiatedDefaultArg(Expr *arg);
+ Expr *getUninstantiatedDefaultArg();
const Expr *getUninstantiatedDefaultArg() const {
- return (const Expr *)Init.get<UninstantiatedDefaultArgument *>();
+ return const_cast<ParmVarDecl *>(this)->getUninstantiatedDefaultArg();
}
/// hasDefaultArg - Determines whether this parameter has a default argument,
/// either parsed or not.
- bool hasDefaultArg() const {
- return getInit() || hasUnparsedDefaultArg() ||
- hasUninstantiatedDefaultArg();
- }
+ bool hasDefaultArg() const;
/// hasUnparsedDefaultArg - Determines whether this parameter has a
/// default argument that has not yet been parsed. This will occur
@@ -1451,11 +1408,11 @@ public:
/// }; // x has a regular default argument now
/// @endcode
bool hasUnparsedDefaultArg() const {
- return Init.is<UnparsedDefaultArgument*>();
+ return ParmVarDeclBits.DefaultArgKind == DAK_Unparsed;
}
bool hasUninstantiatedDefaultArg() const {
- return Init.is<UninstantiatedDefaultArgument*>();
+ return ParmVarDeclBits.DefaultArgKind == DAK_Uninstantiated;
}
/// setUnparsedDefaultArg - Specify that this parameter has an
@@ -1463,7 +1420,9 @@ public:
/// real default argument via setDefaultArg when the class
/// definition enclosing the function declaration that owns this
/// default argument is completed.
- void setUnparsedDefaultArg() { Init = (UnparsedDefaultArgument *)nullptr; }
+ void setUnparsedDefaultArg() {
+ ParmVarDeclBits.DefaultArgKind = DAK_Unparsed;
+ }
bool hasInheritedDefaultArg() const {
return ParmVarDeclBits.HasInheritedDefaultArg;
@@ -1546,25 +1505,25 @@ private:
LazyDeclStmtPtr Body;
- // FIXME: This can be packed into the bitfields in Decl.
- // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
+ // FIXME: This can be packed into the bitfields in DeclContext.
+ // NOTE: VC++ packs bitfields poorly if the types differ.
unsigned SClass : 2;
- bool IsInline : 1;
- bool IsInlineSpecified : 1;
- bool IsVirtualAsWritten : 1;
- bool IsPure : 1;
- bool HasInheritedPrototype : 1;
- bool HasWrittenPrototype : 1;
- bool IsDeleted : 1;
- bool IsTrivial : 1; // sunk from CXXMethodDecl
- bool IsDefaulted : 1; // sunk from CXXMethoDecl
- bool IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
- bool HasImplicitReturnZero : 1;
- bool IsLateTemplateParsed : 1;
- bool IsConstexpr : 1;
+ unsigned IsInline : 1;
+ unsigned IsInlineSpecified : 1;
+ unsigned IsVirtualAsWritten : 1;
+ unsigned IsPure : 1;
+ unsigned HasInheritedPrototype : 1;
+ unsigned HasWrittenPrototype : 1;
+ unsigned IsDeleted : 1;
+ unsigned IsTrivial : 1; // sunk from CXXMethodDecl
+ unsigned IsDefaulted : 1; // sunk from CXXMethoDecl
+ unsigned IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
+ unsigned HasImplicitReturnZero : 1;
+ unsigned IsLateTemplateParsed : 1;
+ unsigned IsConstexpr : 1;
/// \brief Indicates if the function uses __try.
- bool UsesSEHTry : 1;
+ unsigned UsesSEHTry : 1;
/// \brief Indicates if the function was a definition but its body was
/// skipped.
@@ -1835,7 +1794,7 @@ public:
bool isConstexpr() const { return IsConstexpr; }
void setConstexpr(bool IC) { IsConstexpr = IC; }
- /// Whether this is a (C++11) constexpr function or constexpr constructor.
+ /// \brief Indicates the function uses __try.
bool usesSEHTry() const { return UsesSEHTry; }
void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }
@@ -2084,9 +2043,7 @@ public:
/// \brief If this function is an instantiation of a member function of a
/// class template specialization, retrieves the member specialization
/// information.
- MemberSpecializationInfo *getMemberSpecializationInfo() const {
- return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
- }
+ MemberSpecializationInfo *getMemberSpecializationInfo() const;
/// \brief Specify that this record is an instantiation of the
/// member function FD.
@@ -2107,13 +2064,9 @@ public:
/// FunctionDecl that describes the function template,
/// getDescribedFunctionTemplate() retrieves the
/// FunctionTemplateDecl from a FunctionDecl.
- FunctionTemplateDecl *getDescribedFunctionTemplate() const {
- return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl*>();
- }
+ FunctionTemplateDecl *getDescribedFunctionTemplate() const;
- void setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
- TemplateOrSpecialization = Template;
- }
+ void setDescribedFunctionTemplate(FunctionTemplateDecl *Template);
/// \brief Determine whether this function is a function template
/// specialization.
@@ -2128,10 +2081,7 @@ public:
/// \brief If this function is actually a function template specialization,
/// retrieve information about this function template specialization.
/// Otherwise, returns NULL.
- FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const {
- return TemplateOrSpecialization.
- dyn_cast<FunctionTemplateSpecializationInfo*>();
- }
+ FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const;
/// \brief Determines whether this function is a function template
/// specialization or a member of a class template specialization that can
@@ -2208,10 +2158,7 @@ public:
const TemplateArgumentListInfo &TemplateArgs);
DependentFunctionTemplateSpecializationInfo *
- getDependentSpecializationInfo() const {
- return TemplateOrSpecialization.
- dyn_cast<DependentFunctionTemplateSpecializationInfo*>();
- }
+ getDependentSpecializationInfo() const;
/// \brief Determine what kind of template instantiation this function
/// represents.
@@ -2487,15 +2434,15 @@ public:
/// IndirectFieldDecl - An instance of this class is created to represent a
/// field injected from an anonymous union/struct into the parent scope.
/// IndirectFieldDecl are always implicit.
-class IndirectFieldDecl : public ValueDecl {
+class IndirectFieldDecl : public ValueDecl,
+ public Mergeable<IndirectFieldDecl> {
void anchor() override;
NamedDecl **Chaining;
unsigned ChainingSize;
- IndirectFieldDecl(DeclContext *DC, SourceLocation L,
+ IndirectFieldDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T,
- NamedDecl **CH, unsigned CHS)
- : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {}
+ NamedDecl **CH, unsigned CHS);
public:
static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,
@@ -2525,6 +2472,9 @@ public:
return dyn_cast<VarDecl>(*chain_begin());
}
+ IndirectFieldDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const IndirectFieldDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == IndirectField; }
@@ -2762,12 +2712,12 @@ private:
/// declaration specifier for variables, it points to the first VarDecl (used
/// for mangling);
/// otherwise, it is a null (TypedefNameDecl) pointer.
- llvm::PointerUnion<NamedDecl *, ExtInfo *> NamedDeclOrQualifier;
+ llvm::PointerUnion<TypedefNameDecl *, ExtInfo *> TypedefNameDeclOrQualifier;
- bool hasExtInfo() const { return NamedDeclOrQualifier.is<ExtInfo *>(); }
- ExtInfo *getExtInfo() { return NamedDeclOrQualifier.get<ExtInfo *>(); }
+ bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo *>(); }
+ ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo *>(); }
const ExtInfo *getExtInfo() const {
- return NamedDeclOrQualifier.get<ExtInfo *>();
+ return TypedefNameDeclOrQualifier.get<ExtInfo *>();
}
protected:
@@ -2778,7 +2728,7 @@ protected:
TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false),
IsEmbeddedInDeclarator(false), IsFreeStanding(false),
IsCompleteDefinitionRequired(false),
- NamedDeclOrQualifier((NamedDecl *)nullptr) {
+ TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
assert((DK != Enum || TK == TTK_Enum) &&
"EnumDecl not matched with TTK_Enum");
setPreviousDecl(PrevDecl);
@@ -2925,22 +2875,11 @@ public:
return (getDeclName() || getTypedefNameForAnonDecl());
}
- bool hasDeclaratorForAnonDecl() const {
- return dyn_cast_or_null<DeclaratorDecl>(
- NamedDeclOrQualifier.get<NamedDecl *>());
- }
- DeclaratorDecl *getDeclaratorForAnonDecl() const {
- return hasExtInfo() ? nullptr : dyn_cast_or_null<DeclaratorDecl>(
- NamedDeclOrQualifier.get<NamedDecl *>());
- }
-
TypedefNameDecl *getTypedefNameForAnonDecl() const {
- return hasExtInfo() ? nullptr : dyn_cast_or_null<TypedefNameDecl>(
- NamedDeclOrQualifier.get<NamedDecl *>());
+ return hasExtInfo() ? nullptr
+ : TypedefNameDeclOrQualifier.get<TypedefNameDecl *>();
}
- void setDeclaratorForAnonDecl(DeclaratorDecl *DD) { NamedDeclOrQualifier = DD; }
-
void setTypedefNameForAnonDecl(TypedefNameDecl *TDD);
/// \brief Retrieve the nested-name-specifier that qualifies the name of this
@@ -2967,8 +2906,8 @@ public:
assert(i < getNumTemplateParameterLists());
return getExtInfo()->TemplParamLists[i];
}
- void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
- TemplateParameterList **TPLists);
+ void setTemplateParameterListsInfo(ASTContext &Context,
+ ArrayRef<TemplateParameterList *> TPLists);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -3301,7 +3240,14 @@ public:
bool hasVolatileMember() const { return HasVolatileMember; }
void setHasVolatileMember (bool val) { HasVolatileMember = val; }
-
+
+ bool hasLoadedFieldsFromExternalStorage() const {
+ return LoadedFieldsFromExternalStorage;
+ }
+ void setHasLoadedFieldsFromExternalStorage(bool val) {
+ LoadedFieldsFromExternalStorage = val;
+ }
+
/// \brief Determines whether this declaration represents the
/// injected class name.
///
@@ -3475,7 +3421,7 @@ private:
Stmt *Body;
TypeSourceInfo *SignatureAsWritten;
- Capture *Captures;
+ const Capture *Captures;
unsigned NumCaptures;
unsigned ManglingNumber;
@@ -3581,10 +3527,8 @@ public:
bool capturesVariable(const VarDecl *var) const;
- void setCaptures(ASTContext &Context,
- const Capture *begin,
- const Capture *end,
- bool capturesCXXThis);
+ void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
+ bool CapturesCXXThis);
unsigned getBlockManglingNumber() const {
return ManglingNumber;
@@ -3613,7 +3557,15 @@ public:
/// \brief This represents the body of a CapturedStmt, and serves as its
/// DeclContext.
-class CapturedDecl : public Decl, public DeclContext {
+class CapturedDecl final
+ : public Decl,
+ public DeclContext,
+ private llvm::TrailingObjects<CapturedDecl, ImplicitParamDecl *> {
+protected:
+ size_t numTrailingObjects(OverloadToken<ImplicitParamDecl>) {
+ return NumParams;
+ }
+
private:
/// \brief The number of parameters to the outlined function.
unsigned NumParams;
@@ -3622,13 +3574,14 @@ private:
/// \brief The body of the outlined function.
llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow;
- explicit CapturedDecl(DeclContext *DC, unsigned NumParams)
- : Decl(Captured, DC, SourceLocation()), DeclContext(Captured),
- NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) { }
+ explicit CapturedDecl(DeclContext *DC, unsigned NumParams);
+
+ ImplicitParamDecl *const *getParams() const {
+ return getTrailingObjects<ImplicitParamDecl *>();
+ }
- ImplicitParamDecl **getParams() const {
- return reinterpret_cast<ImplicitParamDecl **>(
- const_cast<CapturedDecl *>(this) + 1);
+ ImplicitParamDecl **getParams() {
+ return getTrailingObjects<ImplicitParamDecl *>();
}
public:
@@ -3637,11 +3590,11 @@ public:
static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumParams);
- Stmt *getBody() const override { return BodyAndNothrow.getPointer(); }
- void setBody(Stmt *B) { BodyAndNothrow.setPointer(B); }
+ Stmt *getBody() const override;
+ void setBody(Stmt *B);
- bool isNothrow() const { return BodyAndNothrow.getInt(); }
- void setNothrow(bool Nothrow = true) { BodyAndNothrow.setInt(Nothrow); }
+ bool isNothrow() const;
+ void setNothrow(bool Nothrow = true);
unsigned getNumParams() const { return NumParams; }
@@ -3666,7 +3619,7 @@ public:
}
unsigned getContextParamPosition() const { return ContextParam; }
- typedef ImplicitParamDecl **param_iterator;
+ typedef ImplicitParamDecl *const *param_iterator;
typedef llvm::iterator_range<param_iterator> param_range;
/// \brief Retrieve an iterator pointing to the first parameter decl.
@@ -3689,6 +3642,7 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend TrailingObjects;
};
/// \brief Describes a module import declaration, which makes the contents
@@ -3701,7 +3655,8 @@ public:
///
/// Import declarations can also be implicitly generated from
/// \#include/\#import directives.
-class ImportDecl : public Decl {
+class ImportDecl final : public Decl,
+ llvm::TrailingObjects<ImportDecl, SourceLocation> {
/// \brief The imported module, along with a bit that indicates whether
/// we have source-location information for each identifier in the module
/// name.
@@ -3717,7 +3672,8 @@ class ImportDecl : public Decl {
friend class ASTReader;
friend class ASTDeclReader;
friend class ASTContext;
-
+ friend TrailingObjects;
+
ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
index 6b6ac3f..2d6e84a 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
@@ -70,8 +70,15 @@ namespace clang {
/// Decl - This represents one declaration (or definition), e.g. a variable,
/// typedef, function, struct, etc.
///
+/// Note: There are objects tacked on before the *beginning* of Decl
+/// (and its subclasses) in its Decl::operator new(). Proper alignment
+/// of all subclasses (not requiring more than DeclObjAlignment) is
+/// asserted in DeclBase.cpp.
class Decl {
public:
+ /// \brief Alignment guaranteed when allocating Decl and any subtypes.
+ enum { DeclObjAlignment = llvm::AlignOf<uint64_t>::Alignment };
+
/// \brief Lists the kind of concrete classes of Decl.
enum Kind {
#define DECL(DERIVED, BASE) DERIVED,
@@ -106,6 +113,9 @@ public:
/// Tags, declared with 'struct foo;' and referenced with
/// 'struct foo'. All tags are also types. This is what
/// elaborated-type-specifiers look for in C.
+ /// This also contains names that conflict with tags in the
+ /// same scope but that are otherwise ordinary names (non-type
+ /// template parameters and indirect field declarations).
IDNS_Tag = 0x0002,
/// Types, declared with 'struct foo', typedefs, etc.
@@ -124,7 +134,7 @@ public:
IDNS_Namespace = 0x0010,
/// Ordinary names. In C, everything that's not a label, tag,
- /// or member ends up here.
+ /// member, or function-local extern ends up here.
IDNS_Ordinary = 0x0020,
/// Objective C \@protocol.
@@ -153,7 +163,9 @@ public:
/// This declaration is a function-local extern declaration of a
/// variable or function. This may also be IDNS_Ordinary if it
- /// has been declared outside any function.
+ /// has been declared outside any function. These act mostly like
+ /// invisible friend declarations, but are also visible to unqualified
+ /// lookup within the scope of the declaring function.
IDNS_LocalExtern = 0x0800
};
@@ -468,8 +480,7 @@ public:
template <typename T>
llvm::iterator_range<specific_attr_iterator<T>> specific_attrs() const {
- return llvm::iterator_range<specific_attr_iterator<T>>(
- specific_attr_begin<T>(), specific_attr_end<T>());
+ return llvm::make_range(specific_attr_begin<T>(), specific_attr_end<T>());
}
template <typename T>
@@ -721,6 +732,15 @@ public:
return getParentFunctionOrMethod() == nullptr;
}
+ /// \brief Returns true if this declaration lexically is inside a function.
+ /// It recognizes non-defining declarations as well as members of local
+ /// classes:
+ /// \code
+ /// void foo() { void bar(); }
+ /// void foo2() { class ABC { void bar(); }; }
+ /// \endcode
+ bool isLexicallyWithinFunctionOrMethod() const;
+
/// \brief If this decl is defined inside a function/method/block it returns
/// the corresponding DeclContext, otherwise it returns null.
const DeclContext *getParentFunctionOrMethod() const;
@@ -1126,6 +1146,11 @@ class DeclContext {
/// that are missing from the lookup table.
mutable bool HasLazyExternalLexicalLookups : 1;
+ /// \brief If \c true, lookups should only return identifier from
+ /// DeclContext scope (for example TranslationUnit). Used in
+ /// LookupQualifiedName()
+ mutable bool UseQualifiedLookup : 1;
+
/// \brief Pointer to the data structure used to lookup declarations
/// within this context (or a DependentStoredDeclsMap if this is a
/// dependent context). We maintain the invariant that, if the map
@@ -1160,6 +1185,7 @@ protected:
ExternalVisibleStorage(false),
NeedToReconcileExternalVisibleStorage(false),
HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false),
+ UseQualifiedLookup(false),
LookupPtr(nullptr), FirstDecl(nullptr), LastDecl(nullptr) {}
public:
@@ -1740,6 +1766,16 @@ public:
D == LastDecl);
}
+ bool setUseQualifiedLookup(bool use = true) {
+ bool old_value = UseQualifiedLookup;
+ UseQualifiedLookup = use;
+ return old_value;
+ }
+
+ bool shouldUseQualifiedLookup() const {
+ return UseQualifiedLookup;
+ }
+
static bool classof(const Decl *D);
static bool classof(const DeclContext *D) { return true; }
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
index 08451c0..7c54901 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
@@ -1344,9 +1344,7 @@ public:
/// \brief If this class is an instantiation of a member class of a
/// class template specialization, retrieves the member specialization
/// information.
- MemberSpecializationInfo *getMemberSpecializationInfo() const {
- return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>();
- }
+ MemberSpecializationInfo *getMemberSpecializationInfo() const;
/// \brief Specify that this record is an instantiation of the
/// member class \p RD.
@@ -1364,13 +1362,9 @@ public:
/// CXXRecordDecl that from a ClassTemplateDecl, while
/// getDescribedClassTemplate() retrieves the ClassTemplateDecl from
/// a CXXRecordDecl.
- ClassTemplateDecl *getDescribedClassTemplate() const {
- return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl*>();
- }
+ ClassTemplateDecl *getDescribedClassTemplate() const;
- void setDescribedClassTemplate(ClassTemplateDecl *Template) {
- TemplateOrInstantiation = Template;
- }
+ void setDescribedClassTemplate(ClassTemplateDecl *Template);
/// \brief Determine whether this particular class is a specialization or
/// instantiation of a class template or member class of a class template,
@@ -1468,8 +1462,8 @@ public:
/// \param BaseDefinition the definition of the base class
///
/// \returns true if this base matched the search criteria
- typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition,
- void *UserData);
+ typedef llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)>
+ ForallBasesCallback;
/// \brief Determines if the given callback holds for all the direct
/// or indirect base classes of this type.
@@ -1481,13 +1475,10 @@ public:
/// class of this type, or if \p AllowShortCircuit is true then until a call
/// returns false.
///
- /// \param UserData Passed as the second argument of every call to
- /// \p BaseMatches.
- ///
/// \param AllowShortCircuit if false, forces the callback to be called
/// for every base class, even if a dependent or non-matching base was
/// found.
- bool forallBases(ForallBasesCallback *BaseMatches, void *UserData,
+ bool forallBases(ForallBasesCallback BaseMatches,
bool AllowShortCircuit = true) const;
/// \brief Function type used by lookupInBases() to determine whether a
@@ -1499,13 +1490,9 @@ public:
/// \param Path the current path, from the most-derived class down to the
/// base named by the \p Specifier.
///
- /// \param UserData a single pointer to user-specified data, provided to
- /// lookupInBases().
- ///
/// \returns true if this base matched the search criteria, false otherwise.
- typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *UserData);
+ typedef llvm::function_ref<bool(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path)> BaseMatchesCallback;
/// \brief Look for entities within the base classes of this C++ class,
/// transitively searching all base class subobjects.
@@ -1520,14 +1507,12 @@ public:
/// \param BaseMatches callback function used to determine whether a given
/// base matches the user-defined search criteria.
///
- /// \param UserData user data pointer that will be provided to \p BaseMatches.
- ///
/// \param Paths used to record the paths from this class to its base class
/// subobjects that match the search criteria.
///
/// \returns true if there exists any path from this class to a base class
/// subobject that matches the search criteria.
- bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData,
+ bool lookupInBases(BaseMatchesCallback BaseMatches,
CXXBasePaths &Paths) const;
/// \brief Base-class lookup callback that determines whether the given
@@ -1535,10 +1520,10 @@ public:
///
/// This callback can be used with \c lookupInBases() to determine whether
/// a given derived class has is a base class subobject of a particular type.
- /// The user data pointer should refer to the canonical CXXRecordDecl of the
+ /// The base record pointer should refer to the canonical CXXRecordDecl of the
/// base class that we are searching for.
static bool FindBaseClass(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *BaseRecord);
+ CXXBasePath &Path, const CXXRecordDecl *BaseRecord);
/// \brief Base-class lookup callback that determines whether the
/// given base class specifier refers to a specific class
@@ -1546,39 +1531,38 @@ public:
///
/// This callback can be used with \c lookupInBases() to determine
/// whether a given derived class has is a virtual base class
- /// subobject of a particular type. The user data pointer should
+ /// subobject of a particular type. The base record pointer should
/// refer to the canonical CXXRecordDecl of the base class that we
/// are searching for.
static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *BaseRecord);
+ CXXBasePath &Path,
+ const CXXRecordDecl *BaseRecord);
/// \brief Base-class lookup callback that determines whether there exists
/// a tag with the given name.
///
/// This callback can be used with \c lookupInBases() to find tag members
- /// of the given name within a C++ class hierarchy. The user data pointer
- /// is an opaque \c DeclarationName pointer.
+ /// of the given name within a C++ class hierarchy.
static bool FindTagMember(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *Name);
+ CXXBasePath &Path, DeclarationName Name);
/// \brief Base-class lookup callback that determines whether there exists
/// a member with the given name.
///
/// This callback can be used with \c lookupInBases() to find members
- /// of the given name within a C++ class hierarchy. The user data pointer
- /// is an opaque \c DeclarationName pointer.
+ /// of the given name within a C++ class hierarchy.
static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *Name);
+ CXXBasePath &Path, DeclarationName Name);
/// \brief Base-class lookup callback that determines whether there exists
/// a member with the given name that can be used in a nested-name-specifier.
///
- /// This callback can be used with \c lookupInBases() to find membes of
+ /// This callback can be used with \c lookupInBases() to find members of
/// the given name within a C++ class hierarchy that can occur within
/// nested-name-specifiers.
static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *UserData);
+ DeclarationName Name);
/// \brief Retrieve the final overriders for each virtual member
/// function in the class hierarchy where this class is the
@@ -1898,7 +1882,8 @@ public:
/// B(A& a) : A(a), f(3.14159) { }
/// };
/// \endcode
-class CXXCtorInitializer {
+class CXXCtorInitializer final
+ : private llvm::TrailingObjects<CXXCtorInitializer, VarDecl *> {
/// \brief Either the base class name/delegating constructor type (stored as
/// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field
/// (IndirectFieldDecl*) being initialized.
@@ -2114,24 +2099,26 @@ public:
/// describe an array member initialization.
VarDecl *getArrayIndex(unsigned I) {
assert(I < getNumArrayIndices() && "Out of bounds member array index");
- return reinterpret_cast<VarDecl **>(this + 1)[I];
+ return getTrailingObjects<VarDecl *>()[I];
}
const VarDecl *getArrayIndex(unsigned I) const {
assert(I < getNumArrayIndices() && "Out of bounds member array index");
- return reinterpret_cast<const VarDecl * const *>(this + 1)[I];
+ return getTrailingObjects<VarDecl *>()[I];
}
void setArrayIndex(unsigned I, VarDecl *Index) {
assert(I < getNumArrayIndices() && "Out of bounds member array index");
- reinterpret_cast<VarDecl **>(this + 1)[I] = Index;
+ getTrailingObjects<VarDecl *>()[I] = Index;
}
ArrayRef<VarDecl *> getArrayIndexes() {
assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init");
- return llvm::makeArrayRef(reinterpret_cast<VarDecl **>(this + 1),
+ return llvm::makeArrayRef(getTrailingObjects<VarDecl *>(),
getNumArrayIndices());
}
/// \brief Get the initializer.
Expr *getInit() const { return static_cast<Expr*>(Init); }
+
+ friend TrailingObjects;
};
/// \brief Represents a C++ constructor within a class.
@@ -2289,14 +2276,14 @@ public:
}
/// \brief Determine whether this constructor is a move constructor
- /// (C++0x [class.copy]p3), which can be used to move values of the class.
+ /// (C++11 [class.copy]p3), which can be used to move values of the class.
///
/// \param TypeQuals If this constructor is a move constructor, will be set
/// to the type qualifiers on the referent of the first parameter's type.
bool isMoveConstructor(unsigned &TypeQuals) const;
/// \brief Determine whether this constructor is a move constructor
- /// (C++0x [class.copy]p3), which can be used to move values of the class.
+ /// (C++11 [class.copy]p3), which can be used to move values of the class.
bool isMoveConstructor() const {
unsigned TypeQuals = 0;
return isMoveConstructor(TypeQuals);
@@ -2406,7 +2393,7 @@ class CXXConversionDecl : public CXXMethodDecl {
void anchor() override;
/// Whether this conversion function declaration is marked
/// "explicit", meaning that it can only be applied when the user
- /// explicitly wrote a cast. This is a C++0x feature.
+ /// explicitly wrote a cast. This is a C++11 feature.
bool IsExplicitSpecified : 1;
CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
index 12b93b4..27b0388 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
@@ -37,7 +37,9 @@ namespace clang {
/// @endcode
///
/// The semantic context of a friend decl is its declaring class.
-class FriendDecl : public Decl {
+class FriendDecl final
+ : public Decl,
+ private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> {
virtual void anchor();
public:
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
@@ -62,14 +64,6 @@ private:
// template <class T> friend class A<T>::B;
unsigned NumTPLists : 31;
- // The tail-allocated friend type template parameter lists (if any).
- TemplateParameterList* const *getTPLists() const {
- return reinterpret_cast<TemplateParameterList* const *>(this + 1);
- }
- TemplateParameterList **getTPLists() {
- return reinterpret_cast<TemplateParameterList**>(this + 1);
- }
-
friend class CXXRecordDecl::friend_iterator;
friend class CXXRecordDecl;
@@ -83,7 +77,7 @@ private:
UnsupportedFriend(false),
NumTPLists(FriendTypeTPLists.size()) {
for (unsigned i = 0; i < NumTPLists; ++i)
- getTPLists()[i] = FriendTypeTPLists[i];
+ getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i];
}
FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
@@ -118,7 +112,7 @@ public:
}
TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
assert(N < NumTPLists);
- return getTPLists()[N];
+ return getTrailingObjects<TemplateParameterList *>()[N];
}
/// If this friend declaration doesn't name a type, return the inner
@@ -148,9 +142,10 @@ public:
return SourceRange(getFriendLoc(), ND->getLocEnd());
}
else if (TypeSourceInfo *TInfo = getFriendType()) {
- SourceLocation StartL = (NumTPLists == 0)
- ? getFriendLoc()
- : getTPLists()[0]->getTemplateLoc();
+ SourceLocation StartL =
+ (NumTPLists == 0) ? getFriendLoc()
+ : getTrailingObjects<TemplateParameterList *>()[0]
+ ->getTemplateLoc();
return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc());
}
else
@@ -171,6 +166,7 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend TrailingObjects;
};
/// An iterator over the friend declarations of a class.
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
index bd3dbd8..c84bb5e 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_DECLGROUP_H
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/TrailingObjects.h"
#include <cassert>
namespace clang {
@@ -24,13 +25,9 @@ class Decl;
class DeclGroup;
class DeclGroupIterator;
-class DeclGroup {
+class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> {
// FIXME: Include a TypeSpecifier object.
- union {
- unsigned NumDecls;
-
- Decl *Aligner;
- };
+ unsigned NumDecls;
private:
DeclGroup() : NumDecls(0) {}
@@ -43,13 +40,15 @@ public:
Decl*& operator[](unsigned i) {
assert (i < NumDecls && "Out-of-bounds access.");
- return ((Decl**) (this+1))[i];
+ return getTrailingObjects<Decl *>()[i];
}
Decl* const& operator[](unsigned i) const {
assert (i < NumDecls && "Out-of-bounds access.");
- return ((Decl* const*) (this+1))[i];
+ return getTrailingObjects<Decl *>()[i];
}
+
+ friend TrailingObjects;
};
class DeclGroupRef {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h
index c42764b..f46078f 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h
@@ -612,7 +612,8 @@ public:
/// @interface NSArray<T> // stores the <T>
/// @end
/// \endcode
-class ObjCTypeParamList {
+class ObjCTypeParamList final
+ : private llvm::TrailingObjects<ObjCTypeParamList, ObjCTypeParamDecl *> {
/// Stores the components of a SourceRange as a POD.
struct PODSourceRange {
unsigned Begin;
@@ -644,7 +645,7 @@ public:
/// Iterate through the type parameters in the list.
typedef ObjCTypeParamDecl **iterator;
- iterator begin() { return reinterpret_cast<ObjCTypeParamDecl **>(this + 1); }
+ iterator begin() { return getTrailingObjects<ObjCTypeParamDecl *>(); }
iterator end() { return begin() + size(); }
@@ -655,7 +656,7 @@ public:
typedef ObjCTypeParamDecl * const *const_iterator;
const_iterator begin() const {
- return reinterpret_cast<ObjCTypeParamDecl * const *>(this + 1);
+ return getTrailingObjects<ObjCTypeParamDecl *>();
}
const_iterator end() const {
@@ -685,6 +686,7 @@ public:
/// Gather the default set of type arguments to be substituted for
/// these type parameters when dealing with an unspecialized type.
void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const;
+ friend TrailingObjects;
};
/// ObjCContainerDecl - Represents a container for method declarations.
@@ -1202,13 +1204,8 @@ public:
// might bring in a definition.
// Note: a null value indicates that we don't have a definition and that
// modules are enabled.
- if (!Data.getOpaqueValue()) {
- if (IdentifierInfo *II = getIdentifier()) {
- if (II->isOutOfDate()) {
- updateOutOfDate(*II);
- }
- }
- }
+ if (!Data.getOpaqueValue())
+ getMostRecentDecl();
return Data.getPointer();
}
@@ -1851,13 +1848,8 @@ public:
// might bring in a definition.
// Note: a null value indicates that we don't have a definition and that
// modules are enabled.
- if (!Data.getOpaqueValue()) {
- if (IdentifierInfo *II = getIdentifier()) {
- if (II->isOutOfDate()) {
- updateOutOfDate(*II);
- }
- }
- }
+ if (!Data.getOpaqueValue())
+ getMostRecentDecl();
return Data.getPointer();
}
@@ -2519,26 +2511,18 @@ public:
void setPropertyAttributes(PropertyAttributeKind PRVal) {
PropertyAttributes |= PRVal;
}
+ void overwritePropertyAttributes(unsigned PRVal) {
+ PropertyAttributes = PRVal;
+ }
PropertyAttributeKind getPropertyAttributesAsWritten() const {
return PropertyAttributeKind(PropertyAttributesAsWritten);
}
- bool hasWrittenStorageAttribute() const {
- return PropertyAttributesAsWritten & (OBJC_PR_assign | OBJC_PR_copy |
- OBJC_PR_unsafe_unretained | OBJC_PR_retain | OBJC_PR_strong |
- OBJC_PR_weak);
- }
-
void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) {
PropertyAttributesAsWritten = PRVal;
}
- void makeitReadWriteAttribute() {
- PropertyAttributes &= ~OBJC_PR_readonly;
- PropertyAttributes |= OBJC_PR_readwrite;
- }
-
// Helper methods for accessing attributes.
/// isReadOnly - Return true iff the property has a setter.
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h
index 7f0616f..598f418 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h
@@ -33,8 +33,12 @@ class Expr;
/// };
/// \endcode
///
-class OMPThreadPrivateDecl : public Decl {
+class OMPThreadPrivateDecl final
+ : public Decl,
+ private llvm::TrailingObjects<OMPThreadPrivateDecl, Expr *> {
friend class ASTDeclReader;
+ friend TrailingObjects;
+
unsigned NumVars;
virtual void anchor();
@@ -43,14 +47,11 @@ class OMPThreadPrivateDecl : public Decl {
Decl(DK, DC, L), NumVars(0) { }
ArrayRef<const Expr *> getVars() const {
- return llvm::makeArrayRef(reinterpret_cast<const Expr * const *>(this + 1),
- NumVars);
+ return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars);
}
MutableArrayRef<Expr *> getVars() {
- return MutableArrayRef<Expr *>(
- reinterpret_cast<Expr **>(this + 1),
- NumVars);
+ return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars);
}
void setVars(ArrayRef<Expr *> VL);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
index 0fc9b49..a9109ef 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
@@ -20,10 +20,12 @@
#include "clang/AST/TemplateBase.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TrailingObjects.h"
#include <limits>
namespace clang {
+enum BuiltinTemplateKind : int;
class TemplateParameterList;
class TemplateDecl;
class RedeclarableTemplateDecl;
@@ -43,7 +45,9 @@ typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
/// \brief Stores a list of template parameters for a TemplateDecl and its
/// derived classes.
-class TemplateParameterList {
+class TemplateParameterList final
+ : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *> {
+
/// The location of the 'template' keyword.
SourceLocation TemplateLoc;
@@ -59,16 +63,18 @@ class TemplateParameterList {
unsigned ContainsUnexpandedParameterPack : 1;
protected:
+ size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
+ return NumParams;
+ }
+
TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
- NamedDecl **Params, unsigned NumParams,
- SourceLocation RAngleLoc);
+ ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc);
public:
static TemplateParameterList *Create(const ASTContext &C,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- NamedDecl **Params,
- unsigned NumParams,
+ ArrayRef<NamedDecl *> Params,
SourceLocation RAngleLoc);
/// \brief Iterates through the template parameters in this list.
@@ -77,10 +83,8 @@ public:
/// \brief Iterates through the template parameters in this list.
typedef NamedDecl* const* const_iterator;
- iterator begin() { return reinterpret_cast<NamedDecl **>(this + 1); }
- const_iterator begin() const {
- return reinterpret_cast<NamedDecl * const *>(this + 1);
- }
+ iterator begin() { return getTrailingObjects<NamedDecl *>(); }
+ const_iterator begin() const { return getTrailingObjects<NamedDecl *>(); }
iterator end() { return begin() + NumParams; }
const_iterator end() const { return begin() + NumParams; }
@@ -130,29 +134,45 @@ public:
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(TemplateLoc, RAngleLoc);
}
+
+ friend TrailingObjects;
+ template <size_t N> friend class FixedSizeTemplateParameterListStorage;
};
/// \brief Stores a list of template parameters for a TemplateDecl and its
/// derived classes. Suitable for creating on the stack.
-template<size_t N>
-class FixedSizeTemplateParameterList : public TemplateParameterList {
+template <size_t N> class FixedSizeTemplateParameterListStorage {
+ // This is kinda ugly: TemplateParameterList usually gets allocated
+ // in a block of memory with NamedDecls appended to it. Here, to get
+ // it stack allocated, we include the params as a separate
+ // variable. After allocation, the TemplateParameterList object
+ // treats them as part of itself.
+ TemplateParameterList List;
NamedDecl *Params[N];
public:
- FixedSizeTemplateParameterList(SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- NamedDecl **Params, SourceLocation RAngleLoc) :
- TemplateParameterList(TemplateLoc, LAngleLoc, Params, N, RAngleLoc) {
- }
+ FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ArrayRef<NamedDecl *> Params,
+ SourceLocation RAngleLoc)
+ : List(TemplateLoc, LAngleLoc, Params, RAngleLoc) {
+ // Because we're doing an evil layout hack above, have some
+ // asserts, just to double-check everything is laid out like
+ // expected.
+ assert(sizeof(*this) ==
+ TemplateParameterList::totalSizeToAlloc<NamedDecl *>(N) &&
+ "Object layout not as expected");
+ assert(this->Params == List.getTrailingObjects<NamedDecl *>() &&
+ "Object layout not as expected");
+ }
+ TemplateParameterList *get() { return &List; }
};
/// \brief A template argument list.
-class TemplateArgumentList {
+class TemplateArgumentList final
+ : private llvm::TrailingObjects<TemplateArgumentList, TemplateArgument> {
/// \brief The template argument list.
- ///
- /// The integer value will be non-zero to indicate that this
- /// template argument list does own the pointer.
- llvm::PointerIntPair<const TemplateArgument *, 1> Arguments;
+ const TemplateArgument *Arguments;
/// \brief The number of template arguments in this template
/// argument list.
@@ -161,9 +181,9 @@ class TemplateArgumentList {
TemplateArgumentList(const TemplateArgumentList &Other) = delete;
void operator=(const TemplateArgumentList &Other) = delete;
- TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs,
- bool Owned)
- : Arguments(Args, Owned), NumArguments(NumArgs) { }
+ // Constructs an instance with an internal Argument list, containing
+ // a copy of the Args array. (Called by CreateCopy)
+ TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs);
public:
/// \brief Type used to indicate that the template argument list itself is a
@@ -180,9 +200,9 @@ public:
///
/// The template argument list does not own the template arguments
/// provided.
- explicit TemplateArgumentList(OnStackType,
- const TemplateArgument *Args, unsigned NumArgs)
- : Arguments(Args, false), NumArguments(NumArgs) { }
+ explicit TemplateArgumentList(OnStackType, const TemplateArgument *Args,
+ unsigned NumArgs)
+ : Arguments(Args), NumArguments(NumArgs) {}
/// \brief Produces a shallow copy of the given template argument list.
///
@@ -191,7 +211,7 @@ public:
/// constructor, since this really really isn't safe to use that
/// way.
explicit TemplateArgumentList(const TemplateArgumentList *Other)
- : Arguments(Other->data(), false), NumArguments(Other->size()) { }
+ : Arguments(Other->data()), NumArguments(Other->size()) {}
/// \brief Retrieve the template argument at a given index.
const TemplateArgument &get(unsigned Idx) const {
@@ -212,9 +232,9 @@ public:
unsigned size() const { return NumArguments; }
/// \brief Retrieve a pointer to the template argument list.
- const TemplateArgument *data() const {
- return Arguments.getPointer();
- }
+ const TemplateArgument *data() const { return Arguments; }
+
+ friend TrailingObjects;
};
void *allocateDefaultArgStorageChain(const ASTContext &C);
@@ -426,17 +446,8 @@ public:
/// explicit instantiation declaration, or explicit instantiation
/// definition.
bool isExplicitInstantiationOrSpecialization() const {
- switch (getTemplateSpecializationKind()) {
- case TSK_ExplicitSpecialization:
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- return true;
-
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- return false;
- }
- llvm_unreachable("bad template specialization kind");
+ return isTemplateExplicitInstantiationOrSpecialization(
+ getTemplateSpecializationKind());
}
/// \brief Set the template specialization kind.
@@ -542,56 +553,52 @@ public:
/// friend void foo<>(T);
/// };
/// \endcode
-class DependentFunctionTemplateSpecializationInfo {
- struct CA {
- /// The number of potential template candidates.
- unsigned NumTemplates;
+class DependentFunctionTemplateSpecializationInfo final
+ : private llvm::TrailingObjects<DependentFunctionTemplateSpecializationInfo,
+ TemplateArgumentLoc,
+ FunctionTemplateDecl *> {
+ /// The number of potential template candidates.
+ unsigned NumTemplates;
- /// The number of template arguments.
- unsigned NumArgs;
- };
-
- union {
- // Force sizeof to be a multiple of sizeof(void*) so that the
- // trailing data is aligned.
- void *Aligner;
- struct CA d;
- };
+ /// The number of template arguments.
+ unsigned NumArgs;
/// The locations of the left and right angle brackets.
SourceRange AngleLocs;
- FunctionTemplateDecl * const *getTemplates() const {
- return reinterpret_cast<FunctionTemplateDecl*const*>(this+1);
+ size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
+ return NumArgs;
+ }
+ size_t numTrailingObjects(OverloadToken<FunctionTemplateDecl *>) const {
+ return NumTemplates;
}
-public:
DependentFunctionTemplateSpecializationInfo(
const UnresolvedSetImpl &Templates,
const TemplateArgumentListInfo &TemplateArgs);
+public:
+ static DependentFunctionTemplateSpecializationInfo *
+ Create(ASTContext &Context, const UnresolvedSetImpl &Templates,
+ const TemplateArgumentListInfo &TemplateArgs);
+
/// \brief Returns the number of function templates that this might
/// be a specialization of.
- unsigned getNumTemplates() const {
- return d.NumTemplates;
- }
+ unsigned getNumTemplates() const { return NumTemplates; }
/// \brief Returns the i'th template candidate.
FunctionTemplateDecl *getTemplate(unsigned I) const {
assert(I < getNumTemplates() && "template index out of range");
- return getTemplates()[I];
+ return getTrailingObjects<FunctionTemplateDecl *>()[I];
}
/// \brief Returns the explicit template arguments that were given.
const TemplateArgumentLoc *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgumentLoc*>(
- &getTemplates()[getNumTemplates()]);
+ return getTrailingObjects<TemplateArgumentLoc>();
}
/// \brief Returns the number of explicit template arguments that were given.
- unsigned getNumTemplateArgs() const {
- return d.NumArgs;
- }
+ unsigned getNumTemplateArgs() const { return NumArgs; }
/// \brief Returns the nth template argument.
const TemplateArgumentLoc &getTemplateArg(unsigned I) const {
@@ -606,6 +613,8 @@ public:
SourceLocation getRAngleLoc() const {
return AngleLocs.getEnd();
}
+
+ friend TrailingObjects;
};
/// Declaration of a redeclarable template.
@@ -926,7 +935,7 @@ public:
return const_cast<FunctionTemplateDecl*>(this)->getMostRecentDecl();
}
- FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
+ FunctionTemplateDecl *getInstantiatedFromMemberTemplate() const {
return cast_or_null<FunctionTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
@@ -1120,8 +1129,11 @@ public:
/// @code
/// template<int Size> class array { };
/// @endcode
-class NonTypeTemplateParmDecl
- : public DeclaratorDecl, protected TemplateParmPosition {
+class NonTypeTemplateParmDecl final
+ : public DeclaratorDecl,
+ protected TemplateParmPosition,
+ private llvm::TrailingObjects<NonTypeTemplateParmDecl,
+ std::pair<QualType, TypeSourceInfo *>> {
/// \brief The default template argument, if any, and whether or not
/// it was inherited.
typedef DefaultArgStorage<NonTypeTemplateParmDecl, Expr*> DefArgStorage;
@@ -1141,6 +1153,11 @@ class NonTypeTemplateParmDecl
/// \brief The number of types in an expanded parameter pack.
unsigned NumExpandedTypes;
+ size_t numTrailingObjects(
+ OverloadToken<std::pair<QualType, TypeSourceInfo *>>) const {
+ return NumExpandedTypes;
+ }
+
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, unsigned D, unsigned P,
IdentifierInfo *Id, QualType T,
@@ -1159,6 +1176,7 @@ class NonTypeTemplateParmDecl
TypeSourceInfo **ExpandedTInfos);
friend class ASTDeclReader;
+ friend TrailingObjects;
public:
static NonTypeTemplateParmDecl *
@@ -1274,16 +1292,18 @@ public:
/// pack.
QualType getExpansionType(unsigned I) const {
assert(I < NumExpandedTypes && "Out-of-range expansion type index");
- void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
- return QualType::getFromOpaquePtr(TypesAndInfos[2*I]);
+ auto TypesAndInfos =
+ getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
+ return TypesAndInfos[I].first;
}
/// \brief Retrieve a particular expansion type source info within an
/// expanded parameter pack.
TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const {
assert(I < NumExpandedTypes && "Out-of-range expansion type index");
- void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
- return static_cast<TypeSourceInfo *>(TypesAndInfos[2*I+1]);
+ auto TypesAndInfos =
+ getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
+ return TypesAndInfos[I].second;
}
// Implement isa/cast/dyncast/etc.
@@ -1298,9 +1318,11 @@ public:
/// @endcode
/// A template template parameter is a TemplateDecl because it defines the
/// name of a template and the template parameters allowable for substitution.
-class TemplateTemplateParmDecl : public TemplateDecl,
- protected TemplateParmPosition
-{
+class TemplateTemplateParmDecl final
+ : public TemplateDecl,
+ protected TemplateParmPosition,
+ private llvm::TrailingObjects<TemplateTemplateParmDecl,
+ TemplateParameterList *> {
void anchor() override;
/// \brief The default template argument, if any.
@@ -1404,7 +1426,7 @@ public:
/// pack.
TemplateParameterList *getExpansionTemplateParameters(unsigned I) const {
assert(I < NumExpandedParams && "Out-of-range expansion type index");
- return reinterpret_cast<TemplateParameterList *const *>(this + 1)[I];
+ return getTrailingObjects<TemplateParameterList *>()[I];
}
const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
@@ -1454,6 +1476,36 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend TrailingObjects;
+};
+
+/// \brief Represents the builtin template declaration which is used to
+/// implement __make_integer_seq. It serves no real purpose beyond existing as
+/// a place to hold template parameters.
+class BuiltinTemplateDecl : public TemplateDecl {
+ void anchor() override;
+
+ BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
+ DeclarationName Name, BuiltinTemplateKind BTK);
+
+ BuiltinTemplateKind BTK;
+
+public:
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == BuiltinTemplate; }
+
+ static BuiltinTemplateDecl *Create(const ASTContext &C, DeclContext *DC,
+ DeclarationName Name,
+ BuiltinTemplateKind BTK) {
+ return new (C, DC) BuiltinTemplateDecl(C, DC, Name, BTK);
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange();
+ }
+
+ BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; }
};
/// \brief Represents a class template specialization, which refers to
@@ -1580,17 +1632,8 @@ public:
/// explicit instantiation declaration, or explicit instantiation
/// definition.
bool isExplicitInstantiationOrSpecialization() const {
- switch (getTemplateSpecializationKind()) {
- case TSK_ExplicitSpecialization:
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- return true;
-
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- return false;
- }
- llvm_unreachable("bad template specialization kind");
+ return isTemplateExplicitInstantiationOrSpecialization(
+ getTemplateSpecializationKind());
}
void setSpecializationKind(TemplateSpecializationKind TSK) {
@@ -1819,8 +1862,8 @@ public:
/// template partial specialization \c Outer<T>::Inner<U*>. Given
/// \c Outer<float>::Inner<U*>, this function would return
/// \c Outer<T>::Inner<U*>.
- ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
- ClassTemplatePartialSpecializationDecl *First =
+ ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
+ const ClassTemplatePartialSpecializationDecl *First =
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getPointer();
}
@@ -2000,7 +2043,7 @@ public:
return const_cast<ClassTemplateDecl*>(this)->getMostRecentDecl();
}
- ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
+ ClassTemplateDecl *getInstantiatedFromMemberTemplate() const {
return cast_or_null<ClassTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
@@ -2230,7 +2273,7 @@ public:
this)->getPreviousDecl());
}
- TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() {
+ TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() const {
return cast_or_null<TypeAliasTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
@@ -2435,17 +2478,8 @@ public:
/// explicit instantiation declaration, or explicit instantiation
/// definition.
bool isExplicitInstantiationOrSpecialization() const {
- switch (getTemplateSpecializationKind()) {
- case TSK_ExplicitSpecialization:
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- return true;
-
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- return false;
- }
- llvm_unreachable("bad template specialization kind");
+ return isTemplateExplicitInstantiationOrSpecialization(
+ getTemplateSpecializationKind());
}
void setSpecializationKind(TemplateSpecializationKind TSK) {
@@ -2668,8 +2702,8 @@ public:
/// variable template partial specialization \c Outer<T>::Inner<U*>. Given
/// \c Outer<float>::Inner<U*>, this function would return
/// \c Outer<T>::Inner<U*>.
- VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
- VarTemplatePartialSpecializationDecl *First =
+ VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
+ const VarTemplatePartialSpecializationDecl *First =
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getPointer();
}
@@ -2833,7 +2867,7 @@ public:
return const_cast<VarTemplateDecl *>(this)->getMostRecentDecl();
}
- VarTemplateDecl *getInstantiatedFromMemberTemplate() {
+ VarTemplateDecl *getInstantiatedFromMemberTemplate() const {
return cast_or_null<VarTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
index ec0fb0b..9482e83e 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
@@ -395,7 +395,7 @@ struct DeclarationNameLoc {
// Locations (if any) for the tilde (destructor) or operator keyword
// (conversion) are stored elsewhere.
struct NT {
- TypeSourceInfo* TInfo;
+ TypeSourceInfo *TInfo;
};
// The location (if any) of the operator keyword is stored elsewhere.
diff --git a/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h
index ad52873..aad7726 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h
@@ -88,8 +88,8 @@ public:
void VisitLambdaExpr(PTR(LambdaExpr) LE) {
// Only visit the capture initializers, and not the body.
- for (LambdaExpr::capture_init_iterator I = LE->capture_init_begin(),
- E = LE->capture_init_end();
+ for (LambdaExpr::const_capture_init_iterator I = LE->capture_init_begin(),
+ E = LE->capture_init_end();
I != E; ++I)
if (*I)
this->Visit(*I);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
index 2a5b4c0..38733ee 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Expr.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
@@ -23,6 +23,7 @@
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
@@ -61,7 +62,6 @@ struct SubobjectAdjustment {
MemberPointerAdjustment
} Kind;
-
struct DTB {
const CastExpr *BasePath;
const CXXRecordDecl *DerivedClass;
@@ -148,8 +148,6 @@ public:
/// \brief Set whether this expression is value-dependent or not.
void setValueDependent(bool VD) {
ExprBits.ValueDependent = VD;
- if (VD)
- ExprBits.InstantiationDependent = true;
}
/// isTypeDependent - Determines whether this expression is
@@ -168,8 +166,6 @@ public:
/// \brief Set whether this expression is type-dependent or not.
void setTypeDependent(bool TD) {
ExprBits.TypeDependent = TD;
- if (TD)
- ExprBits.InstantiationDependent = true;
}
/// \brief Whether this expression is instantiation-dependent, meaning that
@@ -458,6 +454,10 @@ public:
/// \brief Returns whether this expression refers to a vector element.
bool refersToVectorElement() const;
+ /// \brief Returns whether this expression refers to a global register
+ /// variable.
+ bool refersToGlobalRegisterVar() const;
+
/// \brief Returns whether this expression has a placeholder type.
bool hasPlaceholderType() const {
return getType()->isPlaceholderType();
@@ -529,10 +529,15 @@ public:
/// EvalStatus is a struct with detailed info about an evaluation in progress.
struct EvalStatus {
- /// HasSideEffects - Whether the evaluated expression has side effects.
+ /// \brief Whether the evaluated expression has side effects.
/// For example, (f() && 0) can be folded, but it still has side effects.
bool HasSideEffects;
+ /// \brief Whether the evaluation hit undefined behavior.
+ /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior.
+ /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB.
+ bool HasUndefinedBehavior;
+
/// Diag - If this is non-null, it will be filled in with a stack of notes
/// indicating why evaluation failed (or why it failed to produce a constant
/// expression).
@@ -542,7 +547,8 @@ public:
/// expression *is* a constant expression, no notes will be produced.
SmallVectorImpl<PartialDiagnosticAt> *Diag;
- EvalStatus() : HasSideEffects(false), Diag(nullptr) {}
+ EvalStatus()
+ : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {}
// hasSideEffects - Return true if the evaluated expression has
// side effects.
@@ -575,7 +581,12 @@ public:
/// side-effects.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
- enum SideEffectsKind { SE_NoSideEffects, SE_AllowSideEffects };
+ enum SideEffectsKind {
+ SE_NoSideEffects, ///< Strictly evaluate the expression.
+ SE_AllowUndefinedBehavior, ///< Allow UB that we can give a value, but not
+ ///< arbitrary unmodeled side effects.
+ SE_AllowSideEffects ///< Allow any unmodeled side effect.
+ };
/// EvaluateAsInt - Return true if this is a constant which we can fold and
/// convert to an integer, using any crazy technique that we want to.
@@ -584,7 +595,8 @@ public:
/// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
/// constant folded without side-effects, but discard the result.
- bool isEvaluatable(const ASTContext &Ctx) const;
+ bool isEvaluatable(const ASTContext &Ctx,
+ SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
/// HasSideEffects - This routine returns true for all those expressions
/// which have any effect other than producing a value. Example is a function
@@ -628,6 +640,16 @@ public:
const FunctionDecl *Callee,
ArrayRef<const Expr*> Args) const;
+ /// \brief If the current Expr is a pointer, this will try to statically
+ /// determine the number of bytes available where the pointer is pointing.
+ /// Returns true if all of the above holds and we were able to figure out the
+ /// size, false otherwise.
+ ///
+ /// \param Type - How to evaluate the size of the Expr, as defined by the
+ /// "type" parameter of __builtin_object_size
+ bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
+ unsigned Type) const;
+
/// \brief Enumeration used to describe the kind of Null pointer constant
/// returned from \c isNullPointerConstant().
enum NullPointerConstantKind {
@@ -806,7 +828,6 @@ public:
}
};
-
//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//
@@ -856,7 +877,9 @@ public:
return Loc;
}
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
/// The source expression of an opaque value expression is the
/// expression which originally generated the value. This is
@@ -896,7 +919,11 @@ public:
/// DeclRefExprBits.RefersToEnclosingVariableOrCapture
/// Specifies when this declaration reference expression (validly)
/// refers to an enclosed local or a captured variable.
-class DeclRefExpr : public Expr {
+class DeclRefExpr final
+ : public Expr,
+ private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc,
+ NamedDecl *, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
/// \brief The declaration that we are referencing.
ValueDecl *D;
@@ -907,36 +934,22 @@ class DeclRefExpr : public Expr {
/// embedded in D.
DeclarationNameLoc DNLoc;
- /// \brief Helper to retrieve the optional NestedNameSpecifierLoc.
- NestedNameSpecifierLoc &getInternalQualifierLoc() {
- assert(hasQualifier());
- return *reinterpret_cast<NestedNameSpecifierLoc *>(this + 1);
+ size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const {
+ return hasQualifier() ? 1 : 0;
+ }
+
+ size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
+ return hasFoundDecl() ? 1 : 0;
}
- /// \brief Helper to retrieve the optional NestedNameSpecifierLoc.
- const NestedNameSpecifierLoc &getInternalQualifierLoc() const {
- return const_cast<DeclRefExpr *>(this)->getInternalQualifierLoc();
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return hasTemplateKWAndArgsInfo() ? 1 : 0;
}
/// \brief Test whether there is a distinct FoundDecl attached to the end of
/// this DRE.
bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; }
- /// \brief Helper to retrieve the optional NamedDecl through which this
- /// reference occurred.
- NamedDecl *&getInternalFoundDecl() {
- assert(hasFoundDecl());
- if (hasQualifier())
- return *reinterpret_cast<NamedDecl **>(&getInternalQualifierLoc() + 1);
- return *reinterpret_cast<NamedDecl **>(this + 1);
- }
-
- /// \brief Helper to retrieve the optional NamedDecl through which this
- /// reference occurred.
- NamedDecl *getInternalFoundDecl() const {
- return const_cast<DeclRefExpr *>(this)->getInternalFoundDecl();
- }
-
DeclRefExpr(const ASTContext &Ctx,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
@@ -1009,21 +1022,17 @@ public:
bool hasQualifier() const { return DeclRefExprBits.HasQualifier; }
/// \brief If the name was qualified, retrieves the nested-name-specifier
- /// that precedes the name. Otherwise, returns NULL.
- NestedNameSpecifier *getQualifier() const {
- if (!hasQualifier())
- return nullptr;
-
- return getInternalQualifierLoc().getNestedNameSpecifier();
- }
-
- /// \brief If the name was qualified, retrieves the nested-name-specifier
/// that precedes the name, with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const {
if (!hasQualifier())
return NestedNameSpecifierLoc();
+ return *getTrailingObjects<NestedNameSpecifierLoc>();
+ }
- return getInternalQualifierLoc();
+ /// \brief If the name was qualified, retrieves the nested-name-specifier
+ /// that precedes the name. Otherwise, returns NULL.
+ NestedNameSpecifier *getQualifier() const {
+ return getQualifierLoc().getNestedNameSpecifier();
}
/// \brief Get the NamedDecl through which this reference occurred.
@@ -1031,60 +1040,40 @@ public:
/// This Decl may be different from the ValueDecl actually referred to in the
/// presence of using declarations, etc. It always returns non-NULL, and may
/// simple return the ValueDecl when appropriate.
+
NamedDecl *getFoundDecl() {
- return hasFoundDecl() ? getInternalFoundDecl() : D;
+ return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
}
/// \brief Get the NamedDecl through which this reference occurred.
/// See non-const variant.
const NamedDecl *getFoundDecl() const {
- return hasFoundDecl() ? getInternalFoundDecl() : D;
+ return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
}
bool hasTemplateKWAndArgsInfo() const {
return DeclRefExprBits.HasTemplateKWAndArgsInfo;
}
- /// \brief Return the optional template keyword and arguments info.
- ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
- if (!hasTemplateKWAndArgsInfo())
- return nullptr;
-
- if (hasFoundDecl())
- return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
- &getInternalFoundDecl() + 1);
-
- if (hasQualifier())
- return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
- &getInternalQualifierLoc() + 1);
-
- return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1);
- }
-
- /// \brief Return the optional template keyword and arguments info.
- const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const {
- return const_cast<DeclRefExpr*>(this)->getTemplateKWAndArgsInfo();
- }
-
/// \brief Retrieve the location of the template keyword preceding
/// this name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
- return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
/// \brief Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the name, if any.
SourceLocation getLAngleLoc() const {
if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
- return getTemplateKWAndArgsInfo()->LAngleLoc;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
/// \brief Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the name, if any.
SourceLocation getRAngleLoc() const {
if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
- return getTemplateKWAndArgsInfo()->RAngleLoc;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
}
/// \brief Determines whether the name in this declaration reference
@@ -1095,32 +1084,12 @@ public:
/// explicit template argument list.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name.
- ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
- assert(hasExplicitTemplateArgs());
- return *getTemplateKWAndArgsInfo();
- }
-
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name.
- const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
- return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgs();
- }
-
- /// \brief Retrieves the optional explicit template arguments.
- /// This points to the same data as getExplicitTemplateArgs(), but
- /// returns null if there are no explicit template arguments.
- const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
- if (!hasExplicitTemplateArgs()) return nullptr;
- return &getExplicitTemplateArgs();
- }
-
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
- getExplicitTemplateArgs().copyInto(List);
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
+ getTrailingObjects<TemplateArgumentLoc>(), List);
}
/// \brief Retrieve the template arguments provided as part of this
@@ -1129,7 +1098,7 @@ public:
if (!hasExplicitTemplateArgs())
return nullptr;
- return getExplicitTemplateArgs().getTemplateArgs();
+ return getTrailingObjects<TemplateArgumentLoc>();
}
/// \brief Retrieve the number of template arguments provided as part of this
@@ -1138,7 +1107,7 @@ public:
if (!hasExplicitTemplateArgs())
return 0;
- return getExplicitTemplateArgs().NumTemplateArgs;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
}
/// \brief Returns true if this expression refers to a function that
@@ -1164,8 +1133,11 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+ friend TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
@@ -1310,7 +1282,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
class CharacterLiteral : public Expr {
@@ -1318,6 +1292,7 @@ public:
enum CharacterKind {
Ascii,
Wide,
+ UTF8,
UTF16,
UTF32
};
@@ -1357,7 +1332,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
class FloatingLiteral : public Expr, private APFloatStorage {
@@ -1419,7 +1396,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// ImaginaryLiteral - We support imaginary integer and floating point literals,
@@ -1596,13 +1575,15 @@ public:
/// and can have escape sequences in them in addition to the usual trigraph
/// and escaped newline business. This routine handles this complexity.
///
- SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
- const LangOptions &Features,
- const TargetInfo &Target) const;
+ SourceLocation
+ getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
+ const LangOptions &Features, const TargetInfo &Target,
+ unsigned *StartToken = nullptr,
+ unsigned *StartTokenByteOffset = nullptr) const;
typedef const SourceLocation *tokloc_iterator;
tokloc_iterator tokloc_begin() const { return TokLocs; }
- tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; }
+ tokloc_iterator tokloc_end() const { return TokLocs + NumConcatenated; }
SourceLocation getLocStart() const LLVM_READONLY { return TokLocs[0]; }
SourceLocation getLocEnd() const LLVM_READONLY {
@@ -1614,7 +1595,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
@@ -1658,7 +1641,6 @@ public:
child_range children() { return child_range(&Val, &Val+1); }
};
-
/// UnaryOperator - This represents the unary-expression's (except sizeof and
/// alignof), the postinc/postdec operators from postfix-expression, and various
/// extensions.
@@ -1768,6 +1750,99 @@ public:
child_range children() { return child_range(&Val, &Val+1); }
};
+/// Helper class for OffsetOfExpr.
+
+// __builtin_offsetof(type, identifier(.identifier|[expr])*)
+class OffsetOfNode {
+public:
+ /// \brief The kind of offsetof node we have.
+ enum Kind {
+ /// \brief An index into an array.
+ Array = 0x00,
+ /// \brief A field.
+ Field = 0x01,
+ /// \brief A field in a dependent type, known only by its name.
+ Identifier = 0x02,
+ /// \brief An implicit indirection through a C++ base class, when the
+ /// field found is in a base class.
+ Base = 0x03
+ };
+
+private:
+ enum { MaskBits = 2, Mask = 0x03 };
+
+ /// \brief The source range that covers this part of the designator.
+ SourceRange Range;
+
+ /// \brief The data describing the designator, which comes in three
+ /// different forms, depending on the lower two bits.
+ /// - An unsigned index into the array of Expr*'s stored after this node
+ /// in memory, for [constant-expression] designators.
+ /// - A FieldDecl*, for references to a known field.
+ /// - An IdentifierInfo*, for references to a field with a given name
+ /// when the class type is dependent.
+ /// - A CXXBaseSpecifier*, for references that look at a field in a
+ /// base class.
+ uintptr_t Data;
+
+public:
+ /// \brief Create an offsetof node that refers to an array element.
+ OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
+ SourceLocation RBracketLoc)
+ : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) {}
+
+ /// \brief Create an offsetof node that refers to a field.
+ OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc)
+ : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
+ Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) {}
+
+ /// \brief Create an offsetof node that refers to an identifier.
+ OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
+ SourceLocation NameLoc)
+ : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
+ Data(reinterpret_cast<uintptr_t>(Name) | Identifier) {}
+
+ /// \brief Create an offsetof node that refers into a C++ base class.
+ explicit OffsetOfNode(const CXXBaseSpecifier *Base)
+ : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}
+
+ /// \brief Determine what kind of offsetof node this is.
+ Kind getKind() const { return static_cast<Kind>(Data & Mask); }
+
+ /// \brief For an array element node, returns the index into the array
+ /// of expressions.
+ unsigned getArrayExprIndex() const {
+ assert(getKind() == Array);
+ return Data >> 2;
+ }
+
+ /// \brief For a field offsetof node, returns the field.
+ FieldDecl *getField() const {
+ assert(getKind() == Field);
+ return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask);
+ }
+
+ /// \brief For a field or identifier offsetof node, returns the name of
+ /// the field.
+ IdentifierInfo *getFieldName() const;
+
+ /// \brief For a base class node, returns the base specifier.
+ CXXBaseSpecifier *getBase() const {
+ assert(getKind() == Base);
+ return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
+ }
+
+ /// \brief Retrieve the source range that covers this offsetof node.
+ ///
+ /// For an array element node, the source range contains the locations of
+ /// the square brackets. For a field or identifier node, the source range
+ /// contains the location of the period (if there is one) and the
+ /// identifier.
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+};
+
/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form
/// offsetof(record-type, member-designator). For example, given:
/// @code
@@ -1782,104 +1857,9 @@ public:
/// @endcode
/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d).
-class OffsetOfExpr : public Expr {
-public:
- // __builtin_offsetof(type, identifier(.identifier|[expr])*)
- class OffsetOfNode {
- public:
- /// \brief The kind of offsetof node we have.
- enum Kind {
- /// \brief An index into an array.
- Array = 0x00,
- /// \brief A field.
- Field = 0x01,
- /// \brief A field in a dependent type, known only by its name.
- Identifier = 0x02,
- /// \brief An implicit indirection through a C++ base class, when the
- /// field found is in a base class.
- Base = 0x03
- };
-
- private:
- enum { MaskBits = 2, Mask = 0x03 };
-
- /// \brief The source range that covers this part of the designator.
- SourceRange Range;
-
- /// \brief The data describing the designator, which comes in three
- /// different forms, depending on the lower two bits.
- /// - An unsigned index into the array of Expr*'s stored after this node
- /// in memory, for [constant-expression] designators.
- /// - A FieldDecl*, for references to a known field.
- /// - An IdentifierInfo*, for references to a field with a given name
- /// when the class type is dependent.
- /// - A CXXBaseSpecifier*, for references that look at a field in a
- /// base class.
- uintptr_t Data;
-
- public:
- /// \brief Create an offsetof node that refers to an array element.
- OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
- SourceLocation RBracketLoc)
- : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { }
-
- /// \brief Create an offsetof node that refers to a field.
- OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field,
- SourceLocation NameLoc)
- : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
- Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) { }
-
- /// \brief Create an offsetof node that refers to an identifier.
- OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
- SourceLocation NameLoc)
- : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
- Data(reinterpret_cast<uintptr_t>(Name) | Identifier) { }
-
- /// \brief Create an offsetof node that refers into a C++ base class.
- explicit OffsetOfNode(const CXXBaseSpecifier *Base)
- : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}
-
- /// \brief Determine what kind of offsetof node this is.
- Kind getKind() const {
- return static_cast<Kind>(Data & Mask);
- }
-
- /// \brief For an array element node, returns the index into the array
- /// of expressions.
- unsigned getArrayExprIndex() const {
- assert(getKind() == Array);
- return Data >> 2;
- }
-
- /// \brief For a field offsetof node, returns the field.
- FieldDecl *getField() const {
- assert(getKind() == Field);
- return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask);
- }
-
- /// \brief For a field or identifier offsetof node, returns the name of
- /// the field.
- IdentifierInfo *getFieldName() const;
-
- /// \brief For a base class node, returns the base specifier.
- CXXBaseSpecifier *getBase() const {
- assert(getKind() == Base);
- return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
- }
-
- /// \brief Retrieve the source range that covers this offsetof node.
- ///
- /// For an array element node, the source range contains the locations of
- /// the square brackets. For a field or identifier node, the source range
- /// contains the location of the period (if there is one) and the
- /// identifier.
- SourceRange getSourceRange() const LLVM_READONLY { return Range; }
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
- };
-
-private:
-
+class OffsetOfExpr final
+ : public Expr,
+ private llvm::TrailingObjects<OffsetOfExpr, OffsetOfNode, Expr *> {
SourceLocation OperatorLoc, RParenLoc;
// Base type;
TypeSourceInfo *TSInfo;
@@ -1888,6 +1868,10 @@ private:
// Number of sub-expressions (i.e. array subscript expressions).
unsigned NumExprs;
+ size_t numTrailingObjects(OverloadToken<OffsetOfNode>) const {
+ return NumComps;
+ }
+
OffsetOfExpr(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
@@ -1924,12 +1908,12 @@ public:
const OffsetOfNode &getComponent(unsigned Idx) const {
assert(Idx < NumComps && "Subscript out of range");
- return reinterpret_cast<const OffsetOfNode *> (this + 1)[Idx];
+ return getTrailingObjects<OffsetOfNode>()[Idx];
}
void setComponent(unsigned Idx, OffsetOfNode ON) {
assert(Idx < NumComps && "Subscript out of range");
- reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON;
+ getTrailingObjects<OffsetOfNode>()[Idx] = ON;
}
unsigned getNumComponents() const {
@@ -1938,17 +1922,17 @@ public:
Expr* getIndexExpr(unsigned Idx) {
assert(Idx < NumExprs && "Subscript out of range");
- return reinterpret_cast<Expr **>(
- reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx];
+ return getTrailingObjects<Expr *>()[Idx];
}
+
const Expr *getIndexExpr(unsigned Idx) const {
- return const_cast<OffsetOfExpr*>(this)->getIndexExpr(Idx);
+ assert(Idx < NumExprs && "Subscript out of range");
+ return getTrailingObjects<Expr *>()[Idx];
}
void setIndexExpr(unsigned Idx, Expr* E) {
assert(Idx < NumComps && "Subscript out of range");
- reinterpret_cast<Expr **>(
- reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E;
+ getTrailingObjects<Expr *>()[Idx] = E;
}
unsigned getNumExpressions() const {
@@ -1964,11 +1948,10 @@ public:
// Iterators
child_range children() {
- Stmt **begin =
- reinterpret_cast<Stmt**>(reinterpret_cast<OffsetOfNode*>(this + 1)
- + NumComps);
+ Stmt **begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
return child_range(begin, begin + NumExprs);
}
+ friend TrailingObjects;
};
/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated)
@@ -2142,7 +2125,6 @@ public:
}
};
-
/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
/// CallExpr itself represents a normal function call, e.g., "f(x, 2)",
/// while its subclasses may represent alternative syntax that (semantically)
@@ -2209,7 +2191,8 @@ public:
return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START);
}
const Expr *const *getArgs() const {
- return const_cast<CallExpr*>(this)->getArgs();
+ return reinterpret_cast<Expr **>(SubExprs + getNumPreArgs() +
+ PREARGS_START);
}
/// getArg - Return the specified argument.
@@ -2298,20 +2281,24 @@ public:
}
};
+/// Extra data stored in some MemberExpr objects.
+struct MemberExprNameQualifier {
+ /// \brief The nested-name-specifier that qualifies the name, including
+ /// source-location information.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// \brief The DeclAccessPair through which the MemberDecl was found due to
+ /// name qualifiers.
+ DeclAccessPair FoundDecl;
+};
+
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
///
-class MemberExpr : public Expr {
- /// Extra data stored in some member expressions.
- struct MemberNameQualifier {
- /// \brief The nested-name-specifier that qualifies the name, including
- /// source-location information.
- NestedNameSpecifierLoc QualifierLoc;
-
- /// \brief The DeclAccessPair through which the MemberDecl was found due to
- /// name qualifiers.
- DeclAccessPair FoundDecl;
- };
-
+class MemberExpr final
+ : public Expr,
+ private llvm::TrailingObjects<MemberExpr, MemberExprNameQualifier,
+ ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
/// Base - the expression for the base pointer or structure references. In
/// X.F, this is "X".
Stmt *Base;
@@ -2335,7 +2322,7 @@ class MemberExpr : public Expr {
/// \brief True if this member expression used a nested-name-specifier to
/// refer to the member, e.g., "x->Base::f", or found its member via a using
- /// declaration. When true, a MemberNameQualifier
+ /// declaration. When true, a MemberExprNameQualifier
/// structure is allocated immediately after the MemberExpr.
bool HasQualifierOrFoundDecl : 1;
@@ -2343,24 +2330,19 @@ class MemberExpr : public Expr {
/// and/or a template argument list explicitly, e.g., x->f<int>,
/// x->template f, x->template f<int>.
/// When true, an ASTTemplateKWAndArgsInfo structure and its
- /// TemplateArguments (if any) are allocated immediately after
- /// the MemberExpr or, if the member expression also has a qualifier,
- /// after the MemberNameQualifier structure.
+ /// TemplateArguments (if any) are present.
bool HasTemplateKWAndArgsInfo : 1;
/// \brief True if this member expression refers to a method that
/// was resolved from an overloaded set having size greater than 1.
bool HadMultipleCandidates : 1;
- /// \brief Retrieve the qualifier that preceded the member name, if any.
- MemberNameQualifier *getMemberQualifier() {
- assert(HasQualifierOrFoundDecl);
- return reinterpret_cast<MemberNameQualifier *> (this + 1);
+ size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const {
+ return HasQualifierOrFoundDecl ? 1 : 0;
}
- /// \brief Retrieve the qualifier that preceded the member name, if any.
- const MemberNameQualifier *getMemberQualifier() const {
- return const_cast<MemberExpr *>(this)->getMemberQualifier();
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
}
public:
@@ -2416,7 +2398,7 @@ public:
if (!HasQualifierOrFoundDecl)
return DeclAccessPair::make(getMemberDecl(),
getMemberDecl()->getAccess());
- return getMemberQualifier()->FoundDecl;
+ return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl;
}
/// \brief Determines whether this member expression actually had
@@ -2425,61 +2407,41 @@ public:
bool hasQualifier() const { return getQualifier() != nullptr; }
/// \brief If the member name was qualified, retrieves the
- /// nested-name-specifier that precedes the member name. Otherwise, returns
- /// NULL.
- NestedNameSpecifier *getQualifier() const {
- if (!HasQualifierOrFoundDecl)
- return nullptr;
-
- return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier();
- }
-
- /// \brief If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name, with source-location
/// information.
NestedNameSpecifierLoc getQualifierLoc() const {
- if (!hasQualifier())
- return NestedNameSpecifierLoc();
-
- return getMemberQualifier()->QualifierLoc;
- }
-
- /// \brief Return the optional template keyword and arguments info.
- ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
- if (!HasTemplateKWAndArgsInfo)
- return nullptr;
-
if (!HasQualifierOrFoundDecl)
- return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1);
+ return NestedNameSpecifierLoc();
- return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
- getMemberQualifier() + 1);
+ return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc;
}
- /// \brief Return the optional template keyword and arguments info.
- const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const {
- return const_cast<MemberExpr*>(this)->getTemplateKWAndArgsInfo();
+ /// \brief If the member name was qualified, retrieves the
+ /// nested-name-specifier that precedes the member name. Otherwise, returns
+ /// NULL.
+ NestedNameSpecifier *getQualifier() const {
+ return getQualifierLoc().getNestedNameSpecifier();
}
/// \brief Retrieve the location of the template keyword preceding
/// the member name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
/// \brief Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the member name, if any.
SourceLocation getLAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->LAngleLoc;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
/// \brief Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the member name, if any.
SourceLocation getRAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->RAngleLoc;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
}
/// Determines whether the member name was preceded by the template keyword.
@@ -2493,30 +2455,8 @@ public:
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
- getExplicitTemplateArgs().copyInto(List);
- }
-
- /// \brief Retrieve the explicit template argument list that
- /// follow the member template name. This must only be called on an
- /// expression with explicit template arguments.
- ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
- assert(hasExplicitTemplateArgs());
- return *getTemplateKWAndArgsInfo();
- }
-
- /// \brief Retrieve the explicit template argument list that
- /// followed the member template name. This must only be called on
- /// an expression with explicit template arguments.
- const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
- return const_cast<MemberExpr *>(this)->getExplicitTemplateArgs();
- }
-
- /// \brief Retrieves the optional explicit template arguments.
- /// This points to the same data as getExplicitTemplateArgs(), but
- /// returns null if there are no explicit template arguments.
- const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
- if (!hasExplicitTemplateArgs()) return nullptr;
- return &getExplicitTemplateArgs();
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
+ getTrailingObjects<TemplateArgumentLoc>(), List);
}
/// \brief Retrieve the template arguments provided as part of this
@@ -2525,7 +2465,7 @@ public:
if (!hasExplicitTemplateArgs())
return nullptr;
- return getExplicitTemplateArgs().getTemplateArgs();
+ return getTrailingObjects<TemplateArgumentLoc>();
}
/// \brief Retrieve the number of template arguments provided as part of this
@@ -2534,7 +2474,7 @@ public:
if (!hasExplicitTemplateArgs())
return 0;
- return getExplicitTemplateArgs().NumTemplateArgs;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
}
/// \brief Retrieve the member declaration name info.
@@ -2575,6 +2515,14 @@ public:
HadMultipleCandidates = V;
}
+ /// \brief Returns true if virtual dispatch is performed.
+ /// If the member access is fully qualified, (i.e. X::f()), virtual
+ /// dispatching is not performed. In -fapple-kext mode qualified
+ /// calls to virtual method will still go through the vtable.
+ bool performsVirtualDispatch(const LangOptions &LO) const {
+ return LO.AppleKext || !hasQualifier();
+ }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == MemberExprClass;
}
@@ -2582,6 +2530,7 @@ public:
// Iterators
child_range children() { return child_range(&Base, &Base+1); }
+ friend TrailingObjects;
friend class ASTReader;
friend class ASTStmtWriter;
};
@@ -2731,8 +2680,6 @@ public:
path_const_iterator path_begin() const { return path_buffer(); }
path_const_iterator path_end() const { return path_buffer() + path_size(); }
- void setCastPath(const CXXCastPath &Path);
-
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCastExprConstant &&
T->getStmtClass() <= lastCastExprConstant;
@@ -2762,7 +2709,9 @@ public:
/// // to an xvalue of type Base
/// }
/// @endcode
-class ImplicitCastExpr : public CastExpr {
+class ImplicitCastExpr final
+ : public CastExpr,
+ private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> {
private:
ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
unsigned BasePathLength, ExprValueKind VK)
@@ -2798,6 +2747,9 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImplicitCastExprClass;
}
+
+ friend TrailingObjects;
+ friend class CastExpr;
};
inline Expr *Expr::IgnoreImpCasts() {
@@ -2857,7 +2809,9 @@ public:
/// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style
/// cast in C++ (C++ [expr.cast]), which uses the syntax
/// (Type)expr. For example: @c (int)f.
-class CStyleCastExpr : public ExplicitCastExpr {
+class CStyleCastExpr final
+ : public ExplicitCastExpr,
+ private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
@@ -2895,6 +2849,9 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CStyleCastExprClass;
}
+
+ friend TrailingObjects;
+ friend class CastExpr;
};
/// \brief A builtin binary operation expression such as "x + y" or "x <= y".
@@ -2989,7 +2946,10 @@ public:
/// predicates to categorize the respective opcodes.
bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; }
- bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; }
+ static bool isMultiplicativeOp(Opcode Opc) {
+ return Opc >= BO_Mul && Opc <= BO_Rem;
+ }
+ bool isMultiplicativeOp() const { return isMultiplicativeOp(getOpcode()); }
static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; }
bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); }
static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; }
@@ -3384,7 +3344,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
@@ -3429,7 +3391,6 @@ public:
child_range children() { return child_range(&SubStmt, &SubStmt+1); }
};
-
/// ShuffleVectorExpr - clang-specific builtin-in function
/// __builtin_shufflevector.
/// This AST node represents a operator that does a constant
@@ -3663,36 +3624,40 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
-/// VAArgExpr, used for the builtin function __builtin_va_arg.
+/// Represents a call to the builtin function \c __builtin_va_arg.
class VAArgExpr : public Expr {
Stmt *Val;
- TypeSourceInfo *TInfo;
+ llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfo;
SourceLocation BuiltinLoc, RParenLoc;
public:
- VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo,
- SourceLocation RPLoc, QualType t)
- : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary,
- t->isDependentType(), false,
- (TInfo->getType()->isInstantiationDependentType() ||
- e->isInstantiationDependent()),
- (TInfo->getType()->containsUnexpandedParameterPack() ||
- e->containsUnexpandedParameterPack())),
- Val(e), TInfo(TInfo),
- BuiltinLoc(BLoc),
- RParenLoc(RPLoc) { }
-
- /// \brief Create an empty __builtin_va_arg expression.
- explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { }
+ VAArgExpr(SourceLocation BLoc, Expr *e, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc, QualType t, bool IsMS)
+ : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary, t->isDependentType(),
+ false, (TInfo->getType()->isInstantiationDependentType() ||
+ e->isInstantiationDependent()),
+ (TInfo->getType()->containsUnexpandedParameterPack() ||
+ e->containsUnexpandedParameterPack())),
+ Val(e), TInfo(TInfo, IsMS), BuiltinLoc(BLoc), RParenLoc(RPLoc) {}
+
+ /// Create an empty __builtin_va_arg expression.
+ explicit VAArgExpr(EmptyShell Empty)
+ : Expr(VAArgExprClass, Empty), Val(nullptr), TInfo(nullptr, false) {}
const Expr *getSubExpr() const { return cast<Expr>(Val); }
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
- TypeSourceInfo *getWrittenTypeInfo() const { return TInfo; }
- void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo = TI; }
+ /// Returns whether this is really a Win64 ABI va_arg expression.
+ bool isMicrosoftABI() const { return TInfo.getInt(); }
+ void setIsMicrosoftABI(bool IsMS) { TInfo.setInt(IsMS); }
+
+ TypeSourceInfo *getWrittenTypeInfo() const { return TInfo.getPointer(); }
+ void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo.setPointer(TI); }
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
@@ -3791,6 +3756,10 @@ public:
/// \brief Retrieve the set of initializers.
Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); }
+ ArrayRef<Expr *> inits() {
+ return llvm::makeArrayRef(getInits(), getNumInits());
+ }
+
const Expr *getInit(unsigned Init) const {
assert(Init < getNumInits() && "Initializer access out of range!");
return cast_or_null<Expr>(InitExprs[Init]);
@@ -3916,7 +3885,8 @@ public:
// Iterators
child_range children() {
// FIXME: This does not include the array filler expression.
- if (InitExprs.empty()) return child_range();
+ if (InitExprs.empty())
+ return child_range(child_iterator(), child_iterator());
return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
}
@@ -3958,7 +3928,9 @@ public:
/// which covers @c [2].y=1.0. This DesignatedInitExpr will have two
/// designators, one array designator for @c [2] followed by one field
/// designator for @c .y. The initialization expression will be 1.0.
-class DesignatedInitExpr : public Expr {
+class DesignatedInitExpr final
+ : public Expr,
+ private llvm::TrailingObjects<DesignatedInitExpr, Stmt *> {
public:
/// \brief Forward declaration of the Designator class.
class Designator;
@@ -4238,12 +4210,12 @@ public:
Expr *getSubExpr(unsigned Idx) const {
assert(Idx < NumSubExprs && "Subscript out of range");
- return cast<Expr>(reinterpret_cast<Stmt *const *>(this + 1)[Idx]);
+ return cast<Expr>(getTrailingObjects<Stmt *>()[Idx]);
}
void setSubExpr(unsigned Idx, Expr *E) {
assert(Idx < NumSubExprs && "Subscript out of range");
- reinterpret_cast<Stmt **>(this + 1)[Idx] = E;
+ getTrailingObjects<Stmt *>()[Idx] = E;
}
/// \brief Replaces the designator at index @p Idx with the series
@@ -4262,9 +4234,11 @@ public:
// Iterators
child_range children() {
- Stmt **begin = reinterpret_cast<Stmt**>(this + 1);
+ Stmt **begin = getTrailingObjects<Stmt *>();
return child_range(begin, begin + NumSubExprs);
}
+
+ friend TrailingObjects;
};
/// \brief Represents a place-holder for an object not to be initialized by
@@ -4293,7 +4267,9 @@ public:
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
// In cases like:
@@ -4367,10 +4343,11 @@ public:
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
-
class ParenListExpr : public Expr {
Stmt **Exprs;
unsigned NumExprs;
@@ -4397,6 +4374,10 @@ public:
Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); }
+ ArrayRef<Expr *> exprs() {
+ return llvm::makeArrayRef(getExprs(), getNumExprs());
+ }
+
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -4416,7 +4397,6 @@ public:
friend class ASTStmtWriter;
};
-
/// \brief Represents a C11 generic selection.
///
/// A generic selection (C11 6.5.1.1) contains an unevaluated controlling
@@ -4532,7 +4512,6 @@ public:
// Clang Extensions
//===----------------------------------------------------------------------===//
-
/// ExtVectorElementExpr - This represents access to specific elements of a
/// vector, and may occur on the left hand side or right hand side. For example
/// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector.
@@ -4577,7 +4556,7 @@ public:
/// getEncodedElementAccess - Encode the elements accessed into an llvm
/// aggregate Constant of ConstantInt(s).
- void getEncodedElementAccess(SmallVectorImpl<unsigned> &Elts) const;
+ void getEncodedElementAccess(SmallVectorImpl<uint32_t> &Elts) const;
SourceLocation getLocStart() const LLVM_READONLY {
return getBase()->getLocStart();
@@ -4596,7 +4575,6 @@ public:
child_range children() { return child_range(&Base, &Base+1); }
};
-
/// BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
class BlockExpr : public Expr {
@@ -4633,7 +4611,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2]
@@ -4709,7 +4689,9 @@ public:
/// equivalent to a particular message send, and this is very much
/// part of the user model. The name of this class encourages this
/// modelling design.
-class PseudoObjectExpr : public Expr {
+class PseudoObjectExpr final
+ : public Expr,
+ private llvm::TrailingObjects<PseudoObjectExpr, Expr *> {
// PseudoObjectExprBits.NumSubExprs - The number of sub-expressions.
// Always at least two, because the first sub-expression is the
// syntactic form.
@@ -4721,13 +4703,11 @@ class PseudoObjectExpr : public Expr {
// in to Create, which is an index within the semantic forms.
// Note also that ASTStmtWriter assumes this encoding.
- Expr **getSubExprsBuffer() { return reinterpret_cast<Expr**>(this + 1); }
+ Expr **getSubExprsBuffer() { return getTrailingObjects<Expr *>(); }
const Expr * const *getSubExprsBuffer() const {
- return reinterpret_cast<const Expr * const *>(this + 1);
+ return getTrailingObjects<Expr *>();
}
- friend class ASTStmtReader;
-
PseudoObjectExpr(QualType type, ExprValueKind VK,
Expr *syntactic, ArrayRef<Expr*> semantic,
unsigned resultIndex);
@@ -4789,6 +4769,14 @@ public:
const_semantics_iterator semantics_end() const {
return getSubExprsBuffer() + getNumSubExprs();
}
+
+ llvm::iterator_range<semantics_iterator> semantics() {
+ return llvm::make_range(semantics_begin(), semantics_end());
+ }
+ llvm::iterator_range<const_semantics_iterator> semantics() const {
+ return llvm::make_range(semantics_begin(), semantics_end());
+ }
+
Expr *getSemanticExpr(unsigned index) {
assert(index + 1 < getNumSubExprs());
return getSubExprsBuffer()[index + 1];
@@ -4816,6 +4804,9 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == PseudoObjectExprClass;
}
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
};
/// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*,
@@ -4935,10 +4926,17 @@ public:
assert(T->isDependentType() && "TypoExpr given a non-dependent type");
}
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == TypoExprClass;
+ }
+
};
-} // end namespace clang
+} // end namespace clang
-#endif
+#endif // LLVM_CLANG_AST_EXPR_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
index 1dbf574..6821274 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
@@ -235,7 +235,9 @@ public:
///
/// This expression node represents a C++ static cast, e.g.,
/// \c static_cast<int>(1.0).
-class CXXStaticCastExpr : public CXXNamedCastExpr {
+class CXXStaticCastExpr final
+ : public CXXNamedCastExpr,
+ private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> {
CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation RParenLoc,
@@ -259,6 +261,9 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXStaticCastExprClass;
}
+
+ friend TrailingObjects;
+ friend class CastExpr;
};
/// \brief A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]).
@@ -266,7 +271,9 @@ public:
/// This expression node represents a dynamic cast, e.g.,
/// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time
/// check to determine how to perform the type conversion.
-class CXXDynamicCastExpr : public CXXNamedCastExpr {
+class CXXDynamicCastExpr final
+ : public CXXNamedCastExpr,
+ private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> {
CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind,
Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation RParenLoc,
@@ -293,6 +300,9 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDynamicCastExprClass;
}
+
+ friend TrailingObjects;
+ friend class CastExpr;
};
/// \brief A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]).
@@ -303,7 +313,10 @@ public:
/// A reinterpret_cast provides a differently-typed view of a value but
/// (in Clang, as in most C++ implementations) performs no actual work at
/// run time.
-class CXXReinterpretCastExpr : public CXXNamedCastExpr {
+class CXXReinterpretCastExpr final
+ : public CXXNamedCastExpr,
+ private llvm::TrailingObjects<CXXReinterpretCastExpr,
+ CXXBaseSpecifier *> {
CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind,
Expr *op, unsigned pathSize,
TypeSourceInfo *writtenTy, SourceLocation l,
@@ -328,6 +341,9 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXReinterpretCastExprClass;
}
+
+ friend TrailingObjects;
+ friend class CastExpr;
};
/// \brief A C++ \c const_cast expression (C++ [expr.const.cast]).
@@ -337,7 +353,9 @@ public:
///
/// A const_cast can remove type qualifiers but does not change the underlying
/// value.
-class CXXConstCastExpr : public CXXNamedCastExpr {
+class CXXConstCastExpr final
+ : public CXXNamedCastExpr,
+ private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> {
CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
TypeSourceInfo *writtenTy, SourceLocation l,
SourceLocation RParenLoc, SourceRange AngleBrackets)
@@ -358,6 +376,9 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstCastExprClass;
}
+
+ friend TrailingObjects;
+ friend class CastExpr;
};
/// \brief A call to a literal operator (C++11 [over.literal])
@@ -457,7 +478,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief The null pointer literal (C++11 [lex.nullptr])
@@ -484,7 +507,9 @@ public:
return T->getStmtClass() == CXXNullPtrLiteralExprClass;
}
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief Implicit construction of a std::initializer_list<T> object from an
@@ -607,7 +632,8 @@ public:
// Iterators
child_range children() {
- if (isTypeOperand()) return child_range();
+ if (isTypeOperand())
+ return child_range(child_iterator(), child_iterator());
Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
return child_range(begin, begin + 1);
}
@@ -672,6 +698,69 @@ public:
friend class ASTStmtReader;
};
+/// MS property subscript expression.
+/// MSVC supports 'property' attribute and allows to apply it to the
+/// declaration of an empty array in a class or structure definition.
+/// For example:
+/// \code
+/// __declspec(property(get=GetX, put=PutX)) int x[];
+/// \endcode
+/// The above statement indicates that x[] can be used with one or more array
+/// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), and
+/// p->x[a][b] = i will be turned into p->PutX(a, b, i).
+/// This is a syntactic pseudo-object expression.
+class MSPropertySubscriptExpr : public Expr {
+ friend class ASTStmtReader;
+ enum { BASE_EXPR, IDX_EXPR, NUM_SUBEXPRS = 2 };
+ Stmt *SubExprs[NUM_SUBEXPRS];
+ SourceLocation RBracketLoc;
+
+ void setBase(Expr *Base) { SubExprs[BASE_EXPR] = Base; }
+ void setIdx(Expr *Idx) { SubExprs[IDX_EXPR] = Idx; }
+
+public:
+ MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK,
+ ExprObjectKind OK, SourceLocation RBracketLoc)
+ : Expr(MSPropertySubscriptExprClass, Ty, VK, OK, Idx->isTypeDependent(),
+ Idx->isValueDependent(), Idx->isInstantiationDependent(),
+ Idx->containsUnexpandedParameterPack()),
+ RBracketLoc(RBracketLoc) {
+ SubExprs[BASE_EXPR] = Base;
+ SubExprs[IDX_EXPR] = Idx;
+ }
+
+ /// \brief Create an empty array subscript expression.
+ explicit MSPropertySubscriptExpr(EmptyShell Shell)
+ : Expr(MSPropertySubscriptExprClass, Shell) {}
+
+ Expr *getBase() { return cast<Expr>(SubExprs[BASE_EXPR]); }
+ const Expr *getBase() const { return cast<Expr>(SubExprs[BASE_EXPR]); }
+
+ Expr *getIdx() { return cast<Expr>(SubExprs[IDX_EXPR]); }
+ const Expr *getIdx() const { return cast<Expr>(SubExprs[IDX_EXPR]); }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBase()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
+
+ SourceLocation getRBracketLoc() const { return RBracketLoc; }
+ void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
+
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ return getBase()->getExprLoc();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MSPropertySubscriptExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS);
+ }
+};
+
/// A Microsoft C++ @c __uuidof expression, which gets
/// the _GUID that corresponds to the supplied type or expression.
///
@@ -749,7 +838,8 @@ public:
// Iterators
child_range children() {
- if (isTypeOperand()) return child_range();
+ if (isTypeOperand())
+ return child_range(child_iterator(), child_iterator());
Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
return child_range(begin, begin + 1);
}
@@ -797,7 +887,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief A C++ throw-expression (C++ [except.throw]).
@@ -859,13 +951,9 @@ public:
/// This wraps up a function call argument that was created from the
/// corresponding parameter's default argument, when the call did not
/// explicitly supply arguments for all of the parameters.
-class CXXDefaultArgExpr : public Expr {
+class CXXDefaultArgExpr final : public Expr {
/// \brief The parameter whose default is being used.
- ///
- /// When the bit is set, the subexpression is stored after the
- /// CXXDefaultArgExpr itself. When the bit is clear, the parameter's
- /// actual default expression is the subexpression.
- llvm::PointerIntPair<ParmVarDecl *, 1, bool> Param;
+ ParmVarDecl *Param;
/// \brief The location where the default argument expression was used.
SourceLocation Loc;
@@ -877,16 +965,7 @@ class CXXDefaultArgExpr : public Expr {
: param->getDefaultArg()->getType(),
param->getDefaultArg()->getValueKind(),
param->getDefaultArg()->getObjectKind(), false, false, false, false),
- Param(param, false), Loc(Loc) { }
-
- CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param,
- Expr *SubExpr)
- : Expr(SC, SubExpr->getType(),
- SubExpr->getValueKind(), SubExpr->getObjectKind(),
- false, false, false, false),
- Param(param, true), Loc(Loc) {
- *reinterpret_cast<Expr **>(this + 1) = SubExpr;
- }
+ Param(param), Loc(Loc) { }
public:
CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
@@ -898,24 +977,15 @@ public:
return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param);
}
- // \p Param is the parameter whose default argument is used by this
- // expression, and \p SubExpr is the expression that will actually be used.
- static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc,
- ParmVarDecl *Param, Expr *SubExpr);
-
// Retrieve the parameter that the argument was created from.
- const ParmVarDecl *getParam() const { return Param.getPointer(); }
- ParmVarDecl *getParam() { return Param.getPointer(); }
+ const ParmVarDecl *getParam() const { return Param; }
+ ParmVarDecl *getParam() { return Param; }
// Retrieve the actual argument to the function call.
const Expr *getExpr() const {
- if (Param.getInt())
- return *reinterpret_cast<Expr const * const*> (this + 1);
return getParam()->getDefaultArg();
}
Expr *getExpr() {
- if (Param.getInt())
- return *reinterpret_cast<Expr **> (this + 1);
return getParam()->getDefaultArg();
}
@@ -935,7 +1005,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
friend class ASTStmtReader;
friend class ASTStmtWriter;
@@ -991,7 +1063,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
friend class ASTReader;
friend class ASTStmtReader;
@@ -1238,7 +1312,9 @@ public:
/// \code
/// x = int(0.5);
/// \endcode
-class CXXFunctionalCastExpr : public ExplicitCastExpr {
+class CXXFunctionalCastExpr final
+ : public ExplicitCastExpr,
+ private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> {
SourceLocation LParenLoc;
SourceLocation RParenLoc;
@@ -1275,6 +1351,9 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXFunctionalCastExprClass;
}
+
+ friend TrailingObjects;
+ friend class CastExpr;
};
/// @brief Represents a C++ functional cast expression that builds a
@@ -1340,7 +1419,9 @@ public:
/// C++1y introduces a new form of "capture" called an init-capture that
/// includes an initializing expression (rather than capturing a variable),
/// and which can never occur implicitly.
-class LambdaExpr : public Expr {
+class LambdaExpr final
+ : public Expr,
+ private llvm::TrailingObjects<LambdaExpr, Stmt *, unsigned, VarDecl *> {
/// \brief The source range that covers the lambda introducer ([...]).
SourceRange IntroducerRange;
@@ -1375,23 +1456,21 @@ class LambdaExpr : public Expr {
/// module file just to determine the source range.
SourceLocation ClosingBrace;
- // Note: The capture initializers are stored directly after the lambda
- // expression, along with the index variables used to initialize by-copy
- // array captures.
+ size_t numTrailingObjects(OverloadToken<Stmt *>) const {
+ return NumCaptures + 1;
+ }
- typedef LambdaCapture Capture;
+ size_t numTrailingObjects(OverloadToken<unsigned>) const {
+ return HasArrayIndexVars ? NumCaptures + 1 : 0;
+ }
/// \brief Construct a lambda expression.
LambdaExpr(QualType T, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
- SourceLocation CaptureDefaultLoc,
- ArrayRef<Capture> Captures,
- bool ExplicitParams,
- bool ExplicitResultType,
- ArrayRef<Expr *> CaptureInits,
- ArrayRef<VarDecl *> ArrayIndexVars,
- ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace,
+ SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
+ bool ExplicitParams, bool ExplicitResultType,
+ ArrayRef<Expr *> CaptureInits, ArrayRef<VarDecl *> ArrayIndexVars,
+ ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack);
/// \brief Construct an empty lambda expression.
@@ -1401,40 +1480,36 @@ class LambdaExpr : public Expr {
ExplicitResultType(false), HasArrayIndexVars(true) {
getStoredStmts()[NumCaptures] = nullptr;
}
-
- Stmt **getStoredStmts() const {
- return reinterpret_cast<Stmt **>(const_cast<LambdaExpr *>(this) + 1);
- }
-
+
+ Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); }
+
+ Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); }
+
/// \brief Retrieve the mapping from captures to the first array index
/// variable.
- unsigned *getArrayIndexStarts() const {
- return reinterpret_cast<unsigned *>(getStoredStmts() + NumCaptures + 1);
+ unsigned *getArrayIndexStarts() { return getTrailingObjects<unsigned>(); }
+
+ const unsigned *getArrayIndexStarts() const {
+ return getTrailingObjects<unsigned>();
}
/// \brief Retrieve the complete set of array-index variables.
- VarDecl **getArrayIndexVars() const {
- unsigned ArrayIndexSize = llvm::RoundUpToAlignment(
- sizeof(unsigned) * (NumCaptures + 1), llvm::alignOf<VarDecl *>());
- return reinterpret_cast<VarDecl **>(
- reinterpret_cast<char *>(getArrayIndexStarts()) + ArrayIndexSize);
+ VarDecl **getArrayIndexVars() { return getTrailingObjects<VarDecl *>(); }
+
+ VarDecl *const *getArrayIndexVars() const {
+ return getTrailingObjects<VarDecl *>();
}
public:
/// \brief Construct a new lambda expression.
- static LambdaExpr *Create(const ASTContext &C,
- CXXRecordDecl *Class,
- SourceRange IntroducerRange,
- LambdaCaptureDefault CaptureDefault,
- SourceLocation CaptureDefaultLoc,
- ArrayRef<Capture> Captures,
- bool ExplicitParams,
- bool ExplicitResultType,
- ArrayRef<Expr *> CaptureInits,
- ArrayRef<VarDecl *> ArrayIndexVars,
- ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace,
- bool ContainsUnexpandedParameterPack);
+ static LambdaExpr *
+ Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange,
+ LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc,
+ ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
+ bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
+ ArrayRef<VarDecl *> ArrayIndexVars,
+ ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace,
+ bool ContainsUnexpandedParameterPack);
/// \brief Construct a new lambda expression that will be deserialized from
/// an external source.
@@ -1457,7 +1532,7 @@ public:
/// \brief An iterator that walks over the captures of the lambda,
/// both implicit and explicit.
- typedef const Capture *capture_iterator;
+ typedef const LambdaCapture *capture_iterator;
/// \brief An iterator over a range of lambda captures.
typedef llvm::iterator_range<capture_iterator> capture_range;
@@ -1501,31 +1576,52 @@ public:
/// arguments.
typedef Expr **capture_init_iterator;
+ /// \brief Const iterator that walks over the capture initialization
+ /// arguments.
+ typedef Expr *const *const_capture_init_iterator;
+
+ /// \brief Retrieve the initialization expressions for this lambda's captures.
+ llvm::iterator_range<capture_init_iterator> capture_inits() {
+ return llvm::make_range(capture_init_begin(), capture_init_end());
+ }
+
/// \brief Retrieve the initialization expressions for this lambda's captures.
- llvm::iterator_range<capture_init_iterator> capture_inits() const {
- return llvm::iterator_range<capture_init_iterator>(capture_init_begin(),
- capture_init_end());
+ llvm::iterator_range<const_capture_init_iterator> capture_inits() const {
+ return llvm::make_range(capture_init_begin(), capture_init_end());
}
/// \brief Retrieve the first initialization argument for this
/// lambda expression (which initializes the first capture field).
- capture_init_iterator capture_init_begin() const {
+ capture_init_iterator capture_init_begin() {
return reinterpret_cast<Expr **>(getStoredStmts());
}
+ /// \brief Retrieve the first initialization argument for this
+ /// lambda expression (which initializes the first capture field).
+ const_capture_init_iterator capture_init_begin() const {
+ return reinterpret_cast<Expr *const *>(getStoredStmts());
+ }
+
+ /// \brief Retrieve the iterator pointing one past the last
+ /// initialization argument for this lambda expression.
+ capture_init_iterator capture_init_end() {
+ return capture_init_begin() + NumCaptures;
+ }
+
/// \brief Retrieve the iterator pointing one past the last
/// initialization argument for this lambda expression.
- capture_init_iterator capture_init_end() const {
- return capture_init_begin() + NumCaptures;
+ const_capture_init_iterator capture_init_end() const {
+ return capture_init_begin() + NumCaptures;
}
- /// \brief Retrieve the set of index variables used in the capture
+ /// \brief Retrieve the set of index variables used in the capture
/// initializer of an array captured by copy.
///
- /// \param Iter The iterator that points at the capture initializer for
+ /// \param Iter The iterator that points at the capture initializer for
/// which we are extracting the corresponding index variables.
- ArrayRef<VarDecl *> getCaptureInitIndexVars(capture_init_iterator Iter) const;
-
+ ArrayRef<VarDecl *>
+ getCaptureInitIndexVars(const_capture_init_iterator Iter) const;
+
/// \brief Retrieve the source range covering the lambda introducer,
/// which contains the explicit capture list surrounded by square
/// brackets ([...]).
@@ -1573,9 +1669,11 @@ public:
SourceLocation getLocEnd() const LLVM_READONLY { return ClosingBrace; }
child_range children() {
+ // Includes initialization exprs plus body stmt
return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1);
}
+ friend TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
@@ -1615,7 +1713,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief Represents a new-expression for memory allocation and constructor
@@ -1770,6 +1870,14 @@ public:
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
+ llvm::iterator_range<arg_iterator> placement_arguments() {
+ return llvm::make_range(placement_arg_begin(), placement_arg_end());
+ }
+
+ llvm::iterator_range<const_arg_iterator> placement_arguments() const {
+ return llvm::make_range(placement_arg_begin(), placement_arg_end());
+ }
+
arg_iterator placement_arg_begin() {
return SubExprs + Array + hasInitializer();
}
@@ -2080,7 +2188,9 @@ public:
/// __is_enum(std::string) == false
/// __is_trivially_constructible(vector<int>, int*, int*)
/// \endcode
-class TypeTraitExpr : public Expr {
+class TypeTraitExpr final
+ : public Expr,
+ private llvm::TrailingObjects<TypeTraitExpr, TypeSourceInfo *> {
/// \brief The location of the type trait keyword.
SourceLocation Loc;
@@ -2097,16 +2207,10 @@ class TypeTraitExpr : public Expr {
TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) { }
- /// \brief Retrieve the argument types.
- TypeSourceInfo **getTypeSourceInfos() {
- return reinterpret_cast<TypeSourceInfo **>(this+1);
+ size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const {
+ return getNumArgs();
}
-
- /// \brief Retrieve the argument types.
- TypeSourceInfo * const *getTypeSourceInfos() const {
- return reinterpret_cast<TypeSourceInfo * const*>(this+1);
- }
-
+
public:
/// \brief Create a new type trait expression.
static TypeTraitExpr *Create(const ASTContext &C, QualType T,
@@ -2138,22 +2242,9 @@ public:
}
/// \brief Retrieve the argument types.
- ArrayRef<TypeSourceInfo *> getArgs() const {
- return llvm::makeArrayRef(getTypeSourceInfos(), getNumArgs());
- }
-
- typedef TypeSourceInfo **arg_iterator;
- arg_iterator arg_begin() {
- return getTypeSourceInfos();
- }
- arg_iterator arg_end() {
- return getTypeSourceInfos() + getNumArgs();
- }
-
- typedef TypeSourceInfo const * const *arg_const_iterator;
- arg_const_iterator arg_begin() const { return getTypeSourceInfos(); }
- arg_const_iterator arg_end() const {
- return getTypeSourceInfos() + getNumArgs();
+ ArrayRef<TypeSourceInfo *> getArgs() const {
+ return llvm::makeArrayRef(getTrailingObjects<TypeSourceInfo *>(),
+ getNumArgs());
}
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
@@ -2164,11 +2255,13 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
-
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ friend TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
-
};
/// \brief An Embarcadero array type trait, as used in the implementation of
@@ -2237,7 +2330,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
friend class ASTStmtReader;
};
@@ -2294,7 +2389,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
friend class ASTStmtReader;
};
@@ -2322,13 +2419,18 @@ protected:
bool HasTemplateKWAndArgsInfo;
/// \brief Return the optional template keyword and arguments info.
- ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo(); // defined far below.
+ ASTTemplateKWAndArgsInfo *
+ getTrailingASTTemplateKWAndArgsInfo(); // defined far below.
/// \brief Return the optional template keyword and arguments info.
- const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const {
- return const_cast<OverloadExpr*>(this)->getTemplateKWAndArgsInfo();
+ const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const {
+ return const_cast<OverloadExpr *>(this)
+ ->getTrailingASTTemplateKWAndArgsInfo();
}
+ /// Return the optional template arguments.
+ TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); // defined far below
+
OverloadExpr(StmtClass K, const ASTContext &C,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
@@ -2391,7 +2493,7 @@ public:
return UnresolvedSetIterator(Results + NumResults);
}
llvm::iterator_range<decls_iterator> decls() const {
- return llvm::iterator_range<decls_iterator>(decls_begin(), decls_end());
+ return llvm::make_range(decls_begin(), decls_end());
}
/// \brief Gets the number of declarations in the unresolved set.
@@ -2419,21 +2521,21 @@ public:
/// this name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc();
+ return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc;
}
/// \brief Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the name, if any.
SourceLocation getLAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->LAngleLoc;
+ return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc;
}
/// \brief Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the name, if any.
SourceLocation getRAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->RAngleLoc;
+ return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc;
}
/// \brief Determines whether the name was preceded by the template keyword.
@@ -2442,39 +2544,23 @@ public:
/// \brief Determines whether this expression had explicit template arguments.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
- // Note that, inconsistently with the explicit-template-argument AST
- // nodes, users are *forbidden* from calling these methods on objects
- // without explicit template arguments.
-
- ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
- assert(hasExplicitTemplateArgs());
- return *getTemplateKWAndArgsInfo();
- }
-
- const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
- return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs();
- }
-
TemplateArgumentLoc const *getTemplateArgs() const {
- return getExplicitTemplateArgs().getTemplateArgs();
+ if (!hasExplicitTemplateArgs())
+ return nullptr;
+ return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc();
}
unsigned getNumTemplateArgs() const {
- return getExplicitTemplateArgs().NumTemplateArgs;
+ if (!hasExplicitTemplateArgs())
+ return 0;
+
+ return getTrailingASTTemplateKWAndArgsInfo()->NumTemplateArgs;
}
/// \brief Copies the template arguments into the given structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
- getExplicitTemplateArgs().copyInto(List);
- }
-
- /// \brief Retrieves the optional explicit template arguments.
- ///
- /// This points to the same data as getExplicitTemplateArgs(), but
- /// returns null if there are no explicit template arguments.
- const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
- if (!hasExplicitTemplateArgs()) return nullptr;
- return &getExplicitTemplateArgs();
+ if (hasExplicitTemplateArgs())
+ getTrailingASTTemplateKWAndArgsInfo()->copyInto(getTemplateArgs(), List);
}
static bool classof(const Stmt *T) {
@@ -2497,7 +2583,10 @@ public:
///
/// These never include UnresolvedUsingValueDecls, which are always class
/// members and therefore appear only in UnresolvedMemberLookupExprs.
-class UnresolvedLookupExpr : public OverloadExpr {
+class UnresolvedLookupExpr final
+ : public OverloadExpr,
+ private llvm::TrailingObjects<
+ UnresolvedLookupExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
/// True if these lookup results should be extended by
/// argument-dependent lookup if this is the operand of a function
/// call.
@@ -2514,6 +2603,10 @@ class UnresolvedLookupExpr : public OverloadExpr {
/// against the qualified-lookup bits.
CXXRecordDecl *NamingClass;
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
+ }
+
UnresolvedLookupExpr(const ASTContext &C,
CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc QualifierLoc,
@@ -2533,6 +2626,8 @@ class UnresolvedLookupExpr : public OverloadExpr {
RequiresADL(false), Overloaded(false), NamingClass(nullptr)
{}
+ friend TrailingObjects;
+ friend class OverloadExpr;
friend class ASTStmtReader;
public:
@@ -2585,7 +2680,9 @@ public:
return getNameInfo().getLocEnd();
}
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedLookupExprClass;
@@ -2606,7 +2703,11 @@ public:
/// qualifier (X<T>::) and the name of the entity being referenced
/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
/// declaration can be found.
-class DependentScopeDeclRefExpr : public Expr {
+class DependentScopeDeclRefExpr final
+ : public Expr,
+ private llvm::TrailingObjects<DependentScopeDeclRefExpr,
+ ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
/// \brief The nested-name-specifier that qualifies this unresolved
/// declaration name.
NestedNameSpecifierLoc QualifierLoc;
@@ -2618,15 +2719,8 @@ class DependentScopeDeclRefExpr : public Expr {
/// keyword and arguments.
bool HasTemplateKWAndArgsInfo;
- /// \brief Return the optional template keyword and arguments info.
- ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
- if (!HasTemplateKWAndArgsInfo) return nullptr;
- return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1);
- }
- /// \brief Return the optional template keyword and arguments info.
- const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const {
- return const_cast<DependentScopeDeclRefExpr*>(this)
- ->getTemplateKWAndArgsInfo();
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
}
DependentScopeDeclRefExpr(QualType T,
@@ -2671,21 +2765,21 @@ public:
/// this name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
/// \brief Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the name, if any.
SourceLocation getLAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->LAngleLoc;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
/// \brief Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the name, if any.
SourceLocation getRAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->RAngleLoc;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
}
/// Determines whether the name was preceded by the template keyword.
@@ -2694,42 +2788,26 @@ public:
/// Determines whether this lookup had explicit template arguments.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
- // Note that, inconsistently with the explicit-template-argument AST
- // nodes, users are *forbidden* from calling these methods on objects
- // without explicit template arguments.
-
- ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
- assert(hasExplicitTemplateArgs());
- return *reinterpret_cast<ASTTemplateArgumentListInfo*>(this + 1);
- }
-
- /// Gets a reference to the explicit template argument list.
- const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
- assert(hasExplicitTemplateArgs());
- return *reinterpret_cast<const ASTTemplateArgumentListInfo*>(this + 1);
- }
-
- /// \brief Retrieves the optional explicit template arguments.
- ///
- /// This points to the same data as getExplicitTemplateArgs(), but
- /// returns null if there are no explicit template arguments.
- const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
- if (!hasExplicitTemplateArgs()) return nullptr;
- return &getExplicitTemplateArgs();
- }
-
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
- getExplicitTemplateArgs().copyInto(List);
+ if (hasExplicitTemplateArgs())
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
+ getTrailingObjects<TemplateArgumentLoc>(), List);
}
TemplateArgumentLoc const *getTemplateArgs() const {
- return getExplicitTemplateArgs().getTemplateArgs();
+ if (!hasExplicitTemplateArgs())
+ return nullptr;
+
+ return getTrailingObjects<TemplateArgumentLoc>();
}
unsigned getNumTemplateArgs() const {
- return getExplicitTemplateArgs().NumTemplateArgs;
+ if (!hasExplicitTemplateArgs())
+ return 0;
+
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
}
/// Note: getLocStart() is the start of the whole DependentScopeDeclRefExpr,
@@ -2747,8 +2825,11 @@ public:
return T->getStmtClass() == DependentScopeDeclRefExprClass;
}
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+ friend TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
@@ -2763,7 +2844,9 @@ public:
/// This expression also tracks whether the sub-expression contains a
/// potentially-evaluated block literal. The lifetime of a block
/// literal is the extent of the enclosing scope.
-class ExprWithCleanups : public Expr {
+class ExprWithCleanups final
+ : public Expr,
+ private llvm::TrailingObjects<ExprWithCleanups, BlockDecl *> {
public:
/// The type of objects that are kept in the cleanup.
/// It's useful to remember the set of blocks; we could also
@@ -2777,12 +2860,7 @@ private:
ExprWithCleanups(EmptyShell, unsigned NumObjects);
ExprWithCleanups(Expr *SubExpr, ArrayRef<CleanupObject> Objects);
- CleanupObject *getObjectsBuffer() {
- return reinterpret_cast<CleanupObject*>(this + 1);
- }
- const CleanupObject *getObjectsBuffer() const {
- return reinterpret_cast<const CleanupObject*>(this + 1);
- }
+ friend TrailingObjects;
friend class ASTStmtReader;
public:
@@ -2793,7 +2871,8 @@ public:
ArrayRef<CleanupObject> objects);
ArrayRef<CleanupObject> getObjects() const {
- return llvm::makeArrayRef(getObjectsBuffer(), getNumObjects());
+ return llvm::makeArrayRef(getTrailingObjects<CleanupObject>(),
+ getNumObjects());
}
unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; }
@@ -2845,7 +2924,9 @@ public:
/// When the returned expression is instantiated, it may resolve to a
/// constructor call, conversion function call, or some kind of type
/// conversion.
-class CXXUnresolvedConstructExpr : public Expr {
+class CXXUnresolvedConstructExpr final
+ : public Expr,
+ private llvm::TrailingObjects<CXXUnresolvedConstructExpr, Expr *> {
/// \brief The type being constructed.
TypeSourceInfo *Type;
@@ -2866,6 +2947,7 @@ class CXXUnresolvedConstructExpr : public Expr {
CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs)
: Expr(CXXUnresolvedConstructExprClass, Empty), Type(), NumArgs(NumArgs) { }
+ friend TrailingObjects;
friend class ASTStmtReader;
public:
@@ -2900,13 +2982,11 @@ public:
unsigned arg_size() const { return NumArgs; }
typedef Expr** arg_iterator;
- arg_iterator arg_begin() { return reinterpret_cast<Expr**>(this + 1); }
+ arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); }
arg_iterator arg_end() { return arg_begin() + NumArgs; }
typedef const Expr* const * const_arg_iterator;
- const_arg_iterator arg_begin() const {
- return reinterpret_cast<const Expr* const *>(this + 1);
- }
+ const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); }
const_arg_iterator arg_end() const {
return arg_begin() + NumArgs;
}
@@ -2939,7 +3019,7 @@ public:
// Iterators
child_range children() {
- Stmt **begin = reinterpret_cast<Stmt**>(this+1);
+ Stmt **begin = reinterpret_cast<Stmt **>(arg_begin());
return child_range(begin, begin + NumArgs);
}
};
@@ -2951,7 +3031,11 @@ public:
/// Like UnresolvedMemberExprs, these can be either implicit or
/// explicit accesses. It is only possible to get one of these with
/// an implicit access if a qualifier is provided.
-class CXXDependentScopeMemberExpr : public Expr {
+class CXXDependentScopeMemberExpr final
+ : public Expr,
+ private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
+ ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
/// \brief The expression for the base pointer or class reference,
/// e.g., the \c x in x.f. Can be null in implicit accesses.
Stmt *Base;
@@ -2989,15 +3073,8 @@ class CXXDependentScopeMemberExpr : public Expr {
/// FIXME: could also be a template-id
DeclarationNameInfo MemberNameInfo;
- /// \brief Return the optional template keyword and arguments info.
- ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
- if (!HasTemplateKWAndArgsInfo) return nullptr;
- return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1);
- }
- /// \brief Return the optional template keyword and arguments info.
- const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const {
- return const_cast<CXXDependentScopeMemberExpr*>(this)
- ->getTemplateKWAndArgsInfo();
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
}
CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base,
@@ -3093,21 +3170,21 @@ public:
/// member name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
/// \brief Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the member name, if any.
SourceLocation getLAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->LAngleLoc;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
/// \brief Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the member name, if any.
SourceLocation getRAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
- return getTemplateKWAndArgsInfo()->RAngleLoc;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
}
/// Determines whether the member name was preceded by the template keyword.
@@ -3117,50 +3194,30 @@ public:
/// template argument list explicitly specified, e.g., x.f<int>.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name, if any.
- ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
- assert(hasExplicitTemplateArgs());
- return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1);
- }
-
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name, if any.
- const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
- return const_cast<CXXDependentScopeMemberExpr *>(this)
- ->getExplicitTemplateArgs();
- }
-
- /// \brief Retrieves the optional explicit template arguments.
- ///
- /// This points to the same data as getExplicitTemplateArgs(), but
- /// returns null if there are no explicit template arguments.
- const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
- if (!hasExplicitTemplateArgs()) return nullptr;
- return &getExplicitTemplateArgs();
- }
-
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
- getExplicitTemplateArgs().copyInto(List);
- }
-
- /// \brief Initializes the template arguments using the given structure.
- void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) {
- getExplicitTemplateArgs().initializeFrom(List);
+ if (hasExplicitTemplateArgs())
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
+ getTrailingObjects<TemplateArgumentLoc>(), List);
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
- return getExplicitTemplateArgs().getTemplateArgs();
+ if (!hasExplicitTemplateArgs())
+ return nullptr;
+
+ return getTrailingObjects<TemplateArgumentLoc>();
}
/// \brief Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
- return getExplicitTemplateArgs().NumTemplateArgs;
+ if (!hasExplicitTemplateArgs())
+ return 0;
+
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
}
SourceLocation getLocStart() const LLVM_READONLY {
@@ -3169,8 +3226,8 @@ public:
if (getQualifier())
return getQualifierLoc().getBeginLoc();
return MemberNameInfo.getBeginLoc();
-
}
+
SourceLocation getLocEnd() const LLVM_READONLY {
if (hasExplicitTemplateArgs())
return getRAngleLoc();
@@ -3183,10 +3240,12 @@ public:
// Iterators
child_range children() {
- if (isImplicitAccess()) return child_range();
+ if (isImplicitAccess())
+ return child_range(child_iterator(), child_iterator());
return child_range(&Base, &Base + 1);
}
+ friend TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
@@ -3206,7 +3265,10 @@ public:
/// In the final AST, an explicit access always becomes a MemberExpr.
/// An implicit access may become either a MemberExpr or a
/// DeclRefExpr, depending on whether the member is static.
-class UnresolvedMemberExpr : public OverloadExpr {
+class UnresolvedMemberExpr final
+ : public OverloadExpr,
+ private llvm::TrailingObjects<
+ UnresolvedMemberExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
/// \brief Whether this member expression used the '->' operator or
/// the '.' operator.
bool IsArrow : 1;
@@ -3227,6 +3289,10 @@ class UnresolvedMemberExpr : public OverloadExpr {
/// \brief The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
+ }
+
UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing,
Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
@@ -3240,6 +3306,8 @@ class UnresolvedMemberExpr : public OverloadExpr {
: OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false),
HasUnresolvedUsing(false), Base(nullptr) { }
+ friend TrailingObjects;
+ friend class OverloadExpr;
friend class ASTStmtReader;
public:
@@ -3325,11 +3393,34 @@ public:
// Iterators
child_range children() {
- if (isImplicitAccess()) return child_range();
+ if (isImplicitAccess())
+ return child_range(child_iterator(), child_iterator());
return child_range(&Base, &Base + 1);
}
};
+inline ASTTemplateKWAndArgsInfo *
+OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() {
+ if (!HasTemplateKWAndArgsInfo)
+ return nullptr;
+
+ if (isa<UnresolvedLookupExpr>(this))
+ return cast<UnresolvedLookupExpr>(this)
+ ->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
+ else
+ return cast<UnresolvedMemberExpr>(this)
+ ->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
+}
+
+inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() {
+ if (isa<UnresolvedLookupExpr>(this))
+ return cast<UnresolvedLookupExpr>(this)
+ ->getTrailingObjects<TemplateArgumentLoc>();
+ else
+ return cast<UnresolvedMemberExpr>(this)
+ ->getTrailingObjects<TemplateArgumentLoc>();
+}
+
/// \brief Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]).
///
/// The noexcept expression tests whether a given expression might throw. Its
@@ -3451,15 +3542,6 @@ public:
}
};
-inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() {
- if (!HasTemplateKWAndArgsInfo) return nullptr;
- if (isa<UnresolvedLookupExpr>(this))
- return reinterpret_cast<ASTTemplateKWAndArgsInfo*>
- (cast<UnresolvedLookupExpr>(this) + 1);
- else
- return reinterpret_cast<ASTTemplateKWAndArgsInfo*>
- (cast<UnresolvedMemberExpr>(this) + 1);
-}
/// \brief Represents an expression that computes the length of a parameter
/// pack.
@@ -3470,7 +3552,9 @@ inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() {
/// static const unsigned value = sizeof...(Types);
/// };
/// \endcode
-class SizeOfPackExpr : public Expr {
+class SizeOfPackExpr final
+ : public Expr,
+ private llvm::TrailingObjects<SizeOfPackExpr, TemplateArgument> {
/// \brief The location of the \c sizeof keyword.
SourceLocation OperatorLoc;
@@ -3482,43 +3566,52 @@ class SizeOfPackExpr : public Expr {
/// \brief The length of the parameter pack, if known.
///
- /// When this expression is value-dependent, the length of the parameter pack
- /// is unknown. When this expression is not value-dependent, the length is
- /// known.
+ /// When this expression is not value-dependent, this is the length of
+ /// the pack. When the expression was parsed rather than instantiated
+ /// (and thus is value-dependent), this is zero.
+ ///
+ /// After partial substitution into a sizeof...(X) expression (for instance,
+ /// within an alias template or during function template argument deduction),
+ /// we store a trailing array of partially-substituted TemplateArguments,
+ /// and this is the length of that array.
unsigned Length;
- /// \brief The parameter pack itself.
+ /// \brief The parameter pack.
NamedDecl *Pack;
+ friend TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
-public:
- /// \brief Create a value-dependent expression that computes the length of
- /// the given parameter pack.
- SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
- SourceLocation PackLoc, SourceLocation RParenLoc)
- : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary,
- /*TypeDependent=*/false, /*ValueDependent=*/true,
- /*InstantiationDependent=*/true,
- /*ContainsUnexpandedParameterPack=*/false),
- OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
- Length(0), Pack(Pack) { }
-
/// \brief Create an expression that computes the length of
- /// the given parameter pack, which is already known.
+ /// the given parameter pack.
SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
SourceLocation PackLoc, SourceLocation RParenLoc,
- unsigned Length)
- : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary,
- /*TypeDependent=*/false, /*ValueDependent=*/false,
- /*InstantiationDependent=*/false,
- /*ContainsUnexpandedParameterPack=*/false),
- OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
- Length(Length), Pack(Pack) { }
+ Optional<unsigned> Length, ArrayRef<TemplateArgument> PartialArgs)
+ : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false, /*ValueDependent=*/!Length,
+ /*InstantiationDependent=*/!Length,
+ /*ContainsUnexpandedParameterPack=*/false),
+ OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
+ Length(Length ? *Length : PartialArgs.size()), Pack(Pack) {
+ assert((!Length || PartialArgs.empty()) &&
+ "have partial args for non-dependent sizeof... expression");
+ TemplateArgument *Args = getTrailingObjects<TemplateArgument>();
+ std::uninitialized_copy(PartialArgs.begin(), PartialArgs.end(), Args);
+ }
/// \brief Create an empty expression.
- SizeOfPackExpr(EmptyShell Empty) : Expr(SizeOfPackExprClass, Empty) { }
+ SizeOfPackExpr(EmptyShell Empty, unsigned NumPartialArgs)
+ : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs), Pack() {}
+
+public:
+ static SizeOfPackExpr *Create(ASTContext &Context, SourceLocation OperatorLoc,
+ NamedDecl *Pack, SourceLocation PackLoc,
+ SourceLocation RParenLoc,
+ Optional<unsigned> Length = None,
+ ArrayRef<TemplateArgument> PartialArgs = None);
+ static SizeOfPackExpr *CreateDeserialized(ASTContext &Context,
+ unsigned NumPartialArgs);
/// \brief Determine the location of the 'sizeof' keyword.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
@@ -3542,6 +3635,22 @@ public:
return Length;
}
+ /// \brief Determine whether this represents a partially-substituted sizeof...
+ /// expression, such as is produced for:
+ ///
+ /// template<typename ...Ts> using X = int[sizeof...(Ts)];
+ /// template<typename ...Us> void f(X<Us..., 1, 2, 3, Us...>);
+ bool isPartiallySubstituted() const {
+ return isValueDependent() && Length;
+ }
+
+ /// \brief Get
+ ArrayRef<TemplateArgument> getPartialArguments() const {
+ assert(isPartiallySubstituted());
+ const TemplateArgument *Args = getTrailingObjects<TemplateArgument>();
+ return llvm::makeArrayRef(Args, Args + Length);
+ }
+
SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
@@ -3550,7 +3659,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief Represents a reference to a non-type template parameter
@@ -3653,7 +3764,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief Represents a reference to a function parameter pack that has been
@@ -3670,7 +3783,9 @@ public:
/// };
/// template struct S<int, int>;
/// \endcode
-class FunctionParmPackExpr : public Expr {
+class FunctionParmPackExpr final
+ : public Expr,
+ private llvm::TrailingObjects<FunctionParmPackExpr, ParmVarDecl *> {
/// \brief The function parameter pack which was referenced.
ParmVarDecl *ParamPack;
@@ -3682,8 +3797,9 @@ class FunctionParmPackExpr : public Expr {
FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack,
SourceLocation NameLoc, unsigned NumParams,
- Decl * const *Params);
+ ParmVarDecl *const *Params);
+ friend TrailingObjects;
friend class ASTReader;
friend class ASTStmtReader;
@@ -3691,7 +3807,7 @@ public:
static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T,
ParmVarDecl *ParamPack,
SourceLocation NameLoc,
- ArrayRef<Decl *> Params);
+ ArrayRef<ParmVarDecl *> Params);
static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context,
unsigned NumParams);
@@ -3704,7 +3820,7 @@ public:
/// \brief Iterators over the parameters which the parameter pack expanded
/// into.
typedef ParmVarDecl * const *iterator;
- iterator begin() const { return reinterpret_cast<iterator>(this+1); }
+ iterator begin() const { return getTrailingObjects<ParmVarDecl *>(); }
iterator end() const { return begin() + NumParameters; }
/// \brief Get the number of parameters in this parameter pack.
@@ -3720,7 +3836,9 @@ public:
return T->getStmtClass() == FunctionParmPackExprClass;
}
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief Represents a prvalue temporary that is written into memory so that
@@ -3901,6 +4019,136 @@ public:
child_range children() { return child_range(SubExprs, SubExprs + 2); }
};
+/// \brief Represents an expression that might suspend coroutine execution;
+/// either a co_await or co_yield expression.
+///
+/// Evaluation of this expression first evaluates its 'ready' expression. If
+/// that returns 'false':
+/// -- execution of the coroutine is suspended
+/// -- the 'suspend' expression is evaluated
+/// -- if the 'suspend' expression returns 'false', the coroutine is
+/// resumed
+/// -- otherwise, control passes back to the resumer.
+/// If the coroutine is not suspended, or when it is resumed, the 'resume'
+/// expression is evaluated, and its result is the result of the overall
+/// expression.
+class CoroutineSuspendExpr : public Expr {
+ SourceLocation KeywordLoc;
+
+ enum SubExpr { Common, Ready, Suspend, Resume, Count };
+ Stmt *SubExprs[SubExpr::Count];
+
+ friend class ASTStmtReader;
+public:
+ CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common,
+ Expr *Ready, Expr *Suspend, Expr *Resume)
+ : Expr(SC, Resume->getType(), Resume->getValueKind(),
+ Resume->getObjectKind(), Resume->isTypeDependent(),
+ Resume->isValueDependent(), Common->isInstantiationDependent(),
+ Common->containsUnexpandedParameterPack()),
+ KeywordLoc(KeywordLoc) {
+ SubExprs[SubExpr::Common] = Common;
+ SubExprs[SubExpr::Ready] = Ready;
+ SubExprs[SubExpr::Suspend] = Suspend;
+ SubExprs[SubExpr::Resume] = Resume;
+ }
+ CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty,
+ Expr *Common)
+ : Expr(SC, Ty, VK_RValue, OK_Ordinary, true, true, true,
+ Common->containsUnexpandedParameterPack()),
+ KeywordLoc(KeywordLoc) {
+ assert(Common->isTypeDependent() && Ty->isDependentType() &&
+ "wrong constructor for non-dependent co_await/co_yield expression");
+ SubExprs[SubExpr::Common] = Common;
+ SubExprs[SubExpr::Ready] = nullptr;
+ SubExprs[SubExpr::Suspend] = nullptr;
+ SubExprs[SubExpr::Resume] = nullptr;
+ }
+ CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {
+ SubExprs[SubExpr::Common] = nullptr;
+ SubExprs[SubExpr::Ready] = nullptr;
+ SubExprs[SubExpr::Suspend] = nullptr;
+ SubExprs[SubExpr::Resume] = nullptr;
+ }
+
+ SourceLocation getKeywordLoc() const { return KeywordLoc; }
+ Expr *getCommonExpr() const {
+ return static_cast<Expr*>(SubExprs[SubExpr::Common]);
+ }
+
+ Expr *getReadyExpr() const {
+ return static_cast<Expr*>(SubExprs[SubExpr::Ready]);
+ }
+ Expr *getSuspendExpr() const {
+ return static_cast<Expr*>(SubExprs[SubExpr::Suspend]);
+ }
+ Expr *getResumeExpr() const {
+ return static_cast<Expr*>(SubExprs[SubExpr::Resume]);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return KeywordLoc;
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getCommonExpr()->getLocEnd();
+ }
+
+ child_range children() {
+ return child_range(SubExprs, SubExprs + SubExpr::Count);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoawaitExprClass ||
+ T->getStmtClass() == CoyieldExprClass;
+ }
+};
+
+/// \brief Represents a 'co_await' expression.
+class CoawaitExpr : public CoroutineSuspendExpr {
+ friend class ASTStmtReader;
+public:
+ CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready,
+ Expr *Suspend, Expr *Resume)
+ : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Ready,
+ Suspend, Resume) {}
+ CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand)
+ : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) {}
+ CoawaitExpr(EmptyShell Empty)
+ : CoroutineSuspendExpr(CoawaitExprClass, Empty) {}
+
+ Expr *getOperand() const {
+ // FIXME: Dig out the actual operand or store it.
+ return getCommonExpr();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoawaitExprClass;
+ }
+};
+
+/// \brief Represents a 'co_yield' expression.
+class CoyieldExpr : public CoroutineSuspendExpr {
+ friend class ASTStmtReader;
+public:
+ CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready,
+ Expr *Suspend, Expr *Resume)
+ : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Ready,
+ Suspend, Resume) {}
+ CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand)
+ : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand) {}
+ CoyieldExpr(EmptyShell Empty)
+ : CoroutineSuspendExpr(CoyieldExprClass, Empty) {}
+
+ Expr *getOperand() const {
+ // FIXME: Dig out the actual operand or store it.
+ return getCommonExpr();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoyieldExprClass;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
index f28e519..61e6383 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
@@ -82,7 +82,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// ObjCBoxedExpr - used for generalized expression boxing.
@@ -139,15 +141,17 @@ public:
/// ObjCArrayLiteral - used for objective-c array containers; as in:
/// @[@"Hello", NSApp, [NSNumber numberWithInt:42]];
-class ObjCArrayLiteral : public Expr {
+class ObjCArrayLiteral final
+ : public Expr,
+ private llvm::TrailingObjects<ObjCArrayLiteral, Expr *> {
unsigned NumElements;
SourceRange Range;
ObjCMethodDecl *ArrayWithObjectsMethod;
-
+
ObjCArrayLiteral(ArrayRef<Expr *> Elements,
QualType T, ObjCMethodDecl * Method,
SourceRange SR);
-
+
explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements)
: Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {}
@@ -169,11 +173,11 @@ public:
}
/// \brief Retrieve elements of array of literals.
- Expr **getElements() { return reinterpret_cast<Expr **>(this + 1); }
+ Expr **getElements() { return getTrailingObjects<Expr *>(); }
/// \brief Retrieve elements of array of literals.
- const Expr * const *getElements() const {
- return reinterpret_cast<const Expr * const*>(this + 1);
+ const Expr * const *getElements() const {
+ return getTrailingObjects<Expr *>();
}
/// getNumElements - Return number of elements of objective-c array literal.
@@ -194,11 +198,12 @@ public:
}
// Iterators
- child_range children() {
- return child_range((Stmt **)getElements(),
- (Stmt **)getElements() + NumElements);
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(getElements()),
+ reinterpret_cast<Stmt **>(getElements()) + NumElements);
}
-
+
+ friend TrailingObjects;
friend class ASTStmtReader;
};
@@ -228,32 +233,35 @@ template <> struct isPodLike<clang::ObjCDictionaryElement> : std::true_type {};
}
namespace clang {
-/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary
-/// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] };
-class ObjCDictionaryLiteral : public Expr {
- /// \brief Key/value pair used to store the key and value of a given element.
- ///
- /// Objects of this type are stored directly after the expression.
- struct KeyValuePair {
- Expr *Key;
- Expr *Value;
- };
-
- /// \brief Data that describes an element that is a pack expansion, used if any
- /// of the elements in the dictionary literal are pack expansions.
- struct ExpansionData {
- /// \brief The location of the ellipsis, if this element is a pack
- /// expansion.
- SourceLocation EllipsisLoc;
-
- /// \brief If non-zero, the number of elements that this pack
- /// expansion will expand to (+1).
- unsigned NumExpansionsPlusOne;
- };
+/// \brief Internal struct for storing Key/value pair.
+struct ObjCDictionaryLiteral_KeyValuePair {
+ Expr *Key;
+ Expr *Value;
+};
+/// \brief Internal struct to describes an element that is a pack
+/// expansion, used if any of the elements in the dictionary literal
+/// are pack expansions.
+struct ObjCDictionaryLiteral_ExpansionData {
+ /// \brief The location of the ellipsis, if this element is a pack
+ /// expansion.
+ SourceLocation EllipsisLoc;
+
+ /// \brief If non-zero, the number of elements that this pack
+ /// expansion will expand to (+1).
+ unsigned NumExpansionsPlusOne;
+};
+
+/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary
+/// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] };
+class ObjCDictionaryLiteral final
+ : public Expr,
+ private llvm::TrailingObjects<ObjCDictionaryLiteral,
+ ObjCDictionaryLiteral_KeyValuePair,
+ ObjCDictionaryLiteral_ExpansionData> {
/// \brief The number of elements in this dictionary literal.
unsigned NumElements : 31;
-
+
/// \brief Determine whether this dictionary literal has any pack expansions.
///
/// If the dictionary literal has pack expansions, then there will
@@ -262,10 +270,17 @@ class ObjCDictionaryLiteral : public Expr {
/// any) and number of elements in the expansion (if known). If
/// there are no pack expansions, we optimize away this storage.
unsigned HasPackExpansions : 1;
-
+
SourceRange Range;
ObjCMethodDecl *DictWithObjectsMethod;
-
+
+ typedef ObjCDictionaryLiteral_KeyValuePair KeyValuePair;
+ typedef ObjCDictionaryLiteral_ExpansionData ExpansionData;
+
+ size_t numTrailingObjects(OverloadToken<KeyValuePair>) const {
+ return NumElements;
+ }
+
ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
bool HasPackExpansions,
QualType T, ObjCMethodDecl *method,
@@ -276,28 +291,6 @@ class ObjCDictionaryLiteral : public Expr {
: Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements),
HasPackExpansions(HasPackExpansions) {}
- KeyValuePair *getKeyValues() {
- return reinterpret_cast<KeyValuePair *>(this + 1);
- }
-
- const KeyValuePair *getKeyValues() const {
- return reinterpret_cast<const KeyValuePair *>(this + 1);
- }
-
- ExpansionData *getExpansionData() {
- if (!HasPackExpansions)
- return nullptr;
-
- return reinterpret_cast<ExpansionData *>(getKeyValues() + NumElements);
- }
-
- const ExpansionData *getExpansionData() const {
- if (!HasPackExpansions)
- return nullptr;
-
- return reinterpret_cast<const ExpansionData *>(getKeyValues()+NumElements);
- }
-
public:
static ObjCDictionaryLiteral *Create(const ASTContext &C,
ArrayRef<ObjCDictionaryElement> VK,
@@ -315,10 +308,11 @@ public:
ObjCDictionaryElement getKeyValueElement(unsigned Index) const {
assert((Index < NumElements) && "Arg access out of range!");
- const KeyValuePair &KV = getKeyValues()[Index];
+ const KeyValuePair &KV = getTrailingObjects<KeyValuePair>()[Index];
ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), None };
if (HasPackExpansions) {
- const ExpansionData &Expansion = getExpansionData()[Index];
+ const ExpansionData &Expansion =
+ getTrailingObjects<ExpansionData>()[Index];
Result.EllipsisLoc = Expansion.EllipsisLoc;
if (Expansion.NumExpansionsPlusOne > 0)
Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1;
@@ -338,15 +332,20 @@ public:
}
// Iterators
- child_range children() {
+ child_range children() {
// Note: we're taking advantage of the layout of the KeyValuePair struct
// here. If that struct changes, this code will need to change as well.
- return child_range(reinterpret_cast<Stmt **>(this + 1),
- reinterpret_cast<Stmt **>(this + 1) + NumElements * 2);
+ static_assert(sizeof(KeyValuePair) == sizeof(Stmt *) * 2,
+ "KeyValuePair is expected size");
+ return child_range(
+ reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()),
+ reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()) +
+ NumElements * 2);
}
friend class ASTStmtReader;
friend class ASTStmtWriter;
+ friend TrailingObjects;
};
@@ -389,7 +388,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// ObjCSelectorExpr used for \@selector in Objective-C.
@@ -424,7 +425,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// ObjCProtocolExpr used for protocol expression in Objective-C.
@@ -464,7 +467,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
friend class ASTStmtReader;
friend class ASTStmtWriter;
@@ -713,7 +718,7 @@ public:
Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
return child_range(begin, begin+1);
}
- return child_range();
+ return child_range(child_iterator(), child_iterator());
}
private:
@@ -787,13 +792,6 @@ public:
explicit ObjCSubscriptRefExpr(EmptyShell Empty)
: Expr(ObjCSubscriptRefExprClass, Empty) {}
- static ObjCSubscriptRefExpr *Create(const ASTContext &C,
- Expr *base,
- Expr *key, QualType T,
- ObjCMethodDecl *getMethod,
- ObjCMethodDecl *setMethod,
- SourceLocation RB);
-
SourceLocation getRBracket() const { return RBracket; }
void setRBracket(SourceLocation RB) { RBracket = RB; }
@@ -855,7 +853,13 @@ private:
/// All four kinds of message sends are modeled by the ObjCMessageExpr
/// class, and can be distinguished via \c getReceiverKind(). Example:
///
-class ObjCMessageExpr : public Expr {
+/// The "void *" trailing objects are actually ONE void * (the
+/// receiver pointer), and NumArgs Expr *. But due to the
+/// implementation of children(), these must be together contiguously.
+
+class ObjCMessageExpr final
+ : public Expr,
+ private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> {
/// \brief Stores either the selector that this message is sending
/// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer
/// referring to the method that we type-checked against.
@@ -867,11 +871,6 @@ class ObjCMessageExpr : public Expr {
/// including the receiver.
unsigned NumArgs : NumArgsBitWidth;
- void setNumArgs(unsigned Num) {
- assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!");
- NumArgs = Num;
- }
-
/// \brief The kind of message send this is, which is one of the
/// ReceiverKind values.
///
@@ -905,6 +904,13 @@ class ObjCMessageExpr : public Expr {
/// brackets ('[' and ']', respectively).
SourceLocation LBracLoc, RBracLoc;
+ size_t numTrailingObjects(OverloadToken<void *>) const { return NumArgs + 1; }
+
+ void setNumArgs(unsigned Num) {
+ assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!");
+ NumArgs = Num;
+ }
+
ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
: Expr(ObjCMessageExprClass, Empty), SelectorOrMethod(0), Kind(0),
HasMethod(0), IsDelegateInitCall(0), IsImplicit(0), SelLocsKind(0) {
@@ -949,14 +955,11 @@ class ObjCMessageExpr : public Expr {
SelectorLocationsKind SelLocsK);
/// \brief Retrieve the pointer value of the message receiver.
- void *getReceiverPointer() const {
- return *const_cast<void **>(
- reinterpret_cast<const void * const*>(this + 1));
- }
+ void *getReceiverPointer() const { return *getTrailingObjects<void *>(); }
/// \brief Set the pointer value of the message receiver.
void setReceiverPointer(void *Value) {
- *reinterpret_cast<void **>(this + 1) = Value;
+ *getTrailingObjects<void *>() = Value;
}
SelectorLocationsKind getSelLocsKind() const {
@@ -969,10 +972,10 @@ class ObjCMessageExpr : public Expr {
/// \brief Get a pointer to the stored selector identifiers locations array.
/// No locations will be stored if HasStandardSelLocs is true.
SourceLocation *getStoredSelLocs() {
- return reinterpret_cast<SourceLocation*>(getArgs() + getNumArgs());
+ return getTrailingObjects<SourceLocation>();
}
const SourceLocation *getStoredSelLocs() const {
- return reinterpret_cast<const SourceLocation*>(getArgs() + getNumArgs());
+ return getTrailingObjects<SourceLocation>();
}
/// \brief Get the number of stored selector identifiers locations.
@@ -1276,20 +1279,21 @@ public:
/// \brief Retrieve the arguments to this message, not including the
/// receiver.
Expr **getArgs() {
- return reinterpret_cast<Expr **>(this + 1) + 1;
+ return reinterpret_cast<Expr **>(getTrailingObjects<void *>() + 1);
}
const Expr * const *getArgs() const {
- return reinterpret_cast<const Expr * const *>(this + 1) + 1;
+ return reinterpret_cast<const Expr *const *>(getTrailingObjects<void *>() +
+ 1);
}
/// getArg - Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
- return cast<Expr>(getArgs()[Arg]);
+ return getArgs()[Arg];
}
const Expr *getArg(unsigned Arg) const {
assert(Arg < NumArgs && "Arg access out of range!");
- return cast<Expr>(getArgs()[Arg]);
+ return getArgs()[Arg];
}
/// setArg - Set the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr) {
@@ -1350,6 +1354,14 @@ public:
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
+ llvm::iterator_range<arg_iterator> arguments() {
+ return llvm::make_range(arg_begin(), arg_end());
+ }
+
+ llvm::iterator_range<const_arg_iterator> arguments() const {
+ return llvm::make_range(arg_begin(), arg_end());
+ }
+
arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
arg_iterator arg_end() {
return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
@@ -1361,6 +1373,7 @@ public:
return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
}
+ friend TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
@@ -1503,11 +1516,15 @@ public:
/// \code
/// NSString *str = (__bridge_transfer NSString *)CFCreateString();
/// \endcode
-class ObjCBridgedCastExpr : public ExplicitCastExpr {
+class ObjCBridgedCastExpr final
+ : public ExplicitCastExpr,
+ private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> {
SourceLocation LParenLoc;
SourceLocation BridgeKeywordLoc;
unsigned Kind : 2;
-
+
+ friend TrailingObjects;
+ friend class CastExpr;
friend class ASTStmtReader;
friend class ASTStmtWriter;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h
new file mode 100644
index 0000000..2d71a3a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h
@@ -0,0 +1,129 @@
+//===--- ExprOpenMP.h - Classes for representing expressions ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Expr interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_EXPROPENMP_H
+#define LLVM_CLANG_AST_EXPROPENMP_H
+
+#include "clang/AST/Expr.h"
+
+namespace clang {
+/// \brief OpenMP 4.0 [2.4, Array Sections].
+/// To specify an array section in an OpenMP construct, array subscript
+/// expressions are extended with the following syntax:
+/// \code
+/// [ lower-bound : length ]
+/// [ lower-bound : ]
+/// [ : length ]
+/// [ : ]
+/// \endcode
+/// The array section must be a subset of the original array.
+/// Array sections are allowed on multidimensional arrays. Base language array
+/// subscript expressions can be used to specify length-one dimensions of
+/// multidimensional array sections.
+/// The lower-bound and length are integral type expressions. When evaluated
+/// they represent a set of integer values as follows:
+/// \code
+/// { lower-bound, lower-bound + 1, lower-bound + 2,... , lower-bound + length -
+/// 1 }
+/// \endcode
+/// The lower-bound and length must evaluate to non-negative integers.
+/// When the size of the array dimension is not known, the length must be
+/// specified explicitly.
+/// When the length is absent, it defaults to the size of the array dimension
+/// minus the lower-bound.
+/// When the lower-bound is absent it defaults to 0.
+class OMPArraySectionExpr : public Expr {
+ enum { BASE, LOWER_BOUND, LENGTH, END_EXPR };
+ Stmt *SubExprs[END_EXPR];
+ SourceLocation ColonLoc;
+ SourceLocation RBracketLoc;
+
+public:
+ OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation ColonLoc, SourceLocation RBracketLoc)
+ : Expr(
+ OMPArraySectionExprClass, Type, VK, OK,
+ Base->isTypeDependent() ||
+ (LowerBound && LowerBound->isTypeDependent()) ||
+ (Length && Length->isTypeDependent()),
+ Base->isValueDependent() ||
+ (LowerBound && LowerBound->isValueDependent()) ||
+ (Length && Length->isValueDependent()),
+ Base->isInstantiationDependent() ||
+ (LowerBound && LowerBound->isInstantiationDependent()) ||
+ (Length && Length->isInstantiationDependent()),
+ Base->containsUnexpandedParameterPack() ||
+ (LowerBound && LowerBound->containsUnexpandedParameterPack()) ||
+ (Length && Length->containsUnexpandedParameterPack())),
+ ColonLoc(ColonLoc), RBracketLoc(RBracketLoc) {
+ SubExprs[BASE] = Base;
+ SubExprs[LOWER_BOUND] = LowerBound;
+ SubExprs[LENGTH] = Length;
+ }
+
+ /// \brief Create an empty array section expression.
+ explicit OMPArraySectionExpr(EmptyShell Shell)
+ : Expr(OMPArraySectionExprClass, Shell) {}
+
+ /// An array section can be written only as Base[LowerBound:Length].
+
+ /// \brief Get base of the array section.
+ Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
+ const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
+ /// \brief Set base of the array section.
+ void setBase(Expr *E) { SubExprs[BASE] = E; }
+
+ /// \brief Return original type of the base expression for array section.
+ static QualType getBaseOriginalType(Expr *Base);
+
+ /// \brief Get lower bound of array section.
+ Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
+ const Expr *getLowerBound() const {
+ return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
+ }
+ /// \brief Set lower bound of the array section.
+ void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
+
+ /// \brief Get length of array section.
+ Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
+ const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
+ /// \brief Set length of the array section.
+ void setLength(Expr *E) { SubExprs[LENGTH] = E; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBase()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
+
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ void setColonLoc(SourceLocation L) { ColonLoc = L; }
+
+ SourceLocation getRBracketLoc() const { return RBracketLoc; }
+ void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
+
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ return getBase()->getExprLoc();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPArraySectionExprClass;
+ }
+
+ child_range children() {
+ return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
+ }
+};
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
index 08c2e0c..81cf631 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
@@ -33,20 +33,6 @@ class Selector;
class Stmt;
class TagDecl;
-/// \brief Enumeration describing the result of loading information from
-/// an external source.
-enum ExternalLoadResult {
- /// \brief Loading the external information has succeeded.
- ELR_Success,
-
- /// \brief Loading the external information has failed.
- ELR_Failure,
-
- /// \brief The external information has already been loaded, and therefore
- /// no additional processing is required.
- ELR_AlreadyLoaded
-};
-
/// \brief Abstract interface for external sources of AST nodes.
///
/// External AST sources provide AST nodes constructed from some
@@ -156,47 +142,50 @@ public:
/// \brief Retrieve the module that corresponds to the given module ID.
virtual Module *getModule(unsigned ID) { return nullptr; }
- /// \brief Holds everything needed to generate debug info for an
- /// imported module or precompiled header file.
- struct ASTSourceDescriptor {
- std::string ModuleName;
- std::string Path;
- std::string ASTFile;
- uint64_t Signature;
+ /// Abstracts clang modules and precompiled header files and holds
+ /// everything needed to generate debug info for an imported module
+ /// or PCH.
+ class ASTSourceDescriptor {
+ StringRef PCHModuleName;
+ StringRef Path;
+ StringRef ASTFile;
+ uint64_t Signature = 0;
+ const Module *ClangModule = nullptr;
+
+ public:
+ ASTSourceDescriptor(){};
+ ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
+ uint64_t Signature)
+ : PCHModuleName(std::move(Name)), Path(std::move(Path)),
+ ASTFile(std::move(ASTFile)), Signature(Signature){};
+ ASTSourceDescriptor(const Module &M);
+ std::string getModuleName() const;
+ StringRef getPath() const { return Path; }
+ StringRef getASTFile() const { return ASTFile; }
+ uint64_t getSignature() const { return Signature; }
+ const Module *getModuleOrNull() const { return ClangModule; }
};
- /// \brief Return a descriptor for the corresponding module, if one exists.
+ /// Return a descriptor for the corresponding module, if one exists.
virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);
- /// \brief Return a descriptor for the module.
- virtual ASTSourceDescriptor getSourceDescriptor(const Module &M);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
///
- /// \param isKindWeWant a predicate function that returns true if the passed
- /// declaration kind is one we are looking for. If NULL, all declarations
- /// are returned.
- ///
- /// \return an indication of whether the load succeeded or failed.
+ /// \param IsKindWeWant a predicate function that returns true if the passed
+ /// declaration kind is one we are looking for.
///
/// The default implementation of this method is a no-op.
- virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Result);
+ virtual void
+ FindExternalLexicalDecls(const DeclContext *DC,
+ llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Result);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext.
- ///
- /// \return true if an error occurred
- ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
- SmallVectorImpl<Decl*> &Result) {
- return FindExternalLexicalDecls(DC, nullptr, Result);
- }
-
- template <typename DeclTy>
- ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC,
- SmallVectorImpl<Decl*> &Result) {
- return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
+ void FindExternalLexicalDecls(const DeclContext *DC,
+ SmallVectorImpl<Decl *> &Result) {
+ FindExternalLexicalDecls(DC, [](Decl::Kind) { return true; }, Result);
}
/// \brief Get the decls that are contained in a file in the Offset/Length
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Mangle.h b/contrib/llvm/tools/clang/include/clang/AST/Mangle.h
index 735ae11..4872738 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Mangle.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Mangle.h
@@ -144,9 +144,6 @@ public:
/// across translation units so it can be used with LTO.
virtual void mangleTypeName(QualType T, raw_ostream &) = 0;
- virtual void mangleCXXVTableBitSet(const CXXRecordDecl *RD,
- raw_ostream &) = 0;
-
/// @}
};
@@ -219,9 +216,6 @@ public:
uint32_t NVOffset, int32_t VBPtrOffset,
uint32_t VBIndex, raw_ostream &Out) = 0;
- virtual void mangleCXXCatchHandlerType(QualType T, uint32_t Flags,
- raw_ostream &Out) = 0;
-
virtual void mangleCXXRTTIBaseClassDescriptor(
const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
index 4da17b0..b1ff9bd 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
@@ -217,7 +217,8 @@ public:
/// \brief Dump the nested name specifier to standard output to aid
/// in debugging.
- void dump(const LangOptions &LO);
+ void dump(const LangOptions &LO) const;
+ void dump() const;
};
/// \brief A C++ nested-name-specifier augmented with source location
diff --git a/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h b/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h
index fcfa1dd..7632a4b 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h
@@ -57,9 +57,15 @@ public:
bool isImplicit() const { return StartLoc.isInvalid(); }
- StmtRange children();
- ConstStmtRange children() const {
- return const_cast<OMPClause *>(this)->children();
+ typedef StmtIterator child_iterator;
+ typedef ConstStmtIterator const_child_iterator;
+ typedef llvm::iterator_range<child_iterator> child_range;
+ typedef llvm::iterator_range<const_child_iterator> const_child_range;
+
+ child_range children();
+ const_child_range children() const {
+ auto Children = const_cast<OMPClause *>(this)->children();
+ return const_child_range(Children.begin(), Children.end());
}
static bool classof(const OMPClause *) { return true; }
};
@@ -78,21 +84,15 @@ protected:
/// \brief Fetches list of variables associated with this clause.
MutableArrayRef<Expr *> getVarRefs() {
return MutableArrayRef<Expr *>(
- reinterpret_cast<Expr **>(
- reinterpret_cast<char *>(this) +
- llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<Expr *>())),
- NumVars);
+ static_cast<T *>(this)->template getTrailingObjects<Expr *>(), NumVars);
}
/// \brief Sets the list of variables for this clause.
void setVarRefs(ArrayRef<Expr *> VL) {
assert(VL.size() == NumVars &&
"Number of variables is not the same as the preallocated buffer");
- std::copy(
- VL.begin(), VL.end(),
- reinterpret_cast<Expr **>(
- reinterpret_cast<char *>(this) +
- llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<Expr *>())));
+ std::copy(VL.begin(), VL.end(),
+ static_cast<T *>(this)->template getTrailingObjects<Expr *>());
}
/// \brief Build a clause with \a N variables
@@ -136,9 +136,7 @@ public:
/// \brief Fetches list of all variables in the clause.
ArrayRef<const Expr *> getVarRefs() const {
return llvm::makeArrayRef(
- reinterpret_cast<const Expr *const *>(
- reinterpret_cast<const char *>(this) +
- llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<const Expr *>())),
+ static_cast<const T *>(this)->template getTrailingObjects<Expr *>(),
NumVars);
}
};
@@ -146,10 +144,10 @@ public:
/// \brief This represents 'if' clause in the '#pragma omp ...' directive.
///
/// \code
-/// #pragma omp parallel if(a > 5)
+/// #pragma omp parallel if(parallel:a > 5)
/// \endcode
-/// In this example directive '#pragma omp parallel' has simple 'if'
-/// clause with condition 'a > 5'.
+/// In this example directive '#pragma omp parallel' has simple 'if' clause with
+/// condition 'a > 5' and directive name modifier 'parallel'.
///
class OMPIfClause : public OMPClause {
friend class OMPClauseReader;
@@ -157,43 +155,73 @@ class OMPIfClause : public OMPClause {
SourceLocation LParenLoc;
/// \brief Condition of the 'if' clause.
Stmt *Condition;
+ /// \brief Location of ':' (if any).
+ SourceLocation ColonLoc;
+ /// \brief Directive name modifier for the clause.
+ OpenMPDirectiveKind NameModifier;
+ /// \brief Name modifier location.
+ SourceLocation NameModifierLoc;
/// \brief Set condition.
///
void setCondition(Expr *Cond) { Condition = Cond; }
+ /// \brief Set directive name modifier for the clause.
+ ///
+ void setNameModifier(OpenMPDirectiveKind NM) { NameModifier = NM; }
+ /// \brief Set location of directive name modifier for the clause.
+ ///
+ void setNameModifierLoc(SourceLocation Loc) { NameModifierLoc = Loc; }
+ /// \brief Set location of ':'.
+ ///
+ void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
public:
/// \brief Build 'if' clause with condition \a Cond.
///
+ /// \param NameModifier [OpenMP 4.1] Directive name modifier of clause.
+ /// \param Cond Condition of the clause.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
- /// \param Cond Condition of the clause.
+ /// \param NameModifierLoc Location of directive name modifier.
+ /// \param ColonLoc [OpenMP 4.1] Location of ':'.
/// \param EndLoc Ending location of the clause.
///
- OMPIfClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc,
+ OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation NameModifierLoc, SourceLocation ColonLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_if, StartLoc, EndLoc), LParenLoc(LParenLoc),
- Condition(Cond) {}
+ Condition(Cond), ColonLoc(ColonLoc), NameModifier(NameModifier),
+ NameModifierLoc(NameModifierLoc) {}
/// \brief Build an empty clause.
///
OMPIfClause()
- : OMPClause(OMPC_if, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Condition(nullptr) {}
+ : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), LParenLoc(),
+ Condition(nullptr), ColonLoc(), NameModifier(OMPD_unknown),
+ NameModifierLoc() {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return the location of ':'.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
/// \brief Returns condition.
Expr *getCondition() const { return cast_or_null<Expr>(Condition); }
+ /// \brief Return directive name modifier associated with the clause.
+ OpenMPDirectiveKind getNameModifier() const { return NameModifier; }
+
+ /// \brief Return the location of directive name modifier.
+ SourceLocation getNameModifierLoc() const { return NameModifierLoc; }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_if;
}
- StmtRange children() { return StmtRange(&Condition, &Condition + 1); }
+ child_range children() { return child_range(&Condition, &Condition + 1); }
};
/// \brief This represents 'final' clause in the '#pragma omp ...' directive.
@@ -246,7 +274,7 @@ public:
return T->getClauseKind() == OMPC_final;
}
- StmtRange children() { return StmtRange(&Condition, &Condition + 1); }
+ child_range children() { return child_range(&Condition, &Condition + 1); }
};
/// \brief This represents 'num_threads' clause in the '#pragma omp ...'
@@ -300,7 +328,7 @@ public:
return T->getClauseKind() == OMPC_num_threads;
}
- StmtRange children() { return StmtRange(&NumThreads, &NumThreads + 1); }
+ child_range children() { return child_range(&NumThreads, &NumThreads + 1); }
};
/// \brief This represents 'safelen' clause in the '#pragma omp ...'
@@ -356,7 +384,62 @@ public:
return T->getClauseKind() == OMPC_safelen;
}
- StmtRange children() { return StmtRange(&Safelen, &Safelen + 1); }
+ child_range children() { return child_range(&Safelen, &Safelen + 1); }
+};
+
+/// \brief This represents 'simdlen' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp simd simdlen(4)
+/// \endcode
+/// In this example directive '#pragma omp simd' has clause 'simdlen'
+/// with single expression '4'.
+/// If the 'simdlen' clause is used then it specifies the preferred number of
+/// iterations to be executed concurrently. The parameter of the 'simdlen'
+/// clause must be a constant positive integer expression.
+///
+class OMPSimdlenClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Safe iteration space distance.
+ Stmt *Simdlen;
+
+ /// \brief Set simdlen.
+ void setSimdlen(Expr *Len) { Simdlen = Len; }
+
+public:
+ /// \brief Build 'simdlen' clause.
+ ///
+ /// \param Len Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPSimdlenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_simdlen, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Simdlen(Len) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPSimdlenClause()
+ : OMPClause(OMPC_simdlen, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Simdlen(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return safe iteration space distance.
+ Expr *getSimdlen() const { return cast_or_null<Expr>(Simdlen); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_simdlen;
+ }
+
+ child_range children() { return child_range(&Simdlen, &Simdlen + 1); }
};
/// \brief This represents 'collapse' clause in the '#pragma omp ...'
@@ -412,7 +495,7 @@ public:
return T->getClauseKind() == OMPC_collapse;
}
- StmtRange children() { return StmtRange(&NumForLoops, &NumForLoops + 1); }
+ child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
};
/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
@@ -481,7 +564,9 @@ public:
return T->getClauseKind() == OMPC_default;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'proc_bind' clause in the '#pragma omp ...'
@@ -552,7 +637,9 @@ public:
return T->getClauseKind() == OMPC_proc_bind;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'schedule' clause in the '#pragma omp ...' directive.
@@ -569,6 +656,11 @@ class OMPScheduleClause : public OMPClause {
SourceLocation LParenLoc;
/// \brief A kind of the 'schedule' clause.
OpenMPScheduleClauseKind Kind;
+ /// \brief Modifiers for 'schedule' clause.
+ enum {FIRST, SECOND, NUM_MODIFIERS};
+ OpenMPScheduleClauseModifier Modifiers[NUM_MODIFIERS];
+ /// \brief Locations of modifiers.
+ SourceLocation ModifiersLoc[NUM_MODIFIERS];
/// \brief Start location of the schedule ind in source code.
SourceLocation KindLoc;
/// \brief Location of ',' (if any).
@@ -583,6 +675,42 @@ class OMPScheduleClause : public OMPClause {
/// \param K Schedule kind.
///
void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; }
+ /// \brief Set the first schedule modifier.
+ ///
+ /// \param M Schedule modifier.
+ ///
+ void setFirstScheduleModifier(OpenMPScheduleClauseModifier M) {
+ Modifiers[FIRST] = M;
+ }
+ /// \brief Set the second schedule modifier.
+ ///
+ /// \param M Schedule modifier.
+ ///
+ void setSecondScheduleModifier(OpenMPScheduleClauseModifier M) {
+ Modifiers[SECOND] = M;
+ }
+ /// \brief Set location of the first schedule modifier.
+ ///
+ void setFirstScheduleModifierLoc(SourceLocation Loc) {
+ ModifiersLoc[FIRST] = Loc;
+ }
+ /// \brief Set location of the second schedule modifier.
+ ///
+ void setSecondScheduleModifierLoc(SourceLocation Loc) {
+ ModifiersLoc[SECOND] = Loc;
+ }
+ /// \brief Set schedule modifier location.
+ ///
+ /// \param M Schedule modifier location.
+ ///
+ void setScheduleModifer(OpenMPScheduleClauseModifier M) {
+ if (Modifiers[FIRST] == OMPC_SCHEDULE_MODIFIER_unknown)
+ Modifiers[FIRST] = M;
+ else {
+ assert(Modifiers[SECOND] == OMPC_SCHEDULE_MODIFIER_unknown);
+ Modifiers[SECOND] = M;
+ }
+ }
/// \brief Sets the location of '('.
///
/// \param Loc Location of '('.
@@ -621,15 +749,25 @@ public:
/// \param Kind Schedule kind.
/// \param ChunkSize Chunk size.
/// \param HelperChunkSize Helper chunk size for combined directives.
+ /// \param M1 The first modifier applied to 'schedule' clause.
+ /// \param M1Loc Location of the first modifier
+ /// \param M2 The second modifier applied to 'schedule' clause.
+ /// \param M2Loc Location of the second modifier
///
OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation KLoc, SourceLocation CommaLoc,
SourceLocation EndLoc, OpenMPScheduleClauseKind Kind,
- Expr *ChunkSize, Expr *HelperChunkSize)
+ Expr *ChunkSize, Expr *HelperChunkSize,
+ OpenMPScheduleClauseModifier M1, SourceLocation M1Loc,
+ OpenMPScheduleClauseModifier M2, SourceLocation M2Loc)
: OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc),
Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) {
ChunkSizes[CHUNK_SIZE] = ChunkSize;
ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize;
+ Modifiers[FIRST] = M1;
+ Modifiers[SECOND] = M2;
+ ModifiersLoc[FIRST] = M1Loc;
+ ModifiersLoc[SECOND] = M2Loc;
}
/// \brief Build an empty clause.
@@ -639,17 +777,39 @@ public:
Kind(OMPC_SCHEDULE_unknown) {
ChunkSizes[CHUNK_SIZE] = nullptr;
ChunkSizes[HELPER_CHUNK_SIZE] = nullptr;
+ Modifiers[FIRST] = OMPC_SCHEDULE_MODIFIER_unknown;
+ Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown;
}
/// \brief Get kind of the clause.
///
OpenMPScheduleClauseKind getScheduleKind() const { return Kind; }
+ /// \brief Get the first modifier of the clause.
+ ///
+ OpenMPScheduleClauseModifier getFirstScheduleModifier() const {
+ return Modifiers[FIRST];
+ }
+ /// \brief Get the second modifier of the clause.
+ ///
+ OpenMPScheduleClauseModifier getSecondScheduleModifier() const {
+ return Modifiers[SECOND];
+ }
/// \brief Get location of '('.
///
SourceLocation getLParenLoc() { return LParenLoc; }
/// \brief Get kind location.
///
SourceLocation getScheduleKindLoc() { return KindLoc; }
+ /// \brief Get the first modifier location.
+ ///
+ SourceLocation getFirstScheduleModifierLoc() const {
+ return ModifiersLoc[FIRST];
+ }
+ /// \brief Get the second modifier location.
+ ///
+ SourceLocation getSecondScheduleModifierLoc() const {
+ return ModifiersLoc[SECOND];
+ }
/// \brief Get location of ','.
///
SourceLocation getCommaLoc() { return CommaLoc; }
@@ -676,38 +836,61 @@ public:
return T->getClauseKind() == OMPC_schedule;
}
- StmtRange children() {
- return StmtRange(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1);
+ child_range children() {
+ return child_range(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1);
}
};
/// \brief This represents 'ordered' clause in the '#pragma omp ...' directive.
///
/// \code
-/// #pragma omp for ordered
+/// #pragma omp for ordered (2)
/// \endcode
-/// In this example directive '#pragma omp for' has 'ordered' clause.
+/// In this example directive '#pragma omp for' has 'ordered' clause with
+/// parameter 2.
///
class OMPOrderedClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Number of for-loops.
+ Stmt *NumForLoops;
+
+ /// \brief Set the number of associated for-loops.
+ void setNumForLoops(Expr *Num) { NumForLoops = Num; }
+
public:
/// \brief Build 'ordered' clause.
///
+ /// \param Num Expression, possibly associated with this clause.
/// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
///
- OMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc)
- : OMPClause(OMPC_ordered, StartLoc, EndLoc) {}
+ OMPOrderedClause(Expr *Num, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumForLoops(Num) {}
/// \brief Build an empty clause.
///
- OMPOrderedClause()
- : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {}
+ explicit OMPOrderedClause()
+ : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), NumForLoops(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return the number of associated for-loops.
+ Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_ordered;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
};
/// \brief This represents 'nowait' clause in the '#pragma omp ...' directive.
@@ -736,7 +919,9 @@ public:
return T->getClauseKind() == OMPC_nowait;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'untied' clause in the '#pragma omp ...' directive.
@@ -765,7 +950,9 @@ public:
return T->getClauseKind() == OMPC_untied;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'mergeable' clause in the '#pragma omp ...'
@@ -795,7 +982,9 @@ public:
return T->getClauseKind() == OMPC_mergeable;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'read' clause in the '#pragma omp atomic' directive.
@@ -823,7 +1012,9 @@ public:
return T->getClauseKind() == OMPC_read;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'write' clause in the '#pragma omp atomic' directive.
@@ -852,7 +1043,9 @@ public:
return T->getClauseKind() == OMPC_write;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'update' clause in the '#pragma omp atomic'
@@ -882,7 +1075,9 @@ public:
return T->getClauseKind() == OMPC_update;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'capture' clause in the '#pragma omp atomic'
@@ -912,7 +1107,9 @@ public:
return T->getClauseKind() == OMPC_capture;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic'
@@ -942,7 +1139,9 @@ public:
return T->getClauseKind() == OMPC_seq_cst;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents clause 'private' in the '#pragma omp ...' directives.
@@ -953,7 +1152,11 @@ public:
/// In this example directive '#pragma omp parallel' has clause 'private'
/// with the variables 'a' and 'b'.
///
-class OMPPrivateClause : public OMPVarListClause<OMPPrivateClause> {
+class OMPPrivateClause final
+ : public OMPVarListClause<OMPPrivateClause>,
+ private llvm::TrailingObjects<OMPPrivateClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
friend class OMPClauseReader;
/// \brief Build clause with number of variables \a N.
///
@@ -1026,9 +1229,9 @@ public:
getPrivateCopies().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1045,7 +1248,11 @@ public:
/// In this example directive '#pragma omp parallel' has clause 'firstprivate'
/// with the variables 'a' and 'b'.
///
-class OMPFirstprivateClause : public OMPVarListClause<OMPFirstprivateClause> {
+class OMPFirstprivateClause final
+ : public OMPVarListClause<OMPFirstprivateClause>,
+ private llvm::TrailingObjects<OMPFirstprivateClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
friend class OMPClauseReader;
/// \brief Build clause with number of variables \a N.
@@ -1147,9 +1354,9 @@ public:
return inits_const_range(getInits().begin(), getInits().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1165,7 +1372,9 @@ public:
/// \endcode
/// In this example directive '#pragma omp simd' has clause 'lastprivate'
/// with the variables 'a' and 'b'.
-class OMPLastprivateClause : public OMPVarListClause<OMPLastprivateClause> {
+class OMPLastprivateClause final
+ : public OMPVarListClause<OMPLastprivateClause>,
+ private llvm::TrailingObjects<OMPLastprivateClause, Expr *> {
// There are 4 additional tail-allocated arrays at the end of the class:
// 1. Contains list of pseudo variables with the default initialization for
// each non-firstprivate variables. Used in codegen for initialization of
@@ -1183,6 +1392,8 @@ class OMPLastprivateClause : public OMPVarListClause<OMPLastprivateClause> {
// Required for proper codegen of final assignment performed by the
// lastprivate clause.
//
+ friend TrailingObjects;
+ friend OMPVarListClause;
friend class OMPClauseReader;
/// \brief Build clause with number of variables \a N.
@@ -1332,9 +1543,9 @@ public:
getAssignmentOps().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1350,7 +1561,11 @@ public:
/// In this example directive '#pragma omp parallel' has clause 'shared'
/// with the variables 'a' and 'b'.
///
-class OMPSharedClause : public OMPVarListClause<OMPSharedClause> {
+class OMPSharedClause final
+ : public OMPVarListClause<OMPSharedClause>,
+ private llvm::TrailingObjects<OMPSharedClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
@@ -1391,9 +1606,9 @@ public:
///
static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N);
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1410,7 +1625,11 @@ public:
/// In this example directive '#pragma omp parallel' has clause 'reduction'
/// with operator '+' and the variables 'a' and 'b'.
///
-class OMPReductionClause : public OMPVarListClause<OMPReductionClause> {
+class OMPReductionClause final
+ : public OMPVarListClause<OMPReductionClause>,
+ private llvm::TrailingObjects<OMPReductionClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
friend class OMPClauseReader;
/// \brief Location of ':'.
SourceLocation ColonLoc;
@@ -1455,16 +1674,29 @@ class OMPReductionClause : public OMPVarListClause<OMPReductionClause> {
void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; }
/// \brief Set list of helper expressions, required for proper codegen of the
+ /// clause. These expressions represent private copy of the reduction
+ /// variable.
+ void setPrivates(ArrayRef<Expr *> Privates);
+
+ /// \brief Get the list of helper privates.
+ MutableArrayRef<Expr *> getPrivates() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getPrivates() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+ /// \brief Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent LHS expression in the final
/// reduction expression performed by the reduction clause.
void setLHSExprs(ArrayRef<Expr *> LHSExprs);
/// \brief Get the list of helper LHS expressions.
MutableArrayRef<Expr *> getLHSExprs() {
- return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size());
}
ArrayRef<const Expr *> getLHSExprs() const {
- return llvm::makeArrayRef(varlist_end(), varlist_size());
+ return llvm::makeArrayRef(getPrivates().end(), varlist_size());
}
/// \brief Set list of helper expressions, required for proper codegen of the
@@ -1506,6 +1738,8 @@ public:
/// \param VL The variables in the clause.
/// \param QualifierLoc The nested-name qualifier with location information
/// \param NameInfo The full name info for reduction identifier.
+ /// \param Privates List of helper expressions for proper generation of
+ /// private copies.
/// \param LHSExprs List of helper expressions for proper generation of
/// assignment operation required for copyprivate clause. This list represents
/// LHSs of the reduction expressions.
@@ -1528,8 +1762,9 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
NestedNameSpecifierLoc QualifierLoc,
- const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> LHSExprs,
- ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps);
+ const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates,
+ ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
+ ArrayRef<Expr *> ReductionOps);
/// \brief Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
@@ -1550,6 +1785,12 @@ public:
typedef llvm::iterator_range<helper_expr_const_iterator>
helper_expr_const_range;
+ helper_expr_const_range privates() const {
+ return helper_expr_const_range(getPrivates().begin(), getPrivates().end());
+ }
+ helper_expr_range privates() {
+ return helper_expr_range(getPrivates().begin(), getPrivates().end());
+ }
helper_expr_const_range lhs_exprs() const {
return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end());
}
@@ -1571,9 +1812,9 @@ public:
getReductionOps().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1590,8 +1831,16 @@ public:
/// In this example directive '#pragma omp simd' has clause 'linear'
/// with variables 'a', 'b' and linear step '2'.
///
-class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
+class OMPLinearClause final
+ : public OMPVarListClause<OMPLinearClause>,
+ private llvm::TrailingObjects<OMPLinearClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
friend class OMPClauseReader;
+ /// \brief Modifier of 'linear' clause.
+ OpenMPLinearClauseKind Modifier;
+ /// \brief Location of linear modifier if any.
+ SourceLocation ModifierLoc;
/// \brief Location of ':'.
SourceLocation ColonLoc;
@@ -1610,11 +1859,12 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
/// \param NumVars Number of variables.
///
OMPLinearClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
SourceLocation ColonLoc, SourceLocation EndLoc,
unsigned NumVars)
: OMPVarListClause<OMPLinearClause>(OMPC_linear, StartLoc, LParenLoc,
EndLoc, NumVars),
- ColonLoc(ColonLoc) {}
+ Modifier(Modifier), ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {}
/// \brief Build an empty clause.
///
@@ -1624,7 +1874,7 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
: OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(),
SourceLocation(), SourceLocation(),
NumVars),
- ColonLoc(SourceLocation()) {}
+ Modifier(OMPC_LINEAR_val), ModifierLoc(), ColonLoc() {}
/// \brief Gets the list of initial values for linear variables.
///
@@ -1636,16 +1886,23 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
/// expressions - linear step and a helper to calculate it before the
/// loop body (used when the linear step is not constant):
///
- /// { Vars[] /* in OMPVarListClause */; Inits[]; Updates[]; Finals[];
- /// Step; CalcStep; }
+ /// { Vars[] /* in OMPVarListClause */; Privates[]; Inits[]; Updates[];
+ /// Finals[]; Step; CalcStep; }
///
- MutableArrayRef<Expr *> getInits() {
+ MutableArrayRef<Expr *> getPrivates() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
- ArrayRef<const Expr *> getInits() const {
+ ArrayRef<const Expr *> getPrivates() const {
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
+ MutableArrayRef<Expr *> getInits() {
+ return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getInits() const {
+ return llvm::makeArrayRef(getPrivates().end(), varlist_size());
+ }
+
/// \brief Sets the list of update expressions for linear variables.
MutableArrayRef<Expr *> getUpdates() {
return MutableArrayRef<Expr *>(getInits().end(), varlist_size());
@@ -1662,6 +1919,10 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
return llvm::makeArrayRef(getUpdates().end(), varlist_size());
}
+ /// \brief Sets the list of the copies of original linear variables.
+ /// \param PL List of expressions.
+ void setPrivates(ArrayRef<Expr *> PL);
+
/// \brief Sets the list of the initial values for linear variables.
/// \param IL List of expressions.
void setInits(ArrayRef<Expr *> IL);
@@ -1673,17 +1934,20 @@ public:
/// \param C AST Context.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
+ /// \param Modifier Modifier of 'linear' clause.
+ /// \param ModifierLoc Modifier location.
/// \param ColonLoc Location of ':'.
/// \param EndLoc Ending location of the clause.
/// \param VL List of references to the variables.
+ /// \param PL List of private copies of original variables.
/// \param IL List of initial values for the variables.
/// \param Step Linear step.
/// \param CalcStep Calculation of the linear step.
- static OMPLinearClause *Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ColonLoc, SourceLocation EndLoc,
- ArrayRef<Expr *> VL, ArrayRef<Expr *> IL,
- Expr *Step, Expr *CalcStep);
+ static OMPLinearClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep);
/// \brief Creates an empty clause with the place for \a NumVars variables.
///
@@ -1692,9 +1956,19 @@ public:
///
static OMPLinearClause *CreateEmpty(const ASTContext &C, unsigned NumVars);
+ /// \brief Set modifier.
+ void setModifier(OpenMPLinearClauseKind Kind) { Modifier = Kind; }
+ /// \brief Return modifier.
+ OpenMPLinearClauseKind getModifier() const { return Modifier; }
+
+ /// \brief Set modifier location.
+ void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; }
+ /// \brief Return modifier location.
+ SourceLocation getModifierLoc() const { return ModifierLoc; }
+
/// \brief Sets the location of ':'.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// \brief Returns the location of ':'.
SourceLocation getColonLoc() const { return ColonLoc; }
/// \brief Returns linear step.
@@ -1714,6 +1988,18 @@ public:
/// \param FL List of expressions.
void setFinals(ArrayRef<Expr *> FL);
+ typedef MutableArrayRef<Expr *>::iterator privates_iterator;
+ typedef ArrayRef<const Expr *>::iterator privates_const_iterator;
+ typedef llvm::iterator_range<privates_iterator> privates_range;
+ typedef llvm::iterator_range<privates_const_iterator> privates_const_range;
+
+ privates_range privates() {
+ return privates_range(getPrivates().begin(), getPrivates().end());
+ }
+ privates_const_range privates() const {
+ return privates_const_range(getPrivates().begin(), getPrivates().end());
+ }
+
typedef MutableArrayRef<Expr *>::iterator inits_iterator;
typedef ArrayRef<const Expr *>::iterator inits_const_iterator;
typedef llvm::iterator_range<inits_iterator> inits_range;
@@ -1750,9 +2036,9 @@ public:
return finals_const_range(getFinals().begin(), getFinals().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1769,7 +2055,11 @@ public:
/// In this example directive '#pragma omp simd' has clause 'aligned'
/// with variables 'a', 'b' and alignment '8'.
///
-class OMPAlignedClause : public OMPVarListClause<OMPAlignedClause> {
+class OMPAlignedClause final
+ : public OMPVarListClause<OMPAlignedClause>,
+ private llvm::TrailingObjects<OMPAlignedClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
friend class OMPClauseReader;
/// \brief Location of ':'.
SourceLocation ColonLoc;
@@ -1835,9 +2125,9 @@ public:
/// \brief Returns alignment.
const Expr *getAlignment() const { return *varlist_end(); }
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1853,7 +2143,9 @@ public:
/// In this example directive '#pragma omp parallel' has clause 'copyin'
/// with the variables 'a' and 'b'.
///
-class OMPCopyinClause : public OMPVarListClause<OMPCopyinClause> {
+class OMPCopyinClause final
+ : public OMPVarListClause<OMPCopyinClause>,
+ private llvm::TrailingObjects<OMPCopyinClause, Expr *> {
// Class has 3 additional tail allocated arrays:
// 1. List of helper expressions for proper generation of assignment operation
// required for copyin clause. This list represents sources.
@@ -1867,6 +2159,8 @@ class OMPCopyinClause : public OMPVarListClause<OMPCopyinClause> {
// threadprivate variables to local instances of that variables in other
// implicit threads.
+ friend TrailingObjects;
+ friend OMPVarListClause;
friend class OMPClauseReader;
/// \brief Build clause with number of variables \a N.
///
@@ -1993,9 +2287,9 @@ public:
getAssignmentOps().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -2012,7 +2306,11 @@ public:
/// In this example directive '#pragma omp single' has clause 'copyprivate'
/// with the variables 'a' and 'b'.
///
-class OMPCopyprivateClause : public OMPVarListClause<OMPCopyprivateClause> {
+class OMPCopyprivateClause final
+ : public OMPVarListClause<OMPCopyprivateClause>,
+ private llvm::TrailingObjects<OMPCopyprivateClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
friend class OMPClauseReader;
/// \brief Build clause with number of variables \a N.
///
@@ -2138,9 +2436,9 @@ public:
getAssignmentOps().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -2161,7 +2459,11 @@ public:
/// In this example directive '#pragma omp flush' has implicit clause 'flush'
/// with the variables 'a' and 'b'.
///
-class OMPFlushClause : public OMPVarListClause<OMPFlushClause> {
+class OMPFlushClause final
+ : public OMPVarListClause<OMPFlushClause>,
+ private llvm::TrailingObjects<OMPFlushClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
@@ -2202,9 +2504,9 @@ public:
///
static OMPFlushClause *CreateEmpty(const ASTContext &C, unsigned N);
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -2221,7 +2523,11 @@ public:
/// In this example directive '#pragma omp task' with clause 'depend' with the
/// variables 'a' and 'b' with dependency 'in'.
///
-class OMPDependClause : public OMPVarListClause<OMPDependClause> {
+class OMPDependClause final
+ : public OMPVarListClause<OMPDependClause>,
+ private llvm::TrailingObjects<OMPDependClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
friend class OMPClauseReader;
/// \brief Dependency type (one of in, out, inout).
OpenMPDependClauseKind DepKind;
@@ -2290,9 +2596,9 @@ public:
/// \brief Get colon location.
SourceLocation getColonLoc() const { return ColonLoc; }
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -2300,7 +2606,593 @@ public:
}
};
-} // end namespace clang
+/// \brief This represents 'device' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp target device(a)
+/// \endcode
+/// In this example directive '#pragma omp target' has clause 'device'
+/// with single expression 'a'.
+///
+class OMPDeviceClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Device number.
+ Stmt *Device;
+ /// \brief Set the device number.
+ ///
+ /// \param E Device number.
+ ///
+ void setDevice(Expr *E) { Device = E; }
+
+public:
+ /// \brief Build 'device' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPDeviceClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_device, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Device(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPDeviceClause()
+ : OMPClause(OMPC_device, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Device(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return device number.
+ Expr *getDevice() { return cast<Expr>(Device); }
+ /// \brief Return device number.
+ Expr *getDevice() const { return cast<Expr>(Device); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_device;
+ }
+
+ child_range children() { return child_range(&Device, &Device + 1); }
+};
+
+/// \brief This represents 'threads' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp ordered threads
+/// \endcode
+/// In this example directive '#pragma omp ordered' has simple 'threads' clause.
+///
+class OMPThreadsClause : public OMPClause {
+public:
+ /// \brief Build 'threads' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_threads, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPThreadsClause()
+ : OMPClause(OMPC_threads, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_threads;
+ }
-#endif
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'simd' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp ordered simd
+/// \endcode
+/// In this example directive '#pragma omp ordered' has simple 'simd' clause.
+///
+class OMPSIMDClause : public OMPClause {
+public:
+ /// \brief Build 'simd' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_simd, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPSIMDClause() : OMPClause(OMPC_simd, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_simd;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents clause 'map' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp target map(a,b)
+/// \endcode
+/// In this example directive '#pragma omp target' has clause 'map'
+/// with the variables 'a' and 'b'.
+///
+class OMPMapClause final : public OMPVarListClause<OMPMapClause>,
+ private llvm::TrailingObjects<OMPMapClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend class OMPClauseReader;
+
+ /// \brief Map type modifier for the 'map' clause.
+ OpenMPMapClauseKind MapTypeModifier;
+ /// \brief Map type for the 'map' clause.
+ OpenMPMapClauseKind MapType;
+ /// \brief Location of the map type.
+ SourceLocation MapLoc;
+ /// \brief Colon location.
+ SourceLocation ColonLoc;
+
+ /// \brief Set type modifier for the clause.
+ ///
+ /// \param T Type Modifier for the clause.
+ ///
+ void setMapTypeModifier(OpenMPMapClauseKind T) { MapTypeModifier = T; }
+
+ /// \brief Set type for the clause.
+ ///
+ /// \param T Type for the clause.
+ ///
+ void setMapType(OpenMPMapClauseKind T) { MapType = T; }
+
+ /// \brief Set type location.
+ ///
+ /// \param TLoc Type location.
+ ///
+ void setMapLoc(SourceLocation TLoc) { MapLoc = TLoc; }
+
+ /// \brief Set colon location.
+ void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param MapTypeModifier Map type modifier.
+ /// \param MapType Map type.
+ /// \param MapLoc Location of the map type.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ explicit OMPMapClause(OpenMPMapClauseKind MapTypeModifier,
+ OpenMPMapClauseKind MapType, SourceLocation MapLoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPMapClause>(OMPC_map, StartLoc, LParenLoc, EndLoc, N),
+ MapTypeModifier(MapTypeModifier), MapType(MapType), MapLoc(MapLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPMapClause(unsigned N)
+ : OMPVarListClause<OMPMapClause>(OMPC_map, SourceLocation(),
+ SourceLocation(), SourceLocation(), N),
+ MapTypeModifier(OMPC_MAP_unknown), MapType(OMPC_MAP_unknown), MapLoc() {}
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ /// \param TypeModifier Map type modifier.
+ /// \param Type Map type.
+ /// \param TypeLoc Location of the map type.
+ ///
+ static OMPMapClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ OpenMPMapClauseKind TypeModifier,
+ OpenMPMapClauseKind Type, SourceLocation TypeLoc);
+ /// \brief Creates an empty clause with the place for \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPMapClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ /// \brief Fetches mapping kind for the clause.
+ OpenMPMapClauseKind getMapType() const LLVM_READONLY { return MapType; }
+
+ /// \brief Fetches the map type modifier for the clause.
+ OpenMPMapClauseKind getMapTypeModifier() const LLVM_READONLY {
+ return MapTypeModifier;
+ }
+
+ /// \brief Fetches location of clause mapping kind.
+ SourceLocation getMapLoc() const LLVM_READONLY { return MapLoc; }
+
+ /// \brief Get colon location.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_map;
+ }
+
+ child_range children() {
+ return child_range(
+ reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+};
+
+/// \brief This represents 'num_teams' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp teams num_teams(n)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'num_teams'
+/// with single expression 'n'.
+///
+class OMPNumTeamsClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief NumTeams number.
+ Stmt *NumTeams;
+ /// \brief Set the NumTeams number.
+ ///
+ /// \param E NumTeams number.
+ ///
+ void setNumTeams(Expr *E) { NumTeams = E; }
+
+public:
+ /// \brief Build 'num_teams' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPNumTeamsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_num_teams, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumTeams(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPNumTeamsClause()
+ : OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), NumTeams(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return NumTeams number.
+ Expr *getNumTeams() { return cast<Expr>(NumTeams); }
+ /// \brief Return NumTeams number.
+ Expr *getNumTeams() const { return cast<Expr>(NumTeams); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_num_teams;
+ }
+
+ child_range children() { return child_range(&NumTeams, &NumTeams + 1); }
+};
+
+/// \brief This represents 'thread_limit' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp teams thread_limit(n)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'thread_limit'
+/// with single expression 'n'.
+///
+class OMPThreadLimitClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief ThreadLimit number.
+ Stmt *ThreadLimit;
+ /// \brief Set the ThreadLimit number.
+ ///
+ /// \param E ThreadLimit number.
+ ///
+ void setThreadLimit(Expr *E) { ThreadLimit = E; }
+
+public:
+ /// \brief Build 'thread_limit' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPThreadLimitClause(Expr *E, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_thread_limit, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ ThreadLimit(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPThreadLimitClause()
+ : OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), ThreadLimit(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return ThreadLimit number.
+ Expr *getThreadLimit() { return cast<Expr>(ThreadLimit); }
+ /// \brief Return ThreadLimit number.
+ Expr *getThreadLimit() const { return cast<Expr>(ThreadLimit); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_thread_limit;
+ }
+
+ child_range children() { return child_range(&ThreadLimit, &ThreadLimit + 1); }
+};
+
+/// \brief This represents 'priority' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp task priority(n)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'priority' with
+/// single expression 'n'.
+///
+class OMPPriorityClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Priority number.
+ Stmt *Priority;
+ /// \brief Set the Priority number.
+ ///
+ /// \param E Priority number.
+ ///
+ void setPriority(Expr *E) { Priority = E; }
+
+public:
+ /// \brief Build 'priority' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPPriorityClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_priority, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Priority(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPPriorityClause()
+ : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Priority(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return Priority number.
+ Expr *getPriority() { return cast<Expr>(Priority); }
+ /// \brief Return Priority number.
+ Expr *getPriority() const { return cast<Expr>(Priority); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_priority;
+ }
+
+ child_range children() { return child_range(&Priority, &Priority + 1); }
+};
+
+/// \brief This represents 'grainsize' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp taskloop grainsize(4)
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has clause 'grainsize'
+/// with single expression '4'.
+///
+class OMPGrainsizeClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Safe iteration space distance.
+ Stmt *Grainsize;
+
+ /// \brief Set safelen.
+ void setGrainsize(Expr *Size) { Grainsize = Size; }
+
+public:
+ /// \brief Build 'grainsize' clause.
+ ///
+ /// \param Size Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPGrainsizeClause(Expr *Size, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_grainsize, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Grainsize(Size) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPGrainsizeClause()
+ : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Grainsize(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return safe iteration space distance.
+ Expr *getGrainsize() const { return cast_or_null<Expr>(Grainsize); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_grainsize;
+ }
+
+ child_range children() { return child_range(&Grainsize, &Grainsize + 1); }
+};
+
+/// \brief This represents 'nogroup' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp taskloop nogroup
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has 'nogroup' clause.
+///
+class OMPNogroupClause : public OMPClause {
+public:
+ /// \brief Build 'nogroup' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_nogroup, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPNogroupClause()
+ : OMPClause(OMPC_nogroup, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_nogroup;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'num_tasks' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp taskloop num_tasks(4)
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has clause 'num_tasks'
+/// with single expression '4'.
+///
+class OMPNumTasksClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Safe iteration space distance.
+ Stmt *NumTasks;
+
+ /// \brief Set safelen.
+ void setNumTasks(Expr *Size) { NumTasks = Size; }
+
+public:
+ /// \brief Build 'num_tasks' clause.
+ ///
+ /// \param Size Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPNumTasksClause(Expr *Size, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_num_tasks, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumTasks(Size) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPNumTasksClause()
+ : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), NumTasks(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return safe iteration space distance.
+ Expr *getNumTasks() const { return cast_or_null<Expr>(NumTasks); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_num_tasks;
+ }
+
+ child_range children() { return child_range(&NumTasks, &NumTasks + 1); }
+};
+
+/// \brief This represents 'hint' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp critical (name) hint(6)
+/// \endcode
+/// In this example directive '#pragma omp critical' has name 'name' and clause
+/// 'hint' with argument '6'.
+///
+class OMPHintClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Hint expression of the 'hint' clause.
+ Stmt *Hint;
+
+ /// \brief Set hint expression.
+ ///
+ void setHint(Expr *H) { Hint = H; }
+
+public:
+ /// \brief Build 'hint' clause with expression \a Hint.
+ ///
+ /// \param Hint Hint expression.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_hint, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Hint(Hint) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPHintClause()
+ : OMPClause(OMPC_hint, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Hint(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Returns number of threads.
+ Expr *getHint() const { return cast_or_null<Expr>(Hint); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_hint;
+ }
+
+ child_range children() { return child_range(&Hint, &Hint + 1); }
+};
+
+} // end namespace clang
+#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
index e3f0126..102bbc2 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
@@ -185,7 +185,11 @@ enum CastKind {
/// CK_FloatingToBoolean - Floating point to boolean.
/// (bool) f
CK_FloatingToBoolean,
-
+
+ // CK_BooleanToSignedIntegral - Convert a boolean to -1 or 0 for true and
+ // false, respectively.
+ CK_BooleanToSignedIntegral,
+
/// CK_FloatingCast - Casting between floating types of different size.
/// (double) f
/// (float) ld
@@ -334,7 +338,8 @@ enum UnaryOperatorKind {
UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic
UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic
UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension.
- UO_Extension // __extension__ marker.
+ UO_Extension, // __extension__ marker.
+ UO_Coawait // [C++ Coroutines] co_await operator
};
/// \brief The kind of bridging performed by the Objective-C bridge cast.
diff --git a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
index 35ceabb..8ab3f617 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
@@ -42,7 +42,7 @@ struct PrintingPolicy {
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false),
Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
- IncludeNewlines(true) { }
+ IncludeNewlines(true), MSVCFormatting(false) { }
/// \brief What language we're printing.
LangOptions LangOpts;
@@ -109,7 +109,7 @@ struct PrintingPolicy {
/// \brief Whether we should print the sizes of constant array expressions
/// as written in the sources.
///
- /// This flag is determines whether arrays types declared as
+ /// This flag determines whether array types declared as
///
/// \code
/// int a[4+10*10];
@@ -163,6 +163,11 @@ struct PrintingPolicy {
/// \brief When true, include newlines after statements like "break", etc.
unsigned IncludeNewlines : 1;
+
+ /// \brief Use whitespace and punctuation like MSVC does. In particular, this
+ /// prints anonymous namespaces as `anonymous namespace' and does not insert
+ /// spaces after template arguments.
+ bool MSVCFormatting : 1;
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
index 1017656..0c25a45 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
#define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
+#include <type_traits>
+
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -24,6 +26,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
@@ -42,7 +45,7 @@
OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \
OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \
OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \
- OPERATOR(Extension)
+ OPERATOR(Extension) OPERATOR(Coawait)
// All binary operators (excluding compound assign operators).
#define BINOP_LIST() \
@@ -132,6 +135,12 @@ namespace clang {
/// from which they were produced.
template <typename Derived> class RecursiveASTVisitor {
public:
+ /// A queue used for performing data recursion over statements.
+ /// Parameters involving this type are used to implement data
+ /// recursion over Stmts and Exprs within this class, and should
+ /// typically not be explicitly specified by derived classes.
+ typedef SmallVectorImpl<Stmt *> DataRecursionQueue;
+
/// \brief Return a reference to the derived class.
Derived &getDerived() { return *static_cast<Derived *>(this); }
@@ -147,19 +156,12 @@ public:
/// code, e.g., implicit constructors and destructors.
bool shouldVisitImplicitCode() const { return false; }
- /// \brief Return whether \param S should be traversed using data recursion
- /// to avoid a stack overflow with extreme cases.
- bool shouldUseDataRecursionFor(Stmt *S) const {
- return isa<BinaryOperator>(S) || isa<UnaryOperator>(S) ||
- isa<CaseStmt>(S) || isa<CXXOperatorCallExpr>(S);
- }
-
/// \brief Recursively visit a statement or expression, by
/// dispatching to Traverse*() based on the argument's dynamic type.
///
/// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is NULL).
- bool TraverseStmt(Stmt *S);
+ /// otherwise (including when the argument is nullptr).
+ bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr);
/// \brief Recursively visit a type, by dispatching to
/// Traverse*Type() based on the argument's getTypeClass() property.
@@ -252,7 +254,14 @@ public:
/// \c LE->getBody().
///
/// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseLambdaBody(LambdaExpr *LE);
+ bool TraverseLambdaBody(LambdaExpr *LE, DataRecursionQueue *Queue = nullptr);
+
+ /// \brief Recursively visit the syntactic or semantic form of an
+ /// initialization list.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseSynOrSemInitListExpr(InitListExpr *S,
+ DataRecursionQueue *Queue = nullptr);
// ---- Methods on Attrs ----
@@ -266,9 +275,44 @@ public:
// ---- Methods on Stmts ----
+private:
+ template<typename T, typename U>
+ struct has_same_member_pointer_type : std::false_type {};
+ template<typename T, typename U, typename R, typename... P>
+ struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)>
+ : std::true_type {};
+
+ // Traverse the given statement. If the most-derived traverse function takes a
+ // data recursion queue, pass it on; otherwise, discard it. Note that the
+ // first branch of this conditional must compile whether or not the derived
+ // class can take a queue, so if we're taking the second arm, make the first
+ // arm call our function rather than the derived class version.
+#define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \
+ (has_same_member_pointer_type<decltype( \
+ &RecursiveASTVisitor::Traverse##NAME), \
+ decltype(&Derived::Traverse##NAME)>::value \
+ ? static_cast<typename std::conditional< \
+ has_same_member_pointer_type< \
+ decltype(&RecursiveASTVisitor::Traverse##NAME), \
+ decltype(&Derived::Traverse##NAME)>::value, \
+ Derived &, RecursiveASTVisitor &>::type>(*this) \
+ .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \
+ : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)))
+
+// Try to traverse the given statement, or enqueue it if we're performing data
+// recursion in the middle of traversing another statement. Can only be called
+// from within a DEF_TRAVERSE_STMT body or similar context.
+#define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S) \
+ do { \
+ if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue)) \
+ return false; \
+ } while (0)
+
+public:
// Declare Traverse*() for all concrete Stmt classes.
#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S);
+#define STMT(CLASS, PARENT) \
+ bool Traverse##CLASS(CLASS *S, DataRecursionQueue *Queue = nullptr);
#include "clang/AST/StmtNodes.inc"
// The above header #undefs ABSTRACT_STMT and STMT upon exit.
@@ -288,9 +332,10 @@ public:
// operator methods. Unary operators are not classes in themselves
// (they're all opcodes in UnaryOperator) but do have visitors.
#define OPERATOR(NAME) \
- bool TraverseUnary##NAME(UnaryOperator *S) { \
+ bool TraverseUnary##NAME(UnaryOperator *S, \
+ DataRecursionQueue *Queue = nullptr) { \
TRY_TO(WalkUpFromUnary##NAME(S)); \
- TRY_TO(TraverseStmt(S->getSubExpr())); \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \
return true; \
} \
bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
@@ -307,10 +352,10 @@ public:
// operator methods. Binary operators are not classes in themselves
// (they're all opcodes in BinaryOperator) but do have visitors.
#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
- bool TraverseBin##NAME(BINOP_TYPE *S) { \
+ bool TraverseBin##NAME(BINOP_TYPE *S, DataRecursionQueue *Queue = nullptr) { \
TRY_TO(WalkUpFromBin##NAME(S)); \
- TRY_TO(TraverseStmt(S->getLHS())); \
- TRY_TO(TraverseStmt(S->getRHS())); \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS()); \
return true; \
} \
bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
@@ -436,98 +481,45 @@ private:
/// \brief Process clauses with list of variables.
template <typename T> bool VisitOMPClauseList(T *Node);
- struct EnqueueJob {
- Stmt *S;
- Stmt::child_iterator StmtIt;
-
- EnqueueJob(Stmt *S) : S(S), StmtIt() {}
- };
- bool dataTraverse(Stmt *S);
- bool dataTraverseNode(Stmt *S, bool &EnqueueChildren);
+ bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue);
};
template <typename Derived>
-bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {
-
- SmallVector<EnqueueJob, 16> Queue;
- Queue.push_back(S);
-
- while (!Queue.empty()) {
- EnqueueJob &job = Queue.back();
- Stmt *CurrS = job.S;
- if (!CurrS) {
- Queue.pop_back();
- continue;
- }
-
- if (getDerived().shouldUseDataRecursionFor(CurrS)) {
- if (job.StmtIt == Stmt::child_iterator()) {
- bool EnqueueChildren = true;
- if (!dataTraverseNode(CurrS, EnqueueChildren))
- return false;
- if (!EnqueueChildren) {
- Queue.pop_back();
- continue;
- }
- job.StmtIt = CurrS->child_begin();
- } else {
- ++job.StmtIt;
- }
-
- if (job.StmtIt != CurrS->child_end())
- Queue.push_back(*job.StmtIt);
- else
- Queue.pop_back();
- continue;
- }
-
- Queue.pop_back();
- TRY_TO(TraverseStmt(CurrS));
- }
-
- return true;
-}
-
-template <typename Derived>
bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
- bool &EnqueueChildren) {
-
-// Dispatch to the corresponding WalkUpFrom* function only if the derived
-// class didn't override Traverse* (and thus the traversal is trivial).
-#define DISPATCH_WALK(NAME, CLASS, VAR) \
- { \
- bool (Derived::*DerivedFn)(CLASS *) = &Derived::Traverse##NAME; \
- bool (Derived::*BaseFn)(CLASS *) = &RecursiveASTVisitor::Traverse##NAME; \
- if (DerivedFn == BaseFn) \
- return getDerived().WalkUpFrom##NAME(static_cast<CLASS *>(VAR)); \
- } \
- EnqueueChildren = false; \
- return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR));
+ DataRecursionQueue *Queue) {
+#define DISPATCH_STMT(NAME, CLASS, VAR) \
+ return TRAVERSE_STMT_BASE(NAME, CLASS, VAR, Queue);
+ // If we have a binary expr, dispatch to the subcode of the binop. A smart
+ // optimizer (e.g. LLVM) will fold this comparison into the switch stmt
+ // below.
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
#define OPERATOR(NAME) \
case BO_##NAME: \
- DISPATCH_WALK(Bin##NAME, BinaryOperator, S);
+ DISPATCH_STMT(Bin##NAME, BinaryOperator, S);
BINOP_LIST()
#undef OPERATOR
+#undef BINOP_LIST
#define OPERATOR(NAME) \
case BO_##NAME##Assign: \
- DISPATCH_WALK(Bin##NAME##Assign, CompoundAssignOperator, S);
+ DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S);
CAO_LIST()
#undef OPERATOR
+#undef CAO_LIST
}
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
#define OPERATOR(NAME) \
case UO_##NAME: \
- DISPATCH_WALK(Unary##NAME, UnaryOperator, S);
+ DISPATCH_STMT(Unary##NAME, UnaryOperator, S);
UNARYOP_LIST()
#undef OPERATOR
+#undef UNARYOP_LIST
}
}
@@ -538,76 +530,43 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
#define ABSTRACT_STMT(STMT)
#define STMT(CLASS, PARENT) \
case Stmt::CLASS##Class: \
- DISPATCH_WALK(CLASS, CLASS, S);
+ DISPATCH_STMT(CLASS, CLASS, S);
#include "clang/AST/StmtNodes.inc"
}
-#undef DISPATCH_WALK
-
return true;
}
-#define DISPATCH(NAME, CLASS, VAR) \
- return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
+#undef DISPATCH_STMT
template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
+bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S,
+ DataRecursionQueue *Queue) {
if (!S)
return true;
-#define DISPATCH_STMT(NAME, CLASS, VAR) DISPATCH(NAME, CLASS, VAR)
-
- if (getDerived().shouldUseDataRecursionFor(S))
- return dataTraverse(S);
-
- // If we have a binary expr, dispatch to the subcode of the binop. A smart
- // optimizer (e.g. LLVM) will fold this comparison into the switch stmt
- // below.
- if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
- switch (BinOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case BO_##NAME: \
- DISPATCH_STMT(Bin##NAME, BinaryOperator, S);
+ if (Queue) {
+ Queue->push_back(S);
+ return true;
+ }
- BINOP_LIST()
-#undef OPERATOR
-#undef BINOP_LIST
+ SmallVector<Stmt *, 8> LocalQueue;
+ LocalQueue.push_back(S);
-#define OPERATOR(NAME) \
- case BO_##NAME##Assign: \
- DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S);
+ while (!LocalQueue.empty()) {
+ Stmt *CurrS = LocalQueue.pop_back_val();
- CAO_LIST()
-#undef OPERATOR
-#undef CAO_LIST
- }
- } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
- switch (UnOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case UO_##NAME: \
- DISPATCH_STMT(Unary##NAME, UnaryOperator, S);
-
- UNARYOP_LIST()
-#undef OPERATOR
-#undef UNARYOP_LIST
- }
- }
-
- // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
- switch (S->getStmtClass()) {
- case Stmt::NoStmtClass:
- break;
-#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) \
- case Stmt::CLASS##Class: \
- DISPATCH_STMT(CLASS, CLASS, S);
-#include "clang/AST/StmtNodes.inc"
+ size_t N = LocalQueue.size();
+ TRY_TO(dataTraverseNode(CurrS, &LocalQueue));
+ // Process new children in the order they were added.
+ std::reverse(LocalQueue.begin() + N, LocalQueue.end());
}
return true;
}
-#undef DISPATCH_STMT
+#define DISPATCH(NAME, CLASS, VAR) \
+ return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
@@ -863,8 +822,9 @@ RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
}
template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) {
- TRY_TO(TraverseStmt(LE->getBody()));
+bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(
+ LambdaExpr *LE, DataRecursionQueue *Queue) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(LE->getBody());
return true;
}
@@ -1018,6 +978,8 @@ DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
+DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); })
+
#undef DEF_TRAVERSE_TYPE
// ----------------- TypeLoc traversal -----------------
@@ -1246,6 +1208,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
+DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
+
#undef DEF_TRAVERSE_TYPELOC
// ----------------- Decl traversal -----------------
@@ -1364,6 +1328,8 @@ DEF_TRAVERSE_DECL(
DEF_TRAVERSE_DECL(ExternCContextDecl, {})
DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+
// We shouldn't traverse an aliased namespace, since it will be
// defined (and, therefore, traversed) somewhere else.
//
@@ -1596,6 +1562,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
})
+DEF_TRAVERSE_DECL(BuiltinTemplateDecl, {
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+})
+
DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
// D is the "T" in something like "template<typename T> class vector;"
if (D->getTypeForDecl())
@@ -1906,25 +1876,26 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
// This macro makes available a variable S, the passed-in stmt.
#define DEF_TRAVERSE_STMT(STMT, CODE) \
template <typename Derived> \
- bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \
+ bool RecursiveASTVisitor<Derived>::Traverse##STMT( \
+ STMT *S, DataRecursionQueue *Queue) { \
TRY_TO(WalkUpFrom##STMT(S)); \
{ CODE; } \
for (Stmt *SubStmt : S->children()) { \
- TRY_TO(TraverseStmt(SubStmt)); \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \
} \
return true; \
}
DEF_TRAVERSE_STMT(GCCAsmStmt, {
- TRY_TO(TraverseStmt(S->getAsmString()));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString());
for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
- TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I)));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I));
}
for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
- TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I)));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I));
}
for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
- TRY_TO(TraverseStmt(S->getClobberStringLiteral(I)));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I));
}
// children() iterates over inputExpr and outputExpr.
})
@@ -1977,9 +1948,9 @@ DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {})
DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {})
DEF_TRAVERSE_STMT(CXXForRangeStmt, {
if (!getDerived().shouldVisitImplicitCode()) {
- TRY_TO(TraverseStmt(S->getLoopVarStmt()));
- TRY_TO(TraverseStmt(S->getRangeInit()));
- TRY_TO(TraverseStmt(S->getBody()));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLoopVarStmt());
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRangeInit());
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
// Visit everything else only if shouldVisitImplicitCode().
return true;
}
@@ -2012,9 +1983,8 @@ DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
if (S->hasExplicitTemplateArgs()) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- S->getExplicitTemplateArgs().getTemplateArgs(),
- S->getNumTemplateArgs()));
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
}
})
@@ -2055,64 +2025,60 @@ DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
-// InitListExpr is a tricky one, because we want to do all our work on
-// the syntactic form of the listexpr, but this method takes the
-// semantic form by default. We can't use the macro helper because it
-// calls WalkUp*() on the semantic form, before our code can convert
-// to the syntactic form.
template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
- InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S;
- if (Syn) {
- TRY_TO(WalkUpFromInitListExpr(Syn));
+bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
+ InitListExpr *S, DataRecursionQueue *Queue) {
+ if (S) {
+ TRY_TO(WalkUpFromInitListExpr(S));
// All we need are the default actions. FIXME: use a helper function.
- for (Stmt *SubStmt : Syn->children()) {
- TRY_TO(TraverseStmt(SubStmt));
- }
- }
- InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm();
- if (Sem) {
- TRY_TO(WalkUpFromInitListExpr(Sem));
- for (Stmt *SubStmt : Sem->children()) {
- TRY_TO(TraverseStmt(SubStmt));
+ for (Stmt *SubStmt : S->children()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt);
}
}
return true;
}
+// This method is called once for each pair of syntactic and semantic
+// InitListExpr, and it traverses the subtrees defined by the two forms. This
+// may cause some of the children to be visited twice, if they appear both in
+// the syntactic and the semantic form.
+//
+// There is no guarantee about which form \p S takes when this method is called.
+DEF_TRAVERSE_STMT(InitListExpr, {
+ TRY_TO(TraverseSynOrSemInitListExpr(
+ S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
+ TRY_TO(TraverseSynOrSemInitListExpr(
+ S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
+ return true;
+})
+
// GenericSelectionExpr is a special case because the types and expressions
// are interleaved. We also need to watch out for null types (default
// generic associations).
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr(
- GenericSelectionExpr *S) {
- TRY_TO(WalkUpFromGenericSelectionExpr(S));
+DEF_TRAVERSE_STMT(GenericSelectionExpr, {
TRY_TO(TraverseStmt(S->getControllingExpr()));
for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
- TRY_TO(TraverseStmt(S->getAssocExpr(i)));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAssocExpr(i));
}
return true;
-}
+})
-// PseudoObjectExpr is a special case because of the wierdness with
+// PseudoObjectExpr is a special case because of the weirdness with
// syntactic expressions and opaque values.
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) {
- TRY_TO(WalkUpFromPseudoObjectExpr(S));
- TRY_TO(TraverseStmt(S->getSyntacticForm()));
+DEF_TRAVERSE_STMT(PseudoObjectExpr, {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSyntacticForm());
for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(),
e = S->semantics_end();
i != e; ++i) {
Expr *sub = *i;
if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub))
sub = OVE->getSourceExpr();
- TRY_TO(TraverseStmt(sub));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(sub);
}
return true;
-}
+})
DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
// This is called for code like 'return T()' where T is a built-in
@@ -2151,6 +2117,8 @@ DEF_TRAVERSE_STMT(MSPropertyRefExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
})
+DEF_TRAVERSE_STMT(MSPropertySubscriptExpr, {})
+
DEF_TRAVERSE_STMT(CXXUuidofExpr, {
// The child-iterator will pick up the arg if it's an expression,
// but not if it's a type.
@@ -2168,7 +2136,7 @@ DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
})
DEF_TRAVERSE_STMT(ExpressionTraitExpr,
- { TRY_TO(TraverseStmt(S->getQueriedExpression())); })
+ { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getQueriedExpression()); })
DEF_TRAVERSE_STMT(VAArgExpr, {
// The child-iterator will pick up the expression argument.
@@ -2181,10 +2149,7 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
})
// Walk only the visible parts of lambda expressions.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
- TRY_TO(WalkUpFromLambdaExpr(S));
-
+DEF_TRAVERSE_STMT(LambdaExpr, {
for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
CEnd = S->explicit_capture_end();
C != CEnd; ++C) {
@@ -2213,12 +2178,11 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
}
if (Expr *NE = T->getNoexceptExpr())
- TRY_TO(TraverseStmt(NE));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE);
}
- TRY_TO(TraverseLambdaBody(S));
- return true;
-}
+ return TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue);
+})
DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
// This is called for code like 'T()', where T is a template argument.
@@ -2235,6 +2199,7 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
// over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, {})
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
+DEF_TRAVERSE_STMT(OMPArraySectionExpr, {})
DEF_TRAVERSE_STMT(BlockExpr, {
TRY_TO(TraverseDecl(S->getBlockDecl()));
return true; // no child statements to loop through.
@@ -2336,6 +2301,34 @@ DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
DEF_TRAVERSE_STMT(CXXFoldExpr, {})
DEF_TRAVERSE_STMT(AtomicExpr, {})
+// For coroutines expressions, traverse either the operand
+// as written or the implied calls, depending on what the
+// derived class requests.
+DEF_TRAVERSE_STMT(CoroutineBodyStmt, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
+ return true;
+ }
+})
+DEF_TRAVERSE_STMT(CoreturnStmt, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
+ return true;
+ }
+})
+DEF_TRAVERSE_STMT(CoawaitExpr, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
+ return true;
+ }
+})
+DEF_TRAVERSE_STMT(CoyieldExpr, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
+ return true;
+ }
+})
+
// These literals (all of them) do not need any action.
DEF_TRAVERSE_STMT(IntegerLiteral, {})
DEF_TRAVERSE_STMT(CharacterLiteral, {})
@@ -2437,9 +2430,21 @@ DEF_TRAVERSE_STMT(OMPAtomicDirective,
DEF_TRAVERSE_STMT(OMPTargetDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPTargetDataDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
DEF_TRAVERSE_STMT(OMPTeamsDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPTaskLoopDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTaskLoopSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPDistributeDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
@@ -2484,6 +2489,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) {
}
template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
+ TRY_TO(TraverseStmt(C->getSimdlen()));
+ return true;
+}
+
+template <typename Derived>
bool
RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) {
TRY_TO(TraverseStmt(C->getNumForLoops()));
@@ -2509,7 +2520,8 @@ RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
}
template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) {
+bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *C) {
+ TRY_TO(TraverseStmt(C->getNumForLoops()));
return true;
}
@@ -2555,6 +2567,21 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
}
template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSIMDClause(OMPSIMDClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNogroupClause(OMPNogroupClause *) {
+ return true;
+}
+
+template <typename Derived>
template <typename T>
bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
for (auto *E : Node->varlists()) {
@@ -2615,6 +2642,9 @@ bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
TRY_TO(TraverseStmt(C->getStep()));
TRY_TO(TraverseStmt(C->getCalcStep()));
TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->privates()) {
+ TRY_TO(TraverseStmt(E));
+ }
for (auto *E : C->inits()) {
TRY_TO(TraverseStmt(E));
}
@@ -2671,6 +2701,9 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->privates()) {
+ TRY_TO(TraverseStmt(E));
+ }
for (auto *E : C->lhs_exprs()) {
TRY_TO(TraverseStmt(E));
}
@@ -2695,6 +2728,59 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ TRY_TO(TraverseStmt(C->getDevice()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPMapClause(OMPMapClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNumTeamsClause(
+ OMPNumTeamsClause *C) {
+ TRY_TO(TraverseStmt(C->getNumTeams()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause(
+ OMPThreadLimitClause *C) {
+ TRY_TO(TraverseStmt(C->getThreadLimit()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause(
+ OMPPriorityClause *C) {
+ TRY_TO(TraverseStmt(C->getPriority()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause(
+ OMPGrainsizeClause *C) {
+ TRY_TO(TraverseStmt(C->getGrainsize()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNumTasksClause(
+ OMPNumTasksClause *C) {
+ TRY_TO(TraverseStmt(C->getNumTasks()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPHintClause(OMPHintClause *C) {
+ TRY_TO(TraverseStmt(C->getHint()));
+ return true;
+}
+
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
@@ -2713,6 +2799,8 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
// Every class that has getQualifier.
#undef DEF_TRAVERSE_STMT
+#undef TRAVERSE_STMT
+#undef TRAVERSE_STMT_BASE
#undef TRY_TO
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
index 92046d5..eaa22f8 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
@@ -20,6 +20,7 @@
#include <iterator>
namespace clang {
+class ASTContext;
/// \brief Provides common interface for the Decls that can be redeclared.
template<typename decl_type>
@@ -32,7 +33,11 @@ protected:
&ExternalASTSource::CompleteRedeclChain>
KnownLatest;
- typedef const ASTContext *UninitializedLatest;
+ /// We store a pointer to the ASTContext in the UninitializedLatest
+ /// pointer, but to avoid circular type dependencies when we steal the low
+ /// bits of this pointer, we use a raw void* here.
+ typedef const void *UninitializedLatest;
+
typedef Decl *Previous;
/// A pointer to either an uninitialized latest declaration (where either
@@ -47,7 +52,7 @@ protected:
enum LatestTag { LatestLink };
DeclLink(LatestTag, const ASTContext &Ctx)
- : Next(NotKnownLatest(&Ctx)) {}
+ : Next(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {}
DeclLink(PreviousTag, decl_type *D)
: Next(NotKnownLatest(Previous(D))) {}
@@ -67,7 +72,8 @@ protected:
return static_cast<decl_type*>(NKL.get<Previous>());
// Allocate the generational 'most recent' cache now, if needed.
- Next = KnownLatest(*NKL.get<UninitializedLatest>(),
+ Next = KnownLatest(*reinterpret_cast<const ASTContext *>(
+ NKL.get<UninitializedLatest>()),
const_cast<decl_type *>(D));
}
@@ -83,7 +89,9 @@ protected:
assert(NextIsLatest() && "decl became canonical unexpectedly");
if (Next.is<NotKnownLatest>()) {
NotKnownLatest NKL = Next.get<NotKnownLatest>();
- Next = KnownLatest(*NKL.get<UninitializedLatest>(), D);
+ Next = KnownLatest(*reinterpret_cast<const ASTContext *>(
+ NKL.get<UninitializedLatest>()),
+ D);
} else {
auto Latest = Next.get<KnownLatest>();
Latest.set(D);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
index ce9449d..d3950e9 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
@@ -22,6 +22,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <string>
@@ -49,57 +50,6 @@ namespace clang {
class Token;
class VarDecl;
- //===--------------------------------------------------------------------===//
- // ExprIterator - Iterators for iterating over Stmt* arrays that contain
- // only Expr*. This is needed because AST nodes use Stmt* arrays to store
- // references to children (to be compatible with StmtIterator).
- //===--------------------------------------------------------------------===//
-
- class Stmt;
- class Expr;
-
- class ExprIterator : public std::iterator<std::forward_iterator_tag,
- Expr *&, ptrdiff_t,
- Expr *&, Expr *&> {
- Stmt** I;
- public:
- ExprIterator(Stmt** i) : I(i) {}
- ExprIterator() : I(nullptr) {}
- ExprIterator& operator++() { ++I; return *this; }
- ExprIterator operator-(size_t i) { return I-i; }
- ExprIterator operator+(size_t i) { return I+i; }
- Expr* operator[](size_t idx);
- // FIXME: Verify that this will correctly return a signed distance.
- signed operator-(const ExprIterator& R) const { return I - R.I; }
- Expr* operator*() const;
- Expr* operator->() const;
- bool operator==(const ExprIterator& R) const { return I == R.I; }
- bool operator!=(const ExprIterator& R) const { return I != R.I; }
- bool operator>(const ExprIterator& R) const { return I > R.I; }
- bool operator>=(const ExprIterator& R) const { return I >= R.I; }
- };
-
- class ConstExprIterator : public std::iterator<std::forward_iterator_tag,
- const Expr *&, ptrdiff_t,
- const Expr *&,
- const Expr *&> {
- const Stmt * const *I;
- public:
- ConstExprIterator(const Stmt * const *i) : I(i) {}
- ConstExprIterator() : I(nullptr) {}
- ConstExprIterator& operator++() { ++I; return *this; }
- ConstExprIterator operator+(size_t i) const { return I+i; }
- ConstExprIterator operator-(size_t i) const { return I-i; }
- const Expr * operator[](size_t idx) const;
- signed operator-(const ConstExprIterator& R) const { return I - R.I; }
- const Expr * operator*() const;
- const Expr * operator->() const;
- bool operator==(const ConstExprIterator& R) const { return I == R.I; }
- bool operator!=(const ConstExprIterator& R) const { return I != R.I; }
- bool operator>(const ConstExprIterator& R) const { return I > R.I; }
- bool operator>=(const ConstExprIterator& R) const { return I >= R.I; }
- };
-
//===----------------------------------------------------------------------===//
// AST classes for statements.
//===----------------------------------------------------------------------===//
@@ -121,10 +71,10 @@ public:
// Make vanilla 'new' and 'delete' illegal for Stmts.
protected:
- void* operator new(size_t bytes) throw() {
+ void *operator new(size_t bytes) LLVM_NOEXCEPT {
llvm_unreachable("Stmts cannot be allocated with regular 'new'.");
}
- void operator delete(void* data) throw() {
+ void operator delete(void *data) LLVM_NOEXCEPT {
llvm_unreachable("Stmts cannot be released with regular 'delete'.");
}
@@ -180,7 +130,7 @@ protected:
friend class CharacterLiteral;
unsigned : NumExprBits;
- unsigned Kind : 2;
+ unsigned Kind : 3;
};
enum APFloatSemantics {
@@ -322,14 +272,12 @@ public:
return operator new(bytes, *C, alignment);
}
- void* operator new(size_t bytes, void* mem) throw() {
- return mem;
- }
+ void *operator new(size_t bytes, void *mem) LLVM_NOEXCEPT { return mem; }
- void operator delete(void*, const ASTContext&, unsigned) throw() { }
- void operator delete(void*, const ASTContext*, unsigned) throw() { }
- void operator delete(void*, size_t) throw() { }
- void operator delete(void*, void*) throw() { }
+ void operator delete(void *, const ASTContext &, unsigned) LLVM_NOEXCEPT {}
+ void operator delete(void *, const ASTContext *, unsigned) LLVM_NOEXCEPT {}
+ void operator delete(void *, size_t) LLVM_NOEXCEPT {}
+ void operator delete(void *, void *) LLVM_NOEXCEPT {}
public:
/// \brief A placeholder type used to construct an empty shell of a
@@ -337,6 +285,39 @@ public:
/// de-serialization).
struct EmptyShell { };
+protected:
+ /// Iterator for iterating over Stmt * arrays that contain only Expr *
+ ///
+ /// This is needed because AST nodes use Stmt* arrays to store
+ /// references to children (to be compatible with StmtIterator).
+ struct ExprIterator
+ : llvm::iterator_adaptor_base<ExprIterator, Stmt **,
+ std::random_access_iterator_tag, Expr *> {
+ ExprIterator() : iterator_adaptor_base(nullptr) {}
+ ExprIterator(Stmt **I) : iterator_adaptor_base(I) {}
+
+ reference operator*() const {
+ assert((*I)->getStmtClass() >= firstExprConstant &&
+ (*I)->getStmtClass() <= lastExprConstant);
+ return *reinterpret_cast<Expr **>(I);
+ }
+ };
+
+ /// Const iterator for iterating over Stmt * arrays that contain only Expr *
+ struct ConstExprIterator
+ : llvm::iterator_adaptor_base<ConstExprIterator, const Stmt *const *,
+ std::random_access_iterator_tag,
+ const Expr *const> {
+ ConstExprIterator() : iterator_adaptor_base(nullptr) {}
+ ConstExprIterator(const Stmt *const *I) : iterator_adaptor_base(I) {}
+
+ reference operator*() const {
+ assert((*I)->getStmtClass() >= firstExprConstant &&
+ (*I)->getStmtClass() <= lastExprConstant);
+ return *reinterpret_cast<const Expr *const *>(I);
+ }
+ };
+
private:
/// \brief Whether statistic collection is enabled.
static bool StatisticsEnabled;
@@ -411,19 +392,20 @@ public:
typedef StmtIterator child_iterator;
typedef ConstStmtIterator const_child_iterator;
- typedef StmtRange child_range;
- typedef ConstStmtRange const_child_range;
+ typedef llvm::iterator_range<child_iterator> child_range;
+ typedef llvm::iterator_range<const_child_iterator> const_child_range;
child_range children();
const_child_range children() const {
- return const_cast<Stmt*>(this)->children();
+ auto Children = const_cast<Stmt *>(this)->children();
+ return const_child_range(Children.begin(), Children.end());
}
- child_iterator child_begin() { return children().first; }
- child_iterator child_end() { return children().second; }
+ child_iterator child_begin() { return children().begin(); }
+ child_iterator child_end() { return children().end(); }
- const_child_iterator child_begin() const { return children().first; }
- const_child_iterator child_end() const { return children().second; }
+ const_child_iterator child_begin() const { return children().begin(); }
+ const_child_iterator child_end() const { return children().end(); }
/// \brief Produce a unique representation of the given statement.
///
@@ -544,7 +526,9 @@ public:
return T->getStmtClass() == NullStmtClass;
}
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
friend class ASTStmtReader;
friend class ASTStmtWriter;
@@ -574,7 +558,7 @@ public:
CompoundStmtBits.NumStmts = 0;
}
- void setStmts(const ASTContext &C, Stmt **Stmts, unsigned NumStmts);
+ void setStmts(const ASTContext &C, ArrayRef<Stmt *> Stmts);
bool body_empty() const { return CompoundStmtBits.NumStmts == 0; }
unsigned size() const { return CompoundStmtBits.NumStmts; }
@@ -643,7 +627,8 @@ public:
}
const_child_range children() const {
- return child_range(Body, Body + CompoundStmtBits.NumStmts);
+ return const_child_range(child_iterator(Body),
+ child_iterator(Body + CompoundStmtBits.NumStmts));
}
};
@@ -840,18 +825,20 @@ class AttributedStmt : public Stmt {
AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
: Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
NumAttrs(Attrs.size()) {
- memcpy(getAttrArrayPtr(), Attrs.data(), Attrs.size() * sizeof(Attr *));
+ std::copy(Attrs.begin(), Attrs.end(), getAttrArrayPtr());
}
explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
: Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
- memset(getAttrArrayPtr(), 0, NumAttrs * sizeof(Attr *));
+ std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr);
}
- Attr *const *getAttrArrayPtr() const {
- return reinterpret_cast<Attr *const *>(this + 1);
+ const Attr *const *getAttrArrayPtr() const {
+ return reinterpret_cast<const Attr *const *>(this + 1);
+ }
+ const Attr **getAttrArrayPtr() {
+ return reinterpret_cast<const Attr **>(this + 1);
}
- Attr **getAttrArrayPtr() { return reinterpret_cast<Attr **>(this + 1); }
public:
static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
@@ -1239,7 +1226,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// IndirectGotoStmt - This represents an indirect goto.
@@ -1307,7 +1296,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// BreakStmt - This represents a break.
@@ -1335,7 +1326,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
@@ -1390,7 +1383,7 @@ public:
// Iterators
child_range children() {
if (RetExpr) return child_range(&RetExpr, &RetExpr+1);
- return child_range();
+ return child_range(child_iterator(), child_iterator());
}
};
@@ -1974,7 +1967,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This captures a statement into a function. For example, the following
@@ -1993,6 +1988,7 @@ public:
enum VariableCaptureKind {
VCK_This,
VCK_ByRef,
+ VCK_ByCopy,
VCK_VLAType,
};
@@ -2012,24 +2008,10 @@ public:
/// \param Var The variable being captured, or null if capturing this.
///
Capture(SourceLocation Loc, VariableCaptureKind Kind,
- VarDecl *Var = nullptr)
- : VarAndKind(Var, Kind), Loc(Loc) {
- switch (Kind) {
- case VCK_This:
- assert(!Var && "'this' capture cannot have a variable!");
- break;
- case VCK_ByRef:
- assert(Var && "capturing by reference must have a variable!");
- break;
- case VCK_VLAType:
- assert(!Var &&
- "Variable-length array type capture cannot have a variable!");
- break;
- }
- }
+ VarDecl *Var = nullptr);
/// \brief Determine the kind of capture.
- VariableCaptureKind getCaptureKind() const { return VarAndKind.getInt(); }
+ VariableCaptureKind getCaptureKind() const;
/// \brief Retrieve the source location at which the variable or 'this' was
/// first used.
@@ -2038,9 +2020,14 @@ public:
/// \brief Determine whether this capture handles the C++ 'this' pointer.
bool capturesThis() const { return getCaptureKind() == VCK_This; }
- /// \brief Determine whether this capture handles a variable.
+ /// \brief Determine whether this capture handles a variable (by reference).
bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; }
+ /// \brief Determine whether this capture handles a variable by copy.
+ bool capturesVariableByCopy() const {
+ return getCaptureKind() == VCK_ByCopy;
+ }
+
/// \brief Determine whether this capture handles a variable-length array
/// type.
bool capturesVariableArrayType() const {
@@ -2050,11 +2037,8 @@ public:
/// \brief Retrieve the declaration of the variable being captured.
///
/// This operation is only valid if this capture captures a variable.
- VarDecl *getCapturedVar() const {
- assert(capturesVariable() &&
- "No variable available for 'this' or VAT capture");
- return VarAndKind.getPointer();
- }
+ VarDecl *getCapturedVar() const;
+
friend class ASTStmtReader;
};
@@ -2076,8 +2060,10 @@ private:
/// \brief Construct an empty captured statement.
CapturedStmt(EmptyShell Empty, unsigned NumCaptures);
- Stmt **getStoredStmts() const {
- return reinterpret_cast<Stmt **>(const_cast<CapturedStmt *>(this) + 1);
+ Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); }
+
+ Stmt *const *getStoredStmts() const {
+ return reinterpret_cast<Stmt *const *>(this + 1);
}
Capture *getStoredCaptures() const;
@@ -2096,31 +2082,20 @@ public:
/// \brief Retrieve the statement being captured.
Stmt *getCapturedStmt() { return getStoredStmts()[NumCaptures]; }
- const Stmt *getCapturedStmt() const {
- return const_cast<CapturedStmt *>(this)->getCapturedStmt();
- }
+ const Stmt *getCapturedStmt() const { return getStoredStmts()[NumCaptures]; }
/// \brief Retrieve the outlined function declaration.
- CapturedDecl *getCapturedDecl() { return CapDeclAndKind.getPointer(); }
- const CapturedDecl *getCapturedDecl() const {
- return const_cast<CapturedStmt *>(this)->getCapturedDecl();
- }
+ CapturedDecl *getCapturedDecl();
+ const CapturedDecl *getCapturedDecl() const;
/// \brief Set the outlined function declaration.
- void setCapturedDecl(CapturedDecl *D) {
- assert(D && "null CapturedDecl");
- CapDeclAndKind.setPointer(D);
- }
+ void setCapturedDecl(CapturedDecl *D);
/// \brief Retrieve the captured region kind.
- CapturedRegionKind getCapturedRegionKind() const {
- return CapDeclAndKind.getInt();
- }
+ CapturedRegionKind getCapturedRegionKind() const;
/// \brief Set the captured region kind.
- void setCapturedRegionKind(CapturedRegionKind Kind) {
- CapDeclAndKind.setInt(Kind);
- }
+ void setCapturedRegionKind(CapturedRegionKind Kind);
/// \brief Retrieve the record declaration for captured variables.
const RecordDecl *getCapturedRecordDecl() const { return TheRecordDecl; }
@@ -2164,18 +2139,36 @@ public:
typedef Expr **capture_init_iterator;
typedef llvm::iterator_range<capture_init_iterator> capture_init_range;
- capture_init_range capture_inits() const {
+ /// \brief Const iterator that walks over the capture initialization
+ /// arguments.
+ typedef Expr *const *const_capture_init_iterator;
+ typedef llvm::iterator_range<const_capture_init_iterator>
+ const_capture_init_range;
+
+ capture_init_range capture_inits() {
return capture_init_range(capture_init_begin(), capture_init_end());
}
+ const_capture_init_range capture_inits() const {
+ return const_capture_init_range(capture_init_begin(), capture_init_end());
+ }
+
/// \brief Retrieve the first initialization argument.
- capture_init_iterator capture_init_begin() const {
+ capture_init_iterator capture_init_begin() {
return reinterpret_cast<Expr **>(getStoredStmts());
}
+ const_capture_init_iterator capture_init_begin() const {
+ return reinterpret_cast<Expr *const *>(getStoredStmts());
+ }
+
/// \brief Retrieve the iterator pointing one past the last initialization
/// argument.
- capture_init_iterator capture_init_end() const {
+ capture_init_iterator capture_init_end() {
+ return capture_init_begin() + NumCaptures;
+ }
+
+ const_capture_init_iterator capture_init_end() const {
return capture_init_begin() + NumCaptures;
}
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h
index 567a772..1ca73e2 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h
@@ -131,12 +131,16 @@ class CXXForRangeStmt : public Stmt {
// SubExprs[RANGE] is an expression or declstmt.
// SubExprs[COND] and SubExprs[INC] are expressions.
Stmt *SubExprs[END];
+ SourceLocation CoawaitLoc;
SourceLocation ColonLoc;
SourceLocation RParenLoc;
+
+ friend class ASTStmtReader;
public:
CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd,
Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body,
- SourceLocation FL, SourceLocation CL, SourceLocation RPL);
+ SourceLocation FL, SourceLocation CAL, SourceLocation CL,
+ SourceLocation RPL);
CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { }
@@ -181,13 +185,10 @@ public:
void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; }
void setBody(Stmt *S) { SubExprs[BODY] = S; }
-
SourceLocation getForLoc() const { return ForLoc; }
- void setForLoc(SourceLocation Loc) { ForLoc = Loc; }
+ SourceLocation getCoawaitLoc() const { return CoawaitLoc; }
SourceLocation getColonLoc() const { return ColonLoc; }
- void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
- void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
@@ -287,6 +288,130 @@ public:
}
};
+/// \brief Represents the body of a coroutine. This wraps the normal function
+/// body and holds the additional semantic context required to set up and tear
+/// down the coroutine frame.
+class CoroutineBodyStmt : public Stmt {
+ enum SubStmt {
+ Body, ///< The body of the coroutine.
+ Promise, ///< The promise statement.
+ InitSuspend, ///< The initial suspend statement, run before the body.
+ FinalSuspend, ///< The final suspend statement, run after the body.
+ OnException, ///< Handler for exceptions thrown in the body.
+ OnFallthrough, ///< Handler for control flow falling off the body.
+ ReturnValue, ///< Return value for thunk function.
+ FirstParamMove ///< First offset for move construction of parameter copies.
+ };
+ Stmt *SubStmts[SubStmt::FirstParamMove];
+
+ friend class ASTStmtReader;
+public:
+ CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend,
+ Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough,
+ Expr *ReturnValue, ArrayRef<Expr *> ParamMoves)
+ : Stmt(CoroutineBodyStmtClass) {
+ SubStmts[CoroutineBodyStmt::Body] = Body;
+ SubStmts[CoroutineBodyStmt::Promise] = Promise;
+ SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend;
+ SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend;
+ SubStmts[CoroutineBodyStmt::OnException] = OnException;
+ SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough;
+ SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue;
+ // FIXME: Tail-allocate space for parameter move expressions and store them.
+ assert(ParamMoves.empty() && "not implemented yet");
+ }
+
+ /// \brief Retrieve the body of the coroutine as written. This will be either
+ /// a CompoundStmt or a TryStmt.
+ Stmt *getBody() const {
+ return SubStmts[SubStmt::Body];
+ }
+
+ Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; }
+ VarDecl *getPromiseDecl() const {
+ return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl());
+ }
+
+ Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; }
+ Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; }
+
+ Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; }
+ Stmt *getFallthroughHandler() const {
+ return SubStmts[SubStmt::OnFallthrough];
+ }
+
+ Expr *getReturnValueInit() const {
+ return cast<Expr>(SubStmts[SubStmt::ReturnValue]);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBody()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getBody()->getLocEnd();
+ }
+
+ child_range children() {
+ return child_range(SubStmts, SubStmts + SubStmt::FirstParamMove);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoroutineBodyStmtClass;
+ }
+};
+
+/// \brief Represents a 'co_return' statement in the C++ Coroutines TS.
+///
+/// This statament models the initialization of the coroutine promise
+/// (encapsulating the eventual notional return value) from an expression
+/// (or braced-init-list), followed by termination of the coroutine.
+///
+/// This initialization is modeled by the evaluation of the operand
+/// followed by a call to one of:
+/// <promise>.return_value(<operand>)
+/// <promise>.return_void()
+/// which we name the "promise call".
+class CoreturnStmt : public Stmt {
+ SourceLocation CoreturnLoc;
+
+ enum SubStmt { Operand, PromiseCall, Count };
+ Stmt *SubStmts[SubStmt::Count];
+
+ friend class ASTStmtReader;
+public:
+ CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall)
+ : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) {
+ SubStmts[SubStmt::Operand] = Operand;
+ SubStmts[SubStmt::PromiseCall] = PromiseCall;
+ }
+
+ SourceLocation getKeywordLoc() const { return CoreturnLoc; }
+
+ /// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr
+ /// if none was specified.
+ Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); }
+
+ /// \brief Retrieve the promise call that results from this 'co_return'
+ /// statement. Will be nullptr if either the coroutine has not yet been
+ /// finalized or the coroutine has no eventual return type.
+ Expr *getPromiseCall() const {
+ return static_cast<Expr*>(SubStmts[PromiseCall]);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getOperand()->getLocEnd();
+ }
+
+ child_range children() {
+ return child_range(SubStmts, SubStmts + SubStmt::Count);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoreturnStmtClass;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
index a5a57af..81f8ad43 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
@@ -139,86 +139,6 @@ struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
};
-/// A range of statement iterators.
-///
-/// This class provides some extra functionality beyond std::pair
-/// in order to allow the following idiom:
-/// for (StmtRange range = stmt->children(); range; ++range)
-struct StmtRange : std::pair<StmtIterator,StmtIterator> {
- StmtRange() {}
- StmtRange(const StmtIterator &begin, const StmtIterator &end)
- : std::pair<StmtIterator,StmtIterator>(begin, end) {}
-
- bool empty() const { return first == second; }
- explicit operator bool() const { return !empty(); }
-
- Stmt *operator->() const { return first.operator->(); }
- Stmt *&operator*() const { return first.operator*(); }
-
- StmtRange &operator++() {
- assert(!empty() && "incrementing on empty range");
- ++first;
- return *this;
- }
-
- StmtRange operator++(int) {
- assert(!empty() && "incrementing on empty range");
- StmtRange copy = *this;
- ++first;
- return copy;
- }
-
- friend const StmtIterator &begin(const StmtRange &range) {
- return range.first;
- }
- friend const StmtIterator &end(const StmtRange &range) {
- return range.second;
- }
-};
-
-/// A range of const statement iterators.
-///
-/// This class provides some extra functionality beyond std::pair
-/// in order to allow the following idiom:
-/// for (ConstStmtRange range = stmt->children(); range; ++range)
-struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
- ConstStmtRange() {}
- ConstStmtRange(const ConstStmtIterator &begin,
- const ConstStmtIterator &end)
- : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
- ConstStmtRange(const StmtRange &range)
- : std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second)
- {}
- ConstStmtRange(const StmtIterator &begin, const StmtIterator &end)
- : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
-
- bool empty() const { return first == second; }
- explicit operator bool() const { return !empty(); }
-
- const Stmt *operator->() const { return first.operator->(); }
- const Stmt *operator*() const { return first.operator*(); }
-
- ConstStmtRange &operator++() {
- assert(!empty() && "incrementing on empty range");
- ++first;
- return *this;
- }
-
- ConstStmtRange operator++(int) {
- assert(!empty() && "incrementing on empty range");
- ConstStmtRange copy = *this;
- ++first;
- return copy;
- }
-
- friend const ConstStmtIterator &begin(const ConstStmtRange &range) {
- return range.first;
- }
- friend const ConstStmtIterator &end(const ConstStmtRange &range) {
- return range.second;
- }
-};
-
} // end namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h
index 708b866..1ba859c 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h
@@ -92,65 +92,78 @@ public:
/// \brief Iterates over a filtered subrange of clauses applied to a
/// directive.
///
- /// This iterator visits only those declarations that meet some run-time
- /// criteria.
- template <class FilterPredicate> class filtered_clause_iterator {
- protected:
- ArrayRef<OMPClause *>::const_iterator Current;
+ /// This iterator visits only clauses of type SpecificClause.
+ template <typename SpecificClause>
+ class specific_clause_iterator
+ : public llvm::iterator_adaptor_base<
+ specific_clause_iterator<SpecificClause>,
+ ArrayRef<OMPClause *>::const_iterator, std::forward_iterator_tag,
+ const SpecificClause *, ptrdiff_t, const SpecificClause *,
+ const SpecificClause *> {
ArrayRef<OMPClause *>::const_iterator End;
- FilterPredicate Pred;
+
void SkipToNextClause() {
- while (Current != End && !Pred(*Current))
- ++Current;
+ while (this->I != End && !isa<SpecificClause>(*this->I))
+ ++this->I;
}
public:
- typedef const OMPClause *value_type;
- filtered_clause_iterator() : Current(), End() {}
- filtered_clause_iterator(ArrayRef<OMPClause *> Arr, FilterPredicate Pred)
- : Current(Arr.begin()), End(Arr.end()), Pred(std::move(Pred)) {
+ explicit specific_clause_iterator(ArrayRef<OMPClause *> Clauses)
+ : specific_clause_iterator::iterator_adaptor_base(Clauses.begin()),
+ End(Clauses.end()) {
SkipToNextClause();
}
- value_type operator*() const { return *Current; }
- value_type operator->() const { return *Current; }
- filtered_clause_iterator &operator++() {
- ++Current;
- SkipToNextClause();
- return *this;
- }
- filtered_clause_iterator operator++(int) {
- filtered_clause_iterator tmp(*this);
- ++(*this);
- return tmp;
+ const SpecificClause *operator*() const {
+ return cast<SpecificClause>(*this->I);
}
+ const SpecificClause *operator->() const { return **this; }
- bool operator!() { return Current == End; }
- explicit operator bool() { return Current != End; }
- bool empty() const { return Current == End; }
+ specific_clause_iterator &operator++() {
+ ++this->I;
+ SkipToNextClause();
+ return *this;
+ }
};
- template <typename Fn>
- filtered_clause_iterator<Fn> getFilteredClauses(Fn &&fn) const {
- return filtered_clause_iterator<Fn>(clauses(), std::move(fn));
+ template <typename SpecificClause>
+ static llvm::iterator_range<specific_clause_iterator<SpecificClause>>
+ getClausesOfKind(ArrayRef<OMPClause *> Clauses) {
+ return {specific_clause_iterator<SpecificClause>(Clauses),
+ specific_clause_iterator<SpecificClause>(
+ llvm::makeArrayRef(Clauses.end(), 0))};
}
- struct ClauseKindFilter {
- OpenMPClauseKind Kind;
- bool operator()(const OMPClause *clause) const {
- return clause->getClauseKind() == Kind;
- }
- };
- filtered_clause_iterator<ClauseKindFilter>
- getClausesOfKind(OpenMPClauseKind Kind) const {
- return getFilteredClauses(ClauseKindFilter{Kind});
+
+ template <typename SpecificClause>
+ llvm::iterator_range<specific_clause_iterator<SpecificClause>>
+ getClausesOfKind() const {
+ return getClausesOfKind<SpecificClause>(clauses());
}
- /// \brief Gets a single clause of the specified kind \a K associated with the
+ /// Gets a single clause of the specified kind associated with the
/// current directive iff there is only one clause of this kind (and assertion
/// is fired if there is more than one clause is associated with the
- /// directive). Returns nullptr if no clause of kind \a K is associated with
+ /// directive). Returns nullptr if no clause of this kind is associated with
/// the directive.
- const OMPClause *getSingleClause(OpenMPClauseKind K) const;
+ template <typename SpecificClause>
+ const SpecificClause *getSingleClause() const {
+ auto Clauses = getClausesOfKind<SpecificClause>();
+
+ if (Clauses.begin() != Clauses.end()) {
+ assert(std::next(Clauses.begin()) == Clauses.end() &&
+ "There are at least 2 clauses of the specified kind");
+ return *Clauses.begin();
+ }
+ return nullptr;
+ }
+
+ /// Returns true if the current directive has one or more clauses of a
+ /// specific kind.
+ template <typename SpecificClause>
+ bool hasClausesOfKind() const {
+ auto Clauses = getClausesOfKind<SpecificClause>();
+ return Clauses.begin() != Clauses.end();
+ }
/// \brief Returns starting location of directive kind.
SourceLocation getLocStart() const { return StartLoc; }
@@ -195,7 +208,7 @@ public:
child_range children() {
if (!hasAssociatedStmt())
- return child_range();
+ return child_range(child_iterator(), child_iterator());
Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end());
return child_range(ChildStorage, ChildStorage + NumChildren);
}
@@ -217,6 +230,10 @@ public:
/// variables 'c' and 'd'.
///
class OMPParallelDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief true if the construct has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive (directive keyword).
@@ -225,7 +242,8 @@ class OMPParallelDirective : public OMPExecutableDirective {
OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
- StartLoc, EndLoc, NumClauses, 1) {}
+ StartLoc, EndLoc, NumClauses, 1),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -234,7 +252,11 @@ class OMPParallelDirective : public OMPExecutableDirective {
explicit OMPParallelDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
SourceLocation(), SourceLocation(), NumClauses,
- 1) {}
+ 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -244,10 +266,11 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement associated with the directive.
+ /// \param HasCancel true if this directive has inner cancel directive.
///
static OMPParallelDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
/// \brief Creates an empty directive with the place for \a N clauses.
///
@@ -257,6 +280,9 @@ public:
static OMPParallelDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelDirectiveClass;
}
@@ -311,11 +337,18 @@ class OMPLoopDirective : public OMPExecutableDirective {
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
+ /// \brief Get the private counters storage.
+ MutableArrayRef<Expr *> getPrivateCounters() {
+ Expr **Storage = reinterpret_cast<Expr **>(&*std::next(
+ child_begin(), getArraysOffset(getDirectiveKind()) + CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
/// \brief Get the updates storage.
MutableArrayRef<Expr *> getInits() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
- getArraysOffset(getDirectiveKind()) + CollapsedNum));
+ getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum));
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
@@ -323,7 +356,7 @@ class OMPLoopDirective : public OMPExecutableDirective {
MutableArrayRef<Expr *> getUpdates() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
- getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum));
+ getArraysOffset(getDirectiveKind()) + 3 * CollapsedNum));
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
@@ -331,7 +364,7 @@ class OMPLoopDirective : public OMPExecutableDirective {
MutableArrayRef<Expr *> getFinals() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
- getArraysOffset(getDirectiveKind()) + 3 * CollapsedNum));
+ getArraysOffset(getDirectiveKind()) + 4 * CollapsedNum));
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
@@ -358,15 +391,19 @@ protected:
/// \brief Offset to the start of children expression arrays.
static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
- return isOpenMPWorksharingDirective(Kind) ? WorksharingEnd
- : DefaultEnd;
+ return (isOpenMPWorksharingDirective(Kind) ||
+ isOpenMPTaskLoopDirective(Kind) ||
+ isOpenMPDistributeDirective(Kind))
+ ? WorksharingEnd
+ : DefaultEnd;
}
/// \brief Children number.
static unsigned numLoopChildren(unsigned CollapsedNum,
OpenMPDirectiveKind Kind) {
- return getArraysOffset(Kind) +
- 4 * CollapsedNum; // Counters, Inits, Updates and Finals
+ return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters,
+ // PrivateCounters, Inits,
+ // Updates and Finals
}
void setIterationVariable(Expr *IV) {
@@ -387,41 +424,56 @@ protected:
void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; }
void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; }
void setIsLastIterVariable(Expr *IL) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), IsLastIterVariableOffset) = IL;
}
void setLowerBoundVariable(Expr *LB) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), LowerBoundVariableOffset) = LB;
}
void setUpperBoundVariable(Expr *UB) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), UpperBoundVariableOffset) = UB;
}
void setStrideVariable(Expr *ST) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), StrideVariableOffset) = ST;
}
void setEnsureUpperBound(Expr *EUB) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), EnsureUpperBoundOffset) = EUB;
}
void setNextLowerBound(Expr *NLB) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), NextLowerBoundOffset) = NLB;
}
void setNextUpperBound(Expr *NUB) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), NextUpperBoundOffset) = NUB;
}
void setCounters(ArrayRef<Expr *> A);
+ void setPrivateCounters(ArrayRef<Expr *> A);
void setInits(ArrayRef<Expr *> A);
void setUpdates(ArrayRef<Expr *> A);
void setFinals(ArrayRef<Expr *> A);
@@ -462,6 +514,8 @@ public:
Expr *NUB;
/// \brief Counters Loop counters.
SmallVector<Expr *, 4> Counters;
+ /// \brief PrivateCounters Loop counters.
+ SmallVector<Expr *, 4> PrivateCounters;
/// \brief Expressions for loop counters inits for CodeGen.
SmallVector<Expr *, 4> Inits;
/// \brief Expressions for loop counters update for CodeGen.
@@ -495,11 +549,13 @@ public:
NLB = nullptr;
NUB = nullptr;
Counters.resize(Size);
+ PrivateCounters.resize(Size);
Inits.resize(Size);
Updates.resize(Size);
Finals.resize(Size);
for (unsigned i = 0; i < Size; ++i) {
Counters[i] = nullptr;
+ PrivateCounters[i] = nullptr;
Inits[i] = nullptr;
Updates[i] = nullptr;
Finals[i] = nullptr;
@@ -539,43 +595,50 @@ public:
reinterpret_cast<const Expr *>(*std::next(child_begin(), IncOffset)));
}
Expr *getIsLastIterVariable() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), IsLastIterVariableOffset)));
}
Expr *getLowerBoundVariable() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), LowerBoundVariableOffset)));
}
Expr *getUpperBoundVariable() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), UpperBoundVariableOffset)));
}
Expr *getStrideVariable() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), StrideVariableOffset)));
}
Expr *getEnsureUpperBound() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), EnsureUpperBoundOffset)));
}
Expr *getNextLowerBound() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), NextLowerBoundOffset)));
}
Expr *getNextUpperBound() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), NextUpperBoundOffset)));
@@ -597,6 +660,12 @@ public:
return const_cast<OMPLoopDirective *>(this)->getCounters();
}
+ ArrayRef<Expr *> private_counters() { return getPrivateCounters(); }
+
+ ArrayRef<Expr *> private_counters() const {
+ return const_cast<OMPLoopDirective *>(this)->getPrivateCounters();
+ }
+
ArrayRef<Expr *> inits() { return getInits(); }
ArrayRef<Expr *> inits() const {
@@ -620,7 +689,10 @@ public:
T->getStmtClass() == OMPForDirectiveClass ||
T->getStmtClass() == OMPForSimdDirectiveClass ||
T->getStmtClass() == OMPParallelForDirectiveClass ||
- T->getStmtClass() == OMPParallelForSimdDirectiveClass;
+ T->getStmtClass() == OMPParallelForSimdDirectiveClass ||
+ T->getStmtClass() == OMPTaskLoopDirectiveClass ||
+ T->getStmtClass() == OMPTaskLoopSimdDirectiveClass ||
+ T->getStmtClass() == OMPDistributeDirectiveClass;
}
};
@@ -700,6 +772,10 @@ public:
///
class OMPForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -710,7 +786,8 @@ class OMPForDirective : public OMPLoopDirective {
OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, EndLoc,
- CollapsedNum, NumClauses) {}
+ CollapsedNum, NumClauses),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -719,7 +796,11 @@ class OMPForDirective : public OMPLoopDirective {
///
explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, SourceLocation(),
- SourceLocation(), CollapsedNum, NumClauses) {}
+ SourceLocation(), CollapsedNum, NumClauses),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -731,12 +812,13 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
+ /// \param HasCancel true if current directive has inner cancel directive.
///
static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt,
- const HelperExprs &Exprs);
+ Stmt *AssociatedStmt, const HelperExprs &Exprs,
+ bool HasCancel);
/// \brief Creates an empty directive with the place
/// for \a NumClauses clauses.
@@ -748,6 +830,9 @@ public:
static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPForDirectiveClass;
}
@@ -829,6 +914,10 @@ public:
///
class OMPSectionsDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -838,7 +927,8 @@ class OMPSectionsDirective : public OMPExecutableDirective {
OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections,
- StartLoc, EndLoc, NumClauses, 1) {}
+ StartLoc, EndLoc, NumClauses, 1),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -847,7 +937,11 @@ class OMPSectionsDirective : public OMPExecutableDirective {
explicit OMPSectionsDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections,
SourceLocation(), SourceLocation(), NumClauses,
- 1) {}
+ 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -857,10 +951,11 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true if current directive has inner directive.
///
static OMPSectionsDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
/// \brief Creates an empty directive with the place for \a NumClauses
/// clauses.
@@ -871,6 +966,9 @@ public:
static OMPSectionsDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPSectionsDirectiveClass;
}
@@ -884,6 +982,10 @@ public:
///
class OMPSectionDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -891,13 +993,15 @@ class OMPSectionDirective : public OMPExecutableDirective {
///
OMPSectionDirective(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section,
- StartLoc, EndLoc, 0, 1) {}
+ StartLoc, EndLoc, 0, 1),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
explicit OMPSectionDirective()
: OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section,
- SourceLocation(), SourceLocation(), 0, 1) {}
+ SourceLocation(), SourceLocation(), 0, 1),
+ HasCancel(false) {}
public:
/// \brief Creates directive.
@@ -906,11 +1010,12 @@ public:
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true if current directive has inner directive.
///
static OMPSectionDirective *Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
- Stmt *AssociatedStmt);
+ Stmt *AssociatedStmt, bool HasCancel);
/// \brief Creates an empty directive.
///
@@ -918,6 +1023,12 @@ public:
///
static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
+
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPSectionDirectiveClass;
}
@@ -1042,18 +1153,22 @@ class OMPCriticalDirective : public OMPExecutableDirective {
/// \param Name Name of the directive.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
///
OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc,
- SourceLocation EndLoc)
+ SourceLocation EndLoc, unsigned NumClauses)
: OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical,
- StartLoc, EndLoc, 0, 1),
+ StartLoc, EndLoc, NumClauses, 1),
DirName(Name) {}
/// \brief Build an empty directive.
///
- explicit OMPCriticalDirective()
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPCriticalDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical,
- SourceLocation(), SourceLocation(), 0, 1),
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1),
DirName() {}
/// \brief Set name of the directive.
@@ -1069,17 +1184,21 @@ public:
/// \param Name Name of the directive.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
///
static OMPCriticalDirective *
Create(const ASTContext &C, const DeclarationNameInfo &Name,
- SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt);
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
/// \brief Creates an empty directive.
///
/// \param C AST context.
+ /// \param NumClauses Number of clauses.
///
- static OMPCriticalDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+ static OMPCriticalDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
/// \brief Return name of the directive.
///
@@ -1101,6 +1220,10 @@ public:
///
class OMPParallelForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
+
+ /// \brief true if current region has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -1111,7 +1234,8 @@ class OMPParallelForDirective : public OMPLoopDirective {
OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for,
- StartLoc, EndLoc, CollapsedNum, NumClauses) {}
+ StartLoc, EndLoc, CollapsedNum, NumClauses),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -1121,7 +1245,11 @@ class OMPParallelForDirective : public OMPLoopDirective {
explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for,
SourceLocation(), SourceLocation(), CollapsedNum,
- NumClauses) {}
+ NumClauses),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -1133,11 +1261,12 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
+ /// \param HasCancel true if current directive has inner cancel directive.
///
static OMPParallelForDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt, const HelperExprs &Exprs);
+ Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
/// \brief Creates an empty directive with the place
/// for \a NumClauses clauses.
@@ -1151,6 +1280,9 @@ public:
unsigned CollapsedNum,
EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelForDirectiveClass;
}
@@ -1236,6 +1368,10 @@ public:
///
class OMPParallelSectionsDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -1246,7 +1382,8 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective {
unsigned NumClauses)
: OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass,
OMPD_parallel_sections, StartLoc, EndLoc,
- NumClauses, 1) {}
+ NumClauses, 1),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -1255,7 +1392,11 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective {
explicit OMPParallelSectionsDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass,
OMPD_parallel_sections, SourceLocation(),
- SourceLocation(), NumClauses, 1) {}
+ SourceLocation(), NumClauses, 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -1265,10 +1406,11 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true if current directive has inner cancel directive.
///
static OMPParallelSectionsDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
/// \brief Creates an empty directive with the place for \a NumClauses
/// clauses.
@@ -1279,6 +1421,9 @@ public:
static OMPParallelSectionsDirective *
CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelSectionsDirectiveClass;
}
@@ -1294,6 +1439,9 @@ public:
///
class OMPTaskDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
+ /// \brief true if this directive has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -1303,7 +1451,8 @@ class OMPTaskDirective : public OMPExecutableDirective {
OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, StartLoc,
- EndLoc, NumClauses, 1) {}
+ EndLoc, NumClauses, 1),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -1312,7 +1461,11 @@ class OMPTaskDirective : public OMPExecutableDirective {
explicit OMPTaskDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task,
SourceLocation(), SourceLocation(), NumClauses,
- 1) {}
+ 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -1322,11 +1475,12 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true, if current directive has inner cancel directive.
///
static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt);
+ Stmt *AssociatedStmt, bool HasCancel);
/// \brief Creates an empty directive with the place for \a NumClauses
/// clauses.
@@ -1337,6 +1491,9 @@ public:
static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTaskDirectiveClass;
}
@@ -1592,16 +1749,21 @@ class OMPOrderedDirective : public OMPExecutableDirective {
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
///
- OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
: OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered,
- StartLoc, EndLoc, 0, 1) {}
+ StartLoc, EndLoc, NumClauses, 1) {}
/// \brief Build an empty directive.
///
- explicit OMPOrderedDirective()
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPOrderedDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered,
- SourceLocation(), SourceLocation(), 0, 1) {}
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
public:
/// \brief Creates directive.
@@ -1609,18 +1771,20 @@ public:
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
///
- static OMPOrderedDirective *Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- Stmt *AssociatedStmt);
+ static OMPOrderedDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
/// \brief Creates an empty directive.
///
/// \param C AST context.
+ /// \param NumClauses Number of clauses.
///
- static OMPOrderedDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+ static OMPOrderedDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPOrderedDirectiveClass;
@@ -1817,6 +1981,64 @@ public:
}
};
+/// \brief This represents '#pragma omp target data' directive.
+///
+/// \code
+/// #pragma omp target data device(0) if(a) map(b[:])
+/// \endcode
+/// In this example directive '#pragma omp target data' has clauses 'device'
+/// with the value '0', 'if' with condition 'a' and 'map' with array
+/// section 'b[:]'.
+///
+class OMPTargetDataDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param NumClauses The number of clauses.
+ ///
+ OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
+ OMPD_target_data, StartLoc, EndLoc, NumClauses,
+ 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTargetDataDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
+ OMPD_target_data, SourceLocation(),
+ SourceLocation(), NumClauses, 1) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPTargetDataDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive with the place for \a N clauses.
+ ///
+ /// \param C AST context.
+ /// \param N The number of clauses.
+ ///
+ static OMPTargetDataDirective *CreateEmpty(const ASTContext &C, unsigned N,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTargetDataDirectiveClass;
+ }
+};
+
/// \brief This represents '#pragma omp teams' directive.
///
/// \code
@@ -1947,17 +2169,21 @@ class OMPCancelDirective : public OMPExecutableDirective {
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
///
- OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
: OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel,
- StartLoc, EndLoc, 0, 0),
+ StartLoc, EndLoc, NumClauses, 0),
CancelRegion(OMPD_unknown) {}
/// \brief Build an empty directive.
///
- explicit OMPCancelDirective()
+ /// \param NumClauses Number of clauses.
+ explicit OMPCancelDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel,
- SourceLocation(), SourceLocation(), 0, 0),
+ SourceLocation(), SourceLocation(), NumClauses,
+ 0),
CancelRegion(OMPD_unknown) {}
/// \brief Set cancel region for current cancellation point.
@@ -1970,17 +2196,19 @@ public:
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
///
- static OMPCancelDirective *Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- OpenMPDirectiveKind CancelRegion);
+ static OMPCancelDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, OpenMPDirectiveKind CancelRegion);
/// \brief Creates an empty directive.
///
/// \param C AST context.
+ /// \param NumClauses Number of clauses.
///
- static OMPCancelDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+ static OMPCancelDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
/// \brief Get cancellation region for the current cancellation point.
OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
@@ -1990,6 +2218,205 @@ public:
}
};
+/// \brief This represents '#pragma omp taskloop' directive.
+///
+/// \code
+/// #pragma omp taskloop private(a,b) grainsize(val) num_tasks(num)
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has clauses 'private'
+/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
+/// 'num_tasks' with expression 'num'.
+///
+class OMPTaskLoopDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop,
+ StartLoc, EndLoc, CollapsedNum, NumClauses) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTaskLoopDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTaskLoopDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTaskLoopDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskLoopDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp taskloop simd' directive.
+///
+/// \code
+/// #pragma omp taskloop simd private(a,b) grainsize(val) num_tasks(num)
+/// \endcode
+/// In this example directive '#pragma omp taskloop simd' has clauses 'private'
+/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
+/// 'num_tasks' with expression 'num'.
+///
+class OMPTaskLoopSimdDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass,
+ OMPD_taskloop_simd, StartLoc, EndLoc, CollapsedNum,
+ NumClauses) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTaskLoopSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass,
+ OMPD_taskloop_simd, SourceLocation(), SourceLocation(),
+ CollapsedNum, NumClauses) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTaskLoopSimdDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskLoopSimdDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp distribute' directive.
+///
+/// \code
+/// #pragma omp distribute private(a,b)
+/// \endcode
+/// In this example directive '#pragma omp distribute' has clauses 'private'
+/// with the variables 'a' and 'b'
+///
+class OMPDistributeDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPDistributeDirectiveClass, OMPD_distribute,
+ StartLoc, EndLoc, CollapsedNum, NumClauses)
+ {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPDistributeDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPDistributeDirectiveClass, OMPD_distribute,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses)
+ {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPDistributeDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPDistributeDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPDistributeDirectiveClass;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
index c71af38..df4a2d8 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
@@ -16,6 +16,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtOpenMP.h"
@@ -93,6 +94,7 @@ public:
case UO_Real: DISPATCH(UnaryReal, UnaryOperator);
case UO_Imag: DISPATCH(UnaryImag, UnaryOperator);
case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator);
+ case UO_Coawait: DISPATCH(UnaryCoawait, UnaryOperator);
}
}
@@ -157,7 +159,7 @@ public:
UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
- UNARYOP_FALLBACK(Extension)
+ UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(Coawait)
#undef UNARYOP_FALLBACK
// Base case, ignore it. :)
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
index 1d01753..f87171a 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
@@ -22,6 +22,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TrailingObjects.h"
namespace llvm {
class FoldingSetNodeID;
@@ -198,22 +199,19 @@ public:
///
/// We assume that storage for the template arguments provided
/// outlives the TemplateArgument itself.
- TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) {
+ explicit TemplateArgument(ArrayRef<TemplateArgument> Args) {
this->Args.Kind = Pack;
- this->Args.Args = Args;
- this->Args.NumArgs = NumArgs;
+ this->Args.Args = Args.data();
+ this->Args.NumArgs = Args.size();
}
- static TemplateArgument getEmptyPack() {
- return TemplateArgument((TemplateArgument*)nullptr, 0);
- }
+ static TemplateArgument getEmptyPack() { return TemplateArgument(None); }
/// \brief Create a new template argument pack by copying the given set of
/// template arguments.
static TemplateArgument CreatePackCopy(ASTContext &Context,
- const TemplateArgument *Args,
- unsigned NumArgs);
-
+ ArrayRef<TemplateArgument> Args);
+
/// \brief Return the kind of stored template argument.
ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
@@ -523,7 +521,7 @@ class TemplateArgumentListInfo {
// This can leak if used in an AST node, use ASTTemplateArgumentListInfo
// instead.
- void* operator new(size_t bytes, ASTContext& C);
+ void *operator new(size_t bytes, ASTContext &C) = delete;
public:
TemplateArgumentListInfo() {}
@@ -544,6 +542,10 @@ public:
return Arguments.data();
}
+ llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
+ return Arguments;
+ }
+
const TemplateArgumentLoc &operator[](unsigned I) const {
return Arguments[I];
}
@@ -561,84 +563,72 @@ public:
/// the "<int>" in "sort<int>".
/// This is safe to be used inside an AST node, in contrast with
/// TemplateArgumentListInfo.
-struct ASTTemplateArgumentListInfo {
+struct ASTTemplateArgumentListInfo final
+ : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
+ TemplateArgumentLoc> {
+private:
+ friend TrailingObjects;
+
+ ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
+
+public:
/// \brief The source location of the left angle bracket ('<').
SourceLocation LAngleLoc;
-
+
/// \brief The source location of the right angle bracket ('>').
SourceLocation RAngleLoc;
-
- union {
- /// \brief The number of template arguments in TemplateArgs.
- /// The actual template arguments (if any) are stored after the
- /// ExplicitTemplateArgumentList structure.
- unsigned NumTemplateArgs;
-
- /// Force ASTTemplateArgumentListInfo to the right alignment
- /// for the following array of TemplateArgumentLocs.
- llvm::AlignedCharArray<
- llvm::AlignOf<TemplateArgumentLoc>::Alignment, 1> Aligner;
- };
- /// \brief Retrieve the template arguments
- TemplateArgumentLoc *getTemplateArgs() {
- return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
- }
-
+ /// \brief The number of template arguments in TemplateArgs.
+ unsigned NumTemplateArgs;
+
/// \brief Retrieve the template arguments
const TemplateArgumentLoc *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
+ return getTrailingObjects<TemplateArgumentLoc>();
}
const TemplateArgumentLoc &operator[](unsigned I) const {
return getTemplateArgs()[I];
}
- static const ASTTemplateArgumentListInfo *Create(ASTContext &C,
- const TemplateArgumentListInfo &List);
-
- void initializeFrom(const TemplateArgumentListInfo &List);
- void initializeFrom(const TemplateArgumentListInfo &List,
- bool &Dependent, bool &InstantiationDependent,
- bool &ContainsUnexpandedParameterPack);
- void copyInto(TemplateArgumentListInfo &List) const;
- static std::size_t sizeFor(unsigned NumTemplateArgs);
+ static const ASTTemplateArgumentListInfo *
+ Create(ASTContext &C, const TemplateArgumentListInfo &List);
};
-/// \brief Extends ASTTemplateArgumentListInfo with the source location
-/// information for the template keyword; this is used as part of the
-/// representation of qualified identifiers, such as S<T>::template apply<T>.
-struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo {
- typedef ASTTemplateArgumentListInfo Base;
-
- // NOTE: the source location of the (optional) template keyword is
- // stored after all template arguments.
+/// \brief Represents an explicit template argument list in C++, e.g.,
+/// the "<int>" in "sort<int>".
+///
+/// It is intended to be used as a trailing object on AST nodes, and
+/// as such, doesn't contain the array of TemplateArgumentLoc itself,
+/// but expects the containing object to also provide storage for
+/// that.
+struct LLVM_ALIGNAS(LLVM_PTR_SIZE) ASTTemplateKWAndArgsInfo {
+ /// \brief The source location of the left angle bracket ('<').
+ SourceLocation LAngleLoc;
- /// \brief Get the source location of the template keyword.
- SourceLocation getTemplateKeywordLoc() const {
- return *reinterpret_cast<const SourceLocation*>
- (getTemplateArgs() + NumTemplateArgs);
- }
+ /// \brief The source location of the right angle bracket ('>').
+ SourceLocation RAngleLoc;
- /// \brief Sets the source location of the template keyword.
- void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) {
- *reinterpret_cast<SourceLocation*>
- (getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc;
- }
+ /// \brief The source location of the template keyword; this is used
+ /// as part of the representation of qualified identifiers, such as
+ /// S<T>::template apply<T>. Will be empty if this expression does
+ /// not have a template keyword.
+ SourceLocation TemplateKWLoc;
- static const ASTTemplateKWAndArgsInfo*
- Create(ASTContext &C, SourceLocation TemplateKWLoc,
- const TemplateArgumentListInfo &List);
+ /// \brief The number of template arguments in TemplateArgs.
+ unsigned NumTemplateArgs;
void initializeFrom(SourceLocation TemplateKWLoc,
- const TemplateArgumentListInfo &List);
+ const TemplateArgumentListInfo &List,
+ TemplateArgumentLoc *OutArgArray);
void initializeFrom(SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo &List,
- bool &Dependent, bool &InstantiationDependent,
+ TemplateArgumentLoc *OutArgArray, bool &Dependent,
+ bool &InstantiationDependent,
bool &ContainsUnexpandedParameterPack);
void initializeFrom(SourceLocation TemplateKWLoc);
- static std::size_t sizeFor(unsigned NumTemplateArgs);
+ void copyInto(const TemplateArgumentLoc *ArgArray,
+ TemplateArgumentListInfo &List) const;
};
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h
index f3d23b9..3e10d2f 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h
@@ -180,9 +180,7 @@ class TemplateName {
StorageType Storage;
- explicit TemplateName(void *Ptr) {
- Storage = StorageType::getFromOpaqueValue(Ptr);
- }
+ explicit TemplateName(void *Ptr);
public:
// \brief Kind of name that is actually stored.
@@ -207,17 +205,15 @@ public:
};
TemplateName() : Storage() { }
- explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
- explicit TemplateName(OverloadedTemplateStorage *Storage)
- : Storage(Storage) { }
+ explicit TemplateName(TemplateDecl *Template);
+ explicit TemplateName(OverloadedTemplateStorage *Storage);
explicit TemplateName(SubstTemplateTemplateParmStorage *Storage);
- explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
- : Storage(Storage) { }
- explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
- explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
+ explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage);
+ explicit TemplateName(QualifiedTemplateName *Qual);
+ explicit TemplateName(DependentTemplateName *Dep);
/// \brief Determine whether this template name is NULL.
- bool isNull() const { return Storage.isNull(); }
+ bool isNull() const;
// \brief Get the kind of name that is actually stored.
NameKind getKind() const;
@@ -238,26 +234,14 @@ public:
/// name refers to, if known. If the template name does not refer to a
/// specific set of function templates because it is a dependent name or
/// refers to a single template, returns NULL.
- OverloadedTemplateStorage *getAsOverloadedTemplate() const {
- if (UncommonTemplateNameStorage *Uncommon =
- Storage.dyn_cast<UncommonTemplateNameStorage *>())
- return Uncommon->getAsOverloadedStorage();
-
- return nullptr;
- }
+ OverloadedTemplateStorage *getAsOverloadedTemplate() const;
/// \brief Retrieve the substituted template template parameter, if
/// known.
///
/// \returns The storage for the substituted template template parameter,
/// if known. Otherwise, returns NULL.
- SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const {
- if (UncommonTemplateNameStorage *uncommon =
- Storage.dyn_cast<UncommonTemplateNameStorage *>())
- return uncommon->getAsSubstTemplateTemplateParm();
-
- return nullptr;
- }
+ SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const;
/// \brief Retrieve the substituted template template parameter pack, if
/// known.
@@ -265,25 +249,15 @@ public:
/// \returns The storage for the substituted template template parameter pack,
/// if known. Otherwise, returns NULL.
SubstTemplateTemplateParmPackStorage *
- getAsSubstTemplateTemplateParmPack() const {
- if (UncommonTemplateNameStorage *Uncommon =
- Storage.dyn_cast<UncommonTemplateNameStorage *>())
- return Uncommon->getAsSubstTemplateTemplateParmPack();
-
- return nullptr;
- }
+ getAsSubstTemplateTemplateParmPack() const;
/// \brief Retrieve the underlying qualified template name
/// structure, if any.
- QualifiedTemplateName *getAsQualifiedTemplateName() const {
- return Storage.dyn_cast<QualifiedTemplateName *>();
- }
+ QualifiedTemplateName *getAsQualifiedTemplateName() const;
/// \brief Retrieve the underlying dependent template name
/// structure, if any.
- DependentTemplateName *getAsDependentTemplateName() const {
- return Storage.dyn_cast<DependentTemplateName *>();
- }
+ DependentTemplateName *getAsDependentTemplateName() const;
TemplateName getUnderlying() const;
@@ -359,9 +333,6 @@ public:
TemplateName replacement);
};
-inline TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
- : Storage(Storage) { }
-
inline TemplateName TemplateName::getUnderlying() const {
if (SubstTemplateTemplateParmStorage *subst
= getAsSubstTemplateTemplateParm())
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Type.h b/contrib/llvm/tools/clang/include/clang/AST/Type.h
index 632d4b9..d63b2c4 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Type.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Type.h
@@ -6,9 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the Type interface and subclasses.
-//
+/// \file
+/// \brief C Language Family Type Representation
+///
+/// This file defines the clang::Type interface and subclasses, used to
+/// represent types for languages in the C family.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TYPE_H
@@ -105,7 +108,7 @@ namespace clang {
#define TYPE(Class, Base) class Class##Type;
#include "clang/AST/TypeNodes.def"
-/// Qualifiers - The collection of all-type qualifiers we support.
+/// The collection of all-type qualifiers we support.
/// Clang supports five independent qualifiers:
/// * C99: const, volatile, and restrict
/// * Embedded C (TR18037): address spaces
@@ -161,7 +164,7 @@ public:
Qualifiers() : Mask(0) {}
- /// \brief Returns the common set of qualifiers while removing them from
+ /// Returns the common set of qualifiers while removing them from
/// the given sets.
static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
// If both are only CVR-qualified, bit operations are sufficient.
@@ -342,8 +345,8 @@ public:
Mask |= mask;
}
- /// hasNonFastQualifiers - Return true if the set contains any
- /// qualifiers which require an ExtQuals node to be allocated.
+ /// Return true if the set contains any qualifiers which require an ExtQuals
+ /// node to be allocated.
bool hasNonFastQualifiers() const { return Mask & ~FastMask; }
Qualifiers getNonFastQualifiers() const {
Qualifiers Quals = *this;
@@ -351,11 +354,11 @@ public:
return Quals;
}
- /// hasQualifiers - Return true if the set contains any qualifiers.
+ /// Return true if the set contains any qualifiers.
bool hasQualifiers() const { return Mask; }
bool empty() const { return !Mask; }
- /// \brief Add the qualifiers from the given set to this set.
+ /// Add the qualifiers from the given set to this set.
void addQualifiers(Qualifiers Q) {
// If the other set doesn't have any non-boolean qualifiers, just
// bit-or it in.
@@ -389,7 +392,7 @@ public:
}
}
- /// \brief Add the qualifiers from the given set to this set, given that
+ /// Add the qualifiers from the given set to this set, given that
/// they don't conflict.
void addConsistentQualifiers(Qualifiers qs) {
assert(getAddressSpace() == qs.getAddressSpace() ||
@@ -401,7 +404,7 @@ public:
Mask |= qs.Mask;
}
- /// \brief Returns true if this address space is a superset of the other one.
+ /// Returns true if this address space is a superset of the other one.
/// OpenCL v2.0 defines conversion rules (OpenCLC v2.0 s6.5.5) and notion of
/// overlapping address spaces.
/// CL1.1 or CL1.2:
@@ -418,7 +421,7 @@ public:
other.getAddressSpace() != LangAS::opencl_constant);
}
- /// \brief Determines if these qualifiers compatibly include another set.
+ /// Determines if these qualifiers compatibly include another set.
/// Generally this answers the question of whether an object with the other
/// qualifiers can be safely used as an object with these qualifiers.
bool compatiblyIncludes(Qualifiers other) const {
@@ -438,7 +441,8 @@ public:
///
/// One set of Objective-C lifetime qualifiers compatibly includes the other
/// if the lifetime qualifiers match, or if both are non-__weak and the
- /// including set also contains the 'const' qualifier.
+ /// including set also contains the 'const' qualifier, or both are non-__weak
+ /// and one is None (which can only happen in non-ARC modes).
bool compatiblyIncludesObjCLifetime(Qualifiers other) const {
if (getObjCLifetime() == other.getObjCLifetime())
return true;
@@ -446,6 +450,9 @@ public:
if (getObjCLifetime() == OCL_Weak || other.getObjCLifetime() == OCL_Weak)
return false;
+ if (getObjCLifetime() == OCL_None || other.getObjCLifetime() == OCL_None)
+ return true;
+
return hasConst();
}
@@ -551,8 +558,10 @@ enum class ObjCSubstitutionContext {
Superclass,
};
-/// QualType - For efficiency, we don't store CV-qualified types as nodes on
-/// their own: instead each reference to a type stores the qualifiers. This
+/// A (possibly-)qualified type.
+///
+/// For efficiency, we don't store CV-qualified types as nodes on their
+/// own: instead each reference to a type stores the qualifiers. This
/// greatly reduces the number of nodes we need to allocate for types (for
/// example we only need one for 'int', 'const int', 'volatile int',
/// 'const volatile int', etc).
@@ -629,7 +638,7 @@ public:
bool isCanonical() const;
bool isCanonicalAsParam() const;
- /// isNull - Return true if this QualType doesn't point to a type yet.
+ /// Return true if this QualType doesn't point to a type yet.
bool isNull() const {
return Value.getPointer().isNull();
}
@@ -707,29 +716,25 @@ public:
/// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
bool isPODType(ASTContext &Context) const;
- /// isCXX98PODType() - Return true if this is a POD type according to the
- /// rules of the C++98 standard, regardless of the current compilation's
- /// language.
+ /// Return true if this is a POD type according to the rules of the C++98
+ /// standard, regardless of the current compilation's language.
bool isCXX98PODType(ASTContext &Context) const;
- /// isCXX11PODType() - Return true if this is a POD type according to the
- /// more relaxed rules of the C++11 standard, regardless of the current
- /// compilation's language.
+ /// Return true if this is a POD type according to the more relaxed rules
+ /// of the C++11 standard, regardless of the current compilation's language.
/// (C++0x [basic.types]p9)
bool isCXX11PODType(ASTContext &Context) const;
- /// isTrivialType - Return true if this is a trivial type
- /// (C++0x [basic.types]p9)
+ /// Return true if this is a trivial type per (C++0x [basic.types]p9)
bool isTrivialType(ASTContext &Context) const;
- /// isTriviallyCopyableType - Return true if this is a trivially
- /// copyable type (C++0x [basic.types]p9)
+ /// Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool isTriviallyCopyableType(ASTContext &Context) const;
// Don't promise in the API that anything besides 'const' can be
// easily added.
- /// addConst - add the specified type qualifier to this QualType.
+ /// Add the `const` type qualifier to this QualType.
void addConst() {
addFastQualifiers(Qualifiers::Const);
}
@@ -737,15 +742,15 @@ public:
return withFastQualifiers(Qualifiers::Const);
}
- /// addVolatile - add the specified type qualifier to this QualType.
+ /// Add the `volatile` type qualifier to this QualType.
void addVolatile() {
addFastQualifiers(Qualifiers::Volatile);
}
QualType withVolatile() const {
return withFastQualifiers(Qualifiers::Volatile);
}
-
- /// Add the restrict qualifier to this QualType.
+
+ /// Add the `restrict` qualifier to this QualType.
void addRestrict() {
addFastQualifiers(Qualifiers::Restrict);
}
@@ -822,8 +827,8 @@ public:
/// ASTContext::getUnqualifiedArrayType.
inline QualType getUnqualifiedType() const;
- /// getSplitUnqualifiedType - Retrieve the unqualified variant of the
- /// given type, removing as little sugar as possible.
+ /// Retrieve the unqualified variant of the given type, removing as little
+ /// sugar as possible.
///
/// Like getUnqualifiedType(), but also returns the set of
/// qualifiers that were built up.
@@ -853,7 +858,7 @@ public:
/// from non-class types (in C++) or all types (in C).
QualType getNonLValueExprType(const ASTContext &Context) const;
- /// getDesugaredType - Return the specified type with any "sugar" removed from
+ /// Return the specified type with any "sugar" removed from
/// the type. This takes off typedefs, typeof's etc. If the outer level of
/// the type is already concrete, it returns it unmodified. This is similar
/// to getting the canonical type, but it doesn't remove *all* typedefs. For
@@ -878,7 +883,7 @@ public:
return getSingleStepDesugaredTypeImpl(*this, Context);
}
- /// IgnoreParens - Returns the specified type after dropping any
+ /// Returns the specified type after dropping any
/// outer-level parentheses.
QualType IgnoreParens() const {
if (isa<ParenType>(*this))
@@ -886,8 +891,7 @@ public:
return *this;
}
- /// operator==/!= - Indicate whether the specified types and qualifiers are
- /// identical.
+ /// Indicate whether the specified types and qualifiers are identical.
friend bool operator==(const QualType &LHS, const QualType &RHS) {
return LHS.Value == RHS.Value;
}
@@ -956,23 +960,23 @@ public:
ID.AddPointer(getAsOpaquePtr());
}
- /// getAddressSpace - Return the address space of this type.
+ /// Return the address space of this type.
inline unsigned getAddressSpace() const;
- /// getObjCGCAttr - Returns gc attribute of this type.
+ /// Returns gc attribute of this type.
inline Qualifiers::GC getObjCGCAttr() const;
- /// isObjCGCWeak true when Type is objc's weak.
+ /// true when Type is objc's weak.
bool isObjCGCWeak() const {
return getObjCGCAttr() == Qualifiers::Weak;
}
- /// isObjCGCStrong true when Type is objc's strong.
+ /// true when Type is objc's strong.
bool isObjCGCStrong() const {
return getObjCGCAttr() == Qualifiers::Strong;
}
- /// getObjCLifetime - Returns lifetime attribute of this type.
+ /// Returns lifetime attribute of this type.
Qualifiers::ObjCLifetime getObjCLifetime() const {
return getQualifiers().getObjCLifetime();
}
@@ -992,7 +996,7 @@ public:
DK_objc_weak_lifetime
};
- /// isDestructedType - nonzero if objects of this type require
+ /// Returns a nonzero value if objects of this type require
/// non-trivial work to clean up after. Non-zero because it's
/// conceivable that qualifiers (objc_gc(weak)?) could make
/// something require destruction.
@@ -1000,7 +1004,7 @@ public:
return isDestructedTypeImpl(*this);
}
- /// \brief Determine whether expressions of the given type are forbidden
+ /// Determine whether expressions of the given type are forbidden
/// from being lvalues in C.
///
/// The expression types that are forbidden to be lvalues are:
@@ -1124,7 +1128,7 @@ class ExtQualsTypeCommonBase {
friend class ExtQuals;
};
-/// ExtQuals - We can encode up to four bits in the low bits of a
+/// We can encode up to four bits in the low bits of a
/// type pointer, but there are many more type qualifiers that we want
/// to be able to apply to an arbitrary type. Therefore we have this
/// struct, intended to be heap-allocated and used by QualType to
@@ -1148,8 +1152,8 @@ class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode {
// 3. ASTContext:
// a) Update get{Volatile,Restrict}Type.
- /// Quals - the immutable set of qualifiers applied by this
- /// node; always contains extended qualifiers.
+ /// The immutable set of qualifiers applied by this node. Always contains
+ /// extended qualifiers.
Qualifiers Quals;
ExtQuals *this_() { return this; }
@@ -1194,8 +1198,8 @@ public:
}
};
-/// \brief The kind of C++0x ref-qualifier associated with a function type,
-/// which determines whether a member function's "this" object can be an
+/// The kind of C++11 ref-qualifier associated with a function type.
+/// This determines whether a member function's "this" object can be an
/// lvalue, rvalue, or neither.
enum RefQualifierKind {
/// \brief No ref-qualifier was provided.
@@ -1206,17 +1210,28 @@ enum RefQualifierKind {
RQ_RValue
};
-/// Type - This is the base class of the type hierarchy. A central concept
-/// with types is that each type always has a canonical type. A canonical type
-/// is the type with any typedef names stripped out of it or the types it
-/// references. For example, consider:
+/// Which keyword(s) were used to create an AutoType.
+enum class AutoTypeKeyword {
+ /// \brief auto
+ Auto,
+ /// \brief decltype(auto)
+ DecltypeAuto,
+ /// \brief __auto_type (GNU extension)
+ GNUAutoType
+};
+
+/// The base class of the type hierarchy.
+///
+/// A central concept with types is that each type always has a canonical
+/// type. A canonical type is the type with any typedef names stripped out
+/// of it or the types it references. For example, consider:
///
/// typedef int foo;
/// typedef foo* bar;
/// 'int *' 'foo *' 'bar'
///
/// There will be a Type object created for 'int'. Since int is canonical, its
-/// canonicaltype pointer points to itself. There is also a Type for 'foo' (a
+/// CanonicalType pointer points to itself. There is also a Type for 'foo' (a
/// TypedefType). Its CanonicalType pointer points to the 'int' Type. Next
/// there is a PointerType that represents 'int*', which, like 'int', is
/// canonical. Finally, there is a PointerType type for 'foo*' whose canonical
@@ -1253,18 +1268,18 @@ private:
/// TypeClass bitfield - Enum that specifies what subclass this belongs to.
unsigned TC : 8;
- /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]).
+ /// Whether this type is a dependent type (C++ [temp.dep.type]).
unsigned Dependent : 1;
- /// \brief Whether this type somehow involves a template parameter, even
+ /// Whether this type somehow involves a template parameter, even
/// if the resolution of the type does not depend on a template parameter.
unsigned InstantiationDependent : 1;
- /// \brief Whether this type is a variably-modified type (C99 6.7.5).
+ /// Whether this type is a variably-modified type (C99 6.7.5).
unsigned VariablyModified : 1;
/// \brief Whether this type contains an unexpanded parameter pack
- /// (for C++0x variadic templates).
+ /// (for C++11 variadic templates).
unsigned ContainsUnexpandedParameterPack : 1;
/// \brief True if the cache (i.e. the bitfields here starting with
@@ -1277,7 +1292,7 @@ private:
/// \brief Whether this type involves and local or unnamed types.
mutable unsigned CachedLocalOrUnnamed : 1;
- /// \brief FromAST - Whether this type comes from an AST file.
+ /// \brief Whether this type comes from an AST file.
mutable unsigned FromAST : 1;
bool isCacheValid() const {
@@ -1303,11 +1318,11 @@ protected:
unsigned : NumTypeBits;
- /// IndexTypeQuals - CVR qualifiers from declarations like
+ /// CVR qualifiers from declarations like
/// 'int X[static restrict 4]'. For function parameters only.
unsigned IndexTypeQuals : 3;
- /// SizeModifier - storage class qualifiers from declarations like
+ /// Storage class qualifiers from declarations like
/// 'int X[static restrict 4]'. For function parameters only.
/// Actually an ArrayType::ArraySizeModifier.
unsigned SizeModifier : 3;
@@ -1332,7 +1347,7 @@ protected:
/// regparm and the calling convention.
unsigned ExtInfo : 9;
- /// TypeQuals - Used only by FunctionProtoType, put here to pack with the
+ /// Used only by FunctionProtoType, put here to pack with the
/// other bitfields.
/// The qualifiers are part of FunctionProtoType because...
///
@@ -1354,8 +1369,7 @@ protected:
/// The number of type arguments stored directly on this object type.
unsigned NumTypeArgs : 7;
- /// NumProtocols - The number of protocols stored directly on this
- /// object type.
+ /// The number of protocols stored directly on this object type.
unsigned NumProtocols : 6;
/// Whether this is a "kindof" type.
@@ -1400,11 +1414,11 @@ protected:
unsigned : NumTypeBits;
- /// VecKind - The kind of vector, either a generic vector type or some
+ /// The kind of vector, either a generic vector type or some
/// target-specific vector type such as for AltiVec or Neon.
unsigned VecKind : 3;
- /// NumElements - The number of elements in the vector.
+ /// The number of elements in the vector.
unsigned NumElements : 29 - NumTypeBits;
enum { MaxNumElements = (1 << (29 - NumTypeBits)) - 1 };
@@ -1415,7 +1429,7 @@ protected:
unsigned : NumTypeBits;
- /// AttrKind - an AttributedType::Kind
+ /// An AttributedType::Kind
unsigned AttrKind : 32 - NumTypeBits;
};
@@ -1424,8 +1438,9 @@ protected:
unsigned : NumTypeBits;
- /// Was this placeholder type spelled as 'decltype(auto)'?
- unsigned IsDecltypeAuto : 1;
+ /// Was this placeholder type spelled as 'auto', 'decltype(auto)',
+ /// or '__auto_type'? AutoTypeKeyword value.
+ unsigned Keyword : 2;
};
union {
@@ -1521,17 +1536,17 @@ public:
/// Types are partitioned into 3 broad categories (C99 6.2.5p1):
/// object types, function types, and incomplete types.
- /// isIncompleteType - Return true if this is an incomplete type.
+ /// Return true if this is an incomplete type.
/// A type that can describe objects, but which lacks information needed to
/// determine its size (e.g. void, or a fwd declared struct). Clients of this
/// routine will need to determine if the size is actually required.
///
- /// \brief Def If non-NULL, and the type refers to some kind of declaration
+ /// \brief Def If non-null, and the type refers to some kind of declaration
/// that can be completed (such as a C struct, C++ class, or Objective-C
/// class), will be set to the declaration.
bool isIncompleteType(NamedDecl **Def = nullptr) const;
- /// isIncompleteOrObjectType - Return true if this is an incomplete or object
+ /// Return true if this is an incomplete or object
/// type, in other words, not a function type.
bool isIncompleteOrObjectType() const {
return !isFunctionType();
@@ -1545,35 +1560,34 @@ public:
return !isReferenceType() && !isFunctionType() && !isVoidType();
}
- /// isLiteralType - Return true if this is a literal type
+ /// Return true if this is a literal type
/// (C++11 [basic.types]p10)
bool isLiteralType(const ASTContext &Ctx) const;
- /// \brief Test if this type is a standard-layout type.
+ /// Test if this type is a standard-layout type.
/// (C++0x [basic.type]p9)
bool isStandardLayoutType() const;
/// Helper methods to distinguish type categories. All type predicates
/// operate on the canonical type, ignoring typedefs and qualifiers.
- /// isBuiltinType - returns true if the type is a builtin type.
+ /// Returns true if the type is a builtin type.
bool isBuiltinType() const;
- /// isSpecificBuiltinType - Test for a particular builtin type.
+ /// Test for a particular builtin type.
bool isSpecificBuiltinType(unsigned K) const;
- /// isPlaceholderType - Test for a type which does not represent an
- /// actual type-system type but is instead used as a placeholder for
- /// various convenient purposes within Clang. All such types are
- /// BuiltinTypes.
+ /// Test for a type which does not represent an actual type-system type but
+ /// is instead used as a placeholder for various convenient purposes within
+ /// Clang. All such types are BuiltinTypes.
bool isPlaceholderType() const;
const BuiltinType *getAsPlaceholderType() const;
- /// isSpecificPlaceholderType - Test for a specific placeholder type.
+ /// Test for a specific placeholder type.
bool isSpecificPlaceholderType(unsigned K) const;
- /// isNonOverloadPlaceholderType - Test for a placeholder type
- /// other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
+ /// Test for a placeholder type other than Overload; see
+ /// BuiltinType::isNonOverloadPlaceholderType.
bool isNonOverloadPlaceholderType() const;
/// isIntegerType() does *not* include complex integers (a GCC extension).
@@ -1588,10 +1602,9 @@ public:
bool isAnyCharacterType() const;
bool isIntegralType(ASTContext &Ctx) const;
- /// \brief Determine whether this type is an integral or enumeration type.
+ /// Determine whether this type is an integral or enumeration type.
bool isIntegralOrEnumerationType() const;
- /// \brief Determine whether this type is an integral or unscoped enumeration
- /// type.
+ /// Determine whether this type is an integral or unscoped enumeration type.
bool isIntegralOrUnscopedEnumerationType() const;
/// Floating point categories.
@@ -1655,6 +1668,7 @@ public:
bool isObjCQualifiedClassType() const; // Class<foo>
bool isObjCObjectOrInterfaceType() const;
bool isObjCIdType() const; // id
+ bool isObjCInertUnsafeUnretainedType() const;
/// Whether the type is Objective-C 'id' or a __kindof type of an
/// object type, e.g., __kindof NSView * or __kindof id
@@ -1685,18 +1699,29 @@ public:
bool isNullPtrType() const; // C++0x nullptr_t
bool isAtomicType() const; // C11 _Atomic()
- bool isImage1dT() const; // OpenCL image1d_t
- bool isImage1dArrayT() const; // OpenCL image1d_array_t
- bool isImage1dBufferT() const; // OpenCL image1d_buffer_t
- bool isImage2dT() const; // OpenCL image2d_t
- bool isImage2dArrayT() const; // OpenCL image2d_array_t
- bool isImage3dT() const; // OpenCL image3d_t
+ bool isImage1dT() const; // OpenCL image1d_t
+ bool isImage1dArrayT() const; // OpenCL image1d_array_t
+ bool isImage1dBufferT() const; // OpenCL image1d_buffer_t
+ bool isImage2dT() const; // OpenCL image2d_t
+ bool isImage2dArrayT() const; // OpenCL image2d_array_t
+ bool isImage2dDepthT() const; // OpenCL image_2d_depth_t
+ bool isImage2dArrayDepthT() const; // OpenCL image_2d_array_depth_t
+ bool isImage2dMSAAT() const; // OpenCL image_2d_msaa_t
+ bool isImage2dArrayMSAAT() const; // OpenCL image_2d_array_msaa_t
+ bool isImage2dMSAATDepth() const; // OpenCL image_2d_msaa_depth_t
+ bool isImage2dArrayMSAATDepth() const; // OpenCL image_2d_array_msaa_depth_t
+ bool isImage3dT() const; // OpenCL image3d_t
bool isImageType() const; // Any OpenCL image type
bool isSamplerT() const; // OpenCL sampler_t
bool isEventT() const; // OpenCL event_t
+ bool isClkEventT() const; // OpenCL clk_event_t
+ bool isQueueT() const; // OpenCL queue_t
+ bool isNDRangeT() const; // OpenCL ndrange_t
+ bool isReserveIDT() const; // OpenCL reserve_id_t
+ bool isPipeType() const; // OpenCL pipe type
bool isOpenCLSpecificType() const; // Any OpenCL specific type
/// Determines if this type, which must satisfy
@@ -1718,12 +1743,11 @@ public:
STK_IntegralComplex,
STK_FloatingComplex
};
- /// getScalarTypeKind - Given that this is a scalar type, classify it.
+ /// Given that this is a scalar type, classify it.
ScalarTypeKind getScalarTypeKind() const;
- /// isDependentType - Whether this type is a dependent type, meaning
- /// that its definition somehow depends on a template parameter
- /// (C++ [temp.dep.type]).
+ /// Whether this type is a dependent type, meaning that its definition
+ /// somehow depends on a template parameter (C++ [temp.dep.type]).
bool isDependentType() const { return TypeBits.Dependent; }
/// \brief Determine whether this type is an instantiation-dependent type,
@@ -1755,14 +1779,13 @@ public:
bool canDecayToPointerType() const;
- /// hasPointerRepresentation - Whether this type is represented
- /// natively as a pointer; this includes pointers, references, block
- /// pointers, and Objective-C interface, qualified id, and qualified
- /// interface types, as well as nullptr_t.
+ /// Whether this type is represented natively as a pointer. This includes
+ /// pointers, references, block pointers, and Objective-C interface,
+ /// qualified id, and qualified interface types, as well as nullptr_t.
bool hasPointerRepresentation() const;
- /// hasObjCPointerRepresentation - Whether this type can represent
- /// an objective pointer type for the purpose of GC'ability
+ /// Whether this type can represent an objective pointer type for the
+ /// purpose of GC'ability
bool hasObjCPointerRepresentation() const;
/// \brief Determine whether this type has an integer representation
@@ -1813,7 +1836,7 @@ public:
/// not refer to a CXXRecordDecl, returns NULL.
const CXXRecordDecl *getPointeeCXXRecordDecl() const;
- /// \brief Get the AutoType whose type will be deduced for a variable with
+ /// Get the AutoType whose type will be deduced for a variable with
/// an initializer of this type. This looks through declarators like pointer
/// types, but not through decltype or typedefs.
AutoType *getContainedAutoType() const;
@@ -1842,34 +1865,33 @@ public:
/// qualifiers from the outermost type.
const ArrayType *castAsArrayTypeUnsafe() const;
- /// getBaseElementTypeUnsafe - Get the base element type of this
- /// type, potentially discarding type qualifiers. This method
- /// should never be used when type qualifiers are meaningful.
+ /// Get the base element type of this type, potentially discarding type
+ /// qualifiers. This should never be used when type qualifiers
+ /// are meaningful.
const Type *getBaseElementTypeUnsafe() const;
- /// getArrayElementTypeNoTypeQual - If this is an array type, return the
- /// element type of the array, potentially with type qualifiers missing.
- /// This method should never be used when type qualifiers are meaningful.
+ /// If this is an array type, return the element type of the array,
+ /// potentially with type qualifiers missing.
+ /// This should never be used when type qualifiers are meaningful.
const Type *getArrayElementTypeNoTypeQual() const;
- /// getPointeeType - If this is a pointer, ObjC object pointer, or block
+ /// If this is a pointer, ObjC object pointer, or block
/// pointer, this returns the respective pointee.
QualType getPointeeType() const;
- /// getUnqualifiedDesugaredType() - Return the specified type with
- /// any "sugar" removed from the type, removing any typedefs,
- /// typeofs, etc., as well as any qualifiers.
+ /// Return the specified type with any "sugar" removed from the type,
+ /// removing any typedefs, typeofs, etc., as well as any qualifiers.
const Type *getUnqualifiedDesugaredType() const;
/// More type predicates useful for type checking/promotion
bool isPromotableIntegerType() const; // C99 6.3.1.1p2
- /// isSignedIntegerType - Return true if this is an integer type that is
+ /// Return true if this is an integer type that is
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
/// or an enum decl which has a signed representation.
bool isSignedIntegerType() const;
- /// isUnsignedIntegerType - Return true if this is an integer type that is
+ /// Return true if this is an integer type that is
/// unsigned, according to C99 6.2.5p6 [which returns true for _Bool],
/// or an enum decl which has an unsigned representation.
bool isUnsignedIntegerType() const;
@@ -1882,32 +1904,32 @@ public:
/// enumeration types whose underlying type is a unsigned integer type.
bool isUnsignedIntegerOrEnumerationType() const;
- /// isConstantSizeType - Return true if this is not a variable sized type,
+ /// Return true if this is not a variable sized type,
/// according to the rules of C99 6.7.5p3. It is not legal to call this on
/// incomplete types.
bool isConstantSizeType() const;
- /// isSpecifierType - Returns true if this type can be represented by some
+ /// Returns true if this type can be represented by some
/// set of type specifiers.
bool isSpecifierType() const;
- /// \brief Determine the linkage of this type.
+ /// Determine the linkage of this type.
Linkage getLinkage() const;
- /// \brief Determine the visibility of this type.
+ /// Determine the visibility of this type.
Visibility getVisibility() const {
return getLinkageAndVisibility().getVisibility();
}
- /// \brief Return true if the visibility was explicitly set is the code.
+ /// Return true if the visibility was explicitly set is the code.
bool isVisibilityExplicit() const {
return getLinkageAndVisibility().isVisibilityExplicit();
}
- /// \brief Determine the linkage and visibility of this type.
+ /// Determine the linkage and visibility of this type.
LinkageInfo getLinkageAndVisibility() const;
- /// \brief True if the computed linkage is valid. Used for consistency
+ /// True if the computed linkage is valid. Used for consistency
/// checking. Should always return true.
bool isLinkageValid() const;
@@ -1984,7 +2006,7 @@ template <> inline const Class##Type *Type::castAs() const { \
#include "clang/AST/TypeNodes.def"
-/// BuiltinType - This class is used for builtin types like 'int'. Builtin
+/// This class is used for builtin types like 'int'. Builtin
/// types are always canonical and have a literal name field.
class BuiltinType : public Type {
public:
@@ -2059,7 +2081,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
};
-/// ComplexType - C99 6.2.5p11 - Complex values. This supports the C99 complex
+/// Complex values, per C99 6.2.5p11. This supports the C99 complex
/// types (_Complex float etc) as well as the GCC integer complex extensions.
///
class ComplexType : public Type, public llvm::FoldingSetNode {
@@ -2089,7 +2111,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Complex; }
};
-/// ParenType - Sugar for parentheses used when specifying types.
+/// Sugar for parentheses used when specifying types.
///
class ParenType : public Type, public llvm::FoldingSetNode {
QualType Inner;
@@ -2138,7 +2160,7 @@ public:
QualType getPointeeType() const { return PointeeType; }
- /// \brief Returns true if address spaces of pointers overlap.
+ /// Returns true if address spaces of pointers overlap.
/// OpenCL v2.0 defines conversion rules for pointers to different
/// address spaces (OpenCLC v2.0 s6.5.5) and notion of overlapping
/// address spaces.
@@ -2167,7 +2189,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
};
-/// \brief Represents a type which was implicitly adjusted by the semantic
+/// Represents a type which was implicitly adjusted by the semantic
/// engine for arbitrary reasons. For example, array and function types can
/// decay, and function types can have their calling conventions adjusted.
class AdjustedType : public Type, public llvm::FoldingSetNode {
@@ -2205,7 +2227,7 @@ public:
}
};
-/// \brief Represents a pointer type decayed from an array or function type.
+/// Represents a pointer type decayed from an array or function type.
class DecayedType : public AdjustedType {
DecayedType(QualType OriginalType, QualType DecayedPtr, QualType CanonicalPtr)
@@ -2225,7 +2247,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Decayed; }
};
-/// BlockPointerType - pointer to a block type.
+/// Pointer to a block type.
/// This type is to represent types syntactically represented as
/// "void (^)(int)", etc. Pointee is required to always be a function type.
///
@@ -2260,7 +2282,7 @@ public:
}
};
-/// ReferenceType - Base for LValueReferenceType and RValueReferenceType
+/// Base for LValueReferenceType and RValueReferenceType
///
class ReferenceType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
@@ -2307,7 +2329,7 @@ public:
}
};
-/// LValueReferenceType - C++ [dcl.ref] - Lvalue reference
+/// An lvalue reference type, per C++11 [dcl.ref].
///
class LValueReferenceType : public ReferenceType {
LValueReferenceType(QualType Referencee, QualType CanonicalRef,
@@ -2324,7 +2346,7 @@ public:
}
};
-/// RValueReferenceType - C++0x [dcl.ref] - Rvalue reference
+/// An rvalue reference type, per C++11 [dcl.ref].
///
class RValueReferenceType : public ReferenceType {
RValueReferenceType(QualType Referencee, QualType CanonicalRef) :
@@ -2340,7 +2362,9 @@ public:
}
};
-/// MemberPointerType - C++ 8.3.3 - Pointers to members
+/// A pointer to member type per C++ 8.3.3 - Pointers to members.
+///
+/// This includes both pointers to data members and pointer to member functions.
///
class MemberPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
@@ -2395,11 +2419,11 @@ public:
}
};
-/// ArrayType - C99 6.7.5.2 - Array Declarators.
+/// Represents an array type, per C99 6.7.5.2 - Array Declarators.
///
class ArrayType : public Type, public llvm::FoldingSetNode {
public:
- /// ArraySizeModifier - Capture whether this is a normal array (e.g. int X[4])
+ /// Capture whether this is a normal array (e.g. int X[4])
/// an array with a static size (e.g. int X[static 4]), or an array
/// with a star size (e.g. int X[*]).
/// 'static' is only allowed on function parameters.
@@ -2407,7 +2431,7 @@ public:
Normal, Static, Star
};
private:
- /// ElementType - The element type of the array.
+ /// The element type of the array.
QualType ElementType;
protected:
@@ -2450,10 +2474,9 @@ public:
}
};
-/// ConstantArrayType - This class represents the canonical version of
-/// C arrays with a specified constant size. For example, the canonical
-/// type for 'int A[4 + 4*100]' is a ConstantArrayType where the element
-/// type is 'int' and the size is 404.
+/// Represents the canonical version of C arrays with a specified constant size.
+/// For example, the canonical type for 'int A[4 + 4*100]' is a
+/// ConstantArrayType where the element type is 'int' and the size is 404.
class ConstantArrayType : public ArrayType {
llvm::APInt Size; // Allows us to unique the type.
@@ -2501,9 +2524,9 @@ public:
}
};
-/// IncompleteArrayType - This class represents C arrays with an unspecified
-/// size. For example 'int A[]' has an IncompleteArrayType where the element
-/// type is 'int' and the size is unspecified.
+/// Represents a C array with an unspecified size. For example 'int A[]' has
+/// an IncompleteArrayType where the element type is 'int' and the size is
+/// unspecified.
class IncompleteArrayType : public ArrayType {
IncompleteArrayType(QualType et, QualType can,
@@ -2534,8 +2557,8 @@ public:
}
};
-/// VariableArrayType - This class represents C arrays with a specified size
-/// which is not an integer-constant-expression. For example, 'int s[x+foo()]'.
+/// Represents a C array with a specified size that is not an
+/// integer-constant-expression. For example, 'int s[x+foo()]'.
/// Since the size expression is an arbitrary expression, we store it as such.
///
/// Note: VariableArrayType's aren't uniqued (since the expressions aren't) and
@@ -2550,10 +2573,10 @@ public:
/// }
///
class VariableArrayType : public ArrayType {
- /// SizeExpr - An assignment expression. VLA's are only permitted within
+ /// An assignment-expression. VLA's are only permitted within
/// a function block.
Stmt *SizeExpr;
- /// Brackets - The left and right array brackets.
+ /// The range spanned by the left and right array brackets.
SourceRange Brackets;
VariableArrayType(QualType et, QualType can, Expr *e,
@@ -2588,9 +2611,9 @@ public:
}
};
-/// DependentSizedArrayType - This type represents an array type in
-/// C++ whose size is a value-dependent expression. For example:
+/// Represents an array type in C++ whose size is a value-dependent expression.
///
+/// For example:
/// \code
/// template<typename T, int Size>
/// class array {
@@ -2607,11 +2630,11 @@ class DependentSizedArrayType : public ArrayType {
/// \brief An assignment expression that will instantiate to the
/// size of the array.
///
- /// The expression itself might be NULL, in which case the array
+ /// The expression itself might be null, in which case the array
/// type will have its size deduced from an initializer.
Stmt *SizeExpr;
- /// Brackets - The left and right array brackets.
+ /// The range spanned by the left and right array brackets.
SourceRange Brackets;
DependentSizedArrayType(const ASTContext &Context, QualType et, QualType can,
@@ -2650,18 +2673,20 @@ public:
unsigned TypeQuals, Expr *E);
};
-/// DependentSizedExtVectorType - This type represent an extended vector type
-/// where either the type or size is dependent. For example:
-/// @code
+/// Represents an extended vector type where either the type or size is
+/// dependent.
+///
+/// For example:
+/// \code
/// template<typename T, int Size>
/// class vector {
/// typedef T __attribute__((ext_vector_type(Size))) type;
/// }
-/// @endcode
+/// \endcode
class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
const ASTContext &Context;
Expr *SizeExpr;
- /// ElementType - The element type of the array.
+ /// The element type of the array.
QualType ElementType;
SourceLocation loc;
@@ -2691,7 +2716,7 @@ public:
};
-/// VectorType - GCC generic vector type. This type is created using
+/// Represents a GCC generic vector type. This type is created using
/// __attribute__((vector_size(n)), where "n" specifies the vector size in
/// bytes; or from an Altivec __vector or vector declaration.
/// Since the constructor takes the number of vector elements, the
@@ -2699,15 +2724,15 @@ public:
class VectorType : public Type, public llvm::FoldingSetNode {
public:
enum VectorKind {
- GenericVector, // not a target-specific vector type
- AltiVecVector, // is AltiVec vector
- AltiVecPixel, // is AltiVec 'vector Pixel'
- AltiVecBool, // is AltiVec 'vector bool ...'
- NeonVector, // is ARM Neon vector
- NeonPolyVector // is ARM Neon polynomial vector
+ GenericVector, ///< not a target-specific vector type
+ AltiVecVector, ///< is AltiVec vector
+ AltiVecPixel, ///< is AltiVec 'vector Pixel'
+ AltiVecBool, ///< is AltiVec 'vector bool ...'
+ NeonVector, ///< is ARM Neon vector
+ NeonPolyVector ///< is ARM Neon polynomial vector
};
protected:
- /// ElementType - The element type of the vector.
+ /// The element type of the vector.
QualType ElementType;
VectorType(QualType vecType, unsigned nElements, QualType canonType,
@@ -2824,7 +2849,7 @@ class FunctionType : public Type {
QualType ResultType;
public:
- /// ExtInfo - A class which abstracts out some details necessary for
+ /// A class which abstracts out some details necessary for
/// making a call.
///
/// It is not actually used directly for storing this information in
@@ -2878,7 +2903,7 @@ class FunctionType : public Type {
}
// Constructor with all defaults. Use when for example creating a
- // function know to use defaults.
+ // function known to use defaults.
ExtInfo() : Bits(CC_C) { }
// Constructor with just the calling convention, which is an important part
@@ -2953,7 +2978,7 @@ public:
bool getHasRegParm() const { return getExtInfo().getHasRegParm(); }
unsigned getRegParmType() const { return getExtInfo().getRegParm(); }
- /// \brief Determine whether this function type includes the GNU noreturn
+ /// Determine whether this function type includes the GNU noreturn
/// attribute. The C++11 [[noreturn]] attribute does not affect the function
/// type.
bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); }
@@ -2977,7 +3002,7 @@ public:
}
};
-/// FunctionNoProtoType - Represents a K&R-style 'int foo()' function, which has
+/// Represents a K&R-style 'int foo()' function, which has
/// no information available about its arguments.
class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info)
@@ -3008,7 +3033,7 @@ public:
}
};
-/// FunctionProtoType - Represents a prototype with parameter type info, e.g.
+/// Represents a prototype with parameter type info, e.g.
/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no
/// parameters, not as having a single void parameter. Such a type can have an
/// exception specification, but this specification is not part of the canonical
@@ -3038,7 +3063,7 @@ public:
FunctionDecl *SourceTemplate;
};
- /// ExtProtoInfo - Extra information about a function prototype.
+ /// Extra information about a function prototype.
struct ExtProtoInfo {
ExtProtoInfo()
: Variadic(false), HasTrailingReturn(false), TypeQuals(0),
@@ -3081,19 +3106,19 @@ private:
/// The number of parameters this function has, not counting '...'.
unsigned NumParams : 15;
- /// NumExceptions - The number of types in the exception spec, if any.
+ /// The number of types in the exception spec, if any.
unsigned NumExceptions : 9;
- /// ExceptionSpecType - The type of exception specification this function has.
+ /// The type of exception specification this function has.
unsigned ExceptionSpecType : 4;
- /// HasAnyConsumedParams - Whether this function has any consumed parameters.
+ /// Whether this function has any consumed parameters.
unsigned HasAnyConsumedParams : 1;
- /// Variadic - Whether the function is variadic.
+ /// Whether the function is variadic.
unsigned Variadic : 1;
- /// HasTrailingReturn - Whether this function has a trailing return type.
+ /// Whether this function has a trailing return type.
unsigned HasTrailingReturn : 1;
// ParamInfo - There is an variable size array after the class in memory that
@@ -3120,11 +3145,13 @@ private:
assert(hasAnyConsumedParams());
// Find the end of the exceptions.
- Expr *const *eh_end = reinterpret_cast<Expr *const *>(param_type_end());
- if (getExceptionSpecType() != EST_ComputedNoexcept)
- eh_end += NumExceptions;
- else
+ Expr *const *eh_end = reinterpret_cast<Expr *const *>(exception_end());
+ if (getExceptionSpecType() == EST_ComputedNoexcept)
eh_end += 1; // NoexceptExpr
+ // The memory layout of these types isn't handled here, so
+ // hopefully this is never called for them?
+ assert(getExceptionSpecType() != EST_Uninstantiated &&
+ getExceptionSpecType() != EST_Unevaluated);
return reinterpret_cast<const bool*>(eh_end);
}
@@ -3162,25 +3189,25 @@ public:
return EPI;
}
- /// \brief Get the kind of exception specification on this function.
+ /// Get the kind of exception specification on this function.
ExceptionSpecificationType getExceptionSpecType() const {
return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
}
- /// \brief Return whether this function has any kind of exception spec.
+ /// Return whether this function has any kind of exception spec.
bool hasExceptionSpec() const {
return getExceptionSpecType() != EST_None;
}
- /// \brief Return whether this function has a dynamic (throw) exception spec.
+ /// Return whether this function has a dynamic (throw) exception spec.
bool hasDynamicExceptionSpec() const {
return isDynamicExceptionSpec(getExceptionSpecType());
}
- /// \brief Return whether this function has a noexcept exception spec.
+ /// Return whether this function has a noexcept exception spec.
bool hasNoexceptExceptionSpec() const {
return isNoexceptExceptionSpec(getExceptionSpecType());
}
- /// \brief Return whether this function has a dependent exception spec.
+ /// Return whether this function has a dependent exception spec.
bool hasDependentExceptionSpec() const;
- /// \brief Result type of getNoexceptSpec().
+ /// Result type of getNoexceptSpec().
enum NoexceptResult {
NR_NoNoexcept, ///< There is no noexcept specifier.
NR_BadNoexcept, ///< The noexcept specifier has a bad expression.
@@ -3188,7 +3215,7 @@ public:
NR_Throw, ///< The noexcept specifier evaluates to false.
NR_Nothrow ///< The noexcept specifier evaluates to true.
};
- /// \brief Get the meaning of the noexcept spec on this function, if any.
+ /// Get the meaning of the noexcept spec on this function, if any.
NoexceptResult getNoexceptSpec(const ASTContext &Ctx) const;
unsigned getNumExceptions() const { return NumExceptions; }
QualType getExceptionType(unsigned i) const {
@@ -3220,14 +3247,14 @@ public:
return nullptr;
return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1];
}
- /// \brief Determine whether this function type has a non-throwing exception
+ /// Determine whether this function type has a non-throwing exception
/// specification. If this depends on template arguments, returns
/// \c ResultIfDependent.
bool isNothrow(const ASTContext &Ctx, bool ResultIfDependent = false) const;
bool isVariadic() const { return Variadic; }
- /// \brief Determines whether this function prototype contains a
+ /// Determines whether this function prototype contains a
/// parameter pack at the end.
///
/// A function template whose last parameter is a parameter pack can be
@@ -3240,7 +3267,7 @@ public:
unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
- /// \brief Retrieve the ref-qualifier associated with this function type.
+ /// Retrieve the ref-qualifier associated with this function type.
RefQualifierKind getRefQualifier() const {
return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier);
}
@@ -3284,7 +3311,7 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
- void printExceptionSpecification(raw_ostream &OS,
+ void printExceptionSpecification(raw_ostream &OS,
const PrintingPolicy &Policy) const;
static bool classof(const Type *T) {
@@ -3297,10 +3324,10 @@ public:
const ExtProtoInfo &EPI, const ASTContext &Context);
};
-
/// \brief Represents the dependent type named by a dependently-scoped
/// typename using declaration, e.g.
/// using typename Base<T>::foo;
+///
/// Template instantiation turns these into the underlying type.
class UnresolvedUsingType : public Type {
UnresolvedUsingTypenameDecl *Decl;
@@ -3353,7 +3380,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
};
-/// TypeOfExprType (GCC extension).
+/// Represents a `typeof` (or __typeof__) expression (a GCC extension).
class TypeOfExprType : public Type {
Expr *TOExpr;
@@ -3373,7 +3400,7 @@ public:
};
/// \brief Internal representation of canonical, dependent
-/// typeof(expr) types.
+/// `typeof(expr)` types.
///
/// This class is used internally by the ASTContext to manage
/// canonical, dependent types, only. Clients will only see instances
@@ -3394,7 +3421,7 @@ public:
Expr *E);
};
-/// TypeOfType (GCC extension).
+/// Represents `typeof(type)`, a GCC extension.
class TypeOfType : public Type {
QualType TOType;
TypeOfType(QualType T, QualType can)
@@ -3418,7 +3445,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; }
};
-/// DecltypeType (C++0x)
+/// Represents the type `decltype(expr)` (C++11).
class DecltypeType : public Type {
Expr *E;
QualType UnderlyingType;
@@ -3459,7 +3486,7 @@ public:
Expr *E);
};
-/// \brief A unary type transform, which is a type constructed from another
+/// A unary type transform, which is a type constructed from another.
class UnaryTransformType : public Type {
public:
enum UTTKind {
@@ -3497,15 +3524,14 @@ class TagType : public Type {
TagDecl * decl;
friend class ASTReader;
-
+
protected:
TagType(TypeClass TC, const TagDecl *D, QualType can);
public:
TagDecl *getDecl() const;
- /// @brief Determines whether this type is in the process of being
- /// defined.
+ /// Determines whether this type is in the process of being defined.
bool isBeingDefined() const;
static bool classof(const Type *T) {
@@ -3513,7 +3539,7 @@ public:
}
};
-/// RecordType - This is a helper class that allows the use of isa/cast/dyncast
+/// A helper class that allows the use of isa/cast/dyncast
/// to detect TagType objects of structs/unions/classes.
class RecordType : public TagType {
protected:
@@ -3539,7 +3565,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Record; }
};
-/// EnumType - This is a helper class that allows the use of isa/cast/dyncast
+/// A helper class that allows the use of isa/cast/dyncast
/// to detect TagType objects of enums.
class EnumType : public TagType {
explicit EnumType(const EnumDecl *D)
@@ -3557,12 +3583,12 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Enum; }
};
-/// AttributedType - An attributed type is a type to which a type
-/// attribute has been applied. The "modified type" is the
-/// fully-sugared type to which the attributed type was applied;
-/// generally it is not canonically equivalent to the attributed type.
-/// The "equivalent type" is the minimally-desugared type which the
-/// type is canonically equivalent to.
+/// An attributed type is a type to which a type attribute has been applied.
+///
+/// The "modified type" is the fully-sugared type to which the attributed
+/// type was applied; generally it is not canonically equivalent to the
+/// attributed type. The "equivalent type" is the minimally-desugared type
+/// which the type is canonically equivalent to.
///
/// For example, in the following attributed type:
/// int32_t __attribute__((vector_size(16)))
@@ -3612,6 +3638,7 @@ public:
attr_nullable,
attr_null_unspecified,
attr_objc_kindof,
+ attr_objc_inert_unsafe_unretained,
};
private:
@@ -3641,6 +3668,23 @@ public:
bool isSugared() const { return true; }
QualType desugar() const { return getEquivalentType(); }
+ /// Does this attribute behave like a type qualifier?
+ ///
+ /// A type qualifier adjusts a type to provide specialized rules for
+ /// a specific object, like the standard const and volatile qualifiers.
+ /// This includes attributes controlling things like nullability,
+ /// address spaces, and ARC ownership. The value of the object is still
+ /// largely described by the modified type.
+ ///
+ /// In contrast, many type attributes "rewrite" their modified type to
+ /// produce a fundamentally different type, not necessarily related in any
+ /// formalizable way to the original type. For example, calling convention
+ /// and vector attributes are not simple type qualifiers.
+ ///
+ /// Type qualifiers are often, but not always, reflected in the canonical
+ /// type.
+ bool isQualifier() const;
+
bool isMSTypeSpec() const;
bool isCallingConv() const;
@@ -3653,7 +3697,7 @@ public:
switch (kind) {
case NullabilityKind::NonNull:
return attr_nonnull;
-
+
case NullabilityKind::Nullable:
return attr_nullable;
@@ -3865,29 +3909,33 @@ public:
}
};
-/// \brief Represents a C++11 auto or C++1y decltype(auto) type.
+/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
///
/// These types are usually a placeholder for a deduced type. However, before
/// the initializer is attached, or if the initializer is type-dependent, there
/// is no deduced type and an auto type is canonical. In the latter case, it is
/// also a dependent type.
class AutoType : public Type, public llvm::FoldingSetNode {
- AutoType(QualType DeducedType, bool IsDecltypeAuto,
- bool IsDependent)
+ AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent)
: Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
/*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
- /*VariablyModified=*/false,
- /*ContainsParameterPack=*/DeducedType.isNull()
+ /*VariablyModified=*/false,
+ /*ContainsParameterPack=*/DeducedType.isNull()
? false : DeducedType->containsUnexpandedParameterPack()) {
assert((DeducedType.isNull() || !IsDependent) &&
"auto deduced to dependent type");
- AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto;
+ AutoTypeBits.Keyword = (unsigned)Keyword;
}
friend class ASTContext; // ASTContext creates these
public:
- bool isDecltypeAuto() const { return AutoTypeBits.IsDecltypeAuto; }
+ bool isDecltypeAuto() const {
+ return getKeyword() == AutoTypeKeyword::DecltypeAuto;
+ }
+ AutoTypeKeyword getKeyword() const {
+ return (AutoTypeKeyword)AutoTypeBits.Keyword;
+ }
bool isSugared() const { return !isCanonicalUnqualified(); }
QualType desugar() const { return getCanonicalTypeInternal(); }
@@ -3902,14 +3950,13 @@ public:
}
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getDeducedType(), isDecltypeAuto(),
- isDependentType());
+ Profile(ID, getDeducedType(), getKeyword(), isDependentType());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced,
- bool IsDecltypeAuto, bool IsDependent) {
+ AutoTypeKeyword Keyword, bool IsDependent) {
ID.AddPointer(Deduced.getAsOpaquePtr());
- ID.AddBoolean(IsDecltypeAuto);
+ ID.AddInteger((unsigned)Keyword);
ID.AddBoolean(IsDependent);
}
@@ -3926,9 +3973,9 @@ public:
/// @c DependentTemplateSpecializationType.
///
/// A non-dependent template specialization type is always "sugar",
-/// typically for a @c RecordType. For example, a class template
-/// specialization type of @c vector<int> will refer to a tag type for
-/// the instantiation @c std::vector<int, std::allocator<int>>
+/// typically for a \c RecordType. For example, a class template
+/// specialization type of \c vector<int> will refer to a tag type for
+/// the instantiation \c std::vector<int, std::allocator<int>>
///
/// Template specializations are dependent if either the template or
/// any of the template arguments are dependent, in which case the
@@ -3938,9 +3985,10 @@ public:
/// TemplateArguments, followed by a QualType representing the
/// non-canonical aliased type when the template is a type alias
/// template.
-class TemplateSpecializationType
- : public Type, public llvm::FoldingSetNode {
- /// \brief The name of the template being specialized. This is
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType
+ : public Type,
+ public llvm::FoldingSetNode {
+ /// The name of the template being specialized. This is
/// either a TemplateName::Template (in which case it is a
/// ClassTemplateDecl*, a TemplateTemplateParmDecl*, or a
/// TypeAliasTemplateDecl*), a
@@ -3949,14 +3997,13 @@ class TemplateSpecializationType
/// replacement must, recursively, be one of these).
TemplateName Template;
- /// \brief - The number of template arguments named in this class
- /// template specialization.
+ /// The number of template arguments named in this class template
+ /// specialization.
unsigned NumArgs : 31;
- /// \brief Whether this template specialization type is a substituted
- /// type alias.
+ /// Whether this template specialization type is a substituted type alias.
bool TypeAlias : 1;
-
+
TemplateSpecializationType(TemplateName T,
const TemplateArgument *Args,
unsigned NumArgs, QualType Canon,
@@ -3965,8 +4012,7 @@ class TemplateSpecializationType
friend class ASTContext; // ASTContext creates these
public:
- /// \brief Determine whether any of the given template arguments are
- /// dependent.
+ /// Determine whether any of the given template arguments are dependent.
static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args,
unsigned NumArgs,
bool &InstantiationDependent);
@@ -4013,7 +4059,7 @@ public:
/// };
/// \endcode
bool isTypeAlias() const { return TypeAlias; }
-
+
/// Get the aliased type, if this is a specialization of a type alias
/// template.
QualType getAliasedType() const {
@@ -4026,19 +4072,19 @@ public:
iterator begin() const { return getArgs(); }
iterator end() const; // defined inline in TemplateBase.h
- /// \brief Retrieve the name of the template that we are specializing.
+ /// Retrieve the name of the template that we are specializing.
TemplateName getTemplateName() const { return Template; }
- /// \brief Retrieve the template arguments.
+ /// Retrieve the template arguments.
const TemplateArgument *getArgs() const {
return reinterpret_cast<const TemplateArgument *>(this + 1);
}
- /// \brief Retrieve the number of template arguments.
+ /// Retrieve the number of template arguments.
unsigned getNumArgs() const { return NumArgs; }
- /// \brief Retrieve a specific template argument as a type.
- /// \pre @c isArgType(Arg)
+ /// Retrieve a specific template argument as a type.
+ /// \pre \c isArgType(Arg)
const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
bool isSugared() const {
@@ -4062,7 +4108,7 @@ public:
}
};
-/// \brief The injected class name of a C++ class template or class
+/// The injected class name of a C++ class template or class
/// template partial specialization. Used to record that a type was
/// spelled with a bare identifier rather than as a template-id; the
/// equivalent for non-templated classes is just RecordType.
@@ -4178,21 +4224,18 @@ public:
return static_cast<ElaboratedTypeKeyword>(TypeWithKeywordBits.Keyword);
}
- /// getKeywordForTypeSpec - Converts a type specifier (DeclSpec::TST)
- /// into an elaborated type keyword.
+ /// Converts a type specifier (DeclSpec::TST) into an elaborated type keyword.
static ElaboratedTypeKeyword getKeywordForTypeSpec(unsigned TypeSpec);
- /// getTagTypeKindForTypeSpec - Converts a type specifier (DeclSpec::TST)
- /// into a tag type kind. It is an error to provide a type specifier
- /// which *isn't* a tag kind here.
+ /// Converts a type specifier (DeclSpec::TST) into a tag type kind.
+ /// It is an error to provide a type specifier which *isn't* a tag kind here.
static TagTypeKind getTagTypeKindForTypeSpec(unsigned TypeSpec);
- /// getKeywordForTagDeclKind - Converts a TagTypeKind into an
- /// elaborated type keyword.
+ /// Converts a TagTypeKind into an elaborated type keyword.
static ElaboratedTypeKeyword getKeywordForTagTypeKind(TagTypeKind Tag);
- /// getTagTypeKindForKeyword - Converts an elaborated type keyword into
- // a TagTypeKind. It is an error to provide an elaborated type keyword
+ /// Converts an elaborated type keyword into a TagTypeKind.
+ /// It is an error to provide an elaborated type keyword
/// which *isn't* a tag kind here.
static TagTypeKind getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword);
@@ -4218,10 +4261,10 @@ public:
/// in the source code but containing no additional semantic information.
class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
- /// \brief The nested name specifier containing the qualifier.
+ /// The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
- /// \brief The type that this qualified name refers to.
+ /// The type that this qualified name refers to.
QualType NamedType;
ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
@@ -4242,16 +4285,16 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
public:
~ElaboratedType();
- /// \brief Retrieve the qualification on this type.
+ /// Retrieve the qualification on this type.
NestedNameSpecifier *getQualifier() const { return NNS; }
- /// \brief Retrieve the type named by the qualified-id.
+ /// Retrieve the type named by the qualified-id.
QualType getNamedType() const { return NamedType; }
- /// \brief Remove a single level of sugar.
+ /// Remove a single level of sugar.
QualType desugar() const { return getNamedType(); }
- /// \brief Returns whether this type directly provides sugar.
+ /// Returns whether this type directly provides sugar.
bool isSugared() const { return true; }
void Profile(llvm::FoldingSetNodeID &ID) {
@@ -4301,11 +4344,10 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
public:
- /// \brief Retrieve the qualification on this type.
+ /// Retrieve the qualification on this type.
NestedNameSpecifier *getQualifier() const { return NNS; }
- /// \brief Retrieve the type named by the typename specifier as an
- /// identifier.
+ /// Retrieve the type named by the typename specifier as an identifier.
///
/// This routine will return a non-NULL identifier pointer when the
/// form of the original typename was terminated by an identifier,
@@ -4333,20 +4375,21 @@ public:
}
};
-/// DependentTemplateSpecializationType - Represents a template
-/// specialization type whose template cannot be resolved, e.g.
+/// Represents a template specialization type whose template cannot be
+/// resolved, e.g.
/// A<T>::template B<T>
-class DependentTemplateSpecializationType :
- public TypeWithKeyword, public llvm::FoldingSetNode {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType
+ : public TypeWithKeyword,
+ public llvm::FoldingSetNode {
- /// \brief The nested name specifier containing the qualifier.
+ /// The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
- /// \brief The identifier of the template.
+ /// The identifier of the template.
const IdentifierInfo *Name;
- /// \brief - The number of template arguments named in this class
- /// template specialization.
+ /// \brief The number of template arguments named in this class template
+ /// specialization.
unsigned NumArgs;
const TemplateArgument *getArgBuffer() const {
@@ -4405,7 +4448,7 @@ public:
/// \brief Represents a pack expansion of types.
///
-/// Pack expansions are part of C++0x variadic templates. A pack
+/// Pack expansions are part of C++11 variadic templates. A pack
/// expansion contains a pattern, which itself contains one or more
/// "unexpanded" parameter packs. When instantiated, a pack expansion
/// produces a series of types, each instantiated from the pattern of
@@ -4483,7 +4526,7 @@ public:
}
};
-/// ObjCObjectType - Represents a class type in Objective C.
+/// Represents a class type in Objective C.
///
/// Every Objective C type is a combination of a base type, a set of
/// type arguments (optional, for parameterized classes) and a list of
@@ -4560,8 +4603,8 @@ protected:
void computeSuperClassTypeSlow() const;
public:
- /// getBaseType - Gets the base type of this object type. This is
- /// always (possibly sugar for) one of:
+ /// Gets the base type of this object type. This is always (possibly
+ /// sugar for) one of:
/// - the 'id' builtin type (as opposed to the 'id' type visible to the
/// user, which is a typedef for an ObjCObjectPointerType)
/// - the 'Class' builtin type (same caveat)
@@ -4595,8 +4638,8 @@ public:
bool isSpecialized() const;
/// Determine whether this object type was written with type arguments.
- bool isSpecializedAsWritten() const {
- return ObjCObjectTypeBits.NumTypeArgs > 0;
+ bool isSpecializedAsWritten() const {
+ return ObjCObjectTypeBits.NumTypeArgs > 0;
}
/// Determine whether this object type is "unspecialized", meaning
@@ -4612,8 +4655,8 @@ public:
/// Retrieve the type arguments of this object type as they were
/// written.
- ArrayRef<QualType> getTypeArgsAsWritten() const {
- return ArrayRef<QualType>(getTypeArgStorage(),
+ ArrayRef<QualType> getTypeArgsAsWritten() const {
+ return llvm::makeArrayRef(getTypeArgStorage(),
ObjCObjectTypeBits.NumTypeArgs);
}
@@ -4626,11 +4669,11 @@ public:
bool qual_empty() const { return getNumProtocols() == 0; }
- /// getNumProtocols - Return the number of qualifying protocols in this
- /// interface type, or 0 if there are none.
+ /// Return the number of qualifying protocols in this interface type,
+ /// or 0 if there are none.
unsigned getNumProtocols() const { return ObjCObjectTypeBits.NumProtocols; }
- /// \brief Fetch a protocol by index.
+ /// Fetch a protocol by index.
ObjCProtocolDecl *getProtocol(unsigned I) const {
assert(I < getNumProtocols() && "Out-of-range protocol access");
return qual_begin()[I];
@@ -4674,7 +4717,7 @@ public:
}
};
-/// ObjCObjectTypeImpl - A class providing a concrete implementation
+/// A class providing a concrete implementation
/// of ObjCObjectType, so as to not increase the footprint of
/// ObjCInterfaceType. Code outside of ASTContext and the core type
/// system should not reference this type.
@@ -4708,11 +4751,10 @@ inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() {
getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs);
}
-/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
-/// object oriented design. They basically correspond to C++ classes. There
-/// are two kinds of interface types, normal interfaces like "NSString" and
-/// qualified interfaces, which are qualified with a protocol list like
-/// "NSString<NSCopyable, NSAmazing>".
+/// Interfaces are the core concept in Objective-C for object oriented design.
+/// They basically correspond to C++ classes. There are two kinds of interface
+/// types: normal interfaces like `NSString`, and qualified interfaces, which
+/// are qualified with a protocol list like `NSString<NSCopyable, NSAmazing>`.
///
/// ObjCInterfaceType guarantees the following properties when considered
/// as a subtype of its superclass, ObjCObjectType:
@@ -4732,7 +4774,7 @@ class ObjCInterfaceType : public ObjCObjectType {
friend class ObjCInterfaceDecl;
public:
- /// getDecl - Get the declaration of this interface.
+ /// Get the declaration of this interface.
ObjCInterfaceDecl *getDecl() const { return Decl; }
bool isSugared() const { return false; }
@@ -4767,12 +4809,12 @@ inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const {
return nullptr;
}
-/// ObjCObjectPointerType - Used to represent a pointer to an
-/// Objective C object. These are constructed from pointer
-/// declarators when the pointee type is an ObjCObjectType (or sugar
-/// for one). In addition, the 'id' and 'Class' types are typedefs
-/// for these, and the protocol-qualified types 'id<P>' and 'Class<P>'
-/// are translated into these.
+/// Represents a pointer to an Objective C object.
+///
+/// These are constructed from pointer declarators when the pointee type is
+/// an ObjCObjectType (or sugar for one). In addition, the 'id' and 'Class'
+/// types are typedefs for these, and the protocol-qualified types 'id<P>'
+/// and 'Class<P>' are translated into these.
///
/// Pointers to pointers to Objective C objects are still PointerTypes;
/// only the first level of pointer gets it own type implementation.
@@ -4789,12 +4831,11 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
public:
- /// getPointeeType - Gets the type pointed to by this ObjC pointer.
+ /// Gets the type pointed to by this ObjC pointer.
/// The result will always be an ObjCObjectType or sugar thereof.
QualType getPointeeType() const { return PointeeType; }
- /// getObjCObjectType - Gets the type pointed to by this ObjC
- /// pointer. This method always returns non-null.
+ /// Gets the type pointed to by this ObjC pointer. Always returns non-null.
///
/// This method is equivalent to getPointeeType() except that
/// it discards any typedefs (or other sugar) between this
@@ -4821,14 +4862,14 @@ public:
return PointeeType->castAs<ObjCObjectType>();
}
- /// getInterfaceType - If this pointer points to an Objective C
+ /// If this pointer points to an Objective C
/// \@interface type, gets the type for that interface. Any protocol
/// qualifiers on the interface are ignored.
///
/// \return null if the base type for this pointer is 'id' or 'Class'
const ObjCInterfaceType *getInterfaceType() const;
- /// getInterfaceDecl - If this pointer points to an Objective \@interface
+ /// If this pointer points to an Objective \@interface
/// type, gets the declaration for that interface.
///
/// \return null if the base type for this pointer is 'id' or 'Class'
@@ -4836,32 +4877,31 @@ public:
return getObjectType()->getInterface();
}
- /// isObjCIdType - True if this is equivalent to the 'id' type, i.e. if
+ /// True if this is equivalent to the 'id' type, i.e. if
/// its object type is the primitive 'id' type with no protocols.
bool isObjCIdType() const {
return getObjectType()->isObjCUnqualifiedId();
}
- /// isObjCClassType - True if this is equivalent to the 'Class' type,
+ /// True if this is equivalent to the 'Class' type,
/// i.e. if its object tive is the primitive 'Class' type with no protocols.
bool isObjCClassType() const {
return getObjectType()->isObjCUnqualifiedClass();
}
- /// isObjCIdOrClassType - True if this is equivalent to the 'id' or
- /// 'Class' type,
+ /// True if this is equivalent to the 'id' or 'Class' type,
bool isObjCIdOrClassType() const {
return getObjectType()->isObjCUnqualifiedIdOrClass();
}
- /// isObjCQualifiedIdType - True if this is equivalent to 'id<P>' for some
- /// non-empty set of protocols.
+ /// True if this is equivalent to 'id<P>' for some non-empty set of
+ /// protocols.
bool isObjCQualifiedIdType() const {
return getObjectType()->isObjCQualifiedId();
}
- /// isObjCQualifiedClassType - True if this is equivalent to 'Class<P>' for
- /// some non-empty set of protocols.
+ /// True if this is equivalent to 'Class<P>' for some non-empty set of
+ /// protocols.
bool isObjCQualifiedClassType() const {
return getObjectType()->isObjCQualifiedClass();
}
@@ -4873,10 +4913,10 @@ public:
bool isSpecialized() const { return getObjectType()->isSpecialized(); }
/// Whether this type is specialized, meaning that it has type arguments.
- bool isSpecializedAsWritten() const {
- return getObjectType()->isSpecializedAsWritten();
+ bool isSpecializedAsWritten() const {
+ return getObjectType()->isSpecializedAsWritten();
}
-
+
/// Whether this type is unspecialized, meaning that is has no type arguments.
bool isUnspecialized() const { return getObjectType()->isUnspecialized(); }
@@ -4885,13 +4925,13 @@ public:
bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); }
/// Retrieve the type arguments for this type.
- ArrayRef<QualType> getTypeArgs() const {
- return getObjectType()->getTypeArgs();
+ ArrayRef<QualType> getTypeArgs() const {
+ return getObjectType()->getTypeArgs();
}
/// Retrieve the type arguments for this type.
- ArrayRef<QualType> getTypeArgsAsWritten() const {
- return getObjectType()->getTypeArgsAsWritten();
+ ArrayRef<QualType> getTypeArgsAsWritten() const {
+ return getObjectType()->getTypeArgsAsWritten();
}
/// An iterator over the qualifiers on the object type. Provided
@@ -4909,14 +4949,12 @@ public:
}
bool qual_empty() const { return getObjectType()->qual_empty(); }
- /// getNumProtocols - Return the number of qualifying protocols on
- /// the object type.
+ /// Return the number of qualifying protocols on the object type.
unsigned getNumProtocols() const {
return getObjectType()->getNumProtocols();
}
- /// \brief Retrieve a qualifying protocol by index on the object
- /// type.
+ /// Retrieve a qualifying protocol by index on the object type.
ObjCProtocolDecl *getProtocol(unsigned I) const {
return getObjectType()->getProtocol(I);
}
@@ -4960,7 +4998,7 @@ class AtomicType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
public:
- /// getValueType - Gets the type contained by this atomic type, i.e.
+ /// Gets the type contained by this atomic type, i.e.
/// the type returned by performing an atomic load of this atomic type.
QualType getValueType() const { return ValueType; }
@@ -4978,6 +5016,41 @@ class AtomicType : public Type, public llvm::FoldingSetNode {
}
};
+/// PipeType - OpenCL20.
+class PipeType : public Type, public llvm::FoldingSetNode {
+ QualType ElementType;
+
+ PipeType(QualType elemType, QualType CanonicalPtr) :
+ Type(Pipe, CanonicalPtr, elemType->isDependentType(),
+ elemType->isInstantiationDependentType(),
+ elemType->isVariablyModifiedType(),
+ elemType->containsUnexpandedParameterPack()),
+ ElementType(elemType) {}
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+
+ QualType getElementType() const { return ElementType; }
+
+ bool isSugared() const { return false; }
+
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getElementType());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
+ ID.AddPointer(T.getAsOpaquePtr());
+ }
+
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Pipe;
+ }
+
+};
+
/// A qualifier set is used to build a set of qualifiers.
class QualifierCollector : public Qualifiers {
public:
@@ -5127,12 +5200,12 @@ inline void QualType::removeLocalCVRQualifiers(unsigned Mask) {
removeLocalFastQualifiers(Mask);
}
-/// getAddressSpace - Return the address space of this type.
+/// Return the address space of this type.
inline unsigned QualType::getAddressSpace() const {
return getQualifiers().getAddressSpace();
}
-
-/// getObjCGCAttr - Return the gc attribute of this type.
+
+/// Return the gc attribute of this type.
inline Qualifiers::GC QualType::getObjCGCAttr() const {
return getQualifiers().getObjCGCAttr();
}
@@ -5151,7 +5224,7 @@ inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) {
return getFunctionExtInfo(*t);
}
-/// isMoreQualifiedThan - Determine whether this type is more
+/// Determine whether this type is more
/// qualified than the Other type. For example, "const volatile int"
/// is more qualified than "const int", "volatile int", and
/// "int". However, it is not more qualified than "const volatile
@@ -5162,7 +5235,7 @@ inline bool QualType::isMoreQualifiedThan(QualType other) const {
return (myQuals != otherQuals && myQuals.compatiblyIncludes(otherQuals));
}
-/// isAtLeastAsQualifiedAs - Determine whether this type is at last
+/// Determine whether this type is at last
/// as qualified as the Other type. For example, "const volatile
/// int" is at least as qualified as "const int", "volatile int",
/// "int", and "const volatile int".
@@ -5170,7 +5243,7 @@ inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const {
return getQualifiers().compatiblyIncludes(other.getQualifiers());
}
-/// getNonReferenceType - If Type is a reference type (e.g., const
+/// If Type is a reference type (e.g., const
/// int&), returns the type that the reference refers to ("const
/// int"). Otherwise, returns the type itself. This routine is used
/// throughout Sema to implement C++ 5p6:
@@ -5191,7 +5264,7 @@ inline bool QualType::isCForbiddenLValueType() const {
getTypePtr()->isFunctionType());
}
-/// \brief Tests whether the type is categorized as a fundamental type.
+/// Tests whether the type is categorized as a fundamental type.
///
/// \returns True for types specified in C++0x [basic.fundamental].
inline bool Type::isFundamentalType() const {
@@ -5201,7 +5274,7 @@ inline bool Type::isFundamentalType() const {
(isArithmeticType() && !isEnumeralType());
}
-/// \brief Tests whether the type is categorized as a compound type.
+/// Tests whether the type is categorized as a compound type.
///
/// \returns True for types specified in C++0x [basic.compound].
inline bool Type::isCompoundType() const {
@@ -5364,6 +5437,30 @@ inline bool Type::isImage2dArrayT() const {
return isSpecificBuiltinType(BuiltinType::OCLImage2dArray);
}
+inline bool Type::isImage2dDepthT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dDepth);
+}
+
+inline bool Type::isImage2dArrayDepthT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayDepth);
+}
+
+inline bool Type::isImage2dMSAAT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAA);
+}
+
+inline bool Type::isImage2dArrayMSAAT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAA);
+}
+
+inline bool Type::isImage2dMSAATDepth() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAADepth);
+}
+
+inline bool Type::isImage2dArrayMSAATDepth() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAADepth);
+}
+
inline bool Type::isImage3dT() const {
return isSpecificBuiltinType(BuiltinType::OCLImage3d);
}
@@ -5376,14 +5473,37 @@ inline bool Type::isEventT() const {
return isSpecificBuiltinType(BuiltinType::OCLEvent);
}
+inline bool Type::isClkEventT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLClkEvent);
+}
+
+inline bool Type::isQueueT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLQueue);
+}
+
+inline bool Type::isNDRangeT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLNDRange);
+}
+
+inline bool Type::isReserveIDT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLReserveID);
+}
+
inline bool Type::isImageType() const {
- return isImage3dT() ||
- isImage2dT() || isImage2dArrayT() ||
- isImage1dT() || isImage1dArrayT() || isImage1dBufferT();
+ return isImage3dT() || isImage2dT() || isImage2dArrayT() ||
+ isImage2dDepthT() || isImage2dArrayDepthT() || isImage2dMSAAT() ||
+ isImage2dArrayMSAAT() || isImage2dMSAATDepth() ||
+ isImage2dArrayMSAATDepth() || isImage1dT() || isImage1dArrayT() ||
+ isImage1dBufferT();
+}
+
+inline bool Type::isPipeType() const {
+ return isa<PipeType>(CanonicalType);
}
inline bool Type::isOpenCLSpecificType() const {
- return isSamplerT() || isEventT() || isImageType();
+ return isSamplerT() || isEventT() || isImageType() || isClkEventT() ||
+ isQueueT() || isNDRangeT() || isReserveIDT() || isPipeType();
}
inline bool Type::isTemplateTypeParmType() const {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
index f4d20b8..29035a4 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
@@ -151,6 +151,14 @@ public:
TypeLoc IgnoreParens() const;
+ /// \brief Find a type with the location of an explicit type qualifier.
+ ///
+ /// The result, if non-null, will be one of:
+ /// QualifiedTypeLoc
+ /// AtomicTypeLoc
+ /// AttributedTypeLoc, for those type attributes that behave as qualifiers
+ TypeLoc findExplicitQualifierLoc() const;
+
/// \brief Initializes this to state that every location in this
/// type is the given location.
///
@@ -162,19 +170,18 @@ public:
/// \brief Initializes this by copying its information from another
/// TypeLoc of the same type.
- void initializeFullCopy(TypeLoc Other) const {
+ void initializeFullCopy(TypeLoc Other) {
assert(getType() == Other.getType());
- size_t Size = getFullDataSize();
- memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
+ copy(Other);
}
/// \brief Initializes this by copying its information from another
/// TypeLoc of the same type. The given size must be the full data
/// size.
- void initializeFullCopy(TypeLoc Other, unsigned Size) const {
+ void initializeFullCopy(TypeLoc Other, unsigned Size) {
assert(getType() == Other.getType());
assert(getFullDataSize() == Size);
- memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
+ copy(Other);
}
/// Copies the other type loc into this one.
@@ -206,6 +213,7 @@ private:
/// \brief Return the TypeLoc for a type source info.
inline TypeLoc TypeSourceInfo::getTypeLoc() const {
+ // TODO: is this alignment already sufficient?
return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1)));
}
@@ -736,6 +744,10 @@ public:
return hasAttrExprOperand() || hasAttrEnumOperand();
}
+ bool isQualifier() const {
+ return getTypePtr()->isQualifier();
+ }
+
/// The modified type, which is generally canonically different from
/// the attribute type.
/// int main(int, char**) __attribute__((noreturn))
@@ -2021,7 +2033,26 @@ public:
}
};
+struct PipeTypeLocInfo {
+ SourceLocation KWLoc;
+};
+
+class PipeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, PipeTypeLoc, PipeType,
+ PipeTypeLocInfo> {
+public:
+ TypeLoc getValueLoc() const { return this->getInnerTypeLoc(); }
+
+ SourceRange getLocalSourceRange() const { return SourceRange(getKWLoc()); }
+
+ SourceLocation getKWLoc() const { return this->getLocalData()->KWLoc; }
+ void setKWLoc(SourceLocation Loc) { this->getLocalData()->KWLoc = Loc; }
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setKWLoc(Loc);
+ }
+
+ QualType getInnerType() const { return this->getTypePtr()->getElementType(); }
+};
}
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
index 2549f0b..8caf102 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
@@ -104,6 +104,7 @@ NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type)
TYPE(ObjCObject, Type)
TYPE(ObjCInterface, ObjCObjectType)
TYPE(ObjCObjectPointer, Type)
+TYPE(Pipe, Type)
TYPE(Atomic, Type)
#ifdef LAST_TYPE
diff --git a/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h b/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h
index ebfbb8a..481fd11 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h
@@ -51,7 +51,7 @@ public:
CK_UnusedFunctionPointer
};
- VTableComponent() { }
+ VTableComponent() = default;
static VTableComponent MakeVCallOffset(CharUnits Offset) {
return VTableComponent(CK_VCallOffset, Offset);
@@ -122,31 +122,56 @@ public:
}
const CXXRecordDecl *getRTTIDecl() const {
- assert(getKind() == CK_RTTI && "Invalid component kind!");
-
+ assert(isRTTIKind() && "Invalid component kind!");
return reinterpret_cast<CXXRecordDecl *>(getPointer());
}
const CXXMethodDecl *getFunctionDecl() const {
- assert(getKind() == CK_FunctionPointer);
-
+ assert(isFunctionPointerKind() && "Invalid component kind!");
+ if (isDestructorKind())
+ return getDestructorDecl();
return reinterpret_cast<CXXMethodDecl *>(getPointer());
}
const CXXDestructorDecl *getDestructorDecl() const {
- assert((getKind() == CK_CompleteDtorPointer ||
- getKind() == CK_DeletingDtorPointer) && "Invalid component kind!");
-
+ assert(isDestructorKind() && "Invalid component kind!");
return reinterpret_cast<CXXDestructorDecl *>(getPointer());
}
const CXXMethodDecl *getUnusedFunctionDecl() const {
- assert(getKind() == CK_UnusedFunctionPointer);
-
+ assert(getKind() == CK_UnusedFunctionPointer && "Invalid component kind!");
return reinterpret_cast<CXXMethodDecl *>(getPointer());
}
+ bool isDestructorKind() const { return isDestructorKind(getKind()); }
+
+ bool isUsedFunctionPointerKind() const {
+ return isUsedFunctionPointerKind(getKind());
+ }
+
+ bool isFunctionPointerKind() const {
+ return isFunctionPointerKind(getKind());
+ }
+
+ bool isRTTIKind() const { return isRTTIKind(getKind()); }
+
private:
+ static bool isFunctionPointerKind(Kind ComponentKind) {
+ return isUsedFunctionPointerKind(ComponentKind) ||
+ ComponentKind == CK_UnusedFunctionPointer;
+ }
+ static bool isUsedFunctionPointerKind(Kind ComponentKind) {
+ return ComponentKind == CK_FunctionPointer ||
+ isDestructorKind(ComponentKind);
+ }
+ static bool isDestructorKind(Kind ComponentKind) {
+ return ComponentKind == CK_CompleteDtorPointer ||
+ ComponentKind == CK_DeletingDtorPointer;
+ }
+ static bool isRTTIKind(Kind ComponentKind) {
+ return ComponentKind == CK_RTTI;
+ }
+
VTableComponent(Kind ComponentKind, CharUnits Offset) {
assert((ComponentKind == CK_VCallOffset ||
ComponentKind == CK_VBaseOffset ||
@@ -158,12 +183,8 @@ private:
}
VTableComponent(Kind ComponentKind, uintptr_t Ptr) {
- assert((ComponentKind == CK_RTTI ||
- ComponentKind == CK_FunctionPointer ||
- ComponentKind == CK_CompleteDtorPointer ||
- ComponentKind == CK_DeletingDtorPointer ||
- ComponentKind == CK_UnusedFunctionPointer) &&
- "Invalid component kind!");
+ assert((isRTTIKind(ComponentKind) || isFunctionPointerKind(ComponentKind)) &&
+ "Invalid component kind!");
assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
@@ -178,11 +199,7 @@ private:
}
uintptr_t getPointer() const {
- assert((getKind() == CK_RTTI ||
- getKind() == CK_FunctionPointer ||
- getKind() == CK_CompleteDtorPointer ||
- getKind() == CK_DeletingDtorPointer ||
- getKind() == CK_UnusedFunctionPointer) &&
+ assert((getKind() == CK_RTTI || isFunctionPointerKind()) &&
"Invalid component kind!");
return static_cast<uintptr_t>(Value & ~7ULL);
@@ -205,8 +222,11 @@ public:
typedef const VTableComponent *vtable_component_iterator;
typedef const VTableThunkTy *vtable_thunk_iterator;
+ typedef llvm::iterator_range<vtable_component_iterator>
+ vtable_component_range;
typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
+
private:
uint64_t NumVTableComponents;
std::unique_ptr<VTableComponent[]> VTableComponents;
@@ -233,6 +253,11 @@ public:
return NumVTableComponents;
}
+ vtable_component_range vtable_components() const {
+ return vtable_component_range(vtable_component_begin(),
+ vtable_component_end());
+ }
+
vtable_component_iterator vtable_component_begin() const {
return VTableComponents.get();
}
@@ -376,10 +401,6 @@ struct VPtrInfo {
VPtrInfo(const CXXRecordDecl *RD)
: ReusingBase(RD), BaseWithVPtr(RD), NextBaseToMangle(RD) {}
- // Copy constructor.
- // FIXME: Uncomment when we've moved to C++11.
- // VPtrInfo(const VPtrInfo &) = default;
-
/// The vtable will hold all of the virtual bases or virtual methods of
/// ReusingBase. This may or may not be the same class as VPtrSubobject.Base.
/// A derived class will reuse the vptr of the first non-virtual base
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h
index ce2674e..92ec92c 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -42,6 +42,7 @@
#define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Timer.h"
@@ -208,7 +209,7 @@ public:
NestedNameSpecifierLoc;
std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
/// \brief All the callbacks in one container to simplify iteration.
- std::vector<MatchCallback *> AllCallbacks;
+ llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
};
private:
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h
index 281d637..e6ba877 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -14,7 +14,7 @@
// a functional in-language DSL to express queries over the C++ AST.
//
// For example, to match a class with a certain name, one would call:
-// recordDecl(hasName("MyClass"))
+// cxxRecordDecl(hasName("MyClass"))
// which returns a matcher that can be used to find all AST nodes that declare
// a class named 'MyClass'.
//
@@ -25,13 +25,13 @@
//
// For example, when we're interested in child classes of a certain class, we
// would write:
-// recordDecl(hasName("MyClass"), hasChild(id("child", recordDecl())))
+// cxxRecordDecl(hasName("MyClass"), hasChild(id("child", recordDecl())))
// When the match is found via the MatchFinder, a user provided callback will
// be called with a BoundNodes instance that contains a mapping from the
// strings that we provided for the id(...) calls to the nodes that were
// matched.
// In the given example, each time our matcher finds a match we get a callback
-// where "child" is bound to the CXXRecordDecl node of the matching child
+// where "child" is bound to the RecordDecl node of the matching child
// class declaration.
//
// See ASTMatchersInternal.h for a more in-depth explanation of the
@@ -170,7 +170,8 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
/// \brief Matches AST nodes that were expanded within the main-file.
///
-/// Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
+/// Example matches X but not Y
+/// (matcher = cxxRecordDecl(isExpansionInMainFile())
/// \code
/// #include <Y.h>
/// class X {};
@@ -191,7 +192,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
/// \brief Matches AST nodes that were expanded within system-header-files.
///
/// Example matches Y but not X
-/// (matcher = recordDecl(isExpansionInSystemHeader())
+/// (matcher = cxxRecordDecl(isExpansionInSystemHeader())
/// \code
/// #include <SystemHeader.h>
/// class X {};
@@ -216,7 +217,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
/// partially matching a given regex.
///
/// Example matches Y but not X
-/// (matcher = recordDecl(isExpansionInFileMatching("AST.*"))
+/// (matcher = cxxRecordDecl(isExpansionInFileMatching("AST.*"))
/// \code
/// #include "ASTMatcher.h"
/// class X {};
@@ -292,6 +293,31 @@ const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
/// matches "namespace {}" and "namespace test {}"
const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl;
+/// \brief Matches a declaration of a namespace alias.
+///
+/// Given
+/// \code
+/// namespace test {}
+/// namespace alias = ::test;
+/// \endcode
+/// namespaceAliasDecl()
+/// matches "namespace alias" but not "namespace test"
+const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
+ namespaceAliasDecl;
+
+/// \brief Matches class, struct, and union declarations.
+///
+/// Example matches \c X, \c Z, \c U, and \c S
+/// \code
+/// class X;
+/// template<class T> class Z {};
+/// struct S {};
+/// union U {};
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ RecordDecl> recordDecl;
+
/// \brief Matches C++ class declarations.
///
/// Example matches \c X, \c Z
@@ -301,7 +327,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Decl,
- CXXRecordDecl> recordDecl;
+ CXXRecordDecl> cxxRecordDecl;
/// \brief Matches C++ class template declarations.
///
@@ -373,7 +399,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// int i;
/// };
/// \endcode
-const internal::VariadicAllOfMatcher<CXXCtorInitializer> ctorInitializer;
+const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
/// \brief Matches template arguments.
///
@@ -386,6 +412,30 @@ const internal::VariadicAllOfMatcher<CXXCtorInitializer> ctorInitializer;
/// matches 'int' in C<int>.
const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
+/// \brief Matches non-type template parameter declarations.
+///
+/// Given
+/// \code
+/// template <typename T, int N> struct C {};
+/// \endcode
+/// nonTypeTemplateParmDecl()
+/// matches 'N', but not 'T'.
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ NonTypeTemplateParmDecl> nonTypeTemplateParmDecl;
+
+/// \brief Matches template type parameter declarations.
+///
+/// Given
+/// \code
+/// template <typename T, int N> struct C {};
+/// \endcode
+/// templateTypeParmDecl()
+/// matches 'T', but not 'N'.
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ TemplateTypeParmDecl> templateTypeParmDecl;
+
/// \brief Matches public C++ declarations.
///
/// Given
@@ -712,7 +762,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Decl,
- CXXConstructorDecl> constructorDecl;
+ CXXConstructorDecl> cxxConstructorDecl;
/// \brief Matches explicit C++ destructor declarations.
///
@@ -725,7 +775,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Decl,
- CXXDestructorDecl> destructorDecl;
+ CXXDestructorDecl> cxxDestructorDecl;
/// \brief Matches enum declarations.
///
@@ -755,7 +805,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// class X { void y(); };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> methodDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl;
/// \brief Matches conversion operator declarations.
///
@@ -764,7 +814,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> methodDecl;
/// class X { operator int() const; };
/// \endcode
const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
- conversionDecl;
+ cxxConversionDecl;
/// \brief Matches variable declarations.
///
@@ -877,7 +927,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXMemberCallExpr> memberCallExpr;
+ CXXMemberCallExpr> cxxMemberCallExpr;
/// \brief Matches ObjectiveC Message invocation expressions.
///
@@ -892,6 +942,16 @@ const internal::VariadicDynCastAllOfMatcher<
Stmt,
ObjCMessageExpr> objcMessageExpr;
+/// \brief Matches Objective-C interface declarations.
+///
+/// Example matches Foo
+/// \code
+/// @interface Foo
+/// @end
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ObjCInterfaceDecl> objcInterfaceDecl;
/// \brief Matches expressions that introduce cleanups to be run at the end
/// of the sub-expression's evaluation.
@@ -900,8 +960,9 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// const std::string str = std::string();
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups>
-exprWithCleanups;
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ ExprWithCleanups> exprWithCleanups;
/// \brief Matches init list expressions.
///
@@ -925,8 +986,9 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr;
/// \endcode
/// substNonTypeTemplateParmExpr()
/// matches "N" in the right-hand side of "static const int n = N;"
-const internal::VariadicDynCastAllOfMatcher<Stmt, SubstNonTypeTemplateParmExpr>
-substNonTypeTemplateParmExpr;
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ SubstNonTypeTemplateParmExpr> substNonTypeTemplateParmExpr;
/// \brief Matches using declarations.
///
@@ -948,8 +1010,9 @@ const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
/// \endcode
/// usingDirectiveDecl()
/// matches \code using namespace X \endcode
-const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl>
- usingDirectiveDecl;
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ UsingDirectiveDecl> usingDirectiveDecl;
/// \brief Matches unresolved using value declarations.
///
@@ -966,10 +1029,29 @@ const internal::VariadicDynCastAllOfMatcher<
Decl,
UnresolvedUsingValueDecl> unresolvedUsingValueDecl;
+/// \brief Matches unresolved using value declarations that involve the
+/// typename.
+///
+/// Given
+/// \code
+/// template <typename T>
+/// struct Base { typedef T Foo; };
+///
+/// template<typename T>
+/// struct S : private Base<T> {
+/// using typename Base<T>::Foo;
+/// };
+/// \endcode
+/// unresolvedUsingTypenameDecl()
+/// matches \code using Base<T>::Foo \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ UnresolvedUsingTypenameDecl> unresolvedUsingTypenameDecl;
+
/// \brief Matches constructor call expressions (including implicit ones).
///
/// Example matches string(ptr, n) and ptr within arguments of f
-/// (matcher = constructExpr())
+/// (matcher = cxxConstructExpr())
/// \code
/// void f(const string &a, const string &b);
/// char *ptr;
@@ -978,43 +1060,43 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXConstructExpr> constructExpr;
+ CXXConstructExpr> cxxConstructExpr;
/// \brief Matches unresolved constructor call expressions.
///
/// Example matches T(t) in return statement of f
-/// (matcher = unresolvedConstructExpr())
+/// (matcher = cxxUnresolvedConstructExpr())
/// \code
/// template <typename T>
/// void f(const T& t) { return T(t); }
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXUnresolvedConstructExpr> unresolvedConstructExpr;
+ CXXUnresolvedConstructExpr> cxxUnresolvedConstructExpr;
/// \brief Matches implicit and explicit this expressions.
///
/// Example matches the implicit this expression in "return i".
-/// (matcher = thisExpr())
+/// (matcher = cxxThisExpr())
/// \code
/// struct foo {
/// int i;
/// int f() { return i; }
/// };
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> thisExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr;
/// \brief Matches nodes where temporaries are created.
///
/// Example matches FunctionTakesString(GetStringByValue())
-/// (matcher = bindTemporaryExpr())
+/// (matcher = cxxBindTemporaryExpr())
/// \code
/// FunctionTakesString(GetStringByValue());
/// FunctionTakesStringByPointer(GetStringPointer());
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXBindTemporaryExpr> bindTemporaryExpr;
+ CXXBindTemporaryExpr> cxxBindTemporaryExpr;
/// \brief Matches nodes where temporaries are materialized.
///
@@ -1044,9 +1126,9 @@ const internal::VariadicDynCastAllOfMatcher<
/// \code
/// new X;
/// \endcode
-/// newExpr()
+/// cxxNewExpr()
/// matches 'new X'.
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> newExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
/// \brief Matches delete expressions.
///
@@ -1054,9 +1136,9 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> newExpr;
/// \code
/// delete X;
/// \endcode
-/// deleteExpr()
+/// cxxDeleteExpr()
/// matches 'delete X'.
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> deleteExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr;
/// \brief Matches array subscript expressions.
///
@@ -1074,14 +1156,14 @@ const internal::VariadicDynCastAllOfMatcher<
///
/// Example matches the CXXDefaultArgExpr placeholder inserted for the
/// default value of the second parameter in the call expression f(42)
-/// (matcher = defaultArgExpr())
+/// (matcher = cxxDefaultArgExpr())
/// \code
/// void f(int x, int y = 0);
/// f(42);
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXDefaultArgExpr> defaultArgExpr;
+ CXXDefaultArgExpr> cxxDefaultArgExpr;
/// \brief Matches overloaded operator calls.
///
@@ -1091,7 +1173,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// FIXME: figure out why these do not match?
///
/// Example matches both operator<<((o << b), c) and operator<<(o, b)
-/// (matcher = operatorCallExpr())
+/// (matcher = cxxOperatorCallExpr())
/// \code
/// ostream &operator<< (ostream &out, int i) { };
/// ostream &o; int b = 1, c = 1;
@@ -1099,7 +1181,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXOperatorCallExpr> operatorCallExpr;
+ CXXOperatorCallExpr> cxxOperatorCallExpr;
/// \brief Matches expressions.
///
@@ -1166,12 +1248,14 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>,
/// \brief Matches range-based for statements.
///
-/// forRangeStmt() matches 'for (auto a : i)'
+/// cxxForRangeStmt() matches 'for (auto a : i)'
/// \code
/// int i[] = {1, 2, 3}; for (auto a : i);
/// for(int j = 0; j < 5; ++j);
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt> forRangeStmt;
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXForRangeStmt> cxxForRangeStmt;
/// \brief Matches the initialization statement of a for loop.
///
@@ -1326,27 +1410,27 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt;
/// \code
/// try {} catch(int i) {}
/// \endcode
-/// catchStmt()
+/// cxxCatchStmt()
/// matches 'catch(int i)'
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> catchStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt;
/// \brief Matches try statements.
///
/// \code
/// try {} catch(int i) {}
/// \endcode
-/// tryStmt()
+/// cxxTryStmt()
/// matches 'try {}'
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> tryStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt;
/// \brief Matches throw expressions.
///
/// \code
/// try { throw 5; } catch(int i) {}
/// \endcode
-/// throwExpr()
+/// cxxThrowExpr()
/// matches 'throw 5'
-const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> throwExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr;
/// \brief Matches null statements.
///
@@ -1375,7 +1459,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXBoolLiteralExpr> boolLiteral;
+ CXXBoolLiteralExpr> cxxBoolLiteral;
/// \brief Matches string literals (also matches wide string literals).
///
@@ -1439,7 +1523,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \brief Matches nullptr literal.
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXNullPtrLiteralExpr> nullPtrLiteralExpr;
+ CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr;
/// \brief Matches GNU __null expression.
const internal::VariadicDynCastAllOfMatcher<
@@ -1505,7 +1589,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXReinterpretCastExpr> reinterpretCastExpr;
+ CXXReinterpretCastExpr> cxxReinterpretCastExpr;
/// \brief Matches a C++ static_cast expression.
///
@@ -1513,7 +1597,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \see reinterpretCast
///
/// Example:
-/// staticCastExpr()
+/// cxxStaticCastExpr()
/// matches
/// static_cast<long>(8)
/// in
@@ -1522,12 +1606,12 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXStaticCastExpr> staticCastExpr;
+ CXXStaticCastExpr> cxxStaticCastExpr;
/// \brief Matches a dynamic_cast expression.
///
/// Example:
-/// dynamicCastExpr()
+/// cxxDynamicCastExpr()
/// matches
/// dynamic_cast<D*>(&b);
/// in
@@ -1538,7 +1622,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXDynamicCastExpr> dynamicCastExpr;
+ CXXDynamicCastExpr> cxxDynamicCastExpr;
/// \brief Matches a const_cast expression.
///
@@ -1550,7 +1634,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXConstCastExpr> constCastExpr;
+ CXXConstCastExpr> cxxConstCastExpr;
/// \brief Matches a C-style cast expression.
///
@@ -1620,7 +1704,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXFunctionalCastExpr> functionalCastExpr;
+ CXXFunctionalCastExpr> cxxFunctionalCastExpr;
/// \brief Matches functional cast expressions having N != 1 arguments
///
@@ -1630,7 +1714,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
- CXXTemporaryObjectExpr> temporaryObjectExpr;
+ CXXTemporaryObjectExpr> cxxTemporaryObjectExpr;
/// \brief Matches \c QualTypes in the clang AST.
const internal::VariadicAllOfMatcher<QualType> qualType;
@@ -1652,8 +1736,8 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
/// \endcode
/// The matcher:
/// \code
-/// recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
-/// has(fieldDecl(hasName("b")).bind("v"))))
+/// cxxRecordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+/// has(fieldDecl(hasName("b")).bind("v"))))
/// \endcode
/// will generate two results binding "v", the first of which binds
/// the field declaration of \c a, the second the field declaration of
@@ -1789,9 +1873,10 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
/// a << a; // <-- This matches
/// \endcode
///
-/// \c operatorCallExpr(hasOverloadedOperatorName("<<"))) matches the specified
-/// line and \c recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches
-/// the declaration of \c A.
+/// \c cxxOperatorCallExpr(hasOverloadedOperatorName("<<"))) matches the
+/// specified line and
+/// \c cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")))
+/// matches the declaration of \c A.
///
/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl>
inline internal::PolymorphicMatcherWithParam1<
@@ -1858,10 +1943,10 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string,
/// \code
/// class A { void func(); };
/// class B { void member(); };
-/// \code
+/// \endcode
///
-/// \c recordDecl(hasMethod(hasName("func"))) matches the declaration of \c A
-/// but not \c B.
+/// \c cxxRecordDecl(hasMethod(hasName("func"))) matches the declaration of
+/// \c A but not \c B.
AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
InnerMatcher) {
return matchesFirstInPointerRange(InnerMatcher, Node.method_begin(),
@@ -1871,7 +1956,8 @@ AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
/// \brief Matches AST nodes that have child AST nodes that match the
/// provided matcher.
///
-/// Example matches X, Y (matcher = recordDecl(has(recordDecl(hasName("X")))
+/// Example matches X, Y
+/// (matcher = cxxRecordDecl(has(cxxRecordDecl(hasName("X")))
/// \code
/// class X {}; // Matches X, because X::X is a class of name X inside X.
/// class Y { class X {}; };
@@ -1888,7 +1974,7 @@ LLVM_ATTRIBUTE_UNUSED has = {};
/// provided matcher.
///
/// Example matches X, Y, Z
-/// (matcher = recordDecl(hasDescendant(recordDecl(hasName("X")))))
+/// (matcher = cxxRecordDecl(hasDescendant(cxxRecordDecl(hasName("X")))))
/// \code
/// class X {}; // Matches X, because X::X is a class of name X inside X.
/// class Y { class X {}; };
@@ -1904,7 +1990,8 @@ LLVM_ATTRIBUTE_UNUSED hasDescendant = {};
/// \brief Matches AST nodes that have child AST nodes that match the
/// provided matcher.
///
-/// Example matches X, Y (matcher = recordDecl(forEach(recordDecl(hasName("X")))
+/// Example matches X, Y
+/// (matcher = cxxRecordDecl(forEach(cxxRecordDecl(hasName("X")))
/// \code
/// class X {}; // Matches X, because X::X is a class of name X inside X.
/// class Y { class X {}; };
@@ -1924,7 +2011,7 @@ LLVM_ATTRIBUTE_UNUSED forEach = {};
/// provided matcher.
///
/// Example matches X, A, B, C
-/// (matcher = recordDecl(forEachDescendant(recordDecl(hasName("X")))))
+/// (matcher = cxxRecordDecl(forEachDescendant(cxxRecordDecl(hasName("X")))))
/// \code
/// class X {}; // Matches X, because X::X is a class of name X inside X.
/// class A { class X {}; };
@@ -1937,7 +2024,9 @@ LLVM_ATTRIBUTE_UNUSED forEach = {};
/// each result that matches instead of only on the first one.
///
/// Note: Recursively combined ForEachDescendant can cause many matches:
-/// recordDecl(forEachDescendant(recordDecl(forEachDescendant(recordDecl()))))
+/// cxxRecordDecl(forEachDescendant(cxxRecordDecl(
+/// forEachDescendant(cxxRecordDecl())
+/// )))
/// will match 10 times (plus injected class name matches) on:
/// \code
/// class A { class B { class C { class D { class E {}; }; }; }; };
@@ -1957,7 +2046,8 @@ LLVM_ATTRIBUTE_UNUSED forEachDescendant = {};
/// \endcode
/// The matcher:
/// \code
-/// recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("m")))
+/// cxxRecordDecl(hasName("::A"),
+/// findAll(cxxRecordDecl(isDefinition()).bind("m")))
/// \endcode
/// will generate results for \c A, \c B and \c C.
///
@@ -1978,8 +2068,10 @@ internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) {
///
/// Usable as: Any Matcher
const internal::ArgumentAdaptingMatcherFunc<
- internal::HasParentMatcher, internal::TypeList<Decl, Stmt>,
- internal::TypeList<Decl, Stmt> > LLVM_ATTRIBUTE_UNUSED hasParent = {};
+ internal::HasParentMatcher,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
+ LLVM_ATTRIBUTE_UNUSED hasParent = {};
/// \brief Matches AST nodes that have an ancestor that matches the provided
/// matcher.
@@ -1993,12 +2085,14 @@ const internal::ArgumentAdaptingMatcherFunc<
///
/// Usable as: Any Matcher
const internal::ArgumentAdaptingMatcherFunc<
- internal::HasAncestorMatcher, internal::TypeList<Decl, Stmt>,
- internal::TypeList<Decl, Stmt> > LLVM_ATTRIBUTE_UNUSED hasAncestor = {};
+ internal::HasAncestorMatcher,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
+ LLVM_ATTRIBUTE_UNUSED hasAncestor = {};
/// \brief Matches if the provided matcher does not match.
///
-/// Example matches Y (matcher = recordDecl(unless(hasName("X"))))
+/// Example matches Y (matcher = cxxRecordDecl(unless(hasName("X"))))
/// \code
/// class X {};
/// class Y {};
@@ -2038,7 +2132,8 @@ hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
/// \brief Matches on the implicit object argument of a member call expression.
///
-/// Example matches y.x() (matcher = callExpr(on(hasType(recordDecl(hasName("Y"))))))
+/// Example matches y.x()
+/// (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y"))))))
/// \code
/// class Y { public: void x(); };
/// void z() { Y y; y.x(); }",
@@ -2078,7 +2173,7 @@ AST_MATCHER_P(ObjCMessageExpr, hasReceiverType, internal::Matcher<QualType>,
/// \code
/// [self.bodyView loadHTMLString:html baseURL:NULL];
/// \endcode
- AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) {
+AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) {
Selector Sel = Node.getSelector();
return BaseName.compare(Sel.getAsString()) == 0;
}
@@ -2131,14 +2226,13 @@ AST_MATCHER(ObjCMessageExpr, hasUnarySelector) {
/// webView.frame = bodyFrame;
/// // ^---- matches here
/// \endcode
-
AST_MATCHER(ObjCMessageExpr, hasKeywordSelector) {
return Node.getSelector().isKeywordSelector();
}
/// \brief Matches when the selector has the specified number of arguments
///
-/// matcher = objCMessageExpr(numSelectorArgs(1));
+/// matcher = objCMessageExpr(numSelectorArgs(0));
/// matches self.bodyView in the code below
///
/// matcher = objCMessageExpr(numSelectorArgs(2));
@@ -2177,7 +2271,8 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
/// \brief Matches if the call expression's callee's declaration matches the
/// given matcher.
///
-/// Example matches y.x() (matcher = callExpr(callee(methodDecl(hasName("x")))))
+/// Example matches y.x() (matcher = callExpr(callee(
+/// cxxMethodDecl(hasName("x")))))
/// \code
/// class Y { public: void x(); };
/// void z() { Y y; y.x(); }
@@ -2190,8 +2285,8 @@ AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher,
/// \brief Matches if the expression's or declaration's type matches a type
/// matcher.
///
-/// Example matches x (matcher = expr(hasType(recordDecl(hasName("X")))))
-/// and z (matcher = varDecl(hasType(recordDecl(hasName("X")))))
+/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
/// \code
/// class X {};
/// void y(X &x) { x; X z; }
@@ -2207,12 +2302,12 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
///
/// In case of a value declaration (for example a variable declaration),
/// this resolves one layer of indirection. For example, in the value
-/// declaration "X x;", recordDecl(hasName("X")) matches the declaration of X,
-/// while varDecl(hasType(recordDecl(hasName("X")))) matches the declaration
-/// of x."
+/// declaration "X x;", cxxRecordDecl(hasName("X")) matches the declaration of
+/// X, while varDecl(hasType(cxxRecordDecl(hasName("X")))) matches the
+/// declaration of x.
///
-/// Example matches x (matcher = expr(hasType(recordDecl(hasName("X")))))
-/// and z (matcher = varDecl(hasType(recordDecl(hasName("X")))))
+/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
/// \code
/// class X {};
/// void y(X &x) { x; X z; }
@@ -2250,7 +2345,7 @@ AST_MATCHER_P(DeclaratorDecl, hasTypeLoc, internal::Matcher<TypeLoc>, Inner) {
/// class Y { public: void x(); };
/// void z() { Y* y; y->x(); }
/// \endcode
-/// callExpr(on(hasType(asString("class Y *"))))
+/// cxxMemberCallExpr(on(hasType(asString("class Y *"))))
/// matches y->x()
AST_MATCHER_P(QualType, asString, std::string, Name) {
return Name == Node.getAsString();
@@ -2260,7 +2355,8 @@ AST_MATCHER_P(QualType, asString, std::string, Name) {
/// matches the specified matcher.
///
/// Example matches y->x()
-/// (matcher = callExpr(on(hasType(pointsTo(recordDecl(hasName("Y")))))))
+/// (matcher = cxxMemberCallExpr(on(hasType(pointsTo
+/// cxxRecordDecl(hasName("Y")))))))
/// \code
/// class Y { public: void x(); };
/// void z() { Y *y; y->x(); }
@@ -2268,7 +2364,7 @@ AST_MATCHER_P(QualType, asString, std::string, Name) {
AST_MATCHER_P(
QualType, pointsTo, internal::Matcher<QualType>,
InnerMatcher) {
- return (!Node.isNull() && Node->isPointerType() &&
+ return (!Node.isNull() && Node->isAnyPointerType() &&
InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
}
@@ -2283,7 +2379,7 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
/// type matches the specified matcher.
///
/// Example matches X &x and const X &y
-/// (matcher = varDecl(hasType(references(recordDecl(hasName("X"))))))
+/// (matcher = varDecl(hasType(references(cxxRecordDecl(hasName("X"))))))
/// \code
/// class X {
/// void a(X b) {
@@ -2305,7 +2401,7 @@ AST_MATCHER_P(QualType, references, internal::Matcher<QualType>,
/// typedef int &int_ref;
/// int a;
/// int_ref b = a;
-/// \code
+/// \endcode
///
/// \c varDecl(hasType(qualType(referenceType()))))) will not match the
/// declaration of b but \c
@@ -2367,8 +2463,6 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
/// \brief Matches a \c DeclRefExpr that refers to a declaration through a
/// specific using shadow declaration.
///
-/// FIXME: This currently only works for functions. Fix.
-///
/// Given
/// \code
/// namespace a { void f() {} }
@@ -2378,7 +2472,7 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
/// a::f(); // .. but not this.
/// }
/// \endcode
-/// declRefExpr(throughUsingDeclaration(anything()))
+/// declRefExpr(throughUsingDecl(anything()))
/// matches \c f()
AST_MATCHER_P(DeclRefExpr, throughUsingDecl,
internal::Matcher<UsingShadowDecl>, InnerMatcher) {
@@ -2450,6 +2544,69 @@ AST_MATCHER(VarDecl, hasGlobalStorage) {
return Node.hasGlobalStorage();
}
+/// \brief Matches a variable declaration that has automatic storage duration.
+///
+/// Example matches x, but not y, z, or a.
+/// (matcher = varDecl(hasAutomaticStorageDuration())
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// thread_local int z;
+/// }
+/// int a;
+/// \endcode
+AST_MATCHER(VarDecl, hasAutomaticStorageDuration) {
+ return Node.getStorageDuration() == SD_Automatic;
+}
+
+/// \brief Matches a variable declaration that has static storage duration.
+///
+/// Example matches y and a, but not x or z.
+/// (matcher = varDecl(hasStaticStorageDuration())
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// thread_local int z;
+/// }
+/// int a;
+/// \endcode
+AST_MATCHER(VarDecl, hasStaticStorageDuration) {
+ return Node.getStorageDuration() == SD_Static;
+}
+
+/// \brief Matches a variable declaration that has thread storage duration.
+///
+/// Example matches z, but not x, z, or a.
+/// (matcher = varDecl(hasThreadStorageDuration())
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// thread_local int z;
+/// }
+/// int a;
+/// \endcode
+AST_MATCHER(VarDecl, hasThreadStorageDuration) {
+ return Node.getStorageDuration() == SD_Thread;
+}
+
+/// \brief Matches a variable declaration that is an exception variable from
+/// a C++ catch block, or an Objective-C \@catch statement.
+///
+/// Example matches x (matcher = varDecl(isExceptionVariable())
+/// \code
+/// void f(int y) {
+/// try {
+/// } catch (int x) {
+/// }
+/// }
+/// \endcode
+AST_MATCHER(VarDecl, isExceptionVariable) {
+ return Node.isExceptionVariable();
+}
+
/// \brief Checks that a call expression or a constructor call expression has
/// a specific number of arguments (including absent default arguments).
///
@@ -2540,7 +2697,7 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N,
/// // ...
/// }
/// /endcode
-/// catchStmt(isCatchAll()) matches catch(...) but not catch(int).
+/// cxxCatchStmt(isCatchAll()) matches catch(...) but not catch(int).
AST_MATCHER(CXXCatchStmt, isCatchAll) {
return Node.getExceptionDecl() == nullptr;
}
@@ -2554,7 +2711,9 @@ AST_MATCHER(CXXCatchStmt, isCatchAll) {
/// int foo_;
/// };
/// \endcode
-/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer(anything()))))
+/// cxxRecordDecl(has(cxxConstructorDecl(
+/// hasAnyConstructorInitializer(anything())
+/// )))
/// record matches Foo, hasAnyConstructorInitializer matches foo_(1)
AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
@@ -2571,7 +2730,7 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
/// int foo_;
/// };
/// \endcode
-/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer(
+/// cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer(
/// forField(hasName("foo_"))))))
/// matches Foo
/// with forField matching foo_
@@ -2591,7 +2750,7 @@ AST_MATCHER_P(CXXCtorInitializer, forField,
/// int foo_;
/// };
/// \endcode
-/// recordDecl(has(constructorDecl(hasAnyConstructorInitializer(
+/// cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer(
/// withInitializer(integerLiteral(equals(1)))))))
/// matches Foo
/// with withInitializer matching (1)
@@ -2613,12 +2772,52 @@ AST_MATCHER_P(CXXCtorInitializer, withInitializer,
/// string foo_;
/// };
/// \endcode
-/// constructorDecl(hasAnyConstructorInitializer(isWritten()))
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isWritten()))
/// will match Foo(int), but not Foo()
AST_MATCHER(CXXCtorInitializer, isWritten) {
return Node.isWritten();
}
+/// \brief Matches a constructor initializer if it is initializing a base, as
+/// opposed to a member.
+///
+/// Given
+/// \code
+/// struct B {};
+/// struct D : B {
+/// int I;
+/// D(int i) : I(i) {}
+/// };
+/// struct E : B {
+/// E() : B() {}
+/// };
+/// \endcode
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isBaseInitializer()))
+/// will match E(), but not match D(int).
+AST_MATCHER(CXXCtorInitializer, isBaseInitializer) {
+ return Node.isBaseInitializer();
+}
+
+/// \brief Matches a constructor initializer if it is initializing a member, as
+/// opposed to a base.
+///
+/// Given
+/// \code
+/// struct B {};
+/// struct D : B {
+/// int I;
+/// D(int i) : I(i) {}
+/// };
+/// struct E : B {
+/// E() : B() {}
+/// };
+/// \endcode
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isMemberInitializer()))
+/// will match D(int), but not match E().
+AST_MATCHER(CXXCtorInitializer, isMemberInitializer) {
+ return Node.isMemberInitializer();
+}
+
/// \brief Matches any argument of a call expression or a constructor call
/// expression.
///
@@ -2660,7 +2859,7 @@ AST_MATCHER(CXXConstructExpr, isListInitialization) {
/// \code
/// class X { void f(int x) {} };
/// \endcode
-/// methodDecl(hasParameter(0, hasType(varDecl())))
+/// cxxMethodDecl(hasParameter(0, hasType(varDecl())))
/// matches f(int x) {}
/// with hasParameter(...)
/// matching int x
@@ -2680,7 +2879,7 @@ AST_MATCHER_P2(FunctionDecl, hasParameter,
/// \code
/// class X { void f(int x, int y, int z) {} };
/// \endcode
-/// methodDecl(hasAnyParameter(hasName("y")))
+/// cxxMethodDecl(hasAnyParameter(hasName("y")))
/// matches f(int x, int y, int z) {}
/// with hasAnyParameter(...)
/// matching int y
@@ -2709,7 +2908,7 @@ AST_MATCHER_P(FunctionDecl, parameterCountIs, unsigned, N) {
/// \code
/// class X { int f() { return 1; } };
/// \endcode
-/// methodDecl(returns(asString("int")))
+/// cxxMethodDecl(returns(asString("int")))
/// matches int f() { return 1; }
AST_MATCHER_P(FunctionDecl, returns,
internal::Matcher<QualType>, InnerMatcher) {
@@ -2743,6 +2942,34 @@ AST_MATCHER(FunctionDecl, isDeleted) {
return Node.isDeleted();
}
+/// \brief Matches functions that have a non-throwing exception specification.
+///
+/// Given:
+/// \code
+/// void f();
+/// void g() noexcept;
+/// void h() throw();
+/// void i() throw(int);
+/// void j() noexcept(false);
+/// \endcode
+/// functionDecl(isNoThrow())
+/// matches the declarations of g, and h, but not f, i or j.
+AST_MATCHER(FunctionDecl, isNoThrow) {
+ const auto *FnTy = Node.getType()->getAs<FunctionProtoType>();
+
+ // If the function does not have a prototype, then it is assumed to be a
+ // throwing function (as it would if the function did not have any exception
+ // specification).
+ if (!FnTy)
+ return false;
+
+ // Assume the best for any unresolved exception specification.
+ if (isUnresolvedExceptionSpec(FnTy->getExceptionSpecType()))
+ return true;
+
+ return FnTy->isNothrow(Node.getASTContext());
+}
+
/// \brief Matches constexpr variable and function declarations.
///
/// Given:
@@ -2763,7 +2990,7 @@ AST_POLYMORPHIC_MATCHER(isConstexpr,
/// \brief Matches the condition expression of an if statement, for loop,
/// or conditional operator.
///
-/// Example matches true (matcher = hasCondition(boolLiteral(equals(true))))
+/// Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
/// \code
/// if (true) {}
/// \endcode
@@ -2780,7 +3007,7 @@ AST_POLYMORPHIC_MATCHER_P(hasCondition,
/// \brief Matches the then-statement of an if statement.
///
/// Examples matches the if statement
-/// (matcher = ifStmt(hasThen(boolLiteral(equals(true)))))
+/// (matcher = ifStmt(hasThen(cxxBoolLiteral(equals(true)))))
/// \code
/// if (false) true; else false;
/// \endcode
@@ -2792,7 +3019,7 @@ AST_MATCHER_P(IfStmt, hasThen, internal::Matcher<Stmt>, InnerMatcher) {
/// \brief Matches the else-statement of an if statement.
///
/// Examples matches the if statement
-/// (matcher = ifStmt(hasElse(boolLiteral(equals(true)))))
+/// (matcher = ifStmt(hasElse(cxxBoolLiteral(equals(true)))))
/// \code
/// if (false) false; else true;
/// \endcode
@@ -2809,7 +3036,7 @@ AST_MATCHER_P(IfStmt, hasElse, internal::Matcher<Stmt>, InnerMatcher) {
/// \code
/// class X { int a; int b; };
/// \endcode
-/// recordDecl(
+/// cxxRecordDecl(
/// has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
/// has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))
/// matches the class \c X, as \c a and \c b have the same type.
@@ -2941,7 +3168,7 @@ AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) {
/// \brief Matches literals that are equal to the given value.
///
-/// Example matches true (matcher = boolLiteral(equals(true)))
+/// Example matches true (matcher = cxxBoolLiteral(equals(true)))
/// \code
/// true
/// \endcode
@@ -2976,9 +3203,11 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName,
/// \code
/// a || b
/// \endcode
-AST_MATCHER_P(BinaryOperator, hasLHS,
- internal::Matcher<Expr>, InnerMatcher) {
- Expr *LeftHandSide = Node.getLHS();
+AST_POLYMORPHIC_MATCHER_P(hasLHS,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
+ ArraySubscriptExpr),
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *LeftHandSide = Node.getLHS();
return (LeftHandSide != nullptr &&
InnerMatcher.matches(*LeftHandSide, Finder, Builder));
}
@@ -2989,9 +3218,11 @@ AST_MATCHER_P(BinaryOperator, hasLHS,
/// \code
/// a || b
/// \endcode
-AST_MATCHER_P(BinaryOperator, hasRHS,
- internal::Matcher<Expr>, InnerMatcher) {
- Expr *RightHandSide = Node.getRHS();
+AST_POLYMORPHIC_MATCHER_P(hasRHS,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
+ ArraySubscriptExpr),
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *RightHandSide = Node.getRHS();
return (RightHandSide != nullptr &&
InnerMatcher.matches(*RightHandSide, Finder, Builder));
}
@@ -3005,7 +3236,8 @@ inline internal::Matcher<BinaryOperator> hasEitherOperand(
/// \brief Matches if the operand of a unary operator matches.
///
-/// Example matches true (matcher = hasUnaryOperand(boolLiteral(equals(true))))
+/// Example matches true (matcher = hasUnaryOperand(
+/// cxxBoolLiteral(equals(true))))
/// \code
/// !true
/// \endcode
@@ -3019,10 +3251,11 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand,
/// \brief Matches if the cast's source expression matches the given matcher.
///
/// Example: matches "a string" (matcher =
-/// hasSourceExpression(constructExpr()))
+/// hasSourceExpression(cxxConstructExpr()))
/// \code
/// class URL { URL(string); };
/// URL url = "a string";
+/// \endcode
AST_MATCHER_P(CastExpr, hasSourceExpression,
internal::Matcher<Expr>, InnerMatcher) {
const Expr* const SubExpression = Node.getSubExpr();
@@ -3049,6 +3282,42 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
return InnerMatcher.matches(Node.getType(), Finder, Builder);
}
+/// \brief Matches RecordDecl object that are spelled with "struct."
+///
+/// Example matches S, but not C or U.
+/// \code
+/// struct S {};
+/// class C {};
+/// union U {};
+/// \endcode
+AST_MATCHER(RecordDecl, isStruct) {
+ return Node.isStruct();
+}
+
+/// \brief Matches RecordDecl object that are spelled with "union."
+///
+/// Example matches U, but not C or S.
+/// \code
+/// struct S {};
+/// class C {};
+/// union U {};
+/// \endcode
+AST_MATCHER(RecordDecl, isUnion) {
+ return Node.isUnion();
+}
+
+/// \brief Matches RecordDecl object that are spelled with "class."
+///
+/// Example matches C, but not S or U.
+/// \code
+/// struct S {};
+/// class C {};
+/// union U {};
+/// \endcode
+AST_MATCHER(RecordDecl, isClass) {
+ return Node.isClass();
+}
+
/// \brief Matches the true branch expression of a conditional operator.
///
/// Example matches a
@@ -3057,7 +3326,7 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
/// \endcode
AST_MATCHER_P(ConditionalOperator, hasTrueExpression,
internal::Matcher<Expr>, InnerMatcher) {
- Expr *Expression = Node.getTrueExpr();
+ const Expr *Expression = Node.getTrueExpr();
return (Expression != nullptr &&
InnerMatcher.matches(*Expression, Finder, Builder));
}
@@ -3070,7 +3339,7 @@ AST_MATCHER_P(ConditionalOperator, hasTrueExpression,
/// \endcode
AST_MATCHER_P(ConditionalOperator, hasFalseExpression,
internal::Matcher<Expr>, InnerMatcher) {
- Expr *Expression = Node.getFalseExpr();
+ const Expr *Expression = Node.getFalseExpr();
return (Expression != nullptr &&
InnerMatcher.matches(*Expression, Finder, Builder));
}
@@ -3094,6 +3363,20 @@ AST_POLYMORPHIC_MATCHER(isDefinition,
return Node.isThisDeclarationADefinition();
}
+/// \brief Matches if a function declaration is variadic.
+///
+/// Example matches f, but not g or h. The function i will not match, even when
+/// compiled in C mode.
+/// \code
+/// void f(...);
+/// void g(int);
+/// template <typename... Ts> void h(Ts...);
+/// void i();
+/// \endcode
+AST_MATCHER(FunctionDecl, isVariadic) {
+ return Node.isVariadic();
+}
+
/// \brief Matches the class declaration that the given method declaration
/// belongs to.
///
@@ -3102,7 +3385,7 @@ AST_POLYMORPHIC_MATCHER(isDefinition,
/// this to?
///
/// Example matches A() in the last line
-/// (matcher = constructExpr(hasDeclaration(methodDecl(
+/// (matcher = cxxConstructExpr(hasDeclaration(cxxMethodDecl(
/// ofClass(hasName("A"))))))
/// \code
/// class A {
@@ -3132,6 +3415,27 @@ AST_MATCHER(CXXMethodDecl, isVirtual) {
return Node.isVirtual();
}
+/// \brief Matches if the given method or class declaration is final.
+///
+/// Given:
+/// \code
+/// class A final {};
+///
+/// struct B {
+/// virtual void f();
+/// };
+///
+/// struct C : B {
+/// void f() final;
+/// };
+/// \endcode
+/// matches A and C::f, but not B, C, or B::f
+AST_POLYMORPHIC_MATCHER(isFinal,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl,
+ CXXMethodDecl)) {
+ return Node.template hasAttr<FinalAttr>();
+}
+
/// \brief Matches if the given method declaration is pure.
///
/// Given
@@ -3156,11 +3460,28 @@ AST_MATCHER(CXXMethodDecl, isPure) {
/// };
/// \endcode
///
-/// methodDecl(isConst()) matches A::foo() but not A::bar()
+/// cxxMethodDecl(isConst()) matches A::foo() but not A::bar()
AST_MATCHER(CXXMethodDecl, isConst) {
return Node.isConst();
}
+/// \brief Matches if the given method declaration declares a copy assignment
+/// operator.
+///
+/// Given
+/// \code
+/// struct A {
+/// A &operator=(const A &);
+/// A &operator=(A &&);
+/// };
+/// \endcode
+///
+/// cxxMethodDecl(isCopyAssignmentOperator()) matches the first method but not
+/// the second one.
+AST_MATCHER(CXXMethodDecl, isCopyAssignmentOperator) {
+ return Node.isCopyAssignmentOperator();
+}
+
/// \brief Matches if the given method declaration overrides another method.
///
/// Given
@@ -3212,6 +3533,20 @@ AST_MATCHER(QualType, isInteger) {
return Node->isIntegerType();
}
+/// \brief Matches QualType nodes that are of character type.
+///
+/// Given
+/// \code
+/// void a(char);
+/// void b(wchar_t);
+/// void c(double);
+/// \endcode
+/// functionDecl(hasAnyParameter(hasType(isAnyCharacter())))
+/// matches "a(char)", "b(wchar_t)", but not "c(double)".
+AST_MATCHER(QualType, isAnyCharacter) {
+ return Node->isAnyCharacterType();
+}
+
/// \brief Matches QualType nodes that are const-qualified, i.e., that
/// include "top-level" const.
///
@@ -3231,6 +3566,25 @@ AST_MATCHER(QualType, isConstQualified) {
return Node.isConstQualified();
}
+/// \brief Matches QualType nodes that are volatile-qualified, i.e., that
+/// include "top-level" volatile.
+///
+/// Given
+/// \code
+/// void a(int);
+/// void b(int volatile);
+/// void c(volatile int);
+/// void d(volatile int*);
+/// void e(int volatile) {};
+/// \endcode
+/// functionDecl(hasAnyParameter(hasType(isVolatileQualified())))
+/// matches "void b(int volatile)", "void c(volatile int)" and
+/// "void e(int volatile) {}". It does not match d as there
+/// is no top-level volatile on the parameter type "volatile int *".
+AST_MATCHER(QualType, isVolatileQualified) {
+ return Node.isVolatileQualified();
+}
+
/// \brief Matches QualType nodes that have local CV-qualifiers attached to
/// the node, not hidden within a typedef.
///
@@ -3273,7 +3627,7 @@ AST_MATCHER_P(MemberExpr, member,
/// struct X { int m; };
/// void f(X x) { x.m; m; }
/// \endcode
-/// memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))))
+/// memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
/// matches "x.m" and "m"
/// with hasObjectExpression(...)
/// matching "x" and the implicit object expression of "m" which has type X*.
@@ -3325,7 +3679,7 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
/// \code
/// template <typename T> class X {}; class A {}; template class X<A>;
/// \endcode
-/// recordDecl(hasName("::X"), isTemplateInstantiation())
+/// cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
/// matches the template instantiation of X<A>.
///
/// But given
@@ -3333,7 +3687,7 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
/// template <typename T> class X {}; class A {};
/// template <> class X<A> {}; X<A> x;
/// \endcode
-/// recordDecl(hasName("::X"), isTemplateInstantiation())
+/// cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
/// does not match, as X<A> is an explicit template specialization.
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
@@ -3357,7 +3711,7 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstantiation,
/// functionDecl(isInstantiated())
/// matches 'A(int) {...};' and 'A(unsigned) {...}'.
AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
- auto IsInstantiation = decl(anyOf(recordDecl(isTemplateInstantiation()),
+ auto IsInstantiation = decl(anyOf(cxxRecordDecl(isTemplateInstantiation()),
functionDecl(isTemplateInstantiation())));
return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
}
@@ -3378,7 +3732,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
/// instantiation.
AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
return stmt(
- hasAncestor(decl(anyOf(recordDecl(isTemplateInstantiation()),
+ hasAncestor(decl(anyOf(cxxRecordDecl(isTemplateInstantiation()),
functionDecl(isTemplateInstantiation())))));
}
@@ -3408,6 +3762,18 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc,
new internal::TypeLocTypeMatcher(InnerMatcher));
}
+/// \brief Matches type \c bool.
+///
+/// Given
+/// \code
+/// struct S { bool func(); };
+/// \endcode
+/// functionDecl(returns(booleanType()))
+/// matches "bool func();"
+AST_MATCHER(Type, booleanType) {
+ return Node.isBooleanType();
+}
+
/// \brief Matches type \c void.
///
/// Given
@@ -3665,18 +4031,38 @@ AST_TYPE_MATCHER(BlockPointerType, blockPointerType);
/// matches "A::* ptr"
AST_TYPE_MATCHER(MemberPointerType, memberPointerType);
-/// \brief Matches pointer types.
+/// \brief Matches pointer types, but does not match Objective-C object pointer
+/// types.
///
/// Given
/// \code
/// int *a;
/// int &b = *a;
/// int c = 5;
+///
+/// @interface Foo
+/// @end
+/// Foo *f;
/// \endcode
/// pointerType()
-/// matches "int *a"
+/// matches "int *a", but does not match "Foo *f".
AST_TYPE_MATCHER(PointerType, pointerType);
+/// \brief Matches an Objective-C object pointer type, which is different from
+/// a pointer type, despite being syntactically similar.
+///
+/// Given
+/// \code
+/// int *a;
+///
+/// @interface Foo
+/// @end
+/// Foo *f;
+/// \endcode
+/// pointerType()
+/// matches "Foo *f", but does not match "int *a".
+AST_TYPE_MATCHER(ObjCObjectPointerType, objcObjectPointerType);
+
/// \brief Matches both lvalue and rvalue reference types.
///
/// Given
@@ -3766,7 +4152,7 @@ AST_TYPE_MATCHER(TypedefType, typedefType);
///
/// template class C<int>; // A
/// C<char> var; // B
-/// \code
+/// \endcode
///
/// \c templateSpecializationType() matches the type of the explicit
/// instantiation in \c A and the type of the variable declaration in \c B.
@@ -3791,7 +4177,7 @@ AST_TYPE_MATCHER(UnaryTransformType, unaryTransformType);
///
/// C c;
/// S s;
-/// \code
+/// \endcode
///
/// \c recordType() matches the type of the variable declarations of both \c c
/// and \c s.
@@ -3811,7 +4197,7 @@ AST_TYPE_MATCHER(RecordType, recordType);
///
/// class C c;
/// N::M::D d;
-/// \code
+/// \endcode
///
/// \c elaboratedType() matches the type of the variable declarations of both
/// \c c and \c d.
@@ -3828,7 +4214,7 @@ AST_TYPE_MATCHER(ElaboratedType, elaboratedType);
/// }
/// }
/// N::M::D d;
-/// \code
+/// \endcode
///
/// \c elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N"))))
/// matches the type of the variable declaration of \c d.
@@ -3850,7 +4236,7 @@ AST_MATCHER_P(ElaboratedType, hasQualifier,
/// }
/// }
/// N::M::D d;
-/// \code
+/// \endcode
///
/// \c elaboratedType(namesType(recordType(
/// hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable
@@ -3860,6 +4246,59 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
return InnerMatcher.matches(Node.getNamedType(), Finder, Builder);
}
+/// \brief Matches types that represent the result of substituting a type for a
+/// template type parameter.
+///
+/// Given
+/// \code
+/// template <typename T>
+/// void F(T t) {
+/// int i = 1 + t;
+/// }
+/// \endcode
+///
+/// \c substTemplateTypeParmType() matches the type of 't' but not '1'
+AST_TYPE_MATCHER(SubstTemplateTypeParmType, substTemplateTypeParmType);
+
+/// \brief Matches template type parameter types.
+///
+/// Example matches T, but not int.
+/// (matcher = templateTypeParmType())
+/// \code
+/// template <typename T> void f(int i);
+/// \endcode
+AST_TYPE_MATCHER(TemplateTypeParmType, templateTypeParmType);
+
+/// \brief Matches injected class name types.
+///
+/// Example matches S s, but not S<T> s.
+/// (matcher = parmVarDecl(hasType(injectedClassNameType())))
+/// \code
+/// template <typename T> struct S {
+/// void f(S s);
+/// void g(S<T> s);
+/// };
+/// \endcode
+AST_TYPE_MATCHER(InjectedClassNameType, injectedClassNameType);
+
+/// \brief Matches decayed type
+/// Example matches i[] in declaration of f.
+/// (matcher = valueDecl(hasType(decayedType(hasDecayedType(pointerType())))))
+/// Example matches i[1].
+/// (matcher = expr(hasType(decayedType(hasDecayedType(pointerType())))))
+/// \code
+/// void f(int i[]) {
+/// i[1] = 0;
+/// }
+/// \endcode
+AST_TYPE_MATCHER(DecayedType, decayedType);
+
+/// \brief Matches the decayed type, whos decayed type matches \c InnerMatcher
+AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher<QualType>,
+ InnerType) {
+ return InnerType.matches(Node.getDecayedType(), Finder, Builder);
+}
+
/// \brief Matches declarations whose declaration context, interpreted as a
/// Decl, matches \c InnerMatcher.
///
@@ -3870,9 +4309,9 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
/// class D {};
/// }
/// }
-/// \code
+/// \endcode
///
-/// \c recordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
+/// \c cxxRcordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
/// declaration of \c class \c D.
AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) {
const DeclContext *DC = Node.getDeclContext();
@@ -3917,7 +4356,9 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(
/// struct A { struct B { struct C {}; }; };
/// A::B::C c;
/// \endcode
-/// nestedNameSpecifier(specifiesType(hasDeclaration(recordDecl(hasName("A")))))
+/// nestedNameSpecifier(specifiesType(
+/// hasDeclaration(cxxRecordDecl(hasName("A")))
+/// ))
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifier, specifiesType,
internal::Matcher<QualType>, InnerMatcher) {
@@ -3935,7 +4376,7 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType,
/// A::B::C c;
/// \endcode
/// nestedNameSpecifierLoc(specifiesTypeLoc(loc(type(
-/// hasDeclaration(recordDecl(hasName("A")))))))
+/// hasDeclaration(cxxRecordDecl(hasName("A")))))))
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
internal::Matcher<TypeLoc>, InnerMatcher) {
@@ -3954,7 +4395,7 @@ AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
internal::Matcher<NestedNameSpecifier>, InnerMatcher,
0) {
- NestedNameSpecifier *NextNode = Node.getPrefix();
+ const NestedNameSpecifier *NextNode = Node.getPrefix();
if (!NextNode)
return false;
return InnerMatcher.matches(*NextNode, Finder, Builder);
@@ -4008,10 +4449,15 @@ AST_MATCHER_P_OVERLOAD(Decl, equalsNode, const Decl*, Other, 0) {
/// \brief Matches if a node equals another node.
///
/// \c Stmt has pointer identity in the AST.
-///
AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, const Stmt*, Other, 1) {
return &Node == Other;
}
+/// \brief Matches if a node equals another node.
+///
+/// \c Type has pointer identity in the AST.
+AST_MATCHER_P_OVERLOAD(Type, equalsNode, const Type*, Other, 2) {
+ return &Node == Other;
+}
/// @}
@@ -4053,7 +4499,9 @@ AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>,
/// \code
/// class A { A() : i(42), j(42) {} int i; int j; };
/// \endcode
-/// constructorDecl(forEachConstructorInitializer(forField(decl().bind("x"))))
+/// cxxConstructorDecl(forEachConstructorInitializer(
+/// forField(decl().bind("x"))
+/// ))
/// will trigger two matches, binding for 'i' and 'j' respectively.
AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
@@ -4070,6 +4518,109 @@ AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
return Matched;
}
+/// \brief Matches constructor declarations that are copy constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// cxxConstructorDecl(isCopyConstructor()) will match #2, but not #1 or #3.
+AST_MATCHER(CXXConstructorDecl, isCopyConstructor) {
+ return Node.isCopyConstructor();
+}
+
+/// \brief Matches constructor declarations that are move constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// cxxConstructorDecl(isMoveConstructor()) will match #3, but not #1 or #2.
+AST_MATCHER(CXXConstructorDecl, isMoveConstructor) {
+ return Node.isMoveConstructor();
+}
+
+/// \brief Matches constructor declarations that are default constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// cxxConstructorDecl(isDefaultConstructor()) will match #1, but not #2 or #3.
+AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) {
+ return Node.isDefaultConstructor();
+}
+
+/// \brief Matches constructor and conversion declarations that are marked with
+/// the explicit keyword.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(int); // #1
+/// explicit S(double); // #2
+/// operator int(); // #3
+/// explicit operator bool(); // #4
+/// };
+/// \endcode
+/// cxxConstructorDecl(isExplicit()) will match #2, but not #1.
+/// cxxConversionDecl(isExplicit()) will match #4, but not #3.
+AST_POLYMORPHIC_MATCHER(isExplicit,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXConstructorDecl,
+ CXXConversionDecl)) {
+ return Node.isExplicit();
+}
+
+/// \brief Matches function and namespace declarations that are marked with
+/// the inline keyword.
+///
+/// Given
+/// \code
+/// inline void f();
+/// void g();
+/// namespace n {
+/// inline namespace m {}
+/// }
+/// \endcode
+/// functionDecl(isInline()) will match ::f().
+/// namespaceDecl(isInline()) will match n::m.
+AST_POLYMORPHIC_MATCHER(isInline,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(NamespaceDecl,
+ FunctionDecl)) {
+ // This is required because the spelling of the function used to determine
+ // whether inline is specified or not differs between the polymorphic types.
+ if (const auto *FD = dyn_cast<FunctionDecl>(&Node))
+ return FD->isInlineSpecified();
+ else if (const auto *NSD = dyn_cast<NamespaceDecl>(&Node))
+ return NSD->isInline();
+ llvm_unreachable("Not a valid polymorphic type");
+}
+
+/// \brief Matches anonymous namespace declarations.
+///
+/// Given
+/// \code
+/// namespace n {
+/// namespace {} // #1
+/// }
+/// \endcode
+/// namespaceDecl(isAnonymous()) will match #1 but not ::n.
+AST_MATCHER(NamespaceDecl, isAnonymous) {
+ return Node.isAnonymousNamespace();
+}
+
/// \brief If the given case statement does not use the GNU case range
/// extension, matches the constant given in the statement.
///
@@ -4094,7 +4645,8 @@ AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>,
/// __attribute__((device)) void f() { ... }
/// \endcode
/// decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
-/// f.
+/// f. If the matcher is use from clang-query, attr::Kind parameter should be
+/// passed as a quoted string. e.g., hasAttr("attr::CUDADevice").
AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
for (const auto *Attr : Node.attrs()) {
if (Attr->getKind() == AttrKind)
@@ -4109,8 +4661,9 @@ AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
/// \code
/// kernel<<<i,j>>>();
/// \endcode
-const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr>
- CUDAKernelCallExpr;
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CUDAKernelCallExpr> cudaKernelCallExpr;
} // end namespace ast_matchers
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index b494647..1d1d795 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -188,8 +188,11 @@ class ASTMatchFinder;
/// Used by the implementation of Matcher<T> and DynTypedMatcher.
/// In general, implement MatcherInterface<T> or SingleNodeMatcherInterface<T>
/// instead.
-class DynMatcherInterface : public RefCountedBaseVPTR {
+class DynMatcherInterface
+ : public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> {
public:
+ virtual ~DynMatcherInterface() {}
+
/// \brief Returns true if \p DynNode can be matched.
///
/// May bind \p DynNode to an ID via \p Builder, or recurse into
@@ -209,8 +212,6 @@ public:
template <typename T>
class MatcherInterface : public DynMatcherInterface {
public:
- ~MatcherInterface() override {}
-
/// \brief Returns true if 'Node' can be matched.
///
/// May bind 'Node' to an ID via 'Builder', or recurse into
@@ -281,6 +282,7 @@ public:
};
static DynTypedMatcher
constructVariadic(VariadicOperator Op,
+ ast_type_traits::ASTNodeKind SupportedKind,
std::vector<DynTypedMatcher> InnerMatchers);
/// \brief Get a "true" matcher for \p NodeKind.
@@ -556,22 +558,32 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
return false;
}
-/// \brief Metafunction to determine if type T has a member called getDecl.
+// Metafunction to determine if type T has a member called
+// getDecl.
+#if defined(_MSC_VER) && !defined(__clang__)
+// For MSVC, we use a weird nonstandard __if_exists statement, as it
+// is not standards-conformant enough to properly compile the standard
+// code below. (At least up through MSVC 2015 require this workaround)
template <typename T> struct has_getDecl {
- struct Default { int getDecl; };
- struct Derived : T, Default { };
-
- template<typename C, C> struct CheckT;
-
- // If T::getDecl exists, an ambiguity arises and CheckT will
- // not be instantiable. This makes f(...) the only available
- // overload.
- template<typename C>
- static char (&f(CheckT<int Default::*, &C::getDecl>*))[1];
- template<typename C> static char (&f(...))[2];
-
- static bool const value = sizeof(f<Derived>(nullptr)) == 2;
+ __if_exists(T::getDecl) {
+ enum { value = 1 };
+ }
+ __if_not_exists(T::getDecl) {
+ enum { value = 0 };
+ }
};
+#else
+// There is a default template inheriting from "false_type". Then, a
+// partial specialization inherits from "true_type". However, this
+// specialization will only exist when the call to getDecl() isn't an
+// error -- it vanishes by SFINAE when the member doesn't exist.
+template <typename> struct type_sink_to_void { typedef void type; };
+template <typename T, typename = void> struct has_getDecl : std::false_type {};
+template <typename T>
+struct has_getDecl<
+ T, typename type_sink_to_void<decltype(std::declval<T>().getDecl())>::type>
+ : std::true_type {};
+#endif
/// \brief Matches overloaded operators with a specific name.
///
@@ -667,16 +679,30 @@ private:
return matchesDecl(Node.getDecl(), Finder, Builder);
}
- /// \brief Extracts the CXXRecordDecl or EnumDecl of a QualType and returns
- /// whether the inner matcher matches on it.
+ /// \brief Extracts the TagDecl of a QualType and returns whether the inner
+ /// matcher matches on it.
bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- /// FIXME: Add other ways to convert...
if (Node.isNull())
return false;
- if (const EnumType *AsEnum = dyn_cast<EnumType>(Node.getTypePtr()))
- return matchesDecl(AsEnum->getDecl(), Finder, Builder);
- return matchesDecl(Node->getAsCXXRecordDecl(), Finder, Builder);
+
+ if (auto *TD = Node->getAsTagDecl())
+ return matchesDecl(TD, Finder, Builder);
+ else if (auto *TT = Node->getAs<TypedefType>())
+ return matchesDecl(TT->getDecl(), Finder, Builder);
+ // Do not use getAs<TemplateTypeParmType> instead of the direct dyn_cast.
+ // Calling getAs will return the canonical type, but that type does not
+ // store a TemplateTypeParmDecl. We *need* the uncanonical type, if it is
+ // available, and using dyn_cast ensures that.
+ else if (auto *TTP = dyn_cast<TemplateTypeParmType>(Node.getTypePtr()))
+ return matchesDecl(TTP->getDecl(), Finder, Builder);
+ else if (auto *OCIT = Node->getAs<ObjCInterfaceType>())
+ return matchesDecl(OCIT->getDecl(), Finder, Builder);
+ else if (auto *UUT = Node->getAs<UnresolvedUsingType>())
+ return matchesDecl(UUT->getDecl(), Finder, Builder);
+ else if (auto *ICNT = Node->getAs<InjectedClassNameType>())
+ return matchesDecl(ICNT->getDecl(), Finder, Builder);
+ return false;
}
/// \brief Gets the TemplateDecl from a TemplateSpecializationType
@@ -753,7 +779,7 @@ const bool IsBaseType<T>::value;
/// at least one ancestor matched.
///
/// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal.
-/// In the future, we wan to implement this for all nodes for which it makes
+/// In the future, we want to implement this for all nodes for which it makes
/// sense. In the case of matchesAncestorOf, we'll want to implement it for
/// all nodes, as all nodes have ancestors.
class ASTMatchFinder {
@@ -833,8 +859,10 @@ public:
BoundNodesTreeBuilder *Builder,
AncestorMatchMode MatchMode) {
static_assert(std::is_base_of<Decl, T>::value ||
- std::is_base_of<Stmt, T>::value,
- "only Decl or Stmt allowed for recursive matching");
+ std::is_base_of<NestedNameSpecifierLoc, T>::value ||
+ std::is_base_of<Stmt, T>::value ||
+ std::is_base_of<TypeLoc, T>::value,
+ "type not allowed for recursive matching");
return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node),
Matcher, Builder, MatchMode);
}
@@ -1137,7 +1165,8 @@ public:
template <typename T> operator Matcher<T>() const {
return DynTypedMatcher::constructVariadic(
- Op, getMatchers<T>(llvm::index_sequence_for<Ps...>()))
+ Op, ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
+ getMatchers<T>(llvm::index_sequence_for<Ps...>()))
.template unconditionalConvertTo<T>();
}
@@ -1191,8 +1220,10 @@ BindableMatcher<T> makeAllOfComposite(
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
PI(InnerMatchers.end()));
return BindableMatcher<T>(
- DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
- std::move(DynMatchers))
+ DynTypedMatcher::constructVariadic(
+ DynTypedMatcher::VO_AllOf,
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
+ std::move(DynMatchers))
.template unconditionalConvertTo<T>());
}
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h
index ef93ac5..2c76dda 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h
@@ -104,11 +104,11 @@ public:
/// \brief About to call the constructor for a matcher.
enum ConstructMatcherEnum { ConstructMatcher };
Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName,
- const SourceRange &MatcherRange);
+ SourceRange MatcherRange);
/// \brief About to recurse into parsing one argument for a matcher.
enum MatcherArgEnum { MatcherArg };
Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName,
- const SourceRange &MatcherRange, unsigned ArgNumber);
+ SourceRange MatcherRange, unsigned ArgNumber);
~Context();
private:
@@ -137,7 +137,7 @@ public:
/// All the context information will be kept on the error message.
/// \return a helper class to allow the caller to pass the arguments for the
/// error message, using the << operator.
- ArgStream addError(const SourceRange &Range, ErrorType Error);
+ ArgStream addError(SourceRange Range, ErrorType Error);
/// \brief Information stored for one frame of the context.
struct ContextFrame {
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h
index cdc259e..76926f0 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -81,7 +81,7 @@ public:
/// matcher if an error occurred. In that case, \c Error will contain a
/// description of the error.
virtual VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
- const SourceRange &NameRange,
+ SourceRange NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) = 0;
@@ -129,7 +129,7 @@ public:
lookupMatcherCtor(StringRef MatcherName) override;
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
- const SourceRange &NameRange,
+ SourceRange NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) override;
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h
index fc1e783..3808adb 100644
--- a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -106,7 +106,7 @@ public:
/// the signature. In that case \c Error will contain the description of
/// the error.
static VariantMatcher constructMatcher(MatcherCtor Ctor,
- const SourceRange &NameRange,
+ SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error);
@@ -117,7 +117,7 @@ public:
/// If the matcher is not bindable, it sets an error in \c Error and returns
/// a null matcher.
static VariantMatcher constructBoundMatcher(MatcherCtor Ctor,
- const SourceRange &NameRange,
+ SourceRange NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error);
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h
index a710923..1f5aa12 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h
@@ -71,7 +71,7 @@ namespace consumed {
virtual void warnParamReturnTypestateMismatch(SourceLocation Loc,
StringRef VariableName,
StringRef ExpectedState,
- StringRef ObservedState) {};
+ StringRef ObservedState) {}
// FIXME: Add documentation.
virtual void warnParamTypestateMismatch(SourceLocation LOC,
@@ -162,8 +162,8 @@ namespace consumed {
ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const;
/// \brief Merge this state map with another map.
- void intersect(const ConsumedStateMap *Other);
-
+ void intersect(const ConsumedStateMap &Other);
+
void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack,
const ConsumedStateMap *LoopBackStates,
ConsumedWarningsHandlerBase &WarningsHandler);
@@ -196,15 +196,19 @@ namespace consumed {
};
class ConsumedBlockInfo {
- std::vector<ConsumedStateMap*> StateMapsArray;
+ std::vector<std::unique_ptr<ConsumedStateMap>> StateMapsArray;
std::vector<unsigned int> VisitOrder;
public:
- ConsumedBlockInfo() { }
- ~ConsumedBlockInfo() { llvm::DeleteContainerPointers(StateMapsArray); }
+ ConsumedBlockInfo() = default;
+ ConsumedBlockInfo &operator=(ConsumedBlockInfo &&Other) {
+ StateMapsArray = std::move(Other.StateMapsArray);
+ VisitOrder = std::move(Other.VisitOrder);
+ return *this;
+ }
ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph)
- : StateMapsArray(NumBlocks, nullptr), VisitOrder(NumBlocks, 0) {
+ : StateMapsArray(NumBlocks), VisitOrder(NumBlocks, 0) {
unsigned int VisitOrderCounter = 0;
for (PostOrderCFGView::iterator BI = SortedGraph->begin(),
BE = SortedGraph->end(); BI != BE; ++BI) {
@@ -214,17 +218,18 @@ namespace consumed {
bool allBackEdgesVisited(const CFGBlock *CurrBlock,
const CFGBlock *TargetBlock);
-
+
void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap,
- bool &AlreadyOwned);
- void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap);
-
+ std::unique_ptr<ConsumedStateMap> &OwnedStateMap);
+ void addInfo(const CFGBlock *Block,
+ std::unique_ptr<ConsumedStateMap> StateMap);
+
ConsumedStateMap* borrowInfo(const CFGBlock *Block);
void discardInfo(const CFGBlock *Block);
-
- ConsumedStateMap* getInfo(const CFGBlock *Block);
-
+
+ std::unique_ptr<ConsumedStateMap> getInfo(const CFGBlock *Block);
+
bool isBackEdge(const CFGBlock *From, const CFGBlock *To);
bool isBackEdgeTarget(const CFGBlock *Block);
};
@@ -233,13 +238,12 @@ namespace consumed {
class ConsumedAnalyzer {
ConsumedBlockInfo BlockInfo;
- ConsumedStateMap *CurrStates;
-
+ std::unique_ptr<ConsumedStateMap> CurrStates;
+
ConsumedState ExpectedReturnState;
void determineExpectedReturnState(AnalysisDeclContext &AC,
const FunctionDecl *D);
- bool hasConsumableAttributes(const CXXRecordDecl *RD);
bool splitState(const CFGBlock *CurrBlock,
const ConsumedStmtVisitor &Visitor);
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
index 9b7725a..e357013 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -287,10 +287,12 @@ public:
}
const ValueDecl* valueDecl() const {
- if (Negated)
+ if (Negated || CapExpr == nullptr)
return nullptr;
if (auto *P = dyn_cast<til::Project>(CapExpr))
return P->clangDecl();
+ if (auto *P = dyn_cast<til::LiteralPtr>(CapExpr))
+ return P->clangDecl();
return nullptr;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
index 4b59466..be8a710 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
@@ -1395,7 +1395,7 @@ public:
/// Return the list of basic blocks that this terminator can branch to.
ArrayRef<BasicBlock*> successors() {
- return ArrayRef<BasicBlock*>(&TargetBlock, 1);
+ return TargetBlock;
}
template <class V>
@@ -1445,7 +1445,7 @@ public:
/// Return the list of basic blocks that this terminator can branch to.
ArrayRef<BasicBlock*> successors() {
- return ArrayRef<BasicBlock*>(Branches, 2);
+ return llvm::makeArrayRef(Branches);
}
template <class V>
@@ -1479,7 +1479,7 @@ public:
/// Return an empty list.
ArrayRef<BasicBlock*> successors() {
- return ArrayRef<BasicBlock*>();
+ return None;
}
SExpr *returnValue() { return Retval; }
@@ -1507,7 +1507,7 @@ inline ArrayRef<BasicBlock*> Terminator::successors() {
case COP_Branch: return cast<Branch>(this)->successors();
case COP_Return: return cast<Return>(this)->successors();
default:
- return ArrayRef<BasicBlock*>();
+ return None;
}
}
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
index 5430c3b..293990c 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
@@ -229,7 +229,6 @@ public:
return static_cast<CXXDeleteExpr *>(Data2.getPointer());
}
-
private:
friend class CFGElement;
CFGDeleteDtor() {}
@@ -693,7 +692,7 @@ public:
iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt,
BumpVectorContext &C) {
return iterator(Elements.insert(I.base(), Cnt,
- CFGAutomaticObjDtor(nullptr, 0), C));
+ CFGAutomaticObjDtor(nullptr, nullptr), C));
}
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S) {
*I = CFGAutomaticObjDtor(VD, S);
@@ -767,7 +766,7 @@ public:
/// (not a pointer to CFGBlock).
class graph_iterator {
public:
- typedef const CFGBlock value_type;
+ typedef CFGBlock value_type;
typedef value_type& reference;
typedef value_type* pointer;
typedef BumpVector<CFGBlock*>::iterator ImplTy;
@@ -1110,4 +1109,5 @@ template <> struct GraphTraits<Inverse<const ::clang::CFG*> >
}
};
} // end llvm namespace
-#endif
+
+#endif // LLVM_CLANG_ANALYSIS_CFG_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
index f872715..6d816fd 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
@@ -33,8 +33,31 @@ namespace clang {
class AnalysisDeclContext;
class FunctionDecl;
class LocationContext;
-class ProgramPointTag;
+/// ProgramPoints can be "tagged" as representing points specific to a given
+/// analysis entity. Tags are abstract annotations, with an associated
+/// description and potentially other information.
+class ProgramPointTag {
+public:
+ ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
+ virtual ~ProgramPointTag();
+ virtual StringRef getTagDescription() const = 0;
+
+protected:
+ /// Used to implement 'isKind' in subclasses.
+ const void *getTagKind() { return TagKind; }
+
+private:
+ const void *TagKind;
+};
+
+class SimpleProgramPointTag : public ProgramPointTag {
+ std::string Desc;
+public:
+ SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
+ StringRef getTagDescription() const override;
+};
+
class ProgramPoint {
public:
enum Kind { BlockEdgeKind,
@@ -643,30 +666,6 @@ private:
}
};
-/// ProgramPoints can be "tagged" as representing points specific to a given
-/// analysis entity. Tags are abstract annotations, with an associated
-/// description and potentially other information.
-class ProgramPointTag {
-public:
- ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
- virtual ~ProgramPointTag();
- virtual StringRef getTagDescription() const = 0;
-
-protected:
- /// Used to implement 'isKind' in subclasses.
- const void *getTagKind() { return TagKind; }
-
-private:
- const void *TagKind;
-};
-
-class SimpleProgramPointTag : public ProgramPointTag {
- std::string Desc;
-public:
- SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
- StringRef getTagDescription() const override;
-};
-
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
index 3abe32d..591d17b 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
@@ -35,7 +35,12 @@ public:
/// Construct a new BumpVectorContext that creates a new BumpPtrAllocator
/// and destroys it when the BumpVectorContext object is destroyed.
BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), 1) {}
-
+
+ BumpVectorContext(BumpVectorContext &&Other) : Alloc(Other.Alloc) {
+ Other.Alloc.setInt(false);
+ Other.Alloc.setPointer(nullptr);
+ }
+
/// Construct a new BumpVectorContext that reuses an existing
/// BumpPtrAllocator. This BumpPtrAllocator is not destroyed when the
/// BumpVectorContext object is destroyed.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
index 6187bcb..d5ba722 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
@@ -113,7 +113,7 @@ def GlobalVar : SubsetSubject<Var,
// the case of a SubsetSubject, there's no way to express it without this hack.
def DeclBase : AttrSubject;
def FunctionLike : SubsetSubject<DeclBase,
- [{S->getFunctionType(false) != NULL}]>;
+ [{S->getFunctionType(false) != nullptr}]>;
def OpenCLKernelFunction : SubsetSubject<Function, [{
S->hasAttr<OpenCLKernelAttr>()
@@ -123,15 +123,19 @@ def OpenCLKernelFunction : SubsetSubject<Function, [{
// never be specified in a Subjects list along with FunctionLike (due to the
// inclusive nature of subject testing).
def HasFunctionProto : SubsetSubject<DeclBase,
- [{(S->getFunctionType(true) != NULL &&
+ [{(S->getFunctionType(true) != nullptr &&
isa<FunctionProtoType>(S->getFunctionType())) ||
isa<ObjCMethodDecl>(S) ||
isa<BlockDecl>(S)}]>;
// A single argument to an attribute
-class Argument<string name, bit optional> {
+class Argument<string name, bit optional, bit fake = 0> {
string Name = name;
bit Optional = optional;
+
+ /// A fake argument is used to store and serialize additional information
+ /// in an attribute without actually changing its parsing or pretty-printing.
+ bit Fake = fake;
}
class BoolArgument<string name, bit opt = 0> : Argument<name, opt>;
@@ -167,7 +171,8 @@ class DefaultIntArgument<string name, int default> : IntArgument<name, 1> {
// This argument is more complex, it includes the enumerator type name,
// a list of strings to accept, and a list of enumerators to map them to.
class EnumArgument<string name, string type, list<string> values,
- list<string> enums, bit opt = 0> : Argument<name, opt> {
+ list<string> enums, bit opt = 0, bit fake = 0>
+ : Argument<name, opt, fake> {
string Type = type;
list<string> Values = values;
list<string> Enums = enums;
@@ -241,14 +246,18 @@ def COnly : LangOpt<"CPlusPlus", 1>;
class TargetArch<list<string> arches> {
list<string> Arches = arches;
list<string> OSes;
+ list<string> CXXABIs;
}
def TargetARM : TargetArch<["arm", "thumb"]>;
+def TargetMips : TargetArch<["mips", "mipsel"]>;
def TargetMSP430 : TargetArch<["msp430"]>;
def TargetX86 : TargetArch<["x86"]>;
def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
let OSes = ["Win32"];
}
-def TargetMips : TargetArch<["mips", "mipsel"]>;
+def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
+ let CXXABIs = ["Microsoft"];
+}
class Attr {
// The various ways in which an attribute can be spelled in source
@@ -286,6 +295,8 @@ class Attr {
// attribute to be applicable. If empty, no language options are required.
list<LangOpt> LangOpts = [];
// Any additional text that should be included verbatim in the class.
+ // Note: Any additional data members will leak and should be constructed
+ // externally on the ASTContext.
code AdditionalMembers = [{}];
// Any documentation that should be associated with the attribute. Since an
// attribute may be documented under multiple categories, more than one
@@ -415,8 +426,8 @@ def Annotate : InheritableParamAttr {
}
def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
- // NOTE: If you add any additional spellings, MSP430Interrupt's spellings
- // must match.
+ // NOTE: If you add any additional spellings, MSP430Interrupt's and
+ // MipsInterrupt's spellings must match.
let Spellings = [GNU<"interrupt">];
let Args = [EnumArgument<"Interrupt", "InterruptType",
["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", ""],
@@ -445,8 +456,12 @@ def Availability : InheritableAttr {
.Case("android", "Android")
.Case("ios", "iOS")
.Case("macosx", "OS X")
+ .Case("tvos", "tvOS")
+ .Case("watchos", "watchOS")
.Case("ios_app_extension", "iOS (App Extension)")
.Case("macosx_app_extension", "OS X (App Extension)")
+ .Case("tvos_app_extension", "tvOS (App Extension)")
+ .Case("watchos_app_extension", "watchOS (App Extension)")
.Default(llvm::StringRef());
} }];
let HasCustomParsing = 1;
@@ -553,6 +568,11 @@ def CUDAConstant : InheritableAttr {
let Documentation = [Undocumented];
}
+def CUDACudartBuiltin : IgnoredAttr {
+ let Spellings = [GNU<"cudart_builtin">];
+ let LangOpts = [CUDA];
+}
+
def CUDADevice : InheritableAttr {
let Spellings = [GNU<"device">];
let Subjects = SubjectList<[Function, Var]>;
@@ -560,6 +580,21 @@ def CUDADevice : InheritableAttr {
let Documentation = [Undocumented];
}
+def CUDADeviceBuiltin : IgnoredAttr {
+ let Spellings = [GNU<"device_builtin">];
+ let LangOpts = [CUDA];
+}
+
+def CUDADeviceBuiltinSurfaceType : IgnoredAttr {
+ let Spellings = [GNU<"device_builtin_surface_type">];
+ let LangOpts = [CUDA];
+}
+
+def CUDADeviceBuiltinTextureType : IgnoredAttr {
+ let Spellings = [GNU<"device_builtin_texture_type">];
+ let LangOpts = [CUDA];
+}
+
def CUDAGlobal : InheritableAttr {
let Spellings = [GNU<"global">];
let Subjects = SubjectList<[Function]>;
@@ -721,18 +756,6 @@ def FlagEnum : InheritableAttr {
let Subjects = SubjectList<[Enum]>;
let Documentation = [FlagEnumDocs];
let LangOpts = [COnly];
- let AdditionalMembers = [{
-private:
- llvm::APInt FlagBits;
-public:
- llvm::APInt &getFlagBits() {
- return FlagBits;
- }
-
- const llvm::APInt &getFlagBits() const {
- return FlagBits;
- }
-}];
}
def Flatten : InheritableAttr {
@@ -746,7 +769,7 @@ def Format : InheritableAttr {
let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">,
IntArgument<"FirstArg">];
let Subjects = SubjectList<[ObjCMethod, Block, HasFunctionProto], WarnDiag,
- "ExpectedFunction">;
+ "ExpectedFunctionWithProtoType">;
let Documentation = [FormatDocs];
}
@@ -754,7 +777,7 @@ def FormatArg : InheritableAttr {
let Spellings = [GCC<"format_arg">];
let Args = [IntArgument<"FormatIdx">];
let Subjects = SubjectList<[ObjCMethod, HasFunctionProto], WarnDiag,
- "ExpectedFunction">;
+ "ExpectedFunctionWithProtoType">;
let Documentation = [Undocumented];
}
@@ -822,8 +845,8 @@ def MSABI : InheritableAttr {
}
def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> {
- // NOTE: If you add any additional spellings, ARMInterrupt's spellings must
- // match.
+ // NOTE: If you add any additional spellings, ARMInterrupt's and
+ // MipsInterrupt's spellings must match.
let Spellings = [GNU<"interrupt">];
let Args = [UnsignedArgument<"Number">];
let ParseKind = "Interrupt";
@@ -837,6 +860,22 @@ def Mips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
let Documentation = [Undocumented];
}
+def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips> {
+ // NOTE: If you add any additional spellings, ARMInterrupt's and
+ // MSP430Interrupt's spellings must match.
+ let Spellings = [GNU<"interrupt">];
+ let Subjects = SubjectList<[Function]>;
+ let Args = [EnumArgument<"Interrupt", "InterruptType",
+ ["vector=sw0", "vector=sw1", "vector=hw0",
+ "vector=hw1", "vector=hw2", "vector=hw3",
+ "vector=hw4", "vector=hw5", "eic", ""],
+ ["sw0", "sw1", "hw0", "hw1", "hw2", "hw3",
+ "hw4", "hw5", "eic", "eic"]
+ >];
+ let ParseKind = "Interrupt";
+ let Documentation = [MipsInterruptDocs];
+}
+
def Mode : Attr {
let Spellings = [GCC<"mode">];
let Args = [IdentifierArgument<"Mode">];
@@ -867,6 +906,19 @@ def ReturnsTwice : InheritableAttr {
let Documentation = [Undocumented];
}
+def DisableTailCalls : InheritableAttr {
+ let Spellings = [GNU<"disable_tail_calls">,
+ CXX11<"clang", "disable_tail_calls">];
+ let Subjects = SubjectList<[Function, ObjCMethod]>;
+ let Documentation = [DisableTailCallsDocs];
+}
+
+def NoAlias : InheritableAttr {
+ let Spellings = [Declspec<"noalias">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [NoAliasDocs];
+}
+
def NoCommon : InheritableAttr {
let Spellings = [GCC<"nocommon">];
let Subjects = SubjectList<[Var]>;
@@ -960,6 +1012,15 @@ def ReturnsNonNull : InheritableAttr {
let Documentation = [ReturnsNonNullDocs];
}
+// pass_object_size(N) indicates that the parameter should have
+// __builtin_object_size with Type=N evaluated on the parameter at the callsite.
+def PassObjectSize : InheritableParamAttr {
+ let Spellings = [GNU<"pass_object_size">];
+ let Args = [IntArgument<"Type">];
+ let Subjects = SubjectList<[ParmVar]>;
+ let Documentation = [PassObjectSizeDocs];
+}
+
// Nullability type attributes.
def TypeNonNull : TypeAttr {
let Spellings = [Keyword<"_Nonnull">];
@@ -1000,11 +1061,22 @@ def NoInstrumentFunction : InheritableAttr {
let Documentation = [Undocumented];
}
+def NotTailCalled : InheritableAttr {
+ let Spellings = [GNU<"not_tail_called">, CXX11<"clang", "not_tail_called">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [NotTailCalledDocs];
+}
+
def NoThrow : InheritableAttr {
let Spellings = [GCC<"nothrow">, Declspec<"nothrow">];
let Documentation = [Undocumented];
}
+def NvWeak : IgnoredAttr {
+ let Spellings = [GNU<"nv_weak">];
+ let LangOpts = [CUDA];
+}
+
def ObjCBridge : InheritableAttr {
let Spellings = [GNU<"objc_bridge">];
let Subjects = SubjectList<[Record, TypedefName], ErrorDiag,
@@ -1024,8 +1096,8 @@ def ObjCBridgeRelated : InheritableAttr {
let Spellings = [GNU<"objc_bridge_related">];
let Subjects = SubjectList<[Record], ErrorDiag>;
let Args = [IdentifierArgument<"RelatedClass">,
- IdentifierArgument<"ClassMethod">,
- IdentifierArgument<"InstanceMethod">];
+ IdentifierArgument<"ClassMethod", 1>,
+ IdentifierArgument<"InstanceMethod", 1>];
let HasCustomParsing = 1;
let Documentation = [Undocumented];
}
@@ -1169,7 +1241,8 @@ def Ownership : InheritableAttr {
}
}];
let Args = [IdentifierArgument<"Module">, VariadicUnsignedArgument<"Args">];
- let Subjects = SubjectList<[HasFunctionProto], WarnDiag, "ExpectedFunction">;
+ let Subjects = SubjectList<[HasFunctionProto], WarnDiag,
+ "ExpectedFunctionWithProtoType">;
let Documentation = [Undocumented];
}
@@ -1280,9 +1353,41 @@ def Pascal : InheritableAttr {
def Target : InheritableAttr {
let Spellings = [GCC<"target">];
- let Args = [StringArgument<"features">];
+ let Args = [StringArgument<"featuresStr">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [TargetDocs];
+ let AdditionalMembers = [{
+ typedef std::pair<std::vector<std::string>, StringRef> ParsedTargetAttr;
+ ParsedTargetAttr parse() const {
+ ParsedTargetAttr Ret;
+ SmallVector<StringRef, 1> AttrFeatures;
+ getFeaturesStr().split(AttrFeatures, ",");
+
+ // Grab the various features and prepend a "+" to turn on the feature to
+ // the backend and add them to our existing set of features.
+ for (auto &Feature : AttrFeatures) {
+ // Go ahead and trim whitespace rather than either erroring or
+ // accepting it weirdly.
+ Feature = Feature.trim();
+
+ // We don't support cpu tuning this way currently.
+ // TODO: Support the fpmath option. It will require checking
+ // overall feature validity for the function with the rest of the
+ // attributes on the function.
+ if (Feature.startswith("fpmath=") || Feature.startswith("tune="))
+ continue;
+
+ // While we're here iterating check for a different target cpu.
+ if (Feature.startswith("arch="))
+ Ret.second = Feature.split("=").second.trim();
+ else if (Feature.startswith("no-"))
+ Ret.first.push_back("-" + Feature.split("-").second.str());
+ else
+ Ret.first.push_back("+" + Feature.str());
+ }
+ return Ret;
+ }
+ }];
}
def TransparentUnion : InheritableAttr {
@@ -1293,7 +1398,15 @@ def TransparentUnion : InheritableAttr {
def Unavailable : InheritableAttr {
let Spellings = [GNU<"unavailable">];
- let Args = [StringArgument<"Message", 1>];
+ let Args = [StringArgument<"Message", 1>,
+ EnumArgument<"ImplicitReason", "ImplicitReason",
+ ["", "", "", ""],
+ ["IR_None",
+ "IR_ARCForbiddenType",
+ "IR_ForbiddenWeak",
+ "IR_ARCForbiddenConversion",
+ "IR_ARCInitReturnsUnrelated",
+ "IR_ARCFieldWithOwnership"], 1, /*fake*/ 1>];
let Documentation = [Undocumented];
}
@@ -1486,8 +1599,8 @@ def Capability : InheritableAttr {
let Spellings = [GNU<"capability">, CXX11<"clang", "capability">,
GNU<"shared_capability">,
CXX11<"clang", "shared_capability">];
- let Subjects = SubjectList<[Struct, TypedefName], ErrorDiag,
- "ExpectedStructOrTypedef">;
+ let Subjects = SubjectList<[Record, TypedefName], ErrorDiag,
+ "ExpectedStructOrUnionOrTypedef">;
let Args = [StringArgument<"Name">];
let Accessors = [Accessor<"isShared",
[GNU<"shared_capability">,
@@ -1814,7 +1927,7 @@ def TypeTagForDatatype : InheritableAttr {
// Microsoft-related attributes
-def MSNoVTable : InheritableAttr {
+def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
let Spellings = [Declspec<"novtable">];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [MSNoVTableDocs];
@@ -1970,8 +2083,8 @@ def LoopHint : Attr {
["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
"Unroll", "UnrollCount"]>,
EnumArgument<"State", "LoopHintState",
- ["default", "enable", "disable", "assume_safety"],
- ["Default", "Enable", "Disable", "AssumeSafety"]>,
+ ["enable", "disable", "numeric", "assume_safety", "full"],
+ ["Enable", "Disable", "Numeric", "AssumeSafety", "Full"]>,
ExprArgument<"Value">];
let AdditionalMembers = [{
@@ -1991,17 +2104,15 @@ def LoopHint : Attr {
unsigned SpellingIndex = getSpellingListIndex();
// For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
// "nounroll" is already emitted as the pragma name.
- if (SpellingIndex == Pragma_nounroll) {
- OS << "\n";
+ if (SpellingIndex == Pragma_nounroll)
return;
- }
else if (SpellingIndex == Pragma_unroll) {
- OS << getValueString(Policy) << "\n";
+ OS << getValueString(Policy);
return;
}
assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
- OS << getOptionName(option) << getValueString(Policy) << "\n";
+ OS << getOptionName(option) << getValueString(Policy);
}
// Return a string containing the loop hint argument including the
@@ -2010,13 +2121,12 @@ def LoopHint : Attr {
std::string ValueName;
llvm::raw_string_ostream OS(ValueName);
OS << "(";
- if (option == VectorizeWidth || option == InterleaveCount ||
- option == UnrollCount)
+ if (state == Numeric)
value->printPretty(OS, nullptr, Policy);
- else if (state == Default)
- return "";
else if (state == Enable)
- OS << (option == Unroll ? "full" : "enable");
+ OS << "enable";
+ else if (state == Full)
+ OS << "full";
else if (state == AssumeSafety)
OS << "assume_safety";
else
@@ -2031,7 +2141,7 @@ def LoopHint : Attr {
if (SpellingIndex == Pragma_nounroll)
return "#pragma nounroll";
else if (SpellingIndex == Pragma_unroll)
- return "#pragma unroll" + getValueString(Policy);
+ return "#pragma unroll" + (option == UnrollCount ? getValueString(Policy) : "");
assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
return getOptionName(option) + getValueString(Policy);
@@ -2054,3 +2164,9 @@ def OMPThreadPrivateDecl : InheritableAttr {
let SemaHandler = 0;
let Documentation = [Undocumented];
}
+
+def InternalLinkage : InheritableAttr {
+ let Spellings = [GNU<"internal_linkage">, CXX11<"clang", "internal_linkage">];
+ let Subjects = SubjectList<[Var, Function, CXXRecord]>;
+ let Documentation = [InternalLinkageDocs];
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td b/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td
index 4866016..2567d55 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td
@@ -181,9 +181,9 @@ to enforce the provided alignment assumption.
def EnableIfDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
-.. Note:: Some features of this attribute are experimental. The meaning of
- multiple enable_if attributes on a single declaration is subject to change in
- a future version of clang. Also, the ABI is not standardized and the name
+.. Note:: Some features of this attribute are experimental. The meaning of
+ multiple enable_if attributes on a single declaration is subject to change in
+ a future version of clang. Also, the ABI is not standardized and the name
mangling may change in future versions. To avoid that, use asm labels.
The ``enable_if`` attribute can be placed on function declarations to control
@@ -263,6 +263,103 @@ Query for this feature with ``__has_attribute(enable_if)``.
}];
}
+def PassObjectSizeDocs : Documentation {
+ let Category = DocCatVariable; // Technically it's a parameter doc, but eh.
+ let Content = [{
+.. Note:: The mangling of functions with parameters that are annotated with
+ ``pass_object_size`` is subject to change. You can get around this by
+ using ``__asm__("foo")`` to explicitly name your functions, thus preserving
+ your ABI; also, non-overloadable C functions with ``pass_object_size`` are
+ not mangled.
+
+The ``pass_object_size(Type)`` attribute can be placed on function parameters to
+instruct clang to call ``__builtin_object_size(param, Type)`` at each callsite
+of said function, and implicitly pass the result of this call in as an invisible
+argument of type ``size_t`` directly after the parameter annotated with
+``pass_object_size``. Clang will also replace any calls to
+``__builtin_object_size(param, Type)`` in the function by said implicit
+parameter.
+
+Example usage:
+
+.. code-block:: c
+
+ int bzero1(char *const p __attribute__((pass_object_size(0))))
+ __attribute__((noinline)) {
+ int i = 0;
+ for (/**/; i < (int)__builtin_object_size(p, 0); ++i) {
+ p[i] = 0;
+ }
+ return i;
+ }
+
+ int main() {
+ char chars[100];
+ int n = bzero1(&chars[0]);
+ assert(n == sizeof(chars));
+ return 0;
+ }
+
+If successfully evaluating ``__builtin_object_size(param, Type)`` at the
+callsite is not possible, then the "failed" value is passed in. So, using the
+definition of ``bzero1`` from above, the following code would exit cleanly:
+
+.. code-block:: c
+
+ int main2(int argc, char *argv[]) {
+ int n = bzero1(argv);
+ assert(n == -1);
+ return 0;
+ }
+
+``pass_object_size`` plays a part in overload resolution. If two overload
+candidates are otherwise equally good, then the overload with one or more
+parameters with ``pass_object_size`` is preferred. This implies that the choice
+between two identical overloads both with ``pass_object_size`` on one or more
+parameters will always be ambiguous; for this reason, having two such overloads
+is illegal. For example:
+
+.. code-block:: c++
+
+ #define PS(N) __attribute__((pass_object_size(N)))
+ // OK
+ void Foo(char *a, char *b); // Overload A
+ // OK -- overload A has no parameters with pass_object_size.
+ void Foo(char *a PS(0), char *b PS(0)); // Overload B
+ // Error -- Same signature (sans pass_object_size) as overload B, and both
+ // overloads have one or more parameters with the pass_object_size attribute.
+ void Foo(void *a PS(0), void *b);
+
+ // OK
+ void Bar(void *a PS(0)); // Overload C
+ // OK
+ void Bar(char *c PS(1)); // Overload D
+
+ void main() {
+ char known[10], *unknown;
+ Foo(unknown, unknown); // Calls overload B
+ Foo(known, unknown); // Calls overload B
+ Foo(unknown, known); // Calls overload B
+ Foo(known, known); // Calls overload B
+
+ Bar(known); // Calls overload D
+ Bar(unknown); // Calls overload D
+ }
+
+Currently, ``pass_object_size`` is a bit restricted in terms of its usage:
+
+* Only one use of ``pass_object_size`` is allowed per parameter.
+
+* It is an error to take the address of a function with ``pass_object_size`` on
+ any of its parameters. If you wish to do this, you can create an overload
+ without ``pass_object_size`` on any parameters.
+
+* It is an error to apply the ``pass_object_size`` attribute to parameters that
+ are not pointers. Additionally, any parameter that ``pass_object_size`` is
+ applied to must be marked ``const`` at its function's definition.
+ }];
+}
+
def OverloadableDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -580,6 +677,14 @@ are:
Apple's Mac OS X operating system. The minimum deployment target is
specified by the ``-mmacosx-version-min=*version*`` command-line argument.
+``tvos``
+ Apple's tvOS operating system. The minimum deployment target is specified by
+ the ``-mtvos-version-min=*version*`` command-line argument.
+
+``watchos``
+ Apple's watchOS operating system. The minimum deployment target is specified by
+ the ``-mwatchos-version-min=*version*`` command-line argument.
+
A declaration can be used even when deploying back to a platform version prior
to when the declaration was introduced. When this happens, the declaration is
`weakly linked
@@ -706,6 +811,46 @@ The semantics are as follows:
}];
}
+def MipsInterruptDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Clang supports the GNU style ``__attribute__((interrupt("ARGUMENT")))`` attribute on
+MIPS targets. This attribute may be attached to a function definition and instructs
+the backend to generate appropriate function entry/exit code so that it can be used
+directly as an interrupt service routine.
+
+By default, the compiler will produce a function prologue and epilogue suitable for
+an interrupt service routine that handles an External Interrupt Controller (eic)
+generated interrupt. This behaviour can be explicitly requested with the "eic"
+argument.
+
+Otherwise, for use with vectored interrupt mode, the argument passed should be
+of the form "vector=LEVEL" where LEVEL is one of the following values:
+"sw0", "sw1", "hw0", "hw1", "hw2", "hw3", "hw4", "hw5". The compiler will
+then set the interrupt mask to the corresponding level which will mask all
+interrupts up to and including the argument.
+
+The semantics are as follows:
+
+- The prologue is modified so that the Exception Program Counter (EPC) and
+ Status coprocessor registers are saved to the stack. The interrupt mask is
+ set so that the function can only be interrupted by a higher priority
+ interrupt. The epilogue will restore the previous values of EPC and Status.
+
+- The prologue and epilogue are modified to save and restore all non-kernel
+ registers as necessary.
+
+- The FPU is disabled in the prologue, as the floating pointer registers are not
+ spilled to the stack.
+
+- The function return sequence is changed to use an exception return instruction.
+
+- The parameter sets the interrupt mask for the function corresponding to the
+ interrupt level specified. If no mask is specified the interrupt mask
+ defaults to "eic".
+ }];
+}
+
def TargetDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -1328,7 +1473,7 @@ def MSNoVTableDocs : Documentation {
let Content = [{
This attribute can be added to a class declaration or definition to signal to
the compiler that constructors and destructors will not reference the virtual
-function table.
+function table. It is only supported when using the Microsoft C++ ABI.
}];
}
@@ -1371,7 +1516,9 @@ Loop unrolling optimization hints can be specified with ``#pragma unroll`` and
do-while, or c++11 range-based for loop.
Specifying ``#pragma unroll`` without a parameter directs the loop unroller to
-attempt to fully unroll the loop if the trip count is known at compile time:
+attempt to fully unroll the loop if the trip count is known at compile time and
+attempt to partially unroll the loop if the trip count is not known at compile
+time:
.. code-block:: c++
@@ -1439,7 +1586,6 @@ More details can be found in the OpenCL C language Spec v2.0, Section 6.5.
def OpenCLAddressSpaceGenericDocs : Documentation {
let Category = DocOpenCLAddressSpaces;
- let Heading = "__generic(generic)";
let Content = [{
The generic address space attribute is only available with OpenCL v2.0 and later.
It can be used with pointer types. Variables in global and local scope and
@@ -1452,7 +1598,6 @@ spaces.
def OpenCLAddressSpaceConstantDocs : Documentation {
let Category = DocOpenCLAddressSpaces;
- let Heading = "__constant(constant)";
let Content = [{
The constant address space attribute signals that an object is located in
a constant (non-modifiable) memory region. It is available to all work items.
@@ -1464,7 +1609,6 @@ have an initializer.
def OpenCLAddressSpaceGlobalDocs : Documentation {
let Category = DocOpenCLAddressSpaces;
- let Heading = "__global(global)";
let Content = [{
The global address space attribute specifies that an object is allocated in
global memory, which is accessible by all work items. The content stored in this
@@ -1477,7 +1621,6 @@ scope) variables and static local variable as well.
def OpenCLAddressSpaceLocalDocs : Documentation {
let Category = DocOpenCLAddressSpaces;
- let Heading = "__local(local)";
let Content = [{
The local address space specifies that an object is allocated in the local (work
group) memory area, which is accessible to all work items in the same work
@@ -1490,7 +1633,6 @@ space are allowed. Local address space variables cannot have an initializer.
def OpenCLAddressSpacePrivateDocs : Documentation {
let Category = DocOpenCLAddressSpaces;
- let Heading = "__private(private)";
let Content = [{
The private address space specifies that an object is allocated in the private
(work item) memory. Other work items cannot access the same memory area and its
@@ -1534,7 +1676,6 @@ In Objective-C, there is an alternate spelling for the nullability qualifiers th
def TypeNonNullDocs : Documentation {
let Category = NullabilityDocs;
- let Heading = "_Nonnull";
let Content = [{
The ``_Nonnull`` nullability qualifier indicates that null is not a meaningful value for a value of the ``_Nonnull`` pointer type. For example, given a declaration such as:
@@ -1548,7 +1689,6 @@ a caller of ``fetch`` should not provide a null value, and the compiler will pro
def TypeNullableDocs : Documentation {
let Category = NullabilityDocs;
- let Heading = "_Nullable";
let Content = [{
The ``_Nullable`` nullability qualifier indicates that a value of the ``_Nullable`` pointer type can be null. For example, given:
@@ -1562,7 +1702,6 @@ a caller of ``fetch_or_zero`` can provide null.
def TypeNullUnspecifiedDocs : Documentation {
let Category = NullabilityDocs;
- let Heading = "_Null_unspecified";
let Content = [{
The ``_Null_unspecified`` nullability qualifier indicates that neither the ``_Nonnull`` nor ``_Nullable`` qualifiers make sense for a particular pointer type. It is used primarily to indicate that the role of null with specific pointers in a nullability-annotated header is unclear, e.g., due to overly-complex implementations or historical factors with a long-lived API.
}];
@@ -1570,7 +1709,6 @@ The ``_Null_unspecified`` nullability qualifier indicates that neither the ``_No
def NonNullDocs : Documentation {
let Category = NullabilityDocs;
- let Heading = "nonnull";
let Content = [{
The ``nonnull`` attribute indicates that some function parameters must not be null, and can be used in several different ways. It's original usage (`from GCC <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes>`_) is as a function (or Objective-C method) attribute that specifies which parameters of the function are nonnull in a comma-separated list. For example:
@@ -1600,7 +1738,6 @@ Note that the ``nonnull`` attribute indicates that passing null to a non-null pa
def ReturnsNonNullDocs : Documentation {
let Category = NullabilityDocs;
- let Heading = "returns_nonnull";
let Content = [{
The ``returns_nonnull`` attribute indicates that a particular function (or Objective-C method) always returns a non-null pointer. For example, a particular system ``malloc`` might be defined to terminate a process when memory is not available rather than returning a null pointer:
@@ -1611,3 +1748,114 @@ The ``returns_nonnull`` attribute indicates that a particular function (or Objec
The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable
}];
}
+
+def NoAliasDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``noalias`` attribute indicates that the only memory accesses inside
+function are loads and stores from objects pointed to by its pointer-typed
+arguments, with arbitrary offsets.
+ }];
+}
+
+def NotTailCalledDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``not_tail_called`` attribute prevents tail-call optimization on statically bound calls. It has no effect on indirect calls. Virtual functions, objective-c methods, and functions marked as ``always_inline`` cannot be marked as ``not_tail_called``.
+
+For example, it prevents tail-call optimization in the following case:
+
+ .. code-block: c
+
+ int __attribute__((not_tail_called)) foo1(int);
+
+ int foo2(int a) {
+ return foo1(a); // No tail-call optimization on direct calls.
+ }
+
+However, it doesn't prevent tail-call optimization in this case:
+
+ .. code-block: c
+
+ int __attribute__((not_tail_called)) foo1(int);
+
+ int foo2(int a) {
+ int (*fn)(int) = &foo1;
+
+ // not_tail_called has no effect on an indirect call even if the call can be
+ // resolved at compile time.
+ return (*fn)(a);
+ }
+
+Marking virtual functions as ``not_tail_called`` is an error:
+
+ .. code-block: c++
+
+ class Base {
+ public:
+ // not_tail_called on a virtual function is an error.
+ [[clang::not_tail_called]] virtual int foo1();
+
+ virtual int foo2();
+
+ // Non-virtual functions can be marked ``not_tail_called``.
+ [[clang::not_tail_called]] int foo3();
+ };
+
+ class Derived1 : public Base {
+ public:
+ int foo1() override;
+
+ // not_tail_called on a virtual function is an error.
+ [[clang::not_tail_called]] int foo2() override;
+ };
+ }];
+}
+
+def InternalLinkageDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``internal_linkage`` attribute changes the linkage type of the declaration to internal.
+This is similar to C-style ``static``, but can be used on classes and class methods. When applied to a class definition,
+this attribute affects all methods and static data members of that class.
+This can be used to contain the ABI of a C++ library by excluding unwanted class methods from the export tables.
+ }];
+}
+
+def DisableTailCallsDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``disable_tail_calls`` attribute instructs the backend to not perform tail call optimization inside the marked function.
+
+For example:
+
+ .. code-block:: c
+
+ int callee(int);
+
+ int foo(int a) __attribute__((disable_tail_calls)) {
+ return callee(a); // This call is not tail-call optimized.
+ }
+
+Marking virtual functions as ``disable_tail_calls`` is legal.
+
+ .. code-block: c++
+
+ int callee(int);
+
+ class Base {
+ public:
+ [[clang::disable_tail_calls]] virtual int foo1() {
+ return callee(); // This call is not tail-call optimized.
+ }
+ };
+
+ class Derived1 : public Base {
+ public:
+ int foo1() override {
+ return callee(); // This call is tail-call optimized.
+ }
+ };
+
+ }];
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h b/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h
index a64dd56..a2b8684 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h
@@ -11,7 +11,7 @@
#define LLVM_CLANG_BASIC_ATTRIBUTES_H
#include "clang/Basic/LangOptions.h"
-#include "llvm/ADT/Triple.h"
+#include "clang/Basic/TargetInfo.h"
namespace clang {
@@ -31,7 +31,7 @@ enum class AttrSyntax {
/// \brief Return the version number associated with the attribute if we
/// recognize and implement the attribute specified by the given information.
int hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
- const IdentifierInfo *Attr, const llvm::Triple &T,
+ const IdentifierInfo *Attr, const TargetInfo &Target,
const LangOptions &LangOpts);
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
index bf65b5f..4f474eb 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
@@ -357,25 +357,25 @@ BUILTIN(__builtin_ctanhf, "XfXf", "Fnc")
BUILTIN(__builtin_ctanhl, "XLdXLd", "Fnc")
// FP Comparisons.
-BUILTIN(__builtin_isgreater , "i.", "nc")
-BUILTIN(__builtin_isgreaterequal, "i.", "nc")
-BUILTIN(__builtin_isless , "i.", "nc")
-BUILTIN(__builtin_islessequal , "i.", "nc")
-BUILTIN(__builtin_islessgreater , "i.", "nc")
-BUILTIN(__builtin_isunordered , "i.", "nc")
+BUILTIN(__builtin_isgreater , "i.", "Fnc")
+BUILTIN(__builtin_isgreaterequal, "i.", "Fnc")
+BUILTIN(__builtin_isless , "i.", "Fnc")
+BUILTIN(__builtin_islessequal , "i.", "Fnc")
+BUILTIN(__builtin_islessgreater , "i.", "Fnc")
+BUILTIN(__builtin_isunordered , "i.", "Fnc")
// Unary FP classification
-BUILTIN(__builtin_fpclassify, "iiiii.", "nc")
-BUILTIN(__builtin_isfinite, "i.", "nc")
-BUILTIN(__builtin_isinf, "i.", "nc")
-BUILTIN(__builtin_isinf_sign, "i.", "nc")
-BUILTIN(__builtin_isnan, "i.", "nc")
-BUILTIN(__builtin_isnormal, "i.", "nc")
+BUILTIN(__builtin_fpclassify, "iiiii.", "Fnc")
+BUILTIN(__builtin_isfinite, "i.", "Fnc")
+BUILTIN(__builtin_isinf, "i.", "Fnc")
+BUILTIN(__builtin_isinf_sign, "i.", "Fnc")
+BUILTIN(__builtin_isnan, "i.", "Fnc")
+BUILTIN(__builtin_isnormal, "i.", "Fnc")
// FP signbit builtins
-BUILTIN(__builtin_signbit, "id", "nc")
-BUILTIN(__builtin_signbitf, "if", "nc")
-BUILTIN(__builtin_signbitl, "iLd", "nc")
+BUILTIN(__builtin_signbit, "i.", "Fnc")
+BUILTIN(__builtin_signbitf, "if", "Fnc")
+BUILTIN(__builtin_signbitl, "iLd", "Fnc")
// Builtins for arithmetic.
BUILTIN(__builtin_clzs , "iUs" , "nc")
@@ -388,9 +388,9 @@ BUILTIN(__builtin_ctz , "iUi" , "nc")
BUILTIN(__builtin_ctzl , "iULi" , "nc")
BUILTIN(__builtin_ctzll, "iULLi", "nc")
// TODO: int ctzimax(uintmax_t)
-BUILTIN(__builtin_ffs , "ii" , "nc")
-BUILTIN(__builtin_ffsl , "iLi" , "nc")
-BUILTIN(__builtin_ffsll, "iLLi", "nc")
+BUILTIN(__builtin_ffs , "ii" , "Fnc")
+BUILTIN(__builtin_ffsl , "iLi" , "Fnc")
+BUILTIN(__builtin_ffsll, "iLLi", "Fnc")
BUILTIN(__builtin_parity , "iUi" , "nc")
BUILTIN(__builtin_parityl , "iULi" , "nc")
BUILTIN(__builtin_parityll, "iULLi", "nc")
@@ -414,7 +414,7 @@ BUILTIN(__builtin_va_end, "vA", "n")
BUILTIN(__builtin_va_copy, "vAA", "n")
BUILTIN(__builtin_stdarg_start, "vA.", "n")
BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nc")
-BUILTIN(__builtin_bcmp, "iv*v*z", "n")
+BUILTIN(__builtin_bcmp, "iv*v*z", "Fn")
BUILTIN(__builtin_bcopy, "vv*v*z", "n")
BUILTIN(__builtin_bzero, "vv*z", "nF")
BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:")
@@ -489,6 +489,7 @@ BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:")
BUILTIN(__builtin___vfprintf_chk, "iP*icC*a", "FP:2:")
BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:")
+BUILTIN(__builtin_unpredictable, "LiLi" , "nc")
BUILTIN(__builtin_expect, "LiLiLi" , "nc")
BUILTIN(__builtin_prefetch, "vvC*.", "nc")
BUILTIN(__builtin_readcyclecounter, "ULLi", "n")
@@ -497,7 +498,7 @@ BUILTIN(__builtin_debugtrap, "v", "n")
BUILTIN(__builtin_unreachable, "v", "nr")
BUILTIN(__builtin_shufflevector, "v." , "nc")
BUILTIN(__builtin_convertvector, "v." , "nct")
-BUILTIN(__builtin_alloca, "v*z" , "n")
+BUILTIN(__builtin_alloca, "v*z" , "Fn")
BUILTIN(__builtin_call_with_static_chain, "v.", "nt")
// "Overloaded" Atomic operator builtins. These are overloaded to support data
@@ -1216,6 +1217,9 @@ BUILTIN(__builtin_subcl, "ULiULiCULiCULiCULi*", "n")
BUILTIN(__builtin_subcll, "ULLiULLiCULLiCULLiCULLi*", "n")
// Checked Arithmetic Builtins for Security.
+BUILTIN(__builtin_add_overflow, "v.", "nt")
+BUILTIN(__builtin_sub_overflow, "v.", "nt")
+BUILTIN(__builtin_mul_overflow, "v.", "nt")
BUILTIN(__builtin_uadd_overflow, "bUiCUiCUi*", "n")
BUILTIN(__builtin_uaddl_overflow, "bULiCULiCULi*", "n")
BUILTIN(__builtin_uaddll_overflow, "bULLiCULLiCULLi*", "n")
@@ -1244,6 +1248,10 @@ BUILTIN(__builtin_operator_delete, "vv*", "n")
BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
BUILTIN(__builtin___get_unsafe_stack_ptr, "v*", "Fn")
+// Nontemporal loads/stores builtins
+BUILTIN(__builtin_nontemporal_store, "v.", "t")
+BUILTIN(__builtin_nontemporal_load, "v.", "t")
+
#undef BUILTIN
#undef LIBBUILTIN
#undef LANGBUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
index 27428ad..c0a6af9 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
@@ -16,7 +16,7 @@
#ifndef LLVM_CLANG_BASIC_BUILTINS_H
#define LLVM_CLANG_BASIC_BUILTINS_H
-#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
#include <cstring>
// VC++ defines 'alloca' as an object-like macro, which interferes with our
@@ -24,22 +24,22 @@
#undef alloca
namespace clang {
- class TargetInfo;
- class IdentifierTable;
- class ASTContext;
- class QualType;
- class LangOptions;
-
- enum LanguageID {
- GNU_LANG = 0x1, // builtin requires GNU mode.
- C_LANG = 0x2, // builtin for c only.
- CXX_LANG = 0x4, // builtin for cplusplus only.
- OBJC_LANG = 0x8, // builtin for objective-c and objective-c++
- MS_LANG = 0x10, // builtin requires MS mode.
- ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
- ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.
- ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.
- };
+class TargetInfo;
+class IdentifierTable;
+class ASTContext;
+class QualType;
+class LangOptions;
+
+enum LanguageID {
+ GNU_LANG = 0x1, // builtin requires GNU mode.
+ C_LANG = 0x2, // builtin for c only.
+ CXX_LANG = 0x4, // builtin for cplusplus only.
+ OBJC_LANG = 0x8, // builtin for objective-c and objective-c++
+ MS_LANG = 0x10, // builtin requires MS mode.
+ ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
+ ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.
+ ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.
+};
namespace Builtin {
enum ID {
@@ -51,112 +51,114 @@ enum ID {
struct Info {
const char *Name, *Type, *Attributes, *HeaderName;
- LanguageID builtin_lang;
-
- bool operator==(const Info &RHS) const {
- return !strcmp(Name, RHS.Name) &&
- !strcmp(Type, RHS.Type) &&
- !strcmp(Attributes, RHS.Attributes);
- }
- bool operator!=(const Info &RHS) const { return !(*this == RHS); }
+ LanguageID Langs;
+ const char *Features;
};
/// \brief Holds information about both target-independent and
/// target-specific builtins, allowing easy queries by clients.
+///
+/// Builtins from an optional auxiliary target are stored in
+/// AuxTSRecords. Their IDs are shifted up by TSRecords.size() and need to
+/// be translated back with getAuxBuiltinID() before use.
class Context {
- const Info *TSRecords;
- unsigned NumTSRecords;
+ llvm::ArrayRef<Info> TSRecords;
+ llvm::ArrayRef<Info> AuxTSRecords;
+
public:
- Context();
+ Context() {}
/// \brief Perform target-specific initialization
- void InitializeTarget(const TargetInfo &Target);
-
+ /// \param AuxTarget Target info to incorporate builtins from. May be nullptr.
+ void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget);
+
/// \brief Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
- void InitializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
-
- /// \brief Populate the vector with the names of all of the builtins.
- void GetBuiltinNames(SmallVectorImpl<const char *> &Names);
+ void initializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts);
/// \brief Return the identifier name for the specified builtin,
/// e.g. "__builtin_abs".
- const char *GetName(unsigned ID) const {
- return GetRecord(ID).Name;
+ const char *getName(unsigned ID) const {
+ return getRecord(ID).Name;
}
/// \brief Get the type descriptor string for the specified builtin.
- const char *GetTypeString(unsigned ID) const {
- return GetRecord(ID).Type;
+ const char *getTypeString(unsigned ID) const {
+ return getRecord(ID).Type;
+ }
+
+ /// \brief Return true if this function is a target-specific builtin
+ bool isTSBuiltin(unsigned ID) const {
+ return ID >= Builtin::FirstTSBuiltin;
}
/// \brief Return true if this function has no side effects and doesn't
/// read memory.
bool isConst(unsigned ID) const {
- return strchr(GetRecord(ID).Attributes, 'c') != nullptr;
+ return strchr(getRecord(ID).Attributes, 'c') != nullptr;
}
/// \brief Return true if we know this builtin never throws an exception.
bool isNoThrow(unsigned ID) const {
- return strchr(GetRecord(ID).Attributes, 'n') != nullptr;
+ return strchr(getRecord(ID).Attributes, 'n') != nullptr;
}
/// \brief Return true if we know this builtin never returns.
bool isNoReturn(unsigned ID) const {
- return strchr(GetRecord(ID).Attributes, 'r') != nullptr;
+ return strchr(getRecord(ID).Attributes, 'r') != nullptr;
}
/// \brief Return true if we know this builtin can return twice.
bool isReturnsTwice(unsigned ID) const {
- return strchr(GetRecord(ID).Attributes, 'j') != nullptr;
+ return strchr(getRecord(ID).Attributes, 'j') != nullptr;
}
/// \brief Returns true if this builtin does not perform the side-effects
/// of its arguments.
bool isUnevaluated(unsigned ID) const {
- return strchr(GetRecord(ID).Attributes, 'u') != nullptr;
+ return strchr(getRecord(ID).Attributes, 'u') != nullptr;
}
/// \brief Return true if this is a builtin for a libc/libm function,
/// with a "__builtin_" prefix (e.g. __builtin_abs).
bool isLibFunction(unsigned ID) const {
- return strchr(GetRecord(ID).Attributes, 'F') != nullptr;
+ return strchr(getRecord(ID).Attributes, 'F') != nullptr;
}
/// \brief Determines whether this builtin is a predefined libc/libm
/// function, such as "malloc", where we know the signature a
/// priori.
bool isPredefinedLibFunction(unsigned ID) const {
- return strchr(GetRecord(ID).Attributes, 'f') != nullptr;
+ return strchr(getRecord(ID).Attributes, 'f') != nullptr;
}
/// \brief Determines whether this builtin is a predefined compiler-rt/libgcc
/// function, such as "__clear_cache", where we know the signature a
/// priori.
bool isPredefinedRuntimeFunction(unsigned ID) const {
- return strchr(GetRecord(ID).Attributes, 'i') != nullptr;
+ return strchr(getRecord(ID).Attributes, 'i') != nullptr;
}
/// \brief Determines whether this builtin has custom typechecking.
bool hasCustomTypechecking(unsigned ID) const {
- return strchr(GetRecord(ID).Attributes, 't') != nullptr;
+ return strchr(getRecord(ID).Attributes, 't') != nullptr;
}
/// \brief Determines whether this builtin has a result or any arguments which
/// are pointer types.
bool hasPtrArgsOrResult(unsigned ID) const {
- return strchr(GetRecord(ID).Type, '*') != nullptr;
+ return strchr(getRecord(ID).Type, '*') != nullptr;
}
/// \brief Completely forget that the given ID was ever considered a builtin,
/// e.g., because the user provided a conflicting signature.
- void ForgetBuiltin(unsigned ID, IdentifierTable &Table);
+ void forgetBuiltin(unsigned ID, IdentifierTable &Table);
/// \brief If this is a library function that comes from a specific
/// header, retrieve that header name.
const char *getHeaderName(unsigned ID) const {
- return GetRecord(ID).HeaderName;
+ return getRecord(ID).HeaderName;
}
/// \brief Determine whether this builtin is like printf in its
@@ -174,14 +176,31 @@ public:
///
/// Such functions can be const when the MathErrno lang option is disabled.
bool isConstWithoutErrno(unsigned ID) const {
- return strchr(GetRecord(ID).Attributes, 'e') != nullptr;
+ return strchr(getRecord(ID).Attributes, 'e') != nullptr;
}
+ const char *getRequiredFeatures(unsigned ID) const {
+ return getRecord(ID).Features;
+ }
+
+ /// \brief Return true if builtin ID belongs to AuxTarget.
+ bool isAuxBuiltinID(unsigned ID) const {
+ return ID >= (Builtin::FirstTSBuiltin + TSRecords.size());
+ }
+
+ /// Return real buitin ID (i.e. ID it would have furing compilation
+ /// for AuxTarget).
+ unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); }
+
+ /// Returns true if this is a libc/libm function without the '__builtin_'
+ /// prefix.
+ static bool isBuiltinFunc(const char *Name);
+
private:
- const Info &GetRecord(unsigned ID) const;
+ const Info &getRecord(unsigned ID) const;
/// \brief Is this builtin supported according to the given language options?
- bool BuiltinIsSupported(const Builtin::Info &BuiltinInfo,
+ bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
const LangOptions &LangOpts);
/// \brief Helper function for isPrintfLike and isScanfLike.
@@ -190,5 +209,12 @@ private:
};
}
+
+/// \brief Kinds of BuiltinTemplateDecl.
+enum BuiltinTemplateKind : int {
+ /// \brief This names the __make_integer_seq BuiltinTemplateDecl.
+ BTK__make_integer_seq
+};
+
} // end namespace clang
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def
index 1db4c14..b440443 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -60,5 +60,6 @@ BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc")
BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc")
BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
+BUILTIN(__builtin_thread_pointer, "v*", "nc")
#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def
index c9cdb4b..3e8e2bf 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def
@@ -48,14 +48,14 @@ BUILTIN(__builtin_arm_vcvtr_f, "ffi", "nc")
BUILTIN(__builtin_arm_vcvtr_d, "fdi", "nc")
// Coprocessor
-BUILTIN(__builtin_arm_mcr, "vUiUiUiUiUiUi", "")
-BUILTIN(__builtin_arm_mcr2, "vUiUiUiUiUiUi", "")
-BUILTIN(__builtin_arm_mrc, "UiUiUiUiUiUi", "")
-BUILTIN(__builtin_arm_mrc2, "UiUiUiUiUiUi", "")
+BUILTIN(__builtin_arm_mcr, "vUIiUIiUiUIiUIiUIi", "")
+BUILTIN(__builtin_arm_mcr2, "vUIiUIiUiUIiUIiUIi", "")
+BUILTIN(__builtin_arm_mrc, "UiUIiUIiUIiUIiUIi", "")
+BUILTIN(__builtin_arm_mrc2, "UiUIiUIiUIiUIiUIi", "")
BUILTIN(__builtin_arm_cdp, "vUiUiUiUiUiUi", "")
BUILTIN(__builtin_arm_cdp2, "vUiUiUiUiUiUi", "")
-BUILTIN(__builtin_arm_mcrr, "vUiUiUiUiUi", "")
-BUILTIN(__builtin_arm_mcrr2, "vUiUiUiUiUi", "")
+BUILTIN(__builtin_arm_mcrr, "vUIiUIiUiUiUIi", "")
+BUILTIN(__builtin_arm_mcrr2, "vUIiUIiUiUiUIi", "")
// CRC32
BUILTIN(__builtin_arm_crc32b, "UiUiUc", "nc")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def
index 970f55f..3ab6413 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def
@@ -50,7 +50,7 @@ BUILTIN(__builtin_ptx_read_lanemask_ge, "i", "nc")
BUILTIN(__builtin_ptx_read_lanemask_gt, "i", "nc")
BUILTIN(__builtin_ptx_read_clock, "i", "n")
-BUILTIN(__builtin_ptx_read_clock64, "Li", "n")
+BUILTIN(__builtin_ptx_read_clock64, "LLi", "n")
BUILTIN(__builtin_ptx_read_pm0, "i", "n")
BUILTIN(__builtin_ptx_read_pm1, "i", "n")
@@ -453,6 +453,9 @@ BUILTIN(__nvvm_atom_add_gen_ll, "LLiLLiD*LLi", "n")
BUILTIN(__nvvm_atom_add_g_f, "ffD*1f", "n")
BUILTIN(__nvvm_atom_add_s_f, "ffD*3f", "n")
BUILTIN(__nvvm_atom_add_gen_f, "ffD*f", "n")
+BUILTIN(__nvvm_atom_add_g_d, "ddD*1d", "n")
+BUILTIN(__nvvm_atom_add_s_d, "ddD*3d", "n")
+BUILTIN(__nvvm_atom_add_gen_d, "ddD*d", "n")
BUILTIN(__nvvm_atom_sub_g_i, "iiD*1i", "n")
BUILTIN(__nvvm_atom_sub_s_i, "iiD*3i", "n")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def
index fdf1cb0..5681c1f2 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def
@@ -17,6 +17,8 @@
// The format of this database matches clang/Basic/Builtins.def.
+BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n")
+
// This is just a placeholder, the types and attributes are wrong.
BUILTIN(__builtin_altivec_vaddcuw, "V4UiV4UiV4Ui", "")
@@ -278,12 +280,21 @@ BUILTIN(__builtin_vsx_xvrspip, "V4fV4f", "")
BUILTIN(__builtin_vsx_xvcmpeqdp, "V2ULLiV2dV2d", "")
BUILTIN(__builtin_vsx_xvcmpeqsp, "V4UiV4fV4f", "")
+BUILTIN(__builtin_vsx_xvcmpeqdp_p, "iiV2dV2d", "")
+BUILTIN(__builtin_vsx_xvcmpeqsp_p, "iiV4fV4f", "")
+
BUILTIN(__builtin_vsx_xvcmpgedp, "V2ULLiV2dV2d", "")
BUILTIN(__builtin_vsx_xvcmpgesp, "V4UiV4fV4f", "")
+BUILTIN(__builtin_vsx_xvcmpgedp_p, "iiV2dV2d", "")
+BUILTIN(__builtin_vsx_xvcmpgesp_p, "iiV4fV4f", "")
+
BUILTIN(__builtin_vsx_xvcmpgtdp, "V2ULLiV2dV2d", "")
BUILTIN(__builtin_vsx_xvcmpgtsp, "V4UiV4fV4f", "")
+BUILTIN(__builtin_vsx_xvcmpgtdp_p, "iiV2dV2d", "")
+BUILTIN(__builtin_vsx_xvcmpgtsp_p, "iiV4fV4f", "")
+
BUILTIN(__builtin_vsx_xvrdpim, "V2dV2d", "")
BUILTIN(__builtin_vsx_xvrspim, "V4fV4f", "")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def
new file mode 100644
index 0000000..9754335
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def
@@ -0,0 +1,24 @@
+// BuiltinsWebAssembly.def - WebAssembly builtin function database -*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file defines the WebAssembly-specific builtin function database.
+/// Users of this file must define the BUILTIN macro to make use of this
+/// information.
+///
+//===----------------------------------------------------------------------===//
+
+// The format of this database matches clang/Basic/Builtins.def.
+
+// Note that memory_size is not "c" (readnone) because it must be sequenced with
+// respect to grow_memory calls.
+BUILTIN(__builtin_wasm_memory_size, "z", "n")
+BUILTIN(__builtin_wasm_grow_memory, "vz", "n")
+
+#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
index 1cd8973..f738cc1 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
@@ -14,14 +14,15 @@
// The format of this database matches clang/Basic/Builtins.def.
-// FIXME: In GCC, these builtins are defined depending on whether support for
-// MMX/SSE/etc is turned on. We should do this too.
-
// FIXME: Ideally we would be able to pull this information from what
// LLVM already knows about X86 builtins. We need to match the LLVM
// definition anyway, since code generation will lower to the
// intrinsic if one exists.
+#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
+# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
// FIXME: Are these nothrow/const?
// Miscellaneous builtin for checking x86 cpu features.
@@ -29,35 +30,53 @@
// can use it?
BUILTIN(__builtin_cpu_supports, "bcC*", "nc")
+// Win64-compatible va_list functions
+BUILTIN(__builtin_ms_va_start, "vc*&.", "nt")
+BUILTIN(__builtin_ms_va_end, "vc*&", "n")
+BUILTIN(__builtin_ms_va_copy, "vc*&c*&", "n")
+
+// Undefined Values
+//
+TARGET_BUILTIN(__builtin_ia32_undef128, "V2d", "nc", "")
+TARGET_BUILTIN(__builtin_ia32_undef256, "V4d", "nc", "")
+TARGET_BUILTIN(__builtin_ia32_undef512, "V8d", "nc", "")
+
+// FLAGS
+//
+TARGET_BUILTIN(__builtin_ia32_readeflags_u32, "Ui", "n", "")
+TARGET_BUILTIN(__builtin_ia32_readeflags_u64, "ULLi", "n", "")
+TARGET_BUILTIN(__builtin_ia32_writeeflags_u32, "vUi", "n", "")
+TARGET_BUILTIN(__builtin_ia32_writeeflags_u64, "vULLi", "n", "")
+
// 3DNow!
//
-BUILTIN(__builtin_ia32_femms, "v", "")
-BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "nc")
-BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "nc")
-BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "nc")
-BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "nc")
+TARGET_BUILTIN(__builtin_ia32_femms, "v", "", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "nc", "3dnow")
// 3DNow! Extensions (3dnowa).
-BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "nc")
-BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "nc")
-BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "nc")
-BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "nc")
-BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc")
+TARGET_BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "nc", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "nc", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "nc", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "nc", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "nc", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc", "3dnowa")
// MMX
//
@@ -67,1155 +86,1492 @@ BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc")
// FIXME: _mm_prefetch must be a built-in because it takes a compile-time constant
// argument and our prior approach of using a #define to the current built-in
// doesn't work in the presence of re-declaration of _mm_prefetch for windows.
-BUILTIN(_mm_prefetch, "vcC*i", "nc")
-BUILTIN(__builtin_ia32_emms, "v", "")
-BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "")
-BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "")
-BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "")
-BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "")
-BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "")
-BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "")
-BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "")
-BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "")
-BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "")
-BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "")
-BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "")
-BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "")
-BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "")
-BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "")
-BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "")
-BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "")
-BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "")
-BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "")
-BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "")
-BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "")
-BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
-BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
-BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
-BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
-BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
-BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
-BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "")
-BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "")
-BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "")
-BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "")
+TARGET_BUILTIN(_mm_prefetch, "vcC*i", "nc", "mmx")
+TARGET_BUILTIN(__builtin_ia32_emms, "v", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "", "mmx")
// MMX2 (MMX+SSE) intrinsics
-BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "")
-BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "")
-BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "")
-BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
-BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
-BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "")
+TARGET_BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "", "sse")
// MMX+SSE2
-BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "")
-BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "")
-BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "")
-BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "")
-BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "")
-BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "", "sse2")
// MMX+SSSE3
-BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "")
-BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "")
-BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "")
-BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "")
-BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "")
+TARGET_BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "", "ssse3")
// SSE intrinsics.
-BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_comile, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_comige, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "")
-BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "")
-BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "")
-BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "")
-BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "")
-BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "")
-BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "")
-BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "")
-BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_pmaddubsw128, "V8sV16cV16c", "")
-BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "")
-BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "")
-BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "")
-BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "")
-BUILTIN(__builtin_ia32_stmxcsr, "Ui", "")
-BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "")
-BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "")
-BUILTIN(__builtin_ia32_storeups, "vf*V4f", "")
-BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "")
-BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "")
-BUILTIN(__builtin_ia32_movmskps, "iV4f", "")
-BUILTIN(__builtin_ia32_movntps, "vf*V4f", "")
-BUILTIN(__builtin_ia32_sfence, "v", "")
-BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "")
-BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "")
-BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "")
-BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "")
-BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "")
-BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "")
-BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "")
-BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "")
-BUILTIN(__builtin_ia32_movmskpd, "iV2d", "")
-BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "")
-BUILTIN(__builtin_ia32_movnti, "vi*i", "")
-BUILTIN(__builtin_ia32_movnti64, "vLLi*LLi", "")
-BUILTIN(__builtin_ia32_movntpd, "vd*V2d", "")
-BUILTIN(__builtin_ia32_movntdq, "vV2LLi*V2LLi", "")
-BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "")
-BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "")
-BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "")
-BUILTIN(__builtin_ia32_cvtdq2pd, "V2dV4i", "")
-BUILTIN(__builtin_ia32_cvtdq2ps, "V4fV4i", "")
-BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "")
-BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "")
-BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "")
-BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "")
-BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "")
-BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "")
-BUILTIN(__builtin_ia32_cvtps2pd, "V2dV4f", "")
-BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "")
-BUILTIN(__builtin_ia32_clflush, "vvC*", "")
-BUILTIN(__builtin_ia32_lfence, "v", "")
-BUILTIN(__builtin_ia32_mfence, "v", "")
-BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "")
-BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "")
-BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "")
-BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "")
-BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "")
-BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "")
-BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "")
-BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "")
-BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "")
-BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "")
-BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "")
-BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
-BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
-BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
-BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "")
-BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "")
-
-BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "")
-BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "")
-BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "")
-
-BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "")
-BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_pmovsxbd128, "V4iV16c", "")
-BUILTIN(__builtin_ia32_pmovsxbq128, "V2LLiV16c", "")
-BUILTIN(__builtin_ia32_pmovsxbw128, "V8sV16c", "")
-BUILTIN(__builtin_ia32_pmovsxdq128, "V2LLiV4i", "")
-BUILTIN(__builtin_ia32_pmovsxwd128, "V4iV8s", "")
-BUILTIN(__builtin_ia32_pmovsxwq128, "V2LLiV8s", "")
-BUILTIN(__builtin_ia32_pmovzxbd128, "V4iV16c", "")
-BUILTIN(__builtin_ia32_pmovzxbq128, "V2LLiV16c", "")
-BUILTIN(__builtin_ia32_pmovzxbw128, "V8sV16c", "")
-BUILTIN(__builtin_ia32_pmovzxdq128, "V2LLiV4i", "")
-BUILTIN(__builtin_ia32_pmovzxwd128, "V4iV8s", "")
-BUILTIN(__builtin_ia32_pmovzxwq128, "V2LLiV8s", "")
-BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "")
-BUILTIN(__builtin_ia32_pmulld128, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_roundps, "V4fV4fi", "")
-BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fi", "")
-BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2di", "")
-BUILTIN(__builtin_ia32_roundpd, "V2dV2di", "")
-BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "")
-BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "")
-BUILTIN(__builtin_ia32_movntdqa, "V2LLiV2LLi*", "")
-BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "")
-BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "")
+TARGET_BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_comile, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_comige, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "", "sse")
+
+TARGET_BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "", "sse2")
+
+TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "", "sse")
+
+TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "", "sse2")
+
+TARGET_BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw128, "V8sV16cV16c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "", "ssse3")
+
+TARGET_BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_stmxcsr, "Ui", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_storeups, "vf*V4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_movmskps, "iV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_movntps, "vf*V4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_sfence, "v", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "", "sse")
+
+TARGET_BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movmskpd, "iV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movnti, "vi*i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movnti64, "vLLi*LLi", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movntpd, "vd*V2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movntdq, "vV2LLi*V2LLi", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2pd, "V2dV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2ps, "V4fV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pd, "V2dV4f", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_clflush, "vvC*", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_lfence, "v", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_mfence, "v", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pause, "v", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "", "sse2")
+
+TARGET_BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_mwait, "vUiUi", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "", "sse3")
+
+TARGET_BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "", "ssse3")
+
+TARGET_BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "", "sse4.1")
+
+TARGET_BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbd128, "V4iV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbq128, "V2LLiV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbw128, "V8sV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxdq128, "V2LLiV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxwd128, "V4iV8s", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxwq128, "V2LLiV8s", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmulld128, "V4iV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundps, "V4fV4fIi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fIi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2dIi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundpd, "V2dV2dIi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_movntdqa, "V2LLiV2LLiC*", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "", "sse4.1")
// SSE 4.2
-BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "")
-BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "")
-BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "")
-BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","")
-
-BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","")
-BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","")
-BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","")
-BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","")
-BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","")
-BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","")
-BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","")
-BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","")
-BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","")
-BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","")
-
-BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "")
-BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "")
-BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "")
-BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "")
+TARGET_BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","", "sse4.2")
+
+TARGET_BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","", "sse4.2")
+
+TARGET_BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "", "sse4.2")
// SSE4a
-BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "")
-BUILTIN(__builtin_ia32_extrq, "V2LLiV2LLiV16c", "")
-BUILTIN(__builtin_ia32_insertqi, "V2LLiV2LLiV2LLiIcIc", "")
-BUILTIN(__builtin_ia32_insertq, "V2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_movntsd, "vd*V2d", "")
-BUILTIN(__builtin_ia32_movntss, "vf*V4f", "")
+TARGET_BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_extrq, "V2LLiV2LLiV16c", "", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_insertqi, "V2LLiV2LLiV2LLiIcIc", "", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_insertq, "V2LLiV2LLiV2LLi", "", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_movntsd, "vd*V2d", "", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_movntss, "vf*V4f", "", "sse4a")
// AES
-BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "")
+TARGET_BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "", "aes")
+TARGET_BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "", "aes")
// CLMUL
-BUILTIN(__builtin_ia32_pclmulqdq128, "V2LLiV2LLiV2LLiIc", "")
+TARGET_BUILTIN(__builtin_ia32_pclmulqdq128, "V2LLiV2LLiV2LLiIc", "", "pclmul")
// AVX
-BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "")
-BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "")
-BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "")
-BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "")
-BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "")
-BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "")
-BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "")
-BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "")
-BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "")
-BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "")
-BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "")
-BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "")
-BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "")
-BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "")
-BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "")
-BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "")
-BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "")
-BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "")
-BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "")
-BUILTIN(__builtin_ia32_cvtdq2pd256, "V4dV4i", "")
-BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "")
-BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "")
-BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "")
-BUILTIN(__builtin_ia32_cvtps2pd256, "V4dV4f", "")
-BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "")
-BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "")
-BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "")
-BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIc", "")
-BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIc", "")
-BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIc", "")
-BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "")
-BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "")
-BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "")
-BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "")
-BUILTIN(__builtin_ia32_roundpd256, "V4dV4dIi", "")
-BUILTIN(__builtin_ia32_roundps256, "V8fV8fIi", "")
-BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "")
-BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "")
-BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "")
-BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "")
-BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "")
-BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "")
-BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "")
-BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "")
-BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "")
-BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "")
-BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "")
-BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "")
-BUILTIN(__builtin_ia32_movmskps256, "iV8f", "")
-BUILTIN(__builtin_ia32_vzeroall, "v", "")
-BUILTIN(__builtin_ia32_vzeroupper, "v", "")
-BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "")
-BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "")
-BUILTIN(__builtin_ia32_storeupd256, "vd*V4d", "")
-BUILTIN(__builtin_ia32_storeups256, "vf*V8f", "")
-BUILTIN(__builtin_ia32_storedqu256, "vc*V32c", "")
-BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "")
-BUILTIN(__builtin_ia32_movntdq256, "vV4LLi*V4LLi", "")
-BUILTIN(__builtin_ia32_movntpd256, "vd*V4d", "")
-BUILTIN(__builtin_ia32_movntps256, "vf*V8f", "")
-BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2d", "")
-BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4f", "")
-BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4d", "")
-BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8f", "")
-BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2dV2d", "")
-BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4fV4f", "")
-BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4dV4d", "")
-BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8fV8f", "")
+TARGET_BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2pd256, "V4dV4i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pd256, "V4dV4f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_roundpd256, "V4dV4dIi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_roundps256, "V8fV8fIi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_movmskps256, "iV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vzeroall, "v", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vzeroupper, "v", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_storeupd256, "vd*V4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_storeups256, "vf*V8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_storedqu256, "vc*V32c", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_movntdq256, "vV4LLi*V4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_movntpd256, "vd*V4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_movntps256, "vf*V8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2LLiV2d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4iV4f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4LLiV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8iV8f", "", "avx")
// AVX2
-BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "")
-BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "")
-BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "")
-BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "")
-BUILTIN(__builtin_ia32_packsswb256, "V32cV16sV16s", "")
-BUILTIN(__builtin_ia32_packssdw256, "V16sV8iV8i", "")
-BUILTIN(__builtin_ia32_packuswb256, "V32cV16sV16s", "")
-BUILTIN(__builtin_ia32_packusdw256, "V16sV8iV8i", "")
-BUILTIN(__builtin_ia32_paddsb256, "V32cV32cV32c", "")
-BUILTIN(__builtin_ia32_paddsw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_psubsb256, "V32cV32cV32c", "")
-BUILTIN(__builtin_ia32_psubsw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_paddusb256, "V32cV32cV32c", "")
-BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "")
-BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIc", "")
-BUILTIN(__builtin_ia32_pavgb256, "V32cV32cV32c", "")
-BUILTIN(__builtin_ia32_pavgw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "")
-BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "")
-BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_phsubw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_phsubd256, "V8iV8iV8i", "")
-BUILTIN(__builtin_ia32_phsubsw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_pmaddubsw256, "V16sV32cV32c", "")
-BUILTIN(__builtin_ia32_pmaddwd256, "V8iV16sV16s", "")
-BUILTIN(__builtin_ia32_pmaxub256, "V32cV32cV32c", "")
-BUILTIN(__builtin_ia32_pmaxuw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_pmaxud256, "V8iV8iV8i", "")
-BUILTIN(__builtin_ia32_pmaxsb256, "V32cV32cV32c", "")
-BUILTIN(__builtin_ia32_pmaxsw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_pmaxsd256, "V8iV8iV8i", "")
-BUILTIN(__builtin_ia32_pminub256, "V32cV32cV32c", "")
-BUILTIN(__builtin_ia32_pminuw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_pminud256, "V8iV8iV8i", "")
-BUILTIN(__builtin_ia32_pminsb256, "V32cV32cV32c", "")
-BUILTIN(__builtin_ia32_pminsw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_pminsd256, "V8iV8iV8i", "")
-BUILTIN(__builtin_ia32_pmovmskb256, "iV32c", "")
-BUILTIN(__builtin_ia32_pmovsxbw256, "V16sV16c", "")
-BUILTIN(__builtin_ia32_pmovsxbd256, "V8iV16c", "")
-BUILTIN(__builtin_ia32_pmovsxbq256, "V4LLiV16c", "")
-BUILTIN(__builtin_ia32_pmovsxwd256, "V8iV8s", "")
-BUILTIN(__builtin_ia32_pmovsxwq256, "V4LLiV8s", "")
-BUILTIN(__builtin_ia32_pmovsxdq256, "V4LLiV4i", "")
-BUILTIN(__builtin_ia32_pmovzxbw256, "V16sV16c", "")
-BUILTIN(__builtin_ia32_pmovzxbd256, "V8iV16c", "")
-BUILTIN(__builtin_ia32_pmovzxbq256, "V4LLiV16c", "")
-BUILTIN(__builtin_ia32_pmovzxwd256, "V8iV8s", "")
-BUILTIN(__builtin_ia32_pmovzxwq256, "V4LLiV8s", "")
-BUILTIN(__builtin_ia32_pmovzxdq256, "V4LLiV4i", "")
-BUILTIN(__builtin_ia32_pmuldq256, "V4LLiV8iV8i", "")
-BUILTIN(__builtin_ia32_pmulhrsw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_pmulhuw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_pmulhw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_pmuludq256, "V4LLiV8iV8i", "")
-BUILTIN(__builtin_ia32_psadbw256, "V4LLiV32cV32c", "")
-BUILTIN(__builtin_ia32_pshufb256, "V32cV32cV32c", "")
-BUILTIN(__builtin_ia32_psignb256, "V32cV32cV32c", "")
-BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "")
-BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "")
-BUILTIN(__builtin_ia32_pslldqi256, "V4LLiV4LLiIi", "")
-BUILTIN(__builtin_ia32_psllwi256, "V16sV16si", "")
-BUILTIN(__builtin_ia32_psllw256, "V16sV16sV8s", "")
-BUILTIN(__builtin_ia32_pslldi256, "V8iV8ii", "")
-BUILTIN(__builtin_ia32_pslld256, "V8iV8iV4i", "")
-BUILTIN(__builtin_ia32_psllqi256, "V4LLiV4LLii", "")
-BUILTIN(__builtin_ia32_psllq256, "V4LLiV4LLiV2LLi", "")
-BUILTIN(__builtin_ia32_psrawi256, "V16sV16si", "")
-BUILTIN(__builtin_ia32_psraw256, "V16sV16sV8s", "")
-BUILTIN(__builtin_ia32_psradi256, "V8iV8ii", "")
-BUILTIN(__builtin_ia32_psrad256, "V8iV8iV4i", "")
-BUILTIN(__builtin_ia32_psrldqi256, "V4LLiV4LLiIi", "")
-BUILTIN(__builtin_ia32_psrlwi256, "V16sV16si", "")
-BUILTIN(__builtin_ia32_psrlw256, "V16sV16sV8s", "")
-BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "")
-BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "")
-BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "")
-BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "")
-BUILTIN(__builtin_ia32_movntdqa256, "V4LLiV4LLi*", "")
-BUILTIN(__builtin_ia32_vbroadcastss_ps, "V4fV4f", "")
-BUILTIN(__builtin_ia32_vbroadcastss_ps256, "V8fV4f", "")
-BUILTIN(__builtin_ia32_vbroadcastsd_pd256, "V4dV2d", "")
-BUILTIN(__builtin_ia32_pbroadcastb256, "V32cV16c", "")
-BUILTIN(__builtin_ia32_pbroadcastw256, "V16sV8s", "")
-BUILTIN(__builtin_ia32_pbroadcastd256, "V8iV4i", "")
-BUILTIN(__builtin_ia32_pbroadcastq256, "V4LLiV2LLi", "")
-BUILTIN(__builtin_ia32_pbroadcastb128, "V16cV16c", "")
-BUILTIN(__builtin_ia32_pbroadcastw128, "V8sV8s", "")
-BUILTIN(__builtin_ia32_pbroadcastd128, "V4iV4i", "")
-BUILTIN(__builtin_ia32_pbroadcastq128, "V2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "")
-BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8f", "")
-BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "")
-BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "")
-BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "")
-BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "")
-BUILTIN(__builtin_ia32_maskloadq, "V2LLiV2LLiC*V2LLi", "")
-BUILTIN(__builtin_ia32_maskstored256, "vV8i*V8iV8i", "")
-BUILTIN(__builtin_ia32_maskstoreq256, "vV4LLi*V4LLiV4LLi", "")
-BUILTIN(__builtin_ia32_maskstored, "vV4i*V4iV4i", "")
-BUILTIN(__builtin_ia32_maskstoreq, "vV2LLi*V2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_psllv8si, "V8iV8iV8i", "")
-BUILTIN(__builtin_ia32_psllv4si, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_psllv4di, "V4LLiV4LLiV4LLi", "")
-BUILTIN(__builtin_ia32_psllv2di, "V2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_psrav8si, "V8iV8iV8i", "")
-BUILTIN(__builtin_ia32_psrav4si, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_psrlv8si, "V8iV8iV8i", "")
-BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "")
-BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "")
+TARGET_BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packsswb256, "V32cV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packssdw256, "V16sV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packuswb256, "V32cV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packusdw256, "V16sV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddsb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubsb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddusb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pavgb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pavgw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phsubw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phsubd256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phsubsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw256, "V16sV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd256, "V8iV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxub256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxud256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminub256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminuw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminud256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminsb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminsd256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovmskb256, "iV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxbw256, "V16sV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxbd256, "V8iV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxbq256, "V4LLiV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxwd256, "V8iV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxwq256, "V4LLiV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxdq256, "V4LLiV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbw256, "V16sV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbd256, "V8iV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbq256, "V4LLiV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxwd256, "V8iV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxwq256, "V4LLiV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxdq256, "V4LLiV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmuldq256, "V4LLiV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmulhw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmuludq256, "V4LLiV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psadbw256, "V4LLiV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pshufb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psignb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pslldqi256, "V4LLiV4LLiIi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllwi256, "V16sV16si", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllw256, "V16sV16sV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pslldi256, "V8iV8ii", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pslld256, "V8iV8iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllqi256, "V4LLiV4LLii", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllq256, "V4LLiV4LLiV2LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrawi256, "V16sV16si", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psraw256, "V16sV16sV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psradi256, "V8iV8ii", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrad256, "V8iV8iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrldqi256, "V4LLiV4LLiIi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlwi256, "V16sV16si", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlw256, "V16sV16sV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_movntdqa256, "V4LLiV4LLiC*", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadq, "V2LLiV2LLiC*V2LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstored256, "vV8i*V8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstoreq256, "vV4LLi*V4LLiV4LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstored, "vV4i*V4iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstoreq, "vV2LLi*V2LLiV2LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv8si, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv4si, "V4iV4iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv4di, "V4LLiV4LLiV4LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv2di, "V2LLiV2LLiV2LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrav8si, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrav4si, "V4iV4iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv8si, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "", "avx2")
// GATHER
-BUILTIN(__builtin_ia32_gatherd_pd, "V2dV2dV2dC*V4iV2dIc", "")
-BUILTIN(__builtin_ia32_gatherd_pd256, "V4dV4dV4dC*V4iV4dIc", "")
-BUILTIN(__builtin_ia32_gatherq_pd, "V2dV2dV2dC*V2LLiV2dIc", "")
-BUILTIN(__builtin_ia32_gatherq_pd256, "V4dV4dV4dC*V4LLiV4dIc", "")
-BUILTIN(__builtin_ia32_gatherd_ps, "V4fV4fV4fC*V4iV4fIc", "")
-BUILTIN(__builtin_ia32_gatherd_ps256, "V8fV8fV8fC*V8iV8fIc", "")
-BUILTIN(__builtin_ia32_gatherq_ps, "V4fV4fV4fC*V2LLiV4fIc", "")
-BUILTIN(__builtin_ia32_gatherq_ps256, "V4fV4fV4fC*V4LLiV4fIc", "")
-
-BUILTIN(__builtin_ia32_gatherd_q, "V2LLiV2LLiV2LLiC*V4iV2LLiIc", "")
-BUILTIN(__builtin_ia32_gatherd_q256, "V4LLiV4LLiV4LLiC*V4iV4LLiIc", "")
-BUILTIN(__builtin_ia32_gatherq_q, "V2LLiV2LLiV2LLiC*V2LLiV2LLiIc", "")
-BUILTIN(__builtin_ia32_gatherq_q256, "V4LLiV4LLiV4LLiC*V4LLiV4LLiIc", "")
-BUILTIN(__builtin_ia32_gatherd_d, "V4iV4iV4iC*V4iV4iIc", "")
-BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iV8iC*V8iV8iIc", "")
-BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iV4iC*V2LLiV4iIc", "")
-BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iV4iC*V4LLiV4iIc", "")
+TARGET_BUILTIN(__builtin_ia32_gatherd_pd, "V2dV2ddC*V4iV2dIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_pd256, "V4dV4ddC*V4iV4dIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_pd, "V2dV2ddC*V2LLiV2dIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_pd256, "V4dV4ddC*V4LLiV4dIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_ps, "V4fV4ffC*V4iV4fIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_ps256, "V8fV8ffC*V8iV8fIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_ps, "V4fV4ffC*V2LLiV4fIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_ps256, "V4fV4ffC*V4LLiV4fIc", "", "avx2")
+
+TARGET_BUILTIN(__builtin_ia32_gatherd_q, "V2LLiV2LLiLLiC*V4iV2LLiIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_q256, "V4LLiV4LLiLLiC*V4iV4LLiIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_q, "V2LLiV2LLiLLiC*V2LLiV2LLiIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_q256, "V4LLiV4LLiLLiC*V4LLiV4LLiIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_d, "V4iV4iiC*V4iV4iIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iiC*V8iV8iIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iiC*V2LLiV4iIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iiC*V4LLiV4iIc", "", "avx2")
// F16C
-BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "")
-BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "")
-BUILTIN(__builtin_ia32_vcvtps2ph512, "V16sV16fIi", "")
-BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "")
-BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "")
-BUILTIN(__builtin_ia32_vcvtph2ps512, "V16fV16s", "")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph512, "V16sV16fIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps512, "V16fV16s", "", "avx512f")
// RDRAND
-BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "")
-BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "")
-BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "")
+TARGET_BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "", "rdrnd")
+TARGET_BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "", "rdrnd")
+TARGET_BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "", "rdrnd")
// FSGSBASE
-BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "")
-BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "")
-BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "")
-BUILTIN(__builtin_ia32_rdgsbase64, "ULLi", "")
-BUILTIN(__builtin_ia32_wrfsbase32, "vUi", "")
-BUILTIN(__builtin_ia32_wrfsbase64, "vULLi", "")
-BUILTIN(__builtin_ia32_wrgsbase32, "vUi", "")
-BUILTIN(__builtin_ia32_wrgsbase64, "vULLi", "")
+TARGET_BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_rdgsbase64, "ULLi", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrfsbase32, "vUi", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrfsbase64, "vULLi", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrgsbase32, "vUi", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrgsbase64, "vULLi", "", "fsgsbase")
// FXSR
-BUILTIN(__builtin_ia32_fxrstor, "vv*", "")
-BUILTIN(__builtin_ia32_fxrstor64, "vv*", "")
-BUILTIN(__builtin_ia32_fxsave, "vv*", "")
-BUILTIN(__builtin_ia32_fxsave64, "vv*", "")
+TARGET_BUILTIN(__builtin_ia32_fxrstor, "vv*", "", "fxsr")
+TARGET_BUILTIN(__builtin_ia32_fxrstor64, "vv*", "", "fxsr")
+TARGET_BUILTIN(__builtin_ia32_fxsave, "vv*", "", "fxsr")
+TARGET_BUILTIN(__builtin_ia32_fxsave64, "vv*", "", "fxsr")
+
+// XSAVE
+TARGET_BUILTIN(__builtin_ia32_xsave, "vv*ULLi", "", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xsave64, "vv*ULLi", "", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xrstor, "vv*ULLi", "", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xrstor64, "vv*ULLi", "", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xsaveopt, "vv*ULLi", "", "xsaveopt")
+TARGET_BUILTIN(__builtin_ia32_xsaveopt64, "vv*ULLi", "", "xsaveopt")
+TARGET_BUILTIN(__builtin_ia32_xrstors, "vv*ULLi", "", "xsaves")
+TARGET_BUILTIN(__builtin_ia32_xrstors64, "vv*ULLi", "", "xsaves")
+TARGET_BUILTIN(__builtin_ia32_xsavec, "vv*ULLi", "", "xsavec")
+TARGET_BUILTIN(__builtin_ia32_xsavec64, "vv*ULLi", "", "xsavec")
+TARGET_BUILTIN(__builtin_ia32_xsaves, "vv*ULLi", "", "xsaves")
+TARGET_BUILTIN(__builtin_ia32_xsaves64, "vv*ULLi", "", "xsaves")
// ADX
-BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "")
-BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "")
-BUILTIN(__builtin_ia32_addcarry_u32, "UcUcUiUiUi*", "")
-BUILTIN(__builtin_ia32_addcarry_u64, "UcUcULLiULLiULLi*", "")
-BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "")
-BUILTIN(__builtin_ia32_subborrow_u64, "UcUcULLiULLiULLi*", "")
+TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "", "adx")
+TARGET_BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "", "adx")
+TARGET_BUILTIN(__builtin_ia32_addcarry_u32, "UcUcUiUiUi*", "", "adx")
+TARGET_BUILTIN(__builtin_ia32_addcarry_u64, "UcUcULLiULLiULLi*", "", "adx")
+TARGET_BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "", "adx")
+TARGET_BUILTIN(__builtin_ia32_subborrow_u64, "UcUcULLiULLiULLi*", "", "adx")
// RDSEED
-BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "")
-BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "")
-BUILTIN(__builtin_ia32_rdseed64_step, "UiULLi*", "")
+TARGET_BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "", "rdseed")
+TARGET_BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "", "rdseed")
+TARGET_BUILTIN(__builtin_ia32_rdseed64_step, "UiULLi*", "", "rdseed")
// BMI
-BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "")
-BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "")
+TARGET_BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "", "bmi")
+TARGET_BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "", "bmi")
// BMI2
-BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "")
-BUILTIN(__builtin_ia32_bzhi_di, "ULLiULLiULLi", "")
-BUILTIN(__builtin_ia32_pdep_si, "UiUiUi", "")
-BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "")
-BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "")
-BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "")
+TARGET_BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_bzhi_di, "ULLiULLiULLi", "", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pdep_si, "UiUiUi", "", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "", "bmi2")
// TBM
-BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "")
-BUILTIN(__builtin_ia32_bextri_u64, "ULLiULLiIULLi", "")
+TARGET_BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "", "tbm")
+TARGET_BUILTIN(__builtin_ia32_bextri_u64, "ULLiULLiIULLi", "", "tbm")
// SHA
-BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "")
-BUILTIN(__builtin_ia32_sha1nexte, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_sha1msg1, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_sha1msg2, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "")
-BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "")
+TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha1nexte, "V4iV4iV4i", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha1msg1, "V4iV4iV4i", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha1msg2, "V4iV4iV4i", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "", "sha")
// FMA
-BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "")
-BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "")
-BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "")
-BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "")
-BUILTIN(__builtin_ia32_vfmsubps, "V4fV4fV4fV4f", "")
-BUILTIN(__builtin_ia32_vfmsubpd, "V2dV2dV2dV2d", "")
-BUILTIN(__builtin_ia32_vfmsubss, "V4fV4fV4fV4f", "")
-BUILTIN(__builtin_ia32_vfmsubsd, "V2dV2dV2dV2d", "")
-BUILTIN(__builtin_ia32_vfnmaddps, "V4fV4fV4fV4f", "")
-BUILTIN(__builtin_ia32_vfnmaddpd, "V2dV2dV2dV2d", "")
-BUILTIN(__builtin_ia32_vfnmaddss, "V4fV4fV4fV4f", "")
-BUILTIN(__builtin_ia32_vfnmaddsd, "V2dV2dV2dV2d", "")
-BUILTIN(__builtin_ia32_vfnmsubps, "V4fV4fV4fV4f", "")
-BUILTIN(__builtin_ia32_vfnmsubpd, "V2dV2dV2dV2d", "")
-BUILTIN(__builtin_ia32_vfnmsubss, "V4fV4fV4fV4f", "")
-BUILTIN(__builtin_ia32_vfnmsubsd, "V2dV2dV2dV2d", "")
-BUILTIN(__builtin_ia32_vfmaddsubps, "V4fV4fV4fV4f", "")
-BUILTIN(__builtin_ia32_vfmaddsubpd, "V2dV2dV2dV2d", "")
-BUILTIN(__builtin_ia32_vfmsubaddps, "V4fV4fV4fV4f", "")
-BUILTIN(__builtin_ia32_vfmsubaddpd, "V2dV2dV2dV2d", "")
-BUILTIN(__builtin_ia32_vfmaddps256, "V8fV8fV8fV8f", "")
-BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "")
-BUILTIN(__builtin_ia32_vfmsubps256, "V8fV8fV8fV8f", "")
-BUILTIN(__builtin_ia32_vfmsubpd256, "V4dV4dV4dV4d", "")
-BUILTIN(__builtin_ia32_vfnmaddps256, "V8fV8fV8fV8f", "")
-BUILTIN(__builtin_ia32_vfnmaddpd256, "V4dV4dV4dV4d", "")
-BUILTIN(__builtin_ia32_vfnmsubps256, "V8fV8fV8fV8f", "")
-BUILTIN(__builtin_ia32_vfnmsubpd256, "V4dV4dV4dV4d", "")
-BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "")
-BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "")
-BUILTIN(__builtin_ia32_vfmsubaddps256, "V8fV8fV8fV8f", "")
-BUILTIN(__builtin_ia32_vfmsubaddpd256, "V4dV4dV4dV4d", "")
-BUILTIN(__builtin_ia32_vfmaddpd128_mask, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_vfmaddpd128_mask3, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_vfmaddpd128_maskz, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_vfmaddpd256_mask, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_vfmaddpd256_mask3, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_vfmaddpd256_maskz, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_vfmaddpd512_mask3, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_vfmaddpd512_maskz, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_vfmaddps128_mask, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_vfmaddps128_mask3, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_vfmaddps128_maskz, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_vfmaddps256_mask, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_vfmaddps256_mask3, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_vfmaddps256_maskz, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_vfmaddps512_mask3, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_vfmaddps512_maskz, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_vfmaddsubpd128_mask, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubpd128_mask3, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubpd128_maskz, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubpd256_mask, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubpd256_mask3, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubpd256_maskz, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubpd512_mask, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_vfmaddsubpd512_mask3, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_vfmaddsubpd512_maskz, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_vfmaddsubps128_mask, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubps128_mask3, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubps128_maskz, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubps256_mask, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubps256_mask3, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubps256_maskz, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_vfmaddsubps512_mask, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_vfmaddsubps512_mask3, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_vfmaddsubps512_maskz, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_vfmsubpd128_mask3, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_vfmsubpd256_mask3, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_vfmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_vfmsubps128_mask3, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_vfmsubps256_mask3, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_vfmsubps512_mask3, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_vfmsubaddpd128_mask3, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_vfmsubaddpd256_mask3, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_vfmsubaddpd512_mask3, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_vfmsubaddps128_mask3, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_vfmsubaddps256_mask3, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_vfmsubaddps512_mask3, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_vfnmaddpd128_mask, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_vfnmaddpd256_mask, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_vfnmaddpd512_mask, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_vfnmaddps128_mask, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_vfnmaddps256_mask, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_vfnmaddps512_mask, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_vfnmsubpd128_mask, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_vfnmsubpd128_mask3, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_vfnmsubpd256_mask, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_vfnmsubpd256_mask3, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_vfnmsubpd512_mask, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_vfnmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_vfnmsubps128_mask, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_vfnmsubps128_mask3, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_vfnmsubps256_mask, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_vfnmsubps256_mask3, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_vfnmsubps512_mask, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_vfnmsubps512_mask3, "V16fV16fV16fV16fUsIi", "")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubss, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubsd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddss, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddsd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubss, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubsd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_maskz, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_maskz, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_maskz, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps128_maskz, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps256_maskz, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps512_maskz, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_maskz, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_maskz, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_maskz, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_maskz, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_maskz, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_maskz, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmaddpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmaddpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmaddps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmaddps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
// XOP
-BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "")
-BUILTIN(__builtin_ia32_vpmacsww, "V8sV8sV8sV8s", "")
-BUILTIN(__builtin_ia32_vpmacsswd, "V4iV8sV8sV4i", "")
-BUILTIN(__builtin_ia32_vpmacswd, "V4iV8sV8sV4i", "")
-BUILTIN(__builtin_ia32_vpmacssdd, "V4iV4iV4iV4i", "")
-BUILTIN(__builtin_ia32_vpmacsdd, "V4iV4iV4iV4i", "")
-BUILTIN(__builtin_ia32_vpmacssdql, "V2LLiV4iV4iV2LLi", "")
-BUILTIN(__builtin_ia32_vpmacsdql, "V2LLiV4iV4iV2LLi", "")
-BUILTIN(__builtin_ia32_vpmacssdqh, "V2LLiV4iV4iV2LLi", "")
-BUILTIN(__builtin_ia32_vpmacsdqh, "V2LLiV4iV4iV2LLi", "")
-BUILTIN(__builtin_ia32_vpmadcsswd, "V4iV8sV8sV4i", "")
-BUILTIN(__builtin_ia32_vpmadcswd, "V4iV8sV8sV4i", "")
-
-BUILTIN(__builtin_ia32_vphaddbw, "V8sV16c", "")
-BUILTIN(__builtin_ia32_vphaddbd, "V4iV16c", "")
-BUILTIN(__builtin_ia32_vphaddbq, "V2LLiV16c", "")
-BUILTIN(__builtin_ia32_vphaddwd, "V4iV8s", "")
-BUILTIN(__builtin_ia32_vphaddwq, "V2LLiV8s", "")
-BUILTIN(__builtin_ia32_vphadddq, "V2LLiV4i", "")
-BUILTIN(__builtin_ia32_vphaddubw, "V8sV16c", "")
-BUILTIN(__builtin_ia32_vphaddubd, "V4iV16c", "")
-BUILTIN(__builtin_ia32_vphaddubq, "V2LLiV16c", "")
-BUILTIN(__builtin_ia32_vphadduwd, "V4iV8s", "")
-BUILTIN(__builtin_ia32_vphadduwq, "V2LLiV8s", "")
-BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "")
-BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "")
-BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "")
-BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "")
-BUILTIN(__builtin_ia32_vpcmov, "V2LLiV2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_vpcmov_256, "V4LLiV4LLiV4LLiV4LLi", "")
-BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "")
-BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_vprotd, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_vprotq, "V2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_vprotbi, "V16cV16cIc", "")
-BUILTIN(__builtin_ia32_vprotwi, "V8sV8sIc", "")
-BUILTIN(__builtin_ia32_vprotdi, "V4iV4iIc", "")
-BUILTIN(__builtin_ia32_vprotqi, "V2LLiV2LLiIc", "")
-BUILTIN(__builtin_ia32_vpshlb, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_vpshlw, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_vpshld, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_vpshlq, "V2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_vpshab, "V16cV16cV16c", "")
-BUILTIN(__builtin_ia32_vpshaw, "V8sV8sV8s", "")
-BUILTIN(__builtin_ia32_vpshad, "V4iV4iV4i", "")
-BUILTIN(__builtin_ia32_vpshaq, "V2LLiV2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_vpcomub, "V16cV16cV16cIc", "")
-BUILTIN(__builtin_ia32_vpcomuw, "V8sV8sV8sIc", "")
-BUILTIN(__builtin_ia32_vpcomud, "V4iV4iV4iIc", "")
-BUILTIN(__builtin_ia32_vpcomuq, "V2LLiV2LLiV2LLiIc", "")
-BUILTIN(__builtin_ia32_vpcomb, "V16cV16cV16cIc", "")
-BUILTIN(__builtin_ia32_vpcomw, "V8sV8sV8sIc", "")
-BUILTIN(__builtin_ia32_vpcomd, "V4iV4iV4iIc", "")
-BUILTIN(__builtin_ia32_vpcomq, "V2LLiV2LLiV2LLiIc", "")
-BUILTIN(__builtin_ia32_vpermil2pd, "V2dV2dV2dV2LLiIc", "")
-BUILTIN(__builtin_ia32_vpermil2pd256, "V4dV4dV4dV4LLiIc", "")
-BUILTIN(__builtin_ia32_vpermil2ps, "V4fV4fV4fV4iIc", "")
-BUILTIN(__builtin_ia32_vpermil2ps256, "V8fV8fV8fV8iIc", "")
-BUILTIN(__builtin_ia32_vfrczss, "V4fV4f", "")
-BUILTIN(__builtin_ia32_vfrczsd, "V2dV2d", "")
-BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "")
-BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "")
-BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "")
-BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "")
-BUILTIN(__builtin_ia32_xbegin, "i", "")
-BUILTIN(__builtin_ia32_xend, "v", "")
-BUILTIN(__builtin_ia32_xabort, "vIc", "")
-BUILTIN(__builtin_ia32_xtest, "i", "")
+TARGET_BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsww, "V8sV8sV8sV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsswd, "V4iV8sV8sV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacswd, "V4iV8sV8sV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacssdd, "V4iV4iV4iV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsdd, "V4iV4iV4iV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacssdql, "V2LLiV4iV4iV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsdql, "V2LLiV4iV4iV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacssdqh, "V2LLiV4iV4iV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsdqh, "V2LLiV4iV4iV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmadcsswd, "V4iV8sV8sV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmadcswd, "V4iV8sV8sV4i", "", "xop")
+
+TARGET_BUILTIN(__builtin_ia32_vphaddbw, "V8sV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddbd, "V4iV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddbq, "V2LLiV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddwd, "V4iV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddwq, "V2LLiV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphadddq, "V2LLiV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddubw, "V8sV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddubd, "V4iV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddubq, "V2LLiV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphadduwd, "V4iV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphadduwq, "V2LLiV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcmov, "V2LLiV2LLiV2LLiV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcmov_256, "V4LLiV4LLiV4LLiV4LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotd, "V4iV4iV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotq, "V2LLiV2LLiV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotbi, "V16cV16cIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotwi, "V8sV8sIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotdi, "V4iV4iIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotqi, "V2LLiV2LLiIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshlb, "V16cV16cV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshlw, "V8sV8sV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshld, "V4iV4iV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshlq, "V2LLiV2LLiV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshab, "V16cV16cV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshaw, "V8sV8sV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshad, "V4iV4iV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshaq, "V2LLiV2LLiV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomub, "V16cV16cV16cIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomuw, "V8sV8sV8sIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomud, "V4iV4iV4iIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomuq, "V2LLiV2LLiV2LLiIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomb, "V16cV16cV16cIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomw, "V8sV8sV8sIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomd, "V4iV4iV4iIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomq, "V2LLiV2LLiV2LLiIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2pd, "V2dV2dV2dV2LLiIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2pd256, "V4dV4dV4dV4LLiIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2ps, "V4fV4fV4fV4iIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2ps256, "V8fV8fV8fV8iIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczss, "V4fV4f", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczsd, "V2dV2d", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "", "xop")
+
+TARGET_BUILTIN(__builtin_ia32_xbegin, "i", "", "rtm")
+TARGET_BUILTIN(__builtin_ia32_xend, "v", "", "rtm")
+TARGET_BUILTIN(__builtin_ia32_xabort, "vIc", "", "rtm")
+TARGET_BUILTIN(__builtin_ia32_xtest, "i", "", "rtm")
+
BUILTIN(__builtin_ia32_rdpmc, "ULLii", "")
BUILTIN(__builtin_ia32_rdtsc, "ULLi", "")
BUILTIN(__builtin_ia32_rdtscp, "ULLiUi*", "")
+// PKU
+TARGET_BUILTIN(__builtin_ia32_rdpkru, "Ui", "", "pku")
+TARGET_BUILTIN(__builtin_ia32_wrpkru, "vUi", "", "pku")
// AVX-512
-BUILTIN(__builtin_ia32_sqrtpd512_mask, "V8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_sqrtps512_mask, "V16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_rsqrt14sd_mask, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_rsqrt14ss_mask, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "")
-BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "")
-BUILTIN(__builtin_ia32_rsqrt28sd_mask, "V2dV2dV2dV2dUcIi", "")
-BUILTIN(__builtin_ia32_rsqrt28ss_mask, "V4fV4fV4fV4fUcIi", "")
-BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_rcp14sd_mask, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_rcp14ss_mask, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "")
-BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "")
-BUILTIN(__builtin_ia32_rcp28sd_mask, "V2dV2dV2dV2dUcIi", "")
-BUILTIN(__builtin_ia32_rcp28ss_mask, "V4fV4fV4fV4fUcIi", "")
-BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_exp2pd_mask, "V8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_exp2ps_mask, "V16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "")
-BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsIi", "")
-BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUcIi", "")
-BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUcIi", "")
-BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "")
-BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "")
-BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "")
-BUILTIN(__builtin_ia32_pcmpeqb512_mask, "LLiV64cV64cLLi", "")
-BUILTIN(__builtin_ia32_pcmpeqd512_mask, "sV16iV16is", "")
-BUILTIN(__builtin_ia32_pcmpeqq512_mask, "cV8LLiV8LLic", "")
-BUILTIN(__builtin_ia32_pcmpeqw512_mask, "iV32sV32si", "")
-BUILTIN(__builtin_ia32_pcmpeqb256_mask, "iV32cV32ci", "")
-BUILTIN(__builtin_ia32_pcmpeqd256_mask, "cV8iV8ic", "")
-BUILTIN(__builtin_ia32_pcmpeqq256_mask, "cV4LLiV4LLic", "")
-BUILTIN(__builtin_ia32_pcmpeqw256_mask, "sV16sV16ss", "")
-BUILTIN(__builtin_ia32_pcmpeqb128_mask, "sV16cV16cs", "")
-BUILTIN(__builtin_ia32_pcmpeqd128_mask, "cV4iV4ic", "")
-BUILTIN(__builtin_ia32_pcmpeqq128_mask, "cV2LLiV2LLic", "")
-BUILTIN(__builtin_ia32_pcmpeqw128_mask, "cV8sV8sc", "")
-BUILTIN(__builtin_ia32_pcmpgtb512_mask, "LLiV64cV64cLLi", "")
-BUILTIN(__builtin_ia32_pcmpgtd512_mask, "sV16iV16is", "")
-BUILTIN(__builtin_ia32_pcmpgtq512_mask, "cV8LLiV8LLic", "")
-BUILTIN(__builtin_ia32_pcmpgtw512_mask, "iV32sV32si", "")
-BUILTIN(__builtin_ia32_pcmpgtb256_mask, "iV32cV32ci", "")
-BUILTIN(__builtin_ia32_pcmpgtd256_mask, "cV8iV8ic", "")
-BUILTIN(__builtin_ia32_pcmpgtq256_mask, "cV4LLiV4LLic", "")
-BUILTIN(__builtin_ia32_pcmpgtw256_mask, "sV16sV16ss", "")
-BUILTIN(__builtin_ia32_pcmpgtb128_mask, "sV16cV16cs", "")
-BUILTIN(__builtin_ia32_pcmpgtd128_mask, "cV4iV4ic", "")
-BUILTIN(__builtin_ia32_pcmpgtq128_mask, "cV2LLiV2LLic", "")
-BUILTIN(__builtin_ia32_pcmpgtw128_mask, "cV8sV8sc", "")
-BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "")
-BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "")
-BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "")
-BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fIiV16fUsIi", "")
-BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8dIiV8dUcIi", "")
-BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "")
-BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "")
-BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "")
-BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "")
-BUILTIN(__builtin_ia32_minps512_mask, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_minpd512_mask, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsIi", "")
-BUILTIN(__builtin_ia32_maxpd512_mask, "V8dV8dV8dV8dUcIi", "")
-BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "")
-BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "")
-BUILTIN(__builtin_ia32_cvtdq2pd512_mask, "V8dV8iV8dUc", "")
-BUILTIN(__builtin_ia32_cvtudq2pd512_mask, "V8dV8iV8dUc", "")
-BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "")
-BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fIiV16sUs", "")
-BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsIi", "")
-BUILTIN(__builtin_ia32_pandd512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_pandq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_pord512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_porq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_pxord512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_pxorq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_pabsd512_mask, "V16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_pabsq512_mask, "V8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_pmaxsd512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_pmaxsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_pmaxud512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_pmaxuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_pminsd512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_pminsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_pminud512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_pminuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_pmuldq512_mask, "V8LLiV16iV16iV8LLiUc", "")
-BUILTIN(__builtin_ia32_pmuludq512_mask, "V8LLiV16iV16iV8LLiUc", "")
-BUILTIN(__builtin_ia32_blendmd_512_mask, "V16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_blendmq_512_mask, "V8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_blendmps_512_mask, "V16fV16fV16fUs", "")
-BUILTIN(__builtin_ia32_blendmpd_512_mask, "V8dV8dV8dUc", "")
-BUILTIN(__builtin_ia32_ptestmd512, "UsV16iV16iUs", "")
-BUILTIN(__builtin_ia32_ptestmq512, "UcV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_pbroadcastd512_gpr_mask, "V16iiV16iUs", "")
-BUILTIN(__builtin_ia32_pbroadcastq512_gpr_mask, "V8LLiLLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_pbroadcastq512_mem_mask, "V8LLiLLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16ivC*V16iUs", "")
-BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLivC*V8LLiUc", "")
-BUILTIN(__builtin_ia32_loadups512_mask, "V16fvC*V16fUs", "")
-BUILTIN(__builtin_ia32_loadaps512_mask, "V16fvC*V16fUs", "")
-BUILTIN(__builtin_ia32_loadupd512_mask, "V8dvC*V8dUc", "")
-BUILTIN(__builtin_ia32_loadapd512_mask, "V8dvC*V8dUc", "")
-BUILTIN(__builtin_ia32_storedqudi512_mask, "vv*V8LLiUc", "")
-BUILTIN(__builtin_ia32_storedqusi512_mask, "vv*V16iUs", "")
-BUILTIN(__builtin_ia32_storeupd512_mask, "vv*V8dUc", "")
-BUILTIN(__builtin_ia32_storeapd512_mask, "vv*V8dUc", "")
-BUILTIN(__builtin_ia32_storeups512_mask, "vv*V16fUs", "")
-BUILTIN(__builtin_ia32_storeaps512_mask, "vv*V16fUs", "")
-BUILTIN(__builtin_ia32_vpermt2vard512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_vpermt2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_vpermt2varps512_mask, "V16fV16iV16fV16fUs", "")
-BUILTIN(__builtin_ia32_vpermt2varpd512_mask, "V8dV8LLiV8dV8dUc", "")
-BUILTIN(__builtin_ia32_alignq512_mask, "V8LLiV8LLiV8LLiIcV8LLiUc", "")
-BUILTIN(__builtin_ia32_alignd512_mask, "V16iV16iV16iIcV16iUs", "")
-BUILTIN(__builtin_ia32_extractf64x4_mask, "V4dV8dIcV4dUc", "")
-BUILTIN(__builtin_ia32_extractf32x4_mask, "V4fV16fIcV4fUc", "")
-BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8dvC*V8iUcIi", "")
-BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16fvC*UsIi", "")
-BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8dvC*V8LLiUcIi", "")
-BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8fvC*V8LLiUcIi", "")
-BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLivC*V8iUcIi", "")
-BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16ivC*UsIi", "")
-BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLivC*V8LLiUcIi", "")
-BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8ivC*V8LLiUcIi", "")
-BUILTIN(__builtin_ia32_scattersiv8df, "vv*UcV8iV8dIi", "")
-BUILTIN(__builtin_ia32_scattersiv16sf, "vv*UsV16iV16fIi", "")
-BUILTIN(__builtin_ia32_scatterdiv8df, "vv*UcV8LLiV8dIi", "")
-BUILTIN(__builtin_ia32_scatterdiv16sf, "vv*UcV8LLiV8fIi", "")
-BUILTIN(__builtin_ia32_scattersiv8di, "vv*UcV8iV8LLiIi", "")
-BUILTIN(__builtin_ia32_scattersiv16si, "vv*UsV16iV16iIi", "")
-BUILTIN(__builtin_ia32_scatterdiv8di, "vv*UcV8LLiV8LLiIi", "")
-BUILTIN(__builtin_ia32_scatterdiv16si, "vv*UcV8LLiV8iIi", "")
-BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8ivC*IiIi", "")
-BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16ivC*IiIi", "")
-BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLivC*IiIi", "")
-BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLivC*IiIi", "")
-BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iv*IiIi", "")
-BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16iv*IiIi", "")
-BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiv*IiIi", "")
-BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLiv*IiIi", "")
-BUILTIN(__builtin_ia32_knothi, "UsUs", "")
-
-BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIiUs", "")
-BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIiUc", "")
-BUILTIN(__builtin_ia32_cmpq128_mask, "UcV2LLiV2LLiIiUc", "")
-BUILTIN(__builtin_ia32_cmpw128_mask, "UcV8sV8sIiUc", "")
-BUILTIN(__builtin_ia32_cmpb256_mask, "UiV32cV32cIiUi", "")
-BUILTIN(__builtin_ia32_cmpd256_mask, "UcV8iV8iIiUc", "")
-BUILTIN(__builtin_ia32_cmpq256_mask, "UcV4LLiV4LLiIiUc", "")
-BUILTIN(__builtin_ia32_cmpw256_mask, "UsV16sV16sIiUs", "")
-BUILTIN(__builtin_ia32_cmpb512_mask, "ULLiV64cV64cIiULLi", "")
-BUILTIN(__builtin_ia32_cmpd512_mask, "UsV16iV16iIiUs", "")
-BUILTIN(__builtin_ia32_cmpq512_mask, "UcV8LLiV8LLiIiUc", "")
-BUILTIN(__builtin_ia32_cmpw512_mask, "UiV32sV32sIiUi", "")
-BUILTIN(__builtin_ia32_ucmpb128_mask, "UsV16cV16cIiUs", "")
-BUILTIN(__builtin_ia32_ucmpd128_mask, "UcV4iV4iIiUc", "")
-BUILTIN(__builtin_ia32_ucmpq128_mask, "UcV2LLiV2LLiIiUc", "")
-BUILTIN(__builtin_ia32_ucmpw128_mask, "UcV8sV8sIiUc", "")
-BUILTIN(__builtin_ia32_ucmpb256_mask, "UiV32cV32cIiUi", "")
-BUILTIN(__builtin_ia32_ucmpd256_mask, "UcV8iV8iIiUc", "")
-BUILTIN(__builtin_ia32_ucmpq256_mask, "UcV4LLiV4LLiIiUc", "")
-BUILTIN(__builtin_ia32_ucmpw256_mask, "UsV16sV16sIiUs", "")
-BUILTIN(__builtin_ia32_ucmpb512_mask, "ULLiV64cV64cIiULLi", "")
-BUILTIN(__builtin_ia32_ucmpd512_mask, "UsV16iV16iIiUs", "")
-BUILTIN(__builtin_ia32_ucmpq512_mask, "UcV8LLiV8LLiIiUc", "")
-BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "")
-
-BUILTIN(__builtin_ia32_paddd256_mask, "V8iV8iV8iV8iUc", "")
-BUILTIN(__builtin_ia32_paddq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
-BUILTIN(__builtin_ia32_psubd256_mask, "V8iV8iV8iV8iUc", "")
-BUILTIN(__builtin_ia32_psubq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
-BUILTIN(__builtin_ia32_paddd128_mask, "V4iV4iV4iV4iUc", "")
-BUILTIN(__builtin_ia32_paddq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
-BUILTIN(__builtin_ia32_psubd128_mask, "V4iV4iV4iV4iUc", "")
-BUILTIN(__builtin_ia32_psubq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
-BUILTIN(__builtin_ia32_pmuldq256_mask, "V4LLiV8iV8iV4LLiUc", "")
-BUILTIN(__builtin_ia32_pmuldq128_mask, "V2LLiV4iV4iV2LLiUc", "")
-BUILTIN(__builtin_ia32_pmuludq256_mask, "V4LLiV8iV8iV4LLiUc", "")
-BUILTIN(__builtin_ia32_pmuludq128_mask, "V2LLiV4iV4iV2LLiUc", "")
-BUILTIN(__builtin_ia32_pmulld256_mask, "V8iV8iV8iV8iUc", "")
-BUILTIN(__builtin_ia32_pmulld128_mask, "V4iV4iV4iV4iUc", "")
-BUILTIN(__builtin_ia32_pandd256_mask, "V8iV8iV8iV8iUc", "")
-BUILTIN(__builtin_ia32_pandd128_mask, "V4iV4iV4iV4iUc", "")
-BUILTIN(__builtin_ia32_pandnd256_mask, "V8iV8iV8iV8iUc", "")
-BUILTIN(__builtin_ia32_pandnd128_mask, "V4iV4iV4iV4iUc", "")
-BUILTIN(__builtin_ia32_pord256_mask, "V8iV8iV8iV8iUc", "")
-BUILTIN(__builtin_ia32_pord128_mask, "V4iV4iV4iV4iUc", "")
-BUILTIN(__builtin_ia32_pxord256_mask, "V8iV8iV8iV8iUc", "")
-BUILTIN(__builtin_ia32_pxord128_mask, "V4iV4iV4iV4iUc", "")
-BUILTIN(__builtin_ia32_pandq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
-BUILTIN(__builtin_ia32_pandq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
-BUILTIN(__builtin_ia32_pandnq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
-BUILTIN(__builtin_ia32_pandnq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
-BUILTIN(__builtin_ia32_porq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
-BUILTIN(__builtin_ia32_porq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
-BUILTIN(__builtin_ia32_pxorq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
-BUILTIN(__builtin_ia32_pxorq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
-BUILTIN(__builtin_ia32_paddb512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_psubb512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_paddw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_psubw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_pmullw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_paddb256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_paddw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_psubb256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_psubw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_paddb128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_paddw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_psubb128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_psubw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_pmullw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_pmullw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_pandnd512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_pandnq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_paddq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_psubq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_paddd512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_psubd512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_pmulld512_mask, "V16iV16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_pmullq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_xorpd512_mask, "V8dV8dV8dV8dUc", "")
-BUILTIN(__builtin_ia32_xorps512_mask, "V16fV16fV16fV16fUs", "")
-BUILTIN(__builtin_ia32_orpd512_mask, "V8dV8dV8dV8dUc", "")
-BUILTIN(__builtin_ia32_orps512_mask, "V16fV16fV16fV16fUs", "")
-BUILTIN(__builtin_ia32_andpd512_mask, "V8dV8dV8dV8dUc", "")
-BUILTIN(__builtin_ia32_andps512_mask, "V16fV16fV16fV16fUs", "")
-BUILTIN(__builtin_ia32_andnpd512_mask, "V8dV8dV8dV8dUc", "")
-BUILTIN(__builtin_ia32_andnps512_mask, "V16fV16fV16fV16fUs", "")
-BUILTIN(__builtin_ia32_pmullq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
-BUILTIN(__builtin_ia32_pmullq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
-BUILTIN(__builtin_ia32_andnpd256_mask, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_andnpd128_mask, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_andnps256_mask, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_andnps128_mask, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_andpd256_mask, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_andpd128_mask, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_andps256_mask, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_andps128_mask, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_xorpd256_mask, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_xorpd128_mask, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_xorps256_mask, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_xorps128_mask, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_orpd256_mask, "V4dV4dV4dV4dUc", "")
-BUILTIN(__builtin_ia32_orpd128_mask, "V2dV2dV2dV2dUc", "")
-BUILTIN(__builtin_ia32_orps256_mask, "V8fV8fV8fV8fUc", "")
-BUILTIN(__builtin_ia32_orps128_mask, "V4fV4fV4fV4fUc", "")
-BUILTIN(__builtin_ia32_blendmb_512_mask, "V64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_blendmw_512_mask, "V32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_pabsb512_mask, "V64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_pabsw512_mask, "V32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_packssdw512_mask, "V32sV16iV16iV32sUi", "")
-BUILTIN(__builtin_ia32_packsswb512_mask, "V64cV32sV32sV64cULLi", "")
-BUILTIN(__builtin_ia32_packusdw512_mask, "V32sV16iV16iV32sUi", "")
-BUILTIN(__builtin_ia32_packuswb512_mask, "V64cV32sV32sV64cULLi", "")
-BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_paddusw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_pavgb512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_pavgw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_pmaxsb512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_pmaxsw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_pmaxub512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_pmaxuw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_pminsb512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_pminsw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_pminub512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_pminuw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_pshufb512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_psubsb512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_psubsw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_psubusb512_mask, "V64cV64cV64cV64cULLi", "")
-BUILTIN(__builtin_ia32_psubusw512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_vpermi2varhi512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_vpermt2varhi512_mask, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_vpermt2varhi512_maskz, "V32sV32sV32sV32sUi", "")
-BUILTIN(__builtin_ia32_vpconflictdi_512_mask, "V8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_vplzcntd_512_mask, "V16iV16iV16iUs", "")
-BUILTIN(__builtin_ia32_vplzcntq_512_mask, "V8LLiV8LLiV8LLiUc", "")
-BUILTIN(__builtin_ia32_blendmb_128_mask, "V16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_blendmb_256_mask, "V32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_blendmw_128_mask, "V8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_blendmw_256_mask, "V16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_pabsb128_mask, "V16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_pabsb256_mask, "V32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_pabsw128_mask, "V8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_pabsw256_mask, "V16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_packssdw128_mask, "V8sV4iV4iV8sUc", "")
-BUILTIN(__builtin_ia32_packssdw256_mask, "V16sV8iV8iV16sUs", "")
-BUILTIN(__builtin_ia32_packsswb128_mask, "V16cV8sV8sV16cUs", "")
-BUILTIN(__builtin_ia32_packsswb256_mask, "V32cV16sV16sV32cUi", "")
-BUILTIN(__builtin_ia32_packusdw128_mask, "V8sV4iV4iV8sUc", "")
-BUILTIN(__builtin_ia32_packusdw256_mask, "V16sV8iV8iV16sUs", "")
-BUILTIN(__builtin_ia32_packuswb128_mask, "V16cV8sV8sV16cUs", "")
-BUILTIN(__builtin_ia32_packuswb256_mask, "V32cV16sV16sV32cUi", "")
-BUILTIN(__builtin_ia32_paddsb128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_paddsb256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_paddsw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_paddsw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_paddusb128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_paddusb256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_paddusw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_paddusw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_pavgb128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_pavgb256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_pavgw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_pavgw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_pmaxsb128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_pmaxsb256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_pmaxsw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_pmaxsw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_pmaxub128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_pmaxub256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_pmaxuw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_pmaxuw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_pminsb128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_pminsb256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_pminsw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_pminsw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_pminub128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_pminub256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_pminuw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_pminuw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_pshufb128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_pshufb256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_psubsb128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_psubsb256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_psubsw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_psubsw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_psubusb128_mask, "V16cV16cV16cV16cUs", "")
-BUILTIN(__builtin_ia32_psubusb256_mask, "V32cV32cV32cV32cUi", "")
-BUILTIN(__builtin_ia32_psubusw128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_psubusw256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_vpermi2varhi128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_vpermi2varhi256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_vpermt2varhi128_mask, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_vpermt2varhi128_maskz, "V8sV8sV8sV8sUc", "")
-BUILTIN(__builtin_ia32_vpermt2varhi256_mask, "V16sV16sV16sV16sUs", "")
-BUILTIN(__builtin_ia32_vpermt2varhi256_maskz, "V16sV16sV16sV16sUs", "")
+TARGET_BUILTIN(__builtin_ia32_sqrtpd512_mask, "V8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_sqrtps512_mask, "V16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14sd, "V2dV2dV2dV2dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14ss, "V4fV4fV4fV4fUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_rsqrt28sd_round, "V2dV2dV2dV2dUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rsqrt28ss_round, "V4fV4fV4fV4fUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsIi", "", "avx512er")
+
+TARGET_BUILTIN(__builtin_ia32_rcp14sd, "V2dV2dV2dV2dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rcp14ss, "V4fV4fV4fV4fUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_rcp28sd_round, "V2dV2dV2dV2dUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rcp28ss_round, "V4fV4fV4fV4fUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_exp2pd_mask, "V8dV8dV8dUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_exp2ps_mask, "V16fV16fV16fUsIi", "", "avx512er")
+
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_pcmpeqb512_mask, "LLiV64cV64cLLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqd512_mask, "sV16iV16is", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqq512_mask, "cV8LLiV8LLic", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqw512_mask, "iV32sV32si", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_pcmpeqb256_mask, "iV32cV32ci", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqd256_mask, "cV8iV8ic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqq256_mask, "cV4LLiV4LLic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqw256_mask, "sV16sV16ss", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqb128_mask, "sV16cV16cs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqd128_mask, "cV4iV4ic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqq128_mask, "cV2LLiV2LLic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqw128_mask, "cV8sV8sc", "", "avx512vl,avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_pcmpgtb512_mask, "LLiV64cV64cLLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtd512_mask, "sV16iV16is", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtq512_mask, "cV8LLiV8LLic", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtw512_mask, "iV32sV32si", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_pcmpgtb256_mask, "iV32cV32ci", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtd256_mask, "cV8iV8ic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtq256_mask, "cV4LLiV4LLic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtw256_mask, "sV16sV16ss", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtb128_mask, "sV16cV16cs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtd128_mask, "cV4iV4ic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtq128_mask, "cV2LLiV2LLic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtw128_mask, "cV8sV8sc", "", "avx512vl,avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fIiV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8dIiV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2pd512_mask, "V8dV8iV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2pd512_mask, "V8dV8iV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fIiV16sUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pandd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pandq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pord512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_porq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pxord512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pxorq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pabsd512_mask, "V16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pabsq512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxud512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminsd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminud512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmuldq512_mask, "V8LLiV16iV16iV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmuludq512_mask, "V8LLiV16iV16iV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_blendmd_512_mask, "V16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_blendmq_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_blendmps_512_mask, "V16fV16fV16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_blendmpd_512_mask, "V8dV8dV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_ptestmd512, "UsV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_ptestmq512, "UcV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pbroadcastd512_gpr_mask, "V16iiV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pbroadcastq512_gpr_mask, "V8LLiLLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pbroadcastq512_mem_mask, "V8LLiLLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16ivC*V16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLivC*V8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadups512_mask, "V16fvC*V16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadaps512_mask, "V16fvC*V16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadupd512_mask, "V8dvC*V8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadapd512_mask, "V8dvC*V8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storedqudi512_mask, "vv*V8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storedqusi512_mask, "vv*V16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeupd512_mask, "vv*V8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeapd512_mask, "vv*V8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeups512_mask, "vv*V16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeaps512_mask, "vv*V16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermt2vard512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varps512_mask, "V16fV16iV16fV16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varpd512_mask, "V8dV8LLiV8dV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_alignq512_mask, "V8LLiV8LLiV8LLiIiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_alignd512_mask, "V16iV16iV16iIiV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_extractf64x4_mask, "V4dV8dIiV4dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_extractf32x4_mask, "V4fV16fIiV4fUc", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8dvC*V8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16fvC*UsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8dvC*V8LLiUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8fvC*V8LLiUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLivC*V8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16ivC*UsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLivC*V8LLiUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8ivC*V8LLiUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vv*UcV8iV8dIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vv*UsV16iV16fIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vv*UcV8LLiV8dIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vv*UcV8LLiV8fIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vv*UcV8iV8LLiIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vv*UsV16iV16iIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vv*UcV8LLiV8LLiIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vv*UcV8LLiV8iIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8ivC*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16ivC*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLivC*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLivC*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iv*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16iv*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiv*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLiv*IiIi", "", "avx512pf")
+
+TARGET_BUILTIN(__builtin_ia32_knothi, "UsUs", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIiUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpq128_mask, "UcV2LLiV2LLiIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpw128_mask, "UcV8sV8sIiUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpb256_mask, "UiV32cV32cIiUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpd256_mask, "UcV8iV8iIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpq256_mask, "UcV4LLiV4LLiIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpw256_mask, "UsV16sV16sIiUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpb512_mask, "ULLiV64cV64cIiULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpd512_mask, "UsV16iV16iIiUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpq512_mask, "UcV8LLiV8LLiIiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpw512_mask, "UiV32sV32sIiUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpb128_mask, "UsV16cV16cIiUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpd128_mask, "UcV4iV4iIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpq128_mask, "UcV2LLiV2LLiIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpw128_mask, "UcV8sV8sIiUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpb256_mask, "UiV32cV32cIiUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpd256_mask, "UcV8iV8iIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpq256_mask, "UcV4LLiV4LLiIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpw256_mask, "UsV16sV16sIiUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpb512_mask, "ULLiV64cV64cIiULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpd512_mask, "UsV16iV16iIiUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_ucmpq512_mask, "UcV8LLiV8LLiIiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_paddd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_paddq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psubd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psubq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_paddd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_paddq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psubd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psubq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmuldq256_mask, "V4LLiV8iV8iV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmuldq128_mask, "V2LLiV4iV4iV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmuludq256_mask, "V4LLiV8iV8iV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmuludq128_mask, "V2LLiV4iV4iV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmulld256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmulld128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandnd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandnd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pord256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pord128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pxord256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pxord128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandnq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandnq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_porq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_porq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pxorq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pxorq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_paddb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmullw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmullw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmullw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_pandnd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pandnq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_paddq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psubq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_paddd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psubd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_pmulld512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmullq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_pmullq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_pmullq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
+
+TARGET_BUILTIN(__builtin_ia32_blendmb_512_mask, "V64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_blendmw_512_mask, "V32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsb512_mask, "V64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsw512_mask, "V32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packssdw512_mask, "V32sV16iV16iV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packsswb512_mask, "V64cV32sV32sV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packusdw512_mask, "V32sV16iV16iV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packuswb512_mask, "V64cV32sV32sV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxub512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminub512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pshufb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_vpermi2varhi512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi512_maskz, "V32sV32sV32sV32sUi", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_vpconflictdi_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512cd")
+TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "", "avx512cd")
+TARGET_BUILTIN(__builtin_ia32_vplzcntd_512_mask, "V16iV16iV16iUs", "", "avx512cd")
+TARGET_BUILTIN(__builtin_ia32_vplzcntq_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512cd")
+
+TARGET_BUILTIN(__builtin_ia32_blendmb_128_mask, "V16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_blendmb_256_mask, "V32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_blendmw_128_mask, "V8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_blendmw_256_mask, "V16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsb128_mask, "V16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsb256_mask, "V32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsw128_mask, "V8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsw256_mask, "V16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packssdw128_mask, "V8sV4iV4iV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packssdw256_mask, "V16sV8iV8iV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packsswb128_mask, "V16cV8sV8sV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packsswb256_mask, "V32cV16sV16sV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packusdw128_mask, "V8sV4iV4iV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packusdw256_mask, "V16sV8iV8iV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packuswb128_mask, "V16cV8sV8sV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packuswb256_mask, "V32cV16sV16sV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxub128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxub256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminub128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminub256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminuw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminuw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pshufb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pshufb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_vpermi2varhi128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi128_maskz, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi256_maskz, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_addpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_addps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw512_mask, "V32sV64cV64cV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd512_mask, "V16iV32sV32sV16iUs", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_addss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_addsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_addpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_addpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_addps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_addps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmd_128_mask, "V4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmd_256_mask, "V8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmpd_128_mask, "V2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmpd_256_mask, "V4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmps_128_mask, "V4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmps_256_mask, "V8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmq_128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmq_256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressdf128_mask, "V2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressdf256_mask, "V4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressdi128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressdi256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compresssf128_mask, "V4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compresssf256_mask, "V8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compresssi128_mask, "V4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compresssi256_mask, "V8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredf128_mask, "vV2d*V2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredf256_mask, "vV4d*V4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredi128_mask, "vV2LLi*V2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredi256_mask, "vV4LLi*V4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoresf128_mask, "vV4f*V4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoresf256_mask, "vV8f*V8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoresi128_mask, "vV4i*V4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoresi256_mask, "vV8i*V8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2pd128_mask, "V2dV4iV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2pd256_mask, "V4dV4iV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2ps128_mask, "V4fV4iV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2ps256_mask, "V8fV8iV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq128_mask, "V4iV2dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256_mask, "V4iV4dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps_mask, "V4fV2dV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256_mask, "V4fV4dV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2udq128_mask, "V4iV2dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2udq256_mask, "V4iV4dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq128_mask, "V4iV4fV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq256_mask, "V8iV8fV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pd128_mask, "V2dV4fV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pd256_mask, "V4dV4fV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2udq128_mask, "V4iV4fV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2udq256_mask, "V8iV8fV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq128_mask, "V4iV2dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256_mask, "V4iV4dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2udq128_mask, "V4iV2dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2udq256_mask, "V4iV4dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq128_mask, "V4iV4fV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq256_mask, "V8iV8fV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttps2udq128_mask, "V4iV4fV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttps2udq256_mask, "V8iV8fV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2pd128_mask, "V2dV4iV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2pd256_mask, "V4dV4iV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2ps128_mask, "V4fV4iV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2ps256_mask, "V8fV8iV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_divpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_divpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_divps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_divps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddf128_mask, "V2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddf256_mask, "V4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddi128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddi256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloaddf128_mask, "V2dV2d*V2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloaddf256_mask, "V4dV4d*V4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloaddi128_mask, "V4iV2LLi*V2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloaddi256_mask, "V4LLiV4LLi*V4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloadsf128_mask, "V4fV4f*V4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloadsf256_mask, "V8fV8f*V8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloadsi128_mask, "V4iV4i*V4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloadsi256_mask, "V8iV8i*V8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsf128_mask, "V4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsf256_mask, "V8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsi128_mask, "V4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsi256_mask, "V8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexppd128_mask, "V2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexppd256_mask, "V4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexpps128_mask, "V4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexpps256_mask, "V8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_maxpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_maxpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_maxps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_maxps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_minpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_minpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_minps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_minps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_mulpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_mulpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_mulps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_mulps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pabsd128_mask, "V4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pabsd256_mask, "V8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pabsq128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pabsq256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxsq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxsq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxud128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxud256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxuq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxuq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminsd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminsd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminsq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminsq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminud128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminud256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminuq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminuq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscalepd_128_mask, "V2dV2dIiV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscalepd_256_mask, "V4dV4dIiV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscaleps_128_mask, "V4fV4fIiV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscaleps_256_mask, "V8fV8fIiV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vv*UcV2LLiV2dIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vv*UcV2LLiV2LLiIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vv*UcV4LLiV4dIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vv*UcV4LLiV4LLiIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vv*UcV2LLiV4fIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vv*UcV2LLiV4iIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vv*UcV4LLiV4fIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vv*UcV4LLiV4iIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vv*UcV4iV2dIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vv*UcV4iV2LLiIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vv*UcV4iV4dIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vv*UcV4iV4LLiIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vv*UcV4iV4fIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vv*UcV4iV4iIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vv*UcV8iV8fIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vv*UcV8iV8iIi", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_sqrtpd128_mask, "V2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_sqrtpd256_mask, "V4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_sqrtps128_mask, "V4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_sqrtps256_mask, "V8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_subpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_subpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_subps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_subps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2vard128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2vard256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varpd128_mask, "V2dV2dV2LLiV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varpd256_mask, "V4dV4dV4LLiV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varps128_mask, "V4fV4fV4iV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varps256_mask, "V8fV8fV8iV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2vard128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2vard128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2vard256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2vard256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varpd128_mask, "V2dV2LLiV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varpd128_maskz, "V2dV2LLiV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varpd256_mask, "V4dV4LLiV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varpd256_maskz, "V4dV4LLiV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varps128_mask, "V4fV4iV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varps128_maskz, "V4fV4iV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varps256_mask, "V8fV8iV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varps256_maskz, "V8fV8iV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovswb512_mask, "V32cV32sV32cUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb512_mask, "V32cV32sV32cUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovwb512_mask, "V32cV32sV32cUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhbw512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhwd512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklbw512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklwd512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2qq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2qq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2qq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2qq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2uqq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2uqq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2pd128_mask, "V2dV2LLiV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2pd256_mask, "V4dV4LLiV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2ps128_mask, "V4fV2LLiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2ps256_mask, "V4fV4LLiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2qq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2qq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2qq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2qq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2uqq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2uqq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd128_mask, "V2dV2LLiV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd256_mask, "V4dV4LLiV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps128_mask, "V4fV2LLiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps256_mask, "V4fV4LLiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangepd128_mask, "V2dV2dV2dIiV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangepd256_mask, "V4dV4dV4dIiV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangeps128_mask, "V4fV4fV4fIiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangeps256_mask, "V8fV8fV8fIiV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reducepd128_mask, "V2dV2dIiV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reducepd256_mask, "V4dV4dIiV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reduceps128_mask, "V4fV4fIiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reduceps256_mask, "V8fV8fIiV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw128_mask, "V8sV16cV16cV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw256_mask, "V16sV32cV32cV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd128_mask, "V4iV8sV8sV4iUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd256_mask, "V8iV16sV16sV8iUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovswb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovswb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovwb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovwb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhbw128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhbw256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhwd128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhwd256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklbw128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklbw256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklwd128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklwd256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2qq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2pd512_mask, "V8dV8LLiV8dUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2ps512_mask, "V8fV8LLiV8fUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2qq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd512_mask, "V8dV8LLiV8dUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps512_mask, "V8fV8LLiV8fUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangepd512_mask, "V8dV8dV8dIiV8dUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangeps512_mask, "V16fV16fV16fIiV16fUsIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reducepd512_mask, "V8dV8dIiV8dUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reduceps512_mask, "V16fV16fIiV16fUsIi", "", "avx512dq")
#undef BUILTIN
+#undef TARGET_BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td
index e1a2312..723ea54 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td
@@ -59,6 +59,7 @@ def Named : Decl<1>;
def VarTemplate : DDecl<RedeclarableTemplate>;
def TypeAliasTemplate : DDecl<RedeclarableTemplate>;
def TemplateTemplateParm : DDecl<Template>;
+ def BuiltinTemplate : DDecl<Template>;
def Using : DDecl<Named>;
def UsingShadow : DDecl<Named>;
def ObjCMethod : DDecl<Named>, DeclContext;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
index 3b7c282..1d6c19b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
@@ -864,28 +864,27 @@ public:
/// the common fields to registers, eliminating increments of the NumArgs field,
/// for example.
class DiagnosticBuilder {
- mutable DiagnosticsEngine *DiagObj;
- mutable unsigned NumArgs;
+ mutable DiagnosticsEngine *DiagObj = nullptr;
+ mutable unsigned NumArgs = 0;
/// \brief Status variable indicating if this diagnostic is still active.
///
// NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)),
// but LLVM is not currently smart enough to eliminate the null check that
// Emit() would end up with if we used that as our status variable.
- mutable bool IsActive;
+ mutable bool IsActive = false;
/// \brief Flag indicating that this diagnostic is being emitted via a
/// call to ForceEmit.
- mutable bool IsForceEmit;
+ mutable bool IsForceEmit = false;
void operator=(const DiagnosticBuilder &) = delete;
friend class DiagnosticsEngine;
- DiagnosticBuilder()
- : DiagObj(nullptr), NumArgs(0), IsActive(false), IsForceEmit(false) {}
+ DiagnosticBuilder() = default;
explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
- : DiagObj(diagObj), NumArgs(0), IsActive(true), IsForceEmit(false) {
+ : DiagObj(diagObj), IsActive(true) {
assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!");
diagObj->DiagRanges.clear();
diagObj->DiagFixItHints.clear();
@@ -1077,14 +1076,14 @@ operator<<(const DiagnosticBuilder &DB, T *DC) {
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
- const SourceRange &R) {
+ SourceRange R) {
DB.AddSourceRange(CharSourceRange::getTokenRange(R));
return DB;
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
ArrayRef<SourceRange> Ranges) {
- for (const SourceRange &R: Ranges)
+ for (SourceRange R : Ranges)
DB.AddSourceRange(CharSourceRange::getTokenRange(R));
return DB;
}
@@ -1264,7 +1263,7 @@ class StoredDiagnostic {
std::vector<FixItHint> FixIts;
public:
- StoredDiagnostic();
+ StoredDiagnostic() = default;
StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
StringRef Message);
@@ -1272,7 +1271,6 @@ public:
StringRef Message, FullSourceLoc Loc,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> Fixits);
- ~StoredDiagnostic();
/// \brief Evaluates true when this object stores a diagnostic.
explicit operator bool() const { return Message.size() > 0; }
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
index fc3ca62..ccc271a 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -84,6 +84,10 @@ def err_module_not_built : Error<"could not build module '%0'">, DefaultFatal;
def err_module_build_disabled: Error<
"module '%0' is needed but has not been provided, and implicit use of module "
"files is disabled">, DefaultFatal;
+def err_module_unavailable : Error<
+ "module '%0' %select{is incompatible with|requires}1 feature '%2'">;
+def err_module_header_missing : Error<
+ "%select{|umbrella }0header '%1' not found">;
def err_module_lock_failure : Error<
"could not acquire lock file for module '%0'">, DefaultFatal;
def err_module_lock_timeout : Error<
@@ -194,9 +198,8 @@ def err_unable_to_make_temp : Error<
"unable to make temporary file: %0">;
// Modules
-def err_module_file_conflict : Error<"module '%0' found in both '%1' and '%2'">;
def err_module_format_unhandled : Error<
- "no handler registered for module format '%0'">;
+ "no handler registered for module format '%0'">, DefaultFatal;
// TransformActions
// TODO: Use a custom category name to distinguish rewriter errors.
@@ -208,4 +211,7 @@ def note_mt_message : Note<"[rewriter] %0">;
def warn_arcmt_nsalloc_realloc : Warning<"[rewriter] call returns pointer to GC managed memory; it will become unmanaged in ARC">;
def err_arcmt_nsinvocation_ownership : Error<"NSInvocation's %0 is not safe to be used with an object with ownership other than __unsafe_unretained">;
+// OpenMP
+def err_omp_more_one_clause : Error<
+ "directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier| with 'source' dependence}2">;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
index f7f09da..b04498f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -22,6 +22,7 @@ def err_drv_unknown_stdin_type_clang_cl : Error<
def err_drv_unknown_language : Error<"language not recognized: '%0'">;
def err_drv_invalid_arch_name : Error<
"invalid arch name '%0'">;
+def err_drv_cuda_bad_gpu_arch : Error<"Unsupported CUDA gpu architecture: %0">;
def err_drv_invalid_thread_model_for_target : Error<
"invalid thread model '%0' in '%1' for this target">;
def err_drv_invalid_linker_name : Error<
@@ -81,6 +82,8 @@ def err_drv_invalid_mfloat_abi : Error<
"invalid float ABI '%0'">;
def err_drv_invalid_libcxx_deployment : Error<
"invalid deployment target for -stdlib=libc++ (requires %0 or later)">;
+def err_drv_invalid_argument_to_fdebug_prefix_map : Error<
+ "invalid argument '%0' to -fdebug-prefix-map">;
def err_drv_malformed_sanitizer_blacklist : Error<
"malformed sanitizer blacklist: '%0'">;
@@ -100,12 +103,18 @@ def err_drv_cc_print_options_failure : Error<
"unable to open CC_PRINT_OPTIONS file: %0">;
def err_drv_preamble_format : Error<
"incorrect format for -preamble-bytes=N,END">;
+def err_drv_conflicting_deployment_targets : Error<
+ "conflicting deployment targets, both '%0' and '%1' are present in environment">;
def err_drv_objc_gc_arr : Error<
"cannot specify both '-fobjc-arc' and '%0'">;
def err_arc_unsupported_on_runtime : Error<
"-fobjc-arc is not supported on platforms using the legacy runtime">;
def err_arc_unsupported_on_toolchain : Error< // feel free to generalize this
"-fobjc-arc is not supported on versions of OS X prior to 10.6">;
+def err_objc_weak_with_gc : Error<
+ "-fobjc-weak is not supported in Objective-C garbage collection">;
+def err_objc_weak_unsupported : Error<
+ "-fobjc-weak is not supported on the current deployment target">;
def err_drv_mg_requires_m_or_mm : Error<
"option '-MG' requires '-M' or '-MM'">;
def err_drv_unknown_objc_runtime : Error<
@@ -115,8 +124,13 @@ def err_drv_emit_llvm_link : Error<
def err_drv_optimization_remark_pattern : Error<
"%0 in '%1'">;
def err_drv_no_neon_modifier : Error<"[no]neon is not accepted as modifier, please use [no]simd instead">;
+def err_drv_invalid_omp_target : Error<"OpenMP target is invalid: '%0'">;
+def err_drv_omp_host_ir_file_not_found : Error<
+ "The provided host compiler IR file '%0' is required to generate code for OpenMP target regions but cannot be found.">;
def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
+def warn_drv_lto_libpath : Warning<"libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead">,
+ InGroup<LibLTO>;
def warn_drv_optimization_value : Warning<"optimization level '%0' is not supported; using '%1%2' instead">,
InGroup<InvalidCommandLineArgument>;
def warn_ignored_gcc_optimization : Warning<"optimization flag '%0' is not supported">,
@@ -183,6 +197,10 @@ def err_drv_modules_validate_once_requires_timestamp : Error<
"option '-fmodules-validate-once-per-build-session' requires "
"'-fbuild-session-timestamp=<seconds since Epoch>' or '-fbuild-session-file=<file>'">;
+def err_test_module_file_extension_format : Error<
+ "-ftest-module-file-extension argument '%0' is not of the required form "
+ "'blockname:major:minor:hashed:user info'">;
+
def warn_drv_invoking_fallback : Warning<"falling back to %0">,
InGroup<Fallback>;
@@ -192,4 +210,18 @@ def warn_target_unsupported_nan2008 : Warning<
def warn_target_unsupported_nanlegacy : Warning<
"ignoring '-mnan=legacy' option because the '%0' architecture does not support it">,
InGroup<UnsupportedNan>;
+
+def warn_drv_unable_to_find_directory_expected : Warning<
+ "unable to find %0 directory, expected to be in '%1'">,
+ InGroup<InvalidOrNonExistentDirectory>, DefaultIgnore;
+
+def warn_drv_ps4_force_pic : Warning<
+ "option '%0' was ignored by the PS4 toolchain, using '-fPIC'">,
+ InGroup<OptionIgnored>;
+
+def warn_drv_ps4_sdk_dir : Warning<
+ "environment variable SCE_PS4_SDK_DIR is set, but points to invalid or nonexistent directory '%0'">,
+ InGroup<InvalidOrNonExistentDirectory>;
+
+def err_drv_unsupported_linker : Error<"unsupported value '%0' for -linker option">;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index f4ab480..033834b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -45,6 +45,17 @@ def remark_fe_backend_optimization_remark_missed : Remark<"%0">, BackendInfo,
InGroup<BackendOptimizationRemarkMissed>;
def remark_fe_backend_optimization_remark_analysis : Remark<"%0">, BackendInfo,
InGroup<BackendOptimizationRemarkAnalysis>;
+def remark_fe_backend_optimization_remark_analysis_fpcommute : Remark<"%0; "
+ "allow reordering by specifying '#pragma clang loop vectorize(enable)' "
+ "before the loop or by providing the compiler option '-ffast-math'.">,
+ BackendInfo, InGroup<BackendOptimizationRemarkAnalysis>;
+def remark_fe_backend_optimization_remark_analysis_aliasing : Remark<"%0; "
+ "allow reordering by specifying '#pragma clang loop vectorize(enable)' "
+ "before the loop. If the arrays will always be independent specify "
+ "'#pragma clang loop vectorize(assume_safety)' before the loop or provide "
+ "the '__restrict__' qualifier with the independent array arguments. "
+ "Erroneous results will occur if these options are incorrectly applied!">,
+ BackendInfo, InGroup<BackendOptimizationRemarkAnalysis>;
def warn_fe_backend_optimization_failure : Warning<"%0">, BackendInfo,
InGroup<BackendOptimizationFailure>, DefaultWarn;
def note_fe_backend_optimization_remark_invalid_loc : Note<"could "
@@ -161,6 +172,9 @@ def warn_incompatible_analyzer_plugin_api : Warning<
def note_incompatible_analyzer_plugin_api : Note<
"current API version is '%0', but plugin was compiled with version '%1'">;
+def warn_module_config_mismatch : Warning<
+ "module file %0 cannot be loaded due to a configuration mismatch with the current "
+ "compilation">, InGroup<DiagGroup<"module-file-config-mismatch">>, DefaultError;
def err_module_map_not_found : Error<"module map file '%0' not found">,
DefaultFatal;
def err_missing_module_name : Error<
@@ -173,10 +187,6 @@ def err_no_submodule_suggest : Error<
"no submodule named %0 in module '%1'; did you mean '%2'?">;
def warn_missing_submodule : Warning<"missing submodule '%0'">,
InGroup<IncompleteUmbrella>;
-def err_module_unavailable : Error<
- "module '%0' %select{is incompatible with|requires}1 feature '%2'">;
-def err_module_header_missing : Error<
- "%select{|umbrella }0header '%1' not found">;
def err_module_cannot_create_includes : Error<
"cannot create includes file for module %0: %1">;
def warn_module_config_macro_undef : Warning<
@@ -190,20 +200,17 @@ def remark_module_build : Remark<"building module '%0' as '%1'">,
InGroup<ModuleBuild>;
def remark_module_build_done : Remark<"finished building module '%0'">,
InGroup<ModuleBuild>;
+def err_modules_embed_file_not_found :
+ Error<"file '%0' specified by '-fmodules-embed-file=' not found">,
+ DefaultFatal;
+
+def err_test_module_file_extension_version : Error<
+ "test module file extension '%0' has different version (%1.%2) than expected "
+ "(%3.%4)">;
def err_conflicting_module_names : Error<
"conflicting module names specified: '-fmodule-name=%0' and "
"'-fmodule-implementation-of %1'">;
-def err_conflicting_module_files : Error<
- "module '%0' is defined in both '%1' and '%2'">;
-def err_module_file_not_found : Error<
- "module file '%0' not found">, DefaultFatal;
-def err_module_file_invalid : Error<
- "file '%0' is not a valid precompiled module file">, DefaultFatal;
-def note_module_file_imported_by : Note<
- "imported by %select{|module '%2' in }1'%0'">;
-def err_module_file_not_module : Error<
- "AST file '%0' was not built as a module">, DefaultFatal;
def err_missing_vfs_overlay_file : Error<
"virtual filesystem overlay file '%0' not found">, DefaultFatal;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
index 4ecd5d5..2e4e57b 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
@@ -24,14 +24,17 @@ def : DiagGroup<"aggregate-return">;
def GNUAlignofExpression : DiagGroup<"gnu-alignof-expression">;
def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
def GNUAnonymousStruct : DiagGroup<"gnu-anonymous-struct">;
+def GNUAutoType : DiagGroup<"gnu-auto-type">;
def ArrayBounds : DiagGroup<"array-bounds">;
def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">;
def Availability : DiagGroup<"availability">;
def Section : DiagGroup<"section">;
def AutoImport : DiagGroup<"auto-import">;
+def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">;
def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">;
def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">;
def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">;
+def BitFieldWidth : DiagGroup<"bitfield-width">;
def ConstantConversion :
DiagGroup<"constant-conversion", [ BitFieldConstantConversion ] >;
def LiteralConversion : DiagGroup<"literal-conversion">;
@@ -44,6 +47,7 @@ def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion,
def IntConversion : DiagGroup<"int-conversion">;
def EnumConversion : DiagGroup<"enum-conversion">;
def FloatConversion : DiagGroup<"float-conversion">;
+def DoublePromotion : DiagGroup<"double-promotion">;
def EnumTooLarge : DiagGroup<"enum-too-large">;
def UnsupportedNan : DiagGroup<"unsupported-nan">;
def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">;
@@ -79,6 +83,7 @@ def AbstractFinalClass : DiagGroup<"abstract-final-class">;
def CXX11CompatDeprecatedWritableStr :
DiagGroup<"c++11-compat-deprecated-writable-strings">;
+def DeprecatedAttributes : DiagGroup<"deprecated-attributes">;
def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
def UnavailableDeclarations : DiagGroup<"unavailable-declarations">;
def PartialAvailability : DiagGroup<"partial-availability">;
@@ -88,12 +93,14 @@ def DeprecatedRegister : DiagGroup<"deprecated-register">;
def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings",
[CXX11CompatDeprecatedWritableStr]>;
// FIXME: Why is DeprecatedImplementations not in this group?
-def Deprecated : DiagGroup<"deprecated", [DeprecatedDeclarations,
+def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes,
+ DeprecatedDeclarations,
DeprecatedIncrementBool,
DeprecatedRegister,
DeprecatedWritableStr]>,
DiagCategory<"Deprecations">;
+def LibLTO : DiagGroup<"liblto">;
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
def : DiagGroup<"div-by-zero">;
@@ -180,6 +187,9 @@ def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre1zCompat]>;
def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic",
[CXXPre1zCompatPedantic]>;
+def CXX1zCompat : DiagGroup<"c++1z-compat", [DeprecatedRegister,
+ DeprecatedIncrementBool]>;
+
def : DiagGroup<"effc++">;
def DivZero : DiagGroup<"division-by-zero">;
def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
@@ -195,10 +205,12 @@ def DanglingElse: DiagGroup<"dangling-else">;
def DanglingField : DiagGroup<"dangling-field">;
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
def FlagEnum : DiagGroup<"flag-enum">;
+def IncrementBool : DiagGroup<"increment-bool", [DeprecatedIncrementBool]>;
def InfiniteRecursion : DiagGroup<"infinite-recursion">;
def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
+def GNUIncludeNext : DiagGroup<"gnu-include-next">;
def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">;
def IncompatiblePointerTypesDiscardsQualifiers
: DiagGroup<"incompatible-pointer-types-discards-qualifiers">;
@@ -213,6 +225,7 @@ def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module",
def IncompleteModule : DiagGroup<"incomplete-module",
[IncompleteUmbrella, NonModularIncludeInModule]>;
+def CXX11InlineNamespace : DiagGroup<"c++11-inline-namespace">;
def InvalidNoreturn : DiagGroup<"invalid-noreturn">;
def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">;
def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">;
@@ -247,6 +260,7 @@ def MismatchedTags : DiagGroup<"mismatched-tags">;
def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
def ModuleBuild : DiagGroup<"module-build">;
def ModuleConflict : DiagGroup<"module-conflict">;
+def ModuleFileExtension : DiagGroup<"module-file-extension">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;
def NullabilityDeclSpec : DiagGroup<"nullability-declspec">;
@@ -304,6 +318,7 @@ def : DiagGroup<"redundant-decls">;
def RedeclaredClassMember : DiagGroup<"redeclared-class-member">;
def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">;
def RedundantMove : DiagGroup<"redundant-move">;
+def Register : DiagGroup<"register", [DeprecatedRegister]>;
def ReturnStackAddress : DiagGroup<"return-stack-address">;
def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">;
def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>;
@@ -601,6 +616,7 @@ def Most : DiagGroup<"most", [
CharSubscript,
Comment,
DeleteNonVirtualDtor,
+ ForLoopAnalysis,
Format,
Implicit,
InfiniteRecursion,
@@ -648,7 +664,10 @@ def Consumed : DiagGroup<"consumed">;
// Note that putting warnings in -Wall will not disable them by default. If a
// warning should be active _only_ when -Wall is passed in, mark it as
// DefaultIgnore in addition to putting it here.
-def : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool]>;
+def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool]>;
+
+// Warnings that should be in clang-cl /w4.
+def : DiagGroup<"CL4", [All, Extra]>;
// Warnings enabled by -pedantic. This is magically filled in by TableGen.
def Pedantic : DiagGroup<"pedantic">;
@@ -675,11 +694,12 @@ def NonGCC : DiagGroup<"non-gcc",
// A warning group for warnings about using C++11 features as extensions in
// earlier C++ versions.
-def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11LongLong]>;
+def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11InlineNamespace,
+ CXX11LongLong]>;
// A warning group for warnings about using C++14 features as extensions in
// earlier C++ versions.
-def CXX14 : DiagGroup<"c++14-extensions">;
+def CXX14 : DiagGroup<"c++14-extensions", [CXX14BinaryLiteral]>;
// A warning group for warnings about using C++1z features as extensions in
// earlier C++ versions.
@@ -699,13 +719,15 @@ def C99 : DiagGroup<"c99-extensions">;
// A warning group for warnings about GCC extensions.
def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
+ GNUAutoType,
GNUBinaryLiteral, GNUCaseRange,
GNUComplexInteger, GNUCompoundLiteralInitializer,
GNUConditionalOmittedOperand, GNUDesignator,
GNUEmptyInitializer, GNUEmptyStruct,
VLAExtension, GNUFlexibleArrayInitializer,
GNUFlexibleArrayUnionMember, GNUFoldingConstant,
- GNUImaginaryConstant, GNULabelsAsValue,
+ GNUImaginaryConstant, GNUIncludeNext,
+ GNULabelsAsValue,
RedeclaredClassMember, GNURedeclaredEnum,
GNUStatementExpression, GNUStaticFloatInit,
GNUStringLiteralOperatorTemplate,
@@ -715,8 +737,52 @@ def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
// A warning group for warnings about code that clang accepts but gcc doesn't.
def GccCompat : DiagGroup<"gcc-compat">;
-// A warning group for warnings about Microsoft extensions.
-def Microsoft : DiagGroup<"microsoft">;
+// Warnings for Microsoft extensions.
+def MicrosoftCharize : DiagGroup<"microsoft-charize">;
+def MicrosoftInclude : DiagGroup<"microsoft-include">;
+def MicrosoftCppMacro : DiagGroup<"microsoft-cpp-macro">;
+def MicrosoftFixedEnum : DiagGroup<"microsoft-fixed-enum">;
+def MicrosoftSealed : DiagGroup<"microsoft-sealed">;
+def MicrosoftUnqualifiedFriend : DiagGroup<"microsoft-unqualified-friend">;
+def MicrosoftExceptionSpec : DiagGroup<"microsoft-exception-spec">;
+def MicrosoftUsingDecl : DiagGroup<"microsoft-using-decl">;
+def MicrosoftMutableReference : DiagGroup<"microsoft-mutable-reference">;
+def MicrosoftPureDefinition : DiagGroup<"microsoft-pure-definition">;
+def MicrosoftUnionMemberReference : DiagGroup<
+ "microsoft-union-member-reference">;
+def MicrosoftExplicitConstructorCall : DiagGroup<
+ "microsoft-explicit-constructor-call">;
+def MicrosoftEnumValue : DiagGroup<"microsoft-enum-value">;
+def MicrosoftDefaultArgRedefinition :
+ DiagGroup<"microsoft-default-arg-redefinition">;
+def MicrosoftTemplate : DiagGroup<"microsoft-template">;
+def MicrosoftRedeclareStatic : DiagGroup<"microsoft-redeclare-static">;
+def MicrosoftEnumForwardReference :
+ DiagGroup<"microsoft-enum-forward-reference">;
+def MicrosoftGoto : DiagGroup<"microsoft-goto">;
+def MicrosoftFlexibleArray : DiagGroup<"microsoft-flexible-array">;
+def MicrosoftExtraQualification : DiagGroup<"microsoft-extra-qualification">;
+def MicrosoftCast : DiagGroup<"microsoft-cast">;
+def MicrosoftConstInit : DiagGroup<"microsoft-const-init">;
+def MicrosoftVoidPseudoDtor : DiagGroup<"microsoft-void-pseudo-dtor">;
+def MicrosoftAnonTag : DiagGroup<"microsoft-anon-tag">;
+def MicrosoftCommentPaste : DiagGroup<"microsoft-comment-paste">;
+def MicrosoftEndOfFile : DiagGroup<"microsoft-end-of-file">;
+// Aliases.
+def : DiagGroup<"msvc-include", [MicrosoftInclude]>;
+ // -Wmsvc-include = -Wmicrosoft-include
+
+// Warnings group for warnings about Microsoft extensions.
+def Microsoft : DiagGroup<"microsoft",
+ [MicrosoftCharize, MicrosoftInclude, MicrosoftCppMacro, MicrosoftFixedEnum,
+ MicrosoftSealed, MicrosoftUnqualifiedFriend, MicrosoftExceptionSpec,
+ MicrosoftUsingDecl, MicrosoftMutableReference, MicrosoftPureDefinition,
+ MicrosoftUnionMemberReference, MicrosoftExplicitConstructorCall,
+ MicrosoftEnumValue, MicrosoftDefaultArgRedefinition, MicrosoftTemplate,
+ MicrosoftRedeclareStatic, MicrosoftEnumForwardReference, MicrosoftGoto,
+ MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast,
+ MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag,
+ MicrosoftCommentPaste, MicrosoftEndOfFile]>;
def ObjCNonUnifiedException : DiagGroup<"objc-nonunified-exceptions">;
@@ -777,3 +843,7 @@ def CudaCompat : DiagGroup<"cuda-compat">;
// A warning group for things that will change semantics in the future.
def FutureCompat : DiagGroup<"future-compat">;
+
+def InvalidOrNonExistentDirectory : DiagGroup<"invalid-or-nonexistent-directory">;
+
+def OptionIgnored : DiagGroup<"option-ignored">;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
index a675dfa..312b71f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
@@ -29,7 +29,7 @@ namespace clang {
enum {
DIAG_START_COMMON = 0,
DIAG_START_DRIVER = DIAG_START_COMMON + 300,
- DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
+ DIAG_START_FRONTEND = DIAG_START_DRIVER + 200,
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100,
DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
DIAG_START_PARSE = DIAG_START_LEX + 300,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
index 5dd4ae0..2fc9664 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -13,9 +13,8 @@
let Component = "Lex", CategoryName = "Lexical or Preprocessor Issue" in {
-def null_in_string : Warning<"null character(s) preserved in string literal">,
- InGroup<NullCharacter>;
-def null_in_char : Warning<"null character(s) preserved in character literal">,
+def null_in_char_or_string : Warning<
+ "null character(s) preserved in %select{char|string}0 literal">,
InGroup<NullCharacter>;
def null_in_file : Warning<"null character ignored">, InGroup<NullCharacter>;
def warn_nested_block_comment : Warning<"'/*' within block comment">,
@@ -57,8 +56,15 @@ def warn_cxx98_compat_no_newline_eof : Warning<
def ext_dollar_in_identifier : Extension<"'$' in identifier">,
InGroup<DiagGroup<"dollar-in-identifier-extension">>;
-def ext_charize_microsoft : Extension<"charizing operator #@ is a Microsoft extension">,
- InGroup<Microsoft>;
+def ext_charize_microsoft : Extension<
+ "charizing operator #@ is a Microsoft extension">,
+ InGroup<MicrosoftCharize>;
+def ext_comment_paste_microsoft : Extension<
+ "pasting two '/' tokens into a '//' comment is a Microsoft extension">,
+ InGroup<MicrosoftCommentPaste>;
+def ext_ctrl_z_eof_microsoft : Extension<
+ "treating Ctrl-Z as end-of-file is a Microsoft extension">,
+ InGroup<MicrosoftEndOfFile>;
def ext_token_used : Extension<"extension used">,
InGroup<DiagGroup<"language-extension-token">>;
@@ -66,10 +72,8 @@ def ext_token_used : Extension<"extension used">,
def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">,
InGroup<CXX11Compat>, DefaultIgnore;
-def ext_unterminated_string : ExtWarn<"missing terminating '\"' character">,
- InGroup<InvalidPPToken>;
-def ext_unterminated_char : ExtWarn<"missing terminating ' character">,
- InGroup<InvalidPPToken>;
+def ext_unterminated_char_or_string : ExtWarn<
+ "missing terminating %select{'|'\"'}0 character">, InGroup<InvalidPPToken>;
def ext_empty_character : ExtWarn<"empty character constant">,
InGroup<InvalidPPToken>;
def err_unterminated_block_comment : Error<"unterminated /* comment">;
@@ -153,13 +157,10 @@ def ext_nonstandard_escape : Extension<
"use of non-standard escape character '\\%0'">;
def ext_unknown_escape : ExtWarn<"unknown escape sequence '\\%0'">,
InGroup<DiagGroup<"unknown-escape-sequence">>;
-def err_invalid_decimal_digit : Error<"invalid digit '%0' in decimal constant">;
-def err_invalid_binary_digit : Error<"invalid digit '%0' in binary constant">;
-def err_invalid_octal_digit : Error<"invalid digit '%0' in octal constant">;
-def err_invalid_suffix_integer_constant : Error<
- "invalid suffix '%0' on integer constant">;
-def err_invalid_suffix_float_constant : Error<
- "invalid suffix '%0' on floating constant">;
+def err_invalid_digit : Error<
+ "invalid digit '%0' in %select{decimal|octal|binary}1 constant">;
+def err_invalid_suffix_constant : Error<
+ "invalid suffix '%0' on %select{integer|floating}1 constant">;
def warn_cxx11_compat_digit_separator : Warning<
"digit separators are incompatible with C++ standards before C++14">,
InGroup<CXXPre14Compat>, DefaultIgnore;
@@ -174,22 +175,20 @@ def err_multichar_utf_character_literal : Error<
def err_exponent_has_no_digits : Error<"exponent has no digits">;
def ext_imaginary_constant : Extension<
"imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>;
-def err_hexconstant_requires_exponent : Error<
- "hexadecimal floating constants require an exponent">;
-def err_hexconstant_requires_digits : Error<
- "hexadecimal floating constants require a significand">;
+def err_hexconstant_requires: Error<
+ "hexadecimal floating constants require %select{an exponent|a significand}0">;
def ext_hexconstant_invalid : Extension<
"hexadecimal floating constants are a C99 feature">, InGroup<C99>;
def ext_binary_literal : Extension<
"binary integer literals are a GNU extension">, InGroup<GNUBinaryLiteral>;
def ext_binary_literal_cxx14 : Extension<
- "binary integer literals are a C++14 extension">, InGroup<CXX14>;
+ "binary integer literals are a C++14 extension">, InGroup<CXX14BinaryLiteral>;
def warn_cxx11_compat_binary_literal : Warning<
"binary integer literals are incompatible with C++ standards before C++14">,
InGroup<CXXPre14CompatPedantic>, DefaultIgnore;
def err_pascal_string_too_long : Error<"Pascal string is too long">;
-def err_octal_escape_too_large : Error<"octal escape sequence out of range">;
-def err_hex_escape_too_large : Error<"hex escape sequence out of range">;
+def err_escape_too_large : Error<
+ "%select{hex|octal}0 escape sequence out of range">;
def ext_string_too_long : Extension<"string literal of length %0 exceeds "
"maximum length %1 that %select{C90|ISO C99|C++}2 compilers are required to "
"support">, InGroup<OverlengthStrings>;
@@ -255,10 +254,13 @@ def err_pp_hash_error : Error<"%0">;
}
def pp_include_next_in_primary : Warning<
- "#include_next in primary source file">;
+ "#include_next in primary source file">,
+ InGroup<DiagGroup<"include-next-outside-header">>;
def pp_include_macros_out_of_predefines : Error<
"the #__include_macros directive is only for internal use by -imacros">;
-def pp_include_next_absolute_path : Warning<"#include_next with absolute path">;
+def pp_include_next_absolute_path : Warning<
+ "#include_next with absolute path">,
+ InGroup<DiagGroup<"include-next-absolute-path">>;
def ext_c99_whitespace_required_after_macro_name : ExtWarn<
"ISO C99 requires whitespace after the macro name">, InGroup<C99>;
def ext_missing_whitespace_after_macro_name : ExtWarn<
@@ -266,9 +268,11 @@ def ext_missing_whitespace_after_macro_name : ExtWarn<
def warn_missing_whitespace_after_macro_name : Warning<
"whitespace recommended after macro name">;
-def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">;
+def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">,
+ InGroup<DiagGroup<"pragma-once-outside-header">>;
def pp_pragma_sysheader_in_main_file : Warning<
- "#pragma system_header ignored in main file">;
+ "#pragma system_header ignored in main file">,
+ InGroup<DiagGroup<"pragma-system-header-outside-header">>;
def pp_poisoning_existing_macro : Warning<"poisoning existing macro">;
def pp_out_of_date_dependency : Warning<
"current file is older than dependency %0">;
@@ -295,27 +299,29 @@ def warn_pp_macro_hides_keyword : Extension<
def warn_pp_macro_is_reserved_id : Warning<
"macro name is a reserved identifier">, DefaultIgnore,
InGroup<ReservedIdAsMacro>;
+def warn_pp_objc_macro_redef_ignored : Warning<
+ "ignoring redefinition of Objective-C qualifier macro">,
+ InGroup<DiagGroup<"objc-macro-redefinition">>;
def pp_invalid_string_literal : Warning<
"invalid string literal, ignoring final '\\'">;
def warn_pp_expr_overflow : Warning<
"integer overflow in preprocessor expression">;
-def warn_pp_convert_lhs_to_positive : Warning<
- "left side of operator converted from negative value to unsigned: %0">;
-def warn_pp_convert_rhs_to_positive : Warning<
- "right side of operator converted from negative value to unsigned: %0">;
+def warn_pp_convert_to_positive : Warning<
+ "%select{left|right}0 side of operator converted from negative value to "
+ "unsigned: %1">;
def ext_pp_import_directive : Extension<"#import is a language extension">,
InGroup<DiagGroup<"import-preprocessor-directive-pedantic">>;
def err_pp_import_directive_ms : Error<
"#import of type library is an unsupported Microsoft feature">;
def ext_pp_include_search_ms : ExtWarn<
- "#include resolved using non-portable MSVC search rules as: %0">,
- InGroup<DiagGroup<"msvc-include">>;
+ "#include resolved using non-portable Microsoft search rules as: %0">,
+ InGroup<MicrosoftInclude>;
def ext_pp_ident_directive : Extension<"#ident is a language extension">;
def ext_pp_include_next_directive : Extension<
- "#include_next is a language extension">;
+ "#include_next is a language extension">, InGroup<GNUIncludeNext>;
def ext_pp_warning_directive : Extension<"#warning is a language extension">;
def ext_pp_extra_tokens_at_eol : ExtWarn<
@@ -484,6 +490,8 @@ def warn_pragma_diagnostic_unknown_warning :
// - #pragma __debug
def warn_pragma_debug_unexpected_command : Warning<
"unexpected debug command '%0'">, InGroup<IgnoredPragmas>;
+def warn_pragma_debug_missing_argument : Warning<
+ "missing argument to debug command '%0'">, InGroup<IgnoredPragmas>;
def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
def err_paste_at_start : Error<
@@ -510,7 +518,7 @@ def ext_pp_bad_paste_ms : ExtWarn<
def err_pp_operator_used_as_macro_name : Error<
"C++ operator %0 (aka %1) used as a macro name">;
def ext_pp_operator_used_as_macro_name : Extension<
- "C++ operator %0 (aka %1) used as a macro name">, InGroup<Microsoft>;
+ err_pp_operator_used_as_macro_name.Text>, InGroup<MicrosoftCppMacro>;
def err_pp_illegal_floating_literal : Error<
"floating point literal in preprocessor expression">;
def err_pp_line_requires_integer : Error<
@@ -622,6 +630,8 @@ def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">,
def warn_auto_module_import : Warning<
"treating #%select{include|import|include_next|__include_macros}0 as an "
"import of module '%1'">, InGroup<AutoImport>, DefaultIgnore;
+def note_implicit_top_level_module_import_here : Note<
+ "submodule of top-level module '%0' implicitly imported here">;
def warn_uncovered_module_header : Warning<
"umbrella header for module '%0' does not include header '%1'">,
InGroup<IncompleteUmbrella>;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
index e4f8599..f8dee2f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -51,14 +51,6 @@ def warn_extra_semi_after_mem_fn_def : Warning<
"extra ';' after member function definition">,
InGroup<ExtraSemi>, DefaultIgnore;
-def ext_duplicate_declspec : ExtWarn<"duplicate '%0' declaration specifier">,
- InGroup<DuplicateDeclSpecifier>;
-def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">,
- InGroup<DuplicateDeclSpecifier>;
-def ext_plain_complex : ExtWarn<
- "plain '_Complex' requires a type specifier; assuming '_Complex double'">;
-def ext_integer_complex : Extension<
- "complex integer types are a GNU extension">, InGroup<GNUComplexInteger>;
def ext_thread_before : Extension<"'__thread' before '%0'">;
def ext_keyword_as_ident : ExtWarn<
"keyword '%0' will be made available as an identifier "
@@ -70,12 +62,6 @@ def ext_nullability : Extension<
InGroup<DiagGroup<"nullability-extension">>;
def error_empty_enum : Error<"use of empty enum">;
-def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
-def err_invalid_short_spec : Error<"'short %0' is invalid">;
-def err_invalid_long_spec : Error<"'long %0' is invalid">;
-def err_invalid_longlong_spec : Error<"'long long %0' is invalid">;
-def err_invalid_complex_spec : Error<"'_Complex %0' is invalid">;
-def err_friend_decl_spec : Error<"'%0' is invalid in friend declarations">;
def ext_ident_list_in_param : Extension<
"type-less parameter names in function declaration">;
@@ -101,7 +87,7 @@ def ext_cxx11_enum_fixed_underlying_type : Extension<
InGroup<CXX11>;
def ext_c_enum_fixed_underlying_type : Extension<
"enumeration types with a fixed underlying type are a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftFixedEnum>;
def warn_cxx98_compat_enum_fixed_underlying_type : Warning<
"enumeration types with a fixed underlying type are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
@@ -271,7 +257,7 @@ def warn_cxx98_compat_ref_qualifier : Warning<
"reference qualifiers on functions are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def ext_inline_namespace : ExtWarn<
- "inline namespaces are a C++11 feature">, InGroup<CXX11>;
+ "inline namespaces are a C++11 feature">, InGroup<CXX11InlineNamespace>;
def warn_cxx98_compat_inline_namespace : Warning<
"inline namespaces are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
@@ -286,11 +272,6 @@ def err_init_list_bin_op : Error<"initializer list cannot be used on the "
def warn_cxx98_compat_trailing_return_type : Warning<
"trailing return types are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
-def ext_auto_type_specifier : ExtWarn<
- "'auto' type specifier is a C++11 extension">, InGroup<CXX11>;
-def warn_auto_storage_class : Warning<
- "'auto' storage class specifier is redundant and incompatible with C++11">,
- InGroup<CXX11Compat>, DefaultIgnore;
def ext_auto_storage_class : ExtWarn<
"'auto' storage class specifier is not permitted in C++11, and will not "
"be supported in future releases">, InGroup<DiagGroup<"auto-storage-class">>;
@@ -299,6 +280,9 @@ def ext_decltype_auto_type_specifier : ExtWarn<
def warn_cxx11_compat_decltype_auto_type_specifier : Warning<
"'decltype(auto)' type specifier is incompatible with C++ standards before "
"C++14">, InGroup<CXXPre14Compat>, DefaultIgnore;
+def ext_auto_type : Extension<
+ "'__auto_type' is a GNU extension">,
+ InGroup<GNUAutoType>;
def ext_for_range : ExtWarn<
"range-based for loop is a C++11 extension">, InGroup<CXX11>;
def warn_cxx98_compat_for_range : Warning<
@@ -327,9 +311,6 @@ def err_unspecified_vla_size_with_static : Error<
"'static' may not be used with an unspecified variable length array size">;
def err_unspecified_size_with_static : Error<
"'static' may not be used without an array size">;
-def warn_deprecated_register : Warning<
- "'register' storage class specifier is deprecated">,
- InGroup<DeprecatedRegister>;
def err_expected_parentheses_around_typename : Error<
"expected parentheses around type name in %0 expression">;
@@ -348,39 +329,10 @@ def err_typename_invalid_constexpr : Error<
def err_typename_identifiers_only : Error<
"typename is allowed for identifiers only">;
-def err_invalid_decl_spec_combination : Error<
- "cannot combine with previous '%0' declaration specifier">;
-def err_invalid_vector_decl_spec_combination : Error<
- "cannot combine with previous '%0' declaration specifier. "
- "'__vector' must be first">;
-def err_invalid_pixel_decl_spec_combination : Error<
- "'__pixel' must be preceded by '__vector'. "
- "'%0' declaration specifier not allowed here">;
-def err_invalid_vector_bool_decl_spec : Error<
- "cannot use '%0' with '__vector bool'">;
-def err_invalid_vector_long_decl_spec : Error<
- "cannot use 'long' with '__vector'">;
-def err_invalid_vector_float_decl_spec : Error<
- "cannot use 'float' with '__vector'">;
-def err_invalid_vector_double_decl_spec : Error <
- "use of 'double' with '__vector' requires VSX support to be enabled "
- "(available on POWER7 or later)">;
-def err_invalid_vector_long_long_decl_spec : Error <
- "use of 'long long' with '__vector bool' requires VSX support (available on "
- "POWER7 or later) or extended Altivec support (available on POWER8 or later) "
- "to be enabled">;
-def err_invalid_vector_long_double_decl_spec : Error<
- "cannot use 'long double' with '__vector'">;
-def warn_vector_long_decl_spec_combination : Warning<
- "Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>;
def err_friend_invalid_in_context : Error<
"'friend' used outside of class">;
-def err_use_of_tag_name_without_tag : Error<
- "must use '%1' tag to refer to type %0%select{| in this scope}2">;
-def err_templated_using_directive : Error<
- "cannot template a using directive">;
-def err_templated_using_declaration : Error<
- "cannot template a using declaration">;
+def err_templated_using_directive_declaration : Error<
+ "cannot template a using %select{directive|declaration}0">;
def err_unexpected_colon_in_nested_name_spec : Error<
"unexpected ':' in nested name specifier; did you mean '::'?">;
def err_unexpected_token_in_nested_name_spec : Error<
@@ -512,7 +464,7 @@ def note_missing_end_of_definition_before : Note<
"still within definition of %q0 here">;
def ext_ellipsis_exception_spec : Extension<
"exception specification of '...' is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftExceptionSpec>;
def err_dynamic_and_noexcept_specification : Error<
"cannot have both throw() and noexcept() clause on the same function">;
def err_except_spec_unparsed : Error<
@@ -695,12 +647,9 @@ def warn_static_inline_explicit_inst_ignored : Warning<
// Constructor template diagnostics.
def err_out_of_line_constructor_template_id : Error<
"out-of-line constructor for %0 cannot have template arguments">;
-def err_out_of_line_template_id_names_constructor : Error<
+def err_out_of_line_template_id_type_names_constructor : Error<
"qualified reference to %0 is a constructor name rather than a "
- "template name wherever a constructor can be declared">;
-def err_out_of_line_type_names_constructor : Error<
- "qualified reference to %0 is a constructor name rather than a "
- "type wherever a constructor can be declared">;
+ "%select{template name|type}1 wherever a constructor can be declared">;
def err_expected_qualified_after_typename : Error<
"expected a qualified name after 'typename'">;
@@ -740,15 +689,11 @@ def err_missing_whitespace_digraph : Error<
"%select{template name|const_cast|dynamic_cast|reinterpret_cast|static_cast}0"
" which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?">;
-def ext_deleted_function : ExtWarn<
- "deleted function definitions are a C++11 extension">, InGroup<CXX11>;
-def warn_cxx98_compat_deleted_function : Warning<
- "deleted function definitions are incompatible with C++98">,
- InGroup<CXX98Compat>, DefaultIgnore;
-def ext_defaulted_function : ExtWarn<
- "defaulted function definitions are a C++11 extension">, InGroup<CXX11>;
-def warn_cxx98_compat_defaulted_function : Warning<
- "defaulted function definitions are incompatible with C++98">,
+def ext_defaulted_deleted_function : ExtWarn<
+ "%select{defaulted|deleted}0 function definitions are a C++11 extension">,
+ InGroup<CXX11>;
+def warn_cxx98_compat_defaulted_deleted_function : Warning<
+ "%select{defaulted|deleted}0 function definitions are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
// C++11 in-class member initialization
@@ -784,7 +729,7 @@ def err_override_control_interface : Error<
"'%0' keyword not permitted with interface types">;
def ext_ms_sealed_keyword : ExtWarn<
"'sealed' keyword is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftSealed>;
def err_access_specifier_interface : Error<
"interface types cannot specify '%select{private|protected}0' access">;
@@ -821,10 +766,6 @@ def warn_cxx98_compat_lambda : Warning<
def err_lambda_missing_parens : Error<
"lambda requires '()' before %select{'mutable'|return type|"
"attribute specifier}0">;
-def warn_init_capture_direct_list_init : Warning<
- "direct list initialization of a lambda init-capture will change meaning in "
- "a future version of Clang; insert an '=' to avoid a change in behavior">,
- InGroup<FutureCompat>;
// Availability attribute
def err_expected_version : Error<
@@ -945,7 +886,7 @@ def err_pragma_comment_malformed : Error<
def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">;
// PS4 recognizes only #pragma comment(lib)
def warn_pragma_comment_ignored : Warning<"'#pragma comment %0' ignored">,
- InGroup<Microsoft>;
+ InGroup<IgnoredPragmas>;
// - #pragma detect_mismatch
def err_pragma_detect_mismatch_malformed : Error<
"pragma detect_mismatch is malformed; it requires two comma-separated "
@@ -961,10 +902,6 @@ def err_pragma_optimize_invalid_argument : Error<
def err_pragma_optimize_extra_argument : Error<
"unexpected extra argument '%0' to '#pragma clang optimize'">;
-// OpenCL Section 6.8.g
-def err_opencl_unknown_type_specifier : Error<
- "OpenCL does not support the '%0' %select{type qualifier|storage class specifier}1">;
-
// OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
def warn_pragma_expected_colon : Warning<
"missing ':' after %0 - ignoring">, InGroup<IgnoredPragmas>;
@@ -973,12 +910,18 @@ def warn_pragma_expected_enable_disable : Warning<
def warn_pragma_unknown_extension : Warning<
"unknown OpenCL extension %0 - ignoring">, InGroup<IgnoredPragmas>;
+// OpenCL error
+def err_opencl_taking_function_address_parser : Error<
+ "taking address of function is not allowed">;
+
// OpenMP support.
def warn_pragma_omp_ignored : Warning<
"unexpected '#pragma omp ...' in program">, InGroup<SourceUsesOpenMP>, DefaultIgnore;
def warn_omp_extra_tokens_at_eol : Warning<
"extra tokens at the end of '#pragma omp %0' are ignored">,
InGroup<ExtraTokens>;
+def warn_pragma_expected_colon_r_paren : Warning<
+ "missing ':' or ')' after %0 - ignoring">, InGroup<IgnoredPragmas>;
def err_omp_unknown_directive : Error<
"expected an OpenMP directive">;
def err_omp_unexpected_directive : Error<
@@ -987,22 +930,26 @@ def err_omp_expected_punc : Error<
"expected ',' or ')' in '%0' %select{clause|directive}1">;
def err_omp_unexpected_clause : Error<
"unexpected OpenMP clause '%0' in directive '#pragma omp %1'">;
-def err_omp_more_one_clause : Error<
- "directive '#pragma omp %0' cannot contain more than one '%1' clause">;
def err_omp_immediate_directive : Error<
- "'#pragma omp %0' cannot be an immediate substatement">;
+ "'#pragma omp %0' %select{|with '%2' clause }1cannot be an immediate substatement">;
def err_omp_expected_identifier_for_critical : Error<
"expected identifier specifying the name of the 'omp critical' directive">;
+def err_omp_unknown_map_type : Error<
+ "incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">;
+def err_omp_unknown_map_type_modifier : Error<
+ "incorrect map type modifier, expected 'always'">;
+def err_omp_map_type_missing : Error<
+ "missing map type">;
// Pragma loop support.
def err_pragma_loop_missing_argument : Error<
"missing argument; expected %select{an integer value|"
- "%select{'enable', 'assume_safety'|'full'}1 or 'disable'}0">;
+ "'enable', %select{'assume_safety'|'full'}1 or 'disable'}0">;
def err_pragma_loop_invalid_option : Error<
"%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
"vectorize_width, interleave, interleave_count, unroll, or unroll_count">;
def err_pragma_invalid_keyword : Error<
- "invalid argument; expected %select{'enable', 'assume_safety'|'full'}0 or 'disable'">;
+ "invalid argument; expected 'enable', %select{'assume_safety'|'full'}0 or 'disable'">;
// Pragma unroll support.
def warn_pragma_unroll_cuda_value_in_parens : Warning<
@@ -1015,6 +962,7 @@ def err_module_expected_ident : Error<
"expected a module name after module import">;
def err_module_expected_semi : Error<
"expected ';' after module name">;
+def err_missing_before_module_end : Error<"expected %0 at end of module">;
}
let CategoryName = "Generics Issue" in {
@@ -1029,4 +977,9 @@ def err_objc_type_args_after_protocols : Error<
"protocol qualifiers must precede type arguments">;
}
+let CategoryName = "Coroutines Issue" in {
+def err_for_co_await_not_range_for : Error<
+ "'co_await' modifier can only be applied to range-based for loop">;
+}
+
} // end of Parser diagnostics
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 82f5121..6ba482c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1,4 +1,3 @@
-
//==--- DiagnosticSemaKinds.td - libsema diagnostics ----------------------===//
//
// The LLVM Compiler Infrastructure
@@ -67,6 +66,9 @@ def warn_wrong_absolute_value_type : Warning<
"when argument is of %select{integer|floating point|complex}2 type">,
InGroup<AbsoluteValue>;
def note_replace_abs_function : Note<"use function '%0' instead">;
+def warn_pointer_abs : Warning<
+ "taking the absolute value of %select{pointer|function|array}0 type %1 is suspicious">,
+ InGroup<AbsoluteValue>;
def warn_infinite_recursive_function : Warning<
"all paths through this function will call itself">,
@@ -188,6 +190,63 @@ def ext_flexible_array_init : Extension<
"flexible array initialization is a GNU extension">, InGroup<GNUFlexibleArrayInitializer>;
// Declarations.
+def ext_duplicate_declspec : ExtWarn<"duplicate '%0' declaration specifier">,
+ InGroup<DuplicateDeclSpecifier>;
+def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">,
+ InGroup<DuplicateDeclSpecifier>;
+def ext_plain_complex : ExtWarn<
+ "plain '_Complex' requires a type specifier; assuming '_Complex double'">;
+def ext_integer_complex : Extension<
+ "complex integer types are a GNU extension">, InGroup<GNUComplexInteger>;
+
+def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
+def err_invalid_width_spec : Error<
+ "'%select{|short|long|long long}0 %1' is invalid">;
+def err_invalid_complex_spec : Error<"'_Complex %0' is invalid">;
+def err_friend_decl_spec : Error<"'%0' is invalid in friend declarations">;
+
+def ext_auto_type_specifier : ExtWarn<
+ "'auto' type specifier is a C++11 extension">, InGroup<CXX11>;
+def warn_auto_storage_class : Warning<
+ "'auto' storage class specifier is redundant and incompatible with C++11">,
+ InGroup<CXX11Compat>, DefaultIgnore;
+
+def warn_deprecated_register : Warning<
+ "'register' storage class specifier is deprecated "
+ "and incompatible with C++1z">, InGroup<DeprecatedRegister>;
+def ext_register_storage_class : ExtWarn<
+ "ISO C++1z does not allow 'register' storage class specifier">,
+ DefaultError, InGroup<Register>;
+
+def err_invalid_decl_spec_combination : Error<
+ "cannot combine with previous '%0' declaration specifier">;
+def err_invalid_vector_decl_spec_combination : Error<
+ "cannot combine with previous '%0' declaration specifier. "
+ "'__vector' must be first">;
+def err_invalid_pixel_decl_spec_combination : Error<
+ "'__pixel' must be preceded by '__vector'. "
+ "'%0' declaration specifier not allowed here">;
+def err_invalid_vector_bool_decl_spec : Error<
+ "cannot use '%0' with '__vector bool'">;
+def err_invalid_vector_long_decl_spec : Error<
+ "cannot use 'long' with '__vector'">;
+def err_invalid_vector_float_decl_spec : Error<
+ "cannot use 'float' with '__vector'">;
+def err_invalid_vector_double_decl_spec : Error <
+ "use of 'double' with '__vector' requires VSX support to be enabled "
+ "(available on POWER7 or later)">;
+def err_invalid_vector_long_long_decl_spec : Error <
+ "use of 'long long' with '__vector bool' requires VSX support (available on "
+ "POWER7 or later) or extended Altivec support (available on POWER8 or later) "
+ "to be enabled">;
+def err_invalid_vector_long_double_decl_spec : Error<
+ "cannot use 'long double' with '__vector'">;
+def warn_vector_long_decl_spec_combination : Warning<
+ "Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>;
+
+def err_use_of_tag_name_without_tag : Error<
+ "must use '%1' tag to refer to type %0%select{| in this scope}2">;
+
def err_redeclaration_different_type : Error<
"redeclaration of %0 with a different type%diff{: $ vs $|}1,2">;
def err_bad_variable_name : Error<
@@ -195,6 +254,10 @@ def err_bad_variable_name : Error<
def err_bad_parameter_name : Error<
"%0 cannot be the name of a parameter">;
def err_parameter_name_omitted : Error<"parameter name omitted">;
+def warn_mips_interrupt_attribute : Warning<
+ "MIPS 'interrupt' attribute only applies to functions that have "
+ "%select{no parameters|a 'void' return type}0">,
+ InGroup<IgnoredAttributes>;
def warn_unused_parameter : Warning<"unused parameter %0">,
InGroup<UnusedParameter>, DefaultIgnore;
def warn_unused_variable : Warning<"unused variable %0">,
@@ -416,7 +479,8 @@ def note_unreachable_silence : Note<
/// Built-in functions.
def ext_implicit_lib_function_decl : ExtWarn<
- "implicitly declaring library function '%0' with type %1">;
+ "implicitly declaring library function '%0' with type %1">,
+ InGroup<ImplicitFunctionDeclare>;
def note_include_header_or_declare : Note<
"include the header <%0> or explicitly provide a declaration for '%1'">;
def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">;
@@ -429,6 +493,11 @@ def warn_redecl_library_builtin : Warning<
def err_builtin_definition : Error<"definition of builtin function %0">;
def err_arm_invalid_specialreg : Error<"invalid special register for builtin">;
def err_invalid_cpu_supports : Error<"invalid cpu feature string for builtin">;
+def err_builtin_needs_feature : Error<"%0 needs target feature %1">;
+def err_function_needs_feature
+ : Error<"always_inline function %1 requires target feature '%2', but would "
+ "be inlined into function %0 that is compiled without support for "
+ "'%2'">;
def warn_builtin_unknown : Warning<"use of unknown builtin %0">,
InGroup<ImplicitFunctionDeclare>, DefaultError;
def warn_dyn_class_memaccess : Warning<
@@ -510,6 +579,10 @@ def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">,
def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 "
"parameter of 'main' (%select{argument count|argument array|environment|"
"platform-specific data}0) must be of type %1">;
+def err_main_global_variable :
+ Error<"main cannot be declared as global variable">;
+def warn_main_redefined : Warning<"variable named 'main' with external linkage "
+ "has undefined behavior">, InGroup<Main>;
def ext_main_used : Extension<
"ISO C++ does not allow 'main' to be used by a program">, InGroup<Main>;
@@ -548,14 +621,14 @@ def err_pragma_options_align_mac68k_target_unsupported : Error<
def warn_pragma_pack_invalid_alignment : Warning<
"expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">,
InGroup<IgnoredPragmas>;
-// Follow the MSVC implementation.
+// Follow the Microsoft implementation.
def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">;
def warn_pragma_pack_pop_identifer_and_alignment : Warning<
"specifying both a name and alignment to 'pop' is undefined">;
def warn_pragma_pop_failed : Warning<"#pragma %0(pop, ...) failed: %1">,
InGroup<IgnoredPragmas>;
def warn_cxx_ms_struct :
- Warning<"ms_struct may not produce MSVC-compatible layouts for classes "
+ Warning<"ms_struct may not produce Microsoft-compatible layouts for classes "
"with base classes or virtual functions">,
DefaultError, InGroup<IncompatibleMSStruct>;
def err_section_conflict : Error<"%0 causes a section type conflict with %1">;
@@ -856,6 +929,9 @@ def warn_missing_explicit_synthesis : Warning <
def warn_property_getter_owning_mismatch : Warning<
"property declared as returning non-retained objects"
"; getter returning retained objects">;
+def warn_property_redecl_getter_mismatch : Warning<
+ "getter name mismatch between property redeclaration (%1) and its original "
+ "declaration (%0)">, InGroup<PropertyAttr>;
def error_property_setter_ambiguous_use : Error<
"synthesized properties %0 and %1 both claim setter %2 -"
" use of this setter will cause unexpected behavior">;
@@ -878,7 +954,8 @@ def err_property_type : Error<"property cannot have array or function type %0">;
def error_missing_property_context : Error<
"missing context for property implementation declaration">;
def error_bad_property_decl : Error<
- "property implementation must have its declaration in interface %0">;
+ "property implementation must have its declaration in interface %0 or one of "
+ "its extensions">;
def error_category_property : Error<
"property declared in category %0 cannot be implemented in "
"class implementation">;
@@ -901,8 +978,6 @@ def error_bad_property_context : Error<
def error_missing_property_ivar_decl : Error<
"synthesized property %0 must either be named the same as a compatible"
" instance variable or must explicitly name an instance variable">;
-def error_synthesize_weak_non_arc_or_gc : Error<
- "@synthesize of 'weak' property is only allowed in ARC or GC mode">;
def err_arc_perform_selector_retains : Error<
"performSelector names a selector which retains the object">;
def warn_arc_perform_selector_leaks : Warning<
@@ -1058,7 +1133,7 @@ def warn_template_qualified_friend_ignored : Warning<
def ext_friend_tag_redecl_outside_namespace : ExtWarn<
"unqualified friend declaration referring to type outside of the nearest "
"enclosing namespace is a Microsoft extension; add a nested name specifier">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftUnqualifiedFriend>;
def err_pure_friend : Error<"friend declaration cannot have a pure-specifier">;
def err_invalid_member_in_interface : Error<
@@ -1096,10 +1171,15 @@ def err_type_defined_in_param_type : Error<
"%0 cannot be defined in a parameter type">;
def err_type_defined_in_alias_template : Error<
"%0 cannot be defined in a type alias template">;
+def err_type_defined_in_condition : Error<
+ "%0 cannot be defined in a condition">;
def note_pure_virtual_function : Note<
"unimplemented pure virtual method %0 in %1">;
+def note_pure_qualified_call_kext : Note<
+ "qualified call to %0::%1 is treated as a virtual call to %1 due to -fapple-kext">;
+
def err_deleted_decl_not_first : Error<
"deleted definition must be first declaration">;
@@ -1134,21 +1214,25 @@ def err_rref_in_exception_spec : Error<
"rvalue reference type %0 is not allowed in exception specification">;
def err_mismatched_exception_spec : Error<
"exception specification in declaration does not match previous declaration">;
-def ext_mismatched_exception_spec : ExtWarn<
- "exception specification in declaration does not match previous declaration">,
- InGroup<Microsoft>;
+def ext_mismatched_exception_spec : ExtWarn<err_mismatched_exception_spec.Text>,
+ InGroup<MicrosoftExceptionSpec>;
def err_override_exception_spec : Error<
"exception specification of overriding function is more lax than "
"base version">;
-def ext_override_exception_spec : ExtWarn<
- "exception specification of overriding function is more lax than "
- "base version">, InGroup<Microsoft>;
+def ext_override_exception_spec : ExtWarn<err_override_exception_spec.Text>,
+ InGroup<MicrosoftExceptionSpec>;
def err_incompatible_exception_specs : Error<
"target exception specification is not superset of source">;
def err_deep_exception_specs_differ : Error<
"exception specifications of %select{return|argument}0 types differ">;
-def warn_missing_exception_specification : Warning<
+def err_missing_exception_specification : Error<
"%0 is missing exception specification '%1'">;
+def ext_missing_exception_specification : ExtWarn<
+ err_missing_exception_specification.Text>,
+ InGroup<DiagGroup<"missing-exception-spec">>;
+def ext_ms_missing_exception_specification : ExtWarn<
+ err_missing_exception_specification.Text>,
+ InGroup<MicrosoftExceptionSpec>;
def err_noexcept_needs_constant_expression : Error<
"argument to noexcept specifier must be a constant expression">;
def err_exception_spec_not_parsed : Error<
@@ -1162,7 +1246,7 @@ def err_access : Error<
def ext_ms_using_declaration_inaccessible : ExtWarn<
"using declaration referring to inaccessible member '%0' (which refers "
"to accessible member '%1') is a Microsoft compatibility extension">,
- AccessControl, InGroup<Microsoft>;
+ AccessControl, InGroup<MicrosoftUsingDecl>;
def err_access_ctor : Error<
"calling a %select{private|protected}0 constructor of class %2">,
AccessControl;
@@ -1268,7 +1352,7 @@ def err_mutable_function : Error<"'mutable' cannot be applied to functions">;
def err_mutable_reference : Error<"'mutable' cannot be applied to references">;
def ext_mutable_reference : ExtWarn<
"'mutable' on a reference type is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftMutableReference>;
def err_mutable_const : Error<"'mutable' and 'const' cannot be mixed">;
def err_mutable_nonmember : Error<
"'mutable' can only be applied to member variables">;
@@ -1304,7 +1388,7 @@ def err_non_virtual_pure : Error<
"%0 is not virtual and cannot be declared pure">;
def ext_pure_function_definition : ExtWarn<
"function definition with pure-specifier is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftPureDefinition>;
def err_implicit_object_parameter_init : Error<
"cannot initialize object parameter of type %0 with an expression "
"of type %1">;
@@ -1312,8 +1396,9 @@ def err_qualified_member_of_unrelated : Error<
"%q0 is not a member of class %1">;
def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning<
- "call to pure virtual member function %0; overrides of %0 in subclasses are "
- "not available in the %select{constructor|destructor}1 of %2">;
+ "call to pure virtual member function %0 has undefined behavior; "
+ "overrides of %0 in subclasses are not available in the "
+ "%select{constructor|destructor}1 of %2">;
def note_member_declared_at : Note<"member is declared here">;
def note_ivar_decl : Note<"instance variable is declared here">;
@@ -1382,7 +1467,7 @@ def warn_cxx98_compat_static_data_member_in_union : Warning<
InGroup<CXX98Compat>, DefaultIgnore;
def ext_union_member_of_reference_type : ExtWarn<
"union member %0 has reference type %1, which is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftUnionMemberReference>;
def err_union_member_of_reference_type : Error<
"union member %0 has reference type %1">;
def ext_anonymous_struct_union_qualified : Extension<
@@ -1437,7 +1522,8 @@ def warn_no_constructor_for_refconst : Warning<
def note_refconst_member_not_initialized : Note<
"%select{const|reference}0 member %1 will never be initialized">;
def ext_ms_explicit_constructor_call : ExtWarn<
- "explicit constructor calls are a Microsoft extension">, InGroup<Microsoft>;
+ "explicit constructor calls are a Microsoft extension">,
+ InGroup<MicrosoftExplicitConstructorCall>;
// C++ destructors
def err_destructor_not_member : Error<
@@ -1649,18 +1735,22 @@ def warn_cxx98_compat_auto_type_specifier : Warning<
"'auto' type specifier is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def err_auto_variable_cannot_appear_in_own_initializer : Error<
- "variable %0 declared with 'auto' type cannot appear in its own initializer">;
+ "variable %0 declared with %select{'auto'|'decltype(auto)'|'__auto_type'}1 "
+ "type cannot appear in its own initializer">;
def err_illegal_decl_array_of_auto : Error<
"'%0' declared as array of %1">;
def err_new_array_of_auto : Error<
"cannot allocate array of 'auto'">;
def err_auto_not_allowed : Error<
- "%select{'auto'|'decltype(auto)'}0 not allowed %select{in function prototype"
- "|in non-static struct member"
- "|in non-static union member|in non-static class member|in interface member"
+ "%select{'auto'|'decltype(auto)'|'__auto_type'}0 not allowed "
+ "%select{in function prototype"
+ "|in non-static struct member|in struct member"
+ "|in non-static union member|in union member"
+ "|in non-static class member|in interface member"
"|in exception declaration|in template parameter|in block literal"
"|in template argument|in typedef|in type alias|in function return type"
- "|in conversion function type|here|in lambda parameter}1">;
+ "|in conversion function type|here|in lambda parameter"
+ "|in type allocated by 'new'|in K&R-style function parameter}1">;
def err_auto_not_allowed_var_inst : Error<
"'auto' variable template instantiation is not allowed">;
def err_auto_var_requires_init : Error<
@@ -1674,12 +1764,8 @@ def err_auto_var_init_no_expression : Error<
def err_auto_var_init_multiple_expressions : Error<
"initializer for variable %0 with type %1 contains multiple expressions">;
def err_auto_var_init_paren_braces : Error<
- "cannot deduce type for variable %0 with type %1 from "
- "parenthesized initializer list">;
-def warn_auto_var_direct_list_init : Warning<
- "direct list initialization of a variable with a deduced type will change "
- "meaning in a future version of Clang; insert an '=' to avoid a change in "
- "behavior">, InGroup<FutureCompat>;
+ "cannot deduce type for variable %1 with type %2 from "
+ "%select{parenthesized|nested}0 initializer list">;
def err_auto_new_ctor_multiple_expressions : Error<
"new expression for type %0 contains multiple constructor arguments">;
def err_auto_missing_trailing_return : Error<
@@ -1698,8 +1784,8 @@ def err_auto_var_deduction_failure_from_init_list : Error<
def err_auto_new_deduction_failure : Error<
"new expression for type %0 has incompatible constructor argument of type %1">;
def err_auto_different_deductions : Error<
- "'%select{auto|decltype(auto)}0' deduced as %1 in declaration of %2 and "
- "deduced as %3 in declaration of %4">;
+ "'%select{auto|decltype(auto)|__auto_type}0' deduced as %1 in declaration "
+ "of %2 and deduced as %3 in declaration of %4">;
def err_implied_std_initializer_list_not_found : Error<
"cannot deduce type of initializer list because std::initializer_list was "
"not found; include <initializer_list>">;
@@ -1709,6 +1795,10 @@ def warn_dangling_std_initializer_list : Warning<
"array backing the initializer list will be destroyed at the end of "
"%select{the full-expression|the constructor}0">,
InGroup<DiagGroup<"dangling-initializer-list">>;
+def err_auto_init_list_from_c : Error<
+ "cannot use __auto_type with initializer list in C">;
+def err_auto_bitfield : Error<
+ "cannot pass bit-field as __auto_type initializer in C">;
// C++1y decltype(auto) type
def err_decltype_auto_cannot_be_combined : Error<
@@ -1768,7 +1858,7 @@ def err_enumerator_too_large : Error<
"enumerator value is not representable in the underlying type %0">;
def ext_enumerator_too_large : ExtWarn<
"enumerator value is not representable in the underlying type %0">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftEnumValue>;
def err_enumerator_wrapped : Error<
"enumerator value %0 is not representable in the underlying type %1">;
def err_enum_redeclare_type_mismatch : Error<
@@ -1961,11 +2051,34 @@ def warn_private_extern : Warning<
def note_private_extern : Note<
"use __attribute__((visibility(\"hidden\"))) attribute instead">;
+// C++ Concepts TS
+def err_concept_wrong_decl_kind : Error<
+ "'concept' can only appear on the definition of a function template or variable template">;
+def err_concept_decls_may_only_appear_in_namespace_scope : Error<
+ "concept declarations may only appear in namespace scope">;
+def err_function_concept_not_defined : Error<
+ "function concept declaration must be a definition">;
+def err_var_concept_not_initialized : Error<
+ "variable concept declaration must be initialized">;
+def err_function_concept_exception_spec : Error<
+ "function concept cannot have exception specification">;
+def err_concept_decl_invalid_specifiers : Error<
+ "%select{variable|function}0 concept cannot be declared "
+ "'%select{thread_local|inline|friend|constexpr}1'">;
+def err_function_concept_with_params : Error<
+ "function concept cannot have any parameters">;
+
// C++11 char16_t/char32_t
def warn_cxx98_compat_unicode_type : Warning<
"'%0' type specifier is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
-
+
+// __make_integer_seq
+def err_integer_sequence_negative_length : Error<
+ "integer sequences must have non-negative sequence length">;
+def err_integer_sequence_integral_element_type : Error<
+ "integer sequences must have integral element type">;
+
// Objective-C++
def err_objc_decls_may_only_appear_in_global_scope : Error<
"Objective-C declarations may only appear in global scope">;
@@ -2016,8 +2129,7 @@ def err_attribute_argument_type : Error<
"%0 attribute requires %select{int or bool|an integer "
"constant|a string|an identifier}1">;
def err_attribute_argument_outof_range : Error<
- "init_priority attribute requires integer constant between "
- "101 and 65535 inclusive">;
+ "%0 attribute requires integer constant between %1 and %2 inclusive">;
def err_init_priority_object_attr : Error<
"can only use 'init_priority' attribute on file-scope definitions "
"of objects of class type">;
@@ -2025,10 +2137,12 @@ def err_attribute_argument_vec_type_hint : Error<
"invalid attribute argument %0 - expecting a vector or vectorizable scalar type">;
def err_attribute_argument_out_of_bounds : Error<
"%0 attribute parameter %1 is out of bounds">;
+def err_attribute_only_once_per_parameter : Error<
+ "%0 attribute can only be applied once per parameter">;
def err_attribute_uuid_malformed_guid : Error<
"uuid attribute contains a malformed GUID">;
def warn_attribute_pointers_only : Warning<
- "%0 attribute only applies to pointer arguments">,
+ "%0 attribute only applies to%select{| constant}1 pointer arguments">,
InGroup<IgnoredAttributes>;
def err_attribute_pointers_only : Error<warn_attribute_pointers_only.Text>;
def warn_attribute_return_pointers_only : Warning<
@@ -2066,9 +2180,9 @@ def err_attribute_invalid_size : Error<
def err_attribute_zero_size : Error<"zero vector size">;
def err_attribute_size_too_large : Error<"vector size too large">;
def err_typecheck_vector_not_convertable : Error<
- "can't convert between vector values of different size (%0 and %1)">;
+ "cannot convert between vector values of different size (%0 and %1)">;
def err_typecheck_vector_not_convertable_non_scalar : Error<
- "can't convert between vector and non-scalar values (%0 and %1)">;
+ "cannot convert between vector and non-scalar values (%0 and %1)">;
def err_typecheck_vector_lengths_not_equal : Error<
"vector operands do not have the same number of elements (%0 and %1)">;
def err_ext_vector_component_exceeds_length : Error<
@@ -2091,25 +2205,18 @@ def err_field_with_address_space : Error<
"field may not be qualified with an address space">;
def err_attr_objc_ownership_redundant : Error<
"the type %0 is already explicitly ownership-qualified">;
-def err_undeclared_nsnumber : Error<
- "NSNumber must be available to use Objective-C literals">;
-def err_undeclared_nsvalue : Error<
- "NSValue must be available to use Objective-C boxed expressions">;
def err_invalid_nsnumber_type : Error<
"%0 is not a valid literal type for NSNumber">;
-def err_undeclared_nsstring : Error<
- "cannot box a string value because NSString has not been declared">;
def err_objc_illegal_boxed_expression_type : Error<
"illegal type %0 used in a boxed expression">;
def err_objc_non_trivially_copyable_boxed_expression_type : Error<
"non-trivially copyable type %0 cannot be used in a boxed expression">;
def err_objc_incomplete_boxed_expression_type : Error<
"incomplete type %0 used in a boxed expression">;
-def err_undeclared_nsarray : Error<
- "NSArray must be available to use Objective-C array literals">;
-def err_undeclared_nsdictionary : Error<
- "NSDictionary must be available to use Objective-C dictionary "
- "literals">;
+def err_undeclared_objc_literal_class : Error<
+ "definition of class %0 must be available to use Objective-C "
+ "%select{array literals|dictionary literals|numeric literals|boxed expressions|"
+ "string literals}1">;
def err_undeclared_boxing_method : Error<
"declaration of %0 is missing in %1 class">;
def err_objc_literal_method_sig : Error<
@@ -2258,6 +2365,8 @@ def err_attribute_dll_not_extern : Error<
"%q0 must have external linkage when declared %q1">;
def err_attribute_dll_thread_local : Error<
"%q0 cannot be thread local when declared %q1">;
+def err_attribute_dll_lambda : Error<
+ "lambda cannot be declared %0">;
def warn_attribute_invalid_on_definition : Warning<
"'%0' attribute cannot be specified on a definition">,
InGroup<IgnoredAttributes>;
@@ -2290,6 +2399,8 @@ def warn_attribute_dll_instantiated_base_class : Warning<
"propagating dll attribute to %select{already instantiated|explicitly specialized}0 "
"base class template without dll attribute is not supported">,
InGroup<DiagGroup<"unsupported-dll-base-class-template">>, DefaultIgnore;
+def err_attribute_dll_ambiguous_default_ctor : Error<
+ "'__declspec(dllexport)' cannot be applied to more than one default constructor in %0">;
def err_attribute_weakref_not_static : Error<
"weakref declaration must have internal linkage">;
def err_attribute_weakref_not_global_context : Error<
@@ -2323,7 +2434,7 @@ def warn_attribute_wrong_decl_type : Warning<
"Objective-C instance methods|init methods of interface or class extension declarations|"
"variables, functions and classes|Objective-C protocols|"
"functions and global variables|structs, unions, and typedefs|structs and typedefs|"
- "interface or protocol declarations|kernel functions}1">,
+ "interface or protocol declarations|kernel functions|non-K&R-style functions}1">,
InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>;
def warn_type_attribute_wrong_type : Warning<
@@ -2359,6 +2470,9 @@ def err_cconv_varargs : Error<
def warn_cconv_varargs : Warning<
"%0 calling convention ignored on variadic function">,
InGroup<IgnoredAttributes>;
+def warn_cconv_structors : Warning<
+ "%0 calling convention ignored on constructor/destructor">,
+ InGroup<IgnoredAttributes>;
def err_regparm_mismatch : Error<"function declared with regparm(%0) "
"attribute was previously declared "
"%plural{0:without the regparm|:with the regparm(%1)}1 attribute">;
@@ -2375,6 +2489,8 @@ def warn_attribute_not_on_decl : Warning<
"%0 attribute ignored when parsing type">, InGroup<IgnoredAttributes>;
def err_base_specifier_attribute : Error<
"%0 attribute cannot be applied to a base specifier">;
+def err_invalid_attribute_on_virtual_function : Error<
+ "%0 attribute cannot be applied to virtual functions">;
// Availability attribute
def warn_availability_unknown_platform : Warning<
@@ -2386,15 +2502,19 @@ def warn_availability_version_ordering : Warning<
def warn_mismatched_availability: Warning<
"availability does not match previous declaration">, InGroup<Availability>;
def warn_mismatched_availability_override : Warning<
- "overriding method %select{introduced after|"
- "deprecated before|obsoleted before}0 overridden method on %1 (%2 vs. %3)">,
- InGroup<Availability>;
+ "%select{|overriding }4method %select{introduced after|"
+ "deprecated before|obsoleted before}0 "
+ "%select{the protocol method it implements|overridden method}4 "
+ "on %1 (%2 vs. %3)">, InGroup<Availability>;
def warn_mismatched_availability_override_unavail : Warning<
- "overriding method cannot be unavailable on %0 when its overridden method is "
+ "%select{|overriding }1method cannot be unavailable on %0 when "
+ "%select{the protocol method it implements|its overridden method}1 is "
"available">,
InGroup<Availability>;
def note_overridden_method : Note<
"overridden method is here">;
+def note_protocol_method : Note<
+ "protocol method is here">;
// Thread Safety Attributes
def warn_invalid_capability_name : Warning<
@@ -2559,6 +2679,9 @@ def warn_impcast_complex_scalar : Warning<
def warn_impcast_float_precision : Warning<
"implicit conversion loses floating-point precision: %0 to %1">,
InGroup<Conversion>, DefaultIgnore;
+def warn_impcast_double_promotion : Warning<
+ "implicit conversion increases floating-point precision: %0 to %1">,
+ InGroup<DoublePromotion>, DefaultIgnore;
def warn_impcast_float_integer : Warning<
"implicit conversion turns floating-point number into integer: %0 to %1">,
InGroup<FloatConversion>, DefaultIgnore;
@@ -2601,13 +2724,16 @@ def warn_impcast_null_pointer_to_integer : Warning<
def warn_impcast_floating_point_to_bool : Warning<
"implicit conversion turns floating-point number into bool: %0 to %1">,
InGroup<ImplicitConversionFloatingPointToBool>;
+def ext_ms_impcast_fn_obj : ExtWarn<
+ "implicit conversion between pointer-to-function and pointer-to-object is a "
+ "Microsoft extension">, InGroup<MicrosoftCast>;
def warn_impcast_pointer_to_bool : Warning<
"address of%select{| function| array}0 '%1' will always evaluate to "
"'true'">,
InGroup<PointerBoolConversion>;
def warn_cast_nonnull_to_bool : Warning<
- "nonnull parameter '%0' will evaluate to "
+ "nonnull %select{function call|parameter}0 '%1' will evaluate to "
"'true' on first encounter">,
InGroup<PointerBoolConversion>;
def warn_this_bool_conversion : Warning<
@@ -2622,9 +2748,10 @@ def warn_null_pointer_compare : Warning<
"comparison of %select{address of|function|array}0 '%1' %select{not |}2"
"equal to a null pointer is always %select{true|false}2">,
InGroup<TautologicalPointerCompare>;
-def warn_nonnull_parameter_compare : Warning<
- "comparison of nonnull parameter '%0' %select{not |}1"
- "equal to a null pointer is %select{true|false}1 on first encounter">,
+def warn_nonnull_expr_compare : Warning<
+ "comparison of nonnull %select{function call|parameter}0 '%1' "
+ "%select{not |}2equal to a null pointer is '%select{true|false}2' on first "
+ "encounter">,
InGroup<TautologicalPointerCompare>;
def warn_this_null_compare : Warning<
"'this' pointer cannot be null in well-defined C++ code; comparison may be "
@@ -2664,9 +2791,10 @@ def warn_int_to_void_pointer_cast : Warning<
"cast to %1 from smaller integer type %0">,
InGroup<IntToVoidPointerCast>;
-def warn_attribute_ignored_for_field_of_type : Warning<
- "%0 attribute ignored for field of type %1">,
- InGroup<IgnoredAttributes>;
+def warn_attribute_packed_for_bitfield : Warning<
+ "'packed' attribute was ignored on bit-fields with single-byte alignment "
+ "in older versions of GCC and Clang">,
+ InGroup<DiagGroup<"attribute-packed-for-bitfield">>;
def warn_transparent_union_attribute_field_size_align : Warning<
"%select{alignment|size}0 of field %1 (%2 bits) does not match the "
"%select{alignment|size}0 of the first field in transparent union; "
@@ -2710,6 +2838,10 @@ def err_mode_not_primitive : Error<
"mode attribute only supported for integer and floating-point types">;
def err_mode_wrong_type : Error<
"type of machine mode does not match type of base type">;
+def warn_vector_mode_deprecated : Warning<
+ "specifying vector types with the 'mode' attribute is deprecated; "
+ "use the 'vector_size' attribute instead">,
+ InGroup<DeprecatedAttributes>;
def err_complex_mode_vector_type : Error<
"type of machine mode does not support base vector types">;
def err_attr_wrong_decl : Error<
@@ -2852,7 +2984,8 @@ def err_param_default_argument : Error<
def err_param_default_argument_redefinition : Error<
"redefinition of default argument">;
def ext_param_default_argument_redefinition : ExtWarn<
- "redefinition of default argument">, InGroup<Microsoft>;
+ err_param_default_argument_redefinition.Text>,
+ InGroup<MicrosoftDefaultArgRedefinition>;
def err_param_default_argument_missing : Error<
"missing default argument on parameter">;
def err_param_default_argument_missing_name : Error<
@@ -2877,7 +3010,7 @@ def err_param_default_argument_on_parameter_pack : Error<
"parameter pack cannot have a default argument">;
def err_uninitialized_member_for_assign : Error<
"cannot define the implicit copy assignment operator for %0, because "
- "non-static %select{reference|const}1 member %2 can't use copy "
+ "non-static %select{reference|const}1 member %2 cannot use copy "
"assignment operator">;
def err_uninitialized_member_in_ctor : Error<
"%select{|implicit default |inheriting }0constructor for %1 must explicitly "
@@ -2961,17 +3094,29 @@ def note_ovl_candidate_instantiation_depth : Note<
"candidate template ignored: substitution exceeded maximum template "
"instantiation depth">;
def note_ovl_candidate_underqualified : Note<
- "candidate template ignored: can't deduce a type for %0 that would "
+ "candidate template ignored: cannot deduce a type for %0 that would "
"make %2 equal %1">;
def note_ovl_candidate_substitution_failure : Note<
"candidate template ignored: substitution failure%0%1">;
def note_ovl_candidate_disabled_by_enable_if : Note<
"candidate template ignored: disabled by %0%1">;
+def note_ovl_candidate_has_pass_object_size_params: Note<
+ "candidate address cannot be taken because parameter %0 has "
+ "pass_object_size attribute">;
def note_ovl_candidate_disabled_by_enable_if_attr : Note<
"candidate disabled: %0">;
+def err_addrof_function_disabled_by_enable_if_attr : Error<
+ "cannot take address of function %0 becuase it has one or more "
+ "non-tautological enable_if conditions">;
+def note_addrof_ovl_candidate_disabled_by_enable_if_attr : Note<
+ "candidate function made ineligible by enable_if">;
def note_ovl_candidate_failed_overload_resolution : Note<
"candidate template ignored: couldn't resolve reference to overloaded "
"function %0">;
+def note_ovl_candidate_deduced_mismatch : Note<
+ "candidate template ignored: deduced type "
+ "%diff{$ of %ordinal0 parameter does not match adjusted type $ of argument"
+ "|of %ordinal0 parameter does not match adjusted type of argument}1,2%3">;
def note_ovl_candidate_non_deduced_mismatch : Note<
"candidate template ignored: could not match %diff{$ against $|types}0,1">;
// This note is needed because the above note would sometimes print two
@@ -2979,7 +3124,7 @@ def note_ovl_candidate_non_deduced_mismatch : Note<
// can handle that case properly.
def note_ovl_candidate_non_deduced_mismatch_qualified : Note<
"candidate template ignored: could not match %q0 against %q1">;
-
+
// Note that we don't treat templates differently for this diagnostic.
def note_ovl_candidate_arity : Note<"candidate "
"%select{function|function|constructor|function|function|constructor|"
@@ -3251,7 +3396,7 @@ def err_addr_ovl_ambiguous : Error<
def err_addr_ovl_not_func_ptrref : Error<
"address of overloaded function %0 cannot be converted to type %1">;
def err_addr_ovl_no_qualifier : Error<
- "can't form member pointer of type %0 without '&' and class name">;
+ "cannot form member pointer of type %0 without '&' and class name">;
// C++11 Literal Operators
def err_ovl_no_viable_literal_operator : Error<
@@ -3344,11 +3489,12 @@ def note_template_decl_here : Note<"template is declared here">;
def err_template_arg_must_be_type : Error<
"template argument for template type parameter must be a type">;
def err_template_arg_must_be_type_suggest : Error<
- "template argument for template type parameter must be a type; did you forget 'typename'?">;
+ "template argument for template type parameter must be a type; "
+ "did you forget 'typename'?">;
def ext_ms_template_type_arg_missing_typename : ExtWarn<
"template argument for template type parameter must be a type; "
"omitted 'typename' is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftTemplate>;
def err_template_arg_must_be_expr : Error<
"template argument for non-type template parameter must be an expression">;
def err_template_arg_nontype_ambig : Error<
@@ -3468,10 +3614,10 @@ def err_pointer_to_member_oper_value_classify: Error<
"%select{rvalue|lvalue}1">;
def ext_ms_deref_template_argument: ExtWarn<
"non-type template argument containing a dereference operation is a "
- "Microsoft extension">, InGroup<Microsoft>;
+ "Microsoft extension">, InGroup<MicrosoftTemplate>;
def ext_ms_delayed_template_argument: ExtWarn<
"using the undeclared type %0 as a default template argument is a "
- "Microsoft extension">, InGroup<Microsoft>;
+ "Microsoft extension">, InGroup<MicrosoftTemplate>;
// C++ template specialization
def err_template_spec_unknown_kind : Error<
@@ -3519,7 +3665,7 @@ def ext_ms_template_spec_redecl_out_of_scope: ExtWarn<
"variable template partial|function template|member "
"function|static data member|member class|member enumeration}0 "
"specialization of %1 outside namespace enclosing %2 "
- "is a Microsoft extension">, InGroup<Microsoft>;
+ "is a Microsoft extension">, InGroup<MicrosoftTemplate>;
def err_template_spec_redecl_global_scope : Error<
"%select{class template|class template partial|variable template|"
"variable template partial|function template|member "
@@ -3544,7 +3690,7 @@ def err_function_specialization_in_class : Error<
"cannot specialize a function %0 within class scope">;
def ext_function_specialization_in_class : ExtWarn<
"explicit specialization of %0 within class scope is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftTemplate>;
def ext_explicit_specialization_storage_class : ExtWarn<
"explicit specialization cannot have a storage class">;
def err_explicit_specialization_inconsistent_storage_class : Error<
@@ -3705,7 +3851,7 @@ def err_explicit_instantiation_duplicate : Error<
"duplicate explicit instantiation of %0">;
def ext_explicit_instantiation_duplicate : ExtWarn<
"duplicate explicit instantiation of %0 ignored as a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftTemplate>;
def note_previous_explicit_instantiation : Note<
"previous explicit instantiation is here">;
def ext_explicit_instantiation_after_specialization : Extension<
@@ -3790,10 +3936,11 @@ def err_invalid_var_template_spec_type : Error<"type %2 "
"partial specialization|redeclaration}0 of %1 does not match"
" expected type %3">;
def err_mismatched_exception_spec_explicit_instantiation : Error<
- "exception specification in explicit instantiation does not match instantiated one">;
+ "exception specification in explicit instantiation does not match "
+ "instantiated one">;
def ext_mismatched_exception_spec_explicit_instantiation : ExtWarn<
- "exception specification in explicit instantiation does not match instantiated one">,
- InGroup<Microsoft>;
+ err_mismatched_exception_spec_explicit_instantiation.Text>,
+ InGroup<MicrosoftExceptionSpec>;
// C++ typename-specifiers
def err_typename_nested_not_found : Error<"no type named %0 in %1">;
@@ -3911,10 +4058,10 @@ def err_undeclared_var_use : Error<"use of undeclared identifier %0">;
def ext_undeclared_unqual_id_with_dependent_base : ExtWarn<
"use of undeclared identifier %0; "
"unqualified lookup into dependent bases of class template %1 is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftTemplate>;
def ext_found_via_dependent_bases_lookup : ExtWarn<"use of identifier %0 "
"found via unqualified lookup into dependent bases of class templates is a "
- "Microsoft extension">, InGroup<Microsoft>;
+ "Microsoft extension">, InGroup<MicrosoftTemplate>;
def note_dependent_var_use : Note<"must qualify identifier to find this "
"declaration in dependent base class">;
def err_not_found_by_two_phase_lookup : Error<"call to function %0 that is neither "
@@ -4034,6 +4181,12 @@ def warn_undefined_inline : Warning<"inline function %q0 is not defined">,
InGroup<DiagGroup<"undefined-inline">>;
def note_used_here : Note<"used here">;
+def err_internal_linkage_redeclaration : Error<
+ "'internal_linkage' attribute does not appear on the first declaration of %0">;
+def warn_internal_linkage_local_storage : Warning<
+ "'internal_linkage' attribute on a non-static local variable is ignored">,
+ InGroup<IgnoredAttributes>;
+
def ext_internal_in_extern_inline : ExtWarn<
"static %select{function|variable}0 %1 is used in an inline function with "
"external linkage">, InGroup<StaticInInline>;
@@ -4071,7 +4224,8 @@ def note_extern_c_global_conflict : Note<
def warn_weak_import : Warning <
"an already-declared variable is made a weak_import declaration %0">;
def ext_static_non_static : Extension<
- "redeclaring non-static %0 as static is a Microsoft extension">, InGroup<Microsoft>;
+ "redeclaring non-static %0 as static is a Microsoft extension">,
+ InGroup<MicrosoftRedeclareStatic>;
def err_non_static_static : Error<
"non-static declaration of %0 follows static declaration">;
def err_extern_non_extern : Error<
@@ -4110,6 +4264,11 @@ def err_dependent_tag_decl : Error<
def err_tag_definition_of_typedef : Error<
"definition of type %0 conflicts with %select{typedef|type alias}1 of the same name">;
def err_conflicting_types : Error<"conflicting types for %0">;
+def err_different_pass_object_size_params : Error<
+ "conflicting pass_object_size attributes on parameters">;
+def err_late_asm_label_name : Error<
+ "cannot apply asm label to %select{variable|function}0 after its first use">;
+def err_different_asm_label : Error<"conflicting asm label">;
def err_nested_redefinition : Error<"nested redefinition of %0">;
def err_use_with_wrong_tag : Error<
"use of %0 with tag type that does not match previous declaration">;
@@ -4129,9 +4288,11 @@ def ext_forward_ref_enum : Extension<
def err_forward_ref_enum : Error<
"ISO C++ forbids forward references to 'enum' types">;
def ext_ms_forward_ref_enum : Extension<
- "forward references to 'enum' types are a Microsoft extension">, InGroup<Microsoft>;
+ "forward references to 'enum' types are a Microsoft extension">,
+ InGroup<MicrosoftEnumForwardReference>;
def ext_forward_ref_enum_def : Extension<
- "redeclaration of already-defined enum %0 is a GNU extension">, InGroup<GNURedeclaredEnum>;
+ "redeclaration of already-defined enum %0 is a GNU extension">,
+ InGroup<GNURedeclaredEnum>;
def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;
def err_duplicate_member : Error<"duplicate member %0">;
@@ -4172,15 +4333,15 @@ def warn_array_new_too_large : Warning<"array is too large (%0 elements)">,
// -Wpadded, -Wpacked
def warn_padded_struct_field : Warning<
"padding %select{struct|interface|class}0 %1 with %2 "
- "%select{byte|bit}3%select{|s}4 to align %5">,
+ "%select{byte|bit}3%s2 to align %4">,
InGroup<Padded>, DefaultIgnore;
def warn_padded_struct_anon_field : Warning<
"padding %select{struct|interface|class}0 %1 with %2 "
- "%select{byte|bit}3%select{|s}4 to align anonymous bit-field">,
+ "%select{byte|bit}3%s2 to align anonymous bit-field">,
InGroup<Padded>, DefaultIgnore;
def warn_padded_struct_size : Warning<
- "padding size of %0 with %1 %select{byte|bit}2%select{|s}3 "
- "to alignment boundary">, InGroup<Padded>, DefaultIgnore;
+ "padding size of %0 with %1 %select{byte|bit}2%s1 to alignment boundary">,
+ InGroup<Padded>, DefaultIgnore;
def warn_unnecessary_packed : Warning<
"packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore;
@@ -4292,20 +4453,22 @@ def err_bitfield_has_negative_width : Error<
def err_anon_bitfield_has_negative_width : Error<
"anonymous bit-field has negative width (%0)">;
def err_bitfield_has_zero_width : Error<"named bit-field %0 has zero width">;
-def err_bitfield_width_exceeds_type_size : Error<
- "size of bit-field %0 (%1 bits) exceeds size of its type (%2 bits)">;
-def err_anon_bitfield_width_exceeds_type_size : Error<
- "size of anonymous bit-field (%0 bits) exceeds size of its type (%1 bits)">;
+def err_bitfield_width_exceeds_type_width : Error<
+ "width of bit-field %0 (%1 bits) exceeds %select{width|size}2 "
+ "of its type (%3 bit%s3)">;
+def err_anon_bitfield_width_exceeds_type_width : Error<
+ "width of anonymous bit-field (%0 bits) exceeds %select{width|size}1 "
+ "of its type (%2 bit%s2)">;
def err_incorrect_number_of_vector_initializers : Error<
"number of elements must be either one or match the size of the vector">;
// Used by C++ which allows bit-fields that are wider than the type.
-def warn_bitfield_width_exceeds_type_size: Warning<
- "size of bit-field %0 (%1 bits) exceeds the size of its type; value will be "
- "truncated to %2 bits">;
-def warn_anon_bitfield_width_exceeds_type_size : Warning<
- "size of anonymous bit-field (%0 bits) exceeds size of its type; value will "
- "be truncated to %1 bits">;
+def warn_bitfield_width_exceeds_type_width: Warning<
+ "width of bit-field %0 (%1 bits) exceeds the width of its type; value will "
+ "be truncated to %2 bit%s2">, InGroup<BitFieldWidth>;
+def warn_anon_bitfield_width_exceeds_type_width : Warning<
+ "width of anonymous bit-field (%0 bits) exceeds width of its type; value "
+ "will be truncated to %1 bit%s1">, InGroup<BitFieldWidth>;
def warn_missing_braces : Warning<
"suggest braces around initialization of subobject">,
@@ -4324,7 +4487,7 @@ def err_goto_into_protected_scope : Error<
"cannot jump from this goto statement to its label">;
def ext_goto_into_protected_scope : ExtWarn<
"jump from this goto statement to its label is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftGoto>;
def warn_cxx98_compat_goto_into_protected_scope : Warning<
"jump from this goto statement to its label is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
@@ -4378,8 +4541,10 @@ def note_protected_by_seh_finally : Note<
"jump bypasses initialization of __finally block">;
def note_protected_by___block : Note<
"jump bypasses setup of __block variable">;
-def note_protected_by_objc_ownership : Note<
- "jump bypasses initialization of retaining variable">;
+def note_protected_by_objc_strong_init : Note<
+ "jump bypasses initialization of __strong variable">;
+def note_protected_by_objc_weak_init : Note<
+ "jump bypasses initialization of __weak variable">;
def note_enters_block_captures_cxx_obj : Note<
"jump enters lifetime of block which captures a destructible C++ object">;
def note_enters_block_captures_strong : Note<
@@ -4416,8 +4581,10 @@ def note_exits_seh_finally : Note<
"jump exits __finally block">;
def note_exits_objc_autoreleasepool : Note<
"jump exits autoreleasepool block">;
-def note_exits_objc_ownership : Note<
- "jump exits scope of retaining variable">;
+def note_exits_objc_strong : Note<
+ "jump exits scope of __strong variable">;
+def note_exits_objc_weak : Note<
+ "jump exits scope of __weak variable">;
def note_exits_block_captures_cxx_obj : Note<
"jump exits lifetime of block which captures a destructible C++ object">;
def note_exits_block_captures_strong : Note<
@@ -4457,12 +4624,12 @@ def err_flexible_array_init : Error<
def ext_flexible_array_empty_aggregate_ms : Extension<
"flexible array member %0 in otherwise empty "
"%select{struct|interface|union|class|enum}1 is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftFlexibleArray>;
def err_flexible_array_union : Error<
"flexible array member %0 in a union is not allowed">;
def ext_flexible_array_union_ms : Extension<
"flexible array member %0 in a union is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftFlexibleArray>;
def ext_flexible_array_empty_aggregate_gnu : Extension<
"flexible array member %0 in otherwise empty "
"%select{struct|interface|union|class|enum}1 is a GNU extension">,
@@ -4477,7 +4644,15 @@ let CategoryName = "ARC Semantic Issue" in {
let CategoryName = "ARC Weak References" in {
def err_arc_weak_no_runtime : Error<
- "the current deployment target does not support automated __weak references">;
+ "cannot create __weak reference because the current deployment target "
+ "does not support weak references">;
+def err_arc_weak_disabled : Error<
+ "cannot create __weak reference in file using manual reference counting">;
+def err_synthesizing_arc_weak_property_disabled : Error<
+ "cannot synthesize weak property in file using manual reference counting">;
+def err_synthesizing_arc_weak_property_no_runtime : Error<
+ "cannot synthesize weak property because the current deployment target "
+ "does not support weak references">;
def err_arc_unsupported_weak_class : Error<
"class is incompatible with __weak references">;
def err_arc_weak_unavailable_assign : Error<
@@ -4495,6 +4670,21 @@ def err_arc_convesion_of_weak_unavailable : Error<
let CategoryName = "ARC Restrictions" in {
+def err_unavailable_in_arc : Error<
+ "%0 is unavailable in ARC">;
+def note_arc_forbidden_type : Note<
+ "declaration uses type that is ill-formed in ARC">;
+def note_performs_forbidden_arc_conversion : Note<
+ "inline function performs a conversion which is forbidden in ARC">;
+def note_arc_init_returns_unrelated : Note<
+ "init method must return a type related to its receiver type">;
+def note_arc_weak_disabled : Note<
+ "declaration uses __weak, but ARC is disabled">;
+def note_arc_weak_no_runtime : Note<"declaration uses __weak, which "
+ "the current deployment target does not support">;
+def note_arc_field_with_ownership : Note<
+ "field has non-trivial ownership qualification">;
+
def err_arc_illegal_explicit_message : Error<
"ARC forbids explicit message send of %0">;
def err_arc_unused_init_message : Error<
@@ -4540,7 +4730,7 @@ def err_typecheck_arc_assign_self : Error<
def err_typecheck_arc_assign_self_class_method : Error<
"cannot assign to 'self' in a class method">;
def err_typecheck_arr_assign_enumeration : Error<
- "fast enumeration variables can't be modified in ARC by default; "
+ "fast enumeration variables cannot be modified in ARC by default; "
"declare the variable __strong to allow this">;
def warn_arc_retained_assign : Warning<
"assigning retained object to %select{weak|unsafe_unretained}0 "
@@ -4620,7 +4810,7 @@ def err_arc_strong_property_ownership : Error<
"existing instance variable %1 for strong property %0 may not be "
"%select{|__unsafe_unretained||__weak}2">;
def err_arc_assign_property_ownership : Error<
- "existing instance variable %1 for property %0 with %select{unsafe_unretained| assign}2 "
+ "existing instance variable %1 for property %0 with %select{unsafe_unretained|assign}2 "
"attribute must be __unsafe_unretained">;
def err_arc_inconsistent_property_ownership : Error<
"%select{|unsafe_unretained|strong|weak}1 property %0 may not also be "
@@ -4724,8 +4914,8 @@ def err_sizeof_alignof_function_type : Error<
"function type">;
def err_openmp_default_simd_align_expr : Error<
"invalid application of '__builtin_omp_required_simd_align' to an expression, only type is allowed">;
-def err_sizeof_alignof_bitfield : Error<
- "invalid application of '%select{sizeof|alignof}0' to bit-field">;
+def err_sizeof_alignof_typeof_bitfield : Error<
+ "invalid application of '%select{sizeof|alignof|typeof}0' to bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being defined">;
def err_vecstep_non_scalar_vector_type : Error<
@@ -4753,9 +4943,8 @@ def warn_floatingpoint_eq : Warning<
"comparing floating point with == or != is unsafe">,
InGroup<DiagGroup<"float-equal">>, DefaultIgnore;
-def warn_division_by_zero : Warning<"division by zero is undefined">,
- InGroup<DivZero>;
-def warn_remainder_by_zero : Warning<"remainder by zero is undefined">,
+def warn_remainder_division_by_zero : Warning<
+ "%select{remainder|division}0 by zero is undefined">,
InGroup<DivZero>;
def warn_shift_lhs_negative : Warning<"shifting a negative signed value is undefined">,
InGroup<DiagGroup<"shift-negative-value">>;
@@ -4793,8 +4982,8 @@ def note_logical_instead_of_bitwise_change_operator : Note<
def note_logical_instead_of_bitwise_remove_constant : Note<
"remove constant to silence this warning">;
-def warn_bitwise_and_in_bitwise_or : Warning<
- "'&' within '|'">, InGroup<BitwiseOpParentheses>;
+def warn_bitwise_op_in_bitwise_op : Warning<
+ "'%0' within '%1'">, InGroup<BitwiseOpParentheses>;
def warn_logical_and_in_logical_or : Warning<
"'&&' within '||'">, InGroup<LogicalOpParentheses>;
@@ -4945,10 +5134,10 @@ def err_qualified_param_declarator : Error<
def ext_out_of_line_declaration : ExtWarn<
"out-of-line declaration of a member must be a definition">,
InGroup<OutOfLineDeclaration>, DefaultError;
-def warn_member_extra_qualification : Warning<
- "extra qualification on member %0">, InGroup<Microsoft>;
def err_member_extra_qualification : Error<
"extra qualification on member %0">;
+def warn_member_extra_qualification : Warning<
+ err_member_extra_qualification.Text>, InGroup<MicrosoftExtraQualification>;
def warn_namespace_member_extra_qualification : Warning<
"extra qualification on member %0">,
InGroup<DiagGroup<"extra-qualification">>;
@@ -5044,6 +5233,9 @@ def err_unqualified_pointer_member_function : Error<
"must explicitly qualify name of member function when taking its address">;
def err_invalid_form_pointer_member_function : Error<
"cannot create a non-constant pointer to member function">;
+def err_address_of_function_with_pass_object_size_params: Error<
+ "cannot take address of function %0 because parameter %1 has "
+ "pass_object_size attribute">;
def err_parens_pointer_member_function : Error<
"cannot parenthesize the name of a method when forming a member pointer">;
def err_typecheck_invalid_lvalue_addrof_addrof_function : Error<
@@ -5197,6 +5389,8 @@ def err_builtin_func_cast_more_than_one_arg : Error<
"function-style cast to a builtin type can only take one argument">;
def err_value_init_for_array_type : Error<
"array types cannot be value-initialized">;
+def err_value_init_for_function_type : Error<
+ "function types cannot be value-initialized">;
def warn_format_nonliteral_noargs : Warning<
"format string is not a string literal (potentially insecure)">,
InGroup<FormatSecurity>;
@@ -5354,7 +5548,7 @@ def warn_objc_pointer_cxx_catch_fragile : Warning<
"cannot catch an exception thrown with @throw in C++ in the non-unified "
"exception model">, InGroup<ObjCNonUnifiedException>;
def err_objc_object_catch : Error<
- "can't catch an Objective-C object by value">;
+ "cannot catch an Objective-C object by value">;
def err_incomplete_type_objc_at_encode : Error<
"'@encode' of incomplete type %0">;
def warn_objc_circular_container : Warning<
@@ -5423,8 +5617,7 @@ def ext_cast_fn_obj : Extension<
"cast between pointer-to-function and pointer-to-object is an extension">;
def ext_ms_cast_fn_obj : ExtWarn<
"static_cast between pointer-to-function and pointer-to-object is a "
- "Microsoft extension">,
- InGroup<Microsoft>;
+ "Microsoft extension">, InGroup<MicrosoftCast>;
def warn_cxx98_compat_cast_fn_obj : Warning<
"cast between pointer-to-function and pointer-to-object is incompatible with C++98">,
InGroup<CXX98CompatPedantic>, DefaultIgnore;
@@ -5534,7 +5727,7 @@ def ext_default_init_const : ExtWarn<
"default initialization of an object of const type %0"
"%select{| without a user-provided default constructor}1 "
"is a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftConstInit>;
def err_delete_operand : Error<"cannot delete expression of type %0">;
def ext_delete_void_ptr_operand : ExtWarn<
"cannot delete expression with pointer-to-'void' type %0">,
@@ -5565,8 +5758,11 @@ def note_member_declared_here : Note<
"member %0 declared here">;
def err_decrement_bool : Error<"cannot decrement expression of type bool">;
def warn_increment_bool : Warning<
- "incrementing expression of type bool is deprecated">,
- InGroup<DeprecatedIncrementBool>;
+ "incrementing expression of type bool is deprecated and "
+ "incompatible with C++1z">, InGroup<DeprecatedIncrementBool>;
+def ext_increment_bool : ExtWarn<
+ "ISO C++1z does not allow incrementing expression of type bool">,
+ DefaultError, InGroup<IncrementBool>;
def err_increment_decrement_enum : Error<
"cannot %select{decrement|increment}0 expression of enum type %1">;
def err_catch_incomplete_ptr : Error<
@@ -5606,7 +5802,8 @@ def warn_non_virtual_dtor : Warning<
"%0 has virtual functions but non-virtual destructor">,
InGroup<NonVirtualDtor>, DefaultIgnore;
def warn_delete_non_virtual_dtor : Warning<
- "delete called on %0 that has virtual functions but non-virtual destructor">,
+ "delete called on non-final %0 that has virtual functions "
+ "but non-virtual destructor">,
InGroup<DeleteNonVirtualDtor>, DefaultIgnore;
def warn_delete_abstract_non_virtual_dtor : Warning<
"delete called on %0 that is abstract but has non-virtual destructor">,
@@ -5656,6 +5853,9 @@ def err_throw_incomplete_ptr : Error<
"cannot throw pointer to object of incomplete type %0">;
def err_return_in_constructor_handler : Error<
"return in the catch of a function try block of a constructor is illegal">;
+def warn_cdtor_function_try_handler_mem_expr : Warning<
+ "cannot refer to a non-static member from the handler of a "
+ "%select{constructor|destructor}0 function try block">, InGroup<Exceptions>;
let CategoryName = "Lambda Issue" in {
def err_capture_more_than_once : Error<
@@ -5721,8 +5921,8 @@ let CategoryName = "Lambda Issue" in {
def err_init_capture_multiple_expressions : Error<
"initializer for lambda capture %0 contains multiple expressions">;
def err_init_capture_paren_braces : Error<
- "cannot deduce type for lambda capture %0 from "
- "parenthesized initializer list">;
+ "cannot deduce type for lambda capture %1 from "
+ "%select{parenthesized|nested}0 initializer list">;
def err_init_capture_deduction_failure : Error<
"cannot deduce type for lambda capture %0 from initializer of type %2">;
def err_init_capture_deduction_failure_from_init_list : Error<
@@ -5752,7 +5952,7 @@ def err_pseudo_dtor_base_not_scalar : Error<
"pseudo-destructor expression">;
def ext_pseudo_dtor_on_void : ExtWarn<
"pseudo-destructors on type void are a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftVoidPseudoDtor>;
def err_pseudo_dtor_type_mismatch : Error<
"the type of object expression "
"%diff{($) does not match the type being destroyed ($)|"
@@ -5769,14 +5969,13 @@ def err_pseudo_dtor_destructor_non_type : Error<
def err_invalid_use_of_function_type : Error<
"a function type is not allowed here">;
def err_invalid_use_of_array_type : Error<"an array type is not allowed here">;
-def err_type_defined_in_condition : Error<
- "types may not be defined in conditions">;
def err_typecheck_bool_condition : Error<
"value of type %0 is not contextually convertible to 'bool'">;
def err_typecheck_ambiguous_condition : Error<
"conversion %diff{from $ to $|between types}0,1 is ambiguous">;
def err_typecheck_nonviable_condition : Error<
- "no viable conversion%diff{ from $ to $|}0,1">;
+ "no viable conversion%select{%diff{ from $ to $|}1,2|"
+ "%diff{ from returned value of type $ to function return type $|}1,2}0">;
def err_typecheck_nonviable_condition_incomplete : Error<
"no viable conversion%diff{ from $ to incomplete type $|}0,1">;
def err_typecheck_deleted_function : Error<
@@ -6160,6 +6359,9 @@ def err_atomic_op_needs_atomic : Error<
def err_atomic_op_needs_non_const_atomic : Error<
"address argument to atomic operation must be a pointer to non-const _Atomic "
"type (%0 invalid)">;
+def err_atomic_op_needs_non_const_pointer : Error<
+ "address argument to atomic operation must be a pointer to non-const "
+ "type (%0 invalid)">;
def err_atomic_op_needs_trivial_copy : Error<
"address argument to atomic operation must be a pointer to a "
"trivially-copyable type (%0 invalid)">;
@@ -6173,10 +6375,22 @@ def warn_atomic_op_has_invalid_memory_order : Warning<
"memory order argument to atomic operation is invalid">,
InGroup<DiagGroup<"atomic-memory-ordering">>;
+def err_overflow_builtin_must_be_int : Error<
+ "operand argument to overflow builtin must be an integer (%0 invalid)">;
+def err_overflow_builtin_must_be_ptr_int : Error<
+ "result argument to overflow builtin must be a pointer "
+ "to a non-const integer (%0 invalid)">;
+
def err_atomic_load_store_uses_lib : Error<
"atomic %select{load|store}0 requires runtime support that is not "
"available for this target">;
+def err_nontemporal_builtin_must_be_pointer : Error<
+ "address argument to nontemporal builtin must be a pointer (%0 invalid)">;
+def err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector : Error<
+ "address argument to nontemporal builtin must be a pointer to integer, float, "
+ "pointer, or a vector of such types (%0 invalid)">;
+
def err_deleted_function_use : Error<"attempt to use a deleted function">;
def err_kern_type_not_void_return : Error<
@@ -6339,6 +6553,10 @@ def warn_cast_qual : Warning<"cast from %0 to %1 drops %select{const and "
InGroup<CastQual>, DefaultIgnore;
def warn_cast_qual2 : Warning<"cast from %0 to %1 must have all intermediate "
"pointers const qualified to be safe">, InGroup<CastQual>, DefaultIgnore;
+def warn_redefine_extname_not_applied : Warning<
+ "#pragma redefine_extname is applicable to external C declarations only; "
+ "not applied to %select{function|variable}0 %1">,
+ InGroup<Pragmas>;
} // End of general sema category.
// inline asm.
@@ -6361,6 +6579,10 @@ let CategoryName = "Inline Assembly Issue" in {
"asm constraint has an unexpected number of alternatives: %0 vs %1">;
def err_asm_incomplete_type : Error<"asm operand has incomplete type %0">;
def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">;
+ def err_asm_invalid_global_var_reg : Error<"register '%0' unsuitable for "
+ "global register variables on this target">;
+ def err_asm_register_size_mismatch : Error<"size of register '%0' does not "
+ "match variable size">;
def err_asm_bad_register_type : Error<"bad type for named register variable">;
def err_asm_invalid_input_size : Error<
"invalid input size for constraint '%0'">;
@@ -6371,9 +6593,11 @@ let CategoryName = "Inline Assembly Issue" in {
"remove the cast or build with -fheinous-gnu-extensions">;
def err_invalid_asm_value_for_constraint
: Error <"value '%0' out of range for constraint '%1'">;
- def err_asm_bitfield_in_memory_constraint
- : Error <"reference to a bit-field in asm "
- "%select{input|output}0 with a memory constraint '%1'">;
+ def err_asm_non_addr_value_in_memory_constraint : Error <
+ "reference to a %select{bit-field|vector element|global register variable}0"
+ " in asm %select{input|output}1 with a memory constraint '%2'">;
+ def err_asm_input_duplicate_match : Error<
+ "more than one input constraint matches the same output '%0'">;
def warn_asm_label_on_auto_decl : Warning<
"ignored asm label '%0' on automatic variable">;
@@ -6388,6 +6612,8 @@ let CategoryName = "Inline Assembly Issue" in {
def note_asm_missing_constraint_modifier : Note<
"use constraint modifier \"%0\"">;
+ def note_asm_input_duplicate_first : Note<
+ "constraint '%0' is already present here">;
}
let CategoryName = "Semantic Issue" in {
@@ -6490,15 +6716,13 @@ def err_anonymous_union_with_storage_spec : Error<
def err_anonymous_struct_not_member : Error<
"anonymous %select{structs|structs and classes}0 must be "
"%select{struct or union|class}0 members">;
-def err_anonymous_union_member_redecl : Error<
- "member of anonymous union redeclares %0">;
-def err_anonymous_struct_member_redecl : Error<
- "member of anonymous struct redeclares %0">;
+def err_anonymous_record_member_redecl : Error<
+ "member of anonymous %select{struct|union}0 redeclares %1">;
def err_anonymous_record_with_type : Error<
"types cannot be declared in an anonymous %select{struct|union}0">;
def ext_anonymous_record_with_type : Extension<
"types declared in an anonymous %select{struct|union}0 are a Microsoft "
- "extension">, InGroup<Microsoft>;
+ "extension">, InGroup<MicrosoftAnonTag>;
def ext_anonymous_record_with_anonymous_type : Extension<
"anonymous types declared in an anonymous %select{struct|union}0 "
"are an extension">, InGroup<DiagGroup<"nested-anon-types">>;
@@ -6513,7 +6737,7 @@ def err_anonymous_record_nonpublic_member : Error<
"%select{private|protected}1 data member">;
def ext_ms_anonymous_record : ExtWarn<
"anonymous %select{structs|unions}0 are a Microsoft extension">,
- InGroup<Microsoft>;
+ InGroup<MicrosoftAnonTag>;
// C++ local classes
def err_reference_to_local_var_in_enclosing_function : Error<
@@ -6846,17 +7070,12 @@ def warn_null_ret : Warning<
InGroup<NonNull>;
// CHECK: returning address/reference of stack memory
-def warn_ret_stack_addr : Warning<
- "address of stack memory associated with local variable %0 returned">,
+def warn_ret_stack_addr_ref : Warning<
+ "%select{address of|reference to}0 stack memory associated with local "
+ "variable %1 returned">,
InGroup<ReturnStackAddress>;
-def warn_ret_stack_ref : Warning<
- "reference to stack memory associated with local variable %0 returned">,
- InGroup<ReturnStackAddress>;
-def warn_ret_local_temp_addr : Warning<
- "returning address of local temporary object">,
- InGroup<ReturnStackAddress>;
-def warn_ret_local_temp_ref : Warning<
- "returning reference to local temporary object">,
+def warn_ret_local_temp_addr_ref : Warning<
+ "returning %select{address of|reference to}0 local temporary object">,
InGroup<ReturnStackAddress>;
def warn_ret_addr_label : Warning<
"returning address of label, which is local">,
@@ -7058,6 +7277,10 @@ def note_empty_body_on_separate_line : Note<
def err_va_start_used_in_non_variadic_function : Error<
"'va_start' used in function with fixed args">;
+def err_va_start_used_in_wrong_abi_function : Error<
+ "'va_start' used in %select{System V|Win64}0 ABI function">;
+def err_ms_va_start_used_in_sysv_function : Error<
+ "'__builtin_ms_va_start' used in System V ABI function">;
def warn_second_parameter_of_va_start_not_last_named_argument : Warning<
"second parameter of 'va_start' not last named argument">, InGroup<Varargs>;
def warn_va_start_of_reference_type_is_undefined : Warning<
@@ -7172,6 +7395,8 @@ def err_64_bit_builtin_32_bit_tgt : Error<
"this builtin is only available on 64-bit targets">;
def err_ppc_builtin_only_on_pwr7 : Error<
"this builtin is only valid on POWER7 or later CPUs">;
+def err_x86_builtin_32_bit_tgt : Error<
+ "this builtin is only available on x86-64 targets">;
def err_builtin_longjmp_unsupported : Error<
"__builtin_longjmp is not supported for the current target">;
@@ -7387,6 +7612,8 @@ def err_opencl_ptrptr_kernel_param : Error<
"kernel parameter cannot be declared as a pointer to a pointer">;
def err_opencl_private_ptr_kernel_param : Error<
"kernel parameter cannot be declared as a pointer to the __private address space">;
+def err_opencl_non_kernel_variable : Error<
+ "non-kernel function variable cannot be declared in %0 address space">;
def err_static_function_scope : Error<
"variables in function scope cannot be declared static">;
def err_opencl_bitfields : Error<
@@ -7414,7 +7641,11 @@ def err_sampler_argument_required : Error<
def err_wrong_sampler_addressspace: Error<
"sampler type cannot be used with the __local and __global address space qualifiers">;
def err_opencl_global_invalid_addr_space : Error<
- "global variables must have a constant address space qualifier">;
+ "program scope variable must reside in %0 address space">;
+def err_missing_actual_pipe_type : Error<
+ "missing actual type specifier for pipe">;
+def err_reference_pipe_type : Error <
+ "pipes packet types cannot be of reference type">;
def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">;
def err_opencl_kernel_attr :
Error<"attribute %0 can only be applied to a kernel function">;
@@ -7422,6 +7653,16 @@ def err_opencl_return_value_with_address_space : Error<
"return value cannot be qualified with address space">;
def err_opencl_constant_no_init : Error<
"variable in constant address space must be initialized">;
+def err_atomic_init_constant : Error<
+ "atomic variable can only be assigned to a compile time constant"
+ " in the declaration statement in the program scope">;
+def err_opencl_implicit_vector_conversion : Error<
+ "implicit conversions between vector types (%0 and %1) are not permitted">;
+
+// OpenCL Section 6.8.g
+def err_opencl_unknown_type_specifier : Error<
+ "OpenCL does not support the '%0' %select{type qualifier|storage class specifier}1">;
+
} // end of sema category
let CategoryName = "OpenMP Issue" in {
@@ -7448,7 +7689,7 @@ def err_omp_firstprivate_incomplete_type : Error<
def err_omp_lastprivate_incomplete_type : Error<
"a lastprivate variable with incomplete type %0">;
def err_omp_reduction_incomplete_type : Error<
- "a reduction variable with incomplete type %0">;
+ "a reduction list item with incomplete type %0">;
def err_omp_unexpected_clause_value : Error<
"expected %0 in OpenMP clause '%1'">;
def err_omp_expected_var_name : Error<
@@ -7457,10 +7698,6 @@ def err_omp_expected_var_name_or_array_item : Error<
"expected variable name, array element or array section">;
def note_omp_task_predetermined_firstprivate_here : Note<
"predetermined as a firstprivate in a task construct here">;
-def err_omp_clause_ref_type_arg : Error<
- "arguments of OpenMP clause '%0' cannot be of reference type %1">;
-def err_omp_task_predetermined_firstprivate_ref_type_arg : Error<
- "predetermined as a firstprivate in a task construct variable cannot be of reference type %0">;
def err_omp_threadprivate_incomplete_type : Error<
"threadprivate variable with incomplete type %0">;
def err_omp_no_dsa_for_variable : Error<
@@ -7489,10 +7726,10 @@ def err_omp_loop_var_dsa : Error<
def err_omp_not_for : Error<
"%select{statement after '#pragma omp %1' must be a for loop|"
"expected %2 for loops after '#pragma omp %1'%select{|, but found only %4}3}0">;
-def note_omp_collapse_expr : Note<
- "as specified in 'collapse' clause">;
+def note_omp_collapse_ordered_expr : Note<
+ "as specified in %select{'collapse'|'ordered'|'collapse' and 'ordered'}0 clause%select{||s}0">;
def err_omp_negative_expression_in_clause : Error<
- "argument to '%0' clause must be a positive integer value">;
+ "argument to '%0' clause must be a %select{non-negative|strictly positive}1 integer value">;
def err_omp_not_integral : Error<
"expression must have integral or unscoped enumeration "
"type, not %0">;
@@ -7509,6 +7746,8 @@ def err_omp_required_access : Error<
"%0 variable must be %1">;
def err_omp_const_variable : Error<
"const-qualified variable cannot be %0">;
+def err_omp_const_reduction_list_item : Error<
+ "const-qualified list item cannot be reduction">;
def err_omp_linear_incomplete_type : Error<
"a linear variable with incomplete type %0">;
def err_omp_linear_expected_int_or_ptr : Error<
@@ -7529,8 +7768,8 @@ def err_omp_aligned_twice : Error<
def err_omp_local_var_in_threadprivate_init : Error<
"variable with local storage in initial value of threadprivate variable">;
def err_omp_loop_not_canonical_init : Error<
- "initialization clause of OpenMP for loop must be of the form "
- "'var = init' or 'T var = init'">;
+ "initialization clause of OpenMP for loop is not in canonical form "
+ "('var = init' or 'T var = init')">;
def ext_omp_loop_not_canonical_init : ExtWarn<
"initialization clause of OpenMP for loop is not in canonical form "
"('var = init' or 'T var = init')">, InGroup<OpenMPLoopForm>;
@@ -7560,7 +7799,7 @@ def warn_omp_loop_64_bit_var : Warning<
def err_omp_unknown_reduction_identifier : Error<
"incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'">;
def err_omp_reduction_type_array : Error<
- "a reduction variable with array type %0">;
+ "a reduction list item with array type %0">;
def err_omp_reduction_ref_type_arg : Error<
"argument of OpenMP clause 'reduction' must reference the same object in all threads">;
def err_omp_clause_not_arithmetic_type_arg : Error<
@@ -7574,12 +7813,13 @@ def note_omp_referenced : Note<
def err_omp_reduction_in_task : Error<
"reduction variables may not be accessed in an explicit task">;
def err_omp_reduction_id_not_compatible : Error<
- "variable of type %0 is not valid for specified reduction operation: unable to provide default initialization value">;
+ "list item of type %0 is not valid for specified reduction operation: unable to provide default initialization value">;
def err_omp_prohibited_region : Error<
"region cannot be%select{| closely}0 nested inside '%1' region"
"%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?|"
"; perhaps you forget to enclose 'omp %3' directive into a for or a parallel for region with 'ordered' clause?|"
- "; perhaps you forget to enclose 'omp %3' directive into a target region?}2">;
+ "; perhaps you forget to enclose 'omp %3' directive into a target region?|"
+ "; perhaps you forget to enclose 'omp %3' directive into a teams region?}2">;
def err_omp_prohibited_region_simd : Error<
"OpenMP constructs may not be nested inside a simd region">;
def err_omp_prohibited_region_atomic : Error<
@@ -7649,6 +7889,97 @@ def err_omp_parent_cancel_region_nowait : Error<
"parent region for 'omp %select{cancellation point/cancel}0' construct cannot be nowait">;
def err_omp_parent_cancel_region_ordered : Error<
"parent region for 'omp %select{cancellation point/cancel}0' construct cannot be ordered">;
+def err_omp_array_section_use : Error<"OpenMP array section is not allowed here">;
+def err_omp_typecheck_section_value : Error<
+ "subscripted value is not an array or pointer">;
+def err_omp_typecheck_section_not_integer : Error<
+ "array section %select{lower bound|length}0 is not an integer">;
+def err_omp_section_function_type : Error<
+ "section of pointer to function type %0">;
+def warn_omp_section_is_char : Warning<"array section %select{lower bound|length}0 is of type 'char'">,
+ InGroup<CharSubscript>, DefaultIgnore;
+def err_omp_section_incomplete_type : Error<
+ "section of pointer to incomplete type %0">;
+def err_omp_section_negative : Error<
+ "section %select{lower bound|length}0 is evaluated to a negative value %1">;
+def err_omp_section_length_undefined : Error<
+ "section length is unspecified and cannot be inferred because subscripted value is %select{not an array|an array of unknown bound}0">;
+def err_omp_wrong_linear_modifier : Error<
+ "expected %select{'val' modifier|one of 'ref', val' or 'uval' modifiers}0">;
+def err_omp_wrong_linear_modifier_non_reference : Error<
+ "variable of non-reference type %0 can be used only with 'val' modifier, but used with '%1'">;
+def err_omp_wrong_simdlen_safelen_values : Error<
+ "the value of 'simdlen' parameter must be less than or equal to the value of the 'safelen' parameter">;
+def err_omp_wrong_if_directive_name_modifier : Error<
+ "directive name modifier '%0' is not allowed for '#pragma omp %1'">;
+def err_omp_no_more_if_clause : Error<
+ "no more 'if' clause is allowed">;
+def err_omp_unnamed_if_clause : Error<
+ "expected %select{|one of}0 %1 directive name modifier%select{|s}0">;
+def note_omp_previous_named_if_clause : Note<
+ "previous clause with directive name modifier specified here">;
+def err_omp_ordered_directive_with_param : Error<
+ "'ordered' directive %select{without any clauses|with 'threads' clause}0 cannot be closely nested inside ordered region with specified parameter">;
+def err_omp_ordered_directive_without_param : Error<
+ "'ordered' directive with 'depend' clause cannot be closely nested inside ordered region without specified parameter">;
+def note_omp_ordered_param : Note<
+ "'ordered' clause with specified parameter">;
+def err_omp_expected_base_var_name : Error<
+ "expected variable name as a base of the array %select{subscript|section}0">;
+def err_omp_map_shared_storage : Error<
+ "variable already marked as mapped in current construct">;
+def err_omp_not_mappable_type : Error<
+ "type %0 is not mappable to target">;
+def note_omp_polymorphic_in_target : Note<
+ "mappable type cannot be polymorphic">;
+def note_omp_static_member_in_target : Note<
+ "mappable type cannot contain static members">;
+def err_omp_threadprivate_in_map : Error<
+ "threadprivate variables are not allowed in map clause">;
+def err_omp_wrong_ordered_loop_count : Error<
+ "the parameter of the 'ordered' clause must be greater than or equal to the parameter of the 'collapse' clause">;
+def note_collapse_loop_count : Note<
+ "parameter of the 'collapse' clause">;
+def err_omp_grainsize_num_tasks_mutually_exclusive : Error<
+ "'%0' and '%1' clause are mutually exclusive and may not appear on the same directive">;
+def note_omp_previous_grainsize_num_tasks : Note<
+ "'%0' clause is specified here">;
+def err_omp_hint_clause_no_name : Error<
+ "the name of the construct must be specified in presence of 'hint' clause">;
+def err_omp_critical_with_hint : Error<
+ "constructs with the same name must have a 'hint' clause with the same value">;
+def note_omp_critical_hint_here : Note<
+ "%select{|previous }0'hint' clause with value '%1'">;
+def note_omp_critical_no_hint : Note<
+ "%select{|previous }0directive with no 'hint' clause specified">;
+def err_omp_firstprivate_distribute_private_teams : Error<
+ "private variable in '#pragma omp teams' cannot be firstprivate in '#pragma omp distribute'">;
+def err_omp_firstprivate_and_lastprivate_in_distribute : Error<
+ "lastprivate variable cannot be firstprivate in '#pragma omp distribute'">;
+def err_omp_firstprivate_distribute_in_teams_reduction : Error<
+ "reduction variable in '#pragma omp teams' cannot be firstprivate in '#pragma omp distribute'">;
+def err_omp_depend_clause_thread_simd : Error<
+ "'depend' clauses cannot be mixed with '%0' clause">;
+def err_omp_depend_sink_wrong_expr : Error<
+ "expected expression form x[+-d], where x is the loop iteration variable and d is a constant non-negative integer">;
+def err_omp_depend_sink_expected_loop_iteration : Error<
+ "expected %0 loop iteration variable">;
+def err_omp_depend_sink_unexpected_expr : Error<
+ "unexpected expression: number of expressions is larger than the number of associated loops">;
+def err_omp_depend_sink_expected_plus_minus : Error<
+ "expected '+' or '-' operation">;
+def err_omp_depend_sink_source_not_allowed : Error<
+ "'depend(%select{source|sink:vec}0)' clause%select{|s}0 cannot be mixed with 'depend(%select{sink:vec|source}0)' clause%select{s|}0">;
+def err_omp_linear_ordered : Error<
+ "'linear' clause cannot be specified along with 'ordered' clause with a parameter">;
+def err_omp_unexpected_schedule_modifier : Error<
+ "modifier '%0' cannot be used along with modifier '%1'">;
+def err_omp_schedule_nonmonotonic_static : Error<
+ "'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind">;
+def err_omp_schedule_nonmonotonic_ordered : Error<
+ "'schedule' clause with 'nonmonotonic' modifier cannot be specified if an 'ordered' clause is specified">;
+def err_omp_ordered_simd : Error<
+ "'ordered' clause with a parameter can not be specified in '#pragma omp %0' directive">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
@@ -7692,18 +8023,63 @@ def err_module_unimported_use : Error<
def err_module_unimported_use_multiple : Error<
"%select{declaration|definition|default argument}0 of %1 must be imported "
"from one of the following modules before it is required:%2">;
-def err_module_import_in_extern_c : Error<
+def ext_module_import_in_extern_c : ExtWarn<
"import of C++ module '%0' appears within extern \"C\" language linkage "
- "specification">;
+ "specification">, DefaultError,
+ InGroup<DiagGroup<"module-import-in-extern-c">>;
def note_module_import_in_extern_c : Note<
"extern \"C\" language linkage specification begins here">;
-def err_module_import_not_at_top_level : Error<
- "import of module '%0' appears within %1">;
+def err_module_import_not_at_top_level_fatal : Error<
+ "import of module '%0' appears within %1">, DefaultFatal;
+def ext_module_import_not_at_top_level_noop : ExtWarn<
+ "redundant #include of module '%0' appears within %1">, DefaultError,
+ InGroup<DiagGroup<"modules-import-nested-redundant">>;
def note_module_import_not_at_top_level : Note<"%0 begins here">;
def err_module_self_import : Error<
"import of module '%0' appears within same top-level module '%1'">;
def err_module_import_in_implementation : Error<
"@import of module '%0' in implementation of '%1'; use #import">;
+
+def ext_equivalent_internal_linkage_decl_in_modules : ExtWarn<
+ "ambiguous use of internal linkage declaration %0 defined in multiple modules">,
+ InGroup<DiagGroup<"modules-ambiguous-internal-linkage">>;
+def note_equivalent_internal_linkage_decl : Note<
+ "declared here%select{ in module '%1'|}0">;
+}
+
+let CategoryName = "Coroutines Issue" in {
+def err_return_in_coroutine : Error<
+ "return statement not allowed in coroutine; did you mean 'co_return'?">;
+def note_declared_coroutine_here : Note<
+ "function is a coroutine due to use of "
+ "'%select{co_await|co_yield|co_return}0' here">;
+def err_coroutine_objc_method : Error<
+ "Objective-C methods as coroutines are not yet supported">;
+def err_coroutine_unevaluated_context : Error<
+ "'%0' cannot be used in an unevaluated context">;
+def err_coroutine_outside_function : Error<
+ "'%0' cannot be used outside a function">;
+def err_coroutine_ctor_dtor : Error<
+ "'%1' cannot be used in a %select{constructor|destructor}0">;
+def err_coroutine_constexpr : Error<
+ "'%0' cannot be used in a constexpr function">;
+def err_coroutine_varargs : Error<
+ "'%0' cannot be used in a varargs function">;
+def ext_coroutine_without_co_await_co_yield : ExtWarn<
+ "'co_return' used in a function "
+ "that uses neither 'co_await' nor 'co_yield'">,
+ InGroup<DiagGroup<"coreturn-without-coawait">>;
+def err_implied_std_coroutine_traits_not_found : Error<
+ "you need to include <coroutine> before defining a coroutine">;
+def err_malformed_std_coroutine_traits : Error<
+ "'std::coroutine_traits' must be a class template">;
+def err_implied_std_coroutine_traits_promise_type_not_found : Error<
+ "this function cannot be a coroutine: %q0 has no member named 'promise_type'">;
+def err_implied_std_coroutine_traits_promise_type_not_class : Error<
+ "this function cannot be a coroutine: %0 is not a class">;
+def err_coroutine_traits_missing_specialization : Error<
+ "this function cannot be a coroutine: missing definition of "
+ "specialization %q0">;
}
let CategoryName = "Documentation Issue" in {
@@ -7761,10 +8137,10 @@ def warn_nullability_missing : Warning<
"type specifier (_Nonnull, _Nullable, or _Null_unspecified)">,
InGroup<NullabilityCompleteness>;
-def err_type_arg_explicit_nullability : Error<
+def err_objc_type_arg_explicit_nullability : Error<
"type argument %0 cannot explicitly specify nullability">;
-def err_type_param_bound_explicit_nullability : Error<
+def err_objc_type_param_bound_explicit_nullability : Error<
"type parameter %0 bound %1 cannot explicitly specify nullability">;
}
@@ -7776,6 +8152,8 @@ def err_objc_type_param_bound_nonobject : Error<
def err_objc_type_param_bound_missing_pointer : Error<
"missing '*' in type bound %0 for type parameter %1">;
+def err_objc_type_param_bound_qualified : Error<
+ "type bound %1 for type parameter %0 cannot be qualified with '%2'">;
def err_objc_type_param_redecl : Error<
"redeclaration of type parameter %0">;
@@ -7810,6 +8188,8 @@ def err_objc_parameterized_forward_class_first : Error<
def err_objc_type_arg_missing_star : Error<
"type argument %0 must be a pointer (requires a '*')">;
+def err_objc_type_arg_qualified : Error<
+ "type argument %0 cannot be qualified with '%1'">;
def err_objc_type_arg_missing : Error<
"no type or protocol named %0">;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td
index 796027e..16c7743 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -53,6 +53,20 @@ def err_pch_different_branch : Error<
def err_pch_with_compiler_errors : Error<
"PCH file contains compiler errors">;
+def err_module_file_conflict : Error<
+ "module '%0' is defined in both '%1' and '%2'">, DefaultFatal;
+def err_module_file_not_found : Error<
+ "%select{PCH|module|AST}0 file '%1' not found%select{|: %3}2">, DefaultFatal;
+def err_module_file_out_of_date : Error<
+ "%select{PCH|module|AST}0 file '%1' is out of date and "
+ "needs to be rebuilt%select{|: %3}2">, DefaultFatal;
+def err_module_file_invalid : Error<
+ "file '%1' is not a valid precompiled %select{PCH|module|AST}0 file">, DefaultFatal;
+def note_module_file_imported_by : Note<
+ "imported by %select{|module '%2' in }1'%0'">;
+def err_module_file_not_module : Error<
+ "AST file '%0' was not built as a module">, DefaultFatal;
+
def err_imported_module_not_found : Error<
"module '%0' in AST file '%1' (imported by AST file '%2') "
"is not defined in any loaded module map file; "
@@ -82,9 +96,6 @@ def err_pch_pp_detailed_record : Error<
"'-detailed-preprocessing-record' but %select{precompiled header was not "
"built with it|it is not present on the command line}0">;
-def err_not_a_pch_file : Error<
- "'%0' does not appear to be a precompiled header file">, DefaultFatal;
-
def err_module_odr_violation_missing_decl : Error<
"%q0 from module '%1' is not present in definition of %q2"
"%select{ in module '%4'| provided earlier}3">, NoSFINAE;
@@ -100,6 +111,14 @@ def note_module_odr_violation_different_definitions : Note<
def err_module_odr_violation_different_instantiations : Error<
"instantiation of %q0 is different in different modules">;
+def warn_module_uses_date_time : Warning<
+ "%select{precompiled header|module}0 uses __DATE__ or __TIME__">,
+ InGroup<DiagGroup<"pch-date-time">>;
+
+def warn_duplicate_module_file_extension : Warning<
+ "duplicate module file extension block name '%0'">,
+ InGroup<ModuleFileExtension>;
+
} // let CategoryName
} // let Component
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h
index ac0d7a1..17758ec 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h
@@ -126,9 +126,9 @@ class FileManager : public RefCountedBase<FileManager> {
///
/// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
/// directories (foo/ and foo/bar/) here.
- SmallVector<DirectoryEntry*, 4> VirtualDirectoryEntries;
+ SmallVector<std::unique_ptr<DirectoryEntry>, 4> VirtualDirectoryEntries;
/// \brief The virtual files that we have allocated.
- SmallVector<FileEntry*, 4> VirtualFileEntries;
+ SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries;
/// \brief A cache that maps paths to directory entries (either real or
/// virtual) we have looked up
@@ -218,7 +218,8 @@ public:
bool CacheFailure = true);
/// \brief Returns the current file system options
- const FileSystemOptions &getFileSystemOptions() { return FileSystemOpts; }
+ FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
+ const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
IntrusiveRefCntPtr<vfs::FileSystem> getVirtualFileSystem() const {
return FS;
@@ -254,7 +255,13 @@ public:
/// \brief If path is not absolute and FileSystemOptions set the working
/// directory, the path is modified to be relative to the given
/// working directory.
- void FixupRelativePath(SmallVectorImpl<char> &path) const;
+ /// \returns true if \c path changed.
+ bool FixupRelativePath(SmallVectorImpl<char> &path) const;
+
+ /// Makes \c Path absolute taking into account FileSystemOptions and the
+ /// working directory option.
+ /// \returns true if \c Path changed to absolute.
+ bool makeAbsolutePath(SmallVectorImpl<char> &Path) const;
/// \brief Produce an array mapping from the unique IDs assigned to each
/// file to the corresponding FileEntry pointer.
@@ -266,9 +273,6 @@ public:
static void modifyFileEntry(FileEntry *File, off_t Size,
time_t ModificationTime);
- /// \brief Remove any './' components from a path.
- static bool removeDotPaths(SmallVectorImpl<char> &Path);
-
/// \brief Retrieve the canonical name for a given directory.
///
/// This is a very expensive operation, despite its results being cached,
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
index 1785e04..d672314 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
@@ -62,7 +62,7 @@ class IdentifierInfo {
// partially) from an AST file.
bool ChangedAfterLoad : 1; // True if identifier has changed from the
// definition loaded from an AST file.
- bool RevertedTokenID : 1; // True if RevertTokenIDToIdentifier was
+ bool RevertedTokenID : 1; // True if revertTokenIDToIdentifier was
// called.
bool OutOfDate : 1; // True if there may be additional
// information about this identifier
@@ -152,7 +152,7 @@ public:
/// tokens.
tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
- /// \brief True if RevertTokenIDToIdentifier() was called.
+ /// \brief True if revertTokenIDToIdentifier() was called.
bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; }
/// \brief Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2
@@ -161,11 +161,16 @@ public:
/// TokenID is normally read-only but there are 2 instances where we revert it
/// to tok::identifier for libstdc++ 4.2. Keep track of when this happens
/// using this method so we can inform serialization about it.
- void RevertTokenIDToIdentifier() {
+ void revertTokenIDToIdentifier() {
assert(TokenID != tok::identifier && "Already at tok::identifier");
TokenID = tok::identifier;
RevertedTokenID = true;
}
+ void revertIdentifierToTokenID(tok::TokenKind TK) {
+ assert(TokenID == tok::identifier && "Should be at tok::identifier");
+ TokenID = TK;
+ RevertedTokenID = false;
+ }
/// \brief Return the preprocessor keyword ID for this identifier.
///
@@ -183,6 +188,18 @@ public:
}
void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; }
+ /// \brief True if setNotBuiltin() was called.
+ bool hasRevertedBuiltin() const {
+ return ObjCOrBuiltinID == tok::NUM_OBJC_KEYWORDS;
+ }
+
+ /// \brief Revert the identifier to a non-builtin identifier. We do this if
+ /// the name of a known builtin library function is used to declare that
+ /// function, but an unexpected type is specified.
+ void revertBuiltin() {
+ setBuiltinID(0);
+ }
+
/// \brief Return a value indicating whether this is a builtin function.
///
/// 0 is not-built-in. 1 is builtin-for-some-nonprimary-target.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def
index c184df7..cc70d62 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def
@@ -90,6 +90,7 @@ LANGOPT(LineComment , 1, 0, "'//' comments")
LANGOPT(Bool , 1, 0, "bool, true, and false keywords")
LANGOPT(Half , 1, 0, "half keyword")
LANGOPT(WChar , 1, CPlusPlus, "wchar_t keyword")
+LANGOPT(DeclSpecKeyword , 1, 0, "__declspec keyword")
BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers")
BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode")
BENIGN_LANGOPT(GNUMode , 1, 1, "GNU extensions")
@@ -117,6 +118,7 @@ LANGOPT(Freestanding, 1, 0, "freestanding implementation")
LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly")
+LANGOPT(Coroutines , 1, 0, "C++ coroutines")
BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
LANGOPT(POSIXThreads , 1, 0, "POSIX thread support")
@@ -131,7 +133,6 @@ COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module us
BENIGN_LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery")
BENIGN_LANGOPT(ImplicitModules, 1, 1, "build modules that are not specified via -fmodule-file")
COMPATIBLE_LANGOPT(ModulesLocalVisibility, 1, 0, "local submodule visibility")
-COMPATIBLE_LANGOPT(ModulesHideInternalLinkage, 1, 1, "hiding non-visible internal linkage declarations from redeclaration lookup")
COMPATIBLE_LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro")
COMPATIBLE_LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
@@ -146,6 +147,7 @@ COMPATIBLE_LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro")
COMPATIBLE_LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro")
LANGOPT(FastMath , 1, 0, "__FAST_MATH__ predefined macro")
LANGOPT(FiniteMathOnly , 1, 0, "__FINITE_MATH_ONLY__ predefined macro")
+LANGOPT(UnsafeFPMath , 1, 0, "Unsafe Floating Point Math")
BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars")
@@ -163,9 +165,12 @@ LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns")
LANGOPT(CUDA , 1, 0, "CUDA")
LANGOPT(OpenMP , 1, 0, "OpenMP support")
LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls")
+LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device")
+
LANGOPT(CUDAIsDevice , 1, 0, "Compiling for CUDA device")
LANGOPT(CUDAAllowHostCallsFromHostDevice, 1, 0, "Allow host device functions to call host functions")
LANGOPT(CUDADisableTargetCallChecks, 1, 0, "Disable checks for call targets (host, device, etc.)")
+LANGOPT(CUDATargetOverloads, 1, 0, "Enable function overloads based on CUDA target attributes")
LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators")
LANGOPT(SizedDeallocation , 1, 0, "enable sized deallocation functions")
@@ -188,7 +193,8 @@ LANGOPT(DefaultFPContract , 1, 0, "FP_CONTRACT")
LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting")
-LANGOPT(ObjCARCWeak , 1, 0, "__weak support in the ARC runtime")
+LANGOPT(ObjCWeakRuntime , 1, 0, "__weak support in the ARC runtime")
+LANGOPT(ObjCWeak , 1, 0, "Objective-C __weak in ARC and MRC files")
LANGOPT(ObjCSubscriptingLegacyRuntime , 1, 0, "Subscripting support in legacy ObjectiveC runtime")
LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
index 3c9d23e..736d4e0 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
@@ -108,7 +108,18 @@ public:
/// \brief Options for parsing comments.
CommentOptions CommentOpts;
-
+
+ /// \brief A list of all -fno-builtin-* function names (e.g., memset).
+ std::vector<std::string> NoBuiltinFuncs;
+
+ /// \brief Triples of the OpenMP targets that the host code codegen should
+ /// take into account in order to generate accurate offloading descriptors.
+ std::vector<llvm::Triple> OMPTargetTriples;
+
+ /// \brief Name of the IR file that contains the result of the OpenMP target
+ /// host code generation.
+ std::string OMPHostIRFile;
+
LangOptions();
// Define accessors/mutators for language options of enumeration type.
@@ -134,6 +145,10 @@ public:
/// \brief Reset all of the options that are not considered when building a
/// module.
void resetNonModularOptions();
+
+ /// \brief Is this a libc/libm function that is no longer recognized as a
+ /// builtin because a -fno-builtin-* option has been specified?
+ bool isNoBuiltinFunc(const char *Name) const;
};
/// \brief Floating point control options
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Module.h b/contrib/llvm/tools/clang/include/clang/Basic/Module.h
index 1bc8925..1702fb1 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Module.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Module.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_BASIC_MODULE_H
#define LLVM_CLANG_BASIC_MODULE_H
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
@@ -35,9 +36,6 @@ namespace llvm {
namespace clang {
-class DirectoryEntry;
-class FileEntry;
-class FileManager;
class LangOptions;
class TargetInfo;
class IdentifierInfo;
@@ -152,6 +150,9 @@ public:
/// \brief Whether this module is missing a feature from \c Requirements.
unsigned IsMissingRequirement : 1;
+ /// \brief Whether we tried and failed to load a module file for this module.
+ unsigned HasIncompatibleModuleFile : 1;
+
/// \brief Whether this module is available in the current translation unit.
///
/// If the module is missing headers or does not meet all requirements then
@@ -356,6 +357,12 @@ public:
/// its top-level module.
std::string getFullModuleName() const;
+ /// \brief Whether the full name of this module is equal to joining
+ /// \p nameParts with "."s.
+ ///
+ /// This is more efficient than getFullModuleName().
+ bool fullModuleNameIs(ArrayRef<StringRef> nameParts) const;
+
/// \brief Retrieve the top-level module for this (sub)module, which may
/// be this module.
Module *getTopLevelModule() {
@@ -469,6 +476,13 @@ public:
submodule_iterator submodule_end() { return SubModules.end(); }
submodule_const_iterator submodule_end() const { return SubModules.end(); }
+ llvm::iterator_range<submodule_iterator> submodules() {
+ return llvm::make_range(submodule_begin(), submodule_end());
+ }
+ llvm::iterator_range<submodule_const_iterator> submodules() const {
+ return llvm::make_range(submodule_begin(), submodule_end());
+ }
+
/// \brief Appends this module's list of exported modules to \p Exported.
///
/// This provides a subset of immediately imported modules (the ones that are
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h b/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h
index e33587d..cf51b14 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h
@@ -41,6 +41,10 @@ public:
/// version of iOS.
iOS,
+ /// 'watchos' is a variant of iOS for Apple's watchOS. The version
+ /// is a release version of watchOS.
+ WatchOS,
+
/// 'gcc' is the Objective-C runtime shipped with GCC, implementing a
/// fragile Objective-C ABI
GCC,
@@ -81,6 +85,7 @@ public:
case GNUstep: return true;
case ObjFW: return true;
case iOS: return true;
+ case WatchOS: return true;
}
llvm_unreachable("bad kind");
}
@@ -114,6 +119,7 @@ public:
case FragileMacOSX:
case MacOSX:
case iOS:
+ case WatchOS:
return false;
case GCC:
case GNUstep:
@@ -133,9 +139,12 @@ public:
/// \brief Does this runtime allow ARC at all?
bool allowsARC() const {
switch (getKind()) {
- case FragileMacOSX: return false;
+ case FragileMacOSX:
+ // No stub library for the fragile runtime.
+ return getVersion() >= VersionTuple(10, 7);
case MacOSX: return true;
case iOS: return true;
+ case WatchOS: return true;
case GCC: return false;
case GNUstep: return true;
case ObjFW: return true;
@@ -150,9 +159,10 @@ public:
/// library.
bool hasNativeARC() const {
switch (getKind()) {
- case FragileMacOSX: return false;
+ case FragileMacOSX: return getVersion() >= VersionTuple(10, 7);
case MacOSX: return getVersion() >= VersionTuple(10, 7);
case iOS: return getVersion() >= VersionTuple(5);
+ case WatchOS: return true;
case GCC: return false;
case GNUstep: return getVersion() >= VersionTuple(1, 6);
@@ -168,6 +178,8 @@ public:
return getVersion() >= VersionTuple(10, 8);
case iOS:
return (getVersion() >= VersionTuple(6));
+ case WatchOS:
+ return true;
case GNUstep:
return getVersion() >= VersionTuple(1, 7);
@@ -197,6 +209,7 @@ public:
case FragileMacOSX: return false;
case MacOSX: return getVersion() >= VersionTuple(10, 8);
case iOS: return getVersion() >= VersionTuple(6);
+ case WatchOS: return true;
// This is really a lie, because some implementations and versions
// of the runtime do not support ARC. Probably -fgnu-runtime
@@ -224,6 +237,7 @@ public:
return true;
case MacOSX:
case iOS:
+ case WatchOS:
case GNUstep:
case ObjFW:
return false;
@@ -245,6 +259,7 @@ public:
case FragileMacOSX: return getVersion() >= VersionTuple(10, 8);
case MacOSX: return getVersion() >= VersionTuple(10, 8);
case iOS: return getVersion() >= VersionTuple(5);
+ case WatchOS: return true;
case GCC: return false;
case GNUstep: return false;
case ObjFW: return false;
@@ -257,6 +272,7 @@ public:
switch (getKind()) {
case MacOSX: return true;
case iOS: return true;
+ case WatchOS: return true;
case FragileMacOSX: return false;
case GCC: return true;
case GNUstep: return true;
@@ -270,6 +286,7 @@ public:
switch (getKind()) {
case MacOSX: return true;
case iOS: return true;
+ case WatchOS: return true;
case FragileMacOSX: return false;
case GCC: return true;
case GNUstep: return true;
@@ -283,6 +300,7 @@ public:
case FragileMacOSX:
case MacOSX:
case iOS:
+ case WatchOS:
return true;
case GNUstep:
return getVersion() >= VersionTuple(1, 7);
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def b/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
index 103fa83..91fd919 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
@@ -26,6 +26,9 @@ OPENCLEXT(cl_khr_local_int32_extended_atomics)
OPENCLEXT(cl_khr_byte_addressable_store)
OPENCLEXT(cl_khr_3d_image_writes)
+// OpenCL 2.0
+OPENCLEXT(cl_khr_gl_msaa_sharing)
+
// Clang Extensions.
OPENCLEXT(cl_clang_storage_class_specifiers)
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def
index 67a5068..44f77ad 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def
@@ -57,9 +57,30 @@
#ifndef OPENMP_TARGET_CLAUSE
# define OPENMP_TARGET_CLAUSE(Name)
#endif
+#ifndef OPENMP_TARGET_DATA_CLAUSE
+# define OPENMP_TARGET_DATA_CLAUSE(Name)
+#endif
#ifndef OPENMP_TEAMS_CLAUSE
# define OPENMP_TEAMS_CLAUSE(Name)
#endif
+#ifndef OPENMP_CANCEL_CLAUSE
+# define OPENMP_CANCEL_CLAUSE(Name)
+#endif
+#ifndef OPENMP_ORDERED_CLAUSE
+# define OPENMP_ORDERED_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TASKLOOP_CLAUSE
+# define OPENMP_TASKLOOP_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TASKLOOP_SIMD_CLAUSE
+# define OPENMP_TASKLOOP_SIMD_CLAUSE(Name)
+#endif
+#ifndef OPENMP_CRITICAL_CLAUSE
+# define OPENMP_CRITICAL_CLAUSE(Name)
+#endif
+#ifndef OPENMP_DISTRIBUTE_CLAUSE
+#define OPENMP_DISTRIBUTE_CLAUSE(Name)
+#endif
#ifndef OPENMP_DEFAULT_KIND
# define OPENMP_DEFAULT_KIND(Name)
#endif
@@ -69,9 +90,18 @@
#ifndef OPENMP_SCHEDULE_KIND
#define OPENMP_SCHEDULE_KIND(Name)
#endif
+#ifndef OPENMP_SCHEDULE_MODIFIER
+#define OPENMP_SCHEDULE_MODIFIER(Name)
+#endif
#ifndef OPENMP_DEPEND_KIND
#define OPENMP_DEPEND_KIND(Name)
#endif
+#ifndef OPENMP_LINEAR_KIND
+#define OPENMP_LINEAR_KIND(Name)
+#endif
+#ifndef OPENMP_MAP_KIND
+#define OPENMP_MAP_KIND(Name)
+#endif
// OpenMP directives.
OPENMP_DIRECTIVE(threadprivate)
@@ -94,17 +124,22 @@ OPENMP_DIRECTIVE(atomic)
OPENMP_DIRECTIVE(target)
OPENMP_DIRECTIVE(teams)
OPENMP_DIRECTIVE(cancel)
+OPENMP_DIRECTIVE_EXT(target_data, "target data")
OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for")
OPENMP_DIRECTIVE_EXT(parallel_for_simd, "parallel for simd")
OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections")
OPENMP_DIRECTIVE_EXT(for_simd, "for simd")
OPENMP_DIRECTIVE_EXT(cancellation_point, "cancellation point")
+OPENMP_DIRECTIVE(taskloop)
+OPENMP_DIRECTIVE_EXT(taskloop_simd, "taskloop simd")
+OPENMP_DIRECTIVE(distribute)
// OpenMP clauses.
OPENMP_CLAUSE(if, OMPIfClause)
OPENMP_CLAUSE(final, OMPFinalClause)
OPENMP_CLAUSE(num_threads, OMPNumThreadsClause)
OPENMP_CLAUSE(safelen, OMPSafelenClause)
+OPENMP_CLAUSE(simdlen, OMPSimdlenClause)
OPENMP_CLAUSE(collapse, OMPCollapseClause)
OPENMP_CLAUSE(default, OMPDefaultClause)
OPENMP_CLAUSE(private, OMPPrivateClause)
@@ -129,6 +164,17 @@ OPENMP_CLAUSE(update, OMPUpdateClause)
OPENMP_CLAUSE(capture, OMPCaptureClause)
OPENMP_CLAUSE(seq_cst, OMPSeqCstClause)
OPENMP_CLAUSE(depend, OMPDependClause)
+OPENMP_CLAUSE(device, OMPDeviceClause)
+OPENMP_CLAUSE(threads, OMPThreadsClause)
+OPENMP_CLAUSE(simd, OMPSIMDClause)
+OPENMP_CLAUSE(map, OMPMapClause)
+OPENMP_CLAUSE(num_teams, OMPNumTeamsClause)
+OPENMP_CLAUSE(thread_limit, OMPThreadLimitClause)
+OPENMP_CLAUSE(priority, OMPPriorityClause)
+OPENMP_CLAUSE(grainsize, OMPGrainsizeClause)
+OPENMP_CLAUSE(nogroup, OMPNogroupClause)
+OPENMP_CLAUSE(num_tasks, OMPNumTasksClause)
+OPENMP_CLAUSE(hint, OMPHintClause)
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
@@ -147,6 +193,7 @@ OPENMP_SIMD_CLAUSE(lastprivate)
OPENMP_SIMD_CLAUSE(linear)
OPENMP_SIMD_CLAUSE(aligned)
OPENMP_SIMD_CLAUSE(safelen)
+OPENMP_SIMD_CLAUSE(simdlen)
OPENMP_SIMD_CLAUSE(collapse)
OPENMP_SIMD_CLAUSE(reduction)
@@ -159,6 +206,7 @@ OPENMP_FOR_CLAUSE(collapse)
OPENMP_FOR_CLAUSE(schedule)
OPENMP_FOR_CLAUSE(ordered)
OPENMP_FOR_CLAUSE(nowait)
+OPENMP_FOR_CLAUSE(linear)
// Clauses allowed for directive 'omp for simd'.
OPENMP_FOR_SIMD_CLAUSE(private)
@@ -169,8 +217,10 @@ OPENMP_FOR_SIMD_CLAUSE(schedule)
OPENMP_FOR_SIMD_CLAUSE(collapse)
OPENMP_FOR_SIMD_CLAUSE(nowait)
OPENMP_FOR_SIMD_CLAUSE(safelen)
+OPENMP_FOR_SIMD_CLAUSE(simdlen)
OPENMP_FOR_SIMD_CLAUSE(linear)
OPENMP_FOR_SIMD_CLAUSE(aligned)
+OPENMP_FOR_SIMD_CLAUSE(ordered)
// Clauses allowed for OpenMP directive 'omp sections'.
OPENMP_SECTIONS_CLAUSE(private)
@@ -185,6 +235,9 @@ OPENMP_SINGLE_CLAUSE(firstprivate)
OPENMP_SINGLE_CLAUSE(copyprivate)
OPENMP_SINGLE_CLAUSE(nowait)
+// Clauses allowed for OpenMP directive 'cancel'.
+OPENMP_CANCEL_CLAUSE(if)
+
// Static attributes for 'default' clause.
OPENMP_DEFAULT_KIND(none)
OPENMP_DEFAULT_KIND(shared)
@@ -201,10 +254,22 @@ OPENMP_SCHEDULE_KIND(guided)
OPENMP_SCHEDULE_KIND(auto)
OPENMP_SCHEDULE_KIND(runtime)
+// Modifiers for 'schedule' clause.
+OPENMP_SCHEDULE_MODIFIER(monotonic)
+OPENMP_SCHEDULE_MODIFIER(nonmonotonic)
+OPENMP_SCHEDULE_MODIFIER(simd)
+
// Static attributes for 'depend' clause.
OPENMP_DEPEND_KIND(in)
OPENMP_DEPEND_KIND(out)
OPENMP_DEPEND_KIND(inout)
+OPENMP_DEPEND_KIND(source)
+OPENMP_DEPEND_KIND(sink)
+
+// Modifiers for 'linear' clause.
+OPENMP_LINEAR_KIND(val)
+OPENMP_LINEAR_KIND(ref)
+OPENMP_LINEAR_KIND(uval)
// Clauses allowed for OpenMP directive 'parallel for'.
OPENMP_PARALLEL_FOR_CLAUSE(if)
@@ -220,6 +285,7 @@ OPENMP_PARALLEL_FOR_CLAUSE(lastprivate)
OPENMP_PARALLEL_FOR_CLAUSE(collapse)
OPENMP_PARALLEL_FOR_CLAUSE(schedule)
OPENMP_PARALLEL_FOR_CLAUSE(ordered)
+OPENMP_PARALLEL_FOR_CLAUSE(linear)
// Clauses allowed for OpenMP directive 'parallel for simd'.
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(if)
@@ -235,8 +301,10 @@ OPENMP_PARALLEL_FOR_SIMD_CLAUSE(lastprivate)
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(collapse)
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(schedule)
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(safelen)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(simdlen)
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(linear)
OPENMP_PARALLEL_FOR_SIMD_CLAUSE(aligned)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(ordered)
// Clauses allowed for OpenMP directive 'parallel sections'.
OPENMP_PARALLEL_SECTIONS_CLAUSE(if)
@@ -260,6 +328,7 @@ OPENMP_TASK_CLAUSE(shared)
OPENMP_TASK_CLAUSE(untied)
OPENMP_TASK_CLAUSE(mergeable)
OPENMP_TASK_CLAUSE(depend)
+OPENMP_TASK_CLAUSE(priority)
// Clauses allowed for OpenMP directive 'atomic'.
OPENMP_ATOMIC_CLAUSE(read)
@@ -271,6 +340,14 @@ OPENMP_ATOMIC_CLAUSE(seq_cst)
// Clauses allowed for OpenMP directive 'target'.
// TODO More clauses for 'target' directive.
OPENMP_TARGET_CLAUSE(if)
+OPENMP_TARGET_CLAUSE(device)
+OPENMP_TARGET_CLAUSE(map)
+
+// Clauses allowed for OpenMP directive 'target data'.
+// TODO More clauses for 'target data' directive.
+OPENMP_TARGET_DATA_CLAUSE(if)
+OPENMP_TARGET_DATA_CLAUSE(device)
+OPENMP_TARGET_DATA_CLAUSE(map)
// Clauses allowed for OpenMP directive 'teams'.
// TODO More clauses for 'teams' directive.
@@ -279,14 +356,83 @@ OPENMP_TEAMS_CLAUSE(private)
OPENMP_TEAMS_CLAUSE(firstprivate)
OPENMP_TEAMS_CLAUSE(shared)
OPENMP_TEAMS_CLAUSE(reduction)
+OPENMP_TEAMS_CLAUSE(num_teams)
+OPENMP_TEAMS_CLAUSE(thread_limit)
+
+// Clauses allowed for OpenMP directive 'ordered'.
+// TODO More clauses for 'ordered' directive.
+OPENMP_ORDERED_CLAUSE(threads)
+OPENMP_ORDERED_CLAUSE(simd)
+OPENMP_ORDERED_CLAUSE(depend)
+
+// Map types and map type modifier for 'map' clause.
+OPENMP_MAP_KIND(alloc)
+OPENMP_MAP_KIND(to)
+OPENMP_MAP_KIND(from)
+OPENMP_MAP_KIND(tofrom)
+OPENMP_MAP_KIND(delete)
+OPENMP_MAP_KIND(release)
+OPENMP_MAP_KIND(always)
+// Clauses allowed for OpenMP directive 'taskloop'.
+OPENMP_TASKLOOP_CLAUSE(if)
+OPENMP_TASKLOOP_CLAUSE(shared)
+OPENMP_TASKLOOP_CLAUSE(private)
+OPENMP_TASKLOOP_CLAUSE(firstprivate)
+OPENMP_TASKLOOP_CLAUSE(lastprivate)
+OPENMP_TASKLOOP_CLAUSE(default)
+OPENMP_TASKLOOP_CLAUSE(collapse)
+OPENMP_TASKLOOP_CLAUSE(final)
+OPENMP_TASKLOOP_CLAUSE(untied)
+OPENMP_TASKLOOP_CLAUSE(mergeable)
+OPENMP_TASKLOOP_CLAUSE(priority)
+OPENMP_TASKLOOP_CLAUSE(grainsize)
+OPENMP_TASKLOOP_CLAUSE(nogroup)
+OPENMP_TASKLOOP_CLAUSE(num_tasks)
+
+// Clauses allowed for OpenMP directive 'taskloop simd'.
+OPENMP_TASKLOOP_SIMD_CLAUSE(if)
+OPENMP_TASKLOOP_SIMD_CLAUSE(shared)
+OPENMP_TASKLOOP_SIMD_CLAUSE(private)
+OPENMP_TASKLOOP_SIMD_CLAUSE(firstprivate)
+OPENMP_TASKLOOP_SIMD_CLAUSE(lastprivate)
+OPENMP_TASKLOOP_SIMD_CLAUSE(default)
+OPENMP_TASKLOOP_SIMD_CLAUSE(collapse)
+OPENMP_TASKLOOP_SIMD_CLAUSE(final)
+OPENMP_TASKLOOP_SIMD_CLAUSE(untied)
+OPENMP_TASKLOOP_SIMD_CLAUSE(mergeable)
+OPENMP_TASKLOOP_SIMD_CLAUSE(priority)
+OPENMP_TASKLOOP_SIMD_CLAUSE(linear)
+OPENMP_TASKLOOP_SIMD_CLAUSE(aligned)
+OPENMP_TASKLOOP_SIMD_CLAUSE(safelen)
+OPENMP_TASKLOOP_SIMD_CLAUSE(simdlen)
+OPENMP_TASKLOOP_SIMD_CLAUSE(grainsize)
+OPENMP_TASKLOOP_SIMD_CLAUSE(nogroup)
+OPENMP_TASKLOOP_SIMD_CLAUSE(num_tasks)
+
+// Clauses allowed for OpenMP directive 'critical'.
+OPENMP_CRITICAL_CLAUSE(hint)
+
+// Clauses allowed for OpenMP directive 'distribute'
+OPENMP_DISTRIBUTE_CLAUSE(private)
+OPENMP_DISTRIBUTE_CLAUSE(firstprivate)
+OPENMP_DISTRIBUTE_CLAUSE(lastprivate)
+OPENMP_DISTRIBUTE_CLAUSE(collapse)
+
+#undef OPENMP_TASKLOOP_SIMD_CLAUSE
+#undef OPENMP_TASKLOOP_CLAUSE
+#undef OPENMP_LINEAR_KIND
#undef OPENMP_DEPEND_KIND
+#undef OPENMP_SCHEDULE_MODIFIER
#undef OPENMP_SCHEDULE_KIND
#undef OPENMP_PROC_BIND_KIND
#undef OPENMP_DEFAULT_KIND
#undef OPENMP_DIRECTIVE
#undef OPENMP_DIRECTIVE_EXT
#undef OPENMP_CLAUSE
+#undef OPENMP_CRITICAL_CLAUSE
+#undef OPENMP_ORDERED_CLAUSE
+#undef OPENMP_CANCEL_CLAUSE
#undef OPENMP_SINGLE_CLAUSE
#undef OPENMP_SECTIONS_CLAUSE
#undef OPENMP_PARALLEL_CLAUSE
@@ -296,8 +442,10 @@ OPENMP_TEAMS_CLAUSE(reduction)
#undef OPENMP_TASK_CLAUSE
#undef OPENMP_ATOMIC_CLAUSE
#undef OPENMP_TARGET_CLAUSE
+#undef OPENMP_TARGET_DATA_CLAUSE
#undef OPENMP_TEAMS_CLAUSE
#undef OPENMP_SIMD_CLAUSE
#undef OPENMP_FOR_CLAUSE
#undef OPENMP_FOR_SIMD_CLAUSE
-
+#undef OPENMP_MAP_KIND
+#undef OPENMP_DISTRIBUTE_CLAUSE
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h
index 83939bb..d4d3db8 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h
@@ -62,6 +62,15 @@ enum OpenMPScheduleClauseKind {
OMPC_SCHEDULE_unknown
};
+/// \brief OpenMP modifiers for 'schedule' clause.
+enum OpenMPScheduleClauseModifier {
+ OMPC_SCHEDULE_MODIFIER_unknown = OMPC_SCHEDULE_unknown,
+#define OPENMP_SCHEDULE_MODIFIER(Name) \
+ OMPC_SCHEDULE_MODIFIER_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_SCHEDULE_MODIFIER_last
+};
+
/// \brief OpenMP attributes for 'depend' clause.
enum OpenMPDependClauseKind {
#define OPENMP_DEPEND_KIND(Name) \
@@ -70,6 +79,22 @@ enum OpenMPDependClauseKind {
OMPC_DEPEND_unknown
};
+/// \brief OpenMP attributes for 'linear' clause.
+enum OpenMPLinearClauseKind {
+#define OPENMP_LINEAR_KIND(Name) \
+ OMPC_LINEAR_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_LINEAR_unknown
+};
+
+/// \brief OpenMP mapping kind for 'map' clause.
+enum OpenMPMapClauseKind {
+#define OPENMP_MAP_KIND(Name) \
+ OMPC_MAP_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_MAP_unknown
+};
+
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);
@@ -95,12 +120,24 @@ bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind);
/// otherwise - false.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind);
+/// \brief Checks if the specified directive is a taskloop directive.
+/// \param DKind Specified directive.
+/// \return true - the directive is a worksharing directive like 'omp taskloop',
+/// otherwise - false.
+bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind);
+
/// \brief Checks if the specified directive is a parallel-kind directive.
/// \param DKind Specified directive.
/// \return true - the directive is a parallel-like directive like 'omp
/// parallel', otherwise - false.
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind);
+/// \brief Checks if the specified directive is a target-kind directive.
+/// \param DKind Specified directive.
+/// \return true - the directive is a target-like directive like 'omp target',
+/// otherwise - false.
+bool isOpenMPTargetDirective(OpenMPDirectiveKind DKind);
+
/// \brief Checks if the specified directive is a teams-kind directive.
/// \param DKind Specified directive.
/// \return true - the directive is a teams-like directive like 'omp teams',
@@ -113,6 +150,13 @@ bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind);
/// otherwise - false.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind);
+/// \brief Checks if the specified directive is a distribute directive.
+/// \param DKind Specified directive.
+/// \return true - the directive is a distribute-directive like 'omp
+/// distribute',
+/// otherwise - false.
+bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind);
+
/// \brief Checks if the specified clause is one of private clauses like
/// 'private', 'firstprivate', 'reduction' etc..
/// \param Kind Clause kind.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def
index d011e9d..34ad764 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def
@@ -101,6 +101,7 @@ OVERLOADED_OPERATOR_MULTI(Subscript , "[]" , false, t
// ?: can *not* be overloaded, but we need the overload
// resolution machinery for it.
OVERLOADED_OPERATOR_MULTI(Conditional , "?" , false, true , false)
+OVERLOADED_OPERATOR(Coawait , "co_await", kw_co_await , true , false, false)
#undef OVERLOADED_OPERATOR_MULTI
#undef OVERLOADED_OPERATOR
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
index 84c8dd1..53ce95c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
@@ -377,7 +377,7 @@ public:
}
friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
- const SourceRange &R) {
+ SourceRange R) {
PD.AddSourceRange(CharSourceRange::getTokenRange(R));
return PD;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def
index 1b528c8..4b68593 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def
@@ -84,11 +84,13 @@ SANITIZER("dataflow", DataFlow)
// Control Flow Integrity
SANITIZER("cfi-cast-strict", CFICastStrict)
SANITIZER("cfi-derived-cast", CFIDerivedCast)
+SANITIZER("cfi-icall", CFIICall)
SANITIZER("cfi-unrelated-cast", CFIUnrelatedCast)
SANITIZER("cfi-nvcall", CFINVCall)
SANITIZER("cfi-vcall", CFIVCall)
SANITIZER_GROUP("cfi", CFI,
- CFIDerivedCast | CFIUnrelatedCast | CFINVCall | CFIVCall)
+ CFIDerivedCast | CFIICall | CFIUnrelatedCast | CFINVCall |
+ CFIVCall)
// Safe Stack
SANITIZER("safe-stack", SafeStack)
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
index 7aaee1d..0aeba5e 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
@@ -43,6 +43,7 @@ class FileID {
public:
FileID() : ID(0) {}
+ bool isValid() const { return ID != 0; }
bool isInvalid() const { return ID == 0; }
bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
@@ -252,7 +253,7 @@ public:
SourceLocation getBegin() const { return Range.getBegin(); }
SourceLocation getEnd() const { return Range.getEnd(); }
- const SourceRange &getAsRange() const { return Range; }
+ SourceRange getAsRange() const { return Range; }
void setBegin(SourceLocation b) { Range.setBegin(b); }
void setEnd(SourceLocation e) { Range.setEnd(e); }
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
index 3aea5ea..99392a0 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
@@ -39,6 +39,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -121,7 +122,7 @@ namespace SrcMgr {
/// \brief The number of lines in this ContentCache.
///
/// This is only valid if SourceLineCache is non-null.
- unsigned NumLines : 31;
+ unsigned NumLines;
/// \brief Indicates whether the buffer itself was provided to override
/// the actual file contents.
@@ -134,12 +135,17 @@ namespace SrcMgr {
/// file considered as a system one.
unsigned IsSystemFile : 1;
+ /// \brief True if this file may be transient, that is, if it might not
+ /// exist at some later point in time when this content entry is used,
+ /// after serialization and deserialization.
+ unsigned IsTransient : 1;
+
ContentCache(const FileEntry *Ent = nullptr) : ContentCache(Ent, Ent) {}
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
: Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
SourceLineCache(nullptr), NumLines(0), BufferOverridden(false),
- IsSystemFile(false) {}
+ IsSystemFile(false), IsTransient(false) {}
~ContentCache();
@@ -148,7 +154,7 @@ namespace SrcMgr {
/// is not transferred, so this is a logical error.
ContentCache(const ContentCache &RHS)
: Buffer(nullptr, false), SourceLineCache(nullptr),
- BufferOverridden(false), IsSystemFile(false) {
+ BufferOverridden(false), IsSystemFile(false), IsTransient(false) {
OrigEntry = RHS.OrigEntry;
ContentsEntry = RHS.ContentsEntry;
@@ -388,15 +394,16 @@ namespace SrcMgr {
/// SourceManager keeps an array of these objects, and they are uniquely
/// identified by the FileID datatype.
class SLocEntry {
- unsigned Offset; // low bit is set for expansion info.
+ unsigned Offset : 31;
+ unsigned IsExpansion : 1;
union {
FileInfo File;
ExpansionInfo Expansion;
};
public:
- unsigned getOffset() const { return Offset >> 1; }
+ unsigned getOffset() const { return Offset; }
- bool isExpansion() const { return Offset & 1; }
+ bool isExpansion() const { return IsExpansion; }
bool isFile() const { return !isExpansion(); }
const FileInfo &getFile() const {
@@ -410,15 +417,19 @@ namespace SrcMgr {
}
static SLocEntry get(unsigned Offset, const FileInfo &FI) {
+ assert(!(Offset & (1 << 31)) && "Offset is too large");
SLocEntry E;
- E.Offset = Offset << 1;
+ E.Offset = Offset;
+ E.IsExpansion = false;
E.File = FI;
return E;
}
static SLocEntry get(unsigned Offset, const ExpansionInfo &Expansion) {
+ assert(!(Offset & (1 << 31)) && "Offset is too large");
SLocEntry E;
- E.Offset = (Offset << 1) | 1;
+ E.Offset = Offset;
+ E.IsExpansion = true;
E.Expansion = Expansion;
return E;
}
@@ -560,6 +571,11 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// (likely to change while trying to use them). Defaults to false.
bool UserFilesAreVolatile;
+ /// \brief True if all files read during this compilation should be treated
+ /// as transient (may not be present in later compilations using a module
+ /// file created from this compilation). Defaults to false.
+ bool FilesAreTransient;
+
struct OverriddenFilesInfoTy {
/// \brief Files that have been overridden with the contents from another
/// file.
@@ -615,7 +631,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// have already been loaded from the external source.
///
/// Same indexing as LoadedSLocEntryTable.
- std::vector<bool> SLocEntryLoaded;
+ llvm::BitVector SLocEntryLoaded;
/// \brief An external source for source location entries.
ExternalSLocEntrySource *ExternalSLocEntries;
@@ -851,6 +867,15 @@ public:
/// This should be called before parsing has begun.
void disableFileContentsOverride(const FileEntry *File);
+ /// \brief Specify that a file is transient.
+ void setFileIsTransient(const FileEntry *SourceFile);
+
+ /// \brief Specify that all files that are read during this compilation are
+ /// transient.
+ void setAllFilesAreTransient(bool Transient) {
+ FilesAreTransient = Transient;
+ }
+
//===--------------------------------------------------------------------===//
// FileID manipulation methods.
//===--------------------------------------------------------------------===//
@@ -1139,10 +1164,14 @@ public:
/// \brief Tests whether the given source location represents a macro
/// argument's expansion into the function-like macro definition.
///
+ /// \param StartLoc If non-null and function returns true, it is set to the
+ /// start location of the macro argument expansion.
+ ///
/// Such source locations only appear inside of the expansion
/// locations representing where a particular function-like macro was
/// expanded.
- bool isMacroArgExpansion(SourceLocation Loc) const;
+ bool isMacroArgExpansion(SourceLocation Loc,
+ SourceLocation *StartLoc = nullptr) const;
/// \brief Tests whether the given source location represents the expansion of
/// a macro body.
@@ -1463,6 +1492,8 @@ public:
///
void PrintStats() const;
+ void dump() const;
+
/// \brief Get the number of local SLocEntries we have.
unsigned local_sloc_entry_size() const { return LocalSLocEntryTable.size(); }
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
index d95a77f..e284171 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
namespace clang {
/// \brief Specifies the width of a type, e.g., short, long, or long long.
@@ -35,6 +36,11 @@ namespace clang {
TSS_unsigned
};
+ enum TypeSpecifiersPipe {
+ TSP_unspecified,
+ TSP_pipe
+ };
+
/// \brief Specifies the kind of type.
enum TypeSpecifierType {
TST_unspecified,
@@ -64,6 +70,7 @@ namespace clang {
TST_underlyingType, // __underlying_type for C++11
TST_auto, // C++11 auto
TST_decltype_auto, // C++1y decltype(auto)
+ TST_auto_type, // __auto_type extension
TST_unknown_anytype, // __unknown_anytype extension
TST_atomic, // C11 _Atomic
TST_error // erroneous type
@@ -156,6 +163,24 @@ namespace clang {
return Kind != TSK_Undeclared && Kind != TSK_ExplicitSpecialization;
}
+ /// \brief True if this template specialization kind is an explicit
+ /// specialization, explicit instantiation declaration, or explicit
+ /// instantiation definition.
+ inline bool isTemplateExplicitInstantiationOrSpecialization(
+ TemplateSpecializationKind Kind) {
+ switch (Kind) {
+ case TSK_ExplicitSpecialization:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ return true;
+
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ return false;
+ }
+ llvm_unreachable("bad template specialization kind");
+ }
+
/// \brief Thread storage-class-specifier.
enum ThreadStorageClassSpecifier {
TSCS_unspecified,
@@ -178,7 +203,6 @@ namespace clang {
SC_PrivateExtern,
// These are only legal on variables.
- SC_OpenCLWorkGroupLocal,
SC_Auto,
SC_Register
};
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td
index 9d7b6fb..36519ea 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td
@@ -48,6 +48,10 @@ def CXXCatchStmt : Stmt;
def CXXTryStmt : Stmt;
def CXXForRangeStmt : Stmt;
+// C++ Coroutines TS statements
+def CoroutineBodyStmt : Stmt;
+def CoreturnStmt : Stmt;
+
// Expressions
def Expr : Stmt<1>;
def PredefinedExpr : DStmt<Expr>;
@@ -62,6 +66,7 @@ def UnaryOperator : DStmt<Expr>;
def OffsetOfExpr : DStmt<Expr>;
def UnaryExprOrTypeTraitExpr : DStmt<Expr>;
def ArraySubscriptExpr : DStmt<Expr>;
+def OMPArraySectionExpr : DStmt<Expr>;
def CallExpr : DStmt<Expr>;
def MemberExpr : DStmt<Expr>;
def CastExpr : DStmt<Expr, 1>;
@@ -139,6 +144,11 @@ def MaterializeTemporaryExpr : DStmt<Expr>;
def LambdaExpr : DStmt<Expr>;
def CXXFoldExpr : DStmt<Expr>;
+// C++ Coroutines TS expressions
+def CoroutineSuspendExpr : DStmt<Expr, 1>;
+def CoawaitExpr : DStmt<CoroutineSuspendExpr>;
+def CoyieldExpr : DStmt<CoroutineSuspendExpr>;
+
// Obj-C Expressions.
def ObjCStringLiteral : DStmt<Expr>;
def ObjCBoxedExpr : DStmt<Expr>;
@@ -170,6 +180,7 @@ def TypoExpr : DStmt<Expr>;
// Microsoft Extensions.
def MSPropertyRefExpr : DStmt<Expr>;
+def MSPropertySubscriptExpr : DStmt<Expr>;
def CXXUuidofExpr : DStmt<Expr>;
def SEHTryStmt : Stmt;
def SEHExceptStmt : Stmt;
@@ -204,6 +215,10 @@ def OMPFlushDirective : DStmt<OMPExecutableDirective>;
def OMPOrderedDirective : DStmt<OMPExecutableDirective>;
def OMPAtomicDirective : DStmt<OMPExecutableDirective>;
def OMPTargetDirective : DStmt<OMPExecutableDirective>;
+def OMPTargetDataDirective : DStmt<OMPExecutableDirective>;
def OMPTeamsDirective : DStmt<OMPExecutableDirective>;
def OMPCancellationPointDirective : DStmt<OMPExecutableDirective>;
def OMPCancelDirective : DStmt<OMPExecutableDirective>;
+def OMPTaskLoopDirective : DStmt<OMPLoopDirective>;
+def OMPTaskLoopSimdDirective : DStmt<OMPLoopDirective>;
+def OMPDistributeDirective : DStmt<OMPLoopDirective>;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h
index b4740c5..623c0b6 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h
@@ -185,6 +185,17 @@ namespace clang {
LastTSBuiltin
};
}
+
+ /// \brief WebAssembly builtins
+ namespace WebAssembly {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsWebAssembly.def"
+ LastTSBuiltin
+ };
+ }
+
} // end namespace clang.
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h
index 42a976b..67247ea 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h
@@ -71,6 +71,11 @@ public:
/// /help/topic/com.arm.doc.ihi0059a/IHI0059A_cppabi64.pdf
iOS64,
+ /// WatchOS is a modernisation of the iOS ABI, which roughly means it's
+ /// the iOS64 ABI ported to 32-bits. The primary difference from iOS64 is
+ /// that RTTI objects must still be unique at the moment.
+ WatchOS,
+
/// The generic AArch64 ABI is also a modified version of the Itanium ABI,
/// but it has fewer divergences than the 32-bit ARM ABI.
///
@@ -85,6 +90,21 @@ public:
/// - representation of member function pointers adjusted as in ARM.
GenericMIPS,
+ /// The WebAssembly ABI is a modified version of the Itanium ABI.
+ ///
+ /// The changes from the Itanium ABI are:
+ /// - representation of member function pointers is adjusted, as in ARM;
+ /// - member functions are not specially aligned;
+ /// - constructors and destructors return 'this', as in ARM;
+ /// - guard variables are 32-bit on wasm32, as in ARM;
+ /// - unused bits of guard variables are reserved, as in ARM;
+ /// - inline functions are never key functions, as in ARM;
+ /// - C++11 POD rules are used for tail padding, as in iOS64.
+ ///
+ /// TODO: At present the WebAssembly ABI is not considered stable, so none
+ /// of these details is necessarily final yet.
+ WebAssembly,
+
/// The Microsoft ABI is the ABI used by Microsoft Visual Studio (and
/// compatible compilers).
///
@@ -120,7 +140,9 @@ public:
case GenericARM:
case iOS:
case iOS64:
+ case WatchOS:
case GenericMIPS:
+ case WebAssembly:
return true;
case Microsoft:
@@ -137,7 +159,9 @@ public:
case GenericARM:
case iOS:
case iOS64:
+ case WatchOS:
case GenericMIPS:
+ case WebAssembly:
return false;
case Microsoft:
@@ -146,6 +170,36 @@ public:
llvm_unreachable("bad ABI kind");
}
+ /// \brief Are member functions differently aligned?
+ ///
+ /// Many Itanium-style C++ ABIs require member functions to be aligned, so
+ /// that a pointer to such a function is guaranteed to have a zero in the
+ /// least significant bit, so that pointers to member functions can use that
+ /// bit to distinguish between virtual and non-virtual functions. However,
+ /// some Itanium-style C++ ABIs differentiate between virtual and non-virtual
+ /// functions via other means, and consequently don't require that member
+ /// functions be aligned.
+ bool areMemberFunctionsAligned() const {
+ switch (getKind()) {
+ case WebAssembly:
+ // WebAssembly doesn't require any special alignment for member functions.
+ return false;
+ case GenericARM:
+ case GenericAArch64:
+ case GenericMIPS:
+ // TODO: ARM-style pointers to member functions put the discriminator in
+ // the this adjustment, so they don't require functions to have any
+ // special alignment and could therefore also return false.
+ case GenericItanium:
+ case iOS:
+ case iOS64:
+ case WatchOS:
+ case Microsoft:
+ return true;
+ }
+ llvm_unreachable("bad ABI kind");
+ }
+
/// \brief Is the default C++ member function calling convention
/// the same as the default calling convention?
bool isMemberFunctionCCDefault() const {
@@ -214,6 +268,8 @@ public:
switch (getKind()) {
case GenericARM:
case iOS64:
+ case WebAssembly:
+ case WatchOS:
return false;
case GenericAArch64:
@@ -261,7 +317,7 @@ public:
switch (getKind()) {
// To preserve binary compatibility, the generic Itanium ABI has
// permanently locked the definition of POD to the rules of C++ TR1,
- // and that trickles down to all the derived ABIs.
+ // and that trickles down to derived ABIs.
case GenericItanium:
case GenericAArch64:
case GenericARM:
@@ -269,9 +325,11 @@ public:
case GenericMIPS:
return UseTailPaddingUnlessPOD03;
- // iOS on ARM64 uses the C++11 POD rules. It does not honor the
- // Itanium exception about classes with over-large bitfields.
+ // iOS on ARM64 and WebAssembly use the C++11 POD rules. They do not honor
+ // the Itanium exception about classes with over-large bitfields.
case iOS64:
+ case WebAssembly:
+ case WatchOS:
return UseTailPaddingUnlessPOD11;
// MSVC always allocates fields in the tail-padding of a base class
@@ -282,9 +340,6 @@ public:
llvm_unreachable("bad ABI kind");
}
- /// Try to parse an ABI name, returning false on error.
- bool tryParse(llvm::StringRef name);
-
friend bool operator==(const TargetCXXABI &left, const TargetCXXABI &right) {
return left.getKind() == right.getKind();
}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
index 39f575f..f1d8338 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
@@ -22,6 +22,8 @@
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
@@ -72,7 +74,7 @@ protected:
unsigned short MaxVectorAlign;
unsigned short MaxTLSAlign;
unsigned short SimdDefaultAlign;
- const char *DescriptionString;
+ const char *DataLayoutString;
const char *UserLabelPrefix;
const char *MCountName;
const llvm::fltSemantics *HalfFormat, *FloatFormat, *DoubleFormat,
@@ -88,6 +90,8 @@ protected:
unsigned RealTypeUsesObjCFPRet : 3;
unsigned ComplexLongDoubleUsesFP2Ret : 1;
+ unsigned HasBuiltinMSVaList : 1;
+
// TargetInfo Constructor. Default initializes all fields.
TargetInfo(const llvm::Triple &T);
@@ -104,9 +108,9 @@ public:
virtual ~TargetInfo();
/// \brief Retrieve the target options.
- TargetOptions &getTargetOpts() const {
+ TargetOptions &getTargetOpts() const {
assert(TargetOpts && "Missing target options");
- return *TargetOpts;
+ return *TargetOpts;
}
///===---- Target Data Type Query Methods -------------------------------===//
@@ -253,10 +257,11 @@ public:
unsigned getTypeWidth(IntType T) const;
/// \brief Return integer type with specified width.
- IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const;
+ virtual IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const;
/// \brief Return the smallest integer type with at least the specified width.
- IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const;
+ virtual IntType getLeastIntTypeByWidth(unsigned BitWidth,
+ bool IsSigned) const;
/// \brief Return floating point type with specified width.
RealType getRealTypeByWidth(unsigned BitWidth) const;
@@ -311,7 +316,9 @@ public:
unsigned getLongLongAlign() const { return LongLongAlign; }
/// \brief Determine whether the __int128 type is supported on this target.
- virtual bool hasInt128Type() const { return getPointerWidth(0) >= 64; } // FIXME
+ virtual bool hasInt128Type() const {
+ return getPointerWidth(0) >= 64;
+ } // FIXME
/// \brief Return the alignment that is suitable for storing any
/// object with a fundamental alignment requirement.
@@ -509,8 +516,7 @@ public:
/// Return information about target-specific builtins for
/// the current primary target, and info about which builtins are non-portable
/// across the current set of primary and secondary targets.
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const = 0;
+ virtual ArrayRef<Builtin::Info> getTargetBuiltins() const = 0;
/// The __builtin_clz* and __builtin_ctz* built-in
/// functions are specified to have undefined results for zero inputs, but
@@ -523,6 +529,10 @@ public:
/// with this target.
virtual BuiltinVaListKind getBuiltinVaListKind() const = 0;
+ /// Returns whether or not type \c __builtin_ms_va_list type is
+ /// available on this target.
+ bool hasBuiltinMSVaList() const { return HasBuiltinMSVaList; }
+
/// \brief Returns whether the passed in string is a valid clobber in an
/// inline asm statement.
///
@@ -556,6 +566,7 @@ public:
int Min;
int Max;
} ImmRange;
+ llvm::SmallSet<int, 4> ImmSet;
std::string ConstraintStr; // constraint: "=rm"
std::string Name; // Operand name: [foo] with no []'s.
@@ -591,8 +602,10 @@ public:
bool requiresImmediateConstant() const {
return (Flags & CI_ImmediateConstant) != 0;
}
- int getImmConstantMin() const { return ImmRange.Min; }
- int getImmConstantMax() const { return ImmRange.Max; }
+ bool isValidAsmImmediate(const llvm::APInt &Value) const {
+ return (Value.sge(ImmRange.Min) && Value.sle(ImmRange.Max)) ||
+ ImmSet.count(Value.getZExtValue()) != 0;
+ }
void setIsReadWrite() { Flags |= CI_ReadWrite; }
void setEarlyClobber() { Flags |= CI_EarlyClobber; }
@@ -604,9 +617,23 @@ public:
ImmRange.Min = Min;
ImmRange.Max = Max;
}
+ void setRequiresImmediate(llvm::ArrayRef<int> Exacts) {
+ Flags |= CI_ImmediateConstant;
+ for (int Exact : Exacts)
+ ImmSet.insert(Exact);
+ }
+ void setRequiresImmediate(int Exact) {
+ Flags |= CI_ImmediateConstant;
+ ImmSet.insert(Exact);
+ }
+ void setRequiresImmediate() {
+ Flags |= CI_ImmediateConstant;
+ ImmRange.Min = INT_MIN;
+ ImmRange.Max = INT_MAX;
+ }
/// \brief Indicate that this is an input operand that is tied to
- /// the specified output operand.
+ /// the specified output operand.
///
/// Copy over the various constraint information from the output.
void setTiedOperand(unsigned N, ConstraintInfo &Output) {
@@ -617,15 +644,24 @@ public:
}
};
- // Validate the contents of the __builtin_cpu_supports(const char*) argument.
- virtual bool validateCpuSupports(StringRef Name) const { return false; }
+ /// \brief Validate register name used for global register variables.
+ ///
+ /// This function returns true if the register passed in RegName can be used
+ /// for global register variables on this target. In addition, it returns
+ /// true in HasSizeMismatch if the size of the register doesn't match the
+ /// variable size passed in RegSize.
+ virtual bool validateGlobalRegisterVariable(StringRef RegName,
+ unsigned RegSize,
+ bool &HasSizeMismatch) const {
+ HasSizeMismatch = false;
+ return true;
+ }
// validateOutputConstraint, validateInputConstraint - Checks that
// a constraint is valid and provides information about it.
// FIXME: These should return a real error instead of just true/false.
bool validateOutputConstraint(ConstraintInfo &Info) const;
- bool validateInputConstraint(ConstraintInfo *OutputConstraints,
- unsigned NumOutputs,
+ bool validateInputConstraint(MutableArrayRef<ConstraintInfo> OutputConstraints,
ConstraintInfo &info) const;
virtual bool validateOutputSize(StringRef /*Constraint*/,
@@ -644,9 +680,13 @@ public:
std::string &/*SuggestedModifier*/) const {
return true;
}
+ virtual bool
+ validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const = 0;
+
bool resolveSymbolicName(const char *&Name,
- ConstraintInfo *OutputConstraints,
- unsigned NumOutputs, unsigned &Index) const;
+ ArrayRef<ConstraintInfo> OutputConstraints,
+ unsigned &Index) const;
// Constraint parm will be left pointing at the last character of
// the constraint. In practice, it won't be changed unless the
@@ -658,24 +698,23 @@ public:
return std::string(1, *Constraint);
}
+ /// \brief Returns a string of target-specific clobbers, in LLVM format.
+ virtual const char *getClobbers() const = 0;
+
/// \brief Returns true if NaN encoding is IEEE 754-2008.
/// Only MIPS allows a different encoding.
virtual bool isNan2008() const {
return true;
}
- /// \brief Returns a string of target-specific clobbers, in LLVM format.
- virtual const char *getClobbers() const = 0;
-
-
/// \brief Returns the target triple of the primary target.
const llvm::Triple &getTriple() const {
return Triple;
}
- const char *getTargetDescription() const {
- assert(DescriptionString);
- return DescriptionString;
+ const char *getDataLayoutString() const {
+ assert(DataLayoutString && "Uninitialized DataLayoutString!");
+ return DataLayoutString;
}
struct GCCRegAlias {
@@ -721,10 +760,13 @@ public:
/// language options which change the target configuration.
virtual void adjust(const LangOptions &Opts);
- /// \brief Get the default set of target features for the CPU;
- /// this should include all legal feature strings on the target.
- virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const {
- }
+ /// \brief Initialize the map with the default set of target features for the
+ /// CPU this should include all legal feature strings on the target.
+ ///
+ /// \return False on error (invalid features).
+ virtual bool initFeatureMap(llvm::StringMap<bool> &Features,
+ DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeatureVec) const;
/// \brief Get the ABI currently in use.
virtual StringRef getABI() const { return StringRef(); }
@@ -755,23 +797,6 @@ public:
return false;
}
- /// \brief Use this specified C++ ABI.
- ///
- /// \return False on error (invalid C++ ABI name).
- bool setCXXABI(llvm::StringRef name) {
- TargetCXXABI ABI;
- if (!ABI.tryParse(name)) return false;
- return setCXXABI(ABI);
- }
-
- /// \brief Set the C++ ABI to be used by this implementation.
- ///
- /// \return False on error (ABI not valid on this target)
- virtual bool setCXXABI(TargetCXXABI ABI) {
- TheCXXABI = ABI;
- return true;
- }
-
/// \brief Enable or disable a specific target feature;
/// the feature name must be valid.
virtual void setFeatureEnabled(llvm::StringMap<bool> &Features,
@@ -787,6 +812,8 @@ public:
///
/// The target may modify the features list, to change which options are
/// passed onwards to the backend.
+ /// FIXME: This part should be fixed so that we can change handleTargetFeatures
+ /// to merely a TargetInfo initialization routine.
///
/// \return False on error.
virtual bool handleTargetFeatures(std::vector<std::string> &Features,
@@ -798,7 +825,11 @@ public:
virtual bool hasFeature(StringRef Feature) const {
return false;
}
-
+
+ // \brief Validate the contents of the __builtin_cpu_supports(const char*)
+ // argument.
+ virtual bool validateCpuSupports(StringRef Name) const { return false; }
+
// \brief Returns maximal number of args passed in registers.
unsigned getRegParmMax() const {
assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle");
@@ -882,7 +913,7 @@ public:
};
/// \brief Determines whether a given calling convention is valid for the
- /// target. A calling convention can either be accepted, produce a warning
+ /// target. A calling convention can either be accepted, produce a warning
/// and be substituted with the default calling convention, or (someday)
/// produce an error (such as using thiscall on a non-instance function).
virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
@@ -910,17 +941,11 @@ protected:
virtual enum IntType getPtrDiffTypeV(unsigned AddrSpace) const {
return PtrDiffType;
}
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const = 0;
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const = 0;
- virtual void getGCCAddlRegNames(const AddlRegName *&Addl,
- unsigned &NumAddl) const {
- Addl = nullptr;
- NumAddl = 0;
- }
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const= 0;
+ virtual ArrayRef<const char *> getGCCRegNames() const = 0;
+ virtual ArrayRef<GCCRegAlias> getGCCRegAliases() const = 0;
+ virtual ArrayRef<AddlRegName> getGCCAddlRegNames() const {
+ return None;
+ }
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
index 8333a4c..0269451 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
@@ -242,6 +242,8 @@ PUNCTUATOR(greatergreatergreater, ">>>")
// KEYZVECTOR - This is a keyword for the System z vector extensions,
// which are heavily based on AltiVec
// KEYBORLAND - This is a keyword if Borland extensions are enabled
+// KEYCOROUTINES - This is a keyword if support for the C++ coroutines
+// TS is enabled
// BOOLSUPPORT - This is a keyword if 'bool' is a built-in type
// HALFSUPPORT - This is a keyword if 'half' is a built-in type
// WCHARSUPPORT - This is a keyword if 'wchar_t' is a built-in type
@@ -282,7 +284,7 @@ KEYWORD(volatile , KEYALL)
KEYWORD(while , KEYALL)
KEYWORD(_Alignas , KEYALL)
KEYWORD(_Alignof , KEYALL)
-KEYWORD(_Atomic , KEYALL|KEYNOMS18|KEYNOOPENCL)
+KEYWORD(_Atomic , KEYALL|KEYNOOPENCL)
KEYWORD(_Bool , KEYNOCXX)
KEYWORD(_Complex , KEYALL)
KEYWORD(_Generic , KEYALL)
@@ -356,6 +358,11 @@ CXX11_KEYWORD(thread_local , 0)
CONCEPTS_KEYWORD(concept)
CONCEPTS_KEYWORD(requires)
+// C++ coroutines TS keywords
+KEYWORD(co_await , KEYCOROUTINES)
+KEYWORD(co_return , KEYCOROUTINES)
+KEYWORD(co_yield , KEYCOROUTINES)
+
// GNU Extensions (in impl-reserved namespace)
KEYWORD(_Decimal32 , KEYALL)
KEYWORD(_Decimal64 , KEYALL)
@@ -377,6 +384,7 @@ KEYWORD(__real , KEYALL)
KEYWORD(__thread , KEYALL)
KEYWORD(__FUNCTION__ , KEYALL)
KEYWORD(__PRETTY_FUNCTION__ , KEYALL)
+KEYWORD(__auto_type , KEYALL)
// GNU Extensions (outside impl-reserved namespace)
KEYWORD(typeof , KEYGNU)
@@ -469,8 +477,11 @@ KEYWORD(__array_extent , KEYCXX)
KEYWORD(__private_extern__ , KEYALL)
KEYWORD(__module_private__ , KEYALL)
+// Extension that will be enabled for Microsoft, Borland and PS4, but can be
+// disabled via '-fno-declspec'.
+KEYWORD(__declspec , 0)
+
// Microsoft Extension.
-KEYWORD(__declspec , KEYMS|KEYBORLAND)
KEYWORD(__cdecl , KEYALL)
KEYWORD(__stdcall , KEYALL)
KEYWORD(__fastcall , KEYALL)
@@ -508,6 +519,8 @@ KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC|KEYZVECTOR)
// OpenMP Type Traits
KEYWORD(__builtin_omp_required_simd_align, KEYALL)
+KEYWORD(pipe , KEYOPENCL)
+
// Borland Extensions.
KEYWORD(__pascal , KEYALL)
@@ -686,6 +699,11 @@ ANNOTATION(pragma_parser_crash)
// handles them.
ANNOTATION(pragma_captured)
+// Annotation for #pragma clang __debug dump...
+// The lexer produces these so that the parser and semantic analysis can
+// look up and dump the operand.
+ANNOTATION(pragma_dump)
+
// Annotation for #pragma ms_struct...
// The lexer produces these so that they only take effect when the parser
// handles them.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h b/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h
index 1c65fb5..bab88c9 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h
@@ -45,14 +45,18 @@ public:
public:
Status() : Type(llvm::sys::fs::file_type::status_error) {}
Status(const llvm::sys::fs::file_status &Status);
- Status(StringRef Name, StringRef RealName, llvm::sys::fs::UniqueID UID,
+ Status(StringRef Name, llvm::sys::fs::UniqueID UID,
llvm::sys::TimeValue MTime, uint32_t User, uint32_t Group,
uint64_t Size, llvm::sys::fs::file_type Type,
llvm::sys::fs::perms Perms);
+ /// Get a copy of a Status with a different name.
+ static Status copyWithNewName(const Status &In, StringRef NewName);
+ static Status copyWithNewName(const llvm::sys::fs::file_status &In,
+ StringRef NewName);
+
/// \brief Returns the name that should be used for this file or directory.
StringRef getName() const { return Name; }
- void setName(StringRef N) { Name = N; }
/// @name Status interface from llvm::sys::fs
/// @{
@@ -63,8 +67,6 @@ public:
uint32_t getUser() const { return User; }
uint32_t getGroup() const { return Group; }
uint64_t getSize() const { return Size; }
- void setType(llvm::sys::fs::file_type v) { Type = v; }
- void setPermissions(llvm::sys::fs::perms p) { Perms = p; }
/// @}
/// @name Status queries
/// These are static queries in llvm::sys::fs.
@@ -94,8 +96,6 @@ public:
bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
/// \brief Closes the file.
virtual std::error_code close() = 0;
- /// \brief Sets the name to use for this file.
- virtual void setName(StringRef Name) = 0;
};
namespace detail {
@@ -199,6 +199,28 @@ public:
/// \note The 'end' iterator is directory_iterator().
virtual directory_iterator dir_begin(const Twine &Dir,
std::error_code &EC) = 0;
+
+ /// Set the working directory. This will affect all following operations on
+ /// this file system and may propagate down for nested file systems.
+ virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0;
+ /// Get the working directory of this file system.
+ virtual llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const = 0;
+
+ /// Check whether a file exists. Provided for convenience.
+ bool exists(const Twine &Path);
+
+ /// Make \a Path an absolute path.
+ ///
+ /// Makes \a Path absolute using the current directory if it is not already.
+ /// An empty \a Path will result in the current directory.
+ ///
+ /// /absolute/path => /absolute/path
+ /// relative/../path => <current-directory>/relative/../path
+ ///
+ /// \param Path A path that is modified to be an absolute path.
+ /// \returns success if \a path has been made absolute, otherwise a
+ /// platform-specific error_code.
+ std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
};
/// \brief Gets an \p vfs::FileSystem for the 'real' file system, as seen by
@@ -230,6 +252,8 @@ public:
llvm::ErrorOr<std::unique_ptr<File>>
openFileForRead(const Twine &Path) override;
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
typedef FileSystemList::reverse_iterator iterator;
@@ -241,6 +265,43 @@ public:
iterator overlays_end() { return FSList.rend(); }
};
+namespace detail {
+class InMemoryDirectory;
+} // end namespace detail
+
+/// An in-memory file system.
+class InMemoryFileSystem : public FileSystem {
+ std::unique_ptr<detail::InMemoryDirectory> Root;
+ std::string WorkingDirectory;
+ bool UseNormalizedPaths = true;
+
+public:
+ explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
+ ~InMemoryFileSystem() override;
+ /// Add a buffer to the VFS with a path. The VFS owns the buffer.
+ /// \return true if the file was successfully added, false if the file already
+ /// exists in the file system with different contents.
+ bool addFile(const Twine &Path, time_t ModificationTime,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer);
+ /// Add a buffer to the VFS with a path. The VFS does not own the buffer.
+ /// \return true if the file was successfully added, false if the file already
+ /// exists in the file system with different contents.
+ bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
+ llvm::MemoryBuffer *Buffer);
+ std::string toString() const;
+ /// Return true if this file system normalizes . and .. in paths.
+ bool useNormalizedPaths() const { return UseNormalizedPaths; }
+
+ llvm::ErrorOr<Status> status(const Twine &Path) override;
+ llvm::ErrorOr<std::unique_ptr<File>>
+ openFileForRead(const Twine &Path) override;
+ directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+ return WorkingDirectory;
+ }
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
+};
+
/// \brief Get a globally unique ID for a virtual file or directory.
llvm::sys::fs::UniqueID getNextVirtualUniqueID();
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td
index c6f8795..6d95c1e 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td
@@ -373,6 +373,10 @@ def OP_QDMLSLHi_LN : Op<(call "vqdmlsl", $p0, (call "vget_high", $p1),
(splat $p2, $p3))>;
def OP_QDMULH_LN : Op<(call "vqdmulh", $p0, (splat $p1, $p2))>;
def OP_QRDMULH_LN : Op<(call "vqrdmulh", $p0, (splat $p1, $p2))>;
+def OP_QRDMLAH : Op<(call "vqadd", $p0, (call "vqrdmulh", $p1, $p2))>;
+def OP_QRDMLSH : Op<(call "vqsub", $p0, (call "vqrdmulh", $p1, $p2))>;
+def OP_QRDMLAH_LN : Op<(call "vqadd", $p0, (call "vqrdmulh", $p1, (splat $p2, $p3)))>;
+def OP_QRDMLSH_LN : Op<(call "vqsub", $p0, (call "vqrdmulh", $p1, (splat $p2, $p3)))>;
def OP_FMS_LN : Op<(call "vfma_lane", $p0, $p1, (op "-", $p2), $p3)>;
def OP_FMS_LNQ : Op<(call "vfma_laneq", $p0, $p1, (op "-", $p2), $p3)>;
def OP_TRN1 : Op<(shuffle $p0, $p1, (interleave (decimate mask0, 2),
@@ -414,7 +418,7 @@ def OP_XTN : Op<(call "vcombine", $p0, (call "vmovn", $p1))>;
def OP_SQXTUN : Op<(call "vcombine", (cast $p0, "U", $p0),
(call "vqmovun", $p1))>;
def OP_QXTN : Op<(call "vcombine", $p0, (call "vqmovn", $p1))>;
-def OP_VCVT_NA_HI_F16 : Op<(call "vcombine", $p0, (call "vcvt_f16", $p1))>;
+def OP_VCVT_NA_HI_F16 : Op<(call "vcombine", $p0, (call "vcvt_f16_f32", $p1))>;
def OP_VCVT_NA_HI_F32 : Op<(call "vcombine", $p0, (call "vcvt_f32_f64", $p1))>;
def OP_VCVT_EX_HI_F32 : Op<(call "vcvt_f32_f16", (call "vget_high", $p0))>;
def OP_VCVT_EX_HI_F64 : Op<(call "vcvt_f64_f32", (call "vget_high", $p0))>;
@@ -473,6 +477,11 @@ def OP_SCALAR_QDMULL_LN : ScalarMulOp<"vqdmull">;
def OP_SCALAR_QDMULH_LN : ScalarMulOp<"vqdmulh">;
def OP_SCALAR_QRDMULH_LN : ScalarMulOp<"vqrdmulh">;
+def OP_SCALAR_QRDMLAH_LN : Op<(call "vqadd", $p0, (call "vqrdmulh", $p1,
+ (call "vget_lane", $p2, $p3)))>;
+def OP_SCALAR_QRDMLSH_LN : Op<(call "vqsub", $p0, (call "vqrdmulh", $p1,
+ (call "vget_lane", $p2, $p3)))>;
+
def OP_SCALAR_HALF_GET_LN : Op<(bitcast "float16_t",
(call "vget_lane",
(bitcast "int16x4_t", $p0), $p1))>;
@@ -514,6 +523,12 @@ def VMLS : IOpInst<"vmls", "dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLS>;
def VMLSL : SOpInst<"vmlsl", "wwdd", "csiUcUsUi", OP_MLSL>;
def VQDMULH : SInst<"vqdmulh", "ddd", "siQsQi">;
def VQRDMULH : SInst<"vqrdmulh", "ddd", "siQsQi">;
+
+let ArchGuard = "defined(__ARM_FEATURE_QRDMX)" in {
+def VQRDMLAH : SOpInst<"vqrdmlah", "dddd", "siQsQi", OP_QRDMLAH>;
+def VQRDMLSH : SOpInst<"vqrdmlsh", "dddd", "siQsQi", OP_QRDMLSH>;
+}
+
def VQDMLAL : SInst<"vqdmlal", "wwdd", "si">;
def VQDMLSL : SInst<"vqdmlsl", "wwdd", "si">;
def VMULL : SInst<"vmull", "wdd", "csiUcUsUiPc">;
@@ -687,16 +702,19 @@ def VGET_LOW : NoTestOpInst<"vget_low", "dk", "csilhfUcUsUiUlPcPs", OP_LO>;
////////////////////////////////////////////////////////////////////////////////
// E.3.22 Converting vectors
+
+def VCVT_F16_F32 : SInst<"vcvt_f16_f32", "md", "Hf">;
+def VCVT_F32_F16 : SInst<"vcvt_f32_f16", "wd", "h">;
+
def VCVT_S32 : SInst<"vcvt_s32", "xd", "fQf">;
def VCVT_U32 : SInst<"vcvt_u32", "ud", "fQf">;
-def VCVT_F16 : SInst<"vcvt_f16", "hk", "f">;
def VCVT_F32 : SInst<"vcvt_f32", "fd", "iUiQiQUi">;
-def VCVT_F32_F16 : SInst<"vcvt_f32_f16", "fd", "h">;
let isVCVT_N = 1 in {
def VCVT_N_S32 : SInst<"vcvt_n_s32", "xdi", "fQf">;
def VCVT_N_U32 : SInst<"vcvt_n_u32", "udi", "fQf">;
def VCVT_N_F32 : SInst<"vcvt_n_f32", "fdi", "iUiQiQUi">;
}
+
def VMOVN : IInst<"vmovn", "hk", "silUsUiUl">;
def VMOVL : SInst<"vmovl", "wd", "csiUcUsUi">;
def VQMOVN : SInst<"vqmovn", "hk", "silUsUiUl">;
@@ -738,6 +756,12 @@ def VQDMULH_N : SInst<"vqdmulh_n", "dda", "siQsQi">;
def VQDMULH_LANE : SOpInst<"vqdmulh_lane", "ddgi", "siQsQi", OP_QDMULH_LN>;
def VQRDMULH_N : SInst<"vqrdmulh_n", "dda", "siQsQi">;
def VQRDMULH_LANE : SOpInst<"vqrdmulh_lane", "ddgi", "siQsQi", OP_QRDMULH_LN>;
+
+let ArchGuard = "defined(__ARM_FEATURE_QRDMX)" in {
+def VQRDMLAH_LANE : SOpInst<"vqrdmlah_lane", "dddgi", "siQsQi", OP_QRDMLAH_LN>;
+def VQRDMLSH_LANE : SOpInst<"vqrdmlsh_lane", "dddgi", "siQsQi", OP_QRDMLSH_LN>;
+}
+
def VMLA_N : IOpInst<"vmla_n", "ddda", "siUsUifQsQiQUsQUiQf", OP_MLA_N>;
def VMLAL_N : SOpInst<"vmlal_n", "wwda", "siUsUi", OP_MLAL_N>;
def VQDMLAL_N : SInst<"vqdmlal_n", "wwda", "si">;
@@ -923,6 +947,9 @@ def USQADD : SInst<"vsqadd", "ddd", "UcUsUiUlQUcQUsQUiQUl">;
// Reciprocal/Sqrt
def FRECPS : IInst<"vrecps", "ddd", "dQd">;
def FRSQRTS : IInst<"vrsqrts", "ddd", "dQd">;
+def FRECPE : SInst<"vrecpe", "dd", "dQd">;
+def FRSQRTE : SInst<"vrsqrte", "dd", "dQd">;
+def FSQRT : SInst<"vsqrt", "dd", "fdQfQd">;
////////////////////////////////////////////////////////////////////////////////
// bitwise reverse
@@ -942,20 +969,21 @@ def QXTN2 : SOpInst<"vqmovn_high", "qhk", "silUsUiUl", OP_QXTN>;
////////////////////////////////////////////////////////////////////////////////
// Converting vectors
-def VCVT_HIGH_F16 : SOpInst<"vcvt_high_f16", "qhj", "f", OP_VCVT_NA_HI_F16>;
-def VCVT_HIGH_F32_F16 : SOpInst<"vcvt_high_f32", "wk", "h", OP_VCVT_EX_HI_F32>;
+
def VCVT_F32_F64 : SInst<"vcvt_f32_f64", "md", "Qd">;
-def VCVT_HIGH_F32_F64 : SOpInst<"vcvt_high_f32", "qfj", "d", OP_VCVT_NA_HI_F32>;
def VCVT_F64_F32 : SInst<"vcvt_f64_f32", "wd", "f">;
+
+def VCVT_S64 : SInst<"vcvt_s64", "xd", "dQd">;
+def VCVT_U64 : SInst<"vcvt_u64", "ud", "dQd">;
def VCVT_F64 : SInst<"vcvt_f64", "Fd", "lUlQlQUl">;
+
+def VCVT_HIGH_F16_F32 : SOpInst<"vcvt_high_f16", "hmj", "Hf", OP_VCVT_NA_HI_F16>;
+def VCVT_HIGH_F32_F16 : SOpInst<"vcvt_high_f32", "wk", "h", OP_VCVT_EX_HI_F32>;
+def VCVT_HIGH_F32_F64 : SOpInst<"vcvt_high_f32", "qfj", "d", OP_VCVT_NA_HI_F32>;
def VCVT_HIGH_F64_F32 : SOpInst<"vcvt_high_f64", "wj", "f", OP_VCVT_EX_HI_F64>;
-def VCVTX_F32_F64 : SInst<"vcvtx_f32", "fj", "d">;
+
+def VCVTX_F32_F64 : SInst<"vcvtx_f32", "fj", "d">;
def VCVTX_HIGH_F32_F64 : SOpInst<"vcvtx_high_f32", "qfj", "d", OP_VCVTX_HI>;
-def VCVT_S64 : SInst<"vcvt_s64", "xd", "dQd">;
-def VCVT_U64 : SInst<"vcvt_u64", "ud", "dQd">;
-def FRECPE : SInst<"vrecpe", "dd", "dQd">;
-def FRSQRTE : SInst<"vrsqrte", "dd", "dQd">;
-def FSQRT : SInst<"vsqrt", "dd", "fdQfQd">;
////////////////////////////////////////////////////////////////////////////////
// Comparison
@@ -1153,6 +1181,11 @@ def VQDMULL_HIGH_LANEQ : SOpInst<"vqdmull_high_laneq", "wkki", "si",
def VQDMULH_LANEQ : SOpInst<"vqdmulh_laneq", "ddji", "siQsQi", OP_QDMULH_LN>;
def VQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ddji", "siQsQi", OP_QRDMULH_LN>;
+let ArchGuard = "defined(__ARM_FEATURE_QRDMX) && defined(__aarch64__)" in {
+def VQRDMLAH_LANEQ : SOpInst<"vqrdmlah_laneq", "dddji", "siQsQi", OP_QRDMLAH_LN>;
+def VQRDMLSH_LANEQ : SOpInst<"vqrdmlsh_laneq", "dddji", "siQsQi", OP_QRDMLSH_LN>;
+}
+
// Note: d type implemented by SCALAR_VMULX_LANE
def VMULX_LANE : IOpInst<"vmulx_lane", "ddgi", "fQfQd", OP_MULX_LN>;
// Note: d type is implemented by SCALAR_VMULX_LANEQ
@@ -1398,6 +1431,16 @@ def SCALAR_SQDMULH : SInst<"vqdmulh", "sss", "SsSi">;
// Scalar Integer Saturating Rounding Doubling Multiply Half High
def SCALAR_SQRDMULH : SInst<"vqrdmulh", "sss", "SsSi">;
+let ArchGuard = "defined(__ARM_FEATURE_QRDMX) && defined(__aarch64__)" in {
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Rounding Doubling Multiply Accumulate Returning High Half
+def SCALAR_SQRDMLAH : SOpInst<"vqrdmlah", "ssss", "SsSi", OP_QRDMLAH>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Rounding Doubling Multiply Subtract Returning High Half
+def SCALAR_SQRDMLSH : SOpInst<"vqrdmlsh", "ssss", "SsSi", OP_QRDMLSH>;
+}
+
////////////////////////////////////////////////////////////////////////////////
// Scalar Floating-point Multiply Extended
def SCALAR_FMULX : IInst<"vmulx", "sss", "SfSd">;
@@ -1599,6 +1642,16 @@ def SCALAR_SQDMULH_LANEQ : SOpInst<"vqdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QD
def SCALAR_SQRDMULH_LANE : SOpInst<"vqrdmulh_lane", "ssdi", "SsSi", OP_SCALAR_QRDMULH_LN>;
def SCALAR_SQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QRDMULH_LN>;
+let ArchGuard = "defined(__ARM_FEATURE_QRDMX) && defined(__aarch64__)" in {
+// Signed Saturating Rounding Doubling Multiply Accumulate Returning High Half
+def SCALAR_SQRDMLAH_LANE : SOpInst<"vqrdmlah_lane", "sssdi", "SsSi", OP_SCALAR_QRDMLAH_LN>;
+def SCALAR_SQRDMLAH_LANEQ : SOpInst<"vqrdmlah_laneq", "sssji", "SsSi", OP_SCALAR_QRDMLAH_LN>;
+
+// Signed Saturating Rounding Doubling Multiply Subtract Returning High Half
+def SCALAR_SQRDMLSH_LANE : SOpInst<"vqrdmlsh_lane", "sssdi", "SsSi", OP_SCALAR_QRDMLSH_LN>;
+def SCALAR_SQRDMLSH_LANEQ : SOpInst<"vqrdmlsh_laneq", "sssji", "SsSi", OP_SCALAR_QRDMLSH_LN>;
+}
+
def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
}
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h b/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h
index 8586e77..d375a78 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h
@@ -11,6 +11,8 @@
#define LLVM_CLANG_CODEGEN_BACKENDUTIL_H
#include "clang/Basic/LLVM.h"
+#include "llvm/IR/FunctionInfo.h"
+#include <memory>
namespace llvm {
class Module;
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h
index e32fb14..bb6ceb4 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -17,6 +17,7 @@
#define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
#include "clang/AST/CanonicalType.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/FoldingSet.h"
#include <cassert>
@@ -126,7 +127,7 @@ public:
static ABIArgInfo getIgnore() {
return ABIArgInfo(Ignore);
}
- static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true,
+ static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true,
bool Realign = false,
llvm::Type *Padding = nullptr) {
auto AI = ABIArgInfo(Indirect);
@@ -137,7 +138,7 @@ public:
AI.setPaddingType(Padding);
return AI;
}
- static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true,
+ static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
bool Realign = false) {
auto AI = getIndirect(Alignment, ByVal, Realign);
AI.setInReg(true);
@@ -211,20 +212,20 @@ public:
}
// Indirect accessors
- unsigned getIndirectAlign() const {
+ CharUnits getIndirectAlign() const {
assert(isIndirect() && "Invalid kind!");
- return IndirectAlign;
+ return CharUnits::fromQuantity(IndirectAlign);
}
- void setIndirectAlign(unsigned IA) {
+ void setIndirectAlign(CharUnits IA) {
assert(isIndirect() && "Invalid kind!");
- IndirectAlign = IA;
+ IndirectAlign = IA.getQuantity();
}
bool getIndirectByVal() const {
assert(isIndirect() && "Invalid kind!");
return IndirectByVal;
}
- void setIndirectByVal(unsigned IBV) {
+ void setIndirectByVal(bool IBV) {
assert(isIndirect() && "Invalid kind!");
IndirectByVal = IBV;
}
@@ -370,6 +371,7 @@ class CGFunctionInfo : public llvm::FoldingSetNode {
/// The struct representing all arguments passed in memory. Only used when
/// passing non-trivial types with inalloca. Not part of the profile.
llvm::StructType *ArgStruct;
+ unsigned ArgStructAlign;
unsigned NumArgs;
ArgInfo *getArgsBuffer() {
@@ -463,7 +465,13 @@ public:
/// \brief Get the struct type used to represent all the arguments in memory.
llvm::StructType *getArgStruct() const { return ArgStruct; }
- void setArgStruct(llvm::StructType *Ty) { ArgStruct = Ty; }
+ CharUnits getArgStructAlignment() const {
+ return CharUnits::fromQuantity(ArgStructAlign);
+ }
+ void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
+ ArgStruct = Ty;
+ ArgStructAlign = Align.getQuantity();
+ }
void Profile(llvm::FoldingSetNodeID &ID) {
ID.AddInteger(getASTCallingConvention());
@@ -501,6 +509,29 @@ public:
}
};
+/// CGCalleeInfo - Class to encapsulate the information about a callee to be
+/// used during the generation of call/invoke instructions.
+class CGCalleeInfo {
+ /// \brief The function proto type of the callee.
+ const FunctionProtoType *CalleeProtoTy;
+ /// \brief The function declaration of the callee.
+ const Decl *CalleeDecl;
+
+public:
+ explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl(nullptr) {}
+ CGCalleeInfo(const FunctionProtoType *calleeProtoTy, const Decl *calleeDecl)
+ : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
+ CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
+ : CalleeProtoTy(calleeProtoTy), CalleeDecl(nullptr) {}
+ CGCalleeInfo(const Decl *calleeDecl)
+ : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
+
+ const FunctionProtoType *getCalleeFunctionProtoType() {
+ return CalleeProtoTy;
+ }
+ const Decl *getCalleeDecl() { return CalleeDecl; }
+};
+
} // end namespace CodeGen
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h
index 4e76cd4..9d9504a 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h
@@ -36,6 +36,7 @@ namespace llvm {
namespace clang {
class ASTContext;
class CXXRecordDecl;
+class CXXMethodDecl;
class CodeGenOptions;
class CoverageSourceInfo;
class DiagnosticsEngine;
@@ -50,7 +51,7 @@ class CodeGenModule;
class CodeGenABITypes
{
public:
- CodeGenABITypes(ASTContext &C, llvm::Module &M, const llvm::DataLayout &TD,
+ CodeGenABITypes(ASTContext &C, llvm::Module &M,
CoverageSourceInfo *CoverageInfo = nullptr);
~CodeGenABITypes();
@@ -60,12 +61,13 @@ public:
const CGFunctionInfo &arrangeObjCMessageSendSignature(
const ObjCMethodDecl *MD,
QualType receiverType);
- const CGFunctionInfo &arrangeFreeFunctionType(
- CanQual<FunctionProtoType> Ty);
+ const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty,
+ const FunctionDecl *FD);
const CGFunctionInfo &arrangeFreeFunctionType(
CanQual<FunctionNoProtoType> Ty);
const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD,
- const FunctionProtoType *FTP);
+ const FunctionProtoType *FTP,
+ const CXXMethodDecl *MD);
const CGFunctionInfo &arrangeFreeFunctionCall(CanQualType returnType,
ArrayRef<CanQualType> argTypes,
FunctionType::ExtInfo info,
@@ -75,12 +77,12 @@ private:
/// Default CodeGenOptions object used to initialize the
/// CodeGenModule and otherwise not used. More specifically, it is
/// not used in ABI type generation, so none of the options matter.
- CodeGenOptions *CGO;
- HeaderSearchOptions *HSO;
- PreprocessorOptions *PPO;
+ std::unique_ptr<CodeGenOptions> CGO;
+ std::unique_ptr<HeaderSearchOptions> HSO;
+ std::unique_ptr<PreprocessorOptions> PPO;
/// The CodeGenModule we use get to the CodeGenTypes object.
- CodeGen::CodeGenModule *CGM;
+ std::unique_ptr<CodeGen::CodeGenModule> CGM;
};
} // end namespace CodeGen
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h
index 264780d..cc38e24 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h
@@ -25,7 +25,9 @@ class CodeGenAction : public ASTFrontendAction {
private:
unsigned Act;
std::unique_ptr<llvm::Module> TheModule;
- llvm::Module *LinkModule;
+ // Vector of {Linker::Flags, Module*} pairs to specify bitcode
+ // modules to link in using corresponding linker flags.
+ SmallVector<std::pair<unsigned, llvm::Module *>, 4> LinkModules;
llvm::LLVMContext *VMContext;
bool OwnsVMContext;
@@ -50,7 +52,9 @@ public:
/// setLinkModule - Set the link module to be used by this action. If a link
/// module is not provided, and CodeGenOptions::LinkBitcodeFile is non-empty,
/// the action will load it from the specified file.
- void setLinkModule(llvm::Module *Mod) { LinkModule = Mod; }
+ void addLinkModule(llvm::Module *Mod, unsigned LinkFlags) {
+ LinkModules.push_back(std::make_pair(LinkFlags, Mod));
+ }
/// Take the generated LLVM module, for use after the action has been run.
/// The result may be null on failure.
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h b/contrib/llvm/tools/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
index e82aab7..15132ac 100644
--- a/contrib/llvm/tools/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
@@ -23,9 +23,7 @@ class ObjectFilePCHContainerWriter : public PCHContainerWriter {
/// PCHGenerator that produces a wrapper file format
/// that also contains full debug info for the module.
std::unique_ptr<ASTConsumer> CreatePCHContainerGenerator(
- DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO,
- const PreprocessorOptions &PPO, const TargetOptions &TO,
- const LangOptions &LO, const std::string &MainFileName,
+ CompilerInstance &CI, const std::string &MainFileName,
const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
std::shared_ptr<PCHBuffer> Buffer) const override;
};
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Action.h b/contrib/llvm/tools/clang/include/clang/Driver/Action.h
index fddd158..c5b0f47 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Action.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Action.h
@@ -15,6 +15,9 @@
#include "llvm/ADT/SmallVector.h"
namespace llvm {
+
+class StringRef;
+
namespace opt {
class Arg;
}
@@ -32,6 +35,9 @@ namespace driver {
/// single primary output, at least in terms of controlling the
/// compilation. Actions can produce auxiliary files, but can only
/// produce a single output to feed into subsequent actions.
+///
+/// Actions are usually owned by a Compilation, which creates new
+/// actions via MakeAction().
class Action {
public:
typedef ActionList::size_type size_type;
@@ -70,27 +76,20 @@ private:
ActionList Inputs;
- unsigned OwnsInputs : 1;
-
protected:
- Action(ActionClass Kind, types::ID Type)
- : Kind(Kind), Type(Type), OwnsInputs(true) {}
- Action(ActionClass Kind, std::unique_ptr<Action> Input, types::ID Type)
- : Kind(Kind), Type(Type), Inputs(1, Input.release()), OwnsInputs(true) {
- }
- Action(ActionClass Kind, std::unique_ptr<Action> Input)
- : Kind(Kind), Type(Input->getType()), Inputs(1, Input.release()),
- OwnsInputs(true) {}
+ Action(ActionClass Kind, types::ID Type) : Action(Kind, ActionList(), Type) {}
+ Action(ActionClass Kind, Action *Input, types::ID Type)
+ : Action(Kind, ActionList({Input}), Type) {}
+ Action(ActionClass Kind, Action *Input)
+ : Action(Kind, ActionList({Input}), Input->getType()) {}
Action(ActionClass Kind, const ActionList &Inputs, types::ID Type)
- : Kind(Kind), Type(Type), Inputs(Inputs), OwnsInputs(true) {}
+ : Kind(Kind), Type(Type), Inputs(Inputs) {}
+
public:
virtual ~Action();
const char *getClassName() const { return Action::getClassName(getKind()); }
- bool getOwnsInputs() { return OwnsInputs; }
- void setOwnsInputs(bool Value) { OwnsInputs = Value; }
-
ActionClass getKind() const { return Kind; }
types::ID getType() const { return Type; }
@@ -126,7 +125,7 @@ class BindArchAction : public Action {
const char *ArchName;
public:
- BindArchAction(std::unique_ptr<Action> Input, const char *ArchName);
+ BindArchAction(Action *Input, const char *ArchName);
const char *getArchName() const { return ArchName; }
@@ -137,19 +136,24 @@ public:
class CudaDeviceAction : public Action {
virtual void anchor();
- /// GPU architecture to bind -- e.g 'sm_35'.
+ /// GPU architecture to bind. Always of the form /sm_\d+/.
const char *GpuArchName;
/// True when action results are not consumed by the host action (e.g when
/// -fsyntax-only or --cuda-device-only options are used).
bool AtTopLevel;
public:
- CudaDeviceAction(std::unique_ptr<Action> Input, const char *ArchName,
- bool AtTopLevel);
+ CudaDeviceAction(Action *Input, const char *ArchName, bool AtTopLevel);
const char *getGpuArchName() const { return GpuArchName; }
+
+ /// Gets the compute_XX that corresponds to getGpuArchName().
+ const char *getComputeArchName() const;
+
bool isAtTopLevel() const { return AtTopLevel; }
+ static bool IsValidGpuArchName(llvm::StringRef ArchName);
+
static bool classof(const Action *A) {
return A->getKind() == CudaDeviceClass;
}
@@ -160,11 +164,8 @@ class CudaHostAction : public Action {
ActionList DeviceActions;
public:
- CudaHostAction(std::unique_ptr<Action> Input,
- const ActionList &DeviceActions);
- ~CudaHostAction() override;
+ CudaHostAction(Action *Input, const ActionList &DeviceActions);
- ActionList &getDeviceActions() { return DeviceActions; }
const ActionList &getDeviceActions() const { return DeviceActions; }
static bool classof(const Action *A) { return A->getKind() == CudaHostClass; }
@@ -173,7 +174,7 @@ public:
class JobAction : public Action {
virtual void anchor();
protected:
- JobAction(ActionClass Kind, std::unique_ptr<Action> Input, types::ID Type);
+ JobAction(ActionClass Kind, Action *Input, types::ID Type);
JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type);
public:
@@ -186,7 +187,7 @@ public:
class PreprocessJobAction : public JobAction {
void anchor() override;
public:
- PreprocessJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+ PreprocessJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) {
return A->getKind() == PreprocessJobClass;
@@ -196,7 +197,7 @@ public:
class PrecompileJobAction : public JobAction {
void anchor() override;
public:
- PrecompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+ PrecompileJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) {
return A->getKind() == PrecompileJobClass;
@@ -206,7 +207,7 @@ public:
class AnalyzeJobAction : public JobAction {
void anchor() override;
public:
- AnalyzeJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+ AnalyzeJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) {
return A->getKind() == AnalyzeJobClass;
@@ -216,7 +217,7 @@ public:
class MigrateJobAction : public JobAction {
void anchor() override;
public:
- MigrateJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+ MigrateJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) {
return A->getKind() == MigrateJobClass;
@@ -226,7 +227,7 @@ public:
class CompileJobAction : public JobAction {
void anchor() override;
public:
- CompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+ CompileJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) {
return A->getKind() == CompileJobClass;
@@ -236,7 +237,7 @@ public:
class BackendJobAction : public JobAction {
void anchor() override;
public:
- BackendJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+ BackendJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) {
return A->getKind() == BackendJobClass;
@@ -246,7 +247,7 @@ public:
class AssembleJobAction : public JobAction {
void anchor() override;
public:
- AssembleJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+ AssembleJobAction(Action *Input, types::ID OutputType);
static bool classof(const Action *A) {
return A->getKind() == AssembleJobClass;
@@ -286,9 +287,7 @@ public:
class VerifyJobAction : public JobAction {
void anchor() override;
public:
- VerifyJobAction(ActionClass Kind, std::unique_ptr<Action> Input,
- types::ID Type);
- VerifyJobAction(ActionClass Kind, ActionList &Inputs, types::ID Type);
+ VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type);
static bool classof(const Action *A) {
return A->getKind() == VerifyDebugInfoJobClass ||
A->getKind() == VerifyPCHJobClass;
@@ -298,7 +297,7 @@ public:
class VerifyDebugInfoJobAction : public VerifyJobAction {
void anchor() override;
public:
- VerifyDebugInfoJobAction(std::unique_ptr<Action> Input, types::ID Type);
+ VerifyDebugInfoJobAction(Action *Input, types::ID Type);
static bool classof(const Action *A) {
return A->getKind() == VerifyDebugInfoJobClass;
}
@@ -307,7 +306,7 @@ public:
class VerifyPCHJobAction : public VerifyJobAction {
void anchor() override;
public:
- VerifyPCHJobAction(std::unique_ptr<Action> Input, types::ID Type);
+ VerifyPCHJobAction(Action *Input, types::ID Type);
static bool classof(const Action *A) {
return A->getKind() == VerifyPCHJobClass;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
index d2f0d05..051f903 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
@@ -132,6 +132,9 @@ def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">,
let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
+def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">;
+def dwarf_version_EQ : Joined<["-"], "dwarf-version=">;
+def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">;
def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">,
HelpText<"The compilation directory to embed in the debug info.">;
def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">,
@@ -146,13 +149,17 @@ def msave_temp_labels : Flag<["-"], "msave-temp-labels">,
HelpText<"Save temporary labels in the symbol table. "
"Note this may change .s semantics and shouldn't generally be used "
"on compiler-generated code.">;
-
+def mrelocation_model : Separate<["-"], "mrelocation-model">,
+ HelpText<"The relocation model to use">;
}
def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">,
HelpText<"Don't run LLVM optimization passes">;
def disable_llvm_verifier : Flag<["-"], "disable-llvm-verifier">,
HelpText<"Don't run the LLVM IR verifier pass">;
+def disable_llvm_passes : Flag<["-"], "disable-llvm-passes">,
+ HelpText<"Use together with -emit-llvm to get pristine LLVM IR from the "
+ "frontend by not running any LLVM passes at all">;
def disable_red_zone : Flag<["-"], "disable-red-zone">,
HelpText<"Do not emit code that uses the red zone.">;
def dwarf_column_info : Flag<["-"], "dwarf-column-info">,
@@ -163,6 +170,9 @@ def gnu_pubnames : Flag<["-"], "gnu-pubnames">,
HelpText<"Emit newer GNU style pubnames">;
def arange_sections : Flag<["-"], "arange_sections">,
HelpText<"Emit DWARF .debug_arange sections">;
+def dwarf_ext_refs : Flag<["-"], "dwarf-ext-refs">,
+ HelpText<"Generate debug info with external references to clang modules"
+ " or precompiled headers">;
def fforbid_guard_variables : Flag<["-"], "fforbid-guard-variables">,
HelpText<"Emit an error if a C++ static local initializer would need a guard variable">;
def no_implicit_float : Flag<["-"], "no-implicit-float">,
@@ -225,14 +235,15 @@ def backend_option : Separate<["-"], "backend-option">,
HelpText<"Additional arguments to forward to LLVM backend (during code gen)">;
def mregparm : Separate<["-"], "mregparm">,
HelpText<"Limit the number of registers available for integer arguments">;
-def mrelocation_model : Separate<["-"], "mrelocation-model">,
- HelpText<"The relocation model to use">;
def munwind_tables : Flag<["-"], "munwind-tables">,
HelpText<"Generate unwinding tables for all functions">;
def mconstructor_aliases : Flag<["-"], "mconstructor-aliases">,
HelpText<"Emit complete constructors and destructors as aliases when possible">;
def mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">,
HelpText<"Link the given bitcode file before performing optimizations.">;
+def mlink_cuda_bitcode : Separate<["-"], "mlink-cuda-bitcode">,
+ HelpText<"Link and internalize needed symbols from the given bitcode file "
+ "before performing optimizations.">;
def vectorize_loops : Flag<["-"], "vectorize-loops">,
HelpText<"Run the Loop vectorization passes">;
def vectorize_slp : Flag<["-"], "vectorize-slp">,
@@ -320,6 +331,8 @@ def cc1as : Flag<["-"], "cc1as">;
def ast_merge : Separate<["-"], "ast-merge">,
MetaVarName<"<ast file>">,
HelpText<"Merge the given AST file into the translation unit being compiled.">;
+def aux_triple : Separate<["-"], "aux-triple">,
+ HelpText<"Auxiliary target triple.">;
def code_completion_at : Separate<["-"], "code-completion-at">,
MetaVarName<"<file>:<line>:<column>">,
HelpText<"Dump code-completion information at a location">;
@@ -365,6 +378,13 @@ def fmodule_map_file_home_is_cwd : Flag<["-"], "fmodule-map-file-home-is-cwd">,
def fmodule_feature : Separate<["-"], "fmodule-feature">,
MetaVarName<"<feature>">,
HelpText<"Enable <feature> in module map requires declarations">;
+def fmodules_embed_file_EQ : Joined<["-"], "fmodules-embed-file=">,
+ MetaVarName<"<file>">,
+ HelpText<"Embed the contents of the specified file into the module file "
+ "being compiled.">;
+def fmodules_embed_all_files : Joined<["-"], "fmodules-embed-all-files">,
+ HelpText<"Embed the contents of all files read by this compilation into "
+ "the produced module file.">;
def fmodules_local_submodule_visibility :
Flag<["-"], "fmodules-local-submodule-visibility">,
HelpText<"Enforce name visibility rules across submodules of the same "
@@ -372,10 +392,10 @@ def fmodules_local_submodule_visibility :
def fmodule_format_EQ : Joined<["-"], "fmodule-format=">,
HelpText<"Select the container format for clang modules and PCH. "
"Supported options are 'raw' and 'obj'.">;
-def fno_modules_hide_internal_linkage :
- Flag<["-"], "fno-modules-hide-internal-linkage">,
- HelpText<"Make all declarations visible to redeclaration lookup, "
- "even if they have internal linkage.">;
+def ftest_module_file_extension_EQ :
+ Joined<["-"], "ftest-module-file-extension=">,
+ HelpText<"introduce a module file extension for testing purposes. "
+ "The argument is parsed as blockname:major:minor:hashed:user info">;
def fconcepts_ts : Flag<["-"], "fconcepts-ts">,
HelpText<"Enable C++ Extensions for Concepts.">;
@@ -483,6 +503,8 @@ def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">,
HelpText<"Weakly link in the blocks runtime">;
def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">,
HelpText<"Use SjLj style exceptions">;
+def fnew_ms_eh: Flag<["-"], "fnew-ms-eh">,
+ HelpText<"Use the new IR representation for MS exceptions">;
def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
HelpText<"File name to use for split dwarf debug info output">;
def fno_wchar : Flag<["-"], "fno-wchar">,
@@ -565,6 +587,10 @@ def fnative_half_type: Flag<["-"], "fnative-half-type">,
def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">,
HelpText<"Allow function arguments and returns of type half">;
+// C++ TSes.
+def fcoroutines : Flag<["-"], "fcoroutines">,
+ HelpText<"Enable support for the C++ Coroutines TS">;
+
//===----------------------------------------------------------------------===//
// Header Search Options
//===----------------------------------------------------------------------===//
@@ -648,7 +674,18 @@ def fcuda_disable_target_call_checks : Flag<["-"],
HelpText<"Disable all cross-target (host, device, etc.) call checks in CUDA">;
def fcuda_include_gpubinary : Separate<["-"], "fcuda-include-gpubinary">,
HelpText<"Incorporate CUDA device-side binary into host object file.">;
+def fcuda_target_overloads : Flag<["-"], "fcuda-target-overloads">,
+ HelpText<"Enable function overloads based on CUDA target attributes.">;
+//===----------------------------------------------------------------------===//
+// OpenMP Options
+//===----------------------------------------------------------------------===//
+
+def fopenmp_is_device : Flag<["-"], "fopenmp-is-device">,
+ HelpText<"Generate code only for an OpenMP target device.">;
+def omp_host_ir_file_path : Separate<["-"], "omp-host-ir-file-path">,
+ HelpText<"Path to the IR file produced by the frontend for the host.">;
+
} // let Flags = [CC1Option]
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td b/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td
index 907b16f..16a5b72 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td
@@ -52,6 +52,12 @@ class CLRemainingArgs<string name> : Option<["/", "-"], name,
// (We don't put any of these in cl_compile_Group as the options they alias are
// already in the right group.)
+def _SLASH_Brepro : CLFlag<"Brepro">,
+ HelpText<"Emit an object file which can be reproduced over time">,
+ Alias<mincremental_linker_compatible>;
+def _SLASH_Brepro_ : CLFlag<"Brepro-">,
+ HelpText<"Emit an object file which cannot be reproduced over time">,
+ Alias<mno_incremental_linker_compatible>;
def _SLASH_C : CLFlag<"C">,
HelpText<"Don't discard comments when preprocessing">, Alias<C>;
def _SLASH_c : CLFlag<"c">, HelpText<"Compile only">, Alias<c>;
@@ -92,8 +98,7 @@ def _SLASH_I : CLJoinedOrSeparate<"I">,
def _SLASH_J : CLFlag<"J">, HelpText<"Make char type unsigned">,
Alias<funsigned_char>;
def _SLASH_O0 : CLFlag<"O0">, Alias<O0>;
-def _SLASH_O : CLJoined<"O">, HelpText<"Optimization level">,
- MetaVarName<"<n>">, Alias<O>;
+def _SLASH_O : CLJoined<"O">, HelpText<"Optimization level">;
def _SLASH_Ob0 : CLFlag<"Ob0">, HelpText<"Disable inlining">,
Alias<fno_inline>;
def _SLASH_Od : CLFlag<"Od">, HelpText<"Disable optimization">, Alias<O0>;
@@ -105,12 +110,6 @@ def _SLASH_Os : CLFlag<"Os">, HelpText<"Optimize for size">, Alias<O>,
AliasArgs<["s"]>;
def _SLASH_Ot : CLFlag<"Ot">, HelpText<"Optimize for speed">, Alias<O>,
AliasArgs<["2"]>;
-def _SLASH_Ox : CLFlag<"Ox">, HelpText<"Maximum optimization">, Alias<O>,
- AliasArgs<["3"]>;
-def _SLASH_Oy : CLFlag<"Oy">, HelpText<"Enable frame pointer omission">,
- Alias<fomit_frame_pointer>;
-def _SLASH_Oy_ : CLFlag<"Oy-">, HelpText<"Disable frame pointer omission">,
- Alias<fno_omit_frame_pointer>;
def _SLASH_QUESTION : CLFlag<"?">, Alias<help>,
HelpText<"Display available options">;
def _SLASH_Qvec : CLFlag<"Qvec">,
@@ -126,8 +125,8 @@ def _SLASH_W0 : CLFlag<"W0">, HelpText<"Disable all warnings">, Alias<w>;
def _SLASH_W1 : CLFlag<"W1">, HelpText<"Enable -Wall">, Alias<Wall>;
def _SLASH_W2 : CLFlag<"W2">, HelpText<"Enable -Wall">, Alias<Wall>;
def _SLASH_W3 : CLFlag<"W3">, HelpText<"Enable -Wall">, Alias<Wall>;
-def _SLASH_W4 : CLFlag<"W4">, HelpText<"Enable -Wall">, Alias<Wall>;
-def _SLASH_Wall : CLFlag<"Wall">, HelpText<"Enable -Wall">, Alias<Wall>;
+def _SLASH_W4 : CLFlag<"W4">, HelpText<"Enable -Wall and -Wextra">, Alias<WCL4>;
+def _SLASH_Wall : CLFlag<"Wall">, HelpText<"Enable -Wall and -Wextra">, Alias<WCL4>;
def _SLASH_WX : CLFlag<"WX">, HelpText<"Treat warnings as errors">,
Alias<W_Joined>, AliasArgs<["error"]>;
def _SLASH_WX_ : CLFlag<"WX-">, HelpText<"Do not treat warnings as errors">,
@@ -135,10 +134,12 @@ def _SLASH_WX_ : CLFlag<"WX-">, HelpText<"Do not treat warnings as errors">,
def _SLASH_w_flag : CLFlag<"w">, HelpText<"Disable all warnings">, Alias<w>;
def _SLASH_wd4005 : CLFlag<"wd4005">, Alias<W_Joined>,
AliasArgs<["no-macro-redefined"]>;
-def _SLASH_wd4996 : CLFlag<"wd4996">, Alias<W_Joined>,
- AliasArgs<["no-deprecated-declarations"]>;
+def _SLASH_wd4100 : CLFlag<"wd4100">, Alias<W_Joined>,
+ AliasArgs<["no-unused-parameter"]>;
def _SLASH_wd4910 : CLFlag<"wd4910">, Alias<W_Joined>,
AliasArgs<["no-dllexport-explicit-instantiation-decl"]>;
+def _SLASH_wd4996 : CLFlag<"wd4996">, Alias<W_Joined>,
+ AliasArgs<["no-deprecated-declarations"]>;
def _SLASH_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">,
Alias<vtordisp_mode_EQ>;
def _SLASH_Zc_sizedDealloc : CLFlag<"Zc:sizedDealloc">,
@@ -160,9 +161,10 @@ def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">,
HelpText<"Enable trigraphs">, Alias<ftrigraphs>;
def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">,
HelpText<"Disable trigraphs (default)">, Alias<fno_trigraphs>;
-def _SLASH_Z7 : CLFlag<"Z7">, Alias<gline_tables_only>;
-def _SLASH_Zi : CLFlag<"Zi">, HelpText<"Enable debug information">,
- Alias<gline_tables_only>;
+def _SLASH_Z7 : CLFlag<"Z7">,
+ HelpText<"Enable CodeView debug information in object files">;
+def _SLASH_Zi : CLFlag<"Zi">, Alias<_SLASH_Z7>,
+ HelpText<"Alias for /Z7. Does not produce PDBs.">;
def _SLASH_Zp : CLJoined<"Zp">,
HelpText<"Specify the default maximum struct packing alignment">,
Alias<fpack_struct_EQ>;
@@ -243,10 +245,13 @@ def _SLASH_vmv : CLFlag<"vmv">,
def _SLASH_volatile_ms : Option<["/", "-"], "volatile:ms", KIND_FLAG>,
Group<_SLASH_volatile_Group>, Flags<[CLOption, DriverOption]>,
HelpText<"Volatile loads and stores have acquire and release semantics">;
+def _SLASH_Zl : CLFlag<"Zl">,
+ HelpText<"Don't mention any default libraries in the object file">;
// Ignored:
def _SLASH_analyze_ : CLIgnoredFlag<"analyze-">;
+def _SLASH_bigobj : CLIgnoredFlag<"bigobj">;
def _SLASH_cgthreads : CLIgnoredJoined<"cgthreads">;
def _SLASH_d2Zi_PLUS : CLIgnoredFlag<"d2Zi+">;
def _SLASH_errorReport : CLIgnoredJoined<"errorReport">;
@@ -259,6 +264,7 @@ def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">;
def _SLASH_nologo : CLIgnoredFlag<"nologo">;
def _SLASH_Ob1 : CLIgnoredFlag<"Ob1">;
def _SLASH_Ob2 : CLIgnoredFlag<"Ob2">;
+def _SLASH_Og : CLIgnoredFlag<"Og">;
def _SLASH_openmp_ : CLIgnoredFlag<"openmp-">;
def _SLASH_RTC : CLIgnoredJoined<"RTC">;
def _SLASH_sdl : CLIgnoredFlag<"sdl">;
@@ -277,7 +283,6 @@ def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">;
// Unsupported:
def _SLASH_AI : CLJoined<"AI">;
-def _SLASH_bigobj : CLFlag<"bigobj">;
def _SLASH_clr : CLJoined<"clr">;
def _SLASH_doc : CLJoined<"doc">;
def _SLASH_FA_joined : CLJoined<"FA">;
@@ -302,6 +307,7 @@ def _SLASH_Gm_ : CLFlag<"Gm-">;
def _SLASH_Gr : CLFlag<"Gr">;
def _SLASH_GS : CLFlag<"GS">;
def _SLASH_GT : CLFlag<"GT">;
+def _SLASH_Guard : CLJoined<"guard:">;
def _SLASH_GX : CLFlag<"GX">;
def _SLASH_Gv : CLFlag<"Gv">;
def _SLASH_Gz : CLFlag<"Gz">;
@@ -333,5 +339,4 @@ def _SLASH_Zc : CLJoined<"Zc:">;
def _SLASH_Ze : CLFlag<"Ze">;
def _SLASH_Zg : CLFlag<"Zg">;
def _SLASH_ZI : CLFlag<"ZI">;
-def _SLASH_Zl : CLFlag<"Zl">;
def _SLASH_ZW : CLJoined<"ZW">;
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
index f0c1bed..3ed1913 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
@@ -10,6 +10,7 @@
#ifndef LLVM_CLANG_DRIVER_COMPILATION_H
#define LLVM_CLANG_DRIVER_COMPILATION_H
+#include "clang/Driver/Action.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Util.h"
#include "llvm/ADT/DenseMap.h"
@@ -25,7 +26,6 @@ namespace opt {
namespace clang {
namespace driver {
class Driver;
- class JobAction;
class JobList;
class ToolChain;
@@ -38,6 +38,9 @@ class Compilation {
/// The default tool chain.
const ToolChain &DefaultToolChain;
+ const ToolChain *CudaHostToolChain;
+ const ToolChain *CudaDeviceToolChain;
+
/// The original (untranslated) input argument list.
llvm::opt::InputArgList *Args;
@@ -45,7 +48,12 @@ class Compilation {
/// own argument translation.
llvm::opt::DerivedArgList *TranslatedArgs;
- /// The list of actions.
+ /// The list of actions we've created via MakeAction. This is not accessible
+ /// to consumers; it's here just to manage ownership.
+ std::vector<std::unique_ptr<Action>> AllActions;
+
+ /// The list of actions. This is maintained and modified by consumers, via
+ /// getActions().
ActionList Actions;
/// The root list of jobs.
@@ -81,6 +89,17 @@ public:
const Driver &getDriver() const { return TheDriver; }
const ToolChain &getDefaultToolChain() const { return DefaultToolChain; }
+ const ToolChain *getCudaHostToolChain() const { return CudaHostToolChain; }
+ const ToolChain *getCudaDeviceToolChain() const {
+ return CudaDeviceToolChain;
+ }
+
+ void setCudaHostToolChain(const ToolChain *HostToolChain) {
+ CudaHostToolChain = HostToolChain;
+ }
+ void setCudaDeviceToolChain(const ToolChain *DeviceToolChain) {
+ CudaDeviceToolChain = DeviceToolChain;
+ }
const llvm::opt::InputArgList &getInputArgs() const { return *Args; }
@@ -91,6 +110,15 @@ public:
ActionList &getActions() { return Actions; }
const ActionList &getActions() const { return Actions; }
+ /// Creates a new Action owned by this Compilation.
+ ///
+ /// The new Action is *not* added to the list returned by getActions().
+ template <typename T, typename... Args> T *MakeAction(Args &&... Arg) {
+ T *RawPtr = new T(std::forward<Args>(Arg)...);
+ AllActions.push_back(std::unique_ptr<Action>(RawPtr));
+ return RawPtr;
+ }
+
JobList &getJobs() { return Jobs; }
const JobList &getJobs() const { return Jobs; }
@@ -179,7 +207,7 @@ public:
void initCompilationForDiagnostics();
/// Return true if we're compiling for diagnostics.
- bool isForDiagnostics() { return ForDiagnostics; }
+ bool isForDiagnostics() const { return ForDiagnostics; }
};
} // end namespace driver
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
index 4a67fdb..a229779 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
@@ -18,10 +18,10 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo
-#include <memory>
- // lands.
+#include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo lands.
+
#include <list>
+#include <memory>
#include <set>
#include <string>
@@ -36,6 +36,11 @@ namespace opt {
}
namespace clang {
+
+namespace vfs {
+class FileSystem;
+}
+
namespace driver {
class Action;
@@ -47,6 +52,14 @@ namespace driver {
class SanitizerArgs;
class ToolChain;
+/// Describes the kind of LTO mode selected via -f(no-)?lto(=.*)? options.
+enum LTOKind {
+ LTOK_None,
+ LTOK_Full,
+ LTOK_Thin,
+ LTOK_Unknown
+};
+
/// Driver - Encapsulate logic for constructing compilation processes
/// from a set of gcc-driver-like command line arguments.
class Driver {
@@ -54,6 +67,8 @@ class Driver {
DiagnosticsEngine &Diags;
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS;
+
enum DriverMode {
GCCMode,
GXXMode,
@@ -67,6 +82,9 @@ class Driver {
SaveTempsObj
} SaveTemps;
+ /// LTO mode selected via -f(no-)?lto(=.*)? options.
+ LTOKind LTOMode;
+
public:
// Diag - Forwarding function for diagnostics.
DiagnosticBuilder Diag(unsigned DiagID) const {
@@ -201,9 +219,9 @@ private:
SmallVectorImpl<std::string> &Names) const;
public:
- Driver(StringRef _ClangExecutable,
- StringRef _DefaultTargetTriple,
- DiagnosticsEngine &_Diags);
+ Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
+ DiagnosticsEngine &Diags,
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
~Driver();
/// @name Accessors
@@ -216,6 +234,8 @@ public:
const DiagnosticsEngine &getDiags() const { return Diags; }
+ vfs::FileSystem &getVFS() const { return *VFS; }
+
bool getCheckInputsExist() const { return CheckInputsExist; }
void setCheckInputsExist(bool Value) { CheckInputsExist = Value; }
@@ -277,22 +297,21 @@ public:
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a single architecture.
///
+ /// \param C - The compilation that is being built.
/// \param TC - The default host tool chain.
/// \param Args - The input arguments.
/// \param Actions - The list to store the resulting actions onto.
- void BuildActions(const ToolChain &TC, llvm::opt::DerivedArgList &Args,
- const InputList &Inputs, ActionList &Actions) const;
+ void BuildActions(Compilation &C, const ToolChain &TC,
+ llvm::opt::DerivedArgList &Args, const InputList &Inputs,
+ ActionList &Actions) const;
/// BuildUniversalActions - Construct the list of actions to perform
/// for the given arguments, which may require a universal build.
///
+ /// \param C - The compilation that is being built.
/// \param TC - The default host tool chain.
- /// \param Args - The input arguments.
- /// \param Actions - The list to store the resulting actions onto.
- void BuildUniversalActions(const ToolChain &TC,
- llvm::opt::DerivedArgList &Args,
- const InputList &BAInputs,
- ActionList &Actions) const;
+ void BuildUniversalActions(Compilation &C, const ToolChain &TC,
+ const InputList &BAInputs) const;
/// BuildJobs - Bind actions to concrete tools and translate
/// arguments to form the list of jobs to run.
@@ -356,20 +375,16 @@ public:
/// ConstructAction - Construct the appropriate action to do for
/// \p Phase on the \p Input, taking in to account arguments
/// like -fsyntax-only or --analyze.
- std::unique_ptr<Action>
- ConstructPhaseAction(const ToolChain &TC, const llvm::opt::ArgList &Args,
- phases::ID Phase, std::unique_ptr<Action> Input) const;
+ Action *ConstructPhaseAction(Compilation &C, const ToolChain &TC,
+ const llvm::opt::ArgList &Args, phases::ID Phase,
+ Action *Input) const;
/// BuildJobsForAction - Construct the jobs to perform for the
- /// action \p A.
- void BuildJobsForAction(Compilation &C,
- const Action *A,
- const ToolChain *TC,
- const char *BoundArch,
- bool AtTopLevel,
- bool MultipleArchs,
- const char *LinkingOutput,
- InputInfo &Result) const;
+ /// action \p A and return an InputInfo for the result of running \p A.
+ InputInfo BuildJobsForAction(Compilation &C, const Action *A,
+ const ToolChain *TC, const char *BoundArch,
+ bool AtTopLevel, bool MultipleArchs,
+ const char *LinkingOutput) const;
/// Returns the default name for linked images (e.g., "a.out").
const char *getDefaultImageName() const;
@@ -402,9 +417,17 @@ public:
/// handle this action.
bool ShouldUseClangCompiler(const JobAction &JA) const;
- bool IsUsingLTO(const llvm::opt::ArgList &Args) const;
+ /// Returns true if we are performing any kind of LTO.
+ bool isUsingLTO() const { return LTOMode != LTOK_None; }
+
+ /// Get the specific kind of LTO being performed.
+ LTOKind getLTOMode() const { return LTOMode; }
private:
+ /// Parse the \p Args list for LTO options and record the type of LTO
+ /// compilation based on which -f(no-)?lto(=.*)? option occurs last.
+ void setLTOMode(const llvm::opt::ArgList &Args);
+
/// \brief Retrieves a ToolChain for a particular \p Target triple.
///
/// Will cache ToolChains for the life of the driver object, and create them
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Job.h b/contrib/llvm/tools/clang/include/clang/Driver/Job.h
index 186244b..263356f 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Job.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Job.h
@@ -25,6 +25,7 @@ namespace driver {
class Action;
class Command;
class Tool;
+class InputInfo;
// Re-export this as clang::driver::ArgStringList.
using llvm::opt::ArgStringList;
@@ -53,6 +54,9 @@ class Command {
/// argument, which will be the executable).
llvm::opt::ArgStringList Arguments;
+ /// The list of program arguments which are inputs.
+ llvm::opt::ArgStringList InputFilenames;
+
/// Response file name, if this command is set to use one, or nullptr
/// otherwise
const char *ResponseFile;
@@ -79,7 +83,11 @@ class Command {
public:
Command(const Action &Source, const Tool &Creator, const char *Executable,
- const llvm::opt::ArgStringList &Arguments);
+ const llvm::opt::ArgStringList &Arguments,
+ ArrayRef<InputInfo> Inputs);
+ // FIXME: This really shouldn't be copyable, but is currently copied in some
+ // error handling in Driver::generateCompilationDiagnostics.
+ Command(const Command &) = default;
virtual ~Command() {}
virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
@@ -117,6 +125,7 @@ class FallbackCommand : public Command {
public:
FallbackCommand(const Action &Source_, const Tool &Creator_,
const char *Executable_, const ArgStringList &Arguments_,
+ ArrayRef<InputInfo> Inputs,
std::unique_ptr<Command> Fallback_);
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.td b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
index 9d3e2cf..e4279e8 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Options.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
@@ -71,15 +71,31 @@ def d_Group : OptionGroup<"<d group>">;
def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>;
def f_clang_Group : OptionGroup<"<f (clang-only) group>">, Group<CompileOnly_Group>;
def g_Group : OptionGroup<"<g group>">;
+def gN_Group : OptionGroup<"<gN group>">, Group<g_Group>;
+def ggdbN_Group : OptionGroup<"<ggdbN group>">, Group<gN_Group>;
+def gTune_Group : OptionGroup<"<gTune group>">, Group<g_Group>;
def g_flags_Group : OptionGroup<"<g flags group>">;
def i_Group : OptionGroup<"<i group>">, Group<CompileOnly_Group>;
def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>;
def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>;
-def m_x86_Features_Group : OptionGroup<"<m x86 features group>">, Group<m_Group>, Flags<[CoreOption]>;
-def m_hexagon_Features_Group : OptionGroup<"<m hexagon features group>">, Group<m_Group>;
-def m_arm_Features_Group : OptionGroup<"<m arm features group>">, Group<m_Group>;
-def m_aarch64_Features_Group : OptionGroup<"<m aarch64 features group>">, Group<m_Group>;
-def m_ppc_Features_Group : OptionGroup<"<m ppc features group>">, Group<m_Group>;
+
+// Feature groups - these take command line options that correspond directly to
+// target specific features and can be translated directly from command line
+// options.
+def m_x86_Features_Group : OptionGroup<"<x86 features group>">,
+ Group<m_Group>,
+ Flags<[CoreOption]>;
+def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">,
+ Group<m_Group>;
+def m_arm_Features_Group : OptionGroup<"<arm features group>">,
+ Group<m_Group>;
+def m_aarch64_Features_Group : OptionGroup<"<aarch64 features group>">,
+ Group<m_Group>;
+def m_ppc_Features_Group : OptionGroup<"<ppc features group>">,
+ Group<m_Group>;
+def m_wasm_Features_Group : OptionGroup<"<wasm features group>">,
+ Group<m_Group>;
+
def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_Group>;
def u_Group : OptionGroup<"<u group>">;
@@ -143,7 +159,7 @@ def ccc_pch_is_pth : Flag<["-"], "ccc-pch-is-pth">, InternalDriverOpt,
HelpText<"Use pretokenized headers for precompiled headers">;
class InternalDebugOpt : Group<internal_debug_Group>,
- Flags<[DriverOption, HelpHidden]>;
+ Flags<[DriverOption, HelpHidden, CoreOption]>;
def ccc_install_dir : Separate<["-"], "ccc-install-dir">, InternalDebugOpt,
HelpText<"Simulate installation in the given directory">;
def ccc_print_phases : Flag<["-"], "ccc-print-phases">, InternalDebugOpt,
@@ -293,6 +309,7 @@ def Wa_COMMA : CommaJoined<["-"], "Wa,">,
HelpText<"Pass the comma separated arguments in <arg> to the assembler">,
MetaVarName<"<arg>">;
def Wall : Flag<["-"], "Wall">, Group<W_Group>, Flags<[CC1Option]>;
+def WCL4 : Flag<["-"], "WCL4">, Group<W_Group>, Flags<[CC1Option]>;
def Wdeprecated : Flag<["-"], "Wdeprecated">, Group<W_Group>, Flags<[CC1Option]>;
def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group<W_Group>, Flags<[CC1Option]>;
def Wextra : Flag<["-"], "Wextra">, Group<W_Group>, Flags<[CC1Option]>;
@@ -357,6 +374,8 @@ def cuda_gpu_arch_EQ : Joined<["--"], "cuda-gpu-arch=">,
Flags<[DriverOption, HelpHidden]>, HelpText<"CUDA GPU architecture">;
def cuda_host_only : Flag<["--"], "cuda-host-only">,
HelpText<"Do host-side CUDA compilation only">;
+def cuda_path_EQ : Joined<["--"], "cuda-path=">, Group<i_Group>,
+ HelpText<"CUDA installation path">;
def dA : Flag<["-"], "dA">, Group<d_Group>;
def dD : Flag<["-"], "dD">, Group<d_Group>, Flags<[CC1Option]>,
HelpText<"Print macro definitions in -E mode in addition to normal output">;
@@ -436,6 +455,9 @@ def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Generate coverage mapping to enable code coverage analysis">;
+def fno_coverage_mapping : Flag<["-"], "fno-coverage-mapping">,
+ Group<f_Group>, Flags<[DriverOption]>,
+ HelpText<"Disable code coverage analysis">;
def fprofile_generate : Flag<["-"], "fprofile-generate">,
Alias<fprofile_instr_generate>;
def fprofile_generate_EQ : Joined<["-"], "fprofile-generate=">,
@@ -446,6 +468,16 @@ def fprofile_use : Flag<["-"], "fprofile-use">, Group<f_Group>,
def fprofile_use_EQ : Joined<["-"], "fprofile-use=">,
Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<pathname>">,
HelpText<"Use instrumentation data for profile-guided optimization. If pathname is a directory, it reads from <pathname>/default.profdata. Otherwise, it reads from file <pathname>.">;
+def fno_profile_instr_generate : Flag<["-"], "fno-profile-instr-generate">,
+ Group<f_Group>, Flags<[DriverOption]>,
+ HelpText<"Disable generation of profile instrumentation.">;
+def fno_profile_generate : Flag<["-"], "fno-profile-generate">,
+ Alias<fno_profile_instr_generate>;
+def fno_profile_instr_use : Flag<["-"], "fno-profile-instr-use">,
+ Group<f_Group>, Flags<[DriverOption]>,
+ HelpText<"Disable using instrumentation data for profile-guided optimization">;
+def fno_profile_use : Flag<["-"], "fno-profile-use">,
+ Alias<fno_profile_instr_use>;
def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable the 'blocks' language feature">;
@@ -482,6 +514,8 @@ def fcxx_modules : Flag <["-"], "fcxx-modules">, Group<f_Group>,
Flags<[DriverOption]>;
def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group<f_Group>;
def fdebug_pass_structure : Flag<["-"], "fdebug-pass-structure">, Group<f_Group>;
+def fdepfile_entry : Joined<["-"], "fdepfile-entry=">,
+ Group<f_clang_Group>, Flags<[CC1Option]>;
def fdiagnostics_fixit_info : Flag<["-"], "fdiagnostics-fixit-info">, Group<f_clang_Group>;
def fdiagnostics_parseable_fixits : Flag<["-"], "fdiagnostics-parseable-fixits">, Group<f_clang_Group>,
Flags<[CoreOption, CC1Option]>, HelpText<"Print fix-its in machine parseable form">;
@@ -497,6 +531,8 @@ def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">
def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Print a template comparison tree for differing templates">;
+def fdeclspec : Flag<["-"], "fdeclspec">, Group<f_clang_Group>,
+ HelpText<"Allow __declspec as a keyword">, Flags<[CC1Option]>;
def fdollars_in_identifiers : Flag<["-"], "fdollars-in-identifiers">, Group<f_Group>,
HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>;
def fdwarf2_cfi_asm : Flag<["-"], "fdwarf2-cfi-asm">, Group<clang_ignored_f_Group>;
@@ -510,6 +546,9 @@ def fno_elide_type : Flag<["-"], "fno-elide-type">, Group<f_Group>,
def feliminate_unused_debug_symbols : Flag<["-"], "feliminate-unused-debug-symbols">, Group<f_Group>;
def femit_all_decls : Flag<["-"], "femit-all-decls">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Emit all declarations, even if unused">;
+def femulated_tls : Flag<["-"], "femulated-tls">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use emutls functions to access thread_local variables">;
+def fno_emulated_tls : Flag<["-"], "fno-emulated-tls">, Group<f_Group>;
def fencoding_EQ : Joined<["-"], "fencoding=">, Group<f_Group>;
def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<f_Group>, Flags<[CoreOption]>;
def fexceptions : Flag<["-"], "fexceptions">, Group<f_Group>, Flags<[CC1Option]>,
@@ -538,7 +577,7 @@ def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>;
def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>,
Flags<[CC1Option, CoreOption]>, MetaVarName<"<check>">,
HelpText<"Turn on runtime checks for various forms of undefined "
- "or suspicious behavior. See user manual for available checks ">;
+ "or suspicious behavior. See user manual for available checks">;
def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>,
Flags<[CoreOption]>;
def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">,
@@ -595,6 +634,12 @@ def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-t
Group<f_clang_Group>;
def fsanitize_link_cxx_runtime : Flag<["-"], "fsanitize-link-c++-runtime">,
Group<f_clang_Group>;
+def fsanitize_cfi_cross_dso : Flag<["-"], "fsanitize-cfi-cross-dso">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable control flow integrity (CFI) checks for cross-DSO calls.">;
+def fno_sanitize_cfi_cross_dso : Flag<["-"], "fno-sanitize-cfi-cross-dso">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable control flow integrity (CFI) checks for cross-DSO calls.">;
def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">,
Group<f_Group>;
def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">,
@@ -663,16 +708,22 @@ def finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>
def flat__namespace : Flag<["-"], "flat_namespace">;
def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
-def flto_EQ : Joined<["-"], "flto=">, Group<clang_ignored_gcc_optimization_f_Group>;
-def flto : Flag<["-"], "flto">, Flags<[CC1Option]>, Group<f_Group>;
-def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>;
+def flto_EQ : Joined<["-"], "flto=">, Flags<[CC1Option]>, Group<f_Group>,
+ HelpText<"Set LTO mode to either 'full' or 'thin'">;
+def flto : Flag<["-"], "flto">, Flags<[CC1Option]>, Group<f_Group>,
+ HelpText<"Enable LTO in 'full' mode">;
+def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>,
+ HelpText<"Disable LTO mode (default)">;
+def fthinlto_index_EQ : Joined<["-"], "fthinlto-index=">,
+ Flags<[CC1Option]>, Group<f_Group>,
+ HelpText<"Perform ThinLTO importing using provided function summary index">;
def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">,
Group<f_Group>, Flags<[DriverOption, CoreOption]>;
def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group<f_Group>;
def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group<f_Group>;
-def fms_extensions : Flag<["-"], "fms-extensions">, Group<f_Group>, Flags<[CC1Option]>,
+def fms_extensions : Flag<["-"], "fms-extensions">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">;
-def fms_compatibility : Flag<["-"], "fms-compatibility">, Group<f_Group>, Flags<[CC1Option]>,
+def fms_compatibility : Flag<["-"], "fms-compatibility">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Enable full Microsoft Visual C++ compatibility">;
def fms_volatile : Joined<["-"], "fms-volatile">, Group<f_Group>, Flags<[CC1Option]>;
def fmsc_version : Joined<["-"], "fmsc-version=">, Group<f_Group>, Flags<[DriverOption, CoreOption]>,
@@ -763,7 +814,7 @@ def fno_blocks : Flag<["-"], "fno-blocks">, Group<f_Group>;
def fno_borland_extensions : Flag<["-"], "fno-borland-extensions">, Group<f_Group>;
def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disable implicit builtin knowledge of functions">;
-def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<clang_ignored_f_Group>,
+def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disable implicit builtin knowledge of a specific function">;
def fno_math_builtin : Flag<["-"], "fno-math-builtin">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disable implicit builtin knowledge of math functions">;
@@ -786,6 +837,8 @@ def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Grou
def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group<f_Group>;
def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">,
Flags<[CC1Option]>, Group<f_Group>;
+def fno_declspec : Flag<["-"], "fno-declspec">, Group<f_clang_Group>,
+ HelpText<"Disallow __declspec as a keyword">, Flags<[CC1Option]>;
def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group<f_Group>,
HelpText<"Disallow '$' in identifiers">, Flags<[CC1Option]>;
def fno_elide_constructors : Flag<["-"], "fno-elide-constructors">, Group<f_Group>,
@@ -816,11 +869,14 @@ def fmodule_file_deps : Flag <["-"], "fmodule-file-deps">, Group<f_Group>,
Flags<[DriverOption]>;
def fno_module_file_deps : Flag <["-"], "fno-module-file-deps">, Group<f_Group>,
Flags<[DriverOption]>;
-def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>;
-def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>;
+def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>,
+ Flags<[CoreOption]>;
+def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>,
+ Flags<[CoreOption]>;
def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group<f_Group>;
def fno_objc_exceptions: Flag<["-"], "fno-objc-exceptions">, Group<f_Group>;
def fno_objc_legacy_dispatch : Flag<["-"], "fno-objc-legacy-dispatch">, Group<f_Group>;
+def fno_objc_weak : Flag<["-"], "fno-objc-weak">, Group<f_Group>, Flags<[CC1Option]>;
def fno_omit_frame_pointer : Flag<["-"], "fno-omit-frame-pointer">, Group<f_Group>;
def fno_operator_names : Flag<["-"], "fno-operator-names">, Group<f_Group>,
HelpText<"Do not treat C++ operator name keywords as synonyms for operators">,
@@ -842,6 +898,8 @@ def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>,
def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>;
def fno_struct_path_tbaa : Flag<["-"], "fno-struct-path-tbaa">, Group<f_Group>;
def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>;
+def fno_strict_vtable_pointers: Flag<["-"], "fno-strict-vtable-pointers">,
+ Group<f_Group>;
def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>;
def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">;
@@ -888,6 +946,8 @@ def fno_objc_infer_related_result_type : Flag<["-"],
"do not infer Objective-C related result type based on method family">,
Flags<[CC1Option]>;
def fobjc_link_runtime: Flag<["-"], "fobjc-link-runtime">, Group<f_Group>;
+def fobjc_weak : Flag<["-"], "fobjc-weak">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable ARC-style weak references in Objective-C">;
// Objective-C ABI options.
def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option]>,
@@ -927,6 +987,8 @@ def fpic : Flag<["-"], "fpic">, Group<f_Group>;
def fno_pic : Flag<["-"], "fno-pic">, Group<f_Group>;
def fpie : Flag<["-"], "fpie">, Group<f_Group>;
def fno_pie : Flag<["-"], "fno-pie">, Group<f_Group>;
+def fplugin_EQ : Joined<["-"], "fplugin=">, Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<dsopath>">,
+ HelpText<"Load the named plugin (dynamic shared object)">;
def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group<f_Group>;
def fno_profile_arcs : Flag<["-"], "fno-profile-arcs">, Group<f_Group>;
def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>;
@@ -959,9 +1021,9 @@ def fstack_protector_strong : Flag<["-"], "fstack-protector-strong">, Group<f_Gr
HelpText<"Use a strong heuristic to apply stack protectors to functions">;
def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>,
HelpText<"Enable stack protectors for functions potentially vulnerable to stack smashing">;
-def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>, Flags<[CC1Option]>,
+def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>,
HelpText<"Emit full debug info for all types used by the program">;
-def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>, Flags<[CC1Option]>,
+def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>,
HelpText<"Limit debug information produced to reduce size of debug binary">;
def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Alias<fno_standalone_debug>;
def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Alias<fstandalone_debug>;
@@ -970,6 +1032,10 @@ def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>,
def fstrict_enums : Flag<["-"], "fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable optimizations based on the strict definition of an enum's "
"value range">;
+def fstrict_vtable_pointers: Flag<["-"], "fstrict-vtable-pointers">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable optimizations based on the strict rules for overwriting "
+ "polymorphic C++ objects">;
def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group<f_Group>;
def fsyntax_only : Flag<["-"], "fsyntax-only">,
Flags<[DriverOption,CoreOption,CC1Option]>, Group<Action_Group>;
@@ -1073,26 +1139,40 @@ def fdebug_types_section: Flag <["-"], "fdebug-types-section">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">;
def fno_debug_types_section: Flag<["-"], "fno-debug-types-section">, Group<f_Group>,
Flags<[CC1Option]>;
+def fdebug_prefix_map_EQ
+ : Joined<["-"], "fdebug-prefix-map=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"remap file source paths in debug info">;
def g_Flag : Flag<["-"], "g">, Group<g_Group>,
- HelpText<"Generate source-level debug information">, Flags<[CC1Option,CC1AsOption]>;
-def gline_tables_only : Flag<["-"], "gline-tables-only">, Group<g_Group>,
- HelpText<"Emit debug line number tables only">, Flags<[CC1Option]>;
+ HelpText<"Generate source-level debug information">;
+def gline_tables_only : Flag<["-"], "gline-tables-only">, Group<gN_Group>,
+ HelpText<"Emit debug line number tables only">;
def gmlt : Flag<["-"], "gmlt">, Alias<gline_tables_only>;
-def g0 : Flag<["-"], "g0">, Group<g_Group>;
-def g1 : Flag<["-"], "g1">, Group<g_Group>;
-def g2 : Flag<["-"], "g2">, Group<g_Group>;
-def g3 : Flag<["-"], "g3">, Group<g_Group>;
-def ggdb : Flag<["-"], "ggdb">, Group<g_Group>;
-def ggdb0 : Flag<["-"], "ggdb0">, Group<g_Group>;
-def ggdb1 : Flag<["-"], "ggdb1">, Group<g_Group>;
-def ggdb2 : Flag<["-"], "ggdb2">, Group<g_Group>;
-def ggdb3 : Flag<["-"], "ggdb3">, Group<g_Group>;
+def g0 : Flag<["-"], "g0">, Group<gN_Group>;
+def g1 : Flag<["-"], "g1">, Group<gN_Group>, Alias<gline_tables_only>;
+def g2 : Flag<["-"], "g2">, Group<gN_Group>;
+def g3 : Flag<["-"], "g3">, Group<gN_Group>;
+def ggdb : Flag<["-"], "ggdb">, Group<gTune_Group>;
+def ggdb0 : Flag<["-"], "ggdb0">, Group<ggdbN_Group>;
+def ggdb1 : Flag<["-"], "ggdb1">, Group<ggdbN_Group>;
+def ggdb2 : Flag<["-"], "ggdb2">, Group<ggdbN_Group>;
+def ggdb3 : Flag<["-"], "ggdb3">, Group<ggdbN_Group>;
+def glldb : Flag<["-"], "glldb">, Group<gTune_Group>;
+def gsce : Flag<["-"], "gsce">, Group<gTune_Group>;
def gdwarf_2 : Flag<["-"], "gdwarf-2">, Group<g_Group>,
- HelpText<"Generate source-level debug information with dwarf version 2">, Flags<[CC1Option,CC1AsOption]>;
+ HelpText<"Generate source-level debug information with dwarf version 2">;
def gdwarf_3 : Flag<["-"], "gdwarf-3">, Group<g_Group>,
- HelpText<"Generate source-level debug information with dwarf version 3">, Flags<[CC1Option,CC1AsOption]>;
+ HelpText<"Generate source-level debug information with dwarf version 3">;
def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group<g_Group>,
- HelpText<"Generate source-level debug information with dwarf version 4">, Flags<[CC1Option,CC1AsOption]>;
+ HelpText<"Generate source-level debug information with dwarf version 4">;
+def gdwarf_5 : Flag<["-"], "gdwarf-5">, Group<g_Group>,
+ HelpText<"Generate source-level debug information with dwarf version 5">;
+def gcodeview : Flag<["-"], "gcodeview">,
+ HelpText<"Generate CodeView debug information">,
+ Flags<[CC1Option, CC1AsOption, CoreOption]>;
+// Equivalent to our default dwarf version. Forces usual dwarf emission when
+// CodeView is enabled.
+def gdwarf : Flag<["-"], "gdwarf">, Alias<gdwarf_4>, Flags<[CoreOption]>;
+
def gfull : Flag<["-"], "gfull">, Group<g_Group>;
def gused : Flag<["-"], "gused">, Group<g_Group>;
def gstabs : Joined<["-"], "gstabs">, Group<g_Group>, Flags<[Unsupported]>;
@@ -1110,6 +1190,9 @@ def gno_column_info : Flag<["-"], "gno-column-info">, Group<g_flags_Group>;
def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>;
def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>;
def gdwarf_aranges : Flag<["-"], "gdwarf-aranges">, Group<g_flags_Group>;
+def gmodules : Flag <["-"], "gmodules">, Group<f_Group>,
+ HelpText<"Generate debug info with external references to clang modules"
+ " or precompiled headers">;
def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">;
def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption]>,
HelpText<"Display available options">;
@@ -1173,6 +1256,13 @@ def malign_functions_EQ : Joined<["-"], "malign-functions=">, Group<clang_ignore
def malign_loops_EQ : Joined<["-"], "malign-loops=">, Group<clang_ignored_m_Group>;
def malign_jumps_EQ : Joined<["-"], "malign-jumps=">, Group<clang_ignored_m_Group>;
def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group<clang_ignored_m_Group>;
+def mtvos_version_min_EQ : Joined<["-"], "mtvos-version-min=">, Group<m_Group>;
+def mappletvos_version_min_EQ : Joined<["-"], "mappletvos-version-min=">, Alias<mtvos_version_min_EQ>;
+def mtvos_simulator_version_min_EQ : Joined<["-"], "mtvos-simulator-version-min=">, Alias<mtvos_version_min_EQ>;
+def mappletvsimulator_version_min_EQ : Joined<["-"], "mappletvsimulator-version-min=">, Alias<mtvos_version_min_EQ>;
+def mwatchos_version_min_EQ : Joined<["-"], "mwatchos-version-min=">, Group<m_Group>;
+def mwatchos_simulator_version_min_EQ : Joined<["-"], "mwatchos-simulator-version-min=">, Alias<mwatchos_version_min_EQ>;
+def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min=">, Alias<mwatchos_version_min_EQ>;
def march_EQ : Joined<["-"], "march=">, Group<m_Group>;
def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Flags<[DriverOption]>;
def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>;
@@ -1209,6 +1299,8 @@ def mmacosx_version_min_EQ : Joined<["-"], "mmacosx-version-min=">,
Group<m_Group>, HelpText<"Set Mac OS X deployment target">;
def mms_bitfields : Flag<["-"], "mms-bitfields">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard">;
+def mno_ms_bitfields : Flag<["-"], "mno-ms-bitfields">, Group<m_Group>,
+ HelpText<"Do not set the default structure layout to be compatible with the Microsoft compiler standard">;
def mstackrealign : Flag<["-"], "mstackrealign">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Force realign the stack at entry to every function">;
def mstack_alignment : Joined<["-"], "mstack-alignment=">, Group<m_Group>, Flags<[CC1Option]>,
@@ -1217,6 +1309,8 @@ def mstack_probe_size : Joined<["-"], "mstack-probe-size=">, Group<m_Group>, Fla
HelpText<"Set the stack probe size">;
def mthread_model : Separate<["-"], "mthread-model">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"The thread model to use, e.g. posix, single (posix by default)">;
+def meabi : Separate<["-"], "meabi">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Set EABI type, e.g. 4, 5 or gnu (default depends on triple)">;
def mmmx : Flag<["-"], "mmmx">, Group<m_x86_Features_Group>;
def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group<m_x86_Features_Group>;
@@ -1270,6 +1364,12 @@ def mno_prfchw : Flag<["-"], "mno-prfchw">, Group<m_x86_Features_Group>;
def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>;
def mno_adx : Flag<["-"], "mno-adx">, Group<m_x86_Features_Group>;
def mno_sha : Flag<["-"], "mno-sha">, Group<m_x86_Features_Group>;
+def mno_fxsr : Flag<["-"], "mno-fxsr">, Group<m_x86_Features_Group>;
+def mno_xsave : Flag<["-"], "mno-xsave">, Group<m_x86_Features_Group>;
+def mno_xsaveopt : Flag<["-"], "mno-xsaveopt">, Group<m_x86_Features_Group>;
+def mno_xsavec : Flag<["-"], "mno-xsavec">, Group<m_x86_Features_Group>;
+def mno_xsaves : Flag<["-"], "mno-xsaves">, Group<m_x86_Features_Group>;
+def mno_pku : Flag<["-"], "mno-pku">, Group<m_x86_Features_Group>;
def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">;
@@ -1285,6 +1385,8 @@ def mno_restrict_it: Flag<["-"], "mno-restrict-it">, Group<m_arm_Features_Group>
def marm : Flag<["-"], "marm">, Alias<mno_thumb>;
def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_arm_Features_Group>,
HelpText<"Reserve the r9 register (ARM only)">;
+def mno_movt : Flag<["-"], "mno-movt">, Group<m_arm_Features_Group>,
+ HelpText<"Disallow use of movt/movw pairs (ARM only)">;
def mcrc : Flag<["-"], "mcrc">, Group<m_arm_Features_Group>,
HelpText<"Allow use of CRC instructions (ARM only)">;
def mnocrc : Flag<["-"], "mnocrc">, Group<m_arm_Features_Group>,
@@ -1306,6 +1408,9 @@ def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">,
def ffixed_x18 : Flag<["-"], "ffixed-x18">, Group<m_aarch64_Features_Group>,
HelpText<"Reserve the x18 register (AArch64 only)">;
+def msimd128 : Flag<["-"], "msimd128">, Group<m_wasm_Features_Group>;
+def mno_simd128 : Flag<["-"], "mno-simd128">, Group<m_wasm_Features_Group>;
+
def mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>;
def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>;
def mpower8_vector : Flag<["-"], "mpower8-vector">,
@@ -1328,8 +1433,10 @@ def mcmpb : Flag<["-"], "mcmpb">, Group<m_ppc_Features_Group>;
def mno_cmpb : Flag<["-"], "mno-cmpb">, Group<m_ppc_Features_Group>;
def misel : Flag<["-"], "misel">, Group<m_ppc_Features_Group>;
def mno_isel : Flag<["-"], "mno-isel">, Group<m_ppc_Features_Group>;
-def mmfcrf : Flag<["-"], "mmfcrf">, Group<m_ppc_Features_Group>;
-def mno_mfcrf : Flag<["-"], "mno-mfcrf">, Group<m_ppc_Features_Group>;
+def mmfocrf : Flag<["-"], "mmfocrf">, Group<m_ppc_Features_Group>;
+def mmfcrf : Flag<["-"], "mmfcrf">, Alias<mmfocrf>;
+def mno_mfocrf : Flag<["-"], "mno-mfocrf">, Group<m_ppc_Features_Group>;
+def mno_mfcrf : Flag<["-"], "mno-mfcrf">, Alias<mno_mfocrf>;
def mpopcntd : Flag<["-"], "mpopcntd">, Group<m_ppc_Features_Group>;
def mno_popcntd : Flag<["-"], "mno-popcntd">, Group<m_ppc_Features_Group>;
def mqpx : Flag<["-"], "mqpx">, Group<m_ppc_Features_Group>;
@@ -1368,6 +1475,11 @@ def mred_zone : Flag<["-"], "mred-zone">, Group<m_Group>;
def mregparm_EQ : Joined<["-"], "mregparm=">, Group<m_Group>;
def mrelax_all : Flag<["-"], "mrelax-all">, Group<m_Group>, Flags<[CC1Option,CC1AsOption]>,
HelpText<"(integrated-as) Relax all machine instructions">;
+def mincremental_linker_compatible : Flag<["-"], "mincremental-linker-compatible">, Group<m_Group>,
+ Flags<[CC1Option,CC1AsOption]>,
+ HelpText<"(integrated-as) Emit an object file which can be used with an incremental linker">;
+def mno_incremental_linker_compatible : Flag<["-"], "mno-incremental-linker-compatible">, Group<m_Group>,
+ HelpText<"(integrated-as) Emit an object file which cannot be used with an incremental linker">;
def mrtd : Flag<["-"], "mrtd">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Make StdCall calling convention the default">;
def msmall_data_threshold_EQ : Joined <["-"], "msmall-data-threshold=">, Group<m_Group>;
@@ -1411,9 +1523,15 @@ def mf16c : Flag<["-"], "mf16c">, Group<m_x86_Features_Group>;
def mrtm : Flag<["-"], "mrtm">, Group<m_x86_Features_Group>;
def mprfchw : Flag<["-"], "mprfchw">, Group<m_x86_Features_Group>;
def mrdseed : Flag<["-"], "mrdseed">, Group<m_x86_Features_Group>;
+def mpku : Flag<["-"], "mpku">, Group<m_x86_Features_Group>;
def madx : Flag<["-"], "madx">, Group<m_x86_Features_Group>;
def msha : Flag<["-"], "msha">, Group<m_x86_Features_Group>;
def mcx16 : Flag<["-"], "mcx16">, Group<m_x86_Features_Group>;
+def mfxsr : Flag<["-"], "mfxsr">, Group<m_x86_Features_Group>;
+def mxsave : Flag<["-"], "mxsave">, Group<m_x86_Features_Group>;
+def mxsaveopt : Flag<["-"], "mxsaveopt">, Group<m_x86_Features_Group>;
+def mxsavec : Flag<["-"], "mxsavec">, Group<m_x86_Features_Group>;
+def mxsaves : Flag<["-"], "mxsaves">, Group<m_x86_Features_Group>;
def mips16 : Flag<["-"], "mips16">, Group<m_Group>;
def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_Group>;
def mmicromips : Flag<["-"], "mmicromips">, Group<m_Group>;
@@ -1515,6 +1633,8 @@ def no_pedantic : Flag<["-", "--"], "no-pedantic">, Group<pedantic_Group>;
def no__dead__strip__inits__and__terms : Flag<["-"], "no_dead_strip_inits_and_terms">;
def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option]>,
HelpText<"Disable builtin #include directories">;
+def nocudainc : Flag<["-"], "nocudainc">;
+def nocudalib : Flag<["-"], "nocudalib">;
def nodefaultlibs : Flag<["-"], "nodefaultlibs">;
def nofixprebinding : Flag<["-"], "nofixprebinding">;
def nolibc : Flag<["-"], "nolibc">;
@@ -1531,6 +1651,8 @@ def nostdlib : Flag<["-"], "nostdlib">;
def object : Flag<["-"], "object">;
def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option, CC1AsOption]>,
HelpText<"Write output to <file>">, MetaVarName<"<file>">;
+def omptargets_EQ : CommaJoined<["-"], "omptargets=">, Flags<[DriverOption, CC1Option]>,
+ HelpText<"Specify comma-separated list of triples OpenMP offloading targets to be supported">;
def pagezero__size : JoinedOrSeparate<["-"], "pagezero_size">;
def pass_exit_codes : Flag<["-", "--"], "pass-exit-codes">, Flags<[Unsupported]>;
def pedantic_errors : Flag<["-", "--"], "pedantic-errors">, Group<pedantic_Group>, Flags<[CC1Option]>;
@@ -1576,7 +1698,7 @@ def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[DriverOption]>,
Alias<resource_dir>;
def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>;
def rtlib_EQ : Joined<["-", "--"], "rtlib=">;
-def r : Flag<["-"], "r">;
+def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>;
def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[DriverOption]>,
HelpText<"Save intermediate compilation results.">;
def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>,
@@ -1783,16 +1905,22 @@ def _write_user_dependencies : Flag<["--"], "write-user-dependencies">, Alias<MM
def _ : Joined<["--"], "">, Flags<[Unsupported]>;
def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group<m_hexagon_Features_Group>;
-def mv1 : Flag<["-"], "mv1">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
- AliasArgs<["v1"]>;
-def mv2 : Flag<["-"], "mv2">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
- AliasArgs<["v2"]>;
-def mv3 : Flag<["-"], "mv3">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
- AliasArgs<["v3"]>;
-def mv4 : Flag<["-"], "mv4">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
- AliasArgs<["v4"]>;
-def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
- AliasArgs<["v5"]>;
+def mv4 : Flag<["-"], "mv4">, Group<m_hexagon_Features_Group>,
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv4"]>;
+def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>,
+ AliasArgs<["hexagonv5"]>;
+def mv55 : Flag<["-"], "mv55">, Group<m_hexagon_Features_Group>,
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv55"]>;
+def mv60 : Flag<["-"], "mv60">, Group<m_hexagon_Features_Group>,
+ Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>;
+def mhexagon_hvx : Flag<["-"], "mhvx">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable Hexagon Vector eXtensions">;
+def mno_hexagon_hvx : Flag<["-"], "mno-hvx">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Disable Hexagon Vector eXtensions">;
+def mhexagon_hvx_double : Flag<["-"], "mhvx-double">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable Hexagon Double Vector eXtensions">;
+def mno_hexagon_hvx_double : Flag<["-"], "mno-hvx-double">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Disable Hexagon Double Vector eXtensions">;
// These are legacy user-facing driver-level option spellings. They are always
// aliases for options that are spelled using the more common Unix / GNU flag
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h b/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h
index 82b668a..c2611b5 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h
@@ -27,13 +27,15 @@ class SanitizerArgs {
SanitizerSet TrapSanitizers;
std::vector<std::string> BlacklistFiles;
+ std::vector<std::string> ExtraDeps;
int CoverageFeatures;
int MsanTrackOrigins;
bool MsanUseAfterDtor;
+ bool CfiCrossDso;
int AsanFieldPadding;
- bool AsanZeroBaseShadow;
bool AsanSharedRuntime;
bool LinkCXXRuntimes;
+ bool NeedPIE;
public:
/// Parses the sanitizer arguments from an argument list.
@@ -52,6 +54,8 @@ class SanitizerArgs {
bool needsSafeStackRt() const {
return Sanitizers.has(SanitizerKind::SafeStack);
}
+ bool needsCfiRt() const;
+ bool needsCfiDiagRt() const;
bool requiresPIE() const;
bool needsUnwindTables() const;
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
index aba18c9..7e68d0a 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Path.h"
+#include "llvm/Target/TargetOptions.h"
#include <memory>
#include <string>
@@ -30,7 +31,10 @@ namespace opt {
}
namespace clang {
- class ObjCRuntime;
+class ObjCRuntime;
+namespace vfs {
+class FileSystem;
+}
namespace driver {
class Compilation;
@@ -89,6 +93,7 @@ private:
protected:
MultilibSet Multilibs;
+ const char *DefaultLinker = "ld";
ToolChain(const Driver &D, const llvm::Triple &T,
const llvm::opt::ArgList &Args);
@@ -119,7 +124,8 @@ public:
// Accessors
- const Driver &getDriver() const;
+ const Driver &getDriver() const { return D; }
+ vfs::FileSystem &getVFS() const;
const llvm::Triple &getTriple() const { return Triple; }
llvm::Triple::ArchType getArch() const { return Triple.getArch(); }
@@ -128,7 +134,7 @@ public:
StringRef getOS() const { return Triple.getOSName(); }
/// \brief Provide the default architecture name (as expected by -arch) for
- /// this toolchain. Note t
+ /// this toolchain.
StringRef getDefaultUniversalArchName() const;
std::string getTripleString() const {
@@ -151,6 +157,20 @@ public:
// Returns the RTTIMode for the toolchain with the current arguments.
RTTIMode getRTTIMode() const { return CachedRTTIMode; }
+ /// \brief Return any implicit target and/or mode flag for an invocation of
+ /// the compiler driver as `ProgName`.
+ ///
+ /// For example, when called with i686-linux-android-g++, the first element
+ /// of the return value will be set to `"i686-linux-android"` and the second
+ /// will be set to "--driver-mode=g++"`.
+ ///
+ /// \pre `llvm::InitializeAllTargets()` has been called.
+ /// \param ProgName The name the Clang driver was invoked with (from,
+ /// e.g., argv[0])
+ /// \return A pair of (`target`, `mode-flag`), where one or both may be empty.
+ static std::pair<std::string, std::string>
+ getTargetAndModeFromProgramName(StringRef ProgName);
+
// Tool access.
/// TranslateArgs - Create a new derived argument list for any argument
@@ -167,7 +187,7 @@ public:
/// Choose a tool to use to handle the action \p JA.
///
/// This can be overridden when a particular ToolChain needs to use
- /// a C compiler other than Clang.
+ /// a compiler other than Clang.
virtual Tool *SelectTool(const JobAction &JA) const;
// Helper methods
@@ -184,7 +204,7 @@ public:
/// This is used when handling the verbose option to print detailed,
/// toolchain-specific information useful for understanding the behavior of
/// the driver on a specific platform.
- virtual void printVerboseInfo(raw_ostream &OS) const {};
+ virtual void printVerboseInfo(raw_ostream &OS) const {}
// Platform defaults information
@@ -236,6 +256,16 @@ public:
return ToolChain::RLT_Libgcc;
}
+ virtual std::string getCompilerRT(const llvm::opt::ArgList &Args,
+ StringRef Component,
+ bool Shared = false) const;
+
+ const char *getCompilerRTArgString(const llvm::opt::ArgList &Args,
+ StringRef Component,
+ bool Shared = false) const;
+ /// needsProfileRT - returns true if instrumentation profile is on.
+ static bool needsProfileRT(const llvm::opt::ArgList &Args);
+
/// IsUnwindTablesDefault - Does this tool chain use -funwind-tables
/// by default.
virtual bool IsUnwindTablesDefault() const;
@@ -265,8 +295,25 @@ public:
/// compile unit information.
virtual bool UseDwarfDebugFlags() const { return false; }
+ // Return the DWARF version to emit, in the absence of arguments
+ // to the contrary.
+ virtual unsigned GetDefaultDwarfVersion() const { return 4; }
+
+ // True if the driver should assume "-fstandalone-debug"
+ // in the absence of an option specifying otherwise,
+ // provided that debugging was requested in the first place.
+ // i.e. a value of 'true' does not imply that debugging is wanted.
+ virtual bool GetDefaultStandaloneDebug() const { return false; }
+
+ // Return the default debugger "tuning."
+ virtual llvm::DebuggerKind getDefaultDebuggerTuning() const {
+ return llvm::DebuggerKind::GDB;
+ }
+
/// UseSjLjExceptions - Does this tool chain use SjLj exceptions.
- virtual bool UseSjLjExceptions() const { return false; }
+ virtual bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const {
+ return false;
+ }
/// getThreadModel() - Which thread model does this target use?
virtual std::string getThreadModel() const { return "posix"; }
@@ -337,6 +384,10 @@ public:
virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
+ /// AddFilePathLibArgs - Add each thing in getFilePaths() as a "-L" option.
+ void AddFilePathLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
/// AddCCKextLibArgs - Add the system specific linker arguments to use
/// for kernel extensions (Darwin-specific).
virtual void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
@@ -346,10 +397,17 @@ public:
/// global flags for unsafe floating point math, add it and return true.
///
/// This checks for presence of the -Ofast, -ffast-math or -funsafe-math flags.
- virtual bool
- AddFastMathRuntimeIfAvailable(const llvm::opt::ArgList &Args,
+ virtual bool AddFastMathRuntimeIfAvailable(
+ const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const;
+ /// addProfileRTLibs - When -fprofile-instr-profile is specified, try to pass
+ /// a suitable profile runtime library to the linker.
+ virtual void addProfileRTLibs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
+ /// \brief Add arguments to use system-specific CUDA includes.
+ virtual void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
/// \brief Return sanitizers which are available in this toolchain.
virtual SanitizerMask getSupportedSanitizers() const;
};
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Types.h b/contrib/llvm/tools/clang/include/clang/Driver/Types.h
index dd95d65..22122c7 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Types.h
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Types.h
@@ -63,6 +63,9 @@ namespace types {
/// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
bool isCXX(ID Id);
+ /// Is this LLVM IR.
+ bool isLLVMIR(ID Id);
+
/// isCuda - Is this a CUDA input.
bool isCuda(ID Id);
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/Commit.h b/contrib/llvm/tools/clang/include/clang/Edit/Commit.h
index 5cc5b9c..ac4bb47 100644
--- a/contrib/llvm/tools/clang/include/clang/Edit/Commit.h
+++ b/contrib/llvm/tools/clang/include/clang/Edit/Commit.h
@@ -134,12 +134,6 @@ private:
SourceLocation *MacroBegin = nullptr) const;
bool isAtEndOfMacroExpansion(SourceLocation loc,
SourceLocation *MacroEnd = nullptr) const;
-
- StringRef copyString(StringRef str) {
- char *buf = StrAlloc.Allocate<char>(str.size());
- std::memcpy(buf, str.data(), str.size());
- return StringRef(buf, str.size());
- }
};
}
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h b/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h
index 150a5b41..b6ec8b8 100644
--- a/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h
+++ b/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h
@@ -10,9 +10,11 @@
#ifndef LLVM_CLANG_EDIT_EDITEDSOURCE_H
#define LLVM_CLANG_EDIT_EDITEDSOURCE_H
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Edit/FileOffset.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Allocator.h"
#include <map>
@@ -39,14 +41,18 @@ class EditedSource {
typedef std::map<FileOffset, FileEdit> FileEditsTy;
FileEditsTy FileEdits;
- llvm::DenseMap<unsigned, SourceLocation> ExpansionToArgMap;
+ llvm::DenseMap<unsigned, llvm::TinyPtrVector<IdentifierInfo*>>
+ ExpansionToArgMap;
+ SmallVector<std::pair<SourceLocation, IdentifierInfo*>, 2>
+ CurrCommitMacroArgExps;
+ IdentifierTable IdentTable;
llvm::BumpPtrAllocator StrAlloc;
public:
EditedSource(const SourceManager &SM, const LangOptions &LangOpts,
const PPConditionalDirectiveRecord *PPRec = nullptr)
- : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec),
+ : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), IdentTable(LangOpts),
StrAlloc() { }
const SourceManager &getSourceManager() const { return SourceMgr; }
@@ -62,11 +68,7 @@ public:
void applyRewrites(EditsReceiver &receiver);
void clearRewrites();
- StringRef copyString(StringRef str) {
- char *buf = StrAlloc.Allocate<char>(str.size());
- std::memcpy(buf, str.data(), str.size());
- return StringRef(buf, str.size());
- }
+ StringRef copyString(StringRef str) { return str.copy(StrAlloc); }
StringRef copyString(const Twine &twine);
private:
@@ -80,6 +82,12 @@ private:
StringRef getSourceText(FileOffset BeginOffs, FileOffset EndOffs,
bool &Invalid);
FileEditsTy::iterator getActionForOffset(FileOffset Offs);
+ void deconstructMacroArgLoc(SourceLocation Loc,
+ SourceLocation &ExpansionLoc,
+ IdentifierInfo *&II);
+
+ void startingCommit();
+ void finishedCommit();
};
}
diff --git a/contrib/llvm/tools/clang/include/clang/Format/Format.h b/contrib/llvm/tools/clang/include/clang/Format/Format.h
index f8c8c37..6d051e0 100644
--- a/contrib/llvm/tools/clang/include/clang/Format/Format.h
+++ b/contrib/llvm/tools/clang/include/clang/Format/Format.h
@@ -43,33 +43,70 @@ struct FormatStyle {
/// \brief The extra indent or outdent of access modifiers, e.g. \c public:.
int AccessModifierOffset;
+ /// \brief Different styles for aligning after open brackets.
+ enum BracketAlignmentStyle {
+ /// \brief Align parameters on the open bracket, e.g.:
+ /// \code
+ /// someLongFunction(argument1,
+ /// argument2);
+ /// \endcode
+ BAS_Align,
+ /// \brief Don't align, instead use \c ContinuationIndentWidth, e.g.:
+ /// \code
+ /// someLongFunction(argument1,
+ /// argument2);
+ /// \endcode
+ BAS_DontAlign,
+ /// \brief Always break after an open bracket, if the parameters don't fit
+ /// on a single line, e.g.:
+ /// \code
+ /// someLongFunction(
+ /// argument1, argument2);
+ /// \endcode
+ BAS_AlwaysBreak,
+ };
+
/// \brief If \c true, horizontally aligns arguments after an open bracket.
///
/// This applies to round brackets (parentheses), angle brackets and square
- /// brackets. This will result in formattings like
- /// \code
- /// someLongFunction(argument1,
- /// argument2);
- /// \endcode
- bool AlignAfterOpenBracket;
+ /// brackets.
+ BracketAlignmentStyle AlignAfterOpenBracket;
/// \brief If \c true, aligns consecutive assignments.
///
/// This will align the assignment operators of consecutive lines. This
/// will result in formattings like
/// \code
- /// int aaaa = 12;
- /// int b = 23;
- /// int ccc = 23;
+ /// int aaaa = 12;
+ /// int b = 23;
+ /// int ccc = 23;
/// \endcode
bool AlignConsecutiveAssignments;
+ /// \brief If \c true, aligns consecutive declarations.
+ ///
+ /// This will align the declaration names of consecutive lines. This
+ /// will result in formattings like
+ /// \code
+ /// int aaaa = 12;
+ /// float b = 23;
+ /// std::string ccc = 23;
+ /// \endcode
+ bool AlignConsecutiveDeclarations;
+
/// \brief If \c true, aligns escaped newlines as far left as possible.
/// Otherwise puts them into the right-most column.
bool AlignEscapedNewlinesLeft;
/// \brief If \c true, horizontally align operands of binary and ternary
/// expressions.
+ ///
+ /// Specifically, this aligns operands of a single expression that needs to be
+ /// split over multiple lines, e.g.:
+ /// \code
+ /// int aaa = bbbbbbbbbbbbbbb +
+ /// ccccccccccccccc;
+ /// \endcode
bool AlignOperands;
/// \brief If \c true, aligns trailing comments.
@@ -119,13 +156,33 @@ struct FormatStyle {
DRTBS_None,
/// Always break after the return type.
DRTBS_All,
- /// Always break after the return types of top level functions.
+ /// Always break after the return types of top-level functions.
DRTBS_TopLevel,
};
- /// \brief The function definition return type breaking style to use.
+ /// \brief Different ways to break after the function definition or
+ /// declaration return type.
+ enum ReturnTypeBreakingStyle {
+ /// Break after return type automatically.
+ /// \c PenaltyReturnTypeOnItsOwnLine is taken into account.
+ RTBS_None,
+ /// Always break after the return type.
+ RTBS_All,
+ /// Always break after the return types of top-level functions.
+ RTBS_TopLevel,
+ /// Always break after the return type of function definitions.
+ RTBS_AllDefinitions,
+ /// Always break after the return type of top-level definitions.
+ RTBS_TopLevelDefinitions,
+ };
+
+ /// \brief The function definition return type breaking style to use. This
+ /// option is deprecated and is retained for backwards compatibility.
DefinitionReturnTypeBreakingStyle AlwaysBreakAfterDefinitionReturnType;
+ /// \brief The function declaration return type breaking style to use.
+ ReturnTypeBreakingStyle AlwaysBreakAfterReturnType;
+
/// \brief If \c true, always break before multiline string literals.
///
/// This flag is mean to make cases where there are multiple multiline strings
@@ -169,19 +226,55 @@ struct FormatStyle {
/// Like ``Attach``, but break before braces on enum, function, and record
/// definitions.
BS_Mozilla,
- /// Like \c Attach, but break before function definitions, and 'else'.
+ /// Like \c Attach, but break before function definitions, 'catch', and 'else'.
BS_Stroustrup,
/// Always break before braces.
BS_Allman,
/// Always break before braces and add an extra level of indentation to
/// braces of control statements, not to those of class, function
/// or other definitions.
- BS_GNU
+ BS_GNU,
+ /// Like ``Attach``, but break before functions.
+ BS_WebKit,
+ /// Configure each individual brace in \c BraceWrapping.
+ BS_Custom
};
/// \brief The brace breaking style to use.
BraceBreakingStyle BreakBeforeBraces;
+ /// \brief Precise control over the wrapping of braces.
+ struct BraceWrappingFlags {
+ /// \brief Wrap class definitions.
+ bool AfterClass;
+ /// \brief Wrap control statements (if/for/while/switch/..).
+ bool AfterControlStatement;
+ /// \brief Wrap enum definitions.
+ bool AfterEnum;
+ /// \brief Wrap function definitions.
+ bool AfterFunction;
+ /// \brief Wrap namespace definitions.
+ bool AfterNamespace;
+ /// \brief Wrap ObjC definitions (@autoreleasepool, interfaces, ..).
+ bool AfterObjCDeclaration;
+ /// \brief Wrap struct definitions.
+ bool AfterStruct;
+ /// \brief Wrap union definitions.
+ bool AfterUnion;
+ /// \brief Wrap before \c catch.
+ bool BeforeCatch;
+ /// \brief Wrap before \c else.
+ bool BeforeElse;
+ /// \brief Indent the wrapped braces themselves.
+ bool IndentBraces;
+ };
+
+ /// \brief Control of individual brace wrapping cases.
+ ///
+ /// If \c BreakBeforeBraces is set to \c custom, use this to specify how each
+ /// individual brace case should be handled. Otherwise, this is ignored.
+ BraceWrappingFlags BraceWrapping;
+
/// \brief If \c true, ternary operators will be placed after line breaks.
bool BreakBeforeTernaryOperators;
@@ -189,6 +282,9 @@ struct FormatStyle {
/// the commas with the colon.
bool BreakConstructorInitializersBeforeComma;
+ /// \brief Break after each annotation on a field in Java files.
+ bool BreakAfterJavaFieldAnnotations;
+
/// \brief The column limit.
///
/// A column limit of \c 0 means that there is no column limit. In this case,
@@ -250,13 +346,57 @@ struct FormatStyle {
///
/// These are expected to be macros of the form:
/// \code
- /// FOREACH(<variable-declaration>, ...)
- /// <loop-body>
+ /// FOREACH(<variable-declaration>, ...)
+ /// <loop-body>
+ /// \endcode
+ ///
+ /// In the .clang-format configuration file, this can be configured like:
+ /// \code
+ /// ForEachMacros: ['RANGES_FOR', 'FOREACH']
/// \endcode
///
/// For example: BOOST_FOREACH.
std::vector<std::string> ForEachMacros;
+ /// \brief See documentation of \c IncludeCategories.
+ struct IncludeCategory {
+ /// \brief The regular expression that this category matches.
+ std::string Regex;
+ /// \brief The priority to assign to this category.
+ int Priority;
+ bool operator==(const IncludeCategory &Other) const {
+ return Regex == Other.Regex && Priority == Other.Priority;
+ }
+ };
+
+ /// \brief Regular expressions denoting the different #include categories used
+ /// for ordering #includes.
+ ///
+ /// These regular expressions are matched against the filename of an include
+ /// (including the <> or "") in order. The value belonging to the first
+ /// matching regular expression is assigned and #includes are sorted first
+ /// according to increasing category number and then alphabetically within
+ /// each category.
+ ///
+ /// If none of the regular expressions match, INT_MAX is assigned as
+ /// category. The main header for a source file automatically gets category 0.
+ /// so that it is generally kept at the beginning of the #includes
+ /// (http://llvm.org/docs/CodingStandards.html#include-style). However, you
+ /// can also assign negative priorities if you have certain headers that
+ /// always need to be first.
+ ///
+ /// To configure this in the .clang-format file, use:
+ /// \code
+ /// IncludeCategories:
+ /// - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ /// Priority: 2
+ /// - Regex: '^(<|"(gtest|isl|json)/)'
+ /// Priority: 3
+ /// - Regex: '.*'
+ /// Priority: 1
+ /// \endcode
+ std::vector<IncludeCategory> IncludeCategories;
+
/// \brief Indent case labels one level from the switch statement.
///
/// When \c false, use the same indentation level as for the switch statement.
@@ -287,7 +427,9 @@ struct FormatStyle {
LK_JavaScript,
/// Should be used for Protocol Buffers
/// (https://developers.google.com/protocol-buffers/).
- LK_Proto
+ LK_Proto,
+ /// Should be used for TableGen code.
+ LK_TableGen
};
/// \brief Language, this format style is targeted at.
@@ -355,9 +497,15 @@ struct FormatStyle {
PAS_Middle
};
- /// Pointer and reference alignment style.
+ /// \brief Pointer and reference alignment style.
PointerAlignmentStyle PointerAlignment;
+ /// \brief If true, clang-format will attempt to re-flow comments.
+ bool ReflowComments;
+
+ /// \brief If true, clang-format will sort #includes.
+ bool SortIncludes;
+
/// \brief If \c true, a space may be inserted after C style casts.
bool SpaceAfterCStyleCast;
@@ -444,6 +592,7 @@ struct FormatStyle {
return AccessModifierOffset == R.AccessModifierOffset &&
AlignAfterOpenBracket == R.AlignAfterOpenBracket &&
AlignConsecutiveAssignments == R.AlignConsecutiveAssignments &&
+ AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations &&
AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft &&
AlignOperands == R.AlignOperands &&
AlignTrailingComments == R.AlignTrailingComments &&
@@ -457,8 +606,7 @@ struct FormatStyle {
AllowShortIfStatementsOnASingleLine ==
R.AllowShortIfStatementsOnASingleLine &&
AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine &&
- AlwaysBreakAfterDefinitionReturnType ==
- R.AlwaysBreakAfterDefinitionReturnType &&
+ AlwaysBreakAfterReturnType == R.AlwaysBreakAfterReturnType &&
AlwaysBreakBeforeMultilineStrings ==
R.AlwaysBreakBeforeMultilineStrings &&
AlwaysBreakTemplateDeclarations ==
@@ -470,8 +618,8 @@ struct FormatStyle {
BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators &&
BreakConstructorInitializersBeforeComma ==
R.BreakConstructorInitializersBeforeComma &&
- ColumnLimit == R.ColumnLimit &&
- CommentPragmas == R.CommentPragmas &&
+ BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations &&
+ ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas &&
ConstructorInitializerAllOnOneLineOrOnePerLine ==
R.ConstructorInitializerAllOnOneLineOrOnePerLine &&
ConstructorInitializerIndentWidth ==
@@ -483,6 +631,7 @@ struct FormatStyle {
ExperimentalAutoDetectBinPacking ==
R.ExperimentalAutoDetectBinPacking &&
ForEachMacros == R.ForEachMacros &&
+ IncludeCategories == R.IncludeCategories &&
IndentCaseLabels == R.IndentCaseLabels &&
IndentWidth == R.IndentWidth && Language == R.Language &&
IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
@@ -513,8 +662,7 @@ struct FormatStyle {
SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses &&
SpacesInParentheses == R.SpacesInParentheses &&
SpacesInSquareBrackets == R.SpacesInSquareBrackets &&
- Standard == R.Standard &&
- TabWidth == R.TabWidth &&
+ Standard == R.Standard && TabWidth == R.TabWidth &&
UseTab == R.UseTab;
}
};
@@ -569,6 +717,13 @@ std::error_code parseConfiguration(StringRef Text, FormatStyle *Style);
/// \brief Gets configuration in a YAML string.
std::string configurationAsText(const FormatStyle &Style);
+/// \brief Returns the replacements necessary to sort all #include blocks that
+/// are affected by 'Ranges'.
+tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
+ ArrayRef<tooling::Range> Ranges,
+ StringRef FileName,
+ unsigned *Cursor = nullptr);
+
/// \brief Reformats the given \p Ranges in the file \p ID.
///
/// Each range is extended on either end to its next bigger logic unit, i.e.
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
index fa4bcf2..a5f7af5 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
@@ -719,7 +719,7 @@ public:
///
/// \param Filename - The AST file to load.
///
- /// \param PCHContainerOps - The PCHContainerOperations to use for loading and
+ /// \param PCHContainerRdr - The PCHContainerOperations to use for loading and
/// creating modules.
/// \param Diags - The diagnostics engine to use for reporting errors; its
/// lifetime is expected to extend past that of the returned ASTUnit.
@@ -728,8 +728,8 @@ public:
static std::unique_ptr<ASTUnit> LoadFromASTFile(
const std::string &Filename, const PCHContainerReader &PCHContainerRdr,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls = false,
- ArrayRef<RemappedFile> RemappedFiles = None,
+ const FileSystemOptions &FileSystemOpts, bool UseDebugInfo = false,
+ bool OnlyLocalDecls = false, ArrayRef<RemappedFile> RemappedFiles = None,
bool CaptureDiagnostics = false, bool AllowPCHWithCompilerErrors = false,
bool UserFilesAreVolatile = false);
@@ -737,14 +737,15 @@ private:
/// \brief Helper function for \c LoadFromCompilerInvocation() and
/// \c LoadFromCommandLine(), which loads an AST from a compiler invocation.
///
- /// \param PrecompilePreamble Whether to precompile the preamble of this
- /// translation unit, to improve the performance of reparsing.
+ /// \param PrecompilePreambleAfterNParses After how many parses the preamble
+ /// of this translation unit should be precompiled, to improve the performance
+ /// of reparsing. Set to zero to disable preambles.
///
/// \returns \c true if a catastrophic failure occurred (which means that the
/// \c ASTUnit itself is invalid), or \c false otherwise.
bool LoadFromCompilerInvocation(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- bool PrecompilePreamble);
+ unsigned PrecompilePreambleAfterNParses);
public:
@@ -783,7 +784,8 @@ public:
ASTFrontendAction *Action = nullptr, ASTUnit *Unit = nullptr,
bool Persistent = true, StringRef ResourceFilesPath = StringRef(),
bool OnlyLocalDecls = false, bool CaptureDiagnostics = false,
- bool PrecompilePreamble = false, bool CacheCodeCompletionResults = false,
+ unsigned PrecompilePreambleAfterNParses = 0,
+ bool CacheCodeCompletionResults = false,
bool IncludeBriefCommentsInCodeCompletion = false,
bool UserFilesAreVolatile = false,
std::unique_ptr<ASTUnit> *ErrAST = nullptr);
@@ -805,8 +807,9 @@ public:
static std::unique_ptr<ASTUnit> LoadFromCompilerInvocation(
CompilerInvocation *CI,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool OnlyLocalDecls = false,
- bool CaptureDiagnostics = false, bool PrecompilePreamble = false,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr,
+ bool OnlyLocalDecls = false, bool CaptureDiagnostics = false,
+ unsigned PrecompilePreambleAfterNParses = 0,
TranslationUnitKind TUKind = TU_Complete,
bool CacheCodeCompletionResults = false,
bool IncludeBriefCommentsInCodeCompletion = false,
@@ -827,6 +830,8 @@ public:
///
/// \param ResourceFilesPath - The path to the compiler resource files.
///
+ /// \param ModuleFormat - If provided, uses the specific module format.
+ ///
/// \param ErrAST - If non-null and parsing failed without any AST to return
/// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
/// mainly to allow the caller to see the diagnostics.
@@ -840,11 +845,13 @@ public:
bool OnlyLocalDecls = false, bool CaptureDiagnostics = false,
ArrayRef<RemappedFile> RemappedFiles = None,
bool RemappedFilesKeepOriginalName = true,
- bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete,
+ unsigned PrecompilePreambleAfterNParses = 0,
+ TranslationUnitKind TUKind = TU_Complete,
bool CacheCodeCompletionResults = false,
bool IncludeBriefCommentsInCodeCompletion = false,
bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false,
bool UserFilesAreVolatile = false, bool ForSerialization = false,
+ llvm::Optional<StringRef> ModuleFormat = llvm::None,
std::unique_ptr<ASTUnit> *ErrAST = nullptr);
/// \brief Reparse the source files using the same command-line options that
@@ -909,7 +916,7 @@ public:
GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
{ return nullptr; }
bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
- { return 0; };
+ { return 0; }
};
} // namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
index 803d023..d9f6ab7 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
@@ -48,6 +48,9 @@ CODEGENOPT(DisableLLVMOpts , 1, 0) ///< Don't run any optimizations, for use i
///< getting .bc files that correspond to the
///< internal state before optimizations are
///< done.
+CODEGENOPT(DisableLLVMPasses , 1, 0) ///< Don't run any LLVM IR passes to get
+ ///< the pristine IR generated by the
+ ///< frontend.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls.
CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what
@@ -57,6 +60,7 @@ CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what
CODEGENOPT(EmitGcovArcs , 1, 0) ///< Emit coverage data files, aka. GCDA.
CODEGENOPT(EmitGcovNotes , 1, 0) ///< Emit coverage "notes" files, aka GCNO.
CODEGENOPT(EmitOpenCLArgMetadata , 1, 0) ///< Emit OpenCL kernel arg metadata.
+CODEGENOPT(EmulatedTLS , 1, 0) ///< Set when -femulated-tls is enabled.
/// \brief FP_CONTRACT mode (on/off/fast).
ENUM_CODEGENOPT(FPContractMode, FPContractModeKind, 2, FPC_On)
CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables
@@ -69,6 +73,11 @@ CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions t
///< be generated.
CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the
///< compile step.
+CODEGENOPT(EmitFunctionSummary, 1, 0) ///< Set when -flto=thin is enabled on the
+ ///< compile step.
+CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can
+ ///< be used with an incremental
+ ///< linker.
CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants.
CODEGENOPT(MergeFunctions , 1, 0) ///< Set when -fmerge-functions is enabled.
CODEGENOPT(MSVolatile , 1, 0) ///< Set when /volatile:ms is enabled.
@@ -114,6 +123,7 @@ CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
///< MemorySanitizer
CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection
///< in MemorySanitizer
+CODEGENOPT(SanitizeCfiCrossDso, 1, 0) ///< Enable cross-dso support in CFI.
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
///< instrumentation.
CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage
@@ -127,6 +137,7 @@ CODEGENOPT(SanitizeCoverage8bitCounters, 1, 0) ///< Use 8-bit frequency counters
CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float.
CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition.
+CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers
CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled.
CODEGENOPT(UnitAtATime , 1, 1) ///< Unused. For mirroring GCC optimization
///< selection.
@@ -145,7 +156,7 @@ CODEGENOPT(UseRegisterSizedBitfieldAccess , 1, 0)
CODEGENOPT(VerifyModule , 1, 1) ///< Control whether the module should be run
///< through the LLVM Verifier.
-CODEGENOPT(StackRealignment , 1, 0) ///< Control whether to permit stack
+CODEGENOPT(StackRealignment , 1, 0) ///< Control whether to force stack
///< realignment.
CODEGENOPT(UseInitArray , 1, 0) ///< Control whether to use .init_array or
///< .ctors.
@@ -156,6 +167,13 @@ VALUE_CODEGENOPT(StackProbeSize , 32, 4096) ///< Overrides default stack
CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information
///< in debug info.
+CODEGENOPT(DebugTypeExtRefs, 1, 0) ///< Whether or not debug info should contain
+ ///< external references to a PCH or module.
+
+CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should
+ ///< contain explicit imports for
+ ///< anonymous namespaces
+
CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists.
/// The user specified number of registers to be used for integral arguments,
@@ -168,9 +186,17 @@ VALUE_CODEGENOPT(SSPBufferSize, 32, 0)
/// The kind of generated debug info.
ENUM_CODEGENOPT(DebugInfo, DebugInfoKind, 3, NoDebugInfo)
-/// Dwarf version.
+/// Tune the debug info for this debugger.
+ENUM_CODEGENOPT(DebuggerTuning, DebuggerKind, 2, DebuggerKindDefault)
+
+/// Dwarf version. Version zero indicates to LLVM that no DWARF should be
+/// emitted.
VALUE_CODEGENOPT(DwarfVersion, 3, 0)
+/// Whether we should emit CodeView debug information. It's possible to emit
+/// CodeView and DWARF into the same object.
+CODEGENOPT(EmitCodeView, 1, 0)
+
/// The kind of inlining to perform.
ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NoInlining)
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h
index 53246bc..7550e6f 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h
@@ -16,6 +16,7 @@
#include "clang/Basic/Sanitizers.h"
#include "llvm/Support/Regex.h"
+#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -81,6 +82,13 @@ public:
FullDebugInfo /// Generate complete debug info.
};
+ enum DebuggerKind {
+ DebuggerKindDefault,
+ DebuggerKindGDB,
+ DebuggerKindLLDB,
+ DebuggerKindSCE
+ };
+
enum TLSModel {
GeneralDynamicTLSModel,
LocalDynamicTLSModel,
@@ -120,6 +128,8 @@ public:
/// non-empty.
std::string DwarfDebugFlags;
+ std::map<std::string, std::string> DebugPrefixMap;
+
/// The ABI to use for passing floating point arguments.
std::string FloatABI;
@@ -127,7 +137,7 @@ public:
std::string LimitFloatPrecision;
/// The name of the bitcode file to link before optzns.
- std::string LinkBitcodeFile;
+ std::vector<std::pair<unsigned, std::string>> LinkBitcodeFiles;
/// The user provided name for the "main file", if non-empty. This is useful
/// in situations where the input file name does not match the original input
@@ -164,6 +174,13 @@ public:
/// Name of the profile file to use as input for -fprofile-instr-use
std::string InstrProfileInput;
+ /// Name of the function summary index file to use for ThinLTO function
+ /// importing.
+ std::string ThinLTOIndexFile;
+
+ /// The EABI version to use
+ std::string EABIVersion;
+
/// A list of file names passed with -fcuda-include-gpubinary options to
/// forward to CUDA runtime back-end for incorporating them into host-side
/// object file.
@@ -201,6 +218,9 @@ public:
/// Set of sanitizer checks that trap rather than diagnose.
SanitizerSet SanitizeTrap;
+ /// \brief A list of all -fno-builtin-* function names (e.g., memset).
+ std::vector<std::string> NoBuiltinFuncs;
+
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
@@ -210,6 +230,14 @@ public:
#include "clang/Frontend/CodeGenOptions.def"
CodeGenOptions();
+
+ /// \brief Is this a libc/libm function that is no longer recognized as a
+ /// builtin because a -fno-builtin-* option has been specified?
+ bool isNoBuiltinFunc(const char *Name) const;
+
+ const std::vector<std::string> &getNoBuiltinFuncs() const {
+ return NoBuiltinFuncs;
+ }
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
index 45e5ed1..83eed2c 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
@@ -78,6 +78,9 @@ class CompilerInstance : public ModuleLoader {
/// The target being compiled for.
IntrusiveRefCntPtr<TargetInfo> Target;
+ /// Auxiliary Target info.
+ IntrusiveRefCntPtr<TargetInfo> AuxTarget;
+
/// The virtual file system.
IntrusiveRefCntPtr<vfs::FileSystem> VirtualFileSystem;
@@ -126,13 +129,6 @@ class CompilerInstance : public ModuleLoader {
/// along with the module map
llvm::DenseMap<const IdentifierInfo *, Module *> KnownModules;
- /// \brief Module names that have an override for the target file.
- llvm::StringMap<std::string> ModuleFileOverrides;
-
- /// \brief Module files that we've explicitly loaded via \ref loadModuleFile,
- /// and their dependencies.
- llvm::StringSet<> ExplicitlyLoadedModuleFiles;
-
/// \brief The location of the module-import keyword for the last module
/// import.
SourceLocation LastModuleImportLoc;
@@ -355,10 +351,19 @@ public:
return *Target;
}
- /// Replace the current diagnostics engine.
+ /// Replace the current Target.
void setTarget(TargetInfo *Value);
/// }
+ /// @name AuxTarget Info
+ /// {
+
+ TargetInfo *getAuxTarget() const { return AuxTarget.get(); }
+
+ /// Replace the current AuxTarget.
+ void setAuxTarget(TargetInfo *Value);
+
+ /// }
/// @name Virtual File System
/// {
@@ -650,6 +655,7 @@ public:
StringRef Path, StringRef Sysroot, bool DisablePCHValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
const PCHContainerReader &PCHContainerRdr,
+ ArrayRef<IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
void *DeserializationListener, bool OwnDeserializationListener,
bool Preamble, bool UseGlobalModuleIndex);
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h
index 7d12548..0b4a1e5 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h
@@ -72,7 +72,7 @@ public:
~CompilerInvocationBase();
CompilerInvocationBase(const CompilerInvocationBase &X);
-
+
LangOptions *getLangOpts() { return LangOpts.get(); }
const LangOptions *getLangOpts() const { return LangOpts.get(); }
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h
index 2221b54..129b534 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h
@@ -47,6 +47,9 @@ public:
/// must contain at least one entry.
std::vector<std::string> Targets;
+ /// A list of filenames to be used as extra dependencies for every target.
+ std::vector<std::string> ExtraDeps;
+
/// \brief The file to write GraphViz-formatted header dependencies to.
std::string DOTOutputFile;
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h
index 84a0f50..c372fdd 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h
@@ -117,13 +117,15 @@ private:
void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints,
const SourceManager &SM);
+ void emitSingleMacroExpansion(SourceLocation Loc,
+ DiagnosticsEngine::Level Level,
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager &SM);
void emitMacroExpansions(SourceLocation Loc,
DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> Hints,
- const SourceManager &SM,
- unsigned &MacroDepth,
- unsigned OnMacroInst = 0);
+ const SourceManager &SM);
public:
/// \brief Emit a diagnostic.
///
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
index c3aa226..c800a51 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H
#include "clang/Frontend/CommandLineSourceLoc.h"
+#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Sema/CodeCompleteOptions.h"
#include "llvm/ADT/StringRef.h"
#include <string>
@@ -91,7 +92,7 @@ class FrontendInputFile {
bool IsSystem;
public:
- FrontendInputFile() : Buffer(nullptr), Kind(IK_None) { }
+ FrontendInputFile() : Buffer(nullptr), Kind(IK_None), IsSystem(false) { }
FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false)
: File(File.str()), Buffer(nullptr), Kind(Kind), IsSystem(IsSystem) { }
FrontendInputFile(llvm::MemoryBuffer *buffer, InputKind Kind,
@@ -147,6 +148,10 @@ public:
///< dumps in AST dumps.
unsigned ASTDumpLookups : 1; ///< Whether we include lookup table
///< dumps in AST dumps.
+ unsigned BuildingImplicitModule : 1; ///< Whether we are performing an
+ ///< implicit module build.
+ unsigned ModulesEmbedAllFiles : 1; ///< Whether we should embed all used
+ ///< files into the PCM file.
CodeCompleteOptions CodeCompleteOpts;
@@ -234,6 +239,9 @@ public:
/// The list of plugins to load.
std::vector<std::string> Plugins;
+ /// The list of module file extensions.
+ std::vector<IntrusiveRefCntPtr<ModuleFileExtension>> ModuleFileExtensions;
+
/// \brief The list of module map files to load before processing the input.
std::vector<std::string> ModuleMapFiles;
@@ -241,6 +249,9 @@ public:
/// processing the input.
std::vector<std::string> ModuleFiles;
+ /// \brief The list of files to embed into the compiled module file.
+ std::vector<std::string> ModulesEmbedFiles;
+
/// \brief The list of AST files to merge.
std::vector<std::string> ASTMergeFiles;
@@ -251,7 +262,10 @@ public:
/// \brief File name of the file that will provide record layouts
/// (in the format produced by -fdump-record-layouts).
std::string OverrideRecordLayoutsFile;
-
+
+ /// \brief Auxiliary triple for CUDA compilation.
+ std::string AuxTriple;
+
public:
FrontendOptions() :
DisableFree(false), RelocatablePCH(false), ShowHelp(false),
@@ -260,6 +274,7 @@ public:
FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false),
SkipFunctionBodies(false), UseGlobalModuleIndex(true),
GenerateGlobalModuleIndex(true), ASTDumpDecls(false), ASTDumpLookups(false),
+ BuildingImplicitModule(false), ModulesEmbedAllFiles(false),
ARCMTAction(ARCMT_None), ObjCMTAction(ObjCMT_None),
ProgramAction(frontend::ParseSyntaxOnly)
{}
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h b/contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h
index 868ea68..67c36cf 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h
@@ -27,14 +27,12 @@ namespace clang {
class ASTConsumer;
class CodeGenOptions;
class DiagnosticsEngine;
-class HeaderSearchOptions;
-class LangOptions;
-class PreprocessorOptions;
-class TargetOptions;
+class CompilerInstance;
struct PCHBuffer {
- bool IsComplete;
+ uint64_t Signature;
llvm::SmallVector<char, 0> Data;
+ bool IsComplete;
};
/// This abstract interface provides operations for creating
@@ -49,9 +47,7 @@ public:
/// PCHGenerator that produces a wrapper file format containing a
/// serialized AST bitstream.
virtual std::unique_ptr<ASTConsumer> CreatePCHContainerGenerator(
- DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO,
- const PreprocessorOptions &PPO, const TargetOptions &TO,
- const LangOptions &LO, const std::string &MainFileName,
+ CompilerInstance &CI, const std::string &MainFileName,
const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
std::shared_ptr<PCHBuffer> Buffer) const = 0;
};
@@ -78,9 +74,7 @@ class RawPCHContainerWriter : public PCHContainerWriter {
/// Return an ASTConsumer that can be chained with a
/// PCHGenerator that writes the module to a flat file.
std::unique_ptr<ASTConsumer> CreatePCHContainerGenerator(
- DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO,
- const PreprocessorOptions &PPO, const TargetOptions &TO,
- const LangOptions &LO, const std::string &MainFileName,
+ CompilerInstance &CI, const std::string &MainFileName,
const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
std::shared_ptr<PCHBuffer> Buffer) const override;
};
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h
index 92e99d3..3db362b 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h
@@ -81,43 +81,43 @@ protected:
/// \brief Visit the start of a diagnostic block.
virtual std::error_code visitStartOfDiagnostic() {
return std::error_code();
- };
+ }
/// \brief Visit the end of a diagnostic block.
- virtual std::error_code visitEndOfDiagnostic() { return std::error_code(); };
+ virtual std::error_code visitEndOfDiagnostic() { return std::error_code(); }
/// \brief Visit a category. This associates the category \c ID to a \c Name.
virtual std::error_code visitCategoryRecord(unsigned ID, StringRef Name) {
return std::error_code();
- };
+ }
/// \brief Visit a flag. This associates the flag's \c ID to a \c Name.
virtual std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) {
return std::error_code();
- };
+ }
/// \brief Visit a diagnostic.
virtual std::error_code
visitDiagnosticRecord(unsigned Severity, const Location &Location,
unsigned Category, unsigned Flag, StringRef Message) {
return std::error_code();
- };
+ }
/// \brief Visit a filename. This associates the file's \c ID to a \c Name.
virtual std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
unsigned Timestamp,
StringRef Name) {
return std::error_code();
- };
+ }
/// \brief Visit a fixit hint.
virtual std::error_code
visitFixitRecord(const Location &Start, const Location &End, StringRef Text) {
return std::error_code();
- };
+ }
/// \brief Visit a source range.
virtual std::error_code visitSourceRangeRecord(const Location &Start,
const Location &End) {
return std::error_code();
- };
+ }
/// \brief Visit the version of the set of diagnostics.
virtual std::error_code visitVersionRecord(unsigned Version) {
return std::error_code();
- };
+ }
};
} // end serialized_diags namespace
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
index aa567b4..a5f667e 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
@@ -148,6 +148,9 @@ public:
/// AttachHeaderIncludeGen - Create a header include list generator, and attach
/// it to the given preprocessor.
///
+/// \param ExtraHeaders - If not empty, will write the header filenames, just
+/// like they were included during a regular preprocessing. Useful for
+/// implicit include dependencies, like sanitizer blacklists.
/// \param ShowAllHeaders - If true, show all header information instead of just
/// headers following the predefines buffer. This is useful for making sure
/// includes mentioned on the command line are also reported, but differs from
@@ -156,7 +159,9 @@ public:
/// information to, instead of writing to stderr.
/// \param ShowDepth - Whether to indent to show the nesting of the includes.
/// \param MSStyle - Whether to print in cl.exe /showIncludes style.
-void AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders = false,
+void AttachHeaderIncludeGen(Preprocessor &PP,
+ const std::vector<std::string> &ExtraHeaders,
+ bool ShowAllHeaders = false,
StringRef OutputPath = "",
bool ShowDepth = true, bool MSStyle = false);
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h
index 9edf119..20c4bb0 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h
@@ -158,6 +158,8 @@ public:
/// SearchPath at which the file was found. This only differs from the
/// Filename for framework includes.
///
+ /// \param RequestingModule The module in which the lookup was performed.
+ ///
/// \param SuggestedModule If non-null, and the file found is semantically
/// part of a known module, this will be set to the module that should
/// be imported instead of preprocessing/parsing the file found.
@@ -172,6 +174,7 @@ public:
const FileEntry *LookupFile(StringRef &Filename, HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
+ Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework,
bool &HasBeenMapped,
@@ -182,6 +185,7 @@ private:
StringRef Filename, HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
+ Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemHeader) const;
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
index 4c13380..6d592e1 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
@@ -49,7 +49,8 @@ struct HeaderFileInfo {
/// SrcMgr::CharacteristicKind.
unsigned DirInfo : 2;
- /// \brief Whether this header file info was supplied by an external source.
+ /// \brief Whether this header file info was supplied by an external source,
+ /// and has not changed since.
unsigned External : 1;
/// \brief Whether this header is part of a module.
@@ -58,10 +59,6 @@ struct HeaderFileInfo {
/// \brief Whether this header is part of the module that we are building.
unsigned isCompilingModuleHeader : 1;
- /// \brief Whether this header is part of the module that we are building.
- /// This is an instance of ModuleMap::ModuleHeaderRole.
- unsigned HeaderRole : 2;
-
/// \brief Whether this structure is considered to already have been
/// "resolved", meaning that it was loaded from the external source.
unsigned Resolved : 1;
@@ -75,7 +72,7 @@ struct HeaderFileInfo {
/// those framework headers.
unsigned IndexHeaderMapHeader : 1;
- /// \brief Whether this file had been looked up as a header.
+ /// \brief Whether this file has been looked up as a header.
unsigned IsValid : 1;
/// \brief The number of times the file has been included already.
@@ -105,7 +102,6 @@ struct HeaderFileInfo {
HeaderFileInfo()
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
- HeaderRole(ModuleMap::NormalHeader),
Resolved(false), IndexHeaderMapHeader(false), IsValid(0),
NumIncludes(0), ControllingMacroID(0), ControllingMacro(nullptr) {}
@@ -120,16 +116,6 @@ struct HeaderFileInfo {
return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
ControllingMacroID;
}
-
- /// \brief Get the HeaderRole properly typed.
- ModuleMap::ModuleHeaderRole getHeaderRole() const {
- return static_cast<ModuleMap::ModuleHeaderRole>(HeaderRole);
- }
-
- /// \brief Set the HeaderRole properly typed.
- void setHeaderRole(ModuleMap::ModuleHeaderRole Role) {
- HeaderRole = Role;
- }
};
/// \brief An external source of header file information, which may supply
@@ -189,7 +175,7 @@ class HeaderSearch {
/// \brief All of the preprocessor-specific data about files that are
/// included, indexed by the FileEntry's UID.
- std::vector<HeaderFileInfo> FileInfo;
+ mutable std::vector<HeaderFileInfo> FileInfo;
/// Keeps track of each lookup performed by LookupFile.
struct LookupFileCacheInfo {
@@ -396,7 +382,8 @@ public:
const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
- ModuleMap::KnownHeader *SuggestedModule, bool SkipCache = false);
+ Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
+ bool SkipCache = false);
/// \brief Look up a subframework for the specified \#include file.
///
@@ -405,11 +392,9 @@ public:
/// HIToolbox is a subframework within Carbon.framework. If so, return
/// the FileEntry for the designated file, otherwise return null.
const FileEntry *LookupSubframeworkHeader(
- StringRef Filename,
- const FileEntry *RelativeFileEnt,
- SmallVectorImpl<char> *SearchPath,
- SmallVectorImpl<char> *RelativePath,
- ModuleMap::KnownHeader *SuggestedModule);
+ StringRef Filename, const FileEntry *RelativeFileEnt,
+ SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
+ Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule);
/// \brief Look up the specified framework name in our framework cache.
/// \returns The DirectoryEntry it is in if we know, null otherwise.
@@ -575,20 +560,51 @@ private:
/// of the given search directory.
void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir);
- /// \brief Return the HeaderFileInfo structure for the specified FileEntry.
- const HeaderFileInfo &getFileInfo(const FileEntry *FE) const {
- return const_cast<HeaderSearch*>(this)->getFileInfo(FE);
- }
+ /// \brief Find and suggest a usable module for the given file.
+ ///
+ /// \return \c true if the file can be used, \c false if we are not permitted to
+ /// find this file due to requirements from \p RequestingModule.
+ bool findUsableModuleForHeader(const FileEntry *File,
+ const DirectoryEntry *Root,
+ Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule,
+ bool IsSystemHeaderDir);
+
+ /// \brief Find and suggest a usable module for the given file, which is part of
+ /// the specified framework.
+ ///
+ /// \return \c true if the file can be used, \c false if we are not permitted to
+ /// find this file due to requirements from \p RequestingModule.
+ bool findUsableModuleForFrameworkHeader(
+ const FileEntry *File, StringRef FrameworkDir, Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework);
+
+ /// \brief Look up the file with the specified name and determine its owning
+ /// module.
+ const FileEntry *
+ getFileAndSuggestModule(StringRef FileName, const DirectoryEntry *Dir,
+ bool IsSystemHeaderDir, Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule);
public:
/// \brief Retrieve the module map.
ModuleMap &getModuleMap() { return ModMap; }
+ /// \brief Retrieve the module map.
+ const ModuleMap &getModuleMap() const { return ModMap; }
+
unsigned header_file_size() const { return FileInfo.size(); }
- /// \brief Get a \c HeaderFileInfo structure for the specified \c FileEntry,
- /// if one exists.
- bool tryGetFileInfo(const FileEntry *FE, HeaderFileInfo &Result) const;
+ /// \brief Return the HeaderFileInfo structure for the specified FileEntry,
+ /// in preparation for updating it in some way.
+ HeaderFileInfo &getFileInfo(const FileEntry *FE);
+
+ /// \brief Return the HeaderFileInfo structure for the specified FileEntry,
+ /// if it has ever been filled in.
+ /// \param WantExternal Whether the caller wants purely-external header file
+ /// info (where \p External is true).
+ const HeaderFileInfo *getExistingFileInfo(const FileEntry *FE,
+ bool WantExternal = true) const;
// Used by external tools
typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator;
@@ -665,9 +681,6 @@ private:
/// named directory.
LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir,
bool IsSystem, bool IsFramework);
-
- /// \brief Return the HeaderFileInfo structure for the specified FileEntry.
- HeaderFileInfo &getFileInfo(const FileEntry *FE);
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h
index 12f0447..915dbf7 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h
@@ -20,10 +20,11 @@
namespace clang {
namespace frontend {
- /// IncludeDirGroup - Identifiers the group a include entry belongs to, which
- /// represents its relative positive in the search list. A \#include of a ""
- /// path starts at the -iquote group, then searches the Angled group, then
- /// searches the system group, etc.
+ /// IncludeDirGroup - Identifies the group an include Entry belongs to,
+ /// representing its relative positive in the search list.
+ /// \#include directives whose paths are enclosed by string quotes ("")
+ /// start searching at the Quoted group (specified by '-iquote'),
+ /// then search the Angled group, then the System group, etc.
enum IncludeDirGroup {
Quoted = 0, ///< '\#include ""' paths, added by 'gcc -iquote'.
Angled, ///< Paths for '\#include <>' added by '-I'.
@@ -140,7 +141,7 @@ public:
/// \brief The set of macro names that should be ignored for the purposes
/// of computing the module hash.
- llvm::SetVector<std::string> ModulesIgnoreMacros;
+ llvm::SmallSetVector<std::string, 16> ModulesIgnoreMacros;
/// \brief The set of user-provided virtual filesystem overlay files.
std::vector<std::string> VFSOverlayFiles;
@@ -168,7 +169,9 @@ public:
/// \brief Whether to validate system input files when a module is loaded.
unsigned ModulesValidateSystemHeaders : 1;
-public:
+ /// Whether the module includes debug information (-gmodules).
+ unsigned UseDebugInfo : 1;
+
HeaderSearchOptions(StringRef _Sysroot = "/")
: Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(0),
ImplicitModuleMaps(0), ModuleMapFileHomeIsCwd(0),
@@ -177,7 +180,8 @@ public:
UseBuiltinIncludes(true), UseStandardSystemIncludes(true),
UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false),
ModulesValidateOncePerBuildSession(false),
- ModulesValidateSystemHeaders(false) {}
+ ModulesValidateSystemHeaders(false),
+ UseDebugInfo(false) {}
/// AddPath - Add the \p Path path to the specified \p Group list.
void AddPath(StringRef Path, frontend::IncludeDirGroup Group,
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
index 5210e3f..d568614 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
@@ -166,6 +166,7 @@ public:
bool hadError() const { return HadError; }
bool isAscii() const { return Kind == tok::char_constant; }
bool isWide() const { return Kind == tok::wide_char_constant; }
+ bool isUTF8() const { return Kind == tok::utf8_char_constant; }
bool isUTF16() const { return Kind == tok::utf16_char_constant; }
bool isUTF32() const { return Kind == tok::utf32_char_constant; }
bool isMultiChar() const { return IsMultiChar; }
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
index 8b82a5b..320645e 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
@@ -158,17 +158,16 @@ public:
/// \brief Set the specified list of identifiers as the argument list for
/// this macro.
- void setArgumentList(IdentifierInfo *const *List, unsigned NumArgs,
+ void setArgumentList(ArrayRef<IdentifierInfo *> List,
llvm::BumpPtrAllocator &PPAllocator) {
assert(ArgumentList == nullptr && NumArguments == 0 &&
"Argument list already set!");
- if (NumArgs == 0)
+ if (List.empty())
return;
- NumArguments = NumArgs;
- ArgumentList = PPAllocator.Allocate<IdentifierInfo *>(NumArgs);
- for (unsigned i = 0; i != NumArgs; ++i)
- ArgumentList[i] = List[i];
+ NumArguments = List.size();
+ ArgumentList = PPAllocator.Allocate<IdentifierInfo *>(List.size());
+ std::copy(List.begin(), List.end(), ArgumentList);
}
/// Arguments - The list of arguments for a function-like macro. This can be
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h
index 0b03c4a..155943e 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h
@@ -35,6 +35,22 @@ class DiagnosticConsumer;
class DiagnosticsEngine;
class HeaderSearch;
class ModuleMapParser;
+
+/// \brief A mechanism to observe the actions of the module map parser as it
+/// reads module map files.
+class ModuleMapCallbacks {
+public:
+ virtual ~ModuleMapCallbacks() {}
+
+ /// \brief Called when a module map file has been read.
+ ///
+ /// \param FileStart A SourceLocation referring to the start of the file's
+ /// contents.
+ /// \param File The file itself.
+ /// \param IsSystem Whether this is a module map from a system include path.
+ virtual void moduleMapFileRead(SourceLocation FileStart,
+ const FileEntry &File, bool IsSystem) {}
+};
class ModuleMap {
SourceManager &SourceMgr;
@@ -42,6 +58,8 @@ class ModuleMap {
const LangOptions &LangOpts;
const TargetInfo *Target;
HeaderSearch &HeaderInfo;
+
+ llvm::SmallVector<std::unique_ptr<ModuleMapCallbacks>, 1> Callbacks;
/// \brief The directory used for Clang-supplied, builtin include headers,
/// such as "stdint.h".
@@ -94,6 +112,13 @@ public:
KnownHeader() : Storage(nullptr, NormalHeader) { }
KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { }
+ friend bool operator==(const KnownHeader &A, const KnownHeader &B) {
+ return A.Storage == B.Storage;
+ }
+ friend bool operator!=(const KnownHeader &A, const KnownHeader &B) {
+ return A.Storage != B.Storage;
+ }
+
/// \brief Retrieve the module the header is stored in.
Module *getModule() const { return Storage.getPointer(); }
@@ -224,6 +249,10 @@ private:
KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File,
SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs);
+ /// \brief Given that \p File is not in the Headers map, look it up within
+ /// umbrella directories and find or create a module for it.
+ KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File);
+
/// \brief A convenience method to determine if \p File is (possibly nested)
/// in an umbrella directory.
bool isHeaderInUmbrellaDirs(const FileEntry *File) {
@@ -263,6 +292,11 @@ public:
BuiltinIncludeDir = Dir;
}
+ /// \brief Add a module map callback.
+ void addModuleMapCallbacks(std::unique_ptr<ModuleMapCallbacks> Callback) {
+ Callbacks.push_back(std::move(Callback));
+ }
+
/// \brief Retrieve the module that owns the given header file, if any.
///
/// \param File The header file that is likely to be included.
@@ -272,6 +306,14 @@ public:
/// that no module owns this header file.
KnownHeader findModuleForHeader(const FileEntry *File);
+ /// \brief Retrieve all the modules that contain the given header file. This
+ /// may not include umbrella modules, nor information from external sources,
+ /// if they have not yet been inferred / loaded.
+ ///
+ /// Typically, \ref findModuleForHeader should be used instead, as it picks
+ /// the preferred module for the header.
+ ArrayRef<KnownHeader> findAllModulesForHeader(const FileEntry *File) const;
+
/// \brief Reports errors if a module must not include a specific file.
///
/// \param RequestingModule The module including a file.
@@ -436,7 +478,7 @@ public:
/// \brief Adds this header to the given module.
/// \param Role The role of the header wrt the module.
void addHeader(Module *Mod, Module::Header Header,
- ModuleHeaderRole Role);
+ ModuleHeaderRole Role, bool Imported = false);
/// \brief Marks this header as being excluded from the given module.
void excludeHeader(Module *Mod, Module::Header Header);
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
index 3803533..68b8f1c 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
@@ -201,19 +201,19 @@ public:
PragmaMessageKind Kind, StringRef Str) {
}
- /// \brief Callback invoked when a \#pragma gcc dianostic push directive
+ /// \brief Callback invoked when a \#pragma gcc diagnostic push directive
/// is read.
virtual void PragmaDiagnosticPush(SourceLocation Loc,
StringRef Namespace) {
}
- /// \brief Callback invoked when a \#pragma gcc dianostic pop directive
+ /// \brief Callback invoked when a \#pragma gcc diagnostic pop directive
/// is read.
virtual void PragmaDiagnosticPop(SourceLocation Loc,
StringRef Namespace) {
}
- /// \brief Callback invoked when a \#pragma gcc dianostic directive is read.
+ /// \brief Callback invoked when a \#pragma gcc diagnostic directive is read.
virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
diag::Severity mapping, StringRef Str) {}
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h
index 70fcfda..274f0da 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Pragma.h
@@ -76,7 +76,7 @@ public:
/// used to ignore particular pragmas.
class EmptyPragmaHandler : public PragmaHandler {
public:
- EmptyPragmaHandler();
+ explicit EmptyPragmaHandler(StringRef Name = StringRef());
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken) override;
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
index 53367ab..87b8ce1 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
@@ -32,12 +32,12 @@ namespace clang {
}
/// \brief Allocates memory within a Clang preprocessing record.
-void* operator new(size_t bytes, clang::PreprocessingRecord& PR,
- unsigned alignment = 8) throw();
+void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
+ unsigned alignment = 8) LLVM_NOEXCEPT;
/// \brief Frees memory allocated in a Clang preprocessing record.
void operator delete(void *ptr, clang::PreprocessingRecord &PR,
- unsigned) throw();
+ unsigned) LLVM_NOEXCEPT;
namespace clang {
class MacroDefinitionRecord;
@@ -98,27 +98,25 @@ namespace clang {
// Only allow allocation of preprocessed entities using the allocator
// in PreprocessingRecord or by doing a placement new.
- void* operator new(size_t bytes, PreprocessingRecord& PR,
- unsigned alignment = 8) throw() {
+ void *operator new(size_t bytes, PreprocessingRecord &PR,
+ unsigned alignment = 8) LLVM_NOEXCEPT {
return ::operator new(bytes, PR, alignment);
}
-
- void* operator new(size_t bytes, void* mem) throw() {
- return mem;
- }
-
- void operator delete(void* ptr, PreprocessingRecord& PR,
- unsigned alignment) throw() {
+
+ void *operator new(size_t bytes, void *mem) LLVM_NOEXCEPT { return mem; }
+
+ void operator delete(void *ptr, PreprocessingRecord &PR,
+ unsigned alignment) LLVM_NOEXCEPT {
return ::operator delete(ptr, PR, alignment);
}
-
- void operator delete(void*, std::size_t) throw() { }
- void operator delete(void*, void*) throw() { }
-
+
+ void operator delete(void *, std::size_t) LLVM_NOEXCEPT {}
+ void operator delete(void *, void *) LLVM_NOEXCEPT {}
+
private:
// Make vanilla 'new' and 'delete' illegal for preprocessed entities.
- void* operator new(size_t bytes) throw();
- void operator delete(void* data) throw();
+ void *operator new(size_t bytes) LLVM_NOEXCEPT;
+ void operator delete(void *data) LLVM_NOEXCEPT;
};
/// \brief Records the presence of a preprocessor directive.
@@ -525,13 +523,13 @@ namespace clang {
};
} // end namespace clang
-inline void* operator new(size_t bytes, clang::PreprocessingRecord& PR,
- unsigned alignment) throw() {
+inline void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
+ unsigned alignment) LLVM_NOEXCEPT {
return PR.Allocate(bytes, alignment);
}
-inline void operator delete(void* ptr, clang::PreprocessingRecord& PR,
- unsigned) throw() {
+inline void operator delete(void *ptr, clang::PreprocessingRecord &PR,
+ unsigned) LLVM_NOEXCEPT {
PR.Deallocate(ptr);
}
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
index b2f58ead..f6154b6 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
@@ -24,7 +24,6 @@
#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/PTHLexer.h"
-#include "clang/Lex/PTHManager.h"
#include "clang/Lex/TokenLexer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -57,6 +56,7 @@ class CodeCompletionHandler;
class DirectoryLookup;
class PreprocessingRecord;
class ModuleLoader;
+class PTHManager;
class PreprocessorOptions;
/// \brief Stores token information for comparing actual tokens with
@@ -98,6 +98,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
DiagnosticsEngine *Diags;
LangOptions &LangOpts;
const TargetInfo *Target;
+ const TargetInfo *AuxTarget;
FileManager &FileMgr;
SourceManager &SourceMgr;
std::unique_ptr<ScratchBuffer> ScratchBuf;
@@ -656,7 +657,10 @@ public:
///
/// \param Target is owned by the caller and must remain valid for the
/// lifetime of the preprocessor.
- void Initialize(const TargetInfo &Target);
+ /// \param AuxTarget is owned by the caller and must remain valid for
+ /// the lifetime of the preprocessor.
+ void Initialize(const TargetInfo &Target,
+ const TargetInfo *AuxTarget = nullptr);
/// \brief Initialize the preprocessor to parse a model file
///
@@ -678,6 +682,7 @@ public:
const LangOptions &getLangOpts() const { return LangOpts; }
const TargetInfo &getTargetInfo() const { return *Target; }
+ const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
FileManager &getFileManager() const { return FileMgr; }
SourceManager &getSourceManager() const { return SourceMgr; }
HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
index 3119736..fdeed44 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
@@ -175,7 +175,7 @@ private:
/// macro, other active macros, and anything left on the current physical
/// source line of the expanded buffer. Handle this by returning the
/// first token on the next line.
- void HandleMicrosoftCommentPaste(Token &Tok);
+ void HandleMicrosoftCommentPaste(Token &Tok, SourceLocation OpLoc);
/// \brief If \p loc is a FileID and points inside the current macro
/// definition, returns the appropriate source location pointing at the
diff --git a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
index 8719555..00885a5 100644
--- a/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
+++ b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
@@ -163,6 +163,7 @@ class Parser : public CodeCompletionHandler {
std::unique_ptr<PragmaHandler> MSConstSeg;
std::unique_ptr<PragmaHandler> MSCodeSeg;
std::unique_ptr<PragmaHandler> MSSection;
+ std::unique_ptr<PragmaHandler> MSRuntimeChecks;
std::unique_ptr<PragmaHandler> OptimizeHandler;
std::unique_ptr<PragmaHandler> LoopHintHandler;
std::unique_ptr<PragmaHandler> UnrollHintHandler;
@@ -501,6 +502,10 @@ private:
void HandlePragmaAlign();
/// \brief Handle the annotation token produced for
+ /// #pragma clang __debug dump...
+ void HandlePragmaDump();
+
+ /// \brief Handle the annotation token produced for
/// #pragma weak id...
void HandlePragmaWeak();
@@ -1236,6 +1241,7 @@ private:
ParsingDeclSpec &DS,
AccessSpecifier AS);
+ void SkipFunctionBody();
Decl *ParseFunctionDefinition(ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
LateParsedAttrList *LateParsedAttrs = nullptr);
@@ -1251,12 +1257,12 @@ private:
DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
ParsedAttributes &prefixAttrs);
+ class ObjCTypeParamListScope;
ObjCTypeParamList *parseObjCTypeParamList();
ObjCTypeParamList *parseObjCTypeParamListOrProtocolRefs(
- SourceLocation &lAngleLoc,
- SmallVectorImpl<IdentifierLocPair> &protocolIdents,
- SourceLocation &rAngleLoc,
- bool mayBeProtocolList = true);
+ ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc,
+ SmallVectorImpl<IdentifierLocPair> &protocolIdents,
+ SourceLocation &rAngleLoc, bool mayBeProtocolList = true);
void HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
BalancedDelimiterTracker &T,
@@ -1578,7 +1584,9 @@ private:
SourceLocation Loc, bool ConvertToBoolean);
//===--------------------------------------------------------------------===//
- // C++ types
+ // C++ Coroutines
+
+ ExprResult ParseCoyieldExpression();
//===--------------------------------------------------------------------===//
// C99 6.7.8: Initialization.
@@ -1636,13 +1644,22 @@ private:
/// A SmallVector of types.
typedef SmallVector<ParsedType, 12> TypeVector;
- StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr);
+ StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr,
+ bool AllowOpenMPStandalone = false);
+ enum AllowedContsructsKind {
+ /// \brief Allow any declarations, statements, OpenMP directives.
+ ACK_Any,
+ /// \brief Allow only statements and non-standalone OpenMP directives.
+ ACK_StatementsOpenMPNonStandalone,
+ /// \brief Allow statements and all executable OpenMP directives
+ ACK_StatementsOpenMPAnyExecutable
+ };
StmtResult
- ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
+ ParseStatementOrDeclaration(StmtVector &Stmts, AllowedContsructsKind Allowed,
SourceLocation *TrailingElseLoc = nullptr);
StmtResult ParseStatementOrDeclarationAfterAttributes(
StmtVector &Stmts,
- bool OnlyStatement,
+ AllowedContsructsKind Allowed,
SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs);
StmtResult ParseExprStatement();
@@ -1670,7 +1687,8 @@ private:
StmtResult ParseReturnStatement();
StmtResult ParseAsmStatement(bool &msAsm);
StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc);
- StmtResult ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement,
+ StmtResult ParsePragmaLoopHint(StmtVector &Stmts,
+ AllowedContsructsKind Allowed,
SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs);
@@ -2164,8 +2182,7 @@ private:
void MaybeParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
SourceLocation *End = nullptr) {
const auto &LO = getLangOpts();
- if ((LO.MicrosoftExt || LO.Borland || LO.CUDA) &&
- Tok.is(tok::kw___declspec))
+ if (LO.DeclSpecKeyword && Tok.is(tok::kw___declspec))
ParseMicrosoftDeclSpecs(Attrs, End);
}
void ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
@@ -2334,8 +2351,8 @@ private:
void DiagnoseUnexpectedNamespace(NamedDecl *Context);
- Decl *ParseNamespace(unsigned Context, SourceLocation &DeclEnd,
- SourceLocation InlineLoc = SourceLocation());
+ DeclGroupPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd,
+ SourceLocation InlineLoc = SourceLocation());
void ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
std::vector<IdentifierInfo*>& Ident,
std::vector<SourceLocation>& NamespaceLoc,
@@ -2388,9 +2405,13 @@ private:
LateParsedAttrList &LateAttrs);
void MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(Declarator &D,
VirtSpecifiers &VS);
- void ParseCXXClassMemberDeclaration(AccessSpecifier AS, AttributeList *Attr,
- const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
- ParsingDeclRAIIObject *DiagsFromTParams = nullptr);
+ DeclGroupPtrTy ParseCXXClassMemberDeclaration(
+ AccessSpecifier AS, AttributeList *Attr,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ ParsingDeclRAIIObject *DiagsFromTParams = nullptr);
+ DeclGroupPtrTy ParseCXXClassMemberDeclarationWithPragmas(
+ AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs,
+ DeclSpec::TST TagType, Decl *TagDecl);
void ParseConstructorInitializer(Decl *ConstructorDecl);
MemInitResult ParseMemInitializer(Decl *ConstructorDecl);
void HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
@@ -2432,11 +2453,13 @@ private:
bool AllowScopeSpecifier);
/// \brief Parses declarative or executable directive.
///
- /// \param StandAloneAllowed true if allowed stand-alone directives,
- /// false - otherwise
+ /// \param Allowed ACK_Any, if any directives are allowed,
+ /// ACK_StatementsOpenMPAnyExecutable - if any executable directives are
+ /// allowed, ACK_StatementsOpenMPNonStandalone - if only non-standalone
+ /// executable directives are allowed.
///
StmtResult
- ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed);
+ ParseOpenMPDeclarativeOrExecutableDirective(AllowedContsructsKind Allowed);
/// \brief Parses clause of kind \a CKind for directive of a kind \a Kind.
///
/// \param DKind Kind of current directive.
@@ -2471,7 +2494,9 @@ private:
///
/// \param Kind Kind of current clause.
///
- OMPClause *ParseOpenMPVarListClause(OpenMPClauseKind Kind);
+ OMPClause *ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind Kind);
+
public:
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
bool AllowDestructorName,
@@ -2550,6 +2575,14 @@ private:
//===--------------------------------------------------------------------===//
// Modules
DeclGroupPtrTy ParseModuleImport(SourceLocation AtLoc);
+ bool parseMisplacedModuleImport();
+ bool tryParseMisplacedModuleImport() {
+ tok::TokenKind Kind = Tok.getKind();
+ if (Kind == tok::annot_module_begin || Kind == tok::annot_module_end ||
+ Kind == tok::annot_module_include)
+ return parseMisplacedModuleImport();
+ return false;
+ }
//===--------------------------------------------------------------------===//
// C++11/G++: Type Traits [Type-Traits.html in the GCC manual]
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h
index 4d18633..e32781d 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h
@@ -16,11 +16,11 @@
#define LLVM_CLANG_SEMA_ATTRIBUTELIST_H
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/VersionTuple.h"
#include "clang/Sema/Ownership.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Support/Allocator.h"
#include <cassert>
@@ -137,11 +137,9 @@ private:
AttributeList *NextInPool;
/// Arguments, if any, are stored immediately following the object.
- ArgsUnion *getArgsBuffer() {
- return reinterpret_cast<ArgsUnion*>(this+1);
- }
+ ArgsUnion *getArgsBuffer() { return reinterpret_cast<ArgsUnion *>(this + 1); }
ArgsUnion const *getArgsBuffer() const {
- return reinterpret_cast<ArgsUnion const *>(this+1);
+ return reinterpret_cast<ArgsUnion const *>(this + 1);
}
enum AvailabilitySlot {
@@ -466,7 +464,7 @@ public:
bool hasVariadicArg() const;
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
bool diagnoseLangOpts(class Sema &S) const;
- bool existsInTarget(const llvm::Triple &T) const;
+ bool existsInTarget(const TargetInfo &Target) const;
bool isKnownToGCC() const;
/// \brief If the parsed attribute has a semantic equivalent, and it would
@@ -559,8 +557,10 @@ public:
/// Create a new pool for a factory.
AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {}
+ AttributePool(const AttributePool &) = delete;
+
/// Move the given pool's allocations to this pool.
- AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) {
+ AttributePool(AttributePool &&pool) : Factory(pool.Factory), Head(pool.Head) {
pool.Head = nullptr;
}
@@ -854,7 +854,8 @@ enum AttributeDeclKind {
ExpectedStructOrUnionOrTypedef,
ExpectedStructOrTypedef,
ExpectedObjectiveCInterfaceOrProtocol,
- ExpectedKernelFunction
+ ExpectedKernelFunction,
+ ExpectedFunctionWithProtoType
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h
index e43496f..fc7713c 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h
@@ -10,6 +10,8 @@
#ifndef LLVM_CLANG_SEMA_CODECOMPLETEOPTIONS_H
#define LLVM_CLANG_SEMA_CODECOMPLETEOPTIONS_H
+namespace clang {
+
/// Options controlling the behavior of code completion.
class CodeCompleteOptions {
public:
@@ -33,5 +35,7 @@ public:
{ }
};
+} // namespace clang
+
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
index 41d4900..064d37b 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
@@ -31,7 +31,6 @@
#include "clang/Lex/Token.h"
#include "clang/Sema/AttributeList.h"
#include "clang/Sema/Ownership.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
@@ -41,14 +40,10 @@ namespace clang {
class CXXRecordDecl;
class TypeLoc;
class LangOptions;
- class DiagnosticsEngine;
class IdentifierInfo;
class NamespaceAliasDecl;
class NamespaceDecl;
- class NestedNameSpecifier;
- class NestedNameSpecifierLoc;
class ObjCDeclSpec;
- class Preprocessor;
class Sema;
class Declarator;
struct TemplateIdAnnotation;
@@ -70,8 +65,8 @@ class CXXScopeSpec {
NestedNameSpecifierLocBuilder Builder;
public:
- const SourceRange &getRange() const { return Range; }
- void setRange(const SourceRange &R) { Range = R; }
+ SourceRange getRange() const { return Range; }
+ void setRange(SourceRange R) { Range = R; }
void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); }
void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); }
SourceLocation getBeginLoc() const { return Range.getBegin(); }
@@ -301,6 +296,7 @@ public:
static const TST TST_decltype_auto = clang::TST_decltype_auto;
static const TST TST_underlyingType = clang::TST_underlyingType;
static const TST TST_auto = clang::TST_auto;
+ static const TST TST_auto_type = clang::TST_auto_type;
static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
static const TST TST_atomic = clang::TST_atomic;
static const TST TST_error = clang::TST_error;
@@ -341,6 +337,7 @@ private:
unsigned TypeAltiVecPixel : 1;
unsigned TypeAltiVecBool : 1;
unsigned TypeSpecOwned : 1;
+ unsigned TypeSpecPipe : 1;
// type-qualifiers
unsigned TypeQualifiers : 4; // Bitwise OR of TQ.
@@ -389,6 +386,7 @@ private:
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
SourceLocation FS_forceinlineLoc;
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc;
+ SourceLocation TQ_pipeLoc;
WrittenBuiltinSpecs writtenBS;
void SaveWrittenBuiltinSpecs();
@@ -424,6 +422,7 @@ public:
TypeAltiVecPixel(false),
TypeAltiVecBool(false),
TypeSpecOwned(false),
+ TypeSpecPipe(false),
TypeQualifiers(TQ_unspecified),
FS_inline_specified(false),
FS_forceinline_specified(false),
@@ -477,6 +476,7 @@ public:
bool isTypeAltiVecBool() const { return TypeAltiVecBool; }
bool isTypeSpecOwned() const { return TypeSpecOwned; }
bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
+ bool isTypeSpecPipe() const { return TypeSpecPipe; }
ParsedType getRepAsType() const {
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
@@ -493,7 +493,7 @@ public:
CXXScopeSpec &getTypeSpecScope() { return TypeScope; }
const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; }
- const SourceRange &getSourceRange() const LLVM_READONLY { return Range; }
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
@@ -512,7 +512,8 @@ public:
void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; }
bool containsPlaceholderType() const {
- return TypeSpecType == TST_auto || TypeSpecType == TST_decltype_auto;
+ return (TypeSpecType == TST_auto || TypeSpecType == TST_auto_type ||
+ TypeSpecType == TST_decltype_auto);
}
bool hasTagDefinition() const;
@@ -535,6 +536,7 @@ public:
SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; }
+ SourceLocation getPipeLoc() const { return TQ_pipeLoc; }
/// \brief Clear out all of the type qualifiers.
void ClearTypeQualifiers() {
@@ -543,6 +545,7 @@ public:
TQ_restrictLoc = SourceLocation();
TQ_volatileLoc = SourceLocation();
TQ_atomicLoc = SourceLocation();
+ TQ_pipeLoc = SourceLocation();
}
// function-specifier
@@ -646,6 +649,9 @@ public:
bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID,
const PrintingPolicy &Policy);
+ bool SetTypePipe(bool isPipe, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
bool SetTypeSpecError();
void UpdateDeclRep(Decl *Rep) {
assert(isDeclRep((TST) TypeSpecType));
@@ -742,8 +748,7 @@ public:
/// Finish - This does final analysis of the declspec, issuing diagnostics for
/// things like "_Imaginary" (lacking an FP type). After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
- void Finish(DiagnosticsEngine &D, Preprocessor &PP,
- const PrintingPolicy &Policy);
+ void Finish(Sema &S, const PrintingPolicy &Policy);
const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
return writtenBS;
@@ -1085,7 +1090,7 @@ typedef SmallVector<Token, 4> CachedTokens;
/// This is intended to be a small value object.
struct DeclaratorChunk {
enum {
- Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren
+ Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren, Pipe
} Kind;
/// Loc - The place where this type was defined.
@@ -1255,8 +1260,11 @@ struct DeclaratorChunk {
/// any.
unsigned MutableLoc;
- /// \brief The location of the keyword introducing the spec, if any.
- unsigned ExceptionSpecLoc;
+ /// \brief The beginning location of the exception specification, if any.
+ unsigned ExceptionSpecLocBeg;
+
+ /// \brief The end location of the exception specification, if any.
+ unsigned ExceptionSpecLocEnd;
/// Params - This is a pointer to a new[]'d array of ParamInfo objects that
/// describe the parameters specified by this function declarator. null if
@@ -1323,8 +1331,16 @@ struct DeclaratorChunk {
return SourceLocation::getFromRawEncoding(RParenLoc);
}
- SourceLocation getExceptionSpecLoc() const {
- return SourceLocation::getFromRawEncoding(ExceptionSpecLoc);
+ SourceLocation getExceptionSpecLocBeg() const {
+ return SourceLocation::getFromRawEncoding(ExceptionSpecLocBeg);
+ }
+
+ SourceLocation getExceptionSpecLocEnd() const {
+ return SourceLocation::getFromRawEncoding(ExceptionSpecLocEnd);
+ }
+
+ SourceRange getExceptionSpecRange() const {
+ return SourceRange(getExceptionSpecLocBeg(), getExceptionSpecLocEnd());
}
/// \brief Retrieve the location of the ref-qualifier, if any.
@@ -1402,6 +1418,13 @@ struct DeclaratorChunk {
}
};
+ struct PipeTypeInfo : TypeInfoCommon {
+ /// The access writes.
+ unsigned AccessWrites : 3;
+
+ void destroy() {}
+ };
+
union {
TypeInfoCommon Common;
PointerTypeInfo Ptr;
@@ -1410,6 +1433,7 @@ struct DeclaratorChunk {
FunctionTypeInfo Fun;
BlockPointerTypeInfo Cls;
MemberPointerTypeInfo Mem;
+ PipeTypeInfo PipeInfo;
};
void destroy() {
@@ -1421,6 +1445,7 @@ struct DeclaratorChunk {
case DeclaratorChunk::Array: return Arr.destroy();
case DeclaratorChunk::MemberPointer: return Mem.destroy();
case DeclaratorChunk::Paren: return;
+ case DeclaratorChunk::Pipe: return PipeInfo.destroy();
}
}
@@ -1496,7 +1521,7 @@ struct DeclaratorChunk {
SourceLocation RestrictQualifierLoc,
SourceLocation MutableLoc,
ExceptionSpecificationType ESpecType,
- SourceLocation ESpecLoc,
+ SourceRange ESpecRange,
ParsedType *Exceptions,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
@@ -1519,6 +1544,17 @@ struct DeclaratorChunk {
return I;
}
+ /// \brief Return a DeclaratorChunk for a block.
+ static DeclaratorChunk getPipe(unsigned TypeQuals,
+ SourceLocation Loc) {
+ DeclaratorChunk I;
+ I.Kind = Pipe;
+ I.Loc = Loc;
+ I.Cls.TypeQuals = TypeQuals;
+ I.Cls.AttrList = 0;
+ return I;
+ }
+
static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
unsigned TypeQuals,
SourceLocation Loc) {
@@ -1704,7 +1740,7 @@ public:
}
/// \brief Get the source range that spans this declarator.
- const SourceRange &getSourceRange() const LLVM_READONLY { return Range; }
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
@@ -1724,7 +1760,7 @@ public:
/// given declspec, unless its location is invalid. Adopts the range start if
/// the current range start is invalid.
void ExtendWithDeclSpec(const DeclSpec &DS) {
- const SourceRange &SR = DS.getSourceRange();
+ SourceRange SR = DS.getSourceRange();
if (Range.getBegin().isInvalid())
Range.setBegin(SR.getBegin());
if (!SR.getEnd().isInvalid())
@@ -2019,6 +2055,7 @@ public:
case DeclaratorChunk::Array:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
return false;
}
llvm_unreachable("Invalid type chunk");
@@ -2197,6 +2234,9 @@ public:
/// redeclaration time if the decl is static.
bool isStaticMember();
+ /// Returns true if this declares a constructor or a destructor.
+ bool isCtorOrDtor();
+
void setRedeclaration(bool Val) { Redeclaration = Val; }
bool isRedeclaration() const { return Redeclaration; }
};
@@ -2251,6 +2291,13 @@ private:
SourceLocation LastLocation;
};
+enum class LambdaCaptureInitKind {
+ NoInit, //!< [a]
+ CopyInit, //!< [a = b], [a = {b}]
+ DirectInit, //!< [a(b)]
+ ListInit //!< [a{b}]
+};
+
/// \brief Represents a complete lambda introducer.
struct LambdaIntroducer {
/// \brief An individual capture in a lambda introducer.
@@ -2259,13 +2306,15 @@ struct LambdaIntroducer {
SourceLocation Loc;
IdentifierInfo *Id;
SourceLocation EllipsisLoc;
+ LambdaCaptureInitKind InitKind;
ExprResult Init;
ParsedType InitCaptureType;
LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc,
IdentifierInfo *Id, SourceLocation EllipsisLoc,
- ExprResult Init, ParsedType InitCaptureType)
- : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), Init(Init),
- InitCaptureType(InitCaptureType) {}
+ LambdaCaptureInitKind InitKind, ExprResult Init,
+ ParsedType InitCaptureType)
+ : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc),
+ InitKind(InitKind), Init(Init), InitCaptureType(InitCaptureType) {}
};
SourceRange Range;
@@ -2281,10 +2330,11 @@ struct LambdaIntroducer {
SourceLocation Loc,
IdentifierInfo* Id,
SourceLocation EllipsisLoc,
+ LambdaCaptureInitKind InitKind,
ExprResult Init,
ParsedType InitCaptureType) {
- Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, Init,
- InitCaptureType));
+ Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init,
+ InitCaptureType));
}
};
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
index ef3d2db..97f78f4 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
@@ -139,7 +139,7 @@ public:
/// be invoked multiple times; the external source should take care not to
/// introduce the same declarations repeatedly.
virtual void ReadUnusedLocalTypedefNameCandidates(
- llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {};
+ llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {}
/// \brief Read the set of referenced selectors known to the
/// external Sema source.
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
index 74de00f..d4f57b7 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
@@ -828,6 +828,9 @@ public:
/// \brief Initializer has a placeholder type which cannot be
/// resolved by initialization.
FK_PlaceholderType,
+ /// \brief Trying to take the address of a function that doesn't support
+ /// having its address taken.
+ FK_AddressOfUnaddressableFunction,
/// \brief List-copy-initialization chose an explicit constructor.
FK_ExplicitConstructor
};
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
index 5bfee8b..7efb19f 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
@@ -139,7 +139,7 @@ public:
Redecl(Redecl != Sema::NotForRedeclaration),
HideTags(true),
Diagnose(Redecl == Sema::NotForRedeclaration),
- AllowHidden(Redecl == Sema::ForRedeclaration),
+ AllowHidden(false),
Shadowed(false)
{
configure();
@@ -161,7 +161,7 @@ public:
Redecl(Redecl != Sema::NotForRedeclaration),
HideTags(true),
Diagnose(Redecl == Sema::NotForRedeclaration),
- AllowHidden(Redecl == Sema::ForRedeclaration),
+ AllowHidden(false),
Shadowed(false)
{
configure();
@@ -228,10 +228,11 @@ public:
/// \brief Determine whether this lookup is permitted to see hidden
/// declarations, such as those in modules that have not yet been imported.
- bool isHiddenDeclarationVisible() const {
- return AllowHidden || LookupKind == Sema::LookupTagName;
+ bool isHiddenDeclarationVisible(NamedDecl *ND) const {
+ return AllowHidden ||
+ (isForRedeclaration() && ND->isExternallyVisible());
}
-
+
/// Sets whether tag declarations should be hidden by non-tag
/// declarations during resolution. The default is true.
void setHideTags(bool Hide) {
@@ -302,7 +303,7 @@ public:
if (!D->isInIdentifierNamespace(IDNS))
return nullptr;
- if (isHiddenDeclarationVisible() || isVisible(getSema(), D))
+ if (isVisible(getSema(), D) || isHiddenDeclarationVisible(D))
return D;
return getAcceptableDeclSlow(D);
@@ -511,10 +512,10 @@ public:
/// \brief Change this lookup's redeclaration kind.
void setRedeclarationKind(Sema::RedeclarationKind RK) {
Redecl = RK;
- AllowHidden = (RK == Sema::ForRedeclaration);
configure();
}
+ void dump();
void print(raw_ostream &);
/// Suppress the diagnostics that would normally fire because of this
@@ -565,6 +566,11 @@ public:
{}
public:
+ Filter(Filter &&F)
+ : Results(F.Results), I(F.I), Changed(F.Changed),
+ CalledDone(F.CalledDone) {
+ F.CalledDone = true;
+ }
~Filter() {
assert(CalledDone &&
"LookupResult::Filter destroyed without done() call");
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h
index af7083a..d6daadc 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -102,29 +102,12 @@ public:
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
///
- /// \param isKindWeWant a predicate function that returns true if the passed
- /// declaration kind is one we are looking for. If NULL, all declarations
- /// are returned.
- ///
- /// \return an indication of whether the load succeeded or failed.
- ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Result) override;
-
- /// \brief Finds all declarations lexically contained within the given
- /// DeclContext.
- ///
- /// \return true if an error occurred
- ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
- SmallVectorImpl<Decl*> &Result) {
- return FindExternalLexicalDecls(DC, nullptr, Result);
- }
-
- template <typename DeclTy>
- ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC,
- SmallVectorImpl<Decl*> &Result) {
- return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
- }
+ /// \param IsKindWeWant a predicate function that returns true if the passed
+ /// declaration kind is one we are looking for.
+ void
+ FindExternalLexicalDecls(const DeclContext *DC,
+ llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Result) override;
/// \brief Get the decls that are contained in a file in the Offset/Length
/// range. \p Length can be 0 to indicate a point at \p Offset instead of
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
index 2007dcb..6243795 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
@@ -83,7 +83,8 @@ namespace clang {
ICK_TransparentUnionConversion, ///< Transparent Union Conversions
ICK_Writeback_Conversion, ///< Objective-C ARC writeback conversion
ICK_Zero_Event_Conversion, ///< Zero constant to event (OpenCL1.2 6.12.10)
- ICK_Num_Conversion_Kinds ///< The number of conversion kinds
+ ICK_C_Only_Conversion, ///< Conversions allowed in C, but not C++
+ ICK_Num_Conversion_Kinds, ///< The number of conversion kinds
};
/// ImplicitConversionRank - The rank of an implicit conversion
@@ -95,7 +96,9 @@ namespace clang {
ICR_Promotion, ///< Promotion
ICR_Conversion, ///< Conversion
ICR_Complex_Real_Conversion, ///< Complex <-> Real conversion
- ICR_Writeback_Conversion ///< ObjC ARC writeback conversion
+ ICR_Writeback_Conversion, ///< ObjC ARC writeback conversion
+ ICR_C_Conversion ///< Conversion only allowed in the C standard.
+ /// (e.g. void* to char*)
};
ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind);
@@ -567,8 +570,8 @@ namespace clang {
/// This conversion candidate is not viable because its result
/// type is not implicitly convertible to the desired type.
ovl_fail_bad_final_conversion,
-
- /// This conversion function template specialization candidate is not
+
+ /// This conversion function template specialization candidate is not
/// viable because the final conversion was not an exact match.
ovl_fail_final_conversion_not_exact,
@@ -579,7 +582,10 @@ namespace clang {
/// This candidate function was not viable because an enable_if
/// attribute disabled it.
- ovl_fail_enable_if
+ ovl_fail_enable_if,
+
+ /// This candidate was not viable because its address could not be taken.
+ ovl_fail_addr_not_available
};
/// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
index 15ee8a4..d13667e 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
@@ -89,40 +89,43 @@ protected:
public:
/// \brief What kind of scope we are describing.
///
- ScopeKind Kind;
+ ScopeKind Kind : 3;
/// \brief Whether this function contains a VLA, \@try, try, C++
/// initializer, or anything else that can't be jumped past.
- bool HasBranchProtectedScope;
+ bool HasBranchProtectedScope : 1;
/// \brief Whether this function contains any switches or direct gotos.
- bool HasBranchIntoScope;
+ bool HasBranchIntoScope : 1;
/// \brief Whether this function contains any indirect gotos.
- bool HasIndirectGoto;
+ bool HasIndirectGoto : 1;
/// \brief Whether a statement was dropped because it was invalid.
- bool HasDroppedStmt;
+ bool HasDroppedStmt : 1;
/// A flag that is set when parsing a method that must call super's
/// implementation, such as \c -dealloc, \c -finalize, or any method marked
/// with \c __attribute__((objc_requires_super)).
- bool ObjCShouldCallSuper;
+ bool ObjCShouldCallSuper : 1;
/// True when this is a method marked as a designated initializer.
- bool ObjCIsDesignatedInit;
+ bool ObjCIsDesignatedInit : 1;
/// This starts true for a method marked as designated initializer and will
/// be set to false if there is an invocation to a designated initializer of
/// the super class.
- bool ObjCWarnForNoDesignatedInitChain;
+ bool ObjCWarnForNoDesignatedInitChain : 1;
/// True when this is an initializer method not marked as a designated
/// initializer within a class that has at least one initializer marked as a
/// designated initializer.
- bool ObjCIsSecondaryInit;
+ bool ObjCIsSecondaryInit : 1;
/// This starts true for a secondary initializer method and will be set to
/// false if there is an invocation of an initializer on 'self'.
- bool ObjCWarnForNoInitDelegation;
+ bool ObjCWarnForNoInitDelegation : 1;
+
+ /// First 'return' statement in the current function.
+ SourceLocation FirstReturnLoc;
/// First C++ 'try' statement in the current function.
SourceLocation FirstCXXTryLoc;
@@ -142,6 +145,14 @@ public:
/// optimization, or if we need to infer a return type.
SmallVector<ReturnStmt*, 4> Returns;
+ /// \brief The promise object for this coroutine, if any.
+ VarDecl *CoroutinePromise;
+
+ /// \brief The list of coroutine control flow constructs (co_await, co_yield,
+ /// co_return) that occur within the function or block. Empty if and only if
+ /// this function or block is not (yet known to be) a coroutine.
+ SmallVector<Stmt*, 4> CoroutineStmts;
+
/// \brief The stack of currently active compound stamement scopes in the
/// function.
SmallVector<CompoundScopeInfo, 4> CompoundScopes;
@@ -153,7 +164,7 @@ public:
/// \brief A list of parameters which have the nonnull attribute and are
/// modified in the function.
- llvm::SmallPtrSet<const ParmVarDecl*, 8> ModifiedNonNullParams;
+ llvm::SmallPtrSet<const ParmVarDecl*, 8> ModifiedNonNullParams;
public:
/// Represents a simple identification of a weak object.
@@ -291,6 +302,9 @@ private:
/// Part of the implementation of -Wrepeated-use-of-weak.
WeakObjectUseMap WeakObjectUses;
+protected:
+ FunctionScopeInfo(const FunctionScopeInfo&) = default;
+
public:
/// Record that a weak object was accessed.
///
@@ -364,6 +378,9 @@ public:
};
class CapturingScopeInfo : public FunctionScopeInfo {
+protected:
+ CapturingScopeInfo(const CapturingScopeInfo&) = default;
+
public:
enum ImplicitCaptureStyle {
ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block,
@@ -549,7 +566,7 @@ public:
};
/// \brief Retains information about a block that is currently being parsed.
-class BlockScopeInfo : public CapturingScopeInfo {
+class BlockScopeInfo final : public CapturingScopeInfo {
public:
BlockDecl *TheDecl;
@@ -576,7 +593,7 @@ public:
};
/// \brief Retains information about a captured region.
-class CapturedRegionScopeInfo: public CapturingScopeInfo {
+class CapturedRegionScopeInfo final : public CapturingScopeInfo {
public:
/// \brief The CapturedDecl for this statement.
CapturedDecl *TheCapturedDecl;
@@ -617,7 +634,7 @@ public:
}
};
-class LambdaScopeInfo : public CapturingScopeInfo {
+class LambdaScopeInfo final : public CapturingScopeInfo {
public:
/// \brief The class that describes the lambda.
CXXRecordDecl *Lambda;
@@ -697,8 +714,6 @@ public:
Kind = SK_Lambda;
}
- ~LambdaScopeInfo() override;
-
/// \brief Note when all explicit captures have been added.
void finishedExplicitCaptures() {
NumExplicitCaptures = Captures.size();
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
index 7204433..ffe1ff3 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
@@ -145,6 +145,7 @@ namespace clang {
class ObjCProtocolDecl;
class OMPThreadPrivateDecl;
class OMPClause;
+ struct OverloadCandidate;
class OverloadCandidateSet;
class OverloadExpr;
class ParenListExpr;
@@ -277,10 +278,9 @@ class Sema {
// it will keep having external linkage. If it has internal linkage, we
// will not link it. Since it has no previous decls, it will remain
// with internal linkage.
- if (getLangOpts().ModulesHideInternalLinkage)
- return isVisible(Old) || New->isExternallyVisible();
- return true;
+ return isVisible(Old) || New->isExternallyVisible();
}
+ bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New);
public:
typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
@@ -903,6 +903,10 @@ public:
/// for C++ records.
llvm::FoldingSet<SpecialMemberOverloadResult> SpecialMemberCache;
+ /// \brief A cache of the flags available in enumerations with the flag_bits
+ /// attribute.
+ mutable llvm::DenseMap<const EnumDecl*, llvm::APInt> FlagBitsCache;
+
/// \brief The kind of translation unit we are processing.
///
/// When we're processing a complete translation unit, Sema will perform
@@ -1004,6 +1008,24 @@ public:
bool OldFPContractState : 1;
};
+ /// Records and restores the vtordisp state on entry/exit of C++ method body.
+ class VtorDispStackRAII {
+ public:
+ VtorDispStackRAII(Sema &S, bool ShouldSaveAndRestore)
+ : S(S), ShouldSaveAndRestore(ShouldSaveAndRestore), OldVtorDispStack() {
+ if (ShouldSaveAndRestore)
+ OldVtorDispStack = S.VtorDispModeStack;
+ }
+ ~VtorDispStackRAII() {
+ if (ShouldSaveAndRestore)
+ S.VtorDispModeStack = OldVtorDispStack;
+ }
+ private:
+ Sema &S;
+ bool ShouldSaveAndRestore;
+ SmallVector<MSVtorDispAttr::Mode, 2> OldVtorDispStack;
+ };
+
void addImplicitTypedef(StringRef Name, QualType T);
public:
@@ -1054,6 +1076,14 @@ public:
SemaDiagnosticBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID)
: DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) { }
+ // This is a cunning lie. DiagnosticBuilder actually performs move
+ // construction in its copy constructor (but due to varied uses, it's not
+ // possible to conveniently express this as actual move construction). So
+ // the default copy ctor here is fine, because the base class disables the
+ // source anyway, so the user-defined ~SemaDiagnosticBuilder is a safe no-op
+ // in that case anwyay.
+ SemaDiagnosticBuilder(const SemaDiagnosticBuilder&) = default;
+
~SemaDiagnosticBuilder() {
// If we aren't active, there is nothing to do.
if (!isActive()) return;
@@ -1200,16 +1230,6 @@ public:
bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
- unsigned deduceWeakPropertyFromType(QualType T) {
- if ((getLangOpts().getGC() != LangOptions::NonGC &&
- T.isObjCGCWeak()) ||
- (getLangOpts().ObjCAutoRefCount &&
- T.getObjCLifetime() == Qualifiers::OCL_Weak))
- return ObjCDeclSpec::DQ_PR_weak;
- return 0;
- }
-
-
/// \brief Build a function type.
///
/// This routine checks the function type according to C++ rules and
@@ -1249,6 +1269,8 @@ public:
SourceLocation Loc, DeclarationName Entity);
QualType BuildParenType(QualType T);
QualType BuildAtomicType(QualType T, SourceLocation Loc);
+ QualType BuildPipeType(QualType T,
+ SourceLocation Loc);
TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
@@ -1266,7 +1288,7 @@ public:
const FunctionProtoType *FPT);
void UpdateExceptionSpec(FunctionDecl *FD,
const FunctionProtoType::ExceptionSpecInfo &ESI);
- bool CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range);
+ bool CheckSpecifiedExceptionType(QualType &T, SourceRange Range);
bool CheckDistantExceptionSpec(QualType T);
bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
bool CheckEquivalentExceptionSpec(
@@ -1296,9 +1318,7 @@ public:
/// \brief Abstract class used to diagnose incomplete types.
struct TypeDiagnoser {
- bool Suppressed;
-
- TypeDiagnoser(bool Suppressed = false) : Suppressed(Suppressed) { }
+ TypeDiagnoser() {}
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0;
virtual ~TypeDiagnoser() {}
@@ -1328,17 +1348,17 @@ public:
void emit(const SemaDiagnosticBuilder &DB,
llvm::index_sequence<Is...>) const {
// Apply all tuple elements to the builder in order.
- bool Dummy[] = {(DB << getPrintable(std::get<Is>(Args)))...};
+ bool Dummy[] = {false, (DB << getPrintable(std::get<Is>(Args)))...};
(void)Dummy;
}
public:
BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args)
- : TypeDiagnoser(DiagID == 0), DiagID(DiagID), Args(Args...) {}
+ : TypeDiagnoser(), DiagID(DiagID), Args(Args...) {
+ assert(DiagID != 0 && "no diagnostic for type diagnoser");
+ }
void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
- if (Suppressed)
- return;
const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID);
emit(DB, llvm::index_sequence_for<Ts...>());
DB << T;
@@ -1347,7 +1367,7 @@ public:
private:
bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
- TypeDiagnoser &Diagnoser);
+ TypeDiagnoser *Diagnoser);
VisibleModuleSet VisibleModules;
llvm::SmallVector<VisibleModuleSet, 16> VisibleModulesStack;
@@ -1384,6 +1404,18 @@ public:
hasVisibleDefaultArgument(const NamedDecl *D,
llvm::SmallVectorImpl<Module *> *Modules = nullptr);
+ /// Determine if \p A and \p B are equivalent internal linkage declarations
+ /// from different modules, and thus an ambiguity error can be downgraded to
+ /// an extension warning.
+ bool isEquivalentInternalLinkageDeclaration(const NamedDecl *A,
+ const NamedDecl *B);
+ void diagnoseEquivalentInternalLinkageDeclarations(
+ SourceLocation Loc, const NamedDecl *D,
+ ArrayRef<const NamedDecl *> Equiv);
+
+ bool isCompleteType(SourceLocation Loc, QualType T) {
+ return !RequireCompleteTypeImpl(Loc, T, nullptr);
+ }
bool RequireCompleteType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser);
bool RequireCompleteType(SourceLocation Loc, QualType T,
@@ -1396,6 +1428,7 @@ public:
return RequireCompleteType(Loc, T, Diagnoser);
}
+ void completeExprArrayBound(Expr *E);
bool RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser);
bool RequireCompleteExprType(Expr *E, unsigned DiagID);
@@ -1432,6 +1465,12 @@ public:
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
//
+ struct SkipBodyInfo {
+ SkipBodyInfo() : ShouldSkip(false), Previous(nullptr) {}
+ bool ShouldSkip;
+ NamedDecl *Previous;
+ };
+
/// List of decls defined in a function prototype. This contains EnumConstants
/// that incorrectly end up in translation unit scope because there is no
/// function to pin them on. ActOnFunctionDeclarator reads this list and patches
@@ -1697,11 +1736,14 @@ public:
void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
SourceLocation LocAfterDecls);
- void CheckForFunctionRedefinition(FunctionDecl *FD,
- const FunctionDecl *EffectiveDefinition =
- nullptr);
- Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
- Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D);
+ void CheckForFunctionRedefinition(
+ FunctionDecl *FD, const FunctionDecl *EffectiveDefinition = nullptr,
+ SkipBodyInfo *SkipBody = nullptr);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists,
+ SkipBodyInfo *SkipBody = nullptr);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
+ SkipBodyInfo *SkipBody = nullptr);
void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
bool isObjCMethodDecl(Decl *D) {
return D && isa<ObjCMethodDecl>(D);
@@ -1778,6 +1820,10 @@ public:
/// \brief The parser has left a submodule.
void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod);
+ /// \brief Check if module import may be found in the current context,
+ /// emit error if not.
+ void diagnoseMisplacedModuleImport(Module *M, SourceLocation ImportLoc);
+
/// \brief Create an implicit import of the given module at the given
/// source location, for error recovery, if possible.
///
@@ -1843,12 +1889,6 @@ public:
TUK_Friend // Friend declaration: 'friend struct foo;'
};
- struct SkipBodyInfo {
- SkipBodyInfo() : ShouldSkip(false), Previous(nullptr) {}
- bool ShouldSkip;
- NamedDecl *Previous;
- };
-
Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
@@ -1965,7 +2005,9 @@ public:
Expr *val);
bool CheckEnumUnderlyingType(TypeSourceInfo *TI);
bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
- QualType EnumUnderlyingTy, const EnumDecl *Prev);
+ QualType EnumUnderlyingTy,
+ bool EnumUnderlyingIsImplicit,
+ const EnumDecl *Prev);
/// Determine whether the body of an anonymous enumeration should be skipped.
/// \param II The name of the first enumerator.
@@ -2043,6 +2085,22 @@ public:
TypeSourceInfo *TInfo);
bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New);
+ /// \brief Describes the kind of merge to perform for availability
+ /// attributes (including "deprecated", "unavailable", and "availability").
+ enum AvailabilityMergeKind {
+ /// \brief Don't merge availability attributes at all.
+ AMK_None,
+ /// \brief Merge availability attributes for a redeclaration, which requires
+ /// an exact match.
+ AMK_Redeclaration,
+ /// \brief Merge availability attributes for an override, which requires
+ /// an exact match or a weakening of constraints.
+ AMK_Override,
+ /// \brief Merge availability attributes for an implementation of
+ /// a protocol requirement.
+ AMK_ProtocolImplementation,
+ };
+
/// Attribute merging methods. Return true if a new attribute was added.
AvailabilityAttr *mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
IdentifierInfo *Platform,
@@ -2051,7 +2109,7 @@ public:
VersionTuple Obsoleted,
bool IsUnavailable,
StringRef Message,
- bool Override,
+ AvailabilityMergeKind AMK,
unsigned AttrSpellingListIndex);
TypeVisibilityAttr *mergeTypeVisibilityAttr(Decl *D, SourceRange Range,
TypeVisibilityAttr::VisibilityType Vis,
@@ -2079,23 +2137,16 @@ public:
unsigned AttrSpellingListIndex);
OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex);
-
- /// \brief Describes the kind of merge to perform for availability
- /// attributes (including "deprecated", "unavailable", and "availability").
- enum AvailabilityMergeKind {
- /// \brief Don't merge availability attributes at all.
- AMK_None,
- /// \brief Merge availability attributes for a redeclaration, which requires
- /// an exact match.
- AMK_Redeclaration,
- /// \brief Merge availability attributes for an override, which requires
- /// an exact match or a weakening of constraints.
- AMK_Override
- };
+ InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Ident,
+ unsigned AttrSpellingListIndex);
+ CommonAttr *mergeCommonAttr(Decl *D, SourceRange Range, IdentifierInfo *Ident,
+ unsigned AttrSpellingListIndex);
void mergeDeclAttributes(NamedDecl *New, Decl *Old,
AvailabilityMergeKind AMK = AMK_Redeclaration);
- void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls);
+ void MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
+ LookupResult &OldDecls);
bool MergeFunctionDecl(FunctionDecl *New, NamedDecl *&Old, Scope *S,
bool MergeTypeWithOld);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
@@ -2416,17 +2467,27 @@ public:
bool PartialOverloading = false);
// Emit as a 'note' the specific overload candidate
- void NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType = QualType());
+ void NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType = QualType(),
+ bool TakingAddress = false);
- // Emit as a series of 'note's all template and non-templates
- // identified by the expression Expr
- void NoteAllOverloadCandidates(Expr* E, QualType DestType = QualType());
+ // Emit as a series of 'note's all template and non-templates identified by
+ // the expression Expr
+ void NoteAllOverloadCandidates(Expr *E, QualType DestType = QualType(),
+ bool TakingAddress = false);
/// Check the enable_if expressions on the given function. Returns the first
/// failing attribute, or NULL if they were all successful.
EnableIfAttr *CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
bool MissingImplicitThis = false);
+ /// Returns whether the given function's address can be taken or not,
+ /// optionally emitting a diagnostic if the address can't be taken.
+ ///
+ /// Returns false if taking the address of the function is illegal.
+ bool checkAddressOfFunctionIsAvailable(const FunctionDecl *Function,
+ bool Complain = false,
+ SourceLocation Loc = SourceLocation());
+
// [PossiblyAFunctionType] --> [Return]
// NonFunctionType --> NonFunctionType
// R (A) --> R(A)
@@ -2451,7 +2512,7 @@ public:
ExprResult &SrcExpr,
bool DoFunctionPointerConverion = false,
bool Complain = false,
- const SourceRange& OpRangeForComplaining = SourceRange(),
+ SourceRange OpRangeForComplaining = SourceRange(),
QualType DestTypeForComplaining = QualType(),
unsigned DiagIDForComplaining = 0);
@@ -2476,17 +2537,8 @@ public:
FRS_DiagnosticIssued
};
- // An enum to represent whether something is dealing with a call to begin()
- // or a call to end() in a range-based for loop.
- enum BeginEndFunction {
- BEF_begin,
- BEF_end
- };
-
- ForRangeStatus BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
+ ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc,
SourceLocation RangeLoc,
- VarDecl *Decl,
- BeginEndFunction BEF,
const DeclarationNameInfo &NameInfo,
LookupResult &MemberLookup,
OverloadCandidateSet *CandidateSet,
@@ -2498,7 +2550,8 @@ public:
MultiExprArg Args,
SourceLocation RParenLoc,
Expr *ExecConfig,
- bool AllowTypoCorrection=true);
+ bool AllowTypoCorrection=true,
+ bool CalleesAddressIsTaken=false);
bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
MultiExprArg Args, SourceLocation RParenLoc,
@@ -2506,12 +2559,12 @@ public:
ExprResult *Result);
ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
- unsigned Opc,
+ UnaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
Expr *input);
ExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
- unsigned Opc,
+ BinaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
Expr *LHS, Expr *RHS);
@@ -2904,7 +2957,8 @@ public:
/// Adjust the calling convention of a method to be the ABI default if it
/// wasn't specified explicitly. This handles method types formed from
/// function type typedefs and typename template arguments.
- void adjustMemberFunctionCC(QualType &T, bool IsStatic);
+ void adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
+ SourceLocation Loc);
// Check if there is an explicit attribute, but only look through parens.
// The intent is to look for an attribute on the current declarator, but not
@@ -3008,11 +3062,9 @@ public:
FieldDeclarator &FD,
Selector GetterSel,
Selector SetterSel,
- const bool isAssign,
const bool isReadWrite,
- const unsigned Attributes,
+ unsigned &Attributes,
const unsigned AttributesAsWritten,
- bool *isOverridingProperty,
QualType T,
TypeSourceInfo *TSI,
tok::ObjCKeywordKind MethodImplKind);
@@ -3026,7 +3078,6 @@ public:
FieldDeclarator &FD,
Selector GetterSel,
Selector SetterSel,
- const bool isAssign,
const bool isReadWrite,
const unsigned Attributes,
const unsigned AttributesAsWritten,
@@ -3039,7 +3090,7 @@ public:
/// warning) when atomic property has one but not the other user-declared
/// setter or getter.
void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl,
- ObjCContainerDecl* IDecl);
+ ObjCInterfaceDecl* IDecl);
void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);
@@ -3307,11 +3358,14 @@ public:
BFRK_Check
};
- StmtResult ActOnCXXForRangeStmt(SourceLocation ForLoc, Stmt *LoopVar,
+ StmtResult ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
+ SourceLocation CoawaitLoc,
+ Stmt *LoopVar,
SourceLocation ColonLoc, Expr *Collection,
SourceLocation RParenLoc,
BuildForRangeKind Kind);
StmtResult BuildCXXForRangeStmt(SourceLocation ForLoc,
+ SourceLocation CoawaitLoc,
SourceLocation ColonLoc,
Stmt *RangeDecl, Stmt *BeginEndDecl,
Expr *Cond, Expr *Inc,
@@ -3364,6 +3418,9 @@ public:
bool IsUnevaluatedContext);
bool LookupInlineAsmField(StringRef Base, StringRef Member,
unsigned &Offset, SourceLocation AsmLoc);
+ ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member,
+ llvm::InlineAsmIdentifierInfo &Info,
+ SourceLocation AsmLoc);
StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
ArrayRef<Token> AsmToks,
StringRef AsmString,
@@ -3458,6 +3515,11 @@ public:
void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
SourceLocation OpLoc);
+ /// \brief Warn if we're implicitly casting from a _Nullable pointer type to a
+ /// _Nonnull one.
+ void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType,
+ SourceLocation Loc);
+
ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
return DelayedDiagnostics.push(pool);
}
@@ -3483,7 +3545,7 @@ public:
bool ObjCPropertyAccess);
bool makeUnavailableInSystemHeader(SourceLocation loc,
- StringRef message);
+ UnavailableAttr::ImplicitReason reason);
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
@@ -3664,19 +3726,23 @@ public:
ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
- const TemplateArgumentListInfo *TemplateArgs);
+ const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S);
ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
- bool IsDefiniteInstance);
+ bool IsDefiniteInstance,
+ const Scope *S);
bool UseArgumentDependentLookup(const CXXScopeSpec &SS,
const LookupResult &R,
bool HasTrailingLParen);
- ExprResult BuildQualifiedDeclarationNameExpr(
- CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo,
- bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr);
+ ExprResult
+ BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ bool IsAddressOfOperand, const Scope *S,
+ TypeSourceInfo **RecoveryTSI = nullptr);
ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
@@ -3752,7 +3818,7 @@ public:
ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind,
bool IsType, void *TyOrEx,
- const SourceRange &ArgRange);
+ SourceRange ArgRange);
ExprResult CheckPlaceholderExpr(Expr *E);
bool CheckVecStepExpr(Expr *E);
@@ -3773,6 +3839,9 @@ public:
Expr *Idx, SourceLocation RLoc);
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc);
+ ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
+ Expr *LowerBound, SourceLocation ColonLoc,
+ Expr *Length, SourceLocation RBLoc);
// This struct is for use by ActOnMemberAccess to allow
// BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after
@@ -3790,6 +3859,7 @@ public:
CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S,
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
ExprResult
@@ -3798,6 +3868,7 @@ public:
SourceLocation TemplateKWLoc,
NamedDecl *FirstQualifierInScope, LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S,
bool SuppressQualifierCheck = false,
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
@@ -3926,15 +3997,13 @@ public:
/// __builtin_offsetof(type, a.b[123][456].c)
ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
TypeSourceInfo *TInfo,
- OffsetOfComponent *CompPtr,
- unsigned NumComponents,
+ ArrayRef<OffsetOfComponent> Components,
SourceLocation RParenLoc);
ExprResult ActOnBuiltinOffsetOf(Scope *S,
SourceLocation BuiltinLoc,
SourceLocation TypeLoc,
ParsedType ParsedArgTy,
- OffsetOfComponent *CompPtr,
- unsigned NumComponents,
+ ArrayRef<OffsetOfComponent> Components,
SourceLocation RParenLoc);
// __builtin_choose_expr(constExpr, expr1, expr2)
@@ -4030,7 +4099,8 @@ public:
SourceLocation IdentLoc,
IdentifierInfo *Ident,
SourceLocation LBrace,
- AttributeList *AttrList);
+ AttributeList *AttrList,
+ UsingDirectiveDecl * &UsingDecl);
void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
NamespaceDecl *getStdNamespace() const;
@@ -4936,15 +5006,25 @@ public:
/// \brief Perform initialization analysis of the init-capture and perform
/// any implicit conversions such as an lvalue-to-rvalue conversion if
/// not being used to initialize a reference.
- QualType performLambdaInitCaptureInitialization(SourceLocation Loc,
- bool ByRef, IdentifierInfo *Id, Expr *&Init);
+ ParsedType actOnLambdaInitCaptureInitialization(
+ SourceLocation Loc, bool ByRef, IdentifierInfo *Id,
+ LambdaCaptureInitKind InitKind, Expr *&Init) {
+ return ParsedType::make(buildLambdaInitCaptureInitialization(
+ Loc, ByRef, Id, InitKind != LambdaCaptureInitKind::CopyInit, Init));
+ }
+ QualType buildLambdaInitCaptureInitialization(SourceLocation Loc, bool ByRef,
+ IdentifierInfo *Id,
+ bool DirectInit, Expr *&Init);
+
/// \brief Create a dummy variable within the declcontext of the lambda's
/// call operator, for name lookup purposes for a lambda init capture.
///
/// CodeGen handles emission of lambda captures, ignoring these dummy
/// variables appropriately.
- VarDecl *createLambdaInitCaptureVarDecl(SourceLocation Loc,
- QualType InitCaptureType, IdentifierInfo *Id, Expr *Init);
+ VarDecl *createLambdaInitCaptureVarDecl(SourceLocation Loc,
+ QualType InitCaptureType,
+ IdentifierInfo *Id,
+ unsigned InitStyle, Expr *Init);
/// \brief Build the implicit field for an init-capture.
FieldDecl *buildInitCaptureField(sema::LambdaScopeInfo *LSI, VarDecl *Var);
@@ -5009,8 +5089,7 @@ public:
// ParseObjCStringLiteral - Parse Objective-C string literals.
ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
- Expr **Strings,
- unsigned NumStrings);
+ ArrayRef<Expr *> Strings);
ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
@@ -5035,8 +5114,7 @@ public:
ObjCMethodDecl *setterMethod);
ExprResult BuildObjCDictionaryLiteral(SourceRange SR,
- ObjCDictionaryElement *Elements,
- unsigned NumElements);
+ MutableArrayRef<ObjCDictionaryElement> Elements);
ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
TypeSourceInfo *EncodedTypeInfo,
@@ -5222,7 +5300,7 @@ public:
SourceLocation RBrac,
AttributeList *AttrList);
void ActOnFinishCXXMemberDecls();
- void ActOnFinishCXXMemberDefaultArgs(Decl *D);
+ void ActOnFinishCXXNonNestedClass(Decl *D);
void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param);
unsigned ActOnReenterTemplateScope(Scope *S, Decl *Template);
@@ -5289,13 +5367,14 @@ public:
SourceLocation BaseLoc,
SourceLocation EllipsisLoc);
- bool AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
- unsigned NumBases);
- void ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases,
- unsigned NumBases);
+ bool AttachBaseSpecifiers(CXXRecordDecl *Class,
+ MutableArrayRef<CXXBaseSpecifier *> Bases);
+ void ActOnBaseSpecifiers(Decl *ClassDecl,
+ MutableArrayRef<CXXBaseSpecifier *> Bases);
- bool IsDerivedFrom(QualType Derived, QualType Base);
- bool IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths);
+ bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base);
+ bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
+ CXXBasePaths &Paths);
// FIXME: I don't like this name.
void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
@@ -5424,6 +5503,7 @@ public:
AbstractArrayType
};
+ bool isAbstractType(SourceLocation Loc, QualType T);
bool RequireNonAbstractType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser);
template <typename... Ts>
@@ -5435,9 +5515,6 @@ public:
void DiagnoseAbstractType(const CXXRecordDecl *RD);
- bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
- AbstractDiagSelID SelID = AbstractNone);
-
//===--------------------------------------------------------------------===//
// C++ Overloaded Operators [C++ 13.5]
//
@@ -5508,7 +5585,7 @@ public:
SourceLocation ExportLoc,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- Decl **Params, unsigned NumParams,
+ ArrayRef<Decl *> Params,
SourceLocation RAngleLoc);
/// \brief The context in which we are checking a template parameter list.
@@ -5622,10 +5699,6 @@ public:
MultiTemplateParamsArg TemplateParameterLists,
Declarator &D);
- Decl *ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
- MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D);
-
bool
CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
TemplateSpecializationKind NewTSK,
@@ -6231,6 +6304,9 @@ public:
/// \brief Substitution of the deduced template argument values
/// resulted in an error.
TDK_SubstitutionFailure,
+ /// \brief After substituting deduced template arguments, a dependent
+ /// parameter type did not match the corresponding argument.
+ TDK_DeducedMismatch,
/// \brief A non-depnedent component of the parameter did not match the
/// corresponding component of the argument.
TDK_NonDeducedMismatch,
@@ -6340,6 +6416,11 @@ public:
bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
bool Diagnose = true);
+ QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
+ QualType Type, TypeSourceInfo *TSI,
+ SourceRange Range, bool DirectInit,
+ Expr *Init);
+
TypeLoc getReturnTypeLoc(FunctionDecl *FD) const;
bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
@@ -6581,12 +6662,6 @@ public:
friend class ArgumentPackSubstitutionRAII;
- /// \brief The stack of calls expression undergoing template instantiation.
- ///
- /// The top of this stack is used by a fixit instantiating unresolved
- /// function calls to fix the AST to match the textual change it prints.
- SmallVector<CallExpr *, 8> CallsUndergoingInstantiation;
-
/// \brief For each declaration that involved template argument deduction, the
/// set of diagnostics that were suppressed during that template argument
/// deduction.
@@ -6609,7 +6684,8 @@ public:
/// the stack.
struct InstantiatingTemplate {
/// \brief Note that we are instantiating a class template,
- /// function template, or a member thereof.
+ /// function template, variable template, alias template,
+ /// or a member thereof.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Decl *Entity,
SourceRange InstantiationRange = SourceRange());
@@ -6655,6 +6731,8 @@ public:
sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange = SourceRange());
+ /// \brief Note that we are instantiating a default argument for a function
+ /// parameter.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ParmVarDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
@@ -6705,7 +6783,7 @@ public:
Sema &SemaRef, ActiveTemplateInstantiation::InstantiationKind Kind,
SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
Decl *Entity, NamedDecl *Template = nullptr,
- ArrayRef<TemplateArgument> TemplateArgs = ArrayRef<TemplateArgument>(),
+ ArrayRef<TemplateArgument> TemplateArgs = None,
sema::TemplateDeductionInfo *DeductionInfo = nullptr);
InstantiatingTemplate(const InstantiatingTemplate&) = delete;
@@ -6925,8 +7003,6 @@ public:
///
/// \param Exprs The list of expressions to substitute into.
///
- /// \param NumExprs The number of expressions in \p Exprs.
- ///
/// \param IsCall Whether this is some form of call, in which case
/// default arguments will be dropped.
///
@@ -6935,7 +7011,7 @@ public:
/// \param Outputs Will receive all of the substituted arguments.
///
/// \returns true if an error occurred, false otherwise.
- bool SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall,
+ bool SubstExprs(ArrayRef<Expr *> Exprs, bool IsCall,
const MultiLevelTemplateArgumentList &TemplateArgs,
SmallVectorImpl<Expr *> &Outputs);
@@ -7169,13 +7245,11 @@ public:
unsigned NumElts);
DeclGroupPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
- const IdentifierLocPair *IdentList,
- unsigned NumElts,
+ ArrayRef<IdentifierLocPair> IdentList,
AttributeList *attrList);
void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
- const IdentifierLocPair *ProtocolId,
- unsigned NumProtocols,
+ ArrayRef<IdentifierLocPair> ProtocolId,
SmallVectorImpl<Decl *> &Protocols);
/// Given a list of identifiers (and their locations), resolve the
@@ -7244,14 +7318,7 @@ public:
/// Process the specified property declaration and create decls for the
/// setters and getters as needed.
/// \param property The property declaration being processed
- /// \param CD The semantic container for the property
- /// \param redeclaredProperty Declaration for property if redeclared
- /// in class extension.
- /// \param lexicalDC Container for redeclaredProperty.
- void ProcessPropertyDecl(ObjCPropertyDecl *property,
- ObjCContainerDecl *CD,
- ObjCPropertyDecl *redeclaredProperty = nullptr,
- ObjCContainerDecl *lexicalDC = nullptr);
+ void ProcessPropertyDecl(ObjCPropertyDecl *property);
void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
@@ -7270,7 +7337,6 @@ public:
SourceLocation LParenLoc,
FieldDeclarator &FD, ObjCDeclSpec &ODS,
Selector GetterSel, Selector SetterSel,
- bool *OverridingProperty,
tok::ObjCKeywordKind MethodImplKind,
DeclContext *lexicalDC = nullptr);
@@ -7563,6 +7629,9 @@ public:
void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
StringLiteral *SegmentName);
+ /// \brief Called on #pragma clang __debug dump II
+ void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
+
/// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value);
@@ -7674,25 +7743,53 @@ public:
void AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads,
Expr *MinBlocks, unsigned SpellingListIndex);
+ //===--------------------------------------------------------------------===//
+ // C++ Coroutines TS
+ //
+ ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E);
+ ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E);
+ StmtResult ActOnCoreturnStmt(SourceLocation KwLoc, Expr *E);
+
+ ExprResult BuildCoawaitExpr(SourceLocation KwLoc, Expr *E);
+ ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E);
+ StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E);
+
+ void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body);
+
+ //===--------------------------------------------------------------------===//
// OpenMP directives and clauses.
+ //
private:
void *VarDataSharingAttributesStack;
/// \brief Initialization of data-sharing attributes stack.
void InitDataSharingAttributesStack();
void DestroyDataSharingAttributesStack();
- ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op,
- OpenMPClauseKind CKind);
+ ExprResult
+ VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind,
+ bool StrictlyPositive = true);
+
public:
- /// \brief Check if the specified variable is used in a private clause in
- /// Checks if the specified variable is used in one of the private
- /// clauses in OpenMP constructs.
+ /// \brief Return true if the provided declaration \a VD should be captured by
+ /// reference in the provided scope \a RSI. This will take into account the
+ /// semantics of the directive and associated clauses.
+ bool IsOpenMPCapturedByRef(VarDecl *VD,
+ const sema::CapturedRegionScopeInfo *RSI);
+
+ /// \brief Check if the specified variable is used in one of the private
+ /// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP
+ /// constructs.
bool IsOpenMPCapturedVar(VarDecl *VD);
- /// OpenMP constructs.
+ /// \brief Check if the specified variable is used in 'private' clause.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
bool isOpenMPPrivateVar(VarDecl *VD, unsigned Level);
+ /// \brief Check if the specified variable is captured by 'target' directive.
+ /// \param Level Relative level of nested OpenMP construct for that the check
+ /// is performed.
+ bool isOpenMPTargetCapturedVar(VarDecl *VD, unsigned Level);
+
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc,
Expr *Op);
/// \brief Called on start of new data sharing attribute block.
@@ -7785,6 +7882,7 @@ public:
/// \brief Called on well-formed '\#pragma omp critical' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName,
+ ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed '\#pragma omp parallel for' after parsing
@@ -7828,7 +7926,8 @@ public:
SourceLocation EndLoc);
/// \brief Called on well-formed '\#pragma omp ordered' after parsing of the
/// associated statement.
- StmtResult ActOnOpenMPOrderedDirective(Stmt *AStmt, SourceLocation StartLoc,
+ StmtResult ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed '\#pragma omp atomic' after parsing of the
/// associated statement.
@@ -7840,6 +7939,11 @@ public:
StmtResult ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp target data' after parsing of
+ /// the associated statement.
+ StmtResult ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
/// \brief Called on well-formed '\#pragma omp teams' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
@@ -7851,9 +7955,28 @@ public:
SourceLocation EndLoc,
OpenMPDirectiveKind CancelRegion);
/// \brief Called on well-formed '\#pragma omp cancel'.
- StmtResult ActOnOpenMPCancelDirective(SourceLocation StartLoc,
+ StmtResult ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
SourceLocation EndLoc,
OpenMPDirectiveKind CancelRegion);
+ /// \brief Called on well-formed '\#pragma omp taskloop' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPTaskLoopDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+ /// \brief Called on well-formed '\#pragma omp taskloop simd' after parsing of
+ /// the associated statement.
+ StmtResult ActOnOpenMPTaskLoopSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+ /// \brief Called on well-formed '\#pragma omp distribute' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPDistributeDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr,
@@ -7861,8 +7984,11 @@ public:
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'if' clause.
- OMPClause *ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
+ OMPClause *ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
+ Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
+ SourceLocation NameModifierLoc,
+ SourceLocation ColonLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'final' clause.
OMPClause *ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc,
@@ -7878,11 +8004,32 @@ public:
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// \brief Called on well-formed 'simdlen' clause.
+ OMPClause *ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// \brief Called on well-formed 'collapse' clause.
OMPClause *ActOnOpenMPCollapseClause(Expr *NumForLoops,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// \brief Called on well-formed 'ordered' clause.
+ OMPClause *
+ ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc,
+ SourceLocation LParenLoc = SourceLocation(),
+ Expr *NumForLoops = nullptr);
+ /// \brief Called on well-formed 'grainsize' clause.
+ OMPClause *ActOnOpenMPGrainsizeClause(Expr *Size, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'num_tasks' clause.
+ OMPClause *ActOnOpenMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'hint' clause.
+ OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
unsigned Argument,
@@ -7903,26 +8050,20 @@ public:
SourceLocation LParenLoc,
SourceLocation EndLoc);
- OMPClause *ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
- unsigned Argument, Expr *Expr,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ArgumentLoc,
- SourceLocation CommaLoc,
- SourceLocation EndLoc);
+ OMPClause *ActOnOpenMPSingleExprWithArgClause(
+ OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ ArrayRef<SourceLocation> ArgumentsLoc, SourceLocation DelimLoc,
+ SourceLocation EndLoc);
/// \brief Called on well-formed 'schedule' clause.
- OMPClause *ActOnOpenMPScheduleClause(OpenMPScheduleClauseKind Kind,
- Expr *ChunkSize, SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation KindLoc,
- SourceLocation CommaLoc,
- SourceLocation EndLoc);
+ OMPClause *ActOnOpenMPScheduleClause(
+ OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
+ OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
+ SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc);
OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc,
SourceLocation EndLoc);
- /// \brief Called on well-formed 'ordered' clause.
- OMPClause *ActOnOpenMPOrderedClause(SourceLocation StartLoc,
- SourceLocation EndLoc);
/// \brief Called on well-formed 'nowait' clause.
OMPClause *ActOnOpenMPNowaitClause(SourceLocation StartLoc,
SourceLocation EndLoc);
@@ -7947,6 +8088,15 @@ public:
/// \brief Called on well-formed 'seq_cst' clause.
OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
SourceLocation EndLoc);
+ /// \brief Called on well-formed 'threads' clause.
+ OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'simd' clause.
+ OMPClause *ActOnOpenMPSIMDClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'nogroup' clause.
+ OMPClause *ActOnOpenMPNogroupClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
OMPClause *ActOnOpenMPVarListClause(
OpenMPClauseKind Kind, ArrayRef<Expr *> Vars, Expr *TailExpr,
@@ -7954,7 +8104,8 @@ public:
SourceLocation ColonLoc, SourceLocation EndLoc,
CXXScopeSpec &ReductionIdScopeSpec,
const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
- SourceLocation DepLoc);
+ OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier,
+ OpenMPMapClauseKind MapType, SourceLocation DepLinMapLoc);
/// \brief Called on well-formed 'private' clause.
OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
@@ -7983,12 +8134,11 @@ public:
CXXScopeSpec &ReductionIdScopeSpec,
const DeclarationNameInfo &ReductionId);
/// \brief Called on well-formed 'linear' clause.
- OMPClause *ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList,
- Expr *Step,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ColonLoc,
- SourceLocation EndLoc);
+ OMPClause *
+ ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ OpenMPLinearClauseKind LinKind, SourceLocation LinLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc);
/// \brief Called on well-formed 'aligned' clause.
OMPClause *ActOnOpenMPAlignedClause(ArrayRef<Expr *> VarList,
Expr *Alignment,
@@ -8017,6 +8167,28 @@ public:
SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// \brief Called on well-formed 'device' clause.
+ OMPClause *ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'map' clause.
+ OMPClause *ActOnOpenMPMapClause(
+ OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType,
+ SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
+ /// \brief Called on well-formed 'num_teams' clause.
+ OMPClause *ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'thread_limit' clause.
+ OMPClause *ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'priority' clause.
+ OMPClause *ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// \brief The kind of conversion being performed.
enum CheckedConversionKind {
@@ -8058,12 +8230,13 @@ public:
// DefaultFunctionArrayConversion - converts functions and arrays
// to their respective pointers (C99 6.3.2.1).
- ExprResult DefaultFunctionArrayConversion(Expr *E);
+ ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose = true);
// DefaultFunctionArrayLvalueConversion - converts functions and
// arrays to their respective pointers and performs the
// lvalue-to-rvalue conversion.
- ExprResult DefaultFunctionArrayLvalueConversion(Expr *E);
+ ExprResult DefaultFunctionArrayLvalueConversion(Expr *E,
+ bool Diagnose = true);
// DefaultLvalueConversion - performs lvalue-to-rvalue conversion on
// the operand. This is DefaultFunctionArrayLvalueConversion,
@@ -8231,19 +8404,23 @@ public:
QualType LHSType,
QualType RHSType);
- /// Check assignment constraints and prepare for a conversion of the
- /// RHS to the LHS type.
+ /// Check assignment constraints and optionally prepare for a conversion of
+ /// the RHS to the LHS type. The conversion is prepared for if ConvertRHS
+ /// is true.
AssignConvertType CheckAssignmentConstraints(QualType LHSType,
ExprResult &RHS,
- CastKind &Kind);
+ CastKind &Kind,
+ bool ConvertRHS = true);
// CheckSingleAssignmentConstraints - Currently used by
// CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,
- // this routine performs the default function/array converions.
+ // this routine performs the default function/array converions, if ConvertRHS
+ // is true.
AssignConvertType CheckSingleAssignmentConstraints(QualType LHSType,
ExprResult &RHS,
bool Diagnose = true,
- bool DiagnoseCFAudited = false);
+ bool DiagnoseCFAudited = false,
+ bool ConvertRHS = true);
// \brief If the lhs type is a transparent union, check whether we
// can initialize the transparent union with the given expression.
@@ -8287,22 +8464,23 @@ public:
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
bool IsCompAssign = false);
QualType CheckAdditionOperands( // C99 6.5.6
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc,
- QualType* CompLHSTy = nullptr);
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ BinaryOperatorKind Opc, QualType* CompLHSTy = nullptr);
QualType CheckSubtractionOperands( // C99 6.5.6
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
QualType* CompLHSTy = nullptr);
QualType CheckShiftOperands( // C99 6.5.7
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc,
- bool IsCompAssign = false);
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ BinaryOperatorKind Opc, bool IsCompAssign = false);
QualType CheckCompareOperands( // C99 6.5.8/9
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned OpaqueOpc,
- bool isRelational);
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ BinaryOperatorKind Opc, bool isRelational);
QualType CheckBitwiseOperands( // C99 6.5.[10...12]
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
bool IsCompAssign = false);
QualType CheckLogicalOperands( // C99 6.5.[13,14]
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc);
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ BinaryOperatorKind Opc);
// CheckAssignmentOperands is used for both simple and compound assignment.
// For simple assignment, pass both expressions and a null converted type.
// For compound assignment, pass both expressions and the converted type.
@@ -8356,6 +8534,7 @@ public:
QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc);
+ bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
bool isLaxVectorConversion(QualType srcType, QualType destType);
/// type checking declaration initializers (C99 6.7.8)
@@ -8410,6 +8589,10 @@ public:
bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
CastKind &Kind);
+ /// \brief Prepare `SplattedExpr` for a vector splat operation, adding
+ /// implicit casts if necessary.
+ ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr);
+
// CheckExtVectorCast - check type constraints for extended vectors.
// Since vectors are an extension, there are no C standard reference for this.
// We allow casting between vectors and integer datatypes of the same size,
@@ -8562,8 +8745,37 @@ public:
CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D);
+ enum CUDAFunctionPreference {
+ CFP_Never, // Invalid caller/callee combination.
+ CFP_LastResort, // Lowest priority. Only in effect if
+ // LangOpts.CUDADisableTargetCallChecks is true.
+ CFP_Fallback, // Low priority caller/callee combination
+ CFP_Best, // Preferred caller/callee combination
+ };
+
+ /// Identifies relative preference of a given Caller/Callee
+ /// combination, based on their host/device attributes.
+ /// \param Caller function which needs address of \p Callee.
+ /// nullptr in case of global context.
+ /// \param Callee target function
+ ///
+ /// \returns preference value for particular Caller/Callee combination.
+ CUDAFunctionPreference IdentifyCUDAPreference(const FunctionDecl *Caller,
+ const FunctionDecl *Callee);
+
bool CheckCUDATarget(const FunctionDecl *Caller, const FunctionDecl *Callee);
+ /// Finds a function in \p Matches with highest calling priority
+ /// from \p Caller context and erases all functions with lower
+ /// calling priority.
+ void EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
+ SmallVectorImpl<FunctionDecl *> &Matches);
+ void EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
+ SmallVectorImpl<DeclAccessPair> &Matches);
+ void EraseUnwantedCUDAMatches(
+ const FunctionDecl *Caller,
+ SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches);
+
/// Given a implicit special member, infer its CUDA target from the
/// calls it needs to make to underlying base/field special members.
/// \param ClassDecl the class for which the member is being created.
@@ -8693,8 +8905,8 @@ public:
DeclGroupPtrTy IterationVar);
void CodeCompleteObjCSelector(Scope *S,
ArrayRef<IdentifierInfo *> SelIdents);
- void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
- unsigned NumProtocols);
+ void CodeCompleteObjCProtocolReferences(
+ ArrayRef<IdentifierLocPair> Protocols);
void CodeCompleteObjCProtocolDecl(Scope *S);
void CodeCompleteObjCInterfaceDecl(Scope *S);
void CodeCompleteObjCSuperclass(Scope *S,
@@ -8752,8 +8964,8 @@ private:
bool HasVAListArg;
};
- bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
- FormatStringInfo *FSI);
+ static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
+ FormatStringInfo *FSI);
bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
const FunctionProtoType *Proto);
bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
@@ -8774,7 +8986,7 @@ private:
bool CheckObjCString(Expr *Arg);
ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl,
- unsigned BuiltinID, CallExpr *TheCall);
+ unsigned BuiltinID, CallExpr *TheCall);
bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
unsigned MaxWidth);
@@ -8786,8 +8998,10 @@ private:
bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
-
+
+ bool SemaBuiltinVAStartImpl(CallExpr *TheCall);
bool SemaBuiltinVAStart(CallExpr *TheCall);
+ bool SemaBuiltinMSVAStart(CallExpr *TheCall);
bool SemaBuiltinVAStartARM(CallExpr *Call);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
@@ -8806,6 +9020,7 @@ private:
bool SemaBuiltinLongjmp(CallExpr *TheCall);
bool SemaBuiltinSetjmp(CallExpr *TheCall);
ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult);
+ ExprResult SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult);
ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult,
AtomicExpr::AtomicOp Op);
bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
@@ -8815,7 +9030,6 @@ private:
bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
int ArgNum, unsigned ExpectedFieldNum,
bool AllowName);
- bool SemaBuiltinCpuSupports(CallExpr *TheCall);
public:
enum FormatStringType {
FST_Scanf,
@@ -8839,7 +9053,7 @@ public:
bool FormatStringHasSArg(const StringLiteral *FExpr);
- bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
+ static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
private:
bool CheckFormatArguments(const FormatAttr *Format,
@@ -9010,6 +9224,10 @@ public:
return NumArgs + 1 > NumParams; // If so, we view as an extra argument.
return NumArgs > NumParams;
}
+
+ // Emitting members of dllexported classes is delayed until the class
+ // (including field initializers) is fully parsed.
+ SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses;
};
/// \brief RAII object that enters a new expression evaluation context.
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Template.h b/contrib/llvm/tools/clang/include/clang/Sema/Template.h
index 416ef7b..c092630 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Template.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Template.h
@@ -178,8 +178,8 @@ namespace clang {
class LocalInstantiationScope {
public:
/// \brief A set of declarations.
- typedef SmallVector<Decl *, 4> DeclArgumentPack;
-
+ typedef SmallVector<ParmVarDecl *, 4> DeclArgumentPack;
+
private:
/// \brief Reference to the semantic analysis that is performing
/// this template instantiation.
@@ -332,7 +332,7 @@ namespace clang {
findInstantiationOf(const Decl *D);
void InstantiatedLocal(const Decl *D, Decl *Inst);
- void InstantiatedLocalPackArg(const Decl *D, Decl *Inst);
+ void InstantiatedLocalPackArg(const Decl *D, ParmVarDecl *Inst);
void MakeInstantiatedLocalArgPack(const Decl *D);
/// \brief Note that the given parameter pack has been partially substituted
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h
index 229eb71..c22c703 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h
@@ -140,6 +140,9 @@ public:
/// TDK_SubstitutionFailure: this argument is the template
/// argument we were instantiating when we encountered an error.
///
+ /// TDK_DeducedMismatch: this is the parameter type, after substituting
+ /// deduced arguments.
+ ///
/// TDK_NonDeducedMismatch: this is the component of the 'parameter'
/// of the deduction, directly provided in the source code.
TemplateArgument FirstArg;
@@ -147,18 +150,32 @@ public:
/// \brief The second template argument to which the template
/// argument deduction failure refers.
///
+ /// TDK_Inconsistent: this argument is the second value deduced
+ /// for the corresponding template parameter.
+ ///
+ /// TDK_DeducedMismatch: this is the (adjusted) call argument type.
+ ///
/// TDK_NonDeducedMismatch: this is the mismatching component of the
/// 'argument' of the deduction, from which we are deducing arguments.
///
/// FIXME: Finish documenting this.
TemplateArgument SecondArg;
- /// \brief The expression which caused a deduction failure.
- ///
- /// TDK_FailedOverloadResolution: this argument is the reference to
- /// an overloaded function which could not be resolved to a specific
- /// function.
- Expr *Expression;
+ union {
+ /// \brief The expression which caused a deduction failure.
+ ///
+ /// TDK_FailedOverloadResolution: this argument is the reference to
+ /// an overloaded function which could not be resolved to a specific
+ /// function.
+ Expr *Expression;
+
+ /// \brief The index of the function argument that caused a deduction
+ /// failure.
+ ///
+ /// TDK_DeducedMismatch: this is the index of the argument that had a
+ /// different argument type from its substituted parameter type.
+ unsigned CallArgIndex;
+ };
/// \brief Information on packs that we're currently expanding.
///
@@ -211,6 +228,10 @@ struct DeductionFailureInfo {
/// if any.
Expr *getExpr();
+ /// \brief Return the index of the call argument that this deduction
+ /// failure refers to, if any.
+ llvm::Optional<unsigned> getCallArgIndex();
+
/// \brief Free any memory associated with this deduction failure.
void Destroy();
};
@@ -236,7 +257,7 @@ struct TemplateSpecCandidate {
}
/// Diagnose a template argument deduction failure.
- void NoteDeductionFailure(Sema &S);
+ void NoteDeductionFailure(Sema &S, bool ForTakingAddress);
};
/// TemplateSpecCandidateSet - A set of generalized overload candidates,
@@ -246,6 +267,10 @@ struct TemplateSpecCandidate {
class TemplateSpecCandidateSet {
SmallVector<TemplateSpecCandidate, 16> Candidates;
SourceLocation Loc;
+ // Stores whether we're taking the address of these candidates. This helps us
+ // produce better error messages when dealing with the pass_object_size
+ // attribute on parameters.
+ bool ForTakingAddress;
TemplateSpecCandidateSet(
const TemplateSpecCandidateSet &) = delete;
@@ -254,7 +279,8 @@ class TemplateSpecCandidateSet {
void destroyCandidates();
public:
- TemplateSpecCandidateSet(SourceLocation Loc) : Loc(Loc) {}
+ TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false)
+ : Loc(Loc), ForTakingAddress(ForTakingAddress) {}
~TemplateSpecCandidateSet() { destroyCandidates(); }
SourceLocation getLocation() const { return Loc; }
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h b/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h
index 958aab0..3b0385e 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h
@@ -72,15 +72,15 @@ public:
/// \brief Gets the DeclarationName of the typo correction
DeclarationName getCorrection() const { return CorrectionName; }
- IdentifierInfo* getCorrectionAsIdentifierInfo() const {
+ IdentifierInfo *getCorrectionAsIdentifierInfo() const {
return CorrectionName.getAsIdentifierInfo();
}
/// \brief Gets the NestedNameSpecifier needed to use the typo correction
- NestedNameSpecifier* getCorrectionSpecifier() const {
+ NestedNameSpecifier *getCorrectionSpecifier() const {
return CorrectionNameSpec;
}
- void setCorrectionSpecifier(NestedNameSpecifier* NNS) {
+ void setCorrectionSpecifier(NestedNameSpecifier *NNS) {
CorrectionNameSpec = NNS;
ForceSpecifierReplacement = (NNS != nullptr);
}
@@ -129,9 +129,16 @@ public:
return Normalized ? NormalizeEditDistance(ED) : ED;
}
+ /// \brief Get the correction declaration found by name lookup (before we
+ /// looked through using shadow declarations and the like).
+ NamedDecl *getFoundDecl() const {
+ return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : nullptr;
+ }
+
/// \brief Gets the pointer to the declaration of the typo correction
NamedDecl *getCorrectionDecl() const {
- return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : nullptr;
+ auto *D = getFoundDecl();
+ return D ? D->getUnderlyingDecl() : nullptr;
}
template <class DeclClass>
DeclClass *getCorrectionDeclAs() const {
@@ -180,8 +187,7 @@ public:
// Check if this TypoCorrection is a keyword by checking if the first
// item in CorrectionDecls is NULL.
bool isKeyword() const {
- return !CorrectionDecls.empty() &&
- CorrectionDecls.front() == nullptr;
+ return !CorrectionDecls.empty() && CorrectionDecls.front() == nullptr;
}
// Check if this TypoCorrection is the given keyword.
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
index 4b66207..0dfb8cf 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
@@ -17,6 +17,7 @@
#ifndef LLVM_CLANG_SERIALIZATION_ASTBITCODES_H
#define LLVM_CLANG_SERIALIZATION_ASTBITCODES_H
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Bitcode/BitCodes.h"
@@ -61,9 +62,6 @@ namespace clang {
/// used for the translation unit declaration.
typedef uint32_t DeclID;
- /// \brief a Decl::Kind/DeclID pair.
- typedef std::pair<uint32_t, DeclID> KindDeclIDPair;
-
// FIXME: Turn these into classes so we can have some type safety when
// we go from local ID to global and vice-versa.
typedef DeclID LocalDeclID;
@@ -235,7 +233,17 @@ namespace clang {
/// to create this AST file.
///
/// This block is part of the control block.
- INPUT_FILES_BLOCK_ID
+ INPUT_FILES_BLOCK_ID,
+
+ /// \brief The block of configuration options, used to check that
+ /// a module is being used in a configuration compatible with the
+ /// configuration in which it was built.
+ ///
+ /// This block is part of the control block.
+ OPTIONS_BLOCK_ID,
+
+ /// \brief A block containing a module file extension.
+ EXTENSION_BLOCK_ID,
};
/// \brief Record types that occur within the control block.
@@ -246,63 +254,72 @@ namespace clang {
/// \brief Record code for the list of other AST files imported by
/// this AST file.
- IMPORTS = 2,
-
- /// \brief Record code for the language options table.
- ///
- /// The record with this code contains the contents of the
- /// LangOptions structure. We serialize the entire contents of
- /// the structure, and let the reader decide which options are
- /// actually important to check.
- LANGUAGE_OPTIONS = 3,
-
- /// \brief Record code for the target options table.
- TARGET_OPTIONS = 4,
+ IMPORTS,
/// \brief Record code for the original file that was used to
/// generate the AST file, including both its file ID and its
/// name.
- ORIGINAL_FILE = 5,
+ ORIGINAL_FILE,
/// \brief The directory that the PCH was originally created in.
- ORIGINAL_PCH_DIR = 6,
+ ORIGINAL_PCH_DIR,
/// \brief Record code for file ID of the file or buffer that was used to
/// generate the AST file.
- ORIGINAL_FILE_ID = 7,
+ ORIGINAL_FILE_ID,
/// \brief Offsets into the input-files block where input files
/// reside.
- INPUT_FILE_OFFSETS = 8,
-
- /// \brief Record code for the diagnostic options table.
- DIAGNOSTIC_OPTIONS = 9,
-
- /// \brief Record code for the filesystem options table.
- FILE_SYSTEM_OPTIONS = 10,
-
- /// \brief Record code for the headers search options table.
- HEADER_SEARCH_OPTIONS = 11,
-
- /// \brief Record code for the preprocessor options table.
- PREPROCESSOR_OPTIONS = 12,
+ INPUT_FILE_OFFSETS,
/// \brief Record code for the module name.
- MODULE_NAME = 13,
+ MODULE_NAME,
/// \brief Record code for the module map file that was used to build this
/// AST file.
- MODULE_MAP_FILE = 14,
+ MODULE_MAP_FILE,
/// \brief Record code for the signature that identifiers this AST file.
- SIGNATURE = 15,
+ SIGNATURE,
/// \brief Record code for the module build directory.
- MODULE_DIRECTORY = 16,
+ MODULE_DIRECTORY,
+ };
+
+ /// \brief Record types that occur within the options block inside
+ /// the control block.
+ enum OptionsRecordTypes {
+ /// \brief Record code for the language options table.
+ ///
+ /// The record with this code contains the contents of the
+ /// LangOptions structure. We serialize the entire contents of
+ /// the structure, and let the reader decide which options are
+ /// actually important to check.
+ LANGUAGE_OPTIONS = 1,
- /// \brief Record code for the list of other AST files made available by
- /// this AST file but not actually used by it.
- KNOWN_MODULE_FILES = 17,
+ /// \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,
+
+ /// \brief Record code for the headers search options table.
+ HEADER_SEARCH_OPTIONS,
+
+ /// \brief Record code for the preprocessor options table.
+ PREPROCESSOR_OPTIONS,
+ };
+
+ /// \brief Record code for extension blocks.
+ enum ExtensionBlockRecordTypes {
+ /// Metadata describing this particular extension.
+ EXTENSION_METADATA = 1,
+
+ /// The first record ID allocated to the extensions themselves.
+ FIRST_EXTENSION_RECORD_ID = 4
};
/// \brief Record types that occur within the input-files block
@@ -350,7 +367,7 @@ namespace clang {
/// \brief This is so that older clang versions, before the introduction
/// of the control block, can read and reject the newer PCH format.
- /// *DON"T CHANGE THIS NUMBER*.
+ /// *DON'T CHANGE THIS NUMBER*.
METADATA_OLD_FORMAT = 4,
/// \brief Record code for the identifier table.
@@ -440,10 +457,7 @@ namespace clang {
/// declarations.
TU_UPDATE_LEXICAL = 22,
- /// \brief Record code for the array describing the locations (in the
- /// LOCAL_REDECLARATIONS record) of the redeclaration chains, indexed by
- /// the first known ID.
- LOCAL_REDECLARATIONS_MAP = 23,
+ // ID 23 used to be for a list of local redeclarations.
/// \brief Record code for declarations that Sema keeps references of.
SEMA_DECL_REFS = 24,
@@ -521,13 +535,8 @@ namespace clang {
/// imported by the AST file.
IMPORTED_MODULES = 43,
- // ID 40 used to be a table of merged canonical declarations.
-
- /// \brief Record code for the array of redeclaration chains.
- ///
- /// This array can only be interpreted properly using the local
- /// redeclarations map.
- LOCAL_REDECLARATIONS = 45,
+ // 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).
@@ -543,7 +552,10 @@ namespace clang {
/// macro definition.
MACRO_OFFSET = 47,
- // ID 48 used to be a table of macros.
+ /// \brief A list of "interesting" identifiers. Only used in C++ (where we
+ /// don't normally do lookups into the serialized identifier table). These
+ /// are eagerly deserialized.
+ INTERESTING_IDENTIFIERS = 48,
/// \brief Record code for undefined but used functions and variables that
/// need a definition in this TU.
@@ -758,26 +770,46 @@ namespace clang {
PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,
/// \brief The pseudo-object placeholder type.
PREDEF_TYPE_PSEUDO_OBJECT = 35,
- /// \brief The __va_list_tag placeholder type.
- PREDEF_TYPE_VA_LIST_TAG = 36,
/// \brief The placeholder type for builtin functions.
- PREDEF_TYPE_BUILTIN_FN = 37,
+ PREDEF_TYPE_BUILTIN_FN = 36,
/// \brief OpenCL 1d image type.
- PREDEF_TYPE_IMAGE1D_ID = 38,
+ PREDEF_TYPE_IMAGE1D_ID = 37,
/// \brief OpenCL 1d image array type.
- PREDEF_TYPE_IMAGE1D_ARR_ID = 39,
+ PREDEF_TYPE_IMAGE1D_ARR_ID = 38,
/// \brief OpenCL 1d image buffer type.
- PREDEF_TYPE_IMAGE1D_BUFF_ID = 40,
+ PREDEF_TYPE_IMAGE1D_BUFF_ID = 39,
/// \brief OpenCL 2d image type.
- PREDEF_TYPE_IMAGE2D_ID = 41,
+ PREDEF_TYPE_IMAGE2D_ID = 40,
/// \brief OpenCL 2d image array type.
- PREDEF_TYPE_IMAGE2D_ARR_ID = 42,
+ 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 = 43,
+ PREDEF_TYPE_IMAGE3D_ID = 48,
/// \brief OpenCL event type.
- PREDEF_TYPE_EVENT_ID = 44,
+ PREDEF_TYPE_EVENT_ID = 49,
+ /// \brief OpenCL clk event type.
+ PREDEF_TYPE_CLK_EVENT_ID = 50,
/// \brief OpenCL sampler type.
- PREDEF_TYPE_SAMPLER_ID = 45
+ PREDEF_TYPE_SAMPLER_ID = 51,
+ /// \brief OpenCL queue type.
+ PREDEF_TYPE_QUEUE_ID = 52,
+ /// \brief OpenCL ndrange type.
+ PREDEF_TYPE_NDRANGE_ID = 53,
+ /// \brief OpenCL reserve_id type.
+ PREDEF_TYPE_RESERVE_ID_ID = 54,
+ /// \brief The placeholder type for OpenMP array section.
+ PREDEF_TYPE_OMP_ARRAY_SECTION = 55
};
/// \brief The number of predefined type IDs that are reserved for
@@ -875,7 +907,9 @@ namespace clang {
/// \brief A DecayedType record.
TYPE_DECAYED = 41,
/// \brief An AdjustedType record.
- TYPE_ADJUSTED = 42
+ TYPE_ADJUSTED = 42,
+ /// \brief A PipeType record.
+ TYPE_PIPE = 43
};
/// \brief The type IDs for special types constructed by semantic
@@ -913,44 +947,56 @@ namespace clang {
/// it is created.
enum PredefinedDeclIDs {
/// \brief The NULL declaration.
- PREDEF_DECL_NULL_ID = 0,
-
+ PREDEF_DECL_NULL_ID = 0,
+
/// \brief The translation unit.
PREDEF_DECL_TRANSLATION_UNIT_ID = 1,
-
+
/// \brief The Objective-C 'id' type.
PREDEF_DECL_OBJC_ID_ID = 2,
-
+
/// \brief The Objective-C 'SEL' type.
PREDEF_DECL_OBJC_SEL_ID = 3,
-
+
/// \brief The Objective-C 'Class' type.
PREDEF_DECL_OBJC_CLASS_ID = 4,
-
+
/// \brief The Objective-C 'Protocol' type.
PREDEF_DECL_OBJC_PROTOCOL_ID = 5,
-
+
/// \brief The signed 128-bit integer type.
PREDEF_DECL_INT_128_ID = 6,
/// \brief The unsigned 128-bit integer type.
PREDEF_DECL_UNSIGNED_INT_128_ID = 7,
-
+
/// \brief The internal 'instancetype' typedef.
PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,
/// \brief The internal '__builtin_va_list' typedef.
PREDEF_DECL_BUILTIN_VA_LIST_ID = 9,
+ /// \brief The internal '__va_list_tag' struct, if any.
+ PREDEF_DECL_VA_LIST_TAG = 10,
+
+ /// \brief The internal '__builtin_ms_va_list' typedef.
+ PREDEF_DECL_BUILTIN_MS_VA_LIST_ID = 11,
+
/// \brief The extern "C" context.
- PREDEF_DECL_EXTERN_C_CONTEXT_ID = 10,
+ PREDEF_DECL_EXTERN_C_CONTEXT_ID = 12,
+
+ /// \brief The internal '__make_integer_seq' template.
+ PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 13,
};
/// \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 = 11;
+ const unsigned int NUM_PREDEF_DECL_IDS = 14;
+
+ /// \brief Record code for a list of local redeclarations of a declaration.
+ const unsigned int LOCAL_REDECLARATIONS = 50;
/// \brief Record codes for each kind of declaration.
///
@@ -1369,6 +1415,7 @@ namespace clang {
// Microsoft
EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr
+ EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR, // MSPropertySubscriptExpr
EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr).
EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type).
STMT_SEH_LEAVE, // SEHLeaveStmt
@@ -1397,10 +1444,15 @@ namespace clang {
STMT_OMP_ORDERED_DIRECTIVE,
STMT_OMP_ATOMIC_DIRECTIVE,
STMT_OMP_TARGET_DIRECTIVE,
+ STMT_OMP_TARGET_DATA_DIRECTIVE,
STMT_OMP_TEAMS_DIRECTIVE,
STMT_OMP_TASKGROUP_DIRECTIVE,
STMT_OMP_CANCELLATION_POINT_DIRECTIVE,
STMT_OMP_CANCEL_DIRECTIVE,
+ STMT_OMP_TASKLOOP_DIRECTIVE,
+ STMT_OMP_TASKLOOP_SIMD_DIRECTIVE,
+ STMT_OMP_DISTRIBUTE_DIRECTIVE,
+ EXPR_OMP_ARRAY_SECTION,
// ARC
EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
@@ -1484,8 +1536,72 @@ namespace clang {
}
};
+ /// \brief A key used when looking up entities by \ref DeclarationName.
+ ///
+ /// Different \ref DeclarationNames are mapped to different keys, but the
+ /// same key can occasionally represent multiple names (for names that
+ /// contain types, in particular).
+ class DeclarationNameKey {
+ typedef unsigned NameKind;
+
+ NameKind Kind;
+ uint64_t Data;
+
+ public:
+ DeclarationNameKey() : Kind(), Data() {}
+ DeclarationNameKey(DeclarationName Name);
+
+ DeclarationNameKey(NameKind Kind, uint64_t Data)
+ : Kind(Kind), Data(Data) {}
+
+ NameKind getKind() const { return Kind; }
+
+ IdentifierInfo *getIdentifier() const {
+ assert(Kind == DeclarationName::Identifier ||
+ Kind == DeclarationName::CXXLiteralOperatorName);
+ return (IdentifierInfo *)Data;
+ }
+ Selector getSelector() const {
+ assert(Kind == DeclarationName::ObjCZeroArgSelector ||
+ Kind == DeclarationName::ObjCOneArgSelector ||
+ Kind == DeclarationName::ObjCMultiArgSelector);
+ return Selector(Data);
+ }
+ OverloadedOperatorKind getOperatorKind() const {
+ assert(Kind == DeclarationName::CXXOperatorName);
+ return (OverloadedOperatorKind)Data;
+ }
+
+ /// Compute a fingerprint of this key for use in on-disk hash table.
+ unsigned getHash() const;
+
+ friend bool operator==(const DeclarationNameKey &A,
+ const DeclarationNameKey &B) {
+ return A.Kind == B.Kind && A.Data == B.Data;
+ }
+ };
+
/// @}
}
} // end namespace clang
+namespace llvm {
+ template <> struct DenseMapInfo<clang::serialization::DeclarationNameKey> {
+ static clang::serialization::DeclarationNameKey getEmptyKey() {
+ return clang::serialization::DeclarationNameKey(-1, 1);
+ }
+ static clang::serialization::DeclarationNameKey getTombstoneKey() {
+ return clang::serialization::DeclarationNameKey(-1, 2);
+ }
+ static unsigned
+ getHashValue(const clang::serialization::DeclarationNameKey &Key) {
+ return Key.getHash();
+ }
+ static bool isEqual(const clang::serialization::DeclarationNameKey &L,
+ const clang::serialization::DeclarationNameKey &R) {
+ return L == R;
+ }
+ };
+}
+
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
index 840655e..588a6a9 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
@@ -30,6 +30,7 @@
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ContinuousRangeMap.h"
#include "clang/Serialization/Module.h"
+#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Serialization/ModuleManager.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
@@ -38,6 +39,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Bitcode/BitstreamReader.h"
@@ -179,7 +181,8 @@ public:
unsigned Value) {}
/// This is called for each AST file loaded.
- virtual void visitModuleFile(StringRef Filename) {}
+ virtual void visitModuleFile(StringRef Filename,
+ serialization::ModuleKind Kind) {}
/// \brief Returns true if this \c ASTReaderListener wants to receive the
/// input files of the AST file via \c visitInputFile, false otherwise.
@@ -194,7 +197,7 @@ public:
///
/// \returns true to continue receiving the next input file, false to stop.
virtual bool visitInputFile(StringRef Filename, bool isSystem,
- bool isOverridden) {
+ bool isOverridden, bool isExplicitModule) {
return true;
}
@@ -204,6 +207,10 @@ public:
/// \brief If needsImportVisitation returns \c true, this is called for each
/// AST file imported by this AST file.
virtual void visitImport(StringRef Filename) {}
+
+ /// Indicates that a particular module file extension has been read.
+ virtual void readModuleFileExtension(
+ const ModuleFileExtensionMetadata &Metadata) {}
};
/// \brief Simple wrapper class for chaining listeners.
@@ -242,9 +249,12 @@ public:
void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override;
bool needsInputFileVisitation() override;
bool needsSystemInputFileVisitation() override;
- void visitModuleFile(StringRef Filename) override;
+ void visitModuleFile(StringRef Filename,
+ serialization::ModuleKind Kind) override;
bool visitInputFile(StringRef Filename, bool isSystem,
- bool isOverridden) override;
+ bool isOverridden, bool isExplicitModule) override;
+ void readModuleFileExtension(
+ const ModuleFileExtensionMetadata &Metadata) override;
};
/// \brief ASTReaderListener implementation to validate the information of
@@ -280,9 +290,8 @@ class ReadMethodPoolVisitor;
namespace reader {
class ASTIdentifierLookupTrait;
- /// \brief The on-disk hash table used for the DeclContext's Name lookup table.
- typedef llvm::OnDiskIterableChainedHashTable<ASTDeclContextNameLookupTrait>
- ASTDeclContextNameLookupTable;
+ /// \brief The on-disk hash table(s) used for DeclContext name lookup.
+ struct DeclContextLookupTable;
}
} // end namespace serialization
@@ -381,6 +390,9 @@ private:
/// \brief The module manager which manages modules and their dependencies
ModuleManager ModuleMgr;
+ /// A mapping from extension block names to module file extensions.
+ llvm::StringMap<IntrusiveRefCntPtr<ModuleFileExtension>> ModuleFileExtensions;
+
/// \brief A timer used to track the time spent deserializing.
std::unique_ptr<llvm::Timer> ReadTimer;
@@ -494,20 +506,36 @@ private:
/// \brief Map from a FileID to the file-level declarations that it contains.
llvm::DenseMap<FileID, FileDeclsInfo> FileDeclIDs;
+ /// \brief An array of lexical contents of a declaration context, as a sequence of
+ /// Decl::Kind, DeclID pairs.
+ typedef ArrayRef<llvm::support::unaligned_uint32_t> LexicalContents;
+
+ /// \brief Map from a DeclContext to its lexical contents.
+ llvm::DenseMap<const DeclContext*, std::pair<ModuleFile*, LexicalContents>>
+ LexicalDecls;
+
+ /// \brief Map from the TU to its lexical contents from each module file.
+ std::vector<std::pair<ModuleFile*, LexicalContents>> TULexicalDecls;
+
+ /// \brief Map from a DeclContext to its lookup tables.
+ llvm::DenseMap<const DeclContext *,
+ serialization::reader::DeclContextLookupTable> Lookups;
+
// Updates for visible decls can occur for other contexts than just the
- // TU, and when we read those update records, the actual context will not
- // be available yet (unless it's the TU), so have this pending map using the
- // ID as a key. It will be realized when the context is actually loaded.
- typedef
- SmallVector<std::pair<serialization::reader::ASTDeclContextNameLookupTable *,
- ModuleFile*>, 1> DeclContextVisibleUpdates;
- typedef llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
- DeclContextVisibleUpdatesPending;
+ // TU, and when we read those update records, the actual context may not
+ // be available yet, so have this pending map using the ID as a key. It
+ // will be realized when the context is actually loaded.
+ struct PendingVisibleUpdate {
+ ModuleFile *Mod;
+ const unsigned char *Data;
+ };
+ typedef SmallVector<PendingVisibleUpdate, 1> DeclContextVisibleUpdates;
/// \brief Updates to the visible declarations of declaration contexts that
/// haven't been loaded yet.
- DeclContextVisibleUpdatesPending PendingVisibleUpdates;
-
+ llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
+ PendingVisibleUpdates;
+
/// \brief The set of C++ or Objective-C classes that have forward
/// declarations that have not yet been linked to their definitions.
llvm::SmallPtrSet<Decl *, 4> PendingDefinitions;
@@ -524,11 +552,14 @@ private:
/// performed deduplication.
llvm::SetVector<NamedDecl*> PendingMergedDefinitionsToDeduplicate;
- /// \brief Read the records that describe the contents of declcontexts.
- bool ReadDeclContextStorage(ModuleFile &M,
- llvm::BitstreamCursor &Cursor,
- const std::pair<uint64_t, uint64_t> &Offsets,
- serialization::DeclContextInfo &Info);
+ /// \brief Read the record that describes the lexical contents of a DC.
+ bool ReadLexicalDeclContextStorage(ModuleFile &M,
+ llvm::BitstreamCursor &Cursor,
+ uint64_t Offset, DeclContext *DC);
+ /// \brief Read the record that describes the visible contents of a DC.
+ bool ReadVisibleDeclContextStorage(ModuleFile &M,
+ llvm::BitstreamCursor &Cursor,
+ uint64_t Offset, serialization::DeclID ID);
/// \brief A vector containing identifiers that have already been
/// loaded.
@@ -914,20 +945,10 @@ private:
/// Objective-C protocols.
std::deque<Decl *> InterestingDecls;
- /// \brief The set of redeclarable declarations that have been deserialized
- /// since the last time the declaration chains were linked.
- llvm::SmallPtrSet<Decl *, 16> RedeclsDeserialized;
-
/// \brief The list of redeclaration chains that still need to be
- /// reconstructed.
- ///
- /// Each element is the canonical declaration of the chain.
- /// Elements in this vector should be unique; use
- /// PendingDeclChainsKnown to ensure uniqueness.
- SmallVector<Decl *, 16> PendingDeclChains;
-
- /// \brief Keeps track of the elements added to PendingDeclChains.
- llvm::SmallSet<Decl *, 16> PendingDeclChainsKnown;
+ /// reconstructed, and the local offset to the corresponding list
+ /// of redeclarations.
+ SmallVector<std::pair<Decl *, uint64_t>, 16> PendingDeclChains;
/// \brief The list of canonical declarations whose redeclaration chains
/// need to be marked as incomplete once we're done deserializing things.
@@ -972,13 +993,6 @@ private:
/// module is loaded.
SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded;
- /// \brief A mapping from a primary context for a declaration chain to the
- /// other declarations of that entity that also have name lookup tables.
- /// Used when we merge together two class definitions that have different
- /// sets of declared special member functions.
- llvm::DenseMap<const DeclContext*, SmallVector<const DeclContext*, 2>>
- MergedLookups;
-
typedef llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2> >
KeyDeclsMap;
@@ -1044,12 +1058,11 @@ private:
off_t StoredSize;
time_t StoredTime;
bool Overridden;
+ bool Transient;
};
/// \brief Reads the stored information about an input file.
InputFileInfo readInputFileInfo(ModuleFile &F, unsigned ID);
- /// \brief A convenience method to read the filename from an input file.
- std::string getInputFileName(ModuleFile &F, unsigned ID);
/// \brief Retrieve the file entry and 'overridden' bit for an input
/// file in the given module file.
@@ -1090,6 +1103,10 @@ public:
Visit(GetExistingDecl(ID));
}
+ /// \brief Get the loaded lookup tables for \p Primary, if any.
+ const serialization::reader::DeclContextLookupTable *
+ getLoadedLookupTables(DeclContext *Primary) const;
+
private:
struct ImportedModule {
ModuleFile *Mod;
@@ -1112,7 +1129,12 @@ private:
SmallVectorImpl<ImportedModule> &Loaded,
const ModuleFile *ImportedBy,
unsigned ClientLoadCapabilities);
+ static ASTReadResult ReadOptionsBlock(
+ llvm::BitstreamCursor &Stream, unsigned ClientLoadCapabilities,
+ bool AllowCompatibleConfigurationMismatch, ASTReaderListener &Listener,
+ std::string &SuggestedPredefines);
ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities);
+ ASTReadResult ReadExtensionBlock(ModuleFile &F);
bool ParseLineTable(ModuleFile &F, const RecordData &Record);
bool ReadSourceManagerBlock(ModuleFile &F);
llvm::BitstreamCursor &SLocCursorForID(int ID);
@@ -1163,7 +1185,7 @@ private:
RecordLocation DeclCursorForID(serialization::DeclID ID,
unsigned &RawLocation);
void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D);
- void loadPendingDeclChain(Decl *D);
+ void loadPendingDeclChain(Decl *D, uint64_t LocalOffset);
void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D,
unsigned PreviousGeneration = 0);
@@ -1261,9 +1283,12 @@ public:
/// \param Context the AST context that this precompiled header will be
/// loaded into.
///
- /// \param PCHContainerOps the PCHContainerOperations to use for loading and
+ /// \param PCHContainerRdr the PCHContainerOperations to use for loading and
/// creating modules.
///
+ /// \param Extensions the list of module file extensions that can be loaded
+ /// from the AST files.
+ ///
/// \param isysroot If non-NULL, the system include path specified by the
/// user. This is only used with relocatable PCH files. If non-NULL,
/// a relocatable PCH file will use the default path "/".
@@ -1290,6 +1315,7 @@ public:
/// deserializing.
ASTReader(Preprocessor &PP, ASTContext &Context,
const PCHContainerReader &PCHContainerRdr,
+ ArrayRef<IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
StringRef isysroot = "", bool DisableValidation = false,
bool AllowASTWithCompilerErrors = false,
bool AllowConfigurationMismatch = false,
@@ -1300,6 +1326,7 @@ public:
SourceManager &getSourceManager() const { return SourceMgr; }
FileManager &getFileManager() const { return FileMgr; }
+ DiagnosticsEngine &getDiags() const { return Diags; }
/// \brief Flags that indicate what kind of AST loading failures the client
/// of the AST reader can directly handle.
@@ -1467,6 +1494,7 @@ public:
static bool
readASTFileControlBlock(StringRef Filename, FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr,
+ bool FindModuleFileExtensions,
ASTReaderListener &Listener);
/// \brief Determine whether the given AST file is acceptable to load into a
@@ -1684,7 +1712,7 @@ public:
/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
/// specified cursor. Read the abbreviations that are at the top of the block
/// and then leave the cursor pointing into the block.
- bool ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, unsigned BlockID);
+ static bool ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, unsigned BlockID);
/// \brief Finds all the visible declarations with a given name.
/// The current implementation of this method just loads the entire
@@ -1698,16 +1726,17 @@ public:
/// \param DC The declaration context whose declarations will be
/// read.
///
+ /// \param IsKindWeWant A predicate indicating which declaration kinds
+ /// we are interested in.
+ ///
/// \param Decls Vector that will contain the declarations loaded
/// from the external source. The caller is responsible for merging
/// these declarations with any declarations already stored in the
/// declaration context.
- ///
- /// \returns true if there was an error while reading the
- /// declarations for this declaration context.
- ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Decls) override;
+ void
+ FindExternalLexicalDecls(const DeclContext *DC,
+ llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Decls) override;
/// \brief Get the decls that are contained in a file in the Offset/Length
/// range. \p Length can be 0 to indicate a point at \p Offset instead of
@@ -1755,10 +1784,7 @@ public:
/// declarations with this name are visible from translation unit scope, their
/// declarations will be deserialized and introduced into the declaration
/// chain of the identifier.
- virtual IdentifierInfo *get(const char *NameStart, const char *NameEnd);
- IdentifierInfo *get(StringRef Name) override {
- return get(Name.begin(), Name.end());
- }
+ IdentifierInfo *get(StringRef Name) override;
/// \brief Retrieve an iterator into the set of all identifiers
/// in all loaded AST files.
@@ -1873,10 +1899,15 @@ public:
/// Note: overrides method in ExternalASTSource
Module *getModule(unsigned ID) override;
+ /// \brief Retrieve the module file with a given local ID within the specified
+ /// ModuleFile.
+ ModuleFile *getLocalModuleFile(ModuleFile &M, unsigned ID);
+
+ /// \brief Get an ID for the given module file.
+ unsigned getModuleFileID(ModuleFile *M);
+
/// \brief Return a descriptor for the corresponding module.
llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override;
- /// \brief Return a descriptor for the module.
- ASTSourceDescriptor getSourceDescriptor(const Module &M) override;
/// \brief Retrieve a selector from the given module with its local ID
/// number.
@@ -1921,8 +1952,9 @@ public:
unsigned &Idx);
/// \brief Read a template argument.
- TemplateArgument ReadTemplateArgument(ModuleFile &F,
- const RecordData &Record,unsigned &Idx);
+ TemplateArgument ReadTemplateArgument(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx,
+ bool Canonicalize = false);
/// \brief Read a template parameter list.
TemplateParameterList *ReadTemplateParameterList(ModuleFile &F,
@@ -1930,10 +1962,9 @@ public:
unsigned &Idx);
/// \brief Read a template argument array.
- void
- ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
- ModuleFile &F, const RecordData &Record,
- unsigned &Idx);
+ void ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
+ ModuleFile &F, const RecordData &Record,
+ unsigned &Idx, bool Canonicalize = false);
/// \brief Read a UnresolvedSet structure.
void ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set,
@@ -2082,12 +2113,8 @@ public:
SmallVector<std::pair<llvm::BitstreamCursor,
serialization::ModuleFile *>, 8> CommentsCursors;
- //RIDErief Loads comments ranges.
+ /// \brief Loads comments ranges.
void ReadComments() override;
-
- /// Return all input files for the given module file.
- void getInputFiles(ModuleFile &F,
- SmallVectorImpl<serialization::InputFile> &Files);
};
/// \brief Helper class that saves the current stream position and
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
index e830fdc..ef8c653 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
@@ -58,6 +58,8 @@ class OpaqueValueExpr;
class OpenCLOptions;
class ASTReader;
class Module;
+class ModuleFileExtension;
+class ModuleFileExtensionWriter;
class PreprocessedEntity;
class PreprocessingRecord;
class Preprocessor;
@@ -84,6 +86,7 @@ class ASTWriter : public ASTDeserializationListener,
public:
typedef SmallVector<uint64_t, 64> RecordData;
typedef SmallVectorImpl<uint64_t> RecordDataImpl;
+ typedef ArrayRef<uint64_t> RecordDataRef;
friend class ASTDeclWriter;
friend class ASTStmtWriter;
@@ -119,6 +122,12 @@ private:
/// \brief The base directory for any relative paths we emit.
std::string BaseDirectory;
+ /// \brief Indicates whether timestamps should be written to the produced
+ /// module file. This is the case for files implicitly written to the
+ /// module cache, where we need the timestamps to determine if the module
+ /// file is up to date, but not otherwise.
+ bool IncludeTimestamps;
+
/// \brief Indicates when the AST writing is actively performing
/// serialization, rather than just queueing updates.
bool WritingAST;
@@ -369,10 +378,6 @@ private:
/// coming from another AST file.
SmallVector<const Decl *, 16> UpdatingVisibleDecls;
- typedef llvm::SmallSetVector<const Decl *, 16> DeclsToRewriteTy;
- /// \brief Decls that will be replaced in the current dependent AST file.
- DeclsToRewriteTy DeclsToRewrite;
-
/// \brief The set of Objective-C class that have categories we
/// should serialize.
llvm::SetVector<ObjCInterfaceDecl *> ObjCClassesWithCategories;
@@ -399,6 +404,10 @@ private:
/// \brief The set of declarations that may have redeclaration chains that
/// need to be serialized.
llvm::SmallVector<const Decl *, 16> Redeclarations;
+
+ /// \brief A cache of the first local declaration for "interesting"
+ /// redeclaration chains.
+ llvm::DenseMap<const Decl *, const Decl *> FirstLocalDeclCache;
/// \brief Statements that we've encountered while serializing a
/// declaration or type.
@@ -484,20 +493,23 @@ private:
/// \brief A mapping from each known submodule to its ID number, which will
/// be a positive integer.
llvm::DenseMap<Module *, unsigned> SubmoduleIDs;
-
+
+ /// \brief A list of the module file extension writers.
+ std::vector<std::unique_ptr<ModuleFileExtensionWriter>>
+ ModuleFileExtensionWriters;
+
/// \brief Retrieve or create a submodule ID for this module.
unsigned getSubmoduleID(Module *Mod);
-
+
/// \brief Write the given subexpression to the bitstream.
void WriteSubStmt(Stmt *S,
llvm::DenseMap<Stmt *, uint64_t> &SubStmtEntries,
llvm::DenseSet<Stmt *> &ParentStmts);
void WriteBlockInfoBlock();
- void WriteControlBlock(Preprocessor &PP, ASTContext &Context,
- StringRef isysroot, const std::string &OutputFile);
- void WriteInputFiles(SourceManager &SourceMgr,
- HeaderSearchOptions &HSOpts,
+ uint64_t WriteControlBlock(Preprocessor &PP, ASTContext &Context,
+ StringRef isysroot, const std::string &OutputFile);
+ void WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts,
bool Modules);
void WriteSourceManagerBlock(SourceManager &SourceMgr,
const Preprocessor &PP);
@@ -519,8 +531,8 @@ private:
bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC);
bool isLookupResultEntirelyExternal(StoredDeclsList &Result, DeclContext *DC);
- uint32_t GenerateNameLookupTable(const DeclContext *DC,
- llvm::SmallVectorImpl<char> &LookupTable);
+ void GenerateNameLookupTable(const DeclContext *DC,
+ llvm::SmallVectorImpl<char> &LookupTable);
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
void WriteTypeDeclOffsets();
@@ -537,9 +549,10 @@ private:
void WriteFPPragmaOptions(const FPOptions &Opts);
void WriteOpenCLExtensions(Sema &SemaRef);
void WriteObjCCategories();
- void WriteRedeclarations();
void WriteLateParsedTemplates(Sema &SemaRef);
void WriteOptimizePragmaOptions(Sema &SemaRef);
+ void WriteModuleFileExtension(Sema &SemaRef,
+ ModuleFileExtensionWriter &Writer);
unsigned DeclParmVarAbbrev;
unsigned DeclContextLexicalAbbrev;
@@ -562,18 +575,25 @@ private:
void WriteDecl(ASTContext &Context, Decl *D);
void AddFunctionDefinition(const FunctionDecl *FD, RecordData &Record);
- void WriteASTCore(Sema &SemaRef,
- StringRef isysroot, const std::string &OutputFile,
- Module *WritingModule);
+ uint64_t WriteASTCore(Sema &SemaRef,
+ StringRef isysroot, const std::string &OutputFile,
+ Module *WritingModule);
public:
/// \brief Create a new precompiled header writer that outputs to
/// the given bitstream.
- ASTWriter(llvm::BitstreamWriter &Stream);
+ ASTWriter(llvm::BitstreamWriter &Stream,
+ ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
+ bool IncludeTimestamps = true);
~ASTWriter() override;
const LangOptions &getLangOpts() const;
+ /// \brief Get a timestamp for output into the AST file. The actual timestamp
+ /// of the specified file may be ignored if we have been instructed to not
+ /// include timestamps in the output file.
+ time_t getTimestampForOutput(const FileEntry *E) const;
+
/// \brief Write a precompiled header for the given semantic analysis.
///
/// \param SemaRef a reference to the semantic analysis object that processed
@@ -585,10 +605,12 @@ public:
/// \param isysroot if non-empty, write a relocatable file whose headers
/// are relative to the given system root. If we're writing a module, its
/// build directory will be used in preference to this if both are available.
- void WriteAST(Sema &SemaRef,
- const std::string &OutputFile,
- Module *WritingModule, StringRef isysroot,
- bool hasErrors = false);
+ ///
+ /// \return the module signature, which eventually will be a hash of
+ /// the module but currently is merely a random 32-bit number.
+ uint64_t WriteAST(Sema &SemaRef, const std::string &OutputFile,
+ Module *WritingModule, StringRef isysroot,
+ bool hasErrors = false);
/// \brief Emit a token.
void AddToken(const Token &Tok, RecordDataImpl &Record);
@@ -665,6 +687,10 @@ public:
const ASTTemplateArgumentListInfo *ASTTemplArgList,
RecordDataImpl &Record);
+ /// \brief Find the first local declaration of a given local redeclarable
+ /// decl.
+ const Decl *getFirstLocalDecl(const Decl *D);
+
/// \brief Emit a reference to a declaration.
void AddDeclRef(const Decl *D, RecordDataImpl &Record);
@@ -738,27 +764,20 @@ public:
void AddPath(StringRef Path, RecordDataImpl &Record);
/// \brief Emit the current record with the given path as a blob.
- void EmitRecordWithPath(unsigned Abbrev, RecordDataImpl &Record,
+ void EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record,
StringRef Path);
/// \brief Add a version tuple to the given record
void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record);
- void RewriteDecl(const Decl *D) {
- DeclsToRewrite.insert(D);
- }
-
- bool isRewritten(const Decl *D) const {
- return DeclsToRewrite.count(D);
- }
-
/// \brief Infer the submodule ID that contains an entity at the given
/// source location.
serialization::SubmoduleID inferSubmoduleIDFromLocation(SourceLocation Loc);
- /// \brief Retrieve a submodule ID for this module.
- /// Returns 0 If no ID has been associated with the module.
- unsigned getExistingSubmoduleID(Module *Mod) const;
+ /// \brief Retrieve or create a submodule ID for this module, or return 0 if
+ /// the submodule is neither local (a submodle of the currently-written module)
+ /// nor from an imported module.
+ unsigned getLocalOrImportedSubmoduleID(Module *Mod);
/// \brief Note that the identifier II occurs at the given offset
/// within the identifier table.
@@ -830,6 +849,7 @@ public:
unsigned getExprImplicitCastAbbrev() const { return ExprImplicitCastAbbrev; }
bool hasChain() const { return Chain; }
+ ASTReader *getChain() const { return Chain; }
// ASTDeserializationListener implementation
void ReaderInitialized(ASTReader *Reader) override;
@@ -845,24 +865,16 @@ public:
void CompletedTagDefinition(const TagDecl *D) override;
void AddedVisibleDecl(const DeclContext *DC, const Decl *D) override;
void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) override;
- void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
- const ClassTemplateSpecializationDecl *D) override;
- void AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
- const VarTemplateSpecializationDecl *D) override;
- void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
- const FunctionDecl *D) override;
void ResolvedExceptionSpec(const FunctionDecl *FD) override;
void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override;
void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
const FunctionDecl *Delete) override;
void CompletedImplicitDefinition(const FunctionDecl *D) override;
void StaticDataMemberInstantiated(const VarDecl *D) override;
+ void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) override;
- void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
- const ObjCPropertyDecl *OrigProp,
- const ObjCCategoryDecl *ClassExt) override;
void DeclarationMarkedUsed(const Decl *D) override;
void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
@@ -889,10 +901,13 @@ protected:
SmallVectorImpl<char> &getPCH() const { return Buffer->Data; }
public:
- PCHGenerator(const Preprocessor &PP, StringRef OutputFile,
- clang::Module *Module, StringRef isysroot,
- std::shared_ptr<PCHBuffer> Buffer,
- bool AllowASTWithErrors = false);
+ PCHGenerator(
+ const Preprocessor &PP, StringRef OutputFile,
+ clang::Module *Module, StringRef isysroot,
+ std::shared_ptr<PCHBuffer> Buffer,
+ ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
+ bool AllowASTWithErrors = false,
+ bool IncludeTimestamps = true);
~PCHGenerator() override;
void InitializeSema(Sema &S) override { SemaPtr = &S; }
void HandleTranslationUnit(ASTContext &Ctx) override;
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h b/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h
index ba4f7e2..0f14eca 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h
@@ -36,6 +36,7 @@ class FileEntry;
class FileManager;
class IdentifierIterator;
class PCHContainerOperations;
+class PCHContainerReader;
namespace serialization {
class ModuleFile;
@@ -193,7 +194,7 @@ public:
/// \brief Write a global index into the given
///
/// \param FileMgr The file manager to use to load module files.
- /// \param PCHContainerOps - The PCHContainerOperations to use for loading and
+ /// \param PCHContainerRdr - The PCHContainerOperations to use for loading and
/// creating modules.
/// \param Path The path to the directory containing module files, into
/// which the global index will be written.
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/Module.h b/contrib/llvm/tools/clang/include/clang/Serialization/Module.h
index c98ced4..d6d16a0 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/Module.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/Module.h
@@ -15,9 +15,11 @@
#ifndef LLVM_CLANG_SERIALIZATION_MODULE_H
#define LLVM_CLANG_SERIALIZATION_MODULE_H
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ContinuousRangeMap.h"
+#include "clang/Serialization/ModuleFileExtension.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/Endian.h"
@@ -31,7 +33,6 @@ template <typename Info> class OnDiskIterableChainedHashTable;
namespace clang {
-class FileEntry;
class DeclContext;
class Module;
@@ -50,17 +51,6 @@ enum ModuleKind {
MK_MainFile ///< File is a PCH file treated as the actual main file.
};
-/// \brief Information about the contents of a DeclContext.
-struct DeclContextInfo {
- DeclContextInfo()
- : NameLookupTableData(), LexicalDecls(), NumLexicalDecls() {}
-
- llvm::OnDiskIterableChainedHashTable<reader::ASTDeclContextNameLookupTrait>
- *NameLookupTableData; // an ASTDeclContextNameLookupTable.
- const KindDeclIDPair *LexicalDecls;
- unsigned NumLexicalDecls;
-};
-
/// \brief The input file that has been loaded from this AST file, along with
/// bools indicating whether this was an overridden buffer or if it was
/// out-of-date or not-found.
@@ -155,6 +145,9 @@ public:
/// \brief Whether this precompiled header is a relocatable PCH file.
bool RelocatablePCH;
+ /// \brief Whether timestamps are included in this module file.
+ bool HasTimestamps;
+
/// \brief The file entry for the module file.
const FileEntry *File;
@@ -202,6 +195,10 @@ public:
/// \brief The first source location in this module.
SourceLocation FirstLoc;
+ /// The list of extension readers that are attached to this module
+ /// file.
+ std::vector<std::unique_ptr<ModuleFileExtensionReader>> ExtensionReaders;
+
// === Input Files ===
/// \brief The cursor to the start of the input-files block.
llvm::BitstreamCursor InputFilesCursor;
@@ -270,6 +267,10 @@ public:
/// IdentifierHashTable.
void *IdentifierLookupTable;
+ /// \brief Offsets of identifiers that we're going to preload within
+ /// IdentifierTableData.
+ std::vector<unsigned> PreloadIdentifierOffsets;
+
// === Macros ===
/// \brief The cursor to the start of the preprocessor block, which stores
@@ -412,28 +413,10 @@ public:
/// indexed by the C++ ctor initializer list ID minus 1.
const uint32_t *CXXCtorInitializersOffsets;
- typedef llvm::DenseMap<const DeclContext *, DeclContextInfo>
- DeclContextInfosMap;
-
- /// \brief Information about the lexical and visible declarations
- /// for each DeclContext.
- DeclContextInfosMap DeclContextInfos;
-
/// \brief Array of file-level DeclIDs sorted by file.
const serialization::DeclID *FileSortedDecls;
unsigned NumFileSortedDecls;
- /// \brief Array of redeclaration chain location information within this
- /// module file, sorted by the first declaration ID.
- const serialization::LocalRedeclarationsInfo *RedeclarationsMap;
-
- /// \brief The number of redeclaration info entries in RedeclarationsMap.
- unsigned LocalNumRedeclarationsInMap;
-
- /// \brief The redeclaration chains for declarations local to this
- /// module file.
- SmallVector<uint64_t, 1> RedeclarationChains;
-
/// \brief Array of category list location information within this
/// module file, sorted by the definition ID.
const serialization::ObjCCategoriesInfo *ObjCCategoriesMap;
@@ -476,6 +459,11 @@ public:
/// any point during translation.
bool isDirectlyImported() const { return DirectlyImported; }
+ /// \brief Is this a module file for a module (rather than a PCH or similar).
+ bool isModule() const {
+ return Kind == MK_ImplicitModule || Kind == MK_ExplicitModule;
+ }
+
/// \brief Dump debugging output for this module.
void dump();
};
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h
new file mode 100644
index 0000000..ba2e2fd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h
@@ -0,0 +1,149 @@
+//===-- ModuleFileExtension.h - Module File Extensions ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H
+#define LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include <memory>
+#include <string>
+
+namespace llvm {
+class BitstreamCursor;
+class BitstreamWriter;
+class hash_code;
+class raw_ostream;
+}
+
+namespace clang {
+
+class ASTReader;
+class ASTWriter;
+class Sema;
+
+namespace serialization {
+ class ModuleFile;
+} // end namespace serialization
+
+/// Metadata for a module file extension.
+struct ModuleFileExtensionMetadata {
+ /// The name used to identify this particular extension block within
+ /// the resulting module file. It should be unique to the particular
+ /// extension, because this name will be used to match the name of
+ /// an extension block to the appropriate reader.
+ std::string BlockName;
+
+ /// The major version of the extension data.
+ unsigned MajorVersion;
+
+ /// The minor version of the extension data.
+ unsigned MinorVersion;
+
+ /// A string containing additional user information that will be
+ /// stored with the metadata.
+ std::string UserInfo;
+};
+
+class ModuleFileExtensionReader;
+class ModuleFileExtensionWriter;
+
+/// An abstract superclass that describes a custom extension to the
+/// module/precompiled header file format.
+///
+/// A module file extension can introduce additional information into
+/// compiled module files (.pcm) and precompiled headers (.pch) via a
+/// custom writer that can then be accessed via a custom reader when
+/// the module file or precompiled header is loaded.
+class ModuleFileExtension : public llvm::RefCountedBase<ModuleFileExtension> {
+public:
+ virtual ~ModuleFileExtension();
+
+ /// Retrieves the metadata for this module file extension.
+ virtual ModuleFileExtensionMetadata getExtensionMetadata() const = 0;
+
+ /// Hash information about the presence of this extension into the
+ /// module hash code.
+ ///
+ /// The module hash code is used to distinguish different variants
+ /// of a module that are incompatible. If the presence, absence, or
+ /// version of the module file extension should force the creation
+ /// of a separate set of module files, override this method to
+ /// combine that distinguishing information into the module hash
+ /// code.
+ ///
+ /// The default implementation of this function simply returns the
+ /// hash code as given, so the presence/absence of this extension
+ /// does not distinguish module files.
+ virtual llvm::hash_code hashExtension(llvm::hash_code c) const;
+
+ /// Create a new module file extension writer, which will be
+ /// responsible for writing the extension contents into a particular
+ /// module file.
+ virtual std::unique_ptr<ModuleFileExtensionWriter>
+ createExtensionWriter(ASTWriter &Writer) = 0;
+
+ /// Create a new module file extension reader, given the
+ /// metadata read from the block and the cursor into the extension
+ /// block.
+ ///
+ /// May return null to indicate that an extension block with the
+ /// given metadata cannot be read.
+ virtual std::unique_ptr<ModuleFileExtensionReader>
+ createExtensionReader(const ModuleFileExtensionMetadata &Metadata,
+ ASTReader &Reader, serialization::ModuleFile &Mod,
+ const llvm::BitstreamCursor &Stream) = 0;
+};
+
+/// Abstract base class that writes a module file extension block into
+/// a module file.
+class ModuleFileExtensionWriter {
+ ModuleFileExtension *Extension;
+
+protected:
+ ModuleFileExtensionWriter(ModuleFileExtension *Extension)
+ : Extension(Extension) { }
+
+public:
+ virtual ~ModuleFileExtensionWriter();
+
+ /// Retrieve the module file extension with which this writer is
+ /// associated.
+ ModuleFileExtension *getExtension() const { return Extension; }
+
+ /// Write the contents of the extension block into the given bitstream.
+ ///
+ /// Responsible for writing the contents of the extension into the
+ /// given stream. All of the contents should be written into custom
+ /// records with IDs >= FIRST_EXTENSION_RECORD_ID.
+ virtual void writeExtensionContents(Sema &SemaRef,
+ llvm::BitstreamWriter &Stream) = 0;
+};
+
+/// Abstract base class that reads a module file extension block from
+/// a module file.
+///
+/// Subclasses
+class ModuleFileExtensionReader {
+ ModuleFileExtension *Extension;
+
+protected:
+ ModuleFileExtensionReader(ModuleFileExtension *Extension)
+ : Extension(Extension) { }
+
+public:
+ /// Retrieve the module file extension with which this reader is
+ /// associated.
+ ModuleFileExtension *getExtension() const { return Extension; }
+
+ virtual ~ModuleFileExtensionReader();
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_FRONTEND_MODULEFILEEXTENSION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h
index ab39aef..08e7d40 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h
@@ -30,23 +30,22 @@ namespace serialization {
/// \brief Manages the set of modules loaded by an AST reader.
class ModuleManager {
- /// \brief The chain of AST files. The first entry is the one named by the
- /// user, the last one is the one that doesn't depend on anything further.
+ /// \brief The chain of AST files, in the order in which we started to load
+ /// them (this order isn't really useful for anything).
SmallVector<ModuleFile *, 2> Chain;
+ /// \brief The chain of non-module PCH files. The first entry is the one named
+ /// by the user, the last one is the one that doesn't depend on anything
+ /// further.
+ SmallVector<ModuleFile *, 2> PCHChain;
+
// \brief The roots of the dependency DAG of AST files. This is used
// to implement short-circuiting logic when running DFS over the dependencies.
SmallVector<ModuleFile *, 2> Roots;
-
+
/// \brief All loaded modules, indexed by name.
llvm::DenseMap<const FileEntry *, ModuleFile *> Modules;
- typedef llvm::SetVector<const FileEntry *> AdditionalKnownModuleFileSet;
-
- /// \brief Additional module files that are known but not loaded. Tracked
- /// here so that we can re-export them if necessary.
- AdditionalKnownModuleFileSet AdditionalKnownModuleFiles;
-
/// \brief FileManager that handles translating between filenames and
/// FileEntry *.
FileManager &FileMgr;
@@ -121,24 +120,26 @@ public:
const PCHContainerReader &PCHContainerRdr);
~ModuleManager();
- /// \brief Forward iterator to traverse all loaded modules. This is reverse
- /// source-order.
+ /// \brief Forward iterator to traverse all loaded modules.
ModuleIterator begin() { return Chain.begin(); }
/// \brief Forward iterator end-point to traverse all loaded modules
ModuleIterator end() { return Chain.end(); }
- /// \brief Const forward iterator to traverse all loaded modules. This is
- /// in reverse source-order.
+ /// \brief Const forward iterator to traverse all loaded modules.
ModuleConstIterator begin() const { return Chain.begin(); }
/// \brief Const forward iterator end-point to traverse all loaded modules
ModuleConstIterator end() const { return Chain.end(); }
- /// \brief Reverse iterator to traverse all loaded modules. This is in
- /// source order.
+ /// \brief Reverse iterator to traverse all loaded modules.
ModuleReverseIterator rbegin() { return Chain.rbegin(); }
/// \brief Reverse iterator end-point to traverse all loaded modules.
ModuleReverseIterator rend() { return Chain.rend(); }
-
+
+ /// \brief A range covering the PCH and preamble module files loaded.
+ llvm::iterator_range<ModuleConstIterator> pch_modules() const {
+ return llvm::make_range(PCHChain.begin(), PCHChain.end());
+ }
+
/// \brief Returns the primary module associated with the manager, that is,
/// the first module loaded
ModuleFile &getPrimaryModule() { return *Chain[0]; }
@@ -235,19 +236,6 @@ public:
/// has been "accepted", and will not (can not) be unloaded.
void moduleFileAccepted(ModuleFile *MF);
- /// \brief Notification from the frontend that the given module file is
- /// part of this compilation (even if not imported) and, if this compilation
- /// is exported, should be made available to importers of it.
- bool addKnownModuleFile(StringRef FileName);
-
- /// \brief Get a list of additional module files that are not currently
- /// loaded but are considered to be part of the current compilation.
- llvm::iterator_range<AdditionalKnownModuleFileSet::const_iterator>
- getAdditionalKnownModuleFiles() {
- return llvm::make_range(AdditionalKnownModuleFiles.begin(),
- AdditionalKnownModuleFiles.end());
- }
-
/// \brief Visit each of the modules.
///
/// This routine visits each of the modules, starting with the
@@ -259,51 +247,17 @@ public:
/// operations that can find data in any of the loaded modules.
///
/// \param Visitor A visitor function that will be invoked with each
- /// module and the given user data pointer. The return value must be
- /// convertible to bool; when false, the visitation continues to
- /// modules that the current module depends on. When true, the
- /// visitation skips any modules that the current module depends on.
- ///
- /// \param UserData User data associated with the visitor object, which
- /// will be passed along to the visitor.
+ /// module. The return value must be convertible to bool; when false, the
+ /// visitation continues to modules that the current module depends on. When
+ /// true, the visitation skips any modules that the current module depends on.
///
/// \param ModuleFilesHit If non-NULL, contains the set of module files
/// that we know we need to visit because the global module index told us to.
/// Any module that is known to both the global module index and the module
/// manager that is *not* in this set can be skipped.
- void visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData,
+ void visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit = nullptr);
- /// \brief Control DFS behavior during preorder visitation.
- enum DFSPreorderControl {
- Continue, /// Continue visiting all nodes.
- Abort, /// Stop the visitation immediately.
- SkipImports, /// Do not visit imports of the current node.
- };
-
- /// \brief Visit each of the modules with a depth-first traversal.
- ///
- /// This routine visits each of the modules known to the module
- /// manager using a depth-first search, starting with the first
- /// loaded module. The traversal invokes one callback before
- /// traversing the imports (preorder traversal) and one after
- /// traversing the imports (postorder traversal).
- ///
- /// \param PreorderVisitor A visitor function that will be invoked with each
- /// module before visiting its imports. The visitor can control how to
- /// continue the visitation through its return value.
- ///
- /// \param PostorderVisitor A visitor function taht will be invoked with each
- /// module after visiting its imports. The visitor may return true at any time
- /// to abort the depth-first visitation.
- ///
- /// \param UserData User data ssociated with the visitor object,
- /// which will be passed along to the user.
- void visitDepthFirst(DFSPreorderControl (*PreorderVisitor)(ModuleFile &M,
- void *UserData),
- bool (*PostorderVisitor)(ModuleFile &M, void *UserData),
- void *UserData);
-
/// \brief Attempt to resolve the given module file name to a file entry.
///
/// \param FileName The name of the module file.
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index f02e48a4..3959de2 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -253,9 +253,18 @@ private:
/// \sa getMaxTimesInlineLarge
Optional<unsigned> MaxTimesInlineLarge;
+ /// \sa getMinCFGSizeTreatFunctionsAsLarge
+ Optional<unsigned> MinCFGSizeTreatFunctionsAsLarge;
+
/// \sa getMaxNodesPerTopLevelFunction
Optional<unsigned> MaxNodesPerTopLevelFunction;
+ /// \sa shouldInlineLambdas
+ Optional<bool> InlineLambdas;
+
+ /// \sa shouldWidenLoops
+ Optional<bool> WidenLoops;
+
/// A helper function that retrieves option for a given full-qualified
/// checker name.
/// Options for checkers can be specified via 'analyzer-config' command-line
@@ -502,6 +511,13 @@ public:
/// This is controlled by the 'max-times-inline-large' config option.
unsigned getMaxTimesInlineLarge();
+ /// Returns the number of basic blocks a function needs to have to be
+ /// considered large for the 'max-times-inline-large' config option.
+ ///
+ /// This is controlled by the 'min-cfg-size-treat-functions-as-large' config
+ /// option.
+ unsigned getMinCFGSizeTreatFunctionsAsLarge();
+
/// Returns the maximum number of nodes the analyzer can generate while
/// exploring a top level function (for each exploded graph).
/// 150000 is default; 0 means no limit.
@@ -509,6 +525,14 @@ public:
/// This is controlled by the 'max-nodes' config option.
unsigned getMaxNodesPerTopLevelFunction();
+ /// Returns true if lambdas should be inlined. Otherwise a sink node will be
+ /// generated each time a LambdaExpr is visited.
+ bool shouldInlineLambdas();
+
+ /// Returns true if the analysis should try to widen loops.
+ /// This is controlled by the 'widen-loops' config option.
+ bool shouldWidenLoops();
+
public:
AnalyzerOptions() :
AnalysisStoreOpt(RegionStoreModel),
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
index 83b05ec..197d27a 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
@@ -37,6 +37,9 @@ class PathDiagnosticPiece;
/// will have to provide your own implementation.)
class BugReporterVisitor : public llvm::FoldingSetNode {
public:
+ BugReporterVisitor() = default;
+ BugReporterVisitor(const BugReporterVisitor &) = default;
+ BugReporterVisitor(BugReporterVisitor &&) {}
virtual ~BugReporterVisitor();
/// \brief Returns a copy of this BugReporter.
@@ -92,9 +95,8 @@ class BugReporterVisitorImpl : public BugReporterVisitor {
}
};
-class FindLastStoreBRVisitor
- : public BugReporterVisitorImpl<FindLastStoreBRVisitor>
-{
+class FindLastStoreBRVisitor final
+ : public BugReporterVisitorImpl<FindLastStoreBRVisitor> {
const MemRegion *R;
SVal V;
bool Satisfied;
@@ -124,9 +126,8 @@ public:
BugReport &BR) override;
};
-class TrackConstraintBRVisitor
- : public BugReporterVisitorImpl<TrackConstraintBRVisitor>
-{
+class TrackConstraintBRVisitor final
+ : public BugReporterVisitorImpl<TrackConstraintBRVisitor> {
DefinedSVal Constraint;
bool Assumption;
bool IsSatisfied;
@@ -161,8 +162,8 @@ private:
/// \class NilReceiverBRVisitor
/// \brief Prints path notes when a message is sent to a nil receiver.
-class NilReceiverBRVisitor
- : public BugReporterVisitorImpl<NilReceiverBRVisitor> {
+class NilReceiverBRVisitor final
+ : public BugReporterVisitorImpl<NilReceiverBRVisitor> {
public:
void Profile(llvm::FoldingSetNodeID &ID) const override {
@@ -181,7 +182,8 @@ public:
};
/// Visitor that tries to report interesting diagnostics from conditions.
-class ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> {
+class ConditionBRVisitor final
+ : public BugReporterVisitorImpl<ConditionBRVisitor> {
public:
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int x = 0;
@@ -247,8 +249,8 @@ public:
/// \brief Suppress reports that might lead to known false positives.
///
/// Currently this suppresses reports based on locations of bugs.
-class LikelyFalsePositiveSuppressionBRVisitor
- : public BugReporterVisitorImpl<LikelyFalsePositiveSuppressionBRVisitor> {
+class LikelyFalsePositiveSuppressionBRVisitor final
+ : public BugReporterVisitorImpl<LikelyFalsePositiveSuppressionBRVisitor> {
public:
static void *getTag() {
static int Tag = 0;
@@ -276,8 +278,8 @@ public:
///
/// As a result, BugReporter will not prune the path through the function even
/// if the region's contents are not modified/accessed by the call.
-class UndefOrNullArgVisitor
- : public BugReporterVisitorImpl<UndefOrNullArgVisitor> {
+class UndefOrNullArgVisitor final
+ : public BugReporterVisitorImpl<UndefOrNullArgVisitor> {
/// The interesting memory region this visitor is tracking.
const MemRegion *R;
@@ -297,9 +299,8 @@ public:
BugReport &BR) override;
};
-class SuppressInlineDefensiveChecksVisitor
-: public BugReporterVisitorImpl<SuppressInlineDefensiveChecksVisitor>
-{
+class SuppressInlineDefensiveChecksVisitor final
+ : public BugReporterVisitorImpl<SuppressInlineDefensiveChecksVisitor> {
/// The symbolic value for which we are tracking constraints.
/// This value is constrained to null in the end of path.
DefinedSVal V;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index 941d5240..35421f9 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -122,7 +122,7 @@ class PathDiagnosticRange : public SourceRange {
public:
bool isPoint;
- PathDiagnosticRange(const SourceRange &R, bool isP = false)
+ PathDiagnosticRange(SourceRange R, bool isP = false)
: SourceRange(R), isPoint(isP) {}
PathDiagnosticRange() : isPoint(false) {}
@@ -422,7 +422,6 @@ class PathPieces : public std::list<IntrusiveRefCntPtr<PathDiagnosticPiece> > {
void flattenTo(PathPieces &Primary, PathPieces &Current,
bool ShouldFlattenMacros) const;
public:
- ~PathPieces();
PathPieces flatten(bool ShouldFlattenMacros) const {
PathPieces Result;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
index 099d763..1410af1 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
@@ -131,6 +131,21 @@ public:
}
};
+class ObjCMessageNil {
+ template <typename CHECKER>
+ static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkObjCMessageNil(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForObjCMessageNil(
+ CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
+ }
+};
+
class PostObjCMessage {
template <typename CHECKER>
static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
@@ -514,6 +529,10 @@ struct ImplicitNullDerefEvent {
bool IsLoad;
ExplodedNode *SinkNode;
BugReporter *BR;
+ // When true, the dereference is in the source code directly. When false, the
+ // dereference might happen later (for example pointer passed to a parameter
+ // that is marked with nonnull attribute.)
+ bool IsDirectDereference;
};
/// \brief A helper class which wraps a boolean value set to false by default.
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 8a1a82b..bc9af49 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -89,11 +89,16 @@ class CheckName {
explicit CheckName(StringRef Name) : Name(Name) {}
public:
- CheckName() {}
- CheckName(const CheckName &Other) : Name(Other.Name) {}
+ CheckName() = default;
StringRef getName() const { return Name; }
};
+enum class ObjCMessageVisitKind {
+ Pre,
+ Post,
+ MessageNil
+};
+
class CheckerManager {
const LangOptions LangOpts;
AnalyzerOptionsRef AOptions;
@@ -212,7 +217,7 @@ public:
const ExplodedNodeSet &Src,
const ObjCMethodCall &msg,
ExprEngine &Eng) {
- runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
+ runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng);
}
/// \brief Run checkers for post-visiting obj-c messages.
@@ -221,12 +226,22 @@ public:
const ObjCMethodCall &msg,
ExprEngine &Eng,
bool wasInlined = false) {
- runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng,
+ runCheckersForObjCMessage(ObjCMessageVisitKind::Post, Dst, Src, msg, Eng,
wasInlined);
}
+ /// \brief Run checkers for visiting an obj-c message to nil.
+ void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMethodCall &msg,
+ ExprEngine &Eng) {
+ runCheckersForObjCMessage(ObjCMessageVisitKind::MessageNil, Dst, Src, msg,
+ Eng);
+ }
+
+
/// \brief Run checkers for visiting obj-c messages.
- void runCheckersForObjCMessage(bool isPreVisit,
+ void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
const ObjCMethodCall &msg, ExprEngine &Eng,
@@ -458,6 +473,8 @@ public:
void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
+ void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn);
+
void _registerForPreCall(CheckCallFunc checkfn);
void _registerForPostCall(CheckCallFunc checkfn);
@@ -558,8 +575,14 @@ private:
const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
bool isPreVisit);
+ /// Returns the checkers that have registered for callbacks of the
+ /// given \p Kind.
+ const std::vector<CheckObjCMessageFunc> &
+ getObjCMessageCheckers(ObjCMessageVisitKind Kind);
+
std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
+ std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers;
std::vector<CheckCallFunc> PreCallCheckers;
std::vector<CheckCallFunc> PostCallCheckers;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h
new file mode 100644
index 0000000..b3c4f14
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h
@@ -0,0 +1,51 @@
+//===---------- IssueHash.h - Generate identification hashes ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_ISSUE_HASH_H
+#define LLVM_CLANG_STATICANALYZER_CORE_ISSUE_HASH_H
+
+#include "llvm/ADT/SmallString.h"
+
+namespace clang {
+class Decl;
+class SourceManager;
+class FullSourceLoc;
+class LangOptions;
+
+/// \brief Get an MD5 hash to help identify bugs.
+///
+/// This function returns a hash that helps identify bugs within a source file.
+/// This identification can be utilized to diff diagnostic results on different
+/// snapshots of a projects, or maintain a database of suppressed diagnotics.
+///
+/// The hash contains the normalized text of the location associated with the
+/// diagnostic. Normalization means removing the whitespaces. The associated
+/// location is the either the last location of a diagnostic path or a uniqueing
+/// location. The bugtype and the name of the checker is also part of the hash.
+/// The last component is the string representation of the enclosing declaration
+/// of the associated location.
+///
+/// In case a new hash is introduced, the old one should still be maintained for
+/// a while. One should not introduce a new hash for every change, it is
+/// possible to introduce experimental hashes that may change in the future.
+/// Such hashes should be marked as experimental using a comment in the plist
+/// files.
+llvm::SmallString<32> GetIssueHash(const SourceManager &SM,
+ FullSourceLoc &IssueLoc,
+ llvm::StringRef CheckerName,
+ llvm::StringRef BugType, const Decl *D,
+ const LangOptions &LangOpts);
+
+/// \brief Get the string representation of issue hash. See GetIssueHash() for
+/// more information.
+std::string GetIssueString(const SourceManager &SM, FullSourceLoc &IssueLoc,
+ llvm::StringRef CheckerName, llvm::StringRef BugType,
+ const Decl *D, const LangOptions &LangOpts);
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index 63b8631..b09dffa 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -164,7 +164,8 @@ protected:
/// \brief Used to specify non-argument regions that will be invalidated as a
/// result of this call.
- virtual void getExtraInvalidatedValues(ValueList &Values) const {}
+ virtual void getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const {}
public:
virtual ~CallEvent() {}
@@ -253,9 +254,16 @@ public:
/// which the return value has already been bound to the origin expression.
SVal getReturnValue() const;
+ /// \brief Returns true if the type of any of the non-null arguments satisfies
+ /// the condition.
+ bool hasNonNullArgumentsWithType(bool (*Condition)(QualType)) const;
+
/// \brief Returns true if any of the arguments appear to represent callbacks.
bool hasNonZeroCallbackArg() const;
+ /// \brief Returns true if any of the arguments is void*.
+ bool hasVoidPointerToNonConstArg() const;
+
/// \brief Returns true if any of the arguments are known to escape to long-
/// term storage, even if this method will not modify them.
// NOTE: The exact semantics of this are still being defined!
@@ -472,7 +480,8 @@ protected:
BlockCall(const BlockCall &Other) : CallEvent(Other) {}
void cloneTo(void *Dest) const override { new (Dest) BlockCall(*this); }
- void getExtraInvalidatedValues(ValueList &Values) const override;
+ void getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const override;
public:
virtual const CallExpr *getOriginExpr() const {
@@ -497,8 +506,55 @@ public:
return BR->getDecl();
}
+ bool isConversionFromLambda() const {
+ const BlockDecl *BD = getDecl();
+ if (!BD)
+ return false;
+
+ return BD->isConversionFromLambda();
+ }
+
+ /// \brief For a block converted from a C++ lambda, returns the block
+ /// VarRegion for the variable holding the captured C++ lambda record.
+ const VarRegion *getRegionStoringCapturedLambda() const {
+ assert(isConversionFromLambda());
+ const BlockDataRegion *BR = getBlockRegion();
+ assert(BR && "Block converted from lambda must have a block region");
+
+ auto I = BR->referenced_vars_begin();
+ assert(I != BR->referenced_vars_end());
+
+ return I.getCapturedRegion();
+ }
+
RuntimeDefinition getRuntimeDefinition() const override {
- return RuntimeDefinition(getDecl());
+ if (!isConversionFromLambda())
+ return RuntimeDefinition(getDecl());
+
+ // Clang converts lambdas to blocks with an implicit user-defined
+ // conversion operator method on the lambda record that looks (roughly)
+ // like:
+ //
+ // typedef R(^block_type)(P1, P2, ...);
+ // operator block_type() const {
+ // auto Lambda = *this;
+ // return ^(P1 p1, P2 p2, ...){
+ // /* return Lambda(p1, p2, ...); */
+ // };
+ // }
+ //
+ // Here R is the return type of the lambda and P1, P2, ... are
+ // its parameter types. 'Lambda' is a fake VarDecl captured by the block
+ // that is initialized to a copy of the lambda.
+ //
+ // Sema leaves the body of a lambda-converted block empty (it is
+ // produced by CodeGen), so we can't analyze it directly. Instead, we skip
+ // the block body and analyze the operator() method on the captured lambda.
+ const VarDecl *LambdaVD = getRegionStoringCapturedLambda()->getDecl();
+ const CXXRecordDecl *LambdaDecl = LambdaVD->getType()->getAsCXXRecordDecl();
+ CXXMethodDecl* LambdaCallOperator = LambdaDecl->getLambdaCallOperator();
+
+ return RuntimeDefinition(LambdaCallOperator);
}
bool argumentsMayEscape() const override {
@@ -521,7 +577,8 @@ public:
/// it is written.
class CXXInstanceCall : public AnyFunctionCall {
protected:
- void getExtraInvalidatedValues(ValueList &Values) const override;
+ void getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const override;
CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx)
@@ -704,7 +761,8 @@ protected:
CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){}
void cloneTo(void *Dest) const override { new (Dest) CXXConstructorCall(*this); }
- void getExtraInvalidatedValues(ValueList &Values) const override;
+ void getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const override;
public:
virtual const CXXConstructExpr *getOriginExpr() const {
@@ -803,7 +861,8 @@ protected:
ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {}
void cloneTo(void *Dest) const override { new (Dest) ObjCMethodCall(*this); }
- void getExtraInvalidatedValues(ValueList &Values) const override;
+ void getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const override;
/// Check if the selector may have multiple definitions (may have overrides).
virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index a4ff133..d4f014d 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -224,13 +224,39 @@ public:
}
/// \brief Generate a sink node. Generating a sink stops exploration of the
- /// given path.
- ExplodedNode *generateSink(ProgramStateRef State = nullptr,
- ExplodedNode *Pred = nullptr,
+ /// given path. To create a sink node for the purpose of reporting an error,
+ /// checkers should use generateErrorNode() instead.
+ ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred,
const ProgramPointTag *Tag = nullptr) {
return addTransitionImpl(State ? State : getState(), true, Pred, Tag);
}
+ /// \brief Generate a transition to a node that will be used to report
+ /// an error. This node will be a sink. That is, it will stop exploration of
+ /// the given path.
+ ///
+ /// @param State The state of the generated node.
+ /// @param Tag The tag to uniquely identify the creation site. If null,
+ /// the default tag for the checker will be used.
+ ExplodedNode *generateErrorNode(ProgramStateRef State = nullptr,
+ const ProgramPointTag *Tag = nullptr) {
+ return generateSink(State, Pred,
+ (Tag ? Tag : Location.getTag()));
+ }
+
+ /// \brief Generate a transition to a node that will be used to report
+ /// an error. This node will not be a sink. That is, exploration will
+ /// continue along this path.
+ ///
+ /// @param State The state of the generated node.
+ /// @param Tag The tag to uniquely identify the creation site. If null,
+ /// the default tag for the checker will be used.
+ ExplodedNode *
+ generateNonFatalErrorNode(ProgramStateRef State = nullptr,
+ const ProgramPointTag *Tag = nullptr) {
+ return addTransition(State, (Tag ? Tag : Location.getTag()));
+ }
+
/// \brief Emit the diagnostics report.
void emitReport(std::unique_ptr<BugReport> R) {
Changed = true;
@@ -287,6 +313,18 @@ private:
bool MarkAsSink,
ExplodedNode *P = nullptr,
const ProgramPointTag *Tag = nullptr) {
+ // The analyzer may stop exploring if it sees a state it has previously
+ // visited ("cache out"). The early return here is a defensive check to
+ // prevent accidental caching out by checker API clients. Unless there is a
+ // tag or the client checker has requested that the generated node be
+ // marked as a sink, we assume that a client requesting a transition to a
+ // state that is the same as the predecessor state has made a mistake. We
+ // return the predecessor rather than cache out.
+ //
+ // TODO: We could potentially change the return to an assertion to alert
+ // clients to their mistake, but several checkers (including
+ // DereferenceChecker, CallAndMessageChecker, and DynamicTypePropagation)
+ // rely upon the defensive behavior and would need to be updated.
if (!State || (State == Pred->getState() && !Tag && !MarkAsSink))
return Pred;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
index e7ec1f4..8dda636 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
@@ -15,9 +15,13 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H
#include "clang/AST/Stmt.h"
+#include <tuple>
namespace clang {
+class Expr;
+class VarDecl;
+
namespace ento {
bool containsMacro(const Stmt *S);
@@ -35,6 +39,9 @@ template <class T> bool containsStmt(const Stmt *S) {
return false;
}
+std::pair<const clang::VarDecl *, const clang::Expr *>
+parseAssignment(const Stmt *S);
+
} // end GR namespace
} // end clang namespace
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
index f876096..9a858c2 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -99,6 +99,35 @@ public:
return ProgramStatePair(StTrue, StFalse);
}
+ virtual ProgramStateRef assumeWithinInclusiveRange(ProgramStateRef State,
+ NonLoc Value,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool InBound) = 0;
+
+ virtual ProgramStatePair assumeWithinInclusiveRangeDual(
+ ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
+ const llvm::APSInt &To) {
+ ProgramStateRef StInRange = assumeWithinInclusiveRange(State, Value, From,
+ To, true);
+
+ // If StTrue is infeasible, asserting the falseness of Cond is unnecessary
+ // because the existing constraints already establish this.
+ if (!StInRange)
+ return ProgramStatePair((ProgramStateRef)nullptr, State);
+
+ ProgramStateRef StOutOfRange = assumeWithinInclusiveRange(State, Value,
+ From, To, false);
+ if (!StOutOfRange) {
+ // We are careful to return the original state, /not/ StTrue,
+ // because we want to avoid having callers generate a new node
+ // in the ExplodedGraph.
+ return ProgramStatePair(State, (ProgramStateRef)nullptr);
+ }
+
+ return ProgramStatePair(StInRange, StOutOfRange);
+ }
+
/// \brief If a symbol is perfectly constrained to a constant, attempt
/// to return the concrete value.
///
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
new file mode 100644
index 0000000..555191d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
@@ -0,0 +1,57 @@
+//== DynamicTypeMap.h - Dynamic type map ----------------------- -*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides APIs for tracking dynamic type information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+namespace clang {
+namespace ento {
+
+/// The GDM component containing the dynamic type info. This is a map from a
+/// symbol to its most likely type.
+struct DynamicTypeMap {};
+typedef llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>
+ DynamicTypeMapImpl;
+template <>
+struct ProgramStateTrait<DynamicTypeMap>
+ : public ProgramStatePartialTrait<DynamicTypeMapImpl> {
+ static void *GDMIndex() {
+ static int index = 0;
+ return &index;
+ }
+};
+
+/// \brief Get dynamic type information for a region.
+DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
+ const MemRegion *Reg);
+
+/// \brief Set dynamic type information of the region; return the new state.
+ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
+ DynamicTypeInfo NewTy);
+
+/// \brief Set dynamic type information of the region; return the new state.
+inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State,
+ const MemRegion *Reg, QualType NewTy,
+ bool CanBeSubClassed = true) {
+ return setDynamicTypeInfo(State, Reg,
+ DynamicTypeInfo(NewTy, CanBeSubClassed));
+}
+
+} // ento
+} // clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index d8f1c34..99083c9 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -341,6 +341,10 @@ public:
void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
+ /// VisitLambdaExpr - Transfer function logic for LambdaExprs.
+ void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
/// VisitBinaryOperator - Transfer function logic for binary operators.
void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
@@ -600,6 +604,28 @@ private:
const LocationContext *LC,
const Expr *E,
const Expr *ResultE = nullptr);
+
+ /// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG
+ /// block to find the constructor expression that directly constructed into
+ /// the storage for this statement. Returns null if the constructor for this
+ /// statement created a temporary object region rather than directly
+ /// constructing into an existing region.
+ const CXXConstructExpr *findDirectConstructorForCurrentCFGElement();
+
+ /// For a CXXConstructExpr, walk forward in the current CFG block to find the
+ /// CFGElement for the DeclStmt or CXXInitCtorInitializer for which is
+ /// directly constructed by this constructor. Returns None if the current
+ /// constructor expression did not directly construct into an existing
+ /// region.
+ Optional<CFGElement> findElementDirectlyInitializedByCurrentConstructor();
+
+ /// For a given constructor, look forward in the current CFG block to
+ /// determine the region into which an object will be constructed by \p CE.
+ /// Returns either a field or local variable region if the object will be
+ /// directly constructed in an existing region or a temporary object region
+ /// if not.
+ const MemRegion *getRegionForConstructedObject(const CXXConstructExpr *CE,
+ ExplodedNode *Pred);
};
/// Traits for storing the call processing policy inside GDM.
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
index faa3500..ce81c98 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H
+#include "clang/AST/Decl.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
@@ -22,7 +23,6 @@
#include <deque>
namespace clang {
-class Decl;
namespace ento {
typedef std::deque<Decl*> SetOfDecls;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
new file mode 100644
index 0000000..3168733
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
@@ -0,0 +1,36 @@
+//===--- LoopWidening.h - Widen loops ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// This header contains the declarations of functions which are used to widen
+/// loops which do not otherwise exit. The widening is done by invalidating
+/// anything which might be modified by the body of the loop.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPWIDENING_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPWIDENING_H
+
+#include "clang/Analysis/CFG.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+
+namespace clang {
+namespace ento {
+
+/// \brief Get the states that result from widening the loop.
+///
+/// Widen the loop by invalidating anything that might be modified
+/// by the loop body in any iteration.
+ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
+ const LocationContext *LCtx,
+ unsigned BlockCount, const Stmt *LoopStmt);
+
+} // end namespace ento
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 4f07129..43f6e5c 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -19,6 +19,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
@@ -46,7 +47,7 @@ class RegionOffset {
/// The base region.
const MemRegion *R;
- /// The bit offset within the base region. It shouldn't be negative.
+ /// The bit offset within the base region. Can be negative.
int64_t Offset;
public:
@@ -79,7 +80,7 @@ class MemRegion : public llvm::FoldingSetNode {
public:
enum Kind {
// Memory spaces.
- GenericMemSpaceRegionKind,
+ CodeSpaceRegionKind,
StackLocalsSpaceRegionKind,
StackArgumentsSpaceRegionKind,
HeapSpaceRegionKind,
@@ -88,29 +89,29 @@ public:
GlobalInternalSpaceRegionKind,
GlobalSystemSpaceRegionKind,
GlobalImmutableSpaceRegionKind,
- BEG_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind,
+ BEGIN_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind,
END_NON_STATIC_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
- BEG_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind,
+ BEGIN_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind,
END_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
- BEG_MEMSPACES = GenericMemSpaceRegionKind,
+ BEGIN_MEMSPACES = CodeSpaceRegionKind,
END_MEMSPACES = GlobalImmutableSpaceRegionKind,
// Untyped regions.
SymbolicRegionKind,
AllocaRegionKind,
// Typed regions.
- BEG_TYPED_REGIONS,
- FunctionTextRegionKind = BEG_TYPED_REGIONS,
- BlockTextRegionKind,
+ BEGIN_TYPED_REGIONS,
+ FunctionCodeRegionKind = BEGIN_TYPED_REGIONS,
+ BlockCodeRegionKind,
BlockDataRegionKind,
- BEG_TYPED_VALUE_REGIONS,
- CompoundLiteralRegionKind = BEG_TYPED_VALUE_REGIONS,
+ BEGIN_TYPED_VALUE_REGIONS,
+ CompoundLiteralRegionKind = BEGIN_TYPED_VALUE_REGIONS,
CXXThisRegionKind,
StringRegionKind,
ObjCStringRegionKind,
ElementRegionKind,
// Decl Regions.
- BEG_DECL_REGIONS,
- VarRegionKind = BEG_DECL_REGIONS,
+ BEGIN_DECL_REGIONS,
+ VarRegionKind = BEGIN_DECL_REGIONS,
FieldRegionKind,
ObjCIvarRegionKind,
END_DECL_REGIONS = ObjCIvarRegionKind,
@@ -192,12 +193,9 @@ public:
/// for example, the set of global variables, the stack frame, etc.
class MemSpaceRegion : public MemRegion {
protected:
- friend class MemRegionManager;
-
MemRegionManager *Mgr;
- MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind)
- : MemRegion(k), Mgr(mgr) {
+ MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) {
assert(classof(this));
}
@@ -210,10 +208,26 @@ public:
static bool classof(const MemRegion *R) {
Kind k = R->getKind();
- return k >= BEG_MEMSPACES && k <= END_MEMSPACES;
+ return k >= BEGIN_MEMSPACES && k <= END_MEMSPACES;
}
};
-
+
+/// CodeSpaceRegion - The memory space that holds the executable code of
+/// functions and blocks.
+class CodeSpaceRegion : public MemSpaceRegion {
+ friend class MemRegionManager;
+
+ CodeSpaceRegion(MemRegionManager *mgr)
+ : MemSpaceRegion(mgr, CodeSpaceRegionKind) {}
+
+public:
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == CodeSpaceRegionKind;
+ }
+};
+
class GlobalsSpaceRegion : public MemSpaceRegion {
virtual void anchor();
protected:
@@ -222,7 +236,7 @@ protected:
public:
static bool classof(const MemRegion *R) {
Kind k = R->getKind();
- return k >= BEG_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES;
+ return k >= BEGIN_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES;
}
};
@@ -258,17 +272,15 @@ public:
/// RegionStoreManager::invalidateRegions (instead of finding all the dependent
/// globals, we invalidate the whole parent region).
class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
- friend class MemRegionManager;
-
protected:
NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
: GlobalsSpaceRegion(mgr, k) {}
-
+
public:
static bool classof(const MemRegion *R) {
Kind k = R->getKind();
- return k >= BEG_NON_STATIC_GLOBAL_MEMSPACES &&
+ return k >= BEGIN_NON_STATIC_GLOBAL_MEMSPACES &&
k <= END_NON_STATIC_GLOBAL_MEMSPACES;
}
};
@@ -356,7 +368,7 @@ public:
return R->getKind() == UnknownSpaceRegionKind;
}
};
-
+
class StackSpaceRegion : public MemSpaceRegion {
private:
const StackFrameContext *SFC;
@@ -367,18 +379,18 @@ protected:
assert(classof(this));
}
-public:
+public:
const StackFrameContext *getStackFrame() const { return SFC; }
-
+
void Profile(llvm::FoldingSetNodeID &ID) const override;
static bool classof(const MemRegion *R) {
Kind k = R->getKind();
return k >= StackLocalsSpaceRegionKind &&
k <= StackArgumentsSpaceRegionKind;
- }
+ }
};
-
+
class StackLocalsSpaceRegion : public StackSpaceRegion {
virtual void anchor();
friend class MemRegionManager;
@@ -490,7 +502,7 @@ public:
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
- return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS;
+ return k >= BEGIN_TYPED_REGIONS && k <= END_TYPED_REGIONS;
}
};
@@ -522,7 +534,7 @@ public:
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
- return k >= BEG_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
+ return k >= BEGIN_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
}
};
@@ -537,16 +549,16 @@ public:
static bool classof(const MemRegion* R) {
Kind k = R->getKind();
- return k >= FunctionTextRegionKind && k <= BlockTextRegionKind;
+ return k >= FunctionCodeRegionKind && k <= BlockCodeRegionKind;
}
};
-/// FunctionTextRegion - A region that represents code texts of function.
-class FunctionTextRegion : public CodeTextRegion {
+/// FunctionCodeRegion - A region that represents code texts of function.
+class FunctionCodeRegion : public CodeTextRegion {
const NamedDecl *FD;
public:
- FunctionTextRegion(const NamedDecl *fd, const MemRegion* sreg)
- : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {
+ FunctionCodeRegion(const NamedDecl *fd, const MemRegion* sreg)
+ : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) {
assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
}
@@ -576,27 +588,27 @@ public:
const MemRegion*);
static bool classof(const MemRegion* R) {
- return R->getKind() == FunctionTextRegionKind;
+ return R->getKind() == FunctionCodeRegionKind;
}
};
-/// BlockTextRegion - A region that represents code texts of blocks (closures).
-/// Blocks are represented with two kinds of regions. BlockTextRegions
+/// BlockCodeRegion - A region that represents code texts of blocks (closures).
+/// Blocks are represented with two kinds of regions. BlockCodeRegions
/// represent the "code", while BlockDataRegions represent instances of blocks,
/// which correspond to "code+data". The distinction is important, because
/// like a closure a block captures the values of externally referenced
/// variables.
-class BlockTextRegion : public CodeTextRegion {
+class BlockCodeRegion : public CodeTextRegion {
friend class MemRegionManager;
const BlockDecl *BD;
AnalysisDeclContext *AC;
CanQualType locTy;
- BlockTextRegion(const BlockDecl *bd, CanQualType lTy,
+ BlockCodeRegion(const BlockDecl *bd, CanQualType lTy,
AnalysisDeclContext *ac, const MemRegion* sreg)
- : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
+ : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {}
public:
QualType getLocationType() const override {
@@ -618,32 +630,32 @@ public:
const MemRegion*);
static bool classof(const MemRegion* R) {
- return R->getKind() == BlockTextRegionKind;
+ return R->getKind() == BlockCodeRegionKind;
}
};
/// BlockDataRegion - A region that represents a block instance.
-/// Blocks are represented with two kinds of regions. BlockTextRegions
+/// Blocks are represented with two kinds of regions. BlockCodeRegions
/// represent the "code", while BlockDataRegions represent instances of blocks,
/// which correspond to "code+data". The distinction is important, because
/// like a closure a block captures the values of externally referenced
/// variables.
class BlockDataRegion : public TypedRegion {
friend class MemRegionManager;
- const BlockTextRegion *BC;
+ const BlockCodeRegion *BC;
const LocationContext *LC; // Can be null */
unsigned BlockCount;
void *ReferencedVars;
void *OriginalVars;
- BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
+ BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc,
unsigned count, const MemRegion *sreg)
: TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
BlockCount(count),
ReferencedVars(nullptr), OriginalVars(nullptr) {}
public:
- const BlockTextRegion *getCodeRegion() const { return BC; }
+ const BlockCodeRegion *getCodeRegion() const { return BC; }
const BlockDecl *getDecl() const { return BC->getDecl(); }
@@ -690,7 +702,7 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const override;
- static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *,
+ static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *,
const LocationContext *, unsigned,
const MemRegion *);
@@ -855,7 +867,7 @@ public:
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
- return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS;
+ return k >= BEGIN_DECL_REGIONS && k <= END_DECL_REGIONS;
}
};
@@ -1137,7 +1149,7 @@ class MemRegionManager {
HeapSpaceRegion *heap;
UnknownSpaceRegion *unknown;
- MemSpaceRegion *code;
+ CodeSpaceRegion *code;
public:
MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a)
@@ -1173,9 +1185,9 @@ public:
/// getUnknownRegion - Retrieve the memory region associated with unknown
/// memory space.
- const MemSpaceRegion *getUnknownRegion();
+ const UnknownSpaceRegion *getUnknownRegion();
- const MemSpaceRegion *getCodeRegion();
+ const CodeSpaceRegion *getCodeRegion();
/// getAllocaRegion - Retrieve a region associated with a call to alloca().
const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt,
@@ -1261,8 +1273,8 @@ public:
baseReg->isVirtual());
}
- const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD);
- const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
+ const FunctionCodeRegion *getFunctionCodeRegion(const NamedDecl *FD);
+ const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD,
CanQualType locTy,
AnalysisDeclContext *AC);
@@ -1270,7 +1282,7 @@ public:
/// of a block. Unlike many other MemRegions, the LocationContext*
/// argument is allowed to be NULL for cases where we have no known
/// context.
- const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
+ const BlockDataRegion *getBlockDataRegion(const BlockCodeRegion *bc,
const LocationContext *lc,
unsigned blockCount);
@@ -1333,7 +1345,12 @@ public:
/// Tells that a region's contents is not changed.
TK_PreserveContents = 0x1,
/// Suppress pointer-escaping of a region.
- TK_SuppressEscape = 0x2
+ TK_SuppressEscape = 0x2,
+ // Do not invalidate super region.
+ TK_DoNotInvalidateSuperRegion = 0x4,
+ /// When applied to a MemSpaceRegion, indicates the entire memory space
+ /// should be invalidated.
+ TK_EntireMemSpace = 0x8
// Do not forget to extend StorageTypeForKinds if number of traits exceed
// the number of bits StorageTypeForKinds can store.
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index ac4e452..c4a62ec 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -190,6 +190,27 @@ public:
DefinedOrUnknownSVal upperBound,
bool assumption,
QualType IndexType = QualType()) const;
+
+ /// Assumes that the value of \p Val is bounded with [\p From; \p To]
+ /// (if \p assumption is "true") or it is fully out of this range
+ /// (if \p assumption is "false").
+ ///
+ /// This returns a new state with the added constraint on \p cond.
+ /// If no new state is feasible, NULL is returned.
+ ProgramStateRef assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool assumption) const;
+
+ /// Assumes given range both "true" and "false" for \p Val, and returns both
+ /// corresponding states (respectively).
+ ///
+ /// This is more efficient than calling assume() twice. Note that one (but not
+ /// both) of the returned states may be NULL.
+ std::pair<ProgramStateRef, ProgramStateRef>
+ assumeWithinInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From,
+ const llvm::APSInt &To) const;
+
/// \brief Check if the given SVal is constrained to zero or is a zero
/// constant.
@@ -337,20 +358,6 @@ public:
bool isTainted(SymbolRef Sym, TaintTagType Kind = TaintTagGeneric) const;
bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const;
- /// \brief Get dynamic type information for a region.
- DynamicTypeInfo getDynamicTypeInfo(const MemRegion *Reg) const;
-
- /// \brief Set dynamic type information of the region; return the new state.
- ProgramStateRef setDynamicTypeInfo(const MemRegion *Reg,
- DynamicTypeInfo NewTy) const;
-
- /// \brief Set dynamic type information of the region; return the new state.
- ProgramStateRef setDynamicTypeInfo(const MemRegion *Reg,
- QualType NewTy,
- bool CanBeSubClassed = true) const {
- return setDynamicTypeInfo(Reg, DynamicTypeInfo(NewTy, CanBeSubClassed));
- }
-
//==---------------------------------------------------------------------==//
// Accessing the Generic Data Map (GDM).
//==---------------------------------------------------------------------==//
@@ -650,6 +657,33 @@ ProgramState::assume(DefinedOrUnknownSVal Cond) const {
->assumeDual(this, Cond.castAs<DefinedSVal>());
}
+inline ProgramStateRef
+ProgramState::assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool Assumption) const {
+ if (Val.isUnknown())
+ return this;
+
+ assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!");
+
+ return getStateManager().ConstraintMgr->assumeWithinInclusiveRange(
+ this, Val.castAs<NonLoc>(), From, To, Assumption);
+}
+
+inline std::pair<ProgramStateRef, ProgramStateRef>
+ProgramState::assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To) const {
+ if (Val.isUnknown())
+ return std::make_pair(this, this);
+
+ assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!");
+
+ return getStateManager().ConstraintMgr
+ ->assumeWithinInclusiveRangeDual(this, Val.castAs<NonLoc>(), From, To);
+}
+
inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const {
if (Optional<Loc> L = LV.getAs<Loc>())
return bindLoc(*L, V);
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index a68d341..3c47114 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -83,7 +83,11 @@ public:
}
SVal evalCast(SVal val, QualType castTy, QualType originalType);
-
+
+ // Handles casts of type CK_IntegralCast.
+ SVal evalIntegralCast(ProgramStateRef state, SVal val, QualType castTy,
+ QualType originalType);
+
virtual SVal evalMinus(NonLoc val) = 0;
virtual SVal evalComplement(NonLoc val) = 0;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 642e11a..d644254 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -45,8 +45,8 @@ class SVal {
public:
enum BaseKind {
// The enumerators must be representable using 2 bits.
- UndefinedKind = 0, // for subclass UndefinedVal (an uninitialized value)
- UnknownKind = 1, // for subclass UnknownVal (a void value)
+ UndefinedValKind = 0, // for subclass UndefinedVal (an uninitialized value)
+ UnknownValKind = 1, // for subclass UnknownVal (a void value)
LocKind = 2, // for subclass Loc (an L-value)
NonLocKind = 3 // for subclass NonLoc (an R-value that's not
// an L-value)
@@ -115,19 +115,19 @@ public:
}
inline bool isUnknown() const {
- return getRawKind() == UnknownKind;
+ return getRawKind() == UnknownValKind;
}
inline bool isUndef() const {
- return getRawKind() == UndefinedKind;
+ return getRawKind() == UndefinedValKind;
}
inline bool isUnknownOrUndef() const {
- return getRawKind() <= UnknownKind;
+ return getRawKind() <= UnknownValKind;
}
inline bool isValid() const {
- return getRawKind() > UnknownKind;
+ return getRawKind() > UnknownValKind;
}
bool isConstant() const;
@@ -190,12 +190,12 @@ public:
class UndefinedVal : public SVal {
public:
- UndefinedVal() : SVal(UndefinedKind) {}
+ UndefinedVal() : SVal(UndefinedValKind) {}
private:
friend class SVal;
static bool isKind(const SVal& V) {
- return V.getBaseKind() == UndefinedKind;
+ return V.getBaseKind() == UndefinedValKind;
}
};
@@ -223,12 +223,12 @@ private:
class UnknownVal : public DefinedOrUnknownSVal {
public:
- explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
+ explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {}
private:
friend class SVal;
static bool isKind(const SVal &V) {
- return V.getBaseKind() == UnknownKind;
+ return V.getBaseKind() == UnknownValKind;
}
};
@@ -465,7 +465,7 @@ private:
namespace loc {
-enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind };
+enum Kind { GotoLabelKind, MemRegionValKind, ConcreteIntKind };
class GotoLabel : public Loc {
public:
@@ -490,7 +490,7 @@ private:
class MemRegionVal : public Loc {
public:
- explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
+ explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) {}
/// \brief Get the underlining region.
const MemRegion* getRegion() const {
@@ -518,11 +518,11 @@ private:
MemRegionVal() {}
static bool isKind(const SVal& V) {
return V.getBaseKind() == LocKind &&
- V.getSubKind() == MemRegionKind;
+ V.getSubKind() == MemRegionValKind;
}
static bool isKind(const Loc& V) {
- return V.getSubKind() == MemRegionKind;
+ return V.getSubKind() == MemRegionValKind;
}
};
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 1ca96a2..77d12e5 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -42,14 +42,22 @@ namespace ento {
class SymExpr : public llvm::FoldingSetNode {
virtual void anchor();
public:
- enum Kind { RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
- MetadataKind,
- BEGIN_SYMBOLS = RegionValueKind,
- END_SYMBOLS = MetadataKind,
- SymIntKind, IntSymKind, SymSymKind,
- BEGIN_BINARYSYMEXPRS = SymIntKind,
- END_BINARYSYMEXPRS = SymSymKind,
- CastSymbolKind };
+ enum Kind {
+ SymbolRegionValueKind,
+ SymbolConjuredKind,
+ SymbolDerivedKind,
+ SymbolExtentKind,
+ SymbolMetadataKind,
+ BEGIN_SYMBOLS = SymbolRegionValueKind,
+ END_SYMBOLS = SymbolMetadataKind,
+ SymIntExprKind,
+ IntSymExprKind,
+ SymSymExprKind,
+ BEGIN_BINARYSYMEXPRS = SymIntExprKind,
+ END_BINARYSYMEXPRS = SymSymExprKind,
+ SymbolCastKind
+ };
+
private:
Kind K;
@@ -126,12 +134,12 @@ class SymbolRegionValue : public SymbolData {
public:
SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
- : SymbolData(RegionValueKind, sym), R(r) {}
+ : SymbolData(SymbolRegionValueKind, sym), R(r) {}
const TypedValueRegion* getRegion() const { return R; }
static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
- profile.AddInteger((unsigned) RegionValueKind);
+ profile.AddInteger((unsigned) SymbolRegionValueKind);
profile.AddPointer(R);
}
@@ -145,7 +153,7 @@ public:
// Implement isa<T> support.
static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == RegionValueKind;
+ return SE->getKind() == SymbolRegionValueKind;
}
};
@@ -160,11 +168,9 @@ class SymbolConjured : public SymbolData {
public:
SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
- QualType t, unsigned count,
- const void *symbolTag)
- : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count),
- LCtx(lctx),
- SymbolTag(symbolTag) {}
+ QualType t, unsigned count, const void *symbolTag)
+ : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
+ LCtx(lctx), SymbolTag(symbolTag) {}
const Stmt *getStmt() const { return S; }
unsigned getCount() const { return Count; }
@@ -177,7 +183,7 @@ public:
static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S,
QualType T, unsigned Count, const LocationContext *LCtx,
const void *SymbolTag) {
- profile.AddInteger((unsigned) ConjuredKind);
+ profile.AddInteger((unsigned) SymbolConjuredKind);
profile.AddPointer(S);
profile.AddPointer(LCtx);
profile.Add(T);
@@ -191,7 +197,7 @@ public:
// Implement isa<T> support.
static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == ConjuredKind;
+ return SE->getKind() == SymbolConjuredKind;
}
};
@@ -203,7 +209,7 @@ class SymbolDerived : public SymbolData {
public:
SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
- : SymbolData(DerivedKind, sym), parentSymbol(parent), R(r) {}
+ : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {}
SymbolRef getParentSymbol() const { return parentSymbol; }
const TypedValueRegion *getRegion() const { return R; }
@@ -214,7 +220,7 @@ public:
static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
const TypedValueRegion *r) {
- profile.AddInteger((unsigned) DerivedKind);
+ profile.AddInteger((unsigned) SymbolDerivedKind);
profile.AddPointer(r);
profile.AddPointer(parent);
}
@@ -225,7 +231,7 @@ public:
// Implement isa<T> support.
static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == DerivedKind;
+ return SE->getKind() == SymbolDerivedKind;
}
};
@@ -237,7 +243,7 @@ class SymbolExtent : public SymbolData {
public:
SymbolExtent(SymbolID sym, const SubRegion *r)
- : SymbolData(ExtentKind, sym), R(r) {}
+ : SymbolData(SymbolExtentKind, sym), R(r) {}
const SubRegion *getRegion() const { return R; }
@@ -246,7 +252,7 @@ public:
void dumpToStream(raw_ostream &os) const override;
static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
- profile.AddInteger((unsigned) ExtentKind);
+ profile.AddInteger((unsigned) SymbolExtentKind);
profile.AddPointer(R);
}
@@ -256,7 +262,7 @@ public:
// Implement isa<T> support.
static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == ExtentKind;
+ return SE->getKind() == SymbolExtentKind;
}
};
@@ -273,7 +279,7 @@ class SymbolMetadata : public SymbolData {
public:
SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
unsigned count, const void *tag)
- : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
+ : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
const MemRegion *getRegion() const { return R; }
const Stmt *getStmt() const { return S; }
@@ -287,7 +293,7 @@ public:
static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
const Stmt *S, QualType T, unsigned Count,
const void *Tag) {
- profile.AddInteger((unsigned) MetadataKind);
+ profile.AddInteger((unsigned) SymbolMetadataKind);
profile.AddPointer(R);
profile.AddPointer(S);
profile.Add(T);
@@ -301,7 +307,7 @@ public:
// Implement isa<T> support.
static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == MetadataKind;
+ return SE->getKind() == SymbolMetadataKind;
}
};
@@ -315,7 +321,7 @@ class SymbolCast : public SymExpr {
public:
SymbolCast(const SymExpr *In, QualType From, QualType To) :
- SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { }
+ SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) { }
QualType getType() const override { return ToTy; }
@@ -325,7 +331,7 @@ public:
static void Profile(llvm::FoldingSetNodeID& ID,
const SymExpr *In, QualType From, QualType To) {
- ID.AddInteger((unsigned) CastSymbolKind);
+ ID.AddInteger((unsigned) SymbolCastKind);
ID.AddPointer(In);
ID.Add(From);
ID.Add(To);
@@ -337,7 +343,7 @@ public:
// Implement isa<T> support.
static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == CastSymbolKind;
+ return SE->getKind() == SymbolCastKind;
}
};
@@ -372,7 +378,7 @@ class SymIntExpr : public BinarySymExpr {
public:
SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
const llvm::APSInt& rhs, QualType t)
- : BinarySymExpr(SymIntKind, op, t), LHS(lhs), RHS(rhs) {}
+ : BinarySymExpr(SymIntExprKind, op, t), LHS(lhs), RHS(rhs) {}
void dumpToStream(raw_ostream &os) const override;
@@ -382,7 +388,7 @@ public:
static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
BinaryOperator::Opcode op, const llvm::APSInt& rhs,
QualType t) {
- ID.AddInteger((unsigned) SymIntKind);
+ ID.AddInteger((unsigned) SymIntExprKind);
ID.AddPointer(lhs);
ID.AddInteger(op);
ID.AddPointer(&rhs);
@@ -395,7 +401,7 @@ public:
// Implement isa<T> support.
static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == SymIntKind;
+ return SE->getKind() == SymIntExprKind;
}
};
@@ -407,7 +413,7 @@ class IntSymExpr : public BinarySymExpr {
public:
IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType t)
- : BinarySymExpr(IntSymKind, op, t), LHS(lhs), RHS(rhs) {}
+ : BinarySymExpr(IntSymExprKind, op, t), LHS(lhs), RHS(rhs) {}
void dumpToStream(raw_ostream &os) const override;
@@ -417,7 +423,7 @@ public:
static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs,
BinaryOperator::Opcode op, const SymExpr *rhs,
QualType t) {
- ID.AddInteger((unsigned) IntSymKind);
+ ID.AddInteger((unsigned) IntSymExprKind);
ID.AddPointer(&lhs);
ID.AddInteger(op);
ID.AddPointer(rhs);
@@ -430,7 +436,7 @@ public:
// Implement isa<T> support.
static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == IntSymKind;
+ return SE->getKind() == IntSymExprKind;
}
};
@@ -442,7 +448,7 @@ class SymSymExpr : public BinarySymExpr {
public:
SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
QualType t)
- : BinarySymExpr(SymSymKind, op, t), LHS(lhs), RHS(rhs) {}
+ : BinarySymExpr(SymSymExprKind, op, t), LHS(lhs), RHS(rhs) {}
const SymExpr *getLHS() const { return LHS; }
const SymExpr *getRHS() const { return RHS; }
@@ -451,7 +457,7 @@ public:
static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
- ID.AddInteger((unsigned) SymSymKind);
+ ID.AddInteger((unsigned) SymSymExprKind);
ID.AddPointer(lhs);
ID.AddInteger(op);
ID.AddPointer(rhs);
@@ -464,7 +470,7 @@ public:
// Implement isa<T> support.
static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == SymSymKind;
+ return SE->getKind() == SymSymExprKind;
}
};
@@ -639,6 +645,7 @@ public:
}
void markLive(const MemRegion *region);
+ void markElementIndicesLive(const MemRegion *region);
/// \brief Set to the value of the symbolic store after
/// StoreManager::removeDeadBindings has been called.
@@ -650,14 +657,20 @@ private:
};
class SymbolVisitor {
+protected:
+ ~SymbolVisitor() = default;
+
public:
+ SymbolVisitor() = default;
+ SymbolVisitor(const SymbolVisitor &) = default;
+ SymbolVisitor(SymbolVisitor &&) {}
+
/// \brief A visitor method invoked by ProgramStateManager::scanReachableSymbols.
///
/// The method returns \c true if symbols should continue be scanned and \c
/// false otherwise.
virtual bool VisitSymbol(SymbolRef sym) = 0;
virtual bool VisitMemRegion(const MemRegion *region) { return true; }
- virtual ~SymbolVisitor();
};
} // end GR namespace
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h b/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h
index a92e021..1fd7be6 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h
@@ -17,6 +17,8 @@
#ifndef LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
#define LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
#include <functional>
#include <string>
#include <vector>
@@ -31,8 +33,8 @@ typedef std::vector<std::string> CommandLineArguments;
///
/// Command line argument adjuster is responsible for command line arguments
/// modification before the arguments are used to run a frontend action.
-typedef std::function<CommandLineArguments(const CommandLineArguments &)>
- ArgumentsAdjuster;
+typedef std::function<CommandLineArguments(
+ const CommandLineArguments &, StringRef Filename)> ArgumentsAdjuster;
/// \brief Gets an argument adjuster that converts input command line arguments
/// to the "syntax check only" variant.
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h b/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h
index c23dc92..1e8462c 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h
@@ -42,6 +42,7 @@ namespace tooling {
/// \code
/// #include "clang/Frontend/FrontendActions.h"
/// #include "clang/Tooling/CommonOptionsParser.h"
+/// #include "clang/Tooling/Tooling.h"
/// #include "llvm/Support/CommandLine.h"
///
/// using namespace clang::tooling;
@@ -56,8 +57,8 @@ namespace tooling {
/// int main(int argc, const char **argv) {
/// CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
/// ClangTool Tool(OptionsParser.getCompilations(),
-/// OptionsParser.getSourcePathListi());
-/// return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>());
+/// OptionsParser.getSourcePathList());
+/// return Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
/// }
/// \endcode
class CommonOptionsParser {
@@ -72,6 +73,23 @@ public:
/// This constructor exits program in case of error.
CommonOptionsParser(int &argc, const char **argv,
llvm::cl::OptionCategory &Category,
+ const char *Overview = nullptr)
+ : CommonOptionsParser(argc, argv, Category, llvm::cl::OneOrMore,
+ Overview) {}
+
+ /// \brief Parses command-line, initializes a compilation database.
+ ///
+ /// This constructor can change argc and argv contents, e.g. consume
+ /// command-line options used for creating FixedCompilationDatabase.
+ ///
+ /// All options not belonging to \p Category become hidden.
+ ///
+ /// I also allows calls to set the required number of positional parameters.
+ ///
+ /// This constructor exits program in case of error.
+ CommonOptionsParser(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ llvm::cl::NumOccurrencesFlag OccurrencesFlag,
const char *Overview = nullptr);
/// Returns a reference to the loaded compilations database.
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h
index e5b95af..08a0ffe 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h
@@ -42,12 +42,18 @@ namespace tooling {
/// \brief Specifies the working directory and command of a compilation.
struct CompileCommand {
CompileCommand() {}
- CompileCommand(Twine Directory, std::vector<std::string> CommandLine)
- : Directory(Directory.str()), CommandLine(std::move(CommandLine)) {}
+ CompileCommand(Twine Directory, Twine Filename,
+ std::vector<std::string> CommandLine)
+ : Directory(Directory.str()),
+ Filename(Filename.str()),
+ CommandLine(std::move(CommandLine)) {}
/// \brief The working directory the command was executed from.
std::string Directory;
+ /// The source file associated with the command.
+ std::string Filename;
+
/// \brief The command line that was executed.
std::vector<std::string> CommandLine;
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Core/Lookup.h b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Lookup.h
new file mode 100644
index 0000000..bc2b4db
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Lookup.h
@@ -0,0 +1,48 @@
+//===--- Lookup.h - Framework for clang refactoring tools --*- C++ -*------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines helper methods for clang tools performing name lookup.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_CORE_LOOKUP_H
+#define LLVM_CLANG_TOOLING_CORE_LOOKUP_H
+
+#include "clang/Basic/LLVM.h"
+#include <string>
+
+namespace clang {
+
+class DeclContext;
+class NamedDecl;
+class NestedNameSpecifier;
+
+namespace tooling {
+
+/// Emulate a lookup to replace one nested name specifier with another using as
+/// few additional namespace qualifications as possible.
+///
+/// This does not perform a full C++ lookup so ADL will not work.
+///
+/// \param Use The nested name to be replaced.
+/// \param UseContext The context in which the nested name is contained. This
+/// will be used to minimize namespace qualifications.
+/// \param FromDecl The declaration to which the nested name points.
+/// \param ReplacementString The replacement nested name. Must be fully
+/// qualified including a leading "::".
+/// \returns The new name to be inserted in place of the current nested name.
+std::string replaceNestedName(const NestedNameSpecifier *Use,
+ const DeclContext *UseContext,
+ const NamedDecl *FromDecl,
+ StringRef ReplacementString);
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_CORE_LOOKUP_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h
index f189e12..37389ac 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h
@@ -220,6 +220,12 @@ bool applyAllReplacements(const std::vector<Replacement> &Replaces,
/// replacements cannot be applied, this returns an empty \c string.
std::string applyAllReplacements(StringRef Code, const Replacements &Replaces);
+/// \brief Merges two sets of replacements with the second set referring to the
+/// code after applying the first set. Within both 'First' and 'Second',
+/// replacements must not overlap.
+Replacements mergeReplacements(const Replacements &First,
+ const Replacements &Second);
+
template <typename Node>
Replacement::Replacement(const SourceManager &Sources,
const Node &NodeToReplace, StringRef ReplacementText,
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h b/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h
index b4edc31..2a13fc1 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h
@@ -33,18 +33,26 @@ namespace tooling {
/// \brief A JSON based compilation database.
///
/// JSON compilation database files must contain a list of JSON objects which
-/// provide the command lines in the attributes 'directory', 'command' and
-/// 'file':
+/// provide the command lines in the attributes 'directory', 'command',
+/// 'arguments' and 'file':
/// [
/// { "directory": "<working directory of the compile>",
/// "command": "<compile command line>",
/// "file": "<path to source file>"
/// },
+/// { "directory": "<working directory of the compile>",
+/// "arguments": ["<raw>", "<command>" "<line>" "<parameters>"],
+/// "file": "<path to source file>"
+/// },
/// ...
/// ]
/// Each object entry defines one compile action. The specified file is
/// considered to be the main source file for the translation unit.
///
+/// 'command' is a full command line that will be unescaped.
+///
+/// 'arguments' is a list of command line arguments that will not be unescaped.
+///
/// JSON compilation databases can for example be generated in CMake projects
/// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS.
class JSONCompilationDatabase : public CompilationDatabase {
@@ -91,17 +99,26 @@ private:
/// failed.
bool parse(std::string &ErrorMessage);
- // Tuple (directory, commandline) where 'commandline' pointing to the
- // corresponding nodes in the YAML stream.
- typedef std::pair<llvm::yaml::ScalarNode*,
- llvm::yaml::ScalarNode*> CompileCommandRef;
+ // Tuple (directory, filename, commandline) where 'commandline' points to the
+ // corresponding scalar nodes in the YAML stream.
+ // If the command line contains a single argument, it is a shell-escaped
+ // command line.
+ // Otherwise, each entry in the command line vector is a literal
+ // argument to the compiler.
+ typedef std::tuple<llvm::yaml::ScalarNode *,
+ llvm::yaml::ScalarNode *,
+ std::vector<llvm::yaml::ScalarNode *>> CompileCommandRef;
/// \brief Converts the given array of CompileCommandRefs to CompileCommands.
void getCommands(ArrayRef<CompileCommandRef> CommandsRef,
std::vector<CompileCommand> &Commands) const;
// Maps file paths to the compile command lines for that file.
- llvm::StringMap< std::vector<CompileCommandRef> > IndexByFile;
+ llvm::StringMap<std::vector<CompileCommandRef>> IndexByFile;
+
+ /// All the compile commands in the order that they were provided in the
+ /// JSON stream.
+ std::vector<CompileCommandRef> AllCommands;
FileMatchTrie MatchTrie;
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h
index 92e9065..b7a9b25 100644
--- a/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h
@@ -243,6 +243,7 @@ public:
///
/// \param FilePath The path at which the content will be mapped.
/// \param Content A null terminated buffer of the file's content.
+ // FIXME: remove this when all users have migrated!
void mapVirtualFile(StringRef FilePath, StringRef Content);
/// \brief Run the clang invocation.
@@ -331,9 +332,12 @@ class ClangTool {
std::vector<std::string> SourcePaths;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem;
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
llvm::IntrusiveRefCntPtr<FileManager> Files;
// Contains a list of pairs (<file name>, <file content>).
std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
+ llvm::StringSet<> SeenWorkingDirectories;
ArgumentsAdjuster ArgsAdjuster;
@@ -417,6 +421,29 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
/// \param File Either an absolute or relative path.
std::string getAbsolutePath(StringRef File);
+/// \brief Changes CommandLine to contain implicit flags that would have been
+/// defined had the compiler driver been invoked through the path InvokedAs.
+///
+/// For example, when called with \c InvokedAs set to `i686-linux-android-g++`,
+/// the arguments '-target', 'i686-linux-android`, `--driver-mode=g++` will
+/// be inserted after the first argument in \c CommandLine.
+///
+/// This function will not add new `-target` or `--driver-mode` flags if they
+/// are already present in `CommandLine` (even if they have different settings
+/// than would have been inserted).
+///
+/// \pre `llvm::InitializeAllTargets()` has been called.
+///
+/// \param CommandLine the command line used to invoke the compiler driver or
+/// Clang tool, including the path to the executable as \c CommandLine[0].
+/// \param InvokedAs the path to the driver used to infer implicit flags.
+///
+/// \note This will not set \c CommandLine[0] to \c InvokedAs. The tooling
+/// infrastructure expects that CommandLine[0] is a tool path relative to which
+/// the builtin headers can be found.
+void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
+ StringRef InvokedAs);
+
/// \brief Creates a \c CompilerInvocation.
clang::CompilerInvocation *newInvocation(
clang::DiagnosticsEngine *Diagnostics,
diff --git a/contrib/llvm/tools/clang/include/clang/module.modulemap b/contrib/llvm/tools/clang/include/clang/module.modulemap
index 6b77adb..28b6d16 100644
--- a/contrib/llvm/tools/clang/include/clang/module.modulemap
+++ b/contrib/llvm/tools/clang/include/clang/module.modulemap
@@ -25,6 +25,7 @@ module Clang_Basic {
umbrella "Basic"
textual header "Basic/BuiltinsAArch64.def"
+ textual header "Basic/BuiltinsAMDGPU.def"
textual header "Basic/BuiltinsARM.def"
textual header "Basic/Builtins.def"
textual header "Basic/BuiltinsHexagon.def"
@@ -33,8 +34,8 @@ module Clang_Basic {
textual header "Basic/BuiltinsNEON.def"
textual header "Basic/BuiltinsNVPTX.def"
textual header "Basic/BuiltinsPPC.def"
- textual header "Basic/BuiltinsR600.def"
textual header "Basic/BuiltinsSystemZ.def"
+ textual header "Basic/BuiltinsWebAssembly.def"
textual header "Basic/BuiltinsX86.def"
textual header "Basic/BuiltinsXCore.def"
textual header "Basic/DiagnosticOptions.def"
@@ -89,6 +90,9 @@ module Clang_Frontend {
textual header "Frontend/LangStandards.def"
module * { export * }
+
+ // FIXME: This violates layers.
+ exclude header "Frontend/PCHContainerOperations.h"
}
module Clang_FrontendTool { requires cplusplus umbrella "FrontendTool" module * { export * } }
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
index e328842..8c04c83 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
@@ -153,6 +153,9 @@ static bool HasARCRuntime(CompilerInvocation &origCI) {
if (triple.isiOS())
return triple.getOSMajorVersion() >= 5;
+ if (triple.isWatchOS())
+ return true;
+
if (triple.getOS() == llvm::Triple::Darwin)
return triple.getOSMajorVersion() >= 11;
@@ -206,7 +209,8 @@ createInvocationForMigration(CompilerInvocation &origCI,
WarnOpts.push_back("error=arc-unsafe-retained-assign");
CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
- CInvok->getLangOpts()->ObjCARCWeak = HasARCRuntime(origCI);
+ CInvok->getLangOpts()->ObjCWeakRuntime = HasARCRuntime(origCI);
+ CInvok->getLangOpts()->ObjCWeak = CInvok->getLangOpts()->ObjCWeakRuntime;
return CInvok.release();
}
@@ -600,7 +604,6 @@ bool MigrationProcess::applyTransform(TransformFn trans,
SmallString<512> newText;
llvm::raw_svector_ostream vecOS(newText);
buf.write(vecOS);
- vecOS.flush();
std::unique_ptr<llvm::MemoryBuffer> memBuf(
llvm::MemoryBuffer::getMemBufferCopy(
StringRef(newText.data(), newText.size()), newFname));
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp
index 72a55da..2cf2069 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp
@@ -144,7 +144,7 @@ bool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) {
SmallString<64> tempPath;
int fd;
if (fs::createTemporaryFile(path::filename(origFE->getName()),
- path::extension(origFE->getName()), fd,
+ path::extension(origFE->getName()).drop_front(), fd,
tempPath))
return report("Could not create file: " + tempPath.str(), Diag);
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp
index b61a421..50b1136 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp
@@ -214,25 +214,15 @@ namespace {
// FIXME. This duplicates one in RewriteObjCFoundationAPI.cpp
bool subscriptOperatorNeedsParens(const Expr *FullExpr) {
const Expr* Expr = FullExpr->IgnoreImpCasts();
- if (isa<ArraySubscriptExpr>(Expr) ||
- isa<CallExpr>(Expr) ||
- isa<DeclRefExpr>(Expr) ||
- isa<CXXNamedCastExpr>(Expr) ||
- isa<CXXConstructExpr>(Expr) ||
- isa<CXXThisExpr>(Expr) ||
- isa<CXXTypeidExpr>(Expr) ||
- isa<CXXUnresolvedConstructExpr>(Expr) ||
- isa<ObjCMessageExpr>(Expr) ||
- isa<ObjCPropertyRefExpr>(Expr) ||
- isa<ObjCProtocolExpr>(Expr) ||
- isa<MemberExpr>(Expr) ||
- isa<ObjCIvarRefExpr>(Expr) ||
- isa<ParenExpr>(FullExpr) ||
- isa<ParenListExpr>(Expr) ||
- isa<SizeOfPackExpr>(Expr))
- return false;
-
- return true;
+ return !(isa<ArraySubscriptExpr>(Expr) || isa<CallExpr>(Expr) ||
+ isa<DeclRefExpr>(Expr) || isa<CXXNamedCastExpr>(Expr) ||
+ isa<CXXConstructExpr>(Expr) || isa<CXXThisExpr>(Expr) ||
+ isa<CXXTypeidExpr>(Expr) ||
+ isa<CXXUnresolvedConstructExpr>(Expr) ||
+ isa<ObjCMessageExpr>(Expr) || isa<ObjCPropertyRefExpr>(Expr) ||
+ isa<ObjCProtocolExpr>(Expr) || isa<MemberExpr>(Expr) ||
+ isa<ObjCIvarRefExpr>(Expr) || isa<ParenExpr>(FullExpr) ||
+ isa<ParenListExpr>(Expr) || isa<SizeOfPackExpr>(Expr));
}
/// \brief - Rewrite message expression for Objective-C setter and getters into
@@ -665,9 +655,7 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
return false;
}
}
- if (HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod)
- return true;
- return false;
+ return HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod;
}
static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
@@ -736,7 +724,7 @@ static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
SourceLocation EndOfEnumDclLoc = EnumDcl->getLocEnd();
EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc,
NS.getASTContext(), /*IsDecl*/true);
- if (!EndOfEnumDclLoc.isInvalid()) {
+ if (EndOfEnumDclLoc.isValid()) {
SourceRange EnumDclRange(EnumDcl->getLocStart(), EndOfEnumDclLoc);
commit.insertFromRange(TypedefDcl->getLocStart(), EnumDclRange);
}
@@ -746,7 +734,7 @@ static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
SourceLocation EndTypedefDclLoc = TypedefDcl->getLocEnd();
EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc,
NS.getASTContext(), /*IsDecl*/true);
- if (!EndTypedefDclLoc.isInvalid()) {
+ if (EndTypedefDclLoc.isValid()) {
SourceRange TDRange(TypedefDcl->getLocStart(), EndTypedefDclLoc);
commit.remove(TDRange);
}
@@ -755,7 +743,7 @@ static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
EndOfEnumDclLoc = trans::findLocationAfterSemi(EnumDcl->getLocEnd(), NS.getASTContext(),
/*IsDecl*/true);
- if (!EndOfEnumDclLoc.isInvalid()) {
+ if (EndOfEnumDclLoc.isValid()) {
SourceLocation BeginOfEnumDclLoc = EnumDcl->getLocStart();
// FIXME. This assumes that enum decl; is immediately preceded by eoln.
// It is trying to remove the enum decl. lines entirely.
@@ -1536,7 +1524,7 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
FuncDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
FuncDecl->hasAttr<NSReturnsAutoreleasedAttr>());
- // Trivial case of when funciton is annotated and has no argument.
+ // Trivial case of when function is annotated and has no argument.
if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0)
return CF_BRIDGING_NONE;
@@ -1665,7 +1653,7 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
Editor->commit(commit);
}
- // Trivial case of when funciton is annotated and has no argument.
+ // Trivial case of when function is annotated and has no argument.
if (MethodIsReturnAnnotated &&
(MethodDecl->param_begin() == MethodDecl->param_end()))
return;
@@ -1805,7 +1793,7 @@ private:
FileID FID;
unsigned Offset;
std::tie(FID, Offset) = SourceMgr.getDecomposedLoc(Loc);
- assert(!FID.isInvalid());
+ assert(FID.isValid());
SmallString<200> Path =
StringRef(SourceMgr.getFileEntryForID(FID)->getName());
llvm::sys::fs::make_absolute(Path);
@@ -1862,8 +1850,8 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
D != DEnd; ++D) {
FileID FID = PP.getSourceManager().getFileID((*D)->getLocation());
- if (!FID.isInvalid())
- if (!FileId.isInvalid() && FileId != FID) {
+ if (FID.isValid())
+ if (FileId.isValid() && FileId != FID) {
if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
AnnotateImplicitBridging(Ctx);
}
@@ -1982,7 +1970,6 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
SmallString<512> newText;
llvm::raw_svector_ostream vecOS(newText);
buf.write(vecOS);
- vecOS.flush();
std::unique_ptr<llvm::MemoryBuffer> memBuf(
llvm::MemoryBuffer::getMemBufferCopy(
StringRef(newText.data(), newText.size()), file->getName()));
@@ -2215,12 +2202,11 @@ static std::string applyEditsToTemp(const FileEntry *FE,
SmallString<512> NewText;
llvm::raw_svector_ostream OS(NewText);
Buf->write(OS);
- OS.flush();
SmallString<64> TempPath;
int FD;
if (fs::createTemporaryFile(path::filename(FE->getName()),
- path::extension(FE->getName()), FD,
+ path::extension(FE->getName()).drop_front(), FD,
TempPath)) {
reportDiag("Could not create file: " + TempPath.str(), Diag);
return std::string();
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
index 9689f40..d45d5d6 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
@@ -104,9 +104,7 @@ public:
return false;
if (!S->getThen() || !Visit(S->getThen()))
return false;
- if (S->getElse() && !Visit(S->getElse()))
- return false;
- return true;
+ return !S->getElse() || Visit(S->getElse());
}
bool VisitWhileStmt(WhileStmt *S) {
if (S->getConditionVariable())
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransGCAttrs.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransGCAttrs.cpp
index 10fce19..2ae6b78 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransGCAttrs.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransGCAttrs.cpp
@@ -152,9 +152,7 @@ public:
return ID->getImplementation() != nullptr;
if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContD))
return CD->getImplementation() != nullptr;
- if (isa<ObjCImplDecl>(ContD))
- return true;
- return false;
+ return isa<ObjCImplDecl>(ContD);
}
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
index ab12884..8667bc2 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
@@ -96,6 +96,10 @@ public:
collectProperties(iface, AtProps);
+ // Look through extensions.
+ for (auto *Ext : iface->visible_extensions())
+ collectProperties(Ext, AtProps);
+
typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
prop_impl_iterator;
for (prop_impl_iterator
@@ -137,19 +141,6 @@ public:
Transaction Trans(Pass.TA);
rewriteProperty(props, atLoc);
}
-
- AtPropDeclsTy AtExtProps;
- // Look through extensions.
- for (auto *Ext : iface->visible_extensions())
- collectProperties(Ext, AtExtProps, &AtProps);
-
- for (AtPropDeclsTy::iterator
- I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
- SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
- PropsTy &props = I->second;
- Transaction Trans(Pass.TA);
- doActionForExtensionProp(props, atLoc);
- }
}
private:
@@ -177,15 +168,6 @@ private:
}
}
- void doActionForExtensionProp(PropsTy &props, SourceLocation atLoc) {
- llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;
- I = ActionOnProp.find(props[0].PropD->getIdentifier());
- if (I == ActionOnProp.end())
- return;
-
- doPropAction(I->second, props, atLoc, false);
- }
-
void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
index 7db1a1c..f81133f 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
@@ -150,11 +150,8 @@ public:
return true;
}
- if (!hasSideEffects(rec, Pass.Ctx)) {
- if (tryRemoving(RecContainer))
- return true;
- }
- Pass.TA.replace(RecContainer->getSourceRange(), RecRange);
+ if (hasSideEffects(rec, Pass.Ctx) || !tryRemoving(RecContainer))
+ Pass.TA.replace(RecContainer->getSourceRange(), RecRange);
return true;
}
@@ -174,11 +171,8 @@ private:
/// return var;
///
bool isCommonUnusedAutorelease(ObjCMessageExpr *E) {
- if (isPlusOneAssignBeforeOrAfterAutorelease(E))
- return true;
- if (isReturnedAfterAutorelease(E))
- return true;
- return false;
+ return isPlusOneAssignBeforeOrAfterAutorelease(E) ||
+ isReturnedAfterAutorelease(E);
}
bool isReturnedAfterAutorelease(ObjCMessageExpr *E) {
@@ -225,11 +219,7 @@ private:
// Check for "RefD = [+1 retained object];".
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {
- if (RefD != getReferencedDecl(Bop->getLHS()))
- return false;
- if (isPlusOneAssign(Bop))
- return true;
- return false;
+ return (RefD == getReferencedDecl(Bop->getLHS())) && isPlusOneAssign(Bop);
}
if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
@@ -359,16 +349,16 @@ private:
return;
Stmt::child_range StmtExprChild = StmtE->children();
- if (!StmtExprChild)
+ if (StmtExprChild.begin() == StmtExprChild.end())
return;
- CompoundStmt *CompS = dyn_cast_or_null<CompoundStmt>(*StmtExprChild);
+ auto *CompS = dyn_cast_or_null<CompoundStmt>(*StmtExprChild.begin());
if (!CompS)
return;
Stmt::child_range CompStmtChild = CompS->children();
- if (!CompStmtChild)
+ if (CompStmtChild.begin() == CompStmtChild.end())
return;
- DeclStmt *DeclS = dyn_cast_or_null<DeclStmt>(*CompStmtChild);
+ auto *DeclS = dyn_cast_or_null<DeclStmt>(*CompStmtChild.begin());
if (!DeclS)
return;
if (!DeclS->isSingleDecl())
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp
index 9fb2f1d..c628b54 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp
@@ -505,11 +505,10 @@ void TransformActionsImpl::commitClearDiagnostic(ArrayRef<unsigned> IDs,
void TransformActionsImpl::addInsertion(SourceLocation loc, StringRef text) {
SourceManager &SM = Ctx.getSourceManager();
loc = SM.getExpansionLoc(loc);
- for (std::list<CharRange>::reverse_iterator
- I = Removals.rbegin(), E = Removals.rend(); I != E; ++I) {
- if (!SM.isBeforeInTranslationUnit(loc, I->End))
+ for (const CharRange &I : llvm::reverse(Removals)) {
+ if (!SM.isBeforeInTranslationUnit(loc, I.End))
break;
- if (I->Begin.isBeforeInTranslationUnitThan(loc))
+ if (I.Begin.isBeforeInTranslationUnitThan(loc))
return;
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
index 56d3af7..3fd36ff 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
@@ -42,7 +42,7 @@ bool MigrationPass::CFBridgingFunctionsDefined() {
bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
bool AllowOnUnknownClass) {
- if (!Ctx.getLangOpts().ObjCARCWeak)
+ if (!Ctx.getLangOpts().ObjCWeakRuntime)
return false;
QualType T = type;
@@ -50,7 +50,8 @@ bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
return false;
// iOS is always safe to use 'weak'.
- if (Ctx.getTargetInfo().getTriple().isiOS())
+ if (Ctx.getTargetInfo().getTriple().isiOS() ||
+ Ctx.getTargetInfo().getTriple().isWatchOS())
AllowOnUnknownClass = true;
while (const PointerType *ptr = T->getAs<PointerType>())
@@ -112,10 +113,7 @@ bool trans::isPlusOne(const Expr *E) {
while (implCE && implCE->getCastKind() == CK_BitCast)
implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr());
- if (implCE && implCE->getCastKind() == CK_ARCConsumeObject)
- return true;
-
- return false;
+ return implCE && implCE->getCastKind() == CK_ARCConsumeObject;
}
/// \brief 'Loc' is the end of a statement range. This returns the location
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
index fb96301..6438696 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/Comment.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
@@ -327,7 +328,7 @@ const Decl *adjustDeclToTemplate(const Decl *D) {
// FIXME: Adjust alias templates?
return D;
}
-} // unnamed namespace
+} // anonymous namespace
const RawComment *ASTContext::getRawCommentForAnyRedecl(
const Decl *D,
@@ -366,8 +367,10 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl(
OriginalDeclForRC = I;
RawCommentAndCacheFlags Raw;
if (RC) {
- Raw.setRaw(RC);
+ // Call order swapped to work around ICE in VS2015 RTM (Release Win32)
+ // https://connect.microsoft.com/VisualStudio/feedback/details/1741530
Raw.setKind(RawCommentAndCacheFlags::FromDecl);
+ Raw.setRaw(RC);
} else
Raw.setKind(RawCommentAndCacheFlags::NoCommentInDecl);
Raw.setOriginalDecl(I);
@@ -428,7 +431,6 @@ comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC,
new (*this) comments::FullComment(FC->getBlocks(),
ThisDeclInfo);
return CFC;
-
}
comments::FullComment *ASTContext::getLocalCommentForDeclUncached(const Decl *D) const {
@@ -659,8 +661,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
nullptr,
TemplateParameterList::Create(*this, SourceLocation(),
SourceLocation(),
- CanonParams.data(),
- CanonParams.size(),
+ CanonParams,
SourceLocation()));
// Get the new insert position for the node we care about.
@@ -681,9 +682,11 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
case TargetCXXABI::GenericARM: // Same as Itanium at this level
case TargetCXXABI::iOS:
case TargetCXXABI::iOS64:
+ case TargetCXXABI::WatchOS:
case TargetCXXABI::GenericAArch64:
case TargetCXXABI::GenericMIPS:
case TargetCXXABI::GenericItanium:
+ case TargetCXXABI::WebAssembly:
return CreateItaniumCXXABI(*this);
case TargetCXXABI::Microsoft:
return CreateMicrosoftCXXABI(*this);
@@ -732,19 +735,20 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
SubstTemplateTemplateParmPacks(this_()),
GlobalNestedNameSpecifier(nullptr), Int128Decl(nullptr),
UInt128Decl(nullptr), Float128StubDecl(nullptr),
- BuiltinVaListDecl(nullptr), ObjCIdDecl(nullptr), ObjCSelDecl(nullptr),
- ObjCClassDecl(nullptr), ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr),
+ BuiltinVaListDecl(nullptr), BuiltinMSVaListDecl(nullptr),
+ ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), ObjCClassDecl(nullptr),
+ ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr),
CFConstantStringTypeDecl(nullptr), ObjCInstanceTypeDecl(nullptr),
FILEDecl(nullptr), jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr),
ucontext_tDecl(nullptr), BlockDescriptorType(nullptr),
BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr),
FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr),
- SourceMgr(SM), LangOpts(LOpts),
+ MakeIntegerSeqDecl(nullptr), SourceMgr(SM), LangOpts(LOpts),
SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
- AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts),
- Idents(idents), Selectors(sels), BuiltinInfo(builtins),
- DeclarationNames(*this), ExternalSource(nullptr), Listener(nullptr),
- Comments(SM), CommentsLoaded(false),
+ AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr),
+ PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
+ BuiltinInfo(builtins), DeclarationNames(*this), ExternalSource(nullptr),
+ Listener(nullptr), Comments(SM), CommentsLoaded(false),
CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(nullptr, 0) {
TUDecl = TranslationUnitDecl::Create(*this);
}
@@ -757,10 +761,8 @@ ASTContext::~ASTContext() {
ReleaseDeclContextMaps();
// Call all of the deallocation functions on all of their targets.
- for (DeallocationMap::const_iterator I = Deallocations.begin(),
- E = Deallocations.end(); I != E; ++I)
- for (unsigned J = 0, N = I->second.size(); J != N; ++J)
- (I->first)((I->second)[J]);
+ for (auto &Pair : Deallocations)
+ (Pair.first)(Pair.second);
// ASTRecordLayout objects in ASTRecordLayouts must always be destroyed
// because they can contain DenseMaps.
@@ -783,23 +785,33 @@ ASTContext::~ASTContext() {
A != AEnd; ++A)
A->second->~AttrVec();
+ for (std::pair<const MaterializeTemporaryExpr *, APValue *> &MTVPair :
+ MaterializedTemporaryValues)
+ MTVPair.second->~APValue();
+
llvm::DeleteContainerSeconds(MangleNumberingContexts);
}
void ASTContext::ReleaseParentMapEntries() {
- if (!AllParents) return;
- for (const auto &Entry : *AllParents) {
+ if (!PointerParents) return;
+ for (const auto &Entry : *PointerParents) {
if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
delete Entry.second.get<ast_type_traits::DynTypedNode *>();
- } else {
- assert(Entry.second.is<ParentVector *>());
+ } else if (Entry.second.is<ParentVector *>()) {
+ delete Entry.second.get<ParentVector *>();
+ }
+ }
+ for (const auto &Entry : *OtherParents) {
+ if (Entry.second.is<ast_type_traits::DynTypedNode *>()) {
+ delete Entry.second.get<ast_type_traits::DynTypedNode *>();
+ } else if (Entry.second.is<ParentVector *>()) {
delete Entry.second.get<ParentVector *>();
}
}
}
void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
- Deallocations[Callback].push_back(Data);
+ Deallocations.push_back({Callback, Data});
}
void
@@ -898,6 +910,24 @@ ExternCContextDecl *ASTContext::getExternCContextDecl() const {
return ExternCContext;
}
+BuiltinTemplateDecl *
+ASTContext::buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
+ const IdentifierInfo *II) const {
+ auto *BuiltinTemplate = BuiltinTemplateDecl::Create(*this, TUDecl, II, BTK);
+ BuiltinTemplate->setImplicit();
+ TUDecl->addDecl(BuiltinTemplate);
+
+ return BuiltinTemplate;
+}
+
+BuiltinTemplateDecl *
+ASTContext::getMakeIntegerSeqDecl() const {
+ if (!MakeIntegerSeqDecl)
+ MakeIntegerSeqDecl = buildBuiltinTemplateDecl(BTK__make_integer_seq,
+ getMakeIntegerSeqName());
+ return MakeIntegerSeqDecl;
+}
+
RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
RecordDecl::TagKind TK) const {
SourceLocation Loc;
@@ -950,13 +980,15 @@ void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) {
Types.push_back(Ty);
}
-void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
+void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
+ const TargetInfo *AuxTarget) {
assert((!this->Target || this->Target == &Target) &&
"Incorrect target reinitialization");
assert(VoidTy.isNull() && "Context reinitialized?");
this->Target = &Target;
-
+ this->AuxTarget = AuxTarget;
+
ABI.reset(createCXXABI(Target));
AddrSpaceMap = getAddressSpaceMap(Target, LangOpts);
AddrSpaceMapMangling = isAddrSpaceMapManglingEnabled(Target, LangOpts);
@@ -1043,6 +1075,10 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
// Placeholder type for builtin functions.
InitBuiltinType(BuiltinFnTy, BuiltinType::BuiltinFn);
+ // Placeholder type for OMP array sections.
+ if (LangOpts.OpenMP)
+ InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection);
+
// C99 6.2.5p11.
FloatComplexTy = getComplexType(FloatTy);
DoubleComplexTy = getComplexType(DoubleTy);
@@ -1059,10 +1095,21 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
InitBuiltinType(OCLImage1dBufferTy, BuiltinType::OCLImage1dBuffer);
InitBuiltinType(OCLImage2dTy, BuiltinType::OCLImage2d);
InitBuiltinType(OCLImage2dArrayTy, BuiltinType::OCLImage2dArray);
+ InitBuiltinType(OCLImage2dDepthTy, BuiltinType::OCLImage2dDepth);
+ InitBuiltinType(OCLImage2dArrayDepthTy, BuiltinType::OCLImage2dArrayDepth);
+ InitBuiltinType(OCLImage2dMSAATy, BuiltinType::OCLImage2dMSAA);
+ InitBuiltinType(OCLImage2dArrayMSAATy, BuiltinType::OCLImage2dArrayMSAA);
+ InitBuiltinType(OCLImage2dMSAADepthTy, BuiltinType::OCLImage2dMSAADepth);
+ InitBuiltinType(OCLImage2dArrayMSAADepthTy,
+ BuiltinType::OCLImage2dArrayMSAADepth);
InitBuiltinType(OCLImage3dTy, BuiltinType::OCLImage3d);
InitBuiltinType(OCLSamplerTy, BuiltinType::OCLSampler);
InitBuiltinType(OCLEventTy, BuiltinType::OCLEvent);
+ InitBuiltinType(OCLClkEventTy, BuiltinType::OCLClkEvent);
+ InitBuiltinType(OCLQueueTy, BuiltinType::OCLQueue);
+ InitBuiltinType(OCLNDRangeTy, BuiltinType::OCLNDRange);
+ InitBuiltinType(OCLReserveIDTy, BuiltinType::OCLReserveID);
}
// Builtin type for __objc_yes and __objc_no
@@ -1083,7 +1130,7 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
InitBuiltinType(HalfTy, BuiltinType::Half);
// Builtin type used to help define __builtin_va_list.
- VaListTagTy = QualType();
+ VaListTagDecl = nullptr;
}
DiagnosticsEngine &ASTContext::getDiagnostics() const {
@@ -1629,11 +1676,21 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Align = Target->getIntAlign();
break;
case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLNDRange:
+ case BuiltinType::OCLReserveID:
case BuiltinType::OCLImage1d:
case BuiltinType::OCLImage1dArray:
case BuiltinType::OCLImage1dBuffer:
case BuiltinType::OCLImage2d:
case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage2dDepth:
+ case BuiltinType::OCLImage2dArrayDepth:
+ case BuiltinType::OCLImage2dMSAA:
+ case BuiltinType::OCLImage2dArrayMSAA:
+ case BuiltinType::OCLImage2dMSAADepth:
+ case BuiltinType::OCLImage2dArrayMSAADepth:
case BuiltinType::OCLImage3d:
// Currently these types are pointers to opaque types.
Width = Target->getPointerWidth(0);
@@ -1779,6 +1836,13 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Align = static_cast<unsigned>(Width);
}
}
+ break;
+
+ case Type::Pipe: {
+ TypeInfo Info = getTypeInfo(cast<PipeType>(T)->getElementType());
+ Width = Info.Width;
+ Align = Info.Align;
+ }
}
@@ -1861,7 +1925,7 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
/// getTargetDefaultAlignForAttributeAligned - Return the default alignment
/// for __attribute__((aligned)) on this target, to be used if no alignment
/// value is specified.
-unsigned ASTContext::getTargetDefaultAlignForAttributeAligned(void) const {
+unsigned ASTContext::getTargetDefaultAlignForAttributeAligned() const {
return getTargetInfo().getDefaultAlignForAttributeAligned();
}
@@ -2006,6 +2070,17 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
ObjCImpls[CatD] = ImplD;
}
+const ObjCMethodDecl *
+ASTContext::getObjCMethodRedeclaration(const ObjCMethodDecl *MD) const {
+ return ObjCMethodRedecls.lookup(MD);
+}
+
+void ASTContext::setObjCMethodRedeclaration(const ObjCMethodDecl *MD,
+ const ObjCMethodDecl *Redecl) {
+ assert(!getObjCMethodRedeclaration(MD) && "MD already has a redeclaration");
+ ObjCMethodRedecls[MD] = Redecl;
+}
+
const ObjCInterfaceDecl *ASTContext::getObjContainingInterface(
const NamedDecl *ND) const {
if (const ObjCInterfaceDecl *ID =
@@ -2595,6 +2670,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
case Type::FunctionProto:
case Type::BlockPointer:
case Type::MemberPointer:
+ case Type::Pipe:
return type;
// These types can be variably-modified. All these modifications
@@ -2759,9 +2835,10 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
QualType canon = getQualifiedType(QualType(canonTy,0),
canonElementType.Quals);
- // If we didn't need extra canonicalization for the element type,
- // then just use that as our result.
- if (QualType(canonElementType.Ty, 0) == elementType)
+ // If we didn't need extra canonicalization for the element type or the size
+ // expression, then just use that as our result.
+ if (QualType(canonElementType.Ty, 0) == elementType &&
+ canonTy->getSizeExpr() == numElements)
return canon;
// Otherwise, we need to build a type which follows the spelling
@@ -2956,6 +3033,21 @@ static bool isCanonicalResultType(QualType T) {
T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone);
}
+CanQualType
+ASTContext::getCanonicalFunctionResultType(QualType ResultType) const {
+ CanQualType CanResultType = getCanonicalType(ResultType);
+
+ // Canonical result types do not have ARC lifetime qualifiers.
+ if (CanResultType.getQualifiers().hasObjCLifetime()) {
+ Qualifiers Qs = CanResultType.getQualifiers();
+ Qs.removeObjCLifetime();
+ return CanQualType::CreateUnsafe(
+ getQualifiedType(CanResultType.getUnqualifiedType(), Qs));
+ }
+
+ return CanResultType;
+}
+
QualType
ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
const FunctionProtoType::ExtProtoInfo &EPI) const {
@@ -2993,14 +3085,8 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
CanonicalEPI.HasTrailingReturn = false;
CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo();
- // Result types do not have ARC lifetime qualifiers.
- QualType CanResultTy = getCanonicalType(ResultTy);
- if (ResultTy.getQualifiers().hasObjCLifetime()) {
- Qualifiers Qs = CanResultTy.getQualifiers();
- Qs.removeObjCLifetime();
- CanResultTy = getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
- }
-
+ // Adjust the canonical function result type.
+ CanQualType CanResultTy = getCanonicalFunctionResultType(ResultTy);
Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI);
// Get the new insert position for the node we care about.
@@ -3039,6 +3125,32 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
return QualType(FTP, 0);
}
+/// Return pipe type for the specified type.
+QualType ASTContext::getPipeType(QualType T) const {
+ llvm::FoldingSetNodeID ID;
+ PipeType::Profile(ID, T);
+
+ void *InsertPos = 0;
+ if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(PT, 0);
+
+ // If the pipe element type isn't canonical, this won't be a canonical type
+ // either, so fill in the canonical type field.
+ QualType Canonical;
+ if (!T.isCanonical()) {
+ Canonical = getPipeType(getCanonicalType(T));
+
+ // Get the new insert position for the node we care about.
+ PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!NewIP && "Shouldn't be in the map!");
+ (void)NewIP;
+ }
+ PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical);
+ Types.push_back(New);
+ PipeTypes.InsertNode(New, InsertPos);
+ return QualType(New, 0);
+}
+
#ifndef NDEBUG
static bool NeedsInjectedClassNameType(const RecordDecl *D) {
if (!isa<CXXRecordDecl>(D)) return false;
@@ -3164,7 +3276,6 @@ QualType ASTContext::getAttributedType(AttributedType::Kind attrKind,
return QualType(type, 0);
}
-
/// \brief Retrieve a substitution-result type.
QualType
ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
@@ -3581,34 +3692,31 @@ static int CmpProtocolNames(ObjCProtocolDecl *const *LHS,
return DeclarationName::compare((*LHS)->getDeclName(), (*RHS)->getDeclName());
}
-static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols,
- unsigned NumProtocols) {
- if (NumProtocols == 0) return true;
+static bool areSortedAndUniqued(ArrayRef<ObjCProtocolDecl *> Protocols) {
+ if (Protocols.empty()) return true;
if (Protocols[0]->getCanonicalDecl() != Protocols[0])
return false;
- for (unsigned i = 1; i != NumProtocols; ++i)
+ for (unsigned i = 1; i != Protocols.size(); ++i)
if (CmpProtocolNames(&Protocols[i - 1], &Protocols[i]) >= 0 ||
Protocols[i]->getCanonicalDecl() != Protocols[i])
return false;
return true;
}
-static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
- unsigned &NumProtocols) {
- ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols;
-
+static void
+SortAndUniqueProtocols(SmallVectorImpl<ObjCProtocolDecl *> &Protocols) {
// Sort protocols, keyed by name.
- llvm::array_pod_sort(Protocols, ProtocolsEnd, CmpProtocolNames);
+ llvm::array_pod_sort(Protocols.begin(), Protocols.end(), CmpProtocolNames);
// Canonicalize.
- for (unsigned I = 0, N = NumProtocols; I != N; ++I)
- Protocols[I] = Protocols[I]->getCanonicalDecl();
-
+ for (ObjCProtocolDecl *&P : Protocols)
+ P = P->getCanonicalDecl();
+
// Remove duplicates.
- ProtocolsEnd = std::unique(Protocols, ProtocolsEnd);
- NumProtocols = ProtocolsEnd-Protocols;
+ auto ProtocolsEnd = std::unique(Protocols.begin(), Protocols.end());
+ Protocols.erase(ProtocolsEnd, Protocols.end());
}
QualType ASTContext::getObjCObjectType(QualType BaseType,
@@ -3655,8 +3763,7 @@ QualType ASTContext::getObjCObjectType(
[&](QualType type) {
return type.isCanonical();
});
- bool protocolsSorted = areSortedAndUniqued(protocols.data(),
- protocols.size());
+ bool protocolsSorted = areSortedAndUniqued(protocols);
if (!typeArgsAreCanonical || !protocolsSorted || !baseType.isCanonical()) {
// Determine the canonical type arguments.
ArrayRef<QualType> canonTypeArgs;
@@ -3673,12 +3780,9 @@ QualType ASTContext::getObjCObjectType(
ArrayRef<ObjCProtocolDecl *> canonProtocols;
SmallVector<ObjCProtocolDecl*, 8> canonProtocolsVec;
if (!protocolsSorted) {
- canonProtocolsVec.insert(canonProtocolsVec.begin(),
- protocols.begin(),
- protocols.end());
- unsigned uniqueCount = protocols.size();
- SortAndUniqueProtocols(&canonProtocolsVec[0], uniqueCount);
- canonProtocols = llvm::makeArrayRef(&canonProtocolsVec[0], uniqueCount);
+ canonProtocolsVec.append(protocols.begin(), protocols.end());
+ SortAndUniqueProtocols(canonProtocolsVec);
+ canonProtocols = canonProtocolsVec;
} else {
canonProtocols = protocols;
}
@@ -3869,7 +3973,6 @@ QualType ASTContext::getTypeOfType(QualType tofType) const {
return QualType(tot, 0);
}
-
/// \brief Unlike many "get<Type>" functions, we don't unique DecltypeType
/// nodes. This would never be helpful, since each such type has its own
/// expression, and would not give a significant memory saving, since there
@@ -3921,20 +4024,20 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType,
/// getAutoType - Return the uniqued reference to the 'auto' type which has been
/// deduced to the given type, or to the canonical undeduced 'auto' type, or the
/// canonical deduced-but-dependent 'auto' type.
-QualType ASTContext::getAutoType(QualType DeducedType, bool IsDecltypeAuto,
+QualType ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
bool IsDependent) const {
- if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent)
+ if (DeducedType.isNull() && Keyword == AutoTypeKeyword::Auto && !IsDependent)
return getAutoDeductType();
// Look in the folding set for an existing type.
void *InsertPos = nullptr;
llvm::FoldingSetNodeID ID;
- AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent);
+ AutoType::Profile(ID, DeducedType, Keyword, IsDependent);
if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(AT, 0);
AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType,
- IsDecltypeAuto,
+ Keyword,
IsDependent);
Types.push_back(AT);
if (InsertPos)
@@ -3974,7 +4077,7 @@ QualType ASTContext::getAtomicType(QualType T) const {
QualType ASTContext::getAutoDeductType() const {
if (AutoDeductTy.isNull())
AutoDeductTy = QualType(
- new (*this, TypeAlignment) AutoType(QualType(), /*decltype(auto)*/false,
+ new (*this, TypeAlignment) AutoType(QualType(), AutoTypeKeyword::Auto,
/*dependent*/false),
0);
return AutoDeductTy;
@@ -4310,7 +4413,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
A != AEnd; (void)++A, ++Idx)
CanonArgs[Idx] = getCanonicalTemplateArgument(*A);
- return TemplateArgument(CanonArgs, Arg.pack_size());
+ return TemplateArgument(llvm::makeArrayRef(CanonArgs, Arg.pack_size()));
}
}
@@ -4374,7 +4477,6 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
}
-
const ArrayType *ASTContext::getAsArrayType(QualType T) const {
// Handle the non-qualified case efficiently.
if (!T.hasLocalQualifiers()) {
@@ -4909,8 +5011,6 @@ bool ASTContext::BlockRequiresCopying(QualType Ty,
// If we have lifetime, that dominates.
if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
- assert(getLangOpts().ObjCAutoRefCount);
-
switch (lifetime) {
case Qualifiers::OCL_None: llvm_unreachable("impossible");
@@ -4944,14 +5044,14 @@ bool ASTContext::getByrefLifetime(QualType Ty,
if (Ty->isRecordType()) {
HasByrefExtendedLayout = true;
LifeTime = Qualifiers::OCL_None;
- }
- else if (getLangOpts().ObjCAutoRefCount)
- LifeTime = Ty.getObjCLifetime();
- // MRR.
- else if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType())
+ } else if ((LifeTime = Ty.getObjCLifetime())) {
+ // Honor the ARC qualifiers.
+ } else if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType()) {
+ // The MRR rule.
LifeTime = Qualifiers::OCL_ExplicitNone;
- else
+ } else {
LifeTime = Qualifiers::OCL_None;
+ }
return true;
}
@@ -4990,9 +5090,10 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const {
}
bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const {
- return getLangOpts().MSVCCompat && VD->isStaticDataMember() &&
+ return getTargetInfo().getCXXABI().isMicrosoft() &&
+ VD->isStaticDataMember() &&
VD->getType()->isIntegralOrEnumerationType() &&
- VD->isFirstDecl() && !VD->isOutOfLine() && VD->hasInit();
+ !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit();
}
static inline
@@ -5364,8 +5465,18 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C,
case BuiltinType::OCLImage1dBuffer:
case BuiltinType::OCLImage2d:
case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage2dDepth:
+ case BuiltinType::OCLImage2dArrayDepth:
+ case BuiltinType::OCLImage2dMSAA:
+ case BuiltinType::OCLImage2dArrayMSAA:
+ case BuiltinType::OCLImage2dMSAADepth:
+ case BuiltinType::OCLImage2dArrayMSAADepth:
case BuiltinType::OCLImage3d:
case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLNDRange:
+ case BuiltinType::OCLReserveID:
case BuiltinType::OCLSampler:
case BuiltinType::Dependent:
#define BUILTIN_TYPE(KIND, ID)
@@ -5779,8 +5890,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
// Just ignore it.
case Type::Auto:
return;
-
+ case Type::Pipe:
#define ABSTRACT_TYPE(KIND, BASE)
#define TYPE(KIND, BASE)
#define DEPENDENT_TYPE(KIND, BASE) \
@@ -5998,10 +6109,19 @@ ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const {
// __builtin_va_list Construction Functions
//===----------------------------------------------------------------------===//
-static TypedefDecl *CreateCharPtrBuiltinVaListDecl(const ASTContext *Context) {
- // typedef char* __builtin_va_list;
+static TypedefDecl *CreateCharPtrNamedVaListDecl(const ASTContext *Context,
+ StringRef Name) {
+ // typedef char* __builtin[_ms]_va_list;
QualType T = Context->getPointerType(Context->CharTy);
- return Context->buildImplicitTypedef(T, "__builtin_va_list");
+ return Context->buildImplicitTypedef(T, Name);
+}
+
+static TypedefDecl *CreateMSVaListDecl(const ASTContext *Context) {
+ return CreateCharPtrNamedVaListDecl(Context, "__builtin_ms_va_list");
+}
+
+static TypedefDecl *CreateCharPtrBuiltinVaListDecl(const ASTContext *Context) {
+ return CreateCharPtrNamedVaListDecl(Context, "__builtin_va_list");
}
static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) {
@@ -6067,8 +6187,8 @@ CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) {
VaListTagDecl->addDecl(Field);
}
VaListTagDecl->completeDefinition();
+ Context->VaListTagDecl = VaListTagDecl;
QualType VaListTagType = Context->getRecordType(VaListTagDecl);
- Context->VaListTagTy = VaListTagType;
// } __builtin_va_list;
return Context->buildImplicitTypedef(VaListTagType, "__builtin_va_list");
@@ -6119,8 +6239,8 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) {
VaListTagDecl->addDecl(Field);
}
VaListTagDecl->completeDefinition();
+ Context->VaListTagDecl = VaListTagDecl;
QualType VaListTagType = Context->getRecordType(VaListTagDecl);
- Context->VaListTagTy = VaListTagType;
// } __va_list_tag;
TypedefDecl *VaListTagTypedefDecl =
@@ -6139,7 +6259,7 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) {
static TypedefDecl *
CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) {
- // typedef struct __va_list_tag {
+ // struct __va_list_tag {
RecordDecl *VaListTagDecl;
VaListTagDecl = Context->buildImplicitRecord("__va_list_tag");
VaListTagDecl->startDefinition();
@@ -6179,21 +6299,15 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) {
VaListTagDecl->addDecl(Field);
}
VaListTagDecl->completeDefinition();
+ Context->VaListTagDecl = VaListTagDecl;
QualType VaListTagType = Context->getRecordType(VaListTagDecl);
- Context->VaListTagTy = VaListTagType;
- // } __va_list_tag;
- TypedefDecl *VaListTagTypedefDecl =
- Context->buildImplicitTypedef(VaListTagType, "__va_list_tag");
-
- QualType VaListTagTypedefType =
- Context->getTypedefType(VaListTagTypedefDecl);
+ // };
- // typedef __va_list_tag __builtin_va_list[1];
+ // typedef struct __va_list_tag __builtin_va_list[1];
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
- QualType VaListTagArrayType
- = Context->getConstantArrayType(VaListTagTypedefType,
- Size, ArrayType::Normal,0);
+ QualType VaListTagArrayType =
+ Context->getConstantArrayType(VaListTagType, Size, ArrayType::Normal, 0);
return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list");
}
@@ -6248,7 +6362,7 @@ CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) {
static TypedefDecl *
CreateSystemZBuiltinVaListDecl(const ASTContext *Context) {
- // typedef struct __va_list_tag {
+ // struct __va_list_tag {
RecordDecl *VaListTagDecl;
VaListTagDecl = Context->buildImplicitRecord("__va_list_tag");
VaListTagDecl->startDefinition();
@@ -6288,20 +6402,15 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) {
VaListTagDecl->addDecl(Field);
}
VaListTagDecl->completeDefinition();
+ Context->VaListTagDecl = VaListTagDecl;
QualType VaListTagType = Context->getRecordType(VaListTagDecl);
- Context->VaListTagTy = VaListTagType;
- // } __va_list_tag;
- TypedefDecl *VaListTagTypedefDecl =
- Context->buildImplicitTypedef(VaListTagType, "__va_list_tag");
- QualType VaListTagTypedefType =
- Context->getTypedefType(VaListTagTypedefDecl);
+ // };
// typedef __va_list_tag __builtin_va_list[1];
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
- QualType VaListTagArrayType
- = Context->getConstantArrayType(VaListTagTypedefType,
- Size, ArrayType::Normal,0);
+ QualType VaListTagArrayType =
+ Context->getConstantArrayType(VaListTagType, Size, ArrayType::Normal, 0);
return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list");
}
@@ -6339,13 +6448,20 @@ TypedefDecl *ASTContext::getBuiltinVaListDecl() const {
return BuiltinVaListDecl;
}
-QualType ASTContext::getVaListTagType() const {
- // Force the creation of VaListTagTy by building the __builtin_va_list
+Decl *ASTContext::getVaListTagDecl() const {
+ // Force the creation of VaListTagDecl by building the __builtin_va_list
// declaration.
- if (VaListTagTy.isNull())
- (void) getBuiltinVaListDecl();
+ if (!VaListTagDecl)
+ (void)getBuiltinVaListDecl();
- return VaListTagTy;
+ return VaListTagDecl;
+}
+
+TypedefDecl *ASTContext::getBuiltinMSVaListDecl() const {
+ if (!BuiltinMSVaListDecl)
+ BuiltinMSVaListDecl = CreateMSVaListDecl(this);
+
+ return BuiltinMSVaListDecl;
}
void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
@@ -7711,6 +7827,24 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return QualType();
}
+ case Type::Pipe:
+ {
+ // Merge two pointer types, while trying to preserve typedef info
+ QualType LHSValue = LHS->getAs<PipeType>()->getElementType();
+ QualType RHSValue = RHS->getAs<PipeType>()->getElementType();
+ if (Unqualified) {
+ LHSValue = LHSValue.getUnqualifiedType();
+ RHSValue = RHSValue.getUnqualifiedType();
+ }
+ QualType ResultType = mergeTypes(LHSValue, RHSValue, false,
+ Unqualified);
+ if (ResultType.isNull()) return QualType();
+ if (getCanonicalType(LHSValue) == getCanonicalType(ResultType))
+ return LHS;
+ if (getCanonicalType(RHSValue) == getCanonicalType(ResultType))
+ return RHS;
+ return getPipeType(ResultType);
+ }
}
llvm_unreachable("Invalid Type::Class!");
@@ -7734,6 +7868,10 @@ bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs(
return true;
}
+void ASTContext::ResetObjCLayout(const ObjCContainerDecl *CD) {
+ ObjCLayouts[CD] = nullptr;
+}
+
/// mergeObjCGCQualifiers - This routine merges ObjC's GC attribute of 'LHS' and
/// 'RHS' attributes and returns the merged version; including for function
/// return types.
@@ -8128,7 +8266,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
QualType ASTContext::GetBuiltinType(unsigned Id,
GetBuiltinTypeError &Error,
unsigned *IntegerConstantArgs) const {
- const char *TypeStr = BuiltinInfo.GetTypeString(Id);
+ const char *TypeStr = BuiltinInfo.getTypeString(Id);
SmallVector<QualType, 8> ArgTypes;
@@ -8212,7 +8350,8 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
if (!FD->isInlined())
return External;
- if ((!Context.getLangOpts().CPlusPlus && !Context.getLangOpts().MSVCCompat &&
+ if ((!Context.getLangOpts().CPlusPlus &&
+ !Context.getTargetInfo().getCXXABI().isMicrosoft() &&
!FD->hasAttr<DLLExportAttr>()) ||
FD->hasAttr<GNUInlineAttr>()) {
// FIXME: This doesn't match gcc's behavior for dllexport inline functions.
@@ -8235,13 +8374,13 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
return GVA_DiscardableODR;
}
-static GVALinkage adjustGVALinkageForDLLAttribute(GVALinkage L, const Decl *D) {
+static GVALinkage adjustGVALinkageForAttributes(GVALinkage L, const Decl *D) {
// See http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx
// dllexport/dllimport on inline functions.
if (D->hasAttr<DLLImportAttr>()) {
if (L == GVA_DiscardableODR || L == GVA_StrongODR)
return GVA_AvailableExternally;
- } else if (D->hasAttr<DLLExportAttr>()) {
+ } else if (D->hasAttr<DLLExportAttr>() || D->hasAttr<CUDAGlobalAttr>()) {
if (L == GVA_DiscardableODR)
return GVA_StrongODR;
}
@@ -8249,8 +8388,8 @@ static GVALinkage adjustGVALinkageForDLLAttribute(GVALinkage L, const Decl *D) {
}
GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const {
- return adjustGVALinkageForDLLAttribute(basicGVALinkageForFunction(*this, FD),
- FD);
+ return adjustGVALinkageForAttributes(basicGVALinkageForFunction(*this, FD),
+ FD);
}
static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
@@ -8285,9 +8424,14 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
switch (VD->getTemplateSpecializationKind()) {
case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
return GVA_StrongExternal;
+ case TSK_ExplicitSpecialization:
+ return Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ VD->isStaticDataMember()
+ ? GVA_StrongODR
+ : GVA_StrongExternal;
+
case TSK_ExplicitInstantiationDefinition:
return GVA_StrongODR;
@@ -8302,8 +8446,8 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
}
GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
- return adjustGVALinkageForDLLAttribute(basicGVALinkageForVariable(*this, VD),
- VD);
+ return adjustGVALinkageForAttributes(basicGVALinkageForVariable(*this, VD),
+ VD);
}
bool ASTContext::DeclMustBeEmitted(const Decl *D) {
@@ -8313,6 +8457,9 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
// Global named register variables (GNU extension) are never emitted.
if (VD->getStorageClass() == SC_Register)
return false;
+ if (VD->getDescribedVarTemplate() ||
+ isa<VarTemplatePartialSpecializationDecl>(VD))
+ return false;
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// We never need to emit an uninstantiated function template.
if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
@@ -8385,7 +8532,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return true;
// Variables that have initialization with side-effects are required.
- if (VD->getInit() && VD->getInit()->HasSideEffects(*this))
+ if (VD->getInit() && VD->getInit()->HasSideEffects(*this) &&
+ !VD->evaluateValue())
return true;
return false;
@@ -8425,6 +8573,8 @@ MangleContext *ASTContext::createMangleContext() {
case TargetCXXABI::GenericMIPS:
case TargetCXXABI::iOS:
case TargetCXXABI::iOS64:
+ case TargetCXXABI::WebAssembly:
+ case TargetCXXABI::WatchOS:
return ItaniumMangleContext::create(*this, getDiagnostics());
case TargetCXXABI::Microsoft:
return MicrosoftMangleContext::create(*this, getDiagnostics());
@@ -8543,6 +8693,25 @@ Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx);
}
+void ASTContext::addTypedefNameForUnnamedTagDecl(TagDecl *TD,
+ TypedefNameDecl *DD) {
+ return ABI->addTypedefNameForUnnamedTagDecl(TD, DD);
+}
+
+TypedefNameDecl *
+ASTContext::getTypedefNameForUnnamedTagDecl(const TagDecl *TD) {
+ return ABI->getTypedefNameForUnnamedTagDecl(TD);
+}
+
+void ASTContext::addDeclaratorForUnnamedTagDecl(TagDecl *TD,
+ DeclaratorDecl *DD) {
+ return ABI->addDeclaratorForUnnamedTagDecl(TD, DD);
+}
+
+DeclaratorDecl *ASTContext::getDeclaratorForUnnamedTagDecl(const TagDecl *TD) {
+ return ABI->getDeclaratorForUnnamedTagDecl(TD);
+}
+
void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
ParamIndices[D] = index;
}
@@ -8559,12 +8728,14 @@ ASTContext::getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E,
bool MayCreate) {
assert(E && E->getStorageDuration() == SD_Static &&
"don't need to cache the computed value for this temporary");
- if (MayCreate)
- return &MaterializedTemporaryValues[E];
+ if (MayCreate) {
+ APValue *&MTVI = MaterializedTemporaryValues[E];
+ if (!MTVI)
+ MTVI = new (*this) APValue;
+ return MTVI;
+ }
- llvm::DenseMap<const MaterializeTemporaryExpr *, APValue>::iterator I =
- MaterializedTemporaryValues.find(E);
- return I == MaterializedTemporaryValues.end() ? nullptr : &I->second;
+ return MaterializedTemporaryValues.lookup(E);
}
bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const {
@@ -8587,6 +8758,32 @@ bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const {
namespace {
+ast_type_traits::DynTypedNode getSingleDynTypedNodeFromParentMap(
+ ASTContext::ParentMapPointers::mapped_type U) {
+ if (const auto *D = U.dyn_cast<const Decl *>())
+ return ast_type_traits::DynTypedNode::create(*D);
+ if (const auto *S = U.dyn_cast<const Stmt *>())
+ return ast_type_traits::DynTypedNode::create(*S);
+ return *U.get<ast_type_traits::DynTypedNode *>();
+}
+
+/// Template specializations to abstract away from pointers and TypeLocs.
+/// @{
+template <typename T>
+ast_type_traits::DynTypedNode createDynTypedNode(const T &Node) {
+ return ast_type_traits::DynTypedNode::create(*Node);
+}
+template <>
+ast_type_traits::DynTypedNode createDynTypedNode(const TypeLoc &Node) {
+ return ast_type_traits::DynTypedNode::create(Node);
+}
+template <>
+ast_type_traits::DynTypedNode
+createDynTypedNode(const NestedNameSpecifierLoc &Node) {
+ return ast_type_traits::DynTypedNode::create(Node);
+}
+/// @}
+
/// \brief A \c RecursiveASTVisitor that builds a map from nodes to their
/// parents as defined by the \c RecursiveASTVisitor.
///
@@ -8596,22 +8793,25 @@ namespace {
///
/// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes.
class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> {
-
public:
/// \brief Builds and returns the translation unit's parent map.
///
/// The caller takes ownership of the returned \c ParentMap.
- static ASTContext::ParentMap *buildMap(TranslationUnitDecl &TU) {
- ParentMapASTVisitor Visitor(new ASTContext::ParentMap);
+ static std::pair<ASTContext::ParentMapPointers *,
+ ASTContext::ParentMapOtherNodes *>
+ buildMap(TranslationUnitDecl &TU) {
+ ParentMapASTVisitor Visitor(new ASTContext::ParentMapPointers,
+ new ASTContext::ParentMapOtherNodes);
Visitor.TraverseDecl(&TU);
- return Visitor.Parents;
+ return std::make_pair(Visitor.Parents, Visitor.OtherParents);
}
private:
typedef RecursiveASTVisitor<ParentMapASTVisitor> VisitorBase;
- ParentMapASTVisitor(ASTContext::ParentMap *Parents) : Parents(Parents) {
- }
+ ParentMapASTVisitor(ASTContext::ParentMapPointers *Parents,
+ ASTContext::ParentMapOtherNodes *OtherParents)
+ : Parents(Parents), OtherParents(OtherParents) {}
bool shouldVisitTemplateInstantiations() const {
return true;
@@ -8619,14 +8819,11 @@ namespace {
bool shouldVisitImplicitCode() const {
return true;
}
- // Disables data recursion. We intercept Traverse* methods in the RAV, which
- // are not triggered during data recursion.
- bool shouldUseDataRecursionFor(clang::Stmt *S) const {
- return false;
- }
- template <typename T>
- bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) {
+ template <typename T, typename MapNodeTy, typename BaseTraverseFn,
+ typename MapTy>
+ bool TraverseNode(T Node, MapNodeTy MapNode,
+ BaseTraverseFn BaseTraverse, MapTy *Parents) {
if (!Node)
return true;
if (ParentStack.size() > 0) {
@@ -8640,18 +8837,25 @@ namespace {
// map. The main problem there is to implement hash functions /
// comparison operators for all types that DynTypedNode supports that
// do not have pointer identity.
- auto &NodeOrVector = (*Parents)[Node];
+ auto &NodeOrVector = (*Parents)[MapNode];
if (NodeOrVector.isNull()) {
- NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back());
+ if (const auto *D = ParentStack.back().get<Decl>())
+ NodeOrVector = D;
+ else if (const auto *S = ParentStack.back().get<Stmt>())
+ NodeOrVector = S;
+ else
+ NodeOrVector =
+ new ast_type_traits::DynTypedNode(ParentStack.back());
} else {
- if (NodeOrVector.template is<ast_type_traits::DynTypedNode *>()) {
- auto *Node =
- NodeOrVector.template get<ast_type_traits::DynTypedNode *>();
- auto *Vector = new ASTContext::ParentVector(1, *Node);
+ if (!NodeOrVector.template is<ASTContext::ParentVector *>()) {
+ auto *Vector = new ASTContext::ParentVector(
+ 1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
+ if (auto *Node =
+ NodeOrVector
+ .template dyn_cast<ast_type_traits::DynTypedNode *>())
+ delete Node;
NodeOrVector = Vector;
- delete Node;
}
- assert(NodeOrVector.template is<ASTContext::ParentVector *>());
auto *Vector =
NodeOrVector.template get<ASTContext::ParentVector *>();
@@ -8666,47 +8870,74 @@ namespace {
Vector->push_back(ParentStack.back());
}
}
- ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node));
- bool Result = (this ->* traverse) (Node);
+ ParentStack.push_back(createDynTypedNode(Node));
+ bool Result = BaseTraverse();
ParentStack.pop_back();
return Result;
}
bool TraverseDecl(Decl *DeclNode) {
- return TraverseNode(DeclNode, &VisitorBase::TraverseDecl);
+ return TraverseNode(DeclNode, DeclNode,
+ [&] { return VisitorBase::TraverseDecl(DeclNode); },
+ Parents);
}
bool TraverseStmt(Stmt *StmtNode) {
- return TraverseNode(StmtNode, &VisitorBase::TraverseStmt);
+ return TraverseNode(StmtNode, StmtNode,
+ [&] { return VisitorBase::TraverseStmt(StmtNode); },
+ Parents);
+ }
+
+ bool TraverseTypeLoc(TypeLoc TypeLocNode) {
+ return TraverseNode(
+ TypeLocNode, ast_type_traits::DynTypedNode::create(TypeLocNode),
+ [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); },
+ OtherParents);
}
- ASTContext::ParentMap *Parents;
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
+ return TraverseNode(
+ NNSLocNode, ast_type_traits::DynTypedNode::create(NNSLocNode),
+ [&] {
+ return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode);
+ },
+ OtherParents);
+ }
+
+ ASTContext::ParentMapPointers *Parents;
+ ASTContext::ParentMapOtherNodes *OtherParents;
llvm::SmallVector<ast_type_traits::DynTypedNode, 16> ParentStack;
friend class RecursiveASTVisitor<ParentMapASTVisitor>;
};
-} // end namespace
+} // anonymous namespace
+
+template <typename NodeTy, typename MapTy>
+static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node,
+ const MapTy &Map) {
+ auto I = Map.find(Node);
+ if (I == Map.end()) {
+ return llvm::ArrayRef<ast_type_traits::DynTypedNode>();
+ }
+ if (auto *V = I->second.template dyn_cast<ASTContext::ParentVector *>()) {
+ return llvm::makeArrayRef(*V);
+ }
+ return getSingleDynTypedNodeFromParentMap(I->second);
+}
-ArrayRef<ast_type_traits::DynTypedNode>
+ASTContext::DynTypedNodeList
ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) {
- assert(Node.getMemoizationData() &&
- "Invariant broken: only nodes that support memoization may be "
- "used in the parent map.");
- if (!AllParents) {
+ if (!PointerParents) {
// We always need to run over the whole translation unit, as
// hasAncestor can escape any subtree.
- AllParents.reset(
- ParentMapASTVisitor::buildMap(*getTranslationUnitDecl()));
- }
- ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData());
- if (I == AllParents->end()) {
- return None;
- }
- if (auto *N = I->second.dyn_cast<ast_type_traits::DynTypedNode *>()) {
- return llvm::makeArrayRef(N, 1);
+ auto Maps = ParentMapASTVisitor::buildMap(*getTranslationUnitDecl());
+ PointerParents.reset(Maps.first);
+ OtherParents.reset(Maps.second);
}
- return *I->second.get<ParentVector *>();
+ if (Node.getNodeKind().hasPointerIdentity())
+ return getDynNodeFromMap(Node.getMemoizationData(), *PointerParents);
+ return getDynNodeFromMap(Node, *OtherParents);
}
bool
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
index dddaa5a..0ab1fa7 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp
@@ -66,11 +66,63 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
continue;
}
- // Don't desugar template specializations, unless it's an alias template.
- if (const TemplateSpecializationType *TST
- = dyn_cast<TemplateSpecializationType>(Ty))
- if (!TST->isTypeAlias())
+ // Desugar FunctionType if return type or any parameter type should be
+ // desugared. Preserve nullability attribute on desugared types.
+ if (const FunctionType *FT = dyn_cast<FunctionType>(Ty)) {
+ bool DesugarReturn = false;
+ QualType SugarRT = FT->getReturnType();
+ QualType RT = Desugar(Context, SugarRT, DesugarReturn);
+ if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) {
+ RT = Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(*nullability), RT, RT);
+ }
+
+ bool DesugarArgument = false;
+ SmallVector<QualType, 4> Args;
+ const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT);
+ if (FPT) {
+ for (QualType SugarPT : FPT->param_types()) {
+ QualType PT = Desugar(Context, SugarPT, DesugarArgument);
+ if (auto nullability =
+ AttributedType::stripOuterNullability(SugarPT)) {
+ PT = Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(*nullability), PT, PT);
+ }
+ Args.push_back(PT);
+ }
+ }
+
+ if (DesugarReturn || DesugarArgument) {
+ ShouldAKA = true;
+ QT = FPT ? Context.getFunctionType(RT, Args, FPT->getExtProtoInfo())
+ : Context.getFunctionNoProtoType(RT, FT->getExtInfo());
+ break;
+ }
+ }
+
+ // Desugar template specializations if any template argument should be
+ // desugared.
+ if (const TemplateSpecializationType *TST =
+ dyn_cast<TemplateSpecializationType>(Ty)) {
+ if (!TST->isTypeAlias()) {
+ bool DesugarArgument = false;
+ SmallVector<TemplateArgument, 4> Args;
+ for (unsigned I = 0, N = TST->getNumArgs(); I != N; ++I) {
+ const TemplateArgument &Arg = TST->getArg(I);
+ if (Arg.getKind() == TemplateArgument::Type)
+ Args.push_back(Desugar(Context, Arg.getAsType(), DesugarArgument));
+ else
+ Args.push_back(Arg);
+ }
+
+ if (DesugarArgument) {
+ ShouldAKA = true;
+ QT = Context.getTemplateSpecializationType(
+ TST->getTemplateName(), Args.data(), Args.size(), QT);
+ }
break;
+ }
+ }
// Don't desugar magic Objective-C types.
if (QualType(Ty,0) == Context.getObjCIdType() ||
@@ -80,7 +132,8 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
break;
// Don't desugar va_list.
- if (QualType(Ty,0) == Context.getBuiltinVaListType())
+ if (QualType(Ty, 0) == Context.getBuiltinVaListType() ||
+ QualType(Ty, 0) == Context.getBuiltinMSVaListType())
break;
// Otherwise, do a single-step desugar.
@@ -393,8 +446,6 @@ void clang::FormatASTNodeDiagnosticArgument(
}
- OS.flush();
-
if (NeedQuotes) {
Output.insert(Output.begin()+OldEnd, '\'');
Output.push_back('\'');
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
index c95922b..4622a75 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTDumper.cpp
@@ -21,8 +21,10 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeVisitor.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Sema/LocInfoType.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace clang::comments;
@@ -447,6 +449,7 @@ namespace {
const ClassTemplatePartialSpecializationDecl *D);
void VisitClassScopeFunctionSpecializationDecl(
const ClassScopeFunctionSpecializationDecl *D);
+ void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D);
void VisitVarTemplateDecl(const VarTemplateDecl *D);
void VisitVarTemplateSpecializationDecl(
const VarTemplateSpecializationDecl *D);
@@ -653,6 +656,15 @@ void ASTDumper::dumpTypeAsChild(const Type *T) {
OS << "<<<NULL>>>";
return;
}
+ if (const LocInfoType *LIT = llvm::dyn_cast<LocInfoType>(T)) {
+ {
+ ColorScope Color(*this, TypeColor);
+ OS << "LocInfo Type";
+ }
+ dumpPointer(T);
+ dumpTypeAsChild(LIT->getTypeSourceInfo()->getType());
+ return;
+ }
{
ColorScope Color(*this, TypeColor);
@@ -1043,6 +1055,7 @@ void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) {
dumpType(D->getUnderlyingType());
if (D->isModulePrivate())
OS << " __module_private__";
+ dumpTypeAsChild(D->getUnderlyingType());
}
void ASTDumper::VisitEnumDecl(const EnumDecl *D) {
@@ -1214,6 +1227,7 @@ void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
dumpName(D);
dumpType(D->getUnderlyingType());
+ dumpTypeAsChild(D->getUnderlyingType());
}
void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
@@ -1333,6 +1347,11 @@ void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
VisitTemplateDecl(D, false);
}
+void ASTDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
+ dumpName(D);
+ dumpTemplateParameters(D->getTemplateParameters());
+}
+
void ASTDumper::VisitVarTemplateSpecializationDecl(
const VarTemplateSpecializationDecl *D) {
dumpTemplateArgumentList(D->getTemplateArgs());
@@ -1378,20 +1397,23 @@ void ASTDumper::VisitTemplateTemplateParmDecl(
void ASTDumper::VisitUsingDecl(const UsingDecl *D) {
OS << ' ';
- D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
+ if (D->getQualifier())
+ D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
OS << D->getNameAsString();
}
void ASTDumper::VisitUnresolvedUsingTypenameDecl(
const UnresolvedUsingTypenameDecl *D) {
OS << ' ';
- D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
+ if (D->getQualifier())
+ D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
OS << D->getNameAsString();
}
void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
OS << ' ';
- D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
+ if (D->getQualifier())
+ D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
OS << D->getNameAsString();
dumpType(D->getType());
}
@@ -1399,6 +1421,8 @@ void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D)
void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) {
OS << ' ';
dumpBareDeclRef(D->getTargetDecl());
+ if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl()))
+ dumpTypeAsChild(TD->getTypeForDecl());
}
void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
@@ -2017,6 +2041,9 @@ void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
VisitExpr(Node);
dumpPointer(Node->getPack());
dumpName(Node->getPack());
+ if (Node->isPartiallySubstituted())
+ for (const auto &A : Node->getPartialArguments())
+ dumpTemplateArgument(A);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
index 35c0f69..916f108 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
@@ -878,6 +878,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
}
+ case Type::Pipe: {
+ if (!IsStructurallyEquivalent(Context,
+ cast<PipeType>(T1)->getElementType(),
+ cast<PipeType>(T2)->getElementType()))
+ return false;
+ break;
+ }
+
} // end switch
return true;
@@ -1746,7 +1754,7 @@ QualType ASTNodeImporter::VisitAutoType(const AutoType *T) {
return QualType();
}
- return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto(),
+ return Importer.getToContext().getAutoType(ToDeduced, T->getKeyword(),
/*IsDependent*/false);
}
@@ -2144,7 +2152,7 @@ TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList(
return TemplateParameterList::Create(Importer.getToContext(),
Importer.Import(Params->getTemplateLoc()),
Importer.Import(Params->getLAngleLoc()),
- ToParams.data(), ToParams.size(),
+ ToParams,
Importer.Import(Params->getRAngleLoc()));
}
@@ -2210,11 +2218,9 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
ToPack.reserve(From.pack_size());
if (ImportTemplateArguments(From.pack_begin(), From.pack_size(), ToPack))
return TemplateArgument();
-
- TemplateArgument *ToArgs
- = new (Importer.getToContext()) TemplateArgument[ToPack.size()];
- std::copy(ToPack.begin(), ToPack.end(), ToArgs);
- return TemplateArgument(ToArgs, ToPack.size());
+
+ return TemplateArgument(
+ llvm::makeArrayRef(ToPack).copy(Importer.getToContext()));
}
}
@@ -4917,13 +4923,14 @@ Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
if (!ToBody && S->getBody())
return nullptr;
SourceLocation ToForLoc = Importer.Import(S->getForLoc());
+ SourceLocation ToCoawaitLoc = Importer.Import(S->getCoawaitLoc());
SourceLocation ToColonLoc = Importer.Import(S->getColonLoc());
SourceLocation ToRParenLoc = Importer.Import(S->getRParenLoc());
return new (Importer.getToContext()) CXXForRangeStmt(ToRange, ToBeginEnd,
ToCond, ToInc,
ToLoopVar, ToBody,
- ToForLoc, ToColonLoc,
- ToRParenLoc);
+ ToForLoc, ToCoawaitLoc,
+ ToColonLoc, ToRParenLoc);
}
Stmt *ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
@@ -5331,7 +5338,7 @@ Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
return new (Importer.getToContext())
CallExpr(Importer.getToContext(), ToCallee,
- ArrayRef<Expr*>(ToArgs_Copied, NumArgs), T, E->getValueKind(),
+ llvm::makeArrayRef(ToArgs_Copied, NumArgs), T, E->getValueKind(),
Importer.Import(E->getRParenLoc()));
}
diff --git a/contrib/llvm/tools/clang/lib/AST/CXXABI.h b/contrib/llvm/tools/clang/lib/AST/CXXABI.h
index dad2264..c23b919 100644
--- a/contrib/llvm/tools/clang/lib/AST/CXXABI.h
+++ b/contrib/llvm/tools/clang/lib/AST/CXXABI.h
@@ -21,6 +21,7 @@ namespace clang {
class ASTContext;
class CXXConstructorDecl;
+class DeclaratorDecl;
class Expr;
class MemberPointerType;
class MangleNumberingContext;
@@ -57,6 +58,17 @@ public:
virtual Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
unsigned ParmIdx) = 0;
+
+ virtual void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
+ TypedefNameDecl *DD) = 0;
+
+ virtual TypedefNameDecl *
+ getTypedefNameForUnnamedTagDecl(const TagDecl *TD) = 0;
+
+ virtual void addDeclaratorForUnnamedTagDecl(TagDecl *TD,
+ DeclaratorDecl *DD) = 0;
+
+ virtual DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) = 0;
};
/// Creates an instance of a C++ ABI class.
diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
index 800c8f8..6785a0c 100644
--- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp
@@ -31,16 +31,16 @@ void CXXBasePaths::ComputeDeclsFound() {
Decls.insert(Path->Decls.front());
NumDeclsFound = Decls.size();
- DeclsFound = new NamedDecl * [NumDeclsFound];
- std::copy(Decls.begin(), Decls.end(), DeclsFound);
+ DeclsFound = llvm::make_unique<NamedDecl *[]>(NumDeclsFound);
+ std::copy(Decls.begin(), Decls.end(), DeclsFound.get());
}
CXXBasePaths::decl_range CXXBasePaths::found_decls() {
if (NumDeclsFound == 0)
ComputeDeclsFound();
- return decl_range(decl_iterator(DeclsFound),
- decl_iterator(DeclsFound + NumDeclsFound));
+ return decl_range(decl_iterator(DeclsFound.get()),
+ decl_iterator(DeclsFound.get() + NumDeclsFound));
}
/// isAmbiguous - Determines whether the set of paths provided is
@@ -85,9 +85,14 @@ bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base,
return false;
Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
- return lookupInBases(&FindBaseClass,
- const_cast<CXXRecordDecl*>(Base->getCanonicalDecl()),
- Paths);
+
+ const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
+ // FIXME: Capturing 'this' is a workaround for name lookup bugs in GCC 4.7.
+ return lookupInBases(
+ [this, BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ return FindBaseClass(Specifier, Path, BaseDecl);
+ },
+ Paths);
}
bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const {
@@ -102,20 +107,20 @@ bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const {
Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
- const void *BasePtr = static_cast<const void*>(Base->getCanonicalDecl());
- return lookupInBases(&FindVirtualBaseClass,
- const_cast<void *>(BasePtr),
- Paths);
-}
-
-static bool BaseIsNot(const CXXRecordDecl *Base, void *OpaqueTarget) {
- // OpaqueTarget is a CXXRecordDecl*.
- return Base->getCanonicalDecl() != (const CXXRecordDecl*) OpaqueTarget;
+ const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
+ // FIXME: Capturing 'this' is a workaround for name lookup bugs in GCC 4.7.
+ return lookupInBases(
+ [this, BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ return FindVirtualBaseClass(Specifier, Path, BaseDecl);
+ },
+ Paths);
}
bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const {
- return forallBases(BaseIsNot,
- const_cast<CXXRecordDecl *>(Base->getCanonicalDecl()));
+ const CXXRecordDecl *TargetDecl = Base->getCanonicalDecl();
+ return forallBases([TargetDecl](const CXXRecordDecl *Base) {
+ return Base->getCanonicalDecl() != TargetDecl;
+ });
}
bool
@@ -129,8 +134,7 @@ CXXRecordDecl::isCurrentInstantiation(const DeclContext *CurContext) const {
return false;
}
-bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches,
- void *OpaqueData,
+bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches,
bool AllowShortCircuit) const {
SmallVector<const CXXRecordDecl*, 8> Queue;
@@ -156,7 +160,7 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches,
}
Queue.push_back(Base);
- if (!BaseMatches(Base, OpaqueData)) {
+ if (!BaseMatches(Base)) {
if (AllowShortCircuit) return false;
AllMatches = false;
continue;
@@ -171,10 +175,9 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches,
return AllMatches;
}
-bool CXXBasePaths::lookupInBases(ASTContext &Context,
- const CXXRecordDecl *Record,
- CXXRecordDecl::BaseMatchesCallback *BaseMatches,
- void *UserData) {
+bool CXXBasePaths::lookupInBases(
+ ASTContext &Context, const CXXRecordDecl *Record,
+ CXXRecordDecl::BaseMatchesCallback BaseMatches) {
bool FoundPath = false;
// The access of the path down to this record.
@@ -248,7 +251,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
// Track whether there's a path involving this specific base.
bool FoundPathThroughBase = false;
- if (BaseMatches(&BaseSpec, ScratchPath, UserData)) {
+ if (BaseMatches(&BaseSpec, ScratchPath)) {
// We've found a path that terminates at this base.
FoundPath = FoundPathThroughBase = true;
if (isRecordingPaths()) {
@@ -263,7 +266,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
CXXRecordDecl *BaseRecord
= cast<CXXRecordDecl>(BaseSpec.getType()->castAs<RecordType>()
->getDecl());
- if (lookupInBases(Context, BaseRecord, BaseMatches, UserData)) {
+ if (lookupInBases(Context, BaseRecord, BaseMatches)) {
// C++ [class.member.lookup]p2:
// A member name f in one sub-object B hides a member name f in
// a sub-object A if A is a base class sub-object of B. Any
@@ -296,11 +299,10 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
return FoundPath;
}
-bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
- void *UserData,
+bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches,
CXXBasePaths &Paths) const {
// If we didn't find anything, report that.
- if (!Paths.lookupInBases(getASTContext(), this, BaseMatches, UserData))
+ if (!Paths.lookupInBases(getASTContext(), this, BaseMatches))
return false;
// If we're not recording paths or we won't ever find ambiguities,
@@ -353,8 +355,8 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *BaseRecord) {
- assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord &&
+ const CXXRecordDecl *BaseRecord) {
+ assert(BaseRecord->getCanonicalDecl() == BaseRecord &&
"User data for FindBaseClass is not canonical!");
return Specifier->getType()->castAs<RecordType>()->getDecl()
->getCanonicalDecl() == BaseRecord;
@@ -362,8 +364,8 @@ bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier,
bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *BaseRecord) {
- assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord &&
+ const CXXRecordDecl *BaseRecord) {
+ assert(BaseRecord->getCanonicalDecl() == BaseRecord &&
"User data for FindBaseClass is not canonical!");
return Specifier->isVirtual() &&
Specifier->getType()->castAs<RecordType>()->getDecl()
@@ -372,12 +374,11 @@ bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *Name) {
+ DeclarationName Name) {
RecordDecl *BaseRecord =
Specifier->getType()->castAs<RecordType>()->getDecl();
- DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
- for (Path.Decls = BaseRecord->lookup(N);
+ for (Path.Decls = BaseRecord->lookup(Name);
!Path.Decls.empty();
Path.Decls = Path.Decls.slice(1)) {
if (Path.Decls.front()->isInIdentifierNamespace(IDNS_Tag))
@@ -389,13 +390,12 @@ bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier,
bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *Name) {
+ DeclarationName Name) {
RecordDecl *BaseRecord =
Specifier->getType()->castAs<RecordType>()->getDecl();
const unsigned IDNS = IDNS_Ordinary | IDNS_Tag | IDNS_Member;
- DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
- for (Path.Decls = BaseRecord->lookup(N);
+ for (Path.Decls = BaseRecord->lookup(Name);
!Path.Decls.empty();
Path.Decls = Path.Decls.slice(1)) {
if (Path.Decls.front()->isInIdentifierNamespace(IDNS))
@@ -408,12 +408,11 @@ bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
bool CXXRecordDecl::
FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *Name) {
+ DeclarationName Name) {
RecordDecl *BaseRecord =
Specifier->getType()->castAs<RecordType>()->getDecl();
- DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
- for (Path.Decls = BaseRecord->lookup(N);
+ for (Path.Decls = BaseRecord->lookup(Name);
!Path.Decls.empty();
Path.Decls = Path.Decls.slice(1)) {
// FIXME: Refactor the "is it a nested-name-specifier?" check
diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
index ea4b2f5..427ca5e 100644
--- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
@@ -207,13 +207,13 @@ static Optional<Visibility> getVisibilityOf(const NamedDecl *D,
// If we're ultimately computing the visibility of a type, look for
// a 'type_visibility' attribute before looking for 'visibility'.
if (kind == NamedDecl::VisibilityForType) {
- if (const TypeVisibilityAttr *A = D->getAttr<TypeVisibilityAttr>()) {
+ if (const auto *A = D->getAttr<TypeVisibilityAttr>()) {
return getVisibilityFromAttr(A);
}
}
// If this declaration has an explicit visibility attribute, use it.
- if (const VisibilityAttr *A = D->getAttr<VisibilityAttr>()) {
+ if (const auto *A = D->getAttr<VisibilityAttr>()) {
return getVisibilityFromAttr(A);
}
@@ -252,8 +252,7 @@ getLVForTemplateParameterList(const TemplateParameterList *Params,
// template <enum X> class A { ... };
// We have to be careful here, though, because we can be dealing with
// dependent types.
- if (const NonTypeTemplateParmDecl *NTTP =
- dyn_cast<NonTypeTemplateParmDecl>(P)) {
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
// Handle the non-pack case first.
if (!NTTP->isExpandedParameterPack()) {
if (!NTTP->getType()->isDependentType()) {
@@ -273,7 +272,7 @@ getLVForTemplateParameterList(const TemplateParameterList *Params,
// Template template parameters can be restricted by their
// template parameters, recursively.
- const TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(P);
+ const auto *TTP = cast<TemplateTemplateParmDecl>(P);
// Handle the non-pack case first.
if (!TTP->isExpandedParameterPack()) {
@@ -329,7 +328,7 @@ static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
continue;
case TemplateArgument::Declaration:
- if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) {
+ if (const auto *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) {
assert(!usesTypeVisibility(ND));
LV.merge(getLVForDecl(ND, computation));
}
@@ -541,7 +540,7 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) {
if (!Opts.CPlusPlus || !Opts.InlineVisibilityHidden)
return false;
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ const auto *FD = dyn_cast<FunctionDecl>(D);
if (!FD)
return false;
@@ -569,7 +568,7 @@ template <typename T> static bool isFirstInExternCContext(T *D) {
}
static bool isSingleLineLanguageLinkage(const Decl &D) {
- if (const LinkageSpecDecl *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext()))
+ if (const auto *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext()))
if (!SD->hasBraces())
return true;
return false;
@@ -587,7 +586,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// - an object, reference, function or function template that is
// explicitly declared static; or,
// (This bullet corresponds to C99 6.2.2p3.)
- if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ if (const auto *Var = dyn_cast<VarDecl>(D)) {
// Explicitly declared static.
if (Var->getStorageClass() == SC_Static)
return LinkageInfo::internal();
@@ -634,8 +633,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");
if (D->isInAnonymousNamespace()) {
- const VarDecl *Var = dyn_cast<VarDecl>(D);
- const FunctionDecl *Func = dyn_cast<FunctionDecl>(D);
+ const auto *Var = dyn_cast<VarDecl>(D);
+ const auto *Func = dyn_cast<FunctionDecl>(D);
+ // FIXME: In C++11 onwards, anonymous namespaces should give decls
+ // within them internal linkage, not unique external linkage.
if ((!Var || !isFirstInExternCContext(Var)) &&
(!Func || !isFirstInExternCContext(Func)))
return LinkageInfo::uniqueExternal();
@@ -658,7 +659,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
for (const DeclContext *DC = D->getDeclContext();
!isa<TranslationUnitDecl>(DC);
DC = DC->getParent()) {
- const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
+ const auto *ND = dyn_cast<NamespaceDecl>(DC);
if (!ND) continue;
if (Optional<Visibility> Vis = getExplicitVisibility(ND, computation)) {
LV.mergeVisibility(*Vis, true);
@@ -692,7 +693,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// name of
//
// - an object or reference, unless it has internal linkage; or
- if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ if (const auto *Var = dyn_cast<VarDecl>(D)) {
// GCC applies the following optimization to variables and static
// data members, but not to functions:
//
@@ -732,13 +733,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// As per function and class template specializations (below),
// consider LV for the template and template arguments. We're at file
// scope, so we do not need to worry about nested specializations.
- if (const VarTemplateSpecializationDecl *spec
- = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
+ if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
mergeTemplateLV(LV, spec, computation);
}
// - a function, unless it has internal linkage; or
- } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ } else if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
// In theory, we can modify the function's LV by the LV of its
// type unless it has C linkage (see comment above about variables
// for justification). In practice, GCC doesn't do this, so it's
@@ -785,7 +785,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// - a named enumeration (7.2), or an unnamed enumeration
// defined in a typedef declaration in which the enumeration
// has the typedef name for linkage purposes (7.1.3); or
- } else if (const TagDecl *Tag = dyn_cast<TagDecl>(D)) {
+ } else if (const auto *Tag = dyn_cast<TagDecl>(D)) {
// Unnamed tags have no linkage.
if (!Tag->hasNameForLinkage())
return LinkageInfo::none();
@@ -793,8 +793,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// If this is a class template specialization, consider the
// linkage of the template and template arguments. We're at file
// scope, so we do not need to worry about nested specializations.
- if (const ClassTemplateSpecializationDecl *spec
- = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
+ if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
mergeTemplateLV(LV, spec, computation);
}
@@ -808,7 +807,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
// - a template, unless it is a function template that has
// internal linkage (Clause 14);
- } else if (const TemplateDecl *temp = dyn_cast<TemplateDecl>(D)) {
+ } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
bool considerVisibility = !hasExplicitVisibilityAlready(computation);
LinkageInfo tempLV =
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
@@ -824,10 +823,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
} else if (isa<ObjCInterfaceDecl>(D)) {
// fallout
+ } else if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
+ // A typedef declaration has linkage if it gives a type a name for
+ // linkage purposes.
+ if (!TD->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
+ return LinkageInfo::none();
+
// Everything not covered here has no linkage.
} else {
- // FIXME: A typedef declaration has linkage if it gives a type a name for
- // linkage purposes.
return LinkageInfo::none();
}
@@ -897,7 +900,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
// Specifically, if this decl exists and has an explicit attribute.
const NamedDecl *explicitSpecSuppressor = nullptr;
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
// If the type of the function uses a type with unique-external
// linkage, it's not legally usable from outside this translation unit.
// But only look at the type-as-written. If this function has an
@@ -928,9 +931,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
explicitSpecSuppressor = MD;
}
- } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
- if (const ClassTemplateSpecializationDecl *spec
- = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+ } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
+ if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
mergeTemplateLV(LV, spec, computation);
if (spec->isExplicitSpecialization()) {
explicitSpecSuppressor = spec;
@@ -945,9 +947,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
}
// Static data members.
- } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (const VarTemplateSpecializationDecl *spec
- = dyn_cast<VarTemplateSpecializationDecl>(VD))
+ } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(VD))
mergeTemplateLV(LV, spec, computation);
// Modify the variable's linkage by its type, but ignore the
@@ -962,7 +963,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
}
// Template members.
- } else if (const TemplateDecl *temp = dyn_cast<TemplateDecl>(D)) {
+ } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
bool considerVisibility =
(!LV.isVisibilityExplicit() &&
!classLV.isVisibilityExplicit() &&
@@ -971,8 +972,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D,
getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
- if (const RedeclarableTemplateDecl *redeclTemp =
- dyn_cast<RedeclarableTemplateDecl>(temp)) {
+ if (const auto *redeclTemp = dyn_cast<RedeclarableTemplateDecl>(temp)) {
if (isExplicitMemberSpecialization(redeclTemp)) {
explicitSpecSuppressor = temp->getTemplatedDecl();
}
@@ -1048,7 +1048,7 @@ getExplicitVisibilityAux(const NamedDecl *ND,
// If this is a member class of a specialization of a class template
// and the corresponding decl has explicit visibility, use that.
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(ND)) {
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
if (InstantiatedFrom)
return getVisibilityOf(InstantiatedFrom, kind);
@@ -1057,8 +1057,7 @@ getExplicitVisibilityAux(const NamedDecl *ND,
// If there wasn't explicit visibility there, and this is a
// specialization of a class template, check for visibility
// on the pattern.
- if (const ClassTemplateSpecializationDecl *spec
- = dyn_cast<ClassTemplateSpecializationDecl>(ND))
+ if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND))
return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
kind);
@@ -1069,7 +1068,7 @@ getExplicitVisibilityAux(const NamedDecl *ND,
return getExplicitVisibilityAux(MostRecent, kind, true);
}
- if (const VarDecl *Var = dyn_cast<VarDecl>(ND)) {
+ if (const auto *Var = dyn_cast<VarDecl>(ND)) {
if (Var->isStaticDataMember()) {
VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember();
if (InstantiatedFrom)
@@ -1083,7 +1082,7 @@ getExplicitVisibilityAux(const NamedDecl *ND,
return None;
}
// Also handle function template specializations.
- if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(ND)) {
+ if (const auto *fn = dyn_cast<FunctionDecl>(ND)) {
// If the function is a specialization of a template with an
// explicit visibility attribute, use that.
if (FunctionTemplateSpecializationInfo *templateInfo
@@ -1101,7 +1100,7 @@ getExplicitVisibilityAux(const NamedDecl *ND,
}
// The visibility of a template is stored in the templated decl.
- if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(ND))
+ if (const auto *TD = dyn_cast<TemplateDecl>(ND))
return getVisibilityOf(TD->getTemplatedDecl(), kind);
return None;
@@ -1122,7 +1121,7 @@ static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
return getLVForDecl(cast<NamedDecl>(ContextDecl), computation);
}
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
+ if (const auto *ND = dyn_cast<NamedDecl>(DC))
return getLVForDecl(ND, computation);
return LinkageInfo::external();
@@ -1130,7 +1129,7 @@ static LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
LVComputationKind computation) {
- if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
if (Function->isInAnonymousNamespace() &&
!Function->isInExternCContext())
return LinkageInfo::uniqueExternal();
@@ -1153,7 +1152,7 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
return LV;
}
- if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ if (const auto *Var = dyn_cast<VarDecl>(D)) {
if (Var->hasExternalStorage()) {
if (Var->isInAnonymousNamespace() && !Var->isInExternCContext())
return LinkageInfo::uniqueExternal();
@@ -1185,18 +1184,18 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
return LinkageInfo::none();
const Decl *OuterD = getOutermostFuncOrBlockContext(D);
- if (!OuterD)
+ if (!OuterD || OuterD->isInvalidDecl())
return LinkageInfo::none();
LinkageInfo LV;
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(OuterD)) {
+ if (const auto *BD = dyn_cast<BlockDecl>(OuterD)) {
if (!BD->getBlockManglingNumber())
return LinkageInfo::none();
LV = getLVForClosure(BD->getDeclContext()->getRedeclContext(),
BD->getBlockManglingContextDecl(), computation);
} else {
- const FunctionDecl *FD = cast<FunctionDecl>(OuterD);
+ const auto *FD = cast<FunctionDecl>(OuterD);
if (!FD->isInlined() &&
!isTemplateInstantiation(FD->getTemplateSpecializationKind()))
return LinkageInfo::none();
@@ -1224,13 +1223,45 @@ getOutermostEnclosingLambda(const CXXRecordDecl *Record) {
static LinkageInfo computeLVForDecl(const NamedDecl *D,
LVComputationKind computation) {
+ // Internal_linkage attribute overrides other considerations.
+ if (D->hasAttr<InternalLinkageAttr>())
+ return LinkageInfo::internal();
+
// Objective-C: treat all Objective-C declarations as having external
// linkage.
switch (D->getKind()) {
default:
break;
+
+ // Per C++ [basic.link]p2, only the names of objects, references,
+ // functions, types, templates, namespaces, and values ever have linkage.
+ //
+ // Note that the name of a typedef, namespace alias, using declaration,
+ // and so on are not the name of the corresponding type, namespace, or
+ // declaration, so they do *not* have linkage.
+ case Decl::ImplicitParam:
+ case Decl::Label:
+ case Decl::NamespaceAlias:
case Decl::ParmVar:
+ case Decl::Using:
+ case Decl::UsingShadow:
+ case Decl::UsingDirective:
return LinkageInfo::none();
+
+ case Decl::EnumConstant:
+ // C++ [basic.link]p4: an enumerator has the linkage of its enumeration.
+ return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation);
+
+ case Decl::Typedef:
+ case Decl::TypeAlias:
+ // A typedef declaration has linkage if it gives a type a name for
+ // linkage purposes.
+ if (!D->getASTContext().getLangOpts().CPlusPlus ||
+ !cast<TypedefNameDecl>(D)
+ ->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
+ return LinkageInfo::none();
+ break;
+
case Decl::TemplateTemplateParm: // count these as external
case Decl::NonTypeTemplateParm:
case Decl::ObjCAtDefsField:
@@ -1245,7 +1276,7 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D,
return LinkageInfo::external();
case Decl::CXXRecord: {
- const CXXRecordDecl *Record = cast<CXXRecordDecl>(D);
+ const auto *Record = cast<CXXRecordDecl>(D);
if (Record->isLambda()) {
if (!Record->getLambdaManglingNumber()) {
// This lambda has no mangling number, so it's internal.
@@ -1314,6 +1345,10 @@ class LinkageComputer {
public:
static LinkageInfo getLVForDecl(const NamedDecl *D,
LVComputationKind computation) {
+ // Internal_linkage attribute overrides other considerations.
+ if (D->hasAttr<InternalLinkageAttr>())
+ return LinkageInfo::internal();
+
if (computation == LVForLinkageOnly && D->hasCachedLinkage())
return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false);
@@ -1336,7 +1371,7 @@ public:
// computed also does.
NamedDecl *Old = nullptr;
for (auto I : D->redecls()) {
- NamedDecl *T = cast<NamedDecl>(I);
+ auto *T = cast<NamedDecl>(I);
if (T == D)
continue;
if (!T->isInvalidDecl() && T->hasCachedLinkage()) {
@@ -1388,28 +1423,29 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
for (ContextsTy::reverse_iterator I = Contexts.rbegin(), E = Contexts.rend();
I != E; ++I) {
- if (const ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(*I)) {
+ if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(*I)) {
OS << Spec->getName();
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
TemplateSpecializationType::PrintTemplateArgumentList(OS,
TemplateArgs.data(),
TemplateArgs.size(),
P);
- } else if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(*I)) {
+ } else if (const auto *ND = dyn_cast<NamespaceDecl>(*I)) {
if (P.SuppressUnwrittenScope &&
(ND->isAnonymousNamespace() || ND->isInline()))
continue;
- if (ND->isAnonymousNamespace())
- OS << "(anonymous namespace)";
+ if (ND->isAnonymousNamespace()) {
+ OS << (P.MSVCFormatting ? "`anonymous namespace\'"
+ : "(anonymous namespace)");
+ }
else
OS << *ND;
- } else if (const RecordDecl *RD = dyn_cast<RecordDecl>(*I)) {
+ } else if (const auto *RD = dyn_cast<RecordDecl>(*I)) {
if (!RD->getIdentifier())
OS << "(anonymous " << RD->getKindName() << ')';
else
OS << *RD;
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+ } else if (const auto *FD = dyn_cast<FunctionDecl>(*I)) {
const FunctionProtoType *FT = nullptr;
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>());
@@ -1430,6 +1466,15 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
}
}
OS << ')';
+ } else if (const auto *ED = dyn_cast<EnumDecl>(*I)) {
+ // C++ [dcl.enum]p10: Each enum-name and each unscoped
+ // enumerator is declared in the scope that immediately contains
+ // the enum-specifier. Each scoped enumerator is declared in the
+ // scope of the enumeration.
+ if (ED->isScoped() || ED->getIdentifier())
+ OS << *ED;
+ else
+ continue;
} else {
OS << *cast<NamedDecl>(*I);
}
@@ -1451,32 +1496,6 @@ void NamedDecl::getNameForDiagnostic(raw_ostream &OS,
printName(OS);
}
-static bool isKindReplaceableBy(Decl::Kind OldK, Decl::Kind NewK) {
- // For method declarations, we never replace.
- if (ObjCMethodDecl::classofKind(NewK))
- return false;
-
- if (OldK == NewK)
- return true;
-
- // A compatibility alias for a class can be replaced by an interface.
- if (ObjCCompatibleAliasDecl::classofKind(OldK) &&
- ObjCInterfaceDecl::classofKind(NewK))
- return true;
-
- // A typedef-declaration, alias-declaration, or Objective-C class declaration
- // can replace another declaration of the same type. Semantic analysis checks
- // that we have matching types.
- if ((TypedefNameDecl::classofKind(OldK) ||
- ObjCInterfaceDecl::classofKind(OldK)) &&
- (TypedefNameDecl::classofKind(NewK) ||
- ObjCInterfaceDecl::classofKind(NewK)))
- return true;
-
- // Otherwise, a kind mismatch implies that the declaration is not replaced.
- return false;
-}
-
template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) {
return true;
}
@@ -1500,9 +1519,19 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
if (OldD->isFromASTFile() && isFromASTFile())
return false;
- if (!isKindReplaceableBy(OldD->getKind(), getKind()))
+ // A kind mismatch implies that the declaration is not replaced.
+ if (OldD->getKind() != getKind())
+ return false;
+
+ // For method declarations, we never replace. (Why?)
+ if (isa<ObjCMethodDecl>(this))
return false;
+ // For parameters, pick the newer one. This is either an error or (in
+ // Objective-C) permitted as an extension.
+ if (isa<ParmVarDecl>(this))
+ return true;
+
// Inline namespaces can give us two declarations with the same
// name and kind in the same scope but different contexts; we should
// keep both declarations in this case.
@@ -1510,28 +1539,8 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
OldD->getDeclContext()->getRedeclContext()))
return false;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
- // For function declarations, we keep track of redeclarations.
- // FIXME: This returns false for functions that should in fact be replaced.
- // Instead, perform some kind of type check?
- if (FD->getPreviousDecl() != OldD)
- return false;
-
- // For function templates, the underlying function declarations are linked.
- if (const FunctionTemplateDecl *FunctionTemplate =
- dyn_cast<FunctionTemplateDecl>(this))
- return FunctionTemplate->getTemplatedDecl()->declarationReplaces(
- cast<FunctionTemplateDecl>(OldD)->getTemplatedDecl());
-
- // Using shadow declarations can be overloaded on their target declarations
- // if they introduce functions.
- // FIXME: If our target replaces the old target, can we replace the old
- // shadow declaration?
- if (auto *USD = dyn_cast<UsingShadowDecl>(this))
- if (USD->getTargetDecl() != cast<UsingShadowDecl>(OldD)->getTargetDecl())
- return false;
-
- // Using declarations can be overloaded if they introduce functions.
+ // Using declarations can be replaced if they import the same name from the
+ // same context.
if (auto *UD = dyn_cast<UsingDecl>(this)) {
ASTContext &Context = getASTContext();
return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) ==
@@ -1546,13 +1555,20 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
}
// UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
- // We want to keep it, unless it nominates same namespace.
+ // They can be replaced if they nominate the same namespace.
+ // FIXME: Is this true even if they have different module visibility?
if (auto *UD = dyn_cast<UsingDirectiveDecl>(this))
return UD->getNominatedNamespace()->getOriginalNamespace() ==
cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace()
->getOriginalNamespace();
- if (!IsKnownNewer && isRedeclarable(getKind())) {
+ if (isRedeclarable(getKind())) {
+ if (getCanonicalDecl() != OldD->getCanonicalDecl())
+ return false;
+
+ if (IsKnownNewer)
+ return true;
+
// Check whether this is actually newer than OldD. We want to keep the
// newer declaration. This loop will usually only iterate once, because
// OldD is usually the previous declaration.
@@ -1567,11 +1583,16 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
if (D->isCanonicalDecl())
return false;
}
+
+ // It's a newer declaration of the same kind of declaration in the same
+ // scope: we want this decl instead of the existing one.
+ return true;
}
- // It's a newer declaration of the same kind of declaration in the same scope,
- // and not an overload: we want this decl instead of the existing one.
- return true;
+ // In all other cases, we need to keep both declarations in case they have
+ // different visibility. Any attempt to use the name will result in an
+ // ambiguity if more than one is visible.
+ return false;
}
bool NamedDecl::hasLinkage() const {
@@ -1580,12 +1601,15 @@ bool NamedDecl::hasLinkage() const {
NamedDecl *NamedDecl::getUnderlyingDeclImpl() {
NamedDecl *ND = this;
- while (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND))
+ while (auto *UD = dyn_cast<UsingShadowDecl>(ND))
ND = UD->getTargetDecl();
- if (ObjCCompatibleAliasDecl *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND))
+ if (auto *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND))
return AD->getClassInterface();
+ if (auto *AD = dyn_cast<NamespaceAliasDecl>(ND))
+ return AD->getNamespace();
+
return ND;
}
@@ -1599,8 +1623,7 @@ bool NamedDecl::isCXXInstanceMember() const {
if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D))
return true;
- if (const CXXMethodDecl *MD =
- dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()))
+ if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()))
return MD->isInstance();
return false;
}
@@ -1628,7 +1651,7 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
// Make sure the extended decl info is allocated.
if (!hasExtInfo()) {
// Save (non-extended) type source info pointer.
- TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
+ auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
// Allocate external info struct.
DeclInfo = new (getASTContext()) ExtInfo;
// Restore savedTInfo into (extended) decl info.
@@ -1653,22 +1676,20 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
}
}
-void
-DeclaratorDecl::setTemplateParameterListsInfo(ASTContext &Context,
- unsigned NumTPLists,
- TemplateParameterList **TPLists) {
- assert(NumTPLists > 0);
+void DeclaratorDecl::setTemplateParameterListsInfo(
+ ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
+ assert(!TPLists.empty());
// Make sure the extended decl info is allocated.
if (!hasExtInfo()) {
// Save (non-extended) type source info pointer.
- TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
+ auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
// Allocate external info struct.
DeclInfo = new (getASTContext()) ExtInfo;
// Restore savedTInfo into (extended) decl info.
getExtInfo()->TInfo = savedTInfo;
}
// Set the template parameter lists info.
- getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
+ getExtInfo()->setTemplateParameterListsInfo(Context, TPLists);
}
SourceLocation DeclaratorDecl::getOuterLocStart() const {
@@ -1726,13 +1747,8 @@ SourceRange DeclaratorDecl::getSourceRange() const {
return SourceRange(getOuterLocStart(), RangeEnd);
}
-void
-QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
- unsigned NumTPLists,
- TemplateParameterList **TPLists) {
- assert((NumTPLists == 0 || TPLists != nullptr) &&
- "Empty array of template parameters with positive size!");
-
+void QualifierInfo::setTemplateParameterListsInfo(
+ ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
// Free previous template parameters (if any).
if (NumTemplParamLists > 0) {
Context.Deallocate(TemplParamLists);
@@ -1740,10 +1756,10 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
NumTemplParamLists = 0;
}
// Set info on matched template parameter lists (if any).
- if (NumTPLists > 0) {
- TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];
- NumTemplParamLists = NumTPLists;
- std::copy(TPLists, TPLists + NumTPLists, TemplParamLists);
+ if (!TPLists.empty()) {
+ TemplParamLists = new (Context) TemplateParameterList *[TPLists.size()];
+ NumTemplParamLists = TPLists.size();
+ std::copy(TPLists.begin(), TPLists.end(), TemplParamLists);
}
}
@@ -1756,7 +1772,6 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
case SC_None: break;
case SC_Auto: return "auto";
case SC_Extern: return "extern";
- case SC_OpenCLWorkGroupLocal: return "<<work-group-local>>";
case SC_PrivateExtern: return "__private_extern__";
case SC_Register: return "register";
case SC_Static: return "static";
@@ -1995,7 +2010,7 @@ VarDecl *VarDecl::getDefinition(ASTContext &C) {
VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const {
DefinitionKind Kind = DeclarationOnly;
-
+
const VarDecl *First = getFirstDecl();
for (auto I : First->redecls()) {
Kind = std::max(Kind, I->isThisDeclarationADefinition(C));
@@ -2016,6 +2031,31 @@ const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const {
return nullptr;
}
+bool VarDecl::hasInit() const {
+ if (auto *P = dyn_cast<ParmVarDecl>(this))
+ if (P->hasUnparsedDefaultArg() || P->hasUninstantiatedDefaultArg())
+ return false;
+
+ return !Init.isNull();
+}
+
+Expr *VarDecl::getInit() {
+ if (!hasInit())
+ return nullptr;
+
+ if (auto *S = Init.dyn_cast<Stmt *>())
+ return cast<Expr>(S);
+
+ return cast_or_null<Expr>(Init.get<EvaluatedStmt *>()->Value);
+}
+
+Stmt **VarDecl::getInitAddress() {
+ if (auto *ES = Init.dyn_cast<EvaluatedStmt *>())
+ return &ES->Value;
+
+ return Init.getAddrOfPtr1();
+}
+
bool VarDecl::isOutOfLine() const {
if (Decl::isOutOfLine())
return true;
@@ -2045,7 +2085,7 @@ VarDecl *VarDecl::getOutOfLineDefinition() {
}
void VarDecl::setInit(Expr *I) {
- if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) {
+ if (auto *Eval = Init.dyn_cast<EvaluatedStmt *>()) {
Eval->~EvaluatedStmt();
getASTContext().Deallocate(Eval);
}
@@ -2084,15 +2124,14 @@ bool VarDecl::isUsableInConstantExpressions(ASTContext &C) const {
/// form, which contains extra information on the evaluated value of the
/// initializer.
EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const {
- EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
+ auto *Eval = Init.dyn_cast<EvaluatedStmt *>();
if (!Eval) {
- Stmt *S = Init.get<Stmt *>();
// Note: EvaluatedStmt contains an APValue, which usually holds
// resources not allocated from the ASTContext. We need to do some
// work to avoid leaking those, but we do so in VarDecl::evaluateValue
// where we can detect whether there's anything to clean up or not.
Eval = new (getASTContext()) EvaluatedStmt;
- Eval->Value = S;
+ Eval->Value = Init.get<Stmt *>();
Init = Eval;
}
return Eval;
@@ -2120,7 +2159,7 @@ APValue *VarDecl::evaluateValue(
if (Eval->WasEvaluated)
return Eval->Evaluated.isUninit() ? nullptr : &Eval->Evaluated;
- const Expr *Init = cast<Expr>(Eval->Value);
+ const auto *Init = cast<Expr>(Eval->Value);
assert(!Init->isValueDependent());
if (Eval->IsEvaluating) {
@@ -2156,6 +2195,27 @@ APValue *VarDecl::evaluateValue(
return Result ? &Eval->Evaluated : nullptr;
}
+APValue *VarDecl::getEvaluatedValue() const {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+ if (Eval->WasEvaluated)
+ return &Eval->Evaluated;
+
+ return nullptr;
+}
+
+bool VarDecl::isInitKnownICE() const {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+ return Eval->CheckedICE;
+
+ return false;
+}
+
+bool VarDecl::isInitICE() const {
+ assert(isInitKnownICE() &&
+ "Check whether we already know that the initializer is an ICE");
+ return Init.get<EvaluatedStmt *>()->IsICE;
+}
+
bool VarDecl::checkInitIsICE() const {
// Initializers of weak variables are never ICEs.
if (isWeak())
@@ -2167,7 +2227,7 @@ bool VarDecl::checkInitIsICE() const {
// integral constant expression.
return Eval->IsICE;
- const Expr *Init = cast<Expr>(Eval->Value);
+ const auto *Init = cast<Expr>(Eval->Value);
assert(!Init->isValueDependent());
// In C++11, evaluate the initializer to check whether it's a constant
@@ -2200,8 +2260,7 @@ VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
}
TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
- if (const VarTemplateSpecializationDecl *Spec =
- dyn_cast<VarTemplateSpecializationDecl>(this))
+ if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
return Spec->getSpecializationKind();
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
@@ -2211,8 +2270,7 @@ TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
}
SourceLocation VarDecl::getPointOfInstantiation() const {
- if (const VarTemplateSpecializationDecl *Spec =
- dyn_cast<VarTemplateSpecializationDecl>(this))
+ if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
return Spec->getPointOfInstantiation();
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
@@ -2285,7 +2343,7 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
QualType ParmVarDecl::getOriginalType() const {
TypeSourceInfo *TSI = getTypeSourceInfo();
QualType T = TSI ? TSI->getType() : getType();
- if (const DecayedType *DT = dyn_cast<DecayedType>(T))
+ if (const auto *DT = dyn_cast<DecayedType>(T))
return DT->getOriginalType();
return T;
}
@@ -2315,22 +2373,56 @@ Expr *ParmVarDecl::getDefaultArg() {
assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
assert(!hasUninstantiatedDefaultArg() &&
"Default argument is not yet instantiated!");
-
+
Expr *Arg = getInit();
- if (ExprWithCleanups *E = dyn_cast_or_null<ExprWithCleanups>(Arg))
+ if (auto *E = dyn_cast_or_null<ExprWithCleanups>(Arg))
return E->getSubExpr();
return Arg;
}
+void ParmVarDecl::setDefaultArg(Expr *defarg) {
+ ParmVarDeclBits.DefaultArgKind = DAK_Normal;
+ Init = defarg;
+}
+
SourceRange ParmVarDecl::getDefaultArgRange() const {
- if (const Expr *E = getInit())
- return E->getSourceRange();
+ switch (ParmVarDeclBits.DefaultArgKind) {
+ case DAK_None:
+ case DAK_Unparsed:
+ // Nothing we can do here.
+ return SourceRange();
- if (hasUninstantiatedDefaultArg())
+ case DAK_Uninstantiated:
return getUninstantiatedDefaultArg()->getSourceRange();
- return SourceRange();
+ case DAK_Normal:
+ if (const Expr *E = getInit())
+ return E->getSourceRange();
+
+ // Missing an actual expression, may be invalid.
+ return SourceRange();
+ }
+ llvm_unreachable("Invalid default argument kind.");
+}
+
+void ParmVarDecl::setUninstantiatedDefaultArg(Expr *arg) {
+ ParmVarDeclBits.DefaultArgKind = DAK_Uninstantiated;
+ Init = arg;
+}
+
+Expr *ParmVarDecl::getUninstantiatedDefaultArg() {
+ assert(hasUninstantiatedDefaultArg() &&
+ "Wrong kind of initialization expression!");
+ return cast_or_null<Expr>(Init.get<Stmt *>());
+}
+
+bool ParmVarDecl::hasDefaultArg() const {
+ // FIXME: We should just return false for DAK_None here once callers are
+ // prepared for the case that we encountered an invalid default argument and
+ // were unable to even build an invalid expression.
+ return hasUnparsedDefaultArg() || hasUninstantiatedDefaultArg() ||
+ !Init.isNull();
}
bool ParmVarDecl::isParameterPack() const {
@@ -2360,7 +2452,7 @@ void FunctionDecl::getNameForDiagnostic(
}
bool FunctionDecl::isVariadic() const {
- if (const FunctionProtoType *FT = getType()->getAs<FunctionProtoType>())
+ if (const auto *FT = getType()->getAs<FunctionProtoType>())
return FT->isVariadic();
return false;
}
@@ -2421,7 +2513,7 @@ void FunctionDecl::setBody(Stmt *B) {
void FunctionDecl::setPure(bool P) {
IsPure = P;
if (P)
- if (CXXRecordDecl *Parent = dyn_cast<CXXRecordDecl>(getDeclContext()))
+ if (auto *Parent = dyn_cast<CXXRecordDecl>(getDeclContext()))
Parent->markedVirtualFunctionPure();
}
@@ -2476,7 +2568,7 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const {
if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
return false;
- const FunctionProtoType *proto = getType()->castAs<FunctionProtoType>();
+ const auto *proto = getType()->castAs<FunctionProtoType>();
if (proto->getNumParams() != 2 || proto->isVariadic())
return false;
@@ -2505,7 +2597,7 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const {
if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
return false;
- const FunctionProtoType *FPT = getType()->castAs<FunctionProtoType>();
+ const auto *FPT = getType()->castAs<FunctionProtoType>();
if (FPT->getNumParams() == 0 || FPT->getNumParams() > 2 || FPT->isVariadic())
return false;
@@ -2547,7 +2639,7 @@ bool FunctionDecl::isInExternCXXContext() const {
}
bool FunctionDecl::isGlobal() const {
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
+ if (const auto *Method = dyn_cast<CXXMethodDecl>(this))
return Method->isStatic();
if (getCanonicalDecl()->getStorageClass() == SC_Static)
@@ -2556,7 +2648,7 @@ bool FunctionDecl::isGlobal() const {
for (const DeclContext *DC = getDeclContext();
DC->isNamespace();
DC = DC->getParent()) {
- if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) {
+ if (const auto *Namespace = cast<NamespaceDecl>(DC)) {
if (!Namespace->getDeclName())
return false;
break;
@@ -2608,8 +2700,8 @@ unsigned FunctionDecl::getBuiltinID() const {
ASTContext &Context = getASTContext();
if (Context.getLangOpts().CPlusPlus) {
- const LinkageSpecDecl *LinkageDecl = dyn_cast<LinkageSpecDecl>(
- getFirstDecl()->getDeclContext());
+ const auto *LinkageDecl =
+ dyn_cast<LinkageSpecDecl>(getFirstDecl()->getDeclContext());
// In C++, the first declaration of a builtin is always inside an implicit
// extern "C".
// FIXME: A recognised library function may not be directly in an extern "C"
@@ -2649,7 +2741,7 @@ unsigned FunctionDecl::getBuiltinID() const {
/// based on its FunctionType. This is the length of the ParamInfo array
/// after it has been created.
unsigned FunctionDecl::getNumParams() const {
- const FunctionProtoType *FPT = getType()->getAs<FunctionProtoType>();
+ const auto *FPT = getType()->getAs<FunctionProtoType>();
return FPT ? FPT->getNumParams() : 0;
}
@@ -2711,7 +2803,8 @@ bool FunctionDecl::isMSExternInline() const {
assert(isInlined() && "expected to get called on an inlined function!");
const ASTContext &Context = getASTContext();
- if (!Context.getLangOpts().MSVCCompat && !hasAttr<DLLExportAttr>())
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ !hasAttr<DLLExportAttr>())
return false;
for (const FunctionDecl *FD = getMostRecentDecl(); FD;
@@ -2840,7 +2933,7 @@ bool FunctionDecl::hasUnusedResultAttr() const {
QualType RetType = getReturnType();
if (RetType->isRecordType()) {
const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl();
- const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(this);
+ const auto *MD = dyn_cast<CXXMethodDecl>(this);
if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() &&
!(MD && MD->getCorrespondingMethodInClass(Ret, true)))
return true;
@@ -2952,6 +3045,10 @@ FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
return nullptr;
}
+MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const {
+ return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>();
+}
+
void
FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
FunctionDecl *FD,
@@ -2963,6 +3060,14 @@ FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
TemplateOrSpecialization = Info;
}
+FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const {
+ return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl *>();
+}
+
+void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
+ TemplateOrSpecialization = Template;
+}
+
bool FunctionDecl::isImplicitlyInstantiable() const {
// If the function is invalid, it can't be implicitly instantiated.
if (isInvalidDecl())
@@ -3069,6 +3174,12 @@ FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const {
return getASTContext().getClassScopeSpecializationPattern(this);
}
+FunctionTemplateSpecializationInfo *
+FunctionDecl::getTemplateSpecializationInfo() const {
+ return TemplateOrSpecialization
+ .dyn_cast<FunctionTemplateSpecializationInfo *>();
+}
+
const TemplateArgumentList *
FunctionDecl::getTemplateSpecializationArgs() const {
if (FunctionTemplateSpecializationInfo *Info
@@ -3115,33 +3226,41 @@ FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context,
const UnresolvedSetImpl &Templates,
const TemplateArgumentListInfo &TemplateArgs) {
assert(TemplateOrSpecialization.isNull());
- size_t Size = sizeof(DependentFunctionTemplateSpecializationInfo);
- Size += Templates.size() * sizeof(FunctionTemplateDecl*);
- Size += TemplateArgs.size() * sizeof(TemplateArgumentLoc);
- void *Buffer = Context.Allocate(Size);
DependentFunctionTemplateSpecializationInfo *Info =
- new (Buffer) DependentFunctionTemplateSpecializationInfo(Templates,
- TemplateArgs);
+ DependentFunctionTemplateSpecializationInfo::Create(Context, Templates,
+ TemplateArgs);
TemplateOrSpecialization = Info;
}
+DependentFunctionTemplateSpecializationInfo *
+FunctionDecl::getDependentSpecializationInfo() const {
+ return TemplateOrSpecialization
+ .dyn_cast<DependentFunctionTemplateSpecializationInfo *>();
+}
+
+DependentFunctionTemplateSpecializationInfo *
+DependentFunctionTemplateSpecializationInfo::Create(
+ ASTContext &Context, const UnresolvedSetImpl &Ts,
+ const TemplateArgumentListInfo &TArgs) {
+ void *Buffer = Context.Allocate(
+ totalSizeToAlloc<TemplateArgumentLoc, FunctionTemplateDecl *>(
+ TArgs.size(), Ts.size()));
+ return new (Buffer) DependentFunctionTemplateSpecializationInfo(Ts, TArgs);
+}
+
DependentFunctionTemplateSpecializationInfo::
DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
const TemplateArgumentListInfo &TArgs)
: AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) {
- static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0,
- "Trailing data is unaligned!");
- d.NumTemplates = Ts.size();
- d.NumArgs = TArgs.size();
+ NumTemplates = Ts.size();
+ NumArgs = TArgs.size();
- FunctionTemplateDecl **TsArray =
- const_cast<FunctionTemplateDecl**>(getTemplates());
+ FunctionTemplateDecl **TsArray = getTrailingObjects<FunctionTemplateDecl *>();
for (unsigned I = 0, E = Ts.size(); I != E; ++I)
TsArray[I] = cast<FunctionTemplateDecl>(Ts[I]->getUnderlyingDecl());
- TemplateArgumentLoc *ArgsArray =
- const_cast<TemplateArgumentLoc*>(getTemplateArgs());
+ TemplateArgumentLoc *ArgsArray = getTrailingObjects<TemplateArgumentLoc>();
for (unsigned I = 0, E = TArgs.size(); I != E; ++I)
new (&ArgsArray[I]) TemplateArgumentLoc(TArgs[I]);
}
@@ -3335,7 +3454,7 @@ bool FieldDecl::isAnonymousStructOrUnion() const {
if (!isImplicit() || getDeclName())
return false;
- if (const RecordType *Record = getType()->getAs<RecordType>())
+ if (const auto *Record = getType()->getAs<RecordType>())
return Record->getDecl()->isAnonymousStructOrUnion();
return false;
@@ -3343,7 +3462,7 @@ bool FieldDecl::isAnonymousStructOrUnion() const {
unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
assert(isBitField() && "not a bitfield");
- Expr *BitWidth = static_cast<Expr *>(InitStorage.getPointer());
+ auto *BitWidth = static_cast<Expr *>(InitStorage.getPointer());
return BitWidth->EvaluateKnownConstInt(Ctx).getZExtValue();
}
@@ -3372,7 +3491,7 @@ SourceRange FieldDecl::getSourceRange() const {
case ISK_BitWidthOrNothing:
case ISK_InClassCopyInit:
case ISK_InClassListInit:
- if (const Expr *E = static_cast<const Expr *>(InitStorage.getPointer()))
+ if (const auto *E = static_cast<const Expr *>(InitStorage.getPointer()))
return SourceRange(getInnerLocStart(), E->getLocEnd());
// FALLTHROUGH
@@ -3408,7 +3527,7 @@ SourceRange TagDecl::getSourceRange() const {
TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); }
void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) {
- NamedDeclOrQualifier = TDD;
+ TypedefNameDeclOrQualifier = TDD;
if (const Type *T = getTypeForDecl()) {
(void)T;
assert(T->isLinkageValid());
@@ -3419,7 +3538,7 @@ void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) {
void TagDecl::startDefinition() {
IsBeingDefined = true;
- if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(this)) {
+ if (auto *D = dyn_cast<CXXRecordDecl>(this)) {
struct CXXRecordDecl::DefinitionData *Data =
new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
for (auto I : redecls())
@@ -3452,7 +3571,7 @@ TagDecl *TagDecl::getDefinition() const {
}
}
- if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this))
+ if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(this))
return CXXRD->getDefinition();
for (auto R : redecls())
@@ -3466,7 +3585,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
if (QualifierLoc) {
// Make sure the extended qualifier info is allocated.
if (!hasExtInfo())
- NamedDeclOrQualifier = new (getASTContext()) ExtInfo;
+ TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo;
// Set qualifier info.
getExtInfo()->QualifierLoc = QualifierLoc;
} else {
@@ -3474,7 +3593,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
if (hasExtInfo()) {
if (getExtInfo()->NumTemplParamLists == 0) {
getASTContext().Deallocate(getExtInfo());
- NamedDeclOrQualifier = (TypedefNameDecl*)nullptr;
+ TypedefNameDeclOrQualifier = (TypedefNameDecl *)nullptr;
}
else
getExtInfo()->QualifierLoc = QualifierLoc;
@@ -3482,16 +3601,15 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
}
}
-void TagDecl::setTemplateParameterListsInfo(ASTContext &Context,
- unsigned NumTPLists,
- TemplateParameterList **TPLists) {
- assert(NumTPLists > 0);
+void TagDecl::setTemplateParameterListsInfo(
+ ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
+ assert(!TPLists.empty());
// Make sure the extended decl info is allocated.
if (!hasExtInfo())
// Allocate external info struct.
- NamedDeclOrQualifier = new (getASTContext()) ExtInfo;
+ TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo;
// Set the template parameter lists info.
- getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists);
+ getExtInfo()->setTemplateParameterListsInfo(Context, TPLists);
}
//===----------------------------------------------------------------------===//
@@ -3505,9 +3623,8 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id,
EnumDecl *PrevDecl, bool IsScoped,
bool IsScopedUsingClassTag, bool IsFixed) {
- EnumDecl *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl,
- IsScoped, IsScopedUsingClassTag,
- IsFixed);
+ auto *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl,
+ IsScoped, IsScopedUsingClassTag, IsFixed);
Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules;
C.getTypeDeclType(Enum, PrevDecl);
return Enum;
@@ -3647,10 +3764,6 @@ bool RecordDecl::isMsStruct(const ASTContext &C) const {
return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1;
}
-static bool isFieldOrIndirectField(Decl::Kind K) {
- return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K);
-}
-
void RecordDecl::LoadFieldsFromExternalStorage() const {
ExternalASTSource *Source = getASTContext().getExternalSource();
assert(hasExternalLexicalStorage() && Source && "No external storage?");
@@ -3659,16 +3772,10 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
ExternalASTSource::Deserializing TheFields(Source);
SmallVector<Decl*, 64> Decls;
- LoadedFieldsFromExternalStorage = true;
- switch (Source->FindExternalLexicalDecls(this, isFieldOrIndirectField,
- Decls)) {
- case ELR_Success:
- break;
-
- case ELR_AlreadyLoaded:
- case ELR_Failure:
- return;
- }
+ LoadedFieldsFromExternalStorage = true;
+ Source->FindExternalLexicalDecls(this, [](Decl::Kind K) {
+ return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K);
+ }, Decls);
#ifndef NDEBUG
// Check that all decls we got were FieldDecls.
@@ -3690,7 +3797,7 @@ bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
!Context.getLangOpts().SanitizeAddressFieldPadding)
return false;
const auto &Blacklist = Context.getSanitizerBlacklist();
- const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this);
+ const auto *CXXRD = dyn_cast<CXXRecordDecl>(this);
// We may be able to relax some of these requirements.
int ReasonToReject = -1;
if (!CXXRD || CXXRD->isExternCContext())
@@ -3731,9 +3838,9 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const {
if (I->getIdentifier())
return I;
- if (const RecordType *RT = I->getType()->getAs<RecordType>())
+ if (const auto *RT = I->getType()->getAs<RecordType>())
if (const FieldDecl *NamedDataMember =
- RT->getDecl()->findFirstNamedDataMember())
+ RT->getDecl()->findFirstNamedDataMember())
return NamedDataMember;
}
@@ -3757,26 +3864,17 @@ void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) {
}
}
-void BlockDecl::setCaptures(ASTContext &Context,
- const Capture *begin,
- const Capture *end,
- bool capturesCXXThis) {
- CapturesCXXThis = capturesCXXThis;
+void BlockDecl::setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
+ bool CapturesCXXThis) {
+ this->CapturesCXXThis = CapturesCXXThis;
+ this->NumCaptures = Captures.size();
- if (begin == end) {
- NumCaptures = 0;
- Captures = nullptr;
+ if (Captures.empty()) {
+ this->Captures = nullptr;
return;
}
- NumCaptures = end - begin;
-
- // Avoid new Capture[] because we don't want to provide a default
- // constructor.
- size_t allocationSize = NumCaptures * sizeof(Capture);
- void *buffer = Context.Allocate(allocationSize, /*alignment*/sizeof(void*));
- memcpy(buffer, begin, allocationSize);
- Captures = static_cast<Capture*>(buffer);
+ this->Captures = Captures.copy(Context).data();
}
bool BlockDecl::capturesVariable(const VarDecl *variable) const {
@@ -3889,18 +3987,28 @@ BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) BlockDecl(nullptr, SourceLocation());
}
+CapturedDecl::CapturedDecl(DeclContext *DC, unsigned NumParams)
+ : Decl(Captured, DC, SourceLocation()), DeclContext(Captured),
+ NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) {}
+
CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC,
unsigned NumParams) {
- return new (C, DC, NumParams * sizeof(ImplicitParamDecl *))
+ return new (C, DC, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams))
CapturedDecl(DC, NumParams);
}
CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumParams) {
- return new (C, ID, NumParams * sizeof(ImplicitParamDecl *))
+ return new (C, ID, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams))
CapturedDecl(nullptr, NumParams);
}
+Stmt *CapturedDecl::getBody() const { return BodyAndNothrow.getPointer(); }
+void CapturedDecl::setBody(Stmt *B) { BodyAndNothrow.setPointer(B); }
+
+bool CapturedDecl::isNothrow() const { return BodyAndNothrow.getInt(); }
+void CapturedDecl::setNothrow(bool Nothrow) { BodyAndNothrow.setInt(Nothrow); }
+
EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
SourceLocation L,
IdentifierInfo *Id, QualType T,
@@ -3916,16 +4024,26 @@ EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
void IndirectFieldDecl::anchor() { }
+IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC,
+ SourceLocation L, DeclarationName N,
+ QualType T, NamedDecl **CH, unsigned CHS)
+ : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {
+ // In C++, indirect field declarations conflict with tag declarations in the
+ // same scope, so add them to IDNS_Tag so that tag redeclaration finds them.
+ if (C.getLangOpts().CPlusPlus)
+ IdentifierNamespace |= IDNS_Tag;
+}
+
IndirectFieldDecl *
IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, NamedDecl **CH,
unsigned CHS) {
- return new (C, DC) IndirectFieldDecl(DC, L, Id, T, CH, CHS);
+ return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH, CHS);
}
IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) IndirectFieldDecl(nullptr, SourceLocation(),
+ return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(),
DeclarationName(), QualType(), nullptr,
0);
}
@@ -4042,9 +4160,9 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
NextLocalImport()
{
assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size());
- SourceLocation *StoredLocs = reinterpret_cast<SourceLocation *>(this + 1);
- memcpy(StoredLocs, IdentifierLocs.data(),
- IdentifierLocs.size() * sizeof(SourceLocation));
+ auto *StoredLocs = getTrailingObjects<SourceLocation>();
+ std::uninitialized_copy(IdentifierLocs.begin(), IdentifierLocs.end(),
+ StoredLocs);
}
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
@@ -4052,13 +4170,14 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
: Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, false),
NextLocalImport()
{
- *reinterpret_cast<SourceLocation *>(this + 1) = EndLoc;
+ *getTrailingObjects<SourceLocation>() = EndLoc;
}
ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs) {
- return new (C, DC, IdentifierLocs.size() * sizeof(SourceLocation))
+ return new (C, DC,
+ additionalSizeToAlloc<SourceLocation>(IdentifierLocs.size()))
ImportDecl(DC, StartLoc, Imported, IdentifierLocs);
}
@@ -4066,16 +4185,15 @@ ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
Module *Imported,
SourceLocation EndLoc) {
- ImportDecl *Import =
- new (C, DC, sizeof(SourceLocation)) ImportDecl(DC, StartLoc,
- Imported, EndLoc);
+ ImportDecl *Import = new (C, DC, additionalSizeToAlloc<SourceLocation>(1))
+ ImportDecl(DC, StartLoc, Imported, EndLoc);
Import->setImplicit();
return Import;
}
ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumLocations) {
- return new (C, ID, NumLocations * sizeof(SourceLocation))
+ return new (C, ID, additionalSizeToAlloc<SourceLocation>(NumLocations))
ImportDecl(EmptyShell());
}
@@ -4083,16 +4201,14 @@ ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
if (!ImportedAndComplete.getInt())
return None;
- const SourceLocation *StoredLocs
- = reinterpret_cast<const SourceLocation *>(this + 1);
+ const auto *StoredLocs = getTrailingObjects<SourceLocation>();
return llvm::makeArrayRef(StoredLocs,
getNumModuleIdentifiers(getImportedModule()));
}
SourceRange ImportDecl::getSourceRange() const {
if (!ImportedAndComplete.getInt())
- return SourceRange(getLocation(),
- *reinterpret_cast<const SourceLocation *>(this + 1));
-
+ return SourceRange(getLocation(), *getTrailingObjects<SourceLocation>());
+
return SourceRange(getLocation(), getIdentifierLocs().back());
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
index 4fcec53..72587e3 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
@@ -45,10 +45,19 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const {
getASTContext().getExternalSource()->updateOutOfDateIdentifier(II);
}
+#define DECL(DERIVED, BASE) \
+ static_assert(Decl::DeclObjAlignment >= \
+ llvm::AlignOf<DERIVED##Decl>::Alignment, \
+ "Alignment sufficient after objects prepended to " #DERIVED);
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+
void *Decl::operator new(std::size_t Size, const ASTContext &Context,
unsigned ID, std::size_t Extra) {
// Allocate an extra 8 bytes worth of storage, which ensures that the
- // resulting pointer will still be 8-byte aligned.
+ // resulting pointer will still be 8-byte aligned.
+ static_assert(sizeof(unsigned) * 2 >= DeclObjAlignment,
+ "Decl won't be misaligned");
void *Start = Context.Allocate(Size + Extra + 8);
void *Result = (char*)Start + 8;
@@ -69,7 +78,13 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
// With local visibility enabled, we track the owning module even for local
// declarations.
if (Ctx.getLangOpts().ModulesLocalVisibility) {
- void *Buffer = ::operator new(sizeof(Module *) + Size + Extra, Ctx);
+ // Ensure required alignment of the resulting object by adding extra
+ // padding at the start if required.
+ size_t ExtraAlign =
+ llvm::OffsetToAlignment(sizeof(Module *), DeclObjAlignment);
+ char *Buffer = reinterpret_cast<char *>(
+ ::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx));
+ Buffer += ExtraAlign;
return new (Buffer) Module*(nullptr) + 1;
}
return ::operator new(Size + Extra, Ctx);
@@ -251,6 +266,18 @@ void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
}
}
+bool Decl::isLexicallyWithinFunctionOrMethod() const {
+ const DeclContext *LDC = getLexicalDeclContext();
+ while (true) {
+ if (LDC->isFunctionOrMethod())
+ return true;
+ if (!isa<TagDecl>(LDC))
+ return false;
+ LDC = LDC->getLexicalParent();
+ }
+ return false;
+}
+
bool Decl::isInAnonymousNamespace() const {
const DeclContext *DC = getDeclContext();
do {
@@ -542,7 +569,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Var:
case ImplicitParam:
case ParmVar:
- case NonTypeTemplateParm:
case ObjCMethod:
case ObjCProperty:
case MSProperty:
@@ -552,6 +578,12 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case IndirectField:
return IDNS_Ordinary | IDNS_Member;
+ case NonTypeTemplateParm:
+ // Non-type template parameters are not found by lookups that ignore
+ // non-types, but they are found by redeclaration lookups for tag types,
+ // so we include them in the tag namespace.
+ return IDNS_Ordinary | IDNS_Tag;
+
case ObjCCompatibleAlias:
case ObjCInterface:
return IDNS_Ordinary | IDNS_Type;
@@ -612,6 +644,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ExternCContext:
case UsingDirective:
+ case BuiltinTemplate:
case ClassTemplateSpecialization:
case ClassTemplatePartialSpecialization:
case ClassScopeFunctionSpecialization:
@@ -1044,14 +1077,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
// Load the external declarations, if any.
SmallVector<Decl*, 64> Decls;
ExternalLexicalStorage = false;
- switch (Source->FindExternalLexicalDecls(this, Decls)) {
- case ELR_Success:
- break;
-
- case ELR_Failure:
- case ELR_AlreadyLoaded:
- return false;
- }
+ Source->FindExternalLexicalDecls(this, Decls);
if (Decls.empty())
return false;
@@ -1189,13 +1215,16 @@ void DeclContext::removeDecl(Decl *D) {
// Remove only decls that have a name
if (!ND->getDeclName()) return;
- StoredDeclsMap *Map = getPrimaryContext()->LookupPtr;
- if (!Map) return;
-
- StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
- assert(Pos != Map->end() && "no lookup entry for decl");
- if (Pos->second.getAsVector() || Pos->second.getAsDecl() == ND)
- Pos->second.remove(ND);
+ auto *DC = this;
+ do {
+ StoredDeclsMap *Map = DC->getPrimaryContext()->LookupPtr;
+ if (Map) {
+ StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
+ assert(Pos != Map->end() && "no lookup entry for decl");
+ if (Pos->second.getAsVector() || Pos->second.getAsDecl() == ND)
+ Pos->second.remove(ND);
+ }
+ } while (DC->isTransparentContext() && (DC = DC->getParent()));
}
}
@@ -1213,7 +1242,7 @@ void DeclContext::addHiddenDecl(Decl *D) {
}
// Notify a C++ record declaration that we've added a member, so it can
- // update it's class-specific state.
+ // update its class-specific state.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
Record->addedMember(D);
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
index d905fcf..4f24fdc 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
@@ -385,17 +385,11 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
}
}
-/// Callback function for CXXRecordDecl::forallBases that acknowledges
-/// that it saw a base class.
-static bool SawBase(const CXXRecordDecl *, void *) {
- return true;
-}
-
bool CXXRecordDecl::hasAnyDependentBases() const {
if (!isDependentContext())
return false;
- return !forallBases(SawBase, nullptr);
+ return !forallBases([](const CXXRecordDecl *) { return true; });
}
bool CXXRecordDecl::isTriviallyCopyable() const {
@@ -1224,6 +1218,10 @@ CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const {
return nullptr;
}
+MemberSpecializationInfo *CXXRecordDecl::getMemberSpecializationInfo() const {
+ return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>();
+}
+
void
CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD,
TemplateSpecializationKind TSK) {
@@ -1234,6 +1232,14 @@ CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD,
= new (getASTContext()) MemberSpecializationInfo(RD, TSK);
}
+ClassTemplateDecl *CXXRecordDecl::getDescribedClassTemplate() const {
+ return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl *>();
+}
+
+void CXXRecordDecl::setDescribedClassTemplate(ClassTemplateDecl *Template) {
+ TemplateOrInstantiation = Template;
+}
+
TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{
if (const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(this))
@@ -1681,8 +1687,8 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices)
{
- VarDecl **MyIndices = reinterpret_cast<VarDecl **> (this + 1);
- memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *));
+ std::uninitialized_copy(Indices, Indices + NumIndices,
+ getTrailingObjects<VarDecl *>());
}
CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context,
@@ -1692,8 +1698,7 @@ CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context,
SourceLocation R,
VarDecl **Indices,
unsigned NumIndices) {
- void *Mem = Context.Allocate(sizeof(CXXCtorInitializer) +
- sizeof(VarDecl *) * NumIndices,
+ void *Mem = Context.Allocate(totalSizeToAlloc<VarDecl *>(NumIndices),
llvm::alignOf<CXXCtorInitializer>());
return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R,
Indices, NumIndices);
@@ -2023,6 +2028,22 @@ NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
SourceLocation(), nullptr, nullptr);
}
+NamespaceDecl *NamespaceDecl::getOriginalNamespace() {
+ if (isFirstDecl())
+ return this;
+
+ return AnonOrFirstNamespaceAndInline.getPointer();
+}
+
+const NamespaceDecl *NamespaceDecl::getOriginalNamespace() const {
+ if (isFirstDecl())
+ return this;
+
+ return AnonOrFirstNamespaceAndInline.getPointer();
+}
+
+bool NamespaceDecl::isOriginalNamespace() const { return isFirstDecl(); }
+
NamespaceDecl *NamespaceDecl::getNextRedeclarationImpl() {
return getNextRedeclaration();
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
index a996cab..121403b 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp
@@ -46,7 +46,9 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
}
#endif
- std::size_t Extra = FriendTypeTPLists.size() * sizeof(TemplateParameterList*);
+ std::size_t Extra =
+ FriendDecl::additionalSizeToAlloc<TemplateParameterList *>(
+ FriendTypeTPLists.size());
FriendDecl *FD = new (C, DC, Extra) FriendDecl(DC, L, Friend, FriendL,
FriendTypeTPLists);
cast<CXXRecordDecl>(DC)->pushFriendDecl(FD);
@@ -55,7 +57,8 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned FriendTypeNumTPLists) {
- std::size_t Extra = FriendTypeNumTPLists * sizeof(TemplateParameterList*);
+ std::size_t Extra =
+ additionalSizeToAlloc<TemplateParameterList *>(FriendTypeNumTPLists);
return new (C, ID, Extra) FriendDecl(EmptyShell(), FriendTypeNumTPLists);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp
index 512837f..f162e6d 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclGroup.cpp
@@ -18,10 +18,8 @@
using namespace clang;
DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
- static_assert(sizeof(DeclGroup) % llvm::AlignOf<void *>::Alignment == 0,
- "Trailing data is unaligned!");
assert(NumDecls > 1 && "Invalid DeclGroup");
- unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls;
+ unsigned Size = totalSizeToAlloc<Decl *>(NumDecls);
void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment);
new (Mem) DeclGroup(NumDecls, Decls);
return static_cast<DeclGroup*>(Mem);
@@ -30,5 +28,6 @@ DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
DeclGroup::DeclGroup(unsigned numdecls, Decl** decls) : NumDecls(numdecls) {
assert(numdecls > 0);
assert(decls);
- memcpy(this+1, decls, numdecls * sizeof(*decls));
+ std::uninitialized_copy(decls, decls + numdecls,
+ getTrailingObjects<Decl *>());
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
index 280c412..050a0f5 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp
@@ -161,6 +161,15 @@ ObjCPropertyDecl::findPropertyDecl(const DeclContext *DC,
return nullptr;
}
+ // If context is class, then lookup property in its extensions.
+ // This comes before property is looked up in primary class.
+ if (auto *IDecl = dyn_cast<ObjCInterfaceDecl>(DC)) {
+ for (const auto *Ext : IDecl->known_extensions())
+ if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(Ext,
+ propertyID))
+ return PD;
+ }
+
DeclContext::lookup_result R = DC->lookup(propertyID);
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
++I)
@@ -190,6 +199,15 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
if (Def->isHidden())
return nullptr;
}
+
+ // Search the extensions of a class first; they override what's in
+ // the class itself.
+ if (const auto *ClassDecl = dyn_cast<ObjCInterfaceDecl>(this)) {
+ for (const auto *Ext : ClassDecl->visible_extensions()) {
+ if (auto *P = Ext->FindPropertyDeclaration(PropertyId))
+ return P;
+ }
+ }
if (ObjCPropertyDecl *PD =
ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(this), PropertyId))
@@ -207,7 +225,7 @@ ObjCPropertyDecl *ObjCContainerDecl::FindPropertyDeclaration(
}
case Decl::ObjCInterface: {
const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(this);
- // Look through categories (but not extensions).
+ // Look through categories (but not extensions; they were handled above).
for (const auto *Cat : OID->visible_categories()) {
if (!Cat->IsClassExtension())
if (ObjCPropertyDecl *P = Cat->FindPropertyDeclaration(PropertyId))
@@ -327,6 +345,13 @@ void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM,
PM[Prop->getIdentifier()] = Prop;
PO.push_back(Prop);
}
+ for (const auto *Ext : known_extensions()) {
+ const ObjCCategoryDecl *ClassExt = Ext;
+ for (auto *Prop : ClassExt->properties()) {
+ PM[Prop->getIdentifier()] = Prop;
+ PO.push_back(Prop);
+ }
+ }
for (const auto *PI : all_referenced_protocols())
PI->collectPropertiesToImplement(PM, PO);
// Note, the properties declared only in class extensions are still copied
@@ -747,6 +772,10 @@ void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C,
if (Params.empty() && SelLocs.empty())
return;
+ static_assert(llvm::AlignOf<ParmVarDecl *>::Alignment >=
+ llvm::AlignOf<SourceLocation>::Alignment,
+ "Alignment not sufficient for SourceLocation");
+
unsigned Size = sizeof(ParmVarDecl *) * NumParams +
sizeof(SourceLocation) * SelLocs.size();
ParamsAndSelLocs = C.Allocate(Size);
@@ -1182,18 +1211,47 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
if (isPropertyAccessor()) {
const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent());
- // If container is class extension, find its primary class.
- if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(Container))
- if (CatDecl->IsClassExtension())
- Container = CatDecl->getClassInterface();
-
bool IsGetter = (NumArgs == 0);
- for (const auto *I : Container->properties()) {
- Selector NextSel = IsGetter ? I->getGetterName()
- : I->getSetterName();
- if (NextSel == Sel)
- return I;
+ /// Local function that attempts to find a matching property within the
+ /// given Objective-C container.
+ auto findMatchingProperty =
+ [&](const ObjCContainerDecl *Container) -> const ObjCPropertyDecl * {
+
+ for (const auto *I : Container->properties()) {
+ Selector NextSel = IsGetter ? I->getGetterName()
+ : I->getSetterName();
+ if (NextSel == Sel)
+ return I;
+ }
+
+ return nullptr;
+ };
+
+ // Look in the container we were given.
+ if (const auto *Found = findMatchingProperty(Container))
+ return Found;
+
+ // If we're in a category or extension, look in the main class.
+ const ObjCInterfaceDecl *ClassDecl = nullptr;
+ if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
+ ClassDecl = Category->getClassInterface();
+ if (const auto *Found = findMatchingProperty(ClassDecl))
+ return Found;
+ } else {
+ // Determine whether the container is a class.
+ ClassDecl = dyn_cast<ObjCInterfaceDecl>(Container);
+ }
+
+ // If we have a class, check its visible extensions.
+ if (ClassDecl) {
+ for (const auto *Ext : ClassDecl->visible_extensions()) {
+ if (Ext == Container)
+ continue;
+
+ if (const auto *Found = findMatchingProperty(Ext))
+ return Found;
+ }
}
llvm_unreachable("Marked as a property accessor but no property found!");
@@ -1272,13 +1330,9 @@ ObjCTypeParamList *ObjCTypeParamList::create(
SourceLocation lAngleLoc,
ArrayRef<ObjCTypeParamDecl *> typeParams,
SourceLocation rAngleLoc) {
- unsigned size = sizeof(ObjCTypeParamList)
- + sizeof(ObjCTypeParamDecl *) * typeParams.size();
- static_assert(llvm::AlignOf<ObjCTypeParamList>::Alignment >=
- llvm::AlignOf<ObjCTypeParamDecl *>::Alignment,
- "type parameter list needs greater alignment");
- unsigned align = llvm::alignOf<ObjCTypeParamList>();
- void *mem = ctx.Allocate(size, align);
+ void *mem =
+ ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()),
+ llvm::alignOf<ObjCTypeParamList>());
return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp
index 5f8b42b..493e2cd 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclOpenMP.cpp
@@ -29,8 +29,9 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C,
DeclContext *DC,
SourceLocation L,
ArrayRef<Expr *> VL) {
- OMPThreadPrivateDecl *D = new (C, DC, VL.size() * sizeof(Expr *))
- OMPThreadPrivateDecl(OMPThreadPrivate, DC, L);
+ OMPThreadPrivateDecl *D =
+ new (C, DC, additionalSizeToAlloc<Expr *>(VL.size()))
+ OMPThreadPrivateDecl(OMPThreadPrivate, DC, L);
D->NumVars = VL.size();
D->setVars(VL);
return D;
@@ -39,7 +40,7 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C,
OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C,
unsigned ID,
unsigned N) {
- OMPThreadPrivateDecl *D = new (C, ID, N * sizeof(Expr *))
+ OMPThreadPrivateDecl *D = new (C, ID, additionalSizeToAlloc<Expr *>(N))
OMPThreadPrivateDecl(OMPThreadPrivate, nullptr, SourceLocation());
D->NumVars = N;
return D;
@@ -48,7 +49,6 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C,
void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) {
assert(VL.size() == NumVars &&
"Number of variables is not the same as the preallocated buffer");
- Expr **Vars = reinterpret_cast<Expr **>(this + 1);
- std::copy(VL.begin(), VL.end(), Vars);
+ std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects<Expr *>());
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
index 3202d8c..5c6002d 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
@@ -96,6 +96,7 @@ namespace {
void PrintTemplateParameters(const TemplateParameterList *Params,
const TemplateArgumentList *Args = nullptr);
void prettyPrintAttributes(Decl *D);
+ void prettyPrintPragmas(Decl *D);
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
};
}
@@ -197,12 +198,40 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
void DeclPrinter::prettyPrintAttributes(Decl *D) {
if (Policy.PolishForDeclaration)
return;
-
+
+ if (D->hasAttrs()) {
+ AttrVec &Attrs = D->getAttrs();
+ for (auto *A : Attrs) {
+ switch (A->getKind()) {
+#define ATTR(X)
+#define PRAGMA_SPELLING_ATTR(X) case attr::X:
+#include "clang/Basic/AttrList.inc"
+ break;
+ default:
+ A->printPretty(Out, Policy);
+ break;
+ }
+ }
+ }
+}
+
+void DeclPrinter::prettyPrintPragmas(Decl *D) {
+ if (Policy.PolishForDeclaration)
+ return;
+
if (D->hasAttrs()) {
AttrVec &Attrs = D->getAttrs();
- for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) {
- Attr *A = *i;
- A->printPretty(Out, Policy);
+ for (auto *A : Attrs) {
+ switch (A->getKind()) {
+#define ATTR(X)
+#define PRAGMA_SPELLING_ATTR(X) case attr::X:
+#include "clang/Basic/AttrList.inc"
+ A->printPretty(Out, Policy);
+ Indent();
+ break;
+ default:
+ break;
+ }
}
}
}
@@ -408,6 +437,10 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
}
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
+ if (!D->getDescribedFunctionTemplate() &&
+ !D->isFunctionTemplateSpecialization())
+ prettyPrintPragmas(D);
+
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
if (!Policy.SuppressSpecifiers) {
@@ -416,7 +449,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
case SC_Extern: Out << "extern "; break;
case SC_Static: Out << "static "; break;
case SC_PrivateExtern: Out << "__private_extern__ "; break;
- case SC_Auto: case SC_Register: case SC_OpenCLWorkGroupLocal:
+ case SC_Auto: case SC_Register:
llvm_unreachable("invalid for functions");
}
@@ -643,6 +676,7 @@ void DeclPrinter::VisitFriendDecl(FriendDecl *D) {
}
void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
+ // FIXME: add printing of pragma attributes if required.
if (!Policy.SuppressSpecifiers && D->isMutable())
Out << "mutable ";
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
@@ -672,6 +706,7 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
}
void DeclPrinter::VisitVarDecl(VarDecl *D) {
+ prettyPrintPragmas(D);
if (!Policy.SuppressSpecifiers) {
StorageClass SC = D->getStorageClass();
if (SC != SC_None)
@@ -779,6 +814,7 @@ void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
}
void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
+ // FIXME: add printing of pragma attributes if required.
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
Out << "__module_private__ ";
Out << D->getKindName();
@@ -914,11 +950,13 @@ void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
if (PrintInstantiation) {
TemplateParameterList *Params = D->getTemplateParameters();
for (auto *I : D->specializations()) {
+ prettyPrintPragmas(I);
PrintTemplateParameters(Params, I->getTemplateSpecializationArgs());
Visit(I);
}
}
+ prettyPrintPragmas(D->getTemplatedDecl());
return VisitRedeclarableTemplateDecl(D);
}
@@ -1088,7 +1126,7 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
}
if (SID)
- Out << " : " << OID->getSuperClass()->getName();
+ Out << " : " << QualType(OID->getSuperClassType(), 0).getAsString(Policy);
// Protocols?
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
@@ -1299,7 +1337,7 @@ void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
if (!D->isAccessDeclaration())
Out << "using ";
D->getQualifier()->print(Out, Policy);
- Out << D->getName();
+ Out << D->getDeclName();
}
void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
index cde497b..de3ebd2 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/STLExtras.h"
#include <memory>
@@ -29,10 +30,10 @@ using namespace clang;
TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- NamedDecl **Params, unsigned NumParams,
+ ArrayRef<NamedDecl *> Params,
SourceLocation RAngleLoc)
: TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
- NumParams(NumParams), ContainsUnexpandedParameterPack(false) {
+ NumParams(Params.size()), ContainsUnexpandedParameterPack(false) {
assert(this->NumParams == NumParams && "Too many template parameters");
for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
NamedDecl *P = Params[Idx];
@@ -53,17 +54,13 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
}
}
-TemplateParameterList *
-TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
- SourceLocation LAngleLoc, NamedDecl **Params,
- unsigned NumParams, SourceLocation RAngleLoc) {
- unsigned Size = sizeof(TemplateParameterList)
- + sizeof(NamedDecl *) * NumParams;
- unsigned Align = std::max(llvm::alignOf<TemplateParameterList>(),
- llvm::alignOf<NamedDecl*>());
- void *Mem = C.Allocate(Size, Align);
+TemplateParameterList *TemplateParameterList::Create(
+ const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc,
+ ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc) {
+ void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *>(Params.size()),
+ llvm::alignOf<TemplateParameterList>());
return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params,
- NumParams, RAngleLoc);
+ RAngleLoc);
}
unsigned TemplateParameterList::getMinRequiredArguments() const {
@@ -240,8 +237,8 @@ static void GenerateInjectedTemplateArgs(ASTContext &Context,
}
if ((*Param)->isTemplateParameterPack())
- Arg = TemplateArgument::CreatePackCopy(Context, &Arg, 1);
-
+ Arg = TemplateArgument::CreatePackCopy(Context, Arg);
+
*Args++ = Arg;
}
}
@@ -552,10 +549,11 @@ NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC,
TemplateParmPosition(D, P), ParameterPack(true),
ExpandedParameterPack(true), NumExpandedTypes(NumExpandedTypes) {
if (ExpandedTypes && ExpandedTInfos) {
- void **TypesAndInfos = reinterpret_cast<void **>(this + 1);
+ auto TypesAndInfos =
+ getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
for (unsigned I = 0; I != NumExpandedTypes; ++I) {
- TypesAndInfos[2*I] = ExpandedTypes[I].getAsOpaquePtr();
- TypesAndInfos[2*I + 1] = ExpandedTInfos[I];
+ new (&TypesAndInfos[I].first) QualType(ExpandedTypes[I]);
+ TypesAndInfos[I].second = ExpandedTInfos[I];
}
}
}
@@ -579,10 +577,11 @@ NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
const QualType *ExpandedTypes,
unsigned NumExpandedTypes,
TypeSourceInfo **ExpandedTInfos) {
- unsigned Extra = NumExpandedTypes * 2 * sizeof(void*);
- return new (C, DC, Extra) NonTypeTemplateParmDecl(
- DC, StartLoc, IdLoc, D, P, Id, T, TInfo,
- ExpandedTypes, NumExpandedTypes, ExpandedTInfos);
+ return new (C, DC,
+ additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>(
+ NumExpandedTypes))
+ NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, TInfo,
+ ExpandedTypes, NumExpandedTypes, ExpandedTInfos);
}
NonTypeTemplateParmDecl *
@@ -595,10 +594,12 @@ NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
NonTypeTemplateParmDecl *
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumExpandedTypes) {
- unsigned Extra = NumExpandedTypes * 2 * sizeof(void*);
- return new (C, ID, Extra) NonTypeTemplateParmDecl(
- nullptr, SourceLocation(), SourceLocation(), 0, 0, nullptr, QualType(),
- nullptr, nullptr, NumExpandedTypes, nullptr);
+ return new (C, ID,
+ additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>(
+ NumExpandedTypes))
+ NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(), 0, 0,
+ nullptr, QualType(), nullptr, nullptr,
+ NumExpandedTypes, nullptr);
}
SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
@@ -628,8 +629,8 @@ TemplateTemplateParmDecl::TemplateTemplateParmDecl(
TemplateParmPosition(D, P), ParameterPack(true),
ExpandedParameterPack(true), NumExpandedParams(NumExpansions) {
if (Expansions)
- std::memcpy(reinterpret_cast<void*>(this + 1), Expansions,
- sizeof(TemplateParameterList*) * NumExpandedParams);
+ std::uninitialized_copy(Expansions, Expansions + NumExpandedParams,
+ getTrailingObjects<TemplateParameterList *>());
}
TemplateTemplateParmDecl *
@@ -647,9 +648,10 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
IdentifierInfo *Id,
TemplateParameterList *Params,
ArrayRef<TemplateParameterList *> Expansions) {
- return new (C, DC, sizeof(TemplateParameterList*) * Expansions.size())
- TemplateTemplateParmDecl(DC, L, D, P, Id, Params,
- Expansions.size(), Expansions.data());
+ return new (C, DC,
+ additionalSizeToAlloc<TemplateParameterList *>(Expansions.size()))
+ TemplateTemplateParmDecl(DC, L, D, P, Id, Params, Expansions.size(),
+ Expansions.data());
}
TemplateTemplateParmDecl *
@@ -661,7 +663,8 @@ TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
TemplateTemplateParmDecl *
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumExpansions) {
- return new (C, ID, sizeof(TemplateParameterList*) * NumExpansions)
+ return new (C, ID,
+ additionalSizeToAlloc<TemplateParameterList *>(NumExpansions))
TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr,
nullptr, NumExpansions, nullptr);
}
@@ -682,18 +685,19 @@ void TemplateTemplateParmDecl::setDefaultArgument(
//===----------------------------------------------------------------------===//
// TemplateArgumentList Implementation
//===----------------------------------------------------------------------===//
+TemplateArgumentList::TemplateArgumentList(const TemplateArgument *Args,
+ unsigned NumArgs)
+ : Arguments(getTrailingObjects<TemplateArgument>()), NumArguments(NumArgs) {
+ std::uninitialized_copy(Args, Args + NumArgs,
+ getTrailingObjects<TemplateArgument>());
+}
+
TemplateArgumentList *
TemplateArgumentList::CreateCopy(ASTContext &Context,
const TemplateArgument *Args,
unsigned NumArgs) {
- std::size_t Size = sizeof(TemplateArgumentList)
- + NumArgs * sizeof(TemplateArgument);
- void *Mem = Context.Allocate(Size);
- TemplateArgument *StoredArgs
- = reinterpret_cast<TemplateArgument *>(
- static_cast<TemplateArgumentList *>(Mem) + 1);
- std::uninitialized_copy(Args, Args + NumArgs, StoredArgs);
- return new (Mem) TemplateArgumentList(StoredArgs, NumArgs, true);
+ void *Mem = Context.Allocate(totalSizeToAlloc<TemplateArgument>(NumArgs));
+ return new (Mem) TemplateArgumentList(Args, NumArgs);
}
FunctionTemplateSpecializationInfo *
@@ -1187,3 +1191,69 @@ VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
return new (C, ID) VarTemplatePartialSpecializationDecl(C);
}
+
+static TemplateParameterList *
+createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
+ // typename T
+ auto *T = TemplateTypeParmDecl::Create(
+ C, DC, SourceLocation(), SourceLocation(), /*Depth=*/1, /*Position=*/0,
+ /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false);
+ T->setImplicit(true);
+
+ // T ...Ints
+ TypeSourceInfo *TI =
+ C.getTrivialTypeSourceInfo(QualType(T->getTypeForDecl(), 0));
+ auto *N = NonTypeTemplateParmDecl::Create(
+ C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
+ /*Id=*/nullptr, TI->getType(), /*ParameterPack=*/true, TI);
+ N->setImplicit(true);
+
+ // <typename T, T ...Ints>
+ NamedDecl *P[2] = {T, N};
+ auto *TPL = TemplateParameterList::Create(
+ C, SourceLocation(), SourceLocation(), P, SourceLocation());
+
+ // template <typename T, ...Ints> class IntSeq
+ auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create(
+ C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0,
+ /*ParameterPack=*/false, /*Id=*/nullptr, TPL);
+ TemplateTemplateParm->setImplicit(true);
+
+ // typename T
+ auto *TemplateTypeParm = TemplateTypeParmDecl::Create(
+ C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
+ /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false);
+ TemplateTypeParm->setImplicit(true);
+
+ // T N
+ TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo(
+ QualType(TemplateTypeParm->getTypeForDecl(), 0));
+ auto *NonTypeTemplateParm = NonTypeTemplateParmDecl::Create(
+ C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/2,
+ /*Id=*/nullptr, TInfo->getType(), /*ParameterPack=*/false, TInfo);
+ NamedDecl *Params[] = {TemplateTemplateParm, TemplateTypeParm,
+ NonTypeTemplateParm};
+
+ // template <template <typename T, T ...Ints> class IntSeq, typename T, T N>
+ return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
+ Params, SourceLocation());
+}
+
+static TemplateParameterList *createBuiltinTemplateParameterList(
+ const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) {
+ switch (BTK) {
+ case BTK__make_integer_seq:
+ return createMakeIntegerSeqParameterList(C, DC);
+ }
+
+ llvm_unreachable("unhandled BuiltinTemplateKind!");
+}
+
+void BuiltinTemplateDecl::anchor() {}
+
+BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
+ DeclarationName Name,
+ BuiltinTemplateKind BTK)
+ : TemplateDecl(BuiltinTemplate, DC, SourceLocation(), Name,
+ createBuiltinTemplateParameterList(C, DC, BTK)),
+ BTK(BTK) {}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
index b7c2877..b2f2727 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp
@@ -182,7 +182,7 @@ raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
}
case DeclarationName::CXXLiteralOperatorName:
- return OS << "operator \"\" " << N.getCXXLiteralIdentifier()->getName();
+ return OS << "operator\"\"" << N.getCXXLiteralIdentifier()->getName();
case DeclarationName::CXXConversionFunctionName: {
OS << "operator ";
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
index 2e066b2..52f34df 100644
--- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
@@ -331,7 +331,8 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
D(D), Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) {
DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0;
if (QualifierLoc) {
- getInternalQualifierLoc() = QualifierLoc;
+ new (getTrailingObjects<NestedNameSpecifierLoc>())
+ NestedNameSpecifierLoc(QualifierLoc);
auto *NNS = QualifierLoc.getNestedNameSpecifier();
if (NNS->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
@@ -340,7 +341,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
}
DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0;
if (FoundD)
- getInternalFoundDecl() = FoundD;
+ *getTrailingObjects<NamedDecl *>() = FoundD;
DeclRefExprBits.HasTemplateKWAndArgsInfo
= (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0;
DeclRefExprBits.RefersToEnclosingVariableOrCapture =
@@ -349,15 +350,15 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
bool Dependent = false;
bool InstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
- getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs,
- Dependent,
- InstantiationDependent,
- ContainsUnexpandedParameterPack);
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(),
+ Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
assert(!Dependent && "built a DeclRefExpr with dependent template args");
ExprBits.InstantiationDependent |= InstantiationDependent;
ExprBits.ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
} else if (TemplateKWLoc.isValid()) {
- getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc);
}
DeclRefExprBits.HadMultipleCandidates = 0;
@@ -394,15 +395,13 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
if (D == FoundD)
FoundD = nullptr;
- std::size_t Size = sizeof(DeclRefExpr);
- if (QualifierLoc)
- Size += sizeof(NestedNameSpecifierLoc);
- if (FoundD)
- Size += sizeof(NamedDecl *);
- if (TemplateArgs)
- Size += ASTTemplateKWAndArgsInfo::sizeFor(TemplateArgs->size());
- else if (TemplateKWLoc.isValid())
- Size += ASTTemplateKWAndArgsInfo::sizeFor(0);
+ bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
+ std::size_t Size =
+ totalSizeToAlloc<NestedNameSpecifierLoc, NamedDecl *,
+ ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ QualifierLoc ? 1 : 0, FoundD ? 1 : 0,
+ HasTemplateKWAndArgsInfo ? 1 : 0,
+ TemplateArgs ? TemplateArgs->size() : 0);
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D,
@@ -415,14 +414,12 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context,
bool HasFoundDecl,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) {
- std::size_t Size = sizeof(DeclRefExpr);
- if (HasQualifier)
- Size += sizeof(NestedNameSpecifierLoc);
- if (HasFoundDecl)
- Size += sizeof(NamedDecl *);
- if (HasTemplateKWAndArgsInfo)
- Size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs);
-
+ assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
+ std::size_t Size =
+ totalSizeToAlloc<NestedNameSpecifierLoc, NamedDecl *,
+ ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasQualifier ? 1 : 0, HasFoundDecl ? 1 : 0, HasTemplateKWAndArgsInfo,
+ NumTemplateArgs);
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
return new (Mem) DeclRefExpr(EmptyShell());
}
@@ -490,7 +487,6 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
else
MC->mangleName(ND, Out);
- Out.flush();
if (!Buffer.empty() && Buffer.front() == '\01')
return Buffer.substr(1);
return Buffer.str();
@@ -652,7 +648,6 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
Out << Proto;
- Out.flush();
return Name.str().str();
}
if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(CurrentDecl)) {
@@ -684,7 +679,6 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
MD->getSelector().print(Out);
Out << ']';
- Out.flush();
return Name.str().str();
}
if (isa<TranslationUnitDecl>(CurrentDecl) && IT == PrettyFunction) {
@@ -1002,15 +996,33 @@ void StringLiteral::setString(const ASTContext &C, StringRef Str,
/// can have escape sequences in them in addition to the usual trigraph and
/// escaped newline business. This routine handles this complexity.
///
-SourceLocation StringLiteral::
-getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
- const LangOptions &Features, const TargetInfo &Target) const {
+/// The *StartToken sets the first token to be searched in this function and
+/// the *StartTokenByteOffset is the byte offset of the first token. Before
+/// returning, it updates the *StartToken to the TokNo of the token being found
+/// and sets *StartTokenByteOffset to the byte offset of the token in the
+/// string.
+/// Using these two parameters can reduce the time complexity from O(n^2) to
+/// O(n) if one wants to get the location of byte for all the tokens in a
+/// string.
+///
+SourceLocation
+StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
+ const LangOptions &Features,
+ const TargetInfo &Target, unsigned *StartToken,
+ unsigned *StartTokenByteOffset) const {
assert((Kind == StringLiteral::Ascii || Kind == StringLiteral::UTF8) &&
"Only narrow string literals are currently supported");
// Loop over all of the tokens in this string until we find the one that
// contains the byte we're looking for.
unsigned TokNo = 0;
+ unsigned StringOffset = 0;
+ if (StartToken)
+ TokNo = *StartToken;
+ if (StartTokenByteOffset) {
+ StringOffset = *StartTokenByteOffset;
+ ByteNo -= StringOffset;
+ }
while (1) {
assert(TokNo < getNumConcatenated() && "Invalid byte number!");
SourceLocation StrTokLoc = getStrTokenLoc(TokNo);
@@ -1019,14 +1031,20 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
// the string literal, not the identifier for the macro it is potentially
// expanded through.
SourceLocation StrTokSpellingLoc = SM.getSpellingLoc(StrTokLoc);
-
+
// Re-lex the token to get its length and original spelling.
- std::pair<FileID, unsigned> LocInfo =SM.getDecomposedLoc(StrTokSpellingLoc);
+ std::pair<FileID, unsigned> LocInfo =
+ SM.getDecomposedLoc(StrTokSpellingLoc);
bool Invalid = false;
StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
- if (Invalid)
+ if (Invalid) {
+ if (StartTokenByteOffset != nullptr)
+ *StartTokenByteOffset = StringOffset;
+ if (StartToken != nullptr)
+ *StartToken = TokNo;
return StrTokSpellingLoc;
-
+ }
+
const char *StrData = Buffer.data()+LocInfo.second;
// Create a lexer starting at the beginning of this token.
@@ -1042,14 +1060,19 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
// If the byte is in this token, return the location of the byte.
if (ByteNo < TokNumBytes ||
(ByteNo == TokNumBytes && TokNo == getNumConcatenated() - 1)) {
- unsigned Offset = SLP.getOffsetOfStringByte(TheTok, ByteNo);
-
+ unsigned Offset = SLP.getOffsetOfStringByte(TheTok, ByteNo);
+
// Now that we know the offset of the token in the spelling, use the
// preprocessor to get the offset in the original source.
+ if (StartTokenByteOffset != nullptr)
+ *StartTokenByteOffset = StringOffset;
+ if (StartToken != nullptr)
+ *StartToken = TokNo;
return Lexer::AdvanceToTokenCharacter(StrTokLoc, Offset, SM, Features);
}
-
+
// Move to the next string token.
+ StringOffset += TokNumBytes;
++TokNo;
ByteNo -= TokNumBytes;
}
@@ -1074,6 +1097,7 @@ StringRef UnaryOperator::getOpcodeStr(Opcode Op) {
case UO_Real: return "__real";
case UO_Imag: return "__imag";
case UO_Extension: return "__extension__";
+ case UO_Coawait: return "co_await";
}
llvm_unreachable("Unknown unary operator");
}
@@ -1090,6 +1114,7 @@ UnaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix) {
case OO_Minus: return UO_Minus;
case OO_Tilde: return UO_Not;
case OO_Exclaim: return UO_LNot;
+ case OO_Coawait: return UO_Coawait;
}
}
@@ -1103,6 +1128,7 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) {
case UO_Minus: return OO_Minus;
case UO_Not: return OO_Tilde;
case UO_LNot: return OO_Exclaim;
+ case UO_Coawait: return OO_Coawait;
default: return OO_None;
}
}
@@ -1288,9 +1314,8 @@ OffsetOfExpr *OffsetOfExpr::Create(const ASTContext &C, QualType type,
ArrayRef<OffsetOfNode> comps,
ArrayRef<Expr*> exprs,
SourceLocation RParenLoc) {
- void *Mem = C.Allocate(sizeof(OffsetOfExpr) +
- sizeof(OffsetOfNode) * comps.size() +
- sizeof(Expr*) * exprs.size());
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<OffsetOfNode, Expr *>(comps.size(), exprs.size()));
return new (Mem) OffsetOfExpr(C, type, OperatorLoc, tsi, comps, exprs,
RParenLoc);
@@ -1298,9 +1323,8 @@ OffsetOfExpr *OffsetOfExpr::Create(const ASTContext &C, QualType type,
OffsetOfExpr *OffsetOfExpr::CreateEmpty(const ASTContext &C,
unsigned numComps, unsigned numExprs) {
- void *Mem = C.Allocate(sizeof(OffsetOfExpr) +
- sizeof(OffsetOfNode) * numComps +
- sizeof(Expr*) * numExprs);
+ void *Mem =
+ C.Allocate(totalSizeToAlloc<OffsetOfNode, Expr *>(numComps, numExprs));
return new (Mem) OffsetOfExpr(numComps, numExprs);
}
@@ -1330,7 +1354,7 @@ OffsetOfExpr::OffsetOfExpr(const ASTContext &C, QualType type,
}
}
-IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const {
+IdentifierInfo *OffsetOfNode::getFieldName() const {
assert(getKind() == Field || getKind() == Identifier);
if (getKind() == Field)
return getField()->getIdentifier();
@@ -1382,18 +1406,17 @@ MemberExpr *MemberExpr::Create(
ValueDecl *memberdecl, DeclAccessPair founddecl,
DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs,
QualType ty, ExprValueKind vk, ExprObjectKind ok) {
- std::size_t Size = sizeof(MemberExpr);
bool hasQualOrFound = (QualifierLoc ||
founddecl.getDecl() != memberdecl ||
founddecl.getAccess() != memberdecl->getAccess());
- if (hasQualOrFound)
- Size += sizeof(MemberNameQualifier);
- if (targs)
- Size += ASTTemplateKWAndArgsInfo::sizeFor(targs->size());
- else if (TemplateKWLoc.isValid())
- Size += ASTTemplateKWAndArgsInfo::sizeFor(0);
+ bool HasTemplateKWAndArgsInfo = targs || TemplateKWLoc.isValid();
+ std::size_t Size =
+ totalSizeToAlloc<MemberExprNameQualifier, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(hasQualOrFound ? 1 : 0,
+ HasTemplateKWAndArgsInfo ? 1 : 0,
+ targs ? targs->size() : 0);
void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>());
MemberExpr *E = new (Mem)
@@ -1412,7 +1435,8 @@ MemberExpr *MemberExpr::Create(
E->HasQualifierOrFoundDecl = true;
- MemberNameQualifier *NQ = E->getMemberQualifier();
+ MemberExprNameQualifier *NQ =
+ E->getTrailingObjects<MemberExprNameQualifier>();
NQ->QualifierLoc = QualifierLoc;
NQ->FoundDecl = founddecl;
}
@@ -1423,14 +1447,14 @@ MemberExpr *MemberExpr::Create(
bool Dependent = false;
bool InstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
- E->getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *targs,
- Dependent,
- InstantiationDependent,
- ContainsUnexpandedParameterPack);
+ E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc, *targs, E->getTrailingObjects<TemplateArgumentLoc>(),
+ Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
if (InstantiationDependent)
E->setInstantiationDependent(true);
} else if (TemplateKWLoc.isValid()) {
- E->getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
+ E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc);
}
return E;
@@ -1529,6 +1553,7 @@ bool CastExpr::CastConsistency() const {
case CK_ToVoid:
case CK_VectorSplat:
case CK_IntegralCast:
+ case CK_BooleanToSignedIntegral:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
case CK_FloatingCast:
@@ -1622,6 +1647,8 @@ const char *CastExpr::getCastKindName() const {
return "VectorSplat";
case CK_IntegralCast:
return "IntegralCast";
+ case CK_BooleanToSignedIntegral:
+ return "BooleanToSignedIntegral";
case CK_IntegralToBoolean:
return "IntegralToBoolean";
case CK_IntegralToFloating:
@@ -1719,9 +1746,9 @@ Expr *CastExpr::getSubExprAsWritten() {
CXXBaseSpecifier **CastExpr::path_buffer() {
switch (getStmtClass()) {
#define ABSTRACT_STMT(x)
-#define CASTEXPR(Type, Base) \
- case Stmt::Type##Class: \
- return reinterpret_cast<CXXBaseSpecifier**>(static_cast<Type*>(this)+1);
+#define CASTEXPR(Type, Base) \
+ case Stmt::Type##Class: \
+ return static_cast<Type *>(this)->getTrailingObjects<CXXBaseSpecifier *>();
#define STMT(Type, Base)
#include "clang/AST/StmtNodes.inc"
default:
@@ -1729,28 +1756,23 @@ CXXBaseSpecifier **CastExpr::path_buffer() {
}
}
-void CastExpr::setCastPath(const CXXCastPath &Path) {
- assert(Path.size() == path_size());
- memcpy(path_buffer(), Path.data(), Path.size() * sizeof(CXXBaseSpecifier*));
-}
-
ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T,
CastKind Kind, Expr *Operand,
const CXXCastPath *BasePath,
ExprValueKind VK) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer =
- C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
ImplicitCastExpr *E =
new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK);
- if (PathSize) E->setCastPath(*BasePath);
+ if (PathSize)
+ std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
+ E->getTrailingObjects<CXXBaseSpecifier *>());
return E;
}
ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer =
- C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize);
}
@@ -1761,18 +1783,18 @@ CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T,
TypeSourceInfo *WrittenTy,
SourceLocation L, SourceLocation R) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer =
- C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
CStyleCastExpr *E =
new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, R);
- if (PathSize) E->setCastPath(*BasePath);
+ if (PathSize)
+ std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
+ E->getTrailingObjects<CXXBaseSpecifier *>());
return E;
}
CStyleCastExpr *CStyleCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer =
- C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize);
}
@@ -2045,6 +2067,9 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
case UO_LNot:
case UO_Deref:
break;
+ case UO_Coawait:
+ // This is just the 'operator co_await' call inside the guts of a
+ // dependent co_await call.
case UO_PostInc:
case UO_PostDec:
case UO_PreInc:
@@ -2880,7 +2905,10 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
return cast<CXXDefaultInitExpr>(this)->getExpr()
->isConstantInitializer(Ctx, false, Culprit);
}
- if (isEvaluatable(Ctx))
+ // Allow certain forms of UB in constant initializers: signed integer
+ // overflow and floating-point division by zero. We'll give a warning on
+ // these, but they're common enough that we have to accept them.
+ if (isEvaluatable(Ctx, SE_AllowUndefinedBehavior))
return true;
if (Culprit)
*Culprit = this;
@@ -2993,6 +3021,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
return true;
case MSPropertyRefExprClass:
+ case MSPropertySubscriptExprClass:
case CompoundAssignOperatorClass:
case VAArgExprClass:
case AtomicExprClass:
@@ -3000,6 +3029,8 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case CXXNewExprClass:
case CXXDeleteExprClass:
case ExprWithCleanupsClass:
+ case CoawaitExprClass:
+ case CoyieldExprClass:
// These always have a side-effect.
return true;
@@ -3012,6 +3043,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ParenExprClass:
case ArraySubscriptExprClass:
+ case OMPArraySectionExprClass:
case MemberExprClass:
case ConditionalOperatorClass:
case BinaryConditionalOperatorClass:
@@ -3246,9 +3278,20 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
// Check that it is a cast to void*.
if (const PointerType *PT = CE->getType()->getAs<PointerType>()) {
QualType Pointee = PT->getPointeeType();
- if (!Pointee.hasQualifiers() &&
- Pointee->isVoidType() && // to void*
- CE->getSubExpr()->getType()->isIntegerType()) // from int.
+ Qualifiers Q = Pointee.getQualifiers();
+ // In OpenCL v2.0 generic address space acts as a placeholder
+ // and should be ignored.
+ bool IsASValid = true;
+ if (Ctx.getLangOpts().OpenCLVersion >= 200) {
+ if (Pointee.getAddressSpace() == LangAS::opencl_generic)
+ Q.removeAddressSpace();
+ else
+ IsASValid = false;
+ }
+
+ if (IsASValid && !Q.hasQualifiers() &&
+ Pointee->isVoidType() && // to void*
+ CE->getSubExpr()->getType()->isIntegerType()) // from int.
return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
}
}
@@ -3429,6 +3472,18 @@ bool Expr::refersToVectorElement() const {
return false;
}
+bool Expr::refersToGlobalRegisterVar() const {
+ const Expr *E = this->IgnoreParenImpCasts();
+
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (VD->getStorageClass() == SC_Register &&
+ VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())
+ return true;
+
+ return false;
+}
+
/// isArrow - Return true if the base expression is a pointer to vector,
/// return false if the base expression is a vector.
bool ExtVectorElementExpr::isArrow() const {
@@ -3464,7 +3519,7 @@ bool ExtVectorElementExpr::containsDuplicateElements() const {
/// getEncodedElementAccess - We encode the fields as a llvm ConstantArray.
void ExtVectorElementExpr::getEncodedElementAccess(
- SmallVectorImpl<unsigned> &Elts) const {
+ SmallVectorImpl<uint32_t> &Elts) const {
StringRef Comp = Accessor->getName();
if (Comp[0] == 's' || Comp[0] == 'S')
Comp = Comp.substr(1);
@@ -3492,285 +3547,6 @@ void ExtVectorElementExpr::getEncodedElementAccess(
}
}
-ObjCMessageExpr::ObjCMessageExpr(QualType T,
- ExprValueKind VK,
- SourceLocation LBracLoc,
- SourceLocation SuperLoc,
- bool IsInstanceSuper,
- QualType SuperType,
- Selector Sel,
- ArrayRef<SourceLocation> SelLocs,
- SelectorLocationsKind SelLocsK,
- ObjCMethodDecl *Method,
- ArrayRef<Expr *> Args,
- SourceLocation RBracLoc,
- bool isImplicit)
- : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary,
- /*TypeDependent=*/false, /*ValueDependent=*/false,
- /*InstantiationDependent=*/false,
- /*ContainsUnexpandedParameterPack=*/false),
- SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
- : Sel.getAsOpaquePtr())),
- Kind(IsInstanceSuper? SuperInstance : SuperClass),
- HasMethod(Method != nullptr), IsDelegateInitCall(false),
- IsImplicit(isImplicit), SuperLoc(SuperLoc), LBracLoc(LBracLoc),
- RBracLoc(RBracLoc)
-{
- initArgsAndSelLocs(Args, SelLocs, SelLocsK);
- setReceiverPointer(SuperType.getAsOpaquePtr());
-}
-
-ObjCMessageExpr::ObjCMessageExpr(QualType T,
- ExprValueKind VK,
- SourceLocation LBracLoc,
- TypeSourceInfo *Receiver,
- Selector Sel,
- ArrayRef<SourceLocation> SelLocs,
- SelectorLocationsKind SelLocsK,
- ObjCMethodDecl *Method,
- ArrayRef<Expr *> Args,
- SourceLocation RBracLoc,
- bool isImplicit)
- : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(),
- T->isDependentType(), T->isInstantiationDependentType(),
- T->containsUnexpandedParameterPack()),
- SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
- : Sel.getAsOpaquePtr())),
- Kind(Class),
- HasMethod(Method != nullptr), IsDelegateInitCall(false),
- IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
-{
- initArgsAndSelLocs(Args, SelLocs, SelLocsK);
- setReceiverPointer(Receiver);
-}
-
-ObjCMessageExpr::ObjCMessageExpr(QualType T,
- ExprValueKind VK,
- SourceLocation LBracLoc,
- Expr *Receiver,
- Selector Sel,
- ArrayRef<SourceLocation> SelLocs,
- SelectorLocationsKind SelLocsK,
- ObjCMethodDecl *Method,
- ArrayRef<Expr *> Args,
- SourceLocation RBracLoc,
- bool isImplicit)
- : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, Receiver->isTypeDependent(),
- Receiver->isTypeDependent(),
- Receiver->isInstantiationDependent(),
- Receiver->containsUnexpandedParameterPack()),
- SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
- : Sel.getAsOpaquePtr())),
- Kind(Instance),
- HasMethod(Method != nullptr), IsDelegateInitCall(false),
- IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
-{
- initArgsAndSelLocs(Args, SelLocs, SelLocsK);
- setReceiverPointer(Receiver);
-}
-
-void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args,
- ArrayRef<SourceLocation> SelLocs,
- SelectorLocationsKind SelLocsK) {
- setNumArgs(Args.size());
- Expr **MyArgs = getArgs();
- for (unsigned I = 0; I != Args.size(); ++I) {
- if (Args[I]->isTypeDependent())
- ExprBits.TypeDependent = true;
- if (Args[I]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (Args[I]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (Args[I]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
- MyArgs[I] = Args[I];
- }
-
- SelLocsKind = SelLocsK;
- if (!isImplicit()) {
- if (SelLocsK == SelLoc_NonStandard)
- std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
- }
-}
-
-ObjCMessageExpr *ObjCMessageExpr::Create(const ASTContext &Context, QualType T,
- ExprValueKind VK,
- SourceLocation LBracLoc,
- SourceLocation SuperLoc,
- bool IsInstanceSuper,
- QualType SuperType,
- Selector Sel,
- ArrayRef<SourceLocation> SelLocs,
- ObjCMethodDecl *Method,
- ArrayRef<Expr *> Args,
- SourceLocation RBracLoc,
- bool isImplicit) {
- assert((!SelLocs.empty() || isImplicit) &&
- "No selector locs for non-implicit message");
- ObjCMessageExpr *Mem;
- SelectorLocationsKind SelLocsK = SelectorLocationsKind();
- if (isImplicit)
- Mem = alloc(Context, Args.size(), 0);
- else
- Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
- return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper,
- SuperType, Sel, SelLocs, SelLocsK,
- Method, Args, RBracLoc, isImplicit);
-}
-
-ObjCMessageExpr *ObjCMessageExpr::Create(const ASTContext &Context, QualType T,
- ExprValueKind VK,
- SourceLocation LBracLoc,
- TypeSourceInfo *Receiver,
- Selector Sel,
- ArrayRef<SourceLocation> SelLocs,
- ObjCMethodDecl *Method,
- ArrayRef<Expr *> Args,
- SourceLocation RBracLoc,
- bool isImplicit) {
- assert((!SelLocs.empty() || isImplicit) &&
- "No selector locs for non-implicit message");
- ObjCMessageExpr *Mem;
- SelectorLocationsKind SelLocsK = SelectorLocationsKind();
- if (isImplicit)
- Mem = alloc(Context, Args.size(), 0);
- else
- Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
- return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel,
- SelLocs, SelLocsK, Method, Args, RBracLoc,
- isImplicit);
-}
-
-ObjCMessageExpr *ObjCMessageExpr::Create(const ASTContext &Context, QualType T,
- ExprValueKind VK,
- SourceLocation LBracLoc,
- Expr *Receiver,
- Selector Sel,
- ArrayRef<SourceLocation> SelLocs,
- ObjCMethodDecl *Method,
- ArrayRef<Expr *> Args,
- SourceLocation RBracLoc,
- bool isImplicit) {
- assert((!SelLocs.empty() || isImplicit) &&
- "No selector locs for non-implicit message");
- ObjCMessageExpr *Mem;
- SelectorLocationsKind SelLocsK = SelectorLocationsKind();
- if (isImplicit)
- Mem = alloc(Context, Args.size(), 0);
- else
- Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
- return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel,
- SelLocs, SelLocsK, Method, Args, RBracLoc,
- isImplicit);
-}
-
-ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(const ASTContext &Context,
- unsigned NumArgs,
- unsigned NumStoredSelLocs) {
- ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs);
- return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs);
-}
-
-ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C,
- ArrayRef<Expr *> Args,
- SourceLocation RBraceLoc,
- ArrayRef<SourceLocation> SelLocs,
- Selector Sel,
- SelectorLocationsKind &SelLocsK) {
- SelLocsK = hasStandardSelectorLocs(Sel, SelLocs, Args, RBraceLoc);
- unsigned NumStoredSelLocs = (SelLocsK == SelLoc_NonStandard) ? SelLocs.size()
- : 0;
- return alloc(C, Args.size(), NumStoredSelLocs);
-}
-
-ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C,
- unsigned NumArgs,
- unsigned NumStoredSelLocs) {
- unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
- NumArgs * sizeof(Expr *) + NumStoredSelLocs * sizeof(SourceLocation);
- return (ObjCMessageExpr *)C.Allocate(Size,
- llvm::AlignOf<ObjCMessageExpr>::Alignment);
-}
-
-void ObjCMessageExpr::getSelectorLocs(
- SmallVectorImpl<SourceLocation> &SelLocs) const {
- for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i)
- SelLocs.push_back(getSelectorLoc(i));
-}
-
-SourceRange ObjCMessageExpr::getReceiverRange() const {
- switch (getReceiverKind()) {
- case Instance:
- return getInstanceReceiver()->getSourceRange();
-
- case Class:
- return getClassReceiverTypeInfo()->getTypeLoc().getSourceRange();
-
- case SuperInstance:
- case SuperClass:
- return getSuperLoc();
- }
-
- llvm_unreachable("Invalid ReceiverKind!");
-}
-
-Selector ObjCMessageExpr::getSelector() const {
- if (HasMethod)
- return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod)
- ->getSelector();
- return Selector(SelectorOrMethod);
-}
-
-QualType ObjCMessageExpr::getReceiverType() const {
- switch (getReceiverKind()) {
- case Instance:
- return getInstanceReceiver()->getType();
- case Class:
- return getClassReceiver();
- case SuperInstance:
- case SuperClass:
- return getSuperType();
- }
-
- llvm_unreachable("unexpected receiver kind");
-}
-
-ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
- QualType T = getReceiverType();
-
- if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
- return Ptr->getInterfaceDecl();
-
- if (const ObjCObjectType *Ty = T->getAs<ObjCObjectType>())
- return Ty->getInterface();
-
- return nullptr;
-}
-
-QualType ObjCPropertyRefExpr::getReceiverType(const ASTContext &ctx) const {
- if (isClassReceiver())
- return ctx.getObjCInterfaceType(getClassReceiver());
-
- if (isSuperReceiver())
- return getSuperReceiverType();
-
- return getBase()->getType();
-}
-
-StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
- switch (getBridgeKind()) {
- case OBC_Bridge:
- return "__bridge";
- case OBC_BridgeTransfer:
- return "__bridge_transfer";
- case OBC_BridgeRetained:
- return "__bridge_retained";
- }
-
- llvm_unreachable("Invalid BridgeKind!");
-}
-
ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args,
QualType Type, SourceLocation BLoc,
SourceLocation RP)
@@ -3883,7 +3659,7 @@ DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty,
this->Designators = new (C) Designator[NumDesignators];
// Record the initializer itself.
- child_range Child = children();
+ child_iterator Child = child_begin();
*Child++ = Init;
// Copy the designators and their subexpressions, computing
@@ -3938,8 +3714,8 @@ DesignatedInitExpr::Create(const ASTContext &C, Designator *Designators,
ArrayRef<Expr*> IndexExprs,
SourceLocation ColonOrEqualLoc,
bool UsesColonSyntax, Expr *Init) {
- void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
- sizeof(Stmt *) * (IndexExprs.size() + 1), 8);
+ void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(IndexExprs.size() + 1),
+ llvm::alignOf<DesignatedInitExpr>());
return new (Mem) DesignatedInitExpr(C, C.VoidTy, NumDesignators, Designators,
ColonOrEqualLoc, UsesColonSyntax,
IndexExprs, Init);
@@ -3947,8 +3723,8 @@ DesignatedInitExpr::Create(const ASTContext &C, Designator *Designators,
DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(const ASTContext &C,
unsigned NumIndexExprs) {
- void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
- sizeof(Stmt *) * (NumIndexExprs + 1), 8);
+ void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(NumIndexExprs + 1),
+ llvm::alignOf<DesignatedInitExpr>());
return new (Mem) DesignatedInitExpr(NumIndexExprs + 1);
}
@@ -3990,22 +3766,19 @@ SourceLocation DesignatedInitExpr::getLocEnd() const {
Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) const {
assert(D.Kind == Designator::ArrayDesignator && "Requires array designator");
- Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1);
- return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
+ return getSubExpr(D.ArrayOrRange.Index + 1);
}
Expr *DesignatedInitExpr::getArrayRangeStart(const Designator &D) const {
assert(D.Kind == Designator::ArrayRangeDesignator &&
"Requires array range designator");
- Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1);
- return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
+ return getSubExpr(D.ArrayOrRange.Index + 1);
}
Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator &D) const {
assert(D.Kind == Designator::ArrayRangeDesignator &&
"Requires array range designator");
- Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1);
- return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 2));
+ return getSubExpr(D.ArrayOrRange.Index + 2);
}
/// \brief Replaces the designator at index @p Idx with the series
@@ -4089,9 +3862,9 @@ const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {
PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &Context,
EmptyShell sh,
unsigned numSemanticExprs) {
- void *buffer = Context.Allocate(sizeof(PseudoObjectExpr) +
- (1 + numSemanticExprs) * sizeof(Expr*),
- llvm::alignOf<PseudoObjectExpr>());
+ void *buffer =
+ Context.Allocate(totalSizeToAlloc<Expr *>(1 + numSemanticExprs),
+ llvm::alignOf<PseudoObjectExpr>());
return new(buffer) PseudoObjectExpr(sh, numSemanticExprs);
}
@@ -4118,8 +3891,7 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &C, Expr *syntax,
assert(semantics[resultIndex]->getObjectKind() == OK_Ordinary);
}
- void *buffer = C.Allocate(sizeof(PseudoObjectExpr) +
- (1 + semantics.size()) * sizeof(Expr*),
+ void *buffer = C.Allocate(totalSizeToAlloc<Expr *>(semantics.size() + 1),
llvm::alignOf<PseudoObjectExpr>());
return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics,
resultIndex);
@@ -4154,19 +3926,6 @@ PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK,
}
//===----------------------------------------------------------------------===//
-// ExprIterator.
-//===----------------------------------------------------------------------===//
-
-Expr* ExprIterator::operator[](size_t idx) { return cast<Expr>(I[idx]); }
-Expr* ExprIterator::operator*() const { return cast<Expr>(*I); }
-Expr* ExprIterator::operator->() const { return cast<Expr>(*I); }
-const Expr* ConstExprIterator::operator[](size_t idx) const {
- return cast<Expr>(I[idx]);
-}
-const Expr* ConstExprIterator::operator*() const { return cast<Expr>(*I); }
-const Expr* ConstExprIterator::operator->() const { return cast<Expr>(*I); }
-
-//===----------------------------------------------------------------------===//
// Child Iterators for iterating over subexpressions/substatements
//===----------------------------------------------------------------------===//
@@ -4179,134 +3938,11 @@ Stmt::child_range UnaryExprOrTypeTraitExpr::children() {
if (const VariableArrayType* T = dyn_cast<VariableArrayType>(
getArgumentType().getTypePtr()))
return child_range(child_iterator(T), child_iterator());
- return child_range();
+ return child_range(child_iterator(), child_iterator());
}
return child_range(&Argument.Ex, &Argument.Ex + 1);
}
-// ObjCMessageExpr
-Stmt::child_range ObjCMessageExpr::children() {
- Stmt **begin;
- if (getReceiverKind() == Instance)
- begin = reinterpret_cast<Stmt **>(this + 1);
- else
- begin = reinterpret_cast<Stmt **>(getArgs());
- return child_range(begin,
- reinterpret_cast<Stmt **>(getArgs() + getNumArgs()));
-}
-
-ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef<Expr *> Elements,
- QualType T, ObjCMethodDecl *Method,
- SourceRange SR)
- : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary,
- false, false, false, false),
- NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method)
-{
- Expr **SaveElements = getElements();
- for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
- if (Elements[I]->isTypeDependent() || Elements[I]->isValueDependent())
- ExprBits.ValueDependent = true;
- if (Elements[I]->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (Elements[I]->containsUnexpandedParameterPack())
- ExprBits.ContainsUnexpandedParameterPack = true;
-
- SaveElements[I] = Elements[I];
- }
-}
-
-ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C,
- ArrayRef<Expr *> Elements,
- QualType T, ObjCMethodDecl * Method,
- SourceRange SR) {
- void *Mem = C.Allocate(sizeof(ObjCArrayLiteral)
- + Elements.size() * sizeof(Expr *));
- return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR);
-}
-
-ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(const ASTContext &C,
- unsigned NumElements) {
-
- void *Mem = C.Allocate(sizeof(ObjCArrayLiteral)
- + NumElements * sizeof(Expr *));
- return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements);
-}
-
-ObjCDictionaryLiteral::ObjCDictionaryLiteral(
- ArrayRef<ObjCDictionaryElement> VK,
- bool HasPackExpansions,
- QualType T, ObjCMethodDecl *method,
- SourceRange SR)
- : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
- false, false),
- NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR),
- DictWithObjectsMethod(method)
-{
- KeyValuePair *KeyValues = getKeyValues();
- ExpansionData *Expansions = getExpansionData();
- for (unsigned I = 0; I < NumElements; I++) {
- if (VK[I].Key->isTypeDependent() || VK[I].Key->isValueDependent() ||
- VK[I].Value->isTypeDependent() || VK[I].Value->isValueDependent())
- ExprBits.ValueDependent = true;
- if (VK[I].Key->isInstantiationDependent() ||
- VK[I].Value->isInstantiationDependent())
- ExprBits.InstantiationDependent = true;
- if (VK[I].EllipsisLoc.isInvalid() &&
- (VK[I].Key->containsUnexpandedParameterPack() ||
- VK[I].Value->containsUnexpandedParameterPack()))
- ExprBits.ContainsUnexpandedParameterPack = true;
-
- KeyValues[I].Key = VK[I].Key;
- KeyValues[I].Value = VK[I].Value;
- if (Expansions) {
- Expansions[I].EllipsisLoc = VK[I].EllipsisLoc;
- if (VK[I].NumExpansions)
- Expansions[I].NumExpansionsPlusOne = *VK[I].NumExpansions + 1;
- else
- Expansions[I].NumExpansionsPlusOne = 0;
- }
- }
-}
-
-ObjCDictionaryLiteral *
-ObjCDictionaryLiteral::Create(const ASTContext &C,
- ArrayRef<ObjCDictionaryElement> VK,
- bool HasPackExpansions,
- QualType T, ObjCMethodDecl *method,
- SourceRange SR) {
- unsigned ExpansionsSize = 0;
- if (HasPackExpansions)
- ExpansionsSize = sizeof(ExpansionData) * VK.size();
-
- void *Mem = C.Allocate(sizeof(ObjCDictionaryLiteral) +
- sizeof(KeyValuePair) * VK.size() + ExpansionsSize);
- return new (Mem) ObjCDictionaryLiteral(VK, HasPackExpansions, T, method, SR);
-}
-
-ObjCDictionaryLiteral *
-ObjCDictionaryLiteral::CreateEmpty(const ASTContext &C, unsigned NumElements,
- bool HasPackExpansions) {
- unsigned ExpansionsSize = 0;
- if (HasPackExpansions)
- ExpansionsSize = sizeof(ExpansionData) * NumElements;
- void *Mem = C.Allocate(sizeof(ObjCDictionaryLiteral) +
- sizeof(KeyValuePair) * NumElements + ExpansionsSize);
- return new (Mem) ObjCDictionaryLiteral(EmptyShell(), NumElements,
- HasPackExpansions);
-}
-
-ObjCSubscriptRefExpr *ObjCSubscriptRefExpr::Create(const ASTContext &C,
- Expr *base,
- Expr *key, QualType T,
- ObjCMethodDecl *getMethod,
- ObjCMethodDecl *setMethod,
- SourceLocation RB) {
- void *Mem = C.Allocate(sizeof(ObjCSubscriptRefExpr));
- return new (Mem) ObjCSubscriptRefExpr(base, key, T, VK_LValue,
- OK_ObjCSubscript,
- getMethod, setMethod, RB);
-}
-
AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args,
QualType t, AtomicOp op, SourceLocation RP)
: Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary,
@@ -4373,3 +4009,29 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
}
llvm_unreachable("unknown atomic op");
}
+
+QualType OMPArraySectionExpr::getBaseOriginalType(Expr *Base) {
+ unsigned ArraySectionCount = 0;
+ while (auto *OASE = dyn_cast<OMPArraySectionExpr>(Base->IgnoreParens())) {
+ Base = OASE->getBase();
+ ++ArraySectionCount;
+ }
+ while (auto *ASE = dyn_cast<ArraySubscriptExpr>(Base->IgnoreParens())) {
+ Base = ASE->getBase();
+ ++ArraySectionCount;
+ }
+ auto OriginalTy = Base->getType();
+ if (auto *DRE = dyn_cast<DeclRefExpr>(Base))
+ if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
+ OriginalTy = PVD->getOriginalType().getNonReferenceType();
+
+ for (unsigned Cnt = 0; Cnt < ArraySectionCount; ++Cnt) {
+ if (OriginalTy->isAnyPointerType())
+ OriginalTy = OriginalTy->getPointeeType();
+ else {
+ assert (OriginalTy->isArrayType());
+ OriginalTy = OriginalTy->castAsArrayTypeUnsafe()->getElementType();
+ }
+ }
+ return OriginalTy;
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
index d6f2ce6..ea98334 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
@@ -295,8 +295,11 @@ UnresolvedLookupExpr::Create(const ASTContext &C,
{
assert(Args || TemplateKWLoc.isValid());
unsigned num_args = Args ? Args->size() : 0;
- void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) +
- ASTTemplateKWAndArgsInfo::sizeFor(num_args));
+
+ std::size_t Size =
+ totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(1,
+ num_args);
+ void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>());
return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
TemplateKWLoc, NameInfo,
ADL, /*Overload*/ true, Args,
@@ -307,11 +310,11 @@ UnresolvedLookupExpr *
UnresolvedLookupExpr::CreateEmpty(const ASTContext &C,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) {
- std::size_t size = sizeof(UnresolvedLookupExpr);
- if (HasTemplateKWAndArgsInfo)
- size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs);
-
- void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedLookupExpr>());
+ assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
+ std::size_t Size =
+ totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>());
UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
@@ -367,10 +370,9 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
bool Dependent = false;
bool InstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
- getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs,
- Dependent,
- InstantiationDependent,
- ContainsUnexpandedParameterPack);
+ getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(
+ TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc(),
+ Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
if (Dependent) {
ExprBits.TypeDependent = true;
@@ -381,7 +383,7 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
if (ContainsUnexpandedParameterPack)
ExprBits.ContainsUnexpandedParameterPack = true;
} else if (TemplateKWLoc.isValid()) {
- getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
+ getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
}
if (isTypeDependent())
@@ -432,13 +434,13 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
bool InstantiationDependent = true;
bool ContainsUnexpandedParameterPack
= ExprBits.ContainsUnexpandedParameterPack;
- getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *Args,
- Dependent,
- InstantiationDependent,
- ContainsUnexpandedParameterPack);
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>(),
+ Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
} else if (TemplateKWLoc.isValid()) {
- getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc);
}
}
@@ -449,12 +451,11 @@ DependentScopeDeclRefExpr::Create(const ASTContext &C,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args) {
assert(QualifierLoc && "should be created for dependent qualifiers");
- std::size_t size = sizeof(DependentScopeDeclRefExpr);
- if (Args)
- size += ASTTemplateKWAndArgsInfo::sizeFor(Args->size());
- else if (TemplateKWLoc.isValid())
- size += ASTTemplateKWAndArgsInfo::sizeFor(0);
- void *Mem = C.Allocate(size);
+ bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid();
+ std::size_t Size =
+ totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasTemplateKWAndArgsInfo, Args ? Args->size() : 0);
+ void *Mem = C.Allocate(Size);
return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc,
TemplateKWLoc, NameInfo, Args);
}
@@ -463,10 +464,11 @@ DependentScopeDeclRefExpr *
DependentScopeDeclRefExpr::CreateEmpty(const ASTContext &C,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) {
- std::size_t size = sizeof(DependentScopeDeclRefExpr);
- if (HasTemplateKWAndArgsInfo)
- size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs);
- void *Mem = C.Allocate(size);
+ assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
+ std::size_t Size =
+ totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ void *Mem = C.Allocate(Size);
DependentScopeDeclRefExpr *E
= new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(),
SourceLocation(),
@@ -587,19 +589,19 @@ CXXStaticCastExpr *CXXStaticCastExpr::Create(const ASTContext &C, QualType T,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(sizeof(CXXStaticCastExpr)
- + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
CXXStaticCastExpr *E =
new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
RParenLoc, AngleBrackets);
- if (PathSize) E->setCastPath(*BasePath);
+ if (PathSize)
+ std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
+ E->getTrailingObjects<CXXBaseSpecifier *>());
return E;
}
CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer =
- C.Allocate(sizeof(CXXStaticCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
}
@@ -612,19 +614,19 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::Create(const ASTContext &C, QualType T,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(sizeof(CXXDynamicCastExpr)
- + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
CXXDynamicCastExpr *E =
new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
RParenLoc, AngleBrackets);
- if (PathSize) E->setCastPath(*BasePath);
+ if (PathSize)
+ std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
+ E->getTrailingObjects<CXXBaseSpecifier *>());
return E;
}
CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
- void *Buffer =
- C.Allocate(sizeof(CXXDynamicCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize);
}
@@ -669,19 +671,19 @@ CXXReinterpretCastExpr::Create(const ASTContext &C, QualType T,
SourceLocation RParenLoc,
SourceRange AngleBrackets) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer =
- C.Allocate(sizeof(CXXReinterpretCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
CXXReinterpretCastExpr *E =
new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L,
RParenLoc, AngleBrackets);
- if (PathSize) E->setCastPath(*BasePath);
+ if (PathSize)
+ std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
+ E->getTrailingObjects<CXXBaseSpecifier *>());
return E;
}
CXXReinterpretCastExpr *
CXXReinterpretCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
- void *Buffer = C.Allocate(sizeof(CXXReinterpretCastExpr)
- + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize);
}
@@ -704,18 +706,18 @@ CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
const CXXCastPath *BasePath,
SourceLocation L, SourceLocation R) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
- void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
- + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
CXXFunctionalCastExpr *E =
new (Buffer) CXXFunctionalCastExpr(T, VK, Written, K, Op, PathSize, L, R);
- if (PathSize) E->setCastPath(*BasePath);
+ if (PathSize)
+ std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
+ E->getTrailingObjects<CXXBaseSpecifier *>());
return E;
}
CXXFunctionalCastExpr *
CXXFunctionalCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize) {
- void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
- + PathSize * sizeof(CXXBaseSpecifier*));
+ void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
}
@@ -761,14 +763,6 @@ const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const {
return cast<FunctionDecl>(getCalleeDecl())->getLiteralIdentifier();
}
-CXXDefaultArgExpr *
-CXXDefaultArgExpr::Create(const ASTContext &C, SourceLocation Loc,
- ParmVarDecl *Param, Expr *SubExpr) {
- void *Mem = C.Allocate(sizeof(CXXDefaultArgExpr) + sizeof(Stmt *));
- return new (Mem) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param,
- SubExpr);
-}
-
CXXDefaultInitExpr::CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc,
FieldDecl *Field, QualType T)
: Expr(CXXDefaultInitExprClass, T.getNonLValueExprType(C),
@@ -922,29 +916,22 @@ LambdaCaptureKind LambdaCapture::getCaptureKind() const {
return CapByCopy ? LCK_ByCopy : LCK_ByRef;
}
-LambdaExpr::LambdaExpr(QualType T,
- SourceRange IntroducerRange,
+LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc,
- ArrayRef<Capture> Captures,
- bool ExplicitParams,
- bool ExplicitResultType,
- ArrayRef<Expr *> CaptureInits,
+ ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
+ bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
ArrayRef<VarDecl *> ArrayIndexVars,
ArrayRef<unsigned> ArrayIndexStarts,
SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack)
- : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
- T->isDependentType(), T->isDependentType(), T->isDependentType(),
- ContainsUnexpandedParameterPack),
- IntroducerRange(IntroducerRange),
- CaptureDefaultLoc(CaptureDefaultLoc),
- NumCaptures(Captures.size()),
- CaptureDefault(CaptureDefault),
- ExplicitParams(ExplicitParams),
- ExplicitResultType(ExplicitResultType),
- ClosingBrace(ClosingBrace)
-{
+ : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(),
+ T->isDependentType(), T->isDependentType(),
+ ContainsUnexpandedParameterPack),
+ IntroducerRange(IntroducerRange), CaptureDefaultLoc(CaptureDefaultLoc),
+ NumCaptures(Captures.size()), CaptureDefault(CaptureDefault),
+ ExplicitParams(ExplicitParams), ExplicitResultType(ExplicitResultType),
+ ClosingBrace(ClosingBrace) {
assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments");
CXXRecordDecl *Class = getLambdaClass();
CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData();
@@ -955,8 +942,9 @@ LambdaExpr::LambdaExpr(QualType T,
const ASTContext &Context = Class->getASTContext();
Data.NumCaptures = NumCaptures;
Data.NumExplicitCaptures = 0;
- Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures);
- Capture *ToCapture = Data.Captures;
+ Data.Captures =
+ (LambdaCapture *)Context.Allocate(sizeof(LambdaCapture) * NumCaptures);
+ LambdaCapture *ToCapture = Data.Captures;
for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
if (Captures[I].isExplicit())
++Data.NumExplicitCaptures;
@@ -984,30 +972,20 @@ LambdaExpr::LambdaExpr(QualType T,
}
}
-LambdaExpr *LambdaExpr::Create(const ASTContext &Context,
- CXXRecordDecl *Class,
- SourceRange IntroducerRange,
- LambdaCaptureDefault CaptureDefault,
- SourceLocation CaptureDefaultLoc,
- ArrayRef<Capture> Captures,
- bool ExplicitParams,
- bool ExplicitResultType,
- ArrayRef<Expr *> CaptureInits,
- ArrayRef<VarDecl *> ArrayIndexVars,
- ArrayRef<unsigned> ArrayIndexStarts,
- SourceLocation ClosingBrace,
- bool ContainsUnexpandedParameterPack) {
+LambdaExpr *LambdaExpr::Create(
+ const ASTContext &Context, CXXRecordDecl *Class,
+ SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
+ bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
+ ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts,
+ SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) {
// Determine the type of the expression (i.e., the type of the
// function object we're creating).
QualType T = Context.getTypeDeclType(Class);
- unsigned Size = sizeof(LambdaExpr) + sizeof(Stmt *) * (Captures.size() + 1);
- if (!ArrayIndexVars.empty()) {
- Size += sizeof(unsigned) * (Captures.size() + 1);
- // Realign for following VarDecl array.
- Size = llvm::RoundUpToAlignment(Size, llvm::alignOf<VarDecl*>());
- Size += sizeof(VarDecl *) * ArrayIndexVars.size();
- }
+ unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>(
+ Captures.size() + 1, ArrayIndexVars.empty() ? 0 : Captures.size() + 1,
+ ArrayIndexVars.size());
void *Mem = Context.Allocate(Size);
return new (Mem) LambdaExpr(T, IntroducerRange,
CaptureDefault, CaptureDefaultLoc, Captures,
@@ -1019,10 +997,9 @@ LambdaExpr *LambdaExpr::Create(const ASTContext &Context,
LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
unsigned NumCaptures,
unsigned NumArrayIndexVars) {
- unsigned Size = sizeof(LambdaExpr) + sizeof(Stmt *) * (NumCaptures + 1);
- if (NumArrayIndexVars)
- Size += sizeof(VarDecl) * NumArrayIndexVars
- + sizeof(unsigned) * (NumCaptures + 1);
+ unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>(
+ NumCaptures + 1, NumArrayIndexVars ? NumCaptures + 1 : 0,
+ NumArrayIndexVars);
void *Mem = C.Allocate(Size);
return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0);
}
@@ -1070,15 +1047,15 @@ LambdaExpr::capture_range LambdaExpr::implicit_captures() const {
return capture_range(implicit_capture_begin(), implicit_capture_end());
}
-ArrayRef<VarDecl *>
-LambdaExpr::getCaptureInitIndexVars(capture_init_iterator Iter) const {
+ArrayRef<VarDecl *>
+LambdaExpr::getCaptureInitIndexVars(const_capture_init_iterator Iter) const {
assert(HasArrayIndexVars && "No array index-var data?");
unsigned Index = Iter - capture_init_begin();
assert(Index < getLambdaClass()->getLambdaData().NumCaptures &&
"Capture index out-of-range");
- VarDecl **IndexVars = getArrayIndexVars();
- unsigned *IndexStarts = getArrayIndexStarts();
+ VarDecl *const *IndexVars = getArrayIndexVars();
+ const unsigned *IndexStarts = getArrayIndexStarts();
return llvm::makeArrayRef(IndexVars + IndexStarts[Index],
IndexVars + IndexStarts[Index + 1]);
}
@@ -1099,10 +1076,14 @@ TemplateParameterList *LambdaExpr::getTemplateParameterList() const {
}
CompoundStmt *LambdaExpr::getBody() const {
+ // FIXME: this mutation in getBody is bogus. It should be
+ // initialized in ASTStmtReader::VisitLambdaExpr, but for reasons I
+ // don't understand, that doesn't work.
if (!getStoredStmts()[NumCaptures])
- getStoredStmts()[NumCaptures] = getCallOperator()->getBody();
-
- return reinterpret_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]);
+ *const_cast<clang::Stmt **>(&getStoredStmts()[NumCaptures]) =
+ getCallOperator()->getBody();
+
+ return static_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]);
}
bool LambdaExpr::isMutable() const {
@@ -1119,14 +1100,13 @@ ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
SubExpr(subexpr) {
ExprWithCleanupsBits.NumObjects = objects.size();
for (unsigned i = 0, e = objects.size(); i != e; ++i)
- getObjectsBuffer()[i] = objects[i];
+ getTrailingObjects<CleanupObject>()[i] = objects[i];
}
ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr,
ArrayRef<CleanupObject> objects) {
- size_t size = sizeof(ExprWithCleanups)
- + objects.size() * sizeof(CleanupObject);
- void *buffer = C.Allocate(size, llvm::alignOf<ExprWithCleanups>());
+ void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()),
+ llvm::alignOf<ExprWithCleanups>());
return new (buffer) ExprWithCleanups(subexpr, objects);
}
@@ -1138,8 +1118,8 @@ ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects)
ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C,
EmptyShell empty,
unsigned numObjects) {
- size_t size = sizeof(ExprWithCleanups) + numObjects * sizeof(CleanupObject);
- void *buffer = C.Allocate(size, llvm::alignOf<ExprWithCleanups>());
+ void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(numObjects),
+ llvm::alignOf<ExprWithCleanups>());
return new (buffer) ExprWithCleanups(empty, numObjects);
}
@@ -1159,7 +1139,7 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
LParenLoc(LParenLoc),
RParenLoc(RParenLoc),
NumArgs(Args.size()) {
- Stmt **StoredArgs = reinterpret_cast<Stmt **>(this + 1);
+ Expr **StoredArgs = getTrailingObjects<Expr *>();
for (unsigned I = 0; I != Args.size(); ++I) {
if (Args[I]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
@@ -1174,16 +1154,14 @@ CXXUnresolvedConstructExpr::Create(const ASTContext &C,
SourceLocation LParenLoc,
ArrayRef<Expr*> Args,
SourceLocation RParenLoc) {
- void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) +
- sizeof(Expr *) * Args.size());
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Args.size()));
return new (Mem) CXXUnresolvedConstructExpr(Type, LParenLoc, Args, RParenLoc);
}
CXXUnresolvedConstructExpr *
CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &C, unsigned NumArgs) {
Stmt::EmptyShell Empty;
- void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) +
- sizeof(Expr *) * NumArgs);
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumArgs));
return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs);
}
@@ -1191,63 +1169,40 @@ SourceLocation CXXUnresolvedConstructExpr::getLocStart() const {
return Type->getTypeLoc().getBeginLoc();
}
-CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(const ASTContext &C,
- Expr *Base, QualType BaseType,
- bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierFoundInScope,
- DeclarationNameInfo MemberNameInfo,
- const TemplateArgumentListInfo *TemplateArgs)
- : Expr(CXXDependentScopeMemberExprClass, C.DependentTy,
- VK_LValue, OK_Ordinary, true, true, true,
- ((Base && Base->containsUnexpandedParameterPack()) ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()
- ->containsUnexpandedParameterPack()) ||
- MemberNameInfo.containsUnexpandedParameterPack())),
- Base(Base), BaseType(BaseType), IsArrow(IsArrow),
- HasTemplateKWAndArgsInfo(TemplateArgs != nullptr ||
- TemplateKWLoc.isValid()),
- OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
- FirstQualifierFoundInScope(FirstQualifierFoundInScope),
- MemberNameInfo(MemberNameInfo) {
+CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
+ const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs)
+ : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, VK_LValue,
+ OK_Ordinary, true, true, true,
+ ((Base && Base->containsUnexpandedParameterPack()) ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()) ||
+ MemberNameInfo.containsUnexpandedParameterPack())),
+ Base(Base), BaseType(BaseType), IsArrow(IsArrow),
+ HasTemplateKWAndArgsInfo(TemplateArgs != nullptr ||
+ TemplateKWLoc.isValid()),
+ OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
+ FirstQualifierFoundInScope(FirstQualifierFoundInScope),
+ MemberNameInfo(MemberNameInfo) {
if (TemplateArgs) {
bool Dependent = true;
bool InstantiationDependent = true;
bool ContainsUnexpandedParameterPack = false;
- getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs,
- Dependent,
- InstantiationDependent,
- ContainsUnexpandedParameterPack);
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(),
+ Dependent, InstantiationDependent, ContainsUnexpandedParameterPack);
if (ContainsUnexpandedParameterPack)
ExprBits.ContainsUnexpandedParameterPack = true;
} else if (TemplateKWLoc.isValid()) {
- getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
+ TemplateKWLoc);
}
}
-CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(const ASTContext &C,
- Expr *Base, QualType BaseType,
- bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
- NamedDecl *FirstQualifierFoundInScope,
- DeclarationNameInfo MemberNameInfo)
- : Expr(CXXDependentScopeMemberExprClass, C.DependentTy,
- VK_LValue, OK_Ordinary, true, true, true,
- ((Base && Base->containsUnexpandedParameterPack()) ||
- (QualifierLoc &&
- QualifierLoc.getNestedNameSpecifier()->
- containsUnexpandedParameterPack()) ||
- MemberNameInfo.containsUnexpandedParameterPack())),
- Base(Base), BaseType(BaseType), IsArrow(IsArrow),
- HasTemplateKWAndArgsInfo(false),
- OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
- FirstQualifierFoundInScope(FirstQualifierFoundInScope),
- MemberNameInfo(MemberNameInfo) { }
-
CXXDependentScopeMemberExpr *
CXXDependentScopeMemberExpr::Create(const ASTContext &C,
Expr *Base, QualType BaseType, bool IsArrow,
@@ -1257,18 +1212,13 @@ CXXDependentScopeMemberExpr::Create(const ASTContext &C,
NamedDecl *FirstQualifierFoundInScope,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
- if (!TemplateArgs && !TemplateKWLoc.isValid())
- return new (C) CXXDependentScopeMemberExpr(C, Base, BaseType,
- IsArrow, OperatorLoc,
- QualifierLoc,
- FirstQualifierFoundInScope,
- MemberNameInfo);
-
+ bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
- std::size_t size = sizeof(CXXDependentScopeMemberExpr)
- + ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs);
+ std::size_t Size =
+ totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>());
+ void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>());
return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType,
IsArrow, OperatorLoc,
QualifierLoc,
@@ -1281,22 +1231,18 @@ CXXDependentScopeMemberExpr *
CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) {
- if (!HasTemplateKWAndArgsInfo)
- return new (C) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
- 0, SourceLocation(),
- NestedNameSpecifierLoc(),
- nullptr, DeclarationNameInfo());
-
- std::size_t size = sizeof(CXXDependentScopeMemberExpr) +
- ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs);
- void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>());
+ assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
+ std::size_t Size =
+ totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>());
CXXDependentScopeMemberExpr *E
= new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
0, SourceLocation(),
NestedNameSpecifierLoc(),
SourceLocation(), nullptr,
DeclarationNameInfo(), nullptr);
- E->HasTemplateKWAndArgsInfo = true;
+ E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
}
@@ -1361,38 +1307,34 @@ bool UnresolvedMemberExpr::isImplicitAccess() const {
return cast<Expr>(Base)->isImplicitCXXThis();
}
-UnresolvedMemberExpr *
-UnresolvedMemberExpr::Create(const ASTContext &C, bool HasUnresolvedUsing,
- Expr *Base, QualType BaseType, bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &MemberNameInfo,
- const TemplateArgumentListInfo *TemplateArgs,
- UnresolvedSetIterator Begin,
- UnresolvedSetIterator End) {
- std::size_t size = sizeof(UnresolvedMemberExpr);
- if (TemplateArgs)
- size += ASTTemplateKWAndArgsInfo::sizeFor(TemplateArgs->size());
- else if (TemplateKWLoc.isValid())
- size += ASTTemplateKWAndArgsInfo::sizeFor(0);
-
- void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>());
- return new (Mem) UnresolvedMemberExpr(C,
- HasUnresolvedUsing, Base, BaseType,
- IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc,
- MemberNameInfo, TemplateArgs, Begin, End);
+UnresolvedMemberExpr *UnresolvedMemberExpr::Create(
+ const ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType,
+ bool IsArrow, SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) {
+ bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
+ std::size_t Size =
+ totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasTemplateKWAndArgsInfo, TemplateArgs ? TemplateArgs->size() : 0);
+
+ void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>());
+ return new (Mem) UnresolvedMemberExpr(
+ C, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc,
+ TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End);
}
UnresolvedMemberExpr *
UnresolvedMemberExpr::CreateEmpty(const ASTContext &C,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) {
- std::size_t size = sizeof(UnresolvedMemberExpr);
- if (HasTemplateKWAndArgsInfo)
- size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs);
+ assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
+ std::size_t Size =
+ totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>());
+ void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>());
UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
@@ -1428,6 +1370,25 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
return Record;
}
+SizeOfPackExpr *
+SizeOfPackExpr::Create(ASTContext &Context, SourceLocation OperatorLoc,
+ NamedDecl *Pack, SourceLocation PackLoc,
+ SourceLocation RParenLoc,
+ Optional<unsigned> Length,
+ ArrayRef<TemplateArgument> PartialArgs) {
+ void *Storage =
+ Context.Allocate(totalSizeToAlloc<TemplateArgument>(PartialArgs.size()));
+ return new (Storage) SizeOfPackExpr(Context.getSizeType(), OperatorLoc, Pack,
+ PackLoc, RParenLoc, Length, PartialArgs);
+}
+
+SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context,
+ unsigned NumPartialArgs) {
+ void *Storage =
+ Context.Allocate(totalSizeToAlloc<TemplateArgument>(NumPartialArgs));
+ return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs);
+}
+
SubstNonTypeTemplateParmPackExpr::
SubstNonTypeTemplateParmPackExpr(QualType T,
NonTypeTemplateParmDecl *Param,
@@ -1439,36 +1400,34 @@ SubstNonTypeTemplateParmPackExpr(QualType T,
NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { }
TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
- return TemplateArgument(Arguments, NumArguments);
+ return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments));
}
FunctionParmPackExpr::FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack,
SourceLocation NameLoc,
unsigned NumParams,
- Decl * const *Params)
- : Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary,
- true, true, true, true),
- ParamPack(ParamPack), NameLoc(NameLoc), NumParameters(NumParams) {
+ ParmVarDecl *const *Params)
+ : Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary, true, true,
+ true, true),
+ ParamPack(ParamPack), NameLoc(NameLoc), NumParameters(NumParams) {
if (Params)
std::uninitialized_copy(Params, Params + NumParams,
- reinterpret_cast<Decl**>(this+1));
+ getTrailingObjects<ParmVarDecl *>());
}
FunctionParmPackExpr *
FunctionParmPackExpr::Create(const ASTContext &Context, QualType T,
ParmVarDecl *ParamPack, SourceLocation NameLoc,
- ArrayRef<Decl *> Params) {
- return new (Context.Allocate(sizeof(FunctionParmPackExpr) +
- sizeof(ParmVarDecl*) * Params.size()))
- FunctionParmPackExpr(T, ParamPack, NameLoc, Params.size(), Params.data());
+ ArrayRef<ParmVarDecl *> Params) {
+ return new (Context.Allocate(totalSizeToAlloc<ParmVarDecl *>(Params.size())))
+ FunctionParmPackExpr(T, ParamPack, NameLoc, Params.size(), Params.data());
}
FunctionParmPackExpr *
FunctionParmPackExpr::CreateEmpty(const ASTContext &Context,
unsigned NumParams) {
- return new (Context.Allocate(sizeof(FunctionParmPackExpr) +
- sizeof(ParmVarDecl*) * NumParams))
- FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr);
+ return new (Context.Allocate(totalSizeToAlloc<ParmVarDecl *>(NumParams)))
+ FunctionParmPackExpr(QualType(), nullptr, SourceLocation(), 0, nullptr);
}
void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy,
@@ -1505,8 +1464,8 @@ TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
TypeTraitExprBits.Value = Value;
TypeTraitExprBits.NumArgs = Args.size();
- TypeSourceInfo **ToArgs = getTypeSourceInfos();
-
+ TypeSourceInfo **ToArgs = getTrailingObjects<TypeSourceInfo *>();
+
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
if (Args[I]->getType()->isDependentType())
setValueDependent(true);
@@ -1525,15 +1484,13 @@ TypeTraitExpr *TypeTraitExpr::Create(const ASTContext &C, QualType T,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc,
bool Value) {
- unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * Args.size();
- void *Mem = C.Allocate(Size);
+ void *Mem = C.Allocate(totalSizeToAlloc<TypeSourceInfo *>(Args.size()));
return new (Mem) TypeTraitExpr(T, Loc, Kind, Args, RParenLoc, Value);
}
TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C,
unsigned NumArgs) {
- unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * NumArgs;
- void *Mem = C.Allocate(Size);
+ void *Mem = C.Allocate(totalSizeToAlloc<TypeSourceInfo *>(NumArgs));
return new (Mem) TypeTraitExpr(EmptyShell());
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
index 9cc612e..a47b03c 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp
@@ -136,6 +136,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::ObjCIvarRefExprClass:
case Expr::FunctionParmPackExprClass:
case Expr::MSPropertyRefExprClass:
+ case Expr::MSPropertySubscriptExprClass:
+ case Expr::OMPArraySectionExprClass:
return Cl::CL_LValue;
// C99 6.5.2.5p5 says that compound literals are lvalues.
@@ -185,6 +187,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::CXXFoldExprClass:
case Expr::NoInitExprClass:
case Expr::DesignatedInitUpdateExprClass:
+ case Expr::CoyieldExprClass:
return Cl::CL_PRValue;
// Next come the complicated cases.
@@ -396,6 +399,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
assert(cast<InitListExpr>(E)->getNumInits() == 1 &&
"Only 1-element init lists can be glvalues.");
return ClassifyInternal(Ctx, cast<InitListExpr>(E)->getInit(0));
+
+ case Expr::CoawaitExprClass:
+ return ClassifyInternal(Ctx, cast<CoawaitExpr>(E)->getResumeExpr());
}
llvm_unreachable("unhandled expression kind in classification");
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
index ed749cc..fa652ba 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
@@ -114,7 +114,8 @@ namespace {
static
unsigned findMostDerivedSubobject(ASTContext &Ctx, QualType Base,
ArrayRef<APValue::LValuePathEntry> Path,
- uint64_t &ArraySize, QualType &Type) {
+ uint64_t &ArraySize, QualType &Type,
+ bool &IsArray) {
unsigned MostDerivedLength = 0;
Type = Base;
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
@@ -124,18 +125,22 @@ namespace {
Type = CAT->getElementType();
ArraySize = CAT->getSize().getZExtValue();
MostDerivedLength = I + 1;
+ IsArray = true;
} else if (Type->isAnyComplexType()) {
const ComplexType *CT = Type->castAs<ComplexType>();
Type = CT->getElementType();
ArraySize = 2;
MostDerivedLength = I + 1;
+ IsArray = true;
} else if (const FieldDecl *FD = getAsField(Path[I])) {
Type = FD->getType();
ArraySize = 0;
MostDerivedLength = I + 1;
+ IsArray = false;
} else {
// Path[I] describes a base class.
ArraySize = 0;
+ IsArray = false;
}
}
return MostDerivedLength;
@@ -157,12 +162,17 @@ namespace {
/// Is this a pointer one past the end of an object?
bool IsOnePastTheEnd : 1;
+ /// Indicator of whether the most-derived object is an array element.
+ bool MostDerivedIsArrayElement : 1;
+
/// The length of the path to the most-derived object of which this is a
/// subobject.
- unsigned MostDerivedPathLength : 30;
+ unsigned MostDerivedPathLength : 29;
- /// The size of the array of which the most-derived object is an element, or
- /// 0 if the most-derived object is not an array element.
+ /// The size of the array of which the most-derived object is an element.
+ /// This will always be 0 if the most-derived object is not an array
+ /// element. 0 is not an indicator of whether or not the most-derived object
+ /// is an array, however, because 0-length arrays are allowed.
uint64_t MostDerivedArraySize;
/// The type of the most derived object referred to by this address.
@@ -176,21 +186,26 @@ namespace {
SubobjectDesignator() : Invalid(true) {}
explicit SubobjectDesignator(QualType T)
- : Invalid(false), IsOnePastTheEnd(false), MostDerivedPathLength(0),
- MostDerivedArraySize(0), MostDerivedType(T) {}
+ : Invalid(false), IsOnePastTheEnd(false),
+ MostDerivedIsArrayElement(false), MostDerivedPathLength(0),
+ MostDerivedArraySize(0), MostDerivedType(T) {}
SubobjectDesignator(ASTContext &Ctx, const APValue &V)
- : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false),
- MostDerivedPathLength(0), MostDerivedArraySize(0) {
+ : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false),
+ MostDerivedIsArrayElement(false), MostDerivedPathLength(0),
+ MostDerivedArraySize(0) {
if (!Invalid) {
IsOnePastTheEnd = V.isLValueOnePastTheEnd();
ArrayRef<PathEntry> VEntries = V.getLValuePath();
Entries.insert(Entries.end(), VEntries.begin(), VEntries.end());
- if (V.getLValueBase())
+ if (V.getLValueBase()) {
+ bool IsArray = false;
MostDerivedPathLength =
findMostDerivedSubobject(Ctx, getType(V.getLValueBase()),
V.getLValuePath(), MostDerivedArraySize,
- MostDerivedType);
+ MostDerivedType, IsArray);
+ MostDerivedIsArrayElement = IsArray;
+ }
}
}
@@ -204,7 +219,7 @@ namespace {
assert(!Invalid);
if (IsOnePastTheEnd)
return true;
- if (MostDerivedArraySize &&
+ if (MostDerivedIsArrayElement &&
Entries[MostDerivedPathLength - 1].ArrayIndex == MostDerivedArraySize)
return true;
return false;
@@ -228,6 +243,7 @@ namespace {
// This is a most-derived object.
MostDerivedType = CAT->getElementType();
+ MostDerivedIsArrayElement = true;
MostDerivedArraySize = CAT->getSize().getZExtValue();
MostDerivedPathLength = Entries.size();
}
@@ -242,6 +258,7 @@ namespace {
// If this isn't a base class, it's a new most-derived object.
if (const FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
MostDerivedType = FD->getType();
+ MostDerivedIsArrayElement = false;
MostDerivedArraySize = 0;
MostDerivedPathLength = Entries.size();
}
@@ -255,6 +272,7 @@ namespace {
// This is technically a most-derived object, though in practice this
// is unlikely to matter.
MostDerivedType = EltTy;
+ MostDerivedIsArrayElement = true;
MostDerivedArraySize = 2;
MostDerivedPathLength = Entries.size();
}
@@ -262,7 +280,8 @@ namespace {
/// Add N to the address of this subobject.
void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) {
if (Invalid) return;
- if (MostDerivedPathLength == Entries.size() && MostDerivedArraySize) {
+ if (MostDerivedPathLength == Entries.size() &&
+ MostDerivedIsArrayElement) {
Entries.back().ArrayIndex += N;
if (Entries.back().ArrayIndex > MostDerivedArraySize) {
diagnosePointerArithmetic(Info, E, Entries.back().ArrayIndex);
@@ -454,6 +473,10 @@ namespace {
/// notes attached to it will also be stored, otherwise they will not be.
bool HasActiveDiagnostic;
+ /// \brief Have we emitted a diagnostic explaining why we couldn't constant
+ /// fold (not just why it's not strictly a constant expression)?
+ bool HasFoldFailureDiagnostic;
+
enum EvaluationMode {
/// Evaluate as a constant expression. Stop if we find that the expression
/// is not a constant expression.
@@ -492,7 +515,11 @@ namespace {
/// optimizer if we don't constant fold them here, but in an unevaluated
/// context we try to fold them immediately since the optimizer never
/// gets a chance to look at it.
- EM_PotentialConstantExpressionUnevaluated
+ EM_PotentialConstantExpressionUnevaluated,
+
+ /// Evaluate as a constant expression. Continue evaluating if we find a
+ /// MemberExpr with a base that can't be evaluated.
+ EM_DesignatorFold,
} EvalMode;
/// Are we checking whether the expression is a potential constant
@@ -514,7 +541,7 @@ namespace {
BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr),
EvaluatingDecl((const ValueDecl *)nullptr),
EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
- EvalMode(Mode) {}
+ HasFoldFailureDiagnostic(false), EvalMode(Mode) {}
void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
EvaluatingDecl = Base;
@@ -574,7 +601,7 @@ namespace {
/// Diagnose that the evaluation cannot be folded.
OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId
= diag::note_invalid_subexpr_in_const_expr,
- unsigned ExtraNotes = 0) {
+ unsigned ExtraNotes = 0, bool IsCCEDiag = false) {
if (EvalStatus.Diag) {
// If we have a prior diagnostic, it will be noting that the expression
// isn't a constant expression. This diagnostic is more important,
@@ -587,14 +614,14 @@ namespace {
case EM_ConstantFold:
case EM_IgnoreSideEffects:
case EM_EvaluateForOverflow:
- if (!EvalStatus.HasSideEffects)
+ if (!HasFoldFailureDiagnostic)
break;
- // We've had side-effects; we want the diagnostic from them, not
- // some later problem.
+ // We've already failed to fold something. Keep that diagnostic.
case EM_ConstantExpression:
case EM_PotentialConstantExpression:
case EM_ConstantExpressionUnevaluated:
case EM_PotentialConstantExpressionUnevaluated:
+ case EM_DesignatorFold:
HasActiveDiagnostic = false;
return OptionalDiagnostic();
}
@@ -608,6 +635,7 @@ namespace {
CallStackNotes = 0;
HasActiveDiagnostic = true;
+ HasFoldFailureDiagnostic = !IsCCEDiag;
EvalStatus.Diag->clear();
EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes);
addDiag(Loc, DiagId);
@@ -621,9 +649,9 @@ namespace {
OptionalDiagnostic Diag(const Expr *E, diag::kind DiagId
= diag::note_invalid_subexpr_in_const_expr,
- unsigned ExtraNotes = 0) {
+ unsigned ExtraNotes = 0, bool IsCCEDiag = false) {
if (EvalStatus.Diag)
- return Diag(E->getExprLoc(), DiagId, ExtraNotes);
+ return Diag(E->getExprLoc(), DiagId, ExtraNotes, IsCCEDiag);
HasActiveDiagnostic = false;
return OptionalDiagnostic();
}
@@ -643,7 +671,7 @@ namespace {
HasActiveDiagnostic = false;
return OptionalDiagnostic();
}
- return Diag(Loc, DiagId, ExtraNotes);
+ return Diag(Loc, DiagId, ExtraNotes, true);
}
/// Add a note to a prior diagnostic.
@@ -674,6 +702,7 @@ namespace {
case EM_ConstantExpression:
case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
+ case EM_DesignatorFold:
return false;
}
llvm_unreachable("Missed EvalMode case");
@@ -686,6 +715,32 @@ namespace {
return keepEvaluatingAfterSideEffect();
}
+ /// Should we continue evaluation after encountering undefined behavior?
+ bool keepEvaluatingAfterUndefinedBehavior() {
+ switch (EvalMode) {
+ case EM_EvaluateForOverflow:
+ case EM_IgnoreSideEffects:
+ case EM_ConstantFold:
+ case EM_DesignatorFold:
+ return true;
+
+ case EM_PotentialConstantExpression:
+ case EM_PotentialConstantExpressionUnevaluated:
+ case EM_ConstantExpression:
+ case EM_ConstantExpressionUnevaluated:
+ return false;
+ }
+ llvm_unreachable("Missed EvalMode case");
+ }
+
+ /// Note that we hit something that was technically undefined behavior, but
+ /// that we can evaluate past it (such as signed overflow or floating-point
+ /// division by zero.)
+ bool noteUndefinedBehavior() {
+ EvalStatus.HasUndefinedBehavior = true;
+ return keepEvaluatingAfterUndefinedBehavior();
+ }
+
/// Should we continue evaluation as much as possible after encountering a
/// construct which can't be reduced to a value?
bool keepEvaluatingAfterFailure() {
@@ -702,10 +757,15 @@ namespace {
case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
case EM_IgnoreSideEffects:
+ case EM_DesignatorFold:
return false;
}
llvm_unreachable("Missed EvalMode case");
}
+
+ bool allowInvalidBaseExpr() const {
+ return EvalMode == EM_DesignatorFold;
+ }
};
/// Object used to treat all foldable expressions as constant expressions.
@@ -736,6 +796,21 @@ namespace {
}
};
+ /// RAII object used to treat the current evaluation as the correct pointer
+ /// offset fold for the current EvalMode
+ struct FoldOffsetRAII {
+ EvalInfo &Info;
+ EvalInfo::EvaluationMode OldMode;
+ explicit FoldOffsetRAII(EvalInfo &Info, bool Subobject)
+ : Info(Info), OldMode(Info.EvalMode) {
+ if (!Info.checkingPotentialConstantExpression())
+ Info.EvalMode = Subobject ? EvalInfo::EM_DesignatorFold
+ : EvalInfo::EM_ConstantFold;
+ }
+
+ ~FoldOffsetRAII() { Info.EvalMode = OldMode; }
+ };
+
/// RAII object used to suppress diagnostics and side-effects from a
/// speculative evaluation.
class SpeculativeEvaluationRAII {
@@ -808,7 +883,7 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E,
void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info,
const Expr *E, uint64_t N) {
- if (MostDerivedPathLength == Entries.size() && MostDerivedArraySize)
+ if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement)
Info.CCEDiag(E, diag::note_constexpr_array_index)
<< static_cast<int>(N) << /*array*/ 0
<< static_cast<unsigned>(MostDerivedArraySize);
@@ -917,7 +992,8 @@ namespace {
struct LValue {
APValue::LValueBase Base;
CharUnits Offset;
- unsigned CallIndex;
+ bool InvalidBase : 1;
+ unsigned CallIndex : 31;
SubobjectDesignator Designator;
const APValue::LValueBase getLValueBase() const { return Base; }
@@ -938,17 +1014,23 @@ namespace {
assert(V.isLValue());
Base = V.getLValueBase();
Offset = V.getLValueOffset();
+ InvalidBase = false;
CallIndex = V.getLValueCallIndex();
Designator = SubobjectDesignator(Ctx, V);
}
- void set(APValue::LValueBase B, unsigned I = 0) {
+ void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false) {
Base = B;
Offset = CharUnits::Zero();
+ InvalidBase = BInvalid;
CallIndex = I;
Designator = SubobjectDesignator(getType(B));
}
+ void setInvalid(APValue::LValueBase B, unsigned I = 0) {
+ set(B, I, true);
+ }
+
// Check that this LValue is not based on a null pointer. If it is, produce
// a diagnostic and mark the designator as invalid.
bool checkNullPointer(EvalInfo &Info, const Expr *E,
@@ -967,10 +1049,6 @@ namespace {
// Check this LValue refers to an object. If not, set the designator to be
// invalid and emit a diagnostic.
bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) {
- // Outside C++11, do not build a designator referring to a subobject of
- // any object: we won't use such a designator for anything.
- if (!Info.getLangOpts().CPlusPlus11)
- Designator.setInvalid();
return (CSK == CSK_ArrayToPointer || checkNullPointer(Info, E, CSK)) &&
Designator.checkSubobject(Info, E, CSK);
}
@@ -1102,12 +1180,13 @@ static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info);
static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result,
EvalInfo &Info);
static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info);
-static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info);
+static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info);
static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result,
EvalInfo &Info);
static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info);
static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info);
static bool EvaluateAtomic(const Expr *E, APValue &Result, EvalInfo &Info);
+static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result);
//===----------------------------------------------------------------------===//
// Misc utilities
@@ -1492,10 +1571,11 @@ static bool EvaluateAsBooleanCondition(const Expr *E, bool &Result,
}
template<typename T>
-static void HandleOverflow(EvalInfo &Info, const Expr *E,
+static bool HandleOverflow(EvalInfo &Info, const Expr *E,
const T &SrcValue, QualType DestType) {
Info.CCEDiag(E, diag::note_constexpr_overflow)
<< SrcValue << DestType;
+ return Info.noteUndefinedBehavior();
}
static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E,
@@ -1509,7 +1589,7 @@ static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E,
bool ignored;
if (Value.convertToInteger(Result, llvm::APFloat::rmTowardZero, &ignored)
& APFloat::opInvalidOp)
- HandleOverflow(Info, E, Value, DestType);
+ return HandleOverflow(Info, E, Value, DestType);
return true;
}
@@ -1521,13 +1601,13 @@ static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E,
if (Result.convert(Info.Ctx.getFloatTypeSemantics(DestType),
APFloat::rmNearestTiesToEven, &ignored)
& APFloat::opOverflow)
- HandleOverflow(Info, E, Value, DestType);
+ return HandleOverflow(Info, E, Value, DestType);
return true;
}
static APSInt HandleIntToIntCast(EvalInfo &Info, const Expr *E,
QualType DestType, QualType SrcType,
- APSInt &Value) {
+ const APSInt &Value) {
unsigned DestWidth = Info.Ctx.getIntWidth(DestType);
APSInt Result = Value;
// Figure out if this is a truncate, extend or noop cast.
@@ -1544,7 +1624,7 @@ static bool HandleIntToFloatCast(EvalInfo &Info, const Expr *E,
if (Result.convertFromAPInt(Value, Value.isSigned(),
APFloat::rmNearestTiesToEven)
& APFloat::opOverflow)
- HandleOverflow(Info, E, Value, DestType);
+ return HandleOverflow(Info, E, Value, DestType);
return true;
}
@@ -1620,23 +1700,26 @@ static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E,
/// bits, and check for overflow in the original type (if that type was not an
/// unsigned type).
template<typename Operation>
-static APSInt CheckedIntArithmetic(EvalInfo &Info, const Expr *E,
- const APSInt &LHS, const APSInt &RHS,
- unsigned BitWidth, Operation Op) {
- if (LHS.isUnsigned())
- return Op(LHS, RHS);
+static bool CheckedIntArithmetic(EvalInfo &Info, const Expr *E,
+ const APSInt &LHS, const APSInt &RHS,
+ unsigned BitWidth, Operation Op,
+ APSInt &Result) {
+ if (LHS.isUnsigned()) {
+ Result = Op(LHS, RHS);
+ return true;
+ }
APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false);
- APSInt Result = Value.trunc(LHS.getBitWidth());
+ Result = Value.trunc(LHS.getBitWidth());
if (Result.extend(BitWidth) != Value) {
if (Info.checkingForOverflow())
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
- diag::warn_integer_constant_overflow)
+ diag::warn_integer_constant_overflow)
<< Result.toString(10) << E->getType();
else
- HandleOverflow(Info, E, Value, E->getType());
+ return HandleOverflow(Info, E, Value, E->getType());
}
- return Result;
+ return true;
}
/// Perform the given binary integer operation.
@@ -1648,17 +1731,14 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS,
Info.Diag(E);
return false;
case BO_Mul:
- Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() * 2,
- std::multiplies<APSInt>());
- return true;
+ return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() * 2,
+ std::multiplies<APSInt>(), Result);
case BO_Add:
- Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1,
- std::plus<APSInt>());
- return true;
+ return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1,
+ std::plus<APSInt>(), Result);
case BO_Sub:
- Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1,
- std::minus<APSInt>());
- return true;
+ return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1,
+ std::minus<APSInt>(), Result);
case BO_And: Result = LHS & RHS; return true;
case BO_Xor: Result = LHS ^ RHS; return true;
case BO_Or: Result = LHS | RHS; return true;
@@ -1668,11 +1748,13 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS,
Info.Diag(E, diag::note_expr_divide_by_zero);
return false;
}
- // Check for overflow case: INT_MIN / -1 or INT_MIN % -1.
+ Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS);
+ // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. APSInt supports
+ // this operation and gives the two's complement result.
if (RHS.isNegative() && RHS.isAllOnesValue() &&
LHS.isSigned() && LHS.isMinSignedValue())
- HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), E->getType());
- Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS);
+ return HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1),
+ E->getType());
return true;
case BO_Shl: {
if (Info.getLangOpts().OpenCL)
@@ -1760,8 +1842,10 @@ static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E,
break;
}
- if (LHS.isInfinity() || LHS.isNaN())
+ if (LHS.isInfinity() || LHS.isNaN()) {
Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN();
+ return Info.noteUndefinedBehavior();
+ }
return true;
}
@@ -2159,6 +2243,7 @@ enum AccessKinds {
AK_Decrement
};
+namespace {
/// A handle to a complete object (an object that is not a subobject of
/// another object).
struct CompleteObject {
@@ -2175,6 +2260,7 @@ struct CompleteObject {
explicit operator bool() const { return Value; }
};
+} // end anonymous namespace
/// Find the designated sub-object of an rvalue.
template<typename SubobjectHandler>
@@ -2488,7 +2574,7 @@ static bool AreElementsOfSameArray(QualType ObjType,
if (A.Entries.size() != B.Entries.size())
return false;
- bool IsArray = A.MostDerivedArraySize != 0;
+ bool IsArray = A.MostDerivedIsArrayElement;
if (IsArray && A.MostDerivedPathLength != A.Entries.size())
// A is a subobject of the array element.
return false;
@@ -2713,8 +2799,7 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
// Check for special cases where there is no existing APValue to look at.
const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
- if (!LVal.Designator.Invalid && Base && !LVal.CallIndex &&
- !Type.isVolatileQualified()) {
+ if (Base && !LVal.CallIndex && !Type.isVolatileQualified()) {
if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(Base)) {
// In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the
// initializer until now for such expressions. Such an expression can't be
@@ -2959,7 +3044,7 @@ struct IncDecSubobjectHandler {
if (!WasNegative && Value.isNegative() &&
isOverflowingIntegerType(Info.Ctx, SubobjType)) {
APSInt ActualValue(Value, /*IsUnsigned*/true);
- HandleOverflow(Info, E, ActualValue, SubobjType);
+ return HandleOverflow(Info, E, ActualValue, SubobjType);
}
} else {
--Value;
@@ -2969,7 +3054,7 @@ struct IncDecSubobjectHandler {
unsigned BitWidth = Value.getBitWidth();
APSInt ActualValue(Value.sext(BitWidth + 1), /*IsUnsigned*/false);
ActualValue.setBit(BitWidth);
- HandleOverflow(Info, E, ActualValue, SubobjType);
+ return HandleOverflow(Info, E, ActualValue, SubobjType);
}
}
return true;
@@ -3253,12 +3338,21 @@ static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl,
return EvaluateAsBooleanCondition(Cond, Result, Info);
}
-static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
+/// \brief A location where the result (returned value) of evaluating a
+/// statement should be stored.
+struct StmtResult {
+ /// The APValue that should be filled in with the returned value.
+ APValue &Value;
+ /// The location containing the result, if any (used to support RVO).
+ const LValue *Slot;
+};
+
+static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
const Stmt *S,
const SwitchCase *SC = nullptr);
/// Evaluate the body of a loop, and translate the result as appropriate.
-static EvalStmtResult EvaluateLoopBody(APValue &Result, EvalInfo &Info,
+static EvalStmtResult EvaluateLoopBody(StmtResult &Result, EvalInfo &Info,
const Stmt *Body,
const SwitchCase *Case = nullptr) {
BlockScopeRAII Scope(Info);
@@ -3277,7 +3371,7 @@ static EvalStmtResult EvaluateLoopBody(APValue &Result, EvalInfo &Info,
}
/// Evaluate a switch statement.
-static EvalStmtResult EvaluateSwitch(APValue &Result, EvalInfo &Info,
+static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info,
const SwitchStmt *SS) {
BlockScopeRAII Scope(Info);
@@ -3334,7 +3428,7 @@ static EvalStmtResult EvaluateSwitch(APValue &Result, EvalInfo &Info,
}
// Evaluate a statement.
-static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
+static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
const Stmt *S, const SwitchCase *Case) {
if (!Info.nextStep(S))
return ESR_Failed;
@@ -3440,7 +3534,10 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
case Stmt::ReturnStmtClass: {
const Expr *RetExpr = cast<ReturnStmt>(S)->getRetValue();
FullExpressionRAII Scope(Info);
- if (RetExpr && !Evaluate(Result, Info, RetExpr))
+ if (RetExpr &&
+ !(Result.Slot
+ ? EvaluateInPlace(Result.Value, Info, *Result.Slot, RetExpr)
+ : Evaluate(Result.Value, Info, RetExpr)))
return ESR_Failed;
return ESR_Returned;
}
@@ -3710,7 +3807,8 @@ static bool EvaluateArgs(ArrayRef<const Expr*> Args, ArgVector &ArgValues,
static bool HandleFunctionCall(SourceLocation CallLoc,
const FunctionDecl *Callee, const LValue *This,
ArrayRef<const Expr*> Args, const Stmt *Body,
- EvalInfo &Info, APValue &Result) {
+ EvalInfo &Info, APValue &Result,
+ const LValue *ResultSlot) {
ArgVector ArgValues(Args.size());
if (!EvaluateArgs(Args, ArgValues, Info))
return false;
@@ -3745,7 +3843,8 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
return true;
}
- EvalStmtResult ESR = EvaluateStmt(Result, Info, Body);
+ StmtResult Ret = {Result, ResultSlot};
+ EvalStmtResult ESR = EvaluateStmt(Ret, Info, Body);
if (ESR == ESR_Succeeded) {
if (Callee->getReturnType()->isVoidType())
return true;
@@ -3774,6 +3873,11 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues.data());
+ // FIXME: Creating an APValue just to hold a nonexistent return value is
+ // wasteful.
+ APValue RetVal;
+ StmtResult Ret = {RetVal, nullptr};
+
// If it's a delegating constructor, just delegate.
if (Definition->isDelegatingConstructor()) {
CXXConstructorDecl::init_const_iterator I = Definition->init_begin();
@@ -3782,7 +3886,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
if (!EvaluateInPlace(Result, Info, This, (*I)->getInit()))
return false;
}
- return EvaluateStmt(Result, Info, Definition->getBody()) != ESR_Failed;
+ return EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed;
}
// For a trivial copy or move constructor, perform an APValue copy. This is
@@ -3890,7 +3994,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
}
return Success &&
- EvaluateStmt(Result, Info, Definition->getBody()) != ESR_Failed;
+ EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed;
}
//===----------------------------------------------------------------------===//
@@ -3902,11 +4006,12 @@ template <class Derived>
class ExprEvaluatorBase
: public ConstStmtVisitor<Derived, bool> {
private:
+ Derived &getDerived() { return static_cast<Derived&>(*this); }
bool DerivedSuccess(const APValue &V, const Expr *E) {
- return static_cast<Derived*>(this)->Success(V, E);
+ return getDerived().Success(V, E);
}
bool DerivedZeroInitialization(const Expr *E) {
- return static_cast<Derived*>(this)->ZeroInitialization(E);
+ return getDerived().ZeroInitialization(E);
}
// Check whether a conditional operator with a non-constant condition is a
@@ -4087,6 +4192,14 @@ public:
}
bool VisitCallExpr(const CallExpr *E) {
+ APValue Result;
+ if (!handleCallExpr(E, Result, nullptr))
+ return false;
+ return DerivedSuccess(Result, E);
+ }
+
+ bool handleCallExpr(const CallExpr *E, APValue &Result,
+ const LValue *ResultSlot) {
const Expr *Callee = E->getCallee()->IgnoreParens();
QualType CalleeType = Callee->getType();
@@ -4161,14 +4274,13 @@ public:
const FunctionDecl *Definition = nullptr;
Stmt *Body = FD->getBody(Definition);
- APValue Result;
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition) ||
- !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body,
- Info, Result))
+ !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info,
+ Result, ResultSlot))
return false;
- return DerivedSuccess(Result, E);
+ return true;
}
bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
@@ -4293,7 +4405,8 @@ public:
}
APValue ReturnValue;
- EvalStmtResult ESR = EvaluateStmt(ReturnValue, Info, *BI);
+ StmtResult Result = { ReturnValue, nullptr };
+ EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI);
if (ESR != ESR_Succeeded) {
// FIXME: If the statement-expression terminated due to 'return',
// 'break', or 'continue', it would be nice to propagate that to
@@ -4345,20 +4458,24 @@ public:
bool VisitMemberExpr(const MemberExpr *E) {
// Handle non-static data members.
QualType BaseTy;
+ bool EvalOK;
if (E->isArrow()) {
- if (!EvaluatePointer(E->getBase(), Result, this->Info))
- return false;
+ EvalOK = EvaluatePointer(E->getBase(), Result, this->Info);
BaseTy = E->getBase()->getType()->castAs<PointerType>()->getPointeeType();
} else if (E->getBase()->isRValue()) {
assert(E->getBase()->getType()->isRecordType());
- if (!EvaluateTemporary(E->getBase(), Result, this->Info))
- return false;
+ EvalOK = EvaluateTemporary(E->getBase(), Result, this->Info);
BaseTy = E->getBase()->getType();
} else {
- if (!this->Visit(E->getBase()))
- return false;
+ EvalOK = this->Visit(E->getBase());
BaseTy = E->getBase()->getType();
}
+ if (!EvalOK) {
+ if (!this->Info.allowInvalidBaseExpr())
+ return false;
+ Result.setInvalid(E);
+ return true;
+ }
const ValueDecl *MD = E->getMemberDecl();
if (const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) {
@@ -4498,12 +4615,13 @@ public:
} // end anonymous namespace
/// Evaluate an expression as an lvalue. This can be legitimately called on
-/// expressions which are not glvalues, in two cases:
+/// expressions which are not glvalues, in three cases:
/// * function designators in C, and
/// * "extern void" objects
+/// * @selector() expressions in Objective-C
static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info) {
assert(E->isGLValue() || E->getType()->isFunctionType() ||
- E->getType()->isVoidType());
+ E->getType()->isVoidType() || isa<ObjCSelectorExpr>(E));
return LValueExprEvaluator(Info, Result).Visit(E);
}
@@ -4770,7 +4888,7 @@ public:
bool VisitObjCStringLiteral(const ObjCStringLiteral *E)
{ return Success(E); }
bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E)
- { return Success(E); }
+ { return Success(E); }
bool VisitAddrLabelExpr(const AddrLabelExpr *E)
{ return Success(E); }
bool VisitCallExpr(const CallExpr *E);
@@ -4896,6 +5014,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
unsigned Size = Info.Ctx.getTypeSize(E->getType());
uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue();
Result.Base = (Expr*)nullptr;
+ Result.InvalidBase = false;
Result.Offset = CharUnits::fromQuantity(N);
Result.CallIndex = 0;
Result.Designator.setInvalid();
@@ -5148,6 +5267,9 @@ namespace {
}
bool ZeroInitialization(const Expr *E);
+ bool VisitCallExpr(const CallExpr *E) {
+ return handleCallExpr(E, Result, &This);
+ }
bool VisitCastExpr(const CastExpr *E);
bool VisitInitListExpr(const InitListExpr *E);
bool VisitCXXConstructExpr(const CXXConstructExpr *E);
@@ -5504,7 +5626,7 @@ namespace {
VectorExprEvaluator(EvalInfo &info, APValue &Result)
: ExprEvaluatorBaseTy(info), Result(Result) {}
- bool Success(const ArrayRef<APValue> &V, const Expr *E) {
+ bool Success(ArrayRef<APValue> V, const Expr *E) {
assert(V.size() == E->getType()->castAs<VectorType>()->getNumElements());
// FIXME: remove this APValue copy.
Result = APValue(V.data(), V.size());
@@ -5533,7 +5655,7 @@ static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) {
return VectorExprEvaluator(Info, Result).Visit(E);
}
-bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
+bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) {
const VectorType *VTy = E->getType()->castAs<VectorType>();
unsigned NElts = VTy->getNumElements();
@@ -5546,13 +5668,13 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
if (SETy->isIntegerType()) {
APSInt IntResult;
if (!EvaluateInteger(SE, IntResult, Info))
- return false;
- Val = APValue(IntResult);
+ return false;
+ Val = APValue(std::move(IntResult));
} else if (SETy->isRealFloatingType()) {
- APFloat F(0.0);
- if (!EvaluateFloat(SE, F, Info))
- return false;
- Val = APValue(F);
+ APFloat FloatResult(0.0);
+ if (!EvaluateFloat(SE, FloatResult, Info))
+ return false;
+ Val = APValue(std::move(FloatResult));
} else {
return Error(E);
}
@@ -5710,6 +5832,9 @@ namespace {
return EvaluateInPlace(Result.getArrayFiller(), Info, Subobject, &VIE);
}
+ bool VisitCallExpr(const CallExpr *E) {
+ return handleCallExpr(E, Result, &This);
+ }
bool VisitInitListExpr(const InitListExpr *E);
bool VisitCXXConstructExpr(const CXXConstructExpr *E);
bool VisitCXXConstructExpr(const CXXConstructExpr *E,
@@ -5998,8 +6123,7 @@ public:
bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
private:
- static QualType GetObjectType(APValue::LValueBase B);
- bool TryEvaluateBuiltinObjectSize(const CallExpr *E);
+ bool TryEvaluateBuiltinObjectSize(const CallExpr *E, unsigned Type);
// FIXME: Missing: array subscript of vector, member of vector
};
} // end anonymous namespace
@@ -6151,8 +6275,8 @@ static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) {
APValue &V = Result.Val;
if (V.getKind() == APValue::Int)
return true;
-
- return EvaluateBuiltinConstantPForLValue(V);
+ if (V.getKind() == APValue::LValue)
+ return EvaluateBuiltinConstantPForLValue(V);
} else if (ArgType->isFloatingType() || ArgType->isAnyComplexType()) {
return Arg->isEvaluatable(Ctx);
} else if (ArgType->isPointerType() || Arg->isGLValue()) {
@@ -6171,7 +6295,7 @@ static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) {
/// Retrieves the "underlying object type" of the given expression,
/// as used by __builtin_object_size.
-QualType IntExprEvaluator::GetObjectType(APValue::LValueBase B) {
+static QualType getObjectType(APValue::LValueBase B) {
if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D))
return VD->getType();
@@ -6183,49 +6307,258 @@ QualType IntExprEvaluator::GetObjectType(APValue::LValueBase B) {
return QualType();
}
-bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) {
- LValue Base;
+/// A more selective version of E->IgnoreParenCasts for
+/// TryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only
+/// to change the type of E.
+/// Ex. For E = `(short*)((char*)(&foo))`, returns `&foo`
+///
+/// Always returns an RValue with a pointer representation.
+static const Expr *ignorePointerCastsAndParens(const Expr *E) {
+ assert(E->isRValue() && E->getType()->hasPointerRepresentation());
+ auto *NoParens = E->IgnoreParens();
+ auto *Cast = dyn_cast<CastExpr>(NoParens);
+ if (Cast == nullptr)
+ return NoParens;
+
+ // We only conservatively allow a few kinds of casts, because this code is
+ // inherently a simple solution that seeks to support the common case.
+ auto CastKind = Cast->getCastKind();
+ if (CastKind != CK_NoOp && CastKind != CK_BitCast &&
+ CastKind != CK_AddressSpaceConversion)
+ return NoParens;
+
+ auto *SubExpr = Cast->getSubExpr();
+ if (!SubExpr->getType()->hasPointerRepresentation() || !SubExpr->isRValue())
+ return NoParens;
+ return ignorePointerCastsAndParens(SubExpr);
+}
+
+/// Checks to see if the given LValue's Designator is at the end of the LValue's
+/// record layout. e.g.
+/// struct { struct { int a, b; } fst, snd; } obj;
+/// obj.fst // no
+/// obj.snd // yes
+/// obj.fst.a // no
+/// obj.fst.b // no
+/// obj.snd.a // no
+/// obj.snd.b // yes
+///
+/// Please note: this function is specialized for how __builtin_object_size
+/// views "objects".
+static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
+ assert(!LVal.Designator.Invalid);
+
+ auto IsLastFieldDecl = [&Ctx](const FieldDecl *FD) {
+ if (FD->getParent()->isUnion())
+ return true;
+ const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(FD->getParent());
+ return FD->getFieldIndex() + 1 == Layout.getFieldCount();
+ };
+
+ auto &Base = LVal.getLValueBase();
+ if (auto *ME = dyn_cast_or_null<MemberExpr>(Base.dyn_cast<const Expr *>())) {
+ if (auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
+ if (!IsLastFieldDecl(FD))
+ return false;
+ } else if (auto *IFD = dyn_cast<IndirectFieldDecl>(ME->getMemberDecl())) {
+ for (auto *FD : IFD->chain())
+ if (!IsLastFieldDecl(cast<FieldDecl>(FD)))
+ return false;
+ }
+ }
+
+ QualType BaseType = getType(Base);
+ for (int I = 0, E = LVal.Designator.Entries.size(); I != E; ++I) {
+ if (BaseType->isArrayType()) {
+ // Because __builtin_object_size treats arrays as objects, we can ignore
+ // the index iff this is the last array in the Designator.
+ if (I + 1 == E)
+ return true;
+ auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType));
+ uint64_t Index = LVal.Designator.Entries[I].ArrayIndex;
+ if (Index + 1 != CAT->getSize())
+ return false;
+ BaseType = CAT->getElementType();
+ } else if (BaseType->isAnyComplexType()) {
+ auto *CT = BaseType->castAs<ComplexType>();
+ uint64_t Index = LVal.Designator.Entries[I].ArrayIndex;
+ if (Index != 1)
+ return false;
+ BaseType = CT->getElementType();
+ } else if (auto *FD = getAsField(LVal.Designator.Entries[I])) {
+ if (!IsLastFieldDecl(FD))
+ return false;
+ BaseType = FD->getType();
+ } else {
+ assert(getAsBaseClass(LVal.Designator.Entries[I]) != nullptr &&
+ "Expecting cast to a base class");
+ return false;
+ }
+ }
+ return true;
+}
+
+/// Tests to see if the LValue has a designator (that isn't necessarily valid).
+static bool refersToCompleteObject(const LValue &LVal) {
+ if (LVal.Designator.Invalid || !LVal.Designator.Entries.empty())
+ return false;
+
+ if (!LVal.InvalidBase)
+ return true;
+
+ auto *E = LVal.Base.dyn_cast<const Expr *>();
+ (void)E;
+ assert(E != nullptr && isa<MemberExpr>(E));
+ return false;
+}
+
+/// Tries to evaluate the __builtin_object_size for @p E. If successful, returns
+/// true and stores the result in @p Size.
+///
+/// If @p WasError is non-null, this will report whether the failure to evaluate
+/// is to be treated as an Error in IntExprEvaluator.
+static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
+ EvalInfo &Info, uint64_t &Size,
+ bool *WasError = nullptr) {
+ if (WasError != nullptr)
+ *WasError = false;
+
+ auto Error = [&](const Expr *E) {
+ if (WasError != nullptr)
+ *WasError = true;
+ return false;
+ };
+
+ auto Success = [&](uint64_t S, const Expr *E) {
+ Size = S;
+ return true;
+ };
+
+ // Determine the denoted object.
+ LValue Base;
{
// The operand of __builtin_object_size is never evaluated for side-effects.
// If there are any, but we can determine the pointed-to object anyway, then
// ignore the side-effects.
SpeculativeEvaluationRAII SpeculativeEval(Info);
- if (!EvaluatePointer(E->getArg(0), Base, Info))
+ FoldOffsetRAII Fold(Info, Type & 1);
+
+ if (E->isGLValue()) {
+ // It's possible for us to be given GLValues if we're called via
+ // Expr::tryEvaluateObjectSize.
+ APValue RVal;
+ if (!EvaluateAsRValue(Info, E, RVal))
+ return false;
+ Base.setFrom(Info.Ctx, RVal);
+ } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), Base, Info))
return false;
}
- if (!Base.getLValueBase()) {
- // It is not possible to determine which objects ptr points to at compile time,
- // __builtin_object_size should return (size_t) -1 for type 0 or 1
- // and (size_t) 0 for type 2 or 3.
- llvm::APSInt TypeIntVaue;
- const Expr *ExprType = E->getArg(1);
- if (!ExprType->EvaluateAsInt(TypeIntVaue, Info.Ctx))
- return false;
- if (TypeIntVaue == 0 || TypeIntVaue == 1)
- return Success(-1, E);
- if (TypeIntVaue == 2 || TypeIntVaue == 3)
- return Success(0, E);
+ CharUnits BaseOffset = Base.getLValueOffset();
+ // If we point to before the start of the object, there are no accessible
+ // bytes.
+ if (BaseOffset.isNegative())
+ return Success(0, E);
+
+ // In the case where we're not dealing with a subobject, we discard the
+ // subobject bit.
+ bool SubobjectOnly = (Type & 1) != 0 && !refersToCompleteObject(Base);
+
+ // If Type & 1 is 0, we need to be able to statically guarantee that the bytes
+ // exist. If we can't verify the base, then we can't do that.
+ //
+ // As a special case, we produce a valid object size for an unknown object
+ // with a known designator if Type & 1 is 1. For instance:
+ //
+ // extern struct X { char buff[32]; int a, b, c; } *p;
+ // int a = __builtin_object_size(p->buff + 4, 3); // returns 28
+ // int b = __builtin_object_size(p->buff + 4, 2); // returns 0, not 40
+ //
+ // This matches GCC's behavior.
+ if (Base.InvalidBase && !SubobjectOnly)
return Error(E);
+
+ // If we're not examining only the subobject, then we reset to a complete
+ // object designator
+ //
+ // If Type is 1 and we've lost track of the subobject, just find the complete
+ // object instead. (If Type is 3, that's not correct behavior and we should
+ // return 0 instead.)
+ LValue End = Base;
+ if (!SubobjectOnly || (End.Designator.Invalid && Type == 1)) {
+ QualType T = getObjectType(End.getLValueBase());
+ if (T.isNull())
+ End.Designator.setInvalid();
+ else {
+ End.Designator = SubobjectDesignator(T);
+ End.Offset = CharUnits::Zero();
+ }
}
- QualType T = GetObjectType(Base.getLValueBase());
- if (T.isNull() ||
- T->isIncompleteType() ||
- T->isFunctionType() ||
- T->isVariablyModifiedType() ||
- T->isDependentType())
+ // If it is not possible to determine which objects ptr points to at compile
+ // time, __builtin_object_size should return (size_t) -1 for type 0 or 1
+ // and (size_t) 0 for type 2 or 3.
+ if (End.Designator.Invalid)
+ return false;
+
+ // According to the GCC documentation, we want the size of the subobject
+ // denoted by the pointer. But that's not quite right -- what we actually
+ // want is the size of the immediately-enclosing array, if there is one.
+ int64_t AmountToAdd = 1;
+ if (End.Designator.MostDerivedIsArrayElement &&
+ End.Designator.Entries.size() == End.Designator.MostDerivedPathLength) {
+ // We got a pointer to an array. Step to its end.
+ AmountToAdd = End.Designator.MostDerivedArraySize -
+ End.Designator.Entries.back().ArrayIndex;
+ } else if (End.Designator.isOnePastTheEnd()) {
+ // We're already pointing at the end of the object.
+ AmountToAdd = 0;
+ }
+
+ QualType PointeeType = End.Designator.MostDerivedType;
+ assert(!PointeeType.isNull());
+ if (PointeeType->isIncompleteType() || PointeeType->isFunctionType())
return Error(E);
- CharUnits Size = Info.Ctx.getTypeSizeInChars(T);
- CharUnits Offset = Base.getLValueOffset();
+ if (!HandleLValueArrayAdjustment(Info, E, End, End.Designator.MostDerivedType,
+ AmountToAdd))
+ return false;
- if (!Offset.isNegative() && Offset <= Size)
- Size -= Offset;
- else
- Size = CharUnits::Zero();
- return Success(Size, E);
+ auto EndOffset = End.getLValueOffset();
+
+ // The following is a moderately common idiom in C:
+ //
+ // struct Foo { int a; char c[1]; };
+ // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar));
+ // strcpy(&F->c[0], Bar);
+ //
+ // So, if we see that we're examining a 1-length (or 0-length) array at the
+ // end of a struct with an unknown base, we give up instead of breaking code
+ // that behaves this way. Note that we only do this when Type=1, because
+ // Type=3 is a lower bound, so answering conservatively is fine.
+ if (End.InvalidBase && SubobjectOnly && Type == 1 &&
+ End.Designator.Entries.size() == End.Designator.MostDerivedPathLength &&
+ End.Designator.MostDerivedIsArrayElement &&
+ End.Designator.MostDerivedArraySize < 2 &&
+ isDesignatorAtObjectEnd(Info.Ctx, End))
+ return false;
+
+ if (BaseOffset > EndOffset)
+ return Success(0, E);
+
+ return Success((EndOffset - BaseOffset).getQuantity(), E);
+}
+
+bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E,
+ unsigned Type) {
+ uint64_t Size;
+ bool WasError;
+ if (::tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size, &WasError))
+ return Success(Size, E);
+ if (WasError)
+ return Error(E);
+ return false;
}
bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
@@ -6234,17 +6567,16 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
return ExprEvaluatorBaseTy::VisitCallExpr(E);
case Builtin::BI__builtin_object_size: {
- if (TryEvaluateBuiltinObjectSize(E))
+ // The type was checked when we built the expression.
+ unsigned Type =
+ E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue();
+ assert(Type <= 3 && "unexpected type");
+
+ if (TryEvaluateBuiltinObjectSize(E, Type))
return true;
- // If evaluating the argument has side-effects, we can't determine the size
- // of the object, and so we lower it to unknown now. CodeGen relies on us to
- // handle all cases where the expression has side-effects.
- if (E->getArg(0)->HasSideEffects(Info.Ctx)) {
- if (E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue() <= 1)
- return Success(-1ULL, E);
- return Success(0, E);
- }
+ if (E->getArg(0)->HasSideEffects(Info.Ctx))
+ return Success((Type & 2) ? 0 : -1, E);
// Expression had no side effects, but we couldn't statically determine the
// size of the referenced object.
@@ -6254,10 +6586,13 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
case EvalInfo::EM_ConstantFold:
case EvalInfo::EM_EvaluateForOverflow:
case EvalInfo::EM_IgnoreSideEffects:
+ case EvalInfo::EM_DesignatorFold:
+ // Leave it to IR generation.
return Error(E);
case EvalInfo::EM_ConstantExpressionUnevaluated:
case EvalInfo::EM_PotentialConstantExpressionUnevaluated:
- return Success(-1ULL, E);
+ // Reduce it to a constant now.
+ return Success((Type & 2) ? 0 : -1, E);
}
}
@@ -6523,9 +6858,15 @@ static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx,
!LV.getLValueDesignator().isOnePastTheEnd())
return false;
+ // A pointer to an incomplete type might be past-the-end if the type's size is
+ // zero. We cannot tell because the type is incomplete.
+ QualType Ty = getType(LV.getLValueBase());
+ if (Ty->isIncompleteType())
+ return true;
+
// We're a past-the-end pointer if we point to the byte after the object,
// no matter what our type or path is.
- auto Size = Ctx.getTypeSizeInChars(getType(LV.getLValueBase()));
+ auto Size = Ctx.getTypeSizeInChars(Ty);
return LV.getLValueOffset() == Size;
}
@@ -6555,7 +6896,13 @@ class DataRecursiveIntBinOpEvaluator {
EvalResult LHSResult; // meaningful only for binary operator expression.
enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind;
- Job() : StoredInfo(nullptr) {}
+ Job() = default;
+ Job(Job &&J)
+ : E(J.E), LHSResult(J.LHSResult), Kind(J.Kind),
+ StoredInfo(J.StoredInfo), OldEvalStatus(J.OldEvalStatus) {
+ J.StoredInfo = nullptr;
+ }
+
void startSpeculativeEval(EvalInfo &Info) {
OldEvalStatus = Info.EvalStatus;
Info.EvalStatus.Diag = nullptr;
@@ -6567,7 +6914,7 @@ class DataRecursiveIntBinOpEvaluator {
}
}
private:
- EvalInfo *StoredInfo; // non-null if status changed.
+ EvalInfo *StoredInfo = nullptr; // non-null if status changed.
Expr::EvalStatus OldEvalStatus;
};
@@ -6946,7 +7293,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
LValue LHSValue, RHSValue;
bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info);
- if (!LHSOK && Info.keepEvaluatingAfterFailure())
+ if (!LHSOK && !Info.keepEvaluatingAfterFailure())
return false;
if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK)
@@ -6958,21 +7305,20 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (E->getOpcode() == BO_Sub) {
// Handle &&A - &&B.
if (!LHSValue.Offset.isZero() || !RHSValue.Offset.isZero())
- return false;
+ return Error(E);
const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr*>();
const Expr *RHSExpr = RHSValue.Base.dyn_cast<const Expr*>();
if (!LHSExpr || !RHSExpr)
- return false;
+ return Error(E);
const AddrLabelExpr *LHSAddrExpr = dyn_cast<AddrLabelExpr>(LHSExpr);
const AddrLabelExpr *RHSAddrExpr = dyn_cast<AddrLabelExpr>(RHSExpr);
if (!LHSAddrExpr || !RHSAddrExpr)
- return false;
+ return Error(E);
// Make sure both labels come from the same function.
if (LHSAddrExpr->getLabel()->getDeclContext() !=
RHSAddrExpr->getLabel()->getDeclContext())
- return false;
- Result = APValue(LHSAddrExpr, RHSAddrExpr);
- return true;
+ return Error(E);
+ return Success(APValue(LHSAddrExpr, RHSAddrExpr), E);
}
// Inequalities and subtractions between unrelated pointers have
// unspecified or undefined behavior.
@@ -7063,8 +7409,9 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
APSInt TrueResult = (LHS - RHS) / ElemSize;
APSInt Result = TrueResult.trunc(Info.Ctx.getIntWidth(E->getType()));
- if (Result.extend(65) != TrueResult)
- HandleOverflow(Info, E, TrueResult, E->getType());
+ if (Result.extend(65) != TrueResult &&
+ !HandleOverflow(Info, E, TrueResult, E->getType()))
+ return false;
return Success(Result, E);
}
@@ -7270,9 +7617,9 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
return Error(OOE);
QualType CurrentType = OOE->getTypeSourceInfo()->getType();
for (unsigned i = 0; i != n; ++i) {
- OffsetOfExpr::OffsetOfNode ON = OOE->getComponent(i);
+ OffsetOfNode ON = OOE->getComponent(i);
switch (ON.getKind()) {
- case OffsetOfExpr::OffsetOfNode::Array: {
+ case OffsetOfNode::Array: {
const Expr *Idx = OOE->getIndexExpr(ON.getArrayExprIndex());
APSInt IdxResult;
if (!EvaluateInteger(Idx, IdxResult, Info))
@@ -7286,7 +7633,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
break;
}
- case OffsetOfExpr::OffsetOfNode::Field: {
+ case OffsetOfNode::Field: {
FieldDecl *MemberDecl = ON.getField();
const RecordType *RT = CurrentType->getAs<RecordType>();
if (!RT)
@@ -7301,10 +7648,10 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) {
break;
}
- case OffsetOfExpr::OffsetOfNode::Identifier:
+ case OffsetOfNode::Identifier:
llvm_unreachable("dependent __builtin_offsetof");
- case OffsetOfExpr::OffsetOfNode::Base: {
+ case OffsetOfNode::Base: {
CXXBaseSpecifier *BaseSpec = ON.getBase();
if (BaseSpec->isVirtual())
return Error(OOE);
@@ -7350,9 +7697,10 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
return false;
if (!Result.isInt()) return Error(E);
const APSInt &Value = Result.getInt();
- if (Value.isSigned() && Value.isMinSignedValue())
- HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
- E->getType());
+ if (Value.isSigned() && Value.isMinSignedValue() &&
+ !HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
+ E->getType()))
+ return false;
return Success(-Value, E);
}
case UO_Not: {
@@ -7433,12 +7781,16 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_PointerToBoolean:
case CK_IntegralToBoolean:
case CK_FloatingToBoolean:
+ case CK_BooleanToSignedIntegral:
case CK_FloatingComplexToBoolean:
case CK_IntegralComplexToBoolean: {
bool BoolResult;
if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info))
return false;
- return Success(BoolResult, E);
+ uint64_t IntResult = BoolResult;
+ if (BoolResult && E->getCastKind() == CK_BooleanToSignedIntegral)
+ IntResult = (uint64_t)-1;
+ return Success(IntResult, E);
}
case CK_IntegralCast: {
@@ -7875,6 +8227,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_ToVoid:
case CK_VectorSplat:
case CK_IntegralCast:
+ case CK_BooleanToSignedIntegral:
case CK_IntegralToBoolean:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
@@ -8512,6 +8865,12 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result,
HandleConversionToBool(Scratch.Val, Result);
}
+static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result,
+ Expr::SideEffectsKind SEK) {
+ return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) ||
+ (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior);
+}
+
bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx,
SideEffectsKind AllowSideEffects) const {
if (!getType()->isIntegralOrEnumerationType())
@@ -8519,7 +8878,7 @@ bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx,
EvalResult ExprResult;
if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isInt() ||
- (!AllowSideEffects && ExprResult.HasSideEffects))
+ hasUnacceptableSideEffect(ExprResult, AllowSideEffects))
return false;
Result = ExprResult.Val.getInt();
@@ -8551,7 +8910,9 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
Expr::EvalStatus EStatus;
EStatus.Diag = &Notes;
- EvalInfo InitInfo(Ctx, EStatus, EvalInfo::EM_ConstantFold);
+ EvalInfo InitInfo(Ctx, EStatus, VD->isConstexpr()
+ ? EvalInfo::EM_ConstantExpression
+ : EvalInfo::EM_ConstantFold);
InitInfo.setEvaluatingDecl(VD, Value);
LValue LVal;
@@ -8580,9 +8941,10 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
/// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
/// constant folded, but discard the result.
-bool Expr::isEvaluatable(const ASTContext &Ctx) const {
+bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const {
EvalResult Result;
- return EvaluateAsRValue(Result, Ctx) && !Result.HasSideEffects;
+ return EvaluateAsRValue(Result, Ctx) &&
+ !hasUnacceptableSideEffect(Result, SEK);
}
APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx,
@@ -8677,6 +9039,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::ImaginaryLiteralClass:
case Expr::StringLiteralClass:
case Expr::ArraySubscriptExprClass:
+ case Expr::OMPArraySectionExprClass:
case Expr::MemberExprClass:
case Expr::CompoundAssignOperatorClass:
case Expr::CompoundLiteralExprClass:
@@ -8695,6 +9058,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::CXXTypeidExprClass:
case Expr::CXXUuidofExprClass:
case Expr::MSPropertyRefExprClass:
+ case Expr::MSPropertySubscriptExprClass:
case Expr::CXXNullPtrLiteralExprClass:
case Expr::UserDefinedLiteralClass:
case Expr::CXXThisExprClass:
@@ -8740,6 +9104,8 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::AtomicExprClass:
case Expr::LambdaExprClass:
case Expr::CXXFoldExprClass:
+ case Expr::CoawaitExprClass:
+ case Expr::CoyieldExprClass:
return ICEDiag(IK_NotICE, E->getLocStart());
case Expr::InitListExprClass: {
@@ -8825,6 +9191,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case UO_PreDec:
case UO_AddrOf:
case UO_Deref:
+ case UO_Coawait:
// C99 6.6/3 allows increment and decrement within unevaluated
// subexpressions of constant expressions, but they can never be ICEs
// because an ICE cannot contain an lvalue operand.
@@ -9078,7 +9445,11 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx,
if (!isIntegerConstantExpr(Ctx, Loc))
return false;
- if (!EvaluateAsInt(Value, Ctx))
+ // The only possible side-effects here are due to UB discovered in the
+ // evaluation (for instance, INT_MAX + 1). In such a case, we are still
+ // required to treat the expression as an ICE, so we produce the folded
+ // value.
+ if (!EvaluateAsInt(Value, Ctx, SE_AllowSideEffects))
llvm_unreachable("ICE cannot be evaluated!");
return true;
}
@@ -9172,7 +9543,7 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
HandleConstructorCall(Loc, This, Args, CD, Info, Scratch);
} else
HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr,
- Args, FD->getBody(), Info, Scratch);
+ Args, FD->getBody(), Info, Scratch, nullptr);
return Diags.empty();
}
@@ -9200,3 +9571,13 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E,
Evaluate(ResultScratch, Info, E);
return Diags.empty();
}
+
+bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
+ unsigned Type) const {
+ if (!getType()->isPointerType())
+ return false;
+
+ Expr::EvalStatus Status;
+ EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold);
+ return ::tryEvaluateBuiltinObjectSize(this, Type, Info, Result);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp b/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp
new file mode 100644
index 0000000..0936a81
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/ExprObjC.cpp
@@ -0,0 +1,360 @@
+//===--- ExprObjC.cpp - (ObjC) Expression AST Node Implementation ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the subclesses of Expr class declared in ExprObjC.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ExprObjC.h"
+
+#include "clang/AST/ASTContext.h"
+
+using namespace clang;
+
+ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef<Expr *> Elements, QualType T,
+ ObjCMethodDecl *Method, SourceRange SR)
+ : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method) {
+ Expr **SaveElements = getElements();
+ for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
+ if (Elements[I]->isTypeDependent() || Elements[I]->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (Elements[I]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (Elements[I]->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ SaveElements[I] = Elements[I];
+ }
+}
+
+ObjCArrayLiteral *ObjCArrayLiteral::Create(const ASTContext &C,
+ ArrayRef<Expr *> Elements,
+ QualType T, ObjCMethodDecl *Method,
+ SourceRange SR) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Elements.size()));
+ return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR);
+}
+
+ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(const ASTContext &C,
+ unsigned NumElements) {
+
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumElements));
+ return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements);
+}
+
+ObjCDictionaryLiteral::ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
+ bool HasPackExpansions, QualType T,
+ ObjCMethodDecl *method,
+ SourceRange SR)
+ : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR),
+ DictWithObjectsMethod(method) {
+ KeyValuePair *KeyValues = getTrailingObjects<KeyValuePair>();
+ ExpansionData *Expansions =
+ HasPackExpansions ? getTrailingObjects<ExpansionData>() : nullptr;
+ for (unsigned I = 0; I < NumElements; I++) {
+ if (VK[I].Key->isTypeDependent() || VK[I].Key->isValueDependent() ||
+ VK[I].Value->isTypeDependent() || VK[I].Value->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (VK[I].Key->isInstantiationDependent() ||
+ VK[I].Value->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (VK[I].EllipsisLoc.isInvalid() &&
+ (VK[I].Key->containsUnexpandedParameterPack() ||
+ VK[I].Value->containsUnexpandedParameterPack()))
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ KeyValues[I].Key = VK[I].Key;
+ KeyValues[I].Value = VK[I].Value;
+ if (Expansions) {
+ Expansions[I].EllipsisLoc = VK[I].EllipsisLoc;
+ if (VK[I].NumExpansions)
+ Expansions[I].NumExpansionsPlusOne = *VK[I].NumExpansions + 1;
+ else
+ Expansions[I].NumExpansionsPlusOne = 0;
+ }
+ }
+}
+
+ObjCDictionaryLiteral *
+ObjCDictionaryLiteral::Create(const ASTContext &C,
+ ArrayRef<ObjCDictionaryElement> VK,
+ bool HasPackExpansions, QualType T,
+ ObjCMethodDecl *method, SourceRange SR) {
+ void *Mem = C.Allocate(totalSizeToAlloc<KeyValuePair, ExpansionData>(
+ VK.size(), HasPackExpansions ? VK.size() : 0));
+ return new (Mem) ObjCDictionaryLiteral(VK, HasPackExpansions, T, method, SR);
+}
+
+ObjCDictionaryLiteral *
+ObjCDictionaryLiteral::CreateEmpty(const ASTContext &C, unsigned NumElements,
+ bool HasPackExpansions) {
+ void *Mem = C.Allocate(totalSizeToAlloc<KeyValuePair, ExpansionData>(
+ NumElements, HasPackExpansions ? NumElements : 0));
+ return new (Mem)
+ ObjCDictionaryLiteral(EmptyShell(), NumElements, HasPackExpansions);
+}
+
+QualType ObjCPropertyRefExpr::getReceiverType(const ASTContext &ctx) const {
+ if (isClassReceiver())
+ return ctx.getObjCInterfaceType(getClassReceiver());
+
+ if (isSuperReceiver())
+ return getSuperReceiverType();
+
+ return getBase()->getType();
+}
+
+ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
+ SourceLocation LBracLoc,
+ SourceLocation SuperLoc, bool IsInstanceSuper,
+ QualType SuperType, Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK,
+ ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc, bool isImplicit)
+ : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary,
+ /*TypeDependent=*/false, /*ValueDependent=*/false,
+ /*InstantiationDependent=*/false,
+ /*ContainsUnexpandedParameterPack=*/false),
+ SelectorOrMethod(
+ reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())),
+ Kind(IsInstanceSuper ? SuperInstance : SuperClass),
+ HasMethod(Method != nullptr), IsDelegateInitCall(false),
+ IsImplicit(isImplicit), SuperLoc(SuperLoc), LBracLoc(LBracLoc),
+ RBracLoc(RBracLoc) {
+ initArgsAndSelLocs(Args, SelLocs, SelLocsK);
+ setReceiverPointer(SuperType.getAsOpaquePtr());
+}
+
+ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
+ SourceLocation LBracLoc,
+ TypeSourceInfo *Receiver, Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK,
+ ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc, bool isImplicit)
+ : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(),
+ T->isDependentType(), T->isInstantiationDependentType(),
+ T->containsUnexpandedParameterPack()),
+ SelectorOrMethod(
+ reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())),
+ Kind(Class), HasMethod(Method != nullptr), IsDelegateInitCall(false),
+ IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) {
+ initArgsAndSelLocs(Args, SelLocs, SelLocsK);
+ setReceiverPointer(Receiver);
+}
+
+ObjCMessageExpr::ObjCMessageExpr(QualType T, ExprValueKind VK,
+ SourceLocation LBracLoc, Expr *Receiver,
+ Selector Sel, ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK,
+ ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc, bool isImplicit)
+ : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary,
+ Receiver->isTypeDependent(), Receiver->isTypeDependent(),
+ Receiver->isInstantiationDependent(),
+ Receiver->containsUnexpandedParameterPack()),
+ SelectorOrMethod(
+ reinterpret_cast<uintptr_t>(Method ? Method : Sel.getAsOpaquePtr())),
+ Kind(Instance), HasMethod(Method != nullptr), IsDelegateInitCall(false),
+ IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) {
+ initArgsAndSelLocs(Args, SelLocs, SelLocsK);
+ setReceiverPointer(Receiver);
+}
+
+void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args,
+ ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK) {
+ setNumArgs(Args.size());
+ Expr **MyArgs = getArgs();
+ for (unsigned I = 0; I != Args.size(); ++I) {
+ if (Args[I]->isTypeDependent())
+ ExprBits.TypeDependent = true;
+ if (Args[I]->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (Args[I]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (Args[I]->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ MyArgs[I] = Args[I];
+ }
+
+ SelLocsKind = SelLocsK;
+ if (!isImplicit()) {
+ if (SelLocsK == SelLoc_NonStandard)
+ std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
+ }
+}
+
+ObjCMessageExpr *
+ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK,
+ SourceLocation LBracLoc, SourceLocation SuperLoc,
+ bool IsInstanceSuper, QualType SuperType, Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc, bool isImplicit) {
+ assert((!SelLocs.empty() || isImplicit) &&
+ "No selector locs for non-implicit message");
+ ObjCMessageExpr *Mem;
+ SelectorLocationsKind SelLocsK = SelectorLocationsKind();
+ if (isImplicit)
+ Mem = alloc(Context, Args.size(), 0);
+ else
+ Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
+ return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper,
+ SuperType, Sel, SelLocs, SelLocsK, Method,
+ Args, RBracLoc, isImplicit);
+}
+
+ObjCMessageExpr *
+ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK,
+ SourceLocation LBracLoc, TypeSourceInfo *Receiver,
+ Selector Sel, ArrayRef<SourceLocation> SelLocs,
+ ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc, bool isImplicit) {
+ assert((!SelLocs.empty() || isImplicit) &&
+ "No selector locs for non-implicit message");
+ ObjCMessageExpr *Mem;
+ SelectorLocationsKind SelLocsK = SelectorLocationsKind();
+ if (isImplicit)
+ Mem = alloc(Context, Args.size(), 0);
+ else
+ Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
+ return new (Mem)
+ ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method,
+ Args, RBracLoc, isImplicit);
+}
+
+ObjCMessageExpr *
+ObjCMessageExpr::Create(const ASTContext &Context, QualType T, ExprValueKind VK,
+ SourceLocation LBracLoc, Expr *Receiver, Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ ObjCMethodDecl *Method, ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc, bool isImplicit) {
+ assert((!SelLocs.empty() || isImplicit) &&
+ "No selector locs for non-implicit message");
+ ObjCMessageExpr *Mem;
+ SelectorLocationsKind SelLocsK = SelectorLocationsKind();
+ if (isImplicit)
+ Mem = alloc(Context, Args.size(), 0);
+ else
+ Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
+ return new (Mem)
+ ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLocs, SelLocsK, Method,
+ Args, RBracLoc, isImplicit);
+}
+
+ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(const ASTContext &Context,
+ unsigned NumArgs,
+ unsigned NumStoredSelLocs) {
+ ObjCMessageExpr *Mem = alloc(Context, NumArgs, NumStoredSelLocs);
+ return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs);
+}
+
+ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C,
+ ArrayRef<Expr *> Args,
+ SourceLocation RBraceLoc,
+ ArrayRef<SourceLocation> SelLocs,
+ Selector Sel,
+ SelectorLocationsKind &SelLocsK) {
+ SelLocsK = hasStandardSelectorLocs(Sel, SelLocs, Args, RBraceLoc);
+ unsigned NumStoredSelLocs =
+ (SelLocsK == SelLoc_NonStandard) ? SelLocs.size() : 0;
+ return alloc(C, Args.size(), NumStoredSelLocs);
+}
+
+ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, unsigned NumArgs,
+ unsigned NumStoredSelLocs) {
+ return (ObjCMessageExpr *)C.Allocate(
+ totalSizeToAlloc<void *, SourceLocation>(NumArgs + 1, NumStoredSelLocs),
+ llvm::AlignOf<ObjCMessageExpr>::Alignment);
+}
+
+void ObjCMessageExpr::getSelectorLocs(
+ SmallVectorImpl<SourceLocation> &SelLocs) const {
+ for (unsigned i = 0, e = getNumSelectorLocs(); i != e; ++i)
+ SelLocs.push_back(getSelectorLoc(i));
+}
+
+SourceRange ObjCMessageExpr::getReceiverRange() const {
+ switch (getReceiverKind()) {
+ case Instance:
+ return getInstanceReceiver()->getSourceRange();
+
+ case Class:
+ return getClassReceiverTypeInfo()->getTypeLoc().getSourceRange();
+
+ case SuperInstance:
+ case SuperClass:
+ return getSuperLoc();
+ }
+
+ llvm_unreachable("Invalid ReceiverKind!");
+}
+
+Selector ObjCMessageExpr::getSelector() const {
+ if (HasMethod)
+ return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod)
+ ->getSelector();
+ return Selector(SelectorOrMethod);
+}
+
+QualType ObjCMessageExpr::getReceiverType() const {
+ switch (getReceiverKind()) {
+ case Instance:
+ return getInstanceReceiver()->getType();
+ case Class:
+ return getClassReceiver();
+ case SuperInstance:
+ case SuperClass:
+ return getSuperType();
+ }
+
+ llvm_unreachable("unexpected receiver kind");
+}
+
+ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
+ QualType T = getReceiverType();
+
+ if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
+ return Ptr->getInterfaceDecl();
+
+ if (const ObjCObjectType *Ty = T->getAs<ObjCObjectType>())
+ return Ty->getInterface();
+
+ return nullptr;
+}
+
+Stmt::child_range ObjCMessageExpr::children() {
+ Stmt **begin;
+ if (getReceiverKind() == Instance)
+ begin = reinterpret_cast<Stmt **>(getTrailingObjects<void *>());
+ else
+ begin = reinterpret_cast<Stmt **>(getArgs());
+ return child_range(begin,
+ reinterpret_cast<Stmt **>(getArgs() + getNumArgs()));
+}
+
+StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
+ switch (getBridgeKind()) {
+ case OBC_Bridge:
+ return "__bridge";
+ case OBC_BridgeTransfer:
+ return "__bridge_transfer";
+ case OBC_BridgeRetained:
+ return "__bridge_retained";
+ }
+
+ llvm_unreachable("Invalid BridgeKind!");
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
index 1c82c35..e3de8c5 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExternalASTSource.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/Module.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
@@ -27,9 +28,19 @@ ExternalASTSource::getSourceDescriptor(unsigned ID) {
return None;
}
-ExternalASTSource::ASTSourceDescriptor
-ExternalASTSource::getSourceDescriptor(const Module &M) {
- return ASTSourceDescriptor();
+ExternalASTSource::ASTSourceDescriptor::ASTSourceDescriptor(const Module &M)
+ : Signature(M.Signature), ClangModule(&M) {
+ if (M.Directory)
+ Path = M.Directory->getName();
+ if (auto *File = M.getASTFile())
+ ASTFile = File->getName();
+}
+
+std::string ExternalASTSource::ASTSourceDescriptor::getModuleName() const {
+ if (ClangModule)
+ return ClangModule->Name;
+ else
+ return PCHModuleName;
}
void ExternalASTSource::FindFileRegionDecls(FileID File, unsigned Offset,
@@ -92,17 +103,13 @@ ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
return false;
}
-void ExternalASTSource::completeVisibleDeclsMap(const DeclContext *DC) {
-}
+void ExternalASTSource::completeVisibleDeclsMap(const DeclContext *DC) {}
-ExternalLoadResult
-ExternalASTSource::FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Result) {
- return ELR_AlreadyLoaded;
-}
+void ExternalASTSource::FindExternalLexicalDecls(
+ const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Result) {}
-void ExternalASTSource::getMemoryBufferSizes(MemoryBufferSizes &sizes) const { }
+void ExternalASTSource::getMemoryBufferSizes(MemoryBufferSizes &sizes) const {}
uint32_t ExternalASTSource::incrementGeneration(ASTContext &C) {
uint32_t OldGeneration = CurrentGeneration;
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
index 7503cbf..8a2cc0f 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
@@ -149,6 +149,20 @@ public:
return nullptr;
}
+ void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
+ TypedefNameDecl *DD) override {}
+
+ TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override {
+ return nullptr;
+ }
+
+ void addDeclaratorForUnnamedTagDecl(TagDecl *TD,
+ DeclaratorDecl *DD) override {}
+
+ DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override {
+ return nullptr;
+ }
+
MangleNumberingContext *createMangleNumberingContext() const override {
return new ItaniumNumberingContext();
}
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
index dac803e..3f6b682 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
@@ -174,8 +174,6 @@ public:
void mangleStringLiteral(const StringLiteral *, raw_ostream &) override;
- void mangleCXXVTableBitSet(const CXXRecordDecl *RD, raw_ostream &) override;
-
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
// Lambda closure types are already numbered.
if (isLambda(ND))
@@ -379,8 +377,8 @@ private:
void mangleType(const TagType*);
void mangleType(TemplateName);
- void mangleBareFunctionType(const FunctionType *T,
- bool MangleReturnType);
+ void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType,
+ const FunctionDecl *FD = nullptr);
void mangleNeonVectorType(const VectorType *T);
void mangleAArch64NeonVectorType(const VectorType *T);
@@ -397,7 +395,8 @@ private:
void mangleCXXCtorType(CXXCtorType T);
void mangleCXXDtorType(CXXDtorType T);
- void mangleTemplateArgs(const ASTTemplateArgumentListInfo &TemplateArgs);
+ void mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs,
+ unsigned NumTemplateArgs);
void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
void mangleTemplateArgs(const TemplateArgumentList &AL);
@@ -525,7 +524,7 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
}
mangleBareFunctionType(FD->getType()->getAs<FunctionType>(),
- MangleReturnType);
+ MangleReturnType, FD);
}
static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
@@ -700,8 +699,7 @@ void CXXNameMangler::mangleFloat(const llvm::APFloat &f) {
assert(numCharacters != 0);
// Allocate a buffer of the right number of characters.
- SmallVector<char, 20> buffer;
- buffer.set_size(numCharacters);
+ SmallVector<char, 20> buffer(numCharacters);
// Fill the buffer left-to-right.
for (unsigned stringIndex = 0; stringIndex != numCharacters; ++stringIndex) {
@@ -1020,7 +1018,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
unsigned UnnamedMangle = getASTContext().getManglingNumber(TD);
Out << "Ut";
if (UnnamedMangle > 1)
- Out << llvm::utostr(UnnamedMangle - 2);
+ Out << UnnamedMangle - 2;
Out << '_';
break;
}
@@ -1285,7 +1283,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
Out << "Ul";
const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()->
getAs<FunctionProtoType>();
- mangleBareFunctionType(Proto, /*MangleReturnType=*/false);
+ mangleBareFunctionType(Proto, /*MangleReturnType=*/false,
+ Lambda->getLambdaStaticInvoker());
Out << "E";
// The number is omitted for the first closure type with a given
@@ -1510,6 +1509,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
case Type::Atomic:
+ case Type::Pipe:
llvm_unreachable("type is illegal as a nested name specifier");
case Type::SubstTemplateTypeParmPack:
@@ -1756,6 +1756,9 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
// The conditional operator can't be overloaded, but we still handle it when
// mangling expressions.
case OO_Conditional: Out << "qu"; break;
+ // Proposal on cxx-abi-dev, 2015-10-21.
+ // ::= aw # co_await
+ case OO_Coawait: Out << "aw"; break;
case OO_None:
case NUM_OVERLOADED_OPERATORS:
@@ -1988,34 +1991,79 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
// ::= u <source-name> # vendor extended type
switch (T->getKind()) {
- case BuiltinType::Void: Out << 'v'; break;
- case BuiltinType::Bool: Out << 'b'; break;
- case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'c'; break;
- case BuiltinType::UChar: Out << 'h'; break;
- case BuiltinType::UShort: Out << 't'; break;
- case BuiltinType::UInt: Out << 'j'; break;
- case BuiltinType::ULong: Out << 'm'; break;
- case BuiltinType::ULongLong: Out << 'y'; break;
- case BuiltinType::UInt128: Out << 'o'; break;
- case BuiltinType::SChar: Out << 'a'; break;
+ case BuiltinType::Void:
+ Out << 'v';
+ break;
+ case BuiltinType::Bool:
+ Out << 'b';
+ break;
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ Out << 'c';
+ break;
+ case BuiltinType::UChar:
+ Out << 'h';
+ break;
+ case BuiltinType::UShort:
+ Out << 't';
+ break;
+ case BuiltinType::UInt:
+ Out << 'j';
+ break;
+ case BuiltinType::ULong:
+ Out << 'm';
+ break;
+ case BuiltinType::ULongLong:
+ Out << 'y';
+ break;
+ case BuiltinType::UInt128:
+ Out << 'o';
+ break;
+ case BuiltinType::SChar:
+ Out << 'a';
+ break;
case BuiltinType::WChar_S:
- case BuiltinType::WChar_U: Out << 'w'; break;
- case BuiltinType::Char16: Out << "Ds"; break;
- case BuiltinType::Char32: Out << "Di"; break;
- case BuiltinType::Short: Out << 's'; break;
- case BuiltinType::Int: Out << 'i'; break;
- case BuiltinType::Long: Out << 'l'; break;
- case BuiltinType::LongLong: Out << 'x'; break;
- case BuiltinType::Int128: Out << 'n'; break;
- case BuiltinType::Half: Out << "Dh"; break;
- case BuiltinType::Float: Out << 'f'; break;
- case BuiltinType::Double: Out << 'd'; break;
+ case BuiltinType::WChar_U:
+ Out << 'w';
+ break;
+ case BuiltinType::Char16:
+ Out << "Ds";
+ break;
+ case BuiltinType::Char32:
+ Out << "Di";
+ break;
+ case BuiltinType::Short:
+ Out << 's';
+ break;
+ case BuiltinType::Int:
+ Out << 'i';
+ break;
+ case BuiltinType::Long:
+ Out << 'l';
+ break;
+ case BuiltinType::LongLong:
+ Out << 'x';
+ break;
+ case BuiltinType::Int128:
+ Out << 'n';
+ break;
+ case BuiltinType::Half:
+ Out << "Dh";
+ break;
+ case BuiltinType::Float:
+ Out << 'f';
+ break;
+ case BuiltinType::Double:
+ Out << 'd';
+ break;
case BuiltinType::LongDouble:
Out << (getASTContext().getTargetInfo().useFloat128ManglingForLongDouble()
? 'g'
: 'e');
break;
- case BuiltinType::NullPtr: Out << "Dn"; break;
+ case BuiltinType::NullPtr:
+ Out << "Dn";
+ break;
#define BUILTIN_TYPE(Id, SingletonId)
#define PLACEHOLDER_TYPE(Id, SingletonId) \
@@ -2023,17 +2071,69 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
#include "clang/AST/BuiltinTypes.def"
case BuiltinType::Dependent:
llvm_unreachable("mangling a placeholder type");
- case BuiltinType::ObjCId: Out << "11objc_object"; break;
- case BuiltinType::ObjCClass: Out << "10objc_class"; break;
- case BuiltinType::ObjCSel: Out << "13objc_selector"; break;
- case BuiltinType::OCLImage1d: Out << "11ocl_image1d"; break;
- case BuiltinType::OCLImage1dArray: Out << "16ocl_image1darray"; break;
- case BuiltinType::OCLImage1dBuffer: Out << "17ocl_image1dbuffer"; break;
- case BuiltinType::OCLImage2d: Out << "11ocl_image2d"; break;
- case BuiltinType::OCLImage2dArray: Out << "16ocl_image2darray"; break;
- case BuiltinType::OCLImage3d: Out << "11ocl_image3d"; break;
- case BuiltinType::OCLSampler: Out << "11ocl_sampler"; break;
- case BuiltinType::OCLEvent: Out << "9ocl_event"; break;
+ case BuiltinType::ObjCId:
+ Out << "11objc_object";
+ break;
+ case BuiltinType::ObjCClass:
+ Out << "10objc_class";
+ break;
+ case BuiltinType::ObjCSel:
+ Out << "13objc_selector";
+ break;
+ case BuiltinType::OCLImage1d:
+ Out << "11ocl_image1d";
+ break;
+ case BuiltinType::OCLImage1dArray:
+ Out << "16ocl_image1darray";
+ break;
+ case BuiltinType::OCLImage1dBuffer:
+ Out << "17ocl_image1dbuffer";
+ break;
+ case BuiltinType::OCLImage2d:
+ Out << "11ocl_image2d";
+ break;
+ case BuiltinType::OCLImage2dArray:
+ Out << "16ocl_image2darray";
+ break;
+ case BuiltinType::OCLImage2dDepth:
+ Out << "16ocl_image2ddepth";
+ break;
+ case BuiltinType::OCLImage2dArrayDepth:
+ Out << "21ocl_image2darraydepth";
+ break;
+ case BuiltinType::OCLImage2dMSAA:
+ Out << "15ocl_image2dmsaa";
+ break;
+ case BuiltinType::OCLImage2dArrayMSAA:
+ Out << "20ocl_image2darraymsaa";
+ break;
+ case BuiltinType::OCLImage2dMSAADepth:
+ Out << "20ocl_image2dmsaadepth";
+ break;
+ case BuiltinType::OCLImage2dArrayMSAADepth:
+ Out << "35ocl_image2darraymsaadepth";
+ break;
+ case BuiltinType::OCLImage3d:
+ Out << "11ocl_image3d";
+ break;
+ case BuiltinType::OCLSampler:
+ Out << "11ocl_sampler";
+ break;
+ case BuiltinType::OCLEvent:
+ Out << "9ocl_event";
+ break;
+ case BuiltinType::OCLClkEvent:
+ Out << "12ocl_clkevent";
+ break;
+ case BuiltinType::OCLQueue:
+ Out << "9ocl_queue";
+ break;
+ case BuiltinType::OCLNDRange:
+ Out << "11ocl_ndrange";
+ break;
+ case BuiltinType::OCLReserveID:
+ Out << "13ocl_reserveid";
+ break;
}
}
@@ -2056,11 +2156,26 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {
Out << 'E';
}
+
void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {
- llvm_unreachable("Can't mangle K&R function prototypes");
+ // Function types without prototypes can arise when mangling a function type
+ // within an overloadable function in C. We mangle these as the absence of any
+ // parameter types (not even an empty parameter list).
+ Out << 'F';
+
+ FunctionTypeDepthState saved = FunctionTypeDepth.push();
+
+ FunctionTypeDepth.enterResultType();
+ mangleType(T->getReturnType());
+ FunctionTypeDepth.leaveResultType();
+
+ FunctionTypeDepth.pop(saved);
+ Out << 'E';
}
+
void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
- bool MangleReturnType) {
+ bool MangleReturnType,
+ const FunctionDecl *FD) {
// We should never be mangling something without a prototype.
const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
@@ -2083,8 +2198,19 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
return;
}
- for (const auto &Arg : Proto->param_types())
- mangleType(Context.getASTContext().getSignatureParameterType(Arg));
+ assert(!FD || FD->getNumParams() == Proto->getNumParams());
+ for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) {
+ const auto &ParamTy = Proto->getParamType(I);
+ mangleType(Context.getASTContext().getSignatureParameterType(ParamTy));
+
+ if (FD) {
+ if (auto *Attr = FD->getParamDecl(I)->getAttr<PassObjectSizeAttr>()) {
+ // Attr can only take 1 character, so we can hardcode the length below.
+ assert(Attr->getType() <= 9 && Attr->getType() >= 0);
+ Out << "U17pass_object_size" << Attr->getType();
+ }
+ }
+ }
FunctionTypeDepth.pop(saved);
@@ -2325,7 +2451,7 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) {
EltName = mangleAArch64VectorBase(cast<BuiltinType>(EltType));
std::string TypeName =
- ("__" + EltName + "x" + llvm::utostr(T->getNumElements()) + "_t").str();
+ ("__" + EltName + "x" + Twine(T->getNumElements()) + "_t").str();
Out << TypeName.length() << TypeName;
}
@@ -2392,7 +2518,6 @@ void CXXNameMangler::mangleType(const ObjCObjectType *T) {
StringRef name = I->getName();
QualOS << name.size() << name;
}
- QualOS.flush();
Out << 'U' << QualStr.size() << QualStr;
}
@@ -2543,9 +2668,11 @@ void CXXNameMangler::mangleType(const UnaryTransformType *T) {
void CXXNameMangler::mangleType(const AutoType *T) {
QualType D = T->getDeducedType();
// <builtin-type> ::= Da # dependent auto
- if (D.isNull())
+ if (D.isNull()) {
+ assert(T->getKeyword() != AutoTypeKeyword::GNUAutoType &&
+ "shouldn't need to mangle __auto_type!");
Out << (T->isDecltypeAuto() ? "Dc" : "Da");
- else
+ } else
mangleType(D);
}
@@ -2556,6 +2683,13 @@ void CXXNameMangler::mangleType(const AtomicType *T) {
mangleType(T->getValueType());
}
+void CXXNameMangler::mangleType(const PipeType *T) {
+ // Pipe type mangling rules are described in SPIR 2.0 specification
+ // A.1 Data types and A.3 Summary of changes
+ // <type> ::= 8ocl_pipe
+ Out << "8ocl_pipe";
+}
+
void CXXNameMangler::mangleIntegerLiteral(QualType T,
const llvm::APSInt &Value) {
// <expr-primary> ::= L <type> <value number> E # integer literal
@@ -2699,7 +2833,9 @@ recurse:
case Expr::ParenListExprClass:
case Expr::LambdaExprClass:
case Expr::MSPropertyRefExprClass:
+ case Expr::MSPropertySubscriptExprClass:
case Expr::TypoExprClass: // This should no longer exist in the AST by now.
+ case Expr::OMPArraySectionExprClass:
llvm_unreachable("unexpected statement kind");
// FIXME: invent manglings for all these.
@@ -2908,7 +3044,7 @@ recurse:
ME->isArrow(), ME->getQualifier(), nullptr,
ME->getMemberName(), Arity);
if (ME->hasExplicitTemplateArgs())
- mangleTemplateArgs(ME->getExplicitTemplateArgs());
+ mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs());
break;
}
@@ -2920,7 +3056,7 @@ recurse:
ME->getFirstQualifierFoundInScope(),
ME->getMember(), Arity);
if (ME->hasExplicitTemplateArgs())
- mangleTemplateArgs(ME->getExplicitTemplateArgs());
+ mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs());
break;
}
@@ -2932,7 +3068,7 @@ recurse:
// base-unresolved-name, where <template-args> are just tacked
// onto the end.
if (ULE->hasExplicitTemplateArgs())
- mangleTemplateArgs(ULE->getExplicitTemplateArgs());
+ mangleTemplateArgs(ULE->getTemplateArgs(), ULE->getNumTemplateArgs());
break;
}
@@ -3254,7 +3390,7 @@ recurse:
// base-unresolved-name, where <template-args> are just tacked
// onto the end.
if (DRE->hasExplicitTemplateArgs())
- mangleTemplateArgs(DRE->getExplicitTemplateArgs());
+ mangleTemplateArgs(DRE->getTemplateArgs(), DRE->getNumTemplateArgs());
break;
}
@@ -3350,8 +3486,17 @@ recurse:
break;
case Expr::SizeOfPackExprClass: {
+ auto *SPE = cast<SizeOfPackExpr>(E);
+ if (SPE->isPartiallySubstituted()) {
+ Out << "sP";
+ for (const auto &A : SPE->getPartialArguments())
+ mangleTemplateArg(A);
+ Out << "E";
+ break;
+ }
+
Out << "sZ";
- const NamedDecl *Pack = cast<SizeOfPackExpr>(E)->getPack();
+ const NamedDecl *Pack = SPE->getPack();
if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack))
mangleTemplateParameter(TTP->getIndex());
else if (const NonTypeTemplateParmDecl *NTTP
@@ -3394,6 +3539,18 @@ recurse:
case Expr::CXXThisExprClass:
Out << "fpT";
break;
+
+ case Expr::CoawaitExprClass:
+ // FIXME: Propose a non-vendor mangling.
+ Out << "v18co_await";
+ mangleExpression(cast<CoawaitExpr>(E)->getOperand());
+ break;
+
+ case Expr::CoyieldExprClass:
+ // FIXME: Propose a non-vendor mangling.
+ Out << "v18co_yield";
+ mangleExpression(cast<CoawaitExpr>(E)->getOperand());
+ break;
}
}
@@ -3501,12 +3658,12 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
}
}
-void CXXNameMangler::mangleTemplateArgs(
- const ASTTemplateArgumentListInfo &TemplateArgs) {
+void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs,
+ unsigned NumTemplateArgs) {
// <template-args> ::= I <template-arg>+ E
Out << 'I';
- for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i)
- mangleTemplateArg(TemplateArgs.getTemplateArgs()[i].getArgument());
+ for (unsigned i = 0; i != NumTemplateArgs; ++i)
+ mangleTemplateArg(TemplateArgs[i].getArgument());
Out << 'E';
}
@@ -4085,21 +4242,6 @@ void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) {
mangleCXXRTTIName(Ty, Out);
}
-void ItaniumMangleContextImpl::mangleCXXVTableBitSet(const CXXRecordDecl *RD,
- raw_ostream &Out) {
- if (!RD->isExternallyVisible()) {
- // This part of the identifier needs to be unique across all translation
- // units in the linked program. The scheme fails if multiple translation
- // units are compiled using the same relative source file path, or if
- // multiple translation units are built from the same source file.
- SourceManager &SM = getASTContext().getSourceManager();
- Out << "[" << SM.getFileEntryForID(SM.getMainFileID())->getName() << "]";
- }
-
- CXXNameMangler Mangler(*this, Out);
- Mangler.mangleType(QualType(RD->getTypeForDecl(), 0));
-}
-
void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_ostream &) {
llvm_unreachable("Can't mangle string literals");
}
@@ -4108,4 +4250,3 @@ ItaniumMangleContext *
ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
return new ItaniumMangleContextImpl(Context, Diags);
}
-
diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
index 1a061c4..014338f 100644
--- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp
@@ -206,7 +206,6 @@ void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
SmallString<64> Buffer;
llvm::raw_svector_ostream Out(Buffer);
mangleCXXCtor(CD, CT, Out);
- Out.flush();
mangleFunctionBlock(*this, Buffer, BD, ResStream);
}
@@ -216,7 +215,6 @@ void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
SmallString<64> Buffer;
llvm::raw_svector_ostream Out(Buffer);
mangleCXXDtor(DD, DT, Out);
- Out.flush();
mangleFunctionBlock(*this, Buffer, BD, ResStream);
}
@@ -253,7 +251,6 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
}
}
}
- Stream.flush();
mangleFunctionBlock(*this, Buffer, BD, Out);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
index aba6796..6ba31cc 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftCXXABI.cpp
@@ -70,6 +70,11 @@ class MicrosoftCXXABI : public CXXABI {
llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *>
CtorToDefaultArgExpr;
+ llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *>
+ UnnamedTagDeclToDeclaratorDecl;
+ llvm::SmallDenseMap<TagDecl *, TypedefNameDecl *>
+ UnnamedTagDeclToTypedefNameDecl;
+
public:
MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
@@ -84,17 +89,7 @@ public:
}
bool isNearlyEmpty(const CXXRecordDecl *RD) const override {
- // FIXME: Audit the corners
- if (!RD->isDynamicClass())
- return false;
-
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
-
- // In the Microsoft ABI, classes can have one or two vtable pointers.
- CharUnits PointerSize =
- Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
- return Layout.getNonVirtualSize() == PointerSize ||
- Layout.getNonVirtualSize() == PointerSize * 2;
+ llvm_unreachable("unapplicable to the MS ABI");
}
void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
@@ -120,6 +115,34 @@ public:
RecordToCopyCtor[RD] = CD;
}
+ void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
+ TypedefNameDecl *DD) override {
+ TD = TD->getCanonicalDecl();
+ DD = cast<TypedefNameDecl>(DD->getCanonicalDecl());
+ TypedefNameDecl *&I = UnnamedTagDeclToTypedefNameDecl[TD];
+ if (!I)
+ I = DD;
+ }
+
+ TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override {
+ return UnnamedTagDeclToTypedefNameDecl.lookup(
+ const_cast<TagDecl *>(TD->getCanonicalDecl()));
+ }
+
+ void addDeclaratorForUnnamedTagDecl(TagDecl *TD,
+ DeclaratorDecl *DD) override {
+ TD = TD->getCanonicalDecl();
+ DD = cast<DeclaratorDecl>(DD->getCanonicalDecl());
+ DeclaratorDecl *&I = UnnamedTagDeclToDeclaratorDecl[TD];
+ if (!I)
+ I = DD;
+ }
+
+ DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override {
+ return UnnamedTagDeclToDeclaratorDecl.lookup(
+ const_cast<TagDecl *>(TD->getCanonicalDecl()));
+ }
+
MangleNumberingContext *createMangleNumberingContext() const override {
return new MicrosoftNumberingContext();
}
diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
index 48a8fa5..4a45f9e 100644
--- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp
@@ -28,6 +28,7 @@
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/JamCRC.h"
using namespace clang;
@@ -126,8 +127,6 @@ public:
CXXCtorType CT, uint32_t Size, uint32_t NVOffset,
int32_t VBPtrOffset, uint32_t VBIndex,
raw_ostream &Out) override;
- void mangleCXXCatchHandlerType(QualType T, uint32_t Flags,
- raw_ostream &Out) override;
void mangleCXXRTTI(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIName(QualType T, raw_ostream &Out) override;
void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived,
@@ -160,8 +159,6 @@ public:
void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
raw_ostream &Out) override;
void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override;
- void mangleCXXVTableBitSet(const CXXRecordDecl *RD,
- raw_ostream &Out) override;
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
// Lambda closure types are already numbered.
if (isLambda(ND))
@@ -179,7 +176,9 @@ public:
// Anonymous tags are already numbered.
if (const TagDecl *Tag = dyn_cast<TagDecl>(ND)) {
- if (Tag->getName().empty() && !Tag->getTypedefNameForAnonDecl())
+ if (!Tag->hasNameForLinkage() &&
+ !getASTContext().getDeclaratorForUnnamedTagDecl(Tag) &&
+ !getASTContext().getTypedefNameForUnnamedTagDecl(Tag))
return false;
}
@@ -220,9 +219,12 @@ class MicrosoftCXXNameMangler {
typedef llvm::SmallVector<std::string, 10> BackRefVec;
BackRefVec NameBackReferences;
- typedef llvm::DenseMap<void *, unsigned> ArgBackRefMap;
+ typedef llvm::DenseMap<const void *, unsigned> ArgBackRefMap;
ArgBackRefMap TypeBackReferences;
+ typedef std::set<int> PassObjectSizeArgsSet;
+ PassObjectSizeArgsSet PassObjectSizeArgs;
+
ASTContext &getASTContext() const { return Context.getASTContext(); }
// FIXME: If we add support for __ptr32/64 qualifiers, then we should push
@@ -262,6 +264,9 @@ public:
const CXXMethodDecl *MD,
const MicrosoftVTableContext::MethodVFTableLocation &ML);
void mangleNumber(int64_t Number);
+ void mangleTagTypeKind(TagTypeKind TK);
+ void mangleArtificalTagType(TagTypeKind TK, StringRef UnqualifiedName,
+ ArrayRef<StringRef> NestedNames = None);
void mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM = QMM_Mangle);
void mangleFunctionType(const FunctionType *T,
@@ -289,6 +294,7 @@ private:
void mangleObjCMethodName(const ObjCMethodDecl *MD);
void mangleArgumentType(QualType T, SourceRange Range);
+ void manglePassObjectSizeArg(const PassObjectSizeAttr *POSA);
// Declare manglers for every type class.
#define ABSTRACT_TYPE(CLASS, PARENT)
@@ -364,7 +370,8 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
DC = getEffectiveParentContext(DC);
if (DC->isTranslationUnit() && D->getFormalLinkage() == InternalLinkage &&
- !isa<VarTemplateSpecializationDecl>(D))
+ !isa<VarTemplateSpecializationDecl>(D) &&
+ D->getIdentifier() != nullptr)
return false;
}
@@ -390,14 +397,8 @@ void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
mangleFunctionEncoding(FD, Context.shouldMangleDeclName(FD));
else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
mangleVariableEncoding(VD);
- else {
- // TODO: Fields? Can MSVC even mangle them?
- // Issue a diagnostic for now.
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(
- DiagnosticsEngine::Error, "cannot mangle this declaration yet");
- Diags.Report(D->getLocation(), DiagID) << D->getSourceRange();
- }
+ else
+ llvm_unreachable("Tried to mangle unexpected NamedDecl!");
}
void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD,
@@ -420,7 +421,7 @@ void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD,
// We would like to mangle all extern "C" functions using this additional
// component but this would break compatibility with MSVC's behavior.
// Instead, do this when we know that compatibility isn't important (in
- // other words, when it is an overloaded extern "C" funciton).
+ // other words, when it is an overloaded extern "C" function).
if (FD->isExternC() && FD->hasAttr<OverloadableAttr>())
Out << "$$J0";
@@ -695,8 +696,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// Function templates aren't considered for name back referencing. This
// makes sense since function templates aren't likely to occur multiple
// times in a symbol.
- // FIXME: Test alias template mangling with MSVC 2013.
- if (!isa<ClassTemplateDecl>(TD)) {
+ if (isa<FunctionTemplateDecl>(TD)) {
mangleTemplateInstantiationName(TD, *TemplateArgs);
Out << '@';
return;
@@ -721,7 +721,6 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
llvm::raw_svector_ostream Stream(TemplateMangling);
MicrosoftCXXNameMangler Extra(Context, Stream);
Extra.mangleTemplateInstantiationName(TD, *TemplateArgs);
- Stream.flush();
mangleSourceName(TemplateMangling);
return;
@@ -787,14 +786,21 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
}
llvm::SmallString<64> Name("<unnamed-type-");
- if (TD->hasDeclaratorForAnonDecl()) {
- // Anonymous types with no tag or typedef get the name of their
+ if (DeclaratorDecl *DD =
+ Context.getASTContext().getDeclaratorForUnnamedTagDecl(TD)) {
+ // Anonymous types without a name for linkage purposes have their
// declarator mangled in if they have one.
- Name += TD->getDeclaratorForAnonDecl()->getName();
+ Name += DD->getName();
+ } else if (TypedefNameDecl *TND =
+ Context.getASTContext().getTypedefNameForUnnamedTagDecl(
+ TD)) {
+ // Anonymous types without a name for linkage purposes have their
+ // associate typedef mangled in if they have one.
+ Name += TND->getName();
} else {
// Otherwise, number the types using a $S prefix.
Name += "$S";
- Name += llvm::utostr(Context.getAnonymousStructId(TD));
+ Name += llvm::utostr(Context.getAnonymousStructId(TD) + 1);
}
Name += ">";
mangleSourceName(Name.str());
@@ -1039,6 +1045,14 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
break;
}
+ case OO_Coawait: {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this operator co_await yet");
+ Diags.Report(Loc, DiagID);
+ break;
+ }
+
case OO_None:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Not an overloaded operator");
@@ -1071,8 +1085,10 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
// Templates have their own context for back references.
ArgBackRefMap OuterArgsContext;
BackRefVec OuterTemplateContext;
+ PassObjectSizeArgsSet OuterPassObjectSizeArgs;
NameBackReferences.swap(OuterTemplateContext);
TypeBackReferences.swap(OuterArgsContext);
+ PassObjectSizeArgs.swap(OuterPassObjectSizeArgs);
mangleUnscopedTemplateName(TD);
mangleTemplateArgs(TD, TemplateArgs);
@@ -1080,6 +1096,7 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
// Restore the previous back reference contexts.
NameBackReferences.swap(OuterTemplateContext);
TypeBackReferences.swap(OuterArgsContext);
+ PassObjectSizeArgs.swap(OuterPassObjectSizeArgs);
}
void
@@ -1121,12 +1138,6 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
UE = dyn_cast<CXXUuidofExpr>(E);
if (UE) {
- // This CXXUuidofExpr is mangled as-if it were actually a VarDecl from
- // const __s_GUID _GUID_{lower case UUID with underscores}
- StringRef Uuid = UE->getUuidAsStringRef(Context.getASTContext());
- std::string Name = "_GUID_" + Uuid.lower();
- std::replace(Name.begin(), Name.end(), '-', '_');
-
// If we had to peek through an address-of operator, treat this like we are
// dealing with a pointer type. Otherwise, treat it like a const reference.
//
@@ -1136,7 +1147,22 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
Out << "$E?";
else
Out << "$1?";
- Out << Name << "@@3U__s_GUID@@B";
+
+ // This CXXUuidofExpr is mangled as-if it were actually a VarDecl from
+ // const __s_GUID _GUID_{lower case UUID with underscores}
+ StringRef Uuid = UE->getUuidAsStringRef(Context.getASTContext());
+ std::string Name = "_GUID_" + Uuid.lower();
+ std::replace(Name.begin(), Name.end(), '-', '_');
+
+ mangleSourceName(Name);
+ // Terminate the whole name with an '@'.
+ Out << '@';
+ // It's a global variable.
+ Out << '3';
+ // It's a struct called __s_GUID.
+ mangleArtificalTagType(TTK_Struct, "__s_GUID");
+ // It's const.
+ Out << 'B';
return;
}
@@ -1210,12 +1236,13 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
QualType T = TA.getNullPtrType();
if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) {
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
- if (MPT->isMemberFunctionPointerType() && isa<ClassTemplateDecl>(TD)) {
+ if (MPT->isMemberFunctionPointerType() &&
+ !isa<FunctionTemplateDecl>(TD)) {
mangleMemberFunctionPointer(RD, nullptr);
return;
}
if (MPT->isMemberDataPointer()) {
- if (isa<ClassTemplateDecl>(TD)) {
+ if (!isa<FunctionTemplateDecl>(TD)) {
mangleMemberDataPointer(RD, nullptr);
return;
}
@@ -1455,6 +1482,27 @@ void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,
}
}
+void MicrosoftCXXNameMangler::manglePassObjectSizeArg(
+ const PassObjectSizeAttr *POSA) {
+ int Type = POSA->getType();
+
+ auto Iter = PassObjectSizeArgs.insert(Type).first;
+ auto *TypePtr = (const void *)&*Iter;
+ ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
+
+ if (Found == TypeBackReferences.end()) {
+ mangleArtificalTagType(TTK_Enum, "__pass_object_size" + llvm::utostr(Type),
+ {"__clang"});
+
+ if (TypeBackReferences.size() < 10) {
+ size_t Size = TypeBackReferences.size();
+ TypeBackReferences[TypePtr] = Size;
+ }
+ } else {
+ Out << Found->second;
+ }
+}
+
void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
QualifierMangleMode QMM) {
// Don't use the canonical types. MSVC includes things like 'const' on
@@ -1546,29 +1594,72 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
// ::= _W # wchar_t
// ::= _Z # __float80 (Digital Mars)
switch (T->getKind()) {
- case BuiltinType::Void: Out << 'X'; break;
- case BuiltinType::SChar: Out << 'C'; break;
- case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'D'; break;
- case BuiltinType::UChar: Out << 'E'; break;
- case BuiltinType::Short: Out << 'F'; break;
- case BuiltinType::UShort: Out << 'G'; break;
- case BuiltinType::Int: Out << 'H'; break;
- case BuiltinType::UInt: Out << 'I'; break;
- case BuiltinType::Long: Out << 'J'; break;
- case BuiltinType::ULong: Out << 'K'; break;
- case BuiltinType::Float: Out << 'M'; break;
- case BuiltinType::Double: Out << 'N'; break;
+ case BuiltinType::Void:
+ Out << 'X';
+ break;
+ case BuiltinType::SChar:
+ Out << 'C';
+ break;
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ Out << 'D';
+ break;
+ case BuiltinType::UChar:
+ Out << 'E';
+ break;
+ case BuiltinType::Short:
+ Out << 'F';
+ break;
+ case BuiltinType::UShort:
+ Out << 'G';
+ break;
+ case BuiltinType::Int:
+ Out << 'H';
+ break;
+ case BuiltinType::UInt:
+ Out << 'I';
+ break;
+ case BuiltinType::Long:
+ Out << 'J';
+ break;
+ case BuiltinType::ULong:
+ Out << 'K';
+ break;
+ case BuiltinType::Float:
+ Out << 'M';
+ break;
+ case BuiltinType::Double:
+ Out << 'N';
+ break;
// TODO: Determine size and mangle accordingly
- case BuiltinType::LongDouble: Out << 'O'; break;
- case BuiltinType::LongLong: Out << "_J"; break;
- case BuiltinType::ULongLong: Out << "_K"; break;
- case BuiltinType::Int128: Out << "_L"; break;
- case BuiltinType::UInt128: Out << "_M"; break;
- case BuiltinType::Bool: Out << "_N"; break;
- case BuiltinType::Char16: Out << "_S"; break;
- case BuiltinType::Char32: Out << "_U"; break;
+ case BuiltinType::LongDouble:
+ Out << 'O';
+ break;
+ case BuiltinType::LongLong:
+ Out << "_J";
+ break;
+ case BuiltinType::ULongLong:
+ Out << "_K";
+ break;
+ case BuiltinType::Int128:
+ Out << "_L";
+ break;
+ case BuiltinType::UInt128:
+ Out << "_M";
+ break;
+ case BuiltinType::Bool:
+ Out << "_N";
+ break;
+ case BuiltinType::Char16:
+ Out << "_S";
+ break;
+ case BuiltinType::Char32:
+ Out << "_U";
+ break;
case BuiltinType::WChar_S:
- case BuiltinType::WChar_U: Out << "_W"; break;
+ case BuiltinType::WChar_U:
+ Out << "_W";
+ break;
#define BUILTIN_TYPE(Id, SingletonId)
#define PLACEHOLDER_TYPE(Id, SingletonId) \
@@ -1577,28 +1668,102 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
case BuiltinType::Dependent:
llvm_unreachable("placeholder types shouldn't get to name mangling");
- case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break;
- case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break;
- case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break;
+ case BuiltinType::ObjCId:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "objc_object");
+ break;
+ case BuiltinType::ObjCClass:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "objc_class");
+ break;
+ case BuiltinType::ObjCSel:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "objc_selector");
+ break;
- case BuiltinType::OCLImage1d: Out << "PAUocl_image1d@@"; break;
- case BuiltinType::OCLImage1dArray: Out << "PAUocl_image1darray@@"; break;
- case BuiltinType::OCLImage1dBuffer: Out << "PAUocl_image1dbuffer@@"; break;
- case BuiltinType::OCLImage2d: Out << "PAUocl_image2d@@"; break;
- case BuiltinType::OCLImage2dArray: Out << "PAUocl_image2darray@@"; break;
- case BuiltinType::OCLImage3d: Out << "PAUocl_image3d@@"; break;
- case BuiltinType::OCLSampler: Out << "PAUocl_sampler@@"; break;
- case BuiltinType::OCLEvent: Out << "PAUocl_event@@"; break;
+ case BuiltinType::OCLImage1d:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image1d");
+ break;
+ case BuiltinType::OCLImage1dArray:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image1darray");
+ break;
+ case BuiltinType::OCLImage1dBuffer:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image1dbuffer");
+ break;
+ case BuiltinType::OCLImage2d:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image2d");
+ break;
+ case BuiltinType::OCLImage2dArray:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image2darray");
+ break;
+ case BuiltinType::OCLImage2dDepth:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image2ddepth");
+ break;
+ case BuiltinType::OCLImage2dArrayDepth:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image2darraydepth");
+ break;
+ case BuiltinType::OCLImage2dMSAA:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image2dmsaa");
+ break;
+ case BuiltinType::OCLImage2dArrayMSAA:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image2darraymsaa");
+ break;
+ case BuiltinType::OCLImage2dMSAADepth:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image2dmsaadepth");
+ break;
+ case BuiltinType::OCLImage2dArrayMSAADepth:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image2darraymsaadepth");
+ break;
+ case BuiltinType::OCLImage3d:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_image3d");
+ break;
+ case BuiltinType::OCLSampler:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_sampler");
+ break;
+ case BuiltinType::OCLEvent:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_event");
+ break;
+ case BuiltinType::OCLClkEvent:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_clkevent");
+ break;
+ case BuiltinType::OCLQueue:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_queue");
+ break;
+ case BuiltinType::OCLNDRange:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_ndrange");
+ break;
+ case BuiltinType::OCLReserveID:
+ Out << "PA";
+ mangleArtificalTagType(TTK_Struct, "ocl_reserveid");
+ break;
- case BuiltinType::NullPtr: Out << "$$T"; break;
+ case BuiltinType::NullPtr:
+ Out << "$$T";
+ break;
case BuiltinType::Half: {
DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this built-in %0 type yet");
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error, "cannot mangle this built-in %0 type yet");
Diags.Report(Range.getBegin(), DiagID)
- << T->getName(Context.getASTContext().getPrintingPolicy())
- << Range;
+ << T->getName(Context.getASTContext().getPrintingPolicy()) << Range;
break;
}
}
@@ -1620,7 +1785,8 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, Qualifiers,
}
void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
Qualifiers, SourceRange) {
- llvm_unreachable("Can't mangle K&R function prototypes");
+ Out << "$$A6";
+ mangleFunctionType(T);
}
void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
@@ -1628,7 +1794,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
bool ForceThisQuals) {
// <function-type> ::= <this-cvr-qualifiers> <calling-convention>
// <return-type> <argument-list> <throw-spec>
- const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+ const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(T);
SourceRange Range;
if (D) Range = D->getSourceRange();
@@ -1699,12 +1865,14 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
}
Out << '@';
} else {
- QualType ResultType = Proto->getReturnType();
+ QualType ResultType = T->getReturnType();
if (const auto *AT =
dyn_cast_or_null<AutoType>(ResultType->getContainedAutoType())) {
Out << '?';
mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false);
Out << '?';
+ assert(AT->getKeyword() != AutoTypeKeyword::GNUAutoType &&
+ "shouldn't need to mangle __auto_type!");
mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>");
Out << '@';
} else {
@@ -1717,12 +1885,29 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// <argument-list> ::= X # void
// ::= <type>+ @
// ::= <type>* Z # varargs
- if (Proto->getNumParams() == 0 && !Proto->isVariadic()) {
+ if (!Proto) {
+ // Function types without prototypes can arise when mangling a function type
+ // within an overloadable function in C. We mangle these as the absence of
+ // any parameter types (not even an empty parameter list).
+ Out << '@';
+ } else if (Proto->getNumParams() == 0 && !Proto->isVariadic()) {
Out << 'X';
} else {
// Happens for function pointer type arguments for example.
- for (const QualType &Arg : Proto->param_types())
- mangleArgumentType(Arg, Range);
+ for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) {
+ mangleArgumentType(Proto->getParamType(I), Range);
+ // Mangle each pass_object_size parameter as if it's a paramater of enum
+ // type passed directly after the parameter with the pass_object_size
+ // attribute. The aforementioned enum's name is __pass_object_size, and we
+ // pretend it resides in a top-level namespace called __clang.
+ //
+ // FIXME: Is there a defined extension notation for the MS ABI, or is it
+ // necessary to just cross our fingers and hope this type+namespace
+ // combination doesn't conflict with anything?
+ if (D)
+ if (const auto *P = D->getParamDecl(I)->getAttr<PassObjectSizeAttr>())
+ manglePassObjectSizeArg(P);
+ }
// <builtin-type> ::= Z # ellipsis
if (Proto->isVariadic())
Out << 'Z';
@@ -1851,16 +2036,8 @@ void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
// <struct-type> ::= U <name>
// <class-type> ::= V <name>
// <enum-type> ::= W4 <name>
-void MicrosoftCXXNameMangler::mangleType(const EnumType *T, Qualifiers,
- SourceRange) {
- mangleType(cast<TagType>(T)->getDecl());
-}
-void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers,
- SourceRange) {
- mangleType(cast<TagType>(T)->getDecl());
-}
-void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
- switch (TD->getTagKind()) {
+void MicrosoftCXXNameMangler::mangleTagTypeKind(TagTypeKind TTK) {
+ switch (TTK) {
case TTK_Union:
Out << 'T';
break;
@@ -1875,8 +2052,33 @@ void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
Out << "W4";
break;
}
+}
+void MicrosoftCXXNameMangler::mangleType(const EnumType *T, Qualifiers,
+ SourceRange) {
+ mangleType(cast<TagType>(T)->getDecl());
+}
+void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers,
+ SourceRange) {
+ mangleType(cast<TagType>(T)->getDecl());
+}
+void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) {
+ mangleTagTypeKind(TD->getTagKind());
mangleName(TD);
}
+void MicrosoftCXXNameMangler::mangleArtificalTagType(
+ TagTypeKind TK, StringRef UnqualifiedName, ArrayRef<StringRef> NestedNames) {
+ // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
+ mangleTagTypeKind(TK);
+
+ // Always start with the unqualified name.
+ mangleSourceName(UnqualifiedName);
+
+ for (auto I = NestedNames.rbegin(), E = NestedNames.rend(); I != E; ++I)
+ mangleSourceName(*I);
+
+ // Terminate the whole name with an '@'.
+ Out << '@';
+}
// <type> ::= <array-type>
// <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
@@ -2011,7 +2213,8 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
Qualifiers Quals, SourceRange Range) {
QualType PointeeType = T->getPointeeType();
- Out << (Quals.hasVolatile() ? 'B' : 'A');
+ assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!");
+ Out << 'A';
manglePointerExtQualifiers(Quals, PointeeType);
mangleType(PointeeType, Range);
}
@@ -2022,18 +2225,24 @@ void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,
Qualifiers Quals, SourceRange Range) {
QualType PointeeType = T->getPointeeType();
- Out << (Quals.hasVolatile() ? "$$R" : "$$Q");
+ assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!");
+ Out << "$$Q";
manglePointerExtQualifiers(Quals, PointeeType);
mangleType(PointeeType, Range);
}
void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, Qualifiers,
SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this complex number type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
+ QualType ElementType = T->getElementType();
+
+ llvm::SmallString<64> TemplateMangling;
+ llvm::raw_svector_ostream Stream(TemplateMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+ Stream << "?$";
+ Extra.mangleSourceName("_Complex");
+ Extra.mangleType(ElementType, Range, QMM_Escape);
+
+ mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"});
}
void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals,
@@ -2043,46 +2252,44 @@ void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals,
uint64_t Width = getASTContext().getTypeSize(T);
// Pattern match exactly the typedefs in our intrinsic headers. Anything that
// doesn't match the Intel types uses a custom mangling below.
- bool IsBuiltin = true;
+ size_t OutSizeBefore = Out.tell();
llvm::Triple::ArchType AT =
getASTContext().getTargetInfo().getTriple().getArch();
if (AT == llvm::Triple::x86 || AT == llvm::Triple::x86_64) {
if (Width == 64 && ET->getKind() == BuiltinType::LongLong) {
- Out << "T__m64";
+ mangleArtificalTagType(TTK_Union, "__m64");
} else if (Width >= 128) {
if (ET->getKind() == BuiltinType::Float)
- Out << "T__m" << Width;
+ mangleArtificalTagType(TTK_Union, "__m" + llvm::utostr(Width));
else if (ET->getKind() == BuiltinType::LongLong)
- Out << "T__m" << Width << 'i';
+ mangleArtificalTagType(TTK_Union, "__m" + llvm::utostr(Width) + 'i');
else if (ET->getKind() == BuiltinType::Double)
- Out << "U__m" << Width << 'd';
- else
- IsBuiltin = false;
- } else {
- IsBuiltin = false;
+ mangleArtificalTagType(TTK_Struct, "__m" + llvm::utostr(Width) + 'd');
}
- } else {
- IsBuiltin = false;
}
+ bool IsBuiltin = Out.tell() != OutSizeBefore;
if (!IsBuiltin) {
// The MS ABI doesn't have a special mangling for vector types, so we define
// our own mangling to handle uses of __vector_size__ on user-specified
// types, and for extensions like __v4sf.
- Out << "T__clang_vec" << T->getNumElements() << '_';
- mangleType(ET, Quals, Range);
- }
- Out << "@@";
+ llvm::SmallString<64> TemplateMangling;
+ llvm::raw_svector_ostream Stream(TemplateMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+ Stream << "?$";
+ Extra.mangleSourceName("__vector");
+ Extra.mangleType(QualType(ET, 0), Range, QMM_Escape);
+ Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumElements()),
+ /*IsBoolean=*/false);
+
+ mangleArtificalTagType(TTK_Union, TemplateMangling, {"__clang"});
+ }
}
-void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, Qualifiers,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this extended vector type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
+void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
+ Qualifiers Quals, SourceRange Range) {
+ mangleType(static_cast<const VectorType *>(T), Quals, Range);
}
void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
Qualifiers, SourceRange Range) {
@@ -2096,7 +2303,7 @@ void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers,
SourceRange) {
// ObjC interfaces have structs underlying them.
- Out << 'U';
+ mangleTagTypeKind(TTK_Struct);
mangleName(T->getDecl());
}
@@ -2209,9 +2416,23 @@ void MicrosoftCXXNameMangler::mangleType(const AutoType *T, Qualifiers,
void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
SourceRange Range) {
+ QualType ValueType = T->getValueType();
+
+ llvm::SmallString<64> TemplateMangling;
+ llvm::raw_svector_ostream Stream(TemplateMangling);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+ Stream << "?$";
+ Extra.mangleSourceName("_Atomic");
+ Extra.mangleType(ValueType, Range, QMM_Escape);
+
+ mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"});
+}
+
+void MicrosoftCXXNameMangler::mangleType(const PipeType *T, Qualifiers,
+ SourceRange Range) {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this C11 atomic type yet");
+ "cannot mangle this OpenCL pipe type yet");
Diags.Report(Range.getBegin(), DiagID)
<< Range;
}
@@ -2408,15 +2629,6 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T,
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
}
-void MicrosoftMangleContextImpl::mangleCXXCatchHandlerType(QualType T,
- uint32_t Flags,
- raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "llvm.eh.handlertype.";
- Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
- Mangler.getStream() << '.' << Flags;
-}
-
void MicrosoftMangleContextImpl::mangleCXXVirtualDisplacementMap(
const CXXRecordDecl *SrcRD, const CXXRecordDecl *DstRD, raw_ostream &Out) {
MicrosoftCXXNameMangler Mangler(*this, Out);
@@ -2574,12 +2786,12 @@ void MicrosoftMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D,
mangler.mangle(D);
}
-void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD,
- unsigned,
- raw_ostream &) {
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this reference temporary yet");
- getDiags().Report(VD->getLocation(), DiagID);
+void MicrosoftMangleContextImpl::mangleReferenceTemporary(
+ const VarDecl *VD, unsigned ManglingNumber, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+
+ Mangler.getStream() << "\01?$RT" << ManglingNumber << '@';
+ Mangler.mangle(VD, "");
}
void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
@@ -2688,28 +2900,6 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
// N.B. The length is in terms of bytes, not characters.
Mangler.mangleNumber(SL->getByteLength() + SL->getCharByteWidth());
- // We will use the "Rocksoft^tm Model CRC Algorithm" to describe the
- // properties of our CRC:
- // Width : 32
- // Poly : 04C11DB7
- // Init : FFFFFFFF
- // RefIn : True
- // RefOut : True
- // XorOut : 00000000
- // Check : 340BC6D9
- uint32_t CRC = 0xFFFFFFFFU;
-
- auto UpdateCRC = [&CRC](char Byte) {
- for (unsigned i = 0; i < 8; ++i) {
- bool Bit = CRC & 0x80000000U;
- if (Byte & (1U << i))
- Bit = !Bit;
- CRC <<= 1;
- if (Bit)
- CRC ^= 0x04C11DB7U;
- }
- };
-
auto GetLittleEndianByte = [&Mangler, &SL](unsigned Index) {
unsigned CharByteWidth = SL->getCharByteWidth();
uint32_t CodeUnit = SL->getCodeUnit(Index / CharByteWidth);
@@ -2725,22 +2915,19 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
};
// CRC all the bytes of the StringLiteral.
+ llvm::JamCRC JC;
for (unsigned I = 0, E = SL->getByteLength(); I != E; ++I)
- UpdateCRC(GetLittleEndianByte(I));
+ JC.update(GetLittleEndianByte(I));
// The NUL terminator byte(s) were not present earlier,
// we need to manually process those bytes into the CRC.
for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth();
++NullTerminator)
- UpdateCRC('\x00');
-
- // The literature refers to the process of reversing the bits in the final CRC
- // output as "reflection".
- CRC = llvm::reverseBits(CRC);
+ JC.update('\x00');
// <encoded-crc>: The CRC is encoded utilizing the standard number mangling
// scheme.
- Mangler.mangleNumber(CRC);
+ Mangler.mangleNumber(JC.getCRC());
// <encoded-string>: The mangled name also contains the first 32 _characters_
// (including null-terminator bytes) of the StringLiteral.
@@ -2790,21 +2977,6 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
Mangler.getStream() << '@';
}
-void MicrosoftMangleContextImpl::mangleCXXVTableBitSet(const CXXRecordDecl *RD,
- raw_ostream &Out) {
- if (!RD->isExternallyVisible()) {
- // This part of the identifier needs to be unique across all translation
- // units in the linked program. The scheme fails if multiple translation
- // units are compiled using the same relative source file path, or if
- // multiple translation units are built from the same source file.
- SourceManager &SM = getASTContext().getSourceManager();
- Out << "[" << SM.getFileEntryForID(SM.getMainFileID())->getName() << "]";
- }
-
- MicrosoftCXXNameMangler mangler(*this, Out);
- mangler.mangleName(RD);
-}
-
MicrosoftMangleContext *
MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
return new MicrosoftMangleContextImpl(Context, Diags);
diff --git a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
index c9264d5..c562dae 100644
--- a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
@@ -450,9 +450,19 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::OCLImage1dBuffer:
case BuiltinType::OCLImage2d:
case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage2dDepth:
+ case BuiltinType::OCLImage2dArrayDepth:
+ case BuiltinType::OCLImage2dMSAA:
+ case BuiltinType::OCLImage2dArrayMSAA:
+ case BuiltinType::OCLImage2dMSAADepth:
+ case BuiltinType::OCLImage2dArrayMSAADepth:
case BuiltinType::OCLImage3d:
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLNDRange:
+ case BuiltinType::OCLReserveID:
case BuiltinType::BoundMember:
case BuiltinType::Dependent:
case BuiltinType::Overload:
@@ -461,6 +471,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::Half:
case BuiltinType::PseudoObject:
case BuiltinType::BuiltinFn:
+ case BuiltinType::OMPArraySection:
break;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
index 97425d0..d2370c8 100644
--- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
@@ -318,7 +318,12 @@ NestedNameSpecifier::print(raw_ostream &OS,
OS << "::";
}
-void NestedNameSpecifier::dump(const LangOptions &LO) {
+void NestedNameSpecifier::dump(const LangOptions &LO) const {
+ print(llvm::errs(), PrintingPolicy(LO));
+}
+
+void NestedNameSpecifier::dump() const {
+ LangOptions LO;
print(llvm::errs(), PrintingPolicy(LO));
}
diff --git a/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp
new file mode 100644
index 0000000..1ef43f7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/OpenMPClause.cpp
@@ -0,0 +1,417 @@
+//===--- OpenMPClause.cpp - Classes for OpenMP clauses --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the subclesses of Stmt class declared in OpenMPClause.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/OpenMPClause.h"
+
+#include "clang/AST/ASTContext.h"
+
+using namespace clang;
+
+OMPClause::child_range OMPClause::children() {
+ switch (getClauseKind()) {
+ default:
+ break;
+#define OPENMP_CLAUSE(Name, Class) \
+ case OMPC_##Name: \
+ return static_cast<Class *>(this)->children();
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("unknown OMPClause");
+}
+
+void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
+ assert(VL.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(), varlist_end());
+}
+
+OMPPrivateClause *
+OMPPrivateClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL) {
+ // Allocate space for private variables and initializer expressions.
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * VL.size()));
+ OMPPrivateClause *Clause =
+ new (Mem) OMPPrivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setPrivateCopies(PrivateVL);
+ return Clause;
+}
+
+OMPPrivateClause *OMPPrivateClause::CreateEmpty(const ASTContext &C,
+ unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * N));
+ return new (Mem) OMPPrivateClause(N);
+}
+
+void OMPFirstprivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
+ assert(VL.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(), varlist_end());
+}
+
+void OMPFirstprivateClause::setInits(ArrayRef<Expr *> VL) {
+ assert(VL.size() == varlist_size() &&
+ "Number of inits is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(), getPrivateCopies().end());
+}
+
+OMPFirstprivateClause *
+OMPFirstprivateClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL,
+ ArrayRef<Expr *> InitVL) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(3 * VL.size()));
+ OMPFirstprivateClause *Clause =
+ new (Mem) OMPFirstprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setPrivateCopies(PrivateVL);
+ Clause->setInits(InitVL);
+ return Clause;
+}
+
+OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C,
+ unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(3 * N));
+ return new (Mem) OMPFirstprivateClause(N);
+}
+
+void OMPLastprivateClause::setPrivateCopies(ArrayRef<Expr *> PrivateCopies) {
+ assert(PrivateCopies.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(PrivateCopies.begin(), PrivateCopies.end(), varlist_end());
+}
+
+void OMPLastprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
+ assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
+ "not the same as the "
+ "preallocated buffer");
+ std::copy(SrcExprs.begin(), SrcExprs.end(), getPrivateCopies().end());
+}
+
+void OMPLastprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
+ assert(DstExprs.size() == varlist_size() && "Number of destination "
+ "expressions is not the same as "
+ "the preallocated buffer");
+ std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
+}
+
+void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
+ assert(AssignmentOps.size() == varlist_size() &&
+ "Number of assignment expressions is not the same as the preallocated "
+ "buffer");
+ std::copy(AssignmentOps.begin(), AssignmentOps.end(),
+ getDestinationExprs().end());
+}
+
+OMPLastprivateClause *OMPLastprivateClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size()));
+ OMPLastprivateClause *Clause =
+ new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setSourceExprs(SrcExprs);
+ Clause->setDestinationExprs(DstExprs);
+ Clause->setAssignmentOps(AssignmentOps);
+ return Clause;
+}
+
+OMPLastprivateClause *OMPLastprivateClause::CreateEmpty(const ASTContext &C,
+ unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N));
+ return new (Mem) OMPLastprivateClause(N);
+}
+
+OMPSharedClause *OMPSharedClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> VL) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
+ OMPSharedClause *Clause =
+ new (Mem) OMPSharedClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ return Clause;
+}
+
+OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C, unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
+ return new (Mem) OMPSharedClause(N);
+}
+
+void OMPLinearClause::setPrivates(ArrayRef<Expr *> PL) {
+ assert(PL.size() == varlist_size() &&
+ "Number of privates is not the same as the preallocated buffer");
+ std::copy(PL.begin(), PL.end(), varlist_end());
+}
+
+void OMPLinearClause::setInits(ArrayRef<Expr *> IL) {
+ assert(IL.size() == varlist_size() &&
+ "Number of inits is not the same as the preallocated buffer");
+ std::copy(IL.begin(), IL.end(), getPrivates().end());
+}
+
+void OMPLinearClause::setUpdates(ArrayRef<Expr *> UL) {
+ assert(UL.size() == varlist_size() &&
+ "Number of updates is not the same as the preallocated buffer");
+ std::copy(UL.begin(), UL.end(), getInits().end());
+}
+
+void OMPLinearClause::setFinals(ArrayRef<Expr *> FL) {
+ assert(FL.size() == varlist_size() &&
+ "Number of final updates is not the same as the preallocated buffer");
+ std::copy(FL.begin(), FL.end(), getUpdates().end());
+}
+
+OMPLinearClause *OMPLinearClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep) {
+ // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions
+ // (Step and CalcStep).
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size() + 2));
+ OMPLinearClause *Clause = new (Mem) OMPLinearClause(
+ StartLoc, LParenLoc, Modifier, ModifierLoc, ColonLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setPrivates(PL);
+ Clause->setInits(IL);
+ // Fill update and final expressions with zeroes, they are provided later,
+ // after the directive construction.
+ std::fill(Clause->getInits().end(), Clause->getInits().end() + VL.size(),
+ nullptr);
+ std::fill(Clause->getUpdates().end(), Clause->getUpdates().end() + VL.size(),
+ nullptr);
+ Clause->setStep(Step);
+ Clause->setCalcStep(CalcStep);
+ return Clause;
+}
+
+OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C,
+ unsigned NumVars) {
+ // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions
+ // (Step and CalcStep).
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * NumVars + 2));
+ return new (Mem) OMPLinearClause(NumVars);
+}
+
+OMPAlignedClause *
+OMPAlignedClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, Expr *A) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1));
+ OMPAlignedClause *Clause = new (Mem)
+ OMPAlignedClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setAlignment(A);
+ return Clause;
+}
+
+OMPAlignedClause *OMPAlignedClause::CreateEmpty(const ASTContext &C,
+ unsigned NumVars) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumVars + 1));
+ return new (Mem) OMPAlignedClause(NumVars);
+}
+
+void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
+ assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
+ "not the same as the "
+ "preallocated buffer");
+ std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end());
+}
+
+void OMPCopyinClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
+ assert(DstExprs.size() == varlist_size() && "Number of destination "
+ "expressions is not the same as "
+ "the preallocated buffer");
+ std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
+}
+
+void OMPCopyinClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
+ assert(AssignmentOps.size() == varlist_size() &&
+ "Number of assignment expressions is not the same as the preallocated "
+ "buffer");
+ std::copy(AssignmentOps.begin(), AssignmentOps.end(),
+ getDestinationExprs().end());
+}
+
+OMPCopyinClause *OMPCopyinClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * VL.size()));
+ OMPCopyinClause *Clause =
+ new (Mem) OMPCopyinClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setSourceExprs(SrcExprs);
+ Clause->setDestinationExprs(DstExprs);
+ Clause->setAssignmentOps(AssignmentOps);
+ return Clause;
+}
+
+OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C, unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * N));
+ return new (Mem) OMPCopyinClause(N);
+}
+
+void OMPCopyprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
+ assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
+ "not the same as the "
+ "preallocated buffer");
+ std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end());
+}
+
+void OMPCopyprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
+ assert(DstExprs.size() == varlist_size() && "Number of destination "
+ "expressions is not the same as "
+ "the preallocated buffer");
+ std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
+}
+
+void OMPCopyprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
+ assert(AssignmentOps.size() == varlist_size() &&
+ "Number of assignment expressions is not the same as the preallocated "
+ "buffer");
+ std::copy(AssignmentOps.begin(), AssignmentOps.end(),
+ getDestinationExprs().end());
+}
+
+OMPCopyprivateClause *OMPCopyprivateClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * VL.size()));
+ OMPCopyprivateClause *Clause =
+ new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setSourceExprs(SrcExprs);
+ Clause->setDestinationExprs(DstExprs);
+ Clause->setAssignmentOps(AssignmentOps);
+ return Clause;
+}
+
+OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C,
+ unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * N));
+ return new (Mem) OMPCopyprivateClause(N);
+}
+
+void OMPReductionClause::setPrivates(ArrayRef<Expr *> Privates) {
+ assert(Privates.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(Privates.begin(), Privates.end(), varlist_end());
+}
+
+void OMPReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
+ assert(
+ LHSExprs.size() == varlist_size() &&
+ "Number of LHS expressions is not the same as the preallocated buffer");
+ std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end());
+}
+
+void OMPReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
+ assert(
+ RHSExprs.size() == varlist_size() &&
+ "Number of RHS expressions is not the same as the preallocated buffer");
+ std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end());
+}
+
+void OMPReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
+ assert(ReductionOps.size() == varlist_size() && "Number of reduction "
+ "expressions is not the same "
+ "as the preallocated buffer");
+ std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
+}
+
+OMPReductionClause *OMPReductionClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
+ NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
+ ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
+ ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size()));
+ OMPReductionClause *Clause = new (Mem) OMPReductionClause(
+ StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
+ Clause->setVarRefs(VL);
+ Clause->setPrivates(Privates);
+ Clause->setLHSExprs(LHSExprs);
+ Clause->setRHSExprs(RHSExprs);
+ Clause->setReductionOps(ReductionOps);
+ return Clause;
+}
+
+OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C,
+ unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N));
+ return new (Mem) OMPReductionClause(N);
+}
+
+OMPFlushClause *OMPFlushClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> VL) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
+ OMPFlushClause *Clause =
+ new (Mem) OMPFlushClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ return Clause;
+}
+
+OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
+ return new (Mem) OMPFlushClause(N);
+}
+
+OMPDependClause *
+OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VL) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
+ OMPDependClause *Clause =
+ new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setDependencyKind(DepKind);
+ Clause->setDependencyLoc(DepLoc);
+ Clause->setColonLoc(ColonLoc);
+ return Clause;
+}
+
+OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
+ return new (Mem) OMPDependClause(N);
+}
+
+OMPMapClause *OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ OpenMPMapClauseKind TypeModifier,
+ OpenMPMapClauseKind Type,
+ SourceLocation TypeLoc) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
+ OMPMapClause *Clause = new (Mem) OMPMapClause(
+ TypeModifier, Type, TypeLoc, StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setMapTypeModifier(TypeModifier);
+ Clause->setMapType(Type);
+ Clause->setMapLoc(TypeLoc);
+ return Clause;
+}
+
+OMPMapClause *OMPMapClause::CreateEmpty(const ASTContext &C, unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
+ return new (Mem) OMPMapClause(N);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp
index 24b129a..8317f76 100644
--- a/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RawCommentList.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/CommentLexer.h"
#include "clang/AST/CommentParser.h"
#include "clang/AST/CommentSema.h"
+#include "clang/Basic/CharInfo.h"
#include "llvm/ADT/STLExtras.h"
using namespace clang;
@@ -62,12 +63,53 @@ std::pair<RawComment::CommentKind, bool> getCommentKind(StringRef Comment,
bool mergedCommentIsTrailingComment(StringRef Comment) {
return (Comment.size() > 3) && (Comment[3] == '<');
}
+
+/// Returns true if R1 and R2 both have valid locations that start on the same
+/// column.
+bool commentsStartOnSameColumn(const SourceManager &SM, const RawComment &R1,
+ const RawComment &R2) {
+ SourceLocation L1 = R1.getLocStart();
+ SourceLocation L2 = R2.getLocStart();
+ bool Invalid = false;
+ unsigned C1 = SM.getPresumedColumnNumber(L1, &Invalid);
+ if (!Invalid) {
+ unsigned C2 = SM.getPresumedColumnNumber(L2, &Invalid);
+ return !Invalid && (C1 == C2);
+ }
+ return false;
+}
} // unnamed namespace
+/// \brief Determines whether there is only whitespace in `Buffer` between `P`
+/// and the previous line.
+/// \param Buffer The buffer to search in.
+/// \param P The offset from the beginning of `Buffer` to start from.
+/// \return true if all of the characters in `Buffer` ranging from the closest
+/// line-ending character before `P` (or the beginning of `Buffer`) to `P - 1`
+/// are whitespace.
+static bool onlyWhitespaceOnLineBefore(const char *Buffer, unsigned P) {
+ // Search backwards until we see linefeed or carriage return.
+ for (unsigned I = P; I != 0; --I) {
+ char C = Buffer[I - 1];
+ if (isVerticalWhitespace(C))
+ return true;
+ if (!isHorizontalWhitespace(C))
+ return false;
+ }
+ // We hit the beginning of the buffer.
+ return true;
+}
+
+/// Returns whether `K` is an ordinary comment kind.
+static bool isOrdinaryKind(RawComment::CommentKind K) {
+ return (K == RawComment::RCK_OrdinaryBCPL) ||
+ (K == RawComment::RCK_OrdinaryC);
+}
+
RawComment::RawComment(const SourceManager &SourceMgr, SourceRange SR,
bool Merged, bool ParseAllComments) :
Range(SR), RawTextValid(false), BriefTextValid(false),
- IsAttached(false), IsAlmostTrailingComment(false),
+ IsAttached(false), IsTrailingComment(false), IsAlmostTrailingComment(false),
ParseAllComments(ParseAllComments) {
// Extract raw comment text, if possible.
if (SR.getBegin() == SR.getEnd() || getRawText(SourceMgr).empty()) {
@@ -75,17 +117,34 @@ RawComment::RawComment(const SourceManager &SourceMgr, SourceRange SR,
return;
}
+ // Guess comment kind.
+ std::pair<CommentKind, bool> K = getCommentKind(RawText, ParseAllComments);
+
+ // Guess whether an ordinary comment is trailing.
+ if (ParseAllComments && isOrdinaryKind(K.first)) {
+ FileID BeginFileID;
+ unsigned BeginOffset;
+ std::tie(BeginFileID, BeginOffset) =
+ SourceMgr.getDecomposedLoc(Range.getBegin());
+ if (BeginOffset != 0) {
+ bool Invalid = false;
+ const char *Buffer =
+ SourceMgr.getBufferData(BeginFileID, &Invalid).data();
+ IsTrailingComment |=
+ (!Invalid && !onlyWhitespaceOnLineBefore(Buffer, BeginOffset));
+ }
+ }
+
if (!Merged) {
- // Guess comment kind.
- std::pair<CommentKind, bool> K = getCommentKind(RawText, ParseAllComments);
Kind = K.first;
- IsTrailingComment = K.second;
+ IsTrailingComment |= K.second;
IsAlmostTrailingComment = RawText.startswith("//<") ||
RawText.startswith("/*<");
} else {
Kind = RCK_Merged;
- IsTrailingComment = mergedCommentIsTrailingComment(RawText);
+ IsTrailingComment =
+ IsTrailingComment || mergedCommentIsTrailingComment(RawText);
}
}
@@ -239,9 +298,22 @@ void RawCommentList::addComment(const RawComment &RC,
const RawComment &C2 = RC;
// Merge comments only if there is only whitespace between them.
- // Can't merge trailing and non-trailing comments.
+ // Can't merge trailing and non-trailing comments unless the second is
+ // non-trailing ordinary in the same column, as in the case:
+ // int x; // documents x
+ // // more text
+ // versus:
+ // int x; // documents x
+ // int y; // documents y
+ // or:
+ // int x; // documents x
+ // // documents y
+ // int y;
// Merge comments if they are on same or consecutive lines.
- if (C1.isTrailingComment() == C2.isTrailingComment() &&
+ if ((C1.isTrailingComment() == C2.isTrailingComment() ||
+ (C1.isTrailingComment() && !C2.isTrailingComment() &&
+ isOrdinaryKind(C2.getKind()) &&
+ commentsStartOnSameColumn(SourceMgr, C1, C2))) &&
onlyWhitespaceBetween(SourceMgr, C1.getLocEnd(), C2.getLocStart(),
/*MaxNewlinesAllowed=*/1)) {
SourceRange MergedRange(C1.getLocStart(), C2.getLocEnd());
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
index de7bcb8..bc5ae0f 100644
--- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -18,7 +18,6 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallSet.h"
-#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
@@ -565,7 +564,7 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD,
typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> ClassSetTy;
-class RecordLayoutBuilder {
+class ItaniumRecordLayoutBuilder {
protected:
// FIXME: Remove this and make the appropriate fields public.
friend class clang::ASTContext;
@@ -656,19 +655,18 @@ protected:
/// Valid if UseExternalLayout is true.
ExternalLayout External;
- RecordLayoutBuilder(const ASTContext &Context,
- EmptySubobjectMap *EmptySubobjects)
- : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
- Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()),
- UseExternalLayout(false), InferAlignment(false),
- Packed(false), IsUnion(false), IsMac68kAlign(false), IsMsStruct(false),
- UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
- MaxFieldAlignment(CharUnits::Zero()),
- DataSize(0), NonVirtualSize(CharUnits::Zero()),
- NonVirtualAlignment(CharUnits::One()),
- PrimaryBase(nullptr), PrimaryBaseIsVirtual(false),
- HasOwnVFPtr(false),
- FirstNearlyEmptyVBase(nullptr) {}
+ ItaniumRecordLayoutBuilder(const ASTContext &Context,
+ EmptySubobjectMap *EmptySubobjects)
+ : Context(Context), EmptySubobjects(EmptySubobjects), Size(0),
+ Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()),
+ UseExternalLayout(false), InferAlignment(false), Packed(false),
+ IsUnion(false), IsMac68kAlign(false), IsMsStruct(false),
+ UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
+ MaxFieldAlignment(CharUnits::Zero()), DataSize(0),
+ NonVirtualSize(CharUnits::Zero()),
+ NonVirtualAlignment(CharUnits::One()), PrimaryBase(nullptr),
+ PrimaryBaseIsVirtual(false), HasOwnVFPtr(false),
+ FirstNearlyEmptyVBase(nullptr) {}
void Layout(const RecordDecl *D);
void Layout(const CXXRecordDecl *D);
@@ -782,13 +780,12 @@ protected:
void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }
void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
- RecordLayoutBuilder(const RecordLayoutBuilder &) = delete;
- void operator=(const RecordLayoutBuilder &) = delete;
+ ItaniumRecordLayoutBuilder(const ItaniumRecordLayoutBuilder &) = delete;
+ void operator=(const ItaniumRecordLayoutBuilder &) = delete;
};
} // end anonymous namespace
-void
-RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
+void ItaniumRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
for (const auto &I : RD->bases()) {
assert(!I.getType()->isDependentType() &&
"Cannot layout class with dependent bases.");
@@ -817,7 +814,7 @@ RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
}
/// DeterminePrimaryBase - Determine the primary base of the given class.
-void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
+void ItaniumRecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
// If the class isn't dynamic, it won't have a primary base.
if (!RD->isDynamicClass())
return;
@@ -864,10 +861,8 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
assert(!PrimaryBase && "Should not get here with a primary base!");
}
-BaseSubobjectInfo *
-RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
- bool IsVirtual,
- BaseSubobjectInfo *Derived) {
+BaseSubobjectInfo *ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
+ const CXXRecordDecl *RD, bool IsVirtual, BaseSubobjectInfo *Derived) {
BaseSubobjectInfo *Info;
if (IsVirtual) {
@@ -943,7 +938,8 @@ RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD,
return Info;
}
-void RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD) {
+void ItaniumRecordLayoutBuilder::ComputeBaseSubobjectInfo(
+ const CXXRecordDecl *RD) {
for (const auto &I : RD->bases()) {
bool IsVirtual = I.isVirtual();
@@ -966,8 +962,8 @@ void RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD) {
}
}
-void
-RecordLayoutBuilder::EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign) {
+void ItaniumRecordLayoutBuilder::EnsureVTablePointerAlignment(
+ CharUnits UnpackedBaseAlign) {
CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign;
// The maximum field alignment overrides base align.
@@ -984,8 +980,8 @@ RecordLayoutBuilder::EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign) {
UpdateAlignment(BaseAlign, UnpackedBaseAlign);
}
-void
-RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
+void ItaniumRecordLayoutBuilder::LayoutNonVirtualBases(
+ const CXXRecordDecl *RD) {
// Then, determine the primary base class.
DeterminePrimaryBase(RD);
@@ -1054,7 +1050,8 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
}
}
-void RecordLayoutBuilder::LayoutNonVirtualBase(const BaseSubobjectInfo *Base) {
+void ItaniumRecordLayoutBuilder::LayoutNonVirtualBase(
+ const BaseSubobjectInfo *Base) {
// Layout the base.
CharUnits Offset = LayoutBase(Base);
@@ -1065,9 +1062,8 @@ void RecordLayoutBuilder::LayoutNonVirtualBase(const BaseSubobjectInfo *Base) {
AddPrimaryVirtualBaseOffsets(Base, Offset);
}
-void
-RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
- CharUnits Offset) {
+void ItaniumRecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(
+ const BaseSubobjectInfo *Info, CharUnits Offset) {
// This base isn't interesting, it has no virtual bases.
if (!Info->Class->getNumVBases())
return;
@@ -1099,9 +1095,8 @@ RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
}
}
-void
-RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
- const CXXRecordDecl *MostDerivedClass) {
+void ItaniumRecordLayoutBuilder::LayoutVirtualBases(
+ const CXXRecordDecl *RD, const CXXRecordDecl *MostDerivedClass) {
const CXXRecordDecl *PrimaryBase;
bool PrimaryBaseIsVirtual;
@@ -1146,7 +1141,8 @@ RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
}
}
-void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base) {
+void ItaniumRecordLayoutBuilder::LayoutVirtualBase(
+ const BaseSubobjectInfo *Base) {
assert(!Base->Derived && "Trying to lay out a primary virtual base!");
// Layout the base.
@@ -1160,7 +1156,8 @@ void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base) {
AddPrimaryVirtualBaseOffsets(Base, Offset);
}
-CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
+CharUnits
+ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base->Class);
@@ -1229,7 +1226,7 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
return Offset;
}
-void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
+void ItaniumRecordLayoutBuilder::InitializeLayout(const Decl *D) {
if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
IsUnion = RD->isUnion();
IsMsStruct = RD->isMsStruct(Context);
@@ -1277,7 +1274,7 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
}
}
-void RecordLayoutBuilder::Layout(const RecordDecl *D) {
+void ItaniumRecordLayoutBuilder::Layout(const RecordDecl *D) {
InitializeLayout(D);
LayoutFields(D);
@@ -1286,7 +1283,7 @@ void RecordLayoutBuilder::Layout(const RecordDecl *D) {
FinishLayout(D);
}
-void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
+void ItaniumRecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
InitializeLayout(RD);
// Lay out the vtable and the non-virtual bases.
@@ -1326,7 +1323,7 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
#endif
}
-void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
+void ItaniumRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
const ASTRecordLayout &SL = Context.getASTObjCInterfaceLayout(SD);
@@ -1349,7 +1346,7 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
FinishLayout(D);
}
-void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
+void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
// Layout each field, for now, just sequentially, respecting alignment. In
// the future, this will need to be tweakable by targets.
bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true);
@@ -1370,10 +1367,10 @@ roundUpSizeToCharAlignment(uint64_t Size,
return llvm::RoundUpToAlignment(Size, CharAlignment);
}
-void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
- uint64_t TypeSize,
- bool FieldPacked,
- const FieldDecl *D) {
+void ItaniumRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
+ uint64_t TypeSize,
+ bool FieldPacked,
+ const FieldDecl *D) {
assert(Context.getLangOpts().CPlusPlus &&
"Can only have wide bit-fields in C++!");
@@ -1437,7 +1434,7 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
UpdateAlignment(TypeAlign);
}
-void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
+void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
uint64_t FieldSize = D->getBitWidthValue(Context);
TypeInfo FieldInfo = Context.getTypeInfo(D->getType());
@@ -1555,7 +1552,8 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
FieldAlign = 1;
// But, if there's an 'aligned' attribute on the field, honor that.
- if (unsigned ExplicitFieldAlign = D->getMaxAlignment()) {
+ unsigned ExplicitFieldAlign = D->getMaxAlignment();
+ if (ExplicitFieldAlign) {
FieldAlign = std::max(FieldAlign, ExplicitFieldAlign);
UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign);
}
@@ -1568,6 +1566,12 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
}
+ // But, ms_struct just ignores all of that in unions, even explicit
+ // alignment attributes.
+ if (IsMsStruct && IsUnion) {
+ FieldAlign = UnpackedFieldAlign = 1;
+ }
+
// For purposes of diagnostics, we're going to simultaneously
// compute the field offsets that we would have used if we weren't
// adding any alignment padding or if the field weren't packed.
@@ -1598,6 +1602,10 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
(AllowPadding &&
(FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) {
FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
+ } else if (ExplicitFieldAlign) {
+ // TODO: figure it out what needs to be done on targets that don't honor
+ // bit-field type alignment like ARM APCS ABI.
+ FieldOffset = llvm::RoundUpToAlignment(FieldOffset, ExplicitFieldAlign);
}
// Repeat the computation for diagnostic purposes.
@@ -1606,6 +1614,9 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
(UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize))
UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
UnpackedFieldAlign);
+ else if (ExplicitFieldAlign)
+ UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
+ ExplicitFieldAlign);
}
// If we're using external layout, give the external layout a chance
@@ -1634,9 +1645,20 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
// For unions, this is just a max operation, as usual.
if (IsUnion) {
- uint64_t RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize,
- Context);
+ // For ms_struct, allocate the entire storage unit --- unless this
+ // is a zero-width bitfield, in which case just use a size of 1.
+ uint64_t RoundedFieldSize;
+ if (IsMsStruct) {
+ RoundedFieldSize =
+ (FieldSize ? TypeSize : Context.getTargetInfo().getCharWidth());
+
+ // Otherwise, allocate just the number of bytes required to store
+ // the bitfield.
+ } else {
+ RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize, Context);
+ }
setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize));
+
// For non-zero-width bitfields in ms_struct structs, allocate a new
// storage unit if necessary.
} else if (IsMsStruct && FieldSize) {
@@ -1672,8 +1694,8 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
Context.toCharUnitsFromBits(UnpackedFieldAlign));
}
-void RecordLayoutBuilder::LayoutField(const FieldDecl *D,
- bool InsertExtraPadding) {
+void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
+ bool InsertExtraPadding) {
if (D->isBitField()) {
LayoutBitField(D);
return;
@@ -1800,7 +1822,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D,
UpdateAlignment(FieldAlign, UnpackedFieldAlign);
}
-void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
+void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
// In C++, records cannot be of size 0.
if (Context.getLangOpts().CPlusPlus && getSizeInBits() == 0) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
@@ -1852,7 +1874,7 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
Diag(RD->getLocation(), diag::warn_padded_struct_size)
<< Context.getTypeDeclType(RD)
<< PadSize
- << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
+ << (InBits ? 1 : 0); // (byte|bit)
}
// Warn if we packed it unnecessarily. If the alignment is 1 byte don't
@@ -1864,8 +1886,8 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
}
}
-void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment,
- CharUnits UnpackedNewAlignment) {
+void ItaniumRecordLayoutBuilder::UpdateAlignment(
+ CharUnits NewAlignment, CharUnits UnpackedNewAlignment) {
// The alignment is not modified when using 'mac68k' alignment or when
// we have an externally-supplied layout that also provides overall alignment.
if (IsMac68kAlign || (UseExternalLayout && !InferAlignment))
@@ -1885,8 +1907,8 @@ void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment,
}
uint64_t
-RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
- uint64_t ComputedOffset) {
+ItaniumRecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field,
+ uint64_t ComputedOffset) {
uint64_t ExternalFieldOffset = External.getExternalFieldOffset(Field);
if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
@@ -1914,12 +1936,9 @@ static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag) {
}
}
-void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
- uint64_t UnpaddedOffset,
- uint64_t UnpackedOffset,
- unsigned UnpackedAlign,
- bool isPacked,
- const FieldDecl *D) {
+void ItaniumRecordLayoutBuilder::CheckFieldPadding(
+ uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset,
+ unsigned UnpackedAlign, bool isPacked, const FieldDecl *D) {
// We let objc ivars without warning, objc interfaces generally are not used
// for padding tricks.
if (isa<ObjCIvarDecl>(D))
@@ -1945,14 +1964,14 @@ void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
<< getPaddingDiagFromTagKind(D->getParent()->getTagKind())
<< Context.getTypeDeclType(D->getParent())
<< PadSize
- << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not
+ << (InBits ? 1 : 0) // (byte|bit)
<< D->getIdentifier();
else
Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
<< getPaddingDiagFromTagKind(D->getParent()->getTagKind())
<< Context.getTypeDeclType(D->getParent())
<< PadSize
- << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
+ << (InBits ? 1 : 0); // (byte|bit)
}
// Warn if we packed it unnecessarily. If the alignment is 1 byte don't
@@ -2014,6 +2033,21 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context,
continue;
}
+ if (Context.getLangOpts().CUDA) {
+ // While compiler may see key method in this TU, during CUDA
+ // compilation we should ignore methods that are not accessible
+ // on this side of compilation.
+ if (Context.getLangOpts().CUDAIsDevice) {
+ // In device mode ignore methods without __device__ attribute.
+ if (!MD->hasAttr<CUDADeviceAttr>())
+ continue;
+ } else {
+ // In host mode ignore __device__-only methods.
+ if (!MD->hasAttr<CUDAHostAttr>() && MD->hasAttr<CUDADeviceAttr>())
+ continue;
+ }
+ }
+
// If the key function is dllimport but the class isn't, then the class has
// no key function. The DLL that exports the key function won't export the
// vtable in this case.
@@ -2027,8 +2061,8 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context,
return nullptr;
}
-DiagnosticBuilder
-RecordLayoutBuilder::Diag(SourceLocation Loc, unsigned DiagID) {
+DiagnosticBuilder ItaniumRecordLayoutBuilder::Diag(SourceLocation Loc,
+ unsigned DiagID) {
return Context.getDiagnostics().Report(Loc, DiagID);
}
@@ -2074,8 +2108,8 @@ static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) {
llvm_unreachable("bad tail-padding use kind");
}
-static bool isMsLayout(const RecordDecl* D) {
- return D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft();
+static bool isMsLayout(const ASTContext &Context) {
+ return Context.getTargetInfo().getCXXABI().isMicrosoft();
}
// This section contains an implementation of struct layout that is, up to the
@@ -2656,13 +2690,20 @@ void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) {
// alignment.
CharUnits Offset = PointerInfo.Size.RoundUpToAlignment(
std::max(RequiredAlignment, Alignment));
- // Increase the size of the object and push back all fields, the vbptr and all
- // bases by the offset amount.
+ // Push back the vbptr, but increase the size of the object and push back
+ // regular fields by the offset only if not using external record layout.
+ if (HasVBPtr)
+ VBPtrOffset += Offset;
+
+ if (UseExternalLayout)
+ return;
+
Size += Offset;
+
+ // If we're using an external layout, the fields offsets have already
+ // accounted for this adjustment.
for (uint64_t &FieldOffset : FieldOffsets)
FieldOffset += Context.toBits(Offset);
- if (HasVBPtr)
- VBPtrOffset += Offset;
for (BaseOffsetsMapTy::value_type &Base : Bases)
Base.second += Offset;
}
@@ -2840,32 +2881,6 @@ void MicrosoftRecordLayoutBuilder::computeVtorDispSet(
}
}
-/// \brief Get or compute information about the layout of the specified record
-/// (struct/union/class), which indicates its size and field position
-/// information.
-const ASTRecordLayout *
-ASTContext::BuildMicrosoftASTRecordLayout(const RecordDecl *D) const {
- MicrosoftRecordLayoutBuilder Builder(*this);
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
- Builder.cxxLayout(RD);
- return new (*this) ASTRecordLayout(
- *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
- Builder.HasOwnVFPtr,
- Builder.HasOwnVFPtr || Builder.PrimaryBase,
- Builder.VBPtrOffset, Builder.NonVirtualSize, Builder.FieldOffsets.data(),
- Builder.FieldOffsets.size(), Builder.NonVirtualSize,
- Builder.Alignment, CharUnits::Zero(), Builder.PrimaryBase,
- false, Builder.SharedVBPtrBase,
- Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
- Builder.Bases, Builder.VBases);
- } else {
- Builder.layout(D);
- return new (*this) ASTRecordLayout(
- *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
- Builder.Size, Builder.FieldOffsets.data(), Builder.FieldOffsets.size());
- }
-}
-
/// getASTRecordLayout - Get or compute information about the layout of the
/// specified record (struct/union/class), which indicates its size and field
/// position information.
@@ -2892,54 +2907,63 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
const ASTRecordLayout *NewEntry = nullptr;
- if (isMsLayout(D)) {
- NewEntry = BuildMicrosoftASTRecordLayout(D);
- } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
- EmptySubobjectMap EmptySubobjects(*this, RD);
- RecordLayoutBuilder Builder(*this, &EmptySubobjects);
- Builder.Layout(RD);
-
- // In certain situations, we are allowed to lay out objects in the
- // tail-padding of base classes. This is ABI-dependent.
- // FIXME: this should be stored in the record layout.
- bool skipTailPadding =
- mustSkipTailPadding(getTargetInfo().getCXXABI(), cast<CXXRecordDecl>(D));
-
- // FIXME: This should be done in FinalizeLayout.
- CharUnits DataSize =
- skipTailPadding ? Builder.getSize() : Builder.getDataSize();
- CharUnits NonVirtualSize =
- skipTailPadding ? DataSize : Builder.NonVirtualSize;
- NewEntry =
- new (*this) ASTRecordLayout(*this, Builder.getSize(),
- Builder.Alignment,
- /*RequiredAlignment : used by MS-ABI)*/
- Builder.Alignment,
- Builder.HasOwnVFPtr,
- RD->isDynamicClass(),
- CharUnits::fromQuantity(-1),
- DataSize,
- Builder.FieldOffsets.data(),
- Builder.FieldOffsets.size(),
- NonVirtualSize,
- Builder.NonVirtualAlignment,
- EmptySubobjects.SizeOfLargestEmptySubobject,
- Builder.PrimaryBase,
- Builder.PrimaryBaseIsVirtual,
- nullptr, false, false,
- Builder.Bases, Builder.VBases);
+ if (isMsLayout(*this)) {
+ MicrosoftRecordLayoutBuilder Builder(*this);
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
+ Builder.cxxLayout(RD);
+ NewEntry = new (*this) ASTRecordLayout(
+ *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
+ Builder.HasOwnVFPtr, Builder.HasOwnVFPtr || Builder.PrimaryBase,
+ Builder.VBPtrOffset, Builder.NonVirtualSize,
+ Builder.FieldOffsets.data(), Builder.FieldOffsets.size(),
+ Builder.NonVirtualSize, Builder.Alignment, CharUnits::Zero(),
+ Builder.PrimaryBase, false, Builder.SharedVBPtrBase,
+ Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
+ Builder.Bases, Builder.VBases);
+ } else {
+ Builder.layout(D);
+ NewEntry = new (*this) ASTRecordLayout(
+ *this, Builder.Size, Builder.Alignment, Builder.RequiredAlignment,
+ Builder.Size, Builder.FieldOffsets.data(),
+ Builder.FieldOffsets.size());
+ }
} else {
- RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
- Builder.Layout(D);
-
- NewEntry =
- new (*this) ASTRecordLayout(*this, Builder.getSize(),
- Builder.Alignment,
- /*RequiredAlignment : used by MS-ABI)*/
- Builder.Alignment,
- Builder.getSize(),
- Builder.FieldOffsets.data(),
- Builder.FieldOffsets.size());
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
+ EmptySubobjectMap EmptySubobjects(*this, RD);
+ ItaniumRecordLayoutBuilder Builder(*this, &EmptySubobjects);
+ Builder.Layout(RD);
+
+ // In certain situations, we are allowed to lay out objects in the
+ // tail-padding of base classes. This is ABI-dependent.
+ // FIXME: this should be stored in the record layout.
+ bool skipTailPadding =
+ mustSkipTailPadding(getTargetInfo().getCXXABI(), RD);
+
+ // FIXME: This should be done in FinalizeLayout.
+ CharUnits DataSize =
+ skipTailPadding ? Builder.getSize() : Builder.getDataSize();
+ CharUnits NonVirtualSize =
+ skipTailPadding ? DataSize : Builder.NonVirtualSize;
+ NewEntry = new (*this) ASTRecordLayout(
+ *this, Builder.getSize(), Builder.Alignment,
+ /*RequiredAlignment : used by MS-ABI)*/
+ Builder.Alignment, Builder.HasOwnVFPtr, RD->isDynamicClass(),
+ CharUnits::fromQuantity(-1), DataSize, Builder.FieldOffsets.data(),
+ Builder.FieldOffsets.size(), NonVirtualSize,
+ Builder.NonVirtualAlignment,
+ EmptySubobjects.SizeOfLargestEmptySubobject, Builder.PrimaryBase,
+ Builder.PrimaryBaseIsVirtual, nullptr, false, false, Builder.Bases,
+ Builder.VBases);
+ } else {
+ ItaniumRecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
+ Builder.Layout(D);
+
+ NewEntry = new (*this) ASTRecordLayout(
+ *this, Builder.getSize(), Builder.Alignment,
+ /*RequiredAlignment : used by MS-ABI)*/
+ Builder.Alignment, Builder.getSize(), Builder.FieldOffsets.data(),
+ Builder.FieldOffsets.size());
+ }
}
ASTRecordLayouts[D] = NewEntry;
@@ -3049,7 +3073,7 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
return getObjCLayout(D, nullptr);
}
- RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
+ ItaniumRecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/nullptr);
Builder.Layout(D);
const ASTRecordLayout *NewEntry =
@@ -3068,148 +3092,193 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
static void PrintOffset(raw_ostream &OS,
CharUnits Offset, unsigned IndentLevel) {
- OS << llvm::format("%4" PRId64 " | ", (int64_t)Offset.getQuantity());
+ OS << llvm::format("%10" PRId64 " | ", (int64_t)Offset.getQuantity());
+ OS.indent(IndentLevel * 2);
+}
+
+static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset,
+ unsigned Begin, unsigned Width,
+ unsigned IndentLevel) {
+ llvm::SmallString<10> Buffer;
+ {
+ llvm::raw_svector_ostream BufferOS(Buffer);
+ BufferOS << Offset.getQuantity() << ':';
+ if (Width == 0) {
+ BufferOS << '-';
+ } else {
+ BufferOS << Begin << '-' << (Begin + Width - 1);
+ }
+ }
+
+ OS << llvm::right_justify(Buffer, 10) << " | ";
OS.indent(IndentLevel * 2);
}
static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel) {
- OS << " | ";
+ OS << " | ";
OS.indent(IndentLevel * 2);
}
-static void DumpCXXRecordLayout(raw_ostream &OS,
- const CXXRecordDecl *RD, const ASTContext &C,
- CharUnits Offset,
- unsigned IndentLevel,
- const char* Description,
- bool IncludeVirtualBases) {
+static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD,
+ const ASTContext &C,
+ CharUnits Offset,
+ unsigned IndentLevel,
+ const char* Description,
+ bool PrintSizeInfo,
+ bool IncludeVirtualBases) {
const ASTRecordLayout &Layout = C.getASTRecordLayout(RD);
+ auto CXXRD = dyn_cast<CXXRecordDecl>(RD);
PrintOffset(OS, Offset, IndentLevel);
- OS << C.getTypeDeclType(const_cast<CXXRecordDecl *>(RD)).getAsString();
+ OS << C.getTypeDeclType(const_cast<RecordDecl*>(RD)).getAsString();
if (Description)
OS << ' ' << Description;
- if (RD->isEmpty())
+ if (CXXRD && CXXRD->isEmpty())
OS << " (empty)";
OS << '\n';
IndentLevel++;
- const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
- bool HasOwnVFPtr = Layout.hasOwnVFPtr();
- bool HasOwnVBPtr = Layout.hasOwnVBPtr();
-
- // Vtable pointer.
- if (RD->isDynamicClass() && !PrimaryBase && !isMsLayout(RD)) {
- PrintOffset(OS, Offset, IndentLevel);
- OS << '(' << *RD << " vtable pointer)\n";
- } else if (HasOwnVFPtr) {
- PrintOffset(OS, Offset, IndentLevel);
- // vfptr (for Microsoft C++ ABI)
- OS << '(' << *RD << " vftable pointer)\n";
- }
-
- // Collect nvbases.
- SmallVector<const CXXRecordDecl *, 4> Bases;
- for (const CXXBaseSpecifier &Base : RD->bases()) {
- assert(!Base.getType()->isDependentType() &&
- "Cannot layout class with dependent bases.");
- if (!Base.isVirtual())
- Bases.push_back(Base.getType()->getAsCXXRecordDecl());
- }
+ // Dump bases.
+ if (CXXRD) {
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+ bool HasOwnVFPtr = Layout.hasOwnVFPtr();
+ bool HasOwnVBPtr = Layout.hasOwnVBPtr();
+
+ // Vtable pointer.
+ if (CXXRD->isDynamicClass() && !PrimaryBase && !isMsLayout(C)) {
+ PrintOffset(OS, Offset, IndentLevel);
+ OS << '(' << *RD << " vtable pointer)\n";
+ } else if (HasOwnVFPtr) {
+ PrintOffset(OS, Offset, IndentLevel);
+ // vfptr (for Microsoft C++ ABI)
+ OS << '(' << *RD << " vftable pointer)\n";
+ }
- // Sort nvbases by offset.
- std::stable_sort(Bases.begin(), Bases.end(),
- [&](const CXXRecordDecl *L, const CXXRecordDecl *R) {
- return Layout.getBaseClassOffset(L) < Layout.getBaseClassOffset(R);
- });
+ // Collect nvbases.
+ SmallVector<const CXXRecordDecl *, 4> Bases;
+ for (const CXXBaseSpecifier &Base : CXXRD->bases()) {
+ assert(!Base.getType()->isDependentType() &&
+ "Cannot layout class with dependent bases.");
+ if (!Base.isVirtual())
+ Bases.push_back(Base.getType()->getAsCXXRecordDecl());
+ }
- // Dump (non-virtual) bases
- for (const CXXRecordDecl *Base : Bases) {
- CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base);
- DumpCXXRecordLayout(OS, Base, C, BaseOffset, IndentLevel,
- Base == PrimaryBase ? "(primary base)" : "(base)",
- /*IncludeVirtualBases=*/false);
- }
+ // Sort nvbases by offset.
+ std::stable_sort(Bases.begin(), Bases.end(),
+ [&](const CXXRecordDecl *L, const CXXRecordDecl *R) {
+ return Layout.getBaseClassOffset(L) < Layout.getBaseClassOffset(R);
+ });
+
+ // Dump (non-virtual) bases
+ for (const CXXRecordDecl *Base : Bases) {
+ CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+ DumpRecordLayout(OS, Base, C, BaseOffset, IndentLevel,
+ Base == PrimaryBase ? "(primary base)" : "(base)",
+ /*PrintSizeInfo=*/false,
+ /*IncludeVirtualBases=*/false);
+ }
- // vbptr (for Microsoft C++ ABI)
- if (HasOwnVBPtr) {
- PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel);
- OS << '(' << *RD << " vbtable pointer)\n";
+ // vbptr (for Microsoft C++ ABI)
+ if (HasOwnVBPtr) {
+ PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel);
+ OS << '(' << *RD << " vbtable pointer)\n";
+ }
}
// Dump fields.
uint64_t FieldNo = 0;
- for (CXXRecordDecl::field_iterator I = RD->field_begin(),
+ for (RecordDecl::field_iterator I = RD->field_begin(),
E = RD->field_end(); I != E; ++I, ++FieldNo) {
const FieldDecl &Field = **I;
- CharUnits FieldOffset = Offset +
- C.toCharUnitsFromBits(Layout.getFieldOffset(FieldNo));
-
- if (const CXXRecordDecl *D = Field.getType()->getAsCXXRecordDecl()) {
- DumpCXXRecordLayout(OS, D, C, FieldOffset, IndentLevel,
- Field.getName().data(),
- /*IncludeVirtualBases=*/true);
+ uint64_t LocalFieldOffsetInBits = Layout.getFieldOffset(FieldNo);
+ CharUnits FieldOffset =
+ Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits);
+
+ // Recursively dump fields of record type.
+ if (auto RT = Field.getType()->getAs<RecordType>()) {
+ DumpRecordLayout(OS, RT->getDecl(), C, FieldOffset, IndentLevel,
+ Field.getName().data(),
+ /*PrintSizeInfo=*/false,
+ /*IncludeVirtualBases=*/true);
continue;
}
- PrintOffset(OS, FieldOffset, IndentLevel);
+ if (Field.isBitField()) {
+ uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset);
+ unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
+ unsigned Width = Field.getBitWidthValue(C);
+ PrintBitFieldOffset(OS, FieldOffset, Begin, Width, IndentLevel);
+ } else {
+ PrintOffset(OS, FieldOffset, IndentLevel);
+ }
OS << Field.getType().getAsString() << ' ' << Field << '\n';
}
- if (!IncludeVirtualBases)
- return;
-
// Dump virtual bases.
- const ASTRecordLayout::VBaseOffsetsMapTy &vtordisps =
- Layout.getVBaseOffsetsMap();
- for (const CXXBaseSpecifier &Base : RD->vbases()) {
- assert(Base.isVirtual() && "Found non-virtual class!");
- const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl();
+ if (CXXRD && IncludeVirtualBases) {
+ const ASTRecordLayout::VBaseOffsetsMapTy &VtorDisps =
+ Layout.getVBaseOffsetsMap();
- CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase);
+ for (const CXXBaseSpecifier &Base : CXXRD->vbases()) {
+ assert(Base.isVirtual() && "Found non-virtual class!");
+ const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl();
- if (vtordisps.find(VBase)->second.hasVtorDisp()) {
- PrintOffset(OS, VBaseOffset - CharUnits::fromQuantity(4), IndentLevel);
- OS << "(vtordisp for vbase " << *VBase << ")\n";
- }
+ CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase);
+
+ if (VtorDisps.find(VBase)->second.hasVtorDisp()) {
+ PrintOffset(OS, VBaseOffset - CharUnits::fromQuantity(4), IndentLevel);
+ OS << "(vtordisp for vbase " << *VBase << ")\n";
+ }
- DumpCXXRecordLayout(OS, VBase, C, VBaseOffset, IndentLevel,
- VBase == PrimaryBase ?
- "(primary virtual base)" : "(virtual base)",
- /*IncludeVirtualBases=*/false);
+ DumpRecordLayout(OS, VBase, C, VBaseOffset, IndentLevel,
+ VBase == Layout.getPrimaryBase() ?
+ "(primary virtual base)" : "(virtual base)",
+ /*PrintSizeInfo=*/false,
+ /*IncludeVirtualBases=*/false);
+ }
}
+ if (!PrintSizeInfo) return;
+
PrintIndentNoOffset(OS, IndentLevel - 1);
OS << "[sizeof=" << Layout.getSize().getQuantity();
- if (!isMsLayout(RD))
+ if (CXXRD && !isMsLayout(C))
OS << ", dsize=" << Layout.getDataSize().getQuantity();
- OS << ", align=" << Layout.getAlignment().getQuantity() << '\n';
+ OS << ", align=" << Layout.getAlignment().getQuantity();
- PrintIndentNoOffset(OS, IndentLevel - 1);
- OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity();
- OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity() << "]\n";
+ if (CXXRD) {
+ OS << ",\n";
+ PrintIndentNoOffset(OS, IndentLevel - 1);
+ OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity();
+ OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity();
+ }
+ OS << "]\n";
}
void ASTContext::DumpRecordLayout(const RecordDecl *RD,
raw_ostream &OS,
bool Simple) const {
- const ASTRecordLayout &Info = getASTRecordLayout(RD);
+ if (!Simple) {
+ ::DumpRecordLayout(OS, RD, *this, CharUnits(), 0, nullptr,
+ /*PrintSizeInfo*/true,
+ /*IncludeVirtualBases=*/true);
+ return;
+ }
- if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
- if (!Simple)
- return DumpCXXRecordLayout(OS, CXXRD, *this, CharUnits(), 0, nullptr,
- /*IncludeVirtualBases=*/true);
+ // The "simple" format is designed to be parsed by the
+ // layout-override testing code. There shouldn't be any external
+ // uses of this format --- when LLDB overrides a layout, it sets up
+ // the data structures directly --- so feel free to adjust this as
+ // you like as long as you also update the rudimentary parser for it
+ // in libFrontend.
+ const ASTRecordLayout &Info = getASTRecordLayout(RD);
OS << "Type: " << getTypeDeclType(RD).getAsString() << "\n";
- if (!Simple) {
- OS << "Record: ";
- RD->dump();
- }
OS << "\nLayout: ";
OS << "<ASTRecordLayout\n";
OS << " Size:" << toBits(Info.getSize()) << "\n";
- if (!isMsLayout(RD))
+ if (!isMsLayout(*this))
OS << " DataSize:" << toBits(Info.getDataSize()) << "\n";
OS << " Alignment:" << toBits(Info.getAlignment()) << "\n";
OS << " FieldOffsets: [";
diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
index e6292b4..ca63d84 100644
--- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
@@ -294,14 +295,15 @@ CompoundStmt::CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts,
std::copy(Stmts.begin(), Stmts.end(), Body);
}
-void CompoundStmt::setStmts(const ASTContext &C, Stmt **Stmts,
- unsigned NumStmts) {
- if (this->Body)
+void CompoundStmt::setStmts(const ASTContext &C, ArrayRef<Stmt *> Stmts) {
+ if (Body)
C.Deallocate(Body);
- this->CompoundStmtBits.NumStmts = NumStmts;
+ CompoundStmtBits.NumStmts = Stmts.size();
+ assert(CompoundStmtBits.NumStmts == Stmts.size() &&
+ "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
- Body = new (C) Stmt*[NumStmts];
- memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts);
+ Body = new (C) Stmt*[Stmts.size()];
+ std::copy(Stmts.begin(), Stmts.end(), Body);
}
const char *LabelStmt::getName() const {
@@ -675,12 +677,6 @@ void MSAsmStmt::setInputExpr(unsigned i, Expr *E) {
Exprs[i + NumOutputs] = E;
}
-QualType CXXCatchStmt::getCaughtType() const {
- if (ExceptionDecl)
- return ExceptionDecl->getType();
- return QualType();
-}
-
//===----------------------------------------------------------------------===//
// Constructors
//===----------------------------------------------------------------------===//
@@ -724,12 +720,7 @@ MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc,
}
static StringRef copyIntoContext(const ASTContext &C, StringRef str) {
- if (str.empty())
- return StringRef();
- size_t size = str.size();
- char *buffer = new (C) char[size];
- memcpy(buffer, str.data(), size);
- return StringRef(buffer, size);
+ return str.copy(C);
}
void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr,
@@ -740,145 +731,29 @@ void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr,
assert(NumAsmToks == asmtoks.size());
assert(NumClobbers == clobbers.size());
- unsigned NumExprs = exprs.size();
- assert(NumExprs == NumOutputs + NumInputs);
- assert(NumExprs == constraints.size());
+ assert(exprs.size() == NumOutputs + NumInputs);
+ assert(exprs.size() == constraints.size());
AsmStr = copyIntoContext(C, asmstr);
- Exprs = new (C) Stmt*[NumExprs];
- for (unsigned i = 0, e = NumExprs; i != e; ++i)
- Exprs[i] = exprs[i];
+ Exprs = new (C) Stmt*[exprs.size()];
+ std::copy(exprs.begin(), exprs.end(), Exprs);
- AsmToks = new (C) Token[NumAsmToks];
- for (unsigned i = 0, e = NumAsmToks; i != e; ++i)
- AsmToks[i] = asmtoks[i];
+ AsmToks = new (C) Token[asmtoks.size()];
+ std::copy(asmtoks.begin(), asmtoks.end(), AsmToks);
- Constraints = new (C) StringRef[NumExprs];
- for (unsigned i = 0, e = NumExprs; i != e; ++i) {
- Constraints[i] = copyIntoContext(C, constraints[i]);
- }
+ Constraints = new (C) StringRef[exprs.size()];
+ std::transform(constraints.begin(), constraints.end(), Constraints,
+ [&](StringRef Constraint) {
+ return copyIntoContext(C, Constraint);
+ });
Clobbers = new (C) StringRef[NumClobbers];
- for (unsigned i = 0, e = NumClobbers; i != e; ++i) {
- // FIXME: Avoid the allocation/copy if at all possible.
- Clobbers[i] = copyIntoContext(C, clobbers[i]);
- }
-}
-
-ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
- Stmt *Body, SourceLocation FCL,
- SourceLocation RPL)
-: Stmt(ObjCForCollectionStmtClass) {
- SubExprs[ELEM] = Elem;
- SubExprs[COLLECTION] = Collect;
- SubExprs[BODY] = Body;
- ForLoc = FCL;
- RParenLoc = RPL;
-}
-
-ObjCAtTryStmt::ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
- Stmt **CatchStmts, unsigned NumCatchStmts,
- Stmt *atFinallyStmt)
- : Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc),
- NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != nullptr) {
- Stmt **Stmts = getStmts();
- Stmts[0] = atTryStmt;
- for (unsigned I = 0; I != NumCatchStmts; ++I)
- Stmts[I + 1] = CatchStmts[I];
-
- if (HasFinally)
- Stmts[NumCatchStmts + 1] = atFinallyStmt;
-}
-
-ObjCAtTryStmt *ObjCAtTryStmt::Create(const ASTContext &Context,
- SourceLocation atTryLoc,
- Stmt *atTryStmt,
- Stmt **CatchStmts,
- unsigned NumCatchStmts,
- Stmt *atFinallyStmt) {
- unsigned Size = sizeof(ObjCAtTryStmt) +
- (1 + NumCatchStmts + (atFinallyStmt != nullptr)) * sizeof(Stmt *);
- void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
- return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts,
- atFinallyStmt);
-}
-
-ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(const ASTContext &Context,
- unsigned NumCatchStmts,
- bool HasFinally) {
- unsigned Size = sizeof(ObjCAtTryStmt) +
- (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *);
- void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
- return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally);
-}
-
-SourceLocation ObjCAtTryStmt::getLocEnd() const {
- if (HasFinally)
- return getFinallyStmt()->getLocEnd();
- if (NumCatchStmts)
- return getCatchStmt(NumCatchStmts - 1)->getLocEnd();
- return getTryBody()->getLocEnd();
-}
-
-CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc,
- Stmt *tryBlock, ArrayRef<Stmt*> handlers) {
- std::size_t Size = sizeof(CXXTryStmt);
- Size += ((handlers.size() + 1) * sizeof(Stmt));
-
- void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
- return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers);
-}
-
-CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty,
- unsigned numHandlers) {
- std::size_t Size = sizeof(CXXTryStmt);
- Size += ((numHandlers + 1) * sizeof(Stmt));
-
- void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
- return new (Mem) CXXTryStmt(Empty, numHandlers);
-}
-
-CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
- ArrayRef<Stmt*> handlers)
- : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(handlers.size()) {
- Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
- Stmts[0] = tryBlock;
- std::copy(handlers.begin(), handlers.end(), Stmts + 1);
-}
-
-CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt,
- Expr *Cond, Expr *Inc, DeclStmt *LoopVar,
- Stmt *Body, SourceLocation FL,
- SourceLocation CL, SourceLocation RPL)
- : Stmt(CXXForRangeStmtClass), ForLoc(FL), ColonLoc(CL), RParenLoc(RPL) {
- SubExprs[RANGE] = Range;
- SubExprs[BEGINEND] = BeginEndStmt;
- SubExprs[COND] = Cond;
- SubExprs[INC] = Inc;
- SubExprs[LOOPVAR] = LoopVar;
- SubExprs[BODY] = Body;
-}
-
-Expr *CXXForRangeStmt::getRangeInit() {
- DeclStmt *RangeStmt = getRangeStmt();
- VarDecl *RangeDecl = dyn_cast_or_null<VarDecl>(RangeStmt->getSingleDecl());
- assert(RangeDecl && "for-range should have a single var decl");
- return RangeDecl->getInit();
-}
-
-const Expr *CXXForRangeStmt::getRangeInit() const {
- return const_cast<CXXForRangeStmt*>(this)->getRangeInit();
-}
-
-VarDecl *CXXForRangeStmt::getLoopVariable() {
- Decl *LV = cast<DeclStmt>(getLoopVarStmt())->getSingleDecl();
- assert(LV && "No loop variable in CXXForRangeStmt");
- return cast<VarDecl>(LV);
-}
-
-const VarDecl *CXXForRangeStmt::getLoopVariable() const {
- return const_cast<CXXForRangeStmt*>(this)->getLoopVariable();
+ // FIXME: Avoid the allocation/copy if at all possible.
+ std::transform(clobbers.begin(), clobbers.end(), Clobbers,
+ [&](StringRef Clobber) {
+ return copyIntoContext(C, Clobber);
+ });
}
IfStmt::IfStmt(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
@@ -1070,6 +945,44 @@ SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc,
return new(C)SEHFinallyStmt(Loc,Block);
}
+CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind,
+ VarDecl *Var)
+ : VarAndKind(Var, Kind), Loc(Loc) {
+ switch (Kind) {
+ case VCK_This:
+ assert(!Var && "'this' capture cannot have a variable!");
+ break;
+ case VCK_ByRef:
+ assert(Var && "capturing by reference must have a variable!");
+ break;
+ case VCK_ByCopy:
+ assert(Var && "capturing by copy must have a variable!");
+ assert(
+ (Var->getType()->isScalarType() || (Var->getType()->isReferenceType() &&
+ Var->getType()
+ ->castAs<ReferenceType>()
+ ->getPointeeType()
+ ->isScalarType())) &&
+ "captures by copy are expected to have a scalar type!");
+ break;
+ case VCK_VLAType:
+ assert(!Var &&
+ "Variable-length array type capture cannot have a variable!");
+ break;
+ }
+}
+
+CapturedStmt::VariableCaptureKind
+CapturedStmt::Capture::getCaptureKind() const {
+ return VarAndKind.getInt();
+}
+
+VarDecl *CapturedStmt::Capture::getCapturedVar() const {
+ assert((capturesVariable() || capturesVariableByCopy()) &&
+ "No variable available for 'this' or VAT capture");
+ return VarAndKind.getPointer();
+}
+
CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const {
unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
@@ -1158,6 +1071,29 @@ Stmt::child_range CapturedStmt::children() {
return child_range(getStoredStmts(), getStoredStmts() + NumCaptures);
}
+CapturedDecl *CapturedStmt::getCapturedDecl() {
+ return CapDeclAndKind.getPointer();
+}
+const CapturedDecl *CapturedStmt::getCapturedDecl() const {
+ return CapDeclAndKind.getPointer();
+}
+
+/// \brief Set the outlined function declaration.
+void CapturedStmt::setCapturedDecl(CapturedDecl *D) {
+ assert(D && "null CapturedDecl");
+ CapDeclAndKind.setPointer(D);
+}
+
+/// \brief Retrieve the captured region kind.
+CapturedRegionKind CapturedStmt::getCapturedRegionKind() const {
+ return CapDeclAndKind.getInt();
+}
+
+/// \brief Set the captured region kind.
+void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) {
+ CapDeclAndKind.setInt(Kind);
+}
+
bool CapturedStmt::capturesVariable(const VarDecl *Var) const {
for (const auto &I : captures()) {
if (!I.capturesVariable())
@@ -1172,1095 +1108,3 @@ bool CapturedStmt::capturesVariable(const VarDecl *Var) const {
return false;
}
-
-StmtRange OMPClause::children() {
- switch(getClauseKind()) {
- default : break;
-#define OPENMP_CLAUSE(Name, Class) \
- case OMPC_ ## Name : return static_cast<Class *>(this)->children();
-#include "clang/Basic/OpenMPKinds.def"
- }
- llvm_unreachable("unknown OMPClause");
-}
-
-void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
- assert(VL.size() == varlist_size() &&
- "Number of private copies is not the same as the preallocated buffer");
- std::copy(VL.begin(), VL.end(), varlist_end());
-}
-
-OMPPrivateClause *
-OMPPrivateClause::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc,
- ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL) {
- // Allocate space for private variables and initializer expressions.
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause),
- llvm::alignOf<Expr *>()) +
- 2 * sizeof(Expr *) * VL.size());
- OMPPrivateClause *Clause =
- new (Mem) OMPPrivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
- Clause->setPrivateCopies(PrivateVL);
- return Clause;
-}
-
-OMPPrivateClause *OMPPrivateClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause),
- llvm::alignOf<Expr *>()) +
- 2 * sizeof(Expr *) * N);
- return new (Mem) OMPPrivateClause(N);
-}
-
-void OMPFirstprivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
- assert(VL.size() == varlist_size() &&
- "Number of private copies is not the same as the preallocated buffer");
- std::copy(VL.begin(), VL.end(), varlist_end());
-}
-
-void OMPFirstprivateClause::setInits(ArrayRef<Expr *> VL) {
- assert(VL.size() == varlist_size() &&
- "Number of inits is not the same as the preallocated buffer");
- std::copy(VL.begin(), VL.end(), getPrivateCopies().end());
-}
-
-OMPFirstprivateClause *
-OMPFirstprivateClause::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc,
- ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL,
- ArrayRef<Expr *> InitVL) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFirstprivateClause),
- llvm::alignOf<Expr *>()) +
- 3 * sizeof(Expr *) * VL.size());
- OMPFirstprivateClause *Clause =
- new (Mem) OMPFirstprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
- Clause->setPrivateCopies(PrivateVL);
- Clause->setInits(InitVL);
- return Clause;
-}
-
-OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFirstprivateClause),
- llvm::alignOf<Expr *>()) +
- 3 * sizeof(Expr *) * N);
- return new (Mem) OMPFirstprivateClause(N);
-}
-
-void OMPLastprivateClause::setPrivateCopies(ArrayRef<Expr *> PrivateCopies) {
- assert(PrivateCopies.size() == varlist_size() &&
- "Number of private copies is not the same as the preallocated buffer");
- std::copy(PrivateCopies.begin(), PrivateCopies.end(), varlist_end());
-}
-
-void OMPLastprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
- assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
- "not the same as the "
- "preallocated buffer");
- std::copy(SrcExprs.begin(), SrcExprs.end(), getPrivateCopies().end());
-}
-
-void OMPLastprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
- assert(DstExprs.size() == varlist_size() && "Number of destination "
- "expressions is not the same as "
- "the preallocated buffer");
- std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
-}
-
-void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
- assert(AssignmentOps.size() == varlist_size() &&
- "Number of assignment expressions is not the same as the preallocated "
- "buffer");
- std::copy(AssignmentOps.begin(), AssignmentOps.end(),
- getDestinationExprs().end());
-}
-
-OMPLastprivateClause *OMPLastprivateClause::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
- ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause),
- llvm::alignOf<Expr *>()) +
- 5 * sizeof(Expr *) * VL.size());
- OMPLastprivateClause *Clause =
- new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
- Clause->setSourceExprs(SrcExprs);
- Clause->setDestinationExprs(DstExprs);
- Clause->setAssignmentOps(AssignmentOps);
- return Clause;
-}
-
-OMPLastprivateClause *OMPLastprivateClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLastprivateClause),
- llvm::alignOf<Expr *>()) +
- 5 * sizeof(Expr *) * N);
- return new (Mem) OMPLastprivateClause(N);
-}
-
-OMPSharedClause *OMPSharedClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPSharedClause),
- llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
- OMPSharedClause *Clause = new (Mem) OMPSharedClause(StartLoc, LParenLoc,
- EndLoc, VL.size());
- Clause->setVarRefs(VL);
- return Clause;
-}
-
-OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPSharedClause),
- llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
- return new (Mem) OMPSharedClause(N);
-}
-
-void OMPLinearClause::setInits(ArrayRef<Expr *> IL) {
- assert(IL.size() == varlist_size() &&
- "Number of inits is not the same as the preallocated buffer");
- std::copy(IL.begin(), IL.end(), varlist_end());
-}
-
-void OMPLinearClause::setUpdates(ArrayRef<Expr *> UL) {
- assert(UL.size() == varlist_size() &&
- "Number of updates is not the same as the preallocated buffer");
- std::copy(UL.begin(), UL.end(), getInits().end());
-}
-
-void OMPLinearClause::setFinals(ArrayRef<Expr *> FL) {
- assert(FL.size() == varlist_size() &&
- "Number of final updates is not the same as the preallocated buffer");
- std::copy(FL.begin(), FL.end(), getUpdates().end());
-}
-
-OMPLinearClause *
-OMPLinearClause::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation ColonLoc,
- SourceLocation EndLoc, ArrayRef<Expr *> VL,
- ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep) {
- // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions
- // (Step and CalcStep).
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
- llvm::alignOf<Expr *>()) +
- (4 * VL.size() + 2) * sizeof(Expr *));
- OMPLinearClause *Clause = new (Mem)
- OMPLinearClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
- Clause->setInits(IL);
- // Fill update and final expressions with zeroes, they are provided later,
- // after the directive construction.
- std::fill(Clause->getInits().end(), Clause->getInits().end() + VL.size(),
- nullptr);
- std::fill(Clause->getUpdates().end(), Clause->getUpdates().end() + VL.size(),
- nullptr);
- Clause->setStep(Step);
- Clause->setCalcStep(CalcStep);
- return Clause;
-}
-
-OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C,
- unsigned NumVars) {
- // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions
- // (Step and CalcStep).
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
- llvm::alignOf<Expr *>()) +
- (4 * NumVars + 2) * sizeof(Expr *));
- return new (Mem) OMPLinearClause(NumVars);
-}
-
-OMPAlignedClause *
-OMPAlignedClause::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation ColonLoc,
- SourceLocation EndLoc, ArrayRef<Expr *> VL, Expr *A) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPAlignedClause),
- llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * (VL.size() + 1));
- OMPAlignedClause *Clause = new (Mem)
- OMPAlignedClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
- Clause->setAlignment(A);
- return Clause;
-}
-
-OMPAlignedClause *OMPAlignedClause::CreateEmpty(const ASTContext &C,
- unsigned NumVars) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPAlignedClause),
- llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * (NumVars + 1));
- return new (Mem) OMPAlignedClause(NumVars);
-}
-
-void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
- assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
- "not the same as the "
- "preallocated buffer");
- std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end());
-}
-
-void OMPCopyinClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
- assert(DstExprs.size() == varlist_size() && "Number of destination "
- "expressions is not the same as "
- "the preallocated buffer");
- std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
-}
-
-void OMPCopyinClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
- assert(AssignmentOps.size() == varlist_size() &&
- "Number of assignment expressions is not the same as the preallocated "
- "buffer");
- std::copy(AssignmentOps.begin(), AssignmentOps.end(),
- getDestinationExprs().end());
-}
-
-OMPCopyinClause *OMPCopyinClause::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
- ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
- llvm::alignOf<Expr *>()) +
- 4 * sizeof(Expr *) * VL.size());
- OMPCopyinClause *Clause = new (Mem) OMPCopyinClause(StartLoc, LParenLoc,
- EndLoc, VL.size());
- Clause->setVarRefs(VL);
- Clause->setSourceExprs(SrcExprs);
- Clause->setDestinationExprs(DstExprs);
- Clause->setAssignmentOps(AssignmentOps);
- return Clause;
-}
-
-OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
- llvm::alignOf<Expr *>()) +
- 4 * sizeof(Expr *) * N);
- return new (Mem) OMPCopyinClause(N);
-}
-
-void OMPCopyprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
- assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
- "not the same as the "
- "preallocated buffer");
- std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end());
-}
-
-void OMPCopyprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
- assert(DstExprs.size() == varlist_size() && "Number of destination "
- "expressions is not the same as "
- "the preallocated buffer");
- std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
-}
-
-void OMPCopyprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
- assert(AssignmentOps.size() == varlist_size() &&
- "Number of assignment expressions is not the same as the preallocated "
- "buffer");
- std::copy(AssignmentOps.begin(), AssignmentOps.end(),
- getDestinationExprs().end());
-}
-
-OMPCopyprivateClause *OMPCopyprivateClause::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
- ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
- llvm::alignOf<Expr *>()) +
- 4 * sizeof(Expr *) * VL.size());
- OMPCopyprivateClause *Clause =
- new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
- Clause->setSourceExprs(SrcExprs);
- Clause->setDestinationExprs(DstExprs);
- Clause->setAssignmentOps(AssignmentOps);
- return Clause;
-}
-
-OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
- llvm::alignOf<Expr *>()) +
- 4 * sizeof(Expr *) * N);
- return new (Mem) OMPCopyprivateClause(N);
-}
-
-void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {
- assert(Clauses.size() == getNumClauses() &&
- "Number of clauses is not the same as the preallocated buffer");
- std::copy(Clauses.begin(), Clauses.end(), getClauses().begin());
-}
-
-void OMPLoopDirective::setCounters(ArrayRef<Expr *> A) {
- assert(A.size() == getCollapsedNumber() &&
- "Number of loop counters is not the same as the collapsed number");
- std::copy(A.begin(), A.end(), getCounters().begin());
-}
-
-void OMPLoopDirective::setInits(ArrayRef<Expr *> A) {
- assert(A.size() == getCollapsedNumber() &&
- "Number of counter inits is not the same as the collapsed number");
- std::copy(A.begin(), A.end(), getInits().begin());
-}
-
-void OMPLoopDirective::setUpdates(ArrayRef<Expr *> A) {
- assert(A.size() == getCollapsedNumber() &&
- "Number of counter updates is not the same as the collapsed number");
- std::copy(A.begin(), A.end(), getUpdates().begin());
-}
-
-void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) {
- assert(A.size() == getCollapsedNumber() &&
- "Number of counter finals is not the same as the collapsed number");
- std::copy(A.begin(), A.end(), getFinals().begin());
-}
-
-void OMPReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
- assert(
- LHSExprs.size() == varlist_size() &&
- "Number of LHS expressions is not the same as the preallocated buffer");
- std::copy(LHSExprs.begin(), LHSExprs.end(), varlist_end());
-}
-
-void OMPReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
- assert(
- RHSExprs.size() == varlist_size() &&
- "Number of RHS expressions is not the same as the preallocated buffer");
- std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end());
-}
-
-void OMPReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
- assert(ReductionOps.size() == varlist_size() && "Number of reduction "
- "expressions is not the same "
- "as the preallocated buffer");
- std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
-}
-
-OMPReductionClause *OMPReductionClause::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
- NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
- ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
- ArrayRef<Expr *> ReductionOps) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause),
- llvm::alignOf<Expr *>()) +
- 4 * sizeof(Expr *) * VL.size());
- OMPReductionClause *Clause = new (Mem) OMPReductionClause(
- StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
- Clause->setVarRefs(VL);
- Clause->setLHSExprs(LHSExprs);
- Clause->setRHSExprs(RHSExprs);
- Clause->setReductionOps(ReductionOps);
- return Clause;
-}
-
-OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPReductionClause),
- llvm::alignOf<Expr *>()) +
- 4 * sizeof(Expr *) * N);
- return new (Mem) OMPReductionClause(N);
-}
-
-OMPFlushClause *OMPFlushClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFlushClause),
- llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
- OMPFlushClause *Clause =
- new (Mem) OMPFlushClause(StartLoc, LParenLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
- return Clause;
-}
-
-OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFlushClause),
- llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
- return new (Mem) OMPFlushClause(N);
-}
-
-OMPDependClause *
-OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc,
- OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
- SourceLocation ColonLoc, ArrayRef<Expr *> VL) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPDependClause),
- llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * VL.size());
- OMPDependClause *Clause =
- new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
- Clause->setDependencyKind(DepKind);
- Clause->setDependencyLoc(DepLoc);
- Clause->setColonLoc(ColonLoc);
- return Clause;
-}
-
-OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) {
- void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPDependClause),
- llvm::alignOf<Expr *>()) +
- sizeof(Expr *) * N);
- return new (Mem) OMPDependClause(N);
-}
-
-const OMPClause *
-OMPExecutableDirective::getSingleClause(OpenMPClauseKind K) const {
- auto &&I = getClausesOfKind(K);
-
- if (I) {
- auto *Clause = *I;
- assert(!++I && "There are at least 2 clauses of the specified kind");
- return Clause;
- }
- return nullptr;
-}
-
-OMPParallelDirective *OMPParallelDirective::Create(
- const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
- sizeof(Stmt *));
- OMPParallelDirective *Dir = new (Mem) OMPParallelDirective(StartLoc, EndLoc,
- Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
- sizeof(Stmt *));
- return new (Mem) OMPParallelDirective(NumClauses);
-}
-
-OMPSimdDirective *
-OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation EndLoc, unsigned CollapsedNum,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
- sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
- OMPSimdDirective *Dir = new (Mem)
- OMPSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- Dir->setIterationVariable(Exprs.IterationVarRef);
- Dir->setLastIteration(Exprs.LastIteration);
- Dir->setCalcLastIteration(Exprs.CalcLastIteration);
- Dir->setPreCond(Exprs.PreCond);
- Dir->setCond(Exprs.Cond);
- Dir->setInit(Exprs.Init);
- Dir->setInc(Exprs.Inc);
- Dir->setCounters(Exprs.Counters);
- Dir->setInits(Exprs.Inits);
- Dir->setUpdates(Exprs.Updates);
- Dir->setFinals(Exprs.Finals);
- return Dir;
-}
-
-OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- unsigned CollapsedNum,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
- sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
- return new (Mem) OMPSimdDirective(CollapsedNum, NumClauses);
-}
-
-OMPForDirective *
-OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation EndLoc, unsigned CollapsedNum,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
- sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
- OMPForDirective *Dir =
- new (Mem) OMPForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- Dir->setIterationVariable(Exprs.IterationVarRef);
- Dir->setLastIteration(Exprs.LastIteration);
- Dir->setCalcLastIteration(Exprs.CalcLastIteration);
- Dir->setPreCond(Exprs.PreCond);
- Dir->setCond(Exprs.Cond);
- Dir->setInit(Exprs.Init);
- Dir->setInc(Exprs.Inc);
- Dir->setIsLastIterVariable(Exprs.IL);
- Dir->setLowerBoundVariable(Exprs.LB);
- Dir->setUpperBoundVariable(Exprs.UB);
- Dir->setStrideVariable(Exprs.ST);
- Dir->setEnsureUpperBound(Exprs.EUB);
- Dir->setNextLowerBound(Exprs.NLB);
- Dir->setNextUpperBound(Exprs.NUB);
- Dir->setCounters(Exprs.Counters);
- Dir->setInits(Exprs.Inits);
- Dir->setUpdates(Exprs.Updates);
- Dir->setFinals(Exprs.Finals);
- return Dir;
-}
-
-OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- unsigned CollapsedNum,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
- sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
- return new (Mem) OMPForDirective(CollapsedNum, NumClauses);
-}
-
-OMPForSimdDirective *
-OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation EndLoc, unsigned CollapsedNum,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
- sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
- OMPForSimdDirective *Dir = new (Mem)
- OMPForSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- Dir->setIterationVariable(Exprs.IterationVarRef);
- Dir->setLastIteration(Exprs.LastIteration);
- Dir->setCalcLastIteration(Exprs.CalcLastIteration);
- Dir->setPreCond(Exprs.PreCond);
- Dir->setCond(Exprs.Cond);
- Dir->setInit(Exprs.Init);
- Dir->setInc(Exprs.Inc);
- Dir->setIsLastIterVariable(Exprs.IL);
- Dir->setLowerBoundVariable(Exprs.LB);
- Dir->setUpperBoundVariable(Exprs.UB);
- Dir->setStrideVariable(Exprs.ST);
- Dir->setEnsureUpperBound(Exprs.EUB);
- Dir->setNextLowerBound(Exprs.NLB);
- Dir->setNextUpperBound(Exprs.NUB);
- Dir->setCounters(Exprs.Counters);
- Dir->setInits(Exprs.Inits);
- Dir->setUpdates(Exprs.Updates);
- Dir->setFinals(Exprs.Finals);
- return Dir;
-}
-
-OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- unsigned CollapsedNum,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
- sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
- return new (Mem) OMPForSimdDirective(CollapsedNum, NumClauses);
-}
-
-OMPSectionsDirective *OMPSectionsDirective::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionsDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
- OMPSectionsDirective *Dir =
- new (Mem) OMPSectionsDirective(StartLoc, EndLoc, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPSectionsDirective *OMPSectionsDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionsDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
- return new (Mem) OMPSectionsDirective(NumClauses);
-}
-
-OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
- OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPSectionDirective *OMPSectionDirective::CreateEmpty(const ASTContext &C,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
- return new (Mem) OMPSectionDirective();
-}
-
-OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSingleDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
- OMPSingleDirective *Dir =
- new (Mem) OMPSingleDirective(StartLoc, EndLoc, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPSingleDirective *OMPSingleDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSingleDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
- return new (Mem) OMPSingleDirective(NumClauses);
-}
-
-OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPMasterDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
- OMPMasterDirective *Dir = new (Mem) OMPMasterDirective(StartLoc, EndLoc);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPMasterDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
- return new (Mem) OMPMasterDirective();
-}
-
-OMPCriticalDirective *OMPCriticalDirective::Create(
- const ASTContext &C, const DeclarationNameInfo &Name,
- SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
- OMPCriticalDirective *Dir =
- new (Mem) OMPCriticalDirective(Name, StartLoc, EndLoc);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
- return new (Mem) OMPCriticalDirective();
-}
-
-OMPParallelForDirective *OMPParallelForDirective::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
- sizeof(Stmt *) *
- numLoopChildren(CollapsedNum, OMPD_parallel_for));
- OMPParallelForDirective *Dir = new (Mem)
- OMPParallelForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- Dir->setIterationVariable(Exprs.IterationVarRef);
- Dir->setLastIteration(Exprs.LastIteration);
- Dir->setCalcLastIteration(Exprs.CalcLastIteration);
- Dir->setPreCond(Exprs.PreCond);
- Dir->setCond(Exprs.Cond);
- Dir->setInit(Exprs.Init);
- Dir->setInc(Exprs.Inc);
- Dir->setIsLastIterVariable(Exprs.IL);
- Dir->setLowerBoundVariable(Exprs.LB);
- Dir->setUpperBoundVariable(Exprs.UB);
- Dir->setStrideVariable(Exprs.ST);
- Dir->setEnsureUpperBound(Exprs.EUB);
- Dir->setNextLowerBound(Exprs.NLB);
- Dir->setNextUpperBound(Exprs.NUB);
- Dir->setCounters(Exprs.Counters);
- Dir->setInits(Exprs.Inits);
- Dir->setUpdates(Exprs.Updates);
- Dir->setFinals(Exprs.Finals);
- return Dir;
-}
-
-OMPParallelForDirective *
-OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
- unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
- sizeof(Stmt *) *
- numLoopChildren(CollapsedNum, OMPD_parallel_for));
- return new (Mem) OMPParallelForDirective(CollapsedNum, NumClauses);
-}
-
-OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
- const HelperExprs &Exprs) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem = C.Allocate(
- Size + sizeof(OMPClause *) * Clauses.size() +
- sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
- OMPParallelForSimdDirective *Dir = new (Mem) OMPParallelForSimdDirective(
- StartLoc, EndLoc, CollapsedNum, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- Dir->setIterationVariable(Exprs.IterationVarRef);
- Dir->setLastIteration(Exprs.LastIteration);
- Dir->setCalcLastIteration(Exprs.CalcLastIteration);
- Dir->setPreCond(Exprs.PreCond);
- Dir->setCond(Exprs.Cond);
- Dir->setInit(Exprs.Init);
- Dir->setInc(Exprs.Inc);
- Dir->setIsLastIterVariable(Exprs.IL);
- Dir->setLowerBoundVariable(Exprs.LB);
- Dir->setUpperBoundVariable(Exprs.UB);
- Dir->setStrideVariable(Exprs.ST);
- Dir->setEnsureUpperBound(Exprs.EUB);
- Dir->setNextLowerBound(Exprs.NLB);
- Dir->setNextUpperBound(Exprs.NUB);
- Dir->setCounters(Exprs.Counters);
- Dir->setInits(Exprs.Inits);
- Dir->setUpdates(Exprs.Updates);
- Dir->setFinals(Exprs.Finals);
- return Dir;
-}
-
-OMPParallelForSimdDirective *
-OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem = C.Allocate(
- Size + sizeof(OMPClause *) * NumClauses +
- sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
- return new (Mem) OMPParallelForSimdDirective(CollapsedNum, NumClauses);
-}
-
-OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelSectionsDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
- OMPParallelSectionsDirective *Dir =
- new (Mem) OMPParallelSectionsDirective(StartLoc, EndLoc, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPParallelSectionsDirective *
-OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses, EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelSectionsDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
- return new (Mem) OMPParallelSectionsDirective(NumClauses);
-}
-
-OMPTaskDirective *OMPTaskDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
- OMPTaskDirective *Dir =
- new (Mem) OMPTaskDirective(StartLoc, EndLoc, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
- return new (Mem) OMPTaskDirective(NumClauses);
-}
-
-OMPTaskyieldDirective *OMPTaskyieldDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
- void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective));
- OMPTaskyieldDirective *Dir =
- new (Mem) OMPTaskyieldDirective(StartLoc, EndLoc);
- return Dir;
-}
-
-OMPTaskyieldDirective *OMPTaskyieldDirective::CreateEmpty(const ASTContext &C,
- EmptyShell) {
- void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective));
- return new (Mem) OMPTaskyieldDirective();
-}
-
-OMPBarrierDirective *OMPBarrierDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
- void *Mem = C.Allocate(sizeof(OMPBarrierDirective));
- OMPBarrierDirective *Dir = new (Mem) OMPBarrierDirective(StartLoc, EndLoc);
- return Dir;
-}
-
-OMPBarrierDirective *OMPBarrierDirective::CreateEmpty(const ASTContext &C,
- EmptyShell) {
- void *Mem = C.Allocate(sizeof(OMPBarrierDirective));
- return new (Mem) OMPBarrierDirective();
-}
-
-OMPTaskwaitDirective *OMPTaskwaitDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
- void *Mem = C.Allocate(sizeof(OMPTaskwaitDirective));
- OMPTaskwaitDirective *Dir = new (Mem) OMPTaskwaitDirective(StartLoc, EndLoc);
- return Dir;
-}
-
-OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C,
- EmptyShell) {
- void *Mem = C.Allocate(sizeof(OMPTaskwaitDirective));
- return new (Mem) OMPTaskwaitDirective();
-}
-
-OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
- OMPTaskgroupDirective *Dir =
- new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
- return new (Mem) OMPTaskgroupDirective();
-}
-
-OMPCancellationPointDirective *OMPCancellationPointDirective::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- OpenMPDirectiveKind CancelRegion) {
- unsigned Size = llvm::RoundUpToAlignment(
- sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size);
- OMPCancellationPointDirective *Dir =
- new (Mem) OMPCancellationPointDirective(StartLoc, EndLoc);
- Dir->setCancelRegion(CancelRegion);
- return Dir;
-}
-
-OMPCancellationPointDirective *
-OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(
- sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size);
- return new (Mem) OMPCancellationPointDirective();
-}
-
-OMPCancelDirective *
-OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation EndLoc,
- OpenMPDirectiveKind CancelRegion) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCancelDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size);
- OMPCancelDirective *Dir = new (Mem) OMPCancelDirective(StartLoc, EndLoc);
- Dir->setCancelRegion(CancelRegion);
- return Dir;
-}
-
-OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCancelDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size);
- return new (Mem) OMPCancelDirective();
-}
-
-OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPFlushDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size());
- OMPFlushDirective *Dir =
- new (Mem) OMPFlushDirective(StartLoc, EndLoc, Clauses.size());
- Dir->setClauses(Clauses);
- return Dir;
-}
-
-OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPFlushDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses);
- return new (Mem) OMPFlushDirective(NumClauses);
-}
-
-OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
- OMPOrderedDirective *Dir = new (Mem) OMPOrderedDirective(StartLoc, EndLoc);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective),
- llvm::alignOf<Stmt *>());
- void *Mem = C.Allocate(Size + sizeof(Stmt *));
- return new (Mem) OMPOrderedDirective();
-}
-
-OMPAtomicDirective *OMPAtomicDirective::Create(
- const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
- Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
- 5 * sizeof(Stmt *));
- OMPAtomicDirective *Dir =
- new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- Dir->setX(X);
- Dir->setV(V);
- Dir->setExpr(E);
- Dir->setUpdateExpr(UE);
- Dir->IsXLHSInRHSPart = IsXLHSInRHSPart;
- Dir->IsPostfixUpdate = IsPostfixUpdate;
- return Dir;
-}
-
-OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *));
- return new (Mem) OMPAtomicDirective(NumClauses);
-}
-
-OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
- OMPTargetDirective *Dir =
- new (Mem) OMPTargetDirective(StartLoc, EndLoc, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
- return new (Mem) OMPTargetDirective(NumClauses);
-}
-
-OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
- OMPTeamsDirective *Dir =
- new (Mem) OMPTeamsDirective(StartLoc, EndLoc, Clauses.size());
- Dir->setClauses(Clauses);
- Dir->setAssociatedStmt(AssociatedStmt);
- return Dir;
-}
-
-OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C,
- unsigned NumClauses,
- EmptyShell) {
- unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective),
- llvm::alignOf<OMPClause *>());
- void *Mem =
- C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
- return new (Mem) OMPTeamsDirective(NumClauses);
-}
-
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp b/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp
new file mode 100644
index 0000000..e39a01d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/StmtCXX.cpp
@@ -0,0 +1,86 @@
+//===--- StmtCXX.cpp - Classes for representing C++ statements ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the subclesses of Stmt class declared in StmtCXX.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/StmtCXX.h"
+
+#include "clang/AST/ASTContext.h"
+
+using namespace clang;
+
+QualType CXXCatchStmt::getCaughtType() const {
+ if (ExceptionDecl)
+ return ExceptionDecl->getType();
+ return QualType();
+}
+
+CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc,
+ Stmt *tryBlock, ArrayRef<Stmt *> handlers) {
+ std::size_t Size = sizeof(CXXTryStmt);
+ Size += ((handlers.size() + 1) * sizeof(Stmt *));
+
+ void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
+ return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers);
+}
+
+CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty,
+ unsigned numHandlers) {
+ std::size_t Size = sizeof(CXXTryStmt);
+ Size += ((numHandlers + 1) * sizeof(Stmt *));
+
+ void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
+ return new (Mem) CXXTryStmt(Empty, numHandlers);
+}
+
+CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
+ ArrayRef<Stmt *> handlers)
+ : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(handlers.size()) {
+ Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
+ Stmts[0] = tryBlock;
+ std::copy(handlers.begin(), handlers.end(), Stmts + 1);
+}
+
+CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt,
+ Expr *Cond, Expr *Inc, DeclStmt *LoopVar,
+ Stmt *Body, SourceLocation FL,
+ SourceLocation CAL, SourceLocation CL,
+ SourceLocation RPL)
+ : Stmt(CXXForRangeStmtClass), ForLoc(FL), CoawaitLoc(CAL), ColonLoc(CL),
+ RParenLoc(RPL) {
+ SubExprs[RANGE] = Range;
+ SubExprs[BEGINEND] = BeginEndStmt;
+ SubExprs[COND] = Cond;
+ SubExprs[INC] = Inc;
+ SubExprs[LOOPVAR] = LoopVar;
+ SubExprs[BODY] = Body;
+}
+
+Expr *CXXForRangeStmt::getRangeInit() {
+ DeclStmt *RangeStmt = getRangeStmt();
+ VarDecl *RangeDecl = dyn_cast_or_null<VarDecl>(RangeStmt->getSingleDecl());
+ assert(RangeDecl && "for-range should have a single var decl");
+ return RangeDecl->getInit();
+}
+
+const Expr *CXXForRangeStmt::getRangeInit() const {
+ return const_cast<CXXForRangeStmt *>(this)->getRangeInit();
+}
+
+VarDecl *CXXForRangeStmt::getLoopVariable() {
+ Decl *LV = cast<DeclStmt>(getLoopVarStmt())->getSingleDecl();
+ assert(LV && "No loop variable in CXXForRangeStmt");
+ return cast<VarDecl>(LV);
+}
+
+const VarDecl *CXXForRangeStmt::getLoopVariable() const {
+ return const_cast<CXXForRangeStmt *>(this)->getLoopVariable();
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp
index 732756f..861d090 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtIterator.cpp
@@ -42,7 +42,7 @@ void StmtIteratorBase::NextVA() {
if (inDeclGroup()) {
if (VarDecl* VD = dyn_cast<VarDecl>(*DGI))
- if (VD->Init)
+ if (VD->hasInit())
return;
NextDecl();
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtObjC.cpp b/contrib/llvm/tools/clang/lib/AST/StmtObjC.cpp
new file mode 100644
index 0000000..a77550c
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/StmtObjC.cpp
@@ -0,0 +1,73 @@
+//===--- StmtObjC.cpp - Classes for representing ObjC statements ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the subclesses of Stmt class declared in StmtObjC.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/StmtObjC.h"
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/ASTContext.h"
+
+using namespace clang;
+
+ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
+ Stmt *Body, SourceLocation FCL,
+ SourceLocation RPL)
+ : Stmt(ObjCForCollectionStmtClass) {
+ SubExprs[ELEM] = Elem;
+ SubExprs[COLLECTION] = Collect;
+ SubExprs[BODY] = Body;
+ ForLoc = FCL;
+ RParenLoc = RPL;
+}
+
+ObjCAtTryStmt::ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
+ Stmt **CatchStmts, unsigned NumCatchStmts,
+ Stmt *atFinallyStmt)
+ : Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc),
+ NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != nullptr) {
+ Stmt **Stmts = getStmts();
+ Stmts[0] = atTryStmt;
+ for (unsigned I = 0; I != NumCatchStmts; ++I)
+ Stmts[I + 1] = CatchStmts[I];
+
+ if (HasFinally)
+ Stmts[NumCatchStmts + 1] = atFinallyStmt;
+}
+
+ObjCAtTryStmt *ObjCAtTryStmt::Create(const ASTContext &Context,
+ SourceLocation atTryLoc, Stmt *atTryStmt,
+ Stmt **CatchStmts, unsigned NumCatchStmts,
+ Stmt *atFinallyStmt) {
+ unsigned Size =
+ sizeof(ObjCAtTryStmt) +
+ (1 + NumCatchStmts + (atFinallyStmt != nullptr)) * sizeof(Stmt *);
+ void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
+ return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts,
+ atFinallyStmt);
+}
+
+ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(const ASTContext &Context,
+ unsigned NumCatchStmts,
+ bool HasFinally) {
+ unsigned Size =
+ sizeof(ObjCAtTryStmt) + (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *);
+ void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
+ return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally);
+}
+
+SourceLocation ObjCAtTryStmt::getLocEnd() const {
+ if (HasFinally)
+ return getFinallyStmt()->getLocEnd();
+ if (NumCatchStmts)
+ return getCatchStmt(NumCatchStmts - 1)->getLocEnd();
+ return getTryBody()->getLocEnd();
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp
new file mode 100644
index 0000000..7f923d8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/AST/StmtOpenMP.cpp
@@ -0,0 +1,884 @@
+//===--- StmtOpenMP.cpp - Classes for OpenMP directives -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the subclesses of Stmt class declared in StmtOpenMP.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/StmtOpenMP.h"
+
+#include "clang/AST/ASTContext.h"
+
+using namespace clang;
+
+void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {
+ assert(Clauses.size() == getNumClauses() &&
+ "Number of clauses is not the same as the preallocated buffer");
+ std::copy(Clauses.begin(), Clauses.end(), getClauses().begin());
+}
+
+void OMPLoopDirective::setCounters(ArrayRef<Expr *> A) {
+ assert(A.size() == getCollapsedNumber() &&
+ "Number of loop counters is not the same as the collapsed number");
+ std::copy(A.begin(), A.end(), getCounters().begin());
+}
+
+void OMPLoopDirective::setPrivateCounters(ArrayRef<Expr *> A) {
+ assert(A.size() == getCollapsedNumber() && "Number of loop private counters "
+ "is not the same as the collapsed "
+ "number");
+ std::copy(A.begin(), A.end(), getPrivateCounters().begin());
+}
+
+void OMPLoopDirective::setInits(ArrayRef<Expr *> A) {
+ assert(A.size() == getCollapsedNumber() &&
+ "Number of counter inits is not the same as the collapsed number");
+ std::copy(A.begin(), A.end(), getInits().begin());
+}
+
+void OMPLoopDirective::setUpdates(ArrayRef<Expr *> A) {
+ assert(A.size() == getCollapsedNumber() &&
+ "Number of counter updates is not the same as the collapsed number");
+ std::copy(A.begin(), A.end(), getUpdates().begin());
+}
+
+void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) {
+ assert(A.size() == getCollapsedNumber() &&
+ "Number of counter finals is not the same as the collapsed number");
+ std::copy(A.begin(), A.end(), getFinals().begin());
+}
+
+OMPParallelDirective *OMPParallelDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPParallelDirective *Dir =
+ new (Mem) OMPParallelDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setHasCancel(HasCancel);
+ return Dir;
+}
+
+OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPParallelDirective(NumClauses);
+}
+
+OMPSimdDirective *
+OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
+ OMPSimdDirective *Dir = new (Mem)
+ OMPSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ return Dir;
+}
+
+OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
+ return new (Mem) OMPSimdDirective(CollapsedNum, NumClauses);
+}
+
+OMPForDirective *
+OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs, bool HasCancel) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
+ OMPForDirective *Dir =
+ new (Mem) OMPForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setHasCancel(HasCancel);
+ return Dir;
+}
+
+OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
+ return new (Mem) OMPForDirective(CollapsedNum, NumClauses);
+}
+
+OMPForSimdDirective *
+OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
+ OMPForSimdDirective *Dir = new (Mem)
+ OMPForSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ return Dir;
+}
+
+OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPForSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
+ return new (Mem) OMPForSimdDirective(CollapsedNum, NumClauses);
+}
+
+OMPSectionsDirective *OMPSectionsDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionsDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPSectionsDirective *Dir =
+ new (Mem) OMPSectionsDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setHasCancel(HasCancel);
+ return Dir;
+}
+
+OMPSectionsDirective *OMPSectionsDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionsDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPSectionsDirective(NumClauses);
+}
+
+OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ Stmt *AssociatedStmt,
+ bool HasCancel) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setHasCancel(HasCancel);
+ return Dir;
+}
+
+OMPSectionDirective *OMPSectionDirective::CreateEmpty(const ASTContext &C,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSectionDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ return new (Mem) OMPSectionDirective();
+}
+
+OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSingleDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPSingleDirective *Dir =
+ new (Mem) OMPSingleDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPSingleDirective *OMPSingleDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPSingleDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPSingleDirective(NumClauses);
+}
+
+OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPMasterDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ OMPMasterDirective *Dir = new (Mem) OMPMasterDirective(StartLoc, EndLoc);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPMasterDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ return new (Mem) OMPMasterDirective();
+}
+
+OMPCriticalDirective *OMPCriticalDirective::Create(
+ const ASTContext &C, const DeclarationNameInfo &Name,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPCriticalDirective *Dir =
+ new (Mem) OMPCriticalDirective(Name, StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPCriticalDirective(NumClauses);
+}
+
+OMPParallelForDirective *OMPParallelForDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs, bool HasCancel) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_parallel_for));
+ OMPParallelForDirective *Dir = new (Mem)
+ OMPParallelForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setHasCancel(HasCancel);
+ return Dir;
+}
+
+OMPParallelForDirective *
+OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_parallel_for));
+ return new (Mem) OMPParallelForDirective(CollapsedNum, NumClauses);
+}
+
+OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
+ OMPParallelForSimdDirective *Dir = new (Mem) OMPParallelForSimdDirective(
+ StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ return Dir;
+}
+
+OMPParallelForSimdDirective *
+OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
+ return new (Mem) OMPParallelForSimdDirective(CollapsedNum, NumClauses);
+}
+
+OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelSectionsDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPParallelSectionsDirective *Dir =
+ new (Mem) OMPParallelSectionsDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setHasCancel(HasCancel);
+ return Dir;
+}
+
+OMPParallelSectionsDirective *
+OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelSectionsDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPParallelSectionsDirective(NumClauses);
+}
+
+OMPTaskDirective *
+OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, bool HasCancel) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPTaskDirective *Dir =
+ new (Mem) OMPTaskDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setHasCancel(HasCancel);
+ return Dir;
+}
+
+OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPTaskDirective(NumClauses);
+}
+
+OMPTaskyieldDirective *OMPTaskyieldDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective));
+ OMPTaskyieldDirective *Dir =
+ new (Mem) OMPTaskyieldDirective(StartLoc, EndLoc);
+ return Dir;
+}
+
+OMPTaskyieldDirective *OMPTaskyieldDirective::CreateEmpty(const ASTContext &C,
+ EmptyShell) {
+ void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective));
+ return new (Mem) OMPTaskyieldDirective();
+}
+
+OMPBarrierDirective *OMPBarrierDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ void *Mem = C.Allocate(sizeof(OMPBarrierDirective));
+ OMPBarrierDirective *Dir = new (Mem) OMPBarrierDirective(StartLoc, EndLoc);
+ return Dir;
+}
+
+OMPBarrierDirective *OMPBarrierDirective::CreateEmpty(const ASTContext &C,
+ EmptyShell) {
+ void *Mem = C.Allocate(sizeof(OMPBarrierDirective));
+ return new (Mem) OMPBarrierDirective();
+}
+
+OMPTaskwaitDirective *OMPTaskwaitDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ void *Mem = C.Allocate(sizeof(OMPTaskwaitDirective));
+ OMPTaskwaitDirective *Dir = new (Mem) OMPTaskwaitDirective(StartLoc, EndLoc);
+ return Dir;
+}
+
+OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C,
+ EmptyShell) {
+ void *Mem = C.Allocate(sizeof(OMPTaskwaitDirective));
+ return new (Mem) OMPTaskwaitDirective();
+}
+
+OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ OMPTaskgroupDirective *Dir =
+ new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskgroupDirective),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size + sizeof(Stmt *));
+ return new (Mem) OMPTaskgroupDirective();
+}
+
+OMPCancellationPointDirective *OMPCancellationPointDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ OpenMPDirectiveKind CancelRegion) {
+ unsigned Size = llvm::RoundUpToAlignment(
+ sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size);
+ OMPCancellationPointDirective *Dir =
+ new (Mem) OMPCancellationPointDirective(StartLoc, EndLoc);
+ Dir->setCancelRegion(CancelRegion);
+ return Dir;
+}
+
+OMPCancellationPointDirective *
+OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(
+ sizeof(OMPCancellationPointDirective), llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size);
+ return new (Mem) OMPCancellationPointDirective();
+}
+
+OMPCancelDirective *
+OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
+ OpenMPDirectiveKind CancelRegion) {
+ unsigned Size = llvm::RoundUpToAlignment(
+ sizeof(OMPCancelDirective) + sizeof(OMPClause *) * Clauses.size(),
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size);
+ OMPCancelDirective *Dir =
+ new (Mem) OMPCancelDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setCancelRegion(CancelRegion);
+ return Dir;
+}
+
+OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCancelDirective) +
+ sizeof(OMPClause *) * NumClauses,
+ llvm::alignOf<Stmt *>());
+ void *Mem = C.Allocate(Size);
+ return new (Mem) OMPCancelDirective(NumClauses);
+}
+
+OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPFlushDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size());
+ OMPFlushDirective *Dir =
+ new (Mem) OMPFlushDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ return Dir;
+}
+
+OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPFlushDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses);
+ return new (Mem) OMPFlushDirective(NumClauses);
+}
+
+OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * Clauses.size());
+ OMPOrderedDirective *Dir =
+ new (Mem) OMPOrderedDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPOrderedDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * NumClauses);
+ return new (Mem) OMPOrderedDirective(NumClauses);
+}
+
+OMPAtomicDirective *OMPAtomicDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
+ Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ 5 * sizeof(Stmt *));
+ OMPAtomicDirective *Dir =
+ new (Mem) OMPAtomicDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setX(X);
+ Dir->setV(V);
+ Dir->setExpr(E);
+ Dir->setUpdateExpr(UE);
+ Dir->IsXLHSInRHSPart = IsXLHSInRHSPart;
+ Dir->IsPostfixUpdate = IsPostfixUpdate;
+ return Dir;
+}
+
+OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPAtomicDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *));
+ return new (Mem) OMPAtomicDirective(NumClauses);
+}
+
+OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPTargetDirective *Dir =
+ new (Mem) OMPTargetDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTargetDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPTargetDirective(NumClauses);
+}
+
+OMPTargetDataDirective *OMPTargetDataDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
+ void *Mem =
+ C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPTargetDataDirective),
+ llvm::alignOf<OMPClause *>()) +
+ sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPTargetDataDirective *Dir =
+ new (Mem) OMPTargetDataDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPTargetDataDirective *OMPTargetDataDirective::CreateEmpty(const ASTContext &C,
+ unsigned N,
+ EmptyShell) {
+ void *Mem =
+ C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPTargetDataDirective),
+ llvm::alignOf<OMPClause *>()) +
+ sizeof(OMPClause *) * N + sizeof(Stmt *));
+ return new (Mem) OMPTargetDataDirective(N);
+}
+
+OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPTeamsDirective *Dir =
+ new (Mem) OMPTeamsDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTeamsDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPTeamsDirective(NumClauses);
+}
+
+OMPTaskLoopDirective *OMPTaskLoopDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskLoopDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop));
+ OMPTaskLoopDirective *Dir = new (Mem)
+ OMPTaskLoopDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ return Dir;
+}
+
+OMPTaskLoopDirective *OMPTaskLoopDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskLoopDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop));
+ return new (Mem) OMPTaskLoopDirective(CollapsedNum, NumClauses);
+}
+
+OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskLoopSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_taskloop_simd));
+ OMPTaskLoopSimdDirective *Dir = new (Mem)
+ OMPTaskLoopSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ return Dir;
+}
+
+OMPTaskLoopSimdDirective *
+OMPTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskLoopSimdDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_taskloop_simd));
+ return new (Mem) OMPTaskLoopSimdDirective(CollapsedNum, NumClauses);
+}
+
+OMPDistributeDirective *OMPDistributeDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPDistributeDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_distribute));
+ OMPDistributeDirective *Dir = new (Mem)
+ OMPDistributeDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ return Dir;
+}
+
+OMPDistributeDirective *
+OMPDistributeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPDistributeDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_distribute));
+ return new (Mem) OMPDistributeDirective(CollapsedNum, NumClauses);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
index 7960077..69f52f5 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/CharInfo.h"
@@ -601,6 +602,8 @@ public:
void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
OS << "if(";
+ if (Node->getNameModifier() != OMPD_unknown)
+ OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": ";
Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
@@ -623,6 +626,12 @@ void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) {
OS << ")";
}
+void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) {
+ OS << "simdlen(";
+ Node->getSimdlen()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) {
OS << "collapse(";
Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0);
@@ -642,8 +651,18 @@ void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) {
}
void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) {
- OS << "schedule("
- << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind());
+ OS << "schedule(";
+ if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
+ OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
+ Node->getFirstScheduleModifier());
+ if (Node->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
+ OS << ", ";
+ OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
+ Node->getSecondScheduleModifier());
+ }
+ OS << ": ";
+ }
+ OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind());
if (Node->getChunkSize()) {
OS << ", ";
Node->getChunkSize()->printPretty(OS, nullptr, Policy);
@@ -651,8 +670,13 @@ void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) {
OS << ")";
}
-void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *) {
+void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *Node) {
OS << "ordered";
+ if (auto *Num = Node->getNumForLoops()) {
+ OS << "(";
+ Num->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+ }
}
void OMPClausePrinter::VisitOMPNowaitClause(OMPNowaitClause *) {
@@ -663,6 +687,10 @@ void OMPClausePrinter::VisitOMPUntiedClause(OMPUntiedClause *) {
OS << "untied";
}
+void OMPClausePrinter::VisitOMPNogroupClause(OMPNogroupClause *) {
+ OS << "nogroup";
+}
+
void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) {
OS << "mergeable";
}
@@ -683,6 +711,54 @@ void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
OS << "seq_cst";
}
+void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) {
+ OS << "threads";
+}
+
+void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; }
+
+void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) {
+ OS << "device(";
+ Node->getDevice()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) {
+ OS << "num_teams(";
+ Node->getNumTeams()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPThreadLimitClause(OMPThreadLimitClause *Node) {
+ OS << "thread_limit(";
+ Node->getThreadLimit()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPPriorityClause(OMPPriorityClause *Node) {
+ OS << "priority(";
+ Node->getPriority()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPGrainsizeClause(OMPGrainsizeClause *Node) {
+ OS << "grainsize(";
+ Node->getGrainsize()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPNumTasksClause(OMPNumTasksClause *Node) {
+ OS << "num_tasks(";
+ Node->getNumTasks()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) {
+ OS << "hint(";
+ Node->getHint()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
template<typename T>
void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
for (typename T::varlist_iterator I = Node->varlist_begin(),
@@ -756,7 +832,13 @@ void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) {
void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
if (!Node->varlist_empty()) {
OS << "linear";
+ if (Node->getModifierLoc().isValid()) {
+ OS << '('
+ << getOpenMPSimpleClauseTypeName(OMPC_linear, Node->getModifier());
+ }
VisitOMPClauseList(Node, '(');
+ if (Node->getModifierLoc().isValid())
+ OS << ')';
if (Node->getStep() != nullptr) {
OS << ": ";
Node->getStep()->printPretty(OS, nullptr, Policy, 0);
@@ -801,11 +883,28 @@ void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) {
}
void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) {
+ OS << "depend(";
+ OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
+ Node->getDependencyKind());
+ if (!Node->varlist_empty()) {
+ OS << " :";
+ VisitOMPClauseList(Node, ' ');
+ }
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) {
if (!Node->varlist_empty()) {
- OS << "depend(";
- OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
- Node->getDependencyKind())
- << " :";
+ OS << "map(";
+ if (Node->getMapType() != OMPC_MAP_unknown) {
+ if (Node->getMapTypeModifier() != OMPC_MAP_unknown) {
+ OS << getOpenMPSimpleClauseTypeName(OMPC_map,
+ Node->getMapTypeModifier());
+ OS << ',';
+ }
+ OS << getOpenMPSimpleClauseTypeName(OMPC_map, Node->getMapType());
+ OS << ':';
+ }
VisitOMPClauseList(Node, ' ');
OS << ")";
}
@@ -881,6 +980,7 @@ void StmtPrinter::VisitOMPCriticalDirective(OMPCriticalDirective *Node) {
Node->getDirectiveName().printName(OS);
OS << ")";
}
+ OS << " ";
PrintOMPExecutableDirective(Node);
}
@@ -932,7 +1032,7 @@ void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) {
}
void StmtPrinter::VisitOMPOrderedDirective(OMPOrderedDirective *Node) {
- Indent() << "#pragma omp ordered";
+ Indent() << "#pragma omp ordered ";
PrintOMPExecutableDirective(Node);
}
@@ -946,6 +1046,11 @@ void StmtPrinter::VisitOMPTargetDirective(OMPTargetDirective *Node) {
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPTargetDataDirective(OMPTargetDataDirective *Node) {
+ Indent() << "#pragma omp target data ";
+ PrintOMPExecutableDirective(Node);
+}
+
void StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) {
Indent() << "#pragma omp teams ";
PrintOMPExecutableDirective(Node);
@@ -960,9 +1065,26 @@ void StmtPrinter::VisitOMPCancellationPointDirective(
void StmtPrinter::VisitOMPCancelDirective(OMPCancelDirective *Node) {
Indent() << "#pragma omp cancel "
- << getOpenMPDirectiveName(Node->getCancelRegion());
+ << getOpenMPDirectiveName(Node->getCancelRegion()) << " ";
PrintOMPExecutableDirective(Node);
}
+
+void StmtPrinter::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *Node) {
+ Indent() << "#pragma omp taskloop ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTaskLoopSimdDirective(
+ OMPTaskLoopSimdDirective *Node) {
+ Indent() << "#pragma omp taskloop simd ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPDistributeDirective(OMPDistributeDirective *Node) {
+ Indent() << "#pragma omp distribute ";
+ PrintOMPExecutableDirective(Node);
+}
+
//===----------------------------------------------------------------------===//
// Expr printing methods.
//===----------------------------------------------------------------------===//
@@ -1043,6 +1165,7 @@ void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
switch (Node->getKind()) {
case CharacterLiteral::Ascii: break; // no prefix.
case CharacterLiteral::Wide: OS << 'L'; break;
+ case CharacterLiteral::UTF8: OS << "u8"; break;
case CharacterLiteral::UTF16: OS << 'u'; break;
case CharacterLiteral::UTF32: OS << 'U'; break;
}
@@ -1110,8 +1233,6 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
case BuiltinType::ULong: OS << "UL"; break;
case BuiltinType::LongLong: OS << "LL"; break;
case BuiltinType::ULongLong: OS << "ULL"; break;
- case BuiltinType::Int128: OS << "i128"; break;
- case BuiltinType::UInt128: OS << "Ui128"; break;
}
}
@@ -1185,8 +1306,8 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
OS << ", ";
bool PrintedSomething = false;
for (unsigned i = 0, n = Node->getNumComponents(); i < n; ++i) {
- OffsetOfExpr::OffsetOfNode ON = Node->getComponent(i);
- if (ON.getKind() == OffsetOfExpr::OffsetOfNode::Array) {
+ OffsetOfNode ON = Node->getComponent(i);
+ if (ON.getKind() == OffsetOfNode::Array) {
// Array node
OS << "[";
PrintExpr(Node->getIndexExpr(ON.getArrayExprIndex()));
@@ -1196,7 +1317,7 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
}
// Skip implicit base indirections.
- if (ON.getKind() == OffsetOfExpr::OffsetOfNode::Base)
+ if (ON.getKind() == OffsetOfNode::Base)
continue;
// Field or identifier node.
@@ -1266,6 +1387,19 @@ void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) {
OS << "]";
}
+void StmtPrinter::VisitOMPArraySectionExpr(OMPArraySectionExpr *Node) {
+ PrintExpr(Node->getBase());
+ OS << "[";
+ if (Node->getLowerBound())
+ PrintExpr(Node->getLowerBound());
+ if (Node->getColonLoc().isValid()) {
+ OS << ":";
+ if (Node->getLength())
+ PrintExpr(Node->getLength());
+ }
+ OS << "]";
+}
+
void StmtPrinter::PrintCallArgs(CallExpr *Call) {
for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) {
if (isa<CXXDefaultArgExpr>(Call->getArg(i))) {
@@ -1667,6 +1801,13 @@ void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) {
OS << Node->getPropertyDecl()->getDeclName();
}
+void StmtPrinter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *Node) {
+ PrintExpr(Node->getBase());
+ OS << "[";
+ PrintExpr(Node->getIdx());
+ OS << "]";
+}
+
void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
switch (Node->getLiteralOperatorKind()) {
case UserDefinedLiteral::LOK_Raw:
@@ -1679,7 +1820,7 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) {
assert(Args);
if (Args->size() != 1) {
- OS << "operator \"\" " << Node->getUDSuffix()->getName();
+ OS << "operator\"\"" << Node->getUDSuffix()->getName();
TemplateSpecializationType::PrintTemplateArgumentList(
OS, Args->data(), Args->size(), Policy);
OS << "()";
@@ -1768,7 +1909,7 @@ void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(),
ArgEnd = Node->arg_end();
Arg != ArgEnd; ++Arg) {
- if (Arg->isDefaultArgument())
+ if ((*Arg)->isDefaultArgument())
break;
if (Arg != Node->arg_begin())
OS << ", ";
@@ -2115,6 +2256,31 @@ void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) {
OS << ")";
}
+// C++ Coroutines TS
+
+void StmtPrinter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {
+ Visit(S->getBody());
+}
+
+void StmtPrinter::VisitCoreturnStmt(CoreturnStmt *S) {
+ OS << "co_return";
+ if (S->getOperand()) {
+ OS << " ";
+ Visit(S->getOperand());
+ }
+ OS << ";";
+}
+
+void StmtPrinter::VisitCoawaitExpr(CoawaitExpr *S) {
+ OS << "co_await ";
+ PrintExpr(S->getOperand());
+}
+
+void StmtPrinter::VisitCoyieldExpr(CoyieldExpr *S) {
+ OS << "co_yield ";
+ PrintExpr(S->getOperand());
+}
+
// Obj-C
void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
@@ -2129,14 +2295,11 @@ void StmtPrinter::VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
void StmtPrinter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
OS << "@[ ";
- StmtRange ch = E->children();
- if (ch.first != ch.second) {
- while (1) {
- Visit(*ch.first);
- ++ch.first;
- if (ch.first == ch.second) break;
+ ObjCArrayLiteral::child_range Ch = E->children();
+ for (auto I = Ch.begin(), E = Ch.end(); I != E; ++I) {
+ if (I != Ch.begin())
OS << ", ";
- }
+ Visit(*I);
}
OS << " ]";
}
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
index da99692..175a43a 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/StmtVisitor.h"
#include "llvm/ADT/FoldingSet.h"
using namespace clang;
@@ -261,6 +262,7 @@ class OMPClauseProfiler : public ConstOMPClauseVisitor<OMPClauseProfiler> {
/// \brief Process clauses with list of variables.
template <typename T>
void VisitOMPClauseList(T *Node);
+
public:
OMPClauseProfiler(StmtProfiler *P) : Profiler(P) { }
#define OPENMP_CLAUSE(Name, Class) \
@@ -288,6 +290,11 @@ void OMPClauseProfiler::VisitOMPSafelenClause(const OMPSafelenClause *C) {
Profiler->VisitStmt(C->getSafelen());
}
+void OMPClauseProfiler::VisitOMPSimdlenClause(const OMPSimdlenClause *C) {
+ if (C->getSimdlen())
+ Profiler->VisitStmt(C->getSimdlen());
+}
+
void OMPClauseProfiler::VisitOMPCollapseClause(const OMPCollapseClause *C) {
if (C->getNumForLoops())
Profiler->VisitStmt(C->getNumForLoops());
@@ -306,7 +313,10 @@ void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) {
}
}
-void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *) {}
+void OMPClauseProfiler::VisitOMPOrderedClause(const OMPOrderedClause *C) {
+ if (auto *Num = C->getNumForLoops())
+ Profiler->VisitStmt(Num);
+}
void OMPClauseProfiler::VisitOMPNowaitClause(const OMPNowaitClause *) {}
@@ -324,6 +334,12 @@ void OMPClauseProfiler::VisitOMPCaptureClause(const OMPCaptureClause *) {}
void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
+void OMPClauseProfiler::VisitOMPThreadsClause(const OMPThreadsClause *) {}
+
+void OMPClauseProfiler::VisitOMPSIMDClause(const OMPSIMDClause *) {}
+
+void OMPClauseProfiler::VisitOMPNogroupClause(const OMPNogroupClause *) {}
+
template<typename T>
void OMPClauseProfiler::VisitOMPClauseList(T *Node) {
for (auto *E : Node->varlists()) {
@@ -369,6 +385,9 @@ void OMPClauseProfiler::VisitOMPReductionClause(
C->getQualifierLoc().getNestedNameSpecifier());
Profiler->VisitName(C->getNameInfo().getName());
VisitOMPClauseList(C);
+ for (auto *E : C->privates()) {
+ Profiler->VisitStmt(E);
+ }
for (auto *E : C->lhs_exprs()) {
Profiler->VisitStmt(E);
}
@@ -381,6 +400,9 @@ void OMPClauseProfiler::VisitOMPReductionClause(
}
void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
VisitOMPClauseList(C);
+ for (auto *E : C->privates()) {
+ Profiler->VisitStmt(E);
+ }
for (auto *E : C->inits()) {
Profiler->VisitStmt(E);
}
@@ -428,6 +450,31 @@ void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) {
void OMPClauseProfiler::VisitOMPDependClause(const OMPDependClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseProfiler::VisitOMPDeviceClause(const OMPDeviceClause *C) {
+ Profiler->VisitStmt(C->getDevice());
+}
+void OMPClauseProfiler::VisitOMPMapClause(const OMPMapClause *C) {
+ VisitOMPClauseList(C);
+}
+void OMPClauseProfiler::VisitOMPNumTeamsClause(const OMPNumTeamsClause *C) {
+ Profiler->VisitStmt(C->getNumTeams());
+}
+void OMPClauseProfiler::VisitOMPThreadLimitClause(
+ const OMPThreadLimitClause *C) {
+ Profiler->VisitStmt(C->getThreadLimit());
+}
+void OMPClauseProfiler::VisitOMPPriorityClause(const OMPPriorityClause *C) {
+ Profiler->VisitStmt(C->getPriority());
+}
+void OMPClauseProfiler::VisitOMPGrainsizeClause(const OMPGrainsizeClause *C) {
+ Profiler->VisitStmt(C->getGrainsize());
+}
+void OMPClauseProfiler::VisitOMPNumTasksClause(const OMPNumTasksClause *C) {
+ Profiler->VisitStmt(C->getNumTasks());
+}
+void OMPClauseProfiler::VisitOMPHintClause(const OMPHintClause *C) {
+ Profiler->VisitStmt(C->getHint());
+}
}
void
@@ -533,6 +580,10 @@ void StmtProfiler::VisitOMPTargetDirective(const OMPTargetDirective *S) {
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPTargetDataDirective(const OMPTargetDataDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitOMPTeamsDirective(const OMPTeamsDirective *S) {
VisitOMPExecutableDirective(S);
}
@@ -546,6 +597,20 @@ void StmtProfiler::VisitOMPCancelDirective(const OMPCancelDirective *S) {
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPTaskLoopDirective(const OMPTaskLoopDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTaskLoopSimdDirective(
+ const OMPTaskLoopSimdDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPDistributeDirective(
+ const OMPDistributeDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}
@@ -610,22 +675,22 @@ void StmtProfiler::VisitOffsetOfExpr(const OffsetOfExpr *S) {
VisitType(S->getTypeSourceInfo()->getType());
unsigned n = S->getNumComponents();
for (unsigned i = 0; i < n; ++i) {
- const OffsetOfExpr::OffsetOfNode& ON = S->getComponent(i);
+ const OffsetOfNode &ON = S->getComponent(i);
ID.AddInteger(ON.getKind());
switch (ON.getKind()) {
- case OffsetOfExpr::OffsetOfNode::Array:
+ case OffsetOfNode::Array:
// Expressions handled below.
break;
- case OffsetOfExpr::OffsetOfNode::Field:
+ case OffsetOfNode::Field:
VisitDecl(ON.getField());
break;
- case OffsetOfExpr::OffsetOfNode::Identifier:
+ case OffsetOfNode::Identifier:
ID.AddPointer(ON.getFieldName());
break;
-
- case OffsetOfExpr::OffsetOfNode::Base:
+
+ case OffsetOfNode::Base:
// These nodes are implicit, and therefore don't need profiling.
break;
}
@@ -646,6 +711,10 @@ void StmtProfiler::VisitArraySubscriptExpr(const ArraySubscriptExpr *S) {
VisitExpr(S);
}
+void StmtProfiler::VisitOMPArraySectionExpr(const OMPArraySectionExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitCallExpr(const CallExpr *S) {
VisitExpr(S);
}
@@ -824,6 +893,7 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
case OO_Arrow:
case OO_Call:
case OO_Conditional:
+ case OO_Coawait:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Invalid operator call kind");
@@ -985,7 +1055,6 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
BinaryOp = BO_Comma;
return Stmt::BinaryOperatorClass;
-
case OO_ArrowStar:
BinaryOp = BO_PtrMemI;
return Stmt::BinaryOperatorClass;
@@ -997,7 +1066,6 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
llvm_unreachable("Invalid overloaded operator expression");
}
-
void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
if (S->isTypeDependent()) {
// Type-dependent operator calls are profiled like their underlying
@@ -1092,6 +1160,11 @@ void StmtProfiler::VisitMSPropertyRefExpr(const MSPropertyRefExpr *S) {
VisitDecl(S->getPropertyDecl());
}
+void StmtProfiler::VisitMSPropertySubscriptExpr(
+ const MSPropertySubscriptExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isImplicit());
@@ -1169,7 +1242,6 @@ void StmtProfiler::VisitCXXDeleteExpr(const CXXDeleteExpr *S) {
VisitDecl(S->getOperatorDelete());
}
-
void StmtProfiler::VisitCXXNewExpr(const CXXNewExpr *S) {
VisitExpr(S);
VisitType(S->getAllocatedType());
@@ -1203,8 +1275,7 @@ void StmtProfiler::VisitOverloadExpr(const OverloadExpr *S) {
VisitName(S->getName());
ID.AddBoolean(S->hasExplicitTemplateArgs());
if (S->hasExplicitTemplateArgs())
- VisitTemplateArguments(S->getExplicitTemplateArgs().getTemplateArgs(),
- S->getExplicitTemplateArgs().NumTemplateArgs);
+ VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
void
@@ -1290,6 +1361,14 @@ void StmtProfiler::VisitPackExpansionExpr(const PackExpansionExpr *S) {
void StmtProfiler::VisitSizeOfPackExpr(const SizeOfPackExpr *S) {
VisitExpr(S);
VisitDecl(S->getPack());
+ if (S->isPartiallySubstituted()) {
+ auto Args = S->getPartialArguments();
+ ID.AddInteger(Args.size());
+ for (const auto &TA : Args)
+ VisitTemplateArgument(TA);
+ } else {
+ ID.AddInteger(0);
+ }
}
void StmtProfiler::VisitSubstNonTypeTemplateParmPackExpr(
@@ -1323,6 +1402,22 @@ void StmtProfiler::VisitCXXFoldExpr(const CXXFoldExpr *S) {
ID.AddInteger(S->getOperator());
}
+void StmtProfiler::VisitCoroutineBodyStmt(const CoroutineBodyStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitCoreturnStmt(const CoreturnStmt *S) {
+ VisitStmt(S);
+}
+
+void StmtProfiler::VisitCoawaitExpr(const CoawaitExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitCoyieldExpr(const CoyieldExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
VisitExpr(E);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
index f8b73cb..e9edb0d 100644
--- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
@@ -53,7 +53,7 @@ static void printIntegral(const TemplateArgument &TemplArg,
}
}
- if (T->isBooleanType()) {
+ if (T->isBooleanType() && !Policy.MSVCFormatting) {
Out << (Val.getBoolValue() ? "true" : "false");
} else if (T->isCharType()) {
const char Ch = Val.getZExtValue();
@@ -88,15 +88,13 @@ TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
Integer.Type = Type.getAsOpaquePtr();
}
-TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
- const TemplateArgument *Args,
- unsigned NumArgs) {
- if (NumArgs == 0)
+TemplateArgument
+TemplateArgument::CreatePackCopy(ASTContext &Context,
+ ArrayRef<TemplateArgument> Args) {
+ if (Args.empty())
return getEmptyPack();
-
- TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
- std::copy(Args, Args + NumArgs, Storage);
- return TemplateArgument(Storage, NumArgs);
+
+ return TemplateArgument(Args.copy(Context));
}
bool TemplateArgument::isDependent() const {
@@ -522,94 +520,67 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
const ASTTemplateArgumentListInfo *
ASTTemplateArgumentListInfo::Create(ASTContext &C,
const TemplateArgumentListInfo &List) {
- assert(llvm::alignOf<ASTTemplateArgumentListInfo>() >=
- llvm::alignOf<TemplateArgumentLoc>());
- std::size_t size = ASTTemplateArgumentListInfo::sizeFor(List.size());
+ std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
- ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo();
- TAI->initializeFrom(List);
- return TAI;
+ return new (Mem) ASTTemplateArgumentListInfo(List);
}
-void ASTTemplateArgumentListInfo::initializeFrom(
- const TemplateArgumentListInfo &Info) {
+ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
+ const TemplateArgumentListInfo &Info) {
LAngleLoc = Info.getLAngleLoc();
RAngleLoc = Info.getRAngleLoc();
NumTemplateArgs = Info.size();
- TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
+ TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
for (unsigned i = 0; i != NumTemplateArgs; ++i)
new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
}
-void ASTTemplateArgumentListInfo::initializeFrom(
- const TemplateArgumentListInfo &Info,
- bool &Dependent,
- bool &InstantiationDependent,
- bool &ContainsUnexpandedParameterPack) {
+void ASTTemplateKWAndArgsInfo::initializeFrom(
+ SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
+ TemplateArgumentLoc *OutArgArray) {
+ this->TemplateKWLoc = TemplateKWLoc;
+ LAngleLoc = Info.getLAngleLoc();
+ RAngleLoc = Info.getRAngleLoc();
+ NumTemplateArgs = Info.size();
+
+ for (unsigned i = 0; i != NumTemplateArgs; ++i)
+ new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
+}
+
+void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
+ assert(TemplateKWLoc.isValid());
+ LAngleLoc = SourceLocation();
+ RAngleLoc = SourceLocation();
+ this->TemplateKWLoc = TemplateKWLoc;
+ NumTemplateArgs = 0;
+}
+
+void ASTTemplateKWAndArgsInfo::initializeFrom(
+ SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
+ TemplateArgumentLoc *OutArgArray, bool &Dependent,
+ bool &InstantiationDependent, bool &ContainsUnexpandedParameterPack) {
+ this->TemplateKWLoc = TemplateKWLoc;
LAngleLoc = Info.getLAngleLoc();
RAngleLoc = Info.getRAngleLoc();
NumTemplateArgs = Info.size();
- TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
for (unsigned i = 0; i != NumTemplateArgs; ++i) {
Dependent = Dependent || Info[i].getArgument().isDependent();
- InstantiationDependent = InstantiationDependent ||
+ InstantiationDependent = InstantiationDependent ||
Info[i].getArgument().isInstantiationDependent();
- ContainsUnexpandedParameterPack
- = ContainsUnexpandedParameterPack ||
+ ContainsUnexpandedParameterPack =
+ ContainsUnexpandedParameterPack ||
Info[i].getArgument().containsUnexpandedParameterPack();
- new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
+ new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
}
}
-void ASTTemplateArgumentListInfo::copyInto(
- TemplateArgumentListInfo &Info) const {
+void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray,
+ TemplateArgumentListInfo &Info) const {
Info.setLAngleLoc(LAngleLoc);
Info.setRAngleLoc(RAngleLoc);
for (unsigned I = 0; I != NumTemplateArgs; ++I)
- Info.addArgument(getTemplateArgs()[I]);
-}
-
-std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) {
- return sizeof(ASTTemplateArgumentListInfo) +
- sizeof(TemplateArgumentLoc) * NumTemplateArgs;
-}
-
-void
-ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc,
- const TemplateArgumentListInfo &Info) {
- Base::initializeFrom(Info);
- setTemplateKeywordLoc(TemplateKWLoc);
-}
-
-void
-ASTTemplateKWAndArgsInfo
-::initializeFrom(SourceLocation TemplateKWLoc,
- const TemplateArgumentListInfo &Info,
- bool &Dependent,
- bool &InstantiationDependent,
- bool &ContainsUnexpandedParameterPack) {
- Base::initializeFrom(Info, Dependent, InstantiationDependent,
- ContainsUnexpandedParameterPack);
- setTemplateKeywordLoc(TemplateKWLoc);
-}
-
-void
-ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
- // No explicit template arguments, but template keyword loc is valid.
- assert(TemplateKWLoc.isValid());
- LAngleLoc = SourceLocation();
- RAngleLoc = SourceLocation();
- NumTemplateArgs = 0;
- setTemplateKeywordLoc(TemplateKWLoc);
-}
-
-std::size_t
-ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) {
- // Add space for the template keyword location.
- // FIXME: There's room for this in the padding before the template args in
- // 64-bit builds.
- return Base::sizeFor(NumTemplateArgs) + sizeof(SourceLocation);
+ Info.addArgument(ArgArray[I]);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
index 77c8fd5..47e0255 100644
--- a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp
@@ -24,7 +24,7 @@ using namespace llvm;
TemplateArgument
SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
- return TemplateArgument(Arguments, size());
+ return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
}
void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
@@ -40,7 +40,7 @@ void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context) {
- Profile(ID, Context, Parameter, TemplateArgument(Arguments, size()));
+ Profile(ID, Context, Parameter, getArgumentPack());
}
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
@@ -51,6 +51,22 @@ void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
ArgPack.Profile(ID, Context);
}
+TemplateName::TemplateName(void *Ptr) {
+ Storage = StorageType::getFromOpaqueValue(Ptr);
+}
+
+TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
+TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
+ : Storage(Storage) {}
+TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
+ : Storage(Storage) {}
+TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
+ : Storage(Storage) {}
+TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
+TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
+
+bool TemplateName::isNull() const { return Storage.isNull(); }
+
TemplateName::NameKind TemplateName::getKind() const {
if (Storage.is<TemplateDecl *>())
return Template;
@@ -81,6 +97,40 @@ TemplateDecl *TemplateName::getAsTemplateDecl() const {
return nullptr;
}
+OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
+ if (UncommonTemplateNameStorage *Uncommon =
+ Storage.dyn_cast<UncommonTemplateNameStorage *>())
+ return Uncommon->getAsOverloadedStorage();
+
+ return nullptr;
+}
+
+SubstTemplateTemplateParmStorage *
+TemplateName::getAsSubstTemplateTemplateParm() const {
+ if (UncommonTemplateNameStorage *uncommon =
+ Storage.dyn_cast<UncommonTemplateNameStorage *>())
+ return uncommon->getAsSubstTemplateTemplateParm();
+
+ return nullptr;
+}
+
+SubstTemplateTemplateParmPackStorage *
+TemplateName::getAsSubstTemplateTemplateParmPack() const {
+ if (UncommonTemplateNameStorage *Uncommon =
+ Storage.dyn_cast<UncommonTemplateNameStorage *>())
+ return Uncommon->getAsSubstTemplateTemplateParmPack();
+
+ return nullptr;
+}
+
+QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
+ return Storage.dyn_cast<QualifiedTemplateName *>();
+}
+
+DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
+ return Storage.dyn_cast<DependentTemplateName *>();
+}
+
bool TemplateName::isDependent() const {
if (TemplateDecl *Template = getAsTemplateDecl()) {
if (isa<TemplateTemplateParmDecl>(Template))
diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp
index cee5fee..b467dac 100644
--- a/contrib/llvm/tools/clang/lib/AST/Type.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp
@@ -22,6 +22,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
@@ -509,6 +510,28 @@ bool Type::isObjCClassOrClassKindOfType() const {
return OPT->isObjCClassType() || OPT->isObjCQualifiedClassType();
}
+/// Was this type written with the special inert-in-MRC __unsafe_unretained
+/// qualifier?
+///
+/// This approximates the answer to the following question: if this
+/// translation unit were compiled in ARC, would this type be qualified
+/// with __unsafe_unretained?
+bool Type::isObjCInertUnsafeUnretainedType() const {
+ const Type *cur = this;
+ while (true) {
+ if (auto attributed = dyn_cast<AttributedType>(cur)) {
+ if (attributed->getAttrKind() ==
+ AttributedType::attr_objc_inert_unsafe_unretained)
+ return true;
+ }
+
+ // Single-step desugar until we run out of sugar.
+ QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType();
+ if (next.getTypePtr() == cur) return false;
+ cur = next.getTypePtr();
+ }
+}
+
ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
@@ -836,11 +859,8 @@ public:
}
if (exceptionChanged) {
- unsigned size = sizeof(QualType) * exceptionTypes.size();
- void *mem = Ctx.Allocate(size, llvm::alignOf<QualType>());
- memcpy(mem, exceptionTypes.data(), size);
- info.ExceptionSpec.Exceptions
- = llvm::makeArrayRef((QualType *)mem, exceptionTypes.size());
+ info.ExceptionSpec.Exceptions =
+ llvm::makeArrayRef(exceptionTypes).copy(Ctx);
}
}
@@ -950,7 +970,7 @@ public:
== T->getDeducedType().getAsOpaquePtr())
return QualType(T, 0);
- return Ctx.getAutoType(deducedType, T->isDecltypeAuto(),
+ return Ctx.getAutoType(deducedType, T->getKeyword(),
T->isDependentType());
}
@@ -1158,11 +1178,8 @@ QualType QualType::substObjCTypeArgs(
}
if (exceptionChanged) {
- unsigned size = sizeof(QualType) * exceptionTypes.size();
- void *mem = ctx.Allocate(size, llvm::alignOf<QualType>());
- memcpy(mem, exceptionTypes.data(), size);
- info.ExceptionSpec.Exceptions
- = llvm::makeArrayRef((QualType *)mem, exceptionTypes.size());
+ info.ExceptionSpec.Exceptions =
+ llvm::makeArrayRef(exceptionTypes).copy(ctx);
}
}
@@ -1275,7 +1292,7 @@ Optional<ArrayRef<QualType>> Type::getObjCSubstitutions(
if (!dcTypeParams)
return None;
} else {
- // If we are in neither a class mor a category, there's no
+ // If we are in neither a class nor a category, there's no
// substitution to perform.
dcCategoryDecl = dyn_cast<ObjCCategoryDecl>(dc);
if (!dcCategoryDecl)
@@ -1905,6 +1922,28 @@ bool Type::isIncompleteType(NamedDecl **Def) const {
case IncompleteArray:
// An array of unknown size is an incomplete type (C99 6.2.5p22).
return true;
+ case MemberPointer: {
+ // Member pointers in the MS ABI have special behavior in
+ // RequireCompleteType: they attach a MSInheritanceAttr to the CXXRecordDecl
+ // to indicate which inheritance model to use.
+ auto *MPTy = cast<MemberPointerType>(CanonicalType);
+ const Type *ClassTy = MPTy->getClass();
+ // Member pointers with dependent class types don't get special treatment.
+ if (ClassTy->isDependentType())
+ return false;
+ const CXXRecordDecl *RD = ClassTy->getAsCXXRecordDecl();
+ ASTContext &Context = RD->getASTContext();
+ // Member pointers not in the MS ABI don't get special treatment.
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft())
+ return false;
+ // The inheritance attribute might only be present on the most recent
+ // CXXRecordDecl, use that one.
+ RD = RD->getMostRecentDecl();
+ // Nothing interesting to do if the inheritance attribute is already set.
+ if (RD->hasAttr<MSInheritanceAttr>())
+ return false;
+ return true;
+ }
case ObjCObject:
return cast<ObjCObjectType>(CanonicalType)->getBaseType()
->isIncompleteType(Def);
@@ -2260,7 +2299,7 @@ bool QualType::isCXX11PODType(ASTContext &Context) const {
// a standard-layout class, and has no non-static data members of type
// non-POD struct, non-POD union (or array of such types). [...]
//
- // We don't directly query the recursive aspect as the requiremets for
+ // We don't directly query the recursive aspect as the requirements for
// both standard-layout classes and trivial classes apply recursively
// already.
}
@@ -2473,51 +2512,115 @@ const char *Type::getTypeClassName() const {
StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
switch (getKind()) {
- case Void: return "void";
- case Bool: return Policy.Bool ? "bool" : "_Bool";
- case Char_S: return "char";
- case Char_U: return "char";
- case SChar: return "signed char";
- case Short: return "short";
- case Int: return "int";
- case Long: return "long";
- case LongLong: return "long long";
- case Int128: return "__int128";
- case UChar: return "unsigned char";
- case UShort: return "unsigned short";
- case UInt: return "unsigned int";
- case ULong: return "unsigned long";
- case ULongLong: return "unsigned long long";
- case UInt128: return "unsigned __int128";
- case Half: return Policy.Half ? "half" : "__fp16";
- case Float: return "float";
- case Double: return "double";
- case LongDouble: return "long double";
+ case Void:
+ return "void";
+ case Bool:
+ return Policy.Bool ? "bool" : "_Bool";
+ case Char_S:
+ return "char";
+ case Char_U:
+ return "char";
+ case SChar:
+ return "signed char";
+ case Short:
+ return "short";
+ case Int:
+ return "int";
+ case Long:
+ return "long";
+ case LongLong:
+ return "long long";
+ case Int128:
+ return "__int128";
+ case UChar:
+ return "unsigned char";
+ case UShort:
+ return "unsigned short";
+ case UInt:
+ return "unsigned int";
+ case ULong:
+ return "unsigned long";
+ case ULongLong:
+ return "unsigned long long";
+ case UInt128:
+ return "unsigned __int128";
+ case Half:
+ return Policy.Half ? "half" : "__fp16";
+ case Float:
+ return "float";
+ case Double:
+ return "double";
+ case LongDouble:
+ return "long double";
case WChar_S:
- case WChar_U: return Policy.MSWChar ? "__wchar_t" : "wchar_t";
- case Char16: return "char16_t";
- case Char32: return "char32_t";
- case NullPtr: return "nullptr_t";
- case Overload: return "<overloaded function type>";
- case BoundMember: return "<bound member function type>";
- case PseudoObject: return "<pseudo-object type>";
- case Dependent: return "<dependent type>";
- case UnknownAny: return "<unknown type>";
- case ARCUnbridgedCast: return "<ARC unbridged cast type>";
- case BuiltinFn: return "<builtin fn type>";
- case ObjCId: return "id";
- case ObjCClass: return "Class";
- case ObjCSel: return "SEL";
- case OCLImage1d: return "image1d_t";
- case OCLImage1dArray: return "image1d_array_t";
- case OCLImage1dBuffer: return "image1d_buffer_t";
- case OCLImage2d: return "image2d_t";
- case OCLImage2dArray: return "image2d_array_t";
- case OCLImage3d: return "image3d_t";
- case OCLSampler: return "sampler_t";
- case OCLEvent: return "event_t";
+ case WChar_U:
+ return Policy.MSWChar ? "__wchar_t" : "wchar_t";
+ case Char16:
+ return "char16_t";
+ case Char32:
+ return "char32_t";
+ case NullPtr:
+ return "nullptr_t";
+ case Overload:
+ return "<overloaded function type>";
+ case BoundMember:
+ return "<bound member function type>";
+ case PseudoObject:
+ return "<pseudo-object type>";
+ case Dependent:
+ return "<dependent type>";
+ case UnknownAny:
+ return "<unknown type>";
+ case ARCUnbridgedCast:
+ return "<ARC unbridged cast type>";
+ case BuiltinFn:
+ return "<builtin fn type>";
+ case ObjCId:
+ return "id";
+ case ObjCClass:
+ return "Class";
+ case ObjCSel:
+ return "SEL";
+ case OCLImage1d:
+ return "image1d_t";
+ case OCLImage1dArray:
+ return "image1d_array_t";
+ case OCLImage1dBuffer:
+ return "image1d_buffer_t";
+ case OCLImage2d:
+ return "image2d_t";
+ case OCLImage2dArray:
+ return "image2d_array_t";
+ case OCLImage2dDepth:
+ return "image2d_depth_t";
+ case OCLImage2dArrayDepth:
+ return "image2d_array_depth_t";
+ case OCLImage2dMSAA:
+ return "image2d_msaa_t";
+ case OCLImage2dArrayMSAA:
+ return "image2d_array_msaa_t";
+ case OCLImage2dMSAADepth:
+ return "image2d_msaa_depth_t";
+ case OCLImage2dArrayMSAADepth:
+ return "image2d_array_msaa_depth_t";
+ case OCLImage3d:
+ return "image3d_t";
+ case OCLSampler:
+ return "sampler_t";
+ case OCLEvent:
+ return "event_t";
+ case OCLClkEvent:
+ return "clk_event_t";
+ case OCLQueue:
+ return "queue_t";
+ case OCLNDRange:
+ return "ndrange_t";
+ case OCLReserveID:
+ return "reserve_id_t";
+ case OMPArraySection:
+ return "<OpenMP array section type>";
}
-
+
llvm_unreachable("Invalid builtin type.");
}
@@ -2863,6 +2966,48 @@ bool TagType::isBeingDefined() const {
return getDecl()->isBeingDefined();
}
+bool AttributedType::isQualifier() const {
+ switch (getAttrKind()) {
+ // These are type qualifiers in the traditional C sense: they annotate
+ // something about a specific value/variable of a type. (They aren't
+ // always part of the canonical type, though.)
+ case AttributedType::attr_address_space:
+ case AttributedType::attr_objc_gc:
+ case AttributedType::attr_objc_ownership:
+ case AttributedType::attr_objc_inert_unsafe_unretained:
+ case AttributedType::attr_nonnull:
+ case AttributedType::attr_nullable:
+ case AttributedType::attr_null_unspecified:
+ return true;
+
+ // These aren't qualifiers; they rewrite the modified type to be a
+ // semantically different type.
+ case AttributedType::attr_regparm:
+ case AttributedType::attr_vector_size:
+ case AttributedType::attr_neon_vector_type:
+ case AttributedType::attr_neon_polyvector_type:
+ case AttributedType::attr_pcs:
+ case AttributedType::attr_pcs_vfp:
+ case AttributedType::attr_noreturn:
+ case AttributedType::attr_cdecl:
+ case AttributedType::attr_fastcall:
+ case AttributedType::attr_stdcall:
+ case AttributedType::attr_thiscall:
+ case AttributedType::attr_pascal:
+ case AttributedType::attr_vectorcall:
+ case AttributedType::attr_inteloclbicc:
+ case AttributedType::attr_ms_abi:
+ case AttributedType::attr_sysv_abi:
+ case AttributedType::attr_ptr32:
+ case AttributedType::attr_ptr64:
+ case AttributedType::attr_sptr:
+ case AttributedType::attr_uptr:
+ case AttributedType::attr_objc_kindof:
+ return false;
+ }
+ llvm_unreachable("bad attributed type kind");
+}
+
bool AttributedType::isMSTypeSpec() const {
switch (getAttrKind()) {
default: return false;
@@ -2888,6 +3033,7 @@ bool AttributedType::isCallingConv() const {
case attr_neon_polyvector_type:
case attr_objc_gc:
case attr_objc_ownership:
+ case attr_objc_inert_unsafe_unretained:
case attr_noreturn:
case attr_nonnull:
case attr_nullable:
@@ -2930,7 +3076,7 @@ SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param,
}
TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const {
- return TemplateArgument(Arguments, NumArguments);
+ return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments));
}
void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) {
@@ -3215,6 +3361,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType());
case Type::Atomic:
return Cache::get(cast<AtomicType>(T)->getValueType());
+ case Type::Pipe:
+ return Cache::get(cast<PipeType>(T)->getElementType());
}
llvm_unreachable("unhandled type class");
@@ -3297,6 +3445,8 @@ static LinkageInfo computeLinkageInfo(const Type *T) {
return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType());
case Type::Atomic:
return computeLinkageInfo(cast<AtomicType>(T)->getValueType());
+ case Type::Pipe:
+ return computeLinkageInfo(cast<PipeType>(T)->getElementType());
}
llvm_unreachable("unhandled type class");
@@ -3416,11 +3566,22 @@ bool Type::canHaveNullability() const {
case BuiltinType::OCLImage1dBuffer:
case BuiltinType::OCLImage2d:
case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage2dDepth:
+ case BuiltinType::OCLImage2dArrayDepth:
+ case BuiltinType::OCLImage2dMSAA:
+ case BuiltinType::OCLImage2dArrayMSAA:
+ case BuiltinType::OCLImage2dMSAADepth:
+ case BuiltinType::OCLImage2dArrayMSAADepth:
case BuiltinType::OCLImage3d:
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLNDRange:
+ case BuiltinType::OCLReserveID:
case BuiltinType::BuiltinFn:
case BuiltinType::NullPtr:
+ case BuiltinType::OMPArraySection:
return false;
}
@@ -3444,6 +3605,7 @@ bool Type::canHaveNullability() const {
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::Atomic:
+ case Type::Pipe:
return false;
}
llvm_unreachable("bad type kind!");
@@ -3521,7 +3683,7 @@ bool Type::isObjCARCImplicitlyUnretainedType() const {
if (const ObjCObjectPointerType *opt
= dyn_cast<ObjCObjectPointerType>(canon)) {
- // Class and Class<Protocol> don't require retension.
+ // Class and Class<Protocol> don't require retention.
if (opt->getObjectType()->isObjCClass())
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
index 85bda6a..d08b07b 100644
--- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp
@@ -192,7 +192,7 @@ SourceLocation TypeLoc::getBeginLoc() const {
Cur = Cur.getNextTypeLoc();
continue;
default:
- if (!Cur.getLocalSourceRange().getBegin().isInvalid())
+ if (Cur.getLocalSourceRange().getBegin().isValid())
LeftMost = Cur;
Cur = Cur.getNextTypeLoc();
if (Cur.isNull())
@@ -338,10 +338,21 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::OCLImage1dBuffer:
case BuiltinType::OCLImage2d:
case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage2dDepth:
+ case BuiltinType::OCLImage2dArrayDepth:
+ case BuiltinType::OCLImage2dMSAA:
+ case BuiltinType::OCLImage2dArrayMSAA:
+ case BuiltinType::OCLImage2dMSAADepth:
+ case BuiltinType::OCLImage2dArrayMSAADepth:
case BuiltinType::OCLImage3d:
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLNDRange:
+ case BuiltinType::OCLReserveID:
case BuiltinType::BuiltinFn:
+ case BuiltinType::OMPArraySection:
return TST_unspecified;
}
@@ -365,6 +376,27 @@ SourceLocation TypeLoc::findNullabilityLoc() const {
return SourceLocation();
}
+TypeLoc TypeLoc::findExplicitQualifierLoc() const {
+ // Qualified types.
+ if (auto qual = getAs<QualifiedTypeLoc>())
+ return qual;
+
+ TypeLoc loc = IgnoreParens();
+
+ // Attributed types.
+ if (auto attr = loc.getAs<AttributedTypeLoc>()) {
+ if (attr.isQualifier()) return attr;
+ return attr.getModifiedLoc().findExplicitQualifierLoc();
+ }
+
+ // C11 _Atomic types.
+ if (auto atomic = loc.getAs<AtomicTypeLoc>()) {
+ return atomic;
+ }
+
+ return TypeLoc();
+}
+
void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
setHasBaseTypeAsWritten(true);
diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
index 0bb50c6..b202523 100644
--- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp
@@ -193,6 +193,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::Atomic:
+ case Type::Pipe:
CanPrefixQualifiers = true;
break;
@@ -835,7 +836,11 @@ void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
if (!T->getDeducedType().isNull()) {
printBefore(T->getDeducedType(), OS);
} else {
- OS << (T->isDecltypeAuto() ? "decltype(auto)" : "auto");
+ switch (T->getKeyword()) {
+ case AutoTypeKeyword::Auto: OS << "auto"; break;
+ case AutoTypeKeyword::DecltypeAuto: OS << "decltype(auto)"; break;
+ case AutoTypeKeyword::GNUAutoType: OS << "__auto_type"; break;
+ }
spaceBeforePlaceHolder(OS);
}
}
@@ -855,6 +860,15 @@ void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
}
void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { }
+void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
+ IncludeStrongLifetimeRAII Strong(Policy);
+
+ OS << "pipe";
+ spaceBeforePlaceHolder(OS);
+}
+
+void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {
+}
/// Appends the given scope to the end of a string.
void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
if (DC->isTranslationUnit()) return;
@@ -921,12 +935,13 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
} else {
// Make an unambiguous representation for anonymous types, e.g.
// (anonymous enum at /usr/include/string.h:120:9)
-
+ OS << (Policy.MSVCFormatting ? '`' : '(');
+
if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {
- OS << "(lambda";
+ OS << "lambda";
HasKindDecoration = true;
} else {
- OS << "(anonymous";
+ OS << "anonymous";
}
if (Policy.AnonymousTagLocations) {
@@ -944,8 +959,8 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
<< ':' << PLoc.getColumn();
}
}
-
- OS << ')';
+
+ OS << (Policy.MSVCFormatting ? '\'' : ')');
}
// If this is a class template specialization, print the template
@@ -1187,6 +1202,10 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
printAfter(T->getModifiedType(), OS);
+ // Don't print the inert __unsafe_unretained attribute at all.
+ if (T->getAttrKind() == AttributedType::attr_objc_inert_unsafe_unretained)
+ return;
+
// Print nullability type specifiers that occur after
if (T->getAttrKind() == AttributedType::attr_nonnull ||
T->getAttrKind() == AttributedType::attr_nullable ||
@@ -1393,6 +1412,7 @@ TemplateSpecializationType::PrintTemplateArgumentList(
unsigned NumArgs,
const PrintingPolicy &Policy,
bool SkipBrackets) {
+ const char *Comma = Policy.MSVCFormatting ? "," : ", ";
if (!SkipBrackets)
OS << '<';
@@ -1403,14 +1423,14 @@ TemplateSpecializationType::PrintTemplateArgumentList(
llvm::raw_svector_ostream ArgOS(Buf);
if (Args[Arg].getKind() == TemplateArgument::Pack) {
if (Args[Arg].pack_size() && Arg > 0)
- OS << ", ";
+ OS << Comma;
PrintTemplateArgumentList(ArgOS,
Args[Arg].pack_begin(),
Args[Arg].pack_size(),
Policy, true);
} else {
if (Arg > 0)
- OS << ", ";
+ OS << Comma;
Args[Arg].print(Policy, ArgOS);
}
StringRef ArgString = ArgOS.str();
@@ -1442,11 +1462,12 @@ PrintTemplateArgumentList(raw_ostream &OS,
const TemplateArgumentLoc *Args, unsigned NumArgs,
const PrintingPolicy &Policy) {
OS << '<';
+ const char *Comma = Policy.MSVCFormatting ? "," : ", ";
bool needSpace = false;
for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
if (Arg > 0)
- OS << ", ";
+ OS << Comma;
// Print the argument into a string.
SmallString<128> Buf;
diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
index ca5f0aa..bae0186 100644
--- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp
@@ -177,14 +177,12 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
CXXFinalOverriderMap FinalOverriders;
MostDerivedClass->getFinalOverriders(FinalOverriders);
- for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(),
- E = FinalOverriders.end(); I != E; ++I) {
- const CXXMethodDecl *MD = I->first;
- const OverridingMethods& Methods = I->second;
-
- for (OverridingMethods::const_iterator I = Methods.begin(),
- E = Methods.end(); I != E; ++I) {
- unsigned SubobjectNumber = I->first;
+ for (const auto &Overrider : FinalOverriders) {
+ const CXXMethodDecl *MD = Overrider.first;
+ const OverridingMethods &Methods = Overrider.second;
+
+ for (const auto &M : Methods) {
+ unsigned SubobjectNumber = M.first;
assert(SubobjectOffsets.count(std::make_pair(MD->getParent(),
SubobjectNumber)) &&
"Did not find subobject offset!");
@@ -192,8 +190,8 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
CharUnits BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(),
SubobjectNumber)];
- assert(I->second.size() == 1 && "Final overrider is not unique!");
- const UniqueVirtualMethod &Method = I->second.front();
+ assert(M.second.size() == 1 && "Final overrider is not unique!");
+ const UniqueVirtualMethod &Method = M.second.front();
const CXXRecordDecl *OverriderRD = Method.Method->getParent();
assert(SubobjectLayoutClassOffsets.count(
@@ -482,13 +480,9 @@ static bool HasSameVirtualSignature(const CXXMethodDecl *LHS,
// Force the signatures to match. We can't rely on the overrides
// list here because there isn't necessarily an inheritance
// relationship between the two methods.
- if (LT->getTypeQuals() != RT->getTypeQuals() ||
- LT->getNumParams() != RT->getNumParams())
+ if (LT->getTypeQuals() != RT->getTypeQuals())
return false;
- for (unsigned I = 0, E = LT->getNumParams(); I != E; ++I)
- if (LT->getParamType(I) != RT->getParamType(I))
- return false;
- return true;
+ return LT->getParamTypes() == RT->getParamTypes();
}
bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
@@ -515,8 +509,8 @@ bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD,
CharUnits OffsetOffset) {
// Check if we can reuse an offset.
- for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
- if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
+ for (const auto &OffsetPair : Offsets) {
+ if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
return false;
}
@@ -527,9 +521,9 @@ bool VCallOffsetMap::AddVCallOffset(const CXXMethodDecl *MD,
CharUnits VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
// Look for an offset.
- for (unsigned I = 0, E = Offsets.size(); I != E; ++I) {
- if (MethodsCanShareVCallOffset(Offsets[I].first, MD))
- return Offsets[I].second;
+ for (const auto &OffsetPair : Offsets) {
+ if (MethodsCanShareVCallOffset(OffsetPair.first, MD))
+ return OffsetPair.second;
}
llvm_unreachable("Should always find a vcall offset offset!");
@@ -1097,39 +1091,30 @@ visitAllOverriddenMethods(const CXXMethodDecl *MD, VisitorTy &Visitor) {
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods(); I != E; ++I) {
const CXXMethodDecl *OverriddenMD = *I;
- if (!Visitor.visit(OverriddenMD))
+ if (!Visitor(OverriddenMD))
continue;
visitAllOverriddenMethods(OverriddenMD, Visitor);
}
}
-namespace {
- struct OverriddenMethodsCollector {
- OverriddenMethodsSetTy *Methods;
-
- bool visit(const CXXMethodDecl *MD) {
- // Don't recurse on this method if we've already collected it.
- return Methods->insert(MD).second;
- }
- };
-}
-
/// ComputeAllOverriddenMethods - Given a method decl, will return a set of all
/// the overridden methods that the function decl overrides.
static void
ComputeAllOverriddenMethods(const CXXMethodDecl *MD,
OverriddenMethodsSetTy& OverriddenMethods) {
- OverriddenMethodsCollector Collector = { &OverriddenMethods };
- visitAllOverriddenMethods(MD, Collector);
+ auto OverriddenMethodsCollector = [&](const CXXMethodDecl *MD) {
+ // Don't recurse on this method if we've already collected it.
+ return OverriddenMethods.insert(MD).second;
+ };
+ visitAllOverriddenMethods(MD, OverriddenMethodsCollector);
}
void ItaniumVTableBuilder::ComputeThisAdjustments() {
// Now go through the method info map and see if any of the methods need
// 'this' pointer adjustments.
- for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
- E = MethodInfoMap.end(); I != E; ++I) {
- const CXXMethodDecl *MD = I->first;
- const MethodInfo &MethodInfo = I->second;
+ for (const auto &MI : MethodInfoMap) {
+ const CXXMethodDecl *MD = MI.first;
+ const MethodInfo &MethodInfo = MI.second;
// Ignore adjustments for unused function pointers.
uint64_t VTableIndex = MethodInfo.VTableIndex;
@@ -1175,10 +1160,9 @@ void ItaniumVTableBuilder::ComputeThisAdjustments() {
return;
}
- for (VTableThunksMapTy::const_iterator I = VTableThunks.begin(),
- E = VTableThunks.end(); I != E; ++I) {
- const VTableComponent &Component = Components[I->first];
- const ThunkInfo &Thunk = I->second;
+ for (const auto &TI : VTableThunks) {
+ const VTableComponent &Component = Components[TI.first];
+ const ThunkInfo &Thunk = TI.second;
const CXXMethodDecl *MD;
switch (Component.getKind()) {
@@ -1237,10 +1221,9 @@ BaseOffset ItaniumVTableBuilder::ComputeThisAdjustmentBaseOffset(
// We have to go through all the paths, and see which one leads us to the
// right base subobject.
- for (CXXBasePaths::const_paths_iterator I = Paths.begin(), E = Paths.end();
- I != E; ++I) {
- BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, *I);
-
+ for (const CXXBasePath &Path : Paths) {
+ BaseOffset Offset = ComputeBaseOffset(Context, DerivedRD, Path);
+
CharUnits OffsetToBaseSubobject = Offset.NonVirtualOffset;
if (Offset.VirtualBase) {
@@ -1440,15 +1423,11 @@ FindNearestOverriddenMethod(const CXXMethodDecl *MD,
BasesSetVectorTy &Bases) {
OverriddenMethodsSetTy OverriddenMethods;
ComputeAllOverriddenMethods(MD, OverriddenMethods);
-
- for (int I = Bases.size(), E = 0; I != E; --I) {
- const CXXRecordDecl *PrimaryBase = Bases[I - 1];
+ for (const CXXRecordDecl *PrimaryBase :
+ llvm::make_range(Bases.rbegin(), Bases.rend())) {
// Now check the overridden methods.
- for (OverriddenMethodsSetTy::const_iterator I = OverriddenMethods.begin(),
- E = OverriddenMethods.end(); I != E; ++I) {
- const CXXMethodDecl *OverriddenMD = *I;
-
+ for (const CXXMethodDecl *OverriddenMD : OverriddenMethods) {
// We found our overridden method.
if (OverriddenMD->getParent() == PrimaryBase)
return OverriddenMD;
@@ -1596,10 +1575,7 @@ void ItaniumVTableBuilder::AddMethods(
if (ImplicitVirtualDtor)
NewVirtualFunctions.push_back(ImplicitVirtualDtor);
- for (NewVirtualFunctionsTy::const_iterator I = NewVirtualFunctions.begin(),
- E = NewVirtualFunctions.end(); I != E; ++I) {
- const CXXMethodDecl *MD = *I;
-
+ for (const CXXMethodDecl *MD : NewVirtualFunctions) {
// Get the final overrider.
FinalOverriders::OverriderInfo Overrider =
Overriders.getOverrider(MD, Base.getBaseOffset());
@@ -1700,10 +1676,9 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
const CXXRecordDecl *RD = Base.getBase();
if (RD == MostDerivedClass) {
assert(MethodVTableIndices.empty());
- for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
- E = MethodInfoMap.end(); I != E; ++I) {
- const CXXMethodDecl *MD = I->first;
- const MethodInfo &MI = I->second;
+ for (const auto &I : MethodInfoMap) {
+ const CXXMethodDecl *MD = I.first;
+ const MethodInfo &MI = I.second;
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
= MI.VTableIndex - AddressPoint;
@@ -1924,11 +1899,10 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
// Since an address point can be shared by multiple subobjects, we use an
// STL multimap.
std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
- for (AddressPointsMapTy::const_iterator I = AddressPoints.begin(),
- E = AddressPoints.end(); I != E; ++I) {
- const BaseSubobject& Base = I->first;
- uint64_t Index = I->second;
-
+ for (const auto &AP : AddressPoints) {
+ const BaseSubobject &Base = AP.first;
+ uint64_t Index = AP.second;
+
AddressPointsByIndex.insert(std::make_pair(Index, Base));
}
@@ -2077,18 +2051,16 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
// We store the class names in a set to get a stable order.
std::set<std::string> ClassNames;
- for (std::multimap<uint64_t, BaseSubobject>::const_iterator I =
- AddressPointsByIndex.lower_bound(NextIndex), E =
- AddressPointsByIndex.upper_bound(NextIndex); I != E; ++I) {
- assert(I->second.getBaseOffset() == BaseOffset &&
+ for (const auto &I :
+ llvm::make_range(AddressPointsByIndex.equal_range(NextIndex))) {
+ assert(I.second.getBaseOffset() == BaseOffset &&
"Invalid base offset!");
- const CXXRecordDecl *RD = I->second.getBase();
+ const CXXRecordDecl *RD = I.second.getBase();
ClassNames.insert(RD->getQualifiedNameAsString());
}
-
- for (std::set<std::string>::const_iterator I = ClassNames.begin(),
- E = ClassNames.end(); I != E; ++I) {
- Out << " -- (" << *I;
+
+ for (const std::string &Name : ClassNames) {
+ Out << " -- (" << Name;
Out << ", " << BaseOffset.getQuantity() << ") vtable address --\n";
}
}
@@ -2105,12 +2077,10 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
// a stable order.
std::map<std::string, CharUnits> ClassNamesAndOffsets;
- for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(),
- E = VBaseOffsetOffsets.end(); I != E; ++I) {
- std::string ClassName = I->first->getQualifiedNameAsString();
- CharUnits OffsetOffset = I->second;
- ClassNamesAndOffsets.insert(
- std::make_pair(ClassName, OffsetOffset));
+ for (const auto &I : VBaseOffsetOffsets) {
+ std::string ClassName = I.first->getQualifiedNameAsString();
+ CharUnits OffsetOffset = I.second;
+ ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
}
Out << "Virtual base offset offsets for '";
@@ -2119,10 +2089,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
Out << ClassNamesAndOffsets.size();
Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n";
- for (std::map<std::string, CharUnits>::const_iterator I =
- ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end();
- I != E; ++I)
- Out << " " << I->first << " | " << I->second.getQuantity() << '\n';
+ for (const auto &I : ClassNamesAndOffsets)
+ Out << " " << I.first << " | " << I.second.getQuantity() << '\n';
Out << "\n";
}
@@ -2130,10 +2098,9 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
if (!Thunks.empty()) {
// We store the method names in a map to get a stable order.
std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
-
- for (ThunksMapTy::const_iterator I = Thunks.begin(), E = Thunks.end();
- I != E; ++I) {
- const CXXMethodDecl *MD = I->first;
+
+ for (const auto &I : Thunks) {
+ const CXXMethodDecl *MD = I.first;
std::string MethodName =
PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
MD);
@@ -2141,11 +2108,9 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
}
- for (std::map<std::string, const CXXMethodDecl *>::const_iterator I =
- MethodNamesAndDecls.begin(), E = MethodNamesAndDecls.end();
- I != E; ++I) {
- const std::string &MethodName = I->first;
- const CXXMethodDecl *MD = I->second;
+ for (const auto &I : MethodNamesAndDecls) {
+ const std::string &MethodName = I.first;
+ const CXXMethodDecl *MD = I.second;
ThunkInfoVectorTy ThunksVector = Thunks[MD];
std::sort(ThunksVector.begin(), ThunksVector.end(),
@@ -2225,10 +2190,9 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
MostDerivedClass->printQualifiedName(Out);
Out << "' (" << IndicesMap.size() << " entries).\n";
- for (std::map<uint64_t, std::string>::const_iterator I = IndicesMap.begin(),
- E = IndicesMap.end(); I != E; ++I) {
- uint64_t VTableIndex = I->first;
- const std::string &MethodName = I->second;
+ for (const auto &I : IndicesMap) {
+ uint64_t VTableIndex = I.first;
+ const std::string &MethodName = I.second;
Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName
<< '\n';
@@ -2303,14 +2267,11 @@ ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
/*BaseIsVirtual=*/false,
/*OffsetInLayoutClass=*/CharUnits::Zero());
- for (VCallAndVBaseOffsetBuilder::VBaseOffsetOffsetsMapTy::const_iterator I =
- Builder.getVBaseOffsetOffsets().begin(),
- E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) {
+ for (const auto &I : Builder.getVBaseOffsetOffsets()) {
// Insert all types.
- ClassPairTy ClassPair(RD, I->first);
-
- VirtualBaseClassOffsetOffsets.insert(
- std::make_pair(ClassPair, I->second));
+ ClassPairTy ClassPair(RD, I.first);
+
+ VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
}
I = VirtualBaseClassOffsetOffsets.find(ClassPair);
@@ -2361,14 +2322,11 @@ ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) {
if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
return;
- for (ItaniumVTableBuilder::VBaseOffsetOffsetsMapTy::const_iterator
- I = Builder.getVBaseOffsetOffsets().begin(),
- E = Builder.getVBaseOffsetOffsets().end();
- I != E; ++I) {
+ for (const auto &I : Builder.getVBaseOffsetOffsets()) {
// Insert all types.
- ClassPairTy ClassPair(RD, I->first);
-
- VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second));
+ ClassPairTy ClassPair(RD, I.first);
+
+ VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I.second));
}
}
@@ -2561,10 +2519,9 @@ private:
"vftable can't be empty");
assert(MethodVFTableLocations.empty());
- for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
- E = MethodInfoMap.end(); I != E; ++I) {
- const CXXMethodDecl *MD = I->first;
- const MethodInfo &MI = I->second;
+ for (const auto &I : MethodInfoMap) {
+ const CXXMethodDecl *MD = I.first;
+ const MethodInfo &MI = I.second;
// Skip the methods that the MostDerivedClass didn't override
// and the entries shadowed by return adjusting thunks.
if (MD->getParent() != MostDerivedClass || MI.Shadowed)
@@ -2633,28 +2590,8 @@ public:
void dumpLayout(raw_ostream &);
};
-/// InitialOverriddenDefinitionCollector - Finds the set of least derived bases
-/// that define the given method.
-struct InitialOverriddenDefinitionCollector {
- BasesSetVectorTy Bases;
- OverriddenMethodsSetTy VisitedOverriddenMethods;
-
- bool visit(const CXXMethodDecl *OverriddenMD) {
- if (OverriddenMD->size_overridden_methods() == 0)
- Bases.insert(OverriddenMD->getParent());
- // Don't recurse on this method if we've already collected it.
- return VisitedOverriddenMethods.insert(OverriddenMD).second;
- }
-};
-
} // end namespace
-static bool BaseInSet(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *BasesSet) {
- BasesSetVectorTy *Bases = (BasesSetVectorTy *)BasesSet;
- return Bases->count(Specifier->getType()->getAsCXXRecordDecl());
-}
-
// Let's study one class hierarchy as an example:
// struct A {
// virtual void f();
@@ -2711,17 +2648,33 @@ static bool BaseInSet(const CXXBaseSpecifier *Specifier,
// for the given method, relative to the beginning of the MostDerivedClass.
CharUnits
VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
- InitialOverriddenDefinitionCollector Collector;
- visitAllOverriddenMethods(Overrider.Method, Collector);
+ BasesSetVectorTy Bases;
+
+ {
+ // Find the set of least derived bases that define the given method.
+ OverriddenMethodsSetTy VisitedOverriddenMethods;
+ auto InitialOverriddenDefinitionCollector = [&](
+ const CXXMethodDecl *OverriddenMD) {
+ if (OverriddenMD->size_overridden_methods() == 0)
+ Bases.insert(OverriddenMD->getParent());
+ // Don't recurse on this method if we've already collected it.
+ return VisitedOverriddenMethods.insert(OverriddenMD).second;
+ };
+ visitAllOverriddenMethods(Overrider.Method,
+ InitialOverriddenDefinitionCollector);
+ }
// If there are no overrides then 'this' is located
// in the base that defines the method.
- if (Collector.Bases.size() == 0)
+ if (Bases.size() == 0)
return Overrider.Offset;
CXXBasePaths Paths;
- Overrider.Method->getParent()->lookupInBases(BaseInSet, &Collector.Bases,
- Paths);
+ Overrider.Method->getParent()->lookupInBases(
+ [&Bases](const CXXBaseSpecifier *Specifier, CXXBasePath &) {
+ return Bases.count(Specifier->getType()->getAsCXXRecordDecl());
+ },
+ Paths);
// This will hold the smallest this offset among overridees of MD.
// This implies that an offset of a non-virtual base will dominate an offset
@@ -2732,17 +2685,14 @@ VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
const ASTRecordLayout &OverriderRDLayout =
Context.getASTRecordLayout(Overrider.Method->getParent());
- for (CXXBasePaths::paths_iterator I = Paths.begin(), E = Paths.end();
- I != E; ++I) {
- const CXXBasePath &Path = (*I);
+ for (const CXXBasePath &Path : Paths) {
CharUnits ThisOffset = Overrider.Offset;
CharUnits LastVBaseOffset;
// For each path from the overrider to the parents of the overridden
// methods, traverse the path, calculating the this offset in the most
// derived class.
- for (int J = 0, F = Path.size(); J != F; ++J) {
- const CXXBasePathElement &Element = Path[J];
+ for (const CXXBasePathElement &Element : Path) {
QualType CurTy = Element.Base->getType();
const CXXRecordDecl *PrevRD = Element.Class,
*CurRD = CurTy->getAsCXXRecordDecl();
@@ -2932,26 +2882,30 @@ static void GroupNewVirtualOverloads(
// Put the virtual methods into VirtualMethods in the proper order:
// 1) Group overloads by declaration name. New groups are added to the
// vftable in the order of their first declarations in this class
- // (including overrides and non-virtual methods).
+ // (including overrides, non-virtual methods and any other named decl that
+ // might be nested within the class).
// 2) In each group, new overloads appear in the reverse order of declaration.
typedef SmallVector<const CXXMethodDecl *, 1> MethodGroup;
SmallVector<MethodGroup, 10> Groups;
typedef llvm::DenseMap<DeclarationName, unsigned> VisitedGroupIndicesTy;
VisitedGroupIndicesTy VisitedGroupIndices;
- for (const auto *MD : RD->methods()) {
- MD = MD->getCanonicalDecl();
+ for (const auto *D : RD->decls()) {
+ const auto *ND = dyn_cast<NamedDecl>(D);
+ if (!ND)
+ continue;
VisitedGroupIndicesTy::iterator J;
bool Inserted;
std::tie(J, Inserted) = VisitedGroupIndices.insert(
- std::make_pair(MD->getDeclName(), Groups.size()));
+ std::make_pair(ND->getDeclName(), Groups.size()));
if (Inserted)
Groups.push_back(MethodGroup());
- if (MD->isVirtual())
- Groups[J->second].push_back(MD);
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(ND))
+ if (MD->isVirtual())
+ Groups[J->second].push_back(MD->getCanonicalDecl());
}
- for (unsigned I = 0, E = Groups.size(); I != E; ++I)
- VirtualMethods.append(Groups[I].rbegin(), Groups[I].rend());
+ for (const MethodGroup &Group : Groups)
+ VirtualMethods.append(Group.rbegin(), Group.rend());
}
static bool isDirectVBase(const CXXRecordDecl *Base, const CXXRecordDecl *RD) {
@@ -3011,9 +2965,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
// sub-bases;
// - adding new slots for methods that require Return adjustment.
// We keep track of the methods visited in the sub-bases in MethodInfoMap.
- for (unsigned I = 0, E = VirtualMethods.size(); I != E; ++I) {
- const CXXMethodDecl *MD = VirtualMethods[I];
-
+ for (const CXXMethodDecl *MD : VirtualMethods) {
FinalOverriders::OverriderInfo FinalOverrider =
Overriders.getOverrider(MD, Base.getBaseOffset());
const CXXMethodDecl *FinalOverriderMD = FinalOverrider.Method;
@@ -3122,10 +3074,10 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
}
static void PrintBasePath(const VPtrInfo::BasePath &Path, raw_ostream &Out) {
- for (VPtrInfo::BasePath::const_reverse_iterator I = Path.rbegin(),
- E = Path.rend(); I != E; ++I) {
+ for (const CXXRecordDecl *Elem :
+ llvm::make_range(Path.rbegin(), Path.rend())) {
Out << "'";
- (*I)->printQualifiedName(Out);
+ Elem->printQualifiedName(Out);
Out << "' in ";
}
}
@@ -3247,21 +3199,17 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) {
// We store the method names in a map to get a stable order.
std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
- for (ThunksMapTy::const_iterator I = Thunks.begin(), E = Thunks.end();
- I != E; ++I) {
- const CXXMethodDecl *MD = I->first;
+ for (const auto &I : Thunks) {
+ const CXXMethodDecl *MD = I.first;
std::string MethodName = PredefinedExpr::ComputeName(
PredefinedExpr::PrettyFunctionNoVirtual, MD);
MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
}
- for (std::map<std::string, const CXXMethodDecl *>::const_iterator
- I = MethodNamesAndDecls.begin(),
- E = MethodNamesAndDecls.end();
- I != E; ++I) {
- const std::string &MethodName = I->first;
- const CXXMethodDecl *MD = I->second;
+ for (const auto &MethodNameAndDecl : MethodNamesAndDecls) {
+ const std::string &MethodName = MethodNameAndDecl.first;
+ const CXXMethodDecl *MD = MethodNameAndDecl.second;
ThunkInfoVectorTy ThunksVector = Thunks[MD];
std::stable_sort(ThunksVector.begin(), ThunksVector.end(),
@@ -3291,9 +3239,8 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) {
static bool setsIntersect(const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &A,
ArrayRef<const CXXRecordDecl *> B) {
- for (ArrayRef<const CXXRecordDecl *>::iterator I = B.begin(), E = B.end();
- I != E; ++I) {
- if (A.count(*I))
+ for (const CXXRecordDecl *Decl : B) {
+ if (A.count(Decl))
return true;
}
return false;
@@ -3636,11 +3583,10 @@ void MicrosoftVTableContext::computeVTableRelatedInformation(
VFPtrLocations[RD] = VFPtrs;
MethodVFTableLocationsTy NewMethodLocations;
- for (VPtrInfoVector::iterator I = VFPtrs->begin(), E = VFPtrs->end();
- I != E; ++I) {
- VFTableBuilder Builder(*this, RD, *I);
+ for (const VPtrInfo *VFPtr : *VFPtrs) {
+ VFTableBuilder Builder(*this, RD, VFPtr);
- VFTableIdTy id(RD, (*I)->FullOffsetInMDC);
+ VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
assert(VFTableLayouts.count(id) == 0);
SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(
Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
@@ -3672,21 +3618,20 @@ void MicrosoftVTableContext::dumpMethodLocations(
std::map<MethodVFTableLocation, std::string> IndicesMap;
bool HasNonzeroOffset = false;
- for (MethodVFTableLocationsTy::const_iterator I = NewMethods.begin(),
- E = NewMethods.end(); I != E; ++I) {
- const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I->first.getDecl());
+ for (const auto &I : NewMethods) {
+ const CXXMethodDecl *MD = cast<const CXXMethodDecl>(I.first.getDecl());
assert(MD->isVirtual());
std::string MethodName = PredefinedExpr::ComputeName(
PredefinedExpr::PrettyFunctionNoVirtual, MD);
if (isa<CXXDestructorDecl>(MD)) {
- IndicesMap[I->second] = MethodName + " [scalar deleting]";
+ IndicesMap[I.second] = MethodName + " [scalar deleting]";
} else {
- IndicesMap[I->second] = MethodName;
+ IndicesMap[I.second] = MethodName;
}
- if (!I->second.VFPtrOffset.isZero() || I->second.VBTableIndex != 0)
+ if (!I.second.VFPtrOffset.isZero() || I.second.VBTableIndex != 0)
HasNonzeroOffset = true;
}
@@ -3700,12 +3645,9 @@ void MicrosoftVTableContext::dumpMethodLocations(
CharUnits LastVFPtrOffset = CharUnits::fromQuantity(-1);
uint64_t LastVBIndex = 0;
- for (std::map<MethodVFTableLocation, std::string>::const_iterator
- I = IndicesMap.begin(),
- E = IndicesMap.end();
- I != E; ++I) {
- CharUnits VFPtrOffset = I->first.VFPtrOffset;
- uint64_t VBIndex = I->first.VBTableIndex;
+ for (const auto &I : IndicesMap) {
+ CharUnits VFPtrOffset = I.first.VFPtrOffset;
+ uint64_t VBIndex = I.first.VBTableIndex;
if (HasNonzeroOffset &&
(VFPtrOffset != LastVFPtrOffset || VBIndex != LastVBIndex)) {
assert(VBIndex > LastVBIndex || VFPtrOffset > LastVFPtrOffset);
@@ -3717,8 +3659,8 @@ void MicrosoftVTableContext::dumpMethodLocations(
LastVBIndex = VBIndex;
}
- uint64_t VTableIndex = I->first.Index;
- const std::string &MethodName = I->second;
+ uint64_t VTableIndex = I.first.Index;
+ const std::string &MethodName = I.second;
Out << llvm::format("%4" PRIu64 " | ", VTableIndex) << MethodName << '\n';
}
Out << '\n';
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index e3b666e..847398c 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -197,9 +197,6 @@ public:
bool shouldVisitTemplateInstantiations() const { return true; }
bool shouldVisitImplicitCode() const { return true; }
- // Disables data recursion. We intercept Traverse* methods in the RAV, which
- // are not triggered during data recursion.
- bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
private:
// Used for updating the depth during traversal.
@@ -487,9 +484,6 @@ public:
bool shouldVisitTemplateInstantiations() const { return true; }
bool shouldVisitImplicitCode() const { return true; }
- // Disables data recursion. We intercept Traverse* methods in the RAV, which
- // are not triggered during data recursion.
- bool shouldUseDataRecursionFor(clang::Stmt *S) const { return false; }
private:
class TimeBucketRegion {
@@ -621,9 +615,6 @@ private:
if (Node.get<TranslationUnitDecl>() ==
ActiveASTContext->getTranslationUnitDecl())
return false;
- assert(Node.getMemoizationData() &&
- "Invariant broken: only nodes that support memoization may be "
- "used in the parent map.");
MatchKey Key;
Key.MatcherID = Matcher.getID();
@@ -867,7 +858,11 @@ bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) {
bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
NestedNameSpecifierLoc NNS) {
+ if (!NNS)
+ return true;
+
match(NNS);
+
// We only match the nested name specifier here (as opposed to traversing it)
// because the traversal is already done in the parallel "Loc"-hierarchy.
if (NNS.hasQualifier())
@@ -913,37 +908,37 @@ MatchFinder::~MatchFinder() {}
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
MatchCallback *Action) {
Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
- Matchers.AllCallbacks.push_back(Action);
+ Matchers.AllCallbacks.insert(Action);
}
void MatchFinder::addMatcher(const TypeMatcher &NodeMatch,
MatchCallback *Action) {
Matchers.Type.emplace_back(NodeMatch, Action);
- Matchers.AllCallbacks.push_back(Action);
+ Matchers.AllCallbacks.insert(Action);
}
void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
MatchCallback *Action) {
Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
- Matchers.AllCallbacks.push_back(Action);
+ Matchers.AllCallbacks.insert(Action);
}
void MatchFinder::addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
MatchCallback *Action) {
Matchers.NestedNameSpecifier.emplace_back(NodeMatch, Action);
- Matchers.AllCallbacks.push_back(Action);
+ Matchers.AllCallbacks.insert(Action);
}
void MatchFinder::addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
MatchCallback *Action) {
Matchers.NestedNameSpecifierLoc.emplace_back(NodeMatch, Action);
- Matchers.AllCallbacks.push_back(Action);
+ Matchers.AllCallbacks.insert(Action);
}
void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
MatchCallback *Action) {
Matchers.TypeLoc.emplace_back(NodeMatch, Action);
- Matchers.AllCallbacks.push_back(Action);
+ Matchers.AllCallbacks.insert(Action);
}
bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 069fcba..463cf0b 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -110,15 +110,15 @@ static llvm::ManagedStatic<TrueMatcherImpl> TrueMatcherInstance;
DynTypedMatcher DynTypedMatcher::constructVariadic(
DynTypedMatcher::VariadicOperator Op,
+ ast_type_traits::ASTNodeKind SupportedKind,
std::vector<DynTypedMatcher> InnerMatchers) {
assert(InnerMatchers.size() > 0 && "Array must not be empty.");
assert(std::all_of(InnerMatchers.begin(), InnerMatchers.end(),
- [&InnerMatchers](const DynTypedMatcher &M) {
- return InnerMatchers[0].canConvertTo(M.SupportedKind);
- }) &&
- "SupportedKind must be convertible to a common type!");
+ [SupportedKind](const DynTypedMatcher &M) {
+ return M.canConvertTo(SupportedKind);
+ }) &&
+ "InnerMatchers must be convertible to SupportedKind!");
- auto SupportedKind = InnerMatchers[0].SupportedKind;
// We must relax the restrict kind here.
// The different operators might deal differently with a mismatch.
// Make it the same as SupportedKind, since that is the broadest type we are
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
index 72f1271..787b780 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
@@ -23,14 +23,14 @@ Diagnostics::ArgStream Diagnostics::pushContextFrame(ContextType Type,
Diagnostics::Context::Context(ConstructMatcherEnum, Diagnostics *Error,
StringRef MatcherName,
- const SourceRange &MatcherRange)
+ SourceRange MatcherRange)
: Error(Error) {
Error->pushContextFrame(CT_MatcherConstruct, MatcherRange) << MatcherName;
}
Diagnostics::Context::Context(MatcherArgEnum, Diagnostics *Error,
StringRef MatcherName,
- const SourceRange &MatcherRange,
+ SourceRange MatcherRange,
unsigned ArgNumber)
: Error(Error) {
Error->pushContextFrame(CT_MatcherArg, MatcherRange) << ArgNumber
@@ -63,7 +63,7 @@ Diagnostics::ArgStream &Diagnostics::ArgStream::operator<<(const Twine &Arg) {
return *this;
}
-Diagnostics::ArgStream Diagnostics::addError(const SourceRange &Range,
+Diagnostics::ArgStream Diagnostics::addError(SourceRange Range,
ErrorType Error) {
Errors.emplace_back();
ErrorContent &Last = Errors.back();
@@ -150,7 +150,7 @@ static void formatErrorString(StringRef FormatString,
}
}
-static void maybeAddLineAndColumn(const SourceRange &Range,
+static void maybeAddLineAndColumn(SourceRange Range,
llvm::raw_ostream &OS) {
if (Range.Start.Line > 0 && Range.Start.Column > 0) {
OS << Range.Start.Line << ":" << Range.Start.Column << ": ";
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
index 36a6415..64d6b78 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -104,7 +104,7 @@ public:
class MatcherDescriptor {
public:
virtual ~MatcherDescriptor() {}
- virtual VariantMatcher create(const SourceRange &NameRange,
+ virtual VariantMatcher create(SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) const = 0;
@@ -162,7 +162,7 @@ class FixedArgCountMatcherDescriptor : public MatcherDescriptor {
public:
typedef VariantMatcher (*MarshallerType)(void (*Func)(),
StringRef MatcherName,
- const SourceRange &NameRange,
+ SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error);
@@ -180,7 +180,7 @@ public:
RetKinds(RetKinds.begin(), RetKinds.end()),
ArgKinds(ArgKinds.begin(), ArgKinds.end()) {}
- VariantMatcher create(const SourceRange &NameRange,
+ VariantMatcher create(SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) const override {
return Marshaller(Func, MatcherName, NameRange, Args, Error);
@@ -279,7 +279,7 @@ struct BuildReturnTypeVector<ast_matchers::internal::BindableMatcher<T> > {
template <typename ResultT, typename ArgT,
ResultT (*Func)(ArrayRef<const ArgT *>)>
VariantMatcher
-variadicMatcherDescriptor(StringRef MatcherName, const SourceRange &NameRange,
+variadicMatcherDescriptor(StringRef MatcherName, SourceRange NameRange,
ArrayRef<ParserValue> Args, Diagnostics *Error) {
ArgT **InnerArgs = new ArgT *[Args.size()]();
@@ -320,7 +320,7 @@ variadicMatcherDescriptor(StringRef MatcherName, const SourceRange &NameRange,
class VariadicFuncMatcherDescriptor : public MatcherDescriptor {
public:
typedef VariantMatcher (*RunFunc)(StringRef MatcherName,
- const SourceRange &NameRange,
+ SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error);
@@ -334,7 +334,7 @@ public:
BuildReturnTypeVector<ResultT>::build(RetKinds);
}
- VariantMatcher create(const SourceRange &NameRange,
+ VariantMatcher create(SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) const override {
return Func(MatcherName, NameRange, Args, Error);
@@ -414,7 +414,7 @@ private:
/// \brief 0-arg marshaller function.
template <typename ReturnType>
static VariantMatcher matcherMarshall0(void (*Func)(), StringRef MatcherName,
- const SourceRange &NameRange,
+ SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
typedef ReturnType (*FuncType)();
@@ -425,7 +425,7 @@ static VariantMatcher matcherMarshall0(void (*Func)(), StringRef MatcherName,
/// \brief 1-arg marshaller function.
template <typename ReturnType, typename ArgType1>
static VariantMatcher matcherMarshall1(void (*Func)(), StringRef MatcherName,
- const SourceRange &NameRange,
+ SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
typedef ReturnType (*FuncType)(ArgType1);
@@ -438,7 +438,7 @@ static VariantMatcher matcherMarshall1(void (*Func)(), StringRef MatcherName,
/// \brief 2-arg marshaller function.
template <typename ReturnType, typename ArgType1, typename ArgType2>
static VariantMatcher matcherMarshall2(void (*Func)(), StringRef MatcherName,
- const SourceRange &NameRange,
+ SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
typedef ReturnType (*FuncType)(ArgType1, ArgType2);
@@ -493,7 +493,7 @@ public:
~OverloadedMatcherDescriptor() override {}
- VariantMatcher create(const SourceRange &NameRange,
+ VariantMatcher create(SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) const override {
std::vector<VariantMatcher> Constructed;
@@ -567,7 +567,7 @@ public:
: MinCount(MinCount), MaxCount(MaxCount), Op(Op),
MatcherName(MatcherName) {}
- VariantMatcher create(const SourceRange &NameRange,
+ VariantMatcher create(SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) const override {
if (Args.size() < MinCount || MaxCount < Args.size()) {
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
index 96a78cd..cf9dab6 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -534,7 +534,7 @@ Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
}
VariantMatcher Parser::RegistrySema::actOnMatcherExpression(
- MatcherCtor Ctor, const SourceRange &NameRange, StringRef BindID,
+ MatcherCtor Ctor, SourceRange NameRange, StringRef BindID,
ArrayRef<ParserValue> Args, Diagnostics *Error) {
if (BindID.empty()) {
return Registry::constructMatcher(Ctor, NameRange, Args, Error);
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 72713dd..5b1c552 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -15,6 +15,7 @@
#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "Marshallers.h"
#include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ManagedStatic.h"
@@ -106,15 +107,13 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(atomicType);
REGISTER_MATCHER(autoType);
REGISTER_MATCHER(binaryOperator);
- REGISTER_MATCHER(bindTemporaryExpr);
REGISTER_MATCHER(blockPointerType);
- REGISTER_MATCHER(boolLiteral);
+ REGISTER_MATCHER(booleanType);
REGISTER_MATCHER(breakStmt);
REGISTER_MATCHER(builtinType);
REGISTER_MATCHER(callExpr);
REGISTER_MATCHER(caseStmt);
REGISTER_MATCHER(castExpr);
- REGISTER_MATCHER(catchStmt);
REGISTER_MATCHER(characterLiteral);
REGISTER_MATCHER(classTemplateDecl);
REGISTER_MATCHER(classTemplateSpecializationDecl);
@@ -123,27 +122,46 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(compoundStmt);
REGISTER_MATCHER(conditionalOperator);
REGISTER_MATCHER(constantArrayType);
- REGISTER_MATCHER(constCastExpr);
- REGISTER_MATCHER(constructExpr);
- REGISTER_MATCHER(constructorDecl);
REGISTER_MATCHER(containsDeclaration);
REGISTER_MATCHER(continueStmt);
- REGISTER_MATCHER(conversionDecl);
REGISTER_MATCHER(cStyleCastExpr);
- REGISTER_MATCHER(ctorInitializer);
- REGISTER_MATCHER(CUDAKernelCallExpr);
+ REGISTER_MATCHER(cudaKernelCallExpr);
+ REGISTER_MATCHER(cxxBindTemporaryExpr);
+ REGISTER_MATCHER(cxxBoolLiteral);
+ REGISTER_MATCHER(cxxCatchStmt);
+ REGISTER_MATCHER(cxxConstCastExpr);
+ REGISTER_MATCHER(cxxConstructExpr);
+ REGISTER_MATCHER(cxxConstructorDecl);
+ REGISTER_MATCHER(cxxConversionDecl);
+ REGISTER_MATCHER(cxxCtorInitializer);
+ REGISTER_MATCHER(cxxDefaultArgExpr);
+ REGISTER_MATCHER(cxxDeleteExpr);
+ REGISTER_MATCHER(cxxDestructorDecl);
+ REGISTER_MATCHER(cxxDynamicCastExpr);
+ REGISTER_MATCHER(cxxForRangeStmt);
+ REGISTER_MATCHER(cxxFunctionalCastExpr);
+ REGISTER_MATCHER(cxxMemberCallExpr);
+ REGISTER_MATCHER(cxxMethodDecl);
+ REGISTER_MATCHER(cxxNewExpr);
+ REGISTER_MATCHER(cxxNullPtrLiteralExpr);
+ REGISTER_MATCHER(cxxOperatorCallExpr);
+ REGISTER_MATCHER(cxxRecordDecl);
+ REGISTER_MATCHER(cxxReinterpretCastExpr);
+ REGISTER_MATCHER(cxxStaticCastExpr);
+ REGISTER_MATCHER(cxxTemporaryObjectExpr);
+ REGISTER_MATCHER(cxxThisExpr);
+ REGISTER_MATCHER(cxxThrowExpr);
+ REGISTER_MATCHER(cxxTryStmt);
+ REGISTER_MATCHER(cxxUnresolvedConstructExpr);
+ REGISTER_MATCHER(decayedType);
REGISTER_MATCHER(decl);
REGISTER_MATCHER(declaratorDecl);
REGISTER_MATCHER(declCountIs);
REGISTER_MATCHER(declRefExpr);
REGISTER_MATCHER(declStmt);
- REGISTER_MATCHER(defaultArgExpr);
REGISTER_MATCHER(defaultStmt);
- REGISTER_MATCHER(deleteExpr);
REGISTER_MATCHER(dependentSizedArrayType);
- REGISTER_MATCHER(destructorDecl);
REGISTER_MATCHER(doStmt);
- REGISTER_MATCHER(dynamicCastExpr);
REGISTER_MATCHER(eachOf);
REGISTER_MATCHER(elaboratedType);
REGISTER_MATCHER(enumConstantDecl);
@@ -160,10 +178,8 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(forEachDescendant);
REGISTER_MATCHER(forEachSwitchCase);
REGISTER_MATCHER(forField);
- REGISTER_MATCHER(forRangeStmt);
REGISTER_MATCHER(forStmt);
REGISTER_MATCHER(friendDecl);
- REGISTER_MATCHER(functionalCastExpr);
REGISTER_MATCHER(functionDecl);
REGISTER_MATCHER(functionTemplateDecl);
REGISTER_MATCHER(functionType);
@@ -179,12 +195,14 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasArgument);
REGISTER_MATCHER(hasArgumentOfType);
REGISTER_MATCHER(hasAttr);
+ REGISTER_MATCHER(hasAutomaticStorageDuration);
REGISTER_MATCHER(hasBase);
REGISTER_MATCHER(hasBody);
REGISTER_MATCHER(hasCanonicalType);
REGISTER_MATCHER(hasCaseConstant);
REGISTER_MATCHER(hasCondition);
REGISTER_MATCHER(hasConditionVariableStatement);
+ REGISTER_MATCHER(hasDecayedType);
REGISTER_MATCHER(hasDeclaration);
REGISTER_MATCHER(hasDeclContext);
REGISTER_MATCHER(hasDeducedType);
@@ -222,9 +240,11 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasSize);
REGISTER_MATCHER(hasSizeExpr);
REGISTER_MATCHER(hasSourceExpression);
+ REGISTER_MATCHER(hasStaticStorageDuration);
REGISTER_MATCHER(hasTargetDecl);
REGISTER_MATCHER(hasTemplateArgument);
REGISTER_MATCHER(hasThen);
+ REGISTER_MATCHER(hasThreadStorageDuration);
REGISTER_MATCHER(hasTrueExpression);
REGISTER_MATCHER(hasTypeLoc);
REGISTER_MATCHER(hasUnaryOperand);
@@ -237,17 +257,27 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(implicitCastExpr);
REGISTER_MATCHER(incompleteArrayType);
REGISTER_MATCHER(initListExpr);
+ REGISTER_MATCHER(injectedClassNameType);
REGISTER_MATCHER(innerType);
REGISTER_MATCHER(integerLiteral);
+ REGISTER_MATCHER(isAnonymous);
REGISTER_MATCHER(isArrow);
+ REGISTER_MATCHER(isBaseInitializer);
REGISTER_MATCHER(isCatchAll);
+ REGISTER_MATCHER(isClass);
REGISTER_MATCHER(isConst);
REGISTER_MATCHER(isConstQualified);
+ REGISTER_MATCHER(isCopyConstructor);
+ REGISTER_MATCHER(isDefaultConstructor);
REGISTER_MATCHER(isDefinition);
REGISTER_MATCHER(isDeleted);
+ REGISTER_MATCHER(isExceptionVariable);
+ REGISTER_MATCHER(isExplicit);
REGISTER_MATCHER(isExplicitTemplateSpecialization);
REGISTER_MATCHER(isExpr);
REGISTER_MATCHER(isExternC);
+ REGISTER_MATCHER(isFinal);
+ REGISTER_MATCHER(isInline);
REGISTER_MATCHER(isImplicit);
REGISTER_MATCHER(isExpansionInFileMatching);
REGISTER_MATCHER(isExpansionInMainFile);
@@ -257,13 +287,20 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isIntegral);
REGISTER_MATCHER(isInTemplateInstantiation);
REGISTER_MATCHER(isListInitialization);
+ REGISTER_MATCHER(isMemberInitializer);
+ REGISTER_MATCHER(isMoveConstructor);
+ REGISTER_MATCHER(isNoThrow);
REGISTER_MATCHER(isOverride);
REGISTER_MATCHER(isPrivate);
REGISTER_MATCHER(isProtected);
REGISTER_MATCHER(isPublic);
REGISTER_MATCHER(isPure);
+ REGISTER_MATCHER(isStruct);
REGISTER_MATCHER(isTemplateInstantiation);
+ REGISTER_MATCHER(isUnion);
+ REGISTER_MATCHER(isVariadic);
REGISTER_MATCHER(isVirtual);
+ REGISTER_MATCHER(isVolatileQualified);
REGISTER_MATCHER(isWritten);
REGISTER_MATCHER(labelStmt);
REGISTER_MATCHER(lambdaExpr);
@@ -272,24 +309,22 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(matchesSelector);
REGISTER_MATCHER(materializeTemporaryExpr);
REGISTER_MATCHER(member);
- REGISTER_MATCHER(memberCallExpr);
REGISTER_MATCHER(memberExpr);
REGISTER_MATCHER(memberPointerType);
- REGISTER_MATCHER(methodDecl);
REGISTER_MATCHER(namedDecl);
+ REGISTER_MATCHER(namespaceAliasDecl);
REGISTER_MATCHER(namespaceDecl);
REGISTER_MATCHER(namesType);
REGISTER_MATCHER(nestedNameSpecifier);
REGISTER_MATCHER(nestedNameSpecifierLoc);
- REGISTER_MATCHER(newExpr);
- REGISTER_MATCHER(nullPtrLiteralExpr);
REGISTER_MATCHER(nullStmt);
REGISTER_MATCHER(numSelectorArgs);
REGISTER_MATCHER(ofClass);
+ REGISTER_MATCHER(objcInterfaceDecl);
REGISTER_MATCHER(objcMessageExpr);
+ REGISTER_MATCHER(objcObjectPointerType);
REGISTER_MATCHER(on);
REGISTER_MATCHER(onImplicitObjectArgument);
- REGISTER_MATCHER(operatorCallExpr);
REGISTER_MATCHER(parameterCountIs);
REGISTER_MATCHER(parenType);
REGISTER_MATCHER(parmVarDecl);
@@ -302,7 +337,6 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(refersToDeclaration);
REGISTER_MATCHER(refersToIntegralType);
REGISTER_MATCHER(refersToType);
- REGISTER_MATCHER(reinterpretCastExpr);
REGISTER_MATCHER(returns);
REGISTER_MATCHER(returnStmt);
REGISTER_MATCHER(rValueReferenceType);
@@ -311,23 +345,20 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(specifiesType);
REGISTER_MATCHER(specifiesTypeLoc);
REGISTER_MATCHER(statementCountIs);
- REGISTER_MATCHER(staticCastExpr);
REGISTER_MATCHER(staticAssertDecl);
REGISTER_MATCHER(stmt);
REGISTER_MATCHER(stringLiteral);
REGISTER_MATCHER(substNonTypeTemplateParmExpr);
+ REGISTER_MATCHER(substTemplateTypeParmType);
REGISTER_MATCHER(switchCase);
REGISTER_MATCHER(switchStmt);
REGISTER_MATCHER(templateArgument);
REGISTER_MATCHER(templateArgumentCountIs);
REGISTER_MATCHER(templateSpecializationType);
- REGISTER_MATCHER(temporaryObjectExpr);
- REGISTER_MATCHER(thisExpr);
+ REGISTER_MATCHER(templateTypeParmType);
REGISTER_MATCHER(throughUsingDecl);
- REGISTER_MATCHER(throwExpr);
REGISTER_MATCHER(to);
REGISTER_MATCHER(translationUnitDecl);
- REGISTER_MATCHER(tryStmt);
REGISTER_MATCHER(type);
REGISTER_MATCHER(typedefDecl);
REGISTER_MATCHER(typedefType);
@@ -336,7 +367,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(unaryOperator);
REGISTER_MATCHER(unaryTransformType);
REGISTER_MATCHER(unless);
- REGISTER_MATCHER(unresolvedConstructExpr);
+ REGISTER_MATCHER(unresolvedUsingTypenameDecl);
REGISTER_MATCHER(unresolvedUsingValueDecl);
REGISTER_MATCHER(userDefinedLiteral);
REGISTER_MATCHER(usingDecl);
@@ -350,11 +381,7 @@ RegistryMaps::RegistryMaps() {
}
RegistryMaps::~RegistryMaps() {
- for (ConstructorMap::iterator it = Constructors.begin(),
- end = Constructors.end();
- it != end; ++it) {
- delete it->second;
- }
+ llvm::DeleteContainerSeconds(Constructors);
}
static llvm::ManagedStatic<RegistryMaps> RegistryData;
@@ -425,12 +452,13 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
std::vector<MatcherCompletion> Completions;
// Search the registry for acceptable matchers.
- for (ConstructorMap::const_iterator I = RegistryData->constructors().begin(),
- E = RegistryData->constructors().end();
- I != E; ++I) {
+ for (const auto &M : RegistryData->constructors()) {
+ const auto *Matcher = M.getValue();
+ StringRef Name = M.getKey();
+
std::set<ASTNodeKind> RetKinds;
- unsigned NumArgs = I->second->isVariadic() ? 1 : I->second->getNumArgs();
- bool IsPolymorphic = I->second->isPolymorphic();
+ unsigned NumArgs = Matcher->isVariadic() ? 1 : Matcher->getNumArgs();
+ bool IsPolymorphic = Matcher->isPolymorphic();
std::vector<std::vector<ArgKind>> ArgsKinds(NumArgs);
unsigned MaxSpecificity = 0;
for (const ArgKind& Kind : AcceptedTypes) {
@@ -438,13 +466,13 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
continue;
unsigned Specificity;
ASTNodeKind LeastDerivedKind;
- if (I->second->isConvertibleTo(Kind.getMatcherKind(), &Specificity,
- &LeastDerivedKind)) {
+ if (Matcher->isConvertibleTo(Kind.getMatcherKind(), &Specificity,
+ &LeastDerivedKind)) {
if (MaxSpecificity < Specificity)
MaxSpecificity = Specificity;
RetKinds.insert(LeastDerivedKind);
for (unsigned Arg = 0; Arg != NumArgs; ++Arg)
- I->second->getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
+ Matcher->getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
if (IsPolymorphic)
break;
}
@@ -455,9 +483,9 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
llvm::raw_string_ostream OS(Decl);
if (IsPolymorphic) {
- OS << "Matcher<T> " << I->first() << "(Matcher<T>";
+ OS << "Matcher<T> " << Name << "(Matcher<T>";
} else {
- OS << "Matcher<" << RetKinds << "> " << I->first() << "(";
+ OS << "Matcher<" << RetKinds << "> " << Name << "(";
for (const std::vector<ArgKind> &Arg : ArgsKinds) {
if (&Arg != &ArgsKinds[0])
OS << ", ";
@@ -480,11 +508,11 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
}
}
}
- if (I->second->isVariadic())
+ if (Matcher->isVariadic())
OS << "...";
OS << ")";
- std::string TypedText = I->first();
+ std::string TypedText = Name;
TypedText += "(";
if (ArgsKinds.empty())
TypedText += ")";
@@ -500,7 +528,7 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
// static
VariantMatcher Registry::constructMatcher(MatcherCtor Ctor,
- const SourceRange &NameRange,
+ SourceRange NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
return Ctor->create(NameRange, Args, Error);
@@ -508,7 +536,7 @@ VariantMatcher Registry::constructMatcher(MatcherCtor Ctor,
// static
VariantMatcher Registry::constructBoundMatcher(MatcherCtor Ctor,
- const SourceRange &NameRange,
+ SourceRange NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
diff --git a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
index 9d8be47..8f3c70c 100644
--- a/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ b/contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -72,7 +72,7 @@ VariantMatcher::MatcherOps::constructVariadicOperator(
return llvm::None;
DynMatchers.push_back(*Inner);
}
- return DynTypedMatcher::constructVariadic(Op, DynMatchers);
+ return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
}
VariantMatcher::Payload::~Payload() {}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp b/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
index d7fb7e9..52c7f26 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
@@ -148,6 +148,23 @@ const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
}
}
+ auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
+ if (!CXXMethod)
+ return nullptr;
+
+ const CXXRecordDecl *parent = CXXMethod->getParent();
+ if (!parent->isLambda())
+ return nullptr;
+
+ for (const LambdaCapture &LC : parent->captures()) {
+ if (!LC.capturesVariable())
+ continue;
+
+ VarDecl *VD = LC.getCapturedVar();
+ if (VD->getName() == "self")
+ return dyn_cast<ImplicitParamDecl>(VD);
+ }
+
return nullptr;
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp b/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp
index 7d1b235..0990436 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/BodyFarm.cpp
@@ -36,10 +36,7 @@ static bool isDispatchBlock(QualType Ty) {
// returns void.
const FunctionProtoType *FT =
BPT->getPointeeType()->getAs<FunctionProtoType>();
- if (!FT || !FT->getReturnType()->isVoidType() || FT->getNumParams() != 0)
- return false;
-
- return true;
+ return FT && FT->getReturnType()->isVoidType() && FT->getNumParams() == 0;
}
namespace {
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
index 54d15bd..ed2239f 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
@@ -39,6 +39,78 @@ static SourceLocation GetEndLoc(Decl *D) {
return D->getLocation();
}
+/// Helper for tryNormalizeBinaryOperator. Attempts to extract an IntegerLiteral
+/// or EnumConstantDecl from the given Expr. If it fails, returns nullptr.
+const Expr *tryTransformToIntOrEnumConstant(const Expr *E) {
+ E = E->IgnoreParens();
+ if (isa<IntegerLiteral>(E))
+ return E;
+ if (auto *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
+ return isa<EnumConstantDecl>(DR->getDecl()) ? DR : nullptr;
+ return nullptr;
+}
+
+/// Tries to interpret a binary operator into `Decl Op Expr` form, if Expr is
+/// an integer literal or an enum constant.
+///
+/// If this fails, at least one of the returned DeclRefExpr or Expr will be
+/// null.
+static std::tuple<const DeclRefExpr *, BinaryOperatorKind, const Expr *>
+tryNormalizeBinaryOperator(const BinaryOperator *B) {
+ BinaryOperatorKind Op = B->getOpcode();
+
+ const Expr *MaybeDecl = B->getLHS();
+ const Expr *Constant = tryTransformToIntOrEnumConstant(B->getRHS());
+ // Expr looked like `0 == Foo` instead of `Foo == 0`
+ if (Constant == nullptr) {
+ // Flip the operator
+ if (Op == BO_GT)
+ Op = BO_LT;
+ else if (Op == BO_GE)
+ Op = BO_LE;
+ else if (Op == BO_LT)
+ Op = BO_GT;
+ else if (Op == BO_LE)
+ Op = BO_GE;
+
+ MaybeDecl = B->getRHS();
+ Constant = tryTransformToIntOrEnumConstant(B->getLHS());
+ }
+
+ auto *D = dyn_cast<DeclRefExpr>(MaybeDecl->IgnoreParenImpCasts());
+ return std::make_tuple(D, Op, Constant);
+}
+
+/// For an expression `x == Foo && x == Bar`, this determines whether the
+/// `Foo` and `Bar` are either of the same enumeration type, or both integer
+/// literals.
+///
+/// It's an error to pass this arguments that are not either IntegerLiterals
+/// or DeclRefExprs (that have decls of type EnumConstantDecl)
+static bool areExprTypesCompatible(const Expr *E1, const Expr *E2) {
+ // User intent isn't clear if they're mixing int literals with enum
+ // constants.
+ if (isa<IntegerLiteral>(E1) != isa<IntegerLiteral>(E2))
+ return false;
+
+ // Integer literal comparisons, regardless of literal type, are acceptable.
+ if (isa<IntegerLiteral>(E1))
+ return true;
+
+ // IntegerLiterals are handled above and only EnumConstantDecls are expected
+ // beyond this point
+ assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2));
+ auto *Decl1 = cast<DeclRefExpr>(E1)->getDecl();
+ auto *Decl2 = cast<DeclRefExpr>(E2)->getDecl();
+
+ assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2));
+ const DeclContext *DC1 = Decl1->getDeclContext();
+ const DeclContext *DC2 = Decl2->getDeclContext();
+
+ assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2));
+ return DC1 == DC2;
+}
+
class CFGBuilder;
/// The CFG builder uses a recursive algorithm to build the CFG. When
@@ -176,8 +248,8 @@ private:
public:
/// Constructs empty scope linked to previous scope in specified place.
- LocalScope(BumpVectorContext &ctx, const_iterator P)
- : ctx(ctx), Vars(ctx, 4), Prev(P) {}
+ LocalScope(BumpVectorContext ctx, const_iterator P)
+ : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
/// Begin of scope in direction of CFG building (backwards).
const_iterator begin() const { return const_iterator(*this, Vars.size()); }
@@ -284,7 +356,7 @@ reverse_children::reverse_children(Stmt *S) {
/// Example usage:
///
/// CFGBuilder builder;
-/// CFG* cfg = builder.BuildAST(stmt1);
+/// std::unique_ptr<CFG> cfg = builder.buildCFG(decl, stmt1);
///
/// CFG construction is done via a recursive walk of an AST. We actually parse
/// the AST in reverse order so that the successor of a basic block is
@@ -388,6 +460,7 @@ private:
CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);
CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);
CFGBlock *VisitLabelStmt(LabelStmt *L);
+ CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc);
CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc);
CFGBlock *VisitLogicalOperator(BinaryOperator *B);
std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B,
@@ -694,56 +767,35 @@ private:
if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
return TryResult();
- BinaryOperatorKind BO1 = LHS->getOpcode();
- const DeclRefExpr *Decl1 =
- dyn_cast<DeclRefExpr>(LHS->getLHS()->IgnoreParenImpCasts());
- const IntegerLiteral *Literal1 =
- dyn_cast<IntegerLiteral>(LHS->getRHS()->IgnoreParens());
- if (!Decl1 && !Literal1) {
- if (BO1 == BO_GT)
- BO1 = BO_LT;
- else if (BO1 == BO_GE)
- BO1 = BO_LE;
- else if (BO1 == BO_LT)
- BO1 = BO_GT;
- else if (BO1 == BO_LE)
- BO1 = BO_GE;
- Decl1 = dyn_cast<DeclRefExpr>(LHS->getRHS()->IgnoreParenImpCasts());
- Literal1 = dyn_cast<IntegerLiteral>(LHS->getLHS()->IgnoreParens());
- }
+ const DeclRefExpr *Decl1;
+ const Expr *Expr1;
+ BinaryOperatorKind BO1;
+ std::tie(Decl1, BO1, Expr1) = tryNormalizeBinaryOperator(LHS);
- if (!Decl1 || !Literal1)
+ if (!Decl1 || !Expr1)
return TryResult();
- BinaryOperatorKind BO2 = RHS->getOpcode();
- const DeclRefExpr *Decl2 =
- dyn_cast<DeclRefExpr>(RHS->getLHS()->IgnoreParenImpCasts());
- const IntegerLiteral *Literal2 =
- dyn_cast<IntegerLiteral>(RHS->getRHS()->IgnoreParens());
- if (!Decl2 && !Literal2) {
- if (BO2 == BO_GT)
- BO2 = BO_LT;
- else if (BO2 == BO_GE)
- BO2 = BO_LE;
- else if (BO2 == BO_LT)
- BO2 = BO_GT;
- else if (BO2 == BO_LE)
- BO2 = BO_GE;
- Decl2 = dyn_cast<DeclRefExpr>(RHS->getRHS()->IgnoreParenImpCasts());
- Literal2 = dyn_cast<IntegerLiteral>(RHS->getLHS()->IgnoreParens());
- }
+ const DeclRefExpr *Decl2;
+ const Expr *Expr2;
+ BinaryOperatorKind BO2;
+ std::tie(Decl2, BO2, Expr2) = tryNormalizeBinaryOperator(RHS);
- if (!Decl2 || !Literal2)
+ if (!Decl2 || !Expr2)
return TryResult();
// Check that it is the same variable on both sides.
if (Decl1->getDecl() != Decl2->getDecl())
return TryResult();
+ // Make sure the user's intent is clear (e.g. they're comparing against two
+ // int literals, or two things from the same enum)
+ if (!areExprTypesCompatible(Expr1, Expr2))
+ return TryResult();
+
llvm::APSInt L1, L2;
- if (!Literal1->EvaluateAsInt(L1, *Context) ||
- !Literal2->EvaluateAsInt(L2, *Context))
+ if (!Expr1->EvaluateAsInt(L1, *Context) ||
+ !Expr2->EvaluateAsInt(L2, *Context))
return TryResult();
// Can't compare signed with unsigned or with different bit width.
@@ -773,10 +825,7 @@ private:
// * Variable x is equal to the largest literal.
// * Variable x is greater than largest literal.
bool AlwaysTrue = true, AlwaysFalse = true;
- for (unsigned int ValueIndex = 0;
- ValueIndex < sizeof(Values) / sizeof(Values[0]);
- ++ValueIndex) {
- llvm::APSInt Value = Values[ValueIndex];
+ for (llvm::APSInt Value : Values) {
TryResult Res1, Res2;
Res1 = analyzeLogicOperatorCondition(BO1, Value, L1);
Res2 = analyzeLogicOperatorCondition(BO2, Value, L2);
@@ -994,9 +1043,8 @@ std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
// For C++ constructor add initializers to CFG.
if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
- for (CXXConstructorDecl::init_const_reverse_iterator I = CD->init_rbegin(),
- E = CD->init_rend(); I != E; ++I) {
- B = addInitializer(*I);
+ for (auto *I : llvm::reverse(CD->inits())) {
+ B = addInitializer(I);
if (badCFG)
return nullptr;
}
@@ -1248,13 +1296,11 @@ void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {
/// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either
/// way return valid LocalScope object.
LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
- if (!Scope) {
- llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
- Scope = alloc.Allocate<LocalScope>();
- BumpVectorContext ctx(alloc);
- new (Scope) LocalScope(ctx, ScopePos);
- }
- return Scope;
+ if (Scope)
+ return Scope;
+ llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
+ return new (alloc.Allocate<LocalScope>())
+ LocalScope(BumpVectorContext(alloc), ScopePos);
}
/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement
@@ -1405,7 +1451,7 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
case Stmt::BlockExprClass:
- return VisitNoRecurse(cast<Expr>(S), asc);
+ return VisitBlockExpr(cast<BlockExpr>(S), asc);
case Stmt::BreakStmtClass:
return VisitBreakStmt(cast<BreakStmt>(S));
@@ -1894,7 +1940,15 @@ CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) {
- addLocalScopeAndDtors(C);
+ LocalScope::const_iterator scopeBeginPos = ScopePos;
+ if (BuildOpts.AddImplicitDtors) {
+ addLocalScopeForStmt(C);
+ }
+ if (!C->body_empty() && !isa<ReturnStmt>(*C->body_rbegin())) {
+ // If the body ends with a ReturnStmt, the dtors will be added in VisitReturnStmt
+ addAutomaticObjDtors(ScopePos, scopeBeginPos, C);
+ }
+
CFGBlock *LastBlock = Block;
for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend();
@@ -2277,6 +2331,18 @@ CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) {
return LabelBlock;
}
+CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
+ CFGBlock *LastBlock = VisitNoRecurse(E, asc);
+ for (const BlockDecl::Capture &CI : E->getBlockDecl()->captures()) {
+ if (Expr *CopyExpr = CI.getCopyExpr()) {
+ CFGBlock *Tmp = Visit(CopyExpr);
+ if (Tmp)
+ LastBlock = Tmp;
+ }
+ }
+ return LastBlock;
+}
+
CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) {
CFGBlock *LastBlock = VisitNoRecurse(E, asc);
for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(),
@@ -3104,11 +3170,11 @@ static bool shouldAddCase(bool &switchExclusivelyCovered,
addCase = true;
switchExclusivelyCovered = true;
}
- else if (condInt < lhsInt) {
+ else if (condInt > lhsInt) {
if (const Expr *RHS = CS->getRHS()) {
// Evaluate the RHS of the case value.
const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx);
- if (V2 <= condInt) {
+ if (V2 >= condInt) {
addCase = true;
switchExclusivelyCovered = true;
}
@@ -4128,7 +4194,8 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
const CompoundStmt *Sub = SE->getSubStmt();
- if (Sub->children()) {
+ auto Children = Sub->children();
+ if (Children.begin() != Children.end()) {
OS << "({ ... ; ";
Helper.handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
OS << " })\n";
diff --git a/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp b/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
index fa985ee..9df2392 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp
@@ -1038,65 +1038,54 @@ bool ConsumedBlockInfo::allBackEdgesVisited(const CFGBlock *CurrBlock,
return true;
}
-void ConsumedBlockInfo::addInfo(const CFGBlock *Block,
- ConsumedStateMap *StateMap,
- bool &AlreadyOwned) {
-
+void ConsumedBlockInfo::addInfo(
+ const CFGBlock *Block, ConsumedStateMap *StateMap,
+ std::unique_ptr<ConsumedStateMap> &OwnedStateMap) {
+
assert(Block && "Block pointer must not be NULL");
-
- ConsumedStateMap *Entry = StateMapsArray[Block->getBlockID()];
-
+
+ auto &Entry = StateMapsArray[Block->getBlockID()];
+
if (Entry) {
- Entry->intersect(StateMap);
-
- } else if (AlreadyOwned) {
- StateMapsArray[Block->getBlockID()] = new ConsumedStateMap(*StateMap);
-
- } else {
- StateMapsArray[Block->getBlockID()] = StateMap;
- AlreadyOwned = true;
- }
+ Entry->intersect(*StateMap);
+ } else if (OwnedStateMap)
+ Entry = std::move(OwnedStateMap);
+ else
+ Entry = llvm::make_unique<ConsumedStateMap>(*StateMap);
}
void ConsumedBlockInfo::addInfo(const CFGBlock *Block,
- ConsumedStateMap *StateMap) {
+ std::unique_ptr<ConsumedStateMap> StateMap) {
assert(Block && "Block pointer must not be NULL");
- ConsumedStateMap *Entry = StateMapsArray[Block->getBlockID()];
-
+ auto &Entry = StateMapsArray[Block->getBlockID()];
+
if (Entry) {
- Entry->intersect(StateMap);
- delete StateMap;
-
+ Entry->intersect(*StateMap);
} else {
- StateMapsArray[Block->getBlockID()] = StateMap;
+ Entry = std::move(StateMap);
}
}
ConsumedStateMap* ConsumedBlockInfo::borrowInfo(const CFGBlock *Block) {
assert(Block && "Block pointer must not be NULL");
assert(StateMapsArray[Block->getBlockID()] && "Block has no block info");
-
- return StateMapsArray[Block->getBlockID()];
+
+ return StateMapsArray[Block->getBlockID()].get();
}
void ConsumedBlockInfo::discardInfo(const CFGBlock *Block) {
- unsigned int BlockID = Block->getBlockID();
- delete StateMapsArray[BlockID];
- StateMapsArray[BlockID] = nullptr;
+ StateMapsArray[Block->getBlockID()] = nullptr;
}
-ConsumedStateMap* ConsumedBlockInfo::getInfo(const CFGBlock *Block) {
+std::unique_ptr<ConsumedStateMap>
+ConsumedBlockInfo::getInfo(const CFGBlock *Block) {
assert(Block && "Block pointer must not be NULL");
-
- ConsumedStateMap *StateMap = StateMapsArray[Block->getBlockID()];
- if (isBackEdgeTarget(Block)) {
- return new ConsumedStateMap(*StateMap);
- } else {
- StateMapsArray[Block->getBlockID()] = nullptr;
- return StateMap;
- }
+
+ auto &Entry = StateMapsArray[Block->getBlockID()];
+ return isBackEdgeTarget(Block) ? llvm::make_unique<ConsumedStateMap>(*Entry)
+ : std::move(Entry);
}
bool ConsumedBlockInfo::isBackEdge(const CFGBlock *From, const CFGBlock *To) {
@@ -1166,15 +1155,15 @@ ConsumedStateMap::getState(const CXXBindTemporaryExpr *Tmp) const {
return CS_None;
}
-void ConsumedStateMap::intersect(const ConsumedStateMap *Other) {
+void ConsumedStateMap::intersect(const ConsumedStateMap &Other) {
ConsumedState LocalState;
-
- if (this->From && this->From == Other->From && !Other->Reachable) {
+
+ if (this->From && this->From == Other.From && !Other.Reachable) {
this->markUnreachable();
return;
}
-
- for (const auto &DM : Other->VarMap) {
+
+ for (const auto &DM : Other.VarMap) {
LocalState = this->getState(DM.first);
if (LocalState == CS_None)
@@ -1282,14 +1271,14 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
if (PInfo.isVarTest()) {
CurrStates->setSource(Cond);
FalseStates->setSource(Cond);
- splitVarStateForIf(IfNode, PInfo.getVarTest(), CurrStates,
+ splitVarStateForIf(IfNode, PInfo.getVarTest(), CurrStates.get(),
FalseStates.get());
-
+
} else if (PInfo.isBinTest()) {
CurrStates->setSource(PInfo.testSourceNode());
FalseStates->setSource(PInfo.testSourceNode());
- splitVarStateForIfBinOp(PInfo, CurrStates, FalseStates.get());
-
+ splitVarStateForIfBinOp(PInfo, CurrStates.get(), FalseStates.get());
+
} else {
return false;
}
@@ -1337,14 +1326,13 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin();
if (*SI)
- BlockInfo.addInfo(*SI, CurrStates);
+ BlockInfo.addInfo(*SI, std::move(CurrStates));
else
- delete CurrStates;
-
+ CurrStates = nullptr;
+
if (*++SI)
- BlockInfo.addInfo(*SI, FalseStates.release());
+ BlockInfo.addInfo(*SI, std::move(FalseStates));
- CurrStates = nullptr;
return true;
}
@@ -1363,10 +1351,10 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
// AC.getCFG()->viewCFG(LangOptions());
BlockInfo = ConsumedBlockInfo(CFGraph->getNumBlockIDs(), SortedGraph);
-
- CurrStates = new ConsumedStateMap();
- ConsumedStmtVisitor Visitor(AC, *this, CurrStates);
-
+
+ CurrStates = llvm::make_unique<ConsumedStateMap>();
+ ConsumedStmtVisitor Visitor(AC, *this, CurrStates.get());
+
// Add all trackable parameters to the state map.
for (const auto *PI : D->params())
Visitor.VisitParmVarDecl(PI);
@@ -1380,13 +1368,12 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
continue;
} else if (!CurrStates->isReachable()) {
- delete CurrStates;
CurrStates = nullptr;
continue;
}
-
- Visitor.reset(CurrStates);
-
+
+ Visitor.reset(CurrStates.get());
+
// Visit all of the basic block's statements.
for (const auto &B : *CurrBlock) {
switch (B.getKind()) {
@@ -1429,28 +1416,24 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
if (CurrBlock->succ_size() > 1 ||
(CurrBlock->succ_size() == 1 &&
(*CurrBlock->succ_begin())->pred_size() > 1)) {
-
- bool OwnershipTaken = false;
-
+
+ auto *RawState = CurrStates.get();
+
for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
SE = CurrBlock->succ_end(); SI != SE; ++SI) {
if (*SI == nullptr) continue;
if (BlockInfo.isBackEdge(CurrBlock, *SI)) {
- BlockInfo.borrowInfo(*SI)->intersectAtLoopHead(*SI, CurrBlock,
- CurrStates,
- WarningsHandler);
-
+ BlockInfo.borrowInfo(*SI)->intersectAtLoopHead(
+ *SI, CurrBlock, RawState, WarningsHandler);
+
if (BlockInfo.allBackEdgesVisited(CurrBlock, *SI))
BlockInfo.discardInfo(*SI);
} else {
- BlockInfo.addInfo(*SI, CurrStates, OwnershipTaken);
+ BlockInfo.addInfo(*SI, RawState, CurrStates);
}
}
-
- if (!OwnershipTaken)
- delete CurrStates;
CurrStates = nullptr;
}
@@ -1463,8 +1446,8 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
} // End of block iterator.
// Delete the last existing state map.
- delete CurrStates;
-
+ CurrStates = nullptr;
+
WarningsHandler.emitDiagnostics();
}
}} // end namespace clang::consumed
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
index e2c6ab5..b282a5b 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp
@@ -258,16 +258,15 @@ private:
typedef SmallVector<const ValueDecl*, 4> BeforeVect;
struct BeforeInfo {
- BeforeInfo() : Vect(nullptr), Visited(false) { }
- BeforeInfo(BeforeInfo &&O)
- : Vect(std::move(O.Vect)), Visited(O.Visited)
- {}
+ BeforeInfo() : Visited(0) {}
+ BeforeInfo(BeforeInfo &&O) : Vect(std::move(O.Vect)), Visited(O.Visited) {}
- std::unique_ptr<BeforeVect> Vect;
- int Visited;
+ BeforeVect Vect;
+ int Visited;
};
- typedef llvm::DenseMap<const ValueDecl*, BeforeInfo> BeforeMap;
+ typedef llvm::DenseMap<const ValueDecl *, std::unique_ptr<BeforeInfo>>
+ BeforeMap;
typedef llvm::DenseMap<const ValueDecl*, bool> CycleMap;
public:
@@ -276,6 +275,9 @@ public:
BeforeInfo* insertAttrExprs(const ValueDecl* Vd,
ThreadSafetyAnalyzer& Analyzer);
+ BeforeInfo *getBeforeInfoForDecl(const ValueDecl *Vd,
+ ThreadSafetyAnalyzer &Analyzer);
+
void checkBeforeAfter(const ValueDecl* Vd,
const FactSet& FSet,
ThreadSafetyAnalyzer& Analyzer,
@@ -787,7 +789,7 @@ static void findBlockLocations(CFG *CFGraph,
}
}
- if (!CurrBlockInfo->ExitLoc.isInvalid()) {
+ if (CurrBlockInfo->ExitLoc.isValid()) {
// This block contains at least one statement. Find the source location
// of the first statement in the block.
for (CFGBlock::const_iterator BI = CurrBlock->begin(),
@@ -965,26 +967,27 @@ public:
BeforeSet::BeforeInfo* BeforeSet::insertAttrExprs(const ValueDecl* Vd,
ThreadSafetyAnalyzer& Analyzer) {
// Create a new entry for Vd.
- auto& Entry = BMap.FindAndConstruct(Vd);
- BeforeInfo* Info = &Entry.second;
- BeforeVect* Bv = nullptr;
+ BeforeInfo *Info = nullptr;
+ {
+ // Keep InfoPtr in its own scope in case BMap is modified later and the
+ // reference becomes invalid.
+ std::unique_ptr<BeforeInfo> &InfoPtr = BMap[Vd];
+ if (!InfoPtr)
+ InfoPtr.reset(new BeforeInfo());
+ Info = InfoPtr.get();
+ }
for (Attr* At : Vd->attrs()) {
switch (At->getKind()) {
case attr::AcquiredBefore: {
auto *A = cast<AcquiredBeforeAttr>(At);
- // Create a new BeforeVect for Vd if necessary.
- if (!Bv) {
- Bv = new BeforeVect;
- Info->Vect.reset(Bv);
- }
// Read exprs from the attribute, and add them to BeforeVect.
for (const auto *Arg : A->args()) {
CapabilityExpr Cp =
Analyzer.SxBuilder.translateAttrExpr(Arg, nullptr);
if (const ValueDecl *Cpvd = Cp.valueDecl()) {
- Bv->push_back(Cpvd);
+ Info->Vect.push_back(Cpvd);
auto It = BMap.find(Cpvd);
if (It == BMap.end())
insertAttrExprs(Cpvd, Analyzer);
@@ -1001,20 +1004,8 @@ BeforeSet::BeforeInfo* BeforeSet::insertAttrExprs(const ValueDecl* Vd,
Analyzer.SxBuilder.translateAttrExpr(Arg, nullptr);
if (const ValueDecl *ArgVd = Cp.valueDecl()) {
// Get entry for mutex listed in attribute
- BeforeInfo* ArgInfo;
- auto It = BMap.find(ArgVd);
- if (It == BMap.end())
- ArgInfo = insertAttrExprs(ArgVd, Analyzer);
- else
- ArgInfo = &It->second;
-
- // Create a new BeforeVect if necessary.
- BeforeVect* ArgBv = ArgInfo->Vect.get();
- if (!ArgBv) {
- ArgBv = new BeforeVect;
- ArgInfo->Vect.reset(ArgBv);
- }
- ArgBv->push_back(Vd);
+ BeforeInfo *ArgInfo = getBeforeInfoForDecl(ArgVd, Analyzer);
+ ArgInfo->Vect.push_back(Vd);
}
}
break;
@@ -1027,6 +1018,18 @@ BeforeSet::BeforeInfo* BeforeSet::insertAttrExprs(const ValueDecl* Vd,
return Info;
}
+BeforeSet::BeforeInfo *
+BeforeSet::getBeforeInfoForDecl(const ValueDecl *Vd,
+ ThreadSafetyAnalyzer &Analyzer) {
+ auto It = BMap.find(Vd);
+ BeforeInfo *Info = nullptr;
+ if (It == BMap.end())
+ Info = insertAttrExprs(Vd, Analyzer);
+ else
+ Info = It->second.get();
+ assert(Info && "BMap contained nullptr?");
+ return Info;
+}
/// Return true if any mutexes in FSet are in the acquired_before set of Vd.
void BeforeSet::checkBeforeAfter(const ValueDecl* StartVd,
@@ -1041,12 +1044,7 @@ void BeforeSet::checkBeforeAfter(const ValueDecl* StartVd,
if (!Vd)
return false;
- BeforeSet::BeforeInfo* Info;
- auto It = BMap.find(Vd);
- if (It == BMap.end())
- Info = insertAttrExprs(Vd, Analyzer);
- else
- Info = &It->second;
+ BeforeSet::BeforeInfo *Info = getBeforeInfoForDecl(Vd, Analyzer);
if (Info->Visited == 1)
return true;
@@ -1054,13 +1052,12 @@ void BeforeSet::checkBeforeAfter(const ValueDecl* StartVd,
if (Info->Visited == 2)
return false;
- BeforeVect* Bv = Info->Vect.get();
- if (!Bv)
+ if (Info->Vect.empty())
return false;
InfoVect.push_back(Info);
Info->Visited = 1;
- for (auto *Vdb : *Bv) {
+ for (auto *Vdb : Info->Vect) {
// Exclude mutexes in our immediate before set.
if (FSet.containsMutexDecl(Analyzer.FactMan, Vdb)) {
StringRef L1 = StartVd->getName();
@@ -1926,34 +1923,42 @@ void BuildLockset::VisitCallExpr(CallExpr *Exp) {
}
}
-
if (ExamineArgs) {
if (FunctionDecl *FD = Exp->getDirectCallee()) {
- unsigned Fn = FD->getNumParams();
- unsigned Cn = Exp->getNumArgs();
- unsigned Skip = 0;
-
- unsigned i = 0;
- if (OperatorFun) {
- if (isa<CXXMethodDecl>(FD)) {
- // First arg in operator call is implicit self argument,
- // and doesn't appear in the FunctionDecl.
- Skip = 1;
- Cn--;
- } else {
- // Ignore the first argument of operators; it's been checked above.
- i = 1;
+
+ // NO_THREAD_SAFETY_ANALYSIS does double duty here. Normally it
+ // only turns off checking within the body of a function, but we also
+ // use it to turn off checking in arguments to the function. This
+ // could result in some false negatives, but the alternative is to
+ // create yet another attribute.
+ //
+ if (!FD->hasAttr<NoThreadSafetyAnalysisAttr>()) {
+ unsigned Fn = FD->getNumParams();
+ unsigned Cn = Exp->getNumArgs();
+ unsigned Skip = 0;
+
+ unsigned i = 0;
+ if (OperatorFun) {
+ if (isa<CXXMethodDecl>(FD)) {
+ // First arg in operator call is implicit self argument,
+ // and doesn't appear in the FunctionDecl.
+ Skip = 1;
+ Cn--;
+ } else {
+ // Ignore the first argument of operators; it's been checked above.
+ i = 1;
+ }
+ }
+ // Ignore default arguments
+ unsigned n = (Fn < Cn) ? Fn : Cn;
+
+ for (; i < n; ++i) {
+ ParmVarDecl* Pvd = FD->getParamDecl(i);
+ Expr* Arg = Exp->getArg(i+Skip);
+ QualType Qt = Pvd->getType();
+ if (Qt->isReferenceType())
+ checkAccess(Arg, AK_Read, POK_PassByRef);
}
- }
- // Ignore default arguments
- unsigned n = (Fn < Cn) ? Fn : Cn;
-
- for (; i < n; ++i) {
- ParmVarDecl* Pvd = FD->getParamDecl(i);
- Expr* Arg = Exp->getArg(i+Skip);
- QualType Qt = Pvd->getType();
- if (Qt->isReferenceType())
- checkAccess(Arg, AK_Read, POK_PassByRef);
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
index d4b1ce2..ffe95ea 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -1,4 +1,4 @@
-//===- ThreadSafetyCommon.cpp ----------------------------------*- C++ --*-===//
+//===- ThreadSafetyCommon.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -31,6 +31,7 @@
#include <algorithm>
#include <climits>
#include <vector>
+
using namespace clang;
using namespace threadSafety;
@@ -66,7 +67,6 @@ static bool isIncompletePhi(const til::SExpr *E) {
typedef SExprBuilder::CallingContext CallingContext;
-
til::SExpr *SExprBuilder::lookupStmt(const Stmt *S) {
auto It = SMap.find(S);
if (It != SMap.end())
@@ -74,7 +74,6 @@ til::SExpr *SExprBuilder::lookupStmt(const Stmt *S) {
return nullptr;
}
-
til::SCFG *SExprBuilder::buildCFG(CFGWalker &Walker) {
Walker.walk(*this);
return Scfg;
@@ -85,7 +84,6 @@ static bool isCalleeArrow(const Expr *E) {
return ME ? ME->isArrow() : false;
}
-
/// \brief Translate a clang expression in an attribute to a til::SExpr.
/// Constructs the context from D, DeclExp, and SelfDecl.
///
@@ -148,7 +146,6 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
return translateAttrExpr(AttrExp, &Ctx);
}
-
/// \brief Translate a clang expression in an attribute to a til::SExpr.
// This assumes a CallingContext has already been created.
CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
@@ -195,8 +192,6 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
return CapabilityExpr(E, Neg);
}
-
-
// Translate a clang statement or expression to a TIL expression.
// Also performs substitution of variables; Ctx provides the context.
// Dispatches on the type of S.
@@ -268,8 +263,6 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
return new (Arena) til::Undefined(S);
}
-
-
til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE,
CallingContext *Ctx) {
const ValueDecl *VD = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
@@ -290,11 +283,10 @@ til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE,
VD = FD->getParamDecl(I);
}
- // For non-local variables, treat it as a referenced to a named object.
+ // For non-local variables, treat it as a reference to a named object.
return new (Arena) til::LiteralPtr(VD);
}
-
til::SExpr *SExprBuilder::translateCXXThisExpr(const CXXThisExpr *TE,
CallingContext *Ctx) {
// Substitute for 'this'
@@ -313,7 +305,7 @@ static const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) {
return P->clangDecl();
if (auto *L = dyn_cast<til::LiteralPtr>(E))
return L->clangDecl();
- return 0;
+ return nullptr;
}
static bool hasCppPointerType(const til::SExpr *E) {
@@ -344,7 +336,8 @@ til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME,
til::SExpr *BE = translate(ME->getBase(), Ctx);
til::SExpr *E = new (Arena) til::SApply(BE);
- const ValueDecl *D = ME->getMemberDecl();
+ const ValueDecl *D =
+ cast<ValueDecl>(ME->getMemberDecl()->getCanonicalDecl());
if (auto *VD = dyn_cast<CXXMethodDecl>(D))
D = getFirstVirtualDecl(VD);
@@ -354,7 +347,6 @@ til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME,
return P;
}
-
til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE,
CallingContext *Ctx,
const Expr *SelfE) {
@@ -380,7 +372,6 @@ til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE,
return new (Arena) til::Call(E, CE);
}
-
til::SExpr *SExprBuilder::translateCXXMemberCallExpr(
const CXXMemberCallExpr *ME, CallingContext *Ctx) {
if (CapabilityExprMode) {
@@ -396,7 +387,6 @@ til::SExpr *SExprBuilder::translateCXXMemberCallExpr(
ME->getImplicitObjectArgument());
}
-
til::SExpr *SExprBuilder::translateCXXOperatorCallExpr(
const CXXOperatorCallExpr *OCE, CallingContext *Ctx) {
if (CapabilityExprMode) {
@@ -411,7 +401,6 @@ til::SExpr *SExprBuilder::translateCXXOperatorCallExpr(
return translateCallExpr(cast<CallExpr>(OCE), Ctx);
}
-
til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO,
CallingContext *Ctx) {
switch (UO->getOpcode()) {
@@ -456,12 +445,12 @@ til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO,
case UO_Real:
case UO_Imag:
case UO_Extension:
+ case UO_Coawait:
return new (Arena) til::Undefined(UO);
}
return new (Arena) til::Undefined(UO);
}
-
til::SExpr *SExprBuilder::translateBinOp(til::TIL_BinaryOpcode Op,
const BinaryOperator *BO,
CallingContext *Ctx, bool Reverse) {
@@ -473,7 +462,6 @@ til::SExpr *SExprBuilder::translateBinOp(til::TIL_BinaryOpcode Op,
return new (Arena) til::BinaryOp(Op, E0, E1);
}
-
til::SExpr *SExprBuilder::translateBinAssign(til::TIL_BinaryOpcode Op,
const BinaryOperator *BO,
CallingContext *Ctx,
@@ -500,7 +488,6 @@ til::SExpr *SExprBuilder::translateBinAssign(til::TIL_BinaryOpcode Op,
return new (Arena) til::Store(E0, E1);
}
-
til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO,
CallingContext *Ctx) {
switch (BO->getOpcode()) {
@@ -546,7 +533,6 @@ til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO,
return new (Arena) til::Undefined(BO);
}
-
til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE,
CallingContext *Ctx) {
clang::CastKind K = CE->getCastKind();
@@ -580,7 +566,6 @@ til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE,
}
}
-
til::SExpr *
SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr *E,
CallingContext *Ctx) {
@@ -589,7 +574,6 @@ SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr *E,
return new (Arena) til::ArrayIndex(E0, E1);
}
-
til::SExpr *
SExprBuilder::translateAbstractConditionalOperator(
const AbstractConditionalOperator *CO, CallingContext *Ctx) {
@@ -599,7 +583,6 @@ SExprBuilder::translateAbstractConditionalOperator(
return new (Arena) til::IfThenElse(C, T, E);
}
-
til::SExpr *
SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) {
DeclGroupRef DGrp = S->getDeclGroup();
@@ -621,8 +604,6 @@ SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) {
return nullptr;
}
-
-
// If (E) is non-trivial, then add it to the current basic block, and
// update the statement map so that S refers to E. Returns a new variable
// that refers to E.
@@ -639,7 +620,6 @@ til::SExpr *SExprBuilder::addStatement(til::SExpr* E, const Stmt *S,
return E;
}
-
// Returns the current value of VD, if known, and nullptr otherwise.
til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) {
auto It = LVarIdxMap.find(VD);
@@ -650,7 +630,6 @@ til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) {
return nullptr;
}
-
// if E is a til::Variable, update its clangDecl.
static void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) {
if (!E)
@@ -670,7 +649,6 @@ til::SExpr *SExprBuilder::addVarDecl(const ValueDecl *VD, til::SExpr *E) {
return E;
}
-
// Updates a current variable declaration. (E.g. by assignment)
til::SExpr *SExprBuilder::updateVarDecl(const ValueDecl *VD, til::SExpr *E) {
maybeUpdateVD(E, VD);
@@ -685,7 +663,6 @@ til::SExpr *SExprBuilder::updateVarDecl(const ValueDecl *VD, til::SExpr *E) {
return E;
}
-
// Make a Phi node in the current block for the i^th variable in CurrentVarMap.
// If E != null, sets Phi[CurrentBlockInfo->ArgIndex] = E.
// If E == null, this is a backedge and will be set later.
@@ -728,7 +705,6 @@ void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) {
CurrentLVarMap.elem(i).second = Ph;
}
-
// Merge values from Map into the current variable map.
// This will construct Phi nodes in the current basic block as necessary.
void SExprBuilder::mergeEntryMap(LVarDefinitionMap Map) {
@@ -763,7 +739,6 @@ void SExprBuilder::mergeEntryMap(LVarDefinitionMap Map) {
}
}
-
// Merge a back edge into the current variable map.
// This will create phi nodes for all variables in the variable map.
void SExprBuilder::mergeEntryMapBackEdge() {
@@ -790,7 +765,6 @@ void SExprBuilder::mergeEntryMapBackEdge() {
}
}
-
// Update the phi nodes that were initially created for a back edge
// once the variable definitions have been computed.
// I.e., merge the current variable map into the phi nodes for Blk.
@@ -843,7 +817,6 @@ void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D,
}
}
-
void SExprBuilder::enterCFGBlock(const CFGBlock *B) {
// Intialize TIL basic block and add it to the CFG.
CurrentBB = lookupBlock(B);
@@ -857,7 +830,6 @@ void SExprBuilder::enterCFGBlock(const CFGBlock *B) {
// assert(!CurrentLVarMap.valid() && "CurrentLVarMap already initialized.");
}
-
void SExprBuilder::handlePredecessor(const CFGBlock *Pred) {
// Compute CurrentLVarMap on entry from ExitMaps of predecessors
@@ -873,12 +845,10 @@ void SExprBuilder::handlePredecessor(const CFGBlock *Pred) {
++CurrentBlockInfo->ProcessedPredecessors;
}
-
void SExprBuilder::handlePredecessorBackEdge(const CFGBlock *Pred) {
mergeEntryMapBackEdge();
}
-
void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) {
// The merge*() methods have created arguments.
// Push those arguments onto the basic block.
@@ -888,13 +858,11 @@ void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) {
CurrentBB->addArgument(A);
}
-
void SExprBuilder::handleStatement(const Stmt *S) {
til::SExpr *E = translate(S, nullptr);
addStatement(E, S);
}
-
void SExprBuilder::handleDestructorCall(const VarDecl *VD,
const CXXDestructorDecl *DD) {
til::SExpr *Sf = new (Arena) til::LiteralPtr(VD);
@@ -904,8 +872,6 @@ void SExprBuilder::handleDestructorCall(const VarDecl *VD,
addStatement(E, nullptr);
}
-
-
void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) {
CurrentBB->instructions().reserve(
static_cast<unsigned>(CurrentInstructions.size()), Arena);
@@ -933,18 +899,15 @@ void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) {
}
}
-
void SExprBuilder::handleSuccessor(const CFGBlock *Succ) {
++CurrentBlockInfo->UnprocessedSuccessors;
}
-
void SExprBuilder::handleSuccessorBackEdge(const CFGBlock *Succ) {
mergePhiNodesBackEdge(Succ);
++BBInfo[Succ->getBlockID()].ProcessedPredecessors;
}
-
void SExprBuilder::exitCFGBlock(const CFGBlock *B) {
CurrentArguments.clear();
CurrentInstructions.clear();
@@ -953,7 +916,6 @@ void SExprBuilder::exitCFGBlock(const CFGBlock *B) {
CurrentBlockInfo = nullptr;
}
-
void SExprBuilder::exitCFG(const CFGBlock *Last) {
for (auto *Ph : IncompleteArgs) {
if (Ph->status() == til::Phi::PH_Incomplete)
@@ -965,7 +927,6 @@ void SExprBuilder::exitCFG(const CFGBlock *Last) {
IncompleteArgs.clear();
}
-
/*
void printSCFG(CFGWalker &Walker) {
llvm::BumpPtrAllocator Bpa;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp b/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp
index da9ac79..c215366 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Attributes.cpp
@@ -4,8 +4,8 @@
using namespace clang;
int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
- const IdentifierInfo *Attr, const llvm::Triple &T,
- const LangOptions &LangOpts) {
+ const IdentifierInfo *Attr, const TargetInfo &Target,
+ const LangOptions &LangOpts) {
StringRef Name = Attr->getName();
// Normalize the attribute name, __foo__ becomes foo.
if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
diff --git a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
index 8efcac6..fb6a645 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Builtins.cpp
@@ -15,86 +15,88 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
using namespace clang;
static const Builtin::Info BuiltinInfo[] = {
- { "not a builtin function", nullptr, nullptr, nullptr, ALL_LANGUAGES},
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) { #ID, TYPE, ATTRS, 0, BUILTIN_LANG },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) { #ID, TYPE, ATTRS, HEADER,\
- BUILTIN_LANG },
+ { "not a builtin function", nullptr, nullptr, nullptr, ALL_LANGUAGES,nullptr},
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define LANGBUILTIN(ID, TYPE, ATTRS, LANGS) \
+ { #ID, TYPE, ATTRS, nullptr, LANGS, nullptr },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, LANGS) \
+ { #ID, TYPE, ATTRS, HEADER, LANGS, nullptr },
#include "clang/Basic/Builtins.def"
};
-const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const {
+const Builtin::Info &Builtin::Context::getRecord(unsigned ID) const {
if (ID < Builtin::FirstTSBuiltin)
return BuiltinInfo[ID];
- assert(ID - Builtin::FirstTSBuiltin < NumTSRecords && "Invalid builtin ID!");
+ assert(((ID - Builtin::FirstTSBuiltin) <
+ (TSRecords.size() + AuxTSRecords.size())) &&
+ "Invalid builtin ID!");
+ if (isAuxBuiltinID(ID))
+ return AuxTSRecords[getAuxBuiltinID(ID) - Builtin::FirstTSBuiltin];
return TSRecords[ID - Builtin::FirstTSBuiltin];
}
-Builtin::Context::Context() {
- // Get the target specific builtins from the target.
- TSRecords = nullptr;
- NumTSRecords = 0;
+void Builtin::Context::InitializeTarget(const TargetInfo &Target,
+ const TargetInfo *AuxTarget) {
+ assert(TSRecords.empty() && "Already initialized target?");
+ TSRecords = Target.getTargetBuiltins();
+ if (AuxTarget)
+ AuxTSRecords = AuxTarget->getTargetBuiltins();
}
-void Builtin::Context::InitializeTarget(const TargetInfo &Target) {
- assert(NumTSRecords == 0 && "Already initialized target?");
- Target.getTargetBuiltins(TSRecords, NumTSRecords);
+bool Builtin::Context::isBuiltinFunc(const char *Name) {
+ StringRef FuncName(Name);
+ for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin; ++i)
+ if (FuncName.equals(BuiltinInfo[i].Name))
+ return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr;
+
+ return false;
}
-bool Builtin::Context::BuiltinIsSupported(const Builtin::Info &BuiltinInfo,
+bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo,
const LangOptions &LangOpts) {
- bool BuiltinsUnsupported = LangOpts.NoBuiltin &&
- strchr(BuiltinInfo.Attributes, 'f');
+ bool BuiltinsUnsupported =
+ (LangOpts.NoBuiltin || LangOpts.isNoBuiltinFunc(BuiltinInfo.Name)) &&
+ strchr(BuiltinInfo.Attributes, 'f');
bool MathBuiltinsUnsupported =
- LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName &&
+ LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName &&
llvm::StringRef(BuiltinInfo.HeaderName).equals("math.h");
- bool GnuModeUnsupported = !LangOpts.GNUMode &&
- (BuiltinInfo.builtin_lang & GNU_LANG);
- bool MSModeUnsupported = !LangOpts.MicrosoftExt &&
- (BuiltinInfo.builtin_lang & MS_LANG);
- bool ObjCUnsupported = !LangOpts.ObjC1 &&
- BuiltinInfo.builtin_lang == OBJC_LANG;
+ bool GnuModeUnsupported = !LangOpts.GNUMode && (BuiltinInfo.Langs & GNU_LANG);
+ bool MSModeUnsupported =
+ !LangOpts.MicrosoftExt && (BuiltinInfo.Langs & MS_LANG);
+ bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.Langs == OBJC_LANG;
return !BuiltinsUnsupported && !MathBuiltinsUnsupported &&
!GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported;
}
-/// InitializeBuiltins - Mark the identifiers for all the builtins with their
+/// initializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
-void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
+void Builtin::Context::initializeBuiltins(IdentifierTable &Table,
const LangOptions& LangOpts) {
// Step #1: mark all target-independent builtins with their ID's.
for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
- if (BuiltinIsSupported(BuiltinInfo[i], LangOpts)) {
+ if (builtinIsSupported(BuiltinInfo[i], LangOpts)) {
Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
}
// Step #2: Register target-specific builtins.
- for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
- if (BuiltinIsSupported(TSRecords[i], LangOpts))
- Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
-}
-
-void
-Builtin::Context::GetBuiltinNames(SmallVectorImpl<const char *> &Names) {
- // Final all target-independent names
- for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
- if (!strchr(BuiltinInfo[i].Attributes, 'f'))
- Names.push_back(BuiltinInfo[i].Name);
-
- // Find target-specific names.
- for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
- if (!strchr(TSRecords[i].Attributes, 'f'))
- Names.push_back(TSRecords[i].Name);
+ for (unsigned i = 0, e = TSRecords.size(); i != e; ++i)
+ if (builtinIsSupported(TSRecords[i], LangOpts))
+ Table.get(TSRecords[i].Name).setBuiltinID(i + Builtin::FirstTSBuiltin);
+
+ // Step #3: Register target-specific builtins for AuxTarget.
+ for (unsigned i = 0, e = AuxTSRecords.size(); i != e; ++i)
+ Table.get(AuxTSRecords[i].Name)
+ .setBuiltinID(i + Builtin::FirstTSBuiltin + TSRecords.size());
}
-void Builtin::Context::ForgetBuiltin(unsigned ID, IdentifierTable &Table) {
- Table.get(GetRecord(ID).Name).setBuiltinID(0);
+void Builtin::Context::forgetBuiltin(unsigned ID, IdentifierTable &Table) {
+ Table.get(getRecord(ID).Name).setBuiltinID(0);
}
bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
@@ -105,7 +107,7 @@ bool Builtin::Context::isLike(unsigned ID, unsigned &FormatIdx,
assert(::toupper(Fmt[0]) == Fmt[1] &&
"Format string is not in the form \"xX\"");
- const char *Like = ::strpbrk(GetRecord(ID).Attributes, Fmt);
+ const char *Like = ::strpbrk(getRecord(ID).Attributes, Fmt);
if (!Like)
return false;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
index f89caf7..7cf7305 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Diagnostic.cpp
@@ -226,12 +226,12 @@ void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
// Update all diagnostic states that are active after the given location.
for (DiagStatePointsTy::iterator
I = Pos+1, E = DiagStatePoints.end(); I != E; ++I) {
- GetCurDiagState()->setMapping(Diag, Mapping);
+ I->State->setMapping(Diag, Mapping);
}
// If the location corresponds to an existing point, just update its state.
if (Pos->Loc == Loc) {
- GetCurDiagState()->setMapping(Diag, Mapping);
+ Pos->State->setMapping(Diag, Mapping);
return;
}
@@ -240,7 +240,7 @@ void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
assert(Pos->Loc.isBeforeInTranslationUnitThan(Loc));
DiagStates.push_back(*Pos->State);
DiagState *NewState = &DiagStates.back();
- GetCurDiagState()->setMapping(Diag, Mapping);
+ NewState->setMapping(Diag, Mapping);
DiagStatePoints.insert(Pos+1, DiagStatePoint(NewState,
FullSourceLoc(Loc, *SourceMgr)));
}
@@ -278,8 +278,8 @@ bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group,
return true;
// Perform the mapping change.
- for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) {
- DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(GroupDiags[i]);
+ for (diag::kind Diag : GroupDiags) {
+ DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
if (Info.getSeverity() == diag::Severity::Error ||
Info.getSeverity() == diag::Severity::Fatal)
@@ -309,8 +309,8 @@ bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group,
return true;
// Perform the mapping change.
- for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) {
- DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(GroupDiags[i]);
+ for (diag::kind Diag : GroupDiags) {
+ DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
if (Info.getSeverity() == diag::Severity::Fatal)
Info.setSeverity(diag::Severity::Error);
@@ -329,9 +329,9 @@ void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor,
Diags->getAllDiagnostics(Flavor, AllDiags);
// Set the mapping.
- for (unsigned i = 0, e = AllDiags.size(); i != e; ++i)
- if (Diags->isBuiltinWarningOrExtension(AllDiags[i]))
- setSeverity(AllDiags[i], Map, Loc);
+ for (diag::kind Diag : AllDiags)
+ if (Diags->isBuiltinWarningOrExtension(Diag))
+ setSeverity(Diag, Map, Loc);
}
void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
@@ -945,8 +945,6 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
OutStr.append(Tree.begin(), Tree.end());
}
-StoredDiagnostic::StoredDiagnostic() { }
-
StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
StringRef Message)
: ID(ID), Level(Level), Loc(), Message(Message) { }
@@ -975,8 +973,6 @@ StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
{
}
-StoredDiagnostic::~StoredDiagnostic() { }
-
/// IncludeInDiagnosticCounts - This method (whose default implementation
/// returns true) indicates whether the diagnostics handled by this
/// DiagnosticConsumer should be included in the number of diagnostics
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
index 643503b..a34c7fec 100644
--- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
@@ -100,14 +100,10 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
#ifndef NDEBUG
static bool IsFirst = true; // So the check is only performed on first call.
if (IsFirst) {
- for (unsigned i = 1; i != StaticDiagInfoSize; ++i) {
- assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
- "Diag ID conflict, the enums at the start of clang::diag (in "
- "DiagnosticIDs.h) probably need to be increased");
-
- assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
- "Improperly sorted diag info");
- }
+ assert(std::is_sorted(std::begin(StaticDiagInfo),
+ std::end(StaticDiagInfo)) &&
+ "Diag ID conflict, the enums at the start of clang::diag (in "
+ "DiagnosticIDs.h) probably need to be increased");
IsFirst = false;
}
#endif
@@ -505,11 +501,6 @@ static const WarningOption OptionTable[] = {
#include "clang/Basic/DiagnosticGroups.inc"
#undef GET_DIAG_TABLE
};
-static const size_t OptionTableSize = llvm::array_lengthof(OptionTable);
-
-static bool WarningOptionCompare(const WarningOption &LHS, StringRef RHS) {
- return LHS.getName() < RHS;
-}
/// getWarningOptionForDiag - Return the lowest-level warning option that
/// enables the specified diagnostic. If there is no -Wfoo flag that controls
@@ -553,10 +544,12 @@ static bool getDiagnosticsInGroup(diag::Flavor Flavor,
bool
DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
SmallVectorImpl<diag::kind> &Diags) const {
- const WarningOption *Found = std::lower_bound(
- OptionTable, OptionTable + OptionTableSize, Group, WarningOptionCompare);
- if (Found == OptionTable + OptionTableSize ||
- Found->getName() != Group)
+ auto Found = std::lower_bound(std::begin(OptionTable), std::end(OptionTable),
+ Group,
+ [](const WarningOption &LHS, StringRef RHS) {
+ return LHS.getName() < RHS;
+ });
+ if (Found == std::end(OptionTable) || Found->getName() != Group)
return true; // Option not found.
return ::getDiagnosticsInGroup(Flavor, Found, Diags);
@@ -573,19 +566,18 @@ StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
StringRef Group) {
StringRef Best;
unsigned BestDistance = Group.size() + 1; // Sanity threshold.
- for (const WarningOption *i = OptionTable, *e = OptionTable + OptionTableSize;
- i != e; ++i) {
+ for (const WarningOption &O : OptionTable) {
// Don't suggest ignored warning flags.
- if (!i->Members && !i->SubGroups)
+ if (!O.Members && !O.SubGroups)
continue;
- unsigned Distance = i->getName().edit_distance(Group, true, BestDistance);
+ unsigned Distance = O.getName().edit_distance(Group, true, BestDistance);
if (Distance > BestDistance)
continue;
// Don't suggest groups that are not of this kind.
llvm::SmallVector<diag::kind, 8> Diags;
- if (::getDiagnosticsInGroup(Flavor, i, Diags) || Diags.empty())
+ if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty())
continue;
if (Distance == BestDistance) {
@@ -593,7 +585,7 @@ StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
Best = "";
} else if (Distance < BestDistance) {
// This is a better match.
- Best = i->getName();
+ Best = O.getName();
BestDistance = Distance;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
index d492744..cb3f75c 100644
--- a/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/FileManager.cpp
@@ -22,6 +22,7 @@
#include "clang/Frontend/PCHContainerOperations.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/llvm-config.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -58,12 +59,7 @@ FileManager::FileManager(const FileSystemOptions &FSO,
this->FS = vfs::getRealFileSystem();
}
-FileManager::~FileManager() {
- for (unsigned i = 0, e = VirtualFileEntries.size(); i != e; ++i)
- delete VirtualFileEntries[i];
- for (unsigned i = 0, e = VirtualDirectoryEntries.size(); i != e; ++i)
- delete VirtualDirectoryEntries[i];
-}
+FileManager::~FileManager() = default;
void FileManager::addStatCache(std::unique_ptr<FileSystemStatCache> statCache,
bool AtBeginning) {
@@ -137,14 +133,14 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
// at the same time. Therefore, if DirName is already in the cache,
// we don't need to recurse as its ancestors must also already be in
// the cache.
- if (NamedDirEnt.second)
+ if (NamedDirEnt.second && NamedDirEnt.second != NON_EXISTENT_DIR)
return;
// Add the virtual directory to the cache.
- DirectoryEntry *UDE = new DirectoryEntry;
+ auto UDE = llvm::make_unique<DirectoryEntry>();
UDE->Name = NamedDirEnt.first().data();
- NamedDirEnt.second = UDE;
- VirtualDirectoryEntries.push_back(UDE);
+ NamedDirEnt.second = UDE.get();
+ VirtualDirectoryEntries.push_back(std::move(UDE));
// Recursively add the other ancestors.
addAncestorsAsVirtualDirs(DirName);
@@ -375,8 +371,8 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
}
if (!UFE) {
- UFE = new FileEntry();
- VirtualFileEntries.push_back(UFE);
+ VirtualFileEntries.push_back(llvm::make_unique<FileEntry>());
+ UFE = VirtualFileEntries.back().get();
NamedFileEnt.second = UFE;
}
@@ -389,16 +385,28 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
return UFE;
}
-void FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const {
+bool FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const {
StringRef pathRef(path.data(), path.size());
if (FileSystemOpts.WorkingDir.empty()
|| llvm::sys::path::is_absolute(pathRef))
- return;
+ return false;
SmallString<128> NewPath(FileSystemOpts.WorkingDir);
llvm::sys::path::append(NewPath, pathRef);
path = NewPath;
+ return true;
+}
+
+bool FileManager::makeAbsolutePath(SmallVectorImpl<char> &Path) const {
+ bool Changed = FixupRelativePath(Path);
+
+ if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
+ llvm::sys::fs::make_absolute(Path);
+ Changed = true;
+ }
+
+ return Changed;
}
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
@@ -501,11 +509,9 @@ void FileManager::GetUniqueIDMapping(
UIDToFiles[FE->getValue()->getUID()] = FE->getValue();
// Map virtual file entries
- for (SmallVectorImpl<FileEntry *>::const_iterator
- VFE = VirtualFileEntries.begin(), VFEEnd = VirtualFileEntries.end();
- VFE != VFEEnd; ++VFE)
- if (*VFE && *VFE != NON_EXISTENT_FILE)
- UIDToFiles[(*VFE)->getUID()] = *VFE;
+ for (const auto &VFE : VirtualFileEntries)
+ if (VFE && VFE.get() != NON_EXISTENT_FILE)
+ UIDToFiles[VFE->getUID()] = VFE.get();
}
void FileManager::modifyFileEntry(FileEntry *File,
@@ -514,37 +520,6 @@ void FileManager::modifyFileEntry(FileEntry *File,
File->ModTime = ModificationTime;
}
-/// Remove '.' path components from the given absolute path.
-/// \return \c true if any changes were made.
-// FIXME: Move this to llvm::sys::path.
-bool FileManager::removeDotPaths(SmallVectorImpl<char> &Path) {
- using namespace llvm::sys;
-
- SmallVector<StringRef, 16> ComponentStack;
- StringRef P(Path.data(), Path.size());
-
- // Skip the root path, then look for traversal in the components.
- StringRef Rel = path::relative_path(P);
- bool AnyDots = false;
- for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) {
- if (C == ".") {
- AnyDots = true;
- continue;
- }
- ComponentStack.push_back(C);
- }
-
- if (!AnyDots)
- return false;
-
- SmallString<256> Buffer = path::root_path(P);
- for (StringRef C : ComponentStack)
- path::append(Buffer, C);
-
- Path.swap(Buffer);
- return true;
-}
-
StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
// FIXME: use llvm::sys::fs::canonical() when it gets implemented
llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known
@@ -556,17 +531,20 @@ StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
#ifdef LLVM_ON_UNIX
char CanonicalNameBuf[PATH_MAX];
- if (realpath(Dir->getName(), CanonicalNameBuf)) {
- unsigned Len = strlen(CanonicalNameBuf);
- char *Mem = static_cast<char *>(CanonicalNameStorage.Allocate(Len, 1));
- memcpy(Mem, CanonicalNameBuf, Len);
- CanonicalName = StringRef(Mem, Len);
- }
+ if (realpath(Dir->getName(), CanonicalNameBuf))
+ CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
#else
SmallString<256> CanonicalNameBuf(CanonicalName);
llvm::sys::fs::make_absolute(CanonicalNameBuf);
llvm::sys::path::native(CanonicalNameBuf);
- removeDotPaths(CanonicalNameBuf);
+ // We've run into needing to remove '..' here in the wild though, so
+ // remove it.
+ // On Windows, symlinks are significantly less prevalent, so removing
+ // '..' is pretty safe.
+ // Ideally we'd have an equivalent of `realpath` and could implement
+ // sys::fs::canonical across all the platforms.
+ llvm::sys::path::remove_dots(CanonicalNameBuf, /* remove_dot_dot */ true);
+ CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
#endif
CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName));
diff --git a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
index 7705834..67de1cb 100644
--- a/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/IdentifierTable.cpp
@@ -111,7 +111,8 @@ namespace {
KEYCONCEPTS = 0x10000,
KEYOBJC2 = 0x20000,
KEYZVECTOR = 0x40000,
- KEYALL = (0x7ffff & ~KEYNOMS18 &
+ KEYCOROUTINES = 0x80000,
+ KEYALL = (0xfffff & ~KEYNOMS18 &
~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
};
@@ -147,6 +148,7 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled;
if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
if (LangOpts.ObjC2 && (Flags & KEYOBJC2)) return KS_Enabled;
+ if (LangOpts.Coroutines && (Flags & KEYCOROUTINES)) return KS_Enabled;
if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) return KS_Future;
return KS_Disabled;
}
@@ -220,10 +222,7 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
LangOpts, *this);
- // FIXME: __declspec 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 this code.
- if (LangOpts.CUDA)
+ if (LangOpts.DeclSpecKeyword)
AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp
index 2c87845..1b08b06 100644
--- a/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/StringRef.h"
using namespace clang;
@@ -36,3 +37,10 @@ void LangOptions::resetNonModularOptions() {
ImplementationOfModule.clear();
}
+bool LangOptions::isNoBuiltinFunc(const char *Name) const {
+ StringRef FuncName(Name);
+ for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i)
+ if (FuncName.equals(NoBuiltinFuncs[i]))
+ return true;
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Module.cpp b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
index 4314b41..0b78326 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Module.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
@@ -28,11 +28,12 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
bool IsFramework, bool IsExplicit, unsigned VisibilityID)
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), Directory(),
Umbrella(), Signature(0), ASTFile(nullptr), VisibilityID(VisibilityID),
- IsMissingRequirement(false), IsAvailable(true), IsFromModuleFile(false),
- IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false),
- IsExternC(false), IsInferred(false), InferSubmodules(false),
- InferExplicitSubmodules(false), InferExportWildcard(false),
- ConfigMacrosExhaustive(false), NameVisibility(Hidden) {
+ IsMissingRequirement(false), HasIncompatibleModuleFile(false),
+ IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
+ IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
+ IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
+ InferExportWildcard(false), ConfigMacrosExhaustive(false),
+ NameVisibility(Hidden) {
if (Parent) {
if (!Parent->isAvailable())
IsAvailable = false;
@@ -139,6 +140,15 @@ std::string Module::getFullModuleName() const {
return Result;
}
+bool Module::fullModuleNameIs(ArrayRef<StringRef> nameParts) const {
+ for (const Module *M = this; M; M = M->Parent) {
+ if (nameParts.empty() || M->Name != nameParts.back())
+ return false;
+ nameParts = nameParts.drop_back();
+ }
+ return nameParts.empty();
+}
+
Module::DirectoryName Module::getUmbrellaDir() const {
if (Header U = getUmbrellaHeader())
return {"", U.Entry->getDir()};
diff --git a/contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp b/contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp
index be50fc4..133c669 100644
--- a/contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/ObjCRuntime.cpp
@@ -30,6 +30,7 @@ raw_ostream &clang::operator<<(raw_ostream &out, const ObjCRuntime &value) {
case ObjCRuntime::MacOSX: out << "macosx"; break;
case ObjCRuntime::FragileMacOSX: out << "macosx-fragile"; break;
case ObjCRuntime::iOS: out << "ios"; break;
+ case ObjCRuntime::WatchOS: out << "watchos"; break;
case ObjCRuntime::GNUstep: out << "gnustep"; break;
case ObjCRuntime::GCC: out << "gcc"; break;
case ObjCRuntime::ObjFW: out << "objfw"; break;
@@ -62,6 +63,8 @@ bool ObjCRuntime::tryParse(StringRef input) {
kind = ObjCRuntime::FragileMacOSX;
} else if (runtimeName == "ios") {
kind = ObjCRuntime::iOS;
+ } else if (runtimeName == "watchos") {
+ kind = ObjCRuntime::WatchOS;
} else if (runtimeName == "gnustep") {
// If no version is specified then default to the most recent one that we
// know about.
diff --git a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
index b7407f6..577132d 100644
--- a/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/OpenMPKinds.cpp
@@ -87,8 +87,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_PROC_BIND_unknown);
case OMPC_schedule:
- return llvm::StringSwitch<OpenMPScheduleClauseKind>(Str)
-#define OPENMP_SCHEDULE_KIND(Name) .Case(#Name, OMPC_SCHEDULE_##Name)
+ return llvm::StringSwitch<unsigned>(Str)
+#define OPENMP_SCHEDULE_KIND(Name) \
+ .Case(#Name, static_cast<unsigned>(OMPC_SCHEDULE_##Name))
+#define OPENMP_SCHEDULE_MODIFIER(Name) \
+ .Case(#Name, static_cast<unsigned>(OMPC_SCHEDULE_MODIFIER_##Name))
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_SCHEDULE_unknown);
case OMPC_depend:
@@ -96,19 +99,29 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
#define OPENMP_DEPEND_KIND(Name) .Case(#Name, OMPC_DEPEND_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_DEPEND_unknown);
+ case OMPC_linear:
+ return llvm::StringSwitch<OpenMPLinearClauseKind>(Str)
+#define OPENMP_LINEAR_KIND(Name) .Case(#Name, OMPC_LINEAR_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_LINEAR_unknown);
+ case OMPC_map:
+ return llvm::StringSwitch<OpenMPMapClauseKind>(Str)
+#define OPENMP_MAP_KIND(Name) .Case(#Name, OMPC_MAP_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_MAP_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
case OMPC_private:
case OMPC_firstprivate:
case OMPC_lastprivate:
case OMPC_shared:
case OMPC_reduction:
- case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
@@ -122,6 +135,16 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -153,12 +176,17 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_schedule:
switch (Type) {
case OMPC_SCHEDULE_unknown:
+ case OMPC_SCHEDULE_MODIFIER_last:
return "unknown";
#define OPENMP_SCHEDULE_KIND(Name) \
- case OMPC_SCHEDULE_##Name: \
- return #Name;
+ case OMPC_SCHEDULE_##Name: \
+ return #Name;
+#define OPENMP_SCHEDULE_MODIFIER(Name) \
+ case OMPC_SCHEDULE_MODIFIER_##Name: \
+ return #Name;
#include "clang/Basic/OpenMPKinds.def"
}
+ llvm_unreachable("Invalid OpenMP 'schedule' clause type");
case OMPC_depend:
switch (Type) {
case OMPC_DEPEND_unknown:
@@ -168,20 +196,42 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
return #Name;
#include "clang/Basic/OpenMPKinds.def"
}
- llvm_unreachable("Invalid OpenMP 'schedule' clause type");
+ llvm_unreachable("Invalid OpenMP 'depend' clause type");
+ case OMPC_linear:
+ switch (Type) {
+ case OMPC_LINEAR_unknown:
+ return "unknown";
+#define OPENMP_LINEAR_KIND(Name) \
+ case OMPC_LINEAR_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'linear' clause type");
+ case OMPC_map:
+ switch (Type) {
+ case OMPC_MAP_unknown:
+ return "unknown";
+#define OPENMP_MAP_KIND(Name) \
+ case OMPC_MAP_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ llvm_unreachable("Invalid OpenMP 'map' clause type");
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
case OMPC_private:
case OMPC_firstprivate:
case OMPC_lastprivate:
case OMPC_shared:
case OMPC_reduction:
- case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
@@ -195,6 +245,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -328,6 +388,16 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
+ case OMPD_target_data:
+ switch (CKind) {
+#define OPENMP_TARGET_DATA_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
case OMPD_teams:
switch (CKind) {
#define OPENMP_TEAMS_CLAUSE(Name) \
@@ -338,18 +408,75 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
+ case OMPD_cancel:
+ switch (CKind) {
+#define OPENMP_CANCEL_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_ordered:
+ switch (CKind) {
+#define OPENMP_ORDERED_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_taskloop:
+ switch (CKind) {
+#define OPENMP_TASKLOOP_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_taskloop_simd:
+ switch (CKind) {
+#define OPENMP_TASKLOOP_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_critical:
+ switch (CKind) {
+#define OPENMP_CRITICAL_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_distribute:
+ switch (CKind) {
+#define OPENMP_DISTRIBUTE_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
case OMPD_unknown:
case OMPD_threadprivate:
case OMPD_section:
case OMPD_master:
- case OMPD_critical:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
case OMPD_taskgroup:
case OMPD_cancellation_point:
- case OMPD_cancel:
- case OMPD_ordered:
break;
}
return false;
@@ -357,8 +484,10 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_simd || DKind == OMPD_for || DKind == OMPD_for_simd ||
- DKind == OMPD_parallel_for ||
- DKind == OMPD_parallel_for_simd; // TODO add next directives.
+ DKind == OMPD_parallel_for || DKind == OMPD_parallel_for_simd ||
+ DKind == OMPD_taskloop ||
+ DKind == OMPD_taskloop_simd ||
+ DKind == OMPD_distribute; // TODO add next directives.
}
bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
@@ -369,19 +498,32 @@ bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
DKind == OMPD_parallel_sections; // TODO add next directives.
}
+bool clang::isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd;
+}
+
bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_parallel || DKind == OMPD_parallel_for ||
DKind == OMPD_parallel_for_simd ||
DKind == OMPD_parallel_sections; // TODO add next directives.
}
+bool clang::isOpenMPTargetDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_target; // TODO add next directives.
+}
+
bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_teams; // TODO add next directives.
}
bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_simd || DKind == OMPD_for_simd ||
- DKind == OMPD_parallel_for_simd; // TODO add next directives.
+ DKind == OMPD_parallel_for_simd ||
+ DKind == OMPD_taskloop_simd; // TODO add next directives.
+}
+
+bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) {
+ return Kind == OMPD_distribute; // TODO add next directives.
}
bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
diff --git a/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp b/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp
index 095fcd6..de78c94 100644
--- a/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/SanitizerBlacklist.cpp
@@ -40,7 +40,7 @@ bool SanitizerBlacklist::isBlacklistedFile(StringRef FileName,
bool SanitizerBlacklist::isBlacklistedLocation(SourceLocation Loc,
StringRef Category) const {
- return !Loc.isInvalid() &&
+ return Loc.isValid() &&
isBlacklistedFile(SM.getFilename(SM.getFileLoc(Loc)), Category);
}
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
index c0b0453..4c50161 100644
--- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
@@ -279,9 +279,7 @@ void LineTableInfo::AddEntry(FileID FID,
/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
///
unsigned SourceManager::getLineTableFilenameID(StringRef Name) {
- if (!LineTable)
- LineTable = new LineTableInfo();
- return LineTable->getLineTableFilenameID(Name);
+ return getLineTable().getLineTableFilenameID(Name);
}
@@ -302,9 +300,7 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
// Remember that this file has #line directives now if it doesn't already.
const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
- if (!LineTable)
- LineTable = new LineTableInfo();
- LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID);
+ getLineTable().AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID);
}
/// AddLineNote - Add a GNU line marker to the line table.
@@ -332,8 +328,7 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
// Remember that this file has #line directives now if it doesn't already.
const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
- if (!LineTable)
- LineTable = new LineTableInfo();
+ (void) getLineTable();
SrcMgr::CharacteristicKind FileKind;
if (IsExternCHeader)
@@ -366,7 +361,7 @@ LineTableInfo &SourceManager::getLineTable() {
SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr,
bool UserFilesAreVolatile)
: Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true),
- UserFilesAreVolatile(UserFilesAreVolatile),
+ UserFilesAreVolatile(UserFilesAreVolatile), FilesAreTransient(false),
ExternalSLocEntries(nullptr), LineTable(nullptr), NumLinearScans(0),
NumBinaryProbes(0) {
clearIDTables();
@@ -444,6 +439,7 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt,
}
Entry->IsSystemFile = isSystemFile;
+ Entry->IsTransient = FilesAreTransient;
return Entry;
}
@@ -484,10 +480,12 @@ std::pair<int, unsigned>
SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
unsigned TotalSize) {
assert(ExternalSLocEntries && "Don't have an external sloc source");
+ // Make sure we're not about to run out of source locations.
+ if (CurrentLoadedOffset - TotalSize < NextLocalOffset)
+ return std::make_pair(0, 0);
LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
CurrentLoadedOffset -= TotalSize;
- assert(CurrentLoadedOffset >= NextLocalOffset && "Out of source locations");
int ID = LoadedSLocEntryTable.size();
return std::make_pair(-ID - 1, CurrentLoadedOffset);
}
@@ -676,6 +674,11 @@ void SourceManager::disableFileContentsOverride(const FileEntry *File) {
OverriddenFilesInfo->OverriddenFilesWithBuffer.erase(File);
}
+void SourceManager::setFileIsTransient(const FileEntry *File) {
+ const SrcMgr::ContentCache *CC = getOrCreateContentCache(File);
+ const_cast<SrcMgr::ContentCache *>(CC)->IsTransient = true;
+}
+
StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
bool MyInvalid = false;
const SLocEntry &SLoc = getSLocEntry(FID, &MyInvalid);
@@ -995,12 +998,17 @@ SourceManager::getExpansionRange(SourceLocation Loc) const {
return Res;
}
-bool SourceManager::isMacroArgExpansion(SourceLocation Loc) const {
+bool SourceManager::isMacroArgExpansion(SourceLocation Loc,
+ SourceLocation *StartLoc) const {
if (!Loc.isMacroID()) return false;
FileID FID = getFileID(Loc);
const SrcMgr::ExpansionInfo &Expansion = getSLocEntry(FID).getExpansion();
- return Expansion.isMacroArgExpansion();
+ if (!Expansion.isMacroArgExpansion()) return false;
+
+ if (StartLoc)
+ *StartLoc = Expansion.getExpansionLocStart();
+ return true;
}
bool SourceManager::isMacroBodyExpansion(SourceLocation Loc) const {
@@ -1394,7 +1402,7 @@ unsigned SourceManager::getPresumedLineNumber(SourceLocation Loc,
/// considered to be from a system header.
SrcMgr::CharacteristicKind
SourceManager::getFileCharacteristic(SourceLocation Loc) const {
- assert(!Loc.isInvalid() && "Can't get file characteristic of invalid loc!");
+ assert(Loc.isValid() && "Can't get file characteristic of invalid loc!");
std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
bool Invalid = false;
const SLocEntry &SEntry = getSLocEntry(LocInfo.first, &Invalid);
@@ -1599,7 +1607,7 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
// location in the main file.
Optional<llvm::sys::fs::UniqueID> SourceFileUID;
Optional<StringRef> SourceFileName;
- if (!MainFileID.isInvalid()) {
+ if (MainFileID.isValid()) {
bool Invalid = false;
const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid);
if (Invalid)
@@ -1709,7 +1717,7 @@ SourceLocation SourceManager::translateLineCol(FileID FID,
unsigned Col) const {
// Lines are used as a one-based index into a zero-based array. This assert
// checks for possible buffer underruns.
- assert(Line != 0 && "Passed a zero-based line");
+ assert(Line && Col && "Line and column should start from 1!");
if (FID.isInvalid())
return SourceLocation();
@@ -1772,7 +1780,7 @@ SourceLocation SourceManager::translateLineCol(FileID FID,
/// 110 -> SourceLocation()
void SourceManager::computeMacroArgsCache(MacroArgsMap *&CachePtr,
FileID FID) const {
- assert(!FID.isInvalid());
+ assert(FID.isValid());
assert(!CachePtr);
CachePtr = new MacroArgsMap();
@@ -2133,6 +2141,63 @@ void SourceManager::PrintStats() const {
<< NumBinaryProbes << " binary.\n";
}
+LLVM_DUMP_METHOD void SourceManager::dump() const {
+ llvm::raw_ostream &out = llvm::errs();
+
+ auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry,
+ llvm::Optional<unsigned> NextStart) {
+ out << "SLocEntry <FileID " << ID << "> " << (Entry.isFile() ? "file" : "expansion")
+ << " <SourceLocation " << Entry.getOffset() << ":";
+ if (NextStart)
+ out << *NextStart << ">\n";
+ else
+ out << "???\?>\n";
+ if (Entry.isFile()) {
+ auto &FI = Entry.getFile();
+ if (FI.NumCreatedFIDs)
+ out << " covers <FileID " << ID << ":" << int(ID + FI.NumCreatedFIDs)
+ << ">\n";
+ if (FI.getIncludeLoc().isValid())
+ out << " included from " << FI.getIncludeLoc().getOffset() << "\n";
+ if (auto *CC = FI.getContentCache()) {
+ out << " for " << (CC->OrigEntry ? CC->OrigEntry->getName() : "<none>")
+ << "\n";
+ if (CC->BufferOverridden)
+ out << " contents overridden\n";
+ if (CC->ContentsEntry != CC->OrigEntry) {
+ out << " contents from "
+ << (CC->ContentsEntry ? CC->ContentsEntry->getName() : "<none>")
+ << "\n";
+ }
+ }
+ } else {
+ auto &EI = Entry.getExpansion();
+ out << " spelling from " << EI.getSpellingLoc().getOffset() << "\n";
+ out << " macro " << (EI.isMacroArgExpansion() ? "arg" : "body")
+ << " range <" << EI.getExpansionLocStart().getOffset() << ":"
+ << EI.getExpansionLocEnd().getOffset() << ">\n";
+ }
+ };
+
+ // Dump local SLocEntries.
+ for (unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
+ DumpSLocEntry(ID, LocalSLocEntryTable[ID],
+ ID == NumIDs - 1 ? NextLocalOffset
+ : LocalSLocEntryTable[ID + 1].getOffset());
+ }
+ // Dump loaded SLocEntries.
+ llvm::Optional<unsigned> NextStart;
+ for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
+ int ID = -(int)Index - 2;
+ if (SLocEntryLoaded[Index]) {
+ DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
+ NextStart = LoadedSLocEntryTable[Index].getOffset();
+ } else {
+ NextStart = None;
+ }
+ }
+}
+
ExternalSLocEntrySource::~ExternalSLocEntrySource() { }
/// Return the amount of memory used by memory buffers, breaking down
diff --git a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
index dbd2f9a..1648a27 100644
--- a/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/TargetInfo.cpp
@@ -71,12 +71,13 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
FloatFormat = &llvm::APFloat::IEEEsingle;
DoubleFormat = &llvm::APFloat::IEEEdouble;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
- DescriptionString = nullptr;
+ DataLayoutString = nullptr;
UserLabelPrefix = "_";
MCountName = "mcount";
RegParmMax = 0;
SSERegParmMax = 0;
HasAlignMac68kSupport = false;
+ HasBuiltinMSVaList = false;
// Default to no types using fpret.
RealTypeUsesObjCFPRet = 0;
@@ -286,9 +287,9 @@ void TargetInfo::adjust(const LangOptions &Opts) {
LongLongWidth = LongLongAlign = 128;
HalfWidth = HalfAlign = 16;
FloatWidth = FloatAlign = 32;
-
- // Embedded 32-bit targets (OpenCL EP) might have double C type
- // defined as float. Let's not override this as it might lead
+
+ // Embedded 32-bit targets (OpenCL EP) might have double C type
+ // defined as float. Let's not override this as it might lead
// to generating illegal code that uses 64bit doubles.
if (DoubleWidth != FloatWidth) {
DoubleWidth = DoubleAlign = 64;
@@ -311,6 +312,18 @@ void TargetInfo::adjust(const LangOptions &Opts) {
}
}
+bool TargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeatureVec) const {
+ for (const auto &F : FeatureVec) {
+ StringRef Name = F;
+ // Apply the feature via the target.
+ bool Enabled = Name[0] == '+';
+ setFeatureEnabled(Features, Name.substr(1), Enabled);
+ }
+ return true;
+}
+
//===----------------------------------------------------------------------===//
@@ -326,7 +339,7 @@ static StringRef removeGCCRegisterPrefix(StringRef Name) {
/// Sema.
bool TargetInfo::isValidClobber(StringRef Name) const {
return (isValidGCCRegisterName(Name) ||
- Name == "memory" || Name == "cc");
+ Name == "memory" || Name == "cc");
}
/// isValidGCCRegisterName - Returns whether the passed in string
@@ -336,56 +349,43 @@ bool TargetInfo::isValidGCCRegisterName(StringRef Name) const {
if (Name.empty())
return false;
- const char * const *Names;
- unsigned NumNames;
-
// Get rid of any register prefix.
Name = removeGCCRegisterPrefix(Name);
if (Name.empty())
- return false;
+ return false;
- getGCCRegNames(Names, NumNames);
+ ArrayRef<const char *> Names = getGCCRegNames();
// If we have a number it maps to an entry in the register name array.
if (isDigit(Name[0])) {
- int n;
+ unsigned n;
if (!Name.getAsInteger(0, n))
- return n >= 0 && (unsigned)n < NumNames;
+ return n < Names.size();
}
// Check register names.
- for (unsigned i = 0; i < NumNames; i++) {
- if (Name == Names[i])
- return true;
- }
+ if (std::find(Names.begin(), Names.end(), Name) != Names.end())
+ return true;
// Check any additional names that we have.
- const AddlRegName *AddlNames;
- unsigned NumAddlNames;
- getGCCAddlRegNames(AddlNames, NumAddlNames);
- for (unsigned i = 0; i < NumAddlNames; i++)
- for (unsigned j = 0; j < llvm::array_lengthof(AddlNames[i].Names); j++) {
- if (!AddlNames[i].Names[j])
- break;
+ for (const AddlRegName &ARN : getGCCAddlRegNames())
+ for (const char *AN : ARN.Names) {
+ if (!AN)
+ break;
// Make sure the register that the additional name is for is within
// the bounds of the register names from above.
- if (AddlNames[i].Names[j] == Name && AddlNames[i].RegNum < NumNames)
- return true;
- }
+ if (AN == Name && ARN.RegNum < Names.size())
+ return true;
+ }
// Now check aliases.
- const GCCRegAlias *Aliases;
- unsigned NumAliases;
-
- getGCCRegAliases(Aliases, NumAliases);
- for (unsigned i = 0; i < NumAliases; i++) {
- for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
- if (!Aliases[i].Aliases[j])
+ for (const GCCRegAlias &GRA : getGCCRegAliases())
+ for (const char *A : GRA.Aliases) {
+ if (!A)
break;
- if (Aliases[i].Aliases[j] == Name)
+ if (A == Name)
return true;
}
- }
return false;
}
@@ -397,48 +397,36 @@ TargetInfo::getNormalizedGCCRegisterName(StringRef Name) const {
// Get rid of any register prefix.
Name = removeGCCRegisterPrefix(Name);
- const char * const *Names;
- unsigned NumNames;
-
- getGCCRegNames(Names, NumNames);
+ ArrayRef<const char *> Names = getGCCRegNames();
// First, check if we have a number.
if (isDigit(Name[0])) {
- int n;
+ unsigned n;
if (!Name.getAsInteger(0, n)) {
- assert(n >= 0 && (unsigned)n < NumNames &&
- "Out of bounds register number!");
+ assert(n < Names.size() && "Out of bounds register number!");
return Names[n];
}
}
// Check any additional names that we have.
- const AddlRegName *AddlNames;
- unsigned NumAddlNames;
- getGCCAddlRegNames(AddlNames, NumAddlNames);
- for (unsigned i = 0; i < NumAddlNames; i++)
- for (unsigned j = 0; j < llvm::array_lengthof(AddlNames[i].Names); j++) {
- if (!AddlNames[i].Names[j])
- break;
+ for (const AddlRegName &ARN : getGCCAddlRegNames())
+ for (const char *AN : ARN.Names) {
+ if (!AN)
+ break;
// Make sure the register that the additional name is for is within
// the bounds of the register names from above.
- if (AddlNames[i].Names[j] == Name && AddlNames[i].RegNum < NumNames)
- return Name;
+ if (AN == Name && ARN.RegNum < Names.size())
+ return Name;
}
// Now check aliases.
- const GCCRegAlias *Aliases;
- unsigned NumAliases;
-
- getGCCRegAliases(Aliases, NumAliases);
- for (unsigned i = 0; i < NumAliases; i++) {
- for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
- if (!Aliases[i].Aliases[j])
+ for (const GCCRegAlias &RA : getGCCRegAliases())
+ for (const char *A : RA.Aliases) {
+ if (!A)
break;
- if (Aliases[i].Aliases[j] == Name)
- return Aliases[i].Register;
+ if (A == Name)
+ return RA.Register;
}
- }
return Name;
}
@@ -513,8 +501,7 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
}
bool TargetInfo::resolveSymbolicName(const char *&Name,
- ConstraintInfo *OutputConstraints,
- unsigned NumOutputs,
+ ArrayRef<ConstraintInfo> OutputConstraints,
unsigned &Index) const {
assert(*Name == '[' && "Symbolic name did not start with '['");
Name++;
@@ -529,16 +516,16 @@ bool TargetInfo::resolveSymbolicName(const char *&Name,
std::string SymbolicName(Start, Name - Start);
- for (Index = 0; Index != NumOutputs; ++Index)
+ for (Index = 0; Index != OutputConstraints.size(); ++Index)
if (SymbolicName == OutputConstraints[Index].getName())
return true;
return false;
}
-bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
- unsigned NumOutputs,
- ConstraintInfo &Info) const {
+bool TargetInfo::validateInputConstraint(
+ MutableArrayRef<ConstraintInfo> OutputConstraints,
+ ConstraintInfo &Info) const {
const char *Name = Info.ConstraintStr.c_str();
if (!*Name)
@@ -559,13 +546,13 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
return false;
// Check if matching constraint is out of bounds.
- if (i >= NumOutputs) return false;
+ if (i >= OutputConstraints.size()) return false;
// A number must refer to an output only operand.
if (OutputConstraints[i].isReadWrite())
return false;
- // If the constraint is already tied, it must be tied to the
+ // If the constraint is already tied, it must be tied to the
// same operand referenced to by the number.
if (Info.hasTiedOperand() && Info.getTiedOperand() != i)
return false;
@@ -582,10 +569,10 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
break;
case '[': {
unsigned Index = 0;
- if (!resolveSymbolicName(Name, OutputConstraints, NumOutputs, Index))
+ if (!resolveSymbolicName(Name, OutputConstraints, Index))
return false;
- // If the constraint is already tied, it must be tied to the
+ // If the constraint is already tied, it must be tied to the
// same operand referenced to by the number.
if (Info.hasTiedOperand() && Info.getTiedOperand() != Index)
return false;
@@ -650,18 +637,3 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
return true;
}
-
-bool TargetCXXABI::tryParse(llvm::StringRef name) {
- const Kind unknown = static_cast<Kind>(-1);
- Kind kind = llvm::StringSwitch<Kind>(name)
- .Case("arm", GenericARM)
- .Case("ios", iOS)
- .Case("itanium", GenericItanium)
- .Case("microsoft", Microsoft)
- .Case("mips", GenericMIPS)
- .Default(unknown);
- if (kind == unknown) return false;
-
- set(kind);
- return true;
-}
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
index 9e44f7d..1bc6c51 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
@@ -1,4 +1,4 @@
-//===--- Targets.cpp - Implement -arch option and targets -----------------===//
+//===--- Targets.cpp - Implement target feature support -------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,6 +19,7 @@
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/Version.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
@@ -30,6 +31,7 @@
#include "llvm/Support/TargetParser.h"
#include <algorithm>
#include <memory>
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -82,8 +84,28 @@ public:
}
};
-} // end anonymous namespace
+// CloudABI Target
+template <typename Target>
+class CloudABITargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__CloudABI__");
+ Builder.defineMacro("__ELF__");
+
+ // CloudABI uses ISO/IEC 10646:2012 for wchar_t, char16_t and char32_t.
+ Builder.defineMacro("__STDC_ISO_10646__", "201206L");
+ Builder.defineMacro("__STDC_UTF_16__");
+ Builder.defineMacro("__STDC_UTF_32__");
+ }
+
+public:
+ CloudABITargetInfo(const llvm::Triple &Triple)
+ : OSTargetInfo<Target>(Triple) {
+ this->UserLabelPrefix = "";
+ }
+};
static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
const llvm::Triple &Triple,
@@ -97,19 +119,11 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
if (Opts.Sanitize.has(SanitizerKind::Address))
Builder.defineMacro("_FORTIFY_SOURCE", "0");
- if (!Opts.ObjCAutoRefCount) {
+ // Darwin defines __weak, __strong, and __unsafe_unretained even in C mode.
+ if (!Opts.ObjC1) {
// __weak is always defined, for use in blocks and with objc pointers.
Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
-
- // Darwin defines __strong even in C mode (just to nothing).
- if (Opts.getGC() != LangOptions::NonGC)
- Builder.defineMacro("__strong", "__attribute__((objc_gc(strong)))");
- else
- Builder.defineMacro("__strong", "");
-
- // __unsafe_unretained is defined to nothing in non-ARC mode. We even
- // allow this in C, since one might have block pointers in structs that
- // are used in pure C code and in Objective-C ARC.
+ Builder.defineMacro("__strong", "");
Builder.defineMacro("__unsafe_unretained", "");
}
@@ -149,8 +163,22 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
Str[3] = '0' + (Rev / 10);
Str[4] = '0' + (Rev % 10);
Str[5] = '\0';
- Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
- Str);
+ if (Triple.isTvOS())
+ Builder.defineMacro("__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__", Str);
+ else
+ Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__",
+ Str);
+
+ } else if (Triple.isWatchOS()) {
+ assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!");
+ char Str[6];
+ Str[0] = '0' + Maj;
+ Str[1] = '0' + (Min / 10);
+ Str[2] = '0' + (Min % 10);
+ Str[3] = '0' + (Rev / 10);
+ Str[4] = '0' + (Rev % 10);
+ Str[5] = '\0';
+ Builder.defineMacro("__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__", Str);
} else if (Triple.isMacOSX()) {
// Note that the Driver allows versions which aren't representable in the
// define (because we only get a single digit for the minor and micro
@@ -184,29 +212,6 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
PlatformMinVersion = VersionTuple(Maj, Min, Rev);
}
-namespace {
-// CloudABI Target
-template <typename Target>
-class CloudABITargetInfo : public OSTargetInfo<Target> {
-protected:
- void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__CloudABI__");
- Builder.defineMacro("__ELF__");
-
- // CloudABI uses ISO/IEC 10646:2012 for wchar_t, char16_t and char32_t.
- Builder.defineMacro("__STDC_ISO_10646__", "201206L");
- Builder.defineMacro("__STDC_UTF_16__");
- Builder.defineMacro("__STDC_UTF_32__");
- }
-
-public:
- CloudABITargetInfo(const llvm::Triple &Triple)
- : OSTargetInfo<Target>(Triple) {
- this->UserLabelPrefix = "";
- }
-};
-
template<typename Target>
class DarwinTargetInfo : public OSTargetInfo<Target> {
protected:
@@ -218,7 +223,24 @@ protected:
public:
DarwinTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {
- this->TLSSupported = Triple.isMacOSX() && !Triple.isMacOSXVersionLT(10, 7);
+ // By default, no TLS, and we whitelist permitted architecture/OS
+ // combinations.
+ this->TLSSupported = false;
+
+ if (Triple.isMacOSX())
+ this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7);
+ else if (Triple.isiOS()) {
+ // 64-bit iOS supported it from 8 onwards, 32-bit from 9 onwards.
+ if (Triple.getArch() == llvm::Triple::x86_64 ||
+ Triple.getArch() == llvm::Triple::aarch64)
+ this->TLSSupported = !Triple.isOSVersionLT(8);
+ else if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb)
+ this->TLSSupported = !Triple.isOSVersionLT(9);
+ } else if (Triple.isWatchOS())
+ this->TLSSupported = !Triple.isOSVersionLT(2);
+
this->MCountName = "\01mcount";
}
@@ -386,7 +408,7 @@ protected:
DefineStd(Builder, "linux", Opts);
Builder.defineMacro("__gnu_linux__");
Builder.defineMacro("__ELF__");
- if (Triple.getEnvironment() == llvm::Triple::Android) {
+ if (Triple.isAndroid()) {
Builder.defineMacro("__ANDROID__", "1");
unsigned Maj, Min, Rev;
Triple.getEnvironmentVersion(Maj, Min, Rev);
@@ -560,7 +582,7 @@ public:
this->IntMaxType = TargetInfo::SignedLongLong;
this->Int64Type = TargetInfo::SignedLongLong;
this->SizeType = TargetInfo::UnsignedInt;
- this->DescriptionString = "E-m:e-p:32:32-i64:64-n32:64";
+ this->DataLayoutString = "E-m:e-p:32:32-i64:64-n32:64";
}
};
@@ -645,6 +667,9 @@ protected:
Builder.defineMacro("_CPPUNWIND");
}
+ if (Opts.Bool)
+ Builder.defineMacro("__BOOL_DEFINED");
+
if (!Opts.CharIsSigned)
Builder.defineMacro("_CHAR_UNSIGNED");
@@ -719,18 +744,45 @@ public:
if (Triple.getArch() == llvm::Triple::arm) {
// Handled in ARM's setABI().
} else if (Triple.getArch() == llvm::Triple::x86) {
- this->DescriptionString = "e-m:e-p:32:32-i64:64-n8:16:32-S128";
+ this->DataLayoutString = "e-m:e-p:32:32-i64:64-n8:16:32-S128";
} else if (Triple.getArch() == llvm::Triple::x86_64) {
- this->DescriptionString = "e-m:e-p:32:32-i64:64-n8:16:32:64-S128";
+ this->DataLayoutString = "e-m:e-p:32:32-i64:64-n8:16:32:64-S128";
} else if (Triple.getArch() == llvm::Triple::mipsel) {
- // Handled on mips' setDescriptionString.
+ // Handled on mips' setDataLayoutString.
} else {
assert(Triple.getArch() == llvm::Triple::le32);
- this->DescriptionString = "e-p:32:32-i64:64";
+ this->DataLayoutString = "e-p:32:32-i64:64";
}
}
};
+// WebAssembly target
+template <typename Target>
+class WebAssemblyOSTargetInfo : public OSTargetInfo<Target> {
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const final {
+ // A common platform macro.
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ // Follow g++ convention and predefine _GNU_SOURCE for C++.
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+
+ // As an optimization, group static init code together in a section.
+ const char *getStaticInitSectionSpecifier() const final {
+ return ".text.__startup";
+ }
+
+public:
+ explicit WebAssemblyOSTargetInfo(const llvm::Triple &Triple)
+ : OSTargetInfo<Target>(Triple) {
+ this->MCountName = "__mcount";
+ this->UserLabelPrefix = "";
+ this->TheCXXABI.set(TargetCXXABI::WebAssembly);
+ }
+};
+
//===----------------------------------------------------------------------===//
// Specific target implementations.
//===----------------------------------------------------------------------===//
@@ -849,10 +901,9 @@ public:
StringRef getABI() const override { return ABI; }
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::PPC::LastTSBuiltin-Builtin::FirstTSBuiltin;
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::PPC::LastTSBuiltin-Builtin::FirstTSBuiltin);
}
bool isCLZForZeroUndef() const override { return false; }
@@ -860,7 +911,10 @@ public:
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
- void getDefaultFeatures(llvm::StringMap<bool> &Features) const override;
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override;
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;
@@ -868,10 +922,8 @@ public:
void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
bool Enabled) const override;
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override;
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
switch (*Name) {
@@ -1006,9 +1058,10 @@ public:
};
const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
- ALL_LANGUAGES },
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsPPC.def"
};
@@ -1016,65 +1069,27 @@ const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
/// configured set of features.
bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) {
- for (unsigned i = 0, e = Features.size(); i !=e; ++i) {
- // Ignore disabled features.
- if (Features[i][0] == '-')
- continue;
-
- StringRef Feature = StringRef(Features[i]).substr(1);
-
- if (Feature == "vsx") {
+ for (const auto &Feature : Features) {
+ if (Feature == "+vsx") {
HasVSX = true;
- continue;
- }
-
- if (Feature == "bpermd") {
+ } else if (Feature == "+bpermd") {
HasBPERMD = true;
- continue;
- }
-
- if (Feature == "extdiv") {
+ } else if (Feature == "+extdiv") {
HasExtDiv = true;
- continue;
- }
-
- if (Feature == "power8-vector") {
+ } else if (Feature == "+power8-vector") {
HasP8Vector = true;
- continue;
- }
-
- if (Feature == "crypto") {
+ } else if (Feature == "+crypto") {
HasP8Crypto = true;
- continue;
- }
-
- if (Feature == "direct-move") {
+ } else if (Feature == "+direct-move") {
HasDirectMove = true;
- continue;
- }
-
- if (Feature == "qpx") {
+ } else if (Feature == "+qpx") {
HasQPX = true;
- continue;
- }
-
- if (Feature == "htm") {
+ } else if (Feature == "+htm") {
HasHTM = true;
- continue;
}
-
// TODO: Finish this list and add an assert that we've handled them
// all.
}
- if (!HasVSX && (HasP8Vector || HasDirectMove)) {
- if (HasP8Vector)
- Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower8-vector" <<
- "-mno-vsx";
- else if (HasDirectMove)
- Diags.Report(diag::err_opt_not_valid_with_opt) << "-mdirect-move" <<
- "-mno-vsx";
- return false;
- }
return true;
}
@@ -1228,14 +1243,12 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__CRYPTO__");
if (HasHTM)
Builder.defineMacro("__HTM__");
- if (getTriple().getArch() == llvm::Triple::ppc64le ||
- (defs & ArchDefinePwr8) || (CPU == "pwr8")) {
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
- if (PointerWidth == 64)
- Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
- }
+
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ if (PointerWidth == 64)
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
// FIXME: The following are not yet generated here by Clang, but are
// generated by GCC:
@@ -1258,7 +1271,36 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
// __NO_FPRS__
}
-void PPCTargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
+// Handle explicit options being passed to the compiler here: if we've
+// explicitly turned off vsx and turned on power8-vector or direct-move then
+// go ahead and error since the customer has expressed a somewhat incompatible
+// set of options.
+static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags,
+ const std::vector<std::string> &FeaturesVec) {
+
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "-vsx") !=
+ FeaturesVec.end()) {
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power8-vector") !=
+ FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower8-vector"
+ << "-mno-vsx";
+ return false;
+ }
+
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+direct-move") !=
+ FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mdirect-move"
+ << "-mno-vsx";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool PPCTargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
Features["altivec"] = llvm::StringSwitch<bool>(CPU)
.Case("7400", true)
.Case("g4", true)
@@ -1301,6 +1343,11 @@ void PPCTargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
.Case("pwr8", true)
.Case("pwr7", true)
.Default(false);
+
+ if (!ppcUserFeaturesCheck(Diags, FeaturesVec))
+ return false;
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
bool PPCTargetInfo::hasFeature(StringRef Feature) const {
@@ -1317,37 +1364,29 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
.Default(false);
}
-/* There is no clear way for the target to know which of the features in the
- final feature vector came from defaults and which are actually specified by
- the user. To that end, we use the fact that this function is not called on
- default features - only user specified ones. By the first time this
- function is called, the default features are populated.
- We then keep track of the features that the user specified so that we
- can ensure we do not override a user's request (only defaults).
- For example:
- -mcpu=pwr8 -mno-vsx (should disable vsx and everything that depends on it)
- -mcpu=pwr8 -mdirect-move -mno-vsx (should actually be diagnosed)
-
-NOTE: Do not call this from PPCTargetInfo::getDefaultFeatures
-*/
void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name, bool Enabled) const {
- static llvm::StringMap<bool> ExplicitFeatures;
- ExplicitFeatures[Name] = Enabled;
-
- // At this point, -mno-vsx turns off the dependent features but we respect
- // the user's requests.
- if (!Enabled && Name == "vsx") {
- Features["direct-move"] = ExplicitFeatures["direct-move"];
- Features["power8-vector"] = ExplicitFeatures["power8-vector"];
- }
- if ((Enabled && Name == "power8-vector") ||
- (Enabled && Name == "direct-move")) {
- if (ExplicitFeatures.find("vsx") == ExplicitFeatures.end()) {
- Features["vsx"] = true;
+ // If we're enabling direct-move or power8-vector go ahead and enable vsx
+ // as well. Do the inverse if we're disabling vsx. We'll diagnose any user
+ // incompatible options.
+ if (Enabled) {
+ if (Name == "vsx") {
+ Features[Name] = true;
+ } else if (Name == "direct-move") {
+ Features[Name] = Features["vsx"] = true;
+ } else if (Name == "power8-vector") {
+ Features[Name] = Features["vsx"] = true;
+ } else {
+ Features[Name] = true;
+ }
+ } else {
+ if (Name == "vsx") {
+ Features[Name] = Features["direct-move"] = Features["power8-vector"] =
+ false;
+ } else {
+ Features[Name] = false;
}
}
- Features[Name] = Enabled;
}
const char * const PPCTargetInfo::GCCRegNames[] = {
@@ -1371,10 +1410,8 @@ const char * const PPCTargetInfo::GCCRegNames[] = {
"sfp"
};
-void PPCTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+ArrayRef<const char*> PPCTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
}
const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
@@ -1447,16 +1484,14 @@ const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
{ { "cc" }, "cr0" },
};
-void PPCTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
+ArrayRef<TargetInfo::GCCRegAlias> PPCTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
}
class PPC32TargetInfo : public PPCTargetInfo {
public:
PPC32TargetInfo(const llvm::Triple &Triple) : PPCTargetInfo(Triple) {
- DescriptionString = "E-m:e-p:32:32-i64:64-n32";
+ DataLayoutString = "E-m:e-p:32:32-i64:64-n32";
switch (getTriple().getOS()) {
case llvm::Triple::Linux:
@@ -1495,10 +1530,10 @@ public:
Int64Type = SignedLong;
if ((Triple.getArch() == llvm::Triple::ppc64le)) {
- DescriptionString = "e-m:e-i64:64-n32:64";
+ DataLayoutString = "e-m:e-i64:64-n32:64";
ABI = "elfv2";
} else {
- DescriptionString = "E-m:e-i64:64-n32:64";
+ DataLayoutString = "E-m:e-i64:64-n32:64";
ABI = "elfv1";
}
@@ -1541,7 +1576,7 @@ public:
PtrDiffType = SignedInt; // for http://llvm.org/bugs/show_bug.cgi?id=15726
LongLongAlign = 32;
SuitableAlign = 128;
- DescriptionString = "E-m:o-p:32:32-f64:32:64-n32";
+ DataLayoutString = "E-m:o-p:32:32-f64:32:64-n32";
}
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::CharPtrBuiltinVaList;
@@ -1555,23 +1590,24 @@ public:
: DarwinTargetInfo<PPC64TargetInfo>(Triple) {
HasAlignMac68kSupport = true;
SuitableAlign = 128;
- DescriptionString = "E-m:o-i64:64-n32:64";
+ DataLayoutString = "E-m:o-i64:64-n32:64";
}
};
- static const unsigned NVPTXAddrSpaceMap[] = {
- 1, // opencl_global
- 3, // opencl_local
- 4, // opencl_constant
+static const unsigned NVPTXAddrSpaceMap[] = {
+ 1, // opencl_global
+ 3, // opencl_local
+ 4, // opencl_constant
// FIXME: generic has to be added to the target
- 0, // opencl_generic
- 1, // cuda_device
- 4, // cuda_constant
- 3, // cuda_shared
- };
- class NVPTXTargetInfo : public TargetInfo {
- static const char * const GCCRegNames[];
- static const Builtin::Info BuiltinInfo[];
+ 0, // opencl_generic
+ 1, // cuda_device
+ 4, // cuda_constant
+ 3, // cuda_shared
+};
+
+class NVPTXTargetInfo : public TargetInfo {
+ static const char *const GCCRegNames[];
+ static const Builtin::Info BuiltinInfo[];
// The GPU profiles supported by the NVPTX backend
enum GPUKind {
@@ -1583,139 +1619,133 @@ public:
GK_SM37,
} GPU;
- public:
- NVPTXTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
- BigEndian = false;
- TLSSupported = false;
- LongWidth = LongAlign = 64;
- AddrSpaceMap = &NVPTXAddrSpaceMap;
- UseAddrSpaceMapMangling = true;
- // Define available target features
- // These must be defined in sorted order!
- NoAsmVariants = true;
- // Set the default GPU to sm20
- GPU = GK_SM20;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("__PTX__");
- Builder.defineMacro("__NVPTX__");
- if (Opts.CUDAIsDevice) {
- // Set __CUDA_ARCH__ for the GPU specified.
- std::string CUDAArchCode;
- switch (GPU) {
- case GK_SM20:
- CUDAArchCode = "200";
- break;
- case GK_SM21:
- CUDAArchCode = "210";
- break;
- case GK_SM30:
- CUDAArchCode = "300";
- break;
- case GK_SM35:
- CUDAArchCode = "350";
- break;
- case GK_SM37:
- CUDAArchCode = "370";
- break;
- default:
- llvm_unreachable("Unhandled target CPU");
- }
- Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode);
- }
- }
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::NVPTX::LastTSBuiltin-Builtin::FirstTSBuiltin;
- }
- bool hasFeature(StringRef Feature) const override {
- return Feature == "ptx" || Feature == "nvptx";
- }
-
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {
- // No aliases.
- Aliases = nullptr;
- NumAliases = 0;
- }
- bool
- validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const override {
- switch (*Name) {
- default: return false;
- case 'c':
- case 'h':
- case 'r':
- case 'l':
- case 'f':
- case 'd':
- Info.setAllowsRegister();
- return true;
+public:
+ NVPTXTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
+ BigEndian = false;
+ TLSSupported = false;
+ LongWidth = LongAlign = 64;
+ AddrSpaceMap = &NVPTXAddrSpaceMap;
+ UseAddrSpaceMapMangling = true;
+ // Define available target features
+ // These must be defined in sorted order!
+ NoAsmVariants = true;
+ // Set the default GPU to sm20
+ GPU = GK_SM20;
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__PTX__");
+ Builder.defineMacro("__NVPTX__");
+ if (Opts.CUDAIsDevice) {
+ // Set __CUDA_ARCH__ for the GPU specified.
+ std::string CUDAArchCode;
+ switch (GPU) {
+ case GK_SM20:
+ CUDAArchCode = "200";
+ break;
+ case GK_SM21:
+ CUDAArchCode = "210";
+ break;
+ case GK_SM30:
+ CUDAArchCode = "300";
+ break;
+ case GK_SM35:
+ CUDAArchCode = "350";
+ break;
+ case GK_SM37:
+ CUDAArchCode = "370";
+ break;
+ default:
+ llvm_unreachable("Unhandled target CPU");
}
+ Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode);
}
- const char *getClobbers() const override {
- // FIXME: Is this really right?
- return "";
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- // FIXME: implement
- return TargetInfo::CharPtrBuiltinVaList;
- }
- bool setCPU(const std::string &Name) override {
- GPU = llvm::StringSwitch<GPUKind>(Name)
- .Case("sm_20", GK_SM20)
- .Case("sm_21", GK_SM21)
- .Case("sm_30", GK_SM30)
- .Case("sm_35", GK_SM35)
- .Case("sm_37", GK_SM37)
- .Default(GK_NONE);
+ }
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin);
+ }
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "ptx" || Feature == "nvptx";
+ }
- return GPU != GK_NONE;
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ // No aliases.
+ return None;
+ }
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ default:
+ return false;
+ case 'c':
+ case 'h':
+ case 'r':
+ case 'l':
+ case 'f':
+ case 'd':
+ Info.setAllowsRegister();
+ return true;
}
- };
+ }
+ const char *getClobbers() const override {
+ // FIXME: Is this really right?
+ return "";
+ }
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ // FIXME: implement
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+ bool setCPU(const std::string &Name) override {
+ GPU = llvm::StringSwitch<GPUKind>(Name)
+ .Case("sm_20", GK_SM20)
+ .Case("sm_21", GK_SM21)
+ .Case("sm_30", GK_SM30)
+ .Case("sm_35", GK_SM35)
+ .Case("sm_37", GK_SM37)
+ .Default(GK_NONE);
+
+ return GPU != GK_NONE;
+ }
+};
- const Builtin::Info NVPTXTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
- ALL_LANGUAGES },
+const Builtin::Info NVPTXTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsNVPTX.def"
- };
+};
- const char * const NVPTXTargetInfo::GCCRegNames[] = {
- "r0"
- };
+const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};
- void NVPTXTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
- }
+ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
- class NVPTX32TargetInfo : public NVPTXTargetInfo {
- public:
- NVPTX32TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) {
- PointerWidth = PointerAlign = 32;
- SizeType = TargetInfo::UnsignedInt;
- PtrDiffType = TargetInfo::SignedInt;
- IntPtrType = TargetInfo::SignedInt;
- DescriptionString = "e-p:32:32-i64:64-v16:16-v32:32-n16:32:64";
- }
- };
+class NVPTX32TargetInfo : public NVPTXTargetInfo {
+public:
+ NVPTX32TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) {
+ LongWidth = LongAlign = 32;
+ PointerWidth = PointerAlign = 32;
+ SizeType = TargetInfo::UnsignedInt;
+ PtrDiffType = TargetInfo::SignedInt;
+ IntPtrType = TargetInfo::SignedInt;
+ DataLayoutString = "e-p:32:32-i64:64-v16:16-v32:32-n16:32:64";
+ }
+};
- class NVPTX64TargetInfo : public NVPTXTargetInfo {
- public:
- NVPTX64TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) {
- PointerWidth = PointerAlign = 64;
- SizeType = TargetInfo::UnsignedLong;
- PtrDiffType = TargetInfo::SignedLong;
- IntPtrType = TargetInfo::SignedLong;
- DescriptionString = "e-i64:64-v16:16-v32:32-n16:32:64";
- }
- };
+class NVPTX64TargetInfo : public NVPTXTargetInfo {
+public:
+ NVPTX64TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) {
+ PointerWidth = PointerAlign = 64;
+ SizeType = TargetInfo::UnsignedLong;
+ PtrDiffType = TargetInfo::SignedLong;
+ IntPtrType = TargetInfo::SignedLong;
+ DataLayoutString = "e-i64:64-v16:16-v32:32-n16:32:64";
+ }
+};
static const unsigned AMDGPUAddrSpaceMap[] = {
1, // opencl_global
@@ -1730,15 +1760,15 @@ static const unsigned AMDGPUAddrSpaceMap[] = {
// If you edit the description strings, make sure you update
// getPointerWidthV().
-static const char *DescriptionStringR600 =
+static const char *const DataLayoutStringR600 =
"e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";
-static const char *DescriptionStringR600DoubleOps =
+static const char *const DataLayoutStringR600DoubleOps =
"e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";
-static const char *DescriptionStringSI =
+static const char *const DataLayoutStringSI =
"e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-p24:64:64"
"-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128"
"-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64";
@@ -1772,13 +1802,13 @@ public:
: TargetInfo(Triple) {
if (Triple.getArch() == llvm::Triple::amdgcn) {
- DescriptionString = DescriptionStringSI;
+ DataLayoutString = DataLayoutStringSI;
GPU = GK_SOUTHERN_ISLANDS;
hasFP64 = true;
hasFMAF = true;
hasLDEXPF = true;
} else {
- DescriptionString = DescriptionStringR600;
+ DataLayoutString = DataLayoutStringR600;
GPU = GK_R600;
hasFP64 = false;
hasFMAF = false;
@@ -1806,24 +1836,27 @@ public:
return "";
}
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override;
+ ArrayRef<const char *> getGCCRegNames() const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {
- Aliases = nullptr;
- NumAliases = 0;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
}
bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override {
- return true;
+ TargetInfo::ConstraintInfo &Info) const override {
+ switch (*Name) {
+ default: break;
+ case 'v': // vgpr
+ case 's': // sgpr
+ Info.setAllowsRegister();
+ return true;
+ }
+ return false;
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin;
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin);
}
void getTargetDefines(const LangOptions &Opts,
@@ -1833,8 +1866,16 @@ public:
Builder.defineMacro("__HAS_FMAF__");
if (hasLDEXPF)
Builder.defineMacro("__HAS_LDEXPF__");
- if (hasFP64 && Opts.OpenCL) {
+ if (hasFP64 && Opts.OpenCL)
Builder.defineMacro("cl_khr_fp64");
+ if (Opts.OpenCL) {
+ if (GPU >= GK_NORTHERN_ISLANDS) {
+ Builder.defineMacro("cl_khr_byte_addressable_store");
+ Builder.defineMacro("cl_khr_global_int32_base_atomics");
+ Builder.defineMacro("cl_khr_global_int32_extended_atomics");
+ Builder.defineMacro("cl_khr_local_int32_base_atomics");
+ Builder.defineMacro("cl_khr_local_int32_extended_atomics");
+ }
}
}
@@ -1895,7 +1936,7 @@ public:
case GK_R700:
case GK_EVERGREEN:
case GK_NORTHERN_ISLANDS:
- DescriptionString = DescriptionStringR600;
+ DataLayoutString = DataLayoutStringR600;
hasFP64 = false;
hasFMAF = false;
hasLDEXPF = false;
@@ -1904,7 +1945,7 @@ public:
case GK_R700_DOUBLE_OPS:
case GK_EVERGREEN_DOUBLE_OPS:
case GK_CAYMAN:
- DescriptionString = DescriptionStringR600DoubleOps;
+ DataLayoutString = DataLayoutStringR600DoubleOps;
hasFP64 = true;
hasFMAF = true;
hasLDEXPF = false;
@@ -1912,7 +1953,7 @@ public:
case GK_SOUTHERN_ISLANDS:
case GK_SEA_ISLANDS:
case GK_VOLCANIC_ISLANDS:
- DescriptionString = DescriptionStringSI;
+ DataLayoutString = DataLayoutStringSI;
hasFP64 = true;
hasFMAF = true;
hasLDEXPF = true;
@@ -1925,7 +1966,7 @@ public:
const Builtin::Info AMDGPUTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsAMDGPU.def"
};
const char * const AMDGPUTargetInfo::GCCRegNames[] = {
@@ -1981,17 +2022,18 @@ const char * const AMDGPUTargetInfo::GCCRegNames[] = {
"vcc_lo", "vcc_hi", "flat_scr_lo", "flat_scr_hi"
};
-void AMDGPUTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+ArrayRef<const char *> AMDGPUTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
}
// Namespace for x86 abstract base class
const Builtin::Info BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
- ALL_LANGUAGES },
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE },
#include "clang/Basic/BuiltinsX86.def"
};
@@ -2016,6 +2058,14 @@ const TargetInfo::AddlRegName AddlRegNames[] = {
{ { "edi", "rdi" }, 5 },
{ { "esp", "rsp" }, 7 },
{ { "ebp", "rbp" }, 6 },
+ { { "r8d", "r8w", "r8b" }, 38 },
+ { { "r9d", "r9w", "r9b" }, 39 },
+ { { "r10d", "r10w", "r10b" }, 40 },
+ { { "r11d", "r11w", "r11b" }, 41 },
+ { { "r12d", "r12w", "r12b" }, 42 },
+ { { "r13d", "r13w", "r13b" }, 43 },
+ { { "r14d", "r14w", "r14b" }, 44 },
+ { { "r15d", "r15w", "r15b" }, 45 },
};
// X86 target abstract base class; x86-32 and x86-64 are very close, so
@@ -2023,36 +2073,46 @@ const TargetInfo::AddlRegName AddlRegNames[] = {
class X86TargetInfo : public TargetInfo {
enum X86SSEEnum {
NoSSE, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, AVX, AVX2, AVX512F
- } SSELevel;
+ } SSELevel = NoSSE;
enum MMX3DNowEnum {
NoMMX3DNow, MMX, AMD3DNow, AMD3DNowAthlon
- } MMX3DNowLevel;
+ } MMX3DNowLevel = NoMMX3DNow;
enum XOPEnum {
NoXOP,
SSE4A,
FMA4,
XOP
- } XOPLevel;
-
- bool HasAES;
- bool HasPCLMUL;
- bool HasLZCNT;
- bool HasRDRND;
- bool HasFSGSBASE;
- bool HasBMI;
- bool HasBMI2;
- bool HasPOPCNT;
- bool HasRTM;
- bool HasPRFCHW;
- bool HasRDSEED;
- bool HasADX;
- bool HasTBM;
- bool HasFMA;
- bool HasF16C;
- bool HasAVX512CD, HasAVX512ER, HasAVX512PF, HasAVX512DQ, HasAVX512BW,
- HasAVX512VL;
- bool HasSHA;
- bool HasCX16;
+ } XOPLevel = NoXOP;
+
+ bool HasAES = false;
+ bool HasPCLMUL = false;
+ bool HasLZCNT = false;
+ bool HasRDRND = false;
+ bool HasFSGSBASE = false;
+ bool HasBMI = false;
+ bool HasBMI2 = false;
+ bool HasPOPCNT = false;
+ bool HasRTM = false;
+ bool HasPRFCHW = false;
+ bool HasRDSEED = false;
+ bool HasADX = false;
+ bool HasTBM = false;
+ bool HasFMA = false;
+ bool HasF16C = false;
+ bool HasAVX512CD = false;
+ bool HasAVX512ER = false;
+ bool HasAVX512PF = false;
+ bool HasAVX512DQ = false;
+ bool HasAVX512BW = false;
+ bool HasAVX512VL = false;
+ bool HasSHA = false;
+ bool HasCX16 = false;
+ bool HasFXSR = false;
+ bool HasXSAVE = false;
+ bool HasXSAVEOPT = false;
+ bool HasXSAVEC = false;
+ bool HasXSAVES = false;
+ bool HasPKU = false;
/// \brief Enumeration of all of the X86 CPUs supported by Clang.
///
@@ -2220,24 +2280,85 @@ class X86TargetInfo : public TargetInfo {
//@{
CK_Geode
//@}
- } CPU;
+ } CPU = CK_Generic;
+
+ CPUKind getCPUKind(StringRef CPU) const {
+ return llvm::StringSwitch<CPUKind>(CPU)
+ .Case("i386", CK_i386)
+ .Case("i486", CK_i486)
+ .Case("winchip-c6", CK_WinChipC6)
+ .Case("winchip2", CK_WinChip2)
+ .Case("c3", CK_C3)
+ .Case("i586", CK_i586)
+ .Case("pentium", CK_Pentium)
+ .Case("pentium-mmx", CK_PentiumMMX)
+ .Case("i686", CK_i686)
+ .Case("pentiumpro", CK_PentiumPro)
+ .Case("pentium2", CK_Pentium2)
+ .Case("pentium3", CK_Pentium3)
+ .Case("pentium3m", CK_Pentium3M)
+ .Case("pentium-m", CK_PentiumM)
+ .Case("c3-2", CK_C3_2)
+ .Case("yonah", CK_Yonah)
+ .Case("pentium4", CK_Pentium4)
+ .Case("pentium4m", CK_Pentium4M)
+ .Case("prescott", CK_Prescott)
+ .Case("nocona", CK_Nocona)
+ .Case("core2", CK_Core2)
+ .Case("penryn", CK_Penryn)
+ .Case("bonnell", CK_Bonnell)
+ .Case("atom", CK_Bonnell) // Legacy name.
+ .Case("silvermont", CK_Silvermont)
+ .Case("slm", CK_Silvermont) // Legacy name.
+ .Case("nehalem", CK_Nehalem)
+ .Case("corei7", CK_Nehalem) // Legacy name.
+ .Case("westmere", CK_Westmere)
+ .Case("sandybridge", CK_SandyBridge)
+ .Case("corei7-avx", CK_SandyBridge) // Legacy name.
+ .Case("ivybridge", CK_IvyBridge)
+ .Case("core-avx-i", CK_IvyBridge) // Legacy name.
+ .Case("haswell", CK_Haswell)
+ .Case("core-avx2", CK_Haswell) // Legacy name.
+ .Case("broadwell", CK_Broadwell)
+ .Case("skylake", CK_Skylake)
+ .Case("skx", CK_Skylake) // Legacy name.
+ .Case("knl", CK_KNL)
+ .Case("k6", CK_K6)
+ .Case("k6-2", CK_K6_2)
+ .Case("k6-3", CK_K6_3)
+ .Case("athlon", CK_Athlon)
+ .Case("athlon-tbird", CK_AthlonThunderbird)
+ .Case("athlon-4", CK_Athlon4)
+ .Case("athlon-xp", CK_AthlonXP)
+ .Case("athlon-mp", CK_AthlonMP)
+ .Case("athlon64", CK_Athlon64)
+ .Case("athlon64-sse3", CK_Athlon64SSE3)
+ .Case("athlon-fx", CK_AthlonFX)
+ .Case("k8", CK_K8)
+ .Case("k8-sse3", CK_K8SSE3)
+ .Case("opteron", CK_Opteron)
+ .Case("opteron-sse3", CK_OpteronSSE3)
+ .Case("barcelona", CK_AMDFAM10)
+ .Case("amdfam10", CK_AMDFAM10)
+ .Case("btver1", CK_BTVER1)
+ .Case("btver2", CK_BTVER2)
+ .Case("bdver1", CK_BDVER1)
+ .Case("bdver2", CK_BDVER2)
+ .Case("bdver3", CK_BDVER3)
+ .Case("bdver4", CK_BDVER4)
+ .Case("x86-64", CK_x86_64)
+ .Case("geode", CK_Geode)
+ .Default(CK_Generic);
+ }
enum FPMathKind {
FP_Default,
FP_SSE,
FP_387
- } FPMath;
+ } FPMath = FP_Default;
public:
- X86TargetInfo(const llvm::Triple &Triple)
- : TargetInfo(Triple), SSELevel(NoSSE), MMX3DNowLevel(NoMMX3DNow),
- XOPLevel(NoXOP), HasAES(false), HasPCLMUL(false), HasLZCNT(false),
- HasRDRND(false), HasFSGSBASE(false), HasBMI(false), HasBMI2(false),
- HasPOPCNT(false), HasRTM(false), HasPRFCHW(false), HasRDSEED(false),
- HasADX(false), HasTBM(false), HasFMA(false), HasF16C(false),
- HasAVX512CD(false), HasAVX512ER(false), HasAVX512PF(false),
- HasAVX512DQ(false), HasAVX512BW(false), HasAVX512VL(false),
- HasSHA(false), HasCX16(false), CPU(CK_Generic), FPMath(FP_Default) {
+ X86TargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
BigEndian = false;
LongDoubleFormat = &llvm::APFloat::x87DoubleExtended;
}
@@ -2245,30 +2366,37 @@ public:
// X87 evaluates with 80 bits "long double" precision.
return SSELevel == NoSSE ? 2 : 0;
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin;
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin);
}
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+ ArrayRef<const char *> getGCCRegNames() const override {
+ return llvm::makeArrayRef(GCCRegNames);
}
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {
- Aliases = nullptr;
- NumAliases = 0;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
}
- void getGCCAddlRegNames(const AddlRegName *&Names,
- unsigned &NumNames) const override {
- Names = AddlRegNames;
- NumNames = llvm::array_lengthof(AddlRegNames);
+ ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override {
+ return llvm::makeArrayRef(AddlRegNames);
}
bool validateCpuSupports(StringRef Name) const override;
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override;
+ bool validateGlobalRegisterVariable(StringRef RegName,
+ unsigned RegSize,
+ bool &HasSizeMismatch) const override {
+ // esp and ebp are the only 32-bit registers the x86 backend can currently
+ // handle.
+ if (RegName.equals("esp") || RegName.equals("ebp")) {
+ // Check that the register size is 32-bit.
+ HasSizeMismatch = RegSize != 32;
+ return true;
+ }
+
+ return false;
+ }
+
bool validateOutputSize(StringRef Constraint, unsigned Size) const override;
bool validateInputSize(StringRef Constraint, unsigned Size) const override;
@@ -2292,90 +2420,28 @@ public:
setFeatureEnabledImpl(Features, Name, Enabled);
}
// This exists purely to cut down on the number of virtual calls in
- // getDefaultFeatures which calls this repeatedly.
+ // initFeatureMap which calls this repeatedly.
static void setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
StringRef Name, bool Enabled);
- void getDefaultFeatures(llvm::StringMap<bool> &Features) const override;
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override;
bool hasFeature(StringRef Feature) const override;
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;
StringRef getABI() const override {
if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX512F)
return "avx512";
- else if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX)
+ if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX)
return "avx";
- else if (getTriple().getArch() == llvm::Triple::x86 &&
+ if (getTriple().getArch() == llvm::Triple::x86 &&
MMX3DNowLevel == NoMMX3DNow)
return "no-mmx";
return "";
}
bool setCPU(const std::string &Name) override {
- CPU = llvm::StringSwitch<CPUKind>(Name)
- .Case("i386", CK_i386)
- .Case("i486", CK_i486)
- .Case("winchip-c6", CK_WinChipC6)
- .Case("winchip2", CK_WinChip2)
- .Case("c3", CK_C3)
- .Case("i586", CK_i586)
- .Case("pentium", CK_Pentium)
- .Case("pentium-mmx", CK_PentiumMMX)
- .Case("i686", CK_i686)
- .Case("pentiumpro", CK_PentiumPro)
- .Case("pentium2", CK_Pentium2)
- .Case("pentium3", CK_Pentium3)
- .Case("pentium3m", CK_Pentium3M)
- .Case("pentium-m", CK_PentiumM)
- .Case("c3-2", CK_C3_2)
- .Case("yonah", CK_Yonah)
- .Case("pentium4", CK_Pentium4)
- .Case("pentium4m", CK_Pentium4M)
- .Case("prescott", CK_Prescott)
- .Case("nocona", CK_Nocona)
- .Case("core2", CK_Core2)
- .Case("penryn", CK_Penryn)
- .Case("bonnell", CK_Bonnell)
- .Case("atom", CK_Bonnell) // Legacy name.
- .Case("silvermont", CK_Silvermont)
- .Case("slm", CK_Silvermont) // Legacy name.
- .Case("nehalem", CK_Nehalem)
- .Case("corei7", CK_Nehalem) // Legacy name.
- .Case("westmere", CK_Westmere)
- .Case("sandybridge", CK_SandyBridge)
- .Case("corei7-avx", CK_SandyBridge) // Legacy name.
- .Case("ivybridge", CK_IvyBridge)
- .Case("core-avx-i", CK_IvyBridge) // Legacy name.
- .Case("haswell", CK_Haswell)
- .Case("core-avx2", CK_Haswell) // Legacy name.
- .Case("broadwell", CK_Broadwell)
- .Case("skylake", CK_Skylake)
- .Case("skx", CK_Skylake) // Legacy name.
- .Case("knl", CK_KNL)
- .Case("k6", CK_K6)
- .Case("k6-2", CK_K6_2)
- .Case("k6-3", CK_K6_3)
- .Case("athlon", CK_Athlon)
- .Case("athlon-tbird", CK_AthlonThunderbird)
- .Case("athlon-4", CK_Athlon4)
- .Case("athlon-xp", CK_AthlonXP)
- .Case("athlon-mp", CK_AthlonMP)
- .Case("athlon64", CK_Athlon64)
- .Case("athlon64-sse3", CK_Athlon64SSE3)
- .Case("athlon-fx", CK_AthlonFX)
- .Case("k8", CK_K8)
- .Case("k8-sse3", CK_K8SSE3)
- .Case("opteron", CK_Opteron)
- .Case("opteron-sse3", CK_OpteronSSE3)
- .Case("barcelona", CK_AMDFAM10)
- .Case("amdfam10", CK_AMDFAM10)
- .Case("btver1", CK_BTVER1)
- .Case("btver2", CK_BTVER2)
- .Case("bdver1", CK_BDVER1)
- .Case("bdver2", CK_BDVER2)
- .Case("bdver3", CK_BDVER3)
- .Case("bdver4", CK_BDVER4)
- .Case("x86-64", CK_x86_64)
- .Case("geode", CK_Geode)
- .Default(CK_Generic);
+ CPU = getCPUKind(Name);
// Perform any per-CPU checks necessary to determine if this CPU is
// acceptable.
@@ -2486,14 +2552,15 @@ bool X86TargetInfo::setFPMath(StringRef Name) {
return false;
}
-void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
+bool X86TargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
// FIXME: This *really* should not be here.
-
// X86_64 always has SSE2.
if (getTriple().getArch() == llvm::Triple::x86_64)
setFeatureEnabledImpl(Features, "sse2", true);
- switch (CPU) {
+ switch (getCPUKind(CPU)) {
case CK_Generic:
case CK_i386:
case CK_i486:
@@ -2512,26 +2579,31 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
case CK_Pentium3M:
case CK_C3_2:
setFeatureEnabledImpl(Features, "sse", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
break;
case CK_PentiumM:
case CK_Pentium4:
case CK_Pentium4M:
case CK_x86_64:
setFeatureEnabledImpl(Features, "sse2", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
break;
case CK_Yonah:
case CK_Prescott:
case CK_Nocona:
setFeatureEnabledImpl(Features, "sse3", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
setFeatureEnabledImpl(Features, "cx16", true);
break;
case CK_Core2:
case CK_Bonnell:
setFeatureEnabledImpl(Features, "ssse3", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
setFeatureEnabledImpl(Features, "cx16", true);
break;
case CK_Penryn:
setFeatureEnabledImpl(Features, "sse4.1", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
setFeatureEnabledImpl(Features, "cx16", true);
break;
case CK_Skylake:
@@ -2540,6 +2612,9 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
setFeatureEnabledImpl(Features, "avx512dq", true);
setFeatureEnabledImpl(Features, "avx512bw", true);
setFeatureEnabledImpl(Features, "avx512vl", true);
+ setFeatureEnabledImpl(Features, "xsavec", true);
+ setFeatureEnabledImpl(Features, "xsaves", true);
+ setFeatureEnabledImpl(Features, "pku", true);
// FALLTHROUGH
case CK_Broadwell:
setFeatureEnabledImpl(Features, "rdseed", true);
@@ -2560,6 +2635,8 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
// FALLTHROUGH
case CK_SandyBridge:
setFeatureEnabledImpl(Features, "avx", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
// FALLTHROUGH
case CK_Westmere:
case CK_Silvermont:
@@ -2568,6 +2645,7 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
// FALLTHROUGH
case CK_Nehalem:
setFeatureEnabledImpl(Features, "sse4.2", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
setFeatureEnabledImpl(Features, "cx16", true);
break;
case CK_KNL:
@@ -2575,6 +2653,7 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
setFeatureEnabledImpl(Features, "avx512cd", true);
setFeatureEnabledImpl(Features, "avx512er", true);
setFeatureEnabledImpl(Features, "avx512pf", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
setFeatureEnabledImpl(Features, "rdseed", true);
setFeatureEnabledImpl(Features, "adx", true);
setFeatureEnabledImpl(Features, "lzcnt", true);
@@ -2588,6 +2667,8 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
setFeatureEnabledImpl(Features, "aes", true);
setFeatureEnabledImpl(Features, "pclmul", true);
setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
break;
case CK_K6_2:
case CK_K6_3:
@@ -2605,6 +2686,7 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
case CK_AthlonMP:
setFeatureEnabledImpl(Features, "sse", true);
setFeatureEnabledImpl(Features, "3dnowa", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
break;
case CK_K8:
case CK_Opteron:
@@ -2612,6 +2694,7 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
case CK_AthlonFX:
setFeatureEnabledImpl(Features, "sse2", true);
setFeatureEnabledImpl(Features, "3dnowa", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
break;
case CK_AMDFAM10:
setFeatureEnabledImpl(Features, "sse4a", true);
@@ -2623,6 +2706,7 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
case CK_Athlon64SSE3:
setFeatureEnabledImpl(Features, "sse3", true);
setFeatureEnabledImpl(Features, "3dnowa", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
break;
case CK_BTVER2:
setFeatureEnabledImpl(Features, "avx", true);
@@ -2630,6 +2714,7 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
setFeatureEnabledImpl(Features, "pclmul", true);
setFeatureEnabledImpl(Features, "bmi", true);
setFeatureEnabledImpl(Features, "f16c", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
// FALLTHROUGH
case CK_BTVER1:
setFeatureEnabledImpl(Features, "ssse3", true);
@@ -2638,6 +2723,8 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
setFeatureEnabledImpl(Features, "popcnt", true);
setFeatureEnabledImpl(Features, "prfchw", true);
setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
break;
case CK_BDVER4:
setFeatureEnabledImpl(Features, "avx2", true);
@@ -2645,6 +2732,7 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
// FALLTHROUGH
case CK_BDVER3:
setFeatureEnabledImpl(Features, "fsgsbase", true);
+ setFeatureEnabledImpl(Features, "xsaveopt", true);
// FALLTHROUGH
case CK_BDVER2:
setFeatureEnabledImpl(Features, "bmi", true);
@@ -2660,8 +2748,39 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
setFeatureEnabledImpl(Features, "pclmul", true);
setFeatureEnabledImpl(Features, "prfchw", true);
setFeatureEnabledImpl(Features, "cx16", true);
+ setFeatureEnabledImpl(Features, "fxsr", true);
+ setFeatureEnabledImpl(Features, "xsave", true);
break;
}
+ if (!TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec))
+ return false;
+
+ // Can't do this earlier because we need to be able to explicitly enable
+ // or disable these features and the things that they depend upon.
+
+ // Enable popcnt if sse4.2 is enabled and popcnt is not explicitly disabled.
+ auto I = Features.find("sse4.2");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-popcnt") ==
+ FeaturesVec.end())
+ Features["popcnt"] = true;
+
+ // Enable prfchw if 3DNow! is enabled and prfchw is not explicitly disabled.
+ I = Features.find("3dnow");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-prfchw") ==
+ FeaturesVec.end())
+ Features["prfchw"] = true;
+
+ // Additionally, if SSE is enabled and mmx is not explicitly disabled,
+ // then enable MMX.
+ I = Features.find("sse");
+ if (I != Features.end() && I->getValue() &&
+ std::find(FeaturesVec.begin(), FeaturesVec.end(), "-mmx") ==
+ FeaturesVec.end())
+ Features["mmx"] = true;
+
+ return true;
}
void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features,
@@ -2674,6 +2793,7 @@ void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features,
Features["avx2"] = true;
case AVX:
Features["avx"] = true;
+ Features["xsave"] = true;
case SSE42:
Features["sse4.2"] = true;
case SSE41:
@@ -2709,7 +2829,8 @@ void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features,
case SSE42:
Features["sse4.2"] = false;
case AVX:
- Features["fma"] = Features["avx"] = Features["f16c"] = false;
+ Features["fma"] = Features["avx"] = Features["f16c"] = Features["xsave"] =
+ Features["xsaveopt"] = false;
setXOPLevel(Features, FMA4, false);
case AVX2:
Features["avx2"] = false;
@@ -2842,6 +2963,16 @@ void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
setSSELevel(Features, SSE42, Enabled);
else
setSSELevel(Features, SSE41, Enabled);
+ } else if (Name == "xsave") {
+ if (Enabled)
+ setSSELevel(Features, AVX, Enabled);
+ else
+ Features["xsaveopt"] = false;
+ } else if (Name == "xsaveopt" || Name == "xsavec" || Name == "xsaves") {
+ if (Enabled) {
+ Features["xsave"] = true;
+ setSSELevel(Features, AVX, Enabled);
+ }
}
}
@@ -2849,198 +2980,110 @@ void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
/// configured set of features.
bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) {
- // Remember the maximum enabled sselevel.
- for (unsigned i = 0, e = Features.size(); i !=e; ++i) {
- // Ignore disabled features.
- if (Features[i][0] == '-')
+ for (const auto &Feature : Features) {
+ if (Feature[0] != '+')
continue;
- StringRef Feature = StringRef(Features[i]).substr(1);
-
- if (Feature == "aes") {
+ if (Feature == "+aes") {
HasAES = true;
- continue;
- }
-
- if (Feature == "pclmul") {
+ } else if (Feature == "+pclmul") {
HasPCLMUL = true;
- continue;
- }
-
- if (Feature == "lzcnt") {
+ } else if (Feature == "+lzcnt") {
HasLZCNT = true;
- continue;
- }
-
- if (Feature == "rdrnd") {
+ } else if (Feature == "+rdrnd") {
HasRDRND = true;
- continue;
- }
-
- if (Feature == "fsgsbase") {
+ } else if (Feature == "+fsgsbase") {
HasFSGSBASE = true;
- continue;
- }
-
- if (Feature == "bmi") {
+ } else if (Feature == "+bmi") {
HasBMI = true;
- continue;
- }
-
- if (Feature == "bmi2") {
+ } else if (Feature == "+bmi2") {
HasBMI2 = true;
- continue;
- }
-
- if (Feature == "popcnt") {
+ } else if (Feature == "+popcnt") {
HasPOPCNT = true;
- continue;
- }
-
- if (Feature == "rtm") {
+ } else if (Feature == "+rtm") {
HasRTM = true;
- continue;
- }
-
- if (Feature == "prfchw") {
+ } else if (Feature == "+prfchw") {
HasPRFCHW = true;
- continue;
- }
-
- if (Feature == "rdseed") {
+ } else if (Feature == "+rdseed") {
HasRDSEED = true;
- continue;
- }
-
- if (Feature == "adx") {
+ } else if (Feature == "+adx") {
HasADX = true;
- continue;
- }
-
- if (Feature == "tbm") {
+ } else if (Feature == "+tbm") {
HasTBM = true;
- continue;
- }
-
- if (Feature == "fma") {
+ } else if (Feature == "+fma") {
HasFMA = true;
- continue;
- }
-
- if (Feature == "f16c") {
+ } else if (Feature == "+f16c") {
HasF16C = true;
- continue;
- }
-
- if (Feature == "avx512cd") {
+ } else if (Feature == "+avx512cd") {
HasAVX512CD = true;
- continue;
- }
-
- if (Feature == "avx512er") {
+ } else if (Feature == "+avx512er") {
HasAVX512ER = true;
- continue;
- }
-
- if (Feature == "avx512pf") {
+ } else if (Feature == "+avx512pf") {
HasAVX512PF = true;
- continue;
- }
-
- if (Feature == "avx512dq") {
+ } else if (Feature == "+avx512dq") {
HasAVX512DQ = true;
- continue;
- }
-
- if (Feature == "avx512bw") {
+ } else if (Feature == "+avx512bw") {
HasAVX512BW = true;
- continue;
- }
-
- if (Feature == "avx512vl") {
+ } else if (Feature == "+avx512vl") {
HasAVX512VL = true;
- continue;
- }
-
- if (Feature == "sha") {
+ } else if (Feature == "+sha") {
HasSHA = true;
- continue;
- }
-
- if (Feature == "cx16") {
+ } else if (Feature == "+cx16") {
HasCX16 = true;
- continue;
+ } else if (Feature == "+fxsr") {
+ HasFXSR = true;
+ } else if (Feature == "+xsave") {
+ HasXSAVE = true;
+ } else if (Feature == "+xsaveopt") {
+ HasXSAVEOPT = true;
+ } else if (Feature == "+xsavec") {
+ HasXSAVEC = true;
+ } else if (Feature == "+xsaves") {
+ HasXSAVES = true;
+ } else if (Feature == "+pku") {
+ HasPKU = true;
}
- assert(Features[i][0] == '+' && "Invalid target feature!");
X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature)
- .Case("avx512f", AVX512F)
- .Case("avx2", AVX2)
- .Case("avx", AVX)
- .Case("sse4.2", SSE42)
- .Case("sse4.1", SSE41)
- .Case("ssse3", SSSE3)
- .Case("sse3", SSE3)
- .Case("sse2", SSE2)
- .Case("sse", SSE1)
+ .Case("+avx512f", AVX512F)
+ .Case("+avx2", AVX2)
+ .Case("+avx", AVX)
+ .Case("+sse4.2", SSE42)
+ .Case("+sse4.1", SSE41)
+ .Case("+ssse3", SSSE3)
+ .Case("+sse3", SSE3)
+ .Case("+sse2", SSE2)
+ .Case("+sse", SSE1)
.Default(NoSSE);
SSELevel = std::max(SSELevel, Level);
MMX3DNowEnum ThreeDNowLevel =
llvm::StringSwitch<MMX3DNowEnum>(Feature)
- .Case("3dnowa", AMD3DNowAthlon)
- .Case("3dnow", AMD3DNow)
- .Case("mmx", MMX)
+ .Case("+3dnowa", AMD3DNowAthlon)
+ .Case("+3dnow", AMD3DNow)
+ .Case("+mmx", MMX)
.Default(NoMMX3DNow);
MMX3DNowLevel = std::max(MMX3DNowLevel, ThreeDNowLevel);
XOPEnum XLevel = llvm::StringSwitch<XOPEnum>(Feature)
- .Case("xop", XOP)
- .Case("fma4", FMA4)
- .Case("sse4a", SSE4A)
+ .Case("+xop", XOP)
+ .Case("+fma4", FMA4)
+ .Case("+sse4a", SSE4A)
.Default(NoXOP);
XOPLevel = std::max(XOPLevel, XLevel);
}
- // Enable popcnt if sse4.2 is enabled and popcnt is not explicitly disabled.
- // Can't do this earlier because we need to be able to explicitly enable
- // popcnt and still disable sse4.2.
- if (!HasPOPCNT && SSELevel >= SSE42 &&
- std::find(Features.begin(), Features.end(), "-popcnt") == Features.end()){
- HasPOPCNT = true;
- Features.push_back("+popcnt");
- }
-
- // Enable prfchw if 3DNow! is enabled and prfchw is not explicitly disabled.
- if (!HasPRFCHW && MMX3DNowLevel >= AMD3DNow &&
- std::find(Features.begin(), Features.end(), "-prfchw") == Features.end()){
- HasPRFCHW = true;
- Features.push_back("+prfchw");
- }
-
// LLVM doesn't have a separate switch for fpmath, so only accept it if it
// matches the selected sse level.
- if (FPMath == FP_SSE && SSELevel < SSE1) {
- Diags.Report(diag::err_target_unsupported_fpmath) << "sse";
- return false;
- } else if (FPMath == FP_387 && SSELevel >= SSE1) {
- Diags.Report(diag::err_target_unsupported_fpmath) << "387";
+ if ((FPMath == FP_SSE && SSELevel < SSE1) ||
+ (FPMath == FP_387 && SSELevel >= SSE1)) {
+ Diags.Report(diag::err_target_unsupported_fpmath) <<
+ (FPMath == FP_SSE ? "sse" : "387");
return false;
}
- // Don't tell the backend if we're turning off mmx; it will end up disabling
- // SSE, which we don't want.
- // Additionally, if SSE is enabled and mmx is not explicitly disabled,
- // then enable MMX.
- std::vector<std::string>::iterator it;
- it = std::find(Features.begin(), Features.end(), "-mmx");
- if (it != Features.end())
- Features.erase(it);
- else if (SSELevel > NoSSE)
- MMX3DNowLevel = std::max(MMX3DNowLevel, MMX);
-
SimdDefaultAlign =
- (getABI() == "avx512") ? 512 : (getABI() == "avx") ? 256 : 128;
+ hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
return true;
}
@@ -3290,6 +3333,18 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasSHA)
Builder.defineMacro("__SHA__");
+ if (HasFXSR)
+ Builder.defineMacro("__FXSR__");
+ if (HasXSAVE)
+ Builder.defineMacro("__XSAVE__");
+ if (HasXSAVEOPT)
+ Builder.defineMacro("__XSAVEOPT__");
+ if (HasXSAVEC)
+ Builder.defineMacro("__XSAVEC__");
+ if (HasXSAVES)
+ Builder.defineMacro("__XSAVES__");
+ if (HasPKU)
+ Builder.defineMacro("__PKU__");
if (HasCX16)
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
@@ -3379,6 +3434,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("fma", HasFMA)
.Case("fma4", XOPLevel >= FMA4)
.Case("fsgsbase", HasFSGSBASE)
+ .Case("fxsr", HasFXSR)
.Case("lzcnt", HasLZCNT)
.Case("mm3dnow", MMX3DNowLevel >= AMD3DNow)
.Case("mm3dnowa", MMX3DNowLevel >= AMD3DNowAthlon)
@@ -3402,6 +3458,11 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("x86_32", getTriple().getArch() == llvm::Triple::x86)
.Case("x86_64", getTriple().getArch() == llvm::Triple::x86_64)
.Case("xop", XOPLevel >= XOP)
+ .Case("xsave", HasXSAVE)
+ .Case("xsavec", HasXSAVEC)
+ .Case("xsaves", HasXSAVES)
+ .Case("xsaveopt", HasXSAVEOPT)
+ .Case("pku", HasPKU)
.Default(false);
}
@@ -3437,6 +3498,14 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const {
switch (*Name) {
default: return false;
+ // Constant constraints.
+ case 'e': // 32-bit signed integer constant for use with sign-extending x86_64
+ // instructions.
+ case 'Z': // 32-bit unsigned integer constant for use with zero-extending
+ // x86_64 instructions.
+ case 's':
+ Info.setRequiresImmediate();
+ return true;
case 'I':
Info.setRequiresImmediate(0, 31);
return true;
@@ -3447,8 +3516,7 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
Info.setRequiresImmediate(-128, 127);
return true;
case 'L':
- // FIXME: properly analyze this constraint:
- // must be one of 0xff, 0xffff, or 0xffffffff
+ Info.setRequiresImmediate({ int(0xff), int(0xffff), int(0xffffffff) });
return true;
case 'M':
Info.setRequiresImmediate(0, 3);
@@ -3459,20 +3527,24 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
case 'O':
Info.setRequiresImmediate(0, 127);
return true;
- case 'Y': // first letter of a pair:
- switch (*(Name+1)) {
- default: return false;
- case '0': // First SSE register.
- case 't': // Any SSE register, when SSE2 is enabled.
- case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
- case 'm': // any MMX register, when inter-unit moves enabled.
- break; // falls through to setAllowsRegister.
- }
- case 'f': // any x87 floating point stack register.
+ // Register constraints.
+ case 'Y': // 'Y' is the first character for several 2-character constraints.
+ // Shift the pointer to the second character of the constraint.
+ Name++;
+ switch (*Name) {
+ default:
+ return false;
+ case '0': // First SSE register.
+ case 't': // Any SSE register, when SSE2 is enabled.
+ case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
+ case 'm': // Any MMX register, when inter-unit moves enabled.
+ Info.setAllowsRegister();
+ return true;
+ }
+ case 'f': // Any x87 floating point stack register.
// Constraint 'f' cannot be used for output operands.
if (Info.ConstraintStr[0] == '=')
return false;
-
Info.setAllowsRegister();
return true;
case 'a': // eax.
@@ -3482,8 +3554,8 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
case 'S': // esi.
case 'D': // edi.
case 'A': // edx:eax.
- case 't': // top of floating point stack.
- case 'u': // second from top of floating point stack.
+ case 't': // Top of floating point stack.
+ case 'u': // Second from top of floating point stack.
case 'q': // Any register accessible as [r]l: a, b, c, and d.
case 'y': // Any MMX register.
case 'x': // Any SSE register.
@@ -3493,12 +3565,9 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
// index in a base+index memory access.
Info.setAllowsRegister();
return true;
+ // Floating point constant constraints.
case 'C': // SSE floating point constant.
case 'G': // x87 floating point constant.
- case 'e': // 32-bit signed integer constant for use with zero-extending
- // x86_64 instructions.
- case 'Z': // 32-bit unsigned integer constant for use with zero-extending
- // x86_64 instructions.
return true;
}
}
@@ -3530,8 +3599,30 @@ bool X86TargetInfo::validateOperandSize(StringRef Constraint,
case 'u':
return Size <= 128;
case 'x':
- // 256-bit ymm registers can be used if target supports AVX.
- return Size <= (SSELevel >= AVX ? 256U : 128U);
+ if (SSELevel >= AVX512F)
+ // 512-bit zmm registers can be used if target supports AVX512F.
+ return Size <= 512U;
+ else if (SSELevel >= AVX)
+ // 256-bit ymm registers can be used if target supports AVX.
+ return Size <= 256U;
+ return Size <= 128U;
+ case 'Y':
+ // 'Y' is the first character for several 2-character constraints.
+ switch (Constraint[1]) {
+ default: break;
+ case 'm':
+ // 'Ym' is synonymous with 'y'.
+ return Size <= 64;
+ case 'i':
+ case 't':
+ // 'Yi' and 'Yt' are synonymous with 'x' when SSE2 is enabled.
+ if (SSELevel >= AVX512F)
+ return Size <= 512U;
+ else if (SSELevel >= AVX)
+ return Size <= 256U;
+ return SSELevel >= SSE2 && Size <= 128U;
+ }
+
}
return true;
@@ -3565,7 +3656,7 @@ public:
LongDoubleWidth = 96;
LongDoubleAlign = 32;
SuitableAlign = 128;
- DescriptionString = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128";
+ DataLayoutString = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128";
SizeType = UnsignedInt;
PtrDiffType = SignedInt;
IntPtrType = SignedInt;
@@ -3656,12 +3747,26 @@ public:
LongDoubleAlign = 128;
SuitableAlign = 128;
MaxVectorAlign = 256;
+ // The watchOS simulator uses the builtin bool type for Objective-C.
+ llvm::Triple T = llvm::Triple(Triple);
+ if (T.isWatchOS())
+ UseSignedCharForObjCBool = false;
SizeType = UnsignedLong;
IntPtrType = SignedLong;
- DescriptionString = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128";
+ DataLayoutString = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128";
HasAlignMac68kSupport = true;
}
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ if (!DarwinTargetInfo<X86_32TargetInfo>::handleTargetFeatures(Features,
+ Diags))
+ return false;
+ // We now know the features we have: we can decide how to align vectors.
+ MaxVectorAlign =
+ hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
+ return true;
+ }
};
// x86-32 Windows target
@@ -3673,9 +3778,9 @@ public:
DoubleAlign = LongLongAlign = 64;
bool IsWinCOFF =
getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
- DescriptionString = IsWinCOFF
- ? "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
- : "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32";
+ DataLayoutString = IsWinCOFF
+ ? "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+ : "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32";
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
@@ -3701,12 +3806,11 @@ public:
Builder.defineMacro("_M_IX86", "600");
}
};
-} // end anonymous namespace
static void addCygMingDefines(const LangOptions &Opts, MacroBuilder &Builder) {
- // Mingw and cygwin define __declspec(a) to __attribute__((a)). Clang supports
- // __declspec natively under -fms-extensions, but we define a no-op __declspec
- // macro anyway for pre-processor compatibility.
+ // Mingw and cygwin define __declspec(a) to __attribute__((a)). Clang
+ // supports __declspec natively under -fms-extensions, but we define a no-op
+ // __declspec macro anyway for pre-processor compatibility.
if (Opts.MicrosoftExt)
Builder.defineMacro("__declspec", "__declspec");
else
@@ -3733,7 +3837,6 @@ static void addMinGWDefines(const LangOptions &Opts, MacroBuilder &Builder) {
addCygMingDefines(Opts, Builder);
}
-namespace {
// x86-32 MinGW target
class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo {
public:
@@ -3754,10 +3857,9 @@ class CygwinX86_32TargetInfo : public X86_32TargetInfo {
public:
CygwinX86_32TargetInfo(const llvm::Triple &Triple)
: X86_32TargetInfo(Triple) {
- TLSSupported = false;
WCharType = UnsignedShort;
DoubleAlign = LongLongAlign = 64;
- DescriptionString = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32";
+ DataLayoutString = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32";
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
@@ -3791,6 +3893,27 @@ public:
}
};
+// X86-32 MCU target
+class MCUX86_32TargetInfo : public X86_32TargetInfo {
+public:
+ MCUX86_32TargetInfo(const llvm::Triple &Triple) : X86_32TargetInfo(Triple) {
+ LongDoubleWidth = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ }
+
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ // On MCU we support only C calling convention.
+ return CC == CC_C ? CCCR_OK : CCCR_Warning;
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ X86_32TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__iamcu");
+ Builder.defineMacro("__iamcu__");
+ }
+};
+
// RTEMS Target
template<typename Target>
class RTEMSTargetInfo : public OSTargetInfo<Target> {
@@ -3864,10 +3987,10 @@ public:
RegParmMax = 6;
// Pointers are 32-bit in x32.
- DescriptionString = IsX32 ? "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128"
- : IsWinCOFF
- ? "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
- : "e-m:e-i64:64-f80:128-n8:16:32:64-S128";
+ DataLayoutString = IsX32 ? "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128"
+ : IsWinCOFF
+ ? "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+ : "e-m:e-i64:64-f80:128-n8:16:32:64-S128";
// Use fpret only for long double.
RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble);
@@ -3875,6 +3998,9 @@ public:
// Use fp2ret for _Complex long double.
ComplexLongDoubleUsesFP2Ret = true;
+ // Make __builtin_ms_va_list available.
+ HasBuiltinMSVaList = true;
+
// x86-64 has atomics up to 16 bytes.
MaxAtomicPromoteWidth = 128;
MaxAtomicInlineWidth = 128;
@@ -3902,6 +4028,22 @@ public:
// for x32 we need it here explicitly
bool hasInt128Type() const override { return true; }
+
+ bool validateGlobalRegisterVariable(StringRef RegName,
+ unsigned RegSize,
+ bool &HasSizeMismatch) const override {
+ // rsp and rbp are the only 64-bit registers the x86 backend can currently
+ // handle.
+ if (RegName.equals("rsp") || RegName.equals("rbp")) {
+ // Check that the register size is 64-bit.
+ HasSizeMismatch = RegSize != 64;
+ return true;
+ }
+
+ // Check if the register is a 32-bit register the backend can handle.
+ return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
+ HasSizeMismatch);
+ }
};
// x86-64 Windows target
@@ -3959,8 +4101,8 @@ public:
MacroBuilder &Builder) const override {
WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
WindowsX86_64TargetInfo::getVisualStudioDefines(Opts, Builder);
- Builder.defineMacro("_M_X64");
- Builder.defineMacro("_M_AMD64");
+ Builder.defineMacro("_M_X64", "100");
+ Builder.defineMacro("_M_AMD64", "100");
}
};
@@ -3988,17 +4130,52 @@ public:
}
};
+// x86-64 Cygwin target
+class CygwinX86_64TargetInfo : public X86_64TargetInfo {
+public:
+ CygwinX86_64TargetInfo(const llvm::Triple &Triple)
+ : X86_64TargetInfo(Triple) {
+ TLSSupported = false;
+ WCharType = UnsignedShort;
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ X86_64TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__x86_64__");
+ Builder.defineMacro("__CYGWIN__");
+ Builder.defineMacro("__CYGWIN64__");
+ addCygMingDefines(Opts, Builder);
+ DefineStd(Builder, "unix", Opts);
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+
+ // GCC defines this macro when it is using __gxx_personality_seh0.
+ if (!Opts.SjLjExceptions)
+ Builder.defineMacro("__SEH__");
+ }
+};
+
class DarwinX86_64TargetInfo : public DarwinTargetInfo<X86_64TargetInfo> {
public:
DarwinX86_64TargetInfo(const llvm::Triple &Triple)
: DarwinTargetInfo<X86_64TargetInfo>(Triple) {
Int64Type = SignedLongLong;
- MaxVectorAlign = 256;
// The 64-bit iOS simulator uses the builtin bool type for Objective-C.
llvm::Triple T = llvm::Triple(Triple);
if (T.isiOS())
UseSignedCharForObjCBool = false;
- DescriptionString = "e-m:o-i64:64-f80:128-n8:16:32:64-S128";
+ DataLayoutString = "e-m:o-i64:64-f80:128-n8:16:32:64-S128";
+ }
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override {
+ if (!DarwinTargetInfo<X86_64TargetInfo>::handleTargetFeatures(Features,
+ Diags))
+ return false;
+ // We now know the features we have: we can decide how to align vectors.
+ MaxVectorAlign =
+ hasFeature("avx512f") ? 512 : hasFeature("avx") ? 256 : 128;
+ return true;
}
};
@@ -4045,16 +4222,23 @@ class ARMTargetInfo : public TargetInfo {
std::string ABI, CPU;
+ StringRef CPUProfile;
+ StringRef CPUAttr;
+
enum {
FP_Default,
FP_VFP,
FP_Neon
} FPMath;
+ unsigned ArchISA;
+ unsigned ArchKind = llvm::ARM::AK_ARMV4T;
+ unsigned ArchProfile;
+ unsigned ArchVersion;
+
unsigned FPU : 5;
unsigned IsAAPCS : 1;
- unsigned IsThumb : 1;
unsigned HWDiv : 2;
// Initialized via features.
@@ -4063,6 +4247,17 @@ class ARMTargetInfo : public TargetInfo {
unsigned CRC : 1;
unsigned Crypto : 1;
+ unsigned DSP : 1;
+ unsigned Unaligned : 1;
+
+ enum {
+ LDREX_B = (1 << 0), /// byte (8-bit)
+ LDREX_H = (1 << 1), /// half (16-bit)
+ LDREX_W = (1 << 2), /// word (32-bit)
+ LDREX_D = (1 << 3), /// double (64-bit)
+ };
+
+ uint32_t LDREX;
// ACLE 6.5.1 Hardware floating point
enum {
@@ -4074,37 +4269,6 @@ class ARMTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
- static bool shouldUseInlineAtomic(const llvm::Triple &T) {
- StringRef ArchName = T.getArchName();
- if (T.getArch() == llvm::Triple::arm ||
- T.getArch() == llvm::Triple::armeb) {
- StringRef VersionStr;
- if (ArchName.startswith("armv"))
- VersionStr = ArchName.substr(4, 1);
- else if (ArchName.startswith("armebv"))
- VersionStr = ArchName.substr(6, 1);
- else
- return false;
- unsigned Version;
- if (VersionStr.getAsInteger(10, Version))
- return false;
- return Version >= 6;
- }
- assert(T.getArch() == llvm::Triple::thumb ||
- T.getArch() == llvm::Triple::thumbeb);
- StringRef VersionStr;
- if (ArchName.startswith("thumbv"))
- VersionStr = ArchName.substr(6, 1);
- else if (ArchName.startswith("thumbebv"))
- VersionStr = ArchName.substr(8, 1);
- else
- return false;
- unsigned Version;
- if (VersionStr.getAsInteger(10, Version))
- return false;
- return Version >= 7;
- }
-
void setABIAAPCS() {
IsAAPCS = true;
@@ -4139,24 +4303,24 @@ class ARMTargetInfo : public TargetInfo {
// Thumb1 add sp, #imm requires the immediate value be multiple of 4,
// so set preferred for small types to 32.
if (T.isOSBinFormatMachO()) {
- DescriptionString =
+ DataLayoutString =
BigEndian ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
: "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64";
} else if (T.isOSWindows()) {
assert(!BigEndian && "Windows on ARM does not support big endian");
- DescriptionString = "e"
- "-m:w"
- "-p:32:32"
- "-i64:64"
- "-v128:64:128"
- "-a:0:32"
- "-n32"
- "-S64";
+ DataLayoutString = "e"
+ "-m:w"
+ "-p:32:32"
+ "-i64:64"
+ "-v128:64:128"
+ "-a:0:32"
+ "-n32"
+ "-S64";
} else if (T.isOSNaCl()) {
assert(!BigEndian && "NaCl on ARM does not support big endian");
- DescriptionString = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128";
+ DataLayoutString = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128";
} else {
- DescriptionString =
+ DataLayoutString =
BigEndian ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64";
}
@@ -4164,12 +4328,15 @@ class ARMTargetInfo : public TargetInfo {
// FIXME: Enumerated types are variable width in straight AAPCS.
}
- void setABIAPCS() {
+ void setABIAPCS(bool IsAAPCS16) {
const llvm::Triple &T = getTriple();
IsAAPCS = false;
- DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
+ if (IsAAPCS16)
+ DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
+ else
+ DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
// size_t is unsigned int on FreeBSD.
if (T.getOS() == llvm::Triple::FreeBSD)
@@ -4189,13 +4356,16 @@ class ARMTargetInfo : public TargetInfo {
/// gcc.
ZeroLengthBitfieldBoundary = 32;
- if (T.isOSBinFormatMachO())
- DescriptionString =
+ if (T.isOSBinFormatMachO() && IsAAPCS16) {
+ assert(!BigEndian && "AAPCS16 does not support big-endian");
+ DataLayoutString = "e-m:o-p:32:32-i64:64-a:0:32-n32-S128";
+ } else if (T.isOSBinFormatMachO())
+ DataLayoutString =
BigEndian
? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32";
else
- DescriptionString =
+ DataLayoutString =
BigEndian
? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
: "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32";
@@ -4203,10 +4373,104 @@ class ARMTargetInfo : public TargetInfo {
// FIXME: Override "preferred align" for double and long long.
}
+ void setArchInfo() {
+ StringRef ArchName = getTriple().getArchName();
+
+ ArchISA = llvm::ARM::parseArchISA(ArchName);
+ CPU = llvm::ARM::getDefaultCPU(ArchName);
+ unsigned AK = llvm::ARM::parseArch(ArchName);
+ if (AK != llvm::ARM::AK_INVALID)
+ ArchKind = AK;
+ setArchInfo(ArchKind);
+ }
+
+ void setArchInfo(unsigned Kind) {
+ StringRef SubArch;
+
+ // cache TargetParser info
+ ArchKind = Kind;
+ SubArch = llvm::ARM::getSubArch(ArchKind);
+ ArchProfile = llvm::ARM::parseArchProfile(SubArch);
+ ArchVersion = llvm::ARM::parseArchVersion(SubArch);
+
+ // cache CPU related strings
+ CPUAttr = getCPUAttr();
+ CPUProfile = getCPUProfile();
+ }
+
+ void setAtomic() {
+ // when triple does not specify a sub arch,
+ // then we are not using inline atomics
+ bool ShouldUseInlineAtomic =
+ (ArchISA == llvm::ARM::IK_ARM && ArchVersion >= 6) ||
+ (ArchISA == llvm::ARM::IK_THUMB && ArchVersion >= 7);
+ // Cortex M does not support 8 byte atomics, while general Thumb2 does.
+ if (ArchProfile == llvm::ARM::PK_M) {
+ MaxAtomicPromoteWidth = 32;
+ if (ShouldUseInlineAtomic)
+ MaxAtomicInlineWidth = 32;
+ }
+ else {
+ MaxAtomicPromoteWidth = 64;
+ if (ShouldUseInlineAtomic)
+ MaxAtomicInlineWidth = 64;
+ }
+ }
+
+ bool isThumb() const {
+ return (ArchISA == llvm::ARM::IK_THUMB);
+ }
+
+ bool supportsThumb() const {
+ return CPUAttr.count('T') || ArchVersion >= 6;
+ }
+
+ bool supportsThumb2() const {
+ return CPUAttr.equals("6T2") || ArchVersion >= 7;
+ }
+
+ StringRef getCPUAttr() const {
+ // For most sub-arches, the build attribute CPU name is enough.
+ // For Cortex variants, it's slightly different.
+ switch(ArchKind) {
+ default:
+ return llvm::ARM::getCPUAttr(ArchKind);
+ case llvm::ARM::AK_ARMV6M:
+ return "6M";
+ case llvm::ARM::AK_ARMV7S:
+ return "7S";
+ case llvm::ARM::AK_ARMV7A:
+ return "7A";
+ case llvm::ARM::AK_ARMV7R:
+ return "7R";
+ case llvm::ARM::AK_ARMV7M:
+ return "7M";
+ case llvm::ARM::AK_ARMV7EM:
+ return "7EM";
+ case llvm::ARM::AK_ARMV8A:
+ return "8A";
+ case llvm::ARM::AK_ARMV8_1A:
+ return "8_1A";
+ }
+ }
+
+ StringRef getCPUProfile() const {
+ switch(ArchProfile) {
+ case llvm::ARM::PK_A:
+ return "A";
+ case llvm::ARM::PK_R:
+ return "R";
+ case llvm::ARM::PK_M:
+ return "M";
+ default:
+ return "";
+ }
+ }
+
public:
ARMTargetInfo(const llvm::Triple &Triple, bool IsBigEndian)
- : TargetInfo(Triple), CPU("arm1136j-s"), FPMath(FP_Default),
- IsAAPCS(true), HW_FP(0) {
+ : TargetInfo(Triple), FPMath(FP_Default),
+ IsAAPCS(true), LDREX(0), HW_FP(0) {
BigEndian = IsBigEndian;
switch (getTriple().getOS()) {
@@ -4218,13 +4482,13 @@ public:
break;
}
+ // Cache arch related info.
+ setArchInfo();
+
// {} in inline assembly are neon specifiers, not assembly variant
// specifiers.
NoAsmVariants = true;
- // FIXME: Should we just treat this as a feature?
- IsThumb = getTriple().getArchName().startswith("thumb");
-
// FIXME: This duplicates code from the driver that sets the -target-abi
// option - this code is used if -target-abi isn't passed and should
// be unified in some way.
@@ -4235,6 +4499,8 @@ public:
Triple.getOS() == llvm::Triple::UnknownOS ||
StringRef(CPU).startswith("cortex-m")) {
setABI("aapcs");
+ } else if (Triple.isWatchOS()) {
+ setABI("aapcs16");
} else {
setABI("apcs-gnu");
}
@@ -4254,8 +4520,8 @@ public:
setABI("aapcs");
break;
case llvm::Triple::GNU:
- setABI("apcs-gnu");
- break;
+ setABI("apcs-gnu");
+ break;
default:
if (Triple.getOS() == llvm::Triple::NetBSD)
setABI("apcs-gnu");
@@ -4269,9 +4535,7 @@ public:
TheCXXABI.set(TargetCXXABI::GenericARM);
// ARM has atomics up to 8 bytes
- MaxAtomicPromoteWidth = 64;
- if (shouldUseInlineAtomic(getTriple()))
- MaxAtomicInlineWidth = 64;
+ setAtomic();
// Do force alignment of members that follow zero length bitfields. If
// the alignment of the zero-length bitfield is greater than the member
@@ -4289,8 +4553,8 @@ public:
//
// FIXME: We need support for -meabi... we could just mangle it into the
// name.
- if (Name == "apcs-gnu") {
- setABIAPCS();
+ if (Name == "apcs-gnu" || Name == "aapcs16") {
+ setABIAPCS(Name == "aapcs16");
return true;
}
if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
@@ -4301,43 +4565,27 @@ public:
}
// FIXME: This should be based on Arch attributes, not CPU names.
- void getDefaultFeatures(llvm::StringMap<bool> &Features) const override {
- StringRef ArchName = getTriple().getArchName();
- unsigned ArchKind = llvm::ARMTargetParser::parseArch(ArchName);
- bool IsV8 = (ArchKind == llvm::ARM::AK_ARMV8A ||
- ArchKind == llvm::ARM::AK_ARMV8_1A);
-
- if (CPU == "arm1136jf-s" || CPU == "arm1176jzf-s" || CPU == "mpcore")
- Features["vfp2"] = true;
- else if (CPU == "cortex-a8" || CPU == "cortex-a9") {
- Features["vfp3"] = true;
- Features["neon"] = true;
- }
- else if (CPU == "cortex-a5") {
- Features["vfp4"] = true;
- Features["neon"] = true;
- } else if (CPU == "swift" || CPU == "cortex-a7" ||
- CPU == "cortex-a12" || CPU == "cortex-a15" ||
- CPU == "cortex-a17" || CPU == "krait") {
- Features["vfp4"] = true;
- Features["neon"] = true;
- Features["hwdiv"] = true;
- Features["hwdiv-arm"] = true;
- } else if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57" ||
- CPU == "cortex-a72") {
- Features["fp-armv8"] = true;
- Features["neon"] = true;
- Features["hwdiv"] = true;
- Features["hwdiv-arm"] = true;
- Features["crc"] = true;
- Features["crypto"] = true;
- } else if (CPU == "cortex-r5" || CPU == "cortex-r7" || IsV8) {
- Features["hwdiv"] = true;
- Features["hwdiv-arm"] = true;
- } else if (CPU == "cortex-m3" || CPU == "cortex-m4" || CPU == "cortex-m7" ||
- CPU == "sc300" || CPU == "cortex-r4" || CPU == "cortex-r4f") {
- Features["hwdiv"] = true;
- }
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
+
+ std::vector<const char*> TargetFeatures;
+ unsigned Arch = llvm::ARM::parseArch(getTriple().getArchName());
+
+ // get default FPU features
+ unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
+ llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
+
+ // get default Extension features
+ unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
+ llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
+
+ for (const char *Feature : TargetFeatures)
+ if (Feature[0] == '+')
+ Features[Feature+1] = true;
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
bool handleTargetFeatures(std::vector<std::string> &Features,
@@ -4345,6 +4593,8 @@ public:
FPU = 0;
CRC = 0;
Crypto = 0;
+ DSP = 0;
+ Unaligned = 1;
SoftFloat = SoftFloatABI = false;
HWDiv = 0;
@@ -4379,12 +4629,37 @@ public:
CRC = 1;
} else if (Feature == "+crypto") {
Crypto = 1;
+ } else if (Feature == "+dsp") {
+ DSP = 1;
} else if (Feature == "+fp-only-sp") {
- HW_FP_remove |= HW_FP_DP | HW_FP_HP;
+ HW_FP_remove |= HW_FP_DP;
+ } else if (Feature == "+strict-align") {
+ Unaligned = 0;
+ } else if (Feature == "+fp16") {
+ HW_FP |= HW_FP_HP;
}
}
HW_FP &= ~HW_FP_remove;
+ switch (ArchVersion) {
+ case 6:
+ if (ArchProfile == llvm::ARM::PK_M)
+ LDREX = 0;
+ else if (ArchKind == llvm::ARM::AK_ARMV6K)
+ LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B ;
+ else
+ LDREX = LDREX_W;
+ break;
+ case 7:
+ if (ArchProfile == llvm::ARM::PK_M)
+ LDREX = LDREX_W | LDREX_H | LDREX_B ;
+ else
+ LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B ;
+ break;
+ case 8:
+ LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B ;
+ }
+
if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
return false;
@@ -4407,107 +4682,28 @@ public:
bool hasFeature(StringRef Feature) const override {
return llvm::StringSwitch<bool>(Feature)
.Case("arm", true)
+ .Case("aarch32", true)
.Case("softfloat", SoftFloat)
- .Case("thumb", IsThumb)
+ .Case("thumb", isThumb())
.Case("neon", (FPU & NeonFPU) && !SoftFloat)
.Case("hwdiv", HWDiv & HWDivThumb)
.Case("hwdiv-arm", HWDiv & HWDivARM)
.Default(false);
}
- const char *getCPUDefineSuffix(StringRef Name) const {
- if(Name == "generic") {
- auto subarch = getTriple().getSubArch();
- switch (subarch) {
- case llvm::Triple::SubArchType::ARMSubArch_v8_1a:
- return "8_1A";
- default:
- break;
- }
- }
-
- unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(Name);
- if (ArchKind == llvm::ARM::AK_INVALID)
- return "";
-
- // For most sub-arches, the build attribute CPU name is enough.
- // For Cortex variants, it's slightly different.
- switch(ArchKind) {
- default:
- return llvm::ARMTargetParser::getCPUAttr(ArchKind);
- case llvm::ARM::AK_ARMV6M:
- case llvm::ARM::AK_ARMV6SM:
- return "6M";
- case llvm::ARM::AK_ARMV7:
- case llvm::ARM::AK_ARMV7A:
- case llvm::ARM::AK_ARMV7S:
- return "7A";
- case llvm::ARM::AK_ARMV7R:
- return "7R";
- case llvm::ARM::AK_ARMV7M:
- return "7M";
- case llvm::ARM::AK_ARMV7EM:
- return "7EM";
- case llvm::ARM::AK_ARMV8A:
- return "8A";
- case llvm::ARM::AK_ARMV8_1A:
- return "8_1A";
- }
- }
- const char *getCPUProfile(StringRef Name) const {
- if(Name == "generic") {
- auto subarch = getTriple().getSubArch();
- switch (subarch) {
- case llvm::Triple::SubArchType::ARMSubArch_v8_1a:
- return "A";
- default:
- break;
- }
- }
- unsigned CPUArch = llvm::ARMTargetParser::parseCPUArch(Name);
- if (CPUArch == llvm::ARM::AK_INVALID)
- return "";
-
- StringRef ArchName = llvm::ARMTargetParser::getArchName(CPUArch);
- switch(llvm::ARMTargetParser::parseArchProfile(ArchName)) {
- case llvm::ARM::PK_A:
- return "A";
- case llvm::ARM::PK_R:
- return "R";
- case llvm::ARM::PK_M:
- return "M";
- default:
- return "";
- }
- }
bool setCPU(const std::string &Name) override {
- if (!getCPUDefineSuffix(Name))
- return false;
-
- // Cortex M does not support 8 byte atomics, while general Thumb2 does.
- StringRef Profile = getCPUProfile(Name);
- if (Profile == "M" && MaxAtomicInlineWidth) {
- MaxAtomicPromoteWidth = 32;
- MaxAtomicInlineWidth = 32;
- }
+ if (Name != "generic")
+ setArchInfo(llvm::ARM::parseCPUArch(Name));
+ if (ArchKind == llvm::ARM::AK_INVALID)
+ return false;
+ setAtomic();
CPU = Name;
return true;
}
+
bool setFPMath(StringRef Name) override;
- bool supportsThumb(StringRef ArchName, StringRef CPUArch,
- unsigned CPUArchVer) const {
- return CPUArchVer >= 7 || (CPUArch.find('T') != StringRef::npos) ||
- (CPUArch.find('M') != StringRef::npos);
- }
- bool supportsThumb2(StringRef ArchName, StringRef CPUArch,
- unsigned CPUArchVer) const {
- // We check both CPUArchVer and ArchName because when only triple is
- // specified, the default CPU is arm1136j-s.
- return ArchName.endswith("v6t2") || ArchName.endswith("v7") ||
- ArchName.endswith("v8.1a") ||
- ArchName.endswith("v8") || CPUArch == "6T2" || CPUArchVer >= 7;
- }
+
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
// Target identification.
@@ -4517,21 +4713,29 @@ public:
// Target properties.
Builder.defineMacro("__REGISTER_PREFIX__", "");
- StringRef CPUArch = getCPUDefineSuffix(CPU);
- unsigned int CPUArchVer;
- if (CPUArch.substr(0, 1).getAsInteger<unsigned int>(10, CPUArchVer))
- llvm_unreachable("Invalid char for architecture version number");
- Builder.defineMacro("__ARM_ARCH_" + CPUArch + "__");
+ // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
+ // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
+ if (getTriple().isWatchOS())
+ Builder.defineMacro("__ARM_ARCH_7K__", "2");
- // ACLE 6.4.1 ARM/Thumb instruction set architecture
- StringRef CPUProfile = getCPUProfile(CPU);
- StringRef ArchName = getTriple().getArchName();
+ if (!CPUAttr.empty())
+ Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
+ // ACLE 6.4.1 ARM/Thumb instruction set architecture
// __ARM_ARCH is defined as an integer value indicating the current ARM ISA
- Builder.defineMacro("__ARM_ARCH", CPUArch.substr(0, 1));
- if (CPUArch[0] >= '8') {
- Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN");
- Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING");
+ Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
+
+ if (ArchVersion >= 8) {
+ // ACLE 6.5.7 Crypto Extension
+ if (Crypto)
+ Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
+ // ACLE 6.5.8 CRC32 Extension
+ if (CRC)
+ Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
+ // ACLE 6.5.10 Numeric Maximum and Minimum
+ Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
+ // ACLE 6.5.9 Directed Rounding
+ Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
}
// __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It
@@ -4543,9 +4747,9 @@ public:
// __ARM_ARCH_ISA_THUMB is defined to 1 if the core supporst the original
// Thumb ISA (including v6-M). It is set to 2 if the core supports the
// Thumb-2 ISA as found in the v6T2 architecture and all v7 architecture.
- if (supportsThumb2(ArchName, CPUArch, CPUArchVer))
+ if (supportsThumb2())
Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
- else if (supportsThumb(ArchName, CPUArch, CPUArchVer))
+ else if (supportsThumb())
Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
// __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
@@ -4558,6 +4762,20 @@ public:
if (!CPUProfile.empty())
Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");
+ // ACLE 6.4.3 Unaligned access supported in hardware
+ if (Unaligned)
+ Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
+
+ // ACLE 6.4.4 LDREX/STREX
+ if (LDREX)
+ Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + llvm::utohexstr(LDREX));
+
+ // ACLE 6.4.5 CLZ
+ if (ArchVersion == 5 ||
+ (ArchVersion == 6 && CPUProfile != "M") ||
+ ArchVersion > 6)
+ Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
+
// ACLE 6.5.1 Hardware Floating Point
if (HW_FP)
Builder.defineMacro("__ARM_FP", "0x" + llvm::utohexstr(HW_FP));
@@ -4565,12 +4783,20 @@ public:
// ACLE predefines.
Builder.defineMacro("__ARM_ACLE", "200");
+ // FP16 support (we currently only support IEEE format).
+ Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
+ Builder.defineMacro("__ARM_FP16_ARGS", "1");
+
+ // ACLE 6.5.3 Fused multiply-accumulate (FMA)
+ if (ArchVersion >= 7 && (CPUProfile != "M" || CPUAttr == "7EM"))
+ Builder.defineMacro("__ARM_FEATURE_FMA", "1");
+
// Subtarget options.
// FIXME: It's more complicated than this and we don't really support
// interworking.
// Windows on ARM does not "support" interworking
- if (5 <= CPUArchVer && CPUArchVer <= 8 && !getTriple().isOSWindows())
+ if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
Builder.defineMacro("__THUMB_INTERWORK__");
if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
@@ -4590,14 +4816,23 @@ public:
if (CPU == "xscale")
Builder.defineMacro("__XSCALE__");
- if (IsThumb) {
+ if (isThumb()) {
Builder.defineMacro("__THUMBEL__");
Builder.defineMacro("__thumb__");
- if (supportsThumb2(ArchName, CPUArch, CPUArchVer))
+ if (supportsThumb2())
Builder.defineMacro("__thumb2__");
}
- if (((HWDiv & HWDivThumb) && IsThumb) || ((HWDiv & HWDivARM) && !IsThumb))
+
+ // ACLE 6.4.9 32-bit SIMD instructions
+ if (ArchVersion >= 6 && (CPUProfile != "M" || CPUAttr == "7EM"))
+ Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
+
+ // ACLE 6.4.10 Hardware Integer Divide
+ if (((HWDiv & HWDivThumb) && isThumb()) ||
+ ((HWDiv & HWDivARM) && !isThumb())) {
+ Builder.defineMacro("__ARM_FEATURE_IDIV", "1");
Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
+ }
// Note, this is always on in gcc, even though it doesn't make sense.
Builder.defineMacro("__APCS_32__");
@@ -4616,9 +4851,13 @@ public:
// the VFP define, hence the soft float and arch check. This is subtly
// different from gcc, we follow the intent which was that it should be set
// when Neon instructions are actually available.
- if ((FPU & NeonFPU) && !SoftFloat && CPUArchVer >= 7) {
- Builder.defineMacro("__ARM_NEON");
+ if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
+ Builder.defineMacro("__ARM_NEON", "1");
Builder.defineMacro("__ARM_NEON__");
+ // current AArch32 NEON implementations do not support double-precision
+ // floating-point even when it is present in VFP.
+ Builder.defineMacro("__ARM_NEON_FP",
+ "0x" + llvm::utohexstr(HW_FP & ~HW_FP_DP));
}
Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
@@ -4627,39 +4866,49 @@ public:
Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM",
Opts.ShortEnums ? "1" : "4");
- if (CRC)
- Builder.defineMacro("__ARM_FEATURE_CRC32");
-
- if (Crypto)
- Builder.defineMacro("__ARM_FEATURE_CRYPTO");
-
- if (CPUArchVer >= 6 && CPUArch != "6M") {
+ if (ArchVersion >= 6 && CPUAttr != "6M") {
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
}
- bool is5EOrAbove = (CPUArchVer >= 6 ||
- (CPUArchVer == 5 &&
- CPUArch.find('E') != StringRef::npos));
- bool is32Bit = (!IsThumb || supportsThumb2(ArchName, CPUArch, CPUArchVer));
- if (is5EOrAbove && is32Bit && (CPUProfile != "M" || CPUArch == "7EM"))
- Builder.defineMacro("__ARM_FEATURE_DSP");
+ // ACLE 6.4.7 DSP instructions
+ if (DSP) {
+ Builder.defineMacro("__ARM_FEATURE_DSP", "1");
+ }
+
+ // ACLE 6.4.8 Saturation instructions
+ bool SAT = false;
+ if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6 ) {
+ Builder.defineMacro("__ARM_FEATURE_SAT", "1");
+ SAT = true;
+ }
+
+ // ACLE 6.4.6 Q (saturation) flag
+ if (DSP || SAT)
+ Builder.defineMacro("__ARM_FEATURE_QBIT", "1");
+
+ if (Opts.UnsafeFPMath)
+ Builder.defineMacro("__ARM_FP_FAST", "1");
+
+ if (ArchKind == llvm::ARM::AK_ARMV8_1A)
+ Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::ARM::LastTSBuiltin-Builtin::FirstTSBuiltin;
+
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::ARM::LastTSBuiltin-Builtin::FirstTSBuiltin);
}
bool isCLZForZeroUndef() const override { return false; }
BuiltinVaListKind getBuiltinVaListKind() const override {
- return IsAAPCS ? AAPCSABIBuiltinVaList : TargetInfo::VoidPtrBuiltinVaList;
+ return IsAAPCS
+ ? AAPCSABIBuiltinVaList
+ : (getTriple().isWatchOS() ? TargetInfo::CharPtrBuiltinVaList
+ : TargetInfo::VoidPtrBuiltinVaList);
}
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override;
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
switch (*Name) {
@@ -4754,6 +5003,10 @@ public:
if (RegNo == 1) return 1;
return -1;
}
+
+ bool hasSjLjLowering() const override {
+ return true;
+ }
};
bool ARMTargetInfo::setFPMath(StringRef Name) {
@@ -4790,10 +5043,8 @@ const char * const ARMTargetInfo::GCCRegNames[] = {
"q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
};
-void ARMTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
}
const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
@@ -4817,22 +5068,23 @@ const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
// don't want to substitute one of these for a different-sized one.
};
-void ARMTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
+ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
}
const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
- ALL_LANGUAGES },
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsNEON.def"
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) { #ID, TYPE, ATTRS, 0, LANG },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
- ALL_LANGUAGES },
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
+ { #ID, TYPE, ATTRS, nullptr, LANG, nullptr },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsARM.def"
};
@@ -4891,6 +5143,19 @@ public:
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::CharPtrBuiltinVaList;
}
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ switch (CC) {
+ case CC_X86StdCall:
+ case CC_X86ThisCall:
+ case CC_X86FastCall:
+ case CC_X86VectorCall:
+ return CCCR_Ignore;
+ case CC_C:
+ return CCCR_OK;
+ default:
+ return CCCR_Warning;
+ }
+ }
};
// Windows ARM + Itanium C++ ABI Target
@@ -4925,6 +5190,45 @@ public:
}
};
+// ARM MinGW target
+class MinGWARMTargetInfo : public WindowsARMTargetInfo {
+public:
+ MinGWARMTargetInfo(const llvm::Triple &Triple)
+ : WindowsARMTargetInfo(Triple) {
+ TheCXXABI.set(TargetCXXABI::GenericARM);
+ }
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+ DefineStd(Builder, "WIN32", Opts);
+ DefineStd(Builder, "WINNT", Opts);
+ Builder.defineMacro("_ARM_");
+ addMinGWDefines(Opts, Builder);
+ }
+};
+
+// ARM Cygwin target
+class CygwinARMTargetInfo : public ARMleTargetInfo {
+public:
+ CygwinARMTargetInfo(const llvm::Triple &Triple) : ARMleTargetInfo(Triple) {
+ TLSSupported = false;
+ WCharType = UnsignedShort;
+ DoubleAlign = LongLongAlign = 64;
+ DataLayoutString = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64";
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ ARMleTargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_ARM_");
+ Builder.defineMacro("__CYGWIN__");
+ Builder.defineMacro("__CYGWIN32__");
+ DefineStd(Builder, "unix", Opts);
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+};
+
class DarwinARMTargetInfo :
public DarwinTargetInfo<ARMleTargetInfo> {
protected:
@@ -4942,13 +5246,23 @@ public:
// ARMleTargetInfo.
MaxAtomicInlineWidth = 64;
- // Darwin on iOS uses a variant of the ARM C++ ABI.
- TheCXXABI.set(TargetCXXABI::iOS);
+ if (Triple.isWatchOS()) {
+ // Darwin on iOS uses a variant of the ARM C++ ABI.
+ TheCXXABI.set(TargetCXXABI::WatchOS);
+
+ // The 32-bit ABI is silent on what ptrdiff_t should be, but given that
+ // size_t is long, it's a bit weird for it to be int.
+ PtrDiffType = SignedLong;
+
+ // BOOL should be a real boolean on the new ABI
+ UseSignedCharForObjCBool = false;
+ } else
+ TheCXXABI.set(TargetCXXABI::iOS);
}
};
class AArch64TargetInfo : public TargetInfo {
- virtual void setDescriptionString() = 0;
+ virtual void setDataLayoutString() = 0;
static const TargetInfo::GCCRegAlias GCCRegAliases[];
static const char *const GCCRegNames[];
@@ -4960,6 +5274,8 @@ class AArch64TargetInfo : public TargetInfo {
unsigned FPU;
unsigned CRC;
unsigned Crypto;
+ unsigned Unaligned;
+ unsigned V8_1A;
static const Builtin::Info BuiltinInfo[];
@@ -4998,7 +5314,7 @@ public:
// contributes to the alignment of the containing aggregate in the same way
// a plain (non bit-field) member of that type would, without exception for
// zero-sized or anonymous bit-fields."
- UseBitFieldTypeAlignment = true;
+ assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
UseZeroLengthBitfieldAlignment = true;
// AArch64 targets default to using the ARM C++ ABI.
@@ -5017,7 +5333,8 @@ public:
bool setCPU(const std::string &Name) override {
bool CPUKnown = llvm::StringSwitch<bool>(Name)
.Case("generic", true)
- .Cases("cortex-a53", "cortex-a57", "cortex-a72", true)
+ .Cases("cortex-a53", "cortex-a57", "cortex-a72",
+ "cortex-a35", "exynos-m1", true)
.Case("cyclone", true)
.Default(false);
return CPUKnown;
@@ -5037,33 +5354,30 @@ public:
Builder.defineMacro("__ARM_ARCH", "8");
Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
- Builder.defineMacro("__ARM_64BIT_STATE");
- Builder.defineMacro("__ARM_PCS_AAPCS64");
- Builder.defineMacro("__ARM_ARCH_ISA_A64");
+ Builder.defineMacro("__ARM_64BIT_STATE", "1");
+ Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
+ Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
- Builder.defineMacro("__ARM_FEATURE_UNALIGNED");
- Builder.defineMacro("__ARM_FEATURE_CLZ");
- Builder.defineMacro("__ARM_FEATURE_FMA");
- Builder.defineMacro("__ARM_FEATURE_DIV");
- Builder.defineMacro("__ARM_FEATURE_IDIV"); // As specified in ACLE
+ Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
+ Builder.defineMacro("__ARM_FEATURE_FMA", "1");
+ Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
+ Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
- Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN");
- Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING");
+ Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
+ Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
// 0xe implies support for half, single and double precision operations.
- Builder.defineMacro("__ARM_FP", "0xe");
+ Builder.defineMacro("__ARM_FP", "0xE");
// PCS specifies this for SysV variants, which is all we support. Other ABIs
// may choose __ARM_FP16_FORMAT_ALTERNATIVE.
- Builder.defineMacro("__ARM_FP16_FORMAT_IEEE");
-
- if (Opts.FastMath || Opts.FiniteMathOnly)
- Builder.defineMacro("__ARM_FP_FAST");
+ Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
+ Builder.defineMacro("__ARM_FP16_ARGS", "1");
- if (Opts.C99 && !Opts.Freestanding)
- Builder.defineMacro("__ARM_FP_FENV_ROUNDING");
+ if (Opts.UnsafeFPMath)
+ Builder.defineMacro("__ARM_FP_FAST", "1");
Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4");
@@ -5071,16 +5385,22 @@ public:
Opts.ShortEnums ? "1" : "4");
if (FPU == NeonMode) {
- Builder.defineMacro("__ARM_NEON");
+ Builder.defineMacro("__ARM_NEON", "1");
// 64-bit NEON supports half, single and double precision operations.
- Builder.defineMacro("__ARM_NEON_FP", "0xe");
+ Builder.defineMacro("__ARM_NEON_FP", "0xE");
}
if (CRC)
- Builder.defineMacro("__ARM_FEATURE_CRC32");
+ Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
if (Crypto)
- Builder.defineMacro("__ARM_FEATURE_CRYPTO");
+ Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
+
+ if (Unaligned)
+ Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
+
+ if (V8_1A)
+ Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
// All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
@@ -5089,15 +5409,15 @@ public:
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin;
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin);
}
bool hasFeature(StringRef Feature) const override {
return Feature == "aarch64" ||
Feature == "arm64" ||
+ Feature == "arm" ||
(Feature == "neon" && FPU == NeonMode);
}
@@ -5106,16 +5426,23 @@ public:
FPU = FPUMode;
CRC = 0;
Crypto = 0;
- for (unsigned i = 0, e = Features.size(); i != e; ++i) {
- if (Features[i] == "+neon")
+ Unaligned = 1;
+ V8_1A = 0;
+
+ for (const auto &Feature : Features) {
+ if (Feature == "+neon")
FPU = NeonMode;
- if (Features[i] == "+crc")
+ if (Feature == "+crc")
CRC = 1;
- if (Features[i] == "+crypto")
+ if (Feature == "+crypto")
Crypto = 1;
+ if (Feature == "+strict-align")
+ Unaligned = 0;
+ if (Feature == "+v8.1a")
+ V8_1A = 1;
}
- setDescriptionString();
+ setDataLayoutString();
return true;
}
@@ -5126,10 +5453,8 @@ public:
return TargetInfo::AArch64ABIBuiltinVaList;
}
- void getGCCRegNames(const char *const *&Names,
- unsigned &NumNames) const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override;
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
@@ -5239,10 +5564,8 @@ const char *const AArch64TargetInfo::GCCRegNames[] = {
"v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
};
-void AArch64TargetInfo::getGCCRegNames(const char *const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
}
const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
@@ -5254,28 +5577,26 @@ const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
// don't want to substitute one of these for a different-sized one.
};
-void AArch64TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
+ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
}
const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsNEON.def"
#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsAArch64.def"
};
class AArch64leTargetInfo : public AArch64TargetInfo {
- void setDescriptionString() override {
+ void setDataLayoutString() override {
if (getTriple().isOSBinFormatMachO())
- DescriptionString = "e-m:o-i64:64-i128:128-n32:64-S128";
+ DataLayoutString = "e-m:o-i64:64-i128:128-n32:64-S128";
else
- DescriptionString = "e-m:e-i64:64-i128:128-n32:64-S128";
+ DataLayoutString = "e-m:e-i64:64-i128:128-n32:64-S128";
}
public:
@@ -5291,9 +5612,9 @@ public:
};
class AArch64beTargetInfo : public AArch64TargetInfo {
- void setDescriptionString() override {
+ void setDataLayoutString() override {
assert(!getTriple().isOSBinFormatMachO());
- DescriptionString = "E-m:e-i64:64-i128:128-n32:64-S128";
+ DataLayoutString = "E-m:e-i64:64-i128:128-n32:64-S128";
}
public:
@@ -5347,20 +5668,32 @@ class HexagonTargetInfo : public TargetInfo {
static const char * const GCCRegNames[];
static const TargetInfo::GCCRegAlias GCCRegAliases[];
std::string CPU;
+ bool HasHVX, HasHVXDouble;
+
public:
HexagonTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
BigEndian = false;
- DescriptionString = "e-m:e-p:32:32-i1:32-i64:64-a:0-n32";
+ DataLayoutString = "e-m:e-p:32:32:32-"
+ "i64:64:64-i32:32:32-i16:16:16-i1:8:8-"
+ "f64:64:64-f32:32:32-v64:64:64-v32:32:32-a:0-n16:32";
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
// {} in inline assembly are packet specifiers, not assembly variant
// specifiers.
NoAsmVariants = true;
+
+ LargeArrayMinWidth = 64;
+ LargeArrayAlign = 64;
+ UseBitFieldTypeAlignment = true;
+ ZeroLengthBitfieldBoundary = 32;
+ HasHVX = HasHVXDouble = false;
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::Hexagon::LastTSBuiltin-Builtin::FirstTSBuiltin;
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::Hexagon::LastTSBuiltin-Builtin::FirstTSBuiltin);
}
bool validateAsmConstraint(const char *&Name,
@@ -5371,17 +5704,28 @@ public:
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
+ bool isCLZForZeroUndef() const override { return false; }
+
bool hasFeature(StringRef Feature) const override {
- return Feature == "hexagon";
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("hexagon", true)
+ .Case("hvx", HasHVX)
+ .Case("hvx-double", HasHVXDouble)
+ .Default(false);
}
+ bool initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU, const std::vector<std::string> &FeaturesVec)
+ const override;
+
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) override;
+
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::CharPtrBuiltinVaList;
}
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override;
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
const char *getClobbers() const override {
return "";
}
@@ -5390,71 +5734,77 @@ public:
return llvm::StringSwitch<const char*>(Name)
.Case("hexagonv4", "4")
.Case("hexagonv5", "5")
+ .Case("hexagonv55", "55")
+ .Case("hexagonv60", "60")
.Default(nullptr);
}
bool setCPU(const std::string &Name) override {
if (!getHexagonCPUSuffix(Name))
return false;
-
CPU = Name;
return true;
}
+
+ int getEHDataRegisterNumber(unsigned RegNo) const override {
+ return RegNo < 2 ? RegNo : -1;
+ }
};
void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- Builder.defineMacro("qdsp6");
- Builder.defineMacro("__qdsp6", "1");
+ MacroBuilder &Builder) const {
Builder.defineMacro("__qdsp6__", "1");
-
- Builder.defineMacro("hexagon");
- Builder.defineMacro("__hexagon", "1");
Builder.defineMacro("__hexagon__", "1");
- if(CPU == "hexagonv1") {
- Builder.defineMacro("__HEXAGON_V1__");
- Builder.defineMacro("__HEXAGON_ARCH__", "1");
- if(Opts.HexagonQdsp6Compat) {
- Builder.defineMacro("__QDSP6_V1__");
- Builder.defineMacro("__QDSP6_ARCH__", "1");
- }
- }
- else if(CPU == "hexagonv2") {
- Builder.defineMacro("__HEXAGON_V2__");
- Builder.defineMacro("__HEXAGON_ARCH__", "2");
- if(Opts.HexagonQdsp6Compat) {
- Builder.defineMacro("__QDSP6_V2__");
- Builder.defineMacro("__QDSP6_ARCH__", "2");
- }
- }
- else if(CPU == "hexagonv3") {
- Builder.defineMacro("__HEXAGON_V3__");
- Builder.defineMacro("__HEXAGON_ARCH__", "3");
- if(Opts.HexagonQdsp6Compat) {
- Builder.defineMacro("__QDSP6_V3__");
- Builder.defineMacro("__QDSP6_ARCH__", "3");
- }
- }
- else if(CPU == "hexagonv4") {
+ if (CPU == "hexagonv4") {
Builder.defineMacro("__HEXAGON_V4__");
Builder.defineMacro("__HEXAGON_ARCH__", "4");
- if(Opts.HexagonQdsp6Compat) {
+ if (Opts.HexagonQdsp6Compat) {
Builder.defineMacro("__QDSP6_V4__");
Builder.defineMacro("__QDSP6_ARCH__", "4");
}
- }
- else if(CPU == "hexagonv5") {
+ } else if (CPU == "hexagonv5") {
Builder.defineMacro("__HEXAGON_V5__");
Builder.defineMacro("__HEXAGON_ARCH__", "5");
if(Opts.HexagonQdsp6Compat) {
Builder.defineMacro("__QDSP6_V5__");
Builder.defineMacro("__QDSP6_ARCH__", "5");
}
+ } else if (CPU == "hexagonv60") {
+ Builder.defineMacro("__HEXAGON_V60__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "60");
+ Builder.defineMacro("__QDSP6_V60__");
+ Builder.defineMacro("__QDSP6_ARCH__", "60");
}
}
-const char * const HexagonTargetInfo::GCCRegNames[] = {
+bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ for (auto &F : Features) {
+ if (F == "+hvx")
+ HasHVX = true;
+ else if (F == "-hvx")
+ HasHVX = HasHVXDouble = false;
+ else if (F == "+hvx-double")
+ HasHVX = HasHVXDouble = true;
+ else if (F == "-hvx-double")
+ HasHVXDouble = false;
+ }
+ return true;
+}
+
+bool HexagonTargetInfo::initFeatureMap(llvm::StringMap<bool> &Features,
+ DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+ // Default for v60: -hvx, -hvx-double.
+ Features["hvx"] = false;
+ Features["hvx-double"] = false;
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+}
+
+
+const char *const HexagonTargetInfo::GCCRegNames[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
@@ -5463,30 +5813,26 @@ const char * const HexagonTargetInfo::GCCRegNames[] = {
"sa0", "lc0", "sa1", "lc1", "m0", "m1", "usr", "ugp"
};
-void HexagonTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+ArrayRef<const char*> HexagonTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
}
-
const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
{ { "sp" }, "r29" },
{ { "fp" }, "r30" },
{ { "lr" }, "r31" },
- };
+};
-void HexagonTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
+ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
}
const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
- ALL_LANGUAGES },
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsHexagon.def"
};
@@ -5526,17 +5872,15 @@ public:
.Default(false);
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
// FIXME: Implement!
+ return None;
}
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList;
}
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override;
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override {
// FIXME: Implement!
@@ -5556,6 +5900,80 @@ public:
// FIXME: Implement!
return "";
}
+
+ // No Sparc V7 for now, the backend doesn't support it anyway.
+ enum CPUKind {
+ CK_GENERIC,
+ CK_V8,
+ CK_SUPERSPARC,
+ CK_SPARCLITE,
+ CK_F934,
+ CK_HYPERSPARC,
+ CK_SPARCLITE86X,
+ CK_SPARCLET,
+ CK_TSC701,
+ CK_V9,
+ CK_ULTRASPARC,
+ CK_ULTRASPARC3,
+ CK_NIAGARA,
+ CK_NIAGARA2,
+ CK_NIAGARA3,
+ CK_NIAGARA4
+ } CPU = CK_GENERIC;
+
+ enum CPUGeneration {
+ CG_V8,
+ CG_V9,
+ };
+
+ CPUGeneration getCPUGeneration(CPUKind Kind) const {
+ switch (Kind) {
+ case CK_GENERIC:
+ case CK_V8:
+ case CK_SUPERSPARC:
+ case CK_SPARCLITE:
+ case CK_F934:
+ case CK_HYPERSPARC:
+ case CK_SPARCLITE86X:
+ case CK_SPARCLET:
+ case CK_TSC701:
+ return CG_V8;
+ case CK_V9:
+ case CK_ULTRASPARC:
+ case CK_ULTRASPARC3:
+ case CK_NIAGARA:
+ case CK_NIAGARA2:
+ case CK_NIAGARA3:
+ case CK_NIAGARA4:
+ return CG_V9;
+ }
+ llvm_unreachable("Unexpected CPU kind");
+ }
+
+ CPUKind getCPUKind(StringRef Name) const {
+ return llvm::StringSwitch<CPUKind>(Name)
+ .Case("v8", CK_V8)
+ .Case("supersparc", CK_SUPERSPARC)
+ .Case("sparclite", CK_SPARCLITE)
+ .Case("f934", CK_F934)
+ .Case("hypersparc", CK_HYPERSPARC)
+ .Case("sparclite86x", CK_SPARCLITE86X)
+ .Case("sparclet", CK_SPARCLET)
+ .Case("tsc701", CK_TSC701)
+ .Case("v9", CK_V9)
+ .Case("ultrasparc", CK_ULTRASPARC)
+ .Case("ultrasparc3", CK_ULTRASPARC3)
+ .Case("niagara", CK_NIAGARA)
+ .Case("niagara2", CK_NIAGARA2)
+ .Case("niagara3", CK_NIAGARA3)
+ .Case("niagara4", CK_NIAGARA4)
+ .Default(CK_GENERIC);
+ }
+
+ bool setCPU(const std::string &Name) override {
+ CPU = getCPUKind(Name);
+ return CPU != CK_GENERIC;
+ }
};
const char * const SparcTargetInfo::GCCRegNames[] = {
@@ -5565,10 +5983,8 @@ const char * const SparcTargetInfo::GCCRegNames[] = {
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
};
-void SparcTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+ArrayRef<const char *> SparcTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
}
const TargetInfo::GCCRegAlias SparcTargetInfo::GCCRegAliases[] = {
@@ -5606,33 +6022,48 @@ const TargetInfo::GCCRegAlias SparcTargetInfo::GCCRegAliases[] = {
{ { "i7" }, "r31" },
};
-void SparcTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
+ArrayRef<TargetInfo::GCCRegAlias> SparcTargetInfo::getGCCRegAliases() const {
+ return llvm::makeArrayRef(GCCRegAliases);
}
// SPARC v8 is the 32-bit mode selected by Triple::sparc.
class SparcV8TargetInfo : public SparcTargetInfo {
public:
SparcV8TargetInfo(const llvm::Triple &Triple) : SparcTargetInfo(Triple) {
- DescriptionString = "E-m:e-p:32:32-i64:64-f128:64-n32-S64";
- // NetBSD uses long (same as llvm default); everyone else uses int.
- if (getTriple().getOS() == llvm::Triple::NetBSD) {
- SizeType = UnsignedLong;
- IntPtrType = SignedLong;
- PtrDiffType = SignedLong;
- } else {
+ DataLayoutString = "E-m:e-p:32:32-i64:64-f128:64-n32-S64";
+ // NetBSD / OpenBSD use long (same as llvm default); everyone else uses int.
+ switch (getTriple().getOS()) {
+ default:
SizeType = UnsignedInt;
IntPtrType = SignedInt;
PtrDiffType = SignedInt;
+ break;
+ case llvm::Triple::NetBSD:
+ case llvm::Triple::OpenBSD:
+ SizeType = UnsignedLong;
+ IntPtrType = SignedLong;
+ PtrDiffType = SignedLong;
+ break;
}
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
SparcTargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("__sparcv8");
+ switch (getCPUGeneration(CPU)) {
+ case CG_V8:
+ Builder.defineMacro("__sparcv8");
+ if (getTriple().getOS() != llvm::Triple::Solaris)
+ Builder.defineMacro("__sparcv8__");
+ break;
+ case CG_V9:
+ Builder.defineMacro("__sparcv9");
+ if (getTriple().getOS() != llvm::Triple::Solaris) {
+ Builder.defineMacro("__sparcv9__");
+ Builder.defineMacro("__sparc_v9__");
+ }
+ break;
+ }
}
};
@@ -5640,7 +6071,7 @@ public:
class SparcV8elTargetInfo : public SparcV8TargetInfo {
public:
SparcV8elTargetInfo(const llvm::Triple &Triple) : SparcV8TargetInfo(Triple) {
- DescriptionString = "e-m:e-p:32:32-i64:64-f128:64-n32-S64";
+ DataLayoutString = "e-m:e-p:32:32-i64:64-f128:64-n32-S64";
BigEndian = false;
}
};
@@ -5650,7 +6081,7 @@ class SparcV9TargetInfo : public SparcTargetInfo {
public:
SparcV9TargetInfo(const llvm::Triple &Triple) : SparcTargetInfo(Triple) {
// FIXME: Support Sparc quad-precision long double?
- DescriptionString = "E-m:e-i64:64-n32:64-S128";
+ DataLayoutString = "E-m:e-i64:64-n32:64-S128";
// This is an LP64 platform.
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
@@ -5683,19 +6114,9 @@ public:
}
bool setCPU(const std::string &Name) override {
- bool CPUKnown = llvm::StringSwitch<bool>(Name)
- .Case("v9", true)
- .Case("ultrasparc", true)
- .Case("ultrasparc3", true)
- .Case("niagara", true)
- .Case("niagara2", true)
- .Case("niagara3", true)
- .Case("niagara4", true)
- .Default(false);
-
- // No need to store the CPU yet. There aren't any CPU-specific
- // macros to define.
- return CPUKnown;
+ if (!SparcTargetInfo::setCPU(Name))
+ return false;
+ return getCPUGeneration(CPU) == CG_V9;
}
};
@@ -5708,7 +6129,8 @@ class SystemZTargetInfo : public TargetInfo {
public:
SystemZTargetInfo(const llvm::Triple &Triple)
- : TargetInfo(Triple), CPU("z10"), HasTransactionalExecution(false), HasVector(false) {
+ : TargetInfo(Triple), CPU("z10"), HasTransactionalExecution(false),
+ HasVector(false) {
IntMaxType = SignedLong;
Int64Type = SignedLong;
TLSSupported = true;
@@ -5720,7 +6142,7 @@ public:
LongDoubleFormat = &llvm::APFloat::IEEEquad;
DefaultAlignForAttributeAligned = 64;
MinGlobalAlign = 16;
- DescriptionString = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64";
+ DataLayoutString = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64";
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
}
void getTargetDefines(const LangOptions &Opts,
@@ -5734,19 +6156,15 @@ public:
if (Opts.ZVector)
Builder.defineMacro("__VEC__", "10301");
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::SystemZ::LastTSBuiltin-Builtin::FirstTSBuiltin;
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::SystemZ::LastTSBuiltin-Builtin::FirstTSBuiltin);
}
- void getGCCRegNames(const char *const *&Names,
- unsigned &NumNames) const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
// No aliases.
- Aliases = nullptr;
- NumAliases = 0;
+ return None;
}
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override;
@@ -5768,29 +6186,33 @@ public:
return CPUKnown;
}
- void getDefaultFeatures(llvm::StringMap<bool> &Features) const override {
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
if (CPU == "zEC12")
Features["transactional-execution"] = true;
if (CPU == "z13") {
Features["transactional-execution"] = true;
Features["vector"] = true;
}
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override {
HasTransactionalExecution = false;
- for (unsigned i = 0, e = Features.size(); i != e; ++i) {
- if (Features[i] == "+transactional-execution")
+ for (const auto &Feature : Features) {
+ if (Feature == "+transactional-execution")
HasTransactionalExecution = true;
- if (Features[i] == "+vector")
+ else if (Feature == "+vector")
HasVector = true;
}
// If we use the vector ABI, vector types are 64-bit aligned.
if (HasVector) {
MaxVectorAlign = 64;
- DescriptionString = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64"
- "-v128:64-a:8:16-n32:64";
+ DataLayoutString = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64"
+ "-v128:64-a:8:16-n32:64";
}
return true;
}
@@ -5816,7 +6238,7 @@ public:
const Builtin::Info SystemZTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsSystemZ.def"
};
@@ -5827,10 +6249,8 @@ const char *const SystemZTargetInfo::GCCRegNames[] = {
"f8", "f10", "f12", "f14", "f9", "f11", "f13", "f15"
};
-void SystemZTargetInfo::getGCCRegNames(const char *const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+ArrayRef<const char *> SystemZTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
}
bool SystemZTargetInfo::
@@ -5862,157 +6282,147 @@ validateAsmConstraint(const char *&Name,
}
}
- class MSP430TargetInfo : public TargetInfo {
- static const char * const GCCRegNames[];
- public:
- MSP430TargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
- BigEndian = false;
- TLSSupported = false;
- IntWidth = 16; IntAlign = 16;
- LongWidth = 32; LongLongWidth = 64;
- LongAlign = LongLongAlign = 16;
- PointerWidth = 16; PointerAlign = 16;
- SuitableAlign = 16;
- SizeType = UnsignedInt;
- IntMaxType = SignedLongLong;
- IntPtrType = SignedInt;
- PtrDiffType = SignedInt;
- SigAtomicType = SignedLong;
- DescriptionString = "e-m:e-p:16:16-i32:16:32-a:16-n8:16";
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- Builder.defineMacro("MSP430");
- Builder.defineMacro("__MSP430__");
- // FIXME: defines for different 'flavours' of MCU
- }
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- // FIXME: Implement.
- Records = nullptr;
- NumRecords = 0;
- }
- bool hasFeature(StringRef Feature) const override {
- return Feature == "msp430";
- }
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {
- // No aliases.
- Aliases = nullptr;
- NumAliases = 0;
- }
- bool
- validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override {
- // FIXME: implement
- switch (*Name) {
- case 'K': // the constant 1
- case 'L': // constant -1^20 .. 1^19
- case 'M': // constant 1-4:
- return true;
- }
- // No target constraints for now.
- return false;
- }
- const char *getClobbers() const override {
- // FIXME: Is this really right?
- return "";
+class MSP430TargetInfo : public TargetInfo {
+ static const char *const GCCRegNames[];
+
+public:
+ MSP430TargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
+ BigEndian = false;
+ TLSSupported = false;
+ IntWidth = 16;
+ IntAlign = 16;
+ LongWidth = 32;
+ LongLongWidth = 64;
+ LongAlign = LongLongAlign = 16;
+ PointerWidth = 16;
+ PointerAlign = 16;
+ SuitableAlign = 16;
+ SizeType = UnsignedInt;
+ IntMaxType = SignedLongLong;
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ SigAtomicType = SignedLong;
+ DataLayoutString = "e-m:e-p:16:16-i32:16:32-a:16-n8:16";
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("MSP430");
+ Builder.defineMacro("__MSP430__");
+ // FIXME: defines for different 'flavours' of MCU
+ }
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ // FIXME: Implement.
+ return None;
+ }
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "msp430";
+ }
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ // No aliases.
+ return None;
+ }
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ // FIXME: implement
+ switch (*Name) {
+ case 'K': // the constant 1
+ case 'L': // constant -1^20 .. 1^19
+ case 'M': // constant 1-4:
+ return true;
}
- BuiltinVaListKind getBuiltinVaListKind() const override {
- // FIXME: implement
- return TargetInfo::CharPtrBuiltinVaList;
- }
- };
+ // No target constraints for now.
+ return false;
+ }
+ const char *getClobbers() const override {
+ // FIXME: Is this really right?
+ return "";
+ }
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ // FIXME: implement
+ return TargetInfo::CharPtrBuiltinVaList;
+ }
+};
- const char * const MSP430TargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
- };
+const char *const MSP430TargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"};
+
+ArrayRef<const char *> MSP430TargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
- void MSP430TargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+// LLVM and Clang cannot be used directly to output native binaries for
+// target, but is used to compile C code to llvm bitcode with correct
+// type and alignment information.
+//
+// TCE uses the llvm bitcode as input and uses it for generating customized
+// target processor and program binary. TCE co-design environment is
+// publicly available in http://tce.cs.tut.fi
+
+static const unsigned TCEOpenCLAddrSpaceMap[] = {
+ 3, // opencl_global
+ 4, // opencl_local
+ 5, // opencl_constant
+ // FIXME: generic has to be added to the target
+ 0, // opencl_generic
+ 0, // cuda_device
+ 0, // cuda_constant
+ 0 // cuda_shared
+};
+
+class TCETargetInfo : public TargetInfo {
+public:
+ TCETargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
+ TLSSupported = false;
+ IntWidth = 32;
+ LongWidth = LongLongWidth = 32;
+ PointerWidth = 32;
+ IntAlign = 32;
+ LongAlign = LongLongAlign = 32;
+ PointerAlign = 32;
+ SuitableAlign = 32;
+ SizeType = UnsignedInt;
+ IntMaxType = SignedLong;
+ IntPtrType = SignedInt;
+ PtrDiffType = SignedInt;
+ FloatWidth = 32;
+ FloatAlign = 32;
+ DoubleWidth = 32;
+ DoubleAlign = 32;
+ LongDoubleWidth = 32;
+ LongDoubleAlign = 32;
+ FloatFormat = &llvm::APFloat::IEEEsingle;
+ DoubleFormat = &llvm::APFloat::IEEEsingle;
+ LongDoubleFormat = &llvm::APFloat::IEEEsingle;
+ DataLayoutString = "E-p:32:32-i8:8:32-i16:16:32-i64:32"
+ "-f64:32-v64:32-v128:32-a:0:32-n32";
+ AddrSpaceMap = &TCEOpenCLAddrSpaceMap;
+ UseAddrSpaceMapMangling = true;
}
- // LLVM and Clang cannot be used directly to output native binaries for
- // target, but is used to compile C code to llvm bitcode with correct
- // type and alignment information.
- //
- // TCE uses the llvm bitcode as input and uses it for generating customized
- // target processor and program binary. TCE co-design environment is
- // publicly available in http://tce.cs.tut.fi
-
- static const unsigned TCEOpenCLAddrSpaceMap[] = {
- 3, // opencl_global
- 4, // opencl_local
- 5, // opencl_constant
- // FIXME: generic has to be added to the target
- 0, // opencl_generic
- 0, // cuda_device
- 0, // cuda_constant
- 0 // cuda_shared
- };
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ DefineStd(Builder, "tce", Opts);
+ Builder.defineMacro("__TCE__");
+ Builder.defineMacro("__TCE_V1__");
+ }
+ bool hasFeature(StringRef Feature) const override { return Feature == "tce"; }
- class TCETargetInfo : public TargetInfo{
- public:
- TCETargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
- TLSSupported = false;
- IntWidth = 32;
- LongWidth = LongLongWidth = 32;
- PointerWidth = 32;
- IntAlign = 32;
- LongAlign = LongLongAlign = 32;
- PointerAlign = 32;
- SuitableAlign = 32;
- SizeType = UnsignedInt;
- IntMaxType = SignedLong;
- IntPtrType = SignedInt;
- PtrDiffType = SignedInt;
- FloatWidth = 32;
- FloatAlign = 32;
- DoubleWidth = 32;
- DoubleAlign = 32;
- LongDoubleWidth = 32;
- LongDoubleAlign = 32;
- FloatFormat = &llvm::APFloat::IEEEsingle;
- DoubleFormat = &llvm::APFloat::IEEEsingle;
- LongDoubleFormat = &llvm::APFloat::IEEEsingle;
- DescriptionString = "E-p:32:32-i8:8:32-i16:16:32-i64:32"
- "-f64:32-v64:32-v128:32-a:0:32-n32";
- AddrSpaceMap = &TCEOpenCLAddrSpaceMap;
- UseAddrSpaceMapMangling = true;
- }
-
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "tce", Opts);
- Builder.defineMacro("__TCE__");
- Builder.defineMacro("__TCE_V1__");
- }
- bool hasFeature(StringRef Feature) const override {
- return Feature == "tce";
- }
-
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {}
- const char *getClobbers() const override {
- return "";
- }
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override {}
- bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override{
- return true;
- }
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {}
- };
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+ const char *getClobbers() const override { return ""; }
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
+ ArrayRef<const char *> getGCCRegNames() const override { return None; }
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return true;
+ }
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+};
class BPFTargetInfo : public TargetInfo {
public:
@@ -6026,10 +6436,10 @@ public:
RegParmMax = 5;
if (Triple.getArch() == llvm::Triple::bpfeb) {
BigEndian = true;
- DescriptionString = "E-m:e-p:64:64-i64:64-n32:64-S128";
+ DataLayoutString = "E-m:e-p:64:64-i64:64-n32:64-S128";
} else {
BigEndian = false;
- DescriptionString = "e-m:e-p:64:64-i64:64-n32:64-S128";
+ DataLayoutString = "e-m:e-p:64:64-i64:64-n32:64-S128";
}
MaxAtomicPromoteWidth = 64;
MaxAtomicInlineWidth = 64;
@@ -6044,32 +6454,27 @@ public:
return Feature == "bpf";
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {}
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
const char *getClobbers() const override {
return "";
}
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList;
}
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override {
- Names = nullptr;
- NumNames = 0;
+ ArrayRef<const char *> getGCCRegNames() const override {
+ return None;
}
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override {
return true;
}
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {
- Aliases = nullptr;
- NumAliases = 0;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
}
};
class MipsTargetInfoBase : public TargetInfo {
- virtual void setDescriptionString() = 0;
+ virtual void setDataLayoutString() = 0;
static const Builtin::Info BuiltinInfo[];
std::string CPU;
@@ -6132,14 +6537,19 @@ public:
.Case("mips64r5", true)
.Case("mips64r6", true)
.Case("octeon", true)
+ .Case("p5600", true)
.Default(false);
}
const std::string& getCPU() const { return CPU; }
- void getDefaultFeatures(llvm::StringMap<bool> &Features) const override {
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
if (CPU == "octeon")
Features["mips64r2"] = Features["cnmips"] = true;
else
Features[CPU] = true;
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
void getTargetDefines(const LangOptions &Opts,
@@ -6199,12 +6609,17 @@ public:
Builder.defineMacro("_MIPS_ARCH", "\"" + CPU + "\"");
Builder.defineMacro("_MIPS_ARCH_" + StringRef(CPU).upper());
+
+ // These shouldn't be defined for MIPS-I but there's no need to check
+ // for that since MIPS-I isn't supported.
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin;
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin);
}
bool hasFeature(StringRef Feature) const override {
return llvm::StringSwitch<bool>(Feature)
@@ -6215,8 +6630,7 @@ public:
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList;
}
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override {
+ ArrayRef<const char *> getGCCRegNames() const override {
static const char *const GCCRegNames[] = {
// CPU register names
// Must match second column of GCCRegAliases
@@ -6241,11 +6655,9 @@ public:
"$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify",
"$msarequest", "$msamap", "$msaunmap"
};
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+ return llvm::makeArrayRef(GCCRegNames);
}
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override = 0;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override = 0;
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
switch (*Name) {
@@ -6331,33 +6743,32 @@ public:
DspRev = NoDSP;
HasFP64 = isFP64Default();
- for (std::vector<std::string>::iterator it = Features.begin(),
- ie = Features.end(); it != ie; ++it) {
- if (*it == "+single-float")
+ for (const auto &Feature : Features) {
+ if (Feature == "+single-float")
IsSingleFloat = true;
- else if (*it == "+soft-float")
+ else if (Feature == "+soft-float")
FloatABI = SoftFloat;
- else if (*it == "+mips16")
+ else if (Feature == "+mips16")
IsMips16 = true;
- else if (*it == "+micromips")
+ else if (Feature == "+micromips")
IsMicromips = true;
- else if (*it == "+dsp")
+ else if (Feature == "+dsp")
DspRev = std::max(DspRev, DSP1);
- else if (*it == "+dspr2")
+ else if (Feature == "+dspr2")
DspRev = std::max(DspRev, DSP2);
- else if (*it == "+msa")
+ else if (Feature == "+msa")
HasMSA = true;
- else if (*it == "+fp64")
+ else if (Feature == "+fp64")
HasFP64 = true;
- else if (*it == "-fp64")
+ else if (Feature == "-fp64")
HasFP64 = false;
- else if (*it == "+nan2008")
+ else if (Feature == "+nan2008")
IsNan2008 = true;
- else if (*it == "-nan2008")
+ else if (Feature == "-nan2008")
IsNan2008 = false;
}
- setDescriptionString();
+ setDataLayoutString();
return true;
}
@@ -6372,9 +6783,10 @@ public:
};
const Builtin::Info MipsTargetInfoBase::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
- ALL_LANGUAGES },
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsMips.def"
};
@@ -6424,8 +6836,7 @@ public:
else
llvm_unreachable("Invalid ABI for Mips32.");
}
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
{ { "at" }, "$1" },
{ { "v0" }, "$2" },
@@ -6459,14 +6870,13 @@ public:
{ { "fp","$fp" }, "$30" },
{ { "ra" }, "$31" }
};
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
+ return llvm::makeArrayRef(GCCRegAliases);
}
};
class Mips32EBTargetInfo : public Mips32TargetInfoBase {
- void setDescriptionString() override {
- DescriptionString = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";
+ void setDataLayoutString() override {
+ DataLayoutString = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";
}
public:
@@ -6482,8 +6892,8 @@ public:
};
class Mips32ELTargetInfo : public Mips32TargetInfoBase {
- void setDescriptionString() override {
- DescriptionString = "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";
+ void setDataLayoutString() override {
+ DataLayoutString = "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";
}
public:
@@ -6579,9 +6989,10 @@ public:
}
else
llvm_unreachable("Invalid ABI for Mips64.");
+
+ Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
}
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
{ { "at" }, "$1" },
{ { "v0" }, "$2" },
@@ -6615,19 +7026,18 @@ public:
{ { "fp","$fp" }, "$30" },
{ { "ra" }, "$31" }
};
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
+ return llvm::makeArrayRef(GCCRegAliases);
}
bool hasInt128Type() const override { return true; }
};
class Mips64EBTargetInfo : public Mips64TargetInfoBase {
- void setDescriptionString() override {
+ void setDataLayoutString() override {
if (ABI == "n32")
- DescriptionString = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128";
+ DataLayoutString = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128";
else
- DescriptionString = "E-m:m-i8:8:32-i16:16:32-i64:64-n32:64-S128";
+ DataLayoutString = "E-m:m-i8:8:32-i16:16:32-i64:64-n32:64-S128";
}
@@ -6643,11 +7053,11 @@ public:
};
class Mips64ELTargetInfo : public Mips64TargetInfoBase {
- void setDescriptionString() override {
+ void setDataLayoutString() override {
if (ABI == "n32")
- DescriptionString = "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128";
+ DataLayoutString = "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128";
else
- DescriptionString = "e-m:m-i8:8:32-i16:16:32-i64:64-n32:64-S128";
+ DataLayoutString = "e-m:m-i8:8:32-i16:16:32-i64:64-n32:64-S128";
}
public:
Mips64ELTargetInfo(const llvm::Triple &Triple)
@@ -6683,8 +7093,6 @@ public:
this->RegParmMax = 0; // Disallow regparm
}
- void getDefaultFeatures(llvm::StringMap<bool> &Features) const override {
- }
void getArchDefines(const LangOptions &Opts, MacroBuilder &Builder) const {
Builder.defineMacro("__le32__");
Builder.defineMacro("__pnacl__");
@@ -6696,16 +7104,12 @@ public:
bool hasFeature(StringRef Feature) const override {
return Feature == "pnacl";
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- }
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::PNaClABIBuiltinVaList;
}
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override;
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override;
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
return false;
@@ -6716,24 +7120,19 @@ public:
}
};
-void PNaClTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = nullptr;
- NumNames = 0;
+ArrayRef<const char *> PNaClTargetInfo::getGCCRegNames() const {
+ return None;
}
-void PNaClTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = nullptr;
- NumAliases = 0;
+ArrayRef<TargetInfo::GCCRegAlias> PNaClTargetInfo::getGCCRegAliases() const {
+ return None;
}
// We attempt to use PNaCl (le32) frontend and Mips32EL backend.
class NaClMips32ELTargetInfo : public Mips32ELTargetInfo {
public:
NaClMips32ELTargetInfo(const llvm::Triple &Triple) :
- Mips32ELTargetInfo(Triple) {
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
+ Mips32ELTargetInfo(Triple) {
}
BuiltinVaListKind getBuiltinVaListKind() const override {
@@ -6750,8 +7149,7 @@ public:
NoAsmVariants = true;
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
- DescriptionString =
- "e-m:e-v128:32-v16:16-v32:32-v96:32-n8:16:32:64-S128";
+ DataLayoutString = "e-m:e-v128:32-v16:16-v32:32-v96:32-n8:16:32:64-S128";
}
void getTargetDefines(const LangOptions &Opts,
@@ -6760,24 +7158,19 @@ public:
defineCPUMacros(Builder, "le64", /*Tuning=*/false);
Builder.defineMacro("__ELF__");
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::Le64::LastTSBuiltin - Builtin::FirstTSBuiltin;
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::Le64::LastTSBuiltin - Builtin::FirstTSBuiltin);
}
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::PNaClABIBuiltinVaList;
}
const char *getClobbers() const override { return ""; }
- void getGCCRegNames(const char *const *&Names,
- unsigned &NumNames) const override {
- Names = nullptr;
- NumNames = 0;
+ ArrayRef<const char *> getGCCRegNames() const override {
+ return None;
}
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {
- Aliases = nullptr;
- NumAliases = 0;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
}
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
@@ -6786,107 +7179,246 @@ public:
bool hasProtectedVisibility() const override { return false; }
};
-} // end anonymous namespace.
+
+class WebAssemblyTargetInfo : public TargetInfo {
+ static const Builtin::Info BuiltinInfo[];
+
+ enum SIMDEnum {
+ NoSIMD,
+ SIMD128,
+ } SIMDLevel;
+
+public:
+ explicit WebAssemblyTargetInfo(const llvm::Triple &T)
+ : TargetInfo(T), SIMDLevel(NoSIMD) {
+ BigEndian = false;
+ NoAsmVariants = true;
+ SuitableAlign = 128;
+ LargeArrayMinWidth = 128;
+ LargeArrayAlign = 128;
+ SimdDefaultAlign = 128;
+ SigAtomicType = SignedLong;
+ LongDoubleWidth = LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ }
+
+protected:
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
+ if (SIMDLevel >= SIMD128)
+ Builder.defineMacro("__wasm_simd128__");
+ }
+
+private:
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
+ if (CPU == "bleeding-edge")
+ Features["simd128"] = true;
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+ }
+ bool hasFeature(StringRef Feature) const final {
+ return llvm::StringSwitch<bool>(Feature)
+ .Case("simd128", SIMDLevel >= SIMD128)
+ .Default(false);
+ }
+ bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) final {
+ for (const auto &Feature : Features) {
+ if (Feature == "+simd128") {
+ SIMDLevel = std::max(SIMDLevel, SIMD128);
+ continue;
+ }
+ if (Feature == "-simd128") {
+ SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
+ continue;
+ }
+
+ Diags.Report(diag::err_opt_not_valid_with_opt) << Feature
+ << "-target-feature";
+ return false;
+ }
+ return true;
+ }
+ bool setCPU(const std::string &Name) final {
+ return llvm::StringSwitch<bool>(Name)
+ .Case("mvp", true)
+ .Case("bleeding-edge", true)
+ .Case("generic", true)
+ .Default(false);
+ }
+ ArrayRef<Builtin::Info> getTargetBuiltins() const final {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::WebAssembly::LastTSBuiltin - Builtin::FirstTSBuiltin);
+ }
+ BuiltinVaListKind getBuiltinVaListKind() const final {
+ return VoidPtrBuiltinVaList;
+ }
+ ArrayRef<const char *> getGCCRegNames() const final {
+ return None;
+ }
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const final {
+ return None;
+ }
+ bool
+ validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const final {
+ return false;
+ }
+ const char *getClobbers() const final { return ""; }
+ bool isCLZForZeroUndef() const final { return false; }
+ bool hasInt128Type() const final { return true; }
+ IntType getIntTypeByWidth(unsigned BitWidth,
+ bool IsSigned) const final {
+ // WebAssembly prefers long long for explicitly 64-bit integers.
+ return BitWidth == 64 ? (IsSigned ? SignedLongLong : UnsignedLongLong)
+ : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
+ }
+ IntType getLeastIntTypeByWidth(unsigned BitWidth,
+ bool IsSigned) const final {
+ // WebAssembly uses long long for int_least64_t and int_fast64_t.
+ return BitWidth == 64
+ ? (IsSigned ? SignedLongLong : UnsignedLongLong)
+ : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
+ }
+};
+
+const Builtin::Info WebAssemblyTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
+#include "clang/Basic/BuiltinsWebAssembly.def"
+};
+
+class WebAssembly32TargetInfo : public WebAssemblyTargetInfo {
+public:
+ explicit WebAssembly32TargetInfo(const llvm::Triple &T)
+ : WebAssemblyTargetInfo(T) {
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
+ DataLayoutString = "e-m:e-p:32:32-i64:64-n32:64-S128";
+ }
+
+protected:
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
+ defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
+ }
+};
+
+class WebAssembly64TargetInfo : public WebAssemblyTargetInfo {
+public:
+ explicit WebAssembly64TargetInfo(const llvm::Triple &T)
+ : WebAssemblyTargetInfo(T) {
+ LongAlign = LongWidth = 64;
+ PointerAlign = PointerWidth = 64;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ DataLayoutString = "e-m:e-p:64:64-i64:64-n32:64-S128";
+ }
+
+protected:
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
+ defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
+ }
+};
const Builtin::Info Le64TargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
- { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsLe64.def"
};
-namespace {
- static const unsigned SPIRAddrSpaceMap[] = {
- 1, // opencl_global
- 3, // opencl_local
- 2, // opencl_constant
- 4, // opencl_generic
- 0, // cuda_device
- 0, // cuda_constant
- 0 // cuda_shared
- };
- class SPIRTargetInfo : public TargetInfo {
- public:
- SPIRTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
- assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
- "SPIR target must use unknown OS");
- assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
- "SPIR target must use unknown environment type");
- BigEndian = false;
- TLSSupported = false;
- LongWidth = LongAlign = 64;
- AddrSpaceMap = &SPIRAddrSpaceMap;
- UseAddrSpaceMapMangling = true;
- // Define available target features
- // These must be defined in sorted order!
- NoAsmVariants = true;
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "SPIR", Opts);
- }
- bool hasFeature(StringRef Feature) const override {
- return Feature == "spir";
- }
-
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {}
- const char *getClobbers() const override {
- return "";
- }
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override {}
- bool
- validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const override {
- return true;
- }
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {}
- BuiltinVaListKind getBuiltinVaListKind() const override {
- return TargetInfo::VoidPtrBuiltinVaList;
- }
+static const unsigned SPIRAddrSpaceMap[] = {
+ 1, // opencl_global
+ 3, // opencl_local
+ 2, // opencl_constant
+ 4, // opencl_generic
+ 0, // cuda_device
+ 0, // cuda_constant
+ 0 // cuda_shared
+};
+class SPIRTargetInfo : public TargetInfo {
+public:
+ SPIRTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {
+ assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
+ "SPIR target must use unknown OS");
+ assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
+ "SPIR target must use unknown environment type");
+ BigEndian = false;
+ TLSSupported = false;
+ LongWidth = LongAlign = 64;
+ AddrSpaceMap = &SPIRAddrSpaceMap;
+ UseAddrSpaceMapMangling = true;
+ // Define available target features
+ // These must be defined in sorted order!
+ NoAsmVariants = true;
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ DefineStd(Builder, "SPIR", Opts);
+ }
+ bool hasFeature(StringRef Feature) const override {
+ return Feature == "spir";
+ }
- CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
- return (CC == CC_SpirFunction ||
- CC == CC_SpirKernel) ? CCCR_OK : CCCR_Warning;
- }
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+ const char *getClobbers() const override { return ""; }
+ ArrayRef<const char *> getGCCRegNames() const override { return None; }
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override {
+ return true;
+ }
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
+ }
+ BuiltinVaListKind getBuiltinVaListKind() const override {
+ return TargetInfo::VoidPtrBuiltinVaList;
+ }
- CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
- return CC_SpirFunction;
- }
- };
+ CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
+ return (CC == CC_SpirFunction || CC == CC_SpirKernel) ? CCCR_OK
+ : CCCR_Warning;
+ }
+ CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
+ return CC_SpirFunction;
+ }
+};
- class SPIR32TargetInfo : public SPIRTargetInfo {
- public:
- SPIR32TargetInfo(const llvm::Triple &Triple) : SPIRTargetInfo(Triple) {
- PointerWidth = PointerAlign = 32;
- SizeType = TargetInfo::UnsignedInt;
- PtrDiffType = IntPtrType = TargetInfo::SignedInt;
- DescriptionString
- = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
- "v96:128-v192:256-v256:256-v512:512-v1024:1024";
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "SPIR32", Opts);
- }
- };
+class SPIR32TargetInfo : public SPIRTargetInfo {
+public:
+ SPIR32TargetInfo(const llvm::Triple &Triple) : SPIRTargetInfo(Triple) {
+ PointerWidth = PointerAlign = 32;
+ SizeType = TargetInfo::UnsignedInt;
+ PtrDiffType = IntPtrType = TargetInfo::SignedInt;
+ DataLayoutString = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
+ "v96:128-v192:256-v256:256-v512:512-v1024:1024";
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ DefineStd(Builder, "SPIR32", Opts);
+ }
+};
- class SPIR64TargetInfo : public SPIRTargetInfo {
- public:
- SPIR64TargetInfo(const llvm::Triple &Triple) : SPIRTargetInfo(Triple) {
- PointerWidth = PointerAlign = 64;
- SizeType = TargetInfo::UnsignedLong;
- PtrDiffType = IntPtrType = TargetInfo::SignedLong;
- DescriptionString = "e-i64:64-v16:16-v24:32-v32:32-v48:64-"
- "v96:128-v192:256-v256:256-v512:512-v1024:1024";
- }
- void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const override {
- DefineStd(Builder, "SPIR64", Opts);
- }
- };
+class SPIR64TargetInfo : public SPIRTargetInfo {
+public:
+ SPIR64TargetInfo(const llvm::Triple &Triple) : SPIRTargetInfo(Triple) {
+ PointerWidth = PointerAlign = 64;
+ SizeType = TargetInfo::UnsignedLong;
+ PtrDiffType = IntPtrType = TargetInfo::SignedLong;
+ DataLayoutString = "e-i64:64-v16:16-v24:32-v32:32-v48:64-"
+ "v96:128-v192:256-v256:256-v512:512-v1024:1024";
+ }
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override {
+ DefineStd(Builder, "SPIR64", Opts);
+ }
+};
class XCoreTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
@@ -6903,17 +7435,16 @@ public:
WCharType = UnsignedChar;
WIntType = UnsignedInt;
UseZeroLengthBitfieldAlignment = true;
- DescriptionString = "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32"
- "-f64:32-a:0:32-n32";
+ DataLayoutString = "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32"
+ "-f64:32-a:0:32-n32";
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
Builder.defineMacro("__XS1B__");
}
- void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const override {
- Records = BuiltinInfo;
- NumRecords = clang::XCore::LastTSBuiltin-Builtin::FirstTSBuiltin;
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfo,
+ clang::XCore::LastTSBuiltin-Builtin::FirstTSBuiltin);
}
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList;
@@ -6921,19 +7452,15 @@ public:
const char *getClobbers() const override {
return "";
}
- void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const override {
+ ArrayRef<const char *> getGCCRegNames() const override {
static const char * const GCCRegNames[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "cp", "dp", "sp", "lr"
};
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
+ return llvm::makeArrayRef(GCCRegNames);
}
- void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const override {
- Aliases = nullptr;
- NumAliases = 0;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
+ return None;
}
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override {
@@ -6946,14 +7473,13 @@ public:
};
const Builtin::Info XCoreTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
- ALL_LANGUAGES },
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
+ { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
#include "clang/Basic/BuiltinsXCore.def"
};
-} // end anonymous namespace.
-namespace {
// x86_32 Android target
class AndroidX86_32TargetInfo : public LinuxTargetInfo<X86_32TargetInfo> {
public:
@@ -6964,9 +7490,7 @@ public:
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
}
};
-} // end anonymous namespace
-namespace {
// x86_64 Android target
class AndroidX86_64TargetInfo : public LinuxTargetInfo<X86_64TargetInfo> {
public:
@@ -6981,7 +7505,6 @@ public:
};
} // end anonymous namespace
-
//===----------------------------------------------------------------------===//
// Driver code
//===----------------------------------------------------------------------===//
@@ -7004,6 +7527,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
return new DarwinAArch64TargetInfo(Triple);
switch (os) {
+ case llvm::Triple::CloudABI:
+ return new CloudABITargetInfo<AArch64leTargetInfo>(Triple);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<AArch64leTargetInfo>(Triple);
case llvm::Triple::Linux:
@@ -7048,6 +7573,10 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
return new NaClTargetInfo<ARMleTargetInfo>(Triple);
case llvm::Triple::Win32:
switch (Triple.getEnvironment()) {
+ case llvm::Triple::Cygnus:
+ return new CygwinARMTargetInfo(Triple);
+ case llvm::Triple::GNU:
+ return new MinGWARMTargetInfo(Triple);
case llvm::Triple::Itanium:
return new ItaniumWindowsARMleTargetInfo(Triple);
case llvm::Triple::MSVC:
@@ -7322,6 +7851,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
return new RTEMSX86_32TargetInfo(Triple);
case llvm::Triple::NaCl:
return new NaClTargetInfo<X86_32TargetInfo>(Triple);
+ case llvm::Triple::ELFIAMCU:
+ return new MCUX86_32TargetInfo(Triple);
default:
return new X86_32TargetInfo(Triple);
}
@@ -7357,6 +7888,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
return new SolarisTargetInfo<X86_64TargetInfo>(Triple);
case llvm::Triple::Win32: {
switch (Triple.getEnvironment()) {
+ case llvm::Triple::Cygnus:
+ return new CygwinX86_64TargetInfo(Triple);
case llvm::Triple::GNU:
return new MinGWX86_64TargetInfo(Triple);
case llvm::Triple::MSVC:
@@ -7384,11 +7917,19 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple) {
return nullptr;
return new SPIR64TargetInfo(Triple);
}
+ case llvm::Triple::wasm32:
+ if (!(Triple == llvm::Triple("wasm32-unknown-unknown")))
+ return nullptr;
+ return new WebAssemblyOSTargetInfo<WebAssembly32TargetInfo>(Triple);
+ case llvm::Triple::wasm64:
+ if (!(Triple == llvm::Triple("wasm64-unknown-unknown")))
+ return nullptr;
+ return new WebAssemblyOSTargetInfo<WebAssembly64TargetInfo>(Triple);
}
}
/// CreateTargetInfo - Return the target info object for the specified target
-/// triple.
+/// options.
TargetInfo *
TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
const std::shared_ptr<TargetOptions> &Opts) {
@@ -7423,25 +7964,15 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
// Compute the default target features, we need the target to handle this
// because features may have dependencies on one another.
llvm::StringMap<bool> Features;
- Target->getDefaultFeatures(Features);
-
- // Apply the user specified deltas.
- for (unsigned I = 0, N = Opts->FeaturesAsWritten.size();
- I < N; ++I) {
- const char *Name = Opts->FeaturesAsWritten[I].c_str();
- // Apply the feature via the target.
- bool Enabled = Name[0] == '+';
- Target->setFeatureEnabled(Features, Name + 1, Enabled);
- }
+ if (!Target->initFeatureMap(Features, Diags, Opts->CPU,
+ Opts->FeaturesAsWritten))
+ return nullptr;
// Add the features to the compile options.
- //
- // FIXME: If we are completely confident that we have the right set, we only
- // need to pass the minuses.
Opts->Features.clear();
- for (llvm::StringMap<bool>::const_iterator it = Features.begin(),
- ie = Features.end(); it != ie; ++it)
- Opts->Features.push_back((it->second ? "+" : "-") + it->first().str());
+ for (const auto &F : Features)
+ Opts->Features.push_back((F.getValue() ? "+" : "-") + F.getKey().str());
+
if (!Target->handleTargetFeatures(Opts->Features, Diags))
return nullptr;
diff --git a/contrib/llvm/tools/clang/lib/Basic/Version.cpp b/contrib/llvm/tools/clang/lib/Basic/Version.cpp
index 4b10dcd..a1a67c2 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Version.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Version.cpp
@@ -36,7 +36,7 @@ std::string getClangRepositoryPath() {
// If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
// pick up a tag in an SVN export, for example.
- StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_371/final/lib/Basic/Version.cpp $");
+ StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $");
if (URL.empty()) {
URL = SVNRepository.slice(SVNRepository.find(':'),
SVNRepository.find("/lib/Basic"));
@@ -128,10 +128,8 @@ std::string getClangToolFullVersion(StringRef ToolName) {
OS << ToolName << " version " CLANG_VERSION_STRING " "
<< getClangFullRepositoryVersion();
-#ifdef CLANG_VENDOR_SUFFIX
- OS << CLANG_VENDOR_SUFFIX;
-#elif defined(CLANG_VENDOR)
// If vendor supplied, include the base LLVM version as well.
+#ifdef CLANG_VENDOR
OS << " (based on " << BACKEND_PACKAGE_STRING << ")";
#endif
diff --git a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
index a36102c..6977f40 100644
--- a/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/VirtualFileSystem.cpp
@@ -10,6 +10,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Basic/FileManager.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
@@ -19,9 +20,17 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/YAMLParser.h"
+#include "llvm/Config/llvm-config.h"
#include <atomic>
#include <memory>
+// For chdir.
+#ifdef LLVM_ON_WIN32
+# include <direct.h>
+#else
+# include <unistd.h>
+#endif
+
using namespace clang;
using namespace clang::vfs;
using namespace llvm;
@@ -35,12 +44,24 @@ Status::Status(const file_status &Status)
User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),
Type(Status.type()), Perms(Status.permissions()), IsVFSMapped(false) {}
-Status::Status(StringRef Name, StringRef ExternalName, UniqueID UID,
- sys::TimeValue MTime, uint32_t User, uint32_t Group,
- uint64_t Size, file_type Type, perms Perms)
+Status::Status(StringRef Name, UniqueID UID, sys::TimeValue MTime,
+ uint32_t User, uint32_t Group, uint64_t Size, file_type Type,
+ perms Perms)
: Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size),
Type(Type), Perms(Perms), IsVFSMapped(false) {}
+Status Status::copyWithNewName(const Status &In, StringRef NewName) {
+ return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
+ In.getUser(), In.getGroup(), In.getSize(), In.getType(),
+ In.getPermissions());
+}
+
+Status Status::copyWithNewName(const file_status &In, StringRef NewName) {
+ return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
+ In.getUser(), In.getGroup(), In.getSize(), In.type(),
+ In.permissions());
+}
+
bool Status::equivalent(const Status &Other) const {
return getUniqueID() == Other.getUniqueID();
}
@@ -77,6 +98,19 @@ FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize,
return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);
}
+std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
+ auto WorkingDir = getCurrentWorkingDirectory();
+ if (!WorkingDir)
+ return WorkingDir.getError();
+
+ return llvm::sys::fs::make_absolute(WorkingDir.get(), Path);
+}
+
+bool FileSystem::exists(const Twine &Path) {
+ auto Status = status(Path);
+ return Status && Status->exists();
+}
+
//===-----------------------------------------------------------------------===/
// RealFileSystem implementation
//===-----------------------------------------------------------------------===/
@@ -87,19 +121,20 @@ class RealFile : public File {
int FD;
Status S;
friend class RealFileSystem;
- RealFile(int FD) : FD(FD) {
+ RealFile(int FD, StringRef NewName)
+ : FD(FD), S(NewName, {}, {}, {}, {}, {},
+ llvm::sys::fs::file_type::status_error, {}) {
assert(FD >= 0 && "Invalid or inactive file descriptor");
}
public:
~RealFile() override;
ErrorOr<Status> status() override;
- ErrorOr<std::unique_ptr<MemoryBuffer>>
- getBuffer(const Twine &Name, int64_t FileSize = -1,
- bool RequiresNullTerminator = true,
- bool IsVolatile = false) override;
+ ErrorOr<std::unique_ptr<MemoryBuffer>> getBuffer(const Twine &Name,
+ int64_t FileSize,
+ bool RequiresNullTerminator,
+ bool IsVolatile) override;
std::error_code close() override;
- void setName(StringRef Name) override;
};
} // end anonymous namespace
RealFile::~RealFile() { close(); }
@@ -110,9 +145,7 @@ ErrorOr<Status> RealFile::status() {
file_status RealStatus;
if (std::error_code EC = sys::fs::status(FD, RealStatus))
return EC;
- Status NewS(RealStatus);
- NewS.setName(S.getName());
- S = std::move(NewS);
+ S = Status::copyWithNewName(RealStatus, S.getName());
}
return S;
}
@@ -142,10 +175,6 @@ std::error_code RealFile::close() {
return std::error_code();
}
-void RealFile::setName(StringRef Name) {
- S.setName(Name);
-}
-
namespace {
/// \brief The file system according to your operating system.
class RealFileSystem : public FileSystem {
@@ -153,6 +182,9 @@ public:
ErrorOr<Status> status(const Twine &Path) override;
ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
};
} // end anonymous namespace
@@ -160,9 +192,7 @@ ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
sys::fs::file_status RealStatus;
if (std::error_code EC = sys::fs::status(Path, RealStatus))
return EC;
- Status Result(RealStatus);
- Result.setName(Path.str());
- return Result;
+ return Status::copyWithNewName(RealStatus, Path.str());
}
ErrorOr<std::unique_ptr<File>>
@@ -170,9 +200,29 @@ RealFileSystem::openFileForRead(const Twine &Name) {
int FD;
if (std::error_code EC = sys::fs::openFileForRead(Name, FD))
return EC;
- std::unique_ptr<File> Result(new RealFile(FD));
- Result->setName(Name.str());
- return std::move(Result);
+ return std::unique_ptr<File>(new RealFile(FD, Name.str()));
+}
+
+llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
+ SmallString<256> Dir;
+ if (std::error_code EC = llvm::sys::fs::current_path(Dir))
+ return EC;
+ return Dir.str().str();
+}
+
+std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
+ // FIXME: chdir is thread hostile; on the other hand, creating the same
+ // behavior as chdir is complex: chdir resolves the path once, thus
+ // guaranteeing that all subsequent relative path operations work
+ // on the same path the original chdir resulted in. This makes a
+ // difference for example on network filesystems, where symlinks might be
+ // switched during runtime of the tool. Fixing this depends on having a
+ // file system abstraction that allows openat() style interactions.
+ SmallString<256> Storage;
+ StringRef Dir = Path.toNullTerminatedStringRef(Storage);
+ if (int Err = ::chdir(Dir.data()))
+ return std::error_code(Err, std::generic_category());
+ return std::error_code();
}
IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
@@ -190,10 +240,8 @@ public:
if (!EC && Iter != llvm::sys::fs::directory_iterator()) {
llvm::sys::fs::file_status S;
EC = Iter->status(S);
- if (!EC) {
- CurrentEntry = Status(S);
- CurrentEntry.setName(Iter->path());
- }
+ if (!EC)
+ CurrentEntry = Status::copyWithNewName(S, Iter->path());
}
}
@@ -207,8 +255,7 @@ public:
} else {
llvm::sys::fs::file_status S;
EC = Iter->status(S);
- CurrentEntry = Status(S);
- CurrentEntry.setName(Iter->path());
+ CurrentEntry = Status::copyWithNewName(S, Iter->path());
}
return EC;
}
@@ -224,11 +271,14 @@ directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
// OverlayFileSystem implementation
//===-----------------------------------------------------------------------===/
OverlayFileSystem::OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> BaseFS) {
- pushOverlay(BaseFS);
+ FSList.push_back(BaseFS);
}
void OverlayFileSystem::pushOverlay(IntrusiveRefCntPtr<FileSystem> FS) {
FSList.push_back(FS);
+ // Synchronize added file systems by duplicating the working directory from
+ // the first one in the list.
+ FS->setCurrentWorkingDirectory(getCurrentWorkingDirectory().get());
}
ErrorOr<Status> OverlayFileSystem::status(const Twine &Path) {
@@ -252,6 +302,19 @@ OverlayFileSystem::openFileForRead(const llvm::Twine &Path) {
return make_error_code(llvm::errc::no_such_file_or_directory);
}
+llvm::ErrorOr<std::string>
+OverlayFileSystem::getCurrentWorkingDirectory() const {
+ // All file systems are synchronized, just take the first working directory.
+ return FSList.front()->getCurrentWorkingDirectory();
+}
+std::error_code
+OverlayFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
+ for (auto &FS : FSList)
+ if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
+ return EC;
+ return std::error_code();
+}
+
clang::vfs::detail::DirIterImpl::~DirIterImpl() { }
namespace {
@@ -320,8 +383,303 @@ directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
std::make_shared<OverlayFSDirIterImpl>(Dir, *this, EC));
}
+namespace clang {
+namespace vfs {
+namespace detail {
+
+enum InMemoryNodeKind { IME_File, IME_Directory };
+
+/// The in memory file system is a tree of Nodes. Every node can either be a
+/// file or a directory.
+class InMemoryNode {
+ Status Stat;
+ InMemoryNodeKind Kind;
+
+public:
+ InMemoryNode(Status Stat, InMemoryNodeKind Kind)
+ : Stat(std::move(Stat)), Kind(Kind) {}
+ virtual ~InMemoryNode() {}
+ const Status &getStatus() const { return Stat; }
+ InMemoryNodeKind getKind() const { return Kind; }
+ virtual std::string toString(unsigned Indent) const = 0;
+};
+
+namespace {
+class InMemoryFile : public InMemoryNode {
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
+
+public:
+ InMemoryFile(Status Stat, std::unique_ptr<llvm::MemoryBuffer> Buffer)
+ : InMemoryNode(std::move(Stat), IME_File), Buffer(std::move(Buffer)) {}
+
+ llvm::MemoryBuffer *getBuffer() { return Buffer.get(); }
+ std::string toString(unsigned Indent) const override {
+ return (std::string(Indent, ' ') + getStatus().getName() + "\n").str();
+ }
+ static bool classof(const InMemoryNode *N) {
+ return N->getKind() == IME_File;
+ }
+};
+
+/// Adapt a InMemoryFile for VFS' File interface.
+class InMemoryFileAdaptor : public File {
+ InMemoryFile &Node;
+
+public:
+ explicit InMemoryFileAdaptor(InMemoryFile &Node) : Node(Node) {}
+
+ llvm::ErrorOr<Status> status() override { return Node.getStatus(); }
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
+ bool IsVolatile) override {
+ llvm::MemoryBuffer *Buf = Node.getBuffer();
+ return llvm::MemoryBuffer::getMemBuffer(
+ Buf->getBuffer(), Buf->getBufferIdentifier(), RequiresNullTerminator);
+ }
+ std::error_code close() override { return std::error_code(); }
+};
+} // end anonymous namespace
+
+class InMemoryDirectory : public InMemoryNode {
+ std::map<std::string, std::unique_ptr<InMemoryNode>> Entries;
+
+public:
+ InMemoryDirectory(Status Stat)
+ : InMemoryNode(std::move(Stat), IME_Directory) {}
+ InMemoryNode *getChild(StringRef Name) {
+ auto I = Entries.find(Name);
+ if (I != Entries.end())
+ return I->second.get();
+ return nullptr;
+ }
+ InMemoryNode *addChild(StringRef Name, std::unique_ptr<InMemoryNode> Child) {
+ return Entries.insert(make_pair(Name, std::move(Child)))
+ .first->second.get();
+ }
+
+ typedef decltype(Entries)::const_iterator const_iterator;
+ const_iterator begin() const { return Entries.begin(); }
+ const_iterator end() const { return Entries.end(); }
+
+ std::string toString(unsigned Indent) const override {
+ std::string Result =
+ (std::string(Indent, ' ') + getStatus().getName() + "\n").str();
+ for (const auto &Entry : Entries) {
+ Result += Entry.second->toString(Indent + 2);
+ }
+ return Result;
+ }
+ static bool classof(const InMemoryNode *N) {
+ return N->getKind() == IME_Directory;
+ }
+};
+}
+
+InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
+ : Root(new detail::InMemoryDirectory(
+ Status("", getNextVirtualUniqueID(), llvm::sys::TimeValue::MinTime(),
+ 0, 0, 0, llvm::sys::fs::file_type::directory_file,
+ llvm::sys::fs::perms::all_all))),
+ UseNormalizedPaths(UseNormalizedPaths) {}
+
+InMemoryFileSystem::~InMemoryFileSystem() {}
+
+std::string InMemoryFileSystem::toString() const {
+ return Root->toString(/*Indent=*/0);
+}
+
+bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+ SmallString<128> Path;
+ P.toVector(Path);
+
+ // Fix up relative paths. This just prepends the current working directory.
+ std::error_code EC = makeAbsolute(Path);
+ assert(!EC);
+ (void)EC;
+
+ if (useNormalizedPaths())
+ llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+
+ if (Path.empty())
+ return false;
+
+ detail::InMemoryDirectory *Dir = Root.get();
+ auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
+ while (true) {
+ StringRef Name = *I;
+ detail::InMemoryNode *Node = Dir->getChild(Name);
+ ++I;
+ if (!Node) {
+ if (I == E) {
+ // End of the path, create a new file.
+ // FIXME: expose the status details in the interface.
+ Status Stat(P.str(), getNextVirtualUniqueID(),
+ llvm::sys::TimeValue(ModificationTime, 0), 0, 0,
+ Buffer->getBufferSize(),
+ llvm::sys::fs::file_type::regular_file,
+ llvm::sys::fs::all_all);
+ Dir->addChild(Name, llvm::make_unique<detail::InMemoryFile>(
+ std::move(Stat), std::move(Buffer)));
+ return true;
+ }
+
+ // Create a new directory. Use the path up to here.
+ // FIXME: expose the status details in the interface.
+ Status Stat(
+ StringRef(Path.str().begin(), Name.end() - Path.str().begin()),
+ getNextVirtualUniqueID(), llvm::sys::TimeValue(ModificationTime, 0),
+ 0, 0, Buffer->getBufferSize(),
+ llvm::sys::fs::file_type::directory_file, llvm::sys::fs::all_all);
+ Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
+ Name, llvm::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
+ continue;
+ }
+
+ if (auto *NewDir = dyn_cast<detail::InMemoryDirectory>(Node)) {
+ Dir = NewDir;
+ } else {
+ assert(isa<detail::InMemoryFile>(Node) &&
+ "Must be either file or directory!");
+
+ // Trying to insert a directory in place of a file.
+ if (I != E)
+ return false;
+
+ // Return false only if the new file is different from the existing one.
+ return cast<detail::InMemoryFile>(Node)->getBuffer()->getBuffer() ==
+ Buffer->getBuffer();
+ }
+ }
+}
+
+bool InMemoryFileSystem::addFileNoOwn(const Twine &P, time_t ModificationTime,
+ llvm::MemoryBuffer *Buffer) {
+ return addFile(P, ModificationTime,
+ llvm::MemoryBuffer::getMemBuffer(
+ Buffer->getBuffer(), Buffer->getBufferIdentifier()));
+}
+
+static ErrorOr<detail::InMemoryNode *>
+lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir,
+ const Twine &P) {
+ SmallString<128> Path;
+ P.toVector(Path);
+
+ // Fix up relative paths. This just prepends the current working directory.
+ std::error_code EC = FS.makeAbsolute(Path);
+ assert(!EC);
+ (void)EC;
+
+ if (FS.useNormalizedPaths())
+ llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+
+ if (Path.empty())
+ return Dir;
+
+ auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
+ while (true) {
+ detail::InMemoryNode *Node = Dir->getChild(*I);
+ ++I;
+ if (!Node)
+ return errc::no_such_file_or_directory;
+
+ // Return the file if it's at the end of the path.
+ if (auto File = dyn_cast<detail::InMemoryFile>(Node)) {
+ if (I == E)
+ return File;
+ return errc::no_such_file_or_directory;
+ }
+
+ // Traverse directories.
+ Dir = cast<detail::InMemoryDirectory>(Node);
+ if (I == E)
+ return Dir;
+ }
+}
+
+llvm::ErrorOr<Status> InMemoryFileSystem::status(const Twine &Path) {
+ auto Node = lookupInMemoryNode(*this, Root.get(), Path);
+ if (Node)
+ return (*Node)->getStatus();
+ return Node.getError();
+}
+
+llvm::ErrorOr<std::unique_ptr<File>>
+InMemoryFileSystem::openFileForRead(const Twine &Path) {
+ auto Node = lookupInMemoryNode(*this, Root.get(), Path);
+ if (!Node)
+ return Node.getError();
+
+ // When we have a file provide a heap-allocated wrapper for the memory buffer
+ // to match the ownership semantics for File.
+ if (auto *F = dyn_cast<detail::InMemoryFile>(*Node))
+ return std::unique_ptr<File>(new detail::InMemoryFileAdaptor(*F));
+
+ // FIXME: errc::not_a_file?
+ return make_error_code(llvm::errc::invalid_argument);
+}
+
+namespace {
+/// Adaptor from InMemoryDir::iterator to directory_iterator.
+class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl {
+ detail::InMemoryDirectory::const_iterator I;
+ detail::InMemoryDirectory::const_iterator E;
+
+public:
+ InMemoryDirIterator() {}
+ explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir)
+ : I(Dir.begin()), E(Dir.end()) {
+ if (I != E)
+ CurrentEntry = I->second->getStatus();
+ }
+
+ std::error_code increment() override {
+ ++I;
+ // When we're at the end, make CurrentEntry invalid and DirIterImpl will do
+ // the rest.
+ CurrentEntry = I != E ? I->second->getStatus() : Status();
+ return std::error_code();
+ }
+};
+} // end anonymous namespace
+
+directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
+ std::error_code &EC) {
+ auto Node = lookupInMemoryNode(*this, Root.get(), Dir);
+ if (!Node) {
+ EC = Node.getError();
+ return directory_iterator(std::make_shared<InMemoryDirIterator>());
+ }
+
+ if (auto *DirNode = dyn_cast<detail::InMemoryDirectory>(*Node))
+ return directory_iterator(std::make_shared<InMemoryDirIterator>(*DirNode));
+
+ EC = make_error_code(llvm::errc::not_a_directory);
+ return directory_iterator(std::make_shared<InMemoryDirIterator>());
+}
+
+std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) {
+ SmallString<128> Path;
+ P.toVector(Path);
+
+ // Fix up relative paths. This just prepends the current working directory.
+ std::error_code EC = makeAbsolute(Path);
+ assert(!EC);
+ (void)EC;
+
+ if (useNormalizedPaths())
+ llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+
+ if (!Path.empty())
+ WorkingDirectory = Path.str();
+ return std::error_code();
+}
+}
+}
+
//===-----------------------------------------------------------------------===/
-// VFSFromYAML implementation
+// RedirectingFileSystem implementation
//===-----------------------------------------------------------------------===/
namespace {
@@ -343,23 +701,24 @@ public:
EntryKind getKind() const { return Kind; }
};
-class DirectoryEntry : public Entry {
- std::vector<Entry *> Contents;
+class RedirectingDirectoryEntry : public Entry {
+ std::vector<std::unique_ptr<Entry>> Contents;
Status S;
public:
- ~DirectoryEntry() override;
- DirectoryEntry(StringRef Name, std::vector<Entry *> Contents, Status S)
+ RedirectingDirectoryEntry(StringRef Name,
+ std::vector<std::unique_ptr<Entry>> Contents,
+ Status S)
: Entry(EK_Directory, Name), Contents(std::move(Contents)),
S(std::move(S)) {}
Status getStatus() { return S; }
- typedef std::vector<Entry *>::iterator iterator;
+ typedef decltype(Contents)::iterator iterator;
iterator contents_begin() { return Contents.begin(); }
iterator contents_end() { return Contents.end(); }
static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
};
-class FileEntry : public Entry {
+class RedirectingFileEntry : public Entry {
public:
enum NameKind {
NK_NotSet,
@@ -370,7 +729,8 @@ private:
std::string ExternalContentsPath;
NameKind UseName;
public:
- FileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
+ RedirectingFileEntry(StringRef Name, StringRef ExternalContentsPath,
+ NameKind UseName)
: Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath),
UseName(UseName) {}
StringRef getExternalContentsPath() const { return ExternalContentsPath; }
@@ -382,16 +742,18 @@ public:
static bool classof(const Entry *E) { return E->getKind() == EK_File; }
};
-class VFSFromYAML;
+class RedirectingFileSystem;
class VFSFromYamlDirIterImpl : public clang::vfs::detail::DirIterImpl {
std::string Dir;
- VFSFromYAML &FS;
- DirectoryEntry::iterator Current, End;
+ RedirectingFileSystem &FS;
+ RedirectingDirectoryEntry::iterator Current, End;
+
public:
- VFSFromYamlDirIterImpl(const Twine &Path, VFSFromYAML &FS,
- DirectoryEntry::iterator Begin,
- DirectoryEntry::iterator End, std::error_code &EC);
+ VFSFromYamlDirIterImpl(const Twine &Path, RedirectingFileSystem &FS,
+ RedirectingDirectoryEntry::iterator Begin,
+ RedirectingDirectoryEntry::iterator End,
+ std::error_code &EC);
std::error_code increment() override;
};
@@ -448,8 +810,9 @@ public:
/// In both cases, the 'name' field may contain multiple path components (e.g.
/// /path/to/file). However, any directory that contains more than one child
/// must be uniquely represented by a directory entry.
-class VFSFromYAML : public vfs::FileSystem {
- std::vector<Entry *> Roots; ///< The root(s) of the virtual file system.
+class RedirectingFileSystem : public vfs::FileSystem {
+ /// The root(s) of the virtual file system.
+ std::vector<std::unique_ptr<Entry>> Roots;
/// \brief The file system to use for external references.
IntrusiveRefCntPtr<FileSystem> ExternalFS;
@@ -466,10 +829,10 @@ class VFSFromYAML : public vfs::FileSystem {
bool UseExternalNames;
/// @}
- friend class VFSFromYAMLParser;
+ friend class RedirectingFileSystemParser;
private:
- VFSFromYAML(IntrusiveRefCntPtr<FileSystem> ExternalFS)
+ RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)
: ExternalFS(ExternalFS), CaseSensitive(true), UseExternalNames(true) {}
/// \brief Looks up \p Path in \c Roots.
@@ -484,18 +847,23 @@ private:
ErrorOr<Status> status(const Twine &Path, Entry *E);
public:
- ~VFSFromYAML() override;
-
/// \brief Parses \p Buffer, which is expected to be in YAML format and
/// returns a virtual file system representing its contents.
- static VFSFromYAML *create(std::unique_ptr<MemoryBuffer> Buffer,
- SourceMgr::DiagHandlerTy DiagHandler,
- void *DiagContext,
- IntrusiveRefCntPtr<FileSystem> ExternalFS);
+ static RedirectingFileSystem *
+ create(std::unique_ptr<MemoryBuffer> Buffer,
+ SourceMgr::DiagHandlerTy DiagHandler, void *DiagContext,
+ IntrusiveRefCntPtr<FileSystem> ExternalFS);
ErrorOr<Status> status(const Twine &Path) override;
ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+ return ExternalFS->getCurrentWorkingDirectory();
+ }
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
+ return ExternalFS->setCurrentWorkingDirectory(Path);
+ }
+
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override{
ErrorOr<Entry *> E = lookupPath(Dir);
if (!E) {
@@ -513,14 +881,14 @@ public:
return directory_iterator();
}
- DirectoryEntry *D = cast<DirectoryEntry>(*E);
+ auto *D = cast<RedirectingDirectoryEntry>(*E);
return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(Dir,
*this, D->contents_begin(), D->contents_end(), EC));
}
};
/// \brief A helper class to hold the common YAML parsing state.
-class VFSFromYAMLParser {
+class RedirectingFileSystemParser {
yaml::Stream &Stream;
void error(yaml::Node *N, const Twine &Msg) {
@@ -596,7 +964,7 @@ class VFSFromYAMLParser {
return true;
}
- Entry *parseEntry(yaml::Node *N) {
+ std::unique_ptr<Entry> parseEntry(yaml::Node *N) {
yaml::MappingNode *M = dyn_cast<yaml::MappingNode>(N);
if (!M) {
error(N, "expected mapping node for file or directory entry");
@@ -611,14 +979,13 @@ class VFSFromYAMLParser {
KeyStatusPair("use-external-name", false),
};
- DenseMap<StringRef, KeyStatus> Keys(
- &Fields[0], Fields + sizeof(Fields)/sizeof(Fields[0]));
+ DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
bool HasContents = false; // external or otherwise
- std::vector<Entry *> EntryArrayContents;
+ std::vector<std::unique_ptr<Entry>> EntryArrayContents;
std::string ExternalContentsPath;
std::string Name;
- FileEntry::NameKind UseExternalName = FileEntry::NK_NotSet;
+ auto UseExternalName = RedirectingFileEntry::NK_NotSet;
EntryKind Kind;
for (yaml::MappingNode::iterator I = M->begin(), E = M->end(); I != E;
@@ -667,8 +1034,8 @@ class VFSFromYAMLParser {
for (yaml::SequenceNode::iterator I = Contents->begin(),
E = Contents->end();
I != E; ++I) {
- if (Entry *E = parseEntry(&*I))
- EntryArrayContents.push_back(E);
+ if (std::unique_ptr<Entry> E = parseEntry(&*I))
+ EntryArrayContents.push_back(std::move(E));
else
return nullptr;
}
@@ -686,7 +1053,8 @@ class VFSFromYAMLParser {
bool Val;
if (!parseScalarBool(I->getValue(), Val))
return nullptr;
- UseExternalName = Val ? FileEntry::NK_External : FileEntry::NK_Virtual;
+ UseExternalName = Val ? RedirectingFileEntry::NK_External
+ : RedirectingFileEntry::NK_Virtual;
} else {
llvm_unreachable("key missing from Keys");
}
@@ -704,7 +1072,8 @@ class VFSFromYAMLParser {
return nullptr;
// check invalid configuration
- if (Kind == EK_Directory && UseExternalName != FileEntry::NK_NotSet) {
+ if (Kind == EK_Directory &&
+ UseExternalName != RedirectingFileEntry::NK_NotSet) {
error(N, "'use-external-name' is not supported for directories");
return nullptr;
}
@@ -718,16 +1087,17 @@ class VFSFromYAMLParser {
// Get the last component
StringRef LastComponent = sys::path::filename(Trimmed);
- Entry *Result = nullptr;
+ std::unique_ptr<Entry> Result;
switch (Kind) {
case EK_File:
- Result = new FileEntry(LastComponent, std::move(ExternalContentsPath),
- UseExternalName);
+ Result = llvm::make_unique<RedirectingFileEntry>(
+ LastComponent, std::move(ExternalContentsPath), UseExternalName);
break;
case EK_Directory:
- Result = new DirectoryEntry(LastComponent, std::move(EntryArrayContents),
- Status("", "", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0,
- 0, file_type::directory_file, sys::fs::all_all));
+ Result = llvm::make_unique<RedirectingDirectoryEntry>(
+ LastComponent, std::move(EntryArrayContents),
+ Status("", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0, 0,
+ file_type::directory_file, sys::fs::all_all));
break;
}
@@ -739,18 +1109,21 @@ class VFSFromYAMLParser {
for (sys::path::reverse_iterator I = sys::path::rbegin(Parent),
E = sys::path::rend(Parent);
I != E; ++I) {
- Result = new DirectoryEntry(*I, llvm::makeArrayRef(Result),
- Status("", "", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0,
- 0, file_type::directory_file, sys::fs::all_all));
+ std::vector<std::unique_ptr<Entry>> Entries;
+ Entries.push_back(std::move(Result));
+ Result = llvm::make_unique<RedirectingDirectoryEntry>(
+ *I, std::move(Entries),
+ Status("", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0, 0,
+ file_type::directory_file, sys::fs::all_all));
}
return Result;
}
public:
- VFSFromYAMLParser(yaml::Stream &S) : Stream(S) {}
+ RedirectingFileSystemParser(yaml::Stream &S) : Stream(S) {}
// false on error
- bool parse(yaml::Node *Root, VFSFromYAML *FS) {
+ bool parse(yaml::Node *Root, RedirectingFileSystem *FS) {
yaml::MappingNode *Top = dyn_cast<yaml::MappingNode>(Root);
if (!Top) {
error(Root, "expected mapping node");
@@ -764,8 +1137,7 @@ public:
KeyStatusPair("roots", true),
};
- DenseMap<StringRef, KeyStatus> Keys(
- &Fields[0], Fields + sizeof(Fields)/sizeof(Fields[0]));
+ DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
// Parse configuration and 'roots'
for (yaml::MappingNode::iterator I = Top->begin(), E = Top->end(); I != E;
@@ -787,8 +1159,8 @@ public:
for (yaml::SequenceNode::iterator I = Roots->begin(), E = Roots->end();
I != E; ++I) {
- if (Entry *E = parseEntry(&*I))
- FS->Roots.push_back(E);
+ if (std::unique_ptr<Entry> E = parseEntry(&*I))
+ FS->Roots.push_back(std::move(E));
else
return false;
}
@@ -831,15 +1203,11 @@ public:
};
} // end of anonymous namespace
-Entry::~Entry() {}
-DirectoryEntry::~DirectoryEntry() { llvm::DeleteContainerPointers(Contents); }
+Entry::~Entry() = default;
-VFSFromYAML::~VFSFromYAML() { llvm::DeleteContainerPointers(Roots); }
-
-VFSFromYAML *VFSFromYAML::create(std::unique_ptr<MemoryBuffer> Buffer,
- SourceMgr::DiagHandlerTy DiagHandler,
- void *DiagContext,
- IntrusiveRefCntPtr<FileSystem> ExternalFS) {
+RedirectingFileSystem *RedirectingFileSystem::create(
+ std::unique_ptr<MemoryBuffer> Buffer, SourceMgr::DiagHandlerTy DiagHandler,
+ void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS) {
SourceMgr SM;
yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
@@ -852,21 +1220,22 @@ VFSFromYAML *VFSFromYAML::create(std::unique_ptr<MemoryBuffer> Buffer,
return nullptr;
}
- VFSFromYAMLParser P(Stream);
+ RedirectingFileSystemParser P(Stream);
- std::unique_ptr<VFSFromYAML> FS(new VFSFromYAML(ExternalFS));
+ std::unique_ptr<RedirectingFileSystem> FS(
+ new RedirectingFileSystem(ExternalFS));
if (!P.parse(Root, FS.get()))
return nullptr;
return FS.release();
}
-ErrorOr<Entry *> VFSFromYAML::lookupPath(const Twine &Path_) {
+ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) {
SmallString<256> Path;
Path_.toVector(Path);
// Handle relative paths
- if (std::error_code EC = sys::fs::make_absolute(Path))
+ if (std::error_code EC = makeAbsolute(Path))
return EC;
if (Path.empty())
@@ -874,18 +1243,17 @@ ErrorOr<Entry *> VFSFromYAML::lookupPath(const Twine &Path_) {
sys::path::const_iterator Start = sys::path::begin(Path);
sys::path::const_iterator End = sys::path::end(Path);
- for (std::vector<Entry *>::iterator I = Roots.begin(), E = Roots.end();
- I != E; ++I) {
- ErrorOr<Entry *> Result = lookupPath(Start, End, *I);
+ for (const std::unique_ptr<Entry> &Root : Roots) {
+ ErrorOr<Entry *> Result = lookupPath(Start, End, Root.get());
if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
return Result;
}
return make_error_code(llvm::errc::no_such_file_or_directory);
}
-ErrorOr<Entry *> VFSFromYAML::lookupPath(sys::path::const_iterator Start,
- sys::path::const_iterator End,
- Entry *From) {
+ErrorOr<Entry *>
+RedirectingFileSystem::lookupPath(sys::path::const_iterator Start,
+ sys::path::const_iterator End, Entry *From) {
if (Start->equals("."))
++Start;
@@ -902,52 +1270,78 @@ ErrorOr<Entry *> VFSFromYAML::lookupPath(sys::path::const_iterator Start,
return From;
}
- DirectoryEntry *DE = dyn_cast<DirectoryEntry>(From);
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(From);
if (!DE)
return make_error_code(llvm::errc::not_a_directory);
- for (DirectoryEntry::iterator I = DE->contents_begin(),
- E = DE->contents_end();
- I != E; ++I) {
- ErrorOr<Entry *> Result = lookupPath(Start, End, *I);
+ for (const std::unique_ptr<Entry> &DirEntry :
+ llvm::make_range(DE->contents_begin(), DE->contents_end())) {
+ ErrorOr<Entry *> Result = lookupPath(Start, End, DirEntry.get());
if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
return Result;
}
return make_error_code(llvm::errc::no_such_file_or_directory);
}
-ErrorOr<Status> VFSFromYAML::status(const Twine &Path, Entry *E) {
+static Status getRedirectedFileStatus(const Twine &Path, bool UseExternalNames,
+ Status ExternalStatus) {
+ Status S = ExternalStatus;
+ if (!UseExternalNames)
+ S = Status::copyWithNewName(S, Path.str());
+ S.IsVFSMapped = true;
+ return S;
+}
+
+ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path, Entry *E) {
assert(E != nullptr);
- std::string PathStr(Path.str());
- if (FileEntry *F = dyn_cast<FileEntry>(E)) {
+ if (auto *F = dyn_cast<RedirectingFileEntry>(E)) {
ErrorOr<Status> S = ExternalFS->status(F->getExternalContentsPath());
assert(!S || S->getName() == F->getExternalContentsPath());
- if (S && !F->useExternalName(UseExternalNames))
- S->setName(PathStr);
if (S)
- S->IsVFSMapped = true;
+ return getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
+ *S);
return S;
} else { // directory
- DirectoryEntry *DE = cast<DirectoryEntry>(E);
- Status S = DE->getStatus();
- S.setName(PathStr);
- return S;
+ auto *DE = cast<RedirectingDirectoryEntry>(E);
+ return Status::copyWithNewName(DE->getStatus(), Path.str());
}
}
-ErrorOr<Status> VFSFromYAML::status(const Twine &Path) {
+ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path) {
ErrorOr<Entry *> Result = lookupPath(Path);
if (!Result)
return Result.getError();
return status(Path, *Result);
}
-ErrorOr<std::unique_ptr<File>> VFSFromYAML::openFileForRead(const Twine &Path) {
+namespace {
+/// Provide a file wrapper with an overriden status.
+class FileWithFixedStatus : public File {
+ std::unique_ptr<File> InnerFile;
+ Status S;
+
+public:
+ FileWithFixedStatus(std::unique_ptr<File> InnerFile, Status S)
+ : InnerFile(std::move(InnerFile)), S(S) {}
+
+ ErrorOr<Status> status() override { return S; }
+ ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
+ bool IsVolatile) override {
+ return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
+ IsVolatile);
+ }
+ std::error_code close() override { return InnerFile->close(); }
+};
+} // end anonymous namespace
+
+ErrorOr<std::unique_ptr<File>>
+RedirectingFileSystem::openFileForRead(const Twine &Path) {
ErrorOr<Entry *> E = lookupPath(Path);
if (!E)
return E.getError();
- FileEntry *F = dyn_cast<FileEntry>(*E);
+ auto *F = dyn_cast<RedirectingFileEntry>(*E);
if (!F) // FIXME: errc::not_a_file?
return make_error_code(llvm::errc::invalid_argument);
@@ -955,18 +1349,23 @@ ErrorOr<std::unique_ptr<File>> VFSFromYAML::openFileForRead(const Twine &Path) {
if (!Result)
return Result;
- if (!F->useExternalName(UseExternalNames))
- (*Result)->setName(Path.str());
+ auto ExternalStatus = (*Result)->status();
+ if (!ExternalStatus)
+ return ExternalStatus.getError();
- return Result;
+ // FIXME: Update the status with the name and VFSMapped.
+ Status S = getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
+ *ExternalStatus);
+ return std::unique_ptr<File>(
+ llvm::make_unique<FileWithFixedStatus>(std::move(*Result), S));
}
IntrusiveRefCntPtr<FileSystem>
vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
SourceMgr::DiagHandlerTy DiagHandler, void *DiagContext,
IntrusiveRefCntPtr<FileSystem> ExternalFS) {
- return VFSFromYAML::create(std::move(Buffer), DiagHandler, DiagContext,
- ExternalFS);
+ return RedirectingFileSystem::create(std::move(Buffer), DiagHandler,
+ DiagContext, ExternalFS);
}
UniqueID vfs::getNextVirtualUniqueID() {
@@ -1111,11 +1510,10 @@ void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
JSONWriter(OS).write(Mappings, IsCaseSensitive);
}
-VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(const Twine &_Path,
- VFSFromYAML &FS,
- DirectoryEntry::iterator Begin,
- DirectoryEntry::iterator End,
- std::error_code &EC)
+VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(
+ const Twine &_Path, RedirectingFileSystem &FS,
+ RedirectingDirectoryEntry::iterator Begin,
+ RedirectingDirectoryEntry::iterator End, std::error_code &EC)
: Dir(_Path.str()), FS(FS), Current(Begin), End(End) {
if (Current != End) {
SmallString<128> PathStr(Dir);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h
index cc8652e..a65f270 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ABIInfo.h
@@ -25,6 +25,8 @@ namespace clang {
class TargetInfo;
namespace CodeGen {
+ class ABIArgInfo;
+ class Address;
class CGCXXABI;
class CGFunctionInfo;
class CodeGenFunction;
@@ -79,8 +81,15 @@ namespace clang {
// the ABI information any lower than CodeGen. Of course, for
// VAArg handling it has to be at this level; there is no way to
// abstract this out.
- virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGen::CodeGenFunction &CGF) const = 0;
+ virtual CodeGen::Address EmitVAArg(CodeGen::CodeGenFunction &CGF,
+ CodeGen::Address VAListAddr,
+ QualType Ty) const = 0;
+
+ /// Emit the target dependent code to load a value of
+ /// \arg Ty from the \c __builtin_ms_va_list pointed to by \arg VAListAddr.
+ virtual CodeGen::Address EmitMSVAArg(CodeGen::CodeGenFunction &CGF,
+ CodeGen::Address VAListAddr,
+ QualType Ty) const;
virtual bool isHomogeneousAggregateBaseType(QualType Ty) const;
@@ -92,6 +101,15 @@ namespace clang {
bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
uint64_t &Members) const;
+ /// A convenience method to return an indirect ABIArgInfo with an
+ /// expected alignment equal to the ABI alignment of the given type.
+ CodeGen::ABIArgInfo
+ getNaturalAlignIndirect(QualType Ty, bool ByRef = true,
+ bool Realign = false,
+ llvm::Type *Padding = nullptr) const;
+
+ CodeGen::ABIArgInfo
+ getNaturalAlignIndirectInReg(QualType Ty, bool Realign = false) const;
};
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/Address.h b/contrib/llvm/tools/clang/lib/CodeGen/Address.h
new file mode 100644
index 0000000..9d145fa
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/Address.h
@@ -0,0 +1,126 @@
+//===-- Address.h - An aligned address -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class provides a simple wrapper for a pair of a pointer and an
+// alignment.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
+#define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
+
+#include "llvm/IR/Constants.h"
+#include "clang/AST/CharUnits.h"
+
+namespace clang {
+namespace CodeGen {
+
+/// An aligned address.
+class Address {
+ llvm::Value *Pointer;
+ CharUnits Alignment;
+public:
+ Address(llvm::Value *pointer, CharUnits alignment)
+ : Pointer(pointer), Alignment(alignment) {
+ assert((!alignment.isZero() || pointer == nullptr) &&
+ "creating valid address with invalid alignment");
+ }
+
+ static Address invalid() { return Address(nullptr, CharUnits()); }
+ bool isValid() const { return Pointer != nullptr; }
+
+ llvm::Value *getPointer() const {
+ assert(isValid());
+ return Pointer;
+ }
+
+ /// Return the type of the pointer value.
+ llvm::PointerType *getType() const {
+ return llvm::cast<llvm::PointerType>(getPointer()->getType());
+ }
+
+ /// Return the type of the values stored in this address.
+ ///
+ /// When IR pointer types lose their element type, we should simply
+ /// store it in Address instead for the convenience of writing code.
+ llvm::Type *getElementType() const {
+ return getType()->getElementType();
+ }
+
+ /// Return the address space that this address resides in.
+ unsigned getAddressSpace() const {
+ return getType()->getAddressSpace();
+ }
+
+ /// Return the IR name of the pointer value.
+ llvm::StringRef getName() const {
+ return getPointer()->getName();
+ }
+
+ /// Return the alignment of this pointer.
+ CharUnits getAlignment() const {
+ assert(isValid());
+ return Alignment;
+ }
+};
+
+/// A specialization of Address that requires the address to be an
+/// LLVM Constant.
+class ConstantAddress : public Address {
+public:
+ ConstantAddress(llvm::Constant *pointer, CharUnits alignment)
+ : Address(pointer, alignment) {}
+
+ static ConstantAddress invalid() {
+ return ConstantAddress(nullptr, CharUnits());
+ }
+
+ llvm::Constant *getPointer() const {
+ return llvm::cast<llvm::Constant>(Address::getPointer());
+ }
+
+ ConstantAddress getBitCast(llvm::Type *ty) const {
+ return ConstantAddress(llvm::ConstantExpr::getBitCast(getPointer(), ty),
+ getAlignment());
+ }
+
+ ConstantAddress getElementBitCast(llvm::Type *ty) const {
+ return getBitCast(ty->getPointerTo(getAddressSpace()));
+ }
+
+ static bool isaImpl(Address addr) {
+ return llvm::isa<llvm::Constant>(addr.getPointer());
+ }
+ static ConstantAddress castImpl(Address addr) {
+ return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()),
+ addr.getAlignment());
+ }
+};
+
+}
+}
+
+namespace llvm {
+ // Present a minimal LLVM-like casting interface.
+ template <class U> inline U cast(clang::CodeGen::Address addr) {
+ return U::castImpl(addr);
+ }
+ template <class U> inline bool isa(clang::CodeGen::Address addr) {
+ return U::isaImpl(addr);
+ }
+}
+
+namespace clang {
+ // Make our custom isa and cast available in namespace clang, to mirror
+ // what we do for LLVM's versions in Basic/LLVM.h.
+ using llvm::isa;
+ using llvm::cast;
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
index afcb9e5..6d746c2 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp
@@ -14,6 +14,7 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
@@ -21,11 +22,13 @@
#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/Verifier.h"
#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/TargetRegistry.h"
@@ -94,7 +97,7 @@ private:
return PerFunctionPasses;
}
- void CreatePasses();
+ void CreatePasses(FunctionInfoIndex *FunctionIndex);
/// Generates the TargetMachine.
/// Returns Null if it is unable to create the target machine.
@@ -112,15 +115,13 @@ private:
bool AddEmitPasses(BackendAction Action, raw_pwrite_stream &OS);
public:
- EmitAssemblyHelper(DiagnosticsEngine &_Diags,
- const CodeGenOptions &CGOpts,
+ EmitAssemblyHelper(DiagnosticsEngine &_Diags, 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) {}
+ 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) {}
~EmitAssemblyHelper() {
delete CodeGenPasses;
@@ -166,14 +167,6 @@ static void addObjCARCOptPass(const PassManagerBuilder &Builder, PassManagerBase
PM.add(createObjCARCOptPass());
}
-static void addSampleProfileLoaderPass(const PassManagerBuilder &Builder,
- legacy::PassManagerBase &PM) {
- const PassManagerBuilderWrapper &BuilderWrapper =
- static_cast<const PassManagerBuilderWrapper &>(Builder);
- const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
- PM.add(createSampleProfileLoaderPass(CGOpts.SampleProfileFile));
-}
-
static void addAddDiscriminatorsPass(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
PM.add(createAddDiscriminatorsPass());
@@ -201,14 +194,20 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
- PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/false));
- PM.add(createAddressSanitizerModulePass(/*CompileKernel*/false));
+ const PassManagerBuilderWrapper &BuilderWrapper =
+ static_cast<const PassManagerBuilderWrapper&>(Builder);
+ const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
+ bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Address);
+ PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/false, Recover));
+ PM.add(createAddressSanitizerModulePass(/*CompileKernel*/false, Recover));
}
static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
- PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/true));
- PM.add(createAddressSanitizerModulePass(/*CompileKernel*/true));
+ PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/true,
+ /*Recover*/true));
+ PM.add(createAddressSanitizerModulePass(/*CompileKernel*/true,
+ /*Recover*/true));
}
static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
@@ -249,6 +248,13 @@ static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple);
if (!CodeGenOpts.SimplifyLibCalls)
TLII->disableAllFunctions();
+ else {
+ // Disable individual libc/libm calls in TargetLibraryInfo.
+ LibFunc::Func F;
+ for (auto &FuncName : CodeGenOpts.getNoBuiltinFuncs())
+ if (TLII->getLibFunc(FuncName, F))
+ TLII->setUnavailable(F);
+ }
switch (CodeGenOpts.getVecLib()) {
case CodeGenOptions::Accelerate:
@@ -271,7 +277,10 @@ static void addSymbolRewriterPass(const CodeGenOptions &Opts,
MPM->add(createRewriteSymbolsPass(DL));
}
-void EmitAssemblyHelper::CreatePasses() {
+void EmitAssemblyHelper::CreatePasses(FunctionInfoIndex *FunctionIndex) {
+ if (CodeGenOpts.DisableLLVMPasses)
+ return;
+
unsigned OptLevel = CodeGenOpts.OptimizationLevel;
CodeGenOptions::InliningMethod Inlining = CodeGenOpts.getInlining();
@@ -283,6 +292,29 @@ void EmitAssemblyHelper::CreatePasses() {
}
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.SizeLevel = CodeGenOpts.OptimizeSize;
PMBuilder.BBVectorize = CodeGenOpts.VectorizeBB;
@@ -295,13 +327,19 @@ void EmitAssemblyHelper::CreatePasses() {
PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO;
PMBuilder.RerollLoops = CodeGenOpts.RerollLoops;
+ legacy::PassManager *MPM = getPerModulePasses();
+
+ // 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.SampleProfileFile.empty())
- PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
- addSampleProfileLoaderPass);
-
// In ObjC ARC mode, add the main ARC optimization passes.
if (LangOpts.ObjCAutoRefCount) {
PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
@@ -363,27 +401,6 @@ void EmitAssemblyHelper::CreatePasses() {
addDataFlowSanitizerPass);
}
- // 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;
- }
-
// Set up the per-function pass manager.
legacy::FunctionPassManager *FPM = getPerFunctionPasses();
if (CodeGenOpts.VerifyModule)
@@ -391,7 +408,6 @@ void EmitAssemblyHelper::CreatePasses() {
PMBuilder.populateFunctionPassManager(*FPM);
// Set up the per-module pass manager.
- legacy::PassManager *MPM = getPerModulePasses();
if (!CodeGenOpts.RewriteMapFiles.empty())
addSymbolRewriterPass(CodeGenOpts, MPM);
@@ -420,6 +436,9 @@ void EmitAssemblyHelper::CreatePasses() {
MPM->add(createInstrProfilingPass(Options));
}
+ if (!CodeGenOpts.SampleProfileFile.empty())
+ MPM->add(createSampleProfileLoaderPass(CodeGenOpts.SampleProfileFile));
+
PMBuilder.populateModulePassManager(*MPM);
}
@@ -455,20 +474,16 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
BackendArgs.push_back("-limit-float-precision");
BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
}
- for (unsigned i = 0, e = CodeGenOpts.BackendOptions.size(); i != e; ++i)
- BackendArgs.push_back(CodeGenOpts.BackendOptions[i].c_str());
+ for (const std::string &BackendOption : CodeGenOpts.BackendOptions)
+ BackendArgs.push_back(BackendOption.c_str());
BackendArgs.push_back(nullptr);
llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
BackendArgs.data());
- std::string FeaturesStr;
- if (!TargetOpts.Features.empty()) {
- SubtargetFeatures Features;
- for (const std::string &Feature : TargetOpts.Features)
- Features.AddFeature(Feature);
- FeaturesStr = Features.getString();
- }
+ 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;
@@ -497,24 +512,16 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
.Case("posix", llvm::ThreadModel::POSIX)
.Case("single", llvm::ThreadModel::Single);
- if (CodeGenOpts.DisableIntegratedAS)
- Options.DisableIntegratedAS = true;
-
- if (CodeGenOpts.CompressDebugSections)
- Options.CompressDebugSections = true;
-
- if (CodeGenOpts.UseInitArray)
- Options.UseInitArray = true;
-
// Set float ABI type.
- if (CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp")
- Options.FloatABIType = llvm::FloatABI::Soft;
- else if (CodeGenOpts.FloatABI == "hard")
- Options.FloatABIType = llvm::FloatABI::Hard;
- else {
- assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!");
- Options.FloatABIType = llvm::FloatABI::Default;
- }
+ 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()) {
@@ -529,6 +536,17 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
break;
}
+ 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);
+
Options.LessPreciseFPMADOption = CodeGenOpts.LessPreciseFPMAD;
Options.NoInfsFPMath = CodeGenOpts.NoInfsFPMath;
Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath;
@@ -539,11 +557,27 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
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;
@@ -605,16 +639,37 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
if (UsesCodeGen && !TM)
return;
if (TM)
- TheModule->setDataLayout(*TM->getDataLayout());
- CreatePasses();
+ 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");
+ }
+
+ CreatePasses(FunctionIndex.get());
switch (Action) {
case Backend_EmitNothing:
break;
case Backend_EmitBC:
- getPerModulePasses()->add(
- createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists));
+ getPerModulePasses()->add(createBitcodeWriterPass(
+ *OS, CodeGenOpts.EmitLLVMUseLists, CodeGenOpts.EmitFunctionSummary));
break;
case Backend_EmitLL:
@@ -667,8 +722,7 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
// If an optional clang TargetInfo description string was passed in, use it to
// verify the LLVM TargetMachine's DataLayout.
if (AsmHelper.TM && !TDesc.empty()) {
- std::string DLDesc =
- AsmHelper.TM->getDataLayout()->getStringRepresentation();
+ std::string DLDesc = M->getDataLayout().getStringRepresentation();
if (DLDesc != TDesc) {
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "backend data layout '%0' does not match "
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
index fc4b66b..24de30b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGAtomic.cpp
@@ -80,7 +80,7 @@ namespace {
AtomicSizeInBits = C.toBits(
C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1)
.RoundUpToAlignment(lvalue.getAlignment()));
- auto VoidPtrAddr = CGF.EmitCastToVoidPtr(lvalue.getBitFieldAddr());
+ auto VoidPtrAddr = CGF.EmitCastToVoidPtr(lvalue.getBitFieldPointer());
auto OffsetInChars =
(C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) *
lvalue.getAlignment();
@@ -94,8 +94,9 @@ namespace {
BFI.Offset = Offset;
BFI.StorageSize = AtomicSizeInBits;
BFI.StorageOffset += OffsetInChars;
- LVal = LValue::MakeBitfield(Addr, BFI, lvalue.getType(),
- lvalue.getAlignment());
+ LVal = LValue::MakeBitfield(Address(Addr, lvalue.getAlignment()),
+ BFI, lvalue.getType(),
+ lvalue.getAlignmentSource());
LVal.setTBAAInfo(lvalue.getTBAAInfo());
AtomicTy = C.getIntTypeForBitwidth(AtomicSizeInBits, OrigBFI.IsSigned);
if (AtomicTy.isNull()) {
@@ -118,10 +119,8 @@ namespace {
ValueTy = lvalue.getType();
ValueSizeInBits = C.getTypeSize(ValueTy);
AtomicTy = ValueTy = CGF.getContext().getExtVectorType(
- lvalue.getType(), lvalue.getExtVectorAddr()
- ->getType()
- ->getPointerElementType()
- ->getVectorNumElements());
+ lvalue.getType(), lvalue.getExtVectorAddress()
+ .getElementType()->getVectorNumElements());
AtomicSizeInBits = C.getTypeSize(AtomicTy);
AtomicAlign = ValueAlign = lvalue.getAlignment();
LVal = lvalue;
@@ -139,15 +138,22 @@ namespace {
TypeEvaluationKind getEvaluationKind() const { return EvaluationKind; }
bool shouldUseLibcall() const { return UseLibcall; }
const LValue &getAtomicLValue() const { return LVal; }
- llvm::Value *getAtomicAddress() const {
+ llvm::Value *getAtomicPointer() const {
if (LVal.isSimple())
- return LVal.getAddress();
+ return LVal.getPointer();
else if (LVal.isBitField())
- return LVal.getBitFieldAddr();
+ return LVal.getBitFieldPointer();
else if (LVal.isVectorElt())
- return LVal.getVectorAddr();
+ return LVal.getVectorPointer();
assert(LVal.isExtVectorElt());
- return LVal.getExtVectorAddr();
+ return LVal.getExtVectorPointer();
+ }
+ Address getAtomicAddress() const {
+ return Address(getAtomicPointer(), getAtomicAlignment());
+ }
+
+ Address getAtomicAddressAsAtomicIntPointer() const {
+ return emitCastToAtomicIntPointer(getAtomicAddress());
}
/// Is the atomic size larger than the underlying value type?
@@ -167,13 +173,18 @@ namespace {
return CGF.CGM.getSize(size);
}
- /// Cast the given pointer to an integer pointer suitable for
- /// atomic operations.
- llvm::Value *emitCastToAtomicIntPointer(llvm::Value *addr) const;
+ /// Cast the given pointer to an integer pointer suitable for atomic
+ /// operations if the source.
+ Address emitCastToAtomicIntPointer(Address Addr) const;
+
+ /// If Addr is compatible with the iN that will be used for an atomic
+ /// operation, bitcast it. Otherwise, create a temporary that is suitable
+ /// and copy the value across.
+ Address convertToAtomicIntPointer(Address Addr) const;
/// Turn an atomic-layout object into an r-value.
- RValue convertTempToRValue(llvm::Value *addr, AggValueSlot resultSlot,
- SourceLocation loc, bool AsValue) const;
+ RValue convertAtomicTempToRValue(Address addr, AggValueSlot resultSlot,
+ SourceLocation loc, bool AsValue) const;
/// \brief Converts a rvalue to integer value.
llvm::Value *convertRValueToInt(RValue RVal) const;
@@ -188,12 +199,12 @@ namespace {
/// Project an l-value down to the value field.
LValue projectValue() const {
assert(LVal.isSimple());
- llvm::Value *addr = getAtomicAddress();
+ Address addr = getAtomicAddress();
if (hasPadding())
- addr = CGF.Builder.CreateStructGEP(nullptr, addr, 0);
+ addr = CGF.Builder.CreateStructGEP(addr, 0, CharUnits());
- return LValue::MakeAddr(addr, getValueType(), LVal.getAlignment(),
- CGF.getContext(), LVal.getTBAAInfo());
+ return LValue::MakeAddr(addr, getValueType(), CGF.getContext(),
+ LVal.getAlignmentSource(), LVal.getTBAAInfo());
}
/// \brief Emits atomic load.
@@ -228,18 +239,18 @@ namespace {
bool IsVolatile);
/// Materialize an atomic r-value in atomic-layout memory.
- llvm::Value *materializeRValue(RValue rvalue) const;
+ Address materializeRValue(RValue rvalue) const;
/// \brief Translates LLVM atomic ordering to GNU atomic ordering for
/// libcalls.
static AtomicExpr::AtomicOrderingKind
translateAtomicOrdering(const llvm::AtomicOrdering AO);
+ /// \brief Creates temp alloca for intermediate operations on atomic value.
+ Address CreateTempAlloca() const;
private:
bool requiresMemSetZero(llvm::Type *type) const;
- /// \brief Creates temp alloca for intermediate operations on atomic value.
- llvm::Value *CreateTempAlloca() const;
/// \brief Emits atomic load as a libcall.
void EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
@@ -294,16 +305,16 @@ AtomicInfo::translateAtomicOrdering(const llvm::AtomicOrdering AO) {
llvm_unreachable("Unhandled AtomicOrdering");
}
-llvm::Value *AtomicInfo::CreateTempAlloca() const {
- auto *TempAlloca = CGF.CreateMemTemp(
+Address AtomicInfo::CreateTempAlloca() const {
+ Address TempAlloca = CGF.CreateMemTemp(
(LVal.isBitField() && ValueSizeInBits > AtomicSizeInBits) ? ValueTy
: AtomicTy,
+ getAtomicAlignment(),
"atomic-temp");
- TempAlloca->setAlignment(getAtomicAlignment().getQuantity());
// Cast to pointer to value type for bitfields.
if (LVal.isBitField())
return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- TempAlloca, getAtomicAddress()->getType());
+ TempAlloca, getAtomicAddress().getType());
return TempAlloca;
}
@@ -351,7 +362,7 @@ bool AtomicInfo::requiresMemSetZero(llvm::Type *type) const {
bool AtomicInfo::emitMemSetZeroIfNecessary() const {
assert(LVal.isSimple());
- llvm::Value *addr = LVal.getAddress();
+ llvm::Value *addr = LVal.getPointer();
if (!requiresMemSetZero(addr->getType()->getPointerElementType()))
return false;
@@ -363,19 +374,17 @@ bool AtomicInfo::emitMemSetZeroIfNecessary() const {
}
static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,
- llvm::Value *Dest, llvm::Value *Ptr,
- llvm::Value *Val1, llvm::Value *Val2,
- uint64_t Size, unsigned Align,
+ Address Dest, Address Ptr,
+ Address Val1, Address Val2,
+ uint64_t Size,
llvm::AtomicOrdering SuccessOrder,
llvm::AtomicOrdering FailureOrder) {
// Note that cmpxchg doesn't support weak cmpxchg, at least at the moment.
- llvm::LoadInst *Expected = CGF.Builder.CreateLoad(Val1);
- Expected->setAlignment(Align);
- llvm::LoadInst *Desired = CGF.Builder.CreateLoad(Val2);
- Desired->setAlignment(Align);
+ llvm::Value *Expected = CGF.Builder.CreateLoad(Val1);
+ llvm::Value *Desired = CGF.Builder.CreateLoad(Val2);
llvm::AtomicCmpXchgInst *Pair = CGF.Builder.CreateAtomicCmpXchg(
- Ptr, Expected, Desired, SuccessOrder, FailureOrder);
+ Ptr.getPointer(), Expected, Desired, SuccessOrder, FailureOrder);
Pair->setVolatile(E->isVolatile());
Pair->setWeak(IsWeak);
@@ -400,26 +409,24 @@ static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,
CGF.Builder.SetInsertPoint(StoreExpectedBB);
// Update the memory at Expected with Old's value.
- llvm::StoreInst *StoreExpected = CGF.Builder.CreateStore(Old, Val1);
- StoreExpected->setAlignment(Align);
+ CGF.Builder.CreateStore(Old, Val1);
// Finally, branch to the exit point.
CGF.Builder.CreateBr(ContinueBB);
CGF.Builder.SetInsertPoint(ContinueBB);
// Update the memory at Dest with Cmp's value.
CGF.EmitStoreOfScalar(Cmp, CGF.MakeAddrLValue(Dest, E->getType()));
- return;
}
/// Given an ordering required on success, emit all possible cmpxchg
/// instructions to cope with the provided (but possibly only dynamically known)
/// FailureOrder.
static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
- bool IsWeak, llvm::Value *Dest,
- llvm::Value *Ptr, llvm::Value *Val1,
- llvm::Value *Val2,
+ bool IsWeak, Address Dest,
+ Address Ptr, Address Val1,
+ Address Val2,
llvm::Value *FailureOrderVal,
- uint64_t Size, unsigned Align,
+ uint64_t Size,
llvm::AtomicOrdering SuccessOrder) {
llvm::AtomicOrdering FailureOrder;
if (llvm::ConstantInt *FO = dyn_cast<llvm::ConstantInt>(FailureOrderVal)) {
@@ -440,7 +447,7 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
FailureOrder =
llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(SuccessOrder);
}
- emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, Align,
+ emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size,
SuccessOrder, FailureOrder);
return;
}
@@ -465,13 +472,13 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
// doesn't fold to a constant for the ordering.
CGF.Builder.SetInsertPoint(MonotonicBB);
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
- Size, Align, SuccessOrder, llvm::Monotonic);
+ Size, SuccessOrder, llvm::Monotonic);
CGF.Builder.CreateBr(ContBB);
if (AcquireBB) {
CGF.Builder.SetInsertPoint(AcquireBB);
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
- Size, Align, SuccessOrder, llvm::Acquire);
+ Size, SuccessOrder, llvm::Acquire);
CGF.Builder.CreateBr(ContBB);
SI->addCase(CGF.Builder.getInt32(AtomicExpr::AO_ABI_memory_order_consume),
AcquireBB);
@@ -481,7 +488,7 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
if (SeqCstBB) {
CGF.Builder.SetInsertPoint(SeqCstBB);
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
- Size, Align, SuccessOrder, llvm::SequentiallyConsistent);
+ Size, SuccessOrder, llvm::SequentiallyConsistent);
CGF.Builder.CreateBr(ContBB);
SI->addCase(CGF.Builder.getInt32(AtomicExpr::AO_ABI_memory_order_seq_cst),
SeqCstBB);
@@ -490,11 +497,10 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
CGF.Builder.SetInsertPoint(ContBB);
}
-static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, llvm::Value *Dest,
- llvm::Value *Ptr, llvm::Value *Val1, llvm::Value *Val2,
+static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
+ Address Ptr, Address Val1, Address Val2,
llvm::Value *IsWeak, llvm::Value *FailureOrder,
- uint64_t Size, unsigned Align,
- llvm::AtomicOrdering Order) {
+ uint64_t Size, llvm::AtomicOrdering Order) {
llvm::AtomicRMWInst::BinOp Op = llvm::AtomicRMWInst::Add;
llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0;
@@ -504,17 +510,17 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, llvm::Value *Dest,
case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,
- FailureOrder, Size, Align, Order);
+ FailureOrder, Size, Order);
return;
case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,
- FailureOrder, Size, Align, Order);
+ FailureOrder, Size, Order);
return;
case AtomicExpr::AO__atomic_compare_exchange:
case AtomicExpr::AO__atomic_compare_exchange_n: {
if (llvm::ConstantInt *IsWeakC = dyn_cast<llvm::ConstantInt>(IsWeak)) {
emitAtomicCmpXchgFailureSet(CGF, E, IsWeakC->getZExtValue(), Dest, Ptr,
- Val1, Val2, FailureOrder, Size, Align, Order);
+ Val1, Val2, FailureOrder, Size, Order);
} else {
// Create all the relevant BB's
llvm::BasicBlock *StrongBB =
@@ -528,12 +534,12 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, llvm::Value *Dest,
CGF.Builder.SetInsertPoint(StrongBB);
emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,
- FailureOrder, Size, Align, Order);
+ FailureOrder, Size, Order);
CGF.Builder.CreateBr(ContBB);
CGF.Builder.SetInsertPoint(WeakBB);
emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,
- FailureOrder, Size, Align, Order);
+ FailureOrder, Size, Order);
CGF.Builder.CreateBr(ContBB);
CGF.Builder.SetInsertPoint(ContBB);
@@ -545,22 +551,17 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, llvm::Value *Dest,
case AtomicExpr::AO__atomic_load: {
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr);
Load->setAtomic(Order);
- Load->setAlignment(Size);
Load->setVolatile(E->isVolatile());
- llvm::StoreInst *StoreDest = CGF.Builder.CreateStore(Load, Dest);
- StoreDest->setAlignment(Align);
+ CGF.Builder.CreateStore(Load, Dest);
return;
}
case AtomicExpr::AO__c11_atomic_store:
case AtomicExpr::AO__atomic_store:
case AtomicExpr::AO__atomic_store_n: {
- assert(!Dest && "Store does not return a value");
- llvm::LoadInst *LoadVal1 = CGF.Builder.CreateLoad(Val1);
- LoadVal1->setAlignment(Align);
+ llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);
llvm::StoreInst *Store = CGF.Builder.CreateStore(LoadVal1, Ptr);
Store->setAtomic(Order);
- Store->setAlignment(Size);
Store->setVolatile(E->isVolatile());
return;
}
@@ -612,17 +613,16 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, llvm::Value *Dest,
break;
case AtomicExpr::AO__atomic_nand_fetch:
- PostOp = llvm::Instruction::And;
- // Fall through.
+ PostOp = llvm::Instruction::And; // the NOT is special cased below
+ // Fall through.
case AtomicExpr::AO__atomic_fetch_nand:
Op = llvm::AtomicRMWInst::Nand;
break;
}
- llvm::LoadInst *LoadVal1 = CGF.Builder.CreateLoad(Val1);
- LoadVal1->setAlignment(Align);
+ llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);
llvm::AtomicRMWInst *RMWI =
- CGF.Builder.CreateAtomicRMW(Op, Ptr, LoadVal1, Order);
+ CGF.Builder.CreateAtomicRMW(Op, Ptr.getPointer(), LoadVal1, Order);
RMWI->setVolatile(E->isVolatile());
// For __atomic_*_fetch operations, perform the operation again to
@@ -632,15 +632,14 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, llvm::Value *Dest,
Result = CGF.Builder.CreateBinOp(PostOp, RMWI, LoadVal1);
if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch)
Result = CGF.Builder.CreateNot(Result);
- llvm::StoreInst *StoreDest = CGF.Builder.CreateStore(Result, Dest);
- StoreDest->setAlignment(Align);
+ CGF.Builder.CreateStore(Result, Dest);
}
// This function emits any expression (scalar, complex, or aggregate)
// into a temporary alloca.
-static llvm::Value *
+static Address
EmitValToTemp(CodeGenFunction &CGF, Expr *E) {
- llvm::Value *DeclPtr = CGF.CreateMemTemp(E->getType(), ".atomictmp");
+ Address DeclPtr = CGF.CreateMemTemp(E->getType(), ".atomictmp");
CGF.EmitAnyExprToMem(E, DeclPtr, E->getType().getQualifiers(),
/*Init*/ true);
return DeclPtr;
@@ -652,14 +651,15 @@ AddDirectArgument(CodeGenFunction &CGF, CallArgList &Args,
SourceLocation Loc, CharUnits SizeInChars) {
if (UseOptimizedLibcall) {
// Load value and pass it to the function directly.
- unsigned Align = CGF.getContext().getTypeAlignInChars(ValTy).getQuantity();
+ CharUnits Align = CGF.getContext().getTypeAlignInChars(ValTy);
int64_t SizeInBits = CGF.getContext().toBits(SizeInChars);
ValTy =
CGF.getContext().getIntTypeForBitwidth(SizeInBits, /*Signed=*/false);
llvm::Type *IPtrTy = llvm::IntegerType::get(CGF.getLLVMContext(),
SizeInBits)->getPointerTo();
- Val = CGF.EmitLoadOfScalar(CGF.Builder.CreateBitCast(Val, IPtrTy), false,
- Align, CGF.getContext().getPointerType(ValTy),
+ Address Ptr = Address(CGF.Builder.CreateBitCast(Val, IPtrTy), Align);
+ Val = CGF.EmitLoadOfScalar(Ptr, false,
+ CGF.getContext().getPointerType(ValTy),
Loc);
// Coerce the value into an appropriately sized integer type.
Args.add(RValue::get(Val), ValTy);
@@ -670,27 +670,27 @@ AddDirectArgument(CodeGenFunction &CGF, CallArgList &Args,
}
}
-RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
+RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
QualType AtomicTy = E->getPtr()->getType()->getPointeeType();
QualType MemTy = AtomicTy;
if (const AtomicType *AT = AtomicTy->getAs<AtomicType>())
MemTy = AT->getValueType();
- CharUnits sizeChars = getContext().getTypeSizeInChars(AtomicTy);
+ CharUnits sizeChars, alignChars;
+ std::tie(sizeChars, alignChars) = getContext().getTypeInfoInChars(AtomicTy);
uint64_t Size = sizeChars.getQuantity();
- CharUnits alignChars = getContext().getTypeAlignInChars(AtomicTy);
- unsigned Align = alignChars.getQuantity();
- unsigned MaxInlineWidthInBits =
- getTarget().getMaxAtomicInlineWidth();
- bool UseLibcall = (Size != Align ||
+ unsigned MaxInlineWidthInBits = getTarget().getMaxAtomicInlineWidth();
+ bool UseLibcall = (sizeChars != alignChars ||
getContext().toBits(sizeChars) > MaxInlineWidthInBits);
- llvm::Value *IsWeak = nullptr, *OrderFail = nullptr, *Val1 = nullptr,
- *Val2 = nullptr;
- llvm::Value *Ptr = EmitScalarExpr(E->getPtr());
+ llvm::Value *IsWeak = nullptr, *OrderFail = nullptr;
+
+ Address Val1 = Address::invalid();
+ Address Val2 = Address::invalid();
+ Address Dest = Address::invalid();
+ Address Ptr(EmitScalarExpr(E->getPtr()), alignChars);
if (E->getOp() == AtomicExpr::AO__c11_atomic_init) {
- assert(!Dest && "Init does not return a value");
- LValue lvalue = LValue::MakeAddr(Ptr, AtomicTy, alignChars, getContext());
+ LValue lvalue = MakeAddrLValue(Ptr, AtomicTy);
EmitAtomicInit(E->getVal1(), lvalue);
return RValue::get(nullptr);
}
@@ -706,25 +706,25 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
break;
case AtomicExpr::AO__atomic_load:
- Dest = EmitScalarExpr(E->getVal1());
+ Dest = EmitPointerWithAlignment(E->getVal1());
break;
case AtomicExpr::AO__atomic_store:
- Val1 = EmitScalarExpr(E->getVal1());
+ Val1 = EmitPointerWithAlignment(E->getVal1());
break;
case AtomicExpr::AO__atomic_exchange:
- Val1 = EmitScalarExpr(E->getVal1());
- Dest = EmitScalarExpr(E->getVal2());
+ Val1 = EmitPointerWithAlignment(E->getVal1());
+ Dest = EmitPointerWithAlignment(E->getVal2());
break;
case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
case AtomicExpr::AO__atomic_compare_exchange_n:
case AtomicExpr::AO__atomic_compare_exchange:
- Val1 = EmitScalarExpr(E->getVal1());
+ Val1 = EmitPointerWithAlignment(E->getVal1());
if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange)
- Val2 = EmitScalarExpr(E->getVal2());
+ Val2 = EmitPointerWithAlignment(E->getVal2());
else
Val2 = EmitValToTemp(*this, E->getVal2());
OrderFail = EmitScalarExpr(E->getOrderFail());
@@ -744,8 +744,9 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
CharUnits PointeeIncAmt =
getContext().getTypeSizeInChars(MemTy->getPointeeType());
Val1Scalar = Builder.CreateMul(Val1Scalar, CGM.getSize(PointeeIncAmt));
- Val1 = CreateMemTemp(Val1Ty, ".atomictmp");
- EmitStoreOfScalar(Val1Scalar, MakeAddrLValue(Val1, Val1Ty));
+ auto Temp = CreateMemTemp(Val1Ty, ".atomictmp");
+ Val1 = Temp;
+ EmitStoreOfScalar(Val1Scalar, MakeAddrLValue(Temp, Val1Ty));
break;
}
// Fall through.
@@ -774,12 +775,21 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
QualType RValTy = E->getType().getUnqualifiedType();
- auto GetDest = [&] {
- if (!RValTy->isVoidType() && !Dest) {
- Dest = CreateMemTemp(RValTy, ".atomicdst");
- }
- return Dest;
- };
+ // The inlined atomics only function on iN types, where N is a power of 2. We
+ // need to make sure (via temporaries if necessary) that all incoming values
+ // are compatible.
+ LValue AtomicVal = MakeAddrLValue(Ptr, AtomicTy);
+ AtomicInfo Atomics(*this, AtomicVal);
+
+ Ptr = Atomics.emitCastToAtomicIntPointer(Ptr);
+ if (Val1.isValid()) Val1 = Atomics.convertToAtomicIntPointer(Val1);
+ if (Val2.isValid()) Val2 = Atomics.convertToAtomicIntPointer(Val2);
+ if (Dest.isValid())
+ Dest = Atomics.emitCastToAtomicIntPointer(Dest);
+ else if (E->isCmpXChg())
+ Dest = CreateMemTemp(RValTy, "cmpxchg.bool");
+ else if (!RValTy->isVoidType())
+ Dest = Atomics.emitCastToAtomicIntPointer(Atomics.CreateTempAlloca());
// Use a library call. See: http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary .
if (UseLibcall) {
@@ -835,13 +845,15 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
getContext().getSizeType());
}
// Atomic address is the first or second parameter
- Args.add(RValue::get(EmitCastToVoidPtr(Ptr)), getContext().VoidPtrTy);
+ Args.add(RValue::get(EmitCastToVoidPtr(Ptr.getPointer())),
+ getContext().VoidPtrTy);
std::string LibCallName;
QualType LoweredMemTy =
MemTy->isPointerType() ? getContext().getIntPtrType() : MemTy;
QualType RetTy;
bool HaveRetTy = false;
+ llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0;
switch (E->getOp()) {
case AtomicExpr::AO__c11_atomic_init:
llvm_unreachable("Already handled!");
@@ -860,9 +872,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
LibCallName = "__atomic_compare_exchange";
RetTy = getContext().BoolTy;
HaveRetTy = true;
- Args.add(RValue::get(EmitCastToVoidPtr(Val1)), getContext().VoidPtrTy);
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val2, MemTy,
- E->getExprLoc(), sizeChars);
+ Args.add(RValue::get(EmitCastToVoidPtr(Val1.getPointer())),
+ getContext().VoidPtrTy);
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val2.getPointer(),
+ MemTy, E->getExprLoc(), sizeChars);
Args.add(RValue::get(Order), getContext().IntTy);
Order = OrderFail;
break;
@@ -873,8 +886,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
case AtomicExpr::AO__atomic_exchange_n:
case AtomicExpr::AO__atomic_exchange:
LibCallName = "__atomic_exchange";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
- E->getExprLoc(), sizeChars);
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
+ MemTy, E->getExprLoc(), sizeChars);
break;
// void __atomic_store(size_t size, void *mem, void *val, int order)
// void __atomic_store_N(T *mem, T val, int order)
@@ -884,8 +897,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
LibCallName = "__atomic_store";
RetTy = getContext().VoidTy;
HaveRetTy = true;
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
- E->getExprLoc(), sizeChars);
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
+ MemTy, E->getExprLoc(), sizeChars);
break;
// void __atomic_load(size_t size, void *mem, void *return, int order)
// T __atomic_load_N(T *mem, int order)
@@ -894,83 +907,70 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
case AtomicExpr::AO__atomic_load_n:
LibCallName = "__atomic_load";
break;
+ // T __atomic_add_fetch_N(T *mem, T val, int order)
// T __atomic_fetch_add_N(T *mem, T val, int order)
+ case AtomicExpr::AO__atomic_add_fetch:
+ PostOp = llvm::Instruction::Add;
+ // Fall through.
case AtomicExpr::AO__c11_atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_add:
LibCallName = "__atomic_fetch_add";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, LoweredMemTy,
- E->getExprLoc(), sizeChars);
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
+ LoweredMemTy, E->getExprLoc(), sizeChars);
break;
+ // T __atomic_and_fetch_N(T *mem, T val, int order)
// T __atomic_fetch_and_N(T *mem, T val, int order)
+ case AtomicExpr::AO__atomic_and_fetch:
+ PostOp = llvm::Instruction::And;
+ // Fall through.
case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__atomic_fetch_and:
LibCallName = "__atomic_fetch_and";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
- E->getExprLoc(), sizeChars);
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
+ MemTy, E->getExprLoc(), sizeChars);
break;
+ // T __atomic_or_fetch_N(T *mem, T val, int order)
// T __atomic_fetch_or_N(T *mem, T val, int order)
+ case AtomicExpr::AO__atomic_or_fetch:
+ PostOp = llvm::Instruction::Or;
+ // Fall through.
case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__atomic_fetch_or:
LibCallName = "__atomic_fetch_or";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
- E->getExprLoc(), sizeChars);
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
+ MemTy, E->getExprLoc(), sizeChars);
break;
+ // T __atomic_sub_fetch_N(T *mem, T val, int order)
// T __atomic_fetch_sub_N(T *mem, T val, int order)
+ case AtomicExpr::AO__atomic_sub_fetch:
+ PostOp = llvm::Instruction::Sub;
+ // Fall through.
case AtomicExpr::AO__c11_atomic_fetch_sub:
case AtomicExpr::AO__atomic_fetch_sub:
LibCallName = "__atomic_fetch_sub";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, LoweredMemTy,
- E->getExprLoc(), sizeChars);
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
+ LoweredMemTy, E->getExprLoc(), sizeChars);
break;
+ // T __atomic_xor_fetch_N(T *mem, T val, int order)
// T __atomic_fetch_xor_N(T *mem, T val, int order)
+ case AtomicExpr::AO__atomic_xor_fetch:
+ PostOp = llvm::Instruction::Xor;
+ // Fall through.
case AtomicExpr::AO__c11_atomic_fetch_xor:
case AtomicExpr::AO__atomic_fetch_xor:
LibCallName = "__atomic_fetch_xor";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
- E->getExprLoc(), sizeChars);
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
+ MemTy, E->getExprLoc(), sizeChars);
break;
+ // T __atomic_nand_fetch_N(T *mem, T val, int order)
// T __atomic_fetch_nand_N(T *mem, T val, int order)
+ case AtomicExpr::AO__atomic_nand_fetch:
+ PostOp = llvm::Instruction::And; // the NOT is special cased below
+ // Fall through.
case AtomicExpr::AO__atomic_fetch_nand:
LibCallName = "__atomic_fetch_nand";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
- E->getExprLoc(), sizeChars);
- break;
-
- // T __atomic_add_fetch_N(T *mem, T val, int order)
- case AtomicExpr::AO__atomic_add_fetch:
- LibCallName = "__atomic_add_fetch";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, LoweredMemTy,
- E->getExprLoc(), sizeChars);
- break;
- // T __atomic_and_fetch_N(T *mem, T val, int order)
- case AtomicExpr::AO__atomic_and_fetch:
- LibCallName = "__atomic_and_fetch";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
- E->getExprLoc(), sizeChars);
- break;
- // T __atomic_or_fetch_N(T *mem, T val, int order)
- case AtomicExpr::AO__atomic_or_fetch:
- LibCallName = "__atomic_or_fetch";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
- E->getExprLoc(), sizeChars);
- break;
- // T __atomic_sub_fetch_N(T *mem, T val, int order)
- case AtomicExpr::AO__atomic_sub_fetch:
- LibCallName = "__atomic_sub_fetch";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, LoweredMemTy,
- E->getExprLoc(), sizeChars);
- break;
- // T __atomic_xor_fetch_N(T *mem, T val, int order)
- case AtomicExpr::AO__atomic_xor_fetch:
- LibCallName = "__atomic_xor_fetch";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
- E->getExprLoc(), sizeChars);
- break;
- // T __atomic_nand_fetch_N(T *mem, T val, int order)
- case AtomicExpr::AO__atomic_nand_fetch:
- LibCallName = "__atomic_nand_fetch";
- AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1, MemTy,
- E->getExprLoc(), sizeChars);
+ AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
+ MemTy, E->getExprLoc(), sizeChars);
break;
}
@@ -987,30 +987,46 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
} else {
// Value is returned through parameter before the order.
RetTy = getContext().VoidTy;
- Args.add(RValue::get(EmitCastToVoidPtr(Dest)), getContext().VoidPtrTy);
+ Args.add(RValue::get(EmitCastToVoidPtr(Dest.getPointer())),
+ getContext().VoidPtrTy);
}
}
// order is always the last parameter
Args.add(RValue::get(Order),
getContext().IntTy);
+ // PostOp is only needed for the atomic_*_fetch operations, and
+ // thus is only needed for and implemented in the
+ // UseOptimizedLibcall codepath.
+ assert(UseOptimizedLibcall || !PostOp);
+
RValue Res = emitAtomicLibcall(*this, LibCallName, RetTy, Args);
// The value is returned directly from the libcall.
- if (HaveRetTy && !RetTy->isVoidType())
+ if (E->isCmpXChg())
return Res;
- // The value is returned via an explicit out param.
- if (RetTy->isVoidType())
- return RValue::get(nullptr);
- // The value is returned directly for optimized libcalls but the caller is
- // expected an out-param.
- if (UseOptimizedLibcall) {
+
+ // The value is returned directly for optimized libcalls but the expr
+ // provided an out-param.
+ if (UseOptimizedLibcall && Res.getScalarVal()) {
llvm::Value *ResVal = Res.getScalarVal();
- llvm::StoreInst *StoreDest = Builder.CreateStore(
+ if (PostOp) {
+ llvm::Value *LoadVal1 = Args[1].RV.getScalarVal();
+ ResVal = Builder.CreateBinOp(PostOp, ResVal, LoadVal1);
+ }
+ if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch)
+ ResVal = Builder.CreateNot(ResVal);
+
+ Builder.CreateStore(
ResVal,
- Builder.CreateBitCast(GetDest(), ResVal->getType()->getPointerTo()));
- StoreDest->setAlignment(Align);
+ Builder.CreateBitCast(Dest, ResVal->getType()->getPointerTo()));
}
- return convertTempToRValue(Dest, RValTy, E->getExprLoc());
+
+ if (RValTy->isVoidType())
+ return RValue::get(nullptr);
+
+ return convertTempToRValue(
+ Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo()),
+ RValTy, E->getExprLoc());
}
bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store ||
@@ -1020,45 +1036,35 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
E->getOp() == AtomicExpr::AO__atomic_load ||
E->getOp() == AtomicExpr::AO__atomic_load_n;
- llvm::Type *ITy =
- llvm::IntegerType::get(getLLVMContext(), Size * 8);
- llvm::Value *OrigDest = GetDest();
- Ptr = Builder.CreateBitCast(
- Ptr, ITy->getPointerTo(Ptr->getType()->getPointerAddressSpace()));
- if (Val1) Val1 = Builder.CreateBitCast(Val1, ITy->getPointerTo());
- if (Val2) Val2 = Builder.CreateBitCast(Val2, ITy->getPointerTo());
- if (Dest && !E->isCmpXChg())
- Dest = Builder.CreateBitCast(Dest, ITy->getPointerTo());
-
if (isa<llvm::ConstantInt>(Order)) {
int ord = cast<llvm::ConstantInt>(Order)->getZExtValue();
switch (ord) {
case AtomicExpr::AO_ABI_memory_order_relaxed:
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, Align, llvm::Monotonic);
+ Size, llvm::Monotonic);
break;
case AtomicExpr::AO_ABI_memory_order_consume:
case AtomicExpr::AO_ABI_memory_order_acquire:
if (IsStore)
break; // Avoid crashing on code with undefined behavior
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, Align, llvm::Acquire);
+ Size, llvm::Acquire);
break;
case AtomicExpr::AO_ABI_memory_order_release:
if (IsLoad)
break; // Avoid crashing on code with undefined behavior
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, Align, llvm::Release);
+ Size, llvm::Release);
break;
case AtomicExpr::AO_ABI_memory_order_acq_rel:
if (IsLoad || IsStore)
break; // Avoid crashing on code with undefined behavior
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, Align, llvm::AcquireRelease);
+ Size, llvm::AcquireRelease);
break;
case AtomicExpr::AO_ABI_memory_order_seq_cst:
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, Align, llvm::SequentiallyConsistent);
+ Size, llvm::SequentiallyConsistent);
break;
default: // invalid order
// We should not ever get here normally, but it's hard to
@@ -1067,7 +1073,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
}
if (RValTy->isVoidType())
return RValue::get(nullptr);
- return convertTempToRValue(OrigDest, RValTy, E->getExprLoc());
+
+ return convertTempToRValue(
+ Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo()),
+ RValTy, E->getExprLoc());
}
// Long case, when Order isn't obviously constant.
@@ -1096,12 +1105,12 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
// Emit all the different atomics
Builder.SetInsertPoint(MonotonicBB);
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, Align, llvm::Monotonic);
+ Size, llvm::Monotonic);
Builder.CreateBr(ContBB);
if (!IsStore) {
Builder.SetInsertPoint(AcquireBB);
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, Align, llvm::Acquire);
+ Size, llvm::Acquire);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_consume),
AcquireBB);
@@ -1111,7 +1120,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
if (!IsLoad) {
Builder.SetInsertPoint(ReleaseBB);
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, Align, llvm::Release);
+ Size, llvm::Release);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_release),
ReleaseBB);
@@ -1119,14 +1128,14 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
if (!IsLoad && !IsStore) {
Builder.SetInsertPoint(AcqRelBB);
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, Align, llvm::AcquireRelease);
+ Size, llvm::AcquireRelease);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_acq_rel),
AcqRelBB);
}
Builder.SetInsertPoint(SeqCstBB);
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail,
- Size, Align, llvm::SequentiallyConsistent);
+ Size, llvm::SequentiallyConsistent);
Builder.CreateBr(ContBB);
SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_seq_cst),
SeqCstBB);
@@ -1135,47 +1144,65 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
Builder.SetInsertPoint(ContBB);
if (RValTy->isVoidType())
return RValue::get(nullptr);
- return convertTempToRValue(OrigDest, RValTy, E->getExprLoc());
+
+ assert(Atomics.getValueSizeInBits() <= Atomics.getAtomicSizeInBits());
+ return convertTempToRValue(
+ Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo()),
+ RValTy, E->getExprLoc());
}
-llvm::Value *AtomicInfo::emitCastToAtomicIntPointer(llvm::Value *addr) const {
+Address AtomicInfo::emitCastToAtomicIntPointer(Address addr) const {
unsigned addrspace =
- cast<llvm::PointerType>(addr->getType())->getAddressSpace();
+ cast<llvm::PointerType>(addr.getPointer()->getType())->getAddressSpace();
llvm::IntegerType *ty =
llvm::IntegerType::get(CGF.getLLVMContext(), AtomicSizeInBits);
return CGF.Builder.CreateBitCast(addr, ty->getPointerTo(addrspace));
}
-RValue AtomicInfo::convertTempToRValue(llvm::Value *addr,
- AggValueSlot resultSlot,
- SourceLocation loc, bool AsValue) const {
+Address AtomicInfo::convertToAtomicIntPointer(Address Addr) const {
+ llvm::Type *Ty = Addr.getElementType();
+ uint64_t SourceSizeInBits = CGF.CGM.getDataLayout().getTypeSizeInBits(Ty);
+ if (SourceSizeInBits != AtomicSizeInBits) {
+ Address Tmp = CreateTempAlloca();
+ CGF.Builder.CreateMemCpy(Tmp, Addr,
+ std::min(AtomicSizeInBits, SourceSizeInBits) / 8);
+ Addr = Tmp;
+ }
+
+ return emitCastToAtomicIntPointer(Addr);
+}
+
+RValue AtomicInfo::convertAtomicTempToRValue(Address addr,
+ AggValueSlot resultSlot,
+ SourceLocation loc,
+ bool asValue) const {
if (LVal.isSimple()) {
if (EvaluationKind == TEK_Aggregate)
return resultSlot.asRValue();
// Drill into the padding structure if we have one.
if (hasPadding())
- addr = CGF.Builder.CreateStructGEP(nullptr, addr, 0);
+ addr = CGF.Builder.CreateStructGEP(addr, 0, CharUnits());
// Otherwise, just convert the temporary to an r-value using the
// normal conversion routine.
return CGF.convertTempToRValue(addr, getValueType(), loc);
}
- if (!AsValue)
+ if (!asValue)
// Get RValue from temp memory as atomic for non-simple lvalues
- return RValue::get(
- CGF.Builder.CreateAlignedLoad(addr, AtomicAlign.getQuantity()));
+ return RValue::get(CGF.Builder.CreateLoad(addr));
if (LVal.isBitField())
- return CGF.EmitLoadOfBitfieldLValue(LValue::MakeBitfield(
- addr, LVal.getBitFieldInfo(), LVal.getType(), LVal.getAlignment()));
+ return CGF.EmitLoadOfBitfieldLValue(
+ LValue::MakeBitfield(addr, LVal.getBitFieldInfo(), LVal.getType(),
+ LVal.getAlignmentSource()));
if (LVal.isVectorElt())
- return CGF.EmitLoadOfLValue(LValue::MakeVectorElt(addr, LVal.getVectorIdx(),
- LVal.getType(),
- LVal.getAlignment()),
- loc);
+ return CGF.EmitLoadOfLValue(
+ LValue::MakeVectorElt(addr, LVal.getVectorIdx(), LVal.getType(),
+ LVal.getAlignmentSource()), loc);
assert(LVal.isExtVectorElt());
return CGF.EmitLoadOfExtVectorElementLValue(LValue::MakeExtVectorElt(
- addr, LVal.getExtVectorElts(), LVal.getType(), LVal.getAlignment()));
+ addr, LVal.getExtVectorElts(), LVal.getType(),
+ LVal.getAlignmentSource()));
}
RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
@@ -1191,7 +1218,7 @@ RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
!AsValue)) {
auto *ValTy = AsValue
? CGF.ConvertTypeForMem(ValueTy)
- : getAtomicAddress()->getType()->getPointerElementType();
+ : getAtomicAddress().getType()->getPointerElementType();
if (ValTy->isIntegerTy()) {
assert(IntVal->getType() == ValTy && "Different integer types.");
return RValue::get(CGF.EmitFromMemory(IntVal, ValueTy));
@@ -1203,25 +1230,22 @@ RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
// Create a temporary. This needs to be big enough to hold the
// atomic integer.
- llvm::Value *Temp;
+ Address Temp = Address::invalid();
bool TempIsVolatile = false;
- CharUnits TempAlignment;
if (AsValue && getEvaluationKind() == TEK_Aggregate) {
assert(!ResultSlot.isIgnored());
- Temp = ResultSlot.getAddr();
- TempAlignment = getValueAlignment();
+ Temp = ResultSlot.getAddress();
TempIsVolatile = ResultSlot.isVolatile();
} else {
Temp = CreateTempAlloca();
- TempAlignment = getAtomicAlignment();
}
// Slam the integer into the temporary.
- llvm::Value *CastTemp = emitCastToAtomicIntPointer(Temp);
- CGF.Builder.CreateAlignedStore(IntVal, CastTemp, TempAlignment.getQuantity())
+ Address CastTemp = emitCastToAtomicIntPointer(Temp);
+ CGF.Builder.CreateStore(IntVal, CastTemp)
->setVolatile(TempIsVolatile);
- return convertTempToRValue(Temp, ResultSlot, Loc, AsValue);
+ return convertAtomicTempToRValue(Temp, ResultSlot, Loc, AsValue);
}
void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
@@ -1229,7 +1253,7 @@ void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
// void __atomic_load(size_t size, void *mem, void *return, int order);
CallArgList Args;
Args.add(RValue::get(getAtomicSizeValue()), CGF.getContext().getSizeType());
- Args.add(RValue::get(CGF.EmitCastToVoidPtr(getAtomicAddress())),
+ Args.add(RValue::get(CGF.EmitCastToVoidPtr(getAtomicPointer())),
CGF.getContext().VoidPtrTy);
Args.add(RValue::get(CGF.EmitCastToVoidPtr(AddForLoaded)),
CGF.getContext().VoidPtrTy);
@@ -1242,16 +1266,15 @@ void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,
bool IsVolatile) {
// Okay, we're doing this natively.
- llvm::Value *Addr = emitCastToAtomicIntPointer(getAtomicAddress());
+ Address Addr = getAtomicAddressAsAtomicIntPointer();
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Addr, "atomic-load");
Load->setAtomic(AO);
// Other decoration.
- Load->setAlignment(getAtomicAlignment().getQuantity());
if (IsVolatile)
Load->setVolatile(true);
if (LVal.getTBAAInfo())
- CGF.CGM.DecorateInstruction(Load, LVal.getTBAAInfo());
+ CGF.CGM.DecorateInstructionWithTBAA(Load, LVal.getTBAAInfo());
return Load;
}
@@ -1259,11 +1282,12 @@ llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,
/// we are operating under /volatile:ms *and* the LValue itself is volatile and
/// performing such an operation can be performed without a libcall.
bool CodeGenFunction::LValueIsSuitableForInlineAtomic(LValue LV) {
+ if (!CGM.getCodeGenOpts().MSVolatile) return false;
AtomicInfo AI(*this, LV);
bool IsVolatile = LV.isVolatile() || hasVolatileMember(LV.getType());
// An atomic is inline if we don't need to use a libcall.
bool AtomicIsInline = !AI.shouldUseLibcall();
- return CGM.getCodeGenOpts().MSVolatile && IsVolatile && AtomicIsInline;
+ return IsVolatile && AtomicIsInline;
}
/// An type is a candidate for having its loads and stores be made atomic if
@@ -1295,18 +1319,18 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
bool IsVolatile) {
// Check whether we should use a library call.
if (shouldUseLibcall()) {
- llvm::Value *TempAddr;
+ Address TempAddr = Address::invalid();
if (LVal.isSimple() && !ResultSlot.isIgnored()) {
assert(getEvaluationKind() == TEK_Aggregate);
- TempAddr = ResultSlot.getAddr();
+ TempAddr = ResultSlot.getAddress();
} else
TempAddr = CreateTempAlloca();
- EmitAtomicLoadLibcall(TempAddr, AO, IsVolatile);
+ EmitAtomicLoadLibcall(TempAddr.getPointer(), AO, IsVolatile);
// Okay, turn that back into the original value or whole atomic (for
// non-simple lvalues) type.
- return convertTempToRValue(TempAddr, ResultSlot, Loc, AsValue);
+ return convertAtomicTempToRValue(TempAddr, ResultSlot, Loc, AsValue);
}
// Okay, we're doing this natively.
@@ -1314,7 +1338,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
// If we're ignoring an aggregate return, don't do anything.
if (getEvaluationKind() == TEK_Aggregate && ResultSlot.isIgnored())
- return RValue::getAggregate(nullptr, false);
+ return RValue::getAggregate(Address::invalid(), false);
// Okay, turn that back into the original value or atomic (for non-simple
// lvalues) type.
@@ -1340,11 +1364,10 @@ void AtomicInfo::emitCopyIntoMemory(RValue rvalue) const {
// any padding. Just do an aggregate copy of that type.
if (rvalue.isAggregate()) {
CGF.EmitAggregateCopy(getAtomicAddress(),
- rvalue.getAggregateAddr(),
+ rvalue.getAggregateAddress(),
getAtomicType(),
(rvalue.isVolatileQualified()
- || LVal.isVolatileQualified()),
- LVal.getAlignment());
+ || LVal.isVolatileQualified()));
return;
}
@@ -1367,15 +1390,14 @@ void AtomicInfo::emitCopyIntoMemory(RValue rvalue) const {
/// Materialize an r-value into memory for the purposes of storing it
/// to an atomic type.
-llvm::Value *AtomicInfo::materializeRValue(RValue rvalue) const {
+Address AtomicInfo::materializeRValue(RValue rvalue) const {
// Aggregate r-values are already in memory, and EmitAtomicStore
// requires them to be values of the atomic type.
if (rvalue.isAggregate())
- return rvalue.getAggregateAddr();
+ return rvalue.getAggregateAddress();
// Otherwise, make a temporary and materialize into it.
- LValue TempLV = CGF.MakeAddrLValue(CreateTempAlloca(), getAtomicType(),
- getAtomicAlignment());
+ LValue TempLV = CGF.MakeAddrLValue(CreateTempAlloca(), getAtomicType());
AtomicInfo Atomics(CGF, TempLV);
Atomics.emitCopyIntoMemory(rvalue);
return TempLV.getAddress();
@@ -1400,20 +1422,20 @@ llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal) const {
}
// Otherwise, we need to go through memory.
// Put the r-value in memory.
- llvm::Value *Addr = materializeRValue(RVal);
+ Address Addr = materializeRValue(RVal);
// Cast the temporary to the atomic int type and pull a value out.
Addr = emitCastToAtomicIntPointer(Addr);
- return CGF.Builder.CreateAlignedLoad(Addr,
- getAtomicAlignment().getQuantity());
+ return CGF.Builder.CreateLoad(Addr);
}
std::pair<llvm::Value *, llvm::Value *> AtomicInfo::EmitAtomicCompareExchangeOp(
llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak) {
// Do the atomic store.
- auto *Addr = emitCastToAtomicIntPointer(getAtomicAddress());
- auto *Inst = CGF.Builder.CreateAtomicCmpXchg(Addr, ExpectedVal, DesiredVal,
+ Address Addr = getAtomicAddressAsAtomicIntPointer();
+ auto *Inst = CGF.Builder.CreateAtomicCmpXchg(Addr.getPointer(),
+ ExpectedVal, DesiredVal,
Success, Failure);
// Other decoration.
Inst->setVolatile(LVal.isVolatileQualified());
@@ -1434,7 +1456,7 @@ AtomicInfo::EmitAtomicCompareExchangeLibcall(llvm::Value *ExpectedAddr,
// void *desired, int success, int failure);
CallArgList Args;
Args.add(RValue::get(getAtomicSizeValue()), CGF.getContext().getSizeType());
- Args.add(RValue::get(CGF.EmitCastToVoidPtr(getAtomicAddress())),
+ Args.add(RValue::get(CGF.EmitCastToVoidPtr(getAtomicPointer())),
CGF.getContext().VoidPtrTy);
Args.add(RValue::get(CGF.EmitCastToVoidPtr(ExpectedAddr)),
CGF.getContext().VoidPtrTy);
@@ -1462,13 +1484,14 @@ std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(
// Check whether we should use a library call.
if (shouldUseLibcall()) {
// Produce a source address.
- auto *ExpectedAddr = materializeRValue(Expected);
- auto *DesiredAddr = materializeRValue(Desired);
- auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedAddr, DesiredAddr,
+ Address ExpectedAddr = materializeRValue(Expected);
+ Address DesiredAddr = materializeRValue(Desired);
+ auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(),
+ DesiredAddr.getPointer(),
Success, Failure);
return std::make_pair(
- convertTempToRValue(ExpectedAddr, AggValueSlot::ignored(),
- SourceLocation(), /*AsValue=*/false),
+ convertAtomicTempToRValue(ExpectedAddr, AggValueSlot::ignored(),
+ SourceLocation(), /*AsValue=*/false),
Res);
}
@@ -1487,42 +1510,41 @@ std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(
static void
EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, RValue OldRVal,
const llvm::function_ref<RValue(RValue)> &UpdateOp,
- llvm::Value *DesiredAddr) {
- llvm::Value *Ptr = nullptr;
- LValue UpdateLVal;
+ Address DesiredAddr) {
RValue UpRVal;
LValue AtomicLVal = Atomics.getAtomicLValue();
LValue DesiredLVal;
if (AtomicLVal.isSimple()) {
UpRVal = OldRVal;
- DesiredLVal =
- LValue::MakeAddr(DesiredAddr, AtomicLVal.getType(),
- AtomicLVal.getAlignment(), CGF.CGM.getContext());
+ DesiredLVal = CGF.MakeAddrLValue(DesiredAddr, AtomicLVal.getType());
} else {
// Build new lvalue for temp address
- Ptr = Atomics.materializeRValue(OldRVal);
+ Address Ptr = Atomics.materializeRValue(OldRVal);
+ LValue UpdateLVal;
if (AtomicLVal.isBitField()) {
UpdateLVal =
LValue::MakeBitfield(Ptr, AtomicLVal.getBitFieldInfo(),
- AtomicLVal.getType(), AtomicLVal.getAlignment());
+ AtomicLVal.getType(),
+ AtomicLVal.getAlignmentSource());
DesiredLVal =
LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),
- AtomicLVal.getType(), AtomicLVal.getAlignment());
+ AtomicLVal.getType(),
+ AtomicLVal.getAlignmentSource());
} else if (AtomicLVal.isVectorElt()) {
UpdateLVal = LValue::MakeVectorElt(Ptr, AtomicLVal.getVectorIdx(),
AtomicLVal.getType(),
- AtomicLVal.getAlignment());
+ AtomicLVal.getAlignmentSource());
DesiredLVal = LValue::MakeVectorElt(
DesiredAddr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(),
- AtomicLVal.getAlignment());
+ AtomicLVal.getAlignmentSource());
} else {
assert(AtomicLVal.isExtVectorElt());
UpdateLVal = LValue::MakeExtVectorElt(Ptr, AtomicLVal.getExtVectorElts(),
AtomicLVal.getType(),
- AtomicLVal.getAlignment());
+ AtomicLVal.getAlignmentSource());
DesiredLVal = LValue::MakeExtVectorElt(
DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),
- AtomicLVal.getAlignment());
+ AtomicLVal.getAlignmentSource());
}
UpdateLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
@@ -1544,26 +1566,26 @@ void AtomicInfo::EmitAtomicUpdateLibcall(
bool IsVolatile) {
auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
- llvm::Value *ExpectedAddr = CreateTempAlloca();
+ Address ExpectedAddr = CreateTempAlloca();
- EmitAtomicLoadLibcall(ExpectedAddr, AO, IsVolatile);
+ EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile);
auto *ContBB = CGF.createBasicBlock("atomic_cont");
auto *ExitBB = CGF.createBasicBlock("atomic_exit");
CGF.EmitBlock(ContBB);
- auto *DesiredAddr = CreateTempAlloca();
+ Address DesiredAddr = CreateTempAlloca();
if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
- requiresMemSetZero(
- getAtomicAddress()->getType()->getPointerElementType())) {
- auto *OldVal = CGF.Builder.CreateAlignedLoad(
- ExpectedAddr, getAtomicAlignment().getQuantity());
- CGF.Builder.CreateAlignedStore(OldVal, DesiredAddr,
- getAtomicAlignment().getQuantity());
+ requiresMemSetZero(getAtomicAddress().getElementType())) {
+ auto *OldVal = CGF.Builder.CreateLoad(ExpectedAddr);
+ CGF.Builder.CreateStore(OldVal, DesiredAddr);
}
- auto OldRVal = convertTempToRValue(ExpectedAddr, AggValueSlot::ignored(),
- SourceLocation(), /*AsValue=*/false);
+ auto OldRVal = convertAtomicTempToRValue(ExpectedAddr,
+ AggValueSlot::ignored(),
+ SourceLocation(), /*AsValue=*/false);
EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, DesiredAddr);
auto *Res =
- EmitAtomicCompareExchangeLibcall(ExpectedAddr, DesiredAddr, AO, Failure);
+ EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(),
+ DesiredAddr.getPointer(),
+ AO, Failure);
CGF.Builder.CreateCondBr(Res, ExitBB, ContBB);
CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
}
@@ -1583,19 +1605,16 @@ void AtomicInfo::EmitAtomicUpdateOp(
llvm::PHINode *PHI = CGF.Builder.CreatePHI(OldVal->getType(),
/*NumReservedValues=*/2);
PHI->addIncoming(OldVal, CurBB);
- auto *NewAtomicAddr = CreateTempAlloca();
- auto *NewAtomicIntAddr = emitCastToAtomicIntPointer(NewAtomicAddr);
+ Address NewAtomicAddr = CreateTempAlloca();
+ Address NewAtomicIntAddr = emitCastToAtomicIntPointer(NewAtomicAddr);
if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
- requiresMemSetZero(
- getAtomicAddress()->getType()->getPointerElementType())) {
- CGF.Builder.CreateAlignedStore(PHI, NewAtomicIntAddr,
- getAtomicAlignment().getQuantity());
+ requiresMemSetZero(getAtomicAddress().getElementType())) {
+ CGF.Builder.CreateStore(PHI, NewAtomicIntAddr);
}
auto OldRVal = ConvertIntToValueOrAtomic(PHI, AggValueSlot::ignored(),
SourceLocation(), /*AsValue=*/false);
EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, NewAtomicAddr);
- auto *DesiredVal = CGF.Builder.CreateAlignedLoad(
- NewAtomicIntAddr, getAtomicAlignment().getQuantity());
+ auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr);
// Try to write new value using cmpxchg operation
auto Res = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure);
PHI->addIncoming(Res.first, CGF.Builder.GetInsertBlock());
@@ -1604,23 +1623,25 @@ void AtomicInfo::EmitAtomicUpdateOp(
}
static void EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics,
- RValue UpdateRVal, llvm::Value *DesiredAddr) {
+ RValue UpdateRVal, Address DesiredAddr) {
LValue AtomicLVal = Atomics.getAtomicLValue();
LValue DesiredLVal;
// Build new lvalue for temp address
if (AtomicLVal.isBitField()) {
DesiredLVal =
LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),
- AtomicLVal.getType(), AtomicLVal.getAlignment());
+ AtomicLVal.getType(),
+ AtomicLVal.getAlignmentSource());
} else if (AtomicLVal.isVectorElt()) {
DesiredLVal =
LValue::MakeVectorElt(DesiredAddr, AtomicLVal.getVectorIdx(),
- AtomicLVal.getType(), AtomicLVal.getAlignment());
+ AtomicLVal.getType(),
+ AtomicLVal.getAlignmentSource());
} else {
assert(AtomicLVal.isExtVectorElt());
DesiredLVal = LValue::MakeExtVectorElt(
DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),
- AtomicLVal.getAlignment());
+ AtomicLVal.getAlignmentSource());
}
DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());
// Store new value in the corresponding memory area
@@ -1632,24 +1653,23 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,
RValue UpdateRVal, bool IsVolatile) {
auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
- llvm::Value *ExpectedAddr = CreateTempAlloca();
+ Address ExpectedAddr = CreateTempAlloca();
- EmitAtomicLoadLibcall(ExpectedAddr, AO, IsVolatile);
+ EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile);
auto *ContBB = CGF.createBasicBlock("atomic_cont");
auto *ExitBB = CGF.createBasicBlock("atomic_exit");
CGF.EmitBlock(ContBB);
- auto *DesiredAddr = CreateTempAlloca();
+ Address DesiredAddr = CreateTempAlloca();
if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
- requiresMemSetZero(
- getAtomicAddress()->getType()->getPointerElementType())) {
- auto *OldVal = CGF.Builder.CreateAlignedLoad(
- ExpectedAddr, getAtomicAlignment().getQuantity());
- CGF.Builder.CreateAlignedStore(OldVal, DesiredAddr,
- getAtomicAlignment().getQuantity());
+ requiresMemSetZero(getAtomicAddress().getElementType())) {
+ auto *OldVal = CGF.Builder.CreateLoad(ExpectedAddr);
+ CGF.Builder.CreateStore(OldVal, DesiredAddr);
}
EmitAtomicUpdateValue(CGF, *this, UpdateRVal, DesiredAddr);
auto *Res =
- EmitAtomicCompareExchangeLibcall(ExpectedAddr, DesiredAddr, AO, Failure);
+ EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(),
+ DesiredAddr.getPointer(),
+ AO, Failure);
CGF.Builder.CreateCondBr(Res, ExitBB, ContBB);
CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
}
@@ -1668,17 +1688,14 @@ void AtomicInfo::EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRVal,
llvm::PHINode *PHI = CGF.Builder.CreatePHI(OldVal->getType(),
/*NumReservedValues=*/2);
PHI->addIncoming(OldVal, CurBB);
- auto *NewAtomicAddr = CreateTempAlloca();
- auto *NewAtomicIntAddr = emitCastToAtomicIntPointer(NewAtomicAddr);
+ Address NewAtomicAddr = CreateTempAlloca();
+ Address NewAtomicIntAddr = emitCastToAtomicIntPointer(NewAtomicAddr);
if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
- requiresMemSetZero(
- getAtomicAddress()->getType()->getPointerElementType())) {
- CGF.Builder.CreateAlignedStore(PHI, NewAtomicIntAddr,
- getAtomicAlignment().getQuantity());
+ requiresMemSetZero(getAtomicAddress().getElementType())) {
+ CGF.Builder.CreateStore(PHI, NewAtomicIntAddr);
}
EmitAtomicUpdateValue(CGF, *this, UpdateRVal, NewAtomicAddr);
- auto *DesiredVal = CGF.Builder.CreateAlignedLoad(
- NewAtomicIntAddr, getAtomicAlignment().getQuantity());
+ auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr);
// Try to write new value using cmpxchg operation
auto Res = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure);
PHI->addIncoming(Res.first, CGF.Builder.GetInsertBlock());
@@ -1729,8 +1746,8 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
// If this is an aggregate r-value, it should agree in type except
// maybe for address-space qualification.
assert(!rvalue.isAggregate() ||
- rvalue.getAggregateAddr()->getType()->getPointerElementType()
- == dest.getAddress()->getType()->getPointerElementType());
+ rvalue.getAggregateAddress().getElementType()
+ == dest.getAddress().getElementType());
AtomicInfo atomics(*this, dest);
LValue LVal = atomics.getAtomicLValue();
@@ -1745,15 +1762,16 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
// Check whether we should use a library call.
if (atomics.shouldUseLibcall()) {
// Produce a source address.
- llvm::Value *srcAddr = atomics.materializeRValue(rvalue);
+ Address srcAddr = atomics.materializeRValue(rvalue);
// void __atomic_store(size_t size, void *mem, void *val, int order)
CallArgList args;
args.add(RValue::get(atomics.getAtomicSizeValue()),
getContext().getSizeType());
- args.add(RValue::get(EmitCastToVoidPtr(atomics.getAtomicAddress())),
+ args.add(RValue::get(EmitCastToVoidPtr(atomics.getAtomicPointer())),
+ getContext().VoidPtrTy);
+ args.add(RValue::get(EmitCastToVoidPtr(srcAddr.getPointer())),
getContext().VoidPtrTy);
- args.add(RValue::get(EmitCastToVoidPtr(srcAddr)), getContext().VoidPtrTy);
args.add(RValue::get(llvm::ConstantInt::get(
IntTy, AtomicInfo::translateAtomicOrdering(AO))),
getContext().IntTy);
@@ -1765,10 +1783,10 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
llvm::Value *intValue = atomics.convertRValueToInt(rvalue);
// Do the atomic store.
- llvm::Value *addr =
+ Address addr =
atomics.emitCastToAtomicIntPointer(atomics.getAtomicAddress());
intValue = Builder.CreateIntCast(
- intValue, addr->getType()->getPointerElementType(), /*isSigned=*/false);
+ intValue, addr.getElementType(), /*isSigned=*/false);
llvm::StoreInst *store = Builder.CreateStore(intValue, addr);
// Initializations don't need to be atomic.
@@ -1776,11 +1794,10 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
store->setAtomic(AO);
// Other decoration.
- store->setAlignment(dest.getAlignment().getQuantity());
if (IsVolatile)
store->setVolatile(true);
if (dest.getTBAAInfo())
- CGM.DecorateInstruction(store, dest.getTBAAInfo());
+ CGM.DecorateInstructionWithTBAA(store, dest.getTBAAInfo());
return;
}
@@ -1797,11 +1814,11 @@ std::pair<RValue, llvm::Value *> CodeGenFunction::EmitAtomicCompareExchange(
// If this is an aggregate r-value, it should agree in type except
// maybe for address-space qualification.
assert(!Expected.isAggregate() ||
- Expected.getAggregateAddr()->getType()->getPointerElementType() ==
- Obj.getAddress()->getType()->getPointerElementType());
+ Expected.getAggregateAddress().getElementType() ==
+ Obj.getAddress().getElementType());
assert(!Desired.isAggregate() ||
- Desired.getAggregateAddr()->getType()->getPointerElementType() ==
- Obj.getAddress()->getType()->getPointerElementType());
+ Desired.getAggregateAddress().getElementType() ==
+ Obj.getAddress().getElementType());
AtomicInfo Atomics(*this, Obj);
return Atomics.EmitAtomicCompareExchange(Expected, Desired, Success, Failure,
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
index 3fd344c..ba2941e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
@@ -1,4 +1,4 @@
-//===--- CGBlocks.cpp - Emit LLVM Code for declarations -------------------===//
+//===--- CGBlocks.cpp - Emit LLVM Code for declarations ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -30,7 +30,7 @@ using namespace CodeGen;
CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
: Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false),
- StructureType(nullptr), Block(block),
+ LocalAddress(Address::invalid()), StructureType(nullptr), Block(block),
DominatingIP(nullptr) {
// Skip asm prefix, if any. 'name' is usually taken directly from
@@ -40,7 +40,7 @@ CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
}
// Anchor the vtable to this translation unit.
-CodeGenModule::ByrefHelpers::~ByrefHelpers() {}
+BlockByrefHelpers::~BlockByrefHelpers() {}
/// Build the given block as a global block.
static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
@@ -78,7 +78,7 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
ASTContext &C = CGM.getContext();
llvm::Type *ulong = CGM.getTypes().ConvertType(C.UnsignedLongTy);
- llvm::Type *i8p = NULL;
+ llvm::Type *i8p = nullptr;
if (CGM.getLangOpts().OpenCL)
i8p =
llvm::Type::getInt8PtrTy(
@@ -111,7 +111,7 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
std::string typeAtEncoding =
CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
elements.push_back(llvm::ConstantExpr::getBitCast(
- CGM.GetAddrOfConstantCString(typeAtEncoding), i8p));
+ CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer(), i8p));
// GC layout.
if (C.getLangOpts().ObjC1) {
@@ -203,46 +203,36 @@ namespace {
Capture(capture), Type(type) {}
/// Tell the block info that this chunk has the given field index.
- void setIndex(CGBlockInfo &info, unsigned index) {
- if (!Capture)
+ void setIndex(CGBlockInfo &info, unsigned index, CharUnits offset) {
+ if (!Capture) {
info.CXXThisIndex = index;
- else
- info.Captures[Capture->getVariable()]
- = CGBlockInfo::Capture::makeIndex(index);
+ info.CXXThisOffset = offset;
+ } else {
+ info.Captures.insert({Capture->getVariable(),
+ CGBlockInfo::Capture::makeIndex(index, offset)});
+ }
}
};
/// Order by 1) all __strong together 2) next, all byfref together 3) next,
/// all __weak together. Preserve descending alignment in all situations.
bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) {
- CharUnits LeftValue, RightValue;
- bool LeftByref = left.Capture ? left.Capture->isByRef() : false;
- bool RightByref = right.Capture ? right.Capture->isByRef() : false;
-
- if (left.Lifetime == Qualifiers::OCL_Strong &&
- left.Alignment >= right.Alignment)
- LeftValue = CharUnits::fromQuantity(64);
- else if (LeftByref && left.Alignment >= right.Alignment)
- LeftValue = CharUnits::fromQuantity(32);
- else if (left.Lifetime == Qualifiers::OCL_Weak &&
- left.Alignment >= right.Alignment)
- LeftValue = CharUnits::fromQuantity(16);
- else
- LeftValue = left.Alignment;
- if (right.Lifetime == Qualifiers::OCL_Strong &&
- right.Alignment >= left.Alignment)
- RightValue = CharUnits::fromQuantity(64);
- else if (RightByref && right.Alignment >= left.Alignment)
- RightValue = CharUnits::fromQuantity(32);
- else if (right.Lifetime == Qualifiers::OCL_Weak &&
- right.Alignment >= left.Alignment)
- RightValue = CharUnits::fromQuantity(16);
- else
- RightValue = right.Alignment;
-
- return LeftValue > RightValue;
+ if (left.Alignment != right.Alignment)
+ return left.Alignment > right.Alignment;
+
+ auto getPrefOrder = [](const BlockLayoutChunk &chunk) {
+ if (chunk.Capture && chunk.Capture->isByRef())
+ return 1;
+ if (chunk.Lifetime == Qualifiers::OCL_Strong)
+ return 0;
+ if (chunk.Lifetime == Qualifiers::OCL_Weak)
+ return 2;
+ return 3;
+ };
+
+ return getPrefOrder(left) < getPrefOrder(right);
}
-}
+} // end anonymous namespace
/// Determines if the given type is safe for constant capture in C++.
static bool isSafeForCXXConstantCapture(QualType type) {
@@ -302,31 +292,20 @@ static CharUnits getLowBit(CharUnits v) {
static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
SmallVectorImpl<llvm::Type*> &elementTypes) {
- ASTContext &C = CGM.getContext();
-
- // The header is basically a 'struct { void *; int; int; void *; void *; }'.
- CharUnits ptrSize, ptrAlign, intSize, intAlign;
- std::tie(ptrSize, ptrAlign) = C.getTypeInfoInChars(C.VoidPtrTy);
- std::tie(intSize, intAlign) = C.getTypeInfoInChars(C.IntTy);
-
- // Are there crazy embedded platforms where this isn't true?
- assert(intSize <= ptrSize && "layout assumptions horribly violated");
+ // The header is basically 'struct { void *; int; int; void *; void *; }'.
+ // Assert that that struct is packed.
+ assert(CGM.getIntSize() <= CGM.getPointerSize());
+ assert(CGM.getIntAlign() <= CGM.getPointerAlign());
+ assert((2 * CGM.getIntSize()).isMultipleOf(CGM.getPointerAlign()));
- CharUnits headerSize = ptrSize;
- if (2 * intSize < ptrAlign) headerSize += ptrSize;
- else headerSize += 2 * intSize;
- headerSize += 2 * ptrSize;
-
- info.BlockAlign = ptrAlign;
- info.BlockSize = headerSize;
+ info.BlockAlign = CGM.getPointerAlign();
+ info.BlockSize = 3 * CGM.getPointerSize() + 2 * CGM.getIntSize();
assert(elementTypes.empty());
- llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy);
- llvm::Type *intTy = CGM.getTypes().ConvertType(C.IntTy);
- elementTypes.push_back(i8p);
- elementTypes.push_back(intTy);
- elementTypes.push_back(intTy);
- elementTypes.push_back(i8p);
+ elementTypes.push_back(CGM.VoidPtrTy);
+ elementTypes.push_back(CGM.IntTy);
+ elementTypes.push_back(CGM.IntTy);
+ elementTypes.push_back(CGM.VoidPtrTy);
elementTypes.push_back(CGM.getBlockDescriptorType());
assert(elementTypes.size() == BlockHeaderSize);
@@ -365,6 +344,8 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
"Can't capture 'this' outside a method");
QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType(C);
+ // Theoretically, this could be in a different address space, so
+ // don't assume standard pointer size/align.
llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType);
std::pair<CharUnits,CharUnits> tinfo
= CGM.getContext().getTypeInfoInChars(thisType);
@@ -384,15 +365,12 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
info.NeedsCopyDispose = true;
// Just use void* instead of a pointer to the byref type.
- QualType byRefPtrTy = C.VoidPtrTy;
-
- llvm::Type *llvmType = CGM.getTypes().ConvertType(byRefPtrTy);
- std::pair<CharUnits,CharUnits> tinfo
- = CGM.getContext().getTypeInfoInChars(byRefPtrTy);
- maxFieldAlign = std::max(maxFieldAlign, tinfo.second);
+ CharUnits align = CGM.getPointerAlign();
+ maxFieldAlign = std::max(maxFieldAlign, align);
- layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first,
- Qualifiers::OCL_None, &CI, llvmType));
+ layout.push_back(BlockLayoutChunk(align, CGM.getPointerSize(),
+ Qualifiers::OCL_None, &CI,
+ CGM.VoidPtrTy));
continue;
}
@@ -421,9 +399,15 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
// Block pointers require copy/dispose. So do Objective-C pointers.
} else if (variable->getType()->isObjCRetainableType()) {
- info.NeedsCopyDispose = true;
- // used for mrr below.
- lifetime = Qualifiers::OCL_Strong;
+ // But honor the inert __unsafe_unretained qualifier, which doesn't
+ // actually make it into the type system.
+ if (variable->getType()->isObjCInertUnsafeUnretainedType()) {
+ lifetime = Qualifiers::OCL_ExplicitNone;
+ } else {
+ info.NeedsCopyDispose = true;
+ // used for mrr below.
+ lifetime = Qualifiers::OCL_Strong;
+ }
// So do types that require non-trivial copy construction.
} else if (CI.hasCopyExpr()) {
@@ -504,18 +488,13 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
for (; li != le; ++li) {
assert(endAlign >= li->Alignment);
- li->setIndex(info, elementTypes.size());
+ li->setIndex(info, elementTypes.size(), blockSize);
elementTypes.push_back(li->Type);
blockSize += li->Size;
endAlign = getLowBit(blockSize);
// ...until we get to the alignment of the maximum field.
if (endAlign >= maxFieldAlign) {
- if (li == first) {
- // No user field was appended. So, a gap was added.
- // Save total gap size for use in block layout bit map.
- info.BlockHeaderForcedGapSize = li->Size;
- }
break;
}
}
@@ -532,6 +511,12 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
CharUnits newBlockSize = blockSize.RoundUpToAlignment(maxFieldAlign);
CharUnits padding = newBlockSize - blockSize;
+ // If we haven't yet added any fields, remember that there was an
+ // initial gap; this need to go into the block layout bit map.
+ if (blockSize == info.BlockHeaderForcedGapOffset) {
+ info.BlockHeaderForcedGapSize = padding;
+ }
+
elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty,
padding.getQuantity()));
blockSize = newBlockSize;
@@ -556,7 +541,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
endAlign = getLowBit(blockSize);
}
assert(endAlign >= li->Alignment);
- li->setIndex(info, elementTypes.size());
+ li->setIndex(info, elementTypes.size(), blockSize);
elementTypes.push_back(li->Type);
blockSize += li->Size;
endAlign = getLowBit(blockSize);
@@ -586,9 +571,8 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
if (blockInfo.CanBeGlobal) return;
// Make the allocation for the block.
- blockInfo.Address =
- CGF.CreateTempAlloca(blockInfo.StructureType, "block");
- blockInfo.Address->setAlignment(blockInfo.BlockAlign.getQuantity());
+ blockInfo.LocalAddress = CGF.CreateTempAlloca(blockInfo.StructureType,
+ blockInfo.BlockAlign, "block");
// If there are cleanups to emit, enter them (but inactive).
if (!blockInfo.NeedsCopyDispose) return;
@@ -621,12 +605,13 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
}
// GEP down to the address.
- llvm::Value *addr = CGF.Builder.CreateStructGEP(
- blockInfo.StructureType, blockInfo.Address, capture.getIndex());
+ Address addr = CGF.Builder.CreateStructGEP(blockInfo.LocalAddress,
+ capture.getIndex(),
+ capture.getOffset());
// We can use that GEP as the dominating IP.
if (!blockInfo.DominatingIP)
- blockInfo.DominatingIP = cast<llvm::Instruction>(addr);
+ blockInfo.DominatingIP = cast<llvm::Instruction>(addr.getPointer());
CleanupKind cleanupKind = InactiveNormalCleanup;
bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind);
@@ -721,9 +706,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// Build the block descriptor.
llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo);
- llvm::Type *blockTy = blockInfo.StructureType;
- llvm::AllocaInst *blockAddr = blockInfo.Address;
- assert(blockAddr && "block has no address!");
+ Address blockAddr = blockInfo.LocalAddress;
+ assert(blockAddr.isValid() && "block has no address!");
// Compute the initial on-stack block flags.
BlockFlags flags = BLOCK_HAS_SIGNATURE;
@@ -732,27 +716,44 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ;
if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET;
- // Initialize the block literal.
- Builder.CreateStore(
- isa, Builder.CreateStructGEP(blockTy, blockAddr, 0, "block.isa"));
- Builder.CreateStore(
- llvm::ConstantInt::get(IntTy, flags.getBitMask()),
- Builder.CreateStructGEP(blockTy, blockAddr, 1, "block.flags"));
- Builder.CreateStore(
- llvm::ConstantInt::get(IntTy, 0),
- Builder.CreateStructGEP(blockTy, blockAddr, 2, "block.reserved"));
- Builder.CreateStore(
- blockFn, Builder.CreateStructGEP(blockTy, blockAddr, 3, "block.invoke"));
- Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockTy, blockAddr, 4,
- "block.descriptor"));
+ auto projectField =
+ [&](unsigned index, CharUnits offset, const Twine &name) -> Address {
+ return Builder.CreateStructGEP(blockAddr, index, offset, name);
+ };
+ auto storeField =
+ [&](llvm::Value *value, unsigned index, CharUnits offset,
+ const Twine &name) {
+ Builder.CreateStore(value, projectField(index, offset, name));
+ };
+
+ // Initialize the block header.
+ {
+ // We assume all the header fields are densely packed.
+ unsigned index = 0;
+ CharUnits offset;
+ auto addHeaderField =
+ [&](llvm::Value *value, CharUnits size, const Twine &name) {
+ storeField(value, index, offset, name);
+ offset += size;
+ index++;
+ };
+
+ addHeaderField(isa, getPointerSize(), "block.isa");
+ addHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
+ getIntSize(), "block.flags");
+ addHeaderField(llvm::ConstantInt::get(IntTy, 0),
+ getIntSize(), "block.reserved");
+ addHeaderField(blockFn, getPointerSize(), "block.invoke");
+ addHeaderField(descriptor, getPointerSize(), "block.descriptor");
+ }
// Finally, capture all the values into the block.
const BlockDecl *blockDecl = blockInfo.getBlockDecl();
// First, 'this'.
if (blockDecl->capturesCXXThis()) {
- llvm::Value *addr = Builder.CreateStructGEP(
- blockTy, blockAddr, blockInfo.CXXThisIndex, "block.captured-this.addr");
+ Address addr = projectField(blockInfo.CXXThisIndex, blockInfo.CXXThisOffset,
+ "block.captured-this.addr");
Builder.CreateStore(LoadCXXThis(), addr);
}
@@ -765,35 +766,37 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
if (capture.isConstant()) continue;
QualType type = variable->getType();
- CharUnits align = getContext().getDeclAlign(variable);
// This will be a [[type]]*, except that a byref entry will just be
// an i8**.
- llvm::Value *blockField = Builder.CreateStructGEP(
- blockTy, blockAddr, capture.getIndex(), "block.captured");
+ Address blockField =
+ projectField(capture.getIndex(), capture.getOffset(), "block.captured");
// Compute the address of the thing we're going to move into the
// block literal.
- llvm::Value *src;
+ Address src = Address::invalid();
if (BlockInfo && CI.isNested()) {
// We need to use the capture from the enclosing block.
const CGBlockInfo::Capture &enclosingCapture =
BlockInfo->getCapture(variable);
// This is a [[type]]*, except that a byref entry wil just be an i8**.
- src = Builder.CreateStructGEP(BlockInfo->StructureType, LoadBlockStruct(),
+ src = Builder.CreateStructGEP(LoadBlockStruct(),
enclosingCapture.getIndex(),
+ enclosingCapture.getOffset(),
"block.capture.addr");
} else if (blockDecl->isConversionFromLambda()) {
// The lambda capture in a lambda's conversion-to-block-pointer is
// special; we'll simply emit it directly.
- src = nullptr;
+ src = Address::invalid();
} else {
// Just look it up in the locals map, which will give us back a
// [[type]]*. If that doesn't work, do the more elaborate DRE
// emission.
- src = LocalDeclMap.lookup(variable);
- if (!src) {
+ auto it = LocalDeclMap.find(variable);
+ if (it != LocalDeclMap.end()) {
+ src = it->second;
+ } else {
DeclRefExpr declRef(
const_cast<VarDecl *>(variable),
/*RefersToEnclosingVariableOrCapture*/ CI.isNested(), type,
@@ -808,14 +811,14 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// live a shorter life than the stack byref anyway.
if (CI.isByRef()) {
// Get a void* that points to the byref struct.
+ llvm::Value *byrefPointer;
if (CI.isNested())
- src = Builder.CreateAlignedLoad(src, align.getQuantity(),
- "byref.capture");
+ byrefPointer = Builder.CreateLoad(src, "byref.capture");
else
- src = Builder.CreateBitCast(src, VoidPtrTy);
+ byrefPointer = Builder.CreateBitCast(src.getPointer(), VoidPtrTy);
// Write that void* into the capture field.
- Builder.CreateAlignedStore(src, blockField, align.getQuantity());
+ Builder.CreateStore(byrefPointer, blockField);
// If we have a copy constructor, evaluate that into the block field.
} else if (const Expr *copyExpr = CI.getCopyExpr()) {
@@ -823,7 +826,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// If we have a lambda conversion, emit the expression
// directly into the block instead.
AggValueSlot Slot =
- AggValueSlot::forAddr(blockField, align, Qualifiers(),
+ AggValueSlot::forAddr(blockField, Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased);
@@ -834,9 +837,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// If it's a reference variable, copy the reference into the block field.
} else if (type->isReferenceType()) {
- llvm::Value *ref =
- Builder.CreateAlignedLoad(src, align.getQuantity(), "ref.val");
- Builder.CreateAlignedStore(ref, blockField, align.getQuantity());
+ llvm::Value *ref = Builder.CreateLoad(src, "ref.val");
+ Builder.CreateStore(ref, blockField);
// If this is an ARC __strong block-pointer variable, don't do a
// block copy.
@@ -848,13 +850,11 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
} else if (type.getObjCLifetime() == Qualifiers::OCL_Strong &&
type->isBlockPointerType()) {
// Load the block and do a simple retain.
- LValue srcLV = MakeAddrLValue(src, type, align);
- llvm::Value *value = EmitLoadOfScalar(srcLV, SourceLocation());
+ llvm::Value *value = Builder.CreateLoad(src, "block.captured_block");
value = EmitARCRetainNonBlock(value);
// Do a primitive store to the block field.
- LValue destLV = MakeAddrLValue(blockField, type, align);
- EmitStoreOfScalar(value, destLV, /*init*/ true);
+ Builder.CreateStore(value, blockField);
// Otherwise, fake up a POD copy into the block field.
} else {
@@ -876,7 +876,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// attributed to a reasonable location - otherwise it may be attributed to
// locations of subexpressions in the initialization.
EmitExprAsInit(&l2r, &blockFieldPseudoVar,
- MakeAddrLValue(blockField, type, align),
+ MakeAddrLValue(blockField, type, AlignmentSource::Decl),
/*captured by init*/ false);
}
@@ -891,7 +891,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// Cast to the converted block-pointer type, which happens (somewhat
// unfortunately) to be a pointer to function type.
llvm::Value *result =
- Builder.CreateBitCast(blockAddr,
+ Builder.CreateBitCast(blockAddr.getPointer(),
ConvertType(blockInfo.getBlockExpr()->getType()));
return result;
@@ -949,7 +949,6 @@ llvm::Type *CodeGenModule::getGenericBlockLiteralType() {
return GenericBlockLiteralType;
}
-
RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue) {
const BlockPointerType *BPT =
@@ -966,8 +965,8 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
// Get the function pointer from the literal.
- llvm::Value *FuncPtr = Builder.CreateStructGEP(
- CGM.getGenericBlockLiteralType(), BlockLiteral, 3);
+ llvm::Value *FuncPtr =
+ Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockLiteral, 3);
BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy);
@@ -978,11 +977,10 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
QualType FnType = BPT->getPointeeType();
// And the rest of the arguments.
- EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(),
- E->arg_begin(), E->arg_end());
+ EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments());
// Load the function.
- llvm::Value *Func = Builder.CreateLoad(FuncPtr);
+ llvm::Value *Func = Builder.CreateAlignedLoad(FuncPtr, getPointerAlign());
const FunctionType *FuncTy = FnType->castAs<FunctionType>();
const CGFunctionInfo &FnInfo =
@@ -998,41 +996,35 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
return EmitCall(FnInfo, Func, ReturnValue, Args);
}
-llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
- bool isByRef) {
+Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
+ bool isByRef) {
assert(BlockInfo && "evaluating block ref without block information?");
const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable);
// Handle constant captures.
- if (capture.isConstant()) return LocalDeclMap[variable];
+ if (capture.isConstant()) return LocalDeclMap.find(variable)->second;
- llvm::Value *addr =
- Builder.CreateStructGEP(BlockInfo->StructureType, LoadBlockStruct(),
- capture.getIndex(), "block.capture.addr");
+ Address addr =
+ Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(),
+ capture.getOffset(), "block.capture.addr");
if (isByRef) {
// addr should be a void** right now. Load, then cast the result
// to byref*.
- addr = Builder.CreateLoad(addr);
- auto *byrefType = BuildByRefType(variable);
- llvm::PointerType *byrefPointerType = llvm::PointerType::get(byrefType, 0);
- addr = Builder.CreateBitCast(addr, byrefPointerType,
- "byref.addr");
-
- // Follow the forwarding pointer.
- addr = Builder.CreateStructGEP(byrefType, addr, 1, "byref.forwarding");
- addr = Builder.CreateLoad(addr, "byref.addr.forwarded");
-
- // Cast back to byref* and GEP over to the actual object.
- addr = Builder.CreateBitCast(addr, byrefPointerType);
- addr = Builder.CreateStructGEP(byrefType, addr,
- getByRefValueLLVMField(variable).second,
- variable->getNameAsString());
+ auto &byrefInfo = getBlockByrefInfo(variable);
+ addr = Address(Builder.CreateLoad(addr), byrefInfo.ByrefAlignment);
+
+ auto byrefPointerType = llvm::PointerType::get(byrefInfo.Type, 0);
+ addr = Builder.CreateBitCast(addr, byrefPointerType, "byref.addr");
+
+ addr = emitBlockByrefAddress(addr, byrefInfo, /*follow*/ true,
+ variable->getName());
}
- if (variable->getType()->isReferenceType())
- addr = Builder.CreateLoad(addr, "ref.tmp");
+ if (auto refType = variable->getType()->getAs<ReferenceType>()) {
+ addr = EmitLoadOfReference(addr, refType);
+ }
return addr;
}
@@ -1049,7 +1041,7 @@ CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr,
// Using that metadata, generate the actual block function.
llvm::Constant *blockFn;
{
- llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
+ CodeGenFunction::DeclMapTy LocalDeclMap;
blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(),
blockInfo,
LocalDeclMap,
@@ -1103,6 +1095,44 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
return llvm::ConstantExpr::getBitCast(literal, requiredType);
}
+void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,
+ unsigned argNum,
+ llvm::Value *arg) {
+ assert(BlockInfo && "not emitting prologue of block invocation function?!");
+
+ llvm::Value *localAddr = nullptr;
+ if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
+ // Allocate a stack slot to let the debug info survive the RA.
+ Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr");
+ Builder.CreateStore(arg, alloc);
+ localAddr = Builder.CreateLoad(alloc);
+ }
+
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ if (CGM.getCodeGenOpts().getDebugInfo()
+ >= CodeGenOptions::LimitedDebugInfo) {
+ DI->setLocation(D->getLocation());
+ DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, arg, argNum,
+ localAddr, Builder);
+ }
+ }
+
+ SourceLocation StartLoc = BlockInfo->getBlockExpr()->getBody()->getLocStart();
+ ApplyDebugLocation Scope(*this, StartLoc);
+
+ // Instead of messing around with LocalDeclMap, just set the value
+ // directly as BlockPointer.
+ BlockPointer = Builder.CreateBitCast(arg,
+ BlockInfo->StructureType->getPointerTo(),
+ "block");
+}
+
+Address CodeGenFunction::LoadBlockStruct() {
+ assert(BlockInfo && "not in a block invocation function!");
+ assert(BlockPointer && "no block pointer set!");
+ return Address(BlockPointer, BlockInfo->BlockAlign);
+}
+
llvm::Function *
CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
const CGBlockInfo &blockInfo,
@@ -1122,7 +1152,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) {
const auto *var = dyn_cast<VarDecl>(i->first);
if (var && !var->hasLocalStorage())
- LocalDeclMap[var] = i->second;
+ setAddrOfLocalVar(var, i->second);
}
// Begin building the function declaration.
@@ -1163,35 +1193,28 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
blockInfo.getBlockExpr()->getBody()->getLocStart());
// Okay. Undo some of what StartFunction did.
-
- // Pull the 'self' reference out of the local decl map.
- llvm::Value *blockAddr = LocalDeclMap[&selfDecl];
- LocalDeclMap.erase(&selfDecl);
- BlockPointer = Builder.CreateBitCast(blockAddr,
- blockInfo.StructureType->getPointerTo(),
- "block");
+
// At -O0 we generate an explicit alloca for the BlockPointer, so the RA
// won't delete the dbg.declare intrinsics for captured variables.
llvm::Value *BlockPointerDbgLoc = BlockPointer;
if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
// Allocate a stack slot for it, so we can point the debugger to it
- llvm::AllocaInst *Alloca = CreateTempAlloca(BlockPointer->getType(),
- "block.addr");
- unsigned Align = getContext().getDeclAlign(&selfDecl).getQuantity();
- Alloca->setAlignment(Align);
+ Address Alloca = CreateTempAlloca(BlockPointer->getType(),
+ getPointerAlign(),
+ "block.addr");
// Set the DebugLocation to empty, so the store is recognized as a
// frame setup instruction by llvm::DwarfDebug::beginFunction().
auto NL = ApplyDebugLocation::CreateEmpty(*this);
- Builder.CreateAlignedStore(BlockPointer, Alloca, Align);
- BlockPointerDbgLoc = Alloca;
+ Builder.CreateStore(BlockPointer, Alloca);
+ BlockPointerDbgLoc = Alloca.getPointer();
}
// If we have a C++ 'this' reference, go ahead and force it into
// existence now.
if (blockDecl->capturesCXXThis()) {
- llvm::Value *addr =
- Builder.CreateStructGEP(blockInfo.StructureType, BlockPointer,
- blockInfo.CXXThisIndex, "block.captured-this");
+ Address addr =
+ Builder.CreateStructGEP(LoadBlockStruct(), blockInfo.CXXThisIndex,
+ blockInfo.CXXThisOffset, "block.captured-this");
CXXThisValue = Builder.CreateLoad(addr, "this");
}
@@ -1201,15 +1224,13 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
if (!capture.isConstant()) continue;
- unsigned align = getContext().getDeclAlign(variable).getQuantity();
-
- llvm::AllocaInst *alloca =
- CreateMemTemp(variable->getType(), "block.captured-const");
- alloca->setAlignment(align);
+ CharUnits align = getContext().getDeclAlign(variable);
+ Address alloca =
+ CreateMemTemp(variable->getType(), align, "block.captured-const");
- Builder.CreateAlignedStore(capture.getConstant(), alloca, align);
+ Builder.CreateStore(capture.getConstant(), alloca);
- LocalDeclMap[variable] = alloca;
+ setAddrOfLocalVar(variable, alloca);
}
// Save a spot to insert the debug information for all the DeclRefExprs.
@@ -1220,7 +1241,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
if (IsLambdaConversionToBlock)
EmitLambdaBlockInvokeBody();
else {
- PGO.assignRegionCounters(blockDecl, fn);
+ PGO.assignRegionCounters(GlobalDecl(blockDecl), fn);
incrementProfileCounter(blockDecl->getBody());
EmitStmt(blockDecl->getBody());
}
@@ -1243,15 +1264,15 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
>= CodeGenOptions::LimitedDebugInfo) {
const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
if (capture.isConstant()) {
- DI->EmitDeclareOfAutoVariable(variable, LocalDeclMap[variable],
+ auto addr = LocalDeclMap.find(variable)->second;
+ DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(),
Builder);
continue;
}
- DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointerDbgLoc,
- Builder, blockInfo,
- entry_ptr == entry->end()
- ? nullptr : entry_ptr);
+ DI->EmitDeclareOfBlockDeclRefVariable(
+ variable, BlockPointerDbgLoc, Builder, blockInfo,
+ entry_ptr == entry->end() ? nullptr : &*entry_ptr);
}
}
// Recover location if it was changed in the above loop.
@@ -1288,7 +1309,6 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
}
*/
-
/// Generate the copy-helper function for a block closure object:
/// static void block_copy_helper(block_t *dst, block_t *src);
/// The runtime will have previously initialized 'dst' by doing a
@@ -1330,18 +1350,21 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
nullptr, SC_Static,
false,
false);
+
+ CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+
auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(FD, C.VoidTy, Fn, FI, args);
// Create a scope with an artificial location for the body of this function.
auto AL = ApplyDebugLocation::CreateArtificial(*this);
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
- llvm::Value *src = GetAddrOfLocalVar(&srcDecl);
- src = Builder.CreateLoad(src);
+ Address src = GetAddrOfLocalVar(&srcDecl);
+ src = Address(Builder.CreateLoad(src), blockInfo.BlockAlign);
src = Builder.CreateBitCast(src, structPtrTy, "block.source");
- llvm::Value *dst = GetAddrOfLocalVar(&dstDecl);
- dst = Builder.CreateLoad(dst);
+ Address dst = GetAddrOfLocalVar(&dstDecl);
+ dst = Address(Builder.CreateLoad(dst), blockInfo.BlockAlign);
dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest");
const BlockDecl *blockDecl = blockInfo.getBlockDecl();
@@ -1375,40 +1398,38 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
flags = BLOCK_FIELD_IS_BLOCK;
// Special rules for ARC captures:
- if (getLangOpts().ObjCAutoRefCount) {
- Qualifiers qs = type.getQualifiers();
-
- // We need to register __weak direct captures with the runtime.
- if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) {
- useARCWeakCopy = true;
-
- // We need to retain the copied value for __strong direct captures.
- } else if (qs.getObjCLifetime() == Qualifiers::OCL_Strong) {
- // If it's a block pointer, we have to copy the block and
- // assign that to the destination pointer, so we might as
- // well use _Block_object_assign. Otherwise we can avoid that.
- if (!isBlockPointer)
- useARCStrongCopy = true;
-
- // Otherwise the memcpy is fine.
- } else {
- continue;
- }
+ Qualifiers qs = type.getQualifiers();
+
+ // We need to register __weak direct captures with the runtime.
+ if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) {
+ useARCWeakCopy = true;
+
+ // We need to retain the copied value for __strong direct captures.
+ } else if (qs.getObjCLifetime() == Qualifiers::OCL_Strong) {
+ // If it's a block pointer, we have to copy the block and
+ // assign that to the destination pointer, so we might as
+ // well use _Block_object_assign. Otherwise we can avoid that.
+ if (!isBlockPointer)
+ useARCStrongCopy = true;
// Non-ARC captures of retainable pointers are strong and
// therefore require a call to _Block_object_assign.
- } else {
+ } else if (!qs.getObjCLifetime() && !getLangOpts().ObjCAutoRefCount) {
// fall through
+
+ // Otherwise the memcpy is fine.
+ } else {
+ continue;
}
+
+ // For all other types, the memcpy is fine.
} else {
continue;
}
unsigned index = capture.getIndex();
- llvm::Value *srcField =
- Builder.CreateStructGEP(blockInfo.StructureType, src, index);
- llvm::Value *dstField =
- Builder.CreateStructGEP(blockInfo.StructureType, dst, index);
+ Address srcField = Builder.CreateStructGEP(src, index, capture.getOffset());
+ Address dstField = Builder.CreateStructGEP(dst, index, capture.getOffset());
// If there's an explicit copy expression, we do that.
if (copyExpr) {
@@ -1435,11 +1456,12 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
// We don't need this anymore, so kill it. It's not quite
// worth the annoyance to avoid creating it in the first place.
- cast<llvm::Instruction>(dstField)->eraseFromParent();
+ cast<llvm::Instruction>(dstField.getPointer())->eraseFromParent();
}
} else {
srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy);
- llvm::Value *dstAddr = Builder.CreateBitCast(dstField, VoidPtrTy);
+ llvm::Value *dstAddr =
+ Builder.CreateBitCast(dstField.getPointer(), VoidPtrTy);
llvm::Value *args[] = {
dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask())
};
@@ -1502,6 +1524,9 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
SourceLocation(), II, C.VoidTy,
nullptr, SC_Static,
false, false);
+
+ CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+
// Create a scope with an artificial location for the body of this function.
auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(FD, C.VoidTy, Fn, FI, args);
@@ -1509,8 +1534,8 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
- llvm::Value *src = GetAddrOfLocalVar(&srcDecl);
- src = Builder.CreateLoad(src);
+ Address src = GetAddrOfLocalVar(&srcDecl);
+ src = Address(Builder.CreateLoad(src), blockInfo.BlockAlign);
src = Builder.CreateBitCast(src, structPtrTy, "block");
const BlockDecl *blockDecl = blockInfo.getBlockDecl();
@@ -1544,29 +1569,31 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
flags = BLOCK_FIELD_IS_BLOCK;
// Special rules for ARC captures.
- if (getLangOpts().ObjCAutoRefCount) {
- Qualifiers qs = type.getQualifiers();
+ Qualifiers qs = type.getQualifiers();
- // Don't generate special dispose logic for a captured object
- // unless it's __strong or __weak.
- if (!qs.hasStrongOrWeakObjCLifetime())
- continue;
+ // Use objc_storeStrong for __strong direct captures; the
+ // dynamic tools really like it when we do this.
+ if (qs.getObjCLifetime() == Qualifiers::OCL_Strong) {
+ useARCStrongDestroy = true;
+
+ // Support __weak direct captures.
+ } else if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) {
+ useARCWeakDestroy = true;
- // Support __weak direct captures.
- if (qs.getObjCLifetime() == Qualifiers::OCL_Weak)
- useARCWeakDestroy = true;
+ // Non-ARC captures are strong, and we need to use _Block_object_dispose.
+ } else if (!qs.hasObjCLifetime() && !getLangOpts().ObjCAutoRefCount) {
+ // fall through
- // Tools really want us to use objc_storeStrong here.
- else
- useARCStrongDestroy = true;
+ // Otherwise, we have nothing to do.
+ } else {
+ continue;
}
} else {
continue;
}
- unsigned index = capture.getIndex();
- llvm::Value *srcField =
- Builder.CreateStructGEP(blockInfo.StructureType, src, index);
+ Address srcField =
+ Builder.CreateStructGEP(src, capture.getIndex(), capture.getOffset());
// If there's an explicit copy expression, we do that.
if (dtor) {
@@ -1600,15 +1627,15 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
namespace {
/// Emits the copy/dispose helper functions for a __block object of id type.
-class ObjectByrefHelpers : public CodeGenModule::ByrefHelpers {
+class ObjectByrefHelpers final : public BlockByrefHelpers {
BlockFieldFlags Flags;
public:
ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags)
- : ByrefHelpers(alignment), Flags(flags) {}
+ : BlockByrefHelpers(alignment), Flags(flags) {}
- void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
- llvm::Value *srcField) override {
+ void emitCopy(CodeGenFunction &CGF, Address destField,
+ Address srcField) override {
destField = CGF.Builder.CreateBitCast(destField, CGF.VoidPtrTy);
srcField = CGF.Builder.CreateBitCast(srcField, CGF.VoidPtrPtrTy);
@@ -1619,11 +1646,11 @@ public:
llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags);
llvm::Value *fn = CGF.CGM.getBlockObjectAssign();
- llvm::Value *args[] = { destField, srcValue, flagsVal };
+ llvm::Value *args[] = { destField.getPointer(), srcValue, flagsVal };
CGF.EmitNounwindRuntimeCall(fn, args);
}
- void emitDispose(CodeGenFunction &CGF, llvm::Value *field) override {
+ void emitDispose(CodeGenFunction &CGF, Address field) override {
field = CGF.Builder.CreateBitCast(field, CGF.Int8PtrTy->getPointerTo(0));
llvm::Value *value = CGF.Builder.CreateLoad(field);
@@ -1636,16 +1663,16 @@ public:
};
/// Emits the copy/dispose helpers for an ARC __block __weak variable.
-class ARCWeakByrefHelpers : public CodeGenModule::ByrefHelpers {
+class ARCWeakByrefHelpers final : public BlockByrefHelpers {
public:
- ARCWeakByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {}
+ ARCWeakByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {}
- void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
- llvm::Value *srcField) override {
+ void emitCopy(CodeGenFunction &CGF, Address destField,
+ Address srcField) override {
CGF.EmitARCMoveWeak(destField, srcField);
}
- void emitDispose(CodeGenFunction &CGF, llvm::Value *field) override {
+ void emitDispose(CodeGenFunction &CGF, Address field) override {
CGF.EmitARCDestroyWeak(field);
}
@@ -1657,36 +1684,31 @@ public:
/// Emits the copy/dispose helpers for an ARC __block __strong variable
/// that's not of block-pointer type.
-class ARCStrongByrefHelpers : public CodeGenModule::ByrefHelpers {
+class ARCStrongByrefHelpers final : public BlockByrefHelpers {
public:
- ARCStrongByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {}
+ ARCStrongByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {}
- void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
- llvm::Value *srcField) override {
+ void emitCopy(CodeGenFunction &CGF, Address destField,
+ Address srcField) override {
// Do a "move" by copying the value and then zeroing out the old
// variable.
- llvm::LoadInst *value = CGF.Builder.CreateLoad(srcField);
- value->setAlignment(Alignment.getQuantity());
+ llvm::Value *value = CGF.Builder.CreateLoad(srcField);
llvm::Value *null =
llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType()));
if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) {
- llvm::StoreInst *store = CGF.Builder.CreateStore(null, destField);
- store->setAlignment(Alignment.getQuantity());
+ CGF.Builder.CreateStore(null, destField);
CGF.EmitARCStoreStrongCall(destField, value, /*ignored*/ true);
CGF.EmitARCStoreStrongCall(srcField, null, /*ignored*/ true);
return;
}
- llvm::StoreInst *store = CGF.Builder.CreateStore(value, destField);
- store->setAlignment(Alignment.getQuantity());
-
- store = CGF.Builder.CreateStore(null, srcField);
- store->setAlignment(Alignment.getQuantity());
+ CGF.Builder.CreateStore(value, destField);
+ CGF.Builder.CreateStore(null, srcField);
}
- void emitDispose(CodeGenFunction &CGF, llvm::Value *field) override {
+ void emitDispose(CodeGenFunction &CGF, Address field) override {
CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime);
}
@@ -1698,25 +1720,22 @@ public:
/// Emits the copy/dispose helpers for an ARC __block __strong
/// variable that's of block-pointer type.
-class ARCStrongBlockByrefHelpers : public CodeGenModule::ByrefHelpers {
+class ARCStrongBlockByrefHelpers final : public BlockByrefHelpers {
public:
- ARCStrongBlockByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {}
+ ARCStrongBlockByrefHelpers(CharUnits alignment)
+ : BlockByrefHelpers(alignment) {}
- void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
- llvm::Value *srcField) override {
+ void emitCopy(CodeGenFunction &CGF, Address destField,
+ Address srcField) override {
// Do the copy with objc_retainBlock; that's all that
// _Block_object_assign would do anyway, and we'd have to pass the
// right arguments to make sure it doesn't get no-op'ed.
- llvm::LoadInst *oldValue = CGF.Builder.CreateLoad(srcField);
- oldValue->setAlignment(Alignment.getQuantity());
-
+ llvm::Value *oldValue = CGF.Builder.CreateLoad(srcField);
llvm::Value *copy = CGF.EmitARCRetainBlock(oldValue, /*mandatory*/ true);
-
- llvm::StoreInst *store = CGF.Builder.CreateStore(copy, destField);
- store->setAlignment(Alignment.getQuantity());
+ CGF.Builder.CreateStore(copy, destField);
}
- void emitDispose(CodeGenFunction &CGF, llvm::Value *field) override {
+ void emitDispose(CodeGenFunction &CGF, Address field) override {
CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime);
}
@@ -1728,23 +1747,23 @@ public:
/// Emits the copy/dispose helpers for a __block variable with a
/// nontrivial copy constructor or destructor.
-class CXXByrefHelpers : public CodeGenModule::ByrefHelpers {
+class CXXByrefHelpers final : public BlockByrefHelpers {
QualType VarType;
const Expr *CopyExpr;
public:
CXXByrefHelpers(CharUnits alignment, QualType type,
const Expr *copyExpr)
- : ByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {}
+ : BlockByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {}
bool needsCopy() const override { return CopyExpr != nullptr; }
- void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
- llvm::Value *srcField) override {
+ void emitCopy(CodeGenFunction &CGF, Address destField,
+ Address srcField) override {
if (!CopyExpr) return;
CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr);
}
- void emitDispose(CodeGenFunction &CGF, llvm::Value *field) override {
+ void emitDispose(CodeGenFunction &CGF, Address field) override {
EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin();
CGF.PushDestructorCleanup(VarType, field);
CGF.PopCleanupBlocks(cleanupDepth);
@@ -1757,10 +1776,8 @@ public:
} // end anonymous namespace
static llvm::Constant *
-generateByrefCopyHelper(CodeGenFunction &CGF,
- llvm::StructType &byrefType,
- unsigned valueFieldIndex,
- CodeGenModule::ByrefHelpers &byrefInfo) {
+generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo,
+ BlockByrefHelpers &generator) {
ASTContext &Context = CGF.getContext();
QualType R = Context.VoidTy;
@@ -1777,8 +1794,7 @@ generateByrefCopyHelper(CodeGenFunction &CGF,
const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeFreeFunctionDeclaration(
R, args, FunctionType::ExtInfo(), /*variadic=*/false);
- CodeGenTypes &Types = CGF.CGM.getTypes();
- llvm::FunctionType *LTy = Types.GetFunctionType(FI);
+ llvm::FunctionType *LTy = CGF.CGM.getTypes().GetFunctionType(FI);
// FIXME: We'd like to put these into a mergable by content, with
// internal linkage.
@@ -1796,26 +1812,30 @@ generateByrefCopyHelper(CodeGenFunction &CGF,
SC_Static,
false, false);
+ CGF.CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+
CGF.StartFunction(FD, R, Fn, FI, args);
- if (byrefInfo.needsCopy()) {
- llvm::Type *byrefPtrType = byrefType.getPointerTo(0);
+ if (generator.needsCopy()) {
+ llvm::Type *byrefPtrType = byrefInfo.Type->getPointerTo(0);
// dst->x
- llvm::Value *destField = CGF.GetAddrOfLocalVar(&dst);
- destField = CGF.Builder.CreateLoad(destField);
+ Address destField = CGF.GetAddrOfLocalVar(&dst);
+ destField = Address(CGF.Builder.CreateLoad(destField),
+ byrefInfo.ByrefAlignment);
destField = CGF.Builder.CreateBitCast(destField, byrefPtrType);
- destField = CGF.Builder.CreateStructGEP(&byrefType, destField,
- valueFieldIndex, "x");
+ destField = CGF.emitBlockByrefAddress(destField, byrefInfo, false,
+ "dest-object");
// src->x
- llvm::Value *srcField = CGF.GetAddrOfLocalVar(&src);
- srcField = CGF.Builder.CreateLoad(srcField);
+ Address srcField = CGF.GetAddrOfLocalVar(&src);
+ srcField = Address(CGF.Builder.CreateLoad(srcField),
+ byrefInfo.ByrefAlignment);
srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType);
- srcField =
- CGF.Builder.CreateStructGEP(&byrefType, srcField, valueFieldIndex, "x");
+ srcField = CGF.emitBlockByrefAddress(srcField, byrefInfo, false,
+ "src-object");
- byrefInfo.emitCopy(CGF, destField, srcField);
+ generator.emitCopy(CGF, destField, srcField);
}
CGF.FinishFunction();
@@ -1825,19 +1845,17 @@ generateByrefCopyHelper(CodeGenFunction &CGF,
/// Build the copy helper for a __block variable.
static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM,
- llvm::StructType &byrefType,
- unsigned byrefValueIndex,
- CodeGenModule::ByrefHelpers &info) {
+ const BlockByrefInfo &byrefInfo,
+ BlockByrefHelpers &generator) {
CodeGenFunction CGF(CGM);
- return generateByrefCopyHelper(CGF, byrefType, byrefValueIndex, info);
+ return generateByrefCopyHelper(CGF, byrefInfo, generator);
}
/// Generate code for a __block variable's dispose helper.
static llvm::Constant *
generateByrefDisposeHelper(CodeGenFunction &CGF,
- llvm::StructType &byrefType,
- unsigned byrefValueIndex,
- CodeGenModule::ByrefHelpers &byrefInfo) {
+ const BlockByrefInfo &byrefInfo,
+ BlockByrefHelpers &generator) {
ASTContext &Context = CGF.getContext();
QualType R = Context.VoidTy;
@@ -1849,8 +1867,7 @@ generateByrefDisposeHelper(CodeGenFunction &CGF,
const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeFreeFunctionDeclaration(
R, args, FunctionType::ExtInfo(), /*variadic=*/false);
- CodeGenTypes &Types = CGF.CGM.getTypes();
- llvm::FunctionType *LTy = Types.GetFunctionType(FI);
+ llvm::FunctionType *LTy = CGF.CGM.getTypes().GetFunctionType(FI);
// FIXME: We'd like to put these into a mergable by content, with
// internal linkage.
@@ -1868,15 +1885,19 @@ generateByrefDisposeHelper(CodeGenFunction &CGF,
SourceLocation(), II, R, nullptr,
SC_Static,
false, false);
+
+ CGF.CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+
CGF.StartFunction(FD, R, Fn, FI, args);
- if (byrefInfo.needsDispose()) {
- llvm::Value *V = CGF.GetAddrOfLocalVar(&src);
- V = CGF.Builder.CreateLoad(V);
- V = CGF.Builder.CreateBitCast(V, byrefType.getPointerTo(0));
- V = CGF.Builder.CreateStructGEP(&byrefType, V, byrefValueIndex, "x");
+ if (generator.needsDispose()) {
+ Address addr = CGF.GetAddrOfLocalVar(&src);
+ addr = Address(CGF.Builder.CreateLoad(addr), byrefInfo.ByrefAlignment);
+ auto byrefPtrType = byrefInfo.Type->getPointerTo(0);
+ addr = CGF.Builder.CreateBitCast(addr, byrefPtrType);
+ addr = CGF.emitBlockByrefAddress(addr, byrefInfo, false, "object");
- byrefInfo.emitDispose(CGF, V);
+ generator.emitDispose(CGF, addr);
}
CGF.FinishFunction();
@@ -1886,38 +1907,29 @@ generateByrefDisposeHelper(CodeGenFunction &CGF,
/// Build the dispose helper for a __block variable.
static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM,
- llvm::StructType &byrefType,
- unsigned byrefValueIndex,
- CodeGenModule::ByrefHelpers &info) {
+ const BlockByrefInfo &byrefInfo,
+ BlockByrefHelpers &generator) {
CodeGenFunction CGF(CGM);
- return generateByrefDisposeHelper(CGF, byrefType, byrefValueIndex, info);
+ return generateByrefDisposeHelper(CGF, byrefInfo, generator);
}
/// Lazily build the copy and dispose helpers for a __block variable
/// with the given information.
-template <class T> static T *buildByrefHelpers(CodeGenModule &CGM,
- llvm::StructType &byrefTy,
- unsigned byrefValueIndex,
- T &byrefInfo) {
- // Increase the field's alignment to be at least pointer alignment,
- // since the layout of the byref struct will guarantee at least that.
- byrefInfo.Alignment = std::max(byrefInfo.Alignment,
- CharUnits::fromQuantity(CGM.PointerAlignInBytes));
-
+template <class T>
+static T *buildByrefHelpers(CodeGenModule &CGM, const BlockByrefInfo &byrefInfo,
+ T &&generator) {
llvm::FoldingSetNodeID id;
- byrefInfo.Profile(id);
+ generator.Profile(id);
void *insertPos;
- CodeGenModule::ByrefHelpers *node
+ BlockByrefHelpers *node
= CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos);
if (node) return static_cast<T*>(node);
- byrefInfo.CopyHelper =
- buildByrefCopyHelper(CGM, byrefTy, byrefValueIndex, byrefInfo);
- byrefInfo.DisposeHelper =
- buildByrefDisposeHelper(CGM, byrefTy, byrefValueIndex,byrefInfo);
+ generator.CopyHelper = buildByrefCopyHelper(CGM, byrefInfo, generator);
+ generator.DisposeHelper = buildByrefDisposeHelper(CGM, byrefInfo, generator);
- T *copy = new (CGM.getContext()) T(byrefInfo);
+ T *copy = new (CGM.getContext()) T(std::move(generator));
CGM.ByrefHelpersCache.InsertNode(copy, insertPos);
return copy;
}
@@ -1925,20 +1937,25 @@ template <class T> static T *buildByrefHelpers(CodeGenModule &CGM,
/// Build the copy and dispose helpers for the given __block variable
/// emission. Places the helpers in the global cache. Returns null
/// if no helpers are required.
-CodeGenModule::ByrefHelpers *
+BlockByrefHelpers *
CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
const AutoVarEmission &emission) {
const VarDecl &var = *emission.Variable;
QualType type = var.getType();
- unsigned byrefValueIndex = getByRefValueLLVMField(&var).second;
+ auto &byrefInfo = getBlockByrefInfo(&var);
+
+ // The alignment we care about for the purposes of uniquing byref
+ // helpers is the alignment of the actual byref value field.
+ CharUnits valueAlignment =
+ byrefInfo.ByrefAlignment.alignmentAtOffset(byrefInfo.FieldOffset);
if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) {
const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var);
if (!copyExpr && record->hasTrivialDestructor()) return nullptr;
- CXXByrefHelpers byrefInfo(emission.Alignment, type, copyExpr);
- return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
+ return ::buildByrefHelpers(
+ CGM, byrefInfo, CXXByrefHelpers(valueAlignment, type, copyExpr));
}
// Otherwise, if we don't have a retainable type, there's nothing to do.
@@ -1949,8 +1966,6 @@ CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
// If we have lifetime, that dominates.
if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
- assert(getLangOpts().ObjCAutoRefCount);
-
switch (lifetime) {
case Qualifiers::OCL_None: llvm_unreachable("impossible");
@@ -1961,24 +1976,23 @@ CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
// Tell the runtime that this is ARC __weak, called by the
// byref routines.
- case Qualifiers::OCL_Weak: {
- ARCWeakByrefHelpers byrefInfo(emission.Alignment);
- return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
- }
+ case Qualifiers::OCL_Weak:
+ return ::buildByrefHelpers(CGM, byrefInfo,
+ ARCWeakByrefHelpers(valueAlignment));
// ARC __strong __block variables need to be retained.
case Qualifiers::OCL_Strong:
// Block pointers need to be copied, and there's no direct
// transfer possible.
if (type->isBlockPointerType()) {
- ARCStrongBlockByrefHelpers byrefInfo(emission.Alignment);
- return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
+ return ::buildByrefHelpers(CGM, byrefInfo,
+ ARCStrongBlockByrefHelpers(valueAlignment));
// Otherwise, we transfer ownership of the retain from the stack
// to the heap.
} else {
- ARCStrongByrefHelpers byrefInfo(emission.Alignment);
- return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
+ return ::buildByrefHelpers(CGM, byrefInfo,
+ ARCStrongByrefHelpers(valueAlignment));
}
}
llvm_unreachable("fell out of lifetime switch!");
@@ -1997,28 +2011,33 @@ CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
if (type.isObjCGCWeak())
flags |= BLOCK_FIELD_IS_WEAK;
- ObjectByrefHelpers byrefInfo(emission.Alignment, flags);
- return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
+ return ::buildByrefHelpers(CGM, byrefInfo,
+ ObjectByrefHelpers(valueAlignment, flags));
}
-std::pair<llvm::Type *, unsigned>
-CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const {
- assert(ByRefValueInfo.count(VD) && "Did not find value!");
-
- return ByRefValueInfo.find(VD)->second;
+Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr,
+ const VarDecl *var,
+ bool followForward) {
+ auto &info = getBlockByrefInfo(var);
+ return emitBlockByrefAddress(baseAddr, info, followForward, var->getName());
}
-llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr,
- const VarDecl *V) {
- auto P = getByRefValueLLVMField(V);
- llvm::Value *Loc =
- Builder.CreateStructGEP(P.first, BaseAddr, 1, "forwarding");
- Loc = Builder.CreateLoad(Loc);
- Loc = Builder.CreateStructGEP(P.first, Loc, P.second, V->getNameAsString());
- return Loc;
+Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr,
+ const BlockByrefInfo &info,
+ bool followForward,
+ const llvm::Twine &name) {
+ // Chase the forwarding address if requested.
+ if (followForward) {
+ Address forwardingAddr =
+ Builder.CreateStructGEP(baseAddr, 1, getPointerSize(), "forwarding");
+ baseAddr = Address(Builder.CreateLoad(forwardingAddr), info.ByrefAlignment);
+ }
+
+ return Builder.CreateStructGEP(baseAddr, info.FieldIndex,
+ info.FieldOffset, name);
}
-/// BuildByRefType - This routine changes a __block variable declared as T x
+/// BuildByrefInfo - This routine changes a __block variable declared as T x
/// into:
///
/// struct {
@@ -2033,108 +2052,116 @@ llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr,
/// T x;
/// } x
///
-llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) {
- std::pair<llvm::Type *, unsigned> &Info = ByRefValueInfo[D];
- if (Info.first)
- return Info.first;
+const BlockByrefInfo &CodeGenFunction::getBlockByrefInfo(const VarDecl *D) {
+ auto it = BlockByrefInfos.find(D);
+ if (it != BlockByrefInfos.end())
+ return it->second;
+
+ llvm::StructType *byrefType =
+ llvm::StructType::create(getLLVMContext(),
+ "struct.__block_byref_" + D->getNameAsString());
QualType Ty = D->getType();
+ CharUnits size;
SmallVector<llvm::Type *, 8> types;
- llvm::StructType *ByRefType =
- llvm::StructType::create(getLLVMContext(),
- "struct.__block_byref_" + D->getNameAsString());
-
// void *__isa;
types.push_back(Int8PtrTy);
+ size += getPointerSize();
// void *__forwarding;
- types.push_back(llvm::PointerType::getUnqual(ByRefType));
+ types.push_back(llvm::PointerType::getUnqual(byrefType));
+ size += getPointerSize();
// int32_t __flags;
types.push_back(Int32Ty);
+ size += CharUnits::fromQuantity(4);
// int32_t __size;
types.push_back(Int32Ty);
+ size += CharUnits::fromQuantity(4);
+
// Note that this must match *exactly* the logic in buildByrefHelpers.
- bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty, D);
- if (HasCopyAndDispose) {
+ bool hasCopyAndDispose = getContext().BlockRequiresCopying(Ty, D);
+ if (hasCopyAndDispose) {
/// void *__copy_helper;
types.push_back(Int8PtrTy);
+ size += getPointerSize();
/// void *__destroy_helper;
types.push_back(Int8PtrTy);
+ size += getPointerSize();
}
+
bool HasByrefExtendedLayout = false;
Qualifiers::ObjCLifetime Lifetime;
if (getContext().getByrefLifetime(Ty, Lifetime, HasByrefExtendedLayout) &&
- HasByrefExtendedLayout)
+ HasByrefExtendedLayout) {
/// void *__byref_variable_layout;
types.push_back(Int8PtrTy);
+ size += CharUnits::fromQuantity(PointerSizeInBytes);
+ }
- bool Packed = false;
- CharUnits Align = getContext().getDeclAlign(D);
- if (Align >
- getContext().toCharUnitsFromBits(getTarget().getPointerAlign(0))) {
- // We have to insert padding.
-
- // The struct above has 2 32-bit integers.
- unsigned CurrentOffsetInBytes = 4 * 2;
-
- // And either 2, 3, 4 or 5 pointers.
- unsigned noPointers = 2;
- if (HasCopyAndDispose)
- noPointers += 2;
- if (HasByrefExtendedLayout)
- noPointers += 1;
-
- CurrentOffsetInBytes += noPointers * CGM.getDataLayout().getTypeAllocSize(Int8PtrTy);
-
- // Align the offset.
- unsigned AlignedOffsetInBytes =
- llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity());
-
- unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes;
- if (NumPaddingBytes > 0) {
- llvm::Type *Ty = Int8Ty;
- // FIXME: We need a sema error for alignment larger than the minimum of
- // the maximal stack alignment and the alignment of malloc on the system.
- if (NumPaddingBytes > 1)
- Ty = llvm::ArrayType::get(Ty, NumPaddingBytes);
-
- types.push_back(Ty);
+ // T x;
+ llvm::Type *varTy = ConvertTypeForMem(Ty);
- // We want a packed struct.
- Packed = true;
- }
+ bool packed = false;
+ CharUnits varAlign = getContext().getDeclAlign(D);
+ CharUnits varOffset = size.RoundUpToAlignment(varAlign);
+
+ // We may have to insert padding.
+ if (varOffset != size) {
+ llvm::Type *paddingTy =
+ llvm::ArrayType::get(Int8Ty, (varOffset - size).getQuantity());
+
+ types.push_back(paddingTy);
+ size = varOffset;
+
+ // Conversely, we might have to prevent LLVM from inserting padding.
+ } else if (CGM.getDataLayout().getABITypeAlignment(varTy)
+ > varAlign.getQuantity()) {
+ packed = true;
}
+ types.push_back(varTy);
- // T x;
- types.push_back(ConvertTypeForMem(Ty));
-
- ByRefType->setBody(types, Packed);
-
- Info.first = ByRefType;
-
- Info.second = types.size() - 1;
-
- return Info.first;
+ byrefType->setBody(types, packed);
+
+ BlockByrefInfo info;
+ info.Type = byrefType;
+ info.FieldIndex = types.size() - 1;
+ info.FieldOffset = varOffset;
+ info.ByrefAlignment = std::max(varAlign, getPointerAlign());
+
+ auto pair = BlockByrefInfos.insert({D, info});
+ assert(pair.second && "info was inserted recursively?");
+ return pair.first->second;
}
/// Initialize the structural components of a __block variable, i.e.
/// everything but the actual object.
void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
// Find the address of the local.
- llvm::Value *addr = emission.Address;
+ Address addr = emission.Addr;
// That's an alloca of the byref structure type.
llvm::StructType *byrefType = cast<llvm::StructType>(
- cast<llvm::PointerType>(addr->getType())->getElementType());
+ cast<llvm::PointerType>(addr.getPointer()->getType())->getElementType());
+
+ unsigned nextHeaderIndex = 0;
+ CharUnits nextHeaderOffset;
+ auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize,
+ const Twine &name) {
+ auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex,
+ nextHeaderOffset, name);
+ Builder.CreateStore(value, fieldAddr);
+
+ nextHeaderIndex++;
+ nextHeaderOffset += fieldSize;
+ };
// Build the byref helpers if necessary. This is null if we don't need any.
- CodeGenModule::ByrefHelpers *helpers =
- buildByrefHelpers(*byrefType, emission);
+ BlockByrefHelpers *helpers = buildByrefHelpers(*byrefType, emission);
const VarDecl &D = *emission.Variable;
QualType type = D.getType();
@@ -2143,7 +2170,7 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
Qualifiers::ObjCLifetime ByrefLifetime;
bool ByRefHasLifetime =
getContext().getByrefLifetime(type, ByrefLifetime, HasByrefExtendedLayout);
-
+
llvm::Value *V;
// Initialize the 'isa', which is just 0 or 1.
@@ -2151,12 +2178,10 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
if (type.isObjCGCWeak())
isa = 1;
V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
- Builder.CreateStore(V,
- Builder.CreateStructGEP(nullptr, addr, 0, "byref.isa"));
+ storeHeaderField(V, getPointerSize(), "byref.isa");
// Store the address of the variable into its own forwarding pointer.
- Builder.CreateStore(
- addr, Builder.CreateStructGEP(nullptr, addr, 1, "byref.forwarding"));
+ storeHeaderField(addr.getPointer(), getPointerSize(), "byref.forwarding");
// Blocks ABI:
// c) the flags field is set to either 0 if no helper functions are
@@ -2202,31 +2227,23 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
printf("\n");
}
}
-
- Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
- Builder.CreateStructGEP(nullptr, addr, 2, "byref.flags"));
+ storeHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
+ getIntSize(), "byref.flags");
CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType);
V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity());
- Builder.CreateStore(V,
- Builder.CreateStructGEP(nullptr, addr, 3, "byref.size"));
+ storeHeaderField(V, getIntSize(), "byref.size");
if (helpers) {
- llvm::Value *copy_helper = Builder.CreateStructGEP(nullptr, addr, 4);
- Builder.CreateStore(helpers->CopyHelper, copy_helper);
-
- llvm::Value *destroy_helper = Builder.CreateStructGEP(nullptr, addr, 5);
- Builder.CreateStore(helpers->DisposeHelper, destroy_helper);
+ storeHeaderField(helpers->CopyHelper, getPointerSize(),
+ "byref.copyHelper");
+ storeHeaderField(helpers->DisposeHelper, getPointerSize(),
+ "byref.disposeHelper");
}
+
if (ByRefHasLifetime && HasByrefExtendedLayout) {
- llvm::Constant* ByrefLayoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type);
- llvm::Value *ByrefInfoAddr =
- Builder.CreateStructGEP(nullptr, addr, helpers ? 6 : 4, "byref.layout");
- // cast destination to pointer to source type.
- llvm::Type *DesTy = ByrefLayoutInfo->getType();
- DesTy = DesTy->getPointerTo();
- llvm::Value *BC = Builder.CreatePointerCast(ByrefInfoAddr, DesTy);
- Builder.CreateStore(ByrefLayoutInfo, BC);
+ auto layoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type);
+ storeHeaderField(layoutInfo, getPointerSize(), "byref.layout");
}
}
@@ -2240,7 +2257,8 @@ void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) {
}
namespace {
- struct CallBlockRelease : EHScopeStack::Cleanup {
+ /// Release a __block variable.
+ struct CallBlockRelease final : EHScopeStack::Cleanup {
llvm::Value *Addr;
CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {}
@@ -2249,7 +2267,7 @@ namespace {
CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF);
}
};
-}
+} // end anonymous namespace
/// Enter a cleanup to destroy a __block variable. Note that this
/// cleanup should be a no-op if the variable hasn't left the stack
@@ -2260,7 +2278,8 @@ void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) {
if (CGM.getLangOpts().getGC() == LangOptions::GCOnly)
return;
- EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address);
+ EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup,
+ emission.Addr.getPointer());
}
/// Adjust the declaration of something from the blocks API.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
index c4eed0d..1edabef 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
@@ -140,6 +140,15 @@ inline BlockFieldFlags operator|(BlockFieldFlag_t l, BlockFieldFlag_t r) {
return BlockFieldFlags(l) | BlockFieldFlags(r);
}
+/// Information about the layout of a __block variable.
+class BlockByrefInfo {
+public:
+ llvm::StructType *Type;
+ unsigned FieldIndex;
+ CharUnits ByrefAlignment;
+ CharUnits FieldOffset;
+};
+
/// CGBlockInfo - Information to generate a block literal.
class CGBlockInfo {
public:
@@ -152,14 +161,19 @@ public:
class Capture {
uintptr_t Data;
EHScopeStack::stable_iterator Cleanup;
+ CharUnits::QuantityType Offset;
public:
bool isIndex() const { return (Data & 1) != 0; }
bool isConstant() const { return !isIndex(); }
- unsigned getIndex() const { assert(isIndex()); return Data >> 1; }
- llvm::Value *getConstant() const {
- assert(isConstant());
- return reinterpret_cast<llvm::Value*>(Data);
+
+ unsigned getIndex() const {
+ assert(isIndex());
+ return Data >> 1;
+ }
+ CharUnits getOffset() const {
+ assert(isIndex());
+ return CharUnits::fromQuantity(Offset);
}
EHScopeStack::stable_iterator getCleanup() const {
assert(isIndex());
@@ -170,9 +184,15 @@ public:
Cleanup = cleanup;
}
- static Capture makeIndex(unsigned index) {
+ llvm::Value *getConstant() const {
+ assert(isConstant());
+ return reinterpret_cast<llvm::Value*>(Data);
+ }
+
+ static Capture makeIndex(unsigned index, CharUnits offset) {
Capture v;
v.Data = (index << 1) | 1;
+ v.Offset = offset.getQuantity();
return v;
}
@@ -205,12 +225,13 @@ public:
/// The mapping of allocated indexes within the block.
llvm::DenseMap<const VarDecl*, Capture> Captures;
- llvm::AllocaInst *Address;
+ Address LocalAddress;
llvm::StructType *StructureType;
const BlockDecl *Block;
const BlockExpr *BlockExpression;
CharUnits BlockSize;
CharUnits BlockAlign;
+ CharUnits CXXThisOffset;
// Offset of the gap caused by block header having a smaller
// alignment than the alignment of the block descriptor. This
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
index 6610659..489f341 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuilder.h
@@ -11,6 +11,8 @@
#define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
#include "llvm/IR/IRBuilder.h"
+#include "Address.h"
+#include "CodeGenTypeCache.h"
namespace clang {
namespace CodeGen {
@@ -22,9 +24,9 @@ class CodeGenFunction;
/// instructions.
template <bool PreserveNames>
class CGBuilderInserter
- : protected llvm::IRBuilderDefaultInserter<PreserveNames> {
+ : protected llvm::IRBuilderDefaultInserter<PreserveNames> {
public:
- CGBuilderInserter() : CGF(nullptr) {}
+ CGBuilderInserter() = default;
explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
protected:
@@ -33,9 +35,7 @@ protected:
llvm::BasicBlock *BB,
llvm::BasicBlock::iterator InsertPt) const;
private:
- void operator=(const CGBuilderInserter &) = delete;
-
- CodeGenFunction *CGF;
+ CodeGenFunction *CGF = nullptr;
};
// Don't preserve names on values in an optimized build.
@@ -44,9 +44,260 @@ private:
#else
#define PreserveNames true
#endif
+
typedef CGBuilderInserter<PreserveNames> CGBuilderInserterTy;
+
typedef llvm::IRBuilder<PreserveNames, llvm::ConstantFolder,
- CGBuilderInserterTy> CGBuilderTy;
+ CGBuilderInserterTy> CGBuilderBaseTy;
+
+class CGBuilderTy : public CGBuilderBaseTy {
+ /// Storing a reference to the type cache here makes it a lot easier
+ /// to build natural-feeling, target-specific IR.
+ const CodeGenTypeCache &TypeCache;
+public:
+ CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
+ : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
+ CGBuilderTy(const CodeGenTypeCache &TypeCache,
+ llvm::LLVMContext &C, const llvm::ConstantFolder &F,
+ const CGBuilderInserterTy &Inserter)
+ : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
+ CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
+ : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
+ CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
+ : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
+
+ llvm::ConstantInt *getSize(CharUnits N) {
+ return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
+ }
+ llvm::ConstantInt *getSize(uint64_t N) {
+ return llvm::ConstantInt::get(TypeCache.SizeTy, N);
+ }
+
+ // Note that we intentionally hide the CreateLoad APIs that don't
+ // take an alignment.
+ llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
+ return CreateAlignedLoad(Addr.getPointer(),
+ Addr.getAlignment().getQuantity(),
+ Name);
+ }
+ llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
+ // This overload is required to prevent string literals from
+ // ending up in the IsVolatile overload.
+ return CreateAlignedLoad(Addr.getPointer(),
+ Addr.getAlignment().getQuantity(),
+ Name);
+ }
+ llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
+ const llvm::Twine &Name = "") {
+ return CreateAlignedLoad(Addr.getPointer(),
+ Addr.getAlignment().getQuantity(),
+ IsVolatile,
+ Name);
+ }
+
+ using CGBuilderBaseTy::CreateAlignedLoad;
+ llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
+ const llvm::Twine &Name = "") {
+ return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
+ }
+ llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
+ const char *Name) {
+ return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
+ }
+ llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
+ CharUnits Align,
+ const llvm::Twine &Name = "") {
+ assert(Addr->getType()->getPointerElementType() == Ty);
+ return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
+ }
+ llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
+ bool IsVolatile,
+ const llvm::Twine &Name = "") {
+ return CreateAlignedLoad(Addr, Align.getQuantity(), IsVolatile, Name);
+ }
+
+ // Note that we intentionally hide the CreateStore APIs that don't
+ // take an alignment.
+ llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
+ bool IsVolatile = false) {
+ return CreateAlignedStore(Val, Addr.getPointer(),
+ Addr.getAlignment().getQuantity(), IsVolatile);
+ }
+
+ using CGBuilderBaseTy::CreateAlignedStore;
+ llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
+ CharUnits Align, bool IsVolatile = false) {
+ return CreateAlignedStore(Val, Addr, Align.getQuantity(), IsVolatile);
+ }
+
+ // FIXME: these "default-aligned" APIs should be removed,
+ // but I don't feel like fixing all the builtin code right now.
+ llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr,
+ const llvm::Twine &Name = "") {
+ return CGBuilderBaseTy::CreateLoad(Addr, false, Name);
+ }
+ llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr,
+ const char *Name) {
+ return CGBuilderBaseTy::CreateLoad(Addr, false, Name);
+ }
+ llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr, bool IsVolatile,
+ const llvm::Twine &Name = "") {
+ return CGBuilderBaseTy::CreateLoad(Addr, IsVolatile, Name);
+ }
+
+ llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
+ llvm::Value *Addr,
+ bool IsVolatile = false) {
+ return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
+ }
+
+ /// Emit a load from an i1 flag variable.
+ llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
+ const llvm::Twine &Name = "") {
+ assert(Addr->getType()->getPointerElementType() == getInt1Ty());
+ return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
+ }
+
+ /// Emit a store to an i1 flag variable.
+ llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
+ assert(Addr->getType()->getPointerElementType() == getInt1Ty());
+ return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
+ }
+
+ using CGBuilderBaseTy::CreateBitCast;
+ Address CreateBitCast(Address Addr, llvm::Type *Ty,
+ const llvm::Twine &Name = "") {
+ return Address(CreateBitCast(Addr.getPointer(), Ty, Name),
+ Addr.getAlignment());
+ }
+
+ /// Cast the element type of the given address to a different type,
+ /// preserving information like the alignment and address space.
+ Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
+ const llvm::Twine &Name = "") {
+ auto PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
+ return CreateBitCast(Addr, PtrTy, Name);
+ }
+
+ using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
+ Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
+ const llvm::Twine &Name = "") {
+ llvm::Value *Ptr =
+ CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
+ return Address(Ptr, Addr.getAlignment());
+ }
+
+ using CGBuilderBaseTy::CreateStructGEP;
+ Address CreateStructGEP(Address Addr, unsigned Index, CharUnits Offset,
+ const llvm::Twine &Name = "") {
+ return Address(CreateStructGEP(Addr.getElementType(),
+ Addr.getPointer(), Index, Name),
+ Addr.getAlignment().alignmentAtOffset(Offset));
+ }
+
+ /// Given
+ /// %addr = [n x T]* ...
+ /// produce
+ /// %name = getelementptr inbounds %addr, i64 0, i64 index
+ /// where i64 is actually the target word size.
+ ///
+ /// This API assumes that drilling into an array like this is always
+ /// an inbounds operation.
+ ///
+ /// \param EltSize - the size of the type T in bytes
+ Address CreateConstArrayGEP(Address Addr, uint64_t Index, CharUnits EltSize,
+ const llvm::Twine &Name = "") {
+ return Address(CreateInBoundsGEP(Addr.getPointer(),
+ {getSize(CharUnits::Zero()),
+ getSize(Index)},
+ Name),
+ Addr.getAlignment().alignmentAtOffset(Index * EltSize));
+ }
+
+ /// Given
+ /// %addr = T* ...
+ /// produce
+ /// %name = getelementptr inbounds %addr, i64 index
+ /// where i64 is actually the target word size.
+ ///
+ /// \param EltSize - the size of the type T in bytes
+ Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
+ CharUnits EltSize,
+ const llvm::Twine &Name = "") {
+ return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
+ getSize(Index), Name),
+ Addr.getAlignment().alignmentAtOffset(Index * EltSize));
+ }
+
+ /// Given
+ /// %addr = T* ...
+ /// produce
+ /// %name = getelementptr inbounds %addr, i64 index
+ /// where i64 is actually the target word size.
+ ///
+ /// \param EltSize - the size of the type T in bytes
+ Address CreateConstGEP(Address Addr, uint64_t Index, CharUnits EltSize,
+ const llvm::Twine &Name = "") {
+ return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
+ getSize(Index), Name),
+ Addr.getAlignment().alignmentAtOffset(Index * EltSize));
+ }
+
+ /// Given a pointer to i8, adjust it by a given constant offset.
+ Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
+ const llvm::Twine &Name = "") {
+ assert(Addr.getElementType() == TypeCache.Int8Ty);
+ return Address(CreateInBoundsGEP(Addr.getPointer(), getSize(Offset), Name),
+ Addr.getAlignment().alignmentAtOffset(Offset));
+ }
+ Address CreateConstByteGEP(Address Addr, CharUnits Offset,
+ const llvm::Twine &Name = "") {
+ assert(Addr.getElementType() == TypeCache.Int8Ty);
+ return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name),
+ Addr.getAlignment().alignmentAtOffset(Offset));
+ }
+
+ llvm::Value *CreateConstInBoundsByteGEP(llvm::Value *Ptr, CharUnits Offset,
+ const llvm::Twine &Name = "") {
+ assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty);
+ return CreateInBoundsGEP(Ptr, getSize(Offset), Name);
+ }
+ llvm::Value *CreateConstByteGEP(llvm::Value *Ptr, CharUnits Offset,
+ const llvm::Twine &Name = "") {
+ assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty);
+ return CreateGEP(Ptr, getSize(Offset), Name);
+ }
+
+ using CGBuilderBaseTy::CreateMemCpy;
+ llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
+ bool IsVolatile = false) {
+ auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
+ return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size,
+ Align.getQuantity(), IsVolatile);
+ }
+ llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
+ bool IsVolatile = false) {
+ auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
+ return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size,
+ Align.getQuantity(), IsVolatile);
+ }
+
+ using CGBuilderBaseTy::CreateMemMove;
+ llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
+ bool IsVolatile = false) {
+ auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
+ return CreateMemMove(Dest.getPointer(), Src.getPointer(), Size,
+ Align.getQuantity(), IsVolatile);
+ }
+
+ using CGBuilderBaseTy::CreateMemSet;
+ llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
+ llvm::Value *Size, bool IsVolatile = false) {
+ return CreateMemSet(Dest.getPointer(), Value, Size,
+ Dest.getAlignment().getQuantity(), IsVolatile);
+ }
+};
+
#undef PreserveNames
} // end namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
index 9b8694f..787ac53 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBuiltin.cpp
@@ -48,7 +48,7 @@ llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
if (FD->hasAttr<AsmLabelAttr>())
Name = getMangledName(D);
else
- Name = Context.BuiltinInfo.GetName(BuiltinID) + 10;
+ Name = Context.BuiltinInfo.getName(BuiltinID) + 10;
llvm::FunctionType *Ty =
cast<llvm::FunctionType>(getTypes().ConvertType(FD->getType()));
@@ -111,6 +111,28 @@ static Value *MakeBinaryAtomicValue(CodeGenFunction &CGF,
return EmitFromInt(CGF, Result, T, ValueType);
}
+static Value *EmitNontemporalStore(CodeGenFunction &CGF, const CallExpr *E) {
+ Value *Val = CGF.EmitScalarExpr(E->getArg(0));
+ Value *Address = CGF.EmitScalarExpr(E->getArg(1));
+
+ // Convert the type of the pointer to a pointer to the stored type.
+ Val = CGF.EmitToMemory(Val, E->getArg(0)->getType());
+ Value *BC = CGF.Builder.CreateBitCast(
+ Address, llvm::PointerType::getUnqual(Val->getType()), "cast");
+ LValue LV = CGF.MakeNaturalAlignAddrLValue(BC, E->getArg(0)->getType());
+ LV.setNontemporal(true);
+ CGF.EmitStoreOfScalar(Val, LV, false);
+ return nullptr;
+}
+
+static Value *EmitNontemporalLoad(CodeGenFunction &CGF, const CallExpr *E) {
+ Value *Address = CGF.EmitScalarExpr(E->getArg(0));
+
+ LValue LV = CGF.MakeNaturalAlignAddrLValue(Address, E->getType());
+ LV.setNontemporal(true);
+ return CGF.EmitLoadOfScalar(LV, E->getExprLoc());
+}
+
static RValue EmitBinaryAtomic(CodeGenFunction &CGF,
llvm::AtomicRMWInst::BinOp Kind,
const CallExpr *E) {
@@ -215,10 +237,20 @@ static Value *EmitSignBit(CodeGenFunction &CGF, Value *V) {
llvm::Type *IntTy = llvm::IntegerType::get(C, Width);
V = CGF.Builder.CreateBitCast(V, IntTy);
if (Ty->isPPC_FP128Ty()) {
- // The higher-order double comes first, and so we need to truncate the
- // pair to extract the overall sign. The order of the pair is the same
- // in both little- and big-Endian modes.
+ // We want the sign bit of the higher-order double. The bitcast we just
+ // did works as if the double-double was stored to memory and then
+ // read as an i128. The "store" will put the higher-order double in the
+ // lower address in both little- and big-Endian modes, but the "load"
+ // will treat those bits as a different part of the i128: the low bits in
+ // little-Endian, the high bits in big-Endian. Therefore, on big-Endian
+ // we need to shift the high bits down to the low before truncating.
Width >>= 1;
+ if (CGF.getTarget().isBigEndian()) {
+ Value *ShiftCst = llvm::ConstantInt::get(IntTy, Width);
+ V = CGF.Builder.CreateLShr(V, ShiftCst);
+ }
+ // We are truncating value in order to extract the higher-order
+ // double, which we will be using to extract the sign from.
IntTy = llvm::IntegerType::get(C, Width);
V = CGF.Builder.CreateTrunc(V, IntTy);
}
@@ -256,6 +288,125 @@ static llvm::Value *EmitOverflowIntrinsic(CodeGenFunction &CGF,
return CGF.Builder.CreateExtractValue(Tmp, 0);
}
+namespace {
+ struct WidthAndSignedness {
+ unsigned Width;
+ bool Signed;
+ };
+}
+
+static WidthAndSignedness
+getIntegerWidthAndSignedness(const clang::ASTContext &context,
+ const clang::QualType Type) {
+ assert(Type->isIntegerType() && "Given type is not an integer.");
+ unsigned Width = Type->isBooleanType() ? 1 : context.getTypeInfo(Type).Width;
+ bool Signed = Type->isSignedIntegerType();
+ return {Width, Signed};
+}
+
+// Given one or more integer types, this function produces an integer type that
+// encompasses them: any value in one of the given types could be expressed in
+// the encompassing type.
+static struct WidthAndSignedness
+EncompassingIntegerType(ArrayRef<struct WidthAndSignedness> Types) {
+ assert(Types.size() > 0 && "Empty list of types.");
+
+ // If any of the given types is signed, we must return a signed type.
+ bool Signed = false;
+ for (const auto &Type : Types) {
+ Signed |= Type.Signed;
+ }
+
+ // The encompassing type must have a width greater than or equal to the width
+ // of the specified types. Aditionally, if the encompassing type is signed,
+ // its width must be strictly greater than the width of any unsigned types
+ // given.
+ unsigned Width = 0;
+ for (const auto &Type : Types) {
+ unsigned MinWidth = Type.Width + (Signed && !Type.Signed);
+ if (Width < MinWidth) {
+ Width = MinWidth;
+ }
+ }
+
+ return {Width, Signed};
+}
+
+Value *CodeGenFunction::EmitVAStartEnd(Value *ArgValue, bool IsStart) {
+ llvm::Type *DestType = Int8PtrTy;
+ if (ArgValue->getType() != DestType)
+ ArgValue =
+ Builder.CreateBitCast(ArgValue, DestType, ArgValue->getName().data());
+
+ Intrinsic::ID inst = IsStart ? Intrinsic::vastart : Intrinsic::vaend;
+ return Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue);
+}
+
+/// Checks if using the result of __builtin_object_size(p, @p From) in place of
+/// __builtin_object_size(p, @p To) is correct
+static bool areBOSTypesCompatible(int From, int To) {
+ // Note: Our __builtin_object_size implementation currently treats Type=0 and
+ // Type=2 identically. Encoding this implementation detail here may make
+ // improving __builtin_object_size difficult in the future, so it's omitted.
+ return From == To || (From == 0 && To == 1) || (From == 3 && To == 2);
+}
+
+static llvm::Value *
+getDefaultBuiltinObjectSizeResult(unsigned Type, llvm::IntegerType *ResType) {
+ return ConstantInt::get(ResType, (Type & 2) ? 0 : -1, /*isSigned=*/true);
+}
+
+llvm::Value *
+CodeGenFunction::evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type,
+ llvm::IntegerType *ResType) {
+ uint64_t ObjectSize;
+ if (!E->tryEvaluateObjectSize(ObjectSize, getContext(), Type))
+ return emitBuiltinObjectSize(E, Type, ResType);
+ return ConstantInt::get(ResType, ObjectSize, /*isSigned=*/true);
+}
+
+/// Returns a Value corresponding to the size of the given expression.
+/// This Value may be either of the following:
+/// - A llvm::Argument (if E is a param with the pass_object_size attribute on
+/// it)
+/// - A call to the @llvm.objectsize intrinsic
+llvm::Value *
+CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type,
+ llvm::IntegerType *ResType) {
+ // We need to reference an argument if the pointer is a parameter with the
+ // pass_object_size attribute.
+ if (auto *D = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) {
+ auto *Param = dyn_cast<ParmVarDecl>(D->getDecl());
+ auto *PS = D->getDecl()->getAttr<PassObjectSizeAttr>();
+ if (Param != nullptr && PS != nullptr &&
+ areBOSTypesCompatible(PS->getType(), Type)) {
+ auto Iter = SizeArguments.find(Param);
+ assert(Iter != SizeArguments.end());
+
+ const ImplicitParamDecl *D = Iter->second;
+ auto DIter = LocalDeclMap.find(D);
+ assert(DIter != LocalDeclMap.end());
+
+ return EmitLoadOfScalar(DIter->second, /*volatile=*/false,
+ getContext().getSizeType(), E->getLocStart());
+ }
+ }
+
+ // LLVM can't handle Type=3 appropriately, and __builtin_object_size shouldn't
+ // evaluate E for side-effects. In either case, we shouldn't lower to
+ // @llvm.objectsize.
+ if (Type == 3 || E->HasSideEffects(getContext()))
+ return getDefaultBuiltinObjectSizeResult(Type, ResType);
+
+ // LLVM only supports 0 and 2, make sure that we pass along that
+ // as a boolean.
+ auto *CI = ConstantInt::get(Builder.getInt1Ty(), (Type & 2) >> 1);
+ // FIXME: Get right address space.
+ llvm::Type *Tys[] = {ResType, Builder.getInt8PtrTy(0)};
+ Value *F = CGM.getIntrinsic(Intrinsic::objectsize, Tys);
+ return Builder.CreateCall(F, {EmitScalarExpr(E), CI});
+}
+
RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue) {
@@ -279,22 +430,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin_stdarg_start:
case Builtin::BI__builtin_va_start:
case Builtin::BI__va_start:
- case Builtin::BI__builtin_va_end: {
- Value *ArgValue = (BuiltinID == Builtin::BI__va_start)
- ? EmitScalarExpr(E->getArg(0))
- : EmitVAListRef(E->getArg(0));
- llvm::Type *DestType = Int8PtrTy;
- if (ArgValue->getType() != DestType)
- ArgValue = Builder.CreateBitCast(ArgValue, DestType,
- ArgValue->getName().data());
-
- Intrinsic::ID inst = (BuiltinID == Builtin::BI__builtin_va_end) ?
- Intrinsic::vaend : Intrinsic::vastart;
- return RValue::get(Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue));
- }
+ case Builtin::BI__builtin_va_end:
+ return RValue::get(
+ EmitVAStartEnd(BuiltinID == Builtin::BI__va_start
+ ? EmitScalarExpr(E->getArg(0))
+ : EmitVAListRef(E->getArg(0)).getPointer(),
+ BuiltinID != Builtin::BI__builtin_va_end));
case Builtin::BI__builtin_va_copy: {
- Value *DstPtr = EmitVAListRef(E->getArg(0));
- Value *SrcPtr = EmitVAListRef(E->getArg(1));
+ Value *DstPtr = EmitVAListRef(E->getArg(0)).getPointer();
+ Value *SrcPtr = EmitVAListRef(E->getArg(1)).getPointer();
llvm::Type *Type = Int8PtrTy;
@@ -455,6 +599,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
"cast");
return RValue::get(Result);
}
+ case Builtin::BI__builtin_unpredictable: {
+ // Always return the argument of __builtin_unpredictable. LLVM does not
+ // handle this builtin. Metadata for this builtin should be added directly
+ // to instructions such as branches or switches that use it.
+ return RValue::get(EmitScalarExpr(E->getArg(0)));
+ }
case Builtin::BI__builtin_expect: {
Value *ArgValue = EmitScalarExpr(E->getArg(0));
llvm::Type *ArgType = ArgValue->getType();
@@ -501,26 +651,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateCall(F, ArgValue));
}
case Builtin::BI__builtin_object_size: {
- // We rely on constant folding to deal with expressions with side effects.
- assert(!E->getArg(0)->HasSideEffects(getContext()) &&
- "should have been constant folded");
-
- // We pass this builtin onto the optimizer so that it can
- // figure out the object size in more complex cases.
- llvm::Type *ResType = ConvertType(E->getType());
-
- // LLVM only supports 0 and 2, make sure that we pass along that
- // as a boolean.
- Value *Ty = EmitScalarExpr(E->getArg(1));
- ConstantInt *CI = dyn_cast<ConstantInt>(Ty);
- assert(CI);
- uint64_t val = CI->getZExtValue();
- CI = ConstantInt::get(Builder.getInt1Ty(), (val & 0x2) >> 1);
- // FIXME: Get right address space.
- llvm::Type *Tys[] = { ResType, Builder.getInt8PtrTy(0) };
- Value *F = CGM.getIntrinsic(Intrinsic::objectsize, Tys);
- return RValue::get(
- Builder.CreateCall(F, {EmitScalarExpr(E->getArg(0)), CI}));
+ unsigned Type =
+ E->getArg(1)->EvaluateKnownConstInt(getContext()).getZExtValue();
+ auto *ResType = cast<llvm::IntegerType>(ConvertType(E->getType()));
+
+ // We pass this builtin onto the optimizer so that it can figure out the
+ // object size in more complex cases.
+ return RValue::get(emitBuiltinObjectSize(E->getArg(0), Type, ResType));
}
case Builtin::BI__builtin_prefetch: {
Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0));
@@ -737,29 +874,24 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
}
case Builtin::BIbzero:
case Builtin::BI__builtin_bzero: {
- std::pair<llvm::Value*, unsigned> Dest =
- EmitPointerWithAlignment(E->getArg(0));
+ Address Dest = EmitPointerWithAlignment(E->getArg(0));
Value *SizeVal = EmitScalarExpr(E->getArg(1));
- EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(),
+ EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(),
E->getArg(0)->getExprLoc(), FD, 0);
- Builder.CreateMemSet(Dest.first, Builder.getInt8(0), SizeVal,
- Dest.second, false);
- return RValue::get(Dest.first);
+ Builder.CreateMemSet(Dest, Builder.getInt8(0), SizeVal, false);
+ return RValue::get(Dest.getPointer());
}
case Builtin::BImemcpy:
case Builtin::BI__builtin_memcpy: {
- std::pair<llvm::Value*, unsigned> Dest =
- EmitPointerWithAlignment(E->getArg(0));
- std::pair<llvm::Value*, unsigned> Src =
- EmitPointerWithAlignment(E->getArg(1));
+ Address Dest = EmitPointerWithAlignment(E->getArg(0));
+ Address Src = EmitPointerWithAlignment(E->getArg(1));
Value *SizeVal = EmitScalarExpr(E->getArg(2));
- unsigned Align = std::min(Dest.second, Src.second);
- EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(),
+ EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(),
E->getArg(0)->getExprLoc(), FD, 0);
- EmitNonNullArgCheck(RValue::get(Src.first), E->getArg(1)->getType(),
+ EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(1)->getType(),
E->getArg(1)->getExprLoc(), FD, 1);
- Builder.CreateMemCpy(Dest.first, Src.first, SizeVal, Align, false);
- return RValue::get(Dest.first);
+ Builder.CreateMemCpy(Dest, Src, SizeVal, false);
+ return RValue::get(Dest.getPointer());
}
case Builtin::BI__builtin___memcpy_chk: {
@@ -770,23 +902,20 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
break;
if (Size.ugt(DstSize))
break;
- std::pair<llvm::Value*, unsigned> Dest =
- EmitPointerWithAlignment(E->getArg(0));
- std::pair<llvm::Value*, unsigned> Src =
- EmitPointerWithAlignment(E->getArg(1));
+ Address Dest = EmitPointerWithAlignment(E->getArg(0));
+ Address Src = EmitPointerWithAlignment(E->getArg(1));
Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size);
- unsigned Align = std::min(Dest.second, Src.second);
- Builder.CreateMemCpy(Dest.first, Src.first, SizeVal, Align, false);
- return RValue::get(Dest.first);
+ Builder.CreateMemCpy(Dest, Src, SizeVal, false);
+ return RValue::get(Dest.getPointer());
}
case Builtin::BI__builtin_objc_memmove_collectable: {
- Value *Address = EmitScalarExpr(E->getArg(0));
- Value *SrcAddr = EmitScalarExpr(E->getArg(1));
+ Address DestAddr = EmitPointerWithAlignment(E->getArg(0));
+ Address SrcAddr = EmitPointerWithAlignment(E->getArg(1));
Value *SizeVal = EmitScalarExpr(E->getArg(2));
CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this,
- Address, SrcAddr, SizeVal);
- return RValue::get(Address);
+ DestAddr, SrcAddr, SizeVal);
+ return RValue::get(DestAddr.getPointer());
}
case Builtin::BI__builtin___memmove_chk: {
@@ -797,42 +926,35 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
break;
if (Size.ugt(DstSize))
break;
- std::pair<llvm::Value*, unsigned> Dest =
- EmitPointerWithAlignment(E->getArg(0));
- std::pair<llvm::Value*, unsigned> Src =
- EmitPointerWithAlignment(E->getArg(1));
+ Address Dest = EmitPointerWithAlignment(E->getArg(0));
+ Address Src = EmitPointerWithAlignment(E->getArg(1));
Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size);
- unsigned Align = std::min(Dest.second, Src.second);
- Builder.CreateMemMove(Dest.first, Src.first, SizeVal, Align, false);
- return RValue::get(Dest.first);
+ Builder.CreateMemMove(Dest, Src, SizeVal, false);
+ return RValue::get(Dest.getPointer());
}
case Builtin::BImemmove:
case Builtin::BI__builtin_memmove: {
- std::pair<llvm::Value*, unsigned> Dest =
- EmitPointerWithAlignment(E->getArg(0));
- std::pair<llvm::Value*, unsigned> Src =
- EmitPointerWithAlignment(E->getArg(1));
+ Address Dest = EmitPointerWithAlignment(E->getArg(0));
+ Address Src = EmitPointerWithAlignment(E->getArg(1));
Value *SizeVal = EmitScalarExpr(E->getArg(2));
- unsigned Align = std::min(Dest.second, Src.second);
- EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(),
+ EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(),
E->getArg(0)->getExprLoc(), FD, 0);
- EmitNonNullArgCheck(RValue::get(Src.first), E->getArg(1)->getType(),
+ EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(1)->getType(),
E->getArg(1)->getExprLoc(), FD, 1);
- Builder.CreateMemMove(Dest.first, Src.first, SizeVal, Align, false);
- return RValue::get(Dest.first);
+ Builder.CreateMemMove(Dest, Src, SizeVal, false);
+ return RValue::get(Dest.getPointer());
}
case Builtin::BImemset:
case Builtin::BI__builtin_memset: {
- std::pair<llvm::Value*, unsigned> Dest =
- EmitPointerWithAlignment(E->getArg(0));
+ Address Dest = EmitPointerWithAlignment(E->getArg(0));
Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)),
Builder.getInt8Ty());
Value *SizeVal = EmitScalarExpr(E->getArg(2));
- EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(),
+ EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(),
E->getArg(0)->getExprLoc(), FD, 0);
- Builder.CreateMemSet(Dest.first, ByteVal, SizeVal, Dest.second, false);
- return RValue::get(Dest.first);
+ Builder.CreateMemSet(Dest, ByteVal, SizeVal, false);
+ return RValue::get(Dest.getPointer());
}
case Builtin::BI__builtin___memset_chk: {
// fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2.
@@ -842,13 +964,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
break;
if (Size.ugt(DstSize))
break;
- std::pair<llvm::Value*, unsigned> Dest =
- EmitPointerWithAlignment(E->getArg(0));
+ Address Dest = EmitPointerWithAlignment(E->getArg(0));
Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)),
Builder.getInt8Ty());
Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size);
- Builder.CreateMemSet(Dest.first, ByteVal, SizeVal, Dest.second, false);
- return RValue::get(Dest.first);
+ Builder.CreateMemSet(Dest, ByteVal, SizeVal, false);
+ return RValue::get(Dest.getPointer());
}
case Builtin::BI__builtin_dwarf_cfa: {
// The offset in bytes from the first argument to the CFA.
@@ -952,7 +1073,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
}
case Builtin::BI__builtin_setjmp: {
// Buffer is a void**.
- Value *Buf = EmitScalarExpr(E->getArg(0));
+ Address Buf = EmitPointerWithAlignment(E->getArg(0));
// Store the frame pointer to the setjmp buffer.
Value *FrameAddr =
@@ -963,14 +1084,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Store the stack pointer to the setjmp buffer.
Value *StackAddr =
Builder.CreateCall(CGM.getIntrinsic(Intrinsic::stacksave));
- Value *StackSaveSlot =
- Builder.CreateGEP(Buf, ConstantInt::get(Int32Ty, 2));
+ Address StackSaveSlot =
+ Builder.CreateConstInBoundsGEP(Buf, 2, getPointerSize());
Builder.CreateStore(StackAddr, StackSaveSlot);
// Call LLVM's EH setjmp, which is lightweight.
Value *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp);
Buf = Builder.CreateBitCast(Buf, Int8PtrTy);
- return RValue::get(Builder.CreateCall(F, Buf));
+ return RValue::get(Builder.CreateCall(F, Buf.getPointer()));
}
case Builtin::BI__builtin_longjmp: {
Value *Buf = EmitScalarExpr(E->getArg(0));
@@ -1135,8 +1256,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
StoreSize.getQuantity() * 8);
Ptr = Builder.CreateBitCast(Ptr, ITy->getPointerTo());
llvm::StoreInst *Store =
- Builder.CreateStore(llvm::Constant::getNullValue(ITy), Ptr);
- Store->setAlignment(StoreSize.getQuantity());
+ Builder.CreateAlignedStore(llvm::Constant::getNullValue(ITy), Ptr,
+ StoreSize);
Store->setAtomic(llvm::Release);
return RValue::get(nullptr);
}
@@ -1153,6 +1274,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(nullptr);
}
+ case Builtin::BI__builtin_nontemporal_load:
+ return RValue::get(EmitNontemporalLoad(*this, E));
+ case Builtin::BI__builtin_nontemporal_store:
+ return RValue::get(EmitNontemporalStore(*this, E));
case Builtin::BI__c11_atomic_is_lock_free:
case Builtin::BI__atomic_is_lock_free: {
// Call "bool __atomic_is_lock_free(size_t size, void *ptr)". For the
@@ -1270,15 +1395,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
bool Volatile =
PtrTy->castAs<PointerType>()->getPointeeType().isVolatileQualified();
- Value *Ptr = EmitScalarExpr(E->getArg(0));
- unsigned AddrSpace = Ptr->getType()->getPointerAddressSpace();
+ Address Ptr = EmitPointerWithAlignment(E->getArg(0));
+ unsigned AddrSpace = Ptr.getPointer()->getType()->getPointerAddressSpace();
Ptr = Builder.CreateBitCast(Ptr, Int8Ty->getPointerTo(AddrSpace));
Value *NewVal = Builder.getInt8(0);
Value *Order = EmitScalarExpr(E->getArg(1));
if (isa<llvm::ConstantInt>(Order)) {
int ord = cast<llvm::ConstantInt>(Order)->getZExtValue();
StoreInst *Store = Builder.CreateStore(NewVal, Ptr, Volatile);
- Store->setAlignment(1);
switch (ord) {
case 0: // memory_order_relaxed
default: // invalid order
@@ -1311,7 +1435,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
for (unsigned i = 0; i < 3; ++i) {
Builder.SetInsertPoint(BBs[i]);
StoreInst *Store = Builder.CreateStore(NewVal, Ptr, Volatile);
- Store->setAlignment(1);
Store->setOrdering(Orders[i]);
Builder.CreateBr(ContBB);
}
@@ -1493,8 +1616,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Value *X = EmitScalarExpr(E->getArg(0));
llvm::Value *Y = EmitScalarExpr(E->getArg(1));
llvm::Value *Carryin = EmitScalarExpr(E->getArg(2));
- std::pair<llvm::Value*, unsigned> CarryOutPtr =
- EmitPointerWithAlignment(E->getArg(3));
+ Address CarryOutPtr = EmitPointerWithAlignment(E->getArg(3));
// Decide if we are lowering to a uadd.with.overflow or usub.with.overflow.
llvm::Intrinsic::ID IntrinsicId;
@@ -1525,11 +1647,91 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Sum1, Carryin, Carry2);
llvm::Value *CarryOut = Builder.CreateZExt(Builder.CreateOr(Carry1, Carry2),
X->getType());
- llvm::StoreInst *CarryOutStore = Builder.CreateStore(CarryOut,
- CarryOutPtr.first);
- CarryOutStore->setAlignment(CarryOutPtr.second);
+ Builder.CreateStore(CarryOut, CarryOutPtr);
return RValue::get(Sum2);
}
+
+ case Builtin::BI__builtin_add_overflow:
+ case Builtin::BI__builtin_sub_overflow:
+ case Builtin::BI__builtin_mul_overflow: {
+ const clang::Expr *LeftArg = E->getArg(0);
+ const clang::Expr *RightArg = E->getArg(1);
+ const clang::Expr *ResultArg = E->getArg(2);
+
+ clang::QualType ResultQTy =
+ ResultArg->getType()->castAs<PointerType>()->getPointeeType();
+
+ WidthAndSignedness LeftInfo =
+ getIntegerWidthAndSignedness(CGM.getContext(), LeftArg->getType());
+ WidthAndSignedness RightInfo =
+ getIntegerWidthAndSignedness(CGM.getContext(), RightArg->getType());
+ WidthAndSignedness ResultInfo =
+ getIntegerWidthAndSignedness(CGM.getContext(), ResultQTy);
+ WidthAndSignedness EncompassingInfo =
+ EncompassingIntegerType({LeftInfo, RightInfo, ResultInfo});
+
+ llvm::Type *EncompassingLLVMTy =
+ llvm::IntegerType::get(CGM.getLLVMContext(), EncompassingInfo.Width);
+
+ llvm::Type *ResultLLVMTy = CGM.getTypes().ConvertType(ResultQTy);
+
+ llvm::Intrinsic::ID IntrinsicId;
+ switch (BuiltinID) {
+ default:
+ llvm_unreachable("Unknown overflow builtin id.");
+ case Builtin::BI__builtin_add_overflow:
+ IntrinsicId = EncompassingInfo.Signed
+ ? llvm::Intrinsic::sadd_with_overflow
+ : llvm::Intrinsic::uadd_with_overflow;
+ break;
+ case Builtin::BI__builtin_sub_overflow:
+ IntrinsicId = EncompassingInfo.Signed
+ ? llvm::Intrinsic::ssub_with_overflow
+ : llvm::Intrinsic::usub_with_overflow;
+ break;
+ case Builtin::BI__builtin_mul_overflow:
+ IntrinsicId = EncompassingInfo.Signed
+ ? llvm::Intrinsic::smul_with_overflow
+ : llvm::Intrinsic::umul_with_overflow;
+ break;
+ }
+
+ llvm::Value *Left = EmitScalarExpr(LeftArg);
+ llvm::Value *Right = EmitScalarExpr(RightArg);
+ Address ResultPtr = EmitPointerWithAlignment(ResultArg);
+
+ // Extend each operand to the encompassing type.
+ Left = Builder.CreateIntCast(Left, EncompassingLLVMTy, LeftInfo.Signed);
+ Right = Builder.CreateIntCast(Right, EncompassingLLVMTy, RightInfo.Signed);
+
+ // Perform the operation on the extended values.
+ llvm::Value *Overflow, *Result;
+ Result = EmitOverflowIntrinsic(*this, IntrinsicId, Left, Right, Overflow);
+
+ if (EncompassingInfo.Width > ResultInfo.Width) {
+ // The encompassing type is wider than the result type, so we need to
+ // truncate it.
+ llvm::Value *ResultTrunc = Builder.CreateTrunc(Result, ResultLLVMTy);
+
+ // To see if the truncation caused an overflow, we will extend
+ // the result and then compare it to the original result.
+ llvm::Value *ResultTruncExt = Builder.CreateIntCast(
+ ResultTrunc, EncompassingLLVMTy, ResultInfo.Signed);
+ llvm::Value *TruncationOverflow =
+ Builder.CreateICmpNE(Result, ResultTruncExt);
+
+ Overflow = Builder.CreateOr(Overflow, TruncationOverflow);
+ Result = ResultTrunc;
+ }
+
+ // Finally, store the result using the pointer.
+ bool isVolatile =
+ ResultArg->getType()->getPointeeType().isVolatileQualified();
+ Builder.CreateStore(EmitToMemory(Result, ResultQTy), ResultPtr, isVolatile);
+
+ return RValue::get(Overflow);
+ }
+
case Builtin::BI__builtin_uadd_overflow:
case Builtin::BI__builtin_uaddl_overflow:
case Builtin::BI__builtin_uaddll_overflow:
@@ -1554,13 +1756,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Scalarize our inputs.
llvm::Value *X = EmitScalarExpr(E->getArg(0));
llvm::Value *Y = EmitScalarExpr(E->getArg(1));
- std::pair<llvm::Value *, unsigned> SumOutPtr =
- EmitPointerWithAlignment(E->getArg(2));
+ Address SumOutPtr = EmitPointerWithAlignment(E->getArg(2));
// Decide which of the overflow intrinsics we are lowering to:
llvm::Intrinsic::ID IntrinsicId;
switch (BuiltinID) {
- default: llvm_unreachable("Unknown security overflow builtin id.");
+ default: llvm_unreachable("Unknown overflow builtin id.");
case Builtin::BI__builtin_uadd_overflow:
case Builtin::BI__builtin_uaddl_overflow:
case Builtin::BI__builtin_uaddll_overflow:
@@ -1596,13 +1797,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Value *Carry;
llvm::Value *Sum = EmitOverflowIntrinsic(*this, IntrinsicId, X, Y, Carry);
- llvm::StoreInst *SumOutStore = Builder.CreateStore(Sum, SumOutPtr.first);
- SumOutStore->setAlignment(SumOutPtr.second);
+ Builder.CreateStore(Sum, SumOutPtr);
return RValue::get(Carry);
}
case Builtin::BI__builtin_addressof:
- return RValue::get(EmitLValue(E->getArg(0)).getAddress());
+ return RValue::get(EmitLValue(E->getArg(0)).getPointer());
case Builtin::BI__builtin_operator_new:
return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProtoType>(),
E->getArg(0), false);
@@ -1777,8 +1977,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return emitLibraryCall(*this, FD, E, EmitScalarExpr(E->getCallee()));
+ // Check that a call to a target specific builtin has the correct target
+ // features.
+ // This is down here to avoid non-target specific builtins, however, if
+ // generic builtins start to require generic target features then we
+ // can move this up to the beginning of the function.
+ checkTargetFeatures(E, FD);
+
// See if we have a target specific intrinsic.
- const char *Name = getContext().BuiltinInfo.GetName(BuiltinID);
+ const char *Name = getContext().BuiltinInfo.getName(BuiltinID);
Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;
if (const char *Prefix =
llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch())) {
@@ -1856,37 +2063,54 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return GetUndefRValue(E->getType());
}
-Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
- const CallExpr *E) {
- switch (getTarget().getTriple().getArch()) {
+static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF,
+ unsigned BuiltinID, const CallExpr *E,
+ llvm::Triple::ArchType Arch) {
+ switch (Arch) {
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
- return EmitARMBuiltinExpr(BuiltinID, E);
+ return CGF->EmitARMBuiltinExpr(BuiltinID, E);
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
- return EmitAArch64BuiltinExpr(BuiltinID, E);
+ return CGF->EmitAArch64BuiltinExpr(BuiltinID, E);
case llvm::Triple::x86:
case llvm::Triple::x86_64:
- return EmitX86BuiltinExpr(BuiltinID, E);
+ return CGF->EmitX86BuiltinExpr(BuiltinID, E);
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
- return EmitPPCBuiltinExpr(BuiltinID, E);
+ return CGF->EmitPPCBuiltinExpr(BuiltinID, E);
case llvm::Triple::r600:
case llvm::Triple::amdgcn:
- return EmitAMDGPUBuiltinExpr(BuiltinID, E);
+ return CGF->EmitAMDGPUBuiltinExpr(BuiltinID, E);
case llvm::Triple::systemz:
- return EmitSystemZBuiltinExpr(BuiltinID, E);
+ return CGF->EmitSystemZBuiltinExpr(BuiltinID, E);
case llvm::Triple::nvptx:
case llvm::Triple::nvptx64:
- return EmitNVPTXBuiltinExpr(BuiltinID, E);
+ return CGF->EmitNVPTXBuiltinExpr(BuiltinID, E);
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ return CGF->EmitWebAssemblyBuiltinExpr(BuiltinID, E);
default:
return nullptr;
}
}
+Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ if (getContext().BuiltinInfo.isAuxBuiltinID(BuiltinID)) {
+ assert(getContext().getAuxTargetInfo() && "Missing aux target info");
+ return EmitTargetArchBuiltinExpr(
+ this, getContext().BuiltinInfo.getAuxBuiltinID(BuiltinID), E,
+ getContext().getAuxTargetInfo()->getTriple().getArch());
+ }
+
+ return EmitTargetArchBuiltinExpr(this, BuiltinID, E,
+ getTarget().getTriple().getArch());
+}
+
static llvm::VectorType *GetNeonType(CodeGenFunction *CGF,
NeonTypeFlags TypeFlags,
bool V1Ty=false) {
@@ -1917,6 +2141,19 @@ static llvm::VectorType *GetNeonType(CodeGenFunction *CGF,
llvm_unreachable("Unknown vector element type!");
}
+static llvm::VectorType *GetFloatNeonType(CodeGenFunction *CGF,
+ NeonTypeFlags IntTypeFlags) {
+ int IsQuad = IntTypeFlags.isQuad();
+ switch (IntTypeFlags.getEltType()) {
+ case NeonTypeFlags::Int32:
+ return llvm::VectorType::get(CGF->FloatTy, (2 << IsQuad));
+ case NeonTypeFlags::Int64:
+ return llvm::VectorType::get(CGF->DoubleTy, (1 << IsQuad));
+ default:
+ llvm_unreachable("Type can't be converted to floating-point!");
+ }
+}
+
Value *CodeGenFunction::EmitNeonSplat(Value *V, Constant *C) {
unsigned nElts = cast<llvm::VectorType>(V->getType())->getNumElements();
Value* SV = llvm::ConstantVector::getSplat(nElts, C);
@@ -1940,10 +2177,7 @@ Value *CodeGenFunction::EmitNeonCall(Function *F, SmallVectorImpl<Value*> &Ops,
Value *CodeGenFunction::EmitNeonShiftVector(Value *V, llvm::Type *Ty,
bool neg) {
int SV = cast<ConstantInt>(V)->getSExtValue();
-
- llvm::VectorType *VTy = cast<llvm::VectorType>(Ty);
- llvm::Constant *C = ConstantInt::get(VTy->getElementType(), neg ? -SV : SV);
- return llvm::ConstantVector::getSplat(VTy->getNumElements(), C);
+ return ConstantInt::get(Ty, neg ? -SV : SV);
}
// \brief Right-shift a vector by a constant.
@@ -1962,8 +2196,7 @@ Value *CodeGenFunction::EmitNeonRShiftImm(Value *Vec, Value *Shift,
if (ShiftAmt == EltSize) {
if (usgn) {
// Right-shifting an unsigned value by its size yields 0.
- llvm::Constant *Zero = ConstantInt::get(VTy->getElementType(), 0);
- return llvm::ConstantVector::getSplat(VTy->getNumElements(), Zero);
+ return llvm::ConstantAggregateZero::get(VTy);
} else {
// Right-shifting a signed value by its size is equivalent
// to a shift of size-1.
@@ -1979,61 +2212,6 @@ Value *CodeGenFunction::EmitNeonRShiftImm(Value *Vec, Value *Shift,
return Builder.CreateAShr(Vec, Shift, name);
}
-/// GetPointeeAlignment - Given an expression with a pointer type, find the
-/// alignment of the type referenced by the pointer. Skip over implicit
-/// casts.
-std::pair<llvm::Value*, unsigned>
-CodeGenFunction::EmitPointerWithAlignment(const Expr *Addr) {
- assert(Addr->getType()->isPointerType());
- Addr = Addr->IgnoreParens();
- if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Addr)) {
- if ((ICE->getCastKind() == CK_BitCast || ICE->getCastKind() == CK_NoOp) &&
- ICE->getSubExpr()->getType()->isPointerType()) {
- std::pair<llvm::Value*, unsigned> Ptr =
- EmitPointerWithAlignment(ICE->getSubExpr());
- Ptr.first = Builder.CreateBitCast(Ptr.first,
- ConvertType(Addr->getType()));
- return Ptr;
- } else if (ICE->getCastKind() == CK_ArrayToPointerDecay) {
- LValue LV = EmitLValue(ICE->getSubExpr());
- unsigned Align = LV.getAlignment().getQuantity();
- if (!Align) {
- // FIXME: Once LValues are fixed to always set alignment,
- // zap this code.
- QualType PtTy = ICE->getSubExpr()->getType();
- if (!PtTy->isIncompleteType())
- Align = getContext().getTypeAlignInChars(PtTy).getQuantity();
- else
- Align = 1;
- }
- return std::make_pair(LV.getAddress(), Align);
- }
- }
- if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Addr)) {
- if (UO->getOpcode() == UO_AddrOf) {
- LValue LV = EmitLValue(UO->getSubExpr());
- unsigned Align = LV.getAlignment().getQuantity();
- if (!Align) {
- // FIXME: Once LValues are fixed to always set alignment,
- // zap this code.
- QualType PtTy = UO->getSubExpr()->getType();
- if (!PtTy->isIncompleteType())
- Align = getContext().getTypeAlignInChars(PtTy).getQuantity();
- else
- Align = 1;
- }
- return std::make_pair(LV.getAddress(), Align);
- }
- }
-
- unsigned Align = 1;
- QualType PtTy = Addr->getType()->getPointeeType();
- if (!PtTy->isIncompleteType())
- Align = getContext().getTypeAlignInChars(PtTy).getQuantity();
-
- return std::make_pair(EmitScalarExpr(Addr), Align);
-}
-
enum {
AddRetType = (1 << 0),
Add1ArgType = (1 << 1),
@@ -2056,31 +2234,36 @@ enum {
AddRetType | VectorizeRetType | Add1ArgType | InventFloatType
};
- struct NeonIntrinsicInfo {
+namespace {
+struct NeonIntrinsicInfo {
+ const char *NameHint;
unsigned BuiltinID;
unsigned LLVMIntrinsic;
unsigned AltLLVMIntrinsic;
- const char *NameHint;
unsigned TypeModifier;
bool operator<(unsigned RHSBuiltinID) const {
return BuiltinID < RHSBuiltinID;
}
+ bool operator<(const NeonIntrinsicInfo &TE) const {
+ return BuiltinID < TE.BuiltinID;
+ }
};
+} // end anonymous namespace
#define NEONMAP0(NameBase) \
- { NEON::BI__builtin_neon_ ## NameBase, 0, 0, #NameBase, 0 }
+ { #NameBase, NEON::BI__builtin_neon_ ## NameBase, 0, 0, 0 }
#define NEONMAP1(NameBase, LLVMIntrinsic, TypeModifier) \
- { NEON:: BI__builtin_neon_ ## NameBase, \
- Intrinsic::LLVMIntrinsic, 0, #NameBase, TypeModifier }
+ { #NameBase, NEON:: BI__builtin_neon_ ## NameBase, \
+ Intrinsic::LLVMIntrinsic, 0, TypeModifier }
#define NEONMAP2(NameBase, LLVMIntrinsic, AltLLVMIntrinsic, TypeModifier) \
- { NEON:: BI__builtin_neon_ ## NameBase, \
+ { #NameBase, NEON:: BI__builtin_neon_ ## NameBase, \
Intrinsic::LLVMIntrinsic, Intrinsic::AltLLVMIntrinsic, \
- #NameBase, TypeModifier }
+ TypeModifier }
-static NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
+static const NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP2(vabd_v, arm_neon_vabdu, arm_neon_vabds, Add1ArgType | UnsignedAlts),
NEONMAP2(vabdq_v, arm_neon_vabdu, arm_neon_vabds, Add1ArgType | UnsignedAlts),
NEONMAP1(vabs_v, arm_neon_vabs, 0),
@@ -2106,7 +2289,7 @@ static NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP1(vclzq_v, ctlz, Add1ArgType),
NEONMAP1(vcnt_v, ctpop, Add1ArgType),
NEONMAP1(vcntq_v, ctpop, Add1ArgType),
- NEONMAP1(vcvt_f16_v, arm_neon_vcvtfp2hf, 0),
+ NEONMAP1(vcvt_f16_f32, arm_neon_vcvtfp2hf, 0),
NEONMAP1(vcvt_f32_f16, arm_neon_vcvthf2fp, 0),
NEONMAP0(vcvt_f32_v),
NEONMAP2(vcvt_n_f32_v, arm_neon_vcvtfxu2fp, arm_neon_vcvtfxs2fp, 0),
@@ -2297,7 +2480,7 @@ static NeonIntrinsicInfo ARMSIMDIntrinsicMap [] = {
NEONMAP0(vzipq_v)
};
-static NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
+static const NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
NEONMAP1(vabs_v, aarch64_neon_abs, 0),
NEONMAP1(vabsq_v, aarch64_neon_abs, 0),
NEONMAP0(vaddhn_v),
@@ -2319,7 +2502,7 @@ static NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
NEONMAP1(vclzq_v, ctlz, Add1ArgType),
NEONMAP1(vcnt_v, ctpop, Add1ArgType),
NEONMAP1(vcntq_v, ctpop, Add1ArgType),
- NEONMAP1(vcvt_f16_v, aarch64_neon_vcvtfp2hf, 0),
+ NEONMAP1(vcvt_f16_f32, aarch64_neon_vcvtfp2hf, 0),
NEONMAP1(vcvt_f32_f16, aarch64_neon_vcvthf2fp, 0),
NEONMAP0(vcvt_f32_v),
NEONMAP2(vcvt_n_f32_v, aarch64_neon_vcvtfxu2fp, aarch64_neon_vcvtfxs2fp, 0),
@@ -2412,7 +2595,7 @@ static NeonIntrinsicInfo AArch64SIMDIntrinsicMap[] = {
NEONMAP0(vtstq_v),
};
-static NeonIntrinsicInfo AArch64SISDIntrinsicMap[] = {
+static const NeonIntrinsicInfo AArch64SISDIntrinsicMap[] = {
NEONMAP1(vabdd_f64, aarch64_sisd_fabd, Add1ArgType),
NEONMAP1(vabds_f32, aarch64_sisd_fabd, Add1ArgType),
NEONMAP1(vabsd_s64, aarch64_neon_abs, Add1ArgType),
@@ -2623,9 +2806,7 @@ findNeonIntrinsicInMap(ArrayRef<NeonIntrinsicInfo> IntrinsicMap,
#ifndef NDEBUG
if (!MapProvenSorted) {
- // FIXME: use std::is_sorted once C++11 is allowed
- for (unsigned i = 0; i < IntrinsicMap.size() - 1; ++i)
- assert(IntrinsicMap[i].BuiltinID <= IntrinsicMap[i + 1].BuiltinID);
+ assert(std::is_sorted(std::begin(IntrinsicMap), std::end(IntrinsicMap)));
MapProvenSorted = true;
}
#endif
@@ -2744,7 +2925,7 @@ static Value *EmitCommonNeonSISDBuiltinExpr(CodeGenFunction &CGF,
Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
unsigned BuiltinID, unsigned LLVMIntrinsic, unsigned AltLLVMIntrinsic,
const char *NameHint, unsigned Modifier, const CallExpr *E,
- SmallVectorImpl<llvm::Value *> &Ops, llvm::Value *Align) {
+ SmallVectorImpl<llvm::Value *> &Ops, Address PtrOp0, Address PtrOp1) {
// Get the last argument, which specifies the vector type.
llvm::APSInt NeonTypeConst;
const Expr *Arg = E->getArg(E->getNumArgs() - 1);
@@ -2761,6 +2942,10 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
if (!Ty)
return nullptr;
+ auto getAlignmentValue32 = [&](Address addr) -> Value* {
+ return Builder.getInt32(addr.getAlignment().getQuantity());
+ };
+
unsigned Int = LLVMIntrinsic;
if ((Modifier & UnsignedAlts) && !Usgn)
Int = AltLLVMIntrinsic;
@@ -2782,9 +2967,8 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Ops[0] = Builder.CreateAdd(Ops[0], Ops[1], "vaddhn");
// %high = lshr <4 x i32> %sum, <i32 16, i32 16, i32 16, i32 16>
- Constant *ShiftAmt = ConstantInt::get(SrcTy->getElementType(),
- SrcTy->getScalarSizeInBits() / 2);
- ShiftAmt = ConstantVector::getSplat(VTy->getNumElements(), ShiftAmt);
+ Constant *ShiftAmt =
+ ConstantInt::get(SrcTy, SrcTy->getScalarSizeInBits() / 2);
Ops[0] = Builder.CreateLShr(Ops[0], ShiftAmt, "vaddhn");
// %res = trunc <4 x i32> %high to <4 x i16>
@@ -2822,13 +3006,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcvt_n_f64_v:
case NEON::BI__builtin_neon_vcvtq_n_f32_v:
case NEON::BI__builtin_neon_vcvtq_n_f64_v: {
- bool Double =
- (cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
- llvm::Type *FloatTy =
- GetNeonType(this, NeonTypeFlags(Double ? NeonTypeFlags::Float64
- : NeonTypeFlags::Float32,
- false, Quad));
- llvm::Type *Tys[2] = { FloatTy, Ty };
+ llvm::Type *Tys[2] = { GetFloatNeonType(this, Type), Ty };
Int = Usgn ? LLVMIntrinsic : AltLLVMIntrinsic;
Function *F = CGM.getIntrinsic(Int, Tys);
return EmitNeonCall(F, Ops, "vcvt_n");
@@ -2841,13 +3019,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcvtq_n_u32_v:
case NEON::BI__builtin_neon_vcvtq_n_s64_v:
case NEON::BI__builtin_neon_vcvtq_n_u64_v: {
- bool Double =
- (cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
- llvm::Type *FloatTy =
- GetNeonType(this, NeonTypeFlags(Double ? NeonTypeFlags::Float64
- : NeonTypeFlags::Float32,
- false, Quad));
- llvm::Type *Tys[2] = { Ty, FloatTy };
+ llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
return EmitNeonCall(F, Ops, "vcvt_n");
}
@@ -2859,13 +3031,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcvtq_u32_v:
case NEON::BI__builtin_neon_vcvtq_s64_v:
case NEON::BI__builtin_neon_vcvtq_u64_v: {
- bool Double =
- (cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
- llvm::Type *FloatTy =
- GetNeonType(this, NeonTypeFlags(Double ? NeonTypeFlags::Float64
- : NeonTypeFlags::Float32,
- false, Quad));
- Ops[0] = Builder.CreateBitCast(Ops[0], FloatTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], GetFloatNeonType(this, Type));
return Usgn ? Builder.CreateFPToUI(Ops[0], Ty, "vcvt")
: Builder.CreateFPToSI(Ops[0], Ty, "vcvt");
}
@@ -2901,13 +3067,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vcvtmq_s64_v:
case NEON::BI__builtin_neon_vcvtmq_u32_v:
case NEON::BI__builtin_neon_vcvtmq_u64_v: {
- bool Double =
- (cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
- llvm::Type *InTy =
- GetNeonType(this,
- NeonTypeFlags(Double ? NeonTypeFlags::Float64
- : NeonTypeFlags::Float32, false, Quad));
- llvm::Type *Tys[2] = { Ty, InTy };
+ llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, NameHint);
}
case NEON::BI__builtin_neon_vext_v:
@@ -2933,28 +3093,31 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
return Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0]});
}
case NEON::BI__builtin_neon_vld1_v:
- case NEON::BI__builtin_neon_vld1q_v:
- Ops.push_back(Align);
- return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Ty), Ops, "vld1");
+ case NEON::BI__builtin_neon_vld1q_v: {
+ llvm::Type *Tys[] = {Ty, Int8PtrTy};
+ Ops.push_back(getAlignmentValue32(PtrOp0));
+ return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Tys), Ops, "vld1");
+ }
case NEON::BI__builtin_neon_vld2_v:
case NEON::BI__builtin_neon_vld2q_v:
case NEON::BI__builtin_neon_vld3_v:
case NEON::BI__builtin_neon_vld3q_v:
case NEON::BI__builtin_neon_vld4_v:
case NEON::BI__builtin_neon_vld4q_v: {
- Function *F = CGM.getIntrinsic(LLVMIntrinsic, Ty);
+ llvm::Type *Tys[] = {Ty, Int8PtrTy};
+ Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
+ Value *Align = getAlignmentValue32(PtrOp1);
Ops[1] = Builder.CreateCall(F, {Ops[1], Align}, NameHint);
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vld1_dup_v:
case NEON::BI__builtin_neon_vld1q_dup_v: {
Value *V = UndefValue::get(Ty);
Ty = llvm::PointerType::getUnqual(VTy->getElementType());
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- LoadInst *Ld = Builder.CreateLoad(Ops[0]);
- Ld->setAlignment(cast<ConstantInt>(Align)->getZExtValue());
+ PtrOp0 = Builder.CreateBitCast(PtrOp0, Ty);
+ LoadInst *Ld = Builder.CreateLoad(PtrOp0);
llvm::Constant *CI = ConstantInt::get(SizeTy, 0);
Ops[0] = Builder.CreateInsertElement(V, Ld, CI);
return EmitNeonSplat(Ops[0], CI);
@@ -2965,14 +3128,15 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vld3q_lane_v:
case NEON::BI__builtin_neon_vld4_lane_v:
case NEON::BI__builtin_neon_vld4q_lane_v: {
- Function *F = CGM.getIntrinsic(LLVMIntrinsic, Ty);
+ llvm::Type *Tys[] = {Ty, Int8PtrTy};
+ Function *F = CGM.getIntrinsic(LLVMIntrinsic, Tys);
for (unsigned I = 2; I < Ops.size() - 1; ++I)
Ops[I] = Builder.CreateBitCast(Ops[I], Ty);
- Ops.push_back(Align);
+ Ops.push_back(getAlignmentValue32(PtrOp1));
Ops[1] = Builder.CreateCall(F, makeArrayRef(Ops).slice(1), NameHint);
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vmovl_v: {
llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
@@ -3019,14 +3183,10 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vqdmlal_v:
case NEON::BI__builtin_neon_vqdmlsl_v: {
SmallVector<Value *, 2> MulOps(Ops.begin() + 1, Ops.end());
- Value *Mul = EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Ty),
- MulOps, "vqdmlal");
-
- SmallVector<Value *, 2> AccumOps;
- AccumOps.push_back(Ops[0]);
- AccumOps.push_back(Mul);
- return EmitNeonCall(CGM.getIntrinsic(AltLLVMIntrinsic, Ty),
- AccumOps, NameHint);
+ Ops[1] =
+ EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Ty), MulOps, "vqdmlal");
+ Ops.resize(2);
+ return EmitNeonCall(CGM.getIntrinsic(AltLLVMIntrinsic, Ty), Ops, NameHint);
}
case NEON::BI__builtin_neon_vqshl_n_v:
case NEON::BI__builtin_neon_vqshlq_n_v:
@@ -3088,9 +3248,11 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
case NEON::BI__builtin_neon_vst3_lane_v:
case NEON::BI__builtin_neon_vst3q_lane_v:
case NEON::BI__builtin_neon_vst4_lane_v:
- case NEON::BI__builtin_neon_vst4q_lane_v:
- Ops.push_back(Align);
- return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "");
+ case NEON::BI__builtin_neon_vst4q_lane_v: {
+ llvm::Type *Tys[] = {Int8PtrTy, Ty};
+ Ops.push_back(getAlignmentValue32(PtrOp0));
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "");
+ }
case NEON::BI__builtin_neon_vsubhn_v: {
llvm::VectorType *SrcTy =
llvm::VectorType::getExtendedElementVectorType(VTy);
@@ -3101,9 +3263,8 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Ops[0] = Builder.CreateSub(Ops[0], Ops[1], "vsubhn");
// %high = lshr <4 x i32> %sum, <i32 16, i32 16, i32 16, i32 16>
- Constant *ShiftAmt = ConstantInt::get(SrcTy->getElementType(),
- SrcTy->getScalarSizeInBits() / 2);
- ShiftAmt = ConstantVector::getSplat(VTy->getNumElements(), ShiftAmt);
+ Constant *ShiftAmt =
+ ConstantInt::get(SrcTy, SrcTy->getScalarSizeInBits() / 2);
Ops[0] = Builder.CreateLShr(Ops[0], ShiftAmt, "vsubhn");
// %res = trunc <4 x i32> %high to <4 x i16>
@@ -3125,7 +3286,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vtrn");
- SV = Builder.CreateStore(SV, Addr);
+ SV = Builder.CreateDefaultAlignedStore(SV, Addr);
}
return SV;
}
@@ -3153,7 +3314,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vuzp");
- SV = Builder.CreateStore(SV, Addr);
+ SV = Builder.CreateDefaultAlignedStore(SV, Addr);
}
return SV;
}
@@ -3173,7 +3334,7 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr(
Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vzip");
- SV = Builder.CreateStore(SV, Addr);
+ SV = Builder.CreateDefaultAlignedStore(SV, Addr);
}
return SV;
}
@@ -3252,33 +3413,37 @@ static Value *packTBLDVectorList(CodeGenFunction &CGF, ArrayRef<Value *> Ops,
}
Value *CodeGenFunction::GetValueForARMHint(unsigned BuiltinID) {
+ unsigned Value;
switch (BuiltinID) {
default:
return nullptr;
case ARM::BI__builtin_arm_nop:
- return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_hint),
- llvm::ConstantInt::get(Int32Ty, 0));
+ Value = 0;
+ break;
case ARM::BI__builtin_arm_yield:
case ARM::BI__yield:
- return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_hint),
- llvm::ConstantInt::get(Int32Ty, 1));
+ Value = 1;
+ break;
case ARM::BI__builtin_arm_wfe:
case ARM::BI__wfe:
- return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_hint),
- llvm::ConstantInt::get(Int32Ty, 2));
+ Value = 2;
+ break;
case ARM::BI__builtin_arm_wfi:
case ARM::BI__wfi:
- return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_hint),
- llvm::ConstantInt::get(Int32Ty, 3));
+ Value = 3;
+ break;
case ARM::BI__builtin_arm_sev:
case ARM::BI__sev:
- return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_hint),
- llvm::ConstantInt::get(Int32Ty, 4));
+ Value = 4;
+ break;
case ARM::BI__builtin_arm_sevl:
case ARM::BI__sevl:
- return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_hint),
- llvm::ConstantInt::get(Int32Ty, 5));
+ Value = 5;
+ break;
}
+
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_hint),
+ llvm::ConstantInt::get(Int32Ty, Value));
}
// Generates the IR for the read/write special register builtin,
@@ -3428,9 +3593,9 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
if (BuiltinID == ARM::BI__clear_cache) {
assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments");
const FunctionDecl *FD = E->getDirectCallee();
- SmallVector<Value*, 2> Ops;
+ Value *Ops[2];
for (unsigned i = 0; i < 2; i++)
- Ops.push_back(EmitScalarExpr(E->getArg(i)));
+ Ops[i] = EmitScalarExpr(E->getArg(i));
llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType());
llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty);
StringRef Name = FD->getName();
@@ -3504,11 +3669,11 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
: Intrinsic::arm_strexd);
llvm::Type *STy = llvm::StructType::get(Int32Ty, Int32Ty, nullptr);
- Value *Tmp = CreateMemTemp(E->getArg(0)->getType());
+ Address Tmp = CreateMemTemp(E->getArg(0)->getType());
Value *Val = EmitScalarExpr(E->getArg(0));
Builder.CreateStore(Val, Tmp);
- Value *LdPtr = Builder.CreateBitCast(Tmp,llvm::PointerType::getUnqual(STy));
+ Address LdPtr = Builder.CreateBitCast(Tmp,llvm::PointerType::getUnqual(STy));
Val = Builder.CreateLoad(LdPtr);
Value *Arg0 = Builder.CreateExtractValue(Val, 0);
@@ -3627,8 +3792,13 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments);
assert(Error == ASTContext::GE_None && "Should not codegen an error");
+ auto getAlignmentValue32 = [&](Address addr) -> Value* {
+ return Builder.getInt32(addr.getAlignment().getQuantity());
+ };
+
+ Address PtrOp0 = Address::invalid();
+ Address PtrOp1 = Address::invalid();
SmallVector<Value*, 4> Ops;
- llvm::Value *Align = nullptr;
bool HasExtraArg = HasExtraNeonArgument(BuiltinID);
unsigned NumArgs = E->getNumArgs() - (HasExtraArg ? 1 : 0);
for (unsigned i = 0, e = NumArgs; i != e; i++) {
@@ -3658,10 +3828,8 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vst4q_lane_v:
// Get the alignment for the argument in addition to the value;
// we'll use it later.
- std::pair<llvm::Value*, unsigned> Src =
- EmitPointerWithAlignment(E->getArg(0));
- Ops.push_back(Src.first);
- Align = Builder.getInt32(Src.second);
+ PtrOp0 = EmitPointerWithAlignment(E->getArg(0));
+ Ops.push_back(PtrOp0.getPointer());
continue;
}
}
@@ -3684,10 +3852,8 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vld4_dup_v:
// Get the alignment for the argument in addition to the value;
// we'll use it later.
- std::pair<llvm::Value*, unsigned> Src =
- EmitPointerWithAlignment(E->getArg(1));
- Ops.push_back(Src.first);
- Align = Builder.getInt32(Src.second);
+ PtrOp1 = EmitPointerWithAlignment(E->getArg(1));
+ Ops.push_back(PtrOp1.getPointer());
continue;
}
}
@@ -3798,7 +3964,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
if (Builtin)
return EmitCommonNeonBuiltinExpr(
Builtin->BuiltinID, Builtin->LLVMIntrinsic, Builtin->AltLLVMIntrinsic,
- Builtin->NameHint, Builtin->TypeModifier, E, Ops, Align);
+ Builtin->NameHint, Builtin->TypeModifier, E, Ops, PtrOp0, PtrOp1);
unsigned Int;
switch (BuiltinID) {
@@ -3809,27 +3975,25 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
if (VTy->getElementType()->isIntegerTy(64)) {
// Extract the other lane.
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
- int Lane = cast<ConstantInt>(Ops[2])->getZExtValue();
+ uint32_t Lane = cast<ConstantInt>(Ops[2])->getZExtValue();
Value *SV = llvm::ConstantVector::get(ConstantInt::get(Int32Ty, 1-Lane));
Ops[1] = Builder.CreateShuffleVector(Ops[1], Ops[1], SV);
// Load the value as a one-element vector.
Ty = llvm::VectorType::get(VTy->getElementType(), 1);
- Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld1, Ty);
+ llvm::Type *Tys[] = {Ty, Int8PtrTy};
+ Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld1, Tys);
+ Value *Align = getAlignmentValue32(PtrOp0);
Value *Ld = Builder.CreateCall(F, {Ops[0], Align});
// Combine them.
- SmallVector<Constant*, 2> Indices;
- Indices.push_back(ConstantInt::get(Int32Ty, 1-Lane));
- Indices.push_back(ConstantInt::get(Int32Ty, Lane));
- SV = llvm::ConstantVector::get(Indices);
+ uint32_t Indices[] = {1 - Lane, Lane};
+ SV = llvm::ConstantDataVector::get(getLLVMContext(), Indices);
return Builder.CreateShuffleVector(Ops[1], Ld, SV, "vld1q_lane");
}
// fall through
case NEON::BI__builtin_neon_vld1_lane_v: {
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
- Ty = llvm::PointerType::getUnqual(VTy->getElementType());
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- LoadInst *Ld = Builder.CreateLoad(Ops[0]);
- Ld->setAlignment(cast<ConstantInt>(Align)->getZExtValue());
+ PtrOp0 = Builder.CreateElementBitCast(PtrOp0, VTy->getElementType());
+ Value *Ld = Builder.CreateLoad(PtrOp0);
return Builder.CreateInsertElement(Ops[1], Ld, Ops[2], "vld1_lane");
}
case NEON::BI__builtin_neon_vld2_dup_v:
@@ -3849,11 +4013,13 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
break;
default: llvm_unreachable("unknown vld_dup intrinsic?");
}
- Function *F = CGM.getIntrinsic(Int, Ty);
+ llvm::Type *Tys[] = {Ty, Int8PtrTy};
+ Function *F = CGM.getIntrinsic(Int, Tys);
+ llvm::Value *Align = getAlignmentValue32(PtrOp1);
Ops[1] = Builder.CreateCall(F, {Ops[1], Align}, "vld_dup");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
switch (BuiltinID) {
case NEON::BI__builtin_neon_vld2_dup_v:
@@ -3867,7 +4033,8 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
break;
default: llvm_unreachable("unknown vld_dup intrinsic?");
}
- Function *F = CGM.getIntrinsic(Int, Ty);
+ llvm::Type *Tys[] = {Ty, Int8PtrTy};
+ Function *F = CGM.getIntrinsic(Int, Tys);
llvm::StructType *STy = cast<llvm::StructType>(F->getReturnType());
SmallVector<Value*, 6> Args;
@@ -3876,7 +4043,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
Args.push_back(CI);
- Args.push_back(Align);
+ Args.push_back(getAlignmentValue32(PtrOp1));
Ops[1] = Builder.CreateCall(F, Args, "vld_dup");
// splat lane 0 to all elts in each vector of the result.
@@ -3889,7 +4056,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
}
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vqrshrn_n_v:
Int =
@@ -3941,18 +4108,17 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Value *SV = llvm::ConstantVector::get(cast<llvm::Constant>(Ops[2]));
Ops[1] = Builder.CreateShuffleVector(Ops[1], Ops[1], SV);
- Ops[2] = Align;
+ Ops[2] = getAlignmentValue32(PtrOp0);
+ llvm::Type *Tys[] = {Int8PtrTy, Ops[1]->getType()};
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst1,
- Ops[1]->getType()), Ops);
+ Tys), Ops);
}
// fall through
case NEON::BI__builtin_neon_vst1_lane_v: {
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]);
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
- StoreInst *St = Builder.CreateStore(Ops[1],
- Builder.CreateBitCast(Ops[0], Ty));
- St->setAlignment(cast<ConstantInt>(Align)->getZExtValue());
+ auto St = Builder.CreateStore(Ops[1], Builder.CreateBitCast(PtrOp0, Ty));
return St;
}
case NEON::BI__builtin_neon_vtbl1_v:
@@ -4029,52 +4195,41 @@ static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID
// Determine the type of this overloaded NEON intrinsic.
NeonTypeFlags Type(Result.getZExtValue());
- llvm::VectorType *VTy = GetNeonType(&CGF, Type);
- llvm::Type *Ty = VTy;
+ llvm::VectorType *Ty = GetNeonType(&CGF, Type);
if (!Ty)
return nullptr;
- unsigned nElts = VTy->getNumElements();
-
CodeGen::CGBuilderTy &Builder = CGF.Builder;
// AArch64 scalar builtins are not overloaded, they do not have an extra
// argument that specifies the vector type, need to handle each case.
- SmallVector<Value *, 2> TblOps;
switch (BuiltinID) {
case NEON::BI__builtin_neon_vtbl1_v: {
- TblOps.push_back(Ops[0]);
- return packTBLDVectorList(CGF, TblOps, nullptr, Ops[1], Ty,
- Intrinsic::aarch64_neon_tbl1, "vtbl1");
+ return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(0, 1), nullptr,
+ Ops[1], Ty, Intrinsic::aarch64_neon_tbl1,
+ "vtbl1");
}
case NEON::BI__builtin_neon_vtbl2_v: {
- TblOps.push_back(Ops[0]);
- TblOps.push_back(Ops[1]);
- return packTBLDVectorList(CGF, TblOps, nullptr, Ops[2], Ty,
- Intrinsic::aarch64_neon_tbl1, "vtbl1");
+ return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(0, 2), nullptr,
+ Ops[2], Ty, Intrinsic::aarch64_neon_tbl1,
+ "vtbl1");
}
case NEON::BI__builtin_neon_vtbl3_v: {
- TblOps.push_back(Ops[0]);
- TblOps.push_back(Ops[1]);
- TblOps.push_back(Ops[2]);
- return packTBLDVectorList(CGF, TblOps, nullptr, Ops[3], Ty,
- Intrinsic::aarch64_neon_tbl2, "vtbl2");
+ return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(0, 3), nullptr,
+ Ops[3], Ty, Intrinsic::aarch64_neon_tbl2,
+ "vtbl2");
}
case NEON::BI__builtin_neon_vtbl4_v: {
- TblOps.push_back(Ops[0]);
- TblOps.push_back(Ops[1]);
- TblOps.push_back(Ops[2]);
- TblOps.push_back(Ops[3]);
- return packTBLDVectorList(CGF, TblOps, nullptr, Ops[4], Ty,
- Intrinsic::aarch64_neon_tbl2, "vtbl2");
+ return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(0, 4), nullptr,
+ Ops[4], Ty, Intrinsic::aarch64_neon_tbl2,
+ "vtbl2");
}
case NEON::BI__builtin_neon_vtbx1_v: {
- TblOps.push_back(Ops[1]);
- Value *TblRes = packTBLDVectorList(CGF, TblOps, nullptr, Ops[2], Ty,
- Intrinsic::aarch64_neon_tbl1, "vtbl1");
+ Value *TblRes =
+ packTBLDVectorList(CGF, makeArrayRef(Ops).slice(1, 1), nullptr, Ops[2],
+ Ty, Intrinsic::aarch64_neon_tbl1, "vtbl1");
- llvm::Constant *Eight = ConstantInt::get(VTy->getElementType(), 8);
- Value* EightV = llvm::ConstantVector::getSplat(nElts, Eight);
+ llvm::Constant *EightV = ConstantInt::get(Ty, 8);
Value *CmpRes = Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[2], EightV);
CmpRes = Builder.CreateSExt(CmpRes, Ty);
@@ -4083,20 +4238,16 @@ static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID
return Builder.CreateOr(EltsFromInput, EltsFromTbl, "vtbx");
}
case NEON::BI__builtin_neon_vtbx2_v: {
- TblOps.push_back(Ops[1]);
- TblOps.push_back(Ops[2]);
- return packTBLDVectorList(CGF, TblOps, Ops[0], Ops[3], Ty,
- Intrinsic::aarch64_neon_tbx1, "vtbx1");
+ return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(1, 2), Ops[0],
+ Ops[3], Ty, Intrinsic::aarch64_neon_tbx1,
+ "vtbx1");
}
case NEON::BI__builtin_neon_vtbx3_v: {
- TblOps.push_back(Ops[1]);
- TblOps.push_back(Ops[2]);
- TblOps.push_back(Ops[3]);
- Value *TblRes = packTBLDVectorList(CGF, TblOps, nullptr, Ops[4], Ty,
- Intrinsic::aarch64_neon_tbl2, "vtbl2");
-
- llvm::Constant *TwentyFour = ConstantInt::get(VTy->getElementType(), 24);
- Value* TwentyFourV = llvm::ConstantVector::getSplat(nElts, TwentyFour);
+ Value *TblRes =
+ packTBLDVectorList(CGF, makeArrayRef(Ops).slice(1, 3), nullptr, Ops[4],
+ Ty, Intrinsic::aarch64_neon_tbl2, "vtbl2");
+
+ llvm::Constant *TwentyFourV = ConstantInt::get(Ty, 24);
Value *CmpRes = Builder.CreateICmp(ICmpInst::ICMP_UGE, Ops[4],
TwentyFourV);
CmpRes = Builder.CreateSExt(CmpRes, Ty);
@@ -4106,12 +4257,9 @@ static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID
return Builder.CreateOr(EltsFromInput, EltsFromTbl, "vtbx");
}
case NEON::BI__builtin_neon_vtbx4_v: {
- TblOps.push_back(Ops[1]);
- TblOps.push_back(Ops[2]);
- TblOps.push_back(Ops[3]);
- TblOps.push_back(Ops[4]);
- return packTBLDVectorList(CGF, TblOps, Ops[0], Ops[5], Ty,
- Intrinsic::aarch64_neon_tbx2, "vtbx2");
+ return packTBLDVectorList(CGF, makeArrayRef(Ops).slice(1, 4), Ops[0],
+ Ops[5], Ty, Intrinsic::aarch64_neon_tbx2,
+ "vtbx2");
}
case NEON::BI__builtin_neon_vqtbl1_v:
case NEON::BI__builtin_neon_vqtbl1q_v:
@@ -4156,15 +4304,6 @@ Value *CodeGenFunction::vectorWrapScalar16(Value *Op) {
return Op;
}
-Value *CodeGenFunction::vectorWrapScalar8(Value *Op) {
- llvm::Type *VTy = llvm::VectorType::get(Int8Ty, 8);
- Op = Builder.CreateBitCast(Op, Int8Ty);
- Value *V = UndefValue::get(VTy);
- llvm::Constant *CI = ConstantInt::get(SizeTy, 0);
- Op = Builder.CreateInsertElement(V, Op, CI);
- return Op;
-}
-
Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
unsigned HintID = static_cast<unsigned>(-1);
@@ -4236,9 +4375,9 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
if (BuiltinID == AArch64::BI__clear_cache) {
assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments");
const FunctionDecl *FD = E->getDirectCallee();
- SmallVector<Value*, 2> Ops;
+ Value *Ops[2];
for (unsigned i = 0; i < 2; i++)
- Ops.push_back(EmitScalarExpr(E->getArg(i)));
+ Ops[i] = EmitScalarExpr(E->getArg(i));
llvm::Type *Ty = CGM.getTypes().ConvertType(FD->getType());
llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty);
StringRef Name = FD->getName();
@@ -4297,14 +4436,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
: Intrinsic::aarch64_stxp);
llvm::Type *STy = llvm::StructType::get(Int64Ty, Int64Ty, nullptr);
- Value *One = llvm::ConstantInt::get(Int32Ty, 1);
- Value *Tmp = Builder.CreateAlloca(ConvertType(E->getArg(0)->getType()),
- One);
- Value *Val = EmitScalarExpr(E->getArg(0));
- Builder.CreateStore(Val, Tmp);
+ Address Tmp = CreateMemTemp(E->getArg(0)->getType());
+ EmitAnyExprToMem(E->getArg(0), Tmp, Qualifiers(), /*init*/ true);
- Value *LdPtr = Builder.CreateBitCast(Tmp,llvm::PointerType::getUnqual(STy));
- Val = Builder.CreateLoad(LdPtr);
+ Tmp = Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(STy));
+ llvm::Value *Val = Builder.CreateLoad(Tmp);
Value *Arg0 = Builder.CreateExtractValue(Val, 0);
Value *Arg1 = Builder.CreateExtractValue(Val, 1);
@@ -4342,6 +4478,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(F);
}
+ if (BuiltinID == AArch64::BI__builtin_thread_pointer) {
+ Function *F = CGM.getIntrinsic(Intrinsic::aarch64_thread_pointer);
+ return Builder.CreateCall(F);
+ }
+
// CRC32
Intrinsic::ID CRCIntrinsicID = Intrinsic::not_intrinsic;
switch (BuiltinID) {
@@ -4453,12 +4594,12 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vldrq_p128: {
llvm::Type *Int128PTy = llvm::Type::getIntNPtrTy(getLLVMContext(), 128);
Value *Ptr = Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), Int128PTy);
- return Builder.CreateLoad(Ptr);
+ return Builder.CreateDefaultAlignedLoad(Ptr);
}
case NEON::BI__builtin_neon_vstrq_p128: {
llvm::Type *Int128PTy = llvm::Type::getIntNPtrTy(getLLVMContext(), 128);
Value *Ptr = Builder.CreateBitCast(Ops[0], Int128PTy);
- return Builder.CreateStore(EmitScalarExpr(E->getArg(1)), Ptr);
+ return Builder.CreateDefaultAlignedStore(EmitScalarExpr(E->getArg(1)), Ptr);
}
case NEON::BI__builtin_neon_vcvts_u32_f32:
case NEON::BI__builtin_neon_vcvtd_u64_f64:
@@ -4491,8 +4632,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
return Builder.CreateSIToFP(Ops[0], FTy);
}
case NEON::BI__builtin_neon_vpaddd_s64: {
- llvm::Type *Ty =
- llvm::VectorType::get(llvm::Type::getInt64Ty(getLLVMContext()), 2);
+ llvm::Type *Ty = llvm::VectorType::get(Int64Ty, 2);
Value *Vec = EmitScalarExpr(E->getArg(0));
// The vector is v2f64, so make sure it's bitcast to that.
Vec = Builder.CreateBitCast(Vec, Ty, "v2i64");
@@ -4505,7 +4645,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
case NEON::BI__builtin_neon_vpaddd_f64: {
llvm::Type *Ty =
- llvm::VectorType::get(llvm::Type::getDoubleTy(getLLVMContext()), 2);
+ llvm::VectorType::get(DoubleTy, 2);
Value *Vec = EmitScalarExpr(E->getArg(0));
// The vector is v2f64, so make sure it's bitcast to that.
Vec = Builder.CreateBitCast(Vec, Ty, "v2f64");
@@ -4518,7 +4658,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
case NEON::BI__builtin_neon_vpadds_f32: {
llvm::Type *Ty =
- llvm::VectorType::get(llvm::Type::getFloatTy(getLLVMContext()), 2);
+ llvm::VectorType::get(FloatTy, 2);
Value *Vec = EmitScalarExpr(E->getArg(0));
// The vector is v2f32, so make sure it's bitcast to that.
Vec = Builder.CreateBitCast(Vec, Ty, "v2f32");
@@ -4566,12 +4706,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
ICmpInst::FCMP_OLT, ICmpInst::ICMP_SLT, "vcltz");
case NEON::BI__builtin_neon_vceqzd_u64: {
- llvm::Type *Ty = llvm::Type::getInt64Ty(getLLVMContext());
Ops.push_back(EmitScalarExpr(E->getArg(0)));
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[0] = Builder.CreateICmp(llvm::ICmpInst::ICMP_EQ, Ops[0],
- llvm::Constant::getNullValue(Ty));
- return Builder.CreateSExt(Ops[0], Ty, "vceqzd");
+ Ops[0] = Builder.CreateBitCast(Ops[0], Int64Ty);
+ Ops[0] =
+ Builder.CreateICmpEQ(Ops[0], llvm::Constant::getNullValue(Int64Ty));
+ return Builder.CreateSExt(Ops[0], Int64Ty, "vceqzd");
}
case NEON::BI__builtin_neon_vceqd_f64:
case NEON::BI__builtin_neon_vcled_f64:
@@ -4645,14 +4784,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
case NEON::BI__builtin_neon_vtstd_s64:
case NEON::BI__builtin_neon_vtstd_u64: {
- llvm::Type *Ty = llvm::Type::getInt64Ty(getLLVMContext());
Ops.push_back(EmitScalarExpr(E->getArg(1)));
- Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ops[0] = Builder.CreateBitCast(Ops[0], Int64Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Int64Ty);
Ops[0] = Builder.CreateAnd(Ops[0], Ops[1]);
Ops[0] = Builder.CreateICmp(ICmpInst::ICMP_NE, Ops[0],
- llvm::Constant::getNullValue(Ty));
- return Builder.CreateSExt(Ops[0], Ty, "vtstd");
+ llvm::Constant::getNullValue(Int64Ty));
+ return Builder.CreateSExt(Ops[0], Int64Ty, "vtstd");
}
case NEON::BI__builtin_neon_vset_lane_i8:
case NEON::BI__builtin_neon_vset_lane_i16:
@@ -4675,89 +4813,80 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vsetq_lane_f64:
// The vector type needs a cast for the v2f64 variant.
Ops[1] = Builder.CreateBitCast(Ops[1],
- llvm::VectorType::get(llvm::Type::getDoubleTy(getLLVMContext()), 2));
+ llvm::VectorType::get(DoubleTy, 2));
Ops.push_back(EmitScalarExpr(E->getArg(2)));
return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vset_lane");
case NEON::BI__builtin_neon_vget_lane_i8:
case NEON::BI__builtin_neon_vdupb_lane_i8:
- Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8));
+ Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int8Ty, 8));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vget_lane");
case NEON::BI__builtin_neon_vgetq_lane_i8:
case NEON::BI__builtin_neon_vdupb_laneq_i8:
- Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16));
+ Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int8Ty, 16));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vgetq_lane");
case NEON::BI__builtin_neon_vget_lane_i16:
case NEON::BI__builtin_neon_vduph_lane_i16:
- Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4));
+ Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int16Ty, 4));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vget_lane");
case NEON::BI__builtin_neon_vgetq_lane_i16:
case NEON::BI__builtin_neon_vduph_laneq_i16:
- Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8));
+ Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int16Ty, 8));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vgetq_lane");
case NEON::BI__builtin_neon_vget_lane_i32:
case NEON::BI__builtin_neon_vdups_lane_i32:
- Ops[0] = Builder.CreateBitCast(
- Ops[0],
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 32), 2));
+ Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int32Ty, 2));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vget_lane");
case NEON::BI__builtin_neon_vdups_lane_f32:
Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::Type::getFloatTy(getLLVMContext()), 2));
+ llvm::VectorType::get(FloatTy, 2));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vdups_lane");
case NEON::BI__builtin_neon_vgetq_lane_i32:
case NEON::BI__builtin_neon_vdups_laneq_i32:
- Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 32), 4));
+ Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int32Ty, 4));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vgetq_lane");
case NEON::BI__builtin_neon_vget_lane_i64:
case NEON::BI__builtin_neon_vdupd_lane_i64:
- Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 64), 1));
+ Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int64Ty, 1));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vget_lane");
case NEON::BI__builtin_neon_vdupd_lane_f64:
Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::Type::getDoubleTy(getLLVMContext()), 1));
+ llvm::VectorType::get(DoubleTy, 1));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vdupd_lane");
case NEON::BI__builtin_neon_vgetq_lane_i64:
case NEON::BI__builtin_neon_vdupd_laneq_i64:
- Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 64), 2));
+ Ops[0] = Builder.CreateBitCast(Ops[0], llvm::VectorType::get(Int64Ty, 2));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vgetq_lane");
case NEON::BI__builtin_neon_vget_lane_f32:
Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::Type::getFloatTy(getLLVMContext()), 2));
+ llvm::VectorType::get(FloatTy, 2));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vget_lane");
case NEON::BI__builtin_neon_vget_lane_f64:
Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::Type::getDoubleTy(getLLVMContext()), 1));
+ llvm::VectorType::get(DoubleTy, 1));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vget_lane");
case NEON::BI__builtin_neon_vgetq_lane_f32:
case NEON::BI__builtin_neon_vdups_laneq_f32:
Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::Type::getFloatTy(getLLVMContext()), 4));
+ llvm::VectorType::get(FloatTy, 4));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vgetq_lane");
case NEON::BI__builtin_neon_vgetq_lane_f64:
case NEON::BI__builtin_neon_vdupd_laneq_f64:
Ops[0] = Builder.CreateBitCast(Ops[0],
- llvm::VectorType::get(llvm::Type::getDoubleTy(getLLVMContext()), 2));
+ llvm::VectorType::get(DoubleTy, 2));
return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)),
"vgetq_lane");
case NEON::BI__builtin_neon_vaddd_s64:
@@ -4930,7 +5059,8 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
if (Builtin)
return EmitCommonNeonBuiltinExpr(
Builtin->BuiltinID, Builtin->LLVMIntrinsic, Builtin->AltLLVMIntrinsic,
- Builtin->NameHint, Builtin->TypeModifier, E, Ops, nullptr);
+ Builtin->NameHint, Builtin->TypeModifier, E, Ops,
+ /*never use addresses*/ Address::invalid(), Address::invalid());
if (Value *V = EmitAArch64TblBuiltinExpr(*this, BuiltinID, E, Ops))
return V;
@@ -5096,15 +5226,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Int = Intrinsic::aarch64_neon_fmaxnm;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vmaxnm");
case NEON::BI__builtin_neon_vrecpss_f32: {
- llvm::Type *f32Type = llvm::Type::getFloatTy(getLLVMContext());
Ops.push_back(EmitScalarExpr(E->getArg(1)));
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, f32Type),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, FloatTy),
Ops, "vrecps");
}
case NEON::BI__builtin_neon_vrecpsd_f64: {
- llvm::Type *f64Type = llvm::Type::getDoubleTy(getLLVMContext());
Ops.push_back(EmitScalarExpr(E->getArg(1)));
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, f64Type),
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_frecps, DoubleTy),
Ops, "vrecps");
}
case NEON::BI__builtin_neon_vqshrun_n_v:
@@ -5207,13 +5335,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcvtq_u32_v:
case NEON::BI__builtin_neon_vcvtq_s64_v:
case NEON::BI__builtin_neon_vcvtq_u64_v: {
- bool Double =
- (cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
- llvm::Type *InTy =
- GetNeonType(this,
- NeonTypeFlags(Double ? NeonTypeFlags::Float64
- : NeonTypeFlags::Float32, false, quad));
- Ops[0] = Builder.CreateBitCast(Ops[0], InTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], GetFloatNeonType(this, Type));
if (usgn)
return Builder.CreateFPToUI(Ops[0], Ty);
return Builder.CreateFPToSI(Ops[0], Ty);
@@ -5227,13 +5349,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcvta_u64_v:
case NEON::BI__builtin_neon_vcvtaq_u64_v: {
Int = usgn ? Intrinsic::aarch64_neon_fcvtau : Intrinsic::aarch64_neon_fcvtas;
- bool Double =
- (cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
- llvm::Type *InTy =
- GetNeonType(this,
- NeonTypeFlags(Double ? NeonTypeFlags::Float64
- : NeonTypeFlags::Float32, false, quad));
- llvm::Type *Tys[2] = { Ty, InTy };
+ llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvta");
}
case NEON::BI__builtin_neon_vcvtm_s32_v:
@@ -5245,13 +5361,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcvtm_u64_v:
case NEON::BI__builtin_neon_vcvtmq_u64_v: {
Int = usgn ? Intrinsic::aarch64_neon_fcvtmu : Intrinsic::aarch64_neon_fcvtms;
- bool Double =
- (cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
- llvm::Type *InTy =
- GetNeonType(this,
- NeonTypeFlags(Double ? NeonTypeFlags::Float64
- : NeonTypeFlags::Float32, false, quad));
- llvm::Type *Tys[2] = { Ty, InTy };
+ llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtm");
}
case NEON::BI__builtin_neon_vcvtn_s32_v:
@@ -5263,13 +5373,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcvtn_u64_v:
case NEON::BI__builtin_neon_vcvtnq_u64_v: {
Int = usgn ? Intrinsic::aarch64_neon_fcvtnu : Intrinsic::aarch64_neon_fcvtns;
- bool Double =
- (cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
- llvm::Type *InTy =
- GetNeonType(this,
- NeonTypeFlags(Double ? NeonTypeFlags::Float64
- : NeonTypeFlags::Float32, false, quad));
- llvm::Type *Tys[2] = { Ty, InTy };
+ llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtn");
}
case NEON::BI__builtin_neon_vcvtp_s32_v:
@@ -5281,13 +5385,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vcvtp_u64_v:
case NEON::BI__builtin_neon_vcvtpq_u64_v: {
Int = usgn ? Intrinsic::aarch64_neon_fcvtpu : Intrinsic::aarch64_neon_fcvtps;
- bool Double =
- (cast<llvm::IntegerType>(VTy->getElementType())->getBitWidth() == 64);
- llvm::Type *InTy =
- GetNeonType(this,
- NeonTypeFlags(Double ? NeonTypeFlags::Float64
- : NeonTypeFlags::Float32, false, quad));
- llvm::Type *Tys[2] = { Ty, InTy };
+ llvm::Type *Tys[2] = { Ty, GetFloatNeonType(this, Type) };
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtp");
}
case NEON::BI__builtin_neon_vmulx_v:
@@ -5338,232 +5436,192 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
// FALLTHROUGH
case NEON::BI__builtin_neon_vaddv_s8: {
Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 8));
+ return Builder.CreateTrunc(Ops[0], Int8Ty);
}
case NEON::BI__builtin_neon_vaddv_u16:
usgn = true;
// FALLTHROUGH
case NEON::BI__builtin_neon_vaddv_s16: {
Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 4);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vaddvq_u8:
usgn = true;
// FALLTHROUGH
case NEON::BI__builtin_neon_vaddvq_s8: {
Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 16);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 8));
+ return Builder.CreateTrunc(Ops[0], Int8Ty);
}
case NEON::BI__builtin_neon_vaddvq_u16:
usgn = true;
// FALLTHROUGH
case NEON::BI__builtin_neon_vaddvq_s16: {
Int = usgn ? Intrinsic::aarch64_neon_uaddv : Intrinsic::aarch64_neon_saddv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vmaxv_u8: {
Int = Intrinsic::aarch64_neon_umaxv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 8));
+ return Builder.CreateTrunc(Ops[0], Int8Ty);
}
case NEON::BI__builtin_neon_vmaxv_u16: {
Int = Intrinsic::aarch64_neon_umaxv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 4);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vmaxvq_u8: {
Int = Intrinsic::aarch64_neon_umaxv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 16);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 8));
+ return Builder.CreateTrunc(Ops[0], Int8Ty);
}
case NEON::BI__builtin_neon_vmaxvq_u16: {
Int = Intrinsic::aarch64_neon_umaxv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vmaxv_s8: {
Int = Intrinsic::aarch64_neon_smaxv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 8));
+ return Builder.CreateTrunc(Ops[0], Int8Ty);
}
case NEON::BI__builtin_neon_vmaxv_s16: {
Int = Intrinsic::aarch64_neon_smaxv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 4);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vmaxvq_s8: {
Int = Intrinsic::aarch64_neon_smaxv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 16);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 8));
+ return Builder.CreateTrunc(Ops[0], Int8Ty);
}
case NEON::BI__builtin_neon_vmaxvq_s16: {
Int = Intrinsic::aarch64_neon_smaxv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vmaxv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vminv_u8: {
Int = Intrinsic::aarch64_neon_uminv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 8));
+ return Builder.CreateTrunc(Ops[0], Int8Ty);
}
case NEON::BI__builtin_neon_vminv_u16: {
Int = Intrinsic::aarch64_neon_uminv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 4);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vminvq_u8: {
Int = Intrinsic::aarch64_neon_uminv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 16);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 8));
+ return Builder.CreateTrunc(Ops[0], Int8Ty);
}
case NEON::BI__builtin_neon_vminvq_u16: {
Int = Intrinsic::aarch64_neon_uminv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vminv_s8: {
Int = Intrinsic::aarch64_neon_sminv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 8));
+ return Builder.CreateTrunc(Ops[0], Int8Ty);
}
case NEON::BI__builtin_neon_vminv_s16: {
Int = Intrinsic::aarch64_neon_sminv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 4);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vminvq_s8: {
Int = Intrinsic::aarch64_neon_sminv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 16);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 8));
+ return Builder.CreateTrunc(Ops[0], Int8Ty);
}
case NEON::BI__builtin_neon_vminvq_s16: {
Int = Intrinsic::aarch64_neon_sminv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vminv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vmul_n_f64: {
Ops[0] = Builder.CreateBitCast(Ops[0], DoubleTy);
@@ -5572,80 +5630,68 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
}
case NEON::BI__builtin_neon_vaddlv_u8: {
Int = Intrinsic::aarch64_neon_uaddlv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vaddlv_u16: {
Int = Intrinsic::aarch64_neon_uaddlv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 4);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
}
case NEON::BI__builtin_neon_vaddlvq_u8: {
Int = Intrinsic::aarch64_neon_uaddlv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 16);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vaddlvq_u16: {
Int = Intrinsic::aarch64_neon_uaddlv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
}
case NEON::BI__builtin_neon_vaddlv_s8: {
Int = Intrinsic::aarch64_neon_saddlv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vaddlv_s16: {
Int = Intrinsic::aarch64_neon_saddlv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 4);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 4);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
}
case NEON::BI__builtin_neon_vaddlvq_s8: {
Int = Intrinsic::aarch64_neon_saddlv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8), 16);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int8Ty, 16);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
- return Builder.CreateTrunc(Ops[0],
- llvm::IntegerType::get(getLLVMContext(), 16));
+ return Builder.CreateTrunc(Ops[0], Int16Ty);
}
case NEON::BI__builtin_neon_vaddlvq_s16: {
Int = Intrinsic::aarch64_neon_saddlv;
- Ty = llvm::IntegerType::get(getLLVMContext(), 32);
- VTy =
- llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16), 8);
+ Ty = Int32Ty;
+ VTy = llvm::VectorType::get(Int16Ty, 8);
llvm::Type *Tys[2] = { Ty, VTy };
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vaddlv");
@@ -5708,7 +5754,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[1] = Builder.CreateCall(F, Ops[1], "vld1xN");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vst1_x2_v:
case NEON::BI__builtin_neon_vst1q_x2_v:
@@ -5733,32 +5779,31 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Int = Intrinsic::aarch64_neon_st1x4;
break;
}
- SmallVector<Value *, 4> IntOps(Ops.begin()+1, Ops.end());
- IntOps.push_back(Ops[0]);
- return EmitNeonCall(CGM.getIntrinsic(Int, Tys), IntOps, "");
+ std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end());
+ return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "");
}
case NEON::BI__builtin_neon_vld1_v:
case NEON::BI__builtin_neon_vld1q_v:
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(VTy));
- return Builder.CreateLoad(Ops[0]);
+ return Builder.CreateDefaultAlignedLoad(Ops[0]);
case NEON::BI__builtin_neon_vst1_v:
case NEON::BI__builtin_neon_vst1q_v:
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(VTy));
Ops[1] = Builder.CreateBitCast(Ops[1], VTy);
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
case NEON::BI__builtin_neon_vld1_lane_v:
case NEON::BI__builtin_neon_vld1q_lane_v:
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ty = llvm::PointerType::getUnqual(VTy->getElementType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[0] = Builder.CreateLoad(Ops[0]);
+ Ops[0] = Builder.CreateDefaultAlignedLoad(Ops[0]);
return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vld1_lane");
case NEON::BI__builtin_neon_vld1_dup_v:
case NEON::BI__builtin_neon_vld1q_dup_v: {
Value *V = UndefValue::get(Ty);
Ty = llvm::PointerType::getUnqual(VTy->getElementType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[0] = Builder.CreateLoad(Ops[0]);
+ Ops[0] = Builder.CreateDefaultAlignedLoad(Ops[0]);
llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
Ops[0] = Builder.CreateInsertElement(V, Ops[0], CI);
return EmitNeonSplat(Ops[0], CI);
@@ -5768,7 +5813,8 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[1] = Builder.CreateExtractElement(Ops[1], Ops[2]);
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
- return Builder.CreateStore(Ops[1], Builder.CreateBitCast(Ops[0], Ty));
+ return Builder.CreateDefaultAlignedStore(Ops[1],
+ Builder.CreateBitCast(Ops[0], Ty));
case NEON::BI__builtin_neon_vld2_v:
case NEON::BI__builtin_neon_vld2q_v: {
llvm::Type *PTy = llvm::PointerType::getUnqual(VTy);
@@ -5778,7 +5824,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[1] = Builder.CreateCall(F, Ops[1], "vld2");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vld3_v:
case NEON::BI__builtin_neon_vld3q_v: {
@@ -5789,7 +5835,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[1] = Builder.CreateCall(F, Ops[1], "vld3");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vld4_v:
case NEON::BI__builtin_neon_vld4q_v: {
@@ -5800,7 +5846,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[1] = Builder.CreateCall(F, Ops[1], "vld4");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vld2_dup_v:
case NEON::BI__builtin_neon_vld2q_dup_v: {
@@ -5812,7 +5858,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[1] = Builder.CreateCall(F, Ops[1], "vld2");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vld3_dup_v:
case NEON::BI__builtin_neon_vld3q_dup_v: {
@@ -5824,7 +5870,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[1] = Builder.CreateCall(F, Ops[1], "vld3");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vld4_dup_v:
case NEON::BI__builtin_neon_vld4q_dup_v: {
@@ -5836,7 +5882,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[1] = Builder.CreateCall(F, Ops[1], "vld4");
Ops[0] = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()));
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vld2_lane_v:
case NEON::BI__builtin_neon_vld2q_lane_v: {
@@ -5846,12 +5892,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops.erase(Ops.begin()+1);
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
- Ops[3] = Builder.CreateZExt(Ops[3],
- llvm::IntegerType::get(getLLVMContext(), 64));
+ Ops[3] = Builder.CreateZExt(Ops[3], Int64Ty);
Ops[1] = Builder.CreateCall(F, makeArrayRef(Ops).slice(1), "vld2_lane");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vld3_lane_v:
case NEON::BI__builtin_neon_vld3q_lane_v: {
@@ -5862,12 +5907,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
Ops[3] = Builder.CreateBitCast(Ops[3], Ty);
- Ops[4] = Builder.CreateZExt(Ops[4],
- llvm::IntegerType::get(getLLVMContext(), 64));
+ Ops[4] = Builder.CreateZExt(Ops[4], Int64Ty);
Ops[1] = Builder.CreateCall(F, makeArrayRef(Ops).slice(1), "vld3_lane");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vld4_lane_v:
case NEON::BI__builtin_neon_vld4q_lane_v: {
@@ -5879,12 +5923,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
Ops[3] = Builder.CreateBitCast(Ops[3], Ty);
Ops[4] = Builder.CreateBitCast(Ops[4], Ty);
- Ops[5] = Builder.CreateZExt(Ops[5],
- llvm::IntegerType::get(getLLVMContext(), 64));
+ Ops[5] = Builder.CreateZExt(Ops[5], Int64Ty);
Ops[1] = Builder.CreateCall(F, makeArrayRef(Ops).slice(1), "vld4_lane");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case NEON::BI__builtin_neon_vst2_v:
case NEON::BI__builtin_neon_vst2q_v: {
@@ -5898,8 +5941,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vst2q_lane_v: {
Ops.push_back(Ops[0]);
Ops.erase(Ops.begin());
- Ops[2] = Builder.CreateZExt(Ops[2],
- llvm::IntegerType::get(getLLVMContext(), 64));
+ Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty);
llvm::Type *Tys[2] = { VTy, Ops[3]->getType() };
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st2lane, Tys),
Ops, "");
@@ -5916,8 +5958,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vst3q_lane_v: {
Ops.push_back(Ops[0]);
Ops.erase(Ops.begin());
- Ops[3] = Builder.CreateZExt(Ops[3],
- llvm::IntegerType::get(getLLVMContext(), 64));
+ Ops[3] = Builder.CreateZExt(Ops[3], Int64Ty);
llvm::Type *Tys[2] = { VTy, Ops[4]->getType() };
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st3lane, Tys),
Ops, "");
@@ -5934,8 +5975,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
case NEON::BI__builtin_neon_vst4q_lane_v: {
Ops.push_back(Ops[0]);
Ops.erase(Ops.begin());
- Ops[4] = Builder.CreateZExt(Ops[4],
- llvm::IntegerType::get(getLLVMContext(), 64));
+ Ops[4] = Builder.CreateZExt(Ops[4], Int64Ty);
llvm::Type *Tys[2] = { VTy, Ops[5]->getType() };
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::aarch64_neon_st4lane, Tys),
Ops, "");
@@ -5956,7 +5996,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vtrn");
- SV = Builder.CreateStore(SV, Addr);
+ SV = Builder.CreateDefaultAlignedStore(SV, Addr);
}
return SV;
}
@@ -5975,7 +6015,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vuzp");
- SV = Builder.CreateStore(SV, Addr);
+ SV = Builder.CreateDefaultAlignedStore(SV, Addr);
}
return SV;
}
@@ -5995,7 +6035,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ty, Ops[0], vi);
SV = llvm::ConstantVector::get(Indices);
SV = Builder.CreateShuffleVector(Ops[1], Ops[2], SV, "vzip");
- SV = Builder.CreateStore(SV, Addr);
+ SV = Builder.CreateDefaultAlignedStore(SV, Addr);
}
return SV;
}
@@ -6072,6 +6112,31 @@ BuildVector(ArrayRef<llvm::Value*> Ops) {
Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
+ if (BuiltinID == X86::BI__builtin_ms_va_start ||
+ BuiltinID == X86::BI__builtin_ms_va_end)
+ return EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).getPointer(),
+ BuiltinID == X86::BI__builtin_ms_va_start);
+ if (BuiltinID == X86::BI__builtin_ms_va_copy) {
+ // Lower this manually. We can't reliably determine whether or not any
+ // given va_copy() is for a Win64 va_list from the calling convention
+ // alone, because it's legal to do this from a System V ABI function.
+ // With opaque pointer types, we won't have enough information in LLVM
+ // IR to determine this from the argument types, either. Best to do it
+ // now, while we have enough information.
+ Address DestAddr = EmitMSVAListRef(E->getArg(0));
+ Address SrcAddr = EmitMSVAListRef(E->getArg(1));
+
+ llvm::Type *BPP = Int8PtrPtrTy;
+
+ DestAddr = Address(Builder.CreateBitCast(DestAddr.getPointer(), BPP, "cp"),
+ DestAddr.getAlignment());
+ SrcAddr = Address(Builder.CreateBitCast(SrcAddr.getPointer(), BPP, "ap"),
+ SrcAddr.getAlignment());
+
+ Value *ArgPtr = Builder.CreateLoad(SrcAddr, "ap.val");
+ return Builder.CreateStore(ArgPtr, DestAddr);
+ }
+
SmallVector<Value*, 4> Ops;
// Find out if any arguments are required to be integer constant expressions.
@@ -6167,7 +6232,8 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
ConstantInt::get(Int32Ty, 0)
};
Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs);
- Value *Features = Builder.CreateLoad(CpuFeatures);
+ Value *Features = Builder.CreateAlignedLoad(CpuFeatures,
+ CharUnits::fromQuantity(4));
// Check the value of the bit corresponding to the feature requested.
Value *Bitset = Builder.CreateAnd(
@@ -6175,13 +6241,17 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return Builder.CreateICmpNE(Bitset, llvm::ConstantInt::get(Int32Ty, 0));
}
case X86::BI_mm_prefetch: {
- Value *Address = EmitScalarExpr(E->getArg(0));
+ Value *Address = Ops[0];
Value *RW = ConstantInt::get(Int32Ty, 0);
- Value *Locality = EmitScalarExpr(E->getArg(1));
+ Value *Locality = Ops[1];
Value *Data = ConstantInt::get(Int32Ty, 1);
Value *F = CGM.getIntrinsic(Intrinsic::prefetch);
return Builder.CreateCall(F, {Address, RW, Locality, Data});
}
+ case X86::BI__builtin_ia32_undef128:
+ case X86::BI__builtin_ia32_undef256:
+ case X86::BI__builtin_ia32_undef512:
+ return UndefValue::get(ConvertType(E->getType()));
case X86::BI__builtin_ia32_vec_init_v8qi:
case X86::BI__builtin_ia32_vec_init_v4hi:
case X86::BI__builtin_ia32_vec_init_v2si:
@@ -6191,17 +6261,57 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return Builder.CreateExtractElement(Ops[0],
llvm::ConstantInt::get(Ops[1]->getType(), 0));
case X86::BI__builtin_ia32_ldmxcsr: {
- Value *Tmp = CreateMemTemp(E->getArg(0)->getType());
+ Address Tmp = CreateMemTemp(E->getArg(0)->getType());
Builder.CreateStore(Ops[0], Tmp);
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr),
- Builder.CreateBitCast(Tmp, Int8PtrTy));
+ Builder.CreateBitCast(Tmp.getPointer(), Int8PtrTy));
}
case X86::BI__builtin_ia32_stmxcsr: {
- Value *Tmp = CreateMemTemp(E->getType());
+ Address Tmp = CreateMemTemp(E->getType());
Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr),
- Builder.CreateBitCast(Tmp, Int8PtrTy));
+ Builder.CreateBitCast(Tmp.getPointer(), Int8PtrTy));
return Builder.CreateLoad(Tmp, "stmxcsr");
}
+ case X86::BI__builtin_ia32_xsave:
+ case X86::BI__builtin_ia32_xsave64:
+ case X86::BI__builtin_ia32_xrstor:
+ case X86::BI__builtin_ia32_xrstor64:
+ case X86::BI__builtin_ia32_xsaveopt:
+ case X86::BI__builtin_ia32_xsaveopt64:
+ case X86::BI__builtin_ia32_xrstors:
+ case X86::BI__builtin_ia32_xrstors64:
+ case X86::BI__builtin_ia32_xsavec:
+ case X86::BI__builtin_ia32_xsavec64:
+ case X86::BI__builtin_ia32_xsaves:
+ case X86::BI__builtin_ia32_xsaves64: {
+ Intrinsic::ID ID;
+#define INTRINSIC_X86_XSAVE_ID(NAME) \
+ case X86::BI__builtin_ia32_##NAME: \
+ ID = Intrinsic::x86_##NAME; \
+ break
+ switch (BuiltinID) {
+ default: llvm_unreachable("Unsupported intrinsic!");
+ INTRINSIC_X86_XSAVE_ID(xsave);
+ INTRINSIC_X86_XSAVE_ID(xsave64);
+ INTRINSIC_X86_XSAVE_ID(xrstor);
+ INTRINSIC_X86_XSAVE_ID(xrstor64);
+ INTRINSIC_X86_XSAVE_ID(xsaveopt);
+ INTRINSIC_X86_XSAVE_ID(xsaveopt64);
+ INTRINSIC_X86_XSAVE_ID(xrstors);
+ INTRINSIC_X86_XSAVE_ID(xrstors64);
+ INTRINSIC_X86_XSAVE_ID(xsavec);
+ INTRINSIC_X86_XSAVE_ID(xsavec64);
+ INTRINSIC_X86_XSAVE_ID(xsaves);
+ INTRINSIC_X86_XSAVE_ID(xsaves64);
+ }
+#undef INTRINSIC_X86_XSAVE_ID
+ Value *Mhi = Builder.CreateTrunc(
+ Builder.CreateLShr(Ops[1], ConstantInt::get(Int64Ty, 32)), Int32Ty);
+ Value *Mlo = Builder.CreateTrunc(Ops[1], Int32Ty);
+ Ops[1] = Mhi;
+ Ops.push_back(Mlo);
+ return Builder.CreateCall(CGM.getIntrinsic(ID), Ops);
+ }
case X86::BI__builtin_ia32_storehps:
case X86::BI__builtin_ia32_storelps: {
llvm::Type *PtrTy = llvm::PointerType::getUnqual(Int64Ty);
@@ -6217,7 +6327,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
// cast pointer to i64 & store
Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy);
- return Builder.CreateStore(Ops[1], Ops[0]);
+ return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
}
case X86::BI__builtin_ia32_palignr128:
case X86::BI__builtin_ia32_palignr256: {
@@ -6242,18 +6352,19 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Ops[0] = llvm::Constant::getNullValue(Ops[0]->getType());
}
- SmallVector<llvm::Constant*, 32> Indices;
+ uint32_t Indices[32];
// 256-bit palignr operates on 128-bit lanes so we need to handle that
for (unsigned l = 0; l != NumElts; l += NumLaneElts) {
for (unsigned i = 0; i != NumLaneElts; ++i) {
unsigned Idx = ShiftVal + i;
if (Idx >= NumLaneElts)
Idx += NumElts - NumLaneElts; // End of lane, switch operand.
- Indices.push_back(llvm::ConstantInt::get(Int32Ty, Idx + l));
+ Indices[l + i] = Idx + l;
}
}
- Value* SV = llvm::ConstantVector::get(Indices);
+ Value *SV = llvm::ConstantDataVector::get(getLLVMContext(),
+ makeArrayRef(Indices, NumElts));
return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr");
}
case X86::BI__builtin_ia32_pslldqi256: {
@@ -6264,13 +6375,13 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
if (shiftVal >= 16)
return llvm::Constant::getNullValue(ConvertType(E->getType()));
- SmallVector<llvm::Constant*, 32> Indices;
+ uint32_t Indices[32];
// 256-bit pslldq operates on 128-bit lanes so we need to handle that
for (unsigned l = 0; l != 32; l += 16) {
for (unsigned i = 0; i != 16; ++i) {
unsigned Idx = 32 + i - shiftVal;
if (Idx < 32) Idx -= 16; // end of lane, switch operand.
- Indices.push_back(llvm::ConstantInt::get(Int32Ty, Idx + l));
+ Indices[l + i] = Idx + l;
}
}
@@ -6278,7 +6389,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast");
Value *Zero = llvm::Constant::getNullValue(VecTy);
- Value *SV = llvm::ConstantVector::get(Indices);
+ Value *SV = llvm::ConstantDataVector::get(getLLVMContext(), Indices);
SV = Builder.CreateShuffleVector(Zero, Ops[0], SV, "pslldq");
llvm::Type *ResultType = ConvertType(E->getType());
return Builder.CreateBitCast(SV, ResultType, "cast");
@@ -6291,13 +6402,13 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
if (shiftVal >= 16)
return llvm::Constant::getNullValue(ConvertType(E->getType()));
- SmallVector<llvm::Constant*, 32> Indices;
+ uint32_t Indices[32];
// 256-bit psrldq operates on 128-bit lanes so we need to handle that
for (unsigned l = 0; l != 32; l += 16) {
for (unsigned i = 0; i != 16; ++i) {
unsigned Idx = i + shiftVal;
if (Idx >= 16) Idx += 16; // end of lane, switch operand.
- Indices.push_back(llvm::ConstantInt::get(Int32Ty, Idx + l));
+ Indices[l + i] = Idx + l;
}
}
@@ -6305,7 +6416,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast");
Value *Zero = llvm::Constant::getNullValue(VecTy);
- Value *SV = llvm::ConstantVector::get(Indices);
+ Value *SV = llvm::ConstantDataVector::get(getLLVMContext(), Indices);
SV = Builder.CreateShuffleVector(Ops[0], Zero, SV, "psrldq");
llvm::Type *ResultType = ConvertType(E->getType());
return Builder.CreateBitCast(SV, ResultType, "cast");
@@ -6325,7 +6436,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Value *BC = Builder.CreateBitCast(Ops[0],
llvm::PointerType::getUnqual(Ops[1]->getType()),
"cast");
- StoreInst *SI = Builder.CreateStore(Ops[1], BC);
+ StoreInst *SI = Builder.CreateDefaultAlignedStore(Ops[1], BC);
SI->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
// If the operand is an integer, we can't assume alignment. Otherwise,
@@ -6377,7 +6488,8 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
}
Value *Call = Builder.CreateCall(CGM.getIntrinsic(ID));
- Builder.CreateStore(Builder.CreateExtractValue(Call, 0), Ops[0]);
+ Builder.CreateDefaultAlignedStore(Builder.CreateExtractValue(Call, 0),
+ Ops[0]);
return Builder.CreateExtractValue(Call, 1);
}
// SSE comparison intrisics
@@ -6544,6 +6656,11 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
switch (BuiltinID) {
default: return nullptr;
+ // __builtin_ppc_get_timebase is GCC 4.8+'s PowerPC-specific name for what we
+ // call __builtin_readcyclecounter.
+ case PPC::BI__builtin_ppc_get_timebase:
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::readcyclecounter));
+
// vec_ld, vec_lvsl, vec_lvsr
case PPC::BI__builtin_altivec_lvx:
case PPC::BI__builtin_altivec_lvxl:
@@ -6775,8 +6892,7 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
// Translate from the intrinsics's struct return to the builtin's out
// argument.
- std::pair<llvm::Value *, unsigned> FlagOutPtr
- = EmitPointerWithAlignment(E->getArg(3));
+ Address FlagOutPtr = EmitPointerWithAlignment(E->getArg(3));
llvm::Value *X = EmitScalarExpr(E->getArg(0));
llvm::Value *Y = EmitScalarExpr(E->getArg(1));
@@ -6791,11 +6907,10 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
llvm::Value *Flag = Builder.CreateExtractValue(Tmp, 1);
llvm::Type *RealFlagType
- = FlagOutPtr.first->getType()->getPointerElementType();
+ = FlagOutPtr.getPointer()->getType()->getPointerElementType();
llvm::Value *FlagExt = Builder.CreateZExt(Flag, RealFlagType);
- llvm::StoreInst *FlagStore = Builder.CreateStore(FlagExt, FlagOutPtr.first);
- FlagStore->setAlignment(FlagOutPtr.second);
+ Builder.CreateStore(FlagExt, FlagOutPtr);
return Result;
}
case AMDGPU::BI__builtin_amdgpu_div_fmas:
@@ -6846,7 +6961,7 @@ static Value *EmitSystemZIntrinsicWithCC(CodeGenFunction &CGF,
SmallVector<Value *, 8> Args(NumArgs);
for (unsigned I = 0; I < NumArgs; ++I)
Args[I] = CGF.EmitScalarExpr(E->getArg(I));
- Value *CCPtr = CGF.EmitScalarExpr(E->getArg(NumArgs));
+ Address CCPtr = CGF.EmitPointerWithAlignment(E->getArg(NumArgs));
Value *F = CGF.CGM.getIntrinsic(IntrinsicID);
Value *Call = CGF.Builder.CreateCall(F, Args);
Value *CC = CGF.Builder.CreateExtractValue(Call, 1);
@@ -7115,23 +7230,29 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
case NVPTX::BI__nvvm_atom_max_gen_i:
case NVPTX::BI__nvvm_atom_max_gen_l:
case NVPTX::BI__nvvm_atom_max_gen_ll:
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Max, E);
+
case NVPTX::BI__nvvm_atom_max_gen_ui:
case NVPTX::BI__nvvm_atom_max_gen_ul:
case NVPTX::BI__nvvm_atom_max_gen_ull:
- return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Max, E);
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::UMax, E);
case NVPTX::BI__nvvm_atom_min_gen_i:
case NVPTX::BI__nvvm_atom_min_gen_l:
case NVPTX::BI__nvvm_atom_min_gen_ll:
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Min, E);
+
case NVPTX::BI__nvvm_atom_min_gen_ui:
case NVPTX::BI__nvvm_atom_min_gen_ul:
case NVPTX::BI__nvvm_atom_min_gen_ull:
- return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::Min, E);
+ return MakeBinaryAtomicValue(*this, llvm::AtomicRMWInst::UMin, E);
case NVPTX::BI__nvvm_atom_cas_gen_i:
case NVPTX::BI__nvvm_atom_cas_gen_l:
case NVPTX::BI__nvvm_atom_cas_gen_ll:
- return MakeAtomicCmpXchgValue(*this, E, true);
+ // __nvvm_atom_cas_gen_* should return the old value rather than the
+ // success flag.
+ return MakeAtomicCmpXchgValue(*this, E, /*ReturnBool=*/false);
case NVPTX::BI__nvvm_atom_add_gen_f: {
Value *Ptr = EmitScalarExpr(E->getArg(0));
@@ -7147,3 +7268,22 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
return nullptr;
}
}
+
+Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E) {
+ switch (BuiltinID) {
+ case WebAssembly::BI__builtin_wasm_memory_size: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_memory_size, ResultType);
+ return Builder.CreateCall(Callee);
+ }
+ case WebAssembly::BI__builtin_wasm_grow_memory: {
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Value *Callee = CGM.getIntrinsic(Intrinsic::wasm_grow_memory, X->getType());
+ return Builder.CreateCall(Callee, X);
+ }
+
+ default:
+ return nullptr;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp
index 67d0ab7..045e19b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp
@@ -57,9 +57,9 @@ private:
unsigned Alignment = 0) {
llvm::Constant *Zeros[] = {llvm::ConstantInt::get(SizeTy, 0),
llvm::ConstantInt::get(SizeTy, 0)};
- auto *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
- return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
- ConstStr, Zeros);
+ auto ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
+ return llvm::ConstantExpr::getGetElementPtr(ConstStr.getElementType(),
+ ConstStr.getPointer(), Zeros);
}
void emitDeviceStubBody(CodeGenFunction &CGF, FunctionArgList &Args);
@@ -121,7 +121,7 @@ void CGNVCUDARuntime::emitDeviceStubBody(CodeGenFunction &CGF,
std::vector<llvm::Type *> ArgTypes;
for (FunctionArgList::const_iterator I = Args.begin(), E = Args.end();
I != E; ++I) {
- llvm::Value *V = CGF.GetAddrOfLocalVar(*I);
+ llvm::Value *V = CGF.GetAddrOfLocalVar(*I).getPointer();
ArgValues.push_back(V);
assert(isa<llvm::PointerType>(V->getType()) && "Arg type not PointerType");
ArgTypes.push_back(cast<llvm::PointerType>(V->getType())->getElementType());
@@ -173,7 +173,7 @@ llvm::Function *CGNVCUDARuntime::makeRegisterKernelsFn() {
llvm::GlobalValue::InternalLinkage, "__cuda_register_kernels", &TheModule);
llvm::BasicBlock *EntryBB =
llvm::BasicBlock::Create(Context, "entry", RegisterKernelsFunc);
- CGBuilderTy Builder(Context);
+ CGBuilderTy Builder(CGM, Context);
Builder.SetInsertPoint(EntryBB);
// void __cudaRegisterFunction(void **, const char *, char *, const char *,
@@ -230,7 +230,7 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
llvm::GlobalValue::InternalLinkage, "__cuda_module_ctor", &TheModule);
llvm::BasicBlock *CtorEntryBB =
llvm::BasicBlock::Create(Context, "entry", ModuleCtorFunc);
- CGBuilderTy CtorBuilder(Context);
+ CGBuilderTy CtorBuilder(CGM, Context);
CtorBuilder.SetInsertPoint(CtorEntryBB);
@@ -267,7 +267,8 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
llvm::GlobalVariable *GpuBinaryHandle = new llvm::GlobalVariable(
TheModule, VoidPtrPtrTy, false, llvm::GlobalValue::InternalLinkage,
llvm::ConstantPointerNull::get(VoidPtrPtrTy), "__cuda_gpubin_handle");
- CtorBuilder.CreateStore(RegisterFatbinCall, GpuBinaryHandle, false);
+ CtorBuilder.CreateAlignedStore(RegisterFatbinCall, GpuBinaryHandle,
+ CGM.getPointerAlign());
// Call __cuda_register_kernels(GpuBinaryHandle);
CtorBuilder.CreateCall(RegisterKernelsFunc, RegisterFatbinCall);
@@ -300,12 +301,13 @@ llvm::Function *CGNVCUDARuntime::makeModuleDtorFunction() {
llvm::GlobalValue::InternalLinkage, "__cuda_module_dtor", &TheModule);
llvm::BasicBlock *DtorEntryBB =
llvm::BasicBlock::Create(Context, "entry", ModuleDtorFunc);
- CGBuilderTy DtorBuilder(Context);
+ CGBuilderTy DtorBuilder(CGM, Context);
DtorBuilder.SetInsertPoint(DtorEntryBB);
for (llvm::GlobalVariable *GpuBinaryHandle : GpuBinaryHandles) {
- DtorBuilder.CreateCall(UnregisterFatbinFunc,
- DtorBuilder.CreateLoad(GpuBinaryHandle, false));
+ auto HandleValue =
+ DtorBuilder.CreateAlignedLoad(GpuBinaryHandle, CGM.getPointerAlign());
+ DtorBuilder.CreateCall(UnregisterFatbinFunc, HandleValue);
}
DtorBuilder.CreateRetVoid();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
index 7d7ed78..6847df9 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXX.cpp
@@ -28,6 +28,7 @@
using namespace clang;
using namespace CodeGen;
+
/// Try to emit a base destructor as an alias to its primary
/// base-class destructor.
bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
@@ -39,6 +40,12 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
if (getCodeGenOpts().OptimizationLevel == 0)
return true;
+ // If sanitizing memory to check for use-after-dtor, do not emit as
+ // an alias, unless this class owns no members.
+ if (getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
+ !D->getParent()->field_empty())
+ return true;
+
// If the destructor doesn't have a trivial body, we have to emit it
// separately.
if (!D->hasTrivialBody())
@@ -124,11 +131,6 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
if (!llvm::GlobalAlias::isValidLinkage(Linkage))
return true;
- // Don't create a weak alias for a dllexport'd symbol.
- if (AliasDecl.getDecl()->hasAttr<DLLExportAttr>() &&
- llvm::GlobalValue::isWeakForLinker(Linkage))
- return true;
-
llvm::GlobalValue::LinkageTypes TargetLinkage =
getFunctionLinkage(TargetDecl);
@@ -141,8 +143,8 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
return false;
// Derive the type for the alias.
- llvm::PointerType *AliasType
- = getTypes().GetFunctionType(AliasDecl)->getPointerTo();
+ llvm::Type *AliasValueType = getTypes().GetFunctionType(AliasDecl);
+ llvm::PointerType *AliasType = AliasValueType->getPointerTo();
// Find the referent. Some aliases might require a bitcast, in
// which case the caller is responsible for ensuring the soundness
@@ -166,6 +168,16 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
return false;
}
+ // If we have a weak, non-discardable alias (weak, weak_odr), like an extern
+ // template instantiation or a dllexported class, avoid forming it on COFF.
+ // A COFF weak external alias cannot satisfy a normal undefined symbol
+ // reference from another TU. The other TU must also mark the referenced
+ // symbol as weak, which we cannot rely on.
+ if (llvm::GlobalValue::isWeakForLinker(Linkage) &&
+ getTriple().isOSBinFormatCOFF()) {
+ return true;
+ }
+
if (!InEveryTU) {
// If we don't have a definition for the destructor yet, don't
// emit. We can't emit aliases to declarations; that's just not
@@ -182,8 +194,8 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
return true;
// Create the alias with no name.
- auto *Alias =
- llvm::GlobalAlias::create(AliasType, Linkage, "", Aliasee, &getModule());
+ auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "",
+ Aliasee, &getModule());
// Switch any previous uses to the alias.
if (Entry) {
@@ -207,7 +219,8 @@ llvm::Function *CodeGenModule::codegenCXXStructor(const CXXMethodDecl *MD,
const CGFunctionInfo &FnInfo =
getTypes().arrangeCXXStructorDeclaration(MD, Type);
auto *Fn = cast<llvm::Function>(
- getAddrOfCXXStructor(MD, Type, &FnInfo, nullptr, true));
+ getAddrOfCXXStructor(MD, Type, &FnInfo, /*FnType=*/nullptr,
+ /*DontDefer=*/true, /*IsForDefinition=*/true));
GlobalDecl GD;
if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
@@ -226,9 +239,9 @@ llvm::Function *CodeGenModule::codegenCXXStructor(const CXXMethodDecl *MD,
return Fn;
}
-llvm::GlobalValue *CodeGenModule::getAddrOfCXXStructor(
+llvm::Constant *CodeGenModule::getAddrOfCXXStructor(
const CXXMethodDecl *MD, StructorType Type, const CGFunctionInfo *FnInfo,
- llvm::FunctionType *FnType, bool DontDefer) {
+ llvm::FunctionType *FnType, bool DontDefer, bool IsForDefinition) {
GlobalDecl GD;
if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
GD = GlobalDecl(CD, toCXXCtorType(Type));
@@ -236,19 +249,15 @@ llvm::GlobalValue *CodeGenModule::getAddrOfCXXStructor(
GD = GlobalDecl(cast<CXXDestructorDecl>(MD), toCXXDtorType(Type));
}
- StringRef Name = getMangledName(GD);
- if (llvm::GlobalValue *Existing = GetGlobalValue(Name))
- return Existing;
-
if (!FnType) {
if (!FnInfo)
FnInfo = &getTypes().arrangeCXXStructorDeclaration(MD, Type);
FnType = getTypes().GetFunctionType(*FnInfo);
}
- return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FnType, GD,
- /*ForVTable=*/false,
- DontDefer));
+ return GetOrCreateLLVMFunction(
+ getMangledName(GD), FnType, GD, /*ForVTable=*/false, DontDefer,
+ /*isThunk=*/false, /*ExtraAttrs=*/llvm::AttributeSet(), IsForDefinition);
}
static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF,
@@ -270,7 +279,7 @@ static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF,
VTableIndex += AddressPoint;
llvm::Value *VFuncPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
- return CGF.Builder.CreateLoad(VFuncPtr);
+ return CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.PointerAlignInBytes);
}
/// BuildAppleKextVirtualCall - This routine is to support gcc's kext ABI making
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
index dc16616..e4da447 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "CGCXXABI.h"
+#include "CGCleanup.h"
using namespace clang;
using namespace CodeGen;
@@ -73,25 +74,28 @@ CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
}
llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(
- CodeGenFunction &CGF, const Expr *E, llvm::Value *&This,
+ CodeGenFunction &CGF, const Expr *E, Address This,
+ llvm::Value *&ThisPtrForCall,
llvm::Value *MemPtr, const MemberPointerType *MPT) {
ErrorUnsupportedABI(CGF, "calls through member pointers");
+ ThisPtrForCall = This.getPointer();
const FunctionProtoType *FPT =
MPT->getPointeeType()->getAs<FunctionProtoType>();
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
- CGM.getTypes().arrangeCXXMethodType(RD, FPT));
+ CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr));
return llvm::Constant::getNullValue(FTy->getPointerTo());
}
llvm::Value *
CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
- llvm::Value *Base, llvm::Value *MemPtr,
+ Address Base, llvm::Value *MemPtr,
const MemberPointerType *MPT) {
ErrorUnsupportedABI(CGF, "loads of member pointers");
- llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())->getPointerTo();
+ llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())
+ ->getPointerTo(Base.getAddressSpace());
return llvm::Constant::getNullValue(Ty);
}
@@ -159,13 +163,24 @@ void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList &params) {
&CGM.getContext().Idents.get("this"),
MD->getThisType(CGM.getContext()));
params.push_back(ThisDecl);
- getThisDecl(CGF) = ThisDecl;
+ CGF.CXXABIThisDecl = ThisDecl;
+
+ // Compute the presumed alignment of 'this', which basically comes
+ // down to whether we know it's a complete object or not.
+ auto &Layout = CGF.getContext().getASTRecordLayout(MD->getParent());
+ if (MD->getParent()->getNumVBases() == 0 || // avoid vcall in common case
+ MD->getParent()->hasAttr<FinalAttr>() ||
+ !isThisCompleteObject(CGF.CurGD)) {
+ CGF.CXXABIThisAlignment = Layout.getAlignment();
+ } else {
+ CGF.CXXABIThisAlignment = Layout.getNonVirtualAlignment();
+ }
}
void CGCXXABI::EmitThisParam(CodeGenFunction &CGF) {
/// Initialize the 'this' slot.
assert(getThisDecl(CGF) && "no 'this' variable for function");
- getThisValue(CGF)
+ CGF.CXXABIThisValue
= CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
"this");
}
@@ -186,14 +201,14 @@ CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) {
return CharUnits::Zero();
}
-llvm::Value *CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
- llvm::Value *NewPtr,
- llvm::Value *NumElements,
- const CXXNewExpr *expr,
- QualType ElementType) {
+Address CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
+ Address NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType) {
// Should never be called.
ErrorUnsupportedABI(CGF, "array cookie initialization");
- return nullptr;
+ return Address::invalid();
}
bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
@@ -215,31 +230,30 @@ bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
return expr->getAllocatedType().isDestructedType();
}
-void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *ptr,
+void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr,
const CXXDeleteExpr *expr, QualType eltTy,
llvm::Value *&numElements,
llvm::Value *&allocPtr, CharUnits &cookieSize) {
// Derive a char* in the same address space as the pointer.
- unsigned AS = ptr->getType()->getPointerAddressSpace();
- llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS);
- ptr = CGF.Builder.CreateBitCast(ptr, charPtrTy);
+ ptr = CGF.Builder.CreateElementBitCast(ptr, CGF.Int8Ty);
// If we don't need an array cookie, bail out early.
if (!requiresArrayCookie(expr, eltTy)) {
- allocPtr = ptr;
+ allocPtr = ptr.getPointer();
numElements = nullptr;
cookieSize = CharUnits::Zero();
return;
}
cookieSize = getArrayCookieSizeImpl(eltTy);
- allocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ptr,
- -cookieSize.getQuantity());
- numElements = readArrayCookieImpl(CGF, allocPtr, cookieSize);
+ Address allocAddr =
+ CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize);
+ allocPtr = allocAddr.getPointer();
+ numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize);
}
llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
- llvm::Value *ptr,
+ Address ptr,
CharUnits cookieSize) {
ErrorUnsupportedABI(CGF, "reading a new[] cookie");
return llvm::ConstantInt::get(CGF.SizeTy, 0);
@@ -308,3 +322,11 @@ CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
// Just call std::terminate and ignore the violating exception.
return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());
}
+
+CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() {
+ return CatchTypeInfo{nullptr, 0};
+}
+
+std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) {
+ return std::vector<CharUnits>();
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
index 436b96a..3f240b1 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCXXABI.h
@@ -37,6 +37,7 @@ class MangleContext;
namespace CodeGen {
class CodeGenFunction;
class CodeGenModule;
+struct CatchTypeInfo;
/// \brief Implements C++ ABI-specific code generation functions.
class CGCXXABI {
@@ -48,12 +49,15 @@ protected:
: CGM(CGM), MangleCtx(CGM.getContext().createMangleContext()) {}
protected:
- ImplicitParamDecl *&getThisDecl(CodeGenFunction &CGF) {
+ ImplicitParamDecl *getThisDecl(CodeGenFunction &CGF) {
return CGF.CXXABIThisDecl;
}
- llvm::Value *&getThisValue(CodeGenFunction &CGF) {
+ llvm::Value *getThisValue(CodeGenFunction &CGF) {
return CGF.CXXABIThisValue;
}
+ Address getThisAddress(CodeGenFunction &CGF) {
+ return Address(CGF.CXXABIThisValue, CGF.CXXABIThisAlignment);
+ }
/// Issue a diagnostic about unsupported features in the ABI.
void ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S);
@@ -77,6 +81,12 @@ protected:
virtual bool requiresArrayCookie(const CXXDeleteExpr *E, QualType eltType);
virtual bool requiresArrayCookie(const CXXNewExpr *E);
+ /// Determine whether there's something special about the rules of
+ /// the ABI tell us that 'this' is a complete object within the
+ /// given function. Obvious common logic like being defined on a
+ /// final class will have been taken care of by the caller.
+ virtual bool isThisCompleteObject(GlobalDecl GD) const = 0;
+
public:
virtual ~CGCXXABI();
@@ -135,13 +145,14 @@ public:
/// pointer. Apply the this-adjustment and set 'This' to the
/// adjusted value.
virtual llvm::Value *EmitLoadOfMemberFunctionPointer(
- CodeGenFunction &CGF, const Expr *E, llvm::Value *&This,
- llvm::Value *MemPtr, const MemberPointerType *MPT);
+ CodeGenFunction &CGF, const Expr *E, Address This,
+ llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr,
+ const MemberPointerType *MPT);
/// Calculate an l-value from an object and a data member pointer.
virtual llvm::Value *
EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
- llvm::Value *Base, llvm::Value *MemPtr,
+ Address Base, llvm::Value *MemPtr,
const MemberPointerType *MPT);
/// Perform a derived-to-base, base-to-derived, or bitcast member
@@ -164,10 +175,6 @@ public:
return true;
}
- virtual bool isTypeInfoCalculable(QualType Ty) const {
- return !Ty->isIncompleteType();
- }
-
/// Create a null member pointer of the given type.
virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
@@ -212,12 +219,17 @@ protected:
public:
virtual void emitVirtualObjectDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *DE,
- llvm::Value *Ptr, QualType ElementType,
+ Address Ptr, QualType ElementType,
const CXXDestructorDecl *Dtor) = 0;
virtual void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) = 0;
virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) = 0;
virtual llvm::GlobalVariable *getThrowInfo(QualType T) { return nullptr; }
+ /// \brief Determine whether it's possible to emit a vtable for \p RD, even
+ /// though we do not know that the vtable has been marked as used by semantic
+ /// analysis.
+ virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const = 0;
+
virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) = 0;
virtual llvm::CallInst *
@@ -225,33 +237,34 @@ public:
llvm::Value *Exn);
virtual llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) = 0;
- virtual llvm::Constant *
+ virtual CatchTypeInfo
getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) = 0;
+ virtual CatchTypeInfo getCatchAllTypeInfo();
virtual bool shouldTypeidBeNullChecked(bool IsDeref,
QualType SrcRecordTy) = 0;
virtual void EmitBadTypeidCall(CodeGenFunction &CGF) = 0;
virtual llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
- llvm::Value *ThisPtr,
+ Address ThisPtr,
llvm::Type *StdTypeInfoPtrTy) = 0;
virtual bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
QualType SrcRecordTy) = 0;
virtual llvm::Value *
- EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
+ EmitDynamicCastCall(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy, QualType DestTy,
QualType DestRecordTy, llvm::BasicBlock *CastEnd) = 0;
virtual llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF,
- llvm::Value *Value,
+ Address Value,
QualType SrcRecordTy,
QualType DestTy) = 0;
virtual bool EmitBadCastCall(CodeGenFunction &CGF) = 0;
virtual llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF,
- llvm::Value *This,
+ Address This,
const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl) = 0;
@@ -294,10 +307,9 @@ public:
/// Perform ABI-specific "this" argument adjustment required prior to
/// a call of a virtual function.
/// The "VirtualCall" argument is true iff the call itself is virtual.
- virtual llvm::Value *
+ virtual Address
adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD,
- llvm::Value *This,
- bool VirtualCall) {
+ Address This, bool VirtualCall) {
return This;
}
@@ -337,19 +349,31 @@ public:
virtual void EmitDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *DD, CXXDtorType Type,
bool ForVirtualBase, bool Delegating,
- llvm::Value *This) = 0;
+ Address This) = 0;
/// Emits the VTable definitions required for the given record type.
virtual void emitVTableDefinitions(CodeGenVTables &CGVT,
const CXXRecordDecl *RD) = 0;
+ /// Checks if ABI requires extra virtual offset for vtable field.
+ virtual bool
+ isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
+ CodeGenFunction::VPtr Vptr) = 0;
+
+ /// Checks if ABI requires to initilize vptrs for given dynamic class.
+ virtual bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) = 0;
+
+ /// Get the address point of the vtable for the given base subobject.
+ virtual llvm::Constant *
+ getVTableAddressPoint(BaseSubobject Base,
+ const CXXRecordDecl *VTableClass) = 0;
+
/// Get the address point of the vtable for the given base subobject while
- /// building a constructor or a destructor. On return, NeedsVirtualOffset
- /// tells if a virtual base adjustment is needed in order to get the offset
- /// of the base subobject.
- virtual llvm::Value *getVTableAddressPointInStructor(
- CodeGenFunction &CGF, const CXXRecordDecl *RD, BaseSubobject Base,
- const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) = 0;
+ /// building a constructor or a destructor.
+ virtual llvm::Value *
+ getVTableAddressPointInStructor(CodeGenFunction &CGF, const CXXRecordDecl *RD,
+ BaseSubobject Base,
+ const CXXRecordDecl *NearestVBase) = 0;
/// Get the address point of the vtable for the given base subobject while
/// building a constexpr.
@@ -365,14 +389,14 @@ public:
/// Build a virtual function pointer in the ABI-specific way.
virtual llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD,
- llvm::Value *This,
+ Address This,
llvm::Type *Ty,
SourceLocation Loc) = 0;
/// Emit the ABI-specific virtual destructor call.
virtual llvm::Value *
EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType, llvm::Value *This,
+ CXXDtorType DtorType, Address This,
const CXXMemberCallExpr *CE) = 0;
virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF,
@@ -388,11 +412,11 @@ public:
GlobalDecl GD, bool ReturnAdjustment) = 0;
virtual llvm::Value *performThisAdjustment(CodeGenFunction &CGF,
- llvm::Value *This,
+ Address This,
const ThisAdjustment &TA) = 0;
virtual llvm::Value *performReturnAdjustment(CodeGenFunction &CGF,
- llvm::Value *Ret,
+ Address Ret,
const ReturnAdjustment &RA) = 0;
virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
@@ -401,6 +425,9 @@ public:
virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
FunctionArgList &Args) const = 0;
+ /// Gets the offsets of all the virtual base pointers in a given class.
+ virtual std::vector<CharUnits> getVBPtrOffsets(const CXXRecordDecl *RD);
+
/// Gets the pure virtual member call function.
virtual StringRef GetPureVirtualCallName() = 0;
@@ -429,11 +456,11 @@ public:
/// always a size_t
/// \param ElementType - the base element allocated type,
/// i.e. the allocated type after stripping all array types
- virtual llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
- llvm::Value *NewPtr,
- llvm::Value *NumElements,
- const CXXNewExpr *expr,
- QualType ElementType);
+ virtual Address InitializeArrayCookie(CodeGenFunction &CGF,
+ Address NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType);
/// Reads the array cookie associated with the given pointer,
/// if it has one.
@@ -448,7 +475,7 @@ public:
/// function
/// \param CookieSize - an out parameter which will be initialized
/// with the size of the cookie, or zero if there is no cookie
- virtual void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
+ virtual void ReadArrayCookie(CodeGenFunction &CGF, Address Ptr,
const CXXDeleteExpr *expr,
QualType ElementType, llvm::Value *&NumElements,
llvm::Value *&AllocPtr, CharUnits &CookieSize);
@@ -471,8 +498,7 @@ protected:
/// Other parameters are as above.
///
/// \return a size_t
- virtual llvm::Value *readArrayCookieImpl(CodeGenFunction &IGF,
- llvm::Value *ptr,
+ virtual llvm::Value *readArrayCookieImpl(CodeGenFunction &IGF, Address ptr,
CharUnits cookieSize);
public:
@@ -512,11 +538,9 @@ public:
/// thread_local variables, a list of functions to perform the
/// initialization.
virtual void EmitThreadLocalInitFuncs(
- CodeGenModule &CGM,
- ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>>
- CXXThreadLocals,
+ CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
ArrayRef<llvm::Function *> CXXThreadLocalInits,
- ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) = 0;
+ ArrayRef<const VarDecl *> CXXThreadLocalInitVars) = 0;
// Determine if references to thread_local global variables can be made
// directly or require access through a thread wrapper function.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
index 0bcf59b..9359850 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
@@ -15,12 +15,14 @@
#include "CGCall.h"
#include "ABIInfo.h"
#include "CGCXXABI.h"
+#include "CGCleanup.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
@@ -91,15 +93,41 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) {
FTNP->getExtInfo(), RequiredArgs(0));
}
+/// Adds the formal paramaters 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) {
+ prefix.append(FPT->param_type_begin(), FPT->param_type_end());
+ return;
+ }
+
+ // In the vast majority 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());
+ for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) {
+ prefix.push_back(FPT->getParamType(I));
+ if (FD->getParamDecl(I)->hasAttr<PassObjectSizeAttr>())
+ prefix.push_back(CGT.getContext().getSizeType());
+ }
+}
+
/// Arrange the LLVM function layout for a value of the given function
/// type, on top of any implicit parameters already stored.
static const CGFunctionInfo &
arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod,
SmallVectorImpl<CanQualType> &prefix,
- CanQual<FunctionProtoType> FTP) {
+ CanQual<FunctionProtoType> FTP,
+ const FunctionDecl *FD) {
RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, prefix.size());
// FIXME: Kill copy.
- prefix.append(FTP->param_type_begin(), FTP->param_type_end());
+ appendParameterTypes(CGT, prefix, FTP, FD);
CanQualType resultType = FTP->getReturnType().getUnqualifiedType();
return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod,
/*chainCall=*/false, prefix,
@@ -109,10 +137,11 @@ arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod,
/// Arrange the argument and result information for a value of the
/// given freestanding function type.
const CGFunctionInfo &
-CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP) {
+CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP,
+ const FunctionDecl *FD) {
SmallVector<CanQualType, 16> argTypes;
return ::arrangeLLVMFunctionInfo(*this, /*instanceMethod=*/false, argTypes,
- FTP);
+ FTP, FD);
}
static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
@@ -155,7 +184,8 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
/// constructor or destructor.
const CGFunctionInfo &
CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
- const FunctionProtoType *FTP) {
+ const FunctionProtoType *FTP,
+ const CXXMethodDecl *MD) {
SmallVector<CanQualType, 16> argTypes;
// Add the 'this' pointer.
@@ -166,7 +196,7 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
return ::arrangeLLVMFunctionInfo(
*this, true, argTypes,
- FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
+ FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>(), MD);
}
/// Arrange the argument and result information for a declaration or
@@ -183,10 +213,10 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) {
if (MD->isInstance()) {
// The abstract case is perfectly fine.
const CXXRecordDecl *ThisType = TheCXXABI.getThisArgumentTypeForMethod(MD);
- return arrangeCXXMethodType(ThisType, prototype.getTypePtr());
+ return arrangeCXXMethodType(ThisType, prototype.getTypePtr(), MD);
}
- return arrangeFreeFunctionType(prototype);
+ return arrangeFreeFunctionType(prototype, MD);
}
const CGFunctionInfo &
@@ -207,7 +237,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
CanQual<FunctionProtoType> FTP = GetFormalType(MD);
// Add the formal parameters.
- argTypes.append(FTP->param_type_begin(), FTP->param_type_end());
+ appendParameterTypes(*this, argTypes, FTP, MD);
TheCXXABI.buildStructorSignature(MD, Type, argTypes);
@@ -273,7 +303,7 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) {
}
assert(isa<FunctionProtoType>(FTy));
- return arrangeFreeFunctionType(FTy.getAs<FunctionProtoType>());
+ return arrangeFreeFunctionType(FTy.getAs<FunctionProtoType>(), FD);
}
/// Arrange the argument and result information for the declaration or
@@ -553,6 +583,7 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC,
FI->HasRegParm = info.getHasRegParm();
FI->RegParm = info.getRegParm();
FI->ArgStruct = nullptr;
+ FI->ArgStructAlign = 0;
FI->NumArgs = argTypes.size();
FI->getArgsBuffer()[0].type = resultType;
for (unsigned i = 0, e = argTypes.size(); i != e; ++i)
@@ -726,6 +757,21 @@ CodeGenTypes::getExpandedTypes(QualType Ty,
}
}
+static void forConstantArrayExpansion(CodeGenFunction &CGF,
+ ConstantArrayExpansion *CAE,
+ Address BaseAddr,
+ llvm::function_ref<void(Address)> Fn) {
+ CharUnits EltSize = CGF.getContext().getTypeSizeInChars(CAE->EltTy);
+ CharUnits EltAlign =
+ BaseAddr.getAlignment().alignmentOfArrayElement(EltSize);
+
+ for (int i = 0, n = CAE->NumElts; i < n; i++) {
+ llvm::Value *EltAddr =
+ CGF.Builder.CreateConstGEP2_32(nullptr, BaseAddr.getPointer(), 0, i);
+ Fn(Address(EltAddr, EltAlign));
+ }
+}
+
void CodeGenFunction::ExpandTypeFromArgs(
QualType Ty, LValue LV, SmallVectorImpl<llvm::Argument *>::iterator &AI) {
assert(LV.isSimple() &&
@@ -733,17 +779,16 @@ void CodeGenFunction::ExpandTypeFromArgs(
auto Exp = getTypeExpansion(Ty, getContext());
if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
- for (int i = 0, n = CAExp->NumElts; i < n; i++) {
- llvm::Value *EltAddr =
- Builder.CreateConstGEP2_32(nullptr, LV.getAddress(), 0, i);
+ forConstantArrayExpansion(*this, CAExp, LV.getAddress(),
+ [&](Address EltAddr) {
LValue LV = MakeAddrLValue(EltAddr, CAExp->EltTy);
ExpandTypeFromArgs(CAExp->EltTy, LV, AI);
- }
+ });
} else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
- llvm::Value *This = LV.getAddress();
+ Address This = LV.getAddress();
for (const CXXBaseSpecifier *BS : RExp->Bases) {
// Perform a single step derived-to-base conversion.
- llvm::Value *Base =
+ Address Base =
GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1,
/*NullCheckValue=*/false, SourceLocation());
LValue SubLV = MakeAddrLValue(Base, BS->getType());
@@ -756,15 +801,10 @@ void CodeGenFunction::ExpandTypeFromArgs(
LValue SubLV = EmitLValueForField(LV, FD);
ExpandTypeFromArgs(FD->getType(), SubLV, AI);
}
- } else if (auto CExp = dyn_cast<ComplexExpansion>(Exp.get())) {
- llvm::Value *RealAddr =
- Builder.CreateStructGEP(nullptr, LV.getAddress(), 0, "real");
- EmitStoreThroughLValue(RValue::get(*AI++),
- MakeAddrLValue(RealAddr, CExp->EltTy));
- llvm::Value *ImagAddr =
- Builder.CreateStructGEP(nullptr, LV.getAddress(), 1, "imag");
- EmitStoreThroughLValue(RValue::get(*AI++),
- MakeAddrLValue(ImagAddr, CExp->EltTy));
+ } else if (isa<ComplexExpansion>(Exp.get())) {
+ auto realValue = *AI++;
+ auto imagValue = *AI++;
+ EmitStoreOfComplex(ComplexPairTy(realValue, imagValue), LV, /*init*/ true);
} else {
assert(isa<NoExpansion>(Exp.get()));
EmitStoreThroughLValue(RValue::get(*AI++), LV);
@@ -776,18 +816,17 @@ void CodeGenFunction::ExpandTypeToArgs(
SmallVectorImpl<llvm::Value *> &IRCallArgs, unsigned &IRCallArgPos) {
auto Exp = getTypeExpansion(Ty, getContext());
if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
- llvm::Value *Addr = RV.getAggregateAddr();
- for (int i = 0, n = CAExp->NumElts; i < n; i++) {
- llvm::Value *EltAddr = Builder.CreateConstGEP2_32(nullptr, Addr, 0, i);
+ forConstantArrayExpansion(*this, CAExp, RV.getAggregateAddress(),
+ [&](Address EltAddr) {
RValue EltRV =
convertTempToRValue(EltAddr, CAExp->EltTy, SourceLocation());
ExpandTypeToArgs(CAExp->EltTy, EltRV, IRFuncTy, IRCallArgs, IRCallArgPos);
- }
+ });
} else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
- llvm::Value *This = RV.getAggregateAddr();
+ Address This = RV.getAggregateAddress();
for (const CXXBaseSpecifier *BS : RExp->Bases) {
// Perform a single step derived-to-base conversion.
- llvm::Value *Base =
+ Address Base =
GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1,
/*NullCheckValue=*/false, SourceLocation());
RValue BaseRV = RValue::getAggregate(Base);
@@ -822,12 +861,22 @@ void CodeGenFunction::ExpandTypeToArgs(
}
}
+/// Create a temporary allocation for the purposes of coercion.
+static Address CreateTempAllocaForCoercion(CodeGenFunction &CGF, llvm::Type *Ty,
+ CharUnits MinAlign) {
+ // Don't use an alignment that's worse than what LLVM would prefer.
+ auto PrefAlign = CGF.CGM.getDataLayout().getPrefTypeAlignment(Ty);
+ CharUnits Align = std::max(MinAlign, CharUnits::fromQuantity(PrefAlign));
+
+ return CGF.CreateTempAlloca(Ty, Align);
+}
+
/// EnterStructPointerForCoercedAccess - Given a struct pointer that we are
/// accessing some number of bytes out of it, try to gep into the struct to get
/// at its inner goodness. Dive as deep as possible without entering an element
/// with an in-memory size smaller than DstSize.
-static llvm::Value *
-EnterStructPointerForCoercedAccess(llvm::Value *SrcPtr,
+static Address
+EnterStructPointerForCoercedAccess(Address SrcPtr,
llvm::StructType *SrcSTy,
uint64_t DstSize, CodeGenFunction &CGF) {
// We can't dive into a zero-element struct.
@@ -846,11 +895,10 @@ EnterStructPointerForCoercedAccess(llvm::Value *SrcPtr,
return SrcPtr;
// GEP into the first element.
- SrcPtr = CGF.Builder.CreateConstGEP2_32(SrcSTy, SrcPtr, 0, 0, "coerce.dive");
+ SrcPtr = CGF.Builder.CreateStructGEP(SrcPtr, 0, CharUnits(), "coerce.dive");
// If the first element is a struct, recurse.
- llvm::Type *SrcTy =
- cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
+ llvm::Type *SrcTy = SrcPtr.getElementType();
if (llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy))
return EnterStructPointerForCoercedAccess(SrcPtr, SrcSTy, DstSize, CGF);
@@ -918,21 +966,19 @@ static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val,
/// This safely handles the case when the src type is smaller than the
/// destination type; in this situation the values of bits which not
/// present in the src are undefined.
-static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
- llvm::Type *Ty, CharUnits SrcAlign,
+static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty,
CodeGenFunction &CGF) {
- llvm::Type *SrcTy =
- cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
+ llvm::Type *SrcTy = Src.getElementType();
// If SrcTy and Ty are the same, just do a load.
if (SrcTy == Ty)
- return CGF.Builder.CreateAlignedLoad(SrcPtr, SrcAlign.getQuantity());
+ return CGF.Builder.CreateLoad(Src);
uint64_t DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
if (llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy)) {
- SrcPtr = EnterStructPointerForCoercedAccess(SrcPtr, SrcSTy, DstSize, CGF);
- SrcTy = cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
+ Src = EnterStructPointerForCoercedAccess(Src, SrcSTy, DstSize, CGF);
+ SrcTy = Src.getType()->getElementType();
}
uint64_t SrcSize = CGF.CGM.getDataLayout().getTypeAllocSize(SrcTy);
@@ -941,8 +987,7 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
// extension or truncation to the desired type.
if ((isa<llvm::IntegerType>(Ty) || isa<llvm::PointerType>(Ty)) &&
(isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy))) {
- llvm::LoadInst *Load =
- CGF.Builder.CreateAlignedLoad(SrcPtr, SrcAlign.getQuantity());
+ llvm::Value *Load = CGF.Builder.CreateLoad(Src);
return CoerceIntOrPtrToIntOrPtr(Load, Ty, CGF);
}
@@ -954,22 +999,18 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
//
// FIXME: Assert that we aren't truncating non-padding bits when have access
// to that information.
- llvm::Value *Casted =
- CGF.Builder.CreateBitCast(SrcPtr, llvm::PointerType::getUnqual(Ty));
- return CGF.Builder.CreateAlignedLoad(Casted, SrcAlign.getQuantity());
- }
-
- // Otherwise do coercion through memory. This is stupid, but
- // simple.
- llvm::AllocaInst *Tmp = CGF.CreateTempAlloca(Ty);
- Tmp->setAlignment(SrcAlign.getQuantity());
- llvm::Type *I8PtrTy = CGF.Builder.getInt8PtrTy();
- llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, I8PtrTy);
- llvm::Value *SrcCasted = CGF.Builder.CreateBitCast(SrcPtr, I8PtrTy);
+ Src = CGF.Builder.CreateBitCast(Src, llvm::PointerType::getUnqual(Ty));
+ return CGF.Builder.CreateLoad(Src);
+ }
+
+ // Otherwise do coercion through memory. This is stupid, but simple.
+ Address Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment());
+ Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.Int8PtrTy);
+ Address SrcCasted = CGF.Builder.CreateBitCast(Src, CGF.Int8PtrTy);
CGF.Builder.CreateMemCpy(Casted, SrcCasted,
llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize),
- SrcAlign.getQuantity(), false);
- return CGF.Builder.CreateAlignedLoad(Tmp, SrcAlign.getQuantity());
+ false);
+ return CGF.Builder.CreateLoad(Tmp);
}
// Function to store a first-class aggregate into memory. We prefer to
@@ -977,8 +1018,7 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
// fast-isel.
// FIXME: Do we need to recurse here?
static void BuildAggStore(CodeGenFunction &CGF, llvm::Value *Val,
- llvm::Value *DestPtr, bool DestIsVolatile,
- CharUnits DestAlign) {
+ Address Dest, bool DestIsVolatile) {
// Prefer scalar stores to first-class aggregate stores.
if (llvm::StructType *STy =
dyn_cast<llvm::StructType>(Val->getType())) {
@@ -986,17 +1026,13 @@ static void BuildAggStore(CodeGenFunction &CGF, llvm::Value *Val,
CGF.CGM.getDataLayout().getStructLayout(STy);
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- llvm::Value *EltPtr = CGF.Builder.CreateConstGEP2_32(STy, DestPtr, 0, i);
+ auto EltOffset = CharUnits::fromQuantity(Layout->getElementOffset(i));
+ Address EltPtr = CGF.Builder.CreateStructGEP(Dest, i, EltOffset);
llvm::Value *Elt = CGF.Builder.CreateExtractValue(Val, i);
- uint64_t EltOffset = Layout->getElementOffset(i);
- CharUnits EltAlign =
- DestAlign.alignmentAtOffset(CharUnits::fromQuantity(EltOffset));
- CGF.Builder.CreateAlignedStore(Elt, EltPtr, EltAlign.getQuantity(),
- DestIsVolatile);
+ CGF.Builder.CreateStore(Elt, EltPtr, DestIsVolatile);
}
} else {
- CGF.Builder.CreateAlignedStore(Val, DestPtr, DestAlign.getQuantity(),
- DestIsVolatile);
+ CGF.Builder.CreateStore(Val, Dest, DestIsVolatile);
}
}
@@ -1007,24 +1043,21 @@ static void BuildAggStore(CodeGenFunction &CGF, llvm::Value *Val,
/// This safely handles the case when the src type is larger than the
/// destination type; the upper bits of the src will be lost.
static void CreateCoercedStore(llvm::Value *Src,
- llvm::Value *DstPtr,
+ Address Dst,
bool DstIsVolatile,
- CharUnits DstAlign,
CodeGenFunction &CGF) {
llvm::Type *SrcTy = Src->getType();
- llvm::Type *DstTy =
- cast<llvm::PointerType>(DstPtr->getType())->getElementType();
+ llvm::Type *DstTy = Dst.getType()->getElementType();
if (SrcTy == DstTy) {
- CGF.Builder.CreateAlignedStore(Src, DstPtr, DstAlign.getQuantity(),
- DstIsVolatile);
+ CGF.Builder.CreateStore(Src, Dst, DstIsVolatile);
return;
}
uint64_t SrcSize = CGF.CGM.getDataLayout().getTypeAllocSize(SrcTy);
if (llvm::StructType *DstSTy = dyn_cast<llvm::StructType>(DstTy)) {
- DstPtr = EnterStructPointerForCoercedAccess(DstPtr, DstSTy, SrcSize, CGF);
- DstTy = cast<llvm::PointerType>(DstPtr->getType())->getElementType();
+ Dst = EnterStructPointerForCoercedAccess(Dst, DstSTy, SrcSize, CGF);
+ DstTy = Dst.getType()->getElementType();
}
// If the source and destination are integer or pointer types, just do an
@@ -1032,8 +1065,7 @@ static void CreateCoercedStore(llvm::Value *Src,
if ((isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy)) &&
(isa<llvm::IntegerType>(DstTy) || isa<llvm::PointerType>(DstTy))) {
Src = CoerceIntOrPtrToIntOrPtr(Src, DstTy, CGF);
- CGF.Builder.CreateAlignedStore(Src, DstPtr, DstAlign.getQuantity(),
- DstIsVolatile);
+ CGF.Builder.CreateStore(Src, Dst, DstIsVolatile);
return;
}
@@ -1041,9 +1073,8 @@ static void CreateCoercedStore(llvm::Value *Src,
// If store is legal, just bitcast the src pointer.
if (SrcSize <= DstSize) {
- llvm::Value *Casted =
- CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy));
- BuildAggStore(CGF, Src, Casted, DstIsVolatile, DstAlign);
+ Dst = CGF.Builder.CreateBitCast(Dst, llvm::PointerType::getUnqual(SrcTy));
+ BuildAggStore(CGF, Src, Dst, DstIsVolatile);
} else {
// Otherwise do coercion through memory. This is stupid, but
// simple.
@@ -1054,16 +1085,25 @@ static void CreateCoercedStore(llvm::Value *Src,
//
// FIXME: Assert that we aren't truncating non-padding bits when have access
// to that information.
- llvm::AllocaInst *Tmp = CGF.CreateTempAlloca(SrcTy);
- Tmp->setAlignment(DstAlign.getQuantity());
- CGF.Builder.CreateAlignedStore(Src, Tmp, DstAlign.getQuantity());
- llvm::Type *I8PtrTy = CGF.Builder.getInt8PtrTy();
- llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, I8PtrTy);
- llvm::Value *DstCasted = CGF.Builder.CreateBitCast(DstPtr, I8PtrTy);
+ Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment());
+ CGF.Builder.CreateStore(Src, Tmp);
+ Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.Int8PtrTy);
+ Address DstCasted = CGF.Builder.CreateBitCast(Dst, CGF.Int8PtrTy);
CGF.Builder.CreateMemCpy(DstCasted, Casted,
llvm::ConstantInt::get(CGF.IntPtrTy, DstSize),
- DstAlign.getQuantity(), false);
+ false);
+ }
+}
+
+static Address emitAddressAtOffset(CodeGenFunction &CGF, Address addr,
+ const ABIArgInfo &info) {
+ if (unsigned offset = info.getDirectOffset()) {
+ addr = CGF.Builder.CreateElementBitCast(addr, CGF.Int8Ty);
+ addr = CGF.Builder.CreateConstInBoundsByteGEP(addr,
+ CharUnits::fromQuantity(offset));
+ addr = CGF.Builder.CreateElementBitCast(addr, info.getCoerceToType());
}
+ return addr;
}
namespace {
@@ -1380,11 +1420,20 @@ llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) {
return GetFunctionType(*Info);
}
-void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
- const Decl *TargetDecl,
- AttributeListType &PAL,
- unsigned &CallingConv,
- bool AttrOnCallSite) {
+static void AddAttributesFromFunctionProtoType(ASTContext &Ctx,
+ llvm::AttrBuilder &FuncAttrs,
+ const FunctionProtoType *FPT) {
+ if (!FPT)
+ return;
+
+ if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
+ FPT->isNothrow(Ctx))
+ FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
+}
+
+void CodeGenModule::ConstructAttributeList(
+ StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo,
+ AttributeListType &PAL, unsigned &CallingConv, bool AttrOnCallSite) {
llvm::AttrBuilder FuncAttrs;
llvm::AttrBuilder RetAttrs;
bool HasOptnone = false;
@@ -1394,6 +1443,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
if (FI.isNoReturn())
FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
+ // If we have information about the function prototype, we can learn
+ // attributes form there.
+ AddAttributesFromFunctionProtoType(getContext(), FuncAttrs,
+ CalleeInfo.getCalleeFunctionProtoType());
+
+ const Decl *TargetDecl = CalleeInfo.getCalleeDecl();
+
// FIXME: handle sseregparm someday...
if (TargetDecl) {
if (TargetDecl->hasAttr<ReturnsTwiceAttr>())
@@ -1406,9 +1462,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate);
if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
- const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>();
- if (FPT && FPT->isNothrow(getContext()))
- FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
+ AddAttributesFromFunctionProtoType(
+ getContext(), FuncAttrs, Fn->getType()->getAs<FunctionProtoType>());
// Don't use [[noreturn]] or _Noreturn for a call to a virtual function.
// These attributes are not inherited by overloads.
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn);
@@ -1416,13 +1471,16 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
}
- // 'const' and 'pure' attribute functions are also nounwind.
+ // 'const', 'pure' and 'noalias' attributed functions are also nounwind.
if (TargetDecl->hasAttr<ConstAttr>()) {
FuncAttrs.addAttribute(llvm::Attribute::ReadNone);
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
} else if (TargetDecl->hasAttr<PureAttr>()) {
FuncAttrs.addAttribute(llvm::Attribute::ReadOnly);
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
+ } else if (TargetDecl->hasAttr<NoAliasAttr>()) {
+ FuncAttrs.addAttribute(llvm::Attribute::ArgMemOnly);
+ FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
}
if (TargetDecl->hasAttr<RestrictAttr>())
RetAttrs.addAttribute(llvm::Attribute::NoAlias);
@@ -1450,7 +1508,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
if (AttrOnCallSite) {
// Attributes that should go on the call site only.
- if (!CodeGenOpts.SimplifyLibCalls)
+ if (!CodeGenOpts.SimplifyLibCalls ||
+ CodeGenOpts.isNoBuiltinFunc(Name.data()))
FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin);
if (!CodeGenOpts.TrapFuncName.empty())
FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName);
@@ -1466,8 +1525,12 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf");
}
+ bool DisableTailCalls =
+ CodeGenOpts.DisableTailCalls ||
+ (TargetDecl && TargetDecl->hasAttr<DisableTailCallsAttr>());
FuncAttrs.addAttribute("disable-tail-calls",
- llvm::toStringRef(CodeGenOpts.DisableTailCalls));
+ llvm::toStringRef(DisableTailCalls));
+
FuncAttrs.addAttribute("less-precise-fpmad",
llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD));
FuncAttrs.addAttribute("no-infs-fp-math",
@@ -1481,77 +1544,53 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
FuncAttrs.addAttribute("stack-protector-buffer-size",
llvm::utostr(CodeGenOpts.SSPBufferSize));
- if (!CodeGenOpts.StackRealignment)
- FuncAttrs.addAttribute("no-realign-stack");
+ 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.
StringRef TargetCPU = getTarget().getTargetOpts().CPU;
-
- // TODO: Features gets us the features on the command line including
- // feature dependencies. For canonicalization purposes we might want to
- // avoid putting features in the target-features set if we know it'll be
- // one of the default features in the backend, e.g. corei7-avx and +avx or
- // figure out non-explicit dependencies.
- // Canonicalize the existing features in a new feature map.
- // TODO: Migrate the existing backends to keep the map around rather than
- // the vector.
- llvm::StringMap<bool> FeatureMap;
- for (auto F : getTarget().getTargetOpts().Features) {
- const char *Name = F.c_str();
- bool Enabled = Name[0] == '+';
- getTarget().setFeatureEnabled(FeatureMap, Name + 1, Enabled);
- }
-
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl);
- if (FD) {
- if (const auto *TD = FD->getAttr<TargetAttr>()) {
- StringRef FeaturesStr = TD->getFeatures();
- SmallVector<StringRef, 1> AttrFeatures;
- FeaturesStr.split(AttrFeatures, ",");
-
- // Grab the various features and prepend a "+" to turn on the feature to
- // the backend and add them to our existing set of features.
- for (auto &Feature : AttrFeatures) {
- // Go ahead and trim whitespace rather than either erroring or
- // accepting it weirdly.
- Feature = Feature.trim();
-
- // While we're here iterating check for a different target cpu.
- if (Feature.startswith("arch="))
- TargetCPU = Feature.split("=").second.trim();
- else if (Feature.startswith("tune="))
- // We don't support cpu tuning this way currently.
- ;
- else if (Feature.startswith("fpmath="))
- // TODO: Support the fpmath option this way. It will require checking
- // overall feature validity for the function with the rest of the
- // attributes on the function.
- ;
- else if (Feature.startswith("mno-"))
- getTarget().setFeatureEnabled(FeatureMap, Feature.split("-").second,
- false);
- else
- getTarget().setFeatureEnabled(FeatureMap, Feature, true);
- }
+ if (FD && FD->hasAttr<TargetAttr>()) {
+ llvm::StringMap<bool> FeatureMap;
+ getFunctionFeatureMap(FeatureMap, FD);
+
+ // Produce the canonical string for this set of features.
+ std::vector<std::string> Features;
+ for (llvm::StringMap<bool>::const_iterator it = FeatureMap.begin(),
+ ie = FeatureMap.end();
+ it != ie; ++it)
+ Features.push_back((it->second ? "+" : "-") + it->first().str());
+
+ // Now add the target-cpu and target-features to the function.
+ // While we populated the feature map above, we still need to
+ // get and parse the target attribute so we can get the cpu for
+ // the function.
+ const auto *TD = FD->getAttr<TargetAttr>();
+ TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse();
+ if (ParsedAttr.second != "")
+ TargetCPU = ParsedAttr.second;
+ if (TargetCPU != "")
+ FuncAttrs.addAttribute("target-cpu", TargetCPU);
+ if (!Features.empty()) {
+ std::sort(Features.begin(), Features.end());
+ FuncAttrs.addAttribute(
+ "target-features",
+ llvm::join(Features.begin(), Features.end(), ","));
+ }
+ } else {
+ // Otherwise just add the existing target cpu and target features to the
+ // function.
+ std::vector<std::string> &Features = getTarget().getTargetOpts().Features;
+ if (TargetCPU != "")
+ FuncAttrs.addAttribute("target-cpu", TargetCPU);
+ if (!Features.empty()) {
+ std::sort(Features.begin(), Features.end());
+ FuncAttrs.addAttribute(
+ "target-features",
+ llvm::join(Features.begin(), Features.end(), ","));
}
- }
-
- // Produce the canonical string for this set of features.
- std::vector<std::string> Features;
- for (llvm::StringMap<bool>::const_iterator it = FeatureMap.begin(),
- ie = FeatureMap.end();
- it != ie; ++it)
- Features.push_back((it->second ? "+" : "-") + it->first().str());
-
- // Now add the target-cpu and target-features to the function.
- if (TargetCPU != "")
- FuncAttrs.addAttribute("target-cpu", TargetCPU);
- if (!Features.empty()) {
- std::sort(Features.begin(), Features.end());
- FuncAttrs.addAttribute("target-features",
- llvm::join(Features.begin(), Features.end(), ","));
}
}
@@ -1655,20 +1694,37 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
Attrs.addAttribute(llvm::Attribute::InReg);
break;
- case ABIArgInfo::Indirect:
+ case ABIArgInfo::Indirect: {
if (AI.getInReg())
Attrs.addAttribute(llvm::Attribute::InReg);
if (AI.getIndirectByVal())
Attrs.addAttribute(llvm::Attribute::ByVal);
- Attrs.addAlignmentAttr(AI.getIndirectAlign());
+ CharUnits Align = AI.getIndirectAlign();
+
+ // In a byval argument, it is important that the required
+ // alignment of the type is honored, as LLVM might be creating a
+ // *new* stack object, and needs to know what alignment to give
+ // it. (Sometimes it can deduce a sensible alignment on its own,
+ // but not if clang decides it must emit a packed struct, or the
+ // user specifies increased alignment requirements.)
+ //
+ // This is different from indirect *not* byval, where the object
+ // exists already, and the align attribute is purely
+ // informative.
+ assert(!Align.isZero());
+
+ // For now, only add this when we have a byval argument.
+ // TODO: be less lazy about updating test cases.
+ if (AI.getIndirectByVal())
+ Attrs.addAlignmentAttr(Align.getQuantity());
// byval disables readnone and readonly.
FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly)
.removeAttribute(llvm::Attribute::ReadNone);
break;
-
+ }
case ABIArgInfo::Ignore:
case ABIArgInfo::Expand:
continue;
@@ -1788,10 +1844,14 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// If we're using inalloca, all the memory arguments are GEPs off of the last
// parameter, which is a pointer to the complete memory area.
- llvm::Value *ArgStruct = nullptr;
+ Address ArgStruct = Address::invalid();
+ const llvm::StructLayout *ArgStructLayout = nullptr;
if (IRFunctionArgs.hasInallocaArg()) {
- ArgStruct = FnArgs[IRFunctionArgs.getInallocaArgNo()];
- assert(ArgStruct->getType() == FI.getArgStruct()->getPointerTo());
+ ArgStructLayout = CGM.getDataLayout().getStructLayout(FI.getArgStruct());
+ ArgStruct = Address(FnArgs[IRFunctionArgs.getInallocaArgNo()],
+ FI.getArgStructAlignment());
+
+ assert(ArgStruct.getType() == FI.getArgStruct()->getPointerTo());
}
// Name the struct return parameter.
@@ -1805,9 +1865,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// Track if we received the parameter as a pointer (indirect, byval, or
// inalloca). If already have a pointer, EmitParmDecl doesn't need to copy it
// into a local alloca for us.
- enum ValOrPointer { HaveValue = 0, HavePointer = 1 };
- typedef llvm::PointerIntPair<llvm::Value *, 1> ValueAndIsPtr;
- SmallVector<ValueAndIsPtr, 16> ArgVals;
+ SmallVector<ParamValue, 16> ArgVals;
ArgVals.reserve(Args.size());
// Create a pointer value for every parameter declaration. This usually
@@ -1833,49 +1891,47 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
switch (ArgI.getKind()) {
case ABIArgInfo::InAlloca: {
assert(NumIRArgs == 0);
- llvm::Value *V =
- Builder.CreateStructGEP(FI.getArgStruct(), ArgStruct,
- ArgI.getInAllocaFieldIndex(), Arg->getName());
- ArgVals.push_back(ValueAndIsPtr(V, HavePointer));
+ auto FieldIndex = ArgI.getInAllocaFieldIndex();
+ CharUnits FieldOffset =
+ CharUnits::fromQuantity(ArgStructLayout->getElementOffset(FieldIndex));
+ Address V = Builder.CreateStructGEP(ArgStruct, FieldIndex, FieldOffset,
+ Arg->getName());
+ ArgVals.push_back(ParamValue::forIndirect(V));
break;
}
case ABIArgInfo::Indirect: {
assert(NumIRArgs == 1);
- llvm::Value *V = FnArgs[FirstIRArg];
+ Address ParamAddr = Address(FnArgs[FirstIRArg], ArgI.getIndirectAlign());
if (!hasScalarEvaluationKind(Ty)) {
// Aggregates and complex variables are accessed by reference. All we
- // need to do is realign the value, if requested
+ // need to do is realign the value, if requested.
+ Address V = ParamAddr;
if (ArgI.getIndirectRealign()) {
- llvm::Value *AlignedTemp = CreateMemTemp(Ty, "coerce");
+ Address AlignedTemp = CreateMemTemp(Ty, "coerce");
// Copy from the incoming argument pointer to the temporary with the
// appropriate alignment.
//
// FIXME: We should have a common utility for generating an aggregate
// copy.
- llvm::Type *I8PtrTy = Builder.getInt8PtrTy();
CharUnits Size = getContext().getTypeSizeInChars(Ty);
- llvm::Value *Dst = Builder.CreateBitCast(AlignedTemp, I8PtrTy);
- llvm::Value *Src = Builder.CreateBitCast(V, I8PtrTy);
- Builder.CreateMemCpy(Dst,
- Src,
- llvm::ConstantInt::get(IntPtrTy,
- Size.getQuantity()),
- ArgI.getIndirectAlign(),
- false);
+ auto SizeVal = llvm::ConstantInt::get(IntPtrTy, Size.getQuantity());
+ Address Dst = Builder.CreateBitCast(AlignedTemp, Int8PtrTy);
+ Address Src = Builder.CreateBitCast(ParamAddr, Int8PtrTy);
+ Builder.CreateMemCpy(Dst, Src, SizeVal, false);
V = AlignedTemp;
}
- ArgVals.push_back(ValueAndIsPtr(V, HavePointer));
+ ArgVals.push_back(ParamValue::forIndirect(V));
} else {
// Load scalar value from indirect argument.
- V = EmitLoadOfScalar(V, false, ArgI.getIndirectAlign(), Ty,
- Arg->getLocStart());
+ llvm::Value *V =
+ EmitLoadOfScalar(ParamAddr, false, Ty, Arg->getLocStart());
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
- ArgVals.push_back(ValueAndIsPtr(V, HaveValue));
+ ArgVals.push_back(ParamValue::forDirect(V));
}
break;
}
@@ -1980,87 +2036,66 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (V->getType() != LTy)
V = Builder.CreateBitCast(V, LTy);
- ArgVals.push_back(ValueAndIsPtr(V, HaveValue));
+ ArgVals.push_back(ParamValue::forDirect(V));
break;
}
- llvm::AllocaInst *Alloca = CreateMemTemp(Ty, Arg->getName());
-
- // The alignment we need to use is the max of the requested alignment for
- // the argument plus the alignment required by our access code below.
- unsigned AlignmentToUse =
- CGM.getDataLayout().getABITypeAlignment(ArgI.getCoerceToType());
- AlignmentToUse = std::max(AlignmentToUse,
- (unsigned)getContext().getDeclAlign(Arg).getQuantity());
+ Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg),
+ Arg->getName());
- Alloca->setAlignment(AlignmentToUse);
- llvm::Value *V = Alloca;
- llvm::Value *Ptr = V; // Pointer to store into.
- CharUnits PtrAlign = CharUnits::fromQuantity(AlignmentToUse);
-
- // If the value is offset in memory, apply the offset now.
- if (unsigned Offs = ArgI.getDirectOffset()) {
- Ptr = Builder.CreateBitCast(Ptr, Builder.getInt8PtrTy());
- Ptr = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), Ptr, Offs);
- Ptr = Builder.CreateBitCast(Ptr,
- llvm::PointerType::getUnqual(ArgI.getCoerceToType()));
- PtrAlign = PtrAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs));
- }
+ // Pointer to store into.
+ Address Ptr = emitAddressAtOffset(*this, Alloca, ArgI);
// Fast-isel and the optimizer generally like scalar values better than
// FCAs, so we flatten them if this is safe to do for this argument.
llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
if (ArgI.isDirect() && ArgI.getCanBeFlattened() && STy &&
STy->getNumElements() > 1) {
+ auto SrcLayout = CGM.getDataLayout().getStructLayout(STy);
uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(STy);
- llvm::Type *DstTy =
- cast<llvm::PointerType>(Ptr->getType())->getElementType();
+ llvm::Type *DstTy = Ptr.getElementType();
uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(DstTy);
+ Address AddrToStoreInto = Address::invalid();
if (SrcSize <= DstSize) {
- Ptr = Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy));
-
- assert(STy->getNumElements() == NumIRArgs);
- for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- auto AI = FnArgs[FirstIRArg + i];
- AI->setName(Arg->getName() + ".coerce" + Twine(i));
- llvm::Value *EltPtr = Builder.CreateConstGEP2_32(STy, Ptr, 0, i);
- Builder.CreateStore(AI, EltPtr);
- }
+ AddrToStoreInto =
+ Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy));
} else {
- llvm::AllocaInst *TempAlloca =
- CreateTempAlloca(ArgI.getCoerceToType(), "coerce");
- TempAlloca->setAlignment(AlignmentToUse);
- llvm::Value *TempV = TempAlloca;
-
- assert(STy->getNumElements() == NumIRArgs);
- for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- auto AI = FnArgs[FirstIRArg + i];
- AI->setName(Arg->getName() + ".coerce" + Twine(i));
- llvm::Value *EltPtr =
- Builder.CreateConstGEP2_32(ArgI.getCoerceToType(), TempV, 0, i);
- Builder.CreateStore(AI, EltPtr);
- }
+ AddrToStoreInto =
+ CreateTempAlloca(STy, Alloca.getAlignment(), "coerce");
+ }
- Builder.CreateMemCpy(Ptr, TempV, DstSize, AlignmentToUse);
+ assert(STy->getNumElements() == NumIRArgs);
+ for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+ auto AI = FnArgs[FirstIRArg + i];
+ AI->setName(Arg->getName() + ".coerce" + Twine(i));
+ auto Offset = CharUnits::fromQuantity(SrcLayout->getElementOffset(i));
+ Address EltPtr =
+ Builder.CreateStructGEP(AddrToStoreInto, i, Offset);
+ Builder.CreateStore(AI, EltPtr);
+ }
+
+ if (SrcSize > DstSize) {
+ Builder.CreateMemCpy(Ptr, AddrToStoreInto, DstSize);
}
+
} else {
// Simple case, just do a coerced store of the argument into the alloca.
assert(NumIRArgs == 1);
auto AI = FnArgs[FirstIRArg];
AI->setName(Arg->getName() + ".coerce");
- CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, PtrAlign, *this);
+ CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, *this);
}
-
// Match to what EmitParmDecl is expecting for this type.
if (CodeGenFunction::hasScalarEvaluationKind(Ty)) {
- V = EmitLoadOfScalar(V, false, AlignmentToUse, Ty, Arg->getLocStart());
+ llvm::Value *V =
+ EmitLoadOfScalar(Alloca, false, Ty, Arg->getLocStart());
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
- ArgVals.push_back(ValueAndIsPtr(V, HaveValue));
+ ArgVals.push_back(ParamValue::forDirect(V));
} else {
- ArgVals.push_back(ValueAndIsPtr(V, HavePointer));
+ ArgVals.push_back(ParamValue::forIndirect(Alloca));
}
break;
}
@@ -2069,11 +2104,9 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// If this structure was expanded into multiple arguments then
// we need to create a temporary and reconstruct it from the
// arguments.
- llvm::AllocaInst *Alloca = CreateMemTemp(Ty);
- CharUnits Align = getContext().getDeclAlign(Arg);
- Alloca->setAlignment(Align.getQuantity());
- LValue LV = MakeAddrLValue(Alloca, Ty, Align);
- ArgVals.push_back(ValueAndIsPtr(Alloca, HavePointer));
+ Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg));
+ LValue LV = MakeAddrLValue(Alloca, Ty);
+ ArgVals.push_back(ParamValue::forIndirect(Alloca));
auto FnArgIter = FnArgs.begin() + FirstIRArg;
ExpandTypeFromArgs(Ty, LV, FnArgIter);
@@ -2089,10 +2122,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
assert(NumIRArgs == 0);
// Initialize the local variable appropriately.
if (!hasScalarEvaluationKind(Ty)) {
- ArgVals.push_back(ValueAndIsPtr(CreateMemTemp(Ty), HavePointer));
+ ArgVals.push_back(ParamValue::forIndirect(CreateMemTemp(Ty)));
} else {
llvm::Value *U = llvm::UndefValue::get(ConvertType(Arg->getType()));
- ArgVals.push_back(ValueAndIsPtr(U, HaveValue));
+ ArgVals.push_back(ParamValue::forDirect(U));
}
break;
}
@@ -2100,12 +2133,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
for (int I = Args.size() - 1; I >= 0; --I)
- EmitParmDecl(*Args[I], ArgVals[I].getPointer(), ArgVals[I].getInt(),
- I + 1);
+ EmitParmDecl(*Args[I], ArgVals[I], I + 1);
} else {
for (unsigned I = 0, E = Args.size(); I != E; ++I)
- EmitParmDecl(*Args[I], ArgVals[I].getPointer(), ArgVals[I].getInt(),
- I + 1);
+ EmitParmDecl(*Args[I], ArgVals[I], I + 1);
}
}
@@ -2158,9 +2189,9 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
bool doRetainAutorelease;
- if (call->getCalledValue() == CGF.CGM.getARCEntrypoints().objc_retain) {
+ if (call->getCalledValue() == CGF.CGM.getObjCEntrypoints().objc_retain) {
doRetainAutorelease = true;
- } else if (call->getCalledValue() == CGF.CGM.getARCEntrypoints()
+ } else if (call->getCalledValue() == CGF.CGM.getObjCEntrypoints()
.objc_retainAutoreleasedReturnValue) {
doRetainAutorelease = false;
@@ -2169,7 +2200,7 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
// for that call. If we can't find it, we can't do this
// optimization. But it should always be the immediately previous
// instruction, unless we needed bitcasts around the call.
- if (CGF.CGM.getARCEntrypoints().retainAutoreleasedReturnValueMarker) {
+ if (CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker) {
llvm::Instruction *prev = call->getPrevNode();
assert(prev);
if (isa<llvm::BitCastInst>(prev)) {
@@ -2178,7 +2209,7 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
}
assert(isa<llvm::CallInst>(prev));
assert(cast<llvm::CallInst>(prev)->getCalledValue() ==
- CGF.CGM.getARCEntrypoints().retainAutoreleasedReturnValueMarker);
+ CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker);
insnsToKill.push_back(prev);
}
} else {
@@ -2223,7 +2254,7 @@ static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF,
llvm::CallInst *retainCall =
dyn_cast<llvm::CallInst>(result->stripPointerCasts());
if (!retainCall ||
- retainCall->getCalledValue() != CGF.CGM.getARCEntrypoints().objc_retain)
+ retainCall->getCalledValue() != CGF.CGM.getObjCEntrypoints().objc_retain)
return nullptr;
// Look for an ordinary load of 'self'.
@@ -2231,7 +2262,7 @@ static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF,
llvm::LoadInst *load =
dyn_cast<llvm::LoadInst>(retainedValue->stripPointerCasts());
if (!load || load->isAtomic() || load->isVolatile() ||
- load->getPointerOperand() != CGF.GetAddrOfLocalVar(self))
+ load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getPointer())
return nullptr;
// Okay! Burn it all down. This relies for correctness on the
@@ -2268,11 +2299,23 @@ static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF,
/// Heuristically search for a dominating store to the return-value slot.
static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) {
+ // Check if a User is a store which pointerOperand is the ReturnValue.
+ // We are looking for stores to the ReturnValue, not for stores of the
+ // ReturnValue to some other location.
+ auto GetStoreIfValid = [&CGF](llvm::User *U) -> llvm::StoreInst * {
+ auto *SI = dyn_cast<llvm::StoreInst>(U);
+ if (!SI || SI->getPointerOperand() != CGF.ReturnValue.getPointer())
+ return nullptr;
+ // These aren't actually possible for non-coerced returns, and we
+ // only care about non-coerced returns on this code path.
+ assert(!SI->isAtomic() && !SI->isVolatile());
+ return SI;
+ };
// If there are multiple uses of the return-value slot, just check
// for something immediately preceding the IP. Sometimes this can
// happen with how we generate implicit-returns; it can also happen
// with noreturn cleanups.
- if (!CGF.ReturnValue->hasOneUse()) {
+ if (!CGF.ReturnValue.getPointer()->hasOneUse()) {
llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock();
if (IP->empty()) return nullptr;
llvm::Instruction *I = &IP->back();
@@ -2296,21 +2339,13 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) {
break;
}
- llvm::StoreInst *store = dyn_cast<llvm::StoreInst>(I);
- if (!store) return nullptr;
- if (store->getPointerOperand() != CGF.ReturnValue) return nullptr;
- assert(!store->isAtomic() && !store->isVolatile()); // see below
- return store;
+ return GetStoreIfValid(I);
}
llvm::StoreInst *store =
- dyn_cast<llvm::StoreInst>(CGF.ReturnValue->user_back());
+ GetStoreIfValid(CGF.ReturnValue.getPointer()->user_back());
if (!store) return nullptr;
- // These aren't actually possible for non-coerced returns, and we
- // only care about non-coerced returns on this code path.
- assert(!store->isAtomic() && !store->isVolatile());
-
// Now do a first-and-dirty dominance check: just walk up the
// single-predecessors chain from the current insertion point.
llvm::BasicBlock *StoreBB = store->getParent();
@@ -2335,7 +2370,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
}
// Functions with no result always return void.
- if (!ReturnValue) {
+ if (!ReturnValue.isValid()) {
Builder.CreateRetVoid();
return;
}
@@ -2353,10 +2388,10 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
if (RetAI.getInAllocaSRet()) {
llvm::Function::arg_iterator EI = CurFn->arg_end();
--EI;
- llvm::Value *ArgStruct = EI;
+ llvm::Value *ArgStruct = &*EI;
llvm::Value *SRet = Builder.CreateStructGEP(
nullptr, ArgStruct, RetAI.getInAllocaFieldIndex());
- RV = Builder.CreateLoad(SRet, "sret");
+ RV = Builder.CreateAlignedLoad(SRet, getPointerAlign(), "sret");
}
break;
@@ -2367,9 +2402,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
switch (getEvaluationKind(RetTy)) {
case TEK_Complex: {
ComplexPairTy RT =
- EmitLoadOfComplex(MakeNaturalAlignAddrLValue(ReturnValue, RetTy),
- EndLoc);
- EmitStoreOfComplex(RT, MakeNaturalAlignAddrLValue(AI, RetTy),
+ EmitLoadOfComplex(MakeAddrLValue(ReturnValue, RetTy), EndLoc);
+ EmitStoreOfComplex(RT, MakeNaturalAlignAddrLValue(&*AI, RetTy),
/*isInit*/ true);
break;
}
@@ -2378,7 +2412,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
break;
case TEK_Scalar:
EmitStoreOfScalar(Builder.CreateLoad(ReturnValue),
- MakeNaturalAlignAddrLValue(AI, RetTy),
+ MakeNaturalAlignAddrLValue(&*AI, RetTy),
/*isInit*/ true);
break;
}
@@ -2406,9 +2440,12 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
SI->eraseFromParent();
// If that was the only use of the return value, nuke it as well now.
- if (ReturnValue->use_empty() && isa<llvm::AllocaInst>(ReturnValue)) {
- cast<llvm::AllocaInst>(ReturnValue)->eraseFromParent();
- ReturnValue = nullptr;
+ auto returnValueInst = ReturnValue.getPointer();
+ if (returnValueInst->use_empty()) {
+ if (auto alloca = dyn_cast<llvm::AllocaInst>(returnValueInst)) {
+ alloca->eraseFromParent();
+ ReturnValue = Address::invalid();
+ }
}
// Otherwise, we have to do a simple load.
@@ -2416,18 +2453,10 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
RV = Builder.CreateLoad(ReturnValue);
}
} else {
- llvm::Value *V = ReturnValue;
- CharUnits Align = getContext().getTypeAlignInChars(RetTy);
// If the value is offset in memory, apply the offset now.
- if (unsigned Offs = RetAI.getDirectOffset()) {
- V = Builder.CreateBitCast(V, Builder.getInt8PtrTy());
- V = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), V, Offs);
- V = Builder.CreateBitCast(V,
- llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
- Align = Align.alignmentAtOffset(CharUnits::fromQuantity(Offs));
- }
+ Address V = emitAddressAtOffset(*this, ReturnValue, RetAI);
- RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), Align, *this);
+ RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this);
}
// In ARC, end functions that return a retainable type with a call
@@ -2450,8 +2479,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
llvm::Instruction *Ret;
if (RV) {
- if (SanOpts.has(SanitizerKind::ReturnsNonnullAttribute)) {
- if (auto RetNNAttr = CurGD.getDecl()->getAttr<ReturnsNonNullAttr>()) {
+ 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()));
@@ -2477,14 +2506,20 @@ static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) {
return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
}
-static AggValueSlot createPlaceholderSlot(CodeGenFunction &CGF, QualType Ty) {
+static AggValueSlot createPlaceholderSlot(CodeGenFunction &CGF,
+ QualType Ty) {
// 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.CreateLoad(Placeholder);
- return AggValueSlot::forAddr(Placeholder, CharUnits::Zero(),
+ llvm::UndefValue::get(IRTy->getPointerTo()->getPointerTo());
+ Placeholder = CGF.Builder.CreateDefaultAlignedLoad(Placeholder);
+
+ // FIXME: When we generate this IR in one pass, we shouldn't need
+ // this win32-specific alignment hack.
+ CharUnits Align = CharUnits::fromQuantity(4);
+
+ return AggValueSlot::forAddr(Address(Placeholder, Align),
Ty.getQualifiers(),
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
@@ -2497,7 +2532,7 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
// StartFunction converted the ABI-lowered parameter(s) into a
// local alloca. We need to turn that into an r-value suitable
// for EmitCall.
- llvm::Value *local = GetAddrOfLocalVar(param);
+ Address local = GetAddrOfLocalVar(param);
QualType type = param->getType();
@@ -2532,20 +2567,21 @@ static bool isProvablyNonNull(llvm::Value *addr) {
static void emitWriteback(CodeGenFunction &CGF,
const CallArgList::Writeback &writeback) {
const LValue &srcLV = writeback.Source;
- llvm::Value *srcAddr = srcLV.getAddress();
- assert(!isProvablyNull(srcAddr) &&
+ Address srcAddr = srcLV.getAddress();
+ assert(!isProvablyNull(srcAddr.getPointer()) &&
"shouldn't have writeback for provably null argument");
llvm::BasicBlock *contBB = nullptr;
// If the argument wasn't provably non-null, we need to null check
// before doing the store.
- bool provablyNonNull = isProvablyNonNull(srcAddr);
+ bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer());
if (!provablyNonNull) {
llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback");
contBB = CGF.createBasicBlock("icr.done");
- llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull");
+ llvm::Value *isNull =
+ CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull");
CGF.Builder.CreateCondBr(isNull, contBB, writebackBB);
CGF.EmitBlock(writebackBB);
}
@@ -2554,9 +2590,8 @@ static void emitWriteback(CodeGenFunction &CGF,
llvm::Value *value = CGF.Builder.CreateLoad(writeback.Temporary);
// Cast it back, in case we're writing an id to a Foo* or something.
- value = CGF.Builder.CreateBitCast(value,
- cast<llvm::PointerType>(srcAddr->getType())->getElementType(),
- "icr.writeback-cast");
+ value = CGF.Builder.CreateBitCast(value, srcAddr.getElementType(),
+ "icr.writeback-cast");
// Perform the writeback.
@@ -2606,10 +2641,9 @@ static void deactivateArgCleanupsBeforeCall(CodeGenFunction &CGF,
ArrayRef<CallArgList::CallArgCleanup> Cleanups =
CallArgs.getCleanupsToDeactivate();
// Iterate in reverse to increase the likelihood of popping the cleanup.
- for (ArrayRef<CallArgList::CallArgCleanup>::reverse_iterator
- I = Cleanups.rbegin(), E = Cleanups.rend(); I != E; ++I) {
- CGF.DeactivateCleanupBlock(I->Cleanup, I->IsActiveIP);
- I->IsActiveIP->eraseFromParent();
+ for (const auto &I : llvm::reverse(Cleanups)) {
+ CGF.DeactivateCleanupBlock(I.Cleanup, I.IsActiveIP);
+ I.IsActiveIP->eraseFromParent();
}
}
@@ -2621,7 +2655,9 @@ static const Expr *maybeGetUnaryAddrOfOperand(const Expr *E) {
}
/// Emit an argument that's being passed call-by-writeback. That is,
-/// we are passing the address of
+/// we are passing the address of an __autoreleased temporary; it
+/// might be copy-initialized with the current value of the given
+/// address, but it will definitely be copied out of after the call.
static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
const ObjCIndirectCopyRestoreExpr *CRE) {
LValue srcLV;
@@ -2633,13 +2669,13 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
// Otherwise, just emit it as a scalar.
} else {
- llvm::Value *srcAddr = CGF.EmitScalarExpr(CRE->getSubExpr());
+ Address srcAddr = CGF.EmitPointerWithAlignment(CRE->getSubExpr());
QualType srcAddrType =
CRE->getSubExpr()->getType()->castAs<PointerType>()->getPointeeType();
- srcLV = CGF.MakeNaturalAlignAddrLValue(srcAddr, srcAddrType);
+ srcLV = CGF.MakeAddrLValue(srcAddr, srcAddrType);
}
- llvm::Value *srcAddr = srcLV.getAddress();
+ Address srcAddr = srcLV.getAddress();
// The dest and src types don't necessarily match in LLVM terms
// because of the crazy ObjC compatibility rules.
@@ -2648,15 +2684,16 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
cast<llvm::PointerType>(CGF.ConvertType(CRE->getType()));
// If the address is a constant null, just pass the appropriate null.
- if (isProvablyNull(srcAddr)) {
+ if (isProvablyNull(srcAddr.getPointer())) {
args.add(RValue::get(llvm::ConstantPointerNull::get(destType)),
CRE->getType());
return;
}
// Create the temporary.
- llvm::Value *temp = CGF.CreateTempAlloca(destType->getElementType(),
- "icr.temp");
+ Address temp = CGF.CreateTempAlloca(destType->getElementType(),
+ CGF.getPointerAlign(),
+ "icr.temp");
// Loading an l-value can introduce a cleanup if the l-value is __weak,
// and that cleanup will be conditional if we can't prove that the l-value
// isn't null, so we need to register a dominating point so that the cleanups
@@ -2678,15 +2715,16 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
// If the address is *not* known to be non-null, we need to switch.
llvm::Value *finalArgument;
- bool provablyNonNull = isProvablyNonNull(srcAddr);
+ bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer());
if (provablyNonNull) {
- finalArgument = temp;
+ finalArgument = temp.getPointer();
} else {
- llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull");
+ llvm::Value *isNull =
+ CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull");
finalArgument = CGF.Builder.CreateSelect(isNull,
llvm::ConstantPointerNull::get(destType),
- temp, "icr.argument");
+ temp.getPointer(), "icr.argument");
// If we need to copy, then the load has to be conditional, which
// means we need control flow.
@@ -2753,24 +2791,12 @@ void CallArgList::allocateArgumentMemory(CodeGenFunction &CGF) {
// Save the stack.
llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stacksave);
StackBase = CGF.Builder.CreateCall(F, {}, "inalloca.save");
-
- // Control gets really tied up in landing pads, so we have to spill the
- // stacksave to an alloca to avoid violating SSA form.
- // TODO: This is dead if we never emit the cleanup. We should create the
- // alloca and store lazily on the first cleanup emission.
- StackBaseMem = CGF.CreateTempAlloca(CGF.Int8PtrTy, "inalloca.spmem");
- CGF.Builder.CreateStore(StackBase, StackBaseMem);
- CGF.pushStackRestore(EHCleanup, StackBaseMem);
- StackCleanup = CGF.EHStack.getInnermostEHScope();
- assert(StackCleanup.isValid());
}
void CallArgList::freeArgumentMemory(CodeGenFunction &CGF) const {
if (StackBase) {
- CGF.DeactivateCleanupBlock(StackCleanup, StackBase);
+ // Restore the stack after the call.
llvm::Value *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
- // We could load StackBase from StackBaseMem, but in the non-exceptional
- // case we can skip it.
CGF.Builder.CreateCall(F, StackBase);
}
}
@@ -2800,12 +2826,26 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
"nonnull_arg", StaticData, None);
}
-void CodeGenFunction::EmitCallArgs(CallArgList &Args,
- ArrayRef<QualType> ArgTypes,
- CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd,
- const FunctionDecl *CalleeDecl,
- unsigned ParamsToSkip) {
+void CodeGenFunction::EmitCallArgs(
+ CallArgList &Args, ArrayRef<QualType> ArgTypes,
+ llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
+ const FunctionDecl *CalleeDecl, unsigned ParamsToSkip) {
+ assert((int)ArgTypes.size() == (ArgRange.end() - ArgRange.begin()));
+
+ auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg) {
+ if (CalleeDecl == nullptr || I >= CalleeDecl->getNumParams())
+ return;
+ auto *PS = CalleeDecl->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);
+ Args.add(RValue::get(V), SizeTy);
+ };
+
// 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()) {
@@ -2822,10 +2862,11 @@ void CodeGenFunction::EmitCallArgs(CallArgList &Args,
// Evaluate each argument.
size_t CallArgsStart = Args.size();
for (int I = ArgTypes.size() - 1; I >= 0; --I) {
- CallExpr::const_arg_iterator Arg = ArgBeg + I;
+ CallExpr::const_arg_iterator Arg = ArgRange.begin() + I;
EmitCallArg(Args, *Arg, ArgTypes[I]);
- EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], Arg->getExprLoc(),
+ EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(),
CalleeDecl, ParamsToSkip + I);
+ MaybeEmitImplicitObjectSize(I, *Arg);
}
// Un-reverse the arguments we just evaluated so they match up with the LLVM
@@ -2835,21 +2876,22 @@ void CodeGenFunction::EmitCallArgs(CallArgList &Args,
}
for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) {
- CallExpr::const_arg_iterator Arg = ArgBeg + I;
- assert(Arg != ArgEnd);
+ 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(),
+ EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(),
CalleeDecl, ParamsToSkip + I);
+ MaybeEmitImplicitObjectSize(I, *Arg);
}
}
namespace {
-struct DestroyUnpassedArg : EHScopeStack::Cleanup {
- DestroyUnpassedArg(llvm::Value *Addr, QualType Ty)
+struct DestroyUnpassedArg final : EHScopeStack::Cleanup {
+ DestroyUnpassedArg(Address Addr, QualType Ty)
: Addr(Addr), Ty(Ty) {}
- llvm::Value *Addr;
+ Address Addr;
QualType Ty;
void Emit(CodeGenFunction &CGF, Flags flags) override {
@@ -2860,8 +2902,6 @@ struct DestroyUnpassedArg : EHScopeStack::Cleanup {
}
};
-}
-
struct DisableDebugLocationUpdates {
CodeGenFunction &CGF;
bool disabledDebugInfo;
@@ -2875,6 +2915,8 @@ struct DisableDebugLocationUpdates {
}
};
+} // end anonymous namespace
+
void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
QualType type) {
DisableDebugLocationUpdates Dis(*this, E);
@@ -2923,7 +2965,8 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
// Create a no-op GEP between the placeholder and the cleanup so we can
// RAUW it successfully. It also serves as a marker of the first
// instruction where the cleanup is active.
- pushFullExprCleanup<DestroyUnpassedArg>(EHCleanup, Slot.getAddr(), type);
+ pushFullExprCleanup<DestroyUnpassedArg>(EHCleanup, Slot.getAddress(),
+ type);
// This unreachable is a temporary marker which will be removed later.
llvm::Instruction *IsActive = Builder.CreateUnreachable();
args.addArgCleanupDeactivation(EHStack.getInnermostEHScope(), IsActive);
@@ -2940,9 +2983,8 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
} else {
// We can't represent a misaligned lvalue in the CallArgList, so copy
// to an aligned temporary now.
- llvm::Value *tmp = CreateMemTemp(type);
- EmitAggregateCopy(tmp, L.getAddress(), type, L.isVolatile(),
- L.getAlignment());
+ Address tmp = CreateMemTemp(type);
+ EmitAggregateCopy(tmp, L.getAddress(), type, L.isVolatile());
args.add(RValue::getAggregate(tmp), type);
}
return;
@@ -3015,19 +3057,41 @@ CodeGenFunction::EmitRuntimeCall(llvm::Value *callee,
return call;
}
+// Calls which may throw must have operand bundles indicating which funclet
+// they are nested within.
+static void
+getBundlesForFunclet(llvm::Value *Callee,
+ llvm::Instruction *CurrentFuncletPad,
+ SmallVectorImpl<llvm::OperandBundleDef> &BundleList) {
+ // There is no need for a funclet operand bundle if we aren't inside a funclet.
+ if (!CurrentFuncletPad)
+ return;
+
+ // Skip intrinsics which cannot throw.
+ auto *CalleeFn = dyn_cast<llvm::Function>(Callee->stripPointerCasts());
+ if (CalleeFn && CalleeFn->isIntrinsic() && CalleeFn->doesNotThrow())
+ return;
+
+ BundleList.emplace_back("funclet", CurrentFuncletPad);
+}
+
/// Emits a call or invoke to the given noreturn runtime function.
void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee,
ArrayRef<llvm::Value*> args) {
+ SmallVector<llvm::OperandBundleDef, 1> BundleList;
+ getBundlesForFunclet(callee, CurrentFuncletPad, BundleList);
+
if (getInvokeDest()) {
llvm::InvokeInst *invoke =
Builder.CreateInvoke(callee,
getUnreachableBlock(),
getInvokeDest(),
- args);
+ args,
+ BundleList);
invoke->setDoesNotReturn();
invoke->setCallingConv(getRuntimeCC());
} else {
- llvm::CallInst *call = Builder.CreateCall(callee, args);
+ llvm::CallInst *call = Builder.CreateCall(callee, args, BundleList);
call->setDoesNotReturn();
call->setCallingConv(getRuntimeCC());
Builder.CreateUnreachable();
@@ -3052,12 +3116,6 @@ CodeGenFunction::EmitRuntimeCallOrInvoke(llvm::Value *callee,
return callSite;
}
-llvm::CallSite
-CodeGenFunction::EmitCallOrInvoke(llvm::Value *Callee,
- const Twine &Name) {
- return EmitCallOrInvoke(Callee, None, Name);
-}
-
/// Emits a call or invoke instruction to the given function, depending
/// on the current state of the EH stack.
llvm::CallSite
@@ -3102,7 +3160,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm::Value *Callee,
ReturnValueSlot ReturnValue,
const CallArgList &CallArgs,
- const Decl *TargetDecl,
+ CGCalleeInfo CalleeInfo,
llvm::Instruction **callOrInvoke) {
// FIXME: We no longer need the types from CallArgs; lift up and simplify.
@@ -3117,8 +3175,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// If we're using inalloca, insert the allocation after the stack save.
// FIXME: Do this earlier rather than hacking it in here!
- llvm::AllocaInst *ArgMemory = nullptr;
+ Address ArgMemory = Address::invalid();
+ const llvm::StructLayout *ArgMemoryLayout = nullptr;
if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) {
+ ArgMemoryLayout = CGM.getDataLayout().getStructLayout(ArgStruct);
llvm::Instruction *IP = CallArgs.getStackBase();
llvm::AllocaInst *AI;
if (IP) {
@@ -3127,36 +3187,44 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
} else {
AI = CreateTempAlloca(ArgStruct, "argmem");
}
+ auto Align = CallInfo.getArgStructAlignment();
+ AI->setAlignment(Align.getQuantity());
AI->setUsedWithInAlloca(true);
assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca());
- ArgMemory = AI;
+ ArgMemory = Address(AI, Align);
}
+ // Helper function to drill into the inalloca allocation.
+ auto createInAllocaStructGEP = [&](unsigned FieldIndex) -> Address {
+ auto FieldOffset =
+ CharUnits::fromQuantity(ArgMemoryLayout->getElementOffset(FieldIndex));
+ return Builder.CreateStructGEP(ArgMemory, FieldIndex, FieldOffset);
+ };
+
ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), CallInfo);
SmallVector<llvm::Value *, 16> IRCallArgs(IRFunctionArgs.totalIRArgs());
// If the call returns a temporary with struct return, create a temporary
// alloca to hold the result, unless one is given to us.
- llvm::Value *SRetPtr = nullptr;
+ Address SRetPtr = Address::invalid();
size_t UnusedReturnSize = 0;
if (RetAI.isIndirect() || RetAI.isInAlloca()) {
- SRetPtr = ReturnValue.getValue();
- if (!SRetPtr) {
+ if (!ReturnValue.isNull()) {
+ SRetPtr = ReturnValue.getValue();
+ } else {
SRetPtr = CreateMemTemp(RetTy);
if (HaveInsertPoint() && ReturnValue.isUnused()) {
uint64_t size =
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
- if (EmitLifetimeStart(size, SRetPtr))
+ if (EmitLifetimeStart(size, SRetPtr.getPointer()))
UnusedReturnSize = size;
}
}
if (IRFunctionArgs.hasSRetArg()) {
- IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr;
+ IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr.getPointer();
} else {
- llvm::Value *Addr =
- Builder.CreateStructGEP(ArgMemory->getAllocatedType(), ArgMemory,
- RetAI.getInAllocaFieldIndex());
- Builder.CreateStore(SRetPtr, Addr);
+ Address Addr = createInAllocaStructGEP(RetAI.getInAllocaFieldIndex());
+ Builder.CreateStore(SRetPtr.getPointer(), Addr);
}
}
@@ -3169,8 +3237,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
const ABIArgInfo &ArgInfo = info_it->info;
RValue RV = I->RV;
- CharUnits TypeAlign = getContext().getTypeAlignInChars(I->Ty);
-
// Insert a padding argument to ensure proper alignment.
if (IRFunctionArgs.hasPaddingArg(ArgNo))
IRCallArgs[IRFunctionArgs.getPaddingArgNo(ArgNo)] =
@@ -3186,27 +3252,23 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (RV.isAggregate()) {
// Replace the placeholder with the appropriate argument slot GEP.
llvm::Instruction *Placeholder =
- cast<llvm::Instruction>(RV.getAggregateAddr());
+ cast<llvm::Instruction>(RV.getAggregatePointer());
CGBuilderTy::InsertPoint IP = Builder.saveIP();
Builder.SetInsertPoint(Placeholder);
- llvm::Value *Addr =
- Builder.CreateStructGEP(ArgMemory->getAllocatedType(), ArgMemory,
- ArgInfo.getInAllocaFieldIndex());
+ Address Addr = createInAllocaStructGEP(ArgInfo.getInAllocaFieldIndex());
Builder.restoreIP(IP);
- deferPlaceholderReplacement(Placeholder, Addr);
+ deferPlaceholderReplacement(Placeholder, Addr.getPointer());
} else {
// Store the RValue into the argument struct.
- llvm::Value *Addr =
- Builder.CreateStructGEP(ArgMemory->getAllocatedType(), ArgMemory,
- ArgInfo.getInAllocaFieldIndex());
- unsigned AS = Addr->getType()->getPointerAddressSpace();
+ Address Addr = createInAllocaStructGEP(ArgInfo.getInAllocaFieldIndex());
+ unsigned AS = Addr.getType()->getPointerAddressSpace();
llvm::Type *MemType = ConvertTypeForMem(I->Ty)->getPointerTo(AS);
// There are some cases where a trivial bitcast is not avoidable. The
// definition of a type later in a translation unit may change it's type
// from {}* to (%struct.foo*)*.
- if (Addr->getType() != MemType)
+ if (Addr.getType() != MemType)
Addr = Builder.CreateBitCast(Addr, MemType);
- LValue argLV = MakeAddrLValue(Addr, I->Ty, TypeAlign);
+ LValue argLV = MakeAddrLValue(Addr, I->Ty);
EmitInitStoreOfNonAggregate(*this, RV, argLV);
}
break;
@@ -3216,12 +3278,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
assert(NumIRArgs == 1);
if (RV.isScalar() || RV.isComplex()) {
// Make a temporary alloca to pass the argument.
- llvm::AllocaInst *AI = CreateMemTemp(I->Ty);
- if (ArgInfo.getIndirectAlign() > AI->getAlignment())
- AI->setAlignment(ArgInfo.getIndirectAlign());
- IRCallArgs[FirstIRArg] = AI;
+ Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign());
+ IRCallArgs[FirstIRArg] = Addr.getPointer();
- LValue argLV = MakeAddrLValue(AI, I->Ty, TypeAlign);
+ LValue argLV = MakeAddrLValue(Addr, I->Ty);
EmitInitStoreOfNonAggregate(*this, RV, argLV);
} else {
// We want to avoid creating an unnecessary temporary+copy here;
@@ -3232,27 +3292,27 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// we cannot force it to be sufficiently aligned.
// 3. If the argument is byval, but RV is located in an address space
// different than that of the argument (0).
- llvm::Value *Addr = RV.getAggregateAddr();
- unsigned Align = ArgInfo.getIndirectAlign();
+ Address Addr = RV.getAggregateAddress();
+ CharUnits Align = ArgInfo.getIndirectAlign();
const llvm::DataLayout *TD = &CGM.getDataLayout();
- const unsigned RVAddrSpace = Addr->getType()->getPointerAddressSpace();
+ const unsigned RVAddrSpace = Addr.getType()->getAddressSpace();
const unsigned ArgAddrSpace =
(FirstIRArg < IRFuncTy->getNumParams()
? IRFuncTy->getParamType(FirstIRArg)->getPointerAddressSpace()
: 0);
if ((!ArgInfo.getIndirectByVal() && I->NeedsCopy) ||
- (ArgInfo.getIndirectByVal() && TypeAlign.getQuantity() < Align &&
- llvm::getOrEnforceKnownAlignment(Addr, Align, *TD) < Align) ||
+ (ArgInfo.getIndirectByVal() && Addr.getAlignment() < Align &&
+ llvm::getOrEnforceKnownAlignment(Addr.getPointer(),
+ Align.getQuantity(), *TD)
+ < Align.getQuantity()) ||
(ArgInfo.getIndirectByVal() && (RVAddrSpace != ArgAddrSpace))) {
// Create an aligned temporary, and copy to it.
- llvm::AllocaInst *AI = CreateMemTemp(I->Ty);
- if (Align > AI->getAlignment())
- AI->setAlignment(Align);
- IRCallArgs[FirstIRArg] = AI;
+ Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign());
+ IRCallArgs[FirstIRArg] = AI.getPointer();
EmitAggregateCopy(AI, Addr, I->Ty, RV.isVolatileQualified());
} else {
// Skip the extra memcpy call.
- IRCallArgs[FirstIRArg] = Addr;
+ IRCallArgs[FirstIRArg] = Addr.getPointer();
}
}
break;
@@ -3272,7 +3332,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (RV.isScalar())
V = RV.getScalarVal();
else
- V = Builder.CreateLoad(RV.getAggregateAddr());
+ V = Builder.CreateLoad(RV.getAggregateAddress());
// We might have to widen integers, but we should never truncate.
if (ArgInfo.getCoerceToType() != V->getType() &&
@@ -3289,35 +3349,24 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
// FIXME: Avoid the conversion through memory if possible.
- llvm::Value *SrcPtr;
- CharUnits SrcAlign;
+ Address Src = Address::invalid();
if (RV.isScalar() || RV.isComplex()) {
- SrcPtr = CreateMemTemp(I->Ty, "coerce");
- SrcAlign = TypeAlign;
- LValue SrcLV = MakeAddrLValue(SrcPtr, I->Ty, TypeAlign);
+ Src = CreateMemTemp(I->Ty, "coerce");
+ LValue SrcLV = MakeAddrLValue(Src, I->Ty);
EmitInitStoreOfNonAggregate(*this, RV, SrcLV);
} else {
- SrcPtr = RV.getAggregateAddr();
- // This alignment is guaranteed by EmitCallArg.
- SrcAlign = TypeAlign;
+ Src = RV.getAggregateAddress();
}
// If the value is offset in memory, apply the offset now.
- if (unsigned Offs = ArgInfo.getDirectOffset()) {
- SrcPtr = Builder.CreateBitCast(SrcPtr, Builder.getInt8PtrTy());
- SrcPtr = Builder.CreateConstGEP1_32(Builder.getInt8Ty(), SrcPtr, Offs);
- SrcPtr = Builder.CreateBitCast(SrcPtr,
- llvm::PointerType::getUnqual(ArgInfo.getCoerceToType()));
- SrcAlign = SrcAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs));
- }
+ Src = emitAddressAtOffset(*this, Src, ArgInfo);
// Fast-isel and the optimizer generally like scalar values better than
// FCAs, so we flatten them if this is safe to do for this argument.
llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType());
if (STy && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) {
- llvm::Type *SrcTy =
- cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
+ llvm::Type *SrcTy = Src.getType()->getElementType();
uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy);
@@ -3326,29 +3375,28 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// of the destination type to allow loading all of it. The bits past
// the source value are left undef.
if (SrcSize < DstSize) {
- llvm::AllocaInst *TempAlloca
- = CreateTempAlloca(STy, SrcPtr->getName() + ".coerce");
- Builder.CreateMemCpy(TempAlloca, SrcPtr, SrcSize, 0);
- SrcPtr = TempAlloca;
+ Address TempAlloca
+ = CreateTempAlloca(STy, Src.getAlignment(),
+ Src.getName() + ".coerce");
+ Builder.CreateMemCpy(TempAlloca, Src, SrcSize);
+ Src = TempAlloca;
} else {
- SrcPtr = Builder.CreateBitCast(SrcPtr,
- llvm::PointerType::getUnqual(STy));
+ Src = Builder.CreateBitCast(Src, llvm::PointerType::getUnqual(STy));
}
+ auto SrcLayout = CGM.getDataLayout().getStructLayout(STy);
assert(NumIRArgs == STy->getNumElements());
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- llvm::Value *EltPtr = Builder.CreateConstGEP2_32(STy, SrcPtr, 0, i);
- llvm::LoadInst *LI = Builder.CreateLoad(EltPtr);
- // We don't know what we're loading from.
- LI->setAlignment(1);
+ auto Offset = CharUnits::fromQuantity(SrcLayout->getElementOffset(i));
+ Address EltPtr = Builder.CreateStructGEP(Src, i, Offset);
+ llvm::Value *LI = Builder.CreateLoad(EltPtr);
IRCallArgs[FirstIRArg + i] = LI;
}
} else {
// In the simple case, just pass the coerced loaded value.
assert(NumIRArgs == 1);
IRCallArgs[FirstIRArg] =
- CreateCoercedLoad(SrcPtr, ArgInfo.getCoerceToType(),
- SrcAlign, *this);
+ CreateCoercedLoad(Src, ArgInfo.getCoerceToType(), *this);
}
break;
@@ -3362,8 +3410,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
}
- if (ArgMemory) {
- llvm::Value *Arg = ArgMemory;
+ if (ArgMemory.isValid()) {
+ llvm::Value *Arg = ArgMemory.getPointer();
if (CallInfo.isVariadic()) {
// When passing non-POD arguments by value to variadic functions, we will
// end up with a variadic prototype and an inalloca call site. In such
@@ -3441,23 +3489,38 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
unsigned CallingConv;
CodeGen::AttributeListType AttributeList;
- CGM.ConstructAttributeList(CallInfo, TargetDecl, AttributeList,
- CallingConv, true);
+ CGM.ConstructAttributeList(Callee->getName(), CallInfo, CalleeInfo,
+ AttributeList, CallingConv,
+ /*AttrOnCallSite=*/true);
llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(),
AttributeList);
- llvm::BasicBlock *InvokeDest = nullptr;
- if (!Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoUnwind) ||
- currentFunctionUsesSEHTry())
- InvokeDest = getInvokeDest();
+ bool CannotThrow;
+ if (currentFunctionUsesSEHTry()) {
+ // SEH cares about asynchronous exceptions, 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.
+ CannotThrow = true;
+ } else {
+ // Otherwise, nowunind callsites will never throw.
+ CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::NoUnwind);
+ }
+ llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
+
+ SmallVector<llvm::OperandBundleDef, 1> BundleList;
+ getBundlesForFunclet(Callee, CurrentFuncletPad, BundleList);
llvm::CallSite CS;
if (!InvokeDest) {
- CS = Builder.CreateCall(Callee, IRCallArgs);
+ CS = Builder.CreateCall(Callee, IRCallArgs, BundleList);
} else {
llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
- CS = Builder.CreateInvoke(Callee, Cont, InvokeDest, IRCallArgs);
+ CS = Builder.CreateInvoke(Callee, Cont, InvokeDest, IRCallArgs,
+ BundleList);
EmitBlock(Cont);
}
if (callOrInvoke)
@@ -3489,7 +3552,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (CS.doesNotReturn()) {
if (UnusedReturnSize)
EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
- SRetPtr);
+ SRetPtr.getPointer());
Builder.CreateUnreachable();
Builder.ClearInsertionPoint();
@@ -3516,6 +3579,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// 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);
+ }
+
RValue Ret = [&] {
switch (RetAI.getKind()) {
case ABIArgInfo::InAlloca:
@@ -3523,7 +3592,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
if (UnusedReturnSize)
EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
- SRetPtr);
+ SRetPtr.getPointer());
return ret;
}
@@ -3543,15 +3612,14 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
return RValue::getComplex(std::make_pair(Real, Imag));
}
case TEK_Aggregate: {
- llvm::Value *DestPtr = ReturnValue.getValue();
+ Address DestPtr = ReturnValue.getValue();
bool DestIsVolatile = ReturnValue.isVolatile();
- CharUnits DestAlign = getContext().getTypeAlignInChars(RetTy);
- if (!DestPtr) {
+ if (!DestPtr.isValid()) {
DestPtr = CreateMemTemp(RetTy, "agg.tmp");
DestIsVolatile = false;
}
- BuildAggStore(*this, CI, DestPtr, DestIsVolatile, DestAlign);
+ BuildAggStore(*this, CI, DestPtr, DestIsVolatile);
return RValue::getAggregate(DestPtr);
}
case TEK_Scalar: {
@@ -3566,28 +3634,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm_unreachable("bad evaluation kind");
}
- llvm::Value *DestPtr = ReturnValue.getValue();
+ Address DestPtr = ReturnValue.getValue();
bool DestIsVolatile = ReturnValue.isVolatile();
- CharUnits DestAlign = getContext().getTypeAlignInChars(RetTy);
- if (!DestPtr) {
+ if (!DestPtr.isValid()) {
DestPtr = CreateMemTemp(RetTy, "coerce");
DestIsVolatile = false;
}
// If the value is offset in memory, apply the offset now.
- llvm::Value *StorePtr = DestPtr;
- CharUnits StoreAlign = DestAlign;
- if (unsigned Offs = RetAI.getDirectOffset()) {
- StorePtr = Builder.CreateBitCast(StorePtr, Builder.getInt8PtrTy());
- StorePtr =
- Builder.CreateConstGEP1_32(Builder.getInt8Ty(), StorePtr, Offs);
- StorePtr = Builder.CreateBitCast(StorePtr,
- llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
- StoreAlign =
- StoreAlign.alignmentAtOffset(CharUnits::fromQuantity(Offs));
- }
- CreateCoercedStore(CI, StorePtr, DestIsVolatile, StoreAlign, *this);
+ Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI);
+ CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this);
return convertTempToRValue(DestPtr, RetTy, SourceLocation());
}
@@ -3599,6 +3656,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm_unreachable("Unhandled ABIArgInfo::Kind");
} ();
+ const Decl *TargetDecl = CalleeInfo.getCalleeDecl();
+
if (Ret.isScalar() && TargetDecl) {
if (const auto *AA = TargetDecl->getAttr<AssumeAlignedAttr>()) {
llvm::Value *OffsetValue = nullptr;
@@ -3617,6 +3676,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
/* VarArg handling */
-llvm::Value *CodeGenFunction::EmitVAArg(llvm::Value *VAListAddr, QualType Ty) {
- return CGM.getTypes().getABIInfo().EmitVAArg(VAListAddr, Ty, *this);
+Address CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr) {
+ VAListAddr = VE->isMicrosoftABI()
+ ? EmitMSVAListRef(VE->getSubExpr())
+ : EmitVAListRef(VE->getSubExpr());
+ QualType Ty = VE->getType();
+ if (VE->isMicrosoftABI())
+ return CGM.getTypes().getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty);
+ return CGM.getTypes().getABIInfo().EmitVAArg(*this, VAListAddr, Ty);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h
index 7a4708e..2ebd09b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.h
@@ -56,7 +56,7 @@ namespace CodeGen {
class CallArgList :
public SmallVector<CallArg, 16> {
public:
- CallArgList() : StackBase(nullptr), StackBaseMem(nullptr) {}
+ CallArgList() : StackBase(nullptr) {}
struct Writeback {
/// The original argument. Note that the argument l-value
@@ -64,7 +64,7 @@ namespace CodeGen {
LValue Source;
/// The temporary alloca.
- llvm::Value *Temporary;
+ Address Temporary;
/// A value to "use" after the writeback, or null.
llvm::Value *ToUse;
@@ -88,12 +88,9 @@ namespace CodeGen {
other.Writebacks.begin(), other.Writebacks.end());
}
- void addWriteback(LValue srcLV, llvm::Value *temporary,
+ void addWriteback(LValue srcLV, Address temporary,
llvm::Value *toUse) {
- Writeback writeback;
- writeback.Source = srcLV;
- writeback.Temporary = temporary;
- writeback.ToUse = toUse;
+ Writeback writeback = { srcLV, temporary, toUse };
Writebacks.push_back(writeback);
}
@@ -137,9 +134,6 @@ namespace CodeGen {
/// The stacksave call. It dominates all of the argument evaluation.
llvm::CallInst *StackBase;
- /// The alloca holding the stackbase. We need it to maintain SSA form.
- llvm::AllocaInst *StackBaseMem;
-
/// The iterator pointing to the stack restore cleanup. We manually run and
/// deactivate this cleanup after the call in the unexceptional case because
/// it doesn't run in the normal order.
@@ -156,6 +150,7 @@ namespace CodeGen {
/// function can be stored, and whether the address is volatile or not.
class ReturnValueSlot {
llvm::PointerIntPair<llvm::Value *, 2, unsigned int> Value;
+ CharUnits Alignment;
// Return value slot flags
enum Flags {
@@ -165,14 +160,15 @@ namespace CodeGen {
public:
ReturnValueSlot() {}
- ReturnValueSlot(llvm::Value *Value, bool IsVolatile, bool IsUnused = false)
- : Value(Value,
- (IsVolatile ? IS_VOLATILE : 0) | (IsUnused ? IS_UNUSED : 0)) {}
+ ReturnValueSlot(Address Addr, bool IsVolatile, bool IsUnused = false)
+ : Value(Addr.isValid() ? Addr.getPointer() : nullptr,
+ (IsVolatile ? IS_VOLATILE : 0) | (IsUnused ? IS_UNUSED : 0)),
+ Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {}
- bool isNull() const { return !getValue(); }
+ bool isNull() const { return !getValue().isValid(); }
bool isVolatile() const { return Value.getInt() & IS_VOLATILE; }
- llvm::Value *getValue() const { return Value.getPointer(); }
+ Address getValue() const { return Address(Value.getPointer(), Alignment); }
bool isUnused() const { return Value.getInt() & IS_UNUSED; }
};
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
index c49f182..2e566de 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
@@ -1,4 +1,4 @@
-//===--- CGClass.cpp - Emit LLVM Code for C++ classes ---------------------===//
+//===--- CGClass.cpp - Emit LLVM Code for C++ classes -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -25,10 +25,124 @@
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Metadata.h"
using namespace clang;
using namespace CodeGen;
+/// Return the best known alignment for an unknown pointer to a
+/// particular class.
+CharUnits CodeGenModule::getClassPointerAlignment(const CXXRecordDecl *RD) {
+ if (!RD->isCompleteDefinition())
+ return CharUnits::One(); // Hopefully won't be used anywhere.
+
+ auto &layout = getContext().getASTRecordLayout(RD);
+
+ // If the class is final, then we know that the pointer points to an
+ // object of that type and can use the full alignment.
+ if (RD->hasAttr<FinalAttr>()) {
+ return layout.getAlignment();
+
+ // Otherwise, we have to assume it could be a subclass.
+ } else {
+ return layout.getNonVirtualAlignment();
+ }
+}
+
+/// Return the best known alignment for a pointer to a virtual base,
+/// given the alignment of a pointer to the derived class.
+CharUnits CodeGenModule::getVBaseAlignment(CharUnits actualDerivedAlign,
+ const CXXRecordDecl *derivedClass,
+ const CXXRecordDecl *vbaseClass) {
+ // The basic idea here is that an underaligned derived pointer might
+ // indicate an underaligned base pointer.
+
+ assert(vbaseClass->isCompleteDefinition());
+ auto &baseLayout = getContext().getASTRecordLayout(vbaseClass);
+ CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();
+
+ return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass,
+ expectedVBaseAlign);
+}
+
+CharUnits
+CodeGenModule::getDynamicOffsetAlignment(CharUnits actualBaseAlign,
+ const CXXRecordDecl *baseDecl,
+ CharUnits expectedTargetAlign) {
+ // If the base is an incomplete type (which is, alas, possible with
+ // member pointers), be pessimistic.
+ if (!baseDecl->isCompleteDefinition())
+ return std::min(actualBaseAlign, expectedTargetAlign);
+
+ auto &baseLayout = getContext().getASTRecordLayout(baseDecl);
+ CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();
+
+ // If the class is properly aligned, assume the target offset is, too.
+ //
+ // This actually isn't necessarily the right thing to do --- if the
+ // class is a complete object, but it's only properly aligned for a
+ // base subobject, then the alignments of things relative to it are
+ // probably off as well. (Note that this requires the alignment of
+ // the target to be greater than the NV alignment of the derived
+ // class.)
+ //
+ // However, our approach to this kind of under-alignment can only
+ // ever be best effort; after all, we're never going to propagate
+ // alignments through variables or parameters. Note, in particular,
+ // that constructing a polymorphic type in an address that's less
+ // than pointer-aligned will generally trap in the constructor,
+ // unless we someday add some sort of attribute to change the
+ // assumed alignment of 'this'. So our goal here is pretty much
+ // just to allow the user to explicitly say that a pointer is
+ // under-aligned and then safely access its fields and v-tables.
+ if (actualBaseAlign >= expectedBaseAlign) {
+ return expectedTargetAlign;
+ }
+
+ // Otherwise, we might be offset by an arbitrary multiple of the
+ // actual alignment. The correct adjustment is to take the min of
+ // the two alignments.
+ return std::min(actualBaseAlign, expectedTargetAlign);
+}
+
+Address CodeGenFunction::LoadCXXThisAddress() {
+ assert(CurFuncDecl && "loading 'this' without a func declaration?");
+ assert(isa<CXXMethodDecl>(CurFuncDecl));
+
+ // Lazily compute CXXThisAlignment.
+ if (CXXThisAlignment.isZero()) {
+ // Just use the best known alignment for the parent.
+ // TODO: if we're currently emitting a complete-object ctor/dtor,
+ // we can always use the complete-object alignment.
+ auto RD = cast<CXXMethodDecl>(CurFuncDecl)->getParent();
+ CXXThisAlignment = CGM.getClassPointerAlignment(RD);
+ }
+
+ return Address(LoadCXXThis(), CXXThisAlignment);
+}
+
+/// Emit the address of a field using a member data pointer.
+///
+/// \param E Only used for emergency diagnostics
+Address
+CodeGenFunction::EmitCXXMemberDataPointerAddress(const Expr *E, Address base,
+ llvm::Value *memberPtr,
+ const MemberPointerType *memberPtrType,
+ AlignmentSource *alignSource) {
+ // Ask the ABI to compute the actual address.
+ llvm::Value *ptr =
+ CGM.getCXXABI().EmitMemberDataPointerAddress(*this, E, base,
+ memberPtr, memberPtrType);
+
+ QualType memberType = memberPtrType->getPointeeType();
+ CharUnits memberAlign = getNaturalTypeAlignment(memberType, alignSource);
+ memberAlign =
+ CGM.getDynamicOffsetAlignment(base.getAlignment(),
+ memberPtrType->getClass()->getAsCXXRecordDecl(),
+ memberAlign);
+ return Address(ptr, memberAlign);
+}
+
CharUnits CodeGenModule::computeNonVirtualBaseClassOffset(
const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start,
CastExpr::path_const_iterator End) {
@@ -78,15 +192,13 @@ CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
/// when the type is known to be complete (e.g. in complete destructors).
///
/// The object pointed to by 'This' is assumed to be non-null.
-llvm::Value *
-CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(llvm::Value *This,
+Address
+CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(Address This,
const CXXRecordDecl *Derived,
const CXXRecordDecl *Base,
bool BaseIsVirtual) {
// 'this' must be a pointer (in some address space) to Derived.
- assert(This->getType()->isPointerTy() &&
- cast<llvm::PointerType>(This->getType())->getElementType()
- == ConvertType(Derived));
+ assert(This.getElementType() == ConvertType(Derived));
// Compute the offset of the virtual base.
CharUnits Offset;
@@ -98,20 +210,22 @@ CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(llvm::Value *This,
// Shift and cast down to the base type.
// TODO: for complete types, this should be possible with a GEP.
- llvm::Value *V = This;
- if (Offset.isPositive()) {
- V = Builder.CreateBitCast(V, Int8PtrTy);
- V = Builder.CreateConstInBoundsGEP1_64(V, Offset.getQuantity());
+ Address V = This;
+ if (!Offset.isZero()) {
+ V = Builder.CreateElementBitCast(V, Int8Ty);
+ V = Builder.CreateConstInBoundsByteGEP(V, Offset);
}
- V = Builder.CreateBitCast(V, ConvertType(Base)->getPointerTo());
+ V = Builder.CreateElementBitCast(V, ConvertType(Base));
return V;
}
-static llvm::Value *
-ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, llvm::Value *ptr,
+static Address
+ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr,
CharUnits nonVirtualOffset,
- llvm::Value *virtualOffset) {
+ llvm::Value *virtualOffset,
+ const CXXRecordDecl *derivedClass,
+ const CXXRecordDecl *nearestVBase) {
// Assert that we have something to do.
assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);
@@ -128,13 +242,27 @@ ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, llvm::Value *ptr,
}
// Apply the base offset.
+ llvm::Value *ptr = addr.getPointer();
ptr = CGF.Builder.CreateBitCast(ptr, CGF.Int8PtrTy);
ptr = CGF.Builder.CreateInBoundsGEP(ptr, baseOffset, "add.ptr");
- return ptr;
+
+ // If we have a virtual component, the alignment of the result will
+ // be relative only to the known alignment of that vbase.
+ CharUnits alignment;
+ if (virtualOffset) {
+ assert(nearestVBase && "virtual offset without vbase?");
+ alignment = CGF.CGM.getVBaseAlignment(addr.getAlignment(),
+ derivedClass, nearestVBase);
+ } else {
+ alignment = addr.getAlignment();
+ }
+ alignment = alignment.alignmentAtOffset(nonVirtualOffset);
+
+ return Address(ptr, alignment);
}
-llvm::Value *CodeGenFunction::GetAddressOfBaseClass(
- llvm::Value *Value, const CXXRecordDecl *Derived,
+Address CodeGenFunction::GetAddressOfBaseClass(
+ Address Value, const CXXRecordDecl *Derived,
CastExpr::path_const_iterator PathBegin,
CastExpr::path_const_iterator PathEnd, bool NullCheckValue,
SourceLocation Loc) {
@@ -174,14 +302,14 @@ llvm::Value *CodeGenFunction::GetAddressOfBaseClass(
ConvertType((PathEnd[-1])->getType())->getPointerTo();
QualType DerivedTy = getContext().getRecordType(Derived);
- CharUnits DerivedAlign = getContext().getTypeAlignInChars(DerivedTy);
+ CharUnits DerivedAlign = CGM.getClassPointerAlignment(Derived);
// If the static offset is zero and we don't have a virtual step,
// just do a bitcast; null checks are unnecessary.
if (NonVirtualOffset.isZero() && !VBase) {
if (sanitizePerformTypeCheck()) {
- EmitTypeCheck(TCK_Upcast, Loc, Value, DerivedTy, DerivedAlign,
- !NullCheckValue);
+ EmitTypeCheck(TCK_Upcast, Loc, Value.getPointer(),
+ DerivedTy, DerivedAlign, !NullCheckValue);
}
return Builder.CreateBitCast(Value, BasePtrTy);
}
@@ -196,14 +324,14 @@ llvm::Value *CodeGenFunction::GetAddressOfBaseClass(
llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull");
endBB = createBasicBlock("cast.end");
- llvm::Value *isNull = Builder.CreateIsNull(Value);
+ llvm::Value *isNull = Builder.CreateIsNull(Value.getPointer());
Builder.CreateCondBr(isNull, endBB, notNullBB);
EmitBlock(notNullBB);
}
if (sanitizePerformTypeCheck()) {
- EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc, Value,
- DerivedTy, DerivedAlign, true);
+ EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc,
+ Value.getPointer(), DerivedTy, DerivedAlign, true);
}
// Compute the virtual offset.
@@ -214,9 +342,8 @@ llvm::Value *CodeGenFunction::GetAddressOfBaseClass(
}
// Apply both offsets.
- Value = ApplyNonVirtualAndVirtualOffset(*this, Value,
- NonVirtualOffset,
- VirtualOffset);
+ Value = ApplyNonVirtualAndVirtualOffset(*this, Value, NonVirtualOffset,
+ VirtualOffset, Derived, VBase);
// Cast to the destination type.
Value = Builder.CreateBitCast(Value, BasePtrTy);
@@ -228,16 +355,16 @@ llvm::Value *CodeGenFunction::GetAddressOfBaseClass(
EmitBlock(endBB);
llvm::PHINode *PHI = Builder.CreatePHI(BasePtrTy, 2, "cast.result");
- PHI->addIncoming(Value, notNullBB);
+ PHI->addIncoming(Value.getPointer(), notNullBB);
PHI->addIncoming(llvm::Constant::getNullValue(BasePtrTy), origBB);
- Value = PHI;
+ Value = Address(PHI, Value.getAlignment());
}
return Value;
}
-llvm::Value *
-CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
+Address
+CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr,
const CXXRecordDecl *Derived,
CastExpr::path_const_iterator PathBegin,
CastExpr::path_const_iterator PathEnd,
@@ -253,7 +380,7 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
if (!NonVirtualOffset) {
// No offset, we can just cast back.
- return Builder.CreateBitCast(Value, DerivedPtrTy);
+ return Builder.CreateBitCast(BaseAddr, DerivedPtrTy);
}
llvm::BasicBlock *CastNull = nullptr;
@@ -265,19 +392,20 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
CastNotNull = createBasicBlock("cast.notnull");
CastEnd = createBasicBlock("cast.end");
- llvm::Value *IsNull = Builder.CreateIsNull(Value);
+ llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr.getPointer());
Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
EmitBlock(CastNotNull);
}
// Apply the offset.
- Value = Builder.CreateBitCast(Value, Int8PtrTy);
+ llvm::Value *Value = Builder.CreateBitCast(BaseAddr.getPointer(), Int8PtrTy);
Value = Builder.CreateGEP(Value, Builder.CreateNeg(NonVirtualOffset),
"sub.ptr");
// Just cast.
Value = Builder.CreateBitCast(Value, DerivedPtrTy);
+ // Produce a PHI if we had a null-check.
if (NullCheckValue) {
Builder.CreateBr(CastEnd);
EmitBlock(CastNull);
@@ -286,12 +414,11 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2);
PHI->addIncoming(Value, CastNotNull);
- PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()),
- CastNull);
+ PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull);
Value = PHI;
}
- return Value;
+ return Address(Value, CGM.getClassPointerAlignment(Derived));
}
llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
@@ -345,7 +472,7 @@ llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
namespace {
/// Call the destructor for a direct base class.
- struct CallBaseDtor : EHScopeStack::Cleanup {
+ struct CallBaseDtor final : EHScopeStack::Cleanup {
const CXXRecordDecl *BaseClass;
bool BaseIsVirtual;
CallBaseDtor(const CXXRecordDecl *Base, bool BaseIsVirtual)
@@ -356,8 +483,8 @@ namespace {
cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();
const CXXDestructorDecl *D = BaseClass->getDestructor();
- llvm::Value *Addr =
- CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThis(),
+ Address Addr =
+ CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThisAddress(),
DerivedClass, BaseClass,
BaseIsVirtual);
CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual,
@@ -381,7 +508,7 @@ namespace {
// external code might potentially access the vtable.
void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; }
};
-}
+} // end anonymous namespace
static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) {
DynamicThisUseChecker Checker(C);
@@ -396,7 +523,7 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
assert(BaseInit->isBaseInitializer() &&
"Must have base initializer!");
- llvm::Value *ThisPtr = CGF.LoadCXXThis();
+ Address ThisPtr = CGF.LoadCXXThisAddress();
const Type *BaseType = BaseInit->getBaseClass();
CXXRecordDecl *BaseClassDecl =
@@ -416,13 +543,12 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
// We can pretend to be a complete class because it only matters for
// virtual bases, and we only do virtual bases for complete ctors.
- llvm::Value *V =
+ Address V =
CGF.GetAddressOfDirectBaseInCompleteClass(ThisPtr, ClassDecl,
BaseClassDecl,
isBaseVirtual);
- CharUnits Alignment = CGF.getContext().getTypeAlignInChars(BaseType);
AggValueSlot AggSlot =
- AggValueSlot::forAddr(V, Alignment, Qualifiers(),
+ AggValueSlot::forAddr(V, Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased);
@@ -438,17 +564,17 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
static void EmitAggMemberInitializer(CodeGenFunction &CGF,
LValue LHS,
Expr *Init,
- llvm::Value *ArrayIndexVar,
+ Address ArrayIndexVar,
QualType T,
ArrayRef<VarDecl *> ArrayIndexes,
unsigned Index) {
if (Index == ArrayIndexes.size()) {
LValue LV = LHS;
- if (ArrayIndexVar) {
+ if (ArrayIndexVar.isValid()) {
// If we have an array index variable, load it and use it as an offset.
// Then, increment the value.
- llvm::Value *Dest = LHS.getAddress();
+ llvm::Value *Dest = LHS.getPointer();
llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar);
Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex, "destaddress");
llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(), 1);
@@ -456,9 +582,9 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
CGF.Builder.CreateStore(Next, ArrayIndexVar);
// Update the LValue.
- LV.setAddress(Dest);
- CharUnits Align = CGF.getContext().getTypeAlignInChars(T);
- LV.setAlignment(std::min(Align, LV.getAlignment()));
+ CharUnits EltSize = CGF.getContext().getTypeSizeInChars(T);
+ CharUnits Align = LV.getAlignment().alignmentOfArrayElement(EltSize);
+ LV.setAddress(Address(Dest, Align));
}
switch (CGF.getEvaluationKind(T)) {
@@ -485,14 +611,11 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
const ConstantArrayType *Array = CGF.getContext().getAsConstantArrayType(T);
assert(Array && "Array initialization without the array type?");
- llvm::Value *IndexVar
- = CGF.GetAddrOfLocalVar(ArrayIndexes[Index]);
- assert(IndexVar && "Array index variable not loaded");
+ Address IndexVar = CGF.GetAddrOfLocalVar(ArrayIndexes[Index]);
// Initialize this index variable to zero.
llvm::Value* Zero
- = llvm::Constant::getNullValue(
- CGF.ConvertType(CGF.getContext().getSizeType()));
+ = llvm::Constant::getNullValue(IndexVar.getElementType());
CGF.Builder.CreateStore(Zero, IndexVar);
// Start the loop with a block that tests the condition.
@@ -626,9 +749,8 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit(), ArrayIndexes);
}
-void CodeGenFunction::EmitInitializerForField(
- FieldDecl *Field, LValue LHS, Expr *Init,
- ArrayRef<VarDecl *> ArrayIndexes) {
+void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS,
+ Expr *Init, ArrayRef<VarDecl *> ArrayIndexes) {
QualType FieldType = Field->getType();
switch (getEvaluationKind(FieldType)) {
case TEK_Scalar:
@@ -643,26 +765,23 @@ void CodeGenFunction::EmitInitializerForField(
EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true);
break;
case TEK_Aggregate: {
- llvm::Value *ArrayIndexVar = nullptr;
+ Address ArrayIndexVar = Address::invalid();
if (ArrayIndexes.size()) {
- llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
-
// The LHS is a pointer to the first object we'll be constructing, as
// a flat array.
QualType BaseElementTy = getContext().getBaseElementType(FieldType);
llvm::Type *BasePtr = ConvertType(BaseElementTy);
BasePtr = llvm::PointerType::getUnqual(BasePtr);
- llvm::Value *BaseAddrPtr = Builder.CreateBitCast(LHS.getAddress(),
- BasePtr);
+ Address BaseAddrPtr = Builder.CreateBitCast(LHS.getAddress(), BasePtr);
LHS = MakeAddrLValue(BaseAddrPtr, BaseElementTy);
// Create an array index that will be used to walk over all of the
// objects we're constructing.
- ArrayIndexVar = CreateTempAlloca(SizeTy, "object.index");
- llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy);
+ ArrayIndexVar = CreateMemTemp(getContext().getSizeType(), "object.index");
+ llvm::Value *Zero =
+ llvm::Constant::getNullValue(ArrayIndexVar.getElementType());
Builder.CreateStore(Zero, ArrayIndexVar);
-
// Emit the block variables for the array indices, if any.
for (unsigned I = 0, N = ArrayIndexes.size(); I != N; ++I)
EmitAutoVarDecl(*ArrayIndexes[I]);
@@ -811,7 +930,7 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
return;
}
- const FunctionDecl *Definition = 0;
+ const FunctionDecl *Definition = nullptr;
Stmt *Body = Ctor->getBody(Definition);
assert(Definition == Ctor && "emitting wrong constructor body");
@@ -868,7 +987,7 @@ namespace {
SanitizerSet OldSanOpts;
};
}
-
+
namespace {
class FieldMemcpyizer {
public:
@@ -930,19 +1049,16 @@ namespace {
CharUnits MemcpySize = getMemcpySize(FirstByteOffset);
QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
- llvm::Value *ThisPtr = CGF.LoadCXXThis();
- LValue DestLV = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
+ Address ThisPtr = CGF.LoadCXXThisAddress();
+ LValue DestLV = CGF.MakeAddrLValue(ThisPtr, RecordTy);
LValue Dest = CGF.EmitLValueForFieldInitialization(DestLV, FirstField);
llvm::Value *SrcPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(SrcRec));
LValue SrcLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
LValue Src = CGF.EmitLValueForFieldInitialization(SrcLV, FirstField);
- CharUnits Offset = CGF.getContext().toCharUnitsFromBits(FirstByteOffset);
- CharUnits Alignment = DestLV.getAlignment().alignmentAtOffset(Offset);
-
- emitMemcpyIR(Dest.isBitField() ? Dest.getBitFieldAddr() : Dest.getAddress(),
- Src.isBitField() ? Src.getBitFieldAddr() : Src.getAddress(),
- MemcpySize, Alignment);
+ emitMemcpyIR(Dest.isBitField() ? Dest.getBitFieldAddress() : Dest.getAddress(),
+ Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(),
+ MemcpySize);
reset();
}
@@ -956,20 +1072,18 @@ namespace {
private:
- void emitMemcpyIR(llvm::Value *DestPtr, llvm::Value *SrcPtr,
- CharUnits Size, CharUnits Alignment) {
- llvm::PointerType *DPT = cast<llvm::PointerType>(DestPtr->getType());
+ void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) {
+ llvm::PointerType *DPT = DestPtr.getType();
llvm::Type *DBP =
llvm::Type::getInt8PtrTy(CGF.getLLVMContext(), DPT->getAddressSpace());
DestPtr = CGF.Builder.CreateBitCast(DestPtr, DBP);
- llvm::PointerType *SPT = cast<llvm::PointerType>(SrcPtr->getType());
+ llvm::PointerType *SPT = SrcPtr.getType();
llvm::Type *SBP =
llvm::Type::getInt8PtrTy(CGF.getLLVMContext(), SPT->getAddressSpace());
SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, SBP);
- CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity(),
- Alignment.getQuantity());
+ CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity());
}
void addInitialField(FieldDecl *F) {
@@ -1089,9 +1203,9 @@ namespace {
}
void pushEHDestructors() {
- llvm::Value *ThisPtr = CGF.LoadCXXThis();
+ Address ThisPtr = CGF.LoadCXXThisAddress();
QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
- LValue LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
+ LValue LHS = CGF.MakeAddrLValue(ThisPtr, RecordTy);
for (unsigned i = 0; i < AggregatedInits.size(); ++i) {
CXXCtorInitializer *MemberInit = AggregatedInits[i];
@@ -1228,7 +1342,13 @@ namespace {
emitAggregatedStmts();
}
};
+} // end anonymous namespace
+static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
+ const Type *BaseType = BaseInit->getBaseClass();
+ const auto *BaseClassDecl =
+ cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
+ return BaseClassDecl->isDynamicClass();
}
/// EmitCtorPrologue - This routine generates necessary code to initialize
@@ -1254,8 +1374,13 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
assert(BaseCtorContinueBB);
}
+ llvm::Value *const OldThis = CXXThisValue;
// Virtual base initializers first.
for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) {
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ isInitializerOfDynamicClass(*B))
+ CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
EmitBaseInitializer(*this, ClassDecl, *B, CtorType);
}
@@ -1268,13 +1393,20 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
// Then, non-virtual base initializers.
for (; B != E && (*B)->isBaseInitializer(); B++) {
assert(!(*B)->isBaseVirtual());
+
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ isInitializerOfDynamicClass(*B))
+ CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
EmitBaseInitializer(*this, ClassDecl, *B, CtorType);
}
+ CXXThisValue = OldThis;
+
InitializeVTablePointers(ClassDecl);
// And finally, initialize class members.
- FieldConstructionScope FCS(*this, CXXThisValue);
+ FieldConstructionScope FCS(*this, LoadCXXThisAddress());
ConstructorMemcpyizer CM(*this, CD, Args);
for (; B != E; B++) {
CXXCtorInitializer *Member = (*B);
@@ -1334,7 +1466,7 @@ HasTrivialDestructorBody(ASTContext &Context,
static bool
FieldHasTrivialDestructorBody(ASTContext &Context,
- const FieldDecl *Field)
+ const FieldDecl *Field)
{
QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());
@@ -1353,39 +1485,23 @@ FieldHasTrivialDestructorBody(ASTContext &Context,
/// CanSkipVTablePointerInitialization - Check whether we need to initialize
/// any vtable pointers before calling this destructor.
-static bool CanSkipVTablePointerInitialization(ASTContext &Context,
+static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor) {
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ if (!ClassDecl->isDynamicClass())
+ return true;
+
if (!Dtor->hasTrivialBody())
return false;
// Check the fields.
- const CXXRecordDecl *ClassDecl = Dtor->getParent();
for (const auto *Field : ClassDecl->fields())
- if (!FieldHasTrivialDestructorBody(Context, Field))
+ if (!FieldHasTrivialDestructorBody(CGF.getContext(), Field))
return false;
return true;
}
-// Generates function call for handling object poisoning, passing in
-// references to 'this' and its size as arguments.
-static void EmitDtorSanitizerCallback(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor) {
- const ASTRecordLayout &Layout =
- CGF.getContext().getASTRecordLayout(Dtor->getParent());
-
- llvm::Value *Args[] = {
- CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.VoidPtrTy),
- llvm::ConstantInt::get(CGF.SizeTy, Layout.getSize().getQuantity())};
- llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy};
-
- llvm::FunctionType *FnType =
- llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false);
- llvm::Value *Fn =
- CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback");
- CGF.EmitNounwindRuntimeCall(Fn, Args);
-}
-
/// EmitDestructorBody - Emits the body of the current destructor.
void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
@@ -1402,7 +1518,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
if (DtorType == Dtor_Deleting) {
EnterDtorCleanups(Dtor, Dtor_Deleting);
EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
- /*Delegating=*/false, LoadCXXThis());
+ /*Delegating=*/false, LoadCXXThisAddress());
PopCleanupBlock();
return;
}
@@ -1437,7 +1553,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
if (!isTryBody) {
EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
- /*Delegating=*/false, LoadCXXThis());
+ /*Delegating=*/false, LoadCXXThisAddress());
break;
}
// Fallthrough: act like we're in the base variant.
@@ -1449,8 +1565,14 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
EnterDtorCleanups(Dtor, Dtor_Base);
// Initialize the vtable pointers before entering the body.
- if (!CanSkipVTablePointerInitialization(getContext(), Dtor))
- InitializeVTablePointers(Dtor->getParent());
+ if (!CanSkipVTablePointerInitialization(*this, Dtor)) {
+ // Insert the llvm.invariant.group.barrier intrinsic before initializing
+ // the vptrs to cancel any previous assumptions we might have made.
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0)
+ CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
+ InitializeVTablePointers(Dtor->getParent());
+ }
if (isTryBody)
EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
@@ -1464,6 +1586,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// the caller's body.
if (getLangOpts().AppleKext)
CurFn->addFnAttr(llvm::Attribute::AlwaysInline);
+
break;
}
@@ -1473,10 +1596,6 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// Exit the try if applicable.
if (isTryBody)
ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
-
- // Insert memory-poisoning instrumentation.
- if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor)
- EmitDtorSanitizerCallback(*this, Dtor);
}
void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) {
@@ -1496,7 +1615,7 @@ void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args)
namespace {
/// Call the operator delete associated with the current destructor.
- struct CallDtorDelete : EHScopeStack::Cleanup {
+ struct CallDtorDelete final : EHScopeStack::Cleanup {
CallDtorDelete() {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
@@ -1507,11 +1626,11 @@ namespace {
}
};
- struct CallDtorDeleteConditional : EHScopeStack::Cleanup {
+ struct CallDtorDeleteConditional final : EHScopeStack::Cleanup {
llvm::Value *ShouldDeleteCondition;
public:
CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)
- : ShouldDeleteCondition(ShouldDeleteCondition) {
+ : ShouldDeleteCondition(ShouldDeleteCondition) {
assert(ShouldDeleteCondition != nullptr);
}
@@ -1533,7 +1652,7 @@ namespace {
}
};
- class DestroyField : public EHScopeStack::Cleanup {
+ class DestroyField final : public EHScopeStack::Cleanup {
const FieldDecl *field;
CodeGenFunction::Destroyer *destroyer;
bool useEHCleanupForArray;
@@ -1541,12 +1660,12 @@ namespace {
public:
DestroyField(const FieldDecl *field, CodeGenFunction::Destroyer *destroyer,
bool useEHCleanupForArray)
- : field(field), destroyer(destroyer),
- useEHCleanupForArray(useEHCleanupForArray) {}
+ : field(field), destroyer(destroyer),
+ useEHCleanupForArray(useEHCleanupForArray) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
// Find the address of the field.
- llvm::Value *thisValue = CGF.LoadCXXThis();
+ Address thisValue = CGF.LoadCXXThisAddress();
QualType RecordTy = CGF.getContext().getTagDeclType(field->getParent());
LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy);
LValue LV = CGF.EmitLValueForField(ThisLV, field);
@@ -1556,7 +1675,133 @@ namespace {
flags.isForNormalCleanup() && useEHCleanupForArray);
}
};
-}
+
+ static void EmitSanitizerDtorCallback(CodeGenFunction &CGF, llvm::Value *Ptr,
+ CharUnits::QuantityType PoisonSize) {
+ // Pass in void pointer and size of region as arguments to runtime
+ // function
+ llvm::Value *Args[] = {CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy),
+ llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)};
+
+ llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy};
+
+ llvm::FunctionType *FnType =
+ llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false);
+ llvm::Value *Fn =
+ CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback");
+ CGF.EmitNounwindRuntimeCall(Fn, Args);
+ }
+
+ class SanitizeDtorMembers final : public EHScopeStack::Cleanup {
+ const CXXDestructorDecl *Dtor;
+
+ public:
+ SanitizeDtorMembers(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {}
+
+ // Generate function call for handling object poisoning.
+ // Disables tail call elimination, to prevent the current stack frame
+ // from disappearing from the stack trace.
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ const ASTRecordLayout &Layout =
+ CGF.getContext().getASTRecordLayout(Dtor->getParent());
+
+ // Nothing to poison.
+ if (Layout.getFieldCount() == 0)
+ return;
+
+ // Prevent the current stack frame from disappearing from the stack trace.
+ CGF.CurFn->addFnAttr("disable-tail-calls", "true");
+
+ // Construct pointer to region to begin poisoning, and calculate poison
+ // size, so that only members declared in this class are poisoned.
+ ASTContext &Context = CGF.getContext();
+ unsigned fieldIndex = 0;
+ int startIndex = -1;
+ // RecordDecl::field_iterator Field;
+ for (const FieldDecl *Field : Dtor->getParent()->fields()) {
+ // Poison field if it is trivial
+ if (FieldHasTrivialDestructorBody(Context, Field)) {
+ // Start sanitizing at this field
+ if (startIndex < 0)
+ startIndex = fieldIndex;
+
+ // Currently on the last field, and it must be poisoned with the
+ // current block.
+ if (fieldIndex == Layout.getFieldCount() - 1) {
+ PoisonMembers(CGF, startIndex, Layout.getFieldCount());
+ }
+ } else if (startIndex >= 0) {
+ // No longer within a block of memory to poison, so poison the block
+ PoisonMembers(CGF, startIndex, fieldIndex);
+ // Re-set the start index
+ startIndex = -1;
+ }
+ fieldIndex += 1;
+ }
+ }
+
+ private:
+ /// \param layoutStartOffset index of the ASTRecordLayout field to
+ /// start poisoning (inclusive)
+ /// \param layoutEndOffset index of the ASTRecordLayout field to
+ /// end poisoning (exclusive)
+ void PoisonMembers(CodeGenFunction &CGF, unsigned layoutStartOffset,
+ unsigned layoutEndOffset) {
+ ASTContext &Context = CGF.getContext();
+ const ASTRecordLayout &Layout =
+ Context.getASTRecordLayout(Dtor->getParent());
+
+ llvm::ConstantInt *OffsetSizePtr = llvm::ConstantInt::get(
+ CGF.SizeTy,
+ Context.toCharUnitsFromBits(Layout.getFieldOffset(layoutStartOffset))
+ .getQuantity());
+
+ llvm::Value *OffsetPtr = CGF.Builder.CreateGEP(
+ CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.Int8PtrTy),
+ OffsetSizePtr);
+
+ CharUnits::QuantityType PoisonSize;
+ if (layoutEndOffset >= Layout.getFieldCount()) {
+ PoisonSize = Layout.getNonVirtualSize().getQuantity() -
+ Context.toCharUnitsFromBits(
+ Layout.getFieldOffset(layoutStartOffset))
+ .getQuantity();
+ } else {
+ PoisonSize = Context.toCharUnitsFromBits(
+ Layout.getFieldOffset(layoutEndOffset) -
+ Layout.getFieldOffset(layoutStartOffset))
+ .getQuantity();
+ }
+
+ if (PoisonSize == 0)
+ return;
+
+ EmitSanitizerDtorCallback(CGF, OffsetPtr, PoisonSize);
+ }
+ };
+
+ class SanitizeDtorVTable final : public EHScopeStack::Cleanup {
+ const CXXDestructorDecl *Dtor;
+
+ public:
+ SanitizeDtorVTable(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {}
+
+ // Generate function call for handling vtable pointer poisoning.
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ assert(Dtor->getParent()->isDynamicClass());
+ (void)Dtor;
+ ASTContext &Context = CGF.getContext();
+ // Poison vtable and vtable ptr if they exist for this class.
+ llvm::Value *VTablePtr = CGF.LoadCXXThis();
+
+ CharUnits::QuantityType PoisonSize =
+ Context.toCharUnitsFromBits(CGF.PointerWidthInBits).getQuantity();
+ // Pass in void pointer and size of region as arguments to runtime
+ // function
+ EmitSanitizerDtorCallback(CGF, VTablePtr, PoisonSize);
+ }
+ };
+} // end anonymous namespace
/// \brief Emit all code that comes at the end of class's
/// destructor. This is to call destructors on members and base classes
@@ -1590,6 +1835,12 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
// The complete-destructor phase just destructs all the virtual bases.
if (DtorType == Dtor_Complete) {
+ // Poison the vtable pointer such that access after the base
+ // and member destructors are invoked is invalid.
+ if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
+ SanOpts.has(SanitizerKind::Memory) && ClassDecl->getNumVBases() &&
+ ClassDecl->isPolymorphic())
+ EHStack.pushCleanup<SanitizeDtorVTable>(NormalAndEHCleanup, DD);
// We push them in the forward order so that they'll be popped in
// the reverse order.
@@ -1610,6 +1861,12 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
}
assert(DtorType == Dtor_Base);
+ // Poison the vtable pointer if it has no virtual bases, but inherits
+ // virtual functions.
+ if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
+ SanOpts.has(SanitizerKind::Memory) && !ClassDecl->getNumVBases() &&
+ ClassDecl->isPolymorphic())
+ EHStack.pushCleanup<SanitizeDtorVTable>(NormalAndEHCleanup, DD);
// Destroy non-virtual bases.
for (const auto &Base : ClassDecl->bases()) {
@@ -1628,6 +1885,12 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
/*BaseIsVirtual*/ false);
}
+ // Poison fields such that access after their destructors are
+ // invoked, and before the base class destructor runs, is invalid.
+ if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
+ SanOpts.has(SanitizerKind::Memory))
+ EHStack.pushCleanup<SanitizeDtorMembers>(NormalAndEHCleanup, DD);
+
// Destroy direct fields.
for (const auto *Field : ClassDecl->fields()) {
QualType type = Field->getType();
@@ -1655,7 +1918,7 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
/// zero-initialized before it is constructed
void CodeGenFunction::EmitCXXAggrConstructorCall(
const CXXConstructorDecl *ctor, const ConstantArrayType *arrayType,
- llvm::Value *arrayBegin, const CXXConstructExpr *E, bool zeroInitialize) {
+ Address arrayBegin, const CXXConstructExpr *E, bool zeroInitialize) {
QualType elementType;
llvm::Value *numElements =
emitArrayLength(arrayType, elementType, arrayBegin);
@@ -1669,15 +1932,14 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(
/// \param ctor the constructor to call for each element
/// \param numElements the number of elements in the array;
/// may be zero
-/// \param arrayBegin a T*, where T is the type constructed by ctor
+/// \param arrayBase a T*, where T is the type constructed by ctor
/// \param zeroInitialize true if each element should be
/// zero-initialized before it is constructed
void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
llvm::Value *numElements,
- llvm::Value *arrayBegin,
+ Address arrayBase,
const CXXConstructExpr *E,
bool zeroInitialize) {
-
// It's legal for numElements to be zero. This can happen both
// dynamically, because x can be zero in 'new A[x]', and statically,
// because of GCC extensions that permit zero-length arrays. There
@@ -1701,6 +1963,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
}
// Find the end of the array.
+ llvm::Value *arrayBegin = arrayBase.getPointer();
llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(arrayBegin, numElements,
"arrayctor.end");
@@ -1714,11 +1977,21 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
// Inside the loop body, emit the constructor call on the array element.
+ // The alignment of the base, adjusted by the size of a single element,
+ // provides a conservative estimate of the alignment of every element.
+ // (This assumes we never start tracking offsetted alignments.)
+ //
+ // Note that these are complete objects and so we don't need to
+ // use the non-virtual size or alignment.
QualType type = getContext().getTypeDeclType(ctor->getParent());
+ CharUnits eltAlignment =
+ arrayBase.getAlignment()
+ .alignmentOfArrayElement(getContext().getTypeSizeInChars(type));
+ Address curAddr = Address(cur, eltAlignment);
// Zero initialize the storage, if requested.
if (zeroInitialize)
- EmitNullInitialization(cur, type);
+ EmitNullInitialization(curAddr, type);
// C++ [class.temporary]p4:
// There are two contexts in which temporaries are destroyed at a different
@@ -1736,11 +2009,12 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
if (getLangOpts().Exceptions &&
!ctor->getParent()->hasTrivialDestructor()) {
Destroyer *destroyer = destroyCXXObject;
- pushRegularPartialArrayCleanup(arrayBegin, cur, type, *destroyer);
+ pushRegularPartialArrayCleanup(arrayBegin, cur, type, eltAlignment,
+ *destroyer);
}
EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/false,
- /*Delegating=*/false, cur, E);
+ /*Delegating=*/false, curAddr, E);
}
// Go to the next element.
@@ -1761,7 +2035,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
}
void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF,
- llvm::Value *addr,
+ Address addr,
QualType type) {
const RecordType *rtype = type->castAs<RecordType>();
const CXXRecordDecl *record = cast<CXXRecordDecl>(rtype->getDecl());
@@ -1774,14 +2048,16 @@ void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF,
void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
CXXCtorType Type,
bool ForVirtualBase,
- bool Delegating, llvm::Value *This,
+ bool Delegating, Address This,
const CXXConstructExpr *E) {
+ const CXXRecordDecl *ClassDecl = D->getParent();
+
// C++11 [class.mfct.non-static]p2:
// If a non-static member function of a class X is called for an object that
// is not of type X, or of a type derived from X, the behavior is undefined.
// FIXME: Provide a source location here.
- EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, SourceLocation(), This,
- getContext().getRecordType(D->getParent()));
+ EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, SourceLocation(),
+ This.getPointer(), getContext().getRecordType(ClassDecl));
if (D->isTrivial() && D->isDefaultConstructor()) {
assert(E->getNumArgs() == 0 && "trivial default ctor with args");
@@ -1796,8 +2072,8 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
const Expr *Arg = E->getArg(0);
QualType SrcTy = Arg->getType();
- llvm::Value *Src = EmitLValue(Arg).getAddress();
- QualType DestTy = getContext().getTypeDeclType(D->getParent());
+ Address Src = EmitLValue(Arg).getAddress();
+ QualType DestTy = getContext().getTypeDeclType(ClassDecl);
EmitAggregateCopyCtor(This, Src, DestTy, SrcTy);
return;
}
@@ -1805,11 +2081,11 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
CallArgList Args;
// Push the this ptr.
- Args.add(RValue::get(This), D->getThisType(getContext()));
+ Args.add(RValue::get(This.getPointer()), D->getThisType(getContext()));
// Add the rest of the user-supplied arguments.
const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>();
- EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end(), E->getConstructor());
+ EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor());
// Insert any ABI-specific implicit constructor arguments.
unsigned ExtraArgs = CGM.getCXXABI().addImplicitConstructorArgs(
@@ -1820,19 +2096,64 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
const CGFunctionInfo &Info =
CGM.getTypes().arrangeCXXConstructorCall(Args, D, Type, ExtraArgs);
EmitCall(Info, Callee, ReturnValueSlot(), Args, D);
+
+ // Generate vtable assumptions if we're constructing a complete object
+ // with a vtable. We don't do this for base subobjects for two reasons:
+ // first, it's incorrect for classes with virtual bases, and second, we're
+ // about to overwrite the vptrs anyway.
+ // We also have to make sure if we can refer to vtable:
+ // - Otherwise we can refer to vtable if it's safe to speculatively emit.
+ // FIXME: If vtable is used by ctor/dtor, or if vtable is external and we are
+ // sure that definition of vtable is not hidden,
+ // then we are always safe to refer to it.
+ // FIXME: It looks like InstCombine is very inefficient on dealing with
+ // assumes. Make assumption loads require -fstrict-vtable-pointers temporarily.
+ if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ ClassDecl->isDynamicClass() && Type != Ctor_Base &&
+ CGM.getCXXABI().canSpeculativelyEmitVTable(ClassDecl) &&
+ CGM.getCodeGenOpts().StrictVTablePointers)
+ EmitVTableAssumptionLoads(ClassDecl, This);
+}
+
+void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr, Address This) {
+ llvm::Value *VTableGlobal =
+ CGM.getCXXABI().getVTableAddressPoint(Vptr.Base, Vptr.VTableClass);
+ if (!VTableGlobal)
+ return;
+
+ // We can just use the base offset in the complete class.
+ CharUnits NonVirtualOffset = Vptr.Base.getBaseOffset();
+
+ if (!NonVirtualOffset.isZero())
+ This =
+ ApplyNonVirtualAndVirtualOffset(*this, This, NonVirtualOffset, nullptr,
+ Vptr.VTableClass, Vptr.NearestVBase);
+
+ llvm::Value *VPtrValue =
+ GetVTablePtr(This, VTableGlobal->getType(), Vptr.VTableClass);
+ llvm::Value *Cmp =
+ Builder.CreateICmpEQ(VPtrValue, VTableGlobal, "cmp.vtables");
+ Builder.CreateAssumption(Cmp);
+}
+
+void CodeGenFunction::EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl,
+ Address This) {
+ if (CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl))
+ for (const VPtr &Vptr : getVTablePointers(ClassDecl))
+ EmitVTableAssumptionLoad(Vptr, This);
}
void
CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
- llvm::Value *This, llvm::Value *Src,
- const CXXConstructExpr *E) {
+ Address This, Address Src,
+ const CXXConstructExpr *E) {
if (isMemcpyEquivalentSpecialMember(D)) {
assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
assert(D->isCopyOrMoveConstructor() &&
"trivial 1-arg ctor not a copy/move ctor");
EmitAggregateCopyCtor(This, Src,
getContext().getTypeDeclType(D->getParent()),
- E->arg_begin()->getType());
+ (*E->arg_begin())->getType());
return;
}
llvm::Value *Callee = CGM.getAddrOfCXXStructor(D, StructorType::Complete);
@@ -1844,16 +2165,16 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
CallArgList Args;
// Push the this ptr.
- Args.add(RValue::get(This), D->getThisType(getContext()));
+ Args.add(RValue::get(This.getPointer()), D->getThisType(getContext()));
// Push the src ptr.
QualType QT = *(FPT->param_type_begin());
llvm::Type *t = CGM.getTypes().ConvertType(QT);
Src = Builder.CreateBitCast(Src, t);
- Args.add(RValue::get(Src), QT);
+ Args.add(RValue::get(Src.getPointer()), QT);
// Skip over first argument (Src).
- EmitCallArgs(Args, FPT, E->arg_begin() + 1, E->arg_end(), E->getConstructor(),
+ EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1), E->getConstructor(),
/*ParamsToSkip*/ 1);
EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, RequiredArgs::All),
@@ -1903,12 +2224,12 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
}
namespace {
- struct CallDelegatingCtorDtor : EHScopeStack::Cleanup {
+ struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup {
const CXXDestructorDecl *Dtor;
- llvm::Value *Addr;
+ Address Addr;
CXXDtorType Type;
- CallDelegatingCtorDtor(const CXXDestructorDecl *D, llvm::Value *Addr,
+ CallDelegatingCtorDtor(const CXXDestructorDecl *D, Address Addr,
CXXDtorType Type)
: Dtor(D), Addr(Addr), Type(Type) {}
@@ -1917,19 +2238,17 @@ namespace {
/*Delegating=*/true, Addr);
}
};
-}
+} // end anonymous namespace
void
CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor,
const FunctionArgList &Args) {
assert(Ctor->isDelegatingConstructor());
- llvm::Value *ThisPtr = LoadCXXThis();
+ Address ThisPtr = LoadCXXThisAddress();
- QualType Ty = getContext().getTagDeclType(Ctor->getParent());
- CharUnits Alignment = getContext().getTypeAlignInChars(Ty);
AggValueSlot AggSlot =
- AggValueSlot::forAddr(ThisPtr, Alignment, Qualifiers(),
+ AggValueSlot::forAddr(ThisPtr, Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased);
@@ -1951,17 +2270,17 @@ void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
CXXDtorType Type,
bool ForVirtualBase,
bool Delegating,
- llvm::Value *This) {
+ Address This) {
CGM.getCXXABI().EmitDestructorCall(*this, DD, Type, ForVirtualBase,
Delegating, This);
}
namespace {
- struct CallLocalDtor : EHScopeStack::Cleanup {
+ struct CallLocalDtor final : EHScopeStack::Cleanup {
const CXXDestructorDecl *Dtor;
- llvm::Value *Addr;
+ Address Addr;
- CallLocalDtor(const CXXDestructorDecl *D, llvm::Value *Addr)
+ CallLocalDtor(const CXXDestructorDecl *D, Address Addr)
: Dtor(D), Addr(Addr) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
@@ -1973,11 +2292,11 @@ namespace {
}
void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D,
- llvm::Value *Addr) {
+ Address Addr) {
EHStack.pushCleanup<CallLocalDtor>(NormalAndEHCleanup, D, Addr);
}
-void CodeGenFunction::PushDestructorCleanup(QualType T, llvm::Value *Addr) {
+void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) {
CXXRecordDecl *ClassDecl = T->getAsCXXRecordDecl();
if (!ClassDecl) return;
if (ClassDecl->hasTrivialDestructor()) return;
@@ -1987,24 +2306,12 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, llvm::Value *Addr) {
PushDestructorCleanup(D, Addr);
}
-void
-CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
- const CXXRecordDecl *NearestVBase,
- CharUnits OffsetFromNearestVBase,
- const CXXRecordDecl *VTableClass) {
- const CXXRecordDecl *RD = Base.getBase();
-
- // Don't initialize the vtable pointer if the class is marked with the
- // 'novtable' attribute.
- if ((RD == VTableClass || RD == NearestVBase) &&
- VTableClass->hasAttr<MSNoVTableAttr>())
- return;
-
+void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {
// Compute the address point.
- bool NeedsVirtualOffset;
llvm::Value *VTableAddressPoint =
CGM.getCXXABI().getVTableAddressPointInStructor(
- *this, VTableClass, Base, NearestVBase, NeedsVirtualOffset);
+ *this, Vptr.VTableClass, Vptr.Base, Vptr.NearestVBase);
+
if (!VTableAddressPoint)
return;
@@ -2012,26 +2319,25 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
llvm::Value *VirtualOffset = nullptr;
CharUnits NonVirtualOffset = CharUnits::Zero();
- if (NeedsVirtualOffset) {
+ if (CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*this, Vptr)) {
// We need to use the virtual base offset offset because the virtual base
// might have a different offset in the most derived class.
- VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(*this,
- LoadCXXThis(),
- VTableClass,
- NearestVBase);
- NonVirtualOffset = OffsetFromNearestVBase;
+
+ VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(
+ *this, LoadCXXThisAddress(), Vptr.VTableClass, Vptr.NearestVBase);
+ NonVirtualOffset = Vptr.OffsetFromNearestVBase;
} else {
// We can just use the base offset in the complete class.
- NonVirtualOffset = Base.getBaseOffset();
+ NonVirtualOffset = Vptr.Base.getBaseOffset();
}
// Apply the offsets.
- llvm::Value *VTableField = LoadCXXThis();
+ Address VTableField = LoadCXXThisAddress();
if (!NonVirtualOffset.isZero() || VirtualOffset)
- VTableField = ApplyNonVirtualAndVirtualOffset(*this, VTableField,
- NonVirtualOffset,
- VirtualOffset);
+ VTableField = ApplyNonVirtualAndVirtualOffset(
+ *this, VTableField, NonVirtualOffset, VirtualOffset, Vptr.VTableClass,
+ Vptr.NearestVBase);
// Finally, store the address point. Use the same LLVM types as the field to
// support optimization.
@@ -2041,23 +2347,39 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
->getPointerTo();
VTableField = Builder.CreateBitCast(VTableField, VTablePtrTy->getPointerTo());
VTableAddressPoint = Builder.CreateBitCast(VTableAddressPoint, VTablePtrTy);
+
llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField);
- CGM.DecorateInstruction(Store, CGM.getTBAAInfoForVTablePtr());
+ CGM.DecorateInstructionWithTBAA(Store, CGM.getTBAAInfoForVTablePtr());
+ if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ CGM.getCodeGenOpts().StrictVTablePointers)
+ CGM.DecorateInstructionWithInvariantGroup(Store, Vptr.VTableClass);
}
-void
-CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
- const CXXRecordDecl *NearestVBase,
- CharUnits OffsetFromNearestVBase,
- bool BaseIsNonVirtualPrimaryBase,
- const CXXRecordDecl *VTableClass,
- VisitedVirtualBasesSetTy& VBases) {
+CodeGenFunction::VPtrsVector
+CodeGenFunction::getVTablePointers(const CXXRecordDecl *VTableClass) {
+ CodeGenFunction::VPtrsVector VPtrsResult;
+ VisitedVirtualBasesSetTy VBases;
+ getVTablePointers(BaseSubobject(VTableClass, CharUnits::Zero()),
+ /*NearestVBase=*/nullptr,
+ /*OffsetFromNearestVBase=*/CharUnits::Zero(),
+ /*BaseIsNonVirtualPrimaryBase=*/false, VTableClass, VBases,
+ VPtrsResult);
+ return VPtrsResult;
+}
+
+void CodeGenFunction::getVTablePointers(BaseSubobject Base,
+ const CXXRecordDecl *NearestVBase,
+ CharUnits OffsetFromNearestVBase,
+ bool BaseIsNonVirtualPrimaryBase,
+ const CXXRecordDecl *VTableClass,
+ VisitedVirtualBasesSetTy &VBases,
+ VPtrsVector &Vptrs) {
// If this base is a non-virtual primary base the address point has already
// been set.
if (!BaseIsNonVirtualPrimaryBase) {
// Initialize the vtable pointer for this base.
- InitializeVTablePointer(Base, NearestVBase, OffsetFromNearestVBase,
- VTableClass);
+ VPtr Vptr = {Base, NearestVBase, OffsetFromNearestVBase, VTableClass};
+ Vptrs.push_back(Vptr);
}
const CXXRecordDecl *RD = Base.getBase();
@@ -2095,11 +2417,10 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl;
}
- InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset),
- I.isVirtual() ? BaseDecl : NearestVBase,
- BaseOffsetFromNearestVBase,
- BaseDeclIsNonVirtualPrimaryBase,
- VTableClass, VBases);
+ getVTablePointers(
+ BaseSubobject(BaseDecl, BaseOffset),
+ I.isVirtual() ? BaseDecl : NearestVBase, BaseOffsetFromNearestVBase,
+ BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs);
}
}
@@ -2109,21 +2430,25 @@ void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {
return;
// Initialize the vtable pointers for this class and all of its bases.
- VisitedVirtualBasesSetTy VBases;
- InitializeVTablePointers(BaseSubobject(RD, CharUnits::Zero()),
- /*NearestVBase=*/nullptr,
- /*OffsetFromNearestVBase=*/CharUnits::Zero(),
- /*BaseIsNonVirtualPrimaryBase=*/false, RD, VBases);
+ if (CGM.getCXXABI().doStructorsInitializeVPtrs(RD))
+ for (const VPtr &Vptr : getVTablePointers(RD))
+ InitializeVTablePointer(Vptr);
if (RD->getNumVBases())
CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD);
}
-llvm::Value *CodeGenFunction::GetVTablePtr(llvm::Value *This,
- llvm::Type *Ty) {
- llvm::Value *VTablePtrSrc = Builder.CreateBitCast(This, Ty->getPointerTo());
+llvm::Value *CodeGenFunction::GetVTablePtr(Address This,
+ llvm::Type *VTableTy,
+ const CXXRecordDecl *RD) {
+ Address VTablePtrSrc = Builder.CreateElementBitCast(This, VTableTy);
llvm::Instruction *VTable = Builder.CreateLoad(VTablePtrSrc, "vtable");
- CGM.DecorateInstruction(VTable, CGM.getTBAAInfoForVTablePtr());
+ CGM.DecorateInstructionWithTBAA(VTable, CGM.getTBAAInfoForVTablePtr());
+
+ if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ CGM.getCodeGenOpts().StrictVTablePointers)
+ CGM.DecorateInstructionWithInvariantGroup(VTable, RD);
+
return VTable;
}
@@ -2190,19 +2515,10 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T,
if (!ClassDecl->isCompleteDefinition() || !ClassDecl->isDynamicClass())
return;
- SmallString<64> MangledName;
- llvm::raw_svector_ostream Out(MangledName);
- CGM.getCXXABI().getMangleContext().mangleCXXRTTI(T.getUnqualifiedType(),
- Out);
-
- // Blacklist based on the mangled type.
- if (CGM.getContext().getSanitizerBlacklist().isBlacklistedType(Out.str()))
- return;
-
if (!SanOpts.has(SanitizerKind::CFICastStrict))
ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl);
- llvm::BasicBlock *ContBlock = 0;
+ llvm::BasicBlock *ContBlock = nullptr;
if (MayBeNull) {
llvm::Value *DerivedNotNull =
@@ -2216,7 +2532,9 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T,
EmitBlock(CheckBlock);
}
- llvm::Value *VTable = GetVTablePtr(Derived, Int8PtrTy);
+ llvm::Value *VTable =
+ GetVTablePtr(Address(Derived, getPointerAlign()), Int8PtrTy, ClassDecl);
+
EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc);
if (MayBeNull) {
@@ -2234,18 +2552,22 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
SanitizerScope SanScope(this);
- std::string OutName;
- llvm::raw_string_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().mangleCXXVTableBitSet(RD, Out);
-
- llvm::Value *BitSetName = llvm::MetadataAsValue::get(
- getLLVMContext(), llvm::MDString::get(getLLVMContext(), Out.str()));
+ llvm::Metadata *MD =
+ CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
+ llvm::Value *BitSetName = llvm::MetadataAsValue::get(getLLVMContext(), MD);
llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy);
llvm::Value *BitSetTest =
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
{CastedVTable, BitSetName});
+ if (CGM.getCodeGenOpts().SanitizeCfiCrossDso) {
+ if (auto TypeId = CGM.CreateCfiIdForTypeMetadata(MD)) {
+ EmitCfiSlowPathCheck(BitSetTest, TypeId, CastedVTable);
+ return;
+ }
+ }
+
SanitizerMask M;
switch (TCK) {
case CFITCK_VCall:
@@ -2263,9 +2585,9 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
}
llvm::Constant *StaticData[] = {
- EmitCheckSourceLocation(Loc),
- EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)),
- llvm::ConstantInt::get(Int8Ty, TCK),
+ EmitCheckSourceLocation(Loc),
+ EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)),
+ llvm::ConstantInt::get(Int8Ty, TCK),
};
EmitCheck(std::make_pair(BitSetTest, M), "cfi_bad_type", StaticData,
CastedVTable);
@@ -2405,8 +2727,8 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() {
CallArgList CallArgs;
QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda));
- llvm::Value *ThisPtr = GetAddrOfBlockDecl(variable, false);
- CallArgs.add(RValue::get(ThisPtr), ThisType);
+ Address ThisPtr = GetAddrOfBlockDecl(variable, false);
+ CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType);
// Add the rest of the parameters.
for (auto param : BD->params())
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
index d97e405..ba7dcf7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
@@ -19,6 +19,7 @@
#include "CGCleanup.h"
#include "CodeGenFunction.h"
+#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace CodeGen;
@@ -27,7 +28,7 @@ bool DominatingValue<RValue>::saved_type::needsSaving(RValue rv) {
if (rv.isScalar())
return DominatingLLVMValue::needsSaving(rv.getScalarVal());
if (rv.isAggregate())
- return DominatingLLVMValue::needsSaving(rv.getAggregateAddr());
+ return DominatingLLVMValue::needsSaving(rv.getAggregatePointer());
return true;
}
@@ -41,9 +42,10 @@ DominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) {
return saved_type(V, ScalarLiteral);
// Everything else needs an alloca.
- llvm::Value *addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue");
+ Address addr =
+ CGF.CreateDefaultAlignTempAlloca(V->getType(), "saved-rvalue");
CGF.Builder.CreateStore(V, addr);
- return saved_type(addr, ScalarAddress);
+ return saved_type(addr.getPointer(), ScalarAddress);
}
if (rv.isComplex()) {
@@ -51,42 +53,56 @@ DominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) {
llvm::Type *ComplexTy =
llvm::StructType::get(V.first->getType(), V.second->getType(),
(void*) nullptr);
- llvm::Value *addr = CGF.CreateTempAlloca(ComplexTy, "saved-complex");
+ Address addr = CGF.CreateDefaultAlignTempAlloca(ComplexTy, "saved-complex");
CGF.Builder.CreateStore(V.first,
- CGF.Builder.CreateStructGEP(ComplexTy, addr, 0));
+ CGF.Builder.CreateStructGEP(addr, 0, CharUnits()));
+ CharUnits offset = CharUnits::fromQuantity(
+ CGF.CGM.getDataLayout().getTypeAllocSize(V.first->getType()));
CGF.Builder.CreateStore(V.second,
- CGF.Builder.CreateStructGEP(ComplexTy, addr, 1));
- return saved_type(addr, ComplexAddress);
+ CGF.Builder.CreateStructGEP(addr, 1, offset));
+ return saved_type(addr.getPointer(), ComplexAddress);
}
assert(rv.isAggregate());
- llvm::Value *V = rv.getAggregateAddr(); // TODO: volatile?
- if (!DominatingLLVMValue::needsSaving(V))
- return saved_type(V, AggregateLiteral);
-
- llvm::Value *addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue");
- CGF.Builder.CreateStore(V, addr);
- return saved_type(addr, AggregateAddress);
+ Address V = rv.getAggregateAddress(); // TODO: volatile?
+ if (!DominatingLLVMValue::needsSaving(V.getPointer()))
+ return saved_type(V.getPointer(), AggregateLiteral,
+ V.getAlignment().getQuantity());
+
+ Address addr =
+ CGF.CreateTempAlloca(V.getType(), CGF.getPointerAlign(), "saved-rvalue");
+ CGF.Builder.CreateStore(V.getPointer(), addr);
+ return saved_type(addr.getPointer(), AggregateAddress,
+ V.getAlignment().getQuantity());
}
/// Given a saved r-value produced by SaveRValue, perform the code
/// necessary to restore it to usability at the current insertion
/// point.
RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) {
+ auto getSavingAddress = [&](llvm::Value *value) {
+ auto alignment = cast<llvm::AllocaInst>(value)->getAlignment();
+ return Address(value, CharUnits::fromQuantity(alignment));
+ };
switch (K) {
case ScalarLiteral:
return RValue::get(Value);
case ScalarAddress:
- return RValue::get(CGF.Builder.CreateLoad(Value));
+ return RValue::get(CGF.Builder.CreateLoad(getSavingAddress(Value)));
case AggregateLiteral:
- return RValue::getAggregate(Value);
- case AggregateAddress:
- return RValue::getAggregate(CGF.Builder.CreateLoad(Value));
+ return RValue::getAggregate(Address(Value, CharUnits::fromQuantity(Align)));
+ case AggregateAddress: {
+ auto addr = CGF.Builder.CreateLoad(getSavingAddress(Value));
+ return RValue::getAggregate(Address(addr, CharUnits::fromQuantity(Align)));
+ }
case ComplexAddress: {
- llvm::Value *real =
- CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(nullptr, Value, 0));
- llvm::Value *imag =
- CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(nullptr, Value, 1));
+ Address address = getSavingAddress(Value);
+ llvm::Value *real = CGF.Builder.CreateLoad(
+ CGF.Builder.CreateStructGEP(address, 0, CharUnits()));
+ CharUnits offset = CharUnits::fromQuantity(
+ CGF.CGM.getDataLayout().getTypeAllocSize(real->getType()));
+ llvm::Value *imag = CGF.Builder.CreateLoad(
+ CGF.Builder.CreateStructGEP(address, 1, offset));
return RValue::getComplex(real, imag);
}
}
@@ -96,6 +112,7 @@ RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) {
/// Push an entry of the given size onto this protected-scope stack.
char *EHScopeStack::allocate(size_t Size) {
+ Size = llvm::RoundUpToAlignment(Size, ScopeStackAlignment);
if (!StartOfBuffer) {
unsigned Capacity = 1024;
while (Capacity < Size) Capacity *= 2;
@@ -125,6 +142,10 @@ char *EHScopeStack::allocate(size_t Size) {
return StartOfData;
}
+void EHScopeStack::deallocate(size_t Size) {
+ StartOfData += llvm::RoundUpToAlignment(Size, ScopeStackAlignment);
+}
+
bool EHScopeStack::containsOnlyLifetimeMarkers(
EHScopeStack::stable_iterator Old) const {
for (EHScopeStack::iterator it = begin(); stabilize(it) != Old; it++) {
@@ -147,26 +168,8 @@ EHScopeStack::getInnermostActiveNormalCleanup() const {
return stable_end();
}
-EHScopeStack::stable_iterator EHScopeStack::getInnermostActiveEHScope() const {
- for (stable_iterator si = getInnermostEHScope(), se = stable_end();
- si != se; ) {
- // Skip over inactive cleanups.
- EHCleanupScope *cleanup = dyn_cast<EHCleanupScope>(&*find(si));
- if (cleanup && !cleanup->isActive()) {
- si = cleanup->getEnclosingEHScope();
- continue;
- }
-
- // All other scopes are always active.
- return si;
- }
-
- return stable_end();
-}
-
void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
- assert(((Size % sizeof(void*)) == 0) && "cleanup type is misaligned");
char *Buffer = allocate(EHCleanupScope::getSizeForCleanupSize(Size));
bool IsNormalCleanup = Kind & NormalCleanup;
bool IsEHCleanup = Kind & EHCleanup;
@@ -194,7 +197,7 @@ void EHScopeStack::popCleanup() {
EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin());
InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup();
InnermostEHScope = Cleanup.getEnclosingEHScope();
- StartOfData += Cleanup.getAllocatedSize();
+ deallocate(Cleanup.getAllocatedSize());
// Destroy the cleanup.
Cleanup.Destroy();
@@ -224,7 +227,7 @@ void EHScopeStack::popFilter() {
assert(!empty() && "popping exception stack when not empty");
EHFilterScope &filter = cast<EHFilterScope>(*begin());
- StartOfData += EHFilterScope::getSizeForNumFilters(filter.getNumFilters());
+ deallocate(EHFilterScope::getSizeForNumFilters(filter.getNumFilters()));
InnermostEHScope = filter.getEnclosingEHScope();
}
@@ -264,8 +267,8 @@ void EHScopeStack::popNullFixups() {
void CodeGenFunction::initFullExprCleanup() {
// Create a variable to decide whether the cleanup needs to be run.
- llvm::AllocaInst *active
- = CreateTempAlloca(Builder.getInt1Ty(), "cleanup.cond");
+ Address active = CreateTempAlloca(Builder.getInt1Ty(), CharUnits::One(),
+ "cleanup.cond");
// Initialize it to false at a site that's guaranteed to be run
// before each evaluation.
@@ -276,7 +279,7 @@ void CodeGenFunction::initFullExprCleanup() {
// Set that as the active flag in the cleanup.
EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin());
- assert(!cleanup.getActiveFlag() && "cleanup already has active flag?");
+ assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?");
cleanup.setActiveFlag(active);
if (cleanup.isNormalCleanup()) cleanup.setTestFlagInNormalCleanup();
@@ -285,6 +288,19 @@ void CodeGenFunction::initFullExprCleanup() {
void EHScopeStack::Cleanup::anchor() {}
+static void createStoreInstBefore(llvm::Value *value, Address addr,
+ llvm::Instruction *beforeInst) {
+ auto store = new llvm::StoreInst(value, addr.getPointer(), beforeInst);
+ store->setAlignment(addr.getAlignment().getQuantity());
+}
+
+static llvm::LoadInst *createLoadInstBefore(Address addr, const Twine &name,
+ llvm::Instruction *beforeInst) {
+ auto load = new llvm::LoadInst(addr.getPointer(), name, beforeInst);
+ load->setAlignment(addr.getAlignment().getQuantity());
+ return load;
+}
+
/// All the branch fixups on the EH stack have propagated out past the
/// outermost normal cleanup; resolve them all by adding cases to the
/// given switch instruction.
@@ -307,9 +323,9 @@ static void ResolveAllBranchFixups(CodeGenFunction &CGF,
// i.e. where there's an unresolved fixup inside a single cleanup
// entry which we're currently popping.
if (Fixup.OptimisticBranchBlock == nullptr) {
- new llvm::StoreInst(CGF.Builder.getInt32(Fixup.DestinationIndex),
- CGF.getNormalCleanupDestSlot(),
- Fixup.InitialBranch);
+ createStoreInstBefore(CGF.Builder.getInt32(Fixup.DestinationIndex),
+ CGF.getNormalCleanupDestSlot(),
+ Fixup.InitialBranch);
Fixup.InitialBranch->setSuccessor(0, CleanupEntry);
}
@@ -335,8 +351,8 @@ static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF,
if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) {
assert(Br->isUnconditional());
- llvm::LoadInst *Load =
- new llvm::LoadInst(CGF.getNormalCleanupDestSlot(), "cleanup.dest", Term);
+ auto Load = createLoadInstBefore(CGF.getNormalCleanupDestSlot(),
+ "cleanup.dest", Term);
llvm::SwitchInst *Switch =
llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block);
Br->eraseFromParent();
@@ -481,20 +497,11 @@ static llvm::BasicBlock *SimplifyCleanupEntry(CodeGenFunction &CGF,
static void EmitCleanup(CodeGenFunction &CGF,
EHScopeStack::Cleanup *Fn,
EHScopeStack::Cleanup::Flags flags,
- llvm::Value *ActiveFlag) {
- // Itanium EH cleanups occur within a terminate scope. Microsoft SEH doesn't
- // have this behavior, and the Microsoft C++ runtime will call terminate for
- // us if the cleanup throws.
- bool PushedTerminate = false;
- if (flags.isForEHCleanup() && !CGF.getTarget().getCXXABI().isMicrosoft()) {
- CGF.EHStack.pushTerminate();
- PushedTerminate = true;
- }
-
+ Address ActiveFlag) {
// If there's an active flag, load it and skip the cleanup if it's
// false.
llvm::BasicBlock *ContBB = nullptr;
- if (ActiveFlag) {
+ if (ActiveFlag.isValid()) {
ContBB = CGF.createBasicBlock("cleanup.done");
llvm::BasicBlock *CleanupBB = CGF.createBasicBlock("cleanup.action");
llvm::Value *IsActive
@@ -508,12 +515,8 @@ static void EmitCleanup(CodeGenFunction &CGF,
assert(CGF.HaveInsertPoint() && "cleanup ended with no insertion point?");
// Emit the continuation block if there was an active flag.
- if (ActiveFlag)
+ if (ActiveFlag.isValid())
CGF.EmitBlock(ContBB);
-
- // Leave the terminate scope.
- if (PushedTerminate)
- CGF.EHStack.popTerminate();
}
static void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit,
@@ -588,10 +591,12 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
// Remember activation information.
bool IsActive = Scope.isActive();
- llvm::Value *NormalActiveFlag =
- Scope.shouldTestFlagInNormalCleanup() ? Scope.getActiveFlag() : nullptr;
- llvm::Value *EHActiveFlag =
- Scope.shouldTestFlagInEHCleanup() ? Scope.getActiveFlag() : nullptr;
+ Address NormalActiveFlag =
+ Scope.shouldTestFlagInNormalCleanup() ? Scope.getActiveFlag()
+ : Address::invalid();
+ Address EHActiveFlag =
+ Scope.shouldTestFlagInEHCleanup() ? Scope.getActiveFlag()
+ : Address::invalid();
// Check whether we need an EH cleanup. This is only true if we've
// generated a lazy EH cleanup block.
@@ -671,16 +676,25 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
return;
}
- // Copy the cleanup emission data out. Note that SmallVector
- // guarantees maximal alignment for its buffer regardless of its
- // type parameter.
- SmallVector<char, 8*sizeof(void*)> CleanupBuffer;
- CleanupBuffer.reserve(Scope.getCleanupSize());
- memcpy(CleanupBuffer.data(),
- Scope.getCleanupBuffer(), Scope.getCleanupSize());
- CleanupBuffer.set_size(Scope.getCleanupSize());
- EHScopeStack::Cleanup *Fn =
- reinterpret_cast<EHScopeStack::Cleanup*>(CleanupBuffer.data());
+ // Copy the cleanup emission data out. This uses either a stack
+ // array or malloc'd memory, depending on the size, which is
+ // behavior that SmallVector would provide, if we could use it
+ // here. Unfortunately, if you ask for a SmallVector<char>, the
+ // alignment isn't sufficient.
+ auto *CleanupSource = reinterpret_cast<char *>(Scope.getCleanupBuffer());
+ llvm::AlignedCharArray<EHScopeStack::ScopeStackAlignment, 8 * sizeof(void *)> CleanupBufferStack;
+ std::unique_ptr<char[]> CleanupBufferHeap;
+ size_t CleanupSize = Scope.getCleanupSize();
+ EHScopeStack::Cleanup *Fn;
+
+ if (CleanupSize <= sizeof(CleanupBufferStack)) {
+ memcpy(CleanupBufferStack.buffer, CleanupSource, CleanupSize);
+ Fn = reinterpret_cast<EHScopeStack::Cleanup *>(CleanupBufferStack.buffer);
+ } else {
+ CleanupBufferHeap.reset(new char[CleanupSize]);
+ memcpy(CleanupBufferHeap.get(), CleanupSource, CleanupSize);
+ Fn = reinterpret_cast<EHScopeStack::Cleanup *>(CleanupBufferHeap.get());
+ }
EHScopeStack::Cleanup::Flags cleanupFlags;
if (Scope.isNormalCleanup())
@@ -761,7 +775,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
// Clean up the possibly dead store to the cleanup dest slot.
llvm::Instruction *NormalCleanupDestSlot =
- cast<llvm::Instruction>(getNormalCleanupDestSlot());
+ cast<llvm::Instruction>(getNormalCleanupDestSlot().getPointer());
if (NormalCleanupDestSlot->hasOneUse()) {
NormalCleanupDestSlot->user_back()->eraseFromParent();
NormalCleanupDestSlot->eraseFromParent();
@@ -787,7 +801,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
const unsigned SwitchCapacity = 10;
llvm::LoadInst *Load =
- new llvm::LoadInst(getNormalCleanupDestSlot(), "cleanup.dest");
+ createLoadInstBefore(getNormalCleanupDestSlot(), "cleanup.dest",
+ nullptr);
llvm::SwitchInst *Switch =
llvm::SwitchInst::Create(Load, Default, SwitchCapacity);
@@ -833,9 +848,9 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
BranchFixup &Fixup = EHStack.getBranchFixup(I);
if (!Fixup.Destination) continue;
if (!Fixup.OptimisticBranchBlock) {
- new llvm::StoreInst(Builder.getInt32(Fixup.DestinationIndex),
- getNormalCleanupDestSlot(),
- Fixup.InitialBranch);
+ createStoreInstBefore(Builder.getInt32(Fixup.DestinationIndex),
+ getNormalCleanupDestSlot(),
+ Fixup.InitialBranch);
Fixup.InitialBranch->setSuccessor(0, NormalEntry);
}
Fixup.OptimisticBranchBlock = NormalExit;
@@ -893,15 +908,40 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
EmitBlock(EHEntry);
+ llvm::BasicBlock *NextAction = getEHDispatchBlock(EHParent);
+
+ // Push a terminate scope or cleanupendpad scope around the potentially
+ // throwing cleanups. For funclet EH personalities, the cleanupendpad models
+ // program termination when cleanups throw.
+ bool PushedTerminate = false;
+ SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
+ CurrentFuncletPad);
+ llvm::CleanupPadInst *CPI = nullptr;
+ if (!EHPersonality::get(*this).usesFuncletPads()) {
+ EHStack.pushTerminate();
+ PushedTerminate = true;
+ } else {
+ llvm::Value *ParentPad = CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
+ CurrentFuncletPad = CPI = Builder.CreateCleanupPad(ParentPad);
+ }
+
// We only actually emit the cleanup code if the cleanup is either
// active or was used before it was deactivated.
- if (EHActiveFlag || IsActive) {
-
+ if (EHActiveFlag.isValid() || IsActive) {
cleanupFlags.setIsForEHCleanup();
EmitCleanup(*this, Fn, cleanupFlags, EHActiveFlag);
}
- Builder.CreateBr(getEHDispatchBlock(EHParent));
+ if (CPI)
+ Builder.CreateCleanupRet(CPI, NextAction);
+ else
+ Builder.CreateBr(NextAction);
+
+ // Leave the terminate scope.
+ if (PushedTerminate)
+ EHStack.popTerminate();
Builder.restoreIP(SavedIP);
@@ -977,7 +1017,7 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {
// Store the index at the start.
llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex());
- new llvm::StoreInst(Index, getNormalCleanupDestSlot(), BI);
+ createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI);
// Adjust BI to point to the first cleanup block.
{
@@ -1096,23 +1136,24 @@ static void SetupCleanupBlockActivation(CodeGenFunction &CGF,
// If it hasn't yet been used as either, we're done.
if (!needFlag) return;
- llvm::AllocaInst *var = Scope.getActiveFlag();
- if (!var) {
- var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "cleanup.isactive");
+ Address var = Scope.getActiveFlag();
+ if (!var.isValid()) {
+ var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), CharUnits::One(),
+ "cleanup.isactive");
Scope.setActiveFlag(var);
assert(dominatingIP && "no existing variable and no dominating IP!");
// Initialize to true or false depending on whether it was
// active up to this point.
- llvm::Value *value = CGF.Builder.getInt1(kind == ForDeactivation);
+ llvm::Constant *value = CGF.Builder.getInt1(kind == ForDeactivation);
// If we're in a conditional block, ignore the dominating IP and
// use the outermost conditional branch.
if (CGF.isInConditionalBranch()) {
CGF.setBeforeOutermostConditional(value, var);
} else {
- new llvm::StoreInst(value, var, dominatingIP);
+ createStoreInstBefore(value, var, dominatingIP);
}
}
@@ -1154,17 +1195,17 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C,
Scope.setActive(false);
}
-llvm::Value *CodeGenFunction::getNormalCleanupDestSlot() {
+Address CodeGenFunction::getNormalCleanupDestSlot() {
if (!NormalCleanupDest)
NormalCleanupDest =
CreateTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot");
- return NormalCleanupDest;
+ return Address(NormalCleanupDest, CharUnits::fromQuantity(4));
}
/// Emits all the code to cause the given temporary to be cleaned up.
void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary,
QualType TempType,
- llvm::Value *Ptr) {
+ Address Ptr) {
pushDestroy(NormalAndEHCleanup, Ptr, TempType, destroyCXXObject,
/*useEHCleanup*/ true);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h
index 81c6412..909f00b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.h
@@ -15,6 +15,8 @@
#define LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H
#include "EHScopeStack.h"
+
+#include "Address.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
@@ -26,7 +28,17 @@ class AllocaInst;
}
namespace clang {
+class FunctionDecl;
namespace CodeGen {
+class CodeGenModule;
+class CodeGenFunction;
+
+/// The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the
+/// type of a catch handler, so we use this wrapper.
+struct CatchTypeInfo {
+ llvm::Constant *RTTI;
+ unsigned Flags;
+};
/// A protected scope for zero-cost EH handling.
class EHScope {
@@ -37,9 +49,9 @@ class EHScope {
class CommonBitFields {
friend class EHScope;
- unsigned Kind : 2;
+ unsigned Kind : 3;
};
- enum { NumCommonBits = 2 };
+ enum { NumCommonBits = 3 };
protected:
class CatchBitFields {
@@ -78,7 +90,7 @@ protected:
/// The number of fixups required by enclosing scopes (not including
/// this one). If this is the top cleanup scope, all the fixups
/// from this index onwards belong to this scope.
- unsigned FixupDepth : 32 - 18 - NumCommonBits; // currently 13
+ unsigned FixupDepth : 32 - 18 - NumCommonBits; // currently 12
};
class FilterBitFields {
@@ -96,7 +108,7 @@ protected:
};
public:
- enum Kind { Cleanup, Catch, Terminate, Filter };
+ enum Kind { Cleanup, Catch, Terminate, Filter, PadEnd };
EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope)
: CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr),
@@ -148,12 +160,12 @@ public:
struct Handler {
/// A type info value, or null (C++ null, not an LLVM null pointer)
/// for a catch-all.
- llvm::Constant *Type;
+ CatchTypeInfo Type;
/// The catch handler for this type.
llvm::BasicBlock *Block;
- bool isCatchAll() const { return Type == nullptr; }
+ bool isCatchAll() const { return Type.RTTI == nullptr; }
};
private:
@@ -183,11 +195,17 @@ public:
}
void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) {
- setHandler(I, /*catchall*/ nullptr, Block);
+ setHandler(I, CatchTypeInfo{nullptr, 0}, Block);
}
void setHandler(unsigned I, llvm::Constant *Type, llvm::BasicBlock *Block) {
assert(I < getNumHandlers());
+ getHandlers()[I].Type = CatchTypeInfo{Type, 0};
+ getHandlers()[I].Block = Block;
+ }
+
+ void setHandler(unsigned I, CatchTypeInfo Type, llvm::BasicBlock *Block) {
+ assert(I < getNumHandlers());
getHandlers()[I].Type = Type;
getHandlers()[I].Block = Block;
}
@@ -216,7 +234,7 @@ public:
};
/// A cleanup scope which generates the cleanup blocks lazily.
-class EHCleanupScope : public EHScope {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EHCleanupScope : public EHScope {
/// The nearest normal cleanup scope enclosing this one.
EHScopeStack::stable_iterator EnclosingNormal;
@@ -302,8 +320,14 @@ public:
bool isLifetimeMarker() const { return CleanupBits.IsLifetimeMarker; }
void setLifetimeMarker() { CleanupBits.IsLifetimeMarker = true; }
- llvm::AllocaInst *getActiveFlag() const { return ActiveFlag; }
- void setActiveFlag(llvm::AllocaInst *Var) { ActiveFlag = Var; }
+ bool hasActiveFlag() const { return ActiveFlag != nullptr; }
+ Address getActiveFlag() const {
+ return Address(ActiveFlag, CharUnits::One());
+ }
+ void setActiveFlag(Address Var) {
+ assert(Var.getAlignment().isOne());
+ ActiveFlag = cast<llvm::AllocaInst>(Var.getPointer());
+ }
void setTestFlagInNormalCleanup() {
CleanupBits.TestFlagInNormalCleanup = true;
@@ -396,6 +420,15 @@ public:
return (Scope->getKind() == Cleanup);
}
};
+// NOTE: there's a bunch of different data classes tacked on after an
+// EHCleanupScope. It is asserted (in EHScopeStack::pushCleanup*) that
+// they don't require greater alignment than ScopeStackAlignment. So,
+// EHCleanupScope ought to have alignment equal to that -- not more
+// (would be misaligned by the stack allocator), and not less (would
+// break the appended classes).
+static_assert(llvm::AlignOf<EHCleanupScope>::Alignment ==
+ EHScopeStack::ScopeStackAlignment,
+ "EHCleanupScope expected alignment");
/// An exceptions scope which filters exceptions thrown through it.
/// Only exceptions matching the filter types will be permitted to be
@@ -454,6 +487,17 @@ public:
}
};
+class EHPadEndScope : public EHScope {
+public:
+ EHPadEndScope(EHScopeStack::stable_iterator enclosingEHScope)
+ : EHScope(PadEnd, enclosingEHScope) {}
+ static size_t getSize() { return sizeof(EHPadEndScope); }
+
+ static bool classof(const EHScope *scope) {
+ return scope->getKind() == PadEnd;
+ }
+};
+
/// A non-stable pointer into the scope stack.
class EHScopeStack::iterator {
char *Ptr;
@@ -472,27 +516,31 @@ public:
EHScope &operator*() const { return *get(); }
iterator &operator++() {
+ size_t Size;
switch (get()->getKind()) {
case EHScope::Catch:
- Ptr += EHCatchScope::getSizeForNumHandlers(
- static_cast<const EHCatchScope*>(get())->getNumHandlers());
+ Size = EHCatchScope::getSizeForNumHandlers(
+ static_cast<const EHCatchScope *>(get())->getNumHandlers());
break;
case EHScope::Filter:
- Ptr += EHFilterScope::getSizeForNumFilters(
- static_cast<const EHFilterScope*>(get())->getNumFilters());
+ Size = EHFilterScope::getSizeForNumFilters(
+ static_cast<const EHFilterScope *>(get())->getNumFilters());
break;
case EHScope::Cleanup:
- Ptr += static_cast<const EHCleanupScope*>(get())
- ->getAllocatedSize();
+ Size = static_cast<const EHCleanupScope *>(get())->getAllocatedSize();
break;
case EHScope::Terminate:
- Ptr += EHTerminateScope::getSize();
+ Size = EHTerminateScope::getSize();
break;
- }
+ case EHScope::PadEnd:
+ Size = EHPadEndScope::getSize();
+ break;
+ }
+ Ptr += llvm::RoundUpToAlignment(Size, ScopeStackAlignment);
return *this;
}
@@ -528,7 +576,7 @@ inline void EHScopeStack::popCatch() {
EHCatchScope &scope = cast<EHCatchScope>(*begin());
InnermostEHScope = scope.getEnclosingEHScope();
- StartOfData += EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers());
+ deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers()));
}
inline void EHScopeStack::popTerminate() {
@@ -536,7 +584,7 @@ inline void EHScopeStack::popTerminate() {
EHTerminateScope &scope = cast<EHTerminateScope>(*begin());
InnermostEHScope = scope.getEnclosingEHScope();
- StartOfData += EHTerminateScope::getSize();
+ deallocate(EHTerminateScope::getSize());
}
inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
@@ -551,6 +599,43 @@ EHScopeStack::stabilize(iterator ir) const {
return stable_iterator(EndOfBuffer - ir.Ptr);
}
+/// The exceptions personality for a function.
+struct EHPersonality {
+ const char *PersonalityFn;
+
+ // If this is non-null, this personality requires a non-standard
+ // function for rethrowing an exception after a catchall cleanup.
+ // This function must have prototype void(void*).
+ const char *CatchallRethrowFn;
+
+ static const EHPersonality &get(CodeGenModule &CGM, const FunctionDecl *FD);
+ static const EHPersonality &get(CodeGenFunction &CGF);
+
+ static const EHPersonality GNU_C;
+ static const EHPersonality GNU_C_SJLJ;
+ static const EHPersonality GNU_C_SEH;
+ static const EHPersonality GNU_ObjC;
+ static const EHPersonality GNUstep_ObjC;
+ static const EHPersonality GNU_ObjCXX;
+ static const EHPersonality NeXT_ObjC;
+ static const EHPersonality GNU_CPlusPlus;
+ static const EHPersonality GNU_CPlusPlus_SJLJ;
+ static const EHPersonality GNU_CPlusPlus_SEH;
+ static const EHPersonality MSVC_except_handler;
+ static const EHPersonality MSVC_C_specific_handler;
+ static const EHPersonality MSVC_CxxFrameHandler3;
+
+ /// Does this personality use landingpads or the family of pad instructions
+ /// designed to form funclets?
+ bool usesFuncletPads() const { return isMSVCPersonality(); }
+
+ bool isMSVCPersonality() const {
+ return this == &MSVC_except_handler || this == &MSVC_C_specific_handler ||
+ this == &MSVC_CxxFrameHandler3;
+ }
+
+ bool isMSVCXXPersonality() const { return this == &MSVC_CxxFrameHandler3; }
+};
}
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
index 93a2287..5df8519 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -28,6 +28,7 @@
#include "clang/Basic/Version.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
@@ -37,7 +38,6 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
-#include "llvm/Support/Dwarf.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
using namespace clang;
@@ -45,7 +45,10 @@ using namespace clang::CodeGen;
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
: CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
+ DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs),
DBuilder(CGM.getModule()) {
+ for (const auto &KV : CGM.getCodeGenOpts().DebugPrefixMap)
+ DebugPrefixMap[KV.first] = KV.second;
CreateCompileUnit();
}
@@ -56,54 +59,63 @@ CGDebugInfo::~CGDebugInfo() {
ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
SourceLocation TemporaryLocation)
- : CGF(CGF) {
+ : CGF(&CGF) {
init(TemporaryLocation);
}
ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
bool DefaultToEmpty,
SourceLocation TemporaryLocation)
- : CGF(CGF) {
+ : CGF(&CGF) {
init(TemporaryLocation, DefaultToEmpty);
}
void ApplyDebugLocation::init(SourceLocation TemporaryLocation,
bool DefaultToEmpty) {
- if (auto *DI = CGF.getDebugInfo()) {
- OriginalLocation = CGF.Builder.getCurrentDebugLocation();
- if (TemporaryLocation.isInvalid()) {
- if (DefaultToEmpty)
- CGF.Builder.SetCurrentDebugLocation(llvm::DebugLoc());
- else {
- // Construct a location that has a valid scope, but no line info.
- assert(!DI->LexicalBlockStack.empty());
- CGF.Builder.SetCurrentDebugLocation(
- llvm::DebugLoc::get(0, 0, DI->LexicalBlockStack.back()));
- }
- } else
- DI->EmitLocation(CGF.Builder, TemporaryLocation);
+ auto *DI = CGF->getDebugInfo();
+ if (!DI) {
+ CGF = nullptr;
+ return;
+ }
+
+ OriginalLocation = CGF->Builder.getCurrentDebugLocation();
+ if (TemporaryLocation.isValid()) {
+ DI->EmitLocation(CGF->Builder, TemporaryLocation);
+ return;
}
+
+ if (DefaultToEmpty) {
+ CGF->Builder.SetCurrentDebugLocation(llvm::DebugLoc());
+ return;
+ }
+
+ // Construct a location that has a valid scope, but no line info.
+ assert(!DI->LexicalBlockStack.empty());
+ CGF->Builder.SetCurrentDebugLocation(
+ llvm::DebugLoc::get(0, 0, DI->LexicalBlockStack.back()));
}
ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, const Expr *E)
- : CGF(CGF) {
+ : CGF(&CGF) {
init(E->getExprLoc());
}
ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc)
- : CGF(CGF) {
- if (CGF.getDebugInfo()) {
- OriginalLocation = CGF.Builder.getCurrentDebugLocation();
- if (Loc)
- CGF.Builder.SetCurrentDebugLocation(std::move(Loc));
+ : CGF(&CGF) {
+ if (!CGF.getDebugInfo()) {
+ this->CGF = nullptr;
+ return;
}
+ OriginalLocation = CGF.Builder.getCurrentDebugLocation();
+ if (Loc)
+ CGF.Builder.SetCurrentDebugLocation(std::move(Loc));
}
ApplyDebugLocation::~ApplyDebugLocation() {
// Query CGF so the location isn't overwritten when location updates are
// temporarily disabled (for C++ default function arguments)
- if (CGF.getDebugInfo())
- CGF.Builder.SetCurrentDebugLocation(std::move(OriginalLocation));
+ if (CGF)
+ CGF->Builder.SetCurrentDebugLocation(std::move(OriginalLocation));
}
void CGDebugInfo::setLocation(SourceLocation Loc) {
@@ -138,9 +150,16 @@ void CGDebugInfo::setLocation(SourceLocation Loc) {
}
}
-llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context) {
+llvm::DIScope *CGDebugInfo::getDeclContextDescriptor(const Decl *D) {
+ llvm::DIScope *Mod = getParentModuleOrNull(D);
+ return getContextDescriptor(cast<Decl>(D->getDeclContext()),
+ Mod ? Mod : TheCU);
+}
+
+llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context,
+ llvm::DIScope *Default) {
if (!Context)
- return TheCU;
+ return Default;
auto I = RegionMap.find(Context);
if (I != RegionMap.end()) {
@@ -156,7 +175,7 @@ llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context) {
if (!RDecl->isDependentType())
return getOrCreateType(CGM.getContext().getTypeDeclType(RDecl),
getOrCreateMainFile());
- return TheCU;
+ return Default;
}
StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
@@ -164,22 +183,31 @@ StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
IdentifierInfo *FII = FD->getIdentifier();
FunctionTemplateSpecializationInfo *Info =
FD->getTemplateSpecializationInfo();
- if (!Info && FII)
+
+ if (!Info && FII && !CGM.getCodeGenOpts().EmitCodeView)
return FII->getName();
// Otherwise construct human readable name for debug info.
SmallString<128> NS;
llvm::raw_svector_ostream OS(NS);
- FD->printName(OS);
+ PrintingPolicy Policy(CGM.getLangOpts());
- // Add any template specialization args.
- if (Info) {
- const TemplateArgumentList *TArgs = Info->TemplateArguments;
- const TemplateArgument *Args = TArgs->data();
- unsigned NumArgs = TArgs->size();
- PrintingPolicy Policy(CGM.getLangOpts());
- TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, NumArgs,
- Policy);
+ if (CGM.getCodeGenOpts().EmitCodeView) {
+ // Print a fully qualified name like MSVC would.
+ Policy.MSVCFormatting = true;
+ FD->printQualifiedName(OS, Policy);
+ } else {
+ // Print the unqualified name with some template arguments. This is what
+ // DWARF-based debuggers expect.
+ FD->printName(OS);
+ // Add any template specialization args.
+ if (Info) {
+ const TemplateArgumentList *TArgs = Info->TemplateArguments;
+ const TemplateArgument *Args = TArgs->data();
+ unsigned NumArgs = TArgs->size();
+ TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, NumArgs,
+ Policy);
+ }
}
// Copy this name on the side and use its reference.
@@ -197,6 +225,13 @@ StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
} else if (const ObjCInterfaceDecl *OID =
dyn_cast<const ObjCInterfaceDecl>(DC)) {
OS << OID->getName();
+ } else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
+ if (OC->IsClassExtension()) {
+ OS << OC->getClassInterface()->getName();
+ } else {
+ OS << ((const NamedDecl *)OC)->getIdentifier()->getNameStart() << '('
+ << OC->getIdentifier()->getNameStart() << ')';
+ }
} else if (const ObjCCategoryImplDecl *OCD =
dyn_cast<const ObjCCategoryImplDecl>(DC)) {
OS << ((const NamedDecl *)OCD)->getIdentifier()->getNameStart() << '('
@@ -238,14 +273,16 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
// If Location is not valid then use main input file.
- return DBuilder.createFile(TheCU->getFilename(), TheCU->getDirectory());
+ return DBuilder.createFile(remapDIPath(TheCU->getFilename()),
+ remapDIPath(TheCU->getDirectory()));
SourceManager &SM = CGM.getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty())
// If the location is not valid then use main input file.
- return DBuilder.createFile(TheCU->getFilename(), TheCU->getDirectory());
+ return DBuilder.createFile(remapDIPath(TheCU->getFilename()),
+ remapDIPath(TheCU->getDirectory()));
// Cache the results.
const char *fname = PLoc.getFilename();
@@ -257,15 +294,23 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
return cast<llvm::DIFile>(V);
}
- llvm::DIFile *F =
- DBuilder.createFile(PLoc.getFilename(), getCurrentDirname());
+ llvm::DIFile *F = DBuilder.createFile(remapDIPath(PLoc.getFilename()),
+ remapDIPath(getCurrentDirname()));
DIFileCache[fname].reset(F);
return F;
}
llvm::DIFile *CGDebugInfo::getOrCreateMainFile() {
- return DBuilder.createFile(TheCU->getFilename(), TheCU->getDirectory());
+ return DBuilder.createFile(remapDIPath(TheCU->getFilename()),
+ remapDIPath(TheCU->getDirectory()));
+}
+
+std::string CGDebugInfo::remapDIPath(StringRef Path) const {
+ for (const auto &Entry : DebugPrefixMap)
+ if (Path.startswith(Entry.first))
+ return (Twine(Entry.second) + Path.substr(Entry.first.size())).str();
+ return Path.str();
}
unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
@@ -321,7 +366,7 @@ void CGDebugInfo::CreateCompileUnit() {
// file to determine the real absolute path for the file.
std::string MainFileDir;
if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
- MainFileDir = MainFile->getDir()->getName();
+ MainFileDir = remapDIPath(MainFile->getDir()->getName());
if (MainFileDir != ".") {
llvm::SmallString<1024> MainFileDirSS(MainFileDir);
llvm::sys::path::append(MainFileDirSS, MainFileName);
@@ -329,13 +374,6 @@ void CGDebugInfo::CreateCompileUnit() {
}
}
- // Save filename string.
- StringRef Filename = internString(MainFileName);
-
- // Save split dwarf file string.
- std::string SplitDwarfFile = CGM.getCodeGenOpts().SplitDwarfFile;
- StringRef SplitDwarfFilename = internString(SplitDwarfFile);
-
llvm::dwarf::SourceLanguage LangTag;
const LangOptions &LO = CGM.getLangOpts();
if (LO.CPlusPlus) {
@@ -361,13 +399,13 @@ void CGDebugInfo::CreateCompileUnit() {
// Create new compile unit.
// FIXME - Eliminate TheCU.
TheCU = DBuilder.createCompileUnit(
- LangTag, Filename, getCurrentDirname(), Producer, LO.Optimize,
- CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers, SplitDwarfFilename,
+ LangTag, remapDIPath(MainFileName), remapDIPath(getCurrentDirname()),
+ Producer, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers,
+ CGM.getCodeGenOpts().SplitDwarfFile,
DebugKind <= CodeGenOptions::DebugLineTablesOnly
? llvm::DIBuilder::LineTablesOnly
: llvm::DIBuilder::FullDebug,
- 0 /* DWOid */,
- DebugKind != CodeGenOptions::LocTrackingOnly);
+ 0 /* DWOid */, DebugKind != CodeGenOptions::LocTrackingOnly);
}
llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
@@ -438,6 +476,24 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::OCLImage2dArray:
return getOrCreateStructPtrType("opencl_image2d_array_t",
OCLImage2dArrayDITy);
+ case BuiltinType::OCLImage2dDepth:
+ return getOrCreateStructPtrType("opencl_image2d_depth_t",
+ OCLImage2dDepthDITy);
+ case BuiltinType::OCLImage2dArrayDepth:
+ return getOrCreateStructPtrType("opencl_image2d_array_depth_t",
+ OCLImage2dArrayDepthDITy);
+ case BuiltinType::OCLImage2dMSAA:
+ return getOrCreateStructPtrType("opencl_image2d_msaa_t",
+ OCLImage2dMSAADITy);
+ case BuiltinType::OCLImage2dArrayMSAA:
+ return getOrCreateStructPtrType("opencl_image2d_array_msaa_t",
+ OCLImage2dArrayMSAADITy);
+ case BuiltinType::OCLImage2dMSAADepth:
+ return getOrCreateStructPtrType("opencl_image2d_msaa_depth_t",
+ OCLImage2dMSAADepthDITy);
+ case BuiltinType::OCLImage2dArrayMSAADepth:
+ return getOrCreateStructPtrType("opencl_image2d_array_msaa_depth_t",
+ OCLImage2dArrayMSAADepthDITy);
case BuiltinType::OCLImage3d:
return getOrCreateStructPtrType("opencl_image3d_t", OCLImage3dDITy);
case BuiltinType::OCLSampler:
@@ -446,6 +502,14 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
CGM.getContext().getTypeAlign(BT), llvm::dwarf::DW_ATE_unsigned);
case BuiltinType::OCLEvent:
return getOrCreateStructPtrType("opencl_event_t", OCLEventDITy);
+ case BuiltinType::OCLClkEvent:
+ return getOrCreateStructPtrType("opencl_clk_event_t", OCLClkEventDITy);
+ case BuiltinType::OCLQueue:
+ return getOrCreateStructPtrType("opencl_queue_t", OCLQueueDITy);
+ case BuiltinType::OCLNDRange:
+ return getOrCreateStructPtrType("opencl_ndrange_t", OCLNDRangeDITy);
+ case BuiltinType::OCLReserveID:
+ return getOrCreateStructPtrType("opencl_reserve_id_t", OCLReserveIDDITy);
case BuiltinType::UChar:
case BuiltinType::Char_U:
@@ -604,7 +668,6 @@ static SmallString<256> getUniqueTagTypeName(const TagType *Ty,
// a unique string for a type?
llvm::raw_svector_ostream Out(FullName);
CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(QualType(Ty, 0), Out);
- Out.flush();
return FullName;
}
@@ -658,10 +721,6 @@ llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
const Type *Ty,
QualType PointeeTy,
llvm::DIFile *Unit) {
- if (Tag == llvm::dwarf::DW_TAG_reference_type ||
- Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
- return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit));
-
// Bit size, align and offset of the type.
// Size is always the size of a pointer. We can't use getTypeSize here
// because that does not return the correct value for references.
@@ -669,8 +728,13 @@ llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
- Align);
+ if (Tag == llvm::dwarf::DW_TAG_reference_type ||
+ Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
+ return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit),
+ Size, Align);
+ else
+ return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
+ Align);
}
llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
@@ -760,9 +824,9 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
Ty->getTemplateName().getAsTemplateDecl())->getTemplatedDecl();
SourceLocation Loc = AliasDecl->getLocation();
- return DBuilder.createTypedef(
- Src, internString(OS.str()), getOrCreateFile(Loc), getLineNumber(Loc),
- getContextDescriptor(cast<Decl>(AliasDecl->getDeclContext())));
+ return DBuilder.createTypedef(Src, OS.str(), getOrCreateFile(Loc),
+ getLineNumber(Loc),
+ getDeclContextDescriptor(AliasDecl));
}
llvm::DIType *CGDebugInfo::CreateType(const TypedefType *Ty,
@@ -775,7 +839,7 @@ llvm::DIType *CGDebugInfo::CreateType(const TypedefType *Ty,
return DBuilder.createTypedef(
getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit),
Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc),
- getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext())));
+ getDeclContextDescriptor(Ty->getDecl()));
}
llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
@@ -797,7 +861,7 @@ llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
}
llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
- return DBuilder.createSubroutineType(Unit, EltTypeArray);
+ return DBuilder.createSubroutineType(EltTypeArray);
}
/// Convert an AccessSpecifier into the corresponding DINode flag.
@@ -972,7 +1036,7 @@ void CGDebugInfo::CollectRecordFields(
if (MI != StaticDataMemberCache.end()) {
assert(MI->second &&
"Static data member declaration should still exist");
- elements.push_back(cast<llvm::DIDerivedTypeBase>(MI->second));
+ elements.push_back(MI->second);
} else {
auto Field = CreateRecordStaticField(V, RecordTy, record);
elements.push_back(Field);
@@ -1048,7 +1112,7 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType(
if (Func->getExtProtoInfo().RefQualifier == RQ_RValue)
Flags |= llvm::DINode::FlagRValueReference;
- return DBuilder.createSubroutineType(Unit, EltTypeArray, Flags);
+ return DBuilder.createSubroutineType(EltTypeArray, Flags);
}
/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
@@ -1129,7 +1193,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
RecordTy, MethodName, MethodLinkageName, MethodDefUnit, MethodLine,
MethodTy, /*isLocalToUnit=*/false,
/* isDefinition=*/false, Virtuality, VIndex, ContainingType, Flags,
- CGM.getLangOpts().Optimize, nullptr, TParamsArray.get());
+ CGM.getLangOpts().Optimize, TParamsArray.get());
SPCache[Method->getCanonicalDecl()].reset(SP);
@@ -1348,7 +1412,7 @@ llvm::DIType *CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile *Unit) {
/* Function type */
llvm::Metadata *STy = getOrCreateType(Context.IntTy, Unit);
llvm::DITypeRefArray SElements = DBuilder.getOrCreateTypeArray(STy);
- llvm::DIType *SubTy = DBuilder.createSubroutineType(Unit, SElements);
+ llvm::DIType *SubTy = DBuilder.createSubroutineType(SElements);
unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
llvm::DIType *vtbl_ptr_type =
DBuilder.createPointerType(SubTy, Size, 0, "__vtbl_ptr_type");
@@ -1389,8 +1453,21 @@ llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy,
llvm::DIType *CGDebugInfo::getOrCreateInterfaceType(QualType D,
SourceLocation Loc) {
+ return getOrCreateStandaloneType(D, Loc);
+}
+
+llvm::DIType *CGDebugInfo::getOrCreateStandaloneType(QualType D,
+ SourceLocation Loc) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
+ assert(!D.isNull() && "null type");
llvm::DIType *T = getOrCreateType(D, getOrCreateFile(Loc));
+ assert(T && "could not create debug info for type");
+
+ // Composite types with UIDs were already retained by DIBuilder
+ // because they are only referenced by name in the IR.
+ if (auto *CTy = dyn_cast<llvm::DICompositeType>(T))
+ if (!CTy->getIdentifier().empty())
+ return T;
RetainedTypes.push_back(D.getAsOpaquePtr());
return T;
}
@@ -1422,6 +1499,9 @@ void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
if (CXXDecl->isDynamicClass())
return;
+ if (DebugTypeExtRefs && RD->isFromASTFile())
+ return;
+
QualType Ty = CGM.getContext().getRecordType(RD);
llvm::DIType *T = getTypeOrNull(Ty);
if (T && T->isForwardDecl())
@@ -1452,8 +1532,13 @@ static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I,
}
static bool shouldOmitDefinition(CodeGenOptions::DebugInfoKind DebugKind,
+ bool DebugTypeExtRefs,
const RecordDecl *RD,
const LangOptions &LangOpts) {
+ // Does the type exist in an imported clang module?
+ if (DebugTypeExtRefs && RD->isFromASTFile() && RD->getDefinition())
+ return true;
+
if (DebugKind > CodeGenOptions::LimitedDebugInfo)
return false;
@@ -1487,10 +1572,10 @@ static bool shouldOmitDefinition(CodeGenOptions::DebugInfoKind DebugKind,
llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0)));
- if (T || shouldOmitDefinition(DebugKind, RD, CGM.getLangOpts())) {
+ if (T || shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD,
+ CGM.getLangOpts())) {
if (!T)
- T = getOrCreateRecordFwdDecl(
- Ty, getContextDescriptor(cast<Decl>(RD->getDeclContext())));
+ T = getOrCreateRecordFwdDecl(Ty, getDeclContextDescriptor(RD));
return T;
}
@@ -1509,9 +1594,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
// its members. Finally, we create a descriptor for the complete type (which
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
-
- auto *FwdDecl =
- cast<llvm::DICompositeType>(getOrCreateLimitedType(Ty, DefUnit));
+ llvm::DICompositeType *FwdDecl = getOrCreateLimitedType(Ty, DefUnit);
const RecordDecl *D = RD->getDefinition();
if (!D || !D->isCompleteDefinition())
@@ -1593,6 +1676,12 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
if (!ID)
return nullptr;
+ // Return a forward declaration if this type was imported from a clang module.
+ if (DebugTypeExtRefs && ID->isFromASTFile() && ID->getDefinition())
+ return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+ ID->getName(),
+ getDeclContextDescriptor(ID), Unit, 0);
+
// Get overall information about the record type for the debug info.
llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation());
unsigned Line = getLineNumber(ID->getLocation());
@@ -1603,9 +1692,10 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// debug type since we won't be able to lay out the entire type.
ObjCInterfaceDecl *Def = ID->getDefinition();
if (!Def || !Def->getImplementation()) {
+ llvm::DIScope *Mod = getParentModuleOrNull(ID);
llvm::DIType *FwdDecl = DBuilder.createReplaceableCompositeType(
- llvm::dwarf::DW_TAG_structure_type, ID->getName(), TheCU, DefUnit, Line,
- RuntimeLang);
+ llvm::dwarf::DW_TAG_structure_type, ID->getName(), Mod ? Mod : TheCU,
+ DefUnit, Line, RuntimeLang);
ObjCInterfaceCache.push_back(ObjCInterfaceCacheEntry(Ty, FwdDecl, Unit));
return FwdDecl;
}
@@ -1614,10 +1704,15 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
}
llvm::DIModule *
-CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod) {
- auto it = ModuleRefCache.find(Mod.Signature);
- if (it != ModuleRefCache.end())
- return it->second;
+CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
+ bool CreateSkeletonCU) {
+ // Use the Module pointer as the key into the cache. This is a
+ // nullptr if the "Module" is a PCH, which is safe because we don't
+ // support chained PCH debug info, so there can only be a single PCH.
+ const Module *M = Mod.getModuleOrNull();
+ auto ModRef = ModuleCache.find(M);
+ if (ModRef != ModuleCache.end())
+ return cast<llvm::DIModule>(ModRef->second);
// Macro definitions that were defined with "-D" on the command line.
SmallString<128> ConfigMacros;
@@ -1641,17 +1736,26 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod) {
OS << '\"';
}
}
- llvm::DIBuilder DIB(CGM.getModule());
- auto *CU = DIB.createCompileUnit(
- TheCU->getSourceLanguage(), internString(Mod.ModuleName),
- internString(Mod.Path), TheCU->getProducer(), true, StringRef(), 0,
- internString(Mod.ASTFile), llvm::DIBuilder::FullDebug, Mod.Signature);
- llvm::DIModule *ModuleRef =
- DIB.createModule(CU, Mod.ModuleName, ConfigMacros, internString(Mod.Path),
- internString(CGM.getHeaderSearchOpts().Sysroot));
- DIB.finalize();
- ModuleRefCache.insert(std::make_pair(Mod.Signature, ModuleRef));
- return ModuleRef;
+
+ bool IsRootModule = M ? !M->Parent : true;
+ if (CreateSkeletonCU && IsRootModule) {
+ llvm::DIBuilder DIB(CGM.getModule());
+ DIB.createCompileUnit(TheCU->getSourceLanguage(), Mod.getModuleName(),
+ Mod.getPath(), TheCU->getProducer(), true,
+ StringRef(), 0, Mod.getASTFile(),
+ llvm::DIBuilder::FullDebug, Mod.getSignature());
+ DIB.finalize();
+ }
+ llvm::DIModule *Parent =
+ IsRootModule ? nullptr
+ : getOrCreateModuleRef(
+ ExternalASTSource::ASTSourceDescriptor(*M->Parent),
+ CreateSkeletonCU);
+ llvm::DIModule *DIMod =
+ DBuilder.createModule(Parent, Mod.getModuleName(), ConfigMacros,
+ Mod.getPath(), CGM.getHeaderSearchOpts().Sysroot);
+ ModuleCache[M].reset(DIMod);
+ return DIMod;
}
llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
@@ -1669,9 +1773,10 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
if (ID->getImplementation())
Flags |= llvm::DINode::FlagObjcClassComplete;
+ llvm::DIScope *Mod = getParentModuleOrNull(ID);
llvm::DICompositeType *RealDecl = DBuilder.createStructType(
- Unit, ID->getName(), DefUnit, Line, Size, Align, Flags, nullptr,
- llvm::DINodeArray(), RuntimeLang);
+ Mod ? Mod : Unit, ID->getName(), DefUnit, Line, Size, Align, Flags,
+ nullptr, llvm::DINodeArray(), RuntimeLang);
QualType QTy(Ty, 0);
TypeCache[QTy.getAsOpaquePtr()].reset(RealDecl);
@@ -1695,7 +1800,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
}
// Create entries for all of the properties.
- for (const auto *PD : ID->properties()) {
+ auto AddProperty = [&](const ObjCPropertyDecl *PD) {
SourceLocation Loc = PD->getLocation();
llvm::DIFile *PUnit = getOrCreateFile(Loc);
unsigned PLine = getLineNumber(Loc);
@@ -1709,6 +1814,21 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
: getSelectorName(PD->getSetterName()),
PD->getPropertyAttributes(), getOrCreateType(PD->getType(), PUnit));
EltTys.push_back(PropertyNode);
+ };
+ {
+ llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
+ for (const ObjCCategoryDecl *ClassExt : ID->known_extensions())
+ for (auto *PD : ClassExt->properties()) {
+ PropertySet.insert(PD->getIdentifier());
+ AddProperty(PD);
+ }
+ for (const auto *PD : ID->properties()) {
+ // Don't emit duplicate metadata for properties that were already in a
+ // class extension.
+ if (!PropertySet.insert(PD->getIdentifier()).second)
+ continue;
+ AddProperty(PD);
+ }
}
const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID);
@@ -1883,9 +2003,8 @@ llvm::DIType *CGDebugInfo::CreateType(const RValueReferenceType *Ty,
llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
llvm::DIFile *U) {
- uint64_t Size = CGM.getCXXABI().isTypeInfoCalculable(QualType(Ty, 0))
- ? CGM.getContext().getTypeSize(Ty)
- : 0;
+ uint64_t Size =
+ !Ty->isIncompleteType() ? CGM.getContext().getTypeSize(Ty) : 0;
llvm::DIType *ClassType = getOrCreateType(QualType(Ty->getClass(), 0), U);
if (Ty->isMemberDataPointerType())
return DBuilder.createMemberPointerType(
@@ -1906,8 +2025,14 @@ llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
return getOrCreateType(Ty->getValueType(), U);
}
+llvm::DIType* CGDebugInfo::CreateType(const PipeType *Ty,
+ llvm::DIFile *U) {
+ return getOrCreateType(Ty->getElementType(), U);
+}
+
llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
const EnumDecl *ED = Ty->getDecl();
+
uint64_t Size = 0;
uint64_t Align = 0;
if (!ED->getTypeForDecl()->isIncompleteType()) {
@@ -1917,11 +2042,13 @@ llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+ bool isImportedFromModule =
+ DebugTypeExtRefs && ED->isFromASTFile() && ED->getDefinition();
+
// If this is just a forward declaration, construct an appropriately
// marked node and just return it.
- if (!ED->getDefinition()) {
- llvm::DIScope *EDContext =
- getContextDescriptor(cast<Decl>(ED->getDeclContext()));
+ if (isImportedFromModule || !ED->getDefinition()) {
+ llvm::DIScope *EDContext = getDeclContextDescriptor(ED);
llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
StringRef EDName = ED->getName();
@@ -1961,8 +2088,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
- llvm::DIScope *EnumContext =
- getContextDescriptor(cast<Decl>(ED->getDeclContext()));
+ llvm::DIScope *EnumContext = getDeclContextDescriptor(ED);
llvm::DIType *ClassTy =
ED->isFixed() ? getOrCreateType(ED->getIntegerType(), DefUnit) : nullptr;
return DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit,
@@ -2061,9 +2187,8 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
if (auto *T = getTypeOrNull(Ty))
return T;
- // Otherwise create the type.
llvm::DIType *Res = CreateTypeNode(Ty, Unit);
- void *TyPtr = Ty.getAsOpaquePtr();
+ void* TyPtr = Ty.getAsOpaquePtr();
// And update the type cache.
TypeCache[TyPtr].reset(Res);
@@ -2071,28 +2196,36 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
return Res;
}
-unsigned CGDebugInfo::Checksum(const ObjCInterfaceDecl *ID) {
- // The assumption is that the number of ivars can only increase
- // monotonically, so it is safe to just use their current number as
- // a checksum.
- unsigned Sum = 0;
- for (const ObjCIvarDecl *Ivar = ID->all_declared_ivar_begin();
- Ivar != nullptr; Ivar = Ivar->getNextIvar())
- ++Sum;
-
- return Sum;
-}
-
-ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) {
- switch (Ty->getTypeClass()) {
- case Type::ObjCObjectPointer:
- return getObjCInterfaceDecl(
- cast<ObjCObjectPointerType>(Ty)->getPointeeType());
- case Type::ObjCInterface:
- return cast<ObjCInterfaceType>(Ty)->getDecl();
- default:
+llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {
+ // A forward declaration inside a module header does not belong to the module.
+ if (isa<RecordDecl>(D) && !cast<RecordDecl>(D)->getDefinition())
return nullptr;
+ if (DebugTypeExtRefs && D->isFromASTFile()) {
+ // Record a reference to an imported clang module or precompiled header.
+ auto *Reader = CGM.getContext().getExternalSource();
+ auto Idx = D->getOwningModuleID();
+ auto Info = Reader->getSourceDescriptor(Idx);
+ if (Info)
+ return getOrCreateModuleRef(*Info, /*SkeletonCU=*/true);
+ } else if (ClangModuleMap) {
+ // We are building a clang module or a precompiled header.
+ //
+ // TODO: When D is a CXXRecordDecl or a C++ Enum, the ODR applies
+ // and it wouldn't be necessary to specify the parent scope
+ // because the type is already unique by definition (it would look
+ // like the output of -fno-standalone-debug). On the other hand,
+ // the parent scope helps a consumer to quickly locate the object
+ // file where the type's definition is located, so it might be
+ // best to make this behavior a command line or debugger tuning
+ // option.
+ FullSourceLoc Loc(D->getLocation(), CGM.getContext().getSourceManager());
+ if (Module *M = ClangModuleMap->inferModuleFromLocation(Loc)) {
+ auto Info = ExternalASTSource::ASTSourceDescriptor(*M);
+ return getOrCreateModuleRef(Info, /*SkeletonCU=*/false);
+ }
}
+
+ return nullptr;
}
llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
@@ -2156,6 +2289,9 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::Atomic:
return CreateType(cast<AtomicType>(Ty), Unit);
+ case Type::Pipe:
+ return CreateType(cast<PipeType>(Ty), Unit);
+
case Type::TemplateSpecialization:
return CreateType(cast<TemplateSpecializationType>(Ty), Unit);
@@ -2175,11 +2311,11 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
llvm_unreachable("type should have been unwrapped!");
}
-llvm::DIType *CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty,
- llvm::DIFile *Unit) {
+llvm::DICompositeType *CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty,
+ llvm::DIFile *Unit) {
QualType QTy(Ty, 0);
- auto *T = cast_or_null<llvm::DICompositeTypeBase>(getTypeOrNull(QTy));
+ auto *T = cast_or_null<llvm::DICompositeType>(getTypeOrNull(QTy));
// We may have cached a forward decl when we could have created
// a non-forward decl. Go ahead and create a non-forward decl
@@ -2209,8 +2345,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
unsigned Line = getLineNumber(RD->getLocation());
StringRef RDName = getClassName(RD);
- llvm::DIScope *RDContext =
- getContextDescriptor(cast<Decl>(RD->getDeclContext()));
+ llvm::DIScope *RDContext = getDeclContextDescriptor(RD);
// If we ended up creating the type during the context chain construction,
// just return that.
@@ -2306,8 +2441,10 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
FDContext = getOrCreateNameSpace(NSDecl);
else if (const RecordDecl *RDecl =
- dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
- FDContext = getContextDescriptor(cast<Decl>(RDecl));
+ dyn_cast_or_null<RecordDecl>(FD->getDeclContext())) {
+ llvm::DIScope *Mod = getParentModuleOrNull(RDecl);
+ FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU);
+ }
// Collect template parameters.
TParamsArray = CollectFunctionTemplateParams(FD, Unit);
}
@@ -2355,7 +2492,9 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit,
// outside the class by putting it in the global scope.
if (DC->isRecord())
DC = CGM.getContext().getTranslationUnitDecl();
- VDContext = getContextDescriptor(dyn_cast<Decl>(DC));
+
+ llvm::DIScope *Mod = getParentModuleOrNull(VD);
+ VDContext = getContextDescriptor(cast<Decl>(DC), Mod ? Mod : TheCU);
}
llvm::DISubprogram *
@@ -2380,7 +2519,7 @@ CGDebugInfo::getFunctionForwardDeclaration(const FunctionDecl *FD) {
llvm::DISubprogram *SP = DBuilder.createTempFunctionFwdDecl(
DContext, Name, LinkageName, Unit, Line,
getOrCreateFunctionType(FD, FnType, Unit), !FD->isExternallyVisible(),
- false /*declaration*/, 0, Flags, CGM.getLangOpts().Optimize, nullptr,
+ /* isDefinition = */ false, 0, Flags, CGM.getLangOpts().Optimize,
TParamsArray.get(), getFunctionDeclaration(FD));
const FunctionDecl *CanonDecl = cast<FunctionDecl>(FD->getCanonicalDecl());
FwdDeclReplaceMap.emplace_back(std::piecewise_construct,
@@ -2441,7 +2580,7 @@ llvm::DISubprogram *CGDebugInfo::getFunctionDeclaration(const Decl *D) {
return nullptr;
// Setup context.
- auto *S = getContextDescriptor(cast<Decl>(D->getDeclContext()));
+ auto *S = getDeclContextDescriptor(D);
auto MI = SPCache.find(FD->getCanonicalDecl());
if (MI == SPCache.end()) {
@@ -2476,8 +2615,7 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
if (!D || DebugKind <= CodeGenOptions::DebugLineTablesOnly)
// Create fake but valid subroutine type. Otherwise -verify would fail, and
// subprogram DIE will miss DW_AT_decl_file and DW_AT_decl_line fields.
- return DBuilder.createSubroutineType(F,
- DBuilder.getOrCreateTypeArray(None));
+ return DBuilder.createSubroutineType(DBuilder.getOrCreateTypeArray(None));
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
return getOrCreateMethodType(Method, F);
@@ -2495,11 +2633,17 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
Elts.push_back(getOrCreateType(ResultTy, F));
// "self" pointer is always first argument.
- QualType SelfDeclTy = OMethod->getSelfDecl()->getType();
- Elts.push_back(CreateSelfType(SelfDeclTy, getOrCreateType(SelfDeclTy, F)));
+ QualType SelfDeclTy;
+ if (auto *SelfDecl = OMethod->getSelfDecl())
+ SelfDeclTy = SelfDecl->getType();
+ else if (auto *FPT = dyn_cast<FunctionProtoType>(FnType))
+ if (FPT->getNumParams() > 1)
+ SelfDeclTy = FPT->getParamType(0);
+ if (!SelfDeclTy.isNull())
+ Elts.push_back(CreateSelfType(SelfDeclTy, getOrCreateType(SelfDeclTy, F)));
// "_cmd" pointer is always second argument.
Elts.push_back(DBuilder.createArtificialType(
- getOrCreateType(OMethod->getCmdDecl()->getType(), F)));
+ getOrCreateType(CGM.getContext().getObjCSelType(), F)));
// Get rest of the arguments.
for (const auto *PI : OMethod->params())
Elts.push_back(getOrCreateType(PI->getType(), F));
@@ -2508,7 +2652,7 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
Elts.push_back(DBuilder.createUnspecifiedParameter());
llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);
- return DBuilder.createSubroutineType(F, EltTypeArray);
+ return DBuilder.createSubroutineType(EltTypeArray);
}
// Handle variadic function types; they need an additional
@@ -2522,7 +2666,7 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
EltTys.push_back(getOrCreateType(FPT->getParamType(i), F));
EltTys.push_back(DBuilder.createUnspecifiedParameter());
llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
- return DBuilder.createSubroutineType(F, EltTypeArray);
+ return DBuilder.createSubroutineType(EltTypeArray);
}
return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F));
@@ -2588,8 +2732,9 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
llvm::DISubprogram *SP = DBuilder.createFunction(
FDContext, Name, LinkageName, Unit, LineNo,
getOrCreateFunctionType(D, FnType, Unit), Fn->hasInternalLinkage(),
- true /*definition*/, ScopeLine, Flags, CGM.getLangOpts().Optimize, Fn,
+ true /*definition*/, ScopeLine, Flags, CGM.getLangOpts().Optimize,
TParamsArray.get(), getFunctionDeclaration(D));
+ Fn->setSubprogram(SP);
// We might get here with a VarDecl in the case we're generating
// code for the initialization of globals. Do not record these decls
// as they will overwrite the actual VarDecl Decl in the cache.
@@ -2603,6 +2748,48 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
RegionMap[D].reset(SP);
}
+void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
+ QualType FnType) {
+ StringRef Name;
+ StringRef LinkageName;
+
+ const Decl *D = GD.getDecl();
+ if (!D)
+ return;
+
+ unsigned Flags = 0;
+ llvm::DIFile *Unit = getOrCreateFile(Loc);
+ llvm::DIScope *FDContext = getDeclContextDescriptor(D);
+ llvm::DINodeArray TParamsArray;
+ if (isa<FunctionDecl>(D)) {
+ // If there is a DISubprogram for this function available then use it.
+ collectFunctionDeclProps(GD, Unit, Name, LinkageName, FDContext,
+ TParamsArray, Flags);
+ } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
+ Name = getObjCMethodName(OMD);
+ Flags |= llvm::DINode::FlagPrototyped;
+ } else {
+ llvm_unreachable("not a function or ObjC method");
+ }
+ if (!Name.empty() && Name[0] == '\01')
+ Name = Name.substr(1);
+
+ if (D->isImplicit()) {
+ Flags |= llvm::DINode::FlagArtificial;
+ // Artificial functions without a location should not silently reuse CurLoc.
+ if (Loc.isInvalid())
+ CurLoc = SourceLocation();
+ }
+ unsigned LineNo = getLineNumber(Loc);
+ unsigned ScopeLine = 0;
+
+ DBuilder.createFunction(FDContext, Name, LinkageName, Unit, LineNo,
+ getOrCreateFunctionType(D, FnType, Unit),
+ false /*internalLinkage*/, true /*definition*/,
+ ScopeLine, Flags, CGM.getLangOpts().Optimize,
+ TParamsArray.get(), getFunctionDeclaration(D));
+}
+
void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
// Update our current location
setLocation(Loc);
@@ -2740,8 +2927,8 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
nullptr, Elements);
}
-void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::Tag Tag,
- llvm::Value *Storage, unsigned ArgNo,
+void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
+ llvm::Optional<unsigned> ArgNo,
CGBuilderTy &Builder) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
@@ -2780,7 +2967,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::Tag Tag,
// FIXME: There has to be a better way to do this, but for static
// functions there won't be an implicit param at arg1 and
// otherwise it is 'self' or 'this'.
- if (isa<ImplicitParamDecl>(VD) && ArgNo == 1)
+ if (isa<ImplicitParamDecl>(VD) && ArgNo && *ArgNo == 1)
Flags |= llvm::DINode::FlagObjectPointer;
if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage))
if (Arg->getType()->isPointerTy() && !Arg->hasByValAttr() &&
@@ -2805,8 +2992,11 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::Tag Tag,
Expr.push_back(offset.getQuantity());
// Create the descriptor for the variable.
- auto *D = DBuilder.createLocalVariable(Tag, Scope, VD->getName(), Unit,
- Line, Ty, ArgNo);
+ auto *D = ArgNo
+ ? DBuilder.createParameterVariable(Scope, VD->getName(),
+ *ArgNo, Unit, Line, Ty)
+ : DBuilder.createAutoVariable(Scope, VD->getName(), Unit,
+ Line, Ty);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
@@ -2836,10 +3026,9 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::Tag Tag,
continue;
// Use VarDecl's Tag, Scope and Line number.
- auto *D = DBuilder.createLocalVariable(
- Tag, Scope, FieldName, Unit, Line, FieldTy,
- CGM.getLangOpts().Optimize, Flags | llvm::DINode::FlagArtificial,
- ArgNo);
+ auto *D = DBuilder.createAutoVariable(
+ Scope, FieldName, Unit, Line, FieldTy, CGM.getLangOpts().Optimize,
+ Flags | llvm::DINode::FlagArtificial);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
@@ -2851,8 +3040,12 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::dwarf::Tag Tag,
// Create the descriptor for the variable.
auto *D =
- DBuilder.createLocalVariable(Tag, Scope, Name, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags, ArgNo);
+ ArgNo
+ ? DBuilder.createParameterVariable(Scope, Name, *ArgNo, Unit, Line,
+ Ty, CGM.getLangOpts().Optimize,
+ Flags)
+ : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
@@ -2864,7 +3057,7 @@ void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
llvm::Value *Storage,
CGBuilderTy &Builder) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
- EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);
+ EmitDeclare(VD, Storage, llvm::None, Builder);
}
llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy,
@@ -2929,8 +3122,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
}
// Create the descriptor for the variable.
- auto *D = DBuilder.createLocalVariable(
- llvm::dwarf::DW_TAG_auto_variable,
+ auto *D = DBuilder.createAutoVariable(
cast<llvm::DILocalScope>(LexicalBlockStack.back()), VD->getName(), Unit,
Line, Ty);
@@ -2948,7 +3140,7 @@ void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
unsigned ArgNo,
CGBuilderTy &Builder) {
assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
- EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, ArgNo, Builder);
+ EmitDeclare(VD, AI, ArgNo, Builder);
}
namespace {
@@ -2977,7 +3169,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
unsigned column = getColumnNumber(loc);
// Build the debug-info type for the block literal.
- getContextDescriptor(cast<Decl>(blockDecl->getDeclContext()));
+ getDeclContextDescriptor(blockDecl);
const llvm::StructLayout *blockLayout =
CGM.getDataLayout().getStructLayout(block.StructureType);
@@ -3090,9 +3282,9 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
auto *scope = cast<llvm::DILocalScope>(LexicalBlockStack.back());
// Create the descriptor for the parameter.
- auto *debugVar = DBuilder.createLocalVariable(
- llvm::dwarf::DW_TAG_arg_variable, scope, Arg->getName(), tunit, line,
- type, CGM.getLangOpts().Optimize, flags, ArgNo);
+ auto *debugVar = DBuilder.createParameterVariable(
+ scope, Arg->getName(), ArgNo, tunit, line, type,
+ CGM.getLangOpts().Optimize, flags);
if (LocalAddr) {
// Insert an llvm.dbg.value into the current block.
@@ -3115,14 +3307,13 @@ CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
auto MI = StaticDataMemberCache.find(D->getCanonicalDecl());
if (MI != StaticDataMemberCache.end()) {
assert(MI->second && "Static data member declaration should still exist");
- return cast<llvm::DIDerivedType>(MI->second);
+ return MI->second;
}
// If the member wasn't found in the cache, lazily construct and add it to the
// type (used when a limited form of the type is emitted).
auto DC = D->getDeclContext();
- auto *Ctxt =
- cast<llvm::DICompositeType>(getContextDescriptor(cast<Decl>(DC)));
+ auto *Ctxt = cast<llvm::DICompositeType>(getDeclContextDescriptor(D));
return CreateRecordStaticField(D, Ctxt, cast<RecordDecl>(DC));
}
@@ -3170,7 +3361,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
// variable for each member of the anonymous union so that it's possible
// to find the name of any field in the union.
if (T->isUnionType() && DeclName.empty()) {
- const RecordDecl *RD = cast<RecordType>(T)->getDecl();
+ const RecordDecl *RD = T->castAs<RecordType>()->getDecl();
assert(RD->isAnonymousStructOrUnion() &&
"unnamed non-anonymous struct or union?");
GV = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext);
@@ -3207,15 +3398,14 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
auto *VarD = cast<VarDecl>(VD);
if (VarD->isStaticDataMember()) {
auto *RD = cast<RecordDecl>(VarD->getDeclContext());
- getContextDescriptor(RD);
+ getDeclContextDescriptor(VarD);
// Ensure that the type is retained even though it's otherwise unreferenced.
RetainedTypes.push_back(
CGM.getContext().getRecordType(RD).getAsOpaquePtr());
return;
}
- llvm::DIScope *DContext =
- getContextDescriptor(dyn_cast<Decl>(VD->getDeclContext()));
+ llvm::DIScope *DContext = getDeclContextDescriptor(VD);
auto &GV = DeclCache[VD];
if (GV)
@@ -3228,16 +3418,21 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
if (!LexicalBlockStack.empty())
return LexicalBlockStack.back();
- return getContextDescriptor(D);
+ llvm::DIScope *Mod = getParentModuleOrNull(D);
+ return getContextDescriptor(D, Mod ? Mod : TheCU);
}
void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) {
if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo)
return;
- DBuilder.createImportedModule(
- getCurrentContextDescriptor(cast<Decl>(UD.getDeclContext())),
- getOrCreateNameSpace(UD.getNominatedNamespace()),
- getLineNumber(UD.getLocation()));
+ const NamespaceDecl *NSDecl = UD.getNominatedNamespace();
+ if (!NSDecl->isAnonymousNamespace() ||
+ CGM.getCodeGenOpts().DebugExplicitImport) {
+ DBuilder.createImportedModule(
+ getCurrentContextDescriptor(cast<Decl>(UD.getDeclContext())),
+ getOrCreateNameSpace(NSDecl),
+ getLineNumber(UD.getLocation()));
+ }
}
void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) {
@@ -3256,12 +3451,13 @@ void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) {
}
void CGDebugInfo::EmitImportDecl(const ImportDecl &ID) {
- auto *Reader = CGM.getContext().getExternalSource();
- auto Info = Reader->getSourceDescriptor(*ID.getImportedModule());
- DBuilder.createImportedDeclaration(
- getCurrentContextDescriptor(cast<Decl>(ID.getDeclContext())),
- getOrCreateModuleRef(Info),
- getLineNumber(ID.getLocation()));
+ if (Module *M = ID.getImportedModule()) {
+ auto Info = ExternalASTSource::ASTSourceDescriptor(*M);
+ DBuilder.createImportedDeclaration(
+ getCurrentContextDescriptor(cast<Decl>(ID.getDeclContext())),
+ getOrCreateModuleRef(Info, DebugTypeExtRefs),
+ getLineNumber(ID.getLocation()));
+ }
}
llvm::DIImportedEntity *
@@ -3297,14 +3493,19 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
unsigned LineNo = getLineNumber(NSDecl->getLocation());
llvm::DIFile *FileD = getOrCreateFile(NSDecl->getLocation());
- llvm::DIScope *Context =
- getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
+ llvm::DIScope *Context = getDeclContextDescriptor(NSDecl);
llvm::DINamespace *NS =
DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
NameSpaceCache[NSDecl].reset(NS);
return NS;
}
+void CGDebugInfo::setDwoId(uint64_t Signature) {
+ assert(TheCU && "no main compile unit");
+ TheCU->setDWOId(Signature);
+}
+
+
void CGDebugInfo::finalize() {
// Creating types might create further types - invalidating the current
// element and the size(), so don't cache/reference them.
@@ -3348,9 +3549,9 @@ void CGDebugInfo::finalize() {
// We keep our own list of retained types, because we need to look
// up the final type in the type cache.
- for (std::vector<void *>::const_iterator RI = RetainedTypes.begin(),
- RE = RetainedTypes.end(); RI != RE; ++RI)
- DBuilder.retainType(cast<llvm::DIType>(TypeCache[*RI]));
+ for (auto &RT : RetainedTypes)
+ if (auto MD = TypeCache[RT])
+ DBuilder.retainType(cast<llvm::DIType>(MD));
DBuilder.finalize();
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
index 82680a8..a68dd33f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
@@ -20,6 +20,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/ValueHandle.h"
@@ -31,12 +32,13 @@ class MDNode;
namespace clang {
class CXXMethodDecl;
-class VarDecl;
-class ObjCInterfaceDecl;
-class ObjCIvarDecl;
class ClassTemplateSpecializationDecl;
class GlobalDecl;
+class ModuleMap;
+class ObjCInterfaceDecl;
+class ObjCIvarDecl;
class UsingDecl;
+class VarDecl;
namespace CodeGen {
class CodeGenModule;
@@ -51,8 +53,10 @@ class CGDebugInfo {
friend class SaveAndRestoreLocation;
CodeGenModule &CGM;
const CodeGenOptions::DebugInfoKind DebugKind;
+ bool DebugTypeExtRefs;
llvm::DIBuilder DBuilder;
llvm::DICompileUnit *TheCU = nullptr;
+ ModuleMap *ClangModuleMap = nullptr;
SourceLocation CurLoc;
llvm::DIType *VTablePtrType = nullptr;
llvm::DIType *ClassTy = nullptr;
@@ -63,12 +67,24 @@ class CGDebugInfo {
llvm::DIType *OCLImage1dBufferDITy = nullptr;
llvm::DIType *OCLImage2dDITy = nullptr;
llvm::DIType *OCLImage2dArrayDITy = nullptr;
+ llvm::DIType *OCLImage2dDepthDITy = nullptr;
+ llvm::DIType *OCLImage2dArrayDepthDITy = nullptr;
+ llvm::DIType *OCLImage2dMSAADITy = nullptr;
+ llvm::DIType *OCLImage2dArrayMSAADITy = nullptr;
+ llvm::DIType *OCLImage2dMSAADepthDITy = nullptr;
+ llvm::DIType *OCLImage2dArrayMSAADepthDITy = nullptr;
llvm::DIType *OCLImage3dDITy = nullptr;
llvm::DIType *OCLEventDITy = nullptr;
+ llvm::DIType *OCLClkEventDITy = nullptr;
+ llvm::DIType *OCLQueueDITy = nullptr;
+ llvm::DIType *OCLNDRangeDITy = nullptr;
+ llvm::DIType *OCLReserveIDDITy = nullptr;
/// Cache of previously constructed Types.
llvm::DenseMap<const void *, llvm::TrackingMDRef> TypeCache;
+ llvm::SmallDenseMap<llvm::StringRef, llvm::StringRef> DebugPrefixMap;
+
struct ObjCInterfaceCacheEntry {
const ObjCInterfaceType *Type;
llvm::DIType *Decl;
@@ -81,8 +97,8 @@ class CGDebugInfo {
/// Cache of previously constructed interfaces which may change.
llvm::SmallVector<ObjCInterfaceCacheEntry, 32> ObjCInterfaceCache;
- /// Cache of references to AST files such as PCHs or modules.
- llvm::DenseMap<uint64_t, llvm::DIModule *> ModuleRefCache;
+ /// Cache of references to clang modules and precompiled headers.
+ llvm::DenseMap<const Module *, llvm::TrackingMDRef> ModuleCache;
/// List of interfaces we want to keep even if orphaned.
std::vector<void *> RetainedTypes;
@@ -117,13 +133,13 @@ class CGDebugInfo {
llvm::DenseMap<const NamespaceDecl *, llvm::TrackingMDRef> NameSpaceCache;
llvm::DenseMap<const NamespaceAliasDecl *, llvm::TrackingMDRef>
NamespaceAliasCache;
- llvm::DenseMap<const Decl *, llvm::TrackingMDRef> StaticDataMemberCache;
+ llvm::DenseMap<const Decl *, llvm::TypedTrackingMDRef<llvm::DIDerivedType>>
+ StaticDataMemberCache;
/// Helper functions for getOrCreateType.
/// @{
/// Currently the checksum of an interface includes the number of
/// ivars and property accessors.
- unsigned Checksum(const ObjCInterfaceDecl *InterfaceDecl);
llvm::DIType *CreateType(const BuiltinType *Ty);
llvm::DIType *CreateType(const ComplexType *Ty);
llvm::DIType *CreateQualifiedType(QualType Ty, llvm::DIFile *Fg);
@@ -152,6 +168,7 @@ class CGDebugInfo {
llvm::DIType *CreateType(const RValueReferenceType *Ty, llvm::DIFile *Unit);
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
+ llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F);
/// Get enumeration type.
llvm::DIType *CreateEnumType(const EnumType *Ty);
llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
@@ -182,11 +199,8 @@ class CGDebugInfo {
llvm::DIType *getOrCreateVTablePtrType(llvm::DIFile *F);
/// \return namespace descriptor for the given namespace decl.
llvm::DINamespace *getOrCreateNameSpace(const NamespaceDecl *N);
- llvm::DIType *getOrCreateTypeDeclaration(QualType PointeeTy, llvm::DIFile *F);
llvm::DIType *CreatePointerLikeType(llvm::dwarf::Tag Tag, const Type *Ty,
QualType PointeeTy, llvm::DIFile *F);
-
- llvm::Value *getCachedInterfaceTypeOrNull(const QualType Ty);
llvm::DIType *getOrCreateStructPtrType(StringRef Name, llvm::DIType *&Cache);
/// A helper function to create a subprogram for a single member
@@ -261,6 +275,14 @@ public:
void finalize();
+ /// Set the main CU's DwoId field to \p Signature.
+ void setDwoId(uint64_t Signature);
+
+ /// When generating debug information for a clang module or
+ /// precompiled header, this module map will be used to determine
+ /// the module of origin of each Decl.
+ void setModuleMap(ModuleMap &MMap) { ClangModuleMap = &MMap; }
+
/// Update the current source location. If \arg loc is invalid it is
/// ignored.
void setLocation(SourceLocation Loc);
@@ -278,6 +300,9 @@ public:
SourceLocation ScopeLoc, QualType FnType,
llvm::Function *Fn, CGBuilderTy &Builder);
+ /// Emit debug info for a function declaration.
+ void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, QualType FnType);
+
/// Constructs the debug code for exiting a function.
void EmitFunctionEnd(CGBuilderTy &Builder);
@@ -300,7 +325,7 @@ public:
llvm::Value *storage,
CGBuilderTy &Builder,
const CGBlockInfo &blockInfo,
- llvm::Instruction *InsertPoint = 0);
+ llvm::Instruction *InsertPoint = nullptr);
/// Emit call to \c llvm.dbg.declare for an argument variable
/// declaration.
@@ -341,6 +366,9 @@ public:
/// Emit an Objective-C interface type standalone debug info.
llvm::DIType *getOrCreateInterfaceType(QualType Ty, SourceLocation Loc);
+ /// Emit standalone debug info for a type.
+ llvm::DIType *getOrCreateStandaloneType(QualType Ty, SourceLocation Loc);
+
void completeType(const EnumDecl *ED);
void completeType(const RecordDecl *RD);
void completeRequiredType(const RecordDecl *RD);
@@ -350,17 +378,18 @@ public:
private:
/// Emit call to llvm.dbg.declare for a variable declaration.
- /// Tag accepts custom types DW_TAG_arg_variable and DW_TAG_auto_variable,
- /// otherwise would be of type llvm::dwarf::Tag.
- void EmitDeclare(const VarDecl *decl, llvm::dwarf::Tag Tag, llvm::Value *AI,
- unsigned ArgNo, CGBuilderTy &Builder);
+ void EmitDeclare(const VarDecl *decl, llvm::Value *AI,
+ llvm::Optional<unsigned> ArgNo, CGBuilderTy &Builder);
/// Build up structure info for the byref. See \a BuildByRefType.
llvm::DIType *EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *OffSet);
- /// Get context info for the decl.
- llvm::DIScope *getContextDescriptor(const Decl *Decl);
+ /// Get context info for the DeclContext of \p Decl.
+ llvm::DIScope *getDeclContextDescriptor(const Decl *D);
+ /// Get context info for a given DeclContext \p Decl.
+ llvm::DIScope *getContextDescriptor(const Decl *Context,
+ llvm::DIScope *Default);
llvm::DIScope *getCurrentContextDescriptor(const Decl *Decl);
@@ -374,6 +403,9 @@ private:
/// Create new compile unit.
void CreateCompileUnit();
+ /// Remap a given path with the current debug prefix map
+ std::string remapDIPath(StringRef) const;
+
/// Get the file debug info descriptor for the input location.
llvm::DIFile *getOrCreateFile(SourceLocation Loc);
@@ -383,21 +415,23 @@ private:
/// Get the type from the cache or create a new type if necessary.
llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg);
- /// Get a reference to a clang module.
+ /// Get a reference to a clang module. If \p CreateSkeletonCU is true,
+ /// this also creates a split dwarf skeleton compile unit.
llvm::DIModule *
- getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod);
+ getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
+ bool CreateSkeletonCU);
+
+ /// DebugTypeExtRefs: If \p D originated in a clang module, return it.
+ llvm::DIModule *getParentModuleOrNull(const Decl *D);
/// Get the type from the cache or create a new partial type if
/// necessary.
- llvm::DIType *getOrCreateLimitedType(const RecordType *Ty, llvm::DIFile *F);
+ llvm::DICompositeType *getOrCreateLimitedType(const RecordType *Ty,
+ llvm::DIFile *F);
/// Create type metadata for a source language type.
llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg);
- /// Return the underlying ObjCInterfaceDecl if \arg Ty is an
- /// ObjCInterface or a pointer to one.
- ObjCInterfaceDecl *getObjCInterfaceDecl(QualType Ty);
-
/// Create new member and increase Offset by FType's size.
llvm::DIType *CreateMemberType(llvm::DIFile *Unit, QualType FType,
StringRef Name, uint64_t *Offset);
@@ -501,13 +535,16 @@ private:
SourceLocation TemporaryLocation);
llvm::DebugLoc OriginalLocation;
- CodeGenFunction &CGF;
+ CodeGenFunction *CGF;
public:
/// Set the location to the (valid) TemporaryLocation.
ApplyDebugLocation(CodeGenFunction &CGF, SourceLocation TemporaryLocation);
ApplyDebugLocation(CodeGenFunction &CGF, const Expr *E);
ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc);
+ ApplyDebugLocation(ApplyDebugLocation &&Other) : CGF(Other.CGF) {
+ Other.CGF = nullptr;
+ }
~ApplyDebugLocation();
@@ -538,20 +575,14 @@ public:
/// passing an empty SourceLocation to \a CGDebugInfo::setLocation()
/// will result in the last valid location being reused. Note that
/// all instructions that do not have a location at the beginning of
- /// a function are counted towards to funciton prologue.
+ /// a function are counted towards to function prologue.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF) {
return ApplyDebugLocation(CGF, true, SourceLocation());
}
- /// \brief Apply TemporaryLocation if it is valid. Otherwise set the IRBuilder
- /// to not attach debug locations.
- static ApplyDebugLocation
- CreateDefaultEmpty(CodeGenFunction &CGF, SourceLocation TemporaryLocation) {
- return ApplyDebugLocation(CGF, true, TemporaryLocation);
- }
};
} // namespace CodeGen
} // namespace clang
-#endif
+#endif // LLVM_CLANG_LIB_CODEGEN_CGDEBUGINFO_H
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
index 96aa8c68..b78e80d 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGBlocks.h"
#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGOpenCLRuntime.h"
@@ -34,6 +35,7 @@ using namespace CodeGen;
void CodeGenFunction::EmitDecl(const Decl &D) {
switch (D.getKind()) {
+ case Decl::BuiltinTemplate:
case Decl::TranslationUnit:
case Decl::ExternCContext:
case Decl::Namespace:
@@ -142,7 +144,7 @@ void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
// Don't emit it now, allow it to be emitted lazily on its first use.
return;
- if (D.getStorageClass() == SC_OpenCLWorkGroupLocal)
+ if (D.getType().getAddressSpace() == LangAS::opencl_local)
return CGM.getOpenCLRuntime().EmitWorkGroupLocalVarDecl(*this, D);
assert(D.hasLocalStorage());
@@ -311,6 +313,7 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
OldGV->getThreadLocalMode(),
CGM.getContext().getTargetAddressSpace(D.getType()));
GV->setVisibility(OldGV->getVisibility());
+ GV->setComdat(OldGV->getComdat());
// Steal the name of the old global
GV->takeName(OldGV);
@@ -339,17 +342,15 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
llvm::GlobalValue::LinkageTypes Linkage) {
- llvm::Value *&DMEntry = LocalDeclMap[&D];
- assert(!DMEntry && "Decl already exists in localdeclmap!");
-
// Check to see if we already have a global variable for this
// declaration. This can happen when double-emitting function
// bodies, e.g. with complete and base constructors.
llvm::Constant *addr = CGM.getOrCreateStaticVarDecl(D, Linkage);
+ CharUnits alignment = getContext().getDeclAlign(&D);
// Store into LocalDeclMap before generating initializer to handle
// circular references.
- DMEntry = addr;
+ setAddrOfLocalVar(&D, Address(addr, alignment));
// We can't have a VLA here, but we can have a pointer to a VLA,
// even though that doesn't really make any sense.
@@ -366,7 +367,7 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
if (D.getInit())
var = AddInitializerToStaticVarDecl(D, var);
- var->setAlignment(getContext().getDeclAlign(&D).getQuantity());
+ var->setAlignment(alignment.getQuantity());
if (D.hasAttr<AnnotateAttr>())
CGM.AddGlobalAnnotations(&D, var);
@@ -384,7 +385,8 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
// RAUW's the GV uses of this constant will be invalid.
llvm::Constant *castedAddr =
llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(var, expectedType);
- DMEntry = castedAddr;
+ if (var != castedAddr)
+ LocalDeclMap.find(&D)->second = Address(castedAddr, alignment);
CGM.setStaticLocalDeclAddress(&D, castedAddr);
CGM.getSanitizerMetadata()->reportGlobalToASan(var, D);
@@ -399,14 +401,14 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
}
namespace {
- struct DestroyObject : EHScopeStack::Cleanup {
- DestroyObject(llvm::Value *addr, QualType type,
+ struct DestroyObject final : EHScopeStack::Cleanup {
+ DestroyObject(Address addr, QualType type,
CodeGenFunction::Destroyer *destroyer,
bool useEHCleanupForArray)
: addr(addr), type(type), destroyer(destroyer),
useEHCleanupForArray(useEHCleanupForArray) {}
- llvm::Value *addr;
+ Address addr;
QualType type;
CodeGenFunction::Destroyer *destroyer;
bool useEHCleanupForArray;
@@ -420,15 +422,15 @@ namespace {
}
};
- struct DestroyNRVOVariable : EHScopeStack::Cleanup {
- DestroyNRVOVariable(llvm::Value *addr,
+ struct DestroyNRVOVariable final : EHScopeStack::Cleanup {
+ DestroyNRVOVariable(Address addr,
const CXXDestructorDecl *Dtor,
llvm::Value *NRVOFlag)
: Dtor(Dtor), NRVOFlag(NRVOFlag), Loc(addr) {}
const CXXDestructorDecl *Dtor;
llvm::Value *NRVOFlag;
- llvm::Value *Loc;
+ Address Loc;
void Emit(CodeGenFunction &CGF, Flags flags) override {
// Along the exceptions path we always execute the dtor.
@@ -439,7 +441,8 @@ namespace {
// If we exited via NRVO, we skip the destructor call.
llvm::BasicBlock *RunDtorBB = CGF.createBasicBlock("nrvo.unused");
SkipDtorBB = CGF.createBasicBlock("nrvo.skipdtor");
- llvm::Value *DidNRVO = CGF.Builder.CreateLoad(NRVOFlag, "nrvo.val");
+ llvm::Value *DidNRVO =
+ CGF.Builder.CreateFlagLoad(NRVOFlag, "nrvo.val");
CGF.Builder.CreateCondBr(DidNRVO, SkipDtorBB, RunDtorBB);
CGF.EmitBlock(RunDtorBB);
}
@@ -453,9 +456,9 @@ namespace {
}
};
- struct CallStackRestore : EHScopeStack::Cleanup {
- llvm::Value *Stack;
- CallStackRestore(llvm::Value *Stack) : Stack(Stack) {}
+ struct CallStackRestore final : EHScopeStack::Cleanup {
+ Address Stack;
+ CallStackRestore(Address Stack) : Stack(Stack) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
llvm::Value *V = CGF.Builder.CreateLoad(Stack);
llvm::Value *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
@@ -463,7 +466,7 @@ namespace {
}
};
- struct ExtendGCLifetime : EHScopeStack::Cleanup {
+ struct ExtendGCLifetime final : EHScopeStack::Cleanup {
const VarDecl &Var;
ExtendGCLifetime(const VarDecl *var) : Var(*var) {}
@@ -478,7 +481,7 @@ namespace {
}
};
- struct CallCleanupFunction : EHScopeStack::Cleanup {
+ struct CallCleanupFunction final : EHScopeStack::Cleanup {
llvm::Constant *CleanupFn;
const CGFunctionInfo &FnInfo;
const VarDecl &Var;
@@ -492,7 +495,7 @@ namespace {
Var.getType(), VK_LValue, SourceLocation());
// Compute the address of the local variable, in case it's a byref
// or something.
- llvm::Value *Addr = CGF.EmitDeclRefLValue(&DRE).getAddress();
+ llvm::Value *Addr = CGF.EmitDeclRefLValue(&DRE).getPointer();
// In some cases, the type of the function argument will be different from
// the type of the pointer. An example of this is
@@ -512,12 +515,12 @@ namespace {
};
/// A cleanup to call @llvm.lifetime.end.
- class CallLifetimeEnd : public EHScopeStack::Cleanup {
+ class CallLifetimeEnd final : public EHScopeStack::Cleanup {
llvm::Value *Addr;
llvm::Value *Size;
public:
- CallLifetimeEnd(llvm::Value *addr, llvm::Value *size)
- : Addr(addr), Size(size) {}
+ CallLifetimeEnd(Address addr, llvm::Value *size)
+ : Addr(addr.getPointer()), Size(size) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
CGF.EmitLifetimeEnd(Size, Addr);
@@ -528,7 +531,7 @@ namespace {
/// EmitAutoVarWithLifetime - Does the setup required for an automatic
/// variable with lifetime.
static void EmitAutoVarWithLifetime(CodeGenFunction &CGF, const VarDecl &var,
- llvm::Value *addr,
+ Address addr,
Qualifiers::ObjCLifetime lifetime) {
switch (lifetime) {
case Qualifiers::OCL_None:
@@ -595,10 +598,61 @@ static bool isAccessedBy(const ValueDecl *decl, const Expr *e) {
return isAccessedBy(*var, e);
}
+static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF,
+ const LValue &destLV, const Expr *init) {
+ bool needsCast = false;
+
+ while (auto castExpr = dyn_cast<CastExpr>(init->IgnoreParens())) {
+ switch (castExpr->getCastKind()) {
+ // Look through casts that don't require representation changes.
+ case CK_NoOp:
+ case CK_BitCast:
+ case CK_BlockPointerToObjCPointerCast:
+ needsCast = true;
+ break;
+
+ // If we find an l-value to r-value cast from a __weak variable,
+ // emit this operation as a copy or move.
+ case CK_LValueToRValue: {
+ const Expr *srcExpr = castExpr->getSubExpr();
+ if (srcExpr->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
+ return false;
+
+ // Emit the source l-value.
+ LValue srcLV = CGF.EmitLValue(srcExpr);
+
+ // Handle a formal type change to avoid asserting.
+ auto srcAddr = srcLV.getAddress();
+ if (needsCast) {
+ srcAddr = CGF.Builder.CreateElementBitCast(srcAddr,
+ destLV.getAddress().getElementType());
+ }
+
+ // If it was an l-value, use objc_copyWeak.
+ if (srcExpr->getValueKind() == VK_LValue) {
+ CGF.EmitARCCopyWeak(destLV.getAddress(), srcAddr);
+ } else {
+ assert(srcExpr->getValueKind() == VK_XValue);
+ CGF.EmitARCMoveWeak(destLV.getAddress(), srcAddr);
+ }
+ return true;
+ }
+
+ // Stop at anything else.
+ default:
+ return false;
+ }
+
+ init = castExpr->getSubExpr();
+ continue;
+ }
+ return false;
+}
+
static void drillIntoBlockVariable(CodeGenFunction &CGF,
LValue &lvalue,
const VarDecl *var) {
- lvalue.setAddress(CGF.BuildBlockByrefAddress(lvalue.getAddress(), var));
+ lvalue.setAddress(CGF.emitBlockByrefAddress(lvalue.getAddress(), var));
}
void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
@@ -636,15 +690,12 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
if (capturedByInit) {
// We can use a simple GEP for this because it can't have been
// moved yet.
- tempLV.setAddress(Builder.CreateStructGEP(
- nullptr, tempLV.getAddress(),
- getByRefValueLLVMField(cast<VarDecl>(D)).second));
+ tempLV.setAddress(emitBlockByrefAddress(tempLV.getAddress(),
+ cast<VarDecl>(D),
+ /*follow*/ false));
}
- llvm::PointerType *ty
- = cast<llvm::PointerType>(tempLV.getAddress()->getType());
- ty = cast<llvm::PointerType>(ty->getElementType());
-
+ auto ty = cast<llvm::PointerType>(tempLV.getAddress().getElementType());
llvm::Value *zero = llvm::ConstantPointerNull::get(ty);
// If __weak, we want to use a barrier under certain conditions.
@@ -674,6 +725,12 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
}
case Qualifiers::OCL_Weak: {
+ // If it's not accessed by the initializer, try to emit the
+ // initialization with a copy or move.
+ if (!accessedByInit && tryEmitARCCopyWeakInit(*this, lvalue, init)) {
+ return;
+ }
+
// No way to optimize a producing initializer into this. It's not
// worth optimizing for, because the value will immediately
// disappear in the common case.
@@ -788,7 +845,7 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
if (isa<llvm::ConstantInt>(Init) || isa<llvm::ConstantFP>(Init) ||
isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) ||
isa<llvm::ConstantExpr>(Init)) {
- Builder.CreateStore(Init, Loc, isVolatile);
+ Builder.CreateDefaultAlignedStore(Init, Loc, isVolatile);
return;
}
@@ -891,13 +948,12 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
emission.IsByRef = isByRef;
CharUnits alignment = getContext().getDeclAlign(&D);
- emission.Alignment = alignment;
// If the type is variably-modified, emit all the VLA sizes for it.
if (Ty->isVariablyModifiedType())
EmitVariablyModifiedType(Ty);
- llvm::Value *DeclPtr;
+ Address address = Address::invalid();
if (Ty->isConstantSizeType()) {
bool NRVO = getLangOpts().ElideConstructors &&
D.isNRVOVariable();
@@ -923,7 +979,8 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
CGM.isTypeConstant(Ty, true)) {
EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
- emission.Address = nullptr; // signal this condition to later callbacks
+ // Signal this condition to later callbacks.
+ emission.Addr = Address::invalid();
assert(emission.wasEmittedAsGlobal());
return emission;
}
@@ -934,13 +991,12 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// A normal fixed sized variable becomes an alloca in the entry block,
// unless it's an NRVO variable.
- llvm::Type *LTy = ConvertTypeForMem(Ty);
if (NRVO) {
// The named return value optimization: allocate this variable in the
// return slot, so that we can elide the copy when returning this
// variable (C++0x [class.copy]p34).
- DeclPtr = ReturnValue;
+ address = ReturnValue;
if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
if (!cast<CXXRecordDecl>(RecordTy->getDecl())->hasTrivialDestructor()) {
@@ -948,34 +1004,46 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// to this variable. Set it to zero to indicate that NRVO was not
// applied.
llvm::Value *Zero = Builder.getFalse();
- llvm::Value *NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo");
+ Address NRVOFlag =
+ CreateTempAlloca(Zero->getType(), CharUnits::One(), "nrvo");
EnsureInsertPoint();
Builder.CreateStore(Zero, NRVOFlag);
// Record the NRVO flag for this variable.
- NRVOFlags[&D] = NRVOFlag;
- emission.NRVOFlag = NRVOFlag;
+ NRVOFlags[&D] = NRVOFlag.getPointer();
+ emission.NRVOFlag = NRVOFlag.getPointer();
}
}
} else {
- if (isByRef)
- LTy = BuildByRefType(&D);
+ CharUnits allocaAlignment;
+ llvm::Type *allocaTy;
+ if (isByRef) {
+ auto &byrefInfo = getBlockByrefInfo(&D);
+ allocaTy = byrefInfo.Type;
+ allocaAlignment = byrefInfo.ByrefAlignment;
+ } else {
+ allocaTy = ConvertTypeForMem(Ty);
+ allocaAlignment = alignment;
+ }
- llvm::AllocaInst *Alloc = CreateTempAlloca(LTy);
- Alloc->setName(D.getName());
+ // Create the alloca. Note that we set the name separately from
+ // building the instruction so that it's there even in no-asserts
+ // builds.
+ address = CreateTempAlloca(allocaTy, allocaAlignment);
+ address.getPointer()->setName(D.getName());
- CharUnits allocaAlignment = alignment;
- if (isByRef)
- allocaAlignment = std::max(allocaAlignment,
- getContext().toCharUnitsFromBits(getTarget().getPointerAlign(0)));
- Alloc->setAlignment(allocaAlignment.getQuantity());
- DeclPtr = Alloc;
+ // Don't emit lifetime markers for MSVC catch parameters. The lifetime of
+ // the catch parameter starts in the catchpad instruction, and we can't
+ // insert code in those basic blocks.
+ bool IsMSCatchParam =
+ D.isExceptionVariable() && getTarget().getCXXABI().isMicrosoft();
// Emit a lifetime intrinsic if meaningful. There's no point
// in doing this if we don't have a valid insertion point (?).
- uint64_t size = CGM.getDataLayout().getTypeAllocSize(LTy);
- if (HaveInsertPoint()) {
- emission.SizeForLifetimeMarkers = EmitLifetimeStart(size, Alloc);
+ if (HaveInsertPoint() && !IsMSCatchParam) {
+ uint64_t size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
+ emission.SizeForLifetimeMarkers =
+ EmitLifetimeStart(size, address.getPointer());
} else {
assert(!emission.useLifetimeMarkers());
}
@@ -985,11 +1053,11 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
if (!DidCallStackSave) {
// Save the stack.
- llvm::Value *Stack = CreateTempAlloca(Int8PtrTy, "saved_stack");
+ Address Stack =
+ CreateTempAlloca(Int8PtrTy, getPointerAlign(), "saved_stack");
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave);
llvm::Value *V = Builder.CreateCall(F);
-
Builder.CreateStore(V, Stack);
DidCallStackSave = true;
@@ -1009,13 +1077,11 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
llvm::AllocaInst *vla = Builder.CreateAlloca(llvmTy, elementCount, "vla");
vla->setAlignment(alignment.getQuantity());
- DeclPtr = vla;
+ address = Address(vla, alignment);
}
- llvm::Value *&DMEntry = LocalDeclMap[&D];
- assert(!DMEntry && "Decl already exists in localdeclmap!");
- DMEntry = DeclPtr;
- emission.Address = DeclPtr;
+ setAddrOfLocalVar(&D, address);
+ emission.Addr = address;
// Emit debug info for local var declaration.
if (HaveInsertPoint())
@@ -1023,12 +1089,12 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
if (CGM.getCodeGenOpts().getDebugInfo()
>= CodeGenOptions::LimitedDebugInfo) {
DI->setLocation(D.getLocation());
- DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
+ DI->EmitDeclareOfAutoVariable(&D, address.getPointer(), Builder);
}
}
if (D.hasAttr<AnnotateAttr>())
- EmitVarAnnotations(&D, emission.Address);
+ EmitVarAnnotations(&D, address.getPointer());
return emission;
}
@@ -1124,15 +1190,13 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
if (isTrivialInitializer(Init))
return;
- CharUnits alignment = emission.Alignment;
-
// Check whether this is a byref variable that's potentially
// captured and moved by its own initializer. If so, we'll need to
// emit the initializer first, then copy into the variable.
bool capturedByInit = emission.IsByRef && isCapturedBy(D, Init);
- llvm::Value *Loc =
- capturedByInit ? emission.Address : emission.getObjectAddress(*this);
+ Address Loc =
+ capturedByInit ? emission.Addr : emission.getObjectAddress(*this);
llvm::Constant *constant = nullptr;
if (emission.IsConstantAggregate || D.isConstexpr()) {
@@ -1141,14 +1205,14 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
}
if (!constant) {
- LValue lv = MakeAddrLValue(Loc, type, alignment);
+ LValue lv = MakeAddrLValue(Loc, type);
lv.setNonGC(true);
return EmitExprAsInit(Init, &D, lv, capturedByInit);
}
if (!emission.IsConstantAggregate) {
// For simple scalar/complex initialization, store the value directly.
- LValue lv = MakeAddrLValue(Loc, type, alignment);
+ LValue lv = MakeAddrLValue(Loc, type);
lv.setNonGC(true);
return EmitStoreThroughLValue(RValue::get(constant), lv, true);
}
@@ -1162,7 +1226,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
getContext().getTypeSizeInChars(type).getQuantity());
llvm::Type *BP = Int8PtrTy;
- if (Loc->getType() != BP)
+ if (Loc.getType() != BP)
Loc = Builder.CreateBitCast(Loc, BP);
// If the initializer is all or mostly zeros, codegen with memset then do
@@ -1170,11 +1234,12 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
if (shouldUseMemSetPlusStoresToInitialize(constant,
CGM.getDataLayout().getTypeAllocSize(constant->getType()))) {
Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal,
- alignment.getQuantity(), isVolatile);
+ isVolatile);
// Zero and undef don't require a stores.
if (!constant->isNullValue() && !isa<llvm::UndefValue>(constant)) {
Loc = Builder.CreateBitCast(Loc, constant->getType()->getPointerTo());
- emitStoresForInitAfterMemset(constant, Loc, isVolatile, Builder);
+ emitStoresForInitAfterMemset(constant, Loc.getPointer(),
+ isVolatile, Builder);
}
} else {
// Otherwise, create a temporary global with the initializer then
@@ -1184,15 +1249,14 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
new llvm::GlobalVariable(CGM.getModule(), constant->getType(), true,
llvm::GlobalValue::PrivateLinkage,
constant, Name);
- GV->setAlignment(alignment.getQuantity());
+ GV->setAlignment(Loc.getAlignment().getQuantity());
GV->setUnnamedAddr(true);
- llvm::Value *SrcPtr = GV;
- if (SrcPtr->getType() != BP)
+ Address SrcPtr = Address(GV, Loc.getAlignment());
+ if (SrcPtr.getType() != BP)
SrcPtr = Builder.CreateBitCast(SrcPtr, BP);
- Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, alignment.getQuantity(),
- isVolatile);
+ Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, isVolatile);
}
}
@@ -1253,7 +1317,7 @@ void CodeGenFunction::emitAutoVarTypeCleanup(
// Note that for __block variables, we want to destroy the
// original stack object, not the possibly forwarded object.
- llvm::Value *addr = emission.getObjectAddress(*this);
+ Address addr = emission.getObjectAddress(*this);
const VarDecl *var = emission.Variable;
QualType type = var->getType();
@@ -1271,8 +1335,8 @@ void CodeGenFunction::emitAutoVarTypeCleanup(
if (emission.NRVOFlag) {
assert(!type->isArrayType());
CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor();
- EHStack.pushCleanup<DestroyNRVOVariable>(cleanupKind, addr, dtor,
- emission.NRVOFlag);
+ EHStack.pushCleanup<DestroyNRVOVariable>(cleanupKind, addr,
+ dtor, emission.NRVOFlag);
return;
}
break;
@@ -1369,7 +1433,7 @@ CodeGenFunction::getDestroyer(QualType::DestructionKind kind) {
/// pushEHDestroy - Push the standard destructor for the given type as
/// an EH-only cleanup.
void CodeGenFunction::pushEHDestroy(QualType::DestructionKind dtorKind,
- llvm::Value *addr, QualType type) {
+ Address addr, QualType type) {
assert(dtorKind && "cannot push destructor for trivial type");
assert(needsEHCleanup(dtorKind));
@@ -1379,7 +1443,7 @@ void CodeGenFunction::pushEHDestroy(QualType::DestructionKind dtorKind,
/// pushDestroy - Push the standard destructor for the given type as
/// at least a normal cleanup.
void CodeGenFunction::pushDestroy(QualType::DestructionKind dtorKind,
- llvm::Value *addr, QualType type) {
+ Address addr, QualType type) {
assert(dtorKind && "cannot push destructor for trivial type");
CleanupKind cleanupKind = getCleanupKind(dtorKind);
@@ -1387,19 +1451,19 @@ void CodeGenFunction::pushDestroy(QualType::DestructionKind dtorKind,
cleanupKind & EHCleanup);
}
-void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, llvm::Value *addr,
+void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, Address addr,
QualType type, Destroyer *destroyer,
bool useEHCleanupForArray) {
pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type,
destroyer, useEHCleanupForArray);
}
-void CodeGenFunction::pushStackRestore(CleanupKind Kind, llvm::Value *SPMem) {
+void CodeGenFunction::pushStackRestore(CleanupKind Kind, Address SPMem) {
EHStack.pushCleanup<CallStackRestore>(Kind, SPMem);
}
void CodeGenFunction::pushLifetimeExtendedDestroy(
- CleanupKind cleanupKind, llvm::Value *addr, QualType type,
+ CleanupKind cleanupKind, Address addr, QualType type,
Destroyer *destroyer, bool useEHCleanupForArray) {
assert(!isInConditionalBranch() &&
"performing lifetime extension from within conditional");
@@ -1429,15 +1493,18 @@ void CodeGenFunction::pushLifetimeExtendedDestroy(
/// \param useEHCleanupForArray - whether an EH cleanup should be
/// used when destroying array elements, in case one of the
/// destructions throws an exception
-void CodeGenFunction::emitDestroy(llvm::Value *addr, QualType type,
+void CodeGenFunction::emitDestroy(Address addr, QualType type,
Destroyer *destroyer,
bool useEHCleanupForArray) {
const ArrayType *arrayType = getContext().getAsArrayType(type);
if (!arrayType)
return destroyer(*this, addr, type);
- llvm::Value *begin = addr;
- llvm::Value *length = emitArrayLength(arrayType, type, begin);
+ llvm::Value *length = emitArrayLength(arrayType, type, addr);
+
+ CharUnits elementAlign =
+ addr.getAlignment()
+ .alignmentOfArrayElement(getContext().getTypeSizeInChars(type));
// Normally we have to check whether the array is zero-length.
bool checkZeroLength = true;
@@ -1449,8 +1516,9 @@ void CodeGenFunction::emitDestroy(llvm::Value *addr, QualType type,
checkZeroLength = false;
}
+ llvm::Value *begin = addr.getPointer();
llvm::Value *end = Builder.CreateInBoundsGEP(begin, length);
- emitArrayDestroy(begin, end, type, destroyer,
+ emitArrayDestroy(begin, end, type, elementAlign, destroyer,
checkZeroLength, useEHCleanupForArray);
}
@@ -1459,18 +1527,19 @@ void CodeGenFunction::emitDestroy(llvm::Value *addr, QualType type,
///
/// \param begin - a type* denoting the first element of the array
/// \param end - a type* denoting one past the end of the array
-/// \param type - the element type of the array
+/// \param elementType - the element type of the array
/// \param destroyer - the function to call to destroy elements
/// \param useEHCleanup - whether to push an EH cleanup to destroy
/// the remaining elements in case the destruction of a single
/// element throws
void CodeGenFunction::emitArrayDestroy(llvm::Value *begin,
llvm::Value *end,
- QualType type,
+ QualType elementType,
+ CharUnits elementAlign,
Destroyer *destroyer,
bool checkZeroLength,
bool useEHCleanup) {
- assert(!type->isArrayType());
+ assert(!elementType->isArrayType());
// The basic structure here is a do-while loop, because we don't
// need to check for the zero-element case.
@@ -1496,10 +1565,11 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin,
"arraydestroy.element");
if (useEHCleanup)
- pushRegularPartialArrayCleanup(begin, element, type, destroyer);
+ pushRegularPartialArrayCleanup(begin, element, elementType, elementAlign,
+ destroyer);
// Perform the actual destruction there.
- destroyer(*this, element, type);
+ destroyer(*this, Address(element, elementAlign), elementType);
if (useEHCleanup)
PopCleanupBlock();
@@ -1517,7 +1587,7 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin,
/// emitArrayDestroy, the element type here may still be an array type.
static void emitPartialArrayDestroy(CodeGenFunction &CGF,
llvm::Value *begin, llvm::Value *end,
- QualType type,
+ QualType type, CharUnits elementAlign,
CodeGenFunction::Destroyer *destroyer) {
// If the element type is itself an array, drill down.
unsigned arrayDepth = 0;
@@ -1529,9 +1599,9 @@ static void emitPartialArrayDestroy(CodeGenFunction &CGF,
}
if (arrayDepth) {
- llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, arrayDepth+1);
+ llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0);
- SmallVector<llvm::Value*,4> gepIndices(arrayDepth, zero);
+ SmallVector<llvm::Value*,4> gepIndices(arrayDepth+1, zero);
begin = CGF.Builder.CreateInBoundsGEP(begin, gepIndices, "pad.arraybegin");
end = CGF.Builder.CreateInBoundsGEP(end, gepIndices, "pad.arrayend");
}
@@ -1539,7 +1609,7 @@ static void emitPartialArrayDestroy(CodeGenFunction &CGF,
// Destroy the array. We don't ever need an EH cleanup because we
// assume that we're in an EH cleanup ourselves, so a throwing
// destructor causes an immediate terminate.
- CGF.emitArrayDestroy(begin, end, type, destroyer,
+ CGF.emitArrayDestroy(begin, end, type, elementAlign, destroyer,
/*checkZeroLength*/ true, /*useEHCleanup*/ false);
}
@@ -1547,44 +1617,49 @@ namespace {
/// RegularPartialArrayDestroy - a cleanup which performs a partial
/// array destroy where the end pointer is regularly determined and
/// does not need to be loaded from a local.
- class RegularPartialArrayDestroy : public EHScopeStack::Cleanup {
+ class RegularPartialArrayDestroy final : public EHScopeStack::Cleanup {
llvm::Value *ArrayBegin;
llvm::Value *ArrayEnd;
QualType ElementType;
CodeGenFunction::Destroyer *Destroyer;
+ CharUnits ElementAlign;
public:
RegularPartialArrayDestroy(llvm::Value *arrayBegin, llvm::Value *arrayEnd,
- QualType elementType,
+ QualType elementType, CharUnits elementAlign,
CodeGenFunction::Destroyer *destroyer)
: ArrayBegin(arrayBegin), ArrayEnd(arrayEnd),
- ElementType(elementType), Destroyer(destroyer) {}
+ ElementType(elementType), Destroyer(destroyer),
+ ElementAlign(elementAlign) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
emitPartialArrayDestroy(CGF, ArrayBegin, ArrayEnd,
- ElementType, Destroyer);
+ ElementType, ElementAlign, Destroyer);
}
};
/// IrregularPartialArrayDestroy - a cleanup which performs a
/// partial array destroy where the end pointer is irregularly
/// determined and must be loaded from a local.
- class IrregularPartialArrayDestroy : public EHScopeStack::Cleanup {
+ class IrregularPartialArrayDestroy final : public EHScopeStack::Cleanup {
llvm::Value *ArrayBegin;
- llvm::Value *ArrayEndPointer;
+ Address ArrayEndPointer;
QualType ElementType;
CodeGenFunction::Destroyer *Destroyer;
+ CharUnits ElementAlign;
public:
IrregularPartialArrayDestroy(llvm::Value *arrayBegin,
- llvm::Value *arrayEndPointer,
+ Address arrayEndPointer,
QualType elementType,
+ CharUnits elementAlign,
CodeGenFunction::Destroyer *destroyer)
: ArrayBegin(arrayBegin), ArrayEndPointer(arrayEndPointer),
- ElementType(elementType), Destroyer(destroyer) {}
+ ElementType(elementType), Destroyer(destroyer),
+ ElementAlign(elementAlign) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
llvm::Value *arrayEnd = CGF.Builder.CreateLoad(ArrayEndPointer);
emitPartialArrayDestroy(CGF, ArrayBegin, arrayEnd,
- ElementType, Destroyer);
+ ElementType, ElementAlign, Destroyer);
}
};
}
@@ -1596,12 +1671,14 @@ namespace {
/// \param elementType - the immediate element type of the array;
/// possibly still an array type
void CodeGenFunction::pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin,
- llvm::Value *arrayEndPointer,
+ Address arrayEndPointer,
QualType elementType,
+ CharUnits elementAlign,
Destroyer *destroyer) {
pushFullExprCleanup<IrregularPartialArrayDestroy>(EHCleanup,
arrayBegin, arrayEndPointer,
- elementType, destroyer);
+ elementType, elementAlign,
+ destroyer);
}
/// pushRegularPartialArrayCleanup - Push an EH cleanup to destroy
@@ -1613,10 +1690,12 @@ void CodeGenFunction::pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin,
void CodeGenFunction::pushRegularPartialArrayCleanup(llvm::Value *arrayBegin,
llvm::Value *arrayEnd,
QualType elementType,
+ CharUnits elementAlign,
Destroyer *destroyer) {
pushFullExprCleanup<RegularPartialArrayDestroy>(EHCleanup,
arrayBegin, arrayEnd,
- elementType, destroyer);
+ elementType, elementAlign,
+ destroyer);
}
/// Lazily declare the @llvm.lifetime.start intrinsic.
@@ -1640,7 +1719,7 @@ namespace {
/// function. This is used to balance out the incoming +1 of a
/// ns_consumed argument when we can't reasonably do that just by
/// not doing the initial retain for a __block argument.
- struct ConsumeARCParameter : EHScopeStack::Cleanup {
+ struct ConsumeARCParameter final : EHScopeStack::Cleanup {
ConsumeARCParameter(llvm::Value *param,
ARCPreciseLifetime_t precise)
: Param(param), Precise(precise) {}
@@ -1656,56 +1735,38 @@ namespace {
/// Emit an alloca (or GlobalValue depending on target)
/// for the specified parameter and set up LocalDeclMap.
-void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
- bool ArgIsPointer, unsigned ArgNo) {
+void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
+ unsigned ArgNo) {
// FIXME: Why isn't ImplicitParamDecl a ParmVarDecl?
assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
"Invalid argument to EmitParmDecl");
- Arg->setName(D.getName());
+ Arg.getAnyValue()->setName(D.getName());
QualType Ty = D.getType();
// Use better IR generation for certain implicit parameters.
- if (isa<ImplicitParamDecl>(D)) {
+ if (auto IPD = dyn_cast<ImplicitParamDecl>(&D)) {
// The only implicit argument a block has is its literal.
+ // We assume this is always passed directly.
if (BlockInfo) {
- LocalDeclMap[&D] = Arg;
- llvm::Value *LocalAddr = nullptr;
- if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
- // Allocate a stack slot to let the debug info survive the RA.
- llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty),
- D.getName() + ".addr");
- Alloc->setAlignment(getContext().getDeclAlign(&D).getQuantity());
- LValue lv = MakeAddrLValue(Alloc, Ty, getContext().getDeclAlign(&D));
- EmitStoreOfScalar(Arg, lv, /* isInitialization */ true);
- LocalAddr = Builder.CreateLoad(Alloc);
- }
-
- if (CGDebugInfo *DI = getDebugInfo()) {
- if (CGM.getCodeGenOpts().getDebugInfo()
- >= CodeGenOptions::LimitedDebugInfo) {
- DI->setLocation(D.getLocation());
- DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, Arg, ArgNo,
- LocalAddr, Builder);
- }
- }
-
+ setBlockContextParameter(IPD, ArgNo, Arg.getDirectValue());
return;
}
}
- llvm::Value *DeclPtr;
+ Address DeclPtr = Address::invalid();
bool DoStore = false;
bool IsScalar = hasScalarEvaluationKind(Ty);
- CharUnits Align = getContext().getDeclAlign(&D);
// If we already have a pointer to the argument, reuse the input pointer.
- if (ArgIsPointer) {
+ if (Arg.isIndirect()) {
+ DeclPtr = Arg.getIndirectAddress();
// If we have a prettier pointer type at this point, bitcast to that.
- unsigned AS = cast<llvm::PointerType>(Arg->getType())->getAddressSpace();
+ unsigned AS = DeclPtr.getType()->getAddressSpace();
llvm::Type *IRTy = ConvertTypeForMem(Ty)->getPointerTo(AS);
- DeclPtr = Arg->getType() == IRTy ? Arg : Builder.CreateBitCast(Arg, IRTy,
- D.getName());
+ if (DeclPtr.getType() != IRTy)
+ DeclPtr = Builder.CreateBitCast(DeclPtr, IRTy, D.getName());
+
// Push a destructor cleanup for this parameter if the ABI requires it.
// Don't push a cleanup in a thunk for a method that will also emit a
// cleanup.
@@ -1717,14 +1778,14 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
}
} else {
// Otherwise, create a temporary to hold the value.
- llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty),
- D.getName() + ".addr");
- Alloc->setAlignment(Align.getQuantity());
- DeclPtr = Alloc;
+ DeclPtr = CreateMemTemp(Ty, getContext().getDeclAlign(&D),
+ D.getName() + ".addr");
DoStore = true;
}
- LValue lv = MakeAddrLValue(DeclPtr, Ty, Align);
+ llvm::Value *ArgVal = (DoStore ? Arg.getDirectValue() : nullptr);
+
+ LValue lv = MakeAddrLValue(DeclPtr, Ty);
if (IsScalar) {
Qualifiers qs = Ty.getQualifiers();
if (Qualifiers::ObjCLifetime lt = qs.getObjCLifetime()) {
@@ -1754,26 +1815,26 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
// objc_storeStrong attempts to release its old value.
llvm::Value *Null = CGM.EmitNullConstant(D.getType());
EmitStoreOfScalar(Null, lv, /* isInitialization */ true);
- EmitARCStoreStrongCall(lv.getAddress(), Arg, true);
+ EmitARCStoreStrongCall(lv.getAddress(), ArgVal, true);
DoStore = false;
}
else
// Don't use objc_retainBlock for block pointers, because we
// don't want to Block_copy something just because we got it
// as a parameter.
- Arg = EmitARCRetainNonBlock(Arg);
+ ArgVal = EmitARCRetainNonBlock(ArgVal);
}
} else {
// Push the cleanup for a consumed parameter.
if (isConsumed) {
ARCPreciseLifetime_t precise = (D.hasAttr<ObjCPreciseLifetimeAttr>()
? ARCPreciseLifetime : ARCImpreciseLifetime);
- EHStack.pushCleanup<ConsumeARCParameter>(getARCCleanupKind(), Arg,
+ EHStack.pushCleanup<ConsumeARCParameter>(getARCCleanupKind(), ArgVal,
precise);
}
if (lt == Qualifiers::OCL_Weak) {
- EmitARCInitWeak(DeclPtr, Arg);
+ EmitARCInitWeak(DeclPtr, ArgVal);
DoStore = false; // The weak init is a store, no need to do two.
}
}
@@ -1785,20 +1846,18 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
// Store the initial value into the alloca.
if (DoStore)
- EmitStoreOfScalar(Arg, lv, /* isInitialization */ true);
+ EmitStoreOfScalar(ArgVal, lv, /* isInitialization */ true);
- llvm::Value *&DMEntry = LocalDeclMap[&D];
- assert(!DMEntry && "Decl already exists in localdeclmap!");
- DMEntry = DeclPtr;
+ setAddrOfLocalVar(&D, DeclPtr);
// Emit debug info for param declaration.
if (CGDebugInfo *DI = getDebugInfo()) {
if (CGM.getCodeGenOpts().getDebugInfo()
>= CodeGenOptions::LimitedDebugInfo) {
- DI->EmitDeclareOfArgVariable(&D, DeclPtr, ArgNo, Builder);
+ DI->EmitDeclareOfArgVariable(&D, DeclPtr.getPointer(), ArgNo, Builder);
}
}
if (D.hasAttr<AnnotateAttr>())
- EmitVarAnnotations(&D, DeclPtr);
+ EmitVarAnnotations(&D, DeclPtr.getPointer());
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
index 00d6d5c..adba731 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -24,16 +24,13 @@ using namespace clang;
using namespace CodeGen;
static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
- llvm::Constant *DeclPtr) {
+ ConstantAddress DeclPtr) {
assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
assert(!D.getType()->isReferenceType() &&
"Should not call EmitDeclInit on a reference!");
- ASTContext &Context = CGF.getContext();
-
- CharUnits alignment = Context.getDeclAlign(&D);
QualType type = D.getType();
- LValue lv = CGF.MakeAddrLValue(DeclPtr, type, alignment);
+ LValue lv = CGF.MakeAddrLValue(DeclPtr, type);
const Expr *Init = D.getInit();
switch (CGF.getEvaluationKind(type)) {
@@ -64,7 +61,7 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
/// Emit code to cause the destruction of the given variable with
/// static storage duration.
static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
- llvm::Constant *addr) {
+ ConstantAddress addr) {
CodeGenModule &CGM = CGF.CGM;
// FIXME: __attribute__((cleanup)) ?
@@ -99,7 +96,7 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
function = CGM.getAddrOfCXXStructor(dtor, StructorType::Complete);
argument = llvm::ConstantExpr::getBitCast(
- addr, CGF.getTypes().ConvertType(type)->getPointerTo());
+ addr.getPointer(), CGF.getTypes().ConvertType(type)->getPointerTo());
// Otherwise, the standard logic requires a helper function.
} else {
@@ -162,25 +159,26 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
DeclPtr = llvm::ConstantExpr::getAddrSpaceCast(DeclPtr, PTy);
}
+ ConstantAddress DeclAddr(DeclPtr, getContext().getDeclAlign(&D));
+
if (!T->isReferenceType()) {
if (getLangOpts().OpenMP && D.hasAttr<OMPThreadPrivateDeclAttr>())
(void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition(
- &D, DeclPtr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),
+ &D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),
PerformInit, this);
if (PerformInit)
- EmitDeclInit(*this, D, DeclPtr);
+ EmitDeclInit(*this, D, DeclAddr);
if (CGM.isTypeConstant(D.getType(), true))
EmitDeclInvariant(*this, D, DeclPtr);
else
- EmitDeclDestroy(*this, D, DeclPtr);
+ EmitDeclDestroy(*this, D, DeclAddr);
return;
}
assert(PerformInit && "cannot have constant initializer which needs "
"destruction for reference");
- unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
RValue RV = EmitReferenceBindingToExpr(Init);
- EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
+ EmitStoreOfScalar(RV.getScalarVal(), DeclAddr, false, T);
}
/// Create a stub function, suitable for being passed to atexit,
@@ -195,13 +193,15 @@ llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD,
llvm::raw_svector_ostream Out(FnName);
CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&VD, Out);
}
+
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction(ty, FnName.str(),
+ FI,
VD.getLocation());
CodeGenFunction CGF(CGM);
- CGF.StartFunction(&VD, CGM.getContext().VoidTy, fn,
- CGM.getTypes().arrangeNullaryFunction(), FunctionArgList());
+ CGF.StartFunction(&VD, CGM.getContext().VoidTy, fn, FI, FunctionArgList());
llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr);
@@ -249,7 +249,8 @@ void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
}
llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
- llvm::FunctionType *FTy, const Twine &Name, SourceLocation Loc, bool TLS) {
+ llvm::FunctionType *FTy, const Twine &Name, const CGFunctionInfo &FI,
+ SourceLocation Loc, bool TLS) {
llvm::Function *Fn =
llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
Name, &getModule());
@@ -259,7 +260,7 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
Fn->setSection(Section);
}
- SetLLVMFunctionAttributes(nullptr, getTypes().arrangeNullaryFunction(), Fn);
+ SetInternalFunctionAttributes(nullptr, Fn, FI);
Fn->setCallingConv(getRuntimeCC());
@@ -317,7 +318,9 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
// Create a variable initialization function.
llvm::Function *Fn =
- CreateGlobalInitOrDestructFunction(FTy, FnName.str(), D->getLocation());
+ CreateGlobalInitOrDestructFunction(FTy, FnName.str(),
+ getTypes().arrangeNullaryFunction(),
+ D->getLocation());
auto *ISA = D->getAttr<InitSegAttr>();
CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr,
@@ -334,7 +337,7 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
// FIXME: We only need to register one __cxa_thread_atexit function for the
// entire TU.
CXXThreadLocalInits.push_back(Fn);
- CXXThreadLocalInitVars.push_back(Addr);
+ CXXThreadLocalInitVars.push_back(D);
} else if (PerformInit && ISA) {
EmitPointerToInitFunc(D, Addr, Fn, ISA);
} else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
@@ -392,7 +395,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
return;
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
-
+ const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
// Create our global initialization function.
if (!PrioritizedCXXGlobalInits.empty()) {
@@ -416,7 +419,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
// Priority is always <= 65535 (enforced by sema).
PrioritySuffix = std::string(6-PrioritySuffix.size(), '0')+PrioritySuffix;
llvm::Function *Fn = CreateGlobalInitOrDestructFunction(
- FTy, "_GLOBAL__I_" + PrioritySuffix);
+ FTy, "_GLOBAL__I_" + PrioritySuffix, FI);
for (; I < PrioE; ++I)
LocalCXXGlobalInits.push_back(I->second);
@@ -446,7 +449,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
}
llvm::Function *Fn = CreateGlobalInitOrDestructFunction(
- FTy, llvm::Twine("_GLOBAL__sub_I_", FileName));
+ FTy, llvm::Twine("_GLOBAL__sub_I_", FileName), FI);
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits);
AddGlobalCtor(Fn);
@@ -461,7 +464,9 @@ void CodeGenModule::EmitCXXGlobalDtorFunc() {
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
// Create our global destructor function.
- llvm::Function *Fn = CreateGlobalInitOrDestructFunction(FTy, "_GLOBAL__D_a");
+ const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
+ llvm::Function *Fn =
+ CreateGlobalInitOrDestructFunction(FTy, "_GLOBAL__D_a", FI);
CodeGenFunction(*this).GenerateCXXGlobalDtorsFunc(Fn, CXXGlobalDtors);
AddGlobalDtor(Fn);
@@ -498,7 +503,7 @@ void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
void
CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
ArrayRef<llvm::Function *> Decls,
- llvm::GlobalVariable *Guard) {
+ Address Guard) {
{
auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
@@ -507,20 +512,20 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
auto AL = ApplyDebugLocation::CreateArtificial(*this);
llvm::BasicBlock *ExitBlock = nullptr;
- if (Guard) {
+ if (Guard.isValid()) {
// If we have a guard variable, check whether we've already performed
// these initializations. This happens for TLS initialization functions.
llvm::Value *GuardVal = Builder.CreateLoad(Guard);
llvm::Value *Uninit = Builder.CreateIsNull(GuardVal,
"guard.uninitialized");
- // Mark as initialized before initializing anything else. If the
- // initializers use previously-initialized thread_local vars, that's
- // probably supposed to be OK, but the standard doesn't say.
- Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard);
llvm::BasicBlock *InitBlock = createBasicBlock("init");
ExitBlock = createBasicBlock("exit");
Builder.CreateCondBr(Uninit, InitBlock, ExitBlock);
EmitBlock(InitBlock);
+ // Mark as initialized before initializing anything else. If the
+ // initializers use previously-initialized thread_local vars, that's
+ // probably supposed to be OK, but the standard doesn't say.
+ Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard);
}
RunCleanupsScope Scope(*this);
@@ -572,9 +577,10 @@ void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn,
}
/// generateDestroyHelper - Generates a helper function which, when
-/// invoked, destroys the given object.
+/// invoked, destroys the given object. The address of the object
+/// should be in global memory.
llvm::Function *CodeGenFunction::generateDestroyHelper(
- llvm::Constant *addr, QualType type, Destroyer *destroyer,
+ Address addr, QualType type, Destroyer *destroyer,
bool useEHCleanupForArray, const VarDecl *VD) {
FunctionArgList args;
ImplicitParamDecl dst(getContext(), nullptr, SourceLocation(), nullptr,
@@ -585,7 +591,7 @@ llvm::Function *CodeGenFunction::generateDestroyHelper(
getContext().VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false);
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction(
- FTy, "__cxx_global_array_dtor", VD->getLocation());
+ FTy, "__cxx_global_array_dtor", FI, VD->getLocation());
CurEHLocation = VD->getLocStart();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
index 7b8368e..fce2e75 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
@@ -1,4 +1,4 @@
-//===--- CGException.cpp - Emit LLVM Code for C++ exceptions --------------===//
+//===--- CGException.cpp - Emit LLVM Code for C++ exceptions ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -81,38 +81,6 @@ static llvm::Constant *getCatchallRethrowFn(CodeGenModule &CGM,
return CGM.CreateRuntimeFunction(FTy, Name);
}
-namespace {
- /// The exceptions personality for a function.
- struct EHPersonality {
- const char *PersonalityFn;
-
- // If this is non-null, this personality requires a non-standard
- // function for rethrowing an exception after a catchall cleanup.
- // This function must have prototype void(void*).
- const char *CatchallRethrowFn;
-
- static const EHPersonality &get(CodeGenModule &CGM,
- const FunctionDecl *FD);
- static const EHPersonality &get(CodeGenFunction &CGF) {
- return get(CGF.CGM, dyn_cast_or_null<FunctionDecl>(CGF.CurCodeDecl));
- }
-
- static const EHPersonality GNU_C;
- static const EHPersonality GNU_C_SJLJ;
- static const EHPersonality GNU_C_SEH;
- static const EHPersonality GNU_ObjC;
- static const EHPersonality GNUstep_ObjC;
- static const EHPersonality GNU_ObjCXX;
- static const EHPersonality NeXT_ObjC;
- static const EHPersonality GNU_CPlusPlus;
- static const EHPersonality GNU_CPlusPlus_SJLJ;
- static const EHPersonality GNU_CPlusPlus_SEH;
- static const EHPersonality MSVC_except_handler;
- static const EHPersonality MSVC_C_specific_handler;
- static const EHPersonality MSVC_CxxFrameHandler3;
- };
-}
-
const EHPersonality EHPersonality::GNU_C = { "__gcc_personality_v0", nullptr };
const EHPersonality
EHPersonality::GNU_C_SJLJ = { "__gcc_personality_sj0", nullptr };
@@ -161,6 +129,7 @@ static const EHPersonality &getObjCPersonality(const llvm::Triple &T,
return getCPersonality(T, L);
case ObjCRuntime::MacOSX:
case ObjCRuntime::iOS:
+ case ObjCRuntime::WatchOS:
return EHPersonality::NeXT_ObjC;
case ObjCRuntime::GNUstep:
if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
@@ -192,6 +161,7 @@ static const EHPersonality &getObjCXXPersonality(const llvm::Triple &T,
// function on targets using (backend-driven) SJLJ EH.
case ObjCRuntime::MacOSX:
case ObjCRuntime::iOS:
+ case ObjCRuntime::WatchOS:
return EHPersonality::NeXT_ObjC;
// In the fragile ABI, just use C++ exception handling and hope
@@ -221,14 +191,16 @@ const EHPersonality &EHPersonality::get(CodeGenModule &CGM,
const llvm::Triple &T = CGM.getTarget().getTriple();
const LangOptions &L = CGM.getLangOpts();
+ // Functions using SEH get an SEH personality.
+ if (FD && FD->usesSEHTry())
+ return getSEHPersonalityMSVC(T);
+
// Try to pick a personality function that is compatible with MSVC if we're
// not compiling Obj-C. Obj-C users better have an Obj-C runtime that supports
// the GCC-style personality function.
if (T.isWindowsMSVCEnvironment() && !L.ObjC1) {
if (L.SjLjExceptions)
return EHPersonality::GNU_CPlusPlus_SJLJ;
- else if (FD && FD->usesSEHTry())
- return getSEHPersonalityMSVC(T);
else
return EHPersonality::MSVC_CxxFrameHandler3;
}
@@ -243,6 +215,10 @@ const EHPersonality &EHPersonality::get(CodeGenModule &CGM,
return getCPersonality(T, L);
}
+const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) {
+ return get(CGF.CGM, dyn_cast_or_null<FunctionDecl>(CGF.CurCodeDecl));
+}
+
static llvm::Constant *getPersonalityFn(CodeGenModule &CGM,
const EHPersonality &Personality) {
llvm::Constant *Fn =
@@ -257,6 +233,36 @@ static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM,
return llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
}
+/// Check whether a landingpad instruction only uses C++ features.
+static bool LandingPadHasOnlyCXXUses(llvm::LandingPadInst *LPI) {
+ for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) {
+ // Look for something that would've been returned by the ObjC
+ // runtime's GetEHType() method.
+ llvm::Value *Val = LPI->getClause(I)->stripPointerCasts();
+ if (LPI->isCatch(I)) {
+ // Check if the catch value has the ObjC prefix.
+ if (llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Val))
+ // ObjC EH selector entries are always global variables with
+ // names starting like this.
+ if (GV->getName().startswith("OBJC_EHTYPE"))
+ return false;
+ } else {
+ // Check if any of the filter values have the ObjC prefix.
+ llvm::Constant *CVal = cast<llvm::Constant>(Val);
+ for (llvm::User::op_iterator
+ II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) {
+ if (llvm::GlobalVariable *GV =
+ cast<llvm::GlobalVariable>((*II)->stripPointerCasts()))
+ // ObjC EH selector entries are always global variables with
+ // names starting like this.
+ if (GV->getName().startswith("OBJC_EHTYPE"))
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
/// Check whether a personality function could reasonably be swapped
/// for a C++ personality function.
static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) {
@@ -269,34 +275,14 @@ static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) {
continue;
}
- // Otherwise, it has to be a landingpad instruction.
- llvm::LandingPadInst *LPI = dyn_cast<llvm::LandingPadInst>(U);
- if (!LPI) return false;
-
- for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) {
- // Look for something that would've been returned by the ObjC
- // runtime's GetEHType() method.
- llvm::Value *Val = LPI->getClause(I)->stripPointerCasts();
- if (LPI->isCatch(I)) {
- // Check if the catch value has the ObjC prefix.
- if (llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Val))
- // ObjC EH selector entries are always global variables with
- // names starting like this.
- if (GV->getName().startswith("OBJC_EHTYPE"))
- return false;
- } else {
- // Check if any of the filter values have the ObjC prefix.
- llvm::Constant *CVal = cast<llvm::Constant>(Val);
- for (llvm::User::op_iterator
- II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) {
- if (llvm::GlobalVariable *GV =
- cast<llvm::GlobalVariable>((*II)->stripPointerCasts()))
- // ObjC EH selector entries are always global variables with
- // names starting like this.
- if (GV->getName().startswith("OBJC_EHTYPE"))
- return false;
- }
- }
+ // Otherwise it must be a function.
+ llvm::Function *F = dyn_cast<llvm::Function>(U);
+ if (!F) return false;
+
+ for (auto BB = F->begin(), E = F->end(); BB != E; ++BB) {
+ if (BB->isLandingPad())
+ if (!LandingPadHasOnlyCXXUses(BB->getLandingPadInst()))
+ return false;
}
}
@@ -355,29 +341,29 @@ static llvm::Constant *getCatchAllValue(CodeGenFunction &CGF) {
namespace {
/// A cleanup to free the exception object if its initialization
/// throws.
- struct FreeException : EHScopeStack::Cleanup {
+ struct FreeException final : EHScopeStack::Cleanup {
llvm::Value *exn;
FreeException(llvm::Value *exn) : exn(exn) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
CGF.EmitNounwindRuntimeCall(getFreeExceptionFn(CGF.CGM), exn);
}
};
-}
+} // end anonymous namespace
// Emits an exception expression into the given location. This
// differs from EmitAnyExprToMem only in that, if a final copy-ctor
// call is required, an exception within that copy ctor causes
// std::terminate to be invoked.
-void CodeGenFunction::EmitAnyExprToExn(const Expr *e, llvm::Value *addr) {
+void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) {
// Make sure the exception object is cleaned up if there's an
// exception during initialization.
- pushFullExprCleanup<FreeException>(EHCleanup, addr);
+ pushFullExprCleanup<FreeException>(EHCleanup, addr.getPointer());
EHScopeStack::stable_iterator cleanup = EHStack.stable_begin();
// __cxa_allocate_exception returns a void*; we need to cast this
// to the appropriate type for the object.
llvm::Type *ty = ConvertTypeForMem(e->getType())->getPointerTo();
- llvm::Value *typedAddr = Builder.CreateBitCast(addr, ty);
+ Address typedAddr = Builder.CreateBitCast(addr, ty);
// FIXME: this isn't quite right! If there's a final unelided call
// to a copy constructor, then according to [except.terminate]p1 we
@@ -390,19 +376,20 @@ void CodeGenFunction::EmitAnyExprToExn(const Expr *e, llvm::Value *addr) {
/*IsInit*/ true);
// Deactivate the cleanup block.
- DeactivateCleanupBlock(cleanup, cast<llvm::Instruction>(typedAddr));
+ DeactivateCleanupBlock(cleanup,
+ cast<llvm::Instruction>(typedAddr.getPointer()));
}
-llvm::Value *CodeGenFunction::getExceptionSlot() {
+Address CodeGenFunction::getExceptionSlot() {
if (!ExceptionSlot)
ExceptionSlot = CreateTempAlloca(Int8PtrTy, "exn.slot");
- return ExceptionSlot;
+ return Address(ExceptionSlot, getPointerAlign());
}
-llvm::Value *CodeGenFunction::getEHSelectorSlot() {
+Address CodeGenFunction::getEHSelectorSlot() {
if (!EHSelectorSlot)
EHSelectorSlot = CreateTempAlloca(Int32Ty, "ehselector.slot");
- return EHSelectorSlot;
+ return Address(EHSelectorSlot, CharUnits::fromQuantity(4));
}
llvm::Value *CodeGenFunction::getExceptionFromSlot() {
@@ -571,22 +558,25 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
QualType CaughtType = CGM.getContext().getUnqualifiedArrayType(
C->getCaughtType().getNonReferenceType(), CaughtTypeQuals);
- llvm::Constant *TypeInfo = nullptr;
+ CatchTypeInfo TypeInfo{nullptr, 0};
if (CaughtType->isObjCObjectPointerType())
- TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType);
+ TypeInfo.RTTI = CGM.getObjCRuntime().GetEHType(CaughtType);
else
- TypeInfo =
- CGM.getAddrOfCXXCatchHandlerType(CaughtType, C->getCaughtType());
+ TypeInfo = CGM.getCXXABI().getAddrOfCXXCatchHandlerType(
+ CaughtType, C->getCaughtType());
CatchScope->setHandler(I, TypeInfo, Handler);
} else {
// No exception decl indicates '...', a catch-all.
- CatchScope->setCatchAllHandler(I, Handler);
+ CatchScope->setHandler(I, CGM.getCXXABI().getCatchAllTypeInfo(), Handler);
}
}
}
llvm::BasicBlock *
CodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) {
+ if (EHPersonality::get(*this).usesFuncletPads())
+ return getMSVCDispatchBlock(si);
+
// The dispatch block for the end of the scope chain is a block that
// just resumes unwinding.
if (si == EHStack.stable_end())
@@ -623,12 +613,58 @@ CodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) {
case EHScope::Terminate:
dispatchBlock = getTerminateHandler();
break;
+
+ case EHScope::PadEnd:
+ llvm_unreachable("PadEnd unnecessary for Itanium!");
}
scope.setCachedEHDispatchBlock(dispatchBlock);
}
return dispatchBlock;
}
+llvm::BasicBlock *
+CodeGenFunction::getMSVCDispatchBlock(EHScopeStack::stable_iterator SI) {
+ // Returning nullptr indicates that the previous dispatch block should unwind
+ // to caller.
+ if (SI == EHStack.stable_end())
+ return nullptr;
+
+ // Otherwise, we should look at the actual scope.
+ EHScope &EHS = *EHStack.find(SI);
+
+ llvm::BasicBlock *DispatchBlock = EHS.getCachedEHDispatchBlock();
+ if (DispatchBlock)
+ return DispatchBlock;
+
+ if (EHS.getKind() == EHScope::Terminate)
+ DispatchBlock = getTerminateHandler();
+ else
+ DispatchBlock = createBasicBlock();
+ CGBuilderTy Builder(*this, DispatchBlock);
+
+ switch (EHS.getKind()) {
+ case EHScope::Catch:
+ DispatchBlock->setName("catch.dispatch");
+ break;
+
+ case EHScope::Cleanup:
+ DispatchBlock->setName("ehcleanup");
+ break;
+
+ case EHScope::Filter:
+ llvm_unreachable("exception specifications not handled yet!");
+
+ case EHScope::Terminate:
+ DispatchBlock->setName("terminate");
+ break;
+
+ case EHScope::PadEnd:
+ llvm_unreachable("PadEnd dispatch block missing!");
+ }
+ EHS.setCachedEHDispatchBlock(DispatchBlock);
+ return DispatchBlock;
+}
+
/// Check whether this is a non-EH scope, i.e. a scope which doesn't
/// affect exception handling. Currently, the only non-EH scopes are
/// normal-only cleanup scopes.
@@ -639,6 +675,7 @@ static bool isNonEHScope(const EHScope &S) {
case EHScope::Filter:
case EHScope::Catch:
case EHScope::Terminate:
+ case EHScope::PadEnd:
return false;
}
@@ -664,8 +701,19 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() {
llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad();
if (LP) return LP;
- // Build the landing pad for this scope.
- LP = EmitLandingPad();
+ const EHPersonality &Personality = EHPersonality::get(*this);
+
+ if (!CurFn->hasPersonalityFn())
+ CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, Personality));
+
+ if (Personality.usesFuncletPads()) {
+ // We don't need separate landing pads in the funclet model.
+ LP = getEHDispatchBlock(EHStack.getInnermostEHScope());
+ } else {
+ // Build the landing pad for this scope.
+ LP = EmitLandingPad();
+ }
+
assert(LP);
// Cache the landing pad on the innermost scope. If this is a
@@ -686,6 +734,9 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
case EHScope::Terminate:
return getTerminateLandingPad();
+ case EHScope::PadEnd:
+ llvm_unreachable("PadEnd unnecessary for Itanium!");
+
case EHScope::Catch:
case EHScope::Cleanup:
case EHScope::Filter:
@@ -697,11 +748,6 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP();
auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, CurEHLocation);
- const EHPersonality &personality = EHPersonality::get(*this);
-
- if (!CurFn->hasPersonalityFn())
- CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, personality));
-
// Create and configure the landing pad.
llvm::BasicBlock *lpad = createBasicBlock("lpad");
EmitBlock(lpad);
@@ -756,23 +802,28 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
case EHScope::Catch:
break;
+
+ case EHScope::PadEnd:
+ llvm_unreachable("PadEnd unnecessary for Itanium!");
}
EHCatchScope &catchScope = cast<EHCatchScope>(*I);
for (unsigned hi = 0, he = catchScope.getNumHandlers(); hi != he; ++hi) {
EHCatchScope::Handler handler = catchScope.getHandler(hi);
+ assert(handler.Type.Flags == 0 &&
+ "landingpads do not support catch handler flags");
// If this is a catch-all, register that and abort.
- if (!handler.Type) {
+ if (!handler.Type.RTTI) {
assert(!hasCatchAll);
hasCatchAll = true;
goto done;
}
// Check whether we already have a handler for this type.
- if (catchTypes.insert(handler.Type).second)
+ if (catchTypes.insert(handler.Type.RTTI).second)
// If not, add it directly to the landingpad.
- LPadInst->addClause(handler.Type);
+ LPadInst->addClause(handler.Type.RTTI);
}
}
@@ -820,10 +871,53 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
return lpad;
}
+static void emitCatchPadBlock(CodeGenFunction &CGF, EHCatchScope &CatchScope) {
+ llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock();
+ assert(DispatchBlock);
+
+ CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP();
+ CGF.EmitBlockAfterUses(DispatchBlock);
+
+ llvm::Value *ParentPad = CGF.CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGF.getLLVMContext());
+ llvm::BasicBlock *UnwindBB =
+ CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope());
+
+ unsigned NumHandlers = CatchScope.getNumHandlers();
+ llvm::CatchSwitchInst *CatchSwitch =
+ CGF.Builder.CreateCatchSwitch(ParentPad, UnwindBB, NumHandlers);
+
+ // Test against each of the exception types we claim to catch.
+ for (unsigned I = 0; I < NumHandlers; ++I) {
+ const EHCatchScope::Handler &Handler = CatchScope.getHandler(I);
+
+ CatchTypeInfo TypeInfo = Handler.Type;
+ if (!TypeInfo.RTTI)
+ TypeInfo.RTTI = llvm::Constant::getNullValue(CGF.VoidPtrTy);
+
+ CGF.Builder.SetInsertPoint(Handler.Block);
+
+ if (EHPersonality::get(CGF).isMSVCXXPersonality()) {
+ CGF.Builder.CreateCatchPad(
+ CatchSwitch, {TypeInfo.RTTI, CGF.Builder.getInt32(TypeInfo.Flags),
+ llvm::Constant::getNullValue(CGF.VoidPtrTy)});
+ } else {
+ CGF.Builder.CreateCatchPad(CatchSwitch, {TypeInfo.RTTI});
+ }
+
+ CatchSwitch->addHandler(Handler.Block);
+ }
+ CGF.Builder.restoreIP(SavedIP);
+}
+
/// Emit the structure of the dispatch block for the given catch scope.
/// It is an invariant that the dispatch block already exists.
static void emitCatchDispatchBlock(CodeGenFunction &CGF,
EHCatchScope &catchScope) {
+ if (EHPersonality::get(CGF).usesFuncletPads())
+ return emitCatchPadBlock(CGF, catchScope);
+
llvm::BasicBlock *dispatchBlock = catchScope.getCachedEHDispatchBlock();
assert(dispatchBlock);
@@ -850,7 +944,9 @@ static void emitCatchDispatchBlock(CodeGenFunction &CGF,
assert(i < e && "ran off end of handlers!");
const EHCatchScope::Handler &handler = catchScope.getHandler(i);
- llvm::Value *typeValue = handler.Type;
+ llvm::Value *typeValue = handler.Type.RTTI;
+ assert(handler.Type.Flags == 0 &&
+ "landingpads do not support catch handler flags");
assert(typeValue && "fell into catch-all case!");
typeValue = CGF.Builder.CreateBitCast(typeValue, CGF.Int8PtrTy);
@@ -919,9 +1015,8 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
// Copy the handler blocks off before we pop the EH stack. Emitting
// the handlers might scribble on this memory.
- SmallVector<EHCatchScope::Handler, 8> Handlers(NumHandlers);
- memcpy(Handlers.data(), CatchScope.begin(),
- NumHandlers * sizeof(EHCatchScope::Handler));
+ SmallVector<EHCatchScope::Handler, 8> Handlers(
+ CatchScope.begin(), CatchScope.begin() + NumHandlers);
EHStack.popCatch();
@@ -958,6 +1053,8 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
RunCleanupsScope CatchScope(*this);
// Initialize the catch variable and set up the cleanups.
+ SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
+ CurrentFuncletPad);
CGM.getCXXABI().emitBeginCatch(*this, C);
// Emit the PGO counter increment.
@@ -994,7 +1091,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
}
namespace {
- struct CallEndCatchForFinally : EHScopeStack::Cleanup {
+ struct CallEndCatchForFinally final : EHScopeStack::Cleanup {
llvm::Value *ForEHVar;
llvm::Value *EndCatchFn;
CallEndCatchForFinally(llvm::Value *ForEHVar, llvm::Value *EndCatchFn)
@@ -1006,7 +1103,7 @@ namespace {
CGF.createBasicBlock("finally.cleanup.cont");
llvm::Value *ShouldEndCatch =
- CGF.Builder.CreateLoad(ForEHVar, "finally.endcatch");
+ CGF.Builder.CreateFlagLoad(ForEHVar, "finally.endcatch");
CGF.Builder.CreateCondBr(ShouldEndCatch, EndCatchBB, CleanupContBB);
CGF.EmitBlock(EndCatchBB);
CGF.EmitRuntimeCallOrInvoke(EndCatchFn); // catch-all, so might throw
@@ -1014,7 +1111,7 @@ namespace {
}
};
- struct PerformFinally : EHScopeStack::Cleanup {
+ struct PerformFinally final : EHScopeStack::Cleanup {
const Stmt *Body;
llvm::Value *ForEHVar;
llvm::Value *EndCatchFn;
@@ -1049,13 +1146,13 @@ namespace {
llvm::BasicBlock *ContBB = CGF.createBasicBlock("finally.cont");
llvm::Value *ShouldRethrow =
- CGF.Builder.CreateLoad(ForEHVar, "finally.shouldthrow");
+ CGF.Builder.CreateFlagLoad(ForEHVar, "finally.shouldthrow");
CGF.Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB);
CGF.EmitBlock(RethrowBB);
if (SavedExnVar) {
CGF.EmitRuntimeCallOrInvoke(RethrowFn,
- CGF.Builder.CreateLoad(SavedExnVar));
+ CGF.Builder.CreateAlignedLoad(SavedExnVar, CGF.getPointerAlign()));
} else {
CGF.EmitRuntimeCallOrInvoke(RethrowFn);
}
@@ -1082,7 +1179,7 @@ namespace {
CGF.EnsureInsertPoint();
}
};
-}
+} // end anonymous namespace
/// Enters a finally block for an implementation using zero-cost
/// exceptions. This is mostly general, but hard-codes some
@@ -1130,7 +1227,7 @@ void CodeGenFunction::FinallyInfo::enter(CodeGenFunction &CGF,
// Whether the finally block is being executed for EH purposes.
ForEHVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "finally.for-eh");
- CGF.Builder.CreateStore(CGF.Builder.getFalse(), ForEHVar);
+ CGF.Builder.CreateFlagStore(false, ForEHVar);
// Enter a normal cleanup which will perform the @finally block.
CGF.EHStack.pushCleanup<PerformFinally>(NormalCleanup, body,
@@ -1168,11 +1265,11 @@ void CodeGenFunction::FinallyInfo::exit(CodeGenFunction &CGF) {
// If we need to remember the exception pointer to rethrow later, do so.
if (SavedExnVar) {
if (!exn) exn = CGF.getExceptionFromSlot();
- CGF.Builder.CreateStore(exn, SavedExnVar);
+ CGF.Builder.CreateAlignedStore(exn, SavedExnVar, CGF.getPointerAlign());
}
// Tell the cleanups in the finally block that we're do this for EH.
- CGF.Builder.CreateStore(CGF.Builder.getTrue(), ForEHVar);
+ CGF.Builder.CreateFlagStore(true, ForEHVar);
// Thread a jump through the finally cleanup.
CGF.EmitBranchThroughCleanup(RethrowDest);
@@ -1204,7 +1301,7 @@ llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() {
llvm::StructType::get(Int8PtrTy, Int32Ty, nullptr), 0);
LPadInst->addClause(getCatchAllValue(*this));
- llvm::Value *Exn = 0;
+ llvm::Value *Exn = nullptr;
if (getLangOpts().CPlusPlus)
Exn = Builder.CreateExtractValue(LPadInst, 0);
llvm::CallInst *terminateCall =
@@ -1228,9 +1325,16 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
// end of the function by FinishFunction.
TerminateHandler = createBasicBlock("terminate.handler");
Builder.SetInsertPoint(TerminateHandler);
- llvm::Value *Exn = 0;
- if (getLangOpts().CPlusPlus)
- Exn = getExceptionFromSlot();
+ llvm::Value *Exn = nullptr;
+ if (EHPersonality::get(*this).usesFuncletPads()) {
+ llvm::Value *ParentPad = CurrentFuncletPad;
+ if (!ParentPad)
+ ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
+ Builder.CreateCleanupPad(ParentPad);
+ } else {
+ if (getLangOpts().CPlusPlus)
+ Exn = getExceptionFromSlot();
+ }
llvm::CallInst *terminateCall =
CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);
terminateCall->setDoesNotReturn();
@@ -1297,7 +1401,7 @@ void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
}
namespace {
-struct PerformSEHFinally : EHScopeStack::Cleanup {
+struct PerformSEHFinally final : EHScopeStack::Cleanup {
llvm::Function *OutlinedFinally;
PerformSEHFinally(llvm::Function *OutlinedFinally)
: OutlinedFinally(OutlinedFinally) {}
@@ -1328,21 +1432,21 @@ struct PerformSEHFinally : EHScopeStack::Cleanup {
CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args);
}
};
-}
+} // end anonymous namespace
namespace {
/// Find all local variable captures in the statement.
struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
CodeGenFunction &ParentCGF;
const VarDecl *ParentThis;
- SmallVector<const VarDecl *, 4> Captures;
- llvm::Value *SEHCodeSlot = nullptr;
+ llvm::SmallSetVector<const VarDecl *, 4> Captures;
+ Address SEHCodeSlot = Address::invalid();
CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis)
: ParentCGF(ParentCGF), ParentThis(ParentThis) {}
// Return true if we need to do any capturing work.
bool foundCaptures() {
- return !Captures.empty() || SEHCodeSlot;
+ return !Captures.empty() || SEHCodeSlot.isValid();
}
void Visit(const Stmt *S) {
@@ -1356,17 +1460,17 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
void VisitDeclRefExpr(const DeclRefExpr *E) {
// If this is already a capture, just make sure we capture 'this'.
if (E->refersToEnclosingVariableOrCapture()) {
- Captures.push_back(ParentThis);
+ Captures.insert(ParentThis);
return;
}
const auto *D = dyn_cast<VarDecl>(E->getDecl());
if (D && D->isLocalVarDeclOrParm() && D->hasLocalStorage())
- Captures.push_back(D);
+ Captures.insert(D);
}
void VisitCXXThisExpr(const CXXThisExpr *E) {
- Captures.push_back(ParentThis);
+ Captures.insert(ParentThis);
}
void VisitCallExpr(const CallExpr *E) {
@@ -1381,19 +1485,20 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
// This is the simple case where we are the outermost finally. All we
// have to do here is make sure we escape this and recover it in the
// outlined handler.
- if (!SEHCodeSlot)
+ if (!SEHCodeSlot.isValid())
SEHCodeSlot = ParentCGF.SEHCodeSlotStack.back();
break;
}
}
};
-}
+} // end anonymous namespace
-llvm::Value *CodeGenFunction::recoverAddrOfEscapedLocal(
- CodeGenFunction &ParentCGF, llvm::Value *ParentVar, llvm::Value *ParentFP) {
+Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF,
+ Address ParentVar,
+ llvm::Value *ParentFP) {
llvm::CallInst *RecoverCall = nullptr;
- CGBuilderTy Builder(AllocaInsertPt);
- if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) {
+ CGBuilderTy Builder(*this, AllocaInsertPt);
+ if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar.getPointer())) {
// Mark the variable escaped if nobody else referenced it and compute the
// localescape index.
auto InsertPair = ParentCGF.EscapedLocals.insert(
@@ -1413,7 +1518,7 @@ llvm::Value *CodeGenFunction::recoverAddrOfEscapedLocal(
// Just clone the existing localrecover call, but tweak the FP argument to
// use our FP value. All other arguments are constants.
auto *ParentRecover =
- cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts());
+ cast<llvm::IntrinsicInst>(ParentVar.getPointer()->stripPointerCasts());
assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover &&
"expected alloca or localrecover in parent LocalDeclMap");
RecoverCall = cast<llvm::CallInst>(ParentRecover->clone());
@@ -1423,9 +1528,9 @@ llvm::Value *CodeGenFunction::recoverAddrOfEscapedLocal(
// Bitcast the variable, rename it, and insert it in the local decl map.
llvm::Value *ChildVar =
- Builder.CreateBitCast(RecoverCall, ParentVar->getType());
- ChildVar->setName(ParentVar->getName());
- return ChildVar;
+ Builder.CreateBitCast(RecoverCall, ParentVar.getType());
+ ChildVar->setName(ParentVar.getName());
+ return Address(ChildVar, ParentVar.getAlignment());
}
void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
@@ -1444,27 +1549,32 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
return;
}
- llvm::Value *EntryEBP = nullptr;
- llvm::Value *ParentFP;
+ llvm::Value *EntryFP = nullptr;
+ CGBuilderTy Builder(CGM, AllocaInsertPt);
if (IsFilter && CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) {
// 32-bit SEH filters need to be careful about FP recovery. The end of the
// EH registration is passed in as the EBP physical register. We can
- // recover that with llvm.frameaddress(1), and adjust that to recover the
- // parent's true frame pointer.
- CGBuilderTy Builder(AllocaInsertPt);
- EntryEBP = Builder.CreateCall(
+ // recover that with llvm.frameaddress(1).
+ EntryFP = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::frameaddress), {Builder.getInt32(1)});
- llvm::Function *RecoverFPIntrin =
- CGM.getIntrinsic(llvm::Intrinsic::x86_seh_recoverfp);
- llvm::Constant *ParentI8Fn =
- llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
- ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryEBP});
} else {
// Otherwise, for x64 and 32-bit finally functions, the parent FP is the
// second parameter.
auto AI = CurFn->arg_begin();
++AI;
- ParentFP = AI;
+ EntryFP = &*AI;
+ }
+
+ llvm::Value *ParentFP = EntryFP;
+ if (IsFilter) {
+ // Given whatever FP the runtime provided us in EntryFP, recover the true
+ // frame pointer of the parent function. We only need to do this in filters,
+ // since finally funclets recover the parent FP for us.
+ llvm::Function *RecoverFPIntrin =
+ CGM.getIntrinsic(llvm::Intrinsic::x86_seh_recoverfp);
+ llvm::Constant *ParentI8Fn =
+ llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
+ ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryFP});
}
// Create llvm.localrecover calls for all captures.
@@ -1486,19 +1596,19 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
auto I = ParentCGF.LocalDeclMap.find(VD);
if (I == ParentCGF.LocalDeclMap.end())
continue;
- llvm::Value *ParentVar = I->second;
- LocalDeclMap[VD] =
- recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP);
+ Address ParentVar = I->second;
+ setAddrOfLocalVar(
+ VD, recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP));
}
- if (Finder.SEHCodeSlot) {
+ if (Finder.SEHCodeSlot.isValid()) {
SEHCodeSlotStack.push_back(
recoverAddrOfEscapedLocal(ParentCGF, Finder.SEHCodeSlot, ParentFP));
}
if (IsFilter)
- EmitSEHExceptionCodeSave(ParentCGF, ParentFP, EntryEBP);
+ EmitSEHExceptionCodeSave(ParentCGF, ParentFP, EntryFP);
}
/// Arrange a function prototype that can be called by Windows exception
@@ -1614,13 +1724,12 @@ CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF,
llvm::Value *ParentFP,
- llvm::Value *EntryEBP) {
+ llvm::Value *EntryFP) {
// Get the pointer to the EXCEPTION_POINTERS struct. This is returned by the
// __exception_info intrinsic.
if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
// On Win64, the info is passed as the first parameter to the filter.
- auto AI = CurFn->arg_begin();
- SEHInfo = AI;
+ SEHInfo = &*CurFn->arg_begin();
SEHCodeSlotStack.push_back(
CreateMemTemp(getContext().IntTy, "__exception_code"));
} else {
@@ -1628,9 +1737,9 @@ void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF,
// exception registration object. It contains 6 32-bit fields, and the info
// pointer is stored in the second field. So, GEP 20 bytes backwards and
// load the pointer.
- SEHInfo = Builder.CreateConstInBoundsGEP1_32(Int8Ty, EntryEBP, -20);
+ SEHInfo = Builder.CreateConstInBoundsGEP1_32(Int8Ty, EntryFP, -20);
SEHInfo = Builder.CreateBitCast(SEHInfo, Int8PtrTy->getPointerTo());
- SEHInfo = Builder.CreateLoad(Int8PtrTy, SEHInfo);
+ SEHInfo = Builder.CreateAlignedLoad(Int8PtrTy, SEHInfo, getPointerAlign());
SEHCodeSlotStack.push_back(recoverAddrOfEscapedLocal(
ParentCGF, ParentCGF.SEHCodeSlotStack.back(), ParentFP));
}
@@ -1646,8 +1755,8 @@ void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF,
llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy, nullptr);
llvm::Value *Ptrs = Builder.CreateBitCast(SEHInfo, PtrsTy->getPointerTo());
llvm::Value *Rec = Builder.CreateStructGEP(PtrsTy, Ptrs, 0);
- Rec = Builder.CreateLoad(Rec);
- llvm::Value *Code = Builder.CreateLoad(Rec);
+ Rec = Builder.CreateAlignedLoad(Rec, getPointerAlign());
+ llvm::Value *Code = Builder.CreateAlignedLoad(Rec, getIntAlign());
assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except");
Builder.CreateStore(Code, SEHCodeSlotStack.back());
}
@@ -1663,7 +1772,7 @@ llvm::Value *CodeGenFunction::EmitSEHExceptionInfo() {
llvm::Value *CodeGenFunction::EmitSEHExceptionCode() {
assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except");
- return Builder.CreateLoad(Int32Ty, SEHCodeSlotStack.back());
+ return Builder.CreateLoad(SEHCodeSlotStack.back());
}
llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
@@ -1709,7 +1818,7 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
HelperCGF.GenerateSEHFilterFunction(*this, *Except);
llvm::Constant *OpaqueFunc =
llvm::ConstantExpr::getBitCast(FilterFunc, Int8PtrTy);
- CatchScope->setHandler(0, OpaqueFunc, createBasicBlock("__except"));
+ CatchScope->setHandler(0, OpaqueFunc, createBasicBlock("__except.ret"));
}
void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
@@ -1745,16 +1854,24 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
emitCatchDispatchBlock(*this, CatchScope);
// Grab the block before we pop the handler.
- llvm::BasicBlock *ExceptBB = CatchScope.getHandler(0).Block;
+ llvm::BasicBlock *CatchPadBB = CatchScope.getHandler(0).Block;
EHStack.popCatch();
- EmitBlockAfterUses(ExceptBB);
+ EmitBlockAfterUses(CatchPadBB);
+
+ // __except blocks don't get outlined into funclets, so immediately do a
+ // catchret.
+ llvm::CatchPadInst *CPI =
+ cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI());
+ llvm::BasicBlock *ExceptBB = createBasicBlock("__except");
+ Builder.CreateCatchRet(CPI, ExceptBB);
+ EmitBlock(ExceptBB);
- // On Win64, the exception pointer is the exception code. Copy it to the slot.
+ // On Win64, the exception code is returned in EAX. Copy it into the slot.
if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
- llvm::Value *Code =
- Builder.CreatePtrToInt(getExceptionFromSlot(), IntPtrTy);
- Code = Builder.CreateTrunc(Code, Int32Ty);
+ llvm::Function *SEHCodeIntrin =
+ CGM.getIntrinsic(llvm::Intrinsic::eh_exceptioncode);
+ llvm::Value *Code = Builder.CreateCall(SEHCodeIntrin, {CPI});
Builder.CreateStore(Code, SEHCodeSlotStack.back());
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
index 9c3dfe5..507ce3d 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
@@ -54,6 +54,15 @@ llvm::Value *CodeGenFunction::EmitCastToVoidPtr(llvm::Value *value) {
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block.
+Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align,
+ const Twine &Name) {
+ auto Alloca = CreateTempAlloca(Ty, Name);
+ Alloca->setAlignment(Align.getQuantity());
+ return Address(Alloca, Align);
+}
+
+/// CreateTempAlloca - This creates a alloca and inserts it into the entry
+/// block.
llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty,
const Twine &Name) {
if (!Builder.isNamePreserving())
@@ -61,29 +70,38 @@ llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty,
return new llvm::AllocaInst(Ty, nullptr, Name, AllocaInsertPt);
}
-void CodeGenFunction::InitTempAlloca(llvm::AllocaInst *Var,
- llvm::Value *Init) {
- auto *Store = new llvm::StoreInst(Init, Var);
+/// CreateDefaultAlignTempAlloca - This creates an alloca with the
+/// default alignment of the corresponding LLVM type, which is *not*
+/// guaranteed to be related in any way to the expected alignment of
+/// an AST type that might have been lowered to Ty.
+Address CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty,
+ const Twine &Name) {
+ CharUnits Align =
+ CharUnits::fromQuantity(CGM.getDataLayout().getABITypeAlignment(Ty));
+ return CreateTempAlloca(Ty, Align, Name);
+}
+
+void CodeGenFunction::InitTempAlloca(Address Var, llvm::Value *Init) {
+ assert(isa<llvm::AllocaInst>(Var.getPointer()));
+ auto *Store = new llvm::StoreInst(Init, Var.getPointer());
+ Store->setAlignment(Var.getAlignment().getQuantity());
llvm::BasicBlock *Block = AllocaInsertPt->getParent();
- Block->getInstList().insertAfter(&*AllocaInsertPt, Store);
+ Block->getInstList().insertAfter(AllocaInsertPt->getIterator(), Store);
}
-llvm::AllocaInst *CodeGenFunction::CreateIRTemp(QualType Ty,
- const Twine &Name) {
- llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertType(Ty), Name);
- // FIXME: Should we prefer the preferred type alignment here?
+Address CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) {
CharUnits Align = getContext().getTypeAlignInChars(Ty);
- Alloc->setAlignment(Align.getQuantity());
- return Alloc;
+ return CreateTempAlloca(ConvertType(Ty), Align, Name);
}
-llvm::AllocaInst *CodeGenFunction::CreateMemTemp(QualType Ty,
- const Twine &Name) {
- llvm::AllocaInst *Alloc = CreateTempAlloca(ConvertTypeForMem(Ty), Name);
+Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name) {
// FIXME: Should we prefer the preferred type alignment here?
- CharUnits Align = getContext().getTypeAlignInChars(Ty);
- Alloc->setAlignment(Align.getQuantity());
- return Alloc;
+ return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name);
+}
+
+Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align,
+ const Twine &Name) {
+ return CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name);
}
/// EvaluateExprAsBool - Perform the usual unary conversions on the specified
@@ -96,10 +114,12 @@ llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) {
}
QualType BoolTy = getContext().BoolTy;
+ SourceLocation Loc = E->getExprLoc();
if (!E->getType()->isAnyComplexType())
- return EmitScalarConversion(EmitScalarExpr(E), E->getType(), BoolTy);
+ return EmitScalarConversion(EmitScalarExpr(E), E->getType(), BoolTy, Loc);
- return EmitComplexToScalarConversion(EmitComplexExpr(E), E->getType(),BoolTy);
+ return EmitComplexToScalarConversion(EmitComplexExpr(E), E->getType(), BoolTy,
+ Loc);
}
/// EmitIgnoredExpr - Emit code to compute the specified expression,
@@ -146,20 +166,18 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E) {
/// EmitAnyExprToMem - Evaluate an expression into a given memory
/// location.
void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
- llvm::Value *Location,
+ Address Location,
Qualifiers Quals,
bool IsInit) {
// FIXME: This function should take an LValue as an argument.
switch (getEvaluationKind(E->getType())) {
case TEK_Complex:
- EmitComplexExprIntoLValue(E,
- MakeNaturalAlignAddrLValue(Location, E->getType()),
+ EmitComplexExprIntoLValue(E, MakeAddrLValue(Location, E->getType()),
/*isInit*/ false);
return;
case TEK_Aggregate: {
- CharUnits Alignment = getContext().getTypeAlignInChars(E->getType());
- EmitAggExpr(E, AggValueSlot::forAddr(Location, Alignment, Quals,
+ EmitAggExpr(E, AggValueSlot::forAddr(Location, Quals,
AggValueSlot::IsDestructed_t(IsInit),
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsAliased_t(!IsInit)));
@@ -178,17 +196,14 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
static void
pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
- const Expr *E, llvm::Value *ReferenceTemporary) {
+ const Expr *E, Address ReferenceTemporary) {
// Objective-C++ ARC:
// If we are binding a reference to a temporary that has ownership, we
// need to perform retain/release operations on the temporary.
//
// FIXME: This should be looking at E, not M.
- if (CGF.getLangOpts().ObjCAutoRefCount &&
- M->getType()->isObjCLifetimeType()) {
- QualType ObjCARCReferenceLifetimeType = M->getType();
- switch (Qualifiers::ObjCLifetime Lifetime =
- ObjCARCReferenceLifetimeType.getObjCLifetime()) {
+ if (auto Lifetime = M->getType().getObjCLifetime()) {
+ switch (Lifetime) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
// Carry on to normal cleanup handling.
@@ -229,11 +244,11 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
}
if (Duration == SD_FullExpression)
CGF.pushDestroy(CleanupKind, ReferenceTemporary,
- ObjCARCReferenceLifetimeType, *Destroy,
+ M->getType(), *Destroy,
CleanupKind & EHCleanup);
else
CGF.pushLifetimeExtendedDestroy(CleanupKind, ReferenceTemporary,
- ObjCARCReferenceLifetimeType,
+ M->getType(),
*Destroy, CleanupKind & EHCleanup);
return;
@@ -264,14 +279,14 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
llvm::Constant *CleanupArg;
if (E->getType()->isArrayType()) {
CleanupFn = CodeGenFunction(CGF.CGM).generateDestroyHelper(
- cast<llvm::Constant>(ReferenceTemporary), E->getType(),
+ ReferenceTemporary, E->getType(),
CodeGenFunction::destroyCXXObject, CGF.getLangOpts().Exceptions,
dyn_cast_or_null<VarDecl>(M->getExtendingDecl()));
CleanupArg = llvm::Constant::getNullValue(CGF.Int8PtrTy);
} else {
CleanupFn = CGF.CGM.getAddrOfCXXStructor(ReferenceTemporaryDtor,
StructorType::Complete);
- CleanupArg = cast<llvm::Constant>(ReferenceTemporary);
+ CleanupArg = cast<llvm::Constant>(ReferenceTemporary.getPointer());
}
CGF.CGM.getCXXABI().registerGlobalDtor(
CGF, *cast<VarDecl>(M->getExtendingDecl()), CleanupFn, CleanupArg);
@@ -296,7 +311,7 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
}
}
-static llvm::Value *
+static Address
createReferenceTemporary(CodeGenFunction &CGF,
const MaterializeTemporaryExpr *M, const Expr *Inner) {
switch (M->getStorageDuration()) {
@@ -314,10 +329,10 @@ createReferenceTemporary(CodeGenFunction &CGF,
auto *GV = new llvm::GlobalVariable(
CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
llvm::GlobalValue::PrivateLinkage, Init, ".ref.tmp");
- GV->setAlignment(
- CGF.getContext().getTypeAlignInChars(Ty).getQuantity());
+ CharUnits alignment = CGF.getContext().getTypeAlignInChars(Ty);
+ GV->setAlignment(alignment.getQuantity());
// FIXME: Should we put the new global into a COMDAT?
- return GV;
+ return Address(GV, alignment);
}
return CGF.CreateMemTemp(Ty, "ref.tmp");
}
@@ -337,20 +352,22 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
// FIXME: ideally this would use EmitAnyExprToMem, however, we cannot do so
// as that will cause the lifetime adjustment to be lost for ARC
- if (getLangOpts().ObjCAutoRefCount &&
- M->getType()->isObjCLifetimeType() &&
- M->getType().getObjCLifetime() != Qualifiers::OCL_None &&
- M->getType().getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
- llvm::Value *Object = createReferenceTemporary(*this, M, E);
- if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
- Object = llvm::ConstantExpr::getBitCast(
- Var, ConvertTypeForMem(E->getType())->getPointerTo());
+ auto ownership = M->getType().getObjCLifetime();
+ if (ownership != Qualifiers::OCL_None &&
+ ownership != Qualifiers::OCL_ExplicitNone) {
+ Address Object = createReferenceTemporary(*this, M, E);
+ if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object.getPointer())) {
+ Object = Address(llvm::ConstantExpr::getBitCast(Var,
+ ConvertTypeForMem(E->getType())
+ ->getPointerTo(Object.getAddressSpace())),
+ Object.getAlignment());
// We should not have emitted the initializer for this temporary as a
// constant.
assert(!Var->hasInitializer());
Var->setInitializer(CGM.EmitNullConstant(E->getType()));
}
- LValue RefTempDst = MakeAddrLValue(Object, M->getType());
+ LValue RefTempDst = MakeAddrLValue(Object, M->getType(),
+ AlignmentSource::Decl);
switch (getEvaluationKind(E->getType())) {
default: llvm_unreachable("expected scalar or aggregate expression");
@@ -358,8 +375,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
EmitScalarInit(E, M->getExtendingDecl(), RefTempDst, false);
break;
case TEK_Aggregate: {
- CharUnits Alignment = getContext().getTypeAlignInChars(E->getType());
- EmitAggExpr(E, AggValueSlot::forAddr(Object, Alignment,
+ EmitAggExpr(E, AggValueSlot::forAddr(Object,
E->getType().getQualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
@@ -387,10 +403,11 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
}
// Create and initialize the reference temporary.
- llvm::Value *Object = createReferenceTemporary(*this, M, E);
- if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object)) {
- Object = llvm::ConstantExpr::getBitCast(
- Var, ConvertTypeForMem(E->getType())->getPointerTo());
+ Address Object = createReferenceTemporary(*this, M, E);
+ if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object.getPointer())) {
+ Object = Address(llvm::ConstantExpr::getBitCast(
+ Var, ConvertTypeForMem(E->getType())->getPointerTo()),
+ Object.getAlignment());
// If the temporary is a global and has a constant initializer or is a
// constant temporary that we promoted to a global, we may have already
// initialized it.
@@ -418,7 +435,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
break;
case SubobjectAdjustment::FieldAdjustment: {
- LValue LV = MakeAddrLValue(Object, E->getType());
+ LValue LV = MakeAddrLValue(Object, E->getType(),
+ AlignmentSource::Decl);
LV = EmitLValueForField(LV, Adjustment.Field);
assert(LV.isSimple() &&
"materialized temporary field is not a simple lvalue");
@@ -428,14 +446,14 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
case SubobjectAdjustment::MemberPointerAdjustment: {
llvm::Value *Ptr = EmitScalarExpr(Adjustment.Ptr.RHS);
- Object = CGM.getCXXABI().EmitMemberDataPointerAddress(
- *this, E, Object, Ptr, Adjustment.Ptr.MPT);
+ Object = EmitCXXMemberDataPointerAddress(E, Object, Ptr,
+ Adjustment.Ptr.MPT);
break;
}
}
}
- return MakeAddrLValue(Object, M->getType());
+ return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl);
}
RValue
@@ -443,7 +461,7 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E) {
// Emit the expression as an lvalue.
LValue LV = EmitLValue(E);
assert(LV.isSimple());
- llvm::Value *Value = LV.getAddress();
+ llvm::Value *Value = LV.getPointer();
if (sanitizePerformTypeCheck() && !E->getType()->isFunctionType()) {
// C++11 [dcl.ref]p5 (as amended by core issue 453):
@@ -487,7 +505,7 @@ bool CodeGenFunction::sanitizePerformTypeCheck() const {
}
void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
- llvm::Value *Address, QualType Ty,
+ llvm::Value *Ptr, QualType Ty,
CharUnits Alignment, bool SkipNullCheck) {
if (!sanitizePerformTypeCheck())
return;
@@ -495,7 +513,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// Don't check pointers outside the default address space. The null check
// isn't correct, the object-size check isn't supported by LLVM, and we can't
// communicate the addresses to the runtime handler for the vptr check.
- if (Address->getType()->getPointerAddressSpace())
+ if (Ptr->getType()->getPointerAddressSpace())
return;
SanitizerScope SanScope(this);
@@ -508,8 +526,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
if ((SanOpts.has(SanitizerKind::Null) || AllowNullPointers) &&
!SkipNullCheck) {
// The glvalue must not be an empty glvalue.
- llvm::Value *IsNonNull = Builder.CreateICmpNE(
- Address, llvm::Constant::getNullValue(Address->getType()));
+ llvm::Value *IsNonNull = Builder.CreateIsNotNull(Ptr);
if (AllowNullPointers) {
// When performing pointer casts, it's OK if the value is null.
@@ -533,7 +550,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::Type *Tys[2] = { IntPtrTy, Int8PtrTy };
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, Tys);
llvm::Value *Min = Builder.getFalse();
- llvm::Value *CastAddr = Builder.CreateBitCast(Address, Int8PtrTy);
+ llvm::Value *CastAddr = Builder.CreateBitCast(Ptr, Int8PtrTy);
llvm::Value *LargeEnough =
Builder.CreateICmpUGE(Builder.CreateCall(F, {CastAddr, Min}),
llvm::ConstantInt::get(IntPtrTy, Size));
@@ -550,7 +567,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// The glvalue must be suitably aligned.
if (AlignVal) {
llvm::Value *Align =
- Builder.CreateAnd(Builder.CreatePtrToInt(Address, IntPtrTy),
+ Builder.CreateAnd(Builder.CreatePtrToInt(Ptr, IntPtrTy),
llvm::ConstantInt::get(IntPtrTy, AlignVal - 1));
llvm::Value *Aligned =
Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0));
@@ -565,7 +582,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::ConstantInt::get(SizeTy, AlignVal),
llvm::ConstantInt::get(Int8Ty, TCK)
};
- EmitCheck(Checks, "type_mismatch", StaticData, Address);
+ EmitCheck(Checks, "type_mismatch", StaticData, Ptr);
}
// If possible, check that the vptr indicates that there is a subobject of
@@ -600,7 +617,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// Load the vptr, and compute hash_16_bytes(TypeHash, vptr).
llvm::Value *Low = llvm::ConstantInt::get(Int64Ty, TypeHash);
llvm::Type *VPtrTy = llvm::PointerType::get(IntPtrTy, 0);
- llvm::Value *VPtrAddr = Builder.CreateBitCast(Address, VPtrTy);
+ Address VPtrAddr(Builder.CreateBitCast(Ptr, VPtrTy), getPointerAlign());
llvm::Value *VPtrVal = Builder.CreateLoad(VPtrAddr);
llvm::Value *High = Builder.CreateZExt(VPtrVal, Int64Ty);
@@ -617,7 +634,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
CacheSize-1));
llvm::Value *Indices[] = { Builder.getInt32(0), Slot };
llvm::Value *CacheVal =
- Builder.CreateLoad(Builder.CreateInBoundsGEP(Cache, Indices));
+ Builder.CreateAlignedLoad(Builder.CreateInBoundsGEP(Cache, Indices),
+ getPointerAlign());
// If the hash isn't in the cache, call a runtime handler to perform the
// hard work of checking whether the vptr is for an object of the right
@@ -630,7 +648,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
CGM.GetAddrOfRTTIDescriptor(Ty.getUnqualifiedType()),
llvm::ConstantInt::get(Int8Ty, TCK)
};
- llvm::Value *DynamicData[] = { Address, Hash };
+ llvm::Value *DynamicData[] = { Ptr, Hash };
EmitCheck(std::make_pair(EqualHash, SanitizerKind::Vptr),
"dynamic_type_cache_miss", StaticData, DynamicData);
}
@@ -758,10 +776,104 @@ EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
return isPre ? IncVal : InVal;
}
+void CodeGenModule::EmitExplicitCastExprType(const ExplicitCastExpr *E,
+ CodeGenFunction *CGF) {
+ // Bind VLAs in the cast type.
+ if (CGF && E->getType()->isVariablyModifiedType())
+ CGF->EmitVariablyModifiedType(E->getType());
+
+ if (CGDebugInfo *DI = getModuleDebugInfo())
+ DI->EmitExplicitCastType(E->getType());
+}
+
//===----------------------------------------------------------------------===//
// LValue Expression Emission
//===----------------------------------------------------------------------===//
+/// EmitPointerWithAlignment - Given an expression of pointer type, try to
+/// derive a more accurate bound on the alignment of the pointer.
+Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
+ AlignmentSource *Source) {
+ // We allow this with ObjC object pointers because of fragile ABIs.
+ assert(E->getType()->isPointerType() ||
+ E->getType()->isObjCObjectPointerType());
+ E = E->IgnoreParens();
+
+ // Casts:
+ if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
+ if (const auto *ECE = dyn_cast<ExplicitCastExpr>(CE))
+ CGM.EmitExplicitCastExprType(ECE, this);
+
+ switch (CE->getCastKind()) {
+ // Non-converting casts (but not C's implicit conversion from void*).
+ case CK_BitCast:
+ case CK_NoOp:
+ if (auto PtrTy = CE->getSubExpr()->getType()->getAs<PointerType>()) {
+ if (PtrTy->getPointeeType()->isVoidType())
+ break;
+
+ AlignmentSource InnerSource;
+ Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), &InnerSource);
+ if (Source) *Source = InnerSource;
+
+ // If this is an explicit bitcast, and the source l-value is
+ // opaque, honor the alignment of the casted-to type.
+ if (isa<ExplicitCastExpr>(CE) &&
+ InnerSource != AlignmentSource::Decl) {
+ Addr = Address(Addr.getPointer(),
+ getNaturalPointeeTypeAlignment(E->getType(), Source));
+ }
+
+ if (SanOpts.has(SanitizerKind::CFIUnrelatedCast)) {
+ if (auto PT = E->getType()->getAs<PointerType>())
+ EmitVTablePtrCheckForCast(PT->getPointeeType(), Addr.getPointer(),
+ /*MayBeNull=*/true,
+ CodeGenFunction::CFITCK_UnrelatedCast,
+ CE->getLocStart());
+ }
+
+ return Builder.CreateBitCast(Addr, ConvertType(E->getType()));
+ }
+ break;
+
+ // Array-to-pointer decay.
+ case CK_ArrayToPointerDecay:
+ return EmitArrayToPointerDecay(CE->getSubExpr(), Source);
+
+ // Derived-to-base conversions.
+ case CK_UncheckedDerivedToBase:
+ case CK_DerivedToBase: {
+ Address Addr = EmitPointerWithAlignment(CE->getSubExpr(), Source);
+ auto Derived = CE->getSubExpr()->getType()->getPointeeCXXRecordDecl();
+ return GetAddressOfBaseClass(Addr, Derived,
+ CE->path_begin(), CE->path_end(),
+ ShouldNullCheckClassCastValue(CE),
+ CE->getExprLoc());
+ }
+
+ // TODO: Is there any reason to treat base-to-derived conversions
+ // specially?
+ default:
+ break;
+ }
+ }
+
+ // Unary &.
+ if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+ if (UO->getOpcode() == UO_AddrOf) {
+ LValue LV = EmitLValue(UO->getSubExpr());
+ if (Source) *Source = LV.getAlignmentSource();
+ return LV.getAddress();
+ }
+ }
+
+ // TODO: conditional operators, comma.
+
+ // Otherwise, use the alignment of the type.
+ CharUnits Align = getNaturalPointeeTypeAlignment(E->getType(), Source);
+ return Address(EmitScalarExpr(E), Align);
+}
+
RValue CodeGenFunction::GetUndefRValue(QualType Ty) {
if (Ty->isVoidType())
return RValue::get(nullptr);
@@ -778,7 +890,7 @@ RValue CodeGenFunction::GetUndefRValue(QualType Ty) {
// identifiable address. Just because the contents of the value are undefined
// doesn't mean that the address can't be taken and compared.
case TEK_Aggregate: {
- llvm::Value *DestPtr = CreateMemTemp(Ty, "undef.agg.tmp");
+ Address DestPtr = CreateMemTemp(Ty, "undef.agg.tmp");
return RValue::getAggregate(DestPtr);
}
@@ -798,7 +910,8 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
const char *Name) {
ErrorUnsupported(E, Name);
llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType()));
- return MakeAddrLValue(llvm::UndefValue::get(Ty), E->getType());
+ return MakeAddrLValue(Address(llvm::UndefValue::get(Ty), CharUnits::One()),
+ E->getType());
}
LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) {
@@ -808,7 +921,7 @@ LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) {
else
LV = EmitLValue(E);
if (!isa<DeclRefExpr>(E) && !LV.isBitField() && LV.isSimple())
- EmitTypeCheck(TCK, E->getExprLoc(), LV.getAddress(),
+ EmitTypeCheck(TCK, E->getExprLoc(), LV.getPointer(),
E->getType(), LV.getAlignment());
return LV;
}
@@ -909,6 +1022,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
return EmitUnaryOpLValue(cast<UnaryOperator>(E));
case Expr::ArraySubscriptExprClass:
return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E));
+ case Expr::OMPArraySectionExprClass:
+ return EmitOMPArraySectionExpr(cast<OMPArraySectionExpr>(E));
case Expr::ExtVectorElementExprClass:
return EmitExtVectorElementExpr(cast<ExtVectorElementExpr>(E));
case Expr::MemberExprClass:
@@ -1055,9 +1170,10 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue,
SourceLocation Loc) {
return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(),
- lvalue.getAlignment().getQuantity(),
- lvalue.getType(), Loc, lvalue.getTBAAInfo(),
- lvalue.getTBAABaseType(), lvalue.getTBAAOffset());
+ lvalue.getType(), Loc, lvalue.getAlignmentSource(),
+ lvalue.getTBAAInfo(),
+ lvalue.getTBAABaseType(), lvalue.getTBAAOffset(),
+ lvalue.isNontemporal());
}
static bool hasBooleanRepresentation(QualType Ty) {
@@ -1117,68 +1233,56 @@ llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) {
return MDHelper.createRange(Min, End);
}
-llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
- unsigned Alignment, QualType Ty,
+llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
+ QualType Ty,
SourceLocation Loc,
+ AlignmentSource AlignSource,
llvm::MDNode *TBAAInfo,
QualType TBAABaseType,
- uint64_t TBAAOffset) {
+ uint64_t TBAAOffset,
+ bool isNontemporal) {
// For better performance, handle vector loads differently.
if (Ty->isVectorType()) {
- llvm::Value *V;
- const llvm::Type *EltTy =
- cast<llvm::PointerType>(Addr->getType())->getElementType();
+ const llvm::Type *EltTy = Addr.getElementType();
const auto *VTy = cast<llvm::VectorType>(EltTy);
- // Handle vectors of size 3, like size 4 for better performance.
+ // Handle vectors of size 3 like size 4 for better performance.
if (VTy->getNumElements() == 3) {
// Bitcast to vec4 type.
llvm::VectorType *vec4Ty = llvm::VectorType::get(VTy->getElementType(),
4);
- llvm::PointerType *ptVec4Ty =
- llvm::PointerType::get(vec4Ty,
- (cast<llvm::PointerType>(
- Addr->getType()))->getAddressSpace());
- llvm::Value *Cast = Builder.CreateBitCast(Addr, ptVec4Ty,
- "castToVec4");
+ Address Cast = Builder.CreateElementBitCast(Addr, vec4Ty, "castToVec4");
// Now load value.
- llvm::Value *LoadVal = Builder.CreateLoad(Cast, Volatile, "loadVec4");
+ llvm::Value *V = Builder.CreateLoad(Cast, Volatile, "loadVec4");
// Shuffle vector to get vec3.
- llvm::Constant *Mask[] = {
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 0),
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 1),
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 2)
- };
-
- llvm::Value *MaskV = llvm::ConstantVector::get(Mask);
- V = Builder.CreateShuffleVector(LoadVal,
- llvm::UndefValue::get(vec4Ty),
- MaskV, "extractVec");
+ V = Builder.CreateShuffleVector(V, llvm::UndefValue::get(vec4Ty),
+ {0, 1, 2}, "extractVec");
return EmitFromMemory(V, Ty);
}
}
// Atomic operations have to be done on integral types.
if (Ty->isAtomicType() || typeIsSuitableForInlineAtomic(Ty, Volatile)) {
- LValue lvalue = LValue::MakeAddr(Addr, Ty,
- CharUnits::fromQuantity(Alignment),
- getContext(), TBAAInfo);
+ LValue lvalue =
+ LValue::MakeAddr(Addr, Ty, getContext(), AlignSource, TBAAInfo);
return EmitAtomicLoad(lvalue, Loc).getScalarVal();
}
- llvm::LoadInst *Load = Builder.CreateLoad(Addr);
- if (Volatile)
- Load->setVolatile(true);
- if (Alignment)
- Load->setAlignment(Alignment);
+ llvm::LoadInst *Load = Builder.CreateLoad(Addr, Volatile);
+ if (isNontemporal) {
+ llvm::MDNode *Node = llvm::MDNode::get(
+ Load->getContext(), llvm::ConstantAsMetadata::get(Builder.getInt32(1)));
+ Load->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
+ }
if (TBAAInfo) {
llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,
TBAAOffset);
if (TBAAPath)
- CGM.DecorateInstruction(Load, TBAAPath, false/*ConvertTypeToTag*/);
+ CGM.DecorateInstructionWithTBAA(Load, TBAAPath,
+ false /*ConvertTypeToTag*/);
}
bool NeedsBoolCheck =
@@ -1241,11 +1345,13 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
return Value;
}
-void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
- bool Volatile, unsigned Alignment,
- QualType Ty, llvm::MDNode *TBAAInfo,
+void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
+ bool Volatile, QualType Ty,
+ AlignmentSource AlignSource,
+ llvm::MDNode *TBAAInfo,
bool isInit, QualType TBAABaseType,
- uint64_t TBAAOffset) {
+ uint64_t TBAAOffset,
+ bool isNontemporal) {
// Handle vectors differently to get better performance.
if (Ty->isVectorType()) {
@@ -1253,29 +1359,18 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
auto *VecTy = cast<llvm::VectorType>(SrcTy);
// Handle vec3 special.
if (VecTy->getNumElements() == 3) {
- llvm::LLVMContext &VMContext = getLLVMContext();
-
// Our source is a vec3, do a shuffle vector to make it a vec4.
- SmallVector<llvm::Constant*, 4> Mask;
- Mask.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
- 0));
- Mask.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
- 1));
- Mask.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
- 2));
- Mask.push_back(llvm::UndefValue::get(llvm::Type::getInt32Ty(VMContext)));
-
+ llvm::Constant *Mask[] = {Builder.getInt32(0), Builder.getInt32(1),
+ Builder.getInt32(2),
+ llvm::UndefValue::get(Builder.getInt32Ty())};
llvm::Value *MaskV = llvm::ConstantVector::get(Mask);
Value = Builder.CreateShuffleVector(Value,
llvm::UndefValue::get(VecTy),
MaskV, "extractVec");
SrcTy = llvm::VectorType::get(VecTy->getElementType(), 4);
}
- auto *DstPtr = cast<llvm::PointerType>(Addr->getType());
- if (DstPtr->getElementType() != SrcTy) {
- llvm::Type *MemTy =
- llvm::PointerType::get(SrcTy, DstPtr->getAddressSpace());
- Addr = Builder.CreateBitCast(Addr, MemTy, "storetmp");
+ if (Addr.getElementType() != SrcTy) {
+ Addr = Builder.CreateElementBitCast(Addr, SrcTy, "storetmp");
}
}
@@ -1284,30 +1379,34 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
if (Ty->isAtomicType() ||
(!isInit && typeIsSuitableForInlineAtomic(Ty, Volatile))) {
EmitAtomicStore(RValue::get(Value),
- LValue::MakeAddr(Addr, Ty,
- CharUnits::fromQuantity(Alignment),
- getContext(), TBAAInfo),
+ LValue::MakeAddr(Addr, Ty, getContext(),
+ AlignSource, TBAAInfo),
isInit);
return;
}
llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile);
- if (Alignment)
- Store->setAlignment(Alignment);
+ if (isNontemporal) {
+ llvm::MDNode *Node =
+ llvm::MDNode::get(Store->getContext(),
+ llvm::ConstantAsMetadata::get(Builder.getInt32(1)));
+ Store->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
+ }
if (TBAAInfo) {
llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo,
TBAAOffset);
if (TBAAPath)
- CGM.DecorateInstruction(Store, TBAAPath, false/*ConvertTypeToTag*/);
+ CGM.DecorateInstructionWithTBAA(Store, TBAAPath,
+ false /*ConvertTypeToTag*/);
}
}
void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue,
bool isInit) {
EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(),
- lvalue.getAlignment().getQuantity(), lvalue.getType(),
+ lvalue.getType(), lvalue.getAlignmentSource(),
lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(),
- lvalue.getTBAAOffset());
+ lvalue.getTBAAOffset(), lvalue.isNontemporal());
}
/// EmitLoadOfLValue - Given an expression that represents a value lvalue, this
@@ -1316,11 +1415,17 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue,
RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
if (LV.isObjCWeak()) {
// load of a __weak object.
- llvm::Value *AddrWeakObj = LV.getAddress();
+ Address AddrWeakObj = LV.getAddress();
return RValue::get(CGM.getObjCRuntime().EmitObjCWeakRead(*this,
AddrWeakObj));
}
if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) {
+ // In MRC mode, we do a load+autorelease.
+ if (!getLangOpts().ObjCAutoRefCount) {
+ return RValue::get(EmitARCLoadWeak(LV.getAddress()));
+ }
+
+ // In ARC mode, we load retained and then consume the value.
llvm::Value *Object = EmitARCLoadWeakRetained(LV.getAddress());
Object = EmitObjCConsumeObject(LV.getType(), Object);
return RValue::get(Object);
@@ -1334,9 +1439,8 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
}
if (LV.isVectorElt()) {
- llvm::LoadInst *Load = Builder.CreateLoad(LV.getVectorAddr(),
+ llvm::LoadInst *Load = Builder.CreateLoad(LV.getVectorAddress(),
LV.isVolatileQualified());
- Load->setAlignment(LV.getAlignment().getQuantity());
return RValue::get(Builder.CreateExtractElement(Load, LV.getVectorIdx(),
"vecext"));
}
@@ -1356,15 +1460,12 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV) {
const CGBitFieldInfo &Info = LV.getBitFieldInfo();
- CharUnits Align = LV.getAlignment().alignmentAtOffset(Info.StorageOffset);
// Get the output type.
llvm::Type *ResLTy = ConvertType(LV.getType());
- llvm::Value *Ptr = LV.getBitFieldAddr();
- llvm::Value *Val = Builder.CreateAlignedLoad(Ptr, Align.getQuantity(),
- LV.isVolatileQualified(),
- "bf.load");
+ Address Ptr = LV.getBitFieldAddress();
+ llvm::Value *Val = Builder.CreateLoad(Ptr, LV.isVolatileQualified(), "bf.load");
if (Info.IsSigned) {
assert(static_cast<unsigned>(Info.Offset + Info.Size) <= Info.StorageSize);
@@ -1389,10 +1490,8 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV) {
// If this is a reference to a subset of the elements of a vector, create an
// appropriate shufflevector.
RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV) {
- llvm::LoadInst *Load = Builder.CreateLoad(LV.getExtVectorAddr(),
- LV.isVolatileQualified());
- Load->setAlignment(LV.getAlignment().getQuantity());
- llvm::Value *Vec = Load;
+ llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddress(),
+ LV.isVolatileQualified());
const llvm::Constant *Elts = LV.getExtVectorElts();
@@ -1419,24 +1518,24 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV) {
}
/// @brief Generates lvalue for partial ext_vector access.
-llvm::Value *CodeGenFunction::EmitExtVectorElementLValue(LValue LV) {
- llvm::Value *VectorAddress = LV.getExtVectorAddr();
+Address CodeGenFunction::EmitExtVectorElementLValue(LValue LV) {
+ Address VectorAddress = LV.getExtVectorAddress();
const VectorType *ExprVT = LV.getType()->getAs<VectorType>();
QualType EQT = ExprVT->getElementType();
llvm::Type *VectorElementTy = CGM.getTypes().ConvertType(EQT);
- llvm::Type *VectorElementPtrToTy = VectorElementTy->getPointerTo();
- llvm::Value *CastToPointerElement =
- Builder.CreateBitCast(VectorAddress,
- VectorElementPtrToTy, "conv.ptr.element");
+ Address CastToPointerElement =
+ Builder.CreateElementBitCast(VectorAddress, VectorElementTy,
+ "conv.ptr.element");
const llvm::Constant *Elts = LV.getExtVectorElts();
unsigned ix = getAccessedFieldNo(0, Elts);
- llvm::Value *VectorBasePtrPlusIx =
- Builder.CreateInBoundsGEP(CastToPointerElement,
- llvm::ConstantInt::get(SizeTy, ix), "add.ptr");
-
+ Address VectorBasePtrPlusIx =
+ Builder.CreateConstInBoundsGEP(CastToPointerElement, ix,
+ getContext().getTypeSizeInChars(EQT),
+ "vector.elt");
+
return VectorBasePtrPlusIx;
}
@@ -1471,15 +1570,12 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
if (!Dst.isSimple()) {
if (Dst.isVectorElt()) {
// Read/modify/write the vector, inserting the new element.
- llvm::LoadInst *Load = Builder.CreateLoad(Dst.getVectorAddr(),
- Dst.isVolatileQualified());
- Load->setAlignment(Dst.getAlignment().getQuantity());
- llvm::Value *Vec = Load;
+ llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddress(),
+ Dst.isVolatileQualified());
Vec = Builder.CreateInsertElement(Vec, Src.getScalarVal(),
Dst.getVectorIdx(), "vecins");
- llvm::StoreInst *Store = Builder.CreateStore(Vec, Dst.getVectorAddr(),
- Dst.isVolatileQualified());
- Store->setAlignment(Dst.getAlignment().getQuantity());
+ Builder.CreateStore(Vec, Dst.getVectorAddress(),
+ Dst.isVolatileQualified());
return;
}
@@ -1523,7 +1619,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
if (Dst.isObjCWeak() && !Dst.isNonGC()) {
// load of a __weak object.
- llvm::Value *LvalueDst = Dst.getAddress();
+ Address LvalueDst = Dst.getAddress();
llvm::Value *src = Src.getScalarVal();
CGM.getObjCRuntime().EmitObjCWeakAssign(*this, src, LvalueDst);
return;
@@ -1531,16 +1627,17 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
if (Dst.isObjCStrong() && !Dst.isNonGC()) {
// load of a __strong object.
- llvm::Value *LvalueDst = Dst.getAddress();
+ Address LvalueDst = Dst.getAddress();
llvm::Value *src = Src.getScalarVal();
if (Dst.isObjCIvar()) {
assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL");
- llvm::Type *ResultType = ConvertType(getContext().LongTy);
- llvm::Value *RHS = EmitScalarExpr(Dst.getBaseIvarExp());
- llvm::Value *dst = RHS;
+ llvm::Type *ResultType = IntPtrTy;
+ Address dst = EmitPointerWithAlignment(Dst.getBaseIvarExp());
+ llvm::Value *RHS = dst.getPointer();
RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast");
llvm::Value *LHS =
- Builder.CreatePtrToInt(LvalueDst, ResultType, "sub.ptr.lhs.cast");
+ Builder.CreatePtrToInt(LvalueDst.getPointer(), ResultType,
+ "sub.ptr.lhs.cast");
llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset");
CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst,
BytesBetween);
@@ -1560,16 +1657,14 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
llvm::Value **Result) {
const CGBitFieldInfo &Info = Dst.getBitFieldInfo();
- CharUnits Align = Dst.getAlignment().alignmentAtOffset(Info.StorageOffset);
llvm::Type *ResLTy = ConvertTypeForMem(Dst.getType());
- llvm::Value *Ptr = Dst.getBitFieldAddr();
+ Address Ptr = Dst.getBitFieldAddress();
// Get the source value, truncated to the width of the bit-field.
llvm::Value *SrcVal = Src.getScalarVal();
// Cast the source to the storage type and shift it into place.
- SrcVal = Builder.CreateIntCast(SrcVal,
- Ptr->getType()->getPointerElementType(),
+ SrcVal = Builder.CreateIntCast(SrcVal, Ptr.getElementType(),
/*IsSigned=*/false);
llvm::Value *MaskedVal = SrcVal;
@@ -1577,9 +1672,8 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
// and mask together with source before storing.
if (Info.StorageSize != Info.Size) {
assert(Info.StorageSize > Info.Size && "Invalid bitfield size.");
- llvm::Value *Val = Builder.CreateAlignedLoad(Ptr, Align.getQuantity(),
- Dst.isVolatileQualified(),
- "bf.load");
+ llvm::Value *Val =
+ Builder.CreateLoad(Ptr, Dst.isVolatileQualified(), "bf.load");
// Mask the source value as needed.
if (!hasBooleanRepresentation(Dst.getType()))
@@ -1605,8 +1699,7 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
}
// Write the new value back out.
- Builder.CreateAlignedStore(SrcVal, Ptr, Align.getQuantity(),
- Dst.isVolatileQualified());
+ Builder.CreateStore(SrcVal, Ptr, Dst.isVolatileQualified());
// Return the new value of the bit-field, if requested.
if (Result) {
@@ -1632,10 +1725,8 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
LValue Dst) {
// This access turns into a read/modify/write of the vector. Load the input
// value now.
- llvm::LoadInst *Load = Builder.CreateLoad(Dst.getExtVectorAddr(),
- Dst.isVolatileQualified());
- Load->setAlignment(Dst.getAlignment().getQuantity());
- llvm::Value *Vec = Load;
+ llvm::Value *Vec = Builder.CreateLoad(Dst.getExtVectorAddress(),
+ Dst.isVolatileQualified());
const llvm::Constant *Elts = Dst.getExtVectorElts();
llvm::Value *SrcVal = Src.getScalarVal();
@@ -1697,9 +1788,8 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt);
}
- llvm::StoreInst *Store = Builder.CreateStore(Vec, Dst.getExtVectorAddr(),
- Dst.isVolatileQualified());
- Store->setAlignment(Dst.getAlignment().getQuantity());
+ Builder.CreateStore(Vec, Dst.getExtVectorAddress(),
+ Dst.isVolatileQualified());
}
/// @brief Store of global named registers are always calls to intrinsics.
@@ -1834,11 +1924,27 @@ EmitBitCastOfLValueToProperType(CodeGenFunction &CGF,
}
static LValue EmitThreadPrivateVarDeclLValue(
- CodeGenFunction &CGF, const VarDecl *VD, QualType T, llvm::Value *V,
- llvm::Type *RealVarTy, CharUnits Alignment, SourceLocation Loc) {
- V = CGF.CGM.getOpenMPRuntime().getAddrOfThreadPrivate(CGF, VD, V, Loc);
- V = EmitBitCastOfLValueToProperType(CGF, V, RealVarTy);
- return CGF.MakeAddrLValue(V, T, Alignment);
+ CodeGenFunction &CGF, const VarDecl *VD, QualType T, Address Addr,
+ llvm::Type *RealVarTy, SourceLocation Loc) {
+ Addr = CGF.CGM.getOpenMPRuntime().getAddrOfThreadPrivate(CGF, VD, Addr, Loc);
+ Addr = CGF.Builder.CreateElementBitCast(Addr, RealVarTy);
+ return CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
+}
+
+Address CodeGenFunction::EmitLoadOfReference(Address Addr,
+ const ReferenceType *RefTy,
+ AlignmentSource *Source) {
+ llvm::Value *Ptr = Builder.CreateLoad(Addr);
+ return Address(Ptr, getNaturalTypeAlignment(RefTy->getPointeeType(),
+ Source, /*forPointee*/ true));
+
+}
+
+LValue CodeGenFunction::EmitLoadOfReferenceLValue(Address RefAddr,
+ const ReferenceType *RefTy) {
+ AlignmentSource Source;
+ Address Addr = EmitLoadOfReference(RefAddr, RefTy, &Source);
+ return MakeAddrLValue(Addr, RefTy->getPointeeType(), Source);
}
static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
@@ -1854,19 +1960,17 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
llvm::Type *RealVarTy = CGF.getTypes().ConvertTypeForMem(VD->getType());
V = EmitBitCastOfLValueToProperType(CGF, V, RealVarTy);
CharUnits Alignment = CGF.getContext().getDeclAlign(VD);
+ Address Addr(V, Alignment);
LValue LV;
// Emit reference to the private copy of the variable if it is an OpenMP
// threadprivate variable.
if (CGF.getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>())
- return EmitThreadPrivateVarDeclLValue(CGF, VD, T, V, RealVarTy, Alignment,
+ return EmitThreadPrivateVarDeclLValue(CGF, VD, T, Addr, RealVarTy,
E->getExprLoc());
- if (VD->getType()->isReferenceType()) {
- llvm::LoadInst *LI = CGF.Builder.CreateLoad(V);
- LI->setAlignment(Alignment.getQuantity());
- V = LI;
- LV = CGF.MakeNaturalAlignAddrLValue(V, T);
+ if (auto RefTy = VD->getType()->getAs<ReferenceType>()) {
+ LV = CGF.EmitLoadOfReferenceLValue(Addr, RefTy);
} else {
- LV = CGF.MakeAddrLValue(V, T, Alignment);
+ LV = CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
}
setObjCGCLValueClass(CGF.getContext(), E, LV);
return LV;
@@ -1888,7 +1992,7 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
}
}
CharUnits Alignment = CGF.getContext().getDeclAlign(FD);
- return CGF.MakeAddrLValue(V, E->getType(), Alignment);
+ return CGF.MakeAddrLValue(V, E->getType(), Alignment, AlignmentSource::Decl);
}
static LValue EmitCapturedFieldLValue(CodeGenFunction &CGF, const FieldDecl *FD,
@@ -1904,9 +2008,7 @@ static LValue EmitCapturedFieldLValue(CodeGenFunction &CGF, const FieldDecl *FD,
/// So far, only the name is being passed down, but other options such as
/// register type, allocation type or even optimization options could be
/// passed down via the metadata node.
-static LValue EmitGlobalNamedRegister(const VarDecl *VD,
- CodeGenModule &CGM,
- CharUnits Alignment) {
+static LValue EmitGlobalNamedRegister(const VarDecl *VD, CodeGenModule &CGM) {
SmallString<64> Name("llvm.named.register.");
AsmLabelAttr *Asm = VD->getAttr<AsmLabelAttr>();
assert(Asm->getLabel().size() < 64-Name.size() &&
@@ -1920,33 +2022,43 @@ static LValue EmitGlobalNamedRegister(const VarDecl *VD,
llvm::Metadata *Ops[] = {Str};
M->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops));
}
- return LValue::MakeGlobalReg(
- llvm::MetadataAsValue::get(CGM.getLLVMContext(), M->getOperand(0)),
- VD->getType(), Alignment);
+
+ CharUnits Alignment = CGM.getContext().getDeclAlign(VD);
+
+ llvm::Value *Ptr =
+ llvm::MetadataAsValue::get(CGM.getLLVMContext(), M->getOperand(0));
+ return LValue::MakeGlobalReg(Address(Ptr, Alignment), VD->getType());
}
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
const NamedDecl *ND = E->getDecl();
- CharUnits Alignment = getContext().getDeclAlign(ND);
QualType T = E->getType();
if (const auto *VD = dyn_cast<VarDecl>(ND)) {
// Global Named registers access via intrinsics only
if (VD->getStorageClass() == SC_Register &&
VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())
- return EmitGlobalNamedRegister(VD, CGM, Alignment);
+ return EmitGlobalNamedRegister(VD, CGM);
// A DeclRefExpr for a reference initialized by a constant expression can
// appear without being odr-used. Directly emit the constant initializer.
const Expr *Init = VD->getAnyInitializer(VD);
if (Init && !isa<ParmVarDecl>(VD) && VD->getType()->isReferenceType() &&
VD->isUsableInConstantExpressions(getContext()) &&
- VD->checkInitIsICE()) {
+ VD->checkInitIsICE() &&
+ // Do not emit if it is private OpenMP variable.
+ !(E->refersToEnclosingVariableOrCapture() && CapturedStmtInfo &&
+ LocalDeclMap.count(VD))) {
llvm::Constant *Val =
CGM.EmitConstantValue(*VD->evaluateValue(), VD->getType(), this);
assert(Val && "failed to emit reference constant expression");
// FIXME: Eventually we will want to emit vector element references.
- return MakeAddrLValue(Val, T, Alignment);
+
+ // Should we be using the alignment of the constant pointer we emitted?
+ CharUnits Alignment = getNaturalTypeAlignment(E->getType(), nullptr,
+ /*pointee*/ true);
+
+ return MakeAddrLValue(Address(Val, Alignment), T, AlignmentSource::Decl);
}
// Check for captured variables.
@@ -1954,15 +2066,24 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (auto *FD = LambdaCaptureFields.lookup(VD))
return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue);
else if (CapturedStmtInfo) {
- if (auto *V = LocalDeclMap.lookup(VD))
- return MakeAddrLValue(V, T, Alignment);
- else
- return EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD),
- CapturedStmtInfo->getContextValue());
+ auto it = LocalDeclMap.find(VD);
+ if (it != LocalDeclMap.end()) {
+ if (auto RefTy = VD->getType()->getAs<ReferenceType>()) {
+ return EmitLoadOfReferenceLValue(it->second, RefTy);
+ }
+ return MakeAddrLValue(it->second, T);
+ }
+ LValue CapLVal =
+ EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD),
+ CapturedStmtInfo->getContextValue());
+ return MakeAddrLValue(
+ Address(CapLVal.getPointer(), getContext().getDeclAlign(VD)),
+ CapLVal.getType(), AlignmentSource::Decl);
}
+
assert(isa<BlockDecl>(CurCodeDecl));
- return MakeAddrLValue(GetAddrOfBlockDecl(VD, VD->hasAttr<BlocksAttr>()),
- T, Alignment);
+ Address addr = GetAddrOfBlockDecl(VD, VD->hasAttr<BlocksAttr>());
+ return MakeAddrLValue(addr, T, AlignmentSource::Decl);
}
}
@@ -1975,8 +2096,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (ND->hasAttr<WeakRefAttr>()) {
const auto *VD = cast<ValueDecl>(ND);
- llvm::Constant *Aliasee = CGM.GetWeakRefReference(VD);
- return MakeAddrLValue(Aliasee, T, Alignment);
+ ConstantAddress Aliasee = CGM.GetWeakRefReference(VD);
+ return MakeAddrLValue(Aliasee, T, AlignmentSource::Decl);
}
if (const auto *VD = dyn_cast<VarDecl>(ND)) {
@@ -1984,39 +2105,52 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (VD->hasLinkage() || VD->isStaticDataMember())
return EmitGlobalVarDeclLValue(*this, E, VD);
- bool isBlockVariable = VD->hasAttr<BlocksAttr>();
+ Address addr = Address::invalid();
- llvm::Value *V = LocalDeclMap.lookup(VD);
- if (!V && VD->isStaticLocal())
- V = CGM.getOrCreateStaticVarDecl(
- *VD, CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false));
+ // The variable should generally be present in the local decl map.
+ auto iter = LocalDeclMap.find(VD);
+ if (iter != LocalDeclMap.end()) {
+ addr = iter->second;
- // Check if variable is threadprivate.
- if (V && getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>())
- return EmitThreadPrivateVarDeclLValue(
- *this, VD, T, V, getTypes().ConvertTypeForMem(VD->getType()),
- Alignment, E->getExprLoc());
+ // Otherwise, it might be static local we haven't emitted yet for
+ // some reason; most likely, because it's in an outer function.
+ } else if (VD->isStaticLocal()) {
+ addr = Address(CGM.getOrCreateStaticVarDecl(
+ *VD, CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false)),
+ getContext().getDeclAlign(VD));
+
+ // No other cases for now.
+ } else {
+ llvm_unreachable("DeclRefExpr for Decl not entered in LocalDeclMap?");
+ }
- assert(V && "DeclRefExpr not entered in LocalDeclMap?");
- if (isBlockVariable)
- V = BuildBlockByrefAddress(V, VD);
+ // Check for OpenMP threadprivate variables.
+ if (getLangOpts().OpenMP && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
+ return EmitThreadPrivateVarDeclLValue(
+ *this, VD, T, addr, getTypes().ConvertTypeForMem(VD->getType()),
+ E->getExprLoc());
+ }
+ // Drill into block byref variables.
+ bool isBlockByref = VD->hasAttr<BlocksAttr>();
+ if (isBlockByref) {
+ addr = emitBlockByrefAddress(addr, VD);
+ }
+
+ // Drill into reference types.
LValue LV;
- if (VD->getType()->isReferenceType()) {
- llvm::LoadInst *LI = Builder.CreateLoad(V);
- LI->setAlignment(Alignment.getQuantity());
- V = LI;
- LV = MakeNaturalAlignAddrLValue(V, T);
+ if (auto RefTy = VD->getType()->getAs<ReferenceType>()) {
+ LV = EmitLoadOfReferenceLValue(addr, RefTy);
} else {
- LV = MakeAddrLValue(V, T, Alignment);
+ LV = MakeAddrLValue(addr, T, AlignmentSource::Decl);
}
bool isLocalStorage = VD->hasLocalStorage();
bool NonGCable = isLocalStorage &&
!VD->getType()->isReferenceType() &&
- !isBlockVariable;
+ !isBlockByref;
if (NonGCable) {
LV.getQuals().removeObjCGCAttr();
LV.setNonGC(true);
@@ -2048,7 +2182,9 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
QualType T = E->getSubExpr()->getType()->getPointeeType();
assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
- LValue LV = MakeNaturalAlignAddrLValue(EmitScalarExpr(E->getSubExpr()), T);
+ AlignmentSource AlignSource;
+ Address Addr = EmitPointerWithAlignment(E->getSubExpr(), &AlignSource);
+ LValue LV = MakeAddrLValue(Addr, T, AlignSource);
LV.getQuals().setAddressSpace(ExprTy.getAddressSpace());
// We should not generate __weak write barrier on indirect reference
@@ -2065,22 +2201,22 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
case UO_Imag: {
LValue LV = EmitLValue(E->getSubExpr());
assert(LV.isSimple() && "real/imag on non-ordinary l-value");
- llvm::Value *Addr = LV.getAddress();
// __real is valid on scalars. This is a faster way of testing that.
// __imag can only produce an rvalue on scalars.
if (E->getOpcode() == UO_Real &&
- !cast<llvm::PointerType>(Addr->getType())
- ->getElementType()->isStructTy()) {
+ !LV.getAddress().getElementType()->isStructTy()) {
assert(E->getSubExpr()->getType()->isArithmeticType());
return LV;
}
assert(E->getSubExpr()->getType()->isAnyComplexType());
- unsigned Idx = E->getOpcode() == UO_Imag;
- return MakeAddrLValue(
- Builder.CreateStructGEP(nullptr, LV.getAddress(), Idx, "idx"), ExprTy);
+ Address Component =
+ (E->getOpcode() == UO_Real
+ ? emitAddrOfRealComponent(LV.getAddress(), LV.getType())
+ : emitAddrOfImagComponent(LV.getAddress(), LV.getType()));
+ return MakeAddrLValue(Component, ExprTy, LV.getAlignmentSource());
}
case UO_PreInc:
case UO_PreDec: {
@@ -2098,12 +2234,12 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
return MakeAddrLValue(CGM.GetAddrOfConstantStringFromLiteral(E),
- E->getType());
+ E->getType(), AlignmentSource::Decl);
}
LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) {
return MakeAddrLValue(CGM.GetAddrOfConstantStringFromObjCEncode(E),
- E->getType());
+ E->getType(), AlignmentSource::Decl);
}
LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
@@ -2116,11 +2252,11 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
PredefinedExpr::getIdentTypeName(E->getIdentType()), FnName};
std::string GVName = llvm::join(NameItems, NameItems + 2, ".");
if (CurCodeDecl && isa<BlockDecl>(CurCodeDecl)) {
- auto C = CGM.GetAddrOfConstantCString(FnName, GVName.c_str(), 1);
- return MakeAddrLValue(C, E->getType());
+ auto C = CGM.GetAddrOfConstantCString(FnName, GVName.c_str());
+ return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
}
auto C = CGM.GetAddrOfConstantStringFromLiteral(SL, GVName);
- return MakeAddrLValue(C, E->getType());
+ return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
}
/// Emit a type description suitable for use by a runtime sanitizer library. The
@@ -2194,9 +2330,9 @@ llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) {
// Pointers are passed directly, everything else is passed by address.
if (!V->getType()->isPointerTy()) {
- llvm::Value *Ptr = CreateTempAlloca(V->getType());
+ Address Ptr = CreateDefaultAlignTempAlloca(V->getType());
Builder.CreateStore(V, Ptr);
- V = Ptr;
+ V = Ptr.getPointer();
}
return Builder.CreatePtrToInt(V, TargetTy);
}
@@ -2217,8 +2353,9 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) {
PresumedLoc PLoc = getContext().getSourceManager().getPresumedLoc(Loc);
if (PLoc.isValid()) {
auto FilenameGV = CGM.GetAddrOfConstantCString(PLoc.getFilename(), ".src");
- CGM.getSanitizerMetadata()->disableSanitizerForGlobal(FilenameGV);
- Filename = FilenameGV;
+ CGM.getSanitizerMetadata()->disableSanitizerForGlobal(
+ cast<llvm::GlobalVariable>(FilenameGV.getPointer()));
+ Filename = FilenameGV.getPointer();
Line = PLoc.getLine();
Column = PLoc.getColumn();
} else {
@@ -2395,6 +2532,34 @@ void CodeGenFunction::EmitCheck(
EmitBlock(Cont);
}
+void CodeGenFunction::EmitCfiSlowPathCheck(llvm::Value *Cond,
+ llvm::ConstantInt *TypeId,
+ llvm::Value *Ptr) {
+ auto &Ctx = getLLVMContext();
+ llvm::BasicBlock *Cont = createBasicBlock("cfi.cont");
+
+ llvm::BasicBlock *CheckBB = createBasicBlock("cfi.slowpath");
+ llvm::BranchInst *BI = Builder.CreateCondBr(Cond, Cont, CheckBB);
+
+ llvm::MDBuilder MDHelper(getLLVMContext());
+ llvm::MDNode *Node = MDHelper.createBranchWeights((1U << 20) - 1, 1);
+ BI->setMetadata(llvm::LLVMContext::MD_prof, Node);
+
+ EmitBlock(CheckBB);
+
+ llvm::Constant *SlowPathFn = CGM.getModule().getOrInsertFunction(
+ "__cfi_slowpath",
+ llvm::FunctionType::get(
+ llvm::Type::getVoidTy(Ctx),
+ {llvm::Type::getInt64Ty(Ctx),
+ llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(Ctx))},
+ false));
+ llvm::CallInst *CheckCall = Builder.CreateCall(SlowPathFn, {TypeId, Ptr});
+ CheckCall->setDoesNotThrow();
+
+ EmitBlock(Cont);
+}
+
void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
llvm::BasicBlock *Cont = createBasicBlock("cont");
@@ -2426,6 +2591,33 @@ llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
return TrapCall;
}
+Address CodeGenFunction::EmitArrayToPointerDecay(const Expr *E,
+ AlignmentSource *AlignSource) {
+ assert(E->getType()->isArrayType() &&
+ "Array to pointer decay must have array source type!");
+
+ // Expressions of array type can't be bitfields or vector elements.
+ LValue LV = EmitLValue(E);
+ Address Addr = LV.getAddress();
+ if (AlignSource) *AlignSource = LV.getAlignmentSource();
+
+ // If the array type was an incomplete type, we need to make sure
+ // the decay ends up being the right type.
+ llvm::Type *NewTy = ConvertType(E->getType());
+ Addr = Builder.CreateElementBitCast(Addr, NewTy);
+
+ // Note that VLA pointers are always decayed, so we don't need to do
+ // anything here.
+ if (!E->getType()->isVariableArrayType()) {
+ assert(isa<llvm::ArrayType>(Addr.getElementType()) &&
+ "Expected pointer to array");
+ Addr = Builder.CreateStructGEP(Addr, 0, CharUnits::Zero(), "arraydecay");
+ }
+
+ QualType EltType = E->getType()->castAsArrayTypeUnsafe()->getElementType();
+ return Builder.CreateElementBitCast(Addr, ConvertTypeForMem(EltType));
+}
+
/// isSimpleArrayDecayOperand - If the specified expr is a simple decay from an
/// array to pointer, return the array subexpression.
static const Expr *isSimpleArrayDecayOperand(const Expr *E) {
@@ -2442,6 +2634,69 @@ static const Expr *isSimpleArrayDecayOperand(const Expr *E) {
return SubExpr;
}
+static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF,
+ llvm::Value *ptr,
+ ArrayRef<llvm::Value*> indices,
+ bool inbounds,
+ const llvm::Twine &name = "arrayidx") {
+ if (inbounds) {
+ return CGF.Builder.CreateInBoundsGEP(ptr, indices, name);
+ } else {
+ return CGF.Builder.CreateGEP(ptr, indices, name);
+ }
+}
+
+static CharUnits getArrayElementAlign(CharUnits arrayAlign,
+ llvm::Value *idx,
+ CharUnits eltSize) {
+ // If we have a constant index, we can use the exact offset of the
+ // element we're accessing.
+ if (auto constantIdx = dyn_cast<llvm::ConstantInt>(idx)) {
+ CharUnits offset = constantIdx->getZExtValue() * eltSize;
+ return arrayAlign.alignmentAtOffset(offset);
+
+ // Otherwise, use the worst-case alignment for any element.
+ } else {
+ return arrayAlign.alignmentOfArrayElement(eltSize);
+ }
+}
+
+static QualType getFixedSizeElementType(const ASTContext &ctx,
+ const VariableArrayType *vla) {
+ QualType eltType;
+ do {
+ eltType = vla->getElementType();
+ } while ((vla = ctx.getAsVariableArrayType(eltType)));
+ return eltType;
+}
+
+static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr,
+ ArrayRef<llvm::Value*> indices,
+ QualType eltType, bool inbounds,
+ const llvm::Twine &name = "arrayidx") {
+ // All the indices except that last must be zero.
+#ifndef NDEBUG
+ for (auto idx : indices.drop_back())
+ assert(isa<llvm::ConstantInt>(idx) &&
+ cast<llvm::ConstantInt>(idx)->isZero());
+#endif
+
+ // Determine the element size of the statically-sized base. This is
+ // the thing that the indices are expressed in terms of.
+ if (auto vla = CGF.getContext().getAsVariableArrayType(eltType)) {
+ eltType = getFixedSizeElementType(CGF.getContext(), vla);
+ }
+
+ // We can use that to compute the best alignment of the element.
+ CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType);
+ CharUnits eltAlign =
+ getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize);
+
+ llvm::Value *eltPtr =
+ emitArraySubscriptGEP(CGF, addr.getPointer(), indices, inbounds, name);
+ return Address(eltPtr, eltAlign);
+}
+
LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
bool Accessed) {
// The index must always be an integer, which is not an aggregate. Emit it.
@@ -2460,32 +2715,34 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
LValue LHS = EmitLValue(E->getBase());
assert(LHS.isSimple() && "Can only subscript lvalue vectors here!");
return LValue::MakeVectorElt(LHS.getAddress(), Idx,
- E->getBase()->getType(), LHS.getAlignment());
+ E->getBase()->getType(),
+ LHS.getAlignmentSource());
}
+ // All the other cases basically behave like simple offsetting.
+
// Extend or truncate the index type to 32 or 64-bits.
if (Idx->getType() != IntPtrTy)
Idx = Builder.CreateIntCast(Idx, IntPtrTy, IdxSigned, "idxprom");
- // We know that the pointer points to a type of the correct size, unless the
- // size is a VLA or Objective-C interface.
- llvm::Value *Address = nullptr;
- CharUnits ArrayAlignment;
+ // Handle the extvector case we ignored above.
if (isa<ExtVectorElementExpr>(E->getBase())) {
LValue LV = EmitLValue(E->getBase());
- Address = EmitExtVectorElementLValue(LV);
- Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx");
- const VectorType *ExprVT = LV.getType()->getAs<VectorType>();
- QualType EQT = ExprVT->getElementType();
- return MakeAddrLValue(Address, EQT,
- getContext().getTypeAlignInChars(EQT));
- }
- else if (const VariableArrayType *vla =
+ Address Addr = EmitExtVectorElementLValue(LV);
+
+ QualType EltType = LV.getType()->castAs<VectorType>()->getElementType();
+ Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true);
+ return MakeAddrLValue(Addr, EltType, LV.getAlignmentSource());
+ }
+
+ AlignmentSource AlignSource;
+ Address Addr = Address::invalid();
+ if (const VariableArrayType *vla =
getContext().getAsVariableArrayType(E->getType())) {
// The base must be a pointer, which is not an aggregate. Emit
// it. It needs to be emitted first in case it's what captures
// the VLA bounds.
- Address = EmitScalarExpr(E->getBase());
+ Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource);
// The element count here is the total number of non-VLA elements.
llvm::Value *numElements = getVLASize(vla).first;
@@ -2496,24 +2753,40 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// multiply. We suppress this if overflow is not undefined behavior.
if (getLangOpts().isSignedOverflowDefined()) {
Idx = Builder.CreateMul(Idx, numElements);
- Address = Builder.CreateGEP(Address, Idx, "arrayidx");
} else {
Idx = Builder.CreateNSWMul(Idx, numElements);
- Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx");
}
- } else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){
- // Indexing over an interface, as in "NSString *P; P[4];"
- llvm::Value *InterfaceSize =
- llvm::ConstantInt::get(Idx->getType(),
- getContext().getTypeSizeInChars(OIT).getQuantity());
- Idx = Builder.CreateMul(Idx, InterfaceSize);
+ Addr = emitArraySubscriptGEP(*this, Addr, Idx, vla->getElementType(),
+ !getLangOpts().isSignedOverflowDefined());
- // The base must be a pointer, which is not an aggregate. Emit it.
- llvm::Value *Base = EmitScalarExpr(E->getBase());
- Address = EmitCastToVoidPtr(Base);
- Address = Builder.CreateGEP(Address, Idx, "arrayidx");
- Address = Builder.CreateBitCast(Address, Base->getType());
+ } else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){
+ // Indexing over an interface, as in "NSString *P; P[4];"
+ CharUnits InterfaceSize = getContext().getTypeSizeInChars(OIT);
+ llvm::Value *InterfaceSizeVal =
+ llvm::ConstantInt::get(Idx->getType(), InterfaceSize.getQuantity());;
+
+ llvm::Value *ScaledIdx = Builder.CreateMul(Idx, InterfaceSizeVal);
+
+ // Emit the base pointer.
+ Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource);
+
+ // We don't necessarily build correct LLVM struct types for ObjC
+ // interfaces, so we can't rely on GEP to do this scaling
+ // correctly, so we need to cast to i8*. FIXME: is this actually
+ // true? A lot of other things in the fragile ABI would break...
+ llvm::Type *OrigBaseTy = Addr.getType();
+ Addr = Builder.CreateElementBitCast(Addr, Int8Ty);
+
+ // Do the GEP.
+ CharUnits EltAlign =
+ getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize);
+ llvm::Value *EltPtr =
+ emitArraySubscriptGEP(*this, Addr.getPointer(), ScaledIdx, false);
+ Addr = Address(EltPtr, EltAlign);
+
+ // Cast back.
+ Addr = Builder.CreateBitCast(Addr, OrigBaseTy);
} else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) {
// If this is A[i] where A is an array, the frontend will have decayed the
// base to be a ArrayToPointerDecay implicit cast. While correct, it is
@@ -2528,42 +2801,23 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
ArrayLV = EmitArraySubscriptExpr(ASE, /*Accessed*/ true);
else
ArrayLV = EmitLValue(Array);
- llvm::Value *ArrayPtr = ArrayLV.getAddress();
- llvm::Value *Zero = llvm::ConstantInt::get(Int32Ty, 0);
- llvm::Value *Args[] = { Zero, Idx };
// Propagate the alignment from the array itself to the result.
- ArrayAlignment = ArrayLV.getAlignment();
-
- if (getLangOpts().isSignedOverflowDefined())
- Address = Builder.CreateGEP(ArrayPtr, Args, "arrayidx");
- else
- Address = Builder.CreateInBoundsGEP(ArrayPtr, Args, "arrayidx");
+ Addr = emitArraySubscriptGEP(*this, ArrayLV.getAddress(),
+ {CGM.getSize(CharUnits::Zero()), Idx},
+ E->getType(),
+ !getLangOpts().isSignedOverflowDefined());
+ AlignSource = ArrayLV.getAlignmentSource();
} else {
- // The base must be a pointer, which is not an aggregate. Emit it.
- llvm::Value *Base = EmitScalarExpr(E->getBase());
- if (getLangOpts().isSignedOverflowDefined())
- Address = Builder.CreateGEP(Base, Idx, "arrayidx");
- else
- Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx");
+ // The base must be a pointer; emit it with an estimate of its alignment.
+ Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource);
+ Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(),
+ !getLangOpts().isSignedOverflowDefined());
}
- QualType T = E->getBase()->getType()->getPointeeType();
- assert(!T.isNull() &&
- "CodeGenFunction::EmitArraySubscriptExpr(): Illegal base type");
-
+ LValue LV = MakeAddrLValue(Addr, E->getType(), AlignSource);
- // Limit the alignment to that of the result type.
- LValue LV;
- if (!ArrayAlignment.isZero()) {
- CharUnits Align = getContext().getTypeAlignInChars(T);
- ArrayAlignment = std::min(Align, ArrayAlignment);
- LV = MakeAddrLValue(Address, T, ArrayAlignment);
- } else {
- LV = MakeNaturalAlignAddrLValue(Address, T);
- }
-
- LV.getQuals().setAddressSpace(E->getBase()->getType().getAddressSpace());
+ // TODO: Preserve/extend path TBAA metadata?
if (getLangOpts().ObjC1 &&
getLangOpts().getGC() != LangOptions::NonGC) {
@@ -2573,14 +2827,150 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
return LV;
}
-static
-llvm::Constant *GenerateConstantVector(CGBuilderTy &Builder,
- SmallVectorImpl<unsigned> &Elts) {
- SmallVector<llvm::Constant*, 4> CElts;
- for (unsigned i = 0, e = Elts.size(); i != e; ++i)
- CElts.push_back(Builder.getInt32(Elts[i]));
+LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
+ bool IsLowerBound) {
+ LValue Base;
+ if (auto *ASE =
+ dyn_cast<OMPArraySectionExpr>(E->getBase()->IgnoreParenImpCasts()))
+ Base = EmitOMPArraySectionExpr(ASE, IsLowerBound);
+ else
+ Base = EmitLValue(E->getBase());
+ QualType BaseTy = Base.getType();
+ llvm::Value *Idx = nullptr;
+ QualType ResultExprTy;
+ if (auto *AT = getContext().getAsArrayType(BaseTy))
+ ResultExprTy = AT->getElementType();
+ else
+ ResultExprTy = BaseTy->getPointeeType();
+ if (IsLowerBound || (!IsLowerBound && E->getColonLoc().isInvalid())) {
+ // Requesting lower bound or upper bound, but without provided length and
+ // without ':' symbol for the default length -> length = 1.
+ // Idx = LowerBound ?: 0;
+ if (auto *LowerBound = E->getLowerBound()) {
+ Idx = Builder.CreateIntCast(
+ EmitScalarExpr(LowerBound), IntPtrTy,
+ LowerBound->getType()->hasSignedIntegerRepresentation());
+ } else
+ Idx = llvm::ConstantInt::getNullValue(IntPtrTy);
+ } else {
+ // Try to emit length or lower bound as constant. If this is possible, 1 is
+ // subtracted from constant length or lower bound. Otherwise, emit LLVM IR
+ // (LB + Len) - 1.
+ auto &C = CGM.getContext();
+ auto *Length = E->getLength();
+ llvm::APSInt ConstLength;
+ if (Length) {
+ // Idx = LowerBound + Length - 1;
+ if (Length->isIntegerConstantExpr(ConstLength, C)) {
+ ConstLength = ConstLength.zextOrTrunc(PointerWidthInBits);
+ Length = nullptr;
+ }
+ auto *LowerBound = E->getLowerBound();
+ llvm::APSInt ConstLowerBound(PointerWidthInBits, /*isUnsigned=*/false);
+ if (LowerBound && LowerBound->isIntegerConstantExpr(ConstLowerBound, C)) {
+ ConstLowerBound = ConstLowerBound.zextOrTrunc(PointerWidthInBits);
+ LowerBound = nullptr;
+ }
+ if (!Length)
+ --ConstLength;
+ else if (!LowerBound)
+ --ConstLowerBound;
+
+ if (Length || LowerBound) {
+ auto *LowerBoundVal =
+ LowerBound
+ ? Builder.CreateIntCast(
+ EmitScalarExpr(LowerBound), IntPtrTy,
+ LowerBound->getType()->hasSignedIntegerRepresentation())
+ : llvm::ConstantInt::get(IntPtrTy, ConstLowerBound);
+ auto *LengthVal =
+ Length
+ ? Builder.CreateIntCast(
+ EmitScalarExpr(Length), IntPtrTy,
+ Length->getType()->hasSignedIntegerRepresentation())
+ : llvm::ConstantInt::get(IntPtrTy, ConstLength);
+ Idx = Builder.CreateAdd(LowerBoundVal, LengthVal, "lb_add_len",
+ /*HasNUW=*/false,
+ !getLangOpts().isSignedOverflowDefined());
+ if (Length && LowerBound) {
+ Idx = Builder.CreateSub(
+ Idx, llvm::ConstantInt::get(IntPtrTy, /*V=*/1), "idx_sub_1",
+ /*HasNUW=*/false, !getLangOpts().isSignedOverflowDefined());
+ }
+ } else
+ Idx = llvm::ConstantInt::get(IntPtrTy, ConstLength + ConstLowerBound);
+ } else {
+ // Idx = ArraySize - 1;
+ if (auto *VAT = C.getAsVariableArrayType(BaseTy)) {
+ Length = VAT->getSizeExpr();
+ if (Length->isIntegerConstantExpr(ConstLength, C))
+ Length = nullptr;
+ } else {
+ auto *CAT = C.getAsConstantArrayType(BaseTy);
+ ConstLength = CAT->getSize();
+ }
+ if (Length) {
+ auto *LengthVal = Builder.CreateIntCast(
+ EmitScalarExpr(Length), IntPtrTy,
+ Length->getType()->hasSignedIntegerRepresentation());
+ Idx = Builder.CreateSub(
+ LengthVal, llvm::ConstantInt::get(IntPtrTy, /*V=*/1), "len_sub_1",
+ /*HasNUW=*/false, !getLangOpts().isSignedOverflowDefined());
+ } else {
+ ConstLength = ConstLength.zextOrTrunc(PointerWidthInBits);
+ --ConstLength;
+ Idx = llvm::ConstantInt::get(IntPtrTy, ConstLength);
+ }
+ }
+ }
+ assert(Idx);
- return llvm::ConstantVector::get(CElts);
+ llvm::Value *EltPtr;
+ QualType FixedSizeEltType = ResultExprTy;
+ if (auto *VLA = getContext().getAsVariableArrayType(ResultExprTy)) {
+ // The element count here is the total number of non-VLA elements.
+ llvm::Value *numElements = getVLASize(VLA).first;
+ FixedSizeEltType = getFixedSizeElementType(getContext(), VLA);
+
+ // Effectively, the multiply by the VLA size is part of the GEP.
+ // GEP indexes are signed, and scaling an index isn't permitted to
+ // signed-overflow, so we use the same semantics for our explicit
+ // multiply. We suppress this if overflow is not undefined behavior.
+ if (getLangOpts().isSignedOverflowDefined()) {
+ Idx = Builder.CreateMul(Idx, numElements);
+ EltPtr = Builder.CreateGEP(Base.getPointer(), Idx, "arrayidx");
+ } else {
+ Idx = Builder.CreateNSWMul(Idx, numElements);
+ EltPtr = Builder.CreateInBoundsGEP(Base.getPointer(), Idx, "arrayidx");
+ }
+ } else if (BaseTy->isConstantArrayType()) {
+ llvm::Value *ArrayPtr = Base.getPointer();
+ llvm::Value *Zero = llvm::ConstantInt::getNullValue(IntPtrTy);
+ llvm::Value *Args[] = {Zero, Idx};
+
+ if (getLangOpts().isSignedOverflowDefined())
+ EltPtr = Builder.CreateGEP(ArrayPtr, Args, "arrayidx");
+ else
+ EltPtr = Builder.CreateInBoundsGEP(ArrayPtr, Args, "arrayidx");
+ } else {
+ // The base must be a pointer, which is not an aggregate. Emit it.
+ if (getLangOpts().isSignedOverflowDefined())
+ EltPtr = Builder.CreateGEP(Base.getPointer(), Idx, "arrayidx");
+ else
+ EltPtr = Builder.CreateInBoundsGEP(Base.getPointer(), Idx, "arrayidx");
+ }
+
+ CharUnits EltAlign =
+ Base.getAlignment().alignmentOfArrayElement(
+ getContext().getTypeSizeInChars(FixedSizeEltType));
+
+ // Limit the alignment to that of the result type.
+ LValue LV = MakeAddrLValue(Address(EltPtr, EltAlign), ResultExprTy,
+ Base.getAlignmentSource());
+
+ LV.getQuals().setAddressSpace(BaseTy.getAddressSpace());
+
+ return LV;
}
LValue CodeGenFunction::
@@ -2592,9 +2982,10 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
if (E->isArrow()) {
// If it is a pointer to a vector, emit the address and form an lvalue with
// it.
- llvm::Value *Ptr = EmitScalarExpr(E->getBase());
+ AlignmentSource AlignSource;
+ Address Ptr = EmitPointerWithAlignment(E->getBase(), &AlignSource);
const PointerType *PT = E->getBase()->getType()->getAs<PointerType>();
- Base = MakeAddrLValue(Ptr, PT->getPointeeType());
+ Base = MakeAddrLValue(Ptr, PT->getPointeeType(), AlignSource);
Base.getQuals().removeObjCGCAttr();
} else if (E->getBase()->isGLValue()) {
// Otherwise, if the base is an lvalue ( as in the case of foo.x.x),
@@ -2608,22 +2999,24 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
llvm::Value *Vec = EmitScalarExpr(E->getBase());
// Store the vector to memory (because LValue wants an address).
- llvm::Value *VecMem = CreateMemTemp(E->getBase()->getType());
+ Address VecMem = CreateMemTemp(E->getBase()->getType());
Builder.CreateStore(Vec, VecMem);
- Base = MakeAddrLValue(VecMem, E->getBase()->getType());
+ Base = MakeAddrLValue(VecMem, E->getBase()->getType(),
+ AlignmentSource::Decl);
}
QualType type =
E->getType().withCVRQualifiers(Base.getQuals().getCVRQualifiers());
// Encode the element access list into a vector of unsigned indices.
- SmallVector<unsigned, 4> Indices;
+ SmallVector<uint32_t, 4> Indices;
E->getEncodedElementAccess(Indices);
if (Base.isSimple()) {
- llvm::Constant *CV = GenerateConstantVector(Builder, Indices);
+ llvm::Constant *CV =
+ llvm::ConstantDataVector::get(getLLVMContext(), Indices);
return LValue::MakeExtVectorElt(Base.getAddress(), CV, type,
- Base.getAlignment());
+ Base.getAlignmentSource());
}
assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!");
@@ -2633,8 +3026,8 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
for (unsigned i = 0, e = Indices.size(); i != e; ++i)
CElts.push_back(BaseElts->getAggregateElement(Indices[i]));
llvm::Constant *CV = llvm::ConstantVector::get(CElts);
- return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV, type,
- Base.getAlignment());
+ return LValue::MakeExtVectorElt(Base.getExtVectorAddress(), CV, type,
+ Base.getAlignmentSource());
}
LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
@@ -2643,10 +3036,11 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
LValue BaseLV;
if (E->isArrow()) {
- llvm::Value *Ptr = EmitScalarExpr(BaseExpr);
+ AlignmentSource AlignSource;
+ Address Addr = EmitPointerWithAlignment(BaseExpr, &AlignSource);
QualType PtrTy = BaseExpr->getType()->getPointeeType();
- EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Ptr, PtrTy);
- BaseLV = MakeNaturalAlignAddrLValue(Ptr, PtrTy);
+ EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy);
+ BaseLV = MakeAddrLValue(Addr, PtrTy, AlignSource);
} else
BaseLV = EmitCheckedLValue(BaseExpr, TCK_MemberAccess);
@@ -2677,41 +3071,65 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field) {
return EmitLValueForField(LambdaLV, Field);
}
+/// Drill down to the storage of a field without walking into
+/// reference types.
+///
+/// The resulting address doesn't necessarily have the right type.
+static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base,
+ const FieldDecl *field) {
+ const RecordDecl *rec = field->getParent();
+
+ unsigned idx =
+ CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
+
+ CharUnits offset;
+ // Adjust the alignment down to the given offset.
+ // As a special case, if the LLVM field index is 0, we know that this
+ // is zero.
+ assert((idx != 0 || CGF.getContext().getASTRecordLayout(rec)
+ .getFieldOffset(field->getFieldIndex()) == 0) &&
+ "LLVM field at index zero had non-zero offset?");
+ if (idx != 0) {
+ auto &recLayout = CGF.getContext().getASTRecordLayout(rec);
+ auto offsetInBits = recLayout.getFieldOffset(field->getFieldIndex());
+ offset = CGF.getContext().toCharUnitsFromBits(offsetInBits);
+ }
+
+ return CGF.Builder.CreateStructGEP(base, idx, offset, field->getName());
+}
+
LValue CodeGenFunction::EmitLValueForField(LValue base,
const FieldDecl *field) {
+ AlignmentSource fieldAlignSource =
+ getFieldAlignmentSource(base.getAlignmentSource());
+
if (field->isBitField()) {
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(field->getParent());
const CGBitFieldInfo &Info = RL.getBitFieldInfo(field);
- llvm::Value *Addr = base.getAddress();
+ Address Addr = base.getAddress();
unsigned Idx = RL.getLLVMFieldNo(field);
if (Idx != 0)
// For structs, we GEP to the field that the record layout suggests.
- Addr = Builder.CreateStructGEP(nullptr, Addr, Idx, field->getName());
+ Addr = Builder.CreateStructGEP(Addr, Idx, Info.StorageOffset,
+ field->getName());
// Get the access type.
- llvm::Type *PtrTy = llvm::Type::getIntNPtrTy(
- getLLVMContext(), Info.StorageSize,
- CGM.getContext().getTargetAddressSpace(base.getType()));
- if (Addr->getType() != PtrTy)
- Addr = Builder.CreateBitCast(Addr, PtrTy);
+ llvm::Type *FieldIntTy =
+ llvm::Type::getIntNTy(getLLVMContext(), Info.StorageSize);
+ if (Addr.getElementType() != FieldIntTy)
+ Addr = Builder.CreateElementBitCast(Addr, FieldIntTy);
QualType fieldType =
field->getType().withCVRQualifiers(base.getVRQualifiers());
- return LValue::MakeBitfield(Addr, Info, fieldType, base.getAlignment());
+ return LValue::MakeBitfield(Addr, Info, fieldType, fieldAlignSource);
}
const RecordDecl *rec = field->getParent();
QualType type = field->getType();
- CharUnits alignment = getContext().getDeclAlign(field);
-
- // FIXME: It should be impossible to have an LValue without alignment for a
- // complete type.
- if (!base.getAlignment().isZero())
- alignment = std::min(alignment, base.getAlignment());
bool mayAlias = rec->hasAttr<MayAliasAttr>();
- llvm::Value *addr = base.getAddress();
+ Address addr = base.getAddress();
unsigned cvr = base.getVRQualifiers();
bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA;
if (rec->isUnion()) {
@@ -2721,14 +3139,12 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
TBAAPath = false;
} else {
// For structs, we GEP to the field that the record layout suggests.
- unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
- addr = Builder.CreateStructGEP(nullptr, addr, idx, field->getName());
+ addr = emitAddrOfFieldStorage(*this, addr, field);
// If this is a reference field, load the reference right now.
if (const ReferenceType *refType = type->getAs<ReferenceType>()) {
llvm::LoadInst *load = Builder.CreateLoad(addr, "ref");
if (cvr & Qualifiers::Volatile) load->setVolatile(true);
- load->setAlignment(alignment.getQuantity());
// Loading the reference will disable path-aware TBAA.
TBAAPath = false;
@@ -2739,17 +3155,20 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
else
tbaa = CGM.getTBAAInfo(type);
if (tbaa)
- CGM.DecorateInstruction(load, tbaa);
+ CGM.DecorateInstructionWithTBAA(load, tbaa);
}
- addr = load;
mayAlias = false;
type = refType->getPointeeType();
- if (type->isIncompleteType())
- alignment = CharUnits();
- else
- alignment = getContext().getTypeAlignInChars(type);
- cvr = 0; // qualifiers don't recursively apply to referencee
+
+ CharUnits alignment =
+ getNaturalTypeAlignment(type, &fieldAlignSource, /*pointee*/ true);
+ addr = Address(load, alignment);
+
+ // Qualifiers on the struct don't apply to the referencee, and
+ // we'll pick up CVR from the actual type later, so reset these
+ // additional qualifiers now.
+ cvr = 0;
}
}
@@ -2757,14 +3176,14 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
// for both unions and structs. A union needs a bitcast, a struct element
// will need a bitcast if the LLVM type laid out doesn't match the desired
// type.
- addr = EmitBitCastOfLValueToProperType(*this, addr,
- CGM.getTypes().ConvertTypeForMem(type),
- field->getName());
+ addr = Builder.CreateElementBitCast(addr,
+ CGM.getTypes().ConvertTypeForMem(type),
+ field->getName());
if (field->hasAttr<AnnotateAttr>())
addr = EmitFieldAnnotations(field, addr);
- LValue LV = MakeAddrLValue(addr, type, alignment);
+ LValue LV = MakeAddrLValue(addr, type, fieldAlignSource);
LV.getQuals().addCVRQualifiers(cvr);
if (TBAAPath) {
const ASTRecordLayout &Layout =
@@ -2798,41 +3217,29 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
if (!FieldType->isReferenceType())
return EmitLValueForField(Base, Field);
- const CGRecordLayout &RL =
- CGM.getTypes().getCGRecordLayout(Field->getParent());
- unsigned idx = RL.getLLVMFieldNo(Field);
- llvm::Value *V = Builder.CreateStructGEP(nullptr, Base.getAddress(), idx);
- assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
+ Address V = emitAddrOfFieldStorage(*this, Base.getAddress(), Field);
- // Make sure that the address is pointing to the right type. This is critical
- // for both unions and structs. A union needs a bitcast, a struct element
- // will need a bitcast if the LLVM type laid out doesn't match the desired
- // type.
+ // Make sure that the address is pointing to the right type.
llvm::Type *llvmType = ConvertTypeForMem(FieldType);
- V = EmitBitCastOfLValueToProperType(*this, V, llvmType, Field->getName());
-
- CharUnits Alignment = getContext().getDeclAlign(Field);
-
- // FIXME: It should be impossible to have an LValue without alignment for a
- // complete type.
- if (!Base.getAlignment().isZero())
- Alignment = std::min(Alignment, Base.getAlignment());
+ V = Builder.CreateElementBitCast(V, llvmType, Field->getName());
- return MakeAddrLValue(V, FieldType, Alignment);
+ // TODO: access-path TBAA?
+ auto FieldAlignSource = getFieldAlignmentSource(Base.getAlignmentSource());
+ return MakeAddrLValue(V, FieldType, FieldAlignSource);
}
LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
if (E->isFileScope()) {
- llvm::Value *GlobalPtr = CGM.GetAddrOfConstantCompoundLiteral(E);
- return MakeAddrLValue(GlobalPtr, E->getType());
+ ConstantAddress GlobalPtr = CGM.GetAddrOfConstantCompoundLiteral(E);
+ return MakeAddrLValue(GlobalPtr, E->getType(), AlignmentSource::Decl);
}
if (E->getType()->isVariablyModifiedType())
// make sure to emit the VLA size.
EmitVariablyModifiedType(E->getType());
- llvm::Value *DeclPtr = CreateMemTemp(E->getType(), ".compoundliteral");
+ Address DeclPtr = CreateMemTemp(E->getType(), ".compoundliteral");
const Expr *InitExpr = E->getInitializer();
- LValue Result = MakeAddrLValue(DeclPtr, E->getType());
+ LValue Result = MakeAddrLValue(DeclPtr, E->getType(), AlignmentSource::Decl);
EmitAnyExprToMem(InitExpr, DeclPtr, E->getType().getQualifiers(),
/*Init*/ true);
@@ -2923,11 +3330,14 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
EmitBlock(contBlock);
if (lhs && rhs) {
- llvm::PHINode *phi = Builder.CreatePHI(lhs->getAddress()->getType(),
+ llvm::PHINode *phi = Builder.CreatePHI(lhs->getPointer()->getType(),
2, "cond-lvalue");
- phi->addIncoming(lhs->getAddress(), lhsBlock);
- phi->addIncoming(rhs->getAddress(), rhsBlock);
- return MakeAddrLValue(phi, expr->getType());
+ phi->addIncoming(lhs->getPointer(), lhsBlock);
+ phi->addIncoming(rhs->getPointer(), rhsBlock);
+ Address result(phi, std::min(lhs->getAlignment(), rhs->getAlignment()));
+ AlignmentSource alignSource =
+ std::max(lhs->getAlignmentSource(), rhs->getAlignmentSource());
+ return MakeAddrLValue(result, expr->getType(), alignSource);
} else {
assert((lhs || rhs) &&
"both operands of glvalue conditional are throw-expressions?");
@@ -2955,6 +3365,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_PointerToBoolean:
case CK_VectorSplat:
case CK_IntegralCast:
+ case CK_BooleanToSignedIntegral:
case CK_IntegralToBoolean:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
@@ -2996,9 +3407,9 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_Dynamic: {
LValue LV = EmitLValue(E->getSubExpr());
- llvm::Value *V = LV.getAddress();
+ Address V = LV.getAddress();
const auto *DCE = cast<CXXDynamicCastExpr>(E);
- return MakeAddrLValue(EmitDynamicCast(V, DCE), E->getType());
+ return MakeNaturalAlignAddrLValue(EmitDynamicCast(V, DCE), E->getType());
}
case CK_ConstructorConversion:
@@ -3016,14 +3427,14 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
auto *DerivedClassDecl = cast<CXXRecordDecl>(DerivedClassTy->getDecl());
LValue LV = EmitLValue(E->getSubExpr());
- llvm::Value *This = LV.getAddress();
+ Address This = LV.getAddress();
// Perform the derived-to-base conversion
- llvm::Value *Base = GetAddressOfBaseClass(
+ Address Base = GetAddressOfBaseClass(
This, DerivedClassDecl, E->path_begin(), E->path_end(),
/*NullCheckValue=*/false, E->getExprLoc());
- return MakeAddrLValue(Base, E->getType());
+ return MakeAddrLValue(Base, E->getType(), LV.getAlignmentSource());
}
case CK_ToUnion:
return EmitAggExprToLValue(E);
@@ -3034,7 +3445,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
LValue LV = EmitLValue(E->getSubExpr());
// Perform the base-to-derived conversion
- llvm::Value *Derived =
+ Address Derived =
GetAddressOfDerivedClass(LV.getAddress(), DerivedClassDecl,
E->path_begin(), E->path_end(),
/*NullCheckValue=*/false);
@@ -3043,34 +3454,36 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
// performed and the object is not of the derived type.
if (sanitizePerformTypeCheck())
EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(),
- Derived, E->getType());
+ Derived.getPointer(), E->getType());
if (SanOpts.has(SanitizerKind::CFIDerivedCast))
- EmitVTablePtrCheckForCast(E->getType(), Derived, /*MayBeNull=*/false,
+ EmitVTablePtrCheckForCast(E->getType(), Derived.getPointer(),
+ /*MayBeNull=*/false,
CFITCK_DerivedCast, E->getLocStart());
- return MakeAddrLValue(Derived, E->getType());
+ return MakeAddrLValue(Derived, E->getType(), LV.getAlignmentSource());
}
case CK_LValueBitCast: {
// This must be a reinterpret_cast (or c-style equivalent).
const auto *CE = cast<ExplicitCastExpr>(E);
+ CGM.EmitExplicitCastExprType(CE, this);
LValue LV = EmitLValue(E->getSubExpr());
- llvm::Value *V = Builder.CreateBitCast(LV.getAddress(),
- ConvertType(CE->getTypeAsWritten()));
+ Address V = Builder.CreateBitCast(LV.getAddress(),
+ ConvertType(CE->getTypeAsWritten()));
if (SanOpts.has(SanitizerKind::CFIUnrelatedCast))
- EmitVTablePtrCheckForCast(E->getType(), V, /*MayBeNull=*/false,
+ EmitVTablePtrCheckForCast(E->getType(), V.getPointer(),
+ /*MayBeNull=*/false,
CFITCK_UnrelatedCast, E->getLocStart());
- return MakeAddrLValue(V, E->getType());
+ return MakeAddrLValue(V, E->getType(), LV.getAlignmentSource());
}
case CK_ObjCObjectLValueCast: {
LValue LV = EmitLValue(E->getSubExpr());
- QualType ToType = getContext().getLValueReferenceType(E->getType());
- llvm::Value *V = Builder.CreateBitCast(LV.getAddress(),
- ConvertType(ToType));
- return MakeAddrLValue(V, E->getType());
+ Address V = Builder.CreateElementBitCast(LV.getAddress(),
+ ConvertType(E->getType()));
+ return MakeAddrLValue(V, E->getType(), LV.getAlignmentSource());
}
case CK_ZeroToOCLEvent:
llvm_unreachable("NULL to OpenCL event lvalue cast is not valid");
@@ -3129,20 +3542,17 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
if (const auto *PseudoDtor =
dyn_cast<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) {
QualType DestroyedType = PseudoDtor->getDestroyedType();
- if (getLangOpts().ObjCAutoRefCount &&
- DestroyedType->isObjCLifetimeType() &&
- (DestroyedType.getObjCLifetime() == Qualifiers::OCL_Strong ||
- DestroyedType.getObjCLifetime() == Qualifiers::OCL_Weak)) {
+ if (DestroyedType.hasStrongOrWeakObjCLifetime()) {
// Automatic Reference Counting:
// If the pseudo-expression names a retainable object with weak or
// strong lifetime, the object shall be released.
Expr *BaseExpr = PseudoDtor->getBase();
- llvm::Value *BaseValue = nullptr;
+ Address BaseValue = Address::invalid();
Qualifiers BaseQuals;
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
if (PseudoDtor->isArrow()) {
- BaseValue = EmitScalarExpr(BaseExpr);
+ BaseValue = EmitPointerWithAlignment(BaseExpr);
const PointerType *PTy = BaseExpr->getType()->getAs<PointerType>();
BaseQuals = PTy->getPointeeType().getQualifiers();
} else {
@@ -3152,7 +3562,7 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
BaseQuals = BaseTy.getQualifiers();
}
- switch (PseudoDtor->getDestroyedType().getObjCLifetime()) {
+ switch (DestroyedType.getObjCLifetime()) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Autoreleasing:
@@ -3237,13 +3647,14 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
RValue RV = EmitCallExpr(E);
if (!RV.isScalar())
- return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
+ return MakeAddrLValue(RV.getAggregateAddress(), E->getType(),
+ AlignmentSource::Decl);
assert(E->getCallReturnType(getContext())->isReferenceType() &&
"Can't have a scalar return unless the return type is a "
"reference type!");
- return MakeAddrLValue(RV.getScalarVal(), E->getType());
+ return MakeNaturalAlignPointeeAddrLValue(RV.getScalarVal(), E->getType());
}
LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) {
@@ -3256,21 +3667,23 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
&& "binding l-value to type which needs a temporary");
AggValueSlot Slot = CreateAggTemp(E->getType());
EmitCXXConstructExpr(E, Slot);
- return MakeAddrLValue(Slot.getAddr(), E->getType());
+ return MakeAddrLValue(Slot.getAddress(), E->getType(),
+ AlignmentSource::Decl);
}
LValue
CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) {
- return MakeAddrLValue(EmitCXXTypeidExpr(E), E->getType());
+ return MakeNaturalAlignAddrLValue(EmitCXXTypeidExpr(E), E->getType());
}
-llvm::Value *CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) {
- return Builder.CreateBitCast(CGM.GetAddrOfUuidDescriptor(E),
- ConvertType(E->getType())->getPointerTo());
+Address CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) {
+ return Builder.CreateElementBitCast(CGM.GetAddrOfUuidDescriptor(E),
+ ConvertType(E->getType()));
}
LValue CodeGenFunction::EmitCXXUuidofLValue(const CXXUuidofExpr *E) {
- return MakeAddrLValue(EmitCXXUuidofExpr(E), E->getType());
+ return MakeAddrLValue(EmitCXXUuidofExpr(E), E->getType(),
+ AlignmentSource::Decl);
}
LValue
@@ -3278,34 +3691,37 @@ CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) {
AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue");
Slot.setExternallyDestructed();
EmitAggExpr(E->getSubExpr(), Slot);
- EmitCXXTemporary(E->getTemporary(), E->getType(), Slot.getAddr());
- return MakeAddrLValue(Slot.getAddr(), E->getType());
+ EmitCXXTemporary(E->getTemporary(), E->getType(), Slot.getAddress());
+ return MakeAddrLValue(Slot.getAddress(), E->getType(),
+ AlignmentSource::Decl);
}
LValue
CodeGenFunction::EmitLambdaLValue(const LambdaExpr *E) {
AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue");
EmitLambdaExpr(E, Slot);
- return MakeAddrLValue(Slot.getAddr(), E->getType());
+ return MakeAddrLValue(Slot.getAddress(), E->getType(),
+ AlignmentSource::Decl);
}
LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
RValue RV = EmitObjCMessageExpr(E);
if (!RV.isScalar())
- return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
+ return MakeAddrLValue(RV.getAggregateAddress(), E->getType(),
+ AlignmentSource::Decl);
assert(E->getMethodDecl()->getReturnType()->isReferenceType() &&
"Can't have a scalar return unless the return type is a "
"reference type!");
- return MakeAddrLValue(RV.getScalarVal(), E->getType());
+ return MakeNaturalAlignPointeeAddrLValue(RV.getScalarVal(), E->getType());
}
LValue CodeGenFunction::EmitObjCSelectorLValue(const ObjCSelectorExpr *E) {
- llvm::Value *V =
- CGM.getObjCRuntime().GetSelector(*this, E->getSelector(), true);
- return MakeAddrLValue(V, E->getType());
+ Address V =
+ CGM.getObjCRuntime().GetAddrOfSelector(*this, E->getSelector());
+ return MakeAddrLValue(V, E->getType(), AlignmentSource::Decl);
}
llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface,
@@ -3333,8 +3749,7 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
BaseQuals = ObjectTy.getQualifiers();
} else {
LValue BaseLV = EmitLValue(BaseExpr);
- // FIXME: this isn't right for bitfields.
- BaseValue = BaseLV.getAddress();
+ BaseValue = BaseLV.getPointer();
ObjectTy = BaseExpr->getType();
BaseQuals = ObjectTy.getQualifiers();
}
@@ -3349,17 +3764,38 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
// Can only get l-value for message expression returning aggregate type
RValue RV = EmitAnyExprToTemp(E);
- return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
+ return MakeAddrLValue(RV.getAggregateAddress(), E->getType(),
+ AlignmentSource::Decl);
}
RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
const CallExpr *E, ReturnValueSlot ReturnValue,
- const Decl *TargetDecl, llvm::Value *Chain) {
+ CGCalleeInfo CalleeInfo, llvm::Value *Chain) {
// Get the actual function type. The callee type will always be a pointer to
// function type or a block pointer type.
assert(CalleeType->isFunctionPointerType() &&
"Call must have function pointer type!");
+ // Preserve the non-canonical function type because things like exception
+ // specifications disappear in the canonical type. That information is useful
+ // to drive the generation of more accurate code for this call later on.
+ const FunctionProtoType *NonCanonicalFTP = CalleeType->getAs<PointerType>()
+ ->getPointeeType()
+ ->getAs<FunctionProtoType>();
+
+ const Decl *TargetDecl = CalleeInfo.getCalleeDecl();
+
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
+ // We can only guarantee that a function is called from the correct
+ // context/function based on the appropriate target attributes,
+ // so only check in the case where we have both always_inline and target
+ // since otherwise we could be making a conditional call after a check for
+ // the proper cpu features (and it won't cause code generation issues due to
+ // function based code generation).
+ if (TargetDecl->hasAttr<AlwaysInlineAttr>() &&
+ TargetDecl->hasAttr<TargetAttr>())
+ checkTargetFeatures(E, FD);
+
CalleeType = getContext().getCanonicalType(CalleeType);
const auto *FnType =
@@ -3383,7 +3819,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
Callee, llvm::PointerType::getUnqual(PrefixStructTy));
llvm::Value *CalleeSigPtr =
Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 0);
- llvm::Value *CalleeSig = Builder.CreateLoad(CalleeSigPtr);
+ llvm::Value *CalleeSig =
+ Builder.CreateAlignedLoad(CalleeSigPtr, getIntAlign());
llvm::Value *CalleeSigMatch = Builder.CreateICmpEQ(CalleeSig, PrefixSig);
llvm::BasicBlock *Cont = createBasicBlock("cont");
@@ -3393,7 +3830,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
EmitBlock(TypeCheck);
llvm::Value *CalleeRTTIPtr =
Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 1);
- llvm::Value *CalleeRTTI = Builder.CreateLoad(CalleeRTTIPtr);
+ llvm::Value *CalleeRTTI =
+ Builder.CreateAlignedLoad(CalleeRTTIPtr, getPointerAlign());
llvm::Value *CalleeRTTIMatch =
Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst);
llvm::Constant *StaticData[] = {
@@ -3408,12 +3846,39 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
}
}
+ // If we are checking indirect calls and this call is indirect, check that the
+ // function pointer is a member of the bit set for the function type.
+ if (SanOpts.has(SanitizerKind::CFIICall) &&
+ (!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
+ SanitizerScope SanScope(this);
+
+ llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(QualType(FnType, 0));
+ llvm::Value *BitSetName = llvm::MetadataAsValue::get(getLLVMContext(), MD);
+
+ llvm::Value *CastedCallee = Builder.CreateBitCast(Callee, Int8PtrTy);
+ llvm::Value *BitSetTest =
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
+ {CastedCallee, BitSetName});
+
+ auto TypeId = CGM.CreateCfiIdForTypeMetadata(MD);
+ if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && TypeId) {
+ EmitCfiSlowPathCheck(BitSetTest, TypeId, CastedCallee);
+ } else {
+ llvm::Constant *StaticData[] = {
+ EmitCheckSourceLocation(E->getLocStart()),
+ EmitCheckTypeDescriptor(QualType(FnType, 0)),
+ };
+ EmitCheck(std::make_pair(BitSetTest, SanitizerKind::CFIICall),
+ "cfi_bad_icall", StaticData, CastedCallee);
+ }
+ }
+
CallArgList Args;
if (Chain)
Args.add(RValue::get(Builder.CreateBitCast(Chain, CGM.VoidPtrTy)),
CGM.getContext().VoidPtrTy);
- EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), E->arg_begin(),
- E->arg_end(), E->getDirectCallee(), /*ParamsToSkip*/ 0);
+ EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), E->arguments(),
+ E->getDirectCallee(), /*ParamsToSkip*/ 0);
const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall(
Args, FnType, /*isChainCall=*/Chain);
@@ -3444,34 +3909,38 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
Callee = Builder.CreateBitCast(Callee, CalleeTy, "callee.knr.cast");
}
- return EmitCall(FnInfo, Callee, ReturnValue, Args, TargetDecl);
+ return EmitCall(FnInfo, Callee, ReturnValue, Args,
+ CGCalleeInfo(NonCanonicalFTP, TargetDecl));
}
LValue CodeGenFunction::
EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
- llvm::Value *BaseV;
- if (E->getOpcode() == BO_PtrMemI)
- BaseV = EmitScalarExpr(E->getLHS());
- else
- BaseV = EmitLValue(E->getLHS()).getAddress();
+ Address BaseAddr = Address::invalid();
+ if (E->getOpcode() == BO_PtrMemI) {
+ BaseAddr = EmitPointerWithAlignment(E->getLHS());
+ } else {
+ BaseAddr = EmitLValue(E->getLHS()).getAddress();
+ }
llvm::Value *OffsetV = EmitScalarExpr(E->getRHS());
const MemberPointerType *MPT
= E->getRHS()->getType()->getAs<MemberPointerType>();
- llvm::Value *AddV = CGM.getCXXABI().EmitMemberDataPointerAddress(
- *this, E, BaseV, OffsetV, MPT);
+ AlignmentSource AlignSource;
+ Address MemberAddr =
+ EmitCXXMemberDataPointerAddress(E, BaseAddr, OffsetV, MPT,
+ &AlignSource);
- return MakeAddrLValue(AddV, MPT->getPointeeType());
+ return MakeAddrLValue(MemberAddr, MPT->getPointeeType(), AlignSource);
}
/// Given the address of a temporary variable, produce an r-value of
/// its type.
-RValue CodeGenFunction::convertTempToRValue(llvm::Value *addr,
+RValue CodeGenFunction::convertTempToRValue(Address addr,
QualType type,
SourceLocation loc) {
- LValue lvalue = MakeNaturalAlignAddrLValue(addr, type);
+ LValue lvalue = MakeAddrLValue(addr, type, AlignmentSource::Decl);
switch (getEvaluationKind(type)) {
case TEK_Complex:
return RValue::getComplex(EmitLoadOfComplex(lvalue, loc));
@@ -3527,7 +3996,8 @@ static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF,
CodeGenFunction::hasAggregateEvaluationKind(ov->getType())) {
CGF.EmitAggExpr(ov->getSourceExpr(), slot);
- LValue LV = CGF.MakeAddrLValue(slot.getAddr(), ov->getType());
+ LValue LV = CGF.MakeAddrLValue(slot.getAddress(), ov->getType(),
+ AlignmentSource::Decl);
opaqueData = OVMA::bind(CGF, ov, LV);
result.RV = slot.asRValue();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
index 883b76b..a4547a9 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprAgg.cpp
@@ -49,7 +49,8 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
if (!shouldUseDestForReturnSlot())
return ReturnValueSlot();
- return ReturnValueSlot(Dest.getAddr(), Dest.isVolatile(), IsResultUnused);
+ return ReturnValueSlot(Dest.getAddress(), Dest.isVolatile(),
+ IsResultUnused);
}
AggValueSlot EnsureSlot(QualType T) {
@@ -77,14 +78,13 @@ public:
/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
void EmitFinalDestCopy(QualType type, const LValue &src);
- void EmitFinalDestCopy(QualType type, RValue src,
- CharUnits srcAlignment = CharUnits::Zero());
+ void EmitFinalDestCopy(QualType type, RValue src);
void EmitCopy(QualType type, const AggValueSlot &dest,
const AggValueSlot &src);
void EmitMoveFromReturnSlot(const Expr *E, RValue Src);
- void EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
+ void EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
QualType elementType, InitListExpr *E);
AggValueSlot::NeedsGCBarriers_t needsGC(QualType T) {
@@ -199,7 +199,8 @@ public:
// case Expr::ChooseExprClass:
void VisitCXXThrowExpr(const CXXThrowExpr *E) { CGF.EmitCXXThrowExpr(E); }
void VisitAtomicExpr(AtomicExpr *E) {
- CGF.EmitAtomicExpr(E, EnsureSlot(E->getType()).getAddr());
+ RValue Res = CGF.EmitAtomicExpr(E);
+ EmitFinalDestCopy(E->getType(), Res);
}
};
} // end anonymous namespace.
@@ -259,17 +260,14 @@ void AggExprEmitter::EmitMoveFromReturnSlot(const Expr *E, RValue src) {
}
// Otherwise, copy from there to the destination.
- assert(Dest.getAddr() != src.getAggregateAddr());
- std::pair<CharUnits, CharUnits> typeInfo =
- CGF.getContext().getTypeInfoInChars(E->getType());
- EmitFinalDestCopy(E->getType(), src, typeInfo.second);
+ assert(Dest.getPointer() != src.getAggregatePointer());
+ EmitFinalDestCopy(E->getType(), src);
}
/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
-void AggExprEmitter::EmitFinalDestCopy(QualType type, RValue src,
- CharUnits srcAlign) {
+void AggExprEmitter::EmitFinalDestCopy(QualType type, RValue src) {
assert(src.isAggregate() && "value must be aggregate value!");
- LValue srcLV = CGF.MakeAddrLValue(src.getAggregateAddr(), type, srcAlign);
+ LValue srcLV = CGF.MakeAddrLValue(src.getAggregateAddress(), type);
EmitFinalDestCopy(type, srcLV);
}
@@ -298,8 +296,8 @@ void AggExprEmitter::EmitCopy(QualType type, const AggValueSlot &dest,
CharUnits sz = CGF.getContext().getTypeSizeInChars(type);
llvm::Value *size = llvm::ConstantInt::get(CGF.SizeTy, sz.getQuantity());
CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF,
- dest.getAddr(),
- src.getAddr(),
+ dest.getAddress(),
+ src.getAddress(),
size);
return;
}
@@ -307,9 +305,8 @@ void AggExprEmitter::EmitCopy(QualType type, const AggValueSlot &dest,
// If the result of the assignment is used, copy the LHS there also.
// It's volatile if either side is. Use the minimum alignment of
// the two sides.
- CGF.EmitAggregateCopy(dest.getAddr(), src.getAddr(), type,
- dest.isVolatile() || src.isVolatile(),
- std::min(dest.getAlignment(), src.getAlignment()));
+ CGF.EmitAggregateCopy(dest.getAddress(), src.getAddress(), type,
+ dest.isVolatile() || src.isVolatile());
}
/// \brief Emit the initializer for a std::initializer_list initialized with a
@@ -321,7 +318,7 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
ASTContext &Ctx = CGF.getContext();
LValue Array = CGF.EmitLValue(E->getSubExpr());
assert(Array.isSimple() && "initializer_list array not a simple lvalue");
- llvm::Value *ArrayPtr = Array.getAddress();
+ Address ArrayPtr = Array.getAddress();
const ConstantArrayType *ArrayType =
Ctx.getAsConstantArrayType(E->getSubExpr()->getType());
@@ -344,13 +341,12 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
}
AggValueSlot Dest = EnsureSlot(E->getType());
- LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
- Dest.getAlignment());
+ LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType());
LValue Start = CGF.EmitLValueForFieldInitialization(DestLV, *Field);
llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0);
llvm::Value *IdxStart[] = { Zero, Zero };
llvm::Value *ArrayStart =
- Builder.CreateInBoundsGEP(ArrayPtr, IdxStart, "arraystart");
+ Builder.CreateInBoundsGEP(ArrayPtr.getPointer(), IdxStart, "arraystart");
CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start);
++Field;
@@ -367,7 +363,7 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
// End pointer.
llvm::Value *IdxEnd[] = { Zero, Size };
llvm::Value *ArrayEnd =
- Builder.CreateInBoundsGEP(ArrayPtr, IdxEnd, "arrayend");
+ Builder.CreateInBoundsGEP(ArrayPtr.getPointer(), IdxEnd, "arrayend");
CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength);
} else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) {
// Length.
@@ -402,7 +398,7 @@ static bool isTrivialFiller(Expr *E) {
}
/// \brief Emit initialization of an array from an initializer list.
-void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
+void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
QualType elementType, InitListExpr *E) {
uint64_t NumInitElements = E->getNumInits();
@@ -414,13 +410,17 @@ void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0);
llvm::Value *indices[] = { zero, zero };
llvm::Value *begin =
- Builder.CreateInBoundsGEP(DestPtr, indices, "arrayinit.begin");
+ Builder.CreateInBoundsGEP(DestPtr.getPointer(), indices, "arrayinit.begin");
+
+ CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType);
+ CharUnits elementAlign =
+ DestPtr.getAlignment().alignmentOfArrayElement(elementSize);
// Exception safety requires us to destroy all the
// already-constructed members if an initializer throws.
// For that, we'll need an EH cleanup.
QualType::DestructionKind dtorKind = elementType.isDestructedType();
- llvm::AllocaInst *endOfInit = nullptr;
+ Address endOfInit = Address::invalid();
EHScopeStack::stable_iterator cleanup;
llvm::Instruction *cleanupDominator = nullptr;
if (CGF.needsEHCleanup(dtorKind)) {
@@ -428,10 +428,11 @@ void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
// directly, but the control flow can get so varied here that it
// would actually be quite complex. Therefore we go through an
// alloca.
- endOfInit = CGF.CreateTempAlloca(begin->getType(),
+ endOfInit = CGF.CreateTempAlloca(begin->getType(), CGF.getPointerAlign(),
"arrayinit.endOfInit");
cleanupDominator = Builder.CreateStore(begin, endOfInit);
CGF.pushIrregularPartialArrayCleanup(begin, endOfInit, elementType,
+ elementAlign,
CGF.getDestroyer(dtorKind));
cleanup = CGF.EHStack.stable_begin();
@@ -458,10 +459,11 @@ void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
// Tell the cleanup that it needs to destroy up to this
// element. TODO: some of these stores can be trivially
// observed to be unnecessary.
- if (endOfInit) Builder.CreateStore(element, endOfInit);
+ if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit);
}
- LValue elementLV = CGF.MakeAddrLValue(element, elementType);
+ LValue elementLV =
+ CGF.MakeAddrLValue(Address(element, elementAlign), elementType);
EmitInitializationToLValue(E->getInit(i), elementLV);
}
@@ -482,7 +484,7 @@ void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
// Advance to the start of the rest of the array.
if (NumInitElements) {
element = Builder.CreateInBoundsGEP(element, one, "arrayinit.start");
- if (endOfInit) Builder.CreateStore(element, endOfInit);
+ if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit);
}
// Compute the end of the array.
@@ -500,7 +502,8 @@ void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
currentElement->addIncoming(element, entryBB);
// Emit the actual filler expression.
- LValue elementLV = CGF.MakeAddrLValue(currentElement, elementType);
+ LValue elementLV =
+ CGF.MakeAddrLValue(Address(currentElement, elementAlign), elementType);
if (filler)
EmitInitializationToLValue(filler, elementLV);
else
@@ -511,7 +514,7 @@ void AggExprEmitter::EmitArrayInit(llvm::Value *DestPtr, llvm::ArrayType *AType,
Builder.CreateInBoundsGEP(currentElement, one, "arrayinit.next");
// Tell the EH cleanup that we finished with the last element.
- if (endOfInit) Builder.CreateStore(nextElement, endOfInit);
+ if (endOfInit.isValid()) Builder.CreateStore(nextElement, endOfInit);
// Leave the loop if we're done.
llvm::Value *done = Builder.CreateICmpEQ(nextElement, end,
@@ -569,6 +572,8 @@ static Expr *findPeephole(Expr *op, CastKind kind) {
}
void AggExprEmitter::VisitCastExpr(CastExpr *E) {
+ if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E))
+ CGF.CGM.EmitExplicitCastExprType(ECE, &CGF);
switch (E->getCastKind()) {
case CK_Dynamic: {
// FIXME: Can this actually happen? We have no test coverage for it.
@@ -596,9 +601,8 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
// GCC union extension
QualType Ty = E->getSubExpr()->getType();
- QualType PtrTy = CGF.getContext().getPointerType(Ty);
- llvm::Value *CastPtr = Builder.CreateBitCast(Dest.getAddr(),
- CGF.ConvertType(PtrTy));
+ Address CastPtr =
+ Builder.CreateElementBitCast(Dest.getAddress(), CGF.ConvertType(Ty));
EmitInitializationToLValue(E->getSubExpr(),
CGF.MakeAddrLValue(CastPtr, Ty));
break;
@@ -649,13 +653,13 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
// Zero-initialize. (Strictly speaking, we only need to intialize
// the padding at the end, but this is simpler.)
if (!Dest.isZeroed())
- CGF.EmitNullInitialization(Dest.getAddr(), atomicType);
+ CGF.EmitNullInitialization(Dest.getAddress(), atomicType);
// Build a GEP to refer to the subobject.
- llvm::Value *valueAddr =
- CGF.Builder.CreateStructGEP(nullptr, valueDest.getAddr(), 0);
+ Address valueAddr =
+ CGF.Builder.CreateStructGEP(valueDest.getAddress(), 0,
+ CharUnits());
valueDest = AggValueSlot::forAddr(valueAddr,
- valueDest.getAlignment(),
valueDest.getQualifiers(),
valueDest.isExternallyDestructed(),
valueDest.requiresGCollection(),
@@ -673,8 +677,8 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
CGF.CreateAggTemp(atomicType, "atomic-to-nonatomic.temp");
CGF.EmitAggExpr(E->getSubExpr(), atomicSlot);
- llvm::Value *valueAddr =
- Builder.CreateStructGEP(nullptr, atomicSlot.getAddr(), 0);
+ Address valueAddr =
+ Builder.CreateStructGEP(atomicSlot.getAddress(), 0, CharUnits());
RValue rvalue = RValue::getAggregate(valueAddr, atomicSlot.isVolatile());
return EmitFinalDestCopy(valueType, rvalue);
}
@@ -717,6 +721,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
case CK_ToVoid:
case CK_VectorSplat:
case CK_IntegralCast:
+ case CK_BooleanToSignedIntegral:
case CK_IntegralToBoolean:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
@@ -959,15 +964,15 @@ void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {
}
void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
- llvm::Value *ArgValue = CGF.EmitVAListRef(VE->getSubExpr());
- llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType());
+ Address ArgValue = Address::invalid();
+ Address ArgPtr = CGF.EmitVAArg(VE, ArgValue);
- if (!ArgPtr) {
+ if (!ArgPtr.isValid()) {
// If EmitVAArg fails, we fall back to the LLVM instruction.
- llvm::Value *Val =
- Builder.CreateVAArg(ArgValue, CGF.ConvertType(VE->getType()));
+ llvm::Value *Val = Builder.CreateVAArg(ArgValue.getPointer(),
+ CGF.ConvertType(VE->getType()));
if (!Dest.isIgnored())
- Builder.CreateStore(Val, Dest.getAddr());
+ Builder.CreateStore(Val, Dest.getAddress());
return;
}
@@ -987,7 +992,7 @@ void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
// Push that destructor we promised.
if (!wasExternallyDestructed)
- CGF.EmitCXXTemporary(E->getTemporary(), E->getType(), Dest.getAddr());
+ CGF.EmitCXXTemporary(E->getTemporary(), E->getType(), Dest.getAddress());
}
void
@@ -1011,13 +1016,13 @@ void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
void AggExprEmitter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
QualType T = E->getType();
AggValueSlot Slot = EnsureSlot(T);
- EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddr(), T));
+ EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddress(), T));
}
void AggExprEmitter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
QualType T = E->getType();
AggValueSlot Slot = EnsureSlot(T);
- EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddr(), T));
+ EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddress(), T));
}
/// isSimpleZero - If emitting this value will obviously just cause a store of
@@ -1135,8 +1140,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
AggValueSlot Dest = EnsureSlot(E->getType());
- LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
- Dest.getAlignment());
+ LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType());
// Handle initialization of an array.
if (E->getType()->isArrayType()) {
@@ -1146,12 +1150,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
QualType elementType =
CGF.getContext().getAsArrayType(E->getType())->getElementType();
- llvm::PointerType *APType =
- cast<llvm::PointerType>(Dest.getAddr()->getType());
- llvm::ArrayType *AType =
- cast<llvm::ArrayType>(APType->getElementType());
-
- EmitArrayInit(Dest.getAddr(), AType, elementType, E);
+ auto AType = cast<llvm::ArrayType>(Dest.getAddress().getElementType());
+ EmitArrayInit(Dest.getAddress(), AType, elementType, E);
return;
}
@@ -1175,7 +1175,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
RecordDecl *record = E->getType()->castAs<RecordType>()->getDecl();
// Prepare a 'this' for CXXDefaultInitExprs.
- CodeGenFunction::FieldConstructionScope FCS(CGF, Dest.getAddr());
+ CodeGenFunction::FieldConstructionScope FCS(CGF, Dest.getAddress());
if (record->isUnion()) {
// Only initialize one field of a union. The field itself is
@@ -1253,7 +1253,10 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
assert(LV.isSimple());
if (CGF.needsEHCleanup(dtorKind)) {
if (!cleanupDominator)
- cleanupDominator = CGF.Builder.CreateUnreachable(); // placeholder
+ cleanupDominator = CGF.Builder.CreateAlignedLoad(
+ CGF.Int8Ty,
+ llvm::Constant::getNullValue(CGF.Int8PtrTy),
+ CharUnits::One()); // placeholder
CGF.pushDestroy(EHCleanup, LV.getAddress(), field->getType(),
CGF.getDestroyer(dtorKind), false);
@@ -1266,7 +1269,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
// else, clean it up for -O0 builds and general tidiness.
if (!pushedCleanup && LV.isSimple())
if (llvm::GetElementPtrInst *GEP =
- dyn_cast<llvm::GetElementPtrInst>(LV.getAddress()))
+ dyn_cast<llvm::GetElementPtrInst>(LV.getPointer()))
if (GEP->use_empty())
GEP->eraseFromParent();
}
@@ -1284,8 +1287,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
void AggExprEmitter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
AggValueSlot Dest = EnsureSlot(E->getType());
- LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
- Dest.getAlignment());
+ LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType());
EmitInitializationToLValue(E->getBase(), DestLV);
VisitInitListExpr(E->getUpdater());
}
@@ -1355,7 +1357,7 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
CodeGenFunction &CGF) {
// If the slot is already known to be zeroed, nothing to do. Don't mess with
// volatile stores.
- if (Slot.isZeroed() || Slot.isVolatile() || Slot.getAddr() == nullptr)
+ if (Slot.isZeroed() || Slot.isVolatile() || !Slot.getAddress().isValid())
return;
// C++ objects with a user-declared constructor don't need zero'ing.
@@ -1368,26 +1370,22 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
}
// If the type is 16-bytes or smaller, prefer individual stores over memset.
- std::pair<CharUnits, CharUnits> TypeInfo =
- CGF.getContext().getTypeInfoInChars(E->getType());
- if (TypeInfo.first <= CharUnits::fromQuantity(16))
+ CharUnits Size = CGF.getContext().getTypeSizeInChars(E->getType());
+ if (Size <= CharUnits::fromQuantity(16))
return;
// Check to see if over 3/4 of the initializer are known to be zero. If so,
// we prefer to emit memset + individual stores for the rest.
CharUnits NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF);
- if (NumNonZeroBytes*4 > TypeInfo.first)
+ if (NumNonZeroBytes*4 > Size)
return;
// Okay, it seems like a good idea to use an initial memset, emit the call.
- llvm::Constant *SizeVal = CGF.Builder.getInt64(TypeInfo.first.getQuantity());
- CharUnits Align = TypeInfo.second;
+ llvm::Constant *SizeVal = CGF.Builder.getInt64(Size.getQuantity());
- llvm::Value *Loc = Slot.getAddr();
-
- Loc = CGF.Builder.CreateBitCast(Loc, CGF.Int8PtrTy);
- CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal,
- Align.getQuantity(), false);
+ Address Loc = Slot.getAddress();
+ Loc = CGF.Builder.CreateElementBitCast(Loc, CGF.Int8Ty);
+ CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal, false);
// Tell the AggExprEmitter that the slot is known zero.
Slot.setZeroed();
@@ -1403,7 +1401,7 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot) {
assert(E && hasAggregateEvaluationKind(E->getType()) &&
"Invalid aggregate expression to emit");
- assert((Slot.getAddr() != nullptr || Slot.isIgnored()) &&
+ assert((Slot.getAddress().isValid() || Slot.isIgnored()) &&
"slot has bits but no address");
// Optimize the slot if possible.
@@ -1414,7 +1412,7 @@ void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot) {
LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) {
assert(hasAggregateEvaluationKind(E->getType()) && "Invalid argument!");
- llvm::Value *Temp = CreateMemTemp(E->getType());
+ Address Temp = CreateMemTemp(E->getType());
LValue LV = MakeAddrLValue(Temp, E->getType());
EmitAggExpr(E, AggValueSlot::forLValue(LV, AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
@@ -1422,10 +1420,9 @@ LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) {
return LV;
}
-void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
- llvm::Value *SrcPtr, QualType Ty,
+void CodeGenFunction::EmitAggregateCopy(Address DestPtr,
+ Address SrcPtr, QualType Ty,
bool isVolatile,
- CharUnits alignment,
bool isAssignment) {
assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex");
@@ -1456,17 +1453,16 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
// implementation handles this case safely. If there is a libc that does not
// safely handle this, we can add a target hook.
- // Get data size and alignment info for this aggregate. If this is an
- // assignment don't copy the tail padding. Otherwise copying it is fine.
+ // Get data size info for this aggregate. If this is an assignment,
+ // don't copy the tail padding, because we might be assigning into a
+ // base subobject where the tail padding is claimed. Otherwise,
+ // copying it is fine.
std::pair<CharUnits, CharUnits> TypeInfo;
if (isAssignment)
TypeInfo = getContext().getTypeInfoDataSizeInChars(Ty);
else
TypeInfo = getContext().getTypeInfoInChars(Ty);
- if (alignment.isZero())
- alignment = TypeInfo.second;
-
llvm::Value *SizeVal = nullptr;
if (TypeInfo.first.isZero()) {
// But note that getTypeInfo returns 0 for a VLA.
@@ -1509,15 +1505,8 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
// we need to use a different call here. We use isVolatile to indicate when
// either the source or the destination is volatile.
- llvm::PointerType *DPT = cast<llvm::PointerType>(DestPtr->getType());
- llvm::Type *DBP =
- llvm::Type::getInt8PtrTy(getLLVMContext(), DPT->getAddressSpace());
- DestPtr = Builder.CreateBitCast(DestPtr, DBP);
-
- llvm::PointerType *SPT = cast<llvm::PointerType>(SrcPtr->getType());
- llvm::Type *SBP =
- llvm::Type::getInt8PtrTy(getLLVMContext(), SPT->getAddressSpace());
- SrcPtr = Builder.CreateBitCast(SrcPtr, SBP);
+ DestPtr = Builder.CreateElementBitCast(DestPtr, Int8Ty);
+ SrcPtr = Builder.CreateElementBitCast(SrcPtr, Int8Ty);
// Don't do any of the memmove_collectable tests if GC isn't set.
if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
@@ -1540,11 +1529,11 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
}
}
+ auto Inst = Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, isVolatile);
+
// Determine the metadata to describe the position of any padding in this
// memcpy, as well as the TBAA tags for the members of the struct, in case
// the optimizer wishes to expand it in to scalar memory operations.
- llvm::MDNode *TBAAStructTag = CGM.getTBAAStructInfo(Ty);
-
- Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, alignment.getQuantity(),
- isVolatile, /*TBAATag=*/nullptr, TBAAStructTag);
+ if (llvm::MDNode *TBAAStructTag = CGM.getTBAAStructInfo(Ty))
+ Inst->setMetadata(llvm::LLVMContext::MD_tbaa_struct, TBAAStructTag);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
index c7adcca..604cde7 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprCXX.cpp
@@ -59,7 +59,7 @@ static RequiredArgs commonEmitCXXMemberOrOperatorCall(
if (CE) {
// Special case: skip first argument of CXXOperatorCall (it is "this").
unsigned ArgsToSkip = isa<CXXOperatorCallExpr>(CE) ? 1 : 0;
- CGF.EmitCallArgs(Args, FPT, CE->arg_begin() + ArgsToSkip, CE->arg_end(),
+ CGF.EmitCallArgs(Args, FPT, drop_begin(CE->arguments(), ArgsToSkip),
CE->getDirectCallee());
} else {
assert(
@@ -166,9 +166,9 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
}
}
- llvm::Value *This;
+ Address This = Address::invalid();
if (IsArrow)
- This = EmitScalarExpr(Base);
+ This = EmitPointerWithAlignment(Base);
else
This = EmitLValue(Base).getAddress();
@@ -185,19 +185,18 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
// when it isn't necessary; just produce the proper effect here.
// Special case: skip first argument of CXXOperatorCall (it is "this").
unsigned ArgsToSkip = isa<CXXOperatorCallExpr>(CE) ? 1 : 0;
- llvm::Value *RHS =
- EmitLValue(*(CE->arg_begin() + ArgsToSkip)).getAddress();
+ Address RHS = EmitLValue(*(CE->arg_begin() + ArgsToSkip)).getAddress();
EmitAggregateAssign(This, RHS, CE->getType());
- return RValue::get(This);
+ return RValue::get(This.getPointer());
}
if (isa<CXXConstructorDecl>(MD) &&
cast<CXXConstructorDecl>(MD)->isCopyOrMoveConstructor()) {
// Trivial move and copy ctor are the same.
assert(CE->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
- llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress();
- EmitAggregateCopy(This, RHS, CE->arg_begin()->getType());
- return RValue::get(This);
+ Address RHS = EmitLValue(*CE->arg_begin()).getAddress();
+ EmitAggregateCopy(This, RHS, (*CE->arg_begin())->getType());
+ return RValue::get(This.getPointer());
}
llvm_unreachable("unknown trivial member function");
}
@@ -245,7 +244,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
cast<CXXDestructorDecl>(DevirtualizedMethod);
Callee = CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty);
}
- EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This,
+ EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This.getPointer(),
/*ImplicitParam=*/nullptr, QualType(), CE);
}
return RValue::get(nullptr);
@@ -259,7 +258,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
} else {
if (SanOpts.has(SanitizerKind::CFINVCall) &&
MD->getParent()->isDynamicClass()) {
- llvm::Value *VTable = GetVTablePtr(This, Int8PtrTy);
+ llvm::Value *VTable = GetVTablePtr(This, Int8PtrTy, MD->getParent());
EmitVTablePtrCheckForCall(MD, VTable, CFITCK_NVCall, CE->getLocStart());
}
@@ -277,7 +276,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
*this, MD, This, UseVirtualCall);
}
- return EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This,
+ return EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This.getPointer(),
/*ImplicitParam=*/nullptr, QualType(), CE);
}
@@ -301,19 +300,20 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
llvm::Value *MemFnPtr = EmitScalarExpr(MemFnExpr);
// Emit the 'this' pointer.
- llvm::Value *This;
-
+ Address This = Address::invalid();
if (BO->getOpcode() == BO_PtrMemI)
- This = EmitScalarExpr(BaseExpr);
+ This = EmitPointerWithAlignment(BaseExpr);
else
This = EmitLValue(BaseExpr).getAddress();
- EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This,
+ EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.getPointer(),
QualType(MPT->getClass(), 0));
// Ask the ABI to load the callee. Note that This is modified.
+ llvm::Value *ThisPtrForCall = nullptr;
llvm::Value *Callee =
- CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, BO, This, MemFnPtr, MPT);
+ CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, BO, This,
+ ThisPtrForCall, MemFnPtr, MPT);
CallArgList Args;
@@ -321,12 +321,12 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
getContext().getPointerType(getContext().getTagDeclType(RD));
// Push the this ptr.
- Args.add(RValue::get(This), ThisType);
+ Args.add(RValue::get(ThisPtrForCall), ThisType);
RequiredArgs required = RequiredArgs::forPrototypePlus(FPT, 1);
// And the rest of the call args
- EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end(), E->getDirectCallee());
+ EmitCallArgs(Args, FPT, E->arguments(), E->getDirectCallee());
return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required),
Callee, ReturnValue, Args);
}
@@ -348,18 +348,43 @@ RValue CodeGenFunction::EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E,
}
static void EmitNullBaseClassInitialization(CodeGenFunction &CGF,
- llvm::Value *DestPtr,
+ Address DestPtr,
const CXXRecordDecl *Base) {
if (Base->isEmpty())
return;
- DestPtr = CGF.EmitCastToVoidPtr(DestPtr);
+ DestPtr = CGF.Builder.CreateElementBitCast(DestPtr, CGF.Int8Ty);
const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(Base);
- CharUnits Size = Layout.getNonVirtualSize();
- CharUnits Align = Layout.getNonVirtualAlignment();
-
- llvm::Value *SizeVal = CGF.CGM.getSize(Size);
+ CharUnits NVSize = Layout.getNonVirtualSize();
+
+ // We cannot simply zero-initialize the entire base sub-object if vbptrs are
+ // present, they are initialized by the most derived class before calling the
+ // constructor.
+ SmallVector<std::pair<CharUnits, CharUnits>, 1> Stores;
+ Stores.emplace_back(CharUnits::Zero(), NVSize);
+
+ // Each store is split by the existence of a vbptr.
+ CharUnits VBPtrWidth = CGF.getPointerSize();
+ std::vector<CharUnits> VBPtrOffsets =
+ CGF.CGM.getCXXABI().getVBPtrOffsets(Base);
+ for (CharUnits VBPtrOffset : VBPtrOffsets) {
+ std::pair<CharUnits, CharUnits> LastStore = Stores.pop_back_val();
+ CharUnits LastStoreOffset = LastStore.first;
+ CharUnits LastStoreSize = LastStore.second;
+
+ CharUnits SplitBeforeOffset = LastStoreOffset;
+ CharUnits SplitBeforeSize = VBPtrOffset - SplitBeforeOffset;
+ assert(!SplitBeforeSize.isNegative() && "negative store size!");
+ if (!SplitBeforeSize.isZero())
+ Stores.emplace_back(SplitBeforeOffset, SplitBeforeSize);
+
+ CharUnits SplitAfterOffset = VBPtrOffset + VBPtrWidth;
+ CharUnits SplitAfterSize = LastStoreSize - SplitAfterOffset;
+ assert(!SplitAfterSize.isNegative() && "negative store size!");
+ if (!SplitAfterSize.isZero())
+ Stores.emplace_back(SplitAfterOffset, SplitAfterSize);
+ }
// If the type contains a pointer to data member we can't memset it to zero.
// Instead, create a null constant and copy it to the destination.
@@ -367,27 +392,43 @@ static void EmitNullBaseClassInitialization(CodeGenFunction &CGF,
// like -1, which happens to be the pattern used by member-pointers.
// TODO: isZeroInitializable can be over-conservative in the case where a
// virtual base contains a member pointer.
- if (!CGF.CGM.getTypes().isZeroInitializable(Base)) {
- llvm::Constant *NullConstant = CGF.CGM.EmitNullConstantForBase(Base);
-
- llvm::GlobalVariable *NullVariable =
- new llvm::GlobalVariable(CGF.CGM.getModule(), NullConstant->getType(),
- /*isConstant=*/true,
- llvm::GlobalVariable::PrivateLinkage,
- NullConstant, Twine());
+ llvm::Constant *NullConstantForBase = CGF.CGM.EmitNullConstantForBase(Base);
+ if (!NullConstantForBase->isNullValue()) {
+ llvm::GlobalVariable *NullVariable = new llvm::GlobalVariable(
+ CGF.CGM.getModule(), NullConstantForBase->getType(),
+ /*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage,
+ NullConstantForBase, Twine());
+
+ CharUnits Align = std::max(Layout.getNonVirtualAlignment(),
+ DestPtr.getAlignment());
NullVariable->setAlignment(Align.getQuantity());
- llvm::Value *SrcPtr = CGF.EmitCastToVoidPtr(NullVariable);
+
+ Address SrcPtr = Address(CGF.EmitCastToVoidPtr(NullVariable), Align);
// Get and call the appropriate llvm.memcpy overload.
- CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, Align.getQuantity());
- return;
- }
-
+ for (std::pair<CharUnits, CharUnits> Store : Stores) {
+ CharUnits StoreOffset = Store.first;
+ CharUnits StoreSize = Store.second;
+ llvm::Value *StoreSizeVal = CGF.CGM.getSize(StoreSize);
+ CGF.Builder.CreateMemCpy(
+ CGF.Builder.CreateConstInBoundsByteGEP(DestPtr, StoreOffset),
+ CGF.Builder.CreateConstInBoundsByteGEP(SrcPtr, StoreOffset),
+ StoreSizeVal);
+ }
+
// Otherwise, just memset the whole thing to zero. This is legal
// because in LLVM, all default initializers (other than the ones we just
// handled above) are guaranteed to have a bit pattern of all zeros.
- CGF.Builder.CreateMemSet(DestPtr, CGF.Builder.getInt8(0), SizeVal,
- Align.getQuantity());
+ } else {
+ for (std::pair<CharUnits, CharUnits> Store : Stores) {
+ CharUnits StoreOffset = Store.first;
+ CharUnits StoreSize = Store.second;
+ llvm::Value *StoreSizeVal = CGF.CGM.getSize(StoreSize);
+ CGF.Builder.CreateMemSet(
+ CGF.Builder.CreateConstInBoundsByteGEP(DestPtr, StoreOffset),
+ CGF.Builder.getInt8(0), StoreSizeVal);
+ }
+ }
}
void
@@ -404,11 +445,12 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
switch (E->getConstructionKind()) {
case CXXConstructExpr::CK_Delegating:
case CXXConstructExpr::CK_Complete:
- EmitNullInitialization(Dest.getAddr(), E->getType());
+ EmitNullInitialization(Dest.getAddress(), E->getType());
break;
case CXXConstructExpr::CK_VirtualBase:
case CXXConstructExpr::CK_NonVirtualBase:
- EmitNullBaseClassInitialization(*this, Dest.getAddr(), CD->getParent());
+ EmitNullBaseClassInitialization(*this, Dest.getAddress(),
+ CD->getParent());
break;
}
}
@@ -431,7 +473,7 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
if (const ConstantArrayType *arrayType
= getContext().getAsConstantArrayType(E->getType())) {
- EmitCXXAggrConstructorCall(CD, arrayType, Dest.getAddr(), E);
+ EmitCXXAggrConstructorCall(CD, arrayType, Dest.getAddress(), E);
} else {
CXXCtorType Type = Ctor_Complete;
bool ForVirtualBase = false;
@@ -457,15 +499,13 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
}
// Call the constructor.
- EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating, Dest.getAddr(),
- E);
+ EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating,
+ Dest.getAddress(), E);
}
}
-void
-CodeGenFunction::EmitSynthesizedCXXCopyCtor(llvm::Value *Dest,
- llvm::Value *Src,
- const Expr *Exp) {
+void CodeGenFunction::EmitSynthesizedCXXCopyCtor(Address Dest, Address Src,
+ const Expr *Exp) {
if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(Exp))
Exp = E->getSubExpr();
assert(isa<CXXConstructExpr>(Exp) &&
@@ -759,22 +799,20 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
}
static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
- QualType AllocType, llvm::Value *NewPtr) {
+ QualType AllocType, Address NewPtr) {
// FIXME: Refactor with EmitExprAsInit.
- CharUnits Alignment = CGF.getContext().getTypeAlignInChars(AllocType);
switch (CGF.getEvaluationKind(AllocType)) {
case TEK_Scalar:
CGF.EmitScalarInit(Init, nullptr,
- CGF.MakeAddrLValue(NewPtr, AllocType, Alignment), false);
+ CGF.MakeAddrLValue(NewPtr, AllocType), false);
return;
case TEK_Complex:
- CGF.EmitComplexExprIntoLValue(Init, CGF.MakeAddrLValue(NewPtr, AllocType,
- Alignment),
+ CGF.EmitComplexExprIntoLValue(Init, CGF.MakeAddrLValue(NewPtr, AllocType),
/*isInit*/ true);
return;
case TEK_Aggregate: {
AggValueSlot Slot
- = AggValueSlot::forAddr(NewPtr, Alignment, AllocType.getQualifiers(),
+ = AggValueSlot::forAddr(NewPtr, AllocType.getQualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased);
@@ -787,23 +825,27 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
void CodeGenFunction::EmitNewArrayInitializer(
const CXXNewExpr *E, QualType ElementType, llvm::Type *ElementTy,
- llvm::Value *BeginPtr, llvm::Value *NumElements,
+ Address BeginPtr, llvm::Value *NumElements,
llvm::Value *AllocSizeWithoutCookie) {
// If we have a type with trivial initialization and no initializer,
// there's nothing to do.
if (!E->hasInitializer())
return;
- llvm::Value *CurPtr = BeginPtr;
+ Address CurPtr = BeginPtr;
unsigned InitListElements = 0;
const Expr *Init = E->getInitializer();
- llvm::AllocaInst *EndOfInit = nullptr;
+ Address EndOfInit = Address::invalid();
QualType::DestructionKind DtorKind = ElementType.isDestructedType();
EHScopeStack::stable_iterator Cleanup;
llvm::Instruction *CleanupDominator = nullptr;
+ CharUnits ElementSize = getContext().getTypeSizeInChars(ElementType);
+ CharUnits ElementAlign =
+ BeginPtr.getAlignment().alignmentOfArrayElement(ElementSize);
+
// If the initializer is an initializer list, first do the explicit elements.
if (const InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
InitListElements = ILE->getNumInits();
@@ -813,10 +855,8 @@ void CodeGenFunction::EmitNewArrayInitializer(
QualType AllocType = E->getAllocatedType();
if (const ConstantArrayType *CAT = dyn_cast_or_null<ConstantArrayType>(
AllocType->getAsArrayTypeUnsafe())) {
- unsigned AS = CurPtr->getType()->getPointerAddressSpace();
ElementTy = ConvertTypeForMem(AllocType);
- llvm::Type *AllocPtrTy = ElementTy->getPointerTo(AS);
- CurPtr = Builder.CreateBitCast(CurPtr, AllocPtrTy);
+ CurPtr = Builder.CreateElementBitCast(CurPtr, ElementTy);
InitListElements *= getContext().getConstantArrayElementCount(CAT);
}
@@ -826,27 +866,34 @@ void CodeGenFunction::EmitNewArrayInitializer(
// directly, but the control flow can get so varied here that it
// would actually be quite complex. Therefore we go through an
// alloca.
- EndOfInit = CreateTempAlloca(BeginPtr->getType(), "array.init.end");
- CleanupDominator = Builder.CreateStore(BeginPtr, EndOfInit);
- pushIrregularPartialArrayCleanup(BeginPtr, EndOfInit, ElementType,
+ EndOfInit = CreateTempAlloca(BeginPtr.getType(), getPointerAlign(),
+ "array.init.end");
+ CleanupDominator = Builder.CreateStore(BeginPtr.getPointer(), EndOfInit);
+ pushIrregularPartialArrayCleanup(BeginPtr.getPointer(), EndOfInit,
+ ElementType, ElementAlign,
getDestroyer(DtorKind));
Cleanup = EHStack.stable_begin();
}
+ CharUnits StartAlign = CurPtr.getAlignment();
for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i) {
// Tell the cleanup that it needs to destroy up to this
// element. TODO: some of these stores can be trivially
// observed to be unnecessary.
- if (EndOfInit)
- Builder.CreateStore(Builder.CreateBitCast(CurPtr, BeginPtr->getType()),
- EndOfInit);
+ if (EndOfInit.isValid()) {
+ auto FinishedPtr =
+ Builder.CreateBitCast(CurPtr.getPointer(), BeginPtr.getType());
+ Builder.CreateStore(FinishedPtr, EndOfInit);
+ }
// FIXME: If the last initializer is an incomplete initializer list for
// an array, and we have an array filler, we can fold together the two
// initialization loops.
StoreAnyExprIntoOneUnit(*this, ILE->getInit(i),
ILE->getInit(i)->getType(), CurPtr);
- CurPtr = Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr, 1,
- "array.exp.next");
+ CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getPointer(),
+ Builder.getSize(1),
+ "array.exp.next"),
+ StartAlign.alignmentAtOffset((i + 1) * ElementSize));
}
// The remaining elements are filled with the array filler expression.
@@ -864,7 +911,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
}
// Switch back to initializing one base element at a time.
- CurPtr = Builder.CreateBitCast(CurPtr, BeginPtr->getType());
+ CurPtr = Builder.CreateBitCast(CurPtr, BeginPtr.getType());
}
// Attempt to perform zero-initialization using memset.
@@ -889,9 +936,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
}
// Create the memset.
- CharUnits Alignment = getContext().getTypeAlignInChars(ElementType);
- Builder.CreateMemSet(CurPtr, Builder.getInt8(0), RemainingSize,
- Alignment.getQuantity(), false);
+ Builder.CreateMemSet(CurPtr, Builder.getInt8(0), RemainingSize, false);
return true;
};
@@ -925,7 +970,8 @@ void CodeGenFunction::EmitNewArrayInitializer(
//
// FIXME: Share this cleanup with the constructor call emission rather than
// having it create a cleanup of its own.
- if (EndOfInit) Builder.CreateStore(CurPtr, EndOfInit);
+ if (EndOfInit.isValid())
+ Builder.CreateStore(CurPtr.getPointer(), EndOfInit);
// Emit a constructor call loop to initialize the remaining elements.
if (InitListElements)
@@ -985,13 +1031,13 @@ void CodeGenFunction::EmitNewArrayInitializer(
// Find the end of the array, hoisted out of the loop.
llvm::Value *EndPtr =
- Builder.CreateInBoundsGEP(BeginPtr, NumElements, "array.end");
+ Builder.CreateInBoundsGEP(BeginPtr.getPointer(), NumElements, "array.end");
// If the number of elements isn't constant, we have to now check if there is
// anything left to initialize.
if (!ConstNum) {
- llvm::Value *IsEmpty = Builder.CreateICmpEQ(CurPtr, EndPtr,
- "array.isempty");
+ llvm::Value *IsEmpty =
+ Builder.CreateICmpEQ(CurPtr.getPointer(), EndPtr, "array.isempty");
Builder.CreateCondBr(IsEmpty, ContBB, LoopBB);
}
@@ -1000,16 +1046,19 @@ void CodeGenFunction::EmitNewArrayInitializer(
// Set up the current-element phi.
llvm::PHINode *CurPtrPhi =
- Builder.CreatePHI(CurPtr->getType(), 2, "array.cur");
- CurPtrPhi->addIncoming(CurPtr, EntryBB);
- CurPtr = CurPtrPhi;
+ Builder.CreatePHI(CurPtr.getType(), 2, "array.cur");
+ CurPtrPhi->addIncoming(CurPtr.getPointer(), EntryBB);
+
+ CurPtr = Address(CurPtrPhi, ElementAlign);
// Store the new Cleanup position for irregular Cleanups.
- if (EndOfInit) Builder.CreateStore(CurPtr, EndOfInit);
+ if (EndOfInit.isValid())
+ Builder.CreateStore(CurPtr.getPointer(), EndOfInit);
// Enter a partial-destruction Cleanup if necessary.
if (!CleanupDominator && needsEHCleanup(DtorKind)) {
- pushRegularPartialArrayCleanup(BeginPtr, CurPtr, ElementType,
+ pushRegularPartialArrayCleanup(BeginPtr.getPointer(), CurPtr.getPointer(),
+ ElementType, ElementAlign,
getDestroyer(DtorKind));
Cleanup = EHStack.stable_begin();
CleanupDominator = Builder.CreateUnreachable();
@@ -1026,7 +1075,8 @@ void CodeGenFunction::EmitNewArrayInitializer(
// Advance to the next element by adjusting the pointer type as necessary.
llvm::Value *NextPtr =
- Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr, 1, "array.next");
+ Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr.getPointer(), 1,
+ "array.next");
// Check whether we've gotten to the end of the array and, if so,
// exit the loop.
@@ -1039,7 +1089,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
QualType ElementType, llvm::Type *ElementTy,
- llvm::Value *NewPtr, llvm::Value *NumElements,
+ Address NewPtr, llvm::Value *NumElements,
llvm::Value *AllocSizeWithoutCookie) {
ApplyDebugLocation DL(CGF, E);
if (E->isArray())
@@ -1089,8 +1139,7 @@ RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
bool IsDelete) {
CallArgList Args;
const Stmt *ArgS = Arg;
- EmitCallArgs(Args, *Type->param_type_begin(),
- ConstExprIterator(&ArgS), ConstExprIterator(&ArgS + 1));
+ EmitCallArgs(Args, *Type->param_type_begin(), llvm::makeArrayRef(ArgS));
// Find the allocation or deallocation function that we're calling.
ASTContext &Ctx = getContext();
DeclarationName Name = Ctx.DeclarationNames
@@ -1105,7 +1154,7 @@ RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
namespace {
/// A cleanup to call the given 'operator delete' function upon
/// abnormal exit from a new expression.
- class CallDeleteDuringNew : public EHScopeStack::Cleanup {
+ class CallDeleteDuringNew final : public EHScopeStack::Cleanup {
size_t NumPlacementArgs;
const FunctionDecl *OperatorDelete;
llvm::Value *Ptr;
@@ -1158,7 +1207,7 @@ namespace {
/// A cleanup to call the given 'operator delete' function upon
/// abnormal exit from a new expression when the new expression is
/// conditional.
- class CallDeleteDuringConditionalNew : public EHScopeStack::Cleanup {
+ class CallDeleteDuringConditionalNew final : public EHScopeStack::Cleanup {
size_t NumPlacementArgs;
const FunctionDecl *OperatorDelete;
DominatingValue<RValue>::saved_type Ptr;
@@ -1219,7 +1268,7 @@ namespace {
/// new-expression throws.
static void EnterNewDeleteCleanup(CodeGenFunction &CGF,
const CXXNewExpr *E,
- llvm::Value *NewPtr,
+ Address NewPtr,
llvm::Value *AllocSize,
const CallArgList &NewArgs) {
// If we're not inside a conditional branch, then the cleanup will
@@ -1229,7 +1278,8 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF,
.pushCleanupWithExtra<CallDeleteDuringNew>(EHCleanup,
E->getNumPlacementArgs(),
E->getOperatorDelete(),
- NewPtr, AllocSize);
+ NewPtr.getPointer(),
+ AllocSize);
for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I)
Cleanup->setPlacementArg(I, NewArgs[I+1].RV);
@@ -1238,7 +1288,7 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF,
// Otherwise, we need to save all this stuff.
DominatingValue<RValue>::saved_type SavedNewPtr =
- DominatingValue<RValue>::save(CGF, RValue::get(NewPtr));
+ DominatingValue<RValue>::save(CGF, RValue::get(NewPtr.getPointer()));
DominatingValue<RValue>::saved_type SavedAllocSize =
DominatingValue<RValue>::save(CGF, RValue::get(AllocSize));
@@ -1261,13 +1311,6 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
// 1. Build a call to the allocation function.
FunctionDecl *allocator = E->getOperatorNew();
- const FunctionProtoType *allocatorType =
- allocator->getType()->castAs<FunctionProtoType>();
-
- CallArgList allocatorArgs;
-
- // The allocation size is the first argument.
- QualType sizeType = getContext().getSizeType();
// If there is a brace-initializer, cannot allocate fewer elements than inits.
unsigned minElements = 0;
@@ -1282,24 +1325,61 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
EmitCXXNewAllocSize(*this, E, minElements, numElements,
allocSizeWithoutCookie);
- allocatorArgs.add(RValue::get(allocSize), sizeType);
-
- // We start at 1 here because the first argument (the allocation size)
- // has already been emitted.
- EmitCallArgs(allocatorArgs, allocatorType, E->placement_arg_begin(),
- E->placement_arg_end(), /* CalleeDecl */ nullptr,
- /*ParamsToSkip*/ 1);
-
// Emit the allocation call. If the allocator is a global placement
// operator, just "inline" it directly.
- RValue RV;
+ Address allocation = Address::invalid();
+ CallArgList allocatorArgs;
if (allocator->isReservedGlobalPlacementOperator()) {
- assert(allocatorArgs.size() == 2);
- RV = allocatorArgs[1].RV;
- // TODO: kill any unnecessary computations done for the size
- // argument.
+ assert(E->getNumPlacementArgs() == 1);
+ const Expr *arg = *E->placement_arguments().begin();
+
+ AlignmentSource alignSource;
+ allocation = EmitPointerWithAlignment(arg, &alignSource);
+
+ // The pointer expression will, in many cases, be an opaque void*.
+ // In these cases, discard the computed alignment and use the
+ // formal alignment of the allocated type.
+ if (alignSource != AlignmentSource::Decl) {
+ allocation = Address(allocation.getPointer(),
+ getContext().getTypeAlignInChars(allocType));
+ }
+
+ // Set up allocatorArgs for the call to operator delete if it's not
+ // the reserved global operator.
+ if (E->getOperatorDelete() &&
+ !E->getOperatorDelete()->isReservedGlobalPlacementOperator()) {
+ allocatorArgs.add(RValue::get(allocSize), getContext().getSizeType());
+ allocatorArgs.add(RValue::get(allocation.getPointer()), arg->getType());
+ }
+
} else {
- RV = EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);
+ const FunctionProtoType *allocatorType =
+ allocator->getType()->castAs<FunctionProtoType>();
+
+ // The allocation size is the first argument.
+ QualType sizeType = getContext().getSizeType();
+ allocatorArgs.add(RValue::get(allocSize), sizeType);
+
+ // We start at 1 here because the first argument (the allocation size)
+ // has already been emitted.
+ EmitCallArgs(allocatorArgs, allocatorType, E->placement_arguments(),
+ /* CalleeDecl */ nullptr,
+ /*ParamsToSkip*/ 1);
+
+ RValue RV =
+ EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);
+
+ // For now, only assume that the allocation function returns
+ // something satisfactorily aligned for the element type, plus
+ // the cookie if we have one.
+ CharUnits allocationAlign =
+ getContext().getTypeAlignInChars(allocType);
+ if (allocSize != allocSizeWithoutCookie) {
+ CharUnits cookieAlign = getSizeAlign(); // FIXME?
+ allocationAlign = std::max(allocationAlign, cookieAlign);
+ }
+
+ allocation = Address(RV.getScalarVal(), allocationAlign);
}
// Emit a null check on the allocation result if the allocation
@@ -1312,9 +1392,6 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
llvm::BasicBlock *nullCheckBB = nullptr;
llvm::BasicBlock *contBB = nullptr;
- llvm::Value *allocation = RV.getScalarVal();
- unsigned AS = allocation->getType()->getPointerAddressSpace();
-
// The null-check means that the initializer is conditionally
// evaluated.
ConditionalEvaluation conditional(*this);
@@ -1326,7 +1403,8 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
llvm::BasicBlock *notNullBB = createBasicBlock("new.notnull");
contBB = createBasicBlock("new.cont");
- llvm::Value *isNull = Builder.CreateIsNull(allocation, "new.isnull");
+ llvm::Value *isNull =
+ Builder.CreateIsNull(allocation.getPointer(), "new.isnull");
Builder.CreateCondBr(isNull, contBB, notNullBB);
EmitBlock(notNullBB);
}
@@ -1352,8 +1430,15 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
}
llvm::Type *elementTy = ConvertTypeForMem(allocType);
- llvm::Type *elementPtrTy = elementTy->getPointerTo(AS);
- llvm::Value *result = Builder.CreateBitCast(allocation, elementPtrTy);
+ Address result = Builder.CreateElementBitCast(allocation, elementTy);
+
+ // Passing pointer through invariant.group.barrier to avoid propagation of
+ // vptrs information which may be included in previous type.
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ allocator->isReservedGlobalPlacementOperator())
+ result = Address(Builder.CreateInvariantGroupBarrier(result.getPointer()),
+ result.getAlignment());
EmitNewInitializer(*this, E, allocType, elementTy, result, numElements,
allocSizeWithoutCookie);
@@ -1362,7 +1447,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
// allocating an array of arrays, we'll need to cast back to the
// array pointer type.
llvm::Type *resultType = ConvertTypeForMem(E->getType());
- if (result->getType() != resultType)
+ if (result.getType() != resultType)
result = Builder.CreateBitCast(result, resultType);
}
@@ -1373,21 +1458,22 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
cleanupDominator->eraseFromParent();
}
+ llvm::Value *resultPtr = result.getPointer();
if (nullCheck) {
conditional.end(*this);
llvm::BasicBlock *notNullBB = Builder.GetInsertBlock();
EmitBlock(contBB);
- llvm::PHINode *PHI = Builder.CreatePHI(result->getType(), 2);
- PHI->addIncoming(result, notNullBB);
- PHI->addIncoming(llvm::Constant::getNullValue(result->getType()),
+ llvm::PHINode *PHI = Builder.CreatePHI(resultPtr->getType(), 2);
+ PHI->addIncoming(resultPtr, notNullBB);
+ PHI->addIncoming(llvm::Constant::getNullValue(resultPtr->getType()),
nullCheckBB);
- result = PHI;
+ resultPtr = PHI;
}
- return result;
+ return resultPtr;
}
void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
@@ -1423,7 +1509,7 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
namespace {
/// Calls the given 'operator delete' on a single object.
- struct CallObjectDelete : EHScopeStack::Cleanup {
+ struct CallObjectDelete final : EHScopeStack::Cleanup {
llvm::Value *Ptr;
const FunctionDecl *OperatorDelete;
QualType ElementType;
@@ -1450,7 +1536,7 @@ CodeGenFunction::pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete,
/// Emit the code for deleting a single object.
static void EmitObjectDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *DE,
- llvm::Value *Ptr,
+ Address Ptr,
QualType ElementType) {
// Find the destructor for the type, if applicable. If the
// destructor is virtual, we'll just emit the vcall and return.
@@ -1473,29 +1559,24 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
// to pop it off in a second.
const FunctionDecl *OperatorDelete = DE->getOperatorDelete();
CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup,
- Ptr, OperatorDelete, ElementType);
+ Ptr.getPointer(),
+ OperatorDelete, ElementType);
if (Dtor)
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
/*ForVirtualBase=*/false,
/*Delegating=*/false,
Ptr);
- else if (CGF.getLangOpts().ObjCAutoRefCount &&
- ElementType->isObjCLifetimeType()) {
- switch (ElementType.getObjCLifetime()) {
+ else if (auto Lifetime = ElementType.getObjCLifetime()) {
+ switch (Lifetime) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
case Qualifiers::OCL_Autoreleasing:
break;
- case Qualifiers::OCL_Strong: {
- // Load the pointer value.
- llvm::Value *PtrValue = CGF.Builder.CreateLoad(Ptr,
- ElementType.isVolatileQualified());
-
- CGF.EmitARCRelease(PtrValue, ARCPreciseLifetime);
+ case Qualifiers::OCL_Strong:
+ CGF.EmitARCDestroyStrong(Ptr, ARCPreciseLifetime);
break;
- }
case Qualifiers::OCL_Weak:
CGF.EmitARCDestroyWeak(Ptr);
@@ -1508,7 +1589,7 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
namespace {
/// Calls the given 'operator delete' on an array of objects.
- struct CallArrayDelete : EHScopeStack::Cleanup {
+ struct CallArrayDelete final : EHScopeStack::Cleanup {
llvm::Value *Ptr;
const FunctionDecl *OperatorDelete;
llvm::Value *NumElements;
@@ -1570,7 +1651,7 @@ namespace {
/// Emit the code for deleting an array of objects.
static void EmitArrayDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *E,
- llvm::Value *deletedPtr,
+ Address deletedPtr,
QualType elementType) {
llvm::Value *numElements = nullptr;
llvm::Value *allocatedPtr = nullptr;
@@ -1591,13 +1672,18 @@ static void EmitArrayDelete(CodeGenFunction &CGF,
if (QualType::DestructionKind dtorKind = elementType.isDestructedType()) {
assert(numElements && "no element count for a type with a destructor!");
+ CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType);
+ CharUnits elementAlign =
+ deletedPtr.getAlignment().alignmentOfArrayElement(elementSize);
+
+ llvm::Value *arrayBegin = deletedPtr.getPointer();
llvm::Value *arrayEnd =
- CGF.Builder.CreateInBoundsGEP(deletedPtr, numElements, "delete.end");
+ CGF.Builder.CreateInBoundsGEP(arrayBegin, numElements, "delete.end");
// Note that it is legal to allocate a zero-length array, and we
// can never fold the check away because the length should always
// come from a cookie.
- CGF.emitArrayDestroy(deletedPtr, arrayEnd, elementType,
+ CGF.emitArrayDestroy(arrayBegin, arrayEnd, elementType, elementAlign,
CGF.getDestroyer(dtorKind),
/*checkZeroLength*/ true,
CGF.needsEHCleanup(dtorKind));
@@ -1609,13 +1695,13 @@ static void EmitArrayDelete(CodeGenFunction &CGF,
void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
const Expr *Arg = E->getArgument();
- llvm::Value *Ptr = EmitScalarExpr(Arg);
+ Address Ptr = EmitPointerWithAlignment(Arg);
// Null check the pointer.
llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull");
llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end");
- llvm::Value *IsNull = Builder.CreateIsNull(Ptr, "isnull");
+ llvm::Value *IsNull = Builder.CreateIsNull(Ptr.getPointer(), "isnull");
Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull);
EmitBlock(DeleteNotNull);
@@ -1640,11 +1726,11 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
GEP.push_back(Zero);
}
- Ptr = Builder.CreateInBoundsGEP(Ptr, GEP, "del.first");
+ Ptr = Address(Builder.CreateInBoundsGEP(Ptr.getPointer(), GEP, "del.first"),
+ Ptr.getAlignment());
}
- assert(ConvertTypeForMem(DeleteTy) ==
- cast<llvm::PointerType>(Ptr->getType())->getElementType());
+ assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType());
if (E->isArrayForm()) {
EmitArrayDelete(*this, E, Ptr, DeleteTy);
@@ -1690,7 +1776,7 @@ static bool isGLValueFromPointerDeref(const Expr *E) {
static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E,
llvm::Type *StdTypeInfoPtrTy) {
// Get the vtable pointer.
- llvm::Value *ThisPtr = CGF.EmitLValue(E).getAddress();
+ Address ThisPtr = CGF.EmitLValue(E).getAddress();
// C++ [expr.typeid]p2:
// If the glvalue expression is obtained by applying the unary * operator to
@@ -1707,7 +1793,7 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E,
CGF.createBasicBlock("typeid.bad_typeid");
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end");
- llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr);
+ llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr.getPointer());
CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock);
CGF.EmitBlock(BadTypeidBlock);
@@ -1758,8 +1844,9 @@ static llvm::Value *EmitDynamicCastToNull(CodeGenFunction &CGF,
return llvm::UndefValue::get(DestLTy);
}
-llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value,
+llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,
const CXXDynamicCastExpr *DCE) {
+ CGM.EmitExplicitCastExprType(DCE, this);
QualType DestTy = DCE->getTypeAsWritten();
if (DCE->isAlwaysNull())
@@ -1803,19 +1890,21 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value,
CastNull = createBasicBlock("dynamic_cast.null");
CastNotNull = createBasicBlock("dynamic_cast.notnull");
- llvm::Value *IsNull = Builder.CreateIsNull(Value);
+ llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr.getPointer());
Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
EmitBlock(CastNotNull);
}
+ llvm::Value *Value;
if (isDynamicCastToVoid) {
- Value = CGM.getCXXABI().EmitDynamicCastToVoid(*this, Value, SrcRecordTy,
+ Value = CGM.getCXXABI().EmitDynamicCastToVoid(*this, ThisAddr, SrcRecordTy,
DestTy);
} else {
assert(DestRecordTy->isRecordType() &&
"destination type must be a record type!");
- Value = CGM.getCXXABI().EmitDynamicCastCall(*this, Value, SrcRecordTy,
+ Value = CGM.getCXXABI().EmitDynamicCastCall(*this, ThisAddr, SrcRecordTy,
DestTy, DestRecordTy, CastEnd);
+ CastNotNull = Builder.GetInsertBlock();
}
if (ShouldNullCheckSrcValue) {
@@ -1840,12 +1929,11 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value,
void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) {
RunCleanupsScope Scope(*this);
- LValue SlotLV =
- MakeAddrLValue(Slot.getAddr(), E->getType(), Slot.getAlignment());
+ LValue SlotLV = MakeAddrLValue(Slot.getAddress(), E->getType());
CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin();
- for (LambdaExpr::capture_init_iterator i = E->capture_init_begin(),
- e = E->capture_init_end();
+ for (LambdaExpr::const_capture_init_iterator i = E->capture_init_begin(),
+ e = E->capture_init_end();
i != e; ++i, ++CurField) {
// Emit initialization
LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
index 27d1c68..22910d9 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp
@@ -83,12 +83,12 @@ public:
/// specified value pointer.
void EmitStoreOfComplex(ComplexPairTy Val, LValue LV, bool isInit);
- /// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
+ /// Emit a cast from complex value Val to DestType.
ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType,
- QualType DestType);
- /// EmitComplexToComplexCast - Emit a cast from scalar value Val to DestType.
+ QualType DestType, SourceLocation Loc);
+ /// Emit a cast from scalar value Val to DestType.
ComplexPairTy EmitScalarToComplexCast(llvm::Value *Val, QualType SrcType,
- QualType DestType);
+ QualType DestType, SourceLocation Loc);
//===--------------------------------------------------------------------===//
// Visitor Methods
@@ -154,6 +154,8 @@ public:
return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
}
ComplexPairTy VisitCastExpr(CastExpr *E) {
+ if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E))
+ CGF.CGM.EmitExplicitCastExprType(ECE, &CGF);
return EmitCast(E->getCastKind(), E->getSubExpr(), E->getType());
}
ComplexPairTy VisitCallExpr(const CallExpr *E);
@@ -298,6 +300,19 @@ public:
// Utilities
//===----------------------------------------------------------------------===//
+Address CodeGenFunction::emitAddrOfRealComponent(Address addr,
+ QualType complexType) {
+ CharUnits offset = CharUnits::Zero();
+ return Builder.CreateStructGEP(addr, 0, offset, addr.getName() + ".realp");
+}
+
+Address CodeGenFunction::emitAddrOfImagComponent(Address addr,
+ QualType complexType) {
+ QualType eltType = complexType->castAs<ComplexType>()->getElementType();
+ CharUnits offset = getContext().getTypeSizeInChars(eltType);
+ return Builder.CreateStructGEP(addr, 1, offset, addr.getName() + ".imagp");
+}
+
/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to
/// load the real and imaginary pieces, returning them as Real/Imag.
ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue,
@@ -306,29 +321,21 @@ ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue,
if (lvalue.getType()->isAtomicType())
return CGF.EmitAtomicLoad(lvalue, loc).getComplexVal();
- llvm::Value *SrcPtr = lvalue.getAddress();
+ Address SrcPtr = lvalue.getAddress();
bool isVolatile = lvalue.isVolatileQualified();
- unsigned AlignR = lvalue.getAlignment().getQuantity();
- ASTContext &C = CGF.getContext();
- QualType ComplexTy = lvalue.getType();
- unsigned ComplexAlign = C.getTypeAlignInChars(ComplexTy).getQuantity();
- unsigned AlignI = std::min(AlignR, ComplexAlign);
- llvm::Value *Real=nullptr, *Imag=nullptr;
+ llvm::Value *Real = nullptr, *Imag = nullptr;
if (!IgnoreReal || isVolatile) {
- llvm::Value *RealP = Builder.CreateStructGEP(nullptr, SrcPtr, 0,
- SrcPtr->getName() + ".realp");
- Real = Builder.CreateAlignedLoad(RealP, AlignR, isVolatile,
- SrcPtr->getName() + ".real");
+ Address RealP = CGF.emitAddrOfRealComponent(SrcPtr, lvalue.getType());
+ Real = Builder.CreateLoad(RealP, isVolatile, SrcPtr.getName() + ".real");
}
if (!IgnoreImag || isVolatile) {
- llvm::Value *ImagP = Builder.CreateStructGEP(nullptr, SrcPtr, 1,
- SrcPtr->getName() + ".imagp");
- Imag = Builder.CreateAlignedLoad(ImagP, AlignI, isVolatile,
- SrcPtr->getName() + ".imag");
+ Address ImagP = CGF.emitAddrOfImagComponent(SrcPtr, lvalue.getType());
+ Imag = Builder.CreateLoad(ImagP, isVolatile, SrcPtr.getName() + ".imag");
}
+
return ComplexPairTy(Real, Imag);
}
@@ -340,19 +347,12 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue,
(!isInit && CGF.LValueIsSuitableForInlineAtomic(lvalue)))
return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit);
- llvm::Value *Ptr = lvalue.getAddress();
- llvm::Value *RealPtr = Builder.CreateStructGEP(nullptr, Ptr, 0, "real");
- llvm::Value *ImagPtr = Builder.CreateStructGEP(nullptr, Ptr, 1, "imag");
- unsigned AlignR = lvalue.getAlignment().getQuantity();
- ASTContext &C = CGF.getContext();
- QualType ComplexTy = lvalue.getType();
- unsigned ComplexAlign = C.getTypeAlignInChars(ComplexTy).getQuantity();
- unsigned AlignI = std::min(AlignR, ComplexAlign);
-
- Builder.CreateAlignedStore(Val.first, RealPtr, AlignR,
- lvalue.isVolatileQualified());
- Builder.CreateAlignedStore(Val.second, ImagPtr, AlignI,
- lvalue.isVolatileQualified());
+ Address Ptr = lvalue.getAddress();
+ Address RealPtr = CGF.emitAddrOfRealComponent(Ptr, lvalue.getType());
+ Address ImagPtr = CGF.emitAddrOfImagComponent(Ptr, lvalue.getType());
+
+ Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
+ Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
}
@@ -385,16 +385,17 @@ ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) {
ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) {
CodeGenFunction::StmtExprEvaluation eval(CGF);
- llvm::Value *RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(), true);
- assert(RetAlloca && "Expected complex return value");
+ Address RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(), true);
+ assert(RetAlloca.isValid() && "Expected complex return value");
return EmitLoadOfLValue(CGF.MakeAddrLValue(RetAlloca, E->getType()),
E->getExprLoc());
}
-/// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
+/// Emit a cast from complex value Val to DestType.
ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val,
QualType SrcType,
- QualType DestType) {
+ QualType DestType,
+ SourceLocation Loc) {
// Get the src/dest element type.
SrcType = SrcType->castAs<ComplexType>()->getElementType();
DestType = DestType->castAs<ComplexType>()->getElementType();
@@ -402,17 +403,18 @@ ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val,
// C99 6.3.1.6: When a value of complex type is converted to another
// complex type, both the real and imaginary parts follow the conversion
// rules for the corresponding real types.
- Val.first = CGF.EmitScalarConversion(Val.first, SrcType, DestType);
- Val.second = CGF.EmitScalarConversion(Val.second, SrcType, DestType);
+ Val.first = CGF.EmitScalarConversion(Val.first, SrcType, DestType, Loc);
+ Val.second = CGF.EmitScalarConversion(Val.second, SrcType, DestType, Loc);
return Val;
}
ComplexPairTy ComplexExprEmitter::EmitScalarToComplexCast(llvm::Value *Val,
QualType SrcType,
- QualType DestType) {
+ QualType DestType,
+ SourceLocation Loc) {
// Convert the input element to the element type of the complex.
DestType = DestType->castAs<ComplexType>()->getElementType();
- Val = CGF.EmitScalarConversion(Val, SrcType, DestType);
+ Val = CGF.EmitScalarConversion(Val, SrcType, DestType, Loc);
// Return (realval, 0).
return ComplexPairTy(Val, llvm::Constant::getNullValue(Val->getType()));
@@ -434,12 +436,9 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
case CK_LValueBitCast: {
LValue origLV = CGF.EmitLValue(Op);
- llvm::Value *V = origLV.getAddress();
- V = Builder.CreateBitCast(V,
- CGF.ConvertType(CGF.getContext().getPointerType(DestTy)));
- return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy,
- origLV.getAlignment()),
- Op->getExprLoc());
+ Address V = origLV.getAddress();
+ V = Builder.CreateElementBitCast(V, CGF.ConvertType(DestTy));
+ return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy), Op->getExprLoc());
}
case CK_BitCast:
@@ -463,6 +462,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
case CK_ToVoid:
case CK_VectorSplat:
case CK_IntegralCast:
+ case CK_BooleanToSignedIntegral:
case CK_IntegralToBoolean:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
@@ -488,14 +488,15 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
case CK_FloatingRealToComplex:
case CK_IntegralRealToComplex:
- return EmitScalarToComplexCast(CGF.EmitScalarExpr(Op),
- Op->getType(), DestTy);
+ return EmitScalarToComplexCast(CGF.EmitScalarExpr(Op), Op->getType(),
+ DestTy, Op->getExprLoc());
case CK_FloatingComplexCast:
case CK_FloatingComplexToIntegralComplex:
case CK_IntegralComplexCast:
case CK_IntegralComplexToFloatingComplex:
- return EmitComplexToComplexCast(Visit(Op), Op->getType(), DestTy);
+ return EmitComplexToComplexCast(Visit(Op), Op->getType(), DestTy,
+ Op->getExprLoc());
}
llvm_unreachable("unknown cast resulting in complex value");
@@ -585,19 +586,25 @@ ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName,
// We *must* use the full CG function call building logic here because the
// complex type has special ABI handling. We also should not forget about
// special calling convention which may be used for compiler builtins.
- const CGFunctionInfo &FuncInfo =
- CGF.CGM.getTypes().arrangeFreeFunctionCall(
- Op.Ty, Args, FunctionType::ExtInfo(/* No CC here - will be added later */),
- RequiredArgs::All);
+
+ // We create a function qualified type to state that this call does not have
+ // any exceptions.
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI = EPI.withExceptionSpec(
+ FunctionProtoType::ExceptionSpecInfo(EST_BasicNoexcept));
+ SmallVector<QualType, 4> ArgsQTys(
+ 4, Op.Ty->castAs<ComplexType>()->getElementType());
+ QualType FQTy = CGF.getContext().getFunctionType(Op.Ty, ArgsQTys, EPI);
+ const CGFunctionInfo &FuncInfo = CGF.CGM.getTypes().arrangeFreeFunctionCall(
+ Args, cast<FunctionType>(FQTy.getTypePtr()), false);
+
llvm::FunctionType *FTy = CGF.CGM.getTypes().GetFunctionType(FuncInfo);
llvm::Constant *Func = CGF.CGM.CreateBuiltinFunction(FTy, LibCallName);
llvm::Instruction *Call;
RValue Res = CGF.EmitCall(FuncInfo, Func, ReturnValueSlot(), Args,
- nullptr, &Call);
+ FQTy->getAs<FunctionProtoType>(), &Call);
cast<llvm::CallInst>(Call)->setCallingConv(CGF.CGM.getBuiltinCC());
- cast<llvm::CallInst>(Call)->setDoesNotThrow();
-
return Res.getComplexVal();
}
@@ -846,19 +853,20 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
LValue LHS = CGF.EmitLValue(E->getLHS());
// Load from the l-value and convert it.
+ SourceLocation Loc = E->getExprLoc();
if (LHSTy->isAnyComplexType()) {
- ComplexPairTy LHSVal = EmitLoadOfLValue(LHS, E->getExprLoc());
- OpInfo.LHS = EmitComplexToComplexCast(LHSVal, LHSTy, OpInfo.Ty);
+ ComplexPairTy LHSVal = EmitLoadOfLValue(LHS, Loc);
+ OpInfo.LHS = EmitComplexToComplexCast(LHSVal, LHSTy, OpInfo.Ty, Loc);
} else {
- llvm::Value *LHSVal = CGF.EmitLoadOfScalar(LHS, E->getExprLoc());
+ llvm::Value *LHSVal = CGF.EmitLoadOfScalar(LHS, Loc);
// For floating point real operands we can directly pass the scalar form
// to the binary operator emission and potentially get more efficient code.
if (LHSTy->isRealFloatingType()) {
if (!CGF.getContext().hasSameUnqualifiedType(ComplexElementTy, LHSTy))
- LHSVal = CGF.EmitScalarConversion(LHSVal, LHSTy, ComplexElementTy);
+ LHSVal = CGF.EmitScalarConversion(LHSVal, LHSTy, ComplexElementTy, Loc);
OpInfo.LHS = ComplexPairTy(LHSVal, nullptr);
} else {
- OpInfo.LHS = EmitScalarToComplexCast(LHSVal, LHSTy, OpInfo.Ty);
+ OpInfo.LHS = EmitScalarToComplexCast(LHSVal, LHSTy, OpInfo.Ty, Loc);
}
}
@@ -867,12 +875,13 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
// Truncate the result and store it into the LHS lvalue.
if (LHSTy->isAnyComplexType()) {
- ComplexPairTy ResVal = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy);
+ ComplexPairTy ResVal =
+ EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy, Loc);
EmitStoreOfComplex(ResVal, LHS, /*isInit*/ false);
Val = RValue::getComplex(ResVal);
} else {
llvm::Value *ResVal =
- CGF.EmitComplexToScalarConversion(Result, OpInfo.Ty, LHSTy);
+ CGF.EmitComplexToScalarConversion(Result, OpInfo.Ty, LHSTy, Loc);
CGF.EmitStoreOfScalar(ResVal, LHS, /*isInit*/ false);
Val = RValue::get(ResVal);
}
@@ -1011,10 +1020,10 @@ ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
}
ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
- llvm::Value *ArgValue = CGF.EmitVAListRef(E->getSubExpr());
- llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, E->getType());
+ Address ArgValue = Address::invalid();
+ Address ArgPtr = CGF.EmitVAArg(E, ArgValue);
- if (!ArgPtr) {
+ if (!ArgPtr.isValid()) {
CGF.ErrorUnsupported(E, "complex va_arg expression");
llvm::Type *EltTy =
CGF.ConvertType(E->getType()->castAs<ComplexType>()->getElementType());
@@ -1022,7 +1031,7 @@ ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
return ComplexPairTy(U, U);
}
- return EmitLoadOfLValue(CGF.MakeNaturalAlignAddrLValue(ArgPtr, E->getType()),
+ return EmitLoadOfLValue(CGF.MakeAddrLValue(ArgPtr, E->getType()),
E->getExprLoc());
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
index a15c151..ee049f1 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp
@@ -636,6 +636,8 @@ public:
}
llvm::Constant *VisitCastExpr(CastExpr* E) {
+ if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E))
+ CGM.EmitExplicitCastExprType(ECE, CGF);
Expr *subExpr = E->getSubExpr();
llvm::Constant *C = CGM.EmitConstantExpr(subExpr, subExpr->getType(), CGF);
if (!C) return nullptr;
@@ -733,6 +735,7 @@ public:
case CK_PointerToBoolean:
case CK_NullToPointer:
case CK_IntegralCast:
+ case CK_BooleanToSignedIntegral:
case CK_IntegralToPointer:
case CK_IntegralToBoolean:
case CK_IntegralToFloating:
@@ -977,23 +980,26 @@ public:
}
public:
- llvm::Constant *EmitLValue(APValue::LValueBase LVBase) {
+ ConstantAddress EmitLValue(APValue::LValueBase LVBase) {
if (const ValueDecl *Decl = LVBase.dyn_cast<const ValueDecl*>()) {
if (Decl->hasAttr<WeakRefAttr>())
return CGM.GetWeakRefReference(Decl);
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
- return CGM.GetAddrOfFunction(FD);
+ return ConstantAddress(CGM.GetAddrOfFunction(FD), CharUnits::One());
if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) {
// We can never refer to a variable with local storage.
if (!VD->hasLocalStorage()) {
+ CharUnits Align = CGM.getContext().getDeclAlign(VD);
if (VD->isFileVarDecl() || VD->hasExternalStorage())
- return CGM.GetAddrOfGlobalVar(VD);
- else if (VD->isLocalVarDecl())
- return CGM.getOrCreateStaticVarDecl(
+ return ConstantAddress(CGM.GetAddrOfGlobalVar(VD), Align);
+ else if (VD->isLocalVarDecl()) {
+ auto Ptr = CGM.getOrCreateStaticVarDecl(
*VD, CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false));
+ return ConstantAddress(Ptr, Align);
+ }
}
}
- return nullptr;
+ return ConstantAddress::invalid();
}
Expr *E = const_cast<Expr*>(LVBase.get<const Expr*>());
@@ -1006,14 +1012,18 @@ public:
llvm::Constant* C = CGM.EmitConstantExpr(CLE->getInitializer(),
CLE->getType(), CGF);
// FIXME: "Leaked" on failure.
- if (C)
- C = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
+ if (!C) return ConstantAddress::invalid();
+
+ CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType());
+
+ auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
E->getType().isConstant(CGM.getContext()),
llvm::GlobalValue::InternalLinkage,
C, ".compoundliteral", nullptr,
llvm::GlobalVariable::NotThreadLocal,
CGM.getContext().getTargetAddressSpace(E->getType()));
- return C;
+ GV->setAlignment(Align.getQuantity());
+ return ConstantAddress(GV, Align);
}
case Expr::StringLiteralClass:
return CGM.GetAddrOfConstantStringFromLiteral(cast<StringLiteral>(E));
@@ -1021,15 +1031,15 @@ public:
return CGM.GetAddrOfConstantStringFromObjCEncode(cast<ObjCEncodeExpr>(E));
case Expr::ObjCStringLiteralClass: {
ObjCStringLiteral* SL = cast<ObjCStringLiteral>(E);
- llvm::Constant *C =
+ ConstantAddress C =
CGM.getObjCRuntime().GenerateConstantString(SL->getString());
- return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
+ return C.getElementBitCast(ConvertType(E->getType()));
}
case Expr::PredefinedExprClass: {
unsigned Type = cast<PredefinedExpr>(E)->getIdentType();
if (CGF) {
LValue Res = CGF->EmitPredefinedLValue(cast<PredefinedExpr>(E));
- return cast<llvm::Constant>(Res.getAddress());
+ return cast<ConstantAddress>(Res.getAddress());
} else if (Type == PredefinedExpr::PrettyFunction) {
return CGM.GetAddrOfConstantCString("top level", ".tmp");
}
@@ -1040,7 +1050,8 @@ public:
assert(CGF && "Invalid address of label expression outside function.");
llvm::Constant *Ptr =
CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
- return llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType()));
+ Ptr = llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType()));
+ return ConstantAddress(Ptr, CharUnits::One());
}
case Expr::CallExprClass: {
CallExpr* CE = cast<CallExpr>(E);
@@ -1066,7 +1077,10 @@ public:
else
FunctionName = "global";
- return CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName.c_str());
+ // This is not really an l-value.
+ llvm::Constant *Ptr =
+ CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName.c_str());
+ return ConstantAddress(Ptr, CGM.getPointerAlign());
}
case Expr::CXXTypeidExprClass: {
CXXTypeidExpr *Typeid = cast<CXXTypeidExpr>(E);
@@ -1075,7 +1089,8 @@ public:
T = Typeid->getTypeOperand(CGM.getContext());
else
T = Typeid->getExprOperand()->getType();
- return CGM.GetAddrOfRTTIDescriptor(T);
+ return ConstantAddress(CGM.GetAddrOfRTTIDescriptor(T),
+ CGM.getPointerAlign());
}
case Expr::CXXUuidofExprClass: {
return CGM.GetAddrOfUuidDescriptor(cast<CXXUuidofExpr>(E));
@@ -1091,7 +1106,7 @@ public:
}
}
- return nullptr;
+ return ConstantAddress::invalid();
}
};
@@ -1255,7 +1270,7 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
llvm::Constant *Offset =
llvm::ConstantInt::get(Int64Ty, Value.getLValueOffset().getQuantity());
- llvm::Constant *C;
+ llvm::Constant *C = nullptr;
if (APValue::LValueBase LVBase = Value.getLValueBase()) {
// An array can be represented as an lvalue referring to the base.
if (isa<llvm::ArrayType>(DestTy)) {
@@ -1264,7 +1279,7 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
const_cast<Expr*>(LVBase.get<const Expr*>()));
}
- C = ConstExprEmitter(*this, CGF).EmitLValue(LVBase);
+ C = ConstExprEmitter(*this, CGF).EmitLValue(LVBase).getPointer();
// Apply offset if necessary.
if (!Offset->isNullValue()) {
@@ -1336,15 +1351,17 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
return llvm::ConstantStruct::get(STy, Complex);
}
case APValue::Vector: {
- SmallVector<llvm::Constant *, 4> Inits;
unsigned NumElts = Value.getVectorLength();
+ SmallVector<llvm::Constant *, 4> Inits(NumElts);
- for (unsigned i = 0; i != NumElts; ++i) {
- const APValue &Elt = Value.getVectorElt(i);
+ for (unsigned I = 0; I != NumElts; ++I) {
+ const APValue &Elt = Value.getVectorElt(I);
if (Elt.isInt())
- Inits.push_back(llvm::ConstantInt::get(VMContext, Elt.getInt()));
+ Inits[I] = llvm::ConstantInt::get(VMContext, Elt.getInt());
+ else if (Elt.isFloat())
+ Inits[I] = llvm::ConstantFP::get(VMContext, Elt.getFloat());
else
- Inits.push_back(llvm::ConstantFP::get(VMContext, Elt.getFloat()));
+ llvm_unreachable("unsupported vector element type");
}
return llvm::ConstantVector::get(Inits);
}
@@ -1438,7 +1455,7 @@ CodeGenModule::EmitConstantValueForMemory(const APValue &Value,
return C;
}
-llvm::Constant *
+ConstantAddress
CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) {
assert(E->isFileScope() && "not a file-scope compound literal expr");
return ConstExprEmitter(*this, nullptr).EmitLValue(E);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
index 74f6019..268e796 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExprScalar.cpp
@@ -140,21 +140,25 @@ public:
/// boolean (i1) truth value. This is equivalent to "Val != 0".
Value *EmitConversionToBool(Value *Src, QualType DstTy);
- /// \brief Emit a check that a conversion to or from a floating-point type
- /// does not overflow.
+ /// Emit a check that a conversion to or from a floating-point type does not
+ /// overflow.
void EmitFloatConversionCheck(Value *OrigSrc, QualType OrigSrcType,
- Value *Src, QualType SrcType,
- QualType DstType, llvm::Type *DstTy);
+ Value *Src, QualType SrcType, QualType DstType,
+ llvm::Type *DstTy, SourceLocation Loc);
- /// EmitScalarConversion - Emit a conversion from the specified type to the
- /// specified destination type, both of which are LLVM scalar types.
- Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy);
+ /// Emit a conversion from the specified type to the specified destination
+ /// type, both of which are LLVM scalar types.
+ Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
+ SourceLocation Loc);
- /// EmitComplexToScalarConversion - Emit a conversion from the specified
- /// complex type to the specified destination type, where the destination type
- /// is an LLVM scalar type.
+ Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
+ SourceLocation Loc, bool TreatBooleanAsSigned);
+
+ /// Emit a conversion from the specified complex type to the specified
+ /// destination type, where the destination type is an LLVM scalar type.
Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
- QualType SrcTy, QualType DstTy);
+ QualType SrcTy, QualType DstTy,
+ SourceLocation Loc);
/// EmitNullValue - Emit a value that corresponds to null for the given type.
Value *EmitNullValue(QualType Ty);
@@ -310,12 +314,7 @@ public:
return EmitNullValue(E->getType());
}
Value *VisitExplicitCastExpr(ExplicitCastExpr *E) {
- if (E->getType()->isVariablyModifiedType())
- CGF.EmitVariablyModifiedType(E->getType());
-
- if (CGDebugInfo *DI = CGF.getDebugInfo())
- DI->EmitExplicitCastType(E->getType());
-
+ CGF.CGM.EmitExplicitCastExprType(E, &CGF);
return VisitCastExpr(E);
}
Value *VisitCastExpr(CastExpr *E);
@@ -362,7 +361,7 @@ public:
if (isa<MemberPointerType>(E->getType())) // never sugared
return CGF.CGM.getMemberPointerConstant(E);
- return EmitLValue(E->getSubExpr()).getAddress();
+ return EmitLValue(E->getSubExpr()).getPointer();
}
Value *VisitUnaryDeref(const UnaryOperator *E) {
if (E->getType()->isVoidType())
@@ -524,8 +523,9 @@ public:
#undef HANDLEBINOP
// Comparisons.
- Value *EmitCompare(const BinaryOperator *E, unsigned UICmpOpc,
- unsigned SICmpOpc, unsigned FCmpOpc);
+ Value *EmitCompare(const BinaryOperator *E, llvm::CmpInst::Predicate UICmpOpc,
+ llvm::CmpInst::Predicate SICmpOpc,
+ llvm::CmpInst::Predicate FCmpOpc);
#define VISITCOMP(CODE, UI, SI, FP) \
Value *VisitBin##CODE(const BinaryOperator *E) { \
return EmitCompare(E, llvm::ICmpInst::UI, llvm::ICmpInst::SI, \
@@ -594,11 +594,9 @@ Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
return EmitPointerToBoolConversion(Src);
}
-void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc,
- QualType OrigSrcType,
- Value *Src, QualType SrcType,
- QualType DstType,
- llvm::Type *DstTy) {
+void ScalarExprEmitter::EmitFloatConversionCheck(
+ Value *OrigSrc, QualType OrigSrcType, Value *Src, QualType SrcType,
+ QualType DstType, llvm::Type *DstTy, SourceLocation Loc) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
using llvm::APFloat;
using llvm::APSInt;
@@ -722,19 +720,25 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc,
}
}
- // FIXME: Provide a SourceLocation.
- llvm::Constant *StaticArgs[] = {
- CGF.EmitCheckTypeDescriptor(OrigSrcType),
- CGF.EmitCheckTypeDescriptor(DstType)
- };
+ llvm::Constant *StaticArgs[] = {CGF.EmitCheckSourceLocation(Loc),
+ CGF.EmitCheckTypeDescriptor(OrigSrcType),
+ CGF.EmitCheckTypeDescriptor(DstType)};
CGF.EmitCheck(std::make_pair(Check, SanitizerKind::FloatCastOverflow),
"float_cast_overflow", StaticArgs, OrigSrc);
}
-/// EmitScalarConversion - Emit a conversion from the specified type to the
-/// specified destination type, both of which are LLVM scalar types.
+/// Emit a conversion from the specified type to the specified destination type,
+/// both of which are LLVM scalar types.
+Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
+ QualType DstType,
+ SourceLocation Loc) {
+ return EmitScalarConversion(Src, SrcType, DstType, Loc, false);
+}
+
Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
- QualType DstType) {
+ QualType DstType,
+ SourceLocation Loc,
+ bool TreatBooleanAsSigned) {
SrcType = CGF.getContext().getCanonicalType(SrcType);
DstType = CGF.getContext().getCanonicalType(DstType);
if (SrcType == DstType) return Src;
@@ -807,13 +811,15 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
// A scalar can be splatted to an extended vector of the same element type
if (DstType->isExtVectorType() && !SrcType->isVectorType()) {
- // Cast the scalar to element type
- QualType EltTy = DstType->getAs<ExtVectorType>()->getElementType();
- llvm::Value *Elt = EmitScalarConversion(Src, SrcType, EltTy);
+ // Sema should add casts to make sure that the source expression's type is
+ // the same as the vector's element type (sans qualifiers)
+ assert(DstType->castAs<ExtVectorType>()->getElementType().getTypePtr() ==
+ SrcType.getTypePtr() &&
+ "Splatted expr doesn't match with vector element type?");
// Splat the element across to all elements
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
- return Builder.CreateVectorSplat(NumElements, Elt, "splat");
+ return Builder.CreateVectorSplat(NumElements, Src, "splat");
}
// Allow bitcast from vector to integer/fp of the same size.
@@ -829,8 +835,8 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
// or the destination type is a floating-point type.
if (CGF.SanOpts.has(SanitizerKind::FloatCastOverflow) &&
(OrigSrcType->isFloatingType() || DstType->isFloatingType()))
- EmitFloatConversionCheck(OrigSrc, OrigSrcType, Src, SrcType, DstType,
- DstTy);
+ EmitFloatConversionCheck(OrigSrc, OrigSrcType, Src, SrcType, DstType, DstTy,
+ Loc);
// Cast to half through float if half isn't a native type.
if (DstType->isHalfType() && !CGF.getContext().getLangOpts().NativeHalfType) {
@@ -849,6 +855,9 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
if (isa<llvm::IntegerType>(SrcTy)) {
bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
+ if (SrcType->isBooleanType() && TreatBooleanAsSigned) {
+ InputSigned = true;
+ }
if (isa<llvm::IntegerType>(DstTy))
Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
else if (InputSigned)
@@ -884,20 +893,19 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
return Res;
}
-/// EmitComplexToScalarConversion - Emit a conversion from the specified complex
-/// type to the specified destination type, where the destination type is an
-/// LLVM scalar type.
-Value *ScalarExprEmitter::
-EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
- QualType SrcTy, QualType DstTy) {
+/// Emit a conversion from the specified complex type to the specified
+/// destination type, where the destination type is an LLVM scalar type.
+Value *ScalarExprEmitter::EmitComplexToScalarConversion(
+ CodeGenFunction::ComplexPairTy Src, QualType SrcTy, QualType DstTy,
+ SourceLocation Loc) {
// Get the source element type.
SrcTy = SrcTy->castAs<ComplexType>()->getElementType();
// Handle conversions to bool first, they are special: comparisons against 0.
if (DstTy->isBooleanType()) {
// Complex != 0 -> (Real != 0) | (Imag != 0)
- Src.first = EmitScalarConversion(Src.first, SrcTy, DstTy);
- Src.second = EmitScalarConversion(Src.second, SrcTy, DstTy);
+ Src.first = EmitScalarConversion(Src.first, SrcTy, DstTy, Loc);
+ Src.second = EmitScalarConversion(Src.second, SrcTy, DstTy, Loc);
return Builder.CreateOr(Src.first, Src.second, "tobool");
}
@@ -905,7 +913,7 @@ EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
// the imaginary part of the complex value is discarded and the value of the
// real part is converted according to the conversion rules for the
// corresponding real type.
- return EmitScalarConversion(Src.first, SrcTy, DstTy);
+ return EmitScalarConversion(Src.first, SrcTy, DstTy, Loc);
}
Value *ScalarExprEmitter::EmitNullValue(QualType Ty) {
@@ -1003,14 +1011,10 @@ Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
}
llvm::VectorType *MTy = cast<llvm::VectorType>(Mask->getType());
- llvm::Constant* EltMask;
-
- EltMask = llvm::ConstantInt::get(MTy->getElementType(),
- llvm::NextPowerOf2(LHSElts-1)-1);
// Mask off the high bits of each shuffle index.
- Value *MaskBits = llvm::ConstantVector::getSplat(MTy->getNumElements(),
- EltMask);
+ Value *MaskBits =
+ llvm::ConstantInt::get(MTy, llvm::NextPowerOf2(LHSElts - 1) - 1);
Mask = Builder.CreateAnd(Mask, MaskBits, "mask");
// newv = undef
@@ -1334,13 +1338,13 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
return V;
}
-static bool ShouldNullCheckClassCastValue(const CastExpr *CE) {
+bool CodeGenFunction::ShouldNullCheckClassCastValue(const CastExpr *CE) {
const Expr *E = CE->getSubExpr();
if (CE->getCastKind() == CK_UncheckedDerivedToBase)
return false;
- if (isa<CXXThisExpr>(E)) {
+ if (isa<CXXThisExpr>(E->IgnoreParens())) {
// We always assume that 'this' is never null.
return false;
}
@@ -1375,11 +1379,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
case CK_LValueBitCast:
case CK_ObjCObjectLValueCast: {
- Value *V = EmitLValue(E).getAddress();
- V = Builder.CreateBitCast(V,
- ConvertType(CGF.getContext().getPointerType(DestTy)));
- return EmitLoadOfLValue(CGF.MakeNaturalAlignAddrLValue(V, DestTy),
- CE->getExprLoc());
+ Address Addr = EmitLValue(E).getAddress();
+ Addr = Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(DestTy));
+ LValue LV = CGF.MakeAddrLValue(Addr, DestTy);
+ return EmitLoadOfLValue(LV, CE->getExprLoc());
}
case CK_CPointerToObjCPointerCast:
@@ -1419,68 +1422,44 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
const CXXRecordDecl *DerivedClassDecl = DestTy->getPointeeCXXRecordDecl();
assert(DerivedClassDecl && "BaseToDerived arg isn't a C++ object pointer!");
- llvm::Value *V = Visit(E);
-
- llvm::Value *Derived =
- CGF.GetAddressOfDerivedClass(V, DerivedClassDecl,
+ Address Base = CGF.EmitPointerWithAlignment(E);
+ Address Derived =
+ CGF.GetAddressOfDerivedClass(Base, DerivedClassDecl,
CE->path_begin(), CE->path_end(),
- ShouldNullCheckClassCastValue(CE));
+ CGF.ShouldNullCheckClassCastValue(CE));
// C++11 [expr.static.cast]p11: Behavior is undefined if a downcast is
// performed and the object is not of the derived type.
if (CGF.sanitizePerformTypeCheck())
CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(),
- Derived, DestTy->getPointeeType());
+ Derived.getPointer(), DestTy->getPointeeType());
if (CGF.SanOpts.has(SanitizerKind::CFIDerivedCast))
- CGF.EmitVTablePtrCheckForCast(DestTy->getPointeeType(), Derived,
+ CGF.EmitVTablePtrCheckForCast(DestTy->getPointeeType(),
+ Derived.getPointer(),
/*MayBeNull=*/true,
CodeGenFunction::CFITCK_DerivedCast,
CE->getLocStart());
- return Derived;
+ return Derived.getPointer();
}
case CK_UncheckedDerivedToBase:
case CK_DerivedToBase: {
- const CXXRecordDecl *DerivedClassDecl =
- E->getType()->getPointeeCXXRecordDecl();
- assert(DerivedClassDecl && "DerivedToBase arg isn't a C++ object pointer!");
-
- return CGF.GetAddressOfBaseClass(
- Visit(E), DerivedClassDecl, CE->path_begin(), CE->path_end(),
- ShouldNullCheckClassCastValue(CE), CE->getExprLoc());
+ // The EmitPointerWithAlignment path does this fine; just discard
+ // the alignment.
+ return CGF.EmitPointerWithAlignment(CE).getPointer();
}
+
case CK_Dynamic: {
- Value *V = Visit(const_cast<Expr*>(E));
+ Address V = CGF.EmitPointerWithAlignment(E);
const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(CE);
return CGF.EmitDynamicCast(V, DCE);
}
- case CK_ArrayToPointerDecay: {
- assert(E->getType()->isArrayType() &&
- "Array to pointer decay must have array source type!");
-
- Value *V = EmitLValue(E).getAddress(); // Bitfields can't be arrays.
-
- // Note that VLA pointers are always decayed, so we don't need to do
- // anything here.
- if (!E->getType()->isVariableArrayType()) {
- assert(isa<llvm::PointerType>(V->getType()) && "Expected pointer");
- llvm::Type *NewTy = ConvertType(E->getType());
- V = CGF.Builder.CreatePointerCast(
- V, NewTy->getPointerTo(V->getType()->getPointerAddressSpace()));
-
- assert(isa<llvm::ArrayType>(V->getType()->getPointerElementType()) &&
- "Expected pointer to array");
- V = Builder.CreateStructGEP(NewTy, V, 0, "arraydecay");
- }
-
- // Make sure the array decay ends up being the right type. This matters if
- // the array type was of an incomplete type.
- return CGF.Builder.CreatePointerCast(V, ConvertType(CE->getType()));
- }
+ case CK_ArrayToPointerDecay:
+ return CGF.EmitArrayToPointerDecay(E).getPointer();
case CK_FunctionToPointerDecay:
- return EmitLValue(E).getAddress();
+ return EmitLValue(E).getPointer();
case CK_NullToPointer:
if (MustVisitNullValue(E))
@@ -1564,9 +1543,6 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
case CK_VectorSplat: {
llvm::Type *DstTy = ConvertType(DestTy);
Value *Elt = Visit(const_cast<Expr*>(E));
- Elt = EmitScalarConversion(Elt, E->getType(),
- DestTy->getAs<VectorType>()->getElementType());
-
// Splat the element across to all elements
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
return Builder.CreateVectorSplat(NumElements, Elt, "splat");
@@ -1576,7 +1552,12 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
case CK_FloatingCast:
- return EmitScalarConversion(Visit(E), E->getType(), DestTy);
+ return EmitScalarConversion(Visit(E), E->getType(), DestTy,
+ CE->getExprLoc());
+ case CK_BooleanToSignedIntegral:
+ return EmitScalarConversion(Visit(E), E->getType(), DestTy,
+ CE->getExprLoc(),
+ /*TreatBooleanAsSigned=*/true);
case CK_IntegralToBoolean:
return EmitIntToBoolConversion(Visit(E));
case CK_PointerToBoolean:
@@ -1598,7 +1579,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
CodeGenFunction::ComplexPairTy V = CGF.EmitComplexExpr(E);
// TODO: kill this function off, inline appropriate case here
- return EmitComplexToScalarConversion(V, E->getType(), DestTy);
+ return EmitComplexToScalarConversion(V, E->getType(), DestTy,
+ CE->getExprLoc());
}
case CK_ZeroToOCLEvent: {
@@ -1613,9 +1595,9 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) {
CodeGenFunction::StmtExprEvaluation eval(CGF);
- llvm::Value *RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(),
- !E->getType()->isVoidType());
- if (!RetAlloca)
+ Address RetAlloca = CGF.EmitCompoundStmt(*E->getSubStmt(),
+ !E->getType()->isVoidType());
+ if (!RetAlloca.isValid())
return nullptr;
return CGF.EmitLoadOfScalar(CGF.MakeAddrLValue(RetAlloca, E->getType()),
E->getExprLoc());
@@ -1671,16 +1653,14 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
if (isInc && type->isBooleanType()) {
llvm::Value *True = CGF.EmitToMemory(Builder.getTrue(), type);
if (isPre) {
- Builder.Insert(new llvm::StoreInst(True,
- LV.getAddress(), LV.isVolatileQualified(),
- LV.getAlignment().getQuantity(),
- llvm::SequentiallyConsistent));
+ Builder.CreateStore(True, LV.getAddress(), LV.isVolatileQualified())
+ ->setAtomic(llvm::SequentiallyConsistent);
return Builder.getTrue();
}
// For atomic bool increment, we just store true and return it for
// preincrement, do an atomic swap with true for postincrement
return Builder.CreateAtomicRMW(llvm::AtomicRMWInst::Xchg,
- LV.getAddress(), True, llvm::SequentiallyConsistent);
+ LV.getPointer(), True, llvm::SequentiallyConsistent);
}
// Special case for atomic increment / decrement on integers, emit
// atomicrmw instructions. We skip this if we want to be doing overflow
@@ -1697,7 +1677,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
llvm::Value *amt = CGF.EmitToMemory(
llvm::ConstantInt::get(ConvertType(type), 1, true), type);
llvm::Value *old = Builder.CreateAtomicRMW(aop,
- LV.getAddress(), amt, llvm::SequentiallyConsistent);
+ LV.getPointer(), amt, llvm::SequentiallyConsistent);
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
}
value = EmitLoadOfLValue(LV, E->getExprLoc());
@@ -1941,10 +1921,10 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
llvm::Value* Result = llvm::Constant::getNullValue(ResultType);
QualType CurrentType = E->getTypeSourceInfo()->getType();
for (unsigned i = 0; i != n; ++i) {
- OffsetOfExpr::OffsetOfNode ON = E->getComponent(i);
+ OffsetOfNode ON = E->getComponent(i);
llvm::Value *Offset = nullptr;
switch (ON.getKind()) {
- case OffsetOfExpr::OffsetOfNode::Array: {
+ case OffsetOfNode::Array: {
// Compute the index
Expr *IdxExpr = E->getIndexExpr(ON.getArrayExprIndex());
llvm::Value* Idx = CGF.EmitScalarExpr(IdxExpr);
@@ -1964,7 +1944,7 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
break;
}
- case OffsetOfExpr::OffsetOfNode::Field: {
+ case OffsetOfNode::Field: {
FieldDecl *MemberDecl = ON.getField();
RecordDecl *RD = CurrentType->getAs<RecordType>()->getDecl();
const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);
@@ -1990,10 +1970,10 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
break;
}
- case OffsetOfExpr::OffsetOfNode::Identifier:
+ case OffsetOfNode::Identifier:
llvm_unreachable("dependent __builtin_offsetof");
- case OffsetOfExpr::OffsetOfNode::Base: {
+ case OffsetOfNode::Base: {
if (ON.getBase()->isVirtual()) {
CGF.ErrorUnsupported(E, "virtual base in offsetof");
continue;
@@ -2134,7 +2114,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
OpInfo.RHS = Visit(E->getRHS());
OpInfo.Ty = E->getComputationResultType();
OpInfo.Opcode = E->getOpcode();
- OpInfo.FPContractable = false;
+ OpInfo.FPContractable = E->isFPContractable();
OpInfo.E = E;
// Load/convert the LHS.
LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);
@@ -2174,9 +2154,11 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
llvm_unreachable("Invalid compound assignment type");
}
if (aop != llvm::AtomicRMWInst::BAD_BINOP) {
- llvm::Value *amt = CGF.EmitToMemory(EmitScalarConversion(OpInfo.RHS,
- E->getRHS()->getType(), LHSTy), LHSTy);
- Builder.CreateAtomicRMW(aop, LHSLV.getAddress(), amt,
+ llvm::Value *amt = CGF.EmitToMemory(
+ EmitScalarConversion(OpInfo.RHS, E->getRHS()->getType(), LHSTy,
+ E->getExprLoc()),
+ LHSTy);
+ Builder.CreateAtomicRMW(aop, LHSLV.getPointer(), amt,
llvm::SequentiallyConsistent);
return LHSLV;
}
@@ -2196,14 +2178,16 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
else
OpInfo.LHS = EmitLoadOfLValue(LHSLV, E->getExprLoc());
- OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy,
- E->getComputationLHSType());
+ SourceLocation Loc = E->getExprLoc();
+ OpInfo.LHS =
+ EmitScalarConversion(OpInfo.LHS, LHSTy, E->getComputationLHSType(), Loc);
// Expand the binary operator.
Result = (this->*Func)(OpInfo);
// Convert the result back to the LHS type.
- Result = EmitScalarConversion(Result, E->getComputationResultType(), LHSTy);
+ Result =
+ EmitScalarConversion(Result, E->getComputationResultType(), LHSTy, Loc);
if (atomicPHI) {
llvm::BasicBlock *opBB = Builder.GetInsertBlock();
@@ -2389,9 +2373,9 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
// Branch in case of overflow.
llvm::BasicBlock *initialBB = Builder.GetInsertBlock();
- llvm::Function::iterator insertPt = initialBB;
+ llvm::Function::iterator insertPt = initialBB->getIterator();
llvm::BasicBlock *continueBB = CGF.createBasicBlock("nooverflow", CGF.CurFn,
- std::next(insertPt));
+ &*std::next(insertPt));
llvm::BasicBlock *overflowBB = CGF.createBasicBlock("overflow", CGF.CurFn);
Builder.CreateCondBr(overflow, overflowBB, continueBB);
@@ -2578,19 +2562,17 @@ static Value* tryEmitFMulAdd(const BinOpInfo &op,
return nullptr;
// We have a potentially fusable op. Look for a mul on one of the operands.
- if (llvm::BinaryOperator* LHSBinOp = dyn_cast<llvm::BinaryOperator>(op.LHS)) {
- if (LHSBinOp->getOpcode() == llvm::Instruction::FMul) {
- assert(LHSBinOp->getNumUses() == 0 &&
- "Operations with multiple uses shouldn't be contracted.");
+ // Also, make sure that the mul result isn't used directly. In that case,
+ // there's no point creating a muladd operation.
+ if (auto *LHSBinOp = dyn_cast<llvm::BinaryOperator>(op.LHS)) {
+ if (LHSBinOp->getOpcode() == llvm::Instruction::FMul &&
+ LHSBinOp->use_empty())
return buildFMulAdd(LHSBinOp, op.RHS, CGF, Builder, false, isSub);
- }
- } else if (llvm::BinaryOperator* RHSBinOp =
- dyn_cast<llvm::BinaryOperator>(op.RHS)) {
- if (RHSBinOp->getOpcode() == llvm::Instruction::FMul) {
- assert(RHSBinOp->getNumUses() == 0 &&
- "Operations with multiple uses shouldn't be contracted.");
+ }
+ if (auto *RHSBinOp = dyn_cast<llvm::BinaryOperator>(op.RHS)) {
+ if (RHSBinOp->getOpcode() == llvm::Instruction::FMul &&
+ RHSBinOp->use_empty())
return buildFMulAdd(RHSBinOp, op.LHS, CGF, Builder, isSub, false);
- }
}
return nullptr;
@@ -2848,8 +2830,10 @@ static llvm::Intrinsic::ID GetIntrinsic(IntrinsicType IT,
}
}
-Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
- unsigned SICmpOpc, unsigned FCmpOpc) {
+Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,
+ llvm::CmpInst::Predicate UICmpOpc,
+ llvm::CmpInst::Predicate SICmpOpc,
+ llvm::CmpInst::Predicate FCmpOpc) {
TestAndClearIgnoreResultAssign();
Value *Result;
QualType LHSTy = E->getLHS()->getType();
@@ -2927,19 +2911,17 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
Value *CR6Param = Builder.getInt32(CR6);
llvm::Function *F = CGF.CGM.getIntrinsic(ID);
Result = Builder.CreateCall(F, {CR6Param, FirstVecArg, SecondVecArg});
- return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType());
+ return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType(),
+ E->getExprLoc());
}
if (LHS->getType()->isFPOrFPVectorTy()) {
- Result = Builder.CreateFCmp((llvm::CmpInst::Predicate)FCmpOpc,
- LHS, RHS, "cmp");
+ Result = Builder.CreateFCmp(FCmpOpc, LHS, RHS, "cmp");
} else if (LHSTy->hasSignedIntegerRepresentation()) {
- Result = Builder.CreateICmp((llvm::ICmpInst::Predicate)SICmpOpc,
- LHS, RHS, "cmp");
+ Result = Builder.CreateICmp(SICmpOpc, LHS, RHS, "cmp");
} else {
// Unsigned integers and pointers.
- Result = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
- LHS, RHS, "cmp");
+ Result = Builder.CreateICmp(UICmpOpc, LHS, RHS, "cmp");
}
// If this is a vector comparison, sign extend the result to the appropriate
@@ -2974,17 +2956,13 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
Value *ResultR, *ResultI;
if (CETy->isRealFloatingType()) {
- ResultR = Builder.CreateFCmp((llvm::FCmpInst::Predicate)FCmpOpc,
- LHS.first, RHS.first, "cmp.r");
- ResultI = Builder.CreateFCmp((llvm::FCmpInst::Predicate)FCmpOpc,
- LHS.second, RHS.second, "cmp.i");
+ ResultR = Builder.CreateFCmp(FCmpOpc, LHS.first, RHS.first, "cmp.r");
+ ResultI = Builder.CreateFCmp(FCmpOpc, LHS.second, RHS.second, "cmp.i");
} else {
// Complex comparisons can only be equality comparisons. As such, signed
// and unsigned opcodes are the same.
- ResultR = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
- LHS.first, RHS.first, "cmp.r");
- ResultI = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
- LHS.second, RHS.second, "cmp.i");
+ ResultR = Builder.CreateICmp(UICmpOpc, LHS.first, RHS.first, "cmp.r");
+ ResultI = Builder.CreateICmp(UICmpOpc, LHS.second, RHS.second, "cmp.i");
}
if (E->getOpcode() == BO_EQ) {
@@ -2996,7 +2974,8 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
}
}
- return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType());
+ return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType(),
+ E->getExprLoc());
}
Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
@@ -3382,13 +3361,14 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
if (Ty->isVariablyModifiedType())
CGF.EmitVariablyModifiedType(Ty);
- llvm::Value *ArgValue = CGF.EmitVAListRef(VE->getSubExpr());
- llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType());
+ Address ArgValue = Address::invalid();
+ Address ArgPtr = CGF.EmitVAArg(VE, ArgValue);
+
llvm::Type *ArgTy = ConvertType(VE->getType());
// If EmitVAArg fails, we fall back to the LLVM instruction.
- if (!ArgPtr)
- return Builder.CreateVAArg(ArgValue, ArgTy);
+ if (!ArgPtr.isValid())
+ return Builder.CreateVAArg(ArgValue.getPointer(), ArgTy);
// FIXME Volatility.
llvm::Value *Val = Builder.CreateLoad(ArgPtr);
@@ -3465,8 +3445,8 @@ Value *ScalarExprEmitter::VisitAtomicExpr(AtomicExpr *E) {
// Entry Point into this File
//===----------------------------------------------------------------------===//
-/// EmitScalarExpr - Emit the computation of the specified expression of scalar
-/// type, ignoring the result.
+/// Emit the computation of the specified expression of scalar type, ignoring
+/// the result.
Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) {
assert(E && hasScalarEvaluationKind(E->getType()) &&
"Invalid scalar expression to emit");
@@ -3475,25 +3455,26 @@ Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) {
.Visit(const_cast<Expr *>(E));
}
-/// EmitScalarConversion - Emit a conversion from the specified type to the
-/// specified destination type, both of which are LLVM scalar types.
+/// Emit a conversion from the specified type to the specified destination type,
+/// both of which are LLVM scalar types.
Value *CodeGenFunction::EmitScalarConversion(Value *Src, QualType SrcTy,
- QualType DstTy) {
+ QualType DstTy,
+ SourceLocation Loc) {
assert(hasScalarEvaluationKind(SrcTy) && hasScalarEvaluationKind(DstTy) &&
"Invalid scalar expression to emit");
- return ScalarExprEmitter(*this).EmitScalarConversion(Src, SrcTy, DstTy);
+ return ScalarExprEmitter(*this).EmitScalarConversion(Src, SrcTy, DstTy, Loc);
}
-/// EmitComplexToScalarConversion - Emit a conversion from the specified complex
-/// type to the specified destination type, where the destination type is an
-/// LLVM scalar type.
+/// Emit a conversion from the specified complex type to the specified
+/// destination type, where the destination type is an LLVM scalar type.
Value *CodeGenFunction::EmitComplexToScalarConversion(ComplexPairTy Src,
QualType SrcTy,
- QualType DstTy) {
+ QualType DstTy,
+ SourceLocation Loc) {
assert(SrcTy->isAnyComplexType() && hasScalarEvaluationKind(DstTy) &&
"Invalid complex -> scalar conversion");
- return ScalarExprEmitter(*this).EmitComplexToScalarConversion(Src, SrcTy,
- DstTy);
+ return ScalarExprEmitter(*this)
+ .EmitComplexToScalarConversion(Src, SrcTy, DstTy, Loc);
}
@@ -3504,30 +3485,20 @@ EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
}
LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) {
- llvm::Value *V;
// object->isa or (*object).isa
// Generate code as for: *(Class*)object
- // build Class* type
- llvm::Type *ClassPtrTy = ConvertType(E->getType());
Expr *BaseExpr = E->getBase();
+ Address Addr = Address::invalid();
if (BaseExpr->isRValue()) {
- V = CreateMemTemp(E->getType(), "resval");
- llvm::Value *Src = EmitScalarExpr(BaseExpr);
- Builder.CreateStore(Src, V);
- V = ScalarExprEmitter(*this).EmitLoadOfLValue(
- MakeNaturalAlignAddrLValue(V, E->getType()), E->getExprLoc());
+ Addr = Address(EmitScalarExpr(BaseExpr), getPointerAlign());
} else {
- if (E->isArrow())
- V = ScalarExprEmitter(*this).EmitLoadOfLValue(BaseExpr);
- else
- V = EmitLValue(BaseExpr).getAddress();
+ Addr = EmitLValue(BaseExpr).getAddress();
}
- // build Class* type
- ClassPtrTy = ClassPtrTy->getPointerTo();
- V = Builder.CreateBitCast(V, ClassPtrTy);
- return MakeNaturalAlignAddrLValue(V, E->getType());
+ // Cast the address to Class*.
+ Addr = Builder.CreateElementBitCast(Addr, ConvertType(E->getType()));
+ return MakeAddrLValue(Addr, E->getType());
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp
index 1163d63..0afe7db 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "CGLoopInfo.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/Sema/LoopHint.h"
#include "llvm/IR/BasicBlock.h"
@@ -20,9 +21,10 @@ using namespace llvm;
static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
- if (!Attrs.IsParallel && Attrs.VectorizerWidth == 0 &&
- Attrs.VectorizerUnroll == 0 &&
- Attrs.VectorizerEnable == LoopAttributes::VecUnspecified)
+ if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
+ Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
+ Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
+ Attrs.UnrollEnable == LoopAttributes::Unspecified)
return nullptr;
SmallVector<Metadata *, 4> Args;
@@ -30,29 +32,49 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
auto TempNode = MDNode::getTemporary(Ctx, None);
Args.push_back(TempNode.get());
- // Setting vectorizer.width
- if (Attrs.VectorizerWidth > 0) {
+ // Setting vectorize.width
+ if (Attrs.VectorizeWidth > 0) {
Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
ConstantAsMetadata::get(ConstantInt::get(
- Type::getInt32Ty(Ctx), Attrs.VectorizerWidth))};
+ Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
Args.push_back(MDNode::get(Ctx, Vals));
}
- // Setting vectorizer.unroll
- if (Attrs.VectorizerUnroll > 0) {
+ // Setting interleave.count
+ if (Attrs.InterleaveCount > 0) {
Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
ConstantAsMetadata::get(ConstantInt::get(
- Type::getInt32Ty(Ctx), Attrs.VectorizerUnroll))};
+ Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
Args.push_back(MDNode::get(Ctx, Vals));
}
- // Setting vectorizer.enable
- if (Attrs.VectorizerEnable != LoopAttributes::VecUnspecified) {
- Metadata *Vals[] = {
- MDString::get(Ctx, "llvm.loop.vectorize.enable"),
- ConstantAsMetadata::get(ConstantInt::get(
- Type::getInt1Ty(Ctx),
- (Attrs.VectorizerEnable == LoopAttributes::VecEnable)))};
+ // Setting interleave.count
+ if (Attrs.UnrollCount > 0) {
+ Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
+ ConstantAsMetadata::get(ConstantInt::get(
+ Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
+ Args.push_back(MDNode::get(Ctx, Vals));
+ }
+
+ // Setting vectorize.enable
+ if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
+ Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
+ ConstantAsMetadata::get(ConstantInt::get(
+ Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable ==
+ LoopAttributes::Enable)))};
+ Args.push_back(MDNode::get(Ctx, Vals));
+ }
+
+ // Setting unroll.full or unroll.disable
+ if (Attrs.UnrollEnable != LoopAttributes::Unspecified) {
+ std::string Name;
+ if (Attrs.UnrollEnable == LoopAttributes::Enable)
+ Name = "llvm.loop.unroll.enable";
+ else if (Attrs.UnrollEnable == LoopAttributes::Full)
+ Name = "llvm.loop.unroll.full";
+ else
+ Name = "llvm.loop.unroll.disable";
+ Metadata *Vals[] = {MDString::get(Ctx, Name)};
Args.push_back(MDNode::get(Ctx, Vals));
}
@@ -63,14 +85,17 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
}
LoopAttributes::LoopAttributes(bool IsParallel)
- : IsParallel(IsParallel), VectorizerEnable(LoopAttributes::VecUnspecified),
- VectorizerWidth(0), VectorizerUnroll(0) {}
+ : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
+ UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
+ InterleaveCount(0), UnrollCount(0) {}
void LoopAttributes::clear() {
IsParallel = false;
- VectorizerWidth = 0;
- VectorizerUnroll = 0;
- VectorizerEnable = LoopAttributes::VecUnspecified;
+ VectorizeWidth = 0;
+ InterleaveCount = 0;
+ UnrollCount = 0;
+ VectorizeEnable = LoopAttributes::Unspecified;
+ UnrollEnable = LoopAttributes::Unspecified;
}
LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
@@ -78,8 +103,16 @@ LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
LoopID = createMetadata(Header->getContext(), Attrs);
}
-void LoopInfoStack::push(BasicBlock *Header,
+void LoopInfoStack::push(BasicBlock *Header) {
+ Active.push_back(LoopInfo(Header, StagedAttrs));
+ // Clear the attributes so nested loops do not inherit them.
+ StagedAttrs.clear();
+}
+
+void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
ArrayRef<const clang::Attr *> Attrs) {
+
+ // Identify loop hint attributes from Attrs.
for (const auto *Attr : Attrs) {
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
@@ -87,28 +120,105 @@ void LoopInfoStack::push(BasicBlock *Header,
if (!LH)
continue;
+ auto *ValueExpr = LH->getValue();
+ unsigned ValueInt = 1;
+ if (ValueExpr) {
+ llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
+ ValueInt = ValueAPS.getSExtValue();
+ }
+
LoopHintAttr::OptionType Option = LH->getOption();
LoopHintAttr::LoopHintState State = LH->getState();
- switch (Option) {
- case LoopHintAttr::Vectorize:
- case LoopHintAttr::Interleave:
- if (State == LoopHintAttr::AssumeSafety) {
+ switch (State) {
+ case LoopHintAttr::Disable:
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ // Disable vectorization by specifying a width of 1.
+ setVectorizeWidth(1);
+ break;
+ case LoopHintAttr::Interleave:
+ // Disable interleaving by speciyfing a count of 1.
+ setInterleaveCount(1);
+ break;
+ case LoopHintAttr::Unroll:
+ setUnrollState(LoopAttributes::Disable);
+ break;
+ case LoopHintAttr::UnrollCount:
+ case LoopHintAttr::VectorizeWidth:
+ case LoopHintAttr::InterleaveCount:
+ llvm_unreachable("Options cannot be disabled.");
+ break;
+ }
+ break;
+ case LoopHintAttr::Enable:
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::Interleave:
+ setVectorizeEnable(true);
+ break;
+ case LoopHintAttr::Unroll:
+ setUnrollState(LoopAttributes::Enable);
+ break;
+ case LoopHintAttr::UnrollCount:
+ case LoopHintAttr::VectorizeWidth:
+ case LoopHintAttr::InterleaveCount:
+ llvm_unreachable("Options cannot enabled.");
+ break;
+ }
+ break;
+ case LoopHintAttr::AssumeSafety:
+ switch (Option) {
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::Interleave:
// Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
setParallel(true);
+ setVectorizeEnable(true);
+ break;
+ case LoopHintAttr::Unroll:
+ case LoopHintAttr::UnrollCount:
+ case LoopHintAttr::VectorizeWidth:
+ case LoopHintAttr::InterleaveCount:
+ llvm_unreachable("Options cannot be used to assume mem safety.");
+ break;
+ }
+ break;
+ case LoopHintAttr::Full:
+ switch (Option) {
+ case LoopHintAttr::Unroll:
+ setUnrollState(LoopAttributes::Full);
+ break;
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::Interleave:
+ case LoopHintAttr::UnrollCount:
+ case LoopHintAttr::VectorizeWidth:
+ case LoopHintAttr::InterleaveCount:
+ llvm_unreachable("Options cannot be used with 'full' hint.");
+ break;
}
break;
- case LoopHintAttr::VectorizeWidth:
- case LoopHintAttr::InterleaveCount:
- case LoopHintAttr::Unroll:
- case LoopHintAttr::UnrollCount:
- // Nothing to do here for these loop hints.
+ case LoopHintAttr::Numeric:
+ switch (Option) {
+ case LoopHintAttr::VectorizeWidth:
+ setVectorizeWidth(ValueInt);
+ break;
+ case LoopHintAttr::InterleaveCount:
+ setInterleaveCount(ValueInt);
+ break;
+ case LoopHintAttr::UnrollCount:
+ setUnrollCount(ValueInt);
+ break;
+ case LoopHintAttr::Unroll:
+ case LoopHintAttr::Vectorize:
+ case LoopHintAttr::Interleave:
+ llvm_unreachable("Options cannot be assigned a value.");
+ break;
+ }
break;
}
}
- Active.push_back(LoopInfo(Header, StagedAttrs));
- // Clear the attributes so nested loops do not inherit them.
- StagedAttrs.clear();
+ /// Stage the attributes.
+ push(Header);
}
void LoopInfoStack::pop() {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h
index 2249937..ec33906 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGLoopInfo.h
@@ -29,6 +29,7 @@ class MDNode;
namespace clang {
class Attr;
+class ASTContext;
namespace CodeGen {
/// \brief Attributes that may be specified on loops.
@@ -39,17 +40,23 @@ struct LoopAttributes {
/// \brief Generate llvm.loop.parallel metadata for loads and stores.
bool IsParallel;
- /// \brief Values of llvm.loop.vectorize.enable metadata.
- enum LVEnableState { VecUnspecified, VecEnable, VecDisable };
+ /// \brief State of loop vectorization or unrolling.
+ enum LVEnableState { Unspecified, Enable, Disable, Full };
- /// \brief llvm.loop.vectorize.enable
- LVEnableState VectorizerEnable;
+ /// \brief Value for llvm.loop.vectorize.enable metadata.
+ LVEnableState VectorizeEnable;
- /// \brief llvm.loop.vectorize.width
- unsigned VectorizerWidth;
+ /// \brief Value for llvm.loop.unroll.* metadata (enable, disable, or full).
+ LVEnableState UnrollEnable;
- /// \brief llvm.loop.interleave.count
- unsigned VectorizerUnroll;
+ /// \brief Value for llvm.loop.vectorize.width metadata.
+ unsigned VectorizeWidth;
+
+ /// \brief Value for llvm.loop.interleave.count metadata.
+ unsigned InterleaveCount;
+
+ /// \brief llvm.unroll.
+ unsigned UnrollCount;
};
/// \brief Information used when generating a structured loop.
@@ -88,8 +95,12 @@ public:
/// \brief Begin a new structured loop. The set of staged attributes will be
/// applied to the loop and then cleared.
- void push(llvm::BasicBlock *Header,
- llvm::ArrayRef<const Attr *> Attrs = llvm::None);
+ void push(llvm::BasicBlock *Header);
+
+ /// \brief Begin a new structured loop. Stage attributes from the Attrs list.
+ /// The staged attributes are applied to the loop and then cleared.
+ void push(llvm::BasicBlock *Header, clang::ASTContext &Ctx,
+ llvm::ArrayRef<const Attr *> Attrs);
/// \brief End the current loop.
void pop();
@@ -109,17 +120,25 @@ public:
/// \brief Set the next pushed loop as parallel.
void setParallel(bool Enable = true) { StagedAttrs.IsParallel = Enable; }
- /// \brief Set the next pushed loop 'vectorizer.enable'
- void setVectorizerEnable(bool Enable = true) {
- StagedAttrs.VectorizerEnable =
- Enable ? LoopAttributes::VecEnable : LoopAttributes::VecDisable;
+ /// \brief Set the next pushed loop 'vectorize.enable'
+ void setVectorizeEnable(bool Enable = true) {
+ StagedAttrs.VectorizeEnable =
+ Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
}
- /// \brief Set the vectorizer width for the next loop pushed.
- void setVectorizerWidth(unsigned W) { StagedAttrs.VectorizerWidth = W; }
+ /// \brief Set the next pushed loop unroll state.
+ void setUnrollState(const LoopAttributes::LVEnableState &State) {
+ StagedAttrs.UnrollEnable = State;
+ }
+
+ /// \brief Set the vectorize width for the next loop pushed.
+ void setVectorizeWidth(unsigned W) { StagedAttrs.VectorizeWidth = W; }
+
+ /// \brief Set the interleave count for the next loop pushed.
+ void setInterleaveCount(unsigned C) { StagedAttrs.InterleaveCount = C; }
- /// \brief Set the vectorizer unroll for the next loop pushed.
- void setVectorizerUnroll(unsigned U) { StagedAttrs.VectorizerUnroll = U; }
+ /// \brief Set the unroll count for the next loop pushed.
+ void setUnrollCount(unsigned C) { StagedAttrs.UnrollCount = C; }
private:
/// \brief Returns true if there is LoopInfo on the stack.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
index eb76ad1..2d5991b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
@@ -37,9 +37,8 @@ static RValue AdjustObjCObjectType(CodeGenFunction &CGF,
/// Given the address of a variable of pointer type, find the correct
/// null to store into it.
-static llvm::Constant *getNullForVariable(llvm::Value *addr) {
- llvm::Type *type =
- cast<llvm::PointerType>(addr->getType())->getElementType();
+static llvm::Constant *getNullForVariable(Address addr) {
+ llvm::Type *type = addr.getElementType();
return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(type));
}
@@ -47,7 +46,7 @@ static llvm::Constant *getNullForVariable(llvm::Value *addr) {
llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
{
llvm::Constant *C =
- CGM.getObjCRuntime().GenerateConstantString(E->getString());
+ CGM.getObjCRuntime().GenerateConstantString(E->getString()).getPointer();
// FIXME: This bitcast should just be made an invariant on the Runtime.
return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
}
@@ -84,16 +83,15 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) {
if (ValueType->isObjCBoxableRecordType()) {
// Emit CodeGen for first parameter
// and cast value to correct type
- llvm::Value *Temporary = CreateMemTemp(SubExpr->getType());
+ Address Temporary = CreateMemTemp(SubExpr->getType());
EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true);
- llvm::Value *BitCast = Builder.CreateBitCast(Temporary,
- ConvertType(ArgQT));
- Args.add(RValue::get(BitCast), ArgQT);
+ Address BitCast = Builder.CreateBitCast(Temporary, ConvertType(ArgQT));
+ Args.add(RValue::get(BitCast.getPointer()), ArgQT);
// Create char array to store type encoding
std::string Str;
getContext().getObjCEncodingForType(ValueType, Str);
- llvm::GlobalVariable *GV = CGM.GetAddrOfConstantCString(Str);
+ llvm::Constant *GV = CGM.GetAddrOfConstantCString(Str).getPointer();
// Cast type encoding to correct type
const ParmVarDecl *EncodingDecl = BoxingMethod->parameters()[1];
@@ -131,8 +129,8 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
ArrayType::Normal, /*IndexTypeQuals=*/0);
// Allocate the temporary array(s).
- llvm::AllocaInst *Objects = CreateMemTemp(ElementArrayType, "objects");
- llvm::AllocaInst *Keys = nullptr;
+ Address Objects = CreateMemTemp(ElementArrayType, "objects");
+ Address Keys = Address::invalid();
if (DLE)
Keys = CreateMemTemp(ElementArrayType, "keys");
@@ -148,9 +146,9 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
if (ALE) {
// Emit the element and store it to the appropriate array slot.
const Expr *Rhs = ALE->getElement(i);
- LValue LV = LValue::MakeAddr(
- Builder.CreateStructGEP(Objects->getAllocatedType(), Objects, i),
- ElementType, Context.getTypeAlignInChars(Rhs->getType()), Context);
+ LValue LV = MakeAddrLValue(
+ Builder.CreateConstArrayGEP(Objects, i, getPointerSize()),
+ ElementType, AlignmentSource::Decl);
llvm::Value *value = EmitScalarExpr(Rhs);
EmitStoreThroughLValue(RValue::get(value), LV, true);
@@ -160,17 +158,17 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
} else {
// Emit the key and store it to the appropriate array slot.
const Expr *Key = DLE->getKeyValueElement(i).Key;
- LValue KeyLV = LValue::MakeAddr(
- Builder.CreateStructGEP(Keys->getAllocatedType(), Keys, i),
- ElementType, Context.getTypeAlignInChars(Key->getType()), Context);
+ LValue KeyLV = MakeAddrLValue(
+ Builder.CreateConstArrayGEP(Keys, i, getPointerSize()),
+ ElementType, AlignmentSource::Decl);
llvm::Value *keyValue = EmitScalarExpr(Key);
EmitStoreThroughLValue(RValue::get(keyValue), KeyLV, /*isInit=*/true);
// Emit the value and store it to the appropriate array slot.
const Expr *Value = DLE->getKeyValueElement(i).Value;
- LValue ValueLV = LValue::MakeAddr(
- Builder.CreateStructGEP(Objects->getAllocatedType(), Objects, i),
- ElementType, Context.getTypeAlignInChars(Value->getType()), Context);
+ LValue ValueLV = MakeAddrLValue(
+ Builder.CreateConstArrayGEP(Objects, i, getPointerSize()),
+ ElementType, AlignmentSource::Decl);
llvm::Value *valueValue = EmitScalarExpr(Value);
EmitStoreThroughLValue(RValue::get(valueValue), ValueLV, /*isInit=*/true);
if (TrackNeededObjects) {
@@ -185,11 +183,11 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
ObjCMethodDecl::param_const_iterator PI = MethodWithObjects->param_begin();
const ParmVarDecl *argDecl = *PI++;
QualType ArgQT = argDecl->getType().getUnqualifiedType();
- Args.add(RValue::get(Objects), ArgQT);
+ Args.add(RValue::get(Objects.getPointer()), ArgQT);
if (DLE) {
argDecl = *PI++;
ArgQT = argDecl->getType().getUnqualifiedType();
- Args.add(RValue::get(Keys), ArgQT);
+ Args.add(RValue::get(Keys.getPointer()), ArgQT);
}
argDecl = *PI;
ArgQT = argDecl->getType().getUnqualifiedType();
@@ -275,10 +273,23 @@ shouldExtendReceiverForInnerPointerMessage(const ObjCMessageExpr *message) {
// receiver is loaded from a variable with precise lifetime.
case ObjCMessageExpr::Instance: {
const Expr *receiver = message->getInstanceReceiver();
+
+ // Look through OVEs.
+ if (auto opaque = dyn_cast<OpaqueValueExpr>(receiver)) {
+ if (opaque->getSourceExpr())
+ receiver = opaque->getSourceExpr()->IgnoreParens();
+ }
+
const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(receiver);
if (!ice || ice->getCastKind() != CK_LValueToRValue) return true;
receiver = ice->getSubExpr()->IgnoreParens();
+ // Look through OVEs.
+ if (auto opaque = dyn_cast<OpaqueValueExpr>(receiver)) {
+ if (opaque->getSourceExpr())
+ receiver = opaque->getSourceExpr()->IgnoreParens();
+ }
+
// Only __strong variables.
if (receiver->getType().getObjCLifetime() != Qualifiers::OCL_Strong)
return true;
@@ -312,6 +323,21 @@ shouldExtendReceiverForInnerPointerMessage(const ObjCMessageExpr *message) {
llvm_unreachable("invalid receiver kind");
}
+/// Given an expression of ObjC pointer type, check whether it was
+/// immediately loaded from an ARC __weak l-value.
+static const Expr *findWeakLValue(const Expr *E) {
+ assert(E->getType()->isObjCRetainableType());
+ E = E->IgnoreParens();
+ if (auto CE = dyn_cast<CastExpr>(E)) {
+ if (CE->getCastKind() == CK_LValueToRValue) {
+ if (CE->getSubExpr()->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
+ return CE->getSubExpr();
+ }
+ }
+
+ return nullptr;
+}
+
RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
ReturnValueSlot Return) {
// Only the lookup mechanism and first two arguments of the method
@@ -322,6 +348,17 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
const ObjCMethodDecl *method = E->getMethodDecl();
+ // If the method is -retain, and the receiver's being loaded from
+ // a __weak variable, peephole the entire operation to objc_loadWeakRetained.
+ if (method && E->getReceiverKind() == ObjCMessageExpr::Instance &&
+ method->getMethodFamily() == OMF_retain) {
+ if (auto lvalueExpr = findWeakLValue(E->getInstanceReceiver())) {
+ LValue lvalue = EmitLValue(lvalueExpr);
+ llvm::Value *result = EmitARCLoadWeakRetained(lvalue.getAddress());
+ return AdjustObjCObjectType(*this, E->getType(), RValue::get(result));
+ }
+ }
+
// We don't retain the receiver in delegate init calls, and this is
// safe because the receiver value is always loaded from 'self',
// which we zero out. We don't want to Block_copy block receivers,
@@ -390,7 +427,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
QualType ResultType = method ? method->getReturnType() : E->getType();
CallArgList Args;
- EmitCallArgs(Args, method, E->arg_begin(), E->arg_end());
+ EmitCallArgs(Args, method, E->arguments());
// For delegate init calls in ARC, do an unsafe store of null into
// self. This represents the call taking direct ownership of that
@@ -404,10 +441,8 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
"delegate init calls should only be marked in ARC");
// Do an unsafe store of null into self.
- llvm::Value *selfAddr =
- LocalDeclMap[cast<ObjCMethodDecl>(CurCodeDecl)->getSelfDecl()];
- assert(selfAddr && "no self entry for a delegate init call?");
-
+ Address selfAddr =
+ GetAddrOfLocalVar(cast<ObjCMethodDecl>(CurCodeDecl)->getSelfDecl());
Builder.CreateStore(getNullForVariable(selfAddr), selfAddr);
}
@@ -434,14 +469,13 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
// For delegate init calls in ARC, implicitly store the result of
// the call back into self. This takes ownership of the value.
if (isDelegateInit) {
- llvm::Value *selfAddr =
- LocalDeclMap[cast<ObjCMethodDecl>(CurCodeDecl)->getSelfDecl()];
+ Address selfAddr =
+ GetAddrOfLocalVar(cast<ObjCMethodDecl>(CurCodeDecl)->getSelfDecl());
llvm::Value *newSelf = result.getScalarVal();
// The delegate return type isn't necessarily a matching type; in
// fact, it's quite likely to be 'id'.
- llvm::Type *selfTy =
- cast<llvm::PointerType>(selfAddr->getType())->getElementType();
+ llvm::Type *selfTy = selfAddr.getElementType();
newSelf = Builder.CreateBitCast(newSelf, selfTy);
Builder.CreateStore(newSelf, selfAddr);
@@ -451,7 +485,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
}
namespace {
-struct FinishARCDealloc : EHScopeStack::Cleanup {
+struct FinishARCDealloc final : EHScopeStack::Cleanup {
void Emit(CodeGenFunction &CGF, Flags flags) override {
const ObjCMethodDecl *method = cast<ObjCMethodDecl>(CGF.CurCodeDecl);
@@ -523,7 +557,7 @@ static llvm::Value *emitARCRetainLoadOfScalar(CodeGenFunction &CGF,
/// its pointer, name, and types registered in the class struture.
void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
StartObjCMethod(OMD, OMD->getClassInterface());
- PGO.assignRegionCounters(OMD, CurFn);
+ PGO.assignRegionCounters(GlobalDecl(OMD), CurFn);
assert(isa<CompoundStmt>(OMD->getBody()));
incrementProfileCounter(OMD->getBody());
EmitCompoundStmtWithoutScope(*cast<CompoundStmt>(OMD->getBody()));
@@ -536,19 +570,19 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
bool isAtomic, bool hasStrong) {
ASTContext &Context = CGF.getContext();
- llvm::Value *src =
- CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), CGF.LoadObjCSelf(),
- ivar, 0).getAddress();
+ Address src =
+ CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), CGF.LoadObjCSelf(), ivar, 0)
+ .getAddress();
// objc_copyStruct (ReturnValue, &structIvar,
// sizeof (Type of Ivar), isAtomic, false);
CallArgList args;
- llvm::Value *dest = CGF.Builder.CreateBitCast(CGF.ReturnValue, CGF.VoidPtrTy);
- args.add(RValue::get(dest), Context.VoidPtrTy);
+ Address dest = CGF.Builder.CreateBitCast(CGF.ReturnValue, CGF.VoidPtrTy);
+ args.add(RValue::get(dest.getPointer()), Context.VoidPtrTy);
src = CGF.Builder.CreateBitCast(src, CGF.VoidPtrTy);
- args.add(RValue::get(src), Context.VoidPtrTy);
+ args.add(RValue::get(src.getPointer()), Context.VoidPtrTy);
CharUnits size = CGF.getContext().getTypeSizeInChars(ivar->getType());
args.add(RValue::get(CGF.CGM.getSize(size)), Context.getSizeType());
@@ -812,8 +846,8 @@ static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF,
// The 2nd argument is the address of the ivar.
llvm::Value *ivarAddr =
- CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(),
- CGF.LoadObjCSelf(), ivar, 0).getAddress();
+ CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(),
+ CGF.LoadObjCSelf(), ivar, 0).getPointer();
ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy);
args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy);
@@ -843,7 +877,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
}
else {
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
- emitCPPObjectAtomicGetterCall(*this, ReturnValue,
+ emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(),
ivar, AtomicHelperFn);
}
return;
@@ -873,10 +907,9 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
bitcastType = bitcastType->getPointerTo(); // addrspace 0 okay
// Perform an atomic load. This does not impose ordering constraints.
- llvm::Value *ivarAddr = LV.getAddress();
+ Address ivarAddr = LV.getAddress();
ivarAddr = Builder.CreateBitCast(ivarAddr, bitcastType);
llvm::LoadInst *load = Builder.CreateLoad(ivarAddr, "load");
- load->setAlignment(strategy.getIvarAlignment().getQuantity());
load->setAtomic(llvm::Unordered);
// Store that value into the return address. Doing this with a
@@ -901,7 +934,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
// FIXME: Can't this be simpler? This might even be worse than the
// corresponding gcc code.
llvm::Value *cmd =
- Builder.CreateLoad(LocalDeclMap[getterMethod->getCmdDecl()], "cmd");
+ Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd");
llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
llvm::Value *ivarOffset =
EmitIvarOffset(classImpl->getClassInterface(), ivar);
@@ -916,11 +949,11 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
// FIXME: We shouldn't need to get the function info here, the
// runtime already should have computed it to build the function.
llvm::Instruction *CallInstruction;
- RValue RV = EmitCall(getTypes().arrangeFreeFunctionCall(propType, args,
- FunctionType::ExtInfo(),
- RequiredArgs::All),
- getPropertyFn, ReturnValueSlot(), args, nullptr,
- &CallInstruction);
+ RValue RV = EmitCall(
+ getTypes().arrangeFreeFunctionCall(
+ propType, args, FunctionType::ExtInfo(), RequiredArgs::All),
+ getPropertyFn, ReturnValueSlot(), args, CGCalleeInfo(),
+ &CallInstruction);
if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(CallInstruction))
call->setTailCall();
@@ -952,8 +985,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
switch (getEvaluationKind(ivarType)) {
case TEK_Complex: {
ComplexPairTy pair = EmitLoadOfComplex(LV, SourceLocation());
- EmitStoreOfComplex(pair,
- MakeNaturalAlignAddrLValue(ReturnValue, ivarType),
+ EmitStoreOfComplex(pair, MakeAddrLValue(ReturnValue, ivarType),
/*init*/ true);
return;
}
@@ -966,11 +998,15 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
case TEK_Scalar: {
llvm::Value *value;
if (propType->isReferenceType()) {
- value = LV.getAddress();
+ value = LV.getAddress().getPointer();
} else {
// We want to load and autoreleaseReturnValue ARC __weak ivars.
if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) {
- value = emitARCRetainLoadOfScalar(*this, LV, ivarType);
+ if (getLangOpts().ObjCAutoRefCount) {
+ value = emitARCRetainLoadOfScalar(*this, LV, ivarType);
+ } else {
+ value = EmitARCLoadWeak(LV.getAddress());
+ }
// Otherwise we want to do a simple load, suppressing the
// final autorelease.
@@ -1006,7 +1042,7 @@ static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD,
// The first argument is the address of the ivar.
llvm::Value *ivarAddr = CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(),
CGF.LoadObjCSelf(), ivar, 0)
- .getAddress();
+ .getPointer();
ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy);
args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy);
@@ -1014,7 +1050,7 @@ static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD,
ParmVarDecl *argVar = *OMD->param_begin();
DeclRefExpr argRef(argVar, false, argVar->getType().getNonReferenceType(),
VK_LValue, SourceLocation());
- llvm::Value *argAddr = CGF.EmitLValue(&argRef).getAddress();
+ llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer();
argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy);
args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy);
@@ -1052,7 +1088,7 @@ static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF,
// The first argument is the address of the ivar.
llvm::Value *ivarAddr =
CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(),
- CGF.LoadObjCSelf(), ivar, 0).getAddress();
+ CGF.LoadObjCSelf(), ivar, 0).getPointer();
ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy);
args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy);
@@ -1060,7 +1096,7 @@ static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF,
ParmVarDecl *argVar = *OMD->param_begin();
DeclRefExpr argRef(argVar, false, argVar->getType().getNonReferenceType(),
VK_LValue, SourceLocation());
- llvm::Value *argAddr = CGF.EmitLValue(&argRef).getAddress();
+ llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer();
argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy);
args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy);
@@ -1135,29 +1171,27 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
if (strategy.getIvarSize().isZero())
return;
- llvm::Value *argAddr = LocalDeclMap[*setterMethod->param_begin()];
+ Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin());
LValue ivarLValue =
EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, /*quals*/ 0);
- llvm::Value *ivarAddr = ivarLValue.getAddress();
+ Address ivarAddr = ivarLValue.getAddress();
// Currently, all atomic accesses have to be through integer
// types, so there's no point in trying to pick a prettier type.
llvm::Type *bitcastType =
llvm::Type::getIntNTy(getLLVMContext(),
getContext().toBits(strategy.getIvarSize()));
- bitcastType = bitcastType->getPointerTo(); // addrspace 0 okay
// Cast both arguments to the chosen operation type.
- argAddr = Builder.CreateBitCast(argAddr, bitcastType);
- ivarAddr = Builder.CreateBitCast(ivarAddr, bitcastType);
+ argAddr = Builder.CreateElementBitCast(argAddr, bitcastType);
+ ivarAddr = Builder.CreateElementBitCast(ivarAddr, bitcastType);
// This bitcast load is likely to cause some nasty IR.
llvm::Value *load = Builder.CreateLoad(argAddr);
// Perform an atomic store. There are no memory ordering requirements.
llvm::StoreInst *store = Builder.CreateStore(load, ivarAddr);
- store->setAlignment(strategy.getIvarAlignment().getQuantity());
store->setAtomic(llvm::Unordered);
return;
}
@@ -1189,13 +1223,14 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
// Emit objc_setProperty((id) self, _cmd, offset, arg,
// <is-atomic>, <is-copy>).
llvm::Value *cmd =
- Builder.CreateLoad(LocalDeclMap[setterMethod->getCmdDecl()]);
+ Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()));
llvm::Value *self =
Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
llvm::Value *ivarOffset =
EmitIvarOffset(classImpl->getClassInterface(), ivar);
- llvm::Value *arg = LocalDeclMap[*setterMethod->param_begin()];
- arg = Builder.CreateBitCast(Builder.CreateLoad(arg, "arg"), VoidPtrTy);
+ Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin());
+ llvm::Value *arg = Builder.CreateLoad(argAddr, "arg");
+ arg = Builder.CreateBitCast(arg, VoidPtrTy);
CallArgList args;
args.add(RValue::get(self), getContext().getObjCIdType());
@@ -1304,7 +1339,7 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
}
namespace {
- struct DestroyIvar : EHScopeStack::Cleanup {
+ struct DestroyIvar final : EHScopeStack::Cleanup {
private:
llvm::Value *addr;
const ObjCIvarDecl *ivar;
@@ -1328,7 +1363,7 @@ namespace {
/// Like CodeGenFunction::destroyARCStrong, but do it with a call.
static void destroyARCStrongWithStore(CodeGenFunction &CGF,
- llvm::Value *addr,
+ Address addr,
QualType type) {
llvm::Value *null = getNullForVariable(addr);
CGF.EmitARCStoreStrongCall(addr, null, /*ignored*/ true);
@@ -1405,22 +1440,6 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
FinishFunction();
}
-bool CodeGenFunction::IndirectObjCSetterArg(const CGFunctionInfo &FI) {
- CGFunctionInfo::const_arg_iterator it = FI.arg_begin();
- it++; it++;
- const ABIArgInfo &AI = it->info;
- // FIXME. Is this sufficient check?
- return (AI.getKind() == ABIArgInfo::Indirect);
-}
-
-bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) {
- if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
- return false;
- if (const RecordType *FDTTy = Ty.getTypePtr()->getAs<RecordType>())
- return FDTTy->getDecl()->hasObjectMember();
- return false;
-}
-
llvm::Value *CodeGenFunction::LoadObjCSelf() {
VarDecl *Self = cast<ObjCMethodDecl>(CurFuncDecl)->getSelfDecl();
DeclRefExpr DRE(Self, /*is enclosing local*/ (CurFuncDecl != CurCodeDecl),
@@ -1458,7 +1477,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Fast enumeration state.
QualType StateTy = CGM.getObjCFastEnumerationStateType();
- llvm::AllocaInst *StatePtr = CreateMemTemp(StateTy, "state.ptr");
+ Address StatePtr = CreateMemTemp(StateTy, "state.ptr");
EmitNullInitialization(StatePtr, StateTy);
// Number of elements in the items array.
@@ -1477,7 +1496,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
getContext().getConstantArrayType(getContext().getObjCIdType(),
llvm::APInt(32, NumItems),
ArrayType::Normal, 0);
- llvm::Value *ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr");
+ Address ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr");
// Emit the collection pointer. In ARC, we do a retain.
llvm::Value *Collection;
@@ -1498,14 +1517,16 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
CallArgList Args;
// The first argument is a temporary of the enumeration-state type.
- Args.add(RValue::get(StatePtr), getContext().getPointerType(StateTy));
+ Args.add(RValue::get(StatePtr.getPointer()),
+ getContext().getPointerType(StateTy));
// The second argument is a temporary array with space for NumItems
// pointers. We'll actually be loading elements from the array
// pointer written into the control state; this buffer is so that
// collections that *aren't* backed by arrays can still queue up
// batches of elements.
- Args.add(RValue::get(ItemsPtr), getContext().getPointerType(ItemsTy));
+ Args.add(RValue::get(ItemsPtr.getPointer()),
+ getContext().getPointerType(ItemsTy));
// The third argument is the capacity of that temporary array.
llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy);
@@ -1542,13 +1563,14 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Save the initial mutations value. This is the value at an
// address that was written into the state object by
// countByEnumeratingWithState:objects:count:.
- llvm::Value *StateMutationsPtrPtr = Builder.CreateStructGEP(
- StatePtr->getAllocatedType(), StatePtr, 2, "mutationsptr.ptr");
- llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr,
- "mutationsptr");
+ Address StateMutationsPtrPtr = Builder.CreateStructGEP(
+ StatePtr, 2, 2 * getPointerSize(), "mutationsptr.ptr");
+ llvm::Value *StateMutationsPtr
+ = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr");
llvm::Value *initialMutations =
- Builder.CreateLoad(StateMutationsPtr, "forcoll.initial-mutations");
+ Builder.CreateAlignedLoad(StateMutationsPtr, getPointerAlign(),
+ "forcoll.initial-mutations");
// Start looping. This is the point we return to whenever we have a
// fresh, non-empty batch of objects.
@@ -1570,7 +1592,8 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// refreshes.
StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr");
llvm::Value *currentMutations
- = Builder.CreateLoad(StateMutationsPtr, "statemutations");
+ = Builder.CreateAlignedLoad(StateMutationsPtr, getPointerAlign(),
+ "statemutations");
llvm::BasicBlock *WasMutatedBB = createBasicBlock("forcoll.mutated");
llvm::BasicBlock *WasNotMutatedBB = createBasicBlock("forcoll.notmutated");
@@ -1623,15 +1646,16 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Fetch the buffer out of the enumeration state.
// TODO: this pointer should actually be invariant between
// refreshes, which would help us do certain loop optimizations.
- llvm::Value *StateItemsPtr = Builder.CreateStructGEP(
- StatePtr->getAllocatedType(), StatePtr, 1, "stateitems.ptr");
+ Address StateItemsPtr = Builder.CreateStructGEP(
+ StatePtr, 1, getPointerSize(), "stateitems.ptr");
llvm::Value *EnumStateItems =
Builder.CreateLoad(StateItemsPtr, "stateitems");
// Fetch the value at the current index from the buffer.
llvm::Value *CurrentItemPtr =
Builder.CreateGEP(EnumStateItems, index, "currentitem.ptr");
- llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr);
+ llvm::Value *CurrentItem =
+ Builder.CreateAlignedLoad(CurrentItemPtr, getPointerAlign());
// Cast that value to the right type.
CurrentItem = Builder.CreateBitCast(CurrentItem, convertedElementType,
@@ -1735,15 +1759,8 @@ void CodeGenFunction::EmitObjCAtSynchronizedStmt(
CGM.getObjCRuntime().EmitSynchronizedStmt(*this, S);
}
-/// Produce the code for a CK_ARCProduceObject. Just does a
-/// primitive retain.
-llvm::Value *CodeGenFunction::EmitObjCProduceObject(QualType type,
- llvm::Value *value) {
- return EmitARCRetain(type, value);
-}
-
namespace {
- struct CallObjCRelease : EHScopeStack::Cleanup {
+ struct CallObjCRelease final : EHScopeStack::Cleanup {
CallObjCRelease(llvm::Value *object) : object(object) {}
llvm::Value *object;
@@ -1772,7 +1789,7 @@ llvm::Value *CodeGenFunction::EmitObjCExtendObjectLifetime(QualType type,
/// Given a number of pointers, inform the optimizer that they're
/// being intrinsically used up until this point in the program.
void CodeGenFunction::EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values) {
- llvm::Constant *&fn = CGM.getARCEntrypoints().clang_arc_use;
+ llvm::Constant *&fn = CGM.getObjCEntrypoints().clang_arc_use;
if (!fn) {
llvm::FunctionType *fnType =
llvm::FunctionType::get(CGM.VoidTy, None, true);
@@ -1838,7 +1855,7 @@ static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF,
/// Perform an operation having the following signature:
/// i8* (i8**)
static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF,
- llvm::Value *addr,
+ Address addr,
llvm::Constant *&fn,
StringRef fnName) {
if (!fn) {
@@ -1848,16 +1865,15 @@ static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF,
}
// Cast the argument to 'id*'.
- llvm::Type *origType = addr->getType();
+ llvm::Type *origType = addr.getElementType();
addr = CGF.Builder.CreateBitCast(addr, CGF.Int8PtrPtrTy);
// Call the function.
- llvm::Value *result = CGF.EmitNounwindRuntimeCall(fn, addr);
+ llvm::Value *result = CGF.EmitNounwindRuntimeCall(fn, addr.getPointer());
// Cast the result back to a dereference of the original type.
- if (origType != CGF.Int8PtrPtrTy)
- result = CGF.Builder.CreateBitCast(result,
- cast<llvm::PointerType>(origType)->getElementType());
+ if (origType != CGF.Int8PtrTy)
+ result = CGF.Builder.CreateBitCast(result, origType);
return result;
}
@@ -1865,13 +1881,12 @@ static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF,
/// Perform an operation having the following signature:
/// i8* (i8**, i8*)
static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF,
- llvm::Value *addr,
+ Address addr,
llvm::Value *value,
llvm::Constant *&fn,
StringRef fnName,
bool ignored) {
- assert(cast<llvm::PointerType>(addr->getType())->getElementType()
- == value->getType());
+ assert(addr.getElementType() == value->getType());
if (!fn) {
llvm::Type *argTypes[] = { CGF.Int8PtrPtrTy, CGF.Int8PtrTy };
@@ -1884,7 +1899,7 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF,
llvm::Type *origType = value->getType();
llvm::Value *args[] = {
- CGF.Builder.CreateBitCast(addr, CGF.Int8PtrPtrTy),
+ CGF.Builder.CreateBitCast(addr.getPointer(), CGF.Int8PtrPtrTy),
CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy)
};
llvm::CallInst *result = CGF.EmitNounwindRuntimeCall(fn, args);
@@ -1897,11 +1912,11 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF,
/// Perform an operation having the following signature:
/// void (i8**, i8**)
static void emitARCCopyOperation(CodeGenFunction &CGF,
- llvm::Value *dst,
- llvm::Value *src,
+ Address dst,
+ Address src,
llvm::Constant *&fn,
StringRef fnName) {
- assert(dst->getType() == src->getType());
+ assert(dst.getType() == src.getType());
if (!fn) {
llvm::Type *argTypes[] = { CGF.Int8PtrPtrTy, CGF.Int8PtrPtrTy };
@@ -1912,8 +1927,8 @@ static void emitARCCopyOperation(CodeGenFunction &CGF,
}
llvm::Value *args[] = {
- CGF.Builder.CreateBitCast(dst, CGF.Int8PtrPtrTy),
- CGF.Builder.CreateBitCast(src, CGF.Int8PtrPtrTy)
+ CGF.Builder.CreateBitCast(dst.getPointer(), CGF.Int8PtrPtrTy),
+ CGF.Builder.CreateBitCast(src.getPointer(), CGF.Int8PtrPtrTy)
};
CGF.EmitNounwindRuntimeCall(fn, args);
}
@@ -1932,7 +1947,7 @@ llvm::Value *CodeGenFunction::EmitARCRetain(QualType type, llvm::Value *value) {
/// call i8* \@objc_retain(i8* %value)
llvm::Value *CodeGenFunction::EmitARCRetainNonBlock(llvm::Value *value) {
return emitARCValueOperation(*this, value,
- CGM.getARCEntrypoints().objc_retain,
+ CGM.getObjCEntrypoints().objc_retain,
"objc_retain");
}
@@ -1946,7 +1961,7 @@ llvm::Value *CodeGenFunction::EmitARCRetainBlock(llvm::Value *value,
bool mandatory) {
llvm::Value *result
= emitARCValueOperation(*this, value,
- CGM.getARCEntrypoints().objc_retainBlock,
+ CGM.getObjCEntrypoints().objc_retainBlock,
"objc_retainBlock");
// If the copy isn't mandatory, add !clang.arc.copy_on_escape to
@@ -1956,7 +1971,7 @@ llvm::Value *CodeGenFunction::EmitARCRetainBlock(llvm::Value *value,
if (!mandatory && isa<llvm::Instruction>(result)) {
llvm::CallInst *call
= cast<llvm::CallInst>(result->stripPointerCasts());
- assert(call->getCalledValue() == CGM.getARCEntrypoints().objc_retainBlock);
+ assert(call->getCalledValue() == CGM.getObjCEntrypoints().objc_retainBlock);
call->setMetadata("clang.arc.copy_on_escape",
llvm::MDNode::get(Builder.getContext(), None));
@@ -1975,7 +1990,7 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
// Fetch the void(void) inline asm which marks that we're going to
// retain the autoreleased return value.
llvm::InlineAsm *&marker
- = CGM.getARCEntrypoints().retainAutoreleasedReturnValueMarker;
+ = CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker;
if (!marker) {
StringRef assembly
= CGM.getTargetCodeGenInfo()
@@ -2012,7 +2027,7 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
Builder.CreateCall(marker);
return emitARCValueOperation(*this, value,
- CGM.getARCEntrypoints().objc_retainAutoreleasedReturnValue,
+ CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue,
"objc_retainAutoreleasedReturnValue");
}
@@ -2022,7 +2037,7 @@ void CodeGenFunction::EmitARCRelease(llvm::Value *value,
ARCPreciseLifetime_t precise) {
if (isa<llvm::ConstantPointerNull>(value)) return;
- llvm::Constant *&fn = CGM.getARCEntrypoints().objc_release;
+ llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_release;
if (!fn) {
llvm::FunctionType *fnType =
llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false);
@@ -2050,12 +2065,10 @@ void CodeGenFunction::EmitARCRelease(llvm::Value *value,
/// At -O1 and above, just load and call objc_release.
///
/// call void \@objc_storeStrong(i8** %addr, i8* null)
-void CodeGenFunction::EmitARCDestroyStrong(llvm::Value *addr,
+void CodeGenFunction::EmitARCDestroyStrong(Address addr,
ARCPreciseLifetime_t precise) {
if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
- llvm::PointerType *addrTy = cast<llvm::PointerType>(addr->getType());
- llvm::Value *null = llvm::ConstantPointerNull::get(
- cast<llvm::PointerType>(addrTy->getElementType()));
+ llvm::Value *null = getNullForVariable(addr);
EmitARCStoreStrongCall(addr, null, /*ignored*/ true);
return;
}
@@ -2066,13 +2079,12 @@ void CodeGenFunction::EmitARCDestroyStrong(llvm::Value *addr,
/// Store into a strong object. Always calls this:
/// call void \@objc_storeStrong(i8** %addr, i8* %value)
-llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(llvm::Value *addr,
+llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr,
llvm::Value *value,
bool ignored) {
- assert(cast<llvm::PointerType>(addr->getType())->getElementType()
- == value->getType());
+ assert(addr.getElementType() == value->getType());
- llvm::Constant *&fn = CGM.getARCEntrypoints().objc_storeStrong;
+ llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_storeStrong;
if (!fn) {
llvm::Type *argTypes[] = { Int8PtrPtrTy, Int8PtrTy };
llvm::FunctionType *fnType
@@ -2081,7 +2093,7 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(llvm::Value *addr,
}
llvm::Value *args[] = {
- Builder.CreateBitCast(addr, Int8PtrPtrTy),
+ Builder.CreateBitCast(addr.getPointer(), Int8PtrPtrTy),
Builder.CreateBitCast(value, Int8PtrTy)
};
EmitNounwindRuntimeCall(fn, args);
@@ -2130,7 +2142,7 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrong(LValue dst,
/// call i8* \@objc_autorelease(i8* %value)
llvm::Value *CodeGenFunction::EmitARCAutorelease(llvm::Value *value) {
return emitARCValueOperation(*this, value,
- CGM.getARCEntrypoints().objc_autorelease,
+ CGM.getObjCEntrypoints().objc_autorelease,
"objc_autorelease");
}
@@ -2139,7 +2151,7 @@ llvm::Value *CodeGenFunction::EmitARCAutorelease(llvm::Value *value) {
llvm::Value *
CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) {
return emitARCValueOperation(*this, value,
- CGM.getARCEntrypoints().objc_autoreleaseReturnValue,
+ CGM.getObjCEntrypoints().objc_autoreleaseReturnValue,
"objc_autoreleaseReturnValue",
/*isTailCall*/ true);
}
@@ -2149,7 +2161,7 @@ CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) {
llvm::Value *
CodeGenFunction::EmitARCRetainAutoreleaseReturnValue(llvm::Value *value) {
return emitARCValueOperation(*this, value,
- CGM.getARCEntrypoints().objc_retainAutoreleaseReturnValue,
+ CGM.getObjCEntrypoints().objc_retainAutoreleaseReturnValue,
"objc_retainAutoreleaseReturnValue",
/*isTailCall*/ true);
}
@@ -2178,32 +2190,32 @@ llvm::Value *CodeGenFunction::EmitARCRetainAutorelease(QualType type,
llvm::Value *
CodeGenFunction::EmitARCRetainAutoreleaseNonBlock(llvm::Value *value) {
return emitARCValueOperation(*this, value,
- CGM.getARCEntrypoints().objc_retainAutorelease,
+ CGM.getObjCEntrypoints().objc_retainAutorelease,
"objc_retainAutorelease");
}
/// i8* \@objc_loadWeak(i8** %addr)
/// Essentially objc_autorelease(objc_loadWeakRetained(addr)).
-llvm::Value *CodeGenFunction::EmitARCLoadWeak(llvm::Value *addr) {
+llvm::Value *CodeGenFunction::EmitARCLoadWeak(Address addr) {
return emitARCLoadOperation(*this, addr,
- CGM.getARCEntrypoints().objc_loadWeak,
+ CGM.getObjCEntrypoints().objc_loadWeak,
"objc_loadWeak");
}
/// i8* \@objc_loadWeakRetained(i8** %addr)
-llvm::Value *CodeGenFunction::EmitARCLoadWeakRetained(llvm::Value *addr) {
+llvm::Value *CodeGenFunction::EmitARCLoadWeakRetained(Address addr) {
return emitARCLoadOperation(*this, addr,
- CGM.getARCEntrypoints().objc_loadWeakRetained,
+ CGM.getObjCEntrypoints().objc_loadWeakRetained,
"objc_loadWeakRetained");
}
/// i8* \@objc_storeWeak(i8** %addr, i8* %value)
/// Returns %value.
-llvm::Value *CodeGenFunction::EmitARCStoreWeak(llvm::Value *addr,
+llvm::Value *CodeGenFunction::EmitARCStoreWeak(Address addr,
llvm::Value *value,
bool ignored) {
return emitARCStoreOperation(*this, addr, value,
- CGM.getARCEntrypoints().objc_storeWeak,
+ CGM.getObjCEntrypoints().objc_storeWeak,
"objc_storeWeak", ignored);
}
@@ -2211,7 +2223,7 @@ llvm::Value *CodeGenFunction::EmitARCStoreWeak(llvm::Value *addr,
/// Returns %value. %addr is known to not have a current weak entry.
/// Essentially equivalent to:
/// *addr = nil; objc_storeWeak(addr, value);
-void CodeGenFunction::EmitARCInitWeak(llvm::Value *addr, llvm::Value *value) {
+void CodeGenFunction::EmitARCInitWeak(Address addr, llvm::Value *value) {
// If we're initializing to null, just write null to memory; no need
// to get the runtime involved. But don't do this if optimization
// is enabled, because accounting for this would make the optimizer
@@ -2223,14 +2235,14 @@ void CodeGenFunction::EmitARCInitWeak(llvm::Value *addr, llvm::Value *value) {
}
emitARCStoreOperation(*this, addr, value,
- CGM.getARCEntrypoints().objc_initWeak,
+ CGM.getObjCEntrypoints().objc_initWeak,
"objc_initWeak", /*ignored*/ true);
}
/// void \@objc_destroyWeak(i8** %addr)
/// Essentially objc_storeWeak(addr, nil).
-void CodeGenFunction::EmitARCDestroyWeak(llvm::Value *addr) {
- llvm::Constant *&fn = CGM.getARCEntrypoints().objc_destroyWeak;
+void CodeGenFunction::EmitARCDestroyWeak(Address addr) {
+ llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_destroyWeak;
if (!fn) {
llvm::FunctionType *fnType =
llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrPtrTy, false);
@@ -2240,31 +2252,31 @@ void CodeGenFunction::EmitARCDestroyWeak(llvm::Value *addr) {
// Cast the argument to 'id*'.
addr = Builder.CreateBitCast(addr, Int8PtrPtrTy);
- EmitNounwindRuntimeCall(fn, addr);
+ EmitNounwindRuntimeCall(fn, addr.getPointer());
}
/// void \@objc_moveWeak(i8** %dest, i8** %src)
/// Disregards the current value in %dest. Leaves %src pointing to nothing.
/// Essentially (objc_copyWeak(dest, src), objc_destroyWeak(src)).
-void CodeGenFunction::EmitARCMoveWeak(llvm::Value *dst, llvm::Value *src) {
+void CodeGenFunction::EmitARCMoveWeak(Address dst, Address src) {
emitARCCopyOperation(*this, dst, src,
- CGM.getARCEntrypoints().objc_moveWeak,
+ CGM.getObjCEntrypoints().objc_moveWeak,
"objc_moveWeak");
}
/// void \@objc_copyWeak(i8** %dest, i8** %src)
/// Disregards the current value in %dest. Essentially
/// objc_release(objc_initWeak(dest, objc_readWeakRetained(src)))
-void CodeGenFunction::EmitARCCopyWeak(llvm::Value *dst, llvm::Value *src) {
+void CodeGenFunction::EmitARCCopyWeak(Address dst, Address src) {
emitARCCopyOperation(*this, dst, src,
- CGM.getARCEntrypoints().objc_copyWeak,
+ CGM.getObjCEntrypoints().objc_copyWeak,
"objc_copyWeak");
}
/// Produce the code to do a objc_autoreleasepool_push.
/// call i8* \@objc_autoreleasePoolPush(void)
llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {
- llvm::Constant *&fn = CGM.getRREntrypoints().objc_autoreleasePoolPush;
+ llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPush;
if (!fn) {
llvm::FunctionType *fnType =
llvm::FunctionType::get(Int8PtrTy, false);
@@ -2279,7 +2291,7 @@ llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {
void CodeGenFunction::EmitObjCAutoreleasePoolPop(llvm::Value *value) {
assert(value->getType() == Int8PtrTy);
- llvm::Constant *&fn = CGM.getRREntrypoints().objc_autoreleasePoolPop;
+ llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPop;
if (!fn) {
llvm::FunctionType *fnType =
llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false);
@@ -2332,25 +2344,25 @@ void CodeGenFunction::EmitObjCMRRAutoreleasePoolPop(llvm::Value *Arg) {
}
void CodeGenFunction::destroyARCStrongPrecise(CodeGenFunction &CGF,
- llvm::Value *addr,
+ Address addr,
QualType type) {
CGF.EmitARCDestroyStrong(addr, ARCPreciseLifetime);
}
void CodeGenFunction::destroyARCStrongImprecise(CodeGenFunction &CGF,
- llvm::Value *addr,
+ Address addr,
QualType type) {
CGF.EmitARCDestroyStrong(addr, ARCImpreciseLifetime);
}
void CodeGenFunction::destroyARCWeak(CodeGenFunction &CGF,
- llvm::Value *addr,
+ Address addr,
QualType type) {
CGF.EmitARCDestroyWeak(addr);
}
namespace {
- struct CallObjCAutoreleasePoolObject : EHScopeStack::Cleanup {
+ struct CallObjCAutoreleasePoolObject final : EHScopeStack::Cleanup {
llvm::Value *Token;
CallObjCAutoreleasePoolObject(llvm::Value *token) : Token(token) {}
@@ -2359,7 +2371,7 @@ namespace {
CGF.EmitObjCAutoreleasePoolPop(Token);
}
};
- struct CallObjCMRRAutoreleasePoolObject : EHScopeStack::Cleanup {
+ struct CallObjCMRRAutoreleasePoolObject final : EHScopeStack::Cleanup {
llvm::Value *Token;
CallObjCMRRAutoreleasePoolObject(llvm::Value *token) : Token(token) {}
@@ -2932,7 +2944,9 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
"__assign_helper_atomic_property_",
&CGM.getModule());
-
+
+ CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+
StartFunction(FD, C.VoidTy, Fn, FI, args);
DeclRefExpr DstExpr(&dstDecl, false, DestTy,
@@ -3011,6 +3025,8 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
"__copy_helper_atomic_property_", &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(nullptr, Fn, FI);
+
StartFunction(FD, C.VoidTy, Fn, FI, args);
DeclRefExpr SrcExpr(&srcDecl, false, SrcTy,
@@ -3046,7 +3062,8 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
CharUnits Alignment
= getContext().getTypeAlignInChars(TheCXXConstructExpr->getType());
EmitAggExpr(TheCXXConstructExpr,
- AggValueSlot::forAddr(DV.getScalarVal(), Alignment, Qualifiers(),
+ AggValueSlot::forAddr(Address(DV.getScalarVal(), Alignment),
+ Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased));
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
index b52d623..f0af3e9 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -166,9 +166,9 @@ protected:
/// where the C code specifies const char*.
llvm::Constant *MakeConstantString(const std::string &Str,
const std::string &Name="") {
- auto *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
- return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
- ConstStr, Zeros);
+ ConstantAddress Array = CGM.GetAddrOfConstantCString(Str, Name.c_str());
+ return llvm::ConstantExpr::getGetElementPtr(Array.getElementType(),
+ Array.getPointer(), Zeros);
}
/// Emits a linkonce_odr string, whose name is the prefix followed by the
/// string value. This allows the linker to combine the strings between
@@ -191,34 +191,41 @@ protected:
/// first argument.
llvm::GlobalVariable *MakeGlobal(llvm::StructType *Ty,
ArrayRef<llvm::Constant *> V,
+ CharUnits Align,
StringRef Name="",
llvm::GlobalValue::LinkageTypes linkage
=llvm::GlobalValue::InternalLinkage) {
llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
- return new llvm::GlobalVariable(TheModule, Ty, false,
- linkage, C, Name);
+ auto GV = new llvm::GlobalVariable(TheModule, Ty, false,
+ linkage, C, Name);
+ GV->setAlignment(Align.getQuantity());
+ return GV;
}
/// Generates a global array. The vector must contain the same number of
/// elements that the array type declares, of the type specified as the array
/// element type.
llvm::GlobalVariable *MakeGlobal(llvm::ArrayType *Ty,
ArrayRef<llvm::Constant *> V,
+ CharUnits Align,
StringRef Name="",
llvm::GlobalValue::LinkageTypes linkage
=llvm::GlobalValue::InternalLinkage) {
llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
- return new llvm::GlobalVariable(TheModule, Ty, false,
- linkage, C, Name);
+ auto GV = new llvm::GlobalVariable(TheModule, Ty, false,
+ linkage, C, Name);
+ GV->setAlignment(Align.getQuantity());
+ return GV;
}
/// Generates a global array, inferring the array type from the specified
/// element type and the size of the initialiser.
llvm::GlobalVariable *MakeGlobalArray(llvm::Type *Ty,
ArrayRef<llvm::Constant *> V,
+ CharUnits Align,
StringRef Name="",
llvm::GlobalValue::LinkageTypes linkage
=llvm::GlobalValue::InternalLinkage) {
llvm::ArrayType *ArrayTy = llvm::ArrayType::get(Ty, V.size());
- return MakeGlobal(ArrayTy, V, Name, linkage);
+ return MakeGlobal(ArrayTy, V, Align, Name, linkage);
}
/// Returns a property name and encoding string.
llvm::Constant *MakePropertyEncodingString(const ObjCPropertyDecl *PD,
@@ -234,9 +241,7 @@ protected:
NameAndAttributes += TypeStr;
NameAndAttributes += '\0';
NameAndAttributes += PD->getNameAsString();
- auto *ConstStr = CGM.GetAddrOfConstantCString(NameAndAttributes);
- return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
- ConstStr, Zeros);
+ return MakeConstantString(NameAndAttributes);
}
return MakeConstantString(PD->getNameAsString());
}
@@ -275,6 +280,10 @@ protected:
if (V->getType() == Ty) return V;
return B.CreateBitCast(V, Ty);
}
+ Address EnforceType(CGBuilderTy &B, Address V, llvm::Type *Ty) {
+ if (V.getType() == Ty) return V;
+ return B.CreateBitCast(V, Ty);
+ }
// Some zeros used for GEPs in lots of places.
llvm::Constant *Zeros[2];
/// Null pointer value. Mainly used as a terminator in various arrays.
@@ -435,7 +444,7 @@ private:
/// Returns a selector with the specified type encoding. An empty string is
/// used to return an untyped selector (with the types field set to NULL).
llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
- const std::string &TypeEncoding, bool lval);
+ const std::string &TypeEncoding);
/// Returns the variable used to store the offset of an instance variable.
llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar);
@@ -458,7 +467,7 @@ protected:
/// mechanism differs between the GCC and GNU runtimes, so this method must
/// be overridden in subclasses.
virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
- llvm::Value *ObjCSuper,
+ Address ObjCSuper,
llvm::Value *cmd,
MessageSendInfo &MSI) = 0;
/// Libobjc2 uses a bitfield representation where small(ish) bitfields are
@@ -477,7 +486,7 @@ public:
CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
unsigned protocolClassVersion);
- llvm::Constant *GenerateConstantString(const StringLiteral *) override;
+ ConstantAddress GenerateConstantString(const StringLiteral *) override;
RValue
GenerateMessageSend(CodeGenFunction &CGF, ReturnValueSlot Return,
@@ -494,8 +503,8 @@ public:
const ObjCMethodDecl *Method) override;
llvm::Value *GetClass(CodeGenFunction &CGF,
const ObjCInterfaceDecl *OID) override;
- llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
- bool lval = false) override;
+ llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
+ Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
llvm::Value *GetSelector(CodeGenFunction &CGF,
const ObjCMethodDecl *Method) override;
llvm::Constant *GetEHType(QualType T) override;
@@ -527,18 +536,18 @@ public:
const ObjCAtThrowStmt &S,
bool ClearInsertionPoint=true) override;
llvm::Value * EmitObjCWeakRead(CodeGenFunction &CGF,
- llvm::Value *AddrWeakObj) override;
+ Address AddrWeakObj) override;
void EmitObjCWeakAssign(CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) override;
+ llvm::Value *src, Address dst) override;
void EmitObjCGlobalAssign(CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest,
+ llvm::Value *src, Address dest,
bool threadlocal=false) override;
void EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *src,
- llvm::Value *dest, llvm::Value *ivarOffset) override;
+ Address dest, llvm::Value *ivarOffset) override;
void EmitObjCStrongCastAssign(CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest) override;
- void EmitGCMemmoveCollectable(CodeGenFunction &CGF, llvm::Value *DestPtr,
- llvm::Value *SrcPtr,
+ llvm::Value *src, Address dest) override;
+ void EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address DestPtr,
+ Address SrcPtr,
llvm::Value *Size) override;
LValue EmitObjCValueForIvar(CodeGenFunction &CGF, QualType ObjectTy,
llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
@@ -593,11 +602,11 @@ protected:
imp->setMetadata(msgSendMDKind, node);
return imp.getInstruction();
}
- llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, llvm::Value *ObjCSuper,
+ llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
llvm::Value *cmd, MessageSendInfo &MSI) override {
CGBuilderTy &Builder = CGF.Builder;
llvm::Value *lookupArgs[] = {EnforceType(Builder, ObjCSuper,
- PtrToObjCSuperTy), cmd};
+ PtrToObjCSuperTy).getPointer(), cmd};
return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs);
}
public:
@@ -647,7 +656,8 @@ class CGObjCGNUstep : public CGObjCGNU {
llvm::Function *LookupFn = SlotLookupFn;
// Store the receiver on the stack so that we can reload it later
- llvm::Value *ReceiverPtr = CGF.CreateTempAlloca(Receiver->getType());
+ Address ReceiverPtr =
+ CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign());
Builder.CreateStore(Receiver, ReceiverPtr);
llvm::Value *self;
@@ -662,7 +672,7 @@ class CGObjCGNUstep : public CGObjCGNU {
LookupFn->setDoesNotCapture(1);
llvm::Value *args[] = {
- EnforceType(Builder, ReceiverPtr, PtrToIdTy),
+ EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy),
EnforceType(Builder, cmd, SelectorTy),
EnforceType(Builder, self, IdTy) };
llvm::CallSite slot = CGF.EmitRuntimeCallOrInvoke(LookupFn, args);
@@ -670,25 +680,27 @@ class CGObjCGNUstep : public CGObjCGNU {
slot->setMetadata(msgSendMDKind, node);
// Load the imp from the slot
- llvm::Value *imp = Builder.CreateLoad(
- Builder.CreateStructGEP(nullptr, slot.getInstruction(), 4));
+ llvm::Value *imp = Builder.CreateAlignedLoad(
+ Builder.CreateStructGEP(nullptr, slot.getInstruction(), 4),
+ CGF.getPointerAlign());
// The lookup function may have changed the receiver, so make sure we use
// the new one.
Receiver = Builder.CreateLoad(ReceiverPtr, true);
return imp;
}
- llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, llvm::Value *ObjCSuper,
+ llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
llvm::Value *cmd,
MessageSendInfo &MSI) override {
CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
+ llvm::Value *lookupArgs[] = {ObjCSuper.getPointer(), cmd};
llvm::CallInst *slot =
CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs);
slot->setOnlyReadsMemory();
- return Builder.CreateLoad(Builder.CreateStructGEP(nullptr, slot, 4));
+ return Builder.CreateAlignedLoad(Builder.CreateStructGEP(nullptr, slot, 4),
+ CGF.getPointerAlign());
}
public:
CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNU(Mod, 9, 3) {
@@ -807,10 +819,10 @@ protected:
return imp.getInstruction();
}
- llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, llvm::Value *ObjCSuper,
+ llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
llvm::Value *cmd, MessageSendInfo &MSI) override {
CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *lookupArgs[] = {EnforceType(Builder, ObjCSuper,
+ llvm::Value *lookupArgs[] = {EnforceType(Builder, ObjCSuper.getPointer(),
PtrToObjCSuperTy), cmd};
if (CGM.ReturnTypeUsesSRet(MSI.CallInfo))
@@ -1011,7 +1023,7 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
llvm::Value *CGObjCGNU::GetClassNamed(CodeGenFunction &CGF,
const std::string &Name,
bool isWeak) {
- llvm::GlobalVariable *ClassNameGV = CGM.GetAddrOfConstantCString(Name);
+ llvm::Constant *ClassName = MakeConstantString(Name);
// With the incompatible ABI, this will need to be replaced with a direct
// reference to the class symbol. For the compatible nonfragile ABI we are
// still performing this lookup at run time but emitting the symbol for the
@@ -1021,8 +1033,6 @@ llvm::Value *CGObjCGNU::GetClassNamed(CodeGenFunction &CGF,
// with memoized versions or with static references if it's safe to do so.
if (!isWeak)
EmitClassRef(Name);
- llvm::Value *ClassName =
- CGF.Builder.CreateStructGEP(ClassNameGV->getValueType(), ClassNameGV, 0);
llvm::Constant *ClassLookupFn =
CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, PtrToInt8Ty, true),
@@ -1041,7 +1051,7 @@ llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
}
llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel,
- const std::string &TypeEncoding, bool lval) {
+ const std::string &TypeEncoding) {
SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
llvm::GlobalAlias *SelValue = nullptr;
@@ -1055,29 +1065,34 @@ llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel,
}
if (!SelValue) {
SelValue = llvm::GlobalAlias::create(
- SelectorTy, llvm::GlobalValue::PrivateLinkage,
+ SelectorTy->getElementType(), 0, llvm::GlobalValue::PrivateLinkage,
".objc_selector_" + Sel.getAsString(), &TheModule);
Types.emplace_back(TypeEncoding, SelValue);
}
- if (lval) {
- llvm::Value *tmp = CGF.CreateTempAlloca(SelValue->getType());
- CGF.Builder.CreateStore(SelValue, tmp);
- return tmp;
- }
return SelValue;
}
-llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel,
- bool lval) {
- return GetSelector(CGF, Sel, std::string(), lval);
+Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
+ llvm::Value *SelValue = GetSelector(CGF, Sel);
+
+ // Store it to a temporary. Does this satisfy the semantics of
+ // GetAddrOfSelector? Hopefully.
+ Address tmp = CGF.CreateTempAlloca(SelValue->getType(),
+ CGF.getPointerAlign());
+ CGF.Builder.CreateStore(SelValue, tmp);
+ return tmp;
+}
+
+llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) {
+ return GetSelector(CGF, Sel, std::string());
}
llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF,
const ObjCMethodDecl *Method) {
std::string SelTypes;
CGM.getContext().getObjCEncodingForMethodDecl(Method, SelTypes);
- return GetSelector(CGF, Method->getSelector(), SelTypes, false);
+ return GetSelector(CGF, Method->getSelector(), SelTypes);
}
llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
@@ -1160,21 +1175,23 @@ llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
fields.push_back(BVtable);
fields.push_back(typeName);
llvm::Constant *TI =
- MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
- nullptr), fields, "__objc_eh_typeinfo_" + className,
+ MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, nullptr),
+ fields, CGM.getPointerAlign(),
+ "__objc_eh_typeinfo_" + className,
llvm::GlobalValue::LinkOnceODRLinkage);
return llvm::ConstantExpr::getBitCast(TI, PtrToInt8Ty);
}
/// Generate an NSConstantString object.
-llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
+ConstantAddress CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
std::string Str = SL->getString().str();
+ CharUnits Align = CGM.getPointerAlign();
// Look for an existing one
llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
if (old != ObjCStrings.end())
- return old->getValue();
+ return ConstantAddress(old->getValue(), Align);
StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass;
@@ -1197,11 +1214,11 @@ llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
llvm::Constant *ObjCStr = MakeGlobal(
llvm::StructType::get(PtrToIdTy, PtrToInt8Ty, IntTy, nullptr),
- Ivars, ".objc_str");
+ Ivars, Align, ".objc_str");
ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty);
ObjCStrings[Str] = ObjCStr;
ConstantStrings.push_back(ObjCStr);
- return ObjCStr;
+ return ConstantAddress(ObjCStr, Align);
}
///Generates a message send where the super is the receiver. This is a message
@@ -1261,14 +1278,14 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
if (IsClassMessage) {
if (!MetaClassPtrAlias) {
MetaClassPtrAlias = llvm::GlobalAlias::create(
- IdTy, llvm::GlobalValue::InternalLinkage,
+ IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
".objc_metaclass_ref" + Class->getNameAsString(), &TheModule);
}
ReceiverClass = MetaClassPtrAlias;
} else {
if (!ClassPtrAlias) {
ClassPtrAlias = llvm::GlobalAlias::create(
- IdTy, llvm::GlobalValue::InternalLinkage,
+ IdTy->getElementType(), 0, llvm::GlobalValue::InternalLinkage,
".objc_class_ref" + Class->getNameAsString(), &TheModule);
}
ReceiverClass = ClassPtrAlias;
@@ -1281,16 +1298,20 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
// Get the superclass pointer
ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
// Load the superclass pointer
- ReceiverClass = Builder.CreateLoad(ReceiverClass);
+ ReceiverClass =
+ Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign());
// Construct the structure used to look up the IMP
llvm::StructType *ObjCSuperTy = llvm::StructType::get(
Receiver->getType(), IdTy, nullptr);
- llvm::Value *ObjCSuper = Builder.CreateAlloca(ObjCSuperTy);
+
+ // FIXME: Is this really supposed to be a dynamic alloca?
+ Address ObjCSuper = Address(Builder.CreateAlloca(ObjCSuperTy),
+ CGF.getPointerAlign());
Builder.CreateStore(Receiver,
- Builder.CreateStructGEP(ObjCSuperTy, ObjCSuper, 0));
+ Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero()));
Builder.CreateStore(ReceiverClass,
- Builder.CreateStructGEP(ObjCSuperTy, ObjCSuper, 1));
+ Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize()));
ObjCSuper = EnforceType(Builder, ObjCSuper, PtrToObjCSuperTy);
@@ -1306,8 +1327,8 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD);
llvm::Instruction *call;
- RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, nullptr,
- &call);
+ RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs,
+ CGCalleeInfo(), &call);
call->setMetadata(msgSendMDKind, node);
return msgRet;
}
@@ -1419,8 +1440,8 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
imp = EnforceType(Builder, imp, MSI.MessengerType);
llvm::Instruction *call;
- RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, nullptr,
- &call);
+ RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs,
+ CGCalleeInfo(), &call);
call->setMetadata(msgSendMDKind, node);
@@ -1435,16 +1456,14 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
phi->addIncoming(llvm::Constant::getNullValue(v->getType()), startBB);
msgRet = RValue::get(phi);
} else if (msgRet.isAggregate()) {
- llvm::Value *v = msgRet.getAggregateAddr();
- llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2);
- llvm::PointerType *RetTy = cast<llvm::PointerType>(v->getType());
- llvm::AllocaInst *NullVal =
- CGF.CreateTempAlloca(RetTy->getElementType(), "null");
- CGF.InitTempAlloca(NullVal,
- llvm::Constant::getNullValue(RetTy->getElementType()));
- phi->addIncoming(v, messageBB);
- phi->addIncoming(NullVal, startBB);
- msgRet = RValue::getAggregate(phi);
+ Address v = msgRet.getAggregateAddress();
+ llvm::PHINode *phi = Builder.CreatePHI(v.getType(), 2);
+ llvm::Type *RetTy = v.getElementType();
+ Address NullVal = CGF.CreateTempAlloca(RetTy, v.getAlignment(), "null");
+ CGF.InitTempAlloca(NullVal, llvm::Constant::getNullValue(RetTy));
+ phi->addIncoming(v.getPointer(), messageBB);
+ phi->addIncoming(NullVal.getPointer(), startBB);
+ msgRet = RValue::getAggregate(Address(phi, v.getAlignment()));
} else /* isComplex() */ {
std::pair<llvm::Value*,llvm::Value*> v = msgRet.getComplexVal();
llvm::PHINode *phi = Builder.CreatePHI(v.first->getType(), 2);
@@ -1517,7 +1536,8 @@ GenerateMethodList(StringRef ClassName,
Methods.push_back(MethodArray);
// Create an instance of the structure
- return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list");
+ return MakeGlobal(ObjCMethodListTy, Methods, CGM.getPointerAlign(),
+ ".objc_method_list");
}
/// Generates an IvarList. Used in construction of a objc_class.
@@ -1557,7 +1577,8 @@ GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
nullptr);
// Create an instance of the structure
- return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list");
+ return MakeGlobal(ObjCIvarListTy, Elements, CGM.getPointerAlign(),
+ ".objc_ivar_list");
}
/// Generate a class structure
@@ -1640,8 +1661,9 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
std::string ClassSym((isMeta ? "_OBJC_METACLASS_": "_OBJC_CLASS_") +
std::string(Name));
llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym);
- llvm::Constant *Class = MakeGlobal(ClassTy, Elements, ClassSym,
- llvm::GlobalValue::ExternalLinkage);
+ llvm::Constant *Class =
+ MakeGlobal(ClassTy, Elements, CGM.getPointerAlign(), ClassSym,
+ llvm::GlobalValue::ExternalLinkage);
if (ClassRef) {
ClassRef->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(Class,
ClassRef->getType()));
@@ -1676,7 +1698,8 @@ GenerateProtocolMethodList(ArrayRef<llvm::Constant *> MethodNames,
Methods.clear();
Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
Methods.push_back(Array);
- return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list");
+ return MakeGlobal(ObjCMethodDescListTy, Methods, CGM.getPointerAlign(),
+ ".objc_method_list");
}
// Create the protocol list structure used in classes, categories and so on
@@ -1709,7 +1732,8 @@ llvm::Constant *CGObjCGNU::GenerateProtocolList(ArrayRef<std::string>Protocols){
Elements.push_back(NULLPtr);
Elements.push_back(llvm::ConstantInt::get(LongTy, Protocols.size()));
Elements.push_back(ProtocolArray);
- return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list");
+ return MakeGlobal(ProtocolListTy, Elements, CGM.getPointerAlign(),
+ ".objc_protocol_list");
}
llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
@@ -1749,7 +1773,8 @@ llvm::Constant *CGObjCGNU::GenerateEmptyProtocol(
Elements.push_back(MethodList);
Elements.push_back(MethodList);
Elements.push_back(MethodList);
- return MakeGlobal(ProtocolTy, Elements, ".objc_protocol");
+ return MakeGlobal(ProtocolTy, Elements, CGM.getPointerAlign(),
+ ".objc_protocol");
}
void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
@@ -1910,7 +1935,7 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
Elements.push_back(OptionalPropertyList);
ExistingProtocols[ProtocolName] =
llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
- ".objc_protocol"), IdTy);
+ CGM.getPointerAlign(), ".objc_protocol"), IdTy);
}
void CGObjCGNU::GenerateProtocolHolderCategory() {
// Collect information about instance methods
@@ -1952,10 +1977,12 @@ void CGObjCGNU::GenerateProtocolHolderCategory() {
ExistingProtocols.size()));
ProtocolElements.push_back(ProtocolArray);
Elements.push_back(llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolListTy,
- ProtocolElements, ".objc_protocol_list"), PtrTy));
+ ProtocolElements, CGM.getPointerAlign(),
+ ".objc_protocol_list"), PtrTy));
Categories.push_back(llvm::ConstantExpr::getBitCast(
MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
- PtrTy, PtrTy, PtrTy, nullptr), Elements), PtrTy));
+ PtrTy, PtrTy, PtrTy, nullptr), Elements, CGM.getPointerAlign()),
+ PtrTy));
}
/// Libobjc2 uses a bitfield representation where small(ish) bitfields are
@@ -1995,7 +2022,7 @@ llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) {
llvm::ConstantInt::get(Int32Ty, values.size()),
array };
llvm::Constant *GS = MakeGlobal(llvm::StructType::get(Int32Ty, arrayTy,
- nullptr), fields);
+ nullptr), fields, CharUnits::fromQuantity(4));
llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
return ptr;
}
@@ -2047,7 +2074,8 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
GenerateProtocolList(Protocols), PtrTy));
Categories.push_back(llvm::ConstantExpr::getBitCast(
MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
- PtrTy, PtrTy, PtrTy, nullptr), Elements), PtrTy));
+ PtrTy, PtrTy, PtrTy, nullptr), Elements, CGM.getPointerAlign()),
+ PtrTy));
}
llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OID,
@@ -2225,7 +2253,8 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
llvm::Constant *StrongIvarBitmap = MakeBitField(StrongIvars);
llvm::Constant *WeakIvarBitmap = MakeBitField(WeakIvars);
llvm::GlobalVariable *IvarOffsetArray =
- MakeGlobalArray(PtrToIntTy, IvarOffsetValues, ".ivar.offsets");
+ MakeGlobalArray(PtrToIntTy, IvarOffsetValues, CGM.getPointerAlign(),
+ ".ivar.offsets");
// Collect information about instance methods
@@ -2385,13 +2414,15 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
llvm::StructType::get(PtrToInt8Ty, StaticsArrayTy, nullptr);
llvm::Type *StaticsListPtrTy =
llvm::PointerType::getUnqual(StaticsListTy);
- Statics = MakeGlobal(StaticsListTy, Elements, ".objc_statics");
+ Statics = MakeGlobal(StaticsListTy, Elements, CGM.getPointerAlign(),
+ ".objc_statics");
llvm::ArrayType *StaticsListArrayTy =
llvm::ArrayType::get(StaticsListPtrTy, 2);
Elements.clear();
Elements.push_back(Statics);
Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
- Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr");
+ Statics = MakeGlobal(StaticsListArrayTy, Elements,
+ CGM.getPointerAlign(), ".objc_statics_ptr");
Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
}
// Array of classes, categories, and constant objects
@@ -2442,7 +2473,8 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
// Number of static selectors
Elements.push_back(llvm::ConstantInt::get(LongTy, SelectorCount));
llvm::GlobalVariable *SelectorList =
- MakeGlobalArray(SelStructTy, Selectors, ".objc_selector_list");
+ MakeGlobalArray(SelStructTy, Selectors, CGM.getPointerAlign(),
+ ".objc_selector_list");
Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList,
SelStructPtrTy));
@@ -2475,7 +2507,8 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes);
Elements.push_back(ClassList);
// Construct the symbol table
- llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements);
+ llvm::Constant *SymTab =
+ MakeGlobal(SymTabTy, Elements, CGM.getPointerAlign());
// The symbol table is contained in a module which has some version-checking
// constants
@@ -2516,7 +2549,7 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
break;
}
- llvm::Value *Module = MakeGlobal(ModuleTy, Elements);
+ llvm::Value *Module = MakeGlobal(ModuleTy, Elements, CGM.getPointerAlign());
// Create the load function calling the runtime entry point with the module
// structure
@@ -2526,7 +2559,7 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
&TheModule);
llvm::BasicBlock *EntryBB =
llvm::BasicBlock::Create(VMContext, "entry", LoadFunction);
- CGBuilderTy Builder(VMContext);
+ CGBuilderTy Builder(CGM, VMContext);
Builder.SetInsertPoint(EntryBB);
llvm::FunctionType *FT =
@@ -2678,57 +2711,63 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
}
llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF,
- llvm::Value *AddrWeakObj) {
+ Address AddrWeakObj) {
CGBuilderTy &B = CGF.Builder;
AddrWeakObj = EnforceType(B, AddrWeakObj, PtrToIdTy);
- return B.CreateCall(WeakReadFn.getType(), WeakReadFn, AddrWeakObj);
+ return B.CreateCall(WeakReadFn.getType(), WeakReadFn,
+ AddrWeakObj.getPointer());
}
void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
+ llvm::Value *src, Address dst) {
CGBuilderTy &B = CGF.Builder;
src = EnforceType(B, src, IdTy);
dst = EnforceType(B, dst, PtrToIdTy);
- B.CreateCall(WeakAssignFn.getType(), WeakAssignFn, {src, dst});
+ B.CreateCall(WeakAssignFn.getType(), WeakAssignFn,
+ {src, dst.getPointer()});
}
void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst,
+ llvm::Value *src, Address dst,
bool threadlocal) {
CGBuilderTy &B = CGF.Builder;
src = EnforceType(B, src, IdTy);
dst = EnforceType(B, dst, PtrToIdTy);
// FIXME. Add threadloca assign API
assert(!threadlocal && "EmitObjCGlobalAssign - Threal Local API NYI");
- B.CreateCall(GlobalAssignFn.getType(), GlobalAssignFn, {src, dst});
+ B.CreateCall(GlobalAssignFn.getType(), GlobalAssignFn,
+ {src, dst.getPointer()});
}
void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst,
+ llvm::Value *src, Address dst,
llvm::Value *ivarOffset) {
CGBuilderTy &B = CGF.Builder;
src = EnforceType(B, src, IdTy);
dst = EnforceType(B, dst, IdTy);
- B.CreateCall(IvarAssignFn.getType(), IvarAssignFn, {src, dst, ivarOffset});
+ B.CreateCall(IvarAssignFn.getType(), IvarAssignFn,
+ {src, dst.getPointer(), ivarOffset});
}
void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
+ llvm::Value *src, Address dst) {
CGBuilderTy &B = CGF.Builder;
src = EnforceType(B, src, IdTy);
dst = EnforceType(B, dst, PtrToIdTy);
- B.CreateCall(StrongCastAssignFn.getType(), StrongCastAssignFn, {src, dst});
+ B.CreateCall(StrongCastAssignFn.getType(), StrongCastAssignFn,
+ {src, dst.getPointer()});
}
void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF,
- llvm::Value *DestPtr,
- llvm::Value *SrcPtr,
+ Address DestPtr,
+ Address SrcPtr,
llvm::Value *Size) {
CGBuilderTy &B = CGF.Builder;
DestPtr = EnforceType(B, DestPtr, PtrTy);
SrcPtr = EnforceType(B, SrcPtr, PtrTy);
- B.CreateCall(MemMoveFn.getType(), MemMoveFn, {DestPtr, SrcPtr, Size});
+ B.CreateCall(MemMoveFn.getType(), MemMoveFn,
+ {DestPtr.getPointer(), SrcPtr.getPointer(), Size});
}
llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
@@ -2811,17 +2850,22 @@ llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar);
if (RuntimeVersion < 10)
return CGF.Builder.CreateZExtOrBitCast(
- CGF.Builder.CreateLoad(CGF.Builder.CreateLoad(
- ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar")),
+ CGF.Builder.CreateDefaultAlignedLoad(CGF.Builder.CreateAlignedLoad(
+ ObjCIvarOffsetVariable(Interface, Ivar),
+ CGF.getPointerAlign(), "ivar")),
PtrDiffTy);
std::string name = "__objc_ivar_offset_value_" +
Interface->getNameAsString() +"." + Ivar->getNameAsString();
+ CharUnits Align = CGM.getIntAlign();
llvm::Value *Offset = TheModule.getGlobalVariable(name);
- if (!Offset)
- Offset = new llvm::GlobalVariable(TheModule, IntTy,
+ if (!Offset) {
+ auto GV = new llvm::GlobalVariable(TheModule, IntTy,
false, llvm::GlobalValue::LinkOnceAnyLinkage,
llvm::Constant::getNullValue(IntTy), name);
- Offset = CGF.Builder.CreateLoad(Offset);
+ GV->setAlignment(Align.getQuantity());
+ Offset = GV;
+ }
+ Offset = CGF.Builder.CreateAlignedLoad(Offset, Align);
if (Offset->getType() != PtrDiffTy)
Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
return Offset;
@@ -2845,6 +2889,7 @@ clang::CodeGen::CreateGNUObjCRuntime(CodeGenModule &CGM) {
case ObjCRuntime::FragileMacOSX:
case ObjCRuntime::MacOSX:
case ObjCRuntime::iOS:
+ case ObjCRuntime::WatchOS:
llvm_unreachable("these runtimes are not GNU runtimes");
}
llvm_unreachable("bad runtime");
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
index a45446a..e30b287 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
@@ -659,9 +659,6 @@ public:
// MessageRefCPtrTy - clang type for struct _message_ref_t*
QualType MessageRefCPtrTy;
- // MessengerTy - Type of the messenger (shown as IMP above)
- llvm::FunctionType *MessengerTy;
-
// SuperMessageRefTy - LLVM for:
// struct _super_message_ref_t {
// SUPER_IMP messenger;
@@ -735,20 +732,6 @@ public:
class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
public:
- // FIXME - accessibility
- class GC_IVAR {
- public:
- unsigned ivar_bytepos;
- unsigned ivar_size;
- GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
- : ivar_bytepos(bytepos), ivar_size(size) {}
-
- // Allow sorting based on byte pos.
- bool operator<(const GC_IVAR &b) const {
- return ivar_bytepos < b.ivar_bytepos;
- }
- };
-
class SKIP_SCAN {
public:
unsigned skip;
@@ -830,10 +813,6 @@ protected:
// FIXME! May not be needing this after all.
unsigned ObjCABI;
- // gc ivar layout bitmap calculation helper caches.
- SmallVector<GC_IVAR, 16> SkipIvars;
- SmallVector<GC_IVAR, 16> IvarsInfo;
-
// arc/mrr layout of captured block literal variables.
SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
@@ -854,7 +833,7 @@ protected:
llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
/// DefinedCategoryNames - list of category names in form Class_Category.
- llvm::SetVector<std::string> DefinedCategoryNames;
+ llvm::SmallSetVector<std::string, 16> DefinedCategoryNames;
/// MethodVarTypes - uniqued method type signatures. We have to use
/// a StringMap here because have no other unique reference.
@@ -934,20 +913,28 @@ protected:
/// BuildIvarLayout - Builds ivar layout bitmap for the class
/// implementation for the __strong or __weak case.
///
+ /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there
+ /// are any weak ivars defined directly in the class. Meaningless unless
+ /// building a weak layout. Does not guarantee that the layout will
+ /// actually have any entries, because the ivar might be under-aligned.
llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
- bool ForStrongLayout);
-
- llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
+ CharUnits beginOffset,
+ CharUnits endOffset,
+ bool forStrongLayout,
+ bool hasMRCWeakIvars);
- void BuildAggrIvarRecordLayout(const RecordType *RT,
- unsigned int BytePos, bool ForStrongLayout,
- bool &HasUnion);
- void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
- const llvm::StructLayout *Layout,
- const RecordDecl *RD,
- ArrayRef<const FieldDecl*> RecFields,
- unsigned int BytePos, bool ForStrongLayout,
- bool &HasUnion);
+ llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI,
+ CharUnits beginOffset,
+ CharUnits endOffset) {
+ return BuildIvarLayout(OI, beginOffset, endOffset, true, false);
+ }
+
+ llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI,
+ CharUnits beginOffset,
+ CharUnits endOffset,
+ bool hasMRCWeakIvars) {
+ return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
+ }
Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
@@ -970,7 +957,6 @@ protected:
llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
-
/// GetIvarLayoutName - Returns a unique constant for the given
/// ivar layout bitmap.
llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
@@ -1002,6 +988,7 @@ protected:
/// defined. The return value has type ProtocolPtrTy.
llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
+public:
/// CreateMetadataVar - Create a global variable with internal
/// linkage for use by the Objective-C runtime.
///
@@ -1017,9 +1004,10 @@ protected:
/// \param AddToUsed - Whether the variable should be added to
/// "llvm.used".
llvm::GlobalVariable *CreateMetadataVar(Twine Name, llvm::Constant *Init,
- StringRef Section, unsigned Align,
+ StringRef Section, CharUnits Align,
bool AddToUsed);
+protected:
CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
ReturnValueSlot Return,
QualType ResultType,
@@ -1029,6 +1017,7 @@ protected:
bool IsSuper,
const CallArgList &CallArgs,
const ObjCMethodDecl *OMD,
+ const ObjCInterfaceDecl *ClassReceiver,
const ObjCCommonTypesHelper &ObjCTypes);
/// EmitImageInfo - Emit the image info marker used to encode some module
@@ -1039,7 +1028,11 @@ public:
CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
- llvm::Constant *GenerateConstantString(const StringLiteral *SL) override;
+ bool isNonFragileABI() const {
+ return ObjCABI == 2;
+ }
+
+ ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD=nullptr) override;
@@ -1084,7 +1077,9 @@ private:
/// EmitClassExtension - Generate the class extension structure used
/// to store the weak ivar layout and properties. The return value
/// has type ClassExtensionPtrTy.
- llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
+ llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
+ CharUnits instanceSize,
+ bool hasMRCWeakIvars);
/// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
/// for the given class.
@@ -1172,8 +1167,8 @@ private:
/// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
/// for the given selector.
- llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel,
- bool lval=false);
+ llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
+ Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
public:
CGObjCMac(CodeGen::CodeGenModule &cgm);
@@ -1199,8 +1194,8 @@ public:
llvm::Value *GetClass(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID) override;
- llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
- bool lval = false) override;
+ llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
+ Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
/// The NeXT/Apple runtimes do not support typed selectors; just emit an
/// untyped one.
@@ -1236,19 +1231,19 @@ public:
void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
bool ClearInsertionPoint=true) override;
llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
- llvm::Value *AddrWeakObj) override;
+ Address AddrWeakObj) override;
void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) override;
+ llvm::Value *src, Address dst) override;
void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest,
+ llvm::Value *src, Address dest,
bool threadlocal = false) override;
void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest,
+ llvm::Value *src, Address dest,
llvm::Value *ivarOffset) override;
void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest) override;
+ llvm::Value *src, Address dest) override;
void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
- llvm::Value *dest, llvm::Value *src,
+ Address dest, Address src,
llvm::Value *size) override;
LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
@@ -1395,8 +1390,8 @@ private:
/// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
/// for the given selector.
- llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel,
- bool lval=false);
+ llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
+ Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
/// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
/// interface. The return value has type EHTypePtrTy.
@@ -1474,9 +1469,10 @@ public:
llvm::Value *GetClass(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID) override;
- llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
- bool lvalue = false) override
- { return EmitSelector(CGF, Sel, lvalue); }
+ llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override
+ { return EmitSelector(CGF, Sel); }
+ Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override
+ { return EmitSelectorAddr(CGF, Sel); }
/// The NeXT/Apple runtimes do not support typed selectors; just emit an
/// untyped one.
@@ -1531,19 +1527,19 @@ public:
void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
bool ClearInsertionPoint=true) override;
llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
- llvm::Value *AddrWeakObj) override;
+ Address AddrWeakObj) override;
void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) override;
+ llvm::Value *src, Address edst) override;
void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest,
+ llvm::Value *src, Address dest,
bool threadlocal = false) override;
void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest,
+ llvm::Value *src, Address dest,
llvm::Value *ivarOffset) override;
void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest) override;
+ llvm::Value *src, Address dest) override;
void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
- llvm::Value *dest, llvm::Value *src,
+ Address dest, Address src,
llvm::Value *size) override;
LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
@@ -1645,7 +1641,7 @@ struct NullReturnState {
// memory or (2) agg values in registers.
if (result.isAggregate()) {
assert(result.isAggregate() && "null init of non-aggregate result?");
- CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
+ CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
if (contBB) CGF.EmitBlock(contBB);
return result;
}
@@ -1711,9 +1707,11 @@ llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
}
/// GetSelector - Return the pointer to the unique'd string for this selector.
-llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel,
- bool lval) {
- return EmitSelector(CGF, Sel, lval);
+llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
+ return EmitSelector(CGF, Sel);
+}
+Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
+ return EmitSelectorAddr(CGF, Sel);
}
llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl
*Method) {
@@ -1756,7 +1754,7 @@ llvm::Constant *CGObjCMac::GetEHType(QualType T) {
};
*/
-llvm::Constant *CGObjCCommonMac::GenerateConstantString(
+ConstantAddress CGObjCCommonMac::GenerateConstantString(
const StringLiteral *SL) {
return (CGM.getLangOpts().NoConstantCFStrings == 0 ?
CGM.GetAddrOfConstantCFString(SL) :
@@ -1783,13 +1781,14 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
const ObjCMethodDecl *Method) {
// Create and init a super structure; this is a (receiver, class)
// pair we will pass to objc_msgSendSuper.
- llvm::Value *ObjCSuper =
- CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
+ Address ObjCSuper =
+ CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
+ "objc_super");
llvm::Value *ReceiverAsObject =
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
CGF.Builder.CreateStore(
ReceiverAsObject,
- CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 0));
+ CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero()));
// If this is a class message the metaclass is passed as the target.
llvm::Value *Target;
@@ -1803,12 +1802,13 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
// isa" is the first ivar in a class (which it must be).
Target = EmitClassRef(CGF, Class->getSuperClass());
Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
- Target = CGF.Builder.CreateLoad(Target);
+ Target = CGF.Builder.CreateAlignedLoad(Target, CGF.getPointerAlign());
} else {
llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
llvm::Value *SuperPtr =
CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
- llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
+ llvm::Value *Super =
+ CGF.Builder.CreateAlignedLoad(SuperPtr, CGF.getPointerAlign());
Target = Super;
}
} else if (isCategoryImpl)
@@ -1816,19 +1816,19 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
else {
llvm::Value *ClassPtr = EmitSuperClassRef(Class);
ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
- Target = CGF.Builder.CreateLoad(ClassPtr);
+ Target = CGF.Builder.CreateAlignedLoad(ClassPtr, CGF.getPointerAlign());
}
// FIXME: We shouldn't need to do this cast, rectify the ASTContext and
// ObjCTypes types.
llvm::Type *ClassTy =
CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Target = CGF.Builder.CreateBitCast(Target, ClassTy);
- CGF.Builder.CreateStore(
- Target, CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 1));
+ CGF.Builder.CreateStore(Target,
+ CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize()));
return EmitMessageSend(CGF, Return, ResultType,
EmitSelector(CGF, Sel),
- ObjCSuper, ObjCTypes.SuperPtrCTy,
- true, CallArgs, Method, ObjCTypes);
+ ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
+ true, CallArgs, Method, Class, ObjCTypes);
}
/// Generate code for a message send expression.
@@ -1843,7 +1843,16 @@ CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
return EmitMessageSend(CGF, Return, ResultType,
EmitSelector(CGF, Sel),
Receiver, CGF.getContext().getObjCIdType(),
- false, CallArgs, Method, ObjCTypes);
+ false, CallArgs, Method, Class, ObjCTypes);
+}
+
+static bool isWeakLinkedClass(const ObjCInterfaceDecl *ID) {
+ do {
+ if (ID->isWeakImported())
+ return true;
+ } while ((ID = ID->getSuperClass()));
+
+ return false;
}
CodeGen::RValue
@@ -1856,6 +1865,7 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
bool IsSuper,
const CallArgList &CallArgs,
const ObjCMethodDecl *Method,
+ const ObjCInterfaceDecl *ClassReceiver,
const ObjCCommonTypesHelper &ObjCTypes) {
CallArgList ActualArgs;
if (!IsSuper)
@@ -1872,11 +1882,38 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
CGM.getContext().getCanonicalType(ResultType) &&
"Result type mismatch!");
+ bool ReceiverCanBeNull = true;
+
+ // Super dispatch assumes that self is non-null; even the messenger
+ // doesn't have a null check internally.
+ if (IsSuper) {
+ ReceiverCanBeNull = false;
+
+ // If this is a direct dispatch of a class method, check whether the class,
+ // or anything in its hierarchy, was weak-linked.
+ } else if (ClassReceiver && Method && Method->isClassMethod()) {
+ ReceiverCanBeNull = isWeakLinkedClass(ClassReceiver);
+
+ // If we're emitting a method, and self is const (meaning just ARC, for now),
+ // and the receiver is a load of self, then self is a valid object.
+ } else if (auto CurMethod =
+ dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) {
+ auto Self = CurMethod->getSelfDecl();
+ if (Self->getType().isConstQualified()) {
+ if (auto LI = dyn_cast<llvm::LoadInst>(Arg0->stripPointerCasts())) {
+ llvm::Value *SelfAddr = CGF.GetAddrOfLocalVar(Self).getPointer();
+ if (SelfAddr == LI->getPointerOperand()) {
+ ReceiverCanBeNull = false;
+ }
+ }
+ }
+ }
+
NullReturnState nullReturn;
llvm::Constant *Fn = nullptr;
if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
- if (!IsSuper) nullReturn.init(CGF, Arg0);
+ if (ReceiverCanBeNull) nullReturn.init(CGF, Arg0);
Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
: ObjCTypes.getSendStretFn(IsSuper);
} else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
@@ -1888,76 +1925,182 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
} else {
// arm64 uses objc_msgSend for stret methods and yet null receiver check
// must be made for it.
- if (!IsSuper && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
+ if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
nullReturn.init(CGF, Arg0);
Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
: ObjCTypes.getSendFn(IsSuper);
}
-
- bool requiresnullCheck = false;
- if (CGM.getLangOpts().ObjCAutoRefCount && Method)
+
+ // Emit a null-check if there's a consumed argument other than the receiver.
+ bool RequiresNullCheck = false;
+ if (ReceiverCanBeNull && CGM.getLangOpts().ObjCAutoRefCount && Method) {
for (const auto *ParamDecl : Method->params()) {
if (ParamDecl->hasAttr<NSConsumedAttr>()) {
if (!nullReturn.NullBB)
nullReturn.init(CGF, Arg0);
- requiresnullCheck = true;
+ RequiresNullCheck = true;
break;
}
}
+ }
+ llvm::Instruction *CallSite;
Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
- RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs);
+ RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs,
+ CGCalleeInfo(), &CallSite);
+
+ // Mark the call as noreturn if the method is marked noreturn and the
+ // receiver cannot be null.
+ if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
+ llvm::CallSite(CallSite).setDoesNotReturn();
+ }
+
return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
- requiresnullCheck ? Method : nullptr);
+ RequiresNullCheck ? Method : nullptr);
}
-static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
+static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT,
+ bool pointee = false) {
+ // Note that GC qualification applies recursively to C pointer types
+ // that aren't otherwise decorated. This is weird, but it's probably
+ // an intentional workaround to the unreliable placement of GC qualifiers.
if (FQT.isObjCGCStrong())
return Qualifiers::Strong;
-
- if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak)
+
+ if (FQT.isObjCGCWeak())
return Qualifiers::Weak;
+
+ if (auto ownership = FQT.getObjCLifetime()) {
+ // Ownership does not apply recursively to C pointer types.
+ if (pointee) return Qualifiers::GCNone;
+ switch (ownership) {
+ case Qualifiers::OCL_Weak: return Qualifiers::Weak;
+ case Qualifiers::OCL_Strong: return Qualifiers::Strong;
+ case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone;
+ case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?");
+ case Qualifiers::OCL_None: llvm_unreachable("known nonzero");
+ }
+ llvm_unreachable("bad objc ownership");
+ }
- // check for __unsafe_unretained
- if (FQT.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
- return Qualifiers::GCNone;
-
+ // Treat unqualified retainable pointers as strong.
if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
return Qualifiers::Strong;
- if (const PointerType *PT = FQT->getAs<PointerType>())
- return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
+ // Walk into C pointer types, but only in GC.
+ if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) {
+ if (const PointerType *PT = FQT->getAs<PointerType>())
+ return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true);
+ }
return Qualifiers::GCNone;
}
+namespace {
+ struct IvarInfo {
+ CharUnits Offset;
+ uint64_t SizeInWords;
+ IvarInfo(CharUnits offset, uint64_t sizeInWords)
+ : Offset(offset), SizeInWords(sizeInWords) {}
+
+ // Allow sorting based on byte pos.
+ bool operator<(const IvarInfo &other) const {
+ return Offset < other.Offset;
+ }
+ };
+
+ /// A helper class for building GC layout strings.
+ class IvarLayoutBuilder {
+ CodeGenModule &CGM;
+
+ /// The start of the layout. Offsets will be relative to this value,
+ /// and entries less than this value will be silently discarded.
+ CharUnits InstanceBegin;
+
+ /// The end of the layout. Offsets will never exceed this value.
+ CharUnits InstanceEnd;
+
+ /// Whether we're generating the strong layout or the weak layout.
+ bool ForStrongLayout;
+
+ /// Whether the offsets in IvarsInfo might be out-of-order.
+ bool IsDisordered = false;
+
+ llvm::SmallVector<IvarInfo, 8> IvarsInfo;
+ public:
+ IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
+ CharUnits instanceEnd, bool forStrongLayout)
+ : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
+ ForStrongLayout(forStrongLayout) {
+ }
+
+ void visitRecord(const RecordType *RT, CharUnits offset);
+
+ template <class Iterator, class GetOffsetFn>
+ void visitAggregate(Iterator begin, Iterator end,
+ CharUnits aggrOffset,
+ const GetOffsetFn &getOffset);
+
+ void visitField(const FieldDecl *field, CharUnits offset);
+
+ /// Add the layout of a block implementation.
+ void visitBlock(const CGBlockInfo &blockInfo);
+
+ /// Is there any information for an interesting bitmap?
+ bool hasBitmapData() const { return !IvarsInfo.empty(); }
+
+ llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
+ llvm::SmallVectorImpl<unsigned char> &buffer);
+
+ static void dump(ArrayRef<unsigned char> buffer) {
+ const unsigned char *s = buffer.data();
+ for (unsigned i = 0, e = buffer.size(); i < e; i++)
+ if (!(s[i] & 0xf0))
+ printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
+ else
+ printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
+ printf("\n");
+ }
+ };
+}
+
llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
const CGBlockInfo &blockInfo) {
llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
- if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
- !CGM.getLangOpts().ObjCAutoRefCount)
+ if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
return nullPtr;
- bool hasUnion = false;
- SkipIvars.clear();
- IvarsInfo.clear();
- unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
- unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
+ IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize,
+ /*for strong layout*/ true);
+
+ builder.visitBlock(blockInfo);
+
+ if (!builder.hasBitmapData())
+ return nullPtr;
+
+ llvm::SmallVector<unsigned char, 32> buffer;
+ llvm::Constant *C = builder.buildBitmap(*this, buffer);
+ if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
+ printf("\n block variable layout for block: ");
+ builder.dump(buffer);
+ }
+ return C;
+}
+
+void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
// __isa is the first field in block descriptor and must assume by runtime's
// convention that it is GC'able.
- IvarsInfo.push_back(GC_IVAR(0, 1));
+ IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1));
const BlockDecl *blockDecl = blockInfo.getBlockDecl();
- // Calculate the basic layout of the block structure.
- const llvm::StructLayout *layout =
- CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
-
// Ignore the optional 'this' capture: C++ objects are not assumed
// to be GC'ed.
+ CharUnits lastFieldOffset;
+
// Walk the captured variables.
for (const auto &CI : blockDecl->captures()) {
const VarDecl *variable = CI.getVariable();
@@ -1968,64 +2111,51 @@ llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
// Ignore constant captures.
if (capture.isConstant()) continue;
- uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
+ CharUnits fieldOffset = capture.getOffset();
+
+ // Block fields are not necessarily ordered; if we detect that we're
+ // adding them out-of-order, make sure we sort later.
+ if (fieldOffset < lastFieldOffset)
+ IsDisordered = true;
+ lastFieldOffset = fieldOffset;
// __block variables are passed by their descriptor address.
if (CI.isByRef()) {
- IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
+ IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
continue;
}
assert(!type->isArrayType() && "array variable should not be caught");
if (const RecordType *record = type->getAs<RecordType>()) {
- BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
+ visitRecord(record, fieldOffset);
continue;
}
Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
- unsigned fieldSize = CGM.getContext().getTypeSize(type);
-
- if (GCAttr == Qualifiers::Strong)
- IvarsInfo.push_back(GC_IVAR(fieldOffset,
- fieldSize / WordSizeInBits));
- else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
- SkipIvars.push_back(GC_IVAR(fieldOffset,
- fieldSize / ByteSizeInBits));
- }
-
- if (IvarsInfo.empty())
- return nullPtr;
- // Sort on byte position; captures might not be allocated in order,
- // and unions can do funny things.
- llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
- llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
-
- std::string BitMap;
- llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
- if (CGM.getLangOpts().ObjCGCBitmapPrint) {
- printf("\n block variable layout for block: ");
- const unsigned char *s = (const unsigned char*)BitMap.c_str();
- for (unsigned i = 0, e = BitMap.size(); i < e; i++)
- if (!(s[i] & 0xf0))
- printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
- else
- printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
- printf("\n");
+ if (GCAttr == Qualifiers::Strong) {
+ assert(CGM.getContext().getTypeSize(type)
+ == CGM.getTarget().getPointerWidth(0));
+ IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
+ }
}
-
- return C;
}
+
/// getBlockCaptureLifetime - This routine returns life time of the captured
/// block variable for the purpose of block layout meta-data generation. FQT is
/// the type of the variable captured in the block.
Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
bool ByrefLayout) {
+ // If it has an ownership qualifier, we're done.
+ if (auto lifetime = FQT.getObjCLifetime())
+ return lifetime;
+
+ // If it doesn't, and this is ARC, it has no ownership.
if (CGM.getLangOpts().ObjCAutoRefCount)
- return FQT.getObjCLifetime();
+ return Qualifiers::OCL_None;
- // MRR.
+ // In MRC, retainable pointers are owned by non-__block variables.
if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
@@ -2361,9 +2491,8 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
}
}
- int e = Layout.size()-1;
- while (e >= 0) {
- unsigned char inst = Layout[e--];
+ while (!Layout.empty()) {
+ unsigned char inst = Layout.back();
enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
Layout.pop_back();
@@ -2376,19 +2505,19 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
// Block variable layout instruction has been inlined.
if (CGM.getLangOpts().ObjCGCBitmapPrint) {
if (ComputeByrefLayout)
- printf("\n Inline instruction for BYREF variable layout: ");
+ printf("\n Inline BYREF variable layout: ");
else
- printf("\n Inline instruction for block variable layout: ");
- printf("0x0%" PRIx64 "\n", Result);
- }
- if (WordSizeInBytes == 8) {
- const llvm::APInt Instruction(64, Result);
- return llvm::Constant::getIntegerValue(CGM.Int64Ty, Instruction);
- }
- else {
- const llvm::APInt Instruction(32, Result);
- return llvm::Constant::getIntegerValue(CGM.Int32Ty, Instruction);
+ printf("\n Inline block variable layout: ");
+ printf("0x0%" PRIx64 "", Result);
+ if (auto numStrong = (Result & 0xF00) >> 8)
+ printf(", BL_STRONG:%d", (int) numStrong);
+ if (auto numByref = (Result & 0x0F0) >> 4)
+ printf(", BL_BYREF:%d", (int) numByref);
+ if (auto numWeak = (Result & 0x00F) >> 0)
+ printf(", BL_WEAK:%d", (int) numWeak);
+ printf(", BL_OPERATOR:0\n");
}
+ return llvm::ConstantInt::get(CGM.IntPtrTy, Result);
}
unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
@@ -2399,9 +2528,9 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
if (CGM.getLangOpts().ObjCGCBitmapPrint) {
if (ComputeByrefLayout)
- printf("\n BYREF variable layout: ");
+ printf("\n Byref variable layout: ");
else
- printf("\n block variable layout: ");
+ printf("\n Block variable layout: ");
for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
unsigned char inst = BitMap[i];
enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
@@ -2443,7 +2572,7 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
llvm::GlobalVariable *Entry = CreateMetadataVar(
"OBJC_CLASS_NAME_",
llvm::ConstantDataArray::getString(VMContext, BitMap, false),
- "__TEXT,__objc_classname,cstring_literals", 1, true);
+ "__TEXT,__objc_classname,cstring_literals", CharUnits::One(), true);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -2511,6 +2640,8 @@ llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
if (const RecordType *record = T->getAs<RecordType>()) {
BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
llvm::Constant *Result = getBitmapBlockLayout(true);
+ if (isa<llvm::ConstantInt>(Result))
+ Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy);
return Result;
}
llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
@@ -2699,7 +2830,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
// No special section, but goes in llvm.used
return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(), Init,
- StringRef(), 0, true);
+ StringRef(), CGM.getPointerAlign(), true);
}
/*
@@ -2738,7 +2869,7 @@ CGObjCMac::EmitProtocolList(Twine Name,
llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
llvm::GlobalVariable *GV =
CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
- 4, false);
+ CGM.getPointerAlign(), false);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
}
@@ -2779,15 +2910,26 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
const ObjCCommonTypesHelper &ObjCTypes) {
SmallVector<llvm::Constant *, 16> Properties;
llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
+
+ auto AddProperty = [&](const ObjCPropertyDecl *PD) {
+ llvm::Constant *Prop[] = {GetPropertyName(PD->getIdentifier()),
+ GetPropertyTypeString(PD, Container)};
+ Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
+ };
+ if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
+ for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
+ for (auto *PD : ClassExt->properties()) {
+ PropertySet.insert(PD->getIdentifier());
+ AddProperty(PD);
+ }
for (const auto *PD : OCD->properties()) {
- PropertySet.insert(PD->getIdentifier());
- llvm::Constant *Prop[] = {
- GetPropertyName(PD->getIdentifier()),
- GetPropertyTypeString(PD, Container)
- };
- Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
- Prop));
+ // Don't emit duplicate metadata for properties that were already in a
+ // class extension.
+ if (!PropertySet.insert(PD->getIdentifier()).second)
+ continue;
+ AddProperty(PD);
}
+
if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
for (const auto *P : OID->all_referenced_protocols())
PushProtocolProperties(PropertySet, Properties, Container, P, ObjCTypes);
@@ -2815,7 +2957,7 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
CreateMetadataVar(Name, Init,
(ObjCABI == 2) ? "__DATA, __objc_const" :
"__OBJC,__property,regular,no_dead_strip",
- (ObjCABI == 2) ? 8 : 4,
+ CGM.getPointerAlign(),
true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
}
@@ -2834,7 +2976,7 @@ CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
llvm::GlobalVariable *GV = CreateMetadataVar(
Name, Init, (ObjCABI == 2) ? "__DATA, __objc_const" : StringRef(),
- (ObjCABI == 2) ? 8 : 4, true);
+ CGM.getPointerAlign(), true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
}
@@ -2872,7 +3014,8 @@ CGObjCMac::EmitMethodDescList(Twine Name, const char *Section,
Values[1] = llvm::ConstantArray::get(AT, Methods);
llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
- llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
+ llvm::GlobalVariable *GV =
+ CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
return llvm::ConstantExpr::getBitCast(GV,
ObjCTypes.MethodDescriptionListPtrTy);
}
@@ -2944,7 +3087,8 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
llvm::GlobalVariable *GV =
CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Init,
- "__OBJC,__category,regular,no_dead_strip", 4, true);
+ "__OBJC,__category,regular,no_dead_strip",
+ CGM.getPointerAlign(), true);
DefinedCategories.push_back(GV);
DefinedCategoryNames.insert(ExtName.str());
// method definition entries must be clear for next implementation.
@@ -2952,10 +3096,24 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
}
enum FragileClassFlags {
+ /// Apparently: is not a meta-class.
FragileABI_Class_Factory = 0x00001,
+
+ /// Is a meta-class.
FragileABI_Class_Meta = 0x00002,
+
+ /// Has a non-trivial constructor or destructor.
FragileABI_Class_HasCXXStructors = 0x02000,
- FragileABI_Class_Hidden = 0x20000
+
+ /// Has hidden visibility.
+ FragileABI_Class_Hidden = 0x20000,
+
+ /// Class implementation was compiled under ARC.
+ FragileABI_Class_CompiledByARC = 0x04000000,
+
+ /// Class implementation was compiled under MRC and has MRC weak ivars.
+ /// Exclusive with CompiledByARC.
+ FragileABI_Class_HasMRCWeakIvars = 0x08000000,
};
enum NonFragileClassFlags {
@@ -2965,7 +3123,7 @@ enum NonFragileClassFlags {
/// Is a root class.
NonFragileABI_Class_Root = 0x00002,
- /// Has a C++ constructor and destructor.
+ /// Has a non-trivial constructor or destructor.
NonFragileABI_Class_HasCXXStructors = 0x00004,
/// Has hidden visibility.
@@ -2981,9 +3139,46 @@ enum NonFragileClassFlags {
NonFragileABI_Class_CompiledByARC = 0x00080,
/// Class has non-trivial destructors, but zero-initialization is okay.
- NonFragileABI_Class_HasCXXDestructorOnly = 0x00100
+ NonFragileABI_Class_HasCXXDestructorOnly = 0x00100,
+
+ /// Class implementation was compiled under MRC and has MRC weak ivars.
+ /// Exclusive with CompiledByARC.
+ NonFragileABI_Class_HasMRCWeakIvars = 0x00200,
};
+static bool hasWeakMember(QualType type) {
+ if (type.getObjCLifetime() == Qualifiers::OCL_Weak) {
+ return true;
+ }
+
+ if (auto recType = type->getAs<RecordType>()) {
+ for (auto field : recType->getDecl()->fields()) {
+ if (hasWeakMember(field->getType()))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/// For compatibility, we only want to set the "HasMRCWeakIvars" flag
+/// (and actually fill in a layout string) if we really do have any
+/// __weak ivars.
+static bool hasMRCWeakIvars(CodeGenModule &CGM,
+ const ObjCImplementationDecl *ID) {
+ if (!CGM.getLangOpts().ObjCWeak) return false;
+ assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
+
+ for (const ObjCIvarDecl *ivar =
+ ID->getClassInterface()->all_declared_ivar_begin();
+ ivar; ivar = ivar->getNextIvar()) {
+ if (hasWeakMember(ivar->getType()))
+ return true;
+ }
+
+ return false;
+}
+
/*
struct _objc_class {
Class isa;
@@ -3017,8 +3212,16 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
unsigned Flags = FragileABI_Class_Factory;
if (ID->hasNonZeroConstructors() || ID->hasDestructors())
Flags |= FragileABI_Class_HasCXXStructors;
- unsigned Size =
- CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
+
+ bool hasMRCWeak = false;
+
+ if (CGM.getLangOpts().ObjCAutoRefCount)
+ Flags |= FragileABI_Class_CompiledByARC;
+ else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
+ Flags |= FragileABI_Class_HasMRCWeakIvars;
+
+ CharUnits Size =
+ CGM.getContext().getASTObjCImplementationLayout(ID).getSize();
// FIXME: Set CXX-structors flag.
if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
@@ -3062,7 +3265,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
// Version is always 0.
Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
- Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
+ Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size.getQuantity());
Values[ 6] = EmitIvarList(ID, false);
Values[7] = EmitMethodList("OBJC_INSTANCE_METHODS_" + ID->getName(),
"__OBJC,__inst_meth,regular,no_dead_strip",
@@ -3070,8 +3273,8 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
// cache is always NULL.
Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Values[ 9] = Protocols;
- Values[10] = BuildIvarLayout(ID, true);
- Values[11] = EmitClassExtension(ID);
+ Values[10] = BuildStrongIvarLayout(ID, CharUnits::Zero(), Size);
+ Values[11] = EmitClassExtension(ID, Size, hasMRCWeak);
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Values);
std::string Name("OBJC_CLASS_");
@@ -3084,10 +3287,10 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
"Forward metaclass reference has incorrect type.");
GV->setInitializer(Init);
GV->setSection(Section);
- GV->setAlignment(4);
+ GV->setAlignment(CGM.getPointerAlign().getQuantity());
CGM.addCompilerUsedGlobal(GV);
} else
- GV = CreateMetadataVar(Name, Init, Section, 4, true);
+ GV = CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
DefinedClasses.push_back(GV);
ImplementedClasses.push_back(Interface);
// method definition entries must be clear for next implementation.
@@ -3198,6 +3401,10 @@ llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
}
/*
+ Emit a "class extension", which in this specific context means extra
+ data that doesn't fit in the normal fragile-ABI class structure, and
+ has nothing to do with the language concept of a class extension.
+
struct objc_class_ext {
uint32_t size;
const char *weak_ivar_layout;
@@ -3205,13 +3412,15 @@ llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
};
*/
llvm::Constant *
-CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
+CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
+ CharUnits InstanceSize, bool hasMRCWeakIvars) {
uint64_t Size =
CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
llvm::Constant *Values[3];
Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
- Values[1] = BuildIvarLayout(ID, false);
+ Values[1] = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
+ hasMRCWeakIvars);
Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
ID, ID->getClassInterface(), ObjCTypes);
@@ -3222,7 +3431,8 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
llvm::Constant *Init =
llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), Init,
- "__OBJC,__class_ext,regular,no_dead_strip", 4, true);
+ "__OBJC,__class_ext,regular,no_dead_strip",
+ CGM.getPointerAlign(), true);
}
/*
@@ -3280,11 +3490,12 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
if (ForClass)
GV =
CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), Init,
- "__OBJC,__class_vars,regular,no_dead_strip", 4, true);
+ "__OBJC,__class_vars,regular,no_dead_strip",
+ CGM.getPointerAlign(), true);
else
GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), Init,
- "__OBJC,__instance_vars,regular,no_dead_strip", 4,
- true);
+ "__OBJC,__instance_vars,regular,no_dead_strip",
+ CGM.getPointerAlign(), true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
}
@@ -3334,7 +3545,8 @@ llvm::Constant *CGObjCMac::EmitMethodList(Twine Name,
Values[2] = llvm::ConstantArray::get(AT, Methods);
llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
- llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
+ llvm::GlobalVariable *GV =
+ CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
}
@@ -3359,7 +3571,7 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
llvm::Constant *Init,
StringRef Section,
- unsigned Align,
+ CharUnits Align,
bool AddToUsed) {
llvm::Type *Ty = Init->getType();
llvm::GlobalVariable *GV =
@@ -3367,8 +3579,7 @@ llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
llvm::GlobalValue::PrivateLinkage, Init, Name);
if (!Section.empty())
GV->setSection(Section);
- if (Align)
- GV->setAlignment(Align);
+ GV->setAlignment(Align.getQuantity());
if (AddToUsed)
CGM.addCompilerUsedGlobal(GV);
return GV;
@@ -3421,16 +3632,16 @@ void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
}
namespace {
- struct PerformFragileFinally : EHScopeStack::Cleanup {
+ struct PerformFragileFinally final : EHScopeStack::Cleanup {
const Stmt &S;
- llvm::Value *SyncArgSlot;
- llvm::Value *CallTryExitVar;
- llvm::Value *ExceptionData;
+ Address SyncArgSlot;
+ Address CallTryExitVar;
+ Address ExceptionData;
ObjCTypesHelper &ObjCTypes;
PerformFragileFinally(const Stmt *S,
- llvm::Value *SyncArgSlot,
- llvm::Value *CallTryExitVar,
- llvm::Value *ExceptionData,
+ Address SyncArgSlot,
+ Address CallTryExitVar,
+ Address ExceptionData,
ObjCTypesHelper *ObjCTypes)
: S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
@@ -3447,7 +3658,7 @@ namespace {
CGF.EmitBlock(FinallyCallExit);
CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
- ExceptionData);
+ ExceptionData.getPointer());
CGF.EmitBlock(FinallyNoCallExit);
@@ -3568,7 +3779,7 @@ void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
void FragileHazards::emitHazardsInNewBlocks() {
if (Locals.empty()) return;
- CGBuilderTy Builder(CGF.getLLVMContext());
+ CGBuilderTy Builder(CGF, CGF.getLLVMContext());
// Iterate through all blocks, skipping those prior to the try.
for (llvm::Function::iterator
@@ -3607,6 +3818,10 @@ static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
if (V) S.insert(V);
}
+static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) {
+ if (V.isValid()) S.insert(V.getPointer());
+}
+
void FragileHazards::collectLocals() {
// Compute a set of allocas to ignore.
llvm::DenseSet<llvm::Value*> AllocasToIgnore;
@@ -3760,21 +3975,23 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
// @synchronized. We can't avoid a temp here because we need the
// value to be preserved. If the backend ever does liveness
// correctly after setjmp, this will be unnecessary.
- llvm::Value *SyncArgSlot = nullptr;
+ Address SyncArgSlot = Address::invalid();
if (!isTry) {
llvm::Value *SyncArg =
CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);
- SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
+ SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(),
+ CGF.getPointerAlign(), "sync.arg");
CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
}
// Allocate memory for the setjmp buffer. This needs to be kept
// live throughout the try and catch blocks.
- llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
- "exceptiondata.ptr");
+ Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
+ CGF.getPointerAlign(),
+ "exceptiondata.ptr");
// Create the fragile hazards. Note that this will not capture any
// of the allocas required for exception processing, but will
@@ -3790,12 +4007,13 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
// The setjmp-safety rule here is that we should always store to this
// variable in a place that dominates the branch through the cleanup
// without passing through any setjmps.
- llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
- "_call_try_exit");
+ Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
+ CharUnits::One(),
+ "_call_try_exit");
// A slot containing the exception to rethrow. Only needed when we
// have both a @catch and a @finally.
- llvm::Value *PropagatingExnVar = nullptr;
+ Address PropagatingExnVar = Address::invalid();
// Push a normal cleanup to leave the try scope.
CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
@@ -3808,13 +4026,14 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
// - Call objc_exception_try_enter to push ExceptionData on top of
// the EH stack.
CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
- ExceptionData);
+ ExceptionData.getPointer());
// - Call setjmp on the exception data buffer.
llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
- ObjCTypes.ExceptionDataTy, ExceptionData, GEPIndexes, "setjmp_buffer");
+ ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes,
+ "setjmp_buffer");
llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
SetJmpResult->setCanReturnTwice();
@@ -3854,7 +4073,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
// nothing can cross this so the value is already in SSA form.
llvm::CallInst *Caught =
CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
- ExceptionData, "caught");
+ ExceptionData.getPointer(), "caught");
// Push the exception to rethrow onto the EH value stack for the
// benefit of any @throws in the handlers.
@@ -3870,13 +4089,14 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
// Save the currently-propagating exception before
// objc_exception_try_enter clears the exception slot.
PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
+ CGF.getPointerAlign(),
"propagating_exception");
CGF.Builder.CreateStore(Caught, PropagatingExnVar);
// Enter a new exception try block (in case a @catch block
// throws an exception).
CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
- ExceptionData);
+ ExceptionData.getPointer());
llvm::CallInst *SetJmpResult =
CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(),
@@ -3928,7 +4148,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
// These types work out because ConvertType(id) == i8*.
- CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
+ EmitInitOfCatchParam(CGF, Caught, CatchParam);
}
CGF.EmitStmt(CatchStmt->getCatchBody());
@@ -3975,7 +4195,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
llvm::Value *Tmp =
CGF.Builder.CreateBitCast(Caught,
CGF.ConvertType(CatchParam->getType()));
- CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
+ EmitInitOfCatchParam(CGF, Tmp, CatchParam);
CGF.EmitStmt(CatchStmt->getCatchBody());
@@ -4008,10 +4228,10 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
// Extract the new exception and save it to the
// propagating-exception slot.
- assert(PropagatingExnVar);
+ assert(PropagatingExnVar.isValid());
llvm::CallInst *NewCaught =
CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
- ExceptionData, "caught");
+ ExceptionData.getPointer(), "caught");
CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
// Don't pop the catch handler; the throw already did.
@@ -4036,14 +4256,14 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
if (CGF.HaveInsertPoint()) {
// If we have a propagating-exception variable, check it.
llvm::Value *PropagatingExn;
- if (PropagatingExnVar) {
+ if (PropagatingExnVar.isValid()) {
PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
// Otherwise, just look in the buffer for the exception to throw.
} else {
llvm::CallInst *Caught =
CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
- ExceptionData);
+ ExceptionData.getPointer());
PropagatingExn = Caught;
}
@@ -4083,14 +4303,13 @@ void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
/// object: objc_read_weak (id *src)
///
llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
- llvm::Value *AddrWeakObj) {
- llvm::Type* DestTy =
- cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
+ Address AddrWeakObj) {
+ llvm::Type* DestTy = AddrWeakObj.getElementType();
AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
ObjCTypes.PtrObjectPtrTy);
llvm::Value *read_weak =
CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
- AddrWeakObj, "weakread");
+ AddrWeakObj.getPointer(), "weakread");
read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
return read_weak;
}
@@ -4099,7 +4318,7 @@ llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
/// objc_assign_weak (id src, id *dst)
///
void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
+ llvm::Value *src, Address dst) {
llvm::Type * SrcTy = src->getType();
if (!isa<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
@@ -4110,7 +4329,7 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- llvm::Value *args[] = { src, dst };
+ llvm::Value *args[] = { src, dst.getPointer() };
CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
args, "weakassign");
return;
@@ -4120,7 +4339,7 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
/// objc_assign_global (id src, id *dst)
///
void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst,
+ llvm::Value *src, Address dst,
bool threadlocal) {
llvm::Type * SrcTy = src->getType();
if (!isa<llvm::PointerType>(SrcTy)) {
@@ -4132,7 +4351,7 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- llvm::Value *args[] = { src, dst };
+ llvm::Value *args[] = { src, dst.getPointer() };
if (!threadlocal)
CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
args, "globalassign");
@@ -4146,7 +4365,7 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
///
void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst,
+ llvm::Value *src, Address dst,
llvm::Value *ivarOffset) {
assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
llvm::Type * SrcTy = src->getType();
@@ -4159,7 +4378,7 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- llvm::Value *args[] = { src, dst, ivarOffset };
+ llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
return;
}
@@ -4168,7 +4387,7 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
/// objc_assign_strongCast (id src, id *dst)
///
void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
+ llvm::Value *src, Address dst) {
llvm::Type * SrcTy = src->getType();
if (!isa<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
@@ -4179,19 +4398,19 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- llvm::Value *args[] = { src, dst };
+ llvm::Value *args[] = { src, dst.getPointer() };
CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
- args, "weakassign");
+ args, "strongassign");
return;
}
void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
- llvm::Value *DestPtr,
- llvm::Value *SrcPtr,
+ Address DestPtr,
+ Address SrcPtr,
llvm::Value *size) {
SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
- llvm::Value *args[] = { DestPtr, SrcPtr, size };
+ llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size };
CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
}
@@ -4283,7 +4502,7 @@ void CGObjCCommonMac::EmitImageInfo() {
// Indicate whether we're compiling this to run on a simulator.
const llvm::Triple &Triple = CGM.getTarget().getTriple();
- if (Triple.isiOS() &&
+ if ((Triple.isiOS() || Triple.isWatchOS()) &&
(Triple.getArch() == llvm::Triple::x86 ||
Triple.getArch() == llvm::Triple::x86_64))
Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
@@ -4312,7 +4531,8 @@ void CGObjCMac::EmitModuleInfo() {
};
CreateMetadataVar("OBJC_MODULES",
llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
- "__OBJC,__module_info,regular,no_dead_strip", 4, true);
+ "__OBJC,__module_info,regular,no_dead_strip",
+ CGM.getPointerAlign(), true);
}
llvm::Constant *CGObjCMac::EmitModuleSymbols() {
@@ -4356,7 +4576,8 @@ llvm::Constant *CGObjCMac::EmitModuleSymbols() {
llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
llvm::GlobalVariable *GV = CreateMetadataVar(
- "OBJC_SYMBOLS", Init, "__OBJC,__symbols,regular,no_dead_strip", 4, true);
+ "OBJC_SYMBOLS", Init, "__OBJC,__symbols,regular,no_dead_strip",
+ CGM.getPointerAlign(), true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
}
@@ -4372,10 +4593,11 @@ llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
ObjCTypes.ClassPtrTy);
Entry = CreateMetadataVar(
"OBJC_CLASS_REFERENCES_", Casted,
- "__OBJC,__cls_refs,literal_pointers,no_dead_strip", 4, true);
+ "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
+ CGM.getPointerAlign(), true);
}
- return CGF.Builder.CreateLoad(Entry);
+ return CGF.Builder.CreateAlignedLoad(Entry, CGF.getPointerAlign());
}
llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
@@ -4388,23 +4610,25 @@ llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
return EmitClassRefFromId(CGF, II);
}
-llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel,
- bool lvalue) {
- llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
+llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
+ return CGF.Builder.CreateLoad(EmitSelectorAddr(CGF, Sel));
+}
+
+Address CGObjCMac::EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel) {
+ CharUnits Align = CGF.getPointerAlign();
+ llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
if (!Entry) {
llvm::Constant *Casted =
llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
ObjCTypes.SelectorPtrTy);
Entry = CreateMetadataVar(
"OBJC_SELECTOR_REFERENCES_", Casted,
- "__OBJC,__message_refs,literal_pointers,no_dead_strip", 4, true);
+ "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true);
Entry->setExternallyInitialized(true);
}
- if (lvalue)
- return Entry;
- return CGF.Builder.CreateLoad(Entry);
+ return Address(Entry, Align);
}
llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
@@ -4415,7 +4639,7 @@ llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
llvm::ConstantDataArray::getString(VMContext, RuntimeName),
((ObjCABI == 2) ? "__TEXT,__objc_classname,cstring_literals"
: "__TEXT,__cstring,cstring_literals"),
- 1, true);
+ CharUnits::One(), true);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -4435,308 +4659,243 @@ llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
}
-void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
- unsigned int BytePos,
- bool ForStrongLayout,
- bool &HasUnion) {
+void IvarLayoutBuilder::visitRecord(const RecordType *RT,
+ CharUnits offset) {
const RecordDecl *RD = RT->getDecl();
- // FIXME - Use iterator.
- SmallVector<const FieldDecl*, 16> Fields(RD->fields());
- llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
- const llvm::StructLayout *RecLayout =
- CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
- BuildAggrIvarLayout(nullptr, RecLayout, RD, Fields, BytePos, ForStrongLayout,
- HasUnion);
-}
+ // If this is a union, remember that we had one, because it might mess
+ // up the ordering of layout entries.
+ if (RD->isUnion())
+ IsDisordered = true;
+
+ const ASTRecordLayout *recLayout = nullptr;
+ visitAggregate(RD->field_begin(), RD->field_end(), offset,
+ [&](const FieldDecl *field) -> CharUnits {
+ if (!recLayout)
+ recLayout = &CGM.getContext().getASTRecordLayout(RD);
+ auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
+ return CGM.getContext().toCharUnitsFromBits(offsetInBits);
+ });
+}
+
+template <class Iterator, class GetOffsetFn>
+void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
+ CharUnits aggregateOffset,
+ const GetOffsetFn &getOffset) {
+ for (; begin != end; ++begin) {
+ auto field = *begin;
+
+ // Skip over bitfields.
+ if (field->isBitField()) {
+ continue;
+ }
-void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
- const llvm::StructLayout *Layout,
- const RecordDecl *RD,
- ArrayRef<const FieldDecl*> RecFields,
- unsigned int BytePos, bool ForStrongLayout,
- bool &HasUnion) {
- bool IsUnion = (RD && RD->isUnion());
- uint64_t MaxUnionIvarSize = 0;
- uint64_t MaxSkippedUnionIvarSize = 0;
- const FieldDecl *MaxField = nullptr;
- const FieldDecl *MaxSkippedField = nullptr;
- const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
- uint64_t MaxFieldOffset = 0;
- uint64_t MaxSkippedFieldOffset = 0;
- uint64_t LastBitfieldOrUnnamedOffset = 0;
- uint64_t FirstFieldDelta = 0;
+ // Compute the offset of the field within the aggregate.
+ CharUnits fieldOffset = aggregateOffset + getOffset(field);
- if (RecFields.empty())
- return;
- unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
- unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
- if (!RD && CGM.getLangOpts().ObjCAutoRefCount) {
- const FieldDecl *FirstField = RecFields[0];
- FirstFieldDelta =
- ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
+ visitField(field, fieldOffset);
}
-
- for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
- const FieldDecl *Field = RecFields[i];
- uint64_t FieldOffset;
- if (RD) {
- // Note that 'i' here is actually the field index inside RD of Field,
- // although this dependency is hidden.
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
- FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
- } else
- FieldOffset =
- ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
+}
- // Skip over unnamed or bitfields
- if (!Field->getIdentifier() || Field->isBitField()) {
- LastFieldBitfieldOrUnnamed = Field;
- LastBitfieldOrUnnamedOffset = FieldOffset;
- continue;
- }
+/// Collect layout information for the given fields into IvarsInfo.
+void IvarLayoutBuilder::visitField(const FieldDecl *field,
+ CharUnits fieldOffset) {
+ QualType fieldType = field->getType();
- LastFieldBitfieldOrUnnamed = nullptr;
- QualType FQT = Field->getType();
- if (FQT->isRecordType() || FQT->isUnionType()) {
- if (FQT->isUnionType())
- HasUnion = true;
+ // Drill down into arrays.
+ uint64_t numElts = 1;
+ while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
+ numElts *= arrayType->getSize().getZExtValue();
+ fieldType = arrayType->getElementType();
+ }
- BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
- BytePos + FieldOffset,
- ForStrongLayout, HasUnion);
- continue;
- }
+ assert(!fieldType->isArrayType() && "ivar of non-constant array type?");
- if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
- const ConstantArrayType *CArray =
- dyn_cast_or_null<ConstantArrayType>(Array);
- uint64_t ElCount = CArray->getSize().getZExtValue();
- assert(CArray && "only array with known element size is supported");
- FQT = CArray->getElementType();
- while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
- const ConstantArrayType *CArray =
- dyn_cast_or_null<ConstantArrayType>(Array);
- ElCount *= CArray->getSize().getZExtValue();
- FQT = CArray->getElementType();
- }
- if (FQT->isRecordType() && ElCount) {
- int OldIndex = IvarsInfo.size() - 1;
- int OldSkIndex = SkipIvars.size() -1;
+ // If we ended up with a zero-sized array, we've done what we can do within
+ // the limits of this layout encoding.
+ if (numElts == 0) return;
- const RecordType *RT = FQT->getAs<RecordType>();
- BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
- ForStrongLayout, HasUnion);
+ // Recurse if the base element type is a record type.
+ if (auto recType = fieldType->getAs<RecordType>()) {
+ size_t oldEnd = IvarsInfo.size();
- // Replicate layout information for each array element. Note that
- // one element is already done.
- uint64_t ElIx = 1;
- for (int FirstIndex = IvarsInfo.size() - 1,
- FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
- uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
- for (int i = OldIndex+1; i <= FirstIndex; ++i)
- IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
- IvarsInfo[i].ivar_size));
- for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
- SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
- SkipIvars[i].ivar_size));
- }
- continue;
- }
- }
- // At this point, we are done with Record/Union and array there of.
- // For other arrays we are down to its element type.
- Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
-
- unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
- if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
- || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
- if (IsUnion) {
- uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
- if (UnionIvarSize > MaxUnionIvarSize) {
- MaxUnionIvarSize = UnionIvarSize;
- MaxField = Field;
- MaxFieldOffset = FieldOffset;
- }
- } else {
- IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
- FieldSize / WordSizeInBits));
- }
- } else if ((ForStrongLayout &&
- (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
- || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
- if (IsUnion) {
- // FIXME: Why the asymmetry? We divide by word size in bits on other
- // side.
- uint64_t UnionIvarSize = FieldSize / ByteSizeInBits;
- if (UnionIvarSize > MaxSkippedUnionIvarSize) {
- MaxSkippedUnionIvarSize = UnionIvarSize;
- MaxSkippedField = Field;
- MaxSkippedFieldOffset = FieldOffset;
+ visitRecord(recType, fieldOffset);
+
+ // If we have an array, replicate the first entry's layout information.
+ auto numEltEntries = IvarsInfo.size() - oldEnd;
+ if (numElts != 1 && numEltEntries != 0) {
+ CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
+ for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
+ // Copy the last numEltEntries onto the end of the array, adjusting
+ // each for the element size.
+ for (size_t i = 0; i != numEltEntries; ++i) {
+ auto firstEntry = IvarsInfo[oldEnd + i];
+ IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
+ firstEntry.SizeInWords));
}
- } else {
- // FIXME: Why the asymmetry, we divide by byte size in bits here?
- SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
- FieldSize / ByteSizeInBits));
}
}
+
+ return;
}
- if (LastFieldBitfieldOrUnnamed) {
- if (LastFieldBitfieldOrUnnamed->isBitField()) {
- // Last field was a bitfield. Must update skip info.
- uint64_t BitFieldSize
- = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
- GC_IVAR skivar;
- skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
- skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
- + ((BitFieldSize % ByteSizeInBits) != 0);
- SkipIvars.push_back(skivar);
- } else {
- assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
- // Last field was unnamed. Must update skip info.
- unsigned FieldSize
- = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
- SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
- FieldSize / ByteSizeInBits));
- }
+ // Classify the element type.
+ Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
+
+ // If it matches what we're looking for, add an entry.
+ if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
+ || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
+ assert(CGM.getContext().getTypeSizeInChars(fieldType)
+ == CGM.getPointerSize());
+ IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
}
+}
- if (MaxField)
- IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
- MaxUnionIvarSize));
- if (MaxSkippedField)
- SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
- MaxSkippedUnionIvarSize));
-}
-
-/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
-/// the computations and returning the layout bitmap (for ivar or blocks) in
-/// the given argument BitMap string container. Routine reads
-/// two containers, IvarsInfo and SkipIvars which are assumed to be
-/// filled already by the caller.
-llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) {
- unsigned int WordsToScan, WordsToSkip;
- llvm::Type *PtrTy = CGM.Int8PtrTy;
-
- // Build the string of skip/scan nibbles
- SmallVector<SKIP_SCAN, 32> SkipScanIvars;
- unsigned int WordSize =
- CGM.getTypes().getDataLayout().getTypeAllocSize(PtrTy);
- if (IvarsInfo[0].ivar_bytepos == 0) {
- WordsToSkip = 0;
- WordsToScan = IvarsInfo[0].ivar_size;
+/// buildBitmap - This routine does the horsework of taking the offsets of
+/// strong/weak references and creating a bitmap. The bitmap is also
+/// returned in the given buffer, suitable for being passed to \c dump().
+llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
+ llvm::SmallVectorImpl<unsigned char> &buffer) {
+ // The bitmap is a series of skip/scan instructions, aligned to word
+ // boundaries. The skip is performed first.
+ const unsigned char MaxNibble = 0xF;
+ const unsigned char SkipMask = 0xF0, SkipShift = 4;
+ const unsigned char ScanMask = 0x0F, ScanShift = 0;
+
+ assert(!IvarsInfo.empty() && "generating bitmap for no data");
+
+ // Sort the ivar info on byte position in case we encounterred a
+ // union nested in the ivar list.
+ if (IsDisordered) {
+ // This isn't a stable sort, but our algorithm should handle it fine.
+ llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
} else {
- WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
- WordsToScan = IvarsInfo[0].ivar_size;
- }
- for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
- unsigned int TailPrevGCObjC =
- IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
- if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
- // consecutive 'scanned' object pointers.
- WordsToScan += IvarsInfo[i].ivar_size;
- } else {
- // Skip over 'gc'able object pointer which lay over each other.
- if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
- continue;
- // Must skip over 1 or more words. We save current skip/scan values
- // and start a new pair.
- SKIP_SCAN SkScan;
- SkScan.skip = WordsToSkip;
- SkScan.scan = WordsToScan;
- SkipScanIvars.push_back(SkScan);
-
- // Skip the hole.
- SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
- SkScan.scan = 0;
- SkipScanIvars.push_back(SkScan);
- WordsToSkip = 0;
- WordsToScan = IvarsInfo[i].ivar_size;
- }
- }
- if (WordsToScan > 0) {
- SKIP_SCAN SkScan;
- SkScan.skip = WordsToSkip;
- SkScan.scan = WordsToScan;
- SkipScanIvars.push_back(SkScan);
+ assert(std::is_sorted(IvarsInfo.begin(), IvarsInfo.end()));
}
-
- if (!SkipIvars.empty()) {
- unsigned int LastIndex = SkipIvars.size()-1;
- int LastByteSkipped =
- SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
- LastIndex = IvarsInfo.size()-1;
- int LastByteScanned =
- IvarsInfo[LastIndex].ivar_bytepos +
- IvarsInfo[LastIndex].ivar_size * WordSize;
- // Compute number of bytes to skip at the tail end of the last ivar scanned.
- if (LastByteSkipped > LastByteScanned) {
- unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
- SKIP_SCAN SkScan;
- SkScan.skip = TotalWords - (LastByteScanned/WordSize);
- SkScan.scan = 0;
- SkipScanIvars.push_back(SkScan);
+ assert(IvarsInfo.back().Offset < InstanceEnd);
+
+ assert(buffer.empty());
+
+ // Skip the next N words.
+ auto skip = [&](unsigned numWords) {
+ assert(numWords > 0);
+
+ // Try to merge into the previous byte. Since scans happen second, we
+ // can't do this if it includes a scan.
+ if (!buffer.empty() && !(buffer.back() & ScanMask)) {
+ unsigned lastSkip = buffer.back() >> SkipShift;
+ if (lastSkip < MaxNibble) {
+ unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
+ numWords -= claimed;
+ lastSkip += claimed;
+ buffer.back() = (lastSkip << SkipShift);
+ }
}
- }
- // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
- // as 0xMN.
- int SkipScan = SkipScanIvars.size()-1;
- for (int i = 0; i <= SkipScan; i++) {
- if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
- && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
- // 0xM0 followed by 0x0N detected.
- SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
- for (int j = i+1; j < SkipScan; j++)
- SkipScanIvars[j] = SkipScanIvars[j+1];
- --SkipScan;
+
+ while (numWords >= MaxNibble) {
+ buffer.push_back(MaxNibble << SkipShift);
+ numWords -= MaxNibble;
}
- }
-
- // Generate the string.
- for (int i = 0; i <= SkipScan; i++) {
- unsigned char byte;
- unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
- unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
- unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
- unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
-
- // first skip big.
- for (unsigned int ix = 0; ix < skip_big; ix++)
- BitMap += (unsigned char)(0xf0);
-
- // next (skip small, scan)
- if (skip_small) {
- byte = skip_small << 4;
- if (scan_big > 0) {
- byte |= 0xf;
- --scan_big;
- } else if (scan_small) {
- byte |= scan_small;
- scan_small = 0;
+ if (numWords) {
+ buffer.push_back(numWords << SkipShift);
+ }
+ };
+
+ // Scan the next N words.
+ auto scan = [&](unsigned numWords) {
+ assert(numWords > 0);
+
+ // Try to merge into the previous byte. Since scans happen second, we can
+ // do this even if it includes a skip.
+ if (!buffer.empty()) {
+ unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
+ if (lastScan < MaxNibble) {
+ unsigned claimed = std::min(MaxNibble - lastScan, numWords);
+ numWords -= claimed;
+ lastScan += claimed;
+ buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
}
- BitMap += byte;
}
- // next scan big
- for (unsigned int ix = 0; ix < scan_big; ix++)
- BitMap += (unsigned char)(0x0f);
- // last scan small
- if (scan_small) {
- byte = scan_small;
- BitMap += byte;
+
+ while (numWords >= MaxNibble) {
+ buffer.push_back(MaxNibble << ScanShift);
+ numWords -= MaxNibble;
+ }
+ if (numWords) {
+ buffer.push_back(numWords << ScanShift);
+ }
+ };
+
+ // One past the end of the last scan.
+ unsigned endOfLastScanInWords = 0;
+ const CharUnits WordSize = CGM.getPointerSize();
+
+ // Consider all the scan requests.
+ for (auto &request : IvarsInfo) {
+ CharUnits beginOfScan = request.Offset - InstanceBegin;
+
+ // Ignore scan requests that don't start at an even multiple of the
+ // word size. We can't encode them.
+ if ((beginOfScan % WordSize) != 0) continue;
+
+ // Ignore scan requests that start before the instance start.
+ // This assumes that scans never span that boundary. The boundary
+ // isn't the true start of the ivars, because in the fragile-ARC case
+ // it's rounded up to word alignment, but the test above should leave
+ // us ignoring that possibility.
+ if (beginOfScan.isNegative()) {
+ assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
+ continue;
}
+
+ unsigned beginOfScanInWords = beginOfScan / WordSize;
+ unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
+
+ // If the scan starts some number of words after the last one ended,
+ // skip forward.
+ if (beginOfScanInWords > endOfLastScanInWords) {
+ skip(beginOfScanInWords - endOfLastScanInWords);
+
+ // Otherwise, start scanning where the last left off.
+ } else {
+ beginOfScanInWords = endOfLastScanInWords;
+
+ // If that leaves us with nothing to scan, ignore this request.
+ if (beginOfScanInWords >= endOfScanInWords) continue;
+ }
+
+ // Scan to the end of the request.
+ assert(beginOfScanInWords < endOfScanInWords);
+ scan(endOfScanInWords - beginOfScanInWords);
+ endOfLastScanInWords = endOfScanInWords;
}
- // null terminate string.
- unsigned char zero = 0;
- BitMap += zero;
- llvm::GlobalVariable *Entry = CreateMetadataVar(
+ if (buffer.empty())
+ return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
+
+ // For GC layouts, emit a skip to the end of the allocation so that we
+ // have precise information about the entire thing. This isn't useful
+ // or necessary for the ARC-style layout strings.
+ if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
+ unsigned lastOffsetInWords =
+ (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
+ if (lastOffsetInWords > endOfLastScanInWords) {
+ skip(lastOffsetInWords - endOfLastScanInWords);
+ }
+ }
+
+ // Null terminate the string.
+ buffer.push_back(0);
+
+ bool isNonFragileABI = CGObjC.isNonFragileABI();
+
+ llvm::GlobalVariable *Entry = CGObjC.CreateMetadataVar(
"OBJC_CLASS_NAME_",
- llvm::ConstantDataArray::getString(VMContext, BitMap, false),
- ((ObjCABI == 2) ? "__TEXT,__objc_classname,cstring_literals"
- : "__TEXT,__cstring,cstring_literals"),
- 1, true);
- return getConstantGEP(VMContext, Entry, 0, 0);
+ llvm::ConstantDataArray::get(CGM.getLLVMContext(), buffer),
+ (isNonFragileABI ? "__TEXT,__objc_classname,cstring_literals"
+ : "__TEXT,__cstring,cstring_literals"),
+ CharUnits::One(), true);
+ return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
}
/// BuildIvarLayout - Builds ivar layout bitmap for the class
@@ -4755,62 +4914,75 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) {
/// 2. When ForStrongLayout is false, following ivars are scanned:
/// - __weak anything
///
-llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
- const ObjCImplementationDecl *OMD,
- bool ForStrongLayout) {
- bool hasUnion = false;
-
+llvm::Constant *
+CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
+ CharUnits beginOffset, CharUnits endOffset,
+ bool ForStrongLayout, bool HasMRCWeakIvars) {
+ // If this is MRC, and we're either building a strong layout or there
+ // are no weak ivars, bail out early.
llvm::Type *PtrTy = CGM.Int8PtrTy;
if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
- !CGM.getLangOpts().ObjCAutoRefCount)
+ !CGM.getLangOpts().ObjCAutoRefCount &&
+ (ForStrongLayout || !HasMRCWeakIvars))
return llvm::Constant::getNullValue(PtrTy);
const ObjCInterfaceDecl *OI = OMD->getClassInterface();
- SmallVector<const FieldDecl*, 32> RecFields;
- if (CGM.getLangOpts().ObjCAutoRefCount) {
+ SmallVector<const ObjCIvarDecl*, 32> ivars;
+
+ // GC layout strings include the complete object layout, possibly
+ // inaccurately in the non-fragile ABI; the runtime knows how to fix this
+ // up.
+ //
+ // ARC layout strings only include the class's ivars. In non-fragile
+ // runtimes, that means starting at InstanceStart, rounded up to word
+ // alignment. In fragile runtimes, there's no InstanceStart, so it means
+ // starting at the offset of the first ivar, rounded up to word alignment.
+ //
+ // MRC weak layout strings follow the ARC style.
+ CharUnits baseOffset;
+ if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
IVD; IVD = IVD->getNextIvar())
- RecFields.push_back(cast<FieldDecl>(IVD));
+ ivars.push_back(IVD);
+
+ if (isNonFragileABI()) {
+ baseOffset = beginOffset; // InstanceStart
+ } else if (!ivars.empty()) {
+ baseOffset =
+ CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
+ } else {
+ baseOffset = CharUnits::Zero();
+ }
+
+ baseOffset = baseOffset.RoundUpToAlignment(CGM.getPointerAlign());
}
else {
- SmallVector<const ObjCIvarDecl*, 32> Ivars;
- CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
+ CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
- // FIXME: This is not ideal; we shouldn't have to do this copy.
- RecFields.append(Ivars.begin(), Ivars.end());
+ baseOffset = CharUnits::Zero();
}
- if (RecFields.empty())
+ if (ivars.empty())
return llvm::Constant::getNullValue(PtrTy);
- SkipIvars.clear();
- IvarsInfo.clear();
+ IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
+
+ builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
+ [&](const ObjCIvarDecl *ivar) -> CharUnits {
+ return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
+ });
- BuildAggrIvarLayout(OMD, nullptr, nullptr, RecFields, 0, ForStrongLayout,
- hasUnion);
- if (IvarsInfo.empty())
+ if (!builder.hasBitmapData())
return llvm::Constant::getNullValue(PtrTy);
- // Sort on byte position in case we encounterred a union nested in
- // the ivar list.
- if (hasUnion && !IvarsInfo.empty())
- std::sort(IvarsInfo.begin(), IvarsInfo.end());
- if (hasUnion && !SkipIvars.empty())
- std::sort(SkipIvars.begin(), SkipIvars.end());
-
- std::string BitMap;
- llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
+
+ llvm::SmallVector<unsigned char, 4> buffer;
+ llvm::Constant *C = builder.buildBitmap(*this, buffer);
- if (CGM.getLangOpts().ObjCGCBitmapPrint) {
+ if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
printf("\n%s ivar layout for class '%s': ",
ForStrongLayout ? "strong" : "weak",
OMD->getClassInterface()->getName().str().c_str());
- const unsigned char *s = (const unsigned char*)BitMap.c_str();
- for (unsigned i = 0, e = BitMap.size(); i < e; i++)
- if (!(s[i] & 0xf0))
- printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
- else
- printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
- printf("\n");
+ builder.dump(buffer);
}
return C;
}
@@ -4825,7 +4997,7 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()),
((ObjCABI == 2) ? "__TEXT,__objc_methname,cstring_literals"
: "__TEXT,__cstring,cstring_literals"),
- 1, true);
+ CharUnits::One(), true);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -4847,7 +5019,7 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
llvm::ConstantDataArray::getString(VMContext, TypeStr),
((ObjCABI == 2) ? "__TEXT,__objc_methtype,cstring_literals"
: "__TEXT,__cstring,cstring_literals"),
- 1, true);
+ CharUnits::One(), true);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -4866,7 +5038,7 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
llvm::ConstantDataArray::getString(VMContext, TypeStr),
((ObjCABI == 2) ? "__TEXT,__objc_methtype,cstring_literals"
: "__TEXT,__cstring,cstring_literals"),
- 1, true);
+ CharUnits::One(), true);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -4879,7 +5051,7 @@ llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Entry = CreateMetadataVar(
"OBJC_PROP_NAME_ATTR_",
llvm::ConstantDataArray::getString(VMContext, Ident->getName()),
- "__TEXT,__cstring,cstring_literals", 1, true);
+ "__TEXT,__cstring,cstring_literals", CharUnits::One(), true);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -5583,8 +5755,14 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
std::string ClassName = ID->getObjCRuntimeNameAsString();
llvm::Constant *Values[10]; // 11 for 64bit targets!
+ CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
+ CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
+
+ bool hasMRCWeak = false;
if (CGM.getLangOpts().ObjCAutoRefCount)
flags |= NonFragileABI_Class_CompiledByARC;
+ else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
+ flags |= NonFragileABI_Class_HasMRCWeakIvars;
Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
@@ -5592,7 +5770,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
// FIXME. For 64bit targets add 0 here.
Values[ 3] = (flags & NonFragileABI_Class_Meta)
? GetIvarLayoutName(nullptr, ObjCTypes)
- : BuildIvarLayout(ID, true);
+ : BuildStrongIvarLayout(ID, beginInstance, endInstance);
Values[ 4] = GetClassName(ID->getObjCRuntimeNameAsString());
// const struct _method_list_t * const baseMethods;
std::vector<llvm::Constant*> Methods;
@@ -5639,7 +5817,8 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
} else {
Values[ 7] = EmitIvarList(ID);
- Values[ 8] = BuildIvarLayout(ID, false);
+ Values[ 8] = BuildWeakIvarLayout(ID, beginInstance, endInstance,
+ hasMRCWeak);
Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
ID, ID->getClassInterface(), ObjCTypes);
}
@@ -5731,7 +5910,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
// Make this entry NULL for any iOS device target, any iOS simulator target,
// OS X with deployment target 10.9 or later.
const llvm::Triple &Triple = CGM.getTarget().getTriple();
- if (Triple.isiOS() || (Triple.isMacOSX() && !Triple.isMacOSXVersionLT(10, 9)))
+ if (Triple.isiOS() || Triple.isWatchOS() ||
+ (Triple.isMacOSX() && !Triple.isMacOSXVersionLT(10, 9)))
// This entry will be null.
ObjCEmptyVtableVar = nullptr;
else
@@ -5887,9 +6067,11 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
ProtocolName += PD->getObjCRuntimeNameAsString();
+ CharUnits Align = CGF.getPointerAlign();
+
llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
if (PTGV)
- return CGF.Builder.CreateLoad(PTGV);
+ return CGF.Builder.CreateAlignedLoad(PTGV, Align);
PTGV = new llvm::GlobalVariable(
CGM.getModule(),
Init->getType(), false,
@@ -5898,8 +6080,9 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
ProtocolName);
PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ PTGV->setAlignment(Align.getQuantity());
CGM.addCompilerUsedGlobal(PTGV);
- return CGF.Builder.CreateLoad(PTGV);
+ return CGF.Builder.CreateAlignedLoad(PTGV, Align);
}
/// GenerateCategory - Build metadata for a category implementation.
@@ -6428,7 +6611,8 @@ llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar) {
llvm::Value *IvarOffsetValue = ObjCIvarOffsetVariable(Interface, Ivar);
- IvarOffsetValue = CGF.Builder.CreateLoad(IvarOffsetValue, "ivar");
+ IvarOffsetValue = CGF.Builder.CreateAlignedLoad(IvarOffsetValue,
+ CGF.getSizeAlign(), "ivar");
if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
cast<llvm::LoadInst>(IvarOffsetValue)
->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
@@ -6559,16 +6743,17 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
}
}
- llvm::Value *mref =
- CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
+ Address mref =
+ Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
+ CGF.getPointerAlign());
// Update the message ref argument.
- args[1].RV = RValue::get(mref);
+ args[1].RV = RValue::get(mref.getPointer());
// Load the function to call from the message ref table.
- llvm::Value *callee =
- CGF.Builder.CreateStructGEP(ObjCTypes.MessageRefTy, mref, 0);
- callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
+ Address calleeAddr =
+ CGF.Builder.CreateStructGEP(mref, 0, CharUnits::Zero());
+ llvm::Value *callee = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
@@ -6594,7 +6779,7 @@ CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
: EmitMessageSend(CGF, Return, ResultType,
EmitSelector(CGF, Sel),
Receiver, CGF.getContext().getObjCIdType(),
- false, CallArgs, Method, ObjCTypes);
+ false, CallArgs, Method, Class, ObjCTypes);
}
llvm::GlobalVariable *
@@ -6617,6 +6802,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
IdentifierInfo *II,
bool Weak,
const ObjCInterfaceDecl *ID) {
+ CharUnits Align = CGF.getPointerAlign();
llvm::GlobalVariable *&Entry = ClassReferences[II];
if (!Entry) {
@@ -6627,13 +6813,11 @@ llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
false, llvm::GlobalValue::PrivateLinkage,
ClassGV, "OBJC_CLASSLIST_REFERENCES_$_");
- Entry->setAlignment(
- CGM.getDataLayout().getABITypeAlignment(
- ObjCTypes.ClassnfABIPtrTy));
+ Entry->setAlignment(Align.getQuantity());
Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
CGM.addCompilerUsedGlobal(Entry);
}
- return CGF.Builder.CreateLoad(Entry);
+ return CGF.Builder.CreateAlignedLoad(Entry, Align);
}
llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
@@ -6644,12 +6828,13 @@ llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
CodeGenFunction &CGF) {
IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
- return EmitClassRefFromId(CGF, II, false, 0);
+ return EmitClassRefFromId(CGF, II, false, nullptr);
}
llvm::Value *
CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID) {
+ CharUnits Align = CGF.getPointerAlign();
llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
if (!Entry) {
@@ -6660,13 +6845,11 @@ CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
false, llvm::GlobalValue::PrivateLinkage,
ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
- Entry->setAlignment(
- CGM.getDataLayout().getABITypeAlignment(
- ObjCTypes.ClassnfABIPtrTy));
+ Entry->setAlignment(Align.getQuantity());
Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
CGM.addCompilerUsedGlobal(Entry);
}
- return CGF.Builder.CreateLoad(Entry);
+ return CGF.Builder.CreateAlignedLoad(Entry, Align);
}
/// EmitMetaClassRef - Return a Value * of the address of _class_t
@@ -6675,6 +6858,7 @@ CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID,
bool Weak) {
+ CharUnits Align = CGF.getPointerAlign();
llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
if (!Entry) {
llvm::SmallString<64> MetaClassName(getMetaclassSymbolPrefix());
@@ -6685,14 +6869,13 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
false, llvm::GlobalValue::PrivateLinkage,
MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
- Entry->setAlignment(
- CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABIPtrTy));
+ Entry->setAlignment(Align.getQuantity());
Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
CGM.addCompilerUsedGlobal(Entry);
}
- return CGF.Builder.CreateLoad(Entry);
+ return CGF.Builder.CreateAlignedLoad(Entry, Align);
}
/// GetClass - Return a reference to the class for the given interface
@@ -6727,14 +6910,15 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
// ...
// Create and init a super structure; this is a (receiver, class)
// pair we will pass to objc_msgSendSuper.
- llvm::Value *ObjCSuper =
- CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
+ Address ObjCSuper =
+ CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
+ "objc_super");
llvm::Value *ReceiverAsObject =
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
CGF.Builder.CreateStore(
ReceiverAsObject,
- CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 0));
+ CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero()));
// If this is a class message the metaclass is passed as the target.
llvm::Value *Target;
@@ -6749,22 +6933,33 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Target = CGF.Builder.CreateBitCast(Target, ClassTy);
CGF.Builder.CreateStore(
- Target, CGF.Builder.CreateStructGEP(ObjCTypes.SuperTy, ObjCSuper, 1));
+ Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize()));
return (isVTableDispatchedSelector(Sel))
? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
- ObjCSuper, ObjCTypes.SuperPtrCTy,
+ ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
true, CallArgs, Method)
: EmitMessageSend(CGF, Return, ResultType,
EmitSelector(CGF, Sel),
- ObjCSuper, ObjCTypes.SuperPtrCTy,
- true, CallArgs, Method, ObjCTypes);
+ ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
+ true, CallArgs, Method, Class, ObjCTypes);
}
llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
- Selector Sel, bool lval) {
+ Selector Sel) {
+ Address Addr = EmitSelectorAddr(CGF, Sel);
+
+ llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
+ LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
+ llvm::MDNode::get(VMContext, None));
+ return LI;
+}
+
+Address CGObjCNonFragileABIMac::EmitSelectorAddr(CodeGenFunction &CGF,
+ Selector Sel) {
llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
+ CharUnits Align = CGF.getPointerAlign();
if (!Entry) {
llvm::Constant *Casted =
llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
@@ -6774,23 +6969,19 @@ llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
Casted, "OBJC_SELECTOR_REFERENCES_");
Entry->setExternallyInitialized(true);
Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
+ Entry->setAlignment(Align.getQuantity());
CGM.addCompilerUsedGlobal(Entry);
}
- if (lval)
- return Entry;
- llvm::LoadInst* LI = CGF.Builder.CreateLoad(Entry);
-
- LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
- llvm::MDNode::get(VMContext, None));
- return LI;
+ return Address(Entry, Align);
}
+
/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
///
void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src,
- llvm::Value *dst,
+ Address dst,
llvm::Value *ivarOffset) {
llvm::Type * SrcTy = src->getType();
if (!isa<llvm::PointerType>(SrcTy)) {
@@ -6802,7 +6993,7 @@ void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- llvm::Value *args[] = { src, dst, ivarOffset };
+ llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
}
@@ -6811,7 +7002,7 @@ void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
///
void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
+ llvm::Value *src, Address dst) {
llvm::Type * SrcTy = src->getType();
if (!isa<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
@@ -6822,19 +7013,19 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- llvm::Value *args[] = { src, dst };
+ llvm::Value *args[] = { src, dst.getPointer() };
CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
args, "weakassign");
}
void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
CodeGen::CodeGenFunction &CGF,
- llvm::Value *DestPtr,
- llvm::Value *SrcPtr,
+ Address DestPtr,
+ Address SrcPtr,
llvm::Value *Size) {
SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
- llvm::Value *args[] = { DestPtr, SrcPtr, Size };
+ llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size };
CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
}
@@ -6843,13 +7034,12 @@ void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
///
llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
CodeGen::CodeGenFunction &CGF,
- llvm::Value *AddrWeakObj) {
- llvm::Type* DestTy =
- cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
+ Address AddrWeakObj) {
+ llvm::Type *DestTy = AddrWeakObj.getElementType();
AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
llvm::Value *read_weak =
CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
- AddrWeakObj, "weakread");
+ AddrWeakObj.getPointer(), "weakread");
read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
return read_weak;
}
@@ -6858,7 +7048,7 @@ llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
/// objc_assign_weak (id src, id *dst)
///
void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
+ llvm::Value *src, Address dst) {
llvm::Type * SrcTy = src->getType();
if (!isa<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
@@ -6869,7 +7059,7 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- llvm::Value *args[] = { src, dst };
+ llvm::Value *args[] = { src, dst.getPointer() };
CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
args, "weakassign");
}
@@ -6878,7 +7068,7 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
/// objc_assign_global (id src, id *dst)
///
void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst,
+ llvm::Value *src, Address dst,
bool threadlocal) {
llvm::Type * SrcTy = src->getType();
if (!isa<llvm::PointerType>(SrcTy)) {
@@ -6890,7 +7080,7 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- llvm::Value *args[] = { src, dst };
+ llvm::Value *args[] = { src, dst.getPointer() };
if (!threadlocal)
CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
args, "globalassign");
@@ -7043,6 +7233,7 @@ CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
case ObjCRuntime::MacOSX:
case ObjCRuntime::iOS:
+ case ObjCRuntime::WatchOS:
return new CGObjCNonFragileABIMac(CGM);
case ObjCRuntime::GNUstep:
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp
index 2ac6bb2..7be9ae9 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.cpp
@@ -136,12 +136,13 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
CGF.CGM.getContext().toBits(StorageSize),
CharUnits::fromQuantity(0)));
- V = CGF.Builder.CreateBitCast(V,
- llvm::Type::getIntNPtrTy(CGF.getLLVMContext(),
+ Address Addr(V, Alignment);
+ Addr = CGF.Builder.CreateElementBitCast(Addr,
+ llvm::Type::getIntNTy(CGF.getLLVMContext(),
Info->StorageSize));
- return LValue::MakeBitfield(V, *Info,
+ return LValue::MakeBitfield(Addr, *Info,
IvarTy.withCVRQualifiers(CVRQualifiers),
- Alignment);
+ AlignmentSource::Decl);
}
namespace {
@@ -152,7 +153,7 @@ namespace {
llvm::Constant *TypeInfo;
};
- struct CallObjCEndCatch : EHScopeStack::Cleanup {
+ struct CallObjCEndCatch final : EHScopeStack::Cleanup {
CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) :
MightThrow(MightThrow), Fn(Fn) {}
bool MightThrow;
@@ -255,24 +256,7 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType);
CGF.EmitAutoVarDecl(*CatchParam);
-
- llvm::Value *CatchParamAddr = CGF.GetAddrOfLocalVar(CatchParam);
-
- switch (CatchParam->getType().getQualifiers().getObjCLifetime()) {
- case Qualifiers::OCL_Strong:
- CastExn = CGF.EmitARCRetainNonBlock(CastExn);
- // fallthrough
-
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- case Qualifiers::OCL_Autoreleasing:
- CGF.Builder.CreateStore(CastExn, CatchParamAddr);
- break;
-
- case Qualifiers::OCL_Weak:
- CGF.EmitARCInitWeak(CatchParamAddr, CastExn);
- break;
- }
+ EmitInitOfCatchParam(CGF, CastExn, CatchParam);
}
CGF.ObjCEHValueStack.push_back(Exn);
@@ -296,8 +280,32 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
CGF.EmitBlock(Cont.getBlock());
}
+void CGObjCRuntime::EmitInitOfCatchParam(CodeGenFunction &CGF,
+ llvm::Value *exn,
+ const VarDecl *paramDecl) {
+
+ Address paramAddr = CGF.GetAddrOfLocalVar(paramDecl);
+
+ switch (paramDecl->getType().getQualifiers().getObjCLifetime()) {
+ case Qualifiers::OCL_Strong:
+ exn = CGF.EmitARCRetainNonBlock(exn);
+ // fallthrough
+
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_ExplicitNone:
+ case Qualifiers::OCL_Autoreleasing:
+ CGF.Builder.CreateStore(exn, paramAddr);
+ return;
+
+ case Qualifiers::OCL_Weak:
+ CGF.EmitARCInitWeak(paramAddr, exn);
+ return;
+ }
+ llvm_unreachable("invalid ownership qualifier");
+}
+
namespace {
- struct CallSyncExit : EHScopeStack::Cleanup {
+ struct CallSyncExit final : EHScopeStack::Cleanup {
llvm::Value *SyncExitFn;
llvm::Value *SyncArg;
CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg)
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h
index 4752546..28d88dd 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCRuntime.h
@@ -100,6 +100,10 @@ protected:
llvm::Constant *beginCatchFn,
llvm::Constant *endCatchFn,
llvm::Constant *exceptionRethrowFn);
+
+ void EmitInitOfCatchParam(CodeGenFunction &CGF, llvm::Value *exn,
+ const VarDecl *paramDecl);
+
/// Emits an \@synchronize() statement, using the \p syncEnterFn and
/// \p syncExitFn arguments as the functions called to lock and unlock
/// the object. This function can be called by subclasses that use
@@ -116,11 +120,16 @@ public:
/// this compilation unit with the runtime library.
virtual llvm::Function *ModuleInitFunction() = 0;
- /// Get a selector for the specified name and type values. The
- /// return value should have the LLVM type for pointer-to
+ /// Get a selector for the specified name and type values.
+ /// The result should have the LLVM type for ASTContext::getObjCSelType().
+ virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) = 0;
+
+ /// Get the address of a selector for the specified name and type values.
+ /// This is a rarely-used language extension, but sadly it exists.
+ ///
+ /// The result should have the LLVM type for a pointer to
/// ASTContext::getObjCSelType().
- virtual llvm::Value *GetSelector(CodeGenFunction &CGF,
- Selector Sel, bool lval=false) = 0;
+ virtual Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) = 0;
/// Get a typed selector.
virtual llvm::Value *GetSelector(CodeGenFunction &CGF,
@@ -133,7 +142,7 @@ public:
virtual llvm::Constant *GetEHType(QualType T) = 0;
/// Generate a constant string object.
- virtual llvm::Constant *GenerateConstantString(const StringLiteral *) = 0;
+ virtual ConstantAddress GenerateConstantString(const StringLiteral *) = 0;
/// Generate a category. A category contains a list of methods (and
/// accompanying metadata) and a list of protocols.
@@ -238,17 +247,17 @@ public:
const ObjCAtThrowStmt &S,
bool ClearInsertionPoint=true) = 0;
virtual llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
- llvm::Value *AddrWeakObj) = 0;
+ Address AddrWeakObj) = 0;
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest) = 0;
+ llvm::Value *src, Address dest) = 0;
virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest,
+ llvm::Value *src, Address dest,
bool threadlocal=false) = 0;
virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest,
+ llvm::Value *src, Address dest,
llvm::Value *ivarOffset) = 0;
virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest) = 0;
+ llvm::Value *src, Address dest) = 0;
virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
QualType ObjectTy,
@@ -259,15 +268,18 @@ public:
const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar) = 0;
virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
- llvm::Value *DestPtr,
- llvm::Value *SrcPtr,
+ Address DestPtr,
+ Address SrcPtr,
llvm::Value *Size) = 0;
virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
const CodeGen::CGBlockInfo &blockInfo) = 0;
virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
const CodeGen::CGBlockInfo &blockInfo) = 0;
+
+ /// Returns an i8* which points to the byref layout information.
virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
QualType T) = 0;
+
virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
bool Weak = false) = 0;
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp
index 079ef72..6866789 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp
@@ -55,6 +55,28 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
case BuiltinType::OCLImage2dArray:
return llvm::PointerType::get(llvm::StructType::create(
Ctx, "opencl.image2d_array_t"), ImgAddrSpc);
+ case BuiltinType::OCLImage2dDepth:
+ return llvm::PointerType::get(
+ llvm::StructType::create(Ctx, "opencl.image2d_depth_t"), ImgAddrSpc);
+ case BuiltinType::OCLImage2dArrayDepth:
+ return llvm::PointerType::get(
+ llvm::StructType::create(Ctx, "opencl.image2d_array_depth_t"),
+ ImgAddrSpc);
+ case BuiltinType::OCLImage2dMSAA:
+ return llvm::PointerType::get(
+ llvm::StructType::create(Ctx, "opencl.image2d_msaa_t"), ImgAddrSpc);
+ case BuiltinType::OCLImage2dArrayMSAA:
+ return llvm::PointerType::get(
+ llvm::StructType::create(Ctx, "opencl.image2d_array_msaa_t"),
+ ImgAddrSpc);
+ case BuiltinType::OCLImage2dMSAADepth:
+ return llvm::PointerType::get(
+ llvm::StructType::create(Ctx, "opencl.image2d_msaa_depth_t"),
+ ImgAddrSpc);
+ case BuiltinType::OCLImage2dArrayMSAADepth:
+ return llvm::PointerType::get(
+ llvm::StructType::create(Ctx, "opencl.image2d_array_msaa_depth_t"),
+ ImgAddrSpc);
case BuiltinType::OCLImage3d:
return llvm::PointerType::get(llvm::StructType::create(
Ctx, "opencl.image3d_t"), ImgAddrSpc);
@@ -63,5 +85,28 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
case BuiltinType::OCLEvent:
return llvm::PointerType::get(llvm::StructType::create(
Ctx, "opencl.event_t"), 0);
+ case BuiltinType::OCLClkEvent:
+ return llvm::PointerType::get(
+ llvm::StructType::create(Ctx, "opencl.clk_event_t"), 0);
+ case BuiltinType::OCLQueue:
+ return llvm::PointerType::get(
+ llvm::StructType::create(Ctx, "opencl.queue_t"), 0);
+ case BuiltinType::OCLNDRange:
+ return llvm::PointerType::get(
+ llvm::StructType::create(Ctx, "opencl.ndrange_t"), 0);
+ case BuiltinType::OCLReserveID:
+ return llvm::PointerType::get(
+ llvm::StructType::create(Ctx, "opencl.reserve_id_t"), 0);
}
}
+
+llvm::Type *CGOpenCLRuntime::getPipeType() {
+ if (!PipeTy){
+ uint32_t PipeAddrSpc =
+ CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
+ PipeTy = llvm::PointerType::get(llvm::StructType::create(
+ CGM.getLLVMContext(), "opencl.pipe_t"), PipeAddrSpc);
+ }
+
+ return PipeTy;
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h
index 0c50b92..f1a7a31 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h
@@ -32,9 +32,10 @@ class CodeGenModule;
class CGOpenCLRuntime {
protected:
CodeGenModule &CGM;
+ llvm::Type *PipeTy;
public:
- CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
+ CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr) {}
virtual ~CGOpenCLRuntime();
/// Emit the IR required for a work-group-local variable declaration, and add
@@ -44,6 +45,8 @@ public:
const VarDecl &D);
virtual llvm::Type *convertOpenCLSpecificType(const Type *T);
+
+ virtual llvm::Type *getPipeType();
};
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 8148839..3b97ba2 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -11,16 +11,19 @@
//
//===----------------------------------------------------------------------===//
+#include "CGCXXABI.h"
+#include "CGCleanup.h"
#include "CGOpenMPRuntime.h"
#include "CodeGenFunction.h"
-#include "CGCleanup.h"
#include "clang/AST/Decl.h"
#include "clang/AST/StmtOpenMP.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Value.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
@@ -41,25 +44,29 @@ public:
/// \brief Region for constructs that do not require function outlining,
/// like 'for', 'sections', 'atomic' etc. directives.
InlinedRegion,
+ /// \brief Region with outlined function for standalone 'target' directive.
+ TargetRegion,
};
CGOpenMPRegionInfo(const CapturedStmt &CS,
const CGOpenMPRegionKind RegionKind,
- const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind)
+ const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
+ bool HasCancel)
: CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
- CodeGen(CodeGen), Kind(Kind) {}
+ CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
- const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind)
+ const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
+ bool HasCancel)
: CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
- Kind(Kind) {}
+ Kind(Kind), HasCancel(HasCancel) {}
/// \brief Get a variable or parameter for storing global thread id
/// inside OpenMP construct.
virtual const VarDecl *getThreadIDVariable() const = 0;
/// \brief Emit the captured statement body.
- virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
+ void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
/// \brief Get an LValue for the current ThreadID variable.
/// \return LValue for thread id variable. This LValue always has type int32*.
@@ -69,14 +76,17 @@ public:
OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const CGCapturedStmtInfo *Info) {
return Info->getKind() == CR_OpenMP;
}
protected:
CGOpenMPRegionKind RegionKind;
- const RegionCodeGenTy &CodeGen;
+ RegionCodeGenTy CodeGen;
OpenMPDirectiveKind Kind;
+ bool HasCancel;
};
/// \brief API for captured statement code generation in OpenMP constructs.
@@ -84,8 +94,9 @@ class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo {
public:
CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
const RegionCodeGenTy &CodeGen,
- OpenMPDirectiveKind Kind)
- : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind),
+ OpenMPDirectiveKind Kind, bool HasCancel)
+ : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
+ HasCancel),
ThreadIDVar(ThreadIDVar) {
assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
}
@@ -114,8 +125,8 @@ public:
CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
const RegionCodeGenTy &CodeGen,
- OpenMPDirectiveKind Kind)
- : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind),
+ OpenMPDirectiveKind Kind, bool HasCancel)
+ : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
ThreadIDVar(ThreadIDVar) {
assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
}
@@ -147,8 +158,9 @@ class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
public:
CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
const RegionCodeGenTy &CodeGen,
- OpenMPDirectiveKind Kind)
- : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind), OldCSI(OldCSI),
+ OpenMPDirectiveKind Kind, bool HasCancel)
+ : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
+ OldCSI(OldCSI),
OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
// \brief Retrieve the value of the context parameter.
llvm::Value *getContextValue() const override {
@@ -156,7 +168,7 @@ public:
return OuterRegionInfo->getContextValue();
llvm_unreachable("No context value for inlined OpenMP region");
}
- virtual void setContextValue(llvm::Value *V) override {
+ void setContextValue(llvm::Value *V) override {
if (OuterRegionInfo) {
OuterRegionInfo->setContextValue(V);
return;
@@ -204,6 +216,35 @@ private:
CGOpenMPRegionInfo *OuterRegionInfo;
};
+/// \brief API for captured statement code generation in OpenMP target
+/// constructs. For this captures, implicit parameters are used instead of the
+/// captured fields. The name of the target region has to be unique in a given
+/// application so it is provided by the client, because only the client has
+/// the information to generate that.
+class CGOpenMPTargetRegionInfo : public CGOpenMPRegionInfo {
+public:
+ CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
+ const RegionCodeGenTy &CodeGen, StringRef HelperName)
+ : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
+ /*HasCancel=*/false),
+ HelperName(HelperName) {}
+
+ /// \brief This is unused for target regions because each starts executing
+ /// with a single thread.
+ const VarDecl *getThreadIDVariable() const override { return nullptr; }
+
+ /// \brief Get the name of the capture helper.
+ StringRef getHelperName() const override { return HelperName; }
+
+ static bool classof(const CGCapturedStmtInfo *Info) {
+ return CGOpenMPRegionInfo::classof(Info) &&
+ cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
+ }
+
+private:
+ StringRef HelperName;
+};
+
/// \brief RAII for emitting code of OpenMP constructs.
class InlinedOpenMPRegionRAII {
CodeGenFunction &CGF;
@@ -214,11 +255,11 @@ public:
/// a list of functions used for code generation of implicitly inlined
/// regions.
InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
- OpenMPDirectiveKind Kind)
+ OpenMPDirectiveKind Kind, bool HasCancel)
: CGF(CGF) {
// Start emission for the construct.
- CGF.CapturedStmtInfo =
- new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen, Kind);
+ CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
+ CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
}
~InlinedOpenMPRegionRAII() {
// Restore original CapturedStmtInfo only if we're done with code emission.
@@ -229,20 +270,25 @@ public:
}
};
-} // namespace
+} // anonymous namespace
+
+static LValue emitLoadOfPointerLValue(CodeGenFunction &CGF, Address PtrAddr,
+ QualType Ty) {
+ AlignmentSource Source;
+ CharUnits Align = CGF.getNaturalPointeeTypeAlignment(Ty, &Source);
+ return CGF.MakeAddrLValue(Address(CGF.Builder.CreateLoad(PtrAddr), Align),
+ Ty->getPointeeType(), Source);
+}
LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
- return CGF.MakeNaturalAlignAddrLValue(
- CGF.Builder.CreateAlignedLoad(
- CGF.GetAddrOfLocalVar(getThreadIDVariable()),
- CGF.PointerAlignInBytes),
- getThreadIDVariable()
- ->getType()
- ->castAs<PointerType>()
- ->getPointeeType());
+ return emitLoadOfPointerLValue(CGF,
+ CGF.GetAddrOfLocalVar(getThreadIDVariable()),
+ getThreadIDVariable()->getType());
}
void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
+ if (!CGF.HaveInsertPoint())
+ return;
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
// top and a single exit at the bottom.
@@ -258,13 +304,14 @@ void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
CodeGenFunction &CGF) {
- return CGF.MakeNaturalAlignAddrLValue(
- CGF.GetAddrOfLocalVar(getThreadIDVariable()),
- getThreadIDVariable()->getType());
+ return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
+ getThreadIDVariable()->getType(),
+ AlignmentSource::Decl);
}
CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
- : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr) {
+ : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr),
+ OffloadEntriesInfoManager(CGM) {
IdentTy = llvm::StructType::create(
"ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
@@ -274,12 +321,33 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
llvm::PointerType::getUnqual(CGM.Int32Ty)};
Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
+
+ loadOffloadInfoMetadata();
}
void CGOpenMPRuntime::clear() {
InternalVars.clear();
}
+// Layout information for ident_t.
+static CharUnits getIdentAlign(CodeGenModule &CGM) {
+ return CGM.getPointerAlign();
+}
+static CharUnits getIdentSize(CodeGenModule &CGM) {
+ assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign()));
+ return CharUnits::fromQuantity(16) + CGM.getPointerSize();
+}
+static CharUnits getOffsetOfIdentField(CGOpenMPRuntime::IdentFieldIndex Field) {
+ // All the fields except the last are i32, so this works beautifully.
+ return unsigned(Field) * CharUnits::fromQuantity(4);
+}
+static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr,
+ CGOpenMPRuntime::IdentFieldIndex Field,
+ const llvm::Twine &Name = "") {
+ auto Offset = getOffsetOfIdentField(Field);
+ return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name);
+}
+
llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
@@ -287,9 +355,17 @@ llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction(
"thread id variable must be of type kmp_int32 *");
const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
CodeGenFunction CGF(CGM, true);
- CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind);
+ bool HasCancel = false;
+ if (auto *OPD = dyn_cast<OMPParallelDirective>(&D))
+ HasCancel = OPD->hasCancel();
+ else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
+ HasCancel = OPSD->hasCancel();
+ else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
+ HasCancel = OPFD->hasCancel();
+ CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
+ HasCancel);
CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
- return CGF.GenerateCapturedStmtFunction(*CS);
+ return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
}
llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
@@ -300,13 +376,14 @@ llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction(
auto *CS = cast<CapturedStmt>(D.getAssociatedStmt());
CodeGenFunction CGF(CGM, true);
CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
- InnermostKind);
+ InnermostKind,
+ cast<OMPTaskDirective>(D).hasCancel());
CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
return CGF.GenerateCapturedStmtFunction(*CS);
}
-llvm::Value *
-CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
+Address CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
+ CharUnits Align = getIdentAlign(CGM);
llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
if (!Entry) {
if (!DefaultOpenMPPSource) {
@@ -315,7 +392,7 @@ CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
// Taken from
// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
DefaultOpenMPPSource =
- CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;");
+ CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
DefaultOpenMPPSource =
llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
}
@@ -323,6 +400,7 @@ CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
CGM.getModule(), IdentTy, /*isConstant*/ true,
llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
DefaultOpenMPLocation->setUnnamedAddr(true);
+ DefaultOpenMPLocation->setAlignment(Align.getQuantity());
llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
llvm::Constant *Values[] = {Zero,
@@ -330,10 +408,9 @@ CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
Zero, Zero, DefaultOpenMPPSource};
llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
DefaultOpenMPLocation->setInitializer(Init);
- OpenMPDefaultLocMap[Flags] = DefaultOpenMPLocation;
- return DefaultOpenMPLocation;
+ OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
}
- return Entry;
+ return Address(Entry, Align);
}
llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
@@ -342,34 +419,33 @@ llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
// If no debug info is generated - return global default location.
if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
Loc.isInvalid())
- return getOrCreateDefaultLocation(Flags);
+ return getOrCreateDefaultLocation(Flags).getPointer();
assert(CGF.CurFn && "No function in current CodeGenFunction.");
- llvm::Value *LocValue = nullptr;
+ Address LocValue = Address::invalid();
auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
if (I != OpenMPLocThreadIDMap.end())
- LocValue = I->second.DebugLoc;
+ LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM));
+
// OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
// GetOpenMPThreadID was called before this routine.
- if (LocValue == nullptr) {
+ if (!LocValue.isValid()) {
// Generate "ident_t .kmpc_loc.addr;"
- llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr");
- AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy));
+ Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM),
+ ".kmpc_loc.addr");
auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
- Elem.second.DebugLoc = AI;
+ Elem.second.DebugLoc = AI.getPointer();
LocValue = AI;
CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
- llvm::ConstantExpr::getSizeOf(IdentTy),
- CGM.PointerAlignInBytes);
+ CGM.getSize(getIdentSize(CGF.CGM)));
}
// char **psource = &.kmpc_loc_<flags>.addr.psource;
- auto *PSource = CGF.Builder.CreateConstInBoundsGEP2_32(IdentTy, LocValue, 0,
- IdentField_PSource);
+ Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource);
auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
if (OMPDebugLoc == nullptr) {
@@ -389,7 +465,9 @@ llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
// *psource = ";<File>;<Function>;<Line>;<Column>;;";
CGF.Builder.CreateStore(OMPDebugLoc, PSource);
- return LocValue;
+ // Our callers always pass this to a runtime function, so for
+ // convenience, go ahead and return a naked pointer.
+ return LocValue.getPointer();
}
llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
@@ -493,6 +571,17 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
break;
}
+ case OMPRTL__kmpc_critical_with_hint: {
+ // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
+ // kmp_critical_name *crit, uintptr_t hint);
+ llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
+ llvm::PointerType::getUnqual(KmpCriticalNameTy),
+ CGM.IntPtrTy};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
+ break;
+ }
case OMPRTL__kmpc_threadprivate_register: {
// Build void __kmpc_threadprivate_register(ident_t *, void *data,
// kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
@@ -838,10 +927,66 @@ CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
break;
}
+ case OMPRTL__tgt_target: {
+ // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
+ // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
+ // *arg_types);
+ llvm::Type *TypeParams[] = {CGM.Int32Ty,
+ CGM.VoidPtrTy,
+ CGM.Int32Ty,
+ CGM.VoidPtrPtrTy,
+ CGM.VoidPtrPtrTy,
+ CGM.SizeTy->getPointerTo(),
+ CGM.Int32Ty->getPointerTo()};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
+ break;
+ }
+ case OMPRTL__tgt_register_lib: {
+ // Build void __tgt_register_lib(__tgt_bin_desc *desc);
+ QualType ParamTy =
+ CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
+ llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
+ break;
+ }
+ case OMPRTL__tgt_unregister_lib: {
+ // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
+ QualType ParamTy =
+ CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
+ llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
+ llvm::FunctionType *FnTy =
+ llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
+ RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
+ break;
+ }
}
return RTLFn;
}
+static llvm::Value *getTypeSize(CodeGenFunction &CGF, QualType Ty) {
+ auto &C = CGF.getContext();
+ llvm::Value *Size = nullptr;
+ auto SizeInChars = C.getTypeSizeInChars(Ty);
+ if (SizeInChars.isZero()) {
+ // getTypeSizeInChars() returns 0 for a VLA.
+ while (auto *VAT = C.getAsVariableArrayType(Ty)) {
+ llvm::Value *ArraySize;
+ std::tie(ArraySize, Ty) = CGF.getVLASize(VAT);
+ Size = Size ? CGF.Builder.CreateNUWMul(Size, ArraySize) : ArraySize;
+ }
+ SizeInChars = C.getTypeSizeInChars(Ty);
+ assert(!SizeInChars.isZero());
+ Size = CGF.Builder.CreateNUWMul(
+ Size, llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity()));
+ } else
+ Size = llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity());
+ return Size;
+}
+
llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize,
bool IVSigned) {
assert((IVSize == 32 || IVSize == 64) &&
@@ -939,25 +1084,27 @@ CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Twine(CGM.getMangledName(VD)) + ".cache.");
}
-llvm::Value *CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
- const VarDecl *VD,
- llvm::Value *VDAddr,
- SourceLocation Loc) {
+Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
+ const VarDecl *VD,
+ Address VDAddr,
+ SourceLocation Loc) {
if (CGM.getLangOpts().OpenMPUseTLS &&
CGM.getContext().getTargetInfo().isTLSSupported())
return VDAddr;
- auto VarTy = VDAddr->getType()->getPointerElementType();
+ auto VarTy = VDAddr.getElementType();
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
- CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy),
+ CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
+ CGM.Int8PtrTy),
CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
getOrCreateThreadPrivateCache(VD)};
- return CGF.EmitRuntimeCall(
- createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args);
+ return Address(CGF.EmitRuntimeCall(
+ createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
+ VDAddr.getAlignment());
}
void CGOpenMPRuntime::emitThreadPrivateVarInit(
- CodeGenFunction &CGF, llvm::Value *VDAddr, llvm::Value *Ctor,
+ CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
// Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
// library.
@@ -967,14 +1114,15 @@ void CGOpenMPRuntime::emitThreadPrivateVarInit(
// Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
// to register constructor/destructor for variable.
llvm::Value *Args[] = {OMPLoc,
- CGF.Builder.CreatePointerCast(VDAddr, CGM.VoidPtrTy),
+ CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
+ CGM.VoidPtrTy),
Ctor, CopyCtor, Dtor};
CGF.EmitRuntimeCall(
createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
}
llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
- const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc,
+ const VarDecl *VD, Address VDAddr, SourceLocation Loc,
bool PerformInit, CodeGenFunction *CGF) {
if (CGM.getLangOpts().OpenMPUseTLS &&
CGM.getContext().getTargetInfo().isTLSSupported())
@@ -1001,21 +1149,19 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
/*isVariadic=*/false);
auto FTy = CGM.getTypes().GetFunctionType(FI);
auto Fn = CGM.CreateGlobalInitOrDestructFunction(
- FTy, ".__kmpc_global_ctor_.", Loc);
+ FTy, ".__kmpc_global_ctor_.", FI, Loc);
CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
Args, SourceLocation());
auto ArgVal = CtorCGF.EmitLoadOfScalar(
- CtorCGF.GetAddrOfLocalVar(&Dst),
- /*Volatile=*/false, CGM.PointerAlignInBytes,
+ CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
CGM.getContext().VoidPtrTy, Dst.getLocation());
- auto Arg = CtorCGF.Builder.CreatePointerCast(
- ArgVal,
- CtorCGF.ConvertTypeForMem(CGM.getContext().getPointerType(ASTTy)));
+ Address Arg = Address(ArgVal, VDAddr.getAlignment());
+ Arg = CtorCGF.Builder.CreateElementBitCast(Arg,
+ CtorCGF.ConvertTypeForMem(ASTTy));
CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
/*IsInitializer=*/true);
ArgVal = CtorCGF.EmitLoadOfScalar(
- CtorCGF.GetAddrOfLocalVar(&Dst),
- /*Volatile=*/false, CGM.PointerAlignInBytes,
+ CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
CGM.getContext().VoidPtrTy, Dst.getLocation());
CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
CtorCGF.FinishFunction();
@@ -1035,14 +1181,13 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
/*isVariadic=*/false);
auto FTy = CGM.getTypes().GetFunctionType(FI);
auto Fn = CGM.CreateGlobalInitOrDestructFunction(
- FTy, ".__kmpc_global_dtor_.", Loc);
+ FTy, ".__kmpc_global_dtor_.", FI, Loc);
DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
SourceLocation());
auto ArgVal = DtorCGF.EmitLoadOfScalar(
DtorCGF.GetAddrOfLocalVar(&Dst),
- /*Volatile=*/false, CGM.PointerAlignInBytes,
- CGM.getContext().VoidPtrTy, Dst.getLocation());
- DtorCGF.emitDestroy(ArgVal, ASTTy,
+ /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
+ DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
DtorCGF.getDestroyer(ASTTy.isDestructedType()),
DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
DtorCGF.FinishFunction();
@@ -1074,7 +1219,8 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
auto InitFunctionTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
- InitFunctionTy, ".__omp_threadprivate_init_.");
+ InitFunctionTy, ".__omp_threadprivate_init_.",
+ CGM.getTypes().arrangeNullaryFunction());
CodeGenFunction InitCGF(CGM);
FunctionArgList ArgList;
InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
@@ -1149,25 +1295,27 @@ static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
llvm::Value *OutlinedFn,
- llvm::Value *CapturedStruct,
+ ArrayRef<llvm::Value *> CapturedVars,
const Expr *IfCond) {
+ if (!CGF.HaveInsertPoint())
+ return;
auto *RTLoc = emitUpdateLocation(CGF, Loc);
- auto &&ThenGen =
- [this, OutlinedFn, CapturedStruct, RTLoc](CodeGenFunction &CGF) {
- // Build call __kmpc_fork_call(loc, 1, microtask,
- // captured_struct/*context*/)
- llvm::Value *Args[] = {
- RTLoc,
- CGF.Builder.getInt32(
- 1), // Number of arguments after 'microtask' argument
- // (there is only one additional argument - 'context')
- CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()),
- CGF.EmitCastToVoidPtr(CapturedStruct)};
- auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
- CGF.EmitRuntimeCall(RTLFn, Args);
- };
- auto &&ElseGen = [this, OutlinedFn, CapturedStruct, RTLoc, Loc](
- CodeGenFunction &CGF) {
+ auto &&ThenGen = [this, OutlinedFn, CapturedVars,
+ RTLoc](CodeGenFunction &CGF) {
+ // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
+ llvm::Value *Args[] = {
+ RTLoc,
+ CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
+ CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
+ llvm::SmallVector<llvm::Value *, 16> RealArgs;
+ RealArgs.append(std::begin(Args), std::end(Args));
+ RealArgs.append(CapturedVars.begin(), CapturedVars.end());
+
+ auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
+ CGF.EmitRuntimeCall(RTLFn, RealArgs);
+ };
+ auto &&ElseGen = [this, OutlinedFn, CapturedVars, RTLoc,
+ Loc](CodeGenFunction &CGF) {
auto ThreadID = getThreadID(CGF, Loc);
// Build calls:
// __kmpc_serialized_parallel(&Loc, GTid);
@@ -1177,11 +1325,14 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
// OutlinedFn(&GTid, &zero, CapturedStruct);
auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
- auto Int32Ty = CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32,
- /*Signed*/ true);
- auto ZeroAddr = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".zero.addr");
+ Address ZeroAddr =
+ CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4),
+ /*Name*/ ".zero.addr");
CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
- llvm::Value *OutlinedFnArgs[] = {ThreadIDAddr, ZeroAddr, CapturedStruct};
+ llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
+ OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
+ OutlinedFnArgs.push_back(ZeroAddr.getPointer());
+ OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
// __kmpc_end_serialized_parallel(&Loc, GTid);
@@ -1203,8 +1354,8 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
// regular serial code region, get thread ID by calling kmp_int32
// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
// return the address of that temp.
-llvm::Value *CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
- SourceLocation Loc) {
+Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
+ SourceLocation Loc) {
if (auto OMPRegionInfo =
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
if (OMPRegionInfo->getThreadIDVariable())
@@ -1215,7 +1366,7 @@ llvm::Value *CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
CGF.EmitStoreOfScalar(ThreadID,
- CGF.MakeNaturalAlignAddrLValue(ThreadIDTemp, Int32Ty));
+ CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
return ThreadIDTemp;
}
@@ -1246,7 +1397,7 @@ llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
}
namespace {
-template <size_t N> class CallEndCleanup : public EHScopeStack::Cleanup {
+template <size_t N> class CallEndCleanup final : public EHScopeStack::Cleanup {
llvm::Value *Callee;
llvm::Value *Args[N];
@@ -1257,39 +1408,50 @@ public:
std::copy(CleanupArgs.begin(), CleanupArgs.end(), std::begin(Args));
}
void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
+ if (!CGF.HaveInsertPoint())
+ return;
CGF.EmitRuntimeCall(Callee, Args);
}
};
-} // namespace
+} // anonymous namespace
void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
StringRef CriticalName,
const RegionCodeGenTy &CriticalOpGen,
- SourceLocation Loc) {
- // __kmpc_critical(ident_t *, gtid, Lock);
+ SourceLocation Loc, const Expr *Hint) {
+ // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
// CriticalOpGen();
// __kmpc_end_critical(ident_t *, gtid, Lock);
// Prepare arguments and build a call to __kmpc_critical
- {
- CodeGenFunction::RunCleanupsScope Scope(CGF);
- llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
- getCriticalRegionLock(CriticalName)};
+ if (!CGF.HaveInsertPoint())
+ return;
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
+ getCriticalRegionLock(CriticalName)};
+ if (Hint) {
+ llvm::SmallVector<llvm::Value *, 8> ArgsWithHint(std::begin(Args),
+ std::end(Args));
+ auto *HintVal = CGF.EmitScalarExpr(Hint);
+ ArgsWithHint.push_back(
+ CGF.Builder.CreateIntCast(HintVal, CGM.IntPtrTy, /*isSigned=*/false));
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical_with_hint),
+ ArgsWithHint);
+ } else
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
- // Build a call to __kmpc_end_critical
- CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
- NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
- llvm::makeArrayRef(Args));
- emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
- }
+ // Build a call to __kmpc_end_critical
+ CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
+ NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical),
+ llvm::makeArrayRef(Args));
+ emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
}
static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
- OpenMPDirectiveKind Kind,
+ OpenMPDirectiveKind Kind, SourceLocation Loc,
const RegionCodeGenTy &BodyOpGen) {
llvm::Value *CallBool = CGF.EmitScalarConversion(
IfCond,
CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
- CGF.getContext().BoolTy);
+ CGF.getContext().BoolTy, Loc);
auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
auto *ContBlock = CGF.createBasicBlock("omp_if.end");
@@ -1305,6 +1467,8 @@ static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
const RegionCodeGenTy &MasterOpGen,
SourceLocation Loc) {
+ if (!CGF.HaveInsertPoint())
+ return;
// if(__kmpc_master(ident_t *, gtid)) {
// MasterOpGen();
// __kmpc_end_master(ident_t *, gtid);
@@ -1315,17 +1479,20 @@ void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
typedef CallEndCleanup<std::extent<decltype(Args)>::value>
MasterCallEndCleanup;
- emitIfStmt(CGF, IsMaster, OMPD_master, [&](CodeGenFunction &CGF) -> void {
- CodeGenFunction::RunCleanupsScope Scope(CGF);
- CGF.EHStack.pushCleanup<MasterCallEndCleanup>(
- NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
- llvm::makeArrayRef(Args));
- MasterOpGen(CGF);
- });
+ emitIfStmt(
+ CGF, IsMaster, OMPD_master, Loc, [&](CodeGenFunction &CGF) -> void {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ CGF.EHStack.pushCleanup<MasterCallEndCleanup>(
+ NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master),
+ llvm::makeArrayRef(Args));
+ MasterOpGen(CGF);
+ });
}
void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
SourceLocation Loc) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Build call __kmpc_omp_taskyield(loc, thread_id, 0);
llvm::Value *Args[] = {
emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
@@ -1336,6 +1503,8 @@ void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
const RegionCodeGenTy &TaskgroupOpGen,
SourceLocation Loc) {
+ if (!CGF.HaveInsertPoint())
+ return;
// __kmpc_taskgroup(ident_t *, gtid);
// TaskgroupOpGen();
// __kmpc_end_taskgroup(ident_t *, gtid);
@@ -1352,6 +1521,21 @@ void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
}
}
+/// Given an array of pointers to variables, project the address of a
+/// given variable.
+static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
+ unsigned Index, const VarDecl *Var) {
+ // Pull out the pointer to the variable.
+ Address PtrAddr =
+ CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize());
+ llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
+
+ Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
+ Addr = CGF.Builder.CreateElementBitCast(
+ Addr, CGF.ConvertTypeForMem(Var->getType()));
+ return Addr;
+}
+
static llvm::Value *emitCopyprivateCopyFunction(
CodeGenModule &CGM, llvm::Type *ArgsType,
ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
@@ -1371,40 +1555,31 @@ static llvm::Value *emitCopyprivateCopyFunction(
auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
".omp.copyprivate.copy_func", &CGM.getModule());
- CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
+ CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
CodeGenFunction CGF(CGM);
CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
// Dest = (void*[n])(LHSArg);
// Src = (void*[n])(RHSArg);
- auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
- CGF.PointerAlignInBytes),
- ArgsType);
- auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg),
- CGF.PointerAlignInBytes),
- ArgsType);
+ Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
+ ArgsType), CGF.getPointerAlign());
+ Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
+ ArgsType), CGF.getPointerAlign());
// *(Type0*)Dst[0] = *(Type0*)Src[0];
// *(Type1*)Dst[1] = *(Type1*)Src[1];
// ...
// *(Typen*)Dst[n] = *(Typen*)Src[n];
for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
- auto *DestAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.Builder.CreateAlignedLoad(
- CGF.Builder.CreateStructGEP(nullptr, LHS, I),
- CGM.PointerAlignInBytes),
- CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
- auto *SrcAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.Builder.CreateAlignedLoad(
- CGF.Builder.CreateStructGEP(nullptr, RHS, I),
- CGM.PointerAlignInBytes),
- CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
+ auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
+ Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
+
+ auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
+ Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
+
auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
QualType Type = VD->getType();
- CGF.EmitOMPCopy(CGF, Type, DestAddr, SrcAddr,
- cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()),
- cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()),
- AssignmentOps[I]);
+ CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
}
CGF.FinishFunction();
return Fn;
@@ -1417,6 +1592,8 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
ArrayRef<const Expr *> SrcExprs,
ArrayRef<const Expr *> DstExprs,
ArrayRef<const Expr *> AssignmentOps) {
+ if (!CGF.HaveInsertPoint())
+ return;
assert(CopyprivateVars.size() == SrcExprs.size() &&
CopyprivateVars.size() == DstExprs.size() &&
CopyprivateVars.size() == AssignmentOps.size());
@@ -1430,13 +1607,12 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
// call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
// <copy_func>, did_it);
- llvm::AllocaInst *DidIt = nullptr;
+ Address DidIt = Address::invalid();
if (!CopyprivateVars.empty()) {
// int32 did_it = 0;
auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
- CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(0), DidIt,
- DidIt->getAlignment());
+ CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
}
// Prepare arguments and build a call to __kmpc_single
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
@@ -1444,52 +1620,51 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
typedef CallEndCleanup<std::extent<decltype(Args)>::value>
SingleCallEndCleanup;
- emitIfStmt(CGF, IsSingle, OMPD_single, [&](CodeGenFunction &CGF) -> void {
- CodeGenFunction::RunCleanupsScope Scope(CGF);
- CGF.EHStack.pushCleanup<SingleCallEndCleanup>(
- NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
- llvm::makeArrayRef(Args));
- SingleOpGen(CGF);
- if (DidIt) {
- // did_it = 1;
- CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(1), DidIt,
- DidIt->getAlignment());
- }
- });
+ emitIfStmt(
+ CGF, IsSingle, OMPD_single, Loc, [&](CodeGenFunction &CGF) -> void {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ CGF.EHStack.pushCleanup<SingleCallEndCleanup>(
+ NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single),
+ llvm::makeArrayRef(Args));
+ SingleOpGen(CGF);
+ if (DidIt.isValid()) {
+ // did_it = 1;
+ CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
+ }
+ });
// call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
// <copy_func>, did_it);
- if (DidIt) {
+ if (DidIt.isValid()) {
llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
auto CopyprivateArrayTy =
C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
/*IndexTypeQuals=*/0);
// Create a list of all private variables for copyprivate.
- auto *CopyprivateList =
+ Address CopyprivateList =
CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
- auto *Elem = CGF.Builder.CreateStructGEP(
- CopyprivateList->getAllocatedType(), CopyprivateList, I);
- CGF.Builder.CreateAlignedStore(
+ Address Elem = CGF.Builder.CreateConstArrayGEP(
+ CopyprivateList, I, CGF.getPointerSize());
+ CGF.Builder.CreateStore(
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.EmitLValue(CopyprivateVars[I]).getAddress(), CGF.VoidPtrTy),
- Elem, CGM.PointerAlignInBytes);
+ CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
+ Elem);
}
// Build function that copies private values from single region to all other
// threads in the corresponding parallel region.
auto *CpyFn = emitCopyprivateCopyFunction(
CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
CopyprivateVars, SrcExprs, DstExprs, AssignmentOps);
- auto *BufSize = llvm::ConstantInt::get(
- CGM.SizeTy, C.getTypeSizeInChars(CopyprivateArrayTy).getQuantity());
- auto *CL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
- CGF.VoidPtrTy);
- auto *DidItVal =
- CGF.Builder.CreateAlignedLoad(DidIt, CGF.PointerAlignInBytes);
+ auto *BufSize = getTypeSize(CGF, CopyprivateArrayTy);
+ Address CL =
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
+ CGF.VoidPtrTy);
+ auto *DidItVal = CGF.Builder.CreateLoad(DidIt);
llvm::Value *Args[] = {
emitUpdateLocation(CGF, Loc), // ident_t *<loc>
getThreadID(CGF, Loc), // i32 <gtid>
BufSize, // size_t <buf_size>
- CL, // void *<copyprivate list>
+ CL.getPointer(), // void *<copyprivate list>
CpyFn, // void (*) (void *, void *) <copy_func>
DidItVal // i32 did_it
};
@@ -1499,26 +1674,30 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
const RegionCodeGenTy &OrderedOpGen,
- SourceLocation Loc) {
+ SourceLocation Loc, bool IsThreads) {
+ if (!CGF.HaveInsertPoint())
+ return;
// __kmpc_ordered(ident_t *, gtid);
// OrderedOpGen();
// __kmpc_end_ordered(ident_t *, gtid);
// Prepare arguments and build a call to __kmpc_ordered
- {
- CodeGenFunction::RunCleanupsScope Scope(CGF);
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ if (IsThreads) {
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_ordered), Args);
// Build a call to __kmpc_end_ordered
CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>(
NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered),
llvm::makeArrayRef(Args));
- emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
}
+ emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
}
void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
- OpenMPDirectiveKind Kind,
- bool CheckForCancel) {
+ OpenMPDirectiveKind Kind, bool EmitChecks,
+ bool ForceSimpleCall) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Build call __kmpc_cancel_barrier(loc, thread_id);
// Build call __kmpc_barrier(loc, thread_id);
OpenMPLocationFlags Flags = OMP_IDENT_KMPC;
@@ -1538,16 +1717,19 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
}
// Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
// thread_id);
+ auto *OMPRegionInfo =
+ dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
+ // Do not emit barrier call in the single directive emitted in some rare cases
+ // for sections directives.
+ if (OMPRegionInfo && OMPRegionInfo->getDirectiveKind() == OMPD_single)
+ return;
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
getThreadID(CGF, Loc)};
- if (auto *OMPRegionInfo =
- dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
- auto CancelDestination =
- CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
- if (CancelDestination.isValid()) {
+ if (OMPRegionInfo) {
+ if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
auto *Result = CGF.EmitRuntimeCall(
createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
- if (CheckForCancel) {
+ if (EmitChecks) {
// if (__kmpc_cancel_barrier()) {
// exit from construct;
// }
@@ -1557,6 +1739,8 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
CGF.EmitBlock(ExitBB);
// exit from construct;
+ auto CancelDestination =
+ CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
CGF.EmitBranchThroughCleanup(CancelDestination);
CGF.EmitBlock(ContBB, /*IsFinished=*/true);
}
@@ -1623,65 +1807,87 @@ bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
return Schedule != OMP_sch_static;
}
-void CGOpenMPRuntime::emitForInit(CodeGenFunction &CGF, SourceLocation Loc,
- OpenMPScheduleClauseKind ScheduleKind,
- unsigned IVSize, bool IVSigned, bool Ordered,
- llvm::Value *IL, llvm::Value *LB,
- llvm::Value *UB, llvm::Value *ST,
- llvm::Value *Chunk) {
+void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ OpenMPScheduleClauseKind ScheduleKind,
+ unsigned IVSize, bool IVSigned,
+ bool Ordered, llvm::Value *UB,
+ llvm::Value *Chunk) {
+ if (!CGF.HaveInsertPoint())
+ return;
OpenMPSchedType Schedule =
getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
- if (Ordered ||
- (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
- Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked)) {
- // Call __kmpc_dispatch_init(
- // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
- // kmp_int[32|64] lower, kmp_int[32|64] upper,
- // kmp_int[32|64] stride, kmp_int[32|64] chunk);
+ assert(Ordered ||
+ (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
+ Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked));
+ // Call __kmpc_dispatch_init(
+ // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
+ // kmp_int[32|64] lower, kmp_int[32|64] upper,
+ // kmp_int[32|64] stride, kmp_int[32|64] chunk);
+
+ // If the Chunk was not specified in the clause - use default value 1.
+ if (Chunk == nullptr)
+ Chunk = CGF.Builder.getIntN(IVSize, 1);
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
+ getThreadID(CGF, Loc),
+ CGF.Builder.getInt32(Schedule), // Schedule type
+ CGF.Builder.getIntN(IVSize, 0), // Lower
+ UB, // Upper
+ CGF.Builder.getIntN(IVSize, 1), // Stride
+ Chunk // Chunk
+ };
+ CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
+}
+void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ OpenMPScheduleClauseKind ScheduleKind,
+ unsigned IVSize, bool IVSigned,
+ bool Ordered, Address IL, Address LB,
+ Address UB, Address ST,
+ llvm::Value *Chunk) {
+ if (!CGF.HaveInsertPoint())
+ return;
+ OpenMPSchedType Schedule =
+ getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered);
+ assert(!Ordered);
+ assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
+ Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked);
+
+ // Call __kmpc_for_static_init(
+ // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
+ // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
+ // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
+ // kmp_int[32|64] incr, kmp_int[32|64] chunk);
+ if (Chunk == nullptr) {
+ assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static) &&
+ "expected static non-chunked schedule");
// If the Chunk was not specified in the clause - use default value 1.
- if (Chunk == nullptr)
Chunk = CGF.Builder.getIntN(IVSize, 1);
- llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
- getThreadID(CGF, Loc),
- CGF.Builder.getInt32(Schedule), // Schedule type
- CGF.Builder.getIntN(IVSize, 0), // Lower
- UB, // Upper
- CGF.Builder.getIntN(IVSize, 1), // Stride
- Chunk // Chunk
- };
- CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
} else {
- // Call __kmpc_for_static_init(
- // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
- // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
- // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
- // kmp_int[32|64] incr, kmp_int[32|64] chunk);
- if (Chunk == nullptr) {
- assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static) &&
- "expected static non-chunked schedule");
- // If the Chunk was not specified in the clause - use default value 1.
- Chunk = CGF.Builder.getIntN(IVSize, 1);
- } else
- assert((Schedule == OMP_sch_static_chunked ||
- Schedule == OMP_ord_static_chunked) &&
- "expected static chunked schedule");
- llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
- getThreadID(CGF, Loc),
- CGF.Builder.getInt32(Schedule), // Schedule type
- IL, // &isLastIter
- LB, // &LB
- UB, // &UB
- ST, // &Stride
- CGF.Builder.getIntN(IVSize, 1), // Incr
- Chunk // Chunk
- };
- CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args);
+ assert((Schedule == OMP_sch_static_chunked ||
+ Schedule == OMP_ord_static_chunked) &&
+ "expected static chunked schedule");
}
+ llvm::Value *Args[] = {
+ emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
+ getThreadID(CGF, Loc),
+ CGF.Builder.getInt32(Schedule), // Schedule type
+ IL.getPointer(), // &isLastIter
+ LB.getPointer(), // &LB
+ UB.getPointer(), // &UB
+ ST.getPointer(), // &Stride
+ CGF.Builder.getIntN(IVSize, 1), // Incr
+ Chunk // Chunk
+ };
+ CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args);
}
void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
SourceLocation Loc) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
getThreadID(CGF, Loc)};
@@ -1693,6 +1899,8 @@ void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
SourceLocation Loc,
unsigned IVSize,
bool IVSigned) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
getThreadID(CGF, Loc)};
@@ -1701,30 +1909,32 @@ void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
SourceLocation Loc, unsigned IVSize,
- bool IVSigned, llvm::Value *IL,
- llvm::Value *LB, llvm::Value *UB,
- llvm::Value *ST) {
+ bool IVSigned, Address IL,
+ Address LB, Address UB,
+ Address ST) {
// Call __kmpc_dispatch_next(
// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
// kmp_int[32|64] *p_stride);
llvm::Value *Args[] = {
emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), getThreadID(CGF, Loc),
- IL, // &isLastIter
- LB, // &Lower
- UB, // &Upper
- ST // &Stride
+ IL.getPointer(), // &isLastIter
+ LB.getPointer(), // &Lower
+ UB.getPointer(), // &Upper
+ ST.getPointer() // &Stride
};
llvm::Value *Call =
CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
return CGF.EmitScalarConversion(
Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true),
- CGF.getContext().BoolTy);
+ CGF.getContext().BoolTy, Loc);
}
void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
llvm::Value *NumThreads,
SourceLocation Loc) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
llvm::Value *Args[] = {
emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
@@ -1736,6 +1946,8 @@ void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
OpenMPProcBindClauseKind ProcBind,
SourceLocation Loc) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Constants for proc bind value accepted by the runtime.
enum ProcBindTy {
ProcBindFalse = 0,
@@ -1768,6 +1980,8 @@ void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
SourceLocation Loc) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Build call void __kmpc_flush(ident_t *loc)
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
emitUpdateLocation(CGF, Loc));
@@ -1785,7 +1999,382 @@ enum KmpTaskTFields {
/// \brief Function with call of destructors for private variables.
KmpTaskTDestructors,
};
-} // namespace
+} // anonymous namespace
+
+bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
+ // FIXME: Add other entries type when they become supported.
+ return OffloadEntriesTargetRegion.empty();
+}
+
+/// \brief Initialize target region entry.
+void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
+ initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
+ StringRef ParentName, unsigned LineNum,
+ unsigned ColNum, unsigned Order) {
+ assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
+ "only required for the device "
+ "code generation.");
+ OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum][ColNum] =
+ OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr);
+ ++OffloadingEntriesNum;
+}
+
+void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
+ registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
+ StringRef ParentName, unsigned LineNum,
+ unsigned ColNum, llvm::Constant *Addr,
+ llvm::Constant *ID) {
+ // If we are emitting code for a target, the entry is already initialized,
+ // only has to be registered.
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum,
+ ColNum) &&
+ "Entry must exist.");
+ auto &Entry = OffloadEntriesTargetRegion[DeviceID][FileID][ParentName]
+ [LineNum][ColNum];
+ assert(Entry.isValid() && "Entry not initialized!");
+ Entry.setAddress(Addr);
+ Entry.setID(ID);
+ return;
+ } else {
+ OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID);
+ OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum][ColNum] =
+ Entry;
+ }
+}
+
+bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
+ unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned LineNum,
+ unsigned ColNum) const {
+ auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
+ if (PerDevice == OffloadEntriesTargetRegion.end())
+ return false;
+ auto PerFile = PerDevice->second.find(FileID);
+ if (PerFile == PerDevice->second.end())
+ return false;
+ auto PerParentName = PerFile->second.find(ParentName);
+ if (PerParentName == PerFile->second.end())
+ return false;
+ auto PerLine = PerParentName->second.find(LineNum);
+ if (PerLine == PerParentName->second.end())
+ return false;
+ auto PerColumn = PerLine->second.find(ColNum);
+ if (PerColumn == PerLine->second.end())
+ return false;
+ // Fail if this entry is already registered.
+ if (PerColumn->second.getAddress() || PerColumn->second.getID())
+ return false;
+ return true;
+}
+
+void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
+ const OffloadTargetRegionEntryInfoActTy &Action) {
+ // Scan all target region entries and perform the provided action.
+ for (auto &D : OffloadEntriesTargetRegion)
+ for (auto &F : D.second)
+ for (auto &P : F.second)
+ for (auto &L : P.second)
+ for (auto &C : L.second)
+ Action(D.first, F.first, P.first(), L.first, C.first, C.second);
+}
+
+/// \brief Create a Ctor/Dtor-like function whose body is emitted through
+/// \a Codegen. This is used to emit the two functions that register and
+/// unregister the descriptor of the current compilation unit.
+static llvm::Function *
+createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
+ const RegionCodeGenTy &Codegen) {
+ auto &C = CGM.getContext();
+ FunctionArgList Args;
+ ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(),
+ /*Id=*/nullptr, C.VoidPtrTy);
+ Args.push_back(&DummyPtr);
+
+ CodeGenFunction CGF(CGM);
+ GlobalDecl();
+ auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
+ C.VoidTy, Args, FunctionType::ExtInfo(),
+ /*isVariadic=*/false);
+ auto FTy = CGM.getTypes().GetFunctionType(FI);
+ auto *Fn =
+ CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation());
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation());
+ Codegen(CGF);
+ CGF.FinishFunction();
+ return Fn;
+}
+
+llvm::Function *
+CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
+
+ // If we don't have entries or if we are emitting code for the device, we
+ // don't need to do anything.
+ if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
+ return nullptr;
+
+ auto &M = CGM.getModule();
+ auto &C = CGM.getContext();
+
+ // Get list of devices we care about
+ auto &Devices = CGM.getLangOpts().OMPTargetTriples;
+
+ // We should be creating an offloading descriptor only if there are devices
+ // specified.
+ assert(!Devices.empty() && "No OpenMP offloading devices??");
+
+ // Create the external variables that will point to the begin and end of the
+ // host entries section. These will be defined by the linker.
+ auto *OffloadEntryTy =
+ CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
+ llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable(
+ M, OffloadEntryTy, /*isConstant=*/true,
+ llvm::GlobalValue::ExternalLinkage, /*Initializer=*/0,
+ ".omp_offloading.entries_begin");
+ llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable(
+ M, OffloadEntryTy, /*isConstant=*/true,
+ llvm::GlobalValue::ExternalLinkage, /*Initializer=*/0,
+ ".omp_offloading.entries_end");
+
+ // Create all device images
+ llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires;
+ auto *DeviceImageTy = cast<llvm::StructType>(
+ CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
+
+ for (unsigned i = 0; i < Devices.size(); ++i) {
+ StringRef T = Devices[i].getTriple();
+ auto *ImgBegin = new llvm::GlobalVariable(
+ M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
+ /*Initializer=*/0, Twine(".omp_offloading.img_start.") + Twine(T));
+ auto *ImgEnd = new llvm::GlobalVariable(
+ M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
+ /*Initializer=*/0, Twine(".omp_offloading.img_end.") + Twine(T));
+
+ llvm::Constant *Dev =
+ llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd,
+ HostEntriesBegin, HostEntriesEnd, nullptr);
+ DeviceImagesEntires.push_back(Dev);
+ }
+
+ // Create device images global array.
+ llvm::ArrayType *DeviceImagesInitTy =
+ llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size());
+ llvm::Constant *DeviceImagesInit =
+ llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires);
+
+ llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable(
+ M, DeviceImagesInitTy, /*isConstant=*/true,
+ llvm::GlobalValue::InternalLinkage, DeviceImagesInit,
+ ".omp_offloading.device_images");
+ DeviceImages->setUnnamedAddr(true);
+
+ // This is a Zero array to be used in the creation of the constant expressions
+ llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
+ llvm::Constant::getNullValue(CGM.Int32Ty)};
+
+ // Create the target region descriptor.
+ auto *BinaryDescriptorTy = cast<llvm::StructType>(
+ CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy()));
+ llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get(
+ BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
+ llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages,
+ Index),
+ HostEntriesBegin, HostEntriesEnd, nullptr);
+
+ auto *Desc = new llvm::GlobalVariable(
+ M, BinaryDescriptorTy, /*isConstant=*/true,
+ llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit,
+ ".omp_offloading.descriptor");
+
+ // Emit code to register or unregister the descriptor at execution
+ // startup or closing, respectively.
+
+ // Create a variable to drive the registration and unregistration of the
+ // descriptor, so we can reuse the logic that emits Ctors and Dtors.
+ auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var");
+ ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(),
+ IdentInfo, C.CharTy);
+
+ auto *UnRegFn = createOffloadingBinaryDescriptorFunction(
+ CGM, ".omp_offloading.descriptor_unreg", [&](CodeGenFunction &CGF) {
+ CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
+ Desc);
+ });
+ auto *RegFn = createOffloadingBinaryDescriptorFunction(
+ CGM, ".omp_offloading.descriptor_reg", [&](CodeGenFunction &CGF) {
+ CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib),
+ Desc);
+ CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
+ });
+ return RegFn;
+}
+
+void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *Addr, StringRef Name,
+ uint64_t Size) {
+ auto *TgtOffloadEntryType = cast<llvm::StructType>(
+ CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()));
+ llvm::LLVMContext &C = CGM.getModule().getContext();
+ llvm::Module &M = CGM.getModule();
+
+ // Make sure the address has the right type.
+ llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(Addr, CGM.VoidPtrTy);
+
+ // Create constant string with the name.
+ llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
+
+ llvm::GlobalVariable *Str =
+ new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true,
+ llvm::GlobalValue::InternalLinkage, StrPtrInit,
+ ".omp_offloading.entry_name");
+ Str->setUnnamedAddr(true);
+ llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy);
+
+ // Create the entry struct.
+ llvm::Constant *EntryInit = llvm::ConstantStruct::get(
+ TgtOffloadEntryType, AddrPtr, StrPtr,
+ llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr);
+ llvm::GlobalVariable *Entry = new llvm::GlobalVariable(
+ M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage,
+ EntryInit, ".omp_offloading.entry");
+
+ // The entry has to be created in the section the linker expects it to be.
+ Entry->setSection(".omp_offloading.entries");
+ // We can't have any padding between symbols, so we need to have 1-byte
+ // alignment.
+ Entry->setAlignment(1);
+ return;
+}
+
+void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
+ // Emit the offloading entries and metadata so that the device codegen side
+ // can
+ // easily figure out what to emit. The produced metadata looks like this:
+ //
+ // !omp_offload.info = !{!1, ...}
+ //
+ // Right now we only generate metadata for function that contain target
+ // regions.
+
+ // If we do not have entries, we dont need to do anything.
+ if (OffloadEntriesInfoManager.empty())
+ return;
+
+ llvm::Module &M = CGM.getModule();
+ llvm::LLVMContext &C = M.getContext();
+ SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
+ OrderedEntries(OffloadEntriesInfoManager.size());
+
+ // Create the offloading info metadata node.
+ llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
+
+ // Auxiliar methods to create metadata values and strings.
+ auto getMDInt = [&](unsigned v) {
+ return llvm::ConstantAsMetadata::get(
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v));
+ };
+
+ auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); };
+
+ // Create function that emits metadata for each target region entry;
+ auto &&TargetRegionMetadataEmitter = [&](
+ unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line,
+ unsigned Column,
+ OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
+ llvm::SmallVector<llvm::Metadata *, 32> Ops;
+ // Generate metadata for target regions. Each entry of this metadata
+ // contains:
+ // - Entry 0 -> Kind of this type of metadata (0).
+ // - Entry 1 -> Device ID of the file where the entry was identified.
+ // - Entry 2 -> File ID of the file where the entry was identified.
+ // - Entry 3 -> Mangled name of the function where the entry was identified.
+ // - Entry 4 -> Line in the file where the entry was identified.
+ // - Entry 5 -> Column in the file where the entry was identified.
+ // - Entry 6 -> Order the entry was created.
+ // The first element of the metadata node is the kind.
+ Ops.push_back(getMDInt(E.getKind()));
+ Ops.push_back(getMDInt(DeviceID));
+ Ops.push_back(getMDInt(FileID));
+ Ops.push_back(getMDString(ParentName));
+ Ops.push_back(getMDInt(Line));
+ Ops.push_back(getMDInt(Column));
+ Ops.push_back(getMDInt(E.getOrder()));
+
+ // Save this entry in the right position of the ordered entries array.
+ OrderedEntries[E.getOrder()] = &E;
+
+ // Add metadata to the named metadata node.
+ MD->addOperand(llvm::MDNode::get(C, Ops));
+ };
+
+ OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
+ TargetRegionMetadataEmitter);
+
+ for (auto *E : OrderedEntries) {
+ assert(E && "All ordered entries must exist!");
+ if (auto *CE =
+ dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
+ E)) {
+ assert(CE->getID() && CE->getAddress() &&
+ "Entry ID and Addr are invalid!");
+ createOffloadEntry(CE->getID(), CE->getAddress()->getName(), /*Size=*/0);
+ } else
+ llvm_unreachable("Unsupported entry kind.");
+ }
+}
+
+/// \brief Loads all the offload entries information from the host IR
+/// metadata.
+void CGOpenMPRuntime::loadOffloadInfoMetadata() {
+ // If we are in target mode, load the metadata from the host IR. This code has
+ // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
+
+ if (!CGM.getLangOpts().OpenMPIsDevice)
+ return;
+
+ if (CGM.getLangOpts().OMPHostIRFile.empty())
+ return;
+
+ auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
+ if (Buf.getError())
+ return;
+
+ llvm::LLVMContext C;
+ auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C);
+
+ if (ME.getError())
+ return;
+
+ llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
+ if (!MD)
+ return;
+
+ for (auto I : MD->operands()) {
+ llvm::MDNode *MN = cast<llvm::MDNode>(I);
+
+ auto getMDInt = [&](unsigned Idx) {
+ llvm::ConstantAsMetadata *V =
+ cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
+ return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
+ };
+
+ auto getMDString = [&](unsigned Idx) {
+ llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx));
+ return V->getString();
+ };
+
+ switch (getMDInt(0)) {
+ default:
+ llvm_unreachable("Unexpected metadata!");
+ break;
+ case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
+ OFFLOAD_ENTRY_INFO_TARGET_REGION:
+ OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
+ /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2),
+ /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4),
+ /*Column=*/getMDInt(5), /*Order=*/getMDInt(6));
+ break;
+ }
+ }
+}
void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
if (!KmpRoutineEntryPtrTy) {
@@ -1799,14 +2388,89 @@ void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
}
}
-static void addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
- QualType FieldTy) {
+static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
+ QualType FieldTy) {
auto *Field = FieldDecl::Create(
C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
/*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
Field->setAccess(AS_public);
DC->addDecl(Field);
+ return Field;
+}
+
+QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
+
+ // Make sure the type of the entry is already created. This is the type we
+ // have to create:
+ // struct __tgt_offload_entry{
+ // void *addr; // Pointer to the offload entry info.
+ // // (function or global)
+ // char *name; // Name of the function or global.
+ // size_t size; // Size of the entry info (0 if it a function).
+ // };
+ if (TgtOffloadEntryQTy.isNull()) {
+ ASTContext &C = CGM.getContext();
+ auto *RD = C.buildImplicitRecord("__tgt_offload_entry");
+ RD->startDefinition();
+ addFieldToRecordDecl(C, RD, C.VoidPtrTy);
+ addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
+ addFieldToRecordDecl(C, RD, C.getSizeType());
+ RD->completeDefinition();
+ TgtOffloadEntryQTy = C.getRecordType(RD);
+ }
+ return TgtOffloadEntryQTy;
+}
+
+QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
+ // These are the types we need to build:
+ // struct __tgt_device_image{
+ // void *ImageStart; // Pointer to the target code start.
+ // void *ImageEnd; // Pointer to the target code end.
+ // // We also add the host entries to the device image, as it may be useful
+ // // for the target runtime to have access to that information.
+ // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
+ // // the entries.
+ // __tgt_offload_entry *EntriesEnd; // End of the table with all the
+ // // entries (non inclusive).
+ // };
+ if (TgtDeviceImageQTy.isNull()) {
+ ASTContext &C = CGM.getContext();
+ auto *RD = C.buildImplicitRecord("__tgt_device_image");
+ RD->startDefinition();
+ addFieldToRecordDecl(C, RD, C.VoidPtrTy);
+ addFieldToRecordDecl(C, RD, C.VoidPtrTy);
+ addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
+ addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
+ RD->completeDefinition();
+ TgtDeviceImageQTy = C.getRecordType(RD);
+ }
+ return TgtDeviceImageQTy;
+}
+
+QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
+ // struct __tgt_bin_desc{
+ // int32_t NumDevices; // Number of devices supported.
+ // __tgt_device_image *DeviceImages; // Arrays of device images
+ // // (one per device).
+ // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
+ // // entries.
+ // __tgt_offload_entry *EntriesEnd; // End of the table with all the
+ // // entries (non inclusive).
+ // };
+ if (TgtBinaryDescriptorQTy.isNull()) {
+ ASTContext &C = CGM.getContext();
+ auto *RD = C.buildImplicitRecord("__tgt_bin_desc");
+ RD->startDefinition();
+ addFieldToRecordDecl(
+ C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
+ addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
+ addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
+ addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
+ RD->completeDefinition();
+ TgtBinaryDescriptorQTy = C.getRecordType(RD);
+ }
+ return TgtBinaryDescriptorQTy;
}
namespace {
@@ -1820,11 +2484,10 @@ struct PrivateHelpersTy {
const VarDecl *PrivateElemInit;
};
typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
-} // namespace
+} // anonymous namespace
static RecordDecl *
-createPrivatesRecordDecl(CodeGenModule &CGM,
- const ArrayRef<PrivateDataTy> Privates) {
+createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
if (!Privates.empty()) {
auto &C = CGM.getContext();
// Build struct .kmp_privates_t. {
@@ -1833,9 +2496,16 @@ createPrivatesRecordDecl(CodeGenModule &CGM,
auto *RD = C.buildImplicitRecord(".kmp_privates.t");
RD->startDefinition();
for (auto &&Pair : Privates) {
- auto Type = Pair.second.Original->getType();
+ auto *VD = Pair.second.Original;
+ auto Type = VD->getType();
Type = Type.getNonReferenceType();
- addFieldToRecordDecl(C, RD, Type);
+ auto *FD = addFieldToRecordDecl(C, RD, Type);
+ if (VD->hasAttrs()) {
+ for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
+ E(VD->getAttrs().end());
+ I != E; ++I)
+ FD->addAttr(*I);
+ }
}
RD->completeDefinition();
return RD;
@@ -1865,7 +2535,7 @@ createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
static RecordDecl *
createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
- const ArrayRef<PrivateDataTy> Privates) {
+ ArrayRef<PrivateDataTy> Privates) {
auto &C = CGM.getContext();
// Build struct kmp_task_t_with_privates {
// kmp_task_t task_data;
@@ -1900,7 +2570,8 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
FunctionArgList Args;
ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
- /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
+ /*Id=*/nullptr,
+ KmpTaskTWithPrivatesPtrQTy.withRestrict());
Args.push_back(&GtidArg);
Args.push_back(&TaskTypeArg);
FunctionType::ExtInfo Info;
@@ -1911,7 +2582,7 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
auto *TaskEntry =
llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage,
".omp_task_entry.", &CGM.getModule());
- CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskEntryFnInfo, TaskEntry);
+ CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo);
CodeGenFunction CGF(CGM);
CGF.disableDebugInfo();
CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
@@ -1919,12 +2590,9 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
// TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
// tt->task_data.shareds);
auto *GtidParam = CGF.EmitLoadOfScalar(
- CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false,
- C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc);
- auto *TaskTypeArgAddr = CGF.Builder.CreateAlignedLoad(
- CGF.GetAddrOfLocalVar(&TaskTypeArg), CGM.PointerAlignInBytes);
- LValue TDBase =
- CGF.MakeNaturalAlignAddrLValue(TaskTypeArgAddr, KmpTaskTWithPrivatesQTy);
+ CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
+ LValue TDBase = emitLoadOfPointerLValue(
+ CGF, CGF.GetAddrOfLocalVar(&TaskTypeArg), KmpTaskTWithPrivatesPtrQTy);
auto *KmpTaskTWithPrivatesQTyRD =
cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
LValue Base =
@@ -1945,7 +2613,7 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- PrivatesLVal.getAddress(), CGF.VoidPtrTy);
+ PrivatesLVal.getPointer(), CGF.VoidPtrTy);
} else {
PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
}
@@ -1955,7 +2623,7 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
CGF.EmitCallOrInvoke(TaskFunction, CallArgs);
CGF.EmitStoreThroughLValue(
RValue::get(CGF.Builder.getInt32(/*C=*/0)),
- CGF.MakeNaturalAlignAddrLValue(CGF.ReturnValue, KmpInt32Ty));
+ CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
CGF.FinishFunction();
return TaskEntry;
}
@@ -1969,7 +2637,8 @@ static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
FunctionArgList Args;
ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
- /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
+ /*Id=*/nullptr,
+ KmpTaskTWithPrivatesPtrQTy.withRestrict());
Args.push_back(&GtidArg);
Args.push_back(&TaskTypeArg);
FunctionType::ExtInfo Info;
@@ -1980,16 +2649,15 @@ static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
auto *DestructorFn =
llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
".omp_task_destructor.", &CGM.getModule());
- CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, DestructorFnInfo, DestructorFn);
+ CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn,
+ DestructorFnInfo);
CodeGenFunction CGF(CGM);
CGF.disableDebugInfo();
CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Args);
- auto *TaskTypeArgAddr = CGF.Builder.CreateAlignedLoad(
- CGF.GetAddrOfLocalVar(&TaskTypeArg), CGM.PointerAlignInBytes);
- LValue Base =
- CGF.MakeNaturalAlignAddrLValue(TaskTypeArgAddr, KmpTaskTWithPrivatesQTy);
+ LValue Base = emitLoadOfPointerLValue(
+ CGF, CGF.GetAddrOfLocalVar(&TaskTypeArg), KmpTaskTWithPrivatesPtrQTy);
auto *KmpTaskTWithPrivatesQTyRD =
cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
@@ -2017,10 +2685,10 @@ static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
/// \endcode
static llvm::Value *
emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
- const ArrayRef<const Expr *> PrivateVars,
- const ArrayRef<const Expr *> FirstprivateVars,
+ ArrayRef<const Expr *> PrivateVars,
+ ArrayRef<const Expr *> FirstprivateVars,
QualType PrivatesQTy,
- const ArrayRef<PrivateDataTy> Privates) {
+ ArrayRef<PrivateDataTy> Privates) {
auto &C = CGM.getContext();
FunctionArgList Args;
ImplicitParamDecl TaskPrivatesArg(
@@ -2058,8 +2726,8 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
auto *TaskPrivatesMap = llvm::Function::Create(
TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage,
".omp_task_privates_map.", &CGM.getModule());
- CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskPrivatesMapFnInfo,
- TaskPrivatesMap);
+ CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
+ TaskPrivatesMapFnInfo);
TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
CodeGenFunction CGF(CGM);
CGF.disableDebugInfo();
@@ -2067,22 +2735,17 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
TaskPrivatesMapFnInfo, Args);
// *privi = &.privates.privi;
- auto *TaskPrivatesArgAddr = CGF.Builder.CreateAlignedLoad(
- CGF.GetAddrOfLocalVar(&TaskPrivatesArg), CGM.PointerAlignInBytes);
- LValue Base =
- CGF.MakeNaturalAlignAddrLValue(TaskPrivatesArgAddr, PrivatesQTy);
+ LValue Base = emitLoadOfPointerLValue(
+ CGF, CGF.GetAddrOfLocalVar(&TaskPrivatesArg), TaskPrivatesArg.getType());
auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Counter = 0;
for (auto *Field : PrivatesQTyRD->fields()) {
auto FieldLVal = CGF.EmitLValueForField(Base, Field);
auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
- auto RefLVal = CGF.MakeNaturalAlignAddrLValue(CGF.GetAddrOfLocalVar(VD),
- VD->getType());
- auto RefLoadRVal = CGF.EmitLoadOfLValue(RefLVal, Loc);
- CGF.EmitStoreOfScalar(
- FieldLVal.getAddress(),
- CGF.MakeNaturalAlignAddrLValue(RefLoadRVal.getScalarVal(),
- RefLVal.getType()->getPointeeType()));
+ auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
+ auto RefLoadLVal =
+ emitLoadOfPointerLValue(CGF, RefLVal.getAddress(), RefLVal.getType());
+ CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
++Counter;
}
CGF.FinishFunction();
@@ -2097,13 +2760,15 @@ static int array_pod_sort_comparator(const PrivateDataTy *P1,
void CGOpenMPRuntime::emitTaskCall(
CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
- llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds,
+ llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
ArrayRef<const Expr *> PrivateCopies,
ArrayRef<const Expr *> FirstprivateVars,
ArrayRef<const Expr *> FirstprivateCopies,
ArrayRef<const Expr *> FirstprivateInits,
ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
+ if (!CGF.HaveInsertPoint())
+ return;
auto &C = CGM.getContext();
llvm::SmallVector<PrivateDataTy, 8> Privates;
// Aggregate privates and sort them by the alignment.
@@ -2111,7 +2776,7 @@ void CGOpenMPRuntime::emitTaskCall(
for (auto *E : PrivateVars) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Privates.push_back(std::make_pair(
- C.getTypeAlignInChars(VD->getType()),
+ C.getDeclAlign(VD),
PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
/*PrivateElemInit=*/nullptr)));
++I;
@@ -2121,7 +2786,7 @@ void CGOpenMPRuntime::emitTaskCall(
for (auto *E : FirstprivateVars) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Privates.push_back(std::make_pair(
- C.getTypeAlignInChars(VD->getType()),
+ C.getDeclAlign(VD),
PrivateHelpersTy(
VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))));
@@ -2146,8 +2811,7 @@ void CGOpenMPRuntime::emitTaskCall(
C.getPointerType(KmpTaskTWithPrivatesQTy);
auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
- auto KmpTaskTWithPrivatesTySize =
- CGM.getSize(C.getTypeSizeInChars(KmpTaskTWithPrivatesQTy));
+ auto *KmpTaskTWithPrivatesTySize = getTypeSize(CGF, KmpTaskTWithPrivatesQTy);
QualType SharedsPtrTy = C.getPointerType(SharedsTy);
// Emit initial values for private copies (if any).
@@ -2188,12 +2852,12 @@ void CGOpenMPRuntime::emitTaskCall(
CGF.Builder.getInt32(/*C=*/0))
: CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
- auto SharedsSize = C.getTypeSizeInChars(SharedsTy);
- llvm::Value *AllocArgs[] = {
- emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), TaskFlags,
- KmpTaskTWithPrivatesTySize, CGM.getSize(SharedsSize),
- CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskEntry,
- KmpRoutineEntryPtrTy)};
+ auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
+ llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
+ getThreadID(CGF, Loc), TaskFlags,
+ KmpTaskTWithPrivatesTySize, SharedsSize,
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ TaskEntry, KmpRoutineEntryPtrTy)};
auto *NewTask = CGF.EmitRuntimeCall(
createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
@@ -2204,12 +2868,15 @@ void CGOpenMPRuntime::emitTaskCall(
CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
// Fill the data in the resulting kmp_task_t record.
// Copy shareds if there are any.
- llvm::Value *KmpTaskSharedsPtr = nullptr;
+ Address KmpTaskSharedsPtr = Address::invalid();
if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
- KmpTaskSharedsPtr = CGF.EmitLoadOfScalar(
- CGF.EmitLValueForField(
- TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
- Loc);
+ KmpTaskSharedsPtr =
+ Address(CGF.EmitLoadOfScalar(
+ CGF.EmitLValueForField(
+ TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
+ KmpTaskTShareds)),
+ Loc),
+ CGF.getNaturalTypeAlignment(SharedsTy));
CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
}
// Emit initial values for private copies (if any).
@@ -2220,7 +2887,7 @@ void CGOpenMPRuntime::emitTaskCall(
FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
LValue SharedsBase;
if (!FirstprivateVars.empty()) {
- SharedsBase = CGF.MakeNaturalAlignAddrLValue(
+ SharedsBase = CGF.MakeAddrLValue(
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
SharedsTy);
@@ -2237,6 +2904,9 @@ void CGOpenMPRuntime::emitTaskCall(
auto *SharedField = CapturesInfo.lookup(OriginalVD);
auto SharedRefLValue =
CGF.EmitLValueForField(SharedsBase, SharedField);
+ SharedRefLValue = CGF.MakeAddrLValue(
+ Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
+ SharedRefLValue.getType(), AlignmentSource::Decl);
QualType Type = OriginalVD->getType();
if (Type->isArrayType()) {
// Initialize firstprivate array.
@@ -2251,10 +2921,10 @@ void CGOpenMPRuntime::emitTaskCall(
CGF.EmitOMPAggregateAssign(
PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type, [&CGF, Elem, Init, &CapturesInfo](
- llvm::Value *DestElement, llvm::Value *SrcElement) {
+ Address DestElement, Address SrcElement) {
// Clean up any temporaries needed by the initialization.
CodeGenFunction::OMPPrivateScope InitScope(CGF);
- InitScope.addPrivate(Elem, [SrcElement]() -> llvm::Value *{
+ InitScope.addPrivate(Elem, [SrcElement]() -> Address {
return SrcElement;
});
(void)InitScope.Privatize();
@@ -2268,7 +2938,7 @@ void CGOpenMPRuntime::emitTaskCall(
}
} else {
CodeGenFunction::OMPPrivateScope InitScope(CGF);
- InitScope.addPrivate(Elem, [SharedRefLValue]() -> llvm::Value *{
+ InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
return SharedRefLValue.getAddress();
});
(void)InitScope.Privatize();
@@ -2298,15 +2968,15 @@ void CGOpenMPRuntime::emitTaskCall(
Destructor);
// Process list of dependences.
- llvm::Value *DependInfo = nullptr;
- unsigned DependencesNumber = Dependences.size();
- if (!Dependences.empty()) {
+ Address DependenciesArray = Address::invalid();
+ unsigned NumDependencies = Dependences.size();
+ if (NumDependencies) {
// Dependence kind for RTL.
- enum RTLDependenceKindTy { DepIn = 1, DepOut = 2, DepInOut = 3 };
+ enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 };
enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
RecordDecl *KmpDependInfoRD;
- QualType FlagsTy = C.getIntTypeForBitwidth(
- C.toBits(C.getTypeSizeInChars(C.BoolTy)), /*Signed=*/false);
+ QualType FlagsTy =
+ C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
if (KmpDependInfoTy.isNull()) {
KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
@@ -2319,25 +2989,37 @@ void CGOpenMPRuntime::emitTaskCall(
} else {
KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
}
+ CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
// Define type kmp_depend_info[<Dependences.size()>];
QualType KmpDependInfoArrayTy = C.getConstantArrayType(
- KmpDependInfoTy, llvm::APInt(/*numBits=*/64, Dependences.size()),
+ KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
ArrayType::Normal, /*IndexTypeQuals=*/0);
// kmp_depend_info[<Dependences.size()>] deps;
- DependInfo = CGF.CreateMemTemp(KmpDependInfoArrayTy);
- for (unsigned i = 0; i < DependencesNumber; ++i) {
- auto Addr = CGF.EmitLValue(Dependences[i].second);
- auto *Size = llvm::ConstantInt::get(
- CGF.SizeTy,
- C.getTypeSizeInChars(Dependences[i].second->getType()).getQuantity());
- auto Base = CGF.MakeNaturalAlignAddrLValue(
- CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, i),
+ DependenciesArray = CGF.CreateMemTemp(KmpDependInfoArrayTy);
+ for (unsigned i = 0; i < NumDependencies; ++i) {
+ const Expr *E = Dependences[i].second;
+ auto Addr = CGF.EmitLValue(E);
+ llvm::Value *Size;
+ QualType Ty = E->getType();
+ if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
+ LValue UpAddrLVal =
+ CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
+ llvm::Value *UpAddr =
+ CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
+ llvm::Value *LowIntPtr =
+ CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
+ llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
+ Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
+ } else
+ Size = getTypeSize(CGF, Ty);
+ auto Base = CGF.MakeAddrLValue(
+ CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize),
KmpDependInfoTy);
// deps[i].base_addr = &<Dependences[i].second>;
auto BaseAddrLVal = CGF.EmitLValueForField(
Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
CGF.EmitStoreOfScalar(
- CGF.Builder.CreatePtrToInt(Addr.getAddress(), CGF.IntPtrTy),
+ CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
BaseAddrLVal);
// deps[i].len = sizeof(<Dependences[i].second>);
auto LenLVal = CGF.EmitLValueForField(
@@ -2349,12 +3031,13 @@ void CGOpenMPRuntime::emitTaskCall(
case OMPC_DEPEND_in:
DepKind = DepIn;
break;
+ // Out and InOut dependencies must use the same code.
case OMPC_DEPEND_out:
- DepKind = DepOut;
- break;
case OMPC_DEPEND_inout:
DepKind = DepInOut;
break;
+ case OMPC_DEPEND_source:
+ case OMPC_DEPEND_sink:
case OMPC_DEPEND_unknown:
llvm_unreachable("Unknown task dependence type");
}
@@ -2363,8 +3046,8 @@ void CGOpenMPRuntime::emitTaskCall(
CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
FlagsLVal);
}
- DependInfo = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, 0),
+ DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()),
CGF.VoidPtrTy);
}
@@ -2378,40 +3061,48 @@ void CGOpenMPRuntime::emitTaskCall(
// list is not empty
auto *ThreadID = getThreadID(CGF, Loc);
auto *UpLoc = emitUpdateLocation(CGF, Loc);
- llvm::Value *TaskArgs[] = {UpLoc, ThreadID, NewTask};
- llvm::Value *DepTaskArgs[] = {
- UpLoc,
- ThreadID,
- NewTask,
- DependInfo ? CGF.Builder.getInt32(DependencesNumber) : nullptr,
- DependInfo,
- DependInfo ? CGF.Builder.getInt32(0) : nullptr,
- DependInfo ? llvm::ConstantPointerNull::get(CGF.VoidPtrTy) : nullptr};
- auto &&ThenCodeGen = [this, DependInfo, &TaskArgs,
- &DepTaskArgs](CodeGenFunction &CGF) {
- // TODO: add check for untied tasks.
- CGF.EmitRuntimeCall(
- createRuntimeFunction(DependInfo ? OMPRTL__kmpc_omp_task_with_deps
- : OMPRTL__kmpc_omp_task),
- DependInfo ? makeArrayRef(DepTaskArgs) : makeArrayRef(TaskArgs));
+ llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
+ llvm::Value *DepTaskArgs[7];
+ if (NumDependencies) {
+ DepTaskArgs[0] = UpLoc;
+ DepTaskArgs[1] = ThreadID;
+ DepTaskArgs[2] = NewTask;
+ DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
+ DepTaskArgs[4] = DependenciesArray.getPointer();
+ DepTaskArgs[5] = CGF.Builder.getInt32(0);
+ DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
+ }
+ auto &&ThenCodeGen = [this, NumDependencies,
+ &TaskArgs, &DepTaskArgs](CodeGenFunction &CGF) {
+ // TODO: add check for untied tasks.
+ if (NumDependencies) {
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps),
+ DepTaskArgs);
+ } else {
+ CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
+ TaskArgs);
+ }
};
typedef CallEndCleanup<std::extent<decltype(TaskArgs)>::value>
IfCallEndCleanup;
- llvm::Value *DepWaitTaskArgs[] = {
- UpLoc,
- ThreadID,
- DependInfo ? CGF.Builder.getInt32(DependencesNumber) : nullptr,
- DependInfo,
- DependInfo ? CGF.Builder.getInt32(0) : nullptr,
- DependInfo ? llvm::ConstantPointerNull::get(CGF.VoidPtrTy) : nullptr};
+
+ llvm::Value *DepWaitTaskArgs[6];
+ if (NumDependencies) {
+ DepWaitTaskArgs[0] = UpLoc;
+ DepWaitTaskArgs[1] = ThreadID;
+ DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
+ DepWaitTaskArgs[3] = DependenciesArray.getPointer();
+ DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
+ DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
+ }
auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
- DependInfo, &DepWaitTaskArgs](CodeGenFunction &CGF) {
+ NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF) {
CodeGenFunction::RunCleanupsScope LocalScope(CGF);
// Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
// kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
// ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
// is specified.
- if (DependInfo)
+ if (NumDependencies)
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
DepWaitTaskArgs);
// Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
@@ -2429,6 +3120,7 @@ void CGOpenMPRuntime::emitTaskCall(
llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs);
};
+
if (IfCond) {
emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
} else {
@@ -2437,8 +3129,89 @@ void CGOpenMPRuntime::emitTaskCall(
}
}
+/// \brief Emit reduction operation for each element of array (required for
+/// array sections) LHS op = RHS.
+/// \param Type Type of array.
+/// \param LHSVar Variable on the left side of the reduction operation
+/// (references element of array in original variable).
+/// \param RHSVar Variable on the right side of the reduction operation
+/// (references element of array in original variable).
+/// \param RedOpGen Generator of reduction operation with use of LHSVar and
+/// RHSVar.
+static void EmitOMPAggregateReduction(
+ CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
+ const VarDecl *RHSVar,
+ const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
+ const Expr *, const Expr *)> &RedOpGen,
+ const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
+ const Expr *UpExpr = nullptr) {
+ // Perform element-by-element initialization.
+ QualType ElementTy;
+ Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
+ Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
+
+ // Drill down to the base element type on both arrays.
+ auto ArrayTy = Type->getAsArrayTypeUnsafe();
+ auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
+
+ auto RHSBegin = RHSAddr.getPointer();
+ auto LHSBegin = LHSAddr.getPointer();
+ // Cast from pointer to array type to pointer to single element.
+ auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
+ // The basic structure here is a while-do loop.
+ auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
+ auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
+ auto IsEmpty =
+ CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
+ CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
+
+ // Enter the loop body, making that address the current address.
+ auto EntryBB = CGF.Builder.GetInsertBlock();
+ CGF.EmitBlock(BodyBB);
+
+ CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
+
+ llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
+ RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
+ RHSElementPHI->addIncoming(RHSBegin, EntryBB);
+ Address RHSElementCurrent =
+ Address(RHSElementPHI,
+ RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
+
+ llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
+ LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
+ LHSElementPHI->addIncoming(LHSBegin, EntryBB);
+ Address LHSElementCurrent =
+ Address(LHSElementPHI,
+ LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
+
+ // Emit copy.
+ CodeGenFunction::OMPPrivateScope Scope(CGF);
+ Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; });
+ Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; });
+ Scope.Privatize();
+ RedOpGen(CGF, XExpr, EExpr, UpExpr);
+ Scope.ForceCleanup();
+
+ // Shift the address forward by one element.
+ auto LHSElementNext = CGF.Builder.CreateConstGEP1_32(
+ LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
+ auto RHSElementNext = CGF.Builder.CreateConstGEP1_32(
+ RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
+ // Check whether we've reached the end.
+ auto Done =
+ CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
+ CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
+ LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
+ RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
+
+ // Done.
+ CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
+}
+
static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
llvm::Type *ArgsType,
+ ArrayRef<const Expr *> Privates,
ArrayRef<const Expr *> LHSExprs,
ArrayRef<const Expr *> RHSExprs,
ArrayRef<const Expr *> ReductionOps) {
@@ -2458,48 +3231,66 @@ static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
".omp.reduction.reduction_func", &CGM.getModule());
- CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn);
+ CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI);
CodeGenFunction CGF(CGM);
CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args);
// Dst = (void*[n])(LHSArg);
// Src = (void*[n])(RHSArg);
- auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg),
- CGF.PointerAlignInBytes),
- ArgsType);
- auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg),
- CGF.PointerAlignInBytes),
- ArgsType);
+ Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
+ ArgsType), CGF.getPointerAlign());
+ Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
+ ArgsType), CGF.getPointerAlign());
// ...
// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
// ...
CodeGenFunction::OMPPrivateScope Scope(CGF);
- for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I) {
- Scope.addPrivate(
- cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()),
- [&]() -> llvm::Value *{
- return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.Builder.CreateAlignedLoad(
- CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, RHS, I),
- CGM.PointerAlignInBytes),
- CGF.ConvertTypeForMem(C.getPointerType(RHSExprs[I]->getType())));
- });
- Scope.addPrivate(
- cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()),
- [&]() -> llvm::Value *{
- return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.Builder.CreateAlignedLoad(
- CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, LHS, I),
- CGM.PointerAlignInBytes),
- CGF.ConvertTypeForMem(C.getPointerType(LHSExprs[I]->getType())));
- });
+ auto IPriv = Privates.begin();
+ unsigned Idx = 0;
+ for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
+ auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
+ Scope.addPrivate(RHSVar, [&]() -> Address {
+ return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
+ });
+ auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
+ Scope.addPrivate(LHSVar, [&]() -> Address {
+ return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
+ });
+ QualType PrivTy = (*IPriv)->getType();
+ if (PrivTy->isArrayType()) {
+ // Get array size and emit VLA type.
+ ++Idx;
+ Address Elem =
+ CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize());
+ llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
+ CodeGenFunction::OpaqueValueMapping OpaqueMap(
+ CGF,
+ cast<OpaqueValueExpr>(
+ CGF.getContext().getAsVariableArrayType(PrivTy)->getSizeExpr()),
+ RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
+ CGF.EmitVariablyModifiedType(PrivTy);
+ }
}
Scope.Privatize();
+ IPriv = Privates.begin();
+ auto ILHS = LHSExprs.begin();
+ auto IRHS = RHSExprs.begin();
for (auto *E : ReductionOps) {
- CGF.EmitIgnoredExpr(E);
+ if ((*IPriv)->getType()->isArrayType()) {
+ // Emit reduction for array section.
+ auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
+ [=](CodeGenFunction &CGF, const Expr *,
+ const Expr *,
+ const Expr *) { CGF.EmitIgnoredExpr(E); });
+ } else
+ // Emit reduction for array subscript or single variable.
+ CGF.EmitIgnoredExpr(E);
+ ++IPriv, ++ILHS, ++IRHS;
}
Scope.ForceCleanup();
CGF.FinishFunction();
@@ -2507,10 +3298,13 @@ static llvm::Value *emitReductionFunction(CodeGenModule &CGM,
}
void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
+ ArrayRef<const Expr *> Privates,
ArrayRef<const Expr *> LHSExprs,
ArrayRef<const Expr *> RHSExprs,
ArrayRef<const Expr *> ReductionOps,
bool WithNowait, bool SimpleReduction) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Next code should be emitted for reduction:
//
// static kmp_critical_name lock = { 0 };
@@ -2550,32 +3344,68 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
if (SimpleReduction) {
CodeGenFunction::RunCleanupsScope Scope(CGF);
+ auto IPriv = Privates.begin();
+ auto ILHS = LHSExprs.begin();
+ auto IRHS = RHSExprs.begin();
for (auto *E : ReductionOps) {
- CGF.EmitIgnoredExpr(E);
+ if ((*IPriv)->getType()->isArrayType()) {
+ auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ EmitOMPAggregateReduction(
+ CGF, (*IPriv)->getType(), LHSVar, RHSVar,
+ [=](CodeGenFunction &CGF, const Expr *, const Expr *,
+ const Expr *) { CGF.EmitIgnoredExpr(E); });
+ } else
+ CGF.EmitIgnoredExpr(E);
+ ++IPriv, ++ILHS, ++IRHS;
}
return;
}
// 1. Build a list of reduction variables.
// void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
- llvm::APInt ArraySize(/*unsigned int numBits=*/32, RHSExprs.size());
+ auto Size = RHSExprs.size();
+ for (auto *E : Privates) {
+ if (E->getType()->isArrayType())
+ // Reserve place for array size.
+ ++Size;
+ }
+ llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
QualType ReductionArrayTy =
C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
/*IndexTypeQuals=*/0);
- auto *ReductionList =
+ Address ReductionList =
CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
- for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I) {
- auto *Elem = CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, ReductionList, I);
- CGF.Builder.CreateAlignedStore(
+ auto IPriv = Privates.begin();
+ unsigned Idx = 0;
+ for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
+ Address Elem =
+ CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize());
+ CGF.Builder.CreateStore(
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- CGF.EmitLValue(RHSExprs[I]).getAddress(), CGF.VoidPtrTy),
- Elem, CGM.PointerAlignInBytes);
+ CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
+ Elem);
+ if ((*IPriv)->getType()->isArrayType()) {
+ // Store array size.
+ ++Idx;
+ Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx,
+ CGF.getPointerSize());
+ CGF.Builder.CreateStore(
+ CGF.Builder.CreateIntToPtr(
+ CGF.Builder.CreateIntCast(
+ CGF.getVLASize(CGF.getContext().getAsVariableArrayType(
+ (*IPriv)->getType()))
+ .first,
+ CGF.SizeTy, /*isSigned=*/false),
+ CGF.VoidPtrTy),
+ Elem);
+ }
}
// 2. Emit reduce_func().
auto *ReductionFn = emitReductionFunction(
- CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), LHSExprs,
- RHSExprs, ReductionOps);
+ CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
+ LHSExprs, RHSExprs, ReductionOps);
// 3. Create static kmp_critical_name lock = { 0 };
auto *Lock = getCriticalRegionLock(".reduction");
@@ -2586,10 +3416,10 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
CGF, Loc,
static_cast<OpenMPLocationFlags>(OMP_IDENT_KMPC | OMP_ATOMIC_REDUCE));
auto *ThreadId = getThreadID(CGF, Loc);
- auto *ReductionArrayTySize = llvm::ConstantInt::get(
- CGM.SizeTy, C.getTypeSizeInChars(ReductionArrayTy).getQuantity());
- auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList,
- CGF.VoidPtrTy);
+ auto *ReductionArrayTySize = getTypeSize(CGF, ReductionArrayTy);
+ auto *RL =
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
+ CGF.VoidPtrTy);
llvm::Value *Args[] = {
IdentTLoc, // ident_t *<loc>
ThreadId, // i32 <gtid>
@@ -2632,8 +3462,22 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
: OMPRTL__kmpc_end_reduce),
llvm::makeArrayRef(EndArgs));
+ auto IPriv = Privates.begin();
+ auto ILHS = LHSExprs.begin();
+ auto IRHS = RHSExprs.begin();
for (auto *E : ReductionOps) {
- CGF.EmitIgnoredExpr(E);
+ if ((*IPriv)->getType()->isArrayType()) {
+ // Emit reduction for array section.
+ auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ EmitOMPAggregateReduction(
+ CGF, (*IPriv)->getType(), LHSVar, RHSVar,
+ [=](CodeGenFunction &CGF, const Expr *, const Expr *,
+ const Expr *) { CGF.EmitIgnoredExpr(E); });
+ } else
+ // Emit reduction for array subscript or single variable.
+ CGF.EmitIgnoredExpr(E);
+ ++IPriv, ++ILHS, ++IRHS;
}
}
@@ -2663,62 +3507,84 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
createRuntimeFunction(OMPRTL__kmpc_end_reduce),
llvm::makeArrayRef(EndArgs));
}
- auto I = LHSExprs.begin();
+ auto ILHS = LHSExprs.begin();
+ auto IRHS = RHSExprs.begin();
+ auto IPriv = Privates.begin();
for (auto *E : ReductionOps) {
- const Expr *XExpr = nullptr;
- const Expr *EExpr = nullptr;
- const Expr *UpExpr = nullptr;
- BinaryOperatorKind BO = BO_Comma;
- if (auto *BO = dyn_cast<BinaryOperator>(E)) {
- if (BO->getOpcode() == BO_Assign) {
- XExpr = BO->getLHS();
- UpExpr = BO->getRHS();
- }
- }
- // Try to emit update expression as a simple atomic.
- auto *RHSExpr = UpExpr;
- if (RHSExpr) {
- // Analyze RHS part of the whole expression.
- if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
- RHSExpr->IgnoreParenImpCasts())) {
- // If this is a conditional operator, analyze its condition for
- // min/max reduction operator.
- RHSExpr = ACO->getCond();
+ const Expr *XExpr = nullptr;
+ const Expr *EExpr = nullptr;
+ const Expr *UpExpr = nullptr;
+ BinaryOperatorKind BO = BO_Comma;
+ if (auto *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->getOpcode() == BO_Assign) {
+ XExpr = BO->getLHS();
+ UpExpr = BO->getRHS();
+ }
}
- if (auto *BORHS =
- dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
- EExpr = BORHS->getRHS();
- BO = BORHS->getOpcode();
+ // Try to emit update expression as a simple atomic.
+ auto *RHSExpr = UpExpr;
+ if (RHSExpr) {
+ // Analyze RHS part of the whole expression.
+ if (auto *ACO = dyn_cast<AbstractConditionalOperator>(
+ RHSExpr->IgnoreParenImpCasts())) {
+ // If this is a conditional operator, analyze its condition for
+ // min/max reduction operator.
+ RHSExpr = ACO->getCond();
+ }
+ if (auto *BORHS =
+ dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
+ EExpr = BORHS->getRHS();
+ BO = BORHS->getOpcode();
+ }
}
- }
- if (XExpr) {
- auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
- LValue X = CGF.EmitLValue(XExpr);
- RValue E;
- if (EExpr)
- E = CGF.EmitAnyExpr(EExpr);
- CGF.EmitOMPAtomicSimpleUpdateExpr(
- X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
- [&CGF, UpExpr, VD](RValue XRValue) {
- CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
- PrivateScope.addPrivate(
- VD, [&CGF, VD, XRValue]() -> llvm::Value *{
- auto *LHSTemp = CGF.CreateMemTemp(VD->getType());
+ if (XExpr) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ auto &&AtomicRedGen = [this, BO, VD, IPriv,
+ Loc](CodeGenFunction &CGF, const Expr *XExpr,
+ const Expr *EExpr, const Expr *UpExpr) {
+ LValue X = CGF.EmitLValue(XExpr);
+ RValue E;
+ if (EExpr)
+ E = CGF.EmitAnyExpr(EExpr);
+ CGF.EmitOMPAtomicSimpleUpdateExpr(
+ X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc,
+ [&CGF, UpExpr, VD, IPriv](RValue XRValue) {
+ CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
+ PrivateScope.addPrivate(VD, [&CGF, VD, XRValue]() -> Address {
+ Address LHSTemp = CGF.CreateMemTemp(VD->getType());
CGF.EmitStoreThroughLValue(
- XRValue,
- CGF.MakeNaturalAlignAddrLValue(LHSTemp, VD->getType()));
+ XRValue, CGF.MakeAddrLValue(LHSTemp, VD->getType()));
return LHSTemp;
});
- (void)PrivateScope.Privatize();
- return CGF.EmitAnyExpr(UpExpr);
- });
- } else {
- // Emit as a critical region.
- emitCriticalRegion(CGF, ".atomic_reduction", [E](CodeGenFunction &CGF) {
- CGF.EmitIgnoredExpr(E);
- }, Loc);
- }
- ++I;
+ (void)PrivateScope.Privatize();
+ return CGF.EmitAnyExpr(UpExpr);
+ });
+ };
+ if ((*IPriv)->getType()->isArrayType()) {
+ // Emit atomic reduction for array section.
+ auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
+ AtomicRedGen, XExpr, EExpr, UpExpr);
+ } else
+ // Emit atomic reduction for array subscript or single variable.
+ AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
+ } else {
+ // Emit as a critical region.
+ auto &&CritRedGen = [this, E, Loc](CodeGenFunction &CGF, const Expr *,
+ const Expr *, const Expr *) {
+ emitCriticalRegion(
+ CGF, ".atomic_reduction",
+ [E](CodeGenFunction &CGF) { CGF.EmitIgnoredExpr(E); }, Loc);
+ };
+ if ((*IPriv)->getType()->isArrayType()) {
+ auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
+ CritRedGen);
+ } else
+ CritRedGen(CGF, nullptr, nullptr, nullptr);
+ }
+ ++ILHS, ++IRHS, ++IPriv;
}
}
@@ -2728,6 +3594,8 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
SourceLocation Loc) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
// global_tid);
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
@@ -2737,8 +3605,11 @@ void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
OpenMPDirectiveKind InnerKind,
- const RegionCodeGenTy &CodeGen) {
- InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind);
+ const RegionCodeGenTy &CodeGen,
+ bool HasCancel) {
+ if (!CGF.HaveInsertPoint())
+ return;
+ InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
}
@@ -2770,13 +3641,15 @@ static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
void CGOpenMPRuntime::emitCancellationPointCall(
CodeGenFunction &CGF, SourceLocation Loc,
OpenMPDirectiveKind CancelRegion) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
// global_tid, kmp_int32 cncl_kind);
if (auto *OMPRegionInfo =
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
- auto CancelDest =
- CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
- if (CancelDest.isValid()) {
+ if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
+ return;
+ if (OMPRegionInfo->hasCancel()) {
llvm::Value *Args[] = {
emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
@@ -2793,8 +3666,10 @@ void CGOpenMPRuntime::emitCancellationPointCall(
CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
CGF.EmitBlock(ExitBB);
// __kmpc_cancel_barrier();
- emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false);
+ emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
// exit from construct;
+ auto CancelDest =
+ CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
CGF.EmitBranchThroughCleanup(CancelDest);
CGF.EmitBlock(ContBB, /*IsFinished=*/true);
}
@@ -2802,14 +3677,18 @@ void CGOpenMPRuntime::emitCancellationPointCall(
}
void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const Expr *IfCond,
OpenMPDirectiveKind CancelRegion) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
// kmp_int32 cncl_kind);
if (auto *OMPRegionInfo =
dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
- auto CancelDest =
- CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
- if (CancelDest.isValid()) {
+ if (OMPRegionInfo->getDirectiveKind() == OMPD_single)
+ return;
+ auto &&ThenGen = [this, Loc, CancelRegion,
+ OMPRegionInfo](CodeGenFunction &CGF) {
llvm::Value *Args[] = {
emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
@@ -2826,11 +3705,554 @@ void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
CGF.EmitBlock(ExitBB);
// __kmpc_cancel_barrier();
- emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false);
+ emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
// exit from construct;
+ auto CancelDest =
+ CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
CGF.EmitBranchThroughCleanup(CancelDest);
CGF.EmitBlock(ContBB, /*IsFinished=*/true);
+ };
+ if (IfCond)
+ emitOMPIfClause(CGF, IfCond, ThenGen, [](CodeGenFunction &) {});
+ else
+ ThenGen(CGF);
+ }
+}
+
+/// \brief Obtain information that uniquely identifies a target entry. This
+/// consists of the file and device IDs as well as line and column numbers
+/// associated with the relevant entry source location.
+static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
+ unsigned &DeviceID, unsigned &FileID,
+ unsigned &LineNum, unsigned &ColumnNum) {
+
+ auto &SM = C.getSourceManager();
+
+ // The loc should be always valid and have a file ID (the user cannot use
+ // #pragma directives in macros)
+
+ assert(Loc.isValid() && "Source location is expected to be always valid.");
+ assert(Loc.isFileID() && "Source location is expected to refer to a file.");
+
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+ assert(PLoc.isValid() && "Source location is expected to be always valid.");
+
+ llvm::sys::fs::UniqueID ID;
+ if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
+ llvm_unreachable("Source file with target region no longer exists!");
+
+ DeviceID = ID.getDevice();
+ FileID = ID.getFile();
+ LineNum = PLoc.getLine();
+ ColumnNum = PLoc.getColumn();
+ return;
+}
+
+void CGOpenMPRuntime::emitTargetOutlinedFunction(
+ const OMPExecutableDirective &D, StringRef ParentName,
+ llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
+ bool IsOffloadEntry) {
+
+ assert(!ParentName.empty() && "Invalid target region parent name!");
+
+ const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
+
+ // Emit target region as a standalone region.
+ auto &&CodeGen = [&CS](CodeGenFunction &CGF) {
+ CGF.EmitStmt(CS.getCapturedStmt());
+ };
+
+ // Create a unique name for the proxy/entry function that using the source
+ // location information of the current target region. The name will be
+ // something like:
+ //
+ // .omp_offloading.DD_FFFF.PP.lBB.cCC
+ //
+ // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
+ // mangled name of the function that encloses the target region, BB is the
+ // line number of the target region, and CC is the column number of the target
+ // region.
+
+ unsigned DeviceID;
+ unsigned FileID;
+ unsigned Line;
+ unsigned Column;
+ getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID,
+ Line, Column);
+ SmallString<64> EntryFnName;
+ {
+ llvm::raw_svector_ostream OS(EntryFnName);
+ OS << ".omp_offloading" << llvm::format(".%x", DeviceID)
+ << llvm::format(".%x.", FileID) << ParentName << ".l" << Line << ".c"
+ << Column;
+ }
+
+ CodeGenFunction CGF(CGM, true);
+ CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
+
+ OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
+
+ // If this target outline function is not an offload entry, we don't need to
+ // register it.
+ if (!IsOffloadEntry)
+ return;
+
+ // The target region ID is used by the runtime library to identify the current
+ // target region, so it only has to be unique and not necessarily point to
+ // anything. It could be the pointer to the outlined function that implements
+ // the target region, but we aren't using that so that the compiler doesn't
+ // need to keep that, and could therefore inline the host function if proven
+ // worthwhile during optimization. In the other hand, if emitting code for the
+ // device, the ID has to be the function address so that it can retrieved from
+ // the offloading entry and launched by the runtime library. We also mark the
+ // outlined function to have external linkage in case we are emitting code for
+ // the device, because these functions will be entry points to the device.
+
+ if (CGM.getLangOpts().OpenMPIsDevice) {
+ OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
+ OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ } else
+ OutlinedFnID = new llvm::GlobalVariable(
+ CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage,
+ llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id");
+
+ // Register the information for the entry associated with this target region.
+ OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
+ DeviceID, FileID, ParentName, Line, Column, OutlinedFn, OutlinedFnID);
+ return;
+}
+
+void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ llvm::Value *OutlinedFn,
+ llvm::Value *OutlinedFnID,
+ const Expr *IfCond, const Expr *Device,
+ ArrayRef<llvm::Value *> CapturedVars) {
+ if (!CGF.HaveInsertPoint())
+ return;
+ /// \brief Values for bit flags used to specify the mapping type for
+ /// offloading.
+ enum OpenMPOffloadMappingFlags {
+ /// \brief Allocate memory on the device and move data from host to device.
+ OMP_MAP_TO = 0x01,
+ /// \brief Allocate memory on the device and move data from device to host.
+ OMP_MAP_FROM = 0x02,
+ /// \brief The element passed to the device is a pointer.
+ OMP_MAP_PTR = 0x20,
+ /// \brief Pass the element to the device by value.
+ OMP_MAP_BYCOPY = 0x80,
+ };
+
+ enum OpenMPOffloadingReservedDeviceIDs {
+ /// \brief Device ID if the device was not defined, runtime should get it
+ /// from environment variables in the spec.
+ OMP_DEVICEID_UNDEF = -1,
+ };
+
+ assert(OutlinedFn && "Invalid outlined function!");
+
+ auto &Ctx = CGF.getContext();
+
+ // Fill up the arrays with the all the captured variables.
+ SmallVector<llvm::Value *, 16> BasePointers;
+ SmallVector<llvm::Value *, 16> Pointers;
+ SmallVector<llvm::Value *, 16> Sizes;
+ SmallVector<unsigned, 16> MapTypes;
+
+ bool hasVLACaptures = false;
+
+ const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt());
+ auto RI = CS.getCapturedRecordDecl()->field_begin();
+ // auto II = CS.capture_init_begin();
+ auto CV = CapturedVars.begin();
+ for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
+ CE = CS.capture_end();
+ CI != CE; ++CI, ++RI, ++CV) {
+ StringRef Name;
+ QualType Ty;
+ llvm::Value *BasePointer;
+ llvm::Value *Pointer;
+ llvm::Value *Size;
+ unsigned MapType;
+
+ // VLA sizes are passed to the outlined region by copy.
+ if (CI->capturesVariableArrayType()) {
+ BasePointer = Pointer = *CV;
+ Size = getTypeSize(CGF, RI->getType());
+ // Copy to the device as an argument. No need to retrieve it.
+ MapType = OMP_MAP_BYCOPY;
+ hasVLACaptures = true;
+ } else if (CI->capturesThis()) {
+ BasePointer = Pointer = *CV;
+ const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr());
+ Size = getTypeSize(CGF, PtrTy->getPointeeType());
+ // Default map type.
+ MapType = OMP_MAP_TO | OMP_MAP_FROM;
+ } else if (CI->capturesVariableByCopy()) {
+ MapType = OMP_MAP_BYCOPY;
+ if (!RI->getType()->isAnyPointerType()) {
+ // If the field is not a pointer, we need to save the actual value and
+ // load it as a void pointer.
+ auto DstAddr = CGF.CreateMemTemp(
+ Ctx.getUIntPtrType(),
+ Twine(CI->getCapturedVar()->getName()) + ".casted");
+ LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
+
+ auto *SrcAddrVal = CGF.EmitScalarConversion(
+ DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
+ Ctx.getPointerType(RI->getType()), SourceLocation());
+ LValue SrcLV =
+ CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType());
+
+ // Store the value using the source type pointer.
+ CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV);
+
+ // Load the value using the destination type pointer.
+ BasePointer = Pointer =
+ CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal();
+ } else {
+ MapType |= OMP_MAP_PTR;
+ BasePointer = Pointer = *CV;
+ }
+ Size = getTypeSize(CGF, RI->getType());
+ } else {
+ assert(CI->capturesVariable() && "Expected captured reference.");
+ BasePointer = Pointer = *CV;
+
+ const ReferenceType *PtrTy =
+ cast<ReferenceType>(RI->getType().getTypePtr());
+ QualType ElementType = PtrTy->getPointeeType();
+ Size = getTypeSize(CGF, ElementType);
+ // The default map type for a scalar/complex type is 'to' because by
+ // default the value doesn't have to be retrieved. For an aggregate type,
+ // the default is 'tofrom'.
+ MapType = ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM)
+ : OMP_MAP_TO;
+ if (ElementType->isAnyPointerType())
+ MapType |= OMP_MAP_PTR;
}
+
+ BasePointers.push_back(BasePointer);
+ Pointers.push_back(Pointer);
+ Sizes.push_back(Size);
+ MapTypes.push_back(MapType);
}
+
+ // Keep track on whether the host function has to be executed.
+ auto OffloadErrorQType =
+ Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true);
+ auto OffloadError = CGF.MakeAddrLValue(
+ CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"),
+ OffloadErrorQType);
+ CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty),
+ OffloadError);
+
+ // Fill up the pointer arrays and transfer execution to the device.
+ auto &&ThenGen = [this, &Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes,
+ hasVLACaptures, Device, OutlinedFnID, OffloadError,
+ OffloadErrorQType](CodeGenFunction &CGF) {
+ unsigned PointerNumVal = BasePointers.size();
+ llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal);
+ llvm::Value *BasePointersArray;
+ llvm::Value *PointersArray;
+ llvm::Value *SizesArray;
+ llvm::Value *MapTypesArray;
+
+ if (PointerNumVal) {
+ llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
+ QualType PointerArrayType = Ctx.getConstantArrayType(
+ Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
+ /*IndexTypeQuals=*/0);
+
+ BasePointersArray =
+ CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
+ PointersArray =
+ CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
+
+ // If we don't have any VLA types, we can use a constant array for the map
+ // sizes, otherwise we need to fill up the arrays as we do for the
+ // pointers.
+ if (hasVLACaptures) {
+ QualType SizeArrayType = Ctx.getConstantArrayType(
+ Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
+ /*IndexTypeQuals=*/0);
+ SizesArray =
+ CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
+ } else {
+ // We expect all the sizes to be constant, so we collect them to create
+ // a constant array.
+ SmallVector<llvm::Constant *, 16> ConstSizes;
+ for (auto S : Sizes)
+ ConstSizes.push_back(cast<llvm::Constant>(S));
+
+ auto *SizesArrayInit = llvm::ConstantArray::get(
+ llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes);
+ auto *SizesArrayGbl = new llvm::GlobalVariable(
+ CGM.getModule(), SizesArrayInit->getType(),
+ /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
+ SizesArrayInit, ".offload_sizes");
+ SizesArrayGbl->setUnnamedAddr(true);
+ SizesArray = SizesArrayGbl;
+ }
+
+ // The map types are always constant so we don't need to generate code to
+ // fill arrays. Instead, we create an array constant.
+ llvm::Constant *MapTypesArrayInit =
+ llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes);
+ auto *MapTypesArrayGbl = new llvm::GlobalVariable(
+ CGM.getModule(), MapTypesArrayInit->getType(),
+ /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
+ MapTypesArrayInit, ".offload_maptypes");
+ MapTypesArrayGbl->setUnnamedAddr(true);
+ MapTypesArray = MapTypesArrayGbl;
+
+ for (unsigned i = 0; i < PointerNumVal; ++i) {
+
+ llvm::Value *BPVal = BasePointers[i];
+ if (BPVal->getType()->isPointerTy())
+ BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy);
+ else {
+ assert(BPVal->getType()->isIntegerTy() &&
+ "If not a pointer, the value type must be an integer.");
+ BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy);
+ }
+ llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
+ llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal),
+ BasePointersArray, 0, i);
+ Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
+ CGF.Builder.CreateStore(BPVal, BPAddr);
+
+ llvm::Value *PVal = Pointers[i];
+ if (PVal->getType()->isPointerTy())
+ PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy);
+ else {
+ assert(PVal->getType()->isIntegerTy() &&
+ "If not a pointer, the value type must be an integer.");
+ PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy);
+ }
+ llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
+ llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
+ 0, i);
+ Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
+ CGF.Builder.CreateStore(PVal, PAddr);
+
+ if (hasVLACaptures) {
+ llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
+ llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
+ /*Idx0=*/0,
+ /*Idx1=*/i);
+ Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
+ CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(
+ Sizes[i], CGM.SizeTy, /*isSigned=*/true),
+ SAddr);
+ }
+ }
+
+ BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
+ llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), BasePointersArray,
+ /*Idx0=*/0, /*Idx1=*/0);
+ PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32(
+ llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray,
+ /*Idx0=*/0,
+ /*Idx1=*/0);
+ SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
+ llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
+ /*Idx0=*/0, /*Idx1=*/0);
+ MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32(
+ llvm::ArrayType::get(CGM.Int32Ty, PointerNumVal), MapTypesArray,
+ /*Idx0=*/0,
+ /*Idx1=*/0);
+
+ } else {
+ BasePointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
+ PointersArray = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
+ SizesArray = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo());
+ MapTypesArray =
+ llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo());
+ }
+
+ // On top of the arrays that were filled up, the target offloading call
+ // takes as arguments the device id as well as the host pointer. The host
+ // pointer is used by the runtime library to identify the current target
+ // region, so it only has to be unique and not necessarily point to
+ // anything. It could be the pointer to the outlined function that
+ // implements the target region, but we aren't using that so that the
+ // compiler doesn't need to keep that, and could therefore inline the host
+ // function if proven worthwhile during optimization.
+
+ // From this point on, we need to have an ID of the target region defined.
+ assert(OutlinedFnID && "Invalid outlined function ID!");
+
+ // Emit device ID if any.
+ llvm::Value *DeviceID;
+ if (Device)
+ DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
+ CGM.Int32Ty, /*isSigned=*/true);
+ else
+ DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
+
+ llvm::Value *OffloadingArgs[] = {
+ DeviceID, OutlinedFnID, PointerNum, BasePointersArray,
+ PointersArray, SizesArray, MapTypesArray};
+ auto Return = CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target),
+ OffloadingArgs);
+
+ CGF.EmitStoreOfScalar(Return, OffloadError);
+ };
+
+ // Notify that the host version must be executed.
+ auto &&ElseGen = [this, OffloadError,
+ OffloadErrorQType](CodeGenFunction &CGF) {
+ CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/-1u),
+ OffloadError);
+ };
+
+ // If we have a target function ID it means that we need to support
+ // offloading, otherwise, just execute on the host. We need to execute on host
+ // regardless of the conditional in the if clause if, e.g., the user do not
+ // specify target triples.
+ if (OutlinedFnID) {
+ if (IfCond) {
+ emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
+ } else {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ ThenGen(CGF);
+ }
+ } else {
+ CodeGenFunction::RunCleanupsScope Scope(CGF);
+ ElseGen(CGF);
+ }
+
+ // Check the error code and execute the host version if required.
+ auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed");
+ auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont");
+ auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation());
+ auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal);
+ CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
+
+ CGF.EmitBlock(OffloadFailedBlock);
+ CGF.Builder.CreateCall(OutlinedFn, BasePointers);
+ CGF.EmitBranch(OffloadContBlock);
+
+ CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
+ return;
+}
+
+void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
+ StringRef ParentName) {
+ if (!S)
+ return;
+
+ // If we find a OMP target directive, codegen the outline function and
+ // register the result.
+ // FIXME: Add other directives with target when they become supported.
+ bool isTargetDirective = isa<OMPTargetDirective>(S);
+
+ if (isTargetDirective) {
+ auto *E = cast<OMPExecutableDirective>(S);
+ unsigned DeviceID;
+ unsigned FileID;
+ unsigned Line;
+ unsigned Column;
+ getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID,
+ FileID, Line, Column);
+
+ // Is this a target region that should not be emitted as an entry point? If
+ // so just signal we are done with this target region.
+ if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(
+ DeviceID, FileID, ParentName, Line, Column))
+ return;
+
+ llvm::Function *Fn;
+ llvm::Constant *Addr;
+ emitTargetOutlinedFunction(*E, ParentName, Fn, Addr,
+ /*isOffloadEntry=*/true);
+ assert(Fn && Addr && "Target region emission failed.");
+ return;
+ }
+
+ if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) {
+ if (!E->getAssociatedStmt())
+ return;
+
+ scanForTargetRegionsFunctions(
+ cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(),
+ ParentName);
+ return;
+ }
+
+ // If this is a lambda function, look into its body.
+ if (auto *L = dyn_cast<LambdaExpr>(S))
+ S = L->getBody();
+
+ // Keep looking for target regions recursively.
+ for (auto *II : S->children())
+ scanForTargetRegionsFunctions(II, ParentName);
+
+ return;
+}
+
+bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
+ auto &FD = *cast<FunctionDecl>(GD.getDecl());
+
+ // If emitting code for the host, we do not process FD here. Instead we do
+ // the normal code generation.
+ if (!CGM.getLangOpts().OpenMPIsDevice)
+ return false;
+
+ // Try to detect target regions in the function.
+ scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
+
+ // We should not emit any function othen that the ones created during the
+ // scanning. Therefore, we signal that this function is completely dealt
+ // with.
+ return true;
+}
+
+bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
+ if (!CGM.getLangOpts().OpenMPIsDevice)
+ return false;
+
+ // Check if there are Ctors/Dtors in this declaration and look for target
+ // regions in it. We use the complete variant to produce the kernel name
+ // mangling.
+ QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
+ if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
+ for (auto *Ctor : RD->ctors()) {
+ StringRef ParentName =
+ CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
+ scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
+ }
+ auto *Dtor = RD->getDestructor();
+ if (Dtor) {
+ StringRef ParentName =
+ CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
+ scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
+ }
+ }
+
+ // If we are in target mode we do not emit any global (declare target is not
+ // implemented yet). Therefore we signal that GD was processed in this case.
+ return true;
}
+bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
+ auto *VD = GD.getDecl();
+ if (isa<FunctionDecl>(VD))
+ return emitTargetFunctions(GD);
+
+ return emitTargetGlobalVariable(GD);
+}
+
+llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
+ // If we have offloading in the current module, we need to emit the entries
+ // now and register the offloading descriptor.
+ createOffloadEntriesAndInfoMetadata();
+
+ // Create and register the offloading binary descriptors. This is the main
+ // entity that captures all the information about offloading in the current
+ // compilation unit.
+ return createOffloadingBinaryDescriptorRegistration();
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
index 44bc8a1..b325637 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -35,11 +35,12 @@ class Value;
namespace clang {
class Expr;
+class GlobalDecl;
class OMPExecutableDirective;
class VarDecl;
namespace CodeGen {
-
+class Address;
class CodeGenFunction;
class CodeGenModule;
@@ -62,6 +63,9 @@ private:
// Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
// kmp_critical_name *crit);
OMPRTL__kmpc_critical,
+ // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
+ // global_tid, kmp_critical_name *crit, uintptr_t hint);
+ OMPRTL__kmpc_critical_with_hint,
// Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
// kmp_critical_name *crit);
OMPRTL__kmpc_end_critical,
@@ -154,6 +158,18 @@ private:
// Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
// kmp_int32 cncl_kind);
OMPRTL__kmpc_cancel,
+
+ //
+ // Offloading related calls
+ //
+ // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t
+ // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t
+ // *arg_types);
+ OMPRTL__tgt_target,
+ // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
+ OMPRTL__tgt_register_lib,
+ // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
+ OMPRTL__tgt_unregister_lib,
};
/// \brief Values for bit flags used in the ident_t to describe the fields.
@@ -184,7 +200,9 @@ private:
/// \brief Map of flags and corresponding default locations.
typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDefaultLocMapTy;
OpenMPDefaultLocMapTy OpenMPDefaultLocMap;
- llvm::Value *getOrCreateDefaultLocation(OpenMPLocationFlags Flags);
+ Address getOrCreateDefaultLocation(OpenMPLocationFlags Flags);
+
+public:
/// \brief Describes ident structure that describes a source location.
/// All descriptions are taken from
/// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
@@ -225,6 +243,7 @@ private:
/// and a pair of line numbers that delimit the construct.
IdentField_PSource
};
+private:
llvm::StructType *IdentTy;
/// \brief Map for SourceLocation and OpenMP runtime library debug locations.
typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDebugLocMapTy;
@@ -274,7 +293,181 @@ private:
/// } flags;
/// } kmp_depend_info_t;
QualType KmpDependInfoTy;
+ /// \brief Type struct __tgt_offload_entry{
+ /// void *addr; // Pointer to the offload entry info.
+ /// // (function or global)
+ /// char *name; // Name of the function or global.
+ /// size_t size; // Size of the entry info (0 if it a function).
+ /// };
+ QualType TgtOffloadEntryQTy;
+ /// struct __tgt_device_image{
+ /// void *ImageStart; // Pointer to the target code start.
+ /// void *ImageEnd; // Pointer to the target code end.
+ /// // We also add the host entries to the device image, as it may be useful
+ /// // for the target runtime to have access to that information.
+ /// __tgt_offload_entry *EntriesBegin; // Begin of the table with all
+ /// // the entries.
+ /// __tgt_offload_entry *EntriesEnd; // End of the table with all the
+ /// // entries (non inclusive).
+ /// };
+ QualType TgtDeviceImageQTy;
+ /// struct __tgt_bin_desc{
+ /// int32_t NumDevices; // Number of devices supported.
+ /// __tgt_device_image *DeviceImages; // Arrays of device images
+ /// // (one per device).
+ /// __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
+ /// // entries.
+ /// __tgt_offload_entry *EntriesEnd; // End of the table with all the
+ /// // entries (non inclusive).
+ /// };
+ QualType TgtBinaryDescriptorQTy;
+ /// \brief Entity that registers the offloading constants that were emitted so
+ /// far.
+ class OffloadEntriesInfoManagerTy {
+ CodeGenModule &CGM;
+
+ /// \brief Number of entries registered so far.
+ unsigned OffloadingEntriesNum;
+
+ public:
+ /// \brief Base class of the entries info.
+ class OffloadEntryInfo {
+ public:
+ /// \brief Kind of a given entry. Currently, only target regions are
+ /// supported.
+ enum OffloadingEntryInfoKinds : unsigned {
+ // Entry is a target region.
+ OFFLOAD_ENTRY_INFO_TARGET_REGION = 0,
+ // Invalid entry info.
+ OFFLOAD_ENTRY_INFO_INVALID = ~0u
+ };
+
+ OffloadEntryInfo() : Order(~0u), Kind(OFFLOAD_ENTRY_INFO_INVALID) {}
+ explicit OffloadEntryInfo(OffloadingEntryInfoKinds Kind, unsigned Order)
+ : Order(Order), Kind(Kind) {}
+
+ bool isValid() const { return Order != ~0u; }
+ unsigned getOrder() const { return Order; }
+ OffloadingEntryInfoKinds getKind() const { return Kind; }
+ static bool classof(const OffloadEntryInfo *Info) { return true; }
+
+ protected:
+ // \brief Order this entry was emitted.
+ unsigned Order;
+
+ OffloadingEntryInfoKinds Kind;
+ };
+
+ /// \brief Return true if a there are no entries defined.
+ bool empty() const;
+ /// \brief Return number of entries defined so far.
+ unsigned size() const { return OffloadingEntriesNum; }
+ OffloadEntriesInfoManagerTy(CodeGenModule &CGM)
+ : CGM(CGM), OffloadingEntriesNum(0) {}
+
+ ///
+ /// Target region entries related.
+ ///
+ /// \brief Target region entries info.
+ class OffloadEntryInfoTargetRegion : public OffloadEntryInfo {
+ // \brief Address of the entity that has to be mapped for offloading.
+ llvm::Constant *Addr;
+ // \brief Address that can be used as the ID of the entry.
+ llvm::Constant *ID;
+
+ public:
+ OffloadEntryInfoTargetRegion()
+ : OffloadEntryInfo(OFFLOAD_ENTRY_INFO_TARGET_REGION, ~0u),
+ Addr(nullptr), ID(nullptr) {}
+ explicit OffloadEntryInfoTargetRegion(unsigned Order,
+ llvm::Constant *Addr,
+ llvm::Constant *ID)
+ : OffloadEntryInfo(OFFLOAD_ENTRY_INFO_TARGET_REGION, Order),
+ Addr(Addr), ID(ID) {}
+
+ llvm::Constant *getAddress() const { return Addr; }
+ llvm::Constant *getID() const { return ID; }
+ void setAddress(llvm::Constant *V) {
+ assert(!Addr && "Address as been set before!");
+ Addr = V;
+ }
+ void setID(llvm::Constant *V) {
+ assert(!ID && "ID as been set before!");
+ ID = V;
+ }
+ static bool classof(const OffloadEntryInfo *Info) {
+ return Info->getKind() == OFFLOAD_ENTRY_INFO_TARGET_REGION;
+ }
+ };
+ /// \brief Initialize target region entry.
+ void initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
+ StringRef ParentName, unsigned LineNum,
+ unsigned ColNum, unsigned Order);
+ /// \brief Register target region entry.
+ void registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
+ StringRef ParentName, unsigned LineNum,
+ unsigned ColNum, llvm::Constant *Addr,
+ llvm::Constant *ID);
+ /// \brief Return true if a target region entry with the provided
+ /// information exists.
+ bool hasTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
+ StringRef ParentName, unsigned LineNum,
+ unsigned ColNum) const;
+ /// brief Applies action \a Action on all registered entries.
+ typedef llvm::function_ref<void(unsigned, unsigned, StringRef, unsigned,
+ unsigned, OffloadEntryInfoTargetRegion &)>
+ OffloadTargetRegionEntryInfoActTy;
+ void actOnTargetRegionEntriesInfo(
+ const OffloadTargetRegionEntryInfoActTy &Action);
+
+ private:
+ // Storage for target region entries kind. The storage is to be indexed by
+ // file ID, device ID, parent function name, lane number, and column number.
+ typedef llvm::DenseMap<unsigned, OffloadEntryInfoTargetRegion>
+ OffloadEntriesTargetRegionPerColumn;
+ typedef llvm::DenseMap<unsigned, OffloadEntriesTargetRegionPerColumn>
+ OffloadEntriesTargetRegionPerLine;
+ typedef llvm::StringMap<OffloadEntriesTargetRegionPerLine>
+ OffloadEntriesTargetRegionPerParentName;
+ typedef llvm::DenseMap<unsigned, OffloadEntriesTargetRegionPerParentName>
+ OffloadEntriesTargetRegionPerFile;
+ typedef llvm::DenseMap<unsigned, OffloadEntriesTargetRegionPerFile>
+ OffloadEntriesTargetRegionPerDevice;
+ typedef OffloadEntriesTargetRegionPerDevice OffloadEntriesTargetRegionTy;
+ OffloadEntriesTargetRegionTy OffloadEntriesTargetRegion;
+ };
+ OffloadEntriesInfoManagerTy OffloadEntriesInfoManager;
+
+ /// \brief Creates and registers offloading binary descriptor for the current
+ /// compilation unit. The function that does the registration is returned.
+ llvm::Function *createOffloadingBinaryDescriptorRegistration();
+
+ /// \brief Creates offloading entry for the provided address \a Addr,
+ /// name \a Name and size \a Size.
+ void createOffloadEntry(llvm::Constant *Addr, StringRef Name, uint64_t Size);
+
+ /// \brief Creates all the offload entries in the current compilation unit
+ /// along with the associated metadata.
+ void createOffloadEntriesAndInfoMetadata();
+
+ /// \brief Loads all the offload entries information from the host IR
+ /// metadata.
+ void loadOffloadInfoMetadata();
+ /// \brief Returns __tgt_offload_entry type.
+ QualType getTgtOffloadEntryQTy();
+
+ /// \brief Returns __tgt_device_image type.
+ QualType getTgtDeviceImageQTy();
+
+ /// \brief Returns __tgt_bin_desc type.
+ QualType getTgtBinaryDescriptorQTy();
+
+ /// \brief Start scanning from statement \a S and and emit all target regions
+ /// found along the way.
+ /// \param S Starting statement.
+ /// \param ParentName Name of the function declaration that is being scanned.
+ void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName);
/// \brief Build type kmp_routine_entry_t (if not built yet).
void emitKmpRoutineEntryT(QualType KmpInt32Ty);
@@ -321,8 +514,7 @@ private:
/// \brief Emits address of the word in a memory where current thread id is
/// stored.
- virtual llvm::Value *emitThreadIDAddress(CodeGenFunction &CGF,
- SourceLocation Loc);
+ virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc);
/// \brief Gets thread id value for the current thread.
///
@@ -346,7 +538,7 @@ private:
/// \param CopyCtor Pointer to a global copy function for \a VD.
/// \param Dtor Pointer to a global destructor function for \a VD.
/// \param Loc Location of threadprivate declaration.
- void emitThreadPrivateVarInit(CodeGenFunction &CGF, llvm::Value *VDAddr,
+ void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr,
llvm::Value *Ctor, llvm::Value *CopyCtor,
llvm::Value *Dtor, SourceLocation Loc);
@@ -396,23 +588,25 @@ public:
/// CapturedStruct.
/// \param OutlinedFn Outlined function to be run in parallel threads. Type of
/// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
- /// \param CapturedStruct A pointer to the record with the references to
+ /// \param CapturedVars A pointer to the record with the references to
/// variables used in \a OutlinedFn function.
/// \param IfCond Condition in the associated 'if' clause, if it was
/// specified, nullptr otherwise.
///
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
llvm::Value *OutlinedFn,
- llvm::Value *CapturedStruct,
+ ArrayRef<llvm::Value *> CapturedVars,
const Expr *IfCond);
/// \brief Emits a critical region.
/// \param CriticalName Name of the critical region.
/// \param CriticalOpGen Generator for the statement associated with the given
/// critical region.
+ /// \param Hint Value of the 'hint' clause (optional).
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName,
const RegionCodeGenTy &CriticalOpGen,
- SourceLocation Loc);
+ SourceLocation Loc,
+ const Expr *Hint = nullptr);
/// \brief Emits a master region.
/// \param MasterOpGen Generator for the statement associated with the given
@@ -447,17 +641,20 @@ public:
/// ordered region.
virtual void emitOrderedRegion(CodeGenFunction &CGF,
const RegionCodeGenTy &OrderedOpGen,
- SourceLocation Loc);
+ SourceLocation Loc, bool IsThreads);
/// \brief Emit an implicit/explicit barrier for OpenMP threads.
/// \param Kind Directive for which this implicit barrier call must be
/// generated. Must be OMPD_barrier for explicit barrier generation.
- /// \param CheckForCancel true if check for possible cancellation must be
- /// performed, false otherwise.
+ /// \param EmitChecks true if need to emit checks for cancellation barriers.
+ /// \param ForceSimpleCall true simple barrier call must be emitted, false if
+ /// runtime class decides which one to emit (simple or with cancellation
+ /// checks).
///
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
OpenMPDirectiveKind Kind,
- bool CheckForCancel = true);
+ bool EmitChecks = true,
+ bool ForceSimpleCall = false);
/// \brief Check if the specified \a ScheduleKind is static non-chunked.
/// This kind of worksharing directive is emitted without outer loop.
@@ -473,6 +670,12 @@ public:
///
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const;
+ virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPScheduleClauseKind SchedKind,
+ unsigned IVSize, bool IVSigned,
+ bool Ordered, llvm::Value *UB,
+ llvm::Value *Chunk = nullptr);
+
/// \brief Call the appropriate runtime routine to initialize it before start
/// of loop.
///
@@ -497,11 +700,12 @@ public:
/// \param Chunk Value of the chunk for the static_chunked scheduled loop.
/// For the default (nullptr) value, the chunk 1 will be used.
///
- virtual void emitForInit(CodeGenFunction &CGF, SourceLocation Loc,
- OpenMPScheduleClauseKind SchedKind, unsigned IVSize,
- bool IVSigned, bool Ordered, llvm::Value *IL,
- llvm::Value *LB, llvm::Value *UB, llvm::Value *ST,
- llvm::Value *Chunk = nullptr);
+ virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc,
+ OpenMPScheduleClauseKind SchedKind,
+ unsigned IVSize, bool IVSigned, bool Ordered,
+ Address IL, Address LB,
+ Address UB, Address ST,
+ llvm::Value *Chunk = nullptr);
/// \brief Call the appropriate runtime routine to notify that we finished
/// iteration of the ordered loop with the dynamic scheduling.
@@ -539,8 +743,8 @@ public:
/// returned.
virtual llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc,
unsigned IVSize, bool IVSigned,
- llvm::Value *IL, llvm::Value *LB,
- llvm::Value *UB, llvm::Value *ST);
+ Address IL, Address LB,
+ Address UB, Address ST);
/// \brief Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
/// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
@@ -562,10 +766,10 @@ public:
/// \param VDAddr Address of the global variable \a VD.
/// \param Loc Location of the reference to threadprivate var.
/// \return Address of the threadprivate variable for the current thread.
- virtual llvm::Value *getAddrOfThreadPrivate(CodeGenFunction &CGF,
- const VarDecl *VD,
- llvm::Value *VDAddr,
- SourceLocation Loc);
+ virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF,
+ const VarDecl *VD,
+ Address VDAddr,
+ SourceLocation Loc);
/// \brief Emit a code for initialization of threadprivate variable. It emits
/// a call to runtime library which adds initial value to the newly created
@@ -576,7 +780,7 @@ public:
/// \param Loc Location of threadprivate declaration.
/// \param PerformInit true if initialization expression is not constant.
virtual llvm::Function *
- emitThreadPrivateVarDefinition(const VarDecl *VD, llvm::Value *VDAddr,
+ emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr,
SourceLocation Loc, bool PerformInit,
CodeGenFunction *CGF = nullptr);
@@ -632,7 +836,7 @@ public:
virtual void emitTaskCall(
CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
- llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds,
+ llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
ArrayRef<const Expr *> PrivateCopies,
ArrayRef<const Expr *> FirstprivateVars,
@@ -645,9 +849,12 @@ public:
/// \param InnermostKind Kind of innermost directive (for simple directives it
/// is a directive itself, for combined - its innermost directive).
/// \param CodeGen Code generation sequence for the \a D directive.
+ /// \param HasCancel true if region has inner cancel directive, false
+ /// otherwise.
virtual void emitInlinedDirective(CodeGenFunction &CGF,
OpenMPDirectiveKind InnermostKind,
- const RegionCodeGenTy &CodeGen);
+ const RegionCodeGenTy &CodeGen,
+ bool HasCancel = false);
/// \brief Emit a code for reduction clause. Next code should be emitted for
/// reduction:
/// \code
@@ -679,6 +886,7 @@ public:
/// }
/// \endcode
///
+ /// \param Privates List of private copies for original reduction arguments.
/// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
/// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
/// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
@@ -686,6 +894,7 @@ public:
/// \param WithNowait true if parent directive has also nowait clause, false
/// otherwise.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
+ ArrayRef<const Expr *> Privates,
ArrayRef<const Expr *> LHSExprs,
ArrayRef<const Expr *> RHSExprs,
ArrayRef<const Expr *> ReductionOps,
@@ -703,10 +912,66 @@ public:
OpenMPDirectiveKind CancelRegion);
/// \brief Emit code for 'cancel' construct.
+ /// \param IfCond Condition in the associated 'if' clause, if it was
+ /// specified, nullptr otherwise.
/// \param CancelRegion Region kind for which the cancel must be emitted.
///
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
+ const Expr *IfCond,
OpenMPDirectiveKind CancelRegion);
+
+ /// \brief Emit outilined function for 'target' directive.
+ /// \param D Directive to emit.
+ /// \param ParentName Name of the function that encloses the target region.
+ /// \param OutlinedFn Outlined function value to be defined by this call.
+ /// \param OutlinedFnID Outlined function ID value to be defined by this call.
+ /// \param IsOffloadEntry True if the outlined function is an offload entry.
+ /// An oulined function may not be an entry if, e.g. the if clause always
+ /// evaluates to false.
+ virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D,
+ StringRef ParentName,
+ llvm::Function *&OutlinedFn,
+ llvm::Constant *&OutlinedFnID,
+ bool IsOffloadEntry);
+
+ /// \brief Emit the target offloading code associated with \a D. The emitted
+ /// code attempts offloading the execution to the device, an the event of
+ /// a failure it executes the host version outlined in \a OutlinedFn.
+ /// \param D Directive to emit.
+ /// \param OutlinedFn Host version of the code to be offloaded.
+ /// \param OutlinedFnID ID of host version of the code to be offloaded.
+ /// \param IfCond Expression evaluated in if clause associated with the target
+ /// directive, or null if no if clause is used.
+ /// \param Device Expression evaluated in device clause associated with the
+ /// target directive, or null if no device clause is used.
+ /// \param CapturedVars Values captured in the current region.
+ virtual void emitTargetCall(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ llvm::Value *OutlinedFn,
+ llvm::Value *OutlinedFnID, const Expr *IfCond,
+ const Expr *Device,
+ ArrayRef<llvm::Value *> CapturedVars);
+
+ /// \brief Emit the target regions enclosed in \a GD function definition or
+ /// the function itself in case it is a valid device function. Returns true if
+ /// \a GD was dealt with successfully.
+ /// \param GD Function to scan.
+ virtual bool emitTargetFunctions(GlobalDecl GD);
+
+ /// \brief Emit the global variable if it is a valid device global variable.
+ /// Returns true if \a GD was dealt with successfully.
+ /// \param GD Variable declaration to emit.
+ virtual bool emitTargetGlobalVariable(GlobalDecl GD);
+
+ /// \brief Emit the global \a GD if it is meaningful for the target. Returns
+ /// if it was emitted succesfully.
+ /// \param GD Global to scan.
+ virtual bool emitTargetGlobal(GlobalDecl GD);
+
+ /// \brief Creates the offloading descriptor in the event any target region
+ /// was emitted in the current module and return the function that registers
+ /// it.
+ virtual llvm::Function *emitRegistrationFunction();
};
} // namespace CodeGen
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index f91eceb..375b59c 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -454,7 +454,7 @@ void CGRecordLowering::accumulateBases() {
// contain only a trailing array member.
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
if (!BaseDecl->isEmpty() &&
- !Context.getASTRecordLayout(BaseDecl).getSize().isZero())
+ !Context.getASTRecordLayout(BaseDecl).getNonVirtualSize().isZero())
Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl),
MemberInfo::Base, getStorageType(BaseDecl), BaseDecl));
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
index 7a0b8a3..cc4fa2e 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmt.cpp
@@ -16,6 +16,7 @@
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/LoopHint.h"
@@ -25,6 +26,8 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/MDBuilder.h"
+
using namespace clang;
using namespace CodeGen;
@@ -138,6 +141,10 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break;
case Stmt::GCCAsmStmtClass: // Intentional fall-through.
case Stmt::MSAsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break;
+ case Stmt::CoroutineBodyStmtClass:
+ case Stmt::CoreturnStmtClass:
+ CGM.ErrorUnsupported(S, "coroutine");
+ break;
case Stmt::CapturedStmtClass: {
const CapturedStmt *CS = cast<CapturedStmt>(S);
EmitCapturedStmt(*CS, CS->getCapturedRegionKind());
@@ -246,6 +253,18 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::OMPCancelDirectiveClass:
EmitOMPCancelDirective(cast<OMPCancelDirective>(*S));
break;
+ case Stmt::OMPTargetDataDirectiveClass:
+ EmitOMPTargetDataDirective(cast<OMPTargetDataDirective>(*S));
+ break;
+ case Stmt::OMPTaskLoopDirectiveClass:
+ EmitOMPTaskLoopDirective(cast<OMPTaskLoopDirective>(*S));
+ break;
+ case Stmt::OMPTaskLoopSimdDirectiveClass:
+ EmitOMPTaskLoopSimdDirective(cast<OMPTaskLoopSimdDirective>(*S));
+ break;
+case Stmt::OMPDistributeDirectiveClass:
+ EmitOMPDistributeDirective(cast<OMPDistributeDirective>(*S));
+ break;
}
}
@@ -272,8 +291,8 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) {
/// EmitCompoundStmt - Emit a compound statement {..} node. If GetLast is true,
/// this captures the expression result of the last sub-statement and returns it
/// (for use by the statement expression extension).
-llvm::Value* CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
- AggValueSlot AggSlot) {
+Address CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
+ AggValueSlot AggSlot) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),S.getLBracLoc(),
"LLVM IR generation of compound statement ('{}')");
@@ -283,7 +302,7 @@ llvm::Value* CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLa
return EmitCompoundStmtWithoutScope(S, GetLast, AggSlot);
}
-llvm::Value*
+Address
CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S,
bool GetLast,
AggValueSlot AggSlot) {
@@ -292,7 +311,7 @@ CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S,
E = S.body_end()-GetLast; I != E; ++I)
EmitStmt(*I);
- llvm::Value *RetAlloca = nullptr;
+ Address RetAlloca = Address::invalid();
if (GetLast) {
// We have to special case labels here. They are statements, but when put
// at the end of a statement expression, they yield the value of their
@@ -337,7 +356,7 @@ void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) {
return;
// Can only simplify empty blocks.
- if (BI != BB->begin())
+ if (BI->getIterator() != BB->begin())
return;
BB->replaceAllUsesWith(BI->getSuccessor(0));
@@ -359,7 +378,7 @@ void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) {
// Place the block after the current block, if possible, or else at
// the end of the function.
if (CurBB && CurBB->getParent())
- CurFn->getBasicBlockList().insertAfter(CurBB, BB);
+ CurFn->getBasicBlockList().insertAfter(CurBB->getIterator(), BB);
else
CurFn->getBasicBlockList().push_back(BB);
Builder.SetInsertPoint(BB);
@@ -386,7 +405,8 @@ void CodeGenFunction::EmitBlockAfterUses(llvm::BasicBlock *block) {
bool inserted = false;
for (llvm::User *u : block->users()) {
if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
- CurFn->getBasicBlockList().insertAfter(insn->getParent(), block);
+ CurFn->getBasicBlockList().insertAfter(insn->getParent()->getIterator(),
+ block);
inserted = true;
break;
}
@@ -590,100 +610,6 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
EmitBlock(ContBlock, true);
}
-void CodeGenFunction::EmitCondBrHints(llvm::LLVMContext &Context,
- llvm::BranchInst *CondBr,
- ArrayRef<const Attr *> Attrs) {
- // Return if there are no hints.
- if (Attrs.empty())
- return;
-
- // Add vectorize and unroll hints to the metadata on the conditional branch.
- //
- // FIXME: Should this really start with a size of 1?
- SmallVector<llvm::Metadata *, 2> Metadata(1);
- for (const auto *Attr : Attrs) {
- const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
-
- // Skip non loop hint attributes
- if (!LH)
- continue;
-
- LoopHintAttr::OptionType Option = LH->getOption();
- LoopHintAttr::LoopHintState State = LH->getState();
- const char *MetadataName;
- switch (Option) {
- case LoopHintAttr::Vectorize:
- case LoopHintAttr::VectorizeWidth:
- MetadataName = "llvm.loop.vectorize.width";
- break;
- case LoopHintAttr::Interleave:
- case LoopHintAttr::InterleaveCount:
- MetadataName = "llvm.loop.interleave.count";
- break;
- case LoopHintAttr::Unroll:
- // With the unroll loop hint, a non-zero value indicates full unrolling.
- MetadataName = State == LoopHintAttr::Disable ? "llvm.loop.unroll.disable"
- : "llvm.loop.unroll.full";
- break;
- case LoopHintAttr::UnrollCount:
- MetadataName = "llvm.loop.unroll.count";
- break;
- }
-
- Expr *ValueExpr = LH->getValue();
- int ValueInt = 1;
- if (ValueExpr) {
- llvm::APSInt ValueAPS =
- ValueExpr->EvaluateKnownConstInt(CGM.getContext());
- ValueInt = static_cast<int>(ValueAPS.getSExtValue());
- }
-
- llvm::Constant *Value;
- llvm::MDString *Name;
- switch (Option) {
- case LoopHintAttr::Vectorize:
- case LoopHintAttr::Interleave:
- if (State != LoopHintAttr::Disable) {
- // FIXME: In the future I will modifiy the behavior of the metadata
- // so we can enable/disable vectorization and interleaving separately.
- Name = llvm::MDString::get(Context, "llvm.loop.vectorize.enable");
- Value = Builder.getTrue();
- break;
- }
- // Vectorization/interleaving is disabled, set width/count to 1.
- ValueInt = 1;
- // Fallthrough.
- case LoopHintAttr::VectorizeWidth:
- case LoopHintAttr::InterleaveCount:
- case LoopHintAttr::UnrollCount:
- Name = llvm::MDString::get(Context, MetadataName);
- Value = llvm::ConstantInt::get(Int32Ty, ValueInt);
- break;
- case LoopHintAttr::Unroll:
- Name = llvm::MDString::get(Context, MetadataName);
- Value = nullptr;
- break;
- }
-
- SmallVector<llvm::Metadata *, 2> OpValues;
- OpValues.push_back(Name);
- if (Value)
- OpValues.push_back(llvm::ConstantAsMetadata::get(Value));
-
- // Set or overwrite metadata indicated by Name.
- Metadata.push_back(llvm::MDNode::get(Context, OpValues));
- }
-
- // FIXME: This condition is never false. Should it be an assert?
- if (!Metadata.empty()) {
- // Add llvm.loop MDNode to CondBr.
- llvm::MDNode *LoopID = llvm::MDNode::get(Context, Metadata);
- LoopID->replaceOperandWith(0, LoopID); // First op points to itself.
-
- CondBr->setMetadata("llvm.loop", LoopID);
- }
-}
-
void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
ArrayRef<const Attr *> WhileAttrs) {
// Emit the header for the loop, which will also become
@@ -691,7 +617,7 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
EmitBlock(LoopHeader.getBlock());
- LoopStack.push(LoopHeader.getBlock(), WhileAttrs);
+ LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), WhileAttrs);
// Create an exit block for when the condition fails, which will
// also become the break target.
@@ -730,7 +656,7 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (ConditionScope.requiresCleanups())
ExitBlock = createBasicBlock("while.exit");
- llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ Builder.CreateCondBr(
BoolCondVal, LoopBody, ExitBlock,
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
@@ -738,9 +664,6 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
}
-
- // Attach metadata to loop body conditional branch.
- EmitCondBrHints(LoopBody->getContext(), CondBr, WhileAttrs);
}
// Emit the loop body. We have to emit this in a cleanup scope
@@ -785,7 +708,7 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
// Emit the body of the loop.
llvm::BasicBlock *LoopBody = createBasicBlock("do.body");
- LoopStack.push(LoopBody, DoAttrs);
+ LoopStack.push(LoopBody, CGM.getContext(), DoAttrs);
EmitBlockWithFallThrough(LoopBody, &S);
{
@@ -815,12 +738,9 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
// As long as the condition is true, iterate the loop.
if (EmitBoolCondBranch) {
uint64_t BackedgeCount = getProfileCount(S.getBody()) - ParentCount;
- llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ Builder.CreateCondBr(
BoolCondVal, LoopBody, LoopExit.getBlock(),
createProfileWeightsForLoop(S.getCond(), BackedgeCount));
-
- // Attach metadata to loop body conditional branch.
- EmitCondBrHints(LoopBody->getContext(), CondBr, DoAttrs);
}
LoopStack.pop();
@@ -851,7 +771,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
llvm::BasicBlock *CondBlock = Continue.getBlock();
EmitBlock(CondBlock);
- LoopStack.push(CondBlock, ForAttrs);
+ LoopStack.push(CondBlock, CGM.getContext(), ForAttrs);
// If the for loop doesn't have an increment we can just use the
// condition as the continue block. Otherwise we'll need to create
@@ -885,13 +805,10 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
// C99 6.8.5p2/p4: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ Builder.CreateCondBr(
BoolCondVal, ForBody, ExitBlock,
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
- // Attach metadata to loop body conditional branch.
- EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);
-
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
@@ -949,7 +866,7 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
EmitBlock(CondBlock);
- LoopStack.push(CondBlock, ForAttrs);
+ LoopStack.push(CondBlock, CGM.getContext(), ForAttrs);
// If there are any cleanups between here and the loop-exit scope,
// create a block to stage a loop exit along.
@@ -963,13 +880,10 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
// The body is executed if the expression, contextually converted
// to bool, is true.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- llvm::BranchInst *CondBr = Builder.CreateCondBr(
+ Builder.CreateCondBr(
BoolCondVal, ForBody, ExitBlock,
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
- // Attach metadata to loop body conditional branch.
- EmitCondBrHints(ForBody->getContext(), CondBr, ForAttrs);
-
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
@@ -1012,10 +926,9 @@ void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
if (RV.isScalar()) {
Builder.CreateStore(RV.getScalarVal(), ReturnValue);
} else if (RV.isAggregate()) {
- EmitAggregateCopy(ReturnValue, RV.getAggregateAddr(), Ty);
+ EmitAggregateCopy(ReturnValue, RV.getAggregateAddress(), Ty);
} else {
- EmitStoreOfComplex(RV.getComplexVal(),
- MakeNaturalAlignAddrLValue(ReturnValue, Ty),
+ EmitStoreOfComplex(RV.getComplexVal(), MakeAddrLValue(ReturnValue, Ty),
/*init*/ true);
}
EmitBranchThroughCleanup(ReturnBlock);
@@ -1056,8 +969,8 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
// If there is an NRVO flag for this variable, set it to 1 into indicate
// that the cleanup code should not destroy the variable.
if (llvm::Value *NRVOFlag = NRVOFlags[S.getNRVOCandidate()])
- Builder.CreateStore(Builder.getTrue(), NRVOFlag);
- } else if (!ReturnValue || (RV && RV->getType()->isVoidType())) {
+ Builder.CreateFlagStore(Builder.getTrue(), NRVOFlag);
+ } else if (!ReturnValue.isValid() || (RV && RV->getType()->isVoidType())) {
// Make sure not to return anything, but evaluate the expression
// for side effects.
if (RV)
@@ -1075,20 +988,17 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
Builder.CreateStore(EmitScalarExpr(RV), ReturnValue);
break;
case TEK_Complex:
- EmitComplexExprIntoLValue(RV,
- MakeNaturalAlignAddrLValue(ReturnValue, RV->getType()),
+ EmitComplexExprIntoLValue(RV, MakeAddrLValue(ReturnValue, RV->getType()),
/*isInit*/ true);
break;
- case TEK_Aggregate: {
- CharUnits Alignment = getContext().getTypeAlignInChars(RV->getType());
- EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue, Alignment,
+ case TEK_Aggregate:
+ EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue,
Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased));
break;
}
- }
}
++NumReturnExprs;
@@ -1624,6 +1534,22 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
EmitBlock(SwitchExit.getBlock(), true);
incrementProfileCounter(&S);
+ // If the switch has a condition wrapped by __builtin_unpredictable,
+ // create metadata that specifies that the switch is unpredictable.
+ // Don't bother if not optimizing because that metadata would not be used.
+ if (CGM.getCodeGenOpts().OptimizationLevel != 0) {
+ if (const CallExpr *Call = dyn_cast<CallExpr>(S.getCond())) {
+ const Decl *TargetDecl = Call->getCalleeDecl();
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
+ if (FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
+ llvm::MDBuilder MDHelper(getLLVMContext());
+ SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
+ MDHelper.createUnpredictable());
+ }
+ }
+ }
+ }
+
if (SwitchWeights) {
assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
"switch weights do not match switch cases");
@@ -1675,9 +1601,7 @@ SimplifyConstraint(const char *Constraint, const TargetInfo &Target,
assert(OutCons &&
"Must pass output names to constraints with a symbolic name");
unsigned Index;
- bool result = Target.resolveSymbolicName(Constraint,
- &(*OutCons)[0],
- OutCons->size(), Index);
+ bool result = Target.resolveSymbolicName(Constraint, *OutCons, Index);
assert(result && "Could not resolve symbolic name"); (void)result;
Result += llvm::utostr(Index);
break;
@@ -1743,12 +1667,12 @@ CodeGenFunction::EmitAsmInputLValue(const TargetInfo::ConstraintInfo &Info,
Arg = Builder.CreateLoad(Builder.CreateBitCast(InputValue.getAddress(),
Ty));
} else {
- Arg = InputValue.getAddress();
+ Arg = InputValue.getPointer();
ConstraintStr += '*';
}
}
} else {
- Arg = InputValue.getAddress();
+ Arg = InputValue.getPointer();
ConstraintStr += '*';
}
@@ -1772,7 +1696,8 @@ llvm::Value* CodeGenFunction::EmitAsmInput(
if (Info.allowsRegister() || !Info.allowsMemory())
if (CodeGenFunction::hasScalarEvaluationKind(InputExpr->getType()))
return EmitScalarExpr(InputExpr);
-
+ if (InputExpr->getStmtClass() == Expr::CXXThisExprClass)
+ return EmitScalarExpr(InputExpr);
InputExpr = InputExpr->IgnoreParenNoopCasts(getContext());
LValue Dest = EmitLValue(InputExpr);
return EmitAsmInputLValue(Info, Dest, InputExpr->getType(), ConstraintStr,
@@ -1793,13 +1718,15 @@ static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str,
if (!StrVal.empty()) {
const SourceManager &SM = CGF.CGM.getContext().getSourceManager();
const LangOptions &LangOpts = CGF.CGM.getLangOpts();
+ unsigned StartToken = 0;
+ unsigned ByteOffset = 0;
// Add the location of the start of each subsequent line of the asm to the
// MDNode.
- for (unsigned i = 0, e = StrVal.size()-1; i != e; ++i) {
+ for (unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
if (StrVal[i] != '\n') continue;
- SourceLocation LineLoc = Str->getLocationOfByte(i+1, SM, LangOpts,
- CGF.getTarget());
+ SourceLocation LineLoc = Str->getLocationOfByte(
+ i + 1, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset);
Locs.push_back(llvm::ConstantAsMetadata::get(
llvm::ConstantInt::get(CGF.Int32Ty, LineLoc.getRawEncoding())));
}
@@ -1832,8 +1759,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
Name = GAS->getInputName(i);
TargetInfo::ConstraintInfo Info(S.getInputConstraint(i), Name);
bool IsValid =
- getTarget().validateInputConstraint(OutputConstraintInfos.data(),
- S.getNumOutputs(), Info);
+ getTarget().validateInputConstraint(OutputConstraintInfos, Info);
assert(IsValid && "Failed to parse input constraint"); (void)IsValid;
InputConstraintInfos.push_back(Info);
}
@@ -1919,8 +1845,8 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
<< OutExpr->getType() << OutputConstraint;
}
} else {
- ArgTypes.push_back(Dest.getAddress()->getType());
- Args.push_back(Dest.getAddress());
+ ArgTypes.push_back(Dest.getAddress().getType());
+ Args.push_back(Dest.getPointer());
Constraints += "=*";
Constraints += OutputConstraint;
ReadOnly = ReadNone = false;
@@ -2077,6 +2003,15 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
Result->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoUnwind);
+ if (isa<MSAsmStmt>(&S)) {
+ // If the assembly contains any labels, mark the call noduplicate to prevent
+ // defining the same ASM label twice (PR23715). This is pretty hacky, but it
+ // works.
+ if (AsmString.find("__MSASMLABEL_") != std::string::npos)
+ Result->addAttribute(llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::NoDuplicate);
+ }
+
// Attach readnone and readonly attributes.
if (!HasSideEffect) {
if (ReadNone)
@@ -2152,12 +2087,12 @@ LValue CodeGenFunction::InitCapturedStruct(const CapturedStmt &S) {
QualType RecordTy = getContext().getRecordType(RD);
// Initialize the captured struct.
- LValue SlotLV = MakeNaturalAlignAddrLValue(
- CreateMemTemp(RecordTy, "agg.captured"), RecordTy);
+ LValue SlotLV =
+ MakeAddrLValue(CreateMemTemp(RecordTy, "agg.captured"), RecordTy);
RecordDecl::field_iterator CurField = RD->field_begin();
- for (CapturedStmt::capture_init_iterator I = S.capture_init_begin(),
- E = S.capture_init_end();
+ for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(),
+ E = S.capture_init_end();
I != E; ++I, ++CurField) {
LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
if (CurField->hasCapturedVLAType()) {
@@ -2184,13 +2119,12 @@ CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K) {
delete CGF.CapturedStmtInfo;
// Emit call to the helper function.
- EmitCallOrInvoke(F, CapStruct.getAddress());
+ EmitCallOrInvoke(F, CapStruct.getPointer());
return F;
}
-llvm::Value *
-CodeGenFunction::GenerateCapturedStmtArgument(const CapturedStmt &S) {
+Address CodeGenFunction::GenerateCapturedStmtArgument(const CapturedStmt &S) {
LValue CapStruct = InitCapturedStruct(S);
return CapStruct.getAddress();
}
@@ -2229,8 +2163,7 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
CD->getLocation(),
CD->getBody()->getLocStart());
// Set the context parameter in CapturedStmtInfo.
- llvm::Value *DeclPtr = LocalDeclMap[CD->getContextParam()];
- assert(DeclPtr && "missing context parameter for CapturedStmt");
+ Address DeclPtr = GetAddrOfLocalVar(CD->getContextParam());
CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr));
// Initialize variable-length arrays.
@@ -2252,7 +2185,7 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
CXXThisValue = EmitLoadOfLValue(ThisLValue, Loc).getScalarVal();
}
- PGO.assignRegionCounters(CD, F);
+ PGO.assignRegionCounters(GlobalDecl(CD), F);
CapturedStmtInfo->EmitBody(*this, CD->getBody());
FinishFunction(CD->getBodyRBrace());
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
index e5f507a..14917c2 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -20,21 +20,195 @@
using namespace clang;
using namespace CodeGen;
+void CodeGenFunction::GenerateOpenMPCapturedVars(
+ const CapturedStmt &S, SmallVectorImpl<llvm::Value *> &CapturedVars) {
+ const RecordDecl *RD = S.getCapturedRecordDecl();
+ auto CurField = RD->field_begin();
+ auto CurCap = S.captures().begin();
+ for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(),
+ E = S.capture_init_end();
+ I != E; ++I, ++CurField, ++CurCap) {
+ if (CurField->hasCapturedVLAType()) {
+ auto VAT = CurField->getCapturedVLAType();
+ auto *Val = VLASizeMap[VAT->getSizeExpr()];
+ CapturedVars.push_back(Val);
+ } else if (CurCap->capturesThis())
+ CapturedVars.push_back(CXXThisValue);
+ else if (CurCap->capturesVariableByCopy())
+ CapturedVars.push_back(
+ EmitLoadOfLValue(EmitLValue(*I), SourceLocation()).getScalarVal());
+ else {
+ assert(CurCap->capturesVariable() && "Expected capture by reference.");
+ CapturedVars.push_back(EmitLValue(*I).getAddress().getPointer());
+ }
+ }
+}
+
+static Address castValueFromUintptr(CodeGenFunction &CGF, QualType DstType,
+ StringRef Name, LValue AddrLV,
+ bool isReferenceType = false) {
+ ASTContext &Ctx = CGF.getContext();
+
+ auto *CastedPtr = CGF.EmitScalarConversion(
+ AddrLV.getAddress().getPointer(), Ctx.getUIntPtrType(),
+ Ctx.getPointerType(DstType), SourceLocation());
+ auto TmpAddr =
+ CGF.MakeNaturalAlignAddrLValue(CastedPtr, Ctx.getPointerType(DstType))
+ .getAddress();
+
+ // If we are dealing with references we need to return the address of the
+ // reference instead of the reference of the value.
+ if (isReferenceType) {
+ QualType RefType = Ctx.getLValueReferenceType(DstType);
+ auto *RefVal = TmpAddr.getPointer();
+ TmpAddr = CGF.CreateMemTemp(RefType, Twine(Name) + ".ref");
+ auto TmpLVal = CGF.MakeAddrLValue(TmpAddr, RefType);
+ CGF.EmitScalarInit(RefVal, TmpLVal);
+ }
+
+ return TmpAddr;
+}
+
+llvm::Function *
+CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
+ assert(
+ CapturedStmtInfo &&
+ "CapturedStmtInfo should be set when generating the captured function");
+ const CapturedDecl *CD = S.getCapturedDecl();
+ const RecordDecl *RD = S.getCapturedRecordDecl();
+ assert(CD->hasBody() && "missing CapturedDecl body");
+
+ // Build the argument list.
+ ASTContext &Ctx = CGM.getContext();
+ FunctionArgList Args;
+ Args.append(CD->param_begin(),
+ std::next(CD->param_begin(), CD->getContextParamPosition()));
+ auto I = S.captures().begin();
+ for (auto *FD : RD->fields()) {
+ QualType ArgType = FD->getType();
+ IdentifierInfo *II = nullptr;
+ VarDecl *CapVar = nullptr;
+
+ // If this is a capture by copy and the type is not a pointer, the outlined
+ // function argument type should be uintptr and the value properly casted to
+ // uintptr. This is necessary given that the runtime library is only able to
+ // deal with pointers. We can pass in the same way the VLA type sizes to the
+ // outlined function.
+ if ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
+ I->capturesVariableArrayType())
+ ArgType = Ctx.getUIntPtrType();
+
+ if (I->capturesVariable() || I->capturesVariableByCopy()) {
+ CapVar = I->getCapturedVar();
+ II = CapVar->getIdentifier();
+ } else if (I->capturesThis())
+ II = &getContext().Idents.get("this");
+ else {
+ assert(I->capturesVariableArrayType());
+ II = &getContext().Idents.get("vla");
+ }
+ if (ArgType->isVariablyModifiedType())
+ ArgType = getContext().getVariableArrayDecayedType(ArgType);
+ Args.push_back(ImplicitParamDecl::Create(getContext(), nullptr,
+ FD->getLocation(), II, ArgType));
+ ++I;
+ }
+ Args.append(
+ std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
+ CD->param_end());
+
+ // Create the function declaration.
+ FunctionType::ExtInfo ExtInfo;
+ const CGFunctionInfo &FuncInfo =
+ CGM.getTypes().arrangeFreeFunctionDeclaration(Ctx.VoidTy, Args, ExtInfo,
+ /*IsVariadic=*/false);
+ llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
+
+ llvm::Function *F = llvm::Function::Create(
+ FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
+ CapturedStmtInfo->getHelperName(), &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
+ if (CD->isNothrow())
+ F->addFnAttr(llvm::Attribute::NoUnwind);
+
+ // Generate the function.
+ StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getLocation(),
+ CD->getBody()->getLocStart());
+ unsigned Cnt = CD->getContextParamPosition();
+ I = S.captures().begin();
+ for (auto *FD : RD->fields()) {
+ // If we are capturing a pointer by copy we don't need to do anything, just
+ // use the value that we get from the arguments.
+ if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
+ setAddrOfLocalVar(I->getCapturedVar(), GetAddrOfLocalVar(Args[Cnt]));
+ ++Cnt, ++I;
+ continue;
+ }
+
+ LValue ArgLVal =
+ MakeAddrLValue(GetAddrOfLocalVar(Args[Cnt]), Args[Cnt]->getType(),
+ AlignmentSource::Decl);
+ if (FD->hasCapturedVLAType()) {
+ LValue CastedArgLVal =
+ MakeAddrLValue(castValueFromUintptr(*this, FD->getType(),
+ Args[Cnt]->getName(), ArgLVal),
+ FD->getType(), AlignmentSource::Decl);
+ auto *ExprArg =
+ EmitLoadOfLValue(CastedArgLVal, SourceLocation()).getScalarVal();
+ auto VAT = FD->getCapturedVLAType();
+ VLASizeMap[VAT->getSizeExpr()] = ExprArg;
+ } else if (I->capturesVariable()) {
+ auto *Var = I->getCapturedVar();
+ QualType VarTy = Var->getType();
+ Address ArgAddr = ArgLVal.getAddress();
+ if (!VarTy->isReferenceType()) {
+ ArgAddr = EmitLoadOfReference(
+ ArgAddr, ArgLVal.getType()->castAs<ReferenceType>());
+ }
+ setAddrOfLocalVar(
+ Var, Address(ArgAddr.getPointer(), getContext().getDeclAlign(Var)));
+ } else if (I->capturesVariableByCopy()) {
+ assert(!FD->getType()->isAnyPointerType() &&
+ "Not expecting a captured pointer.");
+ auto *Var = I->getCapturedVar();
+ QualType VarTy = Var->getType();
+ setAddrOfLocalVar(I->getCapturedVar(),
+ castValueFromUintptr(*this, FD->getType(),
+ Args[Cnt]->getName(), ArgLVal,
+ VarTy->isReferenceType()));
+ } else {
+ // If 'this' is captured, load it into CXXThisValue.
+ assert(I->capturesThis());
+ CXXThisValue =
+ EmitLoadOfLValue(ArgLVal, Args[Cnt]->getLocation()).getScalarVal();
+ }
+ ++Cnt, ++I;
+ }
+
+ PGO.assignRegionCounters(GlobalDecl(CD), F);
+ CapturedStmtInfo->EmitBody(*this, CD->getBody());
+ FinishFunction(CD->getBodyRBrace());
+
+ return F;
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directive Emission
//===----------------------------------------------------------------------===//
void CodeGenFunction::EmitOMPAggregateAssign(
- llvm::Value *DestAddr, llvm::Value *SrcAddr, QualType OriginalType,
- const llvm::function_ref<void(llvm::Value *, llvm::Value *)> &CopyGen) {
+ Address DestAddr, Address SrcAddr, QualType OriginalType,
+ const llvm::function_ref<void(Address, Address)> &CopyGen) {
// Perform element-by-element initialization.
QualType ElementTy;
- auto SrcBegin = SrcAddr;
- auto DestBegin = DestAddr;
+
+ // Drill down to the base element type on both arrays.
auto ArrayTy = OriginalType->getAsArrayTypeUnsafe();
- auto NumElements = emitArrayLength(ArrayTy, ElementTy, DestBegin);
+ auto NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr);
+ SrcAddr = Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
+
+ auto SrcBegin = SrcAddr.getPointer();
+ auto DestBegin = DestAddr.getPointer();
// Cast from pointer to array type to pointer to single element.
- SrcBegin = Builder.CreatePointerBitCastOrAddrSpaceCast(SrcBegin,
- DestBegin->getType());
auto DestEnd = Builder.CreateGEP(DestBegin, NumElements);
// The basic structure here is a while-do loop.
auto BodyBB = createBasicBlock("omp.arraycpy.body");
@@ -46,77 +220,144 @@ void CodeGenFunction::EmitOMPAggregateAssign(
// Enter the loop body, making that address the current address.
auto EntryBB = Builder.GetInsertBlock();
EmitBlock(BodyBB);
- auto SrcElementCurrent =
- Builder.CreatePHI(SrcBegin->getType(), 2, "omp.arraycpy.srcElementPast");
- SrcElementCurrent->addIncoming(SrcBegin, EntryBB);
- auto DestElementCurrent = Builder.CreatePHI(DestBegin->getType(), 2,
- "omp.arraycpy.destElementPast");
- DestElementCurrent->addIncoming(DestBegin, EntryBB);
+
+ CharUnits ElementSize = getContext().getTypeSizeInChars(ElementTy);
+
+ llvm::PHINode *SrcElementPHI =
+ Builder.CreatePHI(SrcBegin->getType(), 2, "omp.arraycpy.srcElementPast");
+ SrcElementPHI->addIncoming(SrcBegin, EntryBB);
+ Address SrcElementCurrent =
+ Address(SrcElementPHI,
+ SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
+
+ llvm::PHINode *DestElementPHI =
+ Builder.CreatePHI(DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
+ DestElementPHI->addIncoming(DestBegin, EntryBB);
+ Address DestElementCurrent =
+ Address(DestElementPHI,
+ DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
// Emit copy.
CopyGen(DestElementCurrent, SrcElementCurrent);
// Shift the address forward by one element.
auto DestElementNext = Builder.CreateConstGEP1_32(
- DestElementCurrent, /*Idx0=*/1, "omp.arraycpy.dest.element");
+ DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
auto SrcElementNext = Builder.CreateConstGEP1_32(
- SrcElementCurrent, /*Idx0=*/1, "omp.arraycpy.src.element");
+ SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
// Check whether we've reached the end.
auto Done =
Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
Builder.CreateCondBr(Done, DoneBB, BodyBB);
- DestElementCurrent->addIncoming(DestElementNext, Builder.GetInsertBlock());
- SrcElementCurrent->addIncoming(SrcElementNext, Builder.GetInsertBlock());
+ DestElementPHI->addIncoming(DestElementNext, Builder.GetInsertBlock());
+ SrcElementPHI->addIncoming(SrcElementNext, Builder.GetInsertBlock());
// Done.
EmitBlock(DoneBB, /*IsFinished=*/true);
}
-void CodeGenFunction::EmitOMPCopy(CodeGenFunction &CGF,
- QualType OriginalType, llvm::Value *DestAddr,
- llvm::Value *SrcAddr, const VarDecl *DestVD,
+/// \brief Emit initialization of arrays of complex types.
+/// \param DestAddr Address of the array.
+/// \param Type Type of array.
+/// \param Init Initial expression of array.
+static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
+ QualType Type, const Expr *Init) {
+ // Perform element-by-element initialization.
+ QualType ElementTy;
+
+ // Drill down to the base element type on both arrays.
+ auto ArrayTy = Type->getAsArrayTypeUnsafe();
+ auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
+ DestAddr =
+ CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
+
+ auto DestBegin = DestAddr.getPointer();
+ // Cast from pointer to array type to pointer to single element.
+ auto DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
+ // The basic structure here is a while-do loop.
+ auto BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
+ auto DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
+ auto IsEmpty =
+ CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
+ CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
+
+ // Enter the loop body, making that address the current address.
+ auto EntryBB = CGF.Builder.GetInsertBlock();
+ CGF.EmitBlock(BodyBB);
+
+ CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
+
+ llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
+ DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
+ DestElementPHI->addIncoming(DestBegin, EntryBB);
+ Address DestElementCurrent =
+ Address(DestElementPHI,
+ DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
+
+ // Emit copy.
+ {
+ CodeGenFunction::RunCleanupsScope InitScope(CGF);
+ CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
+ /*IsInitializer=*/false);
+ }
+
+ // Shift the address forward by one element.
+ auto DestElementNext = CGF.Builder.CreateConstGEP1_32(
+ DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
+ // Check whether we've reached the end.
+ auto Done =
+ CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
+ CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
+ DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
+
+ // Done.
+ CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
+}
+
+void CodeGenFunction::EmitOMPCopy(QualType OriginalType, Address DestAddr,
+ Address SrcAddr, const VarDecl *DestVD,
const VarDecl *SrcVD, const Expr *Copy) {
if (OriginalType->isArrayType()) {
auto *BO = dyn_cast<BinaryOperator>(Copy);
if (BO && BO->getOpcode() == BO_Assign) {
// Perform simple memcpy for simple copying.
- CGF.EmitAggregateAssign(DestAddr, SrcAddr, OriginalType);
+ EmitAggregateAssign(DestAddr, SrcAddr, OriginalType);
} else {
// For arrays with complex element types perform element by element
// copying.
- CGF.EmitOMPAggregateAssign(
+ EmitOMPAggregateAssign(
DestAddr, SrcAddr, OriginalType,
- [&CGF, Copy, SrcVD, DestVD](llvm::Value *DestElement,
- llvm::Value *SrcElement) {
+ [this, Copy, SrcVD, DestVD](Address DestElement, Address SrcElement) {
// Working with the single array element, so have to remap
// destination and source variables to corresponding array
// elements.
- CodeGenFunction::OMPPrivateScope Remap(CGF);
- Remap.addPrivate(DestVD, [DestElement]() -> llvm::Value *{
+ CodeGenFunction::OMPPrivateScope Remap(*this);
+ Remap.addPrivate(DestVD, [DestElement]() -> Address {
return DestElement;
});
Remap.addPrivate(
- SrcVD, [SrcElement]() -> llvm::Value *{ return SrcElement; });
+ SrcVD, [SrcElement]() -> Address { return SrcElement; });
(void)Remap.Privatize();
- CGF.EmitIgnoredExpr(Copy);
+ EmitIgnoredExpr(Copy);
});
}
} else {
// Remap pseudo source variable to private copy.
- CodeGenFunction::OMPPrivateScope Remap(CGF);
- Remap.addPrivate(SrcVD, [SrcAddr]() -> llvm::Value *{ return SrcAddr; });
- Remap.addPrivate(DestVD, [DestAddr]() -> llvm::Value *{ return DestAddr; });
+ CodeGenFunction::OMPPrivateScope Remap(*this);
+ Remap.addPrivate(SrcVD, [SrcAddr]() -> Address { return SrcAddr; });
+ Remap.addPrivate(DestVD, [DestAddr]() -> Address { return DestAddr; });
(void)Remap.Privatize();
// Emit copying of the whole variable.
- CGF.EmitIgnoredExpr(Copy);
+ EmitIgnoredExpr(Copy);
}
}
bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
OMPPrivateScope &PrivateScope) {
+ if (!HaveInsertPoint())
+ return false;
llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
- for (auto &&I = D.getClausesOfKind(OMPC_firstprivate); I; ++I) {
- auto *C = cast<OMPFirstprivateClause>(*I);
+ for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
auto IRef = C->varlist_begin();
auto InitsRef = C->inits().begin();
for (auto IInit : C->private_copies()) {
@@ -131,13 +372,13 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
/*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup(
OrigVD) != nullptr,
(*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
- auto *OriginalAddr = EmitLValue(&DRE).getAddress();
+ Address OriginalAddr = EmitLValue(&DRE).getAddress();
QualType Type = OrigVD->getType();
if (Type->isArrayType()) {
// Emit VarDecl with copy init for arrays.
// Get the address of the original variable captured in current
// captured region.
- IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
+ IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
auto Emission = EmitAutoVarAlloca(*VD);
auto *Init = VD->getInit();
if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) {
@@ -147,12 +388,12 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
} else {
EmitOMPAggregateAssign(
Emission.getAllocatedAddress(), OriginalAddr, Type,
- [this, VDInit, Init](llvm::Value *DestElement,
- llvm::Value *SrcElement) {
+ [this, VDInit, Init](Address DestElement,
+ Address SrcElement) {
// Clean up any temporaries needed by the initialization.
RunCleanupsScope InitScope(*this);
// Emit initialization for single element.
- LocalDeclMap[VDInit] = SrcElement;
+ setAddrOfLocalVar(VDInit, SrcElement);
EmitAnyExprToMem(Init, DestElement,
Init->getType().getQualifiers(),
/*IsInitializer*/ false);
@@ -163,12 +404,12 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
return Emission.getAllocatedAddress();
});
} else {
- IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
+ IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
// Emit private VarDecl with copy init.
// Remap temp VDInit variable to the address of the original
// variable
// (for proper handling of captured global variables).
- LocalDeclMap[VDInit] = OriginalAddr;
+ setAddrOfLocalVar(VDInit, OriginalAddr);
EmitDecl(*VD);
LocalDeclMap.erase(VDInit);
return GetAddrOfLocalVar(VD);
@@ -188,16 +429,17 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
void CodeGenFunction::EmitOMPPrivateClause(
const OMPExecutableDirective &D,
CodeGenFunction::OMPPrivateScope &PrivateScope) {
+ if (!HaveInsertPoint())
+ return;
llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
- for (auto &&I = D.getClausesOfKind(OMPC_private); I; ++I) {
- auto *C = cast<OMPPrivateClause>(*I);
+ for (const auto *C : D.getClausesOfKind<OMPPrivateClause>()) {
auto IRef = C->varlist_begin();
for (auto IInit : C->private_copies()) {
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
auto VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
bool IsRegistered =
- PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
+ PrivateScope.addPrivate(OrigVD, [&]() -> Address {
// Emit private VarDecl with copy init.
EmitDecl(*VD);
return GetAddrOfLocalVar(VD);
@@ -212,14 +454,15 @@ void CodeGenFunction::EmitOMPPrivateClause(
}
bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
+ if (!HaveInsertPoint())
+ return false;
// threadprivate_var1 = master_threadprivate_var1;
// operator=(threadprivate_var2, master_threadprivate_var2);
// ...
// __kmpc_barrier(&loc, global_tid);
llvm::DenseSet<const VarDecl *> CopiedVars;
llvm::BasicBlock *CopyBegin = nullptr, *CopyEnd = nullptr;
- for (auto &&I = D.getClausesOfKind(OMPC_copyin); I; ++I) {
- auto *C = cast<OMPCopyinClause>(*I);
+ for (const auto *C : D.getClausesOfKind<OMPCopyinClause>()) {
auto IRef = C->varlist_begin();
auto ISrcRef = C->source_exprs().begin();
auto IDestRef = C->destination_exprs().begin();
@@ -231,7 +474,7 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
// Get the address of the master variable. If we are emitting code with
// TLS support, the address is passed from the master as field in the
// captured declaration.
- llvm::Value *MasterAddr;
+ Address MasterAddr = Address::invalid();
if (getLangOpts().OpenMPUseTLS &&
getContext().getTargetInfo().isTLSSupported()) {
assert(CapturedStmtInfo->lookup(VD) &&
@@ -239,12 +482,15 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
DeclRefExpr DRE(const_cast<VarDecl *>(VD), true, (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
MasterAddr = EmitLValue(&DRE).getAddress();
+ LocalDeclMap.erase(VD);
} else {
- MasterAddr = VD->isStaticLocal() ? CGM.getStaticLocalDeclAddress(VD)
- : CGM.GetAddrOfGlobal(VD);
+ MasterAddr =
+ Address(VD->isStaticLocal() ? CGM.getStaticLocalDeclAddress(VD)
+ : CGM.GetAddrOfGlobal(VD),
+ getContext().getDeclAlign(VD));
}
// Get the address of the threadprivate variable.
- auto *PrivateAddr = EmitLValue(*IRef).getAddress();
+ Address PrivateAddr = EmitLValue(*IRef).getAddress();
if (CopiedVars.size() == 1) {
// At first check if current thread is a master thread. If it is, no
// need to copy data.
@@ -252,15 +498,14 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
CopyEnd = createBasicBlock("copyin.not.master.end");
Builder.CreateCondBr(
Builder.CreateICmpNE(
- Builder.CreatePtrToInt(MasterAddr, CGM.IntPtrTy),
- Builder.CreatePtrToInt(PrivateAddr, CGM.IntPtrTy)),
+ Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy),
+ Builder.CreatePtrToInt(PrivateAddr.getPointer(), CGM.IntPtrTy)),
CopyBegin, CopyEnd);
EmitBlock(CopyBegin);
}
auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
- EmitOMPCopy(*this, Type, PrivateAddr, MasterAddr, DestVD, SrcVD,
- AssignOp);
+ EmitOMPCopy(Type, PrivateAddr, MasterAddr, DestVD, SrcVD, AssignOp);
}
++IRef;
++ISrcRef;
@@ -277,11 +522,12 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
bool CodeGenFunction::EmitOMPLastprivateClauseInit(
const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope) {
+ if (!HaveInsertPoint())
+ return false;
bool HasAtLeastOneLastprivate = false;
llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
- for (auto &&I = D.getClausesOfKind(OMPC_lastprivate); I; ++I) {
+ for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
HasAtLeastOneLastprivate = true;
- auto *C = cast<OMPLastprivateClause>(*I);
auto IRef = C->varlist_begin();
auto IDestRef = C->destination_exprs().begin();
for (auto *IInit : C->private_copies()) {
@@ -290,7 +536,7 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit(
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
- PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() -> llvm::Value *{
+ PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() -> Address {
DeclRefExpr DRE(
const_cast<VarDecl *>(OrigVD),
/*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup(
@@ -304,7 +550,7 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit(
if (IInit) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
bool IsRegistered =
- PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
+ PrivateScope.addPrivate(OrigVD, [&]() -> Address {
// Emit private VarDecl with copy init.
EmitDecl(*VD);
return GetAddrOfLocalVar(VD);
@@ -322,6 +568,8 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit(
void CodeGenFunction::EmitOMPLastprivateClauseFinal(
const OMPExecutableDirective &D, llvm::Value *IsLastIterCond) {
+ if (!HaveInsertPoint())
+ return;
// Emit following code:
// if (<IsLastIterCond>) {
// orig_var1 = private_orig_var1;
@@ -359,8 +607,7 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal(
{
llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
bool FirstLCV = true;
- for (auto &&I = D.getClausesOfKind(OMPC_lastprivate); I; ++I) {
- auto *C = cast<OMPLastprivateClause>(*I);
+ for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
auto IRef = C->varlist_begin();
auto ISrcRef = C->source_exprs().begin();
auto IDestRef = C->destination_exprs().begin();
@@ -385,11 +632,14 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal(
auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
// Get the address of the original variable.
- auto *OriginalAddr = GetAddrOfLocalVar(DestVD);
+ Address OriginalAddr = GetAddrOfLocalVar(DestVD);
// Get the address of the private variable.
- auto *PrivateAddr = GetAddrOfLocalVar(PrivateVD);
- EmitOMPCopy(*this, Type, OriginalAddr, PrivateAddr, DestVD, SrcVD,
- AssignOp);
+ Address PrivateAddr = GetAddrOfLocalVar(PrivateVD);
+ if (auto RefTy = PrivateVD->getType()->getAs<ReferenceType>())
+ PrivateAddr =
+ Address(Builder.CreateLoad(PrivateAddr),
+ getNaturalTypeAlignment(RefTy->getPointeeType()));
+ EmitOMPCopy(Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
}
++IRef;
++ISrcRef;
@@ -405,46 +655,174 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal(
void CodeGenFunction::EmitOMPReductionClauseInit(
const OMPExecutableDirective &D,
CodeGenFunction::OMPPrivateScope &PrivateScope) {
- for (auto &&I = D.getClausesOfKind(OMPC_reduction); I; ++I) {
- auto *C = cast<OMPReductionClause>(*I);
+ if (!HaveInsertPoint())
+ return;
+ for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
auto ILHS = C->lhs_exprs().begin();
auto IRHS = C->rhs_exprs().begin();
+ auto IPriv = C->privates().begin();
for (auto IRef : C->varlists()) {
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
- auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
- // Store the address of the original variable associated with the LHS
- // implicit variable.
- PrivateScope.addPrivate(LHSVD, [this, OrigVD, IRef]() -> llvm::Value *{
- DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
- CapturedStmtInfo->lookup(OrigVD) != nullptr,
- IRef->getType(), VK_LValue, IRef->getExprLoc());
- return EmitLValue(&DRE).getAddress();
- });
- // Emit reduction copy.
- bool IsRegistered =
- PrivateScope.addPrivate(OrigVD, [this, PrivateVD]() -> llvm::Value *{
- // Emit private VarDecl with reduction init.
- EmitDecl(*PrivateVD);
- return GetAddrOfLocalVar(PrivateVD);
- });
- assert(IsRegistered && "private var already registered as private");
- // Silence the warning about unused variable.
- (void)IsRegistered;
- ++ILHS, ++IRHS;
+ auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());
+ if (auto *OASE = dyn_cast<OMPArraySectionExpr>(IRef)) {
+ auto *Base = OASE->getBase()->IgnoreParenImpCasts();
+ while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
+ Base = TempOASE->getBase()->IgnoreParenImpCasts();
+ while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+ Base = TempASE->getBase()->IgnoreParenImpCasts();
+ auto *DE = cast<DeclRefExpr>(Base);
+ auto *OrigVD = cast<VarDecl>(DE->getDecl());
+ auto OASELValueLB = EmitOMPArraySectionExpr(OASE);
+ auto OASELValueUB =
+ EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
+ auto OriginalBaseLValue = EmitLValue(DE);
+ auto BaseLValue = OriginalBaseLValue;
+ auto *Zero = Builder.getInt64(/*C=*/0);
+ llvm::SmallVector<llvm::Value *, 4> Indexes;
+ Indexes.push_back(Zero);
+ auto *ItemTy =
+ OASELValueLB.getPointer()->getType()->getPointerElementType();
+ auto *Ty = BaseLValue.getPointer()->getType()->getPointerElementType();
+ while (Ty != ItemTy) {
+ Indexes.push_back(Zero);
+ Ty = Ty->getPointerElementType();
+ }
+ BaseLValue = MakeAddrLValue(
+ Address(Builder.CreateInBoundsGEP(BaseLValue.getPointer(), Indexes),
+ OASELValueLB.getAlignment()),
+ OASELValueLB.getType(), OASELValueLB.getAlignmentSource());
+ // Store the address of the original variable associated with the LHS
+ // implicit variable.
+ PrivateScope.addPrivate(LHSVD, [this, OASELValueLB]() -> Address {
+ return OASELValueLB.getAddress();
+ });
+ // Emit reduction copy.
+ bool IsRegistered = PrivateScope.addPrivate(
+ OrigVD, [this, PrivateVD, BaseLValue, OASELValueLB, OASELValueUB,
+ OriginalBaseLValue]() -> Address {
+ // Emit VarDecl with copy init for arrays.
+ // Get the address of the original variable captured in current
+ // captured region.
+ auto *Size = Builder.CreatePtrDiff(OASELValueUB.getPointer(),
+ OASELValueLB.getPointer());
+ Size = Builder.CreateNUWAdd(
+ Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
+ CodeGenFunction::OpaqueValueMapping OpaqueMap(
+ *this, cast<OpaqueValueExpr>(
+ getContext()
+ .getAsVariableArrayType(PrivateVD->getType())
+ ->getSizeExpr()),
+ RValue::get(Size));
+ EmitVariablyModifiedType(PrivateVD->getType());
+ auto Emission = EmitAutoVarAlloca(*PrivateVD);
+ auto Addr = Emission.getAllocatedAddress();
+ auto *Init = PrivateVD->getInit();
+ EmitOMPAggregateInit(*this, Addr, PrivateVD->getType(), Init);
+ EmitAutoVarCleanups(Emission);
+ // Emit private VarDecl with reduction init.
+ auto *Offset = Builder.CreatePtrDiff(BaseLValue.getPointer(),
+ OASELValueLB.getPointer());
+ auto *Ptr = Builder.CreateGEP(Addr.getPointer(), Offset);
+ Ptr = Builder.CreatePointerBitCastOrAddrSpaceCast(
+ Ptr, OriginalBaseLValue.getPointer()->getType());
+ return Address(Ptr, OriginalBaseLValue.getAlignment());
+ });
+ assert(IsRegistered && "private var already registered as private");
+ // Silence the warning about unused variable.
+ (void)IsRegistered;
+ PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address {
+ return GetAddrOfLocalVar(PrivateVD);
+ });
+ } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(IRef)) {
+ auto *Base = ASE->getBase()->IgnoreParenImpCasts();
+ while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+ Base = TempASE->getBase()->IgnoreParenImpCasts();
+ auto *DE = cast<DeclRefExpr>(Base);
+ auto *OrigVD = cast<VarDecl>(DE->getDecl());
+ auto ASELValue = EmitLValue(ASE);
+ auto OriginalBaseLValue = EmitLValue(DE);
+ auto BaseLValue = OriginalBaseLValue;
+ auto *Zero = Builder.getInt64(/*C=*/0);
+ llvm::SmallVector<llvm::Value *, 4> Indexes;
+ Indexes.push_back(Zero);
+ auto *ItemTy =
+ ASELValue.getPointer()->getType()->getPointerElementType();
+ auto *Ty = BaseLValue.getPointer()->getType()->getPointerElementType();
+ while (Ty != ItemTy) {
+ Indexes.push_back(Zero);
+ Ty = Ty->getPointerElementType();
+ }
+ BaseLValue = MakeAddrLValue(
+ Address(Builder.CreateInBoundsGEP(BaseLValue.getPointer(), Indexes),
+ ASELValue.getAlignment()),
+ ASELValue.getType(), ASELValue.getAlignmentSource());
+ // Store the address of the original variable associated with the LHS
+ // implicit variable.
+ PrivateScope.addPrivate(LHSVD, [this, ASELValue]() -> Address {
+ return ASELValue.getAddress();
+ });
+ // Emit reduction copy.
+ bool IsRegistered = PrivateScope.addPrivate(
+ OrigVD, [this, PrivateVD, BaseLValue, ASELValue,
+ OriginalBaseLValue]() -> Address {
+ // Emit private VarDecl with reduction init.
+ EmitDecl(*PrivateVD);
+ auto Addr = GetAddrOfLocalVar(PrivateVD);
+ auto *Offset = Builder.CreatePtrDiff(BaseLValue.getPointer(),
+ ASELValue.getPointer());
+ auto *Ptr = Builder.CreateGEP(Addr.getPointer(), Offset);
+ Ptr = Builder.CreatePointerBitCastOrAddrSpaceCast(
+ Ptr, OriginalBaseLValue.getPointer()->getType());
+ return Address(Ptr, OriginalBaseLValue.getAlignment());
+ });
+ assert(IsRegistered && "private var already registered as private");
+ // Silence the warning about unused variable.
+ (void)IsRegistered;
+ PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address {
+ return GetAddrOfLocalVar(PrivateVD);
+ });
+ } else {
+ auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
+ // Store the address of the original variable associated with the LHS
+ // implicit variable.
+ PrivateScope.addPrivate(LHSVD, [this, OrigVD, IRef]() -> Address {
+ DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
+ CapturedStmtInfo->lookup(OrigVD) != nullptr,
+ IRef->getType(), VK_LValue, IRef->getExprLoc());
+ return EmitLValue(&DRE).getAddress();
+ });
+ // Emit reduction copy.
+ bool IsRegistered =
+ PrivateScope.addPrivate(OrigVD, [this, PrivateVD]() -> Address {
+ // Emit private VarDecl with reduction init.
+ EmitDecl(*PrivateVD);
+ return GetAddrOfLocalVar(PrivateVD);
+ });
+ assert(IsRegistered && "private var already registered as private");
+ // Silence the warning about unused variable.
+ (void)IsRegistered;
+ PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address {
+ return GetAddrOfLocalVar(PrivateVD);
+ });
+ }
+ ++ILHS, ++IRHS, ++IPriv;
}
}
}
void CodeGenFunction::EmitOMPReductionClauseFinal(
const OMPExecutableDirective &D) {
+ if (!HaveInsertPoint())
+ return;
+ llvm::SmallVector<const Expr *, 8> Privates;
llvm::SmallVector<const Expr *, 8> LHSExprs;
llvm::SmallVector<const Expr *, 8> RHSExprs;
llvm::SmallVector<const Expr *, 8> ReductionOps;
bool HasAtLeastOneReduction = false;
- for (auto &&I = D.getClausesOfKind(OMPC_reduction); I; ++I) {
+ for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
HasAtLeastOneReduction = true;
- auto *C = cast<OMPReductionClause>(*I);
+ Privates.append(C->privates().begin(), C->privates().end());
LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
@@ -453,8 +831,8 @@ void CodeGenFunction::EmitOMPReductionClauseFinal(
// Emit nowait reduction if nowait clause is present or directive is a
// parallel directive (it always has implicit barrier).
CGM.getOpenMPRuntime().emitReduction(
- *this, D.getLocEnd(), LHSExprs, RHSExprs, ReductionOps,
- D.getSingleClause(OMPC_nowait) ||
+ *this, D.getLocEnd(), Privates, LHSExprs, RHSExprs, ReductionOps,
+ D.getSingleClause<OMPNowaitClause>() ||
isOpenMPParallelDirective(D.getDirectiveKind()) ||
D.getDirectiveKind() == OMPD_simd,
D.getDirectiveKind() == OMPD_simd);
@@ -466,29 +844,32 @@ static void emitCommonOMPParallelDirective(CodeGenFunction &CGF,
OpenMPDirectiveKind InnermostKind,
const RegionCodeGenTy &CodeGen) {
auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
- auto CapturedStruct = CGF.GenerateCapturedStmtArgument(*CS);
+ llvm::SmallVector<llvm::Value *, 16> CapturedVars;
+ CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction(
S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
- if (auto C = S.getSingleClause(OMPC_num_threads)) {
+ if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) {
CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
- auto NumThreadsClause = cast<OMPNumThreadsClause>(C);
auto NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
/*IgnoreResultAssign*/ true);
CGF.CGM.getOpenMPRuntime().emitNumThreadsClause(
CGF, NumThreads, NumThreadsClause->getLocStart());
}
- if (auto *C = S.getSingleClause(OMPC_proc_bind)) {
+ if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
- auto *ProcBindClause = cast<OMPProcBindClause>(C);
CGF.CGM.getOpenMPRuntime().emitProcBindClause(
CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getLocStart());
}
const Expr *IfCond = nullptr;
- if (auto C = S.getSingleClause(OMPC_if)) {
- IfCond = cast<OMPIfClause>(C)->getCondition();
+ for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
+ if (C->getNameModifier() == OMPD_unknown ||
+ C->getNameModifier() == OMPD_parallel) {
+ IfCond = C->getCondition();
+ break;
+ }
}
CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getLocStart(), OutlinedFn,
- CapturedStruct, IfCond);
+ CapturedVars, IfCond);
}
void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
@@ -503,17 +884,15 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
// initialization of firstprivate variables or propagation master's thread
// values of threadprivate variables to local instances of that variables
// of all other implicit threads.
- CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
- OMPD_unknown);
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(
+ CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
+ /*ForceSimpleCall=*/true);
}
CGF.EmitOMPPrivateClause(S, PrivateScope);
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
(void)PrivateScope.Privatize();
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
CGF.EmitOMPReductionClauseFinal(S);
- // Emit implicit barrier at the end of the 'parallel' directive.
- CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
- OMPD_unknown);
};
emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen);
}
@@ -526,8 +905,7 @@ void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
EmitIgnoredExpr(I);
}
// Update the linear variables.
- for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {
- auto *C = cast<OMPLinearClause>(*I);
+ for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
for (auto U : C->updates()) {
EmitIgnoredExpr(U);
}
@@ -595,9 +973,10 @@ void CodeGenFunction::EmitOMPInnerLoop(
}
void CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
+ if (!HaveInsertPoint())
+ return;
// Emit inits for the linear variables.
- for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {
- auto *C = cast<OMPLinearClause>(*I);
+ for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
for (auto Init : C->inits()) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
auto *OrigVD = cast<VarDecl>(
@@ -608,8 +987,7 @@ void CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
VD->getInit()->getExprLoc());
AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
EmitExprAsInit(&DRE, VD,
- MakeAddrLValue(Emission.getAllocatedAddress(),
- VD->getType(), Emission.Alignment),
+ MakeAddrLValue(Emission.getAllocatedAddress(), VD->getType()),
/*capturedByInit=*/false);
EmitAutoVarCleanups(Emission);
}
@@ -626,19 +1004,20 @@ void CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
static void emitLinearClauseFinal(CodeGenFunction &CGF,
const OMPLoopDirective &D) {
+ if (!CGF.HaveInsertPoint())
+ return;
// Emit the final values of the linear variables.
- for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {
- auto *C = cast<OMPLinearClause>(*I);
+ for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
auto IC = C->varlist_begin();
for (auto F : C->finals()) {
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr,
(*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
- auto *OrigAddr = CGF.EmitLValue(&DRE).getAddress();
+ Address OrigAddr = CGF.EmitLValue(&DRE).getAddress();
CodeGenFunction::OMPPrivateScope VarScope(CGF);
VarScope.addPrivate(OrigVD,
- [OrigAddr]() -> llvm::Value *{ return OrigAddr; });
+ [OrigAddr]() -> Address { return OrigAddr; });
(void)VarScope.Privatize();
CGF.EmitIgnoredExpr(F);
++IC;
@@ -648,8 +1027,9 @@ static void emitLinearClauseFinal(CodeGenFunction &CGF,
static void emitAlignedClause(CodeGenFunction &CGF,
const OMPExecutableDirective &D) {
- for (auto &&I = D.getClausesOfKind(OMPC_aligned); I; ++I) {
- auto *Clause = cast<OMPAlignedClause>(*I);
+ if (!CGF.HaveInsertPoint())
+ return;
+ for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) {
unsigned ClauseAlignment = 0;
if (auto AlignmentExpr = Clause->getAlignment()) {
auto AlignmentCI =
@@ -680,24 +1060,36 @@ static void emitAlignedClause(CodeGenFunction &CGF,
static void emitPrivateLoopCounters(CodeGenFunction &CGF,
CodeGenFunction::OMPPrivateScope &LoopScope,
- ArrayRef<Expr *> Counters) {
+ ArrayRef<Expr *> Counters,
+ ArrayRef<Expr *> PrivateCounters) {
+ if (!CGF.HaveInsertPoint())
+ return;
+ auto I = PrivateCounters.begin();
for (auto *E : Counters) {
- auto VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- (void)LoopScope.addPrivate(VD, [&]() -> llvm::Value *{
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
+ Address Addr = Address::invalid();
+ (void)LoopScope.addPrivate(PrivateVD, [&]() -> Address {
// Emit var without initialization.
- auto VarEmission = CGF.EmitAutoVarAlloca(*VD);
+ auto VarEmission = CGF.EmitAutoVarAlloca(*PrivateVD);
CGF.EmitAutoVarCleanups(VarEmission);
- return VarEmission.getAllocatedAddress();
+ Addr = VarEmission.getAllocatedAddress();
+ return Addr;
});
+ (void)LoopScope.addPrivate(VD, [&]() -> Address { return Addr; });
+ ++I;
}
}
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S,
const Expr *Cond, llvm::BasicBlock *TrueBlock,
llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
+ if (!CGF.HaveInsertPoint())
+ return;
{
CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
- emitPrivateLoopCounters(CGF, PreCondScope, S.counters());
+ emitPrivateLoopCounters(CGF, PreCondScope, S.counters(),
+ S.private_counters());
(void)PreCondScope.Privatize();
// Get initial values of real counters.
for (auto I : S.inits()) {
@@ -711,31 +1103,47 @@ static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S,
static void
emitPrivateLinearVars(CodeGenFunction &CGF, const OMPExecutableDirective &D,
CodeGenFunction::OMPPrivateScope &PrivateScope) {
- for (auto &&I = D.getClausesOfKind(OMPC_linear); I; ++I) {
- auto *C = cast<OMPLinearClause>(*I);
+ if (!CGF.HaveInsertPoint())
+ return;
+ for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
+ auto CurPrivate = C->privates().begin();
for (auto *E : C->varlists()) {
- auto VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- bool IsRegistered = PrivateScope.addPrivate(VD, [&]()->llvm::Value * {
- // Emit var without initialization.
- auto VarEmission = CGF.EmitAutoVarAlloca(*VD);
- CGF.EmitAutoVarCleanups(VarEmission);
- return VarEmission.getAllocatedAddress();
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ auto *PrivateVD =
+ cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl());
+ bool IsRegistered = PrivateScope.addPrivate(VD, [&]() -> Address {
+ // Emit private VarDecl with copy init.
+ CGF.EmitVarDecl(*PrivateVD);
+ return CGF.GetAddrOfLocalVar(PrivateVD);
});
assert(IsRegistered && "linear var already registered as private");
// Silence the warning about unused variable.
(void)IsRegistered;
+ ++CurPrivate;
}
}
}
-static void emitSafelenClause(CodeGenFunction &CGF,
- const OMPExecutableDirective &D) {
- if (auto *C =
- cast_or_null<OMPSafelenClause>(D.getSingleClause(OMPC_safelen))) {
+static void emitSimdlenSafelenClause(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ bool IsMonotonic) {
+ if (!CGF.HaveInsertPoint())
+ return;
+ if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) {
+ RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),
+ /*ignoreResult=*/true);
+ llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
+ CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
+ // In presence of finite 'safelen', it may be unsafe to mark all
+ // the memory instructions parallel, because loop-carried
+ // dependences of 'safelen' iterations are possible.
+ if (!IsMonotonic)
+ CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>());
+ } else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) {
RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
/*ignoreResult=*/true);
llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
- CGF.LoopStack.setVectorizerWidth(Val->getZExtValue());
+ CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
// In presence of finite 'safelen', it may be unsafe to mark all
// the memory instructions parallel, because loop-carried
// dependences of 'safelen' iterations are possible.
@@ -743,25 +1151,28 @@ static void emitSafelenClause(CodeGenFunction &CGF,
}
}
-void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D) {
+void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D,
+ bool IsMonotonic) {
// Walk clauses and process safelen/lastprivate.
- LoopStack.setParallel();
- LoopStack.setVectorizerEnable(true);
- emitSafelenClause(*this, D);
+ LoopStack.setParallel(!IsMonotonic);
+ LoopStack.setVectorizeEnable(true);
+ emitSimdlenSafelenClause(*this, D, IsMonotonic);
}
void CodeGenFunction::EmitOMPSimdFinal(const OMPLoopDirective &D) {
+ if (!HaveInsertPoint())
+ return;
auto IC = D.counters().begin();
for (auto F : D.finals()) {
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
- if (LocalDeclMap.lookup(OrigVD) || CapturedStmtInfo->lookup(OrigVD)) {
+ if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD)) {
DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
CapturedStmtInfo->lookup(OrigVD) != nullptr,
(*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
- auto *OrigAddr = EmitLValue(&DRE).getAddress();
+ Address OrigAddr = EmitLValue(&DRE).getAddress();
OMPPrivateScope VarScope(*this);
VarScope.addPrivate(OrigVD,
- [OrigAddr]() -> llvm::Value *{ return OrigAddr; });
+ [OrigAddr]() -> Address { return OrigAddr; });
(void)VarScope.Privatize();
EmitIgnoredExpr(F);
}
@@ -817,7 +1228,8 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
bool HasLastprivateClause;
{
OMPPrivateScope LoopScope(CGF);
- emitPrivateLoopCounters(CGF, LoopScope, S.counters());
+ emitPrivateLoopCounters(CGF, LoopScope, S.counters(),
+ S.private_counters());
emitPrivateLinearVars(CGF, S, LoopScope);
CGF.EmitOMPPrivateClause(S, LoopScope);
CGF.EmitOMPReductionClauseInit(S, LoopScope);
@@ -846,12 +1258,10 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
}
-void CodeGenFunction::EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
- const OMPLoopDirective &S,
- OMPPrivateScope &LoopScope,
- bool Ordered, llvm::Value *LB,
- llvm::Value *UB, llvm::Value *ST,
- llvm::Value *IL, llvm::Value *Chunk) {
+void CodeGenFunction::EmitOMPForOuterLoop(
+ OpenMPScheduleClauseKind ScheduleKind, bool IsMonotonic,
+ const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered,
+ Address LB, Address UB, Address ST, Address IL, llvm::Value *Chunk) {
auto &RT = CGM.getOpenMPRuntime();
// Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime).
@@ -915,11 +1325,14 @@ void CodeGenFunction::EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
- RT.emitForInit(
- *this, S.getLocStart(), ScheduleKind, IVSize, IVSigned, Ordered, IL, LB,
- (DynamicOrOrdered ? EmitAnyExpr(S.getLastIteration()).getScalarVal()
- : UB),
- ST, Chunk);
+ if (DynamicOrOrdered) {
+ llvm::Value *UBVal = EmitScalarExpr(S.getLastIteration());
+ RT.emitForDispatchInit(*this, S.getLocStart(), ScheduleKind,
+ IVSize, IVSigned, Ordered, UBVal, Chunk);
+ } else {
+ RT.emitForStaticInit(*this, S.getLocStart(), ScheduleKind,
+ IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk);
+ }
auto LoopExit = getJumpDestInCurrentScope("omp.dispatch.end");
@@ -966,13 +1379,10 @@ void CodeGenFunction::EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
// Generate !llvm.loop.parallel metadata for loads and stores for loops
// with dynamic/guided scheduling and without ordered clause.
- if (!isOpenMPSimdDirective(S.getDirectiveKind())) {
- LoopStack.setParallel((ScheduleKind == OMPC_SCHEDULE_dynamic ||
- ScheduleKind == OMPC_SCHEDULE_guided) &&
- !Ordered);
- } else {
- EmitOMPSimdInit(S);
- }
+ if (!isOpenMPSimdDirective(S.getDirectiveKind()))
+ LoopStack.setParallel(!IsMonotonic);
+ else
+ EmitOMPSimdInit(S, IsMonotonic);
SourceLocation Loc = S.getLocStart();
EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
@@ -1013,15 +1423,30 @@ static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
return CGF.EmitLValue(Helper);
}
-static std::pair<llvm::Value * /*Chunk*/, OpenMPScheduleClauseKind>
+namespace {
+ struct ScheduleKindModifiersTy {
+ OpenMPScheduleClauseKind Kind;
+ OpenMPScheduleClauseModifier M1;
+ OpenMPScheduleClauseModifier M2;
+ ScheduleKindModifiersTy(OpenMPScheduleClauseKind Kind,
+ OpenMPScheduleClauseModifier M1,
+ OpenMPScheduleClauseModifier M2)
+ : Kind(Kind), M1(M1), M2(M2) {}
+ };
+} // namespace
+
+static std::pair<llvm::Value * /*Chunk*/, ScheduleKindModifiersTy>
emitScheduleClause(CodeGenFunction &CGF, const OMPLoopDirective &S,
bool OuterRegion) {
// Detect the loop schedule kind and chunk.
auto ScheduleKind = OMPC_SCHEDULE_unknown;
+ OpenMPScheduleClauseModifier M1 = OMPC_SCHEDULE_MODIFIER_unknown;
+ OpenMPScheduleClauseModifier M2 = OMPC_SCHEDULE_MODIFIER_unknown;
llvm::Value *Chunk = nullptr;
- if (auto *C =
- cast_or_null<OMPScheduleClause>(S.getSingleClause(OMPC_schedule))) {
+ if (const auto *C = S.getSingleClause<OMPScheduleClause>()) {
ScheduleKind = C->getScheduleKind();
+ M1 = C->getFirstScheduleModifier();
+ M2 = C->getSecondScheduleModifier();
if (const auto *Ch = C->getChunkSize()) {
if (auto *ImpRef = cast_or_null<DeclRefExpr>(C->getHelperChunkSize())) {
if (OuterRegion) {
@@ -1029,8 +1454,8 @@ emitScheduleClause(CodeGenFunction &CGF, const OMPLoopDirective &S,
CGF.EmitVarDecl(*ImpVar);
CGF.EmitStoreThroughLValue(
CGF.EmitAnyExpr(Ch),
- CGF.MakeNaturalAlignAddrLValue(CGF.GetAddrOfLocalVar(ImpVar),
- ImpVar->getType()));
+ CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(ImpVar),
+ ImpVar->getType()));
} else {
Ch = ImpRef;
}
@@ -1038,11 +1463,12 @@ emitScheduleClause(CodeGenFunction &CGF, const OMPLoopDirective &S,
if (!C->getHelperChunkSize() || !OuterRegion) {
Chunk = CGF.EmitScalarExpr(Ch);
Chunk = CGF.EmitScalarConversion(Chunk, Ch->getType(),
- S.getIterationVariable()->getType());
+ S.getIterationVariable()->getType(),
+ S.getLocStart());
}
}
}
- return std::make_pair(Chunk, ScheduleKind);
+ return std::make_pair(Chunk, ScheduleKindModifiersTy(ScheduleKind, M1, M2));
}
bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
@@ -1100,13 +1526,15 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
if (EmitOMPFirstprivateClause(S, LoopScope)) {
// Emit implicit barrier to synchronize threads and avoid data races on
// initialization of firstprivate variables.
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
- OMPD_unknown);
+ CGM.getOpenMPRuntime().emitBarrierCall(
+ *this, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
+ /*ForceSimpleCall=*/true);
}
EmitOMPPrivateClause(S, LoopScope);
HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
EmitOMPReductionClauseInit(S, LoopScope);
- emitPrivateLoopCounters(*this, LoopScope, S.counters());
+ emitPrivateLoopCounters(*this, LoopScope, S.counters(),
+ S.private_counters());
emitPrivateLinearVars(*this, S, LoopScope);
(void)LoopScope.Privatize();
@@ -1116,25 +1544,32 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
auto ScheduleInfo =
emitScheduleClause(*this, S, /*OuterRegion=*/false);
Chunk = ScheduleInfo.first;
- ScheduleKind = ScheduleInfo.second;
+ ScheduleKind = ScheduleInfo.second.Kind;
+ const OpenMPScheduleClauseModifier M1 = ScheduleInfo.second.M1;
+ const OpenMPScheduleClauseModifier M2 = ScheduleInfo.second.M2;
const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
- const bool Ordered = S.getSingleClause(OMPC_ordered) != nullptr;
+ const bool Ordered = S.getSingleClause<OMPOrderedClause>() != nullptr;
+ // OpenMP 4.5, 2.7.1 Loop Construct, Description.
+ // If the static schedule kind is specified or if the ordered clause is
+ // specified, and if no monotonic modifier is specified, the effect will
+ // be as if the monotonic modifier was specified.
if (RT.isStaticNonchunked(ScheduleKind,
/* Chunked */ Chunk != nullptr) &&
!Ordered) {
- if (isOpenMPSimdDirective(S.getDirectiveKind())) {
- EmitOMPSimdInit(S);
- }
+ if (isOpenMPSimdDirective(S.getDirectiveKind()))
+ EmitOMPSimdInit(S, /*IsMonotonic=*/true);
// OpenMP [2.7.1, Loop Construct, Description, table 2-1]
// When no chunk_size is specified, the iteration space is divided into
// chunks that are approximately equal in size, and at most one chunk is
// distributed to each thread. Note that the size of the chunks is
// unspecified in this case.
- RT.emitForInit(*this, S.getLocStart(), ScheduleKind, IVSize, IVSigned,
- Ordered, IL.getAddress(), LB.getAddress(),
- UB.getAddress(), ST.getAddress());
- auto LoopExit = getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
+ RT.emitForStaticInit(*this, S.getLocStart(), ScheduleKind,
+ IVSize, IVSigned, Ordered,
+ IL.getAddress(), LB.getAddress(),
+ UB.getAddress(), ST.getAddress());
+ auto LoopExit =
+ getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
// UB = min(UB, GlobalUB);
EmitIgnoredExpr(S.getEnsureUpperBound());
// IV = LB;
@@ -1151,9 +1586,14 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
// Tell the runtime we are done.
RT.emitForStaticFinish(*this, S.getLocStart());
} else {
+ const bool IsMonotonic = Ordered ||
+ ScheduleKind == OMPC_SCHEDULE_static ||
+ ScheduleKind == OMPC_SCHEDULE_unknown ||
+ M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
+ M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
// Emit the outer loop, which requests its work chunk [LB..UB] from
// runtime and runs the inner loop to process it.
- EmitOMPForOuterLoop(ScheduleKind, S, LoopScope, Ordered,
+ EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
LB.getAddress(), UB.getAddress(), ST.getAddress(),
IL.getAddress(), Chunk);
}
@@ -1181,10 +1621,11 @@ void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF) {
HasLastprivates = CGF.EmitOMPWorksharingLoop(S);
};
- CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen);
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen,
+ S.hasCancel());
// Emit an implicit barrier at the end.
- if (!S.getSingleClause(OMPC_nowait) || HasLastprivates) {
+ if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) {
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);
}
}
@@ -1198,7 +1639,7 @@ void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
// Emit an implicit barrier at the end.
- if (!S.getSingleClause(OMPC_nowait) || HasLastprivates) {
+ if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) {
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for);
}
}
@@ -1206,7 +1647,7 @@ void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty,
const Twine &Name,
llvm::Value *Init = nullptr) {
- auto LVal = CGF.MakeNaturalAlignAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
+ auto LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
if (Init)
CGF.EmitScalarInit(Init, LVal);
return LVal;
@@ -1276,8 +1717,9 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
// Emit implicit barrier to synchronize threads and avoid data races on
// initialization of firstprivate variables.
- CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
- OMPD_unknown);
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(
+ CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
+ /*ForceSimpleCall=*/true);
}
CGF.EmitOMPPrivateClause(S, LoopScope);
HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
@@ -1285,7 +1727,7 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
(void)LoopScope.Privatize();
// Emit static non-chunked loop.
- CGF.CGM.getOpenMPRuntime().emitForInit(
+ CGF.CGM.getOpenMPRuntime().emitForStaticInit(
CGF, S.getLocStart(), OMPC_SCHEDULE_static, /*IVSize=*/32,
/*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(),
LB.getAddress(), UB.getAddress(), ST.getAddress());
@@ -1310,11 +1752,17 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
CGF.EmitLoadOfScalar(IL, S.getLocStart())));
};
- CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen);
+ bool HasCancel = false;
+ if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
+ HasCancel = OSD->hasCancel();
+ else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
+ HasCancel = OPSD->hasCancel();
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen,
+ HasCancel);
// Emit barrier for lastprivates only if 'sections' directive has 'nowait'
// clause. Otherwise the barrier will be generated by the codegen for the
// directive.
- if (HasLastprivates && S.getSingleClause(OMPC_nowait)) {
+ if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
// Emit implicit barrier to synchronize threads and avoid data races on
// initialization of firstprivate variables.
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
@@ -1327,11 +1775,11 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
bool HasFirstprivates;
// No need to generate reductions for sections with single section region, we
// can use original shared variables for all operations.
- bool HasReductions = !S.getClausesOfKind(OMPC_reduction).empty();
+ bool HasReductions = S.hasClausesOfKind<OMPReductionClause>();
// No need to generate lastprivates for sections with single section region,
// we can use original shared variable for all calculations with barrier at
// the end of the sections.
- bool HasLastprivates = !S.getClausesOfKind(OMPC_lastprivate).empty();
+ bool HasLastprivates = S.hasClausesOfKind<OMPLastprivateClause>();
auto &&CodeGen = [Stmt, &S, &HasFirstprivates](CodeGenFunction &CGF) {
CodeGenFunction::OMPPrivateScope SingleScope(CGF);
HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope);
@@ -1347,10 +1795,12 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
// 'sections' directive has 'nowait' clause. Otherwise the barrier will be
// generated by the codegen for the directive.
if ((HasFirstprivates || HasLastprivates || HasReductions) &&
- S.getSingleClause(OMPC_nowait)) {
+ S.getSingleClause<OMPNowaitClause>()) {
// Emit implicit barrier to synchronize threads and avoid data races on
// initialization of firstprivate variables.
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_unknown);
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_unknown,
+ /*EmitChecks=*/false,
+ /*ForceSimpleCall=*/true);
}
return OMPD_single;
}
@@ -1359,7 +1809,7 @@ void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
LexicalScope Scope(*this, S.getSourceRange());
OpenMPDirectiveKind EmittedAs = EmitSections(S);
// Emit an implicit barrier at the end.
- if (!S.getSingleClause(OMPC_nowait)) {
+ if (!S.getSingleClause<OMPNowaitClause>()) {
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), EmittedAs);
}
}
@@ -1368,9 +1818,9 @@ void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
LexicalScope Scope(*this, S.getSourceRange());
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- CGF.EnsureInsertPoint();
};
- CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen);
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen,
+ S.hasCancel());
}
void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
@@ -1383,8 +1833,7 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
// construct.
// Build a list of copyprivate variables along with helper expressions
// (<source>, <destination>, <destination>=<source> expressions)
- for (auto &&I = S.getClausesOfKind(OMPC_copyprivate); I; ++I) {
- auto *C = cast<OMPCopyprivateClause>(*I);
+ for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) {
CopyprivateVars.append(C->varlists().begin(), C->varlists().end());
DestExprs.append(C->destination_exprs().begin(),
C->destination_exprs().end());
@@ -1402,18 +1851,17 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
(void)SingleScope.Privatize();
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- CGF.EnsureInsertPoint();
};
CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
CopyprivateVars, DestExprs, SrcExprs,
AssignmentOps);
// Emit an implicit barrier at the end (to avoid data race on firstprivate
// init or if no 'nowait' clause was specified and no 'copyprivate' clause).
- if ((!S.getSingleClause(OMPC_nowait) || HasFirstprivates) &&
+ if ((!S.getSingleClause<OMPNowaitClause>() || HasFirstprivates) &&
CopyprivateVars.empty()) {
CGM.getOpenMPRuntime().emitBarrierCall(
*this, S.getLocStart(),
- S.getSingleClause(OMPC_nowait) ? OMPD_unknown : OMPD_single);
+ S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
}
}
@@ -1421,7 +1869,6 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
LexicalScope Scope(*this, S.getSourceRange());
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- CGF.EnsureInsertPoint();
};
CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getLocStart());
}
@@ -1430,10 +1877,13 @@ void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
LexicalScope Scope(*this, S.getSourceRange());
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- CGF.EnsureInsertPoint();
};
- CGM.getOpenMPRuntime().emitCriticalRegion(
- *this, S.getDirectiveName().getAsString(), CodeGen, S.getLocStart());
+ Expr *Hint = nullptr;
+ if (auto *HintClause = S.getSingleClause<OMPHintClause>())
+ Hint = HintClause->getHint();
+ CGM.getOpenMPRuntime().emitCriticalRegion(*this,
+ S.getDirectiveName().getAsString(),
+ CodeGen, S.getLocStart(), Hint);
}
void CodeGenFunction::EmitOMPParallelForDirective(
@@ -1444,11 +1894,6 @@ void CodeGenFunction::EmitOMPParallelForDirective(
(void)emitScheduleClause(*this, S, /*OuterRegion=*/true);
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitOMPWorksharingLoop(S);
- // Emit implicit barrier at the end of parallel region, but this barrier
- // is at the end of 'for' directive, so emit it as the implicit barrier for
- // this 'for' directive.
- CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
- OMPD_parallel);
};
emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen);
}
@@ -1461,11 +1906,6 @@ void CodeGenFunction::EmitOMPParallelForSimdDirective(
(void)emitScheduleClause(*this, S, /*OuterRegion=*/true);
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitOMPWorksharingLoop(S);
- // Emit implicit barrier at the end of parallel region, but this barrier
- // is at the end of 'for' directive, so emit it as the implicit barrier for
- // this 'for' directive.
- CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
- OMPD_parallel);
};
emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen);
}
@@ -1477,9 +1917,6 @@ void CodeGenFunction::EmitOMPParallelSectionsDirective(
LexicalScope Scope(*this, S.getSourceRange());
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
(void)CGF.EmitSections(S);
- // Emit implicit barrier at the end of parallel region.
- CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
- OMPD_parallel);
};
emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen);
}
@@ -1497,8 +1934,7 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
// Get list of private variables.
llvm::SmallVector<const Expr *, 8> PrivateVars;
llvm::SmallVector<const Expr *, 8> PrivateCopies;
- for (auto &&I = S.getClausesOfKind(OMPC_private); I; ++I) {
- auto *C = cast<OMPPrivateClause>(*I);
+ for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
auto IRef = C->varlist_begin();
for (auto *IInit : C->private_copies()) {
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
@@ -1514,8 +1950,7 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
llvm::SmallVector<const Expr *, 8> FirstprivateVars;
llvm::SmallVector<const Expr *, 8> FirstprivateCopies;
llvm::SmallVector<const Expr *, 8> FirstprivateInits;
- for (auto &&I = S.getClausesOfKind(OMPC_firstprivate); I; ++I) {
- auto *C = cast<OMPFirstprivateClause>(*I);
+ for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
auto IRef = C->varlist_begin();
auto IElemInitRef = C->inits().begin();
for (auto *IInit : C->private_copies()) {
@@ -1531,8 +1966,7 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
// Build list of dependences.
llvm::SmallVector<std::pair<OpenMPDependClauseKind, const Expr *>, 8>
Dependences;
- for (auto &&I = S.getClausesOfKind(OMPC_depend); I; ++I) {
- auto *C = cast<OMPDependClause>(*I);
+ for (const auto *C : S.getClausesOfKind<OMPDependClause>()) {
for (auto *IRef : C->varlists()) {
Dependences.push_back(std::make_pair(C->getDependencyKind(), IRef));
}
@@ -1543,35 +1977,33 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
auto *CS = cast<CapturedStmt>(S.getAssociatedStmt());
OMPPrivateScope Scope(CGF);
if (!PrivateVars.empty() || !FirstprivateVars.empty()) {
- auto *CopyFn = CGF.Builder.CreateAlignedLoad(
- CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(3)),
- CGF.PointerAlignInBytes);
- auto *PrivatesPtr = CGF.Builder.CreateAlignedLoad(
- CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(2)),
- CGF.PointerAlignInBytes);
+ auto *CopyFn = CGF.Builder.CreateLoad(
+ CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(3)));
+ auto *PrivatesPtr = CGF.Builder.CreateLoad(
+ CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(2)));
// Map privates.
- llvm::SmallVector<std::pair<const VarDecl *, llvm::Value *>, 16>
+ llvm::SmallVector<std::pair<const VarDecl *, Address>, 16>
PrivatePtrs;
llvm::SmallVector<llvm::Value *, 16> CallArgs;
CallArgs.push_back(PrivatesPtr);
for (auto *E : PrivateVars) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- auto *PrivatePtr =
+ Address PrivatePtr =
CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()));
PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
- CallArgs.push_back(PrivatePtr);
+ CallArgs.push_back(PrivatePtr.getPointer());
}
for (auto *E : FirstprivateVars) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- auto *PrivatePtr =
+ Address PrivatePtr =
CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()));
PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr));
- CallArgs.push_back(PrivatePtr);
+ CallArgs.push_back(PrivatePtr.getPointer());
}
CGF.EmitRuntimeCall(CopyFn, CallArgs);
for (auto &&Pair : PrivatePtrs) {
- auto *Replacement =
- CGF.Builder.CreateAlignedLoad(Pair.second, CGF.PointerAlignInBytes);
+ Address Replacement(CGF.Builder.CreateLoad(Pair.second),
+ CGF.getContext().getDeclAlign(Pair.first));
Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
}
}
@@ -1584,13 +2016,13 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
auto OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
S, *I, OMPD_task, CodeGen);
// Check if we should emit tied or untied task.
- bool Tied = !S.getSingleClause(OMPC_untied);
+ bool Tied = !S.getSingleClause<OMPUntiedClause>();
// Check if the task is final
llvm::PointerIntPair<llvm::Value *, 1, bool> Final;
- if (auto *Clause = S.getSingleClause(OMPC_final)) {
+ if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {
// If the condition constant folds and can be elided, try to avoid emitting
// the condition and the dead arm of the if/else.
- auto *Cond = cast<OMPFinalClause>(Clause)->getCondition();
+ auto *Cond = Clause->getCondition();
bool CondConstant;
if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
Final.setInt(CondConstant);
@@ -1602,8 +2034,12 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
}
auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
const Expr *IfCond = nullptr;
- if (auto C = S.getSingleClause(OMPC_if)) {
- IfCond = cast<OMPIfClause>(C)->getCondition();
+ for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
+ if (C->getNameModifier() == OMPD_unknown ||
+ C->getNameModifier() == OMPD_task) {
+ IfCond = C->getCondition();
+ break;
+ }
}
CGM.getOpenMPRuntime().emitTaskCall(
*this, S.getLocStart(), S, Tied, Final, OutlinedFn, SharedsTy,
@@ -1629,15 +2065,13 @@ void CodeGenFunction::EmitOMPTaskgroupDirective(
LexicalScope Scope(*this, S.getSourceRange());
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- CGF.EnsureInsertPoint();
};
CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getLocStart());
}
void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
CGM.getOpenMPRuntime().emitFlush(*this, [&]() -> ArrayRef<const Expr *> {
- if (auto C = S.getSingleClause(/*K*/ OMPC_flush)) {
- auto FlushClause = cast<OMPFlushClause>(C);
+ if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>()) {
return llvm::makeArrayRef(FlushClause->varlist_begin(),
FlushClause->varlist_end());
}
@@ -1645,37 +2079,65 @@ void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
}(), S.getLocStart());
}
+void CodeGenFunction::EmitOMPDistributeDirective(
+ const OMPDistributeDirective &S) {
+ llvm_unreachable("CodeGen for 'omp distribute' is not supported yet.");
+}
+
+static llvm::Function *emitOutlinedOrderedFunction(CodeGenModule &CGM,
+ const CapturedStmt *S) {
+ CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
+ CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
+ CGF.CapturedStmtInfo = &CapStmtInfo;
+ auto *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S);
+ Fn->addFnAttr(llvm::Attribute::NoInline);
+ return Fn;
+}
+
void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
+ if (!S.getAssociatedStmt())
+ return;
LexicalScope Scope(*this, S.getSourceRange());
- auto &&CodeGen = [&S](CodeGenFunction &CGF) {
- CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
- CGF.EnsureInsertPoint();
+ auto *C = S.getSingleClause<OMPSIMDClause>();
+ auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF) {
+ if (C) {
+ auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
+ llvm::SmallVector<llvm::Value *, 16> CapturedVars;
+ CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
+ auto *OutlinedFn = emitOutlinedOrderedFunction(CGM, CS);
+ CGF.EmitNounwindRuntimeCall(OutlinedFn, CapturedVars);
+ } else {
+ CGF.EmitStmt(
+ cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ }
};
- CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getLocStart());
+ CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getLocStart(), !C);
}
static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val,
- QualType SrcType, QualType DestType) {
+ QualType SrcType, QualType DestType,
+ SourceLocation Loc) {
assert(CGF.hasScalarEvaluationKind(DestType) &&
"DestType must have scalar evaluation kind.");
assert(!Val.isAggregate() && "Must be a scalar or complex.");
return Val.isScalar()
- ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType, DestType)
+ ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType, DestType,
+ Loc)
: CGF.EmitComplexToScalarConversion(Val.getComplexVal(), SrcType,
- DestType);
+ DestType, Loc);
}
static CodeGenFunction::ComplexPairTy
convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType,
- QualType DestType) {
+ QualType DestType, SourceLocation Loc) {
assert(CGF.getEvaluationKind(DestType) == TEK_Complex &&
"DestType must have complex evaluation kind.");
CodeGenFunction::ComplexPairTy ComplexVal;
if (Val.isScalar()) {
// Convert the input element to the element type of the complex.
auto DestElementType = DestType->castAs<ComplexType>()->getElementType();
- auto ScalarVal =
- CGF.EmitScalarConversion(Val.getScalarVal(), SrcType, DestElementType);
+ auto ScalarVal = CGF.EmitScalarConversion(Val.getScalarVal(), SrcType,
+ DestElementType, Loc);
ComplexVal = CodeGenFunction::ComplexPairTy(
ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
} else {
@@ -1683,9 +2145,9 @@ convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType,
auto SrcElementType = SrcType->castAs<ComplexType>()->getElementType();
auto DestElementType = DestType->castAs<ComplexType>()->getElementType();
ComplexVal.first = CGF.EmitScalarConversion(
- Val.getComplexVal().first, SrcElementType, DestElementType);
+ Val.getComplexVal().first, SrcElementType, DestElementType, Loc);
ComplexVal.second = CGF.EmitScalarConversion(
- Val.getComplexVal().second, SrcElementType, DestElementType);
+ Val.getComplexVal().second, SrcElementType, DestElementType, Loc);
}
return ComplexVal;
}
@@ -1702,16 +2164,16 @@ static void emitSimpleAtomicStore(CodeGenFunction &CGF, bool IsSeqCst,
}
static void emitSimpleStore(CodeGenFunction &CGF, LValue LVal, RValue RVal,
- QualType RValTy) {
+ QualType RValTy, SourceLocation Loc) {
switch (CGF.getEvaluationKind(LVal.getType())) {
case TEK_Scalar:
- CGF.EmitStoreThroughLValue(
- RValue::get(convertToScalarValue(CGF, RVal, RValTy, LVal.getType())),
- LVal);
+ CGF.EmitStoreThroughLValue(RValue::get(convertToScalarValue(
+ CGF, RVal, RValTy, LVal.getType(), Loc)),
+ LVal);
break;
case TEK_Complex:
CGF.EmitStoreOfComplex(
- convertToComplexValue(CGF, RVal, RValTy, LVal.getType()), LVal,
+ convertToComplexValue(CGF, RVal, RValTy, LVal.getType(), Loc), LVal,
/*isInit=*/false);
break;
case TEK_Aggregate:
@@ -1739,7 +2201,7 @@ static void EmitOMPAtomicReadExpr(CodeGenFunction &CGF, bool IsSeqCst,
// list.
if (IsSeqCst)
CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc);
- emitSimpleStore(CGF,VLValue, Res, X->getType().getNonReferenceType());
+ emitSimpleStore(CGF, VLValue, Res, X->getType().getNonReferenceType(), Loc);
}
static void EmitOMPAtomicWriteExpr(CodeGenFunction &CGF, bool IsSeqCst,
@@ -1769,8 +2231,8 @@ static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
!Update.getScalarVal()->getType()->isIntegerTy() ||
!X.isSimple() || (!isa<llvm::ConstantInt>(Update.getScalarVal()) &&
(Update.getScalarVal()->getType() !=
- X.getAddress()->getType()->getPointerElementType())) ||
- !X.getAddress()->getType()->getPointerElementType()->isIntegerTy() ||
+ X.getAddress().getElementType())) ||
+ !X.getAddress().getElementType()->isIntegerTy() ||
!Context.getTargetInfo().hasBuiltinAtomic(
Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment())))
return std::make_pair(false, RValue::get(nullptr));
@@ -1841,10 +2303,10 @@ static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
auto *UpdateVal = Update.getScalarVal();
if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
UpdateVal = CGF.Builder.CreateIntCast(
- IC, X.getAddress()->getType()->getPointerElementType(),
+ IC, X.getAddress().getElementType(),
X.getType()->hasSignedIntegerRepresentation());
}
- auto *Res = CGF.Builder.CreateAtomicRMW(RMWOp, X.getAddress(), UpdateVal, AO);
+ auto *Res = CGF.Builder.CreateAtomicRMW(RMWOp, X.getPointer(), UpdateVal, AO);
return std::make_pair(true, RValue::get(Res));
}
@@ -1910,12 +2372,14 @@ static void EmitOMPAtomicUpdateExpr(CodeGenFunction &CGF, bool IsSeqCst,
}
static RValue convertToType(CodeGenFunction &CGF, RValue Value,
- QualType SourceType, QualType ResType) {
+ QualType SourceType, QualType ResType,
+ SourceLocation Loc) {
switch (CGF.getEvaluationKind(ResType)) {
case TEK_Scalar:
- return RValue::get(convertToScalarValue(CGF, Value, SourceType, ResType));
+ return RValue::get(
+ convertToScalarValue(CGF, Value, SourceType, ResType, Loc));
case TEK_Complex: {
- auto Res = convertToComplexValue(CGF, Value, SourceType, ResType);
+ auto Res = convertToComplexValue(CGF, Value, SourceType, ResType, Loc);
return RValue::getComplex(Res.first, Res.second);
}
case TEK_Aggregate:
@@ -1980,7 +2444,7 @@ static void EmitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
// 'x' is simply rewritten with some 'expr'.
NewVValType = X->getType().getNonReferenceType();
ExprRValue = convertToType(CGF, ExprRValue, E->getType(),
- X->getType().getNonReferenceType());
+ X->getType().getNonReferenceType(), Loc);
auto &&Gen = [&CGF, &NewVVal, ExprRValue](RValue XRValue) -> RValue {
NewVVal = XRValue;
return ExprRValue;
@@ -1995,7 +2459,7 @@ static void EmitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst,
}
}
// Emit post-update store to 'v' of old/new 'x' value.
- emitSimpleStore(CGF, VLValue, NewVVal, NewVValType);
+ emitSimpleStore(CGF, VLValue, NewVVal, NewVValType, Loc);
// OpenMP, 2.12.6, atomic Construct
// Any atomic construct with a seq_cst clause forces the atomically
// performed operation to include an implicit flush operation without a
@@ -2032,6 +2496,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_lastprivate:
case OMPC_reduction:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
case OMPC_default:
case OMPC_seq_cst:
@@ -2049,12 +2514,23 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_threadprivate:
case OMPC_depend:
case OMPC_mergeable:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_map:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}
void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
- bool IsSeqCst = S.getSingleClause(/*K=*/OMPC_seq_cst);
+ bool IsSeqCst = S.getSingleClause<OMPSeqCstClause>();
OpenMPClauseKind Kind = OMPC_unknown;
for (auto *C : S.clauses()) {
// Find first clause (skip seq_cst clause, if it is first).
@@ -2079,7 +2555,8 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
}
LexicalScope Scope(*this, S.getSourceRange());
- auto &&CodeGen = [&S, Kind, IsSeqCst](CodeGenFunction &CGF) {
+ auto &&CodeGen = [&S, Kind, IsSeqCst, CS](CodeGenFunction &CGF) {
+ CGF.EmitStopPoint(CS);
EmitOMPAtomicExpr(CGF, Kind, IsSeqCst, S.isPostfixUpdate(), S.getX(),
S.getV(), S.getExpr(), S.getUpdateExpr(),
S.isXLHSInRHSPart(), S.getLocStart());
@@ -2087,8 +2564,58 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen);
}
-void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) {
- llvm_unreachable("CodeGen for 'omp target' is not supported yet.");
+void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &S) {
+ LexicalScope Scope(*this, S.getSourceRange());
+ const CapturedStmt &CS = *cast<CapturedStmt>(S.getAssociatedStmt());
+
+ llvm::SmallVector<llvm::Value *, 16> CapturedVars;
+ GenerateOpenMPCapturedVars(CS, CapturedVars);
+
+ llvm::Function *Fn = nullptr;
+ llvm::Constant *FnID = nullptr;
+
+ // Check if we have any if clause associated with the directive.
+ const Expr *IfCond = nullptr;
+
+ if (auto *C = S.getSingleClause<OMPIfClause>()) {
+ IfCond = C->getCondition();
+ }
+
+ // Check if we have any device clause associated with the directive.
+ const Expr *Device = nullptr;
+ if (auto *C = S.getSingleClause<OMPDeviceClause>()) {
+ Device = C->getDevice();
+ }
+
+ // Check if we have an if clause whose conditional always evaluates to false
+ // or if we do not have any targets specified. If so the target region is not
+ // an offload entry point.
+ bool IsOffloadEntry = true;
+ if (IfCond) {
+ bool Val;
+ if (ConstantFoldsToSimpleInteger(IfCond, Val) && !Val)
+ IsOffloadEntry = false;
+ }
+ if (CGM.getLangOpts().OMPTargetTriples.empty())
+ IsOffloadEntry = false;
+
+ assert(CurFuncDecl && "No parent declaration for target region!");
+ StringRef ParentName;
+ // In case we have Ctors/Dtors we use the complete type variant to produce
+ // the mangling of the device outlined kernel.
+ if (auto *D = dyn_cast<CXXConstructorDecl>(CurFuncDecl))
+ ParentName = CGM.getMangledName(GlobalDecl(D, Ctor_Complete));
+ else if (auto *D = dyn_cast<CXXDestructorDecl>(CurFuncDecl))
+ ParentName = CGM.getMangledName(GlobalDecl(D, Dtor_Complete));
+ else
+ ParentName =
+ CGM.getMangledName(GlobalDecl(cast<FunctionDecl>(CurFuncDecl)));
+
+ CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID,
+ IsOffloadEntry);
+
+ CGM.getOpenMPRuntime().emitTargetCall(*this, S, Fn, FnID, IfCond, Device,
+ CapturedVars);
}
void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &) {
@@ -2102,7 +2629,15 @@ void CodeGenFunction::EmitOMPCancellationPointDirective(
}
void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) {
- CGM.getOpenMPRuntime().emitCancelCall(*this, S.getLocStart(),
+ const Expr *IfCond = nullptr;
+ for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
+ if (C->getNameModifier() == OMPD_unknown ||
+ C->getNameModifier() == OMPD_cancel) {
+ IfCond = C->getCondition();
+ break;
+ }
+ }
+ CGM.getOpenMPRuntime().emitCancelCall(*this, S.getLocStart(), IfCond,
S.getCancelRegion());
}
@@ -2110,8 +2645,35 @@ CodeGenFunction::JumpDest
CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
if (Kind == OMPD_parallel || Kind == OMPD_task)
return ReturnBlock;
- else if (Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections)
- return BreakContinueStack.empty() ? JumpDest()
- : BreakContinueStack.back().BreakBlock;
- return JumpDest();
+ assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
+ Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for);
+ return BreakContinueStack.back().BreakBlock;
+}
+
+// Generate the instructions for '#pragma omp target data' directive.
+void CodeGenFunction::EmitOMPTargetDataDirective(
+ const OMPTargetDataDirective &S) {
+ // emit the code inside the construct for now
+ auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this, OMPD_target_data,
+ [&CS](CodeGenFunction &CGF) { CGF.EmitStmt(CS->getCapturedStmt()); });
}
+
+void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) {
+ // emit the code inside the construct for now
+ auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this, OMPD_taskloop,
+ [&CS](CodeGenFunction &CGF) { CGF.EmitStmt(CS->getCapturedStmt()); });
+}
+
+void CodeGenFunction::EmitOMPTaskLoopSimdDirective(
+ const OMPTaskLoopSimdDirective &S) {
+ // emit the code inside the construct for now
+ auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this, OMPD_taskloop_simd,
+ [&CS](CodeGenFunction &CGF) { CGF.EmitStmt(CS->getCapturedStmt()); });
+}
+
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
index e3df5a4..4fb76710 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp
@@ -108,7 +108,6 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
llvm::raw_svector_ostream Out(OutName);
cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext())
.mangleCXXVTT(RD, Out);
- Out.flush();
StringRef Name = OutName.str();
// This will also defer the definition of the VTT.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
index 1b7f1d7..a40aab2 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
@@ -44,7 +44,6 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
Thunk.This, Out);
else
getCXXABI().getMangleContext().mangleThunk(MD, Thunk, Out);
- Out.flush();
llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD);
return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true,
@@ -103,8 +102,11 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF,
CGF.EmitBlock(AdjustNotNull);
}
- ReturnValue = CGF.CGM.getCXXABI().performReturnAdjustment(CGF, ReturnValue,
- Thunk.Return);
+ auto ClassDecl = ResultType->getPointeeType()->getAsCXXRecordDecl();
+ auto ClassAlign = CGF.CGM.getClassPointerAlignment(ClassDecl);
+ ReturnValue = CGF.CGM.getCXXABI().performReturnAdjustment(CGF,
+ Address(ReturnValue, ClassAlign),
+ Thunk.Return);
if (NullCheckValue) {
CGF.Builder.CreateBr(AdjustEnd);
@@ -172,27 +174,29 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn,
// Find the first store of "this", which will be to the alloca associated
// with "this".
- llvm::Value *ThisPtr = &*AI;
- llvm::BasicBlock *EntryBB = Fn->begin();
- llvm::Instruction *ThisStore =
+ Address ThisPtr(&*AI, CGM.getClassPointerAlignment(MD->getParent()));
+ llvm::BasicBlock *EntryBB = &Fn->front();
+ llvm::BasicBlock::iterator ThisStore =
std::find_if(EntryBB->begin(), EntryBB->end(), [&](llvm::Instruction &I) {
- return isa<llvm::StoreInst>(I) && I.getOperand(0) == ThisPtr;
- });
- assert(ThisStore && "Store of this should be in entry block?");
+ return isa<llvm::StoreInst>(I) &&
+ I.getOperand(0) == ThisPtr.getPointer();
+ });
+ assert(ThisStore != EntryBB->end() &&
+ "Store of this should be in entry block?");
// Adjust "this", if necessary.
- Builder.SetInsertPoint(ThisStore);
+ Builder.SetInsertPoint(&*ThisStore);
llvm::Value *AdjustedThisPtr =
CGM.getCXXABI().performThisAdjustment(*this, ThisPtr, Thunk.This);
ThisStore->setOperand(0, AdjustedThisPtr);
if (!Thunk.Return.isEmpty()) {
// Fix up the returned value, if necessary.
- for (llvm::Function::iterator I = Fn->begin(), E = Fn->end(); I != E; I++) {
- llvm::Instruction *T = I->getTerminator();
+ for (llvm::BasicBlock &BB : *Fn) {
+ llvm::Instruction *T = BB.getTerminator();
if (isa<llvm::ReturnInst>(T)) {
RValue RV = RValue::get(T->getOperand(0));
T->eraseFromParent();
- Builder.SetInsertPoint(&*I);
+ Builder.SetInsertPoint(&BB);
RV = PerformReturnAdjustment(*this, ResultType, RV, Thunk);
Builder.CreateRet(RV.getScalarVal());
break;
@@ -236,6 +240,17 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD,
// Since we didn't pass a GlobalDecl to StartFunction, do this ourselves.
CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
CXXThisValue = CXXABIThisValue;
+ CurCodeDecl = MD;
+ CurFuncDecl = MD;
+}
+
+void CodeGenFunction::FinishThunk() {
+ // Clear these to restore the invariants expected by
+ // StartFunction/FinishFunction.
+ CurCodeDecl = nullptr;
+ CurFuncDecl = nullptr;
+
+ FinishFunction();
}
void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
@@ -245,9 +260,10 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CurGD.getDecl());
// Adjust the 'this' pointer if necessary
- llvm::Value *AdjustedThisPtr = Thunk ? CGM.getCXXABI().performThisAdjustment(
- *this, LoadCXXThis(), Thunk->This)
- : LoadCXXThis();
+ llvm::Value *AdjustedThisPtr =
+ Thunk ? CGM.getCXXABI().performThisAdjustment(
+ *this, LoadCXXThisAddress(), Thunk->This)
+ : LoadCXXThis();
if (CurFnInfo->usesInAlloca()) {
// We don't handle return adjusting thunks, because they require us to call
@@ -312,6 +328,8 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
// Consider return adjustment if we have ThunkInfo.
if (Thunk && !Thunk->Return.isEmpty())
RV = PerformReturnAdjustment(*this, ResultType, RV, *Thunk);
+ else if (llvm::CallInst* Call = dyn_cast<llvm::CallInst>(CallOrInvoke))
+ Call->setTailCallKind(llvm::CallInst::TCK_Tail);
// Emit return.
if (!ResultType->isVoidType() && Slot.isNull())
@@ -320,7 +338,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
// Disable the final ARC autorelease.
AutoreleaseResult = false;
- FinishFunction();
+ FinishThunk();
}
void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
@@ -345,9 +363,8 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
Args[ThisArgNo] = AdjustedThisPtr;
} else {
assert(ThisAI.isInAlloca() && "this is passed directly or inalloca");
- llvm::Value *ThisAddr = GetAddrOfLocalVar(CXXABIThisDecl);
- llvm::Type *ThisType =
- cast<llvm::PointerType>(ThisAddr->getType())->getElementType();
+ Address ThisAddr = GetAddrOfLocalVar(CXXABIThisDecl);
+ llvm::Type *ThisType = ThisAddr.getElementType();
if (ThisType != AdjustedThisPtr->getType())
AdjustedThisPtr = Builder.CreateBitCast(AdjustedThisPtr, ThisType);
Builder.CreateStore(AdjustedThisPtr, ThisAddr);
@@ -361,8 +378,8 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
// Apply the standard set of call attributes.
unsigned CallingConv;
CodeGen::AttributeListType AttributeList;
- CGM.ConstructAttributeList(*CurFnInfo, MD, AttributeList, CallingConv,
- /*AttrOnCallSite=*/true);
+ CGM.ConstructAttributeList(Callee->getName(), *CurFnInfo, MD, AttributeList,
+ CallingConv, /*AttrOnCallSite=*/true);
llvm::AttributeSet Attrs =
llvm::AttributeSet::get(getLLVMContext(), AttributeList);
Call->setAttributes(Attrs);
@@ -502,8 +519,8 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
if (!ThunkInfoVector)
return;
- for (unsigned I = 0, E = ThunkInfoVector->size(); I != E; ++I)
- emitThunk(GD, (*ThunkInfoVector)[I], /*ForVTable=*/false);
+ for (const ThunkInfo& Thunk : *ThunkInfoVector)
+ emitThunk(GD, Thunk, /*ForVTable=*/false);
}
llvm::Constant *CodeGenVTables::CreateVTableInitializer(
@@ -565,6 +582,24 @@ llvm::Constant *CodeGenVTables::CreateVTableInitializer(
break;
}
+ if (CGM.getLangOpts().CUDA) {
+ // Emit NULL for methods we can't codegen on this
+ // side. Otherwise we'd end up with vtable with unresolved
+ // references.
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ // OK on device side: functions w/ __device__ attribute
+ // OK on host side: anything except __device__-only functions.
+ bool CanEmitMethod = CGM.getLangOpts().CUDAIsDevice
+ ? MD->hasAttr<CUDADeviceAttr>()
+ : (MD->hasAttr<CUDAHostAttr>() ||
+ !MD->hasAttr<CUDADeviceAttr>());
+ if (!CanEmitMethod) {
+ Init = llvm::ConstantExpr::getNullValue(Int8PtrTy);
+ break;
+ }
+ // Method is acceptable, continue processing as usual.
+ }
+
if (cast<CXXMethodDecl>(GD.getDecl())->isPure()) {
// We have a pure virtual member function.
if (!PureVirtualFn) {
@@ -642,7 +677,6 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext())
.mangleCXXCtorVTable(RD, Base.getBaseOffset().getQuantity(),
Base.getBase(), Out);
- Out.flush();
StringRef Name = OutName.str();
llvm::ArrayType *ArrayType =
@@ -679,6 +713,12 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
return VTable;
}
+static bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM,
+ const CXXRecordDecl *RD) {
+ return CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ CGM.getCXXABI().canSpeculativelyEmitVTable(RD);
+}
+
/// Compute the required linkage of the v-table for the given class.
///
/// Note that we only call this at the end of the translation unit.
@@ -700,7 +740,12 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
switch (keyFunction->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
- assert(def && "Should not have been asked to emit this");
+ assert((def || CodeGenOpts.OptimizationLevel > 0) &&
+ "Shouldn't query vtable linkage without key function or "
+ "optimizations");
+ if (!def && CodeGenOpts.OptimizationLevel > 0)
+ return llvm::GlobalVariable::AvailableExternallyLinkage;
+
if (keyFunction->isInlined())
return !Context.getLangOpts().AppleKext ?
llvm::GlobalVariable::LinkOnceODRLinkage :
@@ -742,16 +787,18 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
}
switch (RD->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- case TSK_ImplicitInstantiation:
- return DiscardableODRLinkage;
-
- case TSK_ExplicitInstantiationDeclaration:
- return llvm::GlobalVariable::ExternalLinkage;
-
- case TSK_ExplicitInstantiationDefinition:
- return NonDiscardableODRLinkage;
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ case TSK_ImplicitInstantiation:
+ return DiscardableODRLinkage;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ return shouldEmitAvailableExternallyVTable(*this, RD)
+ ? llvm::GlobalVariable::AvailableExternallyLinkage
+ : llvm::GlobalVariable::ExternalLinkage;
+
+ case TSK_ExplicitInstantiationDefinition:
+ return NonDiscardableODRLinkage;
}
llvm_unreachable("Invalid TemplateSpecializationKind!");
@@ -819,7 +866,12 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
/// we define that v-table?
static bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &CGM,
const CXXRecordDecl *RD) {
- return !CGM.getVTables().isVTableExternal(RD);
+ // If vtable is internal then it has to be done.
+ if (!CGM.getVTables().isVTableExternal(RD))
+ return true;
+
+ // If it's external then maybe we will need it as available_externally.
+ return shouldEmitAvailableExternallyVTable(CGM, RD);
}
/// Given that at some point we emitted a reference to one or more
@@ -832,13 +884,9 @@ void CodeGenModule::EmitDeferredVTables() {
size_t savedSize = DeferredVTables.size();
#endif
- typedef std::vector<const CXXRecordDecl *>::const_iterator const_iterator;
- for (const_iterator i = DeferredVTables.begin(),
- e = DeferredVTables.end(); i != e; ++i) {
- const CXXRecordDecl *RD = *i;
+ for (const CXXRecordDecl *RD : DeferredVTables)
if (shouldEmitVTableAtEndOfTranslationUnit(*this, RD))
VTables.GenerateClassData(RD);
- }
assert(savedSize == DeferredVTables.size() &&
"deferred extra v-tables during v-table emission?");
@@ -846,8 +894,12 @@ void CodeGenModule::EmitDeferredVTables() {
}
bool CodeGenModule::IsCFIBlacklistedRecord(const CXXRecordDecl *RD) {
- // FIXME: Make this user configurable.
- return RD->isInStdNamespace();
+ if (RD->hasAttr<UuidAttr>() &&
+ getContext().getSanitizerBlacklist().isBlacklistedType("attr:uuid"))
+ return true;
+
+ return getContext().getSanitizerBlacklist().isBlacklistedType(
+ RD->getQualifiedNameAsString());
}
void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
@@ -861,41 +913,46 @@ void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
CharUnits PointerWidth =
Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
- std::vector<llvm::MDTuple *> BitsetEntries;
+ typedef std::pair<const CXXRecordDecl *, unsigned> BSEntry;
+ std::vector<BSEntry> BitsetEntries;
// Create a bit set entry for each address point.
for (auto &&AP : VTLayout.getAddressPoints()) {
if (IsCFIBlacklistedRecord(AP.first.getBase()))
continue;
- BitsetEntries.push_back(CreateVTableBitSetEntry(
- VTable, PointerWidth * AP.second, AP.first.getBase()));
+ BitsetEntries.push_back(std::make_pair(AP.first.getBase(), AP.second));
}
// Sort the bit set entries for determinism.
- std::sort(BitsetEntries.begin(), BitsetEntries.end(), [](llvm::MDTuple *T1,
- llvm::MDTuple *T2) {
- if (T1 == T2)
+ std::sort(BitsetEntries.begin(), BitsetEntries.end(),
+ [this](const BSEntry &E1, const BSEntry &E2) {
+ if (&E1 == &E2)
return false;
- StringRef S1 = cast<llvm::MDString>(T1->getOperand(0))->getString();
- StringRef S2 = cast<llvm::MDString>(T2->getOperand(0))->getString();
+ std::string S1;
+ llvm::raw_string_ostream O1(S1);
+ getCXXABI().getMangleContext().mangleTypeName(
+ QualType(E1.first->getTypeForDecl(), 0), O1);
+ O1.flush();
+
+ std::string S2;
+ llvm::raw_string_ostream O2(S2);
+ getCXXABI().getMangleContext().mangleTypeName(
+ QualType(E2.first->getTypeForDecl(), 0), O2);
+ O2.flush();
+
if (S1 < S2)
return true;
if (S1 != S2)
return false;
- uint64_t Offset1 = cast<llvm::ConstantInt>(
- cast<llvm::ConstantAsMetadata>(T1->getOperand(2))
- ->getValue())->getZExtValue();
- uint64_t Offset2 = cast<llvm::ConstantInt>(
- cast<llvm::ConstantAsMetadata>(T2->getOperand(2))
- ->getValue())->getZExtValue();
- assert(Offset1 != Offset2);
- return Offset1 < Offset2;
+ return E1.second < E2.second;
});
llvm::NamedMDNode *BitsetsMD =
getModule().getOrInsertNamedMetadata("llvm.bitsets");
for (auto BitsetEntry : BitsetEntries)
- BitsetsMD->addOperand(BitsetEntry);
+ CreateVTableBitSetEntry(BitsetsMD, VTable,
+ PointerWidth * BitsetEntry.second,
+ BitsetEntry.first);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h
index e0195a2..c27e54a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.h
@@ -85,10 +85,6 @@ public:
uint64_t getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
BaseSubobject Base);
- /// getAddressPoint - Get the address point of the given subobject in the
- /// class decl.
- uint64_t getAddressPoint(BaseSubobject Base, const CXXRecordDecl *RD);
-
/// GenerateConstructionVTable - Generate a construction vtable for the given
/// base subobject.
llvm::GlobalVariable *
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h b/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
index 9205591..3ccc4cd 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGValue.h
@@ -16,10 +16,10 @@
#define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H
#include "clang/AST/ASTContext.h"
-#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/Type.h"
+#include "Address.h"
namespace llvm {
class Constant;
@@ -38,6 +38,10 @@ namespace CodeGen {
class RValue {
enum Flavor { Scalar, Complex, Aggregate };
+ // The shift to make to an aggregate's alignment to make it look
+ // like a pointer.
+ enum { AggAlignShift = 4 };
+
// Stores first value and flavor.
llvm::PointerIntPair<llvm::Value *, 2, Flavor> V1;
// Stores second value and volatility.
@@ -63,11 +67,21 @@ public:
}
/// getAggregateAddr() - Return the Value* of the address of the aggregate.
- llvm::Value *getAggregateAddr() const {
+ Address getAggregateAddress() const {
+ assert(isAggregate() && "Not an aggregate!");
+ auto align = reinterpret_cast<uintptr_t>(V2.getPointer()) >> AggAlignShift;
+ return Address(V1.getPointer(), CharUnits::fromQuantity(align));
+ }
+ llvm::Value *getAggregatePointer() const {
assert(isAggregate() && "Not an aggregate!");
return V1.getPointer();
}
+ static RValue getIgnored() {
+ // FIXME: should we make this a more explicit state?
+ return get(nullptr);
+ }
+
static RValue get(llvm::Value *V) {
RValue ER;
ER.V1.setPointer(V);
@@ -89,11 +103,14 @@ public:
// FIXME: Aggregate rvalues need to retain information about whether they are
// volatile or not. Remove default to find all places that probably get this
// wrong.
- static RValue getAggregate(llvm::Value *V, bool Volatile = false) {
+ static RValue getAggregate(Address addr, bool isVolatile = false) {
RValue ER;
- ER.V1.setPointer(V);
+ ER.V1.setPointer(addr.getPointer());
ER.V1.setInt(Aggregate);
- ER.V2.setInt(Volatile);
+
+ auto align = static_cast<uintptr_t>(addr.getAlignment().getQuantity());
+ ER.V2.setPointer(reinterpret_cast<llvm::Value*>(align << AggAlignShift));
+ ER.V2.setInt(isVolatile);
return ER;
}
};
@@ -103,6 +120,32 @@ enum ARCPreciseLifetime_t {
ARCImpreciseLifetime, ARCPreciseLifetime
};
+/// The source of the alignment of an l-value; an expression of
+/// confidence in the alignment actually matching the estimate.
+enum class AlignmentSource {
+ /// The l-value was an access to a declared entity or something
+ /// equivalently strong, like the address of an array allocated by a
+ /// language runtime.
+ Decl,
+
+ /// The l-value was considered opaque, so the alignment was
+ /// determined from a type, but that type was an explicitly-aligned
+ /// typedef.
+ AttributedType,
+
+ /// The l-value was considered opaque, so the alignment was
+ /// determined from a type.
+ Type
+};
+
+/// Given that the base address has the given alignment source, what's
+/// our confidence in the alignment of the field?
+static inline AlignmentSource getFieldAlignmentSource(AlignmentSource Source) {
+ // For now, we don't distinguish fields of opaque pointers from
+ // top-level declarations, but maybe we should.
+ return AlignmentSource::Decl;
+}
+
/// LValue - This represents an lvalue references. Because C/C++ allow
/// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a
/// bitrange.
@@ -157,6 +200,12 @@ class LValue {
// to make the default bitfield pattern all-zeroes.
bool ImpreciseLifetime : 1;
+ unsigned AlignSource : 2;
+
+ // This flag shows if a nontemporal load/stores should be used when accessing
+ // this lvalue.
+ bool Nontemporal : 1;
+
Expr *BaseIvarExp;
/// Used by struct-path-aware TBAA.
@@ -169,17 +218,21 @@ class LValue {
private:
void Initialize(QualType Type, Qualifiers Quals,
- CharUnits Alignment,
+ CharUnits Alignment, AlignmentSource AlignSource,
llvm::MDNode *TBAAInfo = nullptr) {
+ assert((!Alignment.isZero() || Type->isIncompleteType()) &&
+ "initializing l-value with zero alignment!");
this->Type = Type;
this->Quals = Quals;
this->Alignment = Alignment.getQuantity();
assert(this->Alignment == Alignment.getQuantity() &&
"Alignment exceeds allowed max!");
+ this->AlignSource = unsigned(AlignSource);
// Initialize Objective-C flags.
this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
this->ImpreciseLifetime = false;
+ this->Nontemporal = false;
this->ThreadLocalRef = false;
this->BaseIvarExp = nullptr;
@@ -229,6 +282,8 @@ public:
void setARCPreciseLifetime(ARCPreciseLifetime_t value) {
ImpreciseLifetime = (value == ARCImpreciseLifetime);
}
+ bool isNontemporal() const { return Nontemporal; }
+ void setNontemporal(bool Value) { Nontemporal = Value; }
bool isObjCWeak() const {
return Quals.getObjCGCAttr() == Qualifiers::Weak;
@@ -261,29 +316,50 @@ public:
CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); }
void setAlignment(CharUnits A) { Alignment = A.getQuantity(); }
+ AlignmentSource getAlignmentSource() const {
+ return AlignmentSource(AlignSource);
+ }
+ void setAlignmentSource(AlignmentSource Source) {
+ AlignSource = unsigned(Source);
+ }
+
// simple lvalue
- llvm::Value *getAddress() const { assert(isSimple()); return V; }
- void setAddress(llvm::Value *address) {
+ llvm::Value *getPointer() const {
+ assert(isSimple());
+ return V;
+ }
+ Address getAddress() const { return Address(getPointer(), getAlignment()); }
+ void setAddress(Address address) {
assert(isSimple());
- V = address;
+ V = address.getPointer();
+ Alignment = address.getAlignment().getQuantity();
}
// vector elt lvalue
- llvm::Value *getVectorAddr() const { assert(isVectorElt()); return V; }
+ Address getVectorAddress() const {
+ return Address(getVectorPointer(), getAlignment());
+ }
+ llvm::Value *getVectorPointer() const { assert(isVectorElt()); return V; }
llvm::Value *getVectorIdx() const { assert(isVectorElt()); return VectorIdx; }
// extended vector elements.
- llvm::Value *getExtVectorAddr() const { assert(isExtVectorElt()); return V; }
+ Address getExtVectorAddress() const {
+ return Address(getExtVectorPointer(), getAlignment());
+ }
+ llvm::Value *getExtVectorPointer() const {
+ assert(isExtVectorElt());
+ return V;
+ }
llvm::Constant *getExtVectorElts() const {
assert(isExtVectorElt());
return VectorElts;
}
// bitfield lvalue
- llvm::Value *getBitFieldAddr() const {
- assert(isBitField());
- return V;
+ Address getBitFieldAddress() const {
+ return Address(getBitFieldPointer(), getAlignment());
}
+ llvm::Value *getBitFieldPointer() const { assert(isBitField()); return V; }
const CGBitFieldInfo &getBitFieldInfo() const {
assert(isBitField());
return *BitFieldInfo;
@@ -292,37 +368,40 @@ public:
// global register lvalue
llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; }
- static LValue MakeAddr(llvm::Value *address, QualType type,
- CharUnits alignment, ASTContext &Context,
+ static LValue MakeAddr(Address address, QualType type,
+ ASTContext &Context,
+ AlignmentSource alignSource,
llvm::MDNode *TBAAInfo = nullptr) {
Qualifiers qs = type.getQualifiers();
qs.setObjCGCAttr(Context.getObjCGCAttrKind(type));
LValue R;
R.LVType = Simple;
- assert(address->getType()->isPointerTy());
- R.V = address;
- R.Initialize(type, qs, alignment, TBAAInfo);
+ assert(address.getPointer()->getType()->isPointerTy());
+ R.V = address.getPointer();
+ R.Initialize(type, qs, address.getAlignment(), alignSource, TBAAInfo);
return R;
}
- static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx,
- QualType type, CharUnits Alignment) {
+ static LValue MakeVectorElt(Address vecAddress, llvm::Value *Idx,
+ QualType type, AlignmentSource alignSource) {
LValue R;
R.LVType = VectorElt;
- R.V = Vec;
+ R.V = vecAddress.getPointer();
R.VectorIdx = Idx;
- R.Initialize(type, type.getQualifiers(), Alignment);
+ R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
+ alignSource);
return R;
}
- static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts,
- QualType type, CharUnits Alignment) {
+ static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts,
+ QualType type, AlignmentSource alignSource) {
LValue R;
R.LVType = ExtVectorElt;
- R.V = Vec;
+ R.V = vecAddress.getPointer();
R.VectorElts = Elts;
- R.Initialize(type, type.getQualifiers(), Alignment);
+ R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(),
+ alignSource);
return R;
}
@@ -332,29 +411,28 @@ public:
/// bit-field refers to.
/// \param Info - The information describing how to perform the bit-field
/// access.
- static LValue MakeBitfield(llvm::Value *Addr,
+ static LValue MakeBitfield(Address Addr,
const CGBitFieldInfo &Info,
- QualType type, CharUnits Alignment) {
+ QualType type,
+ AlignmentSource alignSource) {
LValue R;
R.LVType = BitField;
- R.V = Addr;
+ R.V = Addr.getPointer();
R.BitFieldInfo = &Info;
- R.Initialize(type, type.getQualifiers(), Alignment);
+ R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), alignSource);
return R;
}
- static LValue MakeGlobalReg(llvm::Value *Reg,
- QualType type,
- CharUnits Alignment) {
+ static LValue MakeGlobalReg(Address Reg, QualType type) {
LValue R;
R.LVType = GlobalReg;
- R.V = Reg;
- R.Initialize(type, type.getQualifiers(), Alignment);
+ R.V = Reg.getPointer();
+ R.Initialize(type, type.getQualifiers(), Reg.getAlignment(),
+ AlignmentSource::Decl);
return R;
}
RValue asAggregateRValue() const {
- // FIMXE: Alignment
return RValue::getAggregate(getAddress(), isVolatileQualified());
}
};
@@ -407,7 +485,7 @@ public:
/// ignored - Returns an aggregate value slot indicating that the
/// aggregate value is being ignored.
static AggValueSlot ignored() {
- return forAddr(nullptr, CharUnits(), Qualifiers(), IsNotDestructed,
+ return forAddr(Address::invalid(), Qualifiers(), IsNotDestructed,
DoesNotNeedGCBarriers, IsNotAliased);
}
@@ -421,15 +499,20 @@ public:
/// for calling destructors on this object
/// \param needsGC - true if the slot is potentially located
/// somewhere that ObjC GC calls should be emitted for
- static AggValueSlot forAddr(llvm::Value *addr, CharUnits align,
+ static AggValueSlot forAddr(Address addr,
Qualifiers quals,
IsDestructed_t isDestructed,
NeedsGCBarriers_t needsGC,
IsAliased_t isAliased,
IsZeroed_t isZeroed = IsNotZeroed) {
AggValueSlot AV;
- AV.Addr = addr;
- AV.Alignment = align.getQuantity();
+ if (addr.isValid()) {
+ AV.Addr = addr.getPointer();
+ AV.Alignment = addr.getAlignment().getQuantity();
+ } else {
+ AV.Addr = nullptr;
+ AV.Alignment = 0;
+ }
AV.Quals = quals;
AV.DestructedFlag = isDestructed;
AV.ObjCGCFlag = needsGC;
@@ -443,7 +526,7 @@ public:
NeedsGCBarriers_t needsGC,
IsAliased_t isAliased,
IsZeroed_t isZeroed = IsNotZeroed) {
- return forAddr(LV.getAddress(), LV.getAlignment(),
+ return forAddr(LV.getAddress(),
LV.getQuals(), isDestructed, needsGC, isAliased, isZeroed);
}
@@ -471,11 +554,15 @@ public:
NeedsGCBarriers_t requiresGCollection() const {
return NeedsGCBarriers_t(ObjCGCFlag);
}
-
- llvm::Value *getAddr() const {
+
+ llvm::Value *getPointer() const {
return Addr;
}
+ Address getAddress() const {
+ return Address(Addr, getAlignment());
+ }
+
bool isIgnored() const {
return Addr == nullptr;
}
@@ -488,9 +575,12 @@ public:
return IsAliased_t(AliasedFlag);
}
- // FIXME: Alignment?
RValue asRValue() const {
- return RValue::getAggregate(getAddr(), isVolatile());
+ if (isIgnored()) {
+ return RValue::getIgnored();
+ } else {
+ return RValue::getAggregate(getAddress(), isVolatile());
+ }
}
void setZeroed(bool V = true) { ZeroedFlag = V; }
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp
index 755e8aa..643c996 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp
@@ -26,23 +26,16 @@
using namespace clang;
using namespace CodeGen;
-CodeGenABITypes::CodeGenABITypes(ASTContext &C,
- llvm::Module &M,
- const llvm::DataLayout &TD,
+CodeGenABITypes::CodeGenABITypes(ASTContext &C, llvm::Module &M,
CoverageSourceInfo *CoverageInfo)
- : CGO(new CodeGenOptions),
- HSO(new HeaderSearchOptions),
- PPO(new PreprocessorOptions),
- CGM(new CodeGen::CodeGenModule(C, *HSO, *PPO, *CGO,
- M, TD, C.getDiagnostics(),
- CoverageInfo)) {
-}
+ : CGO(new CodeGenOptions), HSO(new HeaderSearchOptions),
+ PPO(new PreprocessorOptions),
+ CGM(new CodeGen::CodeGenModule(C, *HSO, *PPO, *CGO, M, C.getDiagnostics(),
+ CoverageInfo)) {}
-CodeGenABITypes::~CodeGenABITypes()
-{
- delete CGO;
- delete CGM;
-}
+// Explicitly out-of-line because ~CodeGenModule() is private but
+// CodeGenABITypes.h is part of clang's API.
+CodeGenABITypes::~CodeGenABITypes() = default;
const CGFunctionInfo &
CodeGenABITypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
@@ -51,8 +44,9 @@ CodeGenABITypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
}
const CGFunctionInfo &
-CodeGenABITypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty) {
- return CGM->getTypes().arrangeFreeFunctionType(Ty);
+CodeGenABITypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty,
+ const FunctionDecl *FD) {
+ return CGM->getTypes().arrangeFreeFunctionType(Ty, FD);
}
const CGFunctionInfo &
@@ -62,15 +56,14 @@ CodeGenABITypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty) {
const CGFunctionInfo &
CodeGenABITypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
- const FunctionProtoType *FTP) {
- return CGM->getTypes().arrangeCXXMethodType(RD, FTP);
+ const FunctionProtoType *FTP,
+ const CXXMethodDecl *MD) {
+ return CGM->getTypes().arrangeCXXMethodType(RD, FTP, MD);
}
-const CGFunctionInfo &
-CodeGenABITypes::arrangeFreeFunctionCall(CanQualType returnType,
- ArrayRef<CanQualType> argTypes,
- FunctionType::ExtInfo info,
- RequiredArgs args) {
+const CGFunctionInfo &CodeGenABITypes::arrangeFreeFunctionCall(
+ CanQualType returnType, ArrayRef<CanQualType> argTypes,
+ FunctionType::ExtInfo info, RequiredArgs args) {
return CGM->getTypes().arrangeLLVMFunctionInfo(
returnType, /*IsInstanceMethod=*/false, /*IsChainCall=*/false, argTypes,
info, args);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
index 0e7b6d8..0a670ab 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp
@@ -53,40 +53,47 @@ namespace clang {
std::unique_ptr<CodeGenerator> Gen;
- std::unique_ptr<llvm::Module> TheModule, LinkModule;
+ std::unique_ptr<llvm::Module> TheModule;
+ SmallVector<std::pair<unsigned, std::unique_ptr<llvm::Module>>, 4>
+ LinkModules;
+
+ // This is here so that the diagnostic printer knows the module a diagnostic
+ // refers to.
+ llvm::Module *CurLinkModule = nullptr;
public:
- BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
- const HeaderSearchOptions &HeaderSearchOpts,
- const PreprocessorOptions &PPOpts,
- const CodeGenOptions &CodeGenOpts,
- const TargetOptions &TargetOpts,
- const LangOptions &LangOpts, bool TimePasses,
- const std::string &InFile, llvm::Module *LinkModule,
- raw_pwrite_stream *OS, LLVMContext &C,
- CoverageSourceInfo *CoverageInfo = nullptr)
+ BackendConsumer(
+ BackendAction Action, DiagnosticsEngine &Diags,
+ const HeaderSearchOptions &HeaderSearchOpts,
+ const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts,
+ const TargetOptions &TargetOpts, const LangOptions &LangOpts,
+ bool TimePasses, const std::string &InFile,
+ const SmallVectorImpl<std::pair<unsigned, llvm::Module *>> &LinkModules,
+ raw_pwrite_stream *OS, LLVMContext &C,
+ CoverageSourceInfo *CoverageInfo = nullptr)
: Diags(Diags), Action(Action), CodeGenOpts(CodeGenOpts),
TargetOpts(TargetOpts), LangOpts(LangOpts), AsmOutStream(OS),
Context(nullptr), LLVMIRGeneration("LLVM IR Generation Time"),
Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts,
- CodeGenOpts, C, CoverageInfo)),
- LinkModule(LinkModule) {
+ CodeGenOpts, C, CoverageInfo)) {
llvm::TimePassesIsEnabled = TimePasses;
+ for (auto &I : LinkModules)
+ this->LinkModules.push_back(
+ std::make_pair(I.first, std::unique_ptr<llvm::Module>(I.second)));
}
-
std::unique_ptr<llvm::Module> takeModule() { return std::move(TheModule); }
- llvm::Module *takeLinkModule() { return LinkModule.release(); }
+ void releaseLinkModules() {
+ for (auto &I : LinkModules)
+ I.second.release();
+ }
void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override {
Gen->HandleCXXStaticMemberVarInstantiation(VD);
}
void Initialize(ASTContext &Ctx) override {
- if (Context) {
- assert(Context == &Ctx);
- return;
- }
-
+ assert(!Context && "initialized multiple times");
+
Context = &Ctx;
if (llvm::TimePassesIsEnabled)
@@ -158,14 +165,6 @@ namespace clang {
assert(TheModule.get() == M &&
"Unexpected module change during IR generation");
- // Link LinkModule into this module if present, preserving its validity.
- if (LinkModule) {
- if (Linker::LinkModules(
- M, LinkModule.get(),
- [=](const DiagnosticInfo &DI) { linkerDiagnosticHandler(DI); }))
- return;
- }
-
// Install an inline asm handler so that diagnostics get printed through
// our diagnostics hooks.
LLVMContext &Ctx = TheModule->getContext();
@@ -179,8 +178,16 @@ namespace clang {
void *OldDiagnosticContext = Ctx.getDiagnosticContext();
Ctx.setDiagnosticHandler(DiagnosticHandler, this);
+ // Link LinkModule into this module if present, preserving its validity.
+ for (auto &I : LinkModules) {
+ unsigned LinkFlags = I.first;
+ CurLinkModule = I.second.get();
+ if (Linker::linkModules(*M, std::move(I.second), LinkFlags))
+ return;
+ }
+
EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
- C.getTargetInfo().getTargetDescription(),
+ C.getTargetInfo().getDataLayoutString(),
TheModule.get(), Action, AsmOutStream);
Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
@@ -226,8 +233,6 @@ namespace clang {
((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc);
}
- void linkerDiagnosticHandler(const llvm::DiagnosticInfo &DI);
-
static void DiagnosticHandler(const llvm::DiagnosticInfo &DI,
void *Context) {
((BackendConsumer *)Context)->DiagnosticHandlerImpl(DI);
@@ -256,6 +261,10 @@ namespace clang {
const llvm::DiagnosticInfoOptimizationRemarkMissed &D);
void OptimizationRemarkHandler(
const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D);
+ void OptimizationRemarkHandler(
+ const llvm::DiagnosticInfoOptimizationRemarkAnalysisFPCommute &D);
+ void OptimizationRemarkHandler(
+ const llvm::DiagnosticInfoOptimizationRemarkAnalysisAliasing &D);
void OptimizationFailureHandler(
const llvm::DiagnosticInfoOptimizationFailure &D);
};
@@ -333,8 +342,7 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here);
// Convert the SMDiagnostic ranges into SourceRange and attach them
// to the diagnostic.
- for (unsigned i = 0, e = D.getRanges().size(); i != e; ++i) {
- std::pair<unsigned, unsigned> Range = D.getRanges()[i];
+ for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) {
unsigned Column = D.getColumnNo();
B << SourceRange(Loc.getLocWithOffset(Range.first - Column),
Loc.getLocWithOffset(Range.second - Column));
@@ -492,33 +500,46 @@ void BackendConsumer::OptimizationRemarkHandler(
void BackendConsumer::OptimizationRemarkHandler(
const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D) {
- // Optimization analysis remarks are active only if the -Rpass-analysis
- // flag has a regular expression that matches the name of the pass
- // name in \p D.
- if (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
- CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))
+ // Optimization analysis remarks are active if the pass name is set to
+ // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
+ // regular expression that matches the name of the pass name in \p D.
+
+ if (D.getPassName() == llvm::DiagnosticInfo::AlwaysPrint ||
+ (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
+ CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
EmitOptimizationMessage(
D, diag::remark_fe_backend_optimization_remark_analysis);
}
-void BackendConsumer::OptimizationFailureHandler(
- const llvm::DiagnosticInfoOptimizationFailure &D) {
- EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure);
+void BackendConsumer::OptimizationRemarkHandler(
+ const llvm::DiagnosticInfoOptimizationRemarkAnalysisFPCommute &D) {
+ // Optimization analysis remarks are active if the pass name is set to
+ // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
+ // regular expression that matches the name of the pass name in \p D.
+
+ if (D.getPassName() == llvm::DiagnosticInfo::AlwaysPrint ||
+ (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
+ CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
+ EmitOptimizationMessage(
+ D, diag::remark_fe_backend_optimization_remark_analysis_fpcommute);
}
-void BackendConsumer::linkerDiagnosticHandler(const DiagnosticInfo &DI) {
- if (DI.getSeverity() != DS_Error)
- return;
-
- std::string MsgStorage;
- {
- raw_string_ostream Stream(MsgStorage);
- DiagnosticPrinterRawOStream DP(Stream);
- DI.print(DP);
- }
+void BackendConsumer::OptimizationRemarkHandler(
+ const llvm::DiagnosticInfoOptimizationRemarkAnalysisAliasing &D) {
+ // Optimization analysis remarks are active if the pass name is set to
+ // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
+ // regular expression that matches the name of the pass name in \p D.
+
+ if (D.getPassName() == llvm::DiagnosticInfo::AlwaysPrint ||
+ (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
+ CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
+ EmitOptimizationMessage(
+ D, diag::remark_fe_backend_optimization_remark_analysis_aliasing);
+}
- Diags.Report(diag::err_fe_cannot_link_module)
- << LinkModule->getModuleIdentifier() << MsgStorage;
+void BackendConsumer::OptimizationFailureHandler(
+ const llvm::DiagnosticInfoOptimizationFailure &D) {
+ EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure);
}
/// \brief This function is invoked when the backend needs
@@ -538,6 +559,13 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
return;
ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
break;
+ case DK_Linker:
+ assert(CurLinkModule);
+ // FIXME: stop eating the warnings and notes.
+ if (Severity != DS_Error)
+ return;
+ DiagID = diag::err_fe_cannot_link_module;
+ break;
case llvm::DK_OptimizationRemark:
// Optimization remarks are always handled completely by this
// handler. There is no generic way of emitting them.
@@ -554,6 +582,18 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
OptimizationRemarkHandler(
cast<DiagnosticInfoOptimizationRemarkAnalysis>(DI));
return;
+ case llvm::DK_OptimizationRemarkAnalysisFPCommute:
+ // Optimization remarks are always handled completely by this
+ // handler. There is no generic way of emitting them.
+ OptimizationRemarkHandler(
+ cast<DiagnosticInfoOptimizationRemarkAnalysisFPCommute>(DI));
+ return;
+ case llvm::DK_OptimizationRemarkAnalysisAliasing:
+ // Optimization remarks are always handled completely by this
+ // handler. There is no generic way of emitting them.
+ OptimizationRemarkHandler(
+ cast<DiagnosticInfoOptimizationRemarkAnalysisAliasing>(DI));
+ return;
case llvm::DK_OptimizationFailure:
// Optimization failures are always handled completely by this
// handler.
@@ -571,6 +611,12 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
DI.print(DP);
}
+ if (DiagID == diag::err_fe_cannot_link_module) {
+ Diags.Report(diag::err_fe_cannot_link_module)
+ << CurLinkModule->getModuleIdentifier() << MsgStorage;
+ return;
+ }
+
// Report the backend message using the usual diagnostic mechanism.
FullSourceLoc Loc;
Diags.Report(Loc, DiagID).AddString(MsgStorage);
@@ -578,9 +624,8 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
#undef ComputeDiagID
CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
- : Act(_Act), LinkModule(nullptr),
- VMContext(_VMContext ? _VMContext : new LLVMContext),
- OwnsVMContext(!_VMContext) {}
+ : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext),
+ OwnsVMContext(!_VMContext) {}
CodeGenAction::~CodeGenAction() {
TheModule.reset();
@@ -595,9 +640,9 @@ void CodeGenAction::EndSourceFileAction() {
if (!getCompilerInstance().hasASTConsumer())
return;
- // If we were given a link module, release consumer's ownership of it.
- if (LinkModule)
- BEConsumer->takeLinkModule();
+ // Take back ownership of link modules we passed to consumer.
+ if (!LinkModules.empty())
+ BEConsumer->releaseLinkModules();
// Steal the module from the consumer.
TheModule = BEConsumer->takeModule();
@@ -639,28 +684,29 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
if (BA != Backend_EmitNothing && !OS)
return nullptr;
- llvm::Module *LinkModuleToUse = LinkModule;
-
- // If we were not given a link module, and the user requested that one be
- // loaded from bitcode, do so now.
- const std::string &LinkBCFile = CI.getCodeGenOpts().LinkBitcodeFile;
- if (!LinkModuleToUse && !LinkBCFile.empty()) {
- auto BCBuf = CI.getFileManager().getBufferForFile(LinkBCFile);
- if (!BCBuf) {
- CI.getDiagnostics().Report(diag::err_cannot_open_file)
- << LinkBCFile << BCBuf.getError().message();
- return nullptr;
- }
+ // Load bitcode modules to link with, if we need to.
+ if (LinkModules.empty())
+ for (auto &I : CI.getCodeGenOpts().LinkBitcodeFiles) {
+ const std::string &LinkBCFile = I.second;
+
+ auto BCBuf = CI.getFileManager().getBufferForFile(LinkBCFile);
+ if (!BCBuf) {
+ CI.getDiagnostics().Report(diag::err_cannot_open_file)
+ << LinkBCFile << BCBuf.getError().message();
+ LinkModules.clear();
+ return nullptr;
+ }
- ErrorOr<std::unique_ptr<llvm::Module>> ModuleOrErr =
- getLazyBitcodeModule(std::move(*BCBuf), *VMContext);
- if (std::error_code EC = ModuleOrErr.getError()) {
- CI.getDiagnostics().Report(diag::err_cannot_open_file)
- << LinkBCFile << EC.message();
- return nullptr;
+ ErrorOr<std::unique_ptr<llvm::Module>> ModuleOrErr =
+ getLazyBitcodeModule(std::move(*BCBuf), *VMContext);
+ if (std::error_code EC = ModuleOrErr.getError()) {
+ CI.getDiagnostics().Report(diag::err_cannot_open_file) << LinkBCFile
+ << EC.message();
+ LinkModules.clear();
+ return nullptr;
+ }
+ addLinkModule(ModuleOrErr.get().release(), I.first);
}
- LinkModuleToUse = ModuleOrErr.get().release();
- }
CoverageSourceInfo *CoverageInfo = nullptr;
// Add the preprocessor callback only when the coverage mapping is generated.
@@ -669,11 +715,12 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
CI.getPreprocessor().addPPCallbacks(
std::unique_ptr<PPCallbacks>(CoverageInfo));
}
+
std::unique_ptr<BackendConsumer> Result(new BackendConsumer(
BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(),
CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
- CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile,
- LinkModuleToUse, OS, *VMContext, CoverageInfo));
+ CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, LinkModules,
+ OS, *VMContext, CoverageInfo));
BEConsumer = Result.get();
return std::move(Result);
}
@@ -735,7 +782,7 @@ void CodeGenAction::ExecuteAction() {
LLVMContext &Ctx = TheModule->getContext();
Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler);
EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), TargetOpts,
- CI.getLangOpts(), CI.getTarget().getTargetDescription(),
+ CI.getLangOpts(), CI.getTarget().getDataLayoutString(),
TheModule.get(), BA, OS);
return;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
index ec3c75c..e38ff0a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGBlocks.h"
#include "CGCleanup.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
@@ -24,9 +25,11 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
@@ -36,12 +39,14 @@ using namespace CodeGen;
CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
: CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()),
- Builder(cgm.getModule().getContext(), llvm::ConstantFolder(),
+ Builder(cgm, cgm.getModule().getContext(), llvm::ConstantFolder(),
CGBuilderInserterTy(this)),
- CurFn(nullptr), CapturedStmtInfo(nullptr),
+ CurFn(nullptr), ReturnValue(Address::invalid()),
+ CapturedStmtInfo(nullptr),
SanOpts(CGM.getLangOpts().Sanitize), IsSanitizerScope(false),
CurFuncIsThunk(false), AutoreleaseResult(false), SawAsmBlock(false),
- IsOutlinedSEHHelper(false), BlockInfo(nullptr), BlockPointer(nullptr),
+ IsOutlinedSEHHelper(false),
+ BlockInfo(nullptr), BlockPointer(nullptr),
LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr),
NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr),
ExceptionSlot(nullptr), EHSelectorSlot(nullptr),
@@ -51,7 +56,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0),
NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr),
CXXABIThisValue(nullptr), CXXThisValue(nullptr),
- CXXDefaultInitExprThis(nullptr), CXXStructorImplicitParamDecl(nullptr),
+ CXXStructorImplicitParamDecl(nullptr),
CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr),
CurLexicalScope(nullptr), TerminateLandingPad(nullptr),
TerminateHandler(nullptr), TrapBB(nullptr) {
@@ -74,7 +79,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
if (CGM.getCodeGenOpts().ReciprocalMath) {
FMF.setAllowReciprocal();
}
- Builder.SetFastMathFlags(FMF);
+ Builder.setFastMathFlags(FMF);
}
CodeGenFunction::~CodeGenFunction() {
@@ -91,18 +96,69 @@ CodeGenFunction::~CodeGenFunction() {
}
}
-LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
+CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T,
+ AlignmentSource *Source) {
+ return getNaturalTypeAlignment(T->getPointeeType(), Source,
+ /*forPointee*/ true);
+}
+
+CharUnits CodeGenFunction::getNaturalTypeAlignment(QualType T,
+ AlignmentSource *Source,
+ bool forPointeeType) {
+ // Honor alignment typedef attributes even on incomplete types.
+ // We also honor them straight for C++ class types, even as pointees;
+ // there's an expressivity gap here.
+ if (auto TT = T->getAs<TypedefType>()) {
+ if (auto Align = TT->getDecl()->getMaxAlignment()) {
+ if (Source) *Source = AlignmentSource::AttributedType;
+ return getContext().toCharUnitsFromBits(Align);
+ }
+ }
+
+ if (Source) *Source = AlignmentSource::Type;
+
CharUnits Alignment;
- if (CGM.getCXXABI().isTypeInfoCalculable(T)) {
- Alignment = getContext().getTypeAlignInChars(T);
- unsigned MaxAlign = getContext().getLangOpts().MaxTypeAlign;
- if (MaxAlign && Alignment.getQuantity() > MaxAlign &&
- !getContext().isAlignmentRequired(T))
- Alignment = CharUnits::fromQuantity(MaxAlign);
+ if (T->isIncompleteType()) {
+ Alignment = CharUnits::One(); // Shouldn't be used, but pessimistic is best.
+ } else {
+ // For C++ class pointees, we don't know whether we're pointing at a
+ // base or a complete object, so we generally need to use the
+ // non-virtual alignment.
+ const CXXRecordDecl *RD;
+ if (forPointeeType && (RD = T->getAsCXXRecordDecl())) {
+ Alignment = CGM.getClassPointerAlignment(RD);
+ } else {
+ Alignment = getContext().getTypeAlignInChars(T);
+ }
+
+ // Cap to the global maximum type alignment unless the alignment
+ // was somehow explicit on the type.
+ if (unsigned MaxAlign = getLangOpts().MaxTypeAlign) {
+ if (Alignment.getQuantity() > MaxAlign &&
+ !getContext().isAlignmentRequired(T))
+ Alignment = CharUnits::fromQuantity(MaxAlign);
+ }
}
- return LValue::MakeAddr(V, T, Alignment, getContext(), CGM.getTBAAInfo(T));
+ return Alignment;
}
+LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
+ AlignmentSource AlignSource;
+ CharUnits Alignment = getNaturalTypeAlignment(T, &AlignSource);
+ return LValue::MakeAddr(Address(V, Alignment), T, getContext(), AlignSource,
+ CGM.getTBAAInfo(T));
+}
+
+/// Given a value of type T* that may not be to a complete object,
+/// construct an l-value with the natural pointee alignment of T.
+LValue
+CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) {
+ AlignmentSource AlignSource;
+ CharUnits Align = getNaturalTypeAlignment(T, &AlignSource, /*pointee*/ true);
+ return MakeAddrLValue(Address(V, Align), T, AlignSource);
+}
+
+
llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) {
return CGM.getTypes().ConvertTypeForMem(T);
}
@@ -139,6 +195,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) {
case Type::FunctionNoProto:
case Type::Enum:
case Type::ObjCObjectPointer:
+ case Type::Pipe:
return TEK_Scalar;
// Complexes.
@@ -295,7 +352,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
EscapeArgs[Pair.second] = Pair.first;
llvm::Function *FrameEscapeFn = llvm::Intrinsic::getDeclaration(
&CGM.getModule(), llvm::Intrinsic::localescape);
- CGBuilderTy(AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs);
+ CGBuilderTy(*this, AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs);
}
// Remove the AllocaInsertPt instruction, which is just a convenience for us.
@@ -455,7 +512,8 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
typeQuals += typeQuals.empty() ? "volatile" : " volatile";
} else {
uint32_t AddrSpc = 0;
- if (ty->isImageType())
+ bool isPipe = ty->isPipeType();
+ if (ty->isImageType() || isPipe)
AddrSpc =
CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
@@ -463,7 +521,11 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
llvm::ConstantAsMetadata::get(Builder.getInt32(AddrSpc)));
// Get argument type name.
- std::string typeName = ty.getUnqualifiedType().getAsString(Policy);
+ std::string typeName;
+ if (isPipe)
+ typeName = cast<PipeType>(ty)->getElementType().getAsString(Policy);
+ else
+ typeName = ty.getUnqualifiedType().getAsString(Policy);
// Turn "unsigned type" to "utype"
std::string::size_type pos = typeName.find("unsigned");
@@ -472,7 +534,12 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
argTypeNames.push_back(llvm::MDString::get(Context, typeName));
- std::string baseTypeName =
+ std::string baseTypeName;
+ if (isPipe)
+ baseTypeName =
+ cast<PipeType>(ty)->getElementType().getCanonicalType().getAsString(Policy);
+ else
+ baseTypeName =
ty.getUnqualifiedType().getCanonicalType().getAsString(Policy);
// Turn "unsigned type" to "utype"
@@ -487,12 +554,16 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
typeQuals = "const";
if (ty.isVolatileQualified())
typeQuals += typeQuals.empty() ? "volatile" : " volatile";
+ if (isPipe)
+ typeQuals = "pipe";
}
argTypeQuals.push_back(llvm::MDString::get(Context, typeQuals));
- // Get image access qualifier:
- if (ty->isImageType()) {
+ // Get image and pipe access qualifier:
+ // FIXME: now image and pipe share the same access qualifier maybe we can
+ // refine it to OpenCL access qualifier and also handle write_read
+ if (ty->isImageType()|| ty->isPipeType()) {
const OpenCLImageAccessAttr *A = parm->getAttr<OpenCLImageAccessAttr>();
if (A && A->isWriteOnly())
accessQuals.push_back(llvm::MDString::get(Context, "write_only"));
@@ -660,6 +731,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
}
}
+ // If we're in C++ mode and the function name is "main", it is guaranteed
+ // to be norecurse by the standard (3.6.1.3 "The function main shall not be
+ // used within a program").
+ if (getLangOpts().CPlusPlus)
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
+ if (FD->isMain())
+ Fn->addFnAttr(llvm::Attribute::NoRecurse);
+
llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn);
// Create a marker to make it easy to insert allocas into the entryblock
@@ -696,7 +775,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (RetTy->isVoidType()) {
// Void type; nothing to return.
- ReturnValue = nullptr;
+ ReturnValue = Address::invalid();
// Count the implicit return.
if (!endsWithReturn(D))
@@ -708,15 +787,16 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
auto AI = CurFn->arg_begin();
if (CurFnInfo->getReturnInfo().isSRetAfterThis())
++AI;
- ReturnValue = AI;
+ ReturnValue = Address(&*AI, CurFnInfo->getReturnInfo().getIndirectAlign());
} else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::InAlloca &&
!hasScalarEvaluationKind(CurFnInfo->getReturnType())) {
// Load the sret pointer from the argument struct and return into that.
unsigned Idx = CurFnInfo->getReturnInfo().getInAllocaFieldIndex();
llvm::Function::arg_iterator EI = CurFn->arg_end();
--EI;
- llvm::Value *Addr = Builder.CreateStructGEP(nullptr, EI, Idx);
- ReturnValue = Builder.CreateLoad(Addr, "agg.result");
+ llvm::Value *Addr = Builder.CreateStructGEP(nullptr, &*EI, Idx);
+ Addr = Builder.CreateAlignedLoad(Addr, getPointerAlign(), "agg.result");
+ ReturnValue = Address(Addr, getNaturalTypeAlignment(RetTy));
} else {
ReturnValue = CreateIRTemp(RetTy, "retval");
@@ -826,15 +906,11 @@ static void TryMarkNoThrow(llvm::Function *F) {
// can't do this on functions that can be overwritten.
if (F->mayBeOverridden()) return;
- for (llvm::Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
- for (llvm::BasicBlock::iterator
- BI = FI->begin(), BE = FI->end(); BI != BE; ++BI)
- if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(&*BI)) {
- if (!Call->doesNotThrow())
- return;
- } else if (isa<llvm::ResumeInst>(&*BI)) {
+ for (llvm::BasicBlock &BB : *F)
+ for (llvm::Instruction &I : BB)
+ if (I.mayThrow())
return;
- }
+
F->setDoesNotThrow();
}
@@ -859,7 +935,18 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
CGM.getCXXABI().buildThisParam(*this, Args);
}
- Args.append(FD->param_begin(), FD->param_end());
+ for (auto *Param : FD->params()) {
+ Args.push_back(Param);
+ if (!Param->hasAttr<PassObjectSizeAttr>())
+ continue;
+
+ IdentifierInfo *NoID = nullptr;
+ auto *Implicit = ImplicitParamDecl::Create(
+ getContext(), Param->getDeclContext(), Param->getLocation(), NoID,
+ getContext().getSizeType());
+ SizeArguments[Param] = Implicit;
+ Args.push_back(Implicit);
+ }
if (MD && (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)))
CGM.getCXXABI().addImplicitStructorParams(*this, ResTy, Args);
@@ -885,8 +972,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
// Generate the body of the function.
- PGO.checkGlobalDecl(GD);
- PGO.assignRegionCounters(GD.getDecl(), CurFn);
+ PGO.assignRegionCounters(GD, CurFn);
if (isa<CXXDestructorDecl>(FD))
EmitDestructorBody(Args);
else if (isa<CXXConstructorDecl>(FD))
@@ -1207,6 +1293,22 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
return;
}
+ // If the branch has a condition wrapped by __builtin_unpredictable,
+ // create metadata that specifies that the branch is unpredictable.
+ // Don't bother if not optimizing because that metadata would not be used.
+ llvm::MDNode *Unpredictable = nullptr;
+ if (CGM.getCodeGenOpts().OptimizationLevel != 0) {
+ if (const CallExpr *Call = dyn_cast<CallExpr>(Cond)) {
+ const Decl *TargetDecl = Call->getCalleeDecl();
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
+ if (FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
+ llvm::MDBuilder MDHelper(getLLVMContext());
+ Unpredictable = MDHelper.createUnpredictable();
+ }
+ }
+ }
+ }
+
// Create branch weights based on the number of times we get here and the
// number of times the condition should be true.
uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
@@ -1219,7 +1321,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
ApplyDebugLocation DL(*this, Cond);
CondV = EvaluateExprAsBool(Cond);
}
- Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights);
+ Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
}
/// ErrorUnsupported - Print out an error that codegen doesn't support the
@@ -1236,20 +1338,18 @@ void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type) {
/// base element of the array
/// \param sizeInChars - the total size of the VLA, in chars
static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType,
- llvm::Value *dest, llvm::Value *src,
+ Address dest, Address src,
llvm::Value *sizeInChars) {
- std::pair<CharUnits,CharUnits> baseSizeAndAlign
- = CGF.getContext().getTypeInfoInChars(baseType);
-
CGBuilderTy &Builder = CGF.Builder;
+ CharUnits baseSize = CGF.getContext().getTypeSizeInChars(baseType);
llvm::Value *baseSizeInChars
- = llvm::ConstantInt::get(CGF.IntPtrTy, baseSizeAndAlign.first.getQuantity());
-
- llvm::Type *i8p = Builder.getInt8PtrTy();
+ = llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity());
- llvm::Value *begin = Builder.CreateBitCast(dest, i8p, "vla.begin");
- llvm::Value *end = Builder.CreateInBoundsGEP(dest, sizeInChars, "vla.end");
+ Address begin =
+ Builder.CreateElementBitCast(dest, CGF.Int8Ty, "vla.begin");
+ llvm::Value *end =
+ Builder.CreateInBoundsGEP(begin.getPointer(), sizeInChars, "vla.end");
llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock();
llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop");
@@ -1259,17 +1359,19 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType,
// count must be nonzero.
CGF.EmitBlock(loopBB);
- llvm::PHINode *cur = Builder.CreatePHI(i8p, 2, "vla.cur");
- cur->addIncoming(begin, originBB);
+ llvm::PHINode *cur = Builder.CreatePHI(begin.getType(), 2, "vla.cur");
+ cur->addIncoming(begin.getPointer(), originBB);
+
+ CharUnits curAlign =
+ dest.getAlignment().alignmentOfArrayElement(baseSize);
// memcpy the individual element bit-pattern.
- Builder.CreateMemCpy(cur, src, baseSizeInChars,
- baseSizeAndAlign.second.getQuantity(),
+ Builder.CreateMemCpy(Address(cur, curAlign), src, baseSizeInChars,
/*volatile*/ false);
// Go to the next element.
- llvm::Value *next = Builder.CreateConstInBoundsGEP1_32(Builder.getInt8Ty(),
- cur, 1, "vla.next");
+ llvm::Value *next =
+ Builder.CreateInBoundsGEP(CGF.Int8Ty, cur, baseSizeInChars, "vla.next");
// Leave if that's the end of the VLA.
llvm::Value *done = Builder.CreateICmpEQ(next, end, "vla-init.isdone");
@@ -1280,7 +1382,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType,
}
void
-CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
+CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) {
// Ignore empty classes in C++.
if (getLangOpts().CPlusPlus) {
if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -1290,23 +1392,17 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
}
// Cast the dest ptr to the appropriate i8 pointer type.
- unsigned DestAS =
- cast<llvm::PointerType>(DestPtr->getType())->getAddressSpace();
- llvm::Type *BP = Builder.getInt8PtrTy(DestAS);
- if (DestPtr->getType() != BP)
- DestPtr = Builder.CreateBitCast(DestPtr, BP);
+ if (DestPtr.getElementType() != Int8Ty)
+ DestPtr = Builder.CreateElementBitCast(DestPtr, Int8Ty);
// Get size and alignment info for this aggregate.
- std::pair<CharUnits, CharUnits> TypeInfo =
- getContext().getTypeInfoInChars(Ty);
- CharUnits Size = TypeInfo.first;
- CharUnits Align = TypeInfo.second;
+ CharUnits size = getContext().getTypeSizeInChars(Ty);
llvm::Value *SizeVal;
const VariableArrayType *vla;
// Don't bother emitting a zero-byte memset.
- if (Size.isZero()) {
+ if (size.isZero()) {
// But note that getTypeInfo returns 0 for a VLA.
if (const VariableArrayType *vlaType =
dyn_cast_or_null<VariableArrayType>(
@@ -1324,7 +1420,7 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
return;
}
} else {
- SizeVal = CGM.getSize(Size);
+ SizeVal = CGM.getSize(size);
vla = nullptr;
}
@@ -1343,21 +1439,22 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
/*isConstant=*/true,
llvm::GlobalVariable::PrivateLinkage,
NullConstant, Twine());
- llvm::Value *SrcPtr =
- Builder.CreateBitCast(NullVariable, Builder.getInt8PtrTy());
+ CharUnits NullAlign = DestPtr.getAlignment();
+ NullVariable->setAlignment(NullAlign.getQuantity());
+ Address SrcPtr(Builder.CreateBitCast(NullVariable, Builder.getInt8PtrTy()),
+ NullAlign);
if (vla) return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal);
// Get and call the appropriate llvm.memcpy overload.
- Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, Align.getQuantity(), false);
+ Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, false);
return;
}
// Otherwise, just memset the whole thing to zero. This is legal
// because in LLVM, all default initializers (other than the ones we just
// handled above) are guaranteed to have a bit pattern of all zeros.
- Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal,
- Align.getQuantity(), false);
+ Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, false);
}
llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelDecl *L) {
@@ -1376,7 +1473,7 @@ llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
// If we already made the indirect branch for indirect goto, return its block.
if (IndirectBranch) return IndirectBranch->getParent();
- CGBuilderTy TmpBuilder(createBasicBlock("indirectgoto"));
+ CGBuilderTy TmpBuilder(*this, createBasicBlock("indirectgoto"));
// Create the PHI node that indirect gotos will add entries to.
llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, 0,
@@ -1391,7 +1488,7 @@ llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
/// element type and a properly-typed first element pointer.
llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType,
QualType &baseType,
- llvm::Value *&addr) {
+ Address &addr) {
const ArrayType *arrayType = origArrayType;
// If it's a VLA, we have to load the stored size. Note that
@@ -1430,8 +1527,7 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType,
QualType eltType;
llvm::ArrayType *llvmArrayType =
- dyn_cast<llvm::ArrayType>(
- cast<llvm::PointerType>(addr->getType())->getElementType());
+ dyn_cast<llvm::ArrayType>(addr.getElementType());
while (llvmArrayType) {
assert(isa<ConstantArrayType>(arrayType));
assert(cast<ConstantArrayType>(arrayType)->getSize().getZExtValue()
@@ -1459,12 +1555,13 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType,
arrayType = getContext().getAsArrayType(eltType);
}
- unsigned AddressSpace = addr->getType()->getPointerAddressSpace();
- llvm::Type *BaseType = ConvertType(eltType)->getPointerTo(AddressSpace);
- addr = Builder.CreateBitCast(addr, BaseType, "array.begin");
+ llvm::Type *baseType = ConvertType(eltType);
+ addr = Builder.CreateElementBitCast(addr, baseType, "array.begin");
} else {
// Create the actual GEP.
- addr = Builder.CreateInBoundsGEP(addr, gepIndices, "array.begin");
+ addr = Address(Builder.CreateInBoundsGEP(addr.getPointer(),
+ gepIndices, "array.begin"),
+ addr.getAlignment());
}
baseType = eltType;
@@ -1645,13 +1742,21 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::Atomic:
type = cast<AtomicType>(ty)->getValueType();
break;
+
+ case Type::Pipe:
+ type = cast<PipeType>(ty)->getElementType();
+ break;
}
} while (type->isVariablyModifiedType());
}
-llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) {
+Address CodeGenFunction::EmitVAListRef(const Expr* E) {
if (getContext().getBuiltinVaListType()->isArrayType())
- return EmitScalarExpr(E);
+ return EmitPointerWithAlignment(E);
+ return EmitLValue(E).getAddress();
+}
+
+Address CodeGenFunction::EmitMSVAListRef(const Expr *E) {
return EmitLValue(E).getAddress();
}
@@ -1713,9 +1818,10 @@ void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) {
I->getAnnotation(), D->getLocation());
}
-llvm::Value *CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
- llvm::Value *V) {
+Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
+ Address Addr) {
assert(D->hasAttr<AnnotateAttr>() && "no annotate attribute");
+ llvm::Value *V = Addr.getPointer();
llvm::Type *VTy = V->getType();
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::ptr_annotation,
CGM.Int8PtrTy);
@@ -1730,7 +1836,7 @@ llvm::Value *CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
V = Builder.CreateBitCast(V, VTy);
}
- return V;
+ return Address(V, Addr.getAlignment());
}
CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { }
@@ -1773,3 +1879,80 @@ template void CGBuilderInserter<PreserveNames>::InsertHelper(
llvm::Instruction *I, const llvm::Twine &Name, llvm::BasicBlock *BB,
llvm::BasicBlock::iterator InsertPt) const;
#undef PreserveNames
+
+static bool hasRequiredFeatures(const SmallVectorImpl<StringRef> &ReqFeatures,
+ CodeGenModule &CGM, const FunctionDecl *FD,
+ std::string &FirstMissing) {
+ // If there aren't any required features listed then go ahead and return.
+ if (ReqFeatures.empty())
+ return false;
+
+ // Now build up the set of caller features and verify that all the required
+ // features are there.
+ llvm::StringMap<bool> CallerFeatureMap;
+ CGM.getFunctionFeatureMap(CallerFeatureMap, FD);
+
+ // If we have at least one of the features in the feature list return
+ // true, otherwise return false.
+ return std::all_of(
+ ReqFeatures.begin(), ReqFeatures.end(), [&](StringRef Feature) {
+ SmallVector<StringRef, 1> OrFeatures;
+ Feature.split(OrFeatures, "|");
+ return std::any_of(OrFeatures.begin(), OrFeatures.end(),
+ [&](StringRef Feature) {
+ if (!CallerFeatureMap.lookup(Feature)) {
+ FirstMissing = Feature.str();
+ return false;
+ }
+ return true;
+ });
+ });
+}
+
+// Emits an error if we don't have a valid set of target features for the
+// called function.
+void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
+ const FunctionDecl *TargetDecl) {
+ // Early exit if this is an indirect call.
+ if (!TargetDecl)
+ return;
+
+ // Get the current enclosing function if it exists. If it doesn't
+ // we can't check the target features anyhow.
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl);
+ if (!FD)
+ return;
+
+ // Grab the required features for the call. For a builtin this is listed in
+ // the td file with the default cpu, for an always_inline function this is any
+ // listed cpu and any listed features.
+ unsigned BuiltinID = TargetDecl->getBuiltinID();
+ std::string MissingFeature;
+ if (BuiltinID) {
+ SmallVector<StringRef, 1> ReqFeatures;
+ const char *FeatureList =
+ CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID);
+ // Return if the builtin doesn't have any required features.
+ if (!FeatureList || StringRef(FeatureList) == "")
+ return;
+ StringRef(FeatureList).split(ReqFeatures, ",");
+ if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature))
+ CGM.getDiags().Report(E->getLocStart(), diag::err_builtin_needs_feature)
+ << TargetDecl->getDeclName()
+ << CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID);
+
+ } else if (TargetDecl->hasAttr<TargetAttr>()) {
+ // Get the required features for the callee.
+ SmallVector<StringRef, 1> ReqFeatures;
+ llvm::StringMap<bool> CalleeFeatureMap;
+ CGM.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl);
+ for (const auto &F : CalleeFeatureMap) {
+ // Only positive features are "required".
+ if (F.getValue())
+ ReqFeatures.push_back(F.getKey());
+ }
+ if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature))
+ CGM.getDiags().Report(E->getLocStart(), diag::err_function_needs_feature)
+ << FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
index f2bc402..b3d5035 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
@@ -24,6 +24,7 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/CapturedStmt.h"
@@ -80,6 +81,8 @@ class CGFunctionInfo;
class CGRecordLayout;
class CGBlockInfo;
class CGCXXABI;
+class BlockByrefHelpers;
+class BlockByrefInfo;
class BlockFlags;
class BlockFieldFlags;
@@ -159,9 +162,9 @@ public:
/// ReturnBlock - Unified return block.
JumpDest ReturnBlock;
- /// ReturnValue - The temporary alloca to hold the return value. This is null
- /// iff the function has no return value.
- llvm::Value *ReturnValue;
+ /// ReturnValue - The temporary alloca to hold the return
+ /// value. This is invalid iff the function has no return value.
+ Address ReturnValue;
/// AllocaInsertPoint - This is an instruction in the entry block before which
/// we prefer to insert allocas.
@@ -247,10 +250,6 @@ public:
~CGCapturedStmtRAII() { CGF.CapturedStmtInfo = PrevCapturedStmtInfo; }
};
- /// BoundsChecking - Emit run-time bounds checks. Higher values mean
- /// potentially higher performance penalties.
- unsigned char BoundsChecking;
-
/// \brief Sanitizers enabled for this function.
SanitizerSet SanOpts;
@@ -294,6 +293,8 @@ public:
llvm::SmallVector<char, 256> LifetimeExtendedCleanupStack;
llvm::SmallVector<const JumpDest *, 2> SEHTryEpilogueStack;
+ llvm::Instruction *CurrentFuncletPad = nullptr;
+
/// Header for data within LifetimeExtendedCleanupStack.
struct LifetimeExtendedCleanupHeader {
/// The size of the following cleanup object.
@@ -327,7 +328,7 @@ public:
/// A stack of exception code slots. Entering an __except block pushes a slot
/// on the stack and leaving pops one. The __exception_code() intrinsic loads
/// a value from the top of the stack.
- SmallVector<llvm::Value *, 1> SEHCodeSlotStack;
+ SmallVector<Address, 1> SEHCodeSlotStack;
/// Value returned by __exception_info intrinsic.
llvm::Value *SEHInfo = nullptr;
@@ -373,6 +374,11 @@ public:
/// Returns true inside SEH __try blocks.
bool isSEHTryScope() const { return !SEHTryEpilogueStack.empty(); }
+ /// Returns true while emitting a cleanuppad.
+ bool isCleanupPadScope() const {
+ return CurrentFuncletPad && isa<llvm::CleanupPadInst>(CurrentFuncletPad);
+ }
+
/// pushFullExprCleanup - Push a cleanup to be run at the end of the
/// current full-expression. Safe against the possibility that
/// we're currently inside a conditionally-evaluated expression.
@@ -419,13 +425,12 @@ public:
/// complete-object destructor of an object of the given type at the
/// given address. Does nothing if T is not a C++ class type with a
/// non-trivial destructor.
- void PushDestructorCleanup(QualType T, llvm::Value *Addr);
+ void PushDestructorCleanup(QualType T, Address Addr);
/// PushDestructorCleanup - Push a cleanup to call the
/// complete-object variant of the given destructor on the object at
/// the given address.
- void PushDestructorCleanup(const CXXDestructorDecl *Dtor,
- llvm::Value *Addr);
+ void PushDestructorCleanup(const CXXDestructorDecl *Dtor, Address Addr);
/// PopCleanupBlock - Will pop the cleanup entry on the stack and
/// process all branch fixups.
@@ -555,13 +560,14 @@ public:
void rescopeLabels();
};
+ typedef llvm::DenseMap<const Decl *, Address> DeclMapTy;
+
/// \brief The scope used to remap some variables as private in the OpenMP
/// loop body (or other captured region emitted without outlining), and to
/// restore old vars back on exit.
class OMPPrivateScope : public RunCleanupsScope {
- typedef llvm::DenseMap<const VarDecl *, llvm::Value *> VarDeclMapTy;
- VarDeclMapTy SavedLocals;
- VarDeclMapTy SavedPrivates;
+ DeclMapTy SavedLocals;
+ DeclMapTy SavedPrivates;
private:
OMPPrivateScope(const OMPPrivateScope &) = delete;
@@ -578,13 +584,30 @@ public:
/// been privatized already.
bool
addPrivate(const VarDecl *LocalVD,
- const std::function<llvm::Value *()> &PrivateGen) {
+ llvm::function_ref<Address()> PrivateGen) {
assert(PerformCleanup && "adding private to dead scope");
- if (SavedLocals.count(LocalVD) > 0) return false;
- SavedLocals[LocalVD] = CGF.LocalDeclMap.lookup(LocalVD);
- CGF.LocalDeclMap.erase(LocalVD);
- SavedPrivates[LocalVD] = PrivateGen();
- CGF.LocalDeclMap[LocalVD] = SavedLocals[LocalVD];
+
+ // Only save it once.
+ if (SavedLocals.count(LocalVD)) return false;
+
+ // Copy the existing local entry to SavedLocals.
+ auto it = CGF.LocalDeclMap.find(LocalVD);
+ if (it != CGF.LocalDeclMap.end()) {
+ SavedLocals.insert({LocalVD, it->second});
+ } else {
+ SavedLocals.insert({LocalVD, Address::invalid()});
+ }
+
+ // Generate the private entry.
+ Address Addr = PrivateGen();
+ QualType VarTy = LocalVD->getType();
+ if (VarTy->isReferenceType()) {
+ Address Temp = CGF.CreateMemTemp(VarTy);
+ CGF.Builder.CreateStore(Addr.getPointer(), Temp);
+ Addr = Temp;
+ }
+ SavedPrivates.insert({LocalVD, Addr});
+
return true;
}
@@ -597,19 +620,14 @@ public:
/// private copies.
/// \return true if at least one variable was privatized, false otherwise.
bool Privatize() {
- for (auto VDPair : SavedPrivates) {
- CGF.LocalDeclMap[VDPair.first] = VDPair.second;
- }
+ copyInto(SavedPrivates, CGF.LocalDeclMap);
SavedPrivates.clear();
return !SavedLocals.empty();
}
void ForceCleanup() {
RunCleanupsScope::ForceCleanup();
- // Remap vars back to the original values.
- for (auto I : SavedLocals) {
- CGF.LocalDeclMap[I.first] = I.second;
- }
+ copyInto(SavedLocals, CGF.LocalDeclMap);
SavedLocals.clear();
}
@@ -618,6 +636,25 @@ public:
if (PerformCleanup)
ForceCleanup();
}
+
+ private:
+ /// Copy all the entries in the source map over the corresponding
+ /// entries in the destination, which must exist.
+ static void copyInto(const DeclMapTy &src, DeclMapTy &dest) {
+ for (auto &pair : src) {
+ if (!pair.second.isValid()) {
+ dest.erase(pair.first);
+ continue;
+ }
+
+ auto it = dest.find(pair.first);
+ if (it != dest.end()) {
+ it->second = pair.second;
+ } else {
+ dest.insert(pair);
+ }
+ }
+ }
};
/// \brief Takes the old cleanup stack size and emits the cleanup blocks
@@ -665,6 +702,7 @@ public:
llvm::BasicBlock *getEHResumeBlock(bool isCleanup);
llvm::BasicBlock *getEHDispatchBlock(EHScopeStack::stable_iterator scope);
+ llvm::BasicBlock *getMSVCDispatchBlock(EHScopeStack::stable_iterator scope);
/// An object to manage conditionally-evaluated expressions.
class ConditionalEvaluation {
@@ -697,10 +735,11 @@ public:
/// one branch or the other of a conditional expression.
bool isInConditionalBranch() const { return OutermostConditional != nullptr; }
- void setBeforeOutermostConditional(llvm::Value *value, llvm::Value *addr) {
+ void setBeforeOutermostConditional(llvm::Value *value, Address addr) {
assert(isInConditionalBranch());
llvm::BasicBlock *block = OutermostConditional->getStartingBlock();
- new llvm::StoreInst(value, addr, &block->back());
+ auto store = new llvm::StoreInst(value, addr.getPointer(), &block->back());
+ store->setAlignment(addr.getAlignment().getQuantity());
}
/// An RAII object to record that we're evaluating a statement
@@ -859,15 +898,6 @@ public:
}
};
- /// getByrefValueFieldNumber - Given a declaration, returns the LLVM field
- /// number that holds the value.
- std::pair<llvm::Type *, unsigned>
- getByRefValueLLVMField(const ValueDecl *VD) const;
-
- /// BuildBlockByrefAddress - Computes address location of the
- /// variable which is declared as __block.
- llvm::Value *BuildBlockByrefAddress(llvm::Value *BaseAddr,
- const VarDecl *V);
private:
CGDebugInfo *DebugInfo;
bool DisableDebugInfo;
@@ -884,9 +914,14 @@ private:
/// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
/// decls.
- typedef llvm::DenseMap<const Decl*, llvm::Value*> DeclMapTy;
DeclMapTy LocalDeclMap;
+ /// SizeArguments - If a ParmVarDecl had the pass_object_size attribute, this
+ /// will contain a mapping from said ParmVarDecl to its implicit "object_size"
+ /// parameter.
+ llvm::SmallDenseMap<const ParmVarDecl *, const ImplicitParamDecl *, 2>
+ SizeArguments;
+
/// Track escaped local variables with auto storage. Used during SEH
/// outlining to produce a call to llvm.localescape.
llvm::DenseMap<llvm::AllocaInst *, int> EscapedLocals;
@@ -984,7 +1019,7 @@ public:
/// if we need to evaluate a CXXDefaultInitExpr within the evaluation.
class FieldConstructionScope {
public:
- FieldConstructionScope(CodeGenFunction &CGF, llvm::Value *This)
+ FieldConstructionScope(CodeGenFunction &CGF, Address This)
: CGF(CGF), OldCXXDefaultInitExprThis(CGF.CXXDefaultInitExprThis) {
CGF.CXXDefaultInitExprThis = This;
}
@@ -994,7 +1029,7 @@ public:
private:
CodeGenFunction &CGF;
- llvm::Value *OldCXXDefaultInitExprThis;
+ Address OldCXXDefaultInitExprThis;
};
/// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this'
@@ -1002,16 +1037,20 @@ public:
class CXXDefaultInitExprScope {
public:
CXXDefaultInitExprScope(CodeGenFunction &CGF)
- : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue) {
- CGF.CXXThisValue = CGF.CXXDefaultInitExprThis;
+ : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue),
+ OldCXXThisAlignment(CGF.CXXThisAlignment) {
+ CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getPointer();
+ CGF.CXXThisAlignment = CGF.CXXDefaultInitExprThis.getAlignment();
}
~CXXDefaultInitExprScope() {
CGF.CXXThisValue = OldCXXThisValue;
+ CGF.CXXThisAlignment = OldCXXThisAlignment;
}
public:
CodeGenFunction &CGF;
llvm::Value *OldCXXThisValue;
+ CharUnits OldCXXThisAlignment;
};
private:
@@ -1020,10 +1059,12 @@ private:
ImplicitParamDecl *CXXABIThisDecl;
llvm::Value *CXXABIThisValue;
llvm::Value *CXXThisValue;
+ CharUnits CXXABIThisAlignment;
+ CharUnits CXXThisAlignment;
/// The value of 'this' to use when evaluating CXXDefaultInitExprs within
/// this expression.
- llvm::Value *CXXDefaultInitExprThis;
+ Address CXXDefaultInitExprThis = Address::invalid();
/// CXXStructorImplicitParamDecl - When generating code for a constructor or
/// destructor, this will hold the implicit argument (e.g. VTT).
@@ -1042,10 +1083,9 @@ private:
/// handling code.
SourceLocation CurEHLocation;
- /// ByrefValueInfoMap - For each __block variable, contains a pair of the LLVM
- /// type as well as the field number that contains the actual data.
- llvm::DenseMap<const ValueDecl *, std::pair<llvm::Type *,
- unsigned> > ByRefValueInfo;
+ /// BlockByrefInfos - For each __block variable, contains
+ /// information about the layout of the variable.
+ llvm::DenseMap<const ValueDecl *, BlockByrefInfo> BlockByrefInfos;
llvm::BasicBlock *TerminateLandingPad;
llvm::BasicBlock *TerminateHandler;
@@ -1086,15 +1126,15 @@ public:
/// Returns a pointer to the function's exception object and selector slot,
/// which is assigned in every landing pad.
- llvm::Value *getExceptionSlot();
- llvm::Value *getEHSelectorSlot();
+ Address getExceptionSlot();
+ Address getEHSelectorSlot();
/// Returns the contents of the function's exception object and selector
/// slots.
llvm::Value *getExceptionFromSlot();
llvm::Value *getSelectorFromSlot();
- llvm::Value *getNormalCleanupDestSlot();
+ Address getNormalCleanupDestSlot();
llvm::BasicBlock *getUnreachableBlock() {
if (!UnreachableBlock) {
@@ -1121,38 +1161,41 @@ public:
// Cleanups
//===--------------------------------------------------------------------===//
- typedef void Destroyer(CodeGenFunction &CGF, llvm::Value *addr, QualType ty);
+ typedef void Destroyer(CodeGenFunction &CGF, Address addr, QualType ty);
void pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin,
- llvm::Value *arrayEndPointer,
+ Address arrayEndPointer,
QualType elementType,
+ CharUnits elementAlignment,
Destroyer *destroyer);
void pushRegularPartialArrayCleanup(llvm::Value *arrayBegin,
llvm::Value *arrayEnd,
QualType elementType,
+ CharUnits elementAlignment,
Destroyer *destroyer);
void pushDestroy(QualType::DestructionKind dtorKind,
- llvm::Value *addr, QualType type);
+ Address addr, QualType type);
void pushEHDestroy(QualType::DestructionKind dtorKind,
- llvm::Value *addr, QualType type);
- void pushDestroy(CleanupKind kind, llvm::Value *addr, QualType type,
+ Address addr, QualType type);
+ void pushDestroy(CleanupKind kind, Address addr, QualType type,
Destroyer *destroyer, bool useEHCleanupForArray);
- void pushLifetimeExtendedDestroy(CleanupKind kind, llvm::Value *addr,
+ void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr,
QualType type, Destroyer *destroyer,
bool useEHCleanupForArray);
void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete,
llvm::Value *CompletePtr,
QualType ElementType);
- void pushStackRestore(CleanupKind kind, llvm::Value *SPMem);
- void emitDestroy(llvm::Value *addr, QualType type, Destroyer *destroyer,
+ void pushStackRestore(CleanupKind kind, Address SPMem);
+ void emitDestroy(Address addr, QualType type, Destroyer *destroyer,
bool useEHCleanupForArray);
- llvm::Function *generateDestroyHelper(llvm::Constant *addr, QualType type,
+ llvm::Function *generateDestroyHelper(Address addr, QualType type,
Destroyer *destroyer,
bool useEHCleanupForArray,
const VarDecl *VD);
void emitArrayDestroy(llvm::Value *begin, llvm::Value *end,
- QualType type, Destroyer *destroyer,
+ QualType elementType, CharUnits elementAlign,
+ Destroyer *destroyer,
bool checkZeroLength, bool useEHCleanup);
Destroyer *getDestroyer(QualType::DestructionKind destructionKind);
@@ -1203,8 +1246,6 @@ public:
void generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
const ObjCPropertyImplDecl *propImpl,
llvm::Constant *AtomicHelperFn);
- bool IndirectObjCSetterArg(const CGFunctionInfo &FI);
- bool IvarTypeWithAggrGCObjects(QualType Ty);
//===--------------------------------------------------------------------===//
// Block Bits
@@ -1213,10 +1254,6 @@ public:
llvm::Value *EmitBlockLiteral(const BlockExpr *);
llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
static void destroyBlockInfos(CGBlockInfo *info);
- llvm::Constant *BuildDescriptorBlockDecl(const BlockExpr *,
- const CGBlockInfo &Info,
- llvm::StructType *,
- llvm::Constant *BlockVarLayout);
llvm::Function *GenerateBlockFunction(GlobalDecl GD,
const CGBlockInfo &Info,
@@ -1238,15 +1275,22 @@ public:
void emitByrefStructureInit(const AutoVarEmission &emission);
void enterByrefCleanup(const AutoVarEmission &emission);
- llvm::Value *LoadBlockStruct() {
- assert(BlockPointer && "no block pointer set!");
- return BlockPointer;
- }
+ void setBlockContextParameter(const ImplicitParamDecl *D, unsigned argNum,
+ llvm::Value *ptr);
+
+ Address LoadBlockStruct();
+ Address GetAddrOfBlockDecl(const VarDecl *var, bool ByRef);
- void AllocateBlockCXXThisPointer(const CXXThisExpr *E);
- void AllocateBlockDecl(const DeclRefExpr *E);
- llvm::Value *GetAddrOfBlockDecl(const VarDecl *var, bool ByRef);
- llvm::Type *BuildByRefType(const VarDecl *var);
+ /// BuildBlockByrefAddress - Computes the location of the
+ /// data in a variable which is declared as __block.
+ Address emitBlockByrefAddress(Address baseAddr, const VarDecl *V,
+ bool followForward = true);
+ Address emitBlockByrefAddress(Address baseAddr,
+ const BlockByrefInfo &info,
+ bool followForward,
+ const llvm::Twine &name);
+
+ const BlockByrefInfo &getBlockByrefInfo(const VarDecl *var);
void GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo);
@@ -1290,6 +1334,8 @@ public:
void EmitCallAndReturnForThunk(llvm::Value *Callee, const ThunkInfo *Thunk);
+ void FinishThunk();
+
/// Emit a musttail call for a thunk with a potentially adjusted this pointer.
void EmitMustTailThunk(const CXXMethodDecl *MD, llvm::Value *AdjustedThisPtr,
llvm::Value *Callee);
@@ -1308,27 +1354,34 @@ public:
void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init,
ArrayRef<VarDecl *> ArrayIndexes);
- /// InitializeVTablePointer - Initialize the vtable pointer of the given
- /// subobject.
- ///
- void InitializeVTablePointer(BaseSubobject Base,
- const CXXRecordDecl *NearestVBase,
- CharUnits OffsetFromNearestVBase,
- const CXXRecordDecl *VTableClass);
+ /// Struct with all informations about dynamic [sub]class needed to set vptr.
+ struct VPtr {
+ BaseSubobject Base;
+ const CXXRecordDecl *NearestVBase;
+ CharUnits OffsetFromNearestVBase;
+ const CXXRecordDecl *VTableClass;
+ };
+
+ /// Initialize the vtable pointer of the given subobject.
+ void InitializeVTablePointer(const VPtr &vptr);
+
+ typedef llvm::SmallVector<VPtr, 4> VPtrsVector;
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
- void InitializeVTablePointers(BaseSubobject Base,
- const CXXRecordDecl *NearestVBase,
- CharUnits OffsetFromNearestVBase,
- bool BaseIsNonVirtualPrimaryBase,
- const CXXRecordDecl *VTableClass,
- VisitedVirtualBasesSetTy& VBases);
+ VPtrsVector getVTablePointers(const CXXRecordDecl *VTableClass);
+
+ void getVTablePointers(BaseSubobject Base, const CXXRecordDecl *NearestVBase,
+ CharUnits OffsetFromNearestVBase,
+ bool BaseIsNonVirtualPrimaryBase,
+ const CXXRecordDecl *VTableClass,
+ VisitedVirtualBasesSetTy &VBases, VPtrsVector &vptrs);
void InitializeVTablePointers(const CXXRecordDecl *ClassDecl);
/// GetVTablePtr - Return the Value of the vtable pointer member pointed
/// to by This.
- llvm::Value *GetVTablePtr(llvm::Value *This, llvm::Type *Ty);
+ llvm::Value *GetVTablePtr(Address This, llvm::Type *VTableTy,
+ const CXXRecordDecl *VTableClass);
enum CFITypeCheckKind {
CFITCK_VCall,
@@ -1495,49 +1548,85 @@ public:
// Helpers
//===--------------------------------------------------------------------===//
- LValue MakeAddrLValue(llvm::Value *V, QualType T,
- CharUnits Alignment = CharUnits()) {
- return LValue::MakeAddr(V, T, Alignment, getContext(),
+ LValue MakeAddrLValue(Address Addr, QualType T,
+ AlignmentSource AlignSource = AlignmentSource::Type) {
+ return LValue::MakeAddr(Addr, T, getContext(), AlignSource,
CGM.getTBAAInfo(T));
}
+ LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment,
+ AlignmentSource AlignSource = AlignmentSource::Type) {
+ return LValue::MakeAddr(Address(V, Alignment), T, getContext(),
+ AlignSource, CGM.getTBAAInfo(T));
+ }
+
+ LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T);
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T);
+ CharUnits getNaturalTypeAlignment(QualType T,
+ AlignmentSource *Source = nullptr,
+ bool forPointeeType = false);
+ CharUnits getNaturalPointeeTypeAlignment(QualType T,
+ AlignmentSource *Source = nullptr);
+
+ Address EmitLoadOfReference(Address Ref, const ReferenceType *RefTy,
+ AlignmentSource *Source = nullptr);
+ LValue EmitLoadOfReferenceLValue(Address Ref, const ReferenceType *RefTy);
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block. The caller is responsible for setting an appropriate alignment on
/// the alloca.
llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty,
const Twine &Name = "tmp");
+ Address CreateTempAlloca(llvm::Type *Ty, CharUnits align,
+ const Twine &Name = "tmp");
- /// InitTempAlloca - Provide an initial value for the given alloca.
- void InitTempAlloca(llvm::AllocaInst *Alloca, llvm::Value *Value);
+ /// CreateDefaultAlignedTempAlloca - This creates an alloca with the
+ /// default ABI alignment of the given LLVM type.
+ ///
+ /// IMPORTANT NOTE: This is *not* generally the right alignment for
+ /// any given AST type that happens to have been lowered to the
+ /// given IR type. This should only ever be used for function-local,
+ /// IR-driven manipulations like saving and restoring a value. Do
+ /// not hand this address off to arbitrary IRGen routines, and especially
+ /// do not pass it as an argument to a function that might expect a
+ /// properly ABI-aligned value.
+ Address CreateDefaultAlignTempAlloca(llvm::Type *Ty,
+ const Twine &Name = "tmp");
+
+ /// InitTempAlloca - Provide an initial value for the given alloca which
+ /// will be observable at all locations in the function.
+ ///
+ /// The address should be something that was returned from one of
+ /// the CreateTempAlloca or CreateMemTemp routines, and the
+ /// initializer must be valid in the entry block (i.e. it must
+ /// either be a constant or an argument value).
+ void InitTempAlloca(Address Alloca, llvm::Value *Value);
/// CreateIRTemp - Create a temporary IR object of the given type, with
/// appropriate alignment. This routine should only be used when an temporary
/// value needs to be stored into an alloca (for example, to avoid explicit
/// PHI construction), but the type is the IR type, not the type appropriate
/// for storing in memory.
- llvm::AllocaInst *CreateIRTemp(QualType T, const Twine &Name = "tmp");
+ ///
+ /// That is, this is exactly equivalent to CreateMemTemp, but calling
+ /// ConvertType instead of ConvertTypeForMem.
+ Address CreateIRTemp(QualType T, const Twine &Name = "tmp");
/// CreateMemTemp - Create a temporary memory object of the given type, with
/// appropriate alignment.
- llvm::AllocaInst *CreateMemTemp(QualType T, const Twine &Name = "tmp");
+ Address CreateMemTemp(QualType T, const Twine &Name = "tmp");
+ Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp");
/// CreateAggTemp - Create a temporary memory object for the given
/// aggregate type.
AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp") {
- CharUnits Alignment = getContext().getTypeAlignInChars(T);
- return AggValueSlot::forAddr(CreateMemTemp(T, Name), Alignment,
+ return AggValueSlot::forAddr(CreateMemTemp(T, Name),
T.getQualifiers(),
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased);
}
- /// CreateInAllocaTmp - Create a temporary memory object for the given
- /// aggregate type.
- AggValueSlot CreateInAllocaTmp(QualType T, const Twine &Name = "inalloca");
-
/// Emit a cast to void* in the appropriate address space.
llvm::Value *EmitCastToVoidPtr(llvm::Value *value);
@@ -1560,7 +1649,12 @@ public:
// EmitVAListRef - Emit a "reference" to a va_list; this is either the address
// or the value of the expression, depending on how va_list is defined.
- llvm::Value *EmitVAListRef(const Expr *E);
+ Address EmitVAListRef(const Expr *E);
+
+ /// Emit a "reference" to a __builtin_ms_va_list; this is
+ /// always the value of the expression, because a __builtin_ms_va_list is a
+ /// pointer to a char.
+ Address EmitMSVAListRef(const Expr *E);
/// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will
/// always be accessible even if no aggregate location is provided.
@@ -1568,10 +1662,10 @@ public:
/// EmitAnyExprToMem - Emits the code necessary to evaluate an
/// arbitrary expression into the given memory location.
- void EmitAnyExprToMem(const Expr *E, llvm::Value *Location,
+ void EmitAnyExprToMem(const Expr *E, Address Location,
Qualifiers Quals, bool IsInitializer);
- void EmitAnyExprToExn(const Expr *E, llvm::Value *Addr);
+ void EmitAnyExprToExn(const Expr *E, Address Addr);
/// EmitExprAsInit - Emits the code necessary to initialize a
/// location in memory with the given initializer.
@@ -1591,19 +1685,15 @@ public:
///
/// The difference to EmitAggregateCopy is that tail padding is not copied.
/// This is required for correctness when assigning non-POD structures in C++.
- void EmitAggregateAssign(llvm::Value *DestPtr, llvm::Value *SrcPtr,
+ void EmitAggregateAssign(Address DestPtr, Address SrcPtr,
QualType EltTy) {
bool IsVolatile = hasVolatileMember(EltTy);
- EmitAggregateCopy(DestPtr, SrcPtr, EltTy, IsVolatile, CharUnits::Zero(),
- true);
+ EmitAggregateCopy(DestPtr, SrcPtr, EltTy, IsVolatile, true);
}
- void EmitAggregateCopyCtor(llvm::Value *DestPtr, llvm::Value *SrcPtr,
- QualType DestTy, QualType SrcTy) {
- CharUnits DestTypeAlign = getContext().getTypeAlignInChars(DestTy);
- CharUnits SrcTypeAlign = getContext().getTypeAlignInChars(SrcTy);
+ void EmitAggregateCopyCtor(Address DestPtr, Address SrcPtr,
+ QualType DestTy, QualType SrcTy) {
EmitAggregateCopy(DestPtr, SrcPtr, SrcTy, /*IsVolatile=*/false,
- std::min(DestTypeAlign, SrcTypeAlign),
/*IsAssignment=*/false);
}
@@ -1613,20 +1703,16 @@ public:
/// volatile.
/// \param isAssignment - If false, allow padding to be copied. This often
/// yields more efficient.
- void EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr,
+ void EmitAggregateCopy(Address DestPtr, Address SrcPtr,
QualType EltTy, bool isVolatile=false,
- CharUnits Alignment = CharUnits::Zero(),
bool isAssignment = false);
- /// StartBlock - Start new block named N. If insert block is a dummy block
- /// then reuse it.
- void StartBlock(const char *N);
-
/// GetAddrOfLocalVar - Return the address of a local variable.
- llvm::Value *GetAddrOfLocalVar(const VarDecl *VD) {
- llvm::Value *Res = LocalDeclMap[VD];
- assert(Res && "Invalid argument to GetAddrOfLocalVar(), no decl!");
- return Res;
+ Address GetAddrOfLocalVar(const VarDecl *VD) {
+ auto it = LocalDeclMap.find(VD);
+ assert(it != LocalDeclMap.end() &&
+ "Invalid argument to GetAddrOfLocalVar(), no decl!");
+ return it->second;
}
/// getOpaqueLValueMapping - Given an opaque value expression (which
@@ -1661,19 +1747,31 @@ public:
/// EmitNullInitialization - Generate code to set a value of the given type to
/// null, If the type contains data member pointers, they will be initialized
/// to -1 in accordance with the Itanium C++ ABI.
- void EmitNullInitialization(llvm::Value *DestPtr, QualType Ty);
-
- // EmitVAArg - Generate code to get an argument from the passed in pointer
- // and update it accordingly. The return value is a pointer to the argument.
+ void EmitNullInitialization(Address DestPtr, QualType Ty);
+
+ /// Emits a call to an LLVM variable-argument intrinsic, either
+ /// \c llvm.va_start or \c llvm.va_end.
+ /// \param ArgValue A reference to the \c va_list as emitted by either
+ /// \c EmitVAListRef or \c EmitMSVAListRef.
+ /// \param IsStart If \c true, emits a call to \c llvm.va_start; otherwise,
+ /// calls \c llvm.va_end.
+ llvm::Value *EmitVAStartEnd(llvm::Value *ArgValue, bool IsStart);
+
+ /// Generate code to get an argument from the passed in pointer
+ /// and update it accordingly.
+ /// \param VE The \c VAArgExpr for which to generate code.
+ /// \param VAListAddr Receives a reference to the \c va_list as emitted by
+ /// either \c EmitVAListRef or \c EmitMSVAListRef.
+ /// \returns A pointer to the argument.
// FIXME: We should be able to get rid of this method and use the va_arg
// instruction in LLVM instead once it works well enough.
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty);
+ Address EmitVAArg(VAArgExpr *VE, Address &VAListAddr);
/// emitArrayLength - Compute the length of an array, even if it's a
/// VLA, and drill down to the base element type.
llvm::Value *emitArrayLength(const ArrayType *arrayType,
QualType &baseType,
- llvm::Value *&addr);
+ Address &addr);
/// EmitVLASize - Capture all the sizes for the VLA expressions in
/// the given variably-modified type and store them in the VLASizeMap.
@@ -1694,6 +1792,7 @@ public:
assert(CXXThisValue && "no 'this' value for this function");
return CXXThisValue;
}
+ Address LoadCXXThisAddress();
/// LoadCXXVTT - Load the VTT parameter to base constructors/destructors have
/// virtual bases.
@@ -1704,35 +1803,29 @@ public:
return CXXStructorImplicitParamValue;
}
- /// LoadCXXStructorImplicitParam - Load the implicit parameter
- /// for a constructor/destructor.
- llvm::Value *LoadCXXStructorImplicitParam() {
- assert(CXXStructorImplicitParamValue &&
- "no implicit argument value for this function");
- return CXXStructorImplicitParamValue;
- }
-
/// GetAddressOfBaseOfCompleteClass - Convert the given pointer to a
/// complete class to the given direct base.
- llvm::Value *
- GetAddressOfDirectBaseInCompleteClass(llvm::Value *Value,
+ Address
+ GetAddressOfDirectBaseInCompleteClass(Address Value,
const CXXRecordDecl *Derived,
const CXXRecordDecl *Base,
bool BaseIsVirtual);
+ static bool ShouldNullCheckClassCastValue(const CastExpr *Cast);
+
/// GetAddressOfBaseClass - This function will add the necessary delta to the
/// load of 'this' and returns address of the base class.
- llvm::Value *GetAddressOfBaseClass(llvm::Value *Value,
- const CXXRecordDecl *Derived,
- CastExpr::path_const_iterator PathBegin,
- CastExpr::path_const_iterator PathEnd,
- bool NullCheckValue, SourceLocation Loc);
-
- llvm::Value *GetAddressOfDerivedClass(llvm::Value *Value,
- const CXXRecordDecl *Derived,
- CastExpr::path_const_iterator PathBegin,
- CastExpr::path_const_iterator PathEnd,
- bool NullCheckValue);
+ Address GetAddressOfBaseClass(Address Value,
+ const CXXRecordDecl *Derived,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
+ bool NullCheckValue, SourceLocation Loc);
+
+ Address GetAddressOfDerivedClass(Address Value,
+ const CXXRecordDecl *Derived,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
+ bool NullCheckValue);
/// GetVTTParameter - Return the VTT parameter that should be passed to a
/// base constructor/destructor with virtual bases.
@@ -1751,23 +1844,31 @@ public:
// they are substantially the same.
void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor,
const FunctionArgList &Args);
+
void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
bool ForVirtualBase, bool Delegating,
- llvm::Value *This, const CXXConstructExpr *E);
+ Address This, const CXXConstructExpr *E);
+
+ /// Emit assumption load for all bases. Requires to be be called only on
+ /// most-derived class and not under construction of the object.
+ void EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, Address This);
+
+ /// Emit assumption that vptr load == global vtable.
+ void EmitVTableAssumptionLoad(const VPtr &vptr, Address This);
void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
- llvm::Value *This, llvm::Value *Src,
- const CXXConstructExpr *E);
+ Address This, Address Src,
+ const CXXConstructExpr *E);
void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
const ConstantArrayType *ArrayTy,
- llvm::Value *ArrayPtr,
+ Address ArrayPtr,
const CXXConstructExpr *E,
bool ZeroInitialization = false);
void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
llvm::Value *NumElements,
- llvm::Value *ArrayPtr,
+ Address ArrayPtr,
const CXXConstructExpr *E,
bool ZeroInitialization = false);
@@ -1775,15 +1876,15 @@ public:
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type,
bool ForVirtualBase, bool Delegating,
- llvm::Value *This);
+ Address This);
void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType,
- llvm::Type *ElementTy, llvm::Value *NewPtr,
+ llvm::Type *ElementTy, Address NewPtr,
llvm::Value *NumElements,
llvm::Value *AllocSizeWithoutCookie);
void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType,
- llvm::Value *Ptr);
+ Address Ptr);
llvm::Value *EmitLifetimeStart(uint64_t Size, llvm::Value *Addr);
void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
@@ -1797,9 +1898,9 @@ public:
RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
const Expr *Arg, bool IsDelete);
- llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
- llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE);
- llvm::Value* EmitCXXUuidofExpr(const CXXUuidofExpr *E);
+ llvm::Value *EmitCXXTypeidExpr(const CXXTypeidExpr *E);
+ llvm::Value *EmitDynamicCast(Address V, const CXXDynamicCastExpr *DCE);
+ Address EmitCXXUuidofExpr(const CXXUuidofExpr *E);
/// \brief Situations in which we might emit a check for the suitability of a
/// pointer or glvalue.
@@ -1896,12 +1997,9 @@ public:
const VarDecl *Variable;
- /// The alignment of the variable.
- CharUnits Alignment;
-
- /// The address of the alloca. Null if the variable was emitted
+ /// The address of the alloca. Invalid if the variable was emitted
/// as a global constant.
- llvm::Value *Address;
+ Address Addr;
llvm::Value *NRVOFlag;
@@ -1916,14 +2014,14 @@ public:
llvm::Value *SizeForLifetimeMarkers;
struct Invalid {};
- AutoVarEmission(Invalid) : Variable(nullptr) {}
+ AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()) {}
AutoVarEmission(const VarDecl &variable)
- : Variable(&variable), Address(nullptr), NRVOFlag(nullptr),
+ : Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
IsByRef(false), IsConstantAggregate(false),
SizeForLifetimeMarkers(nullptr) {}
- bool wasEmittedAsGlobal() const { return Address == nullptr; }
+ bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
public:
static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
@@ -1938,19 +2036,17 @@ public:
/// Returns the raw, allocated address, which is not necessarily
/// the address of the object itself.
- llvm::Value *getAllocatedAddress() const {
- return Address;
+ Address getAllocatedAddress() const {
+ return Addr;
}
/// Returns the address of the object within this declaration.
/// Note that this does not chase the forwarding pointer for
/// __block decls.
- llvm::Value *getObjectAddress(CodeGenFunction &CGF) const {
- if (!IsByRef) return Address;
+ Address getObjectAddress(CodeGenFunction &CGF) const {
+ if (!IsByRef) return Addr;
- auto F = CGF.getByRefValueLLVMField(Variable);
- return CGF.Builder.CreateStructGEP(F.first, Address, F.second,
- Variable->getNameAsString());
+ return CGF.emitBlockByrefAddress(Addr, Variable, /*forward*/ false);
}
};
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var);
@@ -1962,9 +2058,35 @@ public:
void EmitStaticVarDecl(const VarDecl &D,
llvm::GlobalValue::LinkageTypes Linkage);
+ class ParamValue {
+ llvm::Value *Value;
+ unsigned Alignment;
+ ParamValue(llvm::Value *V, unsigned A) : Value(V), Alignment(A) {}
+ public:
+ static ParamValue forDirect(llvm::Value *value) {
+ return ParamValue(value, 0);
+ }
+ static ParamValue forIndirect(Address addr) {
+ assert(!addr.getAlignment().isZero());
+ return ParamValue(addr.getPointer(), addr.getAlignment().getQuantity());
+ }
+
+ bool isIndirect() const { return Alignment != 0; }
+ llvm::Value *getAnyValue() const { return Value; }
+
+ llvm::Value *getDirectValue() const {
+ assert(!isIndirect());
+ return Value;
+ }
+
+ Address getIndirectAddress() const {
+ assert(isIndirect());
+ return Address(Value, CharUnits::fromQuantity(Alignment));
+ }
+ };
+
/// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl.
- void EmitParmDecl(const VarDecl &D, llvm::Value *Arg, bool ArgIsPointer,
- unsigned ArgNo);
+ void EmitParmDecl(const VarDecl &D, ParamValue Arg, unsigned ArgNo);
/// protectFromPeepholes - Protect a value that we're intending to
/// store to the side, but which will probably be used later, from
@@ -2001,11 +2123,11 @@ public:
/// \return True if the statement was handled.
bool EmitSimpleStmt(const Stmt *S);
- llvm::Value *EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
- AggValueSlot AVS = AggValueSlot::ignored());
- llvm::Value *EmitCompoundStmtWithoutScope(const CompoundStmt &S,
- bool GetLast = false,
- AggValueSlot AVS =
+ Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
+ AggValueSlot AVS = AggValueSlot::ignored());
+ Address EmitCompoundStmtWithoutScope(const CompoundStmt &S,
+ bool GetLast = false,
+ AggValueSlot AVS =
AggValueSlot::ignored());
/// EmitLabel - Emit the block for the given label. It is legal to call this
@@ -2018,8 +2140,6 @@ public:
void EmitIndirectGotoStmt(const IndirectGotoStmt &S);
void EmitIfStmt(const IfStmt &S);
- void EmitCondBrHints(llvm::LLVMContext &Context, llvm::BranchInst *CondBr,
- ArrayRef<const Attr *> Attrs);
void EmitWhileStmt(const WhileStmt &S,
ArrayRef<const Attr *> Attrs = None);
void EmitDoStmt(const DoStmt &S, ArrayRef<const Attr *> Attrs = None);
@@ -2077,19 +2197,20 @@ public:
/// either be an alloca or a call to llvm.localrecover if there are nested
/// outlined functions. ParentFP is the frame pointer of the outermost parent
/// frame.
- llvm::Value *recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF,
- llvm::Value *ParentVar,
- llvm::Value *ParentFP);
+ Address recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF,
+ Address ParentVar,
+ llvm::Value *ParentFP);
void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
ArrayRef<const Attr *> Attrs = None);
LValue InitCapturedStruct(const CapturedStmt &S);
llvm::Function *EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K);
- void GenerateCapturedStmtFunctionProlog(const CapturedStmt &S);
- llvm::Function *GenerateCapturedStmtFunctionEpilog(const CapturedStmt &S);
llvm::Function *GenerateCapturedStmtFunction(const CapturedStmt &S);
- llvm::Value *GenerateCapturedStmtArgument(const CapturedStmt &S);
+ Address GenerateCapturedStmtArgument(const CapturedStmt &S);
+ llvm::Function *GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S);
+ void GenerateOpenMPCapturedVars(const CapturedStmt &S,
+ SmallVectorImpl<llvm::Value *> &CapturedVars);
/// \brief Perform element by element copying of arrays with type \a
/// OriginalType from \a SrcAddr to \a DestAddr using copying procedure
/// generated by \a CopyGen.
@@ -2100,8 +2221,8 @@ public:
/// \param CopyGen Copying procedure that copies value of single array element
/// to another single array element.
void EmitOMPAggregateAssign(
- llvm::Value *DestAddr, llvm::Value *SrcAddr, QualType OriginalType,
- const llvm::function_ref<void(llvm::Value *, llvm::Value *)> &CopyGen);
+ Address DestAddr, Address SrcAddr, QualType OriginalType,
+ const llvm::function_ref<void(Address, Address)> &CopyGen);
/// \brief Emit proper copying of data from one variable to another.
///
/// \param OriginalType Original type of the copied variables.
@@ -2113,8 +2234,8 @@ public:
/// the base array element).
/// \param Copy Actual copygin expression for copying data from \a SrcVD to \a
/// DestVD.
- void EmitOMPCopy(CodeGenFunction &CGF, QualType OriginalType,
- llvm::Value *DestAddr, llvm::Value *SrcAddr,
+ void EmitOMPCopy(QualType OriginalType,
+ Address DestAddr, Address SrcAddr,
const VarDecl *DestVD, const VarDecl *SrcVD,
const Expr *Copy);
/// \brief Emit atomic update code for constructs: \a X = \a X \a BO \a E or
@@ -2213,10 +2334,14 @@ public:
void EmitOMPOrderedDirective(const OMPOrderedDirective &S);
void EmitOMPAtomicDirective(const OMPAtomicDirective &S);
void EmitOMPTargetDirective(const OMPTargetDirective &S);
+ void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S);
void EmitOMPTeamsDirective(const OMPTeamsDirective &S);
void
EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S);
void EmitOMPCancelDirective(const OMPCancelDirective &S);
+ void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S);
+ void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S);
+ void EmitOMPDistributeDirective(const OMPDistributeDirective &S);
/// \brief Emit inner loop of the worksharing/simd construct.
///
@@ -2240,17 +2365,17 @@ private:
/// Helpers for the OpenMP loop directives.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit);
- void EmitOMPSimdInit(const OMPLoopDirective &D);
+ void EmitOMPSimdInit(const OMPLoopDirective &D, bool IsMonotonic = false);
void EmitOMPSimdFinal(const OMPLoopDirective &D);
/// \brief Emit code for the worksharing loop-based directive.
/// \return true, if this construct has any lastprivate clause, false -
/// otherwise.
bool EmitOMPWorksharingLoop(const OMPLoopDirective &S);
void EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
- const OMPLoopDirective &S,
- OMPPrivateScope &LoopScope, bool Ordered,
- llvm::Value *LB, llvm::Value *UB, llvm::Value *ST,
- llvm::Value *IL, llvm::Value *Chunk);
+ bool IsMonotonic, const OMPLoopDirective &S,
+ OMPPrivateScope &LoopScope, bool Ordered, Address LB,
+ Address UB, Address ST, Address IL,
+ llvm::Value *Chunk);
/// \brief Emit code for sections directive.
OpenMPDirectiveKind EmitSections(const OMPExecutableDirective &S);
@@ -2297,7 +2422,7 @@ public:
/// that the address will be used to access the object.
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK);
- RValue convertTempToRValue(llvm::Value *addr, QualType type,
+ RValue convertTempToRValue(Address addr, QualType type,
SourceLocation Loc);
void EmitAtomicInit(Expr *E, LValue lvalue);
@@ -2338,12 +2463,14 @@ public:
/// EmitLoadOfScalar - Load a scalar value from an address, taking
/// care to appropriately convert from the memory representation to
/// the LLVM value representation.
- llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
- unsigned Alignment, QualType Ty,
+ llvm::Value *EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty,
SourceLocation Loc,
+ AlignmentSource AlignSource =
+ AlignmentSource::Type,
llvm::MDNode *TBAAInfo = nullptr,
QualType TBAABaseTy = QualType(),
- uint64_t TBAAOffset = 0);
+ uint64_t TBAAOffset = 0,
+ bool isNontemporal = false);
/// EmitLoadOfScalar - Load a scalar value from an address, taking
/// care to appropriately convert from the memory representation to
@@ -2354,11 +2481,12 @@ public:
/// EmitStoreOfScalar - Store a scalar value to an address, taking
/// care to appropriately convert from the memory representation to
/// the LLVM value representation.
- void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
- bool Volatile, unsigned Alignment, QualType Ty,
+ void EmitStoreOfScalar(llvm::Value *Value, Address Addr,
+ bool Volatile, QualType Ty,
+ AlignmentSource AlignSource = AlignmentSource::Type,
llvm::MDNode *TBAAInfo = nullptr, bool isInit = false,
QualType TBAABaseTy = QualType(),
- uint64_t TBAAOffset = 0);
+ uint64_t TBAAOffset = 0, bool isNontemporal = false);
/// EmitStoreOfScalar - Store a scalar value to an address, taking
/// care to appropriately convert from the memory representation to
@@ -2405,13 +2533,14 @@ public:
// Note: only available for agg return types
LValue EmitVAArgExprLValue(const VAArgExpr *E);
LValue EmitDeclRefLValue(const DeclRefExpr *E);
- LValue EmitReadRegister(const VarDecl *VD);
LValue EmitStringLiteralLValue(const StringLiteral *E);
LValue EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E);
LValue EmitPredefinedLValue(const PredefinedExpr *E);
LValue EmitUnaryOpLValue(const UnaryOperator *E);
LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
bool Accessed = false);
+ LValue EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
+ bool IsLowerBound = true);
LValue EmitExtVectorElementExpr(const ExtVectorElementExpr *E);
LValue EmitMemberExpr(const MemberExpr *E);
LValue EmitObjCIsaExpr(const ObjCIsaExpr *E);
@@ -2422,10 +2551,13 @@ public:
LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
- llvm::Value *EmitExtVectorElementLValue(LValue V);
+ Address EmitExtVectorElementLValue(LValue V);
RValue EmitRValueForField(LValue LV, const FieldDecl *FD, SourceLocation Loc);
+ Address EmitArrayToPointerDecay(const Expr *Array,
+ AlignmentSource *AlignSource = nullptr);
+
class ConstantEmission {
llvm::PointerIntPair<llvm::Constant*, 1, bool> ValueAndIsReference;
ConstantEmission(llvm::Constant *C, bool isReference)
@@ -2497,23 +2629,20 @@ public:
/// EmitCall - Generate a call of the given function, expecting the given
/// result type, and using the given argument list which specifies both the
/// LLVM arguments and the types they were derived from.
- ///
- /// \param TargetDecl - If given, the decl of the function in a direct call;
- /// used to set attributes on the call (noreturn, etc.).
- RValue EmitCall(const CGFunctionInfo &FnInfo,
- llvm::Value *Callee,
- ReturnValueSlot ReturnValue,
- const CallArgList &Args,
- const Decl *TargetDecl = nullptr,
+ RValue EmitCall(const CGFunctionInfo &FnInfo, llvm::Value *Callee,
+ ReturnValueSlot ReturnValue, const CallArgList &Args,
+ CGCalleeInfo CalleeInfo = CGCalleeInfo(),
llvm::Instruction **callOrInvoke = nullptr);
RValue EmitCall(QualType FnType, llvm::Value *Callee, const CallExpr *E,
ReturnValueSlot ReturnValue,
- const Decl *TargetDecl = nullptr,
+ CGCalleeInfo CalleeInfo = CGCalleeInfo(),
llvm::Value *Chain = nullptr);
RValue EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue = ReturnValueSlot());
+ void checkTargetFeatures(const CallExpr *E, const FunctionDecl *TargetDecl);
+
llvm::CallInst *EmitRuntimeCall(llvm::Value *callee,
const Twine &name = "");
llvm::CallInst *EmitRuntimeCall(llvm::Value *callee,
@@ -2528,8 +2657,6 @@ public:
llvm::CallSite EmitCallOrInvoke(llvm::Value *Callee,
ArrayRef<llvm::Value *> Args,
const Twine &Name = "");
- llvm::CallSite EmitCallOrInvoke(llvm::Value *Callee,
- const Twine &Name = "");
llvm::CallSite EmitRuntimeCallOrInvoke(llvm::Value *callee,
ArrayRef<llvm::Value*> args,
const Twine &name = "");
@@ -2565,6 +2692,10 @@ public:
NestedNameSpecifier *Qualifier,
bool IsArrow, const Expr *Base);
// Compute the object pointer.
+ Address EmitCXXMemberDataPointerAddress(const Expr *E, Address base,
+ llvm::Value *memberPtr,
+ const MemberPointerType *memberPtrType,
+ AlignmentSource *AlignSource = nullptr);
RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
ReturnValueSlot ReturnValue);
@@ -2599,7 +2730,7 @@ public:
unsigned Modifier,
const CallExpr *E,
SmallVectorImpl<llvm::Value *> &Ops,
- llvm::Value *Align = nullptr);
+ Address PtrOp0, Address PtrOp1);
llvm::Function *LookupNeonLLVMIntrinsic(unsigned IntrinsicID,
unsigned Modifier, llvm::Type *ArgTy,
const CallExpr *E);
@@ -2612,8 +2743,6 @@ public:
bool negateForRightShift);
llvm::Value *EmitNeonRShiftImm(llvm::Value *Vec, llvm::Value *Amt,
llvm::Type *Ty, bool usgn, const char *name);
- // Helper functions for EmitAArch64BuiltinExpr.
- llvm::Value *vectorWrapScalar8(llvm::Value *Op);
llvm::Value *vectorWrapScalar16(llvm::Value *Op);
llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E);
@@ -2623,6 +2752,8 @@ public:
llvm::Value *EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitSystemZBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E);
llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
@@ -2643,24 +2774,23 @@ public:
}
// ARC primitives.
- void EmitARCInitWeak(llvm::Value *value, llvm::Value *addr);
- void EmitARCDestroyWeak(llvm::Value *addr);
- llvm::Value *EmitARCLoadWeak(llvm::Value *addr);
- llvm::Value *EmitARCLoadWeakRetained(llvm::Value *addr);
- llvm::Value *EmitARCStoreWeak(llvm::Value *value, llvm::Value *addr,
- bool ignored);
- void EmitARCCopyWeak(llvm::Value *dst, llvm::Value *src);
- void EmitARCMoveWeak(llvm::Value *dst, llvm::Value *src);
+ void EmitARCInitWeak(Address addr, llvm::Value *value);
+ void EmitARCDestroyWeak(Address addr);
+ llvm::Value *EmitARCLoadWeak(Address addr);
+ llvm::Value *EmitARCLoadWeakRetained(Address addr);
+ llvm::Value *EmitARCStoreWeak(Address addr, llvm::Value *value, bool ignored);
+ void EmitARCCopyWeak(Address dst, Address src);
+ void EmitARCMoveWeak(Address dst, Address src);
llvm::Value *EmitARCRetainAutorelease(QualType type, llvm::Value *value);
llvm::Value *EmitARCRetainAutoreleaseNonBlock(llvm::Value *value);
llvm::Value *EmitARCStoreStrong(LValue lvalue, llvm::Value *value,
bool resultIgnored);
- llvm::Value *EmitARCStoreStrongCall(llvm::Value *addr, llvm::Value *value,
+ llvm::Value *EmitARCStoreStrongCall(Address addr, llvm::Value *value,
bool resultIgnored);
llvm::Value *EmitARCRetain(QualType type, llvm::Value *value);
llvm::Value *EmitARCRetainNonBlock(llvm::Value *value);
llvm::Value *EmitARCRetainBlock(llvm::Value *value, bool mandatory);
- void EmitARCDestroyStrong(llvm::Value *addr, ARCPreciseLifetime_t precise);
+ void EmitARCDestroyStrong(Address addr, ARCPreciseLifetime_t precise);
void EmitARCRelease(llvm::Value *value, ARCPreciseLifetime_t precise);
llvm::Value *EmitARCAutorelease(llvm::Value *value);
llvm::Value *EmitARCAutoreleaseReturnValue(llvm::Value *value);
@@ -2673,8 +2803,6 @@ public:
EmitARCStoreStrong(const BinaryOperator *e, bool ignored);
llvm::Value *EmitObjCThrowOperand(const Expr *expr);
-
- llvm::Value *EmitObjCProduceObject(QualType T, llvm::Value *Ptr);
llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr);
llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr);
@@ -2707,17 +2835,16 @@ public:
/// scalar type, returning the result.
llvm::Value *EmitScalarExpr(const Expr *E , bool IgnoreResultAssign = false);
- /// EmitScalarConversion - Emit a conversion from the specified type to the
- /// specified destination type, both of which are LLVM scalar types.
+ /// Emit a conversion from the specified type to the specified destination
+ /// type, both of which are LLVM scalar types.
llvm::Value *EmitScalarConversion(llvm::Value *Src, QualType SrcTy,
- QualType DstTy);
+ QualType DstTy, SourceLocation Loc);
- /// EmitComplexToScalarConversion - Emit a conversion from the specified
- /// complex type to the specified destination type, where the destination type
- /// is an LLVM scalar type.
+ /// Emit a conversion from the specified complex type to the specified
+ /// destination type, where the destination type is an LLVM scalar type.
llvm::Value *EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy,
- QualType DstTy);
-
+ QualType DstTy,
+ SourceLocation Loc);
/// EmitAggExpr - Emit the computation of the specified expression
/// of aggregate type. The result is computed into the given slot,
@@ -2728,11 +2855,6 @@ public:
/// aggregate type into a temporary LValue.
LValue EmitAggExprToLValue(const Expr *E);
- /// EmitGCMemmoveCollectable - Emit special API for structs with object
- /// pointers.
- void EmitGCMemmoveCollectable(llvm::Value *DestPtr, llvm::Value *SrcPtr,
- QualType Ty);
-
/// EmitExtendGCLifetime - Given a pointer to an Objective-C object,
/// make sure it survives garbage collection until this point.
void EmitExtendGCLifetime(llvm::Value *object);
@@ -2753,6 +2875,9 @@ public:
/// EmitLoadOfComplex - Load a complex number from the specified l-value.
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc);
+ Address emitAddrOfRealComponent(Address complex, QualType complexType);
+ Address emitAddrOfImagComponent(Address complex, QualType complexType);
+
/// AddInitializerToStaticVarDecl - Add the initializer for 'D' to the
/// global variable that has already been created for it. If the initializer
/// has a different type than GV does, this may free GV and return a different
@@ -2787,7 +2912,7 @@ public:
/// variables.
void GenerateCXXGlobalInitFunc(llvm::Function *Fn,
ArrayRef<llvm::Function *> CXXThreadLocals,
- llvm::GlobalVariable *Guard = nullptr);
+ Address Guard = Address::invalid());
/// GenerateCXXGlobalDtorsFunc - Generates code for destroying global
/// variables.
@@ -2802,8 +2927,7 @@ public:
void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest);
- void EmitSynthesizedCXXCopyCtor(llvm::Value *Dest, llvm::Value *Src,
- const Expr *Exp);
+ void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp);
void enterFullExpression(const ExprWithCleanups *E) {
if (E->getNumObjects() == 0) return;
@@ -2815,7 +2939,7 @@ public:
void EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Dest);
- RValue EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest = nullptr);
+ RValue EmitAtomicExpr(AtomicExpr *E);
//===--------------------------------------------------------------------===//
// Annotations Emission
@@ -2832,7 +2956,7 @@ public:
/// Emit field annotations for the given field & value. Returns the
/// annotation result.
- llvm::Value *EmitFieldAnnotations(const FieldDecl *D, llvm::Value *V);
+ Address EmitFieldAnnotations(const FieldDecl *D, Address V);
//===--------------------------------------------------------------------===//
// Internal Helpers
@@ -2885,6 +3009,11 @@ public:
StringRef CheckName, ArrayRef<llvm::Constant *> StaticArgs,
ArrayRef<llvm::Value *> DynamicArgs);
+ /// \brief Emit a slow path cross-DSO CFI check which calls __cfi_slowpath
+ /// if Cond if false.
+ void EmitCfiSlowPathCheck(llvm::Value *Cond, llvm::ConstantInt *TypeId,
+ llvm::Value *Ptr);
+
/// \brief Create a basic block that will call the trap intrinsic, and emit a
/// conditional branch to it, for the -ftrapv checks.
void EmitTrapCheck(llvm::Value *Checked);
@@ -2920,6 +3049,12 @@ private:
llvm::SmallVector<std::pair<llvm::Instruction *, llvm::Value *>, 4>
DeferredReplacements;
+ /// Set the address of a local variable.
+ void setAddrOfLocalVar(const VarDecl *VD, Address Addr) {
+ assert(!LocalDeclMap.count(VD) && "Decl already exists in LocalDeclMap!");
+ LocalDeclMap.insert({VD, Addr});
+ }
+
/// ExpandTypeFromArgs - Reconstruct a structure of type \arg Ty
/// from function arguments into \arg Dst. See ABIArgInfo::Expand.
///
@@ -2942,6 +3077,18 @@ private:
std::string &ConstraintStr,
SourceLocation Loc);
+ /// \brief Attempts to statically evaluate the object size of E. If that
+ /// fails, emits code to figure the size of E out for us. This is
+ /// pass_object_size aware.
+ llvm::Value *evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type,
+ llvm::IntegerType *ResType);
+
+ /// \brief Emits the size of E, as required by __builtin_object_size. This
+ /// function is aware of pass_object_size parameters, and will act accordingly
+ /// if E is a parameter with the pass_object_size attribute.
+ llvm::Value *emitBuiltinObjectSize(const Expr *E, unsigned Type,
+ llvm::IntegerType *ResType);
+
public:
#ifndef NDEBUG
// Determine whether the given argument is an Objective-C method
@@ -2966,12 +3113,11 @@ public:
/// EmitCallArgs - Emit call arguments for a function.
template <typename T>
void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo,
- CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd,
+ llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
const FunctionDecl *CalleeDecl = nullptr,
unsigned ParamsToSkip = 0) {
SmallVector<QualType, 16> ArgTypes;
- CallExpr::const_arg_iterator Arg = ArgBeg;
+ CallExpr::const_arg_iterator Arg = ArgRange.begin();
assert((ParamsToSkip == 0 || CallArgTypeInfo) &&
"Can't skip parameters if type info is not provided");
@@ -2984,7 +3130,7 @@ public:
for (auto I = CallArgTypeInfo->param_type_begin() + ParamsToSkip,
E = CallArgTypeInfo->param_type_end();
I != E; ++I, ++Arg) {
- assert(Arg != ArgEnd && "Running over edge of argument list!");
+ assert(Arg != ArgRange.end() && "Running over edge of argument list!");
assert((isGenericMethod ||
((*I)->isVariablyModifiedType() ||
(*I).getNonReferenceType()->isObjCRetainableType() ||
@@ -2992,7 +3138,7 @@ public:
.getCanonicalType((*I).getNonReferenceType())
.getTypePtr() ==
getContext()
- .getCanonicalType(Arg->getType())
+ .getCanonicalType((*Arg)->getType())
.getTypePtr())) &&
"type mismatch in call argument!");
ArgTypes.push_back(*I);
@@ -3001,23 +3147,46 @@ public:
// Either we've emitted all the call args, or we have a call to variadic
// function.
- assert(
- (Arg == ArgEnd || !CallArgTypeInfo || CallArgTypeInfo->isVariadic()) &&
- "Extra arguments in non-variadic function!");
+ assert((Arg == ArgRange.end() || !CallArgTypeInfo ||
+ CallArgTypeInfo->isVariadic()) &&
+ "Extra arguments in non-variadic function!");
// If we still have any arguments, emit them using the type of the argument.
- for (; Arg != ArgEnd; ++Arg)
- ArgTypes.push_back(getVarArgType(*Arg));
+ for (auto *A : llvm::make_range(Arg, ArgRange.end()))
+ ArgTypes.push_back(getVarArgType(A));
- EmitCallArgs(Args, ArgTypes, ArgBeg, ArgEnd, CalleeDecl, ParamsToSkip);
+ EmitCallArgs(Args, ArgTypes, ArgRange, CalleeDecl, ParamsToSkip);
}
void EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes,
- CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd,
+ llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
const FunctionDecl *CalleeDecl = nullptr,
unsigned ParamsToSkip = 0);
+ /// EmitPointerWithAlignment - Given an expression with a pointer
+ /// type, emit the value and compute our best estimate of the
+ /// alignment of the pointee.
+ ///
+ /// Note that this function will conservatively fall back on the type
+ /// when it doesn't
+ ///
+ /// \param Source - If non-null, this will be initialized with
+ /// information about the source of the alignment. Note that this
+ /// function will conservatively fall back on the type when it
+ /// doesn't recognize the expression, which means that sometimes
+ ///
+ /// a worst-case One
+ /// reasonable way to use this information is when there's a
+ /// language guarantee that the pointer must be aligned to some
+ /// stricter value, and we're simply trying to ensure that
+ /// sufficiently obvious uses of under-aligned objects don't get
+ /// miscompiled; for example, a placement new into the address of
+ /// a local variable. In such a case, it's quite reasonable to
+ /// just ignore the returned alignment when it isn't from an
+ /// explicit source.
+ Address EmitPointerWithAlignment(const Expr *Addr,
+ AlignmentSource *Source = nullptr);
+
private:
QualType getVarArgType(const Expr *Arg);
@@ -3027,16 +3196,11 @@ private:
void EmitDeclMetadata();
- CodeGenModule::ByrefHelpers *
- buildByrefHelpers(llvm::StructType &byrefType,
- const AutoVarEmission &emission);
+ BlockByrefHelpers *buildByrefHelpers(llvm::StructType &byrefType,
+ const AutoVarEmission &emission);
void AddObjCARCExceptionMetadata(llvm::Instruction *Inst);
- /// GetPointeeAlignment - Given an expression with a pointer type, emit the
- /// value and compute our best estimate of the alignment of the pointee.
- std::pair<llvm::Value*, unsigned> EmitPointerWithAlignment(const Expr *Addr);
-
llvm::Value *GetValueForARMHint(unsigned BuiltinID);
};
@@ -3059,17 +3223,23 @@ struct DominatingLLVMValue {
static saved_type save(CodeGenFunction &CGF, llvm::Value *value) {
if (!needsSaving(value)) return saved_type(value, false);
- // Otherwise we need an alloca.
- llvm::Value *alloca =
- CGF.CreateTempAlloca(value->getType(), "cond-cleanup.save");
+ // Otherwise, we need an alloca.
+ auto align = CharUnits::fromQuantity(
+ CGF.CGM.getDataLayout().getPrefTypeAlignment(value->getType()));
+ Address alloca =
+ CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save");
CGF.Builder.CreateStore(value, alloca);
- return saved_type(alloca, true);
+ return saved_type(alloca.getPointer(), true);
}
static llvm::Value *restore(CodeGenFunction &CGF, saved_type value) {
+ // If the value says it wasn't saved, trust that it's still dominating.
if (!value.getInt()) return value.getPointer();
- return CGF.Builder.CreateLoad(value.getPointer());
+
+ // Otherwise, it should be an alloca instruction, as set up in save().
+ auto alloca = cast<llvm::AllocaInst>(value.getPointer());
+ return CGF.Builder.CreateAlignedLoad(alloca, alloca->getAlignment());
}
};
@@ -3082,6 +3252,28 @@ template <class T> struct DominatingPointer<T,true> : DominatingLLVMValue {
}
};
+/// A specialization of DominatingValue for Address.
+template <> struct DominatingValue<Address> {
+ typedef Address type;
+
+ struct saved_type {
+ DominatingLLVMValue::saved_type SavedValue;
+ CharUnits Alignment;
+ };
+
+ static bool needsSaving(type value) {
+ return DominatingLLVMValue::needsSaving(value.getPointer());
+ }
+ static saved_type save(CodeGenFunction &CGF, type value) {
+ return { DominatingLLVMValue::save(CGF, value.getPointer()),
+ value.getAlignment() };
+ }
+ static type restore(CodeGenFunction &CGF, saved_type value) {
+ return Address(DominatingLLVMValue::restore(CGF, value.SavedValue),
+ value.Alignment);
+ }
+};
+
/// A specialization of DominatingValue for RValue.
template <> struct DominatingValue<RValue> {
typedef RValue type;
@@ -3090,15 +3282,17 @@ template <> struct DominatingValue<RValue> {
AggregateAddress, ComplexAddress };
llvm::Value *Value;
- Kind K;
- saved_type(llvm::Value *v, Kind k) : Value(v), K(k) {}
+ unsigned K : 3;
+ unsigned Align : 29;
+ saved_type(llvm::Value *v, Kind k, unsigned a = 0)
+ : Value(v), K(k), Align(a) {}
public:
static bool needsSaving(RValue value);
static saved_type save(CodeGenFunction &CGF, RValue value);
RValue restore(CodeGenFunction &CGF);
- // implementations in CGExprCXX.cpp
+ // implementations in CGCleanup.cpp
};
static bool needsSaving(type value) {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
index c9c48c7..97b1662 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenModule.h"
+#include "CGBlocks.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGCall.h"
@@ -52,6 +53,7 @@
#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MD5.h"
using namespace clang;
using namespace CodeGen;
@@ -64,8 +66,10 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
case TargetCXXABI::GenericARM:
case TargetCXXABI::iOS:
case TargetCXXABI::iOS64:
+ case TargetCXXABI::WatchOS:
case TargetCXXABI::GenericMIPS:
case TargetCXXABI::GenericItanium:
+ case TargetCXXABI::WebAssembly:
return CreateItaniumCXXABI(CGM);
case TargetCXXABI::Microsoft:
return CreateMicrosoftCXXABI(CGM);
@@ -77,17 +81,16 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
const PreprocessorOptions &PPO,
const CodeGenOptions &CGO, llvm::Module &M,
- const llvm::DataLayout &TD,
DiagnosticsEngine &diags,
CoverageSourceInfo *CoverageInfo)
: Context(C), LangOpts(C.getLangOpts()), HeaderSearchOpts(HSO),
PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags),
- TheDataLayout(TD), Target(C.getTargetInfo()), ABI(createCXXABI(*this)),
+ Target(C.getTargetInfo()), ABI(createCXXABI(*this)),
VMContext(M.getContext()), TBAA(nullptr), TheTargetCodeGenInfo(nullptr),
Types(*this), VTables(*this), ObjCRuntime(nullptr),
OpenCLRuntime(nullptr), OpenMPRuntime(nullptr), CUDARuntime(nullptr),
- DebugInfo(nullptr), ARCData(nullptr),
- NoObjCARCExceptionsMetadata(nullptr), RRData(nullptr), PGOReader(nullptr),
+ DebugInfo(nullptr), ObjCData(nullptr),
+ NoObjCARCExceptionsMetadata(nullptr), PGOReader(nullptr),
CFConstantStringClassRef(nullptr), ConstantStringClassRef(nullptr),
NSConstantStringType(nullptr), NSConcreteGlobalBlock(nullptr),
NSConcreteStackBlock(nullptr), BlockObjectAssign(nullptr),
@@ -106,7 +109,9 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
DoubleTy = llvm::Type::getDoubleTy(LLVMContext);
PointerWidthInBits = C.getTargetInfo().getPointerWidth(0);
PointerAlignInBytes =
- C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(0)).getQuantity();
+ C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(0)).getQuantity();
+ IntAlignInBytes =
+ C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity();
IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth());
IntPtrTy = llvm::IntegerType::get(LLVMContext, PointerWidthInBits);
Int8PtrTy = Int8Ty->getPointerTo(0);
@@ -139,9 +144,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
Block.GlobalUniqueCount = 0;
- if (C.getLangOpts().ObjCAutoRefCount)
- ARCData = new ARCEntrypoints();
- RRData = new RREntrypoints();
+ if (C.getLangOpts().ObjC1)
+ ObjCData = new ObjCEntrypoints();
if (!CodeGenOpts.InstrProfileInput.empty()) {
auto ReaderOrErr =
@@ -169,8 +173,7 @@ CodeGenModule::~CodeGenModule() {
delete TheTargetCodeGenInfo;
delete TBAA;
delete DebugInfo;
- delete ARCData;
- delete RRData;
+ delete ObjCData;
}
void CodeGenModule::createObjCRuntime() {
@@ -186,6 +189,7 @@ void CodeGenModule::createObjCRuntime() {
case ObjCRuntime::FragileMacOSX:
case ObjCRuntime::MacOSX:
case ObjCRuntime::iOS:
+ case ObjCRuntime::WatchOS:
ObjCRuntime = CreateMacObjCRuntime(*this);
return;
}
@@ -232,12 +236,27 @@ void CodeGenModule::applyReplacements() {
OldF->replaceAllUsesWith(Replacement);
if (NewF) {
NewF->removeFromParent();
- OldF->getParent()->getFunctionList().insertAfter(OldF, NewF);
+ OldF->getParent()->getFunctionList().insertAfter(OldF->getIterator(),
+ NewF);
}
OldF->eraseFromParent();
}
}
+void CodeGenModule::addGlobalValReplacement(llvm::GlobalValue *GV, llvm::Constant *C) {
+ GlobalValReplacements.push_back(std::make_pair(GV, C));
+}
+
+void CodeGenModule::applyGlobalValReplacements() {
+ for (auto &I : GlobalValReplacements) {
+ llvm::GlobalValue *GV = I.first;
+ llvm::Constant *C = I.second;
+
+ GV->replaceAllUsesWith(C);
+ GV->eraseFromParent();
+ }
+}
+
// This is only used in aliases that we created and we know they have a
// linear structure.
static const llvm::GlobalObject *getAliasedGlobal(const llvm::GlobalAlias &GA) {
@@ -340,6 +359,7 @@ void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags,
void CodeGenModule::Release() {
EmitDeferred();
+ applyGlobalValReplacements();
applyReplacements();
checkAliases();
EmitCXXGlobalInitFunc();
@@ -355,8 +375,15 @@ void CodeGenModule::Release() {
if (llvm::Function *CudaDtorFunction = CUDARuntime->makeModuleDtorFunction())
AddGlobalDtor(CudaDtorFunction);
}
- if (PGOReader && PGOStats.hasDiagnostics())
- PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName);
+ if (OpenMPRuntime)
+ if (llvm::Function *OpenMPRegistrationFunction =
+ OpenMPRuntime->emitRegistrationFunction())
+ AddGlobalCtor(OpenMPRegistrationFunction, 0);
+ if (PGOReader) {
+ getModule().setMaximumFunctionCount(PGOReader->getMaximumFunctionCount());
+ if (PGOStats.hasDiagnostics())
+ PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName);
+ }
EmitCtorList(GlobalCtors, "llvm.global_ctors");
EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitGlobalAnnotations();
@@ -370,11 +397,32 @@ void CodeGenModule::Release() {
(Context.getLangOpts().Modules || !LinkerOptionsMetadata.empty())) {
EmitModuleLinkOptions();
}
- if (CodeGenOpts.DwarfVersion)
+ if (CodeGenOpts.DwarfVersion) {
// We actually want the latest version when there are conflicts.
// We can change from Warning to Latest if such mode is supported.
getModule().addModuleFlag(llvm::Module::Warning, "Dwarf Version",
CodeGenOpts.DwarfVersion);
+ }
+ if (CodeGenOpts.EmitCodeView) {
+ // Indicate that we want CodeView in the metadata.
+ getModule().addModuleFlag(llvm::Module::Warning, "CodeView", 1);
+ }
+ if (CodeGenOpts.OptimizationLevel > 0 && CodeGenOpts.StrictVTablePointers) {
+ // We don't support LTO with 2 with different StrictVTablePointers
+ // FIXME: we could support it by stripping all the information introduced
+ // by StrictVTablePointers.
+
+ getModule().addModuleFlag(llvm::Module::Error, "StrictVTablePointers",1);
+
+ llvm::Metadata *Ops[2] = {
+ llvm::MDString::get(VMContext, "StrictVTablePointers"),
+ llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+ llvm::Type::getInt32Ty(VMContext), 1))};
+
+ getModule().addModuleFlag(llvm::Module::Require,
+ "StrictVTablePointersRequirement",
+ llvm::MDNode::get(VMContext, Ops));
+ }
if (DebugInfo)
// We support a single version in the linked module. The LLVM
// parser will drop debug info with a different version number
@@ -399,6 +447,11 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth);
}
+ if (CodeGenOpts.SanitizeCfiCrossDso) {
+ // Indicate that we want cross-DSO control flow integrity checks.
+ getModule().addModuleFlag(llvm::Module::Override, "Cross-DSO CFI", 1);
+ }
+
if (uint32_t PLevel = Context.getLangOpts().PICLevel) {
llvm::PICLevel::Level PL = llvm::PICLevel::Default;
switch (PLevel) {
@@ -450,12 +503,6 @@ llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) {
return TBAA->getTBAAStructInfo(QTy);
}
-llvm::MDNode *CodeGenModule::getTBAAStructTypeInfo(QualType QTy) {
- if (!TBAA)
- return nullptr;
- return TBAA->getTBAAStructTypeInfo(QTy);
-}
-
llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy,
llvm::MDNode *AccessN,
uint64_t O) {
@@ -468,9 +515,9 @@ llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy,
/// and struct-path aware TBAA, the tag has the same format:
/// base type, access type and offset.
/// When ConvertTypeToTag is true, we create a tag based on the scalar type.
-void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst,
- llvm::MDNode *TBAAInfo,
- bool ConvertTypeToTag) {
+void CodeGenModule::DecorateInstructionWithTBAA(llvm::Instruction *Inst,
+ llvm::MDNode *TBAAInfo,
+ bool ConvertTypeToTag) {
if (ConvertTypeToTag && TBAA)
Inst->setMetadata(llvm::LLVMContext::MD_tbaa,
TBAA->getTBAAScalarTagInfo(TBAAInfo));
@@ -478,6 +525,16 @@ void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst,
Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo);
}
+void CodeGenModule::DecorateInstructionWithInvariantGroup(
+ llvm::Instruction *I, const CXXRecordDecl *RD) {
+ llvm::Metadata *MD = CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
+ auto *MetaDataNode = dyn_cast<llvm::MDNode>(MD);
+ // Check if we have to wrap MDString in MDNode.
+ if (!MetaDataNode)
+ MetaDataNode = llvm::MDNode::get(getLLVMContext(), MD);
+ I->setMetadata(llvm::LLVMContext::MD_invariant_group, MetaDataNode);
+}
+
void CodeGenModule::Error(SourceLocation loc, StringRef message) {
unsigned diagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "%0");
getDiags().Report(Context.getFullLoc(loc), diagID) << message;
@@ -558,7 +615,20 @@ void CodeGenModule::setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const {
}
StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
- StringRef &FoundStr = MangledDeclNames[GD.getCanonicalDecl()];
+ GlobalDecl CanonicalGD = GD.getCanonicalDecl();
+
+ // Some ABIs don't have constructor variants. Make sure that base and
+ // complete constructors get mangled the same.
+ if (const auto *CD = dyn_cast<CXXConstructorDecl>(CanonicalGD.getDecl())) {
+ if (!getTarget().getCXXABI().hasConstructorVariants()) {
+ CXXCtorType OrigCtorType = GD.getCtorType();
+ assert(OrigCtorType == Ctor_Base || OrigCtorType == Ctor_Complete);
+ if (OrigCtorType == Ctor_Base)
+ CanonicalGD = GlobalDecl(CD, Ctor_Complete);
+ }
+ }
+
+ StringRef &FoundStr = MangledDeclNames[CanonicalGD];
if (!FoundStr.empty())
return FoundStr;
@@ -692,6 +762,21 @@ void CodeGenModule::setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F)
F->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);
}
+llvm::ConstantInt *
+CodeGenModule::CreateCfiIdForTypeMetadata(llvm::Metadata *MD) {
+ llvm::MDString *MDS = dyn_cast<llvm::MDString>(MD);
+ if (!MDS) return nullptr;
+
+ llvm::MD5 md5;
+ llvm::MD5::MD5Result result;
+ md5.update(MDS->getString());
+ md5.final(result);
+ uint64_t id = 0;
+ for (int i = 0; i < 8; ++i)
+ id |= static_cast<uint64_t>(result[i]) << (i * 8);
+ return llvm::ConstantInt::get(Int64Ty, id);
+}
+
void CodeGenModule::setFunctionDefinitionAttributes(const FunctionDecl *D,
llvm::Function *F) {
setNonAliasAttributes(D, F);
@@ -702,7 +787,8 @@ void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
llvm::Function *F) {
unsigned CallingConv;
AttributeListType AttributeList;
- ConstructAttributeList(Info, D, AttributeList, CallingConv, false);
+ ConstructAttributeList(F->getName(), Info, D, AttributeList, CallingConv,
+ false);
F->setAttributes(llvm::AttributeSet::get(getLLVMContext(), AttributeList));
F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
}
@@ -737,6 +823,21 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
if (!hasUnwindExceptions(LangOpts))
B.addAttribute(llvm::Attribute::NoUnwind);
+ if (LangOpts.getStackProtector() == LangOptions::SSPOn)
+ B.addAttribute(llvm::Attribute::StackProtect);
+ else if (LangOpts.getStackProtector() == LangOptions::SSPStrong)
+ B.addAttribute(llvm::Attribute::StackProtectStrong);
+ else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
+ B.addAttribute(llvm::Attribute::StackProtectReq);
+
+ if (!D) {
+ F->addAttributes(llvm::AttributeSet::FunctionIndex,
+ llvm::AttributeSet::get(
+ F->getContext(),
+ llvm::AttributeSet::FunctionIndex, B));
+ return;
+ }
+
if (D->hasAttr<NakedAttr>()) {
// Naked implies noinline: we should not be inlining such functions.
B.addAttribute(llvm::Attribute::Naked);
@@ -761,13 +862,6 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
if (D->hasAttr<MinSizeAttr>())
B.addAttribute(llvm::Attribute::MinSize);
- if (LangOpts.getStackProtector() == LangOptions::SSPOn)
- B.addAttribute(llvm::Attribute::StackProtect);
- else if (LangOpts.getStackProtector() == LangOptions::SSPStrong)
- B.addAttribute(llvm::Attribute::StackProtectStrong);
- else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
- B.addAttribute(llvm::Attribute::StackProtectReq);
-
F->addAttributes(llvm::AttributeSet::FunctionIndex,
llvm::AttributeSet::get(
F->getContext(), llvm::AttributeSet::FunctionIndex, B));
@@ -778,10 +872,8 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
F->addFnAttr(llvm::Attribute::NoInline);
// OptimizeNone wins over OptimizeForSize, MinSize, AlwaysInline.
- assert(!F->hasFnAttribute(llvm::Attribute::OptimizeForSize) &&
- "OptimizeNone and OptimizeForSize on same function!");
- assert(!F->hasFnAttribute(llvm::Attribute::MinSize) &&
- "OptimizeNone and MinSize on same function!");
+ F->removeFnAttr(llvm::Attribute::OptimizeForSize);
+ F->removeFnAttr(llvm::Attribute::MinSize);
assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
"OptimizeNone and AlwaysInline on same function!");
@@ -800,19 +892,24 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
if (alignment)
F->setAlignment(alignment);
- // C++ ABI requires 2-byte alignment for member functions.
- if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
- F->setAlignment(2);
+ // Some C++ ABIs require 2-byte alignment for member functions, in order to
+ // reserve a bit for differentiating between virtual and non-virtual member
+ // functions. If the current target's C++ ABI requires this and this is a
+ // member function, set its alignment accordingly.
+ if (getTarget().getCXXABI().areMemberFunctionsAligned()) {
+ if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
+ F->setAlignment(2);
+ }
}
void CodeGenModule::SetCommonAttributes(const Decl *D,
llvm::GlobalValue *GV) {
- if (const auto *ND = dyn_cast<NamedDecl>(D))
+ if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
setGlobalVisibility(GV, ND);
else
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
- if (D->hasAttr<UsedAttr>())
+ if (D && D->hasAttr<UsedAttr>())
addUsedGlobal(GV);
}
@@ -830,8 +927,9 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D,
llvm::GlobalObject *GO) {
SetCommonAttributes(D, GO);
- if (const SectionAttr *SA = D->getAttr<SectionAttr>())
- GO->setSection(SA->getName());
+ if (D)
+ if (const SectionAttr *SA = D->getAttr<SectionAttr>())
+ GO->setSection(SA->getName());
getTargetCodeGenInfo().setTargetAttributes(D, GO, *this);
}
@@ -872,6 +970,49 @@ static void setLinkageAndVisibilityForGV(llvm::GlobalValue *GV,
}
}
+void CodeGenModule::CreateFunctionBitSetEntry(const FunctionDecl *FD,
+ llvm::Function *F) {
+ // Only if we are checking indirect calls.
+ if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall))
+ return;
+
+ // Non-static class methods are handled via vtable pointer checks elsewhere.
+ if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
+ return;
+
+ // Additionally, if building with cross-DSO support...
+ if (CodeGenOpts.SanitizeCfiCrossDso) {
+ // Don't emit entries for function declarations. In cross-DSO mode these are
+ // handled with better precision at run time.
+ if (!FD->hasBody())
+ return;
+ // Skip available_externally functions. They won't be codegen'ed in the
+ // current module anyway.
+ if (getContext().GetGVALinkageForFunction(FD) == GVA_AvailableExternally)
+ return;
+ }
+
+ llvm::NamedMDNode *BitsetsMD =
+ getModule().getOrInsertNamedMetadata("llvm.bitsets");
+
+ llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType());
+ llvm::Metadata *BitsetOps[] = {
+ MD, llvm::ConstantAsMetadata::get(F),
+ llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(Int64Ty, 0))};
+ BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps));
+
+ // Emit a hash-based bit set entry for cross-DSO calls.
+ if (CodeGenOpts.SanitizeCfiCrossDso) {
+ if (auto TypeId = CreateCfiIdForTypeMetadata(MD)) {
+ llvm::Metadata *BitsetOps2[] = {
+ llvm::ConstantAsMetadata::get(TypeId),
+ llvm::ConstantAsMetadata::get(F),
+ llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(Int64Ty, 0))};
+ BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps2));
+ }
+ }
+}
+
void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
bool IsIncompleteFunction,
bool IsThunk) {
@@ -913,6 +1054,8 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
if (FD->isReplaceableGlobalAllocationFunction())
F->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoBuiltin);
+
+ CreateFunctionBitSetEntry(FD, F);
}
void CodeGenModule::addUsedGlobal(llvm::GlobalValue *GV) {
@@ -1104,9 +1247,16 @@ void CodeGenModule::EmitDeferred() {
llvm::GlobalValue *GV = G.GV;
G.GV = nullptr;
- assert(!GV || GV == GetGlobalValue(getMangledName(D)));
- if (!GV)
- GV = GetGlobalValue(getMangledName(D));
+ // We should call GetAddrOfGlobal with IsForDefinition set to true in order
+ // to get GlobalValue with exactly the type we need, not something that
+ // might had been created for another decl with the same mangled name but
+ // different type.
+ // FIXME: Support for variables is not implemented yet.
+ if (isa<FunctionDecl>(D.getDecl()))
+ GV = cast<llvm::GlobalValue>(GetAddrOfGlobal(D, /*IsForDefinition=*/true));
+ else
+ if (!GV)
+ GV = GetGlobalValue(getMangledName(D));
// Check to see if we've already emitted this. This is necessary
// for a couple of reasons: first, decls can end up in the
@@ -1208,7 +1358,7 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::Function *Fn,
if (SanitizerBL.isBlacklistedFunction(Fn->getName()))
return true;
// Blacklist by location.
- if (!Loc.isInvalid())
+ if (Loc.isValid())
return SanitizerBL.isBlacklistedLocation(Loc);
// If location is unknown, this may be a compiler-generated function. Assume
// it's located in the main file.
@@ -1271,7 +1421,7 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
return true;
}
-llvm::Constant *CodeGenModule::GetAddrOfUuidDescriptor(
+ConstantAddress CodeGenModule::GetAddrOfUuidDescriptor(
const CXXUuidofExpr* E) {
// Sema has verified that IIDSource has a __declspec(uuid()), and that its
// well-formed.
@@ -1279,9 +1429,12 @@ llvm::Constant *CodeGenModule::GetAddrOfUuidDescriptor(
std::string Name = "_GUID_" + Uuid.lower();
std::replace(Name.begin(), Name.end(), '-', '_');
+ // Contains a 32-bit field.
+ CharUnits Alignment = CharUnits::fromQuantity(4);
+
// Look for an existing global.
if (llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name))
- return GV;
+ return ConstantAddress(GV, Alignment);
llvm::Constant *Init = EmitUuidofInitializer(Uuid);
assert(Init && "failed to initialize as constant");
@@ -1291,20 +1444,22 @@ llvm::Constant *CodeGenModule::GetAddrOfUuidDescriptor(
/*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name);
if (supportsCOMDAT())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
- return GV;
+ return ConstantAddress(GV, Alignment);
}
-llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
+ConstantAddress CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
const AliasAttr *AA = VD->getAttr<AliasAttr>();
assert(AA && "No alias?");
+ CharUnits Alignment = getContext().getDeclAlign(VD);
llvm::Type *DeclTy = getTypes().ConvertTypeForMem(VD->getType());
// See if there is already something with the target's name in the module.
llvm::GlobalValue *Entry = GetGlobalValue(AA->getAliasee());
if (Entry) {
unsigned AS = getContext().getTargetAddressSpace(VD->getType());
- return llvm::ConstantExpr::getBitCast(Entry, DeclTy->getPointerTo(AS));
+ auto Ptr = llvm::ConstantExpr::getBitCast(Entry, DeclTy->getPointerTo(AS));
+ return ConstantAddress(Ptr, Alignment);
}
llvm::Constant *Aliasee;
@@ -1321,7 +1476,7 @@ llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
F->setLinkage(llvm::Function::ExternalWeakLinkage);
WeakRefReferences.insert(F);
- return Aliasee;
+ return ConstantAddress(Aliasee, Alignment);
}
void CodeGenModule::EmitGlobal(GlobalDecl GD) {
@@ -1353,6 +1508,11 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
}
}
+ // If this is OpenMP device, check if it is legal to emit this global
+ // normally.
+ if (OpenMPRuntime && OpenMPRuntime->emitTargetGlobal(GD))
+ return;
+
// Ignore declarations, they will be emitted on their first use.
if (const auto *FD = dyn_cast<FunctionDecl>(Global)) {
// Forward declarations are emitted lazily on first use.
@@ -1435,7 +1595,7 @@ namespace {
unsigned BuiltinID = FD->getBuiltinID();
if (!BuiltinID || !BI.isLibFunction(BuiltinID))
return true;
- StringRef BuiltinName = BI.GetName(BuiltinID);
+ StringRef BuiltinName = BI.getName(BuiltinID);
if (BuiltinName.startswith("__builtin_") &&
Name == BuiltinName.slice(strlen("__builtin_"), StringRef::npos)) {
Result = true;
@@ -1444,6 +1604,35 @@ namespace {
return true;
}
};
+
+ struct DLLImportFunctionVisitor
+ : public RecursiveASTVisitor<DLLImportFunctionVisitor> {
+ bool SafeToInline = true;
+
+ bool VisitVarDecl(VarDecl *VD) {
+ // A thread-local variable cannot be imported.
+ SafeToInline = !VD->getTLSKind();
+ return SafeToInline;
+ }
+
+ // Make sure we're not referencing non-imported vars or functions.
+ bool VisitDeclRefExpr(DeclRefExpr *E) {
+ ValueDecl *VD = E->getDecl();
+ if (isa<FunctionDecl>(VD))
+ SafeToInline = VD->hasAttr<DLLImportAttr>();
+ else if (VarDecl *V = dyn_cast<VarDecl>(VD))
+ SafeToInline = !V->hasGlobalStorage() || V->hasAttr<DLLImportAttr>();
+ return SafeToInline;
+ }
+ bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+ SafeToInline = E->getOperatorDelete()->hasAttr<DLLImportAttr>();
+ return SafeToInline;
+ }
+ bool VisitCXXNewExpr(CXXNewExpr *E) {
+ SafeToInline = E->getOperatorNew()->hasAttr<DLLImportAttr>();
+ return SafeToInline;
+ }
+ };
}
// isTriviallyRecursive - Check if this function calls another
@@ -1474,6 +1663,15 @@ CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
const auto *F = cast<FunctionDecl>(GD.getDecl());
if (CodeGenOpts.OptimizationLevel == 0 && !F->hasAttr<AlwaysInlineAttr>())
return false;
+
+ if (F->hasAttr<DLLImportAttr>()) {
+ // Check whether it would be safe to inline this dllimport function.
+ DLLImportFunctionVisitor Visitor;
+ Visitor.TraverseFunctionDecl(const_cast<FunctionDecl*>(F));
+ if (!Visitor.SafeToInline)
+ return false;
+ }
+
// PR9614. Avoid cases where the source code is lying to us. An available
// externally function should have an equivalent function somewhere else,
// but a function that calls itself is clearly not equivalent to the real
@@ -1537,6 +1735,9 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
llvm_unreachable("Invalid argument to EmitGlobalDefinition()");
}
+static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
+ llvm::Function *NewFn);
+
/// GetOrCreateLLVMFunction - If the specified mangled name is not in the
/// module, create and return an llvm Function with the specified type. If there
/// is something in the module with the specified name, return it potentially
@@ -1549,7 +1750,8 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
llvm::Type *Ty,
GlobalDecl GD, bool ForVTable,
bool DontDefer, bool IsThunk,
- llvm::AttributeSet ExtraAttrs) {
+ llvm::AttributeSet ExtraAttrs,
+ bool IsForDefinition) {
const Decl *D = GD.getDecl();
// Lookup the entry, lazily creating it if necessary.
@@ -1565,11 +1767,33 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>())
Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
- if (Entry->getType()->getElementType() == Ty)
+ // If there are two attempts to define the same mangled name, issue an
+ // error.
+ if (IsForDefinition && !Entry->isDeclaration()) {
+ GlobalDecl OtherGD;
+ // Check that GD is not yet in ExplicitDefinitions is required to make
+ // sure that we issue an error only once.
+ if (lookupRepresentativeDecl(MangledName, OtherGD) &&
+ (GD.getCanonicalDecl().getDecl() !=
+ OtherGD.getCanonicalDecl().getDecl()) &&
+ DiagnosedConflictingDefinitions.insert(GD).second) {
+ getDiags().Report(D->getLocation(),
+ diag::err_duplicate_mangled_name);
+ getDiags().Report(OtherGD.getDecl()->getLocation(),
+ diag::note_previous_definition);
+ }
+ }
+
+ if ((isa<llvm::Function>(Entry) || isa<llvm::GlobalAlias>(Entry)) &&
+ (Entry->getType()->getElementType() == Ty)) {
return Entry;
+ }
// Make sure the result is of the correct type.
- return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo());
+ // (If function is requested for a definition, we always need to create a new
+ // function, not just return a bitcast.)
+ if (!IsForDefinition)
+ return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo());
}
// This function doesn't have a complete type (for example, the return
@@ -1584,10 +1808,36 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
FTy = llvm::FunctionType::get(VoidTy, false);
IsIncompleteFunction = true;
}
-
- llvm::Function *F = llvm::Function::Create(FTy,
- llvm::Function::ExternalLinkage,
- MangledName, &getModule());
+
+ llvm::Function *F =
+ llvm::Function::Create(FTy, llvm::Function::ExternalLinkage,
+ Entry ? StringRef() : MangledName, &getModule());
+
+ // If we already created a function with the same mangled name (but different
+ // type) before, take its name and add it to the list of functions to be
+ // replaced with F at the end of CodeGen.
+ //
+ // This happens if there is a prototype for a function (e.g. "int f()") and
+ // then a definition of a different type (e.g. "int f(int x)").
+ if (Entry) {
+ F->takeName(Entry);
+
+ // This might be an implementation of a function without a prototype, in
+ // which case, try to do special replacement of calls which match the new
+ // prototype. The really key thing here is that we also potentially drop
+ // arguments from the call site so as to make a direct call, which makes the
+ // inliner happier and suppresses a number of optimizer warnings (!) about
+ // dropping arguments.
+ if (!Entry->use_empty()) {
+ ReplaceUsesOfNonProtoTypeWithRealFunction(Entry, F);
+ Entry->removeDeadConstantUsers();
+ }
+
+ llvm::Constant *BC = llvm::ConstantExpr::getBitCast(
+ F, Entry->getType()->getElementType()->getPointerTo());
+ addGlobalValReplacement(Entry, BC);
+ }
+
assert(F->getName() == MangledName && "name was uniqued!");
if (D)
SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk);
@@ -1660,13 +1910,19 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
llvm::Type *Ty,
bool ForVTable,
- bool DontDefer) {
+ bool DontDefer,
+ bool IsForDefinition) {
// If there was no specific requested type, just convert it now.
- if (!Ty)
- Ty = getTypes().ConvertType(cast<ValueDecl>(GD.getDecl())->getType());
-
+ if (!Ty) {
+ const auto *FD = cast<FunctionDecl>(GD.getDecl());
+ auto CanonTy = Context.getCanonicalType(FD->getType());
+ Ty = getTypes().ConvertFunctionType(CanonTy, FD);
+ }
+
StringRef MangledName = getMangledName(GD);
- return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer);
+ return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer,
+ /*IsThunk=*/false, llvm::AttributeSet(),
+ IsForDefinition);
}
/// CreateRuntimeFunction - Create a new runtime function with the specified
@@ -1781,7 +2037,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
if (D->getTLSKind()) {
if (D->getTLSKind() == VarDecl::TLS_Dynamic)
- CXXThreadLocals.push_back(std::make_pair(D, GV));
+ CXXThreadLocals.push_back(D);
setTLSMode(GV, *D);
}
@@ -1805,6 +2061,33 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
return GV;
}
+llvm::Constant *
+CodeGenModule::GetAddrOfGlobal(GlobalDecl GD,
+ bool IsForDefinition) {
+ if (isa<CXXConstructorDecl>(GD.getDecl()))
+ return getAddrOfCXXStructor(cast<CXXConstructorDecl>(GD.getDecl()),
+ getFromCtorType(GD.getCtorType()),
+ /*FnInfo=*/nullptr, /*FnType=*/nullptr,
+ /*DontDefer=*/false, IsForDefinition);
+ else if (isa<CXXDestructorDecl>(GD.getDecl()))
+ return getAddrOfCXXStructor(cast<CXXDestructorDecl>(GD.getDecl()),
+ getFromDtorType(GD.getDtorType()),
+ /*FnInfo=*/nullptr, /*FnType=*/nullptr,
+ /*DontDefer=*/false, IsForDefinition);
+ else if (isa<CXXMethodDecl>(GD.getDecl())) {
+ auto FInfo = &getTypes().arrangeCXXMethodDeclaration(
+ cast<CXXMethodDecl>(GD.getDecl()));
+ auto Ty = getTypes().GetFunctionType(*FInfo);
+ return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false,
+ IsForDefinition);
+ } else if (isa<FunctionDecl>(GD.getDecl())) {
+ const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
+ llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
+ return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false,
+ IsForDefinition);
+ } else
+ return GetAddrOfGlobalVar(cast<VarDecl>(GD.getDecl()));
+}
llvm::GlobalVariable *
CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
@@ -1893,8 +2176,8 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) {
}
CharUnits CodeGenModule::GetTargetTypeStoreSize(llvm::Type *Ty) const {
- return Context.toCharUnitsFromBits(
- TheDataLayout.getTypeStoreSizeInBits(Ty));
+ return Context.toCharUnitsFromBits(
+ getDataLayout().getTypeStoreSizeInBits(Ty));
}
unsigned CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D,
@@ -1986,7 +2269,18 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
const VarDecl *InitDecl;
const Expr *InitExpr = D->getAnyInitializer(InitDecl);
- if (!InitExpr) {
+ // CUDA E.2.4.1 "__shared__ variables cannot have an initialization as part
+ // of their declaration."
+ if (getLangOpts().CPlusPlus && getLangOpts().CUDAIsDevice
+ && D->hasAttr<CUDASharedAttr>()) {
+ if (InitExpr) {
+ const auto *C = dyn_cast<CXXConstructExpr>(InitExpr);
+ if (C == nullptr || !C->getConstructor()->hasTrivialBody())
+ Error(D->getLocation(),
+ "__shared__ variable cannot have an initialization.");
+ }
+ Init = llvm::UndefValue::get(getTypes().ConvertType(ASTTy));
+ } else if (!InitExpr) {
// This is a tentative definition; tentative definitions are
// implicitly initialized with { 0 }.
//
@@ -2072,6 +2366,17 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
if (D->hasAttr<AnnotateAttr>())
AddGlobalAnnotations(D, GV);
+ // CUDA B.2.1 "The __device__ qualifier declares a variable that resides on
+ // the device. [...]"
+ // CUDA B.2.2 "The __constant__ qualifier, optionally used together with
+ // __device__, declares a variable that: [...]
+ // Is accessible from all the threads within the grid and from the host
+ // through the runtime library (cudaGetSymbolAddress() / cudaGetSymbolSize()
+ // / cudaMemcpyToSymbol() / cudaMemcpyFromSymbol())."
+ if (GV && LangOpts.CUDA && LangOpts.CUDAIsDevice &&
+ (D->hasAttr<CUDAConstantAttr>() || D->hasAttr<CUDADeviceAttr>())) {
+ GV->setExternallyInitialized(true);
+ }
GV->setInitializer(Init);
// If it is safe to mark the global 'constant', do so now.
@@ -2091,12 +2396,17 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
llvm::GlobalValue::LinkageTypes Linkage =
getLLVMLinkageVarDefinition(D, GV->isConstant());
- // On Darwin, the backing variable for a C++11 thread_local variable always
- // has internal linkage; all accesses should just be calls to the
+ // On Darwin, if the normal linkage of a C++ thread_local variable is
+ // LinkOnce or Weak, we keep the normal linkage to prevent multiple
+ // copies within a linkage unit; otherwise, the backing variable has
+ // internal linkage and all accesses should just be calls to the
// Itanium-specified entry point, which has the normal linkage of the
- // variable.
+ // variable. This is to preserve the ability to change the implementation
+ // behind the scenes.
if (!D->isStaticLocal() && D->getTLSKind() == VarDecl::TLS_Dynamic &&
- Context.getTargetInfo().getTriple().isMacOSX())
+ Context.getTargetInfo().getTriple().isOSDarwin() &&
+ !llvm::GlobalVariable::isLinkOnceLinkage(Linkage) &&
+ !llvm::GlobalVariable::isWeakLinkage(Linkage))
Linkage = llvm::GlobalValue::InternalLinkage;
GV->setLinkage(Linkage);
@@ -2115,7 +2425,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
if (D->getTLSKind() && !GV->isThreadLocal()) {
if (D->getTLSKind() == VarDecl::TLS_Dynamic)
- CXXThreadLocals.push_back(std::make_pair(D, GV));
+ CXXThreadLocals.push_back(D);
setTLSMode(GV, *D);
}
@@ -2166,7 +2476,7 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context,
// Declarations with a required alignment do not have common linakge in MSVC
// mode.
- if (Context.getLangOpts().MSVCCompat) {
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
if (D->hasAttr<AlignedAttr>())
return true;
QualType VarType = D->getType();
@@ -2263,6 +2573,7 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
llvm::Type *newRetTy = newFn->getReturnType();
SmallVector<llvm::Value*, 4> newArgs;
+ SmallVector<llvm::OperandBundleDef, 1> newBundles;
for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end();
ui != ue; ) {
@@ -2330,16 +2641,19 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
// over the required information.
newArgs.append(callSite.arg_begin(), callSite.arg_begin() + argNo);
+ // Copy over any operand bundles.
+ callSite.getOperandBundlesAsDefs(newBundles);
+
llvm::CallSite newCall;
if (callSite.isCall()) {
- newCall = llvm::CallInst::Create(newFn, newArgs, "",
+ newCall = llvm::CallInst::Create(newFn, newArgs, newBundles, "",
callSite.getInstruction());
} else {
auto *oldInvoke = cast<llvm::InvokeInst>(callSite.getInstruction());
newCall = llvm::InvokeInst::Create(newFn,
oldInvoke->getNormalDest(),
oldInvoke->getUnwindDest(),
- newArgs, "",
+ newArgs, newBundles, "",
callSite.getInstruction());
}
newArgs.clear(); // for the next iteration
@@ -2357,6 +2671,7 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
// Copy debug location attached to CI.
if (callSite->getDebugLoc())
newCall->setDebugLoc(callSite->getDebugLoc());
+
callSite->eraseFromParent();
}
}
@@ -2397,66 +2712,14 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
// Get or create the prototype for the function.
- if (!GV) {
- llvm::Constant *C =
- GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer*/ true);
-
- // Strip off a bitcast if we got one back.
- if (auto *CE = dyn_cast<llvm::ConstantExpr>(C)) {
- assert(CE->getOpcode() == llvm::Instruction::BitCast);
- GV = cast<llvm::GlobalValue>(CE->getOperand(0));
- } else {
- GV = cast<llvm::GlobalValue>(C);
- }
- }
+ if (!GV || (GV->getType()->getElementType() != Ty))
+ GV = cast<llvm::GlobalValue>(GetAddrOfFunction(GD, Ty, /*ForVTable=*/false,
+ /*DontDefer=*/true,
+ /*IsForDefinition=*/true));
- if (!GV->isDeclaration()) {
- getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name);
- GlobalDecl OldGD = Manglings.lookup(GV->getName());
- if (auto *Prev = OldGD.getDecl())
- getDiags().Report(Prev->getLocation(), diag::note_previous_definition);
+ // Already emitted.
+ if (!GV->isDeclaration())
return;
- }
-
- if (GV->getType()->getElementType() != Ty) {
- // If the types mismatch then we have to rewrite the definition.
- assert(GV->isDeclaration() && "Shouldn't replace non-declaration");
-
- // F is the Function* for the one with the wrong type, we must make a new
- // Function* and update everything that used F (a declaration) with the new
- // Function* (which will be a definition).
- //
- // This happens if there is a prototype for a function
- // (e.g. "int f()") and then a definition of a different type
- // (e.g. "int f(int x)"). Move the old function aside so that it
- // doesn't interfere with GetAddrOfFunction.
- GV->setName(StringRef());
- auto *NewFn = cast<llvm::Function>(GetAddrOfFunction(GD, Ty));
-
- // This might be an implementation of a function without a
- // prototype, in which case, try to do special replacement of
- // calls which match the new prototype. The really key thing here
- // is that we also potentially drop arguments from the call site
- // so as to make a direct call, which makes the inliner happier
- // and suppresses a number of optimizer warnings (!) about
- // dropping arguments.
- if (!GV->use_empty()) {
- ReplaceUsesOfNonProtoTypeWithRealFunction(GV, NewFn);
- GV->removeDeadConstantUsers();
- }
-
- // Replace uses of F with the Function we will endow with a body.
- if (!GV->use_empty()) {
- llvm::Constant *NewPtrForOldDecl =
- llvm::ConstantExpr::getBitCast(NewFn, GV->getType());
- GV->replaceAllUsesWith(NewPtrForOldDecl);
- }
-
- // Ok, delete the old function now, which is dead.
- GV->eraseFromParent();
-
- GV = NewFn;
- }
// We need to set linkage and visibility on the function before
// generating code for it because various parts of IR generation
@@ -2521,8 +2784,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
// Create the new alias itself, but don't set a name yet.
auto *GA = llvm::GlobalAlias::create(
- cast<llvm::PointerType>(Aliasee->getType()),
- llvm::Function::ExternalLinkage, "", Aliasee, &getModule());
+ DeclTy, 0, llvm::Function::ExternalLinkage, "", Aliasee, &getModule());
if (Entry) {
if (GA->getAliasee() == Entry) {
@@ -2612,7 +2874,7 @@ GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
return *Map.insert(std::make_pair(String, nullptr)).first;
}
-llvm::Constant *
+ConstantAddress
CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
unsigned StringLength = 0;
bool isUTF16 = false;
@@ -2622,7 +2884,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
StringLength);
if (auto *C = Entry.second)
- return C;
+ return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty);
llvm::Constant *Zeros[] = { Zero, Zero };
@@ -2658,7 +2920,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
// String pointer.
llvm::Constant *C = nullptr;
if (isUTF16) {
- ArrayRef<uint16_t> Arr = llvm::makeArrayRef<uint16_t>(
+ auto Arr = llvm::makeArrayRef(
reinterpret_cast<uint16_t *>(const_cast<char *>(Entry.first().data())),
Entry.first().size() / 2);
C = llvm::ConstantDataArray::get(VMContext, Arr);
@@ -2699,25 +2961,28 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
Ty = getTypes().ConvertType(getContext().LongTy);
Fields[3] = llvm::ConstantInt::get(Ty, StringLength);
+ CharUnits Alignment = getPointerAlign();
+
// The struct.
C = llvm::ConstantStruct::get(STy, Fields);
GV = new llvm::GlobalVariable(getModule(), C->getType(), true,
llvm::GlobalVariable::PrivateLinkage, C,
"_unnamed_cfstring_");
GV->setSection("__DATA,__cfstring");
+ GV->setAlignment(Alignment.getQuantity());
Entry.second = GV;
- return GV;
+ return ConstantAddress(GV, Alignment);
}
-llvm::GlobalVariable *
+ConstantAddress
CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
unsigned StringLength = 0;
llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
GetConstantStringEntry(CFConstantStringMap, Literal, StringLength);
if (auto *C = Entry.second)
- return C;
+ return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty);
llvm::Constant *Zeros[] = { Zero, Zero };
@@ -2810,10 +3075,12 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
Fields[2] = llvm::ConstantInt::get(Ty, StringLength);
// The struct.
+ CharUnits Alignment = getPointerAlign();
C = llvm::ConstantStruct::get(NSConstantStringType, Fields);
GV = new llvm::GlobalVariable(getModule(), C->getType(), true,
llvm::GlobalVariable::PrivateLinkage, C,
"_unnamed_nsstring_");
+ GV->setAlignment(Alignment.getQuantity());
const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
const char *NSStringNonFragileABISection =
"__DATA,__objc_stringobj,regular,no_dead_strip";
@@ -2823,7 +3090,7 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
: NSStringSection);
Entry.second = GV;
- return GV;
+ return ConstantAddress(GV, Alignment);
}
QualType CodeGenModule::getObjCFastEnumerationStateType() {
@@ -2902,7 +3169,7 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) {
static llvm::GlobalVariable *
GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT,
CodeGenModule &CGM, StringRef GlobalName,
- unsigned Alignment) {
+ CharUnits Alignment) {
// OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
unsigned AddrSpace = 0;
if (CGM.getLangOpts().OpenCL)
@@ -2913,7 +3180,7 @@ GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT,
auto *GV = new llvm::GlobalVariable(
M, C->getType(), !CGM.getLangOpts().WritableStrings, LT, C, GlobalName,
nullptr, llvm::GlobalVariable::NotThreadLocal, AddrSpace);
- GV->setAlignment(Alignment);
+ GV->setAlignment(Alignment.getQuantity());
GV->setUnnamedAddr(true);
if (GV->isWeakForLinker()) {
assert(CGM.supportsCOMDAT() && "Only COFF uses weak string literals");
@@ -2925,20 +3192,19 @@ GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT,
/// GetAddrOfConstantStringFromLiteral - Return a pointer to a
/// constant array for the given string literal.
-llvm::GlobalVariable *
+ConstantAddress
CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S,
StringRef Name) {
- auto Alignment =
- getContext().getAlignOfGlobalVarInChars(S->getType()).getQuantity();
+ CharUnits Alignment = getContext().getAlignOfGlobalVarInChars(S->getType());
llvm::Constant *C = GetConstantArrayFromStringLiteral(S);
llvm::GlobalVariable **Entry = nullptr;
if (!LangOpts.WritableStrings) {
Entry = &ConstantStringMap[C];
if (auto GV = *Entry) {
- if (Alignment > GV->getAlignment())
- GV->setAlignment(Alignment);
- return GV;
+ if (Alignment.getQuantity() > GV->getAlignment())
+ GV->setAlignment(Alignment.getQuantity());
+ return ConstantAddress(GV, Alignment);
}
}
@@ -2954,7 +3220,6 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S,
getCXXABI().getMangleContext().shouldMangleStringLiteral(S)) {
llvm::raw_svector_ostream Out(MangledNameBuffer);
getCXXABI().getMangleContext().mangleStringLiteral(S, Out);
- Out.flush();
LT = llvm::GlobalValue::LinkOnceODRLinkage;
GlobalVariableName = MangledNameBuffer;
@@ -2969,12 +3234,12 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S,
SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "<string literal>",
QualType());
- return GV;
+ return ConstantAddress(GV, Alignment);
}
/// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant
/// array for the given ObjCEncodeExpr node.
-llvm::GlobalVariable *
+ConstantAddress
CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) {
std::string Str;
getContext().getObjCEncodingForType(E->getEncodedType(), Str);
@@ -2985,14 +3250,11 @@ CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) {
/// GetAddrOfConstantCString - Returns a pointer to a character array containing
/// the literal and a terminating '\0' character.
/// The result has pointer to array type.
-llvm::GlobalVariable *CodeGenModule::GetAddrOfConstantCString(
- const std::string &Str, const char *GlobalName, unsigned Alignment) {
+ConstantAddress CodeGenModule::GetAddrOfConstantCString(
+ const std::string &Str, const char *GlobalName) {
StringRef StrWithNull(Str.c_str(), Str.size() + 1);
- if (Alignment == 0) {
- Alignment = getContext()
- .getAlignOfGlobalVarInChars(getContext().CharTy)
- .getQuantity();
- }
+ CharUnits Alignment =
+ getContext().getAlignOfGlobalVarInChars(getContext().CharTy);
llvm::Constant *C =
llvm::ConstantDataArray::getString(getLLVMContext(), StrWithNull, false);
@@ -3002,9 +3264,9 @@ llvm::GlobalVariable *CodeGenModule::GetAddrOfConstantCString(
if (!LangOpts.WritableStrings) {
Entry = &ConstantStringMap[C];
if (auto GV = *Entry) {
- if (Alignment > GV->getAlignment())
- GV->setAlignment(Alignment);
- return GV;
+ if (Alignment.getQuantity() > GV->getAlignment())
+ GV->setAlignment(Alignment.getQuantity());
+ return ConstantAddress(GV, Alignment);
}
}
@@ -3016,10 +3278,10 @@ llvm::GlobalVariable *CodeGenModule::GetAddrOfConstantCString(
GlobalName, Alignment);
if (Entry)
*Entry = GV;
- return GV;
+ return ConstantAddress(GV, Alignment);
}
-llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
+ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary(
const MaterializeTemporaryExpr *E, const Expr *Init) {
assert((E->getStorageDuration() == SD_Static ||
E->getStorageDuration() == SD_Thread) && "not a global temporary");
@@ -3031,9 +3293,10 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
if (Init == E->GetTemporaryExpr())
MaterializedType = E->getType();
- llvm::Constant *&Slot = MaterializedGlobalTemporaryMap[E];
- if (Slot)
- return Slot;
+ CharUnits Align = getContext().getTypeAlignInChars(MaterializedType);
+
+ if (llvm::Constant *Slot = MaterializedGlobalTemporaryMap[E])
+ return ConstantAddress(Slot, Align);
// FIXME: If an externally-visible declaration extends multiple temporaries,
// we need to give each temporary the same name in every translation unit (and
@@ -3042,7 +3305,6 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
llvm::raw_svector_ostream Out(Name);
getCXXABI().getMangleContext().mangleReferenceTemporary(
VD, E->getManglingNumber(), Out);
- Out.flush();
APValue *Value = nullptr;
if (E->getStorageDuration() == SD_Static) {
@@ -3098,14 +3360,13 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary(
/*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal,
AddrSpace);
setGlobalVisibility(GV, VD);
- GV->setAlignment(
- getContext().getTypeAlignInChars(MaterializedType).getQuantity());
+ GV->setAlignment(Align.getQuantity());
if (supportsCOMDAT() && GV->isWeakForLinker())
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
if (VD->getTLSKind())
setTLSMode(GV, *VD);
- Slot = GV;
- return GV;
+ MaterializedGlobalTemporaryMap[E] = GV;
+ return ConstantAddress(GV, Align);
}
/// EmitObjCPropertyImplementations - Emit information for synthesized
@@ -3358,6 +3619,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
// File-scope asm is ignored during device-side CUDA compilation.
if (LangOpts.CUDA && LangOpts.CUDAIsDevice)
break;
+ // File-scope asm is ignored during device-side OpenMP compilation.
+ if (LangOpts.OpenMPIsDevice)
+ break;
auto *AD = cast<FileScopeAsmDecl>(D);
getModule().appendModuleInlineAsm(AD->getAsmString()->getString());
break;
@@ -3367,11 +3631,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
auto *Import = cast<ImportDecl>(D);
// Ignore import declarations that come from imported modules.
- if (clang::Module *Owner = Import->getImportedOwningModule()) {
- if (getLangOpts().CurrentModule.empty() ||
- Owner->getTopLevelModule()->Name == getLangOpts().CurrentModule)
- break;
- }
+ if (Import->getImportedOwningModule())
+ break;
if (CGDebugInfo *DI = getModuleDebugInfo())
DI->EmitImportDecl(*Import);
@@ -3412,7 +3673,7 @@ void CodeGenModule::AddDeferredUnusedCoverageMapping(Decl *D) {
case Decl::ObjCMethod:
case Decl::CXXConstructor:
case Decl::CXXDestructor: {
- if (!cast<FunctionDecl>(D)->hasBody())
+ if (!cast<FunctionDecl>(D)->doesThisDeclarationHaveABody())
return;
auto I = DeferredEmptyCoverageMappingDecls.find(D);
if (I == DeferredEmptyCoverageMappingDecls.end())
@@ -3541,10 +3802,12 @@ bool CodeGenModule::lookupRepresentativeDecl(StringRef MangledName,
void CodeGenModule::EmitDeclMetadata() {
llvm::NamedMDNode *GlobalMetadata = nullptr;
- // StaticLocalDeclMap
for (auto &I : MangledDeclNames) {
llvm::GlobalValue *Addr = getModule().getNamedValue(I.second);
- EmitGlobalDeclMetadata(*this, GlobalMetadata, I.first, Addr);
+ // Some mangled names don't necessarily have an associated GlobalValue
+ // in this module, e.g. if we mangled it for DebugInfo.
+ if (Addr)
+ EmitGlobalDeclMetadata(*this, GlobalMetadata, I.first, Addr);
}
}
@@ -3562,7 +3825,7 @@ void CodeGenFunction::EmitDeclMetadata() {
for (auto &I : LocalDeclMap) {
const Decl *D = I.first;
- llvm::Value *Addr = I.second;
+ llvm::Value *Addr = I.second.getPointer();
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(Addr)) {
llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D);
Alloca->setMetadata(
@@ -3643,12 +3906,6 @@ llvm::Constant *CodeGenModule::EmitUuidofInitializer(StringRef Uuid) {
return llvm::ConstantStruct::getAnon(Fields);
}
-llvm::Constant *
-CodeGenModule::getAddrOfCXXCatchHandlerType(QualType Ty,
- QualType CatchHandlerType) {
- return getCXXABI().getAddrOfCXXCatchHandlerType(Ty, CatchHandlerType);
-}
-
llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
bool ForEH) {
// Return a bogus pointer if RTTI is disabled, unless it's for EH.
@@ -3671,22 +3928,82 @@ void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) {
VD->getAnyInitializer() &&
!VD->getAnyInitializer()->isConstantInitializer(getContext(),
/*ForRef=*/false);
+
+ Address Addr(GetAddrOfGlobalVar(VD), getContext().getDeclAlign(VD));
if (auto InitFunction = getOpenMPRuntime().emitThreadPrivateVarDefinition(
- VD, GetAddrOfGlobalVar(VD), RefExpr->getLocStart(), PerformInit))
+ VD, Addr, RefExpr->getLocStart(), PerformInit))
CXXGlobalInits.push_back(InitFunction);
}
}
-llvm::MDTuple *CodeGenModule::CreateVTableBitSetEntry(
- llvm::GlobalVariable *VTable, CharUnits Offset, const CXXRecordDecl *RD) {
- std::string OutName;
- llvm::raw_string_ostream Out(OutName);
- getCXXABI().getMangleContext().mangleCXXVTableBitSet(RD, Out);
+llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) {
+ llvm::Metadata *&InternalId = MetadataIdMap[T.getCanonicalType()];
+ if (InternalId)
+ return InternalId;
+
+ if (isExternallyVisible(T->getLinkage())) {
+ std::string OutName;
+ llvm::raw_string_ostream Out(OutName);
+ getCXXABI().getMangleContext().mangleTypeName(T, Out);
+
+ InternalId = llvm::MDString::get(getLLVMContext(), Out.str());
+ } else {
+ InternalId = llvm::MDNode::getDistinct(getLLVMContext(),
+ llvm::ArrayRef<llvm::Metadata *>());
+ }
+
+ return InternalId;
+}
+void CodeGenModule::CreateVTableBitSetEntry(llvm::NamedMDNode *BitsetsMD,
+ llvm::GlobalVariable *VTable,
+ CharUnits Offset,
+ const CXXRecordDecl *RD) {
+ llvm::Metadata *MD =
+ CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
llvm::Metadata *BitsetOps[] = {
- llvm::MDString::get(getLLVMContext(), Out.str()),
- llvm::ConstantAsMetadata::get(VTable),
+ MD, llvm::ConstantAsMetadata::get(VTable),
llvm::ConstantAsMetadata::get(
llvm::ConstantInt::get(Int64Ty, Offset.getQuantity()))};
- return llvm::MDTuple::get(getLLVMContext(), BitsetOps);
+ BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps));
+
+ if (CodeGenOpts.SanitizeCfiCrossDso) {
+ if (auto TypeId = CreateCfiIdForTypeMetadata(MD)) {
+ llvm::Metadata *BitsetOps2[] = {
+ llvm::ConstantAsMetadata::get(TypeId),
+ llvm::ConstantAsMetadata::get(VTable),
+ llvm::ConstantAsMetadata::get(
+ llvm::ConstantInt::get(Int64Ty, Offset.getQuantity()))};
+ BitsetsMD->addOperand(llvm::MDTuple::get(getLLVMContext(), BitsetOps2));
+ }
+ }
+}
+
+// Fills in the supplied string map with the set of target features for the
+// passed in function.
+void CodeGenModule::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
+ const FunctionDecl *FD) {
+ StringRef TargetCPU = Target.getTargetOpts().CPU;
+ if (const auto *TD = FD->getAttr<TargetAttr>()) {
+ // If we have a TargetAttr build up the feature map based on that.
+ TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse();
+
+ // Make a copy of the features as passed on the command line into the
+ // beginning of the additional features from the function to override.
+ ParsedAttr.first.insert(ParsedAttr.first.begin(),
+ Target.getTargetOpts().FeaturesAsWritten.begin(),
+ Target.getTargetOpts().FeaturesAsWritten.end());
+
+ if (ParsedAttr.second != "")
+ TargetCPU = ParsedAttr.second;
+
+ // Now populate the feature map, first with the TargetCPU which is either
+ // the default or a new one from the target attribute string. Then we'll use
+ // the passed in features (FeaturesAsWritten) along with the new ones from
+ // the attribute.
+ Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, ParsedAttr.first);
+ } else {
+ Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU,
+ Target.getTargetOpts().Features);
+ }
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
index dd167a2..fdb4d78 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_LIB_CODEGEN_CODEGENMODULE_H
#include "CGVTables.h"
+#include "CodeGenTypeCache.h"
#include "CodeGenTypes.h"
#include "SanitizerMetadata.h"
#include "clang/AST/Attr.h"
@@ -30,7 +31,6 @@
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueHandle.h"
@@ -108,65 +108,14 @@ struct OrderGlobalInits {
}
};
-struct CodeGenTypeCache {
- /// void
- llvm::Type *VoidTy;
+struct ObjCEntrypoints {
+ ObjCEntrypoints() { memset(this, 0, sizeof(*this)); }
- /// i8, i16, i32, and i64
- llvm::IntegerType *Int8Ty, *Int16Ty, *Int32Ty, *Int64Ty;
- /// float, double
- llvm::Type *FloatTy, *DoubleTy;
-
- /// int
- llvm::IntegerType *IntTy;
-
- /// intptr_t, size_t, and ptrdiff_t, which we assume are the same size.
- union {
- llvm::IntegerType *IntPtrTy;
- llvm::IntegerType *SizeTy;
- llvm::IntegerType *PtrDiffTy;
- };
-
- /// void* in address space 0
- union {
- llvm::PointerType *VoidPtrTy;
- llvm::PointerType *Int8PtrTy;
- };
-
- /// void** in address space 0
- union {
- llvm::PointerType *VoidPtrPtrTy;
- llvm::PointerType *Int8PtrPtrTy;
- };
-
- /// The width of a pointer into the generic address space.
- unsigned char PointerWidthInBits;
-
- /// The size and alignment of a pointer into the generic address
- /// space.
- union {
- unsigned char PointerAlignInBytes;
- unsigned char PointerSizeInBytes;
- unsigned char SizeSizeInBytes; // sizeof(size_t)
- };
-
- llvm::CallingConv::ID RuntimeCC;
- llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
- llvm::CallingConv::ID BuiltinCC;
- llvm::CallingConv::ID getBuiltinCC() const { return BuiltinCC; }
-};
-
-struct RREntrypoints {
- RREntrypoints() { memset(this, 0, sizeof(*this)); }
- /// void objc_autoreleasePoolPop(void*);
+ /// void objc_autoreleasePoolPop(void*);
llvm::Constant *objc_autoreleasePoolPop;
/// void *objc_autoreleasePoolPush(void);
llvm::Constant *objc_autoreleasePoolPush;
-};
-
-struct ARCEntrypoints {
- ARCEntrypoints() { memset(this, 0, sizeof(*this)); }
/// id objc_autorelease(id);
llvm::Constant *objc_autorelease;
@@ -257,6 +206,36 @@ public:
void reportDiagnostics(DiagnosticsEngine &Diags, StringRef MainFile);
};
+/// A pair of helper functions for a __block variable.
+class BlockByrefHelpers : public llvm::FoldingSetNode {
+ // MSVC requires this type to be complete in order to process this
+ // header.
+public:
+ llvm::Constant *CopyHelper;
+ llvm::Constant *DisposeHelper;
+
+ /// The alignment of the field. This is important because
+ /// different offsets to the field within the byref struct need to
+ /// have different helper functions.
+ CharUnits Alignment;
+
+ BlockByrefHelpers(CharUnits alignment) : Alignment(alignment) {}
+ BlockByrefHelpers(const BlockByrefHelpers &) = default;
+ virtual ~BlockByrefHelpers();
+
+ void Profile(llvm::FoldingSetNodeID &id) const {
+ id.AddInteger(Alignment.getQuantity());
+ profileImpl(id);
+ }
+ virtual void profileImpl(llvm::FoldingSetNodeID &id) const = 0;
+
+ virtual bool needsCopy() const { return true; }
+ virtual void emitCopy(CodeGenFunction &CGF, Address dest, Address src) = 0;
+
+ virtual bool needsDispose() const { return true; }
+ virtual void emitDispose(CodeGenFunction &CGF, Address field) = 0;
+};
+
/// This class organizes the cross-function state that is used while generating
/// LLVM code.
class CodeGenModule : public CodeGenTypeCache {
@@ -285,7 +264,6 @@ private:
const CodeGenOptions &CodeGenOpts;
llvm::Module &TheModule;
DiagnosticsEngine &Diags;
- const llvm::DataLayout &TheDataLayout;
const TargetInfo &Target;
std::unique_ptr<CGCXXABI> ABI;
llvm::LLVMContext &VMContext;
@@ -307,9 +285,8 @@ private:
CGOpenMPRuntime* OpenMPRuntime;
CGCUDARuntime* CUDARuntime;
CGDebugInfo* DebugInfo;
- ARCEntrypoints *ARCData;
+ ObjCEntrypoints *ObjCData;
llvm::MDNode *NoObjCARCExceptionsMetadata;
- RREntrypoints *RRData;
std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
InstrProfStats PGOStats;
@@ -343,6 +320,17 @@ private:
typedef llvm::StringMap<llvm::TrackingVH<llvm::Constant> > ReplacementsTy;
ReplacementsTy Replacements;
+ /// List of global values to be replaced with something else. Used when we
+ /// want to replace a GlobalValue but can't identify it by its mangled name
+ /// anymore (because the name is already taken).
+ llvm::SmallVector<std::pair<llvm::GlobalValue *, llvm::Constant *>, 8>
+ GlobalValReplacements;
+
+ /// Set of global decls for which we already diagnosed mangled name conflict.
+ /// Required to not issue a warning (on a mangling conflict) multiple times
+ /// for the same decl.
+ llvm::DenseSet<GlobalDecl> DiagnosedConflictingDefinitions;
+
/// A queue of (optional) vtables to consider emitting.
std::vector<const CXXRecordDecl*> DeferredVTables;
@@ -390,13 +378,12 @@ private:
StaticExternCMap StaticExternCValues;
/// \brief thread_local variables defined or used in this TU.
- std::vector<std::pair<const VarDecl *, llvm::GlobalVariable *> >
- CXXThreadLocals;
+ std::vector<const VarDecl *> CXXThreadLocals;
/// \brief thread_local variables with initializers that need to run
/// before any thread_local variable in this TU is odr-used.
std::vector<llvm::Function *> CXXThreadLocalInits;
- std::vector<llvm::GlobalVariable *> CXXThreadLocalInitVars;
+ std::vector<const VarDecl *> CXXThreadLocalInitVars;
/// Global variables with initializers that need to run before main.
std::vector<llvm::Function *> CXXGlobalInits;
@@ -491,12 +478,16 @@ private:
llvm::DenseMap<const Decl *, bool> DeferredEmptyCoverageMappingDecls;
std::unique_ptr<CoverageMappingModuleGen> CoverageMapping;
+
+ /// Mapping from canonical types to their metadata identifiers. We need to
+ /// maintain this mapping because identifiers may be formed from distinct
+ /// MDNodes.
+ llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap;
+
public:
- CodeGenModule(ASTContext &C,
- const HeaderSearchOptions &headersearchopts,
+ CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts,
const PreprocessorOptions &ppopts,
- const CodeGenOptions &CodeGenOpts,
- llvm::Module &M, const llvm::DataLayout &TD,
+ const CodeGenOptions &CodeGenOpts, llvm::Module &M,
DiagnosticsEngine &Diags,
CoverageSourceInfo *CoverageInfo = nullptr);
@@ -534,14 +525,9 @@ public:
return *CUDARuntime;
}
- ARCEntrypoints &getARCEntrypoints() const {
- assert(getLangOpts().ObjCAutoRefCount && ARCData != nullptr);
- return *ARCData;
- }
-
- RREntrypoints &getRREntrypoints() const {
- assert(RRData != nullptr);
- return *RRData;
+ ObjCEntrypoints &getObjCEntrypoints() const {
+ assert(ObjCData != nullptr);
+ return *ObjCData;
}
InstrProfStats &getPGOStats() { return PGOStats; }
@@ -614,7 +600,9 @@ public:
const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
llvm::Module &getModule() const { return TheModule; }
DiagnosticsEngine &getDiags() const { return Diags; }
- const llvm::DataLayout &getDataLayout() const { return TheDataLayout; }
+ const llvm::DataLayout &getDataLayout() const {
+ return TheModule.getDataLayout();
+ }
const TargetInfo &getTarget() const { return Target; }
const llvm::Triple &getTriple() const;
bool supportsCOMDAT() const;
@@ -645,8 +633,6 @@ public:
llvm::MDNode *getTBAAInfo(QualType QTy);
llvm::MDNode *getTBAAInfoForVTablePtr();
llvm::MDNode *getTBAAStructInfo(QualType QTy);
- /// Return the MDNode in the type DAG for the given struct type.
- llvm::MDNode *getTBAAStructTypeInfo(QualType QTy);
/// Return the path-aware tag for given base type, access node and offset.
llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN,
uint64_t O);
@@ -660,9 +646,13 @@ public:
/// is the same as the type. For struct-path aware TBAA, the tag
/// is different from the type: base type, access type and offset.
/// When ConvertTypeToTag is true, we create a tag based on the scalar type.
- void DecorateInstruction(llvm::Instruction *Inst,
- llvm::MDNode *TBAAInfo,
- bool ConvertTypeToTag = true);
+ void DecorateInstructionWithTBAA(llvm::Instruction *Inst,
+ llvm::MDNode *TBAAInfo,
+ bool ConvertTypeToTag = true);
+
+ /// Adds !invariant.barrier !tag to instruction
+ void DecorateInstructionWithInvariantGroup(llvm::Instruction *I,
+ const CXXRecordDecl *RD);
/// Emit the given number of characters as a value of type size_t.
llvm::ConstantInt *getSize(CharUnits numChars);
@@ -683,18 +673,7 @@ public:
llvm_unreachable("unknown visibility!");
}
- llvm::Constant *GetAddrOfGlobal(GlobalDecl GD) {
- if (isa<CXXConstructorDecl>(GD.getDecl()))
- return getAddrOfCXXStructor(cast<CXXConstructorDecl>(GD.getDecl()),
- getFromCtorType(GD.getCtorType()));
- else if (isa<CXXDestructorDecl>(GD.getDecl()))
- return getAddrOfCXXStructor(cast<CXXDestructorDecl>(GD.getDecl()),
- getFromDtorType(GD.getDtorType()));
- else if (isa<FunctionDecl>(GD.getDecl()))
- return GetAddrOfFunction(GD);
- else
- return GetAddrOfGlobalVar(cast<VarDecl>(GD.getDecl()));
- }
+ llvm::Constant *GetAddrOfGlobal(GlobalDecl GD, bool IsForDefinition = false);
/// Will return a global variable of the given type. If a variable with a
/// different type already exists then a new variable with the right type
@@ -706,6 +685,7 @@ public:
llvm::Function *
CreateGlobalInitOrDestructFunction(llvm::FunctionType *ty, const Twine &name,
+ const CGFunctionInfo &FI,
SourceLocation Loc = SourceLocation(),
bool TLS = false);
@@ -724,24 +704,37 @@ public:
/// Return the address of the given function. If Ty is non-null, then this
/// function will use the specified type if it has to create it.
- llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = 0,
+ llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = nullptr,
bool ForVTable = false,
- bool DontDefer = false);
+ bool DontDefer = false,
+ bool IsForDefinition = false);
/// Get the address of the RTTI descriptor for the given type.
llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false);
- llvm::Constant *getAddrOfCXXCatchHandlerType(QualType Ty,
- QualType CatchHandlerType);
-
/// Get the address of a uuid descriptor .
- llvm::Constant *GetAddrOfUuidDescriptor(const CXXUuidofExpr* E);
+ ConstantAddress GetAddrOfUuidDescriptor(const CXXUuidofExpr* E);
/// Get the address of the thunk for the given global decl.
llvm::Constant *GetAddrOfThunk(GlobalDecl GD, const ThunkInfo &Thunk);
/// Get a reference to the target of VD.
- llvm::Constant *GetWeakRefReference(const ValueDecl *VD);
+ ConstantAddress GetWeakRefReference(const ValueDecl *VD);
+
+ /// Returns the assumed alignment of an opaque pointer to the given class.
+ CharUnits getClassPointerAlignment(const CXXRecordDecl *CD);
+
+ /// Returns the assumed alignment of a virtual base of a class.
+ CharUnits getVBaseAlignment(CharUnits DerivedAlign,
+ const CXXRecordDecl *Derived,
+ const CXXRecordDecl *VBase);
+
+ /// Given a class pointer with an actual known alignment, and the
+ /// expected alignment of an object at a dynamic offset w.r.t that
+ /// pointer, return the alignment to assume at the offset.
+ CharUnits getDynamicOffsetAlignment(CharUnits ActualAlign,
+ const CXXRecordDecl *Class,
+ CharUnits ExpectedTargetAlign);
CharUnits
computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass,
@@ -755,35 +748,7 @@ public:
CastExpr::path_const_iterator PathBegin,
CastExpr::path_const_iterator PathEnd);
- /// A pair of helper functions for a __block variable.
- class ByrefHelpers : public llvm::FoldingSetNode {
- public:
- llvm::Constant *CopyHelper;
- llvm::Constant *DisposeHelper;
-
- /// The alignment of the field. This is important because
- /// different offsets to the field within the byref struct need to
- /// have different helper functions.
- CharUnits Alignment;
-
- ByrefHelpers(CharUnits alignment) : Alignment(alignment) {}
- virtual ~ByrefHelpers();
-
- void Profile(llvm::FoldingSetNodeID &id) const {
- id.AddInteger(Alignment.getQuantity());
- profileImpl(id);
- }
- virtual void profileImpl(llvm::FoldingSetNodeID &id) const = 0;
-
- virtual bool needsCopy() const { return true; }
- virtual void emitCopy(CodeGenFunction &CGF,
- llvm::Value *dest, llvm::Value *src) = 0;
-
- virtual bool needsDispose() const { return true; }
- virtual void emitDispose(CodeGenFunction &CGF, llvm::Value *field) = 0;
- };
-
- llvm::FoldingSet<ByrefHelpers> ByrefHelpersCache;
+ llvm::FoldingSet<BlockByrefHelpers> ByrefHelpersCache;
/// Fetches the global unique block count.
int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; }
@@ -798,23 +763,23 @@ public:
llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
/// Return a pointer to a constant CFString object for the given string.
- llvm::Constant *GetAddrOfConstantCFString(const StringLiteral *Literal);
+ ConstantAddress GetAddrOfConstantCFString(const StringLiteral *Literal);
/// Return a pointer to a constant NSString object for the given string. Or a
/// user defined String object as defined via
/// -fconstant-string-class=class_name option.
- llvm::GlobalVariable *GetAddrOfConstantString(const StringLiteral *Literal);
+ ConstantAddress GetAddrOfConstantString(const StringLiteral *Literal);
/// Return a constant array for the given string.
llvm::Constant *GetConstantArrayFromStringLiteral(const StringLiteral *E);
/// Return a pointer to a constant array for the given string literal.
- llvm::GlobalVariable *
+ ConstantAddress
GetAddrOfConstantStringFromLiteral(const StringLiteral *S,
StringRef Name = ".str");
/// Return a pointer to a constant array for the given ObjCEncodeExpr node.
- llvm::GlobalVariable *
+ ConstantAddress
GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *);
/// Returns a pointer to a character array containing the literal and a
@@ -822,18 +787,17 @@ public:
///
/// \param GlobalName If provided, the name to use for the global (if one is
/// created).
- llvm::GlobalVariable *
+ ConstantAddress
GetAddrOfConstantCString(const std::string &Str,
- const char *GlobalName = nullptr,
- unsigned Alignment = 0);
+ const char *GlobalName = nullptr);
/// Returns a pointer to a constant global variable for the given file-scope
/// compound literal expression.
- llvm::Constant *GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr*E);
+ ConstantAddress GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr*E);
/// \brief Returns a pointer to a global variable representing a temporary
/// with static or thread storage duration.
- llvm::Constant *GetAddrOfGlobalTemporary(const MaterializeTemporaryExpr *E,
+ ConstantAddress GetAddrOfGlobalTemporary(const MaterializeTemporaryExpr *E,
const Expr *Inner);
/// \brief Retrieve the record type that describes the state of an
@@ -847,11 +811,11 @@ public:
StructorType Type);
/// Return the address of the constructor/destructor of the given type.
- llvm::GlobalValue *
+ llvm::Constant *
getAddrOfCXXStructor(const CXXMethodDecl *MD, StructorType Type,
const CGFunctionInfo *FnInfo = nullptr,
llvm::FunctionType *FnType = nullptr,
- bool DontDefer = false);
+ bool DontDefer = false, bool IsForDefinition = false);
/// Given a builtin id for a function like "__builtin_fabsf", return a
/// Function* for "fabsf".
@@ -948,6 +912,11 @@ public:
QualType DestType,
CodeGenFunction *CGF = nullptr);
+ /// \brief Emit type info if type of an expression is a variably modified
+ /// type. Also emit proper debug info for cast types.
+ void EmitExplicitCastExprType(const ExplicitCastExpr *E,
+ CodeGenFunction *CGF = nullptr);
+
/// Return the result of value-initializing the given type, i.e. a null
/// expression of the given type. This is usually, but not always, an LLVM
/// null constant.
@@ -997,17 +966,21 @@ public:
/// Get the LLVM attributes and calling convention to use for a particular
/// function type.
///
+ /// \param Name - The function name.
/// \param Info - The function type information.
- /// \param TargetDecl - The decl these attributes are being constructed
- /// for. If supplied the attributes applied to this decl may contribute to the
- /// function attributes and calling convention.
+ /// \param CalleeInfo - The callee information these attributes are being
+ /// constructed for. If valid, the attributes applied to this decl may
+ /// contribute to the function attributes and calling convention.
/// \param PAL [out] - On return, the attribute list to use.
/// \param CallingConv [out] - On return, the LLVM calling convention to use.
- void ConstructAttributeList(const CGFunctionInfo &Info,
- const Decl *TargetDecl,
- AttributeListType &PAL,
- unsigned &CallingConv,
- bool AttrOnCallSite);
+ void ConstructAttributeList(StringRef Name, const CGFunctionInfo &Info,
+ CGCalleeInfo CalleeInfo, AttributeListType &PAL,
+ unsigned &CallingConv, bool AttrOnCallSite);
+
+ // Fills in the supplied string map with the set of target features for the
+ // passed in function.
+ void getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
+ const FunctionDecl *FD);
StringRef getMangledName(GlobalDecl GD);
StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD);
@@ -1016,9 +989,6 @@ public:
void EmitVTable(CXXRecordDecl *Class);
- /// Emit the RTTI descriptors for the builtin types.
- void EmitFundamentalRTTIDescriptors();
-
/// \brief Appends Opts to the "Linker Options" metadata value.
void AppendLinkerOptions(StringRef Opts);
@@ -1122,6 +1092,8 @@ public:
void addReplacement(StringRef Name, llvm::Constant *C);
+ void addGlobalValReplacement(llvm::GlobalValue *GV, llvm::Constant *C);
+
/// \brief Emit a code for threadprivate directive.
/// \param D Threadprivate declaration.
void EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D);
@@ -1135,10 +1107,21 @@ public:
void EmitVTableBitSetEntries(llvm::GlobalVariable *VTable,
const VTableLayout &VTLayout);
- /// Create a bitset entry for the given vtable.
- llvm::MDTuple *CreateVTableBitSetEntry(llvm::GlobalVariable *VTable,
- CharUnits Offset,
- const CXXRecordDecl *RD);
+ /// Generate a cross-DSO type identifier for type.
+ llvm::ConstantInt *CreateCfiIdForTypeMetadata(llvm::Metadata *MD);
+
+ /// Create a metadata identifier for the given type. This may either be an
+ /// MDString (for external identifiers) or a distinct unnamed MDNode (for
+ /// internal identifiers).
+ llvm::Metadata *CreateMetadataIdentifierForType(QualType T);
+
+ /// Create a bitset entry for the given function and add it to BitsetsMD.
+ void CreateFunctionBitSetEntry(const FunctionDecl *FD, llvm::Function *F);
+
+ /// Create a bitset entry for the given vtable and add it to BitsetsMD.
+ void CreateVTableBitSetEntry(llvm::NamedMDNode *BitsetsMD,
+ llvm::GlobalVariable *VTable, CharUnits Offset,
+ const CXXRecordDecl *RD);
/// \breif Get the declaration of std::terminate for the platform.
llvm::Constant *getTerminateFn();
@@ -1148,7 +1131,8 @@ private:
GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D,
bool ForVTable, bool DontDefer = false,
bool IsThunk = false,
- llvm::AttributeSet ExtraAttrs = llvm::AttributeSet());
+ llvm::AttributeSet ExtraAttrs = llvm::AttributeSet(),
+ bool IsForDefinition = false);
llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName,
llvm::PointerType *PTy,
@@ -1194,7 +1178,7 @@ private:
// FIXME: Hardcoding priority here is gross.
void AddGlobalCtor(llvm::Function *Ctor, int Priority = 65535,
- llvm::Constant *AssociatedData = 0);
+ llvm::Constant *AssociatedData = nullptr);
void AddGlobalDtor(llvm::Function *Dtor, int Priority = 65535);
/// Generates a global array of functions and priorities using the given list
@@ -1202,15 +1186,15 @@ private:
/// as a LLVM constructor or destructor array.
void EmitCtorList(const CtorList &Fns, const char *GlobalName);
- /// Emit the RTTI descriptors for the given type.
- void EmitFundamentalRTTIDescriptor(QualType Type);
-
/// Emit any needed decls for which code generation was deferred.
void EmitDeferred();
/// Call replaceAllUsesWith on all pairs in Replacements.
void applyReplacements();
+ /// Call replaceAllUsesWith on all pairs in GlobalValReplacements.
+ void applyGlobalValReplacements();
+
void checkAliases();
/// Emit any vtables which we deferred and still have a use for.
@@ -1258,4 +1242,4 @@ private:
} // end namespace CodeGen
} // end namespace clang
-#endif
+#endif // LLVM_CLANG_LIB_CODEGEN_CODEGENMODULE_H
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
index 8dffefc..2c0d93b 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -28,58 +28,20 @@ using namespace CodeGen;
void CodeGenPGO::setFuncName(StringRef Name,
llvm::GlobalValue::LinkageTypes Linkage) {
- StringRef RawFuncName = Name;
-
- // Function names may be prefixed with a binary '1' to indicate
- // that the backend should not modify the symbols due to any platform
- // naming convention. Do not include that '1' in the PGO profile name.
- if (RawFuncName[0] == '\1')
- RawFuncName = RawFuncName.substr(1);
-
- FuncName = RawFuncName;
- if (llvm::GlobalValue::isLocalLinkage(Linkage)) {
- // For local symbols, prepend the main file name to distinguish them.
- // Do not include the full path in the file name since there's no guarantee
- // that it will stay the same, e.g., if the files are checked out from
- // version control in different locations.
- if (CGM.getCodeGenOpts().MainFileName.empty())
- FuncName = FuncName.insert(0, "<unknown>:");
- else
- FuncName = FuncName.insert(0, CGM.getCodeGenOpts().MainFileName + ":");
- }
+ llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
+ FuncName = llvm::getPGOFuncName(
+ Name, Linkage, CGM.getCodeGenOpts().MainFileName,
+ PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
// If we're generating a profile, create a variable for the name.
if (CGM.getCodeGenOpts().ProfileInstrGenerate)
- createFuncNameVar(Linkage);
+ FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName);
}
void CodeGenPGO::setFuncName(llvm::Function *Fn) {
setFuncName(Fn->getName(), Fn->getLinkage());
}
-void CodeGenPGO::createFuncNameVar(llvm::GlobalValue::LinkageTypes Linkage) {
- // We generally want to match the function's linkage, but available_externally
- // and extern_weak both have the wrong semantics, and anything that doesn't
- // need to link across compilation units doesn't need to be visible at all.
- if (Linkage == llvm::GlobalValue::ExternalWeakLinkage)
- Linkage = llvm::GlobalValue::LinkOnceAnyLinkage;
- else if (Linkage == llvm::GlobalValue::AvailableExternallyLinkage)
- Linkage = llvm::GlobalValue::LinkOnceODRLinkage;
- else if (Linkage == llvm::GlobalValue::InternalLinkage ||
- Linkage == llvm::GlobalValue::ExternalLinkage)
- Linkage = llvm::GlobalValue::PrivateLinkage;
-
- auto *Value =
- llvm::ConstantDataArray::getString(CGM.getLLVMContext(), FuncName, false);
- FuncNameVar =
- new llvm::GlobalVariable(CGM.getModule(), Value->getType(), true, Linkage,
- Value, "__llvm_profile_name_" + FuncName);
-
- // Hide the symbol so that we correctly get a copy for each executable.
- if (!llvm::GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
- FuncNameVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
-}
-
namespace {
/// \brief Stable hasher for PGO region counters.
///
@@ -604,7 +566,7 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
RecordNextStmtCount = true;
}
};
-}
+} // end anonymous namespace
void PGOHash::combine(HashType Type) {
// Check that we never combine 0 and only have six bits.
@@ -643,27 +605,24 @@ uint64_t PGOHash::finalize() {
return endian::read<uint64_t, little, unaligned>(Result);
}
-void CodeGenPGO::checkGlobalDecl(GlobalDecl GD) {
- // Make sure we only emit coverage mapping for one constructor/destructor.
- // Clang emits several functions for the constructor and the destructor of
- // a class. Every function is instrumented, but we only want to provide
- // coverage for one of them. Because of that we only emit the coverage mapping
- // for the base constructor/destructor.
- if ((isa<CXXConstructorDecl>(GD.getDecl()) &&
- GD.getCtorType() != Ctor_Base) ||
- (isa<CXXDestructorDecl>(GD.getDecl()) &&
- GD.getDtorType() != Dtor_Base)) {
- SkipCoverageMapping = true;
- }
-}
-
-void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
+void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
+ const Decl *D = GD.getDecl();
bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
if (!InstrumentRegions && !PGOReader)
return;
if (D->isImplicit())
return;
+ // Constructors and destructors may be represented by several functions in IR.
+ // If so, instrument only base variant, others are implemented by delegation
+ // to the base one, it would be counted twice otherwise.
+ if (CGM.getTarget().getCXXABI().hasConstructorVariants() &&
+ ((isa<CXXConstructorDecl>(GD.getDecl()) &&
+ GD.getCtorType() != Ctor_Base) ||
+ (isa<CXXDestructorDecl>(GD.getDecl()) &&
+ GD.getDtorType() != Dtor_Base))) {
+ return;
+ }
CGM.ClearUnusedCoverageMapping(D);
setFuncName(Fn);
@@ -740,7 +699,7 @@ CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name,
setFuncName(Name, Linkage);
CGM.getCoverageMapping()->addFunctionMappingRecord(
- FuncNameVar, FuncName, FunctionHash, CoverageMapping);
+ FuncNameVar, FuncName, FunctionHash, CoverageMapping, false);
}
void CodeGenPGO::computeRegionCounts(const Decl *D) {
@@ -762,24 +721,14 @@ CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
if (!haveRegionCounts())
return;
- uint64_t MaxFunctionCount = PGOReader->getMaximumFunctionCount();
- uint64_t FunctionCount = getRegionCount(0);
- if (FunctionCount >= (uint64_t)(0.3 * (double)MaxFunctionCount))
- // Turn on InlineHint attribute for hot functions.
- // FIXME: 30% is from preliminary tuning on SPEC, it may not be optimal.
- Fn->addFnAttr(llvm::Attribute::InlineHint);
- else if (FunctionCount <= (uint64_t)(0.01 * (double)MaxFunctionCount))
- // Turn on Cold attribute for cold functions.
- // FIXME: 1% is from preliminary tuning on SPEC, it may not be optimal.
- Fn->addFnAttr(llvm::Attribute::Cold);
-
+ uint64_t FunctionCount = getRegionCount(nullptr);
Fn->setEntryCount(FunctionCount);
}
void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S) {
if (!CGM.getCodeGenOpts().ProfileInstrGenerate || !RegionCounterMap)
return;
- if (!Builder.GetInsertPoint())
+ if (!Builder.GetInsertBlock())
return;
unsigned Counter = (*RegionCounterMap)[S];
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h
index de6f369..6bf29ec 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h
@@ -78,13 +78,11 @@ public:
setCurrentRegionCount(*Count);
}
- /// Check if we need to emit coverage mapping for a given declaration
- void checkGlobalDecl(GlobalDecl GD);
/// Assign counters to regions and configure them for PGO of a given
/// function. Does nothing if instrumentation is not enabled and either
/// generates global variables or associates PGO data with each of the
/// counters depending on whether we are generating or using instrumentation.
- void assignRegionCounters(const Decl *D, llvm::Function *Fn);
+ void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn);
/// Emit a coverage mapping range with a counter zero
/// for an unused declaration.
void emitEmptyCounterMapping(const Decl *D, StringRef FuncName,
@@ -92,14 +90,12 @@ public:
private:
void setFuncName(llvm::Function *Fn);
void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage);
- void createFuncNameVar(llvm::GlobalValue::LinkageTypes Linkage);
void mapRegionCounters(const Decl *D);
void computeRegionCounts(const Decl *D);
void applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
llvm::Function *Fn);
void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
bool IsInMainFile);
- void emitCounterVariables();
void emitCounterRegionMapping(const Decl *D);
public:
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp
index 53ba02a..c3c925c 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -155,7 +155,6 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
MContext.mangleTypeName(QualType(ETy, 0), Out);
- Out.flush();
return MetadataCache[Ty] = createTBAAScalarType(OutName, getChar());
}
@@ -271,7 +270,6 @@ CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {
// Don't use the mangler for C code.
llvm::raw_svector_ostream Out(OutName);
MContext.mangleTypeName(QualType(Ty, 0), Out);
- Out.flush();
} else {
OutName = RD->getName();
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h
new file mode 100644
index 0000000..c32b66d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypeCache.h
@@ -0,0 +1,108 @@
+//===--- CodeGenTypeCache.h - Commonly used LLVM types and info -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This structure provides a set of common types useful during IR emission.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENTYPECACHE_H
+#define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPECACHE_H
+
+#include "clang/AST/CharUnits.h"
+#include "llvm/IR/CallingConv.h"
+
+namespace llvm {
+ class Type;
+ class IntegerType;
+ class PointerType;
+}
+
+namespace clang {
+namespace CodeGen {
+
+/// This structure provides a set of types that are commonly used
+/// during IR emission. It's initialized once in CodeGenModule's
+/// constructor and then copied around into new CodeGenFunctions.
+struct CodeGenTypeCache {
+ /// void
+ llvm::Type *VoidTy;
+
+ /// i8, i16, i32, and i64
+ llvm::IntegerType *Int8Ty, *Int16Ty, *Int32Ty, *Int64Ty;
+ /// float, double
+ llvm::Type *FloatTy, *DoubleTy;
+
+ /// int
+ llvm::IntegerType *IntTy;
+
+ /// intptr_t, size_t, and ptrdiff_t, which we assume are the same size.
+ union {
+ llvm::IntegerType *IntPtrTy;
+ llvm::IntegerType *SizeTy;
+ llvm::IntegerType *PtrDiffTy;
+ };
+
+ /// void* in address space 0
+ union {
+ llvm::PointerType *VoidPtrTy;
+ llvm::PointerType *Int8PtrTy;
+ };
+
+ /// void** in address space 0
+ union {
+ llvm::PointerType *VoidPtrPtrTy;
+ llvm::PointerType *Int8PtrPtrTy;
+ };
+
+ /// The size and alignment of the builtin C type 'int'. This comes
+ /// up enough in various ABI lowering tasks to be worth pre-computing.
+ union {
+ unsigned char IntSizeInBytes;
+ unsigned char IntAlignInBytes;
+ };
+ CharUnits getIntSize() const {
+ return CharUnits::fromQuantity(IntSizeInBytes);
+ }
+ CharUnits getIntAlign() const {
+ return CharUnits::fromQuantity(IntAlignInBytes);
+ }
+
+ /// The width of a pointer into the generic address space.
+ unsigned char PointerWidthInBits;
+
+ /// The size and alignment of a pointer into the generic address space.
+ union {
+ unsigned char PointerAlignInBytes;
+ unsigned char PointerSizeInBytes;
+ unsigned char SizeSizeInBytes; // sizeof(size_t)
+ unsigned char SizeAlignInBytes;
+ };
+ CharUnits getSizeSize() const {
+ return CharUnits::fromQuantity(SizeSizeInBytes);
+ }
+ CharUnits getSizeAlign() const {
+ return CharUnits::fromQuantity(SizeAlignInBytes);
+ }
+ CharUnits getPointerSize() const {
+ return CharUnits::fromQuantity(PointerSizeInBytes);
+ }
+ CharUnits getPointerAlign() const {
+ return CharUnits::fromQuantity(PointerAlignInBytes);
+ }
+
+ llvm::CallingConv::ID RuntimeCC;
+ llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
+ llvm::CallingConv::ID BuiltinCC;
+ llvm::CallingConv::ID getBuiltinCC() const { return BuiltinCC; }
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
index a4a8654..09d9bf1 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -31,7 +31,6 @@ using namespace CodeGen;
CodeGenTypes::CodeGenTypes(CodeGenModule &cgm)
: CGM(cgm), Context(cgm.getContext()), TheModule(cgm.getModule()),
- TheDataLayout(cgm.getDataLayout()),
Target(cgm.getTarget()), TheCXXABI(cgm.getCXXABI()),
TheABIInfo(cgm.getTargetCodeGenInfo().getABIInfo()) {
SkippedLayout = false;
@@ -295,6 +294,76 @@ static llvm::Type *getTypeForFormat(llvm::LLVMContext &VMContext,
llvm_unreachable("Unknown float format!");
}
+llvm::Type *CodeGenTypes::ConvertFunctionType(QualType QFT,
+ const FunctionDecl *FD) {
+ assert(QFT.isCanonical());
+ const Type *Ty = QFT.getTypePtr();
+ const FunctionType *FT = cast<FunctionType>(QFT.getTypePtr());
+ // First, check whether we can build the full function type. If the
+ // function type depends on an incomplete type (e.g. a struct or enum), we
+ // cannot lower the function type.
+ if (!isFuncTypeConvertible(FT)) {
+ // This function's type depends on an incomplete tag type.
+
+ // Force conversion of all the relevant record types, to make sure
+ // we re-convert the FunctionType when appropriate.
+ if (const RecordType *RT = FT->getReturnType()->getAs<RecordType>())
+ ConvertRecordDeclType(RT->getDecl());
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT))
+ for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++)
+ if (const RecordType *RT = FPT->getParamType(i)->getAs<RecordType>())
+ ConvertRecordDeclType(RT->getDecl());
+
+ SkippedLayout = true;
+
+ // Return a placeholder type.
+ return llvm::StructType::get(getLLVMContext());
+ }
+
+ // While we're converting the parameter types for a function, we don't want
+ // to recursively convert any pointed-to structs. Converting directly-used
+ // structs is ok though.
+ if (!RecordsBeingLaidOut.insert(Ty).second) {
+ SkippedLayout = true;
+ return llvm::StructType::get(getLLVMContext());
+ }
+
+ // The function type can be built; call the appropriate routines to
+ // build it.
+ const CGFunctionInfo *FI;
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) {
+ FI = &arrangeFreeFunctionType(
+ CanQual<FunctionProtoType>::CreateUnsafe(QualType(FPT, 0)), FD);
+ } else {
+ const FunctionNoProtoType *FNPT = cast<FunctionNoProtoType>(FT);
+ FI = &arrangeFreeFunctionType(
+ CanQual<FunctionNoProtoType>::CreateUnsafe(QualType(FNPT, 0)));
+ }
+
+ llvm::Type *ResultType = nullptr;
+ // If there is something higher level prodding our CGFunctionInfo, then
+ // don't recurse into it again.
+ if (FunctionsBeingProcessed.count(FI)) {
+
+ ResultType = llvm::StructType::get(getLLVMContext());
+ SkippedLayout = true;
+ } else {
+
+ // Otherwise, we're good to go, go ahead and convert it.
+ ResultType = GetFunctionType(*FI);
+ }
+
+ RecordsBeingLaidOut.erase(Ty);
+
+ if (SkippedLayout)
+ TypeCache.clear();
+
+ if (RecordsBeingLaidOut.empty())
+ while (!DeferredRecords.empty())
+ ConvertRecordDeclType(DeferredRecords.pop_back_val());
+ return ResultType;
+}
+
/// ConvertType - Convert the specified type to its LLVM form.
llvm::Type *CodeGenTypes::ConvertType(QualType T) {
T = Context.getCanonicalType(T);
@@ -389,9 +458,19 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case BuiltinType::OCLImage1dBuffer:
case BuiltinType::OCLImage2d:
case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage2dDepth:
+ case BuiltinType::OCLImage2dArrayDepth:
+ case BuiltinType::OCLImage2dMSAA:
+ case BuiltinType::OCLImage2dArrayMSAA:
+ case BuiltinType::OCLImage2dMSAADepth:
+ case BuiltinType::OCLImage2dArrayMSAADepth:
case BuiltinType::OCLImage3d:
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLNDRange:
+ case BuiltinType::OCLReserveID:
ResultType = CGM.getOpenCLRuntime().convertOpenCLSpecificType(Ty);
break;
@@ -476,75 +555,9 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
break;
}
case Type::FunctionNoProto:
- case Type::FunctionProto: {
- const FunctionType *FT = cast<FunctionType>(Ty);
- // First, check whether we can build the full function type. If the
- // function type depends on an incomplete type (e.g. a struct or enum), we
- // cannot lower the function type.
- if (!isFuncTypeConvertible(FT)) {
- // This function's type depends on an incomplete tag type.
-
- // Force conversion of all the relevant record types, to make sure
- // we re-convert the FunctionType when appropriate.
- if (const RecordType *RT = FT->getReturnType()->getAs<RecordType>())
- ConvertRecordDeclType(RT->getDecl());
- if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT))
- for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++)
- if (const RecordType *RT = FPT->getParamType(i)->getAs<RecordType>())
- ConvertRecordDeclType(RT->getDecl());
-
- // Return a placeholder type.
- ResultType = llvm::StructType::get(getLLVMContext());
-
- SkippedLayout = true;
- break;
- }
-
- // While we're converting the parameter types for a function, we don't want
- // to recursively convert any pointed-to structs. Converting directly-used
- // structs is ok though.
- if (!RecordsBeingLaidOut.insert(Ty).second) {
- ResultType = llvm::StructType::get(getLLVMContext());
-
- SkippedLayout = true;
- break;
- }
-
- // The function type can be built; call the appropriate routines to
- // build it.
- const CGFunctionInfo *FI;
- if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) {
- FI = &arrangeFreeFunctionType(
- CanQual<FunctionProtoType>::CreateUnsafe(QualType(FPT, 0)));
- } else {
- const FunctionNoProtoType *FNPT = cast<FunctionNoProtoType>(FT);
- FI = &arrangeFreeFunctionType(
- CanQual<FunctionNoProtoType>::CreateUnsafe(QualType(FNPT, 0)));
- }
-
- // If there is something higher level prodding our CGFunctionInfo, then
- // don't recurse into it again.
- if (FunctionsBeingProcessed.count(FI)) {
-
- ResultType = llvm::StructType::get(getLLVMContext());
- SkippedLayout = true;
- } else {
-
- // Otherwise, we're good to go, go ahead and convert it.
- ResultType = GetFunctionType(*FI);
- }
-
- RecordsBeingLaidOut.erase(Ty);
-
- if (SkippedLayout)
- TypeCache.clear();
-
- if (RecordsBeingLaidOut.empty())
- while (!DeferredRecords.empty())
- ConvertRecordDeclType(DeferredRecords.pop_back_val());
+ case Type::FunctionProto:
+ ResultType = ConvertFunctionType(T);
break;
- }
-
case Type::ObjCObject:
ResultType = ConvertType(cast<ObjCObjectType>(Ty)->getBaseType());
break;
@@ -615,6 +628,10 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
}
break;
}
+ case Type::Pipe: {
+ ResultType = CGM.getOpenCLRuntime().getPipeType();
+ break;
+ }
}
assert(ResultType && "Didn't convert a type?");
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
index 1580e21..a96f23c4 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenTypes.h
@@ -122,7 +122,6 @@ class CodeGenTypes {
// Some of this stuff should probably be left on the CGM.
ASTContext &Context;
llvm::Module &TheModule;
- const llvm::DataLayout &TheDataLayout;
const TargetInfo &Target;
CGCXXABI &TheCXXABI;
@@ -159,7 +158,6 @@ class CodeGenTypes {
SmallVector<const RecordDecl *, 8> DeferredRecords;
-private:
/// This map keeps cache of llvm::Types and maps clang::Type to
/// corresponding llvm::Type.
llvm::DenseMap<const Type *, llvm::Type *> TypeCache;
@@ -168,7 +166,9 @@ public:
CodeGenTypes(CodeGenModule &cgm);
~CodeGenTypes();
- const llvm::DataLayout &getDataLayout() const { return TheDataLayout; }
+ const llvm::DataLayout &getDataLayout() const {
+ return TheModule.getDataLayout();
+ }
ASTContext &getContext() const { return Context; }
const ABIInfo &getABIInfo() const { return TheABIInfo; }
const TargetInfo &getTarget() const { return Target; }
@@ -178,6 +178,14 @@ public:
/// ConvertType - Convert type T into a llvm::Type.
llvm::Type *ConvertType(QualType T);
+ /// \brief Converts the GlobalDecl into an llvm::Type. This should be used
+ /// when we know the target of the function we want to convert. This is
+ /// because some functions (explicitly, those with pass_object_size
+ /// parameters) may not have the same signature as their type portrays, and
+ /// can only be called directly.
+ llvm::Type *ConvertFunctionType(QualType FT,
+ const FunctionDecl *FD = nullptr);
+
/// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from
/// ConvertType in that it is used to convert to the memory representation for
/// a type. For example, the scalar representation for _Bool is i1, but the
@@ -264,11 +272,12 @@ public:
const CGFunctionInfo &arrangeMSMemberPointerThunk(const CXXMethodDecl *MD);
const CGFunctionInfo &arrangeMSCtorClosure(const CXXConstructorDecl *CD,
CXXCtorType CT);
-
- const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty);
+ const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty,
+ const FunctionDecl *FD);
const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty);
const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD,
- const FunctionProtoType *FTP);
+ const FunctionProtoType *FTP,
+ const CXXMethodDecl *MD);
/// "Arrange" the LLVM information for a call or type with the given
/// signature. This is largely an internal method; other clients
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
index eca9159..03e22cd 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -47,17 +47,6 @@ public:
Optional<SourceLocation> LocEnd)
: Count(Count), LocStart(LocStart), LocEnd(LocEnd) {}
- SourceMappingRegion(SourceMappingRegion &&Region)
- : Count(std::move(Region.Count)), LocStart(std::move(Region.LocStart)),
- LocEnd(std::move(Region.LocEnd)) {}
-
- SourceMappingRegion &operator=(SourceMappingRegion &&RHS) {
- Count = std::move(RHS.Count);
- LocStart = std::move(RHS.LocStart);
- LocEnd = std::move(RHS.LocEnd);
- return *this;
- }
-
const Counter &getCounter() const { return Count; }
void setCounter(Counter C) { Count = C; }
@@ -66,7 +55,7 @@ public:
void setStartLoc(SourceLocation Loc) { LocStart = Loc; }
- const SourceLocation &getStartLoc() const {
+ SourceLocation getStartLoc() const {
assert(LocStart && "Region has no start location");
return *LocStart;
}
@@ -75,7 +64,7 @@ public:
void setEndLoc(SourceLocation Loc) { LocEnd = Loc; }
- const SourceLocation &getEndLoc() const {
+ SourceLocation getEndLoc() const {
assert(LocEnd && "Region has no end location");
return *LocEnd;
}
@@ -174,7 +163,7 @@ public:
unsigned Depth = 0;
for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc);
- !Parent.isInvalid(); Parent = getIncludeOrExpansionLoc(Parent))
+ Parent.isValid(); Parent = getIncludeOrExpansionLoc(Parent))
++Depth;
FileLocs.push_back(std::make_pair(Loc, Depth));
}
@@ -255,7 +244,7 @@ public:
assert(Region.hasEndLoc() && "incomplete region");
SourceLocation LocStart = Region.getStartLoc();
- assert(!SM.getFileID(LocStart).isInvalid() && "region in invalid file");
+ assert(SM.getFileID(LocStart).isValid() && "region in invalid file");
auto CovFileID = getCoverageFileID(LocStart);
// Ignore regions that don't have a file, such as builtin macros.
@@ -413,8 +402,8 @@ struct CounterCoverageMappingBuilder
SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
- assert(!EndLoc.isInvalid() &&
- "File exit was not handled before popRegions");
+ if (EndLoc.isInvalid())
+ llvm::report_fatal_error("File exit not handled before popRegions");
}
Region.setEndLoc(EndLoc);
@@ -426,7 +415,7 @@ struct CounterCoverageMappingBuilder
MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
assert(SM.isWrittenInSameFile(Region.getStartLoc(), EndLoc));
- SourceRegions.push_back(std::move(Region));
+ SourceRegions.push_back(Region);
}
RegionStack.pop_back();
}
@@ -496,12 +485,12 @@ struct CounterCoverageMappingBuilder
llvm::SmallSet<SourceLocation, 8> StartLocs;
Optional<Counter> ParentCounter;
- for (auto I = RegionStack.rbegin(), E = RegionStack.rend(); I != E; ++I) {
- if (!I->hasStartLoc())
+ for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
+ if (!I.hasStartLoc())
continue;
- SourceLocation Loc = I->getStartLoc();
+ SourceLocation Loc = I.getStartLoc();
if (!isNestedIn(Loc, ParentFile)) {
- ParentCounter = I->getCounter();
+ ParentCounter = I.getCounter();
break;
}
@@ -510,11 +499,11 @@ struct CounterCoverageMappingBuilder
// correct count. We avoid creating redundant regions by stopping once
// we've seen this region.
if (StartLocs.insert(Loc).second)
- SourceRegions.emplace_back(I->getCounter(), Loc,
+ SourceRegions.emplace_back(I.getCounter(), Loc,
getEndOfFileOrMacro(Loc));
Loc = getIncludeOrExpansionLoc(Loc);
}
- I->setStartLoc(getPreciseTokenLocEnd(Loc));
+ I.setStartLoc(getPreciseTokenLocEnd(Loc));
}
if (ParentCounter) {
@@ -580,7 +569,7 @@ struct CounterCoverageMappingBuilder
}
void VisitStmt(const Stmt *S) {
- if (!S->getLocStart().isInvalid())
+ if (S->getLocStart().isValid())
extendRegion(S);
for (const Stmt *Child : S->children())
if (Child)
@@ -796,7 +785,7 @@ struct CounterCoverageMappingBuilder
else
pushRegion(Count, getStart(S));
- if (const CaseStmt *CS = dyn_cast<CaseStmt>(S)) {
+ if (const auto *CS = dyn_cast<CaseStmt>(S)) {
Visit(CS->getLHS());
if (const Expr *RHS = CS->getRHS())
Visit(RHS);
@@ -842,7 +831,6 @@ struct CounterCoverageMappingBuilder
}
void VisitCXXCatchStmt(const CXXCatchStmt *S) {
- extendRegion(S);
propagateCounts(getRegionCounter(S), S->getHandlerBlock());
}
@@ -891,7 +879,7 @@ static bool isMachO(const CodeGenModule &CGM) {
}
static StringRef getCoverageSection(const CodeGenModule &CGM) {
- return isMachO(CGM) ? "__DATA,__llvm_covmap" : "__llvm_covmap";
+ return llvm::getInstrProfCoverageSectionName(isMachO(CGM));
}
static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
@@ -922,26 +910,28 @@ static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
}
void CoverageMappingModuleGen::addFunctionMappingRecord(
- llvm::GlobalVariable *FunctionName, StringRef FunctionNameValue,
- uint64_t FunctionHash, const std::string &CoverageMapping) {
+ llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
+ const std::string &CoverageMapping, bool isUsed) {
llvm::LLVMContext &Ctx = CGM.getLLVMContext();
- auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
- auto *Int64Ty = llvm::Type::getInt64Ty(Ctx);
- auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
if (!FunctionRecordTy) {
- llvm::Type *FunctionRecordTypes[] = {Int8PtrTy, Int32Ty, Int32Ty, Int64Ty};
+#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
+ llvm::Type *FunctionRecordTypes[] = {
+ #include "llvm/ProfileData/InstrProfData.inc"
+ };
FunctionRecordTy =
llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes),
/*isPacked=*/true);
}
+ #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init,
llvm::Constant *FunctionRecordVals[] = {
- llvm::ConstantExpr::getBitCast(FunctionName, Int8PtrTy),
- llvm::ConstantInt::get(Int32Ty, FunctionNameValue.size()),
- llvm::ConstantInt::get(Int32Ty, CoverageMapping.size()),
- llvm::ConstantInt::get(Int64Ty, FunctionHash)};
+ #include "llvm/ProfileData/InstrProfData.inc"
+ };
FunctionRecords.push_back(llvm::ConstantStruct::get(
FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
+ if (!isUsed)
+ FunctionNames.push_back(
+ llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)));
CoverageMappings += CoverageMapping;
if (CGM.getCodeGenOpts().DumpCoverageMapping) {
@@ -961,7 +951,7 @@ void CoverageMappingModuleGen::addFunctionMappingRecord(
Expressions, Regions);
if (Reader.read())
return;
- dump(llvm::outs(), FunctionNameValue, Expressions, Regions);
+ dump(llvm::outs(), NameValue, Expressions, Regions);
}
}
@@ -1006,30 +996,47 @@ void CoverageMappingModuleGen::emit() {
llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
auto RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);
+ llvm::Type *CovDataHeaderTypes[] = {
+#define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType,
+#include "llvm/ProfileData/InstrProfData.inc"
+ };
+ auto CovDataHeaderTy =
+ llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes));
+ llvm::Constant *CovDataHeaderVals[] = {
+#define COVMAP_HEADER(Type, LLVMType, Name, Init) Init,
+#include "llvm/ProfileData/InstrProfData.inc"
+ };
+ auto CovDataHeaderVal = llvm::ConstantStruct::get(
+ CovDataHeaderTy, makeArrayRef(CovDataHeaderVals));
+
// Create the coverage data record
- llvm::Type *CovDataTypes[] = {Int32Ty, Int32Ty,
- Int32Ty, Int32Ty,
- RecordsTy, FilenamesAndMappingsVal->getType()};
+ llvm::Type *CovDataTypes[] = {CovDataHeaderTy, RecordsTy,
+ FilenamesAndMappingsVal->getType()};
auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
- llvm::Constant *TUDataVals[] = {
- llvm::ConstantInt::get(Int32Ty, FunctionRecords.size()),
- llvm::ConstantInt::get(Int32Ty, FilenamesSize),
- llvm::ConstantInt::get(Int32Ty, CoverageMappingSize),
- llvm::ConstantInt::get(Int32Ty,
- /*Version=*/CoverageMappingVersion1),
- RecordsVal, FilenamesAndMappingsVal};
+ llvm::Constant *TUDataVals[] = {CovDataHeaderVal, RecordsVal,
+ FilenamesAndMappingsVal};
auto CovDataVal =
llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
- auto CovData = new llvm::GlobalVariable(CGM.getModule(), CovDataTy, true,
- llvm::GlobalValue::InternalLinkage,
- CovDataVal,
- "__llvm_coverage_mapping");
+ auto CovData = new llvm::GlobalVariable(
+ CGM.getModule(), CovDataTy, true, llvm::GlobalValue::InternalLinkage,
+ CovDataVal, llvm::getCoverageMappingVarName());
CovData->setSection(getCoverageSection(CGM));
CovData->setAlignment(8);
// Make sure the data doesn't get deleted.
CGM.addUsedGlobal(CovData);
+ // Create the deferred function records array
+ if (!FunctionNames.empty()) {
+ auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx),
+ FunctionNames.size());
+ auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames);
+ // This variable will *NOT* be emitted to the object file. It is used
+ // to pass the list of names referenced to codegen.
+ new llvm::GlobalVariable(CGM.getModule(), NamesArrTy, true,
+ llvm::GlobalValue::InternalLinkage, NamesArrVal,
+ llvm::getCoverageNamesVarName());
+ }
}
unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h
index 0d1bf6d..9ae2bcf 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CoverageMappingGen.h
@@ -54,6 +54,7 @@ class CoverageMappingModuleGen {
CoverageSourceInfo &SourceInfo;
llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries;
std::vector<llvm::Constant *> FunctionRecords;
+ std::vector<llvm::Constant *> FunctionNames;
llvm::StructType *FunctionRecordTy;
std::string CoverageMappings;
@@ -70,7 +71,8 @@ public:
void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName,
StringRef FunctionNameValue,
uint64_t FunctionHash,
- const std::string &CoverageMapping);
+ const std::string &CoverageMapping,
+ bool isUsed = true);
/// \brief Emit the coverage mapping data for a translation unit.
void emit();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/EHScopeStack.h b/contrib/llvm/tools/clang/lib/CodeGen/EHScopeStack.h
index a795188..85cd154 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/EHScopeStack.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/EHScopeStack.h
@@ -96,6 +96,9 @@ enum CleanupKind : unsigned {
/// and catch blocks.
class EHScopeStack {
public:
+ /* Should switch to alignof(uint64_t) instead of 8, when EHCleanupScope can */
+ enum { ScopeStackAlignment = 8 };
+
/// A saved depth on the scope stack. This is necessary because
/// pushing scopes onto the stack invalidates iterators.
class stable_iterator {
@@ -141,7 +144,15 @@ public:
class Cleanup {
// Anchor the construction vtable.
virtual void anchor();
+
+ protected:
+ ~Cleanup() = default;
+
public:
+ Cleanup(const Cleanup &) = default;
+ Cleanup(Cleanup &&) {}
+ Cleanup() = default;
+
/// Generation flags.
class Flags {
enum {
@@ -168,10 +179,6 @@ public:
void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; }
};
- // Provide a virtual destructor to suppress a very common warning
- // that unfortunately cannot be suppressed without this. Cleanups
- // should not rely on this destructor ever being called.
- virtual ~Cleanup() {}
/// Emit the cleanup. For normal cleanups, this is run in the
/// same EH context as when the cleanup was pushed, i.e. the
@@ -184,7 +191,8 @@ public:
/// ConditionalCleanup stores the saved form of its parameters,
/// then restores them and performs the cleanup.
- template <class T, class... As> class ConditionalCleanup : public Cleanup {
+ template <class T, class... As>
+ class ConditionalCleanup final : public Cleanup {
typedef std::tuple<typename DominatingValue<As>::saved_type...> SavedTuple;
SavedTuple Saved;
@@ -248,6 +256,7 @@ private:
SmallVector<BranchFixup, 8> BranchFixups;
char *allocate(size_t Size);
+ void deallocate(size_t Size);
void *pushCleanup(CleanupKind K, size_t DataSize);
@@ -259,6 +268,8 @@ public:
/// Push a lazily-created cleanup on the stack.
template <class T, class... As> void pushCleanup(CleanupKind Kind, As... A) {
+ static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ "Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new (Buffer) T(A...);
(void) Obj;
@@ -267,6 +278,8 @@ public:
/// Push a lazily-created cleanup on the stack. Tuple version.
template <class T, class... As>
void pushCleanupTuple(CleanupKind Kind, std::tuple<As...> A) {
+ static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ "Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new (Buffer) T(std::move(A));
(void) Obj;
@@ -287,6 +300,8 @@ public:
/// stack is modified.
template <class T, class... As>
T *pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A) {
+ static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ "Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
return new (Buffer) T(N, A...);
}
@@ -346,7 +361,6 @@ public:
return InnermostEHScope;
}
- stable_iterator getInnermostActiveEHScope() const;
/// An unstable reference to a scope-stack depth. Invalidated by
/// pushes but not pops.
@@ -377,9 +391,6 @@ public:
/// to the EH stack.
iterator find(stable_iterator save) const;
- /// Removes the cleanup pointed to by the given stable_iterator.
- void removeCleanup(stable_iterator save);
-
/// Add a branch fixup to the current cleanup scope.
BranchFixup &addBranchFixup() {
assert(hasNormalCleanups() && "adding fixup in scope without cleanups");
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 2be9ceb..e02c8dc 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -69,6 +69,45 @@ public:
return RAA_Default;
}
+ bool isThisCompleteObject(GlobalDecl GD) const override {
+ // The Itanium ABI has separate complete-object vs. base-object
+ // variants of both constructors and destructors.
+ if (isa<CXXDestructorDecl>(GD.getDecl())) {
+ switch (GD.getDtorType()) {
+ case Dtor_Complete:
+ case Dtor_Deleting:
+ return true;
+
+ case Dtor_Base:
+ return false;
+
+ case Dtor_Comdat:
+ llvm_unreachable("emitting dtor comdat as function?");
+ }
+ llvm_unreachable("bad dtor kind");
+ }
+ if (isa<CXXConstructorDecl>(GD.getDecl())) {
+ switch (GD.getCtorType()) {
+ case Ctor_Complete:
+ return true;
+
+ case Ctor_Base:
+ return false;
+
+ case Ctor_CopyingClosure:
+ case Ctor_DefaultClosure:
+ llvm_unreachable("closure ctors in Itanium ABI?");
+
+ case Ctor_Comdat:
+ llvm_unreachable("emitting ctor comdat as function?");
+ }
+ llvm_unreachable("bad dtor kind");
+ }
+
+ // No other kinds.
+ return false;
+ }
+
bool isZeroInitializable(const MemberPointerType *MPT) override;
llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;
@@ -76,13 +115,14 @@ public:
llvm::Value *
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
const Expr *E,
- llvm::Value *&This,
+ Address This,
+ llvm::Value *&ThisPtrForCall,
llvm::Value *MemFnPtr,
const MemberPointerType *MPT) override;
llvm::Value *
EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
- llvm::Value *Base,
+ Address Base,
llvm::Value *MemPtr,
const MemberPointerType *MPT) override;
@@ -111,9 +151,22 @@ public:
const MemberPointerType *MPT) override;
void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,
- llvm::Value *Ptr, QualType ElementType,
+ Address Ptr, QualType ElementType,
const CXXDestructorDecl *Dtor) override;
+ /// Itanium says that an _Unwind_Exception has to be "double-word"
+ /// aligned (and thus the end of it is also so-aligned), meaning 16
+ /// bytes. Of course, that was written for the actual Itanium,
+ /// which is a 64-bit platform. Classically, the ABI doesn't really
+ /// specify the alignment on other platforms, but in practice
+ /// libUnwind declares the struct with __attribute__((aligned)), so
+ /// we assume that alignment here. (It's generally 16 bytes, but
+ /// some targets overwrite it.)
+ CharUnits getAlignmentOfExnObject() {
+ auto align = CGM.getContext().getTargetDefaultAlignForAttributeAligned();
+ return CGM.getContext().toCharUnitsFromBits(align);
+ }
+
void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override;
void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override;
@@ -126,34 +179,34 @@ public:
void EmitFundamentalRTTIDescriptor(QualType Type);
void EmitFundamentalRTTIDescriptors();
llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
- llvm::Constant *
+ CatchTypeInfo
getAddrOfCXXCatchHandlerType(QualType Ty,
QualType CatchHandlerType) override {
- return getAddrOfRTTIDescriptor(Ty);
+ return CatchTypeInfo{getAddrOfRTTIDescriptor(Ty), 0};
}
bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override;
void EmitBadTypeidCall(CodeGenFunction &CGF) override;
llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
- llvm::Value *ThisPtr,
+ Address ThisPtr,
llvm::Type *StdTypeInfoPtrTy) override;
bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
QualType SrcRecordTy) override;
- llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
+ llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy, QualType DestTy,
QualType DestRecordTy,
llvm::BasicBlock *CastEnd) override;
- llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value *Value,
+ llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy,
QualType DestTy) override;
bool EmitBadCastCall(CodeGenFunction &CGF) override;
llvm::Value *
- GetVirtualBaseClassOffset(CodeGenFunction &CGF, llvm::Value *This,
+ GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl) override;
@@ -185,15 +238,29 @@ public:
void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
CXXDtorType Type, bool ForVirtualBase,
- bool Delegating, llvm::Value *This) override;
+ bool Delegating, Address This) override;
void emitVTableDefinitions(CodeGenVTables &CGVT,
const CXXRecordDecl *RD) override;
+ bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
+ CodeGenFunction::VPtr Vptr) override;
+
+ bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override {
+ return true;
+ }
+
+ llvm::Constant *
+ getVTableAddressPoint(BaseSubobject Base,
+ const CXXRecordDecl *VTableClass) override;
+
llvm::Value *getVTableAddressPointInStructor(
CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
- BaseSubobject Base, const CXXRecordDecl *NearestVBase,
- bool &NeedsVirtualOffset) override;
+ BaseSubobject Base, const CXXRecordDecl *NearestVBase) override;
+
+ llvm::Value *getVTableAddressPointInStructorWithVTT(
+ CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
+ BaseSubobject Base, const CXXRecordDecl *NearestVBase);
llvm::Constant *
getVTableAddressPointForConstExpr(BaseSubobject Base,
@@ -203,18 +270,19 @@ public:
CharUnits VPtrOffset) override;
llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
- llvm::Value *This,
- llvm::Type *Ty,
+ Address This, llvm::Type *Ty,
SourceLocation Loc) override;
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
CXXDtorType DtorType,
- llvm::Value *This,
+ Address This,
const CXXMemberCallExpr *CE) override;
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
+ bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override;
+
void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD,
bool ReturnAdjustment) override {
// Allow inlining of thunks by emitting them with available_externally
@@ -223,10 +291,10 @@ public:
Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
}
- llvm::Value *performThisAdjustment(CodeGenFunction &CGF, llvm::Value *This,
+ llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
const ThisAdjustment &TA) override;
- llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
+ llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
const ReturnAdjustment &RA) override;
size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
@@ -240,13 +308,13 @@ public:
{ return "__cxa_deleted_virtual"; }
CharUnits getArrayCookieSizeImpl(QualType elementType) override;
- llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
- llvm::Value *NewPtr,
- llvm::Value *NumElements,
- const CXXNewExpr *expr,
- QualType ElementType) override;
+ Address InitializeArrayCookie(CodeGenFunction &CGF,
+ Address NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType) override;
llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
- llvm::Value *allocPtr,
+ Address allocPtr,
CharUnits cookieSize) override;
void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
@@ -259,10 +327,9 @@ public:
llvm::Value *Val);
void EmitThreadLocalInitFuncs(
CodeGenModule &CGM,
- ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>>
- CXXThreadLocals,
+ ArrayRef<const VarDecl *> CXXThreadLocals,
ArrayRef<llvm::Function *> CXXThreadLocalInits,
- ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) override;
+ ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override;
bool usesThreadWrapperFunction() const override { return true; }
LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
@@ -302,6 +369,41 @@ public:
friend class ItaniumRTTIBuilder;
void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
+
+ private:
+ bool hasAnyUsedVirtualInlineFunction(const CXXRecordDecl *RD) const {
+ const auto &VtableLayout =
+ CGM.getItaniumVTableContext().getVTableLayout(RD);
+
+ for (const auto &VtableComponent : VtableLayout.vtable_components()) {
+ if (!VtableComponent.isUsedFunctionPointerKind())
+ continue;
+
+ const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
+ if (Method->getCanonicalDecl()->isInlined())
+ return true;
+ }
+ return false;
+ }
+
+ bool isVTableHidden(const CXXRecordDecl *RD) const {
+ const auto &VtableLayout =
+ CGM.getItaniumVTableContext().getVTableLayout(RD);
+
+ for (const auto &VtableComponent : VtableLayout.vtable_components()) {
+ if (VtableComponent.isRTTIKind()) {
+ const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl();
+ if (RTTIDecl->getVisibility() == Visibility::HiddenVisibility)
+ return true;
+ } else if (VtableComponent.isUsedFunctionPointerKind()) {
+ const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
+ if (Method->getVisibility() == Visibility::HiddenVisibility &&
+ !Method->isDefined())
+ return true;
+ }
+ }
+ return false;
+ }
};
class ARMCXXABI : public ItaniumCXXABI {
@@ -320,12 +422,12 @@ public:
QualType ResTy) override;
CharUnits getArrayCookieSizeImpl(QualType elementType) override;
- llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
- llvm::Value *NewPtr,
- llvm::Value *NumElements,
- const CXXNewExpr *expr,
- QualType ElementType) override;
- llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, llvm::Value *allocPtr,
+ Address InitializeArrayCookie(CodeGenFunction &CGF,
+ Address NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType) override;
+ llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, Address allocPtr,
CharUnits cookieSize) override;
};
@@ -336,6 +438,20 @@ public:
// ARM64 libraries are prepared for non-unique RTTI.
bool shouldRTTIBeUnique() const override { return false; }
};
+
+class WebAssemblyCXXABI final : public ItaniumCXXABI {
+public:
+ explicit WebAssemblyCXXABI(CodeGen::CodeGenModule &CGM)
+ : ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
+ /*UseARMGuardVarABI=*/true) {}
+
+private:
+ bool HasThisReturn(GlobalDecl GD) const override {
+ return isa<CXXConstructorDecl>(GD.getDecl()) ||
+ (isa<CXXDestructorDecl>(GD.getDecl()) &&
+ GD.getDtorType() != Dtor_Deleting);
+ }
+};
}
CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
@@ -344,6 +460,7 @@ CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
// between the ARM and iOS ABIs.
case TargetCXXABI::GenericARM:
case TargetCXXABI::iOS:
+ case TargetCXXABI::WatchOS:
return new ARMCXXABI(CGM);
case TargetCXXABI::iOS64:
@@ -359,6 +476,9 @@ CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
case TargetCXXABI::GenericMIPS:
return new ItaniumCXXABI(CGM, /* UseARMMethodPtrABI = */ true);
+ case TargetCXXABI::WebAssembly:
+ return new WebAssemblyCXXABI(CGM);
+
case TargetCXXABI::GenericItanium:
if (CGM.getContext().getTargetInfo().getTriple().getArch()
== llvm::Triple::le32) {
@@ -404,7 +524,8 @@ ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
/// If the member is non-virtual, memptr.ptr is the address of
/// the function to call.
llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
- CodeGenFunction &CGF, const Expr *E, llvm::Value *&This,
+ CodeGenFunction &CGF, const Expr *E, Address ThisAddr,
+ llvm::Value *&ThisPtrForCall,
llvm::Value *MemFnPtr, const MemberPointerType *MPT) {
CGBuilderTy &Builder = CGF.Builder;
@@ -413,9 +534,8 @@ llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
- llvm::FunctionType *FTy =
- CGM.getTypes().GetFunctionType(
- CGM.getTypes().arrangeCXXMethodType(RD, FPT));
+ llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
+ CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr));
llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
@@ -433,9 +553,11 @@ llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
// Apply the adjustment and cast back to the original struct type
// for consistency.
+ llvm::Value *This = ThisAddr.getPointer();
llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy());
Ptr = Builder.CreateInBoundsGEP(Ptr, Adj);
This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted");
+ ThisPtrForCall = This;
// Load the function pointer.
llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr");
@@ -457,7 +579,11 @@ llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
// Cast the adjusted this to a pointer to vtable pointer and load.
llvm::Type *VTableTy = Builder.getInt8PtrTy();
- llvm::Value *VTable = CGF.GetVTablePtr(This, VTableTy);
+ CharUnits VTablePtrAlign =
+ CGF.CGM.getDynamicOffsetAlignment(ThisAddr.getAlignment(), RD,
+ CGF.getPointerAlign());
+ llvm::Value *VTable =
+ CGF.GetVTablePtr(Address(This, VTablePtrAlign), VTableTy, RD);
// Apply the offset.
llvm::Value *VTableOffset = FnAsInt;
@@ -467,7 +593,9 @@ llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
// Load the virtual function to call.
VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo());
- llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "memptr.virtualfn");
+ llvm::Value *VirtualFn =
+ Builder.CreateAlignedLoad(VTable, CGF.getPointerAlign(),
+ "memptr.virtualfn");
CGF.EmitBranch(FnEnd);
// In the non-virtual path, the function pointer is actually a
@@ -487,24 +615,23 @@ llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
/// Compute an l-value by applying the given pointer-to-member to a
/// base object.
llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(
- CodeGenFunction &CGF, const Expr *E, llvm::Value *Base, llvm::Value *MemPtr,
+ CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr,
const MemberPointerType *MPT) {
assert(MemPtr->getType() == CGM.PtrDiffTy);
CGBuilderTy &Builder = CGF.Builder;
- unsigned AS = Base->getType()->getPointerAddressSpace();
-
// Cast to char*.
- Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS));
+ Base = Builder.CreateElementBitCast(Base, CGF.Int8Ty);
// Apply the offset, which we assume is non-null.
- llvm::Value *Addr = Builder.CreateInBoundsGEP(Base, MemPtr, "memptr.offset");
+ llvm::Value *Addr =
+ Builder.CreateInBoundsGEP(Base.getPointer(), MemPtr, "memptr.offset");
// Cast the address to the appropriate pointer type, adopting the
// address space of the base pointer.
- llvm::Type *PType
- = CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS);
+ llvm::Type *PType = CGF.ConvertTypeForMem(MPT->getPointeeType())
+ ->getPointerTo(Base.getAddressSpace());
return Builder.CreateBitCast(Addr, PType);
}
@@ -858,7 +985,8 @@ bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
// FIXME: Use canCopyArgument() when it is fixed to handle lazily declared
// special members.
if (RD->hasNonTrivialDestructor() || RD->hasNonTrivialCopyConstructor()) {
- FI.getReturnInfo() = ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
+ FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
return true;
}
return false;
@@ -874,7 +1002,7 @@ bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
/// at entry -2 in the vtable.
void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *DE,
- llvm::Value *Ptr,
+ Address Ptr,
QualType ElementType,
const CXXDestructorDecl *Dtor) {
bool UseGlobalDelete = DE->isGlobalDelete();
@@ -883,16 +1011,20 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
// to pass to the deallocation function.
// Grab the vtable pointer as an intptr_t*.
- llvm::Value *VTable = CGF.GetVTablePtr(Ptr, CGF.IntPtrTy->getPointerTo());
+ auto *ClassDecl =
+ cast<CXXRecordDecl>(ElementType->getAs<RecordType>()->getDecl());
+ llvm::Value *VTable =
+ CGF.GetVTablePtr(Ptr, CGF.IntPtrTy->getPointerTo(), ClassDecl);
// Track back to entry -2 and pull out the offset there.
llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
VTable, -2, "complete-offset.ptr");
- llvm::LoadInst *Offset = CGF.Builder.CreateLoad(OffsetPtr);
- Offset->setAlignment(CGF.PointerAlignInBytes);
+ llvm::Value *Offset =
+ CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign());
// Apply the offset.
- llvm::Value *CompletePtr = CGF.Builder.CreateBitCast(Ptr, CGF.Int8PtrTy);
+ llvm::Value *CompletePtr =
+ CGF.Builder.CreateBitCast(Ptr.getPointer(), CGF.Int8PtrTy);
CompletePtr = CGF.Builder.CreateInBoundsGEP(CompletePtr, Offset);
// If we're supposed to call the global delete, make sure we do so
@@ -954,7 +1086,8 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
llvm::CallInst *ExceptionPtr = CGF.EmitNounwindRuntimeCall(
AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception");
- CGF.EmitAnyExprToExn(E->getSubExpr(), ExceptionPtr);
+ CharUnits ExnAlign = getAlignmentOfExnObject();
+ CGF.EmitAnyExprToExn(E->getSubExpr(), Address(ExceptionPtr, ExnAlign));
// Now throw the exception.
llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
@@ -1023,25 +1156,25 @@ static CharUnits computeOffsetHint(ASTContext &Context,
CharUnits Offset;
// Now walk all possible inheritance paths.
- for (CXXBasePaths::paths_iterator I = Paths.begin(), E = Paths.end(); I != E;
- ++I) {
- if (I->Access != AS_public) // Ignore non-public inheritance.
+ for (const CXXBasePath &Path : Paths) {
+ if (Path.Access != AS_public) // Ignore non-public inheritance.
continue;
++NumPublicPaths;
- for (CXXBasePath::iterator J = I->begin(), JE = I->end(); J != JE; ++J) {
+ for (const CXXBasePathElement &PathElement : Path) {
// If the path contains a virtual base class we can't give any hint.
// -1: no hint.
- if (J->Base->isVirtual())
+ if (PathElement.Base->isVirtual())
return CharUnits::fromQuantity(-1ULL);
if (NumPublicPaths > 1) // Won't use offsets, skip computation.
continue;
// Accumulate the base class offsets.
- const ASTRecordLayout &L = Context.getASTRecordLayout(J->Class);
- Offset += L.getBaseClassOffset(J->Base->getType()->getAsCXXRecordDecl());
+ const ASTRecordLayout &L = Context.getASTRecordLayout(PathElement.Class);
+ Offset += L.getBaseClassOffset(
+ PathElement.Base->getType()->getAsCXXRecordDecl());
}
}
@@ -1078,14 +1211,16 @@ void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
QualType SrcRecordTy,
- llvm::Value *ThisPtr,
+ Address ThisPtr,
llvm::Type *StdTypeInfoPtrTy) {
+ auto *ClassDecl =
+ cast<CXXRecordDecl>(SrcRecordTy->getAs<RecordType>()->getDecl());
llvm::Value *Value =
- CGF.GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo());
+ CGF.GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo(), ClassDecl);
// Load the type info.
Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL);
- return CGF.Builder.CreateLoad(Value);
+ return CGF.Builder.CreateAlignedLoad(Value, CGF.getPointerAlign());
}
bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
@@ -1094,7 +1229,7 @@ bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
}
llvm::Value *ItaniumCXXABI::EmitDynamicCastCall(
- CodeGenFunction &CGF, llvm::Value *Value, QualType SrcRecordTy,
+ CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,
QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
llvm::Type *PtrDiffLTy =
CGF.ConvertType(CGF.getContext().getPointerDiffType());
@@ -1113,6 +1248,7 @@ llvm::Value *ItaniumCXXABI::EmitDynamicCastCall(
computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity());
// Emit the call to __dynamic_cast.
+ llvm::Value *Value = ThisAddr.getPointer();
Value = CGF.EmitCastToVoidPtr(Value);
llvm::Value *args[] = {Value, SrcRTTI, DestRTTI, OffsetHint};
@@ -1136,22 +1272,28 @@ llvm::Value *ItaniumCXXABI::EmitDynamicCastCall(
}
llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF,
- llvm::Value *Value,
+ Address ThisAddr,
QualType SrcRecordTy,
QualType DestTy) {
llvm::Type *PtrDiffLTy =
CGF.ConvertType(CGF.getContext().getPointerDiffType());
llvm::Type *DestLTy = CGF.ConvertType(DestTy);
+ auto *ClassDecl =
+ cast<CXXRecordDecl>(SrcRecordTy->getAs<RecordType>()->getDecl());
// Get the vtable pointer.
- llvm::Value *VTable = CGF.GetVTablePtr(Value, PtrDiffLTy->getPointerTo());
+ llvm::Value *VTable = CGF.GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(),
+ ClassDecl);
// Get the offset-to-top from the vtable.
llvm::Value *OffsetToTop =
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL);
- OffsetToTop = CGF.Builder.CreateLoad(OffsetToTop, "offset.to.top");
+ OffsetToTop =
+ CGF.Builder.CreateAlignedLoad(OffsetToTop, CGF.getPointerAlign(),
+ "offset.to.top");
// Finally, add the offset to the pointer.
+ llvm::Value *Value = ThisAddr.getPointer();
Value = CGF.EmitCastToVoidPtr(Value);
Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop);
@@ -1167,10 +1309,10 @@ bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
llvm::Value *
ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
- llvm::Value *This,
+ Address This,
const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl) {
- llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy);
+ llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);
CharUnits VBaseOffsetOffset =
CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
BaseClassDecl);
@@ -1182,7 +1324,8 @@ ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
CGM.PtrDiffTy->getPointerTo());
llvm::Value *VBaseOffset =
- CGF.Builder.CreateLoad(VBaseOffsetPtr, "vbase.offset");
+ CGF.Builder.CreateAlignedLoad(VBaseOffsetPtr, CGF.getPointerAlign(),
+ "vbase.offset");
return VBaseOffset;
}
@@ -1293,7 +1436,7 @@ unsigned ItaniumCXXABI::addImplicitConstructorArgs(
void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *DD,
CXXDtorType Type, bool ForVirtualBase,
- bool Delegating, llvm::Value *This) {
+ bool Delegating, Address This) {
GlobalDecl GD(DD, Type);
llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating);
QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
@@ -1305,8 +1448,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
if (!Callee)
Callee = CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type));
- CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(), This, VTT,
- VTTTy, nullptr);
+ CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(),
+ This.getPointer(), VTT, VTTTy, nullptr);
}
void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
@@ -1356,41 +1499,29 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
CGM.EmitVTableBitSetEntries(VTable, VTLayout);
}
+bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
+ CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {
+ if (Vptr.NearestVBase == nullptr)
+ return false;
+ return NeedsVTTParameter(CGF.CurGD);
+}
+
llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
- const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
- bool NeedsVTTParam = CGM.getCXXABI().NeedsVTTParameter(CGF.CurGD);
- NeedsVirtualOffset = (NeedsVTTParam && NearestVBase);
-
- llvm::Value *VTableAddressPoint;
- if (NeedsVTTParam && (Base.getBase()->getNumVBases() || NearestVBase)) {
- // Get the secondary vpointer index.
- uint64_t VirtualPointerIndex =
- CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);
-
- /// Load the VTT.
- llvm::Value *VTT = CGF.LoadCXXVTT();
- if (VirtualPointerIndex)
- VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex);
-
- // And load the address point from the VTT.
- VTableAddressPoint = CGF.Builder.CreateLoad(VTT);
- } else {
- llvm::Constant *VTable =
- CGM.getCXXABI().getAddrOfVTable(VTableClass, CharUnits());
- uint64_t AddressPoint = CGM.getItaniumVTableContext()
- .getVTableLayout(VTableClass)
- .getAddressPoint(Base);
- VTableAddressPoint =
- CGF.Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint);
- }
+ const CXXRecordDecl *NearestVBase) {
- return VTableAddressPoint;
+ if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
+ NeedsVTTParameter(CGF.CurGD)) {
+ return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base,
+ NearestVBase);
+ }
+ return getVTableAddressPoint(Base, VTableClass);
}
-llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
- BaseSubobject Base, const CXXRecordDecl *VTableClass) {
- auto *VTable = getAddrOfVTable(VTableClass, CharUnits());
+llvm::Constant *
+ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
+ const CXXRecordDecl *VTableClass) {
+ llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits());
// Find the appropriate vtable within the vtable group.
uint64_t AddressPoint = CGM.getItaniumVTableContext()
@@ -1405,6 +1536,30 @@ llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
VTable, Indices);
}
+llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
+ CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
+ const CXXRecordDecl *NearestVBase) {
+ assert((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
+ NeedsVTTParameter(CGF.CurGD) && "This class doesn't have VTT");
+
+ // Get the secondary vpointer index.
+ uint64_t VirtualPointerIndex =
+ CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);
+
+ /// Load the VTT.
+ llvm::Value *VTT = CGF.LoadCXXVTT();
+ if (VirtualPointerIndex)
+ VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex);
+
+ // And load the address point from the VTT.
+ return CGF.Builder.CreateAlignedLoad(VTT, CGF.getPointerAlign());
+}
+
+llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
+ BaseSubobject Base, const CXXRecordDecl *VTableClass) {
+ return getVTableAddressPoint(Base, VTableClass);
+}
+
llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
CharUnits VPtrOffset) {
assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
@@ -1416,11 +1571,9 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
// Queue up this v-table for possible deferred emission.
CGM.addDeferredVTable(RD);
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
+ SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
getMangleContext().mangleCXXVTable(RD, Out);
- Out.flush();
- StringRef Name = OutName.str();
ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();
llvm::ArrayType *ArrayType = llvm::ArrayType::get(
@@ -1440,26 +1593,27 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD,
- llvm::Value *This,
+ Address This,
llvm::Type *Ty,
SourceLocation Loc) {
GD = GD.getCanonicalDecl();
Ty = Ty->getPointerTo()->getPointerTo();
- llvm::Value *VTable = CGF.GetVTablePtr(This, Ty);
+ auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
+ llvm::Value *VTable = CGF.GetVTablePtr(This, Ty, MethodDecl->getParent());
if (CGF.SanOpts.has(SanitizerKind::CFIVCall))
- CGF.EmitVTablePtrCheckForCall(cast<CXXMethodDecl>(GD.getDecl()), VTable,
+ CGF.EmitVTablePtrCheckForCall(MethodDecl, VTable,
CodeGenFunction::CFITCK_VCall, Loc);
uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
llvm::Value *VFuncPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn");
- return CGF.Builder.CreateLoad(VFuncPtr);
+ return CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
}
llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType,
- llvm::Value *This, const CXXMemberCallExpr *CE) {
+ Address This, const CXXMemberCallExpr *CE) {
assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
@@ -1470,8 +1624,9 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty,
CE ? CE->getLocStart() : SourceLocation());
- CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(), This,
- /*ImplicitParam=*/nullptr, QualType(), CE);
+ CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(),
+ This.getPointer(), /*ImplicitParam=*/nullptr,
+ QualType(), CE);
return nullptr;
}
@@ -1481,30 +1636,41 @@ void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD);
}
+bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
+ // We don't emit available_externally vtables if we are in -fapple-kext mode
+ // because kext mode does not permit devirtualization.
+ if (CGM.getLangOpts().AppleKext)
+ return false;
+
+ // If we don't have any inline virtual functions, and if vtable is not hidden,
+ // then we are safe to emit available_externally copy of vtable.
+ // FIXME we can still emit a copy of the vtable if we
+ // can emit definition of the inline functions.
+ return !hasAnyUsedVirtualInlineFunction(RD) && !isVTableHidden(RD);
+}
static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
- llvm::Value *Ptr,
+ Address InitialPtr,
int64_t NonVirtualAdjustment,
int64_t VirtualAdjustment,
bool IsReturnAdjustment) {
if (!NonVirtualAdjustment && !VirtualAdjustment)
- return Ptr;
+ return InitialPtr.getPointer();
- llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
- llvm::Value *V = CGF.Builder.CreateBitCast(Ptr, Int8PtrTy);
+ Address V = CGF.Builder.CreateElementBitCast(InitialPtr, CGF.Int8Ty);
+ // In a base-to-derived cast, the non-virtual adjustment is applied first.
if (NonVirtualAdjustment && !IsReturnAdjustment) {
- // Perform the non-virtual adjustment for a base-to-derived cast.
- V = CGF.Builder.CreateConstInBoundsGEP1_64(V, NonVirtualAdjustment);
+ V = CGF.Builder.CreateConstInBoundsByteGEP(V,
+ CharUnits::fromQuantity(NonVirtualAdjustment));
}
+ // Perform the virtual adjustment if we have one.
+ llvm::Value *ResultPtr;
if (VirtualAdjustment) {
llvm::Type *PtrDiffTy =
CGF.ConvertType(CGF.getContext().getPointerDiffType());
- // Perform the virtual adjustment.
- llvm::Value *VTablePtrPtr =
- CGF.Builder.CreateBitCast(V, Int8PtrTy->getPointerTo());
-
+ Address VTablePtrPtr = CGF.Builder.CreateElementBitCast(V, CGF.Int8PtrTy);
llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr);
llvm::Value *OffsetPtr =
@@ -1513,23 +1679,28 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
OffsetPtr = CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo());
// Load the adjustment offset from the vtable.
- llvm::Value *Offset = CGF.Builder.CreateLoad(OffsetPtr);
+ llvm::Value *Offset =
+ CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign());
// Adjust our pointer.
- V = CGF.Builder.CreateInBoundsGEP(V, Offset);
+ ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getPointer(), Offset);
+ } else {
+ ResultPtr = V.getPointer();
}
+ // In a derived-to-base conversion, the non-virtual adjustment is
+ // applied second.
if (NonVirtualAdjustment && IsReturnAdjustment) {
- // Perform the non-virtual adjustment for a derived-to-base cast.
- V = CGF.Builder.CreateConstInBoundsGEP1_64(V, NonVirtualAdjustment);
+ ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ResultPtr,
+ NonVirtualAdjustment);
}
// Cast back to the original type.
- return CGF.Builder.CreateBitCast(V, Ptr->getType());
+ return CGF.Builder.CreateBitCast(ResultPtr, InitialPtr.getType());
}
llvm::Value *ItaniumCXXABI::performThisAdjustment(CodeGenFunction &CGF,
- llvm::Value *This,
+ Address This,
const ThisAdjustment &TA) {
return performTypeAdjustment(CGF, This, TA.NonVirtual,
TA.Virtual.Itanium.VCallOffsetOffset,
@@ -1537,7 +1708,7 @@ llvm::Value *ItaniumCXXABI::performThisAdjustment(CodeGenFunction &CGF,
}
llvm::Value *
-ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
+ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
const ReturnAdjustment &RA) {
return performTypeAdjustment(CGF, Ret, RA.NonVirtual,
RA.Virtual.Itanium.VBaseOffsetOffset,
@@ -1550,8 +1721,7 @@ void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
// Destructor thunks in the ARM ABI have indeterminate results.
- llvm::Type *T =
- cast<llvm::PointerType>(CGF.ReturnValue->getType())->getElementType();
+ llvm::Type *T = CGF.ReturnValue.getElementType();
RValue Undef = RValue::get(llvm::UndefValue::get(T));
return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
}
@@ -1565,18 +1735,17 @@ CharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
CGM.getContext().getTypeAlignInChars(elementType));
}
-llvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
- llvm::Value *NewPtr,
- llvm::Value *NumElements,
- const CXXNewExpr *expr,
- QualType ElementType) {
+Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
+ Address NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType) {
assert(requiresArrayCookie(expr));
- unsigned AS = NewPtr->getType()->getPointerAddressSpace();
+ unsigned AS = NewPtr.getAddressSpace();
ASTContext &Ctx = getContext();
- QualType SizeTy = Ctx.getSizeType();
- CharUnits SizeSize = Ctx.getTypeSizeInChars(SizeTy);
+ CharUnits SizeSize = CGF.getSizeSize();
// The size of the cookie.
CharUnits CookieSize =
@@ -1584,49 +1753,45 @@ llvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
assert(CookieSize == getArrayCookieSizeImpl(ElementType));
// Compute an offset to the cookie.
- llvm::Value *CookiePtr = NewPtr;
+ Address CookiePtr = NewPtr;
CharUnits CookieOffset = CookieSize - SizeSize;
if (!CookieOffset.isZero())
- CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_64(CookiePtr,
- CookieOffset.getQuantity());
+ CookiePtr = CGF.Builder.CreateConstInBoundsByteGEP(CookiePtr, CookieOffset);
// Write the number of elements into the appropriate slot.
- llvm::Type *NumElementsTy = CGF.ConvertType(SizeTy)->getPointerTo(AS);
- llvm::Value *NumElementsPtr =
- CGF.Builder.CreateBitCast(CookiePtr, NumElementsTy);
+ Address NumElementsPtr =
+ CGF.Builder.CreateElementBitCast(CookiePtr, CGF.SizeTy);
llvm::Instruction *SI = CGF.Builder.CreateStore(NumElements, NumElementsPtr);
+
+ // Handle the array cookie specially in ASan.
if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 &&
expr->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
// The store to the CookiePtr does not need to be instrumented.
CGM.getSanitizerMetadata()->disableSanitizerForInstruction(SI);
llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.VoidTy, NumElementsTy, false);
+ llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false);
llvm::Constant *F =
CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie");
- CGF.Builder.CreateCall(F, NumElementsPtr);
+ CGF.Builder.CreateCall(F, NumElementsPtr.getPointer());
}
// Finally, compute a pointer to the actual data buffer by skipping
// over the cookie completely.
- return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr,
- CookieSize.getQuantity());
+ return CGF.Builder.CreateConstInBoundsByteGEP(NewPtr, CookieSize);
}
llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
- llvm::Value *allocPtr,
+ Address allocPtr,
CharUnits cookieSize) {
// The element size is right-justified in the cookie.
- llvm::Value *numElementsPtr = allocPtr;
- CharUnits numElementsOffset =
- cookieSize - CharUnits::fromQuantity(CGF.SizeSizeInBytes);
+ Address numElementsPtr = allocPtr;
+ CharUnits numElementsOffset = cookieSize - CGF.getSizeSize();
if (!numElementsOffset.isZero())
numElementsPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(numElementsPtr,
- numElementsOffset.getQuantity());
+ CGF.Builder.CreateConstInBoundsByteGEP(numElementsPtr, numElementsOffset);
- unsigned AS = allocPtr->getType()->getPointerAddressSpace();
- numElementsPtr =
- CGF.Builder.CreateBitCast(numElementsPtr, CGF.SizeTy->getPointerTo(AS));
+ unsigned AS = allocPtr.getAddressSpace();
+ numElementsPtr = CGF.Builder.CreateElementBitCast(numElementsPtr, CGF.SizeTy);
if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) || AS != 0)
return CGF.Builder.CreateLoad(numElementsPtr);
// In asan mode emit a function call instead of a regular load and let the
@@ -1638,7 +1803,7 @@ llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
llvm::FunctionType::get(CGF.SizeTy, CGF.SizeTy->getPointerTo(0), false);
llvm::Constant *F =
CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie");
- return CGF.Builder.CreateCall(F, numElementsPtr);
+ return CGF.Builder.CreateCall(F, numElementsPtr.getPointer());
}
CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
@@ -1654,47 +1819,41 @@ CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
CGM.getContext().getTypeAlignInChars(elementType));
}
-llvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
- llvm::Value *newPtr,
- llvm::Value *numElements,
- const CXXNewExpr *expr,
- QualType elementType) {
+Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
+ Address newPtr,
+ llvm::Value *numElements,
+ const CXXNewExpr *expr,
+ QualType elementType) {
assert(requiresArrayCookie(expr));
- // NewPtr is a char*, but we generalize to arbitrary addrspaces.
- unsigned AS = newPtr->getType()->getPointerAddressSpace();
-
// The cookie is always at the start of the buffer.
- llvm::Value *cookie = newPtr;
+ Address cookie = newPtr;
// The first element is the element size.
- cookie = CGF.Builder.CreateBitCast(cookie, CGF.SizeTy->getPointerTo(AS));
+ cookie = CGF.Builder.CreateElementBitCast(cookie, CGF.SizeTy);
llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy,
getContext().getTypeSizeInChars(elementType).getQuantity());
CGF.Builder.CreateStore(elementSize, cookie);
// The second element is the element count.
- cookie = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.SizeTy, cookie, 1);
+ cookie = CGF.Builder.CreateConstInBoundsGEP(cookie, 1, CGF.getSizeSize());
CGF.Builder.CreateStore(numElements, cookie);
// Finally, compute a pointer to the actual data buffer by skipping
// over the cookie completely.
CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType);
- return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr,
- cookieSize.getQuantity());
+ return CGF.Builder.CreateConstInBoundsByteGEP(newPtr, cookieSize);
}
llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
- llvm::Value *allocPtr,
+ Address allocPtr,
CharUnits cookieSize) {
// The number of elements is at offset sizeof(size_t) relative to
// the allocated pointer.
- llvm::Value *numElementsPtr
- = CGF.Builder.CreateConstInBoundsGEP1_64(allocPtr, CGF.SizeSizeInBytes);
+ Address numElementsPtr
+ = CGF.Builder.CreateConstInBoundsByteGEP(allocPtr, CGF.getSizeSize());
- unsigned AS = allocPtr->getType()->getPointerAddressSpace();
- numElementsPtr =
- CGF.Builder.CreateBitCast(numElementsPtr, CGF.SizeTy->getPointerTo(AS));
+ numElementsPtr = CGF.Builder.CreateElementBitCast(numElementsPtr, CGF.SizeTy);
return CGF.Builder.CreateLoad(numElementsPtr);
}
@@ -1735,7 +1894,7 @@ static llvm::Constant *getGuardAbortFn(CodeGenModule &CGM,
}
namespace {
- struct CallGuardAbort : EHScopeStack::Cleanup {
+ struct CallGuardAbort final : EHScopeStack::Cleanup {
llvm::GlobalVariable *Guard;
CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
@@ -1764,12 +1923,21 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
bool useInt8GuardVariable = !threadsafe && var->hasInternalLinkage();
llvm::IntegerType *guardTy;
+ CharUnits guardAlignment;
if (useInt8GuardVariable) {
guardTy = CGF.Int8Ty;
+ guardAlignment = CharUnits::One();
} else {
// Guard variables are 64 bits in the generic ABI and size width on ARM
// (i.e. 32-bit on AArch32, 64-bit on AArch64).
- guardTy = (UseARMGuardVarABI ? CGF.SizeTy : CGF.Int64Ty);
+ if (UseARMGuardVarABI) {
+ guardTy = CGF.SizeTy;
+ guardAlignment = CGF.getSizeAlign();
+ } else {
+ guardTy = CGF.Int64Ty;
+ guardAlignment = CharUnits::fromQuantity(
+ CGM.getDataLayout().getABITypeAlignment(guardTy));
+ }
}
llvm::PointerType *guardPtrTy = guardTy->getPointerTo();
@@ -1782,7 +1950,6 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
{
llvm::raw_svector_ostream out(guardName);
getMangleContext().mangleStaticGuardVariable(&D, out);
- out.flush();
}
// Create the guard variable with a zero-initializer.
@@ -1794,11 +1961,14 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
guard->setVisibility(var->getVisibility());
// If the variable is thread-local, so is its guard variable.
guard->setThreadLocalMode(var->getThreadLocalMode());
+ guard->setAlignment(guardAlignment.getQuantity());
- // The ABI says: It is suggested that it be emitted in the same COMDAT group
- // as the associated data object
+ // The ABI says: "It is suggested that it be emitted in the same COMDAT
+ // group as the associated data object." In practice, this doesn't work for
+ // non-ELF object formats, so only do it for ELF.
llvm::Comdat *C = var->getComdat();
- if (!D.isLocalVarDecl() && C) {
+ if (!D.isLocalVarDecl() && C &&
+ CGM.getTarget().getTriple().isOSBinFormatELF()) {
guard->setComdat(C);
CGF.CurFn->setComdat(C);
} else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) {
@@ -1808,6 +1978,8 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
CGM.setStaticLocalDeclGuardAddress(&D, guard);
}
+ Address guardAddr = Address(guard, guardAlignment);
+
// Test whether the variable has completed initialization.
//
// Itanium C++ ABI 3.3.2:
@@ -1827,8 +1999,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
// Load the first byte of the guard variable.
llvm::LoadInst *LI =
- Builder.CreateLoad(Builder.CreateBitCast(guard, CGM.Int8PtrTy));
- LI->setAlignment(1);
+ Builder.CreateLoad(Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
// Itanium ABI:
// An implementation supporting thread-safety on multiprocessor
@@ -1898,9 +2069,10 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
CGF.PopCleanupBlock();
// Call __cxa_guard_release. This cannot throw.
- CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy), guard);
+ CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy),
+ guardAddr.getPointer());
} else {
- Builder.CreateStore(llvm::ConstantInt::get(guardTy, 1), guard);
+ Builder.CreateStore(llvm::ConstantInt::get(guardTy, 1), guardAddr);
}
CGF.EmitBlock(EndBlock);
@@ -1914,7 +2086,7 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
const char *Name = "__cxa_atexit";
if (TLS) {
const llvm::Triple &T = CGF.getTarget().getTriple();
- Name = T.isMacOSX() ? "_tlv_atexit" : "__cxa_thread_atexit";
+ Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit";
}
// We're assuming that the destructor function is something we can
@@ -1970,10 +2142,10 @@ void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
static bool isThreadWrapperReplaceable(const VarDecl *VD,
CodeGen::CodeGenModule &CGM) {
assert(!VD->isStaticLocal() && "static local VarDecls don't need wrappers!");
- // OS X prefers to have references to thread local variables to go through
+ // Darwin prefers to have references to thread local variables to go through
// the thread wrapper instead of directly referencing the backing variable.
return VD->getTLSKind() == VarDecl::TLS_Dynamic &&
- CGM.getTarget().getTriple().isMacOSX();
+ CGM.getTarget().getTriple().isOSDarwin();
}
/// Get the appropriate linkage for the wrapper function. This is essentially
@@ -1989,12 +2161,10 @@ getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) {
return VarLinkage;
// If the thread wrapper is replaceable, give it appropriate linkage.
- if (isThreadWrapperReplaceable(VD, CGM)) {
- if (llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) ||
- llvm::GlobalVariable::isWeakODRLinkage(VarLinkage))
- return llvm::GlobalVariable::WeakAnyLinkage;
- return VarLinkage;
- }
+ if (isThreadWrapperReplaceable(VD, CGM))
+ if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) &&
+ !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage))
+ return VarLinkage;
return llvm::GlobalValue::WeakODRLinkage;
}
@@ -2006,7 +2176,6 @@ ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
{
llvm::raw_svector_ostream Out(WrapperName);
getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out);
- Out.flush();
}
if (llvm::Value *V = CGM.getModule().getNamedValue(WrapperName))
@@ -2021,22 +2190,29 @@ ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM),
WrapperName.str(), &CGM.getModule());
// Always resolve references to the wrapper at link time.
- if (!Wrapper->hasLocalLinkage() && !isThreadWrapperReplaceable(VD, CGM))
+ if (!Wrapper->hasLocalLinkage() && !(isThreadWrapperReplaceable(VD, CGM) &&
+ !llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) &&
+ !llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage())))
Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
+
+ if (isThreadWrapperReplaceable(VD, CGM)) {
+ Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
+ Wrapper->addFnAttr(llvm::Attribute::NoUnwind);
+ }
return Wrapper;
}
void ItaniumCXXABI::EmitThreadLocalInitFuncs(
- CodeGenModule &CGM,
- ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>>
- CXXThreadLocals, ArrayRef<llvm::Function *> CXXThreadLocalInits,
- ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) {
+ CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
+ ArrayRef<llvm::Function *> CXXThreadLocalInits,
+ ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
llvm::Function *InitFunc = nullptr;
if (!CXXThreadLocalInits.empty()) {
// Generate a guarded initialization function.
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
- InitFunc = CGM.CreateGlobalInitOrDestructFunction(FTy, "__tls_init",
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
+ InitFunc = CGM.CreateGlobalInitOrDestructFunction(FTy, "__tls_init", FI,
SourceLocation(),
/*TLS=*/true);
llvm::GlobalVariable *Guard = new llvm::GlobalVariable(
@@ -2044,12 +2220,17 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
llvm::GlobalVariable::InternalLinkage,
llvm::ConstantInt::get(CGM.Int8Ty, 0), "__tls_guard");
Guard->setThreadLocal(true);
+
+ CharUnits GuardAlign = CharUnits::One();
+ Guard->setAlignment(GuardAlign.getQuantity());
+
CodeGenFunction(CGM)
- .GenerateCXXGlobalInitFunc(InitFunc, CXXThreadLocalInits, Guard);
+ .GenerateCXXGlobalInitFunc(InitFunc, CXXThreadLocalInits,
+ Address(Guard, GuardAlign));
}
- for (unsigned I = 0, N = CXXThreadLocals.size(); I != N; ++I) {
- const VarDecl *VD = CXXThreadLocals[I].first;
- llvm::GlobalVariable *Var = CXXThreadLocals[I].second;
+ for (const VarDecl *VD : CXXThreadLocals) {
+ llvm::GlobalVariable *Var =
+ cast<llvm::GlobalVariable>(CGM.GetGlobalValue(CGM.getMangledName(VD)));
// Some targets require that all access to thread local variables go through
// the thread wrapper. This means that we cannot attempt to create a thread
@@ -2062,7 +2243,6 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
{
llvm::raw_svector_ostream Out(InitFnName);
getMangleContext().mangleItaniumThreadLocalInit(VD, Out);
- Out.flush();
}
// If we have a definition for the variable, emit the initialization
@@ -2092,7 +2272,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Var);
llvm::LLVMContext &Context = CGM.getModule().getContext();
llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper);
- CGBuilderTy Builder(Entry);
+ CGBuilderTy Builder(CGM, Entry);
if (InitIsInitFunc) {
if (Init)
Builder.CreateCall(Init);
@@ -2114,9 +2294,8 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
// the referenced object.
llvm::Value *Val = Var;
if (VD->getType()->isReferenceType()) {
- llvm::LoadInst *LI = Builder.CreateLoad(Val);
- LI->setAlignment(CGM.getContext().getDeclAlign(VD).getQuantity());
- Val = LI;
+ CharUnits Align = CGM.getContext().getDeclAlign(VD);
+ Val = Builder.CreateAlignedLoad(Val, Align);
}
if (Val->getType() != Wrapper->getReturnType())
Val = Builder.CreatePointerBitCastOrAddrSpaceCast(
@@ -2128,18 +2307,19 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
const VarDecl *VD,
QualType LValType) {
- QualType T = VD->getType();
- llvm::Type *Ty = CGF.getTypes().ConvertTypeForMem(T);
- llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD, Ty);
+ llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD);
llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
- Val = CGF.Builder.CreateCall(Wrapper);
+ llvm::CallInst *CallVal = CGF.Builder.CreateCall(Wrapper);
+ if (isThreadWrapperReplaceable(VD, CGF.CGM))
+ CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
LValue LV;
if (VD->getType()->isReferenceType())
- LV = CGF.MakeNaturalAlignAddrLValue(Val, LValType);
+ LV = CGF.MakeNaturalAlignAddrLValue(CallVal, LValType);
else
- LV = CGF.MakeAddrLValue(Val, LValType, CGF.getContext().getDeclAlign(VD));
+ LV = CGF.MakeAddrLValue(CallVal, LValType,
+ CGF.getContext().getDeclAlign(VD));
// FIXME: need setObjCGCLValueClass?
return LV;
}
@@ -2255,11 +2435,9 @@ public:
llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) {
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
+ SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
- Out.flush();
- StringRef Name = OutName.str();
// We know that the mangled name of the type starts at index 4 of the
// mangled name of the typename, so we can just index into it in order to
@@ -2278,11 +2456,9 @@ llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
llvm::Constant *
ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
// Mangle the RTTI name.
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
+ SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
- Out.flush();
- StringRef Name = OutName.str();
// Look for an existing global.
llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
@@ -2346,9 +2522,19 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
case BuiltinType::OCLImage1dBuffer:
case BuiltinType::OCLImage2d:
case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage2dDepth:
+ case BuiltinType::OCLImage2dArrayDepth:
+ case BuiltinType::OCLImage2dMSAA:
+ case BuiltinType::OCLImage2dArrayMSAA:
+ case BuiltinType::OCLImage2dMSAADepth:
+ case BuiltinType::OCLImage2dArrayMSAADepth:
case BuiltinType::OCLImage3d:
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLNDRange:
+ case BuiltinType::OCLReserveID:
return true;
case BuiltinType::Dependent:
@@ -2529,6 +2715,9 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
case Type::Auto:
llvm_unreachable("Undeduced auto type shouldn't get here");
+ case Type::Pipe:
+ llvm_unreachable("Pipe types shouldn't get here");
+
case Type::Builtin:
// GCC treats vector and complex types as fundamental types.
case Type::Vector:
@@ -2678,11 +2867,9 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
Ty = CGM.getContext().getCanonicalType(Ty);
// Check if we've already emitted an RTTI descriptor for this type.
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
+ SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
- Out.flush();
- StringRef Name = OutName.str();
llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
if (OldGV && !OldGV->isDeclaration()) {
@@ -2755,6 +2942,9 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
case Type::Auto:
llvm_unreachable("Undeduced auto type shouldn't get here");
+ case Type::Pipe:
+ llvm_unreachable("Pipe type shouldn't get here");
+
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
@@ -2818,9 +3008,6 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
new llvm::GlobalVariable(M, Init->getType(),
/*Constant=*/true, Linkage, Init, Name);
- if (CGM.supportsCOMDAT() && GV->isWeakForLinker())
- GV->setComdat(M.getOrInsertComdat(GV->getName()));
-
// If there's already an old global variable, replace it with the new one.
if (OldGV) {
GV->takeName(OldGV);
@@ -2830,6 +3017,9 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
OldGV->eraseFromParent();
}
+ if (CGM.supportsCOMDAT() && GV->isWeakForLinker())
+ GV->setComdat(M.getOrInsertComdat(GV->getName()));
+
// The Itanium ABI specifies that type_info objects must be globally
// unique, with one exception: if the type is an incomplete class
// type or a (possibly indirect) pointer to one. That exception
@@ -3232,15 +3422,13 @@ static void emitConstructorDestructorAlias(CodeGenModule &CGM,
return;
auto *Aliasee = cast<llvm::GlobalValue>(CGM.GetAddrOfGlobal(TargetDecl));
- llvm::PointerType *AliasType = Aliasee->getType();
// Create the alias with no name.
- auto *Alias = llvm::GlobalAlias::create(AliasType, Linkage, "", Aliasee,
- &CGM.getModule());
+ auto *Alias = llvm::GlobalAlias::create(Linkage, "", Aliasee);
// Switch any previous uses to the alias.
if (Entry) {
- assert(Entry->getType() == AliasType &&
+ assert(Entry->getType() == Aliasee->getType() &&
"declaration exists with different type");
Alias->takeName(Entry);
Entry->replaceAllUsesWith(Alias);
@@ -3278,7 +3466,7 @@ void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
if (CGType == StructorCodegen::RAUW) {
StringRef MangledName = CGM.getMangledName(CompleteDecl);
- auto *Aliasee = cast<llvm::GlobalValue>(CGM.GetAddrOfGlobal(BaseDecl));
+ auto *Aliasee = CGM.GetAddrOfGlobal(BaseDecl);
CGM.addReplacement(MangledName, Aliasee);
return;
}
@@ -3345,7 +3533,7 @@ namespace {
/// of the caught type, so we have to assume the actual thrown
/// exception type might have a throwing destructor, even if the
/// caught type's destructor is trivial or nothrow.
- struct CallEndCatch : EHScopeStack::Cleanup {
+ struct CallEndCatch final : EHScopeStack::Cleanup {
CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
bool MightThrow;
@@ -3379,7 +3567,7 @@ static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
/// parameter during catch initialization.
static void InitCatchParam(CodeGenFunction &CGF,
const VarDecl &CatchParam,
- llvm::Value *ParamAddr,
+ Address ParamAddr,
SourceLocation Loc) {
// Load the exception from where the landing pad saved it.
llvm::Value *Exn = CGF.getExceptionFromSlot();
@@ -3433,12 +3621,13 @@ static void InitCatchParam(CodeGenFunction &CGF,
cast<llvm::PointerType>(LLVMCatchTy)->getElementType();
// Create the temporary and write the adjusted pointer into it.
- llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, "exn.byref.tmp");
+ Address ExnPtrTmp =
+ CGF.CreateTempAlloca(PtrTy, CGF.getPointerAlign(), "exn.byref.tmp");
llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
CGF.Builder.CreateStore(Casted, ExnPtrTmp);
// Bind the reference to the temporary.
- AdjustedExn = ExnPtrTmp;
+ AdjustedExn = ExnPtrTmp.getPointer();
}
}
@@ -3483,8 +3672,7 @@ static void InitCatchParam(CodeGenFunction &CGF,
llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
LValue srcLV = CGF.MakeNaturalAlignAddrLValue(Cast, CatchType);
- LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType,
- CGF.getContext().getDeclAlign(&CatchParam));
+ LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType);
switch (TEK) {
case TEK_Complex:
CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV,
@@ -3502,6 +3690,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
}
assert(isa<RecordType>(CatchType) && "unexpected catch type!");
+ auto catchRD = CatchType->getAsCXXRecordDecl();
+ CharUnits caughtExnAlignment = CGF.CGM.getClassPointerAlignment(catchRD);
llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
@@ -3510,7 +3700,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
const Expr *copyExpr = CatchParam.getInit();
if (!copyExpr) {
llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);
- llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);
+ Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
+ caughtExnAlignment);
CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType);
return;
}
@@ -3521,7 +3712,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);
// Cast that to the appropriate type.
- llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);
+ Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
+ caughtExnAlignment);
// The copy expression is defined in terms of an OpaqueValueExpr.
// Find it and map it to the adjusted expression.
@@ -3533,9 +3725,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
CGF.EHStack.pushTerminate();
// Perform the copy construction.
- CharUnits Alignment = CGF.getContext().getDeclAlign(&CatchParam);
CGF.EmitAggExpr(copyExpr,
- AggValueSlot::forAddr(ParamAddr, Alignment, Qualifiers(),
+ AggValueSlot::forAddr(ParamAddr, Qualifiers(),
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased));
@@ -3619,7 +3810,7 @@ static llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) {
// Set up the function.
llvm::BasicBlock *entry =
llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn);
- CGBuilderTy builder(entry);
+ CGBuilderTy builder(CGM, entry);
// Pull the exception pointer out of the parameter list.
llvm::Value *exn = &*fn->arg_begin();
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 3433990..93210d5 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//
#include "CGCXXABI.h"
+#include "CGCleanup.h"
#include "CGVTables.h"
#include "CodeGenModule.h"
#include "CodeGenTypes.h"
@@ -45,7 +46,7 @@ public:
: CGCXXABI(CGM), BaseClassDescriptorType(nullptr),
ClassHierarchyDescriptorType(nullptr),
CompleteObjectLocatorType(nullptr), CatchableTypeType(nullptr),
- ThrowInfoType(nullptr), CatchHandlerTypeType(nullptr) {}
+ ThrowInfoType(nullptr) {}
bool HasThisReturn(GlobalDecl GD) const override;
bool hasMostDerivedReturn(GlobalDecl GD) const override;
@@ -56,6 +57,27 @@ public:
bool isSRetParameterAfterThis() const override { return true; }
+ bool isThisCompleteObject(GlobalDecl GD) const override {
+ // The Microsoft ABI doesn't use separate complete-object vs.
+ // base-object variants of constructors, but it does of destructors.
+ if (isa<CXXDestructorDecl>(GD.getDecl())) {
+ switch (GD.getDtorType()) {
+ case Dtor_Complete:
+ case Dtor_Deleting:
+ return true;
+
+ case Dtor_Base:
+ return false;
+
+ case Dtor_Comdat: llvm_unreachable("emitting dtor comdat as function?");
+ }
+ llvm_unreachable("bad dtor kind");
+ }
+
+ // No other kinds.
+ return false;
+ }
+
size_t getSrcArgforCopyCtor(const CXXConstructorDecl *CD,
FunctionArgList &Args) const override {
assert(Args.size() >= 2 &&
@@ -68,11 +90,30 @@ public:
return 1;
}
+ std::vector<CharUnits> getVBPtrOffsets(const CXXRecordDecl *RD) override {
+ std::vector<CharUnits> VBPtrOffsets;
+ const ASTContext &Context = getContext();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
+ for (const VPtrInfo *VBT : *VBGlobals.VBTables) {
+ const ASTRecordLayout &SubobjectLayout =
+ Context.getASTRecordLayout(VBT->BaseWithVPtr);
+ CharUnits Offs = VBT->NonVirtualOffset;
+ Offs += SubobjectLayout.getVBPtrOffset();
+ if (VBT->getVBaseWithVPtr())
+ Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr());
+ VBPtrOffsets.push_back(Offs);
+ }
+ llvm::array_pod_sort(VBPtrOffsets.begin(), VBPtrOffsets.end());
+ return VBPtrOffsets;
+ }
+
StringRef GetPureVirtualCallName() override { return "_purecall"; }
StringRef GetDeletedVirtualCallName() override { return "_purecall"; }
void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,
- llvm::Value *Ptr, QualType ElementType,
+ Address Ptr, QualType ElementType,
const CXXDestructorDecl *Dtor) override;
void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override;
@@ -84,31 +125,39 @@ public:
const VPtrInfo *Info);
llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
- llvm::Constant *
+ CatchTypeInfo
getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) override;
+ /// MSVC needs an extra flag to indicate a catchall.
+ CatchTypeInfo getCatchAllTypeInfo() override {
+ return CatchTypeInfo{nullptr, 0x40};
+ }
+
bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override;
void EmitBadTypeidCall(CodeGenFunction &CGF) override;
llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
- llvm::Value *ThisPtr,
+ Address ThisPtr,
llvm::Type *StdTypeInfoPtrTy) override;
bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
QualType SrcRecordTy) override;
- llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
+ llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy, QualType DestTy,
QualType DestRecordTy,
llvm::BasicBlock *CastEnd) override;
- llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value *Value,
+ llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy,
QualType DestTy) override;
bool EmitBadCastCall(CodeGenFunction &CGF) override;
+ bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override {
+ return false;
+ }
llvm::Value *
- GetVirtualBaseClassOffset(CodeGenFunction &CGF, llvm::Value *This,
+ GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl) override;
@@ -182,9 +231,9 @@ public:
return MD->getParent();
}
- llvm::Value *
+ Address
adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD,
- llvm::Value *This,
+ Address This,
bool VirtualCall) override;
void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
@@ -203,7 +252,7 @@ public:
void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
CXXDtorType Type, bool ForVirtualBase,
- bool Delegating, llvm::Value *This) override;
+ bool Delegating, Address This) override;
void emitVTableBitSetEntries(VPtrInfo *Info, const CXXRecordDecl *RD,
llvm::GlobalVariable *VTable);
@@ -211,10 +260,22 @@ public:
void emitVTableDefinitions(CodeGenVTables &CGVT,
const CXXRecordDecl *RD) override;
+ bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
+ CodeGenFunction::VPtr Vptr) override;
+
+ /// Don't initialize vptrs if dynamic class
+ /// is marked with with the 'novtable' attribute.
+ bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override {
+ return !VTableClass->hasAttr<MSNoVTableAttr>();
+ }
+
+ llvm::Constant *
+ getVTableAddressPoint(BaseSubobject Base,
+ const CXXRecordDecl *VTableClass) override;
+
llvm::Value *getVTableAddressPointInStructor(
CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
- BaseSubobject Base, const CXXRecordDecl *NearestVBase,
- bool &NeedsVirtualOffset) override;
+ BaseSubobject Base, const CXXRecordDecl *NearestVBase) override;
llvm::Constant *
getVTableAddressPointForConstExpr(BaseSubobject Base,
@@ -224,13 +285,13 @@ public:
CharUnits VPtrOffset) override;
llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
- llvm::Value *This, llvm::Type *Ty,
+ Address This, llvm::Type *Ty,
SourceLocation Loc) override;
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
CXXDtorType DtorType,
- llvm::Value *This,
+ Address This,
const CXXMemberCallExpr *CE) override;
void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD,
@@ -253,7 +314,6 @@ public:
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
getMangleContext().mangleCXXVirtualDisplacementMap(SrcRD, DstRD, Out);
- Out.flush();
StringRef MangledName = OutName.str();
if (auto *VDispMap = CGM.getModule().getNamedGlobal(MangledName))
@@ -310,18 +370,16 @@ public:
Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
}
- llvm::Value *performThisAdjustment(CodeGenFunction &CGF, llvm::Value *This,
+ llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
const ThisAdjustment &TA) override;
- llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
+ llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
const ReturnAdjustment &RA) override;
void EmitThreadLocalInitFuncs(
- CodeGenModule &CGM,
- ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>>
- CXXThreadLocals,
+ CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
ArrayRef<llvm::Function *> CXXThreadLocalInits,
- ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) override;
+ ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override;
bool usesThreadWrapperFunction() const override { return false; }
LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
@@ -360,13 +418,13 @@ public:
QualType elementType) override;
bool requiresArrayCookie(const CXXNewExpr *expr) override;
CharUnits getArrayCookieSizeImpl(QualType type) override;
- llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
- llvm::Value *NewPtr,
- llvm::Value *NumElements,
- const CXXNewExpr *expr,
- QualType ElementType) override;
+ Address InitializeArrayCookie(CodeGenFunction &CGF,
+ Address NewPtr,
+ llvm::Value *NumElements,
+ const CXXNewExpr *expr,
+ QualType ElementType) override;
llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
- llvm::Value *allocPtr,
+ Address allocPtr,
CharUnits cookieSize) override;
friend struct MSRTTIBuilder;
@@ -493,14 +551,6 @@ private:
return llvm::Constant::getAllOnesValue(CGM.IntTy);
}
- llvm::Constant *getConstantOrZeroInt(llvm::Constant *C) {
- return C ? C : getZeroInt();
- }
-
- llvm::Value *getValueOrZeroInt(llvm::Value *C) {
- return C ? C : getZeroInt();
- }
-
CharUnits getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD);
void
@@ -511,13 +561,13 @@ private:
/// the vbptr to the virtual base. Optionally returns the address of the
/// vbptr itself.
llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
- llvm::Value *Base,
+ Address Base,
llvm::Value *VBPtrOffset,
llvm::Value *VBTableOffset,
llvm::Value **VBPtr = nullptr);
llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
- llvm::Value *Base,
+ Address Base,
int32_t VBPtrOffset,
int32_t VBTableOffset,
llvm::Value **VBPtr = nullptr) {
@@ -527,14 +577,14 @@ private:
return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr);
}
- std::pair<llvm::Value *, llvm::Value *>
- performBaseAdjustment(CodeGenFunction &CGF, llvm::Value *Value,
+ std::pair<Address, llvm::Value *>
+ performBaseAdjustment(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy);
/// \brief Performs a full virtual base adjustment. Used to dereference
/// pointers to members of virtual bases.
llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const Expr *E,
- const CXXRecordDecl *RD, llvm::Value *Base,
+ const CXXRecordDecl *RD, Address Base,
llvm::Value *VirtualBaseAdjustmentOffset,
llvm::Value *VBPtrOffset /* optional */);
@@ -570,17 +620,6 @@ public:
return RD->hasAttr<MSInheritanceAttr>();
}
- bool isTypeInfoCalculable(QualType Ty) const override {
- if (!CGCXXABI::isTypeInfoCalculable(Ty))
- return false;
- if (const auto *MPT = Ty->getAs<MemberPointerType>()) {
- const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
- if (!RD->hasAttr<MSInheritanceAttr>())
- return false;
- }
- return true;
- }
-
llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override;
llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
@@ -600,7 +639,7 @@ public:
llvm::Value *
EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
- llvm::Value *Base, llvm::Value *MemPtr,
+ Address Base, llvm::Value *MemPtr,
const MemberPointerType *MPT) override;
llvm::Value *EmitNonNullMemberPointerConversion(
@@ -623,23 +662,12 @@ public:
llvm::Value *
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E,
- llvm::Value *&This, llvm::Value *MemPtr,
+ Address This, llvm::Value *&ThisPtrForCall,
+ llvm::Value *MemPtr,
const MemberPointerType *MPT) override;
void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
- llvm::StructType *getCatchHandlerTypeType() {
- if (!CatchHandlerTypeType) {
- llvm::Type *FieldTypes[] = {
- CGM.IntTy, // Flags
- CGM.Int8PtrTy, // TypeDescriptor
- };
- CatchHandlerTypeType = llvm::StructType::create(
- CGM.getLLVMContext(), FieldTypes, "eh.CatchHandlerType");
- }
- return CatchHandlerTypeType;
- }
-
llvm::StructType *getCatchableTypeType() {
if (CatchableTypeType)
return CatchableTypeType;
@@ -755,7 +783,6 @@ private:
llvm::StructType *CatchableTypeType;
llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap;
llvm::StructType *ThrowInfoType;
- llvm::StructType *CatchHandlerTypeType;
};
}
@@ -823,7 +850,7 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *DE,
- llvm::Value *Ptr,
+ Address Ptr,
QualType ElementType,
const CXXDestructorDecl *Dtor) {
// FIXME: Provide a source location here even though there's no
@@ -848,11 +875,15 @@ void MicrosoftCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {
}
namespace {
-struct CallEndCatchMSVC : EHScopeStack::Cleanup {
- CallEndCatchMSVC() {}
+struct CatchRetScope final : EHScopeStack::Cleanup {
+ llvm::CatchPadInst *CPI;
+
+ CatchRetScope(llvm::CatchPadInst *CPI) : CPI(CPI) {}
+
void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitNounwindRuntimeCall(
- CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_endcatch));
+ llvm::BasicBlock *BB = CGF.createBasicBlock("catchret.dest");
+ CGF.Builder.CreateCatchRet(CPI, BB);
+ CGF.EmitBlock(BB);
}
};
}
@@ -862,50 +893,59 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,
// In the MS ABI, the runtime handles the copy, and the catch handler is
// responsible for destruction.
VarDecl *CatchParam = S->getExceptionDecl();
- llvm::Value *Exn = CGF.getExceptionFromSlot();
- llvm::Function *BeginCatch =
- CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_begincatch);
+ llvm::BasicBlock *CatchPadBB = CGF.Builder.GetInsertBlock();
+ llvm::CatchPadInst *CPI =
+ cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI());
+ CGF.CurrentFuncletPad = CPI;
// If this is a catch-all or the catch parameter is unnamed, we don't need to
// emit an alloca to the object.
if (!CatchParam || !CatchParam->getDeclName()) {
- llvm::Value *Args[2] = {Exn, llvm::Constant::getNullValue(CGF.Int8PtrTy)};
- CGF.EmitNounwindRuntimeCall(BeginCatch, Args);
- CGF.EHStack.pushCleanup<CallEndCatchMSVC>(NormalCleanup);
+ CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI);
return;
}
CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
- llvm::Value *ParamAddr =
- CGF.Builder.CreateBitCast(var.getObjectAddress(CGF), CGF.Int8PtrTy);
- llvm::Value *Args[2] = {Exn, ParamAddr};
- CGF.EmitNounwindRuntimeCall(BeginCatch, Args);
- CGF.EHStack.pushCleanup<CallEndCatchMSVC>(NormalCleanup);
+ CPI->setArgOperand(2, var.getObjectAddress(CGF).getPointer());
+ CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI);
CGF.EmitAutoVarCleanups(var);
}
-std::pair<llvm::Value *, llvm::Value *>
-MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, llvm::Value *Value,
+/// We need to perform a generic polymorphic operation (like a typeid
+/// or a cast), which requires an object with a vfptr. Adjust the
+/// address to point to an object with a vfptr.
+std::pair<Address, llvm::Value *>
+MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy) {
Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy);
const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
const ASTContext &Context = getContext();
+ // If the class itself has a vfptr, great. This check implicitly
+ // covers non-virtual base subobjects: a class with its own virtual
+ // functions would be a candidate to be a primary base.
if (Context.getASTRecordLayout(SrcDecl).hasExtendableVFPtr())
return std::make_pair(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0));
- // Perform a base adjustment.
- const CXXBaseSpecifier *PolymorphicBase = std::find_if(
- SrcDecl->vbases_begin(), SrcDecl->vbases_end(),
- [&](const CXXBaseSpecifier &Base) {
- const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
- return Context.getASTRecordLayout(BaseDecl).hasExtendableVFPtr();
- });
- llvm::Value *Offset = GetVirtualBaseClassOffset(
- CGF, Value, SrcDecl, PolymorphicBase->getType()->getAsCXXRecordDecl());
- Value = CGF.Builder.CreateInBoundsGEP(Value, Offset);
+ // Okay, one of the vbases must have a vfptr, or else this isn't
+ // actually a polymorphic class.
+ const CXXRecordDecl *PolymorphicBase = nullptr;
+ for (auto &Base : SrcDecl->vbases()) {
+ const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
+ if (Context.getASTRecordLayout(BaseDecl).hasExtendableVFPtr()) {
+ PolymorphicBase = BaseDecl;
+ break;
+ }
+ }
+ assert(PolymorphicBase && "polymorphic class has no apparent vfptr?");
+
+ llvm::Value *Offset =
+ GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase);
+ llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP(Value.getPointer(), Offset);
Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty);
- return std::make_pair(Value, Offset);
+ CharUnits VBaseAlign =
+ CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase);
+ return std::make_pair(Address(Ptr, VBaseAlign), Offset);
}
bool MicrosoftCXXABI::shouldTypeidBeNullChecked(bool IsDeref,
@@ -934,12 +974,12 @@ void MicrosoftCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF,
QualType SrcRecordTy,
- llvm::Value *ThisPtr,
+ Address ThisPtr,
llvm::Type *StdTypeInfoPtrTy) {
llvm::Value *Offset;
std::tie(ThisPtr, Offset) = performBaseAdjustment(CGF, ThisPtr, SrcRecordTy);
- return CGF.Builder.CreateBitCast(
- emitRTtypeidCall(CGF, ThisPtr).getInstruction(), StdTypeInfoPtrTy);
+ auto Typeid = emitRTtypeidCall(CGF, ThisPtr.getPointer()).getInstruction();
+ return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy);
}
bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
@@ -950,7 +990,7 @@ bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
}
llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall(
- CodeGenFunction &CGF, llvm::Value *Value, QualType SrcRecordTy,
+ CodeGenFunction &CGF, Address This, QualType SrcRecordTy,
QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
llvm::Type *DestLTy = CGF.ConvertType(DestTy);
@@ -960,7 +1000,8 @@ llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall(
CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
llvm::Value *Offset;
- std::tie(Value, Offset) = performBaseAdjustment(CGF, Value, SrcRecordTy);
+ std::tie(This, Offset) = performBaseAdjustment(CGF, This, SrcRecordTy);
+ llvm::Value *ThisPtr = This.getPointer();
// PVOID __RTDynamicCast(
// PVOID inptr,
@@ -974,14 +1015,14 @@ llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall(
llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),
"__RTDynamicCast");
llvm::Value *Args[] = {
- Value, Offset, SrcRTTI, DestRTTI,
+ ThisPtr, Offset, SrcRTTI, DestRTTI,
llvm::ConstantInt::get(CGF.Int32Ty, DestTy->isReferenceType())};
- Value = CGF.EmitRuntimeCallOrInvoke(Function, Args).getInstruction();
- return CGF.Builder.CreateBitCast(Value, DestLTy);
+ ThisPtr = CGF.EmitRuntimeCallOrInvoke(Function, Args).getInstruction();
+ return CGF.Builder.CreateBitCast(ThisPtr, DestLTy);
}
llvm::Value *
-MicrosoftCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value *Value,
+MicrosoftCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy,
QualType DestTy) {
llvm::Value *Offset;
@@ -993,7 +1034,7 @@ MicrosoftCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value *Value,
llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),
"__RTCastToVoid");
- llvm::Value *Args[] = {Value};
+ llvm::Value *Args[] = {Value.getPointer()};
return CGF.EmitRuntimeCall(Function, Args);
}
@@ -1002,7 +1043,7 @@ bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
}
llvm::Value *MicrosoftCXXABI::GetVirtualBaseClassOffset(
- CodeGenFunction &CGF, llvm::Value *This, const CXXRecordDecl *ClassDecl,
+ CodeGenFunction &CGF, Address This, const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl) {
const ASTContext &Context = getContext();
int64_t VBPtrChars =
@@ -1040,15 +1081,16 @@ bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
if (!RD)
return false;
+ CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
if (FI.isInstanceMethod()) {
// If it's an instance method, aggregates are always returned indirectly via
// the second parameter.
- FI.getReturnInfo() = ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod());
return true;
} else if (!RD->isPOD()) {
// If it's a free function, non-POD types are returned indirectly.
- FI.getReturnInfo() = ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
return true;
}
@@ -1100,8 +1142,7 @@ void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
const VBOffsets &VBaseMap = Layout.getVBaseOffsetsMap();
CGBuilderTy &Builder = CGF.Builder;
- unsigned AS =
- cast<llvm::PointerType>(getThisValue(CGF)->getType())->getAddressSpace();
+ unsigned AS = getThisAddress(CGF).getAddressSpace();
llvm::Value *Int8This = nullptr; // Initialize lazily.
for (VBOffsets::const_iterator I = VBaseMap.begin(), E = VBaseMap.end();
@@ -1110,7 +1151,7 @@ void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
continue;
llvm::Value *VBaseOffset =
- GetVirtualBaseClassOffset(CGF, getThisValue(CGF), RD, I->first);
+ GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, I->first);
// FIXME: it doesn't look right that we SExt in GetVirtualBaseClassOffset()
// just to Trunc back immediately.
VBaseOffset = Builder.CreateTruncOrBitCast(VBaseOffset, CGF.Int32Ty);
@@ -1131,7 +1172,8 @@ void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
VtorDispPtr = Builder.CreateBitCast(
VtorDispPtr, CGF.Int32Ty->getPointerTo(AS), "vtordisp.ptr");
- Builder.CreateStore(VtorDispValue, VtorDispPtr);
+ Builder.CreateAlignedStore(VtorDispValue, VtorDispPtr,
+ CharUnits::fromQuantity(4));
}
}
@@ -1162,8 +1204,8 @@ void MicrosoftCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
const CXXRecordDecl *RD) {
- llvm::Value *ThisInt8Ptr =
- CGF.Builder.CreateBitCast(getThisValue(CGF), CGM.Int8PtrTy, "this.int8");
+ Address This = getThisAddress(CGF);
+ This = CGF.Builder.CreateElementBitCast(This, CGM.Int8Ty, "this.int8");
const ASTContext &Context = getContext();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
@@ -1177,11 +1219,10 @@ void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
Offs += SubobjectLayout.getVBPtrOffset();
if (VBT->getVBaseWithVPtr())
Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr());
- llvm::Value *VBPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(ThisInt8Ptr, Offs.getQuantity());
+ Address VBPtr = CGF.Builder.CreateConstInBoundsByteGEP(This, Offs);
llvm::Value *GVPtr =
CGF.Builder.CreateConstInBoundsGEP2_32(GV->getValueType(), GV, 0, 0);
- VBPtr = CGF.Builder.CreateBitCast(VBPtr, GVPtr->getType()->getPointerTo(0),
+ VBPtr = CGF.Builder.CreateElementBitCast(VBPtr, GVPtr->getType(),
"vbptr." + VBT->ReusingBase->getName());
CGF.Builder.CreateStore(GVPtr, VBPtr);
}
@@ -1255,8 +1296,9 @@ MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) {
return Adjustment;
}
-llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
- CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This, bool VirtualCall) {
+Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
+ CodeGenFunction &CGF, GlobalDecl GD, Address This,
+ bool VirtualCall) {
if (!VirtualCall) {
// If the call of a virtual function is not virtual, we just have to
// compensate for the adjustment the virtual function does in its prologue.
@@ -1264,11 +1306,9 @@ llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
if (Adjustment.isZero())
return This;
- unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace();
- llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS);
- This = CGF.Builder.CreateBitCast(This, charPtrTy);
+ This = CGF.Builder.CreateElementBitCast(This, CGF.Int8Ty);
assert(Adjustment.isPositive());
- return CGF.Builder.CreateConstGEP1_32(This, Adjustment.getQuantity());
+ return CGF.Builder.CreateConstByteGEP(This, Adjustment);
}
GD = GD.getCanonicalDecl();
@@ -1288,8 +1328,6 @@ llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
MicrosoftVTableContext::MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
- unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace();
- llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS);
CharUnits StaticOffset = ML.VFPtrOffset;
// Base destructors expect 'this' to point to the beginning of the base
@@ -1298,27 +1336,34 @@ llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
StaticOffset = CharUnits::Zero();
+ Address Result = This;
if (ML.VBase) {
- This = CGF.Builder.CreateBitCast(This, charPtrTy);
+ Result = CGF.Builder.CreateElementBitCast(Result, CGF.Int8Ty);
+
+ const CXXRecordDecl *Derived = MD->getParent();
+ const CXXRecordDecl *VBase = ML.VBase;
llvm::Value *VBaseOffset =
- GetVirtualBaseClassOffset(CGF, This, MD->getParent(), ML.VBase);
- This = CGF.Builder.CreateInBoundsGEP(This, VBaseOffset);
+ GetVirtualBaseClassOffset(CGF, Result, Derived, VBase);
+ llvm::Value *VBasePtr =
+ CGF.Builder.CreateInBoundsGEP(Result.getPointer(), VBaseOffset);
+ CharUnits VBaseAlign =
+ CGF.CGM.getVBaseAlignment(Result.getAlignment(), Derived, VBase);
+ Result = Address(VBasePtr, VBaseAlign);
}
if (!StaticOffset.isZero()) {
assert(StaticOffset.isPositive());
- This = CGF.Builder.CreateBitCast(This, charPtrTy);
+ Result = CGF.Builder.CreateElementBitCast(Result, CGF.Int8Ty);
if (ML.VBase) {
// Non-virtual adjustment might result in a pointer outside the allocated
// object, e.g. if the final overrider class is laid out after the virtual
// base that declares a method in the most derived class.
// FIXME: Update the code that emits this adjustment in thunks prologues.
- This = CGF.Builder.CreateConstGEP1_32(This, StaticOffset.getQuantity());
+ Result = CGF.Builder.CreateConstByteGEP(Result, StaticOffset);
} else {
- This = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, This,
- StaticOffset.getQuantity());
+ Result = CGF.Builder.CreateConstInBoundsByteGEP(Result, StaticOffset);
}
}
- return This;
+ return Result;
}
void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
@@ -1439,7 +1484,7 @@ unsigned MicrosoftCXXABI::addImplicitConstructorArgs(
void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *DD,
CXXDtorType Type, bool ForVirtualBase,
- bool Delegating, llvm::Value *This) {
+ bool Delegating, Address This) {
llvm::Value *Callee = CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type));
if (DD->isVirtual()) {
@@ -1449,7 +1494,7 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
This, false);
}
- CGF.EmitCXXStructorCall(DD, Callee, ReturnValueSlot(), This,
+ CGF.EmitCXXStructorCall(DD, Callee, ReturnValueSlot(), This.getPointer(),
/*ImplicitParam=*/nullptr,
/*ImplicitParamTy=*/QualType(), nullptr,
getFromDtorType(Type));
@@ -1478,15 +1523,14 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
if (Info->PathToBaseWithVPtr.empty()) {
if (!CGM.IsCFIBlacklistedRecord(RD))
- BitsetsMD->addOperand(
- CGM.CreateVTableBitSetEntry(VTable, AddressPoint, RD));
+ CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD);
return;
}
// Add a bitset entry for the least derived base belonging to this vftable.
if (!CGM.IsCFIBlacklistedRecord(Info->PathToBaseWithVPtr.back()))
- BitsetsMD->addOperand(CGM.CreateVTableBitSetEntry(
- VTable, AddressPoint, Info->PathToBaseWithVPtr.back()));
+ CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint,
+ Info->PathToBaseWithVPtr.back());
// Add a bitset entry for each derived class that is laid out at the same
// offset as the least derived base.
@@ -1505,14 +1549,12 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info,
if (!Offset.isZero())
return;
if (!CGM.IsCFIBlacklistedRecord(DerivedRD))
- BitsetsMD->addOperand(
- CGM.CreateVTableBitSetEntry(VTable, AddressPoint, DerivedRD));
+ CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, DerivedRD);
}
// Finally do the same for the most derived class.
if (Info->FullOffsetInMDC.isZero() && !CGM.IsCFIBlacklistedRecord(RD))
- BitsetsMD->addOperand(
- CGM.CreateVTableBitSetEntry(VTable, AddressPoint, RD));
+ CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD);
}
void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
@@ -1542,14 +1584,15 @@ void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
}
}
+bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField(
+ CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {
+ return Vptr.NearestVBase != nullptr;
+}
+
llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
- const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
- NeedsVirtualOffset = (NearestVBase != nullptr);
-
- (void)getAddrOfVTable(VTableClass, Base.getBaseOffset());
- VFTableIdTy ID(VTableClass, Base.getBaseOffset());
- llvm::GlobalValue *VTableAddressPoint = VFTablesMap[ID];
+ const CXXRecordDecl *NearestVBase) {
+ llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base, VTableClass);
if (!VTableAddressPoint) {
assert(Base.getBase()->getNumVBases() &&
!getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());
@@ -1564,11 +1607,17 @@ static void mangleVFTableName(MicrosoftMangleContext &MangleContext,
MangleContext.mangleCXXVFTable(RD, VFPtr->MangledPath, Out);
}
-llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(
- BaseSubobject Base, const CXXRecordDecl *VTableClass) {
+llvm::Constant *
+MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base,
+ const CXXRecordDecl *VTableClass) {
(void)getAddrOfVTable(VTableClass, Base.getBaseOffset());
VFTableIdTy ID(VTableClass, Base.getBaseOffset());
- llvm::GlobalValue *VFTable = VFTablesMap[ID];
+ return VFTablesMap[ID];
+}
+
+llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(
+ BaseSubobject Base, const CXXRecordDecl *VTableClass) {
+ llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass);
assert(VFTable && "Couldn't find a vftable for the given base?");
return VFTable;
}
@@ -1578,6 +1627,7 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
// getAddrOfVTable may return 0 if asked to get an address of a vtable which
// shouldn't be used in the given record type. We want to cache this result in
// VFTablesMap, thus a simple zero check is not sufficient.
+
VFTableIdTy ID(RD, VPtrOffset);
VTablesMapTy::iterator I;
bool Inserted;
@@ -1631,10 +1681,11 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
if (llvm::GlobalValue *VFTable =
CGM.getModule().getNamedGlobal(VFTableName)) {
VFTablesMap[ID] = VFTable;
- return VTableAliasIsRequred
- ? cast<llvm::GlobalVariable>(
- cast<llvm::GlobalAlias>(VFTable)->getBaseObject())
- : cast<llvm::GlobalVariable>(VFTable);
+ VTable = VTableAliasIsRequred
+ ? cast<llvm::GlobalVariable>(
+ cast<llvm::GlobalAlias>(VFTable)->getBaseObject())
+ : cast<llvm::GlobalVariable>(VFTable);
+ return VTable;
}
uint64_t NumVTableSlots =
@@ -1678,9 +1729,10 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
if (C)
C->setSelectionKind(llvm::Comdat::Largest);
}
- VFTable = llvm::GlobalAlias::create(
- cast<llvm::PointerType>(VTableGEP->getType()), VFTableLinkage,
- VFTableName.str(), VTableGEP, &CGM.getModule());
+ VFTable = llvm::GlobalAlias::create(CGM.Int8PtrTy,
+ /*AddressSpace=*/0, VFTableLinkage,
+ VFTableName.str(), VTableGEP,
+ &CGM.getModule());
VFTable->setUnnamedAddr(true);
} else {
// We don't need a GlobalAlias to be a symbol for the VTable if we won't
@@ -1746,16 +1798,18 @@ getClassAtVTableLocation(ASTContext &Ctx, GlobalDecl GD,
llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
GlobalDecl GD,
- llvm::Value *This,
+ Address This,
llvm::Type *Ty,
SourceLocation Loc) {
GD = GD.getCanonicalDecl();
CGBuilderTy &Builder = CGF.Builder;
Ty = Ty->getPointerTo()->getPointerTo();
- llvm::Value *VPtr =
+ Address VPtr =
adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true);
- llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty);
+
+ auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
+ llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty, MethodDecl->getParent());
MicrosoftVTableContext::MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
@@ -1765,12 +1819,12 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
llvm::Value *VFuncPtr =
Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
- return Builder.CreateLoad(VFuncPtr);
+ return Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
}
llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType,
- llvm::Value *This, const CXXMemberCallExpr *CE) {
+ Address This, const CXXMemberCallExpr *CE) {
assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
@@ -1789,7 +1843,8 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
DtorType == Dtor_Deleting);
This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true);
- RValue RV = CGF.EmitCXXStructorCall(Dtor, Callee, ReturnValueSlot(), This,
+ RValue RV = CGF.EmitCXXStructorCall(Dtor, Callee, ReturnValueSlot(),
+ This.getPointer(),
ImplicitParam, Context.IntTy, CE,
StructorType::Deleting);
return RV.getScalarVal();
@@ -1832,7 +1887,6 @@ llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
SmallString<256> ThunkName;
llvm::raw_svector_ostream Out(ThunkName);
getMangleContext().mangleVirtualMemPtrThunk(MD, Out);
- Out.flush();
// If the thunk has been generated previously, just return it.
if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))
@@ -1882,10 +1936,12 @@ llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
// Load the vfptr and then callee from the vftable. The callee should have
// adjusted 'this' so that the vfptr is at offset zero.
llvm::Value *VTable = CGF.GetVTablePtr(
- getThisValue(CGF), ThunkTy->getPointerTo()->getPointerTo());
+ getThisAddress(CGF), ThunkTy->getPointerTo()->getPointerTo(), MD->getParent());
+
llvm::Value *VFuncPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
- llvm::Value *Callee = CGF.Builder.CreateLoad(VFuncPtr);
+ llvm::Value *Callee =
+ CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
CGF.EmitMustTailThunk(MD, getThisValue(CGF), Callee);
@@ -1908,7 +1964,6 @@ MicrosoftCXXABI::getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD,
SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName);
getMangleContext().mangleCXXVBTable(RD, VBT.MangledPath, Out);
- Out.flush();
StringRef Name = OutName.str();
llvm::ArrayType *VBTableType =
@@ -1978,22 +2033,30 @@ void MicrosoftCXXABI::emitVBTableDefinition(const VPtrInfo &VBT,
}
llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF,
- llvm::Value *This,
+ Address This,
const ThisAdjustment &TA) {
if (TA.isEmpty())
- return This;
+ return This.getPointer();
- llvm::Value *V = CGF.Builder.CreateBitCast(This, CGF.Int8PtrTy);
+ This = CGF.Builder.CreateElementBitCast(This, CGF.Int8Ty);
- if (!TA.Virtual.isEmpty()) {
+ llvm::Value *V;
+ if (TA.Virtual.isEmpty()) {
+ V = This.getPointer();
+ } else {
assert(TA.Virtual.Microsoft.VtordispOffset < 0);
// Adjust the this argument based on the vtordisp value.
- llvm::Value *VtorDispPtr =
- CGF.Builder.CreateConstGEP1_32(V, TA.Virtual.Microsoft.VtordispOffset);
- VtorDispPtr =
- CGF.Builder.CreateBitCast(VtorDispPtr, CGF.Int32Ty->getPointerTo());
+ Address VtorDispPtr =
+ CGF.Builder.CreateConstInBoundsByteGEP(This,
+ CharUnits::fromQuantity(TA.Virtual.Microsoft.VtordispOffset));
+ VtorDispPtr = CGF.Builder.CreateElementBitCast(VtorDispPtr, CGF.Int32Ty);
llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp");
- V = CGF.Builder.CreateGEP(V, CGF.Builder.CreateNeg(VtorDisp));
+ V = CGF.Builder.CreateGEP(This.getPointer(),
+ CGF.Builder.CreateNeg(VtorDisp));
+
+ // Unfortunately, having applied the vtordisp means that we no
+ // longer really have a known alignment for the vbptr step.
+ // We'll assume the vbptr is pointer-aligned.
if (TA.Virtual.Microsoft.VBPtrOffset) {
// If the final overrider is defined in a virtual base other than the one
@@ -2003,7 +2066,8 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF,
assert(TA.Virtual.Microsoft.VBOffsetOffset >= 0);
llvm::Value *VBPtr;
llvm::Value *VBaseOffset =
- GetVBaseOffsetFromVBPtr(CGF, V, -TA.Virtual.Microsoft.VBPtrOffset,
+ GetVBaseOffsetFromVBPtr(CGF, Address(V, CGF.getPointerAlign()),
+ -TA.Virtual.Microsoft.VBPtrOffset,
TA.Virtual.Microsoft.VBOffsetOffset, &VBPtr);
V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset);
}
@@ -2021,20 +2085,21 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF,
}
llvm::Value *
-MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
+MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
const ReturnAdjustment &RA) {
if (RA.isEmpty())
- return Ret;
+ return Ret.getPointer();
- llvm::Value *V = CGF.Builder.CreateBitCast(Ret, CGF.Int8PtrTy);
+ auto OrigTy = Ret.getType();
+ Ret = CGF.Builder.CreateElementBitCast(Ret, CGF.Int8Ty);
+ llvm::Value *V = Ret.getPointer();
if (RA.Virtual.Microsoft.VBIndex) {
assert(RA.Virtual.Microsoft.VBIndex > 0);
- const ASTContext &Context = getContext();
- int32_t IntSize = Context.getTypeSizeInChars(Context.IntTy).getQuantity();
+ int32_t IntSize = CGF.getIntSize().getQuantity();
llvm::Value *VBPtr;
llvm::Value *VBaseOffset =
- GetVBaseOffsetFromVBPtr(CGF, V, RA.Virtual.Microsoft.VBPtrOffset,
+ GetVBaseOffsetFromVBPtr(CGF, Ret, RA.Virtual.Microsoft.VBPtrOffset,
IntSize * RA.Virtual.Microsoft.VBIndex, &VBPtr);
V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset);
}
@@ -2043,7 +2108,7 @@ MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, llvm::Value *Ret,
V = CGF.Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, V, RA.NonVirtual);
// Cast back to the original type.
- return CGF.Builder.CreateBitCast(V, Ret->getType());
+ return CGF.Builder.CreateBitCast(V, OrigTy);
}
bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
@@ -2068,37 +2133,34 @@ CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) {
}
llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
- llvm::Value *allocPtr,
+ Address allocPtr,
CharUnits cookieSize) {
- unsigned AS = allocPtr->getType()->getPointerAddressSpace();
- llvm::Value *numElementsPtr =
- CGF.Builder.CreateBitCast(allocPtr, CGF.SizeTy->getPointerTo(AS));
+ Address numElementsPtr =
+ CGF.Builder.CreateElementBitCast(allocPtr, CGF.SizeTy);
return CGF.Builder.CreateLoad(numElementsPtr);
}
-llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
- llvm::Value *newPtr,
- llvm::Value *numElements,
- const CXXNewExpr *expr,
- QualType elementType) {
+Address MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
+ Address newPtr,
+ llvm::Value *numElements,
+ const CXXNewExpr *expr,
+ QualType elementType) {
assert(requiresArrayCookie(expr));
// The size of the cookie.
CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
// Compute an offset to the cookie.
- llvm::Value *cookiePtr = newPtr;
+ Address cookiePtr = newPtr;
// Write the number of elements into the appropriate slot.
- unsigned AS = newPtr->getType()->getPointerAddressSpace();
- llvm::Value *numElementsPtr
- = CGF.Builder.CreateBitCast(cookiePtr, CGF.SizeTy->getPointerTo(AS));
+ Address numElementsPtr
+ = CGF.Builder.CreateElementBitCast(cookiePtr, CGF.SizeTy);
CGF.Builder.CreateStore(numElements, numElementsPtr);
// Finally, compute a pointer to the actual data buffer by skipping
// over the cookie completely.
- return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr,
- cookieSize.getQuantity());
+ return CGF.Builder.CreateConstInBoundsByteGEP(newPtr, cookieSize);
}
static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD,
@@ -2130,11 +2192,9 @@ void MicrosoftCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
}
void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
- CodeGenModule &CGM,
- ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>>
- CXXThreadLocals,
+ CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
ArrayRef<llvm::Function *> CXXThreadLocalInits,
- ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) {
+ ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
// This will create a GV in the .CRT$XDU section. It will point to our
// initialization function. The CRT will call all of these function
// pointers at start-up time and, eventually, at thread-creation time.
@@ -2152,7 +2212,8 @@ void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
std::vector<llvm::Function *> NonComdatInits;
for (size_t I = 0, E = CXXThreadLocalInitVars.size(); I != E; ++I) {
- llvm::GlobalVariable *GV = CXXThreadLocalInitVars[I];
+ llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>(
+ CGM.GetGlobalValue(CGM.getMangledName(CXXThreadLocalInitVars[I])));
llvm::Function *F = CXXThreadLocalInits[I];
// If the GV is already in a comdat group, then we have to join it.
@@ -2166,8 +2227,8 @@ void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
llvm::Function *InitFunc = CGM.CreateGlobalInitOrDestructFunction(
- FTy, "__tls_init", SourceLocation(),
- /*TLS=*/true);
+ FTy, "__tls_init", CGM.getTypes().arrangeNullaryFunction(),
+ SourceLocation(), /*TLS=*/true);
CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, NonComdatInits);
AddToXDU(InitFunc);
@@ -2181,17 +2242,18 @@ LValue MicrosoftCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
return LValue();
}
-static llvm::GlobalVariable *getInitThreadEpochPtr(CodeGenModule &CGM) {
+static ConstantAddress getInitThreadEpochPtr(CodeGenModule &CGM) {
StringRef VarName("_Init_thread_epoch");
+ CharUnits Align = CGM.getIntAlign();
if (auto *GV = CGM.getModule().getNamedGlobal(VarName))
- return GV;
+ return ConstantAddress(GV, Align);
auto *GV = new llvm::GlobalVariable(
CGM.getModule(), CGM.IntTy,
/*Constant=*/false, llvm::GlobalVariable::ExternalLinkage,
/*Initializer=*/nullptr, VarName,
/*InsertBefore=*/nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel);
- GV->setAlignment(CGM.getTarget().getIntAlign() / 8);
- return GV;
+ GV->setAlignment(Align.getQuantity());
+ return ConstantAddress(GV, Align);
}
static llvm::Constant *getInitThreadHeaderFn(CodeGenModule &CGM) {
@@ -2228,10 +2290,10 @@ static llvm::Constant *getInitThreadAbortFn(CodeGenModule &CGM) {
}
namespace {
-struct ResetGuardBit : EHScopeStack::Cleanup {
- llvm::GlobalVariable *Guard;
+struct ResetGuardBit final : EHScopeStack::Cleanup {
+ Address Guard;
unsigned GuardNum;
- ResetGuardBit(llvm::GlobalVariable *Guard, unsigned GuardNum)
+ ResetGuardBit(Address Guard, unsigned GuardNum)
: Guard(Guard), GuardNum(GuardNum) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
@@ -2245,9 +2307,9 @@ struct ResetGuardBit : EHScopeStack::Cleanup {
}
};
-struct CallInitThreadAbort : EHScopeStack::Cleanup {
- llvm::GlobalVariable *Guard;
- CallInitThreadAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
+struct CallInitThreadAbort final : EHScopeStack::Cleanup {
+ llvm::Value *Guard;
+ CallInitThreadAbort(Address Guard) : Guard(Guard.getPointer()) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
// Calling _Init_thread_abort will reset the guard's state.
@@ -2280,6 +2342,7 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
CGBuilderTy &Builder = CGF.Builder;
llvm::IntegerType *GuardTy = CGF.Int32Ty;
llvm::ConstantInt *Zero = llvm::ConstantInt::get(GuardTy, 0);
+ CharUnits GuardAlign = CharUnits::fromQuantity(4);
// Get the guard variable for this function if we have one already.
GuardInfo *GI = nullptr;
@@ -2320,7 +2383,6 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
Out);
else
getMangleContext().mangleStaticGuardVariable(&D, Out);
- Out.flush();
}
// Create the guard variable with a zero-initializer. Just absorb linkage,
@@ -2330,6 +2392,7 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
GV->getLinkage(), Zero, GuardName.str());
GuardVar->setVisibility(GV->getVisibility());
GuardVar->setDLLStorageClass(GV->getDLLStorageClass());
+ GuardVar->setAlignment(GuardAlign.getQuantity());
if (GuardVar->isWeakForLinker())
GuardVar->setComdat(
CGM.getModule().getOrInsertComdat(GuardVar->getName()));
@@ -2339,6 +2402,8 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
GI->Guard = GuardVar;
}
+ ConstantAddress GuardAddr(GuardVar, GuardAlign);
+
assert(GuardVar->getLinkage() == GV->getLinkage() &&
"static local from the same function had different linkage");
@@ -2351,7 +2416,7 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
// Test our bit from the guard variable.
llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1U << GuardNum);
- llvm::LoadInst *LI = Builder.CreateLoad(GuardVar);
+ llvm::LoadInst *LI = Builder.CreateLoad(GuardAddr);
llvm::Value *IsInitialized =
Builder.CreateICmpNE(Builder.CreateAnd(LI, Bit), Zero);
llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
@@ -2361,8 +2426,8 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
// Set our bit in the guard variable and emit the initializer and add a global
// destructor if appropriate.
CGF.EmitBlock(InitBlock);
- Builder.CreateStore(Builder.CreateOr(LI, Bit), GuardVar);
- CGF.EHStack.pushCleanup<ResetGuardBit>(EHCleanup, GuardVar, GuardNum);
+ Builder.CreateStore(Builder.CreateOr(LI, Bit), GuardAddr);
+ CGF.EHStack.pushCleanup<ResetGuardBit>(EHCleanup, GuardAddr, GuardNum);
CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
CGF.PopCleanupBlock();
Builder.CreateBr(EndBlock);
@@ -2382,11 +2447,8 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
// The algorithm is almost identical to what can be found in the appendix
// found in N2325.
- unsigned IntAlign = CGM.getTarget().getIntAlign() / 8;
-
// This BasicBLock determines whether or not we have any work to do.
- llvm::LoadInst *FirstGuardLoad =
- Builder.CreateAlignedLoad(GuardVar, IntAlign);
+ llvm::LoadInst *FirstGuardLoad = Builder.CreateLoad(GuardAddr);
FirstGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
llvm::LoadInst *InitThreadEpoch =
Builder.CreateLoad(getInitThreadEpochPtr(CGM));
@@ -2399,9 +2461,9 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
// This BasicBlock attempts to determine whether or not this thread is
// responsible for doing the initialization.
CGF.EmitBlock(AttemptInitBlock);
- CGF.EmitNounwindRuntimeCall(getInitThreadHeaderFn(CGM), GuardVar);
- llvm::LoadInst *SecondGuardLoad =
- Builder.CreateAlignedLoad(GuardVar, IntAlign);
+ CGF.EmitNounwindRuntimeCall(getInitThreadHeaderFn(CGM),
+ GuardAddr.getPointer());
+ llvm::LoadInst *SecondGuardLoad = Builder.CreateLoad(GuardAddr);
SecondGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
llvm::Value *ShouldDoInit =
Builder.CreateICmpEQ(SecondGuardLoad, getAllOnesInt());
@@ -2410,10 +2472,11 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
// Ok, we ended up getting selected as the initializing thread.
CGF.EmitBlock(InitBlock);
- CGF.EHStack.pushCleanup<CallInitThreadAbort>(EHCleanup, GuardVar);
+ CGF.EHStack.pushCleanup<CallInitThreadAbort>(EHCleanup, GuardAddr);
CGF.EmitCXXGlobalVarDeclInit(D, GV, PerformInit);
CGF.PopCleanupBlock();
- CGF.EmitNounwindRuntimeCall(getInitThreadFooterFn(CGM), GuardVar);
+ CGF.EmitNounwindRuntimeCall(getInitThreadFooterFn(CGM),
+ GuardAddr.getPointer());
Builder.CreateBr(EndBlock);
CGF.EmitBlock(EndBlock);
@@ -2768,19 +2831,28 @@ bool MicrosoftCXXABI::MemberPointerConstantIsNull(const MemberPointerType *MPT,
llvm::Value *
MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
- llvm::Value *This,
+ Address This,
llvm::Value *VBPtrOffset,
llvm::Value *VBTableOffset,
llvm::Value **VBPtrOut) {
CGBuilderTy &Builder = CGF.Builder;
// Load the vbtable pointer from the vbptr in the instance.
- This = Builder.CreateBitCast(This, CGM.Int8PtrTy);
+ This = Builder.CreateElementBitCast(This, CGM.Int8Ty);
llvm::Value *VBPtr =
- Builder.CreateInBoundsGEP(This, VBPtrOffset, "vbptr");
+ Builder.CreateInBoundsGEP(This.getPointer(), VBPtrOffset, "vbptr");
if (VBPtrOut) *VBPtrOut = VBPtr;
VBPtr = Builder.CreateBitCast(VBPtr,
- CGM.Int32Ty->getPointerTo(0)->getPointerTo(0));
- llvm::Value *VBTable = Builder.CreateLoad(VBPtr, "vbtable");
+ CGM.Int32Ty->getPointerTo(0)->getPointerTo(This.getAddressSpace()));
+
+ CharUnits VBPtrAlign;
+ if (auto CI = dyn_cast<llvm::ConstantInt>(VBPtrOffset)) {
+ VBPtrAlign = This.getAlignment().alignmentAtOffset(
+ CharUnits::fromQuantity(CI->getSExtValue()));
+ } else {
+ VBPtrAlign = CGF.getPointerAlign();
+ }
+
+ llvm::Value *VBTable = Builder.CreateAlignedLoad(VBPtr, VBPtrAlign, "vbtable");
// Translate from byte offset to table index. It improves analyzability.
llvm::Value *VBTableIndex = Builder.CreateAShr(
@@ -2790,16 +2862,17 @@ MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
// Load an i32 offset from the vb-table.
llvm::Value *VBaseOffs = Builder.CreateInBoundsGEP(VBTable, VBTableIndex);
VBaseOffs = Builder.CreateBitCast(VBaseOffs, CGM.Int32Ty->getPointerTo(0));
- return Builder.CreateLoad(VBaseOffs, "vbase_offs");
+ return Builder.CreateAlignedLoad(VBaseOffs, CharUnits::fromQuantity(4),
+ "vbase_offs");
}
// Returns an adjusted base cast to i8*, since we do more address arithmetic on
// it.
llvm::Value *MicrosoftCXXABI::AdjustVirtualBase(
CodeGenFunction &CGF, const Expr *E, const CXXRecordDecl *RD,
- llvm::Value *Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) {
+ Address Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) {
CGBuilderTy &Builder = CGF.Builder;
- Base = Builder.CreateBitCast(Base, CGM.Int8PtrTy);
+ Base = Builder.CreateElementBitCast(Base, CGM.Int8Ty);
llvm::BasicBlock *OriginalBB = nullptr;
llvm::BasicBlock *SkipAdjustBB = nullptr;
llvm::BasicBlock *VBaseAdjustBB = nullptr;
@@ -2844,7 +2917,7 @@ llvm::Value *MicrosoftCXXABI::AdjustVirtualBase(
Builder.CreateBr(SkipAdjustBB);
CGF.EmitBlock(SkipAdjustBB);
llvm::PHINode *Phi = Builder.CreatePHI(CGM.Int8PtrTy, 2, "memptr.base");
- Phi->addIncoming(Base, OriginalBB);
+ Phi->addIncoming(Base.getPointer(), OriginalBB);
Phi->addIncoming(AdjustedBase, VBaseAdjustBB);
return Phi;
}
@@ -2852,10 +2925,10 @@ llvm::Value *MicrosoftCXXABI::AdjustVirtualBase(
}
llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress(
- CodeGenFunction &CGF, const Expr *E, llvm::Value *Base, llvm::Value *MemPtr,
+ CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr,
const MemberPointerType *MPT) {
assert(MPT->isMemberDataPointer());
- unsigned AS = Base->getType()->getPointerAddressSpace();
+ unsigned AS = Base.getAddressSpace();
llvm::Type *PType =
CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS);
CGBuilderTy &Builder = CGF.Builder;
@@ -2877,17 +2950,19 @@ llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress(
VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
}
+ llvm::Value *Addr;
if (VirtualBaseAdjustmentOffset) {
- Base = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset,
+ Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset,
VBPtrOffset);
+ } else {
+ Addr = Base.getPointer();
}
// Cast to char*.
- Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS));
+ Addr = Builder.CreateBitCast(Addr, CGF.Int8Ty->getPointerTo(AS));
// Apply the offset, which we assume is non-null.
- llvm::Value *Addr =
- Builder.CreateInBoundsGEP(Base, FieldOffset, "memptr.offset");
+ Addr = Builder.CreateInBoundsGEP(Addr, FieldOffset, "memptr.offset");
// Cast the address to the appropriate pointer type, adopting the address
// space of the base pointer.
@@ -3050,7 +3125,8 @@ llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion(
} else {
llvm::Value *Idxs[] = {getZeroInt(), VBIndex};
VirtualBaseAdjustmentOffset =
- Builder.CreateLoad(Builder.CreateInBoundsGEP(VDispMap, Idxs));
+ Builder.CreateAlignedLoad(Builder.CreateInBoundsGEP(VDispMap, Idxs),
+ CharUnits::fromQuantity(4));
}
DstVBIndexEqZero =
@@ -3131,7 +3207,7 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
if (CK == CK_ReinterpretMemberPointer)
return Src;
- CGBuilderTy Builder(CGM.getLLVMContext());
+ CGBuilderTy Builder(CGM, CGM.getLLVMContext());
auto *Dst = cast<llvm::Constant>(EmitNonNullMemberPointerConversion(
SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder));
@@ -3139,15 +3215,15 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
}
llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
- CodeGenFunction &CGF, const Expr *E, llvm::Value *&This,
- llvm::Value *MemPtr, const MemberPointerType *MPT) {
+ CodeGenFunction &CGF, const Expr *E, Address This,
+ llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
assert(MPT->isMemberFunctionPointer());
const FunctionProtoType *FPT =
MPT->getPointeeType()->castAs<FunctionProtoType>();
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
- llvm::FunctionType *FTy =
- CGM.getTypes().GetFunctionType(
- CGM.getTypes().arrangeCXXMethodType(RD, FPT));
+ llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
+ CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr));
CGBuilderTy &Builder = CGF.Builder;
MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
@@ -3171,15 +3247,18 @@ llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
}
if (VirtualBaseAdjustmentOffset) {
- This = AdjustVirtualBase(CGF, E, RD, This, VirtualBaseAdjustmentOffset,
- VBPtrOffset);
+ ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This,
+ VirtualBaseAdjustmentOffset, VBPtrOffset);
+ } else {
+ ThisPtrForCall = This.getPointer();
}
if (NonVirtualBaseAdjustment) {
// Apply the adjustment and cast back to the original struct type.
- llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy());
+ llvm::Value *Ptr = Builder.CreateBitCast(ThisPtrForCall, CGF.Int8PtrTy);
Ptr = Builder.CreateInBoundsGEP(Ptr, NonVirtualBaseAdjustment);
- This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted");
+ ThisPtrForCall = Builder.CreateBitCast(Ptr, ThisPtrForCall->getType(),
+ "this.adjusted");
}
return Builder.CreateBitCast(FunctionPointer, FTy->getPointerTo());
@@ -3404,7 +3483,7 @@ llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
auto Type = ABI.getClassHierarchyDescriptorType();
auto CHD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
/*Initializer=*/nullptr,
- StringRef(MangledName));
+ MangledName);
if (CHD->isWeakForLinker())
CHD->setComdat(CGM.getModule().getOrInsertComdat(CHD->getName()));
@@ -3442,7 +3521,7 @@ MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
auto *BCA =
new llvm::GlobalVariable(Module, ArrType,
/*Constant=*/true, Linkage,
- /*Initializer=*/nullptr, StringRef(MangledName));
+ /*Initializer=*/nullptr, MangledName);
if (BCA->isWeakForLinker())
BCA->setComdat(CGM.getModule().getOrInsertComdat(BCA->getName()));
@@ -3484,7 +3563,7 @@ MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) {
auto Type = ABI.getBaseClassDescriptorType();
auto BCD =
new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
- /*Initializer=*/nullptr, StringRef(MangledName));
+ /*Initializer=*/nullptr, MangledName);
if (BCD->isWeakForLinker())
BCD->setComdat(CGM.getModule().getOrInsertComdat(BCD->getName()));
@@ -3530,7 +3609,7 @@ MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) {
// Forward-declare the complete object locator.
llvm::StructType *Type = ABI.getCompleteObjectLocatorType();
auto COL = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
- /*Initializer=*/nullptr, StringRef(MangledName));
+ /*Initializer=*/nullptr, MangledName);
// Initialize the CompleteObjectLocator.
llvm::Constant *Fields[] = {
@@ -3582,7 +3661,7 @@ static QualType decomposeTypeForEH(ASTContext &Context, QualType T,
return T;
}
-llvm::Constant *
+CatchTypeInfo
MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType Type,
QualType CatchHandlerType) {
// TypeDescriptors for exceptions never have qualified pointer types,
@@ -3601,28 +3680,8 @@ MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType Type,
if (IsReference)
Flags |= 8;
- SmallString<256> MangledName;
- {
- llvm::raw_svector_ostream Out(MangledName);
- getMangleContext().mangleCXXCatchHandlerType(Type, Flags, Out);
- }
-
- if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
- return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
-
- llvm::Constant *Fields[] = {
- llvm::ConstantInt::get(CGM.IntTy, Flags), // Flags
- getAddrOfRTTIDescriptor(Type), // TypeDescriptor
- };
- llvm::StructType *CatchHandlerTypeType = getCatchHandlerTypeType();
- auto *Var = new llvm::GlobalVariable(
- CGM.getModule(), CatchHandlerTypeType, /*Constant=*/true,
- llvm::GlobalValue::PrivateLinkage,
- llvm::ConstantStruct::get(CatchHandlerTypeType, Fields),
- StringRef(MangledName));
- Var->setUnnamedAddr(true);
- Var->setSection("llvm.metadata");
- return Var;
+ return CatchTypeInfo{getAddrOfRTTIDescriptor(Type)->stripPointerCasts(),
+ Flags};
}
/// \brief Gets a TypeDescriptor. Returns a llvm::Constant * rather than a
@@ -3658,7 +3717,7 @@ llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) {
CGM.getModule(), TypeDescriptorType, /*Constant=*/false,
getLinkageForRTTI(Type),
llvm::ConstantStruct::get(TypeDescriptorType, Fields),
- StringRef(MangledName));
+ MangledName);
if (Var->isWeakForLinker())
Var->setComdat(CGM.getModule().getOrInsertComdat(Var->getName()));
return llvm::ConstantExpr::getBitCast(Var, CGM.Int8PtrTy);
@@ -3725,7 +3784,6 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
SmallString<256> ThunkName;
llvm::raw_svector_ostream Out(ThunkName);
getMangleContext().mangleCXXCtor(CD, CT, Out);
- Out.flush();
// If the thunk has been generated previously, just return it.
if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))
@@ -3803,9 +3861,7 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
CodeGenFunction::RunCleanupsScope Cleanups(CGF);
const auto *FPT = CD->getType()->castAs<FunctionProtoType>();
- ConstExprIterator ArgBegin(ArgVec.data()),
- ArgEnd(ArgVec.data() + ArgVec.size());
- CGF.EmitCallArgs(Args, FPT, ArgBegin, ArgEnd, CD, IsCopy ? 1 : 0);
+ CGF.EmitCallArgs(Args, FPT, llvm::makeArrayRef(ArgVec), CD, IsCopy ? 1 : 0);
// Insert any ABI-specific implicit constructor arguments.
unsigned ExtraArgs = addImplicitConstructorArgs(CGF, CD, Ctor_Complete,
@@ -3904,7 +3960,7 @@ llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T,
llvm::StructType *CTType = getCatchableTypeType();
auto *GV = new llvm::GlobalVariable(
CGM.getModule(), CTType, /*Constant=*/true, getLinkageForRTTI(T),
- llvm::ConstantStruct::get(CTType, Fields), StringRef(MangledName));
+ llvm::ConstantStruct::get(CTType, Fields), MangledName);
GV->setUnnamedAddr(true);
GV->setSection(".xdata");
if (GV->isWeakForLinker())
@@ -4022,7 +4078,7 @@ llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType T) {
}
CTA = new llvm::GlobalVariable(
CGM.getModule(), CTAType, /*Constant=*/true, getLinkageForRTTI(T),
- llvm::ConstantStruct::get(CTAType, Fields), StringRef(MangledName));
+ llvm::ConstantStruct::get(CTAType, Fields), MangledName);
CTA->setUnnamedAddr(true);
CTA->setSection(".xdata");
if (CTA->isWeakForLinker())
@@ -4102,7 +4158,7 @@ void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
QualType ThrowType = SubExpr->getType();
// The exception object lives on the stack and it's address is passed to the
// runtime function.
- llvm::AllocaInst *AI = CGF.CreateMemTemp(ThrowType);
+ Address AI = CGF.CreateMemTemp(ThrowType);
CGF.EmitAnyExprToMem(SubExpr, AI, ThrowType.getQualifiers(),
/*IsInit=*/true);
@@ -4111,6 +4167,9 @@ void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
llvm::GlobalVariable *TI = getThrowInfo(ThrowType);
// Call into the runtime to throw the exception.
- llvm::Value *Args[] = {CGF.Builder.CreateBitCast(AI, CGM.Int8PtrTy), TI};
+ llvm::Value *Args[] = {
+ CGF.Builder.CreateBitCast(AI.getPointer(), CGM.Int8PtrTy),
+ TI
+ };
CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args);
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp
index def56a9..0be5c55 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -30,7 +30,6 @@ using namespace clang;
namespace {
class CodeGeneratorImpl : public CodeGenerator {
DiagnosticsEngine &Diags;
- std::unique_ptr<const llvm::DataLayout> TD;
ASTContext *Ctx;
const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info.
const PreprocessorOptions &PreprocessorOpts; // Only used for debug info.
@@ -99,14 +98,10 @@ namespace {
Ctx = &Context;
M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple());
- M->setDataLayout(Ctx->getTargetInfo().getTargetDescription());
- TD.reset(
- new llvm::DataLayout(Ctx->getTargetInfo().getTargetDescription()));
- Builder.reset(new CodeGen::CodeGenModule(Context,
- HeaderSearchOpts,
- PreprocessorOpts,
- CodeGenOpts, *M, *TD,
- Diags, CoverageInfo));
+ M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());
+ Builder.reset(new CodeGen::CodeGenModule(Context, HeaderSearchOpts,
+ PreprocessorOpts, CodeGenOpts,
+ *M, Diags, CoverageInfo));
for (size_t i = 0, e = CodeGenOpts.DependentLibraries.size(); i < e; ++i)
HandleDependentLibrary(CodeGenOpts.DependentLibraries[i]);
@@ -180,7 +175,7 @@ namespace {
// For MSVC compatibility, treat declarations of static data members with
// inline initializers as definitions.
- if (Ctx->getLangOpts().MSVCCompat) {
+ if (Ctx->getTargetInfo().getCXXABI().isMicrosoft()) {
for (Decl *Member : D->decls()) {
if (VarDecl *VD = dyn_cast<VarDecl>(Member)) {
if (Ctx->isMSStaticDataMemberInlineDefinition(VD) &&
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
index 9c9b123..f385e53 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
@@ -18,6 +18,9 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/BackendUtil.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
#include "clang/Serialization/ASTWriter.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Bitcode/BitstreamReader.h"
@@ -30,6 +33,7 @@
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/TargetRegistry.h"
#include <memory>
+
using namespace clang;
#define DEBUG_TYPE "pchcontainer"
@@ -39,6 +43,7 @@ class PCHContainerGenerator : public ASTConsumer {
DiagnosticsEngine &Diags;
const std::string MainFileName;
ASTContext *Ctx;
+ ModuleMap &MMap;
const HeaderSearchOptions &HeaderSearchOpts;
const PreprocessorOptions &PreprocessorOpts;
CodeGenOptions CodeGenOpts;
@@ -50,34 +55,152 @@ class PCHContainerGenerator : public ASTConsumer {
raw_pwrite_stream *OS;
std::shared_ptr<PCHBuffer> Buffer;
+ /// Visit every type and emit debug info for it.
+ struct DebugTypeVisitor : public RecursiveASTVisitor<DebugTypeVisitor> {
+ clang::CodeGen::CGDebugInfo &DI;
+ ASTContext &Ctx;
+ bool SkipTagDecls;
+ DebugTypeVisitor(clang::CodeGen::CGDebugInfo &DI, ASTContext &Ctx,
+ bool SkipTagDecls)
+ : DI(DI), Ctx(Ctx), SkipTagDecls(SkipTagDecls) {}
+
+ /// Determine whether this type can be represented in DWARF.
+ static bool CanRepresent(const Type *Ty) {
+ return !Ty->isDependentType() && !Ty->isUndeducedType();
+ }
+
+ bool VisitImportDecl(ImportDecl *D) {
+ auto *Import = cast<ImportDecl>(D);
+ if (!Import->getImportedOwningModule())
+ DI.EmitImportDecl(*Import);
+ return true;
+ }
+
+ bool VisitTypeDecl(TypeDecl *D) {
+ // TagDecls may be deferred until after all decls have been merged and we
+ // know the complete type. Pure forward declarations will be skipped, but
+ // they don't need to be emitted into the module anyway.
+ if (SkipTagDecls && isa<TagDecl>(D))
+ return true;
+
+ QualType QualTy = Ctx.getTypeDeclType(D);
+ if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
+ DI.getOrCreateStandaloneType(QualTy, D->getLocation());
+ return true;
+ }
+
+ bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+ QualType QualTy(D->getTypeForDecl(), 0);
+ if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
+ DI.getOrCreateStandaloneType(QualTy, D->getLocation());
+ return true;
+ }
+
+ bool VisitFunctionDecl(FunctionDecl *D) {
+ if (isa<CXXMethodDecl>(D))
+ // This is not yet supported. Constructing the `this' argument
+ // mandates a CodeGenFunction.
+ return true;
+
+ SmallVector<QualType, 16> ArgTypes;
+ for (auto i : D->params())
+ ArgTypes.push_back(i->getType());
+ QualType RetTy = D->getReturnType();
+ QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes,
+ FunctionProtoType::ExtProtoInfo());
+ if (CanRepresent(FnTy.getTypePtr()))
+ DI.EmitFunctionDecl(D, D->getLocation(), FnTy);
+ return true;
+ }
+
+ bool VisitObjCMethodDecl(ObjCMethodDecl *D) {
+ if (!D->getClassInterface())
+ return true;
+
+ bool selfIsPseudoStrong, selfIsConsumed;
+ SmallVector<QualType, 16> ArgTypes;
+ ArgTypes.push_back(D->getSelfType(Ctx, D->getClassInterface(),
+ selfIsPseudoStrong, selfIsConsumed));
+ ArgTypes.push_back(Ctx.getObjCSelType());
+ for (auto i : D->params())
+ ArgTypes.push_back(i->getType());
+ QualType RetTy = D->getReturnType();
+ QualType FnTy = Ctx.getFunctionType(RetTy, ArgTypes,
+ FunctionProtoType::ExtProtoInfo());
+ if (CanRepresent(FnTy.getTypePtr()))
+ DI.EmitFunctionDecl(D, D->getLocation(), FnTy);
+ return true;
+ }
+ };
+
public:
- PCHContainerGenerator(DiagnosticsEngine &diags,
- const HeaderSearchOptions &HSO,
- const PreprocessorOptions &PPO, const TargetOptions &TO,
- const LangOptions &LO, const std::string &MainFileName,
+ PCHContainerGenerator(CompilerInstance &CI, const std::string &MainFileName,
const std::string &OutputFileName,
raw_pwrite_stream *OS,
std::shared_ptr<PCHBuffer> Buffer)
- : Diags(diags), HeaderSearchOpts(HSO), PreprocessorOpts(PPO),
- TargetOpts(TO), LangOpts(LO), OS(OS), Buffer(Buffer) {
+ : Diags(CI.getDiagnostics()), Ctx(nullptr),
+ MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()),
+ HeaderSearchOpts(CI.getHeaderSearchOpts()),
+ PreprocessorOpts(CI.getPreprocessorOpts()),
+ TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()), OS(OS),
+ Buffer(Buffer) {
// The debug info output isn't affected by CodeModel and
// ThreadModel, but the backend expects them to be nonempty.
CodeGenOpts.CodeModel = "default";
CodeGenOpts.ThreadModel = "single";
+ CodeGenOpts.DebugTypeExtRefs = true;
CodeGenOpts.setDebugInfo(CodeGenOptions::FullDebugInfo);
- CodeGenOpts.SplitDwarfFile = OutputFileName;
}
- virtual ~PCHContainerGenerator() {}
+ ~PCHContainerGenerator() override = default;
void Initialize(ASTContext &Context) override {
+ assert(!Ctx && "initialized multiple times");
+
Ctx = &Context;
VMContext.reset(new llvm::LLVMContext());
M.reset(new llvm::Module(MainFileName, *VMContext));
- M->setDataLayout(Ctx->getTargetInfo().getTargetDescription());
- Builder.reset(new CodeGen::CodeGenModule(*Ctx, HeaderSearchOpts,
- PreprocessorOpts, CodeGenOpts, *M,
- M->getDataLayout(), Diags));
+ M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());
+ Builder.reset(new CodeGen::CodeGenModule(
+ *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
+ Builder->getModuleDebugInfo()->setModuleMap(MMap);
+ }
+
+ bool HandleTopLevelDecl(DeclGroupRef D) override {
+ if (Diags.hasErrorOccurred())
+ return true;
+
+ // Collect debug info for all decls in this group.
+ for (auto *I : D)
+ if (!I->isFromASTFile()) {
+ DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx, true);
+ DTV.TraverseDecl(I);
+ }
+ return true;
+ }
+
+ void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
+ HandleTopLevelDecl(D);
+ }
+
+ void HandleTagDeclDefinition(TagDecl *D) override {
+ if (Diags.hasErrorOccurred())
+ return;
+
+ if (D->isFromASTFile())
+ return;
+
+ DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx, false);
+ DTV.TraverseDecl(D);
+ Builder->UpdateCompletedType(D);
+ }
+
+ void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
+ if (Diags.hasErrorOccurred())
+ return;
+
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(D))
+ Builder->getModuleDebugInfo()->completeRequiredType(RD);
}
/// Emit a container holding the serialized AST.
@@ -92,7 +215,8 @@ public:
return;
M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple());
- M->setDataLayout(Ctx.getTargetInfo().getTargetDescription());
+ M->setDataLayout(Ctx.getTargetInfo().getDataLayoutString());
+ Builder->getModuleDebugInfo()->setDwoId(Buffer->Signature);
// Finalize the Builder.
if (Builder)
@@ -133,15 +257,14 @@ public:
llvm::SmallString<0> Buffer;
llvm::raw_svector_ostream OS(Buffer);
clang::EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
- Ctx.getTargetInfo().getTargetDescription(),
+ Ctx.getTargetInfo().getDataLayoutString(),
M.get(), BackendAction::Backend_EmitLL, &OS);
- OS.flush();
llvm::dbgs() << Buffer;
});
// Use the LLVM backend to emit the pch container.
clang::EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
- Ctx.getTargetInfo().getTargetDescription(),
+ Ctx.getTargetInfo().getDataLayoutString(),
M.get(), BackendAction::Backend_EmitObj, OS);
// Make sure the pch container hits disk.
@@ -153,17 +276,15 @@ public:
}
};
-} // namespace
+} // anonymous namespace
std::unique_ptr<ASTConsumer>
ObjectFilePCHContainerWriter::CreatePCHContainerGenerator(
- DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO,
- const PreprocessorOptions &PPO, const TargetOptions &TO,
- const LangOptions &LO, const std::string &MainFileName,
+ CompilerInstance &CI, const std::string &MainFileName,
const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
std::shared_ptr<PCHBuffer> Buffer) const {
- return llvm::make_unique<PCHContainerGenerator>(
- Diags, HSO, PPO, TO, LO, MainFileName, OutputFileName, OS, Buffer);
+ return llvm::make_unique<PCHContainerGenerator>(CI, MainFileName,
+ OutputFileName, OS, Buffer);
}
void ObjectFilePCHContainerReader::ExtractPCH(
@@ -189,5 +310,4 @@ void ObjectFilePCHContainerReader::ExtractPCH(
// As a fallback, treat the buffer as a raw AST.
StreamFile.init((const unsigned char *)Buffer.getBufferStart(),
(const unsigned char *)Buffer.getBufferEnd());
- return;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
index 25bd733..4566fdb 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
@@ -39,7 +39,7 @@ static void AssignToArrayRange(CodeGen::CGBuilderTy &Builder,
for (unsigned I = FirstIndex; I <= LastIndex; ++I) {
llvm::Value *Cell =
Builder.CreateConstInBoundsGEP1_32(Builder.getInt8Ty(), Array, I);
- Builder.CreateStore(Value, Cell);
+ Builder.CreateAlignedStore(Value, Cell, CharUnits::One());
}
}
@@ -48,6 +48,24 @@ static bool isAggregateTypeForABI(QualType T) {
T->isMemberFunctionPointerType();
}
+ABIArgInfo
+ABIInfo::getNaturalAlignIndirect(QualType Ty, bool ByRef, bool Realign,
+ llvm::Type *Padding) const {
+ return ABIArgInfo::getIndirect(getContext().getTypeAlignInChars(Ty),
+ ByRef, Realign, Padding);
+}
+
+ABIArgInfo
+ABIInfo::getNaturalAlignIndirectInReg(QualType Ty, bool Realign) const {
+ return ABIArgInfo::getIndirectInReg(getContext().getTypeAlignInChars(Ty),
+ /*ByRef*/ false, Realign);
+}
+
+Address ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ return Address::invalid();
+}
+
ABIInfo::~ABIInfo() {}
static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT,
@@ -133,7 +151,7 @@ void ABIArgInfo::dump() const {
OS << "InAlloca Offset=" << getInAllocaFieldIndex();
break;
case Indirect:
- OS << "Indirect Align=" << getIndirectAlign()
+ OS << "Indirect Align=" << getIndirectAlign().getQuantity()
<< " ByVal=" << getIndirectByVal()
<< " Realign=" << getIndirectRealign();
break;
@@ -144,6 +162,135 @@ void ABIArgInfo::dump() const {
OS << ")\n";
}
+// Dynamically round a pointer up to a multiple of the given alignment.
+static llvm::Value *emitRoundPointerUpToAlignment(CodeGenFunction &CGF,
+ llvm::Value *Ptr,
+ CharUnits Align) {
+ llvm::Value *PtrAsInt = Ptr;
+ // OverflowArgArea = (OverflowArgArea + Align - 1) & -Align;
+ PtrAsInt = CGF.Builder.CreatePtrToInt(PtrAsInt, CGF.IntPtrTy);
+ PtrAsInt = CGF.Builder.CreateAdd(PtrAsInt,
+ llvm::ConstantInt::get(CGF.IntPtrTy, Align.getQuantity() - 1));
+ PtrAsInt = CGF.Builder.CreateAnd(PtrAsInt,
+ llvm::ConstantInt::get(CGF.IntPtrTy, -Align.getQuantity()));
+ PtrAsInt = CGF.Builder.CreateIntToPtr(PtrAsInt,
+ Ptr->getType(),
+ Ptr->getName() + ".aligned");
+ return PtrAsInt;
+}
+
+/// Emit va_arg for a platform using the common void* representation,
+/// where arguments are simply emitted in an array of slots on the stack.
+///
+/// This version implements the core direct-value passing rules.
+///
+/// \param SlotSize - The size and alignment of a stack slot.
+/// Each argument will be allocated to a multiple of this number of
+/// slots, and all the slots will be aligned to this value.
+/// \param AllowHigherAlign - The slot alignment is not a cap;
+/// an argument type with an alignment greater than the slot size
+/// will be emitted on a higher-alignment address, potentially
+/// leaving one or more empty slots behind as padding. If this
+/// is false, the returned address might be less-aligned than
+/// DirectAlign.
+static Address emitVoidPtrDirectVAArg(CodeGenFunction &CGF,
+ Address VAListAddr,
+ llvm::Type *DirectTy,
+ CharUnits DirectSize,
+ CharUnits DirectAlign,
+ CharUnits SlotSize,
+ bool AllowHigherAlign) {
+ // Cast the element type to i8* if necessary. Some platforms define
+ // va_list as a struct containing an i8* instead of just an i8*.
+ if (VAListAddr.getElementType() != CGF.Int8PtrTy)
+ VAListAddr = CGF.Builder.CreateElementBitCast(VAListAddr, CGF.Int8PtrTy);
+
+ llvm::Value *Ptr = CGF.Builder.CreateLoad(VAListAddr, "argp.cur");
+
+ // If the CC aligns values higher than the slot size, do so if needed.
+ Address Addr = Address::invalid();
+ if (AllowHigherAlign && DirectAlign > SlotSize) {
+ Addr = Address(emitRoundPointerUpToAlignment(CGF, Ptr, DirectAlign),
+ DirectAlign);
+ } else {
+ Addr = Address(Ptr, SlotSize);
+ }
+
+ // Advance the pointer past the argument, then store that back.
+ CharUnits FullDirectSize = DirectSize.RoundUpToAlignment(SlotSize);
+ llvm::Value *NextPtr =
+ CGF.Builder.CreateConstInBoundsByteGEP(Addr.getPointer(), FullDirectSize,
+ "argp.next");
+ CGF.Builder.CreateStore(NextPtr, VAListAddr);
+
+ // If the argument is smaller than a slot, and this is a big-endian
+ // target, the argument will be right-adjusted in its slot.
+ if (DirectSize < SlotSize && CGF.CGM.getDataLayout().isBigEndian()) {
+ Addr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, SlotSize - DirectSize);
+ }
+
+ Addr = CGF.Builder.CreateElementBitCast(Addr, DirectTy);
+ return Addr;
+}
+
+/// Emit va_arg for a platform using the common void* representation,
+/// where arguments are simply emitted in an array of slots on the stack.
+///
+/// \param IsIndirect - Values of this type are passed indirectly.
+/// \param ValueInfo - The size and alignment of this type, generally
+/// computed with getContext().getTypeInfoInChars(ValueTy).
+/// \param SlotSizeAndAlign - The size and alignment of a stack slot.
+/// Each argument will be allocated to a multiple of this number of
+/// slots, and all the slots will be aligned to this value.
+/// \param AllowHigherAlign - The slot alignment is not a cap;
+/// an argument type with an alignment greater than the slot size
+/// will be emitted on a higher-alignment address, potentially
+/// leaving one or more empty slots behind as padding.
+static Address emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType ValueTy, bool IsIndirect,
+ std::pair<CharUnits, CharUnits> ValueInfo,
+ CharUnits SlotSizeAndAlign,
+ bool AllowHigherAlign) {
+ // The size and alignment of the value that was passed directly.
+ CharUnits DirectSize, DirectAlign;
+ if (IsIndirect) {
+ DirectSize = CGF.getPointerSize();
+ DirectAlign = CGF.getPointerAlign();
+ } else {
+ DirectSize = ValueInfo.first;
+ DirectAlign = ValueInfo.second;
+ }
+
+ // Cast the address we've calculated to the right type.
+ llvm::Type *DirectTy = CGF.ConvertTypeForMem(ValueTy);
+ if (IsIndirect)
+ DirectTy = DirectTy->getPointerTo(0);
+
+ Address Addr = emitVoidPtrDirectVAArg(CGF, VAListAddr, DirectTy,
+ DirectSize, DirectAlign,
+ SlotSizeAndAlign,
+ AllowHigherAlign);
+
+ if (IsIndirect) {
+ Addr = Address(CGF.Builder.CreateLoad(Addr), ValueInfo.second);
+ }
+
+ return Addr;
+
+}
+
+static Address emitMergePHI(CodeGenFunction &CGF,
+ Address Addr1, llvm::BasicBlock *Block1,
+ Address Addr2, llvm::BasicBlock *Block2,
+ const llvm::Twine &Name = "") {
+ assert(Addr1.getType() == Addr2.getType());
+ llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name);
+ PHI->addIncoming(Addr1.getPointer(), Block1);
+ PHI->addIncoming(Addr2.getPointer(), Block2);
+ CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment());
+ return Address(PHI, Align);
+}
+
TargetCodeGenInfo::~TargetCodeGenInfo() { delete Info; }
// If someone can figure out a general rule for this, that would be great.
@@ -394,8 +541,8 @@ public:
I.info = classifyArgumentType(I.type);
}
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
};
class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -404,9 +551,9 @@ public:
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
};
-llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- return nullptr;
+Address DefaultABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ return Address::invalid();
}
ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
@@ -416,9 +563,9 @@ ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
// Records with non-trivial destructors/copy-constructors should not be
// passed by value.
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(Ty);
}
// Treat an enum type as its underlying type.
@@ -434,7 +581,7 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
return ABIArgInfo::getIgnore();
if (isAggregateTypeForABI(RetTy))
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
@@ -445,6 +592,80 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
}
//===----------------------------------------------------------------------===//
+// WebAssembly ABI Implementation
+//
+// This is a very simple ABI that relies a lot on DefaultABIInfo.
+//===----------------------------------------------------------------------===//
+
+class WebAssemblyABIInfo final : public DefaultABIInfo {
+public:
+ explicit WebAssemblyABIInfo(CodeGen::CodeGenTypes &CGT)
+ : DefaultABIInfo(CGT) {}
+
+private:
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType Ty) const;
+
+ // DefaultABIInfo's classifyReturnType and classifyArgumentType are
+ // non-virtual, but computeInfo is virtual, so we overload that.
+ void computeInfo(CGFunctionInfo &FI) const override {
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ for (auto &Arg : FI.arguments())
+ Arg.info = classifyArgumentType(Arg.type);
+ }
+};
+
+class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo {
+public:
+ explicit WebAssemblyTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new WebAssemblyABIInfo(CGT)) {}
+};
+
+/// \brief Classify argument of given type \p Ty.
+ABIArgInfo WebAssemblyABIInfo::classifyArgumentType(QualType Ty) const {
+ Ty = useFirstFieldIfTransparentUnion(Ty);
+
+ if (isAggregateTypeForABI(Ty)) {
+ // Records with non-trivial destructors/copy-constructors should not be
+ // passed by value.
+ if (auto RAA = getRecordArgABI(Ty, getCXXABI()))
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
+ // Ignore empty structs/unions.
+ if (isEmptyRecord(getContext(), Ty, true))
+ return ABIArgInfo::getIgnore();
+ // Lower single-element structs to just pass a regular value. TODO: We
+ // could do reasonable-size multiple-element structs too, using getExpand(),
+ // though watch out for things like bitfields.
+ if (const Type *SeltTy = isSingleElementStruct(Ty, getContext()))
+ return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
+ }
+
+ // Otherwise just do the default thing.
+ return DefaultABIInfo::classifyArgumentType(Ty);
+}
+
+ABIArgInfo WebAssemblyABIInfo::classifyReturnType(QualType RetTy) const {
+ if (isAggregateTypeForABI(RetTy)) {
+ // Records with non-trivial destructors/copy-constructors should not be
+ // returned by value.
+ if (!getRecordArgABI(RetTy, getCXXABI())) {
+ // Ignore empty structs/unions.
+ if (isEmptyRecord(getContext(), RetTy, true))
+ return ABIArgInfo::getIgnore();
+ // Lower single-element structs to just return a regular value. TODO: We
+ // could do reasonable-size multiple-element structs too, using
+ // ABIArgInfo::getDirect().
+ if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext()))
+ return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
+ }
+ }
+
+ // Otherwise just do the default thing.
+ return DefaultABIInfo::classifyReturnType(RetTy);
+}
+
+//===----------------------------------------------------------------------===//
// le32/PNaCl bitcode ABI Implementation
//
// This is a simplified version of the x86_32 ABI. Arguments and return values
@@ -459,8 +680,8 @@ class PNaClABIInfo : public ABIInfo {
ABIArgInfo classifyArgumentType(QualType RetTy) const;
void computeInfo(CGFunctionInfo &FI) const override;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF,
+ Address VAListAddr, QualType Ty) const override;
};
class PNaClTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -477,17 +698,17 @@ void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const {
I.info = classifyArgumentType(I.type);
}
-llvm::Value *PNaClABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- return nullptr;
+Address PNaClABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ return Address::invalid();
}
/// \brief Classify argument of given type \p Ty.
ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
if (isAggregateTypeForABI(Ty)) {
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
+ return getNaturalAlignIndirect(Ty);
} else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
// Treat an enum type as its underlying type.
Ty = EnumTy->getDecl()->getIntegerType();
@@ -506,7 +727,7 @@ ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const {
// In the PNaCl ABI we always return records/structures on the stack.
if (isAggregateTypeForABI(RetTy))
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
@@ -585,8 +806,10 @@ class X86_32ABIInfo : public ABIInfo {
static const unsigned MinABIStackAlignInBytes = 4;
bool IsDarwinVectorABI;
- bool IsSmallStructInRegABI;
+ bool IsRetSmallStructInRegABI;
bool IsWin32StructABI;
+ bool IsSoftFloatABI;
+ bool IsMCUABI;
unsigned DefaultNumRegisterParameters;
static bool isRegisterSize(unsigned Size) {
@@ -610,7 +833,7 @@ class X86_32ABIInfo : public ABIInfo {
/// such that the argument will be passed in memory.
ABIArgInfo getIndirectResult(QualType Ty, bool ByVal, CCState &State) const;
- ABIArgInfo getIndirectReturnResult(CCState &State) const;
+ ABIArgInfo getIndirectReturnResult(QualType Ty, CCState &State) const;
/// \brief Return the alignment to use for the given type on the stack.
unsigned getTypeStackAlignInBytes(QualType Ty, unsigned Align) const;
@@ -618,33 +841,47 @@ class X86_32ABIInfo : public ABIInfo {
Class classify(QualType Ty) const;
ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const;
ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const;
- bool shouldUseInReg(QualType Ty, CCState &State, bool &NeedsPadding) const;
+ /// \brief Updates the number of available free registers, returns
+ /// true if any registers were allocated.
+ bool updateFreeRegs(QualType Ty, CCState &State) const;
+
+ bool shouldAggregateUseDirect(QualType Ty, CCState &State, bool &InReg,
+ bool &NeedsPadding) const;
+ bool shouldPrimitiveUseInReg(QualType Ty, CCState &State) const;
/// \brief Rewrite the function info so that all memory arguments use
/// inalloca.
void rewriteWithInAlloca(CGFunctionInfo &FI) const;
void addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields,
- unsigned &StackOffset, ABIArgInfo &Info,
+ CharUnits &StackOffset, ABIArgInfo &Info,
QualType Type) const;
public:
void computeInfo(CGFunctionInfo &FI) const override;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
-
- X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p, bool w,
- unsigned r)
- : ABIInfo(CGT), IsDarwinVectorABI(d), IsSmallStructInRegABI(p),
- IsWin32StructABI(w), DefaultNumRegisterParameters(r) {}
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
+
+ X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool DarwinVectorABI,
+ bool RetSmallStructInRegABI, bool Win32StructABI,
+ unsigned NumRegisterParameters, bool SoftFloatABI)
+ : ABIInfo(CGT), IsDarwinVectorABI(DarwinVectorABI),
+ IsRetSmallStructInRegABI(RetSmallStructInRegABI),
+ IsWin32StructABI(Win32StructABI),
+ IsSoftFloatABI(SoftFloatABI),
+ IsMCUABI(CGT.getTarget().getTriple().isOSIAMCU()),
+ DefaultNumRegisterParameters(NumRegisterParameters) {}
};
class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
- bool d, bool p, bool w, unsigned r)
- :TargetCodeGenInfo(new X86_32ABIInfo(CGT, d, p, w, r)) {}
+ X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool DarwinVectorABI,
+ bool RetSmallStructInRegABI, bool Win32StructABI,
+ unsigned NumRegisterParameters, bool SoftFloatABI)
+ : TargetCodeGenInfo(new X86_32ABIInfo(
+ CGT, DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
+ NumRegisterParameters, SoftFloatABI)) {}
static bool isStructReturnInRegABI(
const llvm::Triple &Triple, const CodeGenOptions &Opts);
@@ -767,14 +1004,15 @@ void X86_32TargetCodeGenInfo::addReturnRegisterOutputs(
}
/// shouldReturnTypeInRegister - Determine if the given type should be
-/// passed in a register (for the Darwin ABI).
+/// returned in a register (for the Darwin and MCU ABI).
bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
ASTContext &Context) const {
uint64_t Size = Context.getTypeSize(Ty);
- // Type must be register sized.
- if (!isRegisterSize(Size))
- return false;
+ // For i386, type must be register sized.
+ // For the MCU ABI, it only needs to be <= 8-byte
+ if ((IsMCUABI && Size > 64) || (!IsMCUABI && !isRegisterSize(Size)))
+ return false;
if (Ty->isVectorType()) {
// 64- and 128- bit vectors inside structures are not returned in
@@ -816,14 +1054,15 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
return true;
}
-ABIArgInfo X86_32ABIInfo::getIndirectReturnResult(CCState &State) const {
+ABIArgInfo X86_32ABIInfo::getIndirectReturnResult(QualType RetTy, CCState &State) const {
// If the return value is indirect, then the hidden argument is consuming one
// integer register.
if (State.FreeRegs) {
--State.FreeRegs;
- return ABIArgInfo::getIndirectInReg(/*Align=*/0, /*ByVal=*/false);
+ if (!IsMCUABI)
+ return getNaturalAlignIndirectInReg(RetTy);
}
- return ABIArgInfo::getIndirect(/*Align=*/0, /*ByVal=*/false);
+ return getNaturalAlignIndirect(RetTy, /*ByVal=*/false);
}
ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
@@ -858,7 +1097,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
Size));
- return getIndirectReturnResult(State);
+ return getIndirectReturnResult(RetTy, State);
}
return ABIArgInfo::getDirect();
@@ -868,12 +1107,12 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
if (const RecordType *RT = RetTy->getAs<RecordType>()) {
// Structures with flexible arrays are always indirect.
if (RT->getDecl()->hasFlexibleArrayMember())
- return getIndirectReturnResult(State);
+ return getIndirectReturnResult(RetTy, State);
}
// If specified, structs and unions are always indirect.
- if (!IsSmallStructInRegABI && !RetTy->isAnyComplexType())
- return getIndirectReturnResult(State);
+ if (!IsRetSmallStructInRegABI && !RetTy->isAnyComplexType())
+ return getIndirectReturnResult(RetTy, State);
// Small structures which are register sized are generally returned
// in a register.
@@ -895,7 +1134,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),Size));
}
- return getIndirectReturnResult(State);
+ return getIndirectReturnResult(RetTy, State);
}
// Treat an enum type as its underlying type.
@@ -961,21 +1200,23 @@ ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal,
if (!ByVal) {
if (State.FreeRegs) {
--State.FreeRegs; // Non-byval indirects just use one pointer.
- return ABIArgInfo::getIndirectInReg(0, false);
+ if (!IsMCUABI)
+ return getNaturalAlignIndirectInReg(Ty);
}
- return ABIArgInfo::getIndirect(0, false);
+ return getNaturalAlignIndirect(Ty, false);
}
// Compute the byval alignment.
unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
unsigned StackAlign = getTypeStackAlignInBytes(Ty, TypeAlign);
if (StackAlign == 0)
- return ABIArgInfo::getIndirect(4, /*ByVal=*/true);
+ return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true);
// If the stack alignment is less than the type alignment, realign the
// argument.
bool Realign = TypeAlign > StackAlign;
- return ABIArgInfo::getIndirect(StackAlign, /*ByVal=*/true, Realign);
+ return ABIArgInfo::getIndirect(CharUnits::fromQuantity(StackAlign),
+ /*ByVal=*/true, Realign);
}
X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const {
@@ -991,12 +1232,12 @@ X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const {
return Integer;
}
-bool X86_32ABIInfo::shouldUseInReg(QualType Ty, CCState &State,
- bool &NeedsPadding) const {
- NeedsPadding = false;
- Class C = classify(Ty);
- if (C == Float)
- return false;
+bool X86_32ABIInfo::updateFreeRegs(QualType Ty, CCState &State) const {
+ if (!IsSoftFloatABI) {
+ Class C = classify(Ty);
+ if (C == Float)
+ return false;
+ }
unsigned Size = getContext().getTypeSize(Ty);
unsigned SizeInRegs = (Size + 31) / 32;
@@ -1004,31 +1245,61 @@ bool X86_32ABIInfo::shouldUseInReg(QualType Ty, CCState &State,
if (SizeInRegs == 0)
return false;
- if (SizeInRegs > State.FreeRegs) {
- State.FreeRegs = 0;
- return false;
+ if (!IsMCUABI) {
+ if (SizeInRegs > State.FreeRegs) {
+ State.FreeRegs = 0;
+ return false;
+ }
+ } else {
+ // The MCU psABI allows passing parameters in-reg even if there are
+ // earlier parameters that are passed on the stack. Also,
+ // it does not allow passing >8-byte structs in-register,
+ // even if there are 3 free registers available.
+ if (SizeInRegs > State.FreeRegs || SizeInRegs > 2)
+ return false;
}
State.FreeRegs -= SizeInRegs;
+ return true;
+}
+
+bool X86_32ABIInfo::shouldAggregateUseDirect(QualType Ty, CCState &State,
+ bool &InReg,
+ bool &NeedsPadding) const {
+ NeedsPadding = false;
+ InReg = !IsMCUABI;
+
+ if (!updateFreeRegs(Ty, State))
+ return false;
+
+ if (IsMCUABI)
+ return true;
if (State.CC == llvm::CallingConv::X86_FastCall ||
State.CC == llvm::CallingConv::X86_VectorCall) {
- if (Size > 32)
- return false;
-
- if (Ty->isIntegralOrEnumerationType())
- return true;
+ if (getContext().getTypeSize(Ty) <= 32 && State.FreeRegs)
+ NeedsPadding = true;
- if (Ty->isPointerType())
- return true;
+ return false;
+ }
- if (Ty->isReferenceType())
- return true;
+ return true;
+}
- if (State.FreeRegs)
- NeedsPadding = true;
+bool X86_32ABIInfo::shouldPrimitiveUseInReg(QualType Ty, CCState &State) const {
+ if (!updateFreeRegs(Ty, State))
+ return false;
+ if (IsMCUABI)
return false;
+
+ if (State.CC == llvm::CallingConv::X86_FastCall ||
+ State.CC == llvm::CallingConv::X86_VectorCall) {
+ if (getContext().getTypeSize(Ty) > 32)
+ return false;
+
+ return (Ty->isIntegralOrEnumerationType() || Ty->isPointerType() ||
+ Ty->isReferenceType());
}
return true;
@@ -1084,12 +1355,15 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
llvm::LLVMContext &LLVMContext = getVMContext();
llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
- bool NeedsPadding;
- if (shouldUseInReg(Ty, State, NeedsPadding)) {
+ bool NeedsPadding, InReg;
+ if (shouldAggregateUseDirect(Ty, State, InReg, NeedsPadding)) {
unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32;
SmallVector<llvm::Type*, 3> Elements(SizeInRegs, Int32);
llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
- return ABIArgInfo::getDirectInReg(Result);
+ if (InReg)
+ return ABIArgInfo::getDirectInReg(Result);
+ else
+ return ABIArgInfo::getDirect(Result);
}
llvm::IntegerType *PaddingType = NeedsPadding ? Int32 : nullptr;
@@ -1097,8 +1371,11 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
// of those arguments will match the struct. This is important because the
// LLVM backend isn't smart enough to remove byval, which inhibits many
// optimizations.
+ // Don't do this for the MCU if there are still free integer registers
+ // (see X86_64 ABI for full explanation).
if (getContext().getTypeSize(Ty) <= 4*32 &&
- canExpandIndirectArgument(Ty, getContext()))
+ canExpandIndirectArgument(Ty, getContext()) &&
+ (!IsMCUABI || State.FreeRegs == 0))
return ABIArgInfo::getExpandWithPadding(
State.CC == llvm::CallingConv::X86_FastCall ||
State.CC == llvm::CallingConv::X86_VectorCall,
@@ -1128,14 +1405,14 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
- bool NeedsPadding;
- bool InReg = shouldUseInReg(Ty, State, NeedsPadding);
+ bool InReg = shouldPrimitiveUseInReg(Ty, State);
if (Ty->isPromotableIntegerType()) {
if (InReg)
return ABIArgInfo::getExtendInReg();
return ABIArgInfo::getExtend();
}
+
if (InReg)
return ABIArgInfo::getDirectInReg();
return ABIArgInfo::getDirect();
@@ -1143,7 +1420,9 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const {
CCState State(FI.getCallingConvention());
- if (State.CC == llvm::CallingConv::X86_FastCall)
+ if (IsMCUABI)
+ State.FreeRegs = 3;
+ else if (State.CC == llvm::CallingConv::X86_FastCall)
State.FreeRegs = 2;
else if (State.CC == llvm::CallingConv::X86_VectorCall) {
State.FreeRegs = 2;
@@ -1160,7 +1439,8 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const {
// return value was sret and put it in a register ourselves if appropriate.
if (State.FreeRegs) {
--State.FreeRegs; // The sret parameter consumes a register.
- FI.getReturnInfo().setInReg(true);
+ if (!IsMCUABI)
+ FI.getReturnInfo().setInReg(true);
}
}
@@ -1182,22 +1462,23 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const {
void
X86_32ABIInfo::addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields,
- unsigned &StackOffset,
- ABIArgInfo &Info, QualType Type) const {
- assert(StackOffset % 4U == 0 && "unaligned inalloca struct");
+ CharUnits &StackOffset, ABIArgInfo &Info,
+ QualType Type) const {
+ // Arguments are always 4-byte-aligned.
+ CharUnits FieldAlign = CharUnits::fromQuantity(4);
+
+ assert(StackOffset.isMultipleOf(FieldAlign) && "unaligned inalloca struct");
Info = ABIArgInfo::getInAlloca(FrameFields.size());
FrameFields.push_back(CGT.ConvertTypeForMem(Type));
- StackOffset += getContext().getTypeSizeInChars(Type).getQuantity();
-
- // Insert padding bytes to respect alignment. For x86_32, each argument is 4
- // byte aligned.
- if (StackOffset % 4U) {
- unsigned OldOffset = StackOffset;
- StackOffset = llvm::RoundUpToAlignment(StackOffset, 4U);
- unsigned NumBytes = StackOffset - OldOffset;
- assert(NumBytes);
+ StackOffset += getContext().getTypeSizeInChars(Type);
+
+ // Insert padding bytes to respect alignment.
+ CharUnits FieldEnd = StackOffset;
+ StackOffset = FieldEnd.RoundUpToAlignment(FieldAlign);
+ if (StackOffset != FieldEnd) {
+ CharUnits NumBytes = StackOffset - FieldEnd;
llvm::Type *Ty = llvm::Type::getInt8Ty(getVMContext());
- Ty = llvm::ArrayType::get(Ty, NumBytes);
+ Ty = llvm::ArrayType::get(Ty, NumBytes.getQuantity());
FrameFields.push_back(Ty);
}
}
@@ -1228,7 +1509,10 @@ void X86_32ABIInfo::rewriteWithInAlloca(CGFunctionInfo &FI) const {
// Build a packed struct type for all of the arguments in memory.
SmallVector<llvm::Type *, 6> FrameFields;
- unsigned StackOffset = 0;
+ // The stack alignment is always 4.
+ CharUnits StackAlign = CharUnits::fromQuantity(4);
+
+ CharUnits StackOffset;
CGFunctionInfo::arg_iterator I = FI.arg_begin(), E = FI.arg_end();
// Put 'this' into the struct before 'sret', if necessary.
@@ -1260,47 +1544,25 @@ void X86_32ABIInfo::rewriteWithInAlloca(CGFunctionInfo &FI) const {
}
FI.setArgStruct(llvm::StructType::get(getVMContext(), FrameFields,
- /*isPacked=*/true));
+ /*isPacked=*/true),
+ StackAlign);
}
-llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- llvm::Type *BPP = CGF.Int8PtrPtrTy;
+Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF,
+ Address VAListAddr, QualType Ty) const {
- CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
- "ap");
- llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
-
- // Compute if the address needs to be aligned
- unsigned Align = CGF.getContext().getTypeAlignInChars(Ty).getQuantity();
- Align = getTypeStackAlignInBytes(Ty, Align);
- Align = std::max(Align, 4U);
- if (Align > 4) {
- // addr = (addr + align - 1) & -align;
- llvm::Value *Offset =
- llvm::ConstantInt::get(CGF.Int32Ty, Align - 1);
- Addr = CGF.Builder.CreateGEP(Addr, Offset);
- llvm::Value *AsInt = CGF.Builder.CreatePtrToInt(Addr,
- CGF.Int32Ty);
- llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int32Ty, -Align);
- Addr = CGF.Builder.CreateIntToPtr(CGF.Builder.CreateAnd(AsInt, Mask),
- Addr->getType(),
- "ap.cur.aligned");
- }
-
- llvm::Type *PTy =
- llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
-
- uint64_t Offset =
- llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, Align);
- llvm::Value *NextAddr =
- Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset),
- "ap.next");
- Builder.CreateStore(NextAddr, VAListAddrAsBPP);
-
- return AddrTyped;
+ auto TypeInfo = getContext().getTypeInfoInChars(Ty);
+
+ // x86-32 changes the alignment of certain arguments on the stack.
+ //
+ // Just messing with TypeInfo like this works because we never pass
+ // anything indirectly.
+ TypeInfo.second = CharUnits::fromQuantity(
+ getTypeStackAlignInBytes(Ty, TypeInfo.second.getQuantity()));
+
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*Indirect*/ false,
+ TypeInfo, CharUnits::fromQuantity(4),
+ /*AllowHigherAlign*/ true);
}
bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
@@ -1316,7 +1578,7 @@ bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
return true;
}
- if (Triple.isOSDarwin())
+ if (Triple.isOSDarwin() || Triple.isOSIAMCU())
return true;
switch (Triple.getOS()) {
@@ -1334,7 +1596,7 @@ bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
void X86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D,
llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
// Get the LLVM function.
llvm::Function *Fn = cast<llvm::Function>(GV);
@@ -1372,8 +1634,9 @@ bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable(
} else {
// 9 is %eflags, which doesn't get a size on Darwin for some
// reason.
- Builder.CreateStore(
- Four8, Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, Address, 9));
+ Builder.CreateAlignedStore(
+ Four8, Builder.CreateConstInBoundsGEP1_32(CGF.Int8Ty, Address, 9),
+ CharUnits::One());
// 11-16 are st(0..5). Not sure why we stop at 5.
// These have size 12, which is sizeof(long double) on
@@ -1542,8 +1805,10 @@ public:
void computeInfo(CGFunctionInfo &FI) const override;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
+ Address EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
bool has64BitPointers() const {
return Has64BitPointers;
@@ -1559,8 +1824,8 @@ public:
void computeInfo(CGFunctionInfo &FI) const override;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
bool isHomogeneousAggregateBaseType(QualType Ty) const override {
// FIXME: Assumes vectorcall is in use.
@@ -1659,7 +1924,11 @@ public:
void getDependentLibraryOption(llvm::StringRef Lib,
llvm::SmallString<24> &Opt) const override {
Opt = "\01";
- Opt += Lib;
+ // If the argument contains a space, enclose it in quotes.
+ if (Lib.find(" ") != StringRef::npos)
+ Opt += "\"" + Lib.str() + "\"";
+ else
+ Opt += Lib;
}
};
@@ -1679,8 +1948,10 @@ static std::string qualifyWindowsLibrary(llvm::StringRef Lib) {
class WinX86_32TargetCodeGenInfo : public X86_32TargetCodeGenInfo {
public:
WinX86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
- bool d, bool p, bool w, unsigned RegParms)
- : X86_32TargetCodeGenInfo(CGT, d, p, w, RegParms) {}
+ bool DarwinVectorABI, bool RetSmallStructInRegABI, bool Win32StructABI,
+ unsigned NumRegisterParameters)
+ : X86_32TargetCodeGenInfo(CGT, DarwinVectorABI, RetSmallStructInRegABI,
+ Win32StructABI, NumRegisterParameters, false) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override;
@@ -1701,7 +1972,7 @@ public:
static void addStackProbeSizeTargetAttribute(const Decl *D,
llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) {
- if (isa<FunctionDecl>(D)) {
+ if (D && isa<FunctionDecl>(D)) {
if (CGM.getCodeGenOpts().StackProbeSize != 4096) {
llvm::Function *Fn = cast<llvm::Function>(GV);
@@ -1918,16 +2189,18 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
if (const VectorType *VT = Ty->getAs<VectorType>()) {
uint64_t Size = getContext().getTypeSize(VT);
- if (Size == 32) {
- // gcc passes all <4 x char>, <2 x short>, <1 x int>, <1 x
- // float> as integer.
+ if (Size == 1 || Size == 8 || Size == 16 || Size == 32) {
+ // gcc passes the following as integer:
+ // 4 bytes - <4 x char>, <2 x short>, <1 x int>, <1 x float>
+ // 2 bytes - <2 x char>, <1 x short>
+ // 1 byte - <1 x char>
Current = Integer;
// If this type crosses an eightbyte boundary, it should be
// split.
- uint64_t EB_Real = (OffsetBase) / 64;
- uint64_t EB_Imag = (OffsetBase + Size - 1) / 64;
- if (EB_Real != EB_Imag)
+ uint64_t EB_Lo = (OffsetBase) / 64;
+ uint64_t EB_Hi = (OffsetBase + Size - 1) / 64;
+ if (EB_Lo != EB_Hi)
Hi = Lo;
} else if (Size == 64) {
// gcc passes <1 x double> in memory. :(
@@ -2178,7 +2451,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const {
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(Ty);
}
bool X86_64ABIInfo::IsIllegalVectorType(QualType Ty) const {
@@ -2212,7 +2485,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
}
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
// Compute the byval alignment. We specify the alignment of the byval in all
// cases so that the mid-level optimizer knows the alignment of the byval.
@@ -2249,7 +2522,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
Size));
}
- return ABIArgInfo::getIndirect(Align);
+ return ABIArgInfo::getIndirect(CharUnits::fromQuantity(Align));
}
/// The ABI specifies that a value should be passed in a full vector XMM/YMM
@@ -2833,11 +3106,10 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
}
}
-static llvm::Value *EmitVAArgFromMemory(llvm::Value *VAListAddr,
- QualType Ty,
- CodeGenFunction &CGF) {
- llvm::Value *overflow_arg_area_p = CGF.Builder.CreateStructGEP(
- nullptr, VAListAddr, 2, "overflow_arg_area_p");
+static Address EmitX86_64VAArgFromMemory(CodeGenFunction &CGF,
+ Address VAListAddr, QualType Ty) {
+ Address overflow_arg_area_p = CGF.Builder.CreateStructGEP(
+ VAListAddr, 2, CharUnits::fromQuantity(8), "overflow_arg_area_p");
llvm::Value *overflow_arg_area =
CGF.Builder.CreateLoad(overflow_arg_area_p, "overflow_arg_area");
@@ -2845,19 +3117,10 @@ static llvm::Value *EmitVAArgFromMemory(llvm::Value *VAListAddr,
// byte boundary if alignment needed by type exceeds 8 byte boundary.
// It isn't stated explicitly in the standard, but in practice we use
// alignment greater than 16 where necessary.
- uint64_t Align = CGF.getContext().getTypeAlign(Ty) / 8;
- if (Align > 8) {
- // overflow_arg_area = (overflow_arg_area + align - 1) & -align;
- llvm::Value *Offset =
- llvm::ConstantInt::get(CGF.Int64Ty, Align - 1);
- overflow_arg_area = CGF.Builder.CreateGEP(overflow_arg_area, Offset);
- llvm::Value *AsInt = CGF.Builder.CreatePtrToInt(overflow_arg_area,
- CGF.Int64Ty);
- llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int64Ty, -(uint64_t)Align);
- overflow_arg_area =
- CGF.Builder.CreateIntToPtr(CGF.Builder.CreateAnd(AsInt, Mask),
- overflow_arg_area->getType(),
- "overflow_arg_area.align");
+ CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty);
+ if (Align > CharUnits::fromQuantity(8)) {
+ overflow_arg_area = emitRoundPointerUpToAlignment(CGF, overflow_arg_area,
+ Align);
}
// AMD64-ABI 3.5.7p5: Step 8. Fetch type from l->overflow_arg_area.
@@ -2879,11 +3142,11 @@ static llvm::Value *EmitVAArgFromMemory(llvm::Value *VAListAddr,
CGF.Builder.CreateStore(overflow_arg_area, overflow_arg_area_p);
// AMD64-ABI 3.5.7p5: Step 11. Return the fetched type.
- return Res;
+ return Address(Res, Align);
}
-llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
+Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
// Assume that va_list type is correct; should be pointer to LLVM type:
// struct {
// i32 gp_offset;
@@ -2893,14 +3156,14 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
// };
unsigned neededInt, neededSSE;
- Ty = CGF.getContext().getCanonicalType(Ty);
+ Ty = getContext().getCanonicalType(Ty);
ABIArgInfo AI = classifyArgumentType(Ty, 0, neededInt, neededSSE,
/*isNamedArg*/false);
// AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed
// in the registers. If not go to step 7.
if (!neededInt && !neededSSE)
- return EmitVAArgFromMemory(VAListAddr, Ty, CGF);
+ return EmitX86_64VAArgFromMemory(CGF, VAListAddr, Ty);
// AMD64-ABI 3.5.7p5: Step 2. Compute num_gp to hold the number of
// general purpose registers needed to pass type and num_fp to hold
@@ -2914,11 +3177,12 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
// register save space).
llvm::Value *InRegs = nullptr;
- llvm::Value *gp_offset_p = nullptr, *gp_offset = nullptr;
- llvm::Value *fp_offset_p = nullptr, *fp_offset = nullptr;
+ Address gp_offset_p = Address::invalid(), fp_offset_p = Address::invalid();
+ llvm::Value *gp_offset = nullptr, *fp_offset = nullptr;
if (neededInt) {
gp_offset_p =
- CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 0, "gp_offset_p");
+ CGF.Builder.CreateStructGEP(VAListAddr, 0, CharUnits::Zero(),
+ "gp_offset_p");
gp_offset = CGF.Builder.CreateLoad(gp_offset_p, "gp_offset");
InRegs = llvm::ConstantInt::get(CGF.Int32Ty, 48 - neededInt * 8);
InRegs = CGF.Builder.CreateICmpULE(gp_offset, InRegs, "fits_in_gp");
@@ -2926,7 +3190,8 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
if (neededSSE) {
fp_offset_p =
- CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 1, "fp_offset_p");
+ CGF.Builder.CreateStructGEP(VAListAddr, 1, CharUnits::fromQuantity(4),
+ "fp_offset_p");
fp_offset = CGF.Builder.CreateLoad(fp_offset_p, "fp_offset");
llvm::Value *FitsInFP =
llvm::ConstantInt::get(CGF.Int32Ty, 176 - neededSSE * 16);
@@ -2954,14 +3219,17 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
// simple assembling of a structure from scattered addresses has many more
// loads than necessary. Can we clean this up?
llvm::Type *LTy = CGF.ConvertTypeForMem(Ty);
- llvm::Value *RegAddr = CGF.Builder.CreateLoad(
- CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 3), "reg_save_area");
+ llvm::Value *RegSaveArea = CGF.Builder.CreateLoad(
+ CGF.Builder.CreateStructGEP(VAListAddr, 3, CharUnits::fromQuantity(16)),
+ "reg_save_area");
+
+ Address RegAddr = Address::invalid();
if (neededInt && neededSSE) {
// FIXME: Cleanup.
assert(AI.isDirect() && "Unexpected ABI info for mixed regs");
llvm::StructType *ST = cast<llvm::StructType>(AI.getCoerceToType());
- llvm::Value *Tmp = CGF.CreateMemTemp(Ty);
- Tmp = CGF.Builder.CreateBitCast(Tmp, ST->getPointerTo());
+ Address Tmp = CGF.CreateMemTemp(Ty);
+ Tmp = CGF.Builder.CreateElementBitCast(Tmp, ST);
assert(ST->getNumElements() == 2 && "Unexpected ABI info for mixed regs");
llvm::Type *TyLo = ST->getElementType(0);
llvm::Type *TyHi = ST->getElementType(1);
@@ -2969,57 +3237,77 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
"Unexpected ABI info for mixed regs");
llvm::Type *PTyLo = llvm::PointerType::getUnqual(TyLo);
llvm::Type *PTyHi = llvm::PointerType::getUnqual(TyHi);
- llvm::Value *GPAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset);
- llvm::Value *FPAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset);
+ llvm::Value *GPAddr = CGF.Builder.CreateGEP(RegSaveArea, gp_offset);
+ llvm::Value *FPAddr = CGF.Builder.CreateGEP(RegSaveArea, fp_offset);
llvm::Value *RegLoAddr = TyLo->isFPOrFPVectorTy() ? FPAddr : GPAddr;
llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr;
- llvm::Value *V =
- CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegLoAddr, PTyLo));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 0));
- V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegHiAddr, PTyHi));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 1));
- RegAddr = CGF.Builder.CreateBitCast(Tmp,
- llvm::PointerType::getUnqual(LTy));
+ // Copy the first element.
+ llvm::Value *V =
+ CGF.Builder.CreateDefaultAlignedLoad(
+ CGF.Builder.CreateBitCast(RegLoAddr, PTyLo));
+ CGF.Builder.CreateStore(V,
+ CGF.Builder.CreateStructGEP(Tmp, 0, CharUnits::Zero()));
+
+ // Copy the second element.
+ V = CGF.Builder.CreateDefaultAlignedLoad(
+ CGF.Builder.CreateBitCast(RegHiAddr, PTyHi));
+ CharUnits Offset = CharUnits::fromQuantity(
+ getDataLayout().getStructLayout(ST)->getElementOffset(1));
+ CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1, Offset));
+
+ RegAddr = CGF.Builder.CreateElementBitCast(Tmp, LTy);
} else if (neededInt) {
- RegAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset);
- RegAddr = CGF.Builder.CreateBitCast(RegAddr,
- llvm::PointerType::getUnqual(LTy));
+ RegAddr = Address(CGF.Builder.CreateGEP(RegSaveArea, gp_offset),
+ CharUnits::fromQuantity(8));
+ RegAddr = CGF.Builder.CreateElementBitCast(RegAddr, LTy);
// Copy to a temporary if necessary to ensure the appropriate alignment.
std::pair<CharUnits, CharUnits> SizeAlign =
- CGF.getContext().getTypeInfoInChars(Ty);
+ getContext().getTypeInfoInChars(Ty);
uint64_t TySize = SizeAlign.first.getQuantity();
- unsigned TyAlign = SizeAlign.second.getQuantity();
- if (TyAlign > 8) {
- llvm::Value *Tmp = CGF.CreateMemTemp(Ty);
- CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, 8, false);
+ CharUnits TyAlign = SizeAlign.second;
+
+ // Copy into a temporary if the type is more aligned than the
+ // register save area.
+ if (TyAlign.getQuantity() > 8) {
+ Address Tmp = CGF.CreateMemTemp(Ty);
+ CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false);
RegAddr = Tmp;
}
+
} else if (neededSSE == 1) {
- RegAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset);
- RegAddr = CGF.Builder.CreateBitCast(RegAddr,
- llvm::PointerType::getUnqual(LTy));
+ RegAddr = Address(CGF.Builder.CreateGEP(RegSaveArea, fp_offset),
+ CharUnits::fromQuantity(16));
+ RegAddr = CGF.Builder.CreateElementBitCast(RegAddr, LTy);
} else {
assert(neededSSE == 2 && "Invalid number of needed registers!");
// SSE registers are spaced 16 bytes apart in the register save
// area, we need to collect the two eightbytes together.
- llvm::Value *RegAddrLo = CGF.Builder.CreateGEP(RegAddr, fp_offset);
- llvm::Value *RegAddrHi = CGF.Builder.CreateConstGEP1_32(RegAddrLo, 16);
+ // The ABI isn't explicit about this, but it seems reasonable
+ // to assume that the slots are 16-byte aligned, since the stack is
+ // naturally 16-byte aligned and the prologue is expected to store
+ // all the SSE registers to the RSA.
+ Address RegAddrLo = Address(CGF.Builder.CreateGEP(RegSaveArea, fp_offset),
+ CharUnits::fromQuantity(16));
+ Address RegAddrHi =
+ CGF.Builder.CreateConstInBoundsByteGEP(RegAddrLo,
+ CharUnits::fromQuantity(16));
llvm::Type *DoubleTy = CGF.DoubleTy;
- llvm::Type *DblPtrTy =
- llvm::PointerType::getUnqual(DoubleTy);
llvm::StructType *ST = llvm::StructType::get(DoubleTy, DoubleTy, nullptr);
- llvm::Value *V, *Tmp = CGF.CreateMemTemp(Ty);
- Tmp = CGF.Builder.CreateBitCast(Tmp, ST->getPointerTo());
- V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrLo,
- DblPtrTy));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 0));
- V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrHi,
- DblPtrTy));
- CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(ST, Tmp, 1));
- RegAddr = CGF.Builder.CreateBitCast(Tmp,
- llvm::PointerType::getUnqual(LTy));
+ llvm::Value *V;
+ Address Tmp = CGF.CreateMemTemp(Ty);
+ Tmp = CGF.Builder.CreateElementBitCast(Tmp, ST);
+ V = CGF.Builder.CreateLoad(
+ CGF.Builder.CreateElementBitCast(RegAddrLo, DoubleTy));
+ CGF.Builder.CreateStore(V,
+ CGF.Builder.CreateStructGEP(Tmp, 0, CharUnits::Zero()));
+ V = CGF.Builder.CreateLoad(
+ CGF.Builder.CreateElementBitCast(RegAddrHi, DoubleTy));
+ CGF.Builder.CreateStore(V,
+ CGF.Builder.CreateStructGEP(Tmp, 1, CharUnits::fromQuantity(8)));
+
+ RegAddr = CGF.Builder.CreateElementBitCast(Tmp, LTy);
}
// AMD64-ABI 3.5.7p5: Step 5. Set:
@@ -3040,18 +3328,24 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
// Emit code to load the value if it was passed in memory.
CGF.EmitBlock(InMemBlock);
- llvm::Value *MemAddr = EmitVAArgFromMemory(VAListAddr, Ty, CGF);
+ Address MemAddr = EmitX86_64VAArgFromMemory(CGF, VAListAddr, Ty);
// Return the appropriate result.
CGF.EmitBlock(ContBlock);
- llvm::PHINode *ResAddr = CGF.Builder.CreatePHI(RegAddr->getType(), 2,
- "vaarg.addr");
- ResAddr->addIncoming(RegAddr, InRegBlock);
- ResAddr->addIncoming(MemAddr, InMemBlock);
+ Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, MemAddr, InMemBlock,
+ "vaarg.addr");
return ResAddr;
}
+Address X86_64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+ CGF.getContext().getTypeInfoInChars(Ty),
+ CharUnits::fromQuantity(8),
+ /*allowHigherAlign*/ false);
+}
+
ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
bool IsReturnType) const {
@@ -3063,17 +3357,18 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
TypeInfo Info = getContext().getTypeInfo(Ty);
uint64_t Width = Info.Width;
- unsigned Align = getContext().toCharUnitsFromBits(Info.Align).getQuantity();
+ CharUnits Align = getContext().toCharUnitsFromBits(Info.Align);
const RecordType *RT = Ty->getAs<RecordType>();
if (RT) {
if (!IsReturnType) {
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()))
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
}
if (RT->getDecl()->hasFlexibleArrayMember())
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
+
}
// vectorcall adds the concept of a homogenous vector aggregate, similar to
@@ -3103,7 +3398,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
// MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
// not 1, 2, 4, or 8 bytes, must be passed by reference."
if (Width > 64 || !llvm::isPowerOf2_64(Width))
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
// Otherwise, coerce it to a small integer.
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Width));
@@ -3141,43 +3436,31 @@ void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
I.info = classify(I.type, FreeSSERegs, false);
}
-llvm::Value *WinX86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- llvm::Type *BPP = CGF.Int8PtrPtrTy;
-
- CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
- "ap");
- llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
- llvm::Type *PTy =
- llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
-
- uint64_t Offset =
- llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 8);
- llvm::Value *NextAddr =
- Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset),
- "ap.next");
- Builder.CreateStore(NextAddr, VAListAddrAsBPP);
-
- return AddrTyped;
+Address WinX86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+ CGF.getContext().getTypeInfoInChars(Ty),
+ CharUnits::fromQuantity(8),
+ /*allowHigherAlign*/ false);
}
// PowerPC-32
namespace {
/// PPC32_SVR4_ABIInfo - The 32-bit PowerPC ELF (SVR4) ABI information.
class PPC32_SVR4_ABIInfo : public DefaultABIInfo {
+bool IsSoftFloatABI;
public:
- PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
+ PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, bool SoftFloatABI)
+ : DefaultABIInfo(CGT), IsSoftFloatABI(SoftFloatABI) {}
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
};
class PPC32TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- PPC32TargetCodeGenInfo(CodeGenTypes &CGT)
- : TargetCodeGenInfo(new PPC32_SVR4_ABIInfo(CGT)) {}
+ PPC32TargetCodeGenInfo(CodeGenTypes &CGT, bool SoftFloatABI)
+ : TargetCodeGenInfo(new PPC32_SVR4_ABIInfo(CGT, SoftFloatABI)) {}
int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
// This is recovered from gcc output.
@@ -3190,64 +3473,51 @@ public:
}
-llvm::Value *PPC32_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
- QualType Ty,
- CodeGenFunction &CGF) const {
+Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList,
+ QualType Ty) const {
if (const ComplexType *CTy = Ty->getAs<ComplexType>()) {
// TODO: Implement this. For now ignore.
(void)CTy;
- return nullptr;
+ return Address::invalid();
}
+ // struct __va_list_tag {
+ // unsigned char gpr;
+ // unsigned char fpr;
+ // unsigned short reserved;
+ // void *overflow_arg_area;
+ // void *reg_save_area;
+ // };
+
bool isI64 = Ty->isIntegerType() && getContext().getTypeSize(Ty) == 64;
bool isInt =
Ty->isIntegerType() || Ty->isPointerType() || Ty->isAggregateType();
- llvm::Type *CharPtr = CGF.Int8PtrTy;
- llvm::Type *CharPtrPtr = CGF.Int8PtrPtrTy;
+ bool isF64 = Ty->isFloatingType() && getContext().getTypeSize(Ty) == 64;
+
+ // All aggregates are passed indirectly? That doesn't seem consistent
+ // with the argument-lowering code.
+ bool isIndirect = Ty->isAggregateType();
CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *GPRPtr = Builder.CreateBitCast(VAListAddr, CharPtr, "gprptr");
- llvm::Value *GPRPtrAsInt = Builder.CreatePtrToInt(GPRPtr, CGF.Int32Ty);
- llvm::Value *FPRPtrAsInt =
- Builder.CreateAdd(GPRPtrAsInt, Builder.getInt32(1));
- llvm::Value *FPRPtr = Builder.CreateIntToPtr(FPRPtrAsInt, CharPtr);
- llvm::Value *OverflowAreaPtrAsInt =
- Builder.CreateAdd(FPRPtrAsInt, Builder.getInt32(3));
- llvm::Value *OverflowAreaPtr =
- Builder.CreateIntToPtr(OverflowAreaPtrAsInt, CharPtrPtr);
- llvm::Value *RegsaveAreaPtrAsInt =
- Builder.CreateAdd(OverflowAreaPtrAsInt, Builder.getInt32(4));
- llvm::Value *RegsaveAreaPtr =
- Builder.CreateIntToPtr(RegsaveAreaPtrAsInt, CharPtrPtr);
- llvm::Value *GPR = Builder.CreateLoad(GPRPtr, false, "gpr");
- // Align GPR when TY is i64.
- if (isI64) {
- llvm::Value *GPRAnd = Builder.CreateAnd(GPR, Builder.getInt8(1));
- llvm::Value *CC64 = Builder.CreateICmpEQ(GPRAnd, Builder.getInt8(1));
- llvm::Value *GPRPlusOne = Builder.CreateAdd(GPR, Builder.getInt8(1));
- GPR = Builder.CreateSelect(CC64, GPRPlusOne, GPR);
- }
- llvm::Value *FPR = Builder.CreateLoad(FPRPtr, false, "fpr");
- llvm::Value *OverflowArea =
- Builder.CreateLoad(OverflowAreaPtr, false, "overflow_area");
- llvm::Value *OverflowAreaAsInt =
- Builder.CreatePtrToInt(OverflowArea, CGF.Int32Ty);
- llvm::Value *RegsaveArea =
- Builder.CreateLoad(RegsaveAreaPtr, false, "regsave_area");
- llvm::Value *RegsaveAreaAsInt =
- Builder.CreatePtrToInt(RegsaveArea, CGF.Int32Ty);
- llvm::Value *CC =
- Builder.CreateICmpULT(isInt ? GPR : FPR, Builder.getInt8(8), "cond");
+ // The calling convention either uses 1-2 GPRs or 1 FPR.
+ Address NumRegsAddr = Address::invalid();
+ if (isInt || IsSoftFloatABI) {
+ NumRegsAddr = Builder.CreateStructGEP(VAList, 0, CharUnits::Zero(), "gpr");
+ } else {
+ NumRegsAddr = Builder.CreateStructGEP(VAList, 1, CharUnits::One(), "fpr");
+ }
- llvm::Value *RegConstant =
- Builder.CreateMul(isInt ? GPR : FPR, Builder.getInt8(isInt ? 4 : 8));
+ llvm::Value *NumRegs = Builder.CreateLoad(NumRegsAddr, "numUsedRegs");
- llvm::Value *OurReg = Builder.CreateAdd(
- RegsaveAreaAsInt, Builder.CreateSExt(RegConstant, CGF.Int32Ty));
+ // "Align" the register count when TY is i64.
+ if (isI64 || (isF64 && IsSoftFloatABI)) {
+ NumRegs = Builder.CreateAdd(NumRegs, Builder.getInt8(1));
+ NumRegs = Builder.CreateAnd(NumRegs, Builder.getInt8((uint8_t) ~1U));
+ }
- if (Ty->isFloatingType())
- OurReg = Builder.CreateAdd(OurReg, Builder.getInt32(32));
+ llvm::Value *CC =
+ Builder.CreateICmpULT(NumRegs, Builder.getInt8(8), "cond");
llvm::BasicBlock *UsingRegs = CGF.createBasicBlock("using_regs");
llvm::BasicBlock *UsingOverflow = CGF.createBasicBlock("using_overflow");
@@ -3255,39 +3525,91 @@ llvm::Value *PPC32_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
Builder.CreateCondBr(CC, UsingRegs, UsingOverflow);
- CGF.EmitBlock(UsingRegs);
+ llvm::Type *DirectTy = CGF.ConvertType(Ty);
+ if (isIndirect) DirectTy = DirectTy->getPointerTo(0);
- llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- llvm::Value *Result1 = Builder.CreateIntToPtr(OurReg, PTy);
- // Increase the GPR/FPR indexes.
- if (isInt) {
- GPR = Builder.CreateAdd(GPR, Builder.getInt8(isI64 ? 2 : 1));
- Builder.CreateStore(GPR, GPRPtr);
- } else {
- FPR = Builder.CreateAdd(FPR, Builder.getInt8(1));
- Builder.CreateStore(FPR, FPRPtr);
- }
- CGF.EmitBranch(Cont);
+ // Case 1: consume registers.
+ Address RegAddr = Address::invalid();
+ {
+ CGF.EmitBlock(UsingRegs);
+
+ Address RegSaveAreaPtr =
+ Builder.CreateStructGEP(VAList, 4, CharUnits::fromQuantity(8));
+ RegAddr = Address(Builder.CreateLoad(RegSaveAreaPtr),
+ CharUnits::fromQuantity(8));
+ assert(RegAddr.getElementType() == CGF.Int8Ty);
+
+ // Floating-point registers start after the general-purpose registers.
+ if (!(isInt || IsSoftFloatABI)) {
+ RegAddr = Builder.CreateConstInBoundsByteGEP(RegAddr,
+ CharUnits::fromQuantity(32));
+ }
+
+ // Get the address of the saved value by scaling the number of
+ // registers we've used by the number of
+ CharUnits RegSize = CharUnits::fromQuantity((isInt || IsSoftFloatABI) ? 4 : 8);
+ llvm::Value *RegOffset =
+ Builder.CreateMul(NumRegs, Builder.getInt8(RegSize.getQuantity()));
+ RegAddr = Address(Builder.CreateInBoundsGEP(CGF.Int8Ty,
+ RegAddr.getPointer(), RegOffset),
+ RegAddr.getAlignment().alignmentOfArrayElement(RegSize));
+ RegAddr = Builder.CreateElementBitCast(RegAddr, DirectTy);
+
+ // Increase the used-register count.
+ NumRegs =
+ Builder.CreateAdd(NumRegs,
+ Builder.getInt8((isI64 || (isF64 && IsSoftFloatABI)) ? 2 : 1));
+ Builder.CreateStore(NumRegs, NumRegsAddr);
+
+ CGF.EmitBranch(Cont);
+ }
+
+ // Case 2: consume space in the overflow area.
+ Address MemAddr = Address::invalid();
+ {
+ CGF.EmitBlock(UsingOverflow);
+
+ // Everything in the overflow area is rounded up to a size of at least 4.
+ CharUnits OverflowAreaAlign = CharUnits::fromQuantity(4);
+
+ CharUnits Size;
+ if (!isIndirect) {
+ auto TypeInfo = CGF.getContext().getTypeInfoInChars(Ty);
+ Size = TypeInfo.first.RoundUpToAlignment(OverflowAreaAlign);
+ } else {
+ Size = CGF.getPointerSize();
+ }
- CGF.EmitBlock(UsingOverflow);
+ Address OverflowAreaAddr =
+ Builder.CreateStructGEP(VAList, 3, CharUnits::fromQuantity(4));
+ Address OverflowArea(Builder.CreateLoad(OverflowAreaAddr, "argp.cur"),
+ OverflowAreaAlign);
+ // Round up address of argument to alignment
+ CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty);
+ if (Align > OverflowAreaAlign) {
+ llvm::Value *Ptr = OverflowArea.getPointer();
+ OverflowArea = Address(emitRoundPointerUpToAlignment(CGF, Ptr, Align),
+ Align);
+ }
+
+ MemAddr = Builder.CreateElementBitCast(OverflowArea, DirectTy);
- // Increase the overflow area.
- llvm::Value *Result2 = Builder.CreateIntToPtr(OverflowAreaAsInt, PTy);
- OverflowAreaAsInt =
- Builder.CreateAdd(OverflowAreaAsInt, Builder.getInt32(isInt ? 4 : 8));
- Builder.CreateStore(Builder.CreateIntToPtr(OverflowAreaAsInt, CharPtr),
- OverflowAreaPtr);
- CGF.EmitBranch(Cont);
+ // Increase the overflow area.
+ OverflowArea = Builder.CreateConstInBoundsByteGEP(OverflowArea, Size);
+ Builder.CreateStore(OverflowArea.getPointer(), OverflowAreaAddr);
+ CGF.EmitBranch(Cont);
+ }
CGF.EmitBlock(Cont);
- llvm::PHINode *Result = CGF.Builder.CreatePHI(PTy, 2, "vaarg.addr");
- Result->addIncoming(Result1, UsingRegs);
- Result->addIncoming(Result2, UsingOverflow);
+ // Merge the cases with a phi.
+ Address Result = emitMergePHI(CGF, RegAddr, UsingRegs, MemAddr, UsingOverflow,
+ "vaarg.addr");
- if (Ty->isAggregateType()) {
- llvm::Value *AGGPtr = Builder.CreateBitCast(Result, CharPtrPtr, "aggrptr");
- return Builder.CreateLoad(AGGPtr, false, "aggr");
+ // Load the pointer if the argument was passed indirectly.
+ if (isIndirect) {
+ Result = Address(Builder.CreateLoad(Result, "aggr"),
+ getContext().getTypeAlignInChars(Ty));
}
return Result;
@@ -3383,7 +3705,7 @@ public:
: DefaultABIInfo(CGT), Kind(Kind), HasQPX(HasQPX) {}
bool isPromotableTypeForABI(QualType Ty) const;
- bool isAlignedParamType(QualType Ty, bool &Align32) const;
+ CharUnits getParamTypeAlignment(QualType Ty) const;
ABIArgInfo classifyReturnType(QualType RetTy) const;
ABIArgInfo classifyArgumentType(QualType Ty) const;
@@ -3420,8 +3742,8 @@ public:
}
}
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
};
class PPC64_SVR4_TargetCodeGenInfo : public TargetCodeGenInfo {
@@ -3481,12 +3803,9 @@ PPC64_SVR4_ABIInfo::isPromotableTypeForABI(QualType Ty) const {
return false;
}
-/// isAlignedParamType - Determine whether a type requires 16-byte
-/// alignment in the parameter area.
-bool
-PPC64_SVR4_ABIInfo::isAlignedParamType(QualType Ty, bool &Align32) const {
- Align32 = false;
-
+/// isAlignedParamType - Determine whether a type requires 16-byte or
+/// higher alignment in the parameter area. Always returns at least 8.
+CharUnits PPC64_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const {
// Complex types are passed just like their elements.
if (const ComplexType *CTy = Ty->getAs<ComplexType>())
Ty = CTy->getElementType();
@@ -3495,11 +3814,11 @@ PPC64_SVR4_ABIInfo::isAlignedParamType(QualType Ty, bool &Align32) const {
// passed via reference, smaller types are not aligned).
if (IsQPXVectorTy(Ty)) {
if (getContext().getTypeSize(Ty) > 128)
- Align32 = true;
+ return CharUnits::fromQuantity(32);
- return true;
+ return CharUnits::fromQuantity(16);
} else if (Ty->isVectorType()) {
- return getContext().getTypeSize(Ty) == 128;
+ return CharUnits::fromQuantity(getContext().getTypeSize(Ty) == 128 ? 16 : 8);
}
// For single-element float/vector structs, we consider the whole type
@@ -3524,22 +3843,22 @@ PPC64_SVR4_ABIInfo::isAlignedParamType(QualType Ty, bool &Align32) const {
// With special case aggregates, only vector base types need alignment.
if (AlignAsType && IsQPXVectorTy(AlignAsType)) {
if (getContext().getTypeSize(AlignAsType) > 128)
- Align32 = true;
+ return CharUnits::fromQuantity(32);
- return true;
+ return CharUnits::fromQuantity(16);
} else if (AlignAsType) {
- return AlignAsType->isVectorType();
+ return CharUnits::fromQuantity(AlignAsType->isVectorType() ? 16 : 8);
}
// Otherwise, we only need alignment for any aggregate type that
// has an alignment requirement of >= 16 bytes.
if (isAggregateTypeForABI(Ty) && getContext().getTypeAlign(Ty) >= 128) {
if (HasQPX && getContext().getTypeAlign(Ty) >= 256)
- Align32 = true;
- return true;
+ return CharUnits::fromQuantity(32);
+ return CharUnits::fromQuantity(16);
}
- return false;
+ return CharUnits::fromQuantity(8);
}
/// isHomogeneousAggregate - Return true if a type is an ELFv2 homogeneous
@@ -3672,7 +3991,7 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
if (Ty->isVectorType() && !IsQPXVectorTy(Ty)) {
uint64_t Size = getContext().getTypeSize(Ty);
if (Size > 128)
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
else if (Size < 128) {
llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size);
return ABIArgInfo::getDirect(CoerceTy);
@@ -3681,12 +4000,10 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
if (isAggregateTypeForABI(Ty)) {
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
- bool Align32;
- uint64_t ABIAlign = isAlignedParamType(Ty, Align32) ?
- (Align32 ? 32 : 16) : 8;
- uint64_t TyAlign = getContext().getTypeAlign(Ty) / 8;
+ uint64_t ABIAlign = getParamTypeAlignment(Ty).getQuantity();
+ uint64_t TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity();
// ELFv2 homogeneous aggregates are passed as array types.
const Type *Base = nullptr;
@@ -3724,7 +4041,8 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
}
// All other aggregates are passed ByVal.
- return ABIArgInfo::getIndirect(ABIAlign, /*ByVal=*/true,
+ return ABIArgInfo::getIndirect(CharUnits::fromQuantity(ABIAlign),
+ /*ByVal=*/true,
/*Realign=*/TyAlign > ABIAlign);
}
@@ -3745,7 +4063,7 @@ PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const {
if (RetTy->isVectorType() && !IsQPXVectorTy(RetTy)) {
uint64_t Size = getContext().getTypeSize(RetTy);
if (Size > 128)
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
else if (Size < 128) {
llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size);
return ABIArgInfo::getDirect(CoerceTy);
@@ -3780,7 +4098,7 @@ PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const {
}
// All other aggregates are returned indirectly.
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
}
return (isPromotableTypeForABI(RetTy) ?
@@ -3788,47 +4106,12 @@ PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const {
}
// Based on ARMABIInfo::EmitVAArg, adjusted for 64-bit machine.
-llvm::Value *PPC64_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
- QualType Ty,
- CodeGenFunction &CGF) const {
- llvm::Type *BP = CGF.Int8PtrTy;
- llvm::Type *BPP = CGF.Int8PtrPtrTy;
-
- CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
- llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
-
- // Handle types that require 16-byte alignment in the parameter save area.
- bool Align32;
- if (isAlignedParamType(Ty, Align32)) {
- llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int64Ty);
- AddrAsInt = Builder.CreateAdd(AddrAsInt,
- Builder.getInt64(Align32 ? 31 : 15));
- AddrAsInt = Builder.CreateAnd(AddrAsInt,
- Builder.getInt64(Align32 ? -32 : -16));
- Addr = Builder.CreateIntToPtr(AddrAsInt, BP, "ap.align");
- }
-
- // Update the va_list pointer. The pointer should be bumped by the
- // size of the object. We can trust getTypeSize() except for a complex
- // type whose base type is smaller than a doubleword. For these, the
- // size of the object is 16 bytes; see below for further explanation.
- unsigned SizeInBytes = CGF.getContext().getTypeSize(Ty) / 8;
- QualType BaseTy;
- unsigned CplxBaseSize = 0;
+Address PPC64_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ auto TypeInfo = getContext().getTypeInfoInChars(Ty);
+ TypeInfo.second = getParamTypeAlignment(Ty);
- if (const ComplexType *CTy = Ty->getAs<ComplexType>()) {
- BaseTy = CTy->getElementType();
- CplxBaseSize = CGF.getContext().getTypeSize(BaseTy) / 8;
- if (CplxBaseSize < 8)
- SizeInBytes = 16;
- }
-
- unsigned Offset = llvm::RoundUpToAlignment(SizeInBytes, 8);
- llvm::Value *NextAddr =
- Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int64Ty, Offset),
- "ap.next");
- Builder.CreateStore(NextAddr, VAListAddrAsBPP);
+ CharUnits SlotSize = CharUnits::fromQuantity(8);
// If we have a complex type and the base type is smaller than 8 bytes,
// the ABI calls for the real and imaginary parts to be right-adjusted
@@ -3836,44 +4119,40 @@ llvm::Value *PPC64_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
// pointer to a structure with the two parts packed tightly. So generate
// loads of the real and imaginary parts relative to the va_list pointer,
// and store them to a temporary structure.
- if (CplxBaseSize && CplxBaseSize < 8) {
- llvm::Value *RealAddr = Builder.CreatePtrToInt(Addr, CGF.Int64Ty);
- llvm::Value *ImagAddr = RealAddr;
- if (CGF.CGM.getDataLayout().isBigEndian()) {
- RealAddr =
- Builder.CreateAdd(RealAddr, Builder.getInt64(8 - CplxBaseSize));
- ImagAddr =
- Builder.CreateAdd(ImagAddr, Builder.getInt64(16 - CplxBaseSize));
- } else {
- ImagAddr = Builder.CreateAdd(ImagAddr, Builder.getInt64(8));
+ if (const ComplexType *CTy = Ty->getAs<ComplexType>()) {
+ CharUnits EltSize = TypeInfo.first / 2;
+ if (EltSize < SlotSize) {
+ Address Addr = emitVoidPtrDirectVAArg(CGF, VAListAddr, CGF.Int8Ty,
+ SlotSize * 2, SlotSize,
+ SlotSize, /*AllowHigher*/ true);
+
+ Address RealAddr = Addr;
+ Address ImagAddr = RealAddr;
+ if (CGF.CGM.getDataLayout().isBigEndian()) {
+ RealAddr = CGF.Builder.CreateConstInBoundsByteGEP(RealAddr,
+ SlotSize - EltSize);
+ ImagAddr = CGF.Builder.CreateConstInBoundsByteGEP(ImagAddr,
+ 2 * SlotSize - EltSize);
+ } else {
+ ImagAddr = CGF.Builder.CreateConstInBoundsByteGEP(RealAddr, SlotSize);
+ }
+
+ llvm::Type *EltTy = CGF.ConvertTypeForMem(CTy->getElementType());
+ RealAddr = CGF.Builder.CreateElementBitCast(RealAddr, EltTy);
+ ImagAddr = CGF.Builder.CreateElementBitCast(ImagAddr, EltTy);
+ llvm::Value *Real = CGF.Builder.CreateLoad(RealAddr, ".vareal");
+ llvm::Value *Imag = CGF.Builder.CreateLoad(ImagAddr, ".vaimag");
+
+ Address Temp = CGF.CreateMemTemp(Ty, "vacplx");
+ CGF.EmitStoreOfComplex({Real, Imag}, CGF.MakeAddrLValue(Temp, Ty),
+ /*init*/ true);
+ return Temp;
}
- llvm::Type *PBaseTy = llvm::PointerType::getUnqual(CGF.ConvertType(BaseTy));
- RealAddr = Builder.CreateIntToPtr(RealAddr, PBaseTy);
- ImagAddr = Builder.CreateIntToPtr(ImagAddr, PBaseTy);
- llvm::Value *Real = Builder.CreateLoad(RealAddr, false, ".vareal");
- llvm::Value *Imag = Builder.CreateLoad(ImagAddr, false, ".vaimag");
- llvm::AllocaInst *Ptr =
- CGF.CreateTempAlloca(CGT.ConvertTypeForMem(Ty), "vacplx");
- llvm::Value *RealPtr =
- Builder.CreateStructGEP(Ptr->getAllocatedType(), Ptr, 0, ".real");
- llvm::Value *ImagPtr =
- Builder.CreateStructGEP(Ptr->getAllocatedType(), Ptr, 1, ".imag");
- Builder.CreateStore(Real, RealPtr, false);
- Builder.CreateStore(Imag, ImagPtr, false);
- return Ptr;
- }
-
- // If the argument is smaller than 8 bytes, it is right-adjusted in
- // its doubleword slot. Adjust the pointer to pick it up from the
- // correct offset.
- if (SizeInBytes < 8 && CGF.CGM.getDataLayout().isBigEndian()) {
- llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int64Ty);
- AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt64(8 - SizeInBytes));
- Addr = Builder.CreateIntToPtr(AddrAsInt, BP);
- }
-
- llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- return Builder.CreateBitCast(Addr, PTy);
+ }
+
+ // Otherwise, just use the general rule.
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*Indirect*/ false,
+ TypeInfo, SlotSize, /*AllowHigher*/ true);
}
static bool
@@ -3971,14 +4250,14 @@ private:
it.info = classifyArgumentType(it.type);
}
- llvm::Value *EmitDarwinVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const;
+ Address EmitDarwinVAArg(Address VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
- llvm::Value *EmitAAPCSVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const;
+ Address EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override {
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override {
return isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF)
: EmitAAPCSVAArg(VAListAddr, Ty, CGF);
}
@@ -4021,7 +4300,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
llvm::VectorType::get(llvm::Type::getInt32Ty(getVMContext()), 4);
return ABIArgInfo::getDirect(ResType);
}
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
}
if (!isAggregateTypeForABI(Ty)) {
@@ -4037,8 +4316,8 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
// Structures with either a non-trivial destructor or a non-trivial
// copy constructor are always indirect.
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
- return ABIArgInfo::getIndirect(0, /*ByVal=*/RAA ==
- CGCXXABI::RAA_DirectInMemory);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA ==
+ CGCXXABI::RAA_DirectInMemory);
}
// Empty records are always ignored on Darwin, but actually passed in C++ mode
@@ -4073,7 +4352,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size));
}
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
}
ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const {
@@ -4082,7 +4361,7 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const {
// Large vector types should be returned via memory.
if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128)
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
if (!isAggregateTypeForABI(RetTy)) {
// Treat an enum type as its underlying type.
@@ -4118,7 +4397,7 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const {
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size));
}
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
}
/// isIllegalVectorType - check whether the vector type is legal for AArch64.
@@ -4156,7 +4435,7 @@ bool AArch64ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base,
return Members <= 4;
}
-llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
+Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr,
QualType Ty,
CodeGenFunction &CGF) const {
ABIArgInfo AI = classifyArgumentType(Ty);
@@ -4190,24 +4469,32 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg");
llvm::BasicBlock *OnStackBlock = CGF.createBasicBlock("vaarg.on_stack");
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end");
- auto &Ctx = CGF.getContext();
- llvm::Value *reg_offs_p = nullptr, *reg_offs = nullptr;
+ auto TyInfo = getContext().getTypeInfoInChars(Ty);
+ CharUnits TyAlign = TyInfo.second;
+
+ Address reg_offs_p = Address::invalid();
+ llvm::Value *reg_offs = nullptr;
int reg_top_index;
- int RegSize = IsIndirect ? 8 : getContext().getTypeSize(Ty) / 8;
+ CharUnits reg_top_offset;
+ int RegSize = IsIndirect ? 8 : TyInfo.first.getQuantity();
if (!IsFPR) {
// 3 is the field number of __gr_offs
reg_offs_p =
- CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 3, "gr_offs_p");
+ CGF.Builder.CreateStructGEP(VAListAddr, 3, CharUnits::fromQuantity(24),
+ "gr_offs_p");
reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "gr_offs");
reg_top_index = 1; // field number for __gr_top
+ reg_top_offset = CharUnits::fromQuantity(8);
RegSize = llvm::RoundUpToAlignment(RegSize, 8);
} else {
// 4 is the field number of __vr_offs.
reg_offs_p =
- CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 4, "vr_offs_p");
+ CGF.Builder.CreateStructGEP(VAListAddr, 4, CharUnits::fromQuantity(28),
+ "vr_offs_p");
reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "vr_offs");
reg_top_index = 2; // field number for __vr_top
+ reg_top_offset = CharUnits::fromQuantity(16);
RegSize = 16 * NumRegs;
}
@@ -4232,8 +4519,8 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
// Integer arguments may need to correct register alignment (for example a
// "struct { __int128 a; };" gets passed in x_2N, x_{2N+1}). In this case we
// align __gr_offs to calculate the potential address.
- if (!IsFPR && !IsIndirect && Ctx.getTypeAlign(Ty) > 64) {
- int Align = Ctx.getTypeAlign(Ty) / 8;
+ if (!IsFPR && !IsIndirect && TyAlign.getQuantity() > 8) {
+ int Align = TyAlign.getQuantity();
reg_offs = CGF.Builder.CreateAdd(
reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, Align - 1),
@@ -4244,6 +4531,9 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
}
// Update the gr_offs/vr_offs pointer for next call to va_arg on this va_list.
+ // The fact that this is done unconditionally reflects the fact that
+ // allocating an argument to the stack also uses up all the remaining
+ // registers of the appropriate kind.
llvm::Value *NewOffset = nullptr;
NewOffset = CGF.Builder.CreateAdd(
reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, RegSize), "new_reg_offs");
@@ -4265,13 +4555,14 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
// registers. First start the appropriate block:
CGF.EmitBlock(InRegBlock);
- llvm::Value *reg_top_p = nullptr, *reg_top = nullptr;
- reg_top_p = CGF.Builder.CreateStructGEP(nullptr, VAListAddr, reg_top_index,
- "reg_top_p");
+ llvm::Value *reg_top = nullptr;
+ Address reg_top_p = CGF.Builder.CreateStructGEP(VAListAddr, reg_top_index,
+ reg_top_offset, "reg_top_p");
reg_top = CGF.Builder.CreateLoad(reg_top_p, "reg_top");
- llvm::Value *BaseAddr = CGF.Builder.CreateGEP(reg_top, reg_offs);
- llvm::Value *RegAddr = nullptr;
- llvm::Type *MemTy = llvm::PointerType::getUnqual(CGF.ConvertTypeForMem(Ty));
+ Address BaseAddr(CGF.Builder.CreateInBoundsGEP(reg_top, reg_offs),
+ CharUnits::fromQuantity(IsFPR ? 16 : 8));
+ Address RegAddr = Address::invalid();
+ llvm::Type *MemTy = CGF.ConvertTypeForMem(Ty);
if (IsIndirect) {
// If it's been passed indirectly (actually a struct), whatever we find from
@@ -4288,43 +4579,45 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
// qN+1, ...). We reload and store into a temporary local variable
// contiguously.
assert(!IsIndirect && "Homogeneous aggregates should be passed directly");
+ auto BaseTyInfo = getContext().getTypeInfoInChars(QualType(Base, 0));
llvm::Type *BaseTy = CGF.ConvertType(QualType(Base, 0));
llvm::Type *HFATy = llvm::ArrayType::get(BaseTy, NumMembers);
- llvm::AllocaInst *Tmp = CGF.CreateTempAlloca(HFATy);
+ Address Tmp = CGF.CreateTempAlloca(HFATy,
+ std::max(TyAlign, BaseTyInfo.second));
+
+ // On big-endian platforms, the value will be right-aligned in its slot.
int Offset = 0;
+ if (CGF.CGM.getDataLayout().isBigEndian() &&
+ BaseTyInfo.first.getQuantity() < 16)
+ Offset = 16 - BaseTyInfo.first.getQuantity();
- if (CGF.CGM.getDataLayout().isBigEndian() && Ctx.getTypeSize(Base) < 128)
- Offset = 16 - Ctx.getTypeSize(Base) / 8;
for (unsigned i = 0; i < NumMembers; ++i) {
- llvm::Value *BaseOffset =
- llvm::ConstantInt::get(CGF.Int32Ty, 16 * i + Offset);
- llvm::Value *LoadAddr = CGF.Builder.CreateGEP(BaseAddr, BaseOffset);
- LoadAddr = CGF.Builder.CreateBitCast(
- LoadAddr, llvm::PointerType::getUnqual(BaseTy));
- llvm::Value *StoreAddr =
- CGF.Builder.CreateStructGEP(Tmp->getAllocatedType(), Tmp, i);
+ CharUnits BaseOffset = CharUnits::fromQuantity(16 * i + Offset);
+ Address LoadAddr =
+ CGF.Builder.CreateConstInBoundsByteGEP(BaseAddr, BaseOffset);
+ LoadAddr = CGF.Builder.CreateElementBitCast(LoadAddr, BaseTy);
+
+ Address StoreAddr =
+ CGF.Builder.CreateConstArrayGEP(Tmp, i, BaseTyInfo.first);
llvm::Value *Elem = CGF.Builder.CreateLoad(LoadAddr);
CGF.Builder.CreateStore(Elem, StoreAddr);
}
- RegAddr = CGF.Builder.CreateBitCast(Tmp, MemTy);
+ RegAddr = CGF.Builder.CreateElementBitCast(Tmp, MemTy);
} else {
- // Otherwise the object is contiguous in memory
- unsigned BeAlign = reg_top_index == 2 ? 16 : 8;
- if (CGF.CGM.getDataLayout().isBigEndian() &&
- (IsHFA || !isAggregateTypeForABI(Ty)) &&
- Ctx.getTypeSize(Ty) < (BeAlign * 8)) {
- int Offset = BeAlign - Ctx.getTypeSize(Ty) / 8;
- BaseAddr = CGF.Builder.CreatePtrToInt(BaseAddr, CGF.Int64Ty);
+ // Otherwise the object is contiguous in memory.
- BaseAddr = CGF.Builder.CreateAdd(
- BaseAddr, llvm::ConstantInt::get(CGF.Int64Ty, Offset), "align_be");
-
- BaseAddr = CGF.Builder.CreateIntToPtr(BaseAddr, CGF.Int8PtrTy);
+ // It might be right-aligned in its slot.
+ CharUnits SlotSize = BaseAddr.getAlignment();
+ if (CGF.CGM.getDataLayout().isBigEndian() && !IsIndirect &&
+ (IsHFA || !isAggregateTypeForABI(Ty)) &&
+ TyInfo.first < SlotSize) {
+ CharUnits Offset = SlotSize - TyInfo.first;
+ BaseAddr = CGF.Builder.CreateConstInBoundsByteGEP(BaseAddr, Offset);
}
- RegAddr = CGF.Builder.CreateBitCast(BaseAddr, MemTy);
+ RegAddr = CGF.Builder.CreateElementBitCast(BaseAddr, MemTy);
}
CGF.EmitBranch(ContBlock);
@@ -4334,55 +4627,51 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
//=======================================
CGF.EmitBlock(OnStackBlock);
- llvm::Value *stack_p = nullptr, *OnStackAddr = nullptr;
- stack_p = CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 0, "stack_p");
- OnStackAddr = CGF.Builder.CreateLoad(stack_p, "stack");
+ Address stack_p = CGF.Builder.CreateStructGEP(VAListAddr, 0,
+ CharUnits::Zero(), "stack_p");
+ llvm::Value *OnStackPtr = CGF.Builder.CreateLoad(stack_p, "stack");
- // Again, stack arguments may need realigmnent. In this case both integer and
+ // Again, stack arguments may need realignment. In this case both integer and
// floating-point ones might be affected.
- if (!IsIndirect && Ctx.getTypeAlign(Ty) > 64) {
- int Align = Ctx.getTypeAlign(Ty) / 8;
+ if (!IsIndirect && TyAlign.getQuantity() > 8) {
+ int Align = TyAlign.getQuantity();
- OnStackAddr = CGF.Builder.CreatePtrToInt(OnStackAddr, CGF.Int64Ty);
+ OnStackPtr = CGF.Builder.CreatePtrToInt(OnStackPtr, CGF.Int64Ty);
- OnStackAddr = CGF.Builder.CreateAdd(
- OnStackAddr, llvm::ConstantInt::get(CGF.Int64Ty, Align - 1),
+ OnStackPtr = CGF.Builder.CreateAdd(
+ OnStackPtr, llvm::ConstantInt::get(CGF.Int64Ty, Align - 1),
"align_stack");
- OnStackAddr = CGF.Builder.CreateAnd(
- OnStackAddr, llvm::ConstantInt::get(CGF.Int64Ty, -Align),
+ OnStackPtr = CGF.Builder.CreateAnd(
+ OnStackPtr, llvm::ConstantInt::get(CGF.Int64Ty, -Align),
"align_stack");
- OnStackAddr = CGF.Builder.CreateIntToPtr(OnStackAddr, CGF.Int8PtrTy);
+ OnStackPtr = CGF.Builder.CreateIntToPtr(OnStackPtr, CGF.Int8PtrTy);
}
+ Address OnStackAddr(OnStackPtr,
+ std::max(CharUnits::fromQuantity(8), TyAlign));
- uint64_t StackSize;
+ // All stack slots are multiples of 8 bytes.
+ CharUnits StackSlotSize = CharUnits::fromQuantity(8);
+ CharUnits StackSize;
if (IsIndirect)
- StackSize = 8;
+ StackSize = StackSlotSize;
else
- StackSize = Ctx.getTypeSize(Ty) / 8;
-
- // All stack slots are 8 bytes
- StackSize = llvm::RoundUpToAlignment(StackSize, 8);
+ StackSize = TyInfo.first.RoundUpToAlignment(StackSlotSize);
- llvm::Value *StackSizeC = llvm::ConstantInt::get(CGF.Int32Ty, StackSize);
+ llvm::Value *StackSizeC = CGF.Builder.getSize(StackSize);
llvm::Value *NewStack =
- CGF.Builder.CreateGEP(OnStackAddr, StackSizeC, "new_stack");
+ CGF.Builder.CreateInBoundsGEP(OnStackPtr, StackSizeC, "new_stack");
// Write the new value of __stack for the next call to va_arg
CGF.Builder.CreateStore(NewStack, stack_p);
if (CGF.CGM.getDataLayout().isBigEndian() && !isAggregateTypeForABI(Ty) &&
- Ctx.getTypeSize(Ty) < 64) {
- int Offset = 8 - Ctx.getTypeSize(Ty) / 8;
- OnStackAddr = CGF.Builder.CreatePtrToInt(OnStackAddr, CGF.Int64Ty);
-
- OnStackAddr = CGF.Builder.CreateAdd(
- OnStackAddr, llvm::ConstantInt::get(CGF.Int64Ty, Offset), "align_be");
-
- OnStackAddr = CGF.Builder.CreateIntToPtr(OnStackAddr, CGF.Int8PtrTy);
+ TyInfo.first < StackSlotSize) {
+ CharUnits Offset = StackSlotSize - TyInfo.first;
+ OnStackAddr = CGF.Builder.CreateConstInBoundsByteGEP(OnStackAddr, Offset);
}
- OnStackAddr = CGF.Builder.CreateBitCast(OnStackAddr, MemTy);
+ OnStackAddr = CGF.Builder.CreateElementBitCast(OnStackAddr, MemTy);
CGF.EmitBranch(ContBlock);
@@ -4391,75 +4680,48 @@ llvm::Value *AArch64ABIInfo::EmitAAPCSVAArg(llvm::Value *VAListAddr,
//=======================================
CGF.EmitBlock(ContBlock);
- llvm::PHINode *ResAddr = CGF.Builder.CreatePHI(MemTy, 2, "vaarg.addr");
- ResAddr->addIncoming(RegAddr, InRegBlock);
- ResAddr->addIncoming(OnStackAddr, OnStackBlock);
+ Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock,
+ OnStackAddr, OnStackBlock, "vaargs.addr");
if (IsIndirect)
- return CGF.Builder.CreateLoad(ResAddr, "vaarg.addr");
+ return Address(CGF.Builder.CreateLoad(ResAddr, "vaarg.addr"),
+ TyInfo.second);
return ResAddr;
}
-llvm::Value *AArch64ABIInfo::EmitDarwinVAArg(llvm::Value *VAListAddr,
- QualType Ty,
- CodeGenFunction &CGF) const {
- // We do not support va_arg for aggregates or illegal vector types.
- // Lower VAArg here for these cases and use the LLVM va_arg instruction for
- // other cases.
+Address AArch64ABIInfo::EmitDarwinVAArg(Address VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ // The backend's lowering doesn't support va_arg for aggregates or
+ // illegal vector types. Lower VAArg here for these cases and use
+ // the LLVM va_arg instruction for everything else.
if (!isAggregateTypeForABI(Ty) && !isIllegalVectorType(Ty))
- return nullptr;
-
- uint64_t Size = CGF.getContext().getTypeSize(Ty) / 8;
- uint64_t Align = CGF.getContext().getTypeAlign(Ty) / 8;
-
- const Type *Base = nullptr;
- uint64_t Members = 0;
- bool isHA = isHomogeneousAggregate(Ty, Base, Members);
-
- bool isIndirect = false;
- // Arguments bigger than 16 bytes which aren't homogeneous aggregates should
- // be passed indirectly.
- if (Size > 16 && !isHA) {
- isIndirect = true;
- Size = 8;
- Align = 8;
- }
+ return Address::invalid();
- llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
- llvm::Type *BPP = llvm::PointerType::getUnqual(BP);
-
- CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
- llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+ CharUnits SlotSize = CharUnits::fromQuantity(8);
+ // Empty records are ignored for parameter passing purposes.
if (isEmptyRecord(getContext(), Ty, true)) {
- // These are ignored for parameter passing purposes.
- llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- return Builder.CreateBitCast(Addr, PTy);
+ Address Addr(CGF.Builder.CreateLoad(VAListAddr, "ap.cur"), SlotSize);
+ Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty));
+ return Addr;
}
- const uint64_t MinABIAlign = 8;
- if (Align > MinABIAlign) {
- llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int32Ty, Align - 1);
- Addr = Builder.CreateGEP(Addr, Offset);
- llvm::Value *AsInt = Builder.CreatePtrToInt(Addr, CGF.Int64Ty);
- llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int64Ty, ~(Align - 1));
- llvm::Value *Aligned = Builder.CreateAnd(AsInt, Mask);
- Addr = Builder.CreateIntToPtr(Aligned, BP, "ap.align");
- }
-
- uint64_t Offset = llvm::RoundUpToAlignment(Size, MinABIAlign);
- llvm::Value *NextAddr = Builder.CreateGEP(
- Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset), "ap.next");
- Builder.CreateStore(NextAddr, VAListAddrAsBPP);
+ // The size of the actual thing passed, which might end up just
+ // being a pointer for indirect types.
+ auto TyInfo = getContext().getTypeInfoInChars(Ty);
- if (isIndirect)
- Addr = Builder.CreateLoad(Builder.CreateBitCast(Addr, BPP));
- llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
+ // Arguments bigger than 16 bytes which aren't homogeneous
+ // aggregates should be passed indirectly.
+ bool IsIndirect = false;
+ if (TyInfo.first.getQuantity() > 16) {
+ const Type *Base = nullptr;
+ uint64_t Members = 0;
+ IsIndirect = !isHomogeneousAggregate(Ty, Base, Members);
+ }
- return AddrTyped;
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
+ TyInfo, SlotSize, /*AllowHigherAlign*/ true);
}
//===----------------------------------------------------------------------===//
@@ -4473,7 +4735,8 @@ public:
enum ABIKind {
APCS = 0,
AAPCS = 1,
- AAPCS_VFP
+ AAPCS_VFP = 2,
+ AAPCS16_VFP = 3,
};
private:
@@ -4507,6 +4770,11 @@ public:
}
}
+ bool isAndroid() const {
+ return (getTarget().getTriple().getEnvironment() ==
+ llvm::Triple::Android);
+ }
+
ABIKind getABIKind() const { return Kind; }
private:
@@ -4520,8 +4788,8 @@ private:
void computeInfo(CGFunctionInfo &FI) const override;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
llvm::CallingConv::ID getLLVMDefaultCC() const;
llvm::CallingConv::ID getABIDefaultCC() const;
@@ -4561,7 +4829,7 @@ public:
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override {
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD)
return;
@@ -4583,7 +4851,8 @@ public:
Fn->addFnAttr("interrupt", Kind);
- if (cast<ARMABIInfo>(getABIInfo()).getABIKind() == ARMABIInfo::APCS)
+ ARMABIInfo::ABIKind ABI = cast<ARMABIInfo>(getABIInfo()).getABIKind();
+ if (ABI == ARMABIInfo::APCS)
return;
// AAPCS guarantees that sp will be 8-byte aligned on any public interface,
@@ -4649,7 +4918,7 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
/// Return the default calling convention that LLVM will use.
llvm::CallingConv::ID ARMABIInfo::getLLVMDefaultCC() const {
// The default calling convention that LLVM will infer.
- if (isEABIHF())
+ if (isEABIHF() || getTarget().getTriple().isWatchOS())
return llvm::CallingConv::ARM_AAPCS_VFP;
else if (isEABI())
return llvm::CallingConv::ARM_AAPCS;
@@ -4664,6 +4933,7 @@ llvm::CallingConv::ID ARMABIInfo::getABIDefaultCC() const {
case APCS: return llvm::CallingConv::ARM_APCS;
case AAPCS: return llvm::CallingConv::ARM_AAPCS;
case AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP;
+ case AAPCS16_VFP: return llvm::CallingConv::ARM_AAPCS_VFP;
}
llvm_unreachable("bad ABI kind");
}
@@ -4677,8 +4947,20 @@ void ARMABIInfo::setCCs() {
if (abiCC != getLLVMDefaultCC())
RuntimeCC = abiCC;
- BuiltinCC = (getABIKind() == APCS ?
- llvm::CallingConv::ARM_APCS : llvm::CallingConv::ARM_AAPCS);
+ // AAPCS apparently requires runtime support functions to be soft-float, but
+ // that's almost certainly for historic reasons (Thumb1 not supporting VFP
+ // most likely). It's more convenient for AAPCS16_VFP to be hard-float.
+ switch (getABIKind()) {
+ case APCS:
+ case AAPCS16_VFP:
+ if (abiCC != getLLVMDefaultCC())
+ BuiltinCC = abiCC;
+ break;
+ case AAPCS:
+ case AAPCS_VFP:
+ BuiltinCC = llvm::CallingConv::ARM_AAPCS;
+ break;
+ }
}
ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
@@ -4712,7 +4994,17 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
llvm::Type::getInt32Ty(getVMContext()), 4);
return ABIArgInfo::getDirect(ResType);
}
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
+ }
+
+ // __fp16 gets passed as if it were an int or float, but with the top 16 bits
+ // unspecified. This is not done for OpenCL as it handles the half type
+ // natively, and does not need to interwork with AAPCS code.
+ if (Ty->isHalfType() && !getContext().getLangOpts().OpenCL) {
+ llvm::Type *ResType = IsEffectivelyAAPCS_VFP ?
+ llvm::Type::getFloatTy(getVMContext()) :
+ llvm::Type::getInt32Ty(getVMContext());
+ return ABIArgInfo::getDirect(ResType);
}
if (!isAggregateTypeForABI(Ty)) {
@@ -4726,7 +5018,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
}
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
}
// Ignore empty records.
@@ -4743,6 +5035,27 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
// Base can be a floating-point or a vector.
return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
}
+ } else if (getABIKind() == ARMABIInfo::AAPCS16_VFP) {
+ // WatchOS does have homogeneous aggregates. Note that we intentionally use
+ // this convention even for a variadic function: the backend will use GPRs
+ // if needed.
+ const Type *Base = nullptr;
+ uint64_t Members = 0;
+ if (isHomogeneousAggregate(Ty, Base, Members)) {
+ assert(Base && Members <= 4 && "unexpected homogeneous aggregate");
+ llvm::Type *Ty =
+ llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members);
+ return ABIArgInfo::getDirect(Ty, 0, nullptr, false);
+ }
+ }
+
+ if (getABIKind() == ARMABIInfo::AAPCS16_VFP &&
+ getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(16)) {
+ // WatchOS is adopting the 64-bit AAPCS rule on composite types: if they're
+ // bigger than 128-bits, they get placed in space allocated by the caller,
+ // and a pointer is passed.
+ return ABIArgInfo::getIndirect(
+ CharUnits::fromQuantity(getContext().getTypeAlign(Ty) / 8), false);
}
// Support byval for ARM.
@@ -4756,8 +5069,10 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
ABIAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8);
if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64)) {
- return ABIArgInfo::getIndirect(ABIAlign, /*ByVal=*/true,
- /*Realign=*/TyAlign > ABIAlign);
+ assert(getABIKind() != ARMABIInfo::AAPCS16_VFP && "unexpected byval");
+ return ABIArgInfo::getIndirect(CharUnits::fromQuantity(ABIAlign),
+ /*ByVal=*/true,
+ /*Realign=*/TyAlign > ABIAlign);
}
// Otherwise, pass by coercing to a structure of the appropriate size.
@@ -4863,14 +5178,25 @@ static bool isIntegerLikeType(QualType Ty, ASTContext &Context,
ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
bool isVariadic) const {
- bool IsEffectivelyAAPCS_VFP = getABIKind() == AAPCS_VFP && !isVariadic;
+ bool IsEffectivelyAAPCS_VFP =
+ (getABIKind() == AAPCS_VFP || getABIKind() == AAPCS16_VFP) && !isVariadic;
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
// Large vector types should be returned via memory.
if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128) {
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
+ }
+
+ // __fp16 gets returned as if it were an int or float, but with the top 16
+ // bits unspecified. This is not done for OpenCL as it handles the half type
+ // natively, and does not need to interwork with AAPCS code.
+ if (RetTy->isHalfType() && !getContext().getLangOpts().OpenCL) {
+ llvm::Type *ResType = IsEffectivelyAAPCS_VFP ?
+ llvm::Type::getFloatTy(getVMContext()) :
+ llvm::Type::getInt32Ty(getVMContext());
+ return ABIArgInfo::getDirect(ResType);
}
if (!isAggregateTypeForABI(RetTy)) {
@@ -4907,7 +5233,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
}
// Otherwise return in memory.
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
}
// Otherwise this is an AAPCS variant.
@@ -4918,7 +5244,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
// Check for homogeneous aggregates with AAPCS-VFP.
if (IsEffectivelyAAPCS_VFP) {
const Type *Base = nullptr;
- uint64_t Members;
+ uint64_t Members = 0;
if (isHomogeneousAggregate(RetTy, Base, Members)) {
assert(Base && "Base class should be set for homogeneous aggregate");
// Homogeneous Aggregates are returned directly.
@@ -4940,22 +5266,39 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
if (Size <= 16)
return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
+ } else if (Size <= 128 && getABIKind() == AAPCS16_VFP) {
+ llvm::Type *Int32Ty = llvm::Type::getInt32Ty(getVMContext());
+ llvm::Type *CoerceTy =
+ llvm::ArrayType::get(Int32Ty, llvm::RoundUpToAlignment(Size, 32) / 32);
+ return ABIArgInfo::getDirect(CoerceTy);
}
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
}
/// isIllegalVector - check whether Ty is an illegal vector type.
bool ARMABIInfo::isIllegalVectorType(QualType Ty) const {
- if (const VectorType *VT = Ty->getAs<VectorType>()) {
- // Check whether VT is legal.
- unsigned NumElements = VT->getNumElements();
- uint64_t Size = getContext().getTypeSize(VT);
- // NumElements should be power of 2.
- if ((NumElements & (NumElements - 1)) != 0)
- return true;
- // Size should be greater than 32 bits.
- return Size <= 32;
+ if (const VectorType *VT = Ty->getAs<VectorType> ()) {
+ if (isAndroid()) {
+ // Android shipped using Clang 3.1, which supported a slightly different
+ // vector ABI. The primary differences were that 3-element vector types
+ // were legal, and so were sub 32-bit vectors (i.e. <2 x i8>). This path
+ // accepts that legacy behavior for Android only.
+ // Check whether VT is legal.
+ unsigned NumElements = VT->getNumElements();
+ // NumElements should be power of 2 or equal to 3.
+ if (!llvm::isPowerOf2_32(NumElements) && NumElements != 3)
+ return true;
+ } else {
+ // Check whether VT is legal.
+ unsigned NumElements = VT->getNumElements();
+ uint64_t Size = getContext().getTypeSize(VT);
+ // NumElements should be power of 2.
+ if (!llvm::isPowerOf2_32(NumElements))
+ return true;
+ // Size should be greater than 32 bits.
+ return Size <= 32;
+ }
}
return false;
}
@@ -4981,80 +5324,53 @@ bool ARMABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base,
return Members <= 4;
}
-llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- llvm::Type *BP = CGF.Int8PtrTy;
- llvm::Type *BPP = CGF.Int8PtrPtrTy;
-
- CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
- llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+Address ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ CharUnits SlotSize = CharUnits::fromQuantity(4);
+ // Empty records are ignored for parameter passing purposes.
if (isEmptyRecord(getContext(), Ty, true)) {
- // These are ignored for parameter passing purposes.
- llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- return Builder.CreateBitCast(Addr, PTy);
+ Address Addr(CGF.Builder.CreateLoad(VAListAddr), SlotSize);
+ Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty));
+ return Addr;
}
- uint64_t Size = CGF.getContext().getTypeSize(Ty) / 8;
- uint64_t TyAlign = CGF.getContext().getTypeAlign(Ty) / 8;
- bool IsIndirect = false;
+ auto TyInfo = getContext().getTypeInfoInChars(Ty);
+ CharUnits TyAlignForABI = TyInfo.second;
- // The ABI alignment for 64-bit or 128-bit vectors is 8 for AAPCS and 4 for
- // APCS. For AAPCS, the ABI alignment is at least 4-byte and at most 8-byte.
- if (getABIKind() == ARMABIInfo::AAPCS_VFP ||
- getABIKind() == ARMABIInfo::AAPCS)
- TyAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8);
- else
- TyAlign = 4;
// Use indirect if size of the illegal vector is bigger than 16 bytes.
- if (isIllegalVectorType(Ty) && Size > 16) {
+ bool IsIndirect = false;
+ const Type *Base = nullptr;
+ uint64_t Members = 0;
+ if (TyInfo.first > CharUnits::fromQuantity(16) && isIllegalVectorType(Ty)) {
IsIndirect = true;
- Size = 4;
- TyAlign = 4;
- }
- // Handle address alignment for ABI alignment > 4 bytes.
- if (TyAlign > 4) {
- assert((TyAlign & (TyAlign - 1)) == 0 &&
- "Alignment is not power of 2!");
- llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int32Ty);
- AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt32(TyAlign - 1));
- AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt32(~(TyAlign - 1)));
- Addr = Builder.CreateIntToPtr(AddrAsInt, BP, "ap.align");
- }
+ // ARMv7k passes structs bigger than 16 bytes indirectly, in space
+ // allocated by the caller.
+ } else if (TyInfo.first > CharUnits::fromQuantity(16) &&
+ getABIKind() == ARMABIInfo::AAPCS16_VFP &&
+ !isHomogeneousAggregate(Ty, Base, Members)) {
+ IsIndirect = true;
- uint64_t Offset =
- llvm::RoundUpToAlignment(Size, 4);
- llvm::Value *NextAddr =
- Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset),
- "ap.next");
- Builder.CreateStore(NextAddr, VAListAddrAsBPP);
+ // Otherwise, bound the type's ABI alignment.
+ // The ABI alignment for 64-bit or 128-bit vectors is 8 for AAPCS and 4 for
+ // APCS. For AAPCS, the ABI alignment is at least 4-byte and at most 8-byte.
+ // Our callers should be prepared to handle an under-aligned address.
+ } else if (getABIKind() == ARMABIInfo::AAPCS_VFP ||
+ getABIKind() == ARMABIInfo::AAPCS) {
+ TyAlignForABI = std::max(TyAlignForABI, CharUnits::fromQuantity(4));
+ TyAlignForABI = std::min(TyAlignForABI, CharUnits::fromQuantity(8));
+ } else if (getABIKind() == ARMABIInfo::AAPCS16_VFP) {
+ // ARMv7k allows type alignment up to 16 bytes.
+ TyAlignForABI = std::max(TyAlignForABI, CharUnits::fromQuantity(4));
+ TyAlignForABI = std::min(TyAlignForABI, CharUnits::fromQuantity(16));
+ } else {
+ TyAlignForABI = CharUnits::fromQuantity(4);
+ }
+ TyInfo.second = TyAlignForABI;
- if (IsIndirect)
- Addr = Builder.CreateLoad(Builder.CreateBitCast(Addr, BPP));
- else if (TyAlign < CGF.getContext().getTypeAlign(Ty) / 8) {
- // We can't directly cast ap.cur to pointer to a vector type, since ap.cur
- // may not be correctly aligned for the vector type. We create an aligned
- // temporary space and copy the content over from ap.cur to the temporary
- // space. This is necessary if the natural alignment of the type is greater
- // than the ABI alignment.
- llvm::Type *I8PtrTy = Builder.getInt8PtrTy();
- CharUnits CharSize = getContext().getTypeSizeInChars(Ty);
- llvm::Value *AlignedTemp = CGF.CreateTempAlloca(CGF.ConvertType(Ty),
- "var.align");
- llvm::Value *Dst = Builder.CreateBitCast(AlignedTemp, I8PtrTy);
- llvm::Value *Src = Builder.CreateBitCast(Addr, I8PtrTy);
- Builder.CreateMemCpy(Dst, Src,
- llvm::ConstantInt::get(CGF.IntPtrTy, CharSize.getQuantity()),
- TyAlign, false);
- Addr = AlignedTemp; //The content is in aligned location.
- }
- llvm::Type *PTy =
- llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
-
- return AddrTyped;
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, TyInfo,
+ SlotSize, /*AllowHigherAlign*/ true);
}
//===----------------------------------------------------------------------===//
@@ -5071,8 +5387,8 @@ public:
ABIArgInfo classifyArgumentType(QualType Ty) const;
void computeInfo(CGFunctionInfo &FI) const override;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CFG) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
};
class NVPTXTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -5111,7 +5427,7 @@ ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty) const {
// Return aggregates type as indirect by value
if (isAggregateTypeForABI(Ty))
- return ABIArgInfo::getIndirect(0, /* byval */ true);
+ return getNaturalAlignIndirect(Ty, /* byval */ true);
return (Ty->isPromotableIntegerType() ?
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
@@ -5130,15 +5446,15 @@ void NVPTXABIInfo::computeInfo(CGFunctionInfo &FI) const {
FI.setEffectiveCallingConvention(getRuntimeCC());
}
-llvm::Value *NVPTXABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CFG) const {
+Address NVPTXABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
llvm_unreachable("NVPTX does not support varargs");
}
void NVPTXTargetCodeGenInfo::
setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const{
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
llvm::Function *F = cast<llvm::Function>(GV);
@@ -5232,8 +5548,8 @@ public:
I.info = classifyArgumentType(I.type);
}
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
};
class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -5334,8 +5650,8 @@ QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const {
return Ty;
}
-llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
+Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
// Assume that va_list type is correct; should be pointer to LLVM type:
// struct {
// i64 __gpr;
@@ -5347,59 +5663,69 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
// Every non-vector argument occupies 8 bytes and is passed by preference
// in either GPRs or FPRs. Vector arguments occupy 8 or 16 bytes and are
// always passed on the stack.
- Ty = CGF.getContext().getCanonicalType(Ty);
+ Ty = getContext().getCanonicalType(Ty);
+ auto TyInfo = getContext().getTypeInfoInChars(Ty);
llvm::Type *ArgTy = CGF.ConvertTypeForMem(Ty);
- llvm::Type *APTy = llvm::PointerType::getUnqual(ArgTy);
+ llvm::Type *DirectTy = ArgTy;
ABIArgInfo AI = classifyArgumentType(Ty);
bool IsIndirect = AI.isIndirect();
bool InFPRs = false;
bool IsVector = false;
- unsigned UnpaddedBitSize;
+ CharUnits UnpaddedSize;
+ CharUnits DirectAlign;
if (IsIndirect) {
- APTy = llvm::PointerType::getUnqual(APTy);
- UnpaddedBitSize = 64;
+ DirectTy = llvm::PointerType::getUnqual(DirectTy);
+ UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8);
} else {
if (AI.getCoerceToType())
ArgTy = AI.getCoerceToType();
InFPRs = ArgTy->isFloatTy() || ArgTy->isDoubleTy();
IsVector = ArgTy->isVectorTy();
- UnpaddedBitSize = getContext().getTypeSize(Ty);
+ UnpaddedSize = TyInfo.first;
+ DirectAlign = TyInfo.second;
}
- unsigned PaddedBitSize = (IsVector && UnpaddedBitSize > 64) ? 128 : 64;
- assert((UnpaddedBitSize <= PaddedBitSize) && "Invalid argument size.");
+ CharUnits PaddedSize = CharUnits::fromQuantity(8);
+ if (IsVector && UnpaddedSize > PaddedSize)
+ PaddedSize = CharUnits::fromQuantity(16);
+ assert((UnpaddedSize <= PaddedSize) && "Invalid argument size.");
- unsigned PaddedSize = PaddedBitSize / 8;
- unsigned Padding = (PaddedBitSize - UnpaddedBitSize) / 8;
+ CharUnits Padding = (PaddedSize - UnpaddedSize);
llvm::Type *IndexTy = CGF.Int64Ty;
- llvm::Value *PaddedSizeV = llvm::ConstantInt::get(IndexTy, PaddedSize);
+ llvm::Value *PaddedSizeV =
+ llvm::ConstantInt::get(IndexTy, PaddedSize.getQuantity());
if (IsVector) {
// Work out the address of a vector argument on the stack.
// Vector arguments are always passed in the high bits of a
// single (8 byte) or double (16 byte) stack slot.
- llvm::Value *OverflowArgAreaPtr =
- CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 2,
+ Address OverflowArgAreaPtr =
+ CGF.Builder.CreateStructGEP(VAListAddr, 2, CharUnits::fromQuantity(16),
"overflow_arg_area_ptr");
- llvm::Value *OverflowArgArea =
- CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area");
- llvm::Value *MemAddr =
- CGF.Builder.CreateBitCast(OverflowArgArea, APTy, "mem_addr");
+ Address OverflowArgArea =
+ Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"),
+ TyInfo.second);
+ Address MemAddr =
+ CGF.Builder.CreateElementBitCast(OverflowArgArea, DirectTy, "mem_addr");
// Update overflow_arg_area_ptr pointer
llvm::Value *NewOverflowArgArea =
- CGF.Builder.CreateGEP(OverflowArgArea, PaddedSizeV, "overflow_arg_area");
+ CGF.Builder.CreateGEP(OverflowArgArea.getPointer(), PaddedSizeV,
+ "overflow_arg_area");
CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr);
return MemAddr;
}
- unsigned MaxRegs, RegCountField, RegSaveIndex, RegPadding;
+ assert(PaddedSize.getQuantity() == 8);
+
+ unsigned MaxRegs, RegCountField, RegSaveIndex;
+ CharUnits RegPadding;
if (InFPRs) {
MaxRegs = 4; // Maximum of 4 FPR arguments
RegCountField = 1; // __fpr
RegSaveIndex = 16; // save offset for f0
- RegPadding = 0; // floats are passed in the high bits of an FPR
+ RegPadding = CharUnits(); // floats are passed in the high bits of an FPR
} else {
MaxRegs = 5; // Maximum of 5 GPR arguments
RegCountField = 0; // __gpr
@@ -5407,8 +5733,9 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
RegPadding = Padding; // values are passed in the low bits of a GPR
}
- llvm::Value *RegCountPtr = CGF.Builder.CreateStructGEP(
- nullptr, VAListAddr, RegCountField, "reg_count_ptr");
+ Address RegCountPtr = CGF.Builder.CreateStructGEP(
+ VAListAddr, RegCountField, RegCountField * CharUnits::fromQuantity(8),
+ "reg_count_ptr");
llvm::Value *RegCount = CGF.Builder.CreateLoad(RegCountPtr, "reg_count");
llvm::Value *MaxRegsV = llvm::ConstantInt::get(IndexTy, MaxRegs);
llvm::Value *InRegs = CGF.Builder.CreateICmpULT(RegCount, MaxRegsV,
@@ -5426,17 +5753,20 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
llvm::Value *ScaledRegCount =
CGF.Builder.CreateMul(RegCount, PaddedSizeV, "scaled_reg_count");
llvm::Value *RegBase =
- llvm::ConstantInt::get(IndexTy, RegSaveIndex * PaddedSize + RegPadding);
+ llvm::ConstantInt::get(IndexTy, RegSaveIndex * PaddedSize.getQuantity()
+ + RegPadding.getQuantity());
llvm::Value *RegOffset =
CGF.Builder.CreateAdd(ScaledRegCount, RegBase, "reg_offset");
- llvm::Value *RegSaveAreaPtr =
- CGF.Builder.CreateStructGEP(nullptr, VAListAddr, 3, "reg_save_area_ptr");
+ Address RegSaveAreaPtr =
+ CGF.Builder.CreateStructGEP(VAListAddr, 3, CharUnits::fromQuantity(24),
+ "reg_save_area_ptr");
llvm::Value *RegSaveArea =
CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area");
- llvm::Value *RawRegAddr =
- CGF.Builder.CreateGEP(RegSaveArea, RegOffset, "raw_reg_addr");
- llvm::Value *RegAddr =
- CGF.Builder.CreateBitCast(RawRegAddr, APTy, "reg_addr");
+ Address RawRegAddr(CGF.Builder.CreateGEP(RegSaveArea, RegOffset,
+ "raw_reg_addr"),
+ PaddedSize);
+ Address RegAddr =
+ CGF.Builder.CreateElementBitCast(RawRegAddr, DirectTy, "reg_addr");
// Update the register count
llvm::Value *One = llvm::ConstantInt::get(IndexTy, 1);
@@ -5449,30 +5779,31 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CGF.EmitBlock(InMemBlock);
// Work out the address of a stack argument.
- llvm::Value *OverflowArgAreaPtr = CGF.Builder.CreateStructGEP(
- nullptr, VAListAddr, 2, "overflow_arg_area_ptr");
- llvm::Value *OverflowArgArea =
- CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area");
- llvm::Value *PaddingV = llvm::ConstantInt::get(IndexTy, Padding);
- llvm::Value *RawMemAddr =
- CGF.Builder.CreateGEP(OverflowArgArea, PaddingV, "raw_mem_addr");
- llvm::Value *MemAddr =
- CGF.Builder.CreateBitCast(RawMemAddr, APTy, "mem_addr");
+ Address OverflowArgAreaPtr = CGF.Builder.CreateStructGEP(
+ VAListAddr, 2, CharUnits::fromQuantity(16), "overflow_arg_area_ptr");
+ Address OverflowArgArea =
+ Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"),
+ PaddedSize);
+ Address RawMemAddr =
+ CGF.Builder.CreateConstByteGEP(OverflowArgArea, Padding, "raw_mem_addr");
+ Address MemAddr =
+ CGF.Builder.CreateElementBitCast(RawMemAddr, DirectTy, "mem_addr");
// Update overflow_arg_area_ptr pointer
llvm::Value *NewOverflowArgArea =
- CGF.Builder.CreateGEP(OverflowArgArea, PaddedSizeV, "overflow_arg_area");
+ CGF.Builder.CreateGEP(OverflowArgArea.getPointer(), PaddedSizeV,
+ "overflow_arg_area");
CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr);
CGF.EmitBranch(ContBlock);
// Return the appropriate result.
CGF.EmitBlock(ContBlock);
- llvm::PHINode *ResAddr = CGF.Builder.CreatePHI(APTy, 2, "va_arg.addr");
- ResAddr->addIncoming(RegAddr, InRegBlock);
- ResAddr->addIncoming(MemAddr, InMemBlock);
+ Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock,
+ MemAddr, InMemBlock, "va_arg.addr");
if (IsIndirect)
- return CGF.Builder.CreateLoad(ResAddr, "indirect_arg");
+ ResAddr = Address(CGF.Builder.CreateLoad(ResAddr, "indirect_arg"),
+ TyInfo.second);
return ResAddr;
}
@@ -5483,7 +5814,7 @@ ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
if (isVectorArgumentType(RetTy))
return ABIArgInfo::getDirect();
if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64)
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
return (isPromotableIntegerType(RetTy) ?
ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
@@ -5491,7 +5822,7 @@ ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
// Handle the generic C++ ABI.
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
// Integers and enums are extended to full register width.
if (isPromotableIntegerType(Ty))
@@ -5508,7 +5839,7 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
// Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly.
if (Size != 8 && Size != 16 && Size != 32 && Size != 64)
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
// Handle small structures.
if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -5516,7 +5847,7 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
// fail the size test above.
const RecordDecl *RD = RT->getDecl();
if (RD->hasFlexibleArrayMember())
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
// The structure is passed as an unextended integer, a float, or a double.
llvm::Type *PassTy;
@@ -5533,7 +5864,7 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
// Non-structure compounds are passed indirectly.
if (isCompoundType(Ty))
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
return ABIArgInfo::getDirect(nullptr);
}
@@ -5557,7 +5888,7 @@ public:
void MSP430TargetCodeGenInfo::setTargetAttributes(const Decl *D,
llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
if (const MSP430InterruptAttr *attr = FD->getAttr<MSP430InterruptAttr>()) {
// Handle 'interrupt' attribute:
llvm::Function *F = cast<llvm::Function>(GV);
@@ -5598,8 +5929,8 @@ public:
ABIArgInfo classifyReturnType(QualType RetTy) const;
ABIArgInfo classifyArgumentType(QualType RetTy, uint64_t &Offset) const;
void computeInfo(CGFunctionInfo &FI) const override;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
bool shouldSignExtUnsignedType(QualType Ty) const override;
};
@@ -5616,7 +5947,7 @@ public:
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override {
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
llvm::Function *Fn = cast<llvm::Function>(GV);
if (FD->hasAttr<Mips16Attr>()) {
@@ -5625,6 +5956,26 @@ public:
else if (FD->hasAttr<NoMips16Attr>()) {
Fn->addFnAttr("nomips16");
}
+
+ const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>();
+ if (!Attr)
+ return;
+
+ const char *Kind;
+ switch (Attr->getInterrupt()) {
+ case MipsInterruptAttr::eic: Kind = "eic"; break;
+ case MipsInterruptAttr::sw0: Kind = "sw0"; break;
+ case MipsInterruptAttr::sw1: Kind = "sw1"; break;
+ case MipsInterruptAttr::hw0: Kind = "hw0"; break;
+ case MipsInterruptAttr::hw1: Kind = "hw1"; break;
+ case MipsInterruptAttr::hw2: Kind = "hw2"; break;
+ case MipsInterruptAttr::hw3: Kind = "hw3"; break;
+ case MipsInterruptAttr::hw4: Kind = "hw4"; break;
+ case MipsInterruptAttr::hw5: Kind = "hw5"; break;
+ }
+
+ Fn->addFnAttr("interrupt", Kind);
+
}
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
@@ -5738,7 +6089,7 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
Offset = OrigOffset + MinABIStackAlignInBytes;
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
}
// If we have reached here, aggregates are passed directly by coercing to
@@ -5832,7 +6183,7 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
}
}
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
}
// Treat an enum type as its underlying type.
@@ -5855,52 +6206,55 @@ void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
I.info = classifyArgumentType(I.type, Offset);
}
-llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- llvm::Type *BP = CGF.Int8PtrTy;
- llvm::Type *BPP = CGF.Int8PtrPtrTy;
+Address MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType OrigTy) const {
+ QualType Ty = OrigTy;
// Integer arguments are promoted to 32-bit on O32 and 64-bit on N32/N64.
// Pointers are also promoted in the same way but this only matters for N32.
unsigned SlotSizeInBits = IsO32 ? 32 : 64;
unsigned PtrWidth = getTarget().getPointerWidth(0);
+ bool DidPromote = false;
if ((Ty->isIntegerType() &&
- CGF.getContext().getIntWidth(Ty) < SlotSizeInBits) ||
+ getContext().getIntWidth(Ty) < SlotSizeInBits) ||
(Ty->isPointerType() && PtrWidth < SlotSizeInBits)) {
- Ty = CGF.getContext().getIntTypeForBitwidth(SlotSizeInBits,
- Ty->isSignedIntegerType());
+ DidPromote = true;
+ Ty = getContext().getIntTypeForBitwidth(SlotSizeInBits,
+ Ty->isSignedIntegerType());
}
- CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
- llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
- int64_t TypeAlign =
- std::min(getContext().getTypeAlign(Ty) / 8, StackAlignInBytes);
- llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- llvm::Value *AddrTyped;
- llvm::IntegerType *IntTy = (PtrWidth == 32) ? CGF.Int32Ty : CGF.Int64Ty;
-
- if (TypeAlign > MinABIStackAlignInBytes) {
- llvm::Value *AddrAsInt = CGF.Builder.CreatePtrToInt(Addr, IntTy);
- llvm::Value *Inc = llvm::ConstantInt::get(IntTy, TypeAlign - 1);
- llvm::Value *Mask = llvm::ConstantInt::get(IntTy, -TypeAlign);
- llvm::Value *Add = CGF.Builder.CreateAdd(AddrAsInt, Inc);
- llvm::Value *And = CGF.Builder.CreateAnd(Add, Mask);
- AddrTyped = CGF.Builder.CreateIntToPtr(And, PTy);
- }
- else
- AddrTyped = Builder.CreateBitCast(Addr, PTy);
+ auto TyInfo = getContext().getTypeInfoInChars(Ty);
+
+ // The alignment of things in the argument area is never larger than
+ // StackAlignInBytes.
+ TyInfo.second =
+ std::min(TyInfo.second, CharUnits::fromQuantity(StackAlignInBytes));
+
+ // MinABIStackAlignInBytes is the size of argument slots on the stack.
+ CharUnits ArgSlotSize = CharUnits::fromQuantity(MinABIStackAlignInBytes);
+
+ Address Addr = emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+ TyInfo, ArgSlotSize, /*AllowHigherAlign*/ true);
+
- llvm::Value *AlignedAddr = Builder.CreateBitCast(AddrTyped, BP);
- TypeAlign = std::max((unsigned)TypeAlign, MinABIStackAlignInBytes);
- unsigned ArgSizeInBits = CGF.getContext().getTypeSize(Ty);
- uint64_t Offset = llvm::RoundUpToAlignment(ArgSizeInBits / 8, TypeAlign);
- llvm::Value *NextAddr =
- Builder.CreateGEP(AlignedAddr, llvm::ConstantInt::get(IntTy, Offset),
- "ap.next");
- Builder.CreateStore(NextAddr, VAListAddrAsBPP);
+ // If there was a promotion, "unpromote" into a temporary.
+ // TODO: can we just use a pointer into a subset of the original slot?
+ if (DidPromote) {
+ Address Temp = CGF.CreateMemTemp(OrigTy, "vaarg.promotion-temp");
+ llvm::Value *Promoted = CGF.Builder.CreateLoad(Addr);
- return AddrTyped;
+ // Truncate down to the right width.
+ llvm::Type *IntTy = (OrigTy->isIntegerType() ? Temp.getElementType()
+ : CGF.IntPtrTy);
+ llvm::Value *V = CGF.Builder.CreateTrunc(Promoted, IntTy);
+ if (OrigTy->isPointerType())
+ V = CGF.Builder.CreateIntToPtr(V, Temp.getElementType());
+
+ CGF.Builder.CreateStore(V, Temp);
+ Addr = Temp;
+ }
+
+ return Addr;
}
bool MipsABIInfo::shouldSignExtUnsignedType(QualType Ty) const {
@@ -5960,7 +6314,7 @@ public:
void TCETargetCodeGenInfo::setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD) return;
llvm::Function *F = cast<llvm::Function>(GV);
@@ -6022,8 +6376,8 @@ private:
void computeInfo(CGFunctionInfo &FI) const override;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
};
class HexagonTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -6060,11 +6414,11 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty) const {
return ABIArgInfo::getIgnore();
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
uint64_t Size = getContext().getTypeSize(Ty);
if (Size > 64)
- return ABIArgInfo::getIndirect(0, /*ByVal=*/true);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
// Pass in the smallest viable integer type.
else if (Size > 32)
return ABIArgInfo::getDirect(llvm::Type::getInt64Ty(getVMContext()));
@@ -6082,7 +6436,7 @@ ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const {
// Large vector types should be returned via memory.
if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 64)
- return ABIArgInfo::getIndirect(0);
+ return getNaturalAlignIndirect(RetTy);
if (!isAggregateTypeForABI(RetTy)) {
// Treat an enum type as its underlying type.
@@ -6110,30 +6464,16 @@ ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const {
return ABIArgInfo::getDirect(llvm::Type::getInt64Ty(getVMContext()));
}
- return ABIArgInfo::getIndirect(0, /*ByVal=*/true);
+ return getNaturalAlignIndirect(RetTy, /*ByVal=*/true);
}
-llvm::Value *HexagonABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- // FIXME: Need to handle alignment
- llvm::Type *BPP = CGF.Int8PtrPtrTy;
-
- CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
- "ap");
- llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
- llvm::Type *PTy =
- llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
- llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
-
- uint64_t Offset =
- llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 4);
- llvm::Value *NextAddr =
- Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset),
- "ap.next");
- Builder.CreateStore(NextAddr, VAListAddrAsBPP);
-
- return AddrTyped;
+Address HexagonABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
+ // FIXME: Someone needs to audit that this handle alignment correctly.
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+ getContext().getTypeInfoInChars(Ty),
+ CharUnits::fromQuantity(4),
+ /*AllowHigherAlign*/ true);
}
//===----------------------------------------------------------------------===//
@@ -6156,7 +6496,7 @@ void AMDGPUTargetCodeGenInfo::setTargetAttributes(
const Decl *D,
llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const {
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD)
return;
@@ -6210,8 +6550,8 @@ public:
private:
ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const;
void computeInfo(CGFunctionInfo &FI) const override;
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
// Coercion type builder for structs passed in registers. The coercion type
// serves two purposes:
@@ -6331,7 +6671,7 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
// Anything too big to fit in registers is passed with an explicit indirect
// pointer / sret pointer.
if (Size > SizeLimit)
- return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+ return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
@@ -6348,7 +6688,7 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
// If a C++ object has either a non-trivial copy constructor or a non-trivial
// destructor, it is passed with an explicit indirect pointer / sret pointer.
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
- return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+ return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
// This is a small aggregate type that should be passed in registers.
// Build a coercion type from the LLVM struct type.
@@ -6369,55 +6709,59 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
return ABIArgInfo::getDirect(CoerceTy);
}
-llvm::Value *SparcV9ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
+Address SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
ABIArgInfo AI = classifyType(Ty, 16 * 8);
llvm::Type *ArgTy = CGT.ConvertType(Ty);
if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
AI.setCoerceToType(ArgTy);
- llvm::Type *BPP = CGF.Int8PtrPtrTy;
+ CharUnits SlotSize = CharUnits::fromQuantity(8);
+
CGBuilderTy &Builder = CGF.Builder;
- llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
- llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+ Address Addr(Builder.CreateLoad(VAListAddr, "ap.cur"), SlotSize);
llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy);
- llvm::Value *ArgAddr;
- unsigned Stride;
+ auto TypeInfo = getContext().getTypeInfoInChars(Ty);
+
+ Address ArgAddr = Address::invalid();
+ CharUnits Stride;
switch (AI.getKind()) {
case ABIArgInfo::Expand:
case ABIArgInfo::InAlloca:
llvm_unreachable("Unsupported ABI kind for va_arg");
- case ABIArgInfo::Extend:
- Stride = 8;
- ArgAddr = Builder
- .CreateConstGEP1_32(Addr, 8 - getDataLayout().getTypeAllocSize(ArgTy),
- "extend");
+ case ABIArgInfo::Extend: {
+ Stride = SlotSize;
+ CharUnits Offset = SlotSize - TypeInfo.first;
+ ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, "extend");
break;
+ }
- case ABIArgInfo::Direct:
- Stride = getDataLayout().getTypeAllocSize(AI.getCoerceToType());
+ case ABIArgInfo::Direct: {
+ auto AllocSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType());
+ Stride = CharUnits::fromQuantity(AllocSize).RoundUpToAlignment(SlotSize);
ArgAddr = Addr;
break;
+ }
case ABIArgInfo::Indirect:
- Stride = 8;
- ArgAddr = Builder.CreateBitCast(Addr,
- llvm::PointerType::getUnqual(ArgPtrTy),
- "indirect");
- ArgAddr = Builder.CreateLoad(ArgAddr, "indirect.arg");
+ Stride = SlotSize;
+ ArgAddr = Builder.CreateElementBitCast(Addr, ArgPtrTy, "indirect");
+ ArgAddr = Address(Builder.CreateLoad(ArgAddr, "indirect.arg"),
+ TypeInfo.second);
break;
case ABIArgInfo::Ignore:
- return llvm::UndefValue::get(ArgPtrTy);
+ return Address(llvm::UndefValue::get(ArgPtrTy), TypeInfo.second);
}
// Update VAList.
- Addr = Builder.CreateConstGEP1_32(Addr, Stride, "ap.next");
- Builder.CreateStore(Addr, VAListAddrAsBPP);
+ llvm::Value *NextPtr =
+ Builder.CreateConstInBoundsByteGEP(Addr.getPointer(), Stride, "ap.next");
+ Builder.CreateStore(NextPtr, VAListAddr);
- return Builder.CreatePointerCast(ArgAddr, ArgPtrTy, "arg.addr");
+ return Builder.CreateBitCast(ArgAddr, ArgPtrTy, "arg.addr");
}
void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {
@@ -6552,7 +6896,7 @@ class TypeStringCache {
unsigned IncompleteCount; // Number of Incomplete entries in the Map.
unsigned IncompleteUsedCount; // Number of IncompleteUsed entries in the Map.
public:
- TypeStringCache() : IncompleteCount(0), IncompleteUsedCount(0) {};
+ TypeStringCache() : IncompleteCount(0), IncompleteUsedCount(0) {}
void addIncomplete(const IdentifierInfo *ID, std::string StubEnc);
bool removeIncomplete(const IdentifierInfo *ID);
void addIfComplete(const IdentifierInfo *ID, StringRef Str,
@@ -6566,8 +6910,8 @@ class FieldEncoding {
bool HasName;
std::string Enc;
public:
- FieldEncoding(bool b, SmallStringEnc &e) : HasName(b), Enc(e.c_str()) {};
- StringRef str() {return Enc.c_str();};
+ FieldEncoding(bool b, SmallStringEnc &e) : HasName(b), Enc(e.c_str()) {}
+ StringRef str() {return Enc.c_str();}
bool operator<(const FieldEncoding &rhs) const {
if (HasName != rhs.HasName) return HasName;
return Enc < rhs.Enc;
@@ -6577,8 +6921,8 @@ public:
class XCoreABIInfo : public DefaultABIInfo {
public:
XCoreABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const override;
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const override;
};
class XCoreTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -6592,52 +6936,53 @@ public:
} // End anonymous namespace.
-llvm::Value *XCoreABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
+Address XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+ QualType Ty) const {
CGBuilderTy &Builder = CGF.Builder;
// Get the VAList.
- llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr,
- CGF.Int8PtrPtrTy);
- llvm::Value *AP = Builder.CreateLoad(VAListAddrAsBPP);
+ CharUnits SlotSize = CharUnits::fromQuantity(4);
+ Address AP(Builder.CreateLoad(VAListAddr), SlotSize);
// Handle the argument.
ABIArgInfo AI = classifyArgumentType(Ty);
+ CharUnits TypeAlign = getContext().getTypeAlignInChars(Ty);
llvm::Type *ArgTy = CGT.ConvertType(Ty);
if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
AI.setCoerceToType(ArgTy);
llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy);
- llvm::Value *Val;
- uint64_t ArgSize = 0;
+
+ Address Val = Address::invalid();
+ CharUnits ArgSize = CharUnits::Zero();
switch (AI.getKind()) {
case ABIArgInfo::Expand:
case ABIArgInfo::InAlloca:
llvm_unreachable("Unsupported ABI kind for va_arg");
case ABIArgInfo::Ignore:
- Val = llvm::UndefValue::get(ArgPtrTy);
- ArgSize = 0;
+ Val = Address(llvm::UndefValue::get(ArgPtrTy), TypeAlign);
+ ArgSize = CharUnits::Zero();
break;
case ABIArgInfo::Extend:
case ABIArgInfo::Direct:
- Val = Builder.CreatePointerCast(AP, ArgPtrTy);
- ArgSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType());
- if (ArgSize < 4)
- ArgSize = 4;
+ Val = Builder.CreateBitCast(AP, ArgPtrTy);
+ ArgSize = CharUnits::fromQuantity(
+ getDataLayout().getTypeAllocSize(AI.getCoerceToType()));
+ ArgSize = ArgSize.RoundUpToAlignment(SlotSize);
break;
case ABIArgInfo::Indirect:
- llvm::Value *ArgAddr;
- ArgAddr = Builder.CreateBitCast(AP, llvm::PointerType::getUnqual(ArgPtrTy));
- ArgAddr = Builder.CreateLoad(ArgAddr);
- Val = Builder.CreatePointerCast(ArgAddr, ArgPtrTy);
- ArgSize = 4;
+ Val = Builder.CreateElementBitCast(AP, ArgPtrTy);
+ Val = Address(Builder.CreateLoad(Val), TypeAlign);
+ ArgSize = SlotSize;
break;
}
// Increment the VAList.
- if (ArgSize) {
- llvm::Value *APN = Builder.CreateConstGEP1_32(AP, ArgSize);
- Builder.CreateStore(APN, VAListAddrAsBPP);
+ if (!ArgSize.isZero()) {
+ llvm::Value *APN =
+ Builder.CreateConstInBoundsByteGEP(AP.getPointer(), ArgSize);
+ Builder.CreateStore(APN, VAListAddr);
}
+
return Val;
}
@@ -6781,9 +7126,7 @@ static bool extractFieldType(SmallVectorImpl<FieldEncoding> &FE,
if (Field->isBitField()) {
Enc += "b(";
llvm::raw_svector_ostream OS(Enc);
- OS.resync();
OS << Field->getBitWidthValue(CGM.getContext());
- OS.flush();
Enc += ':';
}
if (!appendType(Enc, Field->getType(), CGM, TSC))
@@ -6897,7 +7240,7 @@ static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET,
/// This is done prior to appending the type's encoding.
static void appendQualifier(SmallStringEnc &Enc, QualType QT) {
// Qualifiers are emitted in alphabetical order.
- static const char *Table[] = {"","c:","r:","cr:","v:","cv:","rv:","crv:"};
+ static const char *const Table[]={"","c:","r:","cr:","v:","cv:","rv:","crv:"};
int Lookup = 0;
if (QT.isConstQualified())
Lookup += 1<<0;
@@ -7138,6 +7481,10 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
return *(TheTargetCodeGenInfo = new AArch64TargetCodeGenInfo(Types, Kind));
}
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ return *(TheTargetCodeGenInfo = new WebAssemblyTargetCodeGenInfo(Types));
+
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
@@ -7150,8 +7497,11 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
}
ARMABIInfo::ABIKind Kind = ARMABIInfo::AAPCS;
- if (getTarget().getABI() == "apcs-gnu")
+ StringRef ABIStr = getTarget().getABI();
+ if (ABIStr == "apcs-gnu")
Kind = ARMABIInfo::APCS;
+ else if (ABIStr == "aapcs16")
+ Kind = ARMABIInfo::AAPCS16_VFP;
else if (CodeGenOpts.FloatABI == "hard" ||
(CodeGenOpts.FloatABI != "soft" &&
Triple.getEnvironment() == llvm::Triple::GNUEABIHF))
@@ -7161,7 +7511,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
}
case llvm::Triple::ppc:
- return *(TheTargetCodeGenInfo = new PPC32TargetCodeGenInfo(Types));
+ return *(TheTargetCodeGenInfo =
+ new PPC32TargetCodeGenInfo(Types, CodeGenOpts.FloatABI == "soft"));
case llvm::Triple::ppc64:
if (Triple.isOSBinFormatELF()) {
PPC64_SVR4_ABIInfo::ABIKind Kind = PPC64_SVR4_ABIInfo::ELFv1;
@@ -7202,18 +7553,19 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
case llvm::Triple::x86: {
bool IsDarwinVectorABI = Triple.isOSDarwin();
- bool IsSmallStructInRegABI =
+ bool RetSmallStructInRegABI =
X86_32TargetCodeGenInfo::isStructReturnInRegABI(Triple, CodeGenOpts);
bool IsWin32FloatStructABI = Triple.isOSWindows() && !Triple.isOSCygMing();
if (Triple.getOS() == llvm::Triple::Win32) {
return *(TheTargetCodeGenInfo = new WinX86_32TargetCodeGenInfo(
- Types, IsDarwinVectorABI, IsSmallStructInRegABI,
+ Types, IsDarwinVectorABI, RetSmallStructInRegABI,
IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters));
} else {
return *(TheTargetCodeGenInfo = new X86_32TargetCodeGenInfo(
- Types, IsDarwinVectorABI, IsSmallStructInRegABI,
- IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters));
+ Types, IsDarwinVectorABI, RetSmallStructInRegABI,
+ IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters,
+ CodeGenOpts.FloatABI == "soft"));
}
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
index 95275d5..87b4704 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.h
@@ -47,7 +47,7 @@ class TargetCodeGenInfo {
public:
// WARNING: Acquires the ownership of ABIInfo.
- TargetCodeGenInfo(ABIInfo *info = 0) : Info(info) {}
+ TargetCodeGenInfo(ABIInfo *info = nullptr) : Info(info) {}
virtual ~TargetCodeGenInfo();
/// getABIInfo() - Returns ABI info helper for the target.
@@ -219,6 +219,6 @@ public:
llvm::StringRef Value,
llvm::SmallString<32> &Opt) const {}
};
-}
+} // namespace clang
-#endif
+#endif // LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H
diff --git a/contrib/llvm/tools/clang/lib/Driver/Action.cpp b/contrib/llvm/tools/clang/lib/Driver/Action.cpp
index 3219dc1..e9490e9 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Action.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Action.cpp
@@ -8,17 +8,14 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Action.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Regex.h"
#include <cassert>
using namespace clang::driver;
using namespace llvm::opt;
-Action::~Action() {
- if (OwnsInputs) {
- for (iterator it = begin(), ie = end(); it != ie; ++it)
- delete *it;
- }
-}
+Action::~Action() {}
const char *Action::getClassName(ActionClass AC) {
switch (AC) {
@@ -51,34 +48,53 @@ InputAction::InputAction(const Arg &_Input, types::ID _Type)
void BindArchAction::anchor() {}
-BindArchAction::BindArchAction(std::unique_ptr<Action> Input,
- const char *_ArchName)
- : Action(BindArchClass, std::move(Input)), ArchName(_ArchName) {}
+BindArchAction::BindArchAction(Action *Input, const char *_ArchName)
+ : Action(BindArchClass, Input), ArchName(_ArchName) {}
+
+// Converts CUDA GPU architecture, e.g. "sm_21", to its corresponding virtual
+// compute arch, e.g. "compute_20". Returns null if the input arch is null or
+// doesn't match an existing arch.
+static const char* GpuArchToComputeName(const char *ArchName) {
+ if (!ArchName)
+ return nullptr;
+ return llvm::StringSwitch<const char *>(ArchName)
+ .Cases("sm_20", "sm_21", "compute_20")
+ .Case("sm_30", "compute_30")
+ .Case("sm_32", "compute_32")
+ .Case("sm_35", "compute_35")
+ .Case("sm_37", "compute_37")
+ .Case("sm_50", "compute_50")
+ .Case("sm_52", "compute_52")
+ .Case("sm_53", "compute_53")
+ .Default(nullptr);
+}
void CudaDeviceAction::anchor() {}
-CudaDeviceAction::CudaDeviceAction(std::unique_ptr<Action> Input,
- const char *ArchName, bool AtTopLevel)
- : Action(CudaDeviceClass, std::move(Input)), GpuArchName(ArchName),
- AtTopLevel(AtTopLevel) {}
-
-void CudaHostAction::anchor() {}
+CudaDeviceAction::CudaDeviceAction(Action *Input, const char *ArchName,
+ bool AtTopLevel)
+ : Action(CudaDeviceClass, Input), GpuArchName(ArchName),
+ AtTopLevel(AtTopLevel) {
+ assert(IsValidGpuArchName(GpuArchName));
+}
-CudaHostAction::CudaHostAction(std::unique_ptr<Action> Input,
- const ActionList &_DeviceActions)
- : Action(CudaHostClass, std::move(Input)), DeviceActions(_DeviceActions) {}
+const char *CudaDeviceAction::getComputeArchName() const {
+ return GpuArchToComputeName(GpuArchName);
+}
-CudaHostAction::~CudaHostAction() {
- for (iterator it = DeviceActions.begin(), ie = DeviceActions.end(); it != ie;
- ++it)
- delete *it;
+bool CudaDeviceAction::IsValidGpuArchName(llvm::StringRef ArchName) {
+ return GpuArchToComputeName(ArchName.data()) != nullptr;
}
+void CudaHostAction::anchor() {}
+
+CudaHostAction::CudaHostAction(Action *Input, const ActionList &DeviceActions)
+ : Action(CudaHostClass, Input), DeviceActions(DeviceActions) {}
+
void JobAction::anchor() {}
-JobAction::JobAction(ActionClass Kind, std::unique_ptr<Action> Input,
- types::ID Type)
- : Action(Kind, std::move(Input), Type) {}
+JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
+ : Action(Kind, Input, Type) {}
JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
: Action(Kind, Inputs, Type) {
@@ -86,45 +102,38 @@ JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
void PreprocessJobAction::anchor() {}
-PreprocessJobAction::PreprocessJobAction(std::unique_ptr<Action> Input,
- types::ID OutputType)
- : JobAction(PreprocessJobClass, std::move(Input), OutputType) {}
+PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
+ : JobAction(PreprocessJobClass, Input, OutputType) {}
void PrecompileJobAction::anchor() {}
-PrecompileJobAction::PrecompileJobAction(std::unique_ptr<Action> Input,
- types::ID OutputType)
- : JobAction(PrecompileJobClass, std::move(Input), OutputType) {}
+PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
+ : JobAction(PrecompileJobClass, Input, OutputType) {}
void AnalyzeJobAction::anchor() {}
-AnalyzeJobAction::AnalyzeJobAction(std::unique_ptr<Action> Input,
- types::ID OutputType)
- : JobAction(AnalyzeJobClass, std::move(Input), OutputType) {}
+AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
+ : JobAction(AnalyzeJobClass, Input, OutputType) {}
void MigrateJobAction::anchor() {}
-MigrateJobAction::MigrateJobAction(std::unique_ptr<Action> Input,
- types::ID OutputType)
- : JobAction(MigrateJobClass, std::move(Input), OutputType) {}
+MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
+ : JobAction(MigrateJobClass, Input, OutputType) {}
void CompileJobAction::anchor() {}
-CompileJobAction::CompileJobAction(std::unique_ptr<Action> Input,
- types::ID OutputType)
- : JobAction(CompileJobClass, std::move(Input), OutputType) {}
+CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
+ : JobAction(CompileJobClass, Input, OutputType) {}
void BackendJobAction::anchor() {}
-BackendJobAction::BackendJobAction(std::unique_ptr<Action> Input,
- types::ID OutputType)
- : JobAction(BackendJobClass, std::move(Input), OutputType) {}
+BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
+ : JobAction(BackendJobClass, Input, OutputType) {}
void AssembleJobAction::anchor() {}
-AssembleJobAction::AssembleJobAction(std::unique_ptr<Action> Input,
- types::ID OutputType)
- : JobAction(AssembleJobClass, std::move(Input), OutputType) {}
+AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
+ : JobAction(AssembleJobClass, Input, OutputType) {}
void LinkJobAction::anchor() {}
@@ -146,28 +155,20 @@ DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
void VerifyJobAction::anchor() {}
-VerifyJobAction::VerifyJobAction(ActionClass Kind,
- std::unique_ptr<Action> Input, types::ID Type)
- : JobAction(Kind, std::move(Input), Type) {
- assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
- "ActionClass is not a valid VerifyJobAction");
-}
-
-VerifyJobAction::VerifyJobAction(ActionClass Kind, ActionList &Inputs,
+VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
types::ID Type)
- : JobAction(Kind, Inputs, Type) {
+ : JobAction(Kind, Input, Type) {
assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
- "ActionClass is not a valid VerifyJobAction");
+ "ActionClass is not a valid VerifyJobAction");
}
void VerifyDebugInfoJobAction::anchor() {}
-VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(
- std::unique_ptr<Action> Input, types::ID Type)
- : VerifyJobAction(VerifyDebugInfoJobClass, std::move(Input), Type) {}
+VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
+ types::ID Type)
+ : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
void VerifyPCHJobAction::anchor() {}
-VerifyPCHJobAction::VerifyPCHJobAction(std::unique_ptr<Action> Input,
- types::ID Type)
- : VerifyJobAction(VerifyPCHJobClass, std::move(Input), Type) {}
+VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
+ : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
index 101d1fc..1c2eecd 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
@@ -24,8 +24,9 @@ using namespace llvm::opt;
Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
InputArgList *_Args, DerivedArgList *_TranslatedArgs)
- : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
- TranslatedArgs(_TranslatedArgs), Redirects(nullptr),
+ : TheDriver(D), DefaultToolChain(_DefaultToolChain),
+ CudaHostToolChain(&DefaultToolChain), CudaDeviceToolChain(nullptr),
+ Args(_Args), TranslatedArgs(_TranslatedArgs), Redirects(nullptr),
ForDiagnostics(false) {}
Compilation::~Compilation() {
@@ -39,11 +40,6 @@ Compilation::~Compilation() {
if (it->second != TranslatedArgs)
delete it->second;
- // Free the actions, if built.
- for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
- it != ie; ++it)
- delete *it;
-
// Free redirections of stdout/stderr.
if (Redirects) {
delete Redirects[1];
@@ -207,7 +203,8 @@ void Compilation::initCompilationForDiagnostics() {
ForDiagnostics = true;
// Free actions and jobs.
- DeleteContainerPointers(Actions);
+ Actions.clear();
+ AllActions.clear();
Jobs.clear();
// Clear temporary/results file lists.
diff --git a/contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp
index ffb1469..57bf896 100644
--- a/contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp
@@ -107,6 +107,12 @@ AddCXXStdlibLibArgs(const llvm::opt::ArgList &DriverArgs,
}
}
+clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const {
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ return Res;
+}
+
Tool *CrossWindowsToolChain::buildLinker() const {
return new tools::CrossWindows::Linker(*this);
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
index 180c412..1e0a48d 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
@@ -11,6 +11,7 @@
#include "InputInfo.h"
#include "ToolChains.h"
#include "clang/Basic/Version.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
@@ -46,9 +47,11 @@ using namespace clang;
using namespace llvm::opt;
Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
- DiagnosticsEngine &Diags)
- : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode),
- SaveTemps(SaveTempsNone), ClangExecutable(ClangExecutable),
+ DiagnosticsEngine &Diags,
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS)
+ : Opts(createDriverOptTable()), Diags(Diags), VFS(VFS), Mode(GCCMode),
+ SaveTemps(SaveTempsNone), LTOMode(LTOK_None),
+ ClangExecutable(ClangExecutable),
SysRoot(DEFAULT_SYSROOT), UseStdLib(true),
DefaultTargetTriple(DefaultTargetTriple),
DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr),
@@ -57,8 +60,13 @@ Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
CCCUsePCH(true), SuppressMissingInputWarning(false) {
+ // Provide a sane fallback if no VFS is specified.
+ if (!this->VFS)
+ this->VFS = vfs::getRealFileSystem();
+
Name = llvm::sys::path::filename(ClangExecutable);
Dir = llvm::sys::path::parent_path(ClangExecutable);
+ InstalledDir = Dir; // Provide a sensible default installed dir.
// Compute the path to the resource directory.
StringRef ClangResourceDir(CLANG_RESOURCE_DIR);
@@ -174,10 +182,8 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
} else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) {
FinalPhase = phases::Backend;
- // -c and partial CUDA compilations only run up to the assembler.
- } else if ((PhaseArg = DAL.getLastArg(options::OPT_c)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_cuda_device_only)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_cuda_host_only))) {
+ // -c compilation only runs up to the assembler.
+ } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) {
FinalPhase = phases::Assemble;
// Otherwise do everything.
@@ -203,6 +209,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
DerivedArgList *DAL = new DerivedArgList(Args);
bool HasNostdlib = Args.hasArg(options::OPT_nostdlib);
+ bool HasNodefaultlib = Args.hasArg(options::OPT_nodefaultlibs);
for (Arg *A : Args) {
// Unfortunately, we have to parse some forwarding options (-Xassembler,
// -Xlinker, -Xpreprocessor) because we either integrate their functionality
@@ -217,7 +224,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_Xlinker__no_demangle));
// Add the remaining values as Xlinker arguments.
- for (const StringRef Val : A->getValues())
+ for (StringRef Val : A->getValues())
if (Val != "--no-demangle")
DAL->AddSeparateArg(A, Opts->getOption(options::OPT_Xlinker), Val);
@@ -246,7 +253,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
StringRef Value = A->getValue();
// Rewrite unless -nostdlib is present.
- if (!HasNostdlib && Value == "stdc++") {
+ if (!HasNostdlib && !HasNodefaultlib && Value == "stdc++") {
DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_reserved_lib_stdcxx));
continue;
}
@@ -261,7 +268,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
// Pick up inputs via the -- option.
if (A->getOption().matches(options::OPT__DASH_DASH)) {
A->claim();
- for (const StringRef Val : A->getValues())
+ for (StringRef Val : A->getValues())
DAL->append(MakeInputArg(*DAL, Opts, Val));
continue;
}
@@ -327,7 +334,8 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
}
// Skip further flag support on OSes which don't support '-m32' or '-m64'.
- if (Target.getArchName() == "tce" || Target.getOS() == llvm::Triple::Minix)
+ if (Target.getArch() == llvm::Triple::tce ||
+ Target.getOS() == llvm::Triple::Minix)
return Target;
// Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'.
@@ -360,6 +368,32 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
return Target;
}
+// \brief Parse the LTO options and record the type of LTO compilation
+// based on which -f(no-)?lto(=.*)? option occurs last.
+void Driver::setLTOMode(const llvm::opt::ArgList &Args) {
+ LTOMode = LTOK_None;
+ if (!Args.hasFlag(options::OPT_flto, options::OPT_flto_EQ,
+ options::OPT_fno_lto, false))
+ return;
+
+ StringRef LTOName("full");
+
+ const Arg *A = Args.getLastArg(options::OPT_flto_EQ);
+ if (A)
+ LTOName = A->getValue();
+
+ LTOMode = llvm::StringSwitch<LTOKind>(LTOName)
+ .Case("full", LTOK_Full)
+ .Case("thin", LTOK_Thin)
+ .Default(LTOK_Unknown);
+
+ if (LTOMode == LTOK_Unknown) {
+ assert(A);
+ Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName()
+ << A->getValue();
+ }
+}
+
Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
llvm::PrettyStackTraceString CrashInfo("Compilation construction");
@@ -387,6 +421,9 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
InputArgList Args = ParseArgStrings(ArgList.slice(1));
+ // Silence driver warnings if requested
+ Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w));
+
// -no-canonical-prefixes is used very early in main.
Args.ClaimAllArgs(options::OPT_no_canonical_prefixes);
@@ -411,6 +448,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// clang-cl targets MSVC-style Win32.
llvm::Triple T(DefaultTargetTriple);
T.setOS(llvm::Triple::Win32);
+ T.setVendor(llvm::Triple::PC);
T.setEnvironment(llvm::Triple::MSVC);
DefaultTargetTriple = T.str();
}
@@ -439,6 +477,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
.Default(SaveTempsCwd);
}
+ setLTOMode(Args);
+
std::unique_ptr<llvm::opt::InputArgList> UArgs =
llvm::make_unique<InputArgList>(std::move(Args));
@@ -452,6 +492,10 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// The compilation takes ownership of Args.
Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs);
+ C->setCudaDeviceToolChain(
+ &getToolChain(C->getArgs(), llvm::Triple(TC.getTriple().isArch64Bit()
+ ? "nvptx64-nvidia-cuda"
+ : "nvptx-nvidia-cuda")));
if (!HandleImmediateArgs(*C))
return C;
@@ -462,10 +506,9 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// Construct the list of abstract actions to perform for this compilation. On
// MachO targets this uses the driver-driver and universal actions.
if (TC.getTriple().isOSBinFormatMachO())
- BuildUniversalActions(C->getDefaultToolChain(), C->getArgs(), Inputs,
- C->getActions());
+ BuildUniversalActions(*C, C->getDefaultToolChain(), Inputs);
else
- BuildActions(C->getDefaultToolChain(), C->getArgs(), Inputs,
+ BuildActions(*C, C->getDefaultToolChain(), C->getArgs(), Inputs,
C->getActions());
if (CCCPrintPhases) {
@@ -578,9 +621,9 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
// Darwin OSes this uses the driver-driver and builds universal actions.
const ToolChain &TC = C.getDefaultToolChain();
if (TC.getTriple().isOSBinFormatMachO())
- BuildUniversalActions(TC, C.getArgs(), Inputs, C.getActions());
+ BuildUniversalActions(C, TC, Inputs);
else
- BuildActions(TC, C.getArgs(), Inputs, C.getActions());
+ BuildActions(C, TC, C.getArgs(), Inputs, C.getActions());
BuildJobs(C);
@@ -656,11 +699,11 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
}
void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) {
- // Since argumentsFitWithinSystemLimits() may underestimate system's capacity
+ // Since commandLineFitsWithinSystemLimits() may underestimate system's capacity
// if the tool does not support response files, there is a chance/ that things
// will just work without a response file, so we silently just skip it.
if (Cmd.getCreator().getResponseFilesSupport() == Tool::RF_None ||
- llvm::sys::argumentsFitWithinSystemLimits(Cmd.getArguments()))
+ llvm::sys::commandLineFitsWithinSystemLimits(Cmd.getExecutable(), Cmd.getArguments()))
return;
std::string TmpName = GetTemporaryPath("response", "txt");
@@ -761,6 +804,9 @@ void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
} else
OS << "Thread model: " << TC.getThreadModel();
OS << '\n';
+
+ // Print out the install directory.
+ OS << "InstalledDir: " << InstalledDir << '\n';
}
/// PrintDiagnosticCategories - Implement the --print-diagnostic-categories
@@ -906,7 +952,7 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
os << '"' << CDA->getGpuArchName() << '"' << ", {"
<< PrintActions1(C, *CDA->begin(), Ids) << "}";
} else {
- ActionList *AL;
+ const ActionList *AL;
if (CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) {
os << "{" << PrintActions1(C, *CHA->begin(), Ids) << "}"
<< ", gpu binaries ";
@@ -914,12 +960,15 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
} else
AL = &A->getInputs();
- const char *Prefix = "{";
- for (Action *PreRequisite : *AL) {
- os << Prefix << PrintActions1(C, PreRequisite, Ids);
- Prefix = ", ";
- }
- os << "}";
+ if (AL->size()) {
+ const char *Prefix = "{";
+ for (Action *PreRequisite : *AL) {
+ os << Prefix << PrintActions1(C, PreRequisite, Ids);
+ Prefix = ", ";
+ }
+ os << "}";
+ } else
+ os << "{}";
}
unsigned Id = Ids.size();
@@ -945,16 +994,17 @@ static bool ContainsCompileOrAssembleAction(const Action *A) {
isa<AssembleJobAction>(A))
return true;
- for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it)
- if (ContainsCompileOrAssembleAction(*it))
+ for (const Action *Input : *A)
+ if (ContainsCompileOrAssembleAction(Input))
return true;
return false;
}
-void Driver::BuildUniversalActions(const ToolChain &TC, DerivedArgList &Args,
- const InputList &BAInputs,
- ActionList &Actions) const {
+void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,
+ const InputList &BAInputs) const {
+ DerivedArgList &Args = C.getArgs();
+ ActionList &Actions = C.getActions();
llvm::PrettyStackTraceString CrashInfo("Building universal build actions");
// Collect the list of architectures. Duplicates are allowed, but should only
// be handled once (in the order seen).
@@ -983,13 +1033,11 @@ void Driver::BuildUniversalActions(const ToolChain &TC, DerivedArgList &Args,
Archs.push_back(Args.MakeArgString(TC.getDefaultUniversalArchName()));
ActionList SingleActions;
- BuildActions(TC, Args, BAInputs, SingleActions);
+ BuildActions(C, TC, Args, BAInputs, SingleActions);
// Add in arch bindings for every top level action, as well as lipo and
// dsymutil steps if needed.
- for (unsigned i = 0, e = SingleActions.size(); i != e; ++i) {
- Action *Act = SingleActions[i];
-
+ for (Action* Act : SingleActions) {
// Make sure we can lipo this kind of output. If not (and it is an actual
// output) then we disallow, since we can't create an output file with the
// right name without overwriting it. We could remove this oddity by just
@@ -1001,19 +1049,15 @@ void Driver::BuildUniversalActions(const ToolChain &TC, DerivedArgList &Args,
<< types::getTypeName(Act->getType());
ActionList Inputs;
- for (unsigned i = 0, e = Archs.size(); i != e; ++i) {
- Inputs.push_back(
- new BindArchAction(std::unique_ptr<Action>(Act), Archs[i]));
- if (i != 0)
- Inputs.back()->setOwnsInputs(false);
- }
+ for (unsigned i = 0, e = Archs.size(); i != e; ++i)
+ Inputs.push_back(C.MakeAction<BindArchAction>(Act, Archs[i]));
// Lipo if necessary, we do it this way because we need to set the arch flag
// so that -Xarch_ gets overwritten.
if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing)
Actions.append(Inputs.begin(), Inputs.end());
else
- Actions.push_back(new LipoJobAction(Inputs, Act->getType()));
+ Actions.push_back(C.MakeAction<LipoJobAction>(Inputs, Act->getType()));
// Handle debug info queries.
Arg *A = Args.getLastArg(options::OPT_g_Group);
@@ -1029,15 +1073,16 @@ void Driver::BuildUniversalActions(const ToolChain &TC, DerivedArgList &Args,
ActionList Inputs;
Inputs.push_back(Actions.back());
Actions.pop_back();
- Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM));
+ Actions.push_back(
+ C.MakeAction<DsymutilJobAction>(Inputs, types::TY_dSYM));
}
// Verify the debug info output.
if (Args.hasArg(options::OPT_verify_debug_info)) {
- std::unique_ptr<Action> VerifyInput(Actions.back());
+ Action* LastAction = Actions.back();
Actions.pop_back();
- Actions.push_back(new VerifyDebugInfoJobAction(std::move(VerifyInput),
- types::TY_Nothing));
+ Actions.push_back(C.MakeAction<VerifyDebugInfoJobAction>(
+ LastAction, types::TY_Nothing));
}
}
}
@@ -1228,28 +1273,36 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
}
}
-// For each unique --cuda-gpu-arch= argument creates a TY_CUDA_DEVICE input
-// action and then wraps each in CudaDeviceAction paired with appropriate GPU
-// arch name. If we're only building device-side code, each action remains
-// independent. Otherwise we pass device-side actions as inputs to a new
-// CudaHostAction which combines both host and device side actions.
-static std::unique_ptr<Action>
-buildCudaActions(const Driver &D, const ToolChain &TC, DerivedArgList &Args,
- const Arg *InputArg, const types::ID InputType,
- std::unique_ptr<Action> Current, ActionList &Actions) {
-
- assert(InputType == types::TY_CUDA &&
- "CUDA Actions only apply to CUDA inputs.");
+// For each unique --cuda-gpu-arch= argument creates a TY_CUDA_DEVICE
+// input action and then wraps each in CudaDeviceAction paired with
+// appropriate GPU arch name. In case of partial (i.e preprocessing
+// only) or device-only compilation, each device action is added to /p
+// Actions and /p Current is released. Otherwise the function creates
+// and returns a new CudaHostAction which wraps /p Current and device
+// side actions.
+static Action *buildCudaActions(Compilation &C, DerivedArgList &Args,
+ const Arg *InputArg, Action *HostAction,
+ ActionList &Actions) {
+ Arg *PartialCompilationArg = Args.getLastArg(options::OPT_cuda_host_only,
+ options::OPT_cuda_device_only);
+ // Host-only compilation case.
+ if (PartialCompilationArg &&
+ PartialCompilationArg->getOption().matches(options::OPT_cuda_host_only))
+ return C.MakeAction<CudaHostAction>(HostAction, ActionList());
// Collect all cuda_gpu_arch parameters, removing duplicates.
SmallVector<const char *, 4> GpuArchList;
llvm::StringSet<> GpuArchNames;
for (Arg *A : Args) {
- if (A->getOption().matches(options::OPT_cuda_gpu_arch_EQ)) {
- A->claim();
- if (GpuArchNames.insert(A->getValue()).second)
- GpuArchList.push_back(A->getValue());
- }
+ if (!A->getOption().matches(options::OPT_cuda_gpu_arch_EQ))
+ continue;
+ A->claim();
+
+ const auto& Arch = A->getValue();
+ if (!CudaDeviceAction::IsValidGpuArchName(Arch))
+ C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << Arch;
+ else if (GpuArchNames.insert(Arch).second)
+ GpuArchList.push_back(Arch);
}
// Default to sm_20 which is the lowest common denominator for supported GPUs.
@@ -1259,27 +1312,27 @@ buildCudaActions(const Driver &D, const ToolChain &TC, DerivedArgList &Args,
// Replicate inputs for each GPU architecture.
Driver::InputList CudaDeviceInputs;
- for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i)
+ for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
CudaDeviceInputs.push_back(std::make_pair(types::TY_CUDA_DEVICE, InputArg));
// Build actions for all device inputs.
+ assert(C.getCudaDeviceToolChain() &&
+ "Missing toolchain for device-side compilation.");
ActionList CudaDeviceActions;
- D.BuildActions(TC, Args, CudaDeviceInputs, CudaDeviceActions);
+ C.getDriver().BuildActions(C, *C.getCudaDeviceToolChain(), Args,
+ CudaDeviceInputs, CudaDeviceActions);
assert(GpuArchList.size() == CudaDeviceActions.size() &&
"Failed to create actions for all devices");
// Check whether any of device actions stopped before they could generate PTX.
- bool PartialCompilation = false;
- bool DeviceOnlyCompilation = Args.hasArg(options::OPT_cuda_device_only);
- for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i) {
- if (CudaDeviceActions[i]->getKind() != Action::BackendJobClass) {
- PartialCompilation = true;
- break;
- }
- }
+ bool PartialCompilation =
+ llvm::any_of(CudaDeviceActions, [](const Action *a) {
+ return a->getKind() != Action::BackendJobClass;
+ });
// Figure out what to do with device actions -- pass them as inputs to the
// host action or run each of them independently.
+ bool DeviceOnlyCompilation = PartialCompilationArg != nullptr;
if (PartialCompilation || DeviceOnlyCompilation) {
// In case of partial or device-only compilation results of device actions
// are not consumed by the host action device actions have to be added to
@@ -1288,35 +1341,36 @@ buildCudaActions(const Driver &D, const ToolChain &TC, DerivedArgList &Args,
// -o is ambiguous if we have more than one top-level action.
if (Args.hasArg(options::OPT_o) &&
(!DeviceOnlyCompilation || GpuArchList.size() > 1)) {
- D.Diag(clang::diag::err_drv_output_argument_with_multiple_files);
+ C.getDriver().Diag(
+ clang::diag::err_drv_output_argument_with_multiple_files);
return nullptr;
}
- for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i)
- Actions.push_back(
- new CudaDeviceAction(std::unique_ptr<Action>(CudaDeviceActions[i]),
- GpuArchList[i], /* AtTopLevel */ true));
+ for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
+ Actions.push_back(C.MakeAction<CudaDeviceAction>(CudaDeviceActions[I],
+ GpuArchList[I],
+ /* AtTopLevel */ true));
// Kill host action in case of device-only compilation.
if (DeviceOnlyCompilation)
- Current.reset(nullptr);
- return Current;
- } else {
- // Outputs of device actions during complete CUDA compilation get created
- // with AtTopLevel=false and become inputs for the host action.
- ActionList DeviceActions;
- for (unsigned i = 0, e = GpuArchList.size(); i != e; ++i)
- DeviceActions.push_back(
- new CudaDeviceAction(std::unique_ptr<Action>(CudaDeviceActions[i]),
- GpuArchList[i], /* AtTopLevel */ false));
- // Return a new host action that incorporates original host action and all
- // device actions.
- return std::unique_ptr<Action>(
- new CudaHostAction(std::move(Current), DeviceActions));
- }
+ return nullptr;
+ return HostAction;
+ }
+
+ // Outputs of device actions during complete CUDA compilation get created
+ // with AtTopLevel=false and become inputs for the host action.
+ ActionList DeviceActions;
+ for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
+ DeviceActions.push_back(
+ C.MakeAction<CudaDeviceAction>(CudaDeviceActions[I], GpuArchList[I],
+ /* AtTopLevel */ false));
+ // Return a new host action that incorporates original host action and all
+ // device actions.
+ return C.MakeAction<CudaHostAction>(HostAction, DeviceActions);
}
-void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
- const InputList &Inputs, ActionList &Actions) const {
+void Driver::BuildActions(Compilation &C, const ToolChain &TC,
+ DerivedArgList &Args, const InputList &Inputs,
+ ActionList &Actions) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation actions");
if (!SuppressMissingInputWarning && Inputs.empty()) {
@@ -1373,9 +1427,9 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
ActionList LinkerInputs;
llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL;
- for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
- types::ID InputType = Inputs[i].first;
- const Arg *InputArg = Inputs[i].second;
+ for (auto &I : Inputs) {
+ types::ID InputType = I.first;
+ const Arg *InputArg = I.second;
PL.clear();
types::getCompilationPhases(InputType, PL);
@@ -1412,27 +1466,14 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
continue;
}
- phases::ID CudaInjectionPhase;
- if (isSaveTempsEnabled()) {
- // All phases are done independently, inject GPU blobs during compilation
- // phase as that's where we generate glue code to init them.
- CudaInjectionPhase = phases::Compile;
- } else {
- // Assumes that clang does everything up until linking phase, so we inject
- // cuda device actions at the last step before linking. Otherwise CUDA
- // host action forces preprocessor into a separate invocation.
- if (FinalPhase == phases::Link) {
- for (auto i = PL.begin(), e = PL.end(); i != e; ++i) {
- auto next = i + 1;
- if (next != e && *next == phases::Link)
- CudaInjectionPhase = *i;
- }
- } else
- CudaInjectionPhase = FinalPhase;
- }
+ phases::ID CudaInjectionPhase =
+ (phases::Compile < FinalPhase &&
+ llvm::find(PL, phases::Compile) != PL.end())
+ ? phases::Compile
+ : FinalPhase;
// Build the pipeline for this file.
- std::unique_ptr<Action> Current(new InputAction(*InputArg, InputType));
+ Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end();
i != e; ++i) {
phases::ID Phase = *i;
@@ -1444,7 +1485,8 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
// Queue linker inputs.
if (Phase == phases::Link) {
assert((i + 1) == e && "linking must be final compilation step.");
- LinkerInputs.push_back(Current.release());
+ LinkerInputs.push_back(Current);
+ Current = nullptr;
break;
}
@@ -1455,12 +1497,10 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
continue;
// Otherwise construct the appropriate action.
- Current = ConstructPhaseAction(TC, Args, Phase, std::move(Current));
+ Current = ConstructPhaseAction(C, TC, Args, Phase, Current);
- if (InputType == types::TY_CUDA && Phase == CudaInjectionPhase &&
- !Args.hasArg(options::OPT_cuda_host_only)) {
- Current = buildCudaActions(*this, TC, Args, InputArg, InputType,
- std::move(Current), Actions);
+ if (InputType == types::TY_CUDA && Phase == CudaInjectionPhase) {
+ Current = buildCudaActions(C, Args, InputArg, Current, Actions);
if (!Current)
break;
}
@@ -1471,12 +1511,13 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
// If we ended with something, add to the output list.
if (Current)
- Actions.push_back(Current.release());
+ Actions.push_back(Current);
}
// Add a link action if necessary.
if (!LinkerInputs.empty())
- Actions.push_back(new LinkJobAction(LinkerInputs, types::TY_Image));
+ Actions.push_back(
+ C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image));
// If we are linking, claim any options which are obviously only used for
// compilation.
@@ -1487,12 +1528,15 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
// Claim ignored clang-cl options.
Args.ClaimAllArgs(options::OPT_cl_ignored_Group);
+
+ // Claim --cuda-host-only arg which may be passed to non-CUDA
+ // compilations and should not trigger warnings there.
+ Args.ClaimAllArgs(options::OPT_cuda_host_only);
}
-std::unique_ptr<Action>
-Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args,
- phases::ID Phase,
- std::unique_ptr<Action> Input) const {
+Action *Driver::ConstructPhaseAction(Compilation &C, const ToolChain &TC,
+ const ArgList &Args, phases::ID Phase,
+ Action *Input) const {
llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
// Build the appropriate action.
switch (Phase) {
@@ -1512,7 +1556,7 @@ Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args,
assert(OutputTy != types::TY_INVALID &&
"Cannot preprocess this input type!");
}
- return llvm::make_unique<PreprocessJobAction>(std::move(Input), OutputTy);
+ return C.MakeAction<PreprocessJobAction>(Input, OutputTy);
}
case phases::Precompile: {
types::ID OutputTy = types::TY_PCH;
@@ -1520,62 +1564,48 @@ Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args,
// Syntax checks should not emit a PCH file
OutputTy = types::TY_Nothing;
}
- return llvm::make_unique<PrecompileJobAction>(std::move(Input), OutputTy);
+ return C.MakeAction<PrecompileJobAction>(Input, OutputTy);
}
case phases::Compile: {
if (Args.hasArg(options::OPT_fsyntax_only))
- return llvm::make_unique<CompileJobAction>(std::move(Input),
- types::TY_Nothing);
+ return C.MakeAction<CompileJobAction>(Input, types::TY_Nothing);
if (Args.hasArg(options::OPT_rewrite_objc))
- return llvm::make_unique<CompileJobAction>(std::move(Input),
- types::TY_RewrittenObjC);
+ return C.MakeAction<CompileJobAction>(Input, types::TY_RewrittenObjC);
if (Args.hasArg(options::OPT_rewrite_legacy_objc))
- return llvm::make_unique<CompileJobAction>(std::move(Input),
- types::TY_RewrittenLegacyObjC);
+ return C.MakeAction<CompileJobAction>(Input,
+ types::TY_RewrittenLegacyObjC);
if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto))
- return llvm::make_unique<AnalyzeJobAction>(std::move(Input),
- types::TY_Plist);
+ return C.MakeAction<AnalyzeJobAction>(Input, types::TY_Plist);
if (Args.hasArg(options::OPT__migrate))
- return llvm::make_unique<MigrateJobAction>(std::move(Input),
- types::TY_Remap);
+ return C.MakeAction<MigrateJobAction>(Input, types::TY_Remap);
if (Args.hasArg(options::OPT_emit_ast))
- return llvm::make_unique<CompileJobAction>(std::move(Input),
- types::TY_AST);
+ return C.MakeAction<CompileJobAction>(Input, types::TY_AST);
if (Args.hasArg(options::OPT_module_file_info))
- return llvm::make_unique<CompileJobAction>(std::move(Input),
- types::TY_ModuleFile);
+ return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile);
if (Args.hasArg(options::OPT_verify_pch))
- return llvm::make_unique<VerifyPCHJobAction>(std::move(Input),
- types::TY_Nothing);
- return llvm::make_unique<CompileJobAction>(std::move(Input),
- types::TY_LLVM_BC);
+ return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);
+ return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
}
case phases::Backend: {
- if (IsUsingLTO(Args)) {
+ if (isUsingLTO()) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
- return llvm::make_unique<BackendJobAction>(std::move(Input), Output);
+ return C.MakeAction<BackendJobAction>(Input, Output);
}
if (Args.hasArg(options::OPT_emit_llvm)) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
- return llvm::make_unique<BackendJobAction>(std::move(Input), Output);
+ return C.MakeAction<BackendJobAction>(Input, Output);
}
- return llvm::make_unique<BackendJobAction>(std::move(Input),
- types::TY_PP_Asm);
+ return C.MakeAction<BackendJobAction>(Input, types::TY_PP_Asm);
}
case phases::Assemble:
- return llvm::make_unique<AssembleJobAction>(std::move(Input),
- types::TY_Object);
+ return C.MakeAction<AssembleJobAction>(Input, types::TY_Object);
}
llvm_unreachable("invalid phase in ConstructPhaseAction");
}
-bool Driver::IsUsingLTO(const ArgList &Args) const {
- return Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false);
-}
-
void Driver::BuildJobs(Compilation &C) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
@@ -1617,12 +1647,11 @@ void Driver::BuildJobs(Compilation &C) const {
LinkingOutput = getDefaultImageName();
}
- InputInfo II;
BuildJobsForAction(C, A, &C.getDefaultToolChain(),
/*BoundArch*/ nullptr,
/*AtTopLevel*/ true,
/*MultipleArchs*/ ArchNames.size() > 1,
- /*LinkingOutput*/ LinkingOutput, II);
+ /*LinkingOutput*/ LinkingOutput);
}
// If the user passed -Qunused-arguments or there were errors, don't warn
@@ -1668,10 +1697,17 @@ void Driver::BuildJobs(Compilation &C) const {
}
}
-static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps,
+// Returns a Tool for a given JobAction. In case the action and its
+// predecessors can be combined, updates Inputs with the inputs of the
+// first combined action. If one of the collapsed actions is a
+// CudaHostAction, updates CollapsedCHA with the pointer to it so the
+// caller can deal with extra handling such action requires.
+static const Tool *selectToolForJob(Compilation &C, bool SaveTemps,
const ToolChain *TC, const JobAction *JA,
- const ActionList *&Inputs) {
+ const ActionList *&Inputs,
+ const CudaHostAction *&CollapsedCHA) {
const Tool *ToolForJob = nullptr;
+ CollapsedCHA = nullptr;
// See if we should look for a compiler with an integrated assembler. We match
// bottom up, so what we are actually looking for is an assembler job with a
@@ -1688,13 +1724,19 @@ static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps,
// checking the backend tool, check if the tool for the CompileJob
// has an integrated assembler.
const ActionList *BackendInputs = &(*Inputs)[0]->getInputs();
- JobAction *CompileJA = cast<CompileJobAction>(*BackendInputs->begin());
+ // Compile job may be wrapped in CudaHostAction, extract it if
+ // that's the case and update CollapsedCHA if we combine phases.
+ CudaHostAction *CHA = dyn_cast<CudaHostAction>(*BackendInputs->begin());
+ JobAction *CompileJA =
+ cast<CompileJobAction>(CHA ? *CHA->begin() : *BackendInputs->begin());
+ assert(CompileJA && "Backend job is not preceeded by compile job.");
const Tool *Compiler = TC->SelectTool(*CompileJA);
if (!Compiler)
return nullptr;
if (Compiler->hasIntegratedAssembler()) {
- Inputs = &(*BackendInputs)[0]->getInputs();
+ Inputs = &CompileJA->getInputs();
ToolForJob = Compiler;
+ CollapsedCHA = CHA;
}
}
@@ -1704,19 +1746,19 @@ static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps,
if (isa<BackendJobAction>(JA)) {
// Check if the compiler supports emitting LLVM IR.
assert(Inputs->size() == 1);
- JobAction *CompileJA;
- // Extract real host action, if it's a CudaHostAction.
- if (CudaHostAction *CudaHA = dyn_cast<CudaHostAction>(*Inputs->begin()))
- CompileJA = cast<CompileJobAction>(*CudaHA->begin());
- else
- CompileJA = cast<CompileJobAction>(*Inputs->begin());
-
+ // Compile job may be wrapped in CudaHostAction, extract it if
+ // that's the case and update CollapsedCHA if we combine phases.
+ CudaHostAction *CHA = dyn_cast<CudaHostAction>(*Inputs->begin());
+ JobAction *CompileJA =
+ cast<CompileJobAction>(CHA ? *CHA->begin() : *Inputs->begin());
+ assert(CompileJA && "Backend job is not preceeded by compile job.");
const Tool *Compiler = TC->SelectTool(*CompileJA);
if (!Compiler)
return nullptr;
if (!Compiler->canEmitIR() || !SaveTemps) {
- Inputs = &(*Inputs)[0]->getInputs();
+ Inputs = &CompileJA->getInputs();
ToolForJob = Compiler;
+ CollapsedCHA = CHA;
}
}
@@ -1737,21 +1779,19 @@ static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps,
return ToolForJob;
}
-void Driver::BuildJobsForAction(Compilation &C, const Action *A,
- const ToolChain *TC, const char *BoundArch,
- bool AtTopLevel, bool MultipleArchs,
- const char *LinkingOutput,
- InputInfo &Result) const {
+InputInfo Driver::BuildJobsForAction(Compilation &C, const Action *A,
+ const ToolChain *TC, const char *BoundArch,
+ bool AtTopLevel, bool MultipleArchs,
+ const char *LinkingOutput) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
InputInfoList CudaDeviceInputInfos;
if (const CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) {
- InputInfo II;
// Append outputs of device jobs to the input list.
for (const Action *DA : CHA->getDeviceActions()) {
- BuildJobsForAction(C, DA, TC, "", AtTopLevel,
- /*MultipleArchs*/ false, LinkingOutput, II);
- CudaDeviceInputInfos.push_back(II);
+ CudaDeviceInputInfos.push_back(
+ BuildJobsForAction(C, DA, TC, nullptr, AtTopLevel,
+ /*MultipleArchs*/ false, LinkingOutput));
}
// Override current action with a real host compile action and continue
// processing it.
@@ -1765,11 +1805,9 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
Input.claim();
if (Input.getOption().matches(options::OPT_INPUT)) {
const char *Name = Input.getValue();
- Result = InputInfo(Name, A->getType(), Name);
- } else {
- Result = InputInfo(&Input, A->getType(), "");
+ return InputInfo(A, Name, /* BaseInput = */ Name);
}
- return;
+ return InputInfo(A, &Input, /* BaseInput = */ "");
}
if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
@@ -1783,30 +1821,37 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
else
TC = &C.getDefaultToolChain();
- BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel,
- MultipleArchs, LinkingOutput, Result);
- return;
+ return BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel,
+ MultipleArchs, LinkingOutput);
}
if (const CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) {
- // Figure out which NVPTX triple to use for device-side compilation based on
- // whether host is 64-bit.
- llvm::Triple DeviceTriple(C.getDefaultToolChain().getTriple().isArch64Bit()
- ? "nvptx64-nvidia-cuda"
- : "nvptx-nvidia-cuda");
- BuildJobsForAction(C, *CDA->begin(),
- &getToolChain(C.getArgs(), DeviceTriple),
- CDA->getGpuArchName(), CDA->isAtTopLevel(),
- /*MultipleArchs*/ true, LinkingOutput, Result);
- return;
+ // Initial processing of CudaDeviceAction carries host params.
+ // Call BuildJobsForAction() again, now with correct device parameters.
+ assert(CDA->getGpuArchName() && "No GPU name in device action.");
+ return BuildJobsForAction(C, *CDA->begin(), C.getCudaDeviceToolChain(),
+ CDA->getGpuArchName(), CDA->isAtTopLevel(),
+ /*MultipleArchs*/ true, LinkingOutput);
}
const ActionList *Inputs = &A->getInputs();
const JobAction *JA = cast<JobAction>(A);
- const Tool *T = SelectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs);
+ const CudaHostAction *CollapsedCHA = nullptr;
+ const Tool *T =
+ selectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs, CollapsedCHA);
if (!T)
- return;
+ return InputInfo();
+
+ // If we've collapsed action list that contained CudaHostAction we
+ // need to build jobs for device-side inputs it may have held.
+ if (CollapsedCHA) {
+ for (const Action *DA : CollapsedCHA->getDeviceActions()) {
+ CudaDeviceInputInfos.push_back(
+ BuildJobsForAction(C, DA, TC, "", AtTopLevel,
+ /*MultipleArchs*/ false, LinkingOutput));
+ }
+ }
// Only use pipes when there is exactly one input.
InputInfoList InputInfos;
@@ -1814,14 +1859,11 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
// Treat dsymutil and verify sub-jobs as being at the top-level too, they
// shouldn't get temporary output names.
// FIXME: Clean this up.
- bool SubJobAtTopLevel = false;
- if (AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A)))
- SubJobAtTopLevel = true;
-
- InputInfo II;
- BuildJobsForAction(C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs,
- LinkingOutput, II);
- InputInfos.push_back(II);
+ bool SubJobAtTopLevel =
+ AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A));
+ InputInfos.push_back(BuildJobsForAction(C, Input, TC, BoundArch,
+ SubJobAtTopLevel, MultipleArchs,
+ LinkingOutput));
}
// Always use the first input as the base input.
@@ -1837,12 +1879,13 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
InputInfos.append(CudaDeviceInputInfos.begin(), CudaDeviceInputInfos.end());
// Determine the place to write output to, if any.
+ InputInfo Result;
if (JA->getType() == types::TY_Nothing)
- Result = InputInfo(A->getType(), BaseInput);
+ Result = InputInfo(A, BaseInput);
else
- Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
- AtTopLevel, MultipleArchs),
- A->getType(), BaseInput);
+ Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
+ AtTopLevel, MultipleArchs),
+ BaseInput);
if (CCCPrintBindings && !CCGenDiagnostics) {
llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"'
@@ -1857,6 +1900,7 @@ void Driver::BuildJobsForAction(Compilation &C, const Action *A,
T->ConstructJob(C, *JA, Result, InputInfos,
C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
}
+ return Result;
}
const char *Driver::getDefaultImageName() const {
@@ -2091,6 +2135,11 @@ void Driver::generatePrefixedToolNames(
// FIXME: Needs a better variable than DefaultTargetTriple
Names.emplace_back(DefaultTargetTriple + "-" + Tool);
Names.emplace_back(Tool);
+
+ // Allow the discovery of tools prefixed with LLVM's default target triple.
+ std::string LLVMDefaultTargetTriple = llvm::sys::getDefaultTargetTriple();
+ if (LLVMDefaultTargetTriple != DefaultTargetTriple)
+ Names.emplace_back(LLVMDefaultTargetTriple + "-" + Tool);
}
static bool ScanDirForExecutable(SmallString<128> &Dir,
@@ -2163,6 +2212,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
+ case llvm::Triple::TvOS:
+ case llvm::Triple::WatchOS:
TC = new toolchains::DarwinClang(*this, Target, Args);
break;
case llvm::Triple::DragonFly:
@@ -2185,16 +2236,22 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
break;
case llvm::Triple::Linux:
if (Target.getArch() == llvm::Triple::hexagon)
- TC = new toolchains::Hexagon_TC(*this, Target, Args);
+ TC = new toolchains::HexagonToolChain(*this, Target, Args);
+ else if ((Target.getVendor() == llvm::Triple::MipsTechnologies) &&
+ !Target.hasEnvironment())
+ TC = new toolchains::MipsLLVMToolChain(*this, Target, Args);
else
TC = new toolchains::Linux(*this, Target, Args);
break;
case llvm::Triple::NaCl:
- TC = new toolchains::NaCl_TC(*this, Target, Args);
+ TC = new toolchains::NaClToolChain(*this, Target, Args);
break;
case llvm::Triple::Solaris:
TC = new toolchains::Solaris(*this, Target, Args);
break;
+ case llvm::Triple::AMDHSA:
+ TC = new toolchains::AMDGPUToolChain(*this, Target, Args);
+ break;
case llvm::Triple::Win32:
switch (Target.getEnvironment()) {
default:
@@ -2220,24 +2277,36 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::CUDA:
TC = new toolchains::CudaToolChain(*this, Target, Args);
break;
+ case llvm::Triple::PS4:
+ TC = new toolchains::PS4CPU(*this, Target, Args);
+ break;
default:
// Of these targets, Hexagon is the only one that might have
// an OS of Linux, in which case it got handled above already.
- if (Target.getArchName() == "tce")
+ switch (Target.getArch()) {
+ case llvm::Triple::tce:
TC = new toolchains::TCEToolChain(*this, Target, Args);
- else if (Target.getArch() == llvm::Triple::hexagon)
- TC = new toolchains::Hexagon_TC(*this, Target, Args);
- else if (Target.getArch() == llvm::Triple::xcore)
- TC = new toolchains::XCore(*this, Target, Args);
- else if (Target.getArch() == llvm::Triple::shave)
- TC = new toolchains::SHAVEToolChain(*this, Target, Args);
- else if (Target.isOSBinFormatELF())
- TC = new toolchains::Generic_ELF(*this, Target, Args);
- else if (Target.isOSBinFormatMachO())
- TC = new toolchains::MachO(*this, Target, Args);
- else
- TC = new toolchains::Generic_GCC(*this, Target, Args);
- break;
+ break;
+ case llvm::Triple::hexagon:
+ TC = new toolchains::HexagonToolChain(*this, Target, Args);
+ break;
+ case llvm::Triple::xcore:
+ TC = new toolchains::XCoreToolChain(*this, Target, Args);
+ break;
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ TC = new toolchains::WebAssembly(*this, Target, Args);
+ break;
+ default:
+ if (Target.getVendor() == llvm::Triple::Myriad)
+ TC = new toolchains::MyriadToolChain(*this, Target, Args);
+ else if (Target.isOSBinFormatELF())
+ TC = new toolchains::Generic_ELF(*this, Target, Args);
+ else if (Target.isOSBinFormatMachO())
+ TC = new toolchains::MachO(*this, Target, Args);
+ else
+ TC = new toolchains::Generic_GCC(*this, Target, Args);
+ }
}
}
return *TC;
diff --git a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
index 6ff1cba..8d5332b 100644
--- a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
@@ -34,7 +34,7 @@ namespace {
class DriverOptTable : public OptTable {
public:
DriverOptTable()
- : OptTable(InfoTable, llvm::array_lengthof(InfoTable)) {}
+ : OptTable(InfoTable) {}
};
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/InputInfo.h b/contrib/llvm/tools/clang/lib/Driver/InputInfo.h
index b23ba57..0c36e81 100644
--- a/contrib/llvm/tools/clang/lib/Driver/InputInfo.h
+++ b/contrib/llvm/tools/clang/lib/Driver/InputInfo.h
@@ -10,6 +10,7 @@
#ifndef LLVM_CLANG_LIB_DRIVER_INPUTINFO_H
#define LLVM_CLANG_LIB_DRIVER_INPUTINFO_H
+#include "clang/Driver/Action.h"
#include "clang/Driver/Types.h"
#include "llvm/Option/Arg.h"
#include <cassert>
@@ -38,21 +39,36 @@ class InputInfo {
const llvm::opt::Arg *InputArg;
} Data;
Class Kind;
+ const Action* Act;
types::ID Type;
const char *BaseInput;
+ static types::ID GetActionType(const Action *A) {
+ return A != nullptr ? A->getType() : types::TY_Nothing;
+ }
+
public:
- InputInfo() {}
- InputInfo(types::ID _Type, const char *_BaseInput)
- : Kind(Nothing), Type(_Type), BaseInput(_BaseInput) {
+ InputInfo() : InputInfo(nullptr, nullptr) {}
+ InputInfo(const Action *A, const char *_BaseInput)
+ : Kind(Nothing), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) {}
+
+ InputInfo(types::ID _Type, const char *_Filename, const char *_BaseInput)
+ : Kind(Filename), Act(nullptr), Type(_Type), BaseInput(_BaseInput) {
+ Data.Filename = _Filename;
}
- InputInfo(const char *_Filename, types::ID _Type, const char *_BaseInput)
- : Kind(Filename), Type(_Type), BaseInput(_BaseInput) {
+ InputInfo(const Action *A, const char *_Filename, const char *_BaseInput)
+ : Kind(Filename), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) {
Data.Filename = _Filename;
}
- InputInfo(const llvm::opt::Arg *_InputArg, types::ID _Type,
+
+ InputInfo(types::ID _Type, const llvm::opt::Arg *_InputArg,
+ const char *_BaseInput)
+ : Kind(InputArg), Act(nullptr), Type(_Type), BaseInput(_BaseInput) {
+ Data.InputArg = _InputArg;
+ }
+ InputInfo(const Action *A, const llvm::opt::Arg *_InputArg,
const char *_BaseInput)
- : Kind(InputArg), Type(_Type), BaseInput(_BaseInput) {
+ : Kind(InputArg), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) {
Data.InputArg = _InputArg;
}
@@ -61,6 +77,9 @@ public:
bool isInputArg() const { return Kind == InputArg; }
types::ID getType() const { return Type; }
const char *getBaseInput() const { return BaseInput; }
+ /// The action for which this InputInfo was created. May be null.
+ const Action *getAction() const { return Act; }
+ void setAction(const Action *A) { Act = A; }
const char *getFilename() const {
assert(isFilename() && "Invalid accessor.");
diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
index 42bba56..22904e5 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Job.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "InputInfo.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Job.h"
@@ -26,9 +27,14 @@ using llvm::StringRef;
using llvm::ArrayRef;
Command::Command(const Action &Source, const Tool &Creator,
- const char *Executable, const ArgStringList &Arguments)
+ const char *Executable, const ArgStringList &Arguments,
+ ArrayRef<InputInfo> Inputs)
: Source(Source), Creator(Creator), Executable(Executable),
- Arguments(Arguments), ResponseFile(nullptr) {}
+ Arguments(Arguments), ResponseFile(nullptr) {
+ for (const auto &II : Inputs)
+ if (II.isFilename())
+ InputFilenames.push_back(II.getFilename());
+}
static int skipArgs(const char *Flag, bool HaveCrashVFS) {
// These flags are all of the form -Flag <Arg> and are treated as two
@@ -42,6 +48,7 @@ static int skipArgs(const char *Flag, bool HaveCrashVFS) {
.Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
.Cases("-resource-dir", "-serialize-diagnostic-file", true)
.Cases("-dwarf-debug-flags", "-ivfsoverlay", true)
+ .Cases("-header-include-file", "-diagnostic-log-file", true)
// Some include flags shouldn't be skipped if we have a crash VFS
.Case("-isysroot", !HaveCrashVFS)
.Default(false);
@@ -98,7 +105,9 @@ void Command::writeResponseFile(raw_ostream &OS) const {
return;
}
- // In regular response files, we send all arguments to the response file
+ // In regular response files, we send all arguments to the response file.
+ // Wrapping all arguments in double quotes ensures that both Unix tools and
+ // Windows tools understand the response file.
for (const char *Arg : Arguments) {
OS << '"';
@@ -155,13 +164,6 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
Args = ArrayRef<const char *>(ArgsRespFile).slice(1); // no executable name
}
- StringRef MainFilename;
- // We'll need the argument to -main-file-name to find the input file name.
- if (CrashInfo)
- for (size_t I = 0, E = Args.size(); I + 1 < E; ++I)
- if (StringRef(Args[I]).equals("-main-file-name"))
- MainFilename = Args[I + 1];
-
bool HaveCrashVFS = CrashInfo && !CrashInfo->VFSPath.empty();
for (size_t i = 0, e = Args.size(); i < e; ++i) {
const char *const Arg = Args[i];
@@ -170,8 +172,11 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
if (int Skip = skipArgs(Arg, HaveCrashVFS)) {
i += Skip - 1;
continue;
- } else if (llvm::sys::path::filename(Arg) == MainFilename &&
- (i == 0 || StringRef(Args[i - 1]) != "-main-file-name")) {
+ }
+ auto Found = std::find_if(InputFilenames.begin(), InputFilenames.end(),
+ [&Arg](StringRef IF) { return IF == Arg; });
+ if (Found != InputFilenames.end() &&
+ (i == 0 || StringRef(Args[i - 1]) != "-main-file-name")) {
// Replace the input file name with the crashinfo's file name.
OS << ' ';
StringRef ShortName = llvm::sys::path::filename(CrashInfo->Filename);
@@ -254,8 +259,9 @@ int Command::Execute(const StringRef **Redirects, std::string *ErrMsg,
FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
const char *Executable_,
const ArgStringList &Arguments_,
+ ArrayRef<InputInfo> Inputs,
std::unique_ptr<Command> Fallback_)
- : Command(Source_, Creator_, Executable_, Arguments_),
+ : Command(Source_, Creator_, Executable_, Arguments_, Inputs),
Fallback(std::move(Fallback_)) {}
void FallbackCommand::Print(raw_ostream &OS, const char *Terminator,
diff --git a/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp
index c816b29..6874715 100644
--- a/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp
@@ -205,27 +205,103 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName,
#endif // USE_WIN32
}
+// Convert LLVM's ArchType
+// to the corresponding name of Windows SDK libraries subfolder
+static StringRef getWindowsSDKArch(llvm::Triple::ArchType Arch) {
+ switch (Arch) {
+ case llvm::Triple::x86:
+ return "x86";
+ case llvm::Triple::x86_64:
+ return "x64";
+ case llvm::Triple::arm:
+ return "arm";
+ default:
+ return "";
+ }
+}
+
+// Find the most recent version of Universal CRT or Windows 10 SDK.
+// vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
+// directory by name and uses the last one of the list.
+// So we compare entry names lexicographically to find the greatest one.
+static bool getWindows10SDKVersion(const std::string &SDKPath,
+ std::string &SDKVersion) {
+ SDKVersion.clear();
+
+ std::error_code EC;
+ llvm::SmallString<128> IncludePath(SDKPath);
+ llvm::sys::path::append(IncludePath, "Include");
+ for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
+ DirIt != DirEnd && !EC; DirIt.increment(EC)) {
+ if (!llvm::sys::fs::is_directory(DirIt->path()))
+ continue;
+ StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
+ // If WDK is installed, there could be subfolders like "wdf" in the
+ // "Include" directory.
+ // Allow only directories which names start with "10.".
+ if (!CandidateName.startswith("10."))
+ continue;
+ if (CandidateName > SDKVersion)
+ SDKVersion = CandidateName;
+ }
+
+ return !SDKVersion.empty();
+}
+
/// \brief Get Windows SDK installation directory.
-bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major,
- int &minor) const {
- std::string sdkVersion;
+bool MSVCToolChain::getWindowsSDKDir(std::string &Path, int &Major,
+ std::string &WindowsSDKIncludeVersion,
+ std::string &WindowsSDKLibVersion) const {
+ std::string RegistrySDKVersion;
// Try the Windows registry.
- bool hasSDKDir = getSystemRegistryString(
- "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
- "InstallationFolder", path, &sdkVersion);
- if (!sdkVersion.empty())
- std::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor);
- return hasSDKDir && !path.empty();
+ if (!getSystemRegistryString(
+ "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
+ "InstallationFolder", Path, &RegistrySDKVersion))
+ return false;
+ if (Path.empty() || RegistrySDKVersion.empty())
+ return false;
+
+ WindowsSDKIncludeVersion.clear();
+ WindowsSDKLibVersion.clear();
+ Major = 0;
+ std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
+ if (Major <= 7)
+ return true;
+ if (Major == 8) {
+ // Windows SDK 8.x installs libraries in a folder whose names depend on the
+ // version of the OS you're targeting. By default choose the newest, which
+ // usually corresponds to the version of the OS you've installed the SDK on.
+ const char *Tests[] = {"winv6.3", "win8", "win7"};
+ for (const char *Test : Tests) {
+ llvm::SmallString<128> TestPath(Path);
+ llvm::sys::path::append(TestPath, "Lib", Test);
+ if (llvm::sys::fs::exists(TestPath.c_str())) {
+ WindowsSDKLibVersion = Test;
+ break;
+ }
+ }
+ return !WindowsSDKLibVersion.empty();
+ }
+ if (Major == 10) {
+ if (!getWindows10SDKVersion(Path, WindowsSDKIncludeVersion))
+ return false;
+ WindowsSDKLibVersion = WindowsSDKIncludeVersion;
+ return true;
+ }
+ // Unsupported SDK version
+ return false;
}
// Gets the library path required to link against the Windows SDK.
bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
std::string sdkPath;
int sdkMajor = 0;
- int sdkMinor = 0;
+ std::string windowsSDKIncludeVersion;
+ std::string windowsSDKLibVersion;
path.clear();
- if (!getWindowsSDKDir(sdkPath, sdkMajor, sdkMinor))
+ if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
+ windowsSDKLibVersion))
return false;
llvm::SmallString<128> libPath(sdkPath);
@@ -245,44 +321,57 @@ bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
return false;
}
} else {
- // Windows SDK 8.x installs libraries in a folder whose names depend on the
- // version of the OS you're targeting. By default choose the newest, which
- // usually corresponds to the version of the OS you've installed the SDK on.
- const char *tests[] = {"winv6.3", "win8", "win7"};
- bool found = false;
- for (const char *test : tests) {
- llvm::SmallString<128> testPath(libPath);
- llvm::sys::path::append(testPath, test);
- if (llvm::sys::fs::exists(testPath.c_str())) {
- libPath = testPath;
- found = true;
- break;
- }
- }
-
- if (!found)
+ const StringRef archName = getWindowsSDKArch(getArch());
+ if (archName.empty())
return false;
-
- llvm::sys::path::append(libPath, "um");
- switch (getArch()) {
- case llvm::Triple::x86:
- llvm::sys::path::append(libPath, "x86");
- break;
- case llvm::Triple::x86_64:
- llvm::sys::path::append(libPath, "x64");
- break;
- case llvm::Triple::arm:
- llvm::sys::path::append(libPath, "arm");
- break;
- default:
- return false;
- }
+ llvm::sys::path::append(libPath, windowsSDKLibVersion, "um", archName);
}
path = libPath.str();
return true;
}
+// Check if the Include path of a specified version of Visual Studio contains
+// specific header files. If not, they are probably shipped with Universal CRT.
+bool clang::driver::toolchains::MSVCToolChain::useUniversalCRT(
+ std::string &VisualStudioDir) const {
+ llvm::SmallString<128> TestPath(VisualStudioDir);
+ llvm::sys::path::append(TestPath, "VC\\include\\stdlib.h");
+
+ return !llvm::sys::fs::exists(TestPath);
+}
+
+bool MSVCToolChain::getUniversalCRTSdkDir(std::string &Path,
+ std::string &UCRTVersion) const {
+ // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
+ // for the specific key "KitsRoot10". So do we.
+ if (!getSystemRegistryString(
+ "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
+ Path, nullptr))
+ return false;
+
+ return getWindows10SDKVersion(Path, UCRTVersion);
+}
+
+bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
+ std::string UniversalCRTSdkPath;
+ std::string UCRTVersion;
+
+ Path.clear();
+ if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
+ return false;
+
+ StringRef ArchName = getWindowsSDKArch(getArch());
+ if (ArchName.empty())
+ return false;
+
+ llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
+ llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
+
+ Path = LibPath.str();
+ return true;
+}
+
// Get the location to use for Visual Studio binaries. The location priority
// is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on
// system (as reported by the registry).
@@ -419,12 +508,12 @@ bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
return false;
}
-void MSVCToolChain::AddSystemIncludeWithSubfolder(const ArgList &DriverArgs,
- ArgStringList &CC1Args,
- const std::string &folder,
- const char *subfolder) const {
+void MSVCToolChain::AddSystemIncludeWithSubfolder(
+ const ArgList &DriverArgs, ArgStringList &CC1Args,
+ const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
+ const Twine &subfolder3) const {
llvm::SmallString<128> path(folder);
- llvm::sys::path::append(path, subfolder);
+ llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
addSystemInclude(DriverArgs, CC1Args, path);
}
@@ -434,9 +523,8 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return;
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
- SmallString<128> P(getDriver().ResourceDir);
- llvm::sys::path::append(P, "include");
- addSystemInclude(DriverArgs, CC1Args, P);
+ AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
+ "include");
}
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
@@ -460,16 +548,33 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (getVisualStudioInstallDir(VSDir)) {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include");
+ if (useUniversalCRT(VSDir)) {
+ std::string UniversalCRTSdkPath;
+ std::string UCRTVersion;
+ if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
+ AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
+ "Include", UCRTVersion, "ucrt");
+ }
+ }
+
std::string WindowsSDKDir;
- int major, minor;
- if (getWindowsSDKDir(WindowsSDKDir, major, minor)) {
+ int major;
+ std::string windowsSDKIncludeVersion;
+ std::string windowsSDKLibVersion;
+ if (getWindowsSDKDir(WindowsSDKDir, major, windowsSDKIncludeVersion,
+ windowsSDKLibVersion)) {
if (major >= 8) {
+ // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
+ // Anyway, llvm::sys::path::append is able to manage it.
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include\\shared");
+ "include", windowsSDKIncludeVersion,
+ "shared");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include\\um");
+ "include", windowsSDKIncludeVersion,
+ "um");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include\\winrt");
+ "include", windowsSDKIncludeVersion,
+ "winrt");
} else {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"include");
@@ -528,3 +633,139 @@ SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
Res |= SanitizerKind::Address;
return Res;
}
+
+static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
+ bool SupportsForcingFramePointer,
+ const char *ExpandChar, const OptTable &Opts) {
+ assert(A->getOption().matches(options::OPT__SLASH_O));
+
+ StringRef OptStr = A->getValue();
+ for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
+ const char &OptChar = *(OptStr.data() + I);
+ switch (OptChar) {
+ default:
+ break;
+ case '1':
+ case '2':
+ case 'x':
+ case 'd':
+ if (&OptChar == ExpandChar) {
+ if (OptChar == 'd') {
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
+ } else {
+ if (OptChar == '1') {
+ DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
+ } else if (OptChar == '2' || OptChar == 'x') {
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
+ DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
+ }
+ if (SupportsForcingFramePointer)
+ DAL.AddFlagArg(A,
+ Opts.getOption(options::OPT_fomit_frame_pointer));
+ if (OptChar == '1' || OptChar == '2')
+ DAL.AddFlagArg(A,
+ Opts.getOption(options::OPT_ffunction_sections));
+ }
+ }
+ break;
+ case 'b':
+ if (I + 1 != E && isdigit(OptStr[I + 1]))
+ ++I;
+ break;
+ case 'g':
+ break;
+ case 'i':
+ if (I + 1 != E && OptStr[I + 1] == '-') {
+ ++I;
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
+ } else {
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
+ }
+ break;
+ case 's':
+ DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
+ break;
+ case 't':
+ DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
+ break;
+ case 'y': {
+ bool OmitFramePointer = true;
+ if (I + 1 != E && OptStr[I + 1] == '-') {
+ OmitFramePointer = false;
+ ++I;
+ }
+ if (SupportsForcingFramePointer) {
+ if (OmitFramePointer)
+ DAL.AddFlagArg(A,
+ Opts.getOption(options::OPT_fomit_frame_pointer));
+ else
+ DAL.AddFlagArg(
+ A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
+ }
+ break;
+ }
+ }
+ }
+}
+
+static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
+ const OptTable &Opts) {
+ assert(A->getOption().matches(options::OPT_D));
+
+ StringRef Val = A->getValue();
+ size_t Hash = Val.find('#');
+ if (Hash == StringRef::npos || Hash > Val.find('=')) {
+ DAL.append(A);
+ return;
+ }
+
+ std::string NewVal = Val;
+ NewVal[Hash] = '=';
+ DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
+}
+
+llvm::opt::DerivedArgList *
+MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ const char *BoundArch) const {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+ const OptTable &Opts = getDriver().getOpts();
+
+ // /Oy and /Oy- only has an effect under X86-32.
+ bool SupportsForcingFramePointer = getArch() == llvm::Triple::x86;
+
+ // The -O[12xd] flag actually expands to several flags. We must desugar the
+ // flags so that options embedded can be negated. For example, the '-O2' flag
+ // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to
+ // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
+ // aspect of '-O2'.
+ //
+ // Note that this expansion logic only applies to the *last* of '[12xd]'.
+
+ // First step is to search for the character we'd like to expand.
+ const char *ExpandChar = nullptr;
+ for (Arg *A : Args) {
+ if (!A->getOption().matches(options::OPT__SLASH_O))
+ continue;
+ StringRef OptStr = A->getValue();
+ for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
+ const char &OptChar = *(OptStr.data() + I);
+ if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
+ ExpandChar = OptStr.data() + I;
+ }
+ }
+
+ for (Arg *A : Args) {
+ if (A->getOption().matches(options::OPT__SLASH_O)) {
+ // The -O flag actually takes an amalgam of other options. For example,
+ // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
+ TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
+ } else if (A->getOption().matches(options::OPT_D)) {
+ // Translate -Dfoo#bar into -Dfoo=bar.
+ TranslateDArg(A, *DAL, Opts);
+ } else {
+ DAL->append(A);
+ }
+ }
+
+ return DAL;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp b/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp
index 8acda67..34ad6a7 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp
@@ -260,16 +260,15 @@ bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const {
return false;
}, Multilibs);
- if (Filtered.size() == 0) {
+ if (Filtered.size() == 0)
return false;
- } else if (Filtered.size() == 1) {
+ if (Filtered.size() == 1) {
M = Filtered[0];
return true;
}
// TODO: pick the "best" multlib when more than one is suitable
assert(false);
-
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
index c3ad8ef..2fded1c 100644
--- a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
@@ -29,11 +29,11 @@ enum : SanitizerMask {
NeedsUbsanRt = Undefined | Integer | CFI,
NeedsUbsanCxxRt = Vptr | CFI,
NotAllowedWithTrap = Vptr,
- RequiresPIE = Memory | DataFlow,
+ RequiresPIE = DataFlow,
NeedsUnwindTables = Address | Thread | Memory | DataFlow,
SupportsCoverage = Address | Memory | Leak | Undefined | Integer | DataFlow,
RecoverableByDefault = Undefined | Integer,
- Unrecoverable = Address | Unreachable | Return,
+ Unrecoverable = Unreachable | Return,
LegacyFsanitizeRecoverMask = Undefined | Integer,
NeedsLTO = CFI,
TrappingSupported =
@@ -90,6 +90,8 @@ static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
BlacklistFile = "tsan_blacklist.txt";
else if (Kinds & DataFlow)
BlacklistFile = "dfsan_abilist.txt";
+ else if (Kinds & CFI)
+ BlacklistFile = "cfi_blacklist.txt";
if (BlacklistFile) {
clang::SmallString<64> Path(D.ResourceDir);
@@ -158,11 +160,20 @@ bool SanitizerArgs::needsUbsanRt() const {
return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) &&
!Sanitizers.has(Address) &&
!Sanitizers.has(Memory) &&
- !Sanitizers.has(Thread);
+ !Sanitizers.has(Thread) &&
+ !CfiCrossDso;
+}
+
+bool SanitizerArgs::needsCfiRt() const {
+ return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
+}
+
+bool SanitizerArgs::needsCfiDiagRt() const {
+ return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso;
}
bool SanitizerArgs::requiresPIE() const {
- return AsanZeroBaseShadow || (Sanitizers.Mask & RequiresPIE);
+ return NeedPIE || (Sanitizers.Mask & RequiresPIE);
}
bool SanitizerArgs::needsUnwindTables() const {
@@ -174,13 +185,15 @@ void SanitizerArgs::clear() {
RecoverableSanitizers.clear();
TrapSanitizers.clear();
BlacklistFiles.clear();
+ ExtraDeps.clear();
CoverageFeatures = 0;
MsanTrackOrigins = 0;
MsanUseAfterDtor = false;
+ NeedPIE = false;
AsanFieldPadding = 0;
- AsanZeroBaseShadow = false;
AsanSharedRuntime = false;
LinkCXXRuntimes = false;
+ CfiCrossDso = false;
}
SanitizerArgs::SanitizerArgs(const ToolChain &TC,
@@ -280,7 +293,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
// Check that LTO is enabled if we need it.
- if ((Kinds & NeedsLTO) && !D.IsUsingLTO(Args)) {
+ if ((Kinds & NeedsLTO) && !D.isUsingLTO()) {
D.Diag(diag::err_drv_argument_only_allowed_with)
<< lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
}
@@ -381,13 +394,16 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
Arg->claim();
std::string BLPath = Arg->getValue();
- if (llvm::sys::fs::exists(BLPath))
+ if (llvm::sys::fs::exists(BLPath)) {
BlacklistFiles.push_back(BLPath);
- else
+ ExtraDeps.push_back(BLPath);
+ } else
D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
+
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
Arg->claim();
BlacklistFiles.clear();
+ ExtraDeps.clear();
}
}
// Validate blacklists format.
@@ -418,8 +434,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
}
}
- MsanUseAfterDtor =
- Args.hasArg(options::OPT_fsanitize_memory_use_after_dtor);
+ MsanUseAfterDtor =
+ Args.hasArg(options::OPT_fsanitize_memory_use_after_dtor);
+ NeedPIE |= !(TC.getTriple().isOSLinux() &&
+ TC.getTriple().getArch() == llvm::Triple::x86_64);
+ }
+
+ if (AllAddedKinds & CFI) {
+ CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
+ options::OPT_fno_sanitize_cfi_cross_dso, false);
+ // Without PIE, external function address may resolve to a PLT record, which
+ // can not be verified by the target module.
+ NeedPIE |= CfiCrossDso;
}
// Parse -f(no-)?sanitize-coverage flags if coverage is supported by the
@@ -489,10 +515,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
if (AllAddedKinds & Address) {
AsanSharedRuntime =
- Args.hasArg(options::OPT_shared_libasan) ||
- (TC.getTriple().getEnvironment() == llvm::Triple::Android);
- AsanZeroBaseShadow =
- (TC.getTriple().getEnvironment() == llvm::Triple::Android);
+ Args.hasArg(options::OPT_shared_libasan) || TC.getTriple().isAndroid();
+ NeedPIE |= TC.getTriple().isAndroid();
if (Arg *A =
Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
StringRef S = A->getValue();
@@ -561,6 +585,11 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
BlacklistOpt += BLPath;
CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
}
+ for (const auto &Dep : ExtraDeps) {
+ SmallString<64> ExtraDepOpt("-fdepfile-entry=");
+ ExtraDepOpt += Dep;
+ CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
+ }
if (MsanTrackOrigins)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
@@ -569,6 +598,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
if (MsanUseAfterDtor)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-use-after-dtor"));
+ if (CfiCrossDso)
+ CmdArgs.push_back(Args.MakeArgString("-fsanitize-cfi-cross-dso"));
+
if (AsanFieldPadding)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +
llvm::utostr(AsanFieldPadding)));
@@ -599,11 +631,10 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
// Instruct the code generator to embed linker directives in the object file
// that cause the required runtime libraries to be linked.
CmdArgs.push_back(Args.MakeArgString(
- "--dependent-lib=" + tools::getCompilerRT(TC, "ubsan_standalone")));
+ "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone")));
if (types::isCXX(InputType))
- CmdArgs.push_back(
- Args.MakeArgString("--dependent-lib=" +
- tools::getCompilerRT(TC, "ubsan_standalone_cxx")));
+ CmdArgs.push_back(Args.MakeArgString(
+ "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone_cxx")));
}
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
index d40bb95..cbbd485 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
@@ -22,8 +22,13 @@
#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetParser.h"
+
using namespace clang::driver;
+using namespace clang::driver::tools;
using namespace clang;
+using namespace llvm;
using namespace llvm::opt;
static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) {
@@ -72,9 +77,7 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
ToolChain::~ToolChain() {
}
-const Driver &ToolChain::getDriver() const {
- return D;
-}
+vfs::FileSystem &ToolChain::getVFS() const { return getDriver().getVFS(); }
bool ToolChain::useIntegratedAs() const {
return Args.hasFlag(options::OPT_fintegrated_as,
@@ -88,6 +91,99 @@ const SanitizerArgs& ToolChain::getSanitizerArgs() const {
return *SanitizerArguments.get();
}
+namespace {
+struct DriverSuffix {
+ const char *Suffix;
+ const char *ModeFlag;
+};
+
+const DriverSuffix *FindDriverSuffix(StringRef ProgName) {
+ // A list of known driver suffixes. Suffixes are compared against the
+ // program name in order. If there is a match, the frontend type is updated as
+ // necessary by applying the ModeFlag.
+ static const DriverSuffix DriverSuffixes[] = {
+ {"clang", nullptr},
+ {"clang++", "--driver-mode=g++"},
+ {"clang-c++", "--driver-mode=g++"},
+ {"clang-cc", nullptr},
+ {"clang-cpp", "--driver-mode=cpp"},
+ {"clang-g++", "--driver-mode=g++"},
+ {"clang-gcc", nullptr},
+ {"clang-cl", "--driver-mode=cl"},
+ {"cc", nullptr},
+ {"cpp", "--driver-mode=cpp"},
+ {"cl", "--driver-mode=cl"},
+ {"++", "--driver-mode=g++"},
+ };
+
+ for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i)
+ if (ProgName.endswith(DriverSuffixes[i].Suffix))
+ return &DriverSuffixes[i];
+ return nullptr;
+}
+
+/// Normalize the program name from argv[0] by stripping the file extension if
+/// present and lower-casing the string on Windows.
+std::string normalizeProgramName(llvm::StringRef Argv0) {
+ std::string ProgName = llvm::sys::path::stem(Argv0);
+#ifdef LLVM_ON_WIN32
+ // Transform to lowercase for case insensitive file systems.
+ std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), ::tolower);
+#endif
+ return ProgName;
+}
+
+const DriverSuffix *parseDriverSuffix(StringRef ProgName) {
+ // Try to infer frontend type and default target from the program name by
+ // comparing it against DriverSuffixes in order.
+
+ // If there is a match, the function tries to identify a target as prefix.
+ // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target
+ // prefix "x86_64-linux". If such a target prefix is found, it may be
+ // added via -target as implicit first argument.
+ const DriverSuffix *DS = FindDriverSuffix(ProgName);
+
+ if (!DS) {
+ // Try again after stripping any trailing version number:
+ // clang++3.5 -> clang++
+ ProgName = ProgName.rtrim("0123456789.");
+ DS = FindDriverSuffix(ProgName);
+ }
+
+ if (!DS) {
+ // Try again after stripping trailing -component.
+ // clang++-tot -> clang++
+ ProgName = ProgName.slice(0, ProgName.rfind('-'));
+ DS = FindDriverSuffix(ProgName);
+ }
+ return DS;
+}
+} // anonymous namespace
+
+std::pair<std::string, std::string>
+ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
+ std::string ProgName = normalizeProgramName(PN);
+ const DriverSuffix *DS = parseDriverSuffix(ProgName);
+ if (!DS)
+ return std::make_pair("", "");
+ std::string ModeFlag = DS->ModeFlag == nullptr ? "" : DS->ModeFlag;
+
+ std::string::size_type LastComponent =
+ ProgName.rfind('-', ProgName.size() - strlen(DS->Suffix));
+ if (LastComponent == std::string::npos)
+ return std::make_pair("", ModeFlag);
+
+ // Infer target from the prefix.
+ StringRef Prefix(ProgName);
+ Prefix = Prefix.slice(0, LastComponent);
+ std::string IgnoredError;
+ std::string Target;
+ if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
+ Target = Prefix;
+ }
+ return std::make_pair(Target, ModeFlag);
+}
+
StringRef ToolChain::getDefaultUniversalArchName() const {
// In universal driver terms, the arch name accepted by -arch isn't exactly
// the same as the ones that appear in the triple. Roughly speaking, this is
@@ -171,9 +267,64 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
llvm_unreachable("Invalid tool kind.");
}
+static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,
+ const ArgList &Args) {
+ const llvm::Triple &Triple = TC.getTriple();
+ bool IsWindows = Triple.isOSWindows();
+
+ if (Triple.isWindowsMSVCEnvironment() && TC.getArch() == llvm::Triple::x86)
+ return "i386";
+
+ if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
+ return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows)
+ ? "armhf"
+ : "arm";
+
+ return TC.getArchName();
+}
+
+std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
+ bool Shared) const {
+ const llvm::Triple &TT = getTriple();
+ const char *Env = TT.isAndroid() ? "-android" : "";
+ bool IsITANMSVCWindows =
+ TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
+
+ StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
+ const char *Prefix = IsITANMSVCWindows ? "" : "lib";
+ const char *Suffix = Shared ? (Triple.isOSWindows() ? ".dll" : ".so")
+ : (IsITANMSVCWindows ? ".lib" : ".a");
+
+ SmallString<128> Path(getDriver().ResourceDir);
+ StringRef OSLibName = Triple.isOSFreeBSD() ? "freebsd" : getOS();
+ llvm::sys::path::append(Path, "lib", OSLibName);
+ llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" +
+ Arch + Env + Suffix);
+ return Path.str();
+}
+
+const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
+ StringRef Component,
+ bool Shared) const {
+ return Args.MakeArgString(getCompilerRT(Args, Component, Shared));
+}
+
+bool ToolChain::needsProfileRT(const ArgList &Args) {
+ if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
+ false) ||
+ Args.hasArg(options::OPT_fprofile_generate) ||
+ Args.hasArg(options::OPT_fprofile_generate_EQ) ||
+ Args.hasArg(options::OPT_fprofile_instr_generate) ||
+ Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
+ Args.hasArg(options::OPT_fcreate_profile) ||
+ Args.hasArg(options::OPT_coverage))
+ return true;
+
+ return false;
+}
+
Tool *ToolChain::SelectTool(const JobAction &JA) const {
- if (getDriver().ShouldUseClangCompiler(JA))
- return getClang();
+ if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
Action::ActionClass AC = JA.getKind();
if (AC == Action::AssembleJobClass && useIntegratedAs())
return getClangAs();
@@ -182,7 +333,6 @@ Tool *ToolChain::SelectTool(const JobAction &JA) const {
std::string ToolChain::GetFilePath(const char *Name) const {
return D.GetFilePath(Name, *this);
-
}
std::string ToolChain::GetProgramPath(const char *Name) const {
@@ -209,10 +359,9 @@ std::string ToolChain::GetLinkerPath() const {
return "";
}
- return GetProgramPath("ld");
+ return GetProgramPath(DefaultLinker);
}
-
types::ID ToolChain::LookupTypeForExtension(const char *Ext) const {
return types::lookupTypeForExtension(Ext);
}
@@ -244,11 +393,13 @@ ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
bool ToolChain::isThreadModelSupported(const StringRef Model) const {
if (Model == "single") {
- // FIXME: 'single' is only supported on ARM so far.
+ // FIXME: 'single' is only supported on ARM and WebAssembly so far.
return Triple.getArch() == llvm::Triple::arm ||
Triple.getArch() == llvm::Triple::armeb ||
Triple.getArch() == llvm::Triple::thumb ||
- Triple.getArch() == llvm::Triple::thumbeb;
+ Triple.getArch() == llvm::Triple::thumbeb ||
+ Triple.getArch() == llvm::Triple::wasm32 ||
+ Triple.getArch() == llvm::Triple::wasm64;
} else if (Model == "posix")
return true;
@@ -310,15 +461,15 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
MCPU = A->getValue();
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
MArch = A->getValue();
- std::string CPU = Triple.isOSBinFormatMachO()
- ? tools::arm::getARMCPUForMArch(MArch, Triple)
- : tools::arm::getARMTargetCPU(MCPU, MArch, Triple);
- StringRef Suffix =
- tools::arm::getLLVMArchSuffixForARM(CPU,
- tools::arm::getARMArch(MArch, Triple));
- bool ThumbDefault = Suffix.startswith("v6m") || Suffix.startswith("v7m") ||
- Suffix.startswith("v7em") ||
- (Suffix.startswith("v7") && getTriple().isOSBinFormatMachO());
+ std::string CPU =
+ Triple.isOSBinFormatMachO()
+ ? tools::arm::getARMCPUForMArch(MArch, Triple).str()
+ : tools::arm::getARMTargetCPU(MCPU, MArch, Triple);
+ StringRef Suffix =
+ tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
+ bool IsMProfile = ARM::parseArchProfile(Suffix) == ARM::PK_M;
+ bool ThumbDefault = IsMProfile || (ARM::parseArchVersion(Suffix) == 7 &&
+ getTriple().isOSBinFormatMachO());
// FIXME: this is invalid for WindowsCE
if (getTriple().isOSWindows())
ThumbDefault = true;
@@ -328,10 +479,9 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
else
ArchName = "arm";
- // Assembly files should start in ARM mode.
- if (InputType != types::TY_PP_Asm &&
- Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
- {
+ // Assembly files should start in ARM mode, unless arch is M-profile.
+ if ((InputType != types::TY_PP_Asm && Args.hasFlag(options::OPT_mthumb,
+ options::OPT_mno_thumb, ThumbDefault)) || IsMProfile) {
if (IsBigEndian)
ArchName = "thumbeb";
else
@@ -344,7 +494,7 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
}
}
-std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
+std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
types::ID InputType) const {
return ComputeLLVMTriple(Args, InputType);
}
@@ -360,9 +510,16 @@ void ToolChain::addClangTargetOptions(const ArgList &DriverArgs,
void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
+void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ if (!needsProfileRT(Args)) return;
+
+ CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));
+ return;
+}
+
ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
- const ArgList &Args) const
-{
+ const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) {
StringRef Value = A->getValue();
if (Value == "compiler-rt")
@@ -424,10 +581,9 @@ void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
ArgStringList &CC1Args,
ArrayRef<StringRef> Paths) {
- for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end();
- I != E; ++I) {
+ for (StringRef Path : Paths) {
CC1Args.push_back("-internal-isystem");
- CC1Args.push_back(DriverArgs.MakeArgString(*I));
+ CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
}
@@ -460,6 +616,13 @@ void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
}
}
+void ToolChain::AddFilePathLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ for (const auto &LibPath : getFilePaths())
+ if(LibPath.length() > 0)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
+}
+
void ToolChain::AddCCKextLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CmdArgs.push_back("-lcc_kext");
@@ -491,9 +654,15 @@ bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args,
SanitizerMask ToolChain::getSupportedSanitizers() const {
// Return sanitizers which don't require runtime support and are not
- // platform or architecture-dependent.
+ // platform dependent.
using namespace SanitizerKind;
- return (Undefined & ~Vptr & ~Function) | CFI | CFICastStrict |
- UnsignedIntegerOverflow | LocalBounds;
+ SanitizerMask Res = (Undefined & ~Vptr & ~Function) | (CFI & ~CFIICall) |
+ CFICastStrict | UnsignedIntegerOverflow | LocalBounds;
+ if (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64)
+ Res |= CFIICall;
+ return Res;
}
+void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
index 15e36a1..beede2e 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
@@ -1,4 +1,4 @@
-//===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
+//===--- ToolChains.cpp - ToolChain Implementations -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,6 +10,7 @@
#include "ToolChains.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -24,6 +25,7 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
+#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -65,6 +67,8 @@ bool MachO::HasNativeLLVMSupport() const { return true; }
/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
+ if (isTargetWatchOSBased())
+ return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion);
if (isTargetIOSBased())
return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
if (isNonFragile)
@@ -74,7 +78,9 @@ ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
bool Darwin::hasBlocksRuntime() const {
- if (isTargetIOSBased())
+ if (isTargetWatchOSBased())
+ return true;
+ else if (isTargetIOSBased())
return !isIPhoneOSVersionLT(3, 2);
else {
assert(isTargetMacOS() && "unexpected darwin target");
@@ -104,10 +110,10 @@ static const char *ArmMachOArchName(StringRef Arch) {
}
static const char *ArmMachOArchNameCPU(StringRef CPU) {
- unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(CPU);
+ unsigned ArchKind = llvm::ARM::parseCPUArch(CPU);
if (ArchKind == llvm::ARM::AK_INVALID)
return nullptr;
- StringRef Arch = llvm::ARMTargetParser::getArchName(ArchKind);
+ StringRef Arch = llvm::ARM::getArchName(ArchKind);
// FIXME: Make sure this MachO triple mangling is really necessary.
// ARMv5* normalises to ARMv5.
@@ -142,7 +148,7 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const {
return "arm64";
case llvm::Triple::thumb:
- case llvm::Triple::arm: {
+ case llvm::Triple::arm:
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
if (const char *Arch = ArmMachOArchName(A->getValue()))
return Arch;
@@ -153,7 +159,6 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const {
return "arm";
}
- }
}
Darwin::~Darwin() {}
@@ -177,7 +182,14 @@ std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
return Triple.getTriple();
SmallString<16> Str;
- Str += isTargetIOSBased() ? "ios" : "macosx";
+ if (isTargetWatchOSBased())
+ Str += "watchos";
+ else if (isTargetTvOSBased())
+ Str += "tvos";
+ else if (isTargetIOSBased())
+ Str += "ios";
+ else
+ Str += "macosx";
Str += getTargetVersion().getAsString();
Triple.setOSName(Str);
@@ -216,16 +228,17 @@ DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
: Darwin(D, Triple, Args) {}
void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
- // For iOS, 64-bit, promote certain warnings to errors.
- if (!isTargetMacOS() && getTriple().isArch64Bit()) {
+ // For modern targets, promote certain warnings to errors.
+ if (isTargetWatchOSBased() || getTriple().isArch64Bit()) {
// Always enable -Wdeprecated-objc-isa-usage and promote it
// to an error.
CC1Args.push_back("-Wdeprecated-objc-isa-usage");
CC1Args.push_back("-Werror=deprecated-objc-isa-usage");
- // Also error about implicit function declarations, as that
- // can impact calling conventions.
- CC1Args.push_back("-Werror=implicit-function-declaration");
+ // For iOS and watchOS, also error about implicit function declarations,
+ // as that can impact calling conventions.
+ if (!isTargetMacOS())
+ CC1Args.push_back("-Werror=implicit-function-declaration");
}
}
@@ -253,7 +266,15 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args,
llvm::sys::path::remove_filename(P); // 'bin'
llvm::sys::path::append(P, "lib", "arc", "libarclite_");
// Mash in the platform.
- if (isTargetIOSSimulator())
+ if (isTargetWatchOSSimulator())
+ P += "watchsimulator";
+ else if (isTargetWatchOS())
+ P += "watchos";
+ else if (isTargetTvOSSimulator())
+ P += "appletvsimulator";
+ else if (isTargetTvOS())
+ P += "appletvos";
+ else if (isTargetIOSSimulator())
P += "iphonesimulator";
else if (isTargetIPhoneOS())
P += "iphoneos";
@@ -276,7 +297,7 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build (unless
// we explicitly force linking with this library).
- if (AlwaysLink || llvm::sys::fs::exists(P))
+ if (AlwaysLink || getVFS().exists(P))
CmdArgs.push_back(Args.MakeArgString(P));
// Adding the rpaths might negatively interact when other rpaths are involved,
@@ -300,23 +321,38 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
void Darwin::addProfileRTLibs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- if (!(Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
- false) ||
- Args.hasArg(options::OPT_fprofile_generate) ||
- Args.hasArg(options::OPT_fprofile_generate_EQ) ||
- Args.hasArg(options::OPT_fprofile_instr_generate) ||
- Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
- Args.hasArg(options::OPT_fcreate_profile) ||
- Args.hasArg(options::OPT_coverage)))
- return;
+ if (!needsProfileRT(Args)) return;
+
+ // TODO: Clean this up once autoconf is gone
+ SmallString<128> P(getDriver().ResourceDir);
+ llvm::sys::path::append(P, "lib", "darwin");
+ const char *Library = "libclang_rt.profile_osx.a";
// Select the appropriate runtime library for the target.
- if (isTargetIOSBased())
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a",
- /*AlwaysLink*/ true);
- else
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_osx.a",
- /*AlwaysLink*/ true);
+ if (isTargetWatchOS()) {
+ Library = "libclang_rt.profile_watchos.a";
+ } else if (isTargetWatchOSSimulator()) {
+ llvm::sys::path::append(P, "libclang_rt.profile_watchossim.a");
+ Library = getVFS().exists(P) ? "libclang_rt.profile_watchossim.a"
+ : "libclang_rt.profile_watchos.a";
+ } else if (isTargetTvOS()) {
+ Library = "libclang_rt.profile_tvos.a";
+ } else if (isTargetTvOSSimulator()) {
+ llvm::sys::path::append(P, "libclang_rt.profile_tvossim.a");
+ Library = getVFS().exists(P) ? "libclang_rt.profile_tvossim.a"
+ : "libclang_rt.profile_tvos.a";
+ } else if (isTargetIPhoneOS()) {
+ Library = "libclang_rt.profile_ios.a";
+ } else if (isTargetIOSSimulator()) {
+ llvm::sys::path::append(P, "libclang_rt.profile_iossim.a");
+ Library = getVFS().exists(P) ? "libclang_rt.profile_iossim.a"
+ : "libclang_rt.profile_ios.a";
+ } else {
+ assert(isTargetMacOS() && "unexpected non MacOS platform");
+ }
+ AddLinkRuntimeLib(Args, CmdArgs, Library,
+ /*AlwaysLink*/ true);
+ return;
}
void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
@@ -327,6 +363,7 @@ void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
// Sanitizer runtime libraries requires C++.
AddCXXStdlibLibArgs(Args, CmdArgs);
}
+ // ASan is not supported on watchOS.
assert(isTargetMacOS() || isTargetIOSSimulator());
StringRef OS = isTargetMacOS() ? "osx" : "iossim";
AddLinkRuntimeLib(
@@ -374,13 +411,21 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
if (Sanitize.needsUbsanRt())
AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
+ if (Sanitize.needsTsanRt())
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
// Otherwise link libSystem, then the dynamic runtime library, and finally any
// target specific static runtime library.
CmdArgs.push_back("-lSystem");
// Select the dynamic runtime library and the target specific static library.
- if (isTargetIOSBased()) {
+ if (isTargetWatchOSBased()) {
+ // We currently always need a static runtime library for watchOS.
+ AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.watchos.a");
+ } else if (isTargetTvOSBased()) {
+ // We currently always need a static runtime library for tvOS.
+ AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.tvos.a");
+ } else if (isTargetIOSBased()) {
// If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
// it never went into the SDK.
// Linking against libgcc_s.1 isn't needed for iOS 5.0+
@@ -425,13 +470,13 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
// isysroot.
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
// Warn if the path does not exist.
- if (!llvm::sys::fs::exists(A->getValue()))
+ if (!getVFS().exists(A->getValue()))
getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
} else {
if (char *env = ::getenv("SDKROOT")) {
// We only use this value as the default if it is an absolute path,
// exists, and it is not the root path.
- if (llvm::sys::path::is_absolute(env) && llvm::sys::fs::exists(env) &&
+ if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&
StringRef(env) != "/") {
Args.append(Args.MakeSeparateArg(
nullptr, Opts.getOption(options::OPT_isysroot), env));
@@ -441,26 +486,47 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ);
+ Arg *TvOSVersion = Args.getLastArg(options::OPT_mtvos_version_min_EQ);
+ Arg *WatchOSVersion = Args.getLastArg(options::OPT_mwatchos_version_min_EQ);
- if (OSXVersion && iOSVersion) {
+ if (OSXVersion && (iOSVersion || TvOSVersion || WatchOSVersion)) {
+ getDriver().Diag(diag::err_drv_argument_not_allowed_with)
+ << OSXVersion->getAsString(Args)
+ << (iOSVersion ? iOSVersion :
+ TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
+ iOSVersion = TvOSVersion = WatchOSVersion = nullptr;
+ } else if (iOSVersion && (TvOSVersion || WatchOSVersion)) {
getDriver().Diag(diag::err_drv_argument_not_allowed_with)
- << OSXVersion->getAsString(Args) << iOSVersion->getAsString(Args);
- iOSVersion = nullptr;
- } else if (!OSXVersion && !iOSVersion) {
+ << iOSVersion->getAsString(Args)
+ << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
+ TvOSVersion = WatchOSVersion = nullptr;
+ } else if (TvOSVersion && WatchOSVersion) {
+ getDriver().Diag(diag::err_drv_argument_not_allowed_with)
+ << TvOSVersion->getAsString(Args)
+ << WatchOSVersion->getAsString(Args);
+ WatchOSVersion = nullptr;
+ } else if (!OSXVersion && !iOSVersion && !TvOSVersion && !WatchOSVersion) {
// If no deployment target was specified on the command line, check for
// environment defines.
std::string OSXTarget;
std::string iOSTarget;
+ std::string TvOSTarget;
+ std::string WatchOSTarget;
+
if (char *env = ::getenv("MACOSX_DEPLOYMENT_TARGET"))
OSXTarget = env;
if (char *env = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"))
iOSTarget = env;
+ if (char *env = ::getenv("TVOS_DEPLOYMENT_TARGET"))
+ TvOSTarget = env;
+ if (char *env = ::getenv("WATCHOS_DEPLOYMENT_TARGET"))
+ WatchOSTarget = env;
// If there is no command-line argument to specify the Target version and
// no environment variable defined, see if we can set the default based
// on -isysroot.
- if (iOSTarget.empty() && OSXTarget.empty() &&
- Args.hasArg(options::OPT_isysroot)) {
+ if (OSXTarget.empty() && iOSTarget.empty() && WatchOSTarget.empty() &&
+ TvOSTarget.empty() && Args.hasArg(options::OPT_isysroot)) {
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
StringRef isysroot = A->getValue();
// Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
@@ -479,6 +545,12 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
iOSTarget = Version;
else if (SDK.startswith("MacOSX"))
OSXTarget = Version;
+ else if (SDK.startswith("WatchOS") ||
+ SDK.startswith("WatchSimulator"))
+ WatchOSTarget = Version;
+ else if (SDK.startswith("AppleTVOS") ||
+ SDK.startswith("AppleTVSimulator"))
+ TvOSTarget = Version;
}
}
}
@@ -486,7 +558,8 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
// If no OSX or iOS target has been specified, try to guess platform
// from arch name and compute the version from the triple.
- if (OSXTarget.empty() && iOSTarget.empty()) {
+ if (OSXTarget.empty() && iOSTarget.empty() && TvOSTarget.empty() &&
+ WatchOSTarget.empty()) {
StringRef MachOArchName = getMachOArchName(Args);
unsigned Major, Minor, Micro;
if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
@@ -494,6 +567,10 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
getTriple().getiOSVersion(Major, Minor, Micro);
llvm::raw_string_ostream(iOSTarget) << Major << '.' << Minor << '.'
<< Micro;
+ } else if (MachOArchName == "armv7k") {
+ getTriple().getWatchOSVersion(Major, Minor, Micro);
+ llvm::raw_string_ostream(WatchOSTarget) << Major << '.' << Minor << '.'
+ << Micro;
} else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
MachOArchName != "armv7em") {
if (!getTriple().getMacOSXVersion(Major, Minor, Micro)) {
@@ -505,15 +582,32 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
}
}
+ // Do not allow conflicts with the watchOS target.
+ if (!WatchOSTarget.empty() && (!iOSTarget.empty() || !TvOSTarget.empty())) {
+ getDriver().Diag(diag::err_drv_conflicting_deployment_targets)
+ << "WATCHOS_DEPLOYMENT_TARGET"
+ << (!iOSTarget.empty() ? "IPHONEOS_DEPLOYMENT_TARGET" :
+ "TVOS_DEPLOYMENT_TARGET");
+ }
+
+ // Do not allow conflicts with the tvOS target.
+ if (!TvOSTarget.empty() && !iOSTarget.empty()) {
+ getDriver().Diag(diag::err_drv_conflicting_deployment_targets)
+ << "TVOS_DEPLOYMENT_TARGET"
+ << "IPHONEOS_DEPLOYMENT_TARGET";
+ }
+
// Allow conflicts among OSX and iOS for historical reasons, but choose the
// default platform.
- if (!OSXTarget.empty() && !iOSTarget.empty()) {
+ if (!OSXTarget.empty() && (!iOSTarget.empty() ||
+ !WatchOSTarget.empty() ||
+ !TvOSTarget.empty())) {
if (getTriple().getArch() == llvm::Triple::arm ||
getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::thumb)
OSXTarget = "";
else
- iOSTarget = "";
+ iOSTarget = WatchOSTarget = TvOSTarget = "";
}
if (!OSXTarget.empty()) {
@@ -524,6 +618,14 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
iOSVersion = Args.MakeJoinedArg(nullptr, O, iOSTarget);
Args.append(iOSVersion);
+ } else if (!TvOSTarget.empty()) {
+ const Option O = Opts.getOption(options::OPT_mtvos_version_min_EQ);
+ TvOSVersion = Args.MakeJoinedArg(nullptr, O, TvOSTarget);
+ Args.append(TvOSVersion);
+ } else if (!WatchOSTarget.empty()) {
+ const Option O = Opts.getOption(options::OPT_mwatchos_version_min_EQ);
+ WatchOSVersion = Args.MakeJoinedArg(nullptr, O, WatchOSTarget);
+ Args.append(WatchOSVersion);
}
}
@@ -532,6 +634,10 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
Platform = MacOS;
else if (iOSVersion)
Platform = IPhoneOS;
+ else if (TvOSVersion)
+ Platform = TvOS;
+ else if (WatchOSVersion)
+ Platform = WatchOS;
else
llvm_unreachable("Unable to infer Darwin variant");
@@ -539,7 +645,8 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
unsigned Major, Minor, Micro;
bool HadExtra;
if (Platform == MacOS) {
- assert(!iOSVersion && "Unknown target platform!");
+ assert((!iOSVersion && !TvOSVersion && !WatchOSVersion) &&
+ "Unknown target platform!");
if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, Micro,
HadExtra) ||
HadExtra || Major != 10 || Minor >= 100 || Micro >= 100)
@@ -552,6 +659,18 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
<< iOSVersion->getAsString(Args);
+ } else if (Platform == TvOS) {
+ if (!Driver::GetReleaseVersion(TvOSVersion->getValue(), Major, Minor,
+ Micro, HadExtra) || HadExtra ||
+ Major >= 10 || Minor >= 100 || Micro >= 100)
+ getDriver().Diag(diag::err_drv_invalid_version_number)
+ << TvOSVersion->getAsString(Args);
+ } else if (Platform == WatchOS) {
+ if (!Driver::GetReleaseVersion(WatchOSVersion->getValue(), Major, Minor,
+ Micro, HadExtra) || HadExtra ||
+ Major >= 10 || Minor >= 100 || Micro >= 100)
+ getDriver().Diag(diag::err_drv_invalid_version_number)
+ << WatchOSVersion->getAsString(Args);
} else
llvm_unreachable("unknown kind of Darwin platform");
@@ -559,6 +678,12 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
if (iOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64))
Platform = IPhoneOSSimulator;
+ if (TvOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64))
+ Platform = TvOSSimulator;
+ if (WatchOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64))
+ Platform = WatchOSSimulator;
setTarget(Platform, Major, Minor, Micro);
}
@@ -572,7 +697,7 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
CmdArgs.push_back("-lc++");
break;
- case ToolChain::CST_Libstdcxx: {
+ case ToolChain::CST_Libstdcxx:
// Unfortunately, -lstdc++ doesn't always exist in the standard search path;
// it was previously found in the gcc lib dir. However, for all the Darwin
// platforms we care about it was -lstdc++.6, so we search for that
@@ -583,10 +708,10 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
SmallString<128> P(A->getValue());
llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
- if (!llvm::sys::fs::exists(P)) {
+ if (!getVFS().exists(P)) {
llvm::sys::path::remove_filename(P);
llvm::sys::path::append(P, "libstdc++.6.dylib");
- if (llvm::sys::fs::exists(P)) {
+ if (getVFS().exists(P)) {
CmdArgs.push_back(Args.MakeArgString(P));
return;
}
@@ -596,8 +721,8 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
// Otherwise, look in the root.
// FIXME: This should be removed someday when we don't have to care about
// 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
- if (!llvm::sys::fs::exists("/usr/lib/libstdc++.dylib") &&
- llvm::sys::fs::exists("/usr/lib/libstdc++.6.dylib")) {
+ if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&
+ getVFS().exists("/usr/lib/libstdc++.6.dylib")) {
CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
return;
}
@@ -606,7 +731,6 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
CmdArgs.push_back("-lstdc++");
break;
}
- }
}
void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
@@ -620,17 +744,19 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
llvm::sys::path::append(P, "lib", "darwin");
// Use the newer cc_kext for iOS ARM after 6.0.
- if (!isTargetIPhoneOS() || isTargetIOSSimulator() ||
- getTriple().getArch() == llvm::Triple::aarch64 ||
- !isIPhoneOSVersionLT(6, 0)) {
- llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
+ if (isTargetWatchOS()) {
+ llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a");
+ } else if (isTargetTvOS()) {
+ llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");
+ } else if (isTargetIPhoneOS()) {
+ llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");
} else {
- llvm::sys::path::append(P, "libclang_rt.cc_kext_ios5.a");
+ llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
}
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build.
- if (llvm::sys::fs::exists(P))
+ if (getVFS().exists(P))
CmdArgs.push_back(Args.MakeArgString(P));
}
@@ -856,7 +982,7 @@ void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
// { hard-float, soft-float }
llvm::SmallString<32> CompilerRT = StringRef("libclang_rt.");
CompilerRT +=
- tools::arm::getARMFloatABI(getDriver(), Args, getTriple()) == "hard"
+ (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)
? "hard"
: "soft";
CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic.a" : "_static.a";
@@ -883,8 +1009,9 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
// FIXME: It would be far better to avoid inserting those -static arguments,
// but we can't check the deployment target in the translation code until
// it is set here.
- if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0)) {
- for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie;) {
+ if (isTargetWatchOSBased() ||
+ (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {
+ for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
Arg *A = *it;
++it;
if (A->getOption().getID() != options::OPT_mkernel &&
@@ -900,7 +1027,8 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
// Default to use libc++ on OS X 10.9+ and iOS 7+.
if (((isTargetMacOS() && !isMacosxVersionLT(10, 9)) ||
- (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0))) &&
+ (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0)) ||
+ isTargetWatchOSBased()) &&
!Args.getLastArg(options::OPT_stdlib_EQ))
DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_stdlib_EQ),
"libc++");
@@ -933,10 +1061,14 @@ bool MachO::UseDwarfDebugFlags() const {
return false;
}
-bool Darwin::UseSjLjExceptions() const {
+bool Darwin::UseSjLjExceptions(const ArgList &Args) const {
// Darwin uses SjLj exceptions on ARM.
- return (getTriple().getArch() == llvm::Triple::arm ||
- getTriple().getArch() == llvm::Triple::thumb);
+ if (getTriple().getArch() != llvm::Triple::arm &&
+ getTriple().getArch() != llvm::Triple::thumb)
+ return false;
+
+ // Only watchOS uses the new DWARF/Compact unwinding method.
+ return !isTargetWatchOS();
}
bool MachO::isPICDefault() const { return true; }
@@ -957,7 +1089,15 @@ void Darwin::addMinVersionArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
VersionTuple TargetVersion = getTargetVersion();
- if (isTargetIOSSimulator())
+ if (isTargetWatchOS())
+ CmdArgs.push_back("-watchos_version_min");
+ else if (isTargetWatchOSSimulator())
+ CmdArgs.push_back("-watchos_simulator_version_min");
+ else if (isTargetTvOS())
+ CmdArgs.push_back("-tvos_version_min");
+ else if (isTargetTvOSSimulator())
+ CmdArgs.push_back("-tvos_simulator_version_min");
+ else if (isTargetIOSSimulator())
CmdArgs.push_back("-ios_simulator_version_min");
else if (isTargetIOSBased())
CmdArgs.push_back("-iphoneos_version_min");
@@ -974,7 +1114,9 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args,
// Derived from startfile spec.
if (Args.hasArg(options::OPT_dynamiclib)) {
// Derived from darwin_dylib1 spec.
- if (isTargetIOSSimulator()) {
+ if (isTargetWatchOSBased()) {
+ ; // watchOS does not need dylib1.o.
+ } else if (isTargetIOSSimulator()) {
; // iOS simulator does not need dylib1.o.
} else if (isTargetIPhoneOS()) {
if (isIPhoneOSVersionLT(3, 1))
@@ -989,7 +1131,9 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args,
if (Args.hasArg(options::OPT_bundle)) {
if (!Args.hasArg(options::OPT_static)) {
// Derived from darwin_bundle1 spec.
- if (isTargetIOSSimulator()) {
+ if (isTargetWatchOSBased()) {
+ ; // watchOS does not need bundle1.o.
+ } else if (isTargetIOSSimulator()) {
; // iOS simulator does not need bundle1.o.
} else if (isTargetIPhoneOS()) {
if (isIPhoneOSVersionLT(3, 1))
@@ -1024,7 +1168,9 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args,
CmdArgs.push_back("-lcrt0.o");
} else {
// Derived from darwin_crt1 spec.
- if (isTargetIOSSimulator()) {
+ if (isTargetWatchOSBased()) {
+ ; // watchOS does not need crt1.o.
+ } else if (isTargetIOSSimulator()) {
; // iOS simulator does not need crt1.o.
} else if (isTargetIPhoneOS()) {
if (getArch() == llvm::Triple::aarch64)
@@ -1049,6 +1195,7 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args,
}
if (!isTargetIPhoneOS() && Args.hasArg(options::OPT_shared_libgcc) &&
+ !isTargetWatchOS() &&
isMacosxVersionLT(10, 5)) {
const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
CmdArgs.push_back(Str);
@@ -1058,7 +1205,8 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args,
bool Darwin::SupportsObjCGC() const { return isTargetMacOS(); }
void Darwin::CheckObjCARC() const {
- if (isTargetIOSBased() || (isTargetMacOS() && !isMacosxVersionLT(10, 6)))
+ if (isTargetIOSBased() || isTargetWatchOSBased() ||
+ (isTargetMacOS() && !isMacosxVersionLT(10, 6)))
return;
getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
}
@@ -1071,6 +1219,7 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
if (!isMacosxVersionLT(10, 9))
Res |= SanitizerKind::Vptr;
Res |= SanitizerKind::SafeStack;
+ Res |= SanitizerKind::Thread;
}
return Res;
}
@@ -1170,7 +1319,8 @@ static llvm::StringRef getGCCToolchainDir(const ArgList &Args) {
/// necessary because the driver doesn't store the final version of the target
/// triple.
void Generic_GCC::GCCInstallationDetector::init(
- const Driver &D, const llvm::Triple &TargetTriple, const ArgList &Args) {
+ const llvm::Triple &TargetTriple, const ArgList &Args,
+ ArrayRef<std::string> ExtraTripleAliases) {
llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit()
? TargetTriple.get64BitArchVariant()
: TargetTriple.get32BitArchVariant();
@@ -1212,20 +1362,22 @@ void Generic_GCC::GCCInstallationDetector::init(
// installation available. GCC installs are ranked by version number.
Version = GCCVersion::Parse("0.0.0");
for (const std::string &Prefix : Prefixes) {
- if (!llvm::sys::fs::exists(Prefix))
+ if (!D.getVFS().exists(Prefix))
continue;
- for (const StringRef Suffix : CandidateLibDirs) {
+ for (StringRef Suffix : CandidateLibDirs) {
const std::string LibDir = Prefix + Suffix.str();
- if (!llvm::sys::fs::exists(LibDir))
+ if (!D.getVFS().exists(LibDir))
continue;
- for (const StringRef Candidate : CandidateTripleAliases)
+ for (StringRef Candidate : ExtraTripleAliases) // Try these first.
+ ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate);
+ for (StringRef Candidate : CandidateTripleAliases)
ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate);
}
- for (const StringRef Suffix : CandidateBiarchLibDirs) {
+ for (StringRef Suffix : CandidateBiarchLibDirs) {
const std::string LibDir = Prefix + Suffix.str();
- if (!llvm::sys::fs::exists(LibDir))
+ if (!D.getVFS().exists(LibDir))
continue;
- for (const StringRef Candidate : CandidateBiarchTripleAliases)
+ for (StringRef Candidate : CandidateBiarchTripleAliases)
ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate,
/*NeedsBiarchSuffix=*/ true);
}
@@ -1300,8 +1452,9 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
"i586-linux-gnu"};
static const char *const MIPSLibDirs[] = {"/lib"};
- static const char *const MIPSTriples[] = {
- "mips-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu"};
+ static const char *const MIPSTriples[] = {"mips-linux-gnu", "mips-mti-linux",
+ "mips-mti-linux-gnu",
+ "mips-img-linux-gnu"};
static const char *const MIPSELLibDirs[] = {"/lib"};
static const char *const MIPSELTriples[] = {
"mipsel-linux-gnu", "mipsel-linux-android", "mips-img-linux-gnu"};
@@ -1340,9 +1493,20 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
"s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
"s390x-suse-linux", "s390x-redhat-linux"};
+ // Solaris.
+ static const char *const SolarisSPARCLibDirs[] = {"/gcc"};
+ static const char *const SolarisSPARCTriples[] = {"sparc-sun-solaris2.11",
+ "i386-pc-solaris2.11"};
+
using std::begin;
using std::end;
+ if (TargetTriple.getOS() == llvm::Triple::Solaris) {
+ LibDirs.append(begin(SolarisSPARCLibDirs), end(SolarisSPARCLibDirs));
+ TripleAliases.append(begin(SolarisSPARCTriples), end(SolarisSPARCTriples));
+ return;
+ }
+
switch (TargetTriple.getArch()) {
case llvm::Triple::aarch64:
LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));
@@ -1436,6 +1600,7 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
TripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples));
break;
case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
LibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs));
TripleAliases.append(begin(SPARCv8Triples), end(SPARCv8Triples));
BiarchLibDirs.append(begin(SPARCv9LibDirs), end(SPARCv9LibDirs));
@@ -1451,7 +1616,6 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
LibDirs.append(begin(SystemZLibDirs), end(SystemZLibDirs));
TripleAliases.append(begin(SystemZTriples), end(SystemZTriples));
break;
-
default:
// By default, just rely on the standard lib directories and the original
// triple.
@@ -1467,15 +1631,83 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
BiarchTripleAliases.push_back(BiarchTriple.str());
}
+// \brief -- try common CUDA installation paths looking for files we need for
+// CUDA compilation.
+
+void Generic_GCC::CudaInstallationDetector::init(
+ const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args) {
+ SmallVector<std::string, 4> CudaPathCandidates;
+
+ if (Args.hasArg(options::OPT_cuda_path_EQ))
+ CudaPathCandidates.push_back(
+ Args.getLastArgValue(options::OPT_cuda_path_EQ));
+ else {
+ CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda");
+ CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-7.5");
+ CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-7.0");
+ }
+
+ for (const auto &CudaPath : CudaPathCandidates) {
+ if (CudaPath.empty() || !D.getVFS().exists(CudaPath))
+ continue;
+
+ CudaInstallPath = CudaPath;
+ CudaIncludePath = CudaInstallPath + "/include";
+ CudaLibDevicePath = CudaInstallPath + "/nvvm/libdevice";
+ CudaLibPath =
+ CudaInstallPath + (TargetTriple.isArch64Bit() ? "/lib64" : "/lib");
+
+ if (!(D.getVFS().exists(CudaIncludePath) &&
+ D.getVFS().exists(CudaLibPath) &&
+ D.getVFS().exists(CudaLibDevicePath)))
+ continue;
+
+ std::error_code EC;
+ for (llvm::sys::fs::directory_iterator LI(CudaLibDevicePath, EC), LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef FilePath = LI->path();
+ StringRef FileName = llvm::sys::path::filename(FilePath);
+ // Process all bitcode filenames that look like libdevice.compute_XX.YY.bc
+ const StringRef LibDeviceName = "libdevice.";
+ if (!(FileName.startswith(LibDeviceName) && FileName.endswith(".bc")))
+ continue;
+ StringRef GpuArch = FileName.slice(
+ LibDeviceName.size(), FileName.find('.', LibDeviceName.size()));
+ CudaLibDeviceMap[GpuArch] = FilePath.str();
+ // Insert map entries for specifc devices with this compute capability.
+ if (GpuArch == "compute_20") {
+ CudaLibDeviceMap["sm_20"] = FilePath;
+ CudaLibDeviceMap["sm_21"] = FilePath;
+ } else if (GpuArch == "compute_30") {
+ CudaLibDeviceMap["sm_30"] = FilePath;
+ CudaLibDeviceMap["sm_32"] = FilePath;
+ } else if (GpuArch == "compute_35") {
+ CudaLibDeviceMap["sm_35"] = FilePath;
+ CudaLibDeviceMap["sm_37"] = FilePath;
+ }
+ }
+
+ IsValid = true;
+ break;
+ }
+}
+
+void Generic_GCC::CudaInstallationDetector::print(raw_ostream &OS) const {
+ if (isValid())
+ OS << "Found CUDA installation: " << CudaInstallPath << "\n";
+}
+
namespace {
// Filter to remove Multilibs that don't exist as a suffix to Path
class FilterNonExistent {
StringRef Base;
+ vfs::FileSystem &VFS;
public:
- FilterNonExistent(StringRef Base) : Base(Base) {}
+ FilterNonExistent(StringRef Base, vfs::FileSystem &VFS)
+ : Base(Base), VFS(VFS) {}
bool operator()(const Multilib &M) {
- return !llvm::sys::fs::exists(Base + M.gccSuffix() + "/crtbegin.o");
+ return !VFS.exists(Base + M.gccSuffix() + "/crtbegin.o");
}
};
} // end anonymous namespace
@@ -1515,6 +1747,7 @@ static bool isMicroMips(const ArgList &Args) {
return A && A->getOption().matches(options::OPT_mmicromips);
}
+namespace {
struct DetectedMultilibs {
/// The set of multilibs that the detected installation supports.
MultilibSet Multilibs;
@@ -1526,13 +1759,15 @@ struct DetectedMultilibs {
/// targeting the non-default multilib. Otherwise, it is empty.
llvm::Optional<Multilib> BiarchSibling;
};
+} // end anonymous namespace
static Multilib makeMultilib(StringRef commonSuffix) {
return Multilib(commonSuffix, commonSuffix, commonSuffix);
}
-static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
- const ArgList &Args, DetectedMultilibs &Result) {
+static bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
+ StringRef Path, const ArgList &Args,
+ DetectedMultilibs &Result) {
// Some MIPS toolchains put libraries and object files compiled
// using different options in to the sub-directoris which names
// reflects the flags used for compilation. For example sysroot
@@ -1558,7 +1793,7 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
// /usr
// /lib <= crt*.o files compiled with '-mips32'
- FilterNonExistent NonExistent(Path);
+ FilterNonExistent NonExistent(Path, D.getVFS());
// Check for FSF toolchain multilibs
MultilibSet FSFMipsMultilibs;
@@ -1636,6 +1871,32 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
});
}
+ // Check for Musl toolchain multilibs
+ MultilibSet MuslMipsMultilibs;
+ {
+ auto MArchMipsR2 = makeMultilib("")
+ .osSuffix("/mips-r2-hard-musl")
+ .flag("+EB")
+ .flag("-EL")
+ .flag("+march=mips32r2");
+
+ auto MArchMipselR2 = makeMultilib("/mipsel-r2-hard-musl")
+ .flag("-EB")
+ .flag("+EL")
+ .flag("+march=mips32r2");
+
+ MuslMipsMultilibs = MultilibSet().Either(MArchMipsR2, MArchMipselR2);
+
+ // Specify the callback that computes the include directories.
+ MuslMipsMultilibs.setIncludeDirsCallback([](
+ StringRef InstallDir, StringRef TripleStr, const Multilib &M) {
+ std::vector<std::string> Dirs;
+ Dirs.push_back(
+ (InstallDir + "/../sysroot" + M.osSuffix() + "/usr/include").str());
+ return Dirs;
+ });
+ }
+
// Check for Code Sourcery toolchain multilibs
MultilibSet CSMipsMultilibs;
{
@@ -1754,7 +2015,7 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
addMultilibFlag(isMips16(Args), "mips16", Flags);
addMultilibFlag(CPUName == "mips32", "march=mips32", Flags);
addMultilibFlag(CPUName == "mips32r2" || CPUName == "mips32r3" ||
- CPUName == "mips32r5",
+ CPUName == "mips32r5" || CPUName == "p5600",
"march=mips32r2", Flags);
addMultilibFlag(CPUName == "mips32r6", "march=mips32r6", Flags);
addMultilibFlag(CPUName == "mips64", "march=mips64", Flags);
@@ -1772,7 +2033,7 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
addMultilibFlag(isMipsEL(TargetArch), "EL", Flags);
addMultilibFlag(!isMipsEL(TargetArch), "EB", Flags);
- if (TargetTriple.getEnvironment() == llvm::Triple::Android) {
+ if (TargetTriple.isAndroid()) {
// Select Android toolchain. It's the only choice in that case.
if (AndroidMipsMultilibs.select(Flags, Result.SelectedMultilib)) {
Result.Multilibs = AndroidMipsMultilibs;
@@ -1781,6 +2042,16 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
return false;
}
+ if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies &&
+ TargetTriple.getOS() == llvm::Triple::Linux &&
+ TargetTriple.getEnvironment() == llvm::Triple::UnknownEnvironment) {
+ if (MuslMipsMultilibs.select(Flags, Result.SelectedMultilib)) {
+ Result.Multilibs = MuslMipsMultilibs;
+ return true;
+ }
+ return false;
+ }
+
if (TargetTriple.getVendor() == llvm::Triple::ImaginationTechnologies &&
TargetTriple.getOS() == llvm::Triple::Linux &&
TargetTriple.getEnvironment() == llvm::Triple::GNU) {
@@ -1823,11 +2094,11 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
return false;
}
-static bool findBiarchMultilibs(const llvm::Triple &TargetTriple,
+static bool findBiarchMultilibs(const Driver &D,
+ const llvm::Triple &TargetTriple,
StringRef Path, const ArgList &Args,
bool NeedsBiarchSuffix,
DetectedMultilibs &Result) {
-
// Some versions of SUSE and Fedora on ppc64 put 32-bit libs
// in what would normally be GCCInstallPath and put the 64-bit
// libs in a subdirectory named 64. The simple logic we follow is that
@@ -1855,7 +2126,7 @@ static bool findBiarchMultilibs(const llvm::Triple &TargetTriple,
.flag("-m64")
.flag("+mx32");
- FilterNonExistent NonExistent(Path);
+ FilterNonExistent NonExistent(Path, D.getVFS());
// Determine default multilib from: 32, 64, x32
// Also handle cases such as 64 on 32, 32 on 64, etc.
@@ -1907,6 +2178,56 @@ static bool findBiarchMultilibs(const llvm::Triple &TargetTriple,
return true;
}
+void Generic_GCC::GCCInstallationDetector::scanLibDirForGCCTripleSolaris(
+ const llvm::Triple &TargetArch, const llvm::opt::ArgList &Args,
+ const std::string &LibDir, StringRef CandidateTriple,
+ bool NeedsBiarchSuffix) {
+ // Solaris is a special case. The GCC installation is under
+ // /usr/gcc/<major>.<minor>/lib/gcc/<triple>/<major>.<minor>.<patch>/, so we
+ // need to iterate twice.
+ std::error_code EC;
+ for (vfs::directory_iterator LI = D.getVFS().dir_begin(LibDir, EC), LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef VersionText = llvm::sys::path::filename(LI->getName());
+ GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
+
+ if (CandidateVersion.Major != -1) // Filter obviously bad entries.
+ if (!CandidateGCCInstallPaths.insert(LI->getName()).second)
+ continue; // Saw this path before; no need to look at it again.
+ if (CandidateVersion.isOlderThan(4, 1, 1))
+ continue;
+ if (CandidateVersion <= Version)
+ continue;
+
+ GCCInstallPath =
+ LibDir + "/" + VersionText.str() + "/lib/gcc/" + CandidateTriple.str();
+ if (!D.getVFS().exists(GCCInstallPath))
+ continue;
+
+ // If we make it here there has to be at least one GCC version, let's just
+ // use the latest one.
+ std::error_code EEC;
+ for (vfs::directory_iterator
+ LLI = D.getVFS().dir_begin(GCCInstallPath, EEC),
+ LLE;
+ !EEC && LLI != LLE; LLI = LLI.increment(EEC)) {
+
+ StringRef SubVersionText = llvm::sys::path::filename(LLI->getName());
+ GCCVersion CandidateSubVersion = GCCVersion::Parse(SubVersionText);
+
+ if (CandidateSubVersion > Version)
+ Version = CandidateSubVersion;
+ }
+
+ GCCTriple.setTriple(CandidateTriple);
+
+ GCCInstallPath += "/" + Version.Text;
+ GCCParentLibPath = GCCInstallPath + "/../../../../";
+
+ IsValid = true;
+ }
+}
+
void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
const llvm::Triple &TargetTriple, const ArgList &Args,
const std::string &LibDir, StringRef CandidateTriple,
@@ -1914,41 +2235,48 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
// There are various different suffixes involving the triple we
// check for. We also record what is necessary to walk from each back
- // up to the lib directory.
- const std::string LibSuffixes[] = {
- "/gcc/" + CandidateTriple.str(),
+ // up to the lib directory. Specifically, the number of "up" steps
+ // in the second half of each row is 1 + the number of path separators
+ // in the first half.
+ const std::string LibAndInstallSuffixes[][2] = {
+ {"/gcc/" + CandidateTriple.str(), "/../../.."},
+
// Debian puts cross-compilers in gcc-cross
- "/gcc-cross/" + CandidateTriple.str(),
- "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(),
+ {"/gcc-cross/" + CandidateTriple.str(), "/../../.."},
+
+ {"/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(),
+ "/../../../.."},
// The Freescale PPC SDK has the gcc libraries in
// <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well.
- "/" + CandidateTriple.str(),
+ {"/" + CandidateTriple.str(), "/../.."},
// Ubuntu has a strange mis-matched pair of triples that this happens to
// match.
// FIXME: It may be worthwhile to generalize this and look for a second
// triple.
- "/i386-linux-gnu/gcc/" + CandidateTriple.str()};
- const std::string InstallSuffixes[] = {
- "/../../..", // gcc/
- "/../../..", // gcc-cross/
- "/../../../..", // <triple>/gcc/
- "/../..", // <triple>/
- "/../../../.." // i386-linux-gnu/gcc/<triple>/
- };
+ {"/i386-linux-gnu/gcc/" + CandidateTriple.str(), "/../../../.."}};
+
+ if (TargetTriple.getOS() == llvm::Triple::Solaris) {
+ scanLibDirForGCCTripleSolaris(TargetTriple, Args, LibDir, CandidateTriple,
+ NeedsBiarchSuffix);
+ return;
+ }
+
// Only look at the final, weird Ubuntu suffix for i386-linux-gnu.
- const unsigned NumLibSuffixes =
- (llvm::array_lengthof(LibSuffixes) - (TargetArch != llvm::Triple::x86));
+ const unsigned NumLibSuffixes = (llvm::array_lengthof(LibAndInstallSuffixes) -
+ (TargetArch != llvm::Triple::x86));
for (unsigned i = 0; i < NumLibSuffixes; ++i) {
- StringRef LibSuffix = LibSuffixes[i];
+ StringRef LibSuffix = LibAndInstallSuffixes[i][0];
std::error_code EC;
- for (llvm::sys::fs::directory_iterator LI(LibDir + LibSuffix, EC), LE;
+ for (vfs::directory_iterator
+ LI = D.getVFS().dir_begin(LibDir + LibSuffix, EC),
+ LE;
!EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->path());
+ StringRef VersionText = llvm::sys::path::filename(LI->getName());
GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
if (CandidateVersion.Major != -1) // Filter obviously bad entries.
- if (!CandidateGCCInstallPaths.insert(LI->path()).second)
+ if (!CandidateGCCInstallPaths.insert(LI->getName()).second)
continue; // Saw this path before; no need to look at it again.
if (CandidateVersion.isOlderThan(4, 1, 1))
continue;
@@ -1960,9 +2288,9 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
// Debian mips multilibs behave more like the rest of the biarch ones,
// so handle them there
if (isMipsArch(TargetArch)) {
- if (!findMIPSMultilibs(TargetTriple, LI->path(), Args, Detected))
+ if (!findMIPSMultilibs(D, TargetTriple, LI->getName(), Args, Detected))
continue;
- } else if (!findBiarchMultilibs(TargetTriple, LI->path(), Args,
+ } else if (!findBiarchMultilibs(D, TargetTriple, LI->getName(), Args,
NeedsBiarchSuffix, Detected)) {
continue;
}
@@ -1975,8 +2303,9 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
// FIXME: We hack together the directory name here instead of
// using LI to ensure stable path separators across Windows and
// Linux.
- GCCInstallPath = LibDir + LibSuffixes[i] + "/" + VersionText.str();
- GCCParentLibPath = GCCInstallPath + InstallSuffixes[i];
+ GCCInstallPath =
+ LibDir + LibAndInstallSuffixes[i][0] + "/" + VersionText.str();
+ GCCParentLibPath = GCCInstallPath + LibAndInstallSuffixes[i][1];
IsValid = true;
}
}
@@ -1984,7 +2313,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : ToolChain(D, Triple, Args), GCCInstallation() {
+ : ToolChain(D, Triple, Args), GCCInstallation(D), CudaInstallation(D) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
@@ -2016,6 +2345,7 @@ Tool *Generic_GCC::buildLinker() const { return new tools::gcc::Linker(*this); }
void Generic_GCC::printVerboseInfo(raw_ostream &OS) const {
// Print the information about how we detected the GCC installation.
GCCInstallation.print(OS);
+ CudaInstallation.print(OS);
}
bool Generic_GCC::IsUnwindTablesDefault() const {
@@ -2047,9 +2377,6 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
- case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
- case llvm::Triple::sparcv9:
case llvm::Triple::systemz:
return true;
default:
@@ -2057,6 +2384,40 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
}
}
+/// \brief Helper to add the variant paths of a libstdc++ installation.
+bool Generic_GCC::addLibStdCXXIncludePaths(
+ Twine Base, Twine Suffix, StringRef GCCTriple, StringRef GCCMultiarchTriple,
+ StringRef TargetMultiarchTriple, Twine IncludeSuffix,
+ const ArgList &DriverArgs, ArgStringList &CC1Args) const {
+ if (!getVFS().exists(Base + Suffix))
+ return false;
+
+ addSystemInclude(DriverArgs, CC1Args, Base + Suffix);
+
+ // The vanilla GCC layout of libstdc++ headers uses a triple subdirectory. If
+ // that path exists or we have neither a GCC nor target multiarch triple, use
+ // this vanilla search path.
+ if ((GCCMultiarchTriple.empty() && TargetMultiarchTriple.empty()) ||
+ getVFS().exists(Base + Suffix + "/" + GCCTriple + IncludeSuffix)) {
+ addSystemInclude(DriverArgs, CC1Args,
+ Base + Suffix + "/" + GCCTriple + IncludeSuffix);
+ } else {
+ // Otherwise try to use multiarch naming schemes which have normalized the
+ // triples and put the triple before the suffix.
+ //
+ // GCC surprisingly uses *both* the GCC triple with a multilib suffix and
+ // the target triple, so we support that here.
+ addSystemInclude(DriverArgs, CC1Args,
+ Base + "/" + GCCMultiarchTriple + Suffix + IncludeSuffix);
+ addSystemInclude(DriverArgs, CC1Args,
+ Base + "/" + TargetMultiarchTriple + Suffix);
+ }
+
+ addSystemInclude(DriverArgs, CC1Args, Base + Suffix + "/backward");
+ return true;
+}
+
+
void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
const Generic_GCC::GCCVersion &V = GCCInstallation.getVersion();
@@ -2064,238 +2425,320 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::aarch64_be ||
(getTriple().getOS() == llvm::Triple::Linux &&
- (!V.isOlderThan(4, 7, 0) ||
- getTriple().getEnvironment() == llvm::Triple::Android)) ||
- getTriple().getOS() == llvm::Triple::NaCl;
+ (!V.isOlderThan(4, 7, 0) || getTriple().isAndroid())) ||
+ getTriple().getOS() == llvm::Triple::NaCl ||
+ (getTriple().getVendor() == llvm::Triple::MipsTechnologies &&
+ !getTriple().hasEnvironment());
if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
options::OPT_fno_use_init_array, UseInitArrayDefault))
CC1Args.push_back("-fuse-init-array");
}
+/// Mips Toolchain
+MipsLLVMToolChain::MipsLLVMToolChain(const Driver &D,
+ const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Linux(D, Triple, Args) {
+ // Select the correct multilib according to the given arguments.
+ DetectedMultilibs Result;
+ findMIPSMultilibs(D, Triple, "", Args, Result);
+ Multilibs = Result.Multilibs;
+ SelectedMultilib = Result.SelectedMultilib;
+
+ // Find out the library suffix based on the ABI.
+ LibSuffix = tools::mips::getMipsABILibSuffix(Args, Triple);
+ getFilePaths().clear();
+ getFilePaths().push_back(computeSysRoot() + "/usr/lib" + LibSuffix);
+
+ // Use LLD by default.
+ DefaultLinker = "lld";
+}
+
+void MipsLLVMToolChain::AddClangSystemIncludeArgs(
+ const ArgList &DriverArgs, ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ const Driver &D = getDriver();
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ const auto &Callback = Multilibs.includeDirsCallback();
+ if (Callback) {
+ const auto IncludePaths =
+ Callback(D.getInstalledDir(), getTripleString(), SelectedMultilib);
+ for (const auto &Path : IncludePaths)
+ addExternCSystemIncludeIfExists(DriverArgs, CC1Args, Path);
+ }
+}
+
+Tool *MipsLLVMToolChain::buildLinker() const {
+ return new tools::gnutools::Linker(*this);
+}
+
+std::string MipsLLVMToolChain::computeSysRoot() const {
+ if (!getDriver().SysRoot.empty())
+ return getDriver().SysRoot + SelectedMultilib.osSuffix();
+
+ const std::string InstalledDir(getDriver().getInstalledDir());
+ std::string SysRootPath =
+ InstalledDir + "/../sysroot" + SelectedMultilib.osSuffix();
+ if (llvm::sys::fs::exists(SysRootPath))
+ return SysRootPath;
+
+ return std::string();
+}
+
+ToolChain::CXXStdlibType
+MipsLLVMToolChain::GetCXXStdlibType(const ArgList &Args) const {
+ Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
+ if (A) {
+ StringRef Value = A->getValue();
+ if (Value != "libc++")
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
+
+ return ToolChain::CST_Libcxx;
+}
+
+void MipsLLVMToolChain::AddClangCXXStdlibIncludeArgs(
+ const ArgList &DriverArgs, ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ assert((GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) &&
+ "Only -lc++ (aka libcxx) is suported in this toolchain.");
+
+ const auto &Callback = Multilibs.includeDirsCallback();
+ if (Callback) {
+ const auto IncludePaths = Callback(getDriver().getInstalledDir(),
+ getTripleString(), SelectedMultilib);
+ for (const auto &Path : IncludePaths) {
+ if (llvm::sys::fs::exists(Path + "/c++/v1")) {
+ addSystemInclude(DriverArgs, CC1Args, Path + "/c++/v1");
+ break;
+ }
+ }
+ }
+}
+
+void MipsLLVMToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ assert((GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) &&
+ "Only -lc++ (aka libxx) is suported in this toolchain.");
+
+ CmdArgs.push_back("-lc++");
+ CmdArgs.push_back("-lc++abi");
+ CmdArgs.push_back("-lunwind");
+}
+
+std::string MipsLLVMToolChain::getCompilerRT(const ArgList &Args,
+ StringRef Component,
+ bool Shared) const {
+ SmallString<128> Path(getDriver().ResourceDir);
+ llvm::sys::path::append(Path, SelectedMultilib.osSuffix(), "lib" + LibSuffix,
+ getOS());
+ llvm::sys::path::append(Path, Twine("libclang_rt." + Component + "-" +
+ "mips" + (Shared ? ".so" : ".a")));
+ return Path.str();
+}
+
/// Hexagon Toolchain
-std::string Hexagon_TC::GetGnuDir(const std::string &InstalledDir,
- const ArgList &Args) {
+std::string HexagonToolChain::getHexagonTargetDir(
+ const std::string &InstalledDir,
+ const SmallVectorImpl<std::string> &PrefixDirs) const {
+ std::string InstallRelDir;
+ const Driver &D = getDriver();
// Locate the rest of the toolchain ...
- std::string GccToolchain = getGCCToolchainDir(Args);
+ for (auto &I : PrefixDirs)
+ if (D.getVFS().exists(I))
+ return I;
- if (!GccToolchain.empty())
- return GccToolchain;
-
- std::string InstallRelDir = InstalledDir + "/../../gnu";
- if (llvm::sys::fs::exists(InstallRelDir))
+ if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))
return InstallRelDir;
- std::string PrefixRelDir = std::string(LLVM_PREFIX) + "/../gnu";
- if (llvm::sys::fs::exists(PrefixRelDir))
+ std::string PrefixRelDir = std::string(LLVM_PREFIX) + "/target";
+ if (getVFS().exists(PrefixRelDir))
return PrefixRelDir;
return InstallRelDir;
}
-const char *Hexagon_TC::GetSmallDataThreshold(const ArgList &Args) {
- Arg *A;
- A = Args.getLastArg(options::OPT_G, options::OPT_G_EQ,
- options::OPT_msmall_data_threshold_EQ);
- if (A)
- return A->getValue();
+Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
+ const ArgList &Args) {
+ StringRef Gn = "";
+ if (Arg *A = Args.getLastArg(options::OPT_G, options::OPT_G_EQ,
+ options::OPT_msmall_data_threshold_EQ)) {
+ Gn = A->getValue();
+ } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
+ options::OPT_fPIC)) {
+ Gn = "0";
+ }
- A = Args.getLastArg(options::OPT_shared, options::OPT_fpic,
- options::OPT_fPIC);
- if (A)
- return "0";
+ unsigned G;
+ if (!Gn.getAsInteger(10, G))
+ return G;
- return 0;
+ return None;
}
-bool Hexagon_TC::UsesG0(const char *smallDataThreshold) {
- return smallDataThreshold && smallDataThreshold[0] == '0';
-}
-static void GetHexagonLibraryPaths(const ArgList &Args, const std::string &Ver,
- const std::string &MarchString,
- const std::string &InstalledDir,
- ToolChain::path_list *LibPaths) {
- bool buildingLib = Args.hasArg(options::OPT_shared);
+void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
+ ToolChain::path_list &LibPaths) const {
+ const Driver &D = getDriver();
//----------------------------------------------------------------------------
// -L Args
//----------------------------------------------------------------------------
for (Arg *A : Args.filtered(options::OPT_L))
for (const char *Value : A->getValues())
- LibPaths->push_back(Value);
+ LibPaths.push_back(Value);
//----------------------------------------------------------------------------
// Other standard paths
//----------------------------------------------------------------------------
- const std::string MarchSuffix = "/" + MarchString;
- const std::string G0Suffix = "/G0";
- const std::string MarchG0Suffix = MarchSuffix + G0Suffix;
- const std::string RootDir = Hexagon_TC::GetGnuDir(InstalledDir, Args) + "/";
-
- // lib/gcc/hexagon/...
- std::string LibGCCHexagonDir = RootDir + "lib/gcc/hexagon/";
- if (buildingLib) {
- LibPaths->push_back(LibGCCHexagonDir + Ver + MarchG0Suffix);
- LibPaths->push_back(LibGCCHexagonDir + Ver + G0Suffix);
- }
- LibPaths->push_back(LibGCCHexagonDir + Ver + MarchSuffix);
- LibPaths->push_back(LibGCCHexagonDir + Ver);
-
- // lib/gcc/...
- LibPaths->push_back(RootDir + "lib/gcc");
-
- // hexagon/lib/...
- std::string HexagonLibDir = RootDir + "hexagon/lib";
- if (buildingLib) {
- LibPaths->push_back(HexagonLibDir + MarchG0Suffix);
- LibPaths->push_back(HexagonLibDir + G0Suffix);
+ std::vector<std::string> RootDirs;
+ std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),
+ std::back_inserter(RootDirs));
+
+ std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
+ D.PrefixDirs);
+ if (std::find(RootDirs.begin(), RootDirs.end(), TargetDir) == RootDirs.end())
+ RootDirs.push_back(TargetDir);
+
+ bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);
+ // Assume G0 with -shared.
+ bool HasG0 = Args.hasArg(options::OPT_shared);
+ if (auto G = getSmallDataThreshold(Args))
+ HasG0 = G.getValue() == 0;
+
+ const std::string CpuVer = GetTargetCPUVersion(Args).str();
+ for (auto &Dir : RootDirs) {
+ std::string LibDir = Dir + "/hexagon/lib";
+ std::string LibDirCpu = LibDir + '/' + CpuVer;
+ if (HasG0) {
+ if (HasPIC)
+ LibPaths.push_back(LibDirCpu + "/G0/pic");
+ LibPaths.push_back(LibDirCpu + "/G0");
+ }
+ LibPaths.push_back(LibDirCpu);
+ LibPaths.push_back(LibDir);
}
- LibPaths->push_back(HexagonLibDir + MarchSuffix);
- LibPaths->push_back(HexagonLibDir);
}
-Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
+HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
: Linux(D, Triple, Args) {
- const std::string InstalledDir(getDriver().getInstalledDir());
- const std::string GnuDir = Hexagon_TC::GetGnuDir(InstalledDir, Args);
+ const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
+ D.PrefixDirs);
// Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
// program paths
- const std::string BinDir(GnuDir + "/bin");
- if (llvm::sys::fs::exists(BinDir))
+ const std::string BinDir(TargetDir + "/bin");
+ if (D.getVFS().exists(BinDir))
getProgramPaths().push_back(BinDir);
- // Determine version of GCC libraries and headers to use.
- const std::string HexagonDir(GnuDir + "/lib/gcc/hexagon");
- std::error_code ec;
- GCCVersion MaxVersion = GCCVersion::Parse("0.0.0");
- for (llvm::sys::fs::directory_iterator di(HexagonDir, ec), de;
- !ec && di != de; di = di.increment(ec)) {
- GCCVersion cv = GCCVersion::Parse(llvm::sys::path::filename(di->path()));
- if (MaxVersion < cv)
- MaxVersion = cv;
- }
- GCCLibAndIncVersion = MaxVersion;
-
- ToolChain::path_list *LibPaths = &getFilePaths();
+ ToolChain::path_list &LibPaths = getFilePaths();
// Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
// 'elf' OS type, so the Linux paths are not appropriate. When we actually
// support 'linux' we'll need to fix this up
- LibPaths->clear();
-
- GetHexagonLibraryPaths(Args, GetGCCLibAndIncVersion(), GetTargetCPU(Args),
- InstalledDir, LibPaths);
+ LibPaths.clear();
+ getHexagonLibraryPaths(Args, LibPaths);
}
-Hexagon_TC::~Hexagon_TC() {}
+HexagonToolChain::~HexagonToolChain() {}
-Tool *Hexagon_TC::buildAssembler() const {
+Tool *HexagonToolChain::buildAssembler() const {
return new tools::hexagon::Assembler(*this);
}
-Tool *Hexagon_TC::buildLinker() const {
+Tool *HexagonToolChain::buildLinker() const {
return new tools::hexagon::Linker(*this);
}
-void Hexagon_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- const Driver &D = getDriver();
-
+void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
- std::string Ver(GetGCCLibAndIncVersion());
- std::string GnuDir = Hexagon_TC::GetGnuDir(D.InstalledDir, DriverArgs);
- std::string HexagonDir(GnuDir + "/lib/gcc/hexagon/" + Ver);
- addExternCSystemInclude(DriverArgs, CC1Args, HexagonDir + "/include");
- addExternCSystemInclude(DriverArgs, CC1Args, HexagonDir + "/include-fixed");
- addExternCSystemInclude(DriverArgs, CC1Args, GnuDir + "/hexagon/include");
+ const Driver &D = getDriver();
+ std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
+ D.PrefixDirs);
+ addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
}
-void Hexagon_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
-
+void HexagonToolChain::AddClangCXXStdlibIncludeArgs(
+ const ArgList &DriverArgs, ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
const Driver &D = getDriver();
- std::string Ver(GetGCCLibAndIncVersion());
- SmallString<128> IncludeDir(
- Hexagon_TC::GetGnuDir(D.InstalledDir, DriverArgs));
-
- llvm::sys::path::append(IncludeDir, "hexagon/include/c++/");
- llvm::sys::path::append(IncludeDir, Ver);
- addSystemInclude(DriverArgs, CC1Args, IncludeDir);
+ std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
+ addSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include/c++");
}
ToolChain::CXXStdlibType
-Hexagon_TC::GetCXXStdlibType(const ArgList &Args) const {
+HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
if (!A)
return ToolChain::CST_Libstdcxx;
StringRef Value = A->getValue();
- if (Value != "libstdc++") {
+ if (Value != "libstdc++")
getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
- }
return ToolChain::CST_Libstdcxx;
}
-static int getHexagonVersion(const ArgList &Args) {
- Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ);
- // Select the default CPU (v4) if none was given.
- if (!A)
- return 4;
+//
+// Returns the default CPU for Hexagon. This is the default compilation target
+// if no Hexagon processor is selected at the command-line.
+//
+const StringRef HexagonToolChain::GetDefaultCPU() {
+ return "hexagonv60";
+}
- // FIXME: produce errors if we cannot parse the version.
- StringRef WhichHexagon = A->getValue();
- if (WhichHexagon.startswith("hexagonv")) {
- int Val;
- if (!WhichHexagon.substr(sizeof("hexagonv") - 1).getAsInteger(10, Val))
- return Val;
- }
- if (WhichHexagon.startswith("v")) {
- int Val;
- if (!WhichHexagon.substr(1).getAsInteger(10, Val))
- return Val;
- }
+const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
+ Arg *CpuArg = nullptr;
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ, options::OPT_march_EQ))
+ CpuArg = A;
- // FIXME: should probably be an error.
- return 4;
+ StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();
+ if (CPU.startswith("hexagon"))
+ return CPU.substr(sizeof("hexagon") - 1);
+ return CPU;
}
+// End Hexagon
-StringRef Hexagon_TC::GetTargetCPU(const ArgList &Args) {
- int V = getHexagonVersion(Args);
- // FIXME: We don't support versions < 4. We should error on them.
- switch (V) {
- default:
- llvm_unreachable("Unexpected version");
- case 5:
- return "v5";
- case 4:
- return "v4";
- case 3:
- return "v3";
- case 2:
- return "v2";
- case 1:
- return "v1";
- }
+/// AMDGPU Toolchain
+AMDGPUToolChain::AMDGPUToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) { }
+
+Tool *AMDGPUToolChain::buildLinker() const {
+ return new tools::amdgpu::Linker(*this);
}
-// End Hexagon
+// End AMDGPU
/// NaCl Toolchain
-NaCl_TC::NaCl_TC(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
+NaClToolChain::NaClToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
// Remove paths added by Generic_GCC. NaCl Toolchain cannot use the
@@ -2317,45 +2760,39 @@ NaCl_TC::NaCl_TC(const Driver &D, const llvm::Triple &Triple,
std::string ToolPath(getDriver().ResourceDir + "/lib/");
switch (Triple.getArch()) {
- case llvm::Triple::x86: {
+ case llvm::Triple::x86:
file_paths.push_back(FilePath + "x86_64-nacl/lib32");
- file_paths.push_back(FilePath + "x86_64-nacl/usr/lib32");
+ file_paths.push_back(FilePath + "i686-nacl/usr/lib");
prog_paths.push_back(ProgPath + "x86_64-nacl/bin");
file_paths.push_back(ToolPath + "i686-nacl");
break;
- }
- case llvm::Triple::x86_64: {
+ case llvm::Triple::x86_64:
file_paths.push_back(FilePath + "x86_64-nacl/lib");
file_paths.push_back(FilePath + "x86_64-nacl/usr/lib");
prog_paths.push_back(ProgPath + "x86_64-nacl/bin");
file_paths.push_back(ToolPath + "x86_64-nacl");
break;
- }
- case llvm::Triple::arm: {
+ case llvm::Triple::arm:
file_paths.push_back(FilePath + "arm-nacl/lib");
file_paths.push_back(FilePath + "arm-nacl/usr/lib");
prog_paths.push_back(ProgPath + "arm-nacl/bin");
file_paths.push_back(ToolPath + "arm-nacl");
break;
- }
- case llvm::Triple::mipsel: {
+ case llvm::Triple::mipsel:
file_paths.push_back(FilePath + "mipsel-nacl/lib");
file_paths.push_back(FilePath + "mipsel-nacl/usr/lib");
prog_paths.push_back(ProgPath + "bin");
file_paths.push_back(ToolPath + "mipsel-nacl");
break;
- }
default:
break;
}
- // Use provided linker, not system linker
- Linker = GetProgramPath("ld");
NaClArmMacrosPath = GetFilePath("nacl-arm-macros.s");
}
-void NaCl_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
+void NaClToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
const Driver &D = getDriver();
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
@@ -2371,12 +2808,21 @@ void NaCl_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
SmallString<128> P(D.Dir + "/../");
switch (getTriple().getArch()) {
+ case llvm::Triple::x86:
+ // x86 is special because multilib style uses x86_64-nacl/include for libc
+ // headers but the SDK wants i686-nacl/usr/include. The other architectures
+ // have the same substring.
+ llvm::sys::path::append(P, "i686-nacl/usr/include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ llvm::sys::path::remove_filename(P);
+ llvm::sys::path::remove_filename(P);
+ llvm::sys::path::remove_filename(P);
+ llvm::sys::path::append(P, "x86_64-nacl/include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ return;
case llvm::Triple::arm:
llvm::sys::path::append(P, "arm-nacl/usr/include");
break;
- case llvm::Triple::x86:
- llvm::sys::path::append(P, "x86_64-nacl/usr/include");
- break;
case llvm::Triple::x86_64:
llvm::sys::path::append(P, "x86_64-nacl/usr/include");
break;
@@ -2394,16 +2840,16 @@ void NaCl_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addSystemInclude(DriverArgs, CC1Args, P.str());
}
-void NaCl_TC::AddCXXStdlibLibArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
+void NaClToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
// Check for -stdlib= flags. We only support libc++ but this consumes the arg
// if the value is libc++, and emits an error for other values.
GetCXXStdlibType(Args);
CmdArgs.push_back("-lc++");
}
-void NaCl_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
+void NaClToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
const Driver &D = getDriver();
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
@@ -2436,7 +2882,8 @@ void NaCl_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
}
-ToolChain::CXXStdlibType NaCl_TC::GetCXXStdlibType(const ArgList &Args) const {
+ToolChain::CXXStdlibType
+NaClToolChain::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
if (Value == "libc++")
@@ -2447,8 +2894,9 @@ ToolChain::CXXStdlibType NaCl_TC::GetCXXStdlibType(const ArgList &Args) const {
return ToolChain::CST_Libcxx;
}
-std::string NaCl_TC::ComputeEffectiveClangTriple(const ArgList &Args,
- types::ID InputType) const {
+std::string
+NaClToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
+ types::ID InputType) const {
llvm::Triple TheTriple(ComputeLLVMTriple(Args, InputType));
if (TheTriple.getArch() == llvm::Triple::arm &&
TheTriple.getEnvironment() == llvm::Triple::UnknownEnvironment)
@@ -2456,11 +2904,11 @@ std::string NaCl_TC::ComputeEffectiveClangTriple(const ArgList &Args,
return TheTriple.getTriple();
}
-Tool *NaCl_TC::buildLinker() const {
+Tool *NaClToolChain::buildLinker() const {
return new tools::nacltools::Linker(*this);
}
-Tool *NaCl_TC::buildAssembler() const {
+Tool *NaClToolChain::buildAssembler() const {
if (getTriple().getArch() == llvm::Triple::arm)
return new tools::nacltools::AssemblerARM(*this);
return new tools::gnutools::Assembler(*this);
@@ -2619,7 +3067,7 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple,
// back to '/usr/lib' if it doesn't exist.
if ((Triple.getArch() == llvm::Triple::x86 ||
Triple.getArch() == llvm::Triple::ppc) &&
- llvm::sys::fs::exists(getDriver().SysRoot + "/usr/lib32/crt1.o"))
+ D.getVFS().exists(getDriver().SysRoot + "/usr/lib32/crt1.o"))
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32");
else
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
@@ -2666,7 +3114,7 @@ Tool *FreeBSD::buildAssembler() const {
Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); }
-bool FreeBSD::UseSjLjExceptions() const {
+bool FreeBSD::UseSjLjExceptions(const ArgList &Args) const {
// FreeBSD uses SjLj exceptions on ARM oabi.
switch (getTriple().getEnvironment()) {
case llvm::Triple::GNUEABIHF:
@@ -2829,18 +3277,46 @@ Tool *Minix::buildAssembler() const {
Tool *Minix::buildLinker() const { return new tools::minix::Linker(*this); }
+static void addPathIfExists(const Driver &D, const Twine &Path,
+ ToolChain::path_list &Paths) {
+ if (D.getVFS().exists(Path))
+ Paths.push_back(Path.str());
+}
+
/// Solaris - Solaris tool chain which can call as(1) and ld(1) directly.
Solaris::Solaris(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_GCC(D, Triple, Args) {
- getProgramPaths().push_back(getDriver().getInstalledDir());
+ GCCInstallation.init(Triple, Args);
+
+ path_list &Paths = getFilePaths();
+ if (GCCInstallation.isValid())
+ addPathIfExists(D, GCCInstallation.getInstallPath(), Paths);
+
+ addPathIfExists(D, getDriver().getInstalledDir(), Paths);
if (getDriver().getInstalledDir() != getDriver().Dir)
- getProgramPaths().push_back(getDriver().Dir);
+ addPathIfExists(D, getDriver().Dir, Paths);
- getFilePaths().push_back(getDriver().Dir + "/../lib");
- getFilePaths().push_back("/usr/lib");
+ addPathIfExists(D, getDriver().SysRoot + getDriver().Dir + "/../lib", Paths);
+
+ std::string LibPath = "/usr/lib/";
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::sparc:
+ break;
+ case llvm::Triple::x86_64:
+ LibPath += "amd64/";
+ break;
+ case llvm::Triple::sparcv9:
+ LibPath += "sparcv9/";
+ break;
+ default:
+ llvm_unreachable("Unsupported architecture");
+ }
+
+ addPathIfExists(D, getDriver().SysRoot + LibPath, Paths);
}
Tool *Solaris::buildAssembler() const {
@@ -2849,6 +3325,31 @@ Tool *Solaris::buildAssembler() const {
Tool *Solaris::buildLinker() const { return new tools::solaris::Linker(*this); }
+void Solaris::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ // Include the support directory for things like xlocale and fudged system
+ // headers.
+ addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/v1/support/solaris");
+
+ if (GCCInstallation.isValid()) {
+ GCCVersion Version = GCCInstallation.getVersion();
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/gcc/" +
+ Version.MajorStr + "." +
+ Version.MinorStr +
+ "/include/c++/" + Version.Text);
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/gcc/" + Version.MajorStr +
+ "." + Version.MinorStr + "/include/c++/" +
+ Version.Text + "/" +
+ GCCInstallation.getTriple().str());
+ }
+}
+
/// Distribution (very bare-bones at the moment).
enum Distro {
@@ -2884,6 +3385,7 @@ enum Distro {
UbuntuUtopic,
UbuntuVivid,
UbuntuWily,
+ UbuntuXenial,
UnknownDistro
};
@@ -2898,10 +3400,10 @@ static bool IsDebian(enum Distro Distro) {
}
static bool IsUbuntu(enum Distro Distro) {
- return Distro >= UbuntuHardy && Distro <= UbuntuWily;
+ return Distro >= UbuntuHardy && Distro <= UbuntuXenial;
}
-static Distro DetectDistro(llvm::Triple::ArchType Arch) {
+static Distro DetectDistro(const Driver &D, llvm::Triple::ArchType Arch) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
llvm::MemoryBuffer::getFile("/etc/lsb-release");
if (File) {
@@ -2909,7 +3411,7 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) {
SmallVector<StringRef, 16> Lines;
Data.split(Lines, "\n");
Distro Version = UnknownDistro;
- for (const StringRef Line : Lines)
+ for (StringRef Line : Lines)
if (Version == UnknownDistro && Line.startswith("DISTRIB_CODENAME="))
Version = llvm::StringSwitch<Distro>(Line.substr(17))
.Case("hardy", UbuntuHardy)
@@ -2928,6 +3430,7 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) {
.Case("utopic", UbuntuUtopic)
.Case("vivid", UbuntuVivid)
.Case("wily", UbuntuWily)
+ .Case("xenial", UbuntuXenial)
.Default(UnknownDistro);
return Version;
}
@@ -2967,13 +3470,13 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) {
return UnknownDistro;
}
- if (llvm::sys::fs::exists("/etc/SuSE-release"))
+ if (D.getVFS().exists("/etc/SuSE-release"))
return OpenSUSE;
- if (llvm::sys::fs::exists("/etc/exherbo-release"))
+ if (D.getVFS().exists("/etc/exherbo-release"))
return Exherbo;
- if (llvm::sys::fs::exists("/etc/arch-release"))
+ if (D.getVFS().exists("/etc/arch-release"))
return ArchLinux;
return UnknownDistro;
@@ -2985,9 +3488,11 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) {
/// a target-triple directory in the library and header search paths.
/// Unfortunately, this triple does not align with the vanilla target triple,
/// so we provide a rough mapping here.
-static std::string getMultiarchTriple(const llvm::Triple &TargetTriple,
+static std::string getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
StringRef SysRoot) {
- llvm::Triple::EnvironmentType TargetEnvironment = TargetTriple.getEnvironment();
+ llvm::Triple::EnvironmentType TargetEnvironment =
+ TargetTriple.getEnvironment();
// For most architectures, just use whatever we have rather than trying to be
// clever.
@@ -3002,92 +3507,91 @@ static std::string getMultiarchTriple(const llvm::Triple &TargetTriple,
case llvm::Triple::arm:
case llvm::Triple::thumb:
if (TargetEnvironment == llvm::Triple::GNUEABIHF) {
- if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabihf"))
+ if (D.getVFS().exists(SysRoot + "/lib/arm-linux-gnueabihf"))
return "arm-linux-gnueabihf";
} else {
- if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabi"))
+ if (D.getVFS().exists(SysRoot + "/lib/arm-linux-gnueabi"))
return "arm-linux-gnueabi";
}
break;
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
if (TargetEnvironment == llvm::Triple::GNUEABIHF) {
- if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabihf"))
+ if (D.getVFS().exists(SysRoot + "/lib/armeb-linux-gnueabihf"))
return "armeb-linux-gnueabihf";
} else {
- if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabi"))
+ if (D.getVFS().exists(SysRoot + "/lib/armeb-linux-gnueabi"))
return "armeb-linux-gnueabi";
}
break;
case llvm::Triple::x86:
- if (llvm::sys::fs::exists(SysRoot + "/lib/i386-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/i386-linux-gnu"))
return "i386-linux-gnu";
break;
case llvm::Triple::x86_64:
// We don't want this for x32, otherwise it will match x86_64 libs
if (TargetEnvironment != llvm::Triple::GNUX32 &&
- llvm::sys::fs::exists(SysRoot + "/lib/x86_64-linux-gnu"))
+ D.getVFS().exists(SysRoot + "/lib/x86_64-linux-gnu"))
return "x86_64-linux-gnu";
break;
case llvm::Triple::aarch64:
- if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/aarch64-linux-gnu"))
return "aarch64-linux-gnu";
break;
case llvm::Triple::aarch64_be:
- if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64_be-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/aarch64_be-linux-gnu"))
return "aarch64_be-linux-gnu";
break;
case llvm::Triple::mips:
- if (llvm::sys::fs::exists(SysRoot + "/lib/mips-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/mips-linux-gnu"))
return "mips-linux-gnu";
break;
case llvm::Triple::mipsel:
- if (llvm::sys::fs::exists(SysRoot + "/lib/mipsel-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/mipsel-linux-gnu"))
return "mipsel-linux-gnu";
break;
case llvm::Triple::mips64:
- if (llvm::sys::fs::exists(SysRoot + "/lib/mips64-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnu"))
return "mips64-linux-gnu";
- if (llvm::sys::fs::exists(SysRoot + "/lib/mips64-linux-gnuabi64"))
+ if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnuabi64"))
return "mips64-linux-gnuabi64";
break;
case llvm::Triple::mips64el:
- if (llvm::sys::fs::exists(SysRoot + "/lib/mips64el-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu"))
return "mips64el-linux-gnu";
- if (llvm::sys::fs::exists(SysRoot + "/lib/mips64el-linux-gnuabi64"))
+ if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnuabi64"))
return "mips64el-linux-gnuabi64";
break;
case llvm::Triple::ppc:
- if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
+ if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
return "powerpc-linux-gnuspe";
- if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnu"))
return "powerpc-linux-gnu";
break;
case llvm::Triple::ppc64:
- if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc64-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/powerpc64-linux-gnu"))
return "powerpc64-linux-gnu";
break;
case llvm::Triple::ppc64le:
- if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc64le-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/powerpc64le-linux-gnu"))
return "powerpc64le-linux-gnu";
break;
case llvm::Triple::sparc:
- if (llvm::sys::fs::exists(SysRoot + "/lib/sparc-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/sparc-linux-gnu"))
return "sparc-linux-gnu";
break;
case llvm::Triple::sparcv9:
- if (llvm::sys::fs::exists(SysRoot + "/lib/sparc64-linux-gnu"))
+ if (D.getVFS().exists(SysRoot + "/lib/sparc64-linux-gnu"))
return "sparc64-linux-gnu";
break;
+ case llvm::Triple::systemz:
+ if (D.getVFS().exists(SysRoot + "/lib/s390x-linux-gnu"))
+ return "s390x-linux-gnu";
+ break;
}
return TargetTriple.str();
}
-static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) {
- if (llvm::sys::fs::exists(Path))
- Paths.push_back(Path.str());
-}
-
static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
if (isMipsArch(Triple.getArch())) {
// lib32 directory has a special meaning on MIPS targets.
@@ -3120,7 +3624,8 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
- GCCInstallation.init(D, Triple, Args);
+ GCCInstallation.init(Triple, Args);
+ CudaInstallation.init(Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
llvm::Triple::ArchType Arch = Triple.getArch();
std::string SysRoot = computeSysRoot();
@@ -3138,9 +3643,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
GCCInstallation.getTriple().str() + "/bin")
.str());
- Linker = GetLinkerPath();
-
- Distro Distro = DetectDistro(Arch);
+ Distro Distro = DetectDistro(D, Arch);
if (IsOpenSUSE(Distro) || IsUbuntu(Distro)) {
ExtraOpts.push_back("-z");
@@ -3150,7 +3653,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)
ExtraOpts.push_back("-X");
- const bool IsAndroid = Triple.getEnvironment() == llvm::Triple::Android;
+ const bool IsAndroid = Triple.isAndroid();
const bool IsMips = isMipsArch(Arch);
if (IsMips && !SysRoot.empty())
@@ -3190,7 +3693,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
path_list &Paths = getFilePaths();
const std::string OSLibDir = getOSLibDir(Triple, Args);
- const std::string MultiarchTriple = getMultiarchTriple(Triple, SysRoot);
+ const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
// Add the multilib suffixed paths where they are available.
if (GCCInstallation.isValid()) {
@@ -3200,7 +3703,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// Sourcery CodeBench MIPS toolchain holds some libraries under
// a biarch-like suffix of the GCC installation.
- addPathIfExists((GCCInstallation.getInstallPath() + Multilib.gccSuffix()),
+ addPathIfExists(D, GCCInstallation.getInstallPath() + Multilib.gccSuffix(),
Paths);
// GCC cross compiling toolchains will install target libraries which ship
@@ -3221,8 +3724,8 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
//
// Note that this matches the GCC behavior. See the below comment for where
// Clang diverges from GCC's behavior.
- addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir +
- Multilib.osSuffix(),
+ addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib/../" +
+ OSLibDir + Multilib.osSuffix(),
Paths);
// If the GCC installation we found is inside of the sysroot, we want to
@@ -3235,8 +3738,8 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// configurations but this seems somewhere between questionable and simply
// a bug.
if (StringRef(LibPath).startswith(SysRoot)) {
- addPathIfExists(LibPath + "/" + MultiarchTriple, Paths);
- addPathIfExists(LibPath + "/../" + OSLibDir, Paths);
+ addPathIfExists(D, LibPath + "/" + MultiarchTriple, Paths);
+ addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);
}
}
@@ -3246,27 +3749,29 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// FIXME: It's not clear whether we should use the driver's installed
// directory ('Dir' below) or the ResourceDir.
if (StringRef(D.Dir).startswith(SysRoot)) {
- addPathIfExists(D.Dir + "/../lib/" + MultiarchTriple, Paths);
- addPathIfExists(D.Dir + "/../" + OSLibDir, Paths);
+ addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
}
- addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths);
- addPathIfExists(SysRoot + "/lib/../" + OSLibDir, Paths);
- addPathIfExists(SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
- addPathIfExists(SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+ addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
+ addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
// Try walking via the GCC triple path in case of biarch or multiarch GCC
// installations with strange symlinks.
if (GCCInstallation.isValid()) {
- addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
+ addPathIfExists(D,
+ SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
"/../../" + OSLibDir,
Paths);
// Add the 'other' biarch variant path
Multilib BiarchSibling;
if (GCCInstallation.getBiarchSibling(BiarchSibling)) {
- addPathIfExists(
- GCCInstallation.getInstallPath() + BiarchSibling.gccSuffix(), Paths);
+ addPathIfExists(D, GCCInstallation.getInstallPath() +
+ BiarchSibling.gccSuffix(),
+ Paths);
}
// See comments above on the multilib variant for details of why this is
@@ -3274,14 +3779,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const std::string &LibPath = GCCInstallation.getParentLibPath();
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
const Multilib &Multilib = GCCInstallation.getMultilib();
- addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib" +
- Multilib.osSuffix(),
+ addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib" +
+ Multilib.osSuffix(),
Paths);
// See comments above on the multilib variant for details of why this is
// only included from within the sysroot.
if (StringRef(LibPath).startswith(SysRoot))
- addPathIfExists(LibPath, Paths);
+ addPathIfExists(D, LibPath, Paths);
}
// Similar to the logic for GCC above, if we are currently running Clang
@@ -3290,10 +3795,10 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// FIXME: It's not clear whether we should use the driver's installed
// directory ('Dir' below) or the ResourceDir.
if (StringRef(D.Dir).startswith(SysRoot))
- addPathIfExists(D.Dir + "/../lib", Paths);
+ addPathIfExists(D, D.Dir + "/../lib", Paths);
- addPathIfExists(SysRoot + "/lib", Paths);
- addPathIfExists(SysRoot + "/usr/lib", Paths);
+ addPathIfExists(D, SysRoot + "/lib", Paths);
+ addPathIfExists(D, SysRoot + "/usr/lib", Paths);
}
bool Linux::HasNativeLLVMSupport() const { return true; }
@@ -3323,12 +3828,12 @@ std::string Linux::computeSysRoot() const {
(InstallDir + "/../../../../" + TripleStr + "/libc" + Multilib.osSuffix())
.str();
- if (llvm::sys::fs::exists(Path))
+ if (getVFS().exists(Path))
return Path;
Path = (InstallDir + "/../../../../sysroot" + Multilib.osSuffix()).str();
- if (llvm::sys::fs::exists(Path))
+ if (getVFS().exists(Path))
return Path;
return std::string();
@@ -3404,6 +3909,10 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
"/usr/include/arm-linux-gnueabi"};
const StringRef ARMHFMultiarchIncludeDirs[] = {
"/usr/include/arm-linux-gnueabihf"};
+ const StringRef ARMEBMultiarchIncludeDirs[] = {
+ "/usr/include/armeb-linux-gnueabi"};
+ const StringRef ARMEBHFMultiarchIncludeDirs[] = {
+ "/usr/include/armeb-linux-gnueabihf"};
const StringRef MIPSMultiarchIncludeDirs[] = {"/usr/include/mips-linux-gnu"};
const StringRef MIPSELMultiarchIncludeDirs[] = {
"/usr/include/mipsel-linux-gnu"};
@@ -3422,6 +3931,8 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
"/usr/include/sparc-linux-gnu"};
const StringRef Sparc64MultiarchIncludeDirs[] = {
"/usr/include/sparc64-linux-gnu"};
+ const StringRef SYSTEMZMultiarchIncludeDirs[] = {
+ "/usr/include/s390x-linux-gnu"};
ArrayRef<StringRef> MultiarchIncludeDirs;
switch (getTriple().getArch()) {
case llvm::Triple::x86_64:
@@ -3435,11 +3946,19 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
MultiarchIncludeDirs = AArch64MultiarchIncludeDirs;
break;
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
MultiarchIncludeDirs = ARMHFMultiarchIncludeDirs;
else
MultiarchIncludeDirs = ARMMultiarchIncludeDirs;
break;
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumbeb:
+ if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
+ MultiarchIncludeDirs = ARMEBHFMultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = ARMEBMultiarchIncludeDirs;
+ break;
case llvm::Triple::mips:
MultiarchIncludeDirs = MIPSMultiarchIncludeDirs;
break;
@@ -3467,11 +3986,14 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
case llvm::Triple::sparcv9:
MultiarchIncludeDirs = Sparc64MultiarchIncludeDirs;
break;
+ case llvm::Triple::systemz:
+ MultiarchIncludeDirs = SYSTEMZMultiarchIncludeDirs;
+ break;
default:
break;
}
for (StringRef Dir : MultiarchIncludeDirs) {
- if (llvm::sys::fs::exists(SysRoot + Dir)) {
+ if (D.getVFS().exists(SysRoot + Dir)) {
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + Dir);
break;
}
@@ -3488,37 +4010,24 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
}
-/// \brief Helper to add the variant paths of a libstdc++ installation.
-/*static*/ bool Linux::addLibStdCXXIncludePaths(
- Twine Base, Twine Suffix, StringRef GCCTriple, StringRef GCCMultiarchTriple,
- StringRef TargetMultiarchTriple, Twine IncludeSuffix,
- const ArgList &DriverArgs, ArgStringList &CC1Args) {
- if (!llvm::sys::fs::exists(Base + Suffix))
- return false;
-
- addSystemInclude(DriverArgs, CC1Args, Base + Suffix);
- // The vanilla GCC layout of libstdc++ headers uses a triple subdirectory. If
- // that path exists or we have neither a GCC nor target multiarch triple, use
- // this vanilla search path.
- if ((GCCMultiarchTriple.empty() && TargetMultiarchTriple.empty()) ||
- llvm::sys::fs::exists(Base + Suffix + "/" + GCCTriple + IncludeSuffix)) {
- addSystemInclude(DriverArgs, CC1Args,
- Base + Suffix + "/" + GCCTriple + IncludeSuffix);
- } else {
- // Otherwise try to use multiarch naming schemes which have normalized the
- // triples and put the triple before the suffix.
- //
- // GCC surprisingly uses *both* the GCC triple with a multilib suffix and
- // the target triple, so we support that here.
- addSystemInclude(DriverArgs, CC1Args,
- Base + "/" + GCCMultiarchTriple + Suffix + IncludeSuffix);
- addSystemInclude(DriverArgs, CC1Args,
- Base + "/" + TargetMultiarchTriple + Suffix);
+static std::string DetectLibcxxIncludePath(StringRef base) {
+ std::error_code EC;
+ int MaxVersion = 0;
+ std::string MaxVersionString = "";
+ for (llvm::sys::fs::directory_iterator LI(base, EC), LE; !EC && LI != LE;
+ LI = LI.increment(EC)) {
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
+ int Version;
+ if (VersionText[0] == 'v' &&
+ !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
+ if (Version > MaxVersion) {
+ MaxVersion = Version;
+ MaxVersionString = VersionText;
+ }
+ }
}
-
- addSystemInclude(DriverArgs, CC1Args, Base + Suffix + "/backward");
- return true;
+ return MaxVersion ? (base + "/" + MaxVersionString).str() : "";
}
void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
@@ -3530,17 +4039,14 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
// Check if libc++ has been enabled and provide its include paths if so.
if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) {
const std::string LibCXXIncludePathCandidates[] = {
- // The primary location is within the Clang installation.
- // FIXME: We shouldn't hard code 'v1' here to make Clang future proof to
- // newer ABI versions.
- getDriver().Dir + "/../include/c++/v1",
+ DetectLibcxxIncludePath(getDriver().Dir + "/../include/c++"),
// We also check the system as for a long time this is the only place
// Clang looked.
// FIXME: We should really remove this. It doesn't make any sense.
- getDriver().SysRoot + "/usr/include/c++/v1"};
+ DetectLibcxxIncludePath(getDriver().SysRoot + "/usr/include/c++")};
for (const auto &IncludePath : LibCXXIncludePathCandidates) {
- if (!llvm::sys::fs::exists(IncludePath))
+ if (IncludePath.empty() || !getVFS().exists(IncludePath))
continue;
// Add the first candidate that exists.
addSystemInclude(DriverArgs, CC1Args, IncludePath);
@@ -3561,10 +4067,10 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
StringRef InstallDir = GCCInstallation.getInstallPath();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
- const std::string GCCMultiarchTriple =
- getMultiarchTriple(GCCInstallation.getTriple(), getDriver().SysRoot);
+ const std::string GCCMultiarchTriple = getMultiarchTriple(
+ getDriver(), GCCInstallation.getTriple(), getDriver().SysRoot);
const std::string TargetMultiarchTriple =
- getMultiarchTriple(getTriple(), getDriver().SysRoot);
+ getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
const GCCVersion &Version = GCCInstallation.getVersion();
// The primary search for libstdc++ supports multiarch variants.
@@ -3598,6 +4104,18 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
}
+void Linux::AddCudaIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nocudainc))
+ return;
+
+ if (CudaInstallation.isValid()) {
+ addSystemInclude(DriverArgs, CC1Args, CudaInstallation.getIncludePath());
+ CC1Args.push_back("-include");
+ CC1Args.push_back("__clang_cuda_runtime_wrapper.h");
+ }
+}
+
bool Linux::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); }
SanitizerMask Linux::getSupportedSanitizers() const {
@@ -3607,24 +4125,39 @@ SanitizerMask Linux::getSupportedSanitizers() const {
getTriple().getArch() == llvm::Triple::mips64el;
const bool IsPowerPC64 = getTriple().getArch() == llvm::Triple::ppc64 ||
getTriple().getArch() == llvm::Triple::ppc64le;
+ const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 ||
+ getTriple().getArch() == llvm::Triple::aarch64_be;
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
Res |= SanitizerKind::KernelAddress;
Res |= SanitizerKind::Vptr;
- if (IsX86_64 || IsMIPS64) {
+ Res |= SanitizerKind::SafeStack;
+ if (IsX86_64 || IsMIPS64 || IsAArch64)
Res |= SanitizerKind::DataFlow;
+ if (IsX86_64 || IsMIPS64 || IsAArch64)
Res |= SanitizerKind::Leak;
+ if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
Res |= SanitizerKind::Thread;
- }
- if (IsX86_64 || IsMIPS64 || IsPowerPC64)
+ if (IsX86_64 || IsMIPS64 || IsPowerPC64 || IsAArch64)
Res |= SanitizerKind::Memory;
if (IsX86 || IsX86_64) {
Res |= SanitizerKind::Function;
- Res |= SanitizerKind::SafeStack;
}
return Res;
}
+void Linux::addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ if (!needsProfileRT(Args)) return;
+
+ // Add linker option -u__llvm_runtime_variable to cause runtime
+ // initialization module to be linked in.
+ if (!Args.hasArg(options::OPT_coverage))
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
+ ToolChain::addProfileRTLibs(Args, CmdArgs);
+}
+
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple,
@@ -3638,10 +4171,7 @@ DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple,
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
- if (llvm::sys::fs::exists("/usr/lib/gcc47"))
- getFilePaths().push_back("/usr/lib/gcc47");
- else
- getFilePaths().push_back("/usr/lib/gcc44");
+ getFilePaths().push_back("/usr/lib/gcc50");
}
Tool *DragonFly::buildAssembler() const {
@@ -3665,6 +4195,22 @@ CudaToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
Linux::addClangTargetOptions(DriverArgs, CC1Args);
CC1Args.push_back("-fcuda-is-device");
+
+ if (DriverArgs.hasArg(options::OPT_nocudalib))
+ return;
+
+ std::string LibDeviceFile = CudaInstallation.getLibDeviceFile(
+ DriverArgs.getLastArgValue(options::OPT_march_EQ));
+ if (!LibDeviceFile.empty()) {
+ CC1Args.push_back("-mlink-cuda-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile));
+
+ // Libdevice in CUDA-7.0 requires PTX version that's more recent
+ // than LLVM defaults to. Use PTX4.2 which is the PTX version that
+ // came with CUDA-7.0.
+ CC1Args.push_back("-target-feature");
+ CC1Args.push_back("+ptx42");
+ }
}
llvm::opt::DerivedArgList *
@@ -3712,29 +4258,32 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
}
/// XCore tool chain
-XCore::XCore(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+XCoreToolChain::XCoreToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
: ToolChain(D, Triple, Args) {
// ProgramPaths are found via 'PATH' environment variable.
}
-Tool *XCore::buildAssembler() const {
+Tool *XCoreToolChain::buildAssembler() const {
return new tools::XCore::Assembler(*this);
}
-Tool *XCore::buildLinker() const { return new tools::XCore::Linker(*this); }
+Tool *XCoreToolChain::buildLinker() const {
+ return new tools::XCore::Linker(*this);
+}
-bool XCore::isPICDefault() const { return false; }
+bool XCoreToolChain::isPICDefault() const { return false; }
-bool XCore::isPIEDefault() const { return false; }
+bool XCoreToolChain::isPIEDefault() const { return false; }
-bool XCore::isPICDefaultForced() const { return false; }
+bool XCoreToolChain::isPICDefaultForced() const { return false; }
-bool XCore::SupportsProfiling() const { return false; }
+bool XCoreToolChain::SupportsProfiling() const { return false; }
-bool XCore::hasBlocksRuntime() const { return false; }
+bool XCoreToolChain::hasBlocksRuntime() const { return false; }
-void XCore::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
+void XCoreToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
@@ -3747,13 +4296,13 @@ void XCore::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
}
}
-void XCore::addClangTargetOptions(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
+void XCoreToolChain::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
CC1Args.push_back("-nostdsysteminc");
}
-void XCore::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
+void XCoreToolChain::AddClangCXXStdlibIncludeArgs(
+ const ArgList &DriverArgs, ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdlibinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
@@ -3767,15 +4316,84 @@ void XCore::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
}
-void XCore::AddCXXStdlibLibArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
+void XCoreToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
// We don't output any lib args. This is handled by xcc.
}
-// SHAVEToolChain does not call Clang's C compiler.
-// We override SelectTool to avoid testing ShouldUseClangCompiler().
-Tool *SHAVEToolChain::SelectTool(const JobAction &JA) const {
+MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_GCC(D, Triple, Args) {
+ // If a target of 'sparc-myriad-elf' is specified to clang, it wants to use
+ // 'sparc-myriad--elf' (note the unknown OS) as the canonical triple.
+ // This won't work to find gcc. Instead we give the installation detector an
+ // extra triple, which is preferable to further hacks of the logic that at
+ // present is based solely on getArch(). In particular, it would be wrong to
+ // choose the myriad installation when targeting a non-myriad sparc install.
+ switch (Triple.getArch()) {
+ default:
+ D.Diag(diag::err_target_unsupported_arch) << Triple.getArchName()
+ << "myriad";
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::shave:
+ GCCInstallation.init(Triple, Args, {"sparc-myriad-elf"});
+ }
+
+ if (GCCInstallation.isValid()) {
+ // The contents of LibDir are independent of the version of gcc.
+ // This contains libc, libg (a superset of libc), libm, libstdc++, libssp.
+ SmallString<128> LibDir(GCCInstallation.getParentLibPath());
+ if (Triple.getArch() == llvm::Triple::sparcel)
+ llvm::sys::path::append(LibDir, "../sparc-myriad-elf/lib/le");
+ else
+ llvm::sys::path::append(LibDir, "../sparc-myriad-elf/lib");
+ addPathIfExists(D, LibDir, getFilePaths());
+
+ // This directory contains crt{i,n,begin,end}.o as well as libgcc.
+ // These files are tied to a particular version of gcc.
+ SmallString<128> CompilerSupportDir(GCCInstallation.getInstallPath());
+ // There are actually 4 choices: {le,be} x {fpu,nofpu}
+ // but as this toolchain is for LEON sparc, it can assume FPU.
+ if (Triple.getArch() == llvm::Triple::sparcel)
+ llvm::sys::path::append(CompilerSupportDir, "le");
+ addPathIfExists(D, CompilerSupportDir, getFilePaths());
+ }
+}
+
+MyriadToolChain::~MyriadToolChain() {}
+
+void MyriadToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (!DriverArgs.hasArg(options::OPT_nostdinc))
+ addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include");
+}
+
+void MyriadToolChain::AddClangCXXStdlibIncludeArgs(
+ const ArgList &DriverArgs, ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ // Only libstdc++, for now.
+ StringRef LibDir = GCCInstallation.getParentLibPath();
+ const GCCVersion &Version = GCCInstallation.getVersion();
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ const Multilib &Multilib = GCCInstallation.getMultilib();
+
+ addLibStdCXXIncludePaths(
+ LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
+ "", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args);
+}
+
+// MyriadToolChain handles several triples:
+// {shave,sparc{,el}}-myriad-{rtems,unknown}-elf
+Tool *MyriadToolChain::SelectTool(const JobAction &JA) const {
+ // The inherited method works fine if not targeting the SHAVE.
+ if (!isShaveCompilation(getTriple()))
+ return ToolChain::SelectTool(JA);
switch (JA.getKind()) {
+ case Action::PreprocessJobClass:
case Action::CompileJobClass:
if (!Compiler)
Compiler.reset(new tools::SHAVE::Compiler(*this));
@@ -3789,28 +4407,122 @@ Tool *SHAVEToolChain::SelectTool(const JobAction &JA) const {
}
}
-SHAVEToolChain::SHAVEToolChain(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
- : Generic_GCC(D, Triple, Args) {}
+Tool *MyriadToolChain::buildLinker() const {
+ return new tools::Myriad::Linker(*this);
+}
+
+WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : ToolChain(D, Triple, Args) {
+ // Use LLD by default.
+ DefaultLinker = "lld";
+}
+
+bool WebAssembly::IsMathErrnoDefault() const { return false; }
+
+bool WebAssembly::IsObjCNonFragileABIDefault() const { return true; }
+
+bool WebAssembly::UseObjCMixedDispatch() const { return true; }
+
+bool WebAssembly::isPICDefault() const { return false; }
+
+bool WebAssembly::isPIEDefault() const { return false; }
+
+bool WebAssembly::isPICDefaultForced() const { return false; }
+
+bool WebAssembly::IsIntegratedAssemblerDefault() const { return true; }
+
+// TODO: Support Objective C stuff.
+bool WebAssembly::SupportsObjCGC() const { return false; }
-SHAVEToolChain::~SHAVEToolChain() {}
+bool WebAssembly::hasBlocksRuntime() const { return false; }
-/// Following are methods necessary to avoid having moviClang be an abstract
-/// class.
+// TODO: Support profiling.
+bool WebAssembly::SupportsProfiling() const { return false; }
-Tool *SHAVEToolChain::getTool(Action::ActionClass AC) const {
- // SelectTool() must find a tool using the method in the superclass.
- // There's nothing we can do if that fails.
- llvm_unreachable("SHAVEToolChain can't getTool");
+bool WebAssembly::HasNativeLLVMSupport() const { return true; }
+
+void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array, true))
+ CC1Args.push_back("-fuse-init-array");
}
-Tool *SHAVEToolChain::buildLinker() const {
- // SHAVEToolChain executables can not be linked except by the vendor tools.
- llvm_unreachable("SHAVEToolChain can't buildLinker");
+Tool *WebAssembly::buildLinker() const {
+ return new tools::wasm::Linker(*this);
}
-Tool *SHAVEToolChain::buildAssembler() const {
- // This one you'd think should be reachable since we expose an
- // assembler to the driver, except not the way it expects.
- llvm_unreachable("SHAVEToolChain can't buildAssembler");
+PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ if (Args.hasArg(options::OPT_static))
+ D.Diag(diag::err_drv_unsupported_opt_for_target) << "-static" << "PS4";
+
+ // Determine where to find the PS4 libraries. We use SCE_PS4_SDK_DIR
+ // if it exists; otherwise use the driver's installation path, which
+ // should be <SDK_DIR>/host_tools/bin.
+
+ SmallString<512> PS4SDKDir;
+ if (const char *EnvValue = getenv("SCE_PS4_SDK_DIR")) {
+ if (!llvm::sys::fs::exists(EnvValue))
+ getDriver().Diag(clang::diag::warn_drv_ps4_sdk_dir) << EnvValue;
+ PS4SDKDir = EnvValue;
+ } else {
+ PS4SDKDir = getDriver().Dir;
+ llvm::sys::path::append(PS4SDKDir, "/../../");
+ }
+
+ // By default, the driver won't report a warning if it can't find
+ // PS4's include or lib directories. This behavior could be changed if
+ // -Weverything or -Winvalid-or-nonexistent-directory options are passed.
+ // If -isysroot was passed, use that as the SDK base path.
+ std::string PrefixDir;
+ if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+ PrefixDir = A->getValue();
+ if (!llvm::sys::fs::exists(PrefixDir))
+ getDriver().Diag(clang::diag::warn_missing_sysroot) << PrefixDir;
+ } else
+ PrefixDir = PS4SDKDir.str();
+
+ SmallString<512> PS4SDKIncludeDir(PrefixDir);
+ llvm::sys::path::append(PS4SDKIncludeDir, "target/include");
+ if (!Args.hasArg(options::OPT_nostdinc) &&
+ !Args.hasArg(options::OPT_nostdlibinc) &&
+ !Args.hasArg(options::OPT_isysroot) &&
+ !Args.hasArg(options::OPT__sysroot_EQ) &&
+ !llvm::sys::fs::exists(PS4SDKIncludeDir)) {
+ getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
+ << "PS4 system headers" << PS4SDKIncludeDir;
+ }
+
+ SmallString<512> PS4SDKLibDir(PS4SDKDir);
+ llvm::sys::path::append(PS4SDKLibDir, "target/lib");
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs) &&
+ !Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) &&
+ !Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) &&
+ !Args.hasArg(options::OPT_emit_ast) &&
+ !llvm::sys::fs::exists(PS4SDKLibDir)) {
+ getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
+ << "PS4 system libraries" << PS4SDKLibDir;
+ return;
+ }
+ getFilePaths().push_back(PS4SDKLibDir.str());
+}
+
+Tool *PS4CPU::buildAssembler() const {
+ return new tools::PS4cpu::Assemble(*this);
+}
+
+Tool *PS4CPU::buildLinker() const { return new tools::PS4cpu::Link(*this); }
+
+bool PS4CPU::isPICDefault() const { return true; }
+
+bool PS4CPU::HasNativeLLVMSupport() const { return true; }
+
+SanitizerMask PS4CPU::getSupportedSanitizers() const {
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::Vptr;
+ return Res;
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
index 59eaade..b6fd426 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
@@ -78,6 +78,7 @@ public:
class GCCInstallationDetector {
bool IsValid;
llvm::Triple GCCTriple;
+ const Driver &D;
// FIXME: These might be better as path objects.
std::string GCCInstallPath;
@@ -99,9 +100,9 @@ public:
MultilibSet Multilibs;
public:
- GCCInstallationDetector() : IsValid(false) {}
- void init(const Driver &D, const llvm::Triple &TargetTriple,
- const llvm::opt::ArgList &Args);
+ explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
+ void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args,
+ ArrayRef<std::string> ExtraTripleAliases = None);
/// \brief Check whether we detected a valid GCC install.
bool isValid() const { return IsValid; }
@@ -145,11 +146,53 @@ public:
const std::string &LibDir,
StringRef CandidateTriple,
bool NeedsBiarchSuffix = false);
+
+ void scanLibDirForGCCTripleSolaris(const llvm::Triple &TargetArch,
+ const llvm::opt::ArgList &Args,
+ const std::string &LibDir,
+ StringRef CandidateTriple,
+ bool NeedsBiarchSuffix = false);
};
protected:
GCCInstallationDetector GCCInstallation;
+ // \brief A class to find a viable CUDA installation
+
+ class CudaInstallationDetector {
+ bool IsValid;
+ const Driver &D;
+ std::string CudaInstallPath;
+ std::string CudaLibPath;
+ std::string CudaLibDevicePath;
+ std::string CudaIncludePath;
+ llvm::StringMap<std::string> CudaLibDeviceMap;
+
+ public:
+ CudaInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
+ void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args);
+
+ /// \brief Check whether we detected a valid Cuda install.
+ bool isValid() const { return IsValid; }
+ /// \brief Print information about the detected CUDA installation.
+ void print(raw_ostream &OS) const;
+
+ /// \brief Get the detected Cuda installation path.
+ StringRef getInstallPath() const { return CudaInstallPath; }
+ /// \brief Get the detected Cuda Include path.
+ StringRef getIncludePath() const { return CudaIncludePath; }
+ /// \brief Get the detected Cuda library path.
+ StringRef getLibPath() const { return CudaLibPath; }
+ /// \brief Get the detected Cuda device library path.
+ StringRef getLibDevicePath() const { return CudaLibDevicePath; }
+ /// \brief Get libdevice file for given architecture
+ std::string getLibDeviceFile(StringRef Gpu) const {
+ return CudaLibDeviceMap.lookup(Gpu);
+ }
+ };
+
+ CudaInstallationDetector CudaInstallation;
+
public:
Generic_GCC(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
@@ -177,6 +220,13 @@ protected:
/// \brief Check whether the target triple's architecture is 32-bits.
bool isTarget32Bit() const { return getTriple().isArch32Bit(); }
+ bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, StringRef GCCTriple,
+ StringRef GCCMultiarchTriple,
+ StringRef TargetMultiarchTriple,
+ Twine IncludeSuffix,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
/// @}
private:
@@ -236,8 +286,8 @@ public:
/// Add any profiling runtime libraries that are needed. This is essentially a
/// MachO specific version of addProfileRT in Tools.cpp.
- virtual void addProfileRTLibs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const {
+ void addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override {
// There aren't any profiling libs for embedded targets currently.
}
@@ -293,7 +343,9 @@ public:
bool UseDwarfDebugFlags() const override;
- bool UseSjLjExceptions() const override { return false; }
+ bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
/// }
};
@@ -308,7 +360,15 @@ public:
// the argument translation business.
mutable bool TargetInitialized;
- enum DarwinPlatformKind { MacOS, IPhoneOS, IPhoneOSSimulator };
+ enum DarwinPlatformKind {
+ MacOS,
+ IPhoneOS,
+ IPhoneOSSimulator,
+ TvOS,
+ TvOSSimulator,
+ WatchOS,
+ WatchOSSimulator
+ };
mutable DarwinPlatformKind TargetPlatform;
@@ -336,7 +396,8 @@ public:
llvm::opt::ArgStringList &CmdArgs) const override;
bool isKernelStatic() const override {
- return !isTargetIPhoneOS() || isIPhoneOSVersionLT(6, 0);
+ return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) &&
+ !isTargetWatchOS());
}
void addProfileRTLibs(const llvm::opt::ArgList &Args,
@@ -365,12 +426,13 @@ protected:
bool isTargetIPhoneOS() const {
assert(TargetInitialized && "Target not initialized!");
- return TargetPlatform == IPhoneOS;
+ return TargetPlatform == IPhoneOS || TargetPlatform == TvOS;
}
bool isTargetIOSSimulator() const {
assert(TargetInitialized && "Target not initialized!");
- return TargetPlatform == IPhoneOSSimulator;
+ return TargetPlatform == IPhoneOSSimulator ||
+ TargetPlatform == TvOSSimulator;
}
bool isTargetIOSBased() const {
@@ -378,6 +440,36 @@ protected:
return isTargetIPhoneOS() || isTargetIOSSimulator();
}
+ bool isTargetTvOS() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetPlatform == TvOS;
+ }
+
+ bool isTargetTvOSSimulator() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetPlatform == TvOSSimulator;
+ }
+
+ bool isTargetTvOSBased() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetPlatform == TvOS || TargetPlatform == TvOSSimulator;
+ }
+
+ bool isTargetWatchOS() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetPlatform == WatchOS;
+ }
+
+ bool isTargetWatchOSSimulator() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetPlatform == WatchOSSimulator;
+ }
+
+ bool isTargetWatchOSBased() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetPlatform == WatchOS || TargetPlatform == WatchOSSimulator;
+ }
+
bool isTargetMacOS() const {
assert(TargetInitialized && "Target not initialized!");
return TargetPlatform == MacOS;
@@ -428,7 +520,7 @@ public:
unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
// Stack protectors default to on for user code on 10.5,
// and for everything in 10.6 and beyond
- if (isTargetIOSBased())
+ if (isTargetIOSBased() || isTargetWatchOSBased())
return 1;
else if (isTargetMacOS() && !isMacosxVersionLT(10, 6))
return 1;
@@ -442,7 +534,7 @@ public:
void CheckObjCARC() const override;
- bool UseSjLjExceptions() const override;
+ bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const override;
SanitizerMask getSupportedSanitizers() const override;
};
@@ -469,6 +561,15 @@ public:
void AddLinkARCArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
+
+ unsigned GetDefaultDwarfVersion() const override { return 2; }
+ // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
+ // Darwin defaults to standalone/full debug info.
+ bool GetDefaultStandaloneDebug() const override { return true; }
+ llvm::DebuggerKind getDefaultDebuggerTuning() const override {
+ return llvm::DebuggerKind::LLDB;
+ }
+
/// }
private:
@@ -521,6 +622,12 @@ public:
bool IsIntegratedAssemblerDefault() const override { return true; }
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ unsigned GetDefaultDwarfVersion() const override { return 2; }
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
@@ -572,6 +679,7 @@ public:
unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
return 2;
}
+ unsigned GetDefaultDwarfVersion() const override { return 2; }
protected:
Tool *buildAssembler() const override;
@@ -615,9 +723,13 @@ public:
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- bool UseSjLjExceptions() const override;
+ bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const override;
bool isPIEDefault() const override;
SanitizerMask getSupportedSanitizers() const override;
+ unsigned GetDefaultDwarfVersion() const override { return 2; }
+ // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
+ // FreeBSD defaults to standalone/full debug info.
+ bool GetDefaultStandaloneDebug() const override { return true; }
protected:
Tool *buildAssembler() const override;
@@ -679,26 +791,19 @@ public:
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
bool isPIEDefault() const override;
SanitizerMask getSupportedSanitizers() const override;
+ void addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+ virtual std::string computeSysRoot() const;
- std::string Linker;
std::vector<std::string> ExtraOpts;
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
-
-private:
- static bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
- StringRef GCCTriple,
- StringRef GCCMultiarchTriple,
- StringRef TargetMultiarchTriple,
- Twine IncludeSuffix,
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args);
-
- std::string computeSysRoot() const;
};
class LLVM_LIBRARY_VISIBILITY CudaToolChain : public Linux {
@@ -713,16 +818,52 @@ public:
llvm::opt::ArgStringList &CC1Args) const override;
};
-class LLVM_LIBRARY_VISIBILITY Hexagon_TC : public Linux {
+class LLVM_LIBRARY_VISIBILITY MipsLLVMToolChain : public Linux {
+protected:
+ Tool *buildLinker() const override;
+
+public:
+ MipsLLVMToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component,
+ bool Shared = false) const override;
+
+ std::string computeSysRoot() const override;
+
+ RuntimeLibType GetDefaultRuntimeLibType() const override {
+ return GCCInstallation.isValid() ? RuntimeLibType::RLT_Libgcc
+ : RuntimeLibType::RLT_CompilerRT;
+ }
+
+private:
+ Multilib SelectedMultilib;
+ std::string LibSuffix;
+};
+
+class LLVM_LIBRARY_VISIBILITY HexagonToolChain : public Linux {
protected:
GCCVersion GCCLibAndIncVersion;
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
public:
- Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
- ~Hexagon_TC() override;
+ HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ ~HexagonToolChain() override;
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
@@ -733,21 +874,37 @@ public:
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; }
+ bool IsIntegratedAssemblerDefault() const override {
+ return true;
+ }
- static std::string GetGnuDir(const std::string &InstalledDir,
- const llvm::opt::ArgList &Args);
+ std::string getHexagonTargetDir(
+ const std::string &InstalledDir,
+ const SmallVectorImpl<std::string> &PrefixDirs) const;
+ void getHexagonLibraryPaths(const llvm::opt::ArgList &Args,
+ ToolChain::path_list &LibPaths) const;
- static StringRef GetTargetCPU(const llvm::opt::ArgList &Args);
+ static const StringRef GetDefaultCPU();
+ static const StringRef GetTargetCPUVersion(const llvm::opt::ArgList &Args);
- static const char *GetSmallDataThreshold(const llvm::opt::ArgList &Args);
+ static Optional<unsigned> getSmallDataThreshold(
+ const llvm::opt::ArgList &Args);
+};
+
+class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF {
+protected:
+ Tool *buildLinker() const override;
- static bool UsesG0(const char *smallDataThreshold);
+public:
+ AMDGPUToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ bool IsIntegratedAssemblerDefault() const override { return true; }
};
-class LLVM_LIBRARY_VISIBILITY NaCl_TC : public Generic_ELF {
+class LLVM_LIBRARY_VISIBILITY NaClToolChain : public Generic_ELF {
public:
- NaCl_TC(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
+ NaClToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
@@ -765,14 +922,13 @@ public:
return getTriple().getArch() == llvm::Triple::mipsel;
}
- // Get the path to the file containing NaCl's ARM macros. It lives in NaCl_TC
- // because the AssembleARM tool needs a const char * that it can pass around
- // and the toolchain outlives all the jobs.
+ // Get the path to the file containing NaCl's ARM macros.
+ // It lives in NaClToolChain because the ARMAssembler tool needs a
+ // const char * that it can pass around,
const char *GetNaClArmMacrosPath() const { return NaClArmMacrosPath.c_str(); }
std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const override;
- std::string Linker;
protected:
Tool *buildLinker() const override;
@@ -801,6 +957,10 @@ public:
MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ const char *BoundArch) const override;
+
bool IsIntegratedAssemblerDefault() const override;
bool IsUnwindTablesDefault() const override;
bool isPICDefault() const override;
@@ -814,8 +974,14 @@ public:
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- bool getWindowsSDKDir(std::string &path, int &major, int &minor) const;
+ bool getWindowsSDKDir(std::string &path, int &major,
+ std::string &windowsSDKIncludeVersion,
+ std::string &windowsSDKLibVersion) const;
bool getWindowsSDKLibraryPath(std::string &path) const;
+ /// \brief Check if Universal CRT should be used if available
+ bool useUniversalCRT(std::string &visualStudioDir) const;
+ bool getUniversalCRTSdkDir(std::string &path, std::string &ucrtVersion) const;
+ bool getUniversalCRTLibraryPath(std::string &path) const;
bool getVisualStudioInstallDir(std::string &path) const;
bool getVisualStudioBinariesFolder(const char *clangProgramPath,
std::string &path) const;
@@ -828,7 +994,9 @@ protected:
void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
const std::string &folder,
- const char *subfolder) const;
+ const Twine &subfolder1,
+ const Twine &subfolder2 = "",
+ const Twine &subfolder3 = "") const;
Tool *buildLinker() const override;
Tool *buildAssembler() const override;
@@ -858,15 +1026,17 @@ public:
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
+ SanitizerMask getSupportedSanitizers() const override;
+
protected:
Tool *buildLinker() const override;
Tool *buildAssembler() const override;
};
-class LLVM_LIBRARY_VISIBILITY XCore : public ToolChain {
+class LLVM_LIBRARY_VISIBILITY XCoreToolChain : public ToolChain {
public:
- XCore(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
+ XCoreToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
protected:
Tool *buildAssembler() const override;
@@ -890,29 +1060,84 @@ public:
llvm::opt::ArgStringList &CmdArgs) const override;
};
-/// SHAVEToolChain - A tool chain using the compiler installed by the the
-// Movidius SDK into MV_TOOLS_DIR (which we assume will be copied to llvm's
-// installation dir) to perform all subcommands.
-class LLVM_LIBRARY_VISIBILITY SHAVEToolChain : public Generic_GCC {
+/// MyriadToolChain - A tool chain using either clang or the external compiler
+/// installed by the Movidius SDK to perform all subcommands.
+class LLVM_LIBRARY_VISIBILITY MyriadToolChain : public Generic_GCC {
public:
- SHAVEToolChain(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
- ~SHAVEToolChain() override;
+ MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ ~MyriadToolChain() override;
- virtual Tool *SelectTool(const JobAction &JA) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ Tool *SelectTool(const JobAction &JA) const override;
+ unsigned GetDefaultDwarfVersion() const override { return 2; }
protected:
- Tool *getTool(Action::ActionClass AC) const override;
- Tool *buildAssembler() const override;
Tool *buildLinker() const override;
+ bool isShaveCompilation(const llvm::Triple &T) const {
+ return T.getArch() == llvm::Triple::shave;
+ }
private:
mutable std::unique_ptr<Tool> Compiler;
mutable std::unique_ptr<Tool> Assembler;
};
+class LLVM_LIBRARY_VISIBILITY WebAssembly final : public ToolChain {
+public:
+ WebAssembly(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+private:
+ bool IsMathErrnoDefault() const override;
+ bool IsObjCNonFragileABIDefault() const override;
+ bool UseObjCMixedDispatch() const override;
+ bool isPICDefault() const override;
+ bool isPIEDefault() const override;
+ bool isPICDefaultForced() const override;
+ bool IsIntegratedAssemblerDefault() const override;
+ bool hasBlocksRuntime() const override;
+ bool SupportsObjCGC() const override;
+ bool SupportsProfiling() const override;
+ bool HasNativeLLVMSupport() const override;
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ Tool *buildLinker() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY PS4CPU : public Generic_ELF {
+public:
+ PS4CPU(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool IsMathErrnoDefault() const override { return false; }
+ bool IsObjCNonFragileABIDefault() const override { return true; }
+ bool HasNativeLLVMSupport() const override;
+ bool isPICDefault() const override;
+
+ unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
+ return 2; // SSPStrong
+ }
+
+ llvm::DebuggerKind getDefaultDebuggerTuning() const override {
+ return llvm::DebuggerKind::SCE;
+ }
+
+ SanitizerMask getSupportedSanitizers() const override;
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
-#endif
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_H
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
index 7352537..5a2dbd3 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
@@ -1,4 +1,4 @@
-//===--- Tools.cpp - Tools Implementations --------------------------------===//
+//===--- Tools.cpp - Tools Implementations ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -32,7 +32,7 @@
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
-#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
@@ -41,6 +41,7 @@
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/TargetParser.h"
#ifdef LLVM_ON_UNIX
#include <unistd.h> // For getuid().
@@ -51,18 +52,51 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-static void addAssemblerKPIC(const ArgList &Args, ArgStringList &CmdArgs) {
- Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
- options::OPT_fpic, options::OPT_fno_pic,
- options::OPT_fPIE, options::OPT_fno_PIE,
- options::OPT_fpie, options::OPT_fno_pie);
- if (!LastPICArg)
- return;
- if (LastPICArg->getOption().matches(options::OPT_fPIC) ||
- LastPICArg->getOption().matches(options::OPT_fpic) ||
- LastPICArg->getOption().matches(options::OPT_fPIE) ||
- LastPICArg->getOption().matches(options::OPT_fpie)) {
- CmdArgs.push_back("-KPIC");
+static void handleTargetFeaturesGroup(const ArgList &Args,
+ std::vector<const char *> &Features,
+ OptSpecifier Group) {
+ for (const Arg *A : Args.filtered(Group)) {
+ StringRef Name = A->getOption().getName();
+ A->claim();
+
+ // Skip over "-m".
+ assert(Name.startswith("m") && "Invalid feature name.");
+ Name = Name.substr(1);
+
+ bool IsNegative = Name.startswith("no-");
+ if (IsNegative)
+ Name = Name.substr(3);
+ Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
+ }
+}
+
+static const char *getSparcAsmModeForCPU(StringRef Name,
+ const llvm::Triple &Triple) {
+ if (Triple.getArch() == llvm::Triple::sparcv9) {
+ return llvm::StringSwitch<const char *>(Name)
+ .Case("niagara", "-Av9b")
+ .Case("niagara2", "-Av9b")
+ .Case("niagara3", "-Av9d")
+ .Case("niagara4", "-Av9d")
+ .Default("-Av9");
+ } else {
+ return llvm::StringSwitch<const char *>(Name)
+ .Case("v8", "-Av8")
+ .Case("supersparc", "-Av8")
+ .Case("sparclite", "-Asparclite")
+ .Case("f934", "-Asparclite")
+ .Case("hypersparc", "-Av8")
+ .Case("sparclite86x", "-Asparclite")
+ .Case("sparclet", "-Asparclet")
+ .Case("tsc701", "-Asparclet")
+ .Case("v9", "-Av8plus")
+ .Case("ultrasparc", "-Av8plus")
+ .Case("ultrasparc3", "-Av8plus")
+ .Case("niagara", "-Av8plusb")
+ .Case("niagara2", "-Av8plusb")
+ .Case("niagara3", "-Av8plusd")
+ .Case("niagara4", "-Av8plusd")
+ .Default("-Av8");
}
}
@@ -199,13 +233,9 @@ static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);
for (const auto &II : Inputs) {
- if (!TC.HasNativeLLVMSupport()) {
+ if (!TC.HasNativeLLVMSupport() && types::isLLVMIR(II.getType()))
// Don't try to pass LLVM inputs unless we have native support.
- if (II.getType() == types::TY_LLVM_IR ||
- II.getType() == types::TY_LTO_IR ||
- II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
- D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString();
- }
+ D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString();
// Add filenames immediately.
if (II.isFilename()) {
@@ -262,7 +292,8 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs,
const InputInfo &Output,
- const InputInfoList &Inputs) const {
+ const InputInfoList &Inputs,
+ const ToolChain *AuxToolChain) const {
Arg *A;
CheckPreprocessingOptions(D, Args);
@@ -412,11 +443,11 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
A->render(Args, CmdArgs);
}
- Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
- Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F,
- options::OPT_index_header_map);
+ Args.AddAllArgs(CmdArgs,
+ {options::OPT_D, options::OPT_U, options::OPT_I_Group,
+ options::OPT_F, options::OPT_index_header_map});
- // Add -Wp, and -Xassembler if using the preprocessor.
+ // Add -Wp, and -Xpreprocessor if using the preprocessor.
// FIXME: There is a very unfortunate problem here, some troubled
// souls abuse -Wp, to pass preprocessor options in gcc syntax. To
@@ -454,12 +485,26 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
// OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++.
addDirectoryList(Args, CmdArgs, "-objcxx-isystem", "OBJCPLUS_INCLUDE_PATH");
+ // Optional AuxToolChain indicates that we need to include headers
+ // for more than one target. If that's the case, add include paths
+ // from AuxToolChain right after include paths of the same kind for
+ // the current target.
+
// Add C++ include arguments, if needed.
- if (types::isCXX(Inputs[0].getType()))
+ if (types::isCXX(Inputs[0].getType())) {
getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
+ if (AuxToolChain)
+ AuxToolChain->AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
+ }
// Add system include arguments.
getToolChain().AddClangSystemIncludeArgs(Args, CmdArgs);
+ if (AuxToolChain)
+ AuxToolChain->AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
+
+ // Add CUDA include arguments, if needed.
+ if (types::isCuda(Inputs[0].getType()))
+ getToolChain().AddCudaIncludeArgs(Args, CmdArgs);
}
// FIXME: Move to target hook.
@@ -498,6 +543,8 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) {
return false;
case llvm::Triple::xcore:
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
return true;
}
}
@@ -507,13 +554,13 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) {
// Get SubArch (vN).
static int getARMSubArchVersionNumber(const llvm::Triple &Triple) {
llvm::StringRef Arch = Triple.getArchName();
- return llvm::ARMTargetParser::parseArchVersion(Arch);
+ return llvm::ARM::parseArchVersion(Arch);
}
// True if M-profile.
static bool isARMMProfile(const llvm::Triple &Triple) {
llvm::StringRef Arch = Triple.getArchName();
- unsigned Profile = llvm::ARMTargetParser::parseArchProfile(Arch);
+ unsigned Profile = llvm::ARM::parseArchProfile(Arch);
return Profile == llvm::ARM::PK_M;
}
@@ -542,19 +589,8 @@ static void getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
static void getARMHWDivFeatures(const Driver &D, const Arg *A,
const ArgList &Args, StringRef HWDiv,
std::vector<const char *> &Features) {
- if (HWDiv == "arm") {
- Features.push_back("+hwdiv-arm");
- Features.push_back("-hwdiv");
- } else if (HWDiv == "thumb") {
- Features.push_back("-hwdiv-arm");
- Features.push_back("+hwdiv");
- } else if (HWDiv == "arm,thumb" || HWDiv == "thumb,arm") {
- Features.push_back("+hwdiv-arm");
- Features.push_back("+hwdiv");
- } else if (HWDiv == "none") {
- Features.push_back("-hwdiv-arm");
- Features.push_back("-hwdiv");
- } else
+ unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv);
+ if (!llvm::ARM::getHWDivFeatures(HWDivID, Features))
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
@@ -562,82 +598,125 @@ static void getARMHWDivFeatures(const Driver &D, const Arg *A,
static void getARMFPUFeatures(const Driver &D, const Arg *A,
const ArgList &Args, StringRef FPU,
std::vector<const char *> &Features) {
- unsigned FPUID = llvm::ARMTargetParser::parseFPU(FPU);
- if (!llvm::ARMTargetParser::getFPUFeatures(FPUID, Features))
+ unsigned FPUID = llvm::ARM::parseFPU(FPU);
+ if (!llvm::ARM::getFPUFeatures(FPUID, Features))
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
+// Decode ARM features from string like +[no]featureA+[no]featureB+...
+static bool DecodeARMFeatures(const Driver &D, StringRef text,
+ std::vector<const char *> &Features) {
+ SmallVector<StringRef, 8> Split;
+ text.split(Split, StringRef("+"), -1, false);
+
+ for (StringRef Feature : Split) {
+ const char *FeatureName = llvm::ARM::getArchExtFeature(Feature);
+ if (FeatureName)
+ Features.push_back(FeatureName);
+ else
+ return false;
+ }
+ return true;
+}
+
// Check if -march is valid by checking if it can be canonicalised and parsed.
// getARMArch is used here instead of just checking the -march value in order
// to handle -march=native correctly.
static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
llvm::StringRef ArchName,
+ std::vector<const char *> &Features,
const llvm::Triple &Triple) {
+ std::pair<StringRef, StringRef> Split = ArchName.split("+");
+
std::string MArch = arm::getARMArch(ArchName, Triple);
- if (llvm::ARMTargetParser::parseArch(MArch) == llvm::ARM::AK_INVALID)
+ if (llvm::ARM::parseArch(MArch) == llvm::ARM::AK_INVALID ||
+ (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features)))
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
// Check -mcpu=. Needs ArchName to handle -mcpu=generic.
static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
llvm::StringRef CPUName, llvm::StringRef ArchName,
+ std::vector<const char *> &Features,
const llvm::Triple &Triple) {
+ std::pair<StringRef, StringRef> Split = CPUName.split("+");
+
std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
- std::string Arch = arm::getARMArch(ArchName, Triple);
- if (strcmp(arm::getLLVMArchSuffixForARM(CPU, Arch), "") == 0)
+ if (arm::getLLVMArchSuffixForARM(CPU, ArchName, Triple).empty() ||
+ (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features)))
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
+static bool useAAPCSForMachO(const llvm::Triple &T) {
+ // The backend is hardwired to assume AAPCS for M-class processors, ensure
+ // the frontend matches that.
+ return T.getEnvironment() == llvm::Triple::EABI ||
+ T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T);
+}
+
// Select the float ABI as determined by -msoft-float, -mhard-float, and
// -mfloat-abi=.
-StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
- const llvm::Triple &Triple) {
- StringRef FloatABI;
+arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
+ const Driver &D = TC.getDriver();
+ const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(Args));
+ auto SubArch = getARMSubArchVersionNumber(Triple);
+ arm::FloatABI ABI = FloatABI::Invalid;
if (Arg *A =
Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
options::OPT_mfloat_abi_EQ)) {
- if (A->getOption().matches(options::OPT_msoft_float))
- FloatABI = "soft";
- else if (A->getOption().matches(options::OPT_mhard_float))
- FloatABI = "hard";
- else {
- FloatABI = A->getValue();
- if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") {
+ if (A->getOption().matches(options::OPT_msoft_float)) {
+ ABI = FloatABI::Soft;
+ } else if (A->getOption().matches(options::OPT_mhard_float)) {
+ ABI = FloatABI::Hard;
+ } else {
+ ABI = llvm::StringSwitch<arm::FloatABI>(A->getValue())
+ .Case("soft", FloatABI::Soft)
+ .Case("softfp", FloatABI::SoftFP)
+ .Case("hard", FloatABI::Hard)
+ .Default(FloatABI::Invalid);
+ if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
- FloatABI = "soft";
+ ABI = FloatABI::Soft;
}
}
+
+ // It is incorrect to select hard float ABI on MachO platforms if the ABI is
+ // "apcs-gnu".
+ if (Triple.isOSBinFormatMachO() && !useAAPCSForMachO(Triple) &&
+ ABI == FloatABI::Hard) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args)
+ << Triple.getArchName();
+ }
}
// If unspecified, choose the default based on the platform.
- if (FloatABI.empty()) {
+ if (ABI == FloatABI::Invalid) {
switch (Triple.getOS()) {
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
- case llvm::Triple::IOS: {
+ case llvm::Triple::IOS:
+ case llvm::Triple::TvOS: {
// Darwin defaults to "softfp" for v6 and v7.
- //
- if (getARMSubArchVersionNumber(Triple) == 6 ||
- getARMSubArchVersionNumber(Triple) == 7)
- FloatABI = "softfp";
- else
- FloatABI = "soft";
+ ABI = (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
break;
}
+ case llvm::Triple::WatchOS:
+ ABI = FloatABI::Hard;
+ break;
// FIXME: this is invalid for WindowsCE
case llvm::Triple::Win32:
- FloatABI = "hard";
+ ABI = FloatABI::Hard;
break;
case llvm::Triple::FreeBSD:
switch (Triple.getEnvironment()) {
case llvm::Triple::GNUEABIHF:
- FloatABI = "hard";
+ ABI = FloatABI::Hard;
break;
default:
// FreeBSD defaults to soft float
- FloatABI = "soft";
+ ABI = FloatABI::Soft;
break;
}
break;
@@ -645,28 +724,20 @@ StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
default:
switch (Triple.getEnvironment()) {
case llvm::Triple::GNUEABIHF:
- FloatABI = "hard";
- break;
- case llvm::Triple::GNUEABI:
- FloatABI = "softfp";
- break;
case llvm::Triple::EABIHF:
- FloatABI = "hard";
+ ABI = FloatABI::Hard;
break;
+ case llvm::Triple::GNUEABI:
case llvm::Triple::EABI:
// EABI is always AAPCS, and if it was not marked 'hard', it's softfp
- FloatABI = "softfp";
+ ABI = FloatABI::SoftFP;
break;
- case llvm::Triple::Android: {
- if (getARMSubArchVersionNumber(Triple) == 7)
- FloatABI = "softfp";
- else
- FloatABI = "soft";
+ case llvm::Triple::Android:
+ ABI = (SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
break;
- }
default:
// Assume "soft", but warn the user we are guessing.
- FloatABI = "soft";
+ ABI = FloatABI::Soft;
if (Triple.getOS() != llvm::Triple::UnknownOS ||
!Triple.isOSBinFormatMachO())
D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
@@ -675,16 +746,20 @@ StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
}
}
- return FloatABI;
+ assert(ABI != FloatABI::Invalid && "must select an ABI");
+ return ABI;
}
-static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+static void getARMTargetFeatures(const ToolChain &TC,
+ const llvm::Triple &Triple,
const ArgList &Args,
std::vector<const char *> &Features,
bool ForAS) {
+ const Driver &D = TC.getDriver();
+
bool KernelOrKext =
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
- StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
+ arm::FloatABI ABI = arm::getARMFloatABI(TC, Args);
const Arg *WaCPU = nullptr, *WaFPU = nullptr;
const Arg *WaHDiv = nullptr, *WaArch = nullptr;
@@ -702,11 +777,11 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// assembler and the frontend behave the same.
// Use software floating point operations?
- if (FloatABI == "soft")
+ if (ABI == arm::FloatABI::Soft)
Features.push_back("+soft-float");
// Use software floating point argument passing?
- if (FloatABI != "hard")
+ if (ABI != arm::FloatABI::Hard)
Features.push_back("+soft-float-abi");
} else {
// Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down
@@ -726,29 +801,6 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
}
}
- // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
- const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
- if (WaFPU) {
- if (FPUArg)
- D.Diag(clang::diag::warn_drv_unused_argument)
- << FPUArg->getAsString(Args);
- getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6),
- Features);
- } else if (FPUArg) {
- getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
- }
-
- // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.
- const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ);
- if (WaHDiv) {
- if (HDivArg)
- D.Diag(clang::diag::warn_drv_unused_argument)
- << HDivArg->getAsString(Args);
- getARMHWDivFeatures(D, WaHDiv, Args,
- StringRef(WaHDiv->getValue()).substr(8), Features);
- } else if (HDivArg)
- getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
-
// Check -march. ClangAs gives preference to -Wa,-march=.
const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);
StringRef ArchName;
@@ -757,12 +809,12 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
D.Diag(clang::diag::warn_drv_unused_argument)
<< ArchArg->getAsString(Args);
ArchName = StringRef(WaArch->getValue()).substr(7);
- checkARMArchName(D, WaArch, Args, ArchName, Triple);
+ checkARMArchName(D, WaArch, Args, ArchName, Features, Triple);
// FIXME: Set Arch.
D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args);
} else if (ArchArg) {
ArchName = ArchArg->getValue();
- checkARMArchName(D, ArchArg, Args, ArchName, Triple);
+ checkARMArchName(D, ArchArg, Args, ArchName, Features, Triple);
}
// Check -mcpu. ClangAs gives preference to -Wa,-mcpu=.
@@ -773,15 +825,47 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
D.Diag(clang::diag::warn_drv_unused_argument)
<< CPUArg->getAsString(Args);
CPUName = StringRef(WaCPU->getValue()).substr(6);
- checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Triple);
+ checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Features, Triple);
} else if (CPUArg) {
CPUName = CPUArg->getValue();
- checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Triple);
+ checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Features, Triple);
}
+ // Add CPU features for generic CPUs
+ if (CPUName == "native") {
+ llvm::StringMap<bool> HostFeatures;
+ if (llvm::sys::getHostCPUFeatures(HostFeatures))
+ for (auto &F : HostFeatures)
+ Features.push_back(
+ Args.MakeArgString((F.second ? "+" : "-") + F.first()));
+ }
+
+ // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
+ const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
+ if (WaFPU) {
+ if (FPUArg)
+ D.Diag(clang::diag::warn_drv_unused_argument)
+ << FPUArg->getAsString(Args);
+ getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6),
+ Features);
+ } else if (FPUArg) {
+ getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
+ }
+
+ // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.
+ const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ);
+ if (WaHDiv) {
+ if (HDivArg)
+ D.Diag(clang::diag::warn_drv_unused_argument)
+ << HDivArg->getAsString(Args);
+ getARMHWDivFeatures(D, WaHDiv, Args,
+ StringRef(WaHDiv->getValue()).substr(8), Features);
+ } else if (HDivArg)
+ getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
+
// Setting -msoft-float effectively disables NEON because of the GCC
// implementation, although the same isn't true of VFP or VFP3.
- if (FloatABI == "soft") {
+ if (ABI == arm::FloatABI::Soft) {
Features.push_back("-neon");
// Also need to explicitly disable features which imply NEON.
Features.push_back("-crypto");
@@ -806,31 +890,72 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
options::OPT_mno_long_calls)) {
if (A->getOption().matches(options::OPT_mlong_calls))
Features.push_back("+long-calls");
- } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6))) {
+ } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
+ !Triple.isWatchOS()) {
Features.push_back("+long-calls");
}
-}
-void Clang::AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs,
- bool KernelOrKext) const {
- const Driver &D = getToolChain().getDriver();
- // Get the effective triple, which takes into account the deployment target.
- std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
- llvm::Triple Triple(TripleStr);
+ // Kernel code has more strict alignment requirements.
+ if (KernelOrKext)
+ Features.push_back("+strict-align");
+ else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
+ options::OPT_munaligned_access)) {
+ if (A->getOption().matches(options::OPT_munaligned_access)) {
+ // No v6M core supports unaligned memory access (v6M ARM ARM A3.2).
+ if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
+ D.Diag(diag::err_target_unsupported_unaligned) << "v6m";
+ } else
+ Features.push_back("+strict-align");
+ } else {
+ // Assume pre-ARMv6 doesn't support unaligned accesses.
+ //
+ // ARMv6 may or may not support unaligned accesses depending on the
+ // SCTLR.U bit, which is architecture-specific. We assume ARMv6
+ // Darwin and NetBSD targets support unaligned accesses, and others don't.
+ //
+ // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit
+ // which raises an alignment fault on unaligned accesses. Linux
+ // defaults this bit to 0 and handles it as a system-wide (not
+ // per-process) setting. It is therefore safe to assume that ARMv7+
+ // Linux targets support unaligned accesses. The same goes for NaCl.
+ //
+ // The above behavior is consistent with GCC.
+ int VersionNum = getARMSubArchVersionNumber(Triple);
+ if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {
+ if (VersionNum < 6 ||
+ Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
+ Features.push_back("+strict-align");
+ } else if (Triple.isOSLinux() || Triple.isOSNaCl()) {
+ if (VersionNum < 7)
+ Features.push_back("+strict-align");
+ } else
+ Features.push_back("+strict-align");
+ }
+ // llvm does not support reserving registers in general. There is support
+ // for reserving r9 on ARM though (defined as a platform-specific register
+ // in ARM EABI).
+ if (Args.hasArg(options::OPT_ffixed_r9))
+ Features.push_back("+reserve-r9");
+
+ // The kext linker doesn't know how to deal with movw/movt.
+ if (KernelOrKext || Args.hasArg(options::OPT_mno_movt))
+ Features.push_back("+no-movt");
+}
+
+void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
+ ArgStringList &CmdArgs, bool KernelOrKext) const {
// Select the ABI to use.
- //
// FIXME: Support -meabi.
// FIXME: Parts of this are duplicated in the backend, unify this somehow.
const char *ABIName = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
} else if (Triple.isOSBinFormatMachO()) {
- // The backend is hardwired to assume AAPCS for M-class processors, ensure
- // the frontend matches that.
- if (Triple.getEnvironment() == llvm::Triple::EABI ||
- Triple.getOS() == llvm::Triple::UnknownOS || isARMMProfile(Triple)) {
+ if (useAAPCSForMachO(Triple)) {
ABIName = "aapcs";
+ } else if (Triple.isWatchOS()) {
+ ABIName = "aapcs16";
} else {
ABIName = "apcs-gnu";
}
@@ -861,50 +986,24 @@ void Clang::AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs,
CmdArgs.push_back(ABIName);
// Determine floating point ABI from the options & target defaults.
- StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
- if (FloatABI == "soft") {
+ arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args);
+ if (ABI == arm::FloatABI::Soft) {
// Floating point operations and argument passing are soft.
- //
// FIXME: This changes CPP defines, we need -target-soft-float.
CmdArgs.push_back("-msoft-float");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
- } else if (FloatABI == "softfp") {
+ } else if (ABI == arm::FloatABI::SoftFP) {
// Floating point operations are hard, but argument passing is soft.
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
} else {
// Floating point operations and argument passing are hard.
- assert(FloatABI == "hard" && "Invalid float abi!");
+ assert(ABI == arm::FloatABI::Hard && "Invalid float abi!");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("hard");
}
- // Kernel code has more strict alignment requirements.
- if (KernelOrKext) {
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-strict-align");
-
- // The kext linker doesn't know how to deal with movw/movt.
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-use-movt=0");
- }
-
- // -mkernel implies -mstrict-align; don't add the redundant option.
- if (!KernelOrKext) {
- if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
- options::OPT_munaligned_access)) {
- CmdArgs.push_back("-backend-option");
- if (A->getOption().matches(options::OPT_mno_unaligned_access))
- CmdArgs.push_back("-arm-strict-align");
- else {
- if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
- D.Diag(diag::err_target_unsupported_unaligned) << "v6m";
- CmdArgs.push_back("-arm-no-strict-align");
- }
- }
- }
-
// Forward the -mglobal-merge option for explicit control over the pass.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
options::OPT_mno_global_merge)) {
@@ -918,14 +1017,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs,
if (!Args.hasFlag(options::OPT_mimplicit_float,
options::OPT_mno_implicit_float, true))
CmdArgs.push_back("-no-implicit-float");
-
- // llvm does not support reserving registers in general. There is support
- // for reserving r9 on ARM though (defined as a platform-specific register
- // in ARM EABI).
- if (Args.hasArg(options::OPT_ffixed_r9)) {
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-reserve-r9");
- }
}
// ARM tools end.
@@ -936,7 +1027,7 @@ static std::string getAArch64TargetCPU(const ArgList &Args) {
std::string CPU;
// If we have -mtune or -mcpu, use that.
if ((A = Args.getLastArg(options::OPT_mtune_EQ))) {
- CPU = A->getValue();
+ CPU = StringRef(A->getValue()).lower();
} else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
StringRef Mcpu = A->getValue();
CPU = Mcpu.split("+").first.lower();
@@ -981,15 +1072,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
- if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
- options::OPT_munaligned_access)) {
- CmdArgs.push_back("-backend-option");
- if (A->getOption().matches(options::OPT_mno_unaligned_access))
- CmdArgs.push_back("-aarch64-strict-align");
- else
- CmdArgs.push_back("-aarch64-no-strict-align");
- }
-
if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
options::OPT_mno_fix_cortex_a53_835769)) {
CmdArgs.push_back("-backend-option");
@@ -997,7 +1079,7 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
else
CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=0");
- } else if (Triple.getEnvironment() == llvm::Triple::Android) {
+ } else if (Triple.isAndroid()) {
// Enabled A53 errata (835769) workaround by default on android
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
@@ -1012,11 +1094,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
else
CmdArgs.push_back("-aarch64-global-merge=true");
}
-
- if (Args.hasArg(options::OPT_ffixed_x18)) {
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-aarch64-reserve-x18");
- }
}
// Get CPU and ABI names. They are not independent
@@ -1034,6 +1111,10 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
DefMips64CPU = "mips64r6";
}
+ // MIPS64r6 is the default for Android MIPS64 (mips64el-linux-android).
+ if (Triple.isAndroid())
+ DefMips64CPU = "mips64r6";
+
// MIPS3 is the default for mips64*-unknown-openbsd.
if (Triple.getOS() == llvm::Triple::OpenBSD)
DefMips64CPU = "mips3";
@@ -1087,6 +1168,16 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
// FIXME: Warn on inconsistent use of -march and -mabi.
}
+std::string mips::getMipsABILibSuffix(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ StringRef CPUName, ABIName;
+ tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+ return llvm::StringSwitch<std::string>(ABIName)
+ .Case("o32", "")
+ .Case("n32", "32")
+ .Case("n64", "64");
+}
+
// Convert ABI name to the GNU tools acceptable variant.
static StringRef getGnuCompatibleMipsABIName(StringRef ABI) {
return llvm::StringSwitch<llvm::StringRef>(ABI)
@@ -1097,33 +1188,37 @@ static StringRef getGnuCompatibleMipsABIName(StringRef ABI) {
// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
// and -mfloat-abi=.
-static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
- StringRef FloatABI;
+static mips::FloatABI getMipsFloatABI(const Driver &D, const ArgList &Args) {
+ mips::FloatABI ABI = mips::FloatABI::Invalid;
if (Arg *A =
Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
options::OPT_mfloat_abi_EQ)) {
if (A->getOption().matches(options::OPT_msoft_float))
- FloatABI = "soft";
+ ABI = mips::FloatABI::Soft;
else if (A->getOption().matches(options::OPT_mhard_float))
- FloatABI = "hard";
+ ABI = mips::FloatABI::Hard;
else {
- FloatABI = A->getValue();
- if (FloatABI != "soft" && FloatABI != "hard") {
+ ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue())
+ .Case("soft", mips::FloatABI::Soft)
+ .Case("hard", mips::FloatABI::Hard)
+ .Default(mips::FloatABI::Invalid);
+ if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
- FloatABI = "hard";
+ ABI = mips::FloatABI::Hard;
}
}
}
// If unspecified, choose the default based on the platform.
- if (FloatABI.empty()) {
+ if (ABI == mips::FloatABI::Invalid) {
// Assume "hard", because it's a default value used by gcc.
// When we start to recognize specific target MIPS processors,
// we will be able to select the default more correctly.
- FloatABI = "hard";
+ ABI = mips::FloatABI::Hard;
}
- return FloatABI;
+ assert(ABI != mips::FloatABI::Invalid && "must select an ABI");
+ return ABI;
}
static void AddTargetFeature(const ArgList &Args,
@@ -1149,8 +1244,8 @@ static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
AddTargetFeature(Args, Features, options::OPT_mno_abicalls,
options::OPT_mabicalls, "noabicalls");
- StringRef FloatABI = getMipsFloatABI(D, Args);
- if (FloatABI == "soft") {
+ mips::FloatABI FloatABI = getMipsFloatABI(D, Args);
+ if (FloatABI == mips::FloatABI::Soft) {
// FIXME: Note, this is a hack. We need to pass the selected float
// mode to the MipsTargetInfoBase to define appropriate macros there.
// Now it is the only method.
@@ -1222,16 +1317,15 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName.data());
- StringRef FloatABI = getMipsFloatABI(D, Args);
-
- if (FloatABI == "soft") {
+ mips::FloatABI ABI = getMipsFloatABI(D, Args);
+ if (ABI == mips::FloatABI::Soft) {
// Floating point operations and argument passing are soft.
CmdArgs.push_back("-msoft-float");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
} else {
// Floating point operations and argument passing are hard.
- assert(FloatABI == "hard" && "Invalid float abi!");
+ assert(ABI == mips::FloatABI::Hard && "Invalid float abi!");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("hard");
}
@@ -1331,33 +1425,54 @@ static std::string getPPCTargetCPU(const ArgList &Args) {
return "";
}
-static void getPPCTargetFeatures(const ArgList &Args,
+static void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args,
std::vector<const char *> &Features) {
- for (const Arg *A : Args.filtered(options::OPT_m_ppc_Features_Group)) {
- StringRef Name = A->getOption().getName();
- A->claim();
+ handleTargetFeaturesGroup(Args, Features, options::OPT_m_ppc_Features_Group);
- // Skip over "-m".
- assert(Name.startswith("m") && "Invalid feature name.");
- Name = Name.substr(1);
+ ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
+ if (FloatABI == ppc::FloatABI::Soft &&
+ !(Triple.getArch() == llvm::Triple::ppc64 ||
+ Triple.getArch() == llvm::Triple::ppc64le))
+ Features.push_back("+soft-float");
+ else if (FloatABI == ppc::FloatABI::Soft &&
+ (Triple.getArch() == llvm::Triple::ppc64 ||
+ Triple.getArch() == llvm::Triple::ppc64le))
+ D.Diag(diag::err_drv_invalid_mfloat_abi)
+ << "soft float is not supported for ppc64";
- bool IsNegative = Name.startswith("no-");
- if (IsNegative)
- Name = Name.substr(3);
+ // Altivec is a bit weird, allow overriding of the Altivec feature here.
+ AddTargetFeature(Args, Features, options::OPT_faltivec,
+ options::OPT_fno_altivec, "altivec");
+}
- // Note that gcc calls this mfcrf and LLVM calls this mfocrf so we
- // pass the correct option to the backend while calling the frontend
- // option the same.
- // TODO: Change the LLVM backend option maybe?
- if (Name == "mfcrf")
- Name = "mfocrf";
+ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {
+ ppc::FloatABI ABI = ppc::FloatABI::Invalid;
+ if (Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ)) {
+ if (A->getOption().matches(options::OPT_msoft_float))
+ ABI = ppc::FloatABI::Soft;
+ else if (A->getOption().matches(options::OPT_mhard_float))
+ ABI = ppc::FloatABI::Hard;
+ else {
+ ABI = llvm::StringSwitch<ppc::FloatABI>(A->getValue())
+ .Case("soft", ppc::FloatABI::Soft)
+ .Case("hard", ppc::FloatABI::Hard)
+ .Default(ppc::FloatABI::Invalid);
+ if (ABI == ppc::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
+ D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
+ ABI = ppc::FloatABI::Hard;
+ }
+ }
+ }
- Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
+ // If unspecified, choose the default based on the platform.
+ if (ABI == ppc::FloatABI::Invalid) {
+ ABI = ppc::FloatABI::Hard;
}
- // Altivec is a bit weird, allow overriding of the Altivec feature here.
- AddTargetFeature(Args, Features, options::OPT_faltivec,
- options::OPT_fno_altivec, "altivec");
+ return ABI;
}
void Clang::AddPPCTargetArgs(const ArgList &Args,
@@ -1396,6 +1511,21 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
if (StringRef(A->getValue()) != "altivec")
ABIName = A->getValue();
+ ppc::FloatABI FloatABI =
+ ppc::getPPCFloatABI(getToolChain().getDriver(), Args);
+
+ if (FloatABI == ppc::FloatABI::Soft) {
+ // Floating point operations and argument passing are soft.
+ CmdArgs.push_back("-msoft-float");
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("soft");
+ } else {
+ // Floating point operations and argument passing are hard.
+ assert(FloatABI == ppc::FloatABI::Hard && "Invalid float abi!");
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("hard");
+ }
+
if (ABIName) {
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
@@ -1533,7 +1663,7 @@ static const char *getX86TargetCPU(const ArgList &Args,
return "btver2";
// On Android use targets compatible with gcc
- if (Triple.getEnvironment() == llvm::Triple::Android)
+ if (Triple.isAndroid())
return Is64Bit ? "x86-64" : "i686";
// Everything else goes to x86-64 in 64-bit mode.
@@ -1555,6 +1685,25 @@ static const char *getX86TargetCPU(const ArgList &Args,
}
}
+/// Get the (LLVM) name of the WebAssembly cpu we are targeting.
+static StringRef getWebAssemblyTargetCPU(const ArgList &Args) {
+ // If we have -mcpu=, use that.
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ StringRef CPU = A->getValue();
+
+#ifdef __wasm__
+ // Handle "native" by examining the host. "native" isn't meaningful when
+ // cross compiling, so only support this when the host is also WebAssembly.
+ if (CPU == "native")
+ return llvm::sys::getHostCPUName();
+#endif
+
+ return CPU;
+ }
+
+ return "generic";
+}
+
static std::string getCPUName(const ArgList &Args, const llvm::Triple &T,
bool FromAs = false) {
switch (T.getArch()) {
@@ -1619,7 +1768,8 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T,
return getX86TargetCPU(Args, T);
case llvm::Triple::hexagon:
- return "hexagon" + toolchains::Hexagon_TC::GetTargetCPU(Args).str();
+ return "hexagon" +
+ toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
case llvm::Triple::systemz:
return getSystemZTargetCPU(Args);
@@ -1627,11 +1777,15 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T,
case llvm::Triple::r600:
case llvm::Triple::amdgcn:
return getR600TargetGPU(Args);
+
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ return getWebAssemblyTargetCPU(Args);
}
}
static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
- ArgStringList &CmdArgs) {
+ ArgStringList &CmdArgs, bool IsThinLTO) {
// Tell the linker to load the plugin. This has to come before AddLinkerInputs
// as gold requires -plugin to come before any -plugin-opt that -Wl might
// forward.
@@ -1647,13 +1801,29 @@ static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
std::string CPU = getCPUName(Args, ToolChain.getTriple());
if (!CPU.empty())
CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
+
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ StringRef OOpt;
+ if (A->getOption().matches(options::OPT_O4) ||
+ A->getOption().matches(options::OPT_Ofast))
+ OOpt = "3";
+ else if (A->getOption().matches(options::OPT_O))
+ OOpt = A->getValue();
+ else if (A->getOption().matches(options::OPT_O0))
+ OOpt = "0";
+ if (!OOpt.empty())
+ CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=O") + OOpt));
+ }
+
+ if (IsThinLTO)
+ CmdArgs.push_back("-plugin-opt=thinlto");
}
/// This is a helper function for validating the optional refinement step
/// parameter in reciprocal argument strings. Return false if there is an error
/// parsing the refinement step. Otherwise, return true and set the Position
/// of the refinement step in the input string.
-static bool getRefinementStep(const StringRef &In, const Driver &D,
+static bool getRefinementStep(StringRef In, const Driver &D,
const Arg &A, size_t &Position) {
const char RefinementStepToken = ':';
Position = In.find(RefinementStepToken);
@@ -1807,7 +1977,7 @@ static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::Triple::ArchType ArchType = Triple.getArch();
// Add features to be compatible with gcc for Android.
- if (Triple.getEnvironment() == llvm::Triple::Android) {
+ if (Triple.isAndroid()) {
if (ArchType == llvm::Triple::x86_64) {
Features.push_back("+sse4.2");
Features.push_back("+popcnt");
@@ -1841,20 +2011,7 @@ static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
- for (const Arg *A : Args.filtered(options::OPT_m_x86_Features_Group)) {
- StringRef Name = A->getOption().getName();
- A->claim();
-
- // Skip over "-m".
- assert(Name.startswith("m") && "Invalid feature name.");
- Name = Name.substr(1);
-
- bool IsNegative = Name.startswith("no-");
- if (IsNegative)
- Name = Name.substr(3);
-
- Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
- }
+ handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group);
}
void Clang::AddX86TargetArgs(const ArgList &Args,
@@ -1895,11 +2052,11 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
CmdArgs.push_back("-mqdsp6-compat");
CmdArgs.push_back("-Wreturn-type");
- if (const char *v = toolchains::Hexagon_TC::GetSmallDataThreshold(Args)) {
- std::string SmallDataThreshold = "-hexagon-small-data-threshold=";
- SmallDataThreshold += v;
+ if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
+ std::string N = llvm::utostr(G.getValue());
+ std::string Opt = std::string("-hexagon-small-data-threshold=") + N;
CmdArgs.push_back("-mllvm");
- CmdArgs.push_back(Args.MakeArgString(SmallDataThreshold));
+ CmdArgs.push_back(Args.MakeArgString(Opt));
}
if (!Args.hasArg(options::OPT_fno_short_enums))
@@ -1912,22 +2069,36 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
CmdArgs.push_back("-machine-sink-split=0");
}
+void Clang::AddWebAssemblyTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Default to "hidden" visibility.
+ if (!Args.hasArg(options::OPT_fvisibility_EQ,
+ options::OPT_fvisibility_ms_compat)) {
+ CmdArgs.push_back("-fvisibility");
+ CmdArgs.push_back("hidden");
+ }
+}
+
// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
static bool DecodeAArch64Features(const Driver &D, StringRef text,
std::vector<const char *> &Features) {
SmallVector<StringRef, 8> Split;
text.split(Split, StringRef("+"), -1, false);
- for (const StringRef Feature : Split) {
+ for (StringRef Feature : Split) {
const char *result = llvm::StringSwitch<const char *>(Feature)
.Case("fp", "+fp-armv8")
.Case("simd", "+neon")
.Case("crc", "+crc")
.Case("crypto", "+crypto")
+ .Case("fp16", "+fullfp16")
+ .Case("profile", "+spe")
.Case("nofp", "-fp-armv8")
.Case("nosimd", "-neon")
.Case("nocrc", "-crc")
.Case("nocrypto", "-crypto")
+ .Case("nofp16", "-fullfp16")
+ .Case("noprofile", "-spe")
.Default(nullptr);
if (result)
Features.push_back(result);
@@ -1946,7 +2117,7 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
std::pair<StringRef, StringRef> Split = Mcpu.split("+");
CPU = Split.first;
if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57" ||
- CPU == "cortex-a72") {
+ CPU == "cortex-a72" || CPU == "cortex-a35" || CPU == "exynos-m1") {
Features.push_back("+neon");
Features.push_back("+crc");
Features.push_back("+crypto");
@@ -1973,6 +2144,8 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
// ok, no additional features.
} else if (Split.first == "armv8.1-a" || Split.first == "armv8.1a") {
Features.push_back("+v8.1a");
+ } else if (Split.first == "armv8.2-a" || Split.first == "armv8.2a" ) {
+ Features.push_back("+v8.2a");
} else {
return false;
}
@@ -1999,10 +2172,11 @@ static bool
getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
const ArgList &Args,
std::vector<const char *> &Features) {
+ std::string MtuneLowerCase = Mtune.lower();
// Handle CPU name is 'native'.
- if (Mtune == "native")
- Mtune = llvm::sys::getHostCPUName();
- if (Mtune == "cyclone") {
+ if (MtuneLowerCase == "native")
+ MtuneLowerCase = llvm::sys::getHostCPUName();
+ if (MtuneLowerCase == "cyclone") {
Features.push_back("+zcm");
Features.push_back("+zcz");
}
@@ -2062,11 +2236,51 @@ static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
else
Features.push_back("-crc");
}
+
+ if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
+ options::OPT_munaligned_access))
+ if (A->getOption().matches(options::OPT_mno_unaligned_access))
+ Features.push_back("+strict-align");
+
+ if (Args.hasArg(options::OPT_ffixed_x18))
+ Features.push_back("+reserve-x18");
+}
+
+static void getHexagonTargetFeatures(const ArgList &Args,
+ std::vector<const char *> &Features) {
+ bool HasHVX = false, HasHVXD = false;
+
+ // FIXME: This should be able to use handleTargetFeaturesGroup except it is
+ // doing dependent option handling here rather than in initFeatureMap or a
+ // similar handler.
+ for (auto &A : Args) {
+ auto &Opt = A->getOption();
+ if (Opt.matches(options::OPT_mhexagon_hvx))
+ HasHVX = true;
+ else if (Opt.matches(options::OPT_mno_hexagon_hvx))
+ HasHVXD = HasHVX = false;
+ else if (Opt.matches(options::OPT_mhexagon_hvx_double))
+ HasHVXD = HasHVX = true;
+ else if (Opt.matches(options::OPT_mno_hexagon_hvx_double))
+ HasHVXD = false;
+ else
+ continue;
+ A->claim();
+ }
+
+ Features.push_back(HasHVX ? "+hvx" : "-hvx");
+ Features.push_back(HasHVXD ? "+hvx-double" : "-hvx-double");
}
-static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+static void getWebAssemblyTargetFeatures(const ArgList &Args,
+ std::vector<const char *> &Features) {
+ handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group);
+}
+
+static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
const ArgList &Args, ArgStringList &CmdArgs,
bool ForAS) {
+ const Driver &D = TC.getDriver();
std::vector<const char *> Features;
switch (Triple.getArch()) {
default:
@@ -2082,13 +2296,13 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
- getARMTargetFeatures(D, Triple, Args, Features, ForAS);
+ getARMTargetFeatures(TC, Triple, Args, Features, ForAS);
break;
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
- getPPCTargetFeatures(Args, Features);
+ getPPCTargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::systemz:
getSystemZTargetFeatures(Args, Features);
@@ -2101,6 +2315,13 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::x86_64:
getX86TargetFeatures(D, Triple, Args, Features);
break;
+ case llvm::Triple::hexagon:
+ getHexagonTargetFeatures(Args, Features);
+ break;
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ getWebAssemblyTargetFeatures(Args, Features);
+ break;
}
// Find the last of each feature.
@@ -2272,6 +2493,67 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
RelaxDefault);
}
+// Convert an arg of the form "-gN" or "-ggdbN" or one of their aliases
+// to the corresponding DebugInfoKind.
+static CodeGenOptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) {
+ assert(A.getOption().matches(options::OPT_gN_Group) &&
+ "Not a -g option that specifies a debug-info level");
+ if (A.getOption().matches(options::OPT_g0) ||
+ A.getOption().matches(options::OPT_ggdb0))
+ return CodeGenOptions::NoDebugInfo;
+ if (A.getOption().matches(options::OPT_gline_tables_only) ||
+ A.getOption().matches(options::OPT_ggdb1))
+ return CodeGenOptions::DebugLineTablesOnly;
+ return CodeGenOptions::LimitedDebugInfo;
+}
+
+// Extract the integer N from a string spelled "-dwarf-N", returning 0
+// on mismatch. The StringRef input (rather than an Arg) allows
+// for use by the "-Xassembler" option parser.
+static unsigned DwarfVersionNum(StringRef ArgValue) {
+ return llvm::StringSwitch<unsigned>(ArgValue)
+ .Case("-gdwarf-2", 2)
+ .Case("-gdwarf-3", 3)
+ .Case("-gdwarf-4", 4)
+ .Case("-gdwarf-5", 5)
+ .Default(0);
+}
+
+static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
+ CodeGenOptions::DebugInfoKind DebugInfoKind,
+ unsigned DwarfVersion,
+ llvm::DebuggerKind DebuggerTuning) {
+ switch (DebugInfoKind) {
+ case CodeGenOptions::DebugLineTablesOnly:
+ CmdArgs.push_back("-debug-info-kind=line-tables-only");
+ break;
+ case CodeGenOptions::LimitedDebugInfo:
+ CmdArgs.push_back("-debug-info-kind=limited");
+ break;
+ case CodeGenOptions::FullDebugInfo:
+ CmdArgs.push_back("-debug-info-kind=standalone");
+ break;
+ default:
+ break;
+ }
+ if (DwarfVersion > 0)
+ CmdArgs.push_back(
+ Args.MakeArgString("-dwarf-version=" + Twine(DwarfVersion)));
+ switch (DebuggerTuning) {
+ case llvm::DebuggerKind::GDB:
+ CmdArgs.push_back("-debugger-tuning=gdb");
+ break;
+ case llvm::DebuggerKind::LLDB:
+ CmdArgs.push_back("-debugger-tuning=lldb");
+ break;
+ case llvm::DebuggerKind::SCE:
+ CmdArgs.push_back("-debugger-tuning=sce");
+ break;
+ default:
+ break;
+ }
+}
+
static void CollectArgsForIntegratedAssembler(Compilation &C,
const ArgList &Args,
ArgStringList &CmdArgs,
@@ -2279,6 +2561,15 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
if (UseRelaxAll(C, Args))
CmdArgs.push_back("-mrelax-all");
+ // Only default to -mincremental-linker-compatible if we think we are
+ // targeting the MSVC linker.
+ bool DefaultIncrementalLinkerCompatible =
+ C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
+ if (Args.hasFlag(options::OPT_mincremental_linker_compatible,
+ options::OPT_mno_incremental_linker_compatible,
+ DefaultIncrementalLinkerCompatible))
+ CmdArgs.push_back("-mincremental-linker-compatible");
+
// When passing -I arguments to the assembler we sometimes need to
// unconditionally take the next argument. For example, when parsing
// '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the
@@ -2293,13 +2584,43 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
A->claim();
- for (const StringRef Value : A->getValues()) {
+ for (StringRef Value : A->getValues()) {
if (TakeNextArg) {
CmdArgs.push_back(Value.data());
TakeNextArg = false;
continue;
}
+ switch (C.getDefaultToolChain().getArch()) {
+ default:
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ if (Value == "--trap") {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("+use-tcc-in-div");
+ continue;
+ }
+ if (Value == "--break") {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("-use-tcc-in-div");
+ continue;
+ }
+ if (Value.startswith("-msoft-float")) {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("+soft-float");
+ continue;
+ }
+ if (Value.startswith("-mhard-float")) {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("-soft-float");
+ continue;
+ }
+ break;
+ }
+
if (Value == "-force_cpusubtype_ALL") {
// Do nothing, this is the default and we don't support anything else.
} else if (Value == "-L") {
@@ -2321,7 +2642,15 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
if (Value == "-I")
TakeNextArg = true;
} else if (Value.startswith("-gdwarf-")) {
- CmdArgs.push_back(Value.data());
+ // "-gdwarf-N" options are not cc1as options.
+ unsigned DwarfVersion = DwarfVersionNum(Value);
+ if (DwarfVersion == 0) { // Send it onward, and let cc1as complain.
+ CmdArgs.push_back(Value.data());
+ } else {
+ RenderDebugEnablingArgs(
+ Args, CmdArgs, CodeGenOptions::LimitedDebugInfo, DwarfVersion,
+ llvm::DebuggerKind::Default);
+ }
} else if (Value.startswith("-mcpu") || Value.startswith("-mfpu") ||
Value.startswith("-mhwdiv") || Value.startswith("-march")) {
// Do nothing, we'll validate it later.
@@ -2339,76 +2668,12 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
}
}
-// Until ARM libraries are build separately, we have them all in one library
-static StringRef getArchNameForCompilerRTLib(const ToolChain &TC) {
- if (TC.getTriple().isWindowsMSVCEnvironment() &&
- TC.getArch() == llvm::Triple::x86)
- return "i386";
- if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
- return "arm";
- return TC.getArchName();
-}
-
-static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) {
- // The runtimes are located in the OS-specific resource directory.
- SmallString<128> Res(TC.getDriver().ResourceDir);
- const llvm::Triple &Triple = TC.getTriple();
- // TC.getOS() yield "freebsd10.0" whereas "freebsd" is expected.
- StringRef OSLibName =
- (Triple.getOS() == llvm::Triple::FreeBSD) ? "freebsd" : TC.getOS();
- llvm::sys::path::append(Res, "lib", OSLibName);
- return Res;
-}
-
-SmallString<128> tools::getCompilerRT(const ToolChain &TC, StringRef Component,
- bool Shared) {
- const char *Env = TC.getTriple().getEnvironment() == llvm::Triple::Android
- ? "-android"
- : "";
-
- bool IsOSWindows = TC.getTriple().isOSWindows();
- bool IsITANMSVCWindows = TC.getTriple().isWindowsMSVCEnvironment() ||
- TC.getTriple().isWindowsItaniumEnvironment();
- StringRef Arch = getArchNameForCompilerRTLib(TC);
- const char *Prefix = IsITANMSVCWindows ? "" : "lib";
- const char *Suffix =
- Shared ? (IsOSWindows ? ".dll" : ".so") : (IsITANMSVCWindows ? ".lib" : ".a");
-
- SmallString<128> Path = getCompilerRTLibDir(TC);
- llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" +
- Arch + Env + Suffix);
-
- return Path;
-}
-
// This adds the static libclang_rt.builtins-arch.a directly to the command line
// FIXME: Make sure we can also emit shared objects if they're requested
// and available, check for possible errors, etc.
static void addClangRT(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
- CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "builtins")));
-
- if (!TC.getTriple().isOSWindows()) {
- // FIXME: why do we link against gcc when we are using compiler-rt?
- CmdArgs.push_back("-lgcc_s");
- if (TC.getDriver().CCCIsCXX())
- CmdArgs.push_back("-lgcc_eh");
- }
-}
-
-static void addProfileRT(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
- if (!(Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
- false) ||
- Args.hasArg(options::OPT_fprofile_generate) ||
- Args.hasArg(options::OPT_fprofile_generate_EQ) ||
- Args.hasArg(options::OPT_fprofile_instr_generate) ||
- Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
- Args.hasArg(options::OPT_fcreate_profile) ||
- Args.hasArg(options::OPT_coverage)))
- return;
-
- CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "profile")));
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins"));
}
namespace {
@@ -2487,11 +2752,9 @@ static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
bool IsShared) {
// Static runtimes must be forced into executable, so we wrap them in
// whole-archive.
- if (!IsShared)
- CmdArgs.push_back("-whole-archive");
- CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Sanitizer, IsShared)));
- if (!IsShared)
- CmdArgs.push_back("-no-whole-archive");
+ if (!IsShared) CmdArgs.push_back("-whole-archive");
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, Sanitizer, IsShared));
+ if (!IsShared) CmdArgs.push_back("-no-whole-archive");
}
// Tries to use a file with the list of dynamic symbols that need to be exported
@@ -2499,7 +2762,7 @@ static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs,
StringRef Sanitizer) {
- SmallString<128> SanRT = getCompilerRT(TC, Sanitizer);
+ SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer));
if (llvm::sys::fs::exists(SanRT + ".syms")) {
CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms"));
return true;
@@ -2532,8 +2795,7 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
}
// Collect static runtimes.
- if (Args.hasArg(options::OPT_shared) ||
- (TC.getTriple().getEnvironment() == llvm::Triple::Android)) {
+ if (Args.hasArg(options::OPT_shared) || TC.getTriple().isAndroid()) {
// Don't link static runtimes into DSOs or if compiling for Android.
return;
}
@@ -2567,6 +2829,10 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
}
if (SanArgs.needsSafeStackRt())
StaticRuntimes.push_back("safestack");
+ if (SanArgs.needsCfiRt())
+ StaticRuntimes.push_back("cfi");
+ if (SanArgs.needsCfiDiagRt())
+ StaticRuntimes.push_back("cfi_diag");
}
// Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
@@ -2603,9 +2869,15 @@ static bool areOptimizationsEnabled(const ArgList &Args) {
static bool shouldUseFramePointerForTarget(const ArgList &Args,
const llvm::Triple &Triple) {
- // XCore never wants frame pointers, regardless of OS.
- if (Triple.getArch() == llvm::Triple::xcore) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::xcore:
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ // XCore never wants frame pointers, regardless of OS.
+ // WebAssembly never wants frame pointers.
return false;
+ default:
+ break;
}
if (Triple.isOSLinux()) {
@@ -2628,6 +2900,10 @@ static bool shouldUseFramePointerForTarget(const ArgList &Args,
switch (Triple.getArch()) {
case llvm::Triple::x86:
return !areOptimizationsEnabled(Args);
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ // Windows on ARM builds with FPO disabled to aid fast stack walking
+ return true;
default:
// All other supported Windows ISAs use xdata unwind information, so frame
// pointers are not generally useful.
@@ -2643,6 +2919,8 @@ static bool shouldUseFramePointer(const ArgList &Args,
if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer,
options::OPT_fomit_frame_pointer))
return A->getOption().matches(options::OPT_fno_omit_frame_pointer);
+ if (Args.hasArg(options::OPT_pg))
+ return true;
return shouldUseFramePointerForTarget(Args, Triple);
}
@@ -2652,6 +2930,8 @@ static bool shouldUseLeafFramePointer(const ArgList &Args,
if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer,
options::OPT_momit_leaf_frame_pointer))
return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);
+ if (Args.hasArg(options::OPT_pg))
+ return true;
if (Triple.isPS4CPU())
return false;
@@ -2700,12 +2980,13 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
ExtractArgs.push_back(OutFile);
const char *Exec = Args.MakeArgString(TC.GetProgramPath("objcopy"));
+ InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename());
// First extract the dwo sections.
- C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs, II));
// Then remove them from the original .o file.
- C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs, II));
}
/// \brief Vectorize at all optimization levels greater than 1 except for -Oz.
@@ -2774,6 +3055,7 @@ static VersionTuple getMSCompatibilityVersion(unsigned Version) {
static void claimNoWarnArgs(const ArgList &Args) {
// Don't warn about unused -f(no-)?lto. This can happen when we're
// preprocessing, precompiling or assembling.
+ Args.ClaimAllArgs(options::OPT_flto_EQ);
Args.ClaimAllArgs(options::OPT_flto);
Args.ClaimAllArgs(options::OPT_fno_lto);
}
@@ -2863,42 +3145,53 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
auto *ProfileGenerateArg = Args.getLastArg(
options::OPT_fprofile_instr_generate,
options::OPT_fprofile_instr_generate_EQ, options::OPT_fprofile_generate,
- options::OPT_fprofile_generate_EQ);
+ options::OPT_fprofile_generate_EQ,
+ options::OPT_fno_profile_instr_generate);
+ if (ProfileGenerateArg &&
+ ProfileGenerateArg->getOption().matches(
+ options::OPT_fno_profile_instr_generate))
+ ProfileGenerateArg = nullptr;
auto *ProfileUseArg = Args.getLastArg(
options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ,
- options::OPT_fprofile_use, options::OPT_fprofile_use_EQ);
+ options::OPT_fprofile_use, options::OPT_fprofile_use_EQ,
+ options::OPT_fno_profile_instr_use);
+ if (ProfileUseArg &&
+ ProfileUseArg->getOption().matches(options::OPT_fno_profile_instr_use))
+ ProfileUseArg = nullptr;
if (ProfileGenerateArg && ProfileUseArg)
D.Diag(diag::err_drv_argument_not_allowed_with)
<< ProfileGenerateArg->getSpelling() << ProfileUseArg->getSpelling();
- if (ProfileGenerateArg &&
- ProfileGenerateArg->getOption().matches(
- options::OPT_fprofile_instr_generate_EQ))
- ProfileGenerateArg->render(Args, CmdArgs);
- else if (ProfileGenerateArg &&
- ProfileGenerateArg->getOption().matches(
- options::OPT_fprofile_generate_EQ)) {
- SmallString<128> Path(ProfileGenerateArg->getValue());
- llvm::sys::path::append(Path, "default.profraw");
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-fprofile-instr-generate=") + Path));
- } else
- Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate);
-
- if (ProfileUseArg &&
- ProfileUseArg->getOption().matches(options::OPT_fprofile_instr_use_EQ))
- ProfileUseArg->render(Args, CmdArgs);
- else if (ProfileUseArg &&
- (ProfileUseArg->getOption().matches(options::OPT_fprofile_use_EQ) ||
- ProfileUseArg->getOption().matches(
- options::OPT_fprofile_instr_use))) {
- SmallString<128> Path(
- ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
- if (Path.empty() || llvm::sys::fs::is_directory(Path))
- llvm::sys::path::append(Path, "default.profdata");
- CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-instr-use=") + Path));
+ if (ProfileGenerateArg) {
+ if (ProfileGenerateArg->getOption().matches(
+ options::OPT_fprofile_instr_generate_EQ))
+ ProfileGenerateArg->render(Args, CmdArgs);
+ else if (ProfileGenerateArg->getOption().matches(
+ options::OPT_fprofile_generate_EQ)) {
+ SmallString<128> Path(ProfileGenerateArg->getValue());
+ llvm::sys::path::append(Path, "default.profraw");
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-fprofile-instr-generate=") + Path));
+ } else
+ Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate);
+ }
+
+ if (ProfileUseArg) {
+ if (ProfileUseArg->getOption().matches(options::OPT_fprofile_instr_use_EQ))
+ ProfileUseArg->render(Args, CmdArgs);
+ else if ((ProfileUseArg->getOption().matches(
+ options::OPT_fprofile_use_EQ) ||
+ ProfileUseArg->getOption().matches(
+ options::OPT_fprofile_instr_use))) {
+ SmallString<128> Path(
+ ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
+ if (Path.empty() || llvm::sys::fs::is_directory(Path))
+ llvm::sys::path::append(Path, "default.profdata");
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-fprofile-instr-use=") + Path));
+ }
}
if (Args.hasArg(options::OPT_ftest_coverage) ||
@@ -2909,12 +3202,15 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
Args.hasArg(options::OPT_coverage))
CmdArgs.push_back("-femit-coverage-data");
- if (Args.hasArg(options::OPT_fcoverage_mapping) && !ProfileGenerateArg)
+ if (Args.hasFlag(options::OPT_fcoverage_mapping,
+ options::OPT_fno_coverage_mapping, false) &&
+ !ProfileGenerateArg)
D.Diag(diag::err_drv_argument_only_allowed_with)
<< "-fcoverage-mapping"
<< "-fprofile-instr-generate";
- if (Args.hasArg(options::OPT_fcoverage_mapping))
+ if (Args.hasFlag(options::OPT_fcoverage_mapping,
+ options::OPT_fno_coverage_mapping, false))
CmdArgs.push_back("-fcoverage-mapping");
if (C.getArgs().hasArg(options::OPT_c) ||
@@ -2939,9 +3235,193 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
}
}
+static void addPS4ProfileRTArgs(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
+ false) ||
+ Args.hasFlag(options::OPT_fprofile_generate,
+ options::OPT_fno_profile_instr_generate, false) ||
+ Args.hasFlag(options::OPT_fprofile_generate_EQ,
+ options::OPT_fno_profile_instr_generate, false) ||
+ Args.hasFlag(options::OPT_fprofile_instr_generate,
+ options::OPT_fno_profile_instr_generate, false) ||
+ Args.hasFlag(options::OPT_fprofile_instr_generate_EQ,
+ options::OPT_fno_profile_instr_generate, false) ||
+ Args.hasArg(options::OPT_fcreate_profile) ||
+ Args.hasArg(options::OPT_coverage)))
+ CmdArgs.push_back("--dependent-lib=libclang_rt.profile-x86_64.a");
+}
+
+/// Parses the various -fpic/-fPIC/-fpie/-fPIE arguments. Then,
+/// smooshes them together with platform defaults, to decide whether
+/// this compile should be using PIC mode or not. Returns a tuple of
+/// (RelocationModel, PICLevel, IsPIE).
+static std::tuple<llvm::Reloc::Model, unsigned, bool>
+ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
+ const ArgList &Args) {
+ // FIXME: why does this code...and so much everywhere else, use both
+ // ToolChain.getTriple() and Triple?
+ bool PIE = ToolChain.isPIEDefault();
+ bool PIC = PIE || ToolChain.isPICDefault();
+ // The Darwin/MachO default to use PIC does not apply when using -static.
+ if (ToolChain.getTriple().isOSBinFormatMachO() &&
+ Args.hasArg(options::OPT_static))
+ PIE = PIC = false;
+ bool IsPICLevelTwo = PIC;
+
+ bool KernelOrKext =
+ Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
+
+ // Android-specific defaults for PIC/PIE
+ if (ToolChain.getTriple().isAndroid()) {
+ switch (ToolChain.getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ PIC = true; // "-fpic"
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ PIC = true; // "-fPIC"
+ IsPICLevelTwo = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // OpenBSD-specific defaults for PIE
+ if (ToolChain.getTriple().getOS() == llvm::Triple::OpenBSD) {
+ switch (ToolChain.getArch()) {
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ IsPICLevelTwo = false; // "-fpie"
+ break;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcv9:
+ IsPICLevelTwo = true; // "-fPIE"
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // The last argument relating to either PIC or PIE wins, and no
+ // other argument is used. If the last argument is any flavor of the
+ // '-fno-...' arguments, both PIC and PIE are disabled. Any PIE
+ // option implicitly enables PIC at the same level.
+ Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
+ options::OPT_fpic, options::OPT_fno_pic,
+ options::OPT_fPIE, options::OPT_fno_PIE,
+ options::OPT_fpie, options::OPT_fno_pie);
+ // Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
+ // is forced, then neither PIC nor PIE flags will have no effect.
+ if (!ToolChain.isPICDefaultForced()) {
+ if (LastPICArg) {
+ Option O = LastPICArg->getOption();
+ if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
+ O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
+ PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
+ PIC =
+ PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic);
+ IsPICLevelTwo =
+ O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC);
+ } else {
+ PIE = PIC = false;
+ if (Triple.isPS4CPU()) {
+ Arg *ModelArg = Args.getLastArg(options::OPT_mcmodel_EQ);
+ StringRef Model = ModelArg ? ModelArg->getValue() : "";
+ if (Model != "kernel") {
+ PIC = true;
+ ToolChain.getDriver().Diag(diag::warn_drv_ps4_force_pic)
+ << LastPICArg->getSpelling();
+ }
+ }
+ }
+ }
+ }
+
+ // Introduce a Darwin and PS4-specific hack. If the default is PIC, but the
+ // PIC level would've been set to level 1, force it back to level 2 PIC
+ // instead.
+ if (PIC && (ToolChain.getTriple().isOSDarwin() || Triple.isPS4CPU()))
+ IsPICLevelTwo |= ToolChain.isPICDefault();
+
+ // This kernel flags are a trump-card: they will disable PIC/PIE
+ // generation, independent of the argument order.
+ if (KernelOrKext && ((!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
+ !Triple.isWatchOS()))
+ PIC = PIE = false;
+
+ if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
+ // This is a very special mode. It trumps the other modes, almost no one
+ // uses it, and it isn't even valid on any OS but Darwin.
+ if (!ToolChain.getTriple().isOSDarwin())
+ ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << ToolChain.getTriple().str();
+
+ // FIXME: Warn when this flag trumps some other PIC or PIE flag.
+
+ // Only a forced PIC mode can cause the actual compile to have PIC defines
+ // etc., no flags are sufficient. This behavior was selected to closely
+ // match that of llvm-gcc and Apple GCC before that.
+ PIC = ToolChain.isPICDefault() && ToolChain.isPICDefaultForced();
+
+ return std::make_tuple(llvm::Reloc::DynamicNoPIC, PIC ? 2 : 0, false);
+ }
+
+ if (PIC)
+ return std::make_tuple(llvm::Reloc::PIC_, IsPICLevelTwo ? 2 : 1, PIE);
+
+ return std::make_tuple(llvm::Reloc::Static, 0, false);
+}
+
+static const char *RelocationModelName(llvm::Reloc::Model Model) {
+ switch (Model) {
+ case llvm::Reloc::Default:
+ return nullptr;
+ case llvm::Reloc::Static:
+ return "static";
+ case llvm::Reloc::PIC_:
+ return "pic";
+ case llvm::Reloc::DynamicNoPIC:
+ return "dynamic-no-pic";
+ }
+ llvm_unreachable("Unknown Reloc::Model kind");
+}
+
+static void AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ llvm::Reloc::Model RelocationModel;
+ unsigned PICLevel;
+ bool IsPIE;
+ std::tie(RelocationModel, PICLevel, IsPIE) =
+ ParsePICArgs(ToolChain, ToolChain.getTriple(), Args);
+
+ if (RelocationModel != llvm::Reloc::Static)
+ CmdArgs.push_back("-KPIC");
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const char *LinkingOutput) const {
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
+ const llvm::Triple Triple(TripleStr);
+
bool KernelOrKext =
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
const Driver &D = getToolChain().getDriver();
@@ -2951,6 +3431,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool IsWindowsCygnus =
getToolChain().getTriple().isWindowsCygwinEnvironment();
bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();
+ bool IsPS4CPU = getToolChain().getTriple().isPS4CPU();
// Check number of inputs for sanity. We need at least one input.
assert(Inputs.size() >= 1 && "Must have at least one input.");
@@ -2968,17 +3449,34 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Add the "effective" target triple.
CmdArgs.push_back("-triple");
- std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
CmdArgs.push_back(Args.MakeArgString(TripleStr));
- const llvm::Triple TT(TripleStr);
- if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
- TT.getArch() == llvm::Triple::thumb)) {
- unsigned Offset = TT.getArch() == llvm::Triple::arm ? 4 : 6;
+ const ToolChain *AuxToolChain = nullptr;
+ if (IsCuda) {
+ // FIXME: We need a (better) way to pass information about
+ // particular compilation pass we're constructing here. For now we
+ // can check which toolchain we're using and pick the other one to
+ // extract the triple.
+ if (&getToolChain() == C.getCudaDeviceToolChain())
+ AuxToolChain = C.getCudaHostToolChain();
+ else if (&getToolChain() == C.getCudaHostToolChain())
+ AuxToolChain = C.getCudaDeviceToolChain();
+ else
+ llvm_unreachable("Can't figure out CUDA compilation mode.");
+ assert(AuxToolChain != nullptr && "No aux toolchain.");
+ CmdArgs.push_back("-aux-triple");
+ CmdArgs.push_back(Args.MakeArgString(AuxToolChain->getTriple().str()));
+ CmdArgs.push_back("-fcuda-target-overloads");
+ CmdArgs.push_back("-fcuda-disable-target-call-checks");
+ }
+
+ if (Triple.isOSWindows() && (Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb)) {
+ unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
unsigned Version;
- TT.getArchName().substr(Offset).getAsInteger(10, Version);
+ Triple.getArchName().substr(Offset).getAsInteger(10, Version);
if (Version < 7)
- D.Diag(diag::err_target_unsupported_arch) << TT.getArchName()
+ D.Diag(diag::err_target_unsupported_arch) << Triple.getArchName()
<< TripleStr;
}
@@ -3026,10 +3524,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
} else {
assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
"Invalid action for clang tool.");
-
- if (JA.getType() == types::TY_LTO_IR || JA.getType() == types::TY_LTO_BC) {
- CmdArgs.push_back("-flto");
- }
if (JA.getType() == types::TY_Nothing) {
CmdArgs.push_back("-fsyntax-only");
} else if (JA.getType() == types::TY_LLVM_IR ||
@@ -3060,6 +3554,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// the use-list order, since serialization to bitcode is part of the flow.
if (JA.getType() == types::TY_LLVM_BC)
CmdArgs.push_back("-emit-llvm-uselists");
+
+ if (D.isUsingLTO())
+ Args.AddLastArg(CmdArgs, options::OPT_flto, options::OPT_flto_EQ);
+ }
+
+ if (const Arg *A = Args.getLastArg(options::OPT_fthinlto_index_EQ)) {
+ if (!types::isLLVMIR(Input.getType()))
+ D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
+ << "-x ir";
+ Args.AddLastArg(CmdArgs, options::OPT_fthinlto_index_EQ);
}
// We normally speed up the clang process a bit by skipping destructors at
@@ -3099,6 +3603,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!IsWindowsMSVC)
CmdArgs.push_back("-analyzer-checker=unix");
+ // Disable some unix checkers for PS4.
+ if (IsPS4CPU) {
+ CmdArgs.push_back("-analyzer-disable-checker=unix.API");
+ CmdArgs.push_back("-analyzer-disable-checker=unix.Vfork");
+ }
+
if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple)
CmdArgs.push_back("-analyzer-checker=osx");
@@ -3107,14 +3617,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (types::isCXX(Input.getType()))
CmdArgs.push_back("-analyzer-checker=cplusplus");
- // Enable the following experimental checkers for testing.
+ if (!IsPS4CPU) {
+ CmdArgs.push_back(
+ "-analyzer-checker=security.insecureAPI.UncheckedReturn");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
+ }
+
+ // Default nullability checks.
+ CmdArgs.push_back("-analyzer-checker=nullability.NullPassedToNonnull");
CmdArgs.push_back(
- "-analyzer-checker=security.insecureAPI.UncheckedReturn");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
+ "-analyzer-checker=nullability.NullReturnedFromNonnull");
}
// Set the output format. The default is plist, for (lame) historical
@@ -3136,136 +3652,29 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CheckCodeGenerationOptions(D, Args);
- bool PIE = getToolChain().isPIEDefault();
- bool PIC = PIE || getToolChain().isPICDefault();
- bool IsPICLevelTwo = PIC;
-
- // Android-specific defaults for PIC/PIE
- if (getToolChain().getTriple().getEnvironment() == llvm::Triple::Android) {
- switch (getToolChain().getArch()) {
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- case llvm::Triple::aarch64:
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- PIC = true; // "-fpic"
- break;
-
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- PIC = true; // "-fPIC"
- IsPICLevelTwo = true;
- break;
+ llvm::Reloc::Model RelocationModel;
+ unsigned PICLevel;
+ bool IsPIE;
+ std::tie(RelocationModel, PICLevel, IsPIE) =
+ ParsePICArgs(getToolChain(), Triple, Args);
- default:
- break;
- }
+ const char *RMName = RelocationModelName(RelocationModel);
+ if (RMName) {
+ CmdArgs.push_back("-mrelocation-model");
+ CmdArgs.push_back(RMName);
}
-
- // OpenBSD-specific defaults for PIE
- if (getToolChain().getTriple().getOS() == llvm::Triple::OpenBSD) {
- switch (getToolChain().getArch()) {
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::sparcel:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- IsPICLevelTwo = false; // "-fpie"
- break;
-
- case llvm::Triple::ppc:
- case llvm::Triple::sparc:
- case llvm::Triple::sparcv9:
- IsPICLevelTwo = true; // "-fPIE"
- break;
-
- default:
- break;
+ if (PICLevel > 0) {
+ CmdArgs.push_back("-pic-level");
+ CmdArgs.push_back(PICLevel == 1 ? "1" : "2");
+ if (IsPIE) {
+ CmdArgs.push_back("-pie-level");
+ CmdArgs.push_back(PICLevel == 1 ? "1" : "2");
}
}
- // For the PIC and PIE flag options, this logic is different from the
- // legacy logic in very old versions of GCC, as that logic was just
- // a bug no one had ever fixed. This logic is both more rational and
- // consistent with GCC's new logic now that the bugs are fixed. The last
- // argument relating to either PIC or PIE wins, and no other argument is
- // used. If the last argument is any flavor of the '-fno-...' arguments,
- // both PIC and PIE are disabled. Any PIE option implicitly enables PIC
- // at the same level.
- Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
- options::OPT_fpic, options::OPT_fno_pic,
- options::OPT_fPIE, options::OPT_fno_PIE,
- options::OPT_fpie, options::OPT_fno_pie);
- // Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
- // is forced, then neither PIC nor PIE flags will have no effect.
- if (!getToolChain().isPICDefaultForced()) {
- if (LastPICArg) {
- Option O = LastPICArg->getOption();
- if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
- O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
- PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
- PIC =
- PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic);
- IsPICLevelTwo =
- O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC);
- } else {
- PIE = PIC = false;
- }
- }
- }
-
- // Introduce a Darwin-specific hack. If the default is PIC but the flags
- // specified while enabling PIC enabled level 1 PIC, just force it back to
- // level 2 PIC instead. This matches the behavior of Darwin GCC (based on my
- // informal testing).
- if (PIC && getToolChain().getTriple().isOSDarwin())
- IsPICLevelTwo |= getToolChain().isPICDefault();
-
- // Note that these flags are trump-cards. Regardless of the order w.r.t. the
- // PIC or PIE options above, if these show up, PIC is disabled.
- llvm::Triple Triple(TripleStr);
- if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)))
- PIC = PIE = false;
- if (Args.hasArg(options::OPT_static))
- PIC = PIE = false;
-
- if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
- // This is a very special mode. It trumps the other modes, almost no one
- // uses it, and it isn't even valid on any OS but Darwin.
- if (!getToolChain().getTriple().isOSDarwin())
- D.Diag(diag::err_drv_unsupported_opt_for_target)
- << A->getSpelling() << getToolChain().getTriple().str();
-
- // FIXME: Warn when this flag trumps some other PIC or PIE flag.
-
- CmdArgs.push_back("-mrelocation-model");
- CmdArgs.push_back("dynamic-no-pic");
-
- // Only a forced PIC mode can cause the actual compile to have PIC defines
- // etc., no flags are sufficient. This behavior was selected to closely
- // match that of llvm-gcc and Apple GCC before that.
- if (getToolChain().isPICDefault() && getToolChain().isPICDefaultForced()) {
- CmdArgs.push_back("-pic-level");
- CmdArgs.push_back("2");
- }
- } else {
- // Currently, LLVM only knows about PIC vs. static; the PIE differences are
- // handled in Clang's IRGen by the -pie-level flag.
- CmdArgs.push_back("-mrelocation-model");
- CmdArgs.push_back(PIC ? "pic" : "static");
-
- if (PIC) {
- CmdArgs.push_back("-pic-level");
- CmdArgs.push_back(IsPICLevelTwo ? "2" : "1");
- if (PIE) {
- CmdArgs.push_back("-pie-level");
- CmdArgs.push_back(IsPICLevelTwo ? "2" : "1");
- }
- }
+ if (Arg *A = Args.getLastArg(options::OPT_meabi)) {
+ CmdArgs.push_back("-meabi");
+ CmdArgs.push_back(A->getValue());
}
CmdArgs.push_back("-mthread-model");
@@ -3343,6 +3752,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
false))
CmdArgs.push_back("-fstrict-enums");
+ if (Args.hasFlag(options::OPT_fstrict_vtable_pointers,
+ options::OPT_fno_strict_vtable_pointers,
+ false))
+ CmdArgs.push_back("-fstrict-vtable-pointers");
if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
options::OPT_fno_optimize_sibling_calls))
CmdArgs.push_back("-mdisable-tail-calls");
@@ -3520,7 +3933,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (KernelOrKext && getToolChain().getTriple().isOSDarwin())
CmdArgs.push_back("-fforbid-guard-variables");
- if (Args.hasArg(options::OPT_mms_bitfields)) {
+ if (Args.hasFlag(options::OPT_mms_bitfields, options::OPT_mno_ms_bitfields,
+ false)) {
CmdArgs.push_back("-mms-bitfields");
}
@@ -3565,7 +3979,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Add the target features
- getTargetFeatures(D, Triple, Args, CmdArgs, false);
+ getTargetFeatures(getToolChain(), Triple, Args, CmdArgs, false);
// Add target specific flags.
switch (getToolChain().getArch()) {
@@ -3576,7 +3990,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
- AddARMTargetArgs(Args, CmdArgs, KernelOrKext);
+ // Use the effective triple, which takes into account the deployment target.
+ AddARMTargetArgs(Triple, Args, CmdArgs, KernelOrKext);
break;
case llvm::Triple::aarch64:
@@ -3611,11 +4026,32 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::hexagon:
AddHexagonTargetArgs(Args, CmdArgs);
break;
+
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ AddWebAssemblyTargetArgs(Args, CmdArgs);
+ break;
}
+ // The 'g' groups options involve a somewhat intricate sequence of decisions
+ // about what to pass from the driver to the frontend, but by the time they
+ // reach cc1 they've been factored into three well-defined orthogonal choices:
+ // * what level of debug info to generate
+ // * what dwarf version to write
+ // * what debugger tuning to use
+ // This avoids having to monkey around further in cc1 other than to disable
+ // codeview if not running in a Windows environment. Perhaps even that
+ // decision should be made in the driver as well though.
+ unsigned DwarfVersion = 0;
+ llvm::DebuggerKind DebuggerTuning = getToolChain().getDefaultDebuggerTuning();
+ // These two are potentially updated by AddClangCLArgs.
+ enum CodeGenOptions::DebugInfoKind DebugInfoKind =
+ CodeGenOptions::NoDebugInfo;
+ bool EmitCodeView = false;
+
// Add clang-cl arguments.
if (getToolChain().getDriver().IsCLMode())
- AddClangCLArgs(Args, CmdArgs);
+ AddClangCLArgs(Args, CmdArgs, &DebugInfoKind, &EmitCodeView);
// Pass the linker version in use.
if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
@@ -3656,57 +4092,86 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
: "-");
}
- // Use the last option from "-g" group. "-gline-tables-only" and "-gdwarf-x"
- // are preserved, all other debug options are substituted with "-g".
Args.ClaimAllArgs(options::OPT_g_Group);
+ Arg *SplitDwarfArg = Args.getLastArg(options::OPT_gsplit_dwarf);
if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
- if (A->getOption().matches(options::OPT_gline_tables_only) ||
- A->getOption().matches(options::OPT_g1)) {
- // FIXME: we should support specifying dwarf version with
- // -gline-tables-only.
- CmdArgs.push_back("-gline-tables-only");
- // Default is dwarf-2 for Darwin, OpenBSD, FreeBSD and Solaris.
- const llvm::Triple &Triple = getToolChain().getTriple();
- if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD ||
- Triple.getOS() == llvm::Triple::FreeBSD ||
- Triple.getOS() == llvm::Triple::Solaris)
- CmdArgs.push_back("-gdwarf-2");
- } else if (A->getOption().matches(options::OPT_gdwarf_2))
- CmdArgs.push_back("-gdwarf-2");
- else if (A->getOption().matches(options::OPT_gdwarf_3))
- CmdArgs.push_back("-gdwarf-3");
- else if (A->getOption().matches(options::OPT_gdwarf_4))
- CmdArgs.push_back("-gdwarf-4");
- else if (!A->getOption().matches(options::OPT_g0) &&
- !A->getOption().matches(options::OPT_ggdb0)) {
- // Default is dwarf-2 for Darwin, OpenBSD, FreeBSD and Solaris.
- const llvm::Triple &Triple = getToolChain().getTriple();
- if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD ||
- Triple.getOS() == llvm::Triple::FreeBSD ||
- Triple.getOS() == llvm::Triple::Solaris)
- CmdArgs.push_back("-gdwarf-2");
- else
- CmdArgs.push_back("-g");
- }
+ // If the last option explicitly specified a debug-info level, use it.
+ if (A->getOption().matches(options::OPT_gN_Group)) {
+ DebugInfoKind = DebugLevelToInfoKind(*A);
+ // If you say "-gsplit-dwarf -gline-tables-only", -gsplit-dwarf loses.
+ // But -gsplit-dwarf is not a g_group option, hence we have to check the
+ // order explicitly. (If -gsplit-dwarf wins, we fix DebugInfoKind later.)
+ if (SplitDwarfArg && DebugInfoKind < CodeGenOptions::LimitedDebugInfo &&
+ A->getIndex() > SplitDwarfArg->getIndex())
+ SplitDwarfArg = nullptr;
+ } else
+ // For any other 'g' option, use Limited.
+ DebugInfoKind = CodeGenOptions::LimitedDebugInfo;
+ }
+
+ // If a debugger tuning argument appeared, remember it.
+ if (Arg *A = Args.getLastArg(options::OPT_gTune_Group,
+ options::OPT_ggdbN_Group)) {
+ if (A->getOption().matches(options::OPT_glldb))
+ DebuggerTuning = llvm::DebuggerKind::LLDB;
+ else if (A->getOption().matches(options::OPT_gsce))
+ DebuggerTuning = llvm::DebuggerKind::SCE;
+ else
+ DebuggerTuning = llvm::DebuggerKind::GDB;
+ }
+
+ // If a -gdwarf argument appeared, remember it.
+ if (Arg *A = Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3,
+ options::OPT_gdwarf_4, options::OPT_gdwarf_5))
+ DwarfVersion = DwarfVersionNum(A->getSpelling());
+
+ // Forward -gcodeview.
+ // 'EmitCodeView might have been set by CL-compatibility argument parsing.
+ if (Args.hasArg(options::OPT_gcodeview) || EmitCodeView) {
+ // DwarfVersion remains at 0 if no explicit choice was made.
+ CmdArgs.push_back("-gcodeview");
+ } else if (DwarfVersion == 0 &&
+ DebugInfoKind != CodeGenOptions::NoDebugInfo) {
+ DwarfVersion = getToolChain().GetDefaultDwarfVersion();
}
// We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now.
Args.ClaimAllArgs(options::OPT_g_flags_Group);
+
+ // PS4 defaults to no column info
if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
- /*Default*/ true))
+ /*Default=*/ !IsPS4CPU))
CmdArgs.push_back("-dwarf-column-info");
// FIXME: Move backend command line options to the module.
+ if (Args.hasArg(options::OPT_gmodules)) {
+ DebugInfoKind = CodeGenOptions::LimitedDebugInfo;
+ CmdArgs.push_back("-dwarf-ext-refs");
+ CmdArgs.push_back("-fmodule-format=obj");
+ }
+
// -gsplit-dwarf should turn on -g and enable the backend dwarf
// splitting and extraction.
// FIXME: Currently only works on Linux.
- if (getToolChain().getTriple().isOSLinux() &&
- Args.hasArg(options::OPT_gsplit_dwarf)) {
- CmdArgs.push_back("-g");
+ if (getToolChain().getTriple().isOSLinux() && SplitDwarfArg) {
+ DebugInfoKind = CodeGenOptions::LimitedDebugInfo;
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-split-dwarf=Enable");
}
+ // After we've dealt with all combinations of things that could
+ // make DebugInfoKind be other than None or DebugLineTablesOnly,
+ // figure out if we need to "upgrade" it to standalone debug info.
+ // We parse these two '-f' options whether or not they will be used,
+ // to claim them even if you wrote "-fstandalone-debug -gline-tables-only"
+ bool NeedFullDebug = Args.hasFlag(options::OPT_fstandalone_debug,
+ options::OPT_fno_standalone_debug,
+ getToolChain().GetDefaultStandaloneDebug());
+ if (DebugInfoKind == CodeGenOptions::LimitedDebugInfo && NeedFullDebug)
+ DebugInfoKind = CodeGenOptions::FullDebugInfo;
+ RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
+ DebuggerTuning);
+
// -ggnu-pubnames turns on gnu style pubnames in the backend.
if (Args.hasArg(options::OPT_ggnu_pubnames)) {
CmdArgs.push_back("-backend-option");
@@ -3715,7 +4180,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -gdwarf-aranges turns on the emission of the aranges section in the
// backend.
- if (Args.hasArg(options::OPT_gdwarf_aranges)) {
+ // Always enabled on the PS4.
+ if (Args.hasArg(options::OPT_gdwarf_aranges) || IsPS4CPU) {
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-generate-arange-section");
}
@@ -3726,8 +4192,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-generate-type-units");
}
- // CloudABI uses -ffunction-sections and -fdata-sections by default.
- bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI;
+ // CloudABI and WebAssembly use -ffunction-sections and -fdata-sections by
+ // default.
+ bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI ||
+ Triple.getArch() == llvm::Triple::wasm32 ||
+ Triple.getArch() == llvm::Triple::wasm64;
if (Args.hasFlag(options::OPT_ffunction_sections,
options::OPT_fno_function_sections, UseSeparateSections)) {
@@ -3747,6 +4216,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs);
+ // Add runtime flag for PS4 when PGO or Coverage are enabled.
+ if (getToolChain().getTriple().isPS4CPU())
+ addPS4ProfileRTArgs(getToolChain(), Args, CmdArgs);
+
// Pass options for controlling the default header search paths.
if (Args.hasArg(options::OPT_nostdinc)) {
CmdArgs.push_back("-nostdsysteminc");
@@ -3839,7 +4312,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
//
// FIXME: Support -fpreprocessed
if (types::getPreprocessedType(InputType) != types::TY_INVALID)
- AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs);
+ AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs,
+ AuxToolChain);
// Don't warn about "clang -c -DPIC -fPIC test.i" because libtool.m4 assumes
// that "The compiler can only warn and ignore the option if not recognized".
@@ -3861,6 +4335,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
for (const Arg *A :
Args.filtered(options::OPT_clang_ignored_gcc_optimization_f_Group)) {
D.Diag(diag::warn_ignored_gcc_optimization) << A->getAsString(Args);
+ A->claim();
}
claimNoWarnArgs(Args);
@@ -3956,6 +4431,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Add in -fdebug-compilation-dir if necessary.
addDebugCompDirArg(Args, CmdArgs);
+ for (const Arg *A : Args.filtered(options::OPT_fdebug_prefix_map_EQ)) {
+ StringRef Map = A->getValue();
+ if (Map.find('=') == StringRef::npos)
+ D.Diag(diag::err_drv_invalid_argument_to_fdebug_prefix_map) << Map;
+ else
+ CmdArgs.push_back(Args.MakeArgString("-fdebug-prefix-map=" + Map));
+ A->claim();
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_,
options::OPT_ftemplate_depth_EQ)) {
CmdArgs.push_back("-ftemplate-depth");
@@ -4068,9 +4552,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Forward -f (flag) options which we can pass directly.
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
- Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug);
- Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
+ // Emulated TLS is enabled by default on Android, and can be enabled manually
+ // with -femulated-tls.
+ bool EmulatedTLSDefault = Triple.isAndroid();
+ if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls,
+ EmulatedTLSDefault))
+ CmdArgs.push_back("-femulated-tls");
// AltiVec-like language extensions aren't relevant for assembling.
if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm) {
Args.AddLastArg(CmdArgs, options::OPT_faltivec);
@@ -4092,10 +4580,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// given, decide a default based on the target. Otherwise rely on the
// options and pass the right information to the frontend.
if (!Args.hasFlag(options::OPT_fopenmp_use_tls,
- options::OPT_fnoopenmp_use_tls,
- getToolChain().getArch() == llvm::Triple::ppc ||
- getToolChain().getArch() == llvm::Triple::ppc64 ||
- getToolChain().getArch() == llvm::Triple::ppc64le))
+ options::OPT_fnoopenmp_use_tls, /*Default=*/true))
CmdArgs.push_back("-fnoopenmp-use-tls");
break;
default:
@@ -4134,7 +4619,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_lax_vector_conversions))
CmdArgs.push_back("-fno-lax-vector-conversions");
- if (Args.getLastArg(options::OPT_fapple_kext))
+ if (Args.getLastArg(options::OPT_fapple_kext) ||
+ (Args.hasArg(options::OPT_mkernel) && types::isCXX(InputType)))
CmdArgs.push_back("-fapple-kext");
Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
@@ -4215,14 +4701,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Translate -mstackrealign
if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
- false)) {
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-force-align-stack");
- }
- if (!Args.hasFlag(options::OPT_mno_stackrealign, options::OPT_mstackrealign,
- false)) {
+ false))
CmdArgs.push_back(Args.MakeArgString("-mstackrealign"));
- }
if (Args.hasArg(options::OPT_mstack_alignment)) {
StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment);
@@ -4238,9 +4718,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mstack-probe-size=0");
}
- if (getToolChain().getArch() == llvm::Triple::aarch64 ||
- getToolChain().getArch() == llvm::Triple::aarch64_be)
+ switch (getToolChain().getArch()) {
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
CmdArgs.push_back("-fallow-half-arguments-and-returns");
+ break;
+
+ default:
+ break;
+ }
if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
options::OPT_mno_restrict_it)) {
@@ -4251,8 +4741,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-arm-no-restrict-it");
}
- } else if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
- TT.getArch() == llvm::Triple::thumb)) {
+ } else if (Triple.isOSWindows() &&
+ (Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb)) {
// Windows on ARM expects restricted IT blocks
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-arm-restrict-it");
@@ -4268,17 +4759,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->render(Args, CmdArgs);
}
- if (Args.hasArg(options::OPT_mkernel)) {
- if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType))
- CmdArgs.push_back("-fapple-kext");
- if (!Args.hasArg(options::OPT_fbuiltin))
- CmdArgs.push_back("-fno-builtin");
- Args.ClaimAllArgs(options::OPT_fno_builtin);
- }
- // -fbuiltin is default.
- else if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin))
+ // -fbuiltin is default unless -mkernel is used.
+ bool UseBuiltins =
+ Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin,
+ !Args.hasArg(options::OPT_mkernel));
+ if (!UseBuiltins)
CmdArgs.push_back("-fno-builtin");
+ // -ffreestanding implies -fno-builtin.
+ if (Args.hasArg(options::OPT_ffreestanding))
+ UseBuiltins = false;
+
+ // Process the -fno-builtin-* options.
+ for (const auto &Arg : Args) {
+ const Option &O = Arg->getOption();
+ if (!O.matches(options::OPT_fno_builtin_))
+ continue;
+
+ Arg->claim();
+ // If -fno-builtin is specified, then there's no need to pass the option to
+ // the frontend.
+ if (!UseBuiltins)
+ continue;
+
+ StringRef FuncName = Arg->getValue();
+ CmdArgs.push_back(Args.MakeArgString("-fno-builtin-" + FuncName));
+ }
+
if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
options::OPT_fno_assume_sane_operator_new))
CmdArgs.push_back("-fno-assume-sane-operator-new");
@@ -4345,7 +4852,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file);
// -fmodule-file can be used to specify files containing precompiled modules.
- Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);
+ if (HaveModules)
+ Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);
+ else
+ Args.ClaimAllArgs(options::OPT_fmodule_file);
// -fmodule-cache-path specifies where our implicitly-built module files
// should be written.
@@ -4453,11 +4963,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// -fuse-cxa-atexit is default.
- if (!Args.hasFlag(options::OPT_fuse_cxa_atexit,
- options::OPT_fno_use_cxa_atexit,
- !IsWindowsCygnus && !IsWindowsGNU &&
- getToolChain().getArch() != llvm::Triple::hexagon &&
- getToolChain().getArch() != llvm::Triple::xcore) ||
+ if (!Args.hasFlag(
+ options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
+ !IsWindowsCygnus && !IsWindowsGNU &&
+ getToolChain().getTriple().getOS() != llvm::Triple::Solaris &&
+ getToolChain().getArch() != llvm::Triple::hexagon &&
+ getToolChain().getArch() != llvm::Triple::xcore &&
+ ((getToolChain().getTriple().getVendor() !=
+ llvm::Triple::MipsTechnologies) ||
+ getToolChain().getTriple().hasEnvironment())) ||
KernelOrKext)
CmdArgs.push_back("-fno-use-cxa-atexit");
@@ -4499,6 +5013,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_borland_extensions, false))
CmdArgs.push_back("-fborland-extensions");
+ // -fno-declspec is default, except for PS4.
+ if (Args.hasFlag(options::OPT_fdeclspec, options::OPT_fno_declspec,
+ getToolChain().getTriple().isPS4()))
+ CmdArgs.push_back("-fdeclspec");
+ else if (Args.hasArg(options::OPT_fno_declspec))
+ CmdArgs.push_back("-fno-declspec"); // Explicitly disabling __declspec.
+
// -fthreadsafe-static is default, except for MSVC compatibility versions less
// than 19.
if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
@@ -4585,6 +5106,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_objc_arc_exceptions,
/*default*/ types::isCXX(InputType)))
CmdArgs.push_back("-fobjc-arc-exceptions");
+
}
// -fobjc-infer-related-result-type is the default, except in the Objective-C
@@ -4608,6 +5130,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ // Pass down -fobjc-weak or -fno-objc-weak if present.
+ if (types::isObjC(InputType)) {
+ auto WeakArg = Args.getLastArg(options::OPT_fobjc_weak,
+ options::OPT_fno_objc_weak);
+ if (!WeakArg) {
+ // nothing to do
+ } else if (GCArg) {
+ if (WeakArg->getOption().matches(options::OPT_fobjc_weak))
+ D.Diag(diag::err_objc_weak_with_gc);
+ } else if (!objcRuntime.allowsWeak()) {
+ if (WeakArg->getOption().matches(options::OPT_fobjc_weak))
+ D.Diag(diag::err_objc_weak_unsupported);
+ } else {
+ WeakArg->render(Args, CmdArgs);
+ }
+ }
+
if (Args.hasFlag(options::OPT_fapplication_extension,
options::OPT_fno_application_extension, false))
CmdArgs.push_back("-fapplication-extension");
@@ -4617,7 +5156,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext, objcRuntime,
CmdArgs);
- if (getToolChain().UseSjLjExceptions())
+ if (getToolChain().UseSjLjExceptions(Args))
CmdArgs.push_back("-fsjlj-exceptions");
// C++ "sane" operator new.
@@ -4676,14 +5215,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (KernelOrKext || isNoCommonDefault(getToolChain().getTriple())) {
- if (!Args.hasArg(options::OPT_fcommon))
- CmdArgs.push_back("-fno-common");
- Args.ClaimAllArgs(options::OPT_fno_common);
- }
-
- // -fcommon is default, only pass non-default.
- else if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common))
+ // -fcommon is the default unless compiling kernel code or the target says so
+ bool NoCommonDefault =
+ KernelOrKext || isNoCommonDefault(getToolChain().getTriple());
+ if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common,
+ !NoCommonDefault))
CmdArgs.push_back("-fno-common");
// -fsigned-bitfields is default, and clang doesn't yet support
@@ -4918,10 +5454,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Forward -fparse-all-comments to -cc1.
Args.AddAllArgs(CmdArgs, options::OPT_fparse_all_comments);
+ // Turn -fplugin=name.so into -load name.so
+ for (const Arg *A : Args.filtered(options::OPT_fplugin_EQ)) {
+ CmdArgs.push_back("-load");
+ CmdArgs.push_back(A->getValue());
+ A->claim();
+ }
+
// Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
// parser.
Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
- bool OptDisabled = false;
for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
A->claim();
@@ -4929,17 +5471,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// it and developers have been trained to spell it with -mllvm.
if (StringRef(A->getValue(0)) == "-disable-llvm-optzns") {
CmdArgs.push_back("-disable-llvm-optzns");
- OptDisabled = true;
} else
A->render(Args, CmdArgs);
}
// With -save-temps, we want to save the unoptimized bitcode output from the
- // CompileJobAction, so disable optimizations if they are not already
- // disabled.
- if (C.getDriver().isSaveTempsEnabled() && !OptDisabled &&
- isa<CompileJobAction>(JA))
- CmdArgs.push_back("-disable-llvm-optzns");
+ // CompileJobAction, use -disable-llvm-passes to get pristine IR generated
+ // by the frontend.
+ if (C.getDriver().isSaveTempsEnabled() && isa<CompileJobAction>(JA))
+ CmdArgs.push_back("-disable-llvm-passes");
if (Output.getType() == types::TY_Dependencies) {
// Handled with other dependency code.
@@ -4982,8 +5522,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Add the split debug info name to the command lines here so we
// can propagate it to the backend.
- bool SplitDwarf = Args.hasArg(options::OPT_gsplit_dwarf) &&
- getToolChain().getTriple().isOSLinux() &&
+ bool SplitDwarf = SplitDwarfArg && getToolChain().getTriple().isOSLinux() &&
(isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
isa<BackendJobAction>(JA));
const char *SplitDwarfOut;
@@ -4996,11 +5535,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Host-side cuda compilation receives device-side outputs as Inputs[1...].
// Include them with -fcuda-include-gpubinary.
if (IsCuda && Inputs.size() > 1)
- for (InputInfoList::const_iterator it = std::next(Inputs.begin()),
- ie = Inputs.end();
- it != ie; ++it) {
+ for (auto I = std::next(Inputs.begin()), E = Inputs.end(); I != E; ++I) {
CmdArgs.push_back("-fcuda-include-gpubinary");
- CmdArgs.push_back(it->getFilename());
+ CmdArgs.push_back(I->getFilename());
}
// Finally add the compile command to the compilation.
@@ -5009,10 +5546,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
(InputType == types::TY_C || InputType == types::TY_CXX)) {
auto CLCommand =
getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput);
- C.addCommand(llvm::make_unique<FallbackCommand>(JA, *this, Exec, CmdArgs,
- std::move(CLCommand)));
+ C.addCommand(llvm::make_unique<FallbackCommand>(
+ JA, *this, Exec, CmdArgs, Inputs, std::move(CLCommand)));
} else {
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
// Handle the debug info splitting at object creation time if we're
@@ -5153,7 +5690,7 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
// -fgnu-runtime
} else {
assert(runtimeArg->getOption().matches(options::OPT_fgnu_runtime));
- // Legacy behaviour is to target the gnustep runtime if we are i
+ // Legacy behaviour is to target the gnustep runtime if we are in
// non-fragile mode or the GCC runtime in fragile mode.
if (isNonFragile)
runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1, 6));
@@ -5172,12 +5709,14 @@ static bool maybeConsumeDash(const std::string &EH, size_t &I) {
return !HaveDash;
}
+namespace {
struct EHFlags {
EHFlags() : Synch(false), Asynch(false), NoExceptC(false) {}
bool Synch;
bool Asynch;
bool NoExceptC;
};
+} // end anonymous namespace
/// /EH controls whether to run destructor cleanups when exceptions are
/// thrown. There are three modifiers:
@@ -5212,14 +5751,12 @@ static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
}
}
- // FIXME: Disable C++ EH completely, until it becomes more reliable. Users
- // can use -Xclang to manually enable C++ EH until then.
- EH = EHFlags();
-
return EH;
}
-void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
+void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs,
+ enum CodeGenOptions::DebugInfoKind *DebugInfoKind,
+ bool *EmitCodeView) const {
unsigned RTOptionID = options::OPT__SLASH_MT;
if (Args.hasArg(options::OPT__SLASH_LDd))
@@ -5230,39 +5767,46 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
RTOptionID = A->getOption().getID();
+ StringRef FlagForCRT;
switch (RTOptionID) {
case options::OPT__SLASH_MD:
if (Args.hasArg(options::OPT__SLASH_LDd))
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-D_DLL");
- CmdArgs.push_back("--dependent-lib=msvcrt");
+ FlagForCRT = "--dependent-lib=msvcrt";
break;
case options::OPT__SLASH_MDd:
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-D_DLL");
- CmdArgs.push_back("--dependent-lib=msvcrtd");
+ FlagForCRT = "--dependent-lib=msvcrtd";
break;
case options::OPT__SLASH_MT:
if (Args.hasArg(options::OPT__SLASH_LDd))
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
- CmdArgs.push_back("--dependent-lib=libcmt");
+ FlagForCRT = "--dependent-lib=libcmt";
break;
case options::OPT__SLASH_MTd:
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
- CmdArgs.push_back("--dependent-lib=libcmtd");
+ FlagForCRT = "--dependent-lib=libcmtd";
break;
default:
llvm_unreachable("Unexpected option ID.");
}
- // This provides POSIX compatibility (maps 'open' to '_open'), which most
- // users want. The /Za flag to cl.exe turns this off, but it's not
- // implemented in clang.
- CmdArgs.push_back("--dependent-lib=oldnames");
+ if (Args.hasArg(options::OPT__SLASH_Zl)) {
+ CmdArgs.push_back("-D_VC_NODEFAULTLIB");
+ } else {
+ CmdArgs.push_back(FlagForCRT.data());
+
+ // This provides POSIX compatibility (maps 'open' to '_open'), which most
+ // users want. The /Za flag to cl.exe turns this off, but it's not
+ // implemented in clang.
+ CmdArgs.push_back("--dependent-lib=oldnames");
+ }
// Both /showIncludes and /E (and /EP) write to stdout. Allowing both
// would produce interleaved output, so ignore /showIncludes in such cases.
@@ -5275,6 +5819,16 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
/*default=*/false))
CmdArgs.push_back("-fno-rtti-data");
+ // Emit CodeView if -Z7 is present.
+ *EmitCodeView = Args.hasArg(options::OPT__SLASH_Z7);
+ bool EmitDwarf = Args.hasArg(options::OPT_gdwarf);
+ // If we are emitting CV but not DWARF, don't build information that LLVM
+ // can't yet process.
+ if (*EmitCodeView && !EmitDwarf)
+ *DebugInfoKind = CodeGenOptions::DebugLineTablesOnly;
+ if (*EmitCodeView)
+ CmdArgs.push_back("-gcodeview");
+
const Driver &D = getToolChain().getDriver();
EHFlags EH = parseClangCLEHFlags(D, Args);
// FIXME: Do something with NoExceptC.
@@ -5366,6 +5920,10 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
assert(Inputs.size() == 1 && "Unexpected number of inputs.");
const InputInfo &Input = Inputs[0];
+ std::string TripleStr =
+ getToolChain().ComputeEffectiveClangTriple(Args, Input.getType());
+ const llvm::Triple Triple(TripleStr);
+
// Don't warn about "clang -w -c foo.s"
Args.ClaimAllArgs(options::OPT_w);
// and "clang -emit-llvm -c foo.s"
@@ -5380,8 +5938,6 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// Add the "effective" target triple.
CmdArgs.push_back("-triple");
- std::string TripleStr =
- getToolChain().ComputeEffectiveClangTriple(Args, Input.getType());
CmdArgs.push_back(Args.MakeArgString(TripleStr));
// Set the output mode, we currently only expect to be used as a real
@@ -5395,7 +5951,6 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Clang::getBaseInputName(Args, Input));
// Add the target cpu
- const llvm::Triple Triple(TripleStr);
std::string CPU = getCPUName(Args, Triple, /*FromAs*/ true);
if (!CPU.empty()) {
CmdArgs.push_back("-target-cpu");
@@ -5403,8 +5958,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
}
// Add the target features
- const Driver &D = getToolChain().getDriver();
- getTargetFeatures(D, Triple, Args, CmdArgs, true);
+ getTargetFeatures(getToolChain(), Triple, Args, CmdArgs, true);
// Ignore explicit -force_cpusubtype_ALL option.
(void)Args.hasArg(options::OPT_force__cpusubtype__ALL);
@@ -5423,17 +5977,21 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// with an actual assembly file.
if (SourceAction->getType() == types::TY_Asm ||
SourceAction->getType() == types::TY_PP_Asm) {
+ bool WantDebug = false;
+ unsigned DwarfVersion = 0;
Args.ClaimAllArgs(options::OPT_g_Group);
- if (Arg *A = Args.getLastArg(options::OPT_g_Group))
- if (!A->getOption().matches(options::OPT_g0))
- CmdArgs.push_back("-g");
-
- if (Args.hasArg(options::OPT_gdwarf_2))
- CmdArgs.push_back("-gdwarf-2");
- if (Args.hasArg(options::OPT_gdwarf_3))
- CmdArgs.push_back("-gdwarf-3");
- if (Args.hasArg(options::OPT_gdwarf_4))
- CmdArgs.push_back("-gdwarf-4");
+ if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
+ WantDebug = !A->getOption().matches(options::OPT_g0) &&
+ !A->getOption().matches(options::OPT_ggdb0);
+ if (WantDebug)
+ DwarfVersion = DwarfVersionNum(A->getSpelling());
+ }
+ if (DwarfVersion == 0)
+ DwarfVersion = getToolChain().GetDefaultDwarfVersion();
+ RenderDebugEnablingArgs(Args, CmdArgs,
+ (WantDebug ? CodeGenOptions::LimitedDebugInfo
+ : CodeGenOptions::NoDebugInfo),
+ DwarfVersion, llvm::DebuggerKind::Default);
// Add the -fdebug-compilation-dir flag if needed.
addDebugCompDirArg(Args, CmdArgs);
@@ -5442,6 +6000,23 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// assembler on assembly source files.
CmdArgs.push_back("-dwarf-debug-producer");
CmdArgs.push_back(Args.MakeArgString(getClangFullVersion()));
+
+ // And pass along -I options
+ Args.AddAllArgs(CmdArgs, options::OPT_I);
+ }
+
+ // Handle -fPIC et al -- the relocation-model affects the assembler
+ // for some targets.
+ llvm::Reloc::Model RelocationModel;
+ unsigned PICLevel;
+ bool IsPIE;
+ std::tie(RelocationModel, PICLevel, IsPIE) =
+ ParsePICArgs(getToolChain(), Triple, Args);
+
+ const char *RMName = RelocationModelName(RelocationModel);
+ if (RMName) {
+ CmdArgs.push_back("-mrelocation-model");
+ CmdArgs.push_back(RMName);
}
// Optionally embed the -cc1as level arguments into the debug info, for build
@@ -5484,8 +6059,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// doesn't handle that so rather than warning about unused flags that are
// actually used, we'll lie by omission instead.
// FIXME: Stop lying and consume only the appropriate driver flags
- for (const Arg *A : Args.filtered(options::OPT_W_Group))
- A->claim();
+ Args.ClaimAllArgs(options::OPT_W_Group);
CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
getToolChain().getDriver());
@@ -5500,7 +6074,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Input.getFilename());
const char *Exec = getToolChain().getDriver().getClangProgramPath();
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
// Handle the debug info splitting at object creation time if we're
// creating an object.
@@ -5522,6 +6096,12 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
for (const auto &A : Args) {
if (forwardToGCC(A->getOption())) {
+ // It is unfortunate that we have to claim here, as this means
+ // we will basically never report anything interesting for
+ // platforms using a generic gcc, even if we are just using gcc
+ // to get to the assembler.
+ A->claim();
+
// Don't forward any -g arguments to assembly steps.
if (isa<AssembleJobAction>(JA) &&
A->getOption().matches(options::OPT_g_Group))
@@ -5532,11 +6112,6 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().matches(options::OPT_W_Group))
continue;
- // It is unfortunate that we have to claim here, as this means
- // we will basically never report anything interesting for
- // platforms using a generic gcc, even if we are just using gcc
- // to get to the assembler.
- A->claim();
A->render(Args, CmdArgs);
}
}
@@ -5555,12 +6130,22 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
//
// FIXME: The triple class should directly provide the information we want
// here.
- const llvm::Triple::ArchType Arch = getToolChain().getArch();
- if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc)
+ switch (getToolChain().getArch()) {
+ default:
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::ppc:
CmdArgs.push_back("-m32");
- else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64 ||
- Arch == llvm::Triple::ppc64le)
+ break;
+ case llvm::Triple::x86_64:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
CmdArgs.push_back("-m64");
+ break;
+ case llvm::Triple::sparcel:
+ CmdArgs.push_back("-EL");
+ break;
+ }
if (Output.isFilename()) {
CmdArgs.push_back("-o");
@@ -5582,8 +6167,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
// inputs into '-Wl,' options?
for (const auto &II : Inputs) {
// Don't try to pass LLVM or AST inputs to a generic gcc.
- if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
- II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
+ if (types::isLLVMIR(II.getType()))
D.Diag(diag::err_drv_no_linker_llvm_support)
<< getToolChain().getTripleString();
else if (II.getType() == types::TY_AST)
@@ -5623,7 +6207,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
GCCName = "gcc";
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void gcc::Preprocessor::RenderExtraToolArgs(const JobAction &JA,
@@ -5643,6 +6227,11 @@ void gcc::Compiler::RenderExtraToolArgs(const JobAction &JA,
case types::TY_LTO_BC:
CmdArgs.push_back("-c");
break;
+ // We assume we've got an "integrated" assembler in that gcc will produce an
+ // object file itself.
+ case types::TY_Object:
+ CmdArgs.push_back("-c");
+ break;
case types::TY_PP_Asm:
CmdArgs.push_back("-S");
break;
@@ -5661,7 +6250,9 @@ void gcc::Linker::RenderExtraToolArgs(const JobAction &JA,
// Hexagon tools start.
void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const {}
+ ArgStringList &CmdArgs) const {
+}
+
void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -5669,15 +6260,21 @@ void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
claimNoWarnArgs(Args);
- const Driver &D = getToolChain().getDriver();
+ auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
+ const Driver &D = HTC.getDriver();
ArgStringList CmdArgs;
- std::string MarchString = "-march=";
- MarchString += toolchains::Hexagon_TC::GetTargetCPU(Args);
- CmdArgs.push_back(Args.MakeArgString(MarchString));
+ std::string MArchString = "-march=hexagon";
+ CmdArgs.push_back(Args.MakeArgString(MArchString));
RenderExtraToolArgs(JA, CmdArgs);
+ std::string AsName = "hexagon-llvm-mc";
+ std::string MCpuString = "-mcpu=hexagon" +
+ toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
+ CmdArgs.push_back("-filetype=obj");
+ CmdArgs.push_back(Args.MakeArgString(MCpuString));
+
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -5686,8 +6283,10 @@ void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fsyntax-only");
}
- if (const char *v = toolchains::Hexagon_TC::GetSmallDataThreshold(Args))
- CmdArgs.push_back(Args.MakeArgString(std::string("-G") + v));
+ if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
+ std::string N = llvm::utostr(G.getValue());
+ CmdArgs.push_back(Args.MakeArgString(std::string("-gpsize=") + N));
+ }
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
@@ -5701,61 +6300,56 @@ void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
// inputs into '-Wl,' options?
for (const auto &II : Inputs) {
// Don't try to pass LLVM or AST inputs to a generic gcc.
- if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
- II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
+ if (types::isLLVMIR(II.getType()))
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
- << getToolChain().getTripleString();
+ << HTC.getTripleString();
else if (II.getType() == types::TY_AST)
D.Diag(clang::diag::err_drv_no_ast_support)
- << getToolChain().getTripleString();
+ << HTC.getTripleString();
else if (II.getType() == types::TY_ModuleFile)
D.Diag(diag::err_drv_no_module_support)
- << getToolChain().getTripleString();
+ << HTC.getTripleString();
if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
// Don't render as input, we need gcc to do the translations.
- // FIXME: Pranav: What is this ?
+ // FIXME: What is this?
II.getInputArg().render(Args, CmdArgs);
}
- const char *GCCName = "hexagon-as";
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName.c_str()));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
ArgStringList &CmdArgs) const {
- // The types are (hopefully) good enough.
}
-static void constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
- const toolchains::Hexagon_TC &ToolChain,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- ArgStringList &CmdArgs,
- const char *LinkingOutput) {
+static void
+constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
+ const toolchains::HexagonToolChain &HTC,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const ArgList &Args, ArgStringList &CmdArgs,
+ const char *LinkingOutput) {
- const Driver &D = ToolChain.getDriver();
+ const Driver &D = HTC.getDriver();
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
- bool hasStaticArg = Args.hasArg(options::OPT_static);
- bool buildingLib = Args.hasArg(options::OPT_shared);
- bool buildPIE = Args.hasArg(options::OPT_pie);
- bool incStdLib = !Args.hasArg(options::OPT_nostdlib);
- bool incStartFiles = !Args.hasArg(options::OPT_nostartfiles);
- bool incDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
- bool useG0 = false;
- bool useShared = buildingLib && !hasStaticArg;
+ bool IsStatic = Args.hasArg(options::OPT_static);
+ bool IsShared = Args.hasArg(options::OPT_shared);
+ bool IsPIE = Args.hasArg(options::OPT_pie);
+ bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
+ bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
+ bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
+ bool UseG0 = false;
+ bool UseShared = IsShared && !IsStatic;
//----------------------------------------------------------------------------
// Silence warnings for various options
//----------------------------------------------------------------------------
-
Args.ClaimAllArgs(options::OPT_g_Group);
Args.ClaimAllArgs(options::OPT_emit_llvm);
Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
@@ -5765,27 +6359,37 @@ static void constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
- for (const auto &Opt : ToolChain.ExtraOpts)
+ if (Args.hasArg(options::OPT_s))
+ CmdArgs.push_back("-s");
+
+ if (Args.hasArg(options::OPT_r))
+ CmdArgs.push_back("-r");
+
+ for (const auto &Opt : HTC.ExtraOpts)
CmdArgs.push_back(Opt.c_str());
- std::string MarchString = toolchains::Hexagon_TC::GetTargetCPU(Args);
- CmdArgs.push_back(Args.MakeArgString("-m" + MarchString));
+ CmdArgs.push_back("-march=hexagon");
+ std::string CpuVer =
+ toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
+ std::string MCpuString = "-mcpu=hexagon" + CpuVer;
+ CmdArgs.push_back(Args.MakeArgString(MCpuString));
- if (buildingLib) {
+ if (IsShared) {
CmdArgs.push_back("-shared");
- CmdArgs.push_back("-call_shared"); // should be the default, but doing as
- // hexagon-gcc does
+ // The following should be the default, but doing as hexagon-gcc does.
+ CmdArgs.push_back("-call_shared");
}
- if (hasStaticArg)
+ if (IsStatic)
CmdArgs.push_back("-static");
- if (buildPIE && !buildingLib)
+ if (IsPIE && !IsShared)
CmdArgs.push_back("-pie");
- if (const char *v = toolchains::Hexagon_TC::GetSmallDataThreshold(Args)) {
- CmdArgs.push_back(Args.MakeArgString(std::string("-G") + v));
- useG0 = toolchains::Hexagon_TC::UsesG0(v);
+ if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
+ std::string N = llvm::utostr(G.getValue());
+ CmdArgs.push_back(Args.MakeArgString(std::string("-G") + N));
+ UseG0 = G.getValue() == 0;
}
//----------------------------------------------------------------------------
@@ -5794,77 +6398,85 @@ static void constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- const std::string MarchSuffix = "/" + MarchString;
- const std::string G0Suffix = "/G0";
- const std::string MarchG0Suffix = MarchSuffix + G0Suffix;
- const std::string RootDir =
- toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir, Args) + "/";
- const std::string StartFilesDir =
- RootDir + "hexagon/lib" + (useG0 ? MarchG0Suffix : MarchSuffix);
-
//----------------------------------------------------------------------------
// moslib
//----------------------------------------------------------------------------
- std::vector<std::string> oslibs;
- bool hasStandalone = false;
+ std::vector<std::string> OsLibs;
+ bool HasStandalone = false;
for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
A->claim();
- oslibs.emplace_back(A->getValue());
- hasStandalone = hasStandalone || (oslibs.back() == "standalone");
+ OsLibs.emplace_back(A->getValue());
+ HasStandalone = HasStandalone || (OsLibs.back() == "standalone");
}
- if (oslibs.empty()) {
- oslibs.push_back("standalone");
- hasStandalone = true;
+ if (OsLibs.empty()) {
+ OsLibs.push_back("standalone");
+ HasStandalone = true;
}
//----------------------------------------------------------------------------
// Start Files
//----------------------------------------------------------------------------
- if (incStdLib && incStartFiles) {
-
- if (!buildingLib) {
- if (hasStandalone) {
- CmdArgs.push_back(
- Args.MakeArgString(StartFilesDir + "/crt0_standalone.o"));
+ const std::string MCpuSuffix = "/" + CpuVer;
+ const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
+ const std::string RootDir =
+ HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
+ const std::string StartSubDir =
+ "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);
+
+ auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,
+ const char *Name) -> std::string {
+ std::string RelName = SubDir + Name;
+ std::string P = HTC.GetFilePath(RelName.c_str());
+ if (llvm::sys::fs::exists(P))
+ return P;
+ return RootDir + RelName;
+ };
+
+ if (IncStdLib && IncStartFiles) {
+ if (!IsShared) {
+ if (HasStandalone) {
+ std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");
+ CmdArgs.push_back(Args.MakeArgString(Crt0SA));
}
- CmdArgs.push_back(Args.MakeArgString(StartFilesDir + "/crt0.o"));
+ std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");
+ CmdArgs.push_back(Args.MakeArgString(Crt0));
}
- std::string initObj = useShared ? "/initS.o" : "/init.o";
- CmdArgs.push_back(Args.MakeArgString(StartFilesDir + initObj));
+ std::string Init = UseShared
+ ? Find(RootDir, StartSubDir + "/pic", "/initS.o")
+ : Find(RootDir, StartSubDir, "/init.o");
+ CmdArgs.push_back(Args.MakeArgString(Init));
}
//----------------------------------------------------------------------------
// Library Search Paths
//----------------------------------------------------------------------------
- const ToolChain::path_list &LibPaths = ToolChain.getFilePaths();
+ const ToolChain::path_list &LibPaths = HTC.getFilePaths();
for (const auto &LibPath : LibPaths)
CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
- Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
- Args.AddAllArgs(CmdArgs, options::OPT_s);
- Args.AddAllArgs(CmdArgs, options::OPT_t);
- Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
+ Args.AddAllArgs(CmdArgs,
+ {options::OPT_T_Group, options::OPT_e, options::OPT_s,
+ options::OPT_t, options::OPT_u_Group});
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+ AddLinkerInputs(HTC, Inputs, Args, CmdArgs);
//----------------------------------------------------------------------------
// Libraries
//----------------------------------------------------------------------------
- if (incStdLib && incDefLibs) {
+ if (IncStdLib && IncDefLibs) {
if (D.CCCIsCXX()) {
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
CmdArgs.push_back("--start-group");
- if (!buildingLib) {
- for (const std::string &Lib : oslibs)
+ if (!IsShared) {
+ for (const std::string &Lib : OsLibs)
CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
CmdArgs.push_back("-lc");
}
@@ -5876,9 +6488,11 @@ static void constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
//----------------------------------------------------------------------------
// End files
//----------------------------------------------------------------------------
- if (incStdLib && incStartFiles) {
- std::string finiObj = useShared ? "/finiS.o" : "/fini.o";
- CmdArgs.push_back(Args.MakeArgString(StartFilesDir + finiObj));
+ if (IncStdLib && IncStartFiles) {
+ std::string Fini = UseShared
+ ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")
+ : Find(RootDir, StartSubDir, "/fini.o");
+ CmdArgs.push_back(Args.MakeArgString(Fini));
}
}
@@ -5887,60 +6501,105 @@ void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
-
- const toolchains::Hexagon_TC &ToolChain =
- static_cast<const toolchains::Hexagon_TC &>(getToolChain());
+ auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
ArgStringList CmdArgs;
- constructHexagonLinkArgs(C, JA, ToolChain, Output, Inputs, Args, CmdArgs,
+ constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
LinkingOutput);
- std::string Linker = ToolChain.GetProgramPath("hexagon-ld");
+ std::string Linker = HTC.GetProgramPath("hexagon-link");
C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
- CmdArgs));
+ CmdArgs, Inputs));
}
// Hexagon tools end.
+void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+
+ std::string Linker = getToolChain().GetProgramPath(getShortName());
+ ArgStringList CmdArgs;
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
+ CmdArgs, Inputs));
+}
+// AMDGPU tools end.
+
+wasm::Linker::Linker(const ToolChain &TC)
+ : GnuTool("wasm::Linker", "lld", TC) {}
+
+bool wasm::Linker::isLinkJob() const {
+ return true;
+}
+
+bool wasm::Linker::hasIntegratedCPP() const {
+ return false;
+}
+
+void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const char *Linker = Args.MakeArgString(getToolChain().GetLinkerPath());
+ ArgStringList CmdArgs;
+ CmdArgs.push_back("-flavor");
+ CmdArgs.push_back("ld");
+
+ // Enable garbage collection of unused input sections by default, since code
+ // size is of particular importance. This is significantly facilitated by
+ // the enabling of -ffunction-sections and -fdata-sections in
+ // Clang::ConstructJob.
+ if (areOptimizationsEnabled(Args))
+ CmdArgs.push_back("--gc-sections");
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Linker, CmdArgs, Inputs));
+}
+
const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {
std::string MArch;
if (!Arch.empty())
MArch = Arch;
else
MArch = Triple.getArchName();
- MArch = StringRef(MArch).lower();
+ MArch = StringRef(MArch).split("+").first.lower();
// Handle -march=native.
if (MArch == "native") {
std::string CPU = llvm::sys::getHostCPUName();
if (CPU != "generic") {
// Translate the native cpu into the architecture suffix for that CPU.
- const char *Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch);
+ StringRef Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
// If there is no valid architecture suffix for this CPU we don't know how
// to handle it, so return no architecture.
- if (strcmp(Suffix, "") == 0)
+ if (Suffix.empty())
MArch = "";
else
- MArch = std::string("arm") + Suffix;
+ MArch = std::string("arm") + Suffix.str();
}
}
return MArch;
}
+
/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
-const char *arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) {
+StringRef arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) {
std::string MArch = getARMArch(Arch, Triple);
// getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch
// here means an -march=native that we can't handle, so instead return no CPU.
if (MArch.empty())
- return "";
+ return StringRef();
// We need to return an empty string here on invalid MArch values as the
// various places that call this function can't cope with a null result.
- const char *result = Triple.getARMCPUForArch(MArch);
- if (result)
- return result;
- else
- return "";
+ return Triple.getARMCPUForArch(MArch);
}
/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
@@ -5949,7 +6608,7 @@ std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch,
// FIXME: Warn on inconsistent use of -mcpu and -march.
// If we have -mcpu=, use that.
if (!CPU.empty()) {
- std::string MCPU = StringRef(CPU).lower();
+ std::string MCPU = StringRef(CPU).split("+").first.lower();
// Handle -mcpu=native.
if (MCPU == "native")
return llvm::sys::getHostCPUName();
@@ -5963,15 +6622,26 @@ std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch,
/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
/// CPU (or Arch, if CPU is generic).
// FIXME: This is redundant with -mcpu, why does LLVM use this.
-const char *arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch) {
- if (CPU == "generic" &&
- llvm::ARMTargetParser::parseArch(Arch) == llvm::ARM::AK_ARMV8_1A)
- return "v8.1a";
-
- unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(CPU);
+StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch,
+ const llvm::Triple &Triple) {
+ unsigned ArchKind;
+ if (CPU == "generic") {
+ std::string ARMArch = tools::arm::getARMArch(Arch, Triple);
+ ArchKind = llvm::ARM::parseArch(ARMArch);
+ if (ArchKind == llvm::ARM::AK_INVALID)
+ // In case of generic Arch, i.e. "arm",
+ // extract arch from default cpu of the Triple
+ ArchKind = llvm::ARM::parseCPUArch(Triple.getARMCPUForArch(ARMArch));
+ } else {
+ // FIXME: horrible hack to get around the fact that Cortex-A7 is only an
+ // armv7k triple if it's actually been specified via "-arch armv7k".
+ ArchKind = (Arch == "armv7k" || Arch == "thumbv7k")
+ ? (unsigned)llvm::ARM::AK_ARMV7K
+ : llvm::ARM::parseCPUArch(CPU);
+ }
if (ArchKind == llvm::ARM::AK_INVALID)
return "";
- return llvm::ARMTargetParser::getSubArch(ArchKind);
+ return llvm::ARM::getSubArch(ArchKind);
}
void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs,
@@ -5986,6 +6656,9 @@ void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs,
}
mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) {
+ // Strictly speaking, mips32r2 and mips64r2 are NanLegacy-only since Nan2008
+ // was first introduced in Release 3. However, other compilers have
+ // traditionally allowed it for Release 2 so we should do the same.
return (NanEncoding)llvm::StringSwitch<int>(CPU)
.Case("mips1", NanLegacy)
.Case("mips2", NanLegacy)
@@ -5993,12 +6666,12 @@ mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) {
.Case("mips4", NanLegacy)
.Case("mips5", NanLegacy)
.Case("mips32", NanLegacy)
- .Case("mips32r2", NanLegacy)
+ .Case("mips32r2", NanLegacy | Nan2008)
.Case("mips32r3", NanLegacy | Nan2008)
.Case("mips32r5", NanLegacy | Nan2008)
.Case("mips32r6", Nan2008)
.Case("mips64", NanLegacy)
- .Case("mips64r2", NanLegacy)
+ .Case("mips64r2", NanLegacy | Nan2008)
.Case("mips64r3", NanLegacy | Nan2008)
.Case("mips64r5", NanLegacy | Nan2008)
.Case("mips64r6", Nan2008)
@@ -6031,7 +6704,7 @@ bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) {
}
bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
- StringRef ABIName, StringRef FloatABI) {
+ StringRef ABIName, mips::FloatABI FloatABI) {
if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies &&
Triple.getVendor() != llvm::Triple::MipsTechnologies)
return false;
@@ -6041,7 +6714,7 @@ bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
// FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is
// present.
- if (FloatABI == "soft")
+ if (FloatABI == mips::FloatABI::Soft)
return false;
return llvm::StringSwitch<bool>(CPUName)
@@ -6053,7 +6726,7 @@ bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
StringRef CPUName, StringRef ABIName,
- StringRef FloatABI) {
+ mips::FloatABI FloatABI) {
bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);
// FPXX shouldn't be used if -msingle-float is present.
@@ -6173,42 +6846,34 @@ void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
- const ToolChain::path_list &Paths = ToolChain.getFilePaths();
- for (const auto &Path : Paths)
- CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
- Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
- Args.AddAllArgs(CmdArgs, options::OPT_s);
- Args.AddAllArgs(CmdArgs, options::OPT_t);
- Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
- Args.AddAllArgs(CmdArgs, options::OPT_r);
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+ Args.AddAllArgs(CmdArgs,
+ {options::OPT_T_Group, options::OPT_e, options::OPT_s,
+ options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
- if (D.IsUsingLTO(Args))
- AddGoldPlugin(ToolChain, Args, CmdArgs);
+ if (D.isUsingLTO())
+ AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX())
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lcompiler_rt");
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles))
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -6228,11 +6893,11 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
SourceAction = SourceAction->getInputs()[0];
}
- // If -fno_integrated_as is used add -Q to the darwin assember driver to make
+ // If -fno-integrated-as is used add -Q to the darwin assember driver to make
// sure it runs its system assembler not clang's integrated assembler.
// Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as.
// FIXME: at run-time detect assembler capabilities or rely on version
- // information forwarded by -target-assembler-version (future)
+ // information forwarded by -target-assembler-version.
if (Args.hasArg(options::OPT_fno_integrated_as)) {
const llvm::Triple &T(getToolChain().getTriple());
if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
@@ -6276,7 +6941,7 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
// asm_final spec is empty.
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void darwin::MachOTool::anchor() {}
@@ -6334,15 +6999,34 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
options::OPT_fno_application_extension, false))
CmdArgs.push_back("-application_extension");
- // If we are using LTO, then automatically create a temporary file path for
- // the linker to use, so that it's lifetime will extend past a possible
- // dsymutil step.
- if (Version[0] >= 116 && D.IsUsingLTO(Args) && NeedsTempPath(Inputs)) {
- const char *TmpPath = C.getArgs().MakeArgString(
- D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
- C.addTempFile(TmpPath);
- CmdArgs.push_back("-object_path_lto");
- CmdArgs.push_back(TmpPath);
+ if (D.isUsingLTO()) {
+ // If we are using LTO, then automatically create a temporary file path for
+ // the linker to use, so that it's lifetime will extend past a possible
+ // dsymutil step.
+ if (Version[0] >= 116 && NeedsTempPath(Inputs)) {
+ const char *TmpPath = C.getArgs().MakeArgString(
+ D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
+ C.addTempFile(TmpPath);
+ CmdArgs.push_back("-object_path_lto");
+ CmdArgs.push_back(TmpPath);
+ }
+
+ // Use -lto_library option to specify the libLTO.dylib path. Try to find
+ // it in clang installed libraries. If not found, the option is not used
+ // and 'ld' will use its default mechanism to search for libLTO.dylib.
+ if (Version[0] >= 133) {
+ // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
+ StringRef P = llvm::sys::path::parent_path(D.getInstalledDir());
+ SmallString<128> LibLTOPath(P);
+ llvm::sys::path::append(LibLTOPath, "lib");
+ llvm::sys::path::append(LibLTOPath, "libLTO.dylib");
+ if (llvm::sys::fs::exists(LibLTOPath)) {
+ CmdArgs.push_back("-lto_library");
+ CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
+ } else {
+ D.Diag(diag::warn_drv_lto_libpath);
+ }
+ }
}
// Derived from the "link" spec.
@@ -6509,7 +7193,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("touch"));
CmdArgs.push_back(Output.getFilename());
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, None));
return;
}
@@ -6517,13 +7201,11 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// we follow suite for ease of comparison.
AddLinkArgs(C, Args, CmdArgs, Inputs);
- Args.AddAllArgs(CmdArgs, options::OPT_d_Flag);
- Args.AddAllArgs(CmdArgs, options::OPT_s);
- Args.AddAllArgs(CmdArgs, options::OPT_t);
- Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
- Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
- Args.AddLastArg(CmdArgs, options::OPT_e);
- Args.AddAllArgs(CmdArgs, options::OPT_r);
+ // It seems that the 'e' option is completely ignored for dynamic executables
+ // (the default), and with static executables, the last one wins, as expected.
+ Args.AddAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
+ options::OPT_Z_Flag, options::OPT_u_Group,
+ options::OPT_e, options::OPT_r});
// Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
// members of static archive libraries which implement Objective-C classes or
@@ -6534,8 +7216,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles))
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
// SafeStack requires its own runtime libraries
@@ -6567,12 +7248,11 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
InputFileList.push_back(II.getFilename());
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs))
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
addOpenMPRuntime(CmdArgs, getToolChain(), Args);
- if (isObjCRuntimeLinked(Args) && !Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (isObjCRuntimeLinked(Args) &&
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
// We use arclite library for both ARC and subscripting support.
getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);
@@ -6591,13 +7271,9 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_fnested_functions))
CmdArgs.push_back("-allow_stack_execute");
- // TODO: It would be nice to use addProfileRT() here, but darwin's compiler-rt
- // paths are different enough from other toolchains that this needs a fair
- // amount of refactoring done first.
getMachOToolChain().addProfileRTLibs(Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (getToolChain().getDriver().CCCIsCXX())
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
@@ -6607,8 +7283,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
// endfile_spec is empty.
}
@@ -6619,8 +7294,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
for (const Arg *A : Args.filtered(options::OPT_iframework))
CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
if (A->getValue() == StringRef("Accelerate")) {
CmdArgs.push_back("-framework");
@@ -6631,7 +7305,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
std::unique_ptr<Command> Cmd =
- llvm::make_unique<Command>(JA, *this, Exec, CmdArgs);
+ llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs);
Cmd->setInputFileList(std::move(InputFileList));
C.addCommand(std::move(Cmd));
}
@@ -6655,7 +7329,7 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
@@ -6675,7 +7349,7 @@ void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
@@ -6698,7 +7372,7 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -6718,7 +7392,7 @@ void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -6726,32 +7400,12 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- // FIXME: Find a real GCC, don't hard-code versions here
- std::string GCCLibPath = "/usr/gcc/4.5/lib/gcc/";
- const llvm::Triple &T = getToolChain().getTriple();
- std::string LibPath = "/usr/lib/";
- const llvm::Triple::ArchType Arch = T.getArch();
- switch (Arch) {
- case llvm::Triple::x86:
- GCCLibPath +=
- ("i386-" + T.getVendorName() + "-" + T.getOSName()).str() + "/4.5.2/";
- break;
- case llvm::Triple::x86_64:
- GCCLibPath += ("i386-" + T.getVendorName() + "-" + T.getOSName()).str();
- GCCLibPath += "/4.5.2/amd64/";
- LibPath += "amd64/";
- break;
- default:
- llvm_unreachable("Unsupported architecture");
- }
-
ArgStringList CmdArgs;
// Demangle C++ names in errors
CmdArgs.push_back("-C");
- if ((!Args.hasArg(options::OPT_nostdlib)) &&
- (!Args.hasArg(options::OPT_shared))) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
CmdArgs.push_back("-e");
CmdArgs.push_back("_start");
}
@@ -6765,7 +7419,8 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-shared");
} else {
CmdArgs.push_back("--dynamic-linker");
- CmdArgs.push_back(Args.MakeArgString(LibPath + "ld.so.1"));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("ld.so.1")));
}
}
@@ -6776,53 +7431,46 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
- if (!Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back(Args.MakeArgString(LibPath + "crt1.o"));
- CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
- CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
- CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
- } else {
- CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
- CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
- CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
- }
- if (getToolChain().getDriver().CCCIsCXX())
- CmdArgs.push_back(Args.MakeArgString(LibPath + "cxa_finalize.o"));
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
+
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("values-Xa.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
}
- CmdArgs.push_back(Args.MakeArgString("-L" + GCCLibPath));
+ getToolChain().AddFilePathLibArgs(Args, CmdArgs);
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
- Args.AddAllArgs(CmdArgs, options::OPT_r);
+ Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
+ options::OPT_e, options::OPT_r});
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (getToolChain().getDriver().CCCIsCXX())
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("-lc");
if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-lgcc");
- CmdArgs.push_back("-lc");
CmdArgs.push_back("-lm");
}
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
- CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtend.o"));
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
}
- CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o"));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
- addProfileRT(getToolChain(), Args, CmdArgs);
+ getToolChain().addProfileRTLibs(Args, CmdArgs);
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -6832,7 +7480,6 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
- bool NeedsKPIC = false;
switch (getToolChain().getArch()) {
case llvm::Triple::x86:
@@ -6847,16 +7494,21 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
break;
case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
+ case llvm::Triple::sparcel: {
CmdArgs.push_back("-32");
- NeedsKPIC = true;
+ std::string CPU = getCPUName(Args, getToolChain().getTriple());
+ CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+ AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
+ }
- case llvm::Triple::sparcv9:
+ case llvm::Triple::sparcv9: {
CmdArgs.push_back("-64");
- CmdArgs.push_back("-Av9a");
- NeedsKPIC = true;
+ std::string CPU = getCPUName(Args, getToolChain().getTriple());
+ CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+ AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
+ }
case llvm::Triple::mips64:
case llvm::Triple::mips64el: {
@@ -6872,7 +7524,7 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-EL");
- NeedsKPIC = true;
+ AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
}
@@ -6880,9 +7532,6 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
break;
}
- if (NeedsKPIC)
- addAssemblerKPIC(Args, CmdArgs);
-
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
@@ -6892,7 +7541,7 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -6916,8 +7565,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
else if (getToolChain().getArch() == llvm::Triple::mips64el)
CmdArgs.push_back("-EL");
- if ((!Args.hasArg(options::OPT_nostdlib)) &&
- (!Args.hasArg(options::OPT_shared))) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
CmdArgs.push_back("-e");
CmdArgs.push_back("__start");
}
@@ -6947,8 +7595,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back(
@@ -6970,18 +7617,13 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(
Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple + "/4.2.1"));
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
- Args.AddAllArgs(CmdArgs, options::OPT_s);
- Args.AddAllArgs(CmdArgs, options::OPT_t);
- Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
- Args.AddAllArgs(CmdArgs, options::OPT_r);
+ Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
+ options::OPT_e, options::OPT_s, options::OPT_t,
+ options::OPT_Z_Flag, options::OPT_r});
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
@@ -7011,8 +7653,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lgcc");
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared))
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
@@ -7022,7 +7663,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void bitrig::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -7042,7 +7683,7 @@ void bitrig::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void bitrig::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -7053,8 +7694,7 @@ void bitrig::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
- if ((!Args.hasArg(options::OPT_nostdlib)) &&
- (!Args.hasArg(options::OPT_shared))) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
CmdArgs.push_back("-e");
CmdArgs.push_back("__start");
}
@@ -7081,8 +7721,7 @@ void bitrig::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back(
@@ -7098,14 +7737,12 @@ void bitrig::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs,
+ {options::OPT_L, options::OPT_T_Group, options::OPT_e});
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
@@ -7145,8 +7782,7 @@ void bitrig::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString("-lclang_rt." + MyArch));
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared))
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
@@ -7156,7 +7792,7 @@ void bitrig::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -7169,14 +7805,19 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
// When building 32-bit code on FreeBSD/amd64, we have to explicitly
// instruct as in the base system to assemble 32-bit code.
- if (getToolChain().getArch() == llvm::Triple::x86)
+ switch (getToolChain().getArch()) {
+ default:
+ break;
+ case llvm::Triple::x86:
CmdArgs.push_back("--32");
- else if (getToolChain().getArch() == llvm::Triple::ppc)
+ break;
+ case llvm::Triple::ppc:
CmdArgs.push_back("-a32");
- else if (getToolChain().getArch() == llvm::Triple::mips ||
- getToolChain().getArch() == llvm::Triple::mipsel ||
- getToolChain().getArch() == llvm::Triple::mips64 ||
- getToolChain().getArch() == llvm::Triple::mips64el) {
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el: {
StringRef CPUName;
StringRef ABIName;
mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
@@ -7193,20 +7834,25 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-EL");
- addAssemblerKPIC(Args, CmdArgs);
- } else if (getToolChain().getArch() == llvm::Triple::arm ||
- getToolChain().getArch() == llvm::Triple::armeb ||
- getToolChain().getArch() == llvm::Triple::thumb ||
- getToolChain().getArch() == llvm::Triple::thumbeb) {
- const Driver &D = getToolChain().getDriver();
- const llvm::Triple &Triple = getToolChain().getTriple();
- StringRef FloatABI = arm::getARMFloatABI(D, Args, Triple);
+ if (Arg *A = Args.getLastArg(options::OPT_G)) {
+ StringRef v = A->getValue();
+ CmdArgs.push_back(Args.MakeArgString("-G" + v));
+ A->claim();
+ }
- if (FloatABI == "hard") {
+ AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
+ break;
+ }
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb: {
+ arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args);
+
+ if (ABI == arm::FloatABI::Hard)
CmdArgs.push_back("-mfpu=vfp");
- } else {
+ else
CmdArgs.push_back("-mfpu=softvfp");
- }
switch (getToolChain().getTriple().getEnvironment()) {
case llvm::Triple::GNUEABIHF:
@@ -7218,15 +7864,16 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
default:
CmdArgs.push_back("-matpcs");
}
- } else if (getToolChain().getArch() == llvm::Triple::sparc ||
- getToolChain().getArch() == llvm::Triple::sparcel ||
- getToolChain().getArch() == llvm::Triple::sparcv9) {
- if (getToolChain().getArch() == llvm::Triple::sparc)
- CmdArgs.push_back("-Av8plusa");
- else
- CmdArgs.push_back("-Av9a");
-
- addAssemblerKPIC(Args, CmdArgs);
+ break;
+ }
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::sparcv9: {
+ std::string CPU = getCPUName(Args, getToolChain().getTriple());
+ CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+ AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
+ break;
+ }
}
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
@@ -7238,7 +7885,7 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -7320,8 +7967,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
const char *crt1 = nullptr;
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
@@ -7348,9 +7994,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
- const ToolChain::path_list &Paths = ToolChain.getFilePaths();
- for (const auto &Path : Paths)
- CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_e);
Args.AddAllArgs(CmdArgs, options::OPT_s);
@@ -7358,14 +8002,13 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
- if (D.IsUsingLTO(Args))
- AddGoldPlugin(ToolChain, Args, CmdArgs);
+ if (D.isUsingLTO())
+ AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin);
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
addOpenMPRuntime(CmdArgs, ToolChain, Args);
if (D.CCCIsCXX()) {
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
@@ -7421,8 +8064,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (Args.hasArg(options::OPT_shared) || IsPIE)
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
else
@@ -7430,10 +8072,10 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
- addProfileRT(ToolChain, Args, CmdArgs);
+ ToolChain.addProfileRTLibs(Args, CmdArgs);
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -7482,21 +8124,26 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-EL");
- addAssemblerKPIC(Args, CmdArgs);
+ AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
}
case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
+ case llvm::Triple::sparcel: {
CmdArgs.push_back("-32");
- addAssemblerKPIC(Args, CmdArgs);
+ std::string CPU = getCPUName(Args, getToolChain().getTriple());
+ CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+ AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
+ }
- case llvm::Triple::sparcv9:
+ case llvm::Triple::sparcv9: {
CmdArgs.push_back("-64");
- CmdArgs.push_back("-Av9");
- addAssemblerKPIC(Args, CmdArgs);
+ std::string CPU = getCPUName(Args, getToolChain().getTriple());
+ CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+ AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
+ }
default:
break;
@@ -7511,7 +8158,7 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as")));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -7631,8 +8278,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
@@ -7680,8 +8326,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
addOpenMPRuntime(CmdArgs, getToolChain(), Args);
if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
@@ -7708,8 +8353,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared))
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
@@ -7719,10 +8363,10 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
}
- addProfileRT(getToolChain(), Args, CmdArgs);
+ getToolChain().addProfileRTLibs(Args, CmdArgs);
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -7732,8 +8376,16 @@ void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
claimNoWarnArgs(Args);
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
+ llvm::Triple Triple = llvm::Triple(TripleStr);
+
ArgStringList CmdArgs;
- bool NeedsKPIC = false;
+
+ llvm::Reloc::Model RelocationModel;
+ unsigned PICLevel;
+ bool IsPIE;
+ std::tie(RelocationModel, PICLevel, IsPIE) =
+ ParsePICArgs(getToolChain(), Triple, Args);
switch (getToolChain().getArch()) {
default:
@@ -7766,22 +8418,26 @@ void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mlittle-endian");
break;
case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
+ case llvm::Triple::sparcel: {
CmdArgs.push_back("-32");
- CmdArgs.push_back("-Av8plusa");
- NeedsKPIC = true;
+ std::string CPU = getCPUName(Args, getToolChain().getTriple());
+ CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+ AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
- case llvm::Triple::sparcv9:
+ }
+ case llvm::Triple::sparcv9: {
CmdArgs.push_back("-64");
- CmdArgs.push_back("-Av9a");
- NeedsKPIC = true;
+ std::string CPU = getCPUName(Args, getToolChain().getTriple());
+ CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+ AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
+ }
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb: {
- const llvm::Triple &Triple = getToolChain().getTriple();
- switch (Triple.getSubArch()) {
+ const llvm::Triple &Triple2 = getToolChain().getTriple();
+ switch (Triple2.getSubArch()) {
case llvm::Triple::ARMSubArch_v7:
CmdArgs.push_back("-mfpu=neon");
break;
@@ -7792,10 +8448,18 @@ void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
break;
}
- StringRef ARMFloatABI = tools::arm::getARMFloatABI(
- getToolChain().getDriver(), Args,
- llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args)));
- CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI));
+ switch (arm::getARMFloatABI(getToolChain(), Args)) {
+ case arm::FloatABI::Invalid: llvm_unreachable("must have an ABI!");
+ case arm::FloatABI::Soft:
+ CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=soft"));
+ break;
+ case arm::FloatABI::SoftFP:
+ CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=softfp"));
+ break;
+ case arm::FloatABI::Hard:
+ CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=hard"));
+ break;
+ }
Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
@@ -7828,18 +8492,7 @@ void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
// -mno-shared should be emitted unless -fpic, -fpie, -fPIC, -fPIE,
// or -mshared (not implemented) is in effect.
- bool IsPicOrPie = false;
- if (Arg *A = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
- options::OPT_fpic, options::OPT_fno_pic,
- options::OPT_fPIE, options::OPT_fno_PIE,
- options::OPT_fpie, options::OPT_fno_pie)) {
- if (A->getOption().matches(options::OPT_fPIC) ||
- A->getOption().matches(options::OPT_fpic) ||
- A->getOption().matches(options::OPT_fPIE) ||
- A->getOption().matches(options::OPT_fpie))
- IsPicOrPie = true;
- }
- if (!IsPicOrPie)
+ if (RelocationModel == llvm::Reloc::Static)
CmdArgs.push_back("-mno-shared");
// LLVM doesn't support -mplt yet and acts as if it is always given.
@@ -7858,13 +8511,13 @@ void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
}
// Add the last -mfp32/-mfpxx/-mfp64 or -mfpxx if it is enabled by default.
- StringRef MIPSFloatABI = getMipsFloatABI(getToolChain().getDriver(), Args);
if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
options::OPT_mfp64)) {
A->claim();
A->render(Args, CmdArgs);
- } else if (mips::shouldUseFPXX(Args, getToolChain().getTriple(), CPUName,
- ABIName, MIPSFloatABI))
+ } else if (mips::shouldUseFPXX(
+ Args, getToolChain().getTriple(), CPUName, ABIName,
+ getMipsFloatABI(getToolChain().getDriver(), Args)))
CmdArgs.push_back("-mfpxx");
// Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of
@@ -7901,7 +8554,7 @@ void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_modd_spreg,
options::OPT_mno_odd_spreg);
- NeedsKPIC = true;
+ AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
}
case llvm::Triple::systemz: {
@@ -7913,9 +8566,7 @@ void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (NeedsKPIC)
- addAssemblerKPIC(Args, CmdArgs);
-
+ Args.AddAllArgs(CmdArgs, options::OPT_I);
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
@@ -7925,7 +8576,7 @@ void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
// Handle the debug info splitting at object creation time if we're
// creating an object.
@@ -7938,7 +8589,7 @@ void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
static void AddLibgcc(const llvm::Triple &Triple, const Driver &D,
ArgStringList &CmdArgs, const ArgList &Args) {
- bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android;
+ bool isAndroid = Triple.isAndroid();
bool isCygMing = Triple.isOSCygMing();
bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) ||
Args.hasArg(options::OPT_static);
@@ -7974,7 +8625,7 @@ static std::string getLinuxDynamicLinker(const ArgList &Args,
const toolchains::Linux &ToolChain) {
const llvm::Triple::ArchType Arch = ToolChain.getArch();
- if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) {
+ if (ToolChain.getTriple().isAndroid()) {
if (ToolChain.getTriple().isArch64Bit())
return "/system/bin/linker64";
else
@@ -7988,33 +8639,30 @@ static std::string getLinuxDynamicLinker(const ArgList &Args,
return "/lib/ld-linux-aarch64_be.so.1";
else if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) {
if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF ||
- tools::arm::getARMFloatABI(ToolChain.getDriver(), Args, ToolChain.getTriple()) == "hard")
+ arm::getARMFloatABI(ToolChain, Args) == arm::FloatABI::Hard)
return "/lib/ld-linux-armhf.so.3";
else
return "/lib/ld-linux.so.3";
} else if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb) {
// TODO: check which dynamic linker name.
if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF ||
- tools::arm::getARMFloatABI(ToolChain.getDriver(), Args, ToolChain.getTriple()) == "hard")
+ arm::getARMFloatABI(ToolChain, Args) == arm::FloatABI::Hard)
return "/lib/ld-linux-armhf.so.3";
else
return "/lib/ld-linux.so.3";
} else if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel ||
Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el) {
- StringRef CPUName;
- StringRef ABIName;
- mips::getMipsCPUAndABI(Args, ToolChain.getTriple(), CPUName, ABIName);
- bool IsNaN2008 = mips::isNaN2008(Args, ToolChain.getTriple());
-
- StringRef LibDir = llvm::StringSwitch<llvm::StringRef>(ABIName)
- .Case("o32", "/lib")
- .Case("n32", "/lib32")
- .Case("n64", "/lib64")
- .Default("/lib");
+ std::string LibDir =
+ "/lib" + mips::getMipsABILibSuffix(Args, ToolChain.getTriple());
StringRef LibName;
+ bool IsNaN2008 = mips::isNaN2008(Args, ToolChain.getTriple());
if (mips::isUCLibc(Args))
LibName = IsNaN2008 ? "ld-uClibc-mipsn8.so.0" : "ld-uClibc.so.0";
- else
+ else if (!ToolChain.getTriple().hasEnvironment()) {
+ bool LE = (ToolChain.getTriple().getArch() == llvm::Triple::mipsel) ||
+ (ToolChain.getTriple().getArch() == llvm::Triple::mips64el);
+ LibName = LE ? "ld-musl-mipsel.so.1" : "ld-musl-mips.so.1";
+ } else
LibName = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1";
return (LibDir + "/" + LibName).str();
@@ -8029,7 +8677,7 @@ static std::string getLinuxDynamicLinker(const ArgList &Args,
return "/lib64/ld64.so.1";
return "/lib64/ld64.so.2";
} else if (Arch == llvm::Triple::systemz)
- return "/lib64/ld64.so.1";
+ return "/lib/ld64.so.1";
else if (Arch == llvm::Triple::sparcv9)
return "/lib64/ld-linux.so.2";
else if (Arch == llvm::Triple::x86_64 &&
@@ -8117,12 +8765,18 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const toolchains::Linux &ToolChain =
static_cast<const toolchains::Linux &>(getToolChain());
const Driver &D = ToolChain.getDriver();
+
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
+ llvm::Triple Triple = llvm::Triple(TripleStr);
+
const llvm::Triple::ArchType Arch = ToolChain.getArch();
- const bool isAndroid =
- ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
+ const bool isAndroid = ToolChain.getTriple().isAndroid();
const bool IsPIE =
!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_static) &&
(Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
+ const bool HasCRTBeginEndFiles =
+ ToolChain.getTriple().hasEnvironment() ||
+ (ToolChain.getTriple().getVendor() != llvm::Triple::MipsTechnologies);
ArgStringList CmdArgs;
@@ -8134,6 +8788,14 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
+ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
+ if (llvm::sys::path::filename(Exec) == "lld") {
+ CmdArgs.push_back("-flavor");
+ CmdArgs.push_back("old-gnu");
+ CmdArgs.push_back("-target");
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString()));
+ }
+
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
@@ -8147,9 +8809,7 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-s");
if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb)
- arm::appendEBLinkFlags(
- Args, CmdArgs,
- llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args)));
+ arm::appendEBLinkFlags(Args, CmdArgs, Triple);
for (const auto &Opt : ToolChain.ExtraOpts)
CmdArgs.push_back(Opt.c_str());
@@ -8183,8 +8843,7 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!isAndroid) {
const char *crt1 = nullptr;
if (!Args.hasArg(options::OPT_shared)) {
@@ -8210,7 +8869,9 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
else
crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+
+ if (HasCRTBeginEndFiles)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
// Add crtfastmath.o if available and fast math is enabled.
ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs);
@@ -8219,13 +8880,10 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_u);
- const ToolChain::path_list &Paths = ToolChain.getFilePaths();
-
- for (const auto &Path : Paths)
- CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- if (D.IsUsingLTO(Args))
- AddGoldPlugin(ToolChain, Args, CmdArgs);
+ if (D.isUsingLTO())
+ AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin);
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
@@ -8233,10 +8891,10 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
// The profile runtime also needs access to system libraries.
- addProfileRT(getToolChain(), Args, CmdArgs);
+ getToolChain().addProfileRTLibs(Args, CmdArgs);
- if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX() &&
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
!Args.hasArg(options::OPT_static);
if (OnlyLibstdcxxStatic)
@@ -8309,14 +8967,14 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
else
crtend = isAndroid ? "crtend_android.o" : "crtend.o";
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
+ if (HasCRTBeginEndFiles)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
if (!isAndroid)
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
}
- C.addCommand(
- llvm::make_unique<Command>(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
// NaCl ARM assembly (inline or standalone) can be written with a set of macros
@@ -8328,9 +8986,9 @@ void nacltools::AssemblerARM::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const toolchains::NaCl_TC &ToolChain =
- static_cast<const toolchains::NaCl_TC &>(getToolChain());
- InputInfo NaClMacros(ToolChain.GetNaClArmMacrosPath(), types::TY_PP_Asm,
+ const toolchains::NaClToolChain &ToolChain =
+ static_cast<const toolchains::NaClToolChain &>(getToolChain());
+ InputInfo NaClMacros(types::TY_PP_Asm, ToolChain.GetNaClArmMacrosPath(),
"nacl-arm-macros.s");
InputInfoList NewInputs;
NewInputs.push_back(NaClMacros);
@@ -8349,8 +9007,8 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const ArgList &Args,
const char *LinkingOutput) const {
- const toolchains::NaCl_TC &ToolChain =
- static_cast<const toolchains::NaCl_TC &>(getToolChain());
+ const toolchains::NaClToolChain &ToolChain =
+ static_cast<const toolchains::NaClToolChain &>(getToolChain());
const Driver &D = ToolChain.getDriver();
const llvm::Triple::ArchType Arch = ToolChain.getArch();
const bool IsStatic =
@@ -8375,8 +9033,8 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("-s");
- // NaCl_TC doesn't have ExtraOpts like Linux; the only relevant flag from
- // there is --build-id, which we do want.
+ // NaClToolChain doesn't have ExtraOpts like Linux; the only relevant flag
+ // from there is --build-id, which we do want.
CmdArgs.push_back("--build-id");
if (!IsStatic)
@@ -8402,8 +9060,7 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared))
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
@@ -8421,18 +9078,15 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_u);
- const ToolChain::path_list &Paths = ToolChain.getFilePaths();
-
- for (const auto &Path : Paths)
- CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
- if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX() &&
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
bool OnlyLibstdcxxStatic =
Args.hasArg(options::OPT_static_libstdcxx) && !IsStatic;
if (OnlyLibstdcxxStatic)
@@ -8491,8 +9145,8 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- C.addCommand(
- llvm::make_unique<Command>(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
+ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void minix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -8512,7 +9166,7 @@ void minix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -8530,8 +9184,7 @@ void minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
CmdArgs.push_back(
@@ -8539,24 +9192,21 @@ void minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
}
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs,
+ {options::OPT_L, options::OPT_T_Group, options::OPT_e});
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
- addProfileRT(getToolChain(), Args, CmdArgs);
+ getToolChain().addProfileRTLibs(Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lc");
@@ -8567,7 +9217,7 @@ void minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
/// DragonFly Tools
@@ -8596,7 +9246,7 @@ void dragonfly::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -8606,7 +9256,6 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
- bool UseGCC47 = llvm::sys::fs::exists("/usr/lib/gcc47");
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
@@ -8623,7 +9272,8 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
}
- CmdArgs.push_back("--hash-style=both");
+ CmdArgs.push_back("--hash-style=gnu");
+ CmdArgs.push_back("--enable-new-dtags");
}
// When building 32-bit code on DragonFly/pc64, we have to explicitly
@@ -8640,8 +9290,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back(
@@ -8664,29 +9313,17 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
}
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs,
+ {options::OPT_L, options::OPT_T_Group, options::OPT_e});
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
- // FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of
- // rpaths
- if (UseGCC47)
- CmdArgs.push_back("-L/usr/lib/gcc47");
- else
- CmdArgs.push_back("-L/usr/lib/gcc44");
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ CmdArgs.push_back("-L/usr/lib/gcc50");
if (!Args.hasArg(options::OPT_static)) {
- if (UseGCC47) {
- CmdArgs.push_back("-rpath");
- CmdArgs.push_back("/usr/lib/gcc47");
- } else {
- CmdArgs.push_back("-rpath");
- CmdArgs.push_back("/usr/lib/gcc44");
- }
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back("/usr/lib/gcc50");
}
if (D.CCCIsCXX()) {
@@ -8701,34 +9338,25 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lc");
}
- if (UseGCC47) {
- if (Args.hasArg(options::OPT_static) ||
- Args.hasArg(options::OPT_static_libgcc)) {
+ if (Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_static_libgcc)) {
CmdArgs.push_back("-lgcc");
CmdArgs.push_back("-lgcc_eh");
- } else {
- if (Args.hasArg(options::OPT_shared_libgcc)) {
+ } else {
+ if (Args.hasArg(options::OPT_shared_libgcc)) {
CmdArgs.push_back("-lgcc_pic");
if (!Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-lgcc");
- } else {
+ } else {
CmdArgs.push_back("-lgcc");
CmdArgs.push_back("--as-needed");
CmdArgs.push_back("-lgcc_pic");
CmdArgs.push_back("--no-as-needed");
- }
- }
- } else {
- if (Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back("-lgcc_pic");
- } else {
- CmdArgs.push_back("-lgcc");
}
}
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
@@ -8738,10 +9366,10 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
}
- addProfileRT(getToolChain(), Args, CmdArgs);
+ getToolChain().addProfileRTLibs(Args, CmdArgs);
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
// Try to find Exe from a Visual Studio distribution. This first tries to find
@@ -8777,8 +9405,8 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(
Args.MakeArgString(std::string("-out:") + Output.getFilename()));
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles) && !C.getDriver().IsCLMode())
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
+ !C.getDriver().IsCLMode())
CmdArgs.push_back("-defaultlib:libcmt");
if (!llvm::sys::Process::GetEnv("LIB")) {
@@ -8806,6 +9434,13 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
CmdArgs.push_back(
Args.MakeArgString(std::string("-libpath:") + LibDir.c_str()));
+
+ if (MSVC.useUniversalCRT(VisualStudioDir)) {
+ std::string UniversalCRTLibPath;
+ if (MSVC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
+ CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
+ UniversalCRTLibPath.c_str()));
+ }
}
std::string WindowsSdkLibPath;
@@ -8816,7 +9451,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-nologo");
- if (Args.hasArg(options::OPT_g_Group))
+ if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))
CmdArgs.push_back("-debug");
bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
@@ -8833,28 +9468,42 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
if (Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
- static const char *CompilerRTComponents[] = {
- "asan_dynamic", "asan_dynamic_runtime_thunk",
- };
- for (const auto &Component : CompilerRTComponents)
- CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component)));
+ for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
// Make sure the dynamic runtime thunk is not optimized out at link time
// to ensure proper SEH handling.
CmdArgs.push_back(Args.MakeArgString("-include:___asan_seh_interceptor"));
} else if (DLL) {
- CmdArgs.push_back(
- Args.MakeArgString(getCompilerRT(TC, "asan_dll_thunk")));
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
} else {
- static const char *CompilerRTComponents[] = {
- "asan", "asan_cxx",
- };
- for (const auto &Component : CompilerRTComponents)
- CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component)));
+ for (const auto &Lib : {"asan", "asan_cxx"})
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
}
}
Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
+ if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
+ options::OPT_fno_openmp, false)) {
+ CmdArgs.push_back("-nodefaultlib:vcomp.lib");
+ CmdArgs.push_back("-nodefaultlib:vcompd.lib");
+ CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
+ TC.getDriver().Dir + "/../lib"));
+ switch (getOpenMPRuntime(getToolChain(), Args)) {
+ case OMPRT_OMP:
+ CmdArgs.push_back("-defaultlib:libomp.lib");
+ break;
+ case OMPRT_IOMP5:
+ CmdArgs.push_back("-defaultlib:libiomp5md.lib");
+ break;
+ case OMPRT_GOMP:
+ break;
+ case OMPRT_Unknown:
+ // Already diagnosed.
+ break;
+ }
+ }
+
// Add filenames, libraries, and other linker inputs.
for (const auto &Input : Inputs) {
if (Input.isFilename()) {
@@ -8881,6 +9530,8 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
A.renderAsInput(Args, CmdArgs);
}
+ TC.addProfileRTLibs(Args, CmdArgs);
+
// We need to special case some linker paths. In the case of lld, we need to
// translate 'lld' into 'lld-link', and in the case of the regular msvc
// linker, we need to use a special search algorithm.
@@ -8902,7 +9553,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec = Args.MakeArgString(linkPath);
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void visualstudio::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -8926,21 +9577,34 @@ std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
// any flag accepted by clang-cl.
// These are spelled the same way in clang and cl.exe,.
- Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
- Args.AddAllArgs(CmdArgs, options::OPT_I);
+ Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I});
// Optimization level.
+ if (Arg *A = Args.getLastArg(options::OPT_fbuiltin, options::OPT_fno_builtin))
+ CmdArgs.push_back(A->getOption().getID() == options::OPT_fbuiltin ? "/Oi"
+ : "/Oi-");
if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
if (A->getOption().getID() == options::OPT_O0) {
CmdArgs.push_back("/Od");
} else {
+ CmdArgs.push_back("/Og");
+
StringRef OptLevel = A->getValue();
- if (OptLevel == "1" || OptLevel == "2" || OptLevel == "s")
- A->render(Args, CmdArgs);
- else if (OptLevel == "3")
- CmdArgs.push_back("/Ox");
+ if (OptLevel == "s" || OptLevel == "z")
+ CmdArgs.push_back("/Os");
+ else
+ CmdArgs.push_back("/Ot");
+
+ CmdArgs.push_back("/Ob2");
}
}
+ if (Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
+ options::OPT_fno_omit_frame_pointer))
+ CmdArgs.push_back(A->getOption().getID() == options::OPT_fomit_frame_pointer
+ ? "/Oy"
+ : "/Oy-");
+ if (!Args.hasArg(options::OPT_fwritable_strings))
+ CmdArgs.push_back("/GF");
// Flags for which clang-cl has an alias.
// FIXME: How can we ensure this stays in sync with relevant clang-cl options?
@@ -8959,7 +9623,8 @@ std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
if (Args.hasArg(options::OPT_fsyntax_only))
CmdArgs.push_back("/Zs");
- if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only))
+ if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only,
+ options::OPT__SLASH_Z7))
CmdArgs.push_back("/Z7");
std::vector<std::string> Includes =
@@ -8971,6 +9636,7 @@ std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);
+ Args.AddAllArgs(CmdArgs, options::OPT__SLASH_Zl);
// The order of these flags is relevant, so pick the last one.
if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
@@ -8997,7 +9663,7 @@ std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe",
D.getClangProgramPath());
return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
- CmdArgs);
+ CmdArgs, Inputs);
}
/// MinGW Tools
@@ -9024,7 +9690,7 @@ void MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
if (Args.hasArg(options::OPT_gsplit_dwarf))
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
@@ -9037,8 +9703,24 @@ void MinGW::Linker::AddLibGCC(const ArgList &Args,
CmdArgs.push_back("-lmingwthrd");
CmdArgs.push_back("-lmingw32");
- // Add libgcc or compiler-rt.
- AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args);
+ // Make use of compiler-rt if --rtlib option is used
+ ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args);
+ if (RLT == ToolChain::RLT_Libgcc) {
+ bool Static = Args.hasArg(options::OPT_static_libgcc) ||
+ Args.hasArg(options::OPT_static);
+ bool Shared = Args.hasArg(options::OPT_shared);
+ bool CXX = getToolChain().getDriver().CCCIsCXX();
+
+ if (Static || (!CXX && !Shared)) {
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lgcc_eh");
+ } else {
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("-lgcc");
+ }
+ } else {
+ AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args);
+ }
CmdArgs.push_back("-lmoldname");
CmdArgs.push_back("-lmingwex");
@@ -9068,6 +9750,8 @@ void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (LinkerName.equals_lower("lld")) {
CmdArgs.push_back("-flavor");
CmdArgs.push_back("gnu");
+ } else if (!LinkerName.equals_lower("ld")) {
+ D.Diag(diag::err_drv_unsupported_linker) << LinkerName;
}
if (!D.SysRoot.empty())
@@ -9121,8 +9805,7 @@ void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
Args.AddLastArg(CmdArgs, options::OPT_Z_Flag);
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) {
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o")));
} else {
@@ -9137,18 +9820,15 @@ void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
- const ToolChain::path_list Paths = TC.getFilePaths();
- for (const auto &Path : Paths)
- CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
-
+ TC.AddFilePathLibArgs(Args, CmdArgs);
AddLinkerInputs(TC, Inputs, Args, CmdArgs);
// TODO: Add ASan stuff here
// TODO: Add profile stuff here
- if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX() &&
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
!Args.hasArg(options::OPT_static);
if (OnlyLibstdcxxStatic)
@@ -9204,7 +9884,7 @@ void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
const char *Exec = Args.MakeArgString(TC.GetProgramPath(LinkerName.data()));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
/// XCore Tools
@@ -9240,7 +9920,7 @@ void XCore::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -9268,7 +9948,7 @@ void XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void CrossWindows::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -9307,7 +9987,7 @@ void CrossWindows::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const std::string Assembler = TC.GetProgramPath("as");
Exec = Args.MakeArgString(Assembler);
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void CrossWindows::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -9386,8 +10066,7 @@ void CrossWindows::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
: "-Bdynamic");
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
CmdArgs.push_back("--entry");
CmdArgs.push_back(Args.MakeArgString(EntryPoint));
}
@@ -9409,8 +10088,7 @@ void CrossWindows::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(ImpLib));
}
- if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
const std::string CRTPath(D.SysRoot + "/usr/lib/");
const char *CRTBegin;
@@ -9420,11 +10098,7 @@ void CrossWindows::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
-
- const auto &Paths = TC.getFilePaths();
- for (const auto &Path : Paths)
- CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
-
+ TC.AddFilePathLibArgs(Args, CmdArgs);
AddLinkerInputs(TC, Inputs, Args, CmdArgs);
if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
@@ -9446,10 +10120,25 @@ void CrossWindows::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- const std::string Linker = TC.GetProgramPath("ld");
- Exec = Args.MakeArgString(Linker);
+ if (TC.getSanitizerArgs().needsAsanRt()) {
+ // TODO handle /MT[d] /MD[d]
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
+ } else {
+ for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
+ CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
+ // Make sure the dynamic runtime thunk is not optimized out at link time
+ // to ensure proper SEH handling.
+ CmdArgs.push_back(Args.MakeArgString("--undefined"));
+ CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86
+ ? "___asan_seh_interceptor"
+ : "__asan_seh_interceptor"));
+ }
+ }
+
+ Exec = Args.MakeArgString(TC.GetLinkerPath());
- C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -9457,35 +10146,46 @@ void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
-
ArgStringList CmdArgs;
-
assert(Inputs.size() == 1);
const InputInfo &II = Inputs[0];
- assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
- assert(Output.getType() == types::TY_PP_Asm); // Require preprocessed asm.
-
- // Append all -I, -iquote, -isystem paths.
- Args.AddAllArgs(CmdArgs, options::OPT_clang_i_Group);
- // These are spelled the same way in clang and moviCompile.
- Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
+ assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX ||
+ II.getType() == types::TY_PP_CXX);
- CmdArgs.push_back("-DMYRIAD2");
+ if (JA.getKind() == Action::PreprocessJobClass) {
+ Args.ClaimAllArgs();
+ CmdArgs.push_back("-E");
+ } else {
+ assert(Output.getType() == types::TY_PP_Asm); // Require preprocessed asm.
+ CmdArgs.push_back("-S");
+ CmdArgs.push_back("-fno-exceptions"); // Always do this even if unspecified.
+ }
CmdArgs.push_back("-mcpu=myriad2");
- CmdArgs.push_back("-S");
-
- // Any -O option passes through without translation. What about -Ofast ?
- if (Arg *A = Args.getLastArg(options::OPT_O_Group))
- A->render(Args, CmdArgs);
+ CmdArgs.push_back("-DMYRIAD2");
- if (Args.hasFlag(options::OPT_ffunction_sections,
- options::OPT_fno_function_sections)) {
- CmdArgs.push_back("-ffunction-sections");
+ // Append all -I, -iquote, -isystem paths, defines/undefines,
+ // 'f' flags, optimize flags, and warning options.
+ // These are spelled the same way in clang and moviCompile.
+ Args.AddAllArgs(CmdArgs, {options::OPT_I_Group, options::OPT_clang_i_Group,
+ options::OPT_std_EQ, options::OPT_D, options::OPT_U,
+ options::OPT_f_Group, options::OPT_f_clang_Group,
+ options::OPT_g_Group, options::OPT_M_Group,
+ options::OPT_O_Group, options::OPT_W_Group});
+
+ // If we're producing a dependency file, and assembly is the final action,
+ // then the name of the target in the dependency file should be the '.o'
+ // file, not the '.s' file produced by this step. For example, instead of
+ // /tmp/mumble.s: mumble.c .../someheader.h
+ // the filename on the lefthand side should be "mumble.o"
+ if (Args.getLastArg(options::OPT_MF) && !Args.getLastArg(options::OPT_MT) &&
+ C.getActions().size() == 1 &&
+ C.getActions()[0]->getKind() == Action::AssembleJobClass) {
+ Arg *A = Args.getLastArg(options::OPT_o);
+ if (A) {
+ CmdArgs.push_back("-MT");
+ CmdArgs.push_back(Args.MakeArgString(A->getValue()));
+ }
}
- if (Args.hasArg(options::OPT_fno_inline_functions))
- CmdArgs.push_back("-fno-inline-functions");
-
- CmdArgs.push_back("-fno-exceptions"); // Always do this even if unspecified.
CmdArgs.push_back(II.getFilename());
CmdArgs.push_back("-o");
@@ -9493,8 +10193,8 @@ void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
std::string Exec =
Args.MakeArgString(getToolChain().GetProgramPath("moviCompile"));
- C.addCommand(
- llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
+ CmdArgs, Inputs));
}
void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -9510,13 +10210,14 @@ void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.getType() == types::TY_Object);
CmdArgs.push_back("-no6thSlotCompression");
- CmdArgs.push_back("-cv:myriad2"); // Chip Version ?
+ CmdArgs.push_back("-cv:myriad2"); // Chip Version
CmdArgs.push_back("-noSPrefixing");
CmdArgs.push_back("-a"); // Mystery option.
- for (auto Arg : Args.filtered(options::OPT_I)) {
- Arg->claim();
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+ for (const Arg *A : Args.filtered(options::OPT_I, options::OPT_isystem)) {
+ A->claim();
CmdArgs.push_back(
- Args.MakeArgString(std::string("-i:") + Arg->getValue(0)));
+ Args.MakeArgString(std::string("-i:") + A->getValue(0)));
}
CmdArgs.push_back("-elf"); // Output format.
CmdArgs.push_back(II.getFilename());
@@ -9525,6 +10226,378 @@ void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
std::string Exec =
Args.MakeArgString(getToolChain().GetProgramPath("moviAsm"));
- C.addCommand(
- llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
+ CmdArgs, Inputs));
+}
+
+void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const auto &TC =
+ static_cast<const toolchains::MyriadToolChain &>(getToolChain());
+ const llvm::Triple &T = TC.getTriple();
+ ArgStringList CmdArgs;
+ bool UseStartfiles =
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
+ bool UseDefaultLibs =
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
+
+ if (T.getArch() == llvm::Triple::sparc)
+ CmdArgs.push_back("-EB");
+ else // SHAVE assumes little-endian, and sparcel is expressly so.
+ CmdArgs.push_back("-EL");
+
+ // The remaining logic is mostly like gnutools::Linker::ConstructJob,
+ // but we never pass through a --sysroot option and various other bits.
+ // For example, there are no sanitizers (yet) nor gold linker.
+
+ // Eat some arguments that may be present but have no effect.
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ Args.ClaimAllArgs(options::OPT_w);
+ Args.ClaimAllArgs(options::OPT_static_libgcc);
+
+ if (Args.hasArg(options::OPT_s)) // Pass the 'strip' option.
+ CmdArgs.push_back("-s");
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ if (UseStartfiles) {
+ // If you want startfiles, it means you want the builtin crti and crtbegin,
+ // but not crt0. Myriad link commands provide their own crt0.o as needed.
+ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
+ }
+
+ Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
+ options::OPT_e, options::OPT_s, options::OPT_t,
+ options::OPT_Z_Flag, options::OPT_r});
+
+ TC.AddFilePathLibArgs(Args, CmdArgs);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (UseDefaultLibs) {
+ if (C.getDriver().CCCIsCXX())
+ CmdArgs.push_back("-lstdc++");
+ if (T.getOS() == llvm::Triple::RTEMS) {
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back("-lc");
+ // You must provide your own "-L" option to enable finding these.
+ CmdArgs.push_back("-lrtemscpu");
+ CmdArgs.push_back("-lrtemsbsp");
+ CmdArgs.push_back("--end-group");
+ } else {
+ CmdArgs.push_back("-lc");
+ }
+ CmdArgs.push_back("-lgcc");
+ }
+ if (UseStartfiles) {
+ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
+ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtn.o")));
+ }
+
+ std::string Exec =
+ Args.MakeArgString(TC.GetProgramPath("sparc-myriad-elf-ld"));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
+ CmdArgs, Inputs));
+}
+
+void PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
+ ArgStringList CmdArgs;
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ assert(Inputs.size() == 1 && "Unexpected number of inputs.");
+ const InputInfo &Input = Inputs[0];
+ assert(Input.isFilename() && "Invalid input.");
+ CmdArgs.push_back(Input.getFilename());
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("ps4-as"));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+}
+
+static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) {
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+ if (SanArgs.needsUbsanRt()) {
+ CmdArgs.push_back("-lSceDbgUBSanitizer_stub_weak");
+ }
+ if (SanArgs.needsAsanRt()) {
+ CmdArgs.push_back("-lSceDbgAddressSanitizer_stub_weak");
+ }
+}
+
+static void ConstructPS4LinkJob(const Tool &T, Compilation &C,
+ const JobAction &JA, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) {
+ const toolchains::FreeBSD &ToolChain =
+ static_cast<const toolchains::FreeBSD &>(T.getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ if (Args.hasArg(options::OPT_pie))
+ CmdArgs.push_back("-pie");
+
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("--oformat=so");
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ AddPS4SanitizerArgs(ToolChain, CmdArgs);
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
+ CmdArgs.push_back("--no-demangle");
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+ if (Args.hasArg(options::OPT_pthread)) {
+ CmdArgs.push_back("-lpthread");
+ }
+
+ const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("ps4-ld"));
+
+ C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs));
+}
+
+static void ConstructGoldLinkJob(const Tool &T, Compilation &C,
+ const JobAction &JA, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) {
+ const toolchains::FreeBSD &ToolChain =
+ static_cast<const toolchains::FreeBSD &>(T.getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ if (Args.hasArg(options::OPT_pie))
+ CmdArgs.push_back("-pie");
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ CmdArgs.push_back("--eh-frame-hdr");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-Bshareable");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/libexec/ld-elf.so.1");
+ }
+ CmdArgs.push_back("--enable-new-dtags");
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ AddPS4SanitizerArgs(ToolChain, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ const char *crt1 = nullptr;
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ crt1 = "gcrt1.o";
+ else if (Args.hasArg(options::OPT_pie))
+ crt1 = "Scrt1.o";
+ else
+ crt1 = "crt1.o";
+ }
+ if (crt1)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+
+ const char *crtbegin = nullptr;
+ if (Args.hasArg(options::OPT_static))
+ crtbegin = "crtbeginT.o";
+ else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ crtbegin = "crtbeginS.o";
+ else
+ crtbegin = "crtbegin.o";
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
+ CmdArgs.push_back("--no-demangle");
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ // For PS4, we always want to pass libm, libstdc++ and libkernel
+ // libraries for both C and C++ compilations.
+ CmdArgs.push_back("-lkernel");
+ if (D.CCCIsCXX()) {
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lm_p");
+ else
+ CmdArgs.push_back("-lm");
+ }
+ // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
+ // the default system libraries. Just mimic this for now.
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lgcc_p");
+ else
+ CmdArgs.push_back("-lcompiler_rt");
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lstdc++");
+ } else if (Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back("-lgcc_eh_p");
+ } else {
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lstdc++");
+ CmdArgs.push_back("--no-as-needed");
+ }
+
+ if (Args.hasArg(options::OPT_pthread)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lpthread_p");
+ else
+ CmdArgs.push_back("-lpthread");
+ }
+
+ if (Args.hasArg(options::OPT_pg)) {
+ if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lc");
+ else {
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back("-lc_p");
+ CmdArgs.push_back("-lpthread_p");
+ CmdArgs.push_back("--end-group");
+ } else {
+ CmdArgs.push_back("-lc_p");
+ }
+ }
+ CmdArgs.push_back("-lgcc_p");
+ } else {
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("--end-group");
+ } else {
+ CmdArgs.push_back("-lc");
+ }
+ CmdArgs.push_back("-lcompiler_rt");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lstdc++");
+ } else if (Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back("-lgcc_eh_p");
+ } else {
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lstdc++");
+ CmdArgs.push_back("--no-as-needed");
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+
+ const char *Exec =
+#ifdef LLVM_ON_WIN32
+ Args.MakeArgString(ToolChain.GetProgramPath("ps4-ld.gold"));
+#else
+ Args.MakeArgString(ToolChain.GetProgramPath("ps4-ld"));
+#endif
+
+ C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs));
+}
+
+void PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const toolchains::FreeBSD &ToolChain =
+ static_cast<const toolchains::FreeBSD &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ bool PS4Linker;
+ StringRef LinkerOptName;
+ if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
+ LinkerOptName = A->getValue();
+ if (LinkerOptName != "ps4" && LinkerOptName != "gold")
+ D.Diag(diag::err_drv_unsupported_linker) << LinkerOptName;
+ }
+
+ if (LinkerOptName == "gold")
+ PS4Linker = false;
+ else if (LinkerOptName == "ps4")
+ PS4Linker = true;
+ else
+ PS4Linker = !Args.hasArg(options::OPT_shared);
+
+ if (PS4Linker)
+ ConstructPS4LinkJob(*this, C, JA, Output, Inputs, Args, LinkingOutput);
+ else
+ ConstructGoldLinkJob(*this, C, JA, Output, Inputs, Args, LinkingOutput);
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h
index 651ddc8..2b137f4 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Tools.h
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h
@@ -14,19 +14,20 @@
#include "clang/Driver/Tool.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
+#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/Compiler.h"
namespace clang {
- class ObjCRuntime;
+class ObjCRuntime;
namespace driver {
- class Command;
- class Driver;
+class Command;
+class Driver;
namespace toolchains {
- class MachO;
+class MachO;
}
namespace tools {
@@ -37,162 +38,167 @@ class Compiler;
using llvm::opt::ArgStringList;
-SmallString<128> getCompilerRT(const ToolChain &TC, StringRef Component,
- bool Shared = false);
-
- /// \brief Clang compiler tool.
- class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
- public:
- static const char *getBaseInputName(const llvm::opt::ArgList &Args,
- const InputInfo &Input);
- static const char *getBaseInputStem(const llvm::opt::ArgList &Args,
- const InputInfoList &Inputs);
- static const char *getDependencyFileName(const llvm::opt::ArgList &Args,
- const InputInfoList &Inputs);
-
- private:
- void AddPreprocessingOptions(Compilation &C, const JobAction &JA,
- const Driver &D,
- const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs,
- const InputInfo &Output,
- const InputInfoList &Inputs) const;
-
- void AddAArch64TargetArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const;
- void AddARMTargetArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs,
- bool KernelOrKext) const;
- void AddARM64TargetArgs(const llvm::opt::ArgList &Args,
+SmallString<128> getCompilerRT(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ StringRef Component, bool Shared = false);
+
+/// \brief Clang compiler tool.
+class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
+public:
+ static const char *getBaseInputName(const llvm::opt::ArgList &Args,
+ const InputInfo &Input);
+ static const char *getBaseInputStem(const llvm::opt::ArgList &Args,
+ const InputInfoList &Inputs);
+ static const char *getDependencyFileName(const llvm::opt::ArgList &Args,
+ const InputInfoList &Inputs);
+
+private:
+ void AddPreprocessingOptions(Compilation &C, const JobAction &JA,
+ const Driver &D, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ToolChain *AuxToolChain) const;
+
+ void AddAArch64TargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
- void AddMIPSTargetArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const;
- void AddPPCTargetArgs(const llvm::opt::ArgList &Args,
+ void AddARMTargetArgs(const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ bool KernelOrKext) const;
+ void AddARM64TargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
- void AddR600TargetArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const;
- void AddSparcTargetArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const;
- void AddSystemZTargetArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const;
- void AddX86TargetArgs(const llvm::opt::ArgList &Args,
+ void AddMIPSTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddPPCTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddR600TargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddSparcTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
- void AddHexagonTargetArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const;
+ void AddSystemZTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddX86TargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddHexagonTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddWebAssemblyTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
- enum RewriteKind { RK_None, RK_Fragile, RK_NonFragile };
+ enum RewriteKind { RK_None, RK_Fragile, RK_NonFragile };
- ObjCRuntime AddObjCRuntimeArgs(const llvm::opt::ArgList &args,
- llvm::opt::ArgStringList &cmdArgs,
- RewriteKind rewrite) const;
+ ObjCRuntime AddObjCRuntimeArgs(const llvm::opt::ArgList &args,
+ llvm::opt::ArgStringList &cmdArgs,
+ RewriteKind rewrite) const;
- void AddClangCLArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const;
+ void AddClangCLArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ enum CodeGenOptions::DebugInfoKind *DebugInfoKind,
+ bool *EmitCodeView) const;
- visualstudio::Compiler *getCLFallback() const;
-
- mutable std::unique_ptr<visualstudio::Compiler> CLFallback;
-
- public:
- // CAUTION! The first constructor argument ("clang") is not arbitrary,
- // as it is for other tools. Some operations on a Tool actually test
- // whether that tool is Clang based on the Tool's Name as a string.
- Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC, RF_Full) {}
-
- bool hasGoodDiagnostics() const override { return true; }
- bool hasIntegratedAssembler() const override { return true; }
- bool hasIntegratedCPP() const override { return true; }
- bool canEmitIR() const override { return true; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
-
- /// \brief Clang integrated assembler tool.
- class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool {
- public:
- ClangAs(const ToolChain &TC) : Tool("clang::as",
- "clang integrated assembler", TC,
- RF_Full) {}
- void AddMIPSTargetArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const;
- bool hasGoodDiagnostics() const override { return true; }
- bool hasIntegratedAssembler() const override { return false; }
- bool hasIntegratedCPP() const override { return false; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
-
- /// \brief Base class for all GNU tools that provide the same behavior when
- /// it comes to response files support
- class LLVM_LIBRARY_VISIBILITY GnuTool : public Tool {
- virtual void anchor();
-
- public:
- GnuTool(const char *Name, const char *ShortName, const ToolChain &TC)
- : Tool(Name, ShortName, TC, RF_Full, llvm::sys::WEM_CurrentCodePage) {}
- };
-
- /// gcc - Generic GCC tool implementations.
+ visualstudio::Compiler *getCLFallback() const;
+
+ mutable std::unique_ptr<visualstudio::Compiler> CLFallback;
+
+public:
+ // CAUTION! The first constructor argument ("clang") is not arbitrary,
+ // as it is for other tools. Some operations on a Tool actually test
+ // whether that tool is Clang based on the Tool's Name as a string.
+ Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC, RF_Full) {}
+
+ bool hasGoodDiagnostics() const override { return true; }
+ bool hasIntegratedAssembler() const override { return true; }
+ bool hasIntegratedCPP() const override { return true; }
+ bool canEmitIR() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+/// \brief Clang integrated assembler tool.
+class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool {
+public:
+ ClangAs(const ToolChain &TC)
+ : Tool("clang::as", "clang integrated assembler", TC, RF_Full) {}
+ void AddMIPSTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ bool hasGoodDiagnostics() const override { return true; }
+ bool hasIntegratedAssembler() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+/// \brief Base class for all GNU tools that provide the same behavior when
+/// it comes to response files support
+class LLVM_LIBRARY_VISIBILITY GnuTool : public Tool {
+ virtual void anchor();
+
+public:
+ GnuTool(const char *Name, const char *ShortName, const ToolChain &TC)
+ : Tool(Name, ShortName, TC, RF_Full, llvm::sys::WEM_CurrentCodePage) {}
+};
+
+/// gcc - Generic GCC tool implementations.
namespace gcc {
- class LLVM_LIBRARY_VISIBILITY Common : public GnuTool {
- public:
- Common(const char *Name, const char *ShortName,
- const ToolChain &TC) : GnuTool(Name, ShortName, TC) {}
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-
- /// RenderExtraToolArgs - Render any arguments necessary to force
- /// the particular tool mode.
- virtual void
- RenderExtraToolArgs(const JobAction &JA,
- llvm::opt::ArgStringList &CmdArgs) const = 0;
- };
-
- class LLVM_LIBRARY_VISIBILITY Preprocessor : public Common {
- public:
- Preprocessor(const ToolChain &TC)
- : Common("gcc::Preprocessor", "gcc preprocessor", TC) {}
-
- bool hasGoodDiagnostics() const override { return true; }
- bool hasIntegratedCPP() const override { return false; }
-
- void RenderExtraToolArgs(const JobAction &JA,
- llvm::opt::ArgStringList &CmdArgs) const override;
- };
-
- class LLVM_LIBRARY_VISIBILITY Compiler : public Common {
- public:
- Compiler(const ToolChain &TC)
- : Common("gcc::Compiler", "gcc frontend", TC) {}
-
- bool hasGoodDiagnostics() const override { return true; }
- bool hasIntegratedCPP() const override { return true; }
-
- void RenderExtraToolArgs(const JobAction &JA,
- llvm::opt::ArgStringList &CmdArgs) const override;
- };
-
- class LLVM_LIBRARY_VISIBILITY Linker : public Common {
- public:
- Linker(const ToolChain &TC)
- : Common("gcc::Linker", "linker (via gcc)", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
-
- void RenderExtraToolArgs(const JobAction &JA,
- llvm::opt::ArgStringList &CmdArgs) const override;
- };
+class LLVM_LIBRARY_VISIBILITY Common : public GnuTool {
+public:
+ Common(const char *Name, const char *ShortName, const ToolChain &TC)
+ : GnuTool(Name, ShortName, TC) {}
+
+ // A gcc tool has an "integrated" assembler that it will call to produce an
+ // object. Let it use that assembler so that we don't have to deal with
+ // assembly syntax incompatibilities.
+ bool hasIntegratedAssembler() const override { return true; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+
+ /// RenderExtraToolArgs - Render any arguments necessary to force
+ /// the particular tool mode.
+ virtual void RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const = 0;
+};
+
+class LLVM_LIBRARY_VISIBILITY Preprocessor : public Common {
+public:
+ Preprocessor(const ToolChain &TC)
+ : Common("gcc::Preprocessor", "gcc preprocessor", TC) {}
+
+ bool hasGoodDiagnostics() const override { return true; }
+ bool hasIntegratedCPP() const override { return false; }
+
+ void RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Compiler : public Common {
+public:
+ Compiler(const ToolChain &TC) : Common("gcc::Compiler", "gcc frontend", TC) {}
+
+ bool hasGoodDiagnostics() const override { return true; }
+ bool hasIntegratedCPP() const override { return true; }
+
+ void RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Linker : public Common {
+public:
+ Linker(const ToolChain &TC) : Common("gcc::Linker", "linker (via gcc)", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+};
} // end namespace gcc
namespace hexagon {
@@ -206,12 +212,12 @@ public:
bool hasIntegratedCPP() const override { return false; }
- void RenderExtraToolArgs(const JobAction &JA,
- llvm::opt::ArgStringList &CmdArgs) const;
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
+ void RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
};
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
@@ -219,50 +225,88 @@ public:
Linker(const ToolChain &TC) : GnuTool("hexagon::Linker", "hexagon-ld", TC) {}
bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+ bool isLinkJob() const override { return true; }
- virtual void RenderExtraToolArgs(const JobAction &JA,
- llvm::opt::ArgStringList &CmdArgs) const;
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
+ virtual void RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
} // end namespace hexagon.
-namespace arm {
- std::string getARMTargetCPU(StringRef CPU, StringRef Arch,
- const llvm::Triple &Triple);
- const std::string getARMArch(StringRef Arch,
- const llvm::Triple &Triple);
- const char* getARMCPUForMArch(StringRef Arch,
- const llvm::Triple &Triple);
- const char* getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch);
+namespace amdgpu {
- void appendEBLinkFlags(const llvm::opt::ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple);
-}
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("amdgpu::Linker", "ld.lld", TC) {}
+ bool isLinkJob() const override { return true; }
+ bool hasIntegratedCPP() const override { return false; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+} // end namespace amdgpu
+
+namespace wasm {
+
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ explicit Linker(const ToolChain &TC);
+ bool isLinkJob() const override;
+ bool hasIntegratedCPP() const override;
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+} // end namespace wasm
+
+namespace arm {
+std::string getARMTargetCPU(StringRef CPU, StringRef Arch,
+ const llvm::Triple &Triple);
+const std::string getARMArch(StringRef Arch,
+ const llvm::Triple &Triple);
+StringRef getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple);
+StringRef getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch,
+ const llvm::Triple &Triple);
+
+void appendEBLinkFlags(const llvm::opt::ArgList &Args, ArgStringList &CmdArgs,
+ const llvm::Triple &Triple);
+} // end namespace arm
namespace mips {
- typedef enum {
- NanLegacy = 1,
- Nan2008 = 2
- } NanEncoding;
- NanEncoding getSupportedNanEncoding(StringRef &CPU);
- void getMipsCPUAndABI(const llvm::opt::ArgList &Args,
- const llvm::Triple &Triple, StringRef &CPUName,
- StringRef &ABIName);
- bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value);
- bool isUCLibc(const llvm::opt::ArgList &Args);
- bool isNaN2008(const llvm::opt::ArgList &Args, const llvm::Triple &Triple);
- bool isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
- StringRef ABIName, StringRef FloatABI);
- bool shouldUseFPXX(const llvm::opt::ArgList &Args, const llvm::Triple &Triple,
- StringRef CPUName, StringRef ABIName, StringRef FloatABI);
-}
+typedef enum { NanLegacy = 1, Nan2008 = 2 } NanEncoding;
+
+enum class FloatABI {
+ Invalid,
+ Soft,
+ Hard,
+};
+
+NanEncoding getSupportedNanEncoding(StringRef &CPU);
+void getMipsCPUAndABI(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple, StringRef &CPUName,
+ StringRef &ABIName);
+std::string getMipsABILibSuffix(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value);
+bool isUCLibc(const llvm::opt::ArgList &Args);
+bool isNaN2008(const llvm::opt::ArgList &Args, const llvm::Triple &Triple);
+bool isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
+ StringRef ABIName, mips::FloatABI FloatABI);
+bool shouldUseFPXX(const llvm::opt::ArgList &Args, const llvm::Triple &Triple,
+ StringRef CPUName, StringRef ABIName,
+ mips::FloatABI FloatABI);
+} // end namespace mips
namespace ppc {
- bool hasPPCAbiArg(const llvm::opt::ArgList &Args, const char *Value);
-}
+bool hasPPCAbiArg(const llvm::opt::ArgList &Args, const char *Value);
+} // end namespace ppc
/// cloudabi -- Directly call GNU Binutils linker
namespace cloudabi {
@@ -281,103 +325,102 @@ public:
} // end namespace cloudabi
namespace darwin {
- llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);
- void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str);
-
- class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool {
- virtual void anchor();
- protected:
- void AddMachOArch(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const;
-
- const toolchains::MachO &getMachOToolChain() const {
- return reinterpret_cast<const toolchains::MachO&>(getToolChain());
- }
-
- public:
- MachOTool(
- const char *Name, const char *ShortName, const ToolChain &TC,
- ResponseFileSupport ResponseSupport = RF_None,
- llvm::sys::WindowsEncodingMethod ResponseEncoding = llvm::sys::WEM_UTF8,
- const char *ResponseFlag = "@")
- : Tool(Name, ShortName, TC, ResponseSupport, ResponseEncoding,
- ResponseFlag) {}
- };
-
- class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool {
- public:
- Assembler(const ToolChain &TC)
- : MachOTool("darwin::Assembler", "assembler", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
-
- class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool {
- bool NeedsTempPath(const InputInfoList &Inputs) const;
- void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs,
- const InputInfoList &Inputs) const;
-
- public:
- Linker(const ToolChain &TC)
- : MachOTool("darwin::Linker", "linker", TC, RF_FileList,
- llvm::sys::WEM_UTF8, "-filelist") {}
-
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
-
- class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool {
- public:
- Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
-
- class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool {
- public:
- Dsymutil(const ToolChain &TC) : MachOTool("darwin::Dsymutil",
- "dsymutil", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
- bool isDsymutilJob() const override { return true; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
-
- class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool {
- public:
- VerifyDebug(const ToolChain &TC) : MachOTool("darwin::VerifyDebug",
- "dwarfdump", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
+llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);
+void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str);
-}
+class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool {
+ virtual void anchor();
+
+protected:
+ void AddMachOArch(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ const toolchains::MachO &getMachOToolChain() const {
+ return reinterpret_cast<const toolchains::MachO &>(getToolChain());
+ }
+
+public:
+ MachOTool(
+ const char *Name, const char *ShortName, const ToolChain &TC,
+ ResponseFileSupport ResponseSupport = RF_None,
+ llvm::sys::WindowsEncodingMethod ResponseEncoding = llvm::sys::WEM_UTF8,
+ const char *ResponseFlag = "@")
+ : Tool(Name, ShortName, TC, ResponseSupport, ResponseEncoding,
+ ResponseFlag) {}
+};
+
+class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool {
+public:
+ Assembler(const ToolChain &TC)
+ : MachOTool("darwin::Assembler", "assembler", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool {
+ bool NeedsTempPath(const InputInfoList &Inputs) const;
+ void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ const InputInfoList &Inputs) const;
+
+public:
+ Linker(const ToolChain &TC)
+ : MachOTool("darwin::Linker", "linker", TC, RF_FileList,
+ llvm::sys::WEM_UTF8, "-filelist") {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool {
+public:
+ Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool {
+public:
+ Dsymutil(const ToolChain &TC)
+ : MachOTool("darwin::Dsymutil", "dsymutil", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isDsymutilJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool {
+public:
+ VerifyDebug(const ToolChain &TC)
+ : MachOTool("darwin::VerifyDebug", "dwarfdump", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace darwin
/// openbsd -- Directly call GNU Binutils assembler and linker
namespace openbsd {
@@ -393,6 +436,7 @@ public:
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
+
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("openbsd::Linker", "linker", TC) {}
@@ -400,11 +444,11 @@ public:
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
} // end namespace openbsd
/// bitrig -- Directly call GNU Binutils assembler and linker
@@ -421,6 +465,7 @@ public:
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
+
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("bitrig::Linker", "linker", TC) {}
@@ -428,11 +473,11 @@ public:
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
} // end namespace bitrig
/// freebsd -- Directly call GNU Binutils assembler and linker
@@ -449,6 +494,7 @@ public:
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
+
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("freebsd::Linker", "linker", TC) {}
@@ -456,17 +502,16 @@ public:
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
} // end namespace freebsd
/// netbsd -- Directly call GNU Binutils assembler and linker
namespace netbsd {
class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
-
public:
Assembler(const ToolChain &TC)
: GnuTool("netbsd::Assembler", "assembler", TC) {}
@@ -478,19 +523,19 @@ public:
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("netbsd::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
} // end namespace netbsd
/// Directly call GNU Binutils' assembler and linker.
@@ -506,6 +551,7 @@ public:
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
+
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("GNU::Linker", "linker", TC) {}
@@ -513,38 +559,37 @@ public:
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
- }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace gnutools
- namespace nacltools {
- class LLVM_LIBRARY_VISIBILITY AssemblerARM : public gnutools::Assembler {
- public:
- AssemblerARM(const ToolChain &TC) : gnutools::Assembler(TC) {}
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
- class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
- public:
- Linker(const ToolChain &TC) : Tool("NaCl::Linker", "linker", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
-}
+namespace nacltools {
+class LLVM_LIBRARY_VISIBILITY AssemblerARM : public gnutools::Assembler {
+public:
+ AssemblerARM(const ToolChain &TC) : gnutools::Assembler(TC) {}
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("NaCl::Linker", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace nacltools
/// minix -- Directly call GNU Binutils assembler and linker
namespace minix {
@@ -560,6 +605,7 @@ public:
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
+
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("minix::Linker", "linker", TC) {}
@@ -567,12 +613,11 @@ public:
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
} // end namespace minix
/// solaris -- Directly call Solaris assembler and linker
@@ -589,6 +634,7 @@ public:
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
+
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
Linker(const ToolChain &TC) : Tool("solaris::Linker", "linker", TC) {}
@@ -596,11 +642,11 @@ public:
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
} // end namespace solaris
/// dragonfly -- Directly call GNU Binutils assembler and linker
@@ -617,6 +663,7 @@ public:
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
+
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
public:
Linker(const ToolChain &TC) : GnuTool("dragonfly::Linker", "linker", TC) {}
@@ -624,12 +671,11 @@ public:
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
} // end namespace dragonfly
/// Visual studio tools.
@@ -644,12 +690,12 @@ public:
llvm::sys::WEM_UTF16) {}
bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+ bool isLinkJob() const override { return true; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
};
class LLVM_LIBRARY_VISIBILITY Compiler : public Tool {
@@ -659,20 +705,20 @@ public:
llvm::sys::WEM_UTF16) {}
bool hasIntegratedAssembler() const override { return true; }
- bool hasIntegratedCPP() const override { return true; }
- bool isLinkJob() const override { return false; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-
- std::unique_ptr<Command> GetCommand(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const;
- };
+ bool hasIntegratedCPP() const override { return true; }
+ bool isLinkJob() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+
+ std::unique_ptr<Command> GetCommand(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const;
+};
} // end namespace visualstudio
/// MinGW -- Directly call GNU Binutils assembler and linker
@@ -707,9 +753,26 @@ private:
} // end namespace MinGW
namespace arm {
- StringRef getARMFloatABI(const Driver &D, const llvm::opt::ArgList &Args,
- const llvm::Triple &Triple);
-}
+enum class FloatABI {
+ Invalid,
+ Soft,
+ SoftFP,
+ Hard,
+};
+
+FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args);
+} // end namespace arm
+
+namespace ppc {
+enum class FloatABI {
+ Invalid,
+ Soft,
+ Hard,
+};
+
+FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
+} // end namespace ppc
+
namespace XCore {
// For XCore, we do not need to instantiate tools for PreProcess, PreCompile and
// Compile.
@@ -730,42 +793,41 @@ public:
Linker(const ToolChain &TC) : Tool("XCore::Linker", "XCore-ld", TC) {}
bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
- } // end namespace XCore.
+ bool isLinkJob() const override { return true; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace XCore.
- namespace CrossWindows {
- class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
- public:
- Assembler(const ToolChain &TC)
- : Tool("CrossWindows::Assembler", "as", TC) {}
+namespace CrossWindows {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+public:
+ Assembler(const ToolChain &TC) : Tool("CrossWindows::Assembler", "as", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
- };
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
- class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
- public:
- Linker(const ToolChain &TC)
- : Tool("CrossWindows::Linker", "ld", TC, RF_Full) {}
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+public:
+ Linker(const ToolChain &TC)
+ : Tool("CrossWindows::Linker", "ld", TC, RF_Full) {}
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
-}
+} // end namespace CrossWindows
/// SHAVE tools -- Directly call moviCompile and moviAsm
namespace SHAVE {
@@ -794,8 +856,55 @@ public:
};
} // end namespace SHAVE
+/// The Myriad toolchain uses tools that are in two different namespaces.
+/// The Compiler and Assembler as defined above are in the SHAVE namespace,
+/// whereas the linker, which accepts code for a mixture of Sparc and SHAVE,
+/// is in the Myriad namespace.
+namespace Myriad {
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("shave::Linker", "ld", TC) {}
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace Myriad
+
+namespace PS4cpu {
+class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+public:
+ Assemble(const ToolChain &TC)
+ : Tool("PS4cpu::Assemble", "assembler", TC, RF_Full) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+public:
+ Link(const ToolChain &TC) : Tool("PS4cpu::Link", "linker", TC, RF_Full) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace PS4cpu
+
} // end namespace tools
} // end namespace driver
} // end namespace clang
-#endif
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLS_H
diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
index 2085b01..c29ce94 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Types.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
@@ -128,6 +128,19 @@ bool types::isCXX(ID Id) {
}
}
+bool types::isLLVMIR(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_LLVM_IR:
+ case TY_LLVM_BC:
+ case TY_LTO_IR:
+ case TY_LTO_BC:
+ return true;
+ }
+}
+
bool types::isCuda(ID Id) {
switch (Id) {
default:
diff --git a/contrib/llvm/tools/clang/lib/Edit/Commit.cpp b/contrib/llvm/tools/clang/lib/Edit/Commit.cpp
index 9c08cc2..cb7a784 100644
--- a/contrib/llvm/tools/clang/lib/Edit/Commit.cpp
+++ b/contrib/llvm/tools/clang/lib/Edit/Commit.cpp
@@ -183,7 +183,7 @@ void Commit::addInsert(SourceLocation OrigLoc, FileOffset Offs, StringRef text,
data.Kind = Act_Insert;
data.OrigLoc = OrigLoc;
data.Offset = Offs;
- data.Text = copyString(text);
+ data.Text = text.copy(StrAlloc);
data.BeforePrev = beforePreviousInsertions;
CachedEdits.push_back(data);
}
diff --git a/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp b/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp
index e557de9..5292a58 100644
--- a/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Edit/EditedSource.cpp
@@ -23,6 +23,36 @@ void EditsReceiver::remove(CharSourceRange range) {
replace(range, StringRef());
}
+void EditedSource::deconstructMacroArgLoc(SourceLocation Loc,
+ SourceLocation &ExpansionLoc,
+ IdentifierInfo *&II) {
+ assert(SourceMgr.isMacroArgExpansion(Loc));
+ SourceLocation DefArgLoc = SourceMgr.getImmediateExpansionRange(Loc).first;
+ ExpansionLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
+ SmallString<20> Buf;
+ StringRef ArgName = Lexer::getSpelling(SourceMgr.getSpellingLoc(DefArgLoc),
+ Buf, SourceMgr, LangOpts);
+ II = nullptr;
+ if (!ArgName.empty()) {
+ II = &IdentTable.get(ArgName);
+ }
+}
+
+void EditedSource::startingCommit() {}
+
+void EditedSource::finishedCommit() {
+ for (auto &ExpArg : CurrCommitMacroArgExps) {
+ SourceLocation ExpLoc;
+ IdentifierInfo *II;
+ std::tie(ExpLoc, II) = ExpArg;
+ auto &ArgNames = ExpansionToArgMap[ExpLoc.getRawEncoding()];
+ if (std::find(ArgNames.begin(), ArgNames.end(), II) == ArgNames.end()) {
+ ArgNames.push_back(II);
+ }
+ }
+ CurrCommitMacroArgExps.clear();
+}
+
StringRef EditedSource::copyString(const Twine &twine) {
SmallString<128> Data;
return copyString(twine.toStringRef(Data));
@@ -36,15 +66,27 @@ bool EditedSource::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) {
}
if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
- SourceLocation
- DefArgLoc = SourceMgr.getImmediateExpansionRange(OrigLoc).first;
- SourceLocation
- ExpLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
- llvm::DenseMap<unsigned, SourceLocation>::iterator
- I = ExpansionToArgMap.find(ExpLoc.getRawEncoding());
- if (I != ExpansionToArgMap.end() && I->second != DefArgLoc)
- return false; // Trying to write in a macro argument input that has
- // already been written for another argument of the same macro.
+ IdentifierInfo *II;
+ SourceLocation ExpLoc;
+ deconstructMacroArgLoc(OrigLoc, ExpLoc, II);
+ auto I = ExpansionToArgMap.find(ExpLoc.getRawEncoding());
+ if (I != ExpansionToArgMap.end() &&
+ std::find(I->second.begin(), I->second.end(), II) != I->second.end()) {
+ // Trying to write in a macro argument input that has already been
+ // written by a previous commit for another expansion of the same macro
+ // argument name. For example:
+ //
+ // \code
+ // #define MAC(x) ((x)+(x))
+ // MAC(a)
+ // \endcode
+ //
+ // A commit modified the macro argument 'a' due to the first '(x)'
+ // expansion inside the macro definition, and a subsequent commit tried
+ // to modify 'a' again for the second '(x)' expansion. The edits of the
+ // second commit will be rejected.
+ return false;
+ }
}
return true;
@@ -59,11 +101,11 @@ bool EditedSource::commitInsert(SourceLocation OrigLoc,
return true;
if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
- SourceLocation
- DefArgLoc = SourceMgr.getImmediateExpansionRange(OrigLoc).first;
- SourceLocation
- ExpLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
- ExpansionToArgMap[ExpLoc.getRawEncoding()] = DefArgLoc;
+ IdentifierInfo *II;
+ SourceLocation ExpLoc;
+ deconstructMacroArgLoc(OrigLoc, ExpLoc, II);
+ if (II)
+ CurrCommitMacroArgExps.emplace_back(ExpLoc, II);
}
FileEdit &FA = FileEdits[Offs];
@@ -219,6 +261,16 @@ bool EditedSource::commit(const Commit &commit) {
if (!commit.isCommitable())
return false;
+ struct CommitRAII {
+ EditedSource &Editor;
+ CommitRAII(EditedSource &Editor) : Editor(Editor) {
+ Editor.startingCommit();
+ }
+ ~CommitRAII() {
+ Editor.finishedCommit();
+ }
+ } CommitRAII(*this);
+
for (edit::Commit::edit_iterator
I = commit.edit_begin(), E = commit.edit_end(); I != E; ++I) {
const edit::Commit::Edit &edit = *I;
@@ -312,7 +364,7 @@ static void adjustRemoval(const SourceManager &SM, const LangOptions &LangOpts,
static void applyRewrite(EditsReceiver &receiver,
StringRef text, FileOffset offs, unsigned len,
const SourceManager &SM, const LangOptions &LangOpts) {
- assert(!offs.getFID().isInvalid());
+ assert(offs.getFID().isValid());
SourceLocation Loc = SM.getLocForStartOfFile(offs.getFID());
Loc = Loc.getLocWithOffset(offs.getOffset());
assert(Loc.isFileID());
diff --git a/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
index 9f71168..482c0f6 100644
--- a/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
+++ b/contrib/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
@@ -1077,6 +1077,9 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
return false;
+
+ case CK_BooleanToSignedIntegral:
+ llvm_unreachable("OpenCL-specific cast in Objective-C?");
}
}
diff --git a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
index dd56831..1118335 100644
--- a/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp
@@ -38,6 +38,12 @@ static unsigned getLengthToMatchingParen(const FormatToken &Tok) {
return End->TotalLength - Tok.TotalLength + 1;
}
+static unsigned getLengthToNextOperator(const FormatToken &Tok) {
+ if (!Tok.NextOperator)
+ return 0;
+ return Tok.NextOperator->TotalLength - Tok.TotalLength;
+}
+
// Returns \c true if \c Tok is the "." or "->" of a call and starts the next
// segment of a builder type call.
static bool startsSegmentOfBuilderTypeCall(const FormatToken &Tok) {
@@ -95,7 +101,7 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
assert(&Previous == Current.Previous);
if (!Current.CanBreakBefore &&
!(State.Stack.back().BreakBeforeClosingBrace &&
- Current.closesBlockTypeList(Style)))
+ Current.closesBlockOrBlockTypeList(Style)))
return false;
// The opening "{" of a braced list has to be on the same line as the first
// element if it is nested in another braced init list or function call.
@@ -125,10 +131,10 @@ bool ContinuationIndenter::canBreak(const LineState &State) {
// Don't break after very short return types (e.g. "void") as that is often
// unexpected.
- if (Current.is(TT_FunctionDeclarationName) &&
- Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_None &&
- State.Column < 6)
- return false;
+ if (Current.is(TT_FunctionDeclarationName) && State.Column < 6) {
+ if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None)
+ return false;
+ }
return !State.Stack.back().NoLineBreak;
}
@@ -139,11 +145,17 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
if (Current.MustBreakBefore || Current.is(TT_InlineASMColon))
return true;
if (State.Stack.back().BreakBeforeClosingBrace &&
- Current.closesBlockTypeList(Style))
+ Current.closesBlockOrBlockTypeList(Style))
return true;
if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection)
return true;
if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) ||
+ (Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) &&
+ // FIXME: This is a temporary workaround for the case where clang-format
+ // sets BreakBeforeParameter to avoid bin packing and this creates a
+ // completely unnecessary line break after a template type that isn't
+ // line-wrapped.
+ (Previous.NestingLevel == 1 || Style.BinPackParameters)) ||
(Style.BreakBeforeTernaryOperators && Current.is(TT_ConditionalExpr) &&
Previous.isNot(tok::question)) ||
(!Style.BreakBeforeTernaryOperators &&
@@ -152,12 +164,16 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
!Current.isOneOf(tok::r_paren, tok::r_brace))
return true;
if (((Previous.is(TT_DictLiteral) && Previous.is(tok::l_brace)) ||
- Previous.is(TT_ArrayInitializerLSquare)) &&
+ (Previous.is(TT_ArrayInitializerLSquare) &&
+ Previous.ParameterCount > 1)) &&
Style.ColumnLimit > 0 &&
getLengthToMatchingParen(Previous) + State.Column - 1 >
getColumnLimit(State))
return true;
if (Current.is(TT_CtorInitializerColon) &&
+ (State.Column + State.Line->Last->TotalLength - Current.TotalLength + 2 >
+ getColumnLimit(State) ||
+ State.Stack.back().BreakBeforeParameter) &&
((Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All) ||
Style.BreakConstructorInitializersBeforeComma || Style.ColumnLimit != 0))
return true;
@@ -166,7 +182,13 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
return true;
unsigned NewLineColumn = getNewLineColumn(State);
- if (State.Column < NewLineColumn)
+ if (Current.isMemberAccess() &&
+ State.Column + getLengthToNextOperator(Current) > Style.ColumnLimit &&
+ (State.Column > NewLineColumn ||
+ Current.NestingLevel < State.StartOfLineLevel))
+ return true;
+
+ if (State.Column <= NewLineColumn)
return false;
if (Style.AlwaysBreakBeforeMultilineStrings &&
@@ -225,7 +247,8 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
}
// If the return type spans multiple lines, wrap before the function name.
- if (Current.isOneOf(TT_FunctionDeclarationName, tok::kw_operator) &&
+ if ((Current.is(TT_FunctionDeclarationName) ||
+ (Current.is(tok::kw_operator) && !Previous.is(tok::coloncolon))) &&
State.Stack.back().BreakBeforeParameter)
return true;
@@ -241,8 +264,10 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
Previous.is(tok::l_brace) && !Current.isOneOf(tok::r_brace, tok::comment))
return true;
- if (Current.is(tok::lessless) && Previous.is(tok::identifier) &&
- Previous.TokenText == "endl")
+ if (Current.is(tok::lessless) &&
+ ((Previous.is(tok::identifier) && Previous.TokenText == "endl") ||
+ (Previous.Tok.isLiteral() && (Previous.TokenText.endswith("\\n\"") ||
+ Previous.TokenText == "\'\\n\'"))))
return true;
return false;
@@ -311,20 +336,29 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
if (Current.is(TT_SelectorName) &&
!State.Stack.back().ObjCSelectorNameFound) {
+ unsigned MinIndent =
+ std::max(State.FirstIndent + Style.ContinuationIndentWidth,
+ State.Stack.back().Indent);
+ unsigned FirstColonPos = State.Column + Spaces + Current.ColumnWidth;
if (Current.LongestObjCSelectorName == 0)
State.Stack.back().AlignColons = false;
- else if (State.Stack.back().Indent + Current.LongestObjCSelectorName >
- State.Column + Spaces + Current.ColumnWidth)
- State.Stack.back().ColonPos =
- std::max(State.FirstIndent + Style.ContinuationIndentWidth,
- State.Stack.back().Indent) +
- Current.LongestObjCSelectorName;
+ else if (MinIndent + Current.LongestObjCSelectorName > FirstColonPos)
+ State.Stack.back().ColonPos = MinIndent + Current.LongestObjCSelectorName;
else
- State.Stack.back().ColonPos = State.Column + Spaces + Current.ColumnWidth;
+ State.Stack.back().ColonPos = FirstColonPos;
}
- if (Style.AlignAfterOpenBracket && Previous.opensScope() &&
- Previous.isNot(TT_ObjCMethodExpr) &&
+ // In "AlwaysBreak" mode, enforce wrapping directly after the parenthesis by
+ // disallowing any further line breaks if there is no line break after the
+ // opening parenthesis. Don't break if it doesn't conserve columns.
+ if (Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak &&
+ Previous.is(tok::l_paren) && State.Column > getNewLineColumn(State) &&
+ (!Previous.Previous ||
+ !Previous.Previous->isOneOf(tok::kw_for, tok::kw_while, tok::kw_switch)))
+ State.Stack.back().NoLineBreak = true;
+
+ if (Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign &&
+ Previous.opensScope() && Previous.isNot(TT_ObjCMethodExpr) &&
(Current.isNot(TT_LineComment) || Previous.BlockKind == BK_BracedInit))
State.Stack.back().Indent = State.Column + Spaces;
if (State.Stack.back().AvoidBinPacking && startsNextParameter(Current, Style))
@@ -356,14 +390,15 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
State.Stack.back().LastSpace = State.Column;
State.Stack.back().NestedBlockIndent = State.Column;
} else if (!Current.isOneOf(tok::comment, tok::caret) &&
- (Previous.is(tok::comma) ||
+ ((Previous.is(tok::comma) &&
+ !Previous.is(TT_OverloadedOperator)) ||
(Previous.is(tok::colon) && Previous.is(TT_ObjCMethodExpr)))) {
State.Stack.back().LastSpace = State.Column;
} else if ((Previous.isOneOf(TT_BinaryOperator, TT_ConditionalExpr,
TT_CtorInitializerColon)) &&
((Previous.getPrecedence() != prec::Assignment &&
(Previous.isNot(tok::lessless) || Previous.OperatorIndex != 0 ||
- !Previous.LastOperator)) ||
+ Previous.NextOperator)) ||
Current.StartsBinaryExpression)) {
// Always indent relative to the RHS of the expression unless this is a
// simple assignment without binary expression on the RHS. Also indent
@@ -500,6 +535,7 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
// Any break on this level means that the parent level has been broken
// and we need to avoid bin packing there.
bool NestedBlockSpecialCase =
+ Style.Language != FormatStyle::LK_Cpp &&
Current.is(tok::r_brace) && State.Stack.size() > 1 &&
State.Stack[State.Stack.size() - 2].NestedBlockInlined;
if (!NestedBlockSpecialCase)
@@ -560,7 +596,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return Current.NestingLevel == 0 ? State.FirstIndent
: State.Stack.back().Indent;
if (Current.isOneOf(tok::r_brace, tok::r_square) && State.Stack.size() > 1) {
- if (Current.closesBlockTypeList(Style))
+ if (Current.closesBlockOrBlockTypeList(Style))
return State.Stack[State.Stack.size() - 2].NestedBlockIndent;
if (Current.MatchingParen &&
Current.MatchingParen->BlockKind == BK_BracedInit)
@@ -677,9 +713,14 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
std::min(State.LowestLevelOnLine, Current.NestingLevel);
if (Current.isMemberAccess())
State.Stack.back().StartOfFunctionCall =
- Current.LastOperator ? 0 : State.Column;
- if (Current.is(TT_SelectorName))
+ !Current.NextOperator ? 0 : State.Column;
+ if (Current.is(TT_SelectorName)) {
State.Stack.back().ObjCSelectorNameFound = true;
+ if (Style.IndentWrappedFunctionNames) {
+ State.Stack.back().Indent =
+ State.FirstIndent + Style.ContinuationIndentWidth;
+ }
+ }
if (Current.is(TT_CtorInitializerColon)) {
// Indent 2 from the column, so:
// SomeClass::SomeClass()
@@ -708,7 +749,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
// }, a, b, c);
if (Current.isNot(tok::comment) && Previous &&
Previous->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) &&
- State.Stack.size() > 1) {
+ !Previous->is(TT_DictLiteral) && State.Stack.size() > 1) {
if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline)
for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i)
State.Stack[i].NoLineBreak = true;
@@ -784,8 +825,8 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
(Style.AlignOperands || *I < prec::Assignment) &&
(!Previous || Previous->isNot(tok::kw_return) ||
(Style.Language != FormatStyle::LK_Java && *I > 0)) &&
- (Style.AlignAfterOpenBracket || *I != prec::Comma ||
- Current.NestingLevel == 0))
+ (Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign ||
+ *I != prec::Comma || Current.NestingLevel == 0))
NewParenState.Indent =
std::max(std::max(State.Column, NewParenState.Indent),
State.Stack.back().LastSpace);
@@ -827,7 +868,7 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
(!SkipFirstExtraIndent && *I > prec::Assignment &&
!Current.isTrailingComment()))
NewParenState.Indent += Style.ContinuationIndentWidth;
- if ((Previous && !Previous->opensScope()) || *I > prec::Comma)
+ if ((Previous && !Previous->opensScope()) || *I != prec::Comma)
NewParenState.BreakBeforeParameter = false;
State.Stack.push_back(NewParenState);
SkipFirstExtraIndent = false;
@@ -865,7 +906,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
unsigned NestedBlockIndent = std::max(State.Stack.back().StartOfFunctionCall,
State.Stack.back().NestedBlockIndent);
if (Current.isOneOf(tok::l_brace, TT_ArrayInitializerLSquare)) {
- if (Current.opensBlockTypeList(Style)) {
+ if (Current.opensBlockOrBlockTypeList(Style)) {
NewIndent = State.Stack.back().NestedBlockIndent + Style.IndentWidth;
NewIndent = std::min(State.Column + 2, NewIndent);
++NewIndentLevel;
@@ -873,8 +914,12 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
NewIndent = State.Stack.back().LastSpace + Style.ContinuationIndentWidth;
}
const FormatToken *NextNoComment = Current.getNextNonComment();
+ bool EndsInComma = Current.MatchingParen &&
+ Current.MatchingParen->Previous &&
+ Current.MatchingParen->Previous->is(tok::comma);
AvoidBinPacking =
- Current.isOneOf(TT_ArrayInitializerLSquare, TT_DictLiteral) ||
+ (Current.is(TT_ArrayInitializerLSquare) && EndsInComma) ||
+ Current.is(TT_DictLiteral) ||
Style.Language == FormatStyle::LK_Proto || !Style.BinPackArguments ||
(NextNoComment && NextNoComment->is(TT_DesignatedInitializerPeriod));
if (Current.ParameterCount > 1)
@@ -923,9 +968,15 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
}
}
}
- bool NoLineBreak = State.Stack.back().NoLineBreak ||
- (Current.is(TT_TemplateOpener) &&
- State.Stack.back().ContainsUnwrappedBuilder);
+ // Generally inherit NoLineBreak from the current scope to nested scope.
+ // However, don't do this for non-empty nested blocks, dict literals and
+ // array literals as these follow different indentation rules.
+ bool NoLineBreak =
+ Current.Children.empty() &&
+ !Current.isOneOf(TT_DictLiteral, TT_ArrayInitializerLSquare) &&
+ (State.Stack.back().NoLineBreak ||
+ (Current.is(TT_TemplateOpener) &&
+ State.Stack.back().ContainsUnwrappedBuilder));
State.Stack.push_back(ParenState(NewIndent, NewIndentLevel, LastSpace,
AvoidBinPacking, NoLineBreak));
State.Stack.back().NestedBlockIndent = NestedBlockIndent;
@@ -964,7 +1015,7 @@ void ContinuationIndenter::moveStateToNewBlock(LineState &State) {
State.Stack.push_back(ParenState(
NewIndent, /*NewIndentLevel=*/State.Stack.back().IndentLevel + 1,
State.Stack.back().LastSpace, /*AvoidBinPacking=*/true,
- State.Stack.back().NoLineBreak));
+ /*NoLineBreak=*/false));
State.Stack.back().NestedBlockIndent = NestedBlockIndent;
State.Stack.back().BreakBeforeParameter = true;
}
@@ -1050,7 +1101,8 @@ unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
return 0;
}
} else if (Current.is(TT_BlockComment) && Current.isTrailingComment()) {
- if (CommentPragmasRegex.match(Current.TokenText.substr(2)))
+ if (!Style.ReflowComments ||
+ CommentPragmasRegex.match(Current.TokenText.substr(2)))
return 0;
Token.reset(new BreakableBlockComment(
Current, State.Line->Level, StartColumn, Current.OriginalColumn,
@@ -1058,7 +1110,8 @@ unsigned ContinuationIndenter::breakProtrudingToken(const FormatToken &Current,
} else if (Current.is(TT_LineComment) &&
(Current.Previous == nullptr ||
Current.Previous->isNot(TT_ImplicitStringLiteral))) {
- if (CommentPragmasRegex.match(Current.TokenText.substr(2)))
+ if (!Style.ReflowComments ||
+ CommentPragmasRegex.match(Current.TokenText.substr(2)))
return 0;
Token.reset(new BreakableLineComment(Current, State.Line->Level,
StartColumn, /*InPPDirective=*/false,
diff --git a/contrib/llvm/tools/clang/lib/Format/Encoding.h b/contrib/llvm/tools/clang/lib/Format/Encoding.h
index 766d292..592d720 100644
--- a/contrib/llvm/tools/clang/lib/Format/Encoding.h
+++ b/contrib/llvm/tools/clang/lib/Format/Encoding.h
@@ -135,7 +135,7 @@ inline unsigned getEscapeSequenceLength(StringRef Text) {
++I;
return I;
}
- return 2;
+ return 1 + getNumBytesForUTF8(Text[1]);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Format/Format.cpp b/contrib/llvm/tools/clang/lib/Format/Format.cpp
index 382ae81..2689368 100644
--- a/contrib/llvm/tools/clang/lib/Format/Format.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/Format.cpp
@@ -13,6 +13,7 @@
///
//===----------------------------------------------------------------------===//
+#include "clang/Format/Format.h"
#include "ContinuationIndenter.h"
#include "TokenAnnotator.h"
#include "UnwrappedLineFormatter.h"
@@ -21,7 +22,6 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Allocator.h"
@@ -37,6 +37,7 @@
using clang::format::FormatStyle;
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)
+LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::IncludeCategory)
namespace llvm {
namespace yaml {
@@ -46,6 +47,7 @@ template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
IO.enumCase(Value, "Java", FormatStyle::LK_Java);
IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
+ IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
}
};
@@ -98,11 +100,27 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
+ IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
+ IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
+ }
+};
+
+template <>
+struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
+ static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::RTBS_None);
+ IO.enumCase(Value, "All", FormatStyle::RTBS_All);
+ IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
+ IO.enumCase(Value, "TopLevelDefinitions",
+ FormatStyle::RTBS_TopLevelDefinitions);
+ IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
}
};
-template <> struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
- static void enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
+template <>
+struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
+ static void
+ enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
@@ -123,6 +141,18 @@ struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
+ static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
+ IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
+ IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
+ IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "true", FormatStyle::BAS_Align);
+ IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
@@ -197,6 +227,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
IO.mapOptional("AlignConsecutiveAssignments",
Style.AlignConsecutiveAssignments);
+ IO.mapOptional("AlignConsecutiveDeclarations",
+ Style.AlignConsecutiveDeclarations);
IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft);
IO.mapOptional("AlignOperands", Style.AlignOperands);
IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
@@ -214,12 +246,28 @@ template <> struct MappingTraits<FormatStyle> {
Style.AllowShortLoopsOnASingleLine);
IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
Style.AlwaysBreakAfterDefinitionReturnType);
+ IO.mapOptional("AlwaysBreakAfterReturnType",
+ Style.AlwaysBreakAfterReturnType);
+ // If AlwaysBreakAfterDefinitionReturnType was specified but
+ // AlwaysBreakAfterReturnType was not, initialize the latter from the
+ // former for backwards compatibility.
+ if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
+ Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) {
+ if (Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All)
+ Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
+ else if (Style.AlwaysBreakAfterDefinitionReturnType ==
+ FormatStyle::DRTBS_TopLevel)
+ Style.AlwaysBreakAfterReturnType =
+ FormatStyle::RTBS_TopLevelDefinitions;
+ }
+
IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
Style.AlwaysBreakBeforeMultilineStrings);
IO.mapOptional("AlwaysBreakTemplateDeclarations",
Style.AlwaysBreakTemplateDeclarations);
IO.mapOptional("BinPackArguments", Style.BinPackArguments);
IO.mapOptional("BinPackParameters", Style.BinPackParameters);
+ IO.mapOptional("BraceWrapping", Style.BraceWrapping);
IO.mapOptional("BreakBeforeBinaryOperators",
Style.BreakBeforeBinaryOperators);
IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
@@ -240,6 +288,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("ExperimentalAutoDetectBinPacking",
Style.ExperimentalAutoDetectBinPacking);
IO.mapOptional("ForEachMacros", Style.ForEachMacros);
+ IO.mapOptional("IncludeCategories", Style.IncludeCategories);
IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
IO.mapOptional("IndentWidth", Style.IndentWidth);
IO.mapOptional("IndentWrappedFunctionNames",
@@ -264,6 +313,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
Style.PenaltyReturnTypeOnItsOwnLine);
IO.mapOptional("PointerAlignment", Style.PointerAlignment);
+ IO.mapOptional("ReflowComments", Style.ReflowComments);
+ IO.mapOptional("SortIncludes", Style.SortIncludes);
IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
IO.mapOptional("SpaceBeforeAssignmentOperators",
Style.SpaceBeforeAssignmentOperators);
@@ -284,6 +335,29 @@ template <> struct MappingTraits<FormatStyle> {
}
};
+template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
+ static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
+ IO.mapOptional("AfterClass", Wrapping.AfterClass);
+ IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
+ IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
+ IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
+ IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
+ IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
+ IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
+ IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
+ IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
+ IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
+ IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
+ }
+};
+
+template <> struct MappingTraits<FormatStyle::IncludeCategory> {
+ static void mapping(IO &IO, FormatStyle::IncludeCategory &Category) {
+ IO.mapOptional("Regex", Category.Regex);
+ IO.mapOptional("Priority", Category.Priority);
+ }
+};
+
// Allows to read vector<FormatStyle> while keeping default values.
// IO.getContext() should contain a pointer to the FormatStyle structure, that
// will be used to get default values for missing keys.
@@ -309,8 +383,8 @@ template <> struct DocumentListTraits<std::vector<FormatStyle>> {
return Seq[Index];
}
};
-}
-}
+} // namespace yaml
+} // namespace llvm
namespace clang {
namespace format {
@@ -339,21 +413,71 @@ std::string ParseErrorCategory::message(int EV) const {
llvm_unreachable("unexpected parse error");
}
+static FormatStyle expandPresets(const FormatStyle &Style) {
+ if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
+ return Style;
+ FormatStyle Expanded = Style;
+ Expanded.BraceWrapping = {false, false, false, false, false, false,
+ false, false, false, false, false};
+ switch (Style.BreakBeforeBraces) {
+ case FormatStyle::BS_Linux:
+ Expanded.BraceWrapping.AfterClass = true;
+ Expanded.BraceWrapping.AfterFunction = true;
+ Expanded.BraceWrapping.AfterNamespace = true;
+ break;
+ case FormatStyle::BS_Mozilla:
+ Expanded.BraceWrapping.AfterClass = true;
+ Expanded.BraceWrapping.AfterEnum = true;
+ Expanded.BraceWrapping.AfterFunction = true;
+ Expanded.BraceWrapping.AfterStruct = true;
+ Expanded.BraceWrapping.AfterUnion = true;
+ break;
+ case FormatStyle::BS_Stroustrup:
+ Expanded.BraceWrapping.AfterFunction = true;
+ Expanded.BraceWrapping.BeforeCatch = true;
+ Expanded.BraceWrapping.BeforeElse = true;
+ break;
+ case FormatStyle::BS_Allman:
+ Expanded.BraceWrapping.AfterClass = true;
+ Expanded.BraceWrapping.AfterControlStatement = true;
+ Expanded.BraceWrapping.AfterEnum = true;
+ Expanded.BraceWrapping.AfterFunction = true;
+ Expanded.BraceWrapping.AfterNamespace = true;
+ Expanded.BraceWrapping.AfterObjCDeclaration = true;
+ Expanded.BraceWrapping.AfterStruct = true;
+ Expanded.BraceWrapping.BeforeCatch = true;
+ Expanded.BraceWrapping.BeforeElse = true;
+ break;
+ case FormatStyle::BS_GNU:
+ Expanded.BraceWrapping = {true, true, true, true, true, true,
+ true, true, true, true, true};
+ break;
+ case FormatStyle::BS_WebKit:
+ Expanded.BraceWrapping.AfterFunction = true;
+ break;
+ default:
+ break;
+ }
+ return Expanded;
+}
+
FormatStyle getLLVMStyle() {
FormatStyle LLVMStyle;
LLVMStyle.Language = FormatStyle::LK_Cpp;
LLVMStyle.AccessModifierOffset = -2;
LLVMStyle.AlignEscapedNewlinesLeft = false;
- LLVMStyle.AlignAfterOpenBracket = true;
+ LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
LLVMStyle.AlignOperands = true;
LLVMStyle.AlignTrailingComments = true;
LLVMStyle.AlignConsecutiveAssignments = false;
+ LLVMStyle.AlignConsecutiveDeclarations = false;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
LLVMStyle.AllowShortBlocksOnASingleLine = false;
LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
LLVMStyle.AllowShortIfStatementsOnASingleLine = false;
LLVMStyle.AllowShortLoopsOnASingleLine = false;
+ LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
LLVMStyle.AlwaysBreakTemplateDeclarations = false;
@@ -362,7 +486,10 @@ FormatStyle getLLVMStyle() {
LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
+ LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
+ false, false, false, false, false};
LLVMStyle.BreakConstructorInitializersBeforeComma = false;
+ LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.ColumnLimit = 80;
LLVMStyle.CommentPragmas = "^ IWYU pragma:";
LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
@@ -374,6 +501,9 @@ FormatStyle getLLVMStyle() {
LLVMStyle.ForEachMacros.push_back("foreach");
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
+ LLVMStyle.IncludeCategories = {{"^\"(llvm|llvm-c|clang|clang-c)/", 2},
+ {"^(<|\"(gtest|isl|json)/)", 3},
+ {".*", 1}};
LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentWrappedFunctionNames = false;
LLVMStyle.IndentWidth = 2;
@@ -388,6 +518,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.SpacesBeforeTrailingComments = 1;
LLVMStyle.Standard = FormatStyle::LS_Cpp11;
LLVMStyle.UseTab = FormatStyle::UT_Never;
+ LLVMStyle.ReflowComments = true;
LLVMStyle.SpacesInParentheses = false;
LLVMStyle.SpacesInSquareBrackets = false;
LLVMStyle.SpaceInEmptyParentheses = false;
@@ -406,6 +537,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
LLVMStyle.DisableFormat = false;
+ LLVMStyle.SortIncludes = true;
return LLVMStyle;
}
@@ -422,6 +554,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.AlwaysBreakTemplateDeclarations = true;
GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
GoogleStyle.DerivePointerAlignment = true;
+ GoogleStyle.IncludeCategories = {{"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}};
GoogleStyle.IndentCaseLabels = true;
GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
GoogleStyle.ObjCSpaceAfterProperty = false;
@@ -434,7 +567,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
if (Language == FormatStyle::LK_Java) {
- GoogleStyle.AlignAfterOpenBracket = false;
+ GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
GoogleStyle.AlignOperands = false;
GoogleStyle.AlignTrailingComments = false;
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
@@ -445,11 +578,14 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
GoogleStyle.SpaceAfterCStyleCast = true;
GoogleStyle.SpacesBeforeTrailingComments = 1;
} else if (Language == FormatStyle::LK_JavaScript) {
+ GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ GoogleStyle.AlignOperands = false;
+ GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+ GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
GoogleStyle.BreakBeforeTernaryOperators = false;
+ GoogleStyle.CommentPragmas = "@(export|visibility) {";
GoogleStyle.MaxEmptyLinesToKeep = 3;
GoogleStyle.SpacesInContainerLiterals = false;
- GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
- GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
} else if (Language == FormatStyle::LK_Proto) {
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
GoogleStyle.SpacesInContainerLiterals = false;
@@ -462,8 +598,9 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
FormatStyle ChromiumStyle = getGoogleStyle(Language);
if (Language == FormatStyle::LK_Java) {
ChromiumStyle.AllowShortIfStatementsOnASingleLine = true;
- ChromiumStyle.IndentWidth = 4;
+ ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
ChromiumStyle.ContinuationIndentWidth = 8;
+ ChromiumStyle.IndentWidth = 4;
} else {
ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
@@ -472,8 +609,7 @@ FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
ChromiumStyle.BinPackParameters = false;
ChromiumStyle.DerivePointerAlignment = false;
}
- ChromiumStyle.MacroBlockBegin = "^IPC_BEGIN_MESSAGE_MAP$";
- ChromiumStyle.MacroBlockBegin = "^IPC_END_MESSAGE_MAP$";
+ ChromiumStyle.SortIncludes = false;
return ChromiumStyle;
}
@@ -481,6 +617,8 @@ FormatStyle getMozillaStyle() {
FormatStyle MozillaStyle = getLLVMStyle();
MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+ MozillaStyle.AlwaysBreakAfterReturnType =
+ FormatStyle::RTBS_TopLevelDefinitions;
MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
FormatStyle::DRTBS_TopLevel;
MozillaStyle.AlwaysBreakTemplateDeclarations = true;
@@ -500,11 +638,11 @@ FormatStyle getMozillaStyle() {
FormatStyle getWebKitStyle() {
FormatStyle Style = getLLVMStyle();
Style.AccessModifierOffset = -4;
- Style.AlignAfterOpenBracket = false;
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
Style.AlignOperands = false;
Style.AlignTrailingComments = false;
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
- Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
+ Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
Style.BreakConstructorInitializersBeforeComma = true;
Style.Cpp11BracedListStyle = false;
Style.ColumnLimit = 0;
@@ -520,6 +658,7 @@ FormatStyle getWebKitStyle() {
FormatStyle getGNUStyle() {
FormatStyle Style = getLLVMStyle();
Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
+ Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
Style.BreakBeforeBraces = FormatStyle::BS_GNU;
Style.BreakBeforeTernaryOperators = true;
@@ -533,6 +672,7 @@ FormatStyle getGNUStyle() {
FormatStyle getNoStyle() {
FormatStyle NoStyle = getLLVMStyle();
NoStyle.DisableFormat = true;
+ NoStyle.SortIncludes = false;
return NoStyle;
}
@@ -612,7 +752,7 @@ std::string configurationAsText(const FormatStyle &Style) {
llvm::yaml::Output Output(Stream);
// We use the same mapping method for input and output, so we need a non-const
// reference here.
- FormatStyle NonConstStyle = Style;
+ FormatStyle NonConstStyle = expandPresets(Style);
Output << NonConstStyle;
return Stream.str();
}
@@ -644,6 +784,8 @@ public:
assert(FirstInLineIndex == 0);
do {
Tokens.push_back(getNextToken());
+ if (Style.Language == FormatStyle::LK_JavaScript)
+ tryParseJSRegexLiteral();
tryMergePreviousTokens();
if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
FirstInLineIndex = Tokens.size() - 1;
@@ -663,10 +805,6 @@ private:
return;
if (Style.Language == FormatStyle::LK_JavaScript) {
- if (tryMergeJSRegexLiteral())
- return;
- if (tryMergeEscapeSequence())
- return;
if (tryMergeTemplateString())
return;
@@ -738,96 +876,97 @@ private:
return true;
}
- // Tries to merge an escape sequence, i.e. a "\\" and the following
- // character. Use e.g. inside JavaScript regex literals.
- bool tryMergeEscapeSequence() {
- if (Tokens.size() < 2)
- return false;
- FormatToken *Previous = Tokens[Tokens.size() - 2];
- if (Previous->isNot(tok::unknown) || Previous->TokenText != "\\")
- return false;
- ++Previous->ColumnWidth;
- StringRef Text = Previous->TokenText;
- Previous->TokenText = StringRef(Text.data(), Text.size() + 1);
- resetLexer(SourceMgr.getFileOffset(Tokens.back()->Tok.getLocation()) + 1);
- Tokens.resize(Tokens.size() - 1);
- Column = Previous->OriginalColumn + Previous->ColumnWidth;
- return true;
+ // Returns \c true if \p Tok can only be followed by an operand in JavaScript.
+ bool precedesOperand(FormatToken *Tok) {
+ // NB: This is not entirely correct, as an r_paren can introduce an operand
+ // location in e.g. `if (foo) /bar/.exec(...);`. That is a rare enough
+ // corner case to not matter in practice, though.
+ return Tok->isOneOf(tok::period, tok::l_paren, tok::comma, tok::l_brace,
+ tok::r_brace, tok::l_square, tok::semi, tok::exclaim,
+ tok::colon, tok::question, tok::tilde) ||
+ Tok->isOneOf(tok::kw_return, tok::kw_do, tok::kw_case, tok::kw_throw,
+ tok::kw_else, tok::kw_new, tok::kw_delete, tok::kw_void,
+ tok::kw_typeof, Keywords.kw_instanceof,
+ Keywords.kw_in) ||
+ Tok->isBinaryOperator();
}
- // Try to determine whether the current token ends a JavaScript regex literal.
- // We heuristically assume that this is a regex literal if we find two
- // unescaped slashes on a line and the token before the first slash is one of
- // "(;,{}![:?", a binary operator or 'return', as those cannot be followed by
- // a division.
- bool tryMergeJSRegexLiteral() {
- if (Tokens.size() < 2)
- return false;
+ bool canPrecedeRegexLiteral(FormatToken *Prev) {
+ if (!Prev)
+ return true;
- // If this is a string literal with a slash inside, compute the slash's
- // offset and try to find the beginning of the regex literal.
- // Also look at tok::unknown, as it can be an unterminated char literal.
- size_t SlashInStringPos = StringRef::npos;
- if (Tokens.back()->isOneOf(tok::string_literal, tok::char_constant,
- tok::unknown)) {
- // Start search from position 1 as otherwise, this is an unknown token
- // for an unterminated /*-comment which is handled elsewhere.
- SlashInStringPos = Tokens.back()->TokenText.find('/', 1);
- if (SlashInStringPos == StringRef::npos)
- return false;
- }
+ // Regex literals can only follow after prefix unary operators, not after
+ // postfix unary operators. If the '++' is followed by a non-operand
+ // introducing token, the slash here is the operand and not the start of a
+ // regex.
+ if (Prev->isOneOf(tok::plusplus, tok::minusminus))
+ return (Tokens.size() < 3 || precedesOperand(Tokens[Tokens.size() - 3]));
- // If a regex literal ends in "\//", this gets represented by an unknown
- // token "\" and a comment.
- bool MightEndWithEscapedSlash =
- Tokens.back()->is(tok::comment) &&
- Tokens.back()->TokenText.startswith("//") &&
- Tokens[Tokens.size() - 2]->TokenText == "\\";
- if (!MightEndWithEscapedSlash && SlashInStringPos == StringRef::npos &&
- (Tokens.back()->isNot(tok::slash) ||
- (Tokens[Tokens.size() - 2]->is(tok::unknown) &&
- Tokens[Tokens.size() - 2]->TokenText == "\\")))
+ // The previous token must introduce an operand location where regex
+ // literals can occur.
+ if (!precedesOperand(Prev))
return false;
- unsigned TokenCount = 0;
+ return true;
+ }
+
+ // Tries to parse a JavaScript Regex literal starting at the current token,
+ // if that begins with a slash and is in a location where JavaScript allows
+ // regex literals. Changes the current token to a regex literal and updates
+ // its text if successful.
+ void tryParseJSRegexLiteral() {
+ FormatToken *RegexToken = Tokens.back();
+ if (!RegexToken->isOneOf(tok::slash, tok::slashequal))
+ return;
+
+ FormatToken *Prev = nullptr;
for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; ++I) {
- ++TokenCount;
- auto Prev = I + 1;
- while (Prev != E && Prev[0]->is(tok::comment))
- ++Prev;
- if (I[0]->isOneOf(tok::slash, tok::slashequal) &&
- (Prev == E ||
- ((Prev[0]->isOneOf(tok::l_paren, tok::semi, tok::l_brace,
- tok::r_brace, tok::exclaim, tok::l_square,
- tok::colon, tok::comma, tok::question,
- tok::kw_return) ||
- Prev[0]->isBinaryOperator())))) {
- unsigned LastColumn = Tokens.back()->OriginalColumn;
- SourceLocation Loc = Tokens.back()->Tok.getLocation();
- if (MightEndWithEscapedSlash) {
- // This regex literal ends in '\//'. Skip past the '//' of the last
- // token and re-start lexing from there.
- resetLexer(SourceMgr.getFileOffset(Loc) + 2);
- } else if (SlashInStringPos != StringRef::npos) {
- // This regex literal ends in a string_literal with a slash inside.
- // Calculate end column and reset lexer appropriately.
- resetLexer(SourceMgr.getFileOffset(Loc) + SlashInStringPos + 1);
- LastColumn += SlashInStringPos;
- }
- Tokens.resize(Tokens.size() - TokenCount);
- Tokens.back()->Tok.setKind(tok::unknown);
- Tokens.back()->Type = TT_RegexLiteral;
- // Treat regex literals like other string_literals.
- Tokens.back()->Tok.setKind(tok::string_literal);
- Tokens.back()->ColumnWidth += LastColumn - I[0]->OriginalColumn;
- return true;
+ // NB: Because previous pointers are not initialized yet, this cannot use
+ // Token.getPreviousNonComment.
+ if ((*I)->isNot(tok::comment)) {
+ Prev = *I;
+ break;
}
+ }
- // There can't be a newline inside a regex literal.
- if (I[0]->NewlinesBefore > 0)
- return false;
+ if (!canPrecedeRegexLiteral(Prev))
+ return;
+
+ // 'Manually' lex ahead in the current file buffer.
+ const char *Offset = Lex->getBufferLocation();
+ const char *RegexBegin = Offset - RegexToken->TokenText.size();
+ StringRef Buffer = Lex->getBuffer();
+ bool InCharacterClass = false;
+ bool HaveClosingSlash = false;
+ for (; !HaveClosingSlash && Offset != Buffer.end(); ++Offset) {
+ // Regular expressions are terminated with a '/', which can only be
+ // escaped using '\' or a character class between '[' and ']'.
+ // See http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.5.
+ switch (*Offset) {
+ case '\\':
+ // Skip the escaped character.
+ ++Offset;
+ break;
+ case '[':
+ InCharacterClass = true;
+ break;
+ case ']':
+ InCharacterClass = false;
+ break;
+ case '/':
+ if (!InCharacterClass)
+ HaveClosingSlash = true;
+ break;
+ }
}
- return false;
+
+ RegexToken->Type = TT_RegexLiteral;
+ // Treat regex literals like other string_literals.
+ RegexToken->Tok.setKind(tok::string_literal);
+ RegexToken->TokenText = StringRef(RegexBegin, Offset - RegexBegin);
+ RegexToken->ColumnWidth = RegexToken->TokenText.size();
+
+ resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset)));
}
bool tryMergeTemplateString() {
@@ -1100,6 +1239,8 @@ private:
FormatTok->Type = TT_ImplicitStringLiteral;
break;
}
+ if (FormatTok->Type == TT_ImplicitStringLiteral)
+ break;
}
if (FormatTok->is(TT_ImplicitStringLiteral))
@@ -1138,7 +1279,13 @@ private:
FormatTok->Tok.setIdentifierInfo(&Info);
FormatTok->Tok.setKind(Info.getTokenID());
if (Style.Language == FormatStyle::LK_Java &&
- FormatTok->isOneOf(tok::kw_struct, tok::kw_union, tok::kw_delete)) {
+ FormatTok->isOneOf(tok::kw_struct, tok::kw_union, tok::kw_delete,
+ tok::kw_operator)) {
+ FormatTok->Tok.setKind(tok::identifier);
+ FormatTok->Tok.setIdentifierInfo(nullptr);
+ } else if (Style.Language == FormatStyle::LK_JavaScript &&
+ FormatTok->isOneOf(tok::kw_struct, tok::kw_union,
+ tok::kw_operator)) {
FormatTok->Tok.setKind(tok::identifier);
FormatTok->Tok.setIdentifierInfo(nullptr);
}
@@ -1485,11 +1632,46 @@ private:
return Text.count('\r') * 2 > Text.count('\n');
}
+ bool
+ hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
+ for (const AnnotatedLine* Line : Lines) {
+ if (hasCpp03IncompatibleFormat(Line->Children))
+ return true;
+ for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
+ if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) {
+ if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
+ return true;
+ if (Tok->is(TT_TemplateCloser) &&
+ Tok->Previous->is(TT_TemplateCloser))
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
+ int AlignmentDiff = 0;
+ for (const AnnotatedLine* Line : Lines) {
+ AlignmentDiff += countVariableAlignments(Line->Children);
+ for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
+ if (!Tok->is(TT_PointerOrReference))
+ continue;
+ bool SpaceBefore =
+ Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
+ bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() !=
+ Tok->Next->WhitespaceRange.getEnd();
+ if (SpaceBefore && !SpaceAfter)
+ ++AlignmentDiff;
+ if (!SpaceBefore && SpaceAfter)
+ --AlignmentDiff;
+ }
+ }
+ return AlignmentDiff;
+ }
+
void
deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
- unsigned CountBoundToVariable = 0;
- unsigned CountBoundToType = 0;
- bool HasCpp03IncompatibleFormat = false;
bool HasBinPackedFunction = false;
bool HasOnePerLineFunction = false;
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
@@ -1497,25 +1679,6 @@ private:
continue;
FormatToken *Tok = AnnotatedLines[i]->First->Next;
while (Tok->Next) {
- if (Tok->is(TT_PointerOrReference)) {
- bool SpacesBefore =
- Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
- bool SpacesAfter = Tok->Next->WhitespaceRange.getBegin() !=
- Tok->Next->WhitespaceRange.getEnd();
- if (SpacesBefore && !SpacesAfter)
- ++CountBoundToVariable;
- else if (!SpacesBefore && SpacesAfter)
- ++CountBoundToType;
- }
-
- if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) {
- if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
- HasCpp03IncompatibleFormat = true;
- if (Tok->is(TT_TemplateCloser) &&
- Tok->Previous->is(TT_TemplateCloser))
- HasCpp03IncompatibleFormat = true;
- }
-
if (Tok->PackingKind == PPK_BinPacked)
HasBinPackedFunction = true;
if (Tok->PackingKind == PPK_OnePerLine)
@@ -1524,16 +1687,14 @@ private:
Tok = Tok->Next;
}
}
- if (Style.DerivePointerAlignment) {
- if (CountBoundToType > CountBoundToVariable)
- Style.PointerAlignment = FormatStyle::PAS_Left;
- else if (CountBoundToType < CountBoundToVariable)
- Style.PointerAlignment = FormatStyle::PAS_Right;
- }
- if (Style.Standard == FormatStyle::LS_Auto) {
- Style.Standard = HasCpp03IncompatibleFormat ? FormatStyle::LS_Cpp11
- : FormatStyle::LS_Cpp03;
- }
+ if (Style.DerivePointerAlignment)
+ Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0
+ ? FormatStyle::PAS_Left
+ : FormatStyle::PAS_Right;
+ if (Style.Standard == FormatStyle::LS_Auto)
+ Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
+ ? FormatStyle::LS_Cpp11
+ : FormatStyle::LS_Cpp03;
BinPackInconclusiveFunctions =
HasBinPackedFunction || !HasOnePerLineFunction;
}
@@ -1558,15 +1719,175 @@ private:
bool BinPackInconclusiveFunctions;
};
+struct IncludeDirective {
+ StringRef Filename;
+ StringRef Text;
+ unsigned Offset;
+ int Category;
+};
+
} // end anonymous namespace
+// Determines whether 'Ranges' intersects with ('Start', 'End').
+static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
+ unsigned End) {
+ for (auto Range : Ranges) {
+ if (Range.getOffset() < End &&
+ Range.getOffset() + Range.getLength() > Start)
+ return true;
+ }
+ return false;
+}
+
+// Sorts a block of includes given by 'Includes' alphabetically adding the
+// necessary replacement to 'Replaces'. 'Includes' must be in strict source
+// order.
+static void sortIncludes(const FormatStyle &Style,
+ const SmallVectorImpl<IncludeDirective> &Includes,
+ ArrayRef<tooling::Range> Ranges, StringRef FileName,
+ tooling::Replacements &Replaces, unsigned *Cursor) {
+ if (!affectsRange(Ranges, Includes.front().Offset,
+ Includes.back().Offset + Includes.back().Text.size()))
+ return;
+ SmallVector<unsigned, 16> Indices;
+ for (unsigned i = 0, e = Includes.size(); i != e; ++i)
+ Indices.push_back(i);
+ std::sort(Indices.begin(), Indices.end(), [&](unsigned LHSI, unsigned RHSI) {
+ return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) <
+ std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
+ });
+
+ // If the #includes are out of order, we generate a single replacement fixing
+ // the entire block. Otherwise, no replacement is generated.
+ bool OutOfOrder = false;
+ for (unsigned i = 1, e = Indices.size(); i != e; ++i) {
+ if (Indices[i] != i) {
+ OutOfOrder = true;
+ break;
+ }
+ }
+ if (!OutOfOrder)
+ return;
+
+ std::string result;
+ bool CursorMoved = false;
+ for (unsigned Index : Indices) {
+ if (!result.empty())
+ result += "\n";
+ result += Includes[Index].Text;
+
+ if (Cursor && !CursorMoved) {
+ unsigned Start = Includes[Index].Offset;
+ unsigned End = Start + Includes[Index].Text.size();
+ if (*Cursor >= Start && *Cursor < End) {
+ *Cursor = Includes.front().Offset + result.size() + *Cursor - End;
+ CursorMoved = true;
+ }
+ }
+ }
+
+ // Sorting #includes shouldn't change their total number of characters.
+ // This would otherwise mess up 'Ranges'.
+ assert(result.size() ==
+ Includes.back().Offset + Includes.back().Text.size() -
+ Includes.front().Offset);
+
+ Replaces.insert(tooling::Replacement(FileName, Includes.front().Offset,
+ result.size(), result));
+}
+
+tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
+ ArrayRef<tooling::Range> Ranges,
+ StringRef FileName, unsigned *Cursor) {
+ tooling::Replacements Replaces;
+ if (!Style.SortIncludes)
+ return Replaces;
+
+ unsigned Prev = 0;
+ unsigned SearchFrom = 0;
+ llvm::Regex IncludeRegex(
+ R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))");
+ SmallVector<StringRef, 4> Matches;
+ SmallVector<IncludeDirective, 16> IncludesInBlock;
+
+ // In compiled files, consider the first #include to be the main #include of
+ // the file if it is not a system #include. This ensures that the header
+ // doesn't have hidden dependencies
+ // (http://llvm.org/docs/CodingStandards.html#include-style).
+ //
+ // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix
+ // cases where the first #include is unlikely to be the main header.
+ bool IsSource = FileName.endswith(".c") || FileName.endswith(".cc") ||
+ FileName.endswith(".cpp") || FileName.endswith(".c++") ||
+ FileName.endswith(".cxx") || FileName.endswith(".m") ||
+ FileName.endswith(".mm");
+ StringRef FileStem = llvm::sys::path::stem(FileName);
+ bool FirstIncludeBlock = true;
+ bool MainIncludeFound = false;
+
+ // Create pre-compiled regular expressions for the #include categories.
+ SmallVector<llvm::Regex, 4> CategoryRegexs;
+ for (const auto &Category : Style.IncludeCategories)
+ CategoryRegexs.emplace_back(Category.Regex);
+
+ bool FormattingOff = false;
+
+ for (;;) {
+ auto Pos = Code.find('\n', SearchFrom);
+ StringRef Line =
+ Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
+
+ StringRef Trimmed = Line.trim();
+ if (Trimmed == "// clang-format off")
+ FormattingOff = true;
+ else if (Trimmed == "// clang-format on")
+ FormattingOff = false;
+
+ if (!FormattingOff && !Line.endswith("\\")) {
+ if (IncludeRegex.match(Line, &Matches)) {
+ StringRef IncludeName = Matches[2];
+ int Category = INT_MAX;
+ for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i) {
+ if (CategoryRegexs[i].match(IncludeName)) {
+ Category = Style.IncludeCategories[i].Priority;
+ break;
+ }
+ }
+ if (IsSource && !MainIncludeFound && Category > 0 &&
+ FirstIncludeBlock && IncludeName.startswith("\"")) {
+ StringRef HeaderStem =
+ llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
+ if (FileStem.startswith(HeaderStem)) {
+ Category = 0;
+ MainIncludeFound = true;
+ }
+ }
+ IncludesInBlock.push_back({IncludeName, Line, Prev, Category});
+ } else if (!IncludesInBlock.empty()) {
+ sortIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces,
+ Cursor);
+ IncludesInBlock.clear();
+ FirstIncludeBlock = false;
+ }
+ Prev = Pos + 1;
+ }
+ if (Pos == StringRef::npos || Pos + 1 == Code.size())
+ break;
+ SearchFrom = Pos + 1;
+ }
+ if (!IncludesInBlock.empty())
+ sortIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, Cursor);
+ return Replaces;
+}
+
tooling::Replacements reformat(const FormatStyle &Style,
SourceManager &SourceMgr, FileID ID,
ArrayRef<CharSourceRange> Ranges,
bool *IncompleteFormat) {
- if (Style.DisableFormat)
+ FormatStyle Expanded = expandPresets(Style);
+ if (Expanded.DisableFormat)
return tooling::Replacements();
- Formatter formatter(Style, SourceMgr, ID, Ranges);
+ Formatter formatter(Expanded, SourceMgr, ID, Ranges);
return formatter.format(IncompleteFormat);
}
@@ -1576,18 +1897,18 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
if (Style.DisableFormat)
return tooling::Replacements();
- FileManager Files((FileSystemOptions()));
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ FileManager Files(FileSystemOptions(), InMemoryFileSystem);
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
new DiagnosticOptions);
SourceManager SourceMgr(Diagnostics, Files);
- std::unique_ptr<llvm::MemoryBuffer> Buf =
- llvm::MemoryBuffer::getMemBuffer(Code, FileName);
- const clang::FileEntry *Entry =
- Files.getVirtualFile(FileName, Buf->getBufferSize(), 0);
- SourceMgr.overrideFileContents(Entry, std::move(Buf));
- FileID ID =
- SourceMgr.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User);
+ InMemoryFileSystem->addFile(
+ FileName, 0, llvm::MemoryBuffer::getMemBuffer(
+ Code, FileName, /*RequiresNullTerminator=*/false));
+ FileID ID = SourceMgr.createFileID(Files.getFile(FileName), SourceLocation(),
+ clang::SrcMgr::C_User);
SourceLocation StartOfFile = SourceMgr.getLocForStartOfFile(ID);
std::vector<CharSourceRange> CharRanges;
for (const tooling::Range &Range : Ranges) {
@@ -1610,6 +1931,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
LangOpts.ObjC1 = 1;
LangOpts.ObjC2 = 1;
LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
+ LangOpts.DeclSpecKeyword = 1; // To get __declspec.
return LangOpts;
}
@@ -1625,15 +1947,15 @@ const char *StyleOptionHelpDescription =
" -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
- if (FileName.endswith(".java")) {
+ if (FileName.endswith(".java"))
return FormatStyle::LK_Java;
- } else if (FileName.endswith_lower(".js") || FileName.endswith_lower(".ts")) {
- // JavaScript or TypeScript.
- return FormatStyle::LK_JavaScript;
- } else if (FileName.endswith_lower(".proto") ||
- FileName.endswith_lower(".protodevel")) {
+ if (FileName.endswith_lower(".js") || FileName.endswith_lower(".ts"))
+ return FormatStyle::LK_JavaScript; // JavaScript or TypeScript.
+ if (FileName.endswith_lower(".proto") ||
+ FileName.endswith_lower(".protodevel"))
return FormatStyle::LK_Proto;
- }
+ if (FileName.endswith_lower(".td"))
+ return FormatStyle::LK_TableGen;
return FormatStyle::LK_Cpp;
}
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp b/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
index 6c244c3..d6cd450 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/FormatToken.cpp
@@ -13,8 +13,8 @@
///
//===----------------------------------------------------------------------===//
-#include "FormatToken.h"
#include "ContinuationIndenter.h"
+#include "FormatToken.h"
#include "clang/Format/Format.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Debug.h"
@@ -80,8 +80,8 @@ unsigned CommaSeparatedList::formatAfterToken(LineState &State,
// Ensure that we start on the opening brace.
const FormatToken *LBrace =
State.NextToken->Previous->getPreviousNonComment();
- if (!LBrace || LBrace->isNot(tok::l_brace) || LBrace->BlockKind == BK_Block ||
- LBrace->Type == TT_DictLiteral ||
+ if (!LBrace || !LBrace->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) ||
+ LBrace->BlockKind == BK_Block || LBrace->Type == TT_DictLiteral ||
LBrace->Next->Type == TT_DesignatedInitializerPeriod)
return 0;
@@ -144,7 +144,8 @@ static unsigned CodePointsBetween(const FormatToken *Begin,
void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
// FIXME: At some point we might want to do this for other lists, too.
- if (!Token->MatchingParen || Token->isNot(tok::l_brace))
+ if (!Token->MatchingParen ||
+ !Token->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare))
return;
// In C++11 braced list style, we should not format in columns unless they
@@ -154,8 +155,14 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
Commas.size() < 19)
return;
+ // Limit column layout for JavaScript array initializers to 20 or more items
+ // for now to introduce it carefully. We can become more aggressive if this
+ // necessary.
+ if (Token->is(TT_ArrayInitializerLSquare) && Commas.size() < 19)
+ return;
+
// Column format doesn't really make sense if we don't align after brackets.
- if (!Style.AlignAfterOpenBracket)
+ if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign)
return;
FormatToken *ItemBegin = Token->Next;
@@ -183,7 +190,8 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
ItemEnd = Token->MatchingParen;
const FormatToken *NonCommentEnd = ItemEnd->getPreviousNonComment();
ItemLengths.push_back(CodePointsBetween(ItemBegin, NonCommentEnd));
- if (Style.Cpp11BracedListStyle) {
+ if (Style.Cpp11BracedListStyle &&
+ !ItemEnd->Previous->isTrailingComment()) {
// In Cpp11 braced list style, the } and possibly other subsequent
// tokens will need to stay on a line with the last element.
while (ItemEnd->Next && !ItemEnd->Next->CanBreakBefore)
@@ -210,9 +218,12 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
ItemBegin = ItemEnd->Next;
}
- // Don't use column layout for nested lists, lists with few elements and in
- // presence of separating comments.
- if (Token->NestingLevel != 0 || Commas.size() < 5 || HasSeparatingComment)
+ // Don't use column layout for lists with few elements and in presence of
+ // separating comments.
+ if (Commas.size() < 5 || HasSeparatingComment)
+ return;
+
+ if (Token->NestingLevel != 0 && Token->is(tok::l_brace) && Commas.size() < 19)
return;
// We can never place more than ColumnLimit / 3 items in a row (because of the
diff --git a/contrib/llvm/tools/clang/lib/Format/FormatToken.h b/contrib/llvm/tools/clang/lib/Format/FormatToken.h
index f335eda..b683660 100644
--- a/contrib/llvm/tools/clang/lib/Format/FormatToken.h
+++ b/contrib/llvm/tools/clang/lib/Format/FormatToken.h
@@ -248,9 +248,9 @@ struct FormatToken {
/// with the same precedence, contains the 0-based operator index.
unsigned OperatorIndex = 0;
- /// \brief Is this the last operator (or "."/"->") in a sequence of operators
- /// with the same precedence?
- bool LastOperator = false;
+ /// \brief If this is an operator (or "."/"->") in a sequence of operators
+ /// with the same precedence, points to the next operator.
+ FormatToken *NextOperator = nullptr;
/// \brief Is this token part of a \c DeclStmt defining multiple variables?
///
@@ -283,6 +283,10 @@ struct FormatToken {
bool is(const IdentifierInfo *II) const {
return II && II == Tok.getIdentifierInfo();
}
+ bool is(tok::PPKeywordKind Kind) const {
+ return Tok.getIdentifierInfo() &&
+ Tok.getIdentifierInfo()->getPPKeywordID() == Kind;
+ }
template <typename A, typename B> bool isOneOf(A K1, B K2) const {
return is(K1) || is(K2);
}
@@ -408,16 +412,16 @@ struct FormatToken {
/// \brief Returns \c true if this tokens starts a block-type list, i.e. a
/// list that should be indented with a block indent.
- bool opensBlockTypeList(const FormatStyle &Style) const {
+ bool opensBlockOrBlockTypeList(const FormatStyle &Style) const {
return is(TT_ArrayInitializerLSquare) ||
(is(tok::l_brace) &&
(BlockKind == BK_Block || is(TT_DictLiteral) ||
(!Style.Cpp11BracedListStyle && NestingLevel == 0)));
}
- /// \brief Same as opensBlockTypeList, but for the closing token.
- bool closesBlockTypeList(const FormatStyle &Style) const {
- return MatchingParen && MatchingParen->opensBlockTypeList(Style);
+ /// \brief Same as opensBlockOrBlockTypeList, but for the closing token.
+ bool closesBlockOrBlockTypeList(const FormatStyle &Style) const {
+ return MatchingParen && MatchingParen->opensBlockOrBlockTypeList(Style);
}
private:
@@ -521,6 +525,8 @@ private:
/// properly supported by Clang's lexer.
struct AdditionalKeywords {
AdditionalKeywords(IdentifierTable &IdentTable) {
+ kw_final = &IdentTable.get("final");
+ kw_override = &IdentTable.get("override");
kw_in = &IdentTable.get("in");
kw_CF_ENUM = &IdentTable.get("CF_ENUM");
kw_CF_OPTIONS = &IdentTable.get("CF_OPTIONS");
@@ -530,11 +536,13 @@ struct AdditionalKeywords {
kw_finally = &IdentTable.get("finally");
kw_function = &IdentTable.get("function");
kw_import = &IdentTable.get("import");
+ kw_is = &IdentTable.get("is");
+ kw_let = &IdentTable.get("let");
kw_var = &IdentTable.get("var");
kw_abstract = &IdentTable.get("abstract");
+ kw_assert = &IdentTable.get("assert");
kw_extends = &IdentTable.get("extends");
- kw_final = &IdentTable.get("final");
kw_implements = &IdentTable.get("implements");
kw_instanceof = &IdentTable.get("instanceof");
kw_interface = &IdentTable.get("interface");
@@ -546,6 +554,7 @@ struct AdditionalKeywords {
kw_mark = &IdentTable.get("mark");
+ kw_extend = &IdentTable.get("extend");
kw_option = &IdentTable.get("option");
kw_optional = &IdentTable.get("optional");
kw_repeated = &IdentTable.get("repeated");
@@ -553,11 +562,14 @@ struct AdditionalKeywords {
kw_returns = &IdentTable.get("returns");
kw_signals = &IdentTable.get("signals");
+ kw_qsignals = &IdentTable.get("Q_SIGNALS");
kw_slots = &IdentTable.get("slots");
kw_qslots = &IdentTable.get("Q_SLOTS");
}
// Context sensitive keywords.
+ IdentifierInfo *kw_final;
+ IdentifierInfo *kw_override;
IdentifierInfo *kw_in;
IdentifierInfo *kw_CF_ENUM;
IdentifierInfo *kw_CF_OPTIONS;
@@ -569,12 +581,14 @@ struct AdditionalKeywords {
IdentifierInfo *kw_finally;
IdentifierInfo *kw_function;
IdentifierInfo *kw_import;
+ IdentifierInfo *kw_is;
+ IdentifierInfo *kw_let;
IdentifierInfo *kw_var;
// Java keywords.
IdentifierInfo *kw_abstract;
+ IdentifierInfo *kw_assert;
IdentifierInfo *kw_extends;
- IdentifierInfo *kw_final;
IdentifierInfo *kw_implements;
IdentifierInfo *kw_instanceof;
IdentifierInfo *kw_interface;
@@ -587,6 +601,7 @@ struct AdditionalKeywords {
IdentifierInfo *kw_mark;
// Proto keywords.
+ IdentifierInfo *kw_extend;
IdentifierInfo *kw_option;
IdentifierInfo *kw_optional;
IdentifierInfo *kw_repeated;
@@ -595,6 +610,7 @@ struct AdditionalKeywords {
// QT keywords.
IdentifierInfo *kw_signals;
+ IdentifierInfo *kw_qsignals;
IdentifierInfo *kw_slots;
IdentifierInfo *kw_qslots;
};
diff --git a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
index ea8b30d..8fbb43b 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.cpp
@@ -119,9 +119,12 @@ private:
}
}
- if (Left->Previous &&
- (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_if,
- tok::kw_while, tok::l_paren, tok::comma) ||
+ if (Left->is(TT_OverloadedOperatorLParen)) {
+ Contexts.back().IsExpression = false;
+ } else if (Left->Previous &&
+ (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype,
+ tok::kw_if, tok::kw_while, tok::l_paren,
+ tok::comma) ||
Left->Previous->is(TT_BinaryOperator))) {
// static_assert, if and while usually contain expressions.
Contexts.back().IsExpression = true;
@@ -131,9 +134,7 @@ private:
// This is a parameter list of a lambda expression.
Contexts.back().IsExpression = false;
} else if (Line.InPPDirective &&
- (!Left->Previous ||
- !Left->Previous->isOneOf(tok::identifier,
- TT_OverloadedOperator))) {
+ (!Left->Previous || !Left->Previous->is(tok::identifier))) {
Contexts.back().IsExpression = true;
} else if (Contexts[Contexts.size() - 2].CaretFound) {
// This is the parameter list of an ObjC block.
@@ -147,6 +148,10 @@ private:
} else if (Left->Previous && Left->Previous->MatchingParen &&
Left->Previous->MatchingParen->is(TT_ObjCBlockLParen)) {
Contexts.back().IsExpression = false;
+ } else if (!Line.MustBeDeclaration && !Line.InPPDirective) {
+ bool IsForOrCatch =
+ Left->Previous && Left->Previous->isOneOf(tok::kw_for, tok::kw_catch);
+ Contexts.back().IsExpression = !IsForOrCatch;
}
if (StartsObjCMethodExpr) {
@@ -154,7 +159,8 @@ private:
Left->Type = TT_ObjCMethodExpr;
}
- bool MightBeFunctionType = CurrentToken->is(tok::star);
+ bool MightBeFunctionType = CurrentToken->isOneOf(tok::star, tok::amp) &&
+ !Contexts[Contexts.size() - 2].IsExpression;
bool HasMultipleLines = false;
bool HasMultipleParametersOnALine = false;
bool MightBeObjCForRangeLoop =
@@ -188,11 +194,23 @@ private:
if (MightBeFunctionType && CurrentToken->Next &&
(CurrentToken->Next->is(tok::l_paren) ||
(CurrentToken->Next->is(tok::l_square) &&
- !Contexts.back().IsExpression)))
+ Line.MustBeDeclaration)))
Left->Type = TT_FunctionTypeLParen;
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
+ if (CurrentToken->Next && CurrentToken->Next->is(tok::l_brace) &&
+ Left->Previous && Left->Previous->is(tok::l_paren)) {
+ // Detect the case where macros are used to generate lambdas or
+ // function bodies, e.g.:
+ // auto my_lambda = MARCO((Type *type, int i) { .. body .. });
+ for (FormatToken *Tok = Left; Tok != CurrentToken; Tok = Tok->Next) {
+ if (Tok->is(TT_BinaryOperator) &&
+ Tok->isOneOf(tok::star, tok::amp, tok::ampamp))
+ Tok->Type = TT_PointerOrReference;
+ }
+ }
+
if (StartsObjCMethodExpr) {
CurrentToken->Type = TT_ObjCMethodExpr;
if (Contexts.back().FirstObjCSelectorName) {
@@ -279,10 +297,13 @@ private:
Contexts.back().ContextKind == tok::l_brace &&
Parent->isOneOf(tok::l_brace, tok::comma)) {
Left->Type = TT_JsComputedPropertyName;
- } else if (Parent &&
- Parent->isOneOf(tok::at, tok::equal, tok::comma, tok::l_paren,
- tok::l_square, tok::question, tok::colon,
- tok::kw_return)) {
+ } else if (Style.Language == FormatStyle::LK_Proto ||
+ (Parent &&
+ Parent->isOneOf(TT_BinaryOperator, tok::at, tok::comma,
+ tok::l_paren, tok::l_square, tok::question,
+ tok::colon, tok::kw_return,
+ // Should only be relevant to JavaScript:
+ tok::kw_default))) {
Left->Type = TT_ArrayInitializerLSquare;
} else {
BindingIncrease = 10;
@@ -371,9 +392,11 @@ private:
updateParameterCount(Left, CurrentToken);
if (CurrentToken->isOneOf(tok::colon, tok::l_brace)) {
FormatToken *Previous = CurrentToken->getPreviousNonComment();
- if ((CurrentToken->is(tok::colon) ||
+ if (((CurrentToken->is(tok::colon) &&
+ (!Contexts.back().ColonIsDictLiteral ||
+ Style.Language != FormatStyle::LK_Cpp)) ||
Style.Language == FormatStyle::LK_Proto) &&
- Previous->is(tok::identifier))
+ Previous->Tok.getIdentifierInfo())
Previous->Type = TT_SelectorName;
if (CurrentToken->is(tok::colon) ||
Style.Language == FormatStyle::LK_JavaScript)
@@ -387,12 +410,8 @@ private:
}
void updateParameterCount(FormatToken *Left, FormatToken *Current) {
- if (Current->is(TT_LambdaLSquare) ||
- (Current->is(tok::caret) && Current->is(TT_UnaryOperator)) ||
- (Style.Language == FormatStyle::LK_JavaScript &&
- Current->is(Keywords.kw_function))) {
+ if (Current->is(tok::l_brace) && !Current->is(TT_DictLiteral))
++Left->BlockParameterCount;
- }
if (Current->is(tok::comma)) {
++Left->ParameterCount;
if (!Left->Role)
@@ -454,16 +473,16 @@ private:
break;
}
}
- if (Contexts.back().ColonIsDictLiteral) {
+ if (Contexts.back().ColonIsDictLiteral ||
+ Style.Language == FormatStyle::LK_Proto) {
Tok->Type = TT_DictLiteral;
} else if (Contexts.back().ColonIsObjCMethodExpr ||
Line.startsWith(TT_ObjCMethodSpecifier)) {
Tok->Type = TT_ObjCMethodExpr;
Tok->Previous->Type = TT_SelectorName;
if (Tok->Previous->ColumnWidth >
- Contexts.back().LongestObjCSelectorName) {
+ Contexts.back().LongestObjCSelectorName)
Contexts.back().LongestObjCSelectorName = Tok->Previous->ColumnWidth;
- }
if (!Contexts.back().FirstObjCSelectorName)
Contexts.back().FirstObjCSelectorName = Tok->Previous;
} else if (Contexts.back().ColonIsForRangeExpr) {
@@ -500,6 +519,19 @@ private:
return false;
break;
case tok::l_paren:
+ // When faced with 'operator()()', the kw_operator handler incorrectly
+ // marks the first l_paren as a OverloadedOperatorLParen. Here, we make
+ // the first two parens OverloadedOperators and the second l_paren an
+ // OverloadedOperatorLParen.
+ if (Tok->Previous &&
+ Tok->Previous->is(tok::r_paren) &&
+ Tok->Previous->MatchingParen &&
+ Tok->Previous->MatchingParen->is(TT_OverloadedOperatorLParen)) {
+ Tok->Previous->Type = TT_OverloadedOperator;
+ Tok->Previous->MatchingParen->Type = TT_OverloadedOperator;
+ Tok->Type = TT_OverloadedOperatorLParen;
+ }
+
if (!parseParens())
return false;
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
@@ -548,7 +580,8 @@ private:
if (CurrentToken->isOneOf(tok::star, tok::amp))
CurrentToken->Type = TT_PointerOrReference;
consumeToken();
- if (CurrentToken && CurrentToken->Previous->is(TT_BinaryOperator))
+ if (CurrentToken &&
+ CurrentToken->Previous->isOneOf(TT_BinaryOperator, tok::comma))
CurrentToken->Previous->Type = TT_OverloadedOperator;
}
if (CurrentToken) {
@@ -715,7 +748,7 @@ public:
while (CurrentToken) {
if (CurrentToken->is(tok::kw_virtual))
KeywordVirtualFound = true;
- if (IsImportStatement(*CurrentToken))
+ if (isImportStatement(*CurrentToken))
ImportStatement = true;
if (!consumeToken())
return LT_Invalid;
@@ -736,14 +769,15 @@ public:
}
private:
- bool IsImportStatement(const FormatToken &Tok) {
+ bool isImportStatement(const FormatToken &Tok) {
// FIXME: Closure-library specific stuff should not be hard-coded but be
// configurable.
return Style.Language == FormatStyle::LK_JavaScript &&
Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) &&
Tok.Next->Next && (Tok.Next->Next->TokenText == "module" ||
+ Tok.Next->Next->TokenText == "provide" ||
Tok.Next->Next->TokenText == "require" ||
- Tok.Next->Next->TokenText == "provide") &&
+ Tok.Next->Next->TokenText == "setTestOnly") &&
Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren);
}
@@ -818,12 +852,13 @@ private:
void modifyContext(const FormatToken &Current) {
if (Current.getPrecedence() == prec::Assignment &&
- !Line.First->isOneOf(tok::kw_template, tok::kw_using) &&
+ !Line.First->isOneOf(tok::kw_template, tok::kw_using, tok::kw_return) &&
(!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
Contexts.back().IsExpression = true;
if (!Line.startsWith(TT_UnaryOperator)) {
for (FormatToken *Previous = Current.Previous;
- Previous && !Previous->isOneOf(tok::comma, tok::semi);
+ Previous && Previous->Previous &&
+ !Previous->Previous->isOneOf(tok::comma, tok::semi);
Previous = Previous->Previous) {
if (Previous->isOneOf(tok::r_square, tok::r_paren)) {
Previous = Previous->MatchingParen;
@@ -845,19 +880,8 @@ private:
Contexts.back().IsExpression = true;
} else if (Current.is(TT_TrailingReturnArrow)) {
Contexts.back().IsExpression = false;
- } else if (Current.is(TT_LambdaArrow)) {
+ } else if (Current.is(TT_LambdaArrow) || Current.is(Keywords.kw_assert)) {
Contexts.back().IsExpression = Style.Language == FormatStyle::LK_Java;
- } else if (Current.is(tok::l_paren) && !Line.MustBeDeclaration &&
- !Line.InPPDirective &&
- (!Current.Previous ||
- Current.Previous->isNot(tok::kw_decltype))) {
- bool ParametersOfFunctionType =
- Current.Previous && Current.Previous->is(tok::r_paren) &&
- Current.Previous->MatchingParen &&
- Current.Previous->MatchingParen->is(TT_FunctionTypeLParen);
- bool IsForOrCatch = Current.Previous &&
- Current.Previous->isOneOf(tok::kw_for, tok::kw_catch);
- Contexts.back().IsExpression = !ParametersOfFunctionType && !IsForOrCatch;
} else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {
for (FormatToken *Previous = Current.Previous;
Previous && Previous->isOneOf(tok::star, tok::amp);
@@ -891,7 +915,7 @@ private:
(!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) {
Contexts.back().FirstStartOfName = &Current;
Current.Type = TT_StartOfName;
- } else if (Current.is(tok::kw_auto)) {
+ } else if (Current.isOneOf(tok::kw_auto, tok::kw___auto_type)) {
AutoFound = true;
} else if (Current.is(tok::arrow) &&
Style.Language == FormatStyle::LK_Java) {
@@ -1035,82 +1059,101 @@ private:
PreviousNotConst->MatchingParen->Previous->is(tok::kw_decltype))
return true;
- return (!IsPPKeyword && PreviousNotConst->is(tok::identifier)) ||
+ return (!IsPPKeyword &&
+ PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto)) ||
PreviousNotConst->is(TT_PointerOrReference) ||
PreviousNotConst->isSimpleTypeSpecifier();
}
/// \brief Determine whether ')' is ending a cast.
bool rParenEndsCast(const FormatToken &Tok) {
- FormatToken *LeftOfParens = nullptr;
- if (Tok.MatchingParen)
- LeftOfParens = Tok.MatchingParen->getPreviousNonComment();
- if (LeftOfParens && LeftOfParens->is(tok::r_paren) &&
- LeftOfParens->MatchingParen)
- LeftOfParens = LeftOfParens->MatchingParen->Previous;
- if (LeftOfParens && LeftOfParens->is(tok::r_square) &&
- LeftOfParens->MatchingParen &&
- LeftOfParens->MatchingParen->is(TT_LambdaLSquare))
+ // C-style casts are only used in C++ and Java.
+ if (Style.Language != FormatStyle::LK_Cpp &&
+ Style.Language != FormatStyle::LK_Java)
return false;
- if (Tok.Next) {
- if (Tok.Next->is(tok::question))
+
+ // Empty parens aren't casts and there are no casts at the end of the line.
+ if (Tok.Previous == Tok.MatchingParen || !Tok.Next || !Tok.MatchingParen)
+ return false;
+
+ FormatToken *LeftOfParens = Tok.MatchingParen->getPreviousNonComment();
+ if (LeftOfParens) {
+ // If there is an opening parenthesis left of the current parentheses,
+ // look past it as these might be chained casts.
+ if (LeftOfParens->is(tok::r_paren)) {
+ if (!LeftOfParens->MatchingParen ||
+ !LeftOfParens->MatchingParen->Previous)
+ return false;
+ LeftOfParens = LeftOfParens->MatchingParen->Previous;
+ }
+
+ // If there is an identifier (or with a few exceptions a keyword) right
+ // before the parentheses, this is unlikely to be a cast.
+ if (LeftOfParens->Tok.getIdentifierInfo() &&
+ !LeftOfParens->isOneOf(Keywords.kw_in, tok::kw_return, tok::kw_case,
+ tok::kw_delete))
return false;
- if (Style.Language == FormatStyle::LK_JavaScript &&
- Tok.Next->is(Keywords.kw_in))
+
+ // Certain other tokens right before the parentheses are also signals that
+ // this cannot be a cast.
+ if (LeftOfParens->isOneOf(tok::at, tok::r_square, TT_OverloadedOperator,
+ TT_TemplateCloser))
return false;
- if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren))
- return true;
}
- bool IsCast = false;
- bool ParensAreEmpty = Tok.Previous == Tok.MatchingParen;
+
+ if (Tok.Next->is(tok::question))
+ return false;
+
+ // As Java has no function types, a "(" after the ")" likely means that this
+ // is a cast.
+ if (Style.Language == FormatStyle::LK_Java && Tok.Next->is(tok::l_paren))
+ return true;
+
+ // If a (non-string) literal follows, this is likely a cast.
+ if (Tok.Next->isNot(tok::string_literal) &&
+ (Tok.Next->Tok.isLiteral() ||
+ Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
+ return true;
+
+ // Heuristically try to determine whether the parentheses contain a type.
bool ParensAreType =
!Tok.Previous ||
Tok.Previous->isOneOf(TT_PointerOrReference, TT_TemplateCloser) ||
Tok.Previous->isSimpleTypeSpecifier();
bool ParensCouldEndDecl =
- Tok.Next && Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace);
- bool IsSizeOfOrAlignOf =
- LeftOfParens && LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof);
- if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
- (Contexts.size() > 1 && Contexts[Contexts.size() - 2].IsExpression))
- IsCast = true;
- else if (Tok.Next && Tok.Next->isNot(tok::string_literal) &&
- (Tok.Next->Tok.isLiteral() ||
- Tok.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
- IsCast = true;
- // If there is an identifier after the (), it is likely a cast, unless
- // there is also an identifier before the ().
- else if (LeftOfParens && Tok.Next &&
- (LeftOfParens->Tok.getIdentifierInfo() == nullptr ||
- LeftOfParens->isOneOf(tok::kw_return, tok::kw_case)) &&
- !LeftOfParens->isOneOf(TT_OverloadedOperator, tok::at,
- TT_TemplateCloser)) {
- if (Tok.Next->isOneOf(tok::identifier, tok::numeric_constant)) {
- IsCast = true;
- } else {
- // Use heuristics to recognize c style casting.
- FormatToken *Prev = Tok.Previous;
- if (Prev && Prev->isOneOf(tok::amp, tok::star))
- Prev = Prev->Previous;
-
- if (Prev && Tok.Next && Tok.Next->Next) {
- bool NextIsUnary = Tok.Next->isUnaryOperator() ||
- Tok.Next->isOneOf(tok::amp, tok::star);
- IsCast =
- NextIsUnary && !Tok.Next->is(tok::plus) &&
- Tok.Next->Next->isOneOf(tok::identifier, tok::numeric_constant);
- }
+ Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
+ if (ParensAreType && !ParensCouldEndDecl)
+ return true;
- for (; Prev != Tok.MatchingParen; Prev = Prev->Previous) {
- if (!Prev ||
- !Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon)) {
- IsCast = false;
- break;
- }
- }
- }
+ // At this point, we heuristically assume that there are no casts at the
+ // start of the line. We assume that we have found most cases where there
+ // are by the logic above, e.g. "(void)x;".
+ if (!LeftOfParens)
+ return false;
+
+ // If the following token is an identifier, this is a cast. All cases where
+ // this can be something else are handled above.
+ if (Tok.Next->is(tok::identifier))
+ return true;
+
+ if (!Tok.Next->Next)
+ return false;
+
+ // If the next token after the parenthesis is a unary operator, assume
+ // that this is cast, unless there are unexpected tokens inside the
+ // parenthesis.
+ bool NextIsUnary =
+ Tok.Next->isUnaryOperator() || Tok.Next->isOneOf(tok::amp, tok::star);
+ if (!NextIsUnary || Tok.Next->is(tok::plus) ||
+ !Tok.Next->Next->isOneOf(tok::identifier, tok::numeric_constant))
+ return false;
+ // Search for unexpected tokens.
+ for (FormatToken *Prev = Tok.Previous; Prev != Tok.MatchingParen;
+ Prev = Prev->Previous) {
+ if (!Prev->isOneOf(tok::kw_const, tok::identifier, tok::coloncolon))
+ return false;
}
- return IsCast && !ParensAreEmpty;
+ return true;
}
/// \brief Return the type of the given token assuming it is * or &.
@@ -1124,9 +1167,11 @@ private:
return TT_UnaryOperator;
const FormatToken *NextToken = Tok.getNextNonComment();
- if (!NextToken || NextToken->is(tok::arrow) ||
+ if (!NextToken ||
+ NextToken->isOneOf(tok::arrow, Keywords.kw_final,
+ Keywords.kw_override) ||
(NextToken->is(tok::l_brace) && !NextToken->getNextNonComment()))
- return TT_Unknown;
+ return TT_PointerOrReference;
if (PrevToken->is(tok::coloncolon))
return TT_PointerOrReference;
@@ -1140,7 +1185,9 @@ private:
if (NextToken->is(tok::l_square) && NextToken->isNot(TT_LambdaLSquare))
return TT_PointerOrReference;
- if (NextToken->isOneOf(tok::kw_operator, tok::comma, tok::semi))
+ if (NextToken->is(tok::kw_operator) && !IsExpression)
+ return TT_PointerOrReference;
+ if (NextToken->isOneOf(tok::comma, tok::semi))
return TT_PointerOrReference;
if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen &&
@@ -1296,6 +1343,8 @@ public:
} else {
// Operator found.
if (CurrentPrecedence == Precedence) {
+ if (LatestOperator)
+ LatestOperator->NextOperator = Current;
LatestOperator = Current;
Current->OperatorIndex = OperatorIndex;
++OperatorIndex;
@@ -1305,7 +1354,7 @@ public:
}
if (LatestOperator && (Current || Precedence > 0)) {
- LatestOperator->LastOperator = true;
+ // LatestOperator->LastOperator = true;
if (Precedence == PrecedenceArrowAndPeriod) {
// Call expressions don't have a binary operator precedence.
addFakeParenthesis(Start, prec::Unknown);
@@ -1460,25 +1509,56 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
// This function heuristically determines whether 'Current' starts the name of a
// function declaration.
static bool isFunctionDeclarationName(const FormatToken &Current) {
- if (!Current.is(TT_StartOfName) || Current.NestingLevel != 0)
- return false;
- const FormatToken *Next = Current.Next;
- for (; Next; Next = Next->Next) {
- if (Next->is(TT_TemplateOpener)) {
- Next = Next->MatchingParen;
- } else if (Next->is(tok::coloncolon)) {
- Next = Next->Next;
- if (!Next || !Next->is(tok::identifier))
- return false;
- } else if (Next->is(tok::l_paren)) {
+ auto skipOperatorName = [](const FormatToken* Next) -> const FormatToken* {
+ for (; Next; Next = Next->Next) {
+ if (Next->is(TT_OverloadedOperatorLParen))
+ return Next;
+ if (Next->is(TT_OverloadedOperator))
+ continue;
+ if (Next->isOneOf(tok::kw_new, tok::kw_delete)) {
+ // For 'new[]' and 'delete[]'.
+ if (Next->Next && Next->Next->is(tok::l_square) &&
+ Next->Next->Next && Next->Next->Next->is(tok::r_square))
+ Next = Next->Next->Next;
+ continue;
+ }
+
break;
- } else {
+ }
+ return nullptr;
+ };
+
+ const FormatToken *Next = Current.Next;
+ if (Current.is(tok::kw_operator)) {
+ if (Current.Previous && Current.Previous->is(tok::coloncolon))
+ return false;
+ Next = skipOperatorName(Next);
+ } else {
+ if (!Current.is(TT_StartOfName) || Current.NestingLevel != 0)
return false;
+ for (; Next; Next = Next->Next) {
+ if (Next->is(TT_TemplateOpener)) {
+ Next = Next->MatchingParen;
+ } else if (Next->is(tok::coloncolon)) {
+ Next = Next->Next;
+ if (!Next)
+ return false;
+ if (Next->is(tok::kw_operator)) {
+ Next = skipOperatorName(Next->Next);
+ break;
+ }
+ if (!Next->is(tok::identifier))
+ return false;
+ } else if (Next->is(tok::l_paren)) {
+ break;
+ } else {
+ return false;
+ }
}
}
- if (!Next)
+
+ if (!Next || !Next->is(tok::l_paren))
return false;
- assert(Next->is(tok::l_paren));
if (Next->Next == Next->MatchingParen)
return true;
for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen;
@@ -1493,6 +1573,29 @@ static bool isFunctionDeclarationName(const FormatToken &Current) {
return false;
}
+bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const {
+ assert(Line.MightBeFunctionDecl);
+
+ if ((Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_TopLevel ||
+ Style.AlwaysBreakAfterReturnType ==
+ FormatStyle::RTBS_TopLevelDefinitions) &&
+ Line.Level > 0)
+ return false;
+
+ switch (Style.AlwaysBreakAfterReturnType) {
+ case FormatStyle::RTBS_None:
+ return false;
+ case FormatStyle::RTBS_All:
+ case FormatStyle::RTBS_TopLevel:
+ return true;
+ case FormatStyle::RTBS_AllDefinitions:
+ case FormatStyle::RTBS_TopLevelDefinitions:
+ return Line.mightBeFunctionDefinition();
+ }
+
+ return false;
+}
+
void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
E = Line.Children.end();
@@ -1544,15 +1647,9 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
Current->MustBreakBefore =
Current->MustBreakBefore || mustBreakBefore(Line, *Current);
- if ((Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All ||
- (Style.AlwaysBreakAfterDefinitionReturnType ==
- FormatStyle::DRTBS_TopLevel &&
- Line.Level == 0)) &&
- InFunctionDecl && Current->is(TT_FunctionDeclarationName) &&
- !Line.Last->isOneOf(tok::semi, tok::comment)) // Only for definitions.
- // FIXME: Line.Last points to other characters than tok::semi
- // and tok::lbrace.
- Current->MustBreakBefore = true;
+ if (!Current->MustBreakBefore && InFunctionDecl &&
+ Current->is(TT_FunctionDeclarationName))
+ Current->MustBreakBefore = mustBreakForReturnType(Line);
Current->CanBreakBefore =
Current->MustBreakBefore || canBreakBefore(Line, *Current);
@@ -1629,7 +1726,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Right.is(Keywords.kw_function) && Left.isNot(tok::comma))
return 100;
if (Left.is(TT_JsTypeColon))
- return 100;
+ return 35;
}
if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next &&
@@ -1638,9 +1735,11 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Right.is(tok::l_square)) {
if (Style.Language == FormatStyle::LK_Proto)
return 1;
+ if (Left.is(tok::r_square))
+ return 25;
// Slightly prefer formatting local lambda definitions like functions.
if (Right.is(TT_LambdaLSquare) && Left.is(tok::equal))
- return 50;
+ return 35;
if (!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
TT_ArrayInitializerLSquare))
return 500;
@@ -1674,10 +1773,28 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
return 2;
if (Right.isMemberAccess()) {
- if (Left.is(tok::r_paren) && Left.MatchingParen &&
- Left.MatchingParen->ParameterCount > 0)
- return 20; // Should be smaller than breaking at a nested comma.
- return 150;
+ // Breaking before the "./->" of a chained call/member access is reasonably
+ // cheap, as formatting those with one call per line is generally
+ // desirable. In particular, it should be cheaper to break before the call
+ // than it is to break inside a call's parameters, which could lead to weird
+ // "hanging" indents. The exception is the very last "./->" to support this
+ // frequent pattern:
+ //
+ // aaaaaaaa.aaaaaaaa.bbbbbbb().ccccccccccccccccccccc(
+ // dddddddd);
+ //
+ // which might otherwise be blown up onto many lines. Here, clang-format
+ // won't produce "hanging" indents anyway as there is no other trailing
+ // call.
+ //
+ // Also apply higher penalty is not a call as that might lead to a wrapping
+ // like:
+ //
+ // aaaaaaa
+ // .aaaaaaaaa.bbbbbbbb(cccccccc);
+ return !Right.NextOperator || !Right.NextOperator->Previous->closesScope()
+ ? 150
+ : 35;
}
if (Right.is(TT_TrailingAnnotation) &&
@@ -1706,7 +1823,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(tok::colon) && Left.is(TT_ObjCMethodExpr))
return Line.MightBeFunctionDecl ? 50 : 500;
- if (Left.is(tok::l_paren) && InFunctionDecl && Style.AlignAfterOpenBracket)
+ if (Left.is(tok::l_paren) && InFunctionDecl &&
+ Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign)
return 100;
if (Left.is(tok::l_paren) && Left.Previous &&
Left.Previous->isOneOf(tok::kw_if, tok::kw_for))
@@ -1718,7 +1836,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(TT_TemplateOpener))
return 100;
if (Left.opensScope()) {
- if (!Style.AlignAfterOpenBracket)
+ if (Style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign)
return 0;
return Left.ParameterCount > 1 ? Style.PenaltyBreakBeforeFirstCallParameter
: 19;
@@ -1728,7 +1846,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Right.is(tok::lessless)) {
if (Left.is(tok::string_literal) &&
- (!Right.LastOperator || Right.OperatorIndex != 1)) {
+ (Right.NextOperator || Right.OperatorIndex != 1)) {
StringRef Content = Left.TokenText;
if (Content.startswith("\""))
Content = Content.drop_front(1);
@@ -1785,6 +1903,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
tok::numeric_constant, tok::l_paren, tok::l_brace,
tok::kw_true, tok::kw_false))
return false;
+ if (Left.is(tok::colon))
+ return !Left.is(TT_ObjCMethodExpr);
if (Left.is(tok::coloncolon))
return false;
if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less))
@@ -1794,11 +1914,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Left.is(tok::l_square) && Right.is(tok::amp))
return false;
if (Right.is(TT_PointerOrReference))
- return !(Left.is(tok::r_paren) && Left.MatchingParen &&
- (Left.MatchingParen->is(TT_OverloadedOperatorLParen) ||
- (Left.MatchingParen->Previous &&
- Left.MatchingParen->Previous->is(
- TT_FunctionDeclarationName)))) &&
+ return (Left.is(tok::r_paren) && Left.MatchingParen &&
+ (Left.MatchingParen->is(TT_OverloadedOperatorLParen) ||
+ (Left.MatchingParen->Previous &&
+ Left.MatchingParen->Previous->is(TT_FunctionDeclarationName)))) ||
(Left.Tok.isLiteral() ||
(!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
(Style.PointerAlignment != FormatStyle::PAS_Left ||
@@ -1809,7 +1928,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
!Line.IsMultiVariableDeclStmt)))
return true;
if (Left.is(TT_PointerOrReference))
- return Right.Tok.isLiteral() || Right.is(TT_BlockComment) ||
+ return Right.Tok.isLiteral() ||
+ Right.isOneOf(TT_BlockComment, Keywords.kw_final,
+ Keywords.kw_override) ||
(Right.is(tok::l_brace) && Right.BlockKind == BK_Block) ||
(!Right.isOneOf(TT_PointerOrReference, TT_ArraySubscriptLSquare,
tok::l_paren) &&
@@ -1834,8 +1955,6 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
!Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare) &&
!Left.isOneOf(tok::numeric_constant, TT_DictLiteral))
return false;
- if (Left.is(tok::colon))
- return !Left.is(TT_ObjCMethodExpr);
if (Left.is(tok::l_brace) && Right.is(tok::r_brace))
return !Left.Children.empty(); // No spaces in "{}".
if ((Left.is(tok::l_brace) && Left.BlockKind != BK_Block) ||
@@ -1849,8 +1968,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return true;
return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
- (Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while,
- tok::kw_switch, tok::kw_case, TT_ForEachMacro) ||
+ (Left.isOneOf(tok::kw_if, tok::pp_elif, tok::kw_for, tok::kw_while,
+ tok::kw_switch, tok::kw_case, TT_ForEachMacro,
+ TT_ObjCForIn) ||
(Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch,
tok::kw_new, tok::kw_delete) &&
(!Left.Previous || Left.Previous->isNot(tok::period))))) ||
@@ -1895,13 +2015,19 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
} else if (Style.Language == FormatStyle::LK_Proto) {
if (Right.is(tok::period) &&
Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,
- Keywords.kw_repeated))
+ Keywords.kw_repeated, Keywords.kw_extend))
return true;
if (Right.is(tok::l_paren) &&
Left.isOneOf(Keywords.kw_returns, Keywords.kw_option))
return true;
} else if (Style.Language == FormatStyle::LK_JavaScript) {
- if (Left.isOneOf(Keywords.kw_var, TT_JsFatArrow))
+ if (Left.isOneOf(Keywords.kw_let, Keywords.kw_var, TT_JsFatArrow,
+ Keywords.kw_in))
+ return true;
+ if (Left.is(tok::kw_default) && Left.Previous &&
+ Left.Previous->is(tok::kw_export))
+ return true;
+ if (Left.is(Keywords.kw_is) && Right.is(tok::l_brace))
return true;
if (Right.isOneOf(TT_JsTypeColon, TT_JsTypeOptionalQuestion))
return false;
@@ -1945,14 +2071,14 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) ||
Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow))
return true;
+ if (Right.is(TT_OverloadedOperatorLParen))
+ return Style.SpaceBeforeParens == FormatStyle::SBPO_Always;
if (Left.is(tok::comma))
return true;
if (Right.is(tok::comma))
return false;
if (Right.isOneOf(TT_CtorInitializerColon, TT_ObjCBlockLParen))
return true;
- if (Right.is(TT_OverloadedOperatorLParen))
- return false;
if (Right.is(tok::colon)) {
if (Line.First->isOneOf(tok::kw_case, tok::kw_default) ||
!Right.getNextNonComment() || Right.getNextNonComment()->is(tok::semi))
@@ -1993,7 +2119,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
return Style.SpacesInAngles;
if ((Right.is(TT_BinaryOperator) && !Left.is(tok::l_paren)) ||
- Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr))
+ (Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&
+ !Right.is(tok::r_paren)))
return true;
if (Left.is(TT_TemplateCloser) && Right.is(tok::l_paren) &&
Right.isNot(TT_FunctionTypeLParen))
@@ -2020,7 +2147,7 @@ static bool isAllmanBrace(const FormatToken &Tok) {
bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
const FormatToken &Right) {
const FormatToken &Left = *Right.Previous;
- if (Right.NewlinesBefore > 1)
+ if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0)
return true;
if (Style.Language == FormatStyle::LK_JavaScript) {
@@ -2032,8 +2159,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Left.Previous && Left.Previous->is(tok::equal) &&
Line.First->isOneOf(tok::identifier, Keywords.kw_import, tok::kw_export,
tok::kw_const) &&
- // kw_var is a pseudo-token that's a tok::identifier, so matches above.
- !Line.startsWith(Keywords.kw_var))
+ // kw_var/kw_let are pseudo-tokens that are tok::identifier, so match
+ // above.
+ !Line.First->isOneOf(Keywords.kw_var, Keywords.kw_let))
// Object literals on the top level of a file are treated as "enum-style".
// Each key/value pair is put on a separate line, instead of bin-packing.
return true;
@@ -2047,6 +2175,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
!Left.Children.empty())
// Support AllowShortFunctionsOnASingleLine for JavaScript.
return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||
+ Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty ||
(Left.NestingLevel == 0 && Line.Level == 0 &&
Style.AllowShortFunctionsOnASingleLine ==
FormatStyle::SFS_Inline);
@@ -2107,10 +2236,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (Right.is(TT_InlineASMBrace))
return Right.HasUnescapedNewline;
if (isAllmanBrace(Left) || isAllmanBrace(Right))
- return Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU ||
- (Style.BreakBeforeBraces == FormatStyle::BS_Mozilla &&
- Line.startsWith(tok::kw_enum));
+ return (Line.startsWith(tok::kw_enum) && Style.BraceWrapping.AfterEnum) ||
+ (Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) ||
+ (Line.startsWith(tok::kw_struct) && Style.BraceWrapping.AfterStruct);
if (Style.Language == FormatStyle::LK_Proto && Left.isNot(tok::l_brace) &&
Right.is(TT_SelectorName))
return true;
@@ -2121,7 +2249,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Style.Language == FormatStyle::LK_JavaScript) &&
Left.is(TT_LeadingJavaAnnotation) &&
Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&
- Line.Last->is(tok::l_brace))
+ (Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations))
return true;
return false;
@@ -2144,6 +2272,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return false;
if (Left.is(TT_JsTypeColon))
return true;
+ if (Right.NestingLevel == 0 && Right.is(Keywords.kw_is))
+ return false;
}
if (Left.is(tok::at))
@@ -2186,7 +2316,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return Left.isNot(tok::period); // FIXME: Properly parse ObjC calls.
if (Left.is(tok::r_paren) && Line.Type == LT_ObjCProperty)
return true;
- if (Left.ClosesTemplateDeclaration)
+ if (Left.ClosesTemplateDeclaration || Left.is(TT_FunctionAnnotationRParen))
return true;
if (Right.isOneOf(TT_RangeBasedForLoopColon, TT_OverloadedOperatorLParen,
TT_OverloadedOperator))
@@ -2199,7 +2329,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
Left.is(tok::kw_operator))
return false;
if (Left.is(tok::equal) && !Right.isOneOf(tok::kw_default, tok::kw_delete) &&
- Line.Type == LT_VirtualFunctionDecl)
+ Line.Type == LT_VirtualFunctionDecl && Left.NestingLevel == 0)
return false;
if (Left.is(tok::l_paren) && Left.is(TT_AttributeParen))
return false;
diff --git a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
index b8a6be0..5329f1f 100644
--- a/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
+++ b/contrib/llvm/tools/clang/lib/Format/TokenAnnotator.h
@@ -86,6 +86,15 @@ public:
return startsWith(First, Tokens...);
}
+ /// \c true if this line looks like a function definition instead of a
+ /// function declaration. Asserts MightBeFunctionDecl.
+ bool mightBeFunctionDefinition() const {
+ assert(MightBeFunctionDecl);
+ // FIXME: Line.Last points to other characters than tok::semi
+ // and tok::lbrace.
+ return !Last->isOneOf(tok::semi, tok::comment);
+ }
+
FormatToken *First;
FormatToken *Last;
@@ -156,6 +165,8 @@ private:
bool canBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
+ bool mustBreakForReturnType(const AnnotatedLine &Line) const;
+
void printDebugInfo(const AnnotatedLine &Line);
void calculateUnbreakableTailLengths(AnnotatedLine &Line);
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
index b6784b3..f650569 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -90,8 +90,8 @@ private:
return 0;
if (RootToken.isAccessSpecifier(false) ||
RootToken.isObjCAccessSpecifier() ||
- (RootToken.is(Keywords.kw_signals) && RootToken.Next &&
- RootToken.Next->is(tok::colon)))
+ (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
+ RootToken.Next && RootToken.Next->is(tok::colon)))
return Style.AccessModifierOffset;
return 0;
}
@@ -199,12 +199,12 @@ private:
return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
}
if (TheLine->Last->is(tok::l_brace)) {
- return Style.BreakBeforeBraces == FormatStyle::BS_Attach
+ return !Style.BraceWrapping.AfterFunction
? tryMergeSimpleBlock(I, E, Limit)
: 0;
}
if (I[1]->First->is(TT_FunctionLBrace) &&
- Style.BreakBeforeBraces != FormatStyle::BS_Attach) {
+ Style.BraceWrapping.AfterFunction) {
if (I[1]->Last->is(TT_LineComment))
return 0;
@@ -263,8 +263,7 @@ private:
SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
if (Limit == 0)
return 0;
- if ((Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU) &&
+ if (Style.BraceWrapping.AfterControlStatement &&
(I[1]->First->is(tok::l_brace) && !Style.AllowShortBlocksOnASingleLine))
return 0;
if (I[1]->InPPDirective != (*I)->InPPDirective ||
@@ -305,7 +304,8 @@ private:
if (Line->First->isOneOf(tok::kw_case, tok::kw_default, tok::r_brace))
break;
if (Line->First->isOneOf(tok::kw_if, tok::kw_for, tok::kw_switch,
- tok::kw_while, tok::comment))
+ tok::kw_while, tok::comment) ||
+ Line->Last->is(tok::comment))
return 0;
Length += I[1 + NumStmts]->Last->TotalLength + 1; // 1 for the space.
}
@@ -606,7 +606,7 @@ public:
/// \brief Puts all tokens into a single line.
unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
- bool DryRun) {
+ bool DryRun) override {
unsigned Penalty = 0;
LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);
while (State.NextToken) {
@@ -629,7 +629,7 @@ public:
/// \brief Formats the line by finding the best line breaks with line lengths
/// below the column limit.
unsigned formatLine(const AnnotatedLine &Line, unsigned FirstIndent,
- bool DryRun) {
+ bool DryRun) override {
LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);
// If the ObjC method declaration does not fit on a line, we should format
@@ -709,7 +709,7 @@ private:
// Cut off the analysis of certain solutions if the analysis gets too
// complex. See description of IgnoreStackForComparison.
- if (Count > 10000)
+ if (Count > 50000)
Node->State.IgnoreStackForComparison = true;
if (!Seen.insert(&Node->State).second)
@@ -791,7 +791,7 @@ private:
llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
};
-} // namespace
+} // anonymous namespace
unsigned
UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
@@ -812,13 +812,26 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
AdditionalIndent);
const AnnotatedLine *PreviousLine = nullptr;
const AnnotatedLine *NextLine = nullptr;
+
+ // The minimum level of consecutive lines that have been formatted.
+ unsigned RangeMinLevel = UINT_MAX;
+
for (const AnnotatedLine *Line =
Joiner.getNextMergedLine(DryRun, IndentTracker);
Line; Line = NextLine) {
const AnnotatedLine &TheLine = *Line;
unsigned Indent = IndentTracker.getIndent();
- bool FixIndentation =
- FixBadIndentation && (Indent != TheLine.First->OriginalColumn);
+
+ // We continue formatting unchanged lines to adjust their indent, e.g. if a
+ // scope was added. However, we need to carefully stop doing this when we
+ // exit the scope of affected lines to prevent indenting a the entire
+ // remaining file if it currently missing a closing brace.
+ bool ContinueFormatting =
+ TheLine.Level > RangeMinLevel ||
+ (TheLine.Level == RangeMinLevel && !TheLine.startsWith(tok::r_brace));
+
+ bool FixIndentation = (FixBadIndentation || ContinueFormatting) &&
+ Indent != TheLine.First->OriginalColumn;
bool ShouldFormat = TheLine.Affected || FixIndentation;
// We cannot format this line; if the reason is that the line had a
// parsing error, remember that.
@@ -845,6 +858,7 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
else
Penalty += OptimizingLineFormatter(Indenter, Whitespaces, Style, this)
.formatLine(TheLine, Indent, DryRun);
+ RangeMinLevel = std::min(RangeMinLevel, TheLine.Level);
} else {
// If no token in the current line is affected, we still need to format
// affected children.
@@ -875,6 +889,7 @@ UnwrappedLineFormatter::format(const SmallVectorImpl<AnnotatedLine *> &Lines,
Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
}
NextLine = Joiner.getNextMergedLine(DryRun, IndentTracker);
+ RangeMinLevel = UINT_MAX;
}
if (!DryRun)
markFinalized(TheLine.First);
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
index 97fd98e..7b8f6e6 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.cpp
@@ -154,12 +154,10 @@ public:
CompoundStatementIndenter(UnwrappedLineParser *Parser,
const FormatStyle &Style, unsigned &LineLevel)
: LineLevel(LineLevel), OldLineLevel(LineLevel) {
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) {
- Parser->addUnwrappedLine();
- } else if (Style.BreakBeforeBraces == FormatStyle::BS_GNU) {
+ if (Style.BraceWrapping.AfterControlStatement)
Parser->addUnwrappedLine();
+ if (Style.BraceWrapping.IndentBraces)
++LineLevel;
- }
}
~CompoundStatementIndenter() { LineLevel = OldLineLevel; }
@@ -284,6 +282,8 @@ void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
case tok::l_brace:
// FIXME: Add parameter whether this can happen - if this happens, we must
// be in a non-declaration context.
+ if (!FormatTok->is(TT_MacroBlockBegin) && tryToParseBracedList())
+ continue;
parseBlock(/*MustBeDeclaration=*/false);
addUnwrappedLine();
break;
@@ -315,13 +315,14 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
// definitions, too.
unsigned StoredPosition = Tokens->getPosition();
FormatToken *Tok = FormatTok;
+ const FormatToken *PrevTok = getPreviousToken();
// Keep a stack of positions of lbrace tokens. We will
// update information about whether an lbrace starts a
// braced init list or a different block during the loop.
SmallVector<FormatToken *, 8> LBraceStack;
assert(Tok->Tok.is(tok::l_brace));
do {
- // Get next none-comment token.
+ // Get next non-comment token.
FormatToken *NextTok;
unsigned ReadTokens = 0;
do {
@@ -331,47 +332,53 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
switch (Tok->Tok.getKind()) {
case tok::l_brace:
- Tok->BlockKind = BK_Unknown;
+ if (Style.Language == FormatStyle::LK_JavaScript && PrevTok &&
+ PrevTok->is(tok::colon))
+ // In TypeScript's TypeMemberLists, there can be semicolons between the
+ // individual members.
+ Tok->BlockKind = BK_BracedInit;
+ else
+ Tok->BlockKind = BK_Unknown;
LBraceStack.push_back(Tok);
break;
case tok::r_brace:
- if (!LBraceStack.empty()) {
- if (LBraceStack.back()->BlockKind == BK_Unknown) {
- bool ProbablyBracedList = false;
- if (Style.Language == FormatStyle::LK_Proto) {
- ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
- } else {
- // Using OriginalColumn to distinguish between ObjC methods and
- // binary operators is a bit hacky.
- bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
- NextTok->OriginalColumn == 0;
-
- // If there is a comma, semicolon or right paren after the closing
- // brace, we assume this is a braced initializer list. Note that
- // regardless how we mark inner braces here, we will overwrite the
- // BlockKind later if we parse a braced list (where all blocks
- // inside are by default braced lists), or when we explicitly detect
- // blocks (for example while parsing lambdas).
- //
- // We exclude + and - as they can be ObjC visibility modifiers.
- ProbablyBracedList =
- NextTok->isOneOf(tok::comma, tok::period, tok::colon,
- tok::r_paren, tok::r_square, tok::l_brace,
- tok::l_paren, tok::ellipsis) ||
- (NextTok->is(tok::semi) &&
- (!ExpectClassBody || LBraceStack.size() != 1)) ||
- (NextTok->isBinaryOperator() && !NextIsObjCMethod);
- }
- if (ProbablyBracedList) {
- Tok->BlockKind = BK_BracedInit;
- LBraceStack.back()->BlockKind = BK_BracedInit;
- } else {
- Tok->BlockKind = BK_Block;
- LBraceStack.back()->BlockKind = BK_Block;
- }
+ if (LBraceStack.empty())
+ break;
+ if (LBraceStack.back()->BlockKind == BK_Unknown) {
+ bool ProbablyBracedList = false;
+ if (Style.Language == FormatStyle::LK_Proto) {
+ ProbablyBracedList = NextTok->isOneOf(tok::comma, tok::r_square);
+ } else {
+ // Using OriginalColumn to distinguish between ObjC methods and
+ // binary operators is a bit hacky.
+ bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
+ NextTok->OriginalColumn == 0;
+
+ // If there is a comma, semicolon or right paren after the closing
+ // brace, we assume this is a braced initializer list. Note that
+ // regardless how we mark inner braces here, we will overwrite the
+ // BlockKind later if we parse a braced list (where all blocks
+ // inside are by default braced lists), or when we explicitly detect
+ // blocks (for example while parsing lambdas).
+ //
+ // We exclude + and - as they can be ObjC visibility modifiers.
+ ProbablyBracedList =
+ NextTok->isOneOf(tok::comma, tok::period, tok::colon,
+ tok::r_paren, tok::r_square, tok::l_brace,
+ tok::l_square, tok::l_paren, tok::ellipsis) ||
+ (NextTok->is(tok::semi) &&
+ (!ExpectClassBody || LBraceStack.size() != 1)) ||
+ (NextTok->isBinaryOperator() && !NextIsObjCMethod);
+ }
+ if (ProbablyBracedList) {
+ Tok->BlockKind = BK_BracedInit;
+ LBraceStack.back()->BlockKind = BK_BracedInit;
+ } else {
+ Tok->BlockKind = BK_Block;
+ LBraceStack.back()->BlockKind = BK_Block;
}
- LBraceStack.pop_back();
}
+ LBraceStack.pop_back();
break;
case tok::at:
case tok::semi:
@@ -381,14 +388,16 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
case tok::kw_switch:
case tok::kw_try:
case tok::kw___try:
- if (!LBraceStack.empty())
+ if (!LBraceStack.empty() && LBraceStack.back()->BlockKind == BK_Unknown)
LBraceStack.back()->BlockKind = BK_Block;
break;
default:
break;
}
+ PrevTok = Tok;
Tok = NextTok;
} while (Tok->Tok.isNot(tok::eof) && !LBraceStack.empty());
+
// Assume other blocks for all unclosed opening braces.
for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) {
if (LBraceStack[i]->BlockKind == BK_Unknown)
@@ -403,6 +412,7 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) &&
"'{' or macro block token expected");
const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
+ FormatTok->BlockKind = BK_Block;
unsigned InitialLevel = Line->Level;
nextToken();
@@ -421,6 +431,7 @@ void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, bool AddLevel,
if (MacroBlock ? !FormatTok->is(TT_MacroBlockEnd)
: !FormatTok->is(tok::r_brace)) {
Line->Level = InitialLevel;
+ FormatTok->BlockKind = BK_Block;
return;
}
@@ -454,17 +465,15 @@ static bool isGoogScope(const UnwrappedLine &Line) {
static bool ShouldBreakBeforeBrace(const FormatStyle &Style,
const FormatToken &InitialToken) {
- switch (Style.BreakBeforeBraces) {
- case FormatStyle::BS_Linux:
- return InitialToken.isOneOf(tok::kw_namespace, tok::kw_class);
- case FormatStyle::BS_Mozilla:
- return InitialToken.isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union);
- case FormatStyle::BS_Allman:
- case FormatStyle::BS_GNU:
- return true;
- default:
- return false;
- }
+ if (InitialToken.is(tok::kw_namespace))
+ return Style.BraceWrapping.AfterNamespace;
+ if (InitialToken.is(tok::kw_class))
+ return Style.BraceWrapping.AfterClass;
+ if (InitialToken.is(tok::kw_union))
+ return Style.BraceWrapping.AfterUnion;
+ if (InitialToken.is(tok::kw_struct))
+ return Style.BraceWrapping.AfterStruct;
+ return false;
}
void UnwrappedLineParser::parseChildBlock() {
@@ -650,7 +659,15 @@ static bool tokenCanStartNewLine(const clang::Token &Tok) {
}
void UnwrappedLineParser::parseStructuralElement() {
- assert(!FormatTok->Tok.is(tok::l_brace));
+ assert(!FormatTok->is(tok::l_brace));
+ if (Style.Language == FormatStyle::LK_TableGen &&
+ FormatTok->is(tok::pp_include)) {
+ nextToken();
+ if (FormatTok->is(tok::string_literal))
+ nextToken();
+ addUnwrappedLine();
+ return;
+ }
switch (FormatTok->Tok.getKind()) {
case tok::at:
nextToken();
@@ -679,8 +696,7 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::objc_autoreleasepool:
nextToken();
if (FormatTok->Tok.is(tok::l_brace)) {
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU)
+ if (Style.BraceWrapping.AfterObjCDeclaration)
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/false);
}
@@ -787,7 +803,8 @@ void UnwrappedLineParser::parseStructuralElement() {
parseJavaScriptEs6ImportExport();
return;
}
- if (FormatTok->is(Keywords.kw_signals)) {
+ if (FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
+ Keywords.kw_slots, Keywords.kw_qslots)) {
nextToken();
if (FormatTok->is(tok::colon)) {
nextToken();
@@ -810,10 +827,10 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::kw_enum:
// parseEnum falls through and does not yet add an unwrapped line as an
// enum definition can start a structural element.
- parseEnum();
- // This does not apply for Java and JavaScript.
- if (Style.Language == FormatStyle::LK_Java ||
- Style.Language == FormatStyle::LK_JavaScript) {
+ if (!parseEnum())
+ break;
+ // This only applies for C++.
+ if (Style.Language != FormatStyle::LK_Cpp) {
addUnwrappedLine();
return;
}
@@ -833,6 +850,8 @@ void UnwrappedLineParser::parseStructuralElement() {
// This does not apply for Java and JavaScript.
if (Style.Language == FormatStyle::LK_Java ||
Style.Language == FormatStyle::LK_JavaScript) {
+ if (FormatTok->is(tok::semi))
+ nextToken();
addUnwrappedLine();
return;
}
@@ -843,6 +862,11 @@ void UnwrappedLineParser::parseStructuralElement() {
if (Style.Language == FormatStyle::LK_Java && FormatTok &&
FormatTok->is(tok::kw_class))
nextToken();
+ if (Style.Language == FormatStyle::LK_JavaScript && FormatTok &&
+ FormatTok->Tok.getIdentifierInfo())
+ // JavaScript only has pseudo keywords, all keywords are allowed to
+ // appear in "IdentifierName" positions. See http://es5.github.io/#x7.6
+ nextToken();
break;
case tok::semi:
nextToken();
@@ -854,6 +878,11 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::l_paren:
parseParens();
break;
+ case tok::kw_operator:
+ nextToken();
+ if (FormatTok->isBinaryOperator())
+ nextToken();
+ break;
case tok::caret:
nextToken();
if (FormatTok->Tok.isAnyIdentifier() ||
@@ -870,7 +899,7 @@ void UnwrappedLineParser::parseStructuralElement() {
// structural element.
// FIXME: Figure out cases where this is not true, and add projections
// for them (the one we know is missing are lambdas).
- if (Style.BreakBeforeBraces != FormatStyle::BS_Attach)
+ if (Style.BraceWrapping.AfterFunction)
addUnwrappedLine();
FormatTok->Type = TT_FunctionLBrace;
parseBlock(/*MustBeDeclaration=*/false);
@@ -968,13 +997,11 @@ bool UnwrappedLineParser::tryToParseLambda() {
nextToken();
return false;
}
- // FIXME: This is a dirty way to access the previous token. Find a better
- // solution.
- if (!Line->Tokens.empty() &&
- (Line->Tokens.back().Tok->isOneOf(tok::identifier, tok::kw_operator,
- tok::kw_new, tok::kw_delete) ||
- Line->Tokens.back().Tok->closesScope() ||
- Line->Tokens.back().Tok->isSimpleTypeSpecifier())) {
+ const FormatToken* Previous = getPreviousToken();
+ if (Previous &&
+ (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
+ tok::kw_delete) ||
+ Previous->closesScope() || Previous->isSimpleTypeSpecifier())) {
nextToken();
return false;
}
@@ -1001,6 +1028,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
case tok::less:
case tok::greater:
case tok::identifier:
+ case tok::numeric_constant:
case tok::coloncolon:
case tok::kw_mutable:
nextToken();
@@ -1155,6 +1183,14 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
nextToken();
return !HasError;
case tok::semi:
+ // JavaScript (or more precisely TypeScript) can have semicolons in braced
+ // lists (in so-called TypeMemberLists). Thus, the semicolon cannot be
+ // used for error recovery if we have otherwise determined that this is
+ // a braced list.
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ nextToken();
+ break;
+ }
HasError = true;
if (!ContinueOnSemicolons)
return !HasError;
@@ -1257,12 +1293,10 @@ void UnwrappedLineParser::parseIfThenElse() {
if (FormatTok->Tok.is(tok::l_brace)) {
CompoundStatementIndenter Indenter(this, Style, Line->Level);
parseBlock(/*MustBeDeclaration=*/false);
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU) {
+ if (Style.BraceWrapping.BeforeElse)
addUnwrappedLine();
- } else {
+ else
NeedsUnwrappedLine = true;
- }
} else {
addUnwrappedLine();
++Line->Level;
@@ -1270,8 +1304,6 @@ void UnwrappedLineParser::parseIfThenElse() {
--Line->Level;
}
if (FormatTok->Tok.is(tok::kw_else)) {
- if (Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup)
- addUnwrappedLine();
nextToken();
if (FormatTok->Tok.is(tok::l_brace)) {
CompoundStatementIndenter Indenter(this, Style, Line->Level);
@@ -1312,9 +1344,7 @@ void UnwrappedLineParser::parseTryCatch() {
if (FormatTok->is(tok::l_brace)) {
CompoundStatementIndenter Indenter(this, Style, Line->Level);
parseBlock(/*MustBeDeclaration=*/false);
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU ||
- Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) {
+ if (Style.BraceWrapping.BeforeCatch) {
addUnwrappedLine();
} else {
NeedsUnwrappedLine = true;
@@ -1352,17 +1382,13 @@ void UnwrappedLineParser::parseTryCatch() {
NeedsUnwrappedLine = false;
CompoundStatementIndenter Indenter(this, Style, Line->Level);
parseBlock(/*MustBeDeclaration=*/false);
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU ||
- Style.BreakBeforeBraces == FormatStyle::BS_Stroustrup) {
+ if (Style.BraceWrapping.BeforeCatch)
addUnwrappedLine();
- } else {
+ else
NeedsUnwrappedLine = true;
- }
}
- if (NeedsUnwrappedLine) {
+ if (NeedsUnwrappedLine)
addUnwrappedLine();
- }
}
void UnwrappedLineParser::parseNamespace() {
@@ -1370,7 +1396,7 @@ void UnwrappedLineParser::parseNamespace() {
const FormatToken &InitialToken = *FormatTok;
nextToken();
- if (FormatTok->Tok.is(tok::identifier))
+ while (FormatTok->isOneOf(tok::identifier, tok::coloncolon))
nextToken();
if (FormatTok->Tok.is(tok::l_brace)) {
if (ShouldBreakBeforeBrace(Style, InitialToken))
@@ -1438,7 +1464,7 @@ void UnwrappedLineParser::parseDoWhile() {
if (FormatTok->Tok.is(tok::l_brace)) {
CompoundStatementIndenter Indenter(this, Style, Line->Level);
parseBlock(/*MustBeDeclaration=*/false);
- if (Style.BreakBeforeBraces == FormatStyle::BS_GNU)
+ if (Style.BraceWrapping.IndentBraces)
addUnwrappedLine();
} else {
addUnwrappedLine();
@@ -1466,11 +1492,8 @@ void UnwrappedLineParser::parseLabel() {
CompoundStatementIndenter Indenter(this, Style, Line->Level);
parseBlock(/*MustBeDeclaration=*/false);
if (FormatTok->Tok.is(tok::kw_break)) {
- // "break;" after "}" on its own line only for BS_Allman and BS_GNU
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU) {
+ if (Style.BraceWrapping.AfterControlStatement)
addUnwrappedLine();
- }
parseStructuralElement();
}
addUnwrappedLine();
@@ -1519,11 +1542,17 @@ void UnwrappedLineParser::parseAccessSpecifier() {
addUnwrappedLine();
}
-void UnwrappedLineParser::parseEnum() {
+bool UnwrappedLineParser::parseEnum() {
// Won't be 'enum' for NS_ENUMs.
if (FormatTok->Tok.is(tok::kw_enum))
nextToken();
+ // In TypeScript, "enum" can also be used as property name, e.g. in interface
+ // declarations. An "enum" keyword followed by a colon would be a syntax
+ // error and thus assume it is just an identifier.
+ if (Style.Language == FormatStyle::LK_JavaScript && FormatTok->is(tok::colon))
+ return false;
+
// Eat up enum class ...
if (FormatTok->Tok.is(tok::kw_class) || FormatTok->Tok.is(tok::kw_struct))
nextToken();
@@ -1541,19 +1570,23 @@ void UnwrappedLineParser::parseEnum() {
// return type. In Java, this can be "implements", etc.
if (Style.Language == FormatStyle::LK_Cpp &&
FormatTok->is(tok::identifier))
- return;
+ return false;
}
}
// Just a declaration or something is wrong.
if (FormatTok->isNot(tok::l_brace))
- return;
+ return true;
FormatTok->BlockKind = BK_Block;
if (Style.Language == FormatStyle::LK_Java) {
// Java enums are different.
parseJavaEnumBody();
- return;
+ return true;
+ }
+ if (Style.Language == FormatStyle::LK_Proto) {
+ parseBlock(/*MustBeDeclaration=*/true);
+ return true;
}
// Parse enum body.
@@ -1563,6 +1596,7 @@ void UnwrappedLineParser::parseEnum() {
nextToken();
addUnwrappedLine();
}
+ return true;
// There is no addUnwrappedLine() here so that we fall through to parsing a
// structural element afterwards. Thus, in "enum A {} n, m;",
@@ -1731,8 +1765,7 @@ void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
parseObjCProtocolList();
if (FormatTok->Tok.is(tok::l_brace)) {
- if (Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
- Style.BreakBeforeBraces == FormatStyle::BS_GNU)
+ if (Style.BraceWrapping.AfterObjCDeclaration)
addUnwrappedLine();
parseBlock(/*MustBeDeclaration=*/true);
}
@@ -1776,18 +1809,22 @@ void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
return;
}
+ // Consume the "abstract" in "export abstract class".
+ if (FormatTok->is(Keywords.kw_abstract))
+ nextToken();
+
if (FormatTok->isOneOf(tok::kw_const, tok::kw_class, tok::kw_enum,
+ Keywords.kw_interface, Keywords.kw_let,
Keywords.kw_var))
return; // Fall through to parsing the corresponding structure.
- if (FormatTok->is(tok::l_brace)) {
- FormatTok->BlockKind = BK_Block;
- parseBracedList();
- }
-
- while (!eof() && FormatTok->isNot(tok::semi) &&
- FormatTok->isNot(tok::l_brace)) {
- nextToken();
+ while (!eof() && FormatTok->isNot(tok::semi)) {
+ if (FormatTok->is(tok::l_brace)) {
+ FormatTok->BlockKind = BK_Block;
+ parseBracedList();
+ } else {
+ nextToken();
+ }
}
}
@@ -1861,6 +1898,14 @@ void UnwrappedLineParser::nextToken() {
readToken();
}
+const FormatToken *UnwrappedLineParser::getPreviousToken() {
+ // FIXME: This is a dirty way to access the previous token. Find a better
+ // solution.
+ if (!Line || Line->Tokens.empty())
+ return nullptr;
+ return Line->Tokens.back().Tok;
+}
+
void UnwrappedLineParser::readToken() {
bool CommentsInCurrentLine = true;
do {
diff --git a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
index c2fa029..6d40ab4 100644
--- a/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
+++ b/contrib/llvm/tools/clang/lib/Format/UnwrappedLineParser.h
@@ -96,7 +96,7 @@ private:
void parseNamespace();
void parseNew();
void parseAccessSpecifier();
- void parseEnum();
+ bool parseEnum();
void parseJavaEnumBody();
void parseRecord();
void parseObjCProtocolList();
@@ -110,6 +110,7 @@ private:
void addUnwrappedLine();
bool eof() const;
void nextToken();
+ const FormatToken *getPreviousToken();
void readToken();
void flushComments(bool NewlineBeforeNext);
void pushToken(FormatToken *Tok);
diff --git a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
index 6539527..d6e6ed2 100644
--- a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.cpp
@@ -26,18 +26,20 @@ operator()(const Change &C1, const Change &C2) const {
}
WhitespaceManager::Change::Change(
- bool CreateReplacement, const SourceRange &OriginalWhitespaceRange,
+ bool CreateReplacement, SourceRange OriginalWhitespaceRange,
unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
unsigned NewlinesBefore, StringRef PreviousLinePostfix,
- StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective)
+ StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective,
+ bool IsStartOfDeclName, bool IsInsideToken)
: CreateReplacement(CreateReplacement),
OriginalWhitespaceRange(OriginalWhitespaceRange),
StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore),
PreviousLinePostfix(PreviousLinePostfix),
CurrentLinePrefix(CurrentLinePrefix), Kind(Kind),
- ContinuesPPDirective(ContinuesPPDirective), IndentLevel(IndentLevel),
- Spaces(Spaces), IsTrailingComment(false), TokenLength(0),
- PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
+ ContinuesPPDirective(ContinuesPPDirective),
+ IsStartOfDeclName(IsStartOfDeclName), IndentLevel(IndentLevel),
+ Spaces(Spaces), IsInsideToken(IsInsideToken), IsTrailingComment(false),
+ TokenLength(0), PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
StartOfBlockComment(nullptr), IndentationOffset(0) {}
void WhitespaceManager::reset() {
@@ -52,19 +54,24 @@ void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines,
if (Tok.Finalized)
return;
Tok.Decision = (Newlines > 0) ? FD_Break : FD_Continue;
- Changes.push_back(Change(true, Tok.WhitespaceRange, IndentLevel, Spaces,
- StartOfTokenColumn, Newlines, "", "",
- Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst));
+ Changes.push_back(
+ Change(/*CreateReplacement=*/true, Tok.WhitespaceRange, IndentLevel,
+ Spaces, StartOfTokenColumn, Newlines, "", "", Tok.Tok.getKind(),
+ InPPDirective && !Tok.IsFirst,
+ Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName),
+ /*IsInsideToken=*/false));
}
void WhitespaceManager::addUntouchableToken(const FormatToken &Tok,
bool InPPDirective) {
if (Tok.Finalized)
return;
- Changes.push_back(Change(false, Tok.WhitespaceRange, /*IndentLevel=*/0,
- /*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore,
- "", "", Tok.Tok.getKind(),
- InPPDirective && !Tok.IsFirst));
+ Changes.push_back(Change(
+ /*CreateReplacement=*/false, Tok.WhitespaceRange, /*IndentLevel=*/0,
+ /*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore, "", "",
+ Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst,
+ Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName),
+ /*IsInsideToken=*/false));
}
void WhitespaceManager::replaceWhitespaceInToken(
@@ -77,14 +84,10 @@ void WhitespaceManager::replaceWhitespaceInToken(
Changes.push_back(Change(
true, SourceRange(Start, Start.getLocWithOffset(ReplaceChars)),
IndentLevel, Spaces, std::max(0, Spaces), Newlines, PreviousPostfix,
- CurrentPrefix,
- // If we don't add a newline this change doesn't start a comment. Thus,
- // when we align line comments, we don't need to treat this change as one.
- // FIXME: We still need to take this change in account to properly
- // calculate the new length of the comment and to calculate the changes
- // for which to do the alignment when aligning comments.
- Tok.is(TT_LineComment) && Newlines > 0 ? tok::comment : tok::unknown,
- InPPDirective && !Tok.IsFirst));
+ CurrentPrefix, Tok.is(TT_LineComment) ? tok::comment : tok::unknown,
+ InPPDirective && !Tok.IsFirst,
+ Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName),
+ /*IsInsideToken=*/Newlines == 0));
}
const tooling::Replacements &WhitespaceManager::generateReplacements() {
@@ -93,6 +96,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
std::sort(Changes.begin(), Changes.end(), Change::IsBeforeInFile(SourceMgr));
calculateLineBreakInformation();
+ alignConsecutiveDeclarations();
alignConsecutiveAssignments();
alignTrailingComments();
alignEscapedNewlines();
@@ -103,6 +107,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
void WhitespaceManager::calculateLineBreakInformation() {
Changes[0].PreviousEndOfTokenColumn = 0;
+ Change *LastOutsideTokenChange = &Changes[0];
for (unsigned i = 1, e = Changes.size(); i != e; ++i) {
unsigned OriginalWhitespaceStart =
SourceMgr.getFileOffset(Changes[i].OriginalWhitespaceRange.getBegin());
@@ -113,11 +118,20 @@ void WhitespaceManager::calculateLineBreakInformation() {
Changes[i].PreviousLinePostfix.size() +
Changes[i - 1].CurrentLinePrefix.size();
+ // If there are multiple changes in this token, sum up all the changes until
+ // the end of the line.
+ if (Changes[i - 1].IsInsideToken)
+ LastOutsideTokenChange->TokenLength +=
+ Changes[i - 1].TokenLength + Changes[i - 1].Spaces;
+ else
+ LastOutsideTokenChange = &Changes[i - 1];
+
Changes[i].PreviousEndOfTokenColumn =
Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength;
Changes[i - 1].IsTrailingComment =
- (Changes[i].NewlinesBefore > 0 || Changes[i].Kind == tok::eof) &&
+ (Changes[i].NewlinesBefore > 0 || Changes[i].Kind == tok::eof ||
+ (Changes[i].IsInsideToken && Changes[i].Kind == tok::comment)) &&
Changes[i - 1].Kind == tok::comment;
}
// FIXME: The last token is currently not always an eof token; in those
@@ -127,6 +141,10 @@ void WhitespaceManager::calculateLineBreakInformation() {
const WhitespaceManager::Change *LastBlockComment = nullptr;
for (auto &Change : Changes) {
+ // Reset the IsTrailingComment flag for changes inside of trailing comments
+ // so they don't get realigned later.
+ if (Change.IsInsideToken)
+ Change.IsTrailingComment = false;
Change.StartOfBlockComment = nullptr;
Change.IndentationOffset = 0;
if (Change.Kind == tok::comment) {
@@ -142,94 +160,183 @@ void WhitespaceManager::calculateLineBreakInformation() {
}
}
-// Walk through all of the changes and find sequences of "=" to align. To do
-// so, keep track of the lines and whether or not an "=" was found on align. If
-// a "=" is found on a line, extend the current sequence. If the current line
-// cannot be part of a sequence, e.g. because there is an empty line before it
-// or it contains non-assignments, finalize the previous sequence.
-void WhitespaceManager::alignConsecutiveAssignments() {
- if (!Style.AlignConsecutiveAssignments)
- return;
+// Align a single sequence of tokens, see AlignTokens below.
+template <typename F>
+static void
+AlignTokenSequence(unsigned Start, unsigned End, unsigned Column, F &&Matches,
+ SmallVector<WhitespaceManager::Change, 16> &Changes) {
+ bool FoundMatchOnLine = false;
+ int Shift = 0;
+ for (unsigned i = Start; i != End; ++i) {
+ if (Changes[i].NewlinesBefore > 0) {
+ FoundMatchOnLine = false;
+ Shift = 0;
+ }
+
+ // If this is the first matching token to be aligned, remember by how many
+ // spaces it has to be shifted, so the rest of the changes on the line are
+ // shifted by the same amount
+ if (!FoundMatchOnLine && Matches(Changes[i])) {
+ FoundMatchOnLine = true;
+ Shift = Column - Changes[i].StartOfTokenColumn;
+ Changes[i].Spaces += Shift;
+ }
+
+ assert(Shift >= 0);
+ Changes[i].StartOfTokenColumn += Shift;
+ if (i + 1 != Changes.size())
+ Changes[i + 1].PreviousEndOfTokenColumn += Shift;
+ }
+}
+// Walk through all of the changes and find sequences of matching tokens to
+// align. To do so, keep track of the lines and whether or not a matching token
+// was found on a line. If a matching token is found, extend the current
+// sequence. If the current line cannot be part of a sequence, e.g. because
+// there is an empty line before it or it contains only non-matching tokens,
+// finalize the previous sequence.
+template <typename F>
+static void AlignTokens(const FormatStyle &Style, F &&Matches,
+ SmallVector<WhitespaceManager::Change, 16> &Changes) {
unsigned MinColumn = 0;
+ unsigned MaxColumn = UINT_MAX;
+
+ // Line number of the start and the end of the current token sequence.
unsigned StartOfSequence = 0;
unsigned EndOfSequence = 0;
- bool FoundAssignmentOnLine = false;
- bool FoundLeftParenOnLine = false;
- unsigned CurrentLine = 0;
- auto AlignSequence = [&] {
- alignConsecutiveAssignments(StartOfSequence, EndOfSequence, MinColumn);
+ // Keep track of the nesting level of matching tokens, i.e. the number of
+ // surrounding (), [], or {}. We will only align a sequence of matching
+ // token that share the same scope depth.
+ //
+ // FIXME: This could use FormatToken::NestingLevel information, but there is
+ // an outstanding issue wrt the brace scopes.
+ unsigned NestingLevelOfLastMatch = 0;
+ unsigned NestingLevel = 0;
+
+ // Keep track of the number of commas before the matching tokens, we will only
+ // align a sequence of matching tokens if they are preceded by the same number
+ // of commas.
+ unsigned CommasBeforeLastMatch = 0;
+ unsigned CommasBeforeMatch = 0;
+
+ // Whether a matching token has been found on the current line.
+ bool FoundMatchOnLine = false;
+
+ // Aligns a sequence of matching tokens, on the MinColumn column.
+ //
+ // Sequences start from the first matching token to align, and end at the
+ // first token of the first line that doesn't need to be aligned.
+ //
+ // We need to adjust the StartOfTokenColumn of each Change that is on a line
+ // containing any matching token to be aligned and located after such token.
+ auto AlignCurrentSequence = [&] {
+ if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
+ AlignTokenSequence(StartOfSequence, EndOfSequence, MinColumn, Matches,
+ Changes);
MinColumn = 0;
+ MaxColumn = UINT_MAX;
StartOfSequence = 0;
EndOfSequence = 0;
};
for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
if (Changes[i].NewlinesBefore != 0) {
- CurrentLine += Changes[i].NewlinesBefore;
- if (StartOfSequence > 0 &&
- (Changes[i].NewlinesBefore > 1 || !FoundAssignmentOnLine)) {
- EndOfSequence = i;
- AlignSequence();
- }
- FoundAssignmentOnLine = false;
- FoundLeftParenOnLine = false;
+ CommasBeforeMatch = 0;
+ EndOfSequence = i;
+ // If there is a blank line, or if the last line didn't contain any
+ // matching token, the sequence ends here.
+ if (Changes[i].NewlinesBefore > 1 || !FoundMatchOnLine)
+ AlignCurrentSequence();
+
+ FoundMatchOnLine = false;
}
- if ((Changes[i].Kind == tok::equal &&
- (FoundAssignmentOnLine || ((Changes[i].NewlinesBefore > 0 ||
- Changes[i + 1].NewlinesBefore > 0)))) ||
- (!FoundLeftParenOnLine && Changes[i].Kind == tok::r_paren)) {
- if (StartOfSequence > 0)
- AlignSequence();
- } else if (Changes[i].Kind == tok::l_paren) {
- FoundLeftParenOnLine = true;
- if (!FoundAssignmentOnLine && StartOfSequence > 0)
- AlignSequence();
- } else if (!FoundAssignmentOnLine && !FoundLeftParenOnLine &&
- Changes[i].Kind == tok::equal) {
- FoundAssignmentOnLine = true;
- EndOfSequence = i;
- if (StartOfSequence == 0)
- StartOfSequence = i;
+ if (Changes[i].Kind == tok::comma) {
+ ++CommasBeforeMatch;
+ } else if (Changes[i].Kind == tok::r_brace ||
+ Changes[i].Kind == tok::r_paren ||
+ Changes[i].Kind == tok::r_square) {
+ --NestingLevel;
+ } else if (Changes[i].Kind == tok::l_brace ||
+ Changes[i].Kind == tok::l_paren ||
+ Changes[i].Kind == tok::l_square) {
+ // We want sequences to skip over child scopes if possible, but not the
+ // other way around.
+ NestingLevelOfLastMatch = std::min(NestingLevelOfLastMatch, NestingLevel);
+ ++NestingLevel;
+ }
- unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
- MinColumn = std::max(MinColumn, ChangeMinColumn);
+ if (!Matches(Changes[i]))
+ continue;
+
+ // If there is more than one matching token per line, or if the number of
+ // preceding commas, or the scope depth, do not match anymore, end the
+ // sequence.
+ if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch ||
+ NestingLevel != NestingLevelOfLastMatch)
+ AlignCurrentSequence();
+
+ CommasBeforeLastMatch = CommasBeforeMatch;
+ NestingLevelOfLastMatch = NestingLevel;
+ FoundMatchOnLine = true;
+
+ if (StartOfSequence == 0)
+ StartOfSequence = i;
+
+ unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
+ int LineLengthAfter = -Changes[i].Spaces;
+ for (unsigned j = i; j != e && Changes[j].NewlinesBefore == 0; ++j)
+ LineLengthAfter += Changes[j].Spaces + Changes[j].TokenLength;
+ unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
+
+ // If we are restricted by the maximum column width, end the sequence.
+ if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
+ CommasBeforeLastMatch != CommasBeforeMatch) {
+ AlignCurrentSequence();
+ StartOfSequence = i;
}
- }
- if (StartOfSequence > 0) {
- EndOfSequence = Changes.size();
- AlignSequence();
+ MinColumn = std::max(MinColumn, ChangeMinColumn);
+ MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
}
+
+ EndOfSequence = Changes.size();
+ AlignCurrentSequence();
}
-void WhitespaceManager::alignConsecutiveAssignments(unsigned Start,
- unsigned End,
- unsigned Column) {
- bool AlignedAssignment = false;
- int PreviousShift = 0;
- for (unsigned i = Start; i != End; ++i) {
- int Shift = 0;
- if (Changes[i].NewlinesBefore > 0)
- AlignedAssignment = false;
- if (!AlignedAssignment && Changes[i].Kind == tok::equal) {
- Shift = Column - Changes[i].StartOfTokenColumn;
- AlignedAssignment = true;
- PreviousShift = Shift;
- }
- assert(Shift >= 0);
- Changes[i].Spaces += Shift;
- if (i + 1 != Changes.size())
- Changes[i + 1].PreviousEndOfTokenColumn += Shift;
- Changes[i].StartOfTokenColumn += Shift;
- if (AlignedAssignment) {
- Changes[i].StartOfTokenColumn += PreviousShift;
- if (i + 1 != Changes.size())
- Changes[i + 1].PreviousEndOfTokenColumn += PreviousShift;
- }
- }
+void WhitespaceManager::alignConsecutiveAssignments() {
+ if (!Style.AlignConsecutiveAssignments)
+ return;
+
+ AlignTokens(Style,
+ [&](const Change &C) {
+ // Do not align on equal signs that are first on a line.
+ if (C.NewlinesBefore > 0)
+ return false;
+
+ // Do not align on equal signs that are last on a line.
+ if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
+ return false;
+
+ return C.Kind == tok::equal;
+ },
+ Changes);
+}
+
+void WhitespaceManager::alignConsecutiveDeclarations() {
+ if (!Style.AlignConsecutiveDeclarations)
+ return;
+
+ // FIXME: Currently we don't handle properly the PointerAlignment: Right
+ // The * and & are not aligned and are left dangling. Something has to be done
+ // about it, but it raises the question of alignment of code like:
+ // const char* const* v1;
+ // float const* v2;
+ // SomeVeryLongType const& v3;
+
+ AlignTokens(Style, [](Change const &C) { return C.IsStartOfDeclName; },
+ Changes);
}
void WhitespaceManager::alignTrailingComments() {
@@ -247,6 +354,12 @@ void WhitespaceManager::alignTrailingComments() {
unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
unsigned ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength;
+
+ // If we don't create a replacement for this change, we have to consider
+ // it to be immovable.
+ if (!Changes[i].CreateReplacement)
+ ChangeMaxColumn = ChangeMinColumn;
+
if (i + 1 != e && Changes[i + 1].ContinuesPPDirective)
ChangeMaxColumn -= 2;
// If this comment follows an } in column 0, it probably documents the
@@ -377,7 +490,7 @@ void WhitespaceManager::generateChanges() {
}
}
-void WhitespaceManager::storeReplacement(const SourceRange &Range,
+void WhitespaceManager::storeReplacement(SourceRange Range,
StringRef Text) {
unsigned WhitespaceLength = SourceMgr.getFileOffset(Range.getEnd()) -
SourceMgr.getFileOffset(Range.getBegin());
diff --git a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
index d973838..9ca9db6 100644
--- a/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
+++ b/contrib/llvm/tools/clang/lib/Format/WhitespaceManager.h
@@ -81,7 +81,6 @@ public:
/// \brief Returns all the \c Replacements created during formatting.
const tooling::Replacements &generateReplacements();
-private:
/// \brief Represents a change before a token, a break inside a token,
/// or the layout of an unchanged token (or whitespace within).
struct Change {
@@ -106,11 +105,12 @@ private:
///
/// \p StartOfTokenColumn and \p InPPDirective will be used to lay out
/// trailing comments and escaped newlines.
- Change(bool CreateReplacement, const SourceRange &OriginalWhitespaceRange,
+ Change(bool CreateReplacement, SourceRange OriginalWhitespaceRange,
unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
unsigned NewlinesBefore, StringRef PreviousLinePostfix,
StringRef CurrentLinePrefix, tok::TokenKind Kind,
- bool ContinuesPPDirective);
+ bool ContinuesPPDirective, bool IsStartOfDeclName,
+ bool IsInsideToken);
bool CreateReplacement;
// Changes might be in the middle of a token, so we cannot just keep the
@@ -126,6 +126,7 @@ private:
// the \c BreakableToken is still doing its own alignment.
tok::TokenKind Kind;
bool ContinuesPPDirective;
+ bool IsStartOfDeclName;
// The number of nested blocks the token is in. This is used to add tabs
// only for the indentation, and not for alignment, when
@@ -139,6 +140,10 @@ private:
// comments. Uncompensated negative offset is truncated to 0.
int Spaces;
+ // If this change is inside of a token but not at the start of the token or
+ // directly after a newline.
+ bool IsInsideToken;
+
// \c IsTrailingComment, \c TokenLength, \c PreviousEndOfTokenColumn and
// \c EscapedNewlineColumn will be calculated in
// \c calculateLineBreakInformation.
@@ -159,6 +164,7 @@ private:
int IndentationOffset;
};
+private:
/// \brief Calculate \c IsTrailingComment, \c TokenLength for the last tokens
/// or token parts in a line and \c PreviousEndOfTokenColumn and
/// \c EscapedNewlineColumn for the first tokens or token parts in a line.
@@ -167,11 +173,8 @@ private:
/// \brief Align consecutive assignments over all \c Changes.
void alignConsecutiveAssignments();
- /// \brief Align consecutive assignments from change \p Start to change \p End
- /// at
- /// the specified \p Column.
- void alignConsecutiveAssignments(unsigned Start, unsigned End,
- unsigned Column);
+ /// \brief Align consecutive declarations over all \c Changes.
+ void alignConsecutiveDeclarations();
/// \brief Align trailing comments over all \c Changes.
void alignTrailingComments();
@@ -191,7 +194,7 @@ private:
void generateChanges();
/// \brief Stores \p Text as the replacement for the whitespace in \p Range.
- void storeReplacement(const SourceRange &Range, StringRef Text);
+ void storeReplacement(SourceRange Range, StringRef Text);
void appendNewlineText(std::string &Text, unsigned Newlines);
void appendNewlineText(std::string &Text, unsigned Newlines,
unsigned PreviousEndOfTokenColumn,
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp
index 762c7a5..b499fa2 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTMerge.cpp
@@ -59,7 +59,6 @@ void ASTMergeAction::ExecuteAction() {
/*MinimalImport=*/false);
TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
- CI.getASTConsumer().Initialize(CI.getASTContext());
for (auto *D : TU->decls()) {
// Don't re-import __va_list_tag, __builtin_va_list.
if (const auto *ND = dyn_cast<NamedDecl>(D))
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
index 1bb5c3f..e6ba292 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
@@ -1,4 +1,4 @@
-//===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
+//===--- ASTUnit.cpp - ASTUnit utility --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -47,6 +47,7 @@
#include <atomic>
#include <cstdio>
#include <cstdlib>
+
using namespace clang;
using llvm::TimeRecord;
@@ -185,7 +186,7 @@ struct ASTUnit::ASTWriterData {
llvm::BitstreamWriter Stream;
ASTWriter Writer;
- ASTWriterData() : Stream(Buffer), Writer(Stream) { }
+ ASTWriterData() : Stream(Buffer), Writer(Stream, { }) { }
};
void ASTUnit::clearFileLevelDecls() {
@@ -649,12 +650,12 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
}
std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
- const std::string &Filename,
- const PCHContainerReader &PCHContainerRdr,
+ const std::string &Filename, const PCHContainerReader &PCHContainerRdr,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls,
- ArrayRef<RemappedFile> RemappedFiles, bool CaptureDiagnostics,
- bool AllowPCHWithCompilerErrors, bool UserFilesAreVolatile) {
+ const FileSystemOptions &FileSystemOpts, bool UseDebugInfo,
+ bool OnlyLocalDecls, ArrayRef<RemappedFile> RemappedFiles,
+ bool CaptureDiagnostics, bool AllowPCHWithCompilerErrors,
+ bool UserFilesAreVolatile) {
std::unique_ptr<ASTUnit> AST(new ASTUnit(true));
// Recover resources if we crash before exiting this method.
@@ -708,7 +709,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
bool disableValid = false;
if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
disableValid = true;
- AST->Reader = new ASTReader(PP, Context, PCHContainerRdr,
+ AST->Reader = new ASTReader(PP, Context, PCHContainerRdr, { },
/*isysroot=*/"",
/*DisableValidation=*/disableValid,
AllowPCHWithCompilerErrors);
@@ -926,6 +927,7 @@ public:
const Preprocessor &PP, StringRef isysroot,
raw_ostream *Out)
: PCHGenerator(PP, "", nullptr, isysroot, std::make_shared<PCHBuffer>(),
+ ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>>(),
/*AllowASTWithErrors=*/true),
Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action),
Out(Out) {
@@ -973,7 +975,7 @@ public:
}
};
-}
+} // anonymous namespace
std::unique_ptr<ASTConsumer>
PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI,
@@ -1076,11 +1078,10 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// Configure the various subsystems.
LangOpts = Clang->getInvocation().LangOpts;
FileSystemOpts = Clang->getFileSystemOpts();
- IntrusiveRefCntPtr<vfs::FileSystem> VFS =
- createVFSFromCompilerInvocation(Clang->getInvocation(), getDiagnostics());
- if (!VFS)
- return true;
- FileMgr = new FileManager(FileSystemOpts, VFS);
+ if (!FileMgr) {
+ Clang->createFileManager();
+ FileMgr = &Clang->getFileManager();
+ }
SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
UserFilesAreVolatile);
TheSema.reset();
@@ -1724,9 +1725,10 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, ASTFrontendAction *Action,
ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath,
- bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble,
- bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
- bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) {
+ bool OnlyLocalDecls, bool CaptureDiagnostics,
+ unsigned PrecompilePreambleAfterNParses, bool CacheCodeCompletionResults,
+ bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile,
+ std::unique_ptr<ASTUnit> *ErrAST) {
assert(CI && "A CompilerInvocation is required");
std::unique_ptr<ASTUnit> OwnAST;
@@ -1745,8 +1747,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
}
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics;
- if (PrecompilePreamble)
- AST->PreambleRebuildCounter = 2;
+ if (PrecompilePreambleAfterNParses > 0)
+ AST->PreambleRebuildCounter = PrecompilePreambleAfterNParses;
AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete;
AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
AST->IncludeBriefCommentsInCodeCompletion
@@ -1863,7 +1865,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
bool ASTUnit::LoadFromCompilerInvocation(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- bool PrecompilePreamble) {
+ unsigned PrecompilePreambleAfterNParses) {
if (!Invocation)
return true;
@@ -1873,8 +1875,8 @@ bool ASTUnit::LoadFromCompilerInvocation(
ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
- if (PrecompilePreamble) {
- PreambleRebuildCounter = 2;
+ if (PrecompilePreambleAfterNParses > 0) {
+ PreambleRebuildCounter = PrecompilePreambleAfterNParses;
OverrideMainBuffer =
getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation);
}
@@ -1892,10 +1894,11 @@ bool ASTUnit::LoadFromCompilerInvocation(
std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
CompilerInvocation *CI,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool OnlyLocalDecls,
- bool CaptureDiagnostics, bool PrecompilePreamble,
- TranslationUnitKind TUKind, bool CacheCodeCompletionResults,
- bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile) {
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr,
+ bool OnlyLocalDecls, bool CaptureDiagnostics,
+ unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
+ bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
+ bool UserFilesAreVolatile) {
// Create the AST unit.
std::unique_ptr<ASTUnit> AST(new ASTUnit(false));
ConfigureDiags(Diags, *AST, CaptureDiagnostics);
@@ -1907,12 +1910,8 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
AST->IncludeBriefCommentsInCodeCompletion
= IncludeBriefCommentsInCodeCompletion;
AST->Invocation = CI;
- AST->FileSystemOpts = CI->getFileSystemOpts();
- IntrusiveRefCntPtr<vfs::FileSystem> VFS =
- createVFSFromCompilerInvocation(*CI, *Diags);
- if (!VFS)
- return nullptr;
- AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
+ AST->FileSystemOpts = FileMgr->getFileSystemOpts();
+ AST->FileMgr = FileMgr;
AST->UserFilesAreVolatile = UserFilesAreVolatile;
// Recover resources if we crash before exiting this method.
@@ -1922,7 +1921,8 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
DiagCleanup(Diags.get());
- if (AST->LoadFromCompilerInvocation(PCHContainerOps, PrecompilePreamble))
+ if (AST->LoadFromCompilerInvocation(PCHContainerOps,
+ PrecompilePreambleAfterNParses))
return nullptr;
return AST;
}
@@ -1933,11 +1933,11 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
bool OnlyLocalDecls, bool CaptureDiagnostics,
ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,
- bool PrecompilePreamble, TranslationUnitKind TUKind,
+ unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies,
bool UserFilesAreVolatile, bool ForSerialization,
- std::unique_ptr<ASTUnit> *ErrAST) {
+ llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST) {
assert(Diags.get() && "no DiagnosticsEngine was provided");
SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
@@ -1970,6 +1970,9 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
CI->getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies;
+ if (ModuleFormat)
+ CI->getHeaderSearchOpts().ModuleFormat = ModuleFormat.getValue();
+
// Create the AST unit.
std::unique_ptr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
@@ -2001,7 +2004,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
ASTUnitCleanup(AST.get());
- if (AST->LoadFromCompilerInvocation(PCHContainerOps, PrecompilePreamble)) {
+ if (AST->LoadFromCompilerInvocation(PCHContainerOps,
+ PrecompilePreambleAfterNParses)) {
// Some error occurred, if caller wants to examine diagnostics, pass it the
// ASTUnit.
if (ErrAST) {
@@ -2043,6 +2047,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation);
// Clear out the diagnostics state.
+ FileMgr.reset();
getDiagnostics().Reset();
ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
if (OverrideMainBuffer)
@@ -2124,7 +2129,7 @@ namespace {
return Next.getCodeCompletionTUInfo();
}
};
-}
+} // anonymous namespace
/// \brief Helper function that computes which global names are hidden by the
/// local code-completion results.
@@ -2210,7 +2215,6 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
}
}
-
void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
CodeCompletionContext Context,
CodeCompletionResult *Results,
@@ -2504,7 +2508,7 @@ bool ASTUnit::serialize(raw_ostream &OS) {
SmallString<128> Buffer;
llvm::BitstreamWriter Stream(Buffer);
- ASTWriter Writer(Stream);
+ ASTWriter Writer(Stream, { });
return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS);
}
@@ -2782,39 +2786,29 @@ bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) {
return true;
}
-namespace {
-struct PCHLocatorInfo {
- serialization::ModuleFile *Mod;
- PCHLocatorInfo() : Mod(nullptr) {}
-};
-}
-
-static bool PCHLocator(serialization::ModuleFile &M, void *UserData) {
- PCHLocatorInfo &Info = *static_cast<PCHLocatorInfo*>(UserData);
- switch (M.Kind) {
- case serialization::MK_ImplicitModule:
- case serialization::MK_ExplicitModule:
- return true; // skip dependencies.
- case serialization::MK_PCH:
- Info.Mod = &M;
- return true; // found it.
- case serialization::MK_Preamble:
- return false; // look in dependencies.
- case serialization::MK_MainFile:
- return false; // look in dependencies.
- }
-
- return true;
-}
-
const FileEntry *ASTUnit::getPCHFile() {
if (!Reader)
return nullptr;
- PCHLocatorInfo Info;
- Reader->getModuleManager().visit(PCHLocator, &Info);
- if (Info.Mod)
- return Info.Mod->File;
+ serialization::ModuleFile *Mod = nullptr;
+ Reader->getModuleManager().visit([&Mod](serialization::ModuleFile &M) {
+ switch (M.Kind) {
+ case serialization::MK_ImplicitModule:
+ case serialization::MK_ExplicitModule:
+ return true; // skip dependencies.
+ case serialization::MK_PCH:
+ Mod = &M;
+ return true; // found it.
+ case serialization::MK_Preamble:
+ return false; // look in dependencies.
+ case serialization::MK_MainFile:
+ return false; // look in dependencies.
+ }
+
+ return true;
+ });
+ if (Mod)
+ return Mod->File;
return nullptr;
}
@@ -2854,9 +2848,9 @@ void ASTUnit::ConcurrencyState::finish() {
#else // NDEBUG
-ASTUnit::ConcurrencyState::ConcurrencyState() { Mutex = 0; }
+ASTUnit::ConcurrencyState::ConcurrencyState() { Mutex = nullptr; }
ASTUnit::ConcurrencyState::~ConcurrencyState() {}
void ASTUnit::ConcurrencyState::start() {}
void ASTUnit::ConcurrencyState::finish() {}
-#endif
+#endif // NDEBUG
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp b/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp
index 7d2a09c..87f3d17 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CacheTokens.cpp
@@ -19,6 +19,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
@@ -105,7 +106,7 @@ public:
}
unsigned getRepresentationLength() const {
- return Kind == IsNoExist ? 0 : 4 + 4 + 2 + 8 + 8;
+ return Kind == IsNoExist ? 0 : 4 * 8;
}
};
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp b/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp
index cc0504b..1c1081f 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ChainedIncludesSource.cpp
@@ -47,9 +47,9 @@ protected:
CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
bool FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) override;
- ExternalLoadResult
+ void
FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
+ llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
SmallVectorImpl<Decl *> &Result) override;
void CompleteType(TagDecl *Tag) override;
void CompleteType(ObjCInterfaceDecl *Class) override;
@@ -82,6 +82,7 @@ createASTReader(CompilerInstance &CI, StringRef pchFile,
std::unique_ptr<ASTReader> Reader;
Reader.reset(new ASTReader(PP, CI.getASTContext(),
CI.getPCHContainerReader(),
+ /*Extensions=*/{ },
/*isysroot=*/"", /*DisableValidation=*/true));
for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
StringRef sr(bufNames[ti]);
@@ -160,8 +161,10 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
Clang->createASTContext();
auto Buffer = std::make_shared<PCHBuffer>();
+ ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions;
auto consumer = llvm::make_unique<PCHGenerator>(
- Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer);
+ Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer,
+ Extensions);
Clang->getASTContext().setASTMutationListener(
consumer->GetASTMutationListener());
Clang->setASTConsumer(std::move(consumer));
@@ -169,7 +172,7 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
if (firstInclude) {
Preprocessor &PP = Clang->getPreprocessor();
- PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
+ PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
PP.getLangOpts());
} else {
assert(!SerialBufs.empty());
@@ -246,11 +249,10 @@ ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) {
return getFinalReader().FindExternalVisibleDeclsByName(DC, Name);
}
-ExternalLoadResult
-ChainedIncludesSource::FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Result) {
- return getFinalReader().FindExternalLexicalDecls(DC, isKindWeWant, Result);
+void ChainedIncludesSource::FindExternalLexicalDecls(
+ const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Result) {
+ return getFinalReader().FindExternalLexicalDecls(DC, IsKindWeWant, Result);
}
void ChainedIncludesSource::CompleteType(TagDecl *Tag) {
return getFinalReader().CompleteType(Tag);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CodeGenOptions.cpp b/contrib/llvm/tools/clang/lib/Frontend/CodeGenOptions.cpp
index 75ee47f..50bb9f9 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CodeGenOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CodeGenOptions.cpp
@@ -21,4 +21,12 @@ CodeGenOptions::CodeGenOptions() {
memcpy(CoverageVersion, "402*", 4);
}
+bool CodeGenOptions::isNoBuiltinFunc(const char *Name) const {
+ StringRef FuncName(Name);
+ for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i)
+ if (FuncName.equals(NoBuiltinFuncs[i]))
+ return true;
+ return false;
+}
+
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
index c33b150..3edcf5d 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp
@@ -78,9 +78,8 @@ void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
Diagnostics = Value;
}
-void CompilerInstance::setTarget(TargetInfo *Value) {
- Target = Value;
-}
+void CompilerInstance::setTarget(TargetInfo *Value) { Target = Value; }
+void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; }
void CompilerInstance::setFileManager(FileManager *Value) {
FileMgr = Value;
@@ -96,7 +95,12 @@ void CompilerInstance::setSourceManager(SourceManager *Value) {
void CompilerInstance::setPreprocessor(Preprocessor *Value) { PP = Value; }
-void CompilerInstance::setASTContext(ASTContext *Value) { Context = Value; }
+void CompilerInstance::setASTContext(ASTContext *Value) {
+ Context = Value;
+
+ if (Context && Consumer)
+ getASTConsumer().Initialize(getASTContext());
+}
void CompilerInstance::setSema(Sema *S) {
TheSema.reset(S);
@@ -104,6 +108,9 @@ void CompilerInstance::setSema(Sema *S) {
void CompilerInstance::setASTConsumer(std::unique_ptr<ASTConsumer> Value) {
Consumer = std::move(Value);
+
+ if (Context && Consumer)
+ getASTConsumer().Initialize(getASTContext());
}
void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
@@ -148,7 +155,6 @@ static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts,
<< DiagOpts->DiagnosticLogFile << EC.message();
} else {
FileOS->SetUnbuffered();
- FileOS->SetUseAtomicWrites(true);
OS = FileOS.get();
StreamOwner = std::move(FileOS);
}
@@ -304,7 +310,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
PP = new Preprocessor(&getPreprocessorOpts(), getDiagnostics(), getLangOpts(),
getSourceManager(), *HeaderInfo, *this, PTHMgr,
/*OwnsHeaderSearch=*/true, TUKind);
- PP->Initialize(getTarget());
+ PP->Initialize(getTarget(), getAuxTarget());
// Note that this is different then passing PTHMgr to Preprocessor's ctor.
// That argument is used as the IdentifierInfoLookup argument to
@@ -331,7 +337,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP);
- if (PP->getLangOpts().Modules)
+ if (PP->getLangOpts().Modules && PP->getLangOpts().ImplicitModules)
PP->getHeaderSearchInfo().setModuleCachePath(getSpecificModuleCachePath());
// Handle generating dependencies, if requested.
@@ -354,17 +360,19 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
// Handle generating header include information, if requested.
if (DepOpts.ShowHeaderIncludes)
- AttachHeaderIncludeGen(*PP);
+ AttachHeaderIncludeGen(*PP, DepOpts.ExtraDeps);
if (!DepOpts.HeaderIncludeOutputFile.empty()) {
StringRef OutputPath = DepOpts.HeaderIncludeOutputFile;
if (OutputPath == "-")
OutputPath = "";
- AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath,
+ AttachHeaderIncludeGen(*PP, DepOpts.ExtraDeps,
+ /*ShowAllHeaders=*/true, OutputPath,
/*ShowDepth=*/false);
}
if (DepOpts.PrintShowIncludes) {
- AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/false, /*OutputPath=*/"",
+ AttachHeaderIncludeGen(*PP, DepOpts.ExtraDeps,
+ /*ShowAllHeaders=*/false, /*OutputPath=*/"",
/*ShowDepth=*/true, /*MSStyle=*/true);
}
}
@@ -372,9 +380,8 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
std::string CompilerInstance::getSpecificModuleCachePath() {
// Set up the module path, including the hash for the
// module-creation options.
- SmallString<256> SpecificModuleCache(
- getHeaderSearchOpts().ModuleCachePath);
- if (!getHeaderSearchOpts().DisableModuleHash)
+ SmallString<256> SpecificModuleCache(getHeaderSearchOpts().ModuleCachePath);
+ if (!SpecificModuleCache.empty() && !getHeaderSearchOpts().DisableModuleHash)
llvm::sys::path::append(SpecificModuleCache,
getInvocation().getModuleHash());
return SpecificModuleCache.str();
@@ -384,10 +391,11 @@ std::string CompilerInstance::getSpecificModuleCachePath() {
void CompilerInstance::createASTContext() {
Preprocessor &PP = getPreprocessor();
- Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
- PP.getIdentifierTable(), PP.getSelectorTable(),
- PP.getBuiltinInfo());
- Context->InitBuiltinTypes(getTarget());
+ auto *Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
+ PP.getIdentifierTable(), PP.getSelectorTable(),
+ PP.getBuiltinInfo());
+ Context->InitBuiltinTypes(getTarget(), getAuxTarget());
+ setASTContext(Context);
}
// ExternalASTSource
@@ -399,7 +407,9 @@ void CompilerInstance::createPCHExternalASTSource(
ModuleManager = createPCHExternalASTSource(
Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation,
AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(),
- getPCHContainerReader(), DeserializationListener,
+ getPCHContainerReader(),
+ getFrontendOpts().ModuleFileExtensions,
+ DeserializationListener,
OwnDeserializationListener, Preamble,
getFrontendOpts().UseGlobalModuleIndex);
}
@@ -408,15 +418,16 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
StringRef Path, StringRef Sysroot, bool DisablePCHValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
const PCHContainerReader &PCHContainerRdr,
+ ArrayRef<IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
void *DeserializationListener, bool OwnDeserializationListener,
bool Preamble, bool UseGlobalModuleIndex) {
HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader(
- PP, Context, PCHContainerRdr, Sysroot.empty() ? "" : Sysroot.data(),
- DisablePCHValidation, AllowPCHWithCompilerErrors,
- /*AllowConfigurationMismatch*/ false, HSOpts.ModulesValidateSystemHeaders,
- UseGlobalModuleIndex));
+ PP, Context, PCHContainerRdr, Extensions,
+ Sysroot.empty() ? "" : Sysroot.data(), DisablePCHValidation,
+ AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false,
+ HSOpts.ModulesValidateSystemHeaders, UseGlobalModuleIndex));
// We need the external source to be set up before we read the AST, because
// eagerly-deserialized declarations may use it.
@@ -631,8 +642,10 @@ std::unique_ptr<llvm::raw_pwrite_stream> CompilerInstance::createOutputFile(
llvm::sys::fs::status(OutputPath, Status);
if (llvm::sys::fs::exists(Status)) {
// Fail early if we can't write to the final destination.
- if (!llvm::sys::fs::can_write(OutputPath))
+ if (!llvm::sys::fs::can_write(OutputPath)) {
+ Error = make_error_code(llvm::errc::operation_not_permitted);
return nullptr;
+ }
// Don't use a temporary if the output is a special file. This handles
// things like '-o /dev/null'
@@ -715,7 +728,7 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,
if (Input.isBuffer()) {
SourceMgr.setMainFileID(SourceMgr.createFileID(
std::unique_ptr<llvm::MemoryBuffer>(Input.getBuffer()), Kind));
- assert(!SourceMgr.getMainFileID().isInvalid() &&
+ assert(SourceMgr.getMainFileID().isValid() &&
"Couldn't establish MainFileID!");
return true;
}
@@ -766,7 +779,7 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,
SourceMgr.overrideFileContents(File, std::move(SB));
}
- assert(!SourceMgr.getMainFileID().isInvalid() &&
+ assert(SourceMgr.getMainFileID().isValid() &&
"Couldn't establish MainFileID!");
return true;
}
@@ -788,6 +801,13 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
if (!hasTarget())
return false;
+ // Create TargetInfo for the other side of CUDA compilation.
+ if (getLangOpts().CUDA && !getFrontendOpts().AuxTriple.empty()) {
+ std::shared_ptr<TargetOptions> TO(new TargetOptions);
+ TO->Triple = getFrontendOpts().AuxTriple;
+ setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO));
+ }
+
// Inform the target of the language options.
//
// FIXME: We shouldn't need to do this, the target should be immutable once
@@ -810,13 +830,13 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
if (getFrontendOpts().ShowStats)
llvm::EnableStatistics();
- for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
+ for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) {
// Reset the ID tables if we are reusing the SourceManager and parsing
// regular files.
if (hasSourceManager() && !Act.isModelParsingAction())
getSourceManager().clearIDTables();
- if (Act.BeginSourceFile(*this, getFrontendOpts().Inputs[i])) {
+ if (Act.BeginSourceFile(*this, FIF)) {
Act.Execute();
Act.EndSourceFile();
}
@@ -912,6 +932,7 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
FrontendOpts.OutputFile = ModuleFileName.str();
FrontendOpts.DisableFree = false;
FrontendOpts.GenerateGlobalModuleIndex = false;
+ FrontendOpts.BuildingImplicitModule = true;
FrontendOpts.Inputs.clear();
InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts());
@@ -945,8 +966,10 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager()));
// If we're collecting module dependencies, we need to share a collector
- // between all of the module CompilerInstances.
+ // between all of the module CompilerInstances. Other than that, we don't
+ // want to produce any dependency output from the module build.
Instance.setModuleDepCollector(ImportingInstance.getModuleDepCollector());
+ Invocation->getDependencyOutputOpts() = DependencyOutputOptions();
// Get or create the module map that we'll use to build this module.
std::string InferredModuleMapContent;
@@ -1151,6 +1174,7 @@ static void pruneModuleCache(const HeaderSearchOptions &HSOpts) {
struct stat StatBuf;
llvm::SmallString<128> TimestampFile;
TimestampFile = HSOpts.ModuleCachePath;
+ assert(!TimestampFile.empty());
llvm::sys::path::append(TimestampFile, "modules.timestamp");
// Try to stat() the timestamp file.
@@ -1229,8 +1253,8 @@ void CompilerInstance::createModuleManager() {
// If we're implicitly building modules but not currently recursively
// building a module, check whether we need to prune the module cache.
- if (getLangOpts().ImplicitModules &&
- getSourceManager().getModuleBuildStack().empty() &&
+ if (getSourceManager().getModuleBuildStack().empty() &&
+ !getPreprocessor().getHeaderSearchInfo().getModuleCachePath().empty() &&
getHeaderSearchOpts().ModuleCachePruneInterval > 0 &&
getHeaderSearchOpts().ModuleCachePruneAfter > 0) {
pruneModuleCache(getHeaderSearchOpts());
@@ -1244,7 +1268,8 @@ void CompilerInstance::createModuleManager() {
ReadTimer = llvm::make_unique<llvm::Timer>("Reading modules",
*FrontendTimerGroup);
ModuleManager = new ASTReader(
- getPreprocessor(), *Context, getPCHContainerReader(),
+ getPreprocessor(), getASTContext(), getPCHContainerReader(),
+ getFrontendOpts().ModuleFileExtensions,
Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation,
/*AllowASTWithCompilerErrors=*/false,
/*AllowConfigurationMismatch=*/false,
@@ -1262,6 +1287,13 @@ void CompilerInstance::createModuleManager() {
ModuleManager->InitializeSema(getSema());
if (hasASTConsumer())
ModuleManager->StartTranslationUnit(&getASTConsumer());
+
+ if (TheDependencyFileGenerator)
+ TheDependencyFileGenerator->AttachToASTReader(*ModuleManager);
+ if (ModuleDepCollector)
+ ModuleDepCollector->attachToASTReader(*ModuleManager);
+ for (auto &Listener : DependencyCollectors)
+ Listener->attachToASTReader(*ModuleManager);
}
}
@@ -1276,87 +1308,68 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
// the files we were handed.
struct ReadModuleNames : ASTReaderListener {
CompilerInstance &CI;
- std::vector<StringRef> ModuleFileStack;
- std::vector<StringRef> ModuleNameStack;
- bool Failed;
- bool TopFileIsModule;
-
- ReadModuleNames(CompilerInstance &CI)
- : CI(CI), Failed(false), TopFileIsModule(false) {}
+ llvm::SmallVector<IdentifierInfo*, 8> LoadedModules;
- bool needsImportVisitation() const override { return true; }
+ ReadModuleNames(CompilerInstance &CI) : CI(CI) {}
- void visitImport(StringRef FileName) override {
- if (!CI.ExplicitlyLoadedModuleFiles.insert(FileName).second) {
- if (ModuleFileStack.size() == 0)
- TopFileIsModule = true;
- return;
- }
+ void ReadModuleName(StringRef ModuleName) override {
+ LoadedModules.push_back(
+ CI.getPreprocessor().getIdentifierInfo(ModuleName));
+ }
- ModuleFileStack.push_back(FileName);
- ModuleNameStack.push_back(StringRef());
- if (ASTReader::readASTFileControlBlock(FileName, CI.getFileManager(),
- CI.getPCHContainerReader(),
- *this)) {
- CI.getDiagnostics().Report(
- SourceLocation(), CI.getFileManager().getBufferForFile(FileName)
- ? diag::err_module_file_invalid
- : diag::err_module_file_not_found)
- << FileName;
- for (int I = ModuleFileStack.size() - 2; I >= 0; --I)
- CI.getDiagnostics().Report(SourceLocation(),
- diag::note_module_file_imported_by)
- << ModuleFileStack[I]
- << !ModuleNameStack[I].empty() << ModuleNameStack[I];
- Failed = true;
+ void registerAll() {
+ for (auto *II : LoadedModules) {
+ CI.KnownModules[II] = CI.getPreprocessor()
+ .getHeaderSearchInfo()
+ .getModuleMap()
+ .findModule(II->getName());
}
- ModuleNameStack.pop_back();
- ModuleFileStack.pop_back();
+ LoadedModules.clear();
}
- void ReadModuleName(StringRef ModuleName) override {
- if (ModuleFileStack.size() == 1)
- TopFileIsModule = true;
- ModuleNameStack.back() = ModuleName;
-
- auto &ModuleFile = CI.ModuleFileOverrides[ModuleName];
- if (!ModuleFile.empty() &&
- CI.getFileManager().getFile(ModuleFile) !=
- CI.getFileManager().getFile(ModuleFileStack.back()))
- CI.getDiagnostics().Report(SourceLocation(),
- diag::err_conflicting_module_files)
- << ModuleName << ModuleFile << ModuleFileStack.back();
- ModuleFile = ModuleFileStack.back();
+ void markAllUnavailable() {
+ for (auto *II : LoadedModules) {
+ if (Module *M = CI.getPreprocessor()
+ .getHeaderSearchInfo()
+ .getModuleMap()
+ .findModule(II->getName()))
+ M->HasIncompatibleModuleFile = true;
+ }
+ LoadedModules.clear();
}
- } RMN(*this);
+ };
// If we don't already have an ASTReader, create one now.
if (!ModuleManager)
createModuleManager();
- // Tell the module manager about this module file.
- if (getModuleManager()->getModuleManager().addKnownModuleFile(FileName)) {
- getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_found)
- << FileName;
- return false;
- }
+ auto Listener = llvm::make_unique<ReadModuleNames>(*this);
+ auto &ListenerRef = *Listener;
+ ASTReader::ListenerScope ReadModuleNamesListener(*ModuleManager,
+ std::move(Listener));
- // Build our mapping of module names to module files from this file
- // and its imports.
- RMN.visitImport(FileName);
+ // Try to load the module file.
+ switch (ModuleManager->ReadAST(FileName, serialization::MK_ExplicitModule,
+ SourceLocation(),
+ ASTReader::ARR_ConfigurationMismatch)) {
+ case ASTReader::Success:
+ // We successfully loaded the module file; remember the set of provided
+ // modules so that we don't try to load implicit modules for them.
+ ListenerRef.registerAll();
+ return true;
- if (RMN.Failed)
- return false;
+ case ASTReader::ConfigurationMismatch:
+ // Ignore unusable module files.
+ getDiagnostics().Report(SourceLocation(), diag::warn_module_config_mismatch)
+ << FileName;
+ // All modules provided by any files we tried and failed to load are now
+ // unavailable; includes of those modules should now be handled textually.
+ ListenerRef.markAllUnavailable();
+ return true;
- // If we never found a module name for the top file, then it's not a module,
- // it's a PCH or preamble or something.
- if (!RMN.TopFileIsModule) {
- getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_module)
- << FileName;
+ default:
return false;
}
-
- return true;
}
ModuleLoadResult
@@ -1371,7 +1384,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// If we've already handled this import, just return the cached result.
// This one-element cache is important to eliminate redundant diagnostics
// when both the preprocessor and parser see the same import declaration.
- if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) {
+ if (ImportLoc.isValid() && LastModuleImportLoc == ImportLoc) {
// Make the named module visible.
if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule &&
ModuleName != getLangOpts().ImplementationOfModule)
@@ -1404,56 +1417,40 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
return ModuleLoadResult();
}
- auto Override = ModuleFileOverrides.find(ModuleName);
- bool Explicit = Override != ModuleFileOverrides.end();
- if (!Explicit && !getLangOpts().ImplicitModules) {
+ std::string ModuleFileName =
+ PP->getHeaderSearchInfo().getModuleFileName(Module);
+ if (ModuleFileName.empty()) {
+ if (Module->HasIncompatibleModuleFile) {
+ // We tried and failed to load a module file for this module. Fall
+ // back to textual inclusion for its headers.
+ return ModuleLoadResult(nullptr, /*missingExpected*/true);
+ }
+
getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled)
<< ModuleName;
ModuleBuildFailed = true;
return ModuleLoadResult();
}
- std::string ModuleFileName =
- Explicit ? Override->second
- : PP->getHeaderSearchInfo().getModuleFileName(Module);
-
// If we don't already have an ASTReader, create one now.
if (!ModuleManager)
createModuleManager();
- if (TheDependencyFileGenerator)
- TheDependencyFileGenerator->AttachToASTReader(*ModuleManager);
-
- if (ModuleDepCollector)
- ModuleDepCollector->attachToASTReader(*ModuleManager);
-
- for (auto &Listener : DependencyCollectors)
- Listener->attachToASTReader(*ModuleManager);
-
llvm::Timer Timer;
if (FrontendTimerGroup)
Timer.init("Loading " + ModuleFileName, *FrontendTimerGroup);
llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
// Try to load the module file.
- unsigned ARRFlags =
- Explicit ? 0 : ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing;
+ unsigned ARRFlags = ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing;
switch (ModuleManager->ReadAST(ModuleFileName,
- Explicit ? serialization::MK_ExplicitModule
- : serialization::MK_ImplicitModule,
+ serialization::MK_ImplicitModule,
ImportLoc, ARRFlags)) {
case ASTReader::Success:
break;
case ASTReader::OutOfDate:
case ASTReader::Missing: {
- if (Explicit) {
- // ReadAST has already complained for us.
- ModuleLoader::HadFatalFailure = true;
- KnownModules[Path[0].first] = nullptr;
- return ModuleLoadResult();
- }
-
// The module file is missing or out-of-date. Build it.
assert(Module && "missing module file");
// Check whether there is a cycle in the module graph.
@@ -1508,7 +1505,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
case ASTReader::ConfigurationMismatch:
case ASTReader::HadErrors:
ModuleLoader::HadFatalFailure = true;
- // FIXME: The ASTReader will already have complained, but can we showhorn
+ // FIXME: The ASTReader will already have complained, but can we shoehorn
// that diagnostic information into a more useful form?
KnownModules[Path[0].first] = nullptr;
return ModuleLoadResult();
@@ -1652,6 +1649,8 @@ void CompilerInstance::makeModuleVisible(Module *Mod,
GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(
SourceLocation TriggerLoc) {
+ if (getPreprocessor().getHeaderSearchInfo().getModuleCachePath().empty())
+ return nullptr;
if (!ModuleManager)
createModuleManager();
// Can't do anything if we don't have the module manager.
@@ -1685,11 +1684,10 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(
if (!Entry) {
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
Path.push_back(std::make_pair(
- getPreprocessor().getIdentifierInfo(TheModule->Name), TriggerLoc));
+ getPreprocessor().getIdentifierInfo(TheModule->Name), TriggerLoc));
std::reverse(Path.begin(), Path.end());
- // Load a module as hidden. This also adds it to the global index.
- loadModule(TheModule->DefinitionLoc, Path,
- Module::Hidden, false);
+ // Load a module as hidden. This also adds it to the global index.
+ loadModule(TheModule->DefinitionLoc, Path, Module::Hidden, false);
RecreateIndex = true;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
index fbeba09..237a447 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -7,24 +7,28 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/CompilerInvocation.h"
+#include "TestModuleFileExtension.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#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/Serialization/ASTReader.h"
+#include "clang/Serialization/ModuleFileExtension.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Linker/Linker.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
@@ -35,6 +39,7 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
+#include "llvm/Target/TargetOptions.h"
#include <atomic>
#include <memory>
#include <sys/stat.h>
@@ -53,7 +58,7 @@ CompilerInvocationBase::CompilerInvocationBase()
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X)
: RefCountedBase<CompilerInvocation>(),
- LangOpts(new LangOptions(*X.getLangOpts())),
+ LangOpts(new LangOptions(*X.getLangOpts())),
TargetOpts(new TargetOptions(X.getTargetOpts())),
DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())),
HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())),
@@ -131,6 +136,20 @@ static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
}
}
+static void getAllNoBuiltinFuncValues(ArgList &Args,
+ std::vector<std::string> &Funcs) {
+ SmallVector<const char *, 8> Values;
+ for (const auto &Arg : Args) {
+ const Option &O = Arg->getOption();
+ if (O.matches(options::OPT_fno_builtin_)) {
+ const char *FuncName = Arg->getValue();
+ if (Builtin::Context::isBuiltinFunc(FuncName))
+ Values.push_back(FuncName);
+ }
+ }
+ Funcs.insert(Funcs.end(), Values.begin(), Values.end());
+}
+
static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
using namespace options;
@@ -361,6 +380,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
const TargetOptions &TargetOpts) {
using namespace options;
bool Success = true;
+ llvm::Triple Triple = llvm::Triple(TargetOpts.Triple);
unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
// TODO: This could be done in Driver
@@ -393,39 +413,47 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
}
- if (Args.hasArg(OPT_gline_tables_only)) {
- Opts.setDebugInfo(CodeGenOptions::DebugLineTablesOnly);
- } else if (Args.hasArg(OPT_g_Flag) || Args.hasArg(OPT_gdwarf_2) ||
- Args.hasArg(OPT_gdwarf_3) || Args.hasArg(OPT_gdwarf_4)) {
- bool Default = false;
- // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
- // Darwin and FreeBSD default to standalone/full debug info.
- if (llvm::Triple(TargetOpts.Triple).isOSDarwin() ||
- llvm::Triple(TargetOpts.Triple).isOSFreeBSD())
- Default = true;
-
- if (Args.hasFlag(OPT_fstandalone_debug, OPT_fno_standalone_debug, Default))
- Opts.setDebugInfo(CodeGenOptions::FullDebugInfo);
+ 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)
+ .Default(~0U);
+ if (Val == ~0U)
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
+ << A->getValue();
else
- Opts.setDebugInfo(CodeGenOptions::LimitedDebugInfo);
+ 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)
+ .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.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 0, Diags);
Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
+ Opts.EmitCodeView = Args.hasArg(OPT_gcodeview);
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
- if (Args.hasArg(OPT_gdwarf_2))
- Opts.DwarfVersion = 2;
- else if (Args.hasArg(OPT_gdwarf_3))
- Opts.DwarfVersion = 3;
- else if (Args.hasArg(OPT_gdwarf_4))
- Opts.DwarfVersion = 4;
- else if (Opts.getDebugInfo() != CodeGenOptions::NoDebugInfo)
- // Default Dwarf version is 4 if we are generating debug information.
- Opts.DwarfVersion = 4;
+ Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
+ Opts.DebugExplicitImport = Triple.isPS4CPU();
+
+ for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
+ Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));
if (const Arg *A =
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.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
Opts.UseRegisterSizedBitfieldAccess = Args.hasArg(
@@ -439,6 +467,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.OptimizeSize = getOptimizationLevelSize(Args);
Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||
Args.hasArg(OPT_ffreestanding));
+ if (Opts.SimplifyLibCalls)
+ getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
Opts.UnrollLoops =
Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
(Opts.OptimizationLevel > 1 && !Opts.OptimizeSize));
@@ -451,7 +481,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
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.CoverageMapping = Args.hasArg(OPT_fcoverage_mapping);
+ 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.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
@@ -459,10 +490,25 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
Opts.CodeModel = getCodeModel(Args, Diags);
Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass);
- Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim);
+ Opts.DisableFPElim =
+ (Args.hasArg(OPT_mdisable_fp_elim) || Args.hasArg(OPT_pg));
Opts.DisableFree = Args.hasArg(OPT_disable_free);
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.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision);
Opts.NoInfsFPMath = (Args.hasArg(OPT_menable_no_infinities) ||
@@ -481,11 +527,14 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
Opts.EnableSegmentedStacks = Args.hasArg(OPT_split_stacks);
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
+ Opts.IncrementalLinkerCompatible =
+ Args.hasArg(OPT_mincremental_linker_compatible);
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.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);
@@ -508,7 +557,15 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions);
- Opts.PrepareForLTO = Args.hasArg(OPT_flto);
+ 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");
+ if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
+ if (IK != IK_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.MSVolatile = Args.hasArg(OPT_fms_volatile);
@@ -546,7 +603,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
- Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file);
+ 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()));
+ }
Opts.SanitizeCoverageType =
getLastArgIntValue(Args, OPT_fsanitize_coverage_type, 0, Diags);
Opts.SanitizeCoverageIndirectCalls =
@@ -559,6 +622,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
Opts.SanitizeMemoryUseAfterDtor =
Args.hasArg(OPT_fsanitize_memory_use_after_dtor);
+ Opts.SanitizeCfiCrossDso = Args.hasArg(OPT_fsanitize_cfi_cross_dso);
Opts.SSPBufferSize =
getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags);
Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
@@ -592,6 +656,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
}
+ Opts.EmulatedTLS =
+ Args.hasFlag(OPT_femulated_tls, OPT_fno_emulated_tls, false);
+
if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) {
StringRef Name = A->getValue();
unsigned Model = llvm::StringSwitch<unsigned>(Name)
@@ -695,6 +762,13 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
Args.getLastArgValue(OPT_module_dependency_dir);
if (Args.hasArg(OPT_MV))
Opts.OutputFormat = DependencyOutputFormat::NMake;
+ // Add sanitizer blacklists as extra dependencies.
+ // 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());
}
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
@@ -822,6 +896,30 @@ static void ParseFileSystemArgs(FileSystemOptions &Opts, ArgList &Args) {
Opts.WorkingDir = Args.getLastArgValue(OPT_working_directory);
}
+/// Parse the argument to the -ftest-module-file-extension
+/// command-line argument.
+///
+/// \returns true on error, false on success.
+static bool parseTestModuleFileExtensionArg(StringRef Arg,
+ std::string &BlockName,
+ unsigned &MajorVersion,
+ unsigned &MinorVersion,
+ bool &Hashed,
+ std::string &UserInfo) {
+ SmallVector<StringRef, 5> Args;
+ Arg.split(Args, ':', 5);
+ if (Args.size() < 5)
+ return true;
+
+ BlockName = Args[0];
+ if (Args[1].getAsInteger(10, MajorVersion)) return true;
+ if (Args[2].getAsInteger(10, MinorVersion)) return true;
+ if (Args[3].getAsInteger(2, Hashed)) return true;
+ if (Args.size() > 4)
+ UserInfo = Args[4];
+ return false;
+}
+
static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
using namespace options;
@@ -914,6 +1012,26 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
if (A->getValue(0) == Opts.AddPluginActions[i])
Opts.AddPluginArgs[i].emplace_back(A->getValue(1));
+ for (const std::string &Arg :
+ Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) {
+ std::string BlockName;
+ unsigned MajorVersion;
+ unsigned MinorVersion;
+ bool Hashed;
+ std::string UserInfo;
+ if (parseTestModuleFileExtensionArg(Arg, BlockName, MajorVersion,
+ MinorVersion, Hashed, UserInfo)) {
+ Diags.Report(diag::err_test_module_file_extension_format) << Arg;
+
+ continue;
+ }
+
+ // Add the testing module file extension.
+ Opts.ModuleFileExtensions.push_back(
+ new TestModuleFileExtension(BlockName, MajorVersion, MinorVersion,
+ Hashed, UserInfo));
+ }
+
if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
Opts.CodeCompletionAt =
ParsedSourceLocation::FromString(A->getValue());
@@ -943,6 +1061,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex;
Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file);
Opts.ModuleFiles = Args.getAllArgValues(OPT_fmodule_file);
+ Opts.ModulesEmbedFiles = Args.getAllArgValues(OPT_fmodules_embed_file_EQ);
+ Opts.ModulesEmbedAllFiles = Args.hasArg(OPT_fmodules_embed_all_files);
Opts.CodeCompleteOpts.IncludeMacros
= Args.hasArg(OPT_code_completion_macros);
@@ -955,6 +1075,9 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.OverrideRecordLayoutsFile
= Args.getLastArgValue(OPT_foverride_record_layout_EQ);
+ Opts.AuxTriple =
+ llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple));
+
if (const Arg *A = Args.getLastArg(OPT_arcmt_check,
OPT_arcmt_modify,
OPT_arcmt_migrate)) {
@@ -1076,13 +1199,11 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
// Compute the path to the resource directory.
StringRef ClangResourceDir(CLANG_RESOURCE_DIR);
SmallString<128> P(Dir);
- if (ClangResourceDir != "") {
+ if (ClangResourceDir != "")
llvm::sys::path::append(P, ClangResourceDir);
- } else {
- StringRef ClangLibdirSuffix(CLANG_LIBDIR_SUFFIX);
- llvm::sys::path::append(P, "..", Twine("lib") + ClangLibdirSuffix, "clang",
- CLANG_VERSION_STRING);
- }
+ else
+ llvm::sys::path::append(P, "..", Twine("lib") + CLANG_LIBDIR_SUFFIX,
+ "clang", CLANG_VERSION_STRING);
return P.str();
}
@@ -1291,7 +1412,7 @@ static Visibility parseVisibility(Arg *arg, ArgList &args,
StringRef value = arg->getValue();
if (value == "default") {
return DefaultVisibility;
- } else if (value == "hidden") {
+ } else if (value == "hidden" || value == "internal") {
return HiddenVisibility;
} else if (value == "protected") {
// FIXME: diagnose if target does not support protected visibility
@@ -1364,7 +1485,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
.Case("CL1.2", LangStandard::lang_opencl12)
.Case("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();
@@ -1372,7 +1493,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
else
LangStd = OpenCLLangStd;
}
-
+
CompilerInvocation::setLangDefaults(Opts, IK, LangStd);
// We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension
@@ -1395,6 +1516,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_fcuda_disable_target_call_checks))
Opts.CUDADisableTargetCallChecks = 1;
+ if (Args.hasArg(OPT_fcuda_target_overloads))
+ Opts.CUDATargetOverloads = 1;
+
if (Opts.ObjC1) {
if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
StringRef value = arg->getValue();
@@ -1410,22 +1534,41 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.ObjCAutoRefCount = 1;
if (!Opts.ObjCRuntime.allowsARC())
Diags.Report(diag::err_arc_unsupported_on_runtime);
+ }
- // Only set ObjCARCWeak if ARC is enabled.
- if (Args.hasArg(OPT_fobjc_runtime_has_weak))
- Opts.ObjCARCWeak = 1;
- else
- Opts.ObjCARCWeak = Opts.ObjCRuntime.allowsWeak();
+ // ObjCWeakRuntime tracks whether the runtime supports __weak, not
+ // whether the feature is actually enabled. This is predominantly
+ // determined by -fobjc-runtime, but we allow it to be overridden
+ // from the command line for testing purposes.
+ if (Args.hasArg(OPT_fobjc_runtime_has_weak))
+ Opts.ObjCWeakRuntime = 1;
+ else
+ Opts.ObjCWeakRuntime = Opts.ObjCRuntime.allowsWeak();
+
+ // ObjCWeak determines whether __weak is actually enabled.
+ // Note that we allow -fno-objc-weak to disable this even in ARC mode.
+ if (auto weakArg = Args.getLastArg(OPT_fobjc_weak, OPT_fno_objc_weak)) {
+ if (!weakArg->getOption().matches(OPT_fobjc_weak)) {
+ assert(!Opts.ObjCWeak);
+ } else if (Opts.getGC() != LangOptions::NonGC) {
+ Diags.Report(diag::err_objc_weak_with_gc);
+ } else if (!Opts.ObjCWeakRuntime) {
+ Diags.Report(diag::err_objc_weak_unsupported);
+ } else {
+ Opts.ObjCWeak = 1;
+ }
+ } else if (Opts.ObjCAutoRefCount) {
+ Opts.ObjCWeak = Opts.ObjCWeakRuntime;
}
if (Args.hasArg(OPT_fno_objc_infer_related_result_type))
Opts.ObjCInferRelatedResultType = 0;
-
+
if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime))
Opts.ObjCSubscriptingLegacyRuntime =
(Opts.ObjCRuntime.getKind() == ObjCRuntime::FragileMacOSX);
}
-
+
if (Args.hasArg(OPT_fgnu89_inline)) {
if (Opts.CPlusPlus)
Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fgnu89-inline"
@@ -1525,14 +1668,13 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.RTTIData = Opts.RTTI && !Args.hasArg(OPT_fno_rtti_data);
Opts.Blocks = Args.hasArg(OPT_fblocks);
Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
+ Opts.Coroutines = Args.hasArg(OPT_fcoroutines);
Opts.Modules = Args.hasArg(OPT_fmodules);
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);
- Opts.ModulesHideInternalLinkage =
- !Args.hasArg(OPT_fno_modules_hide_internal_linkage);
Opts.ModulesSearchAll = Opts.Modules &&
!Args.hasArg(OPT_fno_modules_search_all) &&
Args.hasArg(OPT_fmodules_search_all);
@@ -1544,6 +1686,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
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.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation);
@@ -1578,7 +1722,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.PIELevel = getLastArgIntValue(Args, OPT_pie_level, 0, Diags);
Opts.Static = Args.hasArg(OPT_static_define);
Opts.DumpRecordLayoutsSimple = Args.hasArg(OPT_fdump_record_layouts_simple);
- Opts.DumpRecordLayouts = Opts.DumpRecordLayoutsSimple
+ Opts.DumpRecordLayouts = Opts.DumpRecordLayoutsSimple
|| Args.hasArg(OPT_fdump_record_layouts);
Opts.DumpVTableLayouts = Args.hasArg(OPT_fdump_vtable_layouts);
Opts.SpellChecking = !Args.hasArg(OPT_fno_spell_checking);
@@ -1603,6 +1747,17 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns);
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.
+ 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)
@@ -1622,7 +1777,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
.Case("yes", LangOptions::ASMM_On)
.Default(255)) {
default:
- Diags.Report(diag::err_drv_invalid_value)
+ Diags.Report(diag::err_drv_invalid_value)
<< "-faddress-space-map-mangling=" << A->getValue();
break;
case LangOptions::ASMM_Target:
@@ -1659,6 +1814,30 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.OpenMP = Args.hasArg(options::OPT_fopenmp);
Opts.OpenMPUseTLS =
Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
+ Opts.OpenMPIsDevice =
+ Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device);
+
+ // Get the OpenMP target triples if any.
+ if (Arg *A = Args.getLastArg(options::OPT_omptargets_EQ)) {
+
+ for (unsigned i = 0; i < A->getNumValues(); ++i) {
+ llvm::Triple TT(A->getValue(i));
+
+ if (TT.getArch() == llvm::Triple::UnknownArch)
+ Diags.Report(clang::diag::err_drv_invalid_omp_target) << A->getValue(i);
+ else
+ Opts.OMPTargetTriples.push_back(TT);
+ }
+ }
+
+ // 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)) {
+ Opts.OMPHostIRFile = A->getValue();
+ if (!llvm::sys::fs::exists(Opts.OMPHostIRFile))
+ Diags.Report(clang::diag::err_drv_omp_host_ir_file_not_found)
+ << Opts.OMPHostIRFile;
+ }
// Record whether the __DEPRECATED define was requested.
Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro,
@@ -1681,6 +1860,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.FiniteMathOnly = Args.hasArg(OPT_ffinite_math_only) ||
Args.hasArg(OPT_cl_finite_math_only) ||
Args.hasArg(OPT_cl_fast_relaxed_math);
+ Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) ||
+ Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
+ Args.hasArg(OPT_cl_fast_relaxed_math);
Opts.RetainCommentsFromSystemHeaders =
Args.hasArg(OPT_fretain_comments_from_system_headers);
@@ -1891,14 +2073,23 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags,
Res.getTargetOpts());
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args);
- if (DashX != IK_AST && DashX != IK_LLVM_IR) {
+ if (DashX == IK_AST || DashX == IK_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;
+ parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
+ Diags, Res.getLangOpts()->Sanitize);
+ } else {
+ // Other LangOpts are only initialzed when the input is not AST or LLVM IR.
ParseLangArgs(*Res.getLangOpts(), Args, DashX, Diags);
if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
Res.getLangOpts()->ObjCExceptions = 1;
}
// 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
+ // ParsePreprocessorArgs and remove the FileManager
// parameters from the function and the "FileManager.h" #include.
FileManager FileMgr(Res.getFileSystemOpts());
ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags);
@@ -1913,14 +2104,14 @@ namespace {
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;
};
}
@@ -1931,10 +2122,10 @@ void ModuleSignature::add(uint64_t Value, unsigned int NumBits) {
CurBit += NumBits;
return;
}
-
+
// Add the current word.
Data.push_back(CurValue);
-
+
if (CurBit)
CurValue = Value >> (64-CurBit);
else
@@ -1945,15 +2136,15 @@ void ModuleSignature::add(uint64_t Value, unsigned int NumBits) {
void ModuleSignature::flush() {
if (CurBit == 0)
return;
-
+
Data.push_back(CurValue);
CurBit = 0;
CurValue = 0;
}
void ModuleSignature::add(StringRef Value) {
- for (StringRef::iterator I = Value.begin(), IEnd = Value.end(); I != IEnd;++I)
- add(*I, 8);
+ for (auto &c : Value)
+ add(c, 8);
}
llvm::APInt ModuleSignature::getAsInteger() const {
@@ -1983,7 +2174,7 @@ std::string CompilerInvocation::getModuleHash() const {
for (StringRef Feature : LangOpts->ModuleFeatures)
code = hash_combine(code, Feature);
-
+
// Extend the signature with the target options.
code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU,
TargetOpts->ABI);
@@ -1995,7 +2186,7 @@ std::string CompilerInvocation::getModuleHash() const {
const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
code = hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord);
- for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator
+ for (std::vector<std::pair<std::string, bool/*isUndef*/>>::const_iterator
I = getPreprocessorOpts().Macros.begin(),
IEnd = getPreprocessorOpts().Macros.end();
I != IEnd; ++I) {
@@ -2011,8 +2202,11 @@ std::string CompilerInvocation::getModuleHash() const {
code = hash_combine(code, I->first, I->second);
}
- // Extend the signature with the sysroot.
- code = hash_combine(code, hsOpts.Sysroot, hsOpts.UseBuiltinIncludes,
+ // Extend the signature with the sysroot and other header search options.
+ code = hash_combine(code, hsOpts.Sysroot,
+ hsOpts.ModuleFormat,
+ hsOpts.UseDebugInfo,
+ hsOpts.UseBuiltinIncludes,
hsOpts.UseStandardSystemIncludes,
hsOpts.UseStandardCXXIncludes,
hsOpts.UseLibcxx);
@@ -2021,6 +2215,12 @@ std::string CompilerInvocation::getModuleHash() const {
// Extend the signature with the user build path.
code = hash_combine(code, hsOpts.ModuleUserBuildPath);
+ // Extend the signature with the module file extensions.
+ const FrontendOptions &frontendOpts = getFrontendOpts();
+ for (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
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp b/contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
index 2afd23f..3019164 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -39,15 +39,13 @@ clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList,
Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions);
}
- SmallVector<const char *, 16> Args;
- Args.push_back("<clang>"); // FIXME: Remove dummy argument.
- Args.insert(Args.end(), ArgList.begin(), ArgList.end());
+ SmallVector<const char *, 16> Args(ArgList.begin(), ArgList.end());
// FIXME: Find a cleaner way to force the driver into restricted modes.
Args.push_back("-fsyntax-only");
// FIXME: We shouldn't have to pass in the path info.
- driver::Driver TheDriver("clang", llvm::sys::getDefaultTargetTriple(),
+ driver::Driver TheDriver(Args[0], llvm::sys::getDefaultTargetTriple(),
*Diags);
// Don't check that inputs exist, they may have been remapped.
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp b/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp
index 0995ab4..93d4a80 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/DependencyFile.cpp
@@ -18,6 +18,7 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ASTReader.h"
@@ -50,15 +51,8 @@ struct DepCollectorPPCallbacks : public PPCallbacks {
if (!FE)
return;
- StringRef Filename = FE->getName();
-
- // Remove leading "./" (or ".//" or "././" etc.)
- while (Filename.size() > 2 && Filename[0] == '.' &&
- llvm::sys::path::is_separator(Filename[1])) {
- Filename = Filename.substr(1);
- while (llvm::sys::path::is_separator(Filename[0]))
- Filename = Filename.substr(1);
- }
+ StringRef Filename =
+ llvm::sys::path::remove_leading_dotslash(FE->getName());
DepCollector.maybeAddDependency(Filename, /*FromModule*/false,
FileType != SrcMgr::C_User,
@@ -82,6 +76,20 @@ struct DepCollectorPPCallbacks : public PPCallbacks {
}
};
+struct DepCollectorMMCallbacks : public ModuleMapCallbacks {
+ DependencyCollector &DepCollector;
+ DepCollectorMMCallbacks(DependencyCollector &DC) : DepCollector(DC) {}
+
+ void moduleMapFileRead(SourceLocation Loc, const FileEntry &Entry,
+ bool IsSystem) override {
+ StringRef Filename = Entry.getName();
+ DepCollector.maybeAddDependency(Filename, /*FromModule*/false,
+ /*IsSystem*/IsSystem,
+ /*IsModuleFile*/false,
+ /*IsMissing*/false);
+ }
+};
+
struct DepCollectorASTListener : public ASTReaderListener {
DependencyCollector &DepCollector;
DepCollectorASTListener(DependencyCollector &L) : DepCollector(L) { }
@@ -89,14 +97,15 @@ struct DepCollectorASTListener : public ASTReaderListener {
bool needsSystemInputFileVisitation() override {
return DepCollector.needSystemDependencies();
}
- void visitModuleFile(StringRef Filename) override {
+ void visitModuleFile(StringRef Filename,
+ serialization::ModuleKind Kind) override {
DepCollector.maybeAddDependency(Filename, /*FromModule*/true,
/*IsSystem*/false, /*IsModuleFile*/true,
/*IsMissing*/false);
}
bool visitInputFile(StringRef Filename, bool IsSystem,
- bool IsOverridden) override {
- if (IsOverridden)
+ bool IsOverridden, bool IsExplicitModule) override {
+ if (IsOverridden || IsExplicitModule)
return true;
DepCollector.maybeAddDependency(Filename, /*FromModule*/true, IsSystem,
@@ -132,6 +141,8 @@ DependencyCollector::~DependencyCollector() { }
void DependencyCollector::attachToPreprocessor(Preprocessor &PP) {
PP.addPPCallbacks(
llvm::make_unique<DepCollectorPPCallbacks>(*this, PP.getSourceManager()));
+ PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
+ llvm::make_unique<DepCollectorMMCallbacks>(*this));
}
void DependencyCollector::attachToASTReader(ASTReader &R) {
R.addListener(llvm::make_unique<DepCollectorASTListener>(*this));
@@ -165,7 +176,11 @@ public:
AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
SeenMissingHeader(false),
IncludeModuleFiles(Opts.IncludeModuleFiles),
- OutputFormat(Opts.OutputFormat) {}
+ OutputFormat(Opts.OutputFormat) {
+ for (auto ExtraDep : Opts.ExtraDeps) {
+ AddFilename(ExtraDep);
+ }
+ }
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
@@ -185,6 +200,17 @@ public:
bool includeModuleFiles() const { return IncludeModuleFiles; }
};
+class DFGMMCallback : public ModuleMapCallbacks {
+ DFGImpl &Parent;
+public:
+ DFGMMCallback(DFGImpl &Parent) : Parent(Parent) {}
+ void moduleMapFileRead(SourceLocation Loc, const FileEntry &Entry,
+ bool IsSystem) override {
+ if (!IsSystem || Parent.includeSystemHeaders())
+ Parent.AddFilename(Entry.getName());
+ }
+};
+
class DFGASTReaderListener : public ASTReaderListener {
DFGImpl &Parent;
public:
@@ -194,9 +220,10 @@ public:
bool needsSystemInputFileVisitation() override {
return Parent.includeSystemHeaders();
}
- void visitModuleFile(StringRef Filename) override;
+ void visitModuleFile(StringRef Filename,
+ serialization::ModuleKind Kind) override;
bool visitInputFile(StringRef Filename, bool isSystem,
- bool isOverridden) override;
+ bool isOverridden, bool isExplicitModule) override;
};
}
@@ -217,6 +244,8 @@ DependencyFileGenerator *DependencyFileGenerator::CreateAndAttachToPreprocessor(
DFGImpl *Callback = new DFGImpl(&PP, Opts);
PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callback));
+ PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
+ llvm::make_unique<DFGMMCallback>(*Callback));
return new DependencyFileGenerator(Callback);
}
@@ -259,15 +288,7 @@ void DFGImpl::FileChanged(SourceLocation Loc,
if (!FileMatchesDepCriteria(Filename.data(), FileType))
return;
- // Remove leading "./" (or ".//" or "././" etc.)
- while (Filename.size() > 2 && Filename[0] == '.' &&
- llvm::sys::path::is_separator(Filename[1])) {
- Filename = Filename.substr(1);
- while (llvm::sys::path::is_separator(Filename[0]))
- Filename = Filename.substr(1);
- }
-
- AddFilename(Filename);
+ AddFilename(llvm::sys::path::remove_leading_dotslash(Filename));
}
void DFGImpl::InclusionDirective(SourceLocation HashLoc,
@@ -438,16 +459,18 @@ void DFGImpl::OutputDependencyFile() {
}
bool DFGASTReaderListener::visitInputFile(llvm::StringRef Filename,
- bool IsSystem, bool IsOverridden) {
+ bool IsSystem, bool IsOverridden,
+ bool IsExplicitModule) {
assert(!IsSystem || needsSystemInputFileVisitation());
- if (IsOverridden)
+ if (IsOverridden || IsExplicitModule)
return true;
Parent.AddFilename(Filename);
return true;
}
-void DFGASTReaderListener::visitModuleFile(llvm::StringRef Filename) {
+void DFGASTReaderListener::visitModuleFile(llvm::StringRef Filename,
+ serialization::ModuleKind Kind) {
if (Parent.includeModuleFiles())
Parent.AddFilename(Filename);
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DiagnosticRenderer.cpp b/contrib/llvm/tools/clang/lib/Frontend/DiagnosticRenderer.cpp
index c63e98d..caf1f0d 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/DiagnosticRenderer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/DiagnosticRenderer.cpp
@@ -169,9 +169,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
// If this location is within a macro, walk from UnexpandedLoc up to Loc
// and produce a macro backtrace.
if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) {
- unsigned MacroDepth = 0;
- emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM,
- MacroDepth);
+ emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM);
}
}
@@ -247,7 +245,7 @@ void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
// import stack rather than the
// FIXME: We want submodule granularity here.
std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc);
- if (Imported.first.isValid()) {
+ if (!Imported.second.empty()) {
// This location was imported by a module. Emit the module import stack.
emitImportStackRecursively(Imported.first, Imported.second, SM);
return;
@@ -278,13 +276,11 @@ void DiagnosticRenderer::emitImportStack(SourceLocation Loc,
void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc,
StringRef ModuleName,
const SourceManager &SM) {
- if (Loc.isInvalid()) {
+ if (ModuleName.empty()) {
return;
}
PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
- if (PLoc.isInvalid())
- return;
// Emit the other import frames first.
std::pair<SourceLocation, StringRef> NextImportLoc
@@ -310,6 +306,81 @@ void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) {
}
}
+/// A recursive function to trace all possible backtrace locations
+/// to match the \p CaretLocFileID.
+static SourceLocation
+retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID,
+ FileID CaretFileID,
+ const SmallVectorImpl<FileID> &CommonArgExpansions,
+ bool IsBegin, const SourceManager *SM) {
+ assert(SM->getFileID(Loc) == MacroFileID);
+ if (MacroFileID == CaretFileID)
+ return Loc;
+ if (!Loc.isMacroID())
+ return SourceLocation();
+
+ SourceLocation MacroLocation, MacroArgLocation;
+
+ if (SM->isMacroArgExpansion(Loc)) {
+ // Only look at the immediate spelling location of this macro argument if
+ // the other location in the source range is also present in that expansion.
+ if (std::binary_search(CommonArgExpansions.begin(),
+ CommonArgExpansions.end(), MacroFileID))
+ MacroLocation = SM->getImmediateSpellingLoc(Loc);
+ MacroArgLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first
+ : SM->getImmediateExpansionRange(Loc).second;
+ } else {
+ MacroLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first
+ : SM->getImmediateExpansionRange(Loc).second;
+ MacroArgLocation = SM->getImmediateSpellingLoc(Loc);
+ }
+
+ if (MacroLocation.isValid()) {
+ MacroFileID = SM->getFileID(MacroLocation);
+ MacroLocation =
+ retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID,
+ CommonArgExpansions, IsBegin, SM);
+ if (MacroLocation.isValid())
+ return MacroLocation;
+ }
+
+ MacroFileID = SM->getFileID(MacroArgLocation);
+ return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID,
+ CommonArgExpansions, IsBegin, SM);
+}
+
+/// Walk up the chain of macro expansions and collect the FileIDs identifying the
+/// expansions.
+static void getMacroArgExpansionFileIDs(SourceLocation Loc,
+ SmallVectorImpl<FileID> &IDs,
+ bool IsBegin, const SourceManager *SM) {
+ while (Loc.isMacroID()) {
+ if (SM->isMacroArgExpansion(Loc)) {
+ IDs.push_back(SM->getFileID(Loc));
+ Loc = SM->getImmediateSpellingLoc(Loc);
+ } else {
+ auto ExpRange = SM->getImmediateExpansionRange(Loc);
+ Loc = IsBegin ? ExpRange.first : ExpRange.second;
+ }
+ }
+}
+
+/// Collect the expansions of the begin and end locations and compute the set
+/// intersection. Produces a sorted vector of FileIDs in CommonArgExpansions.
+static void computeCommonMacroArgExpansionFileIDs(
+ SourceLocation Begin, SourceLocation End, const SourceManager *SM,
+ SmallVectorImpl<FileID> &CommonArgExpansions) {
+ SmallVector<FileID, 4> BeginArgExpansions;
+ SmallVector<FileID, 4> EndArgExpansions;
+ getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM);
+ getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM);
+ std::sort(BeginArgExpansions.begin(), BeginArgExpansions.end());
+ std::sort(EndArgExpansions.begin(), EndArgExpansions.end());
+ std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(),
+ EndArgExpansions.begin(), EndArgExpansions.end(),
+ std::back_inserter(CommonArgExpansions));
+}
+
// Helper function to fix up source ranges. It takes in an array of ranges,
// and outputs an array of ranges where we want to draw the range highlighting
// around the location specified by CaretLoc.
@@ -327,9 +398,9 @@ static void mapDiagnosticRanges(
const SourceManager *SM) {
FileID CaretLocFileID = SM->getFileID(CaretLoc);
- for (ArrayRef<CharSourceRange>::const_iterator I = Ranges.begin(),
- E = Ranges.end();
- I != E; ++I) {
+ for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
+ if (I->isInvalid()) continue;
+
SourceLocation Begin = I->getBegin(), End = I->getEnd();
bool IsTokenRange = I->isTokenRange();
@@ -358,27 +429,19 @@ static void mapDiagnosticRanges(
}
}
- while (Begin.isMacroID() && BeginFileID != CaretLocFileID) {
- if (SM->isMacroArgExpansion(Begin)) {
- Begin = SM->getImmediateSpellingLoc(Begin);
- End = SM->getImmediateSpellingLoc(End);
- } else {
- Begin = SM->getImmediateExpansionRange(Begin).first;
- End = SM->getImmediateExpansionRange(End).second;
- }
- BeginFileID = SM->getFileID(Begin);
- if (BeginFileID != SM->getFileID(End)) {
- // FIXME: Ugly hack to stop a crash; this code is making bad
- // assumptions and it's too complicated for me to reason
- // about.
- Begin = End = SourceLocation();
- break;
- }
- }
+ // Do the backtracking.
+ SmallVector<FileID, 4> CommonArgExpansions;
+ computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions);
+ Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID,
+ CommonArgExpansions, /*IsBegin=*/true, SM);
+ End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID,
+ CommonArgExpansions, /*IsBegin=*/false, SM);
+ if (Begin.isInvalid() || End.isInvalid()) continue;
// Return the spelling location of the beginning and end of the range.
Begin = SM->getSpellingLoc(Begin);
End = SM->getSpellingLoc(End);
+
SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End),
IsTokenRange));
}
@@ -394,6 +457,96 @@ void DiagnosticRenderer::emitCaret(SourceLocation Loc,
emitCodeContext(Loc, Level, SpellingRanges, Hints, SM);
}
+/// \brief A helper function for emitMacroExpansion to print the
+/// macro expansion message
+void DiagnosticRenderer::emitSingleMacroExpansion(
+ SourceLocation Loc,
+ DiagnosticsEngine::Level Level,
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager &SM) {
+ // Find the spelling location for the macro definition. We must use the
+ // spelling location here to avoid emitting a macro backtrace for the note.
+ SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
+
+ // Map the ranges into the FileID of the diagnostic location.
+ SmallVector<CharSourceRange, 4> SpellingRanges;
+ mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
+
+ SmallString<100> MessageStorage;
+ llvm::raw_svector_ostream Message(MessageStorage);
+ StringRef MacroName = getImmediateMacroName(Loc, SM, LangOpts);
+ if (MacroName.empty())
+ Message << "expanded from here";
+ else
+ Message << "expanded from macro '" << MacroName << "'";
+
+ emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
+ SpellingRanges, None, &SM);
+}
+
+/// Check that the macro argument location of Loc starts with ArgumentLoc.
+/// The starting location of the macro expansions is used to differeniate
+/// different macro expansions.
+static bool checkLocForMacroArgExpansion(SourceLocation Loc,
+ const SourceManager &SM,
+ SourceLocation ArgumentLoc) {
+ SourceLocation MacroLoc;
+ if (SM.isMacroArgExpansion(Loc, &MacroLoc)) {
+ if (ArgumentLoc == MacroLoc) return true;
+ }
+
+ return false;
+}
+
+/// Check if all the locations in the range have the same macro argument
+/// expansion, and that that expansion starts with ArgumentLoc.
+static bool checkRangeForMacroArgExpansion(CharSourceRange Range,
+ const SourceManager &SM,
+ SourceLocation ArgumentLoc) {
+ SourceLocation BegLoc = Range.getBegin(), EndLoc = Range.getEnd();
+ while (BegLoc != EndLoc) {
+ if (!checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc))
+ return false;
+ BegLoc.getLocWithOffset(1);
+ }
+
+ return checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc);
+}
+
+/// A helper function to check if the current ranges are all inside the same
+/// macro argument expansion as Loc.
+static bool checkRangesForMacroArgExpansion(SourceLocation Loc,
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager &SM) {
+ assert(Loc.isMacroID() && "Must be a macro expansion!");
+
+ SmallVector<CharSourceRange, 4> SpellingRanges;
+ mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
+
+ /// Count all valid ranges.
+ unsigned ValidCount = 0;
+ for (auto I : Ranges)
+ if (I.isValid()) ValidCount++;
+
+ if (ValidCount > SpellingRanges.size())
+ return false;
+
+ /// To store the source location of the argument location.
+ SourceLocation ArgumentLoc;
+
+ /// Set the ArgumentLoc to the beginning location of the expansion of Loc
+ /// so to check if the ranges expands to the same beginning location.
+ if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc))
+ return false;
+
+ for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) {
+ if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc))
+ return false;
+ }
+
+ return true;
+}
+
/// \brief Recursively emit notes for each macro expansion and caret
/// diagnostics where appropriate.
///
@@ -405,71 +558,68 @@ void DiagnosticRenderer::emitCaret(SourceLocation Loc,
/// \param Level The diagnostic level currently being emitted.
/// \param Ranges The underlined ranges for this code snippet.
/// \param Hints The FixIt hints active for this diagnostic.
-/// \param OnMacroInst The current depth of the macro expansion stack.
void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> Hints,
- const SourceManager &SM,
- unsigned &MacroDepth,
- unsigned OnMacroInst) {
- assert(!Loc.isInvalid() && "must have a valid source location here");
-
- // Walk up to the caller of this macro, and produce a backtrace down to there.
- SourceLocation OneLevelUp = SM.getImmediateMacroCallerLoc(Loc);
- if (OneLevelUp.isMacroID())
- emitMacroExpansions(OneLevelUp, Level, Ranges, Hints, SM,
- MacroDepth, OnMacroInst + 1);
- else
- MacroDepth = OnMacroInst + 1;
-
- unsigned MacroSkipStart = 0, MacroSkipEnd = 0;
- if (MacroDepth > DiagOpts->MacroBacktraceLimit &&
- DiagOpts->MacroBacktraceLimit != 0) {
- MacroSkipStart = DiagOpts->MacroBacktraceLimit / 2 +
- DiagOpts->MacroBacktraceLimit % 2;
- MacroSkipEnd = MacroDepth - DiagOpts->MacroBacktraceLimit / 2;
+ const SourceManager &SM) {
+ assert(Loc.isValid() && "must have a valid source location here");
+
+ // Produce a stack of macro backtraces.
+ SmallVector<SourceLocation, 8> LocationStack;
+ unsigned IgnoredEnd = 0;
+ while (Loc.isMacroID()) {
+ // If this is the expansion of a macro argument, point the caret at the
+ // use of the argument in the definition of the macro, not the expansion.
+ if (SM.isMacroArgExpansion(Loc))
+ LocationStack.push_back(SM.getImmediateExpansionRange(Loc).first);
+ else
+ LocationStack.push_back(Loc);
+
+ if (checkRangesForMacroArgExpansion(Loc, Ranges, SM))
+ IgnoredEnd = LocationStack.size();
+
+ Loc = SM.getImmediateMacroCallerLoc(Loc);
+
+ // Once the location no longer points into a macro, try stepping through
+ // the last found location. This sometimes produces additional useful
+ // backtraces.
+ if (Loc.isFileID())
+ Loc = SM.getImmediateMacroCallerLoc(LocationStack.back());
+ assert(Loc.isValid() && "must have a valid source location here");
}
- // Whether to suppress printing this macro expansion.
- bool Suppressed = (OnMacroInst >= MacroSkipStart &&
- OnMacroInst < MacroSkipEnd);
-
- if (Suppressed) {
- // Tell the user that we've skipped contexts.
- if (OnMacroInst == MacroSkipStart) {
- SmallString<200> MessageStorage;
- llvm::raw_svector_ostream Message(MessageStorage);
- Message << "(skipping " << (MacroSkipEnd - MacroSkipStart)
- << " expansions in backtrace; use -fmacro-backtrace-limit=0 to "
- "see all)";
- emitBasicNote(Message.str());
- }
+ LocationStack.erase(LocationStack.begin(),
+ LocationStack.begin() + IgnoredEnd);
+
+ unsigned MacroDepth = LocationStack.size();
+ unsigned MacroLimit = DiagOpts->MacroBacktraceLimit;
+ if (MacroDepth <= MacroLimit || MacroLimit == 0) {
+ for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
+ I != E; ++I)
+ emitSingleMacroExpansion(*I, Level, Ranges, SM);
return;
}
- // Find the spelling location for the macro definition. We must use the
- // spelling location here to avoid emitting a macro bactrace for the note.
- SourceLocation SpellingLoc = Loc;
- // If this is the expansion of a macro argument, point the caret at the
- // use of the argument in the definition of the macro, not the expansion.
- if (SM.isMacroArgExpansion(Loc))
- SpellingLoc = SM.getImmediateExpansionRange(Loc).first;
- SpellingLoc = SM.getSpellingLoc(SpellingLoc);
+ unsigned MacroStartMessages = MacroLimit / 2;
+ unsigned MacroEndMessages = MacroLimit / 2 + MacroLimit % 2;
- // Map the ranges into the FileID of the diagnostic location.
- SmallVector<CharSourceRange, 4> SpellingRanges;
- mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
+ for (auto I = LocationStack.rbegin(),
+ E = LocationStack.rbegin() + MacroStartMessages;
+ I != E; ++I)
+ emitSingleMacroExpansion(*I, Level, Ranges, SM);
- SmallString<100> MessageStorage;
+ SmallString<200> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
- StringRef MacroName = getImmediateMacroName(Loc, SM, LangOpts);
- if (MacroName.empty())
- Message << "expanded from here";
- else
- Message << "expanded from macro '" << MacroName << "'";
- emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
- SpellingRanges, None, &SM);
+ Message << "(skipping " << (MacroDepth - MacroLimit)
+ << " expansions in backtrace; use -fmacro-backtrace-limit=0 to "
+ "see all)";
+ emitBasicNote(Message.str());
+
+ for (auto I = LocationStack.rend() - MacroEndMessages,
+ E = LocationStack.rend();
+ I != E; ++I)
+ emitSingleMacroExpansion(*I, Level, Ranges, SM);
}
DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
@@ -492,8 +642,11 @@ void DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc,
// Generate a note indicating the include location.
SmallString<200> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
- Message << "in module '" << ModuleName << "' imported from "
- << PLoc.getFilename() << ':' << PLoc.getLine() << ":";
+ Message << "in module '" << ModuleName;
+ if (PLoc.isValid())
+ Message << "' imported from " << PLoc.getFilename() << ':'
+ << PLoc.getLine();
+ Message << ":";
emitNote(Loc, Message.str(), &SM);
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
index 3e0f7a1..ecef92e 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendAction.cpp
@@ -190,9 +190,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
- std::unique_ptr<ASTUnit> AST =
- ASTUnit::LoadFromASTFile(InputFile, CI.getPCHContainerReader(),
- Diags, CI.getFileSystemOpts());
+ std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
+ InputFile, CI.getPCHContainerReader(), Diags, CI.getFileSystemOpts(),
+ CI.getCodeGenOpts().DebugTypeExtRefs);
if (!AST)
goto failure;
@@ -284,7 +284,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
if (!Found) {
CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude;
- return true;
+ goto failure;
}
}
}
@@ -375,7 +375,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
if (CI.getLangOpts().Modules)
CI.createModuleManager();
- PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
+ PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(),
PP.getLangOpts());
} else {
// FIXME: If this is a problem, recover from it by creating a multiplex
@@ -442,9 +442,11 @@ bool FrontendAction::Execute() {
// there were any module-build failures.
if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() &&
CI.hasPreprocessor()) {
- GlobalModuleIndex::writeIndex(
- CI.getFileManager(), CI.getPCHContainerReader(),
- CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
+ StringRef Cache =
+ CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath();
+ if (!Cache.empty())
+ GlobalModuleIndex::writeIndex(CI.getFileManager(),
+ CI.getPCHContainerReader(), Cache);
}
return true;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
index 40277bd..407ccea 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/FrontendActions.cpp
@@ -91,12 +91,10 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
auto Buffer = std::make_shared<PCHBuffer>();
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(llvm::make_unique<PCHGenerator>(
- CI.getPreprocessor(), OutputFile, nullptr, Sysroot, Buffer));
- Consumers.push_back(
- CI.getPCHContainerWriter().CreatePCHContainerGenerator(
- CI.getDiagnostics(), CI.getHeaderSearchOpts(),
- CI.getPreprocessorOpts(), CI.getTargetOpts(), CI.getLangOpts(),
- InFile, OutputFile, OS, Buffer));
+ CI.getPreprocessor(), OutputFile, nullptr, Sysroot,
+ Buffer, CI.getFrontendOpts().ModuleFileExtensions));
+ Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
+ CI, InFile, OutputFile, OS, Buffer));
return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
}
@@ -136,13 +134,15 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
auto Buffer = std::make_shared<PCHBuffer>();
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+
Consumers.push_back(llvm::make_unique<PCHGenerator>(
- CI.getPreprocessor(), OutputFile, Module, Sysroot, Buffer));
- Consumers.push_back(
- CI.getPCHContainerWriter().CreatePCHContainerGenerator(
- CI.getDiagnostics(), CI.getHeaderSearchOpts(),
- CI.getPreprocessorOpts(), CI.getTargetOpts(), CI.getLangOpts(),
- InFile, OutputFile, OS, Buffer));
+ CI.getPreprocessor(), OutputFile, Module, Sysroot,
+ Buffer, CI.getFrontendOpts().ModuleFileExtensions,
+ /*AllowASTWithErrors=*/false,
+ /*IncludeTimestamps=*/
+ +CI.getFrontendOpts().BuildingImplicitModule));
+ Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
+ CI, InFile, OutputFile, OS, Buffer));
return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
}
@@ -187,15 +187,17 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
return std::error_code();
// Add includes for each of these headers.
- for (Module::Header &H : Module->Headers[Module::HK_Normal]) {
- Module->addTopHeader(H.Entry);
- // Use the path as specified in the module map file. We'll look for this
- // file relative to the module build directory (the directory containing
- // the module map file) so this will find the same file that we found
- // while parsing the module map.
- if (std::error_code Err = addHeaderInclude(H.NameAsWritten, Includes,
- LangOpts, Module->IsExternC))
- return Err;
+ for (auto HK : {Module::HK_Normal, Module::HK_Private}) {
+ for (Module::Header &H : Module->Headers[HK]) {
+ Module->addTopHeader(H.Entry);
+ // Use the path as specified in the module map file. We'll look for this
+ // file relative to the module build directory (the directory containing
+ // the module map file) so this will find the same file that we found
+ // while parsing the module map.
+ if (std::error_code Err = addHeaderInclude(H.NameAsWritten, Includes,
+ LangOpts, Module->IsExternC))
+ return Err;
+ }
}
// Note that Module->PrivateHeaders will not be a TopHeader.
@@ -268,14 +270,26 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
StringRef Filename) {
- // Find the module map file.
- const FileEntry *ModuleMap = CI.getFileManager().getFile(Filename);
+ // Find the module map file.
+ const FileEntry *ModuleMap =
+ CI.getFileManager().getFile(Filename, /*openFile*/true);
if (!ModuleMap) {
CI.getDiagnostics().Report(diag::err_module_map_not_found)
<< Filename;
return false;
}
+ // Set up embedding for any specified files. Do this before we load any
+ // source files, including the primary module map for the compilation.
+ for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {
+ if (const auto *FE = CI.getFileManager().getFile(F, /*openFile*/true))
+ CI.getSourceManager().setFileIsTransient(FE);
+ else
+ CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F;
+ }
+ if (CI.getFrontendOpts().ModulesEmbedAllFiles)
+ CI.getSourceManager().setAllFilesAreTransient(true);
+
// Parse the module map file.
HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
if (HS.loadModuleMapFile(ModuleMap, IsSystem))
@@ -416,6 +430,7 @@ void VerifyPCHAction::ExecuteAction() {
const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
std::unique_ptr<ASTReader> Reader(new ASTReader(
CI.getPreprocessor(), CI.getASTContext(), CI.getPCHContainerReader(),
+ CI.getFrontendOpts().ModuleFileExtensions,
Sysroot.empty() ? "" : Sysroot.c_str(),
/*DisableValidation*/ false,
/*AllowPCHWithCompilerErrors*/ false,
@@ -559,6 +574,20 @@ namespace {
}
return false;
}
+
+ /// Indicates that a particular module file extension has been read.
+ void readModuleFileExtension(
+ const ModuleFileExtensionMetadata &Metadata) override {
+ Out.indent(2) << "Module file extension '"
+ << Metadata.BlockName << "' " << Metadata.MajorVersion
+ << "." << Metadata.MinorVersion;
+ if (!Metadata.UserInfo.empty()) {
+ Out << ": ";
+ Out.write_escaped(Metadata.UserInfo);
+ }
+
+ Out << "\n";
+ }
#undef DUMP_BOOLEAN
};
}
@@ -578,7 +607,8 @@ void DumpModuleInfoAction::ExecuteAction() {
DumpModuleInfoListener Listener(Out);
ASTReader::readASTFileControlBlock(
getCurrentFile(), getCompilerInstance().getFileManager(),
- getCompilerInstance().getPCHContainerReader(), Listener);
+ getCompilerInstance().getPCHContainerReader(),
+ /*FindModuleFileExtensions=*/true, Listener);
}
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp b/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp
index 5732e5b..0bc1169 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/HeaderIncludeGen.cpp
@@ -46,7 +46,36 @@ public:
};
}
-void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders,
+static void PrintHeaderInfo(raw_ostream *OutputFile, const char* Filename,
+ bool ShowDepth, unsigned CurrentIncludeDepth,
+ bool MSStyle) {
+ // Write to a temporary string to avoid unnecessary flushing on errs().
+ SmallString<512> Pathname(Filename);
+ if (!MSStyle)
+ Lexer::Stringify(Pathname);
+
+ SmallString<256> Msg;
+ if (MSStyle)
+ Msg += "Note: including file:";
+
+ if (ShowDepth) {
+ // The main source file is at depth 1, so skip one dot.
+ for (unsigned i = 1; i != CurrentIncludeDepth; ++i)
+ Msg += MSStyle ? ' ' : '.';
+
+ if (!MSStyle)
+ Msg += ' ';
+ }
+ Msg += Pathname;
+ Msg += '\n';
+
+ OutputFile->write(Msg.data(), Msg.size());
+ OutputFile->flush();
+}
+
+void clang::AttachHeaderIncludeGen(Preprocessor &PP,
+ const std::vector<std::string> &ExtraHeaders,
+ bool ShowAllHeaders,
StringRef OutputPath, bool ShowDepth,
bool MSStyle) {
raw_ostream *OutputFile = MSStyle ? &llvm::outs() : &llvm::errs();
@@ -63,12 +92,19 @@ void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders,
delete OS;
} else {
OS->SetUnbuffered();
- OS->SetUseAtomicWrites(true);
OutputFile = OS;
OwnsOutputFile = true;
}
}
+ // Print header info for extra headers, pretending they were discovered
+ // by the regular preprocessor. The primary use case is to support
+ // proper generation of Make / Ninja file dependencies for implicit includes,
+ // such as sanitizer blacklists. It's only important for cl.exe
+ // compatibility, the GNU way to generate rules is -M / -MM / -MD / -MMD.
+ for (auto Header : ExtraHeaders) {
+ PrintHeaderInfo(OutputFile, Header.c_str(), ShowDepth, 2, MSStyle);
+ }
PP.addPPCallbacks(llvm::make_unique<HeaderIncludesCallback>(&PP,
ShowAllHeaders,
OutputFile,
@@ -112,27 +148,7 @@ void HeaderIncludesCallback::FileChanged(SourceLocation Loc,
// Dump the header include information we are past the predefines buffer or
// are showing all headers.
if (ShowHeader && Reason == PPCallbacks::EnterFile) {
- // Write to a temporary string to avoid unnecessary flushing on errs().
- SmallString<512> Filename(UserLoc.getFilename());
- if (!MSStyle)
- Lexer::Stringify(Filename);
-
- SmallString<256> Msg;
- if (MSStyle)
- Msg += "Note: including file:";
-
- if (ShowDepth) {
- // The main source file is at depth 1, so skip one dot.
- for (unsigned i = 1; i != CurrentIncludeDepth; ++i)
- Msg += MSStyle ? ' ' : '.';
-
- if (!MSStyle)
- Msg += ' ';
- }
- Msg += Filename;
- Msg += '\n';
-
- OutputFile->write(Msg.data(), Msg.size());
- OutputFile->flush();
+ PrintHeaderInfo(OutputFile, UserLoc.getFilename(),
+ ShowDepth, CurrentIncludeDepth, MSStyle);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
index e3a17c9..26bab0d 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
@@ -15,6 +15,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Config/config.h" // C_INCLUDE_DIRS
+#include "clang/Lex/HeaderMap.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -215,6 +216,8 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
case llvm::Triple::OpenBSD:
case llvm::Triple::Bitrig:
case llvm::Triple::NaCl:
+ case llvm::Triple::PS4:
+ case llvm::Triple::ELFIAMCU:
break;
case llvm::Triple::Win32:
if (triple.getEnvironment() != llvm::Triple::Cygnus)
@@ -246,10 +249,8 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
if (CIncludeDirs != "") {
SmallVector<StringRef, 5> dirs;
CIncludeDirs.split(dirs, ":");
- for (SmallVectorImpl<StringRef>::iterator i = dirs.begin();
- i != dirs.end();
- ++i)
- AddPath(*i, ExternCSystem, false);
+ for (StringRef dir : dirs)
+ AddPath(dir, ExternCSystem, false);
return;
}
@@ -319,7 +320,30 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
case llvm::Triple::CloudABI:
case llvm::Triple::RTEMS:
case llvm::Triple::NaCl:
+ case llvm::Triple::ELFIAMCU:
break;
+ case llvm::Triple::PS4: {
+ // <isysroot> gets prepended later in AddPath().
+ std::string BaseSDKPath = "";
+ if (!HasSysroot) {
+ const char *envValue = getenv("SCE_PS4_SDK_DIR");
+ if (envValue)
+ BaseSDKPath = envValue;
+ else {
+ // HSOpts.ResourceDir variable contains the location of Clang's
+ // resource files.
+ // Assuming that Clang is configured for PS4 without
+ // --with-clang-resource-dir option, the location of Clang's resource
+ // files is <SDK_DIR>/host_tools/lib/clang
+ SmallString<128> P = StringRef(HSOpts.ResourceDir);
+ llvm::sys::path::append(P, "../../..");
+ BaseSDKPath = P.str();
+ }
+ }
+ AddPath(BaseSDKPath + "/target/include", System, false);
+ if (triple.isPS4CPU())
+ AddPath(BaseSDKPath + "/target/include_common", System, false);
+ }
default:
AddPath("/usr/include", ExternCSystem, false);
break;
@@ -387,10 +411,7 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOp
}
break;
case llvm::Triple::DragonFly:
- if (llvm::sys::fs::exists("/usr/lib/gcc47"))
- AddPath("/usr/include/c++/4.7", CXXSystem, false);
- else
- AddPath("/usr/include/c++/4.4", CXXSystem, false);
+ AddPath("/usr/include/c++/5.0", CXXSystem, false);
break;
case llvm::Triple::OpenBSD: {
std::string t = triple.getTriple();
@@ -404,10 +425,6 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOp
AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3",
"", "", "", triple);
break;
- case llvm::Triple::Solaris:
- AddGnuCPlusPlusIncludePaths("/usr/gcc/4.5/include/c++/4.5.2/",
- "i386-pc-solaris2.11", "", "", triple);
- break;
default:
break;
}
@@ -453,11 +470,6 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
AddUnmappedPath(P, CXXSystem, false);
}
}
- // On Solaris, include the support directory for things like xlocale and
- // fudged system headers.
- if (triple.getOS() == llvm::Triple::Solaris)
- AddPath("/usr/include/c++/v1/support/solaris", CXXSystem, false);
-
AddPath("/usr/include/c++/v1", CXXSystem, false);
} else {
AddDefaultCPlusPlusIncludePaths(triple, HSOpts);
@@ -568,39 +580,33 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) {
SearchList.reserve(IncludePath.size());
// Quoted arguments go first.
- for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
- it != ie; ++it) {
- if (it->first == Quoted)
- SearchList.push_back(it->second);
- }
+ for (auto &Include : IncludePath)
+ if (Include.first == Quoted)
+ SearchList.push_back(Include.second);
+
// Deduplicate and remember index.
RemoveDuplicates(SearchList, 0, Verbose);
unsigned NumQuoted = SearchList.size();
- for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
- it != ie; ++it) {
- if (it->first == Angled || it->first == IndexHeaderMap)
- SearchList.push_back(it->second);
- }
+ for (auto &Include : IncludePath)
+ if (Include.first == Angled || Include.first == IndexHeaderMap)
+ SearchList.push_back(Include.second);
RemoveDuplicates(SearchList, NumQuoted, Verbose);
unsigned NumAngled = SearchList.size();
- for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
- it != ie; ++it) {
- if (it->first == System || it->first == ExternCSystem ||
- (!Lang.ObjC1 && !Lang.CPlusPlus && it->first == CSystem) ||
- (/*FIXME !Lang.ObjC1 && */Lang.CPlusPlus && it->first == CXXSystem) ||
- (Lang.ObjC1 && !Lang.CPlusPlus && it->first == ObjCSystem) ||
- (Lang.ObjC1 && Lang.CPlusPlus && it->first == ObjCXXSystem))
- SearchList.push_back(it->second);
- }
-
- for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
- it != ie; ++it) {
- if (it->first == After)
- SearchList.push_back(it->second);
- }
+ for (auto &Include : IncludePath)
+ if (Include.first == System || Include.first == ExternCSystem ||
+ (!Lang.ObjC1 && !Lang.CPlusPlus && Include.first == CSystem) ||
+ (/*FIXME !Lang.ObjC1 && */ Lang.CPlusPlus &&
+ Include.first == CXXSystem) ||
+ (Lang.ObjC1 && !Lang.CPlusPlus && Include.first == ObjCSystem) ||
+ (Lang.ObjC1 && Lang.CPlusPlus && Include.first == ObjCXXSystem))
+ SearchList.push_back(Include.second);
+
+ for (auto &Include : IncludePath)
+ if (Include.first == After)
+ SearchList.push_back(Include.second);
// Remove duplicates across both the Angled and System directories. GCC does
// this and failing to remove duplicates across these two groups breaks
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
index 0791494..15aa546 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
@@ -20,6 +20,7 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Serialization/ASTReader.h"
@@ -323,15 +324,17 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
Out << "template<typename _Tp> struct __is_scalar;\n"
<< "\n";
+
+ if (LangOpts.ObjCAutoRefCount) {
+ Out << "template<typename _Tp>\n"
+ << "struct __is_scalar<__attribute__((objc_ownership(strong))) _Tp> {\n"
+ << " enum { __value = 0 };\n"
+ << " typedef __false_type __type;\n"
+ << "};\n"
+ << "\n";
+ }
- Out << "template<typename _Tp>\n"
- << "struct __is_scalar<__attribute__((objc_ownership(strong))) _Tp> {\n"
- << " enum { __value = 0 };\n"
- << " typedef __false_type __type;\n"
- << "};\n"
- << "\n";
-
- if (LangOpts.ObjCARCWeak) {
+ if (LangOpts.ObjCWeak) {
Out << "template<typename _Tp>\n"
<< "struct __is_scalar<__attribute__((objc_ownership(weak))) _Tp> {\n"
<< " enum { __value = 0 };\n"
@@ -340,13 +343,15 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
<< "\n";
}
- Out << "template<typename _Tp>\n"
- << "struct __is_scalar<__attribute__((objc_ownership(autoreleasing)))"
- << " _Tp> {\n"
- << " enum { __value = 0 };\n"
- << " typedef __false_type __type;\n"
- << "};\n"
- << "\n";
+ if (LangOpts.ObjCAutoRefCount) {
+ Out << "template<typename _Tp>\n"
+ << "struct __is_scalar<__attribute__((objc_ownership(autoreleasing)))"
+ << " _Tp> {\n"
+ << " enum { __value = 0 };\n"
+ << " typedef __false_type __type;\n"
+ << "};\n"
+ << "\n";
+ }
Out << "}\n";
}
@@ -406,6 +411,8 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
// Not "standard" per se, but available even with the -undef flag.
if (LangOpts.AsmPreprocessor)
Builder.defineMacro("__ASSEMBLER__");
+ if (LangOpts.CUDA)
+ Builder.defineMacro("__CUDA__");
}
/// Initialize the predefined C++ language feature test macros defined in
@@ -456,6 +463,8 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_sized_deallocation", "201309");
if (LangOpts.ConceptsTS)
Builder.defineMacro("__cpp_experimental_concepts", "1");
+ if (LangOpts.Coroutines)
+ Builder.defineMacro("__cpp_coroutines", "1");
}
static void InitializePredefinedMacros(const TargetInfo &TI,
@@ -849,9 +858,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
Builder.defineMacro("__SSP_ALL__", "3");
- if (FEOpts.ProgramAction == frontend::RewriteObjC)
- Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
-
// Define a macro that exists only when using the static analyzer.
if (FEOpts.ProgramAction == frontend::RunAnalysis)
Builder.defineMacro("__clang_analyzer__");
@@ -859,7 +865,13 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (LangOpts.FastRelaxedMath)
Builder.defineMacro("__FAST_RELAXED_MATH__");
- if (LangOpts.ObjCAutoRefCount) {
+ if (FEOpts.ProgramAction == frontend::RewriteObjC ||
+ LangOpts.getGC() != LangOptions::NonGC) {
+ Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
+ Builder.defineMacro("__strong", "__attribute__((objc_gc(strong)))");
+ Builder.defineMacro("__autoreleasing", "");
+ Builder.defineMacro("__unsafe_unretained", "");
+ } else if (LangOpts.ObjC1) {
Builder.defineMacro("__weak", "__attribute__((objc_ownership(weak)))");
Builder.defineMacro("__strong", "__attribute__((objc_ownership(strong)))");
Builder.defineMacro("__autoreleasing",
@@ -918,14 +930,19 @@ void clang::InitializePreprocessor(
// Install things like __POWERPC__, __GNUC__, etc into the macro table.
if (InitOpts.UsePredefines) {
+ if (LangOpts.CUDA && PP.getAuxTargetInfo())
+ InitializePredefinedMacros(*PP.getAuxTargetInfo(), LangOpts, FEOpts,
+ Builder);
+
InitializePredefinedMacros(PP.getTargetInfo(), LangOpts, FEOpts, Builder);
// Install definitions to make Objective-C++ ARC work well with various
// C++ Standard Library implementations.
- if (LangOpts.ObjC1 && LangOpts.CPlusPlus && LangOpts.ObjCAutoRefCount) {
+ if (LangOpts.ObjC1 && LangOpts.CPlusPlus &&
+ (LangOpts.ObjCAutoRefCount || LangOpts.ObjCWeak)) {
switch (InitOpts.ObjCXXARCStandardLibrary) {
case ARCXX_nolib:
- case ARCXX_libcxx:
+ case ARCXX_libcxx:
break;
case ARCXX_libstdcxx:
diff --git a/contrib/llvm/tools/clang/lib/Frontend/LogDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/LogDiagnosticPrinter.cpp
index c6a18e0..9998f65 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/LogDiagnosticPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/LogDiagnosticPrinter.cpp
@@ -118,7 +118,7 @@ void LogDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
if (MainFilename.empty() && Info.hasSourceManager()) {
const SourceManager &SM = Info.getSourceManager();
FileID FID = SM.getMainFileID();
- if (!FID.isInvalid()) {
+ if (FID.isValid()) {
const FileEntry *FE = SM.getFileEntryForID(FID);
if (FE && FE->isValid())
MainFilename = FE->getName();
@@ -147,7 +147,7 @@ void LogDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
if (PLoc.isInvalid()) {
// At least print the file name if available:
FileID FID = SM.getFileID(Info.getLocation());
- if (!FID.isInvalid()) {
+ if (FID.isValid()) {
const FileEntry *FE = SM.getFileEntryForID(FID);
if (FE && FE->isValid())
DE.Filename = FE->getName();
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp b/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp
index 67852dc..9768a16 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ModuleDependencyCollector.cpp
@@ -32,8 +32,8 @@ public:
: Collector(Collector) {}
bool needsInputFileVisitation() override { return true; }
bool needsSystemInputFileVisitation() override { return true; }
- bool visitInputFile(StringRef Filename, bool IsSystem,
- bool IsOverridden) override;
+ bool visitInputFile(StringRef Filename, bool IsSystem, bool IsOverridden,
+ bool IsExplicitModule) override;
};
}
@@ -67,7 +67,7 @@ std::error_code ModuleDependencyListener::copyToRoot(StringRef Src) {
path::native(AbsoluteSrc);
// TODO: We probably need to handle .. as well as . in order to have valid
// input to the YAMLVFSWriter.
- FileManager::removeDotPaths(AbsoluteSrc);
+ path::remove_dots(AbsoluteSrc);
// Build the destination path.
SmallString<256> Dest = Collector.getDest();
@@ -85,7 +85,8 @@ std::error_code ModuleDependencyListener::copyToRoot(StringRef Src) {
}
bool ModuleDependencyListener::visitInputFile(StringRef Filename, bool IsSystem,
- bool IsOverridden) {
+ bool IsOverridden,
+ bool IsExplicitModule) {
if (Collector.insertSeen(Filename))
if (copyToRoot(Filename))
Collector.setHasErrors();
diff --git a/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
index 91ee100..f8b73e9 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/MultiplexConsumer.cpp
@@ -119,12 +119,10 @@ public:
const FunctionDecl *Delete) override;
void CompletedImplicitDefinition(const FunctionDecl *D) override;
void StaticDataMemberInstantiated(const VarDecl *D) override;
+ void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) override;
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
- void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
- const ObjCPropertyDecl *OrigProp,
- const ObjCCategoryDecl *ClassExt) override;
void DeclarationMarkedUsed(const Decl *D) override;
void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
@@ -196,6 +194,11 @@ void MultiplexASTMutationListener::StaticDataMemberInstantiated(
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->StaticDataMemberInstantiated(D);
}
+void MultiplexASTMutationListener::DefaultArgumentInstantiated(
+ const ParmVarDecl *D) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->DefaultArgumentInstantiated(D);
+}
void MultiplexASTMutationListener::AddedObjCCategoryToInterface(
const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {
@@ -207,13 +210,6 @@ void MultiplexASTMutationListener::FunctionDefinitionInstantiated(
for (auto &Listener : Listeners)
Listener->FunctionDefinitionInstantiated(D);
}
-void MultiplexASTMutationListener::AddedObjCPropertyInClassExtension(
- const ObjCPropertyDecl *Prop,
- const ObjCPropertyDecl *OrigProp,
- const ObjCCategoryDecl *ClassExt) {
- for (size_t i = 0, e = Listeners.size(); i != e; ++i)
- Listeners[i]->AddedObjCPropertyInClassExtension(Prop, OrigProp, ClassExt);
-}
void MultiplexASTMutationListener::DeclarationMarkedUsed(const Decl *D) {
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->DeclarationMarkedUsed(D);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp b/contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp
index cde3ba1..5e1d772 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/PCHContainerOperations.cpp
@@ -16,6 +16,7 @@
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/raw_ostream.h"
#include "clang/Lex/ModuleLoader.h"
+
using namespace clang;
namespace {
@@ -26,17 +27,11 @@ class RawPCHContainerGenerator : public ASTConsumer {
raw_pwrite_stream *OS;
public:
- RawPCHContainerGenerator(DiagnosticsEngine &Diags,
- const HeaderSearchOptions &HSO,
- const PreprocessorOptions &PPO,
- const TargetOptions &TO, const LangOptions &LO,
- const std::string &MainFileName,
- const std::string &OutputFileName,
- llvm::raw_pwrite_stream *OS,
+ RawPCHContainerGenerator(llvm::raw_pwrite_stream *OS,
std::shared_ptr<PCHBuffer> Buffer)
: Buffer(Buffer), OS(OS) {}
- virtual ~RawPCHContainerGenerator() {}
+ ~RawPCHContainerGenerator() override = default;
void HandleTranslationUnit(ASTContext &Ctx) override {
if (Buffer->IsComplete) {
@@ -49,16 +44,14 @@ public:
Buffer->Data = std::move(Empty);
}
};
-}
+
+} // anonymous namespace
std::unique_ptr<ASTConsumer> RawPCHContainerWriter::CreatePCHContainerGenerator(
- DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO,
- const PreprocessorOptions &PPO, const TargetOptions &TO,
- const LangOptions &LO, const std::string &MainFileName,
+ CompilerInstance &CI, const std::string &MainFileName,
const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
std::shared_ptr<PCHBuffer> Buffer) const {
- return llvm::make_unique<RawPCHContainerGenerator>(
- Diags, HSO, PPO, TO, LO, MainFileName, OutputFileName, OS, Buffer);
+ return llvm::make_unique<RawPCHContainerGenerator>(OS, Buffer);
}
void RawPCHContainerReader::ExtractPCH(
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
index dbc661b..8cf8adf 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -78,7 +78,7 @@ public:
std::string RewriteFilename(const std::string &Filename, int &fd) override {
SmallString<128> Path;
llvm::sys::fs::createTemporaryFile(llvm::sys::path::filename(Filename),
- llvm::sys::path::extension(Filename), fd,
+ llvm::sys::path::extension(Filename).drop_front(), fd,
Path);
return Path.str();
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
index 08d6cf1..ca82262 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -160,7 +160,7 @@ void InclusionRewriter::FileChanged(SourceLocation Loc,
void InclusionRewriter::FileSkipped(const FileEntry &/*SkippedFile*/,
const Token &/*FilenameTok*/,
SrcMgr::CharacteristicKind /*FileType*/) {
- assert(!LastInclusionLocation.isInvalid() &&
+ assert(LastInclusionLocation.isValid() &&
"A file, that wasn't found via an inclusion directive, was skipped");
LastInclusionLocation = SourceLocation();
}
@@ -389,9 +389,10 @@ bool InclusionRewriter::HandleHasInclude(
SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 1>
Includers;
Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
+ // FIXME: Why don't we call PP.LookupFile here?
const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
Filename, SourceLocation(), isAngled, nullptr, CurDir, Includers, nullptr,
- nullptr, nullptr, false);
+ nullptr, nullptr, nullptr, false);
FileExists = File != nullptr;
return true;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 2902ba7..be68d42 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -412,7 +412,7 @@ namespace {
// Misc. AST transformation routines. Sometimes they end up calling
// rewriting routines on the new ASTs.
CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
- Expr **args, unsigned nargs,
+ ArrayRef<Expr *> Args,
SourceLocation StartLoc=SourceLocation(),
SourceLocation EndLoc=SourceLocation());
@@ -2105,15 +2105,17 @@ Stmt *RewriteModernObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
SmallVector<Expr*, 8> SelExprs;
SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
- &SelExprs[0], SelExprs.size());
+ SelExprs);
ReplaceStmt(Exp, SelExp);
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
return SelExp;
}
-CallExpr *RewriteModernObjC::SynthesizeCallToFunctionDecl(
- FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc,
- SourceLocation EndLoc) {
+CallExpr *
+RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
+ ArrayRef<Expr *> Args,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
// Get the type, we will need to reference it in a couple spots.
QualType msgSendType = FD->getType();
@@ -2129,10 +2131,9 @@ CallExpr *RewriteModernObjC::SynthesizeCallToFunctionDecl(
const FunctionType *FT = msgSendType->getAs<FunctionType>();
- CallExpr *Exp =
- new (Context) CallExpr(*Context, ICE, llvm::makeArrayRef(args, nargs),
- FT->getCallResultType(*Context),
- VK_RValue, EndLoc);
+ CallExpr *Exp = new (Context) CallExpr(*Context, ICE, Args,
+ FT->getCallResultType(*Context),
+ VK_RValue, EndLoc);
return Exp;
}
@@ -2660,9 +2661,7 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
IdentifierInfo *clsName = BoxingClass->getIdentifier();
ClsExprs.push_back(getStringLiteral(clsName->getName()));
- CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
- &ClsExprs[0],
- ClsExprs.size(),
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
MsgExprs.push_back(Cls);
@@ -2672,8 +2671,7 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
SelExprs.push_back(
getStringLiteral(BoxingMethod->getSelector().getAsString()));
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
- &SelExprs[0], SelExprs.size(),
- StartLoc, EndLoc);
+ SelExprs, StartLoc, EndLoc);
MsgExprs.push_back(SelExp);
// User provided sub-expression is the 3rd, and last, argument.
@@ -2788,9 +2786,7 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
IdentifierInfo *clsName = Class->getIdentifier();
ClsExprs.push_back(getStringLiteral(clsName->getName()));
- CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
- &ClsExprs[0],
- ClsExprs.size(),
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
MsgExprs.push_back(Cls);
@@ -2801,8 +2797,7 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
SelExprs.push_back(
getStringLiteral(ArrayMethod->getSelector().getAsString()));
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
- &SelExprs[0], SelExprs.size(),
- StartLoc, EndLoc);
+ SelExprs, StartLoc, EndLoc);
MsgExprs.push_back(SelExp);
// (const id [])objects
@@ -2939,9 +2934,7 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
IdentifierInfo *clsName = Class->getIdentifier();
ClsExprs.push_back(getStringLiteral(clsName->getName()));
- CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
- &ClsExprs[0],
- ClsExprs.size(),
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
MsgExprs.push_back(Cls);
@@ -2951,8 +2944,7 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
ObjCMethodDecl *DictMethod = Exp->getDictWithObjectsMethod();
SelExprs.push_back(getStringLiteral(DictMethod->getSelector().getAsString()));
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
- &SelExprs[0], SelExprs.size(),
- StartLoc, EndLoc);
+ SelExprs, StartLoc, EndLoc);
MsgExprs.push_back(SelExp);
// (const id [])objects
@@ -3298,14 +3290,10 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
// (Class)objc_getClass("CurrentClass")
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
- &ClsExprs[0],
- ClsExprs.size(),
- StartLoc,
- EndLoc);
+ ClsExprs, StartLoc, EndLoc);
ClsExprs.clear();
ClsExprs.push_back(Cls);
- Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
- &ClsExprs[0], ClsExprs.size(),
+ Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
@@ -3366,9 +3354,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
= Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
IdentifierInfo *clsName = Class->getIdentifier();
ClsExprs.push_back(getStringLiteral(clsName->getName()));
- CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
- &ClsExprs[0],
- ClsExprs.size(),
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
Context->getObjCIdType(),
@@ -3398,14 +3384,11 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SmallVector<Expr*, 8> ClsExprs;
ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
// (Class)objc_getClass("CurrentClass")
- CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
- &ClsExprs[0],
- ClsExprs.size(),
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
ClsExprs.clear();
ClsExprs.push_back(Cls);
- Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
- &ClsExprs[0], ClsExprs.size(),
+ Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
@@ -3476,9 +3459,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SmallVector<Expr*, 8> SelExprs;
SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
- &SelExprs[0], SelExprs.size(),
- StartLoc,
- EndLoc);
+ SelExprs, StartLoc, EndLoc);
MsgExprs.push_back(SelExp);
// Now push any user supplied arguments.
@@ -4862,7 +4843,7 @@ void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) {
std::string Str = "(";
Str += TypeString;
Str += ")";
- InsertText(IC->getSubExpr()->getLocStart(), &Str[0], Str.size());
+ InsertText(IC->getSubExpr()->getLocStart(), Str);
return;
}
@@ -5641,7 +5622,7 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
// FIXME: Missing definition of
// InsertText(clang::SourceLocation, char const*, unsigned int).
- // InsertText(startLoc, messString.c_str(), messString.size());
+ // InsertText(startLoc, messString);
// Tried this, but it didn't work either...
// ReplaceText(startLoc, 0, messString.c_str(), messString.size());
#endif
@@ -5767,7 +5748,7 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
const std::string &Str = Buf.str();
printf("CAST = %s\n", &Str[0]);
- InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
+ InsertText(ICE->getSubExpr()->getLocStart(), Str);
delete S;
return Replacement;
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
index 204820b..e0ddadb 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -346,7 +346,7 @@ namespace {
// Misc. AST transformation routines. Sometimes they end up calling
// rewriting routines on the new ASTs.
CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
- Expr **args, unsigned nargs,
+ ArrayRef<Expr *> Args,
SourceLocation StartLoc=SourceLocation(),
SourceLocation EndLoc=SourceLocation());
CallExpr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
@@ -1997,15 +1997,17 @@ Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
SmallVector<Expr*, 8> SelExprs;
SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
- &SelExprs[0], SelExprs.size());
+ SelExprs);
ReplaceStmt(Exp, SelExp);
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
return SelExp;
}
-CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl(
- FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc,
- SourceLocation EndLoc) {
+CallExpr *
+RewriteObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
+ ArrayRef<Expr *> Args,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
// Get the type, we will need to reference it in a couple spots.
QualType msgSendType = FD->getType();
@@ -2021,10 +2023,9 @@ CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl(
const FunctionType *FT = msgSendType->getAs<FunctionType>();
- CallExpr *Exp =
- new (Context) CallExpr(*Context, ICE, llvm::makeArrayRef(args, nargs),
- FT->getCallResultType(*Context),
- VK_RValue, EndLoc);
+ CallExpr *Exp = new (Context) CallExpr(*Context, ICE, Args,
+ FT->getCallResultType(*Context),
+ VK_RValue, EndLoc);
return Exp;
}
@@ -2680,20 +2681,15 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SmallVector<Expr*, 8> ClsExprs;
ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
- &ClsExprs[0],
- ClsExprs.size(),
- StartLoc,
- EndLoc);
+ ClsExprs, StartLoc, EndLoc);
// (Class)objc_getClass("CurrentClass")
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
Context->getObjCClassType(),
CK_BitCast, Cls);
ClsExprs.clear();
ClsExprs.push_back(ArgExpr);
- Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
- &ClsExprs[0], ClsExprs.size(),
+ Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
-
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
// To turn off a warning, type-cast to 'id'
InitExprs.push_back( // set 'super class', using class_getSuperclass().
@@ -2752,9 +2748,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
= Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
IdentifierInfo *clsName = Class->getIdentifier();
ClsExprs.push_back(getStringLiteral(clsName->getName()));
- CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
- &ClsExprs[0],
- ClsExprs.size(),
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
MsgExprs.push_back(Cls);
break;
@@ -2780,9 +2774,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
SmallVector<Expr*, 8> ClsExprs;
ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
- CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
- &ClsExprs[0],
- ClsExprs.size(),
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
// (Class)objc_getClass("CurrentClass")
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
@@ -2790,8 +2782,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
CK_BitCast, Cls);
ClsExprs.clear();
ClsExprs.push_back(ArgExpr);
- Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
- &ClsExprs[0], ClsExprs.size(),
+ Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
StartLoc, EndLoc);
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
@@ -2862,9 +2853,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SmallVector<Expr*, 8> SelExprs;
SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
- &SelExprs[0], SelExprs.size(),
- StartLoc,
- EndLoc);
+ SelExprs, StartLoc, EndLoc);
MsgExprs.push_back(SelExp);
// Now push any user supplied arguments.
@@ -4675,7 +4664,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
// FIXME: Missing definition of
// InsertText(clang::SourceLocation, char const*, unsigned int).
- // InsertText(startLoc, messString.c_str(), messString.size());
+ // InsertText(startLoc, messString);
// Tried this, but it didn't work either...
// ReplaceText(startLoc, 0, messString.c_str(), messString.size());
#endif
@@ -4790,7 +4779,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
const std::string &Str = Buf.str();
printf("CAST = %s\n", &Str[0]);
- InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
+ InsertText(ICE->getSubExpr()->getLocStart(), Str);
delete S;
return Replacement;
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
index d31b12e..1bf10d2 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -51,6 +51,7 @@ public:
typedef SmallVector<uint64_t, 64> RecordData;
typedef SmallVectorImpl<uint64_t> RecordDataImpl;
+typedef ArrayRef<uint64_t> RecordDataRef;
class SDiagsWriter;
@@ -393,13 +394,9 @@ unsigned SDiagsWriter::getEmitFile(const char *FileName){
// Lazily generate the record for the file.
entry = State->Files.size();
- RecordData Record;
- Record.push_back(RECORD_FILENAME);
- Record.push_back(entry);
- Record.push_back(0); // For legacy.
- Record.push_back(0); // For legacy.
StringRef Name(FileName);
- Record.push_back(Name.size());
+ RecordData::value_type Record[] = {RECORD_FILENAME, entry, 0 /* For legacy */,
+ 0 /* For legacy */, Name.size()};
State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_FILENAME), Record,
Name);
@@ -478,7 +475,7 @@ void SDiagsWriter::EmitBlockInfoBlock() {
AddSourceLocationAbbrev(Abbrev);
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category.
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // Text size.
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text.
Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
@@ -531,14 +528,11 @@ void SDiagsWriter::EmitBlockInfoBlock() {
void SDiagsWriter::EmitMetaBlock() {
llvm::BitstreamWriter &Stream = State->Stream;
- RecordData &Record = State->Record;
AbbreviationMap &Abbrevs = State->Abbrevs;
Stream.EnterSubblock(BLOCK_META, 3);
- Record.clear();
- Record.push_back(RECORD_VERSION);
- Record.push_back(VersionNumber);
- Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record);
+ RecordData::value_type Record[] = {RECORD_VERSION, VersionNumber};
+ Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record);
Stream.ExitBlock();
}
@@ -548,11 +542,8 @@ unsigned SDiagsWriter::getEmitCategory(unsigned int category) {
// We use a local version of 'Record' so that we can be generating
// another record when we lazily generate one for the category entry.
- RecordData Record;
- Record.push_back(RECORD_CATEGORY);
- Record.push_back(category);
StringRef catName = DiagnosticIDs::getCategoryNameFromID(category);
- Record.push_back(catName.size());
+ RecordData::value_type Record[] = {RECORD_CATEGORY, category, catName.size()};
State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_CATEGORY), Record,
catName);
@@ -581,10 +572,8 @@ unsigned SDiagsWriter::getEmitDiagnosticFlag(StringRef FlagName) {
entry.second = FlagName;
// Lazily emit the string in a separate record.
- RecordData Record;
- Record.push_back(RECORD_DIAG_FLAG);
- Record.push_back(entry.first);
- Record.push_back(FlagName.size());
+ RecordData::value_type Record[] = {RECORD_DIAG_FLAG, entry.first,
+ FlagName.size()};
State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_DIAG_FLAG),
Record, FlagName);
}
@@ -844,17 +833,9 @@ std::error_code SDiagsMerger::visitEndOfDiagnostic() {
std::error_code
SDiagsMerger::visitSourceRangeRecord(const serialized_diags::Location &Start,
const serialized_diags::Location &End) {
- RecordData Record;
- Record.push_back(RECORD_SOURCE_RANGE);
- Record.push_back(FileLookup[Start.FileID]);
- Record.push_back(Start.Line);
- Record.push_back(Start.Col);
- Record.push_back(Start.Offset);
- Record.push_back(FileLookup[End.FileID]);
- Record.push_back(End.Line);
- Record.push_back(End.Col);
- Record.push_back(End.Offset);
-
+ RecordData::value_type Record[] = {
+ RECORD_SOURCE_RANGE, FileLookup[Start.FileID], Start.Line, Start.Col,
+ Start.Offset, FileLookup[End.FileID], End.Line, End.Col, End.Offset};
Writer.State->Stream.EmitRecordWithAbbrev(
Writer.State->Abbrevs.get(RECORD_SOURCE_RANGE), Record);
return std::error_code();
@@ -863,19 +844,13 @@ SDiagsMerger::visitSourceRangeRecord(const serialized_diags::Location &Start,
std::error_code SDiagsMerger::visitDiagnosticRecord(
unsigned Severity, const serialized_diags::Location &Location,
unsigned Category, unsigned Flag, StringRef Message) {
- RecordData MergedRecord;
- MergedRecord.push_back(RECORD_DIAG);
- MergedRecord.push_back(Severity);
- MergedRecord.push_back(FileLookup[Location.FileID]);
- MergedRecord.push_back(Location.Line);
- MergedRecord.push_back(Location.Col);
- MergedRecord.push_back(Location.Offset);
- MergedRecord.push_back(CategoryLookup[Category]);
- MergedRecord.push_back(Flag ? DiagFlagLookup[Flag] : 0);
- MergedRecord.push_back(Message.size());
+ RecordData::value_type Record[] = {
+ RECORD_DIAG, Severity, FileLookup[Location.FileID], Location.Line,
+ Location.Col, Location.Offset, CategoryLookup[Category],
+ Flag ? DiagFlagLookup[Flag] : 0, Message.size()};
Writer.State->Stream.EmitRecordWithBlob(
- Writer.State->Abbrevs.get(RECORD_DIAG), MergedRecord, Message);
+ Writer.State->Abbrevs.get(RECORD_DIAG), Record, Message);
return std::error_code();
}
@@ -883,17 +858,10 @@ std::error_code
SDiagsMerger::visitFixitRecord(const serialized_diags::Location &Start,
const serialized_diags::Location &End,
StringRef Text) {
- RecordData Record;
- Record.push_back(RECORD_FIXIT);
- Record.push_back(FileLookup[Start.FileID]);
- Record.push_back(Start.Line);
- Record.push_back(Start.Col);
- Record.push_back(Start.Offset);
- Record.push_back(FileLookup[End.FileID]);
- Record.push_back(End.Line);
- Record.push_back(End.Col);
- Record.push_back(End.Offset);
- Record.push_back(Text.size());
+ RecordData::value_type Record[] = {RECORD_FIXIT, FileLookup[Start.FileID],
+ Start.Line, Start.Col, Start.Offset,
+ FileLookup[End.FileID], End.Line, End.Col,
+ End.Offset, Text.size()};
Writer.State->Stream.EmitRecordWithBlob(
Writer.State->Abbrevs.get(RECORD_FIXIT), Record, Text);
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp b/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp
new file mode 100644
index 0000000..d1b20c4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp
@@ -0,0 +1,123 @@
+//===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "TestModuleFileExtension.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Serialization/ASTReader.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdio>
+using namespace clang;
+using namespace clang::serialization;
+
+TestModuleFileExtension::Writer::~Writer() { }
+
+void TestModuleFileExtension::Writer::writeExtensionContents(
+ Sema &SemaRef,
+ llvm::BitstreamWriter &Stream) {
+ using namespace llvm;
+
+ // Write an abbreviation for this record.
+ BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev();
+ Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // message
+ auto Abbrev = Stream.EmitAbbrev(Abv);
+
+ // Write a message into the extension block.
+ SmallString<64> Message;
+ {
+ auto Ext = static_cast<TestModuleFileExtension *>(getExtension());
+ raw_svector_ostream OS(Message);
+ OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "."
+ << Ext->MinorVersion;
+ }
+ SmallVector<uint64_t, 4> Record;
+ Record.push_back(FIRST_EXTENSION_RECORD_ID);
+ Record.push_back(Message.size());
+ Stream.EmitRecordWithBlob(Abbrev, Record, Message);
+}
+
+TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
+ const llvm::BitstreamCursor &InStream)
+ : ModuleFileExtensionReader(Ext), Stream(InStream)
+{
+ // Read the extension block.
+ SmallVector<uint64_t, 4> Record;
+ while (true) {
+ llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ switch (Entry.Kind) {
+ case llvm::BitstreamEntry::SubBlock:
+ case llvm::BitstreamEntry::EndBlock:
+ case llvm::BitstreamEntry::Error:
+ return;
+
+ case llvm::BitstreamEntry::Record:
+ break;
+ }
+
+ Record.clear();
+ StringRef Blob;
+ unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
+ switch (RecCode) {
+ case FIRST_EXTENSION_RECORD_ID: {
+ StringRef Message = Blob.substr(0, Record[0]);
+ fprintf(stderr, "Read extension block message: %s\n",
+ Message.str().c_str());
+ break;
+ }
+ }
+ }
+}
+
+TestModuleFileExtension::Reader::~Reader() { }
+
+TestModuleFileExtension::~TestModuleFileExtension() { }
+
+ModuleFileExtensionMetadata
+TestModuleFileExtension::getExtensionMetadata() const {
+ return { BlockName, MajorVersion, MinorVersion, UserInfo };
+}
+
+llvm::hash_code TestModuleFileExtension::hashExtension(
+ llvm::hash_code Code) const {
+ if (Hashed) {
+ Code = llvm::hash_combine(Code, BlockName);
+ Code = llvm::hash_combine(Code, MajorVersion);
+ Code = llvm::hash_combine(Code, MinorVersion);
+ Code = llvm::hash_combine(Code, UserInfo);
+ }
+
+ return Code;
+}
+
+std::unique_ptr<ModuleFileExtensionWriter>
+TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
+ return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
+}
+
+std::unique_ptr<ModuleFileExtensionReader>
+TestModuleFileExtension::createExtensionReader(
+ const ModuleFileExtensionMetadata &Metadata,
+ ASTReader &Reader, serialization::ModuleFile &Mod,
+ const llvm::BitstreamCursor &Stream)
+{
+ assert(Metadata.BlockName == BlockName && "Wrong block name");
+ if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) !=
+ std::make_pair(MajorVersion, MinorVersion)) {
+ Reader.getDiags().Report(Mod.ImportLoc,
+ diag::err_test_module_file_extension_version)
+ << BlockName << Metadata.MajorVersion << Metadata.MinorVersion
+ << MajorVersion << MinorVersion;
+ return nullptr;
+ }
+
+ return std::unique_ptr<ModuleFileExtensionReader>(
+ new TestModuleFileExtension::Reader(this, Stream));
+}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.h b/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.h
new file mode 100644
index 0000000..41f3ca9
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.h
@@ -0,0 +1,72 @@
+//===-- TestModuleFileExtension.h - Module Extension Tester -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_TESTMODULEFILEEXTENSION_H
+#define LLVM_CLANG_FRONTEND_TESTMODULEFILEEXTENSION_H
+
+#include "clang/Serialization/ModuleFileExtension.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include <string>
+
+namespace clang {
+
+/// A module file extension used for testing purposes.
+class TestModuleFileExtension : public ModuleFileExtension {
+ std::string BlockName;
+ unsigned MajorVersion;
+ unsigned MinorVersion;
+ bool Hashed;
+ std::string UserInfo;
+
+ class Writer : public ModuleFileExtensionWriter {
+ public:
+ Writer(ModuleFileExtension *Ext) : ModuleFileExtensionWriter(Ext) { }
+ ~Writer() override;
+
+ void writeExtensionContents(Sema &SemaRef,
+ llvm::BitstreamWriter &Stream) override;
+ };
+
+ class Reader : public ModuleFileExtensionReader {
+ llvm::BitstreamCursor Stream;
+
+ public:
+ ~Reader() override;
+
+ Reader(ModuleFileExtension *Ext, const llvm::BitstreamCursor &InStream);
+ };
+
+public:
+ TestModuleFileExtension(StringRef BlockName,
+ unsigned MajorVersion,
+ unsigned MinorVersion,
+ bool Hashed,
+ StringRef UserInfo)
+ : BlockName(BlockName),
+ MajorVersion(MajorVersion), MinorVersion(MinorVersion),
+ Hashed(Hashed), UserInfo(UserInfo) { }
+ ~TestModuleFileExtension() override;
+
+ ModuleFileExtensionMetadata getExtensionMetadata() const override;
+
+ llvm::hash_code hashExtension(llvm::hash_code Code) const override;
+
+ std::unique_ptr<ModuleFileExtensionWriter>
+ createExtensionWriter(ASTWriter &Writer) override;
+
+ std::unique_ptr<ModuleFileExtensionReader>
+ createExtensionReader(const ModuleFileExtensionMetadata &Metadata,
+ ASTReader &Reader, serialization::ModuleFile &Mod,
+ const llvm::BitstreamCursor &Stream) override;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_FRONTEND_TESTMODULEFILEEXTENSION_H
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp
index aaf17a9..d4e156d 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnostic.cpp
@@ -777,7 +777,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
if (PLoc.isInvalid()) {
// At least print the file name if available:
FileID FID = SM.getFileID(Loc);
- if (!FID.isInvalid()) {
+ if (FID.isValid()) {
const FileEntry* FE = SM.getFileEntryForID(FID);
if (FE && FE->isValid()) {
OS << FE->getName();
@@ -875,7 +875,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
PresumedLoc PLoc,
const SourceManager &SM) {
- if (DiagOpts->ShowLocation)
+ if (DiagOpts->ShowLocation && PLoc.getFilename())
OS << "In file included from " << PLoc.getFilename() << ':'
<< PLoc.getLine() << ":\n";
else
@@ -885,11 +885,11 @@ void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
void TextDiagnostic::emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
StringRef ModuleName,
const SourceManager &SM) {
- if (DiagOpts->ShowLocation)
+ if (DiagOpts->ShowLocation && PLoc.getFilename())
OS << "In module '" << ModuleName << "' imported from "
<< PLoc.getFilename() << ':' << PLoc.getLine() << ":\n";
else
- OS << "In module " << ModuleName << "':\n";
+ OS << "In module '" << ModuleName << "':\n";
}
void TextDiagnostic::emitBuildingModuleLocation(SourceLocation Loc,
@@ -1060,7 +1060,7 @@ void TextDiagnostic::emitSnippetAndCaret(
SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints,
const SourceManager &SM) {
- assert(!Loc.isInvalid() && "must have a valid source location here");
+ assert(Loc.isValid() && "must have a valid source location here");
assert(Loc.isFileID() && "must have a file location here");
// If caret diagnostics are enabled and we have location, we want to
diff --git a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 55df936..7331d77 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -186,9 +186,7 @@ public:
Regex(RegexStr) { }
bool isValid(std::string &Error) override {
- if (Regex.isValid(Error))
- return true;
- return false;
+ return Regex.isValid(Error);
}
bool match(StringRef S) override {
diff --git a/contrib/llvm/tools/clang/lib/Headers/Intrin.h b/contrib/llvm/tools/clang/lib/Headers/Intrin.h
index 24b3eae..6c1d0d1 100644
--- a/contrib/llvm/tools/clang/lib/Headers/Intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/Intrin.h
@@ -49,10 +49,7 @@ extern "C" {
#if defined(__MMX__)
/* And the random ones that aren't in those files. */
__m64 _m_from_float(float);
-__m64 _m_from_int(int _l);
-void _m_prefetch(void *);
float _m_to_float(__m64);
-int _m_to_int(__m64 _M);
#endif
/* Other assorted instruction intrinsics. */
@@ -292,9 +289,6 @@ void _xend(void);
static __inline__
#define _XCR_XFEATURE_ENABLED_MASK 0
unsigned __int64 __cdecl _xgetbv(unsigned int);
-void __cdecl _xrstor(void const *, unsigned __int64);
-void __cdecl _xsave(void *, unsigned __int64);
-void __cdecl _xsaveopt(void *, unsigned __int64);
void __cdecl _xsetbv(unsigned int, unsigned __int64);
/* These additional intrinsics are turned on in x64/amd64/x86_64 mode. */
@@ -434,13 +428,21 @@ __umulh(unsigned __int64 _Multiplier, unsigned __int64 _Multiplicand) {
(unsigned __int128)_Multiplier * (unsigned __int128)_Multiplicand;
return _FullProduct >> 64;
}
-void __cdecl _xrstor64(void const *, unsigned __int64);
-void __cdecl _xsave64(void *, unsigned __int64);
-void __cdecl _xsaveopt64(void *, unsigned __int64);
#endif /* __x86_64__ */
/*----------------------------------------------------------------------------*\
+|* Multiplication
+\*----------------------------------------------------------------------------*/
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+__emul(int __in1, int __in2) {
+ return (__int64)__in1 * (__int64)__in2;
+}
+static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
+__emulu(unsigned int __in1, unsigned int __in2) {
+ return (unsigned __int64)__in1 * (unsigned __int64)__in2;
+}
+/*----------------------------------------------------------------------------*\
|* Bit Twiddling
\*----------------------------------------------------------------------------*/
static __inline__ unsigned char __DEFAULT_FN_ATTRS
@@ -770,27 +772,25 @@ _InterlockedCompareExchange64(__int64 volatile *_Destination,
/*----------------------------------------------------------------------------*\
|* Barriers
\*----------------------------------------------------------------------------*/
-#if defined(__i386__) || defined(__x86_64__)
static __inline__ void __DEFAULT_FN_ATTRS
__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
_ReadWriteBarrier(void) {
- __asm__ volatile ("" : : : "memory");
+ __atomic_signal_fence(__ATOMIC_SEQ_CST);
}
static __inline__ void __DEFAULT_FN_ATTRS
__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
_ReadBarrier(void) {
- __asm__ volatile ("" : : : "memory");
+ __atomic_signal_fence(__ATOMIC_SEQ_CST);
}
static __inline__ void __DEFAULT_FN_ATTRS
__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
_WriteBarrier(void) {
- __asm__ volatile ("" : : : "memory");
+ __atomic_signal_fence(__ATOMIC_SEQ_CST);
}
-#endif
#ifdef __x86_64__
static __inline__ void __DEFAULT_FN_ATTRS
__faststorefence(void) {
- __asm__ volatile("lock orq $0, (%%rsp)" : : : "memory");
+ __atomic_thread_fence(__ATOMIC_SEQ_CST);
}
#endif
/*----------------------------------------------------------------------------*\
@@ -851,7 +851,7 @@ __movsd(unsigned long *__dst, unsigned long const *__src, size_t __n) {
}
static __inline__ void __DEFAULT_FN_ATTRS
__movsw(unsigned short *__dst, unsigned short const *__src, size_t __n) {
- __asm__("rep movsh" : : "D"(__dst), "S"(__src), "c"(__n)
+ __asm__("rep movsw" : : "D"(__dst), "S"(__src), "c"(__n)
: "%edi", "%esi", "%ecx");
}
static __inline__ void __DEFAULT_FN_ATTRS
@@ -866,7 +866,7 @@ __stosd(unsigned long *__dst, unsigned long __x, size_t __n) {
}
static __inline__ void __DEFAULT_FN_ATTRS
__stosw(unsigned short *__dst, unsigned short __x, size_t __n) {
- __asm__("rep stosh" : : "D"(__dst), "a"(__x), "c"(__n)
+ __asm__("rep stosw" : : "D"(__dst), "a"(__x), "c"(__n)
: "%edi", "%ecx");
}
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_runtime_wrapper.h b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_runtime_wrapper.h
new file mode 100644
index 0000000..8e5f033
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/__clang_cuda_runtime_wrapper.h
@@ -0,0 +1,216 @@
+/*===---- __clang_cuda_runtime_wrapper.h - CUDA runtime support -------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+/*
+ * WARNING: This header is intended to be directly -include'd by
+ * the compiler and is not supposed to be included by users.
+ *
+ * CUDA headers are implemented in a way that currently makes it
+ * impossible for user code to #include directly when compiling with
+ * Clang. They present different view of CUDA-supplied functions
+ * depending on where in NVCC's compilation pipeline the headers are
+ * included. Neither of these modes provides function definitions with
+ * correct attributes, so we use preprocessor to force the headers
+ * into a form that Clang can use.
+ *
+ * Similarly to NVCC which -include's cuda_runtime.h, Clang -include's
+ * this file during every CUDA compilation.
+ */
+
+#ifndef __CLANG_CUDA_RUNTIME_WRAPPER_H__
+#define __CLANG_CUDA_RUNTIME_WRAPPER_H__
+
+#if defined(__CUDA__) && defined(__clang__)
+
+// Include some standard headers to avoid CUDA headers including them
+// while some required macros (like __THROW) are in a weird state.
+#include <stdlib.h>
+#include <cmath>
+
+// Preserve common macros that will be changed below by us or by CUDA
+// headers.
+#pragma push_macro("__THROW")
+#pragma push_macro("__CUDA_ARCH__")
+
+// WARNING: Preprocessor hacks below are based on specific details of
+// CUDA-7.x headers and are not expected to work with any other
+// version of CUDA headers.
+#include "cuda.h"
+#if !defined(CUDA_VERSION)
+#error "cuda.h did not define CUDA_VERSION"
+#elif CUDA_VERSION < 7000 || CUDA_VERSION > 7050
+#error "Unsupported CUDA version!"
+#endif
+
+// Make largest subset of device functions available during host
+// compilation -- SM_35 for the time being.
+#ifndef __CUDA_ARCH__
+#define __CUDA_ARCH__ 350
+#endif
+
+#include "cuda_builtin_vars.h"
+
+// No need for device_launch_parameters.h as cuda_builtin_vars.h above
+// has taken care of builtin variables declared in the file.
+#define __DEVICE_LAUNCH_PARAMETERS_H__
+
+// {math,device}_functions.h only have declarations of the
+// functions. We don't need them as we're going to pull in their
+// definitions from .hpp files.
+#define __DEVICE_FUNCTIONS_H__
+#define __MATH_FUNCTIONS_H__
+
+#undef __CUDACC__
+#define __CUDABE__
+// Disables definitions of device-side runtime support stubs in
+// cuda_device_runtime_api.h
+#define __CUDADEVRT_INTERNAL__
+#include "host_config.h"
+#include "host_defines.h"
+#include "driver_types.h"
+#include "common_functions.h"
+#undef __CUDADEVRT_INTERNAL__
+
+#undef __CUDABE__
+#define __CUDACC__
+#include "cuda_runtime.h"
+
+#undef __CUDACC__
+#define __CUDABE__
+
+// CUDA headers use __nvvm_memcpy and __nvvm_memset which Clang does
+// not have at the moment. Emulate them with a builtin memcpy/memset.
+#define __nvvm_memcpy(s,d,n,a) __builtin_memcpy(s,d,n)
+#define __nvvm_memset(d,c,n,a) __builtin_memset(d,c,n)
+
+#include "crt/host_runtime.h"
+#include "crt/device_runtime.h"
+// device_runtime.h defines __cxa_* macros that will conflict with
+// cxxabi.h.
+// FIXME: redefine these as __device__ functions.
+#undef __cxa_vec_ctor
+#undef __cxa_vec_cctor
+#undef __cxa_vec_dtor
+#undef __cxa_vec_new2
+#undef __cxa_vec_new3
+#undef __cxa_vec_delete2
+#undef __cxa_vec_delete
+#undef __cxa_vec_delete3
+#undef __cxa_pure_virtual
+
+// We need decls for functions in CUDA's libdevice with __device__
+// attribute only. Alas they come either as __host__ __device__ or
+// with no attributes at all. To work around that, define __CUDA_RTC__
+// which produces HD variant and undef __host__ which gives us desided
+// decls with __device__ attribute.
+#pragma push_macro("__host__")
+#define __host__
+#define __CUDACC_RTC__
+#include "device_functions_decls.h"
+#undef __CUDACC_RTC__
+
+// Temporarily poison __host__ macro to ensure it's not used by any of
+// the headers we're about to include.
+#define __host__ UNEXPECTED_HOST_ATTRIBUTE
+
+// device_functions.hpp and math_functions*.hpp use 'static
+// __forceinline__' (with no __device__) for definitions of device
+// functions. Temporarily redefine __forceinline__ to include
+// __device__.
+#pragma push_macro("__forceinline__")
+#define __forceinline__ __device__ __inline__ __attribute__((always_inline))
+#include "device_functions.hpp"
+#include "math_functions.hpp"
+#include "math_functions_dbl_ptx3.hpp"
+#pragma pop_macro("__forceinline__")
+
+// Pull in host-only functions that are only available when neither
+// __CUDACC__ nor __CUDABE__ are defined.
+#undef __MATH_FUNCTIONS_HPP__
+#undef __CUDABE__
+#include "math_functions.hpp"
+// Alas, additional overloads for these functions are hard to get to.
+// Considering that we only need these overloads for a few functions,
+// we can provide them here.
+static inline float rsqrt(float a) { return rsqrtf(a); }
+static inline float rcbrt(float a) { return rcbrtf(a); }
+static inline float sinpi(float a) { return sinpif(a); }
+static inline float cospi(float a) { return cospif(a); }
+static inline void sincospi(float a, float *b, float *c) {
+ return sincospi(a, b, c);
+}
+static inline float erfcinv(float a) { return erfcinvf(a); }
+static inline float normcdfinv(float a) { return normcdfinvf(a); }
+static inline float normcdf(float a) { return normcdff(a); }
+static inline float erfcx(float a) { return erfcxf(a); }
+
+// For some reason single-argument variant is not always declared by
+// CUDA headers. Alas, device_functions.hpp included below needs it.
+static inline __device__ void __brkpt(int c) { __brkpt(); }
+
+// Now include *.hpp with definitions of various GPU functions. Alas,
+// a lot of thins get declared/defined with __host__ attribute which
+// we don't want and we have to define it out. We also have to include
+// {device,math}_functions.hpp again in order to extract the other
+// branch of #if/else inside.
+
+#define __host__
+#undef __CUDABE__
+#define __CUDACC__
+#undef __DEVICE_FUNCTIONS_HPP__
+#include "device_functions.hpp"
+#include "device_atomic_functions.hpp"
+#include "sm_20_atomic_functions.hpp"
+#include "sm_32_atomic_functions.hpp"
+#include "sm_20_intrinsics.hpp"
+// sm_30_intrinsics.h has declarations that use default argument, so
+// we have to include it and it will in turn include .hpp
+#include "sm_30_intrinsics.h"
+#include "sm_32_intrinsics.hpp"
+#undef __MATH_FUNCTIONS_HPP__
+#include "math_functions.hpp"
+#pragma pop_macro("__host__")
+
+#include "texture_indirect_functions.h"
+
+// Restore state of __CUDA_ARCH__ and __THROW we had on entry.
+#pragma pop_macro("__CUDA_ARCH__")
+#pragma pop_macro("__THROW")
+
+// Set up compiler macros expected to be seen during compilation.
+#undef __CUDABE__
+#define __CUDACC__
+#define __NVCC__
+
+#if defined(__CUDA_ARCH__)
+// We need to emit IR declaration for non-existing __nvvm_reflect() to
+// let backend know that it should be treated as const nothrow
+// function which is what NVVMReflect pass expects to see.
+extern "C" __device__ __attribute__((const)) int __nvvm_reflect(const void *);
+static __device__ __attribute__((used)) int __nvvm_reflect_anchor() {
+ return __nvvm_reflect("NONE");
+}
+#endif
+
+#endif // __CUDA__
+#endif // __CLANG_CUDA_RUNTIME_WRAPPER_H__
diff --git a/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h b/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h
index 9f594ee..100799e 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_aes.h
@@ -25,12 +25,8 @@
#include <emmintrin.h>
-#if !defined (__AES__)
-# error "AES instructions not enabled"
-#else
-
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("aes")))
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_aesenc_si128(__m128i __V, __m128i __R)
@@ -63,10 +59,8 @@ _mm_aesimc_si128(__m128i __V)
}
#define _mm_aeskeygenassist_si128(C, R) \
- __builtin_ia32_aeskeygenassist128((C), (R))
+ (__m128i)__builtin_ia32_aeskeygenassist128((__v2di)(__m128i)(C), (int)(R))
#undef __DEFAULT_FN_ATTRS
-#endif
-
#endif /* _WMMINTRIN_AES_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_pclmul.h b/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_pclmul.h
index 8d1f1b7..68e944e 100644
--- a/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_pclmul.h
+++ b/contrib/llvm/tools/clang/lib/Headers/__wmmintrin_pclmul.h
@@ -1,4 +1,4 @@
-/*===---- __wmmintrin_pclmul.h - AES intrinsics ----------------------------===
+/*===---- __wmmintrin_pclmul.h - PCMUL intrinsics ---------------------------===
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,12 +23,8 @@
#ifndef _WMMINTRIN_PCLMUL_H
#define _WMMINTRIN_PCLMUL_H
-#if !defined (__PCLMUL__)
-# error "PCLMUL instruction is not enabled"
-#else
#define _mm_clmulepi64_si128(__X, __Y, __I) \
((__m128i)__builtin_ia32_pclmulqdq128((__v2di)(__m128i)(__X), \
(__v2di)(__m128i)(__Y), (char)(__I)))
-#endif
#endif /* _WMMINTRIN_PCLMUL_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/adxintrin.h b/contrib/llvm/tools/clang/lib/Headers/adxintrin.h
index b8eb9cb..ee34728 100644
--- a/contrib/llvm/tools/clang/lib/Headers/adxintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/adxintrin.h
@@ -32,8 +32,7 @@
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
/* Intrinsics that are available only if __ADX__ defined */
-#ifdef __ADX__
-static __inline unsigned char __DEFAULT_FN_ATTRS
+static __inline unsigned char __attribute__((__always_inline__, __nodebug__, __target__("adx")))
_addcarryx_u32(unsigned char __cf, unsigned int __x, unsigned int __y,
unsigned int *__p)
{
@@ -41,14 +40,13 @@ _addcarryx_u32(unsigned char __cf, unsigned int __x, unsigned int __y,
}
#ifdef __x86_64__
-static __inline unsigned char __DEFAULT_FN_ATTRS
+static __inline unsigned char __attribute__((__always_inline__, __nodebug__, __target__("adx")))
_addcarryx_u64(unsigned char __cf, unsigned long long __x,
unsigned long long __y, unsigned long long *__p)
{
return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p);
}
#endif
-#endif
/* Intrinsics that are also available if __ADX__ undefined */
static __inline unsigned char __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/altivec.h b/contrib/llvm/tools/clang/lib/Headers/altivec.h
index 5c8eb56..a5b4f74 100644
--- a/contrib/llvm/tools/clang/lib/Headers/altivec.h
+++ b/contrib/llvm/tools/clang/lib/Headers/altivec.h
@@ -27,7 +27,7 @@
#error "AltiVec support not enabled"
#endif
-/* constants for mapping CR6 bits to predicate result. */
+/* Constants for mapping CR6 bits to predicate result. */
#define __CR6_EQ 0
#define __CR6_EQ_REV 1
@@ -137,7 +137,7 @@ static vector double __ATTRS_o_ai vec_abs(vector double __a) {
}
#endif
-/* vec_abss */
+/* vec_abss */
#define __builtin_altivec_abss_v16qi vec_abss
#define __builtin_altivec_abss_v8hi vec_abss
#define __builtin_altivec_abss_v4si vec_abss
@@ -278,6 +278,38 @@ vec_add(vector double __a, vector double __b) {
}
#endif // __VSX__
+/* vec_adde */
+
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static vector signed __int128 __ATTRS_o_ai
+vec_adde(vector signed __int128 __a, vector signed __int128 __b,
+ vector signed __int128 __c) {
+ return __builtin_altivec_vaddeuqm(__a, __b, __c);
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_adde(vector unsigned __int128 __a, vector unsigned __int128 __b,
+ vector unsigned __int128 __c) {
+ return __builtin_altivec_vaddeuqm(__a, __b, __c);
+}
+#endif
+
+/* vec_addec */
+
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static vector signed __int128 __ATTRS_o_ai
+vec_addec(vector signed __int128 __a, vector signed __int128 __b,
+ vector signed __int128 __c) {
+ return __builtin_altivec_vaddecuq(__a, __b, __c);
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_addec(vector unsigned __int128 __a, vector unsigned __int128 __b,
+ vector unsigned __int128 __c) {
+ return __builtin_altivec_vaddecuq(__a, __b, __c);
+}
+#endif
+
/* vec_vaddubm */
#define __builtin_altivec_vaddubm vec_vaddubm
@@ -390,6 +422,12 @@ vec_vaddfp(vector float __a, vector float __b) {
/* vec_addc */
+static vector signed int __ATTRS_o_ai vec_addc(vector signed int __a,
+ vector signed int __b) {
+ return (vector signed int)__builtin_altivec_vaddcuw((vector unsigned int)__a,
+ (vector unsigned int)__b);
+}
+
static vector unsigned int __ATTRS_o_ai vec_addc(vector unsigned int __a,
vector unsigned int __b) {
return __builtin_altivec_vaddcuw(__a, __b);
@@ -398,7 +436,9 @@ static vector unsigned int __ATTRS_o_ai vec_addc(vector unsigned int __a,
#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
static vector signed __int128 __ATTRS_o_ai
vec_addc(vector signed __int128 __a, vector signed __int128 __b) {
- return __builtin_altivec_vaddcuq(__a, __b);
+ return (vector signed __int128)__builtin_altivec_vaddcuq(
+ (vector unsigned __int128)__a,
+ (vector unsigned __int128)__b);
}
static vector unsigned __int128 __ATTRS_o_ai
@@ -1512,48 +1552,6 @@ vec_cmpeq(vector double __a, vector double __b) {
}
#endif
-/* vec_cmpge */
-
-static vector bool int __ATTRS_o_ai
-vec_cmpge(vector float __a, vector float __b) {
-#ifdef __VSX__
- return (vector bool int)__builtin_vsx_xvcmpgesp(__a, __b);
-#else
- return (vector bool int)__builtin_altivec_vcmpgefp(__a, __b);
-#endif
-}
-
-#ifdef __VSX__
-static vector bool long long __ATTRS_o_ai
-vec_cmpge(vector double __a, vector double __b) {
- return (vector bool long long)__builtin_vsx_xvcmpgedp(__a, __b);
-}
-#endif
-
-#ifdef __POWER8_VECTOR__
-/* Forwrad declarations as the functions are used here */
-static vector bool long long __ATTRS_o_ai
-vec_cmpgt(vector unsigned long long __a, vector unsigned long long __b);
-static vector bool long long __ATTRS_o_ai
-vec_cmpgt(vector signed long long __a, vector signed long long __b);
-
-static vector bool long long __ATTRS_o_ai
-vec_cmpge(vector signed long long __a, vector signed long long __b) {
- return ~(vec_cmpgt(__b, __a));
-}
-
-static vector bool long long __ATTRS_o_ai
-vec_cmpge(vector unsigned long long __a, vector unsigned long long __b) {
- return ~(vec_cmpgt(__b, __a));
-}
-#endif
-
-/* vec_vcmpgefp */
-
-static vector bool int __attribute__((__always_inline__))
-vec_vcmpgefp(vector float __a, vector float __b) {
- return (vector bool int)__builtin_altivec_vcmpgefp(__a, __b);
-}
/* vec_cmpgt */
@@ -1613,6 +1611,74 @@ vec_cmpgt(vector double __a, vector double __b) {
return (vector bool long long)__builtin_vsx_xvcmpgtdp(__a, __b);
}
#endif
+
+/* vec_cmpge */
+
+static vector bool char __ATTRS_o_ai
+vec_cmpge (vector signed char __a, vector signed char __b) {
+ return ~(vec_cmpgt(__b, __a));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_cmpge (vector unsigned char __a, vector unsigned char __b) {
+ return ~(vec_cmpgt(__b, __a));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_cmpge (vector signed short __a, vector signed short __b) {
+ return ~(vec_cmpgt(__b, __a));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_cmpge (vector unsigned short __a, vector unsigned short __b) {
+ return ~(vec_cmpgt(__b, __a));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmpge (vector signed int __a, vector signed int __b) {
+ return ~(vec_cmpgt(__b, __a));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmpge (vector unsigned int __a, vector unsigned int __b) {
+ return ~(vec_cmpgt(__b, __a));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmpge(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return (vector bool int)__builtin_vsx_xvcmpgesp(__a, __b);
+#else
+ return (vector bool int)__builtin_altivec_vcmpgefp(__a, __b);
+#endif
+}
+
+#ifdef __VSX__
+static vector bool long long __ATTRS_o_ai
+vec_cmpge(vector double __a, vector double __b) {
+ return (vector bool long long)__builtin_vsx_xvcmpgedp(__a, __b);
+}
+#endif
+
+#ifdef __POWER8_VECTOR__
+static vector bool long long __ATTRS_o_ai
+vec_cmpge(vector signed long long __a, vector signed long long __b) {
+ return ~(vec_cmpgt(__b, __a));
+}
+
+static vector bool long long __ATTRS_o_ai
+vec_cmpge(vector unsigned long long __a, vector unsigned long long __b) {
+ return ~(vec_cmpgt(__b, __a));
+}
+#endif
+
+/* vec_vcmpgefp */
+
+static vector bool int __attribute__((__always_inline__))
+vec_vcmpgefp(vector float __a, vector float __b) {
+ return (vector bool int)__builtin_altivec_vcmpgefp(__a, __b);
+}
+
/* vec_vcmpgtsb */
static vector bool char __attribute__((__always_inline__))
@@ -1664,6 +1730,36 @@ vec_vcmpgtfp(vector float __a, vector float __b) {
/* vec_cmple */
+static vector bool char __ATTRS_o_ai
+vec_cmple (vector signed char __a, vector signed char __b) {
+ return vec_cmpge(__b, __a);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_cmple (vector unsigned char __a, vector unsigned char __b) {
+ return vec_cmpge(__b, __a);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_cmple (vector signed short __a, vector signed short __b) {
+ return vec_cmpge(__b, __a);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_cmple (vector unsigned short __a, vector unsigned short __b) {
+ return vec_cmpge(__b, __a);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmple (vector signed int __a, vector signed int __b) {
+ return vec_cmpge(__b, __a);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_cmple (vector unsigned int __a, vector unsigned int __b) {
+ return vec_cmpge(__b, __a);
+}
+
static vector bool int __ATTRS_o_ai
vec_cmple(vector float __a, vector float __b) {
return vec_cmpge(__b, __a);
@@ -1795,6 +1891,22 @@ static vector float __ATTRS_o_ai vec_ctf(vector unsigned int __a, int __b) {
return __builtin_altivec_vcfux((vector int)__a, __b);
}
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_ctf(vector unsigned long long __a,
+ int __b) {
+ vector double __ret = __builtin_convertvector(__a, vector double);
+ __ret *= (vector double)(vector unsigned long long)((0x3ffULL - __b) << 52);
+ return __ret;
+}
+
+static vector double __ATTRS_o_ai vec_ctf(vector signed long long __a,
+ int __b) {
+ vector double __ret = __builtin_convertvector(__a, vector double);
+ __ret *= (vector double)(vector unsigned long long)((0x3ffULL - __b) << 52);
+ return __ret;
+}
+#endif
+
/* vec_vcfsx */
static vector float __attribute__((__always_inline__))
@@ -1811,11 +1923,18 @@ vec_vcfux(vector unsigned int __a, int __b) {
/* vec_cts */
-static vector int __attribute__((__always_inline__))
-vec_cts(vector float __a, int __b) {
+static vector int __ATTRS_o_ai vec_cts(vector float __a, int __b) {
return __builtin_altivec_vctsxs(__a, __b);
}
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai vec_cts(vector double __a,
+ int __b) {
+ __a *= (vector double)(vector unsigned long long)((0x3ffULL + __b) << 52);
+ return __builtin_convertvector(__a, vector signed long long);
+}
+#endif
+
/* vec_vctsxs */
static vector int __attribute__((__always_inline__))
@@ -1825,11 +1944,18 @@ vec_vctsxs(vector float __a, int __b) {
/* vec_ctu */
-static vector unsigned int __attribute__((__always_inline__))
-vec_ctu(vector float __a, int __b) {
+static vector unsigned int __ATTRS_o_ai vec_ctu(vector float __a, int __b) {
return __builtin_altivec_vctuxs(__a, __b);
}
+#ifdef __VSX__
+static vector unsigned long long __ATTRS_o_ai vec_ctu(vector double __a,
+ int __b) {
+ __a *= (vector double)(vector unsigned long long)((0x3ffULL + __b) << 52);
+ return __builtin_convertvector(__a, vector unsigned long long);
+}
+#endif
+
/* vec_vctuxs */
static vector unsigned int __attribute__((__always_inline__))
@@ -1837,6 +1963,20 @@ vec_vctuxs(vector float __a, int __b) {
return __builtin_altivec_vctuxs(__a, __b);
}
+/* vec_double */
+
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_double (vector signed long long __a) {
+ vector double __ret = { __a[0], __a[1] };
+ return __ret;
+}
+
+static vector double __ATTRS_o_ai vec_double (vector unsigned long long __a) {
+ vector double __ret = { __a[0], __a[1] };
+ return __ret;
+}
+#endif
+
/* vec_div */
/* Integer vector divides (vectors are scalarized, elements divided
@@ -1942,34 +2082,16 @@ static vector signed char __ATTRS_o_ai vec_eqv(vector signed char __a,
(vector unsigned int)__b);
}
-static vector signed char __ATTRS_o_ai vec_eqv(vector bool char __a,
- vector signed char __b) {
- return (vector signed char)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
-static vector signed char __ATTRS_o_ai vec_eqv(vector signed char __a,
- vector bool char __b) {
- return (vector signed char)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
static vector unsigned char __ATTRS_o_ai vec_eqv(vector unsigned char __a,
vector unsigned char __b) {
return (vector unsigned char)__builtin_vsx_xxleqv((vector unsigned int)__a,
(vector unsigned int)__b);
}
-static vector unsigned char __ATTRS_o_ai vec_eqv(vector bool char __a,
- vector unsigned char __b) {
- return (vector unsigned char)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
-static vector unsigned char __ATTRS_o_ai vec_eqv(vector unsigned char __a,
- vector bool char __b) {
- return (vector unsigned char)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
+static vector bool char __ATTRS_o_ai vec_eqv(vector bool char __a,
+ vector bool char __b) {
+ return (vector bool char)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
}
static vector signed short __ATTRS_o_ai vec_eqv(vector signed short __a,
@@ -1978,70 +2100,33 @@ static vector signed short __ATTRS_o_ai vec_eqv(vector signed short __a,
(vector unsigned int)__b);
}
-static vector signed short __ATTRS_o_ai vec_eqv(vector bool short __a,
- vector signed short __b) {
- return (vector signed short)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
-static vector signed short __ATTRS_o_ai vec_eqv(vector signed short __a,
- vector bool short __b) {
- return (vector signed short)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
static vector unsigned short __ATTRS_o_ai vec_eqv(vector unsigned short __a,
vector unsigned short __b) {
return (vector unsigned short)__builtin_vsx_xxleqv((vector unsigned int)__a,
(vector unsigned int)__b);
}
-static vector unsigned short __ATTRS_o_ai vec_eqv(vector bool short __a,
- vector unsigned short __b) {
- return (vector unsigned short)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
-static vector unsigned short __ATTRS_o_ai vec_eqv(vector unsigned short __a,
- vector bool short __b) {
- return (vector unsigned short)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
-static vector signed int __ATTRS_o_ai vec_eqv(vector signed int __a,
- vector signed int __b) {
- return (vector signed int)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
-static vector signed int __ATTRS_o_ai vec_eqv(vector bool int __a,
- vector signed int __b) {
- return (vector signed int)__builtin_vsx_xxleqv((vector unsigned int)__a,
+static vector bool short __ATTRS_o_ai vec_eqv(vector bool short __a,
+ vector bool short __b) {
+ return (vector bool short)__builtin_vsx_xxleqv((vector unsigned int)__a,
(vector unsigned int)__b);
}
static vector signed int __ATTRS_o_ai vec_eqv(vector signed int __a,
- vector bool int __b) {
+ vector signed int __b) {
return (vector signed int)__builtin_vsx_xxleqv((vector unsigned int)__a,
(vector unsigned int)__b);
}
static vector unsigned int __ATTRS_o_ai vec_eqv(vector unsigned int __a,
vector unsigned int __b) {
- return __builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
-static vector unsigned int __ATTRS_o_ai vec_eqv(vector bool int __a,
- vector unsigned int __b) {
- return __builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
+ return __builtin_vsx_xxleqv(__a, __b);
}
-static vector unsigned int __ATTRS_o_ai vec_eqv(vector unsigned int __a,
- vector bool int __b) {
- return __builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
+static vector bool int __ATTRS_o_ai vec_eqv(vector bool int __a,
+ vector bool int __b) {
+ return (vector bool int)__builtin_vsx_xxleqv((vector unsigned int)__a,
+ (vector unsigned int)__b);
}
static vector signed long long __ATTRS_o_ai
@@ -2050,33 +2135,15 @@ vec_eqv(vector signed long long __a, vector signed long long __b) {
__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
}
-static vector signed long long __ATTRS_o_ai
-vec_eqv(vector bool long long __a, vector signed long long __b) {
- return (vector signed long long)
- __builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
-}
-
-static vector signed long long __ATTRS_o_ai
-vec_eqv(vector signed long long __a, vector bool long long __b) {
- return (vector signed long long)
- __builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
-}
-
static vector unsigned long long __ATTRS_o_ai
vec_eqv(vector unsigned long long __a, vector unsigned long long __b) {
return (vector unsigned long long)
__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
}
-static vector unsigned long long __ATTRS_o_ai
-vec_eqv(vector bool long long __a, vector unsigned long long __b) {
- return (vector unsigned long long)
- __builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
-}
-
-static vector unsigned long long __ATTRS_o_ai
-vec_eqv(vector unsigned long long __a, vector bool long long __b) {
- return (vector unsigned long long)
+static vector bool long long __ATTRS_o_ai
+vec_eqv(vector bool long long __a, vector bool long long __b) {
+ return (vector bool long long)
__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b);
}
@@ -2085,35 +2152,11 @@ static vector float __ATTRS_o_ai vec_eqv(vector float __a, vector float __b) {
(vector unsigned int)__b);
}
-static vector float __ATTRS_o_ai vec_eqv(vector bool int __a,
- vector float __b) {
- return (vector float)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
-static vector float __ATTRS_o_ai vec_eqv(vector float __a,
- vector bool int __b) {
- return (vector float)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
static vector double __ATTRS_o_ai vec_eqv(vector double __a,
vector double __b) {
return (vector double)__builtin_vsx_xxleqv((vector unsigned int)__a,
(vector unsigned int)__b);
}
-
-static vector double __ATTRS_o_ai vec_eqv(vector bool long long __a,
- vector double __b) {
- return (vector double)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
-
-static vector double __ATTRS_o_ai vec_eqv(vector double __a,
- vector bool long long __b) {
- return (vector double)__builtin_vsx_xxleqv((vector unsigned int)__a,
- (vector unsigned int)__b);
-}
#endif
/* vec_expte */
@@ -2815,6 +2858,38 @@ static vector unsigned char __ATTRS_o_ai vec_lvsr(int __a, const float *__b) {
#endif
/* vec_madd */
+static vector signed short __ATTRS_o_ai
+vec_mladd(vector signed short, vector signed short, vector signed short);
+static vector signed short __ATTRS_o_ai
+vec_mladd(vector signed short, vector unsigned short, vector unsigned short);
+static vector signed short __ATTRS_o_ai
+vec_mladd(vector unsigned short, vector signed short, vector signed short);
+static vector unsigned short __ATTRS_o_ai
+vec_mladd(vector unsigned short, vector unsigned short, vector unsigned short);
+
+static vector signed short __ATTRS_o_ai
+vec_madd(vector signed short __a, vector signed short __b,
+ vector signed short __c) {
+ return vec_mladd(__a, __b, __c);
+}
+
+static vector signed short __ATTRS_o_ai
+vec_madd(vector signed short __a, vector unsigned short __b,
+ vector unsigned short __c) {
+ return vec_mladd(__a, __b, __c);
+}
+
+static vector signed short __ATTRS_o_ai
+vec_madd(vector unsigned short __a, vector signed short __b,
+ vector signed short __c) {
+ return vec_mladd(__a, __b, __c);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_madd(vector unsigned short __a, vector unsigned short __b,
+ vector unsigned short __c) {
+ return vec_mladd(__a, __b, __c);
+}
static vector float __ATTRS_o_ai
vec_madd(vector float __a, vector float __b, vector float __c) {
@@ -3256,6 +3331,16 @@ vec_mergeh(vector bool long long __a, vector unsigned long long __b) {
0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17));
}
+
+static vector bool long long __ATTRS_o_ai
+vec_mergeh(vector bool long long __a, vector bool long long __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17));
+}
+
static vector double __ATTRS_o_ai vec_mergeh(vector double __a,
vector double __b) {
return vec_perm(__a, __b,
@@ -3519,6 +3604,14 @@ vec_mergel(vector bool long long __a, vector unsigned long long __b) {
0x18, 0X19, 0x1A, 0x1B,
0x1C, 0x1D, 0x1E, 0x1F));
}
+static vector bool long long __ATTRS_o_ai
+vec_mergel(vector bool long long __a, vector bool long long __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x18, 0X19, 0x1A, 0x1B,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
static vector double __ATTRS_o_ai
vec_mergel(vector double __a, vector double __b) {
return vec_perm(__a, __b,
@@ -3651,21 +3744,21 @@ static vector float __ATTRS_o_ai vec_vmrglw(vector float __a,
static vector bool int __ATTRS_o_ai
vec_mergee(vector bool int __a, vector bool int __b) {
return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B));
}
static vector signed int __ATTRS_o_ai
vec_mergee(vector signed int __a, vector signed int __b) {
return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B));
}
static vector unsigned int __ATTRS_o_ai
vec_mergee(vector unsigned int __a, vector unsigned int __b) {
return vec_perm(__a, __b, (vector unsigned char)
- (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B));
}
@@ -4439,6 +4532,11 @@ static vector unsigned char __ATTRS_o_ai vec_nand(vector bool char __a,
return ~(__a & __b);
}
+static vector bool char __ATTRS_o_ai vec_nand(vector bool char __a,
+ vector bool char __b) {
+ return ~(__a & __b);
+}
+
static vector signed short __ATTRS_o_ai vec_nand(vector signed short __a,
vector signed short __b) {
return ~(__a & __b);
@@ -4465,8 +4563,8 @@ static vector unsigned short __ATTRS_o_ai vec_nand(vector unsigned short __a,
}
-static vector unsigned short __ATTRS_o_ai vec_nand(vector bool short __a,
- vector unsigned short __b) {
+static vector bool short __ATTRS_o_ai vec_nand(vector bool short __a,
+ vector bool short __b) {
return ~(__a & __b);
}
@@ -4501,6 +4599,11 @@ static vector unsigned int __ATTRS_o_ai vec_nand(vector bool int __a,
return ~(__a & __b);
}
+static vector bool int __ATTRS_o_ai vec_nand(vector bool int __a,
+ vector bool int __b) {
+ return ~(__a & __b);
+}
+
static vector signed long long __ATTRS_o_ai
vec_nand(vector signed long long __a, vector signed long long __b) {
return ~(__a & __b);
@@ -4531,6 +4634,11 @@ vec_nand(vector bool long long __a, vector unsigned long long __b) {
return ~(__a & __b);
}
+static vector bool long long __ATTRS_o_ai
+vec_nand(vector bool long long __a, vector bool long long __b) {
+ return ~(__a & __b);
+}
+
#endif
/* vec_nmadd */
@@ -4909,6 +5017,11 @@ static vector unsigned char __ATTRS_o_ai vec_orc(vector bool char __a,
return __a | ~__b;
}
+static vector bool char __ATTRS_o_ai vec_orc(vector bool char __a,
+ vector bool char __b) {
+ return __a | ~__b;
+}
+
static vector signed short __ATTRS_o_ai vec_orc(vector signed short __a,
vector signed short __b) {
return __a | ~__b;
@@ -4939,6 +5052,11 @@ vec_orc(vector bool short __a, vector unsigned short __b) {
return __a | ~__b;
}
+static vector bool short __ATTRS_o_ai vec_orc(vector bool short __a,
+ vector bool short __b) {
+ return __a | ~__b;
+}
+
static vector signed int __ATTRS_o_ai vec_orc(vector signed int __a,
vector signed int __b) {
return __a | ~__b;
@@ -4969,6 +5087,11 @@ static vector unsigned int __ATTRS_o_ai vec_orc(vector bool int __a,
return __a | ~__b;
}
+static vector bool int __ATTRS_o_ai vec_orc(vector bool int __a,
+ vector bool int __b) {
+ return __a | ~__b;
+}
+
static vector signed long long __ATTRS_o_ai
vec_orc(vector signed long long __a, vector signed long long __b) {
return __a | ~__b;
@@ -4998,6 +5121,11 @@ static vector unsigned long long __ATTRS_o_ai
vec_orc(vector bool long long __a, vector unsigned long long __b) {
return __a | ~__b;
}
+
+static vector bool long long __ATTRS_o_ai
+vec_orc(vector bool long long __a, vector bool long long __b) {
+ return __a | ~__b;
+}
#endif
/* vec_vor */
@@ -9191,17 +9319,27 @@ vec_sub(vector unsigned __int128 __a, vector unsigned __int128 __b) {
}
#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
-static vector float __ATTRS_o_ai vec_sub(vector float __a, vector float __b) {
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai
+vec_sub(vector signed long long __a, vector signed long long __b) {
+ return __a - __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_sub(vector unsigned long long __a, vector unsigned long long __b) {
return __a - __b;
}
-#ifdef __VSX__
static vector double __ATTRS_o_ai
vec_sub(vector double __a, vector double __b) {
return __a - __b;
}
#endif
+static vector float __ATTRS_o_ai vec_sub(vector float __a, vector float __b) {
+ return __a - __b;
+}
+
/* vec_vsububm */
#define __builtin_altivec_vsububm vec_vsububm
@@ -10390,7 +10528,12 @@ static unsigned char __ATTRS_o_ai vec_extract(vector unsigned char __a,
return __a[__b];
}
-static short __ATTRS_o_ai vec_extract(vector short __a, int __b) {
+static unsigned char __ATTRS_o_ai vec_extract(vector bool char __a,
+ int __b) {
+ return __a[__b];
+}
+
+static signed short __ATTRS_o_ai vec_extract(vector signed short __a, int __b) {
return __a[__b];
}
@@ -10399,7 +10542,12 @@ static unsigned short __ATTRS_o_ai vec_extract(vector unsigned short __a,
return __a[__b];
}
-static int __ATTRS_o_ai vec_extract(vector int __a, int __b) {
+static unsigned short __ATTRS_o_ai vec_extract(vector bool short __a,
+ int __b) {
+ return __a[__b];
+}
+
+static signed int __ATTRS_o_ai vec_extract(vector signed int __a, int __b) {
return __a[__b];
}
@@ -10407,6 +10555,31 @@ static unsigned int __ATTRS_o_ai vec_extract(vector unsigned int __a, int __b) {
return __a[__b];
}
+static unsigned int __ATTRS_o_ai vec_extract(vector bool int __a, int __b) {
+ return __a[__b];
+}
+
+#ifdef __VSX__
+static signed long long __ATTRS_o_ai vec_extract(vector signed long long __a,
+ int __b) {
+ return __a[__b];
+}
+
+static unsigned long long __ATTRS_o_ai
+vec_extract(vector unsigned long long __a, int __b) {
+ return __a[__b];
+}
+
+static unsigned long long __ATTRS_o_ai vec_extract(vector bool long long __a,
+ int __b) {
+ return __a[__b];
+}
+
+static double __ATTRS_o_ai vec_extract(vector double __a, int __b) {
+ return __a[__b];
+}
+#endif
+
static float __ATTRS_o_ai vec_extract(vector float __a, int __b) {
return __a[__b];
}
@@ -10427,8 +10600,16 @@ static vector unsigned char __ATTRS_o_ai vec_insert(unsigned char __a,
return __b;
}
-static vector short __ATTRS_o_ai vec_insert(short __a, vector short __b,
- int __c) {
+static vector bool char __ATTRS_o_ai vec_insert(unsigned char __a,
+ vector bool char __b,
+ int __c) {
+ __b[__c] = __a;
+ return __b;
+}
+
+static vector signed short __ATTRS_o_ai vec_insert(signed short __a,
+ vector signed short __b,
+ int __c) {
__b[__c] = __a;
return __b;
}
@@ -10440,7 +10621,16 @@ static vector unsigned short __ATTRS_o_ai vec_insert(unsigned short __a,
return __b;
}
-static vector int __ATTRS_o_ai vec_insert(int __a, vector int __b, int __c) {
+static vector bool short __ATTRS_o_ai vec_insert(unsigned short __a,
+ vector bool short __b,
+ int __c) {
+ __b[__c] = __a;
+ return __b;
+}
+
+static vector signed int __ATTRS_o_ai vec_insert(signed int __a,
+ vector signed int __b,
+ int __c) {
__b[__c] = __a;
return __b;
}
@@ -10452,6 +10642,38 @@ static vector unsigned int __ATTRS_o_ai vec_insert(unsigned int __a,
return __b;
}
+static vector bool int __ATTRS_o_ai vec_insert(unsigned int __a,
+ vector bool int __b,
+ int __c) {
+ __b[__c] = __a;
+ return __b;
+}
+
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai
+vec_insert(signed long long __a, vector signed long long __b, int __c) {
+ __b[__c] = __a;
+ return __b;
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_insert(unsigned long long __a, vector unsigned long long __b, int __c) {
+ __b[__c] = __a;
+ return __b;
+}
+
+static vector bool long long __ATTRS_o_ai
+vec_insert(unsigned long long __a, vector bool long long __b, int __c) {
+ __b[__c] = __a;
+ return __b;
+}
+static vector double __ATTRS_o_ai vec_insert(double __a, vector double __b,
+ int __c) {
+ __b[__c] = __a;
+ return __b;
+}
+#endif
+
static vector float __ATTRS_o_ai vec_insert(float __a, vector float __b,
int __c) {
__b[__c] = __a;
@@ -11376,6 +11598,33 @@ static vector unsigned int __ATTRS_o_ai vec_splats(unsigned int __a) {
return (vector unsigned int)(__a);
}
+#ifdef __VSX__
+static vector signed long long __ATTRS_o_ai vec_splats(signed long long __a) {
+ return (vector signed long long)(__a);
+}
+
+static vector unsigned long long __ATTRS_o_ai
+vec_splats(unsigned long long __a) {
+ return (vector unsigned long long)(__a);
+}
+
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static vector signed __int128 __ATTRS_o_ai vec_splats(signed __int128 __a) {
+ return (vector signed __int128)(__a);
+}
+
+static vector unsigned __int128 __ATTRS_o_ai
+vec_splats(unsigned __int128 __a) {
+ return (vector unsigned __int128)(__a);
+}
+
+#endif
+
+static vector double __ATTRS_o_ai vec_splats(double __a) {
+ return (vector double)(__a);
+}
+#endif
+
static vector float __ATTRS_o_ai vec_splats(float __a) {
return (vector float)(__a);
}
@@ -11546,9 +11795,19 @@ static int __ATTRS_o_ai vec_all_eq(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_all_eq(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpeqsp_p(__CR6_LT, __a, __b);
+#else
return __builtin_altivec_vcmpeqfp_p(__CR6_LT, __a, __b);
+#endif
}
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_all_eq(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpeqdp_p(__CR6_LT, __a, __b);
+}
+#endif
+
/* vec_all_ge */
static int __ATTRS_o_ai vec_all_ge(vector signed char __a,
@@ -11698,8 +11957,18 @@ static int __ATTRS_o_ai vec_all_ge(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_all_ge(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgesp_p(__CR6_LT, __a, __b);
+#else
return __builtin_altivec_vcmpgefp_p(__CR6_LT, __a, __b);
+#endif
+}
+
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_all_ge(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpgedp_p(__CR6_LT, __a, __b);
}
+#endif
/* vec_all_gt */
@@ -11850,8 +12119,18 @@ static int __ATTRS_o_ai vec_all_gt(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_all_gt(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgtsp_p(__CR6_LT, __a, __b);
+#else
return __builtin_altivec_vcmpgtfp_p(__CR6_LT, __a, __b);
+#endif
+}
+
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_all_gt(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpgtdp_p(__CR6_LT, __a, __b);
}
+#endif
/* vec_all_in */
@@ -12010,9 +12289,19 @@ static int __ATTRS_o_ai vec_all_le(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_all_le(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgesp_p(__CR6_LT, __b, __a);
+#else
return __builtin_altivec_vcmpgefp_p(__CR6_LT, __b, __a);
+#endif
}
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_all_le(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpgedp_p(__CR6_LT, __b, __a);
+}
+#endif
+
/* vec_all_lt */
static int __ATTRS_o_ai vec_all_lt(vector signed char __a,
@@ -12163,14 +12452,34 @@ static int __ATTRS_o_ai vec_all_lt(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_all_lt(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgtsp_p(__CR6_LT, __b, __a);
+#else
return __builtin_altivec_vcmpgtfp_p(__CR6_LT, __b, __a);
+#endif
+}
+
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_all_lt(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpgtdp_p(__CR6_LT, __b, __a);
}
+#endif
/* vec_all_nan */
-static int __attribute__((__always_inline__)) vec_all_nan(vector float __a) {
+static int __ATTRS_o_ai vec_all_nan(vector float __a) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpeqsp_p(__CR6_EQ, __a, __a);
+#else
return __builtin_altivec_vcmpeqfp_p(__CR6_EQ, __a, __a);
+#endif
+}
+
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_all_nan(vector double __a) {
+ return __builtin_vsx_xvcmpeqdp_p(__CR6_EQ, __a, __a);
}
+#endif
/* vec_all_ne */
@@ -12337,23 +12646,55 @@ static int __ATTRS_o_ai vec_all_ne(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_all_ne(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpeqdp_p(__CR6_EQ, __a, __b);
+#else
return __builtin_altivec_vcmpeqfp_p(__CR6_EQ, __a, __b);
+#endif
}
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_all_ne(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpeqdp_p(__CR6_EQ, __a, __b);
+}
+#endif
+
/* vec_all_nge */
-static int __attribute__((__always_inline__))
+static int __ATTRS_o_ai
vec_all_nge(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgesp_p(__CR6_EQ, __a, __b);
+#else
return __builtin_altivec_vcmpgefp_p(__CR6_EQ, __a, __b);
+#endif
}
+#ifdef __VSX__
+static int __ATTRS_o_ai
+vec_all_nge(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpgedp_p(__CR6_EQ, __a, __b);
+}
+#endif
+
/* vec_all_ngt */
-static int __attribute__((__always_inline__))
+static int __ATTRS_o_ai
vec_all_ngt(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgtsp_p(__CR6_EQ, __a, __b);
+#else
return __builtin_altivec_vcmpgtfp_p(__CR6_EQ, __a, __b);
+#endif
}
+#ifdef __VSX__
+static int __ATTRS_o_ai
+vec_all_ngt(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpgtdp_p(__CR6_EQ, __a, __b);
+}
+#endif
+
/* vec_all_nle */
static int __attribute__((__always_inline__))
@@ -12540,9 +12881,19 @@ static int __ATTRS_o_ai vec_any_eq(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_any_eq(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpeqsp_p(__CR6_EQ_REV, __a, __b);
+#else
return __builtin_altivec_vcmpeqfp_p(__CR6_EQ_REV, __a, __b);
+#endif
}
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_any_eq(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpeqdp_p(__CR6_EQ_REV, __a, __b);
+}
+#endif
+
/* vec_any_ge */
static int __ATTRS_o_ai vec_any_ge(vector signed char __a,
@@ -12700,8 +13051,18 @@ static int __ATTRS_o_ai vec_any_ge(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_any_ge(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgesp_p(__CR6_EQ_REV, __a, __b);
+#else
return __builtin_altivec_vcmpgefp_p(__CR6_EQ_REV, __a, __b);
+#endif
+}
+
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_any_ge(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpgedp_p(__CR6_EQ_REV, __a, __b);
}
+#endif
/* vec_any_gt */
@@ -12860,9 +13221,19 @@ static int __ATTRS_o_ai vec_any_gt(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_any_gt(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgtsp_p(__CR6_EQ_REV, __a, __b);
+#else
return __builtin_altivec_vcmpgtfp_p(__CR6_EQ_REV, __a, __b);
+#endif
}
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_any_gt(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpgtdp_p(__CR6_EQ_REV, __a, __b);
+}
+#endif
+
/* vec_any_le */
static int __ATTRS_o_ai vec_any_le(vector signed char __a,
@@ -13020,8 +13391,18 @@ static int __ATTRS_o_ai vec_any_le(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_any_le(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgesp_p(__CR6_EQ_REV, __b, __a);
+#else
return __builtin_altivec_vcmpgefp_p(__CR6_EQ_REV, __b, __a);
+#endif
+}
+
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_any_le(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpgedp_p(__CR6_EQ_REV, __b, __a);
}
+#endif
/* vec_any_lt */
@@ -13180,8 +13561,18 @@ static int __ATTRS_o_ai vec_any_lt(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_any_lt(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgtsp_p(__CR6_EQ_REV, __b, __a);
+#else
return __builtin_altivec_vcmpgtfp_p(__CR6_EQ_REV, __b, __a);
+#endif
+}
+
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_any_lt(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpgtdp_p(__CR6_EQ_REV, __b, __a);
}
+#endif
/* vec_any_nan */
@@ -13354,8 +13745,18 @@ static int __ATTRS_o_ai vec_any_ne(vector bool long long __a,
#endif
static int __ATTRS_o_ai vec_any_ne(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpeqsp_p(__CR6_LT_REV, __a, __b);
+#else
return __builtin_altivec_vcmpeqfp_p(__CR6_LT_REV, __a, __b);
+#endif
+}
+
+#ifdef __VSX__
+static int __ATTRS_o_ai vec_any_ne(vector double __a, vector double __b) {
+ return __builtin_vsx_xvcmpeqdp_p(__CR6_LT_REV, __a, __b);
}
+#endif
/* vec_any_nge */
@@ -13411,11 +13812,14 @@ support). As a result, we need to be able to turn off support for those.
The remaining ones (currently controlled by -mcrypto for GCC) still
need to be provided on compliant hardware even if Vector.Crypto is not
provided.
-FIXME: the naming convention for the builtins will be adjusted due
-to the inconsistency (__builtin_crypto_ prefix on builtins that cannot be
-removed with -mno-crypto). This is under development.
*/
#ifdef __CRYPTO__
+#define vec_sbox_be __builtin_altivec_crypto_vsbox
+#define vec_cipher_be __builtin_altivec_crypto_vcipher
+#define vec_cipherlast_be __builtin_altivec_crypto_vcipherlast
+#define vec_ncipher_be __builtin_altivec_crypto_vncipher
+#define vec_ncipherlast_be __builtin_altivec_crypto_vncipherlast
+
static vector unsigned long long __attribute__((__always_inline__))
__builtin_crypto_vsbox(vector unsigned long long __a) {
return __builtin_altivec_crypto_vsbox(__a);
@@ -13447,6 +13851,11 @@ __builtin_crypto_vncipherlast(vector unsigned long long __a,
#define __builtin_crypto_vshasigmad __builtin_altivec_crypto_vshasigmad
#define __builtin_crypto_vshasigmaw __builtin_altivec_crypto_vshasigmaw
+
+#define vec_shasigma_be(X, Y, Z) \
+ _Generic((X), vector unsigned int: __builtin_crypto_vshasigmaw, \
+ vector unsigned long long: __builtin_crypto_vshasigmad) \
+((X), (Y), (Z))
#endif
#ifdef __POWER8_VECTOR__
@@ -13494,8 +13903,9 @@ __builtin_crypto_vpmsumb(vector unsigned int __a, vector unsigned int __b) {
return __builtin_altivec_crypto_vpmsumw(__a, __b);
}
-static vector unsigned long long __ATTRS_o_ai __builtin_crypto_vpmsumb(
- vector unsigned long long __a, vector unsigned long long __b) {
+static vector unsigned long long __ATTRS_o_ai
+__builtin_crypto_vpmsumb(vector unsigned long long __a,
+ vector unsigned long long __b) {
return __builtin_altivec_crypto_vpmsumd(__a, __b);
}
@@ -13504,6 +13914,9 @@ static vector signed char __ATTRS_o_ai vec_vgbbd (vector signed char __a)
return __builtin_altivec_vgbbd((vector unsigned char) __a);
}
+#define vec_pmsum_be __builtin_crypto_vpmsumb
+#define vec_gb __builtin_altivec_vgbbd
+
static vector unsigned char __ATTRS_o_ai vec_vgbbd (vector unsigned char __a)
{
return __builtin_altivec_vgbbd(__a);
@@ -13521,6 +13934,14 @@ vec_vbpermq (vector unsigned char __a, vector unsigned char __b)
{
return __builtin_altivec_vbpermq(__a, __b);
}
+
+#ifdef __powerpc64__
+static vector unsigned long long __attribute__((__always_inline__))
+vec_bperm (vector unsigned __int128 __a, vector unsigned char __b) {
+ return __builtin_altivec_vbpermq((vector unsigned char) __a,
+ (vector unsigned char) __b);
+}
+#endif
#endif
#undef __ATTRS_o_ai
diff --git a/contrib/llvm/tools/clang/lib/Headers/ammintrin.h b/contrib/llvm/tools/clang/lib/Headers/ammintrin.h
index 4d0e770..4880fd7 100644
--- a/contrib/llvm/tools/clang/lib/Headers/ammintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/ammintrin.h
@@ -24,27 +24,23 @@
#ifndef __AMMINTRIN_H
#define __AMMINTRIN_H
-#ifndef __SSE4A__
-#error "SSE4A instruction set not enabled"
-#else
-
#include <pmmintrin.h>
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4a")))
/// \brief Extracts the specified bits from the lower 64 bits of the 128-bit
/// integer vector operand at the index idx and of the length len.
///
/// \headerfile <x86intrin.h>
///
-/// \code
+/// \code
/// __m128i _mm_extracti_si64(__m128i x, const int len, const int idx);
-/// \endcode
+/// \endcode
///
-/// \code
+/// \code
/// This intrinsic corresponds to the \c EXTRQ instruction.
-/// \endcode
+/// \endcode
///
/// \param x
/// The value from which bits are extracted.
@@ -52,10 +48,10 @@
/// Bits [5:0] specify the length; the other bits are ignored. If bits [5:0]
/// are zero, the length is interpreted as 64.
/// \param idx
-/// Bits [5:0] specify the index of the least significant bit; the other
-/// bits are ignored. If the sum of the index and length is greater than
-/// 64, the result is undefined. If the length and index are both zero,
-/// bits [63:0] of parameter x are extracted. If the length is zero
+/// Bits [5:0] specify the index of the least significant bit; the other
+/// bits are ignored. If the sum of the index and length is greater than
+/// 64, the result is undefined. If the length and index are both zero,
+/// bits [63:0] of parameter x are extracted. If the length is zero
/// but the index is non-zero, the result is undefined.
/// \returns A 128-bit integer vector whose lower 64 bits contain the bits
/// extracted from the source operand.
@@ -68,21 +64,21 @@
///
/// \headerfile <x86intrin.h>
///
-/// \code
+/// \code
/// This intrinsic corresponds to the \c EXTRQ instruction.
-/// \endcode
+/// \endcode
///
/// \param __x
/// The value from which bits are extracted.
/// \param __y
-/// Specifies the index of the least significant bit at [13:8]
-/// and the length at [5:0]; all other bits are ignored.
+/// Specifies the index of the least significant bit at [13:8]
+/// and the length at [5:0]; all other bits are ignored.
/// If bits [5:0] are zero, the length is interpreted as 64.
-/// If the sum of the index and length is greater than 64, the result is
-/// undefined. If the length and index are both zero, bits [63:0] of
-/// parameter __x are extracted. If the length is zero but the index is
-/// non-zero, the result is undefined.
-/// \returns A 128-bit vector whose lower 64 bits contain the bits extracted
+/// If the sum of the index and length is greater than 64, the result is
+/// undefined. If the length and index are both zero, bits [63:0] of
+/// parameter __x are extracted. If the length is zero but the index is
+/// non-zero, the result is undefined.
+/// \returns A 128-bit vector whose lower 64 bits contain the bits extracted
/// from the source operand.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_extract_si64(__m128i __x, __m128i __y)
@@ -90,40 +86,40 @@ _mm_extract_si64(__m128i __x, __m128i __y)
return (__m128i)__builtin_ia32_extrq((__v2di)__x, (__v16qi)__y);
}
-/// \brief Inserts bits of a specified length from the source integer vector
-/// y into the lower 64 bits of the destination integer vector x at the
+/// \brief Inserts bits of a specified length from the source integer vector
+/// y into the lower 64 bits of the destination integer vector x at the
/// index idx and of the length len.
///
/// \headerfile <x86intrin.h>
///
-/// \code
+/// \code
/// __m128i _mm_inserti_si64(__m128i x, __m128i y, const int len,
/// const int idx);
-/// \endcode
+/// \endcode
///
-/// \code
+/// \code
/// This intrinsic corresponds to the \c INSERTQ instruction.
-/// \endcode
+/// \endcode
///
/// \param x
-/// The destination operand where bits will be inserted. The inserted bits
-/// are defined by the length len and by the index idx specifying the least
+/// The destination operand where bits will be inserted. The inserted bits
+/// are defined by the length len and by the index idx specifying the least
/// significant bit.
/// \param y
-/// The source operand containing the bits to be extracted. The extracted
+/// The source operand containing the bits to be extracted. The extracted
/// bits are the least significant bits of operand y of length len.
/// \param len
/// Bits [5:0] specify the length; the other bits are ignored. If bits [5:0]
/// are zero, the length is interpreted as 64.
/// \param idx
-/// Bits [5:0] specify the index of the least significant bit; the other
-/// bits are ignored. If the sum of the index and length is greater than
-/// 64, the result is undefined. If the length and index are both zero,
-/// bits [63:0] of parameter y are inserted into parameter x. If the
+/// Bits [5:0] specify the index of the least significant bit; the other
+/// bits are ignored. If the sum of the index and length is greater than
+/// 64, the result is undefined. If the length and index are both zero,
+/// bits [63:0] of parameter y are inserted into parameter x. If the
/// length is zero but the index is non-zero, the result is undefined.
-/// \returns A 128-bit integer vector containing the original lower 64-bits
+/// \returns A 128-bit integer vector containing the original lower 64-bits
/// of destination operand x with the specified bitfields replaced by the
-/// lower bits of source operand y. The upper 64 bits of the return value
+/// lower bits of source operand y. The upper 64 bits of the return value
/// are undefined.
#define _mm_inserti_si64(x, y, len, idx) \
@@ -131,33 +127,33 @@ _mm_extract_si64(__m128i __x, __m128i __y)
(__v2di)(__m128i)(y), \
(char)(len), (char)(idx)))
-/// \brief Inserts bits of a specified length from the source integer vector
-/// __y into the lower 64 bits of the destination integer vector __x at
+/// \brief Inserts bits of a specified length from the source integer vector
+/// __y into the lower 64 bits of the destination integer vector __x at
/// the index and of the length specified by __y.
///
/// \headerfile <x86intrin.h>
///
-/// \code
+/// \code
/// This intrinsic corresponds to the \c INSERTQ instruction.
-/// \endcode
+/// \endcode
///
/// \param __x
-/// The destination operand where bits will be inserted. The inserted bits
-/// are defined by the length and by the index of the least significant bit
+/// The destination operand where bits will be inserted. The inserted bits
+/// are defined by the length and by the index of the least significant bit
/// specified by operand __y.
/// \param __y
-/// The source operand containing the bits to be extracted. The extracted
+/// The source operand containing the bits to be extracted. The extracted
/// bits are the least significant bits of operand __y with length specified
-/// by bits [69:64]. These are inserted into the destination at the index
+/// by bits [69:64]. These are inserted into the destination at the index
/// specified by bits [77:72]; all other bits are ignored.
/// If bits [69:64] are zero, the length is interpreted as 64.
-/// If the sum of the index and length is greater than 64, the result is
-/// undefined. If the length and index are both zero, bits [63:0] of
+/// If the sum of the index and length is greater than 64, the result is
+/// undefined. If the length and index are both zero, bits [63:0] of
/// parameter __y are inserted into parameter __x. If the length
-/// is zero but the index is non-zero, the result is undefined.
-/// \returns A 128-bit integer vector containing the original lower 64-bits
+/// is zero but the index is non-zero, the result is undefined.
+/// \returns A 128-bit integer vector containing the original lower 64-bits
/// of destination operand __x with the specified bitfields replaced by the
-/// lower bits of source operand __y. The upper 64 bits of the return value
+/// lower bits of source operand __y. The upper 64 bits of the return value
/// are undefined.
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -166,15 +162,15 @@ _mm_insert_si64(__m128i __x, __m128i __y)
return (__m128i)__builtin_ia32_insertq((__v2di)__x, (__v2di)__y);
}
-/// \brief Stores a 64-bit double-precision value in a 64-bit memory location.
+/// \brief Stores a 64-bit double-precision value in a 64-bit memory location.
/// To minimize caching, the data is flagged as non-temporal (unlikely to be
/// used again soon).
///
/// \headerfile <x86intrin.h>
///
-/// \code
+/// \code
/// This intrinsic corresponds to the \c MOVNTSD instruction.
-/// \endcode
+/// \endcode
///
/// \param __p
/// The 64-bit memory location used to store the register value.
@@ -193,9 +189,9 @@ _mm_stream_sd(double *__p, __m128d __a)
///
/// \headerfile <x86intrin.h>
///
-/// \code
+/// \code
/// This intrinsic corresponds to the \c MOVNTSS instruction.
-/// \endcode
+/// \endcode
///
/// \param __p
/// The 32-bit memory location used to store the register value.
@@ -210,6 +206,4 @@ _mm_stream_ss(float *__p, __m128 __a)
#undef __DEFAULT_FN_ATTRS
-#endif /* __SSE4A__ */
-
#endif /* __AMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/arm_acle.h b/contrib/llvm/tools/clang/lib/Headers/arm_acle.h
index 73a7e76..4be1d09 100644
--- a/contrib/llvm/tools/clang/lib/Headers/arm_acle.h
+++ b/contrib/llvm/tools/clang/lib/Headers/arm_acle.h
@@ -175,14 +175,18 @@ static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
return __ror(__rev(t), 16);
}
-static __inline__ unsigned long __attribute__((__always_inline__, __nodebug__))
- __rev16l(unsigned long t) {
- return __rorl(__revl(t), sizeof(long) / 2);
-}
-
static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__))
__rev16ll(uint64_t t) {
- return __rorll(__revll(t), 32);
+ return (((uint64_t)__rev16(t >> 32)) << 32) | __rev16(t);
+}
+
+static __inline__ unsigned long __attribute__((__always_inline__, __nodebug__))
+ __rev16l(unsigned long t) {
+#if __SIZEOF_LONG__ == 4
+ return __rev16(t);
+#else
+ return __rev16ll(t);
+#endif
}
/* REVSH */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h b/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
index d8b6b0a..f786572 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx2intrin.h
@@ -29,7 +29,7 @@
#define __AVX2INTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx2")))
/* SSE4 Multiple Packed Sums of Absolute Difference. */
#define _mm256_mpsadbw_epu8(X, Y, M) __builtin_ia32_mpsadbw256((X), (Y), (M))
@@ -124,10 +124,9 @@ _mm256_adds_epu16(__m256i __a, __m256i __b)
return (__m256i)__builtin_ia32_paddusw256((__v16hi)__a, (__v16hi)__b);
}
-#define _mm256_alignr_epi8(a, b, n) __extension__ ({ \
- __m256i __a = (a); \
- __m256i __b = (b); \
- (__m256i)__builtin_ia32_palignr256((__v32qi)__a, (__v32qi)__b, (n)); })
+#define _mm256_alignr_epi8(a, b, n) __extension__ ({ \
+ (__m256i)__builtin_ia32_palignr256((__v32qi)(__m256i)(a), \
+ (__v32qi)(__m256i)(b), (n)); })
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_and_si256(__m256i __a, __m256i __b)
@@ -160,20 +159,19 @@ _mm256_blendv_epi8(__m256i __V1, __m256i __V2, __m256i __M)
(__v32qi)__M);
}
-#define _mm256_blend_epi16(V1, V2, M) __extension__ ({ \
- __m256i __V1 = (V1); \
- __m256i __V2 = (V2); \
- (__m256i)__builtin_shufflevector((__v16hi)__V1, (__v16hi)__V2, \
- (((M) & 0x01) ? 16 : 0), \
- (((M) & 0x02) ? 17 : 1), \
- (((M) & 0x04) ? 18 : 2), \
- (((M) & 0x08) ? 19 : 3), \
- (((M) & 0x10) ? 20 : 4), \
- (((M) & 0x20) ? 21 : 5), \
- (((M) & 0x40) ? 22 : 6), \
- (((M) & 0x80) ? 23 : 7), \
- (((M) & 0x01) ? 24 : 8), \
- (((M) & 0x02) ? 25 : 9), \
+#define _mm256_blend_epi16(V1, V2, M) __extension__ ({ \
+ (__m256i)__builtin_shufflevector((__v16hi)(__m256i)(V1), \
+ (__v16hi)(__m256i)(V2), \
+ (((M) & 0x01) ? 16 : 0), \
+ (((M) & 0x02) ? 17 : 1), \
+ (((M) & 0x04) ? 18 : 2), \
+ (((M) & 0x08) ? 19 : 3), \
+ (((M) & 0x10) ? 20 : 4), \
+ (((M) & 0x20) ? 21 : 5), \
+ (((M) & 0x40) ? 22 : 6), \
+ (((M) & 0x80) ? 23 : 7), \
+ (((M) & 0x01) ? 24 : 8), \
+ (((M) & 0x02) ? 25 : 9), \
(((M) & 0x04) ? 26 : 10), \
(((M) & 0x08) ? 27 : 11), \
(((M) & 0x10) ? 28 : 12), \
@@ -208,7 +206,9 @@ _mm256_cmpeq_epi64(__m256i __a, __m256i __b)
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_cmpgt_epi8(__m256i __a, __m256i __b)
{
- return (__m256i)((__v32qi)__a > (__v32qi)__b);
+ /* This function always performs a signed comparison, but __v32qi is a char
+ which may be signed or unsigned, so use __v32qs. */
+ return (__m256i)((__v32qs)__a > (__v32qs)__b);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
@@ -488,8 +488,8 @@ _mm256_shuffle_epi8(__m256i __a, __m256i __b)
}
#define _mm256_shuffle_epi32(a, imm) __extension__ ({ \
- __m256i __a = (a); \
- (__m256i)__builtin_shufflevector((__v8si)__a, (__v8si)_mm256_set1_epi32(0), \
+ (__m256i)__builtin_shufflevector((__v8si)(__m256i)(a), \
+ (__v8si)_mm256_setzero_si256(), \
(imm) & 0x3, ((imm) & 0xc) >> 2, \
((imm) & 0x30) >> 4, ((imm) & 0xc0) >> 6, \
4 + (((imm) & 0x03) >> 0), \
@@ -498,8 +498,8 @@ _mm256_shuffle_epi8(__m256i __a, __m256i __b)
4 + (((imm) & 0xc0) >> 6)); })
#define _mm256_shufflehi_epi16(a, imm) __extension__ ({ \
- __m256i __a = (a); \
- (__m256i)__builtin_shufflevector((__v16hi)__a, (__v16hi)_mm256_set1_epi16(0), \
+ (__m256i)__builtin_shufflevector((__v16hi)(__m256i)(a), \
+ (__v16hi)_mm256_setzero_si256(), \
0, 1, 2, 3, \
4 + (((imm) & 0x03) >> 0), \
4 + (((imm) & 0x0c) >> 2), \
@@ -512,8 +512,8 @@ _mm256_shuffle_epi8(__m256i __a, __m256i __b)
12 + (((imm) & 0xc0) >> 6)); })
#define _mm256_shufflelo_epi16(a, imm) __extension__ ({ \
- __m256i __a = (a); \
- (__m256i)__builtin_shufflevector((__v16hi)__a, (__v16hi)_mm256_set1_epi16(0), \
+ (__m256i)__builtin_shufflevector((__v16hi)(__m256i)(a), \
+ (__v16hi)_mm256_setzero_si256(), \
(imm) & 0x3,((imm) & 0xc) >> 2, \
((imm) & 0x30) >> 4, ((imm) & 0xc0) >> 6, \
4, 5, 6, 7, \
@@ -542,8 +542,7 @@ _mm256_sign_epi32(__m256i __a, __m256i __b)
}
#define _mm256_slli_si256(a, count) __extension__ ({ \
- __m256i __a = (a); \
- (__m256i)__builtin_ia32_pslldqi256(__a, (count)*8); })
+ (__m256i)__builtin_ia32_pslldqi256((__m256i)(a), (count)*8); })
#define _mm256_bslli_epi128(a, count) _mm256_slli_si256((a), (count))
@@ -608,8 +607,7 @@ _mm256_sra_epi32(__m256i __a, __m128i __count)
}
#define _mm256_srli_si256(a, count) __extension__ ({ \
- __m256i __a = (a); \
- (__m256i)__builtin_ia32_psrldqi256(__a, (count)*8); })
+ (__m256i)__builtin_ia32_psrldqi256((__m256i)(a), (count)*8); })
#define _mm256_bsrli_epi128(a, count) _mm256_srli_si256((a), (count))
@@ -752,15 +750,15 @@ _mm256_xor_si256(__m256i __a, __m256i __b)
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_stream_load_si256(__m256i *__V)
+_mm256_stream_load_si256(__m256i const *__V)
{
- return (__m256i)__builtin_ia32_movntdqa256((__v4di *)__V);
+ return (__m256i)__builtin_ia32_movntdqa256((const __v4di *)__V);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_broadcastss_ps(__m128 __X)
{
- return (__m128)__builtin_ia32_vbroadcastss_ps((__v4sf)__X);
+ return (__m128)__builtin_shufflevector((__v4sf)__X, (__v4sf)__X, 0, 0, 0, 0);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
@@ -772,13 +770,13 @@ _mm_broadcastsd_pd(__m128d __a)
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_broadcastss_ps(__m128 __X)
{
- return (__m256)__builtin_ia32_vbroadcastss_ps256((__v4sf)__X);
+ return (__m256)__builtin_shufflevector((__v4sf)__X, (__v4sf)__X, 0, 0, 0, 0, 0, 0, 0, 0);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_broadcastsd_pd(__m128d __X)
{
- return (__m256d)__builtin_ia32_vbroadcastsd_pd256((__v2df)__X);
+ return (__m256d)__builtin_shufflevector((__v2df)__X, (__v2df)__X, 0, 0, 0, 0);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
@@ -788,18 +786,16 @@ _mm256_broadcastsi128_si256(__m128i __X)
}
#define _mm_blend_epi32(V1, V2, M) __extension__ ({ \
- __m128i __V1 = (V1); \
- __m128i __V2 = (V2); \
- (__m128i)__builtin_shufflevector((__v4si)__V1, (__v4si)__V2, \
+ (__m128i)__builtin_shufflevector((__v4si)(__m128i)(V1), \
+ (__v4si)(__m128i)(V2), \
(((M) & 0x01) ? 4 : 0), \
(((M) & 0x02) ? 5 : 1), \
(((M) & 0x04) ? 6 : 2), \
(((M) & 0x08) ? 7 : 3)); })
#define _mm256_blend_epi32(V1, V2, M) __extension__ ({ \
- __m256i __V1 = (V1); \
- __m256i __V2 = (V2); \
- (__m256i)__builtin_shufflevector((__v8si)__V1, (__v8si)__V2, \
+ (__m256i)__builtin_shufflevector((__v8si)(__m256i)(V1), \
+ (__v8si)(__m256i)(V2), \
(((M) & 0x01) ? 8 : 0), \
(((M) & 0x02) ? 9 : 1), \
(((M) & 0x04) ? 10 : 2), \
@@ -812,50 +808,50 @@ _mm256_broadcastsi128_si256(__m128i __X)
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcastb_epi8(__m128i __X)
{
- return (__m256i)__builtin_ia32_pbroadcastb256((__v16qi)__X);
+ return (__m256i)__builtin_shufflevector((__v16qi)__X, (__v16qi)__X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcastw_epi16(__m128i __X)
{
- return (__m256i)__builtin_ia32_pbroadcastw256((__v8hi)__X);
+ return (__m256i)__builtin_shufflevector((__v8hi)__X, (__v8hi)__X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcastd_epi32(__m128i __X)
{
- return (__m256i)__builtin_ia32_pbroadcastd256((__v4si)__X);
+ return (__m256i)__builtin_shufflevector((__v4si)__X, (__v4si)__X, 0, 0, 0, 0, 0, 0, 0, 0);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_broadcastq_epi64(__m128i __X)
{
- return (__m256i)__builtin_ia32_pbroadcastq256(__X);
+ return (__m256i)__builtin_shufflevector(__X, __X, 0, 0, 0, 0);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_broadcastb_epi8(__m128i __X)
{
- return (__m128i)__builtin_ia32_pbroadcastb128((__v16qi)__X);
+ return (__m128i)__builtin_shufflevector((__v16qi)__X, (__v16qi)__X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_broadcastw_epi16(__m128i __X)
{
- return (__m128i)__builtin_ia32_pbroadcastw128((__v8hi)__X);
+ return (__m128i)__builtin_shufflevector((__v8hi)__X, (__v8hi)__X, 0, 0, 0, 0, 0, 0, 0, 0);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_broadcastd_epi32(__m128i __X)
{
- return (__m128i)__builtin_ia32_pbroadcastd128((__v4si)__X);
+ return (__m128i)__builtin_shufflevector((__v4si)__X, (__v4si)__X, 0, 0, 0, 0);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_broadcastq_epi64(__m128i __X)
{
- return (__m128i)__builtin_ia32_pbroadcastq128(__X);
+ return (__m128i)__builtin_shufflevector(__X, __X, 0, 0);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
@@ -865,43 +861,39 @@ _mm256_permutevar8x32_epi32(__m256i __a, __m256i __b)
}
#define _mm256_permute4x64_pd(V, M) __extension__ ({ \
- __m256d __V = (V); \
- (__m256d)__builtin_shufflevector((__v4df)__V, (__v4df) _mm256_setzero_pd(), \
+ (__m256d)__builtin_shufflevector((__v4df)(__m256d)(V), \
+ (__v4df)_mm256_setzero_pd(), \
(M) & 0x3, ((M) & 0xc) >> 2, \
((M) & 0x30) >> 4, ((M) & 0xc0) >> 6); })
static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_permutevar8x32_ps(__m256 __a, __m256 __b)
+_mm256_permutevar8x32_ps(__m256 __a, __m256i __b)
{
- return (__m256)__builtin_ia32_permvarsf256((__v8sf)__a, (__v8sf)__b);
+ return (__m256)__builtin_ia32_permvarsf256((__v8sf)__a, (__v8si)__b);
}
#define _mm256_permute4x64_epi64(V, M) __extension__ ({ \
- __m256i __V = (V); \
- (__m256i)__builtin_shufflevector((__v4di)__V, (__v4di) _mm256_setzero_si256(), \
+ (__m256i)__builtin_shufflevector((__v4di)(__m256i)(V), \
+ (__v4di)_mm256_setzero_si256(), \
(M) & 0x3, ((M) & 0xc) >> 2, \
((M) & 0x30) >> 4, ((M) & 0xc0) >> 6); })
#define _mm256_permute2x128_si256(V1, V2, M) __extension__ ({ \
- __m256i __V1 = (V1); \
- __m256i __V2 = (V2); \
- (__m256i)__builtin_ia32_permti256(__V1, __V2, (M)); })
+ (__m256i)__builtin_ia32_permti256((__m256i)(V1), (__m256i)(V2), (M)); })
#define _mm256_extracti128_si256(V, M) __extension__ ({ \
- (__m128i)__builtin_shufflevector( \
- (__v4di)(V), \
- (__v4di)(_mm256_setzero_si256()), \
- (((M) & 1) ? 2 : 0), \
- (((M) & 1) ? 3 : 1) );})
+ (__m128i)__builtin_shufflevector((__v4di)(__m256i)(V), \
+ (__v4di)_mm256_setzero_si256(), \
+ (((M) & 1) ? 2 : 0), \
+ (((M) & 1) ? 3 : 1) ); })
#define _mm256_inserti128_si256(V1, V2, M) __extension__ ({ \
- (__m256i)__builtin_shufflevector( \
- (__v4di)(V1), \
- (__v4di)_mm256_castsi128_si256((__m128i)(V2)), \
- (((M) & 1) ? 0 : 4), \
- (((M) & 1) ? 1 : 5), \
- (((M) & 1) ? 4 : 2), \
- (((M) & 1) ? 5 : 3) );})
+ (__m256i)__builtin_shufflevector((__v4di)(__m256i)(V1), \
+ (__v4di)_mm256_castsi128_si256((__m128i)(V2)), \
+ (((M) & 1) ? 0 : 4), \
+ (((M) & 1) ? 1 : 5), \
+ (((M) & 1) ? 4 : 2), \
+ (((M) & 1) ? 5 : 3) ); })
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskload_epi32(int const *__X, __m256i __M)
@@ -1012,244 +1004,211 @@ _mm_srlv_epi64(__m128i __X, __m128i __Y)
}
#define _mm_mask_i32gather_pd(a, m, i, mask, s) __extension__ ({ \
- __m128d __a = (a); \
- double const *__m = (m); \
- __m128i __i = (i); \
- __m128d __mask = (mask); \
- (__m128d)__builtin_ia32_gatherd_pd((__v2df)__a, (const __v2df *)__m, \
- (__v4si)__i, (__v2df)__mask, (s)); })
+ (__m128d)__builtin_ia32_gatherd_pd((__v2df)(__m128i)(a), \
+ (double const *)(m), \
+ (__v4si)(__m128i)(i), \
+ (__v2df)(__m128d)(mask), (s)); })
#define _mm256_mask_i32gather_pd(a, m, i, mask, s) __extension__ ({ \
- __m256d __a = (a); \
- double const *__m = (m); \
- __m128i __i = (i); \
- __m256d __mask = (mask); \
- (__m256d)__builtin_ia32_gatherd_pd256((__v4df)__a, (const __v4df *)__m, \
- (__v4si)__i, (__v4df)__mask, (s)); })
+ (__m256d)__builtin_ia32_gatherd_pd256((__v4df)(__m256d)(a), \
+ (double const *)(m), \
+ (__v4si)(__m128i)(i), \
+ (__v4df)(__m256d)(mask), (s)); })
#define _mm_mask_i64gather_pd(a, m, i, mask, s) __extension__ ({ \
- __m128d __a = (a); \
- double const *__m = (m); \
- __m128i __i = (i); \
- __m128d __mask = (mask); \
- (__m128d)__builtin_ia32_gatherq_pd((__v2df)__a, (const __v2df *)__m, \
- (__v2di)__i, (__v2df)__mask, (s)); })
+ (__m128d)__builtin_ia32_gatherq_pd((__v2df)(__m128d)(a), \
+ (double const *)(m), \
+ (__v2di)(__m128i)(i), \
+ (__v2df)(__m128d)(mask), (s)); })
#define _mm256_mask_i64gather_pd(a, m, i, mask, s) __extension__ ({ \
- __m256d __a = (a); \
- double const *__m = (m); \
- __m256i __i = (i); \
- __m256d __mask = (mask); \
- (__m256d)__builtin_ia32_gatherq_pd256((__v4df)__a, (const __v4df *)__m, \
- (__v4di)__i, (__v4df)__mask, (s)); })
+ (__m256d)__builtin_ia32_gatherq_pd256((__v4df)(__m256d)(a), \
+ (double const *)(m), \
+ (__v4di)(__m256i)(i), \
+ (__v4df)(__m256d)(mask), (s)); })
#define _mm_mask_i32gather_ps(a, m, i, mask, s) __extension__ ({ \
- __m128 __a = (a); \
- float const *__m = (m); \
- __m128i __i = (i); \
- __m128 __mask = (mask); \
- (__m128)__builtin_ia32_gatherd_ps((__v4sf)__a, (const __v4sf *)__m, \
- (__v4si)__i, (__v4sf)__mask, (s)); })
+ (__m128)__builtin_ia32_gatherd_ps((__v4sf)(__m128)(a), \
+ (float const *)(m), \
+ (__v4si)(__m128i)(i), \
+ (__v4sf)(__m128)(mask), (s)); })
#define _mm256_mask_i32gather_ps(a, m, i, mask, s) __extension__ ({ \
- __m256 __a = (a); \
- float const *__m = (m); \
- __m256i __i = (i); \
- __m256 __mask = (mask); \
- (__m256)__builtin_ia32_gatherd_ps256((__v8sf)__a, (const __v8sf *)__m, \
- (__v8si)__i, (__v8sf)__mask, (s)); })
+ (__m256)__builtin_ia32_gatherd_ps256((__v8sf)(__m256)(a), \
+ (float const *)(m), \
+ (__v8si)(__m256i)(i), \
+ (__v8sf)(__m256)(mask), (s)); })
#define _mm_mask_i64gather_ps(a, m, i, mask, s) __extension__ ({ \
- __m128 __a = (a); \
- float const *__m = (m); \
- __m128i __i = (i); \
- __m128 __mask = (mask); \
- (__m128)__builtin_ia32_gatherq_ps((__v4sf)__a, (const __v4sf *)__m, \
- (__v2di)__i, (__v4sf)__mask, (s)); })
+ (__m128)__builtin_ia32_gatherq_ps((__v4sf)(__m128)(a), \
+ (float const *)(m), \
+ (__v2di)(__m128i)(i), \
+ (__v4sf)(__m128)(mask), (s)); })
#define _mm256_mask_i64gather_ps(a, m, i, mask, s) __extension__ ({ \
- __m128 __a = (a); \
- float const *__m = (m); \
- __m256i __i = (i); \
- __m128 __mask = (mask); \
- (__m128)__builtin_ia32_gatherq_ps256((__v4sf)__a, (const __v4sf *)__m, \
- (__v4di)__i, (__v4sf)__mask, (s)); })
+ (__m128)__builtin_ia32_gatherq_ps256((__v4sf)(__m128)(a), \
+ (float const *)(m), \
+ (__v4di)(__m256i)(i), \
+ (__v4sf)(__m128)(mask), (s)); })
#define _mm_mask_i32gather_epi32(a, m, i, mask, s) __extension__ ({ \
- __m128i __a = (a); \
- int const *__m = (m); \
- __m128i __i = (i); \
- __m128i __mask = (mask); \
- (__m128i)__builtin_ia32_gatherd_d((__v4si)__a, (const __v4si *)__m, \
- (__v4si)__i, (__v4si)__mask, (s)); })
+ (__m128i)__builtin_ia32_gatherd_d((__v4si)(__m128i)(a), \
+ (int const *)(m), \
+ (__v4si)(__m128i)(i), \
+ (__v4si)(__m128i)(mask), (s)); })
#define _mm256_mask_i32gather_epi32(a, m, i, mask, s) __extension__ ({ \
- __m256i __a = (a); \
- int const *__m = (m); \
- __m256i __i = (i); \
- __m256i __mask = (mask); \
- (__m256i)__builtin_ia32_gatherd_d256((__v8si)__a, (const __v8si *)__m, \
- (__v8si)__i, (__v8si)__mask, (s)); })
+ (__m256i)__builtin_ia32_gatherd_d256((__v8si)(__m256i)(a), \
+ (int const *)(m), \
+ (__v8si)(__m256i)(i), \
+ (__v8si)(__m256i)(mask), (s)); })
#define _mm_mask_i64gather_epi32(a, m, i, mask, s) __extension__ ({ \
- __m128i __a = (a); \
- int const *__m = (m); \
- __m128i __i = (i); \
- __m128i __mask = (mask); \
- (__m128i)__builtin_ia32_gatherq_d((__v4si)__a, (const __v4si *)__m, \
- (__v2di)__i, (__v4si)__mask, (s)); })
+ (__m128i)__builtin_ia32_gatherq_d((__v4si)(__m128i)(a), \
+ (int const *)(m), \
+ (__v2di)(__m128i)(i), \
+ (__v4si)(__m128i)(mask), (s)); })
#define _mm256_mask_i64gather_epi32(a, m, i, mask, s) __extension__ ({ \
- __m128i __a = (a); \
- int const *__m = (m); \
- __m256i __i = (i); \
- __m128i __mask = (mask); \
- (__m128i)__builtin_ia32_gatherq_d256((__v4si)__a, (const __v4si *)__m, \
- (__v4di)__i, (__v4si)__mask, (s)); })
+ (__m128i)__builtin_ia32_gatherq_d256((__v4si)(__m128i)(a), \
+ (int const *)(m), \
+ (__v4di)(__m256i)(i), \
+ (__v4si)(__m128i)(mask), (s)); })
#define _mm_mask_i32gather_epi64(a, m, i, mask, s) __extension__ ({ \
- __m128i __a = (a); \
- long long const *__m = (m); \
- __m128i __i = (i); \
- __m128i __mask = (mask); \
- (__m128i)__builtin_ia32_gatherd_q((__v2di)__a, (const __v2di *)__m, \
- (__v4si)__i, (__v2di)__mask, (s)); })
+ (__m128i)__builtin_ia32_gatherd_q((__v2di)(__m128i)(a), \
+ (long long const *)(m), \
+ (__v4si)(__m128i)(i), \
+ (__v2di)(__m128i)(mask), (s)); })
#define _mm256_mask_i32gather_epi64(a, m, i, mask, s) __extension__ ({ \
- __m256i __a = (a); \
- long long const *__m = (m); \
- __m128i __i = (i); \
- __m256i __mask = (mask); \
- (__m256i)__builtin_ia32_gatherd_q256((__v4di)__a, (const __v4di *)__m, \
- (__v4si)__i, (__v4di)__mask, (s)); })
+ (__m256i)__builtin_ia32_gatherd_q256((__v4di)(__m256i)(a), \
+ (long long const *)(m), \
+ (__v4si)(__m128i)(i), \
+ (__v4di)(__m256i)(mask), (s)); })
#define _mm_mask_i64gather_epi64(a, m, i, mask, s) __extension__ ({ \
- __m128i __a = (a); \
- long long const *__m = (m); \
- __m128i __i = (i); \
- __m128i __mask = (mask); \
- (__m128i)__builtin_ia32_gatherq_q((__v2di)__a, (const __v2di *)__m, \
- (__v2di)__i, (__v2di)__mask, (s)); })
+ (__m128i)__builtin_ia32_gatherq_q((__v2di)(__m128i)(a), \
+ (long long const *)(m), \
+ (__v2di)(__m128i)(i), \
+ (__v2di)(__m128i)(mask), (s)); })
#define _mm256_mask_i64gather_epi64(a, m, i, mask, s) __extension__ ({ \
- __m256i __a = (a); \
- long long const *__m = (m); \
- __m256i __i = (i); \
- __m256i __mask = (mask); \
- (__m256i)__builtin_ia32_gatherq_q256((__v4di)__a, (const __v4di *)__m, \
- (__v4di)__i, (__v4di)__mask, (s)); })
+ (__m256i)__builtin_ia32_gatherq_q256((__v4di)(__m256i)(a), \
+ (long long const *)(m), \
+ (__v4di)(__m256i)(i), \
+ (__v4di)(__m256i)(mask), (s)); })
#define _mm_i32gather_pd(m, i, s) __extension__ ({ \
- double const *__m = (m); \
- __m128i __i = (i); \
- (__m128d)__builtin_ia32_gatherd_pd((__v2df)_mm_setzero_pd(), \
- (const __v2df *)__m, (__v4si)__i, \
- (__v2df)_mm_set1_pd((double)(long long int)-1), (s)); })
+ (__m128d)__builtin_ia32_gatherd_pd((__v2df)_mm_undefined_pd(), \
+ (double const *)(m), \
+ (__v4si)(__m128i)(i), \
+ (__v2df)_mm_cmpeq_pd(_mm_setzero_pd(), \
+ _mm_setzero_pd()), \
+ (s)); })
#define _mm256_i32gather_pd(m, i, s) __extension__ ({ \
- double const *__m = (m); \
- __m128i __i = (i); \
- (__m256d)__builtin_ia32_gatherd_pd256((__v4df)_mm256_setzero_pd(), \
- (const __v4df *)__m, (__v4si)__i, \
- (__v4df)_mm256_set1_pd((double)(long long int)-1), (s)); })
+ (__m256d)__builtin_ia32_gatherd_pd256((__v4df)_mm256_undefined_pd(), \
+ (double const *)(m), \
+ (__v4si)(__m128i)(i), \
+ (__v4df)_mm256_cmp_pd(_mm256_setzero_pd(), \
+ _mm256_setzero_pd(), \
+ _CMP_EQ_OQ), \
+ (s)); })
#define _mm_i64gather_pd(m, i, s) __extension__ ({ \
- double const *__m = (m); \
- __m128i __i = (i); \
- (__m128d)__builtin_ia32_gatherq_pd((__v2df)_mm_setzero_pd(), \
- (const __v2df *)__m, (__v2di)__i, \
- (__v2df)_mm_set1_pd((double)(long long int)-1), (s)); })
+ (__m128d)__builtin_ia32_gatherq_pd((__v2df)_mm_undefined_pd(), \
+ (double const *)(m), \
+ (__v2di)(__m128i)(i), \
+ (__v2df)_mm_cmpeq_pd(_mm_setzero_pd(), \
+ _mm_setzero_pd()), \
+ (s)); })
#define _mm256_i64gather_pd(m, i, s) __extension__ ({ \
- double const *__m = (m); \
- __m256i __i = (i); \
- (__m256d)__builtin_ia32_gatherq_pd256((__v4df)_mm256_setzero_pd(), \
- (const __v4df *)__m, (__v4di)__i, \
- (__v4df)_mm256_set1_pd((double)(long long int)-1), (s)); })
+ (__m256d)__builtin_ia32_gatherq_pd256((__v4df)_mm256_undefined_pd(), \
+ (double const *)(m), \
+ (__v4di)(__m256i)(i), \
+ (__v4df)_mm256_cmp_pd(_mm256_setzero_pd(), \
+ _mm256_setzero_pd(), \
+ _CMP_EQ_OQ), \
+ (s)); })
#define _mm_i32gather_ps(m, i, s) __extension__ ({ \
- float const *__m = (m); \
- __m128i __i = (i); \
- (__m128)__builtin_ia32_gatherd_ps((__v4sf)_mm_setzero_ps(), \
- (const __v4sf *)__m, (__v4si)__i, \
- (__v4sf)_mm_set1_ps((float)(int)-1), (s)); })
+ (__m128)__builtin_ia32_gatherd_ps((__v4sf)_mm_undefined_ps(), \
+ (float const *)(m), \
+ (__v4si)(__m128i)(i), \
+ (__v4sf)_mm_cmpeq_ps(_mm_setzero_ps(), \
+ _mm_setzero_ps()), \
+ (s)); })
#define _mm256_i32gather_ps(m, i, s) __extension__ ({ \
- float const *__m = (m); \
- __m256i __i = (i); \
- (__m256)__builtin_ia32_gatherd_ps256((__v8sf)_mm256_setzero_ps(), \
- (const __v8sf *)__m, (__v8si)__i, \
- (__v8sf)_mm256_set1_ps((float)(int)-1), (s)); })
+ (__m256)__builtin_ia32_gatherd_ps256((__v8sf)_mm256_undefined_ps(), \
+ (float const *)(m), \
+ (__v8si)(__m256i)(i), \
+ (__v8sf)_mm256_cmp_ps(_mm256_setzero_ps(), \
+ _mm256_setzero_ps(), \
+ _CMP_EQ_OQ), \
+ (s)); })
#define _mm_i64gather_ps(m, i, s) __extension__ ({ \
- float const *__m = (m); \
- __m128i __i = (i); \
- (__m128)__builtin_ia32_gatherq_ps((__v4sf)_mm_setzero_ps(), \
- (const __v4sf *)__m, (__v2di)__i, \
- (__v4sf)_mm_set1_ps((float)(int)-1), (s)); })
+ (__m128)__builtin_ia32_gatherq_ps((__v4sf)_mm_undefined_ps(), \
+ (float const *)(m), \
+ (__v2di)(__m128i)(i), \
+ (__v4sf)_mm_cmpeq_ps(_mm_setzero_ps(), \
+ _mm_setzero_ps()), \
+ (s)); })
#define _mm256_i64gather_ps(m, i, s) __extension__ ({ \
- float const *__m = (m); \
- __m256i __i = (i); \
- (__m128)__builtin_ia32_gatherq_ps256((__v4sf)_mm_setzero_ps(), \
- (const __v4sf *)__m, (__v4di)__i, \
- (__v4sf)_mm_set1_ps((float)(int)-1), (s)); })
+ (__m128)__builtin_ia32_gatherq_ps256((__v4sf)_mm_undefined_ps(), \
+ (float const *)(m), \
+ (__v4di)(__m256i)(i), \
+ (__v4sf)_mm_cmpeq_ps(_mm_setzero_ps(), \
+ _mm_setzero_ps()), \
+ (s)); })
#define _mm_i32gather_epi32(m, i, s) __extension__ ({ \
- int const *__m = (m); \
- __m128i __i = (i); \
- (__m128i)__builtin_ia32_gatherd_d((__v4si)_mm_setzero_si128(), \
- (const __v4si *)__m, (__v4si)__i, \
- (__v4si)_mm_set1_epi32(-1), (s)); })
+ (__m128i)__builtin_ia32_gatherd_d((__v4si)_mm_undefined_si128(), \
+ (int const *)(m), (__v4si)(__m128i)(i), \
+ (__v4si)_mm_set1_epi32(-1), (s)); })
#define _mm256_i32gather_epi32(m, i, s) __extension__ ({ \
- int const *__m = (m); \
- __m256i __i = (i); \
- (__m256i)__builtin_ia32_gatherd_d256((__v8si)_mm256_setzero_si256(), \
- (const __v8si *)__m, (__v8si)__i, \
- (__v8si)_mm256_set1_epi32(-1), (s)); })
+ (__m256i)__builtin_ia32_gatherd_d256((__v8si)_mm256_undefined_si256(), \
+ (int const *)(m), (__v8si)(__m256i)(i), \
+ (__v8si)_mm256_set1_epi32(-1), (s)); })
#define _mm_i64gather_epi32(m, i, s) __extension__ ({ \
- int const *__m = (m); \
- __m128i __i = (i); \
- (__m128i)__builtin_ia32_gatherq_d((__v4si)_mm_setzero_si128(), \
- (const __v4si *)__m, (__v2di)__i, \
- (__v4si)_mm_set1_epi32(-1), (s)); })
+ (__m128i)__builtin_ia32_gatherq_d((__v4si)_mm_undefined_si128(), \
+ (int const *)(m), (__v2di)(__m128i)(i), \
+ (__v4si)_mm_set1_epi32(-1), (s)); })
#define _mm256_i64gather_epi32(m, i, s) __extension__ ({ \
- int const *__m = (m); \
- __m256i __i = (i); \
- (__m128i)__builtin_ia32_gatherq_d256((__v4si)_mm_setzero_si128(), \
- (const __v4si *)__m, (__v4di)__i, \
- (__v4si)_mm_set1_epi32(-1), (s)); })
+ (__m128i)__builtin_ia32_gatherq_d256((__v4si)_mm_undefined_si128(), \
+ (int const *)(m), (__v4di)(__m256i)(i), \
+ (__v4si)_mm_set1_epi32(-1), (s)); })
#define _mm_i32gather_epi64(m, i, s) __extension__ ({ \
- long long const *__m = (m); \
- __m128i __i = (i); \
- (__m128i)__builtin_ia32_gatherd_q((__v2di)_mm_setzero_si128(), \
- (const __v2di *)__m, (__v4si)__i, \
- (__v2di)_mm_set1_epi64x(-1), (s)); })
+ (__m128i)__builtin_ia32_gatherd_q((__v2di)_mm_undefined_si128(), \
+ (long long const *)(m), \
+ (__v4si)(__m128i)(i), \
+ (__v2di)_mm_set1_epi64x(-1), (s)); })
#define _mm256_i32gather_epi64(m, i, s) __extension__ ({ \
- long long const *__m = (m); \
- __m128i __i = (i); \
- (__m256i)__builtin_ia32_gatherd_q256((__v4di)_mm256_setzero_si256(), \
- (const __v4di *)__m, (__v4si)__i, \
- (__v4di)_mm256_set1_epi64x(-1), (s)); })
+ (__m256i)__builtin_ia32_gatherd_q256((__v4di)_mm256_undefined_si256(), \
+ (long long const *)(m), \
+ (__v4si)(__m128i)(i), \
+ (__v4di)_mm256_set1_epi64x(-1), (s)); })
#define _mm_i64gather_epi64(m, i, s) __extension__ ({ \
- long long const *__m = (m); \
- __m128i __i = (i); \
- (__m128i)__builtin_ia32_gatherq_q((__v2di)_mm_setzero_si128(), \
- (const __v2di *)__m, (__v2di)__i, \
- (__v2di)_mm_set1_epi64x(-1), (s)); })
+ (__m128i)__builtin_ia32_gatherq_q((__v2di)_mm_undefined_si128(), \
+ (long long const *)(m), \
+ (__v2di)(__m128i)(i), \
+ (__v2di)_mm_set1_epi64x(-1), (s)); })
#define _mm256_i64gather_epi64(m, i, s) __extension__ ({ \
- long long const *__m = (m); \
- __m256i __i = (i); \
- (__m256i)__builtin_ia32_gatherq_q256((__v4di)_mm256_setzero_si256(), \
- (const __v4di *)__m, (__v4di)__i, \
- (__v4di)_mm256_set1_epi64x(-1), (s)); })
+ (__m256i)__builtin_ia32_gatherq_q256((__v4di)_mm256_undefined_si256(), \
+ (long long const *)(m), \
+ (__v4di)(__m256i)(i), \
+ (__v4di)_mm256_set1_epi64x(-1), (s)); })
#undef __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
index 9e8297a9..f289ed7 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512bwintrin.h
@@ -34,10 +34,10 @@ typedef char __v64qi __attribute__ ((__vector_size__ (64)));
typedef short __v32hi __attribute__ ((__vector_size__ (64)));
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512bw")))
static __inline __v64qi __DEFAULT_FN_ATTRS
-_mm512_setzero_qi (void) {
+_mm512_setzero_qi(void) {
return (__v64qi){ 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -49,7 +49,7 @@ _mm512_setzero_qi (void) {
}
static __inline __v32hi __DEFAULT_FN_ATTRS
-_mm512_setzero_hi (void) {
+_mm512_setzero_hi(void) {
return (__v32hi){ 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -363,8 +363,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_add_epi8 (__mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i) __builtin_ia32_paddb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi)
- _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) __U);
}
@@ -385,8 +384,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_sub_epi8 (__mmask64 __U, __m512i __A, __m512i __B) {
return (__m512i) __builtin_ia32_psubb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi)
- _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) __U);
}
@@ -407,8 +405,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_add_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i) __builtin_ia32_paddw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) __U);
}
@@ -429,8 +426,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_sub_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i) __builtin_ia32_psubw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) __U);
}
@@ -451,8 +447,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_mullo_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
return (__m512i) __builtin_ia32_pmullw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) __U);
}
@@ -476,7 +471,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_abs_epi8 (__m512i __A)
{
return (__m512i) __builtin_ia32_pabsb512_mask ((__v64qi) __A,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -492,7 +487,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_abs_epi8 (__mmask64 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_pabsb512_mask ((__v64qi) __A,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) __U);
}
@@ -500,7 +495,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_abs_epi16 (__m512i __A)
{
return (__m512i) __builtin_ia32_pabsw512_mask ((__v32hi) __A,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -516,7 +511,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_abs_epi16 (__mmask32 __U, __m512i __A)
{
return (__m512i) __builtin_ia32_pabsw512_mask ((__v32hi) __A,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) __U);
}
@@ -525,7 +520,7 @@ _mm512_packs_epi32 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_packssdw512_mask ((__v16si) __A,
(__v16si) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -553,7 +548,7 @@ _mm512_packs_epi16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_packsswb512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -581,7 +576,7 @@ _mm512_packus_epi32 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_packusdw512_mask ((__v16si) __A,
(__v16si) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -609,7 +604,7 @@ _mm512_packus_epi16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_packuswb512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -637,7 +632,7 @@ _mm512_adds_epi8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -656,7 +651,7 @@ _mm512_maskz_adds_epi8 (__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddsb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) __U);
}
@@ -665,7 +660,7 @@ _mm512_adds_epi16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -684,7 +679,7 @@ _mm512_maskz_adds_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddsw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) __U);
}
@@ -693,7 +688,7 @@ _mm512_adds_epu8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -712,7 +707,7 @@ _mm512_maskz_adds_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddusb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) __U);
}
@@ -721,7 +716,7 @@ _mm512_adds_epu16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -740,7 +735,7 @@ _mm512_maskz_adds_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_paddusw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) __U);
}
@@ -749,7 +744,7 @@ _mm512_avg_epu8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pavgb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -777,7 +772,7 @@ _mm512_avg_epu16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pavgw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -805,7 +800,7 @@ _mm512_max_epi8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pmaxsb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -833,7 +828,7 @@ _mm512_max_epi16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pmaxsw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -861,7 +856,7 @@ _mm512_max_epu8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pmaxub512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -889,7 +884,7 @@ _mm512_max_epu16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pmaxuw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -917,7 +912,7 @@ _mm512_min_epi8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pminsb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -945,7 +940,7 @@ _mm512_min_epi16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pminsw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -973,7 +968,7 @@ _mm512_min_epu8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pminub512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -1001,7 +996,7 @@ _mm512_min_epu16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pminuw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -1029,7 +1024,7 @@ _mm512_shuffle_epi8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pshufb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -1048,7 +1043,7 @@ _mm512_maskz_shuffle_epi8 (__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_pshufb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) __U);
}
@@ -1057,7 +1052,7 @@ _mm512_subs_epi8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -1076,7 +1071,7 @@ _mm512_maskz_subs_epi8 (__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubsb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) __U);
}
@@ -1085,7 +1080,7 @@ _mm512_subs_epi16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -1104,7 +1099,7 @@ _mm512_maskz_subs_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubsw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) __U);
}
@@ -1113,7 +1108,7 @@ _mm512_subs_epu8 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) -1);
}
@@ -1132,7 +1127,7 @@ _mm512_maskz_subs_epu8 (__mmask64 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubusb512_mask ((__v64qi) __A,
(__v64qi) __B,
- (__v64qi) _mm512_setzero_qi (),
+ (__v64qi) _mm512_setzero_qi(),
(__mmask64) __U);
}
@@ -1141,7 +1136,7 @@ _mm512_subs_epu16 (__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) -1);
}
@@ -1160,7 +1155,7 @@ _mm512_maskz_subs_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_psubusw512_mask ((__v32hi) __A,
(__v32hi) __B,
- (__v32hi) _mm512_setzero_hi (),
+ (__v32hi) _mm512_setzero_hi(),
(__mmask32) __U);
}
@@ -1204,6 +1199,303 @@ _mm512_maskz_permutex2var_epi16 (__mmask32 __U, __m512i __A,
(__mmask32) __U);
}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mulhrs_epi16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmulhrsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_mulhrs_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmulhrsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_mulhrs_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmulhrsw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mulhi_epi16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmulhw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_mulhi_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmulhw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_mulhi_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmulhw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mulhi_epu16 (__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmulhuw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_mulhi_epu16 (__m512i __W, __mmask32 __U, __m512i __A,
+ __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmulhuw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_mulhi_epu16 (__mmask32 __U, __m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_pmulhuw512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maddubs_epi16 (__m512i __X, __m512i __Y) {
+ return (__m512i) __builtin_ia32_pmaddubsw512_mask ((__v64qi) __X,
+ (__v64qi) __Y,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_maddubs_epi16 (__m512i __W, __mmask32 __U, __m512i __X,
+ __m512i __Y) {
+ return (__m512i) __builtin_ia32_pmaddubsw512_mask ((__v64qi) __X,
+ (__v64qi) __Y,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_maddubs_epi16 (__mmask32 __U, __m512i __X, __m512i __Y) {
+ return (__m512i) __builtin_ia32_pmaddubsw512_mask ((__v64qi) __X,
+ (__v64qi) __Y,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_madd_epi16 (__m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_pmaddwd512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v16si) _mm512_setzero_si512(),
+ (__mmask16) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_madd_epi16 (__m512i __W, __mmask16 __U, __m512i __A,
+ __m512i __B) {
+ return (__m512i) __builtin_ia32_pmaddwd512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v16si) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_madd_epi16 (__mmask16 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_pmaddwd512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v16si) _mm512_setzero_si512(),
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm512_cvtsepi16_epi8 (__m512i __A) {
+ return (__m256i) __builtin_ia32_pmovswb512_mask ((__v32hi) __A,
+ (__v32qi)_mm256_setzero_si256(),
+ (__mmask32) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm512_mask_cvtsepi16_epi8 (__m256i __O, __mmask32 __M, __m512i __A) {
+ return (__m256i) __builtin_ia32_pmovswb512_mask ((__v32hi) __A,
+ (__v32qi)__O,
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm512_maskz_cvtsepi16_epi8 (__mmask32 __M, __m512i __A) {
+ return (__m256i) __builtin_ia32_pmovswb512_mask ((__v32hi) __A,
+ (__v32qi) _mm256_setzero_si256(),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm512_cvtusepi16_epi8 (__m512i __A) {
+ return (__m256i) __builtin_ia32_pmovuswb512_mask ((__v32hi) __A,
+ (__v32qi) _mm256_setzero_si256(),
+ (__mmask32) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm512_mask_cvtusepi16_epi8 (__m256i __O, __mmask32 __M, __m512i __A) {
+ return (__m256i) __builtin_ia32_pmovuswb512_mask ((__v32hi) __A,
+ (__v32qi) __O,
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm512_maskz_cvtusepi16_epi8 (__mmask32 __M, __m512i __A) {
+ return (__m256i) __builtin_ia32_pmovuswb512_mask ((__v32hi) __A,
+ (__v32qi) _mm256_setzero_si256(),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm512_cvtepi16_epi8 (__m512i __A) {
+ return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A,
+ (__v32qi) _mm256_setzero_si256(),
+ (__mmask32) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm512_mask_cvtepi16_epi8 (__m256i __O, __mmask32 __M, __m512i __A) {
+ return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A,
+ (__v32qi) __O,
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm512_maskz_cvtepi16_epi8 (__mmask32 __M, __m512i __A) {
+ return (__m256i) __builtin_ia32_pmovwb512_mask ((__v32hi) __A,
+ (__v32qi) _mm256_setzero_si256(),
+ __M);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_unpackhi_epi8 (__m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_punpckhbw512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi(),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_unpackhi_epi8 (__m512i __W, __mmask64 __U, __m512i __A,
+ __m512i __B) {
+ return (__m512i) __builtin_ia32_punpckhbw512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_unpackhi_epi8 (__mmask64 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_punpckhbw512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi(),
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_unpackhi_epi16 (__m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_punpckhwd512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_unpackhi_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
+ __m512i __B) {
+ return (__m512i) __builtin_ia32_punpckhwd512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_unpackhi_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_punpckhwd512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_unpacklo_epi8 (__m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_punpcklbw512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi(),
+ (__mmask64) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_unpacklo_epi8 (__m512i __W, __mmask64 __U, __m512i __A,
+ __m512i __B) {
+ return (__m512i) __builtin_ia32_punpcklbw512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) __W,
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_unpacklo_epi8 (__mmask64 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_punpcklbw512_mask ((__v64qi) __A,
+ (__v64qi) __B,
+ (__v64qi) _mm512_setzero_qi(),
+ (__mmask64) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_unpacklo_epi16 (__m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_punpcklwd512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) -1);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_unpacklo_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
+ __m512i __B) {
+ return (__m512i) __builtin_ia32_punpcklwd512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_unpacklo_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
+ return (__m512i) __builtin_ia32_punpcklwd512_mask ((__v32hi) __A,
+ (__v32hi) __B,
+ (__v32hi) _mm512_setzero_hi(),
+ (__mmask32) __U);
+}
+
#define _mm512_cmp_epi8_mask(a, b, p) __extension__ ({ \
(__mmask16)__builtin_ia32_cmpb512_mask((__v64qi)(__m512i)(a), \
(__v64qi)(__m512i)(b), \
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h
index c946de2..afee490 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512dqintrin.h
@@ -29,7 +29,7 @@
#define __AVX512DQINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512dq")))
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mullo_epi64 (__m512i __A, __m512i __B) {
@@ -237,6 +237,542 @@ _mm512_maskz_andnot_ps (__mmask16 __U, __m512 __A, __m512 __B) {
(__mmask16) __U);
}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_cvtpd_epi64 (__m512d __A) {
+ return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_cvtpd_epi64 (__m512i __W, __mmask8 __U, __m512d __A) {
+ return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A,
+ (__v8di) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_cvtpd_epi64 (__mmask8 __U, __m512d __A) {
+ return (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvt_roundpd_epi64(__A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_cvt_roundpd_epi64(__W, __U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A, \
+ (__v8di) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_cvt_roundpd_epi64(__U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtpd2qq512_mask ((__v8df) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) __U, __R); })
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_cvtpd_epu64 (__m512d __A) {
+ return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_cvtpd_epu64 (__m512i __W, __mmask8 __U, __m512d __A) {
+ return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A,
+ (__v8di) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_cvtpd_epu64 (__mmask8 __U, __m512d __A) {
+ return (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvt_roundpd_epu64(__A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_cvt_roundpd_epu64(__W, __U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A, \
+ (__v8di) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_cvt_roundpd_epu64(__U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtpd2uqq512_mask ((__v8df) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) __U, __R);})
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_cvtps_epi64 (__m256 __A) {
+ return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_cvtps_epi64 (__m512i __W, __mmask8 __U, __m256 __A) {
+ return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A,
+ (__v8di) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_cvtps_epi64 (__mmask8 __U, __m256 __A) {
+ return (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvt_roundps_epi64(__A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_cvt_roundps_epi64(__W, __U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A, \
+ (__v8di) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_cvt_roundps_epi64(__U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtps2qq512_mask ((__v8sf) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) __U, __R);})
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_cvtps_epu64 (__m256 __A) {
+ return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_cvtps_epu64 (__m512i __W, __mmask8 __U, __m256 __A) {
+ return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A,
+ (__v8di) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_cvtps_epu64 (__mmask8 __U, __m256 __A) {
+ return (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvt_roundps_epu64(__A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_cvt_roundps_epu64(__W, __U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A, \
+ (__v8di) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_cvt_roundps_epu64(__U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvtps2uqq512_mask ((__v8sf) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) __U, __R);})
+
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_cvtepi64_pd (__m512i __A) {
+ return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A,
+ (__v8df) _mm512_setzero_pd(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_cvtepi64_pd (__m512d __W, __mmask8 __U, __m512i __A) {
+ return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A,
+ (__v8df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_cvtepi64_pd (__mmask8 __U, __m512i __A) {
+ return (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A,
+ (__v8df) _mm512_setzero_pd(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvt_roundepi64_pd(__A, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_cvt_roundepi64_pd(__W, __U, __A, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A, \
+ (__v8df) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_cvt_roundepi64_pd(__U, __A, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_cvtqq2pd512_mask ((__v8di) __A, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) __U, __R);})
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm512_cvtepi64_ps (__m512i __A) {
+ return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A,
+ (__v8sf) _mm256_setzero_ps(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm512_mask_cvtepi64_ps (__m256 __W, __mmask8 __U, __m512i __A) {
+ return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A,
+ (__v8sf) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm512_maskz_cvtepi64_ps (__mmask8 __U, __m512i __A) {
+ return (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A,
+ (__v8sf) _mm256_setzero_ps(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvt_roundepi64_ps(__A, __R) __extension__ ({ \
+ (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A, \
+ (__v8sf) _mm256_setzero_ps(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_cvt_roundepi64_ps(__W, __U, __A, __R) __extension__ ({ \
+ (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A, \
+ (__v8sf) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_cvt_roundepi64_ps(__U, __A, __R) __extension__ ({ \
+ (__m256) __builtin_ia32_cvtqq2ps512_mask ((__v8di) __A, \
+ (__v8sf) _mm256_setzero_ps(), (__mmask8) __U, __R);})
+
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_cvttpd_epi64 (__m512d __A) {
+ return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_cvttpd_epi64 (__m512i __W, __mmask8 __U, __m512d __A) {
+ return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A,
+ (__v8di) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_cvttpd_epi64 (__mmask8 __U, __m512d __A) {
+ return (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvtt_roundpd_epi64(__A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_cvtt_roundpd_epi64(__W, __U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A, \
+ (__v8di) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_cvtt_roundpd_epi64(__U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttpd2qq512_mask ((__v8df) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) __U, __R);})
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_cvttpd_epu64 (__m512d __A) {
+ return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_cvttpd_epu64 (__m512i __W, __mmask8 __U, __m512d __A) {
+ return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A,
+ (__v8di) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_cvttpd_epu64 (__mmask8 __U, __m512d __A) {
+ return (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvtt_roundpd_epu64(__A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_cvtt_roundpd_epu64(__W, __U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A, \
+ (__v8di) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_cvtt_roundpd_epu64(__U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttpd2uqq512_mask ((__v8df) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) __U, __R);})
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_cvttps_epi64 (__m256 __A) {
+ return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_cvttps_epi64 (__m512i __W, __mmask8 __U, __m256 __A) {
+ return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A,
+ (__v8di) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_cvttps_epi64 (__mmask8 __U, __m256 __A) {
+ return (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvtt_roundps_epi64(__A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_cvtt_roundps_epi64(__W, __U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A, \
+ (__v8di) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_cvtt_roundps_epi64(__U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttps2qq512_mask ((__v8sf) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) __U, __R);})
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_cvttps_epu64 (__m256 __A) {
+ return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_cvttps_epu64 (__m512i __W, __mmask8 __U, __m256 __A) {
+ return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A,
+ (__v8di) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_cvttps_epu64 (__mmask8 __U, __m256 __A) {
+ return (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A,
+ (__v8di) _mm512_setzero_si512(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvtt_roundps_epu64(__A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A, \
+ (__v8di) _mm512_setzero_si512(),(__mmask8) -1, __R);})
+
+#define _mm512_mask_cvtt_roundps_epu64(__W, __U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A, \
+ (__v8di) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_cvtt_roundps_epu64(__U, __A, __R) __extension__ ({ \
+ (__m512i) __builtin_ia32_cvttps2uqq512_mask ((__v8sf) __A, \
+ (__v8di) _mm512_setzero_si512(), (__mmask8) __U, __R);})
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_cvtepu64_pd (__m512i __A) {
+ return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A,
+ (__v8df) _mm512_setzero_pd(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_cvtepu64_pd (__m512d __W, __mmask8 __U, __m512i __A) {
+ return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A,
+ (__v8df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_cvtepu64_pd (__mmask8 __U, __m512i __A) {
+ return (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A,
+ (__v8df) _mm512_setzero_pd(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvt_roundepu64_pd(__A, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_cvt_roundepu64_pd(__W, __U, __A, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A, \
+ (__v8df) __W, (__mmask8) __U, __R);})
+
+
+#define _mm512_maskz_cvt_roundepu64_pd(__U, __A, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_cvtuqq2pd512_mask ((__v8di) __A, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) __U, __R);})
+
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm512_cvtepu64_ps (__m512i __A) {
+ return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A,
+ (__v8sf) _mm256_setzero_ps(),
+ (__mmask8) -1,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm512_mask_cvtepu64_ps (__m256 __W, __mmask8 __U, __m512i __A) {
+ return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A,
+ (__v8sf) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm512_maskz_cvtepu64_ps (__mmask8 __U, __m512i __A) {
+ return (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A,
+ (__v8sf) _mm256_setzero_ps(),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_cvt_roundepu64_ps(__A, __R) __extension__ ({ \
+ (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A, \
+ (__v8sf) _mm256_setzero_ps(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_cvt_roundepu64_ps(__W, __U, __A, __R) __extension__ ({ \
+ (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A, \
+ (__v8sf) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_cvt_roundepu64_ps(__U, __A, __R) __extension__ ({ \
+ (__m256) __builtin_ia32_cvtuqq2ps512_mask ((__v8di) __A, \
+ (__v8sf) _mm256_setzero_ps(), (__mmask8) __U, __R);})
+
+#define _mm512_range_pd(__A, __B, __C) __extension__ ({ \
+ (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, (__v8df) __B, __C,\
+ (__v8df) _mm512_setzero_pd(), (__mmask8) -1, \
+ _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_mask_range_pd(__W, __U, __A, __B, __C) __extension__ ({ \
+ (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, (__v8df) __B, __C,\
+ (__v8df) __W, (__mmask8) __U, _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_maskz_range_pd(__U, __A, __B, __C) __extension__ ({ \
+ (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, (__v8df) __B, __C, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) __U, \
+ _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_range_round_pd(__A, __B, __C, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, (__v8df) __B, __C, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_range_round_pd(__W, __U, __A, __B, __C, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, (__v8df) __B, __C, \
+ (__v8df) __W, (__mmask8) __U, __R);})
+
+#define _mm512_maskz_range_round_pd(__U, __A, __B, __C, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_rangepd512_mask ((__v8df) __A, (__v8df) __B, __C, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) __U, __R);})
+
+#define _mm512_range_ps(__A, __B, __C) __extension__ ({ \
+ (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A, (__v16sf) __B, __C, \
+ (__v16sf) _mm512_setzero_ps(), (__mmask16) -1, \
+ _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_mask_range_ps(__W, __U, __A, __B, __C) __extension__ ({ \
+ (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ __C, (__v16sf) __W, (__mmask16) __U, _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_maskz_range_ps(__U, __A, __B, __C) __extension__ ({ \
+ (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A,(__v16sf) __B, \
+ __C, (__v16sf) _mm512_setzero_ps(), (__mmask16) __U, \
+ _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_range_round_ps(__A, __B, __C, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ __C, (__v16sf) _mm512_setzero_ps(), (__mmask16) -1, __R);})
+
+#define _mm512_mask_range_round_ps(__W, __U, __A, __B, __C, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ __C, (__v16sf) __W, (__mmask16) __U, __R);})
+
+#define _mm512_maskz_range_round_ps(__U, __A, __B, __C, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_rangeps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ __C, (__v16sf) _mm512_setzero_ps(), (__mmask16) __U, __R);})
+
+#define _mm512_reduce_pd(__A, __B) __extension__ ({ \
+ (__m512d) __builtin_ia32_reducepd512_mask ((__v8df) __A, __B, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) -1, _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_mask_reduce_pd(__W, __U, __A, __B) __extension__ ({ \
+ (__m512d) __builtin_ia32_reducepd512_mask ((__v8df) __A, __B, \
+ (__v8df) __W,(__mmask8) __U, _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_maskz_reduce_pd(__U, __A, __B) __extension__ ({ \
+ (__m512d) __builtin_ia32_reducepd512_mask ((__v8df) __A, __B, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) __U, _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_reduce_ps(__A, __B) __extension__ ({ \
+ (__m512) __builtin_ia32_reduceps512_mask ((__v16sf) __A, __B, \
+ (__v16sf) _mm512_setzero_ps(), (__mmask16) -1, _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_mask_reduce_ps(__W, __U, __A, __B) __extension__ ({ \
+ (__m512) __builtin_ia32_reduceps512_mask ((__v16sf) __A, __B, \
+ (__v16sf) __W, (__mmask16) __U, _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_maskz_reduce_ps(__U, __A, __B) __extension__ ({ \
+ (__m512) __builtin_ia32_reduceps512_mask ((__v16sf) __A, __B, \
+ (__v16sf) _mm512_setzero_ps(), (__mmask16) __U, _MM_FROUND_CUR_DIRECTION);})
+
+#define _mm512_reduce_round_pd(__A, __B, __R) __extension__ ({\
+ (__m512d) __builtin_ia32_reducepd512_mask ((__v8df) __A, __B, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) -1, __R);})
+
+#define _mm512_mask_reduce_round_pd(__W, __U, __A, __B, __R) __extension__ ({\
+ (__m512d) __builtin_ia32_reducepd512_mask ((__v8df) __A, __B, \
+ (__v8df) __W,(__mmask8) __U, __R);})
+
+#define _mm512_maskz_reduce_round_pd(__U, __A, __B, __R) __extension__ ({\
+ (__m512d) __builtin_ia32_reducepd512_mask ((__v8df) __A, __B, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) __U, __R);})
+
+#define _mm512_reduce_round_ps(__A, __B, __R) __extension__ ({\
+ (__m512) __builtin_ia32_reduceps512_mask ((__v16sf) __A, __B, \
+ (__v16sf) _mm512_setzero_ps(), (__mmask16) -1, __R);})
+
+#define _mm512_mask_reduce_round_ps(__W, __U, __A, __B, __R) __extension__ ({\
+ (__m512) __builtin_ia32_reduceps512_mask ((__v16sf) __A, __B, \
+ (__v16sf) __W, (__mmask16) __U, __R);})
+
+#define _mm512_maskz_reduce_round_ps(__U, __A, __B, __R) __extension__ ({\
+ (__m512) __builtin_ia32_reduceps512_mask ((__v16sf) __A, __B, \
+ (__v16sf) _mm512_setzero_ps(), (__mmask16) __U, __R);})
+
#undef __DEFAULT_FN_ATTRS
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h
index 56edffc..40a9121 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512erintrin.h
@@ -1,4 +1,4 @@
-/*===---- avx512fintrin.h - AVX2 intrinsics -----------------------------------===
+/*===---- avx512erintrin.h - AVX512ER intrinsics ---------------------------===
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -126,19 +126,19 @@
_mm512_maskz_rsqrt28_round_ps((M), (A), _MM_FROUND_CUR_DIRECTION)
#define _mm_rsqrt28_round_ss(A, B, R) __extension__ ({ \
- (__m128)__builtin_ia32_rsqrt28ss_mask((__v4sf)(__m128)(A), \
+ (__m128)__builtin_ia32_rsqrt28ss_round((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)-1, (R)); })
#define _mm_mask_rsqrt28_round_ss(S, M, A, B, R) __extension__ ({ \
- (__m128)__builtin_ia32_rsqrt28ss_mask((__v4sf)(__m128)(A), \
+ (__m128)__builtin_ia32_rsqrt28ss_round((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(S), \
(__mmask8)(M), (R)); })
#define _mm_maskz_rsqrt28_round_ss(M, A, B, R) __extension__ ({ \
- (__m128)__builtin_ia32_rsqrt28ss_mask((__v4sf)(__m128)(A), \
+ (__m128)__builtin_ia32_rsqrt28ss_round((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)(M), (R)); })
@@ -153,19 +153,19 @@
_mm_maskz_rsqrt28_round_ss((M), (A), (B), _MM_FROUND_CUR_DIRECTION)
#define _mm_rsqrt28_round_sd(A, B, R) __extension__ ({ \
- (__m128d)__builtin_ia32_rsqrt28sd_mask((__v2df)(__m128d)(A), \
+ (__m128d)__builtin_ia32_rsqrt28sd_round((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)-1, (R)); })
#define _mm_mask_rsqrt28_round_sd(S, M, A, B, R) __extension__ ({ \
- (__m128d)__builtin_ia32_rsqrt28sd_mask((__v2df)(__m128d)(A), \
+ (__m128d)__builtin_ia32_rsqrt28sd_round((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(S), \
(__mmask8)(M), (R)); })
#define _mm_maskz_rsqrt28_round_sd(M, A, B, R) __extension__ ({ \
- (__m128d)__builtin_ia32_rsqrt28sd_mask((__v2df)(__m128d)(A), \
+ (__m128d)__builtin_ia32_rsqrt28sd_round((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)(M), (R)); })
@@ -229,19 +229,19 @@
_mm512_maskz_rcp28_round_ps((M), (A), _MM_FROUND_CUR_DIRECTION)
#define _mm_rcp28_round_ss(A, B, R) __extension__ ({ \
- (__m128)__builtin_ia32_rcp28ss_mask((__v4sf)(__m128)(A), \
+ (__m128)__builtin_ia32_rcp28ss_round((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)-1, (R)); })
#define _mm_mask_rcp28_round_ss(S, M, A, B, R) __extension__ ({ \
- (__m128)__builtin_ia32_rcp28ss_mask((__v4sf)(__m128)(A), \
+ (__m128)__builtin_ia32_rcp28ss_round((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)(__m128)(S), \
(__mmask8)(M), (R)); })
#define _mm_maskz_rcp28_round_ss(M, A, B, R) __extension__ ({ \
- (__m128)__builtin_ia32_rcp28ss_mask((__v4sf)(__m128)(A), \
+ (__m128)__builtin_ia32_rcp28ss_round((__v4sf)(__m128)(A), \
(__v4sf)(__m128)(B), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8)(M), (R)); })
@@ -256,19 +256,19 @@
_mm_maskz_rcp28_round_ss((M), (A), (B), _MM_FROUND_CUR_DIRECTION)
#define _mm_rcp28_round_sd(A, B, R) __extension__ ({ \
- (__m128d)__builtin_ia32_rcp28sd_mask((__v2df)(__m128d)(A), \
+ (__m128d)__builtin_ia32_rcp28sd_round((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)-1, (R)); })
#define _mm_mask_rcp28_round_sd(S, M, A, B, R) __extension__ ({ \
- (__m128d)__builtin_ia32_rcp28sd_mask((__v2df)(__m128d)(A), \
+ (__m128d)__builtin_ia32_rcp28sd_round((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)(__m128d)(S), \
(__mmask8)(M), (R)); })
#define _mm_maskz_rcp28_round_sd(M, A, B, R) __extension__ ({ \
- (__m128d)__builtin_ia32_rcp28sd_mask((__v2df)(__m128d)(A), \
+ (__m128d)__builtin_ia32_rcp28sd_round((__v2df)(__m128d)(A), \
(__v2df)(__m128d)(B), \
(__v2df)_mm_setzero_pd(), \
(__mmask8)(M), (R)); })
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
index 4f7cba0..8dcdc71 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512fintrin.h
@@ -1,4 +1,4 @@
-/*===---- avx512fintrin.h - AVX2 intrinsics --------------------------------===
+/*===---- avx512fintrin.h - AVX512F intrinsics -----------------------------===
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -47,7 +47,7 @@ typedef unsigned short __mmask16;
#define _MM_FROUND_CUR_DIRECTION 0x04
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512f")))
/* Create vectors with repeated elements */
@@ -57,6 +57,30 @@ _mm512_setzero_si512(void)
return (__m512i)(__v8di){ 0, 0, 0, 0, 0, 0, 0, 0 };
}
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_undefined_pd()
+{
+ return (__m512d)__builtin_ia32_undef512();
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_undefined()
+{
+ return (__m512)__builtin_ia32_undef512();
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_undefined_ps()
+{
+ return (__m512)__builtin_ia32_undef512();
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_undefined_epi32()
+{
+ return (__m512i)__builtin_ia32_undef512();
+}
+
static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_set1_epi32(__mmask16 __M, int __A)
{
@@ -543,6 +567,66 @@ _mm512_max_ps(__m512 __A, __m512 __B)
_MM_FROUND_CUR_DIRECTION);
}
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_max_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_maxss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_max_ss(__mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_maxss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) _mm_setzero_ps (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm_max_round_ss(__A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_maxss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) -1, __R); })
+
+#define _mm_mask_max_round_ss(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_maxss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_max_round_ss(__U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_maxss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) __U,__R); })
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_max_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_maxsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_max_sd(__mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_maxsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) _mm_setzero_pd (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm_max_round_sd(__A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_maxsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) -1, __R); })
+
+#define _mm_mask_max_round_sd(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_maxsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_max_round_sd(__U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_maxsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) __U,__R); })
+
static __inline __m512i
__DEFAULT_FN_ATTRS
_mm512_max_epi32(__m512i __A, __m512i __B)
@@ -606,6 +690,66 @@ _mm512_min_ps(__m512 __A, __m512 __B)
_MM_FROUND_CUR_DIRECTION);
}
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_min_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_minss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_min_ss(__mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_minss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) _mm_setzero_ps (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm_min_round_ss(__A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_minss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) -1, __R); })
+
+#define _mm_mask_min_round_ss(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_minss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_min_round_ss(__U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_minss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) __U,__R); })
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_min_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_minsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_min_sd(__mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_minsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) _mm_setzero_pd (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm_min_round_sd(__A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_minsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) -1, __R); })
+
+#define _mm_mask_min_round_sd(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_minsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_min_round_sd(__U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_minsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) __U,__R); })
+
static __inline __m512i
__DEFAULT_FN_ATTRS
_mm512_min_epi32(__m512i __A, __m512i __B)
@@ -728,18 +872,18 @@ _mm512_mask_mullo_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_sqrt_pd(__m512d a)
+_mm512_sqrt_pd(__m512d __a)
{
- return (__m512d)__builtin_ia32_sqrtpd512_mask((__v8df)a,
+ return (__m512d)__builtin_ia32_sqrtpd512_mask((__v8df)__a,
(__v8df) _mm512_setzero_pd (),
(__mmask8) -1,
_MM_FROUND_CUR_DIRECTION);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_sqrt_ps(__m512 a)
+_mm512_sqrt_ps(__m512 __a)
{
- return (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)a,
+ return (__m512)__builtin_ia32_sqrtps512_mask((__v16sf)__a,
(__v16sf) _mm512_setzero_ps (),
(__mmask16) -1,
_MM_FROUND_CUR_DIRECTION);
@@ -765,7 +909,7 @@ _mm512_rsqrt14_ps(__m512 __A)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_rsqrt14_ss(__m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_rsqrt14ss_mask ((__v4sf) __A,
+ return (__m128) __builtin_ia32_rsqrt14ss ((__v4sf) __A,
(__v4sf) __B,
(__v4sf)
_mm_setzero_ps (),
@@ -775,7 +919,7 @@ _mm_rsqrt14_ss(__m128 __A, __m128 __B)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_rsqrt14_sd(__m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_rsqrt14sd_mask ((__v2df) __A,
+ return (__m128d) __builtin_ia32_rsqrt14sd ((__v2df) __A,
(__v2df) __B,
(__v2df)
_mm_setzero_pd (),
@@ -802,7 +946,7 @@ _mm512_rcp14_ps(__m512 __A)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_rcp14_ss(__m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_rcp14ss_mask ((__v4sf) __A,
+ return (__m128) __builtin_ia32_rcp14ss ((__v4sf) __A,
(__v4sf) __B,
(__v4sf)
_mm_setzero_ps (),
@@ -812,7 +956,7 @@ _mm_rcp14_ss(__m128 __A, __m128 __B)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_rcp14_sd(__m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_rcp14sd_mask ((__v2df) __A,
+ return (__m128d) __builtin_ia32_rcp14sd ((__v2df) __A,
(__v2df) __B,
(__v2df)
_mm_setzero_pd (),
@@ -873,6 +1017,489 @@ _mm512_abs_epi32(__m512i __A)
(__mmask16) -1);
}
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_add_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_addss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_add_ss(__mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_addss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) _mm_setzero_ps (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm_add_round_ss(__A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_addss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) -1, __R); })
+
+#define _mm_mask_add_round_ss(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_addss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_add_round_ss(__U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_addss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) __U,__R); })
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_add_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_addsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_add_sd(__mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_addsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) _mm_setzero_pd (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+#define _mm_add_round_sd(__A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_addsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) -1, __R); })
+
+#define _mm_mask_add_round_sd(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_addsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_add_round_sd(__U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_addsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) __U,__R); })
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_add_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_addpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_add_pd(__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_addpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) _mm512_setzero_pd (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_add_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __W,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_add_ps(__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) _mm512_setzero_ps (),
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_add_round_pd(__A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_addpd512_mask ((__v8df) __A, (__v8df) __B, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) -1, __R); })
+
+#define _mm512_mask_add_round_pd(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_addpd512_mask((__v8df) __A, (__v8df) __B, \
+ (__v8df) __W, (__mmask8) __U, __R); })
+
+#define _mm512_maskz_add_round_pd(__U, __A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_addpd512_mask ((__v8df) __A, (__v8df) __B, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) __U, __R); })
+
+#define _mm512_add_round_ps(__A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) _mm512_setzero_ps(), (__mmask16) -1, __R); })
+
+#define _mm512_mask_add_round_ps(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) __W, (__mmask16)__U, __R); })
+
+#define _mm512_maskz_add_round_ps(__U, __A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) _mm512_setzero_ps(), (__mmask16)__U, __R); })
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_sub_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_subss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_sub_ss(__mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_subss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) _mm_setzero_ps (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+#define _mm_sub_round_ss(__A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_subss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) -1, __R); })
+
+#define _mm_mask_sub_round_ss(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_subss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_sub_round_ss(__U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_subss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) __U,__R); })
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_sub_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_subsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_sub_sd(__mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_subsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) _mm_setzero_pd (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm_sub_round_sd(__A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_subsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) -1, __R); })
+
+#define _mm_mask_sub_round_sd(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_subsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_sub_round_sd(__U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_subsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) __U,__R); })
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_sub_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_sub_pd(__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df)
+ _mm512_setzero_pd (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_sub_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __W,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_sub_ps(__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf)
+ _mm512_setzero_ps (),
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_sub_round_pd(__A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A, (__v8df) __B,\
+ (__v8df) _mm512_setzero_pd(), (__mmask8) -1, __R); })
+
+#define _mm512_mask_sub_round_pd(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A, (__v8df) __B, \
+ (__v8df) __W, (__mmask8) __U, __R); })
+
+#define _mm512_maskz_sub_round_pd(__U, __A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A, (__v8df) __B, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) __U, __R);})
+
+#define _mm512_sub_round_ps(__A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) _mm512_setzero_ps (), (__mmask16) -1, __R);})
+
+#define _mm512_mask_sub_round_ps(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) __W, (__mmask16) __U, __R); });
+
+#define _mm512_maskz_sub_round_ps(__U, __A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) _mm512_setzero_ps (), (__mmask16) __U, __R);});
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_mul_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_mulss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_mul_ss(__mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_mulss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) _mm_setzero_ps (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+#define _mm_mul_round_ss(__A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_mulss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) -1, __R); })
+
+#define _mm_mask_mul_round_ss(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_mulss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_mul_round_ss(__U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_mulss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) __U,__R); })
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_mul_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_mulsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_mul_sd(__mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_mulsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) _mm_setzero_pd (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm_mul_round_sd(__A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_mulsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) -1, __R); })
+
+#define _mm_mask_mul_round_sd(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_mulsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_mul_round_sd(__U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_mulsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) __U,__R); })
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_mul_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_mul_pd(__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df)
+ _mm512_setzero_pd (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_mul_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __W,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_mul_ps(__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf)
+ _mm512_setzero_ps (),
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_mul_round_pd(__A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A, (__v8df) __B,\
+ (__v8df) _mm512_setzero_pd(), (__mmask8) -1, __R); })
+
+#define _mm512_mask_mul_round_pd(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A, (__v8df) __B, \
+ (__v8df) __W, (__mmask8) __U, __R); })
+
+#define _mm512_maskz_mul_round_pd(__U, __A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A, (__v8df) __B, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) __U, __R);})
+
+#define _mm512_mul_round_ps(__A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) _mm512_setzero_ps (), (__mmask16) -1, __R);})
+
+#define _mm512_mask_mul_round_ps(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) __W, (__mmask16) __U, __R); });
+
+#define _mm512_maskz_mul_round_ps(__U, __A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) _mm512_setzero_ps (), (__mmask16) __U, __R);});
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_div_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_divss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_div_ss(__mmask8 __U,__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_divss_round ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) _mm_setzero_ps (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm_div_round_ss(__A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_divss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) -1, __R); })
+
+#define _mm_mask_div_round_ss(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_divss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_div_round_ss(__U, __A, __B, __R) __extension__ ({ \
+ (__m128) __builtin_ia32_divss_round ((__v4sf) __A, (__v4sf) __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) __U,__R); })
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_div_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_divsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_div_sd(__mmask8 __U,__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_divsd_round ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) _mm_setzero_pd (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm_div_round_sd(__A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_divsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) -1, __R); })
+
+#define _mm_mask_div_round_sd(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_divsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) __W, (__mmask8) __U,__R); })
+
+#define _mm_maskz_div_round_sd(__U, __A, __B, __R) __extension__ ({ \
+ (__m128d) __builtin_ia32_divsd_round ((__v2df) __A, (__v2df) __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) __U,__R); })
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_mask_div_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df) __W,
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_maskz_div_pd(__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __A,
+ (__v8df) __B,
+ (__v8df)
+ _mm512_setzero_pd (),
+ (__mmask8) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_div_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf) __W,
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_maskz_div_ps(__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A,
+ (__v16sf) __B,
+ (__v16sf)
+ _mm512_setzero_ps (),
+ (__mmask16) __U,
+ _MM_FROUND_CUR_DIRECTION);
+}
+
+#define _mm512_div_round_pd(__A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __A, (__v8df) __B,\
+ (__v8df) _mm512_setzero_pd(), (__mmask8) -1, __R); })
+
+#define _mm512_mask_div_round_pd(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __A, (__v8df) __B, \
+ (__v8df) __W, (__mmask8) __U, __R); })
+
+#define _mm512_maskz_div_round_pd(__U, __A, __B, __R) __extension__ ({ \
+ (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __A, (__v8df) __B, \
+ (__v8df) _mm512_setzero_pd(), (__mmask8) __U, __R);})
+
+#define _mm512_div_round_ps(__A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) _mm512_setzero_ps (), (__mmask16) -1, __R);})
+
+#define _mm512_mask_div_round_ps(__W, __U, __A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) __W, (__mmask16) __U, __R); });
+
+#define _mm512_maskz_div_round_ps(__U, __A, __B, __R) __extension__ ({ \
+ (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A, (__v16sf) __B, \
+ (__v16sf) _mm512_setzero_ps (), (__mmask16) __U, __R);});
+
#define _mm512_roundscale_ps(A, B) __extension__ ({ \
(__m512)__builtin_ia32_rndscaleps_mask((__v16sf)(A), (B), (__v16sf)(A), \
-1, _MM_FROUND_CUR_DIRECTION); })
@@ -1706,17 +2333,15 @@ _mm512_permutex2var_ps(__m512 __A, __m512i __I, __m512 __B)
/* Vector Extract */
#define _mm512_extractf64x4_pd(A, I) __extension__ ({ \
- __m512d __A = (A); \
(__m256d) \
- __builtin_ia32_extractf64x4_mask((__v8df)__A, \
+ __builtin_ia32_extractf64x4_mask((__v8df)(__m512d)(A), \
(I), \
(__v4df)_mm256_setzero_si256(), \
(__mmask8) -1); })
#define _mm512_extractf32x4_ps(A, I) __extension__ ({ \
- __m512 __A = (A); \
(__m128) \
- __builtin_ia32_extractf32x4_mask((__v16sf)__A, \
+ __builtin_ia32_extractf32x4_mask((__v16sf)(__m512)(A), \
(I), \
(__v4sf)_mm_setzero_ps(), \
(__mmask8) -1); })
@@ -1850,18 +2475,18 @@ _mm512_cvtph_ps(__m256i __A)
}
static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_cvttps_epi32(__m512 a)
+_mm512_cvttps_epi32(__m512 __a)
{
return (__m512i)
- __builtin_ia32_cvttps2dq512_mask((__v16sf) a,
+ __builtin_ia32_cvttps2dq512_mask((__v16sf) __a,
(__v16si) _mm512_setzero_si512 (),
(__mmask16) -1, _MM_FROUND_CUR_DIRECTION);
}
static __inline __m256i __DEFAULT_FN_ATTRS
-_mm512_cvttpd_epi32(__m512d a)
+_mm512_cvttpd_epi32(__m512d __a)
{
- return (__m256i)__builtin_ia32_cvttpd2dq512_mask((__v8df) a,
+ return (__m256i)__builtin_ia32_cvttpd2dq512_mask((__v8df) __a,
(__v8si)_mm256_setzero_si256(),
(__mmask8) -1,
_MM_FROUND_CUR_DIRECTION);
@@ -2405,51 +3030,43 @@ _mm512_mask_cmpneq_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
}
#define _mm512_cmp_epi32_mask(a, b, p) __extension__ ({ \
- __m512i __a = (a); \
- __m512i __b = (b); \
- (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, (p), \
+ (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)(__m512i)(a), \
+ (__v16si)(__m512i)(b), (p), \
(__mmask16)-1); })
#define _mm512_cmp_epu32_mask(a, b, p) __extension__ ({ \
- __m512i __a = (a); \
- __m512i __b = (b); \
- (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, (p), \
+ (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)(__m512i)(a), \
+ (__v16si)(__m512i)(b), (p), \
(__mmask16)-1); })
#define _mm512_cmp_epi64_mask(a, b, p) __extension__ ({ \
- __m512i __a = (a); \
- __m512i __b = (b); \
- (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, (p), \
+ (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)(__m512i)(a), \
+ (__v8di)(__m512i)(b), (p), \
(__mmask8)-1); })
#define _mm512_cmp_epu64_mask(a, b, p) __extension__ ({ \
- __m512i __a = (a); \
- __m512i __b = (b); \
- (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, (p), \
+ (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)(__m512i)(a), \
+ (__v8di)(__m512i)(b), (p), \
(__mmask8)-1); })
#define _mm512_mask_cmp_epi32_mask(m, a, b, p) __extension__ ({ \
- __m512i __a = (a); \
- __m512i __b = (b); \
- (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)__a, (__v16si)__b, (p), \
+ (__mmask16)__builtin_ia32_cmpd512_mask((__v16si)(__m512i)(a), \
+ (__v16si)(__m512i)(b), (p), \
(__mmask16)(m)); })
#define _mm512_mask_cmp_epu32_mask(m, a, b, p) __extension__ ({ \
- __m512i __a = (a); \
- __m512i __b = (b); \
- (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)__a, (__v16si)__b, (p), \
+ (__mmask16)__builtin_ia32_ucmpd512_mask((__v16si)(__m512i)(a), \
+ (__v16si)(__m512i)(b), (p), \
(__mmask16)(m)); })
#define _mm512_mask_cmp_epi64_mask(m, a, b, p) __extension__ ({ \
- __m512i __a = (a); \
- __m512i __b = (b); \
- (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)__a, (__v8di)__b, (p), \
+ (__mmask8)__builtin_ia32_cmpq512_mask((__v8di)(__m512i)(a), \
+ (__v8di)(__m512i)(b), (p), \
(__mmask8)(m)); })
#define _mm512_mask_cmp_epu64_mask(m, a, b, p) __extension__ ({ \
- __m512i __a = (a); \
- __m512i __b = (b); \
- (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)__a, (__v8di)__b, (p), \
+ (__mmask8)__builtin_ia32_ucmpq512_mask((__v8di)(__m512i)(a), \
+ (__v8di)(__m512i)(b), (p), \
(__mmask8)(m)); })
#undef __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
index 74ec175..b4542d6 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlbwintrin.h
@@ -1,4 +1,4 @@
-/*===---- avx512vlbwintrin.h - AVX512VL and AVX512BW intrinsics ----------===
+/*===---- avx512vlbwintrin.h - AVX512VL and AVX512BW intrinsics ------------===
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +29,7 @@
#define __AVX512VLBWINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512bw")))
/* Integer compare */
@@ -1822,6 +1822,435 @@ _mm256_maskz_permutex2var_epi16 (__mmask16 __U, __m256i __A,
(__mmask16) __U);
}
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_maddubs_epi16 (__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
+ return (__m128i) __builtin_ia32_pmaddubsw128_mask ((__v16qi) __X,
+ (__v16qi) __Y,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_maddubs_epi16 (__mmask8 __U, __m128i __X, __m128i __Y) {
+ return (__m128i) __builtin_ia32_pmaddubsw128_mask ((__v16qi) __X,
+ (__v16qi) __Y,
+ (__v8hi) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_maddubs_epi16 (__m256i __W, __mmask16 __U, __m256i __X,
+ __m256i __Y) {
+ return (__m256i) __builtin_ia32_pmaddubsw256_mask ((__v32qi) __X,
+ (__v32qi) __Y,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_maddubs_epi16 (__mmask16 __U, __m256i __X, __m256i __Y) {
+ return (__m256i) __builtin_ia32_pmaddubsw256_mask ((__v32qi) __X,
+ (__v32qi) __Y,
+ (__v16hi) _mm256_setzero_si256(),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_madd_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaddwd128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_madd_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaddwd128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v4si) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_madd_epi16 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaddwd256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_madd_epi16 (__mmask8 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaddwd256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v8si) _mm256_setzero_si256(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvtsepi16_epi8 (__m128i __A) {
+ return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvtsepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) {
+ return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A,
+ (__v16qi) __O,
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvtsepi16_epi8 (__mmask8 __M, __m128i __A) {
+ return (__m128i) __builtin_ia32_pmovswb128_mask ((__v8hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_cvtsepi16_epi8 (__m256i __A) {
+ return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ (__mmask16) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_mask_cvtsepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) {
+ return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A,
+ (__v16qi) __O,
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtsepi16_epi8 (__mmask16 __M, __m256i __A) {
+ return (__m128i) __builtin_ia32_pmovswb256_mask ((__v16hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvtusepi16_epi8 (__m128i __A) {
+ return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvtusepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) {
+ return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A,
+ (__v16qi) __O,
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvtusepi16_epi8 (__mmask8 __M, __m128i __A) {
+ return (__m128i) __builtin_ia32_pmovuswb128_mask ((__v8hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_cvtusepi16_epi8 (__m256i __A) {
+ return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ (__mmask16) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_mask_cvtusepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) {
+ return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A,
+ (__v16qi) __O,
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtusepi16_epi8 (__mmask16 __M, __m256i __A) {
+ return (__m128i) __builtin_ia32_pmovuswb256_mask ((__v16hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvtepi16_epi8 (__m128i __A) {
+
+ return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvtepi16_epi8 (__m128i __O, __mmask8 __M, __m128i __A) {
+ return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A,
+ (__v16qi) __O,
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvtepi16_epi8 (__mmask8 __M, __m128i __A) {
+ return (__m128i) __builtin_ia32_pmovwb128_mask ((__v8hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_cvtepi16_epi8 (__m256i __A) {
+ return (__m128i) __builtin_ia32_pmovwb256_mask ((__v16hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ (__mmask16) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_mask_cvtepi16_epi8 (__m128i __O, __mmask16 __M, __m256i __A) {
+ return (__m128i) __builtin_ia32_pmovwb256_mask ((__v16hi) __A,
+ (__v16qi) __O,
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtepi16_epi8 (__mmask16 __M, __m256i __A) {
+ return (__m128i) __builtin_ia32_pmovwb256_mask ((__v16hi) __A,
+ (__v16qi) _mm_setzero_si128(),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_mulhrs_epi16 (__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
+ return (__m128i) __builtin_ia32_pmulhrsw128_mask ((__v8hi) __X,
+ (__v8hi) __Y,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_mulhrs_epi16 (__mmask8 __U, __m128i __X, __m128i __Y) {
+ return (__m128i) __builtin_ia32_pmulhrsw128_mask ((__v8hi) __X,
+ (__v8hi) __Y,
+ (__v8hi) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_mulhrs_epi16 (__m256i __W, __mmask16 __U, __m256i __X, __m256i __Y) {
+ return (__m256i) __builtin_ia32_pmulhrsw256_mask ((__v16hi) __X,
+ (__v16hi) __Y,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_mulhrs_epi16 (__mmask16 __U, __m256i __X, __m256i __Y) {
+ return (__m256i) __builtin_ia32_pmulhrsw256_mask ((__v16hi) __X,
+ (__v16hi) __Y,
+ (__v16hi) _mm256_setzero_si256(),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_mulhi_epu16 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_pmulhuw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_mulhi_epu16 (__mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmulhuw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_mulhi_epu16 (__m256i __W, __mmask16 __U, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_pmulhuw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_mulhi_epu16 (__mmask16 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmulhuw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256(),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_mulhi_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_pmulhw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_mulhi_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmulhw128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_mulhi_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_pmulhw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_mulhi_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmulhw256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256(),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_unpackhi_epi8 (__m128i __W, __mmask16 __U, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_punpckhbw128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_unpackhi_epi8 (__mmask16 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_punpckhbw128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128(),
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_unpackhi_epi8 (__m256i __W, __mmask32 __U, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_punpckhbw256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_unpackhi_epi8 (__mmask32 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_punpckhbw256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256(),
+ (__mmask32) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_unpackhi_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_punpckhwd128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_unpackhi_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_punpckhwd128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_unpackhi_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_punpckhwd256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_unpackhi_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_punpckhwd256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256(),
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_unpacklo_epi8 (__m128i __W, __mmask16 __U, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_punpcklbw128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_unpacklo_epi8 (__mmask16 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_punpcklbw128_mask ((__v16qi) __A,
+ (__v16qi) __B,
+ (__v16qi) _mm_setzero_si128(),
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_unpacklo_epi8 (__m256i __W, __mmask32 __U, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_punpcklbw256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) __W,
+ (__mmask32) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_unpacklo_epi8 (__mmask32 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_punpcklbw256_mask ((__v32qi) __A,
+ (__v32qi) __B,
+ (__v32qi) _mm256_setzero_si256(),
+ (__mmask32) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_unpacklo_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_punpcklwd128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_unpacklo_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_punpcklwd128_mask ((__v8hi) __A,
+ (__v8hi) __B,
+ (__v8hi) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_unpacklo_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_punpcklwd256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) __W,
+ (__mmask16) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_unpacklo_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_punpcklwd256_mask ((__v16hi) __A,
+ (__v16hi) __B,
+ (__v16hi) _mm256_setzero_si256(),
+ (__mmask16) __U);
+}
+
#define _mm_cmp_epi8_mask(a, b, p) __extension__ ({ \
(__mmask16)__builtin_ia32_cmpb128_mask((__v16qi)(__m128i)(a), \
(__v16qi)(__m128i)(b), \
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h
index 1edf29d..dfd858e0 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vldqintrin.h
@@ -1,4 +1,4 @@
-/*===---- avx512vldqintrin.h - AVX512VL and AVX512DQ intrinsics ---------------------------===
+/*===---- avx512vldqintrin.h - AVX512VL and AVX512DQ intrinsics ------------===
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
*
*===-----------------------------------------------------------------------===
*/
-
+
#ifndef __IMMINTRIN_H
#error "Never use <avx512vldqintrin.h> directly; include <immintrin.h> instead."
#endif
@@ -29,7 +29,7 @@
#define __AVX512VLDQINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl,avx512dq")))
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_mullo_epi64 (__m256i __A, __m256i __B) {
@@ -348,6 +348,606 @@ _mm_maskz_or_ps (__mmask8 __U, __m128 __A, __m128 __B) {
(__mmask8) __U);
}
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvtpd_epi64 (__m128d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvtpd_epi64 (__m128i __W, __mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvtpd_epi64 (__mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2qq128_mask ((__v2df) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_cvtpd_epi64 (__m256d __A) {
+ return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvtpd_epi64 (__m256i __W, __mmask8 __U, __m256d __A) {
+ return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtpd_epi64 (__mmask8 __U, __m256d __A) {
+ return (__m256i) __builtin_ia32_cvtpd2qq256_mask ((__v4df) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvtpd_epu64 (__m128d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvtpd_epu64 (__m128i __W, __mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvtpd_epu64 (__mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2uqq128_mask ((__v2df) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_cvtpd_epu64 (__m256d __A) {
+ return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvtpd_epu64 (__m256i __W, __mmask8 __U, __m256d __A) {
+ return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtpd_epu64 (__mmask8 __U, __m256d __A) {
+ return (__m256i) __builtin_ia32_cvtpd2uqq256_mask ((__v4df) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvtps_epi64 (__m128 __A) {
+ return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvtps_epi64 (__m128i __W, __mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvtps_epi64 (__mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvtps2qq128_mask ((__v4sf) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_cvtps_epi64 (__m128 __A) {
+ return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvtps_epi64 (__m256i __W, __mmask8 __U, __m128 __A) {
+ return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtps_epi64 (__mmask8 __U, __m128 __A) {
+ return (__m256i) __builtin_ia32_cvtps2qq256_mask ((__v4sf) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvtps_epu64 (__m128 __A) {
+ return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvtps_epu64 (__m128i __W, __mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvtps_epu64 (__mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvtps2uqq128_mask ((__v4sf) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_cvtps_epu64 (__m128 __A) {
+ return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvtps_epu64 (__m256i __W, __mmask8 __U, __m128 __A) {
+ return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtps_epu64 (__mmask8 __U, __m128 __A) {
+ return (__m256i) __builtin_ia32_cvtps2uqq256_mask ((__v4sf) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_cvtepi64_pd (__m128i __A) {
+ return (__m128d) __builtin_ia32_cvtqq2pd128_mask ((__v2di) __A,
+ (__v2df) _mm_setzero_pd(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_cvtepi64_pd (__m128d __W, __mmask8 __U, __m128i __A) {
+ return (__m128d) __builtin_ia32_cvtqq2pd128_mask ((__v2di) __A,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_cvtepi64_pd (__mmask8 __U, __m128i __A) {
+ return (__m128d) __builtin_ia32_cvtqq2pd128_mask ((__v2di) __A,
+ (__v2df) _mm_setzero_pd(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_cvtepi64_pd (__m256i __A) {
+ return (__m256d) __builtin_ia32_cvtqq2pd256_mask ((__v4di) __A,
+ (__v4df) _mm256_setzero_pd(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_cvtepi64_pd (__m256d __W, __mmask8 __U, __m256i __A) {
+ return (__m256d) __builtin_ia32_cvtqq2pd256_mask ((__v4di) __A,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtepi64_pd (__mmask8 __U, __m256i __A) {
+ return (__m256d) __builtin_ia32_cvtqq2pd256_mask ((__v4di) __A,
+ (__v4df) _mm256_setzero_pd(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_cvtepi64_ps (__m128i __A) {
+ return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A,
+ (__v4sf) _mm_setzero_ps(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_cvtepi64_ps (__m128 __W, __mmask8 __U, __m128i __A) {
+ return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_cvtepi64_ps (__mmask8 __U, __m128i __A) {
+ return (__m128) __builtin_ia32_cvtqq2ps128_mask ((__v2di) __A,
+ (__v4sf) _mm_setzero_ps(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm256_cvtepi64_ps (__m256i __A) {
+ return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A,
+ (__v4sf) _mm_setzero_ps(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm256_mask_cvtepi64_ps (__m128 __W, __mmask8 __U, __m256i __A) {
+ return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtepi64_ps (__mmask8 __U, __m256i __A) {
+ return (__m128) __builtin_ia32_cvtqq2ps256_mask ((__v4di) __A,
+ (__v4sf) _mm_setzero_ps(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvttpd_epi64 (__m128d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvttpd_epi64 (__m128i __W, __mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvttpd_epi64 (__mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_cvttpd_epi64 (__m256d __A) {
+ return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvttpd_epi64 (__m256i __W, __mmask8 __U, __m256d __A) {
+ return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvttpd_epi64 (__mmask8 __U, __m256d __A) {
+ return (__m256i) __builtin_ia32_cvttpd2qq256_mask ((__v4df) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvttpd_epu64 (__m128d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvttpd_epu64 (__m128i __W, __mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvttpd_epu64 (__mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2uqq128_mask ((__v2df) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_cvttpd_epu64 (__m256d __A) {
+ return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvttpd_epu64 (__m256i __W, __mmask8 __U, __m256d __A) {
+ return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvttpd_epu64 (__mmask8 __U, __m256d __A) {
+ return (__m256i) __builtin_ia32_cvttpd2uqq256_mask ((__v4df) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvttps_epi64 (__m128 __A) {
+ return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvttps_epi64 (__m128i __W, __mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvttps_epi64 (__mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvttps2qq128_mask ((__v4sf) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_cvttps_epi64 (__m128 __A) {
+ return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvttps_epi64 (__m256i __W, __mmask8 __U, __m128 __A) {
+ return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvttps_epi64 (__mmask8 __U, __m128 __A) {
+ return (__m256i) __builtin_ia32_cvttps2qq256_mask ((__v4sf) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvttps_epu64 (__m128 __A) {
+ return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvttps_epu64 (__m128i __W, __mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvttps_epu64 (__mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvttps2uqq128_mask ((__v4sf) __A,
+ (__v2di) _mm_setzero_si128(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_cvttps_epu64 (__m128 __A) {
+ return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvttps_epu64 (__m256i __W, __mmask8 __U, __m128 __A) {
+ return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvttps_epu64 (__mmask8 __U, __m128 __A) {
+ return (__m256i) __builtin_ia32_cvttps2uqq256_mask ((__v4sf) __A,
+ (__v4di) _mm256_setzero_si256(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_cvtepu64_pd (__m128i __A) {
+ return (__m128d) __builtin_ia32_cvtuqq2pd128_mask ((__v2di) __A,
+ (__v2df) _mm_setzero_pd(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_cvtepu64_pd (__m128d __W, __mmask8 __U, __m128i __A) {
+ return (__m128d) __builtin_ia32_cvtuqq2pd128_mask ((__v2di) __A,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_cvtepu64_pd (__mmask8 __U, __m128i __A) {
+ return (__m128d) __builtin_ia32_cvtuqq2pd128_mask ((__v2di) __A,
+ (__v2df) _mm_setzero_pd(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_cvtepu64_pd (__m256i __A) {
+ return (__m256d) __builtin_ia32_cvtuqq2pd256_mask ((__v4di) __A,
+ (__v4df) _mm256_setzero_pd(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_cvtepu64_pd (__m256d __W, __mmask8 __U, __m256i __A) {
+ return (__m256d) __builtin_ia32_cvtuqq2pd256_mask ((__v4di) __A,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtepu64_pd (__mmask8 __U, __m256i __A) {
+ return (__m256d) __builtin_ia32_cvtuqq2pd256_mask ((__v4di) __A,
+ (__v4df) _mm256_setzero_pd(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_cvtepu64_ps (__m128i __A) {
+ return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A,
+ (__v4sf) _mm_setzero_ps(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_cvtepu64_ps (__m128 __W, __mmask8 __U, __m128i __A) {
+ return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_cvtepu64_ps (__mmask8 __U, __m128i __A) {
+ return (__m128) __builtin_ia32_cvtuqq2ps128_mask ((__v2di) __A,
+ (__v4sf) _mm_setzero_ps(),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm256_cvtepu64_ps (__m256i __A) {
+ return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A,
+ (__v4sf) _mm_setzero_ps(),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm256_mask_cvtepu64_ps (__m128 __W, __mmask8 __U, __m256i __A) {
+ return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtepu64_ps (__mmask8 __U, __m256i __A) {
+ return (__m128) __builtin_ia32_cvtuqq2ps256_mask ((__v4di) __A,
+ (__v4sf) _mm_setzero_ps(),
+ (__mmask8) __U);
+}
+
+#define _mm_range_pd(__A, __B, __C) __extension__ ({ \
+ (__m128d) __builtin_ia32_rangepd128_mask ((__v2df) __A, (__v2df) __B, __C, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) -1); })
+
+#define _mm_mask_range_pd(__W, __U, __A, __B, __C) __extension__ ({ \
+ (__m128d) __builtin_ia32_rangepd128_mask ((__v2df) __A, (__v2df) __B, __C, \
+ (__v2df) __W, (__mmask8) __U); })
+
+#define _mm_maskz_range_pd(__U, __A, __B, __C) __extension__ ({ \
+ (__m128d) __builtin_ia32_rangepd128_mask ((__v2df) __A, (__v2df) __B, __C, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) __U); })
+
+#define _mm256_range_pd(__A, __B, __C) __extension__ ({ \
+ (__m256d) __builtin_ia32_rangepd256_mask ((__v4df) __A, (__v4df) __B, __C, \
+ (__v4df) _mm256_setzero_pd(), (__mmask8) -1); })
+
+#define _mm256_mask_range_pd(__W, __U, __A, __B, __C) __extension__ ({ \
+ (__m256d) __builtin_ia32_rangepd256_mask ((__v4df) __A, (__v4df) __B, __C, \
+ (__v4df) __W, (__mmask8) __U); })
+
+#define _mm256_maskz_range_pd(__U, __A, __B, __C) __extension__ ({ \
+ (__m256d) __builtin_ia32_rangepd256_mask ((__v4df) __A, (__v4df) __B, __C, \
+ (__v4df) _mm256_setzero_pd(), (__mmask8) __U); })
+
+#define _mm_range_ps(__A, __B, __C) __extension__ ({ \
+ (__m128) __builtin_ia32_rangeps128_mask ((__v4sf) __A, (__v4sf) __B, __C, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) -1); })
+
+#define _mm_mask_range_ps(__W, __U, __A, __B, __C) __extension__ ({ \
+ (__m128) __builtin_ia32_rangeps128_mask ((__v4sf) __A, (__v4sf) __B, __C, \
+ (__v4sf) __W, (__mmask8) __U); })
+
+#define _mm_maskz_range_ps(__U, __A, __B, __C) __extension__ ({ \
+ (__m128) __builtin_ia32_rangeps128_mask ((__v4sf) __A, (__v4sf) __B, __C, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) __U); })
+
+#define _mm256_range_ps(__A, __B, __C) __extension__ ({ \
+ (__m256) __builtin_ia32_rangeps256_mask ((__v8sf) __A, (__v8sf) __B, __C, \
+ (__v8sf) _mm256_setzero_ps(), (__mmask8) -1); })
+
+#define _mm256_mask_range_ps(__W, __U, __A, __B, __C) __extension__ ({ \
+ (__m256) __builtin_ia32_rangeps256_mask ((__v8sf) __A, (__v8sf) __B, __C, \
+ (__v8sf) __W, (__mmask8) __U); })
+
+#define _mm256_maskz_range_ps(__U, __A, __B, __C) __extension__ ({ \
+ (__m256) __builtin_ia32_rangeps256_mask ((__v8sf) __A, (__v8sf) __B, __C, \
+ (__v8sf) _mm256_setzero_ps(), (__mmask8) __U); })
+
+#define _mm_reduce_pd(__A, __B) __extension__ ({ \
+ (__m128d) __builtin_ia32_reducepd128_mask ((__v2df) __A, __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) -1); })
+
+#define _mm_mask_reduce_pd(__W, __U, __A, __B) __extension__ ({ \
+ (__m128d) __builtin_ia32_reducepd128_mask ((__v2df) __A, __B, \
+ (__v2df) __W, (__mmask8) __U); })
+
+#define _mm_maskz_reduce_pd(__U, __A, __B) __extension__ ({ \
+ (__m128d) __builtin_ia32_reducepd128_mask ((__v2df) __A, __B, \
+ (__v2df) _mm_setzero_pd(), (__mmask8) __U); })
+
+#define _mm256_reduce_pd(__A, __B) __extension__ ({ \
+ (__m256d) __builtin_ia32_reducepd256_mask ((__v4df) __A, __B, \
+ (__v4df) _mm256_setzero_pd(), (__mmask8) -1); })
+
+#define _mm256_mask_reduce_pd(__W, __U, __A, __B) __extension__ ({ \
+ (__m256d) __builtin_ia32_reducepd256_mask ((__v4df) __A, __B, \
+ (__v4df) __W, (__mmask8) __U); })
+
+#define _mm256_maskz_reduce_pd(__U, __A, __B) __extension__ ({ \
+ (__m256d) __builtin_ia32_reducepd256_mask ((__v4df) __A, __B, \
+ (__v4df) _mm256_setzero_pd(), (__mmask8) __U); })
+
+#define _mm_reduce_ps(__A, __B) __extension__ ({ \
+ (__m128) __builtin_ia32_reduceps128_mask ((__v4sf) __A, __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) -1); })
+
+#define _mm_mask_reduce_ps(__W, __U, __A, __B) __extension__ ({ \
+ (__m128) __builtin_ia32_reduceps128_mask ((__v4sf) __A, __B, \
+ (__v4sf) __W, (__mmask8) __U); })
+
+#define _mm_maskz_reduce_ps(__U, __A, __B) __extension__ ({ \
+ (__m128) __builtin_ia32_reduceps128_mask ((__v4sf) __A, __B, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) __U); })
+
+#define _mm256_reduce_ps(__A, __B) __extension__ ({ \
+ (__m256) __builtin_ia32_reduceps256_mask ((__v8sf) __A, __B, \
+ (__v8sf) _mm256_setzero_ps(), (__mmask8) -1); })
+
+#define _mm256_mask_reduce_ps(__W, __U, __A, __B) __extension__ ({ \
+ (__m256) __builtin_ia32_reduceps256_mask ((__v8sf) __A, __B, \
+ (__v8sf) __W, (__mmask8) __U); })
+
+#define _mm256_maskz_reduce_ps(__U, __A, __B) __extension__ ({ \
+ (__m256) __builtin_ia32_reduceps256_mask ((__v8sf) __A, __B, \
+ (__v8sf) _mm256_setzero_ps(), (__mmask8) __U); })
+
#undef __DEFAULT_FN_ATTRS
#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h b/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
index fc1b9d6..8f13536 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avx512vlintrin.h
@@ -28,18 +28,18 @@
#ifndef __AVX512VLINTRIN_H
#define __AVX512VLINTRIN_H
-/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx512vl")))
+#define __DEFAULT_FN_ATTRS_BOTH __attribute__((__always_inline__, __nodebug__, __target__("avx512vl, avx512bw")))
/* Integer compare */
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm_cmpeq_epi32_mask(__m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpeqd128_mask((__v4si)__a, (__v4si)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm_mask_cmpeq_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpeqd128_mask((__v4si)__a, (__v4si)__b,
__u);
@@ -57,13 +57,13 @@ _mm_mask_cmpeq_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
__u);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm256_cmpeq_epi32_mask(__m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpeqd256_mask((__v8si)__a, (__v8si)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm256_mask_cmpeq_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpeqd256_mask((__v8si)__a, (__v8si)__b,
__u);
@@ -81,13 +81,13 @@ _mm256_mask_cmpeq_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
__u);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm_cmpeq_epi64_mask(__m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpeqq128_mask((__v2di)__a, (__v2di)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm_mask_cmpeq_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpeqq128_mask((__v2di)__a, (__v2di)__b,
__u);
@@ -105,13 +105,13 @@ _mm_mask_cmpeq_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
__u);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm256_cmpeq_epi64_mask(__m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpeqq256_mask((__v4di)__a, (__v4di)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm256_mask_cmpeq_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpeqq256_mask((__v4di)__a, (__v4di)__b,
__u);
@@ -226,16 +226,13 @@ _mm256_mask_cmpge_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
__u);
}
-
-
-
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm_cmpgt_epi32_mask(__m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpgtd128_mask((__v4si)__a, (__v4si)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm_mask_cmpgt_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpgtd128_mask((__v4si)__a, (__v4si)__b,
__u);
@@ -253,13 +250,13 @@ _mm_mask_cmpgt_epu32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
__u);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm256_cmpgt_epi32_mask(__m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpgtd256_mask((__v8si)__a, (__v8si)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm256_mask_cmpgt_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpgtd256_mask((__v8si)__a, (__v8si)__b,
__u);
@@ -277,13 +274,13 @@ _mm256_mask_cmpgt_epu32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
__u);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm_cmpgt_epi64_mask(__m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpgtq128_mask((__v2di)__a, (__v2di)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm_mask_cmpgt_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
return (__mmask8)__builtin_ia32_pcmpgtq128_mask((__v2di)__a, (__v2di)__b,
__u);
@@ -301,13 +298,13 @@ _mm_mask_cmpgt_epu64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
__u);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm256_cmpgt_epi64_mask(__m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpgtq256_mask((__v4di)__a, (__v4di)__b,
(__mmask8)-1);
}
-static __inline__ __mmask8 __DEFAULT_FN_ATTRS
+static __inline__ __mmask8 __DEFAULT_FN_ATTRS_BOTH
_mm256_mask_cmpgt_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
return (__mmask8)__builtin_ia32_pcmpgtq256_mask((__v4di)__a, (__v4di)__b,
__u);
@@ -1977,6 +1974,2633 @@ _mm256_mask3_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
(__mmask8) __U);
}
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_add_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_addpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_add_pd (__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_addpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_add_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_addpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_add_pd (__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_addpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_add_ps (__m128 __W, __mmask16 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_addps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_add_ps (__mmask16 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_addps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_add_ps (__m256 __W, __mmask16 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_addps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_add_ps (__mmask16 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_addps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_blend_epi32 (__mmask8 __U, __m128i __A, __m128i __W) {
+ return (__m128i) __builtin_ia32_blendmd_128_mask ((__v4si) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_blend_epi32 (__mmask8 __U, __m256i __A, __m256i __W) {
+ return (__m256i) __builtin_ia32_blendmd_256_mask ((__v8si) __A,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_blend_pd (__mmask8 __U, __m128d __A, __m128d __W) {
+ return (__m128d) __builtin_ia32_blendmpd_128_mask ((__v2df) __A,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_blend_pd (__mmask8 __U, __m256d __A, __m256d __W) {
+ return (__m256d) __builtin_ia32_blendmpd_256_mask ((__v4df) __A,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_blend_ps (__mmask8 __U, __m128 __A, __m128 __W) {
+ return (__m128) __builtin_ia32_blendmps_128_mask ((__v4sf) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_blend_ps (__mmask8 __U, __m256 __A, __m256 __W) {
+ return (__m256) __builtin_ia32_blendmps_256_mask ((__v8sf) __A,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_blend_epi64 (__mmask8 __U, __m128i __A, __m128i __W) {
+ return (__m128i) __builtin_ia32_blendmq_128_mask ((__v2di) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_blend_epi64 (__mmask8 __U, __m256i __A, __m256i __W) {
+ return (__m256i) __builtin_ia32_blendmq_256_mask ((__v4di) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_compress_pd (__m128d __W, __mmask8 __U, __m128d __A) {
+ return (__m128d) __builtin_ia32_compressdf128_mask ((__v2df) __A,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_compress_pd (__mmask8 __U, __m128d __A) {
+ return (__m128d) __builtin_ia32_compressdf128_mask ((__v2df) __A,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_compress_pd (__m256d __W, __mmask8 __U, __m256d __A) {
+ return (__m256d) __builtin_ia32_compressdf256_mask ((__v4df) __A,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_compress_pd (__mmask8 __U, __m256d __A) {
+ return (__m256d) __builtin_ia32_compressdf256_mask ((__v4df) __A,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_compress_epi64 (__m128i __W, __mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_compressdi128_mask ((__v2di) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_compress_epi64 (__mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_compressdi128_mask ((__v2di) __A,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_compress_epi64 (__m256i __W, __mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_compressdi256_mask ((__v4di) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_compress_epi64 (__mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_compressdi256_mask ((__v4di) __A,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_compress_ps (__m128 __W, __mmask8 __U, __m128 __A) {
+ return (__m128) __builtin_ia32_compresssf128_mask ((__v4sf) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_compress_ps (__mmask8 __U, __m128 __A) {
+ return (__m128) __builtin_ia32_compresssf128_mask ((__v4sf) __A,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_compress_ps (__m256 __W, __mmask8 __U, __m256 __A) {
+ return (__m256) __builtin_ia32_compresssf256_mask ((__v8sf) __A,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_compress_ps (__mmask8 __U, __m256 __A) {
+ return (__m256) __builtin_ia32_compresssf256_mask ((__v8sf) __A,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_compress_epi32 (__m128i __W, __mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_compresssi128_mask ((__v4si) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_compress_epi32 (__mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_compresssi128_mask ((__v4si) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_compress_epi32 (__m256i __W, __mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_compresssi256_mask ((__v8si) __A,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_compress_epi32 (__mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_compresssi256_mask ((__v8si) __A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm_mask_compressstoreu_pd (void *__P, __mmask8 __U, __m128d __A) {
+ __builtin_ia32_compressstoredf128_mask ((__v2df *) __P,
+ (__v2df) __A,
+ (__mmask8) __U);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm256_mask_compressstoreu_pd (void *__P, __mmask8 __U, __m256d __A) {
+ __builtin_ia32_compressstoredf256_mask ((__v4df *) __P,
+ (__v4df) __A,
+ (__mmask8) __U);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm_mask_compressstoreu_epi64 (void *__P, __mmask8 __U, __m128i __A) {
+ __builtin_ia32_compressstoredi128_mask ((__v2di *) __P,
+ (__v2di) __A,
+ (__mmask8) __U);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm256_mask_compressstoreu_epi64 (void *__P, __mmask8 __U, __m256i __A) {
+ __builtin_ia32_compressstoredi256_mask ((__v4di *) __P,
+ (__v4di) __A,
+ (__mmask8) __U);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm_mask_compressstoreu_ps (void *__P, __mmask8 __U, __m128 __A) {
+ __builtin_ia32_compressstoresf128_mask ((__v4sf *) __P,
+ (__v4sf) __A,
+ (__mmask8) __U);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm256_mask_compressstoreu_ps (void *__P, __mmask8 __U, __m256 __A) {
+ __builtin_ia32_compressstoresf256_mask ((__v8sf *) __P,
+ (__v8sf) __A,
+ (__mmask8) __U);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm_mask_compressstoreu_epi32 (void *__P, __mmask8 __U, __m128i __A) {
+ __builtin_ia32_compressstoresi128_mask ((__v4si *) __P,
+ (__v4si) __A,
+ (__mmask8) __U);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm256_mask_compressstoreu_epi32 (void *__P, __mmask8 __U, __m256i __A) {
+ __builtin_ia32_compressstoresi256_mask ((__v8si *) __P,
+ (__v8si) __A,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_cvtepi32_pd (__m128d __W, __mmask8 __U, __m128i __A) {
+ return (__m128d) __builtin_ia32_cvtdq2pd128_mask ((__v4si) __A,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_cvtepi32_pd (__mmask8 __U, __m128i __A) {
+ return (__m128d) __builtin_ia32_cvtdq2pd128_mask ((__v4si) __A,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_cvtepi32_pd (__m256d __W, __mmask8 __U, __m128i __A) {
+ return (__m256d) __builtin_ia32_cvtdq2pd256_mask ((__v4si) __A,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtepi32_pd (__mmask8 __U, __m128i __A) {
+ return (__m256d) __builtin_ia32_cvtdq2pd256_mask ((__v4si) __A,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_cvtepi32_ps (__m128 __W, __mmask8 __U, __m128i __A) {
+ return (__m128) __builtin_ia32_cvtdq2ps128_mask ((__v4si) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_cvtepi32_ps (__mmask16 __U, __m128i __A) {
+ return (__m128) __builtin_ia32_cvtdq2ps128_mask ((__v4si) __A,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_cvtepi32_ps (__m256 __W, __mmask8 __U, __m256i __A) {
+ return (__m256) __builtin_ia32_cvtdq2ps256_mask ((__v8si) __A,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtepi32_ps (__mmask16 __U, __m256i __A) {
+ return (__m256) __builtin_ia32_cvtdq2ps256_mask ((__v8si) __A,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvtpd_epi32 (__m128i __W, __mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2dq128_mask ((__v2df) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvtpd_epi32 (__mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2dq128_mask ((__v2df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_mask_cvtpd_epi32 (__m128i __W, __mmask8 __U, __m256d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2dq256_mask ((__v4df) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtpd_epi32 (__mmask8 __U, __m256d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2dq256_mask ((__v4df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_cvtpd_ps (__m128 __W, __mmask8 __U, __m128d __A) {
+ return (__m128) __builtin_ia32_cvtpd2ps_mask ((__v2df) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_cvtpd_ps (__mmask8 __U, __m128d __A) {
+ return (__m128) __builtin_ia32_cvtpd2ps_mask ((__v2df) __A,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm256_mask_cvtpd_ps (__m128 __W, __mmask8 __U, __m256d __A) {
+ return (__m128) __builtin_ia32_cvtpd2ps256_mask ((__v4df) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtpd_ps (__mmask8 __U, __m256d __A) {
+ return (__m128) __builtin_ia32_cvtpd2ps256_mask ((__v4df) __A,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvtpd_epu32 (__m128d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvtpd_epu32 (__m128i __W, __mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvtpd_epu32 (__mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2udq128_mask ((__v2df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_cvtpd_epu32 (__m256d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_mask_cvtpd_epu32 (__m128i __W, __mmask8 __U, __m256d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtpd_epu32 (__mmask8 __U, __m256d __A) {
+ return (__m128i) __builtin_ia32_cvtpd2udq256_mask ((__v4df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvtps_epi32 (__m128i __W, __mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvtps2dq128_mask ((__v4sf) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvtps_epi32 (__mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvtps2dq128_mask ((__v4sf) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvtps_epi32 (__m256i __W, __mmask8 __U, __m256 __A) {
+ return (__m256i) __builtin_ia32_cvtps2dq256_mask ((__v8sf) __A,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtps_epi32 (__mmask8 __U, __m256 __A) {
+ return (__m256i) __builtin_ia32_cvtps2dq256_mask ((__v8sf) __A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_cvtps_pd (__m128d __W, __mmask8 __U, __m128 __A) {
+ return (__m128d) __builtin_ia32_cvtps2pd128_mask ((__v4sf) __A,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_cvtps_pd (__mmask8 __U, __m128 __A) {
+ return (__m128d) __builtin_ia32_cvtps2pd128_mask ((__v4sf) __A,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_cvtps_pd (__m256d __W, __mmask8 __U, __m128 __A) {
+ return (__m256d) __builtin_ia32_cvtps2pd256_mask ((__v4sf) __A,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtps_pd (__mmask8 __U, __m128 __A) {
+ return (__m256d) __builtin_ia32_cvtps2pd256_mask ((__v4sf) __A,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvtps_epu32 (__m128 __A) {
+ return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvtps_epu32 (__m128i __W, __mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvtps_epu32 (__mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvtps2udq128_mask ((__v4sf) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_cvtps_epu32 (__m256 __A) {
+ return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvtps_epu32 (__m256i __W, __mmask8 __U, __m256 __A) {
+ return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtps_epu32 (__mmask8 __U, __m256 __A) {
+ return (__m256i) __builtin_ia32_cvtps2udq256_mask ((__v8sf) __A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvttpd_epi32 (__m128i __W, __mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2dq128_mask ((__v2df) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvttpd_epi32 (__mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2dq128_mask ((__v2df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_mask_cvttpd_epi32 (__m128i __W, __mmask8 __U, __m256d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2dq256_mask ((__v4df) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvttpd_epi32 (__mmask8 __U, __m256d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2dq256_mask ((__v4df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvttpd_epu32 (__m128d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvttpd_epu32 (__m128i __W, __mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvttpd_epu32 (__mmask8 __U, __m128d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2udq128_mask ((__v2df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_cvttpd_epu32 (__m256d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_mask_cvttpd_epu32 (__m128i __W, __mmask8 __U, __m256d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvttpd_epu32 (__mmask8 __U, __m256d __A) {
+ return (__m128i) __builtin_ia32_cvttpd2udq256_mask ((__v4df) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvttps_epi32 (__m128i __W, __mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvttps2dq128_mask ((__v4sf) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvttps_epi32 (__mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvttps2dq128_mask ((__v4sf) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvttps_epi32 (__m256i __W, __mmask8 __U, __m256 __A) {
+ return (__m256i) __builtin_ia32_cvttps2dq256_mask ((__v8sf) __A,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvttps_epi32 (__mmask8 __U, __m256 __A) {
+ return (__m256i) __builtin_ia32_cvttps2dq256_mask ((__v8sf) __A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_cvttps_epu32 (__m128 __A) {
+ return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_cvttps_epu32 (__m128i __W, __mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_cvttps_epu32 (__mmask8 __U, __m128 __A) {
+ return (__m128i) __builtin_ia32_cvttps2udq128_mask ((__v4sf) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_cvttps_epu32 (__m256 __A) {
+ return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_cvttps_epu32 (__m256i __W, __mmask8 __U, __m256 __A) {
+ return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_cvttps_epu32 (__mmask8 __U, __m256 __A) {
+ return (__m256i) __builtin_ia32_cvttps2udq256_mask ((__v8sf) __A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_cvtepu32_pd (__m128i __A) {
+ return (__m128d) __builtin_ia32_cvtudq2pd128_mask ((__v4si) __A,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_cvtepu32_pd (__m128d __W, __mmask8 __U, __m128i __A) {
+ return (__m128d) __builtin_ia32_cvtudq2pd128_mask ((__v4si) __A,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_cvtepu32_pd (__mmask8 __U, __m128i __A) {
+ return (__m128d) __builtin_ia32_cvtudq2pd128_mask ((__v4si) __A,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_cvtepu32_pd (__m128i __A) {
+ return (__m256d) __builtin_ia32_cvtudq2pd256_mask ((__v4si) __A,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_cvtepu32_pd (__m256d __W, __mmask8 __U, __m128i __A) {
+ return (__m256d) __builtin_ia32_cvtudq2pd256_mask ((__v4si) __A,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtepu32_pd (__mmask8 __U, __m128i __A) {
+ return (__m256d) __builtin_ia32_cvtudq2pd256_mask ((__v4si) __A,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_cvtepu32_ps (__m128i __A) {
+ return (__m128) __builtin_ia32_cvtudq2ps128_mask ((__v4si) __A,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_cvtepu32_ps (__m128 __W, __mmask8 __U, __m128i __A) {
+ return (__m128) __builtin_ia32_cvtudq2ps128_mask ((__v4si) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_cvtepu32_ps (__mmask8 __U, __m128i __A) {
+ return (__m128) __builtin_ia32_cvtudq2ps128_mask ((__v4si) __A,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_cvtepu32_ps (__m256i __A) {
+ return (__m256) __builtin_ia32_cvtudq2ps256_mask ((__v8si) __A,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_cvtepu32_ps (__m256 __W, __mmask8 __U, __m256i __A) {
+ return (__m256) __builtin_ia32_cvtudq2ps256_mask ((__v8si) __A,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_cvtepu32_ps (__mmask8 __U, __m256i __A) {
+ return (__m256) __builtin_ia32_cvtudq2ps256_mask ((__v8si) __A,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_div_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_divpd_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_div_pd (__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_divpd_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_div_pd (__m256d __W, __mmask8 __U, __m256d __A,
+ __m256d __B) {
+ return (__m256d) __builtin_ia32_divpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_div_pd (__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_divpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_div_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_divps_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_div_ps (__mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_divps_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_div_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_divps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_div_ps (__mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_divps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_expand_pd (__m128d __W, __mmask8 __U, __m128d __A) {
+ return (__m128d) __builtin_ia32_expanddf128_mask ((__v2df) __A,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_expand_pd (__mmask8 __U, __m128d __A) {
+ return (__m128d) __builtin_ia32_expanddf128_mask ((__v2df) __A,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_expand_pd (__m256d __W, __mmask8 __U, __m256d __A) {
+ return (__m256d) __builtin_ia32_expanddf256_mask ((__v4df) __A,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_expand_pd (__mmask8 __U, __m256d __A) {
+ return (__m256d) __builtin_ia32_expanddf256_mask ((__v4df) __A,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_expand_epi64 (__m128i __W, __mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_expanddi128_mask ((__v2di) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_expand_epi64 (__mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_expanddi128_mask ((__v2di) __A,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_expand_epi64 (__m256i __W, __mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_expanddi256_mask ((__v4di) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_expand_epi64 (__mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_expanddi256_mask ((__v4di) __A,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_expandloadu_pd (__m128d __W, __mmask8 __U, void const *__P) {
+ return (__m128d) __builtin_ia32_expandloaddf128_mask ((__v2df *) __P,
+ (__v2df) __W,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_expandloadu_pd (__mmask8 __U, void const *__P) {
+ return (__m128d) __builtin_ia32_expandloaddf128_mask ((__v2df *) __P,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_expandloadu_pd (__m256d __W, __mmask8 __U, void const *__P) {
+ return (__m256d) __builtin_ia32_expandloaddf256_mask ((__v4df *) __P,
+ (__v4df) __W,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_expandloadu_pd (__mmask8 __U, void const *__P) {
+ return (__m256d) __builtin_ia32_expandloaddf256_mask ((__v4df *) __P,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_expandloadu_epi64 (__m128i __W, __mmask8 __U, void const *__P) {
+ return (__m128i) __builtin_ia32_expandloaddi128_mask ((__v2di *) __P,
+ (__v2di) __W,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) {
+ return (__m128i) __builtin_ia32_expandloaddi128_mask ((__v2di *) __P,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_expandloadu_epi64 (__m256i __W, __mmask8 __U,
+ void const *__P) {
+ return (__m256i) __builtin_ia32_expandloaddi256_mask ((__v4di *) __P,
+ (__v4di) __W,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_expandloadu_epi64 (__mmask8 __U, void const *__P) {
+ return (__m256i) __builtin_ia32_expandloaddi256_mask ((__v4di *) __P,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_expandloadu_ps (__m128 __W, __mmask8 __U, void const *__P) {
+ return (__m128) __builtin_ia32_expandloadsf128_mask ((__v4sf *) __P,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_expandloadu_ps (__mmask8 __U, void const *__P) {
+ return (__m128) __builtin_ia32_expandloadsf128_mask ((__v4sf *) __P,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_expandloadu_ps (__m256 __W, __mmask8 __U, void const *__P) {
+ return (__m256) __builtin_ia32_expandloadsf256_mask ((__v8sf *) __P,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_expandloadu_ps (__mmask8 __U, void const *__P) {
+ return (__m256) __builtin_ia32_expandloadsf256_mask ((__v8sf *) __P,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_expandloadu_epi32 (__m128i __W, __mmask8 __U, void const *__P) {
+ return (__m128i) __builtin_ia32_expandloadsi128_mask ((__v4si *) __P,
+ (__v4si) __W,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) {
+ return (__m128i) __builtin_ia32_expandloadsi128_mask ((__v4si *) __P,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_expandloadu_epi32 (__m256i __W, __mmask8 __U,
+ void const *__P) {
+ return (__m256i) __builtin_ia32_expandloadsi256_mask ((__v8si *) __P,
+ (__v8si) __W,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_expandloadu_epi32 (__mmask8 __U, void const *__P) {
+ return (__m256i) __builtin_ia32_expandloadsi256_mask ((__v8si *) __P,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_expand_ps (__m128 __W, __mmask8 __U, __m128 __A) {
+ return (__m128) __builtin_ia32_expandsf128_mask ((__v4sf) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_expand_ps (__mmask8 __U, __m128 __A) {
+ return (__m128) __builtin_ia32_expandsf128_mask ((__v4sf) __A,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_expand_ps (__m256 __W, __mmask8 __U, __m256 __A) {
+ return (__m256) __builtin_ia32_expandsf256_mask ((__v8sf) __A,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_expand_ps (__mmask8 __U, __m256 __A) {
+ return (__m256) __builtin_ia32_expandsf256_mask ((__v8sf) __A,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_expand_epi32 (__m128i __W, __mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_expandsi128_mask ((__v4si) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_expand_epi32 (__mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_expandsi128_mask ((__v4si) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_expand_epi32 (__m256i __W, __mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_expandsi256_mask ((__v8si) __A,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_expand_epi32 (__mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_expandsi256_mask ((__v8si) __A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_getexp_pd (__m128d __A) {
+ return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_getexp_pd (__m128d __W, __mmask8 __U, __m128d __A) {
+ return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_getexp_pd (__mmask8 __U, __m128d __A) {
+ return (__m128d) __builtin_ia32_getexppd128_mask ((__v2df) __A,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_getexp_pd (__m256d __A) {
+ return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_getexp_pd (__m256d __W, __mmask8 __U, __m256d __A) {
+ return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_getexp_pd (__mmask8 __U, __m256d __A) {
+ return (__m256d) __builtin_ia32_getexppd256_mask ((__v4df) __A,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_getexp_ps (__m128 __A) {
+ return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_getexp_ps (__m128 __W, __mmask8 __U, __m128 __A) {
+ return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_getexp_ps (__mmask8 __U, __m128 __A) {
+ return (__m128) __builtin_ia32_getexpps128_mask ((__v4sf) __A,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_getexp_ps (__m256 __A) {
+ return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_getexp_ps (__m256 __W, __mmask8 __U, __m256 __A) {
+ return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_getexp_ps (__mmask8 __U, __m256 __A) {
+ return (__m256) __builtin_ia32_getexpps256_mask ((__v8sf) __A,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_max_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_maxpd_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_max_pd (__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_maxpd_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_max_pd (__m256d __W, __mmask8 __U, __m256d __A,
+ __m256d __B) {
+ return (__m256d) __builtin_ia32_maxpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_max_pd (__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_maxpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_max_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_maxps_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_max_ps (__mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_maxps_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_max_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_maxps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_max_ps (__mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_maxps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_min_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_minpd_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_min_pd (__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_minpd_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_min_pd (__m256d __W, __mmask8 __U, __m256d __A,
+ __m256d __B) {
+ return (__m256d) __builtin_ia32_minpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_min_pd (__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_minpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_min_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_minps_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_min_ps (__mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_minps_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_min_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_minps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_min_ps (__mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_minps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_mul_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_mulpd_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_mul_pd (__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_mulpd_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_mul_pd (__m256d __W, __mmask8 __U, __m256d __A,
+ __m256d __B) {
+ return (__m256d) __builtin_ia32_mulpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_mul_pd (__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_mulpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_mul_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_mulps_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_mul_ps (__mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_mulps_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_mul_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_mulps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_mul_ps (__mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_mulps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_abs_epi32 (__m128i __W, __mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_pabsd128_mask ((__v4si) __A,
+ (__v4si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_abs_epi32 (__mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_pabsd128_mask ((__v4si) __A,
+ (__v4si)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_abs_epi32 (__m256i __W, __mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_pabsd256_mask ((__v8si) __A,
+ (__v8si) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_abs_epi32 (__mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_pabsd256_mask ((__v8si) __A,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_abs_epi64 (__m128i __A) {
+ return (__m128i) __builtin_ia32_pabsq128_mask ((__v2di) __A,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_abs_epi64 (__m128i __W, __mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_pabsq128_mask ((__v2di) __A,
+ (__v2di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_abs_epi64 (__mmask8 __U, __m128i __A) {
+ return (__m128i) __builtin_ia32_pabsq128_mask ((__v2di) __A,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_abs_epi64 (__m256i __A) {
+ return (__m256i) __builtin_ia32_pabsq256_mask ((__v4di) __A,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_abs_epi64 (__m256i __W, __mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_pabsq256_mask ((__v4di) __A,
+ (__v4di) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_abs_epi64 (__mmask8 __U, __m256i __A) {
+ return (__m256i) __builtin_ia32_pabsq256_mask ((__v4di) __A,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_max_epi32 (__mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaxsd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_max_epi32 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaxsd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_max_epi32 (__mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaxsd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_max_epi32 (__m256i __W, __mmask8 __M, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaxsd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_max_epi64 (__mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaxsq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_max_epi64 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaxsq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_max_epi64 (__m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaxsq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_max_epi64 (__mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaxsq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_max_epi64 (__m256i __W, __mmask8 __M, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaxsq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_max_epi64 (__m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaxsq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_max_epu32 (__mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaxud128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_max_epu32 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaxud128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_max_epu32 (__mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaxud256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_max_epu32 (__m256i __W, __mmask8 __M, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaxud256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_max_epu64 (__mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaxuq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_max_epu64 (__m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaxuq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_max_epu64 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_pmaxuq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_max_epu64 (__mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaxuq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_max_epu64 (__m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaxuq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_max_epu64 (__m256i __W, __mmask8 __M, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_pmaxuq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_min_epi32 (__mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pminsd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_min_epi32 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_pminsd128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_min_epi32 (__mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pminsd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_min_epi32 (__m256i __W, __mmask8 __M, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_pminsd256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_min_epi64 (__m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pminsq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_min_epi64 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_pminsq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_min_epi64 (__mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pminsq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_min_epi64 (__m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pminsq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_min_epi64 (__m256i __W, __mmask8 __M, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_pminsq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_min_epi64 (__mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pminsq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_min_epu32 (__mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pminud128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si)
+ _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_min_epu32 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_pminud128_mask ((__v4si) __A,
+ (__v4si) __B,
+ (__v4si) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_min_epu32 (__mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pminud256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si)
+ _mm256_setzero_si256 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_min_epu32 (__m256i __W, __mmask8 __M, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_pminud256_mask ((__v8si) __A,
+ (__v8si) __B,
+ (__v8si) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_min_epu64 (__m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pminuq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_min_epu64 (__m128i __W, __mmask8 __M, __m128i __A,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_pminuq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di) __W, __M);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_min_epu64 (__mmask8 __M, __m128i __A, __m128i __B) {
+ return (__m128i) __builtin_ia32_pminuq128_mask ((__v2di) __A,
+ (__v2di) __B,
+ (__v2di)
+ _mm_setzero_si128 (),
+ __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_min_epu64 (__m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pminuq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_min_epu64 (__m256i __W, __mmask8 __M, __m256i __A,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_pminuq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di) __W, __M);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_min_epu64 (__mmask8 __M, __m256i __A, __m256i __B) {
+ return (__m256i) __builtin_ia32_pminuq256_mask ((__v4di) __A,
+ (__v4di) __B,
+ (__v4di)
+ _mm256_setzero_si256 (),
+ __M);
+}
+
+#define _mm_roundscale_pd(__A, __imm) __extension__ ({ \
+ (__m128d) __builtin_ia32_rndscalepd_128_mask ((__v2df) __A, \
+ __imm, (__v2df) _mm_setzero_pd (), (__mmask8) -1); })
+
+
+#define _mm_mask_roundscale_pd(__W, __U, __A, __imm) __extension__ ({ \
+ (__m128d) __builtin_ia32_rndscalepd_128_mask ((__v2df) __A, __imm, \
+ (__v2df) __W, (__mmask8) __U); })
+
+
+#define _mm_maskz_roundscale_pd(__U, __A, __imm) __extension__ ({ \
+ (__m128d) __builtin_ia32_rndscalepd_128_mask ((__v2df) __A, __imm, \
+ (__v2df) _mm_setzero_pd (), (__mmask8) __U); })
+
+
+#define _mm256_roundscale_pd(__A, __imm) __extension__ ({ \
+ (__m256d) __builtin_ia32_rndscalepd_256_mask ((__v4df) __A, __imm, \
+ (__v4df) _mm256_setzero_pd (), (__mmask8) -1); })
+
+
+#define _mm256_mask_roundscale_pd(__W, __U, __A, __imm) __extension__ ({ \
+ (__m256d) __builtin_ia32_rndscalepd_256_mask ((__v4df) __A, __imm, \
+ (__v4df) __W, (__mmask8) __U); })
+
+
+#define _mm256_maskz_roundscale_pd(__U, __A, __imm) __extension__ ({ \
+ (__m256d) __builtin_ia32_rndscalepd_256_mask ((__v4df) __A, __imm, \
+ (__v4df) _mm256_setzero_pd(), (__mmask8) __U); })
+
+#define _mm_roundscale_ps(__A, __imm) __extension__ ({ \
+ (__m128) __builtin_ia32_rndscaleps_128_mask ((__v4sf) __A, __imm, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) -1); })
+
+
+#define _mm_mask_roundscale_ps(__W, __U, __A, __imm) __extension__ ({ \
+ (__m128) __builtin_ia32_rndscaleps_128_mask ((__v4sf) __A, __imm, \
+ (__v4sf) __W, (__mmask8) __U); })
+
+
+#define _mm_maskz_roundscale_ps(__U, __A, __imm) __extension__ ({ \
+ (__m128) __builtin_ia32_rndscaleps_128_mask ((__v4sf) __A, __imm, \
+ (__v4sf) _mm_setzero_ps(), (__mmask8) __U); })
+
+#define _mm256_roundscale_ps(__A, __imm) __extension__ ({ \
+ (__m256) __builtin_ia32_rndscaleps_256_mask ((__v8sf) __A,__imm, \
+ (__v8sf) _mm256_setzero_ps(), (__mmask8) -1); })
+
+#define _mm256_mask_roundscale_ps(__W, __U, __A,__imm) __extension__ ({ \
+ (__m256) __builtin_ia32_rndscaleps_256_mask ((__v8sf) __A, __imm, \
+ (__v8sf) __W, (__mmask8) __U); })
+
+
+#define _mm256_maskz_roundscale_ps(__U, __A, __imm) __extension__ ({ \
+ (__m256) __builtin_ia32_rndscaleps_256_mask ((__v8sf) __A, __imm, \
+ (__v8sf) _mm256_setzero_ps(), (__mmask8) __U); })
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_scalef_pd (__m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_scalef_pd (__m128d __W, __mmask8 __U, __m128d __A,
+ __m128d __B) {
+ return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_scalef_pd (__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_scalefpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_scalef_pd (__m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_scalef_pd (__m256d __W, __mmask8 __U, __m256d __A,
+ __m256d __B) {
+ return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_scalef_pd (__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_scalefpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_scalef_ps (__m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_scalef_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_scalef_ps (__mmask8 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_scalefps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_scalef_ps (__m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) -1);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_scalef_ps (__m256 __W, __mmask8 __U, __m256 __A,
+ __m256 __B) {
+ return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_scalefps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+#define _mm_i64scatter_pd(__addr,__index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv2df(__addr, (__mmask8) 0xFF, (__v2di) __index, \
+ (__v2df) __v1, __scale); })
+
+#define _mm_mask_i64scatter_pd(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv2df (__addr, __mask, (__v2di) __index, \
+ (__v2df) __v1, __scale); })
+
+
+#define _mm_i64scatter_epi64(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv2di (__addr, (__mmask8) 0xFF, \
+ (__v2di) __index, (__v2di) __v1, __scale); })
+
+#define _mm_mask_i64scatter_epi64(__addr, __mask, __index, __v1,\
+ __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv2di (__addr, __mask, (__v2di) __index,\
+ (__v2di) __v1, __scale); })
+
+#define _mm256_i64scatter_pd(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv4df (__addr, (__mmask8) 0xFF,\
+ (__v4di) __index, (__v4df) __v1, __scale); })
+
+#define _mm256_mask_i64scatter_pd(__addr, __mask, __index, __v1,\
+ __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv4df (__addr, __mask, (__v4di) __index,\
+ (__v4df) __v1, __scale); })
+
+#define _mm256_i64scatter_epi64(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv4di (__addr, (__mmask8) 0xFF, (__v4di) __index,\
+ (__v4di) __v1, __scale); })
+
+#define _mm256_mask_i64scatter_epi64(__addr, __mask, __index, __v1,\
+ __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv4di (__addr, __mask, (__v4di) __index,\
+ (__v4di) __v1, __scale); })
+
+#define _mm_i64scatter_ps(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv4sf (__addr, (__mmask8) 0xFF,\
+ (__v2di) __index, (__v4sf) __v1, __scale); })
+
+#define _mm_mask_i64scatter_ps(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv4sf (__addr, __mask, (__v2di) __index,\
+ (__v4sf) __v1, __scale); })
+
+#define _mm_i64scatter_epi32(__addr, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv4si (__addr, (__mmask8) 0xFF,\
+ (__v2di) __index, (__v4si) __v1, __scale); })
+
+#define _mm_mask_i64scatter_epi32(__addr, __mask, __index, __v1,\
+ __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv4si (__addr, __mask, (__v2di) __index,\
+ (__v4si) __v1, __scale); })
+
+#define _mm256_i64scatter_ps(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv8sf (__addr, (__mmask8) 0xFF, (__v4di) __index, \
+ (__v4sf) __v1, __scale); })
+
+#define _mm256_mask_i64scatter_ps(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv8sf (__addr, __mask, (__v4di) __index, \
+ (__v4sf) __v1, __scale); })
+
+#define _mm256_i64scatter_epi32(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv8si (__addr, (__mmask8) 0xFF, \
+ (__v4di) __index, (__v4si) __v1, __scale); })
+
+#define _mm256_mask_i64scatter_epi32(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scatterdiv8si(__addr, __mask, (__v4di) __index, \
+ (__v4si) __v1, __scale); })
+
+#define _mm_i32scatter_pd(__addr, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv2df (__addr, (__mmask8) 0xFF, \
+ (__v4si) __index, (__v2df) __v1, __scale); })
+
+#define _mm_mask_i32scatter_pd(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv2df (__addr, __mask, (__v4si) __index,\
+ (__v2df) __v1, __scale); })
+
+#define _mm_i32scatter_epi64(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv2di (__addr, (__mmask8) 0xFF, \
+ (__v4si) __index, (__v2di) __v1, __scale); })
+
+#define _mm_mask_i32scatter_epi64(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv2di (__addr, __mask, (__v4si) __index, \
+ (__v2di) __v1, __scale); })
+
+#define _mm256_i32scatter_pd(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv4df (__addr, (__mmask8) 0xFF, \
+ (__v4si) __index, (__v4df) __v1, __scale); })
+
+#define _mm256_mask_i32scatter_pd(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv4df (__addr, __mask, (__v4si) __index, \
+ (__v4df) __v1, __scale); })
+
+#define _mm256_i32scatter_epi64(__addr, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv4di (__addr, (__mmask8) 0xFF, \
+ (__v4si) __index, (__v4di) __v1, __scale); })
+
+#define _mm256_mask_i32scatter_epi64(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv4di (__addr, __mask, (__v4si) __index, \
+ (__v4di) __v1, __scale); })
+
+#define _mm_i32scatter_ps(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv4sf (__addr, (__mmask8) 0xFF, \
+ (__v4si) __index, (__v4sf) __v1, __scale); })
+
+#define _mm_mask_i32scatter_ps(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv4sf (__addr, __mask, (__v4si) __index, \
+ (__v4sf) __v1, __scale); })
+
+#define _mm_i32scatter_epi32(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv4si (__addr, (__mmask8) 0xFF, \
+ (__v4si) __index, (__v4si) __v1, __scale); })
+
+#define _mm_mask_i32scatter_epi32(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv4si (__addr, __mask, (__v4si) __index,\
+ (__v4si) __v1, __scale); })
+
+#define _mm256_i32scatter_ps(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv8sf (__addr, (__mmask8) 0xFF, \
+ (__v8si) __index, (__v8sf) __v1, __scale); })
+
+#define _mm256_mask_i32scatter_ps(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv8sf (__addr, __mask, (__v8si) __index,\
+ (__v8sf) __v1, __scale); })
+
+#define _mm256_i32scatter_epi32(__addr, __index, __v1, __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv8si (__addr, (__mmask8) 0xFF, \
+ (__v8si) __index, (__v8si) __v1, __scale); })
+
+#define _mm256_mask_i32scatter_epi32(__addr, __mask, __index, __v1, \
+ __scale) __extension__ ({ \
+ __builtin_ia32_scattersiv8si (__addr, __mask, (__v8si) __index, \
+ (__v8si) __v1, __scale); })
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_sqrt_pd (__m128d __W, __mmask8 __U, __m128d __A) {
+ return (__m128d) __builtin_ia32_sqrtpd128_mask ((__v2df) __A,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_sqrt_pd (__mmask8 __U, __m128d __A) {
+ return (__m128d) __builtin_ia32_sqrtpd128_mask ((__v2df) __A,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_sqrt_pd (__m256d __W, __mmask8 __U, __m256d __A) {
+ return (__m256d) __builtin_ia32_sqrtpd256_mask ((__v4df) __A,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_sqrt_pd (__mmask8 __U, __m256d __A) {
+ return (__m256d) __builtin_ia32_sqrtpd256_mask ((__v4df) __A,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_sqrt_ps (__m128 __W, __mmask8 __U, __m128 __A) {
+ return (__m128) __builtin_ia32_sqrtps128_mask ((__v4sf) __A,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_sqrt_ps (__mmask8 __U, __m128 __A) {
+ return (__m128) __builtin_ia32_sqrtps128_mask ((__v4sf) __A,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_sqrt_ps (__m256 __W, __mmask8 __U, __m256 __A) {
+ return (__m256) __builtin_ia32_sqrtps256_mask ((__v8sf) __A,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_sqrt_ps (__mmask8 __U, __m256 __A) {
+ return (__m256) __builtin_ia32_sqrtps256_mask ((__v8sf) __A,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_sub_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_subpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_sub_pd (__mmask8 __U, __m128d __A, __m128d __B) {
+ return (__m128d) __builtin_ia32_subpd128_mask ((__v2df) __A,
+ (__v2df) __B,
+ (__v2df)
+ _mm_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_sub_pd (__m256d __W, __mmask8 __U, __m256d __A,
+ __m256d __B) {
+ return (__m256d) __builtin_ia32_subpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_sub_pd (__mmask8 __U, __m256d __A, __m256d __B) {
+ return (__m256d) __builtin_ia32_subpd256_mask ((__v4df) __A,
+ (__v4df) __B,
+ (__v4df)
+ _mm256_setzero_pd (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_sub_ps (__m128 __W, __mmask16 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_subps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_sub_ps (__mmask16 __U, __m128 __A, __m128 __B) {
+ return (__m128) __builtin_ia32_subps128_mask ((__v4sf) __A,
+ (__v4sf) __B,
+ (__v4sf)
+ _mm_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_sub_ps (__m256 __W, __mmask16 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_subps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf) __W,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_sub_ps (__mmask16 __U, __m256 __A, __m256 __B) {
+ return (__m256) __builtin_ia32_subps256_mask ((__v8sf) __A,
+ (__v8sf) __B,
+ (__v8sf)
+ _mm256_setzero_ps (),
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask2_permutex2var_epi32 (__m128i __A, __m128i __I, __mmask8 __U,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_vpermi2vard128_mask ((__v4si) __A,
+ (__v4si) __I
+ /* idx */ ,
+ (__v4si) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask2_permutex2var_epi32 (__m256i __A, __m256i __I,
+ __mmask8 __U, __m256i __B) {
+ return (__m256i) __builtin_ia32_vpermi2vard256_mask ((__v8si) __A,
+ (__v8si) __I
+ /* idx */ ,
+ (__v8si) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask2_permutex2var_pd (__m128d __A, __m128i __I, __mmask8 __U,
+ __m128d __B) {
+ return (__m128d) __builtin_ia32_vpermi2varpd128_mask ((__v2df) __A,
+ (__v2di) __I
+ /* idx */ ,
+ (__v2df) __B,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask2_permutex2var_pd (__m256d __A, __m256i __I, __mmask8 __U,
+ __m256d __B) {
+ return (__m256d) __builtin_ia32_vpermi2varpd256_mask ((__v4df) __A,
+ (__v4di) __I
+ /* idx */ ,
+ (__v4df) __B,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask2_permutex2var_ps (__m128 __A, __m128i __I, __mmask8 __U,
+ __m128 __B) {
+ return (__m128) __builtin_ia32_vpermi2varps128_mask ((__v4sf) __A,
+ (__v4si) __I
+ /* idx */ ,
+ (__v4sf) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask2_permutex2var_ps (__m256 __A, __m256i __I, __mmask8 __U,
+ __m256 __B) {
+ return (__m256) __builtin_ia32_vpermi2varps256_mask ((__v8sf) __A,
+ (__v8si) __I
+ /* idx */ ,
+ (__v8sf) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask2_permutex2var_epi64 (__m128i __A, __m128i __I, __mmask8 __U,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_vpermi2varq128_mask ((__v2di) __A,
+ (__v2di) __I
+ /* idx */ ,
+ (__v2di) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask2_permutex2var_epi64 (__m256i __A, __m256i __I,
+ __mmask8 __U, __m256i __B) {
+ return (__m256i) __builtin_ia32_vpermi2varq256_mask ((__v4di) __A,
+ (__v4di) __I
+ /* idx */ ,
+ (__v4di) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_permutex2var_epi32 (__m128i __A, __m128i __I, __m128i __B) {
+ return (__m128i) __builtin_ia32_vpermt2vard128_mask ((__v4si) __I
+ /* idx */ ,
+ (__v4si) __A,
+ (__v4si) __B,
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_permutex2var_epi32 (__m128i __A, __mmask8 __U, __m128i __I,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_vpermt2vard128_mask ((__v4si) __I
+ /* idx */ ,
+ (__v4si) __A,
+ (__v4si) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_permutex2var_epi32 (__mmask8 __U, __m128i __A, __m128i __I,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_vpermt2vard128_maskz ((__v4si) __I
+ /* idx */ ,
+ (__v4si) __A,
+ (__v4si) __B,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_permutex2var_epi32 (__m256i __A, __m256i __I, __m256i __B) {
+ return (__m256i) __builtin_ia32_vpermt2vard256_mask ((__v8si) __I
+ /* idx */ ,
+ (__v8si) __A,
+ (__v8si) __B,
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_permutex2var_epi32 (__m256i __A, __mmask8 __U, __m256i __I,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_vpermt2vard256_mask ((__v8si) __I
+ /* idx */ ,
+ (__v8si) __A,
+ (__v8si) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_permutex2var_epi32 (__mmask8 __U, __m256i __A,
+ __m256i __I, __m256i __B) {
+ return (__m256i) __builtin_ia32_vpermt2vard256_maskz ((__v8si) __I
+ /* idx */ ,
+ (__v8si) __A,
+ (__v8si) __B,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_permutex2var_pd (__m128d __A, __m128i __I, __m128d __B) {
+ return (__m128d) __builtin_ia32_vpermt2varpd128_mask ((__v2di) __I
+ /* idx */ ,
+ (__v2df) __A,
+ (__v2df) __B,
+ (__mmask8) -
+ 1);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_mask_permutex2var_pd (__m128d __A, __mmask8 __U, __m128i __I,
+ __m128d __B) {
+ return (__m128d) __builtin_ia32_vpermt2varpd128_mask ((__v2di) __I
+ /* idx */ ,
+ (__v2df) __A,
+ (__v2df) __B,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_permutex2var_pd (__mmask8 __U, __m128d __A, __m128i __I,
+ __m128d __B) {
+ return (__m128d) __builtin_ia32_vpermt2varpd128_maskz ((__v2di) __I
+ /* idx */ ,
+ (__v2df) __A,
+ (__v2df) __B,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_permutex2var_pd (__m256d __A, __m256i __I, __m256d __B) {
+ return (__m256d) __builtin_ia32_vpermt2varpd256_mask ((__v4di) __I
+ /* idx */ ,
+ (__v4df) __A,
+ (__v4df) __B,
+ (__mmask8) -
+ 1);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_mask_permutex2var_pd (__m256d __A, __mmask8 __U, __m256i __I,
+ __m256d __B) {
+ return (__m256d) __builtin_ia32_vpermt2varpd256_mask ((__v4di) __I
+ /* idx */ ,
+ (__v4df) __A,
+ (__v4df) __B,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_maskz_permutex2var_pd (__mmask8 __U, __m256d __A, __m256i __I,
+ __m256d __B) {
+ return (__m256d) __builtin_ia32_vpermt2varpd256_maskz ((__v4di) __I
+ /* idx */ ,
+ (__v4df) __A,
+ (__v4df) __B,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_permutex2var_ps (__m128 __A, __m128i __I, __m128 __B) {
+ return (__m128) __builtin_ia32_vpermt2varps128_mask ((__v4si) __I
+ /* idx */ ,
+ (__v4sf) __A,
+ (__v4sf) __B,
+ (__mmask8) -1);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_mask_permutex2var_ps (__m128 __A, __mmask8 __U, __m128i __I,
+ __m128 __B) {
+ return (__m128) __builtin_ia32_vpermt2varps128_mask ((__v4si) __I
+ /* idx */ ,
+ (__v4sf) __A,
+ (__v4sf) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_permutex2var_ps (__mmask8 __U, __m128 __A, __m128i __I,
+ __m128 __B) {
+ return (__m128) __builtin_ia32_vpermt2varps128_maskz ((__v4si) __I
+ /* idx */ ,
+ (__v4sf) __A,
+ (__v4sf) __B,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_permutex2var_ps (__m256 __A, __m256i __I, __m256 __B) {
+ return (__m256) __builtin_ia32_vpermt2varps256_mask ((__v8si) __I
+ /* idx */ ,
+ (__v8sf) __A,
+ (__v8sf) __B,
+ (__mmask8) -1);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_mask_permutex2var_ps (__m256 __A, __mmask8 __U, __m256i __I,
+ __m256 __B) {
+ return (__m256) __builtin_ia32_vpermt2varps256_mask ((__v8si) __I
+ /* idx */ ,
+ (__v8sf) __A,
+ (__v8sf) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_maskz_permutex2var_ps (__mmask8 __U, __m256 __A, __m256i __I,
+ __m256 __B) {
+ return (__m256) __builtin_ia32_vpermt2varps256_maskz ((__v8si) __I
+ /* idx */ ,
+ (__v8sf) __A,
+ (__v8sf) __B,
+ (__mmask8)
+ __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_permutex2var_epi64 (__m128i __A, __m128i __I, __m128i __B) {
+ return (__m128i) __builtin_ia32_vpermt2varq128_mask ((__v2di) __I
+ /* idx */ ,
+ (__v2di) __A,
+ (__v2di) __B,
+ (__mmask8) -1);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_permutex2var_epi64 (__m128i __A, __mmask8 __U, __m128i __I,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_vpermt2varq128_mask ((__v2di) __I
+ /* idx */ ,
+ (__v2di) __A,
+ (__v2di) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_permutex2var_epi64 (__mmask8 __U, __m128i __A, __m128i __I,
+ __m128i __B) {
+ return (__m128i) __builtin_ia32_vpermt2varq128_maskz ((__v2di) __I
+ /* idx */ ,
+ (__v2di) __A,
+ (__v2di) __B,
+ (__mmask8)
+ __U);
+}
+
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_permutex2var_epi64 (__m256i __A, __m256i __I, __m256i __B) {
+ return (__m256i) __builtin_ia32_vpermt2varq256_mask ((__v4di) __I
+ /* idx */ ,
+ (__v4di) __A,
+ (__v4di) __B,
+ (__mmask8) -1);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_permutex2var_epi64 (__m256i __A, __mmask8 __U, __m256i __I,
+ __m256i __B) {
+ return (__m256i) __builtin_ia32_vpermt2varq256_mask ((__v4di) __I
+ /* idx */ ,
+ (__v4di) __A,
+ (__v4di) __B,
+ (__mmask8) __U);
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_permutex2var_epi64 (__mmask8 __U, __m256i __A,
+ __m256i __I, __m256i __B) {
+ return (__m256i) __builtin_ia32_vpermt2varq256_maskz ((__v4di) __I
+ /* idx */ ,
+ (__v4di) __A,
+ (__v4di) __B,
+ (__mmask8)
+ __U);
+}
+
#undef __DEFAULT_FN_ATTRS
+#undef __DEFAULT_FN_ATTRS_BOTH
#endif /* __AVX512VLINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/avxintrin.h b/contrib/llvm/tools/clang/lib/Headers/avxintrin.h
index c1bc85b..6d1ca54 100644
--- a/contrib/llvm/tools/clang/lib/Headers/avxintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/avxintrin.h
@@ -35,12 +35,16 @@ typedef int __v8si __attribute__ ((__vector_size__ (32)));
typedef short __v16hi __attribute__ ((__vector_size__ (32)));
typedef char __v32qi __attribute__ ((__vector_size__ (32)));
+/* We need an explicitly signed variant for char. Note that this shouldn't
+ * appear in the interface though. */
+typedef signed char __v32qs __attribute__((__vector_size__(32)));
+
typedef float __m256 __attribute__ ((__vector_size__ (32)));
typedef double __m256d __attribute__((__vector_size__(32)));
typedef long long __m256i __attribute__((__vector_size__(32)));
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("avx")))
/* Arithmetic */
static __inline __m256d __DEFAULT_FN_ATTRS
@@ -152,12 +156,10 @@ _mm256_rcp_ps(__m256 __a)
}
#define _mm256_round_pd(V, M) __extension__ ({ \
- __m256d __V = (V); \
- (__m256d)__builtin_ia32_roundpd256((__v4df)__V, (M)); })
+ (__m256d)__builtin_ia32_roundpd256((__v4df)(__m256d)(V), (M)); })
#define _mm256_round_ps(V, M) __extension__ ({ \
- __m256 __V = (V); \
- (__m256)__builtin_ia32_roundps256((__v8sf)__V, (M)); })
+ (__m256)__builtin_ia32_roundps256((__v8sf)(__m256)(V), (M)); })
#define _mm256_ceil_pd(V) _mm256_round_pd((V), _MM_FROUND_CEIL)
#define _mm256_floor_pd(V) _mm256_round_pd((V), _MM_FROUND_FLOOR)
@@ -264,26 +266,26 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
}
#define _mm_permute_pd(A, C) __extension__ ({ \
- __m128d __A = (A); \
- (__m128d)__builtin_shufflevector((__v2df)__A, (__v2df) _mm_setzero_pd(), \
+ (__m128d)__builtin_shufflevector((__v2df)(__m128d)(A), \
+ (__v2df)_mm_setzero_pd(), \
(C) & 0x1, ((C) & 0x2) >> 1); })
#define _mm256_permute_pd(A, C) __extension__ ({ \
- __m256d __A = (A); \
- (__m256d)__builtin_shufflevector((__v4df)__A, (__v4df) _mm256_setzero_pd(), \
+ (__m256d)__builtin_shufflevector((__v4df)(__m256d)(A), \
+ (__v4df)_mm256_setzero_pd(), \
(C) & 0x1, ((C) & 0x2) >> 1, \
2 + (((C) & 0x4) >> 2), \
2 + (((C) & 0x8) >> 3)); })
#define _mm_permute_ps(A, C) __extension__ ({ \
- __m128 __A = (A); \
- (__m128)__builtin_shufflevector((__v4sf)__A, (__v4sf) _mm_setzero_ps(), \
+ (__m128)__builtin_shufflevector((__v4sf)(__m128)(A), \
+ (__v4sf)_mm_setzero_ps(), \
(C) & 0x3, ((C) & 0xc) >> 2, \
((C) & 0x30) >> 4, ((C) & 0xc0) >> 6); })
#define _mm256_permute_ps(A, C) __extension__ ({ \
- __m256 __A = (A); \
- (__m256)__builtin_shufflevector((__v8sf)__A, (__v8sf) _mm256_setzero_ps(), \
+ (__m256)__builtin_shufflevector((__v8sf)(__m256)(A), \
+ (__v8sf)_mm256_setzero_ps(), \
(C) & 0x3, ((C) & 0xc) >> 2, \
((C) & 0x30) >> 4, ((C) & 0xc0) >> 6, \
4 + (((C) & 0x03) >> 0), \
@@ -292,34 +294,29 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
4 + (((C) & 0xc0) >> 6)); })
#define _mm256_permute2f128_pd(V1, V2, M) __extension__ ({ \
- __m256d __V1 = (V1); \
- __m256d __V2 = (V2); \
- (__m256d)__builtin_ia32_vperm2f128_pd256((__v4df)__V1, (__v4df)__V2, (M)); })
+ (__m256d)__builtin_ia32_vperm2f128_pd256((__v4df)(__m256d)(V1), \
+ (__v4df)(__m256d)(V2), (M)); })
#define _mm256_permute2f128_ps(V1, V2, M) __extension__ ({ \
- __m256 __V1 = (V1); \
- __m256 __V2 = (V2); \
- (__m256)__builtin_ia32_vperm2f128_ps256((__v8sf)__V1, (__v8sf)__V2, (M)); })
+ (__m256)__builtin_ia32_vperm2f128_ps256((__v8sf)(__m256)(V1), \
+ (__v8sf)(__m256)(V2), (M)); })
#define _mm256_permute2f128_si256(V1, V2, M) __extension__ ({ \
- __m256i __V1 = (V1); \
- __m256i __V2 = (V2); \
- (__m256i)__builtin_ia32_vperm2f128_si256((__v8si)__V1, (__v8si)__V2, (M)); })
+ (__m256i)__builtin_ia32_vperm2f128_si256((__v8si)(__m256i)(V1), \
+ (__v8si)(__m256i)(V2), (M)); })
/* Vector Blend */
#define _mm256_blend_pd(V1, V2, M) __extension__ ({ \
- __m256d __V1 = (V1); \
- __m256d __V2 = (V2); \
- (__m256d)__builtin_shufflevector((__v4df)__V1, (__v4df)__V2, \
+ (__m256d)__builtin_shufflevector((__v4df)(__m256d)(V1), \
+ (__v4df)(__m256d)(V2), \
(((M) & 0x01) ? 4 : 0), \
(((M) & 0x02) ? 5 : 1), \
(((M) & 0x04) ? 6 : 2), \
(((M) & 0x08) ? 7 : 3)); })
#define _mm256_blend_ps(V1, V2, M) __extension__ ({ \
- __m256 __V1 = (V1); \
- __m256 __V2 = (V2); \
- (__m256)__builtin_shufflevector((__v8sf)__V1, (__v8sf)__V2, \
+ (__m256)__builtin_shufflevector((__v8sf)(__m256)(V1), \
+ (__v8sf)(__m256)(V2), \
(((M) & 0x01) ? 8 : 0), \
(((M) & 0x02) ? 9 : 1), \
(((M) & 0x04) ? 10 : 2), \
@@ -345,28 +342,29 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/* Vector Dot Product */
#define _mm256_dp_ps(V1, V2, M) __extension__ ({ \
- __m256 __V1 = (V1); \
- __m256 __V2 = (V2); \
- (__m256)__builtin_ia32_dpps256((__v8sf)__V1, (__v8sf)__V2, (M)); })
+ (__m256)__builtin_ia32_dpps256((__v8sf)(__m256)(V1), \
+ (__v8sf)(__m256)(V2), (M)); })
/* Vector shuffle */
#define _mm256_shuffle_ps(a, b, mask) __extension__ ({ \
- __m256 __a = (a); \
- __m256 __b = (b); \
- (__m256)__builtin_shufflevector((__v8sf)__a, (__v8sf)__b, \
- (mask) & 0x3, ((mask) & 0xc) >> 2, \
- (((mask) & 0x30) >> 4) + 8, (((mask) & 0xc0) >> 6) + 8, \
- ((mask) & 0x3) + 4, (((mask) & 0xc) >> 2) + 4, \
- (((mask) & 0x30) >> 4) + 12, (((mask) & 0xc0) >> 6) + 12); })
+ (__m256)__builtin_shufflevector((__v8sf)(__m256)(a), \
+ (__v8sf)(__m256)(b), \
+ (mask) & 0x3, \
+ ((mask) & 0xc) >> 2, \
+ (((mask) & 0x30) >> 4) + 8, \
+ (((mask) & 0xc0) >> 6) + 8, \
+ ((mask) & 0x3) + 4, \
+ (((mask) & 0xc) >> 2) + 4, \
+ (((mask) & 0x30) >> 4) + 12, \
+ (((mask) & 0xc0) >> 6) + 12); })
#define _mm256_shuffle_pd(a, b, mask) __extension__ ({ \
- __m256d __a = (a); \
- __m256d __b = (b); \
- (__m256d)__builtin_shufflevector((__v4df)__a, (__v4df)__b, \
- (mask) & 0x1, \
- (((mask) & 0x2) >> 1) + 4, \
- (((mask) & 0x4) >> 2) + 2, \
- (((mask) & 0x8) >> 3) + 6); })
+ (__m256d)__builtin_shufflevector((__v4df)(__m256d)(a), \
+ (__v4df)(__m256d)(b), \
+ (mask) & 0x1, \
+ (((mask) & 0x2) >> 1) + 4, \
+ (((mask) & 0x4) >> 2) + 2, \
+ (((mask) & 0x8) >> 3) + 6); })
/* Compare */
#define _CMP_EQ_OQ 0x00 /* Equal (ordered, non-signaling) */
@@ -403,34 +401,28 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
#define _CMP_TRUE_US 0x1f /* True (unordered, signaling) */
#define _mm_cmp_pd(a, b, c) __extension__ ({ \
- __m128d __a = (a); \
- __m128d __b = (b); \
- (__m128d)__builtin_ia32_cmppd((__v2df)__a, (__v2df)__b, (c)); })
+ (__m128d)__builtin_ia32_cmppd((__v2df)(__m128d)(a), \
+ (__v2df)(__m128d)(b), (c)); })
#define _mm_cmp_ps(a, b, c) __extension__ ({ \
- __m128 __a = (a); \
- __m128 __b = (b); \
- (__m128)__builtin_ia32_cmpps((__v4sf)__a, (__v4sf)__b, (c)); })
+ (__m128)__builtin_ia32_cmpps((__v4sf)(__m128)(a), \
+ (__v4sf)(__m128)(b), (c)); })
#define _mm256_cmp_pd(a, b, c) __extension__ ({ \
- __m256d __a = (a); \
- __m256d __b = (b); \
- (__m256d)__builtin_ia32_cmppd256((__v4df)__a, (__v4df)__b, (c)); })
+ (__m256d)__builtin_ia32_cmppd256((__v4df)(__m256d)(a), \
+ (__v4df)(__m256d)(b), (c)); })
#define _mm256_cmp_ps(a, b, c) __extension__ ({ \
- __m256 __a = (a); \
- __m256 __b = (b); \
- (__m256)__builtin_ia32_cmpps256((__v8sf)__a, (__v8sf)__b, (c)); })
+ (__m256)__builtin_ia32_cmpps256((__v8sf)(__m256)(a), \
+ (__v8sf)(__m256)(b), (c)); })
#define _mm_cmp_sd(a, b, c) __extension__ ({ \
- __m128d __a = (a); \
- __m128d __b = (b); \
- (__m128d)__builtin_ia32_cmpsd((__v2df)__a, (__v2df)__b, (c)); })
+ (__m128d)__builtin_ia32_cmpsd((__v2df)(__m128d)(a), \
+ (__v2df)(__m128d)(b), (c)); })
#define _mm_cmp_ss(a, b, c) __extension__ ({ \
- __m128 __a = (a); \
- __m128 __b = (b); \
- (__m128)__builtin_ia32_cmpss((__v4sf)__a, (__v4sf)__b, (c)); })
+ (__m128)__builtin_ia32_cmpss((__v4sf)(__m128)(a), \
+ (__v4sf)(__m128)(b), (c)); })
static __inline int __DEFAULT_FN_ATTRS
_mm256_extract_epi32(__m256i __a, const int __imm)
@@ -831,53 +823,53 @@ _mm256_storeu_si256(__m256i *__p, __m256i __a)
/* Conditional load ops */
static __inline __m128d __DEFAULT_FN_ATTRS
-_mm_maskload_pd(double const *__p, __m128d __m)
+_mm_maskload_pd(double const *__p, __m128i __m)
{
- return (__m128d)__builtin_ia32_maskloadpd((const __v2df *)__p, (__v2df)__m);
+ return (__m128d)__builtin_ia32_maskloadpd((const __v2df *)__p, (__v2di)__m);
}
static __inline __m256d __DEFAULT_FN_ATTRS
-_mm256_maskload_pd(double const *__p, __m256d __m)
+_mm256_maskload_pd(double const *__p, __m256i __m)
{
return (__m256d)__builtin_ia32_maskloadpd256((const __v4df *)__p,
- (__v4df)__m);
+ (__v4di)__m);
}
static __inline __m128 __DEFAULT_FN_ATTRS
-_mm_maskload_ps(float const *__p, __m128 __m)
+_mm_maskload_ps(float const *__p, __m128i __m)
{
- return (__m128)__builtin_ia32_maskloadps((const __v4sf *)__p, (__v4sf)__m);
+ return (__m128)__builtin_ia32_maskloadps((const __v4sf *)__p, (__v4si)__m);
}
static __inline __m256 __DEFAULT_FN_ATTRS
-_mm256_maskload_ps(float const *__p, __m256 __m)
+_mm256_maskload_ps(float const *__p, __m256i __m)
{
- return (__m256)__builtin_ia32_maskloadps256((const __v8sf *)__p, (__v8sf)__m);
+ return (__m256)__builtin_ia32_maskloadps256((const __v8sf *)__p, (__v8si)__m);
}
/* Conditional store ops */
static __inline void __DEFAULT_FN_ATTRS
-_mm256_maskstore_ps(float *__p, __m256 __m, __m256 __a)
+_mm256_maskstore_ps(float *__p, __m256i __m, __m256 __a)
{
- __builtin_ia32_maskstoreps256((__v8sf *)__p, (__v8sf)__m, (__v8sf)__a);
+ __builtin_ia32_maskstoreps256((__v8sf *)__p, (__v8si)__m, (__v8sf)__a);
}
static __inline void __DEFAULT_FN_ATTRS
-_mm_maskstore_pd(double *__p, __m128d __m, __m128d __a)
+_mm_maskstore_pd(double *__p, __m128i __m, __m128d __a)
{
- __builtin_ia32_maskstorepd((__v2df *)__p, (__v2df)__m, (__v2df)__a);
+ __builtin_ia32_maskstorepd((__v2df *)__p, (__v2di)__m, (__v2df)__a);
}
static __inline void __DEFAULT_FN_ATTRS
-_mm256_maskstore_pd(double *__p, __m256d __m, __m256d __a)
+_mm256_maskstore_pd(double *__p, __m256i __m, __m256d __a)
{
- __builtin_ia32_maskstorepd256((__v4df *)__p, (__v4df)__m, (__v4df)__a);
+ __builtin_ia32_maskstorepd256((__v4df *)__p, (__v4di)__m, (__v4df)__a);
}
static __inline void __DEFAULT_FN_ATTRS
-_mm_maskstore_ps(float *__p, __m128 __m, __m128 __a)
+_mm_maskstore_ps(float *__p, __m128i __m, __m128 __a)
{
- __builtin_ia32_maskstoreps((__v4sf *)__p, (__v4sf)__m, (__v4sf)__a);
+ __builtin_ia32_maskstoreps((__v4sf *)__p, (__v4si)__m, (__v4sf)__a);
}
/* Cacheability support ops */
@@ -900,6 +892,24 @@ _mm256_stream_ps(float *__p, __m256 __a)
}
/* Create vectors */
+static __inline__ __m256d __DEFAULT_FN_ATTRS
+_mm256_undefined_pd()
+{
+ return (__m256d)__builtin_ia32_undef256();
+}
+
+static __inline__ __m256 __DEFAULT_FN_ATTRS
+_mm256_undefined_ps()
+{
+ return (__m256)__builtin_ia32_undef256();
+}
+
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_undefined_si256()
+{
+ return (__m256i)__builtin_ia32_undef256();
+}
+
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_set_pd(double __a, double __b, double __c, double __d)
{
@@ -1140,14 +1150,14 @@ _mm256_castsi128_si256(__m128i __a)
return __builtin_shufflevector(__a, __a, 0, 1, -1, -1);
}
-/*
+/*
Vector insert.
We use macros rather than inlines because we only want to accept
invocations where the immediate M is a constant expression.
*/
#define _mm256_insertf128_ps(V1, V2, M) __extension__ ({ \
(__m256)__builtin_shufflevector( \
- (__v8sf)(V1), \
+ (__v8sf)(__m256)(V1), \
(__v8sf)_mm256_castps128_ps256((__m128)(V2)), \
(((M) & 1) ? 0 : 8), \
(((M) & 1) ? 1 : 9), \
@@ -1160,7 +1170,7 @@ _mm256_castsi128_si256(__m128i __a)
#define _mm256_insertf128_pd(V1, V2, M) __extension__ ({ \
(__m256d)__builtin_shufflevector( \
- (__v4df)(V1), \
+ (__v4df)(__m256d)(V1), \
(__v4df)_mm256_castpd128_pd256((__m128d)(V2)), \
(((M) & 1) ? 0 : 4), \
(((M) & 1) ? 1 : 5), \
@@ -1169,21 +1179,21 @@ _mm256_castsi128_si256(__m128i __a)
#define _mm256_insertf128_si256(V1, V2, M) __extension__ ({ \
(__m256i)__builtin_shufflevector( \
- (__v4di)(V1), \
+ (__v4di)(__m256i)(V1), \
(__v4di)_mm256_castsi128_si256((__m128i)(V2)), \
(((M) & 1) ? 0 : 4), \
(((M) & 1) ? 1 : 5), \
(((M) & 1) ? 4 : 2), \
(((M) & 1) ? 5 : 3) );})
-/*
+/*
Vector extract.
We use macros rather than inlines because we only want to accept
invocations where the immediate M is a constant expression.
*/
#define _mm256_extractf128_ps(V, M) __extension__ ({ \
(__m128)__builtin_shufflevector( \
- (__v8sf)(V), \
+ (__v8sf)(__m256)(V), \
(__v8sf)(_mm256_setzero_ps()), \
(((M) & 1) ? 4 : 0), \
(((M) & 1) ? 5 : 1), \
@@ -1192,14 +1202,14 @@ _mm256_castsi128_si256(__m128i __a)
#define _mm256_extractf128_pd(V, M) __extension__ ({ \
(__m128d)__builtin_shufflevector( \
- (__v4df)(V), \
+ (__v4df)(__m256d)(V), \
(__v4df)(_mm256_setzero_pd()), \
(((M) & 1) ? 2 : 0), \
(((M) & 1) ? 3 : 1) );})
#define _mm256_extractf128_si256(V, M) __extension__ ({ \
(__m128i)__builtin_shufflevector( \
- (__v4di)(V), \
+ (__v4di)(__m256i)(V), \
(__v4di)(_mm256_setzero_si256()), \
(((M) & 1) ? 2 : 0), \
(((M) & 1) ? 3 : 1) );})
@@ -1222,7 +1232,7 @@ _mm256_loadu2_m128d(double const *__addr_hi, double const *__addr_lo)
struct __loadu_pd {
__m128d __v;
} __attribute__((__packed__, __may_alias__));
-
+
__m256d __v256 = _mm256_castpd128_pd256(((struct __loadu_pd*)__addr_lo)->__v);
return _mm256_insertf128_pd(__v256, ((struct __loadu_pd*)__addr_hi)->__v, 1);
}
diff --git a/contrib/llvm/tools/clang/lib/Headers/bmi2intrin.h b/contrib/llvm/tools/clang/lib/Headers/bmi2intrin.h
index c63397c..fdae82c 100644
--- a/contrib/llvm/tools/clang/lib/Headers/bmi2intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/bmi2intrin.h
@@ -25,15 +25,11 @@
#error "Never use <bmi2intrin.h> directly; include <x86intrin.h> instead."
#endif
-#ifndef __BMI2__
-# error "BMI2 instruction set not enabled"
-#endif /* __BMI2__ */
-
#ifndef __BMI2INTRIN_H
#define __BMI2INTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("bmi2")))
static __inline__ unsigned int __DEFAULT_FN_ATTRS
_bzhi_u32(unsigned int __X, unsigned int __Y)
diff --git a/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h b/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h
index 0e93d57..da98792 100644
--- a/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/bmiintrin.h
@@ -25,10 +25,6 @@
#error "Never use <bmiintrin.h> directly; include <x86intrin.h> instead."
#endif
-#ifndef __BMI__
-# error "BMI instruction set not enabled"
-#endif /* __BMI__ */
-
#ifndef __BMIINTRIN_H
#define __BMIINTRIN_H
@@ -41,9 +37,14 @@
#define _tzcnt_u32(a) (__tzcnt_u32((a)))
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("bmi")))
+
+/* Allow using the tzcnt intrinsics even for non-BMI targets. Since the TZCNT
+ instruction behaves as BSF on non-BMI targets, there is code that expects
+ to use it as a potentially faster version of BSF. */
+#define __RELAXED_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
-static __inline__ unsigned short __DEFAULT_FN_ATTRS
+static __inline__ unsigned short __RELAXED_FN_ATTRS
__tzcnt_u16(unsigned short __X)
{
return __X ? __builtin_ctzs(__X) : 16;
@@ -87,7 +88,7 @@ __blsr_u32(unsigned int __X)
return __X & (__X - 1);
}
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
+static __inline__ unsigned int __RELAXED_FN_ATTRS
__tzcnt_u32(unsigned int __X)
{
return __X ? __builtin_ctz(__X) : 32;
@@ -140,7 +141,7 @@ __blsr_u64(unsigned long long __X)
return __X & (__X - 1);
}
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+static __inline__ unsigned long long __RELAXED_FN_ATTRS
__tzcnt_u64(unsigned long long __X)
{
return __X ? __builtin_ctzll(__X) : 64;
@@ -149,5 +150,6 @@ __tzcnt_u64(unsigned long long __X)
#endif /* __x86_64__ */
#undef __DEFAULT_FN_ATTRS
+#undef __RELAXED_FN_ATTRS
#endif /* __BMIINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/emmintrin.h b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
index 656bc19..cfc2c71 100644
--- a/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/emmintrin.h
@@ -24,10 +24,6 @@
#ifndef __EMMINTRIN_H
#define __EMMINTRIN_H
-#ifndef __SSE2__
-#error "SSE2 instruction set not enabled"
-#else
-
#include <xmmintrin.h>
typedef double __m128d __attribute__((__vector_size__(16)));
@@ -39,8 +35,14 @@ typedef long long __v2di __attribute__ ((__vector_size__ (16)));
typedef short __v8hi __attribute__((__vector_size__(16)));
typedef char __v16qi __attribute__((__vector_size__(16)));
+/* We need an explicitly signed variant for char. Note that this shouldn't
+ * appear in the interface though. */
+typedef signed char __v16qs __attribute__((__vector_size__(16)));
+
+#include <f16cintrin.h>
+
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse2")))
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_add_sd(__m128d __a, __m128d __b)
@@ -527,6 +529,12 @@ _mm_loadl_pd(__m128d __a, double const *__dp)
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_undefined_pd()
+{
+ return (__m128d)__builtin_ia32_undef128();
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_set_sd(double __w)
{
return (__m128d){ __w, 0 };
@@ -639,7 +647,7 @@ _mm_add_epi32(__m128i __a, __m128i __b)
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_add_si64(__m64 __a, __m64 __b)
{
- return __a + __b;
+ return (__m64)__builtin_ia32_paddq(__a, __b);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -771,7 +779,7 @@ _mm_sub_epi32(__m128i __a, __m128i __b)
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sub_si64(__m64 __a, __m64 __b)
{
- return __a - __b;
+ return (__m64)__builtin_ia32_psubq(__a, __b);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -992,8 +1000,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cmpgt_epi8(__m128i __a, __m128i __b)
{
/* This function always performs a signed comparison, but __v16qi is a char
- which may be signed or unsigned. */
- typedef signed char __v16qs __attribute__((__vector_size__(16)));
+ which may be signed or unsigned, so use __v16qs. */
return (__m128i)((__v16qs)__a > (__v16qs)__b);
}
@@ -1120,33 +1127,39 @@ _mm_loadl_epi64(__m128i const *__p)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_set_epi64x(long long q1, long long q0)
+_mm_undefined_si128()
{
- return (__m128i){ q0, q1 };
+ return (__m128i)__builtin_ia32_undef128();
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_set_epi64(__m64 q1, __m64 q0)
+_mm_set_epi64x(long long __q1, long long __q0)
{
- return (__m128i){ (long long)q0, (long long)q1 };
+ return (__m128i){ __q0, __q1 };
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_set_epi32(int i3, int i2, int i1, int i0)
+_mm_set_epi64(__m64 __q1, __m64 __q0)
{
- return (__m128i)(__v4si){ i0, i1, i2, i3};
+ return (__m128i){ (long long)__q0, (long long)__q1 };
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_set_epi16(short w7, short w6, short w5, short w4, short w3, short w2, short w1, short w0)
+_mm_set_epi32(int __i3, int __i2, int __i1, int __i0)
{
- return (__m128i)(__v8hi){ w0, w1, w2, w3, w4, w5, w6, w7 };
+ return (__m128i)(__v4si){ __i0, __i1, __i2, __i3};
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_set_epi8(char b15, char b14, char b13, char b12, char b11, char b10, char b9, char b8, char b7, char b6, char b5, char b4, char b3, char b2, char b1, char b0)
+_mm_set_epi16(short __w7, short __w6, short __w5, short __w4, short __w3, short __w2, short __w1, short __w0)
{
- return (__m128i)(__v16qi){ b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 };
+ return (__m128i)(__v8hi){ __w0, __w1, __w2, __w3, __w4, __w5, __w6, __w7 };
+}
+
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_set_epi8(char __b15, char __b14, char __b13, char __b12, char __b11, char __b10, char __b9, char __b8, char __b7, char __b6, char __b5, char __b4, char __b3, char __b2, char __b1, char __b0)
+{
+ return (__m128i)(__v16qi){ __b0, __b1, __b2, __b3, __b4, __b5, __b6, __b7, __b8, __b9, __b10, __b11, __b12, __b13, __b14, __b15 };
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -1180,27 +1193,27 @@ _mm_set1_epi8(char __b)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_setr_epi64(__m64 q0, __m64 q1)
+_mm_setr_epi64(__m64 __q0, __m64 __q1)
{
- return (__m128i){ (long long)q0, (long long)q1 };
+ return (__m128i){ (long long)__q0, (long long)__q1 };
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_setr_epi32(int i0, int i1, int i2, int i3)
+_mm_setr_epi32(int __i0, int __i1, int __i2, int __i3)
{
- return (__m128i)(__v4si){ i0, i1, i2, i3};
+ return (__m128i)(__v4si){ __i0, __i1, __i2, __i3};
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_setr_epi16(short w0, short w1, short w2, short w3, short w4, short w5, short w6, short w7)
+_mm_setr_epi16(short __w0, short __w1, short __w2, short __w3, short __w4, short __w5, short __w6, short __w7)
{
- return (__m128i)(__v8hi){ w0, w1, w2, w3, w4, w5, w6, w7 };
+ return (__m128i)(__v8hi){ __w0, __w1, __w2, __w3, __w4, __w5, __w6, __w7 };
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_setr_epi8(char b0, char b1, char b2, char b3, char b4, char b5, char b6, char b7, char b8, char b9, char b10, char b11, char b12, char b13, char b14, char b15)
+_mm_setr_epi8(char __b0, char __b1, char __b2, char __b3, char __b4, char __b5, char __b6, char __b7, char __b8, char __b9, char __b10, char __b11, char __b12, char __b13, char __b14, char __b15)
{
- return (__m128i)(__v16qi){ b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 };
+ return (__m128i)(__v16qi){ __b0, __b1, __b2, __b3, __b4, __b5, __b6, __b7, __b8, __b9, __b10, __b11, __b12, __b13, __b14, __b15 };
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -1321,20 +1334,20 @@ _mm_movemask_epi8(__m128i __a)
#define _mm_shuffle_epi32(a, imm) __extension__ ({ \
(__m128i)__builtin_shufflevector((__v4si)(__m128i)(a), \
- (__v4si)_mm_set1_epi32(0), \
+ (__v4si)_mm_setzero_si128(), \
(imm) & 0x3, ((imm) & 0xc) >> 2, \
((imm) & 0x30) >> 4, ((imm) & 0xc0) >> 6); })
#define _mm_shufflelo_epi16(a, imm) __extension__ ({ \
(__m128i)__builtin_shufflevector((__v8hi)(__m128i)(a), \
- (__v8hi)_mm_set1_epi16(0), \
+ (__v8hi)_mm_setzero_si128(), \
(imm) & 0x3, ((imm) & 0xc) >> 2, \
((imm) & 0x30) >> 4, ((imm) & 0xc0) >> 6, \
4, 5, 6, 7); })
#define _mm_shufflehi_epi16(a, imm) __extension__ ({ \
(__m128i)__builtin_shufflevector((__v8hi)(__m128i)(a), \
- (__v8hi)_mm_set1_epi16(0), \
+ (__v8hi)_mm_setzero_si128(), \
0, 1, 2, 3, \
4 + (((imm) & 0x03) >> 0), \
4 + (((imm) & 0x0c) >> 2), \
@@ -1426,8 +1439,8 @@ _mm_movemask_pd(__m128d __a)
}
#define _mm_shuffle_pd(a, b, i) __extension__ ({ \
- __builtin_shufflevector((__m128d)(a), (__m128d)(b), \
- (i) & 1, (((i) & 2) >> 1) + 2); })
+ (__m128d)__builtin_shufflevector((__v2df)(__m128d)(a), (__v2df)(__m128d)(b), \
+ (i) & 1, (((i) & 2) >> 1) + 2); })
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_castpd_ps(__m128d __a)
@@ -1468,13 +1481,11 @@ _mm_castsi128_pd(__m128i __a)
static __inline__ void __DEFAULT_FN_ATTRS
_mm_pause(void)
{
- __asm__ volatile ("pause");
+ __builtin_ia32_pause();
}
#undef __DEFAULT_FN_ATTRS
#define _MM_SHUFFLE2(x, y) (((x) << 1) | (y))
-#endif /* __SSE2__ */
-
#endif /* __EMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h b/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h
index 3730ae0..c655d98 100644
--- a/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/f16cintrin.h
@@ -21,30 +21,18 @@
*===-----------------------------------------------------------------------===
*/
-#if !defined __X86INTRIN_H && !defined __IMMINTRIN_H
-#error "Never use <f16cintrin.h> directly; include <x86intrin.h> instead."
+#if !defined __X86INTRIN_H && !defined __EMMINTRIN_H && !defined __IMMINTRIN_H
+#error "Never use <f16cintrin.h> directly; include <emmintrin.h> instead."
#endif
-#ifndef __F16C__
-# error "F16C instruction is not enabled"
-#endif /* __F16C__ */
-
#ifndef __F16CINTRIN_H
#define __F16CINTRIN_H
-typedef float __v8sf __attribute__ ((__vector_size__ (32)));
-typedef float __m256 __attribute__ ((__vector_size__ (32)));
-
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("f16c")))
#define _mm_cvtps_ph(a, imm) __extension__ ({ \
- __m128 __a = (a); \
- (__m128i)__builtin_ia32_vcvtps2ph((__v4sf)__a, (imm)); })
-
-#define _mm256_cvtps_ph(a, imm) __extension__ ({ \
- __m256 __a = (a); \
- (__m128i)__builtin_ia32_vcvtps2ph256((__v8sf)__a, (imm)); })
+ (__m128i)__builtin_ia32_vcvtps2ph((__v4sf)(__m128)(a), (imm)); })
static __inline __m128 __DEFAULT_FN_ATTRS
_mm_cvtph_ps(__m128i __a)
@@ -52,12 +40,6 @@ _mm_cvtph_ps(__m128i __a)
return (__m128)__builtin_ia32_vcvtph2ps((__v8hi)__a);
}
-static __inline __m256 __DEFAULT_FN_ATTRS
-_mm256_cvtph_ps(__m128i __a)
-{
- return (__m256)__builtin_ia32_vcvtph2ps256((__v8hi)__a);
-}
-
#undef __DEFAULT_FN_ATTRS
#endif /* __F16CINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h b/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
index d6405cf..f117887 100644
--- a/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/fma4intrin.h
@@ -28,14 +28,10 @@
#ifndef __FMA4INTRIN_H
#define __FMA4INTRIN_H
-#ifndef __FMA4__
-# error "FMA4 instruction set is not enabled"
-#else
-
#include <pmmintrin.h>
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("fma4")))
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_macc_ps(__m128 __A, __m128 __B, __m128 __C)
@@ -231,6 +227,4 @@ _mm256_msubadd_pd(__m256d __A, __m256d __B, __m256d __C)
#undef __DEFAULT_FN_ATTRS
-#endif /* __FMA4__ */
-
#endif /* __FMA4INTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h b/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
index ad693fe..114a143 100644
--- a/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/fmaintrin.h
@@ -28,12 +28,8 @@
#ifndef __FMAINTRIN_H
#define __FMAINTRIN_H
-#ifndef __FMA__
-# error "FMA instruction set is not enabled"
-#else
-
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("fma")))
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_fmadd_ps(__m128 __A, __m128 __B, __m128 __C)
@@ -229,6 +225,4 @@ _mm256_fmsubadd_pd(__m256d __A, __m256d __B, __m256d __C)
#undef __DEFAULT_FN_ATTRS
-#endif /* __FMA__ */
-
#endif /* __FMAINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h b/contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h
index 2b3549c..ac6026a 100644
--- a/contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/fxsrintrin.h
@@ -28,7 +28,7 @@
#ifndef __FXSRINTRIN_H
#define __FXSRINTRIN_H
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("fxsr")))
static __inline__ void __DEFAULT_FN_ATTRS
_fxsave(void *__p) {
diff --git a/contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h b/contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h
index 30f524d..c7571ec 100644
--- a/contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/htmxlintrin.h
@@ -46,7 +46,7 @@ extern "C" {
typedef char TM_buff_type[16];
-/* This macro can be used to determine whether a transaction was successfully
+/* This macro can be used to determine whether a transaction was successfully
started from the __TM_begin() and __TM_simple_begin() intrinsic functions
below. */
#define _HTM_TBEGIN_STARTED 1
diff --git a/contrib/llvm/tools/clang/lib/Headers/ia32intrin.h b/contrib/llvm/tools/clang/lib/Headers/ia32intrin.h
index 5adf3f1..b2f82bb 100644
--- a/contrib/llvm/tools/clang/lib/Headers/ia32intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/ia32intrin.h
@@ -32,50 +32,26 @@
static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
__readeflags(void)
{
- unsigned long long __res = 0;
- __asm__ __volatile__ ("pushf\n\t"
- "popq %0\n"
- :"=r"(__res)
- :
- :
- );
- return __res;
+ return __builtin_ia32_readeflags_u64();
}
static __inline__ void __attribute__((__always_inline__, __nodebug__))
__writeeflags(unsigned long long __f)
{
- __asm__ __volatile__ ("pushq %0\n\t"
- "popf\n"
- :
- :"r"(__f)
- :"flags"
- );
+ __builtin_ia32_writeeflags_u64(__f);
}
#else /* !__x86_64__ */
static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
__readeflags(void)
{
- unsigned int __res = 0;
- __asm__ __volatile__ ("pushf\n\t"
- "popl %0\n"
- :"=r"(__res)
- :
- :
- );
- return __res;
+ return __builtin_ia32_readeflags_u32();
}
static __inline__ void __attribute__((__always_inline__, __nodebug__))
__writeeflags(unsigned int __f)
{
- __asm__ __volatile__ ("pushl %0\n\t"
- "popf\n"
- :
- :"r"(__f)
- :"flags"
- );
+ __builtin_ia32_writeeflags_u32(__f);
}
#endif /* !__x86_64__ */
diff --git a/contrib/llvm/tools/clang/lib/Headers/immintrin.h b/contrib/llvm/tools/clang/lib/Headers/immintrin.h
index 21ad328..6376461 100644
--- a/contrib/llvm/tools/clang/lib/Headers/immintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/immintrin.h
@@ -24,178 +24,149 @@
#ifndef __IMMINTRIN_H
#define __IMMINTRIN_H
-#ifdef __MMX__
#include <mmintrin.h>
-#endif
-#ifdef __SSE__
#include <xmmintrin.h>
-#endif
-#ifdef __SSE2__
#include <emmintrin.h>
-#endif
-#ifdef __SSE3__
#include <pmmintrin.h>
-#endif
-#ifdef __SSSE3__
#include <tmmintrin.h>
-#endif
-#if defined (__SSE4_2__) || defined (__SSE4_1__)
#include <smmintrin.h>
-#endif
-#if defined (__AES__) || defined (__PCLMUL__)
#include <wmmintrin.h>
-#endif
-#ifdef __AVX__
#include <avxintrin.h>
-#endif
-#ifdef __AVX2__
#include <avx2intrin.h>
-#endif
-#ifdef __BMI__
+/* The 256-bit versions of functions in f16cintrin.h.
+ Intel documents these as being in immintrin.h, and
+ they depend on typedefs from avxintrin.h. */
+
+#define _mm256_cvtps_ph(a, imm) __extension__ ({ \
+ (__m128i)__builtin_ia32_vcvtps2ph256((__v8sf)(__m256)(a), (imm)); })
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__, __target__("f16c")))
+_mm256_cvtph_ps(__m128i __a)
+{
+ return (__m256)__builtin_ia32_vcvtph2ps256((__v8hi)__a);
+}
+
#include <bmiintrin.h>
-#endif
-#ifdef __BMI2__
#include <bmi2intrin.h>
-#endif
-#ifdef __LZCNT__
#include <lzcntintrin.h>
-#endif
-#ifdef __FMA__
#include <fmaintrin.h>
-#endif
-#ifdef __AVX512F__
#include <avx512fintrin.h>
-#endif
-#ifdef __AVX512VL__
#include <avx512vlintrin.h>
-#endif
-#ifdef __AVX512BW__
#include <avx512bwintrin.h>
-#endif
-#ifdef __AVX512CD__
#include <avx512cdintrin.h>
-#endif
-#ifdef __AVX512DQ__
#include <avx512dqintrin.h>
-#endif
-#if defined (__AVX512VL__) && defined (__AVX512BW__)
#include <avx512vlbwintrin.h>
-#endif
-#if defined (__AVX512VL__) && defined (__AVX512DQ__)
#include <avx512vldqintrin.h>
-#endif
-#ifdef __AVX512ER__
#include <avx512erintrin.h>
-#endif
-#ifdef __RDRND__
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+#include <pkuintrin.h>
+
+static __inline__ int __attribute__((__always_inline__, __nodebug__, __target__("rdrnd")))
_rdrand16_step(unsigned short *__p)
{
return __builtin_ia32_rdrand16_step(__p);
}
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __attribute__((__always_inline__, __nodebug__, __target__("rdrnd")))
_rdrand32_step(unsigned int *__p)
{
return __builtin_ia32_rdrand32_step(__p);
}
#ifdef __x86_64__
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
+static __inline__ int __attribute__((__always_inline__, __nodebug__, __target__("rdrnd")))
_rdrand64_step(unsigned long long *__p)
{
return __builtin_ia32_rdrand64_step(__p);
}
#endif
-#endif /* __RDRND__ */
-#ifdef __FSGSBASE__
#ifdef __x86_64__
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_readfsbase_u32(void)
{
return __builtin_ia32_rdfsbase32();
}
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_readfsbase_u64(void)
{
return __builtin_ia32_rdfsbase64();
}
-static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_readgsbase_u32(void)
{
return __builtin_ia32_rdgsbase32();
}
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
+static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_readgsbase_u64(void)
{
return __builtin_ia32_rdgsbase64();
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_writefsbase_u32(unsigned int __V)
{
return __builtin_ia32_wrfsbase32(__V);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_writefsbase_u64(unsigned long long __V)
{
return __builtin_ia32_wrfsbase64(__V);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_writegsbase_u32(unsigned int __V)
{
return __builtin_ia32_wrgsbase32(__V);
}
-static __inline__ void __attribute__((__always_inline__, __nodebug__))
+static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))
_writegsbase_u64(unsigned long long __V)
{
return __builtin_ia32_wrgsbase64(__V);
}
#endif
-#endif /* __FSGSBASE__ */
-#ifdef __RTM__
#include <rtmintrin.h>
-#endif
-#ifdef __RTM__
#include <xtestintrin.h>
-#endif
-#ifdef __SHA__
#include <shaintrin.h>
-#endif
#include <fxsrintrin.h>
+#include <xsaveintrin.h>
+
+#include <xsaveoptintrin.h>
+
+#include <xsavecintrin.h>
+
+#include <xsavesintrin.h>
+
/* Some intrinsics inside adxintrin.h are available only on processors with ADX,
* whereas others are also available at all times. */
#include <adxintrin.h>
diff --git a/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h b/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h
index 8ee2997..4c00e42 100644
--- a/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/lzcntintrin.h
@@ -25,15 +25,11 @@
#error "Never use <lzcntintrin.h> directly; include <x86intrin.h> instead."
#endif
-#ifndef __LZCNT__
-# error "LZCNT instruction is not enabled"
-#endif /* __LZCNT__ */
-
#ifndef __LZCNTINTRIN_H
#define __LZCNTINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("lzcnt")))
static __inline__ unsigned short __DEFAULT_FN_ATTRS
__lzcnt16(unsigned short __X)
diff --git a/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h b/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h
index ac8e0f4..cb93faf 100644
--- a/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h
+++ b/contrib/llvm/tools/clang/lib/Headers/mm3dnow.h
@@ -30,7 +30,7 @@
typedef float __v2sf __attribute__((__vector_size__(8)));
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("3dnow")))
static __inline__ void __DEFAULT_FN_ATTRS
_m_femms() {
@@ -132,6 +132,10 @@ _m_pmulhrw(__m64 __m1, __m64 __m2) {
return (__m64)__builtin_ia32_pmulhrw((__v4hi)__m1, (__v4hi)__m2);
}
+/* Handle the 3dnowa instructions here. */
+#undef __DEFAULT_FN_ATTRS
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("3dnowa")))
+
static __inline__ __m64 __DEFAULT_FN_ATTRS
_m_pf2iw(__m64 __m) {
return (__m64)__builtin_ia32_pf2iw((__v2sf)__m);
diff --git a/contrib/llvm/tools/clang/lib/Headers/mmintrin.h b/contrib/llvm/tools/clang/lib/Headers/mmintrin.h
index 0be5f32..162cb1a 100644
--- a/contrib/llvm/tools/clang/lib/Headers/mmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/mmintrin.h
@@ -24,10 +24,6 @@
#ifndef __MMINTRIN_H
#define __MMINTRIN_H
-#ifndef __MMX__
-#error "MMX instruction set not enabled"
-#else
-
typedef long long __m64 __attribute__((__vector_size__(8)));
typedef int __v2si __attribute__((__vector_size__(8)));
@@ -35,7 +31,7 @@ typedef short __v4hi __attribute__((__vector_size__(8)));
typedef char __v8qi __attribute__((__vector_size__(8)));
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("mmx")))
static __inline__ void __DEFAULT_FN_ATTRS
_mm_empty(void)
@@ -140,7 +136,7 @@ _mm_add_pi32(__m64 __m1, __m64 __m2)
}
static __inline__ __m64 __DEFAULT_FN_ATTRS
-_mm_adds_pi8(__m64 __m1, __m64 __m2)
+_mm_adds_pi8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_paddsb((__v8qi)__m1, (__v8qi)__m2);
}
@@ -148,17 +144,17 @@ _mm_adds_pi8(__m64 __m1, __m64 __m2)
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_adds_pi16(__m64 __m1, __m64 __m2)
{
- return (__m64)__builtin_ia32_paddsw((__v4hi)__m1, (__v4hi)__m2);
+ return (__m64)__builtin_ia32_paddsw((__v4hi)__m1, (__v4hi)__m2);
}
static __inline__ __m64 __DEFAULT_FN_ATTRS
-_mm_adds_pu8(__m64 __m1, __m64 __m2)
+_mm_adds_pu8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_paddusb((__v8qi)__m1, (__v8qi)__m2);
}
-
+
static __inline__ __m64 __DEFAULT_FN_ATTRS
-_mm_adds_pu16(__m64 __m1, __m64 __m2)
+_mm_adds_pu16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_paddusw((__v4hi)__m1, (__v4hi)__m2);
}
@@ -168,13 +164,13 @@ _mm_sub_pi8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_psubb((__v8qi)__m1, (__v8qi)__m2);
}
-
+
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sub_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_psubw((__v4hi)__m1, (__v4hi)__m2);
}
-
+
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sub_pi32(__m64 __m1, __m64 __m2)
{
@@ -198,7 +194,7 @@ _mm_subs_pu8(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_psubusb((__v8qi)__m1, (__v8qi)__m2);
}
-
+
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_subs_pu16(__m64 __m1, __m64 __m2)
{
@@ -216,9 +212,9 @@ _mm_mulhi_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_pmulhw((__v4hi)__m1, (__v4hi)__m2);
}
-
+
static __inline__ __m64 __DEFAULT_FN_ATTRS
-_mm_mullo_pi16(__m64 __m1, __m64 __m2)
+_mm_mullo_pi16(__m64 __m1, __m64 __m2)
{
return (__m64)__builtin_ia32_pmullw((__v4hi)__m1, (__v4hi)__m2);
}
@@ -232,7 +228,7 @@ _mm_sll_pi16(__m64 __m, __m64 __count)
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_slli_pi16(__m64 __m, int __count)
{
- return (__m64)__builtin_ia32_psllwi((__v4hi)__m, __count);
+ return (__m64)__builtin_ia32_psllwi((__v4hi)__m, __count);
}
static __inline__ __m64 __DEFAULT_FN_ATTRS
@@ -256,13 +252,13 @@ _mm_sll_si64(__m64 __m, __m64 __count)
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_slli_si64(__m64 __m, int __count)
{
- return (__m64)__builtin_ia32_psllqi(__m, __count);
+ return (__m64)__builtin_ia32_psllqi(__m, __count);
}
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sra_pi16(__m64 __m, __m64 __count)
{
- return (__m64)__builtin_ia32_psraw((__v4hi)__m, __count);
+ return (__m64)__builtin_ia32_psraw((__v4hi)__m, __count);
}
static __inline__ __m64 __DEFAULT_FN_ATTRS
@@ -274,7 +270,7 @@ _mm_srai_pi16(__m64 __m, int __count)
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sra_pi32(__m64 __m, __m64 __count)
{
- return (__m64)__builtin_ia32_psrad((__v2si)__m, __count);
+ return (__m64)__builtin_ia32_psrad((__v2si)__m, __count);
}
static __inline__ __m64 __DEFAULT_FN_ATTRS
@@ -286,19 +282,19 @@ _mm_srai_pi32(__m64 __m, int __count)
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srl_pi16(__m64 __m, __m64 __count)
{
- return (__m64)__builtin_ia32_psrlw((__v4hi)__m, __count);
+ return (__m64)__builtin_ia32_psrlw((__v4hi)__m, __count);
}
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srli_pi16(__m64 __m, int __count)
{
- return (__m64)__builtin_ia32_psrlwi((__v4hi)__m, __count);
+ return (__m64)__builtin_ia32_psrlwi((__v4hi)__m, __count);
}
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srl_pi32(__m64 __m, __m64 __count)
{
- return (__m64)__builtin_ia32_psrld((__v2si)__m, __count);
+ return (__m64)__builtin_ia32_psrld((__v2si)__m, __count);
}
static __inline__ __m64 __DEFAULT_FN_ATTRS
@@ -310,13 +306,13 @@ _mm_srli_pi32(__m64 __m, int __count)
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srl_si64(__m64 __m, __m64 __count)
{
- return (__m64)__builtin_ia32_psrlq(__m, __count);
+ return (__m64)__builtin_ia32_psrlq(__m, __count);
}
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_srli_si64(__m64 __m, int __count)
{
- return (__m64)__builtin_ia32_psrlqi(__m, __count);
+ return (__m64)__builtin_ia32_psrlqi(__m, __count);
}
static __inline__ __m64 __DEFAULT_FN_ATTRS
@@ -447,7 +443,9 @@ _mm_setr_pi8(char __b0, char __b1, char __b2, char __b3, char __b4, char __b5,
/* Aliases for compatibility. */
#define _m_empty _mm_empty
#define _m_from_int _mm_cvtsi32_si64
+#define _m_from_int64 _mm_cvtsi64_m64
#define _m_to_int _mm_cvtsi64_si32
+#define _m_to_int64 _mm_cvtm64_si64
#define _m_packsswb _mm_packs_pi16
#define _m_packssdw _mm_packs_pi32
#define _m_packuswb _mm_packs_pu16
@@ -501,7 +499,5 @@ _mm_setr_pi8(char __b0, char __b1, char __b2, char __b3, char __b4, char __b5,
#define _m_pcmpgtw _mm_cmpgt_pi16
#define _m_pcmpgtd _mm_cmpgt_pi32
-#endif /* __MMX__ */
-
#endif /* __MMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/module.modulemap b/contrib/llvm/tools/clang/lib/Headers/module.modulemap
index b861fdd..b147e89 100644
--- a/contrib/llvm/tools/clang/lib/Headers/module.modulemap
+++ b/contrib/llvm/tools/clang/lib/Headers/module.modulemap
@@ -32,142 +32,117 @@ module _Builtin_intrinsics [system] [extern_c] {
}
explicit module cpuid {
- requires x86
header "cpuid.h"
}
explicit module mmx {
- requires mmx
header "mmintrin.h"
}
explicit module f16c {
- requires f16c
header "f16cintrin.h"
}
explicit module sse {
- requires sse
export mmx
export sse2 // note: for hackish <emmintrin.h> dependency
header "xmmintrin.h"
}
explicit module sse2 {
- requires sse2
export sse
header "emmintrin.h"
}
explicit module sse3 {
- requires sse3
export sse2
header "pmmintrin.h"
}
explicit module ssse3 {
- requires ssse3
export sse3
header "tmmintrin.h"
}
explicit module sse4_1 {
- requires sse41
export ssse3
header "smmintrin.h"
}
explicit module sse4_2 {
- requires sse42
export sse4_1
header "nmmintrin.h"
}
explicit module sse4a {
- requires sse4a
export sse3
header "ammintrin.h"
}
explicit module avx {
- requires avx
export sse4_2
header "avxintrin.h"
}
explicit module avx2 {
- requires avx2
export avx
header "avx2intrin.h"
}
explicit module avx512f {
- requires avx512f
export avx2
header "avx512fintrin.h"
}
explicit module avx512er {
- requires avx512er
header "avx512erintrin.h"
}
explicit module bmi {
- requires bmi
header "bmiintrin.h"
}
explicit module bmi2 {
- requires bmi2
header "bmi2intrin.h"
}
explicit module fma {
- requires fma
header "fmaintrin.h"
}
explicit module fma4 {
- requires fma4
export sse3
header "fma4intrin.h"
}
explicit module lzcnt {
- requires lzcnt
header "lzcntintrin.h"
}
explicit module popcnt {
- requires popcnt
header "popcntintrin.h"
}
explicit module mm3dnow {
- requires mm3dnow
header "mm3dnow.h"
}
explicit module xop {
- requires xop
export fma4
header "xopintrin.h"
}
explicit module aes_pclmul {
- requires aes, pclmul
header "wmmintrin.h"
export aes
export pclmul
}
explicit module aes {
- requires aes
header "__wmmintrin_aes.h"
}
explicit module pclmul {
- requires pclmul
header "__wmmintrin_pclmul.h"
}
}
diff --git a/contrib/llvm/tools/clang/lib/Headers/nmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/nmmintrin.h
index f12622d..57fec15 100644
--- a/contrib/llvm/tools/clang/lib/Headers/nmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/nmmintrin.h
@@ -24,12 +24,7 @@
#ifndef _NMMINTRIN_H
#define _NMMINTRIN_H
-#ifndef __SSE4_2__
-#error "SSE4.2 instruction set not enabled"
-#else
-
/* To match expectations of gcc we put the sse4.2 definitions into smmintrin.h,
just include it now then. */
#include <smmintrin.h>
-#endif /* __SSE4_2__ */
#endif /* _NMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/pkuintrin.h b/contrib/llvm/tools/clang/lib/Headers/pkuintrin.h
new file mode 100644
index 0000000..ad12348
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/pkuintrin.h
@@ -0,0 +1,48 @@
+/*===------------- pkuintrin.h - PKU intrinsics ------------------===
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+#ifndef __IMMINTRIN_H
+#error "Never use <pkuintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __PKUINTRIN_H
+#define __PKUINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("pku")))
+
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
+_rdpkru_u32(void)
+{
+ return __builtin_ia32_rdpkru();
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_wrpkru(unsigned int val)
+{
+ return __builtin_ia32_wrpkru(val);
+}
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h
index e1b8d9b..0ff9409 100644
--- a/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/pmmintrin.h
@@ -20,18 +20,14 @@
*
*===-----------------------------------------------------------------------===
*/
-
+
#ifndef __PMMINTRIN_H
#define __PMMINTRIN_H
-#ifndef __SSE3__
-#error "SSE3 instruction set not enabled"
-#else
-
#include <emmintrin.h>
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse3")))
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_lddqu_si128(__m128i const *__p)
@@ -117,6 +113,4 @@ _mm_mwait(unsigned __extensions, unsigned __hints)
#undef __DEFAULT_FN_ATTRS
-#endif /* __SSE3__ */
-
#endif /* __PMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h b/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h
index 1a4e900..6fcda65 100644
--- a/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/popcntintrin.h
@@ -21,15 +21,11 @@
*===-----------------------------------------------------------------------===
*/
-#ifndef __POPCNT__
-#error "POPCNT instruction set not enabled"
-#endif
-
#ifndef _POPCNTINTRIN_H
#define _POPCNTINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("popcnt")))
static __inline__ int __DEFAULT_FN_ATTRS
_mm_popcnt_u32(unsigned int __A)
@@ -37,12 +33,24 @@ _mm_popcnt_u32(unsigned int __A)
return __builtin_popcount(__A);
}
+static __inline__ int __DEFAULT_FN_ATTRS
+_popcnt32(int __A)
+{
+ return __builtin_popcount(__A);
+}
+
#ifdef __x86_64__
static __inline__ long long __DEFAULT_FN_ATTRS
_mm_popcnt_u64(unsigned long long __A)
{
return __builtin_popcountll(__A);
}
+
+static __inline__ long long __DEFAULT_FN_ATTRS
+_popcnt64(long long __A)
+{
+ return __builtin_popcountll(__A);
+}
#endif /* __x86_64__ */
#undef __DEFAULT_FN_ATTRS
diff --git a/contrib/llvm/tools/clang/lib/Headers/prfchwintrin.h b/contrib/llvm/tools/clang/lib/Headers/prfchwintrin.h
index 9825bd8..ba02857 100644
--- a/contrib/llvm/tools/clang/lib/Headers/prfchwintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/prfchwintrin.h
@@ -30,6 +30,12 @@
#if defined(__PRFCHW__) || defined(__3dNOW__)
static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_m_prefetch(void *__P)
+{
+ __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
_m_prefetchw(void *__P)
{
__builtin_prefetch (__P, 1, 3 /* _MM_HINT_T0 */);
diff --git a/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h b/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h
index fdf7e18..421f4ea 100644
--- a/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/rdseedintrin.h
@@ -28,10 +28,8 @@
#ifndef __RDSEEDINTRIN_H
#define __RDSEEDINTRIN_H
-#ifdef __RDSEED__
-
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("rdseed")))
static __inline__ int __DEFAULT_FN_ATTRS
_rdseed16_step(unsigned short *__p)
@@ -55,5 +53,4 @@ _rdseed64_step(unsigned long long *__p)
#undef __DEFAULT_FN_ATTRS
-#endif /* __RDSEED__ */
#endif /* __RDSEEDINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/rtmintrin.h b/contrib/llvm/tools/clang/lib/Headers/rtmintrin.h
index 1725681..e6a58d7 100644
--- a/contrib/llvm/tools/clang/lib/Headers/rtmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/rtmintrin.h
@@ -38,7 +38,7 @@
#define _XABORT_CODE(x) (((x) >> 24) & 0xFF)
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("rtm")))
static __inline__ unsigned int __DEFAULT_FN_ATTRS
_xbegin(void)
diff --git a/contrib/llvm/tools/clang/lib/Headers/shaintrin.h b/contrib/llvm/tools/clang/lib/Headers/shaintrin.h
index 960cced..9b5d218 100644
--- a/contrib/llvm/tools/clang/lib/Headers/shaintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/shaintrin.h
@@ -28,15 +28,11 @@
#ifndef __SHAINTRIN_H
#define __SHAINTRIN_H
-#if !defined (__SHA__)
-# error "SHA instructions not enabled"
-#endif
-
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sha")))
#define _mm_sha1rnds4_epu32(V1, V2, M) __extension__ ({ \
- __builtin_ia32_sha1rnds4((V1), (V2), (M)); })
+ __builtin_ia32_sha1rnds4((__v4si)(__m128i)(V1), (__v4si)(__m128i)(V2), (M)); })
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sha1nexte_epu32(__m128i __X, __m128i __Y)
diff --git a/contrib/llvm/tools/clang/lib/Headers/smmintrin.h b/contrib/llvm/tools/clang/lib/Headers/smmintrin.h
index 04bd072..69ad07f 100644
--- a/contrib/llvm/tools/clang/lib/Headers/smmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/smmintrin.h
@@ -24,14 +24,10 @@
#ifndef _SMMINTRIN_H
#define _SMMINTRIN_H
-#ifndef __SSE4_1__
-#error "SSE4.1 instruction set not enabled"
-#else
-
#include <tmmintrin.h>
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4.1")))
/* SSE4 Rounding macros. */
#define _MM_FROUND_TO_NEAREST_INT 0x00
@@ -61,35 +57,28 @@
#define _mm_floor_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_FLOOR)
#define _mm_round_ps(X, M) __extension__ ({ \
- __m128 __X = (X); \
- (__m128) __builtin_ia32_roundps((__v4sf)__X, (M)); })
+ (__m128)__builtin_ia32_roundps((__v4sf)(__m128)(X), (M)); })
#define _mm_round_ss(X, Y, M) __extension__ ({ \
- __m128 __X = (X); \
- __m128 __Y = (Y); \
- (__m128) __builtin_ia32_roundss((__v4sf)__X, (__v4sf)__Y, (M)); })
+ (__m128)__builtin_ia32_roundss((__v4sf)(__m128)(X), \
+ (__v4sf)(__m128)(Y), (M)); })
#define _mm_round_pd(X, M) __extension__ ({ \
- __m128d __X = (X); \
- (__m128d) __builtin_ia32_roundpd((__v2df)__X, (M)); })
+ (__m128d)__builtin_ia32_roundpd((__v2df)(__m128d)(X), (M)); })
#define _mm_round_sd(X, Y, M) __extension__ ({ \
- __m128d __X = (X); \
- __m128d __Y = (Y); \
- (__m128d) __builtin_ia32_roundsd((__v2df)__X, (__v2df)__Y, (M)); })
+ (__m128d)__builtin_ia32_roundsd((__v2df)(__m128d)(X), \
+ (__v2df)(__m128d)(Y), (M)); })
/* SSE4 Packed Blending Intrinsics. */
#define _mm_blend_pd(V1, V2, M) __extension__ ({ \
- __m128d __V1 = (V1); \
- __m128d __V2 = (V2); \
- (__m128d)__builtin_shufflevector((__v2df)__V1, (__v2df)__V2, \
+ (__m128d)__builtin_shufflevector((__v2df)(__m128d)(V1), \
+ (__v2df)(__m128d)(V2), \
(((M) & 0x01) ? 2 : 0), \
(((M) & 0x02) ? 3 : 1)); })
#define _mm_blend_ps(V1, V2, M) __extension__ ({ \
- __m128 __V1 = (V1); \
- __m128 __V2 = (V2); \
- (__m128)__builtin_shufflevector((__v4sf)__V1, (__v4sf)__V2, \
+ (__m128)__builtin_shufflevector((__v4sf)(__m128)(V1), (__v4sf)(__m128)(V2), \
(((M) & 0x01) ? 4 : 0), \
(((M) & 0x02) ? 5 : 1), \
(((M) & 0x04) ? 6 : 2), \
@@ -117,9 +106,8 @@ _mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M)
}
#define _mm_blend_epi16(V1, V2, M) __extension__ ({ \
- __m128i __V1 = (V1); \
- __m128i __V2 = (V2); \
- (__m128i)__builtin_shufflevector((__v8hi)__V1, (__v8hi)__V2, \
+ (__m128i)__builtin_shufflevector((__v8hi)(__m128i)(V1), \
+ (__v8hi)(__m128i)(V2), \
(((M) & 0x01) ? 8 : 0), \
(((M) & 0x02) ? 9 : 1), \
(((M) & 0x04) ? 10 : 2), \
@@ -144,20 +132,18 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2)
/* SSE4 Floating Point Dot Product Instructions. */
#define _mm_dp_ps(X, Y, M) __extension__ ({ \
- __m128 __X = (X); \
- __m128 __Y = (Y); \
- (__m128) __builtin_ia32_dpps((__v4sf)__X, (__v4sf)__Y, (M)); })
+ (__m128) __builtin_ia32_dpps((__v4sf)(__m128)(X), \
+ (__v4sf)(__m128)(Y), (M)); })
#define _mm_dp_pd(X, Y, M) __extension__ ({\
- __m128d __X = (X); \
- __m128d __Y = (Y); \
- (__m128d) __builtin_ia32_dppd((__v2df)__X, (__v2df)__Y, (M)); })
+ (__m128d) __builtin_ia32_dppd((__v2df)(__m128d)(X), \
+ (__v2df)(__m128d)(Y), (M)); })
/* SSE4 Streaming Load Hint Instruction. */
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_stream_load_si128 (__m128i *__V)
+_mm_stream_load_si128 (__m128i const *__V)
{
- return (__m128i) __builtin_ia32_movntdqa ((__v2di *) __V);
+ return (__m128i) __builtin_ia32_movntdqa ((const __v2di *) __V);
}
/* SSE4 Packed Integer Min/Max Instructions. */
@@ -213,7 +199,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
#define _mm_insert_ps(X, Y, N) __builtin_ia32_insertps128((X), (Y), (N))
#define _mm_extract_ps(X, N) (__extension__ \
({ union { int __i; float __f; } __t; \
- __v4sf __a = (__v4sf)(X); \
+ __v4sf __a = (__v4sf)(__m128)(X); \
__t.__f = __a[(N) & 3]; \
__t.__i;}))
@@ -221,39 +207,44 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/* Extract a single-precision float from X at index N into D. */
#define _MM_EXTRACT_FLOAT(D, X, N) (__extension__ ({ __v4sf __a = (__v4sf)(X); \
(D) = __a[N]; }))
-
+
/* Or together 2 sets of indexes (X and Y) with the zeroing bits (Z) to create
an index suitable for _mm_insert_ps. */
#define _MM_MK_INSERTPS_NDX(X, Y, Z) (((X) << 6) | ((Y) << 4) | (Z))
-
+
/* Extract a float from X at index N into the first index of the return. */
#define _MM_PICK_OUT_PS(X, N) _mm_insert_ps (_mm_setzero_ps(), (X), \
_MM_MK_INSERTPS_NDX((N), 0, 0x0e))
-
+
/* Insert int into packed integer array at index. */
-#define _mm_insert_epi8(X, I, N) (__extension__ ({ __v16qi __a = (__v16qi)(X); \
- __a[(N) & 15] = (I); \
- __a;}))
-#define _mm_insert_epi32(X, I, N) (__extension__ ({ __v4si __a = (__v4si)(X); \
- __a[(N) & 3] = (I); \
- __a;}))
+#define _mm_insert_epi8(X, I, N) (__extension__ \
+ ({ __v16qi __a = (__v16qi)(__m128i)(X); \
+ __a[(N) & 15] = (I); \
+ __a;}))
+#define _mm_insert_epi32(X, I, N) (__extension__ \
+ ({ __v4si __a = (__v4si)(__m128i)(X); \
+ __a[(N) & 3] = (I); \
+ __a;}))
#ifdef __x86_64__
-#define _mm_insert_epi64(X, I, N) (__extension__ ({ __v2di __a = (__v2di)(X); \
- __a[(N) & 1] = (I); \
- __a;}))
+#define _mm_insert_epi64(X, I, N) (__extension__ \
+ ({ __v2di __a = (__v2di)(__m128i)(X); \
+ __a[(N) & 1] = (I); \
+ __a;}))
#endif /* __x86_64__ */
/* Extract int from packed integer array at index. This returns the element
* as a zero extended value, so it is unsigned.
*/
-#define _mm_extract_epi8(X, N) (__extension__ ({ __v16qi __a = (__v16qi)(X); \
- (int)(unsigned char) \
- __a[(N) & 15];}))
-#define _mm_extract_epi32(X, N) (__extension__ ({ __v4si __a = (__v4si)(X); \
- __a[(N) & 3];}))
+#define _mm_extract_epi8(X, N) (__extension__ \
+ ({ __v16qi __a = (__v16qi)(__m128i)(X); \
+ (int)(unsigned char) __a[(N) & 15];}))
+#define _mm_extract_epi32(X, N) (__extension__ \
+ ({ __v4si __a = (__v4si)(__m128i)(X); \
+ (int)__a[(N) & 3];}))
#ifdef __x86_64__
-#define _mm_extract_epi64(X, N) (__extension__ ({ __v2di __a = (__v2di)(X); \
- __a[(N) & 1];}))
+#define _mm_extract_epi64(X, N) (__extension__ \
+ ({ __v2di __a = (__v2di)(__m128i)(X); \
+ (long long)__a[(N) & 1];}))
#endif /* __x86_64 */
/* SSE4 128-bit Packed Integer Comparisons. */
@@ -290,37 +281,44 @@ _mm_cmpeq_epi64(__m128i __V1, __m128i __V2)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi8_epi16(__m128i __V)
{
- return (__m128i) __builtin_ia32_pmovsxbw128((__v16qi) __V);
+ /* This function always performs a signed extension, but __v16qi is a char
+ which may be signed or unsigned, so use __v16qs. */
+ return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1, 2, 3, 4, 5, 6, 7), __v8hi);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi8_epi32(__m128i __V)
{
- return (__m128i) __builtin_ia32_pmovsxbd128((__v16qi) __V);
+ /* This function always performs a signed extension, but __v16qi is a char
+ which may be signed or unsigned, so use __v16qs. */
+ return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1, 2, 3), __v4si);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi8_epi64(__m128i __V)
{
- return (__m128i) __builtin_ia32_pmovsxbq128((__v16qi) __V);
+ /* This function always performs a signed extension, but __v16qi is a char
+ which may be signed or unsigned, so use __v16qs. */
+ typedef signed char __v16qs __attribute__((__vector_size__(16)));
+ return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v16qs)__V, (__v16qs)__V, 0, 1), __v2di);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi16_epi32(__m128i __V)
{
- return (__m128i) __builtin_ia32_pmovsxwd128((__v8hi) __V);
+ return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v8hi)__V, (__v8hi)__V, 0, 1, 2, 3), __v4si);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi16_epi64(__m128i __V)
{
- return (__m128i) __builtin_ia32_pmovsxwq128((__v8hi)__V);
+ return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v8hi)__V, (__v8hi)__V, 0, 1), __v2di);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtepi32_epi64(__m128i __V)
{
- return (__m128i) __builtin_ia32_pmovsxdq128((__v4si)__V);
+ return (__m128i)__builtin_convertvector(__builtin_shufflevector((__v4si)__V, (__v4si)__V, 0, 1), __v2di);
}
/* SSE4 Packed Integer Zero-Extension. */
@@ -369,9 +367,8 @@ _mm_packus_epi32(__m128i __V1, __m128i __V2)
/* SSE4 Multiple Packed Sums of Absolute Difference. */
#define _mm_mpsadbw_epu8(X, Y, M) __extension__ ({ \
- __m128i __X = (X); \
- __m128i __Y = (Y); \
- (__m128i) __builtin_ia32_mpsadbw128((__v16qi)__X, (__v16qi)__Y, (M)); })
+ (__m128i) __builtin_ia32_mpsadbw128((__v16qi)(__m128i)(X), \
+ (__v16qi)(__m128i)(Y), (M)); })
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_minpos_epu16(__m128i __V)
@@ -379,9 +376,13 @@ _mm_minpos_epu16(__m128i __V)
return (__m128i) __builtin_ia32_phminposuw128((__v8hi)__V);
}
+/* Handle the sse4.2 definitions here. */
+
/* These definitions are normally in nmmintrin.h, but gcc puts them in here
so we'll do the same. */
-#ifdef __SSE4_2__
+
+#undef __DEFAULT_FN_ATTRS
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4.2")))
/* These specify the type of data that we're comparing. */
#define _SIDD_UBYTE_OPS 0x00
@@ -410,36 +411,59 @@ _mm_minpos_epu16(__m128i __V)
#define _SIDD_UNIT_MASK 0x40
/* SSE4.2 Packed Comparison Intrinsics. */
-#define _mm_cmpistrm(A, B, M) __builtin_ia32_pcmpistrm128((A), (B), (M))
-#define _mm_cmpistri(A, B, M) __builtin_ia32_pcmpistri128((A), (B), (M))
+#define _mm_cmpistrm(A, B, M) \
+ (__m128i)__builtin_ia32_pcmpistrm128((__v16qi)(__m128i)(A), \
+ (__v16qi)(__m128i)(B), (int)(M))
+#define _mm_cmpistri(A, B, M) \
+ (int)__builtin_ia32_pcmpistri128((__v16qi)(__m128i)(A), \
+ (__v16qi)(__m128i)(B), (int)(M))
#define _mm_cmpestrm(A, LA, B, LB, M) \
- __builtin_ia32_pcmpestrm128((A), (LA), (B), (LB), (M))
+ (__m128i)__builtin_ia32_pcmpestrm128((__v16qi)(__m128i)(A), (int)(LA), \
+ (__v16qi)(__m128i)(B), (int)(LB), \
+ (int)(M))
#define _mm_cmpestri(A, LA, B, LB, M) \
- __builtin_ia32_pcmpestri128((A), (LA), (B), (LB), (M))
-
+ (int)__builtin_ia32_pcmpestri128((__v16qi)(__m128i)(A), (int)(LA), \
+ (__v16qi)(__m128i)(B), (int)(LB), \
+ (int)(M))
+
/* SSE4.2 Packed Comparison Intrinsics and EFlag Reading. */
#define _mm_cmpistra(A, B, M) \
- __builtin_ia32_pcmpistria128((A), (B), (M))
+ (int)__builtin_ia32_pcmpistria128((__v16qi)(__m128i)(A), \
+ (__v16qi)(__m128i)(B), (int)(M))
#define _mm_cmpistrc(A, B, M) \
- __builtin_ia32_pcmpistric128((A), (B), (M))
+ (int)__builtin_ia32_pcmpistric128((__v16qi)(__m128i)(A), \
+ (__v16qi)(__m128i)(B), (int)(M))
#define _mm_cmpistro(A, B, M) \
- __builtin_ia32_pcmpistrio128((A), (B), (M))
+ (int)__builtin_ia32_pcmpistrio128((__v16qi)(__m128i)(A), \
+ (__v16qi)(__m128i)(B), (int)(M))
#define _mm_cmpistrs(A, B, M) \
- __builtin_ia32_pcmpistris128((A), (B), (M))
+ (int)__builtin_ia32_pcmpistris128((__v16qi)(__m128i)(A), \
+ (__v16qi)(__m128i)(B), (int)(M))
#define _mm_cmpistrz(A, B, M) \
- __builtin_ia32_pcmpistriz128((A), (B), (M))
+ (int)__builtin_ia32_pcmpistriz128((__v16qi)(__m128i)(A), \
+ (__v16qi)(__m128i)(B), (int)(M))
#define _mm_cmpestra(A, LA, B, LB, M) \
- __builtin_ia32_pcmpestria128((A), (LA), (B), (LB), (M))
+ (int)__builtin_ia32_pcmpestria128((__v16qi)(__m128i)(A), (int)(LA), \
+ (__v16qi)(__m128i)(B), (int)(LB), \
+ (int)(M))
#define _mm_cmpestrc(A, LA, B, LB, M) \
- __builtin_ia32_pcmpestric128((A), (LA), (B), (LB), (M))
+ (int)__builtin_ia32_pcmpestric128((__v16qi)(__m128i)(A), (int)(LA), \
+ (__v16qi)(__m128i)(B), (int)(LB), \
+ (int)(M))
#define _mm_cmpestro(A, LA, B, LB, M) \
- __builtin_ia32_pcmpestrio128((A), (LA), (B), (LB), (M))
+ (int)__builtin_ia32_pcmpestrio128((__v16qi)(__m128i)(A), (int)(LA), \
+ (__v16qi)(__m128i)(B), (int)(LB), \
+ (int)(M))
#define _mm_cmpestrs(A, LA, B, LB, M) \
- __builtin_ia32_pcmpestris128((A), (LA), (B), (LB), (M))
+ (int)__builtin_ia32_pcmpestris128((__v16qi)(__m128i)(A), (int)(LA), \
+ (__v16qi)(__m128i)(B), (int)(LB), \
+ (int)(M))
#define _mm_cmpestrz(A, LA, B, LB, M) \
- __builtin_ia32_pcmpestriz128((A), (LA), (B), (LB), (M))
+ (int)__builtin_ia32_pcmpestriz128((__v16qi)(__m128i)(A), (int)(LA), \
+ (__v16qi)(__m128i)(B), (int)(LB), \
+ (int)(M))
/* SSE4.2 Compare Packed Data -- Greater Than. */
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -481,7 +505,4 @@ _mm_crc32_u64(unsigned long long __C, unsigned long long __D)
#include <popcntintrin.h>
#endif
-#endif /* __SSE4_2__ */
-#endif /* __SSE4_1__ */
-
#endif /* _SMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/stdint.h b/contrib/llvm/tools/clang/lib/Headers/stdint.h
index 0303db9..3f2fcbc 100644
--- a/contrib/llvm/tools/clang/lib/Headers/stdint.h
+++ b/contrib/llvm/tools/clang/lib/Headers/stdint.h
@@ -77,14 +77,14 @@
* C99 7.18.1.2 Minimum-width integer types.
* C99 7.18.1.3 Fastest minimum-width integer types.
*
- * The standard requires that exact-width type be defined for 8-, 16-, 32-, and
+ * The standard requires that exact-width type be defined for 8-, 16-, 32-, and
* 64-bit types if they are implemented. Other exact width types are optional.
* This implementation defines an exact-width types for every integer width
* that is represented in the standard integer types.
*
* The standard also requires minimum-width types be defined for 8-, 16-, 32-,
* and 64-bit widths regardless of whether there are corresponding exact-width
- * types.
+ * types.
*
* To accommodate targets that are missing types that are exactly 8, 16, 32, or
* 64 bits wide, this implementation takes an approach of cascading
@@ -97,7 +97,7 @@
* suboptimal.
*
* In violation of the standard, some targets do not implement a type that is
- * wide enough to represent all of the required widths (8-, 16-, 32-, 64-bit).
+ * wide enough to represent all of the required widths (8-, 16-, 32-, 64-bit).
* To accommodate these targets, a required minimum-width type is only
* defined if there exists an exact-width type of equal or greater width.
*/
@@ -247,7 +247,7 @@ typedef __uint_least8_t uint_fast8_t;
#endif /* __int_least8_t */
/* prevent glibc sys/types.h from defining conflicting types */
-#ifndef __int8_t_defined
+#ifndef __int8_t_defined
# define __int8_t_defined
#endif /* __int8_t_defined */
@@ -280,9 +280,9 @@ typedef __UINTMAX_TYPE__ uintmax_t;
*
* The standard requires that integer constant macros be defined for all the
* minimum-width types defined above. As 8-, 16-, 32-, and 64-bit minimum-width
- * types are required, the corresponding integer constant macros are defined
+ * types are required, the corresponding integer constant macros are defined
* here. This implementation also defines minimum-width types for every other
- * integer width that the target implements, so corresponding macros are
+ * integer width that the target implements, so corresponding macros are
* defined below, too.
*
* These macros are defined using the same successive-shrinking approach as
@@ -452,7 +452,7 @@ typedef __UINTMAX_TYPE__ uintmax_t;
#endif /* __int_least8_t */
-/* C99 7.18.2.1 Limits of exact-width integer types.
+/* C99 7.18.2.1 Limits of exact-width integer types.
* C99 7.18.2.2 Limits of minimum-width integer types.
* C99 7.18.2.3 Limits of fastest minimum-width integer types.
*
diff --git a/contrib/llvm/tools/clang/lib/Headers/tbmintrin.h b/contrib/llvm/tools/clang/lib/Headers/tbmintrin.h
index 48c0b07..785961c 100644
--- a/contrib/llvm/tools/clang/lib/Headers/tbmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/tbmintrin.h
@@ -21,10 +21,6 @@
*===-----------------------------------------------------------------------===
*/
-#ifndef __TBM__
-#error "TBM instruction set is not enabled"
-#endif
-
#ifndef __X86INTRIN_H
#error "Never use <tbmintrin.h> directly; include <x86intrin.h> instead."
#endif
@@ -33,9 +29,11 @@
#define __TBMINTRIN_H
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("tbm")))
-#define __bextri_u32(a, b) (__builtin_ia32_bextri_u32((a), (b)))
+#define __bextri_u32(a, b) \
+ ((unsigned int)__builtin_ia32_bextri_u32((unsigned int)(a), \
+ (unsigned int)(b)))
static __inline__ unsigned int __DEFAULT_FN_ATTRS
__blcfill_u32(unsigned int a)
@@ -92,7 +90,9 @@ __tzmsk_u32(unsigned int a)
}
#ifdef __x86_64__
-#define __bextri_u64(a, b) (__builtin_ia32_bextri_u64((a), (int)(b)))
+#define __bextri_u64(a, b) \
+ ((unsigned long long)__builtin_ia32_bextri_u64((unsigned long long)(a), \
+ (unsigned long long)(b)))
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blcfill_u64(unsigned long long a)
diff --git a/contrib/llvm/tools/clang/lib/Headers/tgmath.h b/contrib/llvm/tools/clang/lib/Headers/tgmath.h
index a48e267..318e118 100644
--- a/contrib/llvm/tools/clang/lib/Headers/tgmath.h
+++ b/contrib/llvm/tools/clang/lib/Headers/tgmath.h
@@ -490,7 +490,7 @@ static double _Complex
static long double _Complex
_TG_ATTRS
- __tg_pow(long double _Complex __x, long double _Complex __y)
+ __tg_pow(long double _Complex __x, long double _Complex __y)
{return cpowl(__x, __y);}
#undef pow
diff --git a/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h
index 2ecc730..0002890 100644
--- a/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/tmmintrin.h
@@ -20,18 +20,14 @@
*
*===-----------------------------------------------------------------------===
*/
-
+
#ifndef __TMMINTRIN_H
#define __TMMINTRIN_H
-#ifndef __SSSE3__
-#error "SSSE3 instruction set not enabled"
-#else
-
#include <pmmintrin.h>
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("ssse3")))
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_abs_pi8(__m64 __a)
@@ -70,14 +66,11 @@ _mm_abs_epi32(__m128i __a)
}
#define _mm_alignr_epi8(a, b, n) __extension__ ({ \
- __m128i __a = (a); \
- __m128i __b = (b); \
- (__m128i)__builtin_ia32_palignr128((__v16qi)__a, (__v16qi)__b, (n)); })
+ (__m128i)__builtin_ia32_palignr128((__v16qi)(__m128i)(a), \
+ (__v16qi)(__m128i)(b), (n)); })
#define _mm_alignr_pi8(a, b, n) __extension__ ({ \
- __m64 __a = (a); \
- __m64 __b = (b); \
- (__m64)__builtin_ia32_palignr((__v8qi)__a, (__v8qi)__b, (n)); })
+ (__m64)__builtin_ia32_palignr((__v8qi)(__m64)(a), (__v8qi)(__m64)(b), (n)); })
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_hadd_epi16(__m128i __a, __m128i __b)
@@ -225,6 +218,4 @@ _mm_sign_pi32(__m64 __a, __m64 __b)
#undef __DEFAULT_FN_ATTRS
-#endif /* __SSSE3__ */
-
#endif /* __TMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/wmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/wmmintrin.h
index 369e3c2..a2d9310 100644
--- a/contrib/llvm/tools/clang/lib/Headers/wmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/wmmintrin.h
@@ -26,17 +26,8 @@
#include <emmintrin.h>
-#if !defined (__AES__) && !defined (__PCLMUL__)
-# error "AES/PCLMUL instructions not enabled"
-#else
-
-#ifdef __AES__
#include <__wmmintrin_aes.h>
-#endif /* __AES__ */
-#ifdef __PCLMUL__
#include <__wmmintrin_pclmul.h>
-#endif /* __PCLMUL__ */
-#endif /* __AES__ || __PCLMUL__ */
#endif /* _WMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/x86intrin.h b/contrib/llvm/tools/clang/lib/Headers/x86intrin.h
index 21a43da..4d8077e 100644
--- a/contrib/llvm/tools/clang/lib/Headers/x86intrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/x86intrin.h
@@ -28,53 +28,29 @@
#include <immintrin.h>
-#ifdef __3dNOW__
#include <mm3dnow.h>
-#endif
-#ifdef __BMI__
#include <bmiintrin.h>
-#endif
-#ifdef __BMI2__
#include <bmi2intrin.h>
-#endif
-#ifdef __LZCNT__
#include <lzcntintrin.h>
-#endif
-#ifdef __POPCNT__
#include <popcntintrin.h>
-#endif
-#ifdef __RDSEED__
#include <rdseedintrin.h>
-#endif
-#ifdef __PRFCHW__
#include <prfchwintrin.h>
-#endif
-#ifdef __SSE4A__
#include <ammintrin.h>
-#endif
-#ifdef __FMA4__
#include <fma4intrin.h>
-#endif
-#ifdef __XOP__
#include <xopintrin.h>
-#endif
-#ifdef __TBM__
#include <tbmintrin.h>
-#endif
-#ifdef __F16C__
#include <f16cintrin.h>
-#endif
/* FIXME: LWP */
diff --git a/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h b/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h
index 0d58c75..ae0b2cd 100644
--- a/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/xmmintrin.h
@@ -20,13 +20,9 @@
*
*===-----------------------------------------------------------------------===
*/
-
+
#ifndef __XMMINTRIN_H
#define __XMMINTRIN_H
-
-#ifndef __SSE__
-#error "SSE instruction set not enabled"
-#else
#include <mmintrin.h>
@@ -41,7 +37,7 @@ typedef float __m128 __attribute__((__vector_size__(16)));
#endif
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse")))
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_add_ss(__m128 __a, __m128 __b)
@@ -581,6 +577,12 @@ _mm_loadr_ps(const float *__p)
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_undefined_ps()
+{
+ return (__m128)__builtin_ia32_undef128();
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set_ss(float __w)
{
return (__m128){ __w, 0, 0, 0 };
@@ -752,8 +754,7 @@ _mm_mulhi_pu16(__m64 __a, __m64 __b)
}
#define _mm_shuffle_pi16(a, n) __extension__ ({ \
- __m64 __a = (a); \
- (__m64)__builtin_ia32_pshufw((__v4hi)__a, (n)); })
+ (__m64)__builtin_ia32_pshufw((__v4hi)(__m64)(a), (n)); })
static __inline__ void __DEFAULT_FN_ATTRS
_mm_maskmove_si64(__m64 __d, __m64 __n, char *__p)
@@ -792,9 +793,7 @@ _mm_setcsr(unsigned int __i)
}
#define _mm_shuffle_ps(a, b, mask) __extension__ ({ \
- __m128 __a = (a); \
- __m128 __b = (b); \
- (__m128)__builtin_shufflevector((__v4sf)__a, (__v4sf)__b, \
+ (__m128)__builtin_shufflevector((__v4sf)(__m128)(a), (__v4sf)(__m128)(b), \
(mask) & 0x3, ((mask) & 0xc) >> 2, \
(((mask) & 0x30) >> 4) + 4, \
(((mask) & 0xc0) >> 6) + 4); })
@@ -868,7 +867,7 @@ static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtpi8_ps(__m64 __a)
{
__m64 __b;
-
+
__b = _mm_setzero_si64();
__b = _mm_cmpgt_pi8(__b, __a);
__b = _mm_unpacklo_pi8(__a, __b);
@@ -880,7 +879,7 @@ static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtpu8_ps(__m64 __a)
{
__m64 __b;
-
+
__b = _mm_setzero_si64();
__b = _mm_unpacklo_pi8(__a, __b);
@@ -891,7 +890,7 @@ static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtpi32x2_ps(__m64 __a, __m64 __b)
{
__m128 __c;
-
+
__c = _mm_setzero_ps();
__c = _mm_cvtpi32_ps(__c, __b);
__c = _mm_movelh_ps(__c, __c);
@@ -903,11 +902,11 @@ static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvtps_pi16(__m128 __a)
{
__m64 __b, __c;
-
+
__b = _mm_cvtps_pi32(__a);
__a = _mm_movehl_ps(__a, __a);
__c = _mm_cvtps_pi32(__a);
-
+
return _mm_packs_pi32(__b, __c);
}
@@ -915,10 +914,10 @@ static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_cvtps_pi8(__m128 __a)
{
__m64 __b, __c;
-
+
__b = _mm_cvtps_pi16(__a);
__c = _mm_setzero_si64();
-
+
return _mm_packs_pi16(__b, __c);
}
@@ -928,6 +927,11 @@ _mm_movemask_ps(__m128 __a)
return __builtin_ia32_movmskps(__a);
}
+
+#ifdef _MSC_VER
+#define _MM_ALIGN16 __declspec(align(16))
+#endif
+
#define _MM_SHUFFLE(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w))
#define _MM_EXCEPT_INVALID (0x0001)
@@ -1003,6 +1007,4 @@ do { \
#include <emmintrin.h>
#endif
-#endif /* __SSE__ */
-
#endif /* __XMMINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/xopintrin.h b/contrib/llvm/tools/clang/lib/Headers/xopintrin.h
index 2eb35c4..f07f51c 100644
--- a/contrib/llvm/tools/clang/lib/Headers/xopintrin.h
+++ b/contrib/llvm/tools/clang/lib/Headers/xopintrin.h
@@ -28,14 +28,10 @@
#ifndef __XOPINTRIN_H
#define __XOPINTRIN_H
-#ifndef __XOP__
-# error "XOP instruction set is not enabled"
-#else
-
#include <fma4intrin.h>
/* Define the default attributes for the functions in this file. */
-#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("xop")))
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maccs_epi16(__m128i __A, __m128i __B, __m128i __C)
@@ -242,20 +238,16 @@ _mm_rot_epi64(__m128i __A, __m128i __B)
}
#define _mm_roti_epi8(A, N) __extension__ ({ \
- __m128i __A = (A); \
- (__m128i)__builtin_ia32_vprotbi((__v16qi)__A, (N)); })
+ (__m128i)__builtin_ia32_vprotbi((__v16qi)(__m128i)(A), (N)); })
#define _mm_roti_epi16(A, N) __extension__ ({ \
- __m128i __A = (A); \
- (__m128i)__builtin_ia32_vprotwi((__v8hi)__A, (N)); })
+ (__m128i)__builtin_ia32_vprotwi((__v8hi)(__m128i)(A), (N)); })
#define _mm_roti_epi32(A, N) __extension__ ({ \
- __m128i __A = (A); \
- (__m128i)__builtin_ia32_vprotdi((__v4si)__A, (N)); })
+ (__m128i)__builtin_ia32_vprotdi((__v4si)(__m128i)(A), (N)); })
#define _mm_roti_epi64(A, N) __extension__ ({ \
- __m128i __A = (A); \
- (__m128i)__builtin_ia32_vprotqi((__v2di)__A, (N)); })
+ (__m128i)__builtin_ia32_vprotqi((__v2di)(__m128i)(A), (N)); })
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_shl_epi8(__m128i __A, __m128i __B)
@@ -306,44 +298,36 @@ _mm_sha_epi64(__m128i __A, __m128i __B)
}
#define _mm_com_epu8(A, B, N) __extension__ ({ \
- __m128i __A = (A); \
- __m128i __B = (B); \
- (__m128i)__builtin_ia32_vpcomub((__v16qi)__A, (__v16qi)__B, (N)); })
+ (__m128i)__builtin_ia32_vpcomub((__v16qi)(__m128i)(A), \
+ (__v16qi)(__m128i)(B), (N)); })
#define _mm_com_epu16(A, B, N) __extension__ ({ \
- __m128i __A = (A); \
- __m128i __B = (B); \
- (__m128i)__builtin_ia32_vpcomuw((__v8hi)__A, (__v8hi)__B, (N)); })
+ (__m128i)__builtin_ia32_vpcomuw((__v8hi)(__m128i)(A), \
+ (__v8hi)(__m128i)(B), (N)); })
#define _mm_com_epu32(A, B, N) __extension__ ({ \
- __m128i __A = (A); \
- __m128i __B = (B); \
- (__m128i)__builtin_ia32_vpcomud((__v4si)__A, (__v4si)__B, (N)); })
+ (__m128i)__builtin_ia32_vpcomud((__v4si)(__m128i)(A), \
+ (__v4si)(__m128i)(B), (N)); })
#define _mm_com_epu64(A, B, N) __extension__ ({ \
- __m128i __A = (A); \
- __m128i __B = (B); \
- (__m128i)__builtin_ia32_vpcomuq((__v2di)__A, (__v2di)__B, (N)); })
+ (__m128i)__builtin_ia32_vpcomuq((__v2di)(__m128i)(A), \
+ (__v2di)(__m128i)(B), (N)); })
#define _mm_com_epi8(A, B, N) __extension__ ({ \
- __m128i __A = (A); \
- __m128i __B = (B); \
- (__m128i)__builtin_ia32_vpcomb((__v16qi)__A, (__v16qi)__B, (N)); })
+ (__m128i)__builtin_ia32_vpcomb((__v16qi)(__m128i)(A), \
+ (__v16qi)(__m128i)(B), (N)); })
#define _mm_com_epi16(A, B, N) __extension__ ({ \
- __m128i __A = (A); \
- __m128i __B = (B); \
- (__m128i)__builtin_ia32_vpcomw((__v8hi)__A, (__v8hi)__B, (N)); })
+ (__m128i)__builtin_ia32_vpcomw((__v8hi)(__m128i)(A), \
+ (__v8hi)(__m128i)(B), (N)); })
#define _mm_com_epi32(A, B, N) __extension__ ({ \
- __m128i __A = (A); \
- __m128i __B = (B); \
- (__m128i)__builtin_ia32_vpcomd((__v4si)__A, (__v4si)__B, (N)); })
+ (__m128i)__builtin_ia32_vpcomd((__v4si)(__m128i)(A), \
+ (__v4si)(__m128i)(B), (N)); })
#define _mm_com_epi64(A, B, N) __extension__ ({ \
- __m128i __A = (A); \
- __m128i __B = (B); \
- (__m128i)__builtin_ia32_vpcomq((__v2di)__A, (__v2di)__B, (N)); })
+ (__m128i)__builtin_ia32_vpcomq((__v2di)(__m128i)(A), \
+ (__v2di)(__m128i)(B), (N)); })
#define _MM_PCOMCTRL_LT 0
#define _MM_PCOMCTRL_LE 1
@@ -739,32 +723,23 @@ _mm_comtrue_epi64(__m128i __A, __m128i __B)
}
#define _mm_permute2_pd(X, Y, C, I) __extension__ ({ \
- __m128d __X = (X); \
- __m128d __Y = (Y); \
- __m128i __C = (C); \
- (__m128d)__builtin_ia32_vpermil2pd((__v2df)__X, (__v2df)__Y, \
- (__v2di)__C, (I)); })
+ (__m128d)__builtin_ia32_vpermil2pd((__v2df)(__m128d)(X), \
+ (__v2df)(__m128d)(Y), \
+ (__v2di)(__m128i)(C), (I)); })
#define _mm256_permute2_pd(X, Y, C, I) __extension__ ({ \
- __m256d __X = (X); \
- __m256d __Y = (Y); \
- __m256i __C = (C); \
- (__m256d)__builtin_ia32_vpermil2pd256((__v4df)__X, (__v4df)__Y, \
- (__v4di)__C, (I)); })
+ (__m256d)__builtin_ia32_vpermil2pd256((__v4df)(__m256d)(X), \
+ (__v4df)(__m256d)(Y), \
+ (__v4di)(__m256i)(C), (I)); })
#define _mm_permute2_ps(X, Y, C, I) __extension__ ({ \
- __m128 __X = (X); \
- __m128 __Y = (Y); \
- __m128i __C = (C); \
- (__m128)__builtin_ia32_vpermil2ps((__v4sf)__X, (__v4sf)__Y, \
- (__v4si)__C, (I)); })
+ (__m128)__builtin_ia32_vpermil2ps((__v4sf)(__m128)(X), (__v4sf)(__m128)(Y), \
+ (__v4si)(__m128i)(C), (I)); })
#define _mm256_permute2_ps(X, Y, C, I) __extension__ ({ \
- __m256 __X = (X); \
- __m256 __Y = (Y); \
- __m256i __C = (C); \
- (__m256)__builtin_ia32_vpermil2ps256((__v8sf)__X, (__v8sf)__Y, \
- (__v8si)__C, (I)); })
+ (__m256)__builtin_ia32_vpermil2ps256((__v8sf)(__m256)(X), \
+ (__v8sf)(__m256)(Y), \
+ (__v8si)(__m256i)(C), (I)); })
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_frcz_ss(__m128 __A)
@@ -804,6 +779,4 @@ _mm256_frcz_pd(__m256d __A)
#undef __DEFAULT_FN_ATTRS
-#endif /* __XOP__ */
-
#endif /* __XOPINTRIN_H */
diff --git a/contrib/llvm/tools/clang/lib/Headers/xsavecintrin.h b/contrib/llvm/tools/clang/lib/Headers/xsavecintrin.h
new file mode 100644
index 0000000..598470a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/xsavecintrin.h
@@ -0,0 +1,48 @@
+/*===---- xsavecintrin.h - XSAVEC intrinsic ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <xsavecintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __XSAVECINTRIN_H
+#define __XSAVECINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("xsavec")))
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_xsavec(void *__p, unsigned long long __m) {
+ __builtin_ia32_xsavec(__p, __m);
+}
+
+#ifdef __x86_64__
+static __inline__ void __DEFAULT_FN_ATTRS
+_xsavec64(void *__p, unsigned long long __m) {
+ __builtin_ia32_xsavec64(__p, __m);
+}
+#endif
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/xsaveintrin.h b/contrib/llvm/tools/clang/lib/Headers/xsaveintrin.h
new file mode 100644
index 0000000..a2e6b2e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/xsaveintrin.h
@@ -0,0 +1,58 @@
+/*===---- xsaveintrin.h - XSAVE intrinsic ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <xsaveintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __XSAVEINTRIN_H
+#define __XSAVEINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("xsave")))
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_xsave(void *__p, unsigned long long __m) {
+ return __builtin_ia32_xsave(__p, __m);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_xrstor(void *__p, unsigned long long __m) {
+ return __builtin_ia32_xrstor(__p, __m);
+}
+
+#ifdef __x86_64__
+static __inline__ void __DEFAULT_FN_ATTRS
+_xsave64(void *__p, unsigned long long __m) {
+ return __builtin_ia32_xsave64(__p, __m);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_xrstor64(void *__p, unsigned long long __m) {
+ return __builtin_ia32_xrstor64(__p, __m);
+}
+#endif
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/xsaveoptintrin.h b/contrib/llvm/tools/clang/lib/Headers/xsaveoptintrin.h
new file mode 100644
index 0000000..d3faae7
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/xsaveoptintrin.h
@@ -0,0 +1,48 @@
+/*===---- xsaveoptintrin.h - XSAVEOPT intrinsic ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <xsaveoptintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __XSAVEOPTINTRIN_H
+#define __XSAVEOPTINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("xsaveopt")))
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_xsaveopt(void *__p, unsigned long long __m) {
+ return __builtin_ia32_xsaveopt(__p, __m);
+}
+
+#ifdef __x86_64__
+static __inline__ void __DEFAULT_FN_ATTRS
+_xsaveopt64(void *__p, unsigned long long __m) {
+ return __builtin_ia32_xsaveopt64(__p, __m);
+}
+#endif
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Headers/xsavesintrin.h b/contrib/llvm/tools/clang/lib/Headers/xsavesintrin.h
new file mode 100644
index 0000000..c5e540a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Headers/xsavesintrin.h
@@ -0,0 +1,58 @@
+/*===---- xsavesintrin.h - XSAVES intrinsic ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <xsavesintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef __XSAVESINTRIN_H
+#define __XSAVESINTRIN_H
+
+/* Define the default attributes for the functions in this file. */
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("xsaves")))
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_xsaves(void *__p, unsigned long long __m) {
+ __builtin_ia32_xsaves(__p, __m);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_xrstors(void *__p, unsigned long long __m) {
+ __builtin_ia32_xrstors(__p, __m);
+}
+
+#ifdef __x86_64__
+static __inline__ void __DEFAULT_FN_ATTRS
+_xrstors64(void *__p, unsigned long long __m) {
+ __builtin_ia32_xrstors64(__p, __m);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_xsaves64(void *__p, unsigned long long __m) {
+ __builtin_ia32_xsaves64(__p, __m);
+}
+#endif
+
+#undef __DEFAULT_FN_ATTRS
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp b/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp
index ef6aeef..15f1696 100644
--- a/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp
@@ -481,7 +481,6 @@ void CommentASTToHTMLConverter::visitFullComment(const FullComment *C) {
Result << "</div>";
}
- Result.flush();
}
void CommentASTToHTMLConverter::visitNonStandaloneParagraphComment(
@@ -895,7 +894,7 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
FileID FID = LocInfo.first;
unsigned FileOffset = LocInfo.second;
- if (!FID.isInvalid()) {
+ if (FID.isValid()) {
if (const FileEntry *FE = SM.getFileEntryForID(FID)) {
Result << " file=\"";
appendToResultWithXMLEscaping(FE->getName());
@@ -1078,8 +1077,6 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
}
Result << RootEndTag;
-
- Result.flush();
}
void CommentASTToXMLConverter::appendToResultWithXMLEscaping(StringRef S) {
diff --git a/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h b/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h
index b884214..2c26e4d 100644
--- a/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h
+++ b/contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h
@@ -38,18 +38,17 @@ public:
: DiagOpts(new DiagnosticOptions()),
Diagnostics(new DiagnosticsEngine(new DiagnosticIDs,
DiagOpts.get())),
- Files((FileSystemOptions())),
+ InMemoryFileSystem(new vfs::InMemoryFileSystem),
+ Files(FileSystemOptions(), InMemoryFileSystem),
Sources(*Diagnostics, Files),
Rewrite(Sources, Options) {
Diagnostics->setClient(new IgnoringDiagConsumer, true);
}
FileID createInMemoryFile(StringRef Name, StringRef Content) {
- std::unique_ptr<llvm::MemoryBuffer> Source =
- llvm::MemoryBuffer::getMemBuffer(Content);
- const FileEntry *Entry =
- Files.getVirtualFile(Name, Source->getBufferSize(), 0);
- Sources.overrideFileContents(Entry, std::move(Source));
+ InMemoryFileSystem->addFile(Name, 0,
+ llvm::MemoryBuffer::getMemBuffer(Content));
+ const FileEntry *Entry = Files.getFile(Name);
assert(Entry != nullptr);
return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
}
@@ -64,6 +63,7 @@ public:
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
FileManager Files;
SourceManager Sources;
Rewriter Rewrite;
diff --git a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
index 8cdd283..c57694f 100644
--- a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
+++ b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp
@@ -156,10 +156,8 @@ public:
//===----------------------------------------------------------------------===//
bool USRGenerator::EmitDeclName(const NamedDecl *D) {
- Out.flush();
const unsigned startSize = Buf.size();
D->printName(Out);
- Out.flush();
const unsigned endSize = Buf.size();
return startSize == endSize;
}
@@ -462,7 +460,6 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) {
}
Out << '@';
- Out.flush();
assert(Buf.size() > 0);
const unsigned off = Buf.size() - 1;
@@ -613,8 +610,18 @@ void USRGenerator::VisitType(QualType T) {
case BuiltinType::OCLImage1dBuffer:
case BuiltinType::OCLImage2d:
case BuiltinType::OCLImage2dArray:
+ case BuiltinType::OCLImage2dDepth:
+ case BuiltinType::OCLImage2dArrayDepth:
+ case BuiltinType::OCLImage2dMSAA:
+ case BuiltinType::OCLImage2dArrayMSAA:
+ case BuiltinType::OCLImage2dMSAADepth:
+ case BuiltinType::OCLImage2dArrayMSAADepth:
case BuiltinType::OCLImage3d:
case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLNDRange:
+ case BuiltinType::OCLReserveID:
case BuiltinType::OCLSampler:
IgnoreResults = true;
return;
diff --git a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
index 983dc18..2d005dd 100644
--- a/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/HeaderSearch.cpp
@@ -127,11 +127,12 @@ std::string HeaderSearch::getModuleFileName(Module *Module) {
std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
StringRef ModuleMapPath) {
- // If we don't have a module cache path, we can't do anything.
- if (ModuleCachePath.empty())
+ // If we don't have a module cache path or aren't supposed to use one, we
+ // can't do anything.
+ if (getModuleCachePath().empty())
return std::string();
- SmallString<256> Result(ModuleCachePath);
+ SmallString<256> Result(getModuleCachePath());
llvm::sys::fs::make_absolute(Result);
if (HSOpts->DisableModuleHash) {
@@ -152,8 +153,7 @@ std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
auto FileName = llvm::sys::path::filename(ModuleMapPath);
llvm::hash_code Hash =
- llvm::hash_combine(DirName.lower(), FileName.lower(),
- HSOpts->ModuleFormat);
+ llvm::hash_combine(DirName.lower(), FileName.lower());
SmallString<128> HashStr;
llvm::APInt(64, size_t(Hash)).toStringUnsigned(HashStr, /*Radix*/36);
@@ -249,31 +249,22 @@ const char *DirectoryLookup::getName() const {
return getHeaderMap()->getFileName();
}
-static const FileEntry *
-getFileAndSuggestModule(HeaderSearch &HS, StringRef FileName,
- const DirectoryEntry *Dir, bool IsSystemHeaderDir,
- ModuleMap::KnownHeader *SuggestedModule) {
+const FileEntry *HeaderSearch::getFileAndSuggestModule(
+ StringRef FileName, const DirectoryEntry *Dir, bool IsSystemHeaderDir,
+ Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) {
// If we have a module map that might map this header, load it and
// check whether we'll have a suggestion for a module.
- HS.hasModuleMap(FileName, Dir, IsSystemHeaderDir);
- if (SuggestedModule) {
- const FileEntry *File = HS.getFileMgr().getFile(FileName,
- /*OpenFile=*/false);
- if (File) {
- // If there is a module that corresponds to this header, suggest it.
- *SuggestedModule = HS.findModuleForHeader(File);
-
- // FIXME: This appears to be a no-op. We loaded the module map for this
- // directory at the start of this function.
- if (!SuggestedModule->getModule() &&
- HS.hasModuleMap(FileName, Dir, IsSystemHeaderDir))
- *SuggestedModule = HS.findModuleForHeader(File);
- }
+ const FileEntry *File = getFileMgr().getFile(FileName, /*OpenFile=*/true);
+ if (!File)
+ return nullptr;
- return File;
- }
+ // If there is a module that corresponds to this header, suggest it.
+ if (!findUsableModuleForHeader(File, Dir ? Dir : File->getDir(),
+ RequestingModule, SuggestedModule,
+ IsSystemHeaderDir))
+ return nullptr;
- return HS.getFileMgr().getFile(FileName, /*openFile=*/true);
+ return File;
}
/// LookupFile - Lookup the specified file in this search path, returning it
@@ -283,6 +274,7 @@ const FileEntry *DirectoryLookup::LookupFile(
HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
+ Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework,
bool &HasBeenMapped,
@@ -305,14 +297,15 @@ const FileEntry *DirectoryLookup::LookupFile(
RelativePath->append(Filename.begin(), Filename.end());
}
- return getFileAndSuggestModule(HS, TmpDir, getDir(),
- isSystemHeaderDirectory(),
- SuggestedModule);
+ return HS.getFileAndSuggestModule(TmpDir, getDir(),
+ isSystemHeaderDirectory(),
+ RequestingModule, SuggestedModule);
}
if (isFramework())
return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
- SuggestedModule, InUserSpecifiedSystemFramework);
+ RequestingModule, SuggestedModule,
+ InUserSpecifiedSystemFramework);
assert(isHeaderMap() && "Unknown directory lookup");
const HeaderMap *HM = getHeaderMap();
@@ -404,13 +397,10 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,
/// DoFrameworkLookup - Do a lookup of the specified file in the current
/// DirectoryLookup, which is a framework directory.
const FileEntry *DirectoryLookup::DoFrameworkLookup(
- StringRef Filename,
- HeaderSearch &HS,
- SmallVectorImpl<char> *SearchPath,
- SmallVectorImpl<char> *RelativePath,
+ StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,
+ SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule,
- bool &InUserSpecifiedSystemFramework) const
-{
+ bool &InUserSpecifiedSystemFramework) const {
FileManager &FileMgr = HS.getFileMgr();
// Framework names must have a '/' in the filename.
@@ -522,27 +512,15 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
break;
} while (true);
+ bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
if (FoundFramework) {
- // Find the top-level framework based on this framework.
- SmallVector<std::string, 4> SubmodulePath;
- const DirectoryEntry *TopFrameworkDir
- = ::getTopFrameworkDir(FileMgr, FrameworkPath, SubmodulePath);
-
- // Determine the name of the top-level framework.
- StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());
-
- // Load this framework module. If that succeeds, find the suggested module
- // for this header, if any.
- bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
- HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem);
-
- // FIXME: This can find a module not part of ModuleName, which is
- // important so that we're consistent about whether this header
- // corresponds to a module. Possibly we should lock down framework modules
- // so that this is not possible.
- *SuggestedModule = HS.findModuleForHeader(FE);
+ if (!HS.findUsableModuleForFrameworkHeader(
+ FE, FrameworkPath, RequestingModule, SuggestedModule, IsSystem))
+ return nullptr;
} else {
- *SuggestedModule = HS.findModuleForHeader(FE);
+ if (!HS.findUsableModuleForHeader(FE, getDir(), RequestingModule,
+ SuggestedModule, IsSystem))
+ return nullptr;
}
}
return FE;
@@ -588,7 +566,8 @@ const FileEntry *HeaderSearch::LookupFile(
const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
- ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) {
+ Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
+ bool SkipCache) {
if (SuggestedModule)
*SuggestedModule = ModuleMap::KnownHeader();
@@ -606,13 +585,9 @@ const FileEntry *HeaderSearch::LookupFile(
RelativePath->append(Filename.begin(), Filename.end());
}
// Otherwise, just return the file.
- const FileEntry *File = FileMgr.getFile(Filename, /*openFile=*/true);
- if (File && SuggestedModule) {
- // If there is a module that corresponds to this header, suggest it.
- hasModuleMap(Filename, File->getDir(), /*SystemHeaderDir*/false);
- *SuggestedModule = findModuleForHeader(File);
- }
- return File;
+ return getFileAndSuggestModule(Filename, nullptr,
+ /*IsSystemHeaderDir*/false,
+ RequestingModule, SuggestedModule);
}
// This is the header that MSVC's header search would have found.
@@ -646,8 +621,8 @@ const FileEntry *HeaderSearch::LookupFile(
bool IncluderIsSystemHeader =
Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User;
if (const FileEntry *FE = getFileAndSuggestModule(
- *this, TmpDir, IncluderAndDir.second,
- IncluderIsSystemHeader, SuggestedModule)) {
+ TmpDir, IncluderAndDir.second, IncluderIsSystemHeader,
+ RequestingModule, SuggestedModule)) {
if (!Includer) {
assert(First && "only first includer can have no file");
return FE;
@@ -736,10 +711,10 @@ const FileEntry *HeaderSearch::LookupFile(
for (; i != SearchDirs.size(); ++i) {
bool InUserSpecifiedSystemFramework = false;
bool HasBeenMapped = false;
- const FileEntry *FE =
- SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
- SuggestedModule, InUserSpecifiedSystemFramework,
- HasBeenMapped, MappedName);
+ const FileEntry *FE = SearchDirs[i].LookupFile(
+ Filename, *this, SearchPath, RelativePath, RequestingModule,
+ SuggestedModule, InUserSpecifiedSystemFramework, HasBeenMapped,
+ MappedName);
if (HasBeenMapped) {
CacheLookup.MappedName =
copyString(Filename, LookupFileCache.getAllocator());
@@ -803,9 +778,10 @@ const FileEntry *HeaderSearch::LookupFile(
ScratchFilename += '/';
ScratchFilename += Filename;
- const FileEntry *FE = LookupFile(
- ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir,
- Includers.front(), SearchPath, RelativePath, SuggestedModule);
+ const FileEntry *FE =
+ LookupFile(ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir,
+ CurDir, Includers.front(), SearchPath, RelativePath,
+ RequestingModule, SuggestedModule);
if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) {
if (SuggestedModule)
@@ -841,6 +817,7 @@ LookupSubframeworkHeader(StringRef Filename,
const FileEntry *ContextFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
+ Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule) {
assert(ContextFileEnt && "No context file?");
@@ -932,24 +909,10 @@ LookupSubframeworkHeader(StringRef Filename,
unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo;
getFileInfo(FE).DirInfo = DirInfo;
- // If we're supposed to suggest a module, look for one now.
- if (SuggestedModule) {
- // Find the top-level framework based on this framework.
- FrameworkName.pop_back(); // remove the trailing '/'
- SmallVector<std::string, 4> SubmodulePath;
- const DirectoryEntry *TopFrameworkDir
- = ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath);
-
- // Determine the name of the top-level framework.
- StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());
-
- // Load this framework module. If that succeeds, find the suggested module
- // for this header, if any.
- bool IsSystem = false;
- if (loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem)) {
- *SuggestedModule = findModuleForHeader(FE);
- }
- }
+ FrameworkName.pop_back(); // remove the trailing '/'
+ if (!findUsableModuleForFrameworkHeader(FE, FrameworkName, RequestingModule,
+ SuggestedModule, /*IsSystem*/ false))
+ return nullptr;
return FE;
}
@@ -962,77 +925,112 @@ LookupSubframeworkHeader(StringRef Filename,
/// header file info (\p HFI)
static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
const HeaderFileInfo &OtherHFI) {
+ assert(OtherHFI.External && "expected to merge external HFI");
+
HFI.isImport |= OtherHFI.isImport;
HFI.isPragmaOnce |= OtherHFI.isPragmaOnce;
HFI.isModuleHeader |= OtherHFI.isModuleHeader;
HFI.NumIncludes += OtherHFI.NumIncludes;
-
+
if (!HFI.ControllingMacro && !HFI.ControllingMacroID) {
HFI.ControllingMacro = OtherHFI.ControllingMacro;
HFI.ControllingMacroID = OtherHFI.ControllingMacroID;
}
-
- if (OtherHFI.External) {
- HFI.DirInfo = OtherHFI.DirInfo;
- HFI.External = OtherHFI.External;
- HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader;
- }
+
+ HFI.DirInfo = OtherHFI.DirInfo;
+ HFI.External = (!HFI.IsValid || HFI.External);
+ HFI.IsValid = true;
+ HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader;
if (HFI.Framework.empty())
HFI.Framework = OtherHFI.Framework;
-
- HFI.Resolved = true;
}
/// getFileInfo - Return the HeaderFileInfo structure for the specified
/// FileEntry.
HeaderFileInfo &HeaderSearch::getFileInfo(const FileEntry *FE) {
if (FE->getUID() >= FileInfo.size())
- FileInfo.resize(FE->getUID()+1);
-
- HeaderFileInfo &HFI = FileInfo[FE->getUID()];
- if (ExternalSource && !HFI.Resolved)
- mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(FE));
- HFI.IsValid = 1;
- return HFI;
+ FileInfo.resize(FE->getUID() + 1);
+
+ HeaderFileInfo *HFI = &FileInfo[FE->getUID()];
+ // FIXME: Use a generation count to check whether this is really up to date.
+ if (ExternalSource && !HFI->Resolved) {
+ HFI->Resolved = true;
+ auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
+
+ HFI = &FileInfo[FE->getUID()];
+ if (ExternalHFI.External)
+ mergeHeaderFileInfo(*HFI, ExternalHFI);
+ }
+
+ HFI->IsValid = true;
+ // We have local information about this header file, so it's no longer
+ // strictly external.
+ HFI->External = false;
+ return *HFI;
}
-bool HeaderSearch::tryGetFileInfo(const FileEntry *FE,
- HeaderFileInfo &Result) const {
- if (FE->getUID() >= FileInfo.size())
- return false;
- const HeaderFileInfo &HFI = FileInfo[FE->getUID()];
- if (HFI.IsValid) {
- Result = HFI;
- return true;
+const HeaderFileInfo *
+HeaderSearch::getExistingFileInfo(const FileEntry *FE,
+ bool WantExternal) const {
+ // If we have an external source, ensure we have the latest information.
+ // FIXME: Use a generation count to check whether this is really up to date.
+ HeaderFileInfo *HFI;
+ if (ExternalSource) {
+ if (FE->getUID() >= FileInfo.size()) {
+ if (!WantExternal)
+ return nullptr;
+ FileInfo.resize(FE->getUID() + 1);
+ }
+
+ HFI = &FileInfo[FE->getUID()];
+ if (!WantExternal && (!HFI->IsValid || HFI->External))
+ return nullptr;
+ if (!HFI->Resolved) {
+ HFI->Resolved = true;
+ auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
+
+ HFI = &FileInfo[FE->getUID()];
+ if (ExternalHFI.External)
+ mergeHeaderFileInfo(*HFI, ExternalHFI);
+ }
+ } else if (FE->getUID() >= FileInfo.size()) {
+ return nullptr;
+ } else {
+ HFI = &FileInfo[FE->getUID()];
}
- return false;
+
+ if (!HFI->IsValid || (HFI->External && !WantExternal))
+ return nullptr;
+
+ return HFI;
}
bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) {
// Check if we've ever seen this file as a header.
- if (File->getUID() >= FileInfo.size())
- return false;
-
- // Resolve header file info from the external source, if needed.
- HeaderFileInfo &HFI = FileInfo[File->getUID()];
- if (ExternalSource && !HFI.Resolved)
- mergeHeaderFileInfo(HFI, ExternalSource->GetHeaderFileInfo(File));
-
- return HFI.isPragmaOnce || HFI.isImport ||
- HFI.ControllingMacro || HFI.ControllingMacroID;
+ if (auto *HFI = getExistingFileInfo(File))
+ return HFI->isPragmaOnce || HFI->isImport || HFI->ControllingMacro ||
+ HFI->ControllingMacroID;
+ return false;
}
void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE,
ModuleMap::ModuleHeaderRole Role,
bool isCompilingModuleHeader) {
- if (FE->getUID() >= FileInfo.size())
- FileInfo.resize(FE->getUID()+1);
+ bool isModularHeader = !(Role & ModuleMap::TextualHeader);
+
+ // Don't mark the file info as non-external if there's nothing to change.
+ if (!isCompilingModuleHeader) {
+ if (!isModularHeader)
+ return;
+ auto *HFI = getExistingFileInfo(FE);
+ if (HFI && HFI->isModuleHeader)
+ return;
+ }
- HeaderFileInfo &HFI = FileInfo[FE->getUID()];
- HFI.isModuleHeader = true;
+ auto &HFI = getFileInfo(FE);
+ HFI.isModuleHeader |= isModularHeader;
HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
- HFI.setHeaderRole(Role);
}
bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
@@ -1142,11 +1140,48 @@ HeaderSearch::findModuleForHeader(const FileEntry *File) const {
if (ExternalSource) {
// Make sure the external source has handled header info about this file,
// which includes whether the file is part of a module.
- (void)getFileInfo(File);
+ (void)getExistingFileInfo(File);
}
return ModMap.findModuleForHeader(File);
}
+bool HeaderSearch::findUsableModuleForHeader(
+ const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) {
+ if (File && SuggestedModule) {
+ // If there is a module that corresponds to this header, suggest it.
+ hasModuleMap(File->getName(), Root, IsSystemHeaderDir);
+ *SuggestedModule = findModuleForHeader(File);
+ }
+ return true;
+}
+
+bool HeaderSearch::findUsableModuleForFrameworkHeader(
+ const FileEntry *File, StringRef FrameworkName, Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) {
+ // If we're supposed to suggest a module, look for one now.
+ if (SuggestedModule) {
+ // Find the top-level framework based on this framework.
+ SmallVector<std::string, 4> SubmodulePath;
+ const DirectoryEntry *TopFrameworkDir
+ = ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath);
+
+ // Determine the name of the top-level framework.
+ StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());
+
+ // Load this framework module. If that succeeds, find the suggested module
+ // for this header, if any.
+ loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystemFramework);
+
+ // FIXME: This can find a module not part of ModuleName, which is
+ // important so that we're consistent about whether this header
+ // corresponds to a module. Possibly we should lock down framework modules
+ // so that this is not possible.
+ *SuggestedModule = findModuleForHeader(File);
+ }
+ return true;
+}
+
static const FileEntry *getPrivateModuleMap(const FileEntry *File,
FileManager &FileMgr) {
StringRef Filename = llvm::sys::path::filename(File->getName());
diff --git a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
index 4007914..27b0feb 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp
@@ -235,7 +235,7 @@ static size_t getSpellingSlow(const Token &Tok, const char *BufPtr,
size_t Length = 0;
const char *BufEnd = BufPtr + Tok.getLength();
- if (Tok.is(tok::string_literal)) {
+ if (tok::isStringLiteral(Tok.getKind())) {
// Munch the encoding-prefix and opening double-quote.
while (BufPtr < BufEnd) {
unsigned Size;
@@ -1354,7 +1354,9 @@ void Lexer::SkipBytes(unsigned Bytes, bool StartOfLine) {
}
static bool isAllowedIDChar(uint32_t C, const LangOptions &LangOpts) {
- if (LangOpts.CPlusPlus11 || LangOpts.C11) {
+ if (LangOpts.AsmPreprocessor) {
+ return false;
+ } else if (LangOpts.CPlusPlus11 || LangOpts.C11) {
static const llvm::sys::UnicodeCharSet C11AllowedIDChars(
C11AllowedIDCharRanges);
return C11AllowedIDChars.contains(C);
@@ -1371,7 +1373,9 @@ static bool isAllowedIDChar(uint32_t C, const LangOptions &LangOpts) {
static bool isAllowedInitiallyIDChar(uint32_t C, const LangOptions &LangOpts) {
assert(isAllowedIDChar(C, LangOpts));
- if (LangOpts.CPlusPlus11 || LangOpts.C11) {
+ if (LangOpts.AsmPreprocessor) {
+ return false;
+ } else if (LangOpts.CPlusPlus11 || LangOpts.C11) {
static const llvm::sys::UnicodeCharSet C11DisallowedInitialIDChars(
C11DisallowedInitialIDCharRanges);
return !C11DisallowedInitialIDChars.contains(C);
@@ -1732,7 +1736,7 @@ bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr,
if (C == '\n' || C == '\r' || // Newline.
(C == 0 && CurPtr-1 == BufferEnd)) { // End of file.
if (!isLexingRawMode() && !LangOpts.AsmPreprocessor)
- Diag(BufferPtr, diag::ext_unterminated_string);
+ Diag(BufferPtr, diag::ext_unterminated_char_or_string) << 1;
FormTokenWithChars(Result, CurPtr-1, tok::unknown);
return true;
}
@@ -1756,7 +1760,7 @@ bool Lexer::LexStringLiteral(Token &Result, const char *CurPtr,
// If a nul character existed in the string, warn about it.
if (NulCharacter && !isLexingRawMode())
- Diag(NulCharacter, diag::null_in_string);
+ Diag(NulCharacter, diag::null_in_char_or_string) << 1;
// Update the location of the token as well as the BufferPtr instance var.
const char *TokStart = BufferPtr;
@@ -1872,7 +1876,7 @@ bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) {
// If a nul character existed in the string, warn about it.
if (NulCharacter && !isLexingRawMode())
- Diag(NulCharacter, diag::null_in_string);
+ Diag(NulCharacter, diag::null_in_char_or_string) << 1;
// Update the location of token as well as BufferPtr.
const char *TokStart = BufferPtr;
@@ -1914,7 +1918,7 @@ bool Lexer::LexCharConstant(Token &Result, const char *CurPtr,
if (C == '\n' || C == '\r' || // Newline.
(C == 0 && CurPtr-1 == BufferEnd)) { // End of file.
if (!isLexingRawMode() && !LangOpts.AsmPreprocessor)
- Diag(BufferPtr, diag::ext_unterminated_char);
+ Diag(BufferPtr, diag::ext_unterminated_char_or_string) << 0;
FormTokenWithChars(Result, CurPtr-1, tok::unknown);
return true;
}
@@ -1938,7 +1942,7 @@ bool Lexer::LexCharConstant(Token &Result, const char *CurPtr,
// If a nul character existed in the character, warn about it.
if (NulCharacter && !isLexingRawMode())
- Diag(NulCharacter, diag::null_in_char);
+ Diag(NulCharacter, diag::null_in_char_or_string) << 0;
// Update the location of token as well as BufferPtr.
const char *TokStart = BufferPtr;
@@ -2956,8 +2960,11 @@ LexNextToken:
case 26: // DOS & CP/M EOF: "^Z".
// If we're in Microsoft extensions mode, treat this as end of file.
- if (LangOpts.MicrosoftExt)
+ if (LangOpts.MicrosoftExt) {
+ if (!isLexingRawMode())
+ Diag(CurPtr-1, diag::ext_ctrl_z_eof_microsoft);
return LexEndOfFile(Result, CurPtr-1);
+ }
// If Microsoft extensions are disabled, this is just random garbage.
Kind = tok::unknown;
diff --git a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
index aed9164..5b1c493 100644
--- a/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/LiteralSupport.cpp
@@ -159,7 +159,7 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin,
// Check for overflow.
if (Overflow && Diags) // Too many digits to fit in
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
- diag::err_hex_escape_too_large);
+ diag::err_escape_too_large) << 0;
break;
}
case '0': case '1': case '2': case '3':
@@ -182,7 +182,7 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin,
if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) {
if (Diags)
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
- diag::err_octal_escape_too_large);
+ diag::err_escape_too_large) << 1;
ResultChar &= ~0U >> (32-CharWidth);
}
break;
@@ -538,7 +538,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
// Done.
} else if (isHexDigit(*s) && !(*s == 'e' || *s == 'E')) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
- diag::err_invalid_decimal_digit) << StringRef(s, 1);
+ diag::err_invalid_digit) << StringRef(s, 1) << 0;
hadError = true;
return;
} else if (*s == '.') {
@@ -613,7 +613,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
break;
if (!isFPConstant) {
- // Allow i8, i16, i32, i64, and i128.
+ // Allow i8, i16, i32, and i64.
switch (s[1]) {
case '8':
s += 2; // i8 suffix
@@ -623,9 +623,6 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
if (s[2] == '6') {
s += 3; // i16 suffix
MicrosoftInteger = 16;
- } else if (s[2] == '2' && s[3] == '8') {
- s += 4; // i128 suffix
- MicrosoftInteger = 128;
}
break;
case '3':
@@ -683,9 +680,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
// Report an error if there are any.
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin),
- isFPConstant ? diag::err_invalid_suffix_float_constant :
- diag::err_invalid_suffix_integer_constant)
- << StringRef(SuffixBegin, ThisTokEnd-SuffixBegin);
+ diag::err_invalid_suffix_constant)
+ << StringRef(SuffixBegin, ThisTokEnd-SuffixBegin) << isFPConstant;
hadError = true;
return;
}
@@ -770,7 +766,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
if (noSignificand) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
- diag::err_hexconstant_requires_digits);
+ diag::err_hexconstant_requires) << 1;
hadError = true;
return;
}
@@ -797,7 +793,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
PP.Diag(TokLoc, diag::ext_hexconstant_invalid);
} else if (saw_period) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
- diag::err_hexconstant_requires_exponent);
+ diag::err_hexconstant_requires) << 0;
hadError = true;
}
return;
@@ -821,7 +817,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
// Done.
} else if (isHexDigit(*s)) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
- diag::err_invalid_binary_digit) << StringRef(s, 1);
+ diag::err_invalid_digit) << StringRef(s, 1) << 2;
hadError = true;
}
// Other suffixes will be diagnosed by the caller.
@@ -851,7 +847,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
// the code is using an incorrect base.
if (isHexDigit(*s) && *s != 'e' && *s != 'E') {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
- diag::err_invalid_octal_digit) << StringRef(s, 1);
+ diag::err_invalid_digit) << StringRef(s, 1) << 1;
hadError = true;
return;
}
@@ -987,6 +983,7 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {
/// u' c-char-sequence '
/// U' c-char-sequence '
/// L' c-char-sequence '
+/// u8' c-char-sequence ' [C++1z lex.ccon]
/// c-char-sequence:
/// c-char
/// c-char-sequence c-char
@@ -1420,10 +1417,23 @@ void StringLiteralParser::init(ArrayRef<Token> StringToks){
ThisTokEnd -= ThisTokBuf - Prefix;
assert(ThisTokEnd >= ThisTokBuf && "malformed raw string literal");
- // Copy the string over
- if (CopyStringFragment(StringToks[i], ThisTokBegin,
- StringRef(ThisTokBuf, ThisTokEnd - ThisTokBuf)))
- hadError = true;
+ // C++14 [lex.string]p4: A source-file new-line in a raw string literal
+ // results in a new-line in the resulting execution string-literal.
+ StringRef RemainingTokenSpan(ThisTokBuf, ThisTokEnd - ThisTokBuf);
+ while (!RemainingTokenSpan.empty()) {
+ // Split the string literal on \r\n boundaries.
+ size_t CRLFPos = RemainingTokenSpan.find("\r\n");
+ StringRef BeforeCRLF = RemainingTokenSpan.substr(0, CRLFPos);
+ StringRef AfterCRLF = RemainingTokenSpan.substr(CRLFPos);
+
+ // Copy everything before the \r\n sequence into the string literal.
+ if (CopyStringFragment(StringToks[i], ThisTokBegin, BeforeCRLF))
+ hadError = true;
+
+ // Point into the \n inside the \r\n sequence and operate on the
+ // remaining portion of the literal.
+ RemainingTokenSpan = AfterCRLF.substr(1);
+ }
} else {
if (ThisTokBuf[0] != '"') {
// The file may have come from PCH and then changed after loading the
diff --git a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
index 109b6c1..0b4292f 100644
--- a/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/MacroInfo.cpp
@@ -154,16 +154,20 @@ void MacroInfo::dump() const {
Out << ")";
}
+ bool First = true;
for (const Token &Tok : ReplacementTokens) {
- Out << " ";
+ // Leading space is semantically meaningful in a macro definition,
+ // so preserve it in the dump output.
+ if (First || Tok.hasLeadingSpace())
+ Out << " ";
+ First = false;
+
if (const char *Punc = tok::getPunctuatorSpelling(Tok.getKind()))
Out << Punc;
- else if (const char *Kwd = tok::getKeywordSpelling(Tok.getKind()))
- Out << Kwd;
- else if (Tok.is(tok::identifier))
- Out << Tok.getIdentifierInfo()->getName();
else if (Tok.isLiteral() && Tok.getLiteralData())
Out << StringRef(Tok.getLiteralData(), Tok.getLength());
+ else if (auto *II = Tok.getIdentifierInfo())
+ Out << II->getName();
else
Out << Tok.getName();
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
index 96d3e4b..a752402 100644
--- a/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/ModuleMap.cpp
@@ -231,11 +231,9 @@ static bool violatesPrivateInclude(Module *RequestingModule,
assert((!IsPrivateRole || IsPrivate) && "inconsistent headers and roles");
}
#endif
- return IsPrivateRole &&
- // FIXME: Should we map RequestingModule to its top-level module here
- // too? This check is redundant with the isSubModuleOf check in
- // diagnoseHeaderInclusion.
- RequestedModule->getTopLevelModule() != RequestingModule;
+ return IsPrivateRole && (!RequestingModule ||
+ RequestedModule->getTopLevelModule() !=
+ RequestingModule->getTopLevelModule());
}
static Module *getTopLevelOrNull(Module *M) {
@@ -261,11 +259,6 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
HeadersMap::iterator Known = findKnownHeader(File);
if (Known != Headers.end()) {
for (const KnownHeader &Header : Known->second) {
- // If 'File' is part of 'RequestingModule' we can definitely include it.
- if (Header.getModule() &&
- Header.getModule()->isSubModuleOf(RequestingModule))
- return;
-
// Remember private headers for later printing of a diagnostic.
if (violatesPrivateInclude(RequestingModule, File, Header.getRole(),
Header.getModule())) {
@@ -320,6 +313,10 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
const ModuleMap::KnownHeader &Old) {
+ // Prefer available modules.
+ if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
+ return true;
+
// Prefer a public header over a private header.
if ((New.getRole() & ModuleMap::PrivateHeader) !=
(Old.getRole() & ModuleMap::PrivateHeader))
@@ -349,15 +346,19 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) {
// Prefer a header from the current module over all others.
if (H.getModule()->getTopLevelModule() == CompilingModule)
return MakeResult(H);
- // Cannot use a module if it is unavailable.
- if (!H.getModule()->isAvailable())
- continue;
if (!Result || isBetterKnownHeader(H, Result))
Result = H;
}
return MakeResult(Result);
}
+ return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
+}
+
+ModuleMap::KnownHeader
+ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
+ assert(!Headers.count(File) && "already have a module for this header");
+
SmallVector<const DirectoryEntry *, 2> SkippedDirs;
KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
if (H) {
@@ -418,19 +419,22 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) {
UmbrellaDirs[SkippedDirs[I]] = Result;
}
- Headers[File].push_back(KnownHeader(Result, NormalHeader));
-
- // If a header corresponds to an unavailable module, don't report
- // that it maps to anything.
- if (!Result->isAvailable())
- return KnownHeader();
-
- return MakeResult(Headers[File].back());
+ KnownHeader Header(Result, NormalHeader);
+ Headers[File].push_back(Header);
+ return Header;
}
return KnownHeader();
}
+ArrayRef<ModuleMap::KnownHeader>
+ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
+ auto It = Headers.find(File);
+ if (It == Headers.end())
+ return None;
+ return It->second;
+}
+
bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
return isHeaderUnavailableInModule(Header, nullptr);
}
@@ -577,9 +581,18 @@ static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
SmallString<128> LibName;
LibName += FrameworkDir->getName();
llvm::sys::path::append(LibName, Mod->Name);
- if (FileMgr.getFile(LibName)) {
- Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
- /*IsFramework=*/true));
+
+ // The library name of a framework has more than one possible extension since
+ // the introduction of the text-based dynamic library format. We need to check
+ // for both before we give up.
+ static const char *frameworkExtensions[] = {"", ".tbd"};
+ for (const auto *extension : frameworkExtensions) {
+ llvm::sys::path::replace_extension(LibName, extension);
+ if (FileMgr.getFile(LibName)) {
+ Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
+ /*IsFramework=*/true));
+ return;
+ }
}
}
@@ -785,15 +798,27 @@ static Module::HeaderKind headerRoleToKind(ModuleMap::ModuleHeaderRole Role) {
}
void ModuleMap::addHeader(Module *Mod, Module::Header Header,
- ModuleHeaderRole Role) {
- if (!(Role & TextualHeader)) {
- bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule;
+ ModuleHeaderRole Role, bool Imported) {
+ KnownHeader KH(Mod, Role);
+
+ // Only add each header to the headers list once.
+ // FIXME: Should we diagnose if a header is listed twice in the
+ // same module definition?
+ auto &HeaderList = Headers[Header.Entry];
+ for (auto H : HeaderList)
+ if (H == KH)
+ return;
+
+ HeaderList.push_back(KH);
+ Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header));
+
+ bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule;
+ if (!Imported || isCompilingModuleHeader) {
+ // When we import HeaderFileInfo, the external source is expected to
+ // set the isModuleHeader flag itself.
HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
isCompilingModuleHeader);
}
- Headers[Header.Entry].push_back(KnownHeader(Mod, Role));
-
- Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header));
}
void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
@@ -1015,7 +1040,17 @@ namespace clang {
/// \brief The active module.
Module *ActiveModule;
-
+
+ /// \brief Whether a module uses the 'requires excluded' hack to mark its
+ /// contents as 'textual'.
+ ///
+ /// On older Darwin SDK versions, 'requires excluded' is used to mark the
+ /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
+ /// non-modular headers. For backwards compatibility, we continue to
+ /// support this idiom for just these modules, and map the headers to
+ /// 'textual' to match the original intent.
+ llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
+
/// \brief Consume the current token and return its location.
SourceLocation consumeToken();
@@ -1570,6 +1605,38 @@ void ModuleMapParser::parseExternModuleDecl() {
: File->getDir(), ExternLoc);
}
+/// Whether to add the requirement \p Feature to the module \p M.
+///
+/// This preserves backwards compatibility for two hacks in the Darwin system
+/// module map files:
+///
+/// 1. The use of 'requires excluded' to make headers non-modular, which
+/// should really be mapped to 'textual' now that we have this feature. We
+/// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
+/// true. Later, this bit will be used to map all the headers inside this
+/// module to 'textual'.
+///
+/// This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
+///
+/// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement
+/// was never correct and causes issues now that we check it, so drop it.
+static bool shouldAddRequirement(Module *M, StringRef Feature,
+ bool &IsRequiresExcludedHack) {
+ static const StringRef DarwinCExcluded[] = {"Darwin", "C", "excluded"};
+ static const StringRef TclPrivate[] = {"Tcl", "Private"};
+ static const StringRef IOKitAVC[] = {"IOKit", "avc"};
+
+ if (Feature == "excluded" && (M->fullModuleNameIs(DarwinCExcluded) ||
+ M->fullModuleNameIs(TclPrivate))) {
+ IsRequiresExcludedHack = true;
+ return false;
+ } else if (Feature == "cplusplus" && M->fullModuleNameIs(IOKitAVC)) {
+ return false;
+ }
+
+ return true;
+}
+
/// \brief Parse a requires declaration.
///
/// requires-declaration:
@@ -1605,9 +1672,18 @@ void ModuleMapParser::parseRequiresDecl() {
std::string Feature = Tok.getString();
consumeToken();
- // Add this feature.
- ActiveModule->addRequirement(Feature, RequiredState,
- Map.LangOpts, *Map.Target);
+ bool IsRequiresExcludedHack = false;
+ bool ShouldAddRequirement =
+ shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
+
+ if (IsRequiresExcludedHack)
+ UsesRequiresExcludedHack.insert(ActiveModule);
+
+ if (ShouldAddRequirement) {
+ // Add this feature.
+ ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
+ *Map.Target);
+ }
if (!Tok.is(MMToken::Comma))
break;
@@ -1657,9 +1733,16 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
consumeToken();
}
}
+
if (LeadingToken == MMToken::TextualKeyword)
Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
+ if (UsesRequiresExcludedHack.count(ActiveModule)) {
+ // Mark this header 'textual' (see doc comment for
+ // Module::UsesRequiresExcludedHack).
+ Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
+ }
+
if (LeadingToken != MMToken::HeaderKeyword) {
if (!Tok.is(MMToken::HeaderKeyword)) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
@@ -1797,6 +1880,11 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
}
}
+static int compareModuleHeaders(const Module::Header *A,
+ const Module::Header *B) {
+ return A->NameAsWritten.compare(B->NameAsWritten);
+}
+
/// \brief Parse an umbrella directory declaration.
///
/// umbrella-dir-declaration:
@@ -1838,14 +1926,38 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
HadError = true;
return;
}
-
+
+ if (UsesRequiresExcludedHack.count(ActiveModule)) {
+ // Mark this header 'textual' (see doc comment for
+ // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
+ // directory is relatively expensive, in practice this only applies to the
+ // uncommonly used Tcl module on Darwin platforms.
+ std::error_code EC;
+ SmallVector<Module::Header, 6> Headers;
+ for (llvm::sys::fs::recursive_directory_iterator I(Dir->getName(), EC), E;
+ I != E && !EC; I.increment(EC)) {
+ if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) {
+
+ Module::Header Header = {I->path(), FE};
+ Headers.push_back(std::move(Header));
+ }
+ }
+
+ // Sort header paths so that the pcm doesn't depend on iteration order.
+ llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
+
+ for (auto &Header : Headers)
+ Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
+ return;
+ }
+
if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
<< OwningModule->getFullModuleName();
HadError = true;
return;
- }
-
+ }
+
// Record this umbrella directory.
Map.setUmbrellaDir(ActiveModule, Dir, DirName);
}
@@ -2335,9 +2447,14 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
// Parse this module map file.
Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts);
+ SourceLocation Start = L.getSourceLocation();
ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
BuiltinIncludeDir, IsSystem);
bool Result = Parser.parseModuleMapFile();
ParsedModuleMap[File] = Result;
+
+ // Notify callbacks that we parsed it.
+ for (const auto &Cb : Callbacks)
+ Cb->moduleMapFileRead(Start, *File, IsSystem);
return Result;
}
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
index ce64538..c02a0cb 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
@@ -611,6 +611,8 @@ const FileEntry *Preprocessor::LookupFile(
SmallVectorImpl<char> *RelativePath,
ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache) {
+ Module *RequestingModule = getModuleForLocation(FilenameLoc);
+
// If the header lookup mechanism may be relative to the current inclusion
// stack, record the parent #includes.
SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 16>
@@ -648,8 +650,7 @@ const FileEntry *Preprocessor::LookupFile(
for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
IncludeStackInfo &ISEntry = IncludeMacroStack[e - i - 1];
if (IsFileLexer(ISEntry))
- if ((FileEnt = SourceMgr.getFileEntryForID(
- ISEntry.ThePPLexer->getFileID())))
+ if ((FileEnt = ISEntry.ThePPLexer->getFileEntry()))
Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
}
}
@@ -664,8 +665,8 @@ const FileEntry *Preprocessor::LookupFile(
const DirectoryLookup *TmpFromDir = nullptr;
while (const FileEntry *FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, TmpFromDir, TmpCurDir,
- Includers, SearchPath, RelativePath, SuggestedModule,
- SkipCache)) {
+ Includers, SearchPath, RelativePath, RequestingModule,
+ SuggestedModule, SkipCache)) {
// Keep looking as if this file did a #include_next.
TmpFromDir = TmpCurDir;
++TmpFromDir;
@@ -681,11 +682,11 @@ const FileEntry *Preprocessor::LookupFile(
// Do a standard file entry lookup.
const FileEntry *FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath,
- RelativePath, SuggestedModule, SkipCache);
+ RelativePath, RequestingModule, SuggestedModule, SkipCache);
if (FE) {
if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
- getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE);
+ RequestingModule, FilenameLoc, Filename, FE);
return FE;
}
@@ -694,13 +695,14 @@ const FileEntry *Preprocessor::LookupFile(
// to one of the headers on the #include stack. Walk the list of the current
// headers on the #include stack and pass them to HeaderInfo.
if (IsFileLexer()) {
- if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) {
+ if ((CurFileEnt = CurPPLexer->getFileEntry())) {
if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt,
SearchPath, RelativePath,
+ RequestingModule,
SuggestedModule))) {
if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
- getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE);
+ RequestingModule, FilenameLoc, Filename, FE);
return FE;
}
}
@@ -709,14 +711,13 @@ const FileEntry *Preprocessor::LookupFile(
for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
IncludeStackInfo &ISEntry = IncludeMacroStack[e-i-1];
if (IsFileLexer(ISEntry)) {
- if ((CurFileEnt =
- SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID()))) {
+ if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) {
if ((FE = HeaderInfo.LookupSubframeworkHeader(
Filename, CurFileEnt, SearchPath, RelativePath,
- SuggestedModule))) {
+ RequestingModule, SuggestedModule))) {
if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
- getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE);
+ RequestingModule, FilenameLoc, Filename, FE);
return FE;
}
}
@@ -1674,6 +1675,29 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
getLangOpts().CurrentModule &&
SuggestedModule.getModule()->getTopLevelModuleName() !=
getLangOpts().ImplementationOfModule) {
+
+ // If this include corresponds to a module but that module is
+ // unavailable, diagnose the situation and bail out.
+ if (!SuggestedModule.getModule()->isAvailable()) {
+ clang::Module::Requirement Requirement;
+ clang::Module::UnresolvedHeaderDirective MissingHeader;
+ Module *M = SuggestedModule.getModule();
+ // Identify the cause.
+ (void)M->isAvailable(getLangOpts(), getTargetInfo(), Requirement,
+ MissingHeader);
+ if (MissingHeader.FileNameLoc.isValid()) {
+ Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing)
+ << MissingHeader.IsUmbrella << MissingHeader.FileName;
+ } else {
+ Diag(M->DefinitionLoc, diag::err_module_unavailable)
+ << M->getFullModuleName() << Requirement.second << Requirement.first;
+ }
+ Diag(FilenameTok.getLocation(),
+ diag::note_implicit_top_level_module_import_here)
+ << M->getTopLevelModuleName();
+ return;
+ }
+
// Compute the module access path corresponding to this module.
// FIXME: Should we have a second loadModule() overload to avoid this
// extra lookup step?
@@ -1776,7 +1800,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
if (IncludePos.isMacroID())
IncludePos = SourceMgr.getExpansionRange(IncludePos).second;
FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter);
- assert(!FID.isInvalid() && "Expected valid file ID");
+ assert(FID.isValid() && "Expected valid file ID");
// If all is good, enter the new file!
if (EnterSourceFile(FID, CurDir, FilenameTok.getLocation()))
@@ -1925,7 +1949,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) {
// Add the __VA_ARGS__ identifier as an argument.
Arguments.push_back(Ident__VA_ARGS__);
MI->setIsC99Varargs();
- MI->setArgumentList(&Arguments[0], Arguments.size(), BP);
+ MI->setArgumentList(Arguments, BP);
return false;
case tok::eod: // #define X(
Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
@@ -1959,7 +1983,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) {
Diag(Tok, diag::err_pp_expected_comma_in_arg_list);
return true;
case tok::r_paren: // #define X(A)
- MI->setArgumentList(&Arguments[0], Arguments.size(), BP);
+ MI->setArgumentList(Arguments, BP);
return false;
case tok::comma: // #define X(A,
break;
@@ -1975,7 +1999,7 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) {
}
MI->setIsGNUVarargs();
- MI->setArgumentList(&Arguments[0], Arguments.size(), BP);
+ MI->setArgumentList(Arguments, BP);
return false;
}
}
@@ -2019,13 +2043,9 @@ static bool isConfigurationPattern(Token &MacroName, MacroInfo *MI,
}
// #define inline
- if (MacroName.isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static,
- tok::kw_const) &&
- MI->getNumTokens() == 0) {
- return true;
- }
-
- return false;
+ return MacroName.isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static,
+ tok::kw_const) &&
+ MI->getNumTokens() == 0;
}
/// HandleDefineDirective - Implements \#define. This consumes the entire macro
@@ -2240,6 +2260,30 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok,
// Finally, if this identifier already had a macro defined for it, verify that
// the macro bodies are identical, and issue diagnostics if they are not.
if (const MacroInfo *OtherMI=getMacroInfo(MacroNameTok.getIdentifierInfo())) {
+ // In Objective-C, ignore attempts to directly redefine the builtin
+ // definitions of the ownership qualifiers. It's still possible to
+ // #undef them.
+ auto isObjCProtectedMacro = [](const IdentifierInfo *II) -> bool {
+ return II->isStr("__strong") ||
+ II->isStr("__weak") ||
+ II->isStr("__unsafe_unretained") ||
+ II->isStr("__autoreleasing");
+ };
+ if (getLangOpts().ObjC1 &&
+ SourceMgr.getFileID(OtherMI->getDefinitionLoc())
+ == getPredefinesFileID() &&
+ isObjCProtectedMacro(MacroNameTok.getIdentifierInfo())) {
+ // Warn if it changes the tokens.
+ if ((!getDiagnostics().getSuppressSystemWarnings() ||
+ !SourceMgr.isInSystemHeader(DefineTok.getLocation())) &&
+ !MI->isIdenticalTo(*OtherMI, *this,
+ /*Syntactic=*/LangOpts.MicrosoftExt)) {
+ Diag(MI->getDefinitionLoc(), diag::warn_pp_objc_macro_redef_ignored);
+ }
+ assert(!OtherMI->isWarnIfUnused());
+ return;
+ }
+
// It is very common for system headers to have tons of macro redefinitions
// and for warnings to be disabled in system headers. If this is the case,
// then don't bother calling MacroInfo::isIdenticalTo.
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp
index 4451302..c40598c 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPExpressions.cpp
@@ -42,7 +42,7 @@ public:
unsigned getBitWidth() const { return Val.getBitWidth(); }
bool isUnsigned() const { return Val.isUnsigned(); }
- const SourceRange &getRange() const { return Range; }
+ SourceRange getRange() const { return Range; }
void setRange(SourceLocation L) { Range.setBegin(L); Range.setEnd(L); }
void setRange(SourceLocation B, SourceLocation E) {
@@ -549,12 +549,12 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
// value was negative, warn about it.
if (ValueLive && Res.isUnsigned()) {
if (!LHS.isUnsigned() && LHS.Val.isNegative())
- PP.Diag(OpLoc, diag::warn_pp_convert_lhs_to_positive)
+ PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 0
<< LHS.Val.toString(10, true) + " to " +
LHS.Val.toString(10, false)
<< LHS.getRange() << RHS.getRange();
if (!RHS.isUnsigned() && RHS.Val.isNegative())
- PP.Diag(OpLoc, diag::warn_pp_convert_rhs_to_positive)
+ PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 1
<< RHS.Val.toString(10, true) + " to " +
RHS.Val.toString(10, false)
<< LHS.getRange() << RHS.getRange();
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
index c231e18..2f09841 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp
@@ -18,6 +18,7 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PTHManager.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -120,7 +121,7 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
CurSubmodule = nullptr;
if (CurLexerKind != CLK_LexAfterModuleImport)
CurLexerKind = CLK_Lexer;
-
+
// Notify the client, if desired, that we are in a new source file.
if (Callbacks && !CurLexer->Is_PragmaLexer) {
SrcMgr::CharacteristicKind FileType =
@@ -300,8 +301,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
if (const IdentifierInfo *ControllingMacro =
CurPPLexer->MIOpt.GetControllingMacroAtEndOfFile()) {
// Okay, this has a controlling macro, remember in HeaderFileInfo.
- if (const FileEntry *FE =
- SourceMgr.getFileEntryForID(CurPPLexer->getFileID())) {
+ if (const FileEntry *FE = CurPPLexer->getFileEntry()) {
HeaderInfo.SetFileControllingMacro(FE, ControllingMacro);
if (MacroInfo *MI =
getMacroInfo(const_cast<IdentifierInfo*>(ControllingMacro))) {
@@ -561,7 +561,6 @@ void Preprocessor::RemoveTopOfLexerStack() {
void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) {
assert(CurTokenLexer && !CurPPLexer &&
"Pasted comment can only be formed from macro");
-
// We handle this by scanning for the closest real lexer, switching it to
// raw mode and preprocessor mode. This will cause it to return \n as an
// explicit EOD token.
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
index 64ce8c9..18348df 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
@@ -145,8 +145,12 @@ void Preprocessor::updateModuleMacroInfo(const IdentifierInfo *II,
NumHiddenOverrides[O] = -1;
// Collect all macros that are not overridden by a visible macro.
- llvm::SmallVector<ModuleMacro *, 16> Worklist(Leaf->second.begin(),
- Leaf->second.end());
+ llvm::SmallVector<ModuleMacro *, 16> Worklist;
+ for (auto *LeafMM : Leaf->second) {
+ assert(LeafMM->getNumOverridingMacros() == 0 && "leaf macro overridden");
+ if (NumHiddenOverrides.lookup(LeafMM) == 0)
+ Worklist.push_back(LeafMM);
+ }
while (!Worklist.empty()) {
auto *MM = Worklist.pop_back_val();
if (CurSubmoduleState->VisibleModules.isVisible(MM->getOwningModule())) {
@@ -593,9 +597,7 @@ static bool CheckMatchedBrackets(const SmallVectorImpl<Token> &Tokens) {
Brackets.pop_back();
}
}
- if (!Brackets.empty())
- return false;
- return true;
+ return Brackets.empty();
}
/// GenerateNewArgTokens - Returns true if OldTokens can be converted to a new
@@ -867,7 +869,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
DiagnosticBuilder DB =
Diag(MacroName,
diag::note_init_list_at_beginning_of_macro_argument);
- for (const SourceRange &Range : InitLists)
+ for (SourceRange Range : InitLists)
DB << Range;
}
return nullptr;
@@ -876,7 +878,7 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
return nullptr;
DiagnosticBuilder DB = Diag(MacroName, diag::note_suggest_parens_for_macro);
- for (const SourceRange &ParenLocation : ParenHints) {
+ for (SourceRange ParenLocation : ParenHints) {
DB << FixItHint::CreateInsertion(ParenLocation.getBegin(), "(");
DB << FixItHint::CreateInsertion(ParenLocation.getEnd(), ")");
}
@@ -1057,6 +1059,9 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("attribute_availability", true)
.Case("attribute_availability_with_message", true)
.Case("attribute_availability_app_extension", true)
+ .Case("attribute_availability_with_version_underscores", true)
+ .Case("attribute_availability_tvos", true)
+ .Case("attribute_availability_watchos", true)
.Case("attribute_cf_returns_not_retained", true)
.Case("attribute_cf_returns_retained", true)
.Case("attribute_cf_returns_on_parameters", true)
@@ -1075,7 +1080,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("blocks", LangOpts.Blocks)
.Case("c_thread_safety_attributes", true)
.Case("cxx_exceptions", LangOpts.CXXExceptions)
- .Case("cxx_rtti", LangOpts.RTTI)
+ .Case("cxx_rtti", LangOpts.RTTI && LangOpts.RTTIData)
.Case("enumerator_attributes", true)
.Case("nullability", true)
.Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory))
@@ -1084,7 +1089,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
// Objective-C features
.Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
.Case("objc_arc", LangOpts.ObjCAutoRefCount)
- .Case("objc_arc_weak", LangOpts.ObjCARCWeak)
+ .Case("objc_arc_weak", LangOpts.ObjCWeak)
.Case("objc_default_synthesize_properties", LangOpts.ObjC2)
.Case("objc_fixed_enum", LangOpts.ObjC2)
.Case("objc_instancetype", LangOpts.ObjC2)
@@ -1629,16 +1634,23 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Value = FeatureII->getTokenID() == tok::identifier;
else if (II == Ident__has_builtin) {
// Check for a builtin is trivial.
- Value = FeatureII->getBuiltinID() != 0;
+ if (FeatureII->getBuiltinID() != 0) {
+ Value = true;
+ } else {
+ StringRef Feature = FeatureII->getName();
+ Value = llvm::StringSwitch<bool>(Feature)
+ .Case("__make_integer_seq", getLangOpts().CPlusPlus)
+ .Default(false);
+ }
} else if (II == Ident__has_attribute)
Value = hasAttribute(AttrSyntax::GNU, nullptr, FeatureII,
- getTargetInfo().getTriple(), getLangOpts());
+ getTargetInfo(), getLangOpts());
else if (II == Ident__has_cpp_attribute)
Value = hasAttribute(AttrSyntax::CXX, ScopeII, FeatureII,
- getTargetInfo().getTriple(), getLangOpts());
+ getTargetInfo(), getLangOpts());
else if (II == Ident__has_declspec)
Value = hasAttribute(AttrSyntax::Declspec, nullptr, FeatureII,
- getTargetInfo().getTriple(), getLangOpts());
+ getTargetInfo(), getLangOpts());
else if (II == Ident__has_extension)
Value = HasExtension(*this, FeatureII);
else {
diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
index 5eb6655..afb41a2 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
@@ -38,7 +38,7 @@ PragmaHandler::~PragmaHandler() {
// EmptyPragmaHandler Implementation.
//===----------------------------------------------------------------------===//
-EmptyPragmaHandler::EmptyPragmaHandler() {}
+EmptyPragmaHandler::EmptyPragmaHandler(StringRef Name) : PragmaHandler(Name) {}
void EmptyPragmaHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
@@ -191,9 +191,13 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
Lex(Tok);
if (!tok::isStringLiteral(Tok.getKind())) {
Diag(PragmaLoc, diag::err__Pragma_malformed);
- // Skip this token, and the ')', if present.
+ // Skip bad tokens, and the ')', if present.
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::eof))
Lex(Tok);
+ while (Tok.isNot(tok::r_paren) &&
+ !Tok.isAtStartOfLine() &&
+ Tok.isNot(tok::eof))
+ Lex(Tok);
if (Tok.is(tok::r_paren))
Lex(Tok);
return _PragmaLexing.failed();
@@ -872,6 +876,22 @@ struct PragmaDebugHandler : public PragmaHandler {
Crasher.setKind(tok::annot_pragma_parser_crash);
Crasher.setAnnotationRange(SourceRange(Tok.getLocation()));
PP.EnterToken(Crasher);
+ } else if (II->isStr("dump")) {
+ Token Identifier;
+ PP.LexUnexpandedToken(Identifier);
+ if (auto *DumpII = Identifier.getIdentifierInfo()) {
+ Token DumpAnnot;
+ DumpAnnot.startToken();
+ DumpAnnot.setKind(tok::annot_pragma_dump);
+ DumpAnnot.setAnnotationRange(
+ SourceRange(Tok.getLocation(), Identifier.getLocation()));
+ DumpAnnot.setAnnotationValue(DumpII);
+ PP.DiscardUntilEndOfDirective();
+ PP.EnterToken(DumpAnnot);
+ } else {
+ PP.Diag(Identifier, diag::warn_pragma_debug_missing_argument)
+ << II->getName();
+ }
} else if (II->isStr("llvm_fatal_error")) {
llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
} else if (II->isStr("llvm_unreachable")) {
@@ -883,7 +903,8 @@ struct PragmaDebugHandler : public PragmaHandler {
if (MacroII)
PP.dumpMacroInfo(MacroII);
else
- PP.Diag(MacroName, diag::warn_pragma_diagnostic_invalid);
+ PP.Diag(MacroName, diag::warn_pragma_debug_missing_argument)
+ << II->getName();
} else if (II->isStr("overflow_stack")) {
DebugOverflowStack();
} else if (II->isStr("handle_crash")) {
diff --git a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
index a423041..32e6de6 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PreprocessingRecord.cpp
@@ -66,7 +66,7 @@ PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
SourceManager &SM) {
- assert(!FID.isInvalid());
+ assert(FID.isValid());
if (!PPE)
return false;
diff --git a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
index e2db638..142d9ce 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp
@@ -38,6 +38,7 @@
#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Pragma.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/PreprocessorOptions.h"
@@ -62,20 +63,19 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts,
IdentifierInfoLookup *IILookup, bool OwnsHeaders,
TranslationUnitKind TUKind)
: PPOpts(PPOpts), Diags(&diags), LangOpts(opts), Target(nullptr),
- FileMgr(Headers.getFileMgr()), SourceMgr(SM),
- ScratchBuf(new ScratchBuffer(SourceMgr)),HeaderInfo(Headers),
+ AuxTarget(nullptr), FileMgr(Headers.getFileMgr()), SourceMgr(SM),
+ ScratchBuf(new ScratchBuffer(SourceMgr)), HeaderInfo(Headers),
TheModuleLoader(TheModuleLoader), ExternalSource(nullptr),
Identifiers(opts, IILookup),
PragmaHandlers(new PragmaNamespace(StringRef())),
- IncrementalProcessing(false), TUKind(TUKind),
- CodeComplete(nullptr), CodeCompletionFile(nullptr),
- CodeCompletionOffset(0), LastTokenWasAt(false),
- ModuleImportExpectsIdentifier(false), CodeCompletionReached(0),
- MainFileDir(nullptr), SkipMainFilePreamble(0, true), CurPPLexer(nullptr),
- CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurSubmodule(nullptr),
- Callbacks(nullptr), CurSubmoduleState(&NullSubmoduleState),
- MacroArgCache(nullptr), Record(nullptr),
- MIChainHead(nullptr), DeserialMIChainHead(nullptr) {
+ IncrementalProcessing(false), TUKind(TUKind), CodeComplete(nullptr),
+ CodeCompletionFile(nullptr), CodeCompletionOffset(0),
+ LastTokenWasAt(false), ModuleImportExpectsIdentifier(false),
+ CodeCompletionReached(0), MainFileDir(nullptr),
+ SkipMainFilePreamble(0, true), CurPPLexer(nullptr), CurDirLookup(nullptr),
+ CurLexerKind(CLK_Lexer), CurSubmodule(nullptr), Callbacks(nullptr),
+ CurSubmoduleState(&NullSubmoduleState), MacroArgCache(nullptr),
+ Record(nullptr), MIChainHead(nullptr), DeserialMIChainHead(nullptr) {
OwnsHeaderSearch = OwnsHeaders;
CounterValue = 0; // __COUNTER__ starts at 0.
@@ -170,13 +170,18 @@ Preprocessor::~Preprocessor() {
delete &HeaderInfo;
}
-void Preprocessor::Initialize(const TargetInfo &Target) {
+void Preprocessor::Initialize(const TargetInfo &Target,
+ const TargetInfo *AuxTarget) {
assert((!this->Target || this->Target == &Target) &&
"Invalid override of target information");
this->Target = &Target;
-
+
+ assert((!this->AuxTarget || this->AuxTarget == AuxTarget) &&
+ "Invalid override of aux target information.");
+ this->AuxTarget = AuxTarget;
+
// Initialize information about built-ins.
- BuiltinInfo.InitializeTarget(Target);
+ BuiltinInfo.InitializeTarget(Target, AuxTarget);
HeaderInfo.setTarget(Target);
}
@@ -515,7 +520,7 @@ void Preprocessor::EnterMainSourceFile() {
llvm::MemoryBuffer::getMemBufferCopy(Predefines, "<built-in>");
assert(SB && "Cannot create predefined source buffer");
FileID FID = SourceMgr.createFileID(std::move(SB));
- assert(!FID.isInvalid() && "Could not create FileID for predefines?");
+ assert(FID.isValid() && "Could not create FileID for predefines?");
setPredefinesFileID(FID);
// Start parsing the predefines.
@@ -712,7 +717,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
}
void Preprocessor::Lex(Token &Result) {
- // We loop here until a lex function retuns a token; this avoids recursion.
+ // We loop here until a lex function returns a token; this avoids recursion.
bool ReturnedToken;
do {
switch (CurLexerKind) {
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
index e7512fa..c429669 100644
--- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
@@ -624,21 +624,22 @@ bool TokenLexer::PasteTokens(Token &Tok) {
// error. This occurs with "x ## +" and other stuff. Return with Tok
// unmodified and with RHS as the next token to lex.
if (isInvalid) {
+ // Explicitly convert the token location to have proper expansion
+ // information so that the user knows where it came from.
+ SourceManager &SM = PP.getSourceManager();
+ SourceLocation Loc =
+ SM.createExpansionLoc(PasteOpLoc, ExpandLocStart, ExpandLocEnd, 2);
+
// Test for the Microsoft extension of /##/ turning into // here on the
// error path.
if (PP.getLangOpts().MicrosoftExt && Tok.is(tok::slash) &&
RHS.is(tok::slash)) {
- HandleMicrosoftCommentPaste(Tok);
+ HandleMicrosoftCommentPaste(Tok, Loc);
return true;
}
// Do not emit the error when preprocessing assembler code.
if (!PP.getLangOpts().AsmPreprocessor) {
- // Explicitly convert the token location to have proper expansion
- // information so that the user knows where it came from.
- SourceManager &SM = PP.getSourceManager();
- SourceLocation Loc =
- SM.createExpansionLoc(PasteOpLoc, ExpandLocStart, ExpandLocEnd, 2);
// If we're in microsoft extensions mode, downgrade this from a hard
// error to an extension that defaults to an error. This allows
// disabling it.
@@ -719,7 +720,9 @@ bool TokenLexer::isParsingPreprocessorDirective() const {
/// macro, other active macros, and anything left on the current physical
/// source line of the expanded buffer. Handle this by returning the
/// first token on the next line.
-void TokenLexer::HandleMicrosoftCommentPaste(Token &Tok) {
+void TokenLexer::HandleMicrosoftCommentPaste(Token &Tok, SourceLocation OpLoc) {
+ PP.Diag(OpLoc, diag::ext_comment_paste_microsoft);
+
// We 'comment out' the rest of this macro by just ignoring the rest of the
// tokens that have not been lexed yet, if any.
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp
index 6727afc..ccf9479 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp
@@ -30,6 +30,21 @@ using namespace clang;
namespace {
+/// Resets LLVM's pretty stack state so that stack traces are printed correctly
+/// when there are nested CrashRecoveryContexts and the inner one recovers from
+/// a crash.
+class ResetStackCleanup
+ : public llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup,
+ const void> {
+public:
+ ResetStackCleanup(llvm::CrashRecoveryContext *Context, const void *Top)
+ : llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, const void>(
+ Context, Top) {}
+ void recoverResources() override {
+ llvm::RestorePrettyStackState(resource);
+ }
+};
+
/// If a crash happens while the parser is active, an entry is printed for it.
class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
const Parser &P;
@@ -113,6 +128,8 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
new Parser(S.getPreprocessor(), S, SkipFunctionBodies));
Parser &P = *ParseOP.get();
+ llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup>
+ CleanupPrettyStack(llvm::SavePrettyStackState());
PrettyStackTraceParserEntry CrashInfo(P);
// Recover resources if we crash before exiting this method.
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
index ab1f97d..e536644 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -67,8 +67,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
SourceLocation KWEndLoc = Tok.getEndLoc().getLocWithOffset(-1);
if (TryConsumeToken(tok::kw_delete, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
- ? diag::warn_cxx98_compat_deleted_function
- : diag::ext_deleted_function);
+ ? diag::warn_cxx98_compat_defaulted_deleted_function
+ : diag::ext_defaulted_deleted_function)
+ << 1 /* deleted */;
Actions.SetDeclDeleted(FnD, KWLoc);
Delete = true;
if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
@@ -76,8 +77,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
}
} else if (TryConsumeToken(tok::kw_default, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
- ? diag::warn_cxx98_compat_defaulted_function
- : diag::ext_defaulted_function);
+ ? diag::warn_cxx98_compat_defaulted_deleted_function
+ : diag::ext_defaulted_deleted_function)
+ << 0 /* defaulted */;
Actions.SetDeclDefaulted(FnD, KWLoc);
if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
DeclAsFunction->setRangeEnd(KWEndLoc);
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
index 45878b9..c64b97d 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
@@ -1,4 +1,4 @@
-//===--- ParseDecl.cpp - Declaration Parsing ------------------------------===//
+//===--- ParseDecl.cpp - Declaration Parsing --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -24,9 +24,11 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
+#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -67,7 +69,6 @@ TypeResult Parser::ParseTypeName(SourceRange *Range,
return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
-
/// isAttributeLateParsed - Return true if the attribute has arguments that
/// require late parsing.
static bool isAttributeLateParsed(const IdentifierInfo &II) {
@@ -387,7 +388,7 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
// If the attribute isn't known, we will not attempt to parse any
// arguments.
if (!hasAttribute(AttrSyntax::Declspec, nullptr, AttrName,
- getTargetInfo().getTriple(), getLangOpts())) {
+ getTargetInfo(), getLangOpts())) {
// Eat the left paren, then skip to the ending right paren.
ConsumeParen();
SkipUntil(tok::r_paren);
@@ -532,9 +533,7 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
/// extended-decl-modifier extended-decl-modifier-seq
void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
SourceLocation *End) {
- assert((getLangOpts().MicrosoftExt || getLangOpts().Borland ||
- getLangOpts().CUDA) &&
- "Incorrect language options for parsing __declspec");
+ assert(getLangOpts().DeclSpecKeyword && "__declspec keyword is not enabled");
assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
while (Tok.is(tok::kw___declspec)) {
@@ -1155,7 +1154,6 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) {
Class.TagOrTemplate);
}
-
/// \brief Parse all attributes in LAs, and attach them to Decl D.
void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
bool EnterScope, bool OnDefinition) {
@@ -1170,7 +1168,6 @@ void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
LAs.clear();
}
-
/// \brief Finish parsing an attribute for which parsing was delayed.
/// This will be called at the end of parsing a class declaration
/// for each LateParsedAttribute. We consume the saved tokens and
@@ -1468,15 +1465,13 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
if (getLangOpts().CPlusPlus && NextToken().is(tok::kw_namespace)) {
ProhibitAttributes(attrs);
SourceLocation InlineLoc = ConsumeToken();
- SingleDecl = ParseNamespace(Context, DeclEnd, InlineLoc);
- break;
+ return ParseNamespace(Context, DeclEnd, InlineLoc);
}
return ParseSimpleDeclaration(Context, DeclEnd, attrs,
true);
case tok::kw_namespace:
ProhibitAttributes(attrs);
- SingleDecl = ParseNamespace(Context, DeclEnd);
- break;
+ return ParseNamespace(Context, DeclEnd);
case tok::kw_using:
SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(),
DeclEnd, attrs, &OwnedType);
@@ -1979,8 +1974,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
// Recover as if it were an explicit specialization.
TemplateParameterLists FakedParamLists;
FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
- 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr,
- 0, LAngleLoc));
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None,
+ LAngleLoc));
ThisDecl =
Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D);
@@ -2161,7 +2156,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
DS.ClearStorageClassSpecs();
}
- // Issue diagnostic and remove function specfier if present.
+ // Issue diagnostic and remove function specifier if present.
if (Specs & DeclSpec::PQ_FunctionSpecifier) {
if (DS.isInlineSpecified())
Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
@@ -2203,7 +2198,6 @@ static bool isValidAfterIdentifierInDeclarator(const Token &T) {
tok::colon);
}
-
/// ParseImplicitInt - This method is called when we have an non-typename
/// identifier in a declspec (which normally terminates the decl spec) when
/// the declspec has no type specifier. In this case, the declspec is either
@@ -2621,8 +2615,6 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
/// [OpenCL] '__kernel'
/// 'friend': [C++ dcl.friend]
/// 'constexpr': [C++0x dcl.constexpr]
-
-///
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS,
@@ -2647,6 +2639,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
const char *PrevSpec = nullptr;
unsigned DiagID = 0;
+ // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
+ // implementation for VS2013 uses _Atomic as an identifier for one of the
+ // classes in <atomic>.
+ //
+ // A typedef declaration containing _Atomic<...> is among the places where
+ // the class is used. If we are currently parsing such a declaration, treat
+ // the token as an identifier.
+ if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) &&
+ DS.getStorageClassSpec() == clang::DeclSpec::SCS_typedef &&
+ !DS.hasTypeSpecifier() && GetLookAheadToken(1).is(tok::less))
+ Tok.setKind(tok::identifier);
+
SourceLocation Loc = Tok.getLocation();
switch (Tok.getKind()) {
@@ -2665,7 +2669,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// If this is not a declaration specifier token, we're done reading decl
// specifiers. First verify that DeclSpec's are consistent.
- DS.Finish(Diags, PP, Policy);
+ DS.Finish(Actions, Policy);
return;
case tok::l_square:
@@ -2780,8 +2784,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// arguments. Complain, then parse it as a type as the user
// intended.
Diag(TemplateId->TemplateNameLoc,
- diag::err_out_of_line_template_id_names_constructor)
- << TemplateId->Name;
+ diag::err_out_of_line_template_id_type_names_constructor)
+ << TemplateId->Name << 0 /* template name */;
}
DS.getTypeSpecScope() = SS;
@@ -2826,8 +2830,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// looked at the declarator, and the user probably meant this
// to be a type. Complain that it isn't supposed to be treated
// as a type, then proceed to parse it as a type.
- Diag(Next.getLocation(), diag::err_out_of_line_type_names_constructor)
- << Next.getIdentifierInfo();
+ Diag(Next.getLocation(),
+ diag::err_out_of_line_template_id_type_names_constructor)
+ << Next.getIdentifierInfo() << 1 /* type */;
}
ParsedType TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(),
@@ -3133,6 +3138,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
PrevSpec, DiagID, Policy);
isStorageClass = true;
break;
+ case tok::kw___auto_type:
+ Diag(Tok, diag::ext_auto_type);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto_type, Loc, PrevSpec,
+ DiagID, Policy);
+ break;
case tok::kw_register:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
PrevSpec, DiagID, Policy);
@@ -3316,6 +3326,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw___bool:
isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
break;
+ case tok::kw_pipe:
+ if (!getLangOpts().OpenCL || (getLangOpts().OpenCLVersion < 200)) {
+ // OpenCL 2.0 defined this keyword. OpenCL 1.2 and earlier should
+ // support the "pipe" word as identifier.
+ Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
+ goto DoneWithDeclSpec;
+ }
+ isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy);
+ break;
case tok::kw___unknown_anytype:
isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc,
PrevSpec, DiagID, Policy);
@@ -3577,7 +3596,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
SmallVector<Decl *, 32> FieldDecls;
// While we still have something to read, read the declarations in the struct.
- while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
+ while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
+ Tok.isNot(tok::eof)) {
// Each iteration of this loop reads one struct-declaration.
// Check for extraneous top-level semicolon.
@@ -4390,6 +4410,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
switch (Tok.getKind()) {
default: return false;
+ case tok::kw_pipe:
+ return getLangOpts().OpenCL && (getLangOpts().OpenCLVersion >= 200);
+
case tok::identifier: // foo::bar
// Unfortunate hack to support "Class.factoryMethod" notation.
if (getLangOpts().ObjC1 && NextToken().is(tok::period))
@@ -4434,6 +4457,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw___private_extern__:
case tok::kw_static:
case tok::kw_auto:
+ case tok::kw___auto_type:
case tok::kw_register:
case tok::kw___thread:
case tok::kw_thread_local:
@@ -4807,7 +4831,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs,
DoneWithTypeQuals:
// If this is not a type-qualifier token, we're done reading type
// qualifiers. First verify that DeclSpec's are consistent.
- DS.Finish(Diags, PP, Actions.getASTContext().getPrintingPolicy());
+ DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
if (EndLoc.isValid())
DS.SetRangeEnd(EndLoc);
return;
@@ -4822,7 +4846,6 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs,
}
}
-
/// ParseDeclarator - Parse and verify a newly-initialized declarator.
///
void Parser::ParseDeclarator(Declarator &D) {
@@ -4836,6 +4859,9 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
if (Kind == tok::star || Kind == tok::caret)
return true;
+ if ((Kind == tok::kw_pipe) && Lang.OpenCL && (Lang.OpenCLVersion >= 200))
+ return true;
+
if (!Lang.CPlusPlus)
return false;
@@ -4854,6 +4880,17 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
return false;
}
+// Indicates whether the given declarator is a pipe declarator.
+static bool isPipeDeclerator(const Declarator &D) {
+ const unsigned NumTypes = D.getNumTypeObjects();
+
+ for (unsigned Idx = 0; Idx != NumTypes; ++Idx)
+ if (DeclaratorChunk::Pipe == D.getTypeObject(Idx).Kind)
+ return true;
+
+ return false;
+}
+
/// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator
/// is parsed by the function passed to it. Pass null, and the direct-declarator
/// isn't parsed at all, making this function effectively parse the C++
@@ -4930,6 +4967,15 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
}
tok::TokenKind Kind = Tok.getKind();
+
+ if (D.getDeclSpec().isTypeSpecPipe() && !isPipeDeclerator(D)) {
+ DeclSpec &DS = D.getMutableDeclSpec();
+
+ D.AddTypeInfo(
+ DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()),
+ DS.getAttributes(), SourceLocation());
+ }
+
// Not a pointer, C++ reference, or block.
if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) {
if (DirectDeclParser)
@@ -5187,6 +5233,15 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
}
goto PastIdentifier;
}
+
+ if (D.getCXXScopeSpec().isNotEmpty()) {
+ // We have a scope specifier but no following unqualified-id.
+ Diag(PP.getLocForEndOfToken(D.getCXXScopeSpec().getEndLoc()),
+ diag::err_expected_unqualified_id)
+ << /*C++*/1;
+ D.SetIdentifier(nullptr, Tok.getLocation());
+ goto PastIdentifier;
+ }
} else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
assert(!getLangOpts().CPlusPlus &&
"There's a C++-specific check for tok::identifier above");
@@ -5470,7 +5525,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
SmallVector<ParsedType, 2> DynamicExceptions;
SmallVector<SourceRange, 2> DynamicExceptionRanges;
ExprResult NoexceptExpr;
- CachedTokens *ExceptionSpecTokens = 0;
+ CachedTokens *ExceptionSpecTokens = nullptr;
ParsedAttributes FnAttrs(AttrFactory);
TypeResult TrailingReturnType;
@@ -5608,7 +5663,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
VolatileQualifierLoc,
RestrictQualifierLoc,
/*MutableLoc=*/SourceLocation(),
- ESpecType, ESpecRange.getBegin(),
+ ESpecType, ESpecRange,
DynamicExceptions.data(),
DynamicExceptionRanges.data(),
DynamicExceptions.size(),
@@ -6072,6 +6127,7 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
case DeclaratorChunk::Reference:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
NeedParens = true;
break;
case DeclaratorChunk::Array:
@@ -6227,7 +6283,6 @@ void Parser::ParseAtomicSpecifier(DeclSpec &DS) {
Diag(StartLoc, DiagID) << PrevSpec;
}
-
/// TryAltiVecVectorTokenOutOfLine - Out of line body that should only be called
/// from TryAltiVecVectorToken.
bool Parser::TryAltiVecVectorTokenOutOfLine() {
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
index e347d4e..3f22ad4 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1,4 +1,4 @@
-//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -----------------------===//
+//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -26,6 +26,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallString.h"
+
using namespace clang;
/// ParseNamespace - We know that the current token is a namespace keyword. This
@@ -54,9 +55,9 @@ using namespace clang;
/// namespace-alias-definition: [C++ 7.3.2: namespace.alias]
/// 'namespace' identifier '=' qualified-namespace-specifier ';'
///
-Decl *Parser::ParseNamespace(unsigned Context,
- SourceLocation &DeclEnd,
- SourceLocation InlineLoc) {
+Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context,
+ SourceLocation &DeclEnd,
+ SourceLocation InlineLoc) {
assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'.
ObjCDeclContextSwitch ObjCDC(*this);
@@ -64,7 +65,7 @@ Decl *Parser::ParseNamespace(unsigned Context,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteNamespaceDecl(getCurScope());
cutOffParsing();
- return nullptr;
+ return DeclGroupPtrTy();
}
SourceLocation IdentLoc;
@@ -108,16 +109,16 @@ Decl *Parser::ParseNamespace(unsigned Context,
Diag(Tok, diag::err_expected) << tok::identifier;
// Skip to end of the definition and eat the ';'.
SkipUntil(tok::semi);
- return nullptr;
+ return DeclGroupPtrTy();
}
if (attrLoc.isValid())
Diag(attrLoc, diag::err_unexpected_namespace_attributes_alias);
if (InlineLoc.isValid())
Diag(InlineLoc, diag::err_inline_namespace_alias)
<< FixItHint::CreateRemoval(InlineLoc);
- return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
- }
-
+ Decl *NSAlias = ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
+ return Actions.ConvertDeclToDeclGroup(NSAlias);
+}
BalancedDelimiterTracker T(*this, tok::l_brace);
if (T.consumeOpen()) {
@@ -125,7 +126,7 @@ Decl *Parser::ParseNamespace(unsigned Context,
Diag(Tok, diag::err_expected) << tok::l_brace;
else
Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
- return nullptr;
+ return DeclGroupPtrTy();
}
if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() ||
@@ -133,7 +134,7 @@ Decl *Parser::ParseNamespace(unsigned Context,
getCurScope()->getFnParent()) {
Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope);
SkipUntil(tok::r_brace);
- return nullptr;
+ return DeclGroupPtrTy();
}
if (ExtraIdent.empty()) {
@@ -180,10 +181,11 @@ Decl *Parser::ParseNamespace(unsigned Context,
// Enter a scope for the namespace.
ParseScope NamespaceScope(this, Scope::DeclScope);
+ UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
Decl *NamespcDecl =
Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, NamespaceLoc,
IdentLoc, Ident, T.getOpenLocation(),
- attrs.getList());
+ attrs.getList(), ImplicitUsingDirectiveDecl);
PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc,
"parsing namespace");
@@ -198,8 +200,9 @@ Decl *Parser::ParseNamespace(unsigned Context,
DeclEnd = T.getCloseLocation();
Actions.ActOnFinishNamespaceDef(NamespcDecl, DeclEnd);
-
- return NamespcDecl;
+
+ return Actions.ConvertDeclToDeclGroup(NamespcDecl,
+ ImplicitUsingDirectiveDecl);
}
/// ParseInnerNamespace - Parse the contents of a namespace.
@@ -210,7 +213,8 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
ParsedAttributes &attrs,
BalancedDelimiterTracker &Tracker) {
if (index == Ident.size()) {
- while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
+ while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
+ Tok.isNot(tok::eof)) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
MaybeParseMicrosoftAttributes(attrs);
@@ -228,17 +232,19 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
// FIXME: Preserve the source information through to the AST rather than
// desugaring it here.
ParseScope NamespaceScope(this, Scope::DeclScope);
+ UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
Decl *NamespcDecl =
Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(),
NamespaceLoc[index], IdentLoc[index],
Ident[index], Tracker.getOpenLocation(),
- attrs.getList());
+ attrs.getList(), ImplicitUsingDirectiveDecl);
+ assert(!ImplicitUsingDirectiveDecl &&
+ "nested namespace definition cannot define anonymous namespace");
ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc,
attrs, Tracker);
NamespaceScope.Exit();
-
Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation());
}
@@ -279,8 +285,8 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name))
SkipUntil(tok::semi);
- return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc, Alias,
- SS, IdentLoc, Ident);
+ return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc,
+ Alias, SS, IdentLoc, Ident);
}
/// ParseLinkage - We know that the current token is a string_literal
@@ -393,8 +399,8 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
// Template parameters are always an error here.
if (TemplateInfo.Kind) {
SourceRange R = TemplateInfo.getSourceRange();
- Diag(UsingLoc, diag::err_templated_using_directive)
- << R << FixItHint::CreateRemoval(R);
+ Diag(UsingLoc, diag::err_templated_using_directive_declaration)
+ << 0 /* directive */ << R << FixItHint::CreateRemoval(R);
}
return ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs);
@@ -546,7 +552,8 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
} else if (ParseUnqualifiedId(
SS, /*EnteringContext=*/false,
/*AllowDestructorName=*/true,
- /*AllowConstructorName=*/NextToken().isNot(tok::equal),
+ /*AllowConstructorName=*/!(Tok.is(tok::identifier) &&
+ NextToken().is(tok::equal)),
ParsedType(), TemplateKWLoc, Name)) {
SkipUntil(tok::semi);
return nullptr;
@@ -643,8 +650,8 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
// template <...> using id = type;
if (TemplateInfo.Kind && !IsAliasDecl) {
SourceRange R = TemplateInfo.getSourceRange();
- Diag(UsingLoc, diag::err_templated_using_declaration)
- << R << FixItHint::CreateRemoval(R);
+ Diag(UsingLoc, diag::err_templated_using_directive_declaration)
+ << 1 /* declaration */ << R << FixItHint::CreateRemoval(R);
// Unfortunately, we have to bail out instead of recovering by
// ignoring the parameters, just in case the nested name specifier
@@ -1307,6 +1314,35 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// allow libstdc++ 4.2 and libc++ to work properly.
TryKeywordIdentFallback(true);
+ struct PreserveAtomicIdentifierInfoRAII {
+ PreserveAtomicIdentifierInfoRAII(Token &Tok, bool Enabled)
+ : AtomicII(nullptr) {
+ if (!Enabled)
+ return;
+ assert(Tok.is(tok::kw__Atomic));
+ AtomicII = Tok.getIdentifierInfo();
+ AtomicII->revertTokenIDToIdentifier();
+ Tok.setKind(tok::identifier);
+ }
+ ~PreserveAtomicIdentifierInfoRAII() {
+ if (!AtomicII)
+ return;
+ AtomicII->revertIdentifierToTokenID(tok::kw__Atomic);
+ }
+ IdentifierInfo *AtomicII;
+ };
+
+ // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
+ // implementation for VS2013 uses _Atomic as an identifier for one of the
+ // classes in <atomic>. When we are parsing 'struct _Atomic', don't consider
+ // '_Atomic' to be a keyword. We are careful to undo this so that clang can
+ // use '_Atomic' in its own header files.
+ bool ShouldChangeAtomicToIdentifier = getLangOpts().MSVCCompat &&
+ Tok.is(tok::kw__Atomic) &&
+ TagType == DeclSpec::TST_struct;
+ PreserveAtomicIdentifierInfoRAII AtomicTokenGuard(
+ Tok, ShouldChangeAtomicToIdentifier);
+
// Parse the (optional) nested-name-specifier.
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLangOpts().CPlusPlus) {
@@ -1626,8 +1662,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// "template<>", so that we treat this construct as a class
// template specialization.
FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
- 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr,
- 0, LAngleLoc));
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None,
+ LAngleLoc));
TemplateParams = &FakedParamLists;
}
}
@@ -1808,7 +1844,7 @@ void Parser::ParseBaseClause(Decl *ClassDecl) {
}
// Attach the base specifiers
- Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo.data(), BaseInfo.size());
+ Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo);
}
/// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is
@@ -1858,6 +1894,15 @@ BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
CheckMisplacedCXX11Attribute(Attributes, StartLoc);
// Parse the class-name.
+
+ // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
+ // implementation for VS2013 uses _Atomic as an identifier for one of the
+ // classes in <atomic>. Treat '_Atomic' to be an identifier when we are
+ // parsing the class-name for a base specifier.
+ if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) &&
+ NextToken().is(tok::less))
+ Tok.setKind(tok::identifier);
+
SourceLocation EndLocation;
SourceLocation BaseLoc;
TypeResult BaseType = ParseBaseTypeSpecifier(BaseLoc, EndLocation);
@@ -1928,7 +1973,7 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
// Stash the exception-specification tokens in the late-pased method.
LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;
- FTI.ExceptionSpecTokens = 0;
+ FTI.ExceptionSpecTokens = nullptr;
// Push tokens for each parameter. Those that do not have
// defaults will be NULL.
@@ -2195,8 +2240,9 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
/// constant-initializer:
/// '=' constant-expression
///
-void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
- AttributeList *AccessAttrs,
+Parser::DeclGroupPtrTy
+Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
+ AttributeList *AccessAttrs,
const ParsedTemplateInfo &TemplateInfo,
ParsingDeclRAIIObject *TemplateDiags) {
if (Tok.is(tok::at)) {
@@ -2207,7 +2253,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ConsumeToken();
SkipUntil(tok::r_brace, StopAtSemi);
- return;
+ return DeclGroupPtrTy();
}
// Turn on colon protection early, while parsing declspec, although there is
@@ -2241,7 +2287,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (SS.isInvalid()) {
SkipUntil(tok::semi);
- return;
+ return DeclGroupPtrTy();
}
// Try to parse an unqualified-id.
@@ -2250,24 +2296,21 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (ParseUnqualifiedId(SS, false, true, true, ParsedType(),
TemplateKWLoc, Name)) {
SkipUntil(tok::semi);
- return;
+ return DeclGroupPtrTy();
}
// TODO: recover from mistakenly-qualified operator declarations.
if (ExpectAndConsume(tok::semi, diag::err_expected_after,
"access declaration")) {
SkipUntil(tok::semi);
- return;
+ return DeclGroupPtrTy();
}
- Actions.ActOnUsingDeclaration(getCurScope(), AS,
- /* HasUsingKeyword */ false,
- SourceLocation(),
- SS, Name,
- /* AttrList */ nullptr,
- /* HasTypenameKeyword */ false,
- SourceLocation());
- return;
+ return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration(
+ getCurScope(), AS,
+ /* HasUsingKeyword */ false, SourceLocation(), SS, Name,
+ /* AttrList */ nullptr,
+ /* HasTypenameKeyword */ false, SourceLocation())));
}
}
@@ -2276,17 +2319,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (!TemplateInfo.Kind &&
Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
SourceLocation DeclEnd;
- ParseStaticAssertDeclaration(DeclEnd);
- return;
+ return DeclGroupPtrTy::make(
+ DeclGroupRef(ParseStaticAssertDeclaration(DeclEnd)));
}
if (Tok.is(tok::kw_template)) {
assert(!TemplateInfo.TemplateParams &&
"Nested template improperly parsed?");
SourceLocation DeclEnd;
- ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd,
- AS, AccessAttrs);
- return;
+ return DeclGroupPtrTy::make(
+ DeclGroupRef(ParseDeclarationStartingWithTemplate(
+ Declarator::MemberContext, DeclEnd, AS, AccessAttrs)));
}
// Handle: member-declaration ::= '__extension__' member-declaration
@@ -2318,13 +2361,12 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (Tok.is(tok::kw_namespace)) {
Diag(UsingLoc, diag::err_using_namespace_in_class);
SkipUntil(tok::semi, StopBeforeMatch);
- } else {
- SourceLocation DeclEnd;
- // Otherwise, it must be a using-declaration or an alias-declaration.
- ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo,
- UsingLoc, DeclEnd, AS);
+ return DeclGroupPtrTy();
}
- return;
+ SourceLocation DeclEnd;
+ // Otherwise, it must be a using-declaration or an alias-declaration.
+ return DeclGroupPtrTy::make(DeclGroupRef(ParseUsingDeclaration(
+ Declarator::MemberContext, TemplateInfo, UsingLoc, DeclEnd, AS)));
}
// Hold late-parsed attributes so we can attach a Decl to them later.
@@ -2349,7 +2391,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate &&
DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_class,
&CommonLateParsedAttrs))
- return;
+ return DeclGroupPtrTy();
MultiTemplateParamsArg TemplateParams(
TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data()
@@ -2363,7 +2405,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
Decl *TheDecl =
Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS, TemplateParams);
DS.complete(TheDecl);
- return;
+ return DeclGroupPtrTy::make(DeclGroupRef(TheDecl));
}
ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
@@ -2404,7 +2446,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (ParseCXXMemberDeclaratorBeforeInitializer(
DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) {
TryConsumeToken(tok::semi);
- return;
+ return DeclGroupPtrTy();
}
// Check for a member function definition.
@@ -2453,7 +2495,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Consume the optional ';'
TryConsumeToken(tok::semi);
- return;
+ return DeclGroupPtrTy();
}
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
@@ -2482,7 +2524,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (Tok.is(tok::semi))
ConsumeExtraSemi(AfterMemberFunctionDefinition);
- return;
+ return DeclGroupPtrTy::make(DeclGroupRef(FunDecl));
}
}
@@ -2656,10 +2698,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
// If we stopped at a ';', eat it.
TryConsumeToken(tok::semi);
- return;
+ return DeclGroupPtrTy();
}
- Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
+ return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
}
/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer.
@@ -2777,6 +2819,100 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,
MaybeParseGNUAttributes(Attrs);
}
+Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
+ AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs,
+ DeclSpec::TST TagType, Decl *TagDecl) {
+ if (getLangOpts().MicrosoftExt &&
+ Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) {
+ ParseMicrosoftIfExistsClassDeclaration(TagType, AS);
+ return DeclGroupPtrTy();
+ }
+
+ // Check for extraneous top-level semicolon.
+ if (Tok.is(tok::semi)) {
+ ConsumeExtraSemi(InsideStruct, TagType);
+ return DeclGroupPtrTy();
+ }
+
+ if (Tok.is(tok::annot_pragma_vis)) {
+ HandlePragmaVisibility();
+ return DeclGroupPtrTy();
+ }
+
+ if (Tok.is(tok::annot_pragma_pack)) {
+ HandlePragmaPack();
+ return DeclGroupPtrTy();
+ }
+
+ if (Tok.is(tok::annot_pragma_align)) {
+ HandlePragmaAlign();
+ return DeclGroupPtrTy();
+ }
+
+ if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) {
+ HandlePragmaMSPointersToMembers();
+ return DeclGroupPtrTy();
+ }
+
+ if (Tok.is(tok::annot_pragma_ms_pragma)) {
+ HandlePragmaMSPragma();
+ return DeclGroupPtrTy();
+ }
+
+ if (Tok.is(tok::annot_pragma_ms_vtordisp)) {
+ HandlePragmaMSVtorDisp();
+ return DeclGroupPtrTy();
+ }
+
+ // If we see a namespace here, a close brace was missing somewhere.
+ if (Tok.is(tok::kw_namespace)) {
+ DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));
+ return DeclGroupPtrTy();
+ }
+
+ AccessSpecifier NewAS = getAccessSpecifierIfPresent();
+ if (NewAS != AS_none) {
+ // Current token is a C++ access specifier.
+ AS = NewAS;
+ SourceLocation ASLoc = Tok.getLocation();
+ unsigned TokLength = Tok.getLength();
+ ConsumeToken();
+ AccessAttrs.clear();
+ MaybeParseGNUAttributes(AccessAttrs);
+
+ SourceLocation EndLoc;
+ if (TryConsumeToken(tok::colon, EndLoc)) {
+ } else if (TryConsumeToken(tok::semi, EndLoc)) {
+ Diag(EndLoc, diag::err_expected)
+ << tok::colon << FixItHint::CreateReplacement(EndLoc, ":");
+ } else {
+ EndLoc = ASLoc.getLocWithOffset(TokLength);
+ Diag(EndLoc, diag::err_expected)
+ << tok::colon << FixItHint::CreateInsertion(EndLoc, ":");
+ }
+
+ // The Microsoft extension __interface does not permit non-public
+ // access specifiers.
+ if (TagType == DeclSpec::TST_interface && AS != AS_public) {
+ Diag(ASLoc, diag::err_access_specifier_interface) << (AS == AS_protected);
+ }
+
+ if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc,
+ AccessAttrs.getList())) {
+ // found another attribute than only annotations
+ AccessAttrs.clear();
+ }
+
+ return DeclGroupPtrTy();
+ }
+
+ if (Tok.is(tok::annot_pragma_openmp))
+ return ParseOpenMPDeclarativeDirective();
+
+ // Parse all the comma separated declarators.
+ return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList());
+}
+
/// ParseCXXMemberSpecification - Parse the class definition.
///
/// member-specification:
@@ -2934,102 +3070,16 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
CurAS = AS_private;
else
CurAS = AS_public;
- ParsedAttributes AccessAttrs(AttrFactory);
+ ParsedAttributesWithRange AccessAttrs(AttrFactory);
if (TagDecl) {
// While we still have something to read, read the member-declarations.
- while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
+ while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
+ Tok.isNot(tok::eof)) {
// Each iteration of this loop reads one member-declaration.
-
- if (getLangOpts().MicrosoftExt && Tok.isOneOf(tok::kw___if_exists,
- tok::kw___if_not_exists)) {
- ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
- continue;
- }
-
- // Check for extraneous top-level semicolon.
- if (Tok.is(tok::semi)) {
- ConsumeExtraSemi(InsideStruct, TagType);
- continue;
- }
-
- if (Tok.is(tok::annot_pragma_vis)) {
- HandlePragmaVisibility();
- continue;
- }
-
- if (Tok.is(tok::annot_pragma_pack)) {
- HandlePragmaPack();
- continue;
- }
-
- if (Tok.is(tok::annot_pragma_align)) {
- HandlePragmaAlign();
- continue;
- }
-
- if (Tok.is(tok::annot_pragma_openmp)) {
- ParseOpenMPDeclarativeDirective();
- continue;
- }
-
- if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) {
- HandlePragmaMSPointersToMembers();
- continue;
- }
-
- if (Tok.is(tok::annot_pragma_ms_pragma)) {
- HandlePragmaMSPragma();
- continue;
- }
-
- // If we see a namespace here, a close brace was missing somewhere.
- if (Tok.is(tok::kw_namespace)) {
- DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));
- break;
- }
-
- AccessSpecifier AS = getAccessSpecifierIfPresent();
- if (AS != AS_none) {
- // Current token is a C++ access specifier.
- CurAS = AS;
- SourceLocation ASLoc = Tok.getLocation();
- unsigned TokLength = Tok.getLength();
- ConsumeToken();
- AccessAttrs.clear();
- MaybeParseGNUAttributes(AccessAttrs);
-
- SourceLocation EndLoc;
- if (TryConsumeToken(tok::colon, EndLoc)) {
- } else if (TryConsumeToken(tok::semi, EndLoc)) {
- Diag(EndLoc, diag::err_expected)
- << tok::colon << FixItHint::CreateReplacement(EndLoc, ":");
- } else {
- EndLoc = ASLoc.getLocWithOffset(TokLength);
- Diag(EndLoc, diag::err_expected)
- << tok::colon << FixItHint::CreateInsertion(EndLoc, ":");
- }
-
- // The Microsoft extension __interface does not permit non-public
- // access specifiers.
- if (TagType == DeclSpec::TST_interface && CurAS != AS_public) {
- Diag(ASLoc, diag::err_access_specifier_interface)
- << (CurAS == AS_protected);
- }
-
- if (Actions.ActOnAccessSpecifier(AS, ASLoc, EndLoc,
- AccessAttrs.getList())) {
- // found another attribute than only annotations
- AccessAttrs.clear();
- }
-
- continue;
- }
-
- // Parse all the comma separated declarators.
- ParseCXXClassMemberDeclaration(CurAS, AccessAttrs.getList());
+ ParseCXXClassMemberDeclarationWithPragmas(
+ CurAS, AccessAttrs, static_cast<DeclSpec::TST>(TagType), TagDecl);
}
-
T.consumeClose();
} else {
SkipUntil(tok::r_brace);
@@ -3068,7 +3118,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
// We've finished parsing everything, including default argument
// initializers.
- Actions.ActOnFinishCXXMemberDefaultArgs(TagDecl);
+ Actions.ActOnFinishCXXNonNestedClass(TagDecl);
}
if (TagDecl)
@@ -3279,7 +3329,7 @@ Parser::tryParseExceptionSpecification(bool Delayed,
ExprResult &NoexceptExpr,
CachedTokens *&ExceptionSpecTokens) {
ExceptionSpecificationType Result = EST_None;
- ExceptionSpecTokens = 0;
+ ExceptionSpecTokens = nullptr;
// Handle delayed parsing of exception-specifications.
if (Delayed) {
@@ -3296,7 +3346,7 @@ Parser::tryParseExceptionSpecification(bool Delayed,
// If this is a bare 'noexcept', we're done.
if (IsNoexcept) {
Diag(Tok, diag::warn_cxx98_compat_noexcept_decl);
- NoexceptExpr = 0;
+ NoexceptExpr = nullptr;
return EST_BasicNoexcept;
}
@@ -3313,7 +3363,8 @@ Parser::tryParseExceptionSpecification(bool Delayed,
ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens,
/*StopAtSemi=*/true,
/*ConsumeFinalToken=*/true);
- SpecificationRange.setEnd(Tok.getLocation());
+ SpecificationRange.setEnd(ExceptionSpecTokens->back().getLocation());
+
return EST_Unparsed;
}
@@ -3379,7 +3430,7 @@ Parser::tryParseExceptionSpecification(bool Delayed,
}
static void diagnoseDynamicExceptionSpecification(
- Parser &P, const SourceRange &Range, bool IsNoexcept) {
+ Parser &P, SourceRange Range, bool IsNoexcept) {
if (P.getLangOpts().CPlusPlus11) {
const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)";
P.Diag(Range.getBegin(), diag::warn_exception_spec_deprecated) << Range;
@@ -3577,9 +3628,8 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
case AttributeList::AT_CarriesDependency:
case AttributeList::AT_Deprecated:
case AttributeList::AT_FallThrough:
- case AttributeList::AT_CXX11NoReturn: {
+ case AttributeList::AT_CXX11NoReturn:
return true;
- }
default:
return false;
@@ -3612,7 +3662,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
// If the attribute isn't known, we will not attempt to parse any
// arguments.
if (!hasAttribute(AttrSyntax::CXX, ScopeName, AttrName,
- getTargetInfo().getTriple(), getLangOpts())) {
+ getTargetInfo(), getLangOpts())) {
// Eat the left paren, then skip to the ending right paren.
ConsumeParen();
SkipUntil(tok::r_paren);
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
index b866798..1fd98c1 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp
@@ -163,6 +163,8 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) {
if (Tok.is(tok::kw_throw))
return ParseThrowExpression();
+ if (Tok.is(tok::kw_co_yield))
+ return ParseCoyieldExpression();
ExprResult LHS = ParseCastExpression(/*isUnaryExpression=*/false,
/*isAddressOfOperand=*/false,
@@ -522,6 +524,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
/// postfix-expression
/// '++' unary-expression
/// '--' unary-expression
+/// [Coro] 'co_await' cast-expression
/// unary-operator cast-expression
/// 'sizeof' unary-expression
/// 'sizeof' '(' type-name ')'
@@ -1041,6 +1044,14 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return Res;
}
+ case tok::kw_co_await: { // unary-expression: 'co_await' cast-expression
+ SourceLocation CoawaitLoc = ConsumeToken();
+ Res = ParseCastExpression(false);
+ if (!Res.isInvalid())
+ Res = Actions.ActOnCoawaitExpr(getCurScope(), CoawaitLoc, Res.get());
+ return Res;
+ }
+
case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU]
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
@@ -1323,8 +1334,23 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ExprError();
}
+ // Check to see whether Res is a function designator only. If it is and we
+ // are compiling for OpenCL, we need to return an error as this implies
+ // that the address of the function is being taken, which is illegal in CL.
+
// These can be followed by postfix-expr pieces.
- return ParsePostfixExpressionSuffix(Res);
+ Res = ParsePostfixExpressionSuffix(Res);
+ if (getLangOpts().OpenCL)
+ if (Expr *PostfixExpr = Res.get()) {
+ QualType Ty = PostfixExpr->getType();
+ if (!Ty.isNull() && Ty->isFunctionType()) {
+ Diag(PostfixExpr->getExprLoc(),
+ diag::err_opencl_taking_function_address_parser);
+ return ExprError();
+ }
+ }
+
+ return Res;
}
/// \brief Once the leading part of a postfix-expression is parsed, this
@@ -1396,21 +1422,42 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
Loc = T.getOpenLocation();
- ExprResult Idx;
+ ExprResult Idx, Length;
+ SourceLocation ColonLoc;
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
Idx = ParseBraceInitializer();
+ } else if (getLangOpts().OpenMP) {
+ ColonProtectionRAIIObject RAII(*this);
+ // Parse [: or [ expr or [ expr :
+ if (!Tok.is(tok::colon)) {
+ // [ expr
+ Idx = ParseExpression();
+ }
+ if (Tok.is(tok::colon)) {
+ // Consume ':'
+ ColonLoc = ConsumeToken();
+ if (Tok.isNot(tok::r_square))
+ Length = ParseExpression();
+ }
} else
Idx = ParseExpression();
SourceLocation RLoc = Tok.getLocation();
- if (!LHS.isInvalid() && !Idx.isInvalid() && Tok.is(tok::r_square)) {
- LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc,
- Idx.get(), RLoc);
+ if (!LHS.isInvalid() && !Idx.isInvalid() && !Length.isInvalid() &&
+ Tok.is(tok::r_square)) {
+ if (ColonLoc.isValid()) {
+ LHS = Actions.ActOnOMPArraySectionExpr(LHS.get(), Loc, Idx.get(),
+ ColonLoc, Length.get(), RLoc);
+ } else {
+ LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc,
+ Idx.get(), RLoc);
+ }
} else {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
(void)Actions.CorrectDelayedTyposInExpr(Idx);
+ (void)Actions.CorrectDelayedTyposInExpr(Length);
LHS = ExprError();
Idx = ExprError();
}
@@ -1965,7 +2012,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
} else {
PT.consumeClose();
Res = Actions.ActOnBuiltinOffsetOf(getCurScope(), StartLoc, TypeLoc,
- Ty.get(), &Comps[0], Comps.size(),
+ Ty.get(), Comps,
PT.getCloseLocation());
}
break;
@@ -2747,7 +2794,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
/*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc,
EST_None,
- /*ESpecLoc=*/NoLoc,
+ /*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
index c1dafe9..f8938ba 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
@@ -841,6 +841,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// Parse capture.
LambdaCaptureKind Kind = LCK_ByCopy;
+ LambdaCaptureInitKind InitKind = LambdaCaptureInitKind::NoInit;
SourceLocation Loc;
IdentifierInfo *Id = nullptr;
SourceLocation EllipsisLoc;
@@ -878,6 +879,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
BalancedDelimiterTracker Parens(*this, tok::l_paren);
Parens.consumeOpen();
+ InitKind = LambdaCaptureInitKind::DirectInit;
+
ExprVector Exprs;
CommaLocsTy Commas;
if (SkippedInits) {
@@ -898,14 +901,13 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// to save the necessary state, and restore it later.
EnterExpressionEvaluationContext EC(Actions,
Sema::PotentiallyEvaluated);
- bool HadEquals = TryConsumeToken(tok::equal);
+
+ if (TryConsumeToken(tok::equal))
+ InitKind = LambdaCaptureInitKind::CopyInit;
+ else
+ InitKind = LambdaCaptureInitKind::ListInit;
if (!SkippedInits) {
- // Warn on constructs that will change meaning when we implement N3922
- if (!HadEquals && Tok.is(tok::l_brace)) {
- Diag(Tok, diag::warn_init_capture_direct_list_init)
- << FixItHint::CreateInsertion(Tok.getLocation(), "=");
- }
Init = ParseInitializer();
} else if (Tok.is(tok::l_brace)) {
BalancedDelimiterTracker Braces(*this, tok::l_brace);
@@ -993,19 +995,19 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// If x was not const, the second use would require 'L' to capture, and
// that would be an error.
- ParsedType InitCaptureParsedType;
+ ParsedType InitCaptureType;
if (Init.isUsable()) {
// Get the pointer and store it in an lvalue, so we can use it as an
// out argument.
Expr *InitExpr = Init.get();
// This performs any lvalue-to-rvalue conversions if necessary, which
// can affect what gets captured in the containing decl-context.
- QualType InitCaptureType = Actions.performLambdaInitCaptureInitialization(
- Loc, Kind == LCK_ByRef, Id, InitExpr);
+ InitCaptureType = Actions.actOnLambdaInitCaptureInitialization(
+ Loc, Kind == LCK_ByRef, Id, InitKind, InitExpr);
Init = InitExpr;
- InitCaptureParsedType.set(InitCaptureType);
}
- Intro.addCapture(Kind, Loc, Id, EllipsisLoc, Init, InitCaptureParsedType);
+ Intro.addCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init,
+ InitCaptureType);
}
T.consumeClose();
@@ -1149,7 +1151,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
/*VolatileQualifierLoc=*/NoLoc,
/*RestrictQualifierLoc=*/NoLoc,
MutableLoc,
- ESpecType, ESpecRange.getBegin(),
+ ESpecType, ESpecRange,
DynamicExceptions.data(),
DynamicExceptionRanges.data(),
DynamicExceptions.size(),
@@ -1217,7 +1219,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
/*RestrictQualifierLoc=*/NoLoc,
MutableLoc,
EST_None,
- /*ESpecLoc=*/NoLoc,
+ /*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
@@ -1558,6 +1560,21 @@ ExprResult Parser::ParseThrowExpression() {
}
}
+/// \brief Parse the C++ Coroutines co_yield expression.
+///
+/// co_yield-expression:
+/// 'co_yield' assignment-expression[opt]
+ExprResult Parser::ParseCoyieldExpression() {
+ assert(Tok.is(tok::kw_co_yield) && "Not co_yield!");
+
+ SourceLocation Loc = ConsumeToken();
+ ExprResult Expr = Tok.is(tok::l_brace) ? ParseBraceInitializer()
+ : ParseAssignmentExpression();
+ if (!Expr.isInvalid())
+ Expr = Actions.ActOnCoyieldExpr(getCurScope(), Loc, Expr.get());
+ return Expr;
+}
+
/// ParseCXXThis - This handles the C++ 'this' pointer.
///
/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
@@ -1805,7 +1822,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
ConsumeToken();
- DS.Finish(Diags, PP, Policy);
+ DS.Finish(Actions, Policy);
return;
}
@@ -1861,12 +1878,12 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
case tok::annot_decltype:
case tok::kw_decltype:
DS.SetRangeEnd(ParseDecltypeSpecifier(DS));
- return DS.Finish(Diags, PP, Policy);
+ return DS.Finish(Actions, Policy);
// GNU typeof support.
case tok::kw_typeof:
ParseTypeofSpecifier(DS);
- DS.Finish(Diags, PP, Policy);
+ DS.Finish(Actions, Policy);
return;
}
if (Tok.is(tok::annot_typename))
@@ -1874,7 +1891,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
else
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken();
- DS.Finish(Diags, PP, Policy);
+ DS.Finish(Actions, Policy);
}
/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
@@ -1890,7 +1907,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
///
bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
ParseSpecifierQualifierList(DS, AS_none, DSC_type_specifier);
- DS.Finish(Diags, PP, Actions.getASTContext().getPrintingPolicy());
+ DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
return false;
}
@@ -2289,7 +2306,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
// This isn't a valid literal-operator-id, but we think we know
// what the user meant. Tell them what they should have written.
SmallString<32> Str;
- Str += "\"\" ";
+ Str += "\"\"";
Str += II->getName();
Diag(DiagLoc, DiagId) << FixItHint::CreateReplacement(
SourceRange(TokLocs.front(), TokLocs.back()), Str);
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
index ed60904..e72a1f6 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp
@@ -94,6 +94,28 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
return Actions.ConvertDeclToDeclGroup(SingleDecl);
}
+/// Class to handle popping type parameters when leaving the scope.
+class Parser::ObjCTypeParamListScope {
+ Sema &Actions;
+ Scope *S;
+ ObjCTypeParamList *Params;
+public:
+ ObjCTypeParamListScope(Sema &Actions, Scope *S)
+ : Actions(Actions), S(S), Params(nullptr) {}
+ ~ObjCTypeParamListScope() {
+ leave();
+ }
+ void enter(ObjCTypeParamList *P) {
+ assert(!Params);
+ Params = P;
+ }
+ void leave() {
+ if (Params)
+ Actions.popObjCTypeParamList(S, Params);
+ Params = nullptr;
+ }
+};
+
///
/// objc-class-declaration:
/// '@' 'class' objc-class-forward-decl (',' objc-class-forward-decl)* ';'
@@ -121,11 +143,8 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
// Parse the optional objc-type-parameter-list.
ObjCTypeParamList *TypeParams = nullptr;
- if (Tok.is(tok::less)) {
+ if (Tok.is(tok::less))
TypeParams = parseObjCTypeParamList();
- if (TypeParams)
- Actions.popObjCTypeParamList(getCurScope(), TypeParams);
- }
ClassTypeParams.push_back(TypeParams);
if (!TryConsumeToken(tok::comma))
break;
@@ -221,11 +240,10 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
SourceLocation LAngleLoc, EndProtoLoc;
SmallVector<IdentifierLocPair, 8> ProtocolIdents;
ObjCTypeParamList *typeParameterList = nullptr;
- if (Tok.is(tok::less)) {
- typeParameterList = parseObjCTypeParamListOrProtocolRefs(LAngleLoc,
- ProtocolIdents,
- EndProtoLoc);
- }
+ ObjCTypeParamListScope typeParamScope(Actions, getCurScope());
+ if (Tok.is(tok::less))
+ typeParameterList = parseObjCTypeParamListOrProtocolRefs(
+ typeParamScope, LAngleLoc, ProtocolIdents, EndProtoLoc);
if (Tok.is(tok::l_paren) &&
!isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category.
@@ -286,9 +304,6 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);
- if (typeParameterList)
- Actions.popObjCTypeParamList(getCurScope(), typeParameterList);
-
return CategoryType;
}
// Parse a class interface.
@@ -342,8 +357,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
}
Actions.FindProtocolDeclaration(/*WarnOnDeclarations=*/true,
/*ForObjCContainer=*/true,
- &ProtocolIdents[0], ProtocolIdents.size(),
- protocols);
+ ProtocolIdents, protocols);
}
} else if (protocols.empty() && Tok.is(tok::less) &&
ParseObjCProtocolReferences(protocols, protocolLocs, true, true,
@@ -371,9 +385,6 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);
- if (typeParameterList)
- Actions.popObjCTypeParamList(getCurScope(), typeParameterList);
-
return ClsType;
}
@@ -433,10 +444,9 @@ static void addContextSensitiveTypeNullability(Parser &P,
///
/// \param rAngleLoc The location of the ending '>'.
ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs(
- SourceLocation &lAngleLoc,
- SmallVectorImpl<IdentifierLocPair> &protocolIdents,
- SourceLocation &rAngleLoc,
- bool mayBeProtocolList) {
+ ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc,
+ SmallVectorImpl<IdentifierLocPair> &protocolIdents,
+ SourceLocation &rAngleLoc, bool mayBeProtocolList) {
assert(Tok.is(tok::less) && "Not at the beginning of a type parameter list");
// Within the type parameter list, don't treat '>' as an operator.
@@ -493,8 +503,7 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs(
if (Tok.is(tok::code_completion)) {
// FIXME: If these aren't protocol references, we'll need different
// completions.
- Actions.CodeCompleteObjCProtocolReferences(protocolIdents.data(),
- protocolIdents.size());
+ Actions.CodeCompleteObjCProtocolReferences(protocolIdents);
cutOffParsing();
// FIXME: Better recovery here?.
@@ -581,18 +590,19 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs(
makeProtocolIdentsIntoTypeParameters();
}
- // Form the type parameter list.
+ // Form the type parameter list and enter its scope.
ObjCTypeParamList *list = Actions.actOnObjCTypeParamList(
getCurScope(),
lAngleLoc,
typeParams,
rAngleLoc);
+ Scope.enter(list);
// Clear out the angle locations; they're used by the caller to indicate
// whether there are any protocol references.
lAngleLoc = SourceLocation();
rAngleLoc = SourceLocation();
- return list;
+ return invalid ? nullptr : list;
}
/// Parse an objc-type-parameter-list.
@@ -600,8 +610,10 @@ ObjCTypeParamList *Parser::parseObjCTypeParamList() {
SourceLocation lAngleLoc;
SmallVector<IdentifierLocPair, 1> protocolIdents;
SourceLocation rAngleLoc;
- return parseObjCTypeParamListOrProtocolRefs(lAngleLoc, protocolIdents,
- rAngleLoc,
+
+ ObjCTypeParamListScope Scope(Actions, getCurScope());
+ return parseObjCTypeParamListOrProtocolRefs(Scope, lAngleLoc, protocolIdents,
+ rAngleLoc,
/*mayBeProtocolList=*/false);
}
@@ -620,7 +632,6 @@ ObjCTypeParamList *Parser::parseObjCTypeParamList() {
void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
Decl *CDecl) {
SmallVector<Decl *, 32> allMethods;
- SmallVector<Decl *, 16> allProperties;
SmallVector<DeclGroupPtrTy, 8> allTUVariables;
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
@@ -776,12 +787,9 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
SetterSel = SelectorTable::constructSetterSelector(
PP.getIdentifierTable(), PP.getSelectorTable(),
FD.D.getIdentifier());
- bool isOverridingProperty = false;
Decl *Property = Actions.ActOnProperty(
getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel,
- &isOverridingProperty, MethodImplKind);
- if (!isOverridingProperty)
- allProperties.push_back(Property);
+ MethodImplKind);
FD.complete(Property);
};
@@ -903,7 +911,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
// getter/setter require extra treatment.
unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter :
- diag::err_objc_expected_equal_for_getter;
+ diag::err_objc_expected_equal_for_getter;
if (ExpectAndConsume(tok::equal, DiagID)) {
SkipUntil(tok::r_paren, StopAtSemi);
@@ -918,7 +926,6 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
return cutOffParsing();
}
-
SourceLocation SelLoc;
IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc);
@@ -1114,6 +1121,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
case tok::kw__Bool:
case tok::kw__Complex:
case tok::kw___alignof:
+ case tok::kw___auto_type:
IdentifierInfo *II = Tok.getIdentifierInfo();
SelectorLoc = ConsumeToken();
return II;
@@ -1557,8 +1565,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
while (1) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(),
- ProtocolIdents.size());
+ Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents);
cutOffParsing();
return true;
}
@@ -1584,8 +1591,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
// Convert the list of protocols identifiers into a list of protocol decls.
Actions.FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer,
- &ProtocolIdents[0], ProtocolIdents.size(),
- Protocols);
+ ProtocolIdents, Protocols);
return false;
}
@@ -1662,8 +1668,7 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers(
if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) {
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
} else {
- Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs.data(),
- identifierLocPairs.size());
+ Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs);
}
cutOffParsing();
return;
@@ -2015,7 +2020,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol.
IdentifierLocPair ProtoInfo(protocolName, nameLoc);
- return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
+ return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo,
attrs.getList());
}
@@ -2044,9 +2049,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol"))
return DeclGroupPtrTy();
- return Actions.ActOnForwardProtocolDeclaration(AtLoc,
- &ProtocolRefs[0],
- ProtocolRefs.size(),
+ return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs,
attrs.getList());
}
@@ -2114,8 +2117,9 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
SourceLocation lAngleLoc, rAngleLoc;
SmallVector<IdentifierLocPair, 8> protocolIdents;
SourceLocation diagLoc = Tok.getLocation();
- if (parseObjCTypeParamListOrProtocolRefs(lAngleLoc, protocolIdents,
- rAngleLoc)) {
+ ObjCTypeParamListScope typeParamScope(Actions, getCurScope());
+ if (parseObjCTypeParamListOrProtocolRefs(typeParamScope, lAngleLoc,
+ protocolIdents, rAngleLoc)) {
Diag(diagLoc, diag::err_objc_parameterized_implementation)
<< SourceRange(diagLoc, PrevTokLocation);
} else if (lAngleLoc.isValid()) {
@@ -2614,6 +2618,7 @@ void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
}
else if (Tok.is(tok::colon)) {
ConsumeToken();
+ // FIXME: This is wrong, due to C++11 braced initialization.
while (Tok.isNot(tok::l_brace)) {
ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
@@ -3279,8 +3284,7 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
AtStrings.push_back(Lit.get());
}
- return Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.data(),
- AtStrings.size());
+ return Actions.ParseObjCStringLiteral(AtLocs.data(), AtStrings);
}
/// ParseObjCBooleanLiteral -
@@ -3431,7 +3435,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
// Create the ObjCDictionaryLiteral.
return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc),
- Elements.data(), Elements.size());
+ Elements);
}
/// objc-encode-expression:
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
index 0113a31..a08db54 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
@@ -19,6 +19,7 @@
#include "clang/Parse/Parser.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/PointerIntPair.h"
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -32,15 +33,18 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
const OpenMPDirectiveKind F[][3] = {
{OMPD_unknown /*cancellation*/, OMPD_unknown /*point*/,
OMPD_cancellation_point},
+ {OMPD_target, OMPD_unknown /*data*/, OMPD_target_data},
{OMPD_for, OMPD_simd, OMPD_for_simd},
{OMPD_parallel, OMPD_for, OMPD_parallel_for},
{OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
- {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}};
+ {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
+ {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}};
auto Tok = P.getCurToken();
auto DKind =
Tok.isAnnotation()
? OMPD_unknown
: getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
+
bool TokenMatched = false;
for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
if (!Tok.isAnnotation() && DKind == OMPD_unknown) {
@@ -50,18 +54,24 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
} else {
TokenMatched = DKind == F[i][0] && DKind != OMPD_unknown;
}
+
if (TokenMatched) {
Tok = P.getPreprocessor().LookAhead(0);
+ auto TokenIsAnnotation = Tok.isAnnotation();
auto SDKind =
- Tok.isAnnotation()
+ TokenIsAnnotation
? OMPD_unknown
: getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
- if (!Tok.isAnnotation() && DKind == OMPD_unknown) {
+
+ if (!TokenIsAnnotation && SDKind == OMPD_unknown) {
TokenMatched =
- (i == 0) && !P.getPreprocessor().getSpelling(Tok).compare("point");
+ ((i == 0) &&
+ !P.getPreprocessor().getSpelling(Tok).compare("point")) ||
+ ((i == 1) && !P.getPreprocessor().getSpelling(Tok).compare("data"));
} else {
TokenMatched = SDKind == F[i][1] && SDKind != OMPD_unknown;
}
+
if (TokenMatched) {
P.ConsumeToken();
DKind = F[i][2];
@@ -127,6 +137,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
case OMPD_teams:
case OMPD_cancellation_point:
case OMPD_cancel:
+ case OMPD_target_data:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_distribute:
Diag(Tok, diag::err_omp_unexpected_directive)
<< getOpenMPDirectiveName(DKind);
break;
@@ -146,12 +160,13 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
/// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
-/// 'for simd' | 'parallel for simd' | 'target' | 'teams' | 'taskgroup'
-/// {clause}
+/// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
+/// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' {clause} |
+/// 'distribute'
/// annot_pragma_openmp_end
///
-StmtResult
-Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
+StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
+ AllowedContsructsKind Allowed) {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
ParenBraceBracketBalancer BalancerRAIIObj(*this);
SmallVector<Expr *, 5> Identifiers;
@@ -171,6 +186,10 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
switch (DKind) {
case OMPD_threadprivate:
+ if (Allowed != ACK_Any) {
+ Diag(Tok, diag::err_omp_immediate_directive)
+ << getOpenMPDirectiveName(DKind) << 0;
+ }
ConsumeToken();
if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
// The last seen token is annot_pragma_openmp_end - need to check for
@@ -198,9 +217,9 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
case OMPD_taskwait:
case OMPD_cancellation_point:
case OMPD_cancel:
- if (!StandAloneAllowed) {
+ if (Allowed == ACK_StatementsOpenMPNonStandalone) {
Diag(Tok, diag::err_omp_immediate_directive)
- << getOpenMPDirectiveName(DKind);
+ << getOpenMPDirectiveName(DKind) << 0;
}
HasAssociatedStatement = false;
// Fall through for further analysis.
@@ -221,7 +240,11 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
case OMPD_atomic:
case OMPD_target:
case OMPD_teams:
- case OMPD_taskgroup: {
+ case OMPD_taskgroup:
+ case OMPD_target_data:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_distribute: {
ConsumeToken();
// Parse directive name of the 'critical' directive if any.
if (DKind == OMPD_critical) {
@@ -276,8 +299,19 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
// Consume final annot_pragma_openmp_end.
ConsumeToken();
+ // OpenMP [2.13.8, ordered Construct, Syntax]
+ // If the depend clause is specified, the ordered construct is a stand-alone
+ // directive.
+ if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
+ if (Allowed == ACK_StatementsOpenMPNonStandalone) {
+ Diag(Loc, diag::err_omp_immediate_directive)
+ << getOpenMPDirectiveName(DKind) << 1
+ << getOpenMPClauseName(OMPC_depend);
+ }
+ HasAssociatedStatement = false;
+ }
+
StmtResult AssociatedStmt;
- bool CreateDirective = true;
if (HasAssociatedStatement) {
// The body is a block scope like in Lambdas and Blocks.
Sema::CompoundScopeRAII CompoundScope(Actions);
@@ -287,12 +321,10 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
AssociatedStmt = ParseStatement();
Actions.ActOnFinishOfCompoundStmt();
AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
- CreateDirective = AssociatedStmt.isUsable();
}
- if (CreateDirective)
- Directive = Actions.ActOnOpenMPExecutableDirective(
- DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
- EndLoc);
+ Directive = Actions.ActOnOpenMPExecutableDirective(
+ DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
+ EndLoc);
// Exit scope.
Actions.EndOpenMPDSABlock(Directive.get());
@@ -385,7 +417,10 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
/// lastprivate-clause | reduction-clause | proc_bind-clause |
/// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
/// mergeable-clause | flush-clause | read-clause | write-clause |
-/// update-clause | capture-clause | seq_cst-clause
+/// update-clause | capture-clause | seq_cst-clause | device-clause |
+/// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
+/// thread_limit-clause | priority-clause | grainsize-clause |
+/// nogroup-clause | num_tasks-clause | hint-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@@ -399,27 +434,49 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
}
switch (CKind) {
- case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
+ case OMPC_ordered:
+ case OMPC_device:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_num_tasks:
+ case OMPC_hint:
// OpenMP [2.5, Restrictions]
- // At most one if clause can appear on the directive.
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
// Only one safelen clause can appear on a simd directive.
+ // Only one simdlen clause can appear on a simd directive.
// Only one collapse clause can appear on a simd directive.
+ // OpenMP [2.9.1, target data construct, Restrictions]
+ // At most one device clause can appear on the directive.
// OpenMP [2.11.1, task Construct, Restrictions]
// At most one if clause can appear on the directive.
// At most one final clause can appear on the directive.
+ // OpenMP [teams Construct, Restrictions]
+ // At most one num_teams clause can appear on the directive.
+ // At most one thread_limit clause can appear on the directive.
+ // OpenMP [2.9.1, task Construct, Restrictions]
+ // At most one priority clause can appear on the directive.
+ // OpenMP [2.9.2, taskloop Construct, Restrictions]
+ // At most one grainsize clause can appear on the directive.
+ // OpenMP [2.9.2, taskloop Construct, Restrictions]
+ // At most one num_tasks clause can appear on the directive.
if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
- << getOpenMPClauseName(CKind);
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
- Clause = ParseOpenMPSingleExprClause(CKind);
+ if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
+ Clause = ParseOpenMPClause(CKind);
+ else
+ Clause = ParseOpenMPSingleExprClause(CKind);
break;
case OMPC_default:
case OMPC_proc_bind:
@@ -429,8 +486,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// OpenMP [2.5, parallel Construct, Restrictions]
// At most one proc_bind clause can appear on the directive.
if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
- << getOpenMPClauseName(CKind);
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
@@ -440,14 +497,14 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// OpenMP [2.7.1, Restrictions, p. 3]
// Only one schedule clause can appear on a loop directive.
if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
- << getOpenMPClauseName(CKind);
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
+ case OMPC_if:
Clause = ParseOpenMPSingleExprWithArgClause(CKind);
break;
- case OMPC_ordered:
case OMPC_nowait:
case OMPC_untied:
case OMPC_mergeable:
@@ -456,13 +513,16 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_nogroup:
// OpenMP [2.7.1, Restrictions, p. 9]
// Only one ordered clause can appear on a loop directive.
// OpenMP [2.7.1, Restrictions, C/C++, p. 4]
// Only one nowait clause can appear on a for directive.
if (!FirstClause) {
- Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
- << getOpenMPClauseName(CKind);
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
@@ -479,7 +539,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_copyprivate:
case OMPC_flush:
case OMPC_depend:
- Clause = ParseOpenMPVarListClause(CKind);
+ case OMPC_map:
+ Clause = ParseOpenMPVarListClause(DKind, CKind);
break;
case OMPC_unknown:
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
@@ -495,12 +556,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
return ErrorFound ? nullptr : Clause;
}
-/// \brief Parsing of OpenMP clauses with single expressions like 'if',
-/// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
-/// 'thread_limit'.
-///
-/// if-clause:
-/// 'if' '(' expression ')'
+/// \brief Parsing of OpenMP clauses with single expressions like 'final',
+/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
+/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
///
/// final-clause:
/// 'final' '(' expression ')'
@@ -511,9 +569,24 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
/// safelen-clause:
/// 'safelen' '(' expression ')'
///
+/// simdlen-clause:
+/// 'simdlen' '(' expression ')'
+///
/// collapse-clause:
/// 'collapse' '(' expression ')'
///
+/// priority-clause:
+/// 'priority' '(' expression ')'
+///
+/// grainsize-clause:
+/// 'grainsize' '(' expression ')'
+///
+/// num_tasks-clause:
+/// 'num_tasks' '(' expression ')'
+///
+/// hint-clause:
+/// 'hint' '(' expression ')'
+///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
SourceLocation Loc = ConsumeToken();
@@ -522,8 +595,10 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
getOpenMPClauseName(Kind)))
return nullptr;
+ SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+ Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
// Parse ')'.
T.consumeClose();
@@ -583,6 +658,15 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
/// read-clause:
/// 'read'
///
+/// threads-clause:
+/// 'threads'
+///
+/// simd-clause:
+/// 'simd'
+///
+/// nogroup-clause:
+/// 'nogroup'
+///
OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
ConsumeAnyToken();
@@ -595,11 +679,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
/// argument like 'schedule' or 'dist_schedule'.
///
/// schedule-clause:
-/// 'schedule' '(' kind [',' expression ] ')'
+/// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
+/// ')'
+///
+/// if-clause:
+/// 'if' '(' [ directive-name-modifier ':' ] expression ')'
///
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
SourceLocation Loc = ConsumeToken();
- SourceLocation CommaLoc;
+ SourceLocation DelimLoc;
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
@@ -607,29 +695,86 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
return nullptr;
ExprResult Val;
- unsigned Type = getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
- SourceLocation KLoc = Tok.getLocation();
- if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
- Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
+ SmallVector<unsigned, 4> Arg;
+ SmallVector<SourceLocation, 4> KLoc;
+ if (Kind == OMPC_schedule) {
+ enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
+ Arg.resize(NumberOfElements);
+ KLoc.resize(NumberOfElements);
+ Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
+ Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
+ Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
+ auto KindModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
+ if (KindModifier > OMPC_SCHEDULE_unknown) {
+ // Parse 'modifier'
+ Arg[Modifier1] = KindModifier;
+ KLoc[Modifier1] = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ if (Tok.is(tok::comma)) {
+ // Parse ',' 'modifier'
+ ConsumeAnyToken();
+ KindModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
+ Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
+ ? KindModifier
+ : (unsigned)OMPC_SCHEDULE_unknown;
+ KLoc[Modifier2] = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ }
+ // Parse ':'
+ if (Tok.is(tok::colon))
+ ConsumeAnyToken();
+ else
+ Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
+ KindModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
+ }
+ Arg[ScheduleKind] = KindModifier;
+ KLoc[ScheduleKind] = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
+ Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
+ Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
+ Tok.is(tok::comma))
+ DelimLoc = ConsumeAnyToken();
+ } else {
+ assert(Kind == OMPC_if);
+ KLoc.push_back(Tok.getLocation());
+ Arg.push_back(ParseOpenMPDirectiveKind(*this));
+ if (Arg.back() != OMPD_unknown) {
+ ConsumeToken();
+ if (Tok.is(tok::colon))
+ DelimLoc = ConsumeToken();
+ else
+ Diag(Tok, diag::warn_pragma_expected_colon)
+ << "directive name modifier";
+ }
+ }
- if (Kind == OMPC_schedule &&
- (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
- Type == OMPC_SCHEDULE_guided) &&
- Tok.is(tok::comma)) {
- CommaLoc = ConsumeAnyToken();
+ bool NeedAnExpression =
+ (Kind == OMPC_schedule && DelimLoc.isValid()) || Kind == OMPC_if;
+ if (NeedAnExpression) {
+ SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
- if (Val.isInvalid())
- return nullptr;
+ Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
}
// Parse ')'.
T.consumeClose();
+ if (NeedAnExpression && Val.isInvalid())
+ return nullptr;
+
return Actions.ActOnOpenMPSingleExprWithArgClause(
- Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
+ Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
T.getCloseLocation());
}
@@ -691,7 +836,7 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
/// shared-clause:
/// 'shared' '(' list ')'
/// linear-clause:
-/// 'linear' '(' list [ ':' linear-step ] ')'
+/// 'linear' '(' linear-list [ ':' linear-step ] ')'
/// aligned-clause:
/// 'aligned' '(' list [ ':' alignment ] ')'
/// reduction-clause:
@@ -701,9 +846,17 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
/// flush-clause:
/// 'flush' '(' list ')'
/// depend-clause:
-/// 'depend' '(' in | out | inout : list ')'
+/// 'depend' '(' in | out | inout : list | source ')'
+/// map-clause:
+/// 'map' '(' [ [ always , ]
+/// to | from | tofrom | alloc | release | delete ':' ] list ')';
///
-OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
+/// For 'linear' clause linear-list may have the following forms:
+/// list
+/// modifier(list)
+/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
+OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
SourceLocation LOpen = ConsumeToken();
SourceLocation ColonLoc = SourceLocation();
@@ -712,7 +865,14 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
UnqualifiedId ReductionId;
bool InvalidReductionId = false;
OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
- SourceLocation DepLoc;
+ // OpenMP 4.1 [2.15.3.7, linear Clause]
+ // If no modifier is specified it is assumed to be val.
+ OpenMPLinearClauseKind LinearModifier = OMPC_LINEAR_val;
+ OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
+ OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
+ bool MapTypeModifierSpecified = false;
+ bool UnexpectedId = false;
+ SourceLocation DepLinMapLoc;
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
@@ -720,6 +880,9 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
getOpenMPClauseName(Kind)))
return nullptr;
+ bool NeedRParenForLinear = false;
+ BalancedDelimiterTracker LinearT(*this, tok::l_paren,
+ tok::annot_pragma_openmp_end);
// Handle reduction-identifier for reduction clause.
if (Kind == OMPC_reduction) {
ColonProtectionRAIIObject ColonRAII(*this);
@@ -742,25 +905,109 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
ColonProtectionRAIIObject ColonRAII(*this);
DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
- DepLoc = Tok.getLocation();
+ DepLinMapLoc = Tok.getLocation();
if (DepKind == OMPC_DEPEND_unknown) {
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
} else {
ConsumeToken();
+ // Special processing for depend(source) clause.
+ if (DKind == OMPD_ordered && DepKind == OMPC_DEPEND_source) {
+ // Parse ')'.
+ T.consumeClose();
+ return Actions.ActOnOpenMPVarListClause(
+ Kind, llvm::None, /*TailExpr=*/nullptr, Loc, LOpen,
+ /*ColonLoc=*/SourceLocation(), Tok.getLocation(),
+ ReductionIdScopeSpec, DeclarationNameInfo(), DepKind,
+ LinearModifier, MapTypeModifier, MapType, DepLinMapLoc);
+ }
}
if (Tok.is(tok::colon)) {
ColonLoc = ConsumeToken();
} else {
- Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type";
+ Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
+ : diag::warn_pragma_expected_colon)
+ << "dependency type";
+ }
+ } else if (Kind == OMPC_linear) {
+ // Try to parse modifier if any.
+ if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
+ LinearModifier = static_cast<OpenMPLinearClauseKind>(
+ getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
+ DepLinMapLoc = ConsumeToken();
+ LinearT.consumeOpen();
+ NeedRParenForLinear = true;
+ }
+ } else if (Kind == OMPC_map) {
+ // Handle map type for map clause.
+ ColonProtectionRAIIObject ColonRAII(*this);
+
+ // the first identifier may be a list item, a map-type or
+ // a map-type-modifier
+ MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
+ DepLinMapLoc = Tok.getLocation();
+ bool ColonExpected = false;
+
+ if (Tok.is(tok::identifier)) {
+ if (PP.LookAhead(0).is(tok::colon)) {
+ MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
+ if (MapType == OMPC_MAP_unknown) {
+ Diag(Tok, diag::err_omp_unknown_map_type);
+ } else if (MapType == OMPC_MAP_always) {
+ Diag(Tok, diag::err_omp_map_type_missing);
+ }
+ ConsumeToken();
+ } else if (PP.LookAhead(0).is(tok::comma)) {
+ if (PP.LookAhead(1).is(tok::identifier) &&
+ PP.LookAhead(2).is(tok::colon)) {
+ MapTypeModifier =
+ static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
+ if (MapTypeModifier != OMPC_MAP_always) {
+ Diag(Tok, diag::err_omp_unknown_map_type_modifier);
+ MapTypeModifier = OMPC_MAP_unknown;
+ } else {
+ MapTypeModifierSpecified = true;
+ }
+
+ ConsumeToken();
+ ConsumeToken();
+
+ MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
+ if (MapType == OMPC_MAP_unknown || MapType == OMPC_MAP_always) {
+ Diag(Tok, diag::err_omp_unknown_map_type);
+ }
+ ConsumeToken();
+ } else {
+ MapType = OMPC_MAP_tofrom;
+ }
+ } else {
+ MapType = OMPC_MAP_tofrom;
+ }
+ } else {
+ UnexpectedId = true;
+ }
+
+ if (Tok.is(tok::colon)) {
+ ColonLoc = ConsumeToken();
+ } else if (ColonExpected) {
+ Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
}
}
SmallVector<Expr *, 5> Vars;
- bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) ||
- ((Kind == OMPC_reduction) && !InvalidReductionId) ||
- ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown);
+ bool IsComma =
+ ((Kind != OMPC_reduction) && (Kind != OMPC_depend) &&
+ (Kind != OMPC_map)) ||
+ ((Kind == OMPC_reduction) && !InvalidReductionId) ||
+ ((Kind == OMPC_map) && (UnexpectedId || MapType != OMPC_MAP_unknown) &&
+ (!MapTypeModifierSpecified ||
+ (MapTypeModifierSpecified && MapTypeModifier == OMPC_MAP_always))) ||
+ ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown);
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
@@ -787,14 +1034,18 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
<< (Kind == OMPC_flush);
}
+ // Parse ')' for linear clause with modifier.
+ if (NeedRParenForLinear)
+ LinearT.consumeClose();
+
// Parse ':' linear-step (or ':' alignment).
Expr *TailExpr = nullptr;
const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
if (MustHaveTail) {
ColonLoc = Tok.getLocation();
- ConsumeToken();
- ExprResult Tail =
- Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+ SourceLocation ELoc = ConsumeToken();
+ ExprResult Tail = ParseAssignmentExpression();
+ Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
if (Tail.isUsable())
TailExpr = Tail.get();
else
@@ -806,14 +1057,16 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
T.consumeClose();
if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) ||
(Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) ||
- InvalidReductionId)
+ (Kind == OMPC_map && MapType == OMPC_MAP_unknown) ||
+ InvalidReductionId) {
return nullptr;
+ }
return Actions.ActOnOpenMPVarListClause(
Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
ReductionIdScopeSpec,
ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
: DeclarationNameInfo(),
- DepKind, DepLoc);
+ DepKind, LinearModifier, MapTypeModifier, MapType, DepLinMapLoc);
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
index 892d3c6..bc70942 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp
@@ -156,6 +156,10 @@ struct PragmaUnrollHintHandler : public PragmaHandler {
Token &FirstToken) override;
};
+struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
+ PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
+};
+
} // end namespace
void Parser::initializePragmaHandlers() {
@@ -222,6 +226,8 @@ void Parser::initializePragmaHandlers() {
PP.AddPragmaHandler(MSCodeSeg.get());
MSSection.reset(new PragmaMSPragma("section"));
PP.AddPragmaHandler(MSSection.get());
+ MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
+ PP.AddPragmaHandler(MSRuntimeChecks.get());
}
OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
@@ -288,6 +294,8 @@ void Parser::resetPragmaHandlers() {
MSCodeSeg.reset();
PP.RemovePragmaHandler(MSSection.get());
MSSection.reset();
+ PP.RemovePragmaHandler(MSRuntimeChecks.get());
+ MSRuntimeChecks.reset();
}
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
@@ -326,6 +334,7 @@ void Parser::HandlePragmaVisibility() {
Actions.ActOnPragmaVisibility(VisType, VisLoc);
}
+namespace {
struct PragmaPackInfo {
Sema::PragmaPackKind Kind;
IdentifierInfo *Name;
@@ -333,6 +342,7 @@ struct PragmaPackInfo {
SourceLocation LParenLoc;
SourceLocation RParenLoc;
};
+} // end anonymous namespace
void Parser::HandlePragmaPack() {
assert(Tok.is(tok::annot_pragma_pack));
@@ -367,6 +377,14 @@ void Parser::HandlePragmaAlign() {
Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
}
+void Parser::HandlePragmaDump() {
+ assert(Tok.is(tok::annot_pragma_dump));
+ IdentifierInfo *II =
+ reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
+ Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
+ ConsumeToken();
+}
+
void Parser::HandlePragmaWeak() {
assert(Tok.is(tok::annot_pragma_weak));
SourceLocation PragmaLoc = ConsumeToken();
@@ -742,13 +760,13 @@ bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
return true;
}
+namespace {
struct PragmaLoopHintInfo {
Token PragmaName;
Token Option;
- Token *Toks;
- size_t TokSize;
- PragmaLoopHintInfo() : Toks(nullptr), TokSize(0) {}
+ ArrayRef<Token> Toks;
};
+} // end anonymous namespace
static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
std::string PragmaString;
@@ -780,8 +798,8 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Hint.OptionLoc = IdentifierLoc::create(
Actions.Context, Info->Option.getLocation(), OptionInfo);
- Token *Toks = Info->Toks;
- size_t TokSize = Info->TokSize;
+ const Token *Toks = Info->Toks.data();
+ size_t TokSize = Info->Toks.size();
// Return a valid hint if pragma unroll or nounroll were specified
// without an argument.
@@ -824,10 +842,9 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
SourceLocation StateLoc = Toks[0].getLocation();
IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
if (!StateInfo ||
- ((OptionUnroll ? !StateInfo->isStr("full")
- : !StateInfo->isStr("enable") &&
- !StateInfo->isStr("assume_safety")) &&
- !StateInfo->isStr("disable"))) {
+ (!StateInfo->isStr("enable") && !StateInfo->isStr("disable") &&
+ ((OptionUnroll && !StateInfo->isStr("full")) ||
+ (!OptionUnroll && !StateInfo->isStr("assume_safety"))))) {
Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
<< /*FullKeyword=*/OptionUnroll;
return false;
@@ -1928,11 +1945,7 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
EOFTok.setLocation(Tok.getLocation());
ValueList.push_back(EOFTok); // Terminates expression for parsing.
- Token *TokenArray = (Token *)PP.getPreprocessorAllocator().Allocate(
- ValueList.size() * sizeof(Token), llvm::alignOf<Token>());
- std::copy(ValueList.begin(), ValueList.end(), TokenArray);
- Info.Toks = TokenArray;
- Info.TokSize = ValueList.size();
+ Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Info.PragmaName = PragmaName;
Info.Option = Option;
@@ -1959,8 +1972,9 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
/// 'assume_safety'
///
/// unroll-hint-keyword:
-/// 'full'
+/// 'enable'
/// 'disable'
+/// 'full'
///
/// loop-hint-value:
/// constant-expression
@@ -1976,10 +1990,13 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
/// only works on inner loops.
///
/// The unroll and unroll_count directives control the concatenation
-/// unroller. Specifying unroll(full) instructs llvm to try to
-/// unroll the loop completely, and unroll(disable) disables unrolling
-/// for the loop. Specifying unroll_count(_value_) instructs llvm to
-/// try to unroll the loop the number of times indicated by the value.
+/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
+/// completely if the trip count is known at compile time and unroll partially
+/// if the trip count is not known. Specifying unroll(full) is similar to
+/// unroll(enable) but will unroll the loop only if the trip count is known at
+/// compile time. Specifying unroll(disable) disables unrolling for the
+/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
+/// loop the number of times indicated by the value.
void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &Tok) {
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
index b658cef..edf0dda 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
@@ -32,14 +32,18 @@ using namespace clang;
/// \brief Parse a standalone statement (for instance, as the body of an 'if',
/// 'while', or 'for').
-StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc) {
+StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc,
+ bool AllowOpenMPStandalone) {
StmtResult Res;
// We may get back a null statement if we found a #pragma. Keep going until
// we get an actual statement.
do {
StmtVector Stmts;
- Res = ParseStatementOrDeclaration(Stmts, true, TrailingElseLoc);
+ Res = ParseStatementOrDeclaration(
+ Stmts, AllowOpenMPStandalone ? ACK_StatementsOpenMPAnyExecutable
+ : ACK_StatementsOpenMPNonStandalone,
+ TrailingElseLoc);
} while (!Res.isInvalid() && !Res.get());
return Res;
@@ -95,7 +99,8 @@ StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc) {
/// [OBC] '@' 'throw' ';'
///
StmtResult
-Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
+Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
+ AllowedContsructsKind Allowed,
SourceLocation *TrailingElseLoc) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
@@ -103,8 +108,8 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
ParsedAttributesWithRange Attrs(AttrFactory);
MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true);
- StmtResult Res = ParseStatementOrDeclarationAfterAttributes(Stmts,
- OnlyStatement, TrailingElseLoc, Attrs);
+ StmtResult Res = ParseStatementOrDeclarationAfterAttributes(
+ Stmts, Allowed, TrailingElseLoc, Attrs);
assert((Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
"attributes on empty statement");
@@ -146,7 +151,7 @@ private:
StmtResult
Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
- bool OnlyStatement, SourceLocation *TrailingElseLoc,
+ AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs) {
const char *SemiError = nullptr;
StmtResult Res;
@@ -202,7 +207,8 @@ Retry:
}
default: {
- if ((getLangOpts().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
+ if ((getLangOpts().CPlusPlus || Allowed == ACK_Any) &&
+ isDeclarationStatement()) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext,
DeclEnd, Attrs);
@@ -259,6 +265,10 @@ Retry:
Res = ParseReturnStatement();
SemiError = "return";
break;
+ case tok::kw_co_return: // C++ Coroutines: co_return statement
+ Res = ParseReturnStatement();
+ SemiError = "co_return";
+ break;
case tok::kw_asm: {
ProhibitAttributes(Attrs);
@@ -342,7 +352,7 @@ Retry:
case tok::annot_pragma_openmp:
ProhibitAttributes(Attrs);
- return ParseOpenMPDeclarativeOrExecutableDirective(!OnlyStatement);
+ return ParseOpenMPDeclarativeOrExecutableDirective(Allowed);
case tok::annot_pragma_ms_pointers_to_members:
ProhibitAttributes(Attrs);
@@ -354,9 +364,18 @@ Retry:
HandlePragmaMSPragma();
return StmtEmpty();
+ case tok::annot_pragma_ms_vtordisp:
+ ProhibitAttributes(Attrs);
+ HandlePragmaMSVtorDisp();
+ return StmtEmpty();
+
case tok::annot_pragma_loop_hint:
ProhibitAttributes(Attrs);
- return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs);
+ return ParsePragmaLoopHint(Stmts, Allowed, TrailingElseLoc, Attrs);
+
+ case tok::annot_pragma_dump:
+ HandlePragmaDump();
+ return StmtEmpty();
}
// If we reached this code, the statement must end in a semicolon.
@@ -574,7 +593,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) {
// can't handle GNU attributes), so only call it in the one case where
// GNU attributes are allowed.
SubStmt = ParseStatementOrDeclarationAfterAttributes(
- Stmts, /*OnlyStmts*/ true, nullptr, TempAttrs);
+ Stmts, /*Allowed=*/ACK_StatementsOpenMPNonStandalone, nullptr,
+ TempAttrs);
if (!TempAttrs.empty() && !SubStmt.isInvalid())
SubStmt = Actions.ProcessStmtAttributes(
SubStmt.get(), TempAttrs.getList(), TempAttrs.Range);
@@ -713,7 +733,8 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
// continue parsing the sub-stmt.
if (Case.isInvalid()) {
if (TopLevelCase.isInvalid()) // No parsed case stmts.
- return ParseStatement();
+ return ParseStatement(/*TrailingElseLoc=*/nullptr,
+ /*AllowOpenMPStandalone=*/true);
// Otherwise, just don't add it as a nested case.
} else {
// If this is the first case statement we parsed, it becomes TopLevelCase.
@@ -733,7 +754,8 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
StmtResult SubStmt;
if (Tok.isNot(tok::r_brace)) {
- SubStmt = ParseStatement();
+ SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr,
+ /*AllowOpenMPStandalone=*/true);
} else {
// Nicely diagnose the common error "switch (X) { case 4: }", which is
// not valid. If ColonLoc doesn't point to a valid text location, there was
@@ -785,7 +807,8 @@ StmtResult Parser::ParseDefaultStatement() {
StmtResult SubStmt;
if (Tok.isNot(tok::r_brace)) {
- SubStmt = ParseStatement();
+ SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr,
+ /*AllowOpenMPStandalone=*/true);
} else {
// Diagnose the common error "switch (X) {... default: }", which is
// not valid.
@@ -881,6 +904,12 @@ void Parser::ParseCompoundStatementLeadingPragmas() {
case tok::annot_pragma_ms_pragma:
HandlePragmaMSPragma();
break;
+ case tok::annot_pragma_ms_vtordisp:
+ HandlePragmaMSVtorDisp();
+ break;
+ case tok::annot_pragma_dump:
+ HandlePragmaDump();
+ break;
default:
checkForPragmas = false;
break;
@@ -944,7 +973,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
Stmts.push_back(R.get());
}
- while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
+ while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
+ Tok.isNot(tok::eof)) {
if (Tok.is(tok::annot_pragma_unused)) {
HandlePragmaUnused();
continue;
@@ -952,7 +982,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
StmtResult R;
if (Tok.isNot(tok::kw___extension__)) {
- R = ParseStatementOrDeclaration(Stmts, false);
+ R = ParseStatementOrDeclaration(Stmts, ACK_Any);
} else {
// __extension__ can start declarations and it can also be a unary
// operator for expressions. Consume multiple __extension__ markers here
@@ -1442,7 +1472,10 @@ bool Parser::isForRangeIdentifier() {
/// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
/// [C++] 'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
/// [C++] statement
-/// [C++0x] 'for' '(' for-range-declaration : for-range-initializer ) statement
+/// [C++0x] 'for'
+/// 'co_await'[opt] [Coroutines]
+/// '(' for-range-declaration ':' for-range-initializer ')'
+/// statement
/// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
/// [OBJC2] 'for' '(' expr 'in' expr ')' statement
///
@@ -1459,6 +1492,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
assert(Tok.is(tok::kw_for) && "Not a for stmt!");
SourceLocation ForLoc = ConsumeToken(); // eat the 'for'.
+ SourceLocation CoawaitLoc;
+ if (Tok.is(tok::kw_co_await))
+ CoawaitLoc = ConsumeToken();
+
if (Tok.isNot(tok::l_paren)) {
Diag(Tok, diag::err_expected_lparen_after) << "for";
SkipUntil(tok::semi);
@@ -1665,6 +1702,13 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
// Match the ')'.
T.consumeClose();
+ // C++ Coroutines [stmt.iter]:
+ // 'co_await' can only be used for a range-based for statement.
+ if (CoawaitLoc.isValid() && !ForRange) {
+ Diag(CoawaitLoc, diag::err_for_co_await_not_range_for);
+ CoawaitLoc = SourceLocation();
+ }
+
// We need to perform most of the semantic analysis for a C++0x for-range
// statememt before parsing the body, in order to be able to deduce the type
// of an auto-typed loop variable.
@@ -1672,12 +1716,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
StmtResult ForEachStmt;
if (ForRange) {
- ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, FirstPart.get(),
- ForRangeInit.ColonLoc,
- ForRangeInit.RangeExpr.get(),
- T.getCloseLocation(),
- Sema::BFRK_Build);
-
+ ForRangeStmt = Actions.ActOnCXXForRangeStmt(
+ getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
+ ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(),
+ T.getCloseLocation(), Sema::BFRK_Build);
// Similarly, we need to do the semantic analysis for a for-range
// statement immediately in order to close over temporaries correctly.
@@ -1799,13 +1841,19 @@ StmtResult Parser::ParseBreakStatement() {
/// ParseReturnStatement
/// jump-statement:
/// 'return' expression[opt] ';'
+/// 'return' braced-init-list ';'
+/// 'co_return' expression[opt] ';'
+/// 'co_return' braced-init-list ';'
StmtResult Parser::ParseReturnStatement() {
- assert(Tok.is(tok::kw_return) && "Not a return stmt!");
+ assert((Tok.is(tok::kw_return) || Tok.is(tok::kw_co_return)) &&
+ "Not a return stmt!");
+ bool IsCoreturn = Tok.is(tok::kw_co_return);
SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
ExprResult R;
if (Tok.isNot(tok::semi)) {
- if (Tok.is(tok::code_completion)) {
+ // FIXME: Code completion for co_return.
+ if (Tok.is(tok::code_completion) && !IsCoreturn) {
Actions.CodeCompleteReturn(getCurScope());
cutOffParsing();
return StmtError();
@@ -1825,10 +1873,13 @@ StmtResult Parser::ParseReturnStatement() {
return StmtError();
}
}
+ if (IsCoreturn)
+ return Actions.ActOnCoreturnStmt(ReturnLoc, R.get());
return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope());
}
-StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement,
+StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,
+ AllowedContsructsKind Allowed,
SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs) {
// Create temporary attribute list.
@@ -1851,7 +1902,7 @@ StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement,
MaybeParseCXX11Attributes(Attrs);
StmtResult S = ParseStatementOrDeclarationAfterAttributes(
- Stmts, OnlyStatement, TrailingElseLoc, Attrs);
+ Stmts, Allowed, TrailingElseLoc, Attrs);
Attrs.takeAllFrom(TempAttrs);
return S;
@@ -1870,6 +1921,11 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
"parsing function body");
+ // Save and reset current vtordisp stack if we have entered a C++ method body.
+ bool IsCXXMethod =
+ getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl);
+ Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod);
+
// Do not enter a scope for the brace, as the arguments are in the same scope
// (the function body) as the body itself. Instead, just read the statement
// list and put it into a CompoundStmt for safe keeping.
@@ -1909,6 +1965,11 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
return Actions.ActOnSkippedFunctionBody(Decl);
}
+ // Save and reset current vtordisp stack if we have entered a C++ method body.
+ bool IsCXXMethod =
+ getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl);
+ Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod);
+
SourceLocation LBraceLoc = Tok.getLocation();
StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true));
// If we failed to parse the try-catch, we just give the function an empty
@@ -2139,7 +2200,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
// Condition is true, parse the statements.
while (Tok.isNot(tok::r_brace)) {
- StmtResult R = ParseStatementOrDeclaration(Stmts, false);
+ StmtResult R = ParseStatementOrDeclaration(Stmts, ACK_Any);
if (R.isUsable())
Stmts.push_back(R.get());
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
index 8cdae6a..142b473 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp
@@ -215,12 +215,35 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
// Require an identifier here.
SourceLocation TemplateKWLoc;
UnqualifiedId Id;
- bool Invalid =
- ParseUnqualifiedId(SS,
- /*EnteringContext=*/false,
- /*AllowDestructorName=*/false,
- /*AllowConstructorName=*/false,
- /*ObjectType=*/ParsedType(), TemplateKWLoc, Id);
+ bool Invalid = true;
+ ExprResult Result;
+ if (Tok.is(tok::kw_this)) {
+ Result = ParseCXXThis();
+ Invalid = false;
+ } else {
+ Invalid =
+ ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/false,
+ /*AllowConstructorName=*/false,
+ /*ObjectType=*/ParsedType(), TemplateKWLoc, Id);
+ // Perform the lookup.
+ Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
+ IsUnevaluatedContext);
+ }
+ // While the next two tokens are 'period' 'identifier', repeatedly parse it as
+ // a field access. We have to avoid consuming assembler directives that look
+ // like '.' 'else'.
+ while (Result.isUsable() && Tok.is(tok::period)) {
+ Token IdTok = PP.LookAhead(0);
+ if (IdTok.isNot(tok::identifier))
+ break;
+ ConsumeToken(); // Consume the period.
+ IdentifierInfo *Id = Tok.getIdentifierInfo();
+ ConsumeToken(); // Consume the identifier.
+ Result = Actions.LookupInlineAsmVarDeclField(Result.get(), Id->getName(),
+ Info, Tok.getLocation());
+ }
// Figure out how many tokens we are into LineToks.
unsigned LineIndex = 0;
@@ -254,9 +277,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
LineToks.pop_back();
LineToks.pop_back();
- // Perform the lookup.
- return Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
- IsUnevaluatedContext);
+ return Result;
}
/// Turn a sequence of our tokens back into a string that we can hand
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
index 3a964dd..a4dcdb1 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
@@ -126,8 +126,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
Actions.ActOnTemplateParameterList(CurTemplateDepthTracker.getDepth(),
ExportLoc,
TemplateLoc, LAngleLoc,
- TemplateParams.data(),
- TemplateParams.size(), RAngleLoc));
+ TemplateParams, RAngleLoc));
if (!TemplateParams.empty()) {
isSpecialization = false;
@@ -280,8 +279,8 @@ Parser::ParseSingleDeclarationAfterTemplate(
// Recover as if it were an explicit specialization.
TemplateParameterLists FakedParamLists;
FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
- 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr,
- 0, LAngleLoc));
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None,
+ LAngleLoc));
return ParseFunctionDefinition(
DeclaratorInfo, ParsedTemplateInfo(&FakedParamLists,
@@ -631,8 +630,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
TemplateParameterList *ParamList =
Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
TemplateLoc, LAngleLoc,
- TemplateParams.data(),
- TemplateParams.size(),
+ TemplateParams,
RAngleLoc);
// Grab a default argument (if available).
@@ -695,7 +693,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// end of the template-parameter-list rather than a greater-than
// operator.
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
- EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
+ EnterExpressionEvaluationContext ConstantEvaluated(Actions,
+ Sema::ConstantEvaluated);
DefaultArg = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
if (DefaultArg.isInvalid())
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
index 9d2a2b9..6fbcfd9 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp
@@ -1089,6 +1089,7 @@ public:
/// [GNU] typeof-specifier
/// [GNU] '_Complex'
/// [C++11] 'auto'
+/// [GNU] '__auto_type'
/// [C++11] 'decltype' ( expression )
/// [C++1y] 'decltype' ( 'auto' )
///
@@ -1262,6 +1263,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw_restrict:
case tok::kw__Complex:
case tok::kw___attribute:
+ case tok::kw___auto_type:
return TPResult::True;
// Microsoft
@@ -1515,6 +1517,7 @@ bool Parser::isCXXDeclarationSpecifierAType() {
case tok::kw_double:
case tok::kw_void:
case tok::kw___unknown_anytype:
+ case tok::kw___auto_type:
return true;
case tok::kw_auto:
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
index 0574a63..ccefb3d 100644
--- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
@@ -282,6 +282,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
// Ran out of tokens.
return false;
+ case tok::annot_pragma_openmp:
case tok::annot_pragma_openmp_end:
// Stop before an OpenMP pragma boundary.
case tok::annot_module_begin:
@@ -667,6 +668,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
case tok::annot_pragma_ms_pragma:
HandlePragmaMSPragma();
return DeclGroupPtrTy();
+ case tok::annot_pragma_dump:
+ HandlePragmaDump();
+ return DeclGroupPtrTy();
case tok::semi:
// Either a C++11 empty-declaration or attribute-declaration.
SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(),
@@ -1067,10 +1071,17 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// Tell the actions module that we have entered a function definition with the
// specified Declarator for the function.
- Decl *Res = TemplateInfo.TemplateParams?
- Actions.ActOnStartOfFunctionTemplateDef(getCurScope(),
- *TemplateInfo.TemplateParams, D)
- : Actions.ActOnStartOfFunctionDef(getCurScope(), D);
+ Sema::SkipBodyInfo SkipBody;
+ Decl *Res = Actions.ActOnStartOfFunctionDef(getCurScope(), D,
+ TemplateInfo.TemplateParams
+ ? *TemplateInfo.TemplateParams
+ : MultiTemplateParamsArg(),
+ &SkipBody);
+
+ if (SkipBody.ShouldSkip) {
+ SkipFunctionBody();
+ return Res;
+ }
// Break out of the ParsingDeclarator context before we parse the body.
D.complete(Res);
@@ -1086,14 +1097,16 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
SourceLocation KWLoc;
if (TryConsumeToken(tok::kw_delete, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
- ? diag::warn_cxx98_compat_deleted_function
- : diag::ext_deleted_function);
+ ? diag::warn_cxx98_compat_defaulted_deleted_function
+ : diag::ext_defaulted_deleted_function)
+ << 1 /* deleted */;
Actions.SetDeclDeleted(Res, KWLoc);
Delete = true;
} else if (TryConsumeToken(tok::kw_default, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
- ? diag::warn_cxx98_compat_defaulted_function
- : diag::ext_defaulted_function);
+ ? diag::warn_cxx98_compat_defaulted_deleted_function
+ : diag::ext_defaulted_deleted_function)
+ << 0 /* defaulted */;
Actions.SetDeclDefaulted(Res, KWLoc);
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
@@ -1137,6 +1150,28 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
return ParseFunctionStatementBody(Res, BodyScope);
}
+void Parser::SkipFunctionBody() {
+ if (Tok.is(tok::equal)) {
+ SkipUntil(tok::semi);
+ return;
+ }
+
+ bool IsFunctionTryBlock = Tok.is(tok::kw_try);
+ if (IsFunctionTryBlock)
+ ConsumeToken();
+
+ CachedTokens Skipped;
+ if (ConsumeAndStoreFunctionPrologue(Skipped))
+ SkipMalformedDecl();
+ else {
+ SkipUntil(tok::r_brace);
+ while (IsFunctionTryBlock && Tok.is(tok::kw_catch)) {
+ SkipUntil(tok::l_brace);
+ SkipUntil(tok::r_brace);
+ }
+ }
+}
+
/// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides
/// types for a function with a K&R-style identifier list for arguments.
void Parser::ParseKNRParamDeclarations(Declarator &D) {
@@ -1493,7 +1528,7 @@ bool Parser::TryKeywordIdentFallback(bool DisableKeyword) {
<< PP.getSpelling(Tok)
<< DisableKeyword;
if (DisableKeyword)
- Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
+ Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
Tok.setKind(tok::identifier);
return true;
}
@@ -1989,6 +2024,37 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
return Actions.ConvertDeclToDeclGroup(Import.get());
}
+/// \brief Try recover parser when module annotation appears where it must not
+/// be found.
+/// \returns false if the recover was successful and parsing may be continued, or
+/// true if parser must bail out to top level and handle the token there.
+bool Parser::parseMisplacedModuleImport() {
+ while (true) {
+ switch (Tok.getKind()) {
+ case tok::annot_module_end:
+ // Inform caller that recovery failed, the error must be handled at upper
+ // level.
+ return true;
+ case tok::annot_module_begin:
+ Actions.diagnoseMisplacedModuleImport(reinterpret_cast<Module *>(
+ Tok.getAnnotationValue()), Tok.getLocation());
+ return true;
+ case tok::annot_module_include:
+ // Module import found where it should not be, for instance, inside a
+ // namespace. Recover by importing the module.
+ Actions.ActOnModuleInclude(Tok.getLocation(),
+ reinterpret_cast<Module *>(
+ Tok.getAnnotationValue()));
+ ConsumeToken();
+ // If there is another module import, process it.
+ continue;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
bool BalancedDelimiterTracker::diagnoseOverflow() {
P.Diag(P.Tok, diag::err_bracket_depth_exceeded)
<< P.getLangOpts().BracketDepth;
@@ -2016,7 +2082,10 @@ bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,
bool BalancedDelimiterTracker::diagnoseMissingClose() {
assert(!P.Tok.is(Close) && "Should have consumed closing delimiter");
- P.Diag(P.Tok, diag::err_expected) << Close;
+ if (P.Tok.is(tok::annot_module_end))
+ P.Diag(P.Tok, diag::err_missing_before_module_end) << Close;
+ else
+ P.Diag(P.Tok, diag::err_expected) << Close;
P.Diag(LOpen, diag::note_matching) << Kind;
// If we're not already at some kind of closing bracket, skip to our closing
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp b/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp
index be09a36..ae41dec 100644
--- a/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Rewrite/Rewriter.cpp
@@ -15,11 +15,9 @@
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticIDs.h"
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -35,7 +33,7 @@ raw_ostream &RewriteBuffer::write(raw_ostream &os) const {
/// \brief Return true if this character is non-new-line whitespace:
/// ' ', '\\t', '\\f', '\\v', '\\r'.
-static inline bool isWhitespace(unsigned char c) {
+static inline bool isWhitespaceExceptNL(unsigned char c) {
switch (c) {
case ' ':
case '\t':
@@ -80,7 +78,7 @@ void RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size,
unsigned lineSize = 0;
posI = curLineStart;
- while (posI != end() && isWhitespace(*posI)) {
+ while (posI != end() && isWhitespaceExceptNL(*posI)) {
++posI;
++lineSize;
}
@@ -256,7 +254,7 @@ bool Rewriter::InsertText(SourceLocation Loc, StringRef Str,
StringRef indentSpace;
{
unsigned i = lineOffs;
- while (isWhitespace(MB[i]))
+ while (isWhitespaceExceptNL(MB[i]))
++i;
indentSpace = MB.substr(lineOffs, i-lineOffs);
}
@@ -363,12 +361,12 @@ bool Rewriter::IncreaseIndentation(CharSourceRange range,
StringRef parentSpace, startSpace;
{
unsigned i = parentLineOffs;
- while (isWhitespace(MB[i]))
+ while (isWhitespaceExceptNL(MB[i]))
++i;
parentSpace = MB.substr(parentLineOffs, i-parentLineOffs);
i = startLineOffs;
- while (isWhitespace(MB[i]))
+ while (isWhitespaceExceptNL(MB[i]))
++i;
startSpace = MB.substr(startLineOffs, i-startLineOffs);
}
@@ -384,7 +382,7 @@ bool Rewriter::IncreaseIndentation(CharSourceRange range,
for (unsigned lineNo = startLineNo; lineNo <= endLineNo; ++lineNo) {
unsigned offs = Content->SourceLineCache[lineNo];
unsigned i = offs;
- while (isWhitespace(MB[i]))
+ while (isWhitespaceExceptNL(MB[i]))
++i;
StringRef origIndent = MB.substr(offs, i-offs);
if (origIndent.startswith(startSpace))
@@ -409,7 +407,7 @@ public:
TempFilename = Filename;
TempFilename += "-%%%%%%%%";
int FD;
- if (llvm::sys::fs::createUniqueFile(TempFilename.str(), FD, TempFilename)) {
+ if (llvm::sys::fs::createUniqueFile(TempFilename, FD, TempFilename)) {
AllWritten = false;
Diagnostics.Report(clang::diag::err_unable_to_make_temp)
<< TempFilename;
@@ -421,19 +419,15 @@ public:
~AtomicallyMovedFile() {
if (!ok()) return;
- FileStream->flush();
-#ifdef LLVM_ON_WIN32
- // Win32 does not allow rename/removing opened files.
- FileStream.reset();
-#endif
- if (std::error_code ec =
- llvm::sys::fs::rename(TempFilename.str(), Filename)) {
+ // Close (will also flush) theFileStream.
+ FileStream->close();
+ if (std::error_code ec = llvm::sys::fs::rename(TempFilename, Filename)) {
AllWritten = false;
Diagnostics.Report(clang::diag::err_unable_to_rename_temp)
<< TempFilename << Filename << ec.message();
// If the remove fails, there's not a lot we can do - this is already an
// error.
- llvm::sys::fs::remove(TempFilename.str());
+ llvm::sys::fs::remove(TempFilename);
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
index f2ff48a..5f74343 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -34,7 +34,6 @@
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
@@ -99,7 +98,7 @@ namespace {
}
}
};
-}
+} // anonymous namespace
/// CheckUnreachable - Check for unreachable code.
static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
@@ -157,12 +156,45 @@ public:
<< DiagRange << isAlwaysTrue;
}
};
-} // namespace
+} // anonymous namespace
//===----------------------------------------------------------------------===//
// Check for infinite self-recursion in functions
//===----------------------------------------------------------------------===//
+// Returns true if the function is called anywhere within the CFGBlock.
+// For member functions, the additional condition of being call from the
+// this pointer is required.
+static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) {
+ // Process all the Stmt's in this block to find any calls to FD.
+ for (const auto &B : Block) {
+ if (B.getKind() != CFGElement::Statement)
+ continue;
+
+ const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());
+ if (!CE || !CE->getCalleeDecl() ||
+ CE->getCalleeDecl()->getCanonicalDecl() != FD)
+ continue;
+
+ // Skip function calls which are qualified with a templated class.
+ if (const DeclRefExpr *DRE =
+ dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) {
+ if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
+ if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
+ isa<TemplateSpecializationType>(NNS->getAsType())) {
+ continue;
+ }
+ }
+ }
+
+ const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE);
+ if (!MCE || isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
+ !MCE->getMethodDecl()->isVirtual())
+ return true;
+ }
+ return false;
+}
+
// All blocks are in one of three states. States are ordered so that blocks
// can only move to higher states.
enum RecursiveState {
@@ -171,68 +203,56 @@ enum RecursiveState {
FoundPathWithNoRecursiveCall
};
-static void checkForFunctionCall(Sema &S, const FunctionDecl *FD,
- CFGBlock &Block, unsigned ExitID,
- llvm::SmallVectorImpl<RecursiveState> &States,
- RecursiveState State) {
- unsigned ID = Block.getBlockID();
+// Returns true if there exists a path to the exit block and every path
+// to the exit block passes through a call to FD.
+static bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) {
- // A block's state can only move to a higher state.
- if (States[ID] >= State)
- return;
+ const unsigned ExitID = cfg->getExit().getBlockID();
- States[ID] = State;
+ // Mark all nodes as FoundNoPath, then set the status of the entry block.
+ SmallVector<RecursiveState, 16> States(cfg->getNumBlockIDs(), FoundNoPath);
+ States[cfg->getEntry().getBlockID()] = FoundPathWithNoRecursiveCall;
- // Found a path to the exit node without a recursive call.
- if (ID == ExitID && State == FoundPathWithNoRecursiveCall)
- return;
+ // Make the processing stack and seed it with the entry block.
+ SmallVector<CFGBlock *, 16> Stack;
+ Stack.push_back(&cfg->getEntry());
- if (State == FoundPathWithNoRecursiveCall) {
- // If the current state is FoundPathWithNoRecursiveCall, the successors
- // will be either FoundPathWithNoRecursiveCall or FoundPath. To determine
- // which, process all the Stmt's in this block to find any recursive calls.
- for (const auto &B : Block) {
- if (B.getKind() != CFGElement::Statement)
- continue;
+ while (!Stack.empty()) {
+ CFGBlock *CurBlock = Stack.back();
+ Stack.pop_back();
- const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt());
- if (CE && CE->getCalleeDecl() &&
- CE->getCalleeDecl()->getCanonicalDecl() == FD) {
-
- // Skip function calls which are qualified with a templated class.
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
- CE->getCallee()->IgnoreParenImpCasts())) {
- if (NestedNameSpecifier *NNS = DRE->getQualifier()) {
- if (NNS->getKind() == NestedNameSpecifier::TypeSpec &&
- isa<TemplateSpecializationType>(NNS->getAsType())) {
- continue;
- }
- }
- }
+ unsigned ID = CurBlock->getBlockID();
+ RecursiveState CurState = States[ID];
- if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) {
- if (isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) ||
- !MCE->getMethodDecl()->isVirtual()) {
- State = FoundPath;
- break;
- }
- } else {
- State = FoundPath;
- break;
+ if (CurState == FoundPathWithNoRecursiveCall) {
+ // Found a path to the exit node without a recursive call.
+ if (ExitID == ID)
+ return false;
+
+ // Only change state if the block has a recursive call.
+ if (hasRecursiveCallInPath(FD, *CurBlock))
+ CurState = FoundPath;
+ }
+
+ // Loop over successor blocks and add them to the Stack if their state
+ // changes.
+ for (auto I = CurBlock->succ_begin(), E = CurBlock->succ_end(); I != E; ++I)
+ if (*I) {
+ unsigned next_ID = (*I)->getBlockID();
+ if (States[next_ID] < CurState) {
+ States[next_ID] = CurState;
+ Stack.push_back(*I);
}
}
- }
}
- for (CFGBlock::succ_iterator I = Block.succ_begin(), E = Block.succ_end();
- I != E; ++I)
- if (*I)
- checkForFunctionCall(S, FD, **I, ExitID, States, State);
+ // Return true if the exit node is reachable, and only reachable through
+ // a recursive call.
+ return States[ExitID] == FoundPath;
}
static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
- const Stmt *Body,
- AnalysisDeclContext &AC) {
+ const Stmt *Body, AnalysisDeclContext &AC) {
FD = FD->getCanonicalDecl();
// Only run on non-templated functions and non-templated members of
@@ -248,15 +268,8 @@ static void checkRecursiveFunction(Sema &S, const FunctionDecl *FD,
if (cfg->getExit().pred_empty())
return;
- // Mark all nodes as FoundNoPath, then begin processing the entry block.
- llvm::SmallVector<RecursiveState, 16> states(cfg->getNumBlockIDs(),
- FoundNoPath);
- checkForFunctionCall(S, FD, cfg->getEntry(), cfg->getExit().getBlockID(),
- states, FoundPathWithNoRecursiveCall);
-
- // Check that the exit block is reachable. This prevents triggering the
- // warning on functions that do not terminate.
- if (states[cfg->getExit().getBlockID()] == FoundPath)
+ // Emit diagnostic if a recursive function call is detected for all paths.
+ if (checkForRecursiveFunctionCall(FD, cfg))
S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function);
}
@@ -492,7 +505,7 @@ struct CheckFallThroughDiagnostics {
}
};
-}
+} // anonymous namespace
/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
/// function that should return a value. Check that we don't fall off the end
@@ -600,7 +613,7 @@ public:
bool doesContainReference() const { return FoundReference; }
};
-}
+} // anonymous namespace
static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
QualType VariableTy = VD->getType().getCanonicalType();
@@ -643,8 +656,7 @@ static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then,
CharSourceRange::getCharRange(If->getLocStart(),
Then->getLocStart()));
if (Else) {
- SourceLocation ElseKwLoc = Lexer::getLocForEndOfToken(
- Then->getLocEnd(), 0, S.getSourceManager(), S.getLangOpts());
+ SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getLocEnd());
Fixit2 = FixItHint::CreateRemoval(
SourceRange(ElseKwLoc, Else->getLocEnd()));
}
@@ -836,7 +848,6 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
const UninitUse &Use,
bool alwaysReportSelfInit = false) {
-
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) {
// Inspect the initializer of the variable declaration which is
// being referenced prior to its initialization. We emit
@@ -1058,7 +1069,7 @@ namespace {
Sema &S;
llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
};
-}
+} // anonymous namespace
static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
bool PerFunction) {
@@ -1090,8 +1101,7 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
FM.fillReachableBlocks(Cfg);
- for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) {
- const CFGBlock *B = *I;
+ for (const CFGBlock *B : llvm::reverse(*Cfg)) {
const Stmt *Label = B->getLabel();
if (!Label || !isa<SwitchCase>(Label))
@@ -1170,7 +1180,6 @@ static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
return false;
}
-
static void diagnoseRepeatedUseOfWeak(Sema &S,
const sema::FunctionScopeInfo *CurFn,
const Decl *D,
@@ -1330,20 +1339,16 @@ class UninitValsDiagReporter : public UninitVariablesHandler {
// the same as insertion order. This is needed to obtain a deterministic
// order of diagnostics when calling flushDiagnostics().
typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap;
- UsesMap *uses;
+ UsesMap uses;
public:
- UninitValsDiagReporter(Sema &S) : S(S), uses(nullptr) {}
+ UninitValsDiagReporter(Sema &S) : S(S) {}
~UninitValsDiagReporter() override { flushDiagnostics(); }
MappedType &getUses(const VarDecl *vd) {
- if (!uses)
- uses = new UsesMap();
-
- MappedType &V = (*uses)[vd];
+ MappedType &V = uses[vd];
if (!V.getPointer())
V.setPointer(new UsesVec());
-
return V;
}
@@ -1357,10 +1362,7 @@ public:
}
void flushDiagnostics() {
- if (!uses)
- return;
-
- for (const auto &P : *uses) {
+ for (const auto &P : uses) {
const VarDecl *vd = P.first;
const MappedType &V = P.second;
@@ -1401,7 +1403,8 @@ public:
// Release the uses vector.
delete vec;
}
- delete uses;
+
+ uses.clear();
}
private:
@@ -1413,7 +1416,7 @@ private:
});
}
};
-}
+} // anonymous namespace
namespace clang {
namespace {
@@ -1431,7 +1434,8 @@ struct SortDiagBySourceLocation {
return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
}
};
-}}
+} // anonymous namespace
+} // namespace clang
//===----------------------------------------------------------------------===//
// -Wthread-safety
@@ -1670,7 +1674,6 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
Warnings.emplace_back(std::move(Warning), getNotes());
}
-
void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName,
SourceLocation Loc) override {
PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex)
@@ -1696,10 +1699,10 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
}
void leaveFunction(const FunctionDecl* FD) override {
- CurrentFunction = 0;
+ CurrentFunction = nullptr;
}
};
-} // namespace
+} // anonymous namespace
} // namespace threadSafety
} // namespace clang
@@ -1792,7 +1795,9 @@ public:
Warnings.emplace_back(std::move(Warning), OptionalNotes());
}
};
-}}}
+} // anonymous namespace
+} // namespace consumed
+} // namespace clang
//===----------------------------------------------------------------------===//
// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
@@ -1958,7 +1963,6 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
flushDiagnostics(S, fscope);
}
-
// Warning: check missing 'return'
if (P.enableCheckFallThrough) {
const CheckFallThroughDiagnostics &CD =
@@ -2038,7 +2042,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
}
- if (S.getLangOpts().ObjCARCWeak &&
+ if (S.getLangOpts().ObjCWeak &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getLocStart()))
diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());
diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
index 34af6cf..3c61c95 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
@@ -108,6 +109,19 @@ void AttributePool::takePool(AttributeList *pool) {
#include "clang/Sema/AttrParsedAttrKinds.inc"
+static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
+ AttributeList::Syntax SyntaxUsed) {
+ // Normalize the attribute name, __foo__ becomes foo. This is only allowable
+ // for GNU attributes.
+ bool IsGNU = SyntaxUsed == AttributeList::AS_GNU ||
+ (SyntaxUsed == AttributeList::AS_CXX11 && ScopeName == "gnu");
+ if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
+ AttrName.endswith("__"))
+ AttrName = AttrName.slice(2, AttrName.size() - 2);
+
+ return AttrName;
+}
+
AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
const IdentifierInfo *ScopeName,
Syntax SyntaxUsed) {
@@ -117,13 +131,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
if (ScopeName)
FullName += ScopeName->getName();
- // Normalize the attribute name, __foo__ becomes foo. This is only allowable
- // for GNU attributes.
- bool IsGNU = SyntaxUsed == AS_GNU || (SyntaxUsed == AS_CXX11 &&
- FullName == "gnu");
- if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
- AttrName.endswith("__"))
- AttrName = AttrName.slice(2, AttrName.size() - 2);
+ AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
// Ensure that in the case of C++11 attributes, we look for '::foo' if it is
// unscoped.
@@ -137,8 +145,9 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
unsigned AttributeList::getAttributeSpellingListIndex() const {
// Both variables will be used in tablegen generated
// attribute spell list index matching code.
- StringRef Name = AttrName->getName();
StringRef Scope = ScopeName ? ScopeName->getName() : "";
+ StringRef Name = normalizeAttrName(AttrName->getName(), Scope,
+ (AttributeList::Syntax)SyntaxUsed);
#include "clang/Sema/AttrSpellingListIndex.inc"
@@ -155,7 +164,7 @@ struct ParsedAttrInfo {
bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
const Decl *);
bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
- bool (*ExistsInTarget)(const llvm::Triple &T);
+ bool (*ExistsInTarget)(const TargetInfo &Target);
unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
};
@@ -195,8 +204,8 @@ bool AttributeList::isTypeAttr() const {
return getInfo(*this).IsType;
}
-bool AttributeList::existsInTarget(const llvm::Triple &T) const {
- return getInfo(*this).ExistsInTarget(T);
+bool AttributeList::existsInTarget(const TargetInfo &Target) const {
+ return getInfo(*this).ExistsInTarget(Target);
}
bool AttributeList::isKnownToGCC() const {
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
index 4adbb2b..6f6c4ca 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -1,4 +1,4 @@
-//===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===//
+//===--- DeclSpec.cpp - Declaration Specifier Semantic Analysis -----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,29 +15,19 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
#include "clang/Sema/LocInfoType.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/ErrorHandling.h"
#include <cstring>
using namespace clang;
-static DiagnosticBuilder Diag(DiagnosticsEngine &D, SourceLocation Loc,
- unsigned DiagID) {
- return D.Report(Loc, DiagID);
-}
-
-
void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
assert(TemplateId && "NULL template-id annotation?");
Kind = IK_TemplateId;
@@ -177,7 +167,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
SourceLocation MutableLoc,
ExceptionSpecificationType
ESpecType,
- SourceLocation ESpecLoc,
+ SourceRange ESpecRange,
ParsedType *Exceptions,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
@@ -212,7 +202,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Fun.RestrictQualifierLoc = RestrictQualifierLoc.getRawEncoding();
I.Fun.MutableLoc = MutableLoc.getRawEncoding();
I.Fun.ExceptionSpecType = ESpecType;
- I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding();
+ I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding();
+ I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd().getRawEncoding();
I.Fun.NumExceptions = 0;
I.Fun.Exceptions = nullptr;
I.Fun.NoexceptExpr = nullptr;
@@ -279,6 +270,7 @@ bool Declarator::isDeclarationOfFunction() const {
case DeclaratorChunk::Array:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
return false;
}
llvm_unreachable("Invalid type chunk");
@@ -287,6 +279,7 @@ bool Declarator::isDeclarationOfFunction() const {
switch (DS.getTypeSpecType()) {
case TST_atomic:
case TST_auto:
+ case TST_auto_type:
case TST_bool:
case TST_char:
case TST_char16:
@@ -350,6 +343,11 @@ bool Declarator::isStaticMember() {
getName().OperatorFunctionId.Operator));
}
+bool Declarator::isCtorOrDtor() {
+ return (getName().getKind() == UnqualifiedId::IK_ConstructorName) ||
+ (getName().getKind() == UnqualifiedId::IK_DestructorName);
+}
+
bool DeclSpec::hasTagDefinition() const {
if (!TypeSpecOwned)
return false;
@@ -470,6 +468,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
case DeclSpec::TST_typeofType:
case DeclSpec::TST_typeofExpr: return "typeof";
case DeclSpec::TST_auto: return "auto";
+ case DeclSpec::TST_auto_type: return "__auto_type";
case DeclSpec::TST_decltype: return "(decltype)";
case DeclSpec::TST_decltype_auto: return "decltype(auto)";
case DeclSpec::TST_underlyingType: return "__underlying_type";
@@ -508,12 +507,12 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
case SCS_extern:
case SCS_private_extern:
case SCS_static:
- if (S.getLangOpts().OpenCLVersion < 120) {
- DiagID = diag::err_opencl_unknown_type_specifier;
- PrevSpec = getSpecifierName(SC);
- return true;
- }
- break;
+ if (S.getLangOpts().OpenCLVersion < 120) {
+ DiagID = diag::err_opencl_unknown_type_specifier;
+ PrevSpec = getSpecifierName(SC);
+ return true;
+ }
+ break;
case SCS_auto:
case SCS_register:
DiagID = diag::err_opencl_unknown_type_specifier;
@@ -715,6 +714,22 @@ bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
return false;
}
+bool DeclSpec::SetTypePipe(bool isPipe, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy) {
+
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST)TypeSpecType, Policy);
+ DiagID = diag::err_invalid_decl_spec_combination;
+ return true;
+ }
+
+ if (isPipe) {
+ TypeSpecPipe = TSP_pipe;
+ }
+ return false;
+}
+
bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID,
const PrintingPolicy &Policy) {
@@ -925,7 +940,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() {
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
-void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPolicy &Policy) {
+void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
// Before possibly changing their values, save specs as written.
SaveWrittenBuiltinSpecs();
@@ -946,10 +961,10 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
FixItHint Hints[NumLocs];
SourceLocation FirstLoc;
for (unsigned I = 0; I != NumLocs; ++I) {
- if (!ExtraLocs[I].isInvalid()) {
+ if (ExtraLocs[I].isValid()) {
if (FirstLoc.isInvalid() ||
- PP.getSourceManager().isBeforeInTranslationUnit(ExtraLocs[I],
- FirstLoc))
+ S.getSourceManager().isBeforeInTranslationUnit(ExtraLocs[I],
+ FirstLoc))
FirstLoc = ExtraLocs[I];
Hints[I] = FixItHint::CreateRemoval(ExtraLocs[I]);
}
@@ -959,7 +974,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
TypeSpecSign = TSS_unspecified;
TypeAltiVecVector = TypeAltiVecPixel = TypeAltiVecBool = false;
TypeQualifiers = 0;
- Diag(D, TSTLoc, diag::err_decltype_auto_cannot_be_combined)
+ S.Diag(TSTLoc, diag::err_decltype_auto_cannot_be_combined)
<< Hints[0] << Hints[1] << Hints[2] << Hints[3]
<< Hints[4] << Hints[5] << Hints[6] << Hints[7];
}
@@ -969,14 +984,14 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
if (TypeAltiVecBool) {
// Sign specifiers are not allowed with vector bool. (PIM 2.1)
if (TypeSpecSign != TSS_unspecified) {
- Diag(D, TSSLoc, diag::err_invalid_vector_bool_decl_spec)
+ S.Diag(TSSLoc, diag::err_invalid_vector_bool_decl_spec)
<< getSpecifierName((TSS)TypeSpecSign);
}
// Only char/int are valid with vector bool. (PIM 2.1)
if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) &&
(TypeSpecType != TST_int)) || TypeAltiVecPixel) {
- Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec)
+ S.Diag(TSTLoc, diag::err_invalid_vector_bool_decl_spec)
<< (TypeAltiVecPixel ? "__pixel" :
getSpecifierName((TST)TypeSpecType, Policy));
}
@@ -984,15 +999,15 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
// Only 'short' and 'long long' are valid with vector bool. (PIM 2.1)
if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) &&
(TypeSpecWidth != TSW_longlong))
- Diag(D, TSWLoc, diag::err_invalid_vector_bool_decl_spec)
+ S.Diag(TSWLoc, diag::err_invalid_vector_bool_decl_spec)
<< getSpecifierName((TSW)TypeSpecWidth);
// vector bool long long requires VSX support or ZVector.
if ((TypeSpecWidth == TSW_longlong) &&
- (!PP.getTargetInfo().hasFeature("vsx")) &&
- (!PP.getTargetInfo().hasFeature("power8-vector")) &&
- !PP.getLangOpts().ZVector)
- Diag(D, TSTLoc, diag::err_invalid_vector_long_long_decl_spec);
+ (!S.Context.getTargetInfo().hasFeature("vsx")) &&
+ (!S.Context.getTargetInfo().hasFeature("power8-vector")) &&
+ !S.getLangOpts().ZVector)
+ S.Diag(TSTLoc, diag::err_invalid_vector_long_long_decl_spec);
// Elements of vector bool are interpreted as unsigned. (PIM 2.1)
if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) ||
@@ -1002,20 +1017,20 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
// 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)
- Diag(D, TSWLoc, diag::err_invalid_vector_long_double_decl_spec);
- else if (!PP.getTargetInfo().hasFeature("vsx") &&
- !PP.getLangOpts().ZVector)
- Diag(D, TSTLoc, diag::err_invalid_vector_double_decl_spec);
+ S.Diag(TSWLoc, 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 (PP.getLangOpts().ZVector)
- Diag(D, TSTLoc, diag::err_invalid_vector_float_decl_spec);
+ if (S.getLangOpts().ZVector)
+ 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 (PP.getLangOpts().ZVector)
- Diag(D, TSWLoc, diag::err_invalid_vector_long_decl_spec);
+ if (S.getLangOpts().ZVector)
+ S.Diag(TSWLoc, diag::err_invalid_vector_long_decl_spec);
else
- Diag(D, TSWLoc, diag::warn_vector_long_decl_spec_combination)
+ S.Diag(TSWLoc, diag::warn_vector_long_decl_spec_combination)
<< getSpecifierName((TST)TypeSpecType, Policy);
}
@@ -1034,7 +1049,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
- Diag(D, TSSLoc, diag::err_invalid_sign_spec)
+ S.Diag(TSSLoc, diag::err_invalid_sign_spec)
<< getSpecifierName((TST)TypeSpecType, Policy);
// signed double -> double.
TypeSpecSign = TSS_unspecified;
@@ -1049,9 +1064,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
else if (TypeSpecType != TST_int) {
- Diag(D, TSWLoc,
- TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
- : diag::err_invalid_longlong_spec)
+ S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth
<< getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
@@ -1061,7 +1074,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // long -> long int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
- Diag(D, TSWLoc, diag::err_invalid_long_spec)
+ S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth
<< getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
@@ -1073,17 +1086,17 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
// disallow their use. Need information about the backend.
if (TypeSpecComplex != TSC_unspecified) {
if (TypeSpecType == TST_unspecified) {
- Diag(D, TSCLoc, diag::ext_plain_complex)
+ S.Diag(TSCLoc, diag::ext_plain_complex)
<< FixItHint::CreateInsertion(
- PP.getLocForEndOfToken(getTypeSpecComplexLoc()),
+ S.getLocForEndOfToken(getTypeSpecComplexLoc()),
" double");
TypeSpecType = TST_double; // _Complex -> _Complex double.
} else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
// Note that this intentionally doesn't include _Complex _Bool.
- if (!PP.getLangOpts().CPlusPlus)
- Diag(D, TSTLoc, diag::ext_integer_complex);
+ if (!S.getLangOpts().CPlusPlus)
+ S.Diag(TSTLoc, diag::ext_integer_complex);
} else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
- Diag(D, TSCLoc, diag::err_invalid_complex_spec)
+ S.Diag(TSCLoc, diag::err_invalid_complex_spec)
<< getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecComplex = TSC_unspecified;
}
@@ -1100,14 +1113,14 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
case SCS_static:
break;
default:
- if (PP.getSourceManager().isBeforeInTranslationUnit(
+ if (S.getSourceManager().isBeforeInTranslationUnit(
getThreadStorageClassSpecLoc(), getStorageClassSpecLoc()))
- Diag(D, getStorageClassSpecLoc(),
+ S.Diag(getStorageClassSpecLoc(),
diag::err_invalid_decl_spec_combination)
<< DeclSpec::getSpecifierName(getThreadStorageClassSpec())
<< SourceRange(getThreadStorageClassSpecLoc());
else
- Diag(D, getThreadStorageClassSpecLoc(),
+ S.Diag(getThreadStorageClassSpecLoc(),
diag::err_invalid_decl_spec_combination)
<< DeclSpec::getSpecifierName(getStorageClassSpec())
<< SourceRange(getStorageClassSpecLoc());
@@ -1121,7 +1134,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
// the type specifier is not optional, but we got 'auto' as a storage
// class specifier, then assume this is an attempt to use C++0x's 'auto'
// type specifier.
- if (PP.getLangOpts().CPlusPlus &&
+ if (S.getLangOpts().CPlusPlus &&
TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) {
TypeSpecType = TST_auto;
StorageClassSpec = SCS_unspecified;
@@ -1130,17 +1143,17 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
}
// Diagnose if we've recovered from an ill-formed 'auto' storage class
// specifier in a pre-C++11 dialect of C++.
- if (!PP.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto)
- Diag(D, TSTLoc, diag::ext_auto_type_specifier);
- if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus11 &&
+ if (!S.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto)
+ S.Diag(TSTLoc, diag::ext_auto_type_specifier);
+ if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11 &&
StorageClassSpec == SCS_auto)
- Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class)
+ S.Diag(StorageClassSpecLoc, diag::warn_auto_storage_class)
<< FixItHint::CreateRemoval(StorageClassSpecLoc);
if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32)
- Diag(D, TSTLoc, diag::warn_cxx98_compat_unicode_type)
+ S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type)
<< (TypeSpecType == TST_char16 ? "char16_t" : "char32_t");
if (Constexpr_specified)
- Diag(D, ConstexprLoc, diag::warn_cxx98_compat_constexpr);
+ S.Diag(ConstexprLoc, diag::warn_cxx98_compat_constexpr);
// C++ [class.friend]p6:
// No storage-class-specifier shall appear in the decl-specifier-seq
@@ -1164,7 +1177,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
ThreadHint = FixItHint::CreateRemoval(SCLoc);
}
- Diag(D, SCLoc, diag::err_friend_decl_spec)
+ S.Diag(SCLoc, diag::err_friend_decl_spec)
<< SpecName << StorageHint << ThreadHint;
ClearStorageClassSpecs();
@@ -1190,7 +1203,7 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
}
FixItHint Hint = FixItHint::CreateRemoval(SCLoc);
- Diag(D, SCLoc, diag::err_friend_decl_spec)
+ S.Diag(SCLoc, diag::err_friend_decl_spec)
<< Keyword << Hint;
FS_virtual_specified = FS_explicit_specified = false;
diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
index 775fe85..c394d24 100644
--- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp
@@ -147,9 +147,12 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
if (VD->hasLocalStorage()) {
switch (VD->getType().isDestructedType()) {
case QualType::DK_objc_strong_lifetime:
+ return ScopePair(diag::note_protected_by_objc_strong_init,
+ diag::note_exits_objc_strong);
+
case QualType::DK_objc_weak_lifetime:
- return ScopePair(diag::note_protected_by_objc_ownership,
- diag::note_exits_objc_ownership);
+ return ScopePair(diag::note_protected_by_objc_weak_init,
+ diag::note_exits_objc_weak);
case QualType::DK_cxx_destructor:
OutDiag = diag::note_exits_dtor;
diff --git a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index 9ecb5a7..0f93421 100644
--- a/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -107,15 +107,11 @@ void MultiplexExternalSemaSource::completeVisibleDeclsMap(const DeclContext *DC)
Sources[i]->completeVisibleDeclsMap(DC);
}
-ExternalLoadResult MultiplexExternalSemaSource::
-FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Result) {
+void MultiplexExternalSemaSource::FindExternalLexicalDecls(
+ const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Result) {
for(size_t i = 0; i < Sources.size(); ++i)
- // FIXME: The semantics of the return result is unclear to me...
- Sources[i]->FindExternalLexicalDecls(DC, isKindWeWant, Result);
-
- return ELR_Success;
+ Sources[i]->FindExternalLexicalDecls(DC, IsKindWeWant, Result);
}
void MultiplexExternalSemaSource::FindFileRegionDecls(FileID File,
diff --git a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
index f80eadf..cbd7ef7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/ScopeInfo.cpp
@@ -33,11 +33,14 @@ void FunctionScopeInfo::Clear() {
ObjCWarnForNoDesignatedInitChain = false;
ObjCIsSecondaryInit = false;
ObjCWarnForNoInitDelegation = false;
+ FirstReturnLoc = SourceLocation();
FirstCXXTryLoc = SourceLocation();
FirstSEHTryLoc = SourceLocation();
SwitchStack.clear();
Returns.clear();
+ CoroutinePromise = nullptr;
+ CoroutineStmts.clear();
ErrorTrap.reset();
PossiblyUnreachableDiags.clear();
WeakObjectUses.clear();
@@ -234,5 +237,4 @@ void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD,
FunctionScopeInfo::~FunctionScopeInfo() { }
BlockScopeInfo::~BlockScopeInfo() { }
-LambdaScopeInfo::~LambdaScopeInfo() { }
CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { }
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
index 18d7e9d..39b8cc9 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
@@ -40,7 +40,6 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
-#include "llvm/Support/CrashRecoveryContext.h"
using namespace clang;
using namespace sema;
@@ -121,8 +120,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
FieldCollector.reset(new CXXFieldCollector());
// Tell diagnostics how to render things from the AST library.
- PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
- &Context);
+ Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context);
ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, false, nullptr, false);
@@ -139,10 +137,6 @@ void Sema::addImplicitTypedef(StringRef Name, QualType T) {
}
void Sema::Initialize() {
- // Tell the AST consumer about this Sema object.
- Consumer.Initialize(Context);
-
- // FIXME: Isn't this redundant with the initialization above?
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
SC->InitializeSema(*this);
@@ -155,6 +149,9 @@ void Sema::Initialize() {
// will not be able to merge any duplicate __va_list_tag decls correctly.
VAListTagName = PP.getIdentifierInfo("__va_list_tag");
+ if (!TUScope)
+ return;
+
// Initialize predefined 128-bit integer types, if needed.
if (Context.getTargetInfo().hasInt128Type()) {
// If either of the 128-bit integer types are unavailable to name lookup,
@@ -170,7 +167,7 @@ void Sema::Initialize() {
// Initialize predefined Objective-C types:
- if (PP.getLangOpts().ObjC1) {
+ if (getLangOpts().ObjC1) {
// If 'SEL' does not yet refer to any declarations, make it refer to the
// predefined 'SEL'.
DeclarationName SEL = &Context.Idents.get("SEL");
@@ -195,8 +192,8 @@ void Sema::Initialize() {
}
// Initialize Microsoft "predefined C++ types".
- if (PP.getLangOpts().MSVCCompat) {
- if (PP.getLangOpts().CPlusPlus &&
+ if (getLangOpts().MSVCCompat) {
+ if (getLangOpts().CPlusPlus &&
IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end())
PushOnScopeChains(Context.buildImplicitRecord("type_info", TTK_Class),
TUScope);
@@ -205,7 +202,7 @@ void Sema::Initialize() {
}
// Initialize predefined OpenCL types.
- if (PP.getLangOpts().OpenCL) {
+ if (getLangOpts().OpenCL) {
addImplicitTypedef("image1d_t", Context.OCLImage1dTy);
addImplicitTypedef("image1d_array_t", Context.OCLImage1dArrayTy);
addImplicitTypedef("image1d_buffer_t", Context.OCLImage1dBufferTy);
@@ -215,6 +212,18 @@ void Sema::Initialize() {
addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
addImplicitTypedef("event_t", Context.OCLEventTy);
if (getLangOpts().OpenCLVersion >= 200) {
+ addImplicitTypedef("image2d_depth_t", Context.OCLImage2dDepthTy);
+ addImplicitTypedef("image2d_array_depth_t",
+ Context.OCLImage2dArrayDepthTy);
+ addImplicitTypedef("image2d_msaa_t", Context.OCLImage2dMSAATy);
+ addImplicitTypedef("image2d_array_msaa_t", Context.OCLImage2dArrayMSAATy);
+ addImplicitTypedef("image2d_msaa_depth_t", Context.OCLImage2dMSAADepthTy);
+ addImplicitTypedef("image2d_array_msaa_depth_t",
+ Context.OCLImage2dArrayMSAADepthTy);
+ addImplicitTypedef("clk_event_t", Context.OCLClkEventTy);
+ addImplicitTypedef("queue_t", Context.OCLQueueTy);
+ addImplicitTypedef("ndrange_t", Context.OCLNDRangeTy);
+ addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy);
addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
addImplicitTypedef("atomic_uint",
Context.getAtomicType(Context.UnsignedIntTy));
@@ -239,6 +248,12 @@ void Sema::Initialize() {
}
}
+ if (Context.getTargetInfo().hasBuiltinMSVaList()) {
+ DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
+ if (IdResolver.begin(MSVaList) == IdResolver.end())
+ PushOnScopeChains(Context.getBuiltinMSVaListDecl(), TUScope);
+ }
+
DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list");
if (IdResolver.begin(BuiltinVaList) == IdResolver.end())
PushOnScopeChains(Context.getBuiltinVaListDecl(), TUScope);
@@ -280,7 +295,7 @@ Sema::~Sema() {
/// make the relevant declaration unavailable instead of erroring, do
/// so and return true.
bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
- StringRef msg) {
+ UnavailableAttr::ImplicitReason reason) {
// If we're not in a function, it's an error.
FunctionDecl *fn = dyn_cast<FunctionDecl>(CurContext);
if (!fn) return false;
@@ -296,7 +311,7 @@ bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
// If the function is already unavailable, it's not an error.
if (fn->hasAttr<UnavailableAttr>()) return true;
- fn->addAttr(UnavailableAttr::CreateImplicit(Context, msg, loc));
+ fn->addAttr(UnavailableAttr::CreateImplicit(Context, "", reason, loc));
return true;
}
@@ -334,6 +349,20 @@ void Sema::PrintStats() const {
AnalysisWarnings.PrintStats();
}
+void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
+ QualType SrcType,
+ SourceLocation Loc) {
+ Optional<NullabilityKind> ExprNullability = SrcType->getNullability(Context);
+ if (!ExprNullability || *ExprNullability != NullabilityKind::Nullable)
+ return;
+
+ Optional<NullabilityKind> TypeNullability = DstType->getNullability(Context);
+ if (!TypeNullability || *TypeNullability != NullabilityKind::NonNull)
+ return;
+
+ Diag(Loc, diag::warn_nullability_lost) << SrcType << DstType;
+}
+
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
/// If there is already an implicit cast, merge into the existing one.
/// The result is of the given category.
@@ -357,18 +386,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
assert((VK == VK_RValue || !E->isRValue()) && "can't cast rvalue to lvalue");
#endif
- // Check whether we're implicitly casting from a nullable type to a nonnull
- // type.
- if (auto exprNullability = E->getType()->getNullability(Context)) {
- if (*exprNullability == NullabilityKind::Nullable) {
- if (auto typeNullability = Ty->getNullability(Context)) {
- if (*typeNullability == NullabilityKind::NonNull) {
- Diag(E->getLocStart(), diag::warn_nullability_lost)
- << E->getType() << Ty;
- }
- }
- }
- }
+ diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getLocStart());
QualType ExprTy = Context.getCanonicalType(E->getType());
QualType TypeTy = Context.getCanonicalType(Ty);
@@ -689,6 +707,9 @@ void Sema::ActOnEndOfTranslationUnit() {
assert(DelayedDefaultedMemberExceptionSpecs.empty());
assert(DelayedExceptionSpecChecks.empty());
+ // All dllexport classes should have been processed already.
+ assert(DelayedDllExportClasses.empty());
+
// Remove file scoped decls that turned out to be used.
UnusedFileScopedDecls.erase(
std::remove_if(UnusedFileScopedDecls.begin(nullptr, true),
@@ -708,8 +729,15 @@ void Sema::ActOnEndOfTranslationUnit() {
if (WeakID.second.getUsed())
continue;
- Diag(WeakID.second.getLocation(), diag::warn_weak_identifier_undeclared)
- << WeakID.first;
+ Decl *PrevDecl = LookupSingleName(TUScope, WeakID.first, SourceLocation(),
+ LookupOrdinaryName);
+ if (PrevDecl != nullptr &&
+ !(isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl)))
+ Diag(WeakID.second.getLocation(), diag::warn_attribute_wrong_decl_type)
+ << "'weak'" << ExpectedVariableOrFunction;
+ else
+ Diag(WeakID.second.getLocation(), diag::warn_weak_identifier_undeclared)
+ << WeakID.first;
}
if (LangOpts.CPlusPlus11 &&
@@ -1443,7 +1471,7 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
// arguments and that it returns something of a reasonable type,
// so we can emit a fixit and carry on pretending that E was
// actually a CallExpr.
- SourceLocation ParenInsertionLoc = PP.getLocForEndOfToken(Range.getEnd());
+ SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
Diag(Loc, PD)
<< /*zero-arg*/ 1 << Range
<< (IsCallableWithAppend(E.get())
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
index 0e973cc..e9772bc 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp
@@ -182,15 +182,20 @@ struct AccessTarget : public AccessedEntity {
class SavedInstanceContext {
public:
+ SavedInstanceContext(SavedInstanceContext &&S)
+ : Target(S.Target), Has(S.Has) {
+ S.Target = nullptr;
+ }
~SavedInstanceContext() {
- Target.HasInstanceContext = Has;
+ if (Target)
+ Target->HasInstanceContext = Has;
}
private:
friend struct AccessTarget;
explicit SavedInstanceContext(AccessTarget &Target)
- : Target(Target), Has(Target.HasInstanceContext) {}
- AccessTarget &Target;
+ : Target(&Target), Has(Target.HasInstanceContext) {}
+ AccessTarget *Target;
bool Has;
};
@@ -1766,7 +1771,7 @@ Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {
case AR_inaccessible: return Sema::AR_inaccessible;
case AR_dependent: return Sema::AR_dependent;
}
- llvm_unreachable("falling off end");
+ llvm_unreachable("invalid access result");
}
Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
index 5973500..61dfdd3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCUDA.cpp
@@ -60,8 +60,101 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
return CFT_Host;
}
+// * CUDA Call preference table
+//
+// F - from,
+// T - to
+// Ph - preference in host mode
+// Pd - preference in device mode
+// H - handled in (x)
+// Preferences: b-best, f-fallback, l-last resort, n-never.
+//
+// | F | T | Ph | Pd | H |
+// |----+----+----+----+-----+
+// | d | d | b | b | (b) |
+// | d | g | n | n | (a) |
+// | d | h | l | l | (e) |
+// | d | hd | f | f | (c) |
+// | g | d | b | b | (b) |
+// | g | g | n | n | (a) |
+// | g | h | l | l | (e) |
+// | g | hd | f | f | (c) |
+// | h | d | l | l | (e) |
+// | h | g | b | b | (b) |
+// | h | h | b | b | (b) |
+// | h | hd | f | f | (c) |
+// | hd | d | l | f | (d) |
+// | hd | g | f | n |(d/a)|
+// | hd | h | f | l | (d) |
+// | hd | hd | b | b | (b) |
+
+Sema::CUDAFunctionPreference
+Sema::IdentifyCUDAPreference(const FunctionDecl *Caller,
+ const FunctionDecl *Callee) {
+ assert(getLangOpts().CUDATargetOverloads &&
+ "Should not be called w/o enabled target overloads.");
+
+ assert(Callee && "Callee must be valid.");
+ CUDAFunctionTarget CalleeTarget = IdentifyCUDATarget(Callee);
+ CUDAFunctionTarget CallerTarget =
+ (Caller != nullptr) ? IdentifyCUDATarget(Caller) : Sema::CFT_Host;
+
+ // If one of the targets is invalid, the check always fails, no matter what
+ // the other target is.
+ if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget)
+ return CFP_Never;
+
+ // (a) Can't call global from some contexts until we support CUDA's
+ // dynamic parallelism.
+ if (CalleeTarget == CFT_Global &&
+ (CallerTarget == CFT_Global || CallerTarget == CFT_Device ||
+ (CallerTarget == CFT_HostDevice && getLangOpts().CUDAIsDevice)))
+ return CFP_Never;
+
+ // (b) Best case scenarios
+ if (CalleeTarget == CallerTarget ||
+ (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) ||
+ (CallerTarget == CFT_Global && CalleeTarget == CFT_Device))
+ return CFP_Best;
+
+ // (c) Calling HostDevice is OK as a fallback that works for everyone.
+ if (CalleeTarget == CFT_HostDevice)
+ return CFP_Fallback;
+
+ // Figure out what should be returned 'last resort' cases. Normally
+ // those would not be allowed, but we'll consider them if
+ // CUDADisableTargetCallChecks is true.
+ CUDAFunctionPreference QuestionableResult =
+ getLangOpts().CUDADisableTargetCallChecks ? CFP_LastResort : CFP_Never;
+
+ // (d) HostDevice behavior depends on compilation mode.
+ if (CallerTarget == CFT_HostDevice) {
+ // Calling a function that matches compilation mode is OK.
+ // Calling a function from the other side is frowned upon.
+ if (getLangOpts().CUDAIsDevice)
+ return CalleeTarget == CFT_Device ? CFP_Fallback : QuestionableResult;
+ else
+ return (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global)
+ ? CFP_Fallback
+ : QuestionableResult;
+ }
+
+ // (e) Calling across device/host boundary is not something you should do.
+ if ((CallerTarget == CFT_Host && CalleeTarget == CFT_Device) ||
+ (CallerTarget == CFT_Device && CalleeTarget == CFT_Host) ||
+ (CallerTarget == CFT_Global && CalleeTarget == CFT_Host))
+ return QuestionableResult;
+
+ llvm_unreachable("All cases should've been handled by now.");
+}
+
bool Sema::CheckCUDATarget(const FunctionDecl *Caller,
const FunctionDecl *Callee) {
+ // With target overloads enabled, we only disallow calling
+ // combinations with CFP_Never.
+ if (getLangOpts().CUDATargetOverloads)
+ return IdentifyCUDAPreference(Caller,Callee) == CFP_Never;
+
// The CUDADisableTargetCallChecks short-circuits this check: we assume all
// cross-target calls are valid.
if (getLangOpts().CUDADisableTargetCallChecks)
@@ -117,6 +210,57 @@ bool Sema::CheckCUDATarget(const FunctionDecl *Caller,
return false;
}
+template <typename T, typename FetchDeclFn>
+static void EraseUnwantedCUDAMatchesImpl(Sema &S, const FunctionDecl *Caller,
+ llvm::SmallVectorImpl<T> &Matches,
+ FetchDeclFn FetchDecl) {
+ assert(S.getLangOpts().CUDATargetOverloads &&
+ "Should not be called w/o enabled target overloads.");
+ if (Matches.size() <= 1)
+ return;
+
+ // Find the best call preference among the functions in Matches.
+ Sema::CUDAFunctionPreference P, BestCFP = Sema::CFP_Never;
+ for (auto const &Match : Matches) {
+ P = S.IdentifyCUDAPreference(Caller, FetchDecl(Match));
+ if (P > BestCFP)
+ BestCFP = P;
+ }
+
+ // Erase all functions with lower priority.
+ for (unsigned I = 0, N = Matches.size(); I != N;)
+ if (S.IdentifyCUDAPreference(Caller, FetchDecl(Matches[I])) < BestCFP) {
+ Matches[I] = Matches[--N];
+ Matches.resize(N);
+ } else {
+ ++I;
+ }
+}
+
+void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
+ SmallVectorImpl<FunctionDecl *> &Matches){
+ EraseUnwantedCUDAMatchesImpl<FunctionDecl *>(
+ *this, Caller, Matches, [](const FunctionDecl *item) { return item; });
+}
+
+void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
+ SmallVectorImpl<DeclAccessPair> &Matches) {
+ EraseUnwantedCUDAMatchesImpl<DeclAccessPair>(
+ *this, Caller, Matches, [](const DeclAccessPair &item) {
+ return dyn_cast<FunctionDecl>(item.getDecl());
+ });
+}
+
+void Sema::EraseUnwantedCUDAMatches(
+ const FunctionDecl *Caller,
+ SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches){
+ EraseUnwantedCUDAMatchesImpl<std::pair<DeclAccessPair, FunctionDecl *>>(
+ *this, Caller, Matches,
+ [](const std::pair<DeclAccessPair, FunctionDecl *> &item) {
+ return dyn_cast<FunctionDecl>(item.second);
+ });
+}
+
/// When an implicitly-declared special member has to invoke more than one
/// base/field special member, conflicts may occur in the targets of these
/// members. For example, if one base's member __host__ and another's is
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 9e146ed..f7aace6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -291,8 +291,10 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD,
if (!SD)
return false;
+ SD = SD->getUnderlyingDecl();
+
// Namespace and namespace aliases are fine.
- if (isa<NamespaceDecl>(SD) || isa<NamespaceAliasDecl>(SD))
+ if (isa<NamespaceDecl>(SD))
return true;
if (!isa<TypeDecl>(SD))
@@ -396,10 +398,7 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
}
Found.suppressDiagnostics();
- if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
- return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
-
- return false;
+ return Found.getAsSingle<NamespaceDecl>();
}
namespace {
@@ -533,6 +532,9 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
LookupName(Found, S);
}
+ if (Found.isAmbiguous())
+ return true;
+
// If we performed lookup into a dependent context and did not find anything,
// that's fine: just build a dependent nested-name-specifier.
if (Found.empty() && isDependent &&
@@ -551,8 +553,6 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
return false;
}
- // FIXME: Deal with ambiguities cleanly.
-
if (Found.empty() && !ErrorRecoveryLookup) {
// If identifier is not found as class-name-or-namespace-name, but is found
// as other entity, don't look for typos.
@@ -562,6 +562,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
else if (S && !isDependent)
LookupName(R, S);
if (!R.empty()) {
+ // Don't diagnose problems with this speculative lookup.
+ R.suppressDiagnostics();
// The identifier is found in ordinary lookup. If correction to colon is
// allowed, suggest replacement to ':'.
if (IsCorrectedToColon) {
@@ -604,7 +606,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
<< Name);
- if (NamedDecl *ND = Corrected.getCorrectionDecl())
+ if (NamedDecl *ND = Corrected.getFoundDecl())
Found.addDecl(ND);
Found.setLookupName(Corrected.getCorrection());
} else {
@@ -612,7 +614,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
}
}
- NamedDecl *SD = Found.getAsSingle<NamedDecl>();
+ NamedDecl *SD =
+ Found.isSingleResult() ? Found.getRepresentativeDecl() : nullptr;
bool IsExtension = false;
bool AcceptSpec = isAcceptableNestedNameSpecifier(SD, &IsExtension);
if (!AcceptSpec && IsExtension) {
@@ -684,7 +687,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
return false;
}
- QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
+ QualType T =
+ Context.getTypeDeclType(cast<TypeDecl>(SD->getUnderlyingDecl()));
TypeLocBuilder TLB;
if (isa<InjectedClassNameType>(T)) {
InjectedClassNameTypeLoc InjectedTL
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
index c0754ba..ad1d7da 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
@@ -160,19 +160,19 @@ static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
unsigned &msg);
static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
QualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg,
CastKind &Kind,
CXXCastPath &BasePath);
static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType,
QualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg,
CastKind &Kind,
CXXCastPath &BasePath);
static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
CanQualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
QualType OrigSrcType,
QualType OrigDestType, unsigned &msg,
CastKind &Kind,
@@ -180,7 +180,7 @@ static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr,
QualType SrcType,
QualType DestType,bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg,
CastKind &Kind,
CXXCastPath &BasePath);
@@ -188,13 +188,13 @@ static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExp
static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType,
Sema::CheckedConversionKind CCK,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg, CastKind &Kind,
bool ListInitialization);
static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType,
Sema::CheckedConversionKind CCK,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg, CastKind &Kind,
CXXCastPath &BasePath,
bool ListInitialization);
@@ -203,7 +203,7 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
unsigned &msg);
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg,
CastKind &Kind);
@@ -489,9 +489,9 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
QualType *TheOffendingDestType = nullptr,
Qualifiers *CastAwayQualifiers = nullptr) {
// If the only checking we care about is for Objective-C lifetime qualifiers,
- // and we're not in ARC mode, there's nothing to check.
+ // and we're not in ObjC mode, there's nothing to check.
if (!CheckCVR && CheckObjCLifetime &&
- !Self.Context.getLangOpts().ObjCAutoRefCount)
+ !Self.Context.getLangOpts().ObjC1)
return false;
// Casting away constness is defined in C++ 5.2.11p8 with reference to
@@ -683,7 +683,8 @@ void CastOperation::CheckDynamicCast() {
// C++ 5.2.7p5
// Upcasts are resolved statically.
- if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) {
+ if (DestRecord &&
+ Self.IsDerivedFrom(OpRange.getBegin(), SrcPointee, DestPointee)) {
if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee,
OpRange.getBegin(), OpRange,
&BasePath)) {
@@ -943,7 +944,7 @@ void CastOperation::CheckStaticCast() {
static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType,
Sema::CheckedConversionKind CCK,
- const SourceRange &OpRange, unsigned &msg,
+ SourceRange OpRange, unsigned &msg,
CastKind &Kind, CXXCastPath &BasePath,
bool ListInitialization) {
// Determine whether we have the semantics of a C-style cast.
@@ -1171,7 +1172,8 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
Kind = CK_DerivedToBase;
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
- if (!Self.IsDerivedFrom(SrcExpr->getType(), R->getPointeeType(), Paths))
+ if (!Self.IsDerivedFrom(SrcExpr->getLocStart(), SrcExpr->getType(),
+ R->getPointeeType(), Paths))
return TC_NotApplicable;
Self.BuildBasePathArray(Paths, BasePath);
@@ -1184,7 +1186,7 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
/// Tests whether a conversion according to C++ 5.2.9p5 is valid.
TryCastResult
TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
- bool CStyle, const SourceRange &OpRange,
+ bool CStyle, SourceRange OpRange,
unsigned &msg, CastKind &Kind,
CXXCastPath &BasePath) {
// C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be
@@ -1222,7 +1224,7 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
/// Tests whether a conversion according to C++ 5.2.9p8 is valid.
TryCastResult
TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
- bool CStyle, const SourceRange &OpRange,
+ bool CStyle, SourceRange OpRange,
unsigned &msg, CastKind &Kind,
CXXCastPath &BasePath) {
// C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class
@@ -1256,12 +1258,12 @@ TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
/// DestType is possible and allowed.
TryCastResult
TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
- bool CStyle, const SourceRange &OpRange, QualType OrigSrcType,
+ bool CStyle, SourceRange OpRange, QualType OrigSrcType,
QualType OrigDestType, unsigned &msg,
CastKind &Kind, CXXCastPath &BasePath) {
// We can only work with complete types. But don't complain if it doesn't work
- if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0) ||
- Self.RequireCompleteType(OpRange.getBegin(), DestType, 0))
+ if (!Self.isCompleteType(OpRange.getBegin(), SrcType) ||
+ !Self.isCompleteType(OpRange.getBegin(), DestType))
return TC_NotApplicable;
// Downcast can only happen in class hierarchies, so we need classes.
@@ -1271,7 +1273,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
- if (!Self.IsDerivedFrom(DestType, SrcType, Paths)) {
+ if (!Self.IsDerivedFrom(OpRange.getBegin(), DestType, SrcType, Paths)) {
return TC_NotApplicable;
}
@@ -1307,7 +1309,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
if (!Paths.isRecordingPaths()) {
Paths.clear();
Paths.setRecordingPaths(true);
- Self.IsDerivedFrom(DestType, SrcType, Paths);
+ Self.IsDerivedFrom(OpRange.getBegin(), DestType, SrcType, Paths);
}
std::string PathDisplayStr;
std::set<unsigned> DisplayedPaths;
@@ -1372,7 +1374,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
TryCastResult
TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
QualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg, CastKind &Kind,
CXXCastPath &BasePath) {
const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
@@ -1398,6 +1400,11 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
return TC_NotApplicable;
}
+ // Lock down the inheritance model right now in MS ABI, whether or not the
+ // pointee types are the same.
+ if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft())
+ (void)Self.isCompleteType(OpRange.getBegin(), SrcType);
+
// T == T, modulo cv
if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(),
DestMemPtr->getPointeeType()))
@@ -1408,16 +1415,15 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
QualType DestClass(DestMemPtr->getClass(), 0);
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
- if (Self.RequireCompleteType(OpRange.getBegin(), SrcClass, 0) ||
- !Self.IsDerivedFrom(SrcClass, DestClass, Paths)) {
+ if (!Self.IsDerivedFrom(OpRange.getBegin(), SrcClass, DestClass, Paths))
return TC_NotApplicable;
- }
// B is a base of D. But is it an allowed base? If not, it's a hard error.
if (Paths.isAmbiguous(Self.Context.getCanonicalType(DestClass))) {
Paths.clear();
Paths.setRecordingPaths(true);
- bool StillOkay = Self.IsDerivedFrom(SrcClass, DestClass, Paths);
+ bool StillOkay =
+ Self.IsDerivedFrom(OpRange.getBegin(), SrcClass, DestClass, Paths);
assert(StillOkay);
(void)StillOkay;
std::string PathDisplayStr = Self.getAmbiguousPathsDisplayString(Paths);
@@ -1484,7 +1490,7 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
TryCastResult
TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
Sema::CheckedConversionKind CCK,
- const SourceRange &OpRange, unsigned &msg,
+ SourceRange OpRange, unsigned &msg,
CastKind &Kind, bool ListInitialization) {
if (DestType->isRecordType()) {
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
@@ -1494,10 +1500,6 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
msg = 0;
return TC_Failed;
}
- } else if (DestType->isMemberPointerType()) {
- if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
- }
}
InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
@@ -1750,7 +1752,7 @@ static void checkIntToPointerCast(bool CStyle, SourceLocation Loc,
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
- const SourceRange &OpRange,
+ SourceRange OpRange,
unsigned &msg,
CastKind &Kind) {
bool IsLValueCast = false;
@@ -1845,8 +1847,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
// We need to determine the inheritance model that the class will use if
// haven't yet.
- Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0);
- Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
+ (void)Self.isCompleteType(OpRange.getBegin(), SrcType);
+ (void)Self.isCompleteType(OpRange.getBegin(), DestType);
}
// Don't allow casting between member pointers of different sizes.
@@ -1877,28 +1879,29 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
return TC_Success;
}
+ // Allow reinterpret_casts between vectors of the same size and
+ // between vectors and integers of the same size.
bool destIsVector = DestType->isVectorType();
bool srcIsVector = SrcType->isVectorType();
if (srcIsVector || destIsVector) {
- // FIXME: Should this also apply to floating point types?
- bool srcIsScalar = SrcType->isIntegralType(Self.Context);
- bool destIsScalar = DestType->isIntegralType(Self.Context);
-
- // Check if this is a cast between a vector and something else.
- if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) &&
- !(srcIsVector && destIsVector))
+ // The non-vector type, if any, must have integral type. This is
+ // the same rule that C vector casts use; note, however, that enum
+ // types are not integral in C++.
+ if ((!destIsVector && !DestType->isIntegralType(Self.Context)) ||
+ (!srcIsVector && !SrcType->isIntegralType(Self.Context)))
return TC_NotApplicable;
- // If both types have the same size, we can successfully cast.
- if (Self.Context.getTypeSize(SrcType)
- == Self.Context.getTypeSize(DestType)) {
+ // The size we want to consider is eltCount * eltSize.
+ // That's exactly what the lax-conversion rules will check.
+ if (Self.areLaxCompatibleVectorTypes(SrcType, DestType)) {
Kind = CK_BitCast;
return TC_Success;
}
-
- if (destIsScalar)
+
+ // Otherwise, pick a reasonable diagnostic.
+ if (!destIsVector)
msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
- else if (srcIsScalar)
+ else if (!srcIsVector)
msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size;
else
msg = diag::err_bad_cxx_cast_vector_to_vector_different_size;
@@ -2102,6 +2105,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
&& (SrcExpr.get()->getType()->isIntegerType()
|| SrcExpr.get()->getType()->isFloatingType())) {
Kind = CK_VectorSplat;
+ SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get());
return;
}
@@ -2237,6 +2241,16 @@ void CastOperation::CheckCStyleCast() {
return;
}
+ // Overloads are allowed with C extensions, so we need to support them.
+ if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
+ DeclAccessPair DAP;
+ if (FunctionDecl *FD = Self.ResolveAddressOfOverloadedFunction(
+ SrcExpr.get(), DestType, /*Complain=*/true, DAP))
+ SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD);
+ else
+ return;
+ assert(SrcExpr.isUsable());
+ }
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
if (SrcExpr.isInvalid())
return;
@@ -2326,6 +2340,7 @@ void CastOperation::CheckCStyleCast() {
if (DestVecTy->getVectorKind() == VectorType::AltiVecVector &&
(SrcType->isIntegerType() || SrcType->isFloatingType())) {
Kind = CK_VectorSplat;
+ SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get());
} else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) {
SrcExpr = ExprError();
}
@@ -2480,8 +2495,11 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false);
if (Op.SrcExpr.isInvalid())
return ExprError();
-
- if (CXXConstructExpr *ConstructExpr = dyn_cast<CXXConstructExpr>(Op.SrcExpr.get()))
+
+ auto *SubExpr = Op.SrcExpr.get();
+ if (auto *BindExpr = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
+ SubExpr = BindExpr->getSubExpr();
+ if (auto *ConstructExpr = dyn_cast<CXXConstructExpr>(SubExpr))
ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc));
return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index 1a8ab6e..6c2834b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/Analyses/FormatString.h"
@@ -111,6 +112,39 @@ static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) {
return false;
}
+static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) {
+ if (checkArgCount(S, TheCall, 3))
+ return true;
+
+ // First two arguments should be integers.
+ for (unsigned I = 0; I < 2; ++I) {
+ Expr *Arg = TheCall->getArg(I);
+ QualType Ty = Arg->getType();
+ if (!Ty->isIntegerType()) {
+ S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_int)
+ << Ty << Arg->getSourceRange();
+ return true;
+ }
+ }
+
+ // Third argument should be a pointer to a non-const integer.
+ // IRGen correctly handles volatile, restrict, and address spaces, and
+ // the other qualifiers aren't possible.
+ {
+ Expr *Arg = TheCall->getArg(2);
+ QualType Ty = Arg->getType();
+ const auto *PtrTy = Ty->getAs<PointerType>();
+ if (!(PtrTy && PtrTy->getPointeeType()->isIntegerType() &&
+ !PtrTy->getPointeeType().isConstQualified())) {
+ S.Diag(Arg->getLocStart(), diag::err_overflow_builtin_must_be_ptr_int)
+ << Ty << Arg->getSourceRange();
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl,
CallExpr *TheCall, unsigned SizeIdx,
unsigned DstSizeIdx) {
@@ -440,6 +474,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__sync_swap_8:
case Builtin::BI__sync_swap_16:
return SemaBuiltinAtomicOverloaded(TheCallResult);
+ case Builtin::BI__builtin_nontemporal_load:
+ case Builtin::BI__builtin_nontemporal_store:
+ return SemaBuiltinNontemporalOverloaded(TheCallResult);
#define BUILTIN(ID, TYPE, ATTRS)
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
case Builtin::BI##ID: \
@@ -453,6 +490,12 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (SemaBuiltinAddressof(*this, TheCall))
return ExprError();
break;
+ case Builtin::BI__builtin_add_overflow:
+ case Builtin::BI__builtin_sub_overflow:
+ case Builtin::BI__builtin_mul_overflow:
+ if (SemaBuiltinOverflow(*this, TheCall))
+ return ExprError();
+ break;
case Builtin::BI__builtin_operator_new:
case Builtin::BI__builtin_operator_delete:
if (!getLangOpts().CPlusPlus) {
@@ -525,7 +568,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
// Since the target specific builtins for each arch overlap, only check those
// of the arch we are compiling for.
- if (BuiltinID >= Builtin::FirstTSBuiltin) {
+ if (Context.BuiltinInfo.isTSBuiltin(BuiltinID)) {
switch (Context.getTargetInfo().getTriple().getArch()) {
case llvm::Triple::arm:
case llvm::Triple::armeb:
@@ -1027,12 +1070,34 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
+/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *).
+/// This checks that the target supports __builtin_cpu_supports and
+/// that the string argument is constant and valid.
+static bool SemaBuiltinCpuSupports(Sema &S, CallExpr *TheCall) {
+ Expr *Arg = TheCall->getArg(0);
+
+ // Check if the argument is a string literal.
+ if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
+ return S.Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
+ << Arg->getSourceRange();
+
+ // Check the contents of the string.
+ StringRef Feature =
+ cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
+ if (!S.Context.getTargetInfo().validateCpuSupports(Feature))
+ return S.Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports)
+ << Arg->getSourceRange();
+ return false;
+}
+
bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
switch (BuiltinID) {
default: return false;
case X86::BI__builtin_cpu_supports:
- return SemaBuiltinCpuSupports(TheCall);
+ return SemaBuiltinCpuSupports(*this, TheCall);
+ case X86::BI__builtin_ms_va_start:
+ return SemaBuiltinMSVAStart(TheCall);
case X86::BI_mm_prefetch: i = 1; l = 0; u = 3; break;
case X86::BI__builtin_ia32_sha1rnds4: i = 2, l = 0; u = 3; break;
case X86::BI__builtin_ia32_vpermil2pd:
@@ -1115,8 +1180,7 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
/// Checks if a the given expression evaluates to null.
///
/// \brief Returns true if the value evaluates to null.
-static bool CheckNonNullExpr(Sema &S,
- const Expr *Expr) {
+static bool CheckNonNullExpr(Sema &S, const Expr *Expr) {
// If the expression has non-null type, it doesn't evaluate to null.
if (auto nullability
= Expr->IgnoreImplicit()->getType()->getNullability(S.Context)) {
@@ -1145,7 +1209,8 @@ static void CheckNonNullArgument(Sema &S,
const Expr *ArgExpr,
SourceLocation CallSiteLoc) {
if (CheckNonNullExpr(S, ArgExpr))
- S.Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
+ S.DiagRuntimeBehavior(CallSiteLoc, ArgExpr,
+ S.PDiag(diag::warn_null_arg) << ArgExpr->getSourceRange());
}
bool Sema::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) {
@@ -1638,6 +1703,12 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
return ExprError();
}
ValType = AtomTy->getAs<AtomicType>()->getValueType();
+ } else if (Form != Load && Op != AtomicExpr::AO__atomic_load) {
+ if (ValType.isConstQualified()) {
+ Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_pointer)
+ << Ptr->getType() << Ptr->getSourceRange();
+ return ExprError();
+ }
}
// For an arithmetic operation, the implied arithmetic must be well-formed.
@@ -1675,9 +1746,6 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
return ExprError();
}
- // FIXME: For any builtin other than a load, the ValType must not be
- // const-qualified.
-
switch (ValType.getObjCLifetime()) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
@@ -1710,6 +1778,10 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
if (!IsC11 && !IsN)
ByValType = Ptr->getType();
+ // FIXME: __atomic_load allows the first argument to be a a pointer to const
+ // but not the second argument. We need to manually remove possible const
+ // qualifiers.
+
// The first argument --- the pointer --- has a fixed type; we
// deduce the types of the rest of the arguments accordingly. Walk
// the remaining arguments, converting them to the deduced value type.
@@ -1729,8 +1801,17 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
Ty = ByValType;
else if (Form == Arithmetic)
Ty = Context.getPointerDiffType();
- else
- Ty = Context.getPointerType(ValType.getUnqualifiedType());
+ else {
+ Expr *ValArg = TheCall->getArg(i);
+ unsigned AS = 0;
+ // Keep address space of non-atomic pointer type.
+ if (const PointerType *PtrTy =
+ ValArg->getType()->getAs<PointerType>()) {
+ AS = PtrTy->getPointeeType().getAddressSpace();
+ }
+ Ty = Context.getPointerType(
+ Context.getAddrSpaceQualType(ValType.getUnqualifiedType(), AS));
+ }
break;
case 2:
// The third argument to compare_exchange / GNU exchange is a
@@ -2142,7 +2223,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// Get the decl for the concrete builtin from this, we can tell what the
// concrete integer type we should convert to is.
unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
- const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID);
+ const char *NewBuiltinName = Context.BuiltinInfo.getName(NewBuiltinID);
FunctionDecl *NewBuiltinDecl;
if (NewBuiltinID == BuiltinID)
NewBuiltinDecl = FDecl;
@@ -2209,6 +2290,78 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
return TheCallResult;
}
+/// SemaBuiltinNontemporalOverloaded - We have a call to
+/// __builtin_nontemporal_store or __builtin_nontemporal_load, which is an
+/// overloaded function based on the pointer type of its last argument.
+///
+/// This function goes through and does final semantic checking for these
+/// builtins.
+ExprResult Sema::SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult) {
+ CallExpr *TheCall = (CallExpr *)TheCallResult.get();
+ DeclRefExpr *DRE =
+ cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
+ FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
+ unsigned BuiltinID = FDecl->getBuiltinID();
+ assert((BuiltinID == Builtin::BI__builtin_nontemporal_store ||
+ BuiltinID == Builtin::BI__builtin_nontemporal_load) &&
+ "Unexpected nontemporal load/store builtin!");
+ bool isStore = BuiltinID == Builtin::BI__builtin_nontemporal_store;
+ unsigned numArgs = isStore ? 2 : 1;
+
+ // Ensure that we have the proper number of arguments.
+ if (checkArgCount(*this, TheCall, numArgs))
+ return ExprError();
+
+ // Inspect the last argument of the nontemporal builtin. This should always
+ // be a pointer type, from which we imply the type of the memory access.
+ // Because it is a pointer type, we don't have to worry about any implicit
+ // casts here.
+ Expr *PointerArg = TheCall->getArg(numArgs - 1);
+ ExprResult PointerArgResult =
+ DefaultFunctionArrayLvalueConversion(PointerArg);
+
+ if (PointerArgResult.isInvalid())
+ return ExprError();
+ PointerArg = PointerArgResult.get();
+ TheCall->setArg(numArgs - 1, PointerArg);
+
+ const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
+ if (!pointerType) {
+ Diag(DRE->getLocStart(), diag::err_nontemporal_builtin_must_be_pointer)
+ << PointerArg->getType() << PointerArg->getSourceRange();
+ return ExprError();
+ }
+
+ QualType ValType = pointerType->getPointeeType();
+
+ // Strip any qualifiers off ValType.
+ ValType = ValType.getUnqualifiedType();
+ if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
+ !ValType->isBlockPointerType() && !ValType->isFloatingType() &&
+ !ValType->isVectorType()) {
+ Diag(DRE->getLocStart(),
+ diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector)
+ << PointerArg->getType() << PointerArg->getSourceRange();
+ return ExprError();
+ }
+
+ if (!isStore) {
+ TheCall->setType(ValType);
+ return TheCallResult;
+ }
+
+ ExprResult ValArg = TheCall->getArg(0);
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, ValType, /*consume*/ false);
+ ValArg = PerformCopyInitialization(Entity, SourceLocation(), ValArg);
+ if (ValArg.isInvalid())
+ return ExprError();
+
+ TheCall->setArg(0, ValArg.get());
+ TheCall->setType(Context.VoidTy);
+ return TheCallResult;
+}
+
/// CheckObjCString - Checks that the argument to the builtin
/// CFString constructor is correct
/// Note: It might also make sense to do the UTF-16 conversion here (would
@@ -2241,9 +2394,10 @@ bool Sema::CheckObjCString(Expr *Arg) {
return false;
}
-/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity.
-/// Emit an error and return true on failure, return false on success.
-bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
+/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start'
+/// for validity. Emit an error and return true on failure; return false
+/// on success.
+bool Sema::SemaBuiltinVAStartImpl(CallExpr *TheCall) {
Expr *Fn = TheCall->getCallee();
if (TheCall->getNumArgs() > 2) {
Diag(TheCall->getArg(2)->getLocStart(),
@@ -2321,6 +2475,48 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
return false;
}
+/// Check the arguments to '__builtin_va_start' for validity, and that
+/// it was called from a function of the native ABI.
+/// Emit an error and return true on failure; return false on success.
+bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
+ // On x86-64 Unix, don't allow this in Win64 ABI functions.
+ // On x64 Windows, don't allow this in System V ABI functions.
+ // (Yes, that means there's no corresponding way to support variadic
+ // System V ABI functions on Windows.)
+ if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64) {
+ unsigned OS = Context.getTargetInfo().getTriple().getOS();
+ clang::CallingConv CC = CC_C;
+ if (const FunctionDecl *FD = getCurFunctionDecl())
+ CC = FD->getType()->getAs<FunctionType>()->getCallConv();
+ if ((OS == llvm::Triple::Win32 && CC == CC_X86_64SysV) ||
+ (OS != llvm::Triple::Win32 && CC == CC_X86_64Win64))
+ return Diag(TheCall->getCallee()->getLocStart(),
+ diag::err_va_start_used_in_wrong_abi_function)
+ << (OS != llvm::Triple::Win32);
+ }
+ return SemaBuiltinVAStartImpl(TheCall);
+}
+
+/// Check the arguments to '__builtin_ms_va_start' for validity, and that
+/// it was called from a Win64 ABI function.
+/// Emit an error and return true on failure; return false on success.
+bool Sema::SemaBuiltinMSVAStart(CallExpr *TheCall) {
+ // This only makes sense for x86-64.
+ const llvm::Triple &TT = Context.getTargetInfo().getTriple();
+ Expr *Callee = TheCall->getCallee();
+ if (TT.getArch() != llvm::Triple::x86_64)
+ return Diag(Callee->getLocStart(), diag::err_x86_builtin_32_bit_tgt);
+ // Don't allow this in System V ABI functions.
+ clang::CallingConv CC = CC_C;
+ if (const FunctionDecl *FD = getCurFunctionDecl())
+ CC = FD->getType()->getAs<FunctionType>()->getCallConv();
+ if (CC == CC_X86_64SysV ||
+ (TT.getOS() != llvm::Triple::Win32 && CC != CC_X86_64Win64))
+ return Diag(Callee->getLocStart(),
+ diag::err_ms_va_start_used_in_sysv_function);
+ return SemaBuiltinVAStartImpl(TheCall);
+}
+
bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) {
// void __va_start(va_list *ap, const char *named_addr, size_t slot_size,
// const char *named_addr);
@@ -2784,26 +2980,6 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
return false;
}
-/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *).
-/// This checks that the target supports __builtin_cpu_supports and
-/// that the string argument is constant and valid.
-bool Sema::SemaBuiltinCpuSupports(CallExpr *TheCall) {
- Expr *Arg = TheCall->getArg(0);
-
- // Check if the argument is a string literal.
- if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
- return Diag(TheCall->getLocStart(), diag::err_expr_not_string_literal)
- << Arg->getSourceRange();
-
- // Check the contents of the string.
- StringRef Feature =
- cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
- if (!Context.getTargetInfo().validateCpuSupports(Feature))
- return Diag(TheCall->getLocStart(), diag::err_invalid_cpu_supports)
- << Arg->getSourceRange();
- return false;
-}
-
/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
/// This checks that the target supports __builtin_longjmp and
/// that val is a constant 1.
@@ -4833,7 +5009,7 @@ static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range,
}
}
} else {
- FunctionName = S.Context.BuiltinInfo.GetName(AbsKind);
+ FunctionName = S.Context.BuiltinInfo.getName(AbsKind);
HeaderName = S.Context.BuiltinInfo.getHeaderName(AbsKind);
if (HeaderName) {
@@ -4909,7 +5085,7 @@ void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,
// function call.
if (ArgType->isUnsignedIntegerType()) {
const char *FunctionName =
- IsStdAbs ? "std::abs" : Context.BuiltinInfo.GetName(AbsKind);
+ IsStdAbs ? "std::abs" : Context.BuiltinInfo.getName(AbsKind);
Diag(Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType;
Diag(Call->getExprLoc(), diag::note_remove_abs)
<< FunctionName
@@ -4917,6 +5093,19 @@ void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,
return;
}
+ // Taking the absolute value of a pointer is very suspicious, they probably
+ // wanted to index into an array, dereference a pointer, call a function, etc.
+ if (ArgType->isPointerType() || ArgType->canDecayToPointerType()) {
+ unsigned DiagType = 0;
+ if (ArgType->isFunctionType())
+ DiagType = 1;
+ else if (ArgType->isArrayType())
+ DiagType = 2;
+
+ Diag(Call->getExprLoc(), diag::warn_pointer_abs) << DiagType << ArgType;
+ return;
+ }
+
// std::abs has overloads which prevent most of the absolute value problems
// from occurring.
if (IsStdAbs)
@@ -5465,17 +5654,15 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
}
if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var.
- S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref
- : diag::warn_ret_stack_addr)
+ S.Diag(diagLoc, diag::warn_ret_stack_addr_ref) << lhsType->isReferenceType()
<< DR->getDecl()->getDeclName() << diagRange;
} else if (isa<BlockExpr>(stackE)) { // local block.
S.Diag(diagLoc, diag::err_ret_local_block) << diagRange;
} else if (isa<AddrLabelExpr>(stackE)) { // address of label.
S.Diag(diagLoc, diag::warn_ret_addr_label) << diagRange;
} else { // local temporary.
- S.Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref
- : diag::warn_ret_local_temp_addr)
- << diagRange;
+ S.Diag(diagLoc, diag::warn_ret_local_temp_addr_ref)
+ << lhsType->isReferenceType() << diagRange;
}
// Display the "trail" of reference variables that we followed until we
@@ -5750,6 +5937,11 @@ do {
return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars,ParentDecl);
}
+ case Stmt::OMPArraySectionExprClass: {
+ return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars,
+ ParentDecl);
+ }
+
case Stmt::ConditionalOperatorClass: {
// For conditional operators we need to see if either the LHS or RHS are
// non-NULL Expr's. If one is non-NULL, we return it.
@@ -6051,7 +6243,8 @@ static IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
IntRange OutputTypeRange = IntRange::forValueOfType(C, GetExprType(CE));
- bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast);
+ bool isIntegerCast = CE->getCastKind() == CK_IntegralCast ||
+ CE->getCastKind() == CK_BooleanToSignedIntegral;
// Assume that non-integer casts can span the full range of the type.
if (!isIntegerCast)
@@ -6791,7 +6984,7 @@ void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T,
SmallString<16> PrettyTargetValue;
if (T->isSpecificBuiltinType(BuiltinType::Bool))
- PrettyTargetValue = IntegerValue == 0 ? "false" : "true";
+ PrettyTargetValue = Value.isZero() ? "false" : "true";
else
IntegerValue.toString(PrettyTargetValue);
@@ -6855,6 +7048,10 @@ static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T,
E->getExprLoc()))
return;
+ // Don't warn on functions which have return type nullptr_t.
+ if (isa<CallExpr>(E))
+ return;
+
// Check for NULL (GNUNull) or nullptr (CXX11_nullptr).
const Expr::NullPointerConstantKind NullKind =
E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull);
@@ -6870,8 +7067,12 @@ static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T,
// __null is usually wrapped in a macro. Go up a macro if that is the case.
if (NullKind == Expr::NPCK_GNUNull) {
- if (Loc.isMacroID())
- Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first;
+ if (Loc.isMacroID()) {
+ StringRef MacroName =
+ Lexer::getImmediateMacroName(Loc, S.SourceMgr, S.getLangOpts());
+ if (MacroName == "NULL")
+ Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first;
+ }
}
// Only warn if the null and context location are in the same macro expansion.
@@ -7083,6 +7284,14 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
return;
DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision);
+
+ }
+ // ... or possibly if we're increasing rank, too
+ else if (TargetBT->getKind() > SourceBT->getKind()) {
+ if (S.SourceMgr.isInSystemMacro(CC))
+ return;
+
+ DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_double_promotion);
}
return;
}
@@ -7105,20 +7314,24 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
}
}
- // If the target is bool, warn if expr is a function or method call.
- if (Target->isSpecificBuiltinType(BuiltinType::Bool) &&
- isa<CallExpr>(E)) {
+ // Detect the case where a call result is converted from floating-point to
+ // to bool, and the final argument to the call is converted from bool, to
+ // discover this typo:
+ //
+ // bool b = fabs(x < 1.0); // should be "bool b = fabs(x) < 1.0;"
+ //
+ // FIXME: This is an incredibly special case; is there some more general
+ // way to detect this class of misplaced-parentheses bug?
+ if (Target->isBooleanType() && isa<CallExpr>(E)) {
// Check last argument of function call to see if it is an
// implicit cast from a type matching the type the result
// is being cast to.
CallExpr *CEx = cast<CallExpr>(E);
- unsigned NumArgs = CEx->getNumArgs();
- if (NumArgs > 0) {
+ if (unsigned NumArgs = CEx->getNumArgs()) {
Expr *LastA = CEx->getArg(NumArgs - 1);
Expr *InnerE = LastA->IgnoreParenImpCasts();
- const Type *InnerType =
- S.Context.getCanonicalType(InnerE->getType()).getTypePtr();
- if (isa<ImplicitCastExpr>(LastA) && (InnerType == Target)) {
+ if (isa<ImplicitCastExpr>(LastA) &&
+ InnerE->getType()->isBooleanType()) {
// Warn on this floating-point to bool conversion
DiagnoseImpCast(S, E, T, CC,
diag::warn_impcast_floating_point_to_bool);
@@ -7301,18 +7514,16 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
CheckImplicitConversion(S, E, T, CC);
// Now continue drilling into this expression.
-
- if (PseudoObjectExpr * POE = dyn_cast<PseudoObjectExpr>(E)) {
- if (POE->getResultExpr())
- E = POE->getResultExpr();
- }
-
- if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
- if (OVE->getSourceExpr())
- AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC);
- return;
+
+ if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
+ // The bound subexpressions in a PseudoObjectExpr are not reachable
+ // as transitive children.
+ // FIXME: Use a more uniform representation for this.
+ for (auto *SE : POE->semantics())
+ if (auto *OVE = dyn_cast<OpaqueValueExpr>(SE))
+ AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC);
}
-
+
// Skip past explicit casts.
if (isa<ExplicitCastExpr>(E)) {
E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts();
@@ -7372,12 +7583,6 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
} // end anonymous namespace
-enum {
- AddressOf,
- FunctionPointer,
- ArrayPointer
-};
-
// Helper function for Sema::DiagnoseAlwaysNonNullPointer.
// Returns true when emitting a warning about taking the address of a reference.
static bool CheckForReference(Sema &SemaRef, const Expr *E,
@@ -7476,6 +7681,26 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
}
}
+ auto ComplainAboutNonnullParamOrCall = [&](bool IsParam) {
+ std::string Str;
+ llvm::raw_string_ostream S(Str);
+ E->printPretty(S, nullptr, getPrintingPolicy());
+ unsigned DiagID = IsCompare ? diag::warn_nonnull_expr_compare
+ : diag::warn_cast_nonnull_to_bool;
+ Diag(E->getExprLoc(), DiagID) << IsParam << S.str()
+ << E->getSourceRange() << Range << IsEqual;
+ };
+
+ // If we have a CallExpr that is tagged with returns_nonnull, we can complain.
+ if (auto *Call = dyn_cast<CallExpr>(E->IgnoreParenImpCasts())) {
+ if (auto *Callee = Call->getDirectCallee()) {
+ if (Callee->hasAttr<ReturnsNonNullAttr>()) {
+ ComplainAboutNonnullParamOrCall(false);
+ return;
+ }
+ }
+ }
+
// Expect to find a single Decl. Skip anything more complicated.
ValueDecl *D = nullptr;
if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) {
@@ -7487,40 +7712,38 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
// Weak Decls can be null.
if (!D || D->isWeak())
return;
-
+
// Check for parameter decl with nonnull attribute
- if (const ParmVarDecl* PV = dyn_cast<ParmVarDecl>(D)) {
- if (getCurFunction() && !getCurFunction()->ModifiedNonNullParams.count(PV))
- if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
- unsigned NumArgs = FD->getNumParams();
- llvm::SmallBitVector AttrNonNull(NumArgs);
+ if (const auto* PV = dyn_cast<ParmVarDecl>(D)) {
+ if (getCurFunction() &&
+ !getCurFunction()->ModifiedNonNullParams.count(PV)) {
+ if (PV->hasAttr<NonNullAttr>()) {
+ ComplainAboutNonnullParamOrCall(true);
+ return;
+ }
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
+ auto ParamIter = std::find(FD->param_begin(), FD->param_end(), PV);
+ assert(ParamIter != FD->param_end());
+ unsigned ParamNo = std::distance(FD->param_begin(), ParamIter);
+
for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) {
if (!NonNull->args_size()) {
- AttrNonNull.set(0, NumArgs);
- break;
- }
- for (unsigned Val : NonNull->args()) {
- if (Val >= NumArgs)
- continue;
- AttrNonNull.set(Val);
+ ComplainAboutNonnullParamOrCall(true);
+ return;
}
- }
- if (!AttrNonNull.empty())
- for (unsigned i = 0; i < NumArgs; ++i)
- if (FD->getParamDecl(i) == PV &&
- (AttrNonNull[i] || PV->hasAttr<NonNullAttr>())) {
- std::string Str;
- llvm::raw_string_ostream S(Str);
- E->printPretty(S, nullptr, getPrintingPolicy());
- unsigned DiagID = IsCompare ? diag::warn_nonnull_parameter_compare
- : diag::warn_cast_nonnull_to_bool;
- Diag(E->getExprLoc(), DiagID) << S.str() << E->getSourceRange()
- << Range << IsEqual;
+
+ for (unsigned ArgNo : NonNull->args()) {
+ if (ArgNo == ParamNo) {
+ ComplainAboutNonnullParamOrCall(true);
return;
}
+ }
+ }
}
}
-
+ }
+
QualType T = D->getType();
const bool IsArray = T->isArrayType();
const bool IsFunction = T->isFunctionType();
@@ -7541,7 +7764,11 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare
: diag::warn_impcast_pointer_to_bool;
- unsigned DiagType;
+ enum {
+ AddressOf,
+ FunctionPointer,
+ ArrayPointer
+ } DiagType;
if (IsAddressOf)
DiagType = AddressOf;
else if (IsFunction)
@@ -7627,6 +7854,10 @@ void Sema::CheckBoolLikeConversion(Expr *E, SourceLocation CC) {
void Sema::CheckForIntOverflow (Expr *E) {
if (isa<BinaryOperator>(E->IgnoreParenCasts()))
E->IgnoreParenCasts()->EvaluateForOverflow(Context);
+ else if (auto InitList = dyn_cast<InitListExpr>(E))
+ for (Expr *E : InitList->inits())
+ if (isa<BinaryOperator>(E->IgnoreParenCasts()))
+ E->IgnoreParenCasts()->EvaluateForOverflow(Context);
}
namespace {
@@ -8229,6 +8460,15 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl *const *P,
}
}
}
+
+ // Parameters with the pass_object_size attribute only need to be marked
+ // constant at function definitions. Because we lack information about
+ // whether we're on a declaration or definition when we're instantiating the
+ // attribute, we need to check for constness here.
+ if (const auto *Attr = Param->getAttr<PassObjectSizeAttr>())
+ if (!Param->getType().isConstQualified())
+ Diag(Param->getLocation(), diag::err_attribute_pointers_only)
+ << Attr->getSpelling() << 1;
}
return HasInvalidParm;
@@ -8348,7 +8588,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
return;
llvm::APSInt index;
- if (!IndexExpr->EvaluateAsInt(index, Context))
+ if (!IndexExpr->EvaluateAsInt(index, Context, Expr::SE_AllowSideEffects))
return;
if (IndexNegated)
index = -index;
@@ -8462,6 +8702,13 @@ void Sema::CheckArrayAccess(const Expr *expr) {
AllowOnePastEnd > 0);
return;
}
+ case Stmt::OMPArraySectionExprClass: {
+ const OMPArraySectionExpr *ASE = cast<OMPArraySectionExpr>(expr);
+ if (ASE->getLowerBound())
+ CheckArrayAccess(ASE->getBase(), ASE->getLowerBound(),
+ /*ASE=*/nullptr, AllowOnePastEnd > 0);
+ return;
+ }
case Stmt::UnaryOperatorClass: {
// Only unwrap the * and & unary operators
const UnaryOperator *UO = cast<UnaryOperator>(expr);
@@ -9672,4 +9919,3 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
<< ArgumentExpr->getSourceRange()
<< TypeTagExpr->getSourceRange();
}
-
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
index 8626527..21cf625 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp
@@ -494,6 +494,7 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
bool &AsNestedNameSpecifier) const {
AsNestedNameSpecifier = false;
+ auto *Named = ND;
ND = ND->getUnderlyingDecl();
// Skip unnamed entities.
@@ -526,14 +527,14 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
return false;
if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
- ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
+ (isa<NamespaceDecl>(ND) &&
Filter != &ResultBuilder::IsNamespace &&
Filter != &ResultBuilder::IsNamespaceOrAlias &&
Filter != nullptr))
AsNestedNameSpecifier = true;
// Filter out any unwanted results.
- if (Filter && !(this->*Filter)(ND)) {
+ if (Filter && !(this->*Filter)(Named)) {
// Check whether it is interesting as a nested-name-specifier.
if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
IsNestedNameSpecifier(ND) &&
@@ -1142,14 +1143,12 @@ bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
/// \brief Determines whether the given declaration is a namespace or
/// namespace alias.
bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
- return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
+ return isa<NamespaceDecl>(ND->getUnderlyingDecl());
}
/// \brief Determines whether the given declaration is a type.
bool ResultBuilder::IsType(const NamedDecl *ND) const {
- if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
- ND = Using->getTargetDecl();
-
+ ND = ND->getUnderlyingDecl();
return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
}
@@ -1157,11 +1156,9 @@ bool ResultBuilder::IsType(const NamedDecl *ND) const {
/// "." or "->". Only value declarations, nested name specifiers, and
/// using declarations thereof should show up.
bool ResultBuilder::IsMember(const NamedDecl *ND) const {
- if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
- ND = Using->getTargetDecl();
-
+ ND = ND->getUnderlyingDecl();
return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
- isa<ObjCPropertyDecl>(ND);
+ isa<ObjCPropertyDecl>(ND);
}
static bool isObjCReceiverType(ASTContext &C, QualType T) {
@@ -3036,6 +3033,7 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
case Decl::ParmVar: return CXCursor_ParmDecl;
case Decl::Typedef: return CXCursor_TypedefDecl;
case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
+ case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
case Decl::Var: return CXCursor_VarDecl;
case Decl::Namespace: return CXCursor_Namespace;
case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
@@ -3376,7 +3374,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
case PCC_Statement:
case PCC_RecoveryInFunction:
if (S->getFnParent())
- AddPrettyFunctionResults(PP.getLangOpts(), Results);
+ AddPrettyFunctionResults(getLangOpts(), Results);
break;
case PCC_Namespace:
@@ -3520,7 +3518,7 @@ void Sema::CodeCompleteExpression(Scope *S,
if (S->getFnParent() &&
!Data.ObjCCollection &&
!Data.IntegralConstantExpression)
- AddPrettyFunctionResults(PP.getLangOpts(), Results);
+ AddPrettyFunctionResults(getLangOpts(), Results);
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
@@ -4051,7 +4049,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
// If expression's type is CXXRecordDecl, it may overload the function
// call operator, so we check if it does and add them as candidates.
// A complete type is needed to lookup for member function call operators.
- if (!RequireCompleteType(Loc, NakedFn->getType(), 0)) {
+ if (isCompleteType(Loc, NakedFn->getType())) {
DeclarationName OpName = Context.DeclarationNames
.getCXXOperatorName(OO_Call);
LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
@@ -4093,7 +4091,7 @@ void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
return;
// A complete type is needed to lookup for constructors.
- if (RequireCompleteType(Loc, Type, 0))
+ if (!isCompleteType(Loc, Type))
return;
CXXRecordDecl *RD = Type->getAsCXXRecordDecl();
@@ -4205,7 +4203,7 @@ void Sema::CodeCompleteAfterIf(Scope *S) {
Results.ExitScope();
if (S->getFnParent())
- AddPrettyFunctionResults(PP.getLangOpts(), Results);
+ AddPrettyFunctionResults(getLangOpts(), Results);
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, false);
@@ -4912,7 +4910,7 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Results.AddResult(CodeCompletionResult("atomic"));
// Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
- if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
+ if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Results.AddResult(CodeCompletionResult("weak"));
@@ -5925,8 +5923,8 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
}
}
-void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
- unsigned NumProtocols) {
+void Sema::CodeCompleteObjCProtocolReferences(
+ ArrayRef<IdentifierLocPair> Protocols) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCProtocolName);
@@ -5937,9 +5935,9 @@ void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
// Tell the result set to ignore all of the protocols we have
// already seen.
// FIXME: This doesn't work when caching code-completion results.
- for (unsigned I = 0; I != NumProtocols; ++I)
- if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
- Protocols[I].second))
+ for (const IdentifierLocPair &Pair : Protocols)
+ if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
+ Pair.second))
Results.Ignore(Protocol);
// Add all protocols.
@@ -7079,11 +7077,13 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
// If the result type was not already provided, add it to the
// pattern as (type).
- if (ReturnType.isNull())
- AddObjCPassingTypeChunk(Method->getSendResultType()
- .stripObjCKindOfType(Context),
+ if (ReturnType.isNull()) {
+ QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
+ AttributedType::stripOuterNullability(ResTy);
+ AddObjCPassingTypeChunk(ResTy,
Method->getObjCDeclQualifier(), Context, Policy,
Builder);
+ }
Selector Sel = Method->getSelector();
@@ -7114,6 +7114,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
ParamType = (*P)->getOriginalType();
ParamType = ParamType.substObjCTypeArgs(Context, {},
ObjCSubstitutionContext::Parameter);
+ AttributedType::stripOuterNullability(ParamType);
AddObjCPassingTypeChunk(ParamType,
(*P)->getObjCDeclQualifier(),
Context, Policy,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp
new file mode 100644
index 0000000..4b4fd6b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCoroutine.cpp
@@ -0,0 +1,448 @@
+//===--- SemaCoroutines.cpp - Semantic Analysis for Coroutines ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for C++ Coroutines.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Overload.h"
+using namespace clang;
+using namespace sema;
+
+/// Look up the std::coroutine_traits<...>::promise_type for the given
+/// function type.
+static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
+ SourceLocation Loc) {
+ // FIXME: Cache std::coroutine_traits once we've found it.
+ NamespaceDecl *Std = S.getStdNamespace();
+ if (!Std) {
+ S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
+ return QualType();
+ }
+
+ LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
+ Loc, Sema::LookupOrdinaryName);
+ if (!S.LookupQualifiedName(Result, Std)) {
+ S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
+ return QualType();
+ }
+
+ ClassTemplateDecl *CoroTraits = Result.getAsSingle<ClassTemplateDecl>();
+ if (!CoroTraits) {
+ Result.suppressDiagnostics();
+ // We found something weird. Complain about the first thing we found.
+ NamedDecl *Found = *Result.begin();
+ S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
+ return QualType();
+ }
+
+ // Form template argument list for coroutine_traits<R, P1, P2, ...>.
+ TemplateArgumentListInfo Args(Loc, Loc);
+ Args.addArgument(TemplateArgumentLoc(
+ TemplateArgument(FnType->getReturnType()),
+ S.Context.getTrivialTypeSourceInfo(FnType->getReturnType(), Loc)));
+ // FIXME: If the function is a non-static member function, add the type
+ // of the implicit object parameter before the formal parameters.
+ for (QualType T : FnType->getParamTypes())
+ Args.addArgument(TemplateArgumentLoc(
+ TemplateArgument(T), S.Context.getTrivialTypeSourceInfo(T, Loc)));
+
+ // Build the template-id.
+ QualType CoroTrait =
+ S.CheckTemplateIdType(TemplateName(CoroTraits), Loc, Args);
+ if (CoroTrait.isNull())
+ return QualType();
+ if (S.RequireCompleteType(Loc, CoroTrait,
+ diag::err_coroutine_traits_missing_specialization))
+ return QualType();
+
+ CXXRecordDecl *RD = CoroTrait->getAsCXXRecordDecl();
+ assert(RD && "specialization of class template is not a class?");
+
+ // Look up the ::promise_type member.
+ LookupResult R(S, &S.PP.getIdentifierTable().get("promise_type"), Loc,
+ Sema::LookupOrdinaryName);
+ S.LookupQualifiedName(R, RD);
+ auto *Promise = R.getAsSingle<TypeDecl>();
+ if (!Promise) {
+ S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_found)
+ << RD;
+ return QualType();
+ }
+
+ // The promise type is required to be a class type.
+ QualType PromiseType = S.Context.getTypeDeclType(Promise);
+ if (!PromiseType->getAsCXXRecordDecl()) {
+ // Use the fully-qualified name of the type.
+ auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, Std);
+ NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
+ CoroTrait.getTypePtr());
+ PromiseType = S.Context.getElaboratedType(ETK_None, NNS, PromiseType);
+
+ S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_class)
+ << PromiseType;
+ return QualType();
+ }
+
+ return PromiseType;
+}
+
+/// Check that this is a context in which a coroutine suspension can appear.
+static FunctionScopeInfo *
+checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword) {
+ // 'co_await' and 'co_yield' are not permitted in unevaluated operands.
+ if (S.isUnevaluatedContext()) {
+ S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
+ return nullptr;
+ }
+
+ // Any other usage must be within a function.
+ // FIXME: Reject a coroutine with a deduced return type.
+ auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
+ if (!FD) {
+ S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
+ ? diag::err_coroutine_objc_method
+ : diag::err_coroutine_outside_function) << Keyword;
+ } else if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD)) {
+ // Coroutines TS [special]/6:
+ // A special member function shall not be a coroutine.
+ //
+ // FIXME: We assume that this really means that a coroutine cannot
+ // be a constructor or destructor.
+ S.Diag(Loc, diag::err_coroutine_ctor_dtor)
+ << isa<CXXDestructorDecl>(FD) << Keyword;
+ } else if (FD->isConstexpr()) {
+ S.Diag(Loc, diag::err_coroutine_constexpr) << Keyword;
+ } else if (FD->isVariadic()) {
+ S.Diag(Loc, diag::err_coroutine_varargs) << Keyword;
+ } else {
+ auto *ScopeInfo = S.getCurFunction();
+ assert(ScopeInfo && "missing function scope for function");
+
+ // If we don't have a promise variable, build one now.
+ if (!ScopeInfo->CoroutinePromise) {
+ QualType T =
+ FD->getType()->isDependentType()
+ ? S.Context.DependentTy
+ : lookupPromiseType(S, FD->getType()->castAs<FunctionProtoType>(),
+ Loc);
+ if (T.isNull())
+ return nullptr;
+
+ // Create and default-initialize the promise.
+ ScopeInfo->CoroutinePromise =
+ VarDecl::Create(S.Context, FD, FD->getLocation(), FD->getLocation(),
+ &S.PP.getIdentifierTable().get("__promise"), T,
+ S.Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
+ S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise);
+ if (!ScopeInfo->CoroutinePromise->isInvalidDecl())
+ S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise, false);
+ }
+
+ return ScopeInfo;
+ }
+
+ return nullptr;
+}
+
+/// Build a call to 'operator co_await' if there is a suitable operator for
+/// the given expression.
+static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S,
+ SourceLocation Loc, Expr *E) {
+ UnresolvedSet<16> Functions;
+ SemaRef.LookupOverloadedOperatorName(OO_Coawait, S, E->getType(), QualType(),
+ Functions);
+ return SemaRef.CreateOverloadedUnaryOp(Loc, UO_Coawait, Functions, E);
+}
+
+struct ReadySuspendResumeResult {
+ bool IsInvalid;
+ Expr *Results[3];
+};
+
+static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
+ StringRef Name,
+ MutableArrayRef<Expr *> Args) {
+ DeclarationNameInfo NameInfo(&S.PP.getIdentifierTable().get(Name), Loc);
+
+ // FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
+ CXXScopeSpec SS;
+ ExprResult Result = S.BuildMemberReferenceExpr(
+ Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
+ SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
+ /*Scope=*/nullptr);
+ if (Result.isInvalid())
+ return ExprError();
+
+ return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
+}
+
+/// Build calls to await_ready, await_suspend, and await_resume for a co_await
+/// expression.
+static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc,
+ Expr *E) {
+ // Assume invalid until we see otherwise.
+ ReadySuspendResumeResult Calls = {true, {}};
+
+ const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
+ for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
+ Expr *Operand = new (S.Context) OpaqueValueExpr(
+ Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
+
+ // FIXME: Pass coroutine handle to await_suspend.
+ ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None);
+ if (Result.isInvalid())
+ return Calls;
+ Calls.Results[I] = Result.get();
+ }
+
+ Calls.IsInvalid = false;
+ return Calls;
+}
+
+ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
+ if (E->getType()->isPlaceholderType()) {
+ ExprResult R = CheckPlaceholderExpr(E);
+ if (R.isInvalid()) return ExprError();
+ E = R.get();
+ }
+
+ ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E);
+ if (Awaitable.isInvalid())
+ return ExprError();
+ return BuildCoawaitExpr(Loc, Awaitable.get());
+}
+ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
+ auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
+ if (!Coroutine)
+ return ExprError();
+
+ if (E->getType()->isPlaceholderType()) {
+ ExprResult R = CheckPlaceholderExpr(E);
+ if (R.isInvalid()) return ExprError();
+ E = R.get();
+ }
+
+ if (E->getType()->isDependentType()) {
+ Expr *Res = new (Context) CoawaitExpr(Loc, Context.DependentTy, E);
+ Coroutine->CoroutineStmts.push_back(Res);
+ return Res;
+ }
+
+ // If the expression is a temporary, materialize it as an lvalue so that we
+ // can use it multiple times.
+ if (E->getValueKind() == VK_RValue)
+ E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true);
+
+ // Build the await_ready, await_suspend, await_resume calls.
+ ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
+ if (RSS.IsInvalid)
+ return ExprError();
+
+ Expr *Res = new (Context) CoawaitExpr(Loc, E, RSS.Results[0], RSS.Results[1],
+ RSS.Results[2]);
+ Coroutine->CoroutineStmts.push_back(Res);
+ return Res;
+}
+
+static ExprResult buildPromiseCall(Sema &S, FunctionScopeInfo *Coroutine,
+ SourceLocation Loc, StringRef Name,
+ MutableArrayRef<Expr *> Args) {
+ assert(Coroutine->CoroutinePromise && "no promise for coroutine");
+
+ // Form a reference to the promise.
+ auto *Promise = Coroutine->CoroutinePromise;
+ ExprResult PromiseRef = S.BuildDeclRefExpr(
+ Promise, Promise->getType().getNonReferenceType(), VK_LValue, Loc);
+ if (PromiseRef.isInvalid())
+ return ExprError();
+
+ // Call 'yield_value', passing in E.
+ return buildMemberCall(S, PromiseRef.get(), Loc, Name, Args);
+}
+
+ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
+ auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
+ if (!Coroutine)
+ return ExprError();
+
+ // Build yield_value call.
+ ExprResult Awaitable =
+ buildPromiseCall(*this, Coroutine, Loc, "yield_value", E);
+ if (Awaitable.isInvalid())
+ return ExprError();
+
+ // Build 'operator co_await' call.
+ Awaitable = buildOperatorCoawaitCall(*this, S, Loc, Awaitable.get());
+ if (Awaitable.isInvalid())
+ return ExprError();
+
+ return BuildCoyieldExpr(Loc, Awaitable.get());
+}
+ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
+ auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
+ if (!Coroutine)
+ return ExprError();
+
+ if (E->getType()->isPlaceholderType()) {
+ ExprResult R = CheckPlaceholderExpr(E);
+ if (R.isInvalid()) return ExprError();
+ E = R.get();
+ }
+
+ if (E->getType()->isDependentType()) {
+ Expr *Res = new (Context) CoyieldExpr(Loc, Context.DependentTy, E);
+ Coroutine->CoroutineStmts.push_back(Res);
+ return Res;
+ }
+
+ // If the expression is a temporary, materialize it as an lvalue so that we
+ // can use it multiple times.
+ if (E->getValueKind() == VK_RValue)
+ E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true);
+
+ // Build the await_ready, await_suspend, await_resume calls.
+ ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E);
+ if (RSS.IsInvalid)
+ return ExprError();
+
+ Expr *Res = new (Context) CoyieldExpr(Loc, E, RSS.Results[0], RSS.Results[1],
+ RSS.Results[2]);
+ Coroutine->CoroutineStmts.push_back(Res);
+ return Res;
+}
+
+StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
+ return BuildCoreturnStmt(Loc, E);
+}
+StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
+ auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
+ if (!Coroutine)
+ return StmtError();
+
+ if (E && E->getType()->isPlaceholderType() &&
+ !E->getType()->isSpecificPlaceholderType(BuiltinType::Overload)) {
+ ExprResult R = CheckPlaceholderExpr(E);
+ if (R.isInvalid()) return StmtError();
+ E = R.get();
+ }
+
+ // FIXME: If the operand is a reference to a variable that's about to go out
+ // of scope, we should treat the operand as an xvalue for this overload
+ // resolution.
+ ExprResult PC;
+ if (E && !E->getType()->isVoidType()) {
+ PC = buildPromiseCall(*this, Coroutine, Loc, "return_value", E);
+ } else {
+ E = MakeFullDiscardedValueExpr(E).get();
+ PC = buildPromiseCall(*this, Coroutine, Loc, "return_void", None);
+ }
+ if (PC.isInvalid())
+ return StmtError();
+
+ Expr *PCE = ActOnFinishFullExpr(PC.get()).get();
+
+ Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE);
+ Coroutine->CoroutineStmts.push_back(Res);
+ return Res;
+}
+
+void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
+ FunctionScopeInfo *Fn = getCurFunction();
+ assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine");
+
+ // Coroutines [stmt.return]p1:
+ // A return statement shall not appear in a coroutine.
+ if (Fn->FirstReturnLoc.isValid()) {
+ Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
+ auto *First = Fn->CoroutineStmts[0];
+ Diag(First->getLocStart(), diag::note_declared_coroutine_here)
+ << (isa<CoawaitExpr>(First) ? 0 :
+ isa<CoyieldExpr>(First) ? 1 : 2);
+ }
+
+ bool AnyCoawaits = false;
+ bool AnyCoyields = false;
+ for (auto *CoroutineStmt : Fn->CoroutineStmts) {
+ AnyCoawaits |= isa<CoawaitExpr>(CoroutineStmt);
+ AnyCoyields |= isa<CoyieldExpr>(CoroutineStmt);
+ }
+
+ if (!AnyCoawaits && !AnyCoyields)
+ Diag(Fn->CoroutineStmts.front()->getLocStart(),
+ diag::ext_coroutine_without_co_await_co_yield);
+
+ SourceLocation Loc = FD->getLocation();
+
+ // Form a declaration statement for the promise declaration, so that AST
+ // visitors can more easily find it.
+ StmtResult PromiseStmt =
+ ActOnDeclStmt(ConvertDeclToDeclGroup(Fn->CoroutinePromise), Loc, Loc);
+ if (PromiseStmt.isInvalid())
+ return FD->setInvalidDecl();
+
+ // Form and check implicit 'co_await p.initial_suspend();' statement.
+ ExprResult InitialSuspend =
+ buildPromiseCall(*this, Fn, Loc, "initial_suspend", None);
+ // FIXME: Support operator co_await here.
+ if (!InitialSuspend.isInvalid())
+ InitialSuspend = BuildCoawaitExpr(Loc, InitialSuspend.get());
+ InitialSuspend = ActOnFinishFullExpr(InitialSuspend.get());
+ if (InitialSuspend.isInvalid())
+ return FD->setInvalidDecl();
+
+ // Form and check implicit 'co_await p.final_suspend();' statement.
+ ExprResult FinalSuspend =
+ buildPromiseCall(*this, Fn, Loc, "final_suspend", None);
+ // FIXME: Support operator co_await here.
+ if (!FinalSuspend.isInvalid())
+ FinalSuspend = BuildCoawaitExpr(Loc, FinalSuspend.get());
+ FinalSuspend = ActOnFinishFullExpr(FinalSuspend.get());
+ if (FinalSuspend.isInvalid())
+ return FD->setInvalidDecl();
+
+ // FIXME: Perform analysis of set_exception call.
+
+ // FIXME: Try to form 'p.return_void();' expression statement to handle
+ // control flowing off the end of the coroutine.
+
+ // Build implicit 'p.get_return_object()' expression and form initialization
+ // of return type from it.
+ ExprResult ReturnObject =
+ buildPromiseCall(*this, Fn, Loc, "get_return_object", None);
+ if (ReturnObject.isInvalid())
+ return FD->setInvalidDecl();
+ QualType RetType = FD->getReturnType();
+ if (!RetType->isDependentType()) {
+ InitializedEntity Entity =
+ InitializedEntity::InitializeResult(Loc, RetType, false);
+ ReturnObject = PerformMoveOrCopyInitialization(Entity, nullptr, RetType,
+ ReturnObject.get());
+ if (ReturnObject.isInvalid())
+ return FD->setInvalidDecl();
+ }
+ ReturnObject = ActOnFinishFullExpr(ReturnObject.get(), Loc);
+ if (ReturnObject.isInvalid())
+ return FD->setInvalidDecl();
+
+ // FIXME: Perform move-initialization of parameters into frame-local copies.
+ SmallVector<Expr*, 16> ParamMoves;
+
+ // Build body for the coroutine wrapper statement.
+ Body = new (Context) CoroutineBodyStmt(
+ Body, PromiseStmt.get(), InitialSuspend.get(), FinalSuspend.get(),
+ /*SetException*/nullptr, /*Fallthrough*/nullptr,
+ ReturnObject.get(), ParamMoves);
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
index c694a20..f95d106 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -33,7 +33,6 @@
#include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
#include "clang/Lex/ModuleLoader.h" // TODO: Sema shouldn't depend on Lex
#include "clang/Lex/Preprocessor.h" // Included for isCodeCompletionEnabled()
-#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
@@ -111,6 +110,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
case tok::kw_wchar_t:
case tok::kw_bool:
case tok::kw___underlying_type:
+ case tok::kw___auto_type:
return true;
case tok::annot_typename:
@@ -795,7 +795,7 @@ Corrected:
}
// In C, we first see whether there is a tag type by the same name, in
- // which case it's likely that the user just forget to write "enum",
+ // which case it's likely that the user just forgot to write "enum",
// "struct", or "union".
if (!getLangOpts().CPlusPlus && !SecondTry &&
isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
@@ -813,9 +813,8 @@ Corrected:
unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
unsigned QualifiedDiag = diag::err_no_member_suggest;
- NamedDecl *FirstDecl = Corrected.getCorrectionDecl();
- NamedDecl *UnderlyingFirstDecl
- = FirstDecl? FirstDecl->getUnderlyingDecl() : nullptr;
+ NamedDecl *FirstDecl = Corrected.getFoundDecl();
+ NamedDecl *UnderlyingFirstDecl = Corrected.getCorrectionDecl();
if (getLangOpts().CPlusPlus && NextToken.is(tok::less) &&
UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) {
UnqualifiedDiag = diag::err_no_template_suggest;
@@ -1022,7 +1021,7 @@ Corrected:
if (FirstDecl->isCXXClassMember())
return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result,
- nullptr);
+ nullptr, S);
bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren));
return BuildDeclarationNameExpr(SS, Result, ADL);
@@ -1089,7 +1088,9 @@ Sema::SkippedDefinitionContext Sema::ActOnTagStartSkippedDefinition(Scope *S,
auto Result = static_cast<SkippedDefinitionContext>(CurContext);
CurContext = cast<TagDecl>(D)->getDefinition();
assert(CurContext && "skipping definition of undefined tag");
- S->setEntity(CurContext);
+ // Start lookups from the parent of the current context; we don't want to look
+ // into the pre-existing complete definition.
+ S->setEntity(CurContext->getLookupParent());
return Result;
}
@@ -1733,20 +1734,18 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
if (Error) {
if (ForRedeclaration)
Diag(Loc, diag::warn_implicit_decl_requires_sysheader)
- << getHeaderName(Error)
- << Context.BuiltinInfo.GetName(ID);
+ << getHeaderName(Error) << Context.BuiltinInfo.getName(ID);
return nullptr;
}
if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(ID)) {
Diag(Loc, diag::ext_implicit_lib_function_decl)
- << Context.BuiltinInfo.GetName(ID)
- << R;
+ << Context.BuiltinInfo.getName(ID) << R;
if (Context.BuiltinInfo.getHeaderName(ID) &&
!Diags.isIgnored(diag::ext_implicit_lib_function_decl, Loc))
Diag(Loc, diag::note_include_header_or_declare)
<< Context.BuiltinInfo.getHeaderName(ID)
- << Context.BuiltinInfo.GetName(ID);
+ << Context.BuiltinInfo.getName(ID);
}
DeclContext *Parent = Context.getTranslationUnitDecl();
@@ -1796,37 +1795,6 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
return New;
}
-/// \brief Filter out any previous declarations that the given declaration
-/// should not consider because they are not permitted to conflict, e.g.,
-/// because they come from hidden sub-modules and do not refer to the same
-/// entity.
-static void filterNonConflictingPreviousDecls(Sema &S,
- NamedDecl *decl,
- LookupResult &previous){
- // This is only interesting when modules are enabled.
- if ((!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility) ||
- !S.getLangOpts().ModulesHideInternalLinkage)
- return;
-
- // Empty sets are uninteresting.
- if (previous.empty())
- return;
-
- LookupResult::Filter filter = previous.makeFilter();
- while (filter.hasNext()) {
- NamedDecl *old = filter.next();
-
- // Non-hidden declarations are never ignored.
- if (S.isVisible(old))
- continue;
-
- if (!old->isExternallyVisible())
- filter.erase();
- }
-
- filter.done();
-}
-
/// Typedef declarations don't have linkage, but they still denote the same
/// entity if their types are the same.
/// FIXME: This is notionally doing the same thing as ASTReaderDecl's
@@ -1859,13 +1827,13 @@ static void filterNonConflictingPreviousTypedefDecls(Sema &S,
// If both declarations give a tag declaration a typedef name for linkage
// purposes, then they declare the same entity.
- if (OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) &&
+ if (S.getLangOpts().CPlusPlus &&
+ OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) &&
Decl->getAnonDeclWithTypedefName())
continue;
}
- if (!Old->isExternallyVisible())
- Filter.erase();
+ Filter.erase();
}
Filter.done();
@@ -1910,7 +1878,8 @@ bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
/// how to resolve this situation, merging decls or emitting
/// diagnostics as appropriate. If there was an error, set New to be invalid.
///
-void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
+void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
+ LookupResult &OldDecls) {
// If the new decl is known invalid already, don't bother doing any
// merging checks.
if (New->isInvalidDecl()) return;
@@ -1991,6 +1960,19 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
// Make the old tag definition visible.
makeMergedDefinitionVisible(Hidden, NewTag->getLocation());
+
+ // If this was an unscoped enumeration, yank all of its enumerators
+ // out of the scope.
+ if (isa<EnumDecl>(NewTag)) {
+ Scope *EnumScope = getNonFieldDeclScope(S);
+ for (auto *D : NewTag->decls()) {
+ auto *ED = cast<EnumConstantDecl>(D);
+ assert(EnumScope->isDeclScope(ED));
+ EnumScope->RemoveDecl(ED);
+ IdResolver.RemoveDecl(ED);
+ ED->getLexicalDeclContext()->removeDecl(ED);
+ }
+ }
}
}
@@ -2206,14 +2188,15 @@ static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
}
static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
- const InheritableAttr *Attr, bool Override) {
+ const InheritableAttr *Attr,
+ Sema::AvailabilityMergeKind AMK) {
InheritableAttr *NewAttr = nullptr;
unsigned AttrSpellingListIndex = Attr->getSpellingListIndex();
if (const auto *AA = dyn_cast<AvailabilityAttr>(Attr))
NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(),
AA->getIntroduced(), AA->getDeprecated(),
AA->getObsoleted(), AA->getUnavailable(),
- AA->getMessage(), Override,
+ AA->getMessage(), AMK,
AttrSpellingListIndex);
else if (const auto *VA = dyn_cast<VisibilityAttr>(Attr))
NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
@@ -2246,11 +2229,22 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
NewAttr = S.mergeMinSizeAttr(D, MA->getRange(), AttrSpellingListIndex);
else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex);
+ else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr))
+ NewAttr = S.mergeInternalLinkageAttr(
+ D, InternalLinkageA->getRange(),
+ &S.Context.Idents.get(InternalLinkageA->getSpelling()),
+ AttrSpellingListIndex);
+ else if (const auto *CommonA = dyn_cast<CommonAttr>(Attr))
+ NewAttr = S.mergeCommonAttr(D, CommonA->getRange(),
+ &S.Context.Idents.get(CommonA->getSpelling()),
+ AttrSpellingListIndex);
else if (isa<AlignedAttr>(Attr))
// AlignedAttrs are handled separately, because we need to handle all
// such attributes on a declaration at the same time.
NewAttr = nullptr;
- else if (isa<DeprecatedAttr>(Attr) && Override)
+ else if ((isa<DeprecatedAttr>(Attr) || isa<UnavailableAttr>(Attr)) &&
+ (AMK == Sema::AMK_Override ||
+ AMK == Sema::AMK_ProtocolImplementation))
NewAttr = nullptr;
else if (Attr->duplicatesAllowed() || !DeclHasAttr(D, Attr))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
@@ -2303,9 +2297,17 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
const Attr *NewAttribute = NewAttributes[I];
if (isa<AliasAttr>(NewAttribute)) {
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New))
- S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def));
- else {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New)) {
+ Sema::SkipBodyInfo SkipBody;
+ S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def), &SkipBody);
+
+ // If we're skipping this definition, drop the "alias" attribute.
+ if (SkipBody.ShouldSkip) {
+ NewAttributes.erase(NewAttributes.begin() + I);
+ --E;
+ continue;
+ }
+ } else {
VarDecl *VD = cast<VarDecl>(New);
unsigned Diag = cast<VarDecl>(Def)->isThisDeclarationADefinition() ==
VarDecl::TentativeDefinition
@@ -2376,9 +2378,24 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
if (!Old->hasAttrs() && !New->hasAttrs())
return;
- // attributes declared post-definition are currently ignored
+ // Attributes declared post-definition are currently ignored.
checkNewAttributesAfterDef(*this, New, Old);
+ if (AsmLabelAttr *NewA = New->getAttr<AsmLabelAttr>()) {
+ if (AsmLabelAttr *OldA = Old->getAttr<AsmLabelAttr>()) {
+ if (OldA->getLabel() != NewA->getLabel()) {
+ // This redeclaration changes __asm__ label.
+ Diag(New->getLocation(), diag::err_different_asm_label);
+ Diag(OldA->getLocation(), diag::note_previous_declaration);
+ }
+ } else if (Old->isUsed()) {
+ // This redeclaration adds an __asm__ label to a declaration that has
+ // already been ODR-used.
+ Diag(New->getLocation(), diag::err_late_asm_label_name)
+ << isa<FunctionDecl>(Old) << New->getAttr<AsmLabelAttr>()->getRange();
+ }
+ }
+
if (!Old->hasAttrs())
return;
@@ -2389,8 +2406,8 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
if (!foundAny) New->setAttrs(AttrVec());
for (auto *I : Old->specific_attrs<InheritableAttr>()) {
- bool Override = false;
// Ignore deprecated/unavailable/availability attributes if requested.
+ AvailabilityMergeKind LocalAMK = AMK_None;
if (isa<DeprecatedAttr>(I) ||
isa<UnavailableAttr>(I) ||
isa<AvailabilityAttr>(I)) {
@@ -2399,10 +2416,9 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
continue;
case AMK_Redeclaration:
- break;
-
case AMK_Override:
- Override = true;
+ case AMK_ProtocolImplementation:
+ LocalAMK = AMK;
break;
}
}
@@ -2411,7 +2427,7 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
if (isa<UsedAttr>(I))
continue;
- if (mergeDeclAttribute(*this, New, I, Override))
+ if (mergeDeclAttribute(*this, New, I, LocalAMK))
foundAny = true;
}
@@ -2619,6 +2635,21 @@ static bool checkUsingShadowRedecl(Sema &S, UsingShadowDecl *OldS,
return false;
}
+static bool hasIdenticalPassObjectSizeAttrs(const FunctionDecl *A,
+ const FunctionDecl *B) {
+ assert(A->getNumParams() == B->getNumParams());
+
+ auto AttrEq = [](const ParmVarDecl *A, const ParmVarDecl *B) {
+ const auto *AttrA = A->getAttr<PassObjectSizeAttr>();
+ const auto *AttrB = B->getAttr<PassObjectSizeAttr>();
+ if (AttrA == AttrB)
+ return true;
+ return AttrA && AttrB && AttrA->getType() == AttrB->getType();
+ };
+
+ return std::equal(A->param_begin(), A->param_end(), B->param_begin(), AttrEq);
+}
+
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -2685,6 +2716,13 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
}
}
+ if (New->hasAttr<InternalLinkageAttr>() &&
+ !Old->hasAttr<InternalLinkageAttr>()) {
+ Diag(New->getLocation(), diag::err_internal_linkage_redeclaration)
+ << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ New->dropAttr<InternalLinkageAttr>();
+ }
// If a function is first declared with a calling convention, but is later
// declared or defined without one, all following decls assume the calling
@@ -2790,7 +2828,17 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
Old->isInlined() && !Old->hasAttr<GNUInlineAttr>()) {
UndefinedButUsed.erase(Old->getCanonicalDecl());
}
-
+
+ // If pass_object_size params don't match up perfectly, this isn't a valid
+ // redeclaration.
+ if (Old->getNumParams() > 0 && Old->getNumParams() == New->getNumParams() &&
+ !hasIdenticalPassObjectSizeAttrs(Old, New)) {
+ Diag(New->getLocation(), diag::err_different_pass_object_size_params)
+ << New->getDeclName();
+ Diag(OldLocation, PrevDiag) << Old << Old->getType();
+ return true;
+ }
+
if (getLangOpts().CPlusPlus) {
// (C++98 13.1p2):
// Certain function declarations cannot be overloaded:
@@ -3115,7 +3163,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
// remain visible, a single bogus local redeclaration (which is
// actually only a warning) could break all the downstream code.
if (!New->getLexicalDeclContext()->isFunctionOrMethod())
- New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin);
+ New->getIdentifier()->revertBuiltin();
return false;
}
@@ -3179,8 +3227,11 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
// Merge the attributes, including deprecated/unavailable
AvailabilityMergeKind MergeKind =
- isa<ObjCImplDecl>(newMethod->getDeclContext()) ? AMK_Redeclaration
- : AMK_Override;
+ isa<ObjCProtocolDecl>(oldMethod->getDeclContext())
+ ? AMK_ProtocolImplementation
+ : isa<ObjCImplDecl>(newMethod->getDeclContext()) ? AMK_Redeclaration
+ : AMK_Override;
+
mergeDeclAttributes(newMethod, oldMethod, MergeKind);
// Merge attributes from the parameters.
@@ -3331,6 +3382,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
if (New->isInvalidDecl())
return;
+ if (!shouldLinkPossiblyHiddenDecl(Previous, New))
+ return;
+
VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate();
// Verify the old decl was also a variable or variable template.
@@ -3362,15 +3416,12 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
return New->setInvalidDecl();
}
- if (!shouldLinkPossiblyHiddenDecl(Old, New))
- return;
-
// Ensure the template parameters are compatible.
if (NewTemplate &&
!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
/*Complain=*/true, TPL_TemplateMatch))
- return;
+ return New->setInvalidDecl();
// C++ [class.mem]p1:
// A member shall not be declared twice in the member-specification [...]
@@ -3395,6 +3446,14 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->dropAttr<WeakImportAttr>();
}
+ if (New->hasAttr<InternalLinkageAttr>() &&
+ !Old->hasAttr<InternalLinkageAttr>()) {
+ Diag(New->getLocation(), diag::err_internal_linkage_redeclaration)
+ << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ New->dropAttr<InternalLinkageAttr>();
+ }
+
// Merge the types.
VarDecl *MostRecent = Old->getMostRecentDecl();
if (MostRecent != Old) {
@@ -3583,11 +3642,11 @@ void Sema::handleTagNumbering(const TagDecl *Tag, Scope *TagScope) {
void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
TypedefNameDecl *NewTD) {
- // Do nothing if the tag is not anonymous or already has an
- // associated typedef (from an earlier typedef in this decl group).
- if (TagFromDeclSpec->getIdentifier())
+ if (TagFromDeclSpec->isInvalidDecl())
return;
- if (TagFromDeclSpec->getTypedefNameForAnonDecl())
+
+ // Do nothing if the tag already has a name for linkage purposes.
+ if (TagFromDeclSpec->hasNameForLinkage())
return;
// A well-formed anonymous tag must always be a TUK_Definition.
@@ -3595,8 +3654,11 @@ void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
// The type must match the tag exactly; no qualifiers allowed.
if (!Context.hasSameType(NewTD->getUnderlyingType(),
- Context.getTagDeclType(TagFromDeclSpec)))
+ Context.getTagDeclType(TagFromDeclSpec))) {
+ if (getLangOpts().CPlusPlus)
+ Context.addTypedefNameForUnnamedTagDecl(TagFromDeclSpec, NewTD);
return;
+ }
// If we've already computed linkage for the anonymous tag, then
// adding a typedef name for the anonymous decl can change that
@@ -3695,6 +3757,14 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return TagD;
}
+ if (DS.isConceptSpecified()) {
+ // C++ Concepts TS [dcl.spec.concept]p1: A concept definition refers to
+ // either a function concept and its definition or a variable concept and
+ // its initializer.
+ Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind);
+ return TagD;
+ }
+
DiagnoseFunctionSpecifiers(DS);
if (DS.isFriendSpecified()) {
@@ -3709,10 +3779,15 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
bool IsExplicitSpecialization =
!TemplateParams.empty() && TemplateParams.back()->size() == 0;
if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() &&
- !IsExplicitInstantiation && !IsExplicitSpecialization) {
+ !IsExplicitInstantiation && !IsExplicitSpecialization &&
+ !isa<ClassTemplatePartialSpecializationDecl>(Tag)) {
// Per C++ [dcl.type.elab]p1, a class declaration cannot have a
// nested-name-specifier unless it is an explicit instantiation
// or an explicit specialization.
+ //
+ // FIXME: We allow class template partial specializations here too, per the
+ // obvious intent of DR1819.
+ //
// Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either.
Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier)
<< GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange();
@@ -3882,14 +3957,11 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
DeclContext *Owner,
DeclarationName Name,
SourceLocation NameLoc,
- unsigned diagnostic) {
+ bool IsUnion) {
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName,
Sema::ForRedeclaration);
if (!SemaRef.LookupName(R, S)) return false;
- if (R.getAsSingle<TagDecl>())
- return false;
-
// Pick a representative declaration.
NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl();
assert(PrevDecl && "Expected a non-null Decl");
@@ -3897,7 +3969,8 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
if (!SemaRef.isDeclInScope(PrevDecl, Owner, S))
return false;
- SemaRef.Diag(NameLoc, diagnostic) << Name;
+ SemaRef.Diag(NameLoc, diag::err_anonymous_record_member_redecl)
+ << IsUnion << Name;
SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
return true;
@@ -3925,10 +3998,6 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
AccessSpecifier AS,
SmallVectorImpl<NamedDecl *> &Chaining,
bool MSAnonStruct) {
- unsigned diagKind
- = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
- : diag::err_anonymous_struct_member_redecl;
-
bool Invalid = false;
// Look every FieldDecl and IndirectFieldDecl with a name.
@@ -3937,7 +4006,8 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
cast<NamedDecl>(D)->getDeclName()) {
ValueDecl *VD = cast<ValueDecl>(D);
if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(),
- VD->getLocation(), diagKind)) {
+ VD->getLocation(),
+ AnonRecord->isUnion())) {
// C++ [class.union]p2:
// The names of the members of an anonymous union shall be
// distinct from the names of any other entity in the
@@ -4131,7 +4201,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
assert(FD->getAccess() != AS_none);
if (FD->getAccess() != AS_public) {
Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member)
- << (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected);
+ << Record->isUnion() << (FD->getAccess() == AS_protected);
Invalid = true;
}
@@ -4155,11 +4225,11 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// Visual C++ allows type definition in anonymous struct or union.
if (getLangOpts().MicrosoftExt)
Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type)
- << (int)Record->isUnion();
+ << Record->isUnion();
else {
// This is a nested type declaration.
Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type)
- << (int)Record->isUnion();
+ << Record->isUnion();
Invalid = true;
}
} else {
@@ -4168,7 +4238,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// not part of standard C++.
Diag(MemRecord->getLocation(),
diag::ext_anonymous_record_with_anonymous_type)
- << (int)Record->isUnion();
+ << Record->isUnion();
}
} else if (isa<AccessSpecDecl>(Mem)) {
// Any access specifier is fine.
@@ -4189,10 +4259,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
if (getLangOpts().MicrosoftExt &&
DK == diag::err_anonymous_record_with_type)
Diag(Mem->getLocation(), diag::ext_anonymous_record_with_type)
- << (int)Record->isUnion();
+ << Record->isUnion();
else {
- Diag(Mem->getLocation(), DK)
- << (int)Record->isUnion();
+ Diag(Mem->getLocation(), DK) << Record->isUnion();
Invalid = true;
}
}
@@ -4209,7 +4278,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
if (!Record->isUnion() && !Owner->isRecord()) {
Diag(Record->getLocation(), diag::err_anonymous_struct_not_member)
- << (int)getLangOpts().CPlusPlus;
+ << getLangOpts().CPlusPlus;
Invalid = true;
}
@@ -4603,11 +4672,13 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
DeclarationNameInfo NameInfo) {
DeclarationName Name = NameInfo.getName();
- if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
- if (Record->getIdentifier() && Record->getDeclName() == Name) {
- Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name;
- return true;
- }
+ CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC);
+ while (Record && Record->isAnonymousStructOrUnion())
+ Record = dyn_cast<CXXRecordDecl>(Record->getParent());
+ if (Record && Record->getIdentifier() && Record->getDeclName() == Name) {
+ Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name;
+ return true;
+ }
return false;
}
@@ -4885,6 +4956,23 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
if (getLangOpts().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
+ if (D.getDeclSpec().isConceptSpecified()) {
+ // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
+ // applied only to the definition of a function template or variable
+ // template, declared in namespace scope
+ if (!TemplateParamLists.size()) {
+ Diag(D.getDeclSpec().getConceptSpecLoc(),
+ diag:: err_concept_wrong_decl_kind);
+ return nullptr;
+ }
+
+ if (!DC->getRedeclContext()->isFileContext()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_concept_decls_may_only_appear_in_namespace_scope);
+ return nullptr;
+ }
+ }
+
NamedDecl *New;
bool AddToScope = true;
@@ -5102,6 +5190,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (D.getDeclSpec().isConstexprSpecified())
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 1;
+ if (D.getDeclSpec().isConceptSpecified())
+ Diag(D.getDeclSpec().getConceptSpecLoc(),
+ diag::err_concept_wrong_decl_kind);
if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
Diag(D.getName().StartLocation, diag::err_typedef_not_identifier)
@@ -5174,7 +5265,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
filterNonConflictingPreviousTypedefDecls(*this, NewTD, Previous);
if (!Previous.empty()) {
Redeclaration = true;
- MergeTypedefNameDecl(NewTD, Previous);
+ MergeTypedefNameDecl(S, NewTD, Previous);
}
// If this is the C FILE type, notify the AST context.
@@ -5343,14 +5434,26 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
}
}
- // dll attributes require external linkage.
if (const InheritableAttr *Attr = getDLLAttr(&ND)) {
- if (!ND.isExternallyVisible()) {
+ // dll attributes require external linkage. Static locals may have external
+ // linkage but still cannot be explicitly imported or exported.
+ auto *VD = dyn_cast<VarDecl>(&ND);
+ if (!ND.isExternallyVisible() || (VD && VD->isStaticLocal())) {
S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern)
<< &ND << Attr;
ND.setInvalidDecl();
}
}
+
+ // Virtual functions cannot be marked as 'notail'.
+ if (auto *Attr = ND.getAttr<NotTailCalledAttr>())
+ if (auto *MD = dyn_cast<CXXMethodDecl>(&ND))
+ if (MD->isVirtual()) {
+ S.Diag(ND.getLocation(),
+ diag::err_invalid_attribute_on_virtual_function)
+ << Attr;
+ ND.dropAttr<NotTailCalledAttr>();
+ }
}
static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
@@ -5501,6 +5604,12 @@ static bool isIncompleteDeclExternC(Sema &S, const T *D) {
// In C++, the overloadable attribute negates the effects of extern "C".
if (!D->isInExternCContext() || D->template hasAttr<OverloadableAttr>())
return false;
+
+ // So do CUDA's host/device attributes if overloading is enabled.
+ if (S.getLangOpts().CUDA && S.getLangOpts().CUDATargetOverloads &&
+ (D->template hasAttr<CUDADeviceAttr>() ||
+ D->template hasAttr<CUDAHostAttr>()))
+ return false;
}
return D->isExternC();
}
@@ -5574,15 +5683,12 @@ bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
return true;
}
-/// \brief Returns true if given declaration is TU-scoped and externally
-/// visible.
-static bool isDeclTUScopedExternallyVisible(const Decl *D) {
- if (auto *FD = dyn_cast<FunctionDecl>(D))
- return (FD->getDeclContext()->isTranslationUnit() || FD->isExternC()) &&
- FD->hasExternalFormalLinkage();
- else if (auto *VD = dyn_cast<VarDecl>(D))
- return (VD->getDeclContext()->isTranslationUnit() || VD->isExternC()) &&
- VD->hasExternalFormalLinkage();
+/// \brief Returns true if given declaration has external C language linkage.
+static bool isDeclExternC(const Decl *D) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ return FD->isExternC();
+ if (const auto *VD = dyn_cast<VarDecl>(D))
+ return VD->isExternC();
llvm_unreachable("Unknown type of decl!");
}
@@ -5646,7 +5752,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Suppress the warning in system macros, it's used in macros in some
// popular C system headers, such as in glibc's htonl() macro.
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
- diag::warn_deprecated_register)
+ getLangOpts().CPlusPlus1z ? diag::ext_register_storage_class
+ : diag::warn_deprecated_register)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
}
@@ -5670,12 +5777,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
if (getLangOpts().OpenCL) {
- // Set up the special work-group-local storage class for variables in the
- // OpenCL __local address space.
- if (R.getAddressSpace() == LangAS::opencl_local) {
- SC = SC_OpenCLWorkGroupLocal;
- }
-
// OpenCL v1.2 s6.9.b p4:
// The sampler type cannot be used with the __local and __global address
// space qualifiers.
@@ -5712,7 +5813,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
R, TInfo, SC);
-
+
+ if (D.getDeclSpec().containsPlaceholderType() && R->getContainedAutoType())
+ ParsingInitForAutoVars.insert(NewVD);
+
if (D.isInvalidType())
NewVD->setInvalidDecl();
} else {
@@ -5742,8 +5846,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
break;
case SC_PrivateExtern:
llvm_unreachable("C storage class in c++!");
- case SC_OpenCLWorkGroupLocal:
- llvm_unreachable("OpenCL storage class in c++!");
}
}
@@ -5860,11 +5962,31 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
unsigned VDTemplateParamLists = TemplateParams ? 1 : 0;
if (TemplateParamLists.size() > VDTemplateParamLists)
NewVD->setTemplateParameterListsInfo(
- Context, TemplateParamLists.size() - VDTemplateParamLists,
- TemplateParamLists.data());
+ Context, TemplateParamLists.drop_back(VDTemplateParamLists));
if (D.getDeclSpec().isConstexprSpecified())
NewVD->setConstexpr(true);
+
+ if (D.getDeclSpec().isConceptSpecified()) {
+ NewVD->setConcept(true);
+
+ // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not
+ // be declared with the thread_local, inline, friend, or constexpr
+ // specifiers, [...]
+ if (D.getDeclSpec().getThreadStorageClassSpec() == TSCS_thread_local) {
+ Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+ diag::err_concept_decl_invalid_specifiers)
+ << 0 << 0;
+ NewVD->setInvalidDecl(true);
+ }
+
+ if (D.getDeclSpec().isConstexprSpecified()) {
+ Diag(D.getDeclSpec().getConstexprSpecLoc(),
+ diag::err_concept_decl_invalid_specifiers)
+ << 0 << 3;
+ NewVD->setInvalidDecl(true);
+ }
+ }
}
// Set the lexical context. If the declarator has a C++ scope specifier, the
@@ -5990,19 +6112,31 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
break;
case SC_Register:
// Local Named register
- if (!Context.getTargetInfo().isValidGCCRegisterName(Label))
+ if (!Context.getTargetInfo().isValidGCCRegisterName(Label) &&
+ DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl()))
Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
break;
case SC_Static:
case SC_Extern:
case SC_PrivateExtern:
- case SC_OpenCLWorkGroupLocal:
break;
}
} else if (SC == SC_Register) {
// Global Named register
- if (!Context.getTargetInfo().isValidGCCRegisterName(Label))
- Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
+ if (DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) {
+ const auto &TI = Context.getTargetInfo();
+ bool HasSizeMismatch;
+
+ if (!TI.isValidGCCRegisterName(Label))
+ Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label;
+ else if (!TI.validateGlobalRegisterVariable(Label,
+ Context.getTypeSize(R),
+ HasSizeMismatch))
+ Diag(E->getExprLoc(), diag::err_asm_invalid_global_var_reg) << Label;
+ else if (HasSizeMismatch)
+ Diag(E->getExprLoc(), diag::err_asm_register_size_mismatch) << Label;
+ }
+
if (!R->isIntegralType(Context) && !R->isPointerType()) {
Diag(D.getLocStart(), diag::err_asm_bad_register_type);
NewVD->setInvalidDecl(true);
@@ -6011,13 +6145,16 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
Context, Label, 0));
- } else if (!ExtnameUndeclaredIdentifiers.empty() &&
- isDeclTUScopedExternallyVisible(NewVD)) {
+ } else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier());
if (I != ExtnameUndeclaredIdentifiers.end()) {
- NewVD->addAttr(I->second);
- ExtnameUndeclaredIdentifiers.erase(I);
+ if (isDeclExternC(NewVD)) {
+ NewVD->addAttr(I->second);
+ ExtnameUndeclaredIdentifiers.erase(I);
+ } else
+ Diag(NewVD->getLocation(), diag::warn_redefine_extname_not_applied)
+ << /*Variable*/1 << NewVD;
}
}
@@ -6118,6 +6255,22 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
+ // Special handling of variable named 'main'.
+ if (Name.isIdentifier() && Name.getAsIdentifierInfo()->isStr("main") &&
+ NewVD->getDeclContext()->getRedeclContext()->isTranslationUnit() &&
+ !getLangOpts().Freestanding && !NewVD->getDescribedVarTemplate()) {
+
+ // C++ [basic.start.main]p3
+ // A program that declares a variable main at global scope is ill-formed.
+ if (getLangOpts().CPlusPlus)
+ Diag(D.getLocStart(), diag::err_main_global_variable);
+
+ // In C, and external-linkage variable named main results in undefined
+ // behavior.
+ else if (NewVD->hasExternalFormalLinkage())
+ Diag(D.getLocStart(), diag::warn_main_redefined);
+ }
+
if (D.isRedeclaration() && !Previous.empty()) {
checkDLLAttributeRedeclaration(
*this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
@@ -6370,31 +6523,79 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
// This includes arrays of objects with address space qualifiers, but not
// automatic variables that point to other address spaces.
// ISO/IEC TR 18037 S5.1.2
- if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
+ if (!getLangOpts().OpenCL
+ && NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl);
NewVD->setInvalidDecl();
return;
}
- // OpenCL v1.2 s6.5 - All program scope variables must be declared in the
- // __constant address space.
- if (getLangOpts().OpenCL && NewVD->isFileVarDecl()
- && T.getAddressSpace() != LangAS::opencl_constant
- && !T->isSamplerT()){
- Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space);
- NewVD->setInvalidDecl();
- return;
- }
-
// OpenCL v1.2 s6.8 -- The static qualifier is valid only in program
// scope.
- if ((getLangOpts().OpenCLVersion >= 120)
- && NewVD->isStaticLocal()) {
+ if (getLangOpts().OpenCLVersion == 120 &&
+ !getOpenCLOptions().cl_clang_storage_class_specifiers &&
+ NewVD->isStaticLocal()) {
Diag(NewVD->getLocation(), diag::err_static_function_scope);
NewVD->setInvalidDecl();
return;
}
+ // OpenCL v1.2 s6.5 - All program scope variables must be declared in the
+ // __constant address space.
+ // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static
+ // variables inside a function can also be declared in the global
+ // address space.
+ if (getLangOpts().OpenCL) {
+ if (NewVD->isFileVarDecl()) {
+ if (!T->isSamplerT() &&
+ !(T.getAddressSpace() == LangAS::opencl_constant ||
+ (T.getAddressSpace() == LangAS::opencl_global &&
+ getLangOpts().OpenCLVersion == 200))) {
+ if (getLangOpts().OpenCLVersion == 200)
+ Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
+ << "global or constant";
+ else
+ Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
+ << "constant";
+ NewVD->setInvalidDecl();
+ return;
+ }
+ } else {
+ // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static
+ // variables inside a function can also be declared in the global
+ // address space.
+ if (NewVD->isStaticLocal() &&
+ !(T.getAddressSpace() == LangAS::opencl_constant ||
+ (T.getAddressSpace() == LangAS::opencl_global &&
+ getLangOpts().OpenCLVersion == 200))) {
+ if (getLangOpts().OpenCLVersion == 200)
+ Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
+ << "global or constant";
+ else
+ Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
+ << "constant";
+ NewVD->setInvalidDecl();
+ return;
+ }
+ // OpenCL v1.1 s6.5.2 and s6.5.3 no local or constant variables
+ // in functions.
+ if (T.getAddressSpace() == LangAS::opencl_constant ||
+ T.getAddressSpace() == LangAS::opencl_local) {
+ FunctionDecl *FD = getCurFunctionDecl();
+ if (FD && !FD->hasAttr<OpenCLKernelAttr>()) {
+ if (T.getAddressSpace() == LangAS::opencl_constant)
+ Diag(NewVD->getLocation(), diag::err_opencl_non_kernel_variable)
+ << "constant";
+ else
+ Diag(NewVD->getLocation(), diag::err_opencl_non_kernel_variable)
+ << "local";
+ NewVD->setInvalidDecl();
+ return;
+ }
+ }
+ }
+ }
+
if (NewVD->hasLocalStorage() && T.isObjCGCWeak()
&& !NewVD->hasAttr<BlocksAttr>()) {
if (getLangOpts().getGC() != LangOptions::NonGC)
@@ -6506,9 +6707,6 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) {
checkForConflictWithNonVisibleExternC(*this, NewVD, Previous))
Previous.setShadowed();
- // Filter out any non-conflicting previous declarations.
- filterNonConflictingPreviousDecls(*this, NewVD, Previous);
-
if (!Previous.empty()) {
MergeVarDecl(NewVD, Previous);
return true;
@@ -6516,50 +6714,45 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) {
return false;
}
-/// \brief Data used with FindOverriddenMethod
-struct FindOverriddenMethodData {
+namespace {
+struct FindOverriddenMethod {
Sema *S;
CXXMethodDecl *Method;
-};
-/// \brief Member lookup function that determines whether a given C++
-/// method overrides a method in a base class, to be used with
-/// CXXRecordDecl::lookupInBases().
-static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *UserData) {
- RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+ /// Member lookup function that determines whether a given C++
+ /// method overrides a method in a base class, to be used with
+ /// CXXRecordDecl::lookupInBases().
+ bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ RecordDecl *BaseRecord =
+ Specifier->getType()->getAs<RecordType>()->getDecl();
- FindOverriddenMethodData *Data
- = reinterpret_cast<FindOverriddenMethodData*>(UserData);
-
- DeclarationName Name = Data->Method->getDeclName();
-
- // FIXME: Do we care about other names here too?
- if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
- // We really want to find the base class destructor here.
- QualType T = Data->S->Context.getTypeDeclType(BaseRecord);
- CanQualType CT = Data->S->Context.getCanonicalType(T);
-
- Name = Data->S->Context.DeclarationNames.getCXXDestructorName(CT);
- }
-
- for (Path.Decls = BaseRecord->lookup(Name);
- !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- NamedDecl *D = Path.Decls.front();
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false))
- return true;
+ DeclarationName Name = Method->getDeclName();
+
+ // FIXME: Do we care about other names here too?
+ if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+ // We really want to find the base class destructor here.
+ QualType T = S->Context.getTypeDeclType(BaseRecord);
+ CanQualType CT = S->Context.getCanonicalType(T);
+
+ Name = S->Context.DeclarationNames.getCXXDestructorName(CT);
}
+
+ for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
+ Path.Decls = Path.Decls.slice(1)) {
+ NamedDecl *D = Path.Decls.front();
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (MD->isVirtual() && !S->IsOverload(Method, MD, false))
+ return true;
+ }
+ }
+
+ return false;
}
-
- return false;
-}
+};
+
+enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
+} // end anonymous namespace
-namespace {
- enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted };
-}
/// \brief Report an error regarding overriding, along with any relevant
/// overriden methods.
///
@@ -6587,13 +6780,13 @@ static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD,
bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
// Look for methods in base classes that this method might override.
CXXBasePaths Paths;
- FindOverriddenMethodData Data;
- Data.Method = MD;
- Data.S = this;
+ FindOverriddenMethod FOM;
+ FOM.Method = MD;
+ FOM.S = this;
bool hasDeletedOverridenMethods = false;
bool hasNonDeletedOverridenMethods = false;
bool AddedAny = false;
- if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
+ if (DC->lookupInBases(FOM, Paths)) {
for (auto *I : Paths.found_decls()) {
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(I)) {
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
@@ -7200,7 +7393,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
<< DeclSpec::getSpecifierName(TSCS);
if (D.isFirstDeclarationOfMember())
- adjustMemberFunctionCC(R, D.isStaticMember());
+ adjustMemberFunctionCC(R, D.isStaticMember(), D.isCtorOrDtor(),
+ D.getIdentifierLoc());
bool isFriend = false;
FunctionTemplateDecl *FunctionTemplate = nullptr;
@@ -7236,6 +7430,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
bool isExplicit = D.getDeclSpec().isExplicitSpecified();
bool isConstexpr = D.getDeclSpec().isConstexprSpecified();
+ bool isConcept = D.getDeclSpec().isConceptSpecified();
isFriend = D.getDeclSpec().isFriendSpecified();
if (isFriend && !isInline && D.isFunctionDefinition()) {
// C++ [class.friend]p5
@@ -7309,17 +7504,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// For source fidelity, store the other template param lists.
if (TemplateParamLists.size() > 1) {
NewFD->setTemplateParameterListsInfo(Context,
- TemplateParamLists.size() - 1,
- TemplateParamLists.data());
+ TemplateParamLists.drop_back(1));
}
} else {
// This is a function template specialization.
isFunctionTemplateSpecialization = true;
// For source fidelity, store all the template param lists.
if (TemplateParamLists.size() > 0)
- NewFD->setTemplateParameterListsInfo(Context,
- TemplateParamLists.size(),
- TemplateParamLists.data());
+ NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists);
// C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
if (isFriend) {
@@ -7349,9 +7541,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// this is NOT (an explicit specialization of) a template.
if (TemplateParamLists.size() > 0)
// For source fidelity, store all the template param lists.
- NewFD->setTemplateParameterListsInfo(Context,
- TemplateParamLists.size(),
- TemplateParamLists.data());
+ NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists);
}
if (Invalid) {
@@ -7452,6 +7642,67 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor);
}
+ if (isConcept) {
+ // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
+ // applied only to the definition of a function template [...]
+ if (!D.isFunctionDefinition()) {
+ Diag(D.getDeclSpec().getConceptSpecLoc(),
+ diag::err_function_concept_not_defined);
+ NewFD->setInvalidDecl();
+ }
+
+ // C++ Concepts TS [dcl.spec.concept]p1: [...] A function concept shall
+ // have no exception-specification and is treated as if it were specified
+ // with noexcept(true) (15.4). [...]
+ if (const FunctionProtoType *FPT = R->getAs<FunctionProtoType>()) {
+ if (FPT->hasExceptionSpec()) {
+ SourceRange Range;
+ if (D.isFunctionDeclarator())
+ Range = D.getFunctionTypeInfo().getExceptionSpecRange();
+ Diag(NewFD->getLocation(), diag::err_function_concept_exception_spec)
+ << FixItHint::CreateRemoval(Range);
+ NewFD->setInvalidDecl();
+ } else {
+ Context.adjustExceptionSpec(NewFD, EST_BasicNoexcept);
+ }
+
+ // C++ Concepts TS [dcl.spec.concept]p5: A function concept has the
+ // following restrictions:
+ // - The declaration's parameter list shall be equivalent to an empty
+ // parameter list.
+ if (FPT->getNumParams() > 0 || FPT->isVariadic())
+ Diag(NewFD->getLocation(), diag::err_function_concept_with_params);
+ }
+
+ // C++ Concepts TS [dcl.spec.concept]p2: Every concept definition is
+ // implicity defined to be a constexpr declaration (implicitly inline)
+ NewFD->setImplicitlyInline();
+
+ // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not
+ // be declared with the thread_local, inline, friend, or constexpr
+ // specifiers, [...]
+ if (isInline) {
+ Diag(D.getDeclSpec().getInlineSpecLoc(),
+ diag::err_concept_decl_invalid_specifiers)
+ << 1 << 1;
+ NewFD->setInvalidDecl(true);
+ }
+
+ if (isFriend) {
+ Diag(D.getDeclSpec().getFriendSpecLoc(),
+ diag::err_concept_decl_invalid_specifiers)
+ << 1 << 2;
+ NewFD->setInvalidDecl(true);
+ }
+
+ if (isConstexpr) {
+ Diag(D.getDeclSpec().getConstexprSpecLoc(),
+ diag::err_concept_decl_invalid_specifiers)
+ << 1 << 3;
+ NewFD->setInvalidDecl(true);
+ }
+ }
+
// If __module_private__ was specified, mark the function accordingly.
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (isFunctionTemplateSpecialization) {
@@ -7539,13 +7790,16 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
StringLiteral *SE = cast<StringLiteral>(E);
NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
SE->getString(), 0));
- } else if (!ExtnameUndeclaredIdentifiers.empty() &&
- isDeclTUScopedExternallyVisible(NewFD)) {
+ } else if (!ExtnameUndeclaredIdentifiers.empty()) {
llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*>::iterator I =
ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier());
if (I != ExtnameUndeclaredIdentifiers.end()) {
- NewFD->addAttr(I->second);
- ExtnameUndeclaredIdentifiers.erase(I);
+ if (isDeclExternC(NewFD)) {
+ NewFD->addAttr(I->second);
+ ExtnameUndeclaredIdentifiers.erase(I);
+ } else
+ Diag(NewFD->getLocation(), diag::warn_redefine_extname_not_applied)
+ << /*Variable*/0 << NewFD;
}
}
@@ -8002,6 +8256,23 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
for (auto Param : NewFD->params())
checkIsValidOpenCLKernelParameter(*this, D, Param, ValidTypes);
}
+ for (FunctionDecl::param_iterator PI = NewFD->param_begin(),
+ PE = NewFD->param_end(); PI != PE; ++PI) {
+ ParmVarDecl *Param = *PI;
+ QualType PT = Param->getType();
+
+ // OpenCL 2.0 pipe restrictions forbids pipe packet types to be non-value
+ // types.
+ if (getLangOpts().OpenCLVersion >= 200) {
+ if(const PipeType *PipeTy = PT->getAs<PipeType>()) {
+ QualType ElemTy = PipeTy->getElementType();
+ if (ElemTy->isReferenceType() || ElemTy->isPointerType()) {
+ Diag(Param->getTypeSpecStartLoc(), diag::err_reference_pipe_type );
+ D.setInvalidType();
+ }
+ }
+ }
+ }
MarkUnusedFileScopedDecl(NewFD);
@@ -8061,9 +8332,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
bool MergeTypeWithPrevious = !getLangOpts().CPlusPlus &&
!Previous.isShadowed();
- // Filter out any non-conflicting previous declarations.
- filterNonConflictingPreviousDecls(*this, NewFD, Previous);
-
bool Redeclaration = false;
NamedDecl *OldDecl = nullptr;
@@ -8075,7 +8343,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// there's no more work to do here; we'll just add the new
// function to the scope.
if (!AllowOverloadingOfFunction(Previous, Context)) {
- NamedDecl *Candidate = Previous.getFoundDecl();
+ NamedDecl *Candidate = Previous.getRepresentativeDecl();
if (shouldLinkPossiblyHiddenDecl(Candidate, NewFD)) {
Redeclaration = true;
OldDecl = Candidate;
@@ -8117,7 +8385,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// Check for a previous extern "C" declaration with this name.
if (!Redeclaration &&
checkForConflictWithNonVisibleExternC(*this, NewFD, Previous)) {
- filterNonConflictingPreviousDecls(*this, NewFD, Previous);
if (!Previous.empty()) {
// This is an extern "C" declaration with the same name as a previous
// declaration, and thus redeclares that entity...
@@ -8294,7 +8561,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) {
// The type of this function differs from the type of the builtin,
// so forget about the builtin entirely.
- Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents);
+ Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents);
}
}
@@ -8577,9 +8844,8 @@ namespace {
// Convert FieldDecls to their index number.
llvm::SmallVector<unsigned, 4> UsedFieldIndex;
- for (auto I = Fields.rbegin(), E = Fields.rend(); I != E; ++I) {
- UsedFieldIndex.push_back((*I)->getFieldIndex());
- }
+ for (const FieldDecl *I : llvm::reverse(Fields))
+ UsedFieldIndex.push_back(I->getFieldIndex());
// See if a warning is needed by checking the first difference in index
// numbers. If field being used has index less than the field being
@@ -8832,6 +9098,96 @@ namespace {
}
}
+QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
+ DeclarationName Name, QualType Type,
+ TypeSourceInfo *TSI,
+ SourceRange Range, bool DirectInit,
+ Expr *Init) {
+ bool IsInitCapture = !VDecl;
+ assert((!VDecl || !VDecl->isInitCapture()) &&
+ "init captures are expected to be deduced prior to initialization");
+
+ ArrayRef<Expr *> DeduceInits = Init;
+ if (DirectInit) {
+ if (auto *PL = dyn_cast<ParenListExpr>(Init))
+ DeduceInits = PL->exprs();
+ else if (auto *IL = dyn_cast<InitListExpr>(Init))
+ DeduceInits = IL->inits();
+ }
+
+ // Deduction only works if we have exactly one source expression.
+ if (DeduceInits.empty()) {
+ // It isn't possible to write this directly, but it is possible to
+ // end up in this situation with "auto x(some_pack...);"
+ Diag(Init->getLocStart(), IsInitCapture
+ ? diag::err_init_capture_no_expression
+ : diag::err_auto_var_init_no_expression)
+ << Name << Type << Range;
+ return QualType();
+ }
+
+ if (DeduceInits.size() > 1) {
+ Diag(DeduceInits[1]->getLocStart(),
+ IsInitCapture ? diag::err_init_capture_multiple_expressions
+ : diag::err_auto_var_init_multiple_expressions)
+ << Name << Type << Range;
+ return QualType();
+ }
+
+ Expr *DeduceInit = DeduceInits[0];
+ if (DirectInit && isa<InitListExpr>(DeduceInit)) {
+ Diag(Init->getLocStart(), IsInitCapture
+ ? diag::err_init_capture_paren_braces
+ : diag::err_auto_var_init_paren_braces)
+ << isa<InitListExpr>(Init) << Name << Type << Range;
+ return QualType();
+ }
+
+ // Expressions default to 'id' when we're in a debugger.
+ bool DefaultedAnyToId = false;
+ if (getLangOpts().DebuggerCastResultToId &&
+ Init->getType() == Context.UnknownAnyTy && !IsInitCapture) {
+ ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
+ if (Result.isInvalid()) {
+ return QualType();
+ }
+ Init = Result.get();
+ DefaultedAnyToId = true;
+ }
+
+ QualType DeducedType;
+ if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) {
+ if (!IsInitCapture)
+ DiagnoseAutoDeductionFailure(VDecl, DeduceInit);
+ else if (isa<InitListExpr>(Init))
+ Diag(Range.getBegin(),
+ diag::err_init_capture_deduction_failure_from_init_list)
+ << Name
+ << (DeduceInit->getType().isNull() ? TSI->getType()
+ : DeduceInit->getType())
+ << DeduceInit->getSourceRange();
+ else
+ Diag(Range.getBegin(), diag::err_init_capture_deduction_failure)
+ << Name << TSI->getType()
+ << (DeduceInit->getType().isNull() ? TSI->getType()
+ : DeduceInit->getType())
+ << DeduceInit->getSourceRange();
+ }
+
+ // Warn if we deduced 'id'. 'auto' usually implies type-safety, but using
+ // 'id' instead of a specific object type prevents most of our usual
+ // checks.
+ // We only want to warn outside of template instantiations, though:
+ // inside a template, the 'id' could have come from a parameter.
+ if (ActiveTemplateInstantiations.empty() && !DefaultedAnyToId &&
+ !IsInitCapture && !DeducedType.isNull() && DeducedType->isObjCIdType()) {
+ SourceLocation Loc = TSI->getTypeLoc().getBeginLoc();
+ Diag(Loc, diag::warn_auto_var_is_id) << Name << Range;
+ }
+
+ return DeducedType;
+}
+
/// AddInitializerToDecl - Adds the initializer Init to the
/// declaration dcl. If DirectInit is true, this is C++ direct
/// initialization rather than copy initialization.
@@ -8859,79 +9215,27 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
RealDecl->setInvalidDecl();
return;
}
- ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->isUndeducedType()) {
// Attempt typo correction early so that the type of the init expression can
- // be deduced based on the chosen correction:if the original init contains a
+ // be deduced based on the chosen correction if the original init contains a
// TypoExpr.
ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl);
if (!Res.isUsable()) {
RealDecl->setInvalidDecl();
return;
}
+ Init = Res.get();
- if (Res.get() != Init) {
- Init = Res.get();
- if (CXXDirectInit)
- CXXDirectInit = dyn_cast<ParenListExpr>(Init);
- }
-
- Expr *DeduceInit = Init;
- // Initializer could be a C++ direct-initializer. Deduction only works if it
- // contains exactly one expression.
- if (CXXDirectInit) {
- if (CXXDirectInit->getNumExprs() == 0) {
- // It isn't possible to write this directly, but it is possible to
- // end up in this situation with "auto x(some_pack...);"
- Diag(CXXDirectInit->getLocStart(),
- VDecl->isInitCapture() ? diag::err_init_capture_no_expression
- : diag::err_auto_var_init_no_expression)
- << VDecl->getDeclName() << VDecl->getType()
- << VDecl->getSourceRange();
- RealDecl->setInvalidDecl();
- return;
- } else if (CXXDirectInit->getNumExprs() > 1) {
- Diag(CXXDirectInit->getExpr(1)->getLocStart(),
- VDecl->isInitCapture()
- ? diag::err_init_capture_multiple_expressions
- : diag::err_auto_var_init_multiple_expressions)
- << VDecl->getDeclName() << VDecl->getType()
- << VDecl->getSourceRange();
- RealDecl->setInvalidDecl();
- return;
- } else {
- DeduceInit = CXXDirectInit->getExpr(0);
- if (isa<InitListExpr>(DeduceInit))
- Diag(CXXDirectInit->getLocStart(),
- diag::err_auto_var_init_paren_braces)
- << VDecl->getDeclName() << VDecl->getType()
- << VDecl->getSourceRange();
- }
- }
-
- // Expressions default to 'id' when we're in a debugger.
- bool DefaultedToAuto = false;
- if (getLangOpts().DebuggerCastResultToId &&
- Init->getType() == Context.UnknownAnyTy) {
- ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
- if (Result.isInvalid()) {
- VDecl->setInvalidDecl();
- return;
- }
- Init = Result.get();
- DefaultedToAuto = true;
- }
-
- QualType DeducedType;
- if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) ==
- DAR_Failed)
- DiagnoseAutoDeductionFailure(VDecl, DeduceInit);
+ QualType DeducedType = deduceVarTypeFromInitializer(
+ VDecl, VDecl->getDeclName(), VDecl->getType(),
+ VDecl->getTypeSourceInfo(), VDecl->getSourceRange(), DirectInit, Init);
if (DeducedType.isNull()) {
RealDecl->setInvalidDecl();
return;
}
+
VDecl->setType(DeducedType);
assert(VDecl->isLinkageValid());
@@ -8939,38 +9243,18 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl))
VDecl->setInvalidDecl();
- // Warn if we deduced 'id'. 'auto' usually implies type-safety, but using
- // 'id' instead of a specific object type prevents most of our usual checks.
- // We only want to warn outside of template instantiations, though:
- // inside a template, the 'id' could have come from a parameter.
- if (ActiveTemplateInstantiations.empty() && !DefaultedToAuto &&
- DeducedType->isObjCIdType()) {
- SourceLocation Loc =
- VDecl->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
- Diag(Loc, diag::warn_auto_var_is_id)
- << VDecl->getDeclName() << DeduceInit->getSourceRange();
- }
-
// If this is a redeclaration, check that the type we just deduced matches
// the previously declared type.
if (VarDecl *Old = VDecl->getPreviousDecl()) {
// We never need to merge the type, because we cannot form an incomplete
// array of auto, nor deduce such a type.
- MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/false);
+ MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/ false);
}
// Check the deduced type is valid for a variable declaration.
CheckVariableDeclarationType(VDecl);
if (VDecl->isInvalidDecl())
return;
-
- // If all looks well, warn if this is a case that will change meaning when
- // we implement N3922.
- if (DirectInit && !CXXDirectInit && isa<InitListExpr>(Init)) {
- Diag(Init->getLocStart(),
- diag::warn_auto_var_direct_list_init)
- << FixItHint::CreateInsertion(Init->getLocStart(), "=");
- }
}
// dllimport cannot be used on variable definitions.
@@ -9059,7 +9343,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// OpenCL 1.1 6.5.2: "Variables allocated in the __local address space inside
// a kernel function cannot be initialized."
- if (VDecl->getStorageClass() == SC_OpenCLWorkGroupLocal) {
+ if (VDecl->getType().getAddressSpace() == LangAS::opencl_local) {
Diag(VDecl->getLocation(), diag::err_local_cant_init);
VDecl->setInvalidDecl();
return;
@@ -9082,17 +9366,18 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
}
// Perform the initialization.
+ ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
if (!VDecl->isInvalidDecl()) {
InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
- InitializationKind Kind
- = DirectInit ?
- CXXDirectInit ? InitializationKind::CreateDirect(VDecl->getLocation(),
- Init->getLocStart(),
- Init->getLocEnd())
- : InitializationKind::CreateDirectList(
- VDecl->getLocation())
- : InitializationKind::CreateCopy(VDecl->getLocation(),
- Init->getLocStart());
+ InitializationKind Kind =
+ DirectInit
+ ? CXXDirectInit
+ ? InitializationKind::CreateDirect(VDecl->getLocation(),
+ Init->getLocStart(),
+ Init->getLocEnd())
+ : InitializationKind::CreateDirectList(VDecl->getLocation())
+ : InitializationKind::CreateCopy(VDecl->getLocation(),
+ Init->getLocStart());
MultiExprArg Args = Init;
if (CXXDirectInit)
@@ -9156,7 +9441,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if (VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
Init->getLocStart()))
- getCurFunction()->markSafeWeakUse(Init);
+ getCurFunction()->markSafeWeakUse(Init);
}
// The initialization is usually a full-expression.
@@ -9409,6 +9694,15 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
return;
}
+ // C++ Concepts TS [dcl.spec.concept]p1: [...] A variable template
+ // definition having the concept specifier is called a variable concept. A
+ // concept definition refers to [...] a variable concept and its initializer.
+ if (Var->isConcept()) {
+ Diag(Var->getLocation(), diag::err_var_concept_not_initialized);
+ Var->setInvalidDecl();
+ return;
+ }
+
// OpenCL v1.1 s6.5.3: variables declared in the constant address space must
// be initialized.
if (!Var->isInvalidDecl() &&
@@ -9621,8 +9915,6 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) {
case SC_Register:
Error = 4;
break;
- case SC_OpenCLWorkGroupLocal:
- llvm_unreachable("Unexpected storage class");
}
if (Error != -1) {
Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class)
@@ -9665,9 +9957,9 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (var->isInvalidDecl()) return;
- // In ARC, don't allow jumps past the implicit initialization of a
+ // In Objective-C, don't allow jumps past the implicit initialization of a
// local retaining variable.
- if (getLangOpts().ObjCAutoRefCount &&
+ if (getLangOpts().ObjC1 &&
var->hasLocalStorage()) {
switch (var->getType().getObjCLifetime()) {
case Qualifiers::OCL_None:
@@ -9913,9 +10205,17 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
// dllimport/dllexport variables cannot be thread local, their TLS index
// isn't exported with the variable.
if (DLLAttr && VD->getTLSKind()) {
- Diag(VD->getLocation(), diag::err_attribute_dll_thread_local) << VD
- << DLLAttr;
- VD->setInvalidDecl();
+ auto *F = dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod());
+ if (F && getDLLAttr(F)) {
+ assert(VD->isStaticLocal());
+ // But if this is a static local in a dlimport/dllexport function, the
+ // function will never be inlined, which means the var would never be
+ // imported, so having it marked import/export is safe.
+ } else {
+ Diag(VD->getLocation(), diag::err_attribute_dll_thread_local) << VD
+ << DLLAttr;
+ VD->setInvalidDecl();
+ }
}
if (UsedAttr *Attr = VD->getAttr<UsedAttr>()) {
@@ -9988,8 +10288,9 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (DeclSpec::isDeclRep(DS.getTypeSpecType())) {
if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) {
handleTagNumbering(Tag, S);
- if (!Tag->hasNameForLinkage() && !Tag->hasDeclaratorForAnonDecl())
- Tag->setDeclaratorForAnonDecl(FirstDeclaratorInGroup);
+ if (FirstDeclaratorInGroup && !Tag->hasNameForLinkage() &&
+ getLangOpts().CPlusPlus)
+ Context.addDeclaratorForUnnamedTagDecl(Tag, FirstDeclaratorInGroup);
}
}
@@ -10028,7 +10329,7 @@ Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group,
} else if (DeducedCanon != UCanon) {
Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
diag::err_auto_different_deductions)
- << (AT->isDecltypeAuto() ? 1 : 0)
+ << (unsigned)AT->getKeyword()
<< Deduced << DeducedDecl->getDeclName()
<< U << D->getDeclName()
<< DeducedDecl->getInit()->getSourceRange()
@@ -10118,6 +10419,8 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
if (DS.isConstexprSpecified())
Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 0;
+ if (DS.isConceptSpecified())
+ Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind);
DiagnoseFunctionSpecifiers(DS);
@@ -10370,14 +10673,17 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
}
}
-Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
+Decl *
+Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ SkipBodyInfo *SkipBody) {
assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
assert(D.isFunctionDeclarator() && "Not a function declarator!");
Scope *ParentScope = FnBodyScope->getParent();
D.setFunctionDefinitionKind(FDK_Definition);
- Decl *DP = HandleDeclarator(ParentScope, D, MultiTemplateParamsArg());
- return ActOnStartOfFunctionDef(FnBodyScope, DP);
+ Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists);
+ return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
}
void Sema::ActOnFinishInlineMethodDef(CXXMethodDecl *D) {
@@ -10441,7 +10747,8 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
void
Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
- const FunctionDecl *EffectiveDefinition) {
+ const FunctionDecl *EffectiveDefinition,
+ SkipBodyInfo *SkipBody) {
// Don't complain if we're in GNU89 mode and the previous definition
// was an extern inline function.
const FunctionDecl *Definition = EffectiveDefinition;
@@ -10453,17 +10760,20 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
return;
// If we don't have a visible definition of the function, and it's inline or
- // a template, it's OK to form another definition of it.
- //
- // FIXME: Should we skip the body of the function and use the old definition
- // in this case? That may be necessary for functions that return local types
- // through a deduced return type, or instantiate templates with local types.
- if (!hasVisibleDefinition(Definition) &&
+ // a template, skip the new definition.
+ if (SkipBody && !hasVisibleDefinition(Definition) &&
(Definition->getFormalLinkage() == InternalLinkage ||
Definition->isInlined() ||
Definition->getDescribedFunctionTemplate() ||
- Definition->getNumTemplateParameterLists()))
+ Definition->getNumTemplateParameterLists())) {
+ SkipBody->ShouldSkip = true;
+ if (auto *TD = Definition->getDescribedFunctionTemplate())
+ makeMergedDefinitionVisible(TD, FD->getLocation());
+ else
+ makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition),
+ FD->getLocation());
return;
+ }
if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
Definition->getStorageClass() == SC_Extern)
@@ -10524,7 +10834,8 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
}
}
-Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
+Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
+ SkipBodyInfo *SkipBody) {
// Clear the last template instantiation error context.
LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
@@ -10536,6 +10847,16 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
FD = FunTmpl->getTemplatedDecl();
else
FD = cast<FunctionDecl>(D);
+
+ // See if this is a redefinition.
+ if (!FD->isLateTemplateParsed()) {
+ CheckForFunctionRedefinition(FD, nullptr, SkipBody);
+
+ // If we're skipping the body, we're done. Don't enter the scope.
+ if (SkipBody && SkipBody->ShouldSkip)
+ return D;
+ }
+
// If we are instantiating a generic lambda call operator, push
// a LambdaScopeInfo onto the function stack. But use the information
// that's already been calculated (ActOnLambdaExpr) to prime the current
@@ -10555,10 +10876,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// Enter a new function scope
PushFunctionScope();
- // See if this is a redefinition.
- if (!FD->isLateTemplateParsed())
- CheckForFunctionRedefinition(FD);
-
// Builtin functions cannot be defined.
if (unsigned BuiltinID = FD->getBuiltinID()) {
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) &&
@@ -10610,12 +10927,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// from the translation unit and reattach to the current context.
if (D->getLexicalDeclContext() == Context.getTranslationUnitDecl()) {
// Is the decl actually in the context?
- for (const auto *DI : Context.getTranslationUnitDecl()->decls()) {
- if (DI == D) {
- Context.getTranslationUnitDecl()->removeDecl(D);
- break;
- }
- }
+ if (Context.getTranslationUnitDecl()->containsDecl(D))
+ Context.getTranslationUnitDecl()->removeDecl(D);
// Either way, reassign the lexical decl context to our FunctionDecl.
D->setLexicalDeclContext(CurContext);
}
@@ -10734,6 +11047,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
+ if (getLangOpts().Coroutines && !getCurFunction()->CoroutineStmts.empty())
+ CheckCompletedCoroutineBody(FD, Body);
+
if (FD) {
FD->setBody(Body);
@@ -11073,7 +11389,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
/*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc,
EST_None,
- /*ESpecLoc=*/NoLoc,
+ /*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
@@ -11159,6 +11475,18 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
FD->addAttr(NoThrowAttr::CreateImplicit(Context, FD->getLocation()));
if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->hasAttr<ConstAttr>())
FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation()));
+ if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads &&
+ Context.BuiltinInfo.isTSBuiltin(BuiltinID) &&
+ !FD->hasAttr<CUDADeviceAttr>() && !FD->hasAttr<CUDAHostAttr>()) {
+ // Assign appropriate attribute depending on CUDA compilation
+ // mode and the target builtin belongs to. E.g. during host
+ // compilation, aux builtins are __device__, the rest are __host__.
+ if (getLangOpts().CUDAIsDevice !=
+ Context.BuiltinInfo.isAuxBuiltinID(BuiltinID))
+ FD->addAttr(CUDADeviceAttr::CreateImplicit(Context, FD->getLocation()));
+ else
+ FD->addAttr(CUDAHostAttr::CreateImplicit(Context, FD->getLocation()));
+ }
}
IdentifierInfo *Name = FD->getIdentifier();
@@ -11269,9 +11597,9 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
/// Check whether this is a valid redeclaration of a previous enumeration.
/// \return true if the redeclaration was invalid.
-bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
- QualType EnumUnderlyingTy,
- const EnumDecl *Prev) {
+bool Sema::CheckEnumRedeclaration(
+ SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy,
+ bool EnumUnderlyingIsImplicit, const EnumDecl *Prev) {
bool IsFixed = !EnumUnderlyingTy.isNull();
if (IsScoped != Prev->isScoped()) {
@@ -11293,6 +11621,10 @@ bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
<< Prev->getIntegerTypeRange();
return true;
}
+ } else if (IsFixed && !Prev->isFixed() && EnumUnderlyingIsImplicit) {
+ ;
+ } else if (!IsFixed && Prev->isFixed() && !Prev->getIntegerTypeSourceInfo()) {
+ ;
} else if (IsFixed != Prev->isFixed()) {
Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch)
<< Prev->isFixed();
@@ -11459,7 +11791,6 @@ static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S,
std::reverse(Namespaces.begin(), Namespaces.end());
for (auto *II : Namespaces)
OS << II->getName() << "::";
- OS.flush();
return FixItHint::CreateInsertion(NameLoc, Insertion);
}
@@ -11484,6 +11815,28 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC,
return false;
}
+/// Find the DeclContext in which a tag is implicitly declared if we see an
+/// elaborated type specifier in the specified context, and lookup finds
+/// nothing.
+static DeclContext *getTagInjectionContext(DeclContext *DC) {
+ while (!DC->isFileContext() && !DC->isFunctionOrMethod())
+ DC = DC->getParent();
+ return DC;
+}
+
+/// Find the Scope in which a tag is implicitly declared if we see an
+/// elaborated type specifier in the specified context, and lookup finds
+/// nothing.
+static Scope *getTagInjectionScope(Scope *S, const LangOptions &LangOpts) {
+ while (S->isClassScope() ||
+ (LangOpts.CPlusPlus &&
+ S->isFunctionPrototypeScope()) ||
+ ((S->getFlags() & Scope::DeclScope) == 0) ||
+ (S->getEntity() && S->getEntity()->isTransparentContext()))
+ S = S->getParent();
+ return S;
+}
+
/// \brief This is invoked when we see 'struct foo' or 'struct {'. In the
/// former case, Name will be non-null. In the later case, Name will be null.
/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
@@ -11563,6 +11916,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// this early, because it's needed to detect if this is an incompatible
// redeclaration.
llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying;
+ bool EnumUnderlyingIsImplicit = false;
if (Kind == TTK_Enum) {
if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum))
@@ -11584,9 +11938,13 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
UPPC_FixedUnderlyingType))
EnumUnderlying = Context.IntTy.getTypePtr();
- } else if (getLangOpts().MSVCCompat)
- // Microsoft enums are always of int type.
- EnumUnderlying = Context.IntTy.getTypePtr();
+ } else if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ if (getLangOpts().MSVCCompat || TUK == TUK_Definition) {
+ // Microsoft enums are always of int type.
+ EnumUnderlying = Context.IntTy.getTypePtr();
+ EnumUnderlyingIsImplicit = true;
+ }
+ }
}
DeclContext *SearchDC = CurContext;
@@ -11795,16 +12153,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Find the context where we'll be declaring the tag.
// FIXME: We would like to maintain the current DeclContext as the
// lexical context,
- while (!SearchDC->isFileContext() && !SearchDC->isFunctionOrMethod())
- SearchDC = SearchDC->getParent();
+ SearchDC = getTagInjectionContext(SearchDC);
// Find the scope where we'll be declaring the tag.
- while (S->isClassScope() ||
- (getLangOpts().CPlusPlus &&
- S->isFunctionPrototypeScope()) ||
- ((S->getFlags() & Scope::DeclScope) == 0) ||
- (S->getEntity() && S->getEntity()->isTransparentContext()))
- S = S->getParent();
+ S = getTagInjectionScope(S, getLangOpts());
} else {
assert(TUK == TUK_Friend);
// C++ [namespace.memdef]p3:
@@ -11816,9 +12168,16 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// In C++, we need to do a redeclaration lookup to properly
// diagnose some problems.
+ // FIXME: redeclaration lookup is also used (with and without C++) to find a
+ // hidden declaration so that we don't get ambiguity errors when using a
+ // type declared by an elaborated-type-specifier. In C that is not correct
+ // and we should instead merge compatible types found by lookup.
if (getLangOpts().CPlusPlus) {
Previous.setRedeclarationKind(ForRedeclaration);
LookupQualifiedName(Previous, SearchDC);
+ } else {
+ Previous.setRedeclarationKind(ForRedeclaration);
+ LookupName(Previous, S);
}
}
@@ -11932,7 +12291,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// returning the previous declaration, unless this is a definition,
// in which case we want the caller to bail out.
if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc,
- ScopedEnum, EnumUnderlyingTy, PrevEnum))
+ ScopedEnum, EnumUnderlyingTy,
+ EnumUnderlyingIsImplicit, PrevEnum))
return TUK == TUK_Declaration ? PrevTagDecl : nullptr;
}
@@ -11949,16 +12309,34 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (!Invalid) {
// If this is a use, just return the declaration we found, unless
// we have attributes.
-
- // FIXME: In the future, return a variant or some other clue
- // for the consumer of this Decl to know it doesn't own it.
- // For our current ASTs this shouldn't be a problem, but will
- // need to be changed with DeclGroups.
- if (!Attr &&
- ((TUK == TUK_Reference &&
- (!PrevTagDecl->getFriendObjectKind() || getLangOpts().MicrosoftExt))
- || TUK == TUK_Friend))
- return PrevTagDecl;
+ if (TUK == TUK_Reference || TUK == TUK_Friend) {
+ if (Attr) {
+ // FIXME: Diagnose these attributes. For now, we create a new
+ // declaration to hold them.
+ } else if (TUK == TUK_Reference &&
+ (PrevTagDecl->getFriendObjectKind() ==
+ Decl::FOK_Undeclared ||
+ PP.getModuleContainingLocation(
+ PrevDecl->getLocation()) !=
+ PP.getModuleContainingLocation(KWLoc)) &&
+ SS.isEmpty()) {
+ // This declaration is a reference to an existing entity, but
+ // has different visibility from that entity: it either makes
+ // a friend visible or it makes a type visible in a new module.
+ // In either case, create a new declaration. We only do this if
+ // the declaration would have meant the same thing if no prior
+ // declaration were found, that is, if it was found in the same
+ // scope where we would have injected a declaration.
+ if (!getTagInjectionContext(CurContext)->getRedeclContext()
+ ->Equals(PrevDecl->getDeclContext()->getRedeclContext()))
+ return PrevTagDecl;
+ // This is in the injected scope, create a new declaration in
+ // that scope.
+ S = getTagInjectionScope(S, getLangOpts());
+ } else {
+ return PrevTagDecl;
+ }
+ }
// Diagnose attempts to redefine a tag.
if (TUK == TUK_Definition) {
@@ -12203,9 +12581,7 @@ CreateNewDecl:
New->setQualifierInfo(SS.getWithLocInContext(Context));
if (TemplateParameterLists.size() > 0) {
- New->setTemplateParameterListsInfo(Context,
- TemplateParameterLists.size(),
- TemplateParameterLists.data());
+ New->setTemplateParameterListsInfo(Context, TemplateParameterLists);
}
}
else
@@ -12258,7 +12634,7 @@ CreateNewDecl:
<< Name;
Invalid = true;
}
- } else {
+ } else if (!PrevDecl) {
Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
}
DeclsInPrototypeScope.push_back(New);
@@ -12504,26 +12880,41 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
}
if (!FieldTy->isDependentType()) {
- uint64_t TypeSize = Context.getTypeSize(FieldTy);
- if (Value.getZExtValue() > TypeSize) {
- if (!getLangOpts().CPlusPlus || IsMsStruct ||
- Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- if (FieldName)
- return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size)
- << FieldName << (unsigned)Value.getZExtValue()
- << (unsigned)TypeSize;
-
- return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_size)
- << (unsigned)Value.getZExtValue() << (unsigned)TypeSize;
- }
-
+ uint64_t TypeStorageSize = Context.getTypeSize(FieldTy);
+ uint64_t TypeWidth = Context.getIntWidth(FieldTy);
+ bool BitfieldIsOverwide = Value.ugt(TypeWidth);
+
+ // Over-wide bitfields are an error in C or when using the MSVC bitfield
+ // ABI.
+ bool CStdConstraintViolation =
+ BitfieldIsOverwide && !getLangOpts().CPlusPlus;
+ bool MSBitfieldViolation =
+ Value.ugt(TypeStorageSize) &&
+ (IsMsStruct || Context.getTargetInfo().getCXXABI().isMicrosoft());
+ if (CStdConstraintViolation || MSBitfieldViolation) {
+ unsigned DiagWidth =
+ CStdConstraintViolation ? TypeWidth : TypeStorageSize;
if (FieldName)
- Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_size)
- << FieldName << (unsigned)Value.getZExtValue()
- << (unsigned)TypeSize;
+ return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width)
+ << FieldName << (unsigned)Value.getZExtValue()
+ << !CStdConstraintViolation << DiagWidth;
+
+ return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_width)
+ << (unsigned)Value.getZExtValue() << !CStdConstraintViolation
+ << DiagWidth;
+ }
+
+ // Warn on types where the user might conceivably expect to get all
+ // specified bits as value bits: that's all integral types other than
+ // 'bool'.
+ if (BitfieldIsOverwide && !FieldTy->isBooleanType()) {
+ if (FieldName)
+ Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width)
+ << FieldName << (unsigned)Value.getZExtValue()
+ << (unsigned)TypeWidth;
else
- Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_size)
- << (unsigned)Value.getZExtValue() << (unsigned)TypeSize;
+ Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_width)
+ << (unsigned)Value.getZExtValue() << (unsigned)TypeWidth;
}
}
@@ -12866,9 +13257,8 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
SourceLocation Loc = FD->getLocation();
if (getSourceManager().isInSystemHeader(Loc)) {
if (!FD->hasAttr<UnavailableAttr>())
- FD->addAttr(UnavailableAttr::CreateImplicit(Context,
- "this system field has retaining ownership",
- Loc));
+ FD->addAttr(UnavailableAttr::CreateImplicit(Context, "",
+ UnavailableAttr::IR_ARCFieldWithOwnership, Loc));
return false;
}
}
@@ -12876,7 +13266,7 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
Diag(FD->getLocation(), getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member :
diag::err_illegal_union_or_anon_struct_member)
- << (int)FD->getParent()->isUnion() << FD->getDeclName() << member;
+ << FD->getParent()->isUnion() << FD->getDeclName() << member;
DiagnoseNontrivial(RDecl, member);
return !getLangOpts().CPlusPlus11;
}
@@ -13237,9 +13627,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
SourceLocation loc = FD->getLocation();
if (getSourceManager().isInSystemHeader(loc)) {
if (!FD->hasAttr<UnavailableAttr>()) {
- FD->addAttr(UnavailableAttr::CreateImplicit(Context,
- "this system field has retaining ownership",
- loc));
+ FD->addAttr(UnavailableAttr::CreateImplicit(Context, "",
+ UnavailableAttr::IR_ARCFieldWithOwnership, loc));
}
} else {
Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag)
@@ -13687,10 +14076,12 @@ Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II,
NamedDecl *PrevDecl = LookupSingleName(S, II, IILoc, LookupOrdinaryName,
ForRedeclaration);
auto *PrevECD = dyn_cast_or_null<EnumConstantDecl>(PrevDecl);
+ if (!PrevECD)
+ return SkipBodyInfo();
+
+ EnumDecl *PrevED = cast<EnumDecl>(PrevECD->getDeclContext());
NamedDecl *Hidden;
- if (PrevECD &&
- !hasVisibleDefinition(cast<NamedDecl>(PrevECD->getDeclContext()),
- &Hidden)) {
+ if (!PrevED->getDeclName() && !hasVisibleDefinition(PrevED, &Hidden)) {
SkipBodyInfo Skip;
Skip.Previous = Hidden;
return Skip;
@@ -13722,12 +14113,27 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
PrevDecl = nullptr;
}
+ // C++ [class.mem]p15:
+ // If T is the name of a class, then each of the following shall have a name
+ // different from T:
+ // - every enumerator of every member of class T that is an unscoped
+ // enumerated type
+ if (!TheEnumDecl->isScoped())
+ DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(),
+ DeclarationNameInfo(Id, IdLoc));
+
+ EnumConstantDecl *New =
+ CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val);
+ if (!New)
+ return nullptr;
+
if (PrevDecl) {
// When in C++, we may get a TagDecl with the same name; in this case the
// enum constant will 'hide' the tag.
assert((getLangOpts().CPlusPlus || !isa<TagDecl>(PrevDecl)) &&
"Received TagDecl when not in C++!");
- if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) {
+ if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S) &&
+ shouldLinkPossiblyHiddenDecl(PrevDecl, New)) {
if (isa<EnumConstantDecl>(PrevDecl))
Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;
else
@@ -13737,26 +14143,12 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
}
}
- // C++ [class.mem]p15:
- // If T is the name of a class, then each of the following shall have a name
- // different from T:
- // - every enumerator of every member of class T that is an unscoped
- // enumerated type
- if (!TheEnumDecl->isScoped())
- DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(),
- DeclarationNameInfo(Id, IdLoc));
-
- EnumConstantDecl *New =
- CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val);
-
- if (New) {
- // Process attributes.
- if (Attr) ProcessDeclAttributeList(S, New, Attr);
+ // Process attributes.
+ if (Attr) ProcessDeclAttributeList(S, New, Attr);
- // Register this decl in the current scope stack.
- New->setAccess(TheEnumDecl->getAccess());
- PushOnScopeChains(New, S);
- }
+ // Register this decl in the current scope stack.
+ New->setAccess(TheEnumDecl->getAccess());
+ PushOnScopeChains(New, S);
ActOnDocumentableDecl(New);
@@ -13803,6 +14195,7 @@ static bool ValidDuplicateEnum(EnumConstantDecl *ECD, EnumDecl *Enum) {
return false;
}
+namespace {
struct DupKey {
int64_t val;
bool isTombstoneOrEmptyKey;
@@ -13826,6 +14219,7 @@ struct DenseMapInfoDupKey {
LHS.val == RHS.val;
}
};
+} // end anonymous namespace
// Emits a warning when an element is implicitly set a value that
// a previous element has already been set to.
@@ -13937,17 +14331,22 @@ static void CheckForDuplicateEnumValues(Sema &S, ArrayRef<Decl *> Elements,
}
}
-bool
-Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
- bool AllowMask) const {
- FlagEnumAttr *FEAttr = ED->getAttr<FlagEnumAttr>();
- assert(FEAttr && "looking for value in non-flag enum");
+bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
+ bool AllowMask) const {
+ assert(ED->hasAttr<FlagEnumAttr>() && "looking for value in non-flag enum");
+ assert(ED->isCompleteDefinition() && "expected enum definition");
- llvm::APInt FlagMask = ~FEAttr->getFlagBits();
- unsigned Width = FlagMask.getBitWidth();
+ auto R = FlagBitsCache.insert(std::make_pair(ED, llvm::APInt()));
+ llvm::APInt &FlagBits = R.first->second;
- // We will try a zero-extended value for the regular check first.
- llvm::APInt ExtVal = Val.zextOrSelf(Width);
+ if (R.second) {
+ for (auto *E : ED->enumerators()) {
+ const auto &EVal = E->getInitVal();
+ // Only single-bit enumerators introduce new flag values.
+ if (EVal.isPowerOf2())
+ FlagBits = FlagBits.zextOrSelf(EVal.getBitWidth()) | EVal;
+ }
+ }
// A value is in a flag enum if either its bits are a subset of the enum's
// flag bits (the first condition) or we are allowing masks and the same is
@@ -13957,27 +14356,8 @@ Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
// While it's true that any value could be used as a mask, the assumption is
// that a mask will have all of the insignificant bits set. Anything else is
// likely a logic error.
- if (!(FlagMask & ExtVal))
- return true;
-
- if (AllowMask) {
- // Try a one-extended value instead. This can happen if the enum is wider
- // than the constant used, in C with extensions to allow for wider enums.
- // The mask will still have the correct behaviour, so we give the user the
- // benefit of the doubt.
- //
- // FIXME: This heuristic can cause weird results if the enum was extended
- // to a larger type and is signed, because then bit-masks of smaller types
- // that get extended will fall out of range (e.g. ~0x1u). We currently don't
- // detect that case and will get a false positive for it. In most cases,
- // though, it can be fixed by making it a signed type (e.g. ~0x1), so it may
- // be fine just to accept this as a warning.
- ExtVal |= llvm::APInt::getHighBitsSet(Width, Width - Val.getBitWidth());
- if (!(FlagMask & ~ExtVal))
- return true;
- }
-
- return false;
+ llvm::APInt FlagMask = ~FlagBits.zextOrTrunc(Val.getBitWidth());
+ return !(FlagMask & Val) || (AllowMask && !(FlagMask & ~Val));
}
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
@@ -14131,13 +14511,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
}
}
- FlagEnumAttr *FEAttr = Enum->getAttr<FlagEnumAttr>();
- if (FEAttr)
- FEAttr->getFlagBits() = llvm::APInt(BestWidth, 0);
-
// Loop over all of the enumerator constants, changing their types to match
- // the type of the enum if needed. If we have a flag type, we also prepare the
- // FlagBits cache.
+ // the type of the enum if needed.
for (auto *D : Elements) {
auto *ECD = cast_or_null<EnumConstantDecl>(D);
if (!ECD) continue; // Already issued a diagnostic.
@@ -14169,7 +14544,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// enum-specifier, each enumerator has the type of its
// enumeration.
ECD->setType(EnumType);
- goto flagbits;
+ continue;
} else {
NewTy = BestType;
NewWidth = BestWidth;
@@ -14196,37 +14571,26 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
ECD->setType(EnumType);
else
ECD->setType(NewTy);
-
-flagbits:
- // Check to see if we have a constant with exactly one bit set. Note that x
- // & (x - 1) will be nonzero if and only if x has more than one bit set.
- if (FEAttr) {
- llvm::APInt ExtVal = InitVal.zextOrSelf(BestWidth);
- if (ExtVal != 0 && !(ExtVal & (ExtVal - 1))) {
- FEAttr->getFlagBits() |= ExtVal;
- }
- }
}
- if (FEAttr) {
+ Enum->completeDefinition(BestType, BestPromotionType,
+ NumPositiveBits, NumNegativeBits);
+
+ CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType);
+
+ if (Enum->hasAttr<FlagEnumAttr>()) {
for (Decl *D : Elements) {
EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(D);
if (!ECD) continue; // Already issued a diagnostic.
llvm::APSInt InitVal = ECD->getInitVal();
- if (InitVal != 0 && !IsValueInFlagEnum(Enum, InitVal, true))
+ if (InitVal != 0 && !InitVal.isPowerOf2() &&
+ !IsValueInFlagEnum(Enum, InitVal, true))
Diag(ECD->getLocation(), diag::warn_flag_enum_constant_out_of_range)
<< ECD << Enum;
}
}
-
-
- Enum->completeDefinition(BestType, BestPromotionType,
- NumPositiveBits, NumNegativeBits);
-
- CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType);
-
// Now that the enum type is defined, ensure it's not been underaligned.
if (Enum->hasAttrs())
CheckAlignasUnderalignment(Enum);
@@ -14245,17 +14609,15 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
}
static void checkModuleImportContext(Sema &S, Module *M,
- SourceLocation ImportLoc,
- DeclContext *DC) {
+ SourceLocation ImportLoc, DeclContext *DC,
+ bool FromInclude = false) {
+ SourceLocation ExternCLoc;
+
if (auto *LSD = dyn_cast<LinkageSpecDecl>(DC)) {
switch (LSD->getLanguage()) {
case LinkageSpecDecl::lang_c:
- if (!M->IsExternC) {
- S.Diag(ImportLoc, diag::err_module_import_in_extern_c)
- << M->getFullModuleName();
- S.Diag(LSD->getLocStart(), diag::note_module_import_in_extern_c);
- return;
- }
+ if (ExternCLoc.isInvalid())
+ ExternCLoc = LSD->getLocStart();
break;
case LinkageSpecDecl::lang_cxx:
break;
@@ -14265,15 +14627,25 @@ static void checkModuleImportContext(Sema &S, Module *M,
while (isa<LinkageSpecDecl>(DC))
DC = DC->getParent();
+
if (!isa<TranslationUnitDecl>(DC)) {
- S.Diag(ImportLoc, diag::err_module_import_not_at_top_level)
- << M->getFullModuleName() << DC;
+ S.Diag(ImportLoc, (FromInclude && S.isModuleVisible(M))
+ ? diag::ext_module_import_not_at_top_level_noop
+ : diag::err_module_import_not_at_top_level_fatal)
+ << M->getFullModuleName() << DC;
S.Diag(cast<Decl>(DC)->getLocStart(),
- diag::note_module_import_not_at_top_level)
- << DC;
+ diag::note_module_import_not_at_top_level) << DC;
+ } else if (!M->IsExternC && ExternCLoc.isValid()) {
+ S.Diag(ImportLoc, diag::ext_module_import_in_extern_c)
+ << M->getFullModuleName();
+ S.Diag(ExternCLoc, diag::note_module_import_in_extern_c);
}
}
+void Sema::diagnoseMisplacedModuleImport(Module *M, SourceLocation ImportLoc) {
+ return checkModuleImportContext(*this, M, ImportLoc, CurContext);
+}
+
DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
SourceLocation ImportLoc,
ModuleIdPath Path) {
@@ -14318,7 +14690,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
}
void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
- checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
+ checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true);
// Determine whether we're in the #include buffer for a module. The #includes
// in that buffer do not qualify as module imports; they're just an
@@ -14394,12 +14766,14 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
// 1) declares a function or a variable
// 2) has external linkage
// already exists, add a label attribute to it.
- if (PrevDecl &&
- (isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl)) &&
- PrevDecl->hasExternalFormalLinkage())
- PrevDecl->addAttr(Attr);
+ if (PrevDecl && (isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl))) {
+ if (isDeclExternC(PrevDecl))
+ PrevDecl->addAttr(Attr);
+ else
+ Diag(PrevDecl->getLocation(), diag::warn_redefine_extname_not_applied)
+ << /*Variable*/(isa<FunctionDecl>(PrevDecl) ? 0 : 1) << PrevDecl;
// Otherwise, add a label atttibute to ExtnameUndeclaredIdentifiers.
- else
+ } else
(void)ExtnameUndeclaredIdentifiers.insert(std::make_pair(Name, Attr));
}
@@ -14426,7 +14800,7 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
LookupOrdinaryName);
WeakInfo W = WeakInfo(Name, NameLoc);
- if (PrevDecl) {
+ if (PrevDecl && (isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl))) {
if (!PrevDecl->hasAttr<AliasAttr>())
if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl))
DeclApplyPragmaWeak(TUScope, ND, W);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
index 191dbd0..f94c822 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -244,11 +244,12 @@ static bool checkUInt32Argument(Sema &S, const AttributeList &Attr,
/// \brief Diagnose mutually exclusive attributes when present on a given
/// declaration. Returns true if diagnosed.
template <typename AttrTy>
-static bool checkAttrMutualExclusion(Sema &S, Decl *D,
- const AttributeList &Attr) {
+static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range,
+ IdentifierInfo *Ident) {
if (AttrTy *A = D->getAttr<AttrTy>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << Attr.getName() << A;
+ S.Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) << Ident
+ << A;
+ S.Diag(A->getLocation(), diag::note_conflicting_attribute);
return true;
}
return false;
@@ -315,7 +316,7 @@ bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
Diag(Loc->Loc, diag::err_attribute_argument_type)
<< Attr.getName() << AANT_ArgumentString
<< FixItHint::CreateInsertion(Loc->Loc, "\"")
- << FixItHint::CreateInsertion(PP.getLocForEndOfToken(Loc->Loc), "\"");
+ << FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\"");
Str = Loc->Ident->getName();
if (ArgLocation)
*ArgLocation = Loc->Loc;
@@ -347,6 +348,25 @@ static void handleSimpleAttribute(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+template <typename AttrType>
+static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ handleSimpleAttribute<AttrType>(S, D, Attr);
+}
+
+/// \brief Applies the given attribute to the Decl so long as the Decl doesn't
+/// already have one of the given incompatible attributes.
+template <typename AttrType, typename IncompatibleAttrType,
+ typename... IncompatibleAttrTypes>
+static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+ handleSimpleAttributeWithExclusions<AttrType, IncompatibleAttrTypes...>(S, D,
+ Attr);
+}
+
/// \brief Check if the passed-in expression is of type int or bool.
static bool isIntOrBool(Expr *Exp) {
QualType QT = Exp->getType();
@@ -432,11 +452,10 @@ static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
// Else check if any base classes have a capability.
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
CXXBasePaths BPaths(false, false);
- if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &P,
- void *) {
- return BS->getType()->getAs<RecordType>()
- ->getDecl()->hasAttr<CapabilityAttr>();
- }, nullptr, BPaths))
+ if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &) {
+ const auto *Type = BS->getType()->getAs<RecordType>();
+ return Type->getDecl()->hasAttr<CapabilityAttr>();
+ }, BPaths))
return true;
}
return false;
@@ -629,13 +648,10 @@ static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
// Check that this attribute only applies to lockable types.
QualType QT = cast<ValueDecl>(D)->getType();
- if (!QT->isDependentType()) {
- const RecordType *RT = getRecordType(QT);
- if (!RT || !RT->getDecl()->hasAttr<CapabilityAttr>()) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
- << Attr.getName();
- return false;
- }
+ if (!QT->isDependentType() && !typeHasCapability(S, QT)) {
+ S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
+ << Attr.getName();
+ return false;
}
// Check that all arguments are lockable objects.
@@ -812,6 +828,43 @@ static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
+static void handlePassObjectSizeAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (D->hasAttr<PassObjectSizeAttr>()) {
+ S.Diag(D->getLocStart(), diag::err_attribute_only_once_per_parameter)
+ << Attr.getName();
+ return;
+ }
+
+ Expr *E = Attr.getArgAsExpr(0);
+ uint32_t Type;
+ if (!checkUInt32Argument(S, Attr, E, Type, /*Idx=*/1))
+ return;
+
+ // pass_object_size's argument is passed in as the second argument of
+ // __builtin_object_size. So, it has the same constraints as that second
+ // argument; namely, it must be in the range [0, 3].
+ if (Type > 3) {
+ S.Diag(E->getLocStart(), diag::err_attribute_argument_outof_range)
+ << Attr.getName() << 0 << 3 << E->getSourceRange();
+ return;
+ }
+
+ // pass_object_size is only supported on constant pointer parameters; as a
+ // kindness to users, we allow the parameter to be non-const for declarations.
+ // At this point, we have no clue if `D` belongs to a function declaration or
+ // definition, so we defer the constness check until later.
+ if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) {
+ S.Diag(D->getLocStart(), diag::err_attribute_pointers_only)
+ << Attr.getName() << 1;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ PassObjectSizeAttr(Attr.getRange(), S.Context, (int)Type,
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
ConsumableAttr::ConsumedState DefaultState;
@@ -1039,17 +1092,14 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
- // If the alignment is less than or equal to 8 bits, the packed attribute
- // has no effect.
+ // Report warning about changed offset in the newer compiler versions.
if (!FD->getType()->isDependentType() &&
- !FD->getType()->isIncompleteType() &&
+ !FD->getType()->isIncompleteType() && FD->isBitField() &&
S.Context.getTypeAlign(FD->getType()) <= 8)
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
- << Attr.getName() << FD->getType();
- else
- FD->addAttr(::new (S.Context)
- PackedAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ S.Diag(Attr.getLoc(), diag::warn_attribute_packed_for_bitfield);
+
+ FD->addAttr(::new (S.Context) PackedAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
} else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
@@ -1165,10 +1215,12 @@ static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr,
SourceRange TypeRange,
bool isReturnValue = false) {
if (!S.isValidPointerAttrType(T)) {
- S.Diag(Attr.getLoc(), isReturnValue
- ? diag::warn_attribute_return_pointers_only
- : diag::warn_attribute_pointers_only)
- << Attr.getName() << AttrParmRange << TypeRange;
+ if (isReturnValue)
+ S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
+ << Attr.getName() << AttrParmRange << TypeRange;
+ else
+ S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only)
+ << Attr.getName() << AttrParmRange << TypeRange << 0;
return false;
}
return true;
@@ -1312,6 +1364,17 @@ void Sema::AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
AssumeAlignedAttr(AttrRange, Context, E, OE, SpellingListIndex));
}
+/// Normalize the attribute, __foo__ becomes foo.
+/// Returns true if normalization was applied.
+static bool normalizeName(StringRef &AttrName) {
+ if (AttrName.size() > 4 && AttrName.startswith("__") &&
+ AttrName.endswith("__")) {
+ AttrName = AttrName.drop_front(2).drop_back(2);
+ return true;
+ }
+ return false;
+}
+
static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
// This attribute must be applied to a function declaration. The first
// argument to the attribute must be an identifier, the name of the resource,
@@ -1353,11 +1416,8 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident;
- // Normalize the argument, __foo__ becomes foo.
StringRef ModuleName = Module->getName();
- if (ModuleName.startswith("__") && ModuleName.endswith("__") &&
- ModuleName.size() > 4) {
- ModuleName = ModuleName.drop_front(2).drop_back(2);
+ if (normalizeName(ModuleName)) {
Module = &S.PP.getIdentifierTable().get(ModuleName);
}
@@ -1519,7 +1579,7 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<HotAttr>(S, D, Attr))
+ if (checkAttrMutualExclusion<HotAttr>(S, D, Attr.getRange(), Attr.getName()))
return;
D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context,
@@ -1527,7 +1587,7 @@ static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr))
+ if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr.getRange(), Attr.getName()))
return;
D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context,
@@ -1569,12 +1629,22 @@ static void handleRestrictAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CPlusPlus) {
S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
- << Attr.getName() << AttributeLangSupport::Cpp;
+ << Attr.getName() << AttributeLangSupport::Cpp;
return;
}
- D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
+ if (CommonAttr *CA = S.mergeCommonAttr(D, Attr.getRange(), Attr.getName(),
+ Attr.getAttributeSpellingListIndex()))
+ D->addAttr(CA);
+}
+
+static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+
+ D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
}
static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
@@ -1613,7 +1683,7 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
!VD->getType()->isFunctionPointerType())) {
S.Diag(Attr.getLoc(),
Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type
- : diag::warn_attribute_wrong_decl_type)
+ : diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionMethodOrBlock;
return;
}
@@ -1697,6 +1767,26 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+static void handleNotTailCalledAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<AlwaysInlineAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+
+ D->addAttr(::new (S.Context) NotTailCalledAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleDisableTailCallsAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<NakedAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+
+ D->addAttr(::new (S.Context) DisableTailCallsAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+}
+
static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasLocalStorage()) {
@@ -1825,12 +1915,24 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
VersionTuple Obsoleted,
bool IsUnavailable,
StringRef Message,
- bool Override,
+ AvailabilityMergeKind AMK,
unsigned AttrSpellingListIndex) {
VersionTuple MergedIntroduced = Introduced;
VersionTuple MergedDeprecated = Deprecated;
VersionTuple MergedObsoleted = Obsoleted;
bool FoundAny = false;
+ bool OverrideOrImpl = false;
+ switch (AMK) {
+ case AMK_None:
+ case AMK_Redeclaration:
+ OverrideOrImpl = false;
+ break;
+
+ case AMK_Override:
+ case AMK_ProtocolImplementation:
+ OverrideOrImpl = true;
+ break;
+ }
if (D->hasAttrs()) {
AttrVec &Attrs = D->getAttrs();
@@ -1847,30 +1949,46 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
continue;
}
+ // If there is an existing availability attribute for this platform that
+ // is explicit and the new one is implicit use the explicit one and
+ // discard the new implicit attribute.
+ if (OldAA->getRange().isValid() && Range.isInvalid()) {
+ return nullptr;
+ }
+
+ // If there is an existing attribute for this platform that is implicit
+ // and the new attribute is explicit then erase the old one and
+ // continue processing the attributes.
+ if (Range.isValid() && OldAA->getRange().isInvalid()) {
+ Attrs.erase(Attrs.begin() + i);
+ --e;
+ continue;
+ }
+
FoundAny = true;
VersionTuple OldIntroduced = OldAA->getIntroduced();
VersionTuple OldDeprecated = OldAA->getDeprecated();
VersionTuple OldObsoleted = OldAA->getObsoleted();
bool OldIsUnavailable = OldAA->getUnavailable();
- if (!versionsMatch(OldIntroduced, Introduced, Override) ||
- !versionsMatch(Deprecated, OldDeprecated, Override) ||
- !versionsMatch(Obsoleted, OldObsoleted, Override) ||
+ if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl) ||
+ !versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl) ||
+ !versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl) ||
!(OldIsUnavailable == IsUnavailable ||
- (Override && !OldIsUnavailable && IsUnavailable))) {
- if (Override) {
+ (OverrideOrImpl && !OldIsUnavailable && IsUnavailable))) {
+ if (OverrideOrImpl) {
int Which = -1;
VersionTuple FirstVersion;
VersionTuple SecondVersion;
- if (!versionsMatch(OldIntroduced, Introduced, Override)) {
+ if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl)) {
Which = 0;
FirstVersion = OldIntroduced;
SecondVersion = Introduced;
- } else if (!versionsMatch(Deprecated, OldDeprecated, Override)) {
+ } else if (!versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl)) {
Which = 1;
FirstVersion = Deprecated;
SecondVersion = OldDeprecated;
- } else if (!versionsMatch(Obsoleted, OldObsoleted, Override)) {
+ } else if (!versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl)) {
Which = 2;
FirstVersion = Obsoleted;
SecondVersion = OldObsoleted;
@@ -1879,15 +1997,20 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
if (Which == -1) {
Diag(OldAA->getLocation(),
diag::warn_mismatched_availability_override_unavail)
- << AvailabilityAttr::getPrettyPlatformName(Platform->getName());
+ << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
+ << (AMK == AMK_Override);
} else {
Diag(OldAA->getLocation(),
diag::warn_mismatched_availability_override)
<< Which
<< AvailabilityAttr::getPrettyPlatformName(Platform->getName())
- << FirstVersion.getAsString() << SecondVersion.getAsString();
+ << FirstVersion.getAsString() << SecondVersion.getAsString()
+ << (AMK == AMK_Override);
}
- Diag(Range.getBegin(), diag::note_overridden_method);
+ if (AMK == AMK_Override)
+ Diag(Range.getBegin(), diag::note_overridden_method);
+ else
+ Diag(Range.getBegin(), diag::note_protocol_method);
} else {
Diag(OldAA->getLocation(), diag::warn_mismatched_availability);
Diag(Range.getBegin(), diag::note_previous_attribute);
@@ -1930,11 +2053,11 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
MergedObsoleted == Obsoleted)
return nullptr;
- // Only create a new attribute if !Override, but we want to do
+ // Only create a new attribute if !OverrideOrImpl, but we want to do
// the checking.
if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced,
MergedDeprecated, MergedObsoleted) &&
- !Override) {
+ !OverrideOrImpl) {
return ::new (Context) AvailabilityAttr(Range, Context, Platform,
Introduced, Deprecated,
Obsoleted, IsUnavailable, Message,
@@ -1975,10 +2098,78 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
Deprecated.Version,
Obsoleted.Version,
IsUnavailable, Str,
- /*Override=*/false,
+ Sema::AMK_None,
Index);
if (NewAttr)
D->addAttr(NewAttr);
+
+ // Transcribe "ios" to "watchos" (and add a new attribute) if the versioning
+ // matches before the start of the watchOS platform.
+ if (S.Context.getTargetInfo().getTriple().isWatchOS()) {
+ IdentifierInfo *NewII = nullptr;
+ if (II->getName() == "ios")
+ NewII = &S.Context.Idents.get("watchos");
+ else if (II->getName() == "ios_app_extension")
+ NewII = &S.Context.Idents.get("watchos_app_extension");
+
+ if (NewII) {
+ auto adjustWatchOSVersion = [](VersionTuple Version) -> VersionTuple {
+ if (Version.empty())
+ return Version;
+ auto Major = Version.getMajor();
+ auto NewMajor = Major >= 9 ? Major - 7 : 0;
+ if (NewMajor >= 2) {
+ if (Version.getMinor().hasValue()) {
+ if (Version.getSubminor().hasValue())
+ return VersionTuple(NewMajor, Version.getMinor().getValue(),
+ Version.getSubminor().getValue());
+ else
+ return VersionTuple(NewMajor, Version.getMinor().getValue());
+ }
+ }
+
+ return VersionTuple(2, 0);
+ };
+
+ auto NewIntroduced = adjustWatchOSVersion(Introduced.Version);
+ auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version);
+ auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version);
+
+ AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND,
+ SourceRange(),
+ NewII,
+ NewIntroduced,
+ NewDeprecated,
+ NewObsoleted,
+ IsUnavailable, Str,
+ Sema::AMK_None,
+ Index);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+ }
+ } else if (S.Context.getTargetInfo().getTriple().isTvOS()) {
+ // Transcribe "ios" to "tvos" (and add a new attribute) if the versioning
+ // matches before the start of the tvOS platform.
+ IdentifierInfo *NewII = nullptr;
+ if (II->getName() == "ios")
+ NewII = &S.Context.Idents.get("tvos");
+ else if (II->getName() == "ios_app_extension")
+ NewII = &S.Context.Idents.get("tvos_app_extension");
+
+ if (NewII) {
+ AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND,
+ SourceRange(),
+ NewII,
+ Introduced.Version,
+ Deprecated.Version,
+ Obsoleted.Version,
+ IsUnavailable, Str,
+ Sema::AMK_None,
+ Index);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+ }
+ }
}
template <class T>
@@ -2492,17 +2683,17 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, IdxExpr, Idx))
return;
- // make sure the format string is really a string
+ // Make sure the format string is really a string.
QualType Ty = getFunctionOrMethodParamType(D, Idx);
- bool not_nsstring_type = !isNSStringType(Ty, S.Context);
- if (not_nsstring_type &&
+ bool NotNSStringTy = !isNSStringType(Ty, S.Context);
+ if (NotNSStringTy &&
!isCFStringType(Ty, S.Context) &&
(!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
- << (not_nsstring_type ? "a string type" : "an NSString")
- << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
+ << "a string type" << IdxExpr->getSourceRange()
+ << getFunctionOrMethodParamRange(D, 0);
return;
}
Ty = getFunctionOrMethodResultType(D);
@@ -2511,7 +2702,7 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
(!Ty->isPointerType() ||
!Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
- << (not_nsstring_type ? "string type" : "NSString")
+ << (NotNSStringTy ? "string type" : "NSString")
<< IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
return;
}
@@ -2588,7 +2779,7 @@ static void handleInitPriorityAttr(Sema &S, Decl *D,
if (prioritynum < 101 || prioritynum > 65535) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
- << E->getSourceRange();
+ << E->getSourceRange() << Attr.getName() << 101 << 65535;
Attr.setInvalid();
return;
}
@@ -2635,9 +2826,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
StringRef Format = II->getName();
- // Normalize the argument, __foo__ becomes foo.
- if (Format.startswith("__") && Format.endswith("__")) {
- Format = Format.substr(2, Format.size() - 4);
+ if (normalizeName(Format)) {
// If we've modified the string name, we need a new identifier for it.
II = &S.Context.Idents.get(Format);
}
@@ -2858,7 +3047,7 @@ void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
}
if (!E->isValueDependent()) {
- llvm::APSInt Alignment(32);
+ llvm::APSInt Alignment;
ExprResult ICE
= VerifyIntegerConstantExpression(E, &Alignment,
diag::err_align_value_attribute_argument_not_int,
@@ -2972,7 +3161,7 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
}
// FIXME: Cache the number on the Attr object?
- llvm::APSInt Alignment(32);
+ llvm::APSInt Alignment;
ExprResult ICE
= VerifyIntegerConstantExpression(E, &Alignment,
diag::err_aligned_attribute_argument_not_int,
@@ -2980,42 +3169,44 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
if (ICE.isInvalid())
return;
+ uint64_t AlignVal = Alignment.getZExtValue();
+
// C++11 [dcl.align]p2:
// -- if the constant expression evaluates to zero, the alignment
// specifier shall have no effect
// C11 6.7.5p6:
// An alignment specification of zero has no effect.
if (!(TmpAttr.isAlignas() && !Alignment)) {
- if(!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
+ if (!llvm::isPowerOf2_64(AlignVal)) {
Diag(AttrLoc, diag::err_alignment_not_power_of_two)
<< E->getSourceRange();
return;
}
- if (Context.getTargetInfo().isTLSSupported()) {
- if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
- if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->getTLSKind()) {
- CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
- if (Alignment.getSExtValue() > MaxAlignChars.getQuantity()) {
- Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
- << (unsigned)Alignment.getZExtValue() << VD
- << (unsigned)MaxAlignChars.getQuantity();
- return;
- }
- }
- }
- }
- }
}
// Alignment calculations can wrap around if it's greater than 2**28.
- unsigned MaxValidAlignment = TmpAttr.isDeclspec() ? 8192 : 268435456;
- if (Alignment.getZExtValue() > MaxValidAlignment) {
+ unsigned MaxValidAlignment =
+ Context.getTargetInfo().getTriple().isOSBinFormatCOFF() ? 8192
+ : 268435456;
+ if (AlignVal > MaxValidAlignment) {
Diag(AttrLoc, diag::err_attribute_aligned_too_great) << MaxValidAlignment
<< E->getSourceRange();
return;
}
+ if (Context.getTargetInfo().isTLSSupported()) {
+ unsigned MaxTLSAlign =
+ Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign())
+ .getQuantity();
+ auto *VD = dyn_cast<VarDecl>(D);
+ if (MaxTLSAlign && AlignVal > MaxTLSAlign && VD &&
+ VD->getTLSKind() != VarDecl::TLS_None) {
+ Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
+ << (unsigned)AlignVal << VD << MaxTLSAlign;
+ return;
+ }
+ }
+
AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true,
ICE.get(), SpellingListIndex);
AA->setPackExpansion(IsPackExpansion);
@@ -3098,40 +3289,31 @@ bool Sema::checkMSInheritanceAttrOnDefinition(
return true;
}
-/// handleModeAttr - This attribute modifies the width of a decl with primitive
-/// type.
-///
-/// Despite what would be logical, the mode attribute is a decl attribute, not a
-/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
-/// HImode, not an intermediate pointer.
-static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // This attribute isn't documented, but glibc uses it. It changes
- // the width of an int or unsigned int to the specified size.
- if (!Attr.isArgIdent(0)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
- << AANT_ArgumentIdentifier;
- return;
- }
-
- IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
- StringRef Str = Name->getName();
-
- // Normalize the attribute name, __foo__ becomes foo.
- if (Str.startswith("__") && Str.endswith("__"))
- Str = Str.substr(2, Str.size() - 4);
-
- unsigned DestWidth = 0;
- bool IntegerMode = true;
- bool ComplexMode = false;
+/// parseModeAttrArg - Parses attribute mode string and returns parsed type
+/// attribute.
+static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
+ bool &IntegerMode, bool &ComplexMode) {
switch (Str.size()) {
case 2:
switch (Str[0]) {
- case 'Q': DestWidth = 8; break;
- case 'H': DestWidth = 16; break;
- case 'S': DestWidth = 32; break;
- case 'D': DestWidth = 64; break;
- case 'X': DestWidth = 96; break;
- case 'T': DestWidth = 128; break;
+ case 'Q':
+ DestWidth = 8;
+ break;
+ case 'H':
+ DestWidth = 16;
+ break;
+ case 'S':
+ DestWidth = 32;
+ break;
+ case 'D':
+ DestWidth = 64;
+ break;
+ case 'X':
+ DestWidth = 96;
+ break;
+ case 'T':
+ DestWidth = 128;
+ break;
}
if (Str[1] == 'F') {
IntegerMode = false;
@@ -3159,6 +3341,52 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
DestWidth = S.Context.getTargetInfo().getUnwindWordWidth();
break;
}
+}
+
+/// handleModeAttr - This attribute modifies the width of a decl with primitive
+/// type.
+///
+/// Despite what would be logical, the mode attribute is a decl attribute, not a
+/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
+/// HImode, not an intermediate pointer.
+static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ // This attribute isn't documented, but glibc uses it. It changes
+ // the width of an int or unsigned int to the specified size.
+ if (!Attr.isArgIdent(0)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+ << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
+ StringRef Str = Name->getName();
+
+ normalizeName(Str);
+
+ unsigned DestWidth = 0;
+ bool IntegerMode = true;
+ bool ComplexMode = false;
+ llvm::APInt VectorSize(64, 0);
+ if (Str.size() >= 4 && Str[0] == 'V') {
+ // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2).
+ size_t StrSize = Str.size();
+ size_t VectorStringLength = 0;
+ while ((VectorStringLength + 1) < StrSize &&
+ isdigit(Str[VectorStringLength + 1]))
+ ++VectorStringLength;
+ if (VectorStringLength &&
+ !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
+ VectorSize.isPowerOf2()) {
+ parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth,
+ IntegerMode, ComplexMode);
+ S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated);
+ } else {
+ VectorSize = 0;
+ }
+ }
+
+ if (!VectorSize)
+ parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode);
QualType OldTy;
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
@@ -3217,7 +3445,10 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
QualType NewTy = NewElemTy;
- if (const VectorType *OldVT = OldTy->getAs<VectorType>()) {
+ if (VectorSize.getBoolValue()) {
+ NewTy = S.Context.getVectorType(NewTy, VectorSize.getZExtValue(),
+ VectorType::GenericVector);
+ } else if (const VectorType *OldVT = OldTy->getAs<VectorType>()) {
// Complex machine mode does not support base vector types.
if (ComplexMode) {
S.Diag(Attr.getLoc(), diag::err_complex_mode_vector_type);
@@ -3280,6 +3511,42 @@ AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
AttrSpellingListIndex);
}
+CommonAttr *Sema::mergeCommonAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Ident,
+ unsigned AttrSpellingListIndex) {
+ if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, Range, Ident))
+ return nullptr;
+
+ return ::new (Context) CommonAttr(Range, Context, AttrSpellingListIndex);
+}
+
+InternalLinkageAttr *
+Sema::mergeInternalLinkageAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Ident,
+ unsigned AttrSpellingListIndex) {
+ if (auto VD = dyn_cast<VarDecl>(D)) {
+ // Attribute applies to Var but not any subclass of it (like ParmVar,
+ // ImplicitParm or VarTemplateSpecialization).
+ if (VD->getKind() != Decl::Var) {
+ Diag(Range.getBegin(), diag::warn_attribute_wrong_decl_type)
+ << Ident << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
+ : ExpectedVariableOrFunction);
+ return nullptr;
+ }
+ // Attribute does not apply to non-static local variables.
+ if (VD->hasLocalStorage()) {
+ Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage);
+ return nullptr;
+ }
+ }
+
+ if (checkAttrMutualExclusion<CommonAttr>(*this, D, Range, Ident))
+ return nullptr;
+
+ return ::new (Context)
+ InternalLinkageAttr(Range, Context, AttrSpellingListIndex);
+}
+
MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex) {
if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
@@ -3316,6 +3583,10 @@ OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
static void handleAlwaysInlineAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+
if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr(
D, Attr.getRange(), Attr.getName(),
Attr.getAttributeSpellingListIndex()))
@@ -3336,6 +3607,12 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D,
}
static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, Attr.getRange(),
+ Attr.getName()) ||
+ checkAttrMutualExclusion<CUDAHostAttr>(S, D, Attr.getRange(),
+ Attr.getName())) {
+ return;
+ }
FunctionDecl *FD = cast<FunctionDecl>(D);
if (!FD->getReturnType()->isVoidType()) {
SourceRange RTRange = FD->getReturnTypeSourceRange();
@@ -3349,6 +3626,7 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
D->addAttr(::new (S.Context)
CUDAGlobalAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
+
}
static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -3645,7 +3923,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
QualType BufferTy = getFunctionOrMethodParamType(D, ArgumentIdx);
if (!BufferTy->isPointerType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
- << Attr.getName();
+ << Attr.getName() << 0;
}
}
@@ -3898,7 +4176,8 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
static void handleCFAuditedTransferAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr))
+ if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
return;
D->addAttr(::new (S.Context)
@@ -3908,7 +4187,8 @@ static void handleCFAuditedTransferAttr(Sema &S, Decl *D,
static void handleCFUnknownTransferAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr))
+ if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
return;
D->addAttr(::new (S.Context)
@@ -4231,10 +4511,74 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D,
D->addAttr(UsedAttr::CreateImplicit(S.Context));
}
+static void handleMipsInterruptAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ // Only one optional argument permitted.
+ if (Attr.getNumArgs() > 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
+ << Attr.getName() << 1;
+ return;
+ }
+
+ StringRef Str;
+ SourceLocation ArgLoc;
+
+ if (Attr.getNumArgs() == 0)
+ Str = "";
+ else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
+ return;
+
+ // Semantic checks for a function with the 'interrupt' attribute for MIPS:
+ // a) Must be a function.
+ // b) Must have no parameters.
+ // c) Must have the 'void' return type.
+ // d) Cannot have the 'mips16' attribute, as that instruction set
+ // lacks the 'eret' instruction.
+ // e) The attribute itself must either have no argument or one of the
+ // valid interrupt types, see [MipsInterruptDocs].
+
+ if (!isFunctionOrMethod(D)) {
+ S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
+ << "'interrupt'" << ExpectedFunctionOrMethod;
+ return;
+ }
+
+ if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
+ S.Diag(D->getLocation(), diag::warn_mips_interrupt_attribute)
+ << 0;
+ return;
+ }
+
+ if (!getFunctionOrMethodResultType(D)->isVoidType()) {
+ S.Diag(D->getLocation(), diag::warn_mips_interrupt_attribute)
+ << 1;
+ return;
+ }
+
+ if (checkAttrMutualExclusion<Mips16Attr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+
+ MipsInterruptAttr::InterruptType Kind;
+ if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+ << Attr.getName() << "'" + std::string(Str) + "'";
+ return;
+ }
+
+ D->addAttr(::new (S.Context) MipsInterruptAttr(
+ Attr.getLoc(), S.Context, Kind, Attr.getAttributeSpellingListIndex()));
+}
+
static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// Dispatch the interrupt attribute based on the current target.
if (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::msp430)
handleMSP430InterruptAttr(S, D, Attr);
+ else if (S.Context.getTargetInfo().getTriple().getArch() ==
+ llvm::Triple::mipsel ||
+ S.Context.getTargetInfo().getTriple().getArch() ==
+ llvm::Triple::mips)
+ handleMipsInterruptAttr(S, D, Attr);
else
handleARMInterruptAttr(S, D, Attr);
}
@@ -4334,6 +4678,14 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
}
}
+ if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ MD->getParent()->isLambda()) {
+ S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A.getName();
+ return;
+ }
+ }
+
unsigned Index = A.getAttributeSpellingListIndex();
Attr *NewAttr = A.getKind() == AttributeList::AT_DLLExport
? (Attr *)S.mergeDLLExportAttr(D, A.getRange(), Index)
@@ -4509,8 +4861,10 @@ static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
+ StringRef AttrName = Attr.getName()->getName();
+ normalizeName(AttrName);
std::string SanitizerName =
- llvm::StringSwitch<std::string>(Attr.getName()->getName())
+ llvm::StringSwitch<std::string>(AttrName)
.Case("no_address_safety_analysis", "address")
.Case("no_sanitize_address", "address")
.Case("no_sanitize_thread", "thread")
@@ -4520,6 +4874,14 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+static void handleInternalLinkageAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (InternalLinkageAttr *Internal =
+ S.mergeInternalLinkageAttr(D, Attr.getRange(), Attr.getName(),
+ Attr.getAttributeSpellingListIndex()))
+ D->addAttr(Internal);
+}
+
/// Handles semantic checking for features that are common to all attributes,
/// such as checking whether a parameter was properly specified, or the correct
/// number of arguments were passed, etc.
@@ -4583,7 +4945,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
// which do not apply to the current target architecture are treated as
// though they were unknown attributes.
if (Attr.getKind() == AttributeList::UnknownAttribute ||
- !Attr.existsInTarget(S.Context.getTargetInfo().getTriple())) {
+ !Attr.existsInTarget(S.Context.getTargetInfo())) {
S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute()
? diag::warn_unhandled_ms_attribute_ignored
: diag::warn_unknown_attribute_ignored)
@@ -4610,7 +4972,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleDLLAttr(S, D, Attr);
break;
case AttributeList::AT_Mips16:
- handleSimpleAttribute<Mips16Attr>(S, D, Attr);
+ handleSimpleAttributeWithExclusions<Mips16Attr, MipsInterruptAttr>(S, D,
+ Attr);
break;
case AttributeList::AT_NoMips16:
handleSimpleAttribute<NoMips16Attr>(S, D, Attr);
@@ -4661,7 +5024,11 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleCommonAttr(S, D, Attr);
break;
case AttributeList::AT_CUDAConstant:
- handleSimpleAttribute<CUDAConstantAttr>(S, D, Attr);
+ handleSimpleAttributeWithExclusions<CUDAConstantAttr, CUDASharedAttr>(S, D,
+ Attr);
+ break;
+ case AttributeList::AT_PassObjectSize:
+ handlePassObjectSizeAttr(S, D, Attr);
break;
case AttributeList::AT_Constructor:
handleConstructorAttr(S, D, Attr);
@@ -4703,10 +5070,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleGlobalAttr(S, D, Attr);
break;
case AttributeList::AT_CUDADevice:
- handleSimpleAttribute<CUDADeviceAttr>(S, D, Attr);
+ handleSimpleAttributeWithExclusions<CUDADeviceAttr, CUDAGlobalAttr>(S, D,
+ Attr);
break;
case AttributeList::AT_CUDAHost:
- handleSimpleAttribute<CUDAHostAttr>(S, D, Attr);
+ handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D,
+ Attr);
break;
case AttributeList::AT_GNUInline:
handleGNUInlineAttr(S, D, Attr);
@@ -4723,6 +5092,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_Mode:
handleModeAttr(S, D, Attr);
break;
+ case AttributeList::AT_NoAlias:
+ handleSimpleAttribute<NoAliasAttr>(S, D, Attr);
+ break;
case AttributeList::AT_NoCommon:
handleSimpleAttribute<NoCommonAttr>(S, D, Attr);
break;
@@ -4754,7 +5126,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleHotAttr(S, D, Attr);
break;
case AttributeList::AT_Naked:
- handleSimpleAttribute<NakedAttr>(S, D, Attr);
+ handleNakedAttr(S, D, Attr);
break;
case AttributeList::AT_NoReturn:
handleNoReturnAttr(S, D, Attr);
@@ -4763,7 +5135,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleSimpleAttribute<NoThrowAttr>(S, D, Attr);
break;
case AttributeList::AT_CUDAShared:
- handleSimpleAttribute<CUDASharedAttr>(S, D, Attr);
+ handleSimpleAttributeWithExclusions<CUDASharedAttr, CUDAConstantAttr>(S, D,
+ Attr);
break;
case AttributeList::AT_VecReturn:
handleVecReturnAttr(S, D, Attr);
@@ -4874,6 +5247,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ReturnsTwice:
handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr);
break;
+ case AttributeList::AT_NotTailCalled:
+ handleNotTailCalledAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_DisableTailCalls:
+ handleDisableTailCallsAttr(S, D, Attr);
+ break;
case AttributeList::AT_Used:
handleUsedAttr(S, D, Attr);
break;
@@ -4958,6 +5337,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_OpenCLImageAccess:
handleSimpleAttribute<OpenCLImageAccessAttr>(S, D, Attr);
break;
+ case AttributeList::AT_InternalLinkage:
+ handleInternalLinkageAttr(S, D, Attr);
+ break;
// Microsoft attributes:
case AttributeList::AT_MSNoVTable:
@@ -5299,26 +5681,50 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
}
/// Is the given declaration allowed to use a forbidden type?
-static bool isForbiddenTypeAllowed(Sema &S, Decl *decl) {
+/// If so, it'll still be annotated with an attribute that makes it
+/// illegal to actually use.
+static bool isForbiddenTypeAllowed(Sema &S, Decl *decl,
+ const DelayedDiagnostic &diag,
+ UnavailableAttr::ImplicitReason &reason) {
// Private ivars are always okay. Unfortunately, people don't
// always properly make their ivars private, even in system headers.
// Plus we need to make fields okay, too.
- // Function declarations in sys headers will be marked unavailable.
if (!isa<FieldDecl>(decl) && !isa<ObjCPropertyDecl>(decl) &&
!isa<FunctionDecl>(decl))
return false;
- // Require it to be declared in a system header.
- return S.Context.getSourceManager().isInSystemHeader(decl->getLocation());
+ // Silently accept unsupported uses of __weak in both user and system
+ // declarations when it's been disabled, for ease of integration with
+ // -fno-objc-arc files. We do have to take some care against attempts
+ // to define such things; for now, we've only done that for ivars
+ // and properties.
+ if ((isa<ObjCIvarDecl>(decl) || isa<ObjCPropertyDecl>(decl))) {
+ if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled ||
+ diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) {
+ reason = UnavailableAttr::IR_ForbiddenWeak;
+ return true;
+ }
+ }
+
+ // Allow all sorts of things in system headers.
+ if (S.Context.getSourceManager().isInSystemHeader(decl->getLocation())) {
+ // Currently, all the failures dealt with this way are due to ARC
+ // restrictions.
+ reason = UnavailableAttr::IR_ARCForbiddenType;
+ return true;
+ }
+
+ return false;
}
/// Handle a delayed forbidden-type diagnostic.
static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag,
Decl *decl) {
- if (decl && isForbiddenTypeAllowed(S, decl)) {
- decl->addAttr(UnavailableAttr::CreateImplicit(S.Context,
- "this system declaration uses an unsupported type",
- diag.Loc));
+ auto reason = UnavailableAttr::IR_None;
+ if (decl && isForbiddenTypeAllowed(S, decl, diag, reason)) {
+ assert(reason && "didn't set reason?");
+ decl->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", reason,
+ diag.Loc));
return;
}
if (S.getLangOpts().ObjCAutoRefCount)
@@ -5371,6 +5777,7 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
bool ObjCPropertyAccess) {
// Diagnostics for deprecated or unavailable.
unsigned diag, diag_message, diag_fwdclass_message;
+ unsigned diag_available_here = diag::note_availability_specified_here;
// Matches 'diag::note_property_attribute' options.
unsigned property_note_select;
@@ -5400,6 +5807,50 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
diag_fwdclass_message = diag::warn_unavailable_fwdclass_message;
property_note_select = /* unavailable */ 1;
available_here_select_kind = /* unavailable */ 0;
+
+ if (auto attr = D->getAttr<UnavailableAttr>()) {
+ if (attr->isImplicit() && attr->getImplicitReason()) {
+ // Most of these failures are due to extra restrictions in ARC;
+ // reflect that in the primary diagnostic when applicable.
+ auto flagARCError = [&] {
+ if (S.getLangOpts().ObjCAutoRefCount &&
+ S.getSourceManager().isInSystemHeader(D->getLocation()))
+ diag = diag::err_unavailable_in_arc;
+ };
+
+ switch (attr->getImplicitReason()) {
+ case UnavailableAttr::IR_None: break;
+
+ case UnavailableAttr::IR_ARCForbiddenType:
+ flagARCError();
+ diag_available_here = diag::note_arc_forbidden_type;
+ break;
+
+ case UnavailableAttr::IR_ForbiddenWeak:
+ if (S.getLangOpts().ObjCWeakRuntime)
+ diag_available_here = diag::note_arc_weak_disabled;
+ else
+ diag_available_here = diag::note_arc_weak_no_runtime;
+ break;
+
+ case UnavailableAttr::IR_ARCForbiddenConversion:
+ flagARCError();
+ diag_available_here = diag::note_performs_forbidden_arc_conversion;
+ break;
+
+ case UnavailableAttr::IR_ARCInitReturnsUnrelated:
+ flagARCError();
+ diag_available_here = diag::note_arc_init_returns_unrelated;
+ break;
+
+ case UnavailableAttr::IR_ARCFieldWithOwnership:
+ flagARCError();
+ diag_available_here = diag::note_arc_field_with_ownership;
+ break;
+ }
+ }
+ }
+
break;
case Sema::AD_Partial:
@@ -5426,7 +5877,7 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
}
- S.Diag(D->getLocation(), diag::note_availability_specified_here)
+ S.Diag(D->getLocation(), diag_available_here)
<< D << available_here_select_kind;
if (K == Sema::AD_Partial)
S.Diag(Loc, diag::note_partial_availability_silence) << D;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
index 0d7cbf4..11f2329 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -162,34 +162,31 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
+ // If we have a throw-all spec at this point, ignore the function.
+ if (ComputedEST == EST_None)
+ return;
+
+ switch(EST) {
// If this function can throw any exceptions, make a note of that.
- if (EST == EST_MSAny || EST == EST_None) {
+ case EST_MSAny:
+ case EST_None:
ClearExceptions();
ComputedEST = EST;
return;
- }
-
// FIXME: If the call to this decl is using any of its default arguments, we
// need to search them for potentially-throwing calls.
-
// If this function has a basic noexcept, it doesn't affect the outcome.
- if (EST == EST_BasicNoexcept)
- return;
-
- // If we have a throw-all spec at this point, ignore the function.
- if (ComputedEST == EST_None)
+ case EST_BasicNoexcept:
return;
-
// If we're still at noexcept(true) and there's a nothrow() callee,
// change to that specification.
- if (EST == EST_DynamicNone) {
+ case EST_DynamicNone:
if (ComputedEST == EST_BasicNoexcept)
ComputedEST = EST_DynamicNone;
return;
- }
-
// Check out noexcept specs.
- if (EST == EST_ComputedNoexcept) {
+ case EST_ComputedNoexcept:
+ {
FunctionProtoType::NoexceptResult NR =
Proto->getNoexceptSpec(Self->Context);
assert(NR != FunctionProtoType::NR_NoNoexcept &&
@@ -197,7 +194,6 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
assert(NR != FunctionProtoType::NR_Dependent &&
"Should not generate implicit declarations for dependent cases, "
"and don't know how to handle them anyway.");
-
// noexcept(false) -> no spec on the new function
if (NR == FunctionProtoType::NR_Throw) {
ClearExceptions();
@@ -206,7 +202,9 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
// noexcept(true) won't change anything either.
return;
}
-
+ default:
+ break;
+ }
assert(EST == EST_Dynamic && "EST case not considered earlier.");
assert(ComputedEST != EST_None &&
"Shouldn't collect exceptions when throw-all is guaranteed.");
@@ -1232,9 +1230,9 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
Diag(Dcl->getLocation(),
OK ? diag::warn_cxx11_compat_constexpr_body_no_return
: diag::err_constexpr_body_no_return);
- return OK;
- }
- if (ReturnStmts.size() > 1) {
+ if (!OK)
+ return false;
+ } else if (ReturnStmts.size() > 1) {
Diag(ReturnStmts.back(),
getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_constexpr_body_multiple_return
@@ -1555,9 +1553,9 @@ NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set,
/// \brief Performs the actual work of attaching the given base class
/// specifiers to a C++ class.
-bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
- unsigned NumBases) {
- if (NumBases == 0)
+bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
+ MutableArrayRef<CXXBaseSpecifier *> Bases) {
+ if (Bases.empty())
return false;
// Used to keep track of which base types we have already seen, so
@@ -1573,7 +1571,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
// Copy non-redundant base specifiers into permanent storage.
unsigned NumGoodBases = 0;
bool Invalid = false;
- for (unsigned idx = 0; idx < NumBases; ++idx) {
+ for (unsigned idx = 0; idx < Bases.size(); ++idx) {
QualType NewBaseType
= Context.getCanonicalType(Bases[idx]->getType());
NewBaseType = NewBaseType.getLocalUnqualifiedType();
@@ -1599,7 +1597,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
Bases[NumGoodBases++] = Bases[idx];
// Note this base's direct & indirect bases, if there could be ambiguity.
- if (NumBases > 1)
+ if (Bases.size() > 1)
NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType);
if (const RecordType *Record = NewBaseType->getAs<RecordType>()) {
@@ -1621,7 +1619,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
}
// Attach the remaining base class specifiers to the derived class.
- Class->setBases(Bases, NumGoodBases);
+ Class->setBases(Bases.data(), NumGoodBases);
for (unsigned idx = 0; idx < NumGoodBases; ++idx) {
// Check whether this direct base is inaccessible due to ambiguity.
@@ -1656,21 +1654,21 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
/// ActOnBaseSpecifiers - Attach the given base specifiers to the
/// class, after checking whether there are any duplicate base
/// classes.
-void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases,
- unsigned NumBases) {
- if (!ClassDecl || !Bases || !NumBases)
+void Sema::ActOnBaseSpecifiers(Decl *ClassDecl,
+ MutableArrayRef<CXXBaseSpecifier *> Bases) {
+ if (!ClassDecl || Bases.empty())
return;
AdjustDeclIfTemplate(ClassDecl);
- AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases, NumBases);
+ AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases);
}
/// \brief Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
-bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
+bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
if (!getLangOpts().CPlusPlus)
return false;
-
+
CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
if (!DerivedRD)
return false;
@@ -1684,13 +1682,18 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl())
return false;
- // FIXME: instantiate DerivedRD if necessary. We need a PoI for this.
- return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD);
+ // FIXME: In a modules build, do we need the entire path to be visible for us
+ // to be able to use the inheritance relationship?
+ if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined())
+ return false;
+
+ return DerivedRD->isDerivedFrom(BaseRD);
}
/// \brief Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
-bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) {
+bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
+ CXXBasePaths &Paths) {
if (!getLangOpts().CPlusPlus)
return false;
@@ -1702,6 +1705,9 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) {
if (!BaseRD)
return false;
+ if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined())
+ return false;
+
return DerivedRD->isDerivedFrom(BaseRD, Paths);
}
@@ -1749,7 +1755,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
// explore multiple paths to determine if there is an ambiguity.
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
- bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths);
+ bool DerivationOkay = IsDerivedFrom(Loc, Derived, Base, Paths);
assert(DerivationOkay &&
"Can only be used with a derived-to-base conversion");
(void)DerivationOkay;
@@ -1783,7 +1789,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
// performance isn't as much of an issue.
Paths.clear();
Paths.setRecordingPaths(true);
- bool StillOkay = IsDerivedFrom(Derived, Base, Paths);
+ bool StillOkay = IsDerivedFrom(Loc, Derived, Base, Paths);
assert(StillOkay && "Can only be used with a derived-to-base conversion");
(void)StillOkay;
@@ -2759,7 +2765,8 @@ static bool FindBaseInitializer(Sema &SemaRef,
// virtual base class.
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
- if (SemaRef.IsDerivedFrom(SemaRef.Context.getTypeDeclType(ClassDecl),
+ if (SemaRef.IsDerivedFrom(ClassDecl->getLocation(),
+ SemaRef.Context.getTypeDeclType(ClassDecl),
BaseType, Paths)) {
for (CXXBasePaths::paths_iterator Path = Paths.begin();
Path != Paths.end(); ++Path) {
@@ -2982,10 +2989,15 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
if (BaseType.isNull()) {
BaseType = Context.getTypeDeclType(TyD);
MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false);
- if (SS.isSet())
- // FIXME: preserve source range information
+ if (SS.isSet()) {
BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(),
BaseType);
+ TInfo = Context.CreateTypeSourceInfo(BaseType);
+ ElaboratedTypeLoc TL = TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>();
+ TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc);
+ TL.setElaboratedKeywordLoc(SourceLocation());
+ TL.setQualifierLoc(SS.getWithLocInContext(Context));
+ }
}
}
@@ -3483,7 +3495,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
/*TemplateKWLoc=*/SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
MemberLookup,
- /*TemplateArgs=*/nullptr);
+ /*TemplateArgs=*/nullptr,
+ /*S*/nullptr);
if (CtorArg.isInvalid())
return true;
@@ -4140,7 +4153,7 @@ static void DiagnoseBaseOrMemInitializerOrder(
if (InitKey == IdealInitKeys[IdealIndex])
break;
- assert(IdealIndex != NumIdealInits &&
+ assert(IdealIndex < NumIdealInits &&
"initializer not found in initializer list");
}
@@ -4407,64 +4420,35 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) {
}
}
-bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
- unsigned DiagID, AbstractDiagSelID SelID) {
- class NonAbstractTypeDiagnoser : public TypeDiagnoser {
- unsigned DiagID;
- AbstractDiagSelID SelID;
-
- public:
- NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID)
- : TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { }
-
- void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
- if (Suppressed) return;
- if (SelID == -1)
- S.Diag(Loc, DiagID) << T;
- else
- S.Diag(Loc, DiagID) << SelID << T;
- }
- } Diagnoser(DiagID, SelID);
-
- return RequireNonAbstractType(Loc, T, Diagnoser);
-}
-
-bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
- TypeDiagnoser &Diagnoser) {
+bool Sema::isAbstractType(SourceLocation Loc, QualType T) {
if (!getLangOpts().CPlusPlus)
return false;
- if (const ArrayType *AT = Context.getAsArrayType(T))
- return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser);
-
- if (const PointerType *PT = T->getAs<PointerType>()) {
- // Find the innermost pointer type.
- while (const PointerType *T = PT->getPointeeType()->getAs<PointerType>())
- PT = T;
-
- if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType()))
- return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser);
- }
-
- const RecordType *RT = T->getAs<RecordType>();
- if (!RT)
+ const auto *RD = Context.getBaseElementType(T)->getAsCXXRecordDecl();
+ if (!RD)
return false;
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ // FIXME: Per [temp.inst]p1, we are supposed to trigger instantiation of a
+ // class template specialization here, but doing so breaks a lot of code.
// We can't answer whether something is abstract until it has a
- // definition. If it's currently being defined, we'll walk back
+ // definition. If it's currently being defined, we'll walk back
// over all the declarations when we have a full definition.
const CXXRecordDecl *Def = RD->getDefinition();
if (!Def || Def->isBeingDefined())
return false;
- if (!RD->isAbstract())
+ return RD->isAbstract();
+}
+
+bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
+ TypeDiagnoser &Diagnoser) {
+ if (!isAbstractType(Loc, T))
return false;
+ T = Context.getBaseElementType(T);
Diagnoser.diagnose(*this, Loc, T);
- DiagnoseAbstractType(RD);
-
+ DiagnoseAbstractType(T->getAsCXXRecordDecl());
return true;
}
@@ -4684,6 +4668,60 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
}
}
+static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
+ Attr *ClassAttr = getDLLAttr(Class);
+ if (!ClassAttr)
+ return;
+
+ assert(ClassAttr->getKind() == attr::DLLExport);
+
+ TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();
+
+ if (TSK == TSK_ExplicitInstantiationDeclaration)
+ // Don't go any further if this is just an explicit instantiation
+ // declaration.
+ return;
+
+ for (Decl *Member : Class->decls()) {
+ auto *MD = dyn_cast<CXXMethodDecl>(Member);
+ if (!MD)
+ continue;
+
+ if (Member->getAttr<DLLExportAttr>()) {
+ if (MD->isUserProvided()) {
+ // Instantiate non-default class member functions ...
+
+ // .. except for certain kinds of template specializations.
+ if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
+ continue;
+
+ S.MarkFunctionReferenced(Class->getLocation(), MD);
+
+ // The function will be passed to the consumer when its definition is
+ // encountered.
+ } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
+ MD->isCopyAssignmentOperator() ||
+ MD->isMoveAssignmentOperator()) {
+ // Synthesize and instantiate non-trivial implicit methods, explicitly
+ // defaulted methods, and the copy and move assignment operators. The
+ // latter are exported even if they are trivial, because the address of
+ // an operator can be taken and should compare equal accross libraries.
+ DiagnosticErrorTrap Trap(S.Diags);
+ S.MarkFunctionReferenced(Class->getLocation(), MD);
+ if (Trap.hasErrorOccurred()) {
+ S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
+ << Class->getName() << !S.getLangOpts().CPlusPlus11;
+ break;
+ }
+
+ // There is no later point when we will see the definition of this
+ // function, so pass it to the consumer now.
+ S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
+ }
+ }
+ }
+}
+
/// \brief Check class-level dllimport/dllexport attribute.
void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
@@ -4785,45 +4823,10 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
NewAttr->setInherited(true);
Member->addAttr(NewAttr);
}
-
- if (MD && ClassExported) {
- if (TSK == TSK_ExplicitInstantiationDeclaration)
- // Don't go any further if this is just an explicit instantiation
- // declaration.
- continue;
-
- if (MD->isUserProvided()) {
- // Instantiate non-default class member functions ...
-
- // .. except for certain kinds of template specializations.
- if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
- continue;
-
- MarkFunctionReferenced(Class->getLocation(), MD);
-
- // The function will be passed to the consumer when its definition is
- // encountered.
- } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
- MD->isCopyAssignmentOperator() ||
- MD->isMoveAssignmentOperator()) {
- // Synthesize and instantiate non-trivial implicit methods, explicitly
- // defaulted methods, and the copy and move assignment operators. The
- // latter are exported even if they are trivial, because the address of
- // an operator can be taken and should compare equal accross libraries.
- DiagnosticErrorTrap Trap(Diags);
- MarkFunctionReferenced(Class->getLocation(), MD);
- if (Trap.hasErrorOccurred()) {
- Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
- << Class->getName() << !getLangOpts().CPlusPlus11;
- break;
- }
-
- // There is no later point when we will see the definition of this
- // function, so pass it to the consumer now.
- Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
- }
- }
}
+
+ if (ClassExported)
+ DelayedDllExportClasses.push_back(Class);
}
/// \brief Perform propagation of DLL attributes from a derived class to a
@@ -5623,7 +5626,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
/// having a particular direct or virtual base class.
bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) {
CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl();
- return shouldDeleteForClassSubobject(BaseClass, Base, 0);
+ // If program is correct, BaseClass cannot be null, but if it is, the error
+ // must be reported elsewhere.
+ return BaseClass && shouldDeleteForClassSubobject(BaseClass, Base, 0);
}
/// Check whether we should delete a special member function due to the class
@@ -6270,77 +6275,75 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
return true;
}
-/// \brief Data used with FindHiddenVirtualMethod
namespace {
- struct FindHiddenVirtualMethodData {
- Sema *S;
- CXXMethodDecl *Method;
- llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
- SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
- };
-}
-
-/// \brief Check whether any most overriden method from MD in Methods
-static bool CheckMostOverridenMethods(const CXXMethodDecl *MD,
- const llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
- if (MD->size_overridden_methods() == 0)
- return Methods.count(MD->getCanonicalDecl());
- for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
- E = MD->end_overridden_methods();
- I != E; ++I)
- if (CheckMostOverridenMethods(*I, Methods))
- return true;
- return false;
-}
+struct FindHiddenVirtualMethod {
+ Sema *S;
+ CXXMethodDecl *Method;
+ llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
+ SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
-/// \brief Member lookup function that determines whether a given C++
-/// method overloads virtual methods in a base class without overriding any,
-/// to be used with CXXRecordDecl::lookupInBases().
-static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *UserData) {
- RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
-
- FindHiddenVirtualMethodData &Data
- = *static_cast<FindHiddenVirtualMethodData*>(UserData);
-
- DeclarationName Name = Data.Method->getDeclName();
- assert(Name.getNameKind() == DeclarationName::Identifier);
-
- bool foundSameNameMethod = false;
- SmallVector<CXXMethodDecl *, 8> overloadedMethods;
- for (Path.Decls = BaseRecord->lookup(Name);
- !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- NamedDecl *D = Path.Decls.front();
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- MD = MD->getCanonicalDecl();
- foundSameNameMethod = true;
- // Interested only in hidden virtual methods.
- if (!MD->isVirtual())
- continue;
- // If the method we are checking overrides a method from its base
- // don't warn about the other overloaded methods. Clang deviates from GCC
- // by only diagnosing overloads of inherited virtual functions that do not
- // override any other virtual functions in the base. GCC's
- // -Woverloaded-virtual diagnoses any derived function hiding a virtual
- // function from a base class. These cases may be better served by a
- // warning (not specific to virtual functions) on call sites when the call
- // would select a different function from the base class, were it visible.
- // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example.
- if (!Data.S->IsOverload(Data.Method, MD, false))
+private:
+ /// Check whether any most overriden method from MD in Methods
+ static bool CheckMostOverridenMethods(
+ const CXXMethodDecl *MD,
+ const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) {
+ if (MD->size_overridden_methods() == 0)
+ return Methods.count(MD->getCanonicalDecl());
+ for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
+ E = MD->end_overridden_methods();
+ I != E; ++I)
+ if (CheckMostOverridenMethods(*I, Methods))
return true;
- // Collect the overload only if its hidden.
- if (!CheckMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods))
- overloadedMethods.push_back(MD);
- }
+ return false;
}
- if (foundSameNameMethod)
- Data.OverloadedMethods.append(overloadedMethods.begin(),
- overloadedMethods.end());
- return foundSameNameMethod;
-}
+public:
+ /// Member lookup function that determines whether a given C++
+ /// method overloads virtual methods in a base class without overriding any,
+ /// to be used with CXXRecordDecl::lookupInBases().
+ bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ RecordDecl *BaseRecord =
+ Specifier->getType()->getAs<RecordType>()->getDecl();
+
+ DeclarationName Name = Method->getDeclName();
+ assert(Name.getNameKind() == DeclarationName::Identifier);
+
+ bool foundSameNameMethod = false;
+ SmallVector<CXXMethodDecl *, 8> overloadedMethods;
+ for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
+ Path.Decls = Path.Decls.slice(1)) {
+ NamedDecl *D = Path.Decls.front();
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ MD = MD->getCanonicalDecl();
+ foundSameNameMethod = true;
+ // Interested only in hidden virtual methods.
+ if (!MD->isVirtual())
+ continue;
+ // If the method we are checking overrides a method from its base
+ // don't warn about the other overloaded methods. Clang deviates from
+ // GCC by only diagnosing overloads of inherited virtual functions that
+ // do not override any other virtual functions in the base. GCC's
+ // -Woverloaded-virtual diagnoses any derived function hiding a virtual
+ // function from a base class. These cases may be better served by a
+ // warning (not specific to virtual functions) on call sites when the
+ // call would select a different function from the base class, were it
+ // visible.
+ // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example.
+ if (!S->IsOverload(Method, MD, false))
+ return true;
+ // Collect the overload only if its hidden.
+ if (!CheckMostOverridenMethods(MD, OverridenAndUsingBaseMethods))
+ overloadedMethods.push_back(MD);
+ }
+ }
+
+ if (foundSameNameMethod)
+ OverloadedMethods.append(overloadedMethods.begin(),
+ overloadedMethods.end());
+ return foundSameNameMethod;
+ }
+};
+} // end anonymous namespace
/// \brief Add the most overriden methods from MD to Methods
static void AddMostOverridenMethods(const CXXMethodDecl *MD,
@@ -6363,9 +6366,9 @@ void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases.
/*bool RecordPaths=*/false,
/*bool DetectVirtual=*/false);
- FindHiddenVirtualMethodData Data;
- Data.Method = MD;
- Data.S = this;
+ FindHiddenVirtualMethod FHVM;
+ FHVM.Method = MD;
+ FHVM.S = this;
// Keep the base methods that were overriden or introduced in the subclass
// by 'using' in a set. A base method not in this set is hidden.
@@ -6376,11 +6379,11 @@ void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*I))
ND = shad->getTargetDecl();
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
- AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods);
+ AddMostOverridenMethods(MD, FHVM.OverridenAndUsingBaseMethods);
}
- if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths))
- OverloadedMethods = Data.OverloadedMethods;
+ if (DC->lookupInBases(FHVM, Paths))
+ OverloadedMethods = FHVM.OverloadedMethods;
}
void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD,
@@ -6897,7 +6900,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
return Context.getFunctionType(Context.VoidTy, None, EPI);
}
-static void extendLeft(SourceRange &R, const SourceRange &Before) {
+static void extendLeft(SourceRange &R, SourceRange Before) {
if (Before.isInvalid())
return;
R.setBegin(Before.getBegin());
@@ -6905,7 +6908,7 @@ static void extendLeft(SourceRange &R, const SourceRange &Before) {
R.setEnd(Before.getEnd());
}
-static void extendRight(SourceRange &R, const SourceRange &After) {
+static void extendRight(SourceRange &R, SourceRange After) {
if (After.isInvalid())
return;
if (R.getBegin().isInvalid())
@@ -6997,6 +7000,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
extendLeft(Before, Chunk.getSourceRange());
break;
@@ -7019,7 +7023,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
// If we can provide a correct fix-it hint, do so.
if (After.isInvalid() && ConvTSI) {
SourceLocation InsertLoc =
- PP.getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd());
+ getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd());
DB << FixItHint::CreateInsertion(InsertLoc, " ")
<< FixItHint::CreateInsertionFromRange(
InsertLoc, CharSourceRange::getTokenRange(Before))
@@ -7102,7 +7106,7 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
if (ConvType == ClassType)
Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used)
<< ClassType;
- else if (IsDerivedFrom(ClassType, ConvType))
+ else if (IsDerivedFrom(Conversion->getLocation(), ClassType, ConvType))
Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used)
<< ClassType << ConvType;
} else if (ConvType->isVoidType()) {
@@ -7169,7 +7173,8 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
SourceLocation IdentLoc,
IdentifierInfo *II,
SourceLocation LBrace,
- AttributeList *AttrList) {
+ AttributeList *AttrList,
+ UsingDirectiveDecl *&UD) {
SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;
// For anonymous namespace, take the location of the left brace.
SourceLocation Loc = II ? IdentLoc : LBrace;
@@ -7190,23 +7195,14 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// treated as an original-namespace-name.
//
// Since namespace names are unique in their scope, and we don't
- // look through using directives, just look for any ordinary names.
-
- const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member |
- Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag |
- Decl::IDNS_Namespace;
- NamedDecl *PrevDecl = nullptr;
- DeclContext::lookup_result R = CurContext->getRedeclContext()->lookup(II);
- for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
- ++I) {
- if ((*I)->getIdentifierNamespace() & IDNS) {
- PrevDecl = *I;
- break;
- }
- }
-
+ // look through using directives, just look for any ordinary names
+ // as if by qualified name lookup.
+ LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, ForRedeclaration);
+ LookupQualifiedName(R, CurContext->getRedeclContext());
+ NamedDecl *PrevDecl =
+ R.isSingleResult() ? R.getRepresentativeDecl() : nullptr;
PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl);
-
+
if (PrevNS) {
// This is an extended namespace definition.
if (IsInline != PrevNS->isInline())
@@ -7293,14 +7289,13 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// namespace internal linkage.
if (!PrevNS) {
- UsingDirectiveDecl* UD
- = UsingDirectiveDecl::Create(Context, Parent,
- /* 'using' */ LBrace,
- /* 'namespace' */ SourceLocation(),
- /* qualifier */ NestedNameSpecifierLoc(),
- /* identifier */ SourceLocation(),
- Namespc,
- /* Ancestor */ Parent);
+ UD = UsingDirectiveDecl::Create(Context, Parent,
+ /* 'using' */ LBrace,
+ /* 'namespace' */ SourceLocation(),
+ /* qualifier */ NestedNameSpecifierLoc(),
+ /* identifier */ SourceLocation(),
+ Namespc,
+ /* Ancestor */ Parent);
UD->setImplicit();
Parent->addDecl(UD);
}
@@ -7538,7 +7533,7 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
S.PDiag(diag::err_using_directive_suggest) << Ident,
S.PDiag(diag::note_namespace_defined_here));
}
- R.addDecl(Corrected.getCorrectionDecl());
+ R.addDecl(Corrected.getFoundDecl());
return true;
}
return false;
@@ -7556,7 +7551,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
assert(IdentLoc.isValid() && "Invalid NamespceName location.");
// This can only happen along a recovery path.
- while (S->getFlags() & Scope::TemplateParamScope)
+ while (S->isTemplateParamScope())
S = S->getParent();
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
@@ -7586,9 +7581,9 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
}
if (!R.empty()) {
- NamedDecl *Named = R.getFoundDecl();
- assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named))
- && "expected namespace decl");
+ NamedDecl *Named = R.getRepresentativeDecl();
+ NamespaceDecl *NS = R.getAsSingle<NamespaceDecl>();
+ assert(NS && "expected namespace decl");
// The use of a nested name specifier may trigger deprecation warnings.
DiagnoseUseOfDecl(Named, IdentLoc);
@@ -7605,7 +7600,6 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
// Find enclosing context containing both using-directive and
// nominated namespace.
- NamespaceDecl *NS = getNamespaceDecl(Named);
DeclContext *CommonAncestor = cast<DeclContext>(NS);
while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
CommonAncestor = CommonAncestor->getParent();
@@ -7803,9 +7797,14 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I))
PrevShadow = Shadow;
FoundEquivalentDecl = true;
+ } else if (isEquivalentInternalLinkageDeclaration(D, Target)) {
+ // We don't conflict with an existing using shadow decl of an equivalent
+ // declaration, but we're not a redeclaration of it.
+ FoundEquivalentDecl = true;
}
- (isa<TagDecl>(D) ? Tag : NonTag) = D;
+ if (isVisible(D))
+ (isa<TagDecl>(D) ? Tag : NonTag) = D;
}
if (FoundEquivalentDecl)
@@ -8014,6 +8013,10 @@ public:
// FIXME: Check that the base class member is accessible?
}
+ } else {
+ auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND);
+ if (FoundRecord && FoundRecord->isInjectedClassName())
+ return false;
}
if (isa<TypeDecl>(ND))
@@ -8377,7 +8380,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
} else {
// Convert 'using X::Y;' to 'typedef X::Y Y;'.
SourceLocation InsertLoc =
- PP.getLocForEndOfToken(NameInfo.getLocEnd());
+ getLocForEndOfToken(NameInfo.getLocEnd());
Diag(InsertLoc, diag::note_using_decl_class_member_workaround)
<< 1 // typedef declaration
<< FixItHint::CreateReplacement(UsingLoc, "typedef")
@@ -8470,40 +8473,26 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
// in the UsingDecl and UsingShadowDecl so that these checks didn't
// need to be repeated.
- struct UserData {
- llvm::SmallPtrSet<const CXXRecordDecl*, 4> Bases;
-
- static bool collect(const CXXRecordDecl *Base, void *OpaqueData) {
- UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
- Data->Bases.insert(Base);
- return true;
- }
-
- bool hasDependentBases(const CXXRecordDecl *Class) {
- return !Class->forallBases(collect, this);
- }
-
- /// Returns true if the base is dependent or is one of the
- /// accumulated base classes.
- static bool doesNotContain(const CXXRecordDecl *Base, void *OpaqueData) {
- UserData *Data = reinterpret_cast<UserData*>(OpaqueData);
- return !Data->Bases.count(Base);
- }
-
- bool mightShareBases(const CXXRecordDecl *Class) {
- return Bases.count(Class) || !Class->forallBases(doesNotContain, this);
- }
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> Bases;
+ auto Collect = [&Bases](const CXXRecordDecl *Base) {
+ Bases.insert(Base);
+ return true;
};
- UserData Data;
-
- // Returns false if we find a dependent base.
- if (Data.hasDependentBases(cast<CXXRecordDecl>(CurContext)))
+ // Collect all bases. Return false if we find a dependent base.
+ if (!cast<CXXRecordDecl>(CurContext)->forallBases(Collect))
return false;
- // Returns false if the class has a dependent base or if it or one
+ // Returns true if the base is dependent or is one of the accumulated base
+ // classes.
+ auto IsNotBase = [&Bases](const CXXRecordDecl *Base) {
+ return !Bases.count(Base);
+ };
+
+ // Return false if the class has a dependent base or if it or one
// of its bases is present in the base set of the current context.
- if (Data.mightShareBases(cast<CXXRecordDecl>(NamedContext)))
+ if (Bases.count(cast<CXXRecordDecl>(NamedContext)) ||
+ !cast<CXXRecordDecl>(NamedContext)->forallBases(IsNotBase))
return false;
Diag(SS.getRange().getBegin(),
@@ -8524,7 +8513,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
TypeResult Type,
Decl *DeclFromDeclSpec) {
// Skip up to the relevant declaration scope.
- while (S->getFlags() & Scope::TemplateParamScope)
+ while (S->isTemplateParamScope())
S = S->getParent();
assert((S->getFlags() & Scope::DeclScope) &&
"got alias-declaration outside of declaration scope");
@@ -8685,28 +8674,41 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
}
}
assert(!R.isAmbiguous() && !R.empty());
+ NamedDecl *ND = R.getRepresentativeDecl();
// Check if we have a previous declaration with the same name.
- NamedDecl *PrevDecl = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName,
- ForRedeclaration);
- if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S))
- PrevDecl = nullptr;
+ LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName,
+ ForRedeclaration);
+ LookupName(PrevR, S);
+
+ // Check we're not shadowing a template parameter.
+ if (PrevR.isSingleResult() && PrevR.getFoundDecl()->isTemplateParameter()) {
+ DiagnoseTemplateParameterShadow(AliasLoc, PrevR.getFoundDecl());
+ PrevR.clear();
+ }
- NamedDecl *ND = R.getFoundDecl();
+ // Filter out any other lookup result from an enclosing scope.
+ FilterLookupForScope(PrevR, CurContext, S, /*ConsiderLinkage*/false,
+ /*AllowInlineNamespace*/false);
- if (PrevDecl) {
+ // Find the previous declaration and check that we can redeclare it.
+ NamespaceAliasDecl *Prev = nullptr;
+ if (PrevR.isSingleResult()) {
+ NamedDecl *PrevDecl = PrevR.getRepresentativeDecl();
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
// We already have an alias with the same name that points to the same
// namespace; check that it matches.
- if (!AD->getNamespace()->Equals(getNamespaceDecl(ND))) {
+ if (AD->getNamespace()->Equals(getNamespaceDecl(ND))) {
+ Prev = AD;
+ } else if (isVisible(PrevDecl)) {
Diag(AliasLoc, diag::err_redefinition_different_namespace_alias)
<< Alias;
- Diag(PrevDecl->getLocation(), diag::note_previous_namespace_alias)
+ Diag(AD->getLocation(), diag::note_previous_namespace_alias)
<< AD->getNamespace();
return nullptr;
}
- } else {
- unsigned DiagID = isa<NamespaceDecl>(PrevDecl)
+ } else if (isVisible(PrevDecl)) {
+ unsigned DiagID = isa<NamespaceDecl>(PrevDecl->getUnderlyingDecl())
? diag::err_redefinition
: diag::err_redefinition_different_kind;
Diag(AliasLoc, DiagID) << Alias;
@@ -8722,8 +8724,8 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
Alias, SS.getWithLocInContext(Context),
IdentLoc, ND);
- if (PrevDecl)
- AliasDecl->setPreviousDecl(cast<NamespaceAliasDecl>(PrevDecl));
+ if (Prev)
+ AliasDecl->setPreviousDecl(Prev);
PushOnScopeChains(AliasDecl, S);
return AliasDecl;
@@ -9473,6 +9475,10 @@ static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {
if (Class->getDescribedClassTemplate())
return;
+ CallingConv ExpectedCallingConv = S.Context.getDefaultCallingConvention(
+ /*IsVariadic=*/false, /*IsCXXMethod=*/true);
+
+ CXXConstructorDecl *LastExportedDefaultCtor = nullptr;
for (Decl *Member : Class->decls()) {
auto *CD = dyn_cast<CXXConstructorDecl>(Member);
if (!CD) {
@@ -9484,7 +9490,25 @@ static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {
continue;
}
- for (unsigned I = 0, E = CD->getNumParams(); I != E; ++I) {
+ CallingConv ActualCallingConv =
+ CD->getType()->getAs<FunctionProtoType>()->getCallConv();
+
+ // Skip default constructors with typical calling conventions and no default
+ // arguments.
+ unsigned NumParams = CD->getNumParams();
+ if (ExpectedCallingConv == ActualCallingConv && NumParams == 0)
+ continue;
+
+ if (LastExportedDefaultCtor) {
+ S.Diag(LastExportedDefaultCtor->getLocation(),
+ diag::err_attribute_dll_ambiguous_default_ctor) << Class;
+ S.Diag(CD->getLocation(), diag::note_entity_declared_at)
+ << CD->getDeclName();
+ return;
+ }
+ LastExportedDefaultCtor = CD;
+
+ for (unsigned I = 0; I != NumParams; ++I) {
// Skip any default arguments that we've already instantiated.
if (S.Context.getDefaultArgExprForConstructor(CD, I))
continue;
@@ -9497,7 +9521,7 @@ static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {
}
}
-void Sema::ActOnFinishCXXMemberDefaultArgs(Decl *D) {
+void Sema::ActOnFinishCXXNonNestedClass(Decl *D) {
auto *RD = dyn_cast<CXXRecordDecl>(D);
// Default constructors that are annotated with __declspec(dllexport) which
@@ -9505,6 +9529,15 @@ void Sema::ActOnFinishCXXMemberDefaultArgs(Decl *D) {
// wrapped with a thunk called the default constructor closure.
if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft())
getDefaultArgExprsForConstructors(*this, RD);
+
+ if (!DelayedDllExportClasses.empty()) {
+ // Calling ReferenceDllExportedMethods might cause the current function to
+ // be called again, so use a local copy of DelayedDllExportClasses.
+ SmallVector<CXXRecordDecl *, 4> WorkList;
+ std::swap(DelayedDllExportClasses, WorkList);
+ for (CXXRecordDecl *Class : WorkList)
+ ReferenceDllExportedMethods(*this, Class);
+ }
}
void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
@@ -9618,7 +9651,7 @@ public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildMemberReferenceExpr(
Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(),
- nullptr, MemberLookup, nullptr).get());
+ nullptr, MemberLookup, nullptr, nullptr).get());
}
MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow,
@@ -9828,7 +9861,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
SS, /*TemplateKWLoc=*/SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
OpLookup,
- /*TemplateArgs=*/nullptr,
+ /*TemplateArgs=*/nullptr, /*S*/nullptr,
/*SuppressQualifierCheck=*/true);
if (OpEqualRef.isInvalid())
return StmtError();
@@ -12207,7 +12240,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
diag::ext_unelaborated_friend_type)
<< (unsigned) RD->getTagKind()
<< T
- << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc),
+ << FixItHint::CreateInsertion(getLocForEndOfToken(FriendLoc),
InsertionText);
} else {
Diag(FriendLoc,
@@ -12673,15 +12706,30 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
DC = CurContext;
assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?");
}
-
+
if (!DC->isRecord()) {
+ int DiagArg = -1;
+ switch (D.getName().getKind()) {
+ case UnqualifiedId::IK_ConstructorTemplateId:
+ case UnqualifiedId::IK_ConstructorName:
+ DiagArg = 0;
+ break;
+ case UnqualifiedId::IK_DestructorName:
+ DiagArg = 1;
+ break;
+ case UnqualifiedId::IK_ConversionFunctionId:
+ DiagArg = 2;
+ break;
+ case UnqualifiedId::IK_Identifier:
+ case UnqualifiedId::IK_ImplicitSelfParam:
+ case UnqualifiedId::IK_LiteralOperatorId:
+ case UnqualifiedId::IK_OperatorFunctionId:
+ case UnqualifiedId::IK_TemplateId:
+ break;
+ }
// This implies that it has to be an operator or function.
- if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ||
- D.getName().getKind() == UnqualifiedId::IK_DestructorName ||
- D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) {
- Diag(Loc, diag::err_introducing_special_friend) <<
- (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
- D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
+ if (DiagArg >= 0) {
+ Diag(Loc, diag::err_introducing_special_friend) << DiagArg;
return nullptr;
}
}
@@ -12983,7 +13031,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
// Check if the new class derives from the old class.
- if (!IsDerivedFrom(NewClassTy, OldClassTy)) {
+ if (!IsDerivedFrom(New->getLocation(), NewClassTy, OldClassTy)) {
Diag(New->getLocation(), diag::err_covariant_return_not_derived)
<< New->getDeclName() << NewTy << OldTy
<< New->getReturnTypeSourceRange();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
index f42c4b7..a2f41a7 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -15,12 +15,11 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
-#include "clang/AST/DataRecursiveASTVisitor.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Lookup.h"
@@ -100,9 +99,8 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
// If we're in a system header, and this is not a call, just make
// the method unusable.
if (receiverTypeIfCall.isNull() && getSourceManager().isInSystemHeader(loc)) {
- method->addAttr(UnavailableAttr::CreateImplicit(Context,
- "init method returns a type unrelated to its receiver type",
- loc));
+ method->addAttr(UnavailableAttr::CreateImplicit(Context, "",
+ UnavailableAttr::IR_ARCInitReturnsUnrelated, loc));
return true;
}
@@ -449,7 +447,7 @@ class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback {
ObjCInterfaceDecl *CurrentIDecl;
};
-}
+} // end anonymous namespace
static void diagnoseUseOfProtocols(Sema &TheSema,
ObjCContainerDecl *CD,
@@ -484,7 +482,7 @@ ActOnSuperClassOfClassInterface(Scope *S,
if (TypoCorrection Corrected = CorrectTypo(
DeclarationNameInfo(SuperName, SuperLoc),
LookupOrdinaryName, TUScope,
- NULL, llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
+ nullptr, llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl),
CTK_ErrorRecovery)) {
diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
<< SuperName << ClassName);
@@ -507,7 +505,7 @@ ActOnSuperClassOfClassInterface(Scope *S,
SuperClassType = Context.getObjCInterfaceType(SuperClassDecl);
}
- if (PrevDecl && SuperClassDecl == 0) {
+ if (PrevDecl && !SuperClassDecl) {
// The previous declaration was not a class decl. Check if we have a
// typedef. If we do, get the underlying class type.
if (const TypedefNameDecl *TDecl =
@@ -548,7 +546,7 @@ ActOnSuperClassOfClassInterface(Scope *S,
SuperClassDecl->getDeclName(),
ClassName,
SourceRange(AtInterfaceLoc, ClassLoc))) {
- SuperClassDecl = 0;
+ SuperClassDecl = nullptr;
SuperClassType = QualType();
}
}
@@ -608,7 +606,7 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S,
} else if (typeBound->isObjCObjectType()) {
// The user forgot the * on an Objective-C pointer type, e.g.,
// "T : NSView".
- SourceLocation starLoc = PP.getLocForEndOfToken(
+ SourceLocation starLoc = getLocForEndOfToken(
typeBoundInfo->getTypeLoc().getEndLoc());
Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),
diag::err_objc_type_param_bound_missing_pointer)
@@ -638,20 +636,44 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S,
typeBoundInfo = nullptr;
}
- // Type bounds cannot have explicit nullability.
+ // Type bounds cannot have qualifiers (even indirectly) or explicit
+ // nullability.
if (typeBoundInfo) {
- // Type arguments cannot explicitly specify nullability.
- if (auto nullability = AttributedType::stripOuterNullability(typeBound)) {
- // Look at the type location information to find the nullability
- // specifier so we can zap it.
- SourceLocation nullabilityLoc
- = typeBoundInfo->getTypeLoc().findNullabilityLoc();
- SourceLocation diagLoc
- = nullabilityLoc.isValid()? nullabilityLoc
- : typeBoundInfo->getTypeLoc().getLocStart();
- Diag(diagLoc, diag::err_type_param_bound_explicit_nullability)
- << paramName << typeBoundInfo->getType()
- << FixItHint::CreateRemoval(nullabilityLoc);
+ QualType typeBound = typeBoundInfo->getType();
+ TypeLoc qual = typeBoundInfo->getTypeLoc().findExplicitQualifierLoc();
+ if (qual || typeBound.hasQualifiers()) {
+ bool diagnosed = false;
+ SourceRange rangeToRemove;
+ if (qual) {
+ if (auto attr = qual.getAs<AttributedTypeLoc>()) {
+ rangeToRemove = attr.getLocalSourceRange();
+ if (attr.getTypePtr()->getImmediateNullability()) {
+ Diag(attr.getLocStart(),
+ diag::err_objc_type_param_bound_explicit_nullability)
+ << paramName << typeBound
+ << FixItHint::CreateRemoval(rangeToRemove);
+ diagnosed = true;
+ }
+ }
+ }
+
+ if (!diagnosed) {
+ Diag(qual ? qual.getLocStart()
+ : typeBoundInfo->getTypeLoc().getLocStart(),
+ diag::err_objc_type_param_bound_qualified)
+ << paramName << typeBound << typeBound.getQualifiers().getAsString()
+ << FixItHint::CreateRemoval(rangeToRemove);
+ }
+
+ // If the type bound has qualifiers other than CVR, we need to strip
+ // them or we'll probably assert later when trying to apply new
+ // qualifiers.
+ Qualifiers quals = typeBound.getQualifiers();
+ quals.removeCVRQualifiers();
+ if (!quals.empty()) {
+ typeBoundInfo =
+ Context.getTrivialTypeSourceInfo(typeBound.getUnqualifiedType());
+ }
}
}
}
@@ -722,7 +744,7 @@ namespace {
Category,
Extension
};
-}
+} // end anonymous namespace
/// Check consistency between two Objective-C type parameter lists, e.g.,
/// between a category/extension and an \@interface or between an \@class and an
@@ -737,7 +759,7 @@ static bool checkTypeParamListConsistency(Sema &S,
if (newTypeParams->size() > prevTypeParams->size()) {
diagLoc = newTypeParams->begin()[prevTypeParams->size()]->getLocation();
} else {
- diagLoc = S.PP.getLocForEndOfToken(newTypeParams->back()->getLocEnd());
+ diagLoc = S.getLocForEndOfToken(newTypeParams->back()->getLocEnd());
}
S.Diag(diagLoc, diag::err_objc_type_param_arity_mismatch)
@@ -852,7 +874,7 @@ static bool checkTypeParamListConsistency(Sema &S,
newContext == TypeParamListContext::Definition) {
// Diagnose this problem for forward declarations and definitions.
SourceLocation insertionLoc
- = S.PP.getLocForEndOfToken(newTypeParam->getLocation());
+ = S.getLocForEndOfToken(newTypeParam->getLocation());
std::string newCode
= " : " + prevTypeParam->getUnderlyingType().getAsString(
S.Context.getPrintingPolicy());
@@ -1184,26 +1206,23 @@ static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl,
/// protocol declarations in its 'Protocols' argument.
void
Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
- const IdentifierLocPair *ProtocolId,
- unsigned NumProtocols,
+ ArrayRef<IdentifierLocPair> ProtocolId,
SmallVectorImpl<Decl *> &Protocols) {
- for (unsigned i = 0; i != NumProtocols; ++i) {
- ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first,
- ProtocolId[i].second);
+ for (const IdentifierLocPair &Pair : ProtocolId) {
+ ObjCProtocolDecl *PDecl = LookupProtocol(Pair.first, Pair.second);
if (!PDecl) {
TypoCorrection Corrected = CorrectTypo(
- DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),
+ DeclarationNameInfo(Pair.first, Pair.second),
LookupObjCProtocolName, TUScope, nullptr,
llvm::make_unique<DeclFilterCCC<ObjCProtocolDecl>>(),
CTK_ErrorRecovery);
if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))
diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest)
- << ProtocolId[i].first);
+ << Pair.first);
}
if (!PDecl) {
- Diag(ProtocolId[i].second, diag::err_undeclared_protocol)
- << ProtocolId[i].first;
+ Diag(Pair.second, diag::err_undeclared_protocol) << Pair.first;
continue;
}
// If this is a forward protocol declaration, get its definition.
@@ -1213,7 +1232,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
// For an objc container, delay protocol reference checking until after we
// can set the objc decl as the availability context, otherwise check now.
if (!ForObjCContainer) {
- (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second);
+ (void)DiagnoseUseOfDecl(PDecl, Pair.second);
}
// If this is a forward declaration and we are supposed to warn in this
@@ -1223,8 +1242,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
if (WarnOnDeclarations &&
NestedProtocolHasNoDefinition(PDecl, UndefinedProtocol)) {
- Diag(ProtocolId[i].second, diag::warn_undef_protocolref)
- << ProtocolId[i].first;
+ Diag(Pair.second, diag::warn_undef_protocolref) << Pair.first;
Diag(UndefinedProtocol->getLocation(), diag::note_protocol_decl_undefined)
<< UndefinedProtocol;
}
@@ -1388,8 +1406,8 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
if (allProtocolsDeclared) {
Diag(firstClassNameLoc, diag::warn_objc_redundant_qualified_class_type)
<< baseClass->getDeclName() << SourceRange(lAngleLoc, rAngleLoc)
- << FixItHint::CreateInsertion(
- PP.getLocForEndOfToken(firstClassNameLoc), " *");
+ << FixItHint::CreateInsertion(getLocForEndOfToken(firstClassNameLoc),
+ " *");
}
}
@@ -1469,15 +1487,15 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers(
// If we have a typedef of an Objective-C class type that is missing a '*',
// add the '*'.
if (type->getAs<ObjCInterfaceType>()) {
- SourceLocation starLoc = PP.getLocForEndOfToken(loc);
+ SourceLocation starLoc = getLocForEndOfToken(loc);
ParsedAttributes parsedAttrs(attrFactory);
D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc,
SourceLocation(),
SourceLocation(),
SourceLocation(),
SourceLocation()),
- parsedAttrs,
- starLoc);
+ parsedAttrs,
+ starLoc);
// Diagnose the missing '*'.
Diag(loc, diag::err_objc_type_arg_missing_star)
@@ -1655,17 +1673,16 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
/// ActOnForwardProtocolDeclaration - Handle \@protocol foo;
Sema::DeclGroupPtrTy
Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
- const IdentifierLocPair *IdentList,
- unsigned NumElts,
+ ArrayRef<IdentifierLocPair> IdentList,
AttributeList *attrList) {
SmallVector<Decl *, 8> DeclsInGroup;
- for (unsigned i = 0; i != NumElts; ++i) {
- IdentifierInfo *Ident = IdentList[i].first;
- ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentList[i].second,
+ for (const IdentifierLocPair &IdentPair : IdentList) {
+ IdentifierInfo *Ident = IdentPair.first;
+ ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentPair.second,
ForRedeclaration);
ObjCProtocolDecl *PDecl
= ObjCProtocolDecl::Create(Context, CurContext, Ident,
- IdentList[i].second, AtProtocolLoc,
+ IdentPair.second, AtProtocolLoc,
PrevDecl);
PushOnScopeChains(PDecl, TUScope);
@@ -1850,6 +1867,8 @@ Decl *Sema::ActOnStartClassImplementation(
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
} else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
+ // FIXME: This will produce an error if the definition of the interface has
+ // been imported from a module but is not visible.
RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
diag::warn_undef_interface);
} else {
@@ -2247,7 +2266,7 @@ static bool CheckMethodOverrideReturn(Sema &S,
DiagID =
IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types
- : diag::warn_non_covariant_ret_types;
+ : diag::warn_non_covariant_ret_types;
}
}
@@ -2331,7 +2350,7 @@ static bool CheckMethodOverrideParam(Sema &S,
DiagID =
IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types
- : diag::warn_non_contravariant_param_types;
+ : diag::warn_non_contravariant_param_types;
}
}
@@ -2340,7 +2359,7 @@ static bool CheckMethodOverrideParam(Sema &S,
<< MethodImpl->getDeclName() << IfaceTy << ImplTy;
S.Diag(IfaceVar->getLocation(),
(IsOverridingMode ? diag::note_previous_declaration
- : diag::note_previous_definition))
+ : diag::note_previous_definition))
<< getTypeRange(IfaceVar->getTypeSourceInfo());
return false;
}
@@ -2749,7 +2768,8 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
if (!WarnCategoryMethodImpl) {
for (auto *Cat : I->visible_categories())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
- IMPDecl, Cat, IncompleteImpl, false,
+ IMPDecl, Cat, IncompleteImpl,
+ ImmediateClass && Cat->IsClassExtension(),
WarnCategoryMethodImpl);
} else {
// Also methods in class extensions need be looked at next.
@@ -2825,6 +2845,20 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
for (const auto *I : IMPDecl->instance_methods())
InsMap.insert(I->getSelector());
+ // Add the selectors for getters/setters of @dynamic properties.
+ for (const auto *PImpl : IMPDecl->property_impls()) {
+ // We only care about @dynamic implementations.
+ if (PImpl->getPropertyImplementation() != ObjCPropertyImplDecl::Dynamic)
+ continue;
+
+ const auto *P = PImpl->getPropertyDecl();
+ if (!P) continue;
+
+ InsMap.insert(P->getGetterName());
+ if (!P->getSetterName().isNull())
+ InsMap.insert(P->getSetterName());
+ }
+
// Check and see if properties declared in the interface have either 1)
// an implementation or 2) there is a @synthesize/@dynamic implementation
// of the property in the @implementation.
@@ -2866,9 +2900,6 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
for (auto *PI : I->all_referenced_protocols())
CheckProtocolMethodDefs(*this, IMPDecl->getLocation(), PI, IncompleteImpl,
InsMap, ClsMap, I, ExplicitImplProtocols);
- // Check class extensions (unnamed categories)
- for (auto *Ext : I->visible_extensions())
- ImplMethodsVsClassMethods(S, IMPDecl, Ext, IncompleteImpl);
} else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
// For extended class, unimplemented methods in its protocols will
// be reported in the primary class.
@@ -3478,6 +3509,23 @@ void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
}
}
+/// Diagnose attempts to define ARC-__weak ivars when __weak is disabled.
+static void DiagnoseWeakIvars(Sema &S, ObjCImplementationDecl *ID) {
+ if (S.getLangOpts().ObjCWeak) return;
+
+ for (auto ivar = ID->getClassInterface()->all_declared_ivar_begin();
+ ivar; ivar = ivar->getNextIvar()) {
+ if (ivar->isInvalidDecl()) continue;
+ if (ivar->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
+ if (S.getLangOpts().ObjCWeakRuntime) {
+ S.Diag(ivar->getLocation(), diag::err_arc_weak_disabled);
+ } else {
+ S.Diag(ivar->getLocation(), diag::err_arc_weak_no_runtime);
+ }
+ }
+ }
+}
+
Sema::ObjCContainerKind Sema::getObjCContainerKind() const {
switch (CurContext->getDeclKind()) {
case Decl::ObjCInterface:
@@ -3590,7 +3638,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
// user-defined setter/getter. It also synthesizes setter/getter methods
// and adds them to the DeclContext and global method pools.
for (auto *I : CDecl->properties())
- ProcessPropertyDecl(I, CDecl);
+ ProcessPropertyDecl(I);
CDecl->setAtEndRange(AtEnd);
}
if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
@@ -3627,6 +3675,7 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
DiagnoseUnusedBackingIvarInAccessor(S, IC);
if (IDecl->hasDesignatedInitializers())
DiagnoseMissingDesignatedInitOverrides(IC, IDecl);
+ DiagnoseWeakIvars(*this, IC);
bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();
if (IDecl->getSuperClass() == nullptr) {
@@ -3700,7 +3749,6 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
return ClassDecl;
}
-
/// CvtQTToAstBitMask - utility routine to produce an AST bitmask for
/// objective-c's type qualifier from the parser version of the same info.
static Decl::ObjCDeclQualifier
@@ -3867,7 +3915,6 @@ private:
search(Interface);
}
-
void search(const ObjCProtocolList &protocols) {
for (ObjCProtocolList::iterator i = protocols.begin(), e = protocols.end();
i != e; ++i)
@@ -3895,7 +3942,7 @@ private:
searchFromContainer(container);
}
};
-}
+} // end anonymous namespace
void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
ObjCInterfaceDecl *CurrentClass,
@@ -4490,7 +4537,6 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() {
if (!LookupImplementedMethodInGlobalPool(Sel))
Diag(Loc, diag::warn_unimplemented_selector) << Sel;
}
- return;
}
ObjCIvarDecl *
@@ -4522,7 +4568,7 @@ namespace {
/// Used by Sema::DiagnoseUnusedBackingIvarInAccessor to check if a property
/// accessor references the backing ivar.
class UnusedBackingIvarChecker :
- public DataRecursiveASTVisitor<UnusedBackingIvarChecker> {
+ public RecursiveASTVisitor<UnusedBackingIvarChecker> {
public:
Sema &S;
const ObjCMethodDecl *Method;
@@ -4553,7 +4599,7 @@ namespace {
return true;
}
};
-}
+} // end anonymous namespace
void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S,
const ObjCImplementationDecl *ImplD) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
index 2cf02b4..f12bf24 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -68,7 +68,7 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
///
/// \param[in,out] T The exception type. This will be decayed to a pointer type
/// when the input is an array or a function type.
-bool Sema::CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range) {
+bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) {
// C++11 [except.spec]p2:
// A type cv T, "array of T", or "function returning T" denoted
// in an exception-specification is adjusted to type T, "pointer to T", or
@@ -232,7 +232,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) {
Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch)
<< hasImplicitExceptionSpec(Old);
- if (!Old->getLocation().isInvalid())
+ if (Old->getLocation().isValid())
Diag(Old->getLocation(), diag::note_previous_declaration);
}
return false;
@@ -270,16 +270,35 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType();
if (ESI.Type == EST_Dynamic) {
ESI.Exceptions = OldProto->exceptions();
- } else if (ESI.Type == EST_ComputedNoexcept) {
- // FIXME: We can't just take the expression from the old prototype. It
- // likely contains references to the old prototype's parameters.
}
- // Update the type of the function with the appropriate exception
- // specification.
- New->setType(Context.getFunctionType(
- NewProto->getReturnType(), NewProto->getParamTypes(),
- NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
+ if (ESI.Type == EST_ComputedNoexcept) {
+ // For computed noexcept, we can't just take the expression from the old
+ // prototype. It likely contains references to the old prototype's
+ // parameters.
+ New->setInvalidDecl();
+ } else {
+ // Update the type of the function with the appropriate exception
+ // specification.
+ New->setType(Context.getFunctionType(
+ NewProto->getReturnType(), NewProto->getParamTypes(),
+ NewProto->getExtProtoInfo().withExceptionSpec(ESI)));
+ }
+
+ if (getLangOpts().MicrosoftExt && ESI.Type != EST_ComputedNoexcept) {
+ // Allow missing exception specifications in redeclarations as an extension.
+ DiagID = diag::ext_ms_missing_exception_specification;
+ ReturnValueOnError = false;
+ } else if (New->isReplaceableGlobalAllocationFunction() &&
+ ESI.Type != EST_ComputedNoexcept) {
+ // Allow missing exception specifications in redeclarations as an extension,
+ // when declaring a replaceable global allocation function.
+ DiagID = diag::ext_missing_exception_specification;
+ ReturnValueOnError = false;
+ } else {
+ DiagID = diag::err_missing_exception_specification;
+ ReturnValueOnError = true;
+ }
// Warn about the lack of exception specification.
SmallString<128> ExceptionSpecString;
@@ -318,30 +337,30 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
default:
llvm_unreachable("This spec type is compatible with none.");
}
- OS.flush();
SourceLocation FixItLoc;
if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
- if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>())
- FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd());
+ // FIXME: Preserve enough information so that we can produce a correct fixit
+ // location when there is a trailing return type.
+ if (auto FTLoc = TL.getAs<FunctionProtoTypeLoc>())
+ if (!FTLoc.getTypePtr()->hasTrailingReturn())
+ FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd());
}
if (FixItLoc.isInvalid())
- Diag(New->getLocation(), diag::warn_missing_exception_specification)
+ Diag(New->getLocation(), DiagID)
<< New << OS.str();
else {
- // FIXME: This will get more complicated with C++0x
- // late-specified return types.
- Diag(New->getLocation(), diag::warn_missing_exception_specification)
+ Diag(New->getLocation(), DiagID)
<< New << OS.str()
<< FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str());
}
- if (!Old->getLocation().isInvalid())
+ if (Old->getLocation().isValid())
Diag(Old->getLocation(), diag::note_previous_declaration);
- return false;
+ return ReturnValueOnError;
}
/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
@@ -694,7 +713,7 @@ bool Sema::CheckExceptionSpecSubset(
continue;
Paths.clear();
- if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths))
+ if (!IsDerivedFrom(SubLoc, CanonicalSubT, CanonicalSuperT, Paths))
continue;
if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT)))
@@ -979,8 +998,9 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::LambdaExprClass: {
const LambdaExpr *Lambda = cast<LambdaExpr>(E);
CanThrowResult CT = CT_Cannot;
- for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
- CapEnd = Lambda->capture_init_end();
+ for (LambdaExpr::const_capture_init_iterator
+ Cap = Lambda->capture_init_begin(),
+ CapEnd = Lambda->capture_init_end();
Cap != CapEnd; ++Cap)
CT = mergeCanThrow(CT, canThrow(*Cap));
return CT;
@@ -1043,8 +1063,10 @@ CanThrowResult Sema::canThrow(const Expr *E) {
// Many other things have subexpressions, so we have to test those.
// Some are simple:
+ case Expr::CoawaitExprClass:
case Expr::ConditionalOperatorClass:
case Expr::CompoundLiteralExprClass:
+ case Expr::CoyieldExprClass:
case Expr::CXXConstCastExprClass:
case Expr::CXXReinterpretCastExprClass:
case Expr::CXXStdInitializerListExprClass:
@@ -1065,6 +1087,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
// Some might be dependent for other reasons.
case Expr::ArraySubscriptExprClass:
+ case Expr::OMPArraySectionExprClass:
case Expr::BinaryOperatorClass:
case Expr::CompoundAssignOperatorClass:
case Expr::CStyleCastExprClass:
@@ -1156,6 +1179,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
return CT_Cannot;
case Expr::MSPropertyRefExprClass:
+ case Expr::MSPropertySubscriptExprClass:
llvm_unreachable("Invalid class for expression");
#define STMT(CLASS, PARENT) case Expr::CLASS##Class:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index 6499cb5..3e89af6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/PartialDiagnostic.h"
@@ -326,18 +327,16 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
- SuppressedDiagnosticsMap::iterator
- Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
+ auto Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
if (Pos != SuppressedDiagnostics.end()) {
- SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second;
- for (unsigned I = 0, N = Suppressed.size(); I != N; ++I)
- Diag(Suppressed[I].first, Suppressed[I].second);
+ for (const PartialDiagnosticAt &Suppressed : Pos->second)
+ Diag(Suppressed.first, Suppressed.second);
// Clear out the list of suppressed diagnostics, so that we don't emit
// them again for this specialization. However, we don't obsolete this
// entry from the table, because we want to avoid ever emitting these
// diagnostics again.
- Suppressed.clear();
+ Pos->second.clear();
}
// C++ [basic.start.main]p3:
@@ -348,8 +347,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
// See if this is an auto-typed variable whose initializer we are parsing.
if (ParsingInitForAutoVars.count(D)) {
+ const AutoType *AT = cast<VarDecl>(D)->getType()->getContainedAutoType();
+
Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
- << D->getDeclName();
+ << D->getDeclName() << (unsigned)AT->getKeyword();
return true;
}
@@ -464,7 +465,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
// 'nil' for ObjC methods, where it's much more likely that the
// variadic arguments form a list of object pointers.
SourceLocation MissingNilLoc
- = PP.getLocForEndOfToken(sentinelExpr->getLocEnd());
+ = getLocForEndOfToken(sentinelExpr->getLocEnd());
std::string NullValue;
if (calleeType == CT_Method && PP.isMacroDefined("nil"))
NullValue = "nil";
@@ -493,7 +494,7 @@ SourceRange Sema::getExprRange(Expr *E) const {
//===----------------------------------------------------------------------===//
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
-ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) {
+ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
// Handle any placeholder expressions which made it here.
if (E->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
@@ -508,9 +509,16 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) {
// If we are here, we are not calling a function but taking
// its address (which is not allowed in OpenCL v1.0 s6.8.a.3).
if (getLangOpts().OpenCL) {
- Diag(E->getExprLoc(), diag::err_opencl_taking_function_address);
+ if (Diagnose)
+ Diag(E->getExprLoc(), diag::err_opencl_taking_function_address);
return ExprError();
}
+
+ if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
+ if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()))
+ if (!checkAddressOfFunctionIsAvailable(FD, Diagnose, E->getExprLoc()))
+ return ExprError();
+
E = ImpCastExprToType(E, Context.getPointerType(Ty),
CK_FunctionToPointerDecay).get();
} else if (Ty->isArrayType()) {
@@ -579,7 +587,7 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
&S.Context.Idents.get("object_setClass"),
SourceLocation(), S.LookupOrdinaryName);
if (ObjectSetClass) {
- SourceLocation RHSLocEnd = S.PP.getLocForEndOfToken(RHS->getLocEnd());
+ SourceLocation RHSLocEnd = S.getLocForEndOfToken(RHS->getLocEnd());
S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign) <<
FixItHint::CreateInsertion(OIRE->getLocStart(), "object_setClass(") <<
FixItHint::CreateReplacement(SourceRange(OIRE->getOpLoc(),
@@ -676,6 +684,11 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
if (T.hasQualifiers())
T = T.getUnqualifiedType();
+ // Under the MS ABI, lock down the inheritance model now.
+ if (T->isMemberPointerType() &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft())
+ (void)isCompleteType(E->getExprLoc(), T);
+
UpdateMarkingForLValueToRValue(E);
// Loading a __weak object implicitly retains the value, so we need a cleanup to
@@ -699,8 +712,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
return Res;
}
-ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) {
- ExprResult Res = DefaultFunctionArrayConversion(E);
+ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose) {
+ ExprResult Res = DefaultFunctionArrayConversion(E, Diagnose);
if (Res.isInvalid())
return ExprError();
Res = DefaultLvalueConversion(Res.get());
@@ -1349,11 +1362,13 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
ArrayRef<Expr *> Exprs) {
unsigned NumAssocs = Types.size();
assert(NumAssocs == Exprs.size());
- if (ControllingExpr->getType()->isPlaceholderType()) {
- ExprResult result = CheckPlaceholderExpr(ControllingExpr);
- if (result.isInvalid()) return ExprError();
- ControllingExpr = result.get();
- }
+
+ // Decay and strip qualifiers for the controlling expression type, and handle
+ // placeholder type replacement. See committee discussion from WG14 DR423.
+ ExprResult R = DefaultFunctionArrayLvalueConversion(ControllingExpr);
+ if (R.isInvalid())
+ return ExprError();
+ ControllingExpr = R.get();
// The controlling expression is an unevaluated operand, so side effects are
// likely unintended.
@@ -1445,12 +1460,11 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match)
<< ControllingExpr->getSourceRange() << ControllingExpr->getType()
<< (unsigned) CompatIndices.size();
- for (SmallVectorImpl<unsigned>::iterator I = CompatIndices.begin(),
- E = CompatIndices.end(); I != E; ++I) {
- Diag(Types[*I]->getTypeLoc().getBeginLoc(),
+ for (unsigned I : CompatIndices) {
+ Diag(Types[I]->getTypeLoc().getBeginLoc(),
diag::note_compat_assoc)
- << Types[*I]->getTypeLoc().getSourceRange()
- << Types[*I]->getType();
+ << Types[I]->getTypeLoc().getSourceRange()
+ << Types[I]->getType();
}
return ExprError();
}
@@ -1533,8 +1547,8 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
return ExprError();
SmallVector<SourceLocation, 4> StringTokLocs;
- for (unsigned i = 0; i != StringToks.size(); ++i)
- StringTokLocs.push_back(StringToks[i].getLocation());
+ for (const Token &Tok : StringToks)
+ StringTokLocs.push_back(Tok.getLocation());
QualType CharTy = Context.CharTy;
StringLiteral::StringKind Kind = StringLiteral::Ascii;
@@ -1697,7 +1711,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
MarkDeclRefReferenced(E);
- if (getLangOpts().ObjCARCWeak && isa<VarDecl>(D) &&
+ if (getLangOpts().ObjCWeak && isa<VarDecl>(D) &&
Ty.getObjCLifetime() == Qualifiers::OCL_Weak &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
recordUseOfEvaluatedWeak(E);
@@ -1762,10 +1776,9 @@ static void emitEmptyLookupTypoDiagnostic(
std::string CorrectedStr = TC.getAsString(SemaRef.getLangOpts());
bool DroppedSpecifier =
TC.WillReplaceSpecifier() && Typo.getAsString() == CorrectedStr;
- unsigned NoteID =
- (TC.getCorrectionDecl() && isa<ImplicitParamDecl>(TC.getCorrectionDecl()))
- ? diag::note_implicit_param_decl
- : diag::note_previous_decl;
+ unsigned NoteID = TC.getCorrectionDeclAs<ImplicitParamDecl>()
+ ? diag::note_implicit_param_decl
+ : diag::note_previous_decl;
if (!Ctx)
SemaRef.diagnoseTypo(TC, SemaRef.PDiag(DiagnosticSuggestID) << Typo,
SemaRef.PDiag(NoteID));
@@ -1799,8 +1812,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// unqualified lookup. This is useful when (for example) the
// original lookup would not have found something because it was a
// dependent name.
- DeclContext *DC = (SS.isEmpty() && !CallsUndergoingInstantiation.empty())
- ? CurContext : nullptr;
+ DeclContext *DC = SS.isEmpty() ? CurContext : nullptr;
while (DC) {
if (isa<CXXRecordDecl>(DC)) {
LookupQualifiedName(R, DC);
@@ -1819,7 +1831,6 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
bool isInstance = CurMethod &&
CurMethod->isInstance() &&
DC == CurMethod->getParent() && !isDefaultArgument;
-
// Give a code modification hint to insert 'this->'.
// TODO: fixit for inserting 'Base<T>::' in the other cases.
@@ -1829,46 +1840,14 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
if (isInstance) {
Diag(R.getNameLoc(), diagnostic) << Name
<< FixItHint::CreateInsertion(R.getNameLoc(), "this->");
- UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(
- CallsUndergoingInstantiation.back()->getCallee());
-
- CXXMethodDecl *DepMethod;
- if (CurMethod->isDependentContext())
- DepMethod = CurMethod;
- else if (CurMethod->getTemplatedKind() ==
- FunctionDecl::TK_FunctionTemplateSpecialization)
- DepMethod = cast<CXXMethodDecl>(CurMethod->getPrimaryTemplate()->
- getInstantiatedFromMemberTemplate()->getTemplatedDecl());
- else
- DepMethod = cast<CXXMethodDecl>(
- CurMethod->getInstantiatedFromMemberFunction());
- assert(DepMethod && "No template pattern found");
-
- QualType DepThisType = DepMethod->getThisType(Context);
CheckCXXThisCapture(R.getNameLoc());
- CXXThisExpr *DepThis = new (Context) CXXThisExpr(
- R.getNameLoc(), DepThisType, false);
- TemplateArgumentListInfo TList;
- if (ULE->hasExplicitTemplateArgs())
- ULE->copyTemplateArgumentsInto(TList);
-
- CXXScopeSpec SS;
- SS.Adopt(ULE->getQualifierLoc());
- CXXDependentScopeMemberExpr *DepExpr =
- CXXDependentScopeMemberExpr::Create(
- Context, DepThis, DepThisType, true, SourceLocation(),
- SS.getWithLocInContext(Context),
- ULE->getTemplateKeywordLoc(), nullptr,
- R.getLookupNameInfo(),
- ULE->hasExplicitTemplateArgs() ? &TList : nullptr);
- CallsUndergoingInstantiation.back()->setCallee(DepExpr);
} else {
Diag(R.getNameLoc(), diagnostic) << Name;
}
// Do we really want to note all of these?
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
- Diag((*I)->getLocation(), diag::note_dependent_var_use);
+ for (NamedDecl *D : R)
+ Diag(D->getLocation(), diag::note_dependent_var_use);
// Return true if we are inside a default argument instantiation
// and the found name refers to an instance member function, otherwise
@@ -1923,28 +1902,26 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
bool AcceptableWithRecovery = false;
bool AcceptableWithoutRecovery = false;
- NamedDecl *ND = Corrected.getCorrectionDecl();
+ NamedDecl *ND = Corrected.getFoundDecl();
if (ND) {
if (Corrected.isOverloaded()) {
OverloadCandidateSet OCS(R.getNameLoc(),
OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
- for (TypoCorrection::decl_iterator CD = Corrected.begin(),
- CDEnd = Corrected.end();
- CD != CDEnd; ++CD) {
+ for (NamedDecl *CD : Corrected) {
if (FunctionTemplateDecl *FTD =
- dyn_cast<FunctionTemplateDecl>(*CD))
+ dyn_cast<FunctionTemplateDecl>(CD))
AddTemplateOverloadCandidate(
FTD, DeclAccessPair::make(FTD, AS_none), ExplicitTemplateArgs,
Args, OCS);
- else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD))
+ else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(CD))
if (!ExplicitTemplateArgs || ExplicitTemplateArgs->size() == 0)
AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none),
Args, OCS);
}
switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) {
case OR_Success:
- ND = Best->Function;
+ ND = Best->FoundDecl;
Corrected.setCorrectionDecl(ND);
break;
default:
@@ -1966,15 +1943,16 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
R.setNamingClass(Record);
}
- AcceptableWithRecovery =
- isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND);
+ auto *UnderlyingND = ND->getUnderlyingDecl();
+ AcceptableWithRecovery = isa<ValueDecl>(UnderlyingND) ||
+ isa<FunctionTemplateDecl>(UnderlyingND);
// FIXME: If we ended up with a typo for a type name or
// Objective-C class name, we're in trouble because the parser
// is in the wrong place to recover. Suggest the typo
// correction, but don't make it a fix-it since we're not going
// to recover well anyway.
AcceptableWithoutRecovery =
- isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
+ isa<TypeDecl>(UnderlyingND) || isa<ObjCInterfaceDecl>(UnderlyingND);
} else {
// FIXME: We found a keyword. Suggest it, but don't provide a fix-it
// because we aren't able to recover.
@@ -1982,8 +1960,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
}
if (AcceptableWithRecovery || AcceptableWithoutRecovery) {
- unsigned NoteID = (Corrected.getCorrectionDecl() &&
- isa<ImplicitParamDecl>(Corrected.getCorrectionDecl()))
+ unsigned NoteID = Corrected.getCorrectionDeclAs<ImplicitParamDecl>()
? diag::note_implicit_param_decl
: diag::note_previous_decl;
if (SS.isEmpty())
@@ -2278,7 +2255,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
if (MightBeImplicitMember)
return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
- R, TemplateArgs);
+ R, TemplateArgs, S);
}
if (TemplateArgs || TemplateKWLoc.isValid()) {
@@ -2302,11 +2279,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
/// declaration name, generally during template instantiation.
/// There's a large number of things which don't need to be done along
/// this path.
-ExprResult
-Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
- const DeclarationNameInfo &NameInfo,
- bool IsAddressOfOperand,
- TypeSourceInfo **RecoveryTSI) {
+ExprResult Sema::BuildQualifiedDeclarationNameExpr(
+ CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo,
+ bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) {
DeclContext *DC = computeDeclContext(SS, false);
if (!DC)
return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
@@ -2373,7 +2348,7 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
if (!R.empty() && (*R.begin())->isCXXClassMember() && !IsAddressOfOperand)
return BuildPossibleImplicitMemberExpr(SS,
/*TemplateKWLoc=*/SourceLocation(),
- R, /*TemplateArgs=*/nullptr);
+ R, /*TemplateArgs=*/nullptr, S);
return BuildDeclarationNameExpr(SS, R, /* ADL */ false);
}
@@ -2615,7 +2590,7 @@ Sema::PerformObjectMemberConversion(Expr *From,
// In C++98, the qualifier type doesn't actually have to be a base
// type of the object type, in which case we just ignore it.
// Otherwise build the appropriate casts.
- if (IsDerivedFrom(FromRecordType, QRecordType)) {
+ if (IsDerivedFrom(FromLoc, FromRecordType, QRecordType)) {
CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
FromLoc, FromRange, &BasePath))
@@ -2651,7 +2626,7 @@ Sema::PerformObjectMemberConversion(Expr *From,
// We only need to do this if the naming-class to declaring-class
// conversion is non-trivial.
if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) {
- assert(IsDerivedFrom(FromRecordType, URecordType));
+ assert(IsDerivedFrom(FromLoc, FromRecordType, URecordType));
CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
FromLoc, FromRange, &BasePath))
@@ -2698,9 +2673,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
// Turn off ADL when we find certain kinds of declarations during
// normal lookup:
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- NamedDecl *D = *I;
-
+ for (NamedDecl *D : R) {
// C++0x [basic.lookup.argdep]p3:
// -- a declaration of a class member
// Since using decls preserve this property, we check this on the
@@ -3111,6 +3084,8 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
Kind = CharacterLiteral::UTF16;
else if (Literal.isUTF32())
Kind = CharacterLiteral::UTF32;
+ else if (Literal.isUTF8())
+ Kind = CharacterLiteral::UTF8;
Expr *Lit = new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty,
Tok.getLocation());
@@ -3355,13 +3330,6 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// Get the value in the widest-possible width.
unsigned MaxWidth = Context.getTargetInfo().getIntMaxTWidth();
- // The microsoft literal suffix extensions support 128-bit literals, which
- // may be wider than [u]intmax_t.
- // FIXME: Actually, they don't. We seem to have accidentally invented the
- // i128 suffix.
- if (Literal.MicrosoftInteger == 128 && MaxWidth < 128 &&
- Context.getTargetInfo().hasInt128Type())
- MaxWidth = 128;
llvm::APInt ResultVal(MaxWidth, 0);
if (Literal.GetIntegerValue(ResultVal)) {
@@ -3384,12 +3352,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// Microsoft specific integer suffixes are explicitly sized.
if (Literal.MicrosoftInteger) {
- if (Literal.MicrosoftInteger > MaxWidth) {
- // If this target doesn't support __int128, error and force to ull.
- Diag(Tok.getLocation(), diag::err_int128_unsupported);
- Width = MaxWidth;
- Ty = Context.getIntMaxType();
- } else if (Literal.MicrosoftInteger == 8 && !Literal.isUnsigned) {
+ if (Literal.MicrosoftInteger == 8 && !Literal.isUnsigned) {
Width = 8;
Ty = Context.CharTy;
} else {
@@ -3726,7 +3689,7 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E) {
return false;
if (E->getObjectKind() == OK_BitField) {
- S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield)
+ S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield)
<< 1 << E->getSourceRange();
return true;
}
@@ -3828,7 +3791,7 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr);
isInvalid = true;
} else if (E->refersToBitField()) { // C99 6.5.3.4p1.
- Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0;
+ Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 0;
isInvalid = true;
} else {
isInvalid = CheckUnaryExprOrTypeTraitOperand(E, UETT_SizeOf);
@@ -3854,7 +3817,7 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
ExprResult
Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind, bool IsType,
- void *TyOrEx, const SourceRange &ArgRange) {
+ void *TyOrEx, SourceRange ArgRange) {
// If error parsing type, ignore.
if (!TyOrEx) return ExprError();
@@ -3940,9 +3903,21 @@ static bool checkArithmeticOnObjCPointer(Sema &S,
return true;
}
+static bool isMSPropertySubscriptExpr(Sema &S, Expr *Base) {
+ auto *BaseNoParens = Base->IgnoreParens();
+ if (auto *MSProp = dyn_cast<MSPropertyRefExpr>(BaseNoParens))
+ return MSProp->getPropertyDecl()->getType()->isArrayType();
+ return isa<MSPropertySubscriptExpr>(BaseNoParens);
+}
+
ExprResult
Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
Expr *idx, SourceLocation rbLoc) {
+ if (base && !base->getType().isNull() &&
+ base->getType()->isSpecificPlaceholderType(BuiltinType::OMPArraySection))
+ return ActOnOMPArraySectionExpr(base, lbLoc, idx, SourceLocation(),
+ /*Length=*/nullptr, rbLoc);
+
// Since this might be a postfix expression, get rid of ParenListExprs.
if (isa<ParenListExpr>(base)) {
ExprResult result = MaybeConvertParenListExprToParenExpr(S, base);
@@ -3955,10 +3930,15 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
// operand might be an overloadable type, in which case the overload
// resolution for the operator overload should get the first crack
// at the overload.
+ bool IsMSPropertySubscript = false;
if (base->getType()->isNonOverloadPlaceholderType()) {
- ExprResult result = CheckPlaceholderExpr(base);
- if (result.isInvalid()) return ExprError();
- base = result.get();
+ IsMSPropertySubscript = isMSPropertySubscriptExpr(*this, base);
+ if (!IsMSPropertySubscript) {
+ ExprResult result = CheckPlaceholderExpr(base);
+ if (result.isInvalid())
+ return ExprError();
+ base = result.get();
+ }
}
if (idx->getType()->isNonOverloadPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(idx);
@@ -3973,6 +3953,21 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
VK_LValue, OK_Ordinary, rbLoc);
}
+ // MSDN, property (C++)
+ // https://msdn.microsoft.com/en-us/library/yhfk0thd(v=vs.120).aspx
+ // This attribute can also be used in the declaration of an empty array in a
+ // class or structure definition. For example:
+ // __declspec(property(get=GetX, put=PutX)) int x[];
+ // The above statement indicates that x[] can be used with one or more array
+ // indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b),
+ // and p->x[a][b] = i will be turned into p->PutX(a, b, i);
+ if (IsMSPropertySubscript) {
+ // Build MS property subscript expression if base is MS property reference
+ // or MS property subscript.
+ return new (Context) MSPropertySubscriptExpr(
+ base, idx, Context.PseudoObjectTy, VK_LValue, OK_Ordinary, rbLoc);
+ }
+
// Use C++ overloaded-operator rules if either operand has record
// type. The spec says to do this if either type is *overloadable*,
// but enum types can't declare subscript operators or conversion
@@ -3991,6 +3986,139 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
return CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc);
}
+ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
+ Expr *LowerBound,
+ SourceLocation ColonLoc, Expr *Length,
+ SourceLocation RBLoc) {
+ if (Base->getType()->isPlaceholderType() &&
+ !Base->getType()->isSpecificPlaceholderType(
+ BuiltinType::OMPArraySection)) {
+ ExprResult Result = CheckPlaceholderExpr(Base);
+ if (Result.isInvalid())
+ return ExprError();
+ Base = Result.get();
+ }
+ if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
+ ExprResult Result = CheckPlaceholderExpr(LowerBound);
+ if (Result.isInvalid())
+ return ExprError();
+ LowerBound = Result.get();
+ }
+ if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
+ ExprResult Result = CheckPlaceholderExpr(Length);
+ if (Result.isInvalid())
+ return ExprError();
+ Length = Result.get();
+ }
+
+ // Build an unanalyzed expression if either operand is type-dependent.
+ if (Base->isTypeDependent() ||
+ (LowerBound &&
+ (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
+ (Length && (Length->isTypeDependent() || Length->isValueDependent()))) {
+ return new (Context)
+ OMPArraySectionExpr(Base, LowerBound, Length, Context.DependentTy,
+ VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
+ }
+
+ // Perform default conversions.
+ QualType OriginalTy = OMPArraySectionExpr::getBaseOriginalType(Base);
+ QualType ResultTy;
+ if (OriginalTy->isAnyPointerType()) {
+ ResultTy = OriginalTy->getPointeeType();
+ } else if (OriginalTy->isArrayType()) {
+ ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
+ } else {
+ return ExprError(
+ Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
+ << Base->getSourceRange());
+ }
+ // C99 6.5.2.1p1
+ if (LowerBound) {
+ auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
+ LowerBound);
+ if (Res.isInvalid())
+ return ExprError(Diag(LowerBound->getExprLoc(),
+ diag::err_omp_typecheck_section_not_integer)
+ << 0 << LowerBound->getSourceRange());
+ LowerBound = Res.get();
+
+ if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
+ Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
+ << 0 << LowerBound->getSourceRange();
+ }
+ if (Length) {
+ auto Res =
+ PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
+ if (Res.isInvalid())
+ return ExprError(Diag(Length->getExprLoc(),
+ diag::err_omp_typecheck_section_not_integer)
+ << 1 << Length->getSourceRange());
+ Length = Res.get();
+
+ if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
+ Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
+ << 1 << Length->getSourceRange();
+ }
+
+ // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
+ // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
+ // type. Note that functions are not objects, and that (in C99 parlance)
+ // incomplete types are not object types.
+ if (ResultTy->isFunctionType()) {
+ Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
+ << ResultTy << Base->getSourceRange();
+ return ExprError();
+ }
+
+ if (RequireCompleteType(Base->getExprLoc(), ResultTy,
+ diag::err_omp_section_incomplete_type, Base))
+ return ExprError();
+
+ if (LowerBound) {
+ llvm::APSInt LowerBoundValue;
+ if (LowerBound->EvaluateAsInt(LowerBoundValue, Context)) {
+ // OpenMP 4.0, [2.4 Array Sections]
+ // The lower-bound and length must evaluate to non-negative integers.
+ if (LowerBoundValue.isNegative()) {
+ Diag(LowerBound->getExprLoc(), diag::err_omp_section_negative)
+ << 0 << LowerBoundValue.toString(/*Radix=*/10, /*Signed=*/true)
+ << LowerBound->getSourceRange();
+ return ExprError();
+ }
+ }
+ }
+
+ if (Length) {
+ llvm::APSInt LengthValue;
+ if (Length->EvaluateAsInt(LengthValue, Context)) {
+ // OpenMP 4.0, [2.4 Array Sections]
+ // The lower-bound and length must evaluate to non-negative integers.
+ if (LengthValue.isNegative()) {
+ Diag(Length->getExprLoc(), diag::err_omp_section_negative)
+ << 1 << LengthValue.toString(/*Radix=*/10, /*Signed=*/true)
+ << Length->getSourceRange();
+ return ExprError();
+ }
+ }
+ } else if (ColonLoc.isValid() &&
+ (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
+ !OriginalTy->isVariableArrayType()))) {
+ // OpenMP 4.0, [2.4 Array Sections]
+ // When the size of the array dimension is not known, the length must be
+ // specified explicitly.
+ Diag(ColonLoc, diag::err_omp_section_length_undefined)
+ << (!OriginalTy.isNull() && OriginalTy->isArrayType());
+ return ExprError();
+ }
+
+ return new (Context)
+ OMPArraySectionExpr(Base, LowerBound, Length, Context.OMPArraySectionTy,
+ VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
+}
+
ExprResult
Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc) {
@@ -4187,10 +4315,16 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
if (Result.isInvalid())
return ExprError();
- Expr *Arg = Result.getAs<Expr>();
- CheckCompletedExpr(Arg, Param->getOuterLocStart());
- // Build the default argument expression.
- return CXXDefaultArgExpr::Create(Context, CallLoc, Param, Arg);
+ Result = ActOnFinishFullExpr(Result.getAs<Expr>(),
+ Param->getOuterLocStart());
+ if (Result.isInvalid())
+ return ExprError();
+
+ // Remember the instantiated default argument.
+ Param->setDefaultArg(Result.getAs<Expr>());
+ if (ASTMutationListener *L = getASTMutationListener()) {
+ L->DefaultArgumentInstantiated(Param);
+ }
}
// If the default expression creates temporaries, we need to
@@ -4275,29 +4409,27 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn,
llvm::make_unique<FunctionCallCCC>(S, FuncName.getAsIdentifierInfo(),
Args.size(), ME),
Sema::CTK_ErrorRecovery)) {
- if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+ if (NamedDecl *ND = Corrected.getFoundDecl()) {
if (Corrected.isOverloaded()) {
OverloadCandidateSet OCS(NameLoc, OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
- for (TypoCorrection::decl_iterator CD = Corrected.begin(),
- CDEnd = Corrected.end();
- CD != CDEnd; ++CD) {
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD))
+ for (NamedDecl *CD : Corrected) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(CD))
S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args,
OCS);
}
switch (OCS.BestViableFunction(S, NameLoc, Best)) {
case OR_Success:
- ND = Best->Function;
+ ND = Best->FoundDecl;
Corrected.setCorrectionDecl(ND);
break;
default:
break;
}
}
- if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
+ ND = ND->getUnderlyingDecl();
+ if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))
return Corrected;
- }
}
}
return TypoCorrection();
@@ -4433,7 +4565,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
bool IsListInitialization) {
unsigned NumParams = Proto->getNumParams();
bool Invalid = false;
- unsigned ArgIx = 0;
+ size_t ArgIx = 0;
// Continue to check argument types (even if we have too few/many args).
for (unsigned i = FirstParam; i < NumParams; i++) {
QualType ProtoArgType = Proto->getParamType(i);
@@ -4503,26 +4635,25 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
// return __unknown_anytype aren't *really* variadic.
if (Proto->getReturnType() == Context.UnknownAnyTy && FDecl &&
FDecl->isExternC()) {
- for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) {
+ for (Expr *A : Args.slice(ArgIx)) {
QualType paramType; // ignored
- ExprResult arg = checkUnknownAnyArg(CallLoc, Args[i], paramType);
+ ExprResult arg = checkUnknownAnyArg(CallLoc, A, paramType);
Invalid |= arg.isInvalid();
AllArgs.push_back(arg.get());
}
// Otherwise do argument promotion, (C99 6.5.2.2p7).
} else {
- for (unsigned i = ArgIx, e = Args.size(); i != e; ++i) {
- ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType,
- FDecl);
+ for (Expr *A : Args.slice(ArgIx)) {
+ ExprResult Arg = DefaultVariadicArgumentPromotion(A, CallType, FDecl);
Invalid |= Arg.isInvalid();
AllArgs.push_back(Arg.get());
}
}
// Check for array bounds violations.
- for (unsigned i = ArgIx, e = Args.size(); i != e; ++i)
- CheckArrayAccess(Args[i]);
+ for (Expr *A : Args.slice(ArgIx))
+ CheckArrayAccess(A);
}
return Invalid;
}
@@ -4623,7 +4754,9 @@ static bool isPlaceholderToRemoveAsArg(QualType type) {
// These are always invalid as call arguments and should be reported.
case BuiltinType::BoundMember:
case BuiltinType::BuiltinFn:
+ case BuiltinType::OMPArraySection:
return true;
+
}
llvm_unreachable("bad builtin type kind");
}
@@ -4647,7 +4780,7 @@ static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) {
}
/// If a builtin function has a pointer argument with no explicit address
-/// space, than it should be able to accept a pointer to any address
+/// space, then it should be able to accept a pointer to any address
/// space as input. In order to do this, we need to replace the
/// standard builtin declaration with one that uses the same address space
/// as the call.
@@ -4745,7 +4878,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
// Pseudo-destructor calls should not have any arguments.
Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args)
<< FixItHint::CreateRemoval(
- SourceRange(ArgExprs[0]->getLocStart(),
+ SourceRange(ArgExprs.front()->getLocStart(),
ArgExprs.back()->getLocEnd()));
}
@@ -4802,14 +4935,12 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
// We aren't supposed to apply this logic for if there's an '&' involved.
if (!find.HasFormOfMemberPointer) {
OverloadExpr *ovl = find.Expression;
- if (isa<UnresolvedLookupExpr>(ovl)) {
- UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl);
+ if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl))
return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs,
- RParenLoc, ExecConfig);
- } else {
- return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs,
- RParenLoc);
- }
+ RParenLoc, ExecConfig,
+ /*AllowTypoCorrection=*/true,
+ find.IsAddressOfOperand);
+ return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs, RParenLoc);
}
}
@@ -4822,17 +4953,21 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
Expr *NakedFn = Fn->IgnoreParens();
+ bool CallingNDeclIndirectly = false;
NamedDecl *NDecl = nullptr;
- if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn))
- if (UnOp->getOpcode() == UO_AddrOf)
+ if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn)) {
+ if (UnOp->getOpcode() == UO_AddrOf) {
+ CallingNDeclIndirectly = true;
NakedFn = UnOp->getSubExpr()->IgnoreParens();
+ }
+ }
if (isa<DeclRefExpr>(NakedFn)) {
NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
FunctionDecl *FDecl = dyn_cast<FunctionDecl>(NDecl);
if (FDecl && FDecl->getBuiltinID()) {
- // Rewrite the function decl for this builtin by replacing paramaters
+ // Rewrite the function decl for this builtin by replacing parameters
// with no explicit address space with the address space of the arguments
// in ArgExprs.
if ((FDecl = rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs))) {
@@ -4847,6 +4982,11 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NDecl)) {
+ if (CallingNDeclIndirectly &&
+ !checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
+ Fn->getLocStart()))
+ return ExprError();
+
if (FD->hasAttr<EnableIfAttr>()) {
if (const EnableIfAttr *Attr = CheckEnableIf(FD, ArgExprs, true)) {
Diag(Fn->getLocStart(),
@@ -4949,7 +5089,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (!Result.isUsable()) return ExprError();
TheCall = dyn_cast<CallExpr>(Result.get());
if (!TheCall) return Result;
- Args = ArrayRef<Expr *>(TheCall->getArgs(), TheCall->getNumArgs());
+ Args = llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs());
}
// Bail out early if calling a builtin with custom typechecking.
@@ -5098,8 +5238,7 @@ ExprResult
Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
SourceLocation RParenLoc, Expr *InitExpr) {
assert(Ty && "ActOnCompoundLiteral(): missing type");
- // FIXME: put back this assert when initializers are worked out.
- //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
+ assert(InitExpr && "ActOnCompoundLiteral(): missing expression");
TypeSourceInfo *TInfo;
QualType literalType = GetTypeFromParser(Ty, &TInfo);
@@ -5280,13 +5419,13 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
return CK_IntegralToFloating;
case Type::STK_IntegralComplex:
Src = ImpCastExprToType(Src.get(),
- DestTy->castAs<ComplexType>()->getElementType(),
- CK_IntegralCast);
+ DestTy->castAs<ComplexType>()->getElementType(),
+ CK_IntegralCast);
return CK_IntegralRealToComplex;
case Type::STK_FloatingComplex:
Src = ImpCastExprToType(Src.get(),
- DestTy->castAs<ComplexType>()->getElementType(),
- CK_IntegralToFloating);
+ DestTy->castAs<ComplexType>()->getElementType(),
+ CK_IntegralToFloating);
return CK_FloatingRealToComplex;
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
@@ -5401,36 +5540,54 @@ static bool breakDownVectorType(QualType type, uint64_t &len,
return true;
}
-static bool VectorTypesMatch(Sema &S, QualType srcTy, QualType destTy) {
+/// Are the two types lax-compatible vector types? That is, given
+/// that one of them is a vector, do they have equal storage sizes,
+/// where the storage size is the number of elements times the element
+/// size?
+///
+/// This will also return false if either of the types is neither a
+/// vector nor a real type.
+bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) {
+ assert(destTy->isVectorType() || srcTy->isVectorType());
+
+ // Disallow lax conversions between scalars and ExtVectors (these
+ // conversions are allowed for other vector types because common headers
+ // depend on them). Most scalar OP ExtVector cases are handled by the
+ // splat path anyway, which does what we want (convert, not bitcast).
+ // What this rules out for ExtVectors is crazy things like char4*float.
+ if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
+ if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
+
uint64_t srcLen, destLen;
- QualType srcElt, destElt;
- if (!breakDownVectorType(srcTy, srcLen, srcElt)) return false;
- if (!breakDownVectorType(destTy, destLen, destElt)) return false;
+ QualType srcEltTy, destEltTy;
+ if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
+ if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
// ASTContext::getTypeSize will return the size rounded up to a
// power of 2, so instead of using that, we need to use the raw
// element size multiplied by the element count.
- uint64_t srcEltSize = S.Context.getTypeSize(srcElt);
- uint64_t destEltSize = S.Context.getTypeSize(destElt);
+ uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
+ uint64_t destEltSize = Context.getTypeSize(destEltTy);
return (srcLen * srcEltSize == destLen * destEltSize);
}
-/// Is this a legal conversion between two known vector types?
+/// Is this a legal conversion between two types, one of which is
+/// known to be a vector type?
bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) {
assert(destTy->isVectorType() || srcTy->isVectorType());
if (!Context.getLangOpts().LaxVectorConversions)
return false;
- return VectorTypesMatch(*this, srcTy, destTy);
+ return areLaxCompatibleVectorTypes(srcTy, destTy);
}
bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
CastKind &Kind) {
assert(VectorTy->isVectorType() && "Not a vector type!");
- if (Ty->isVectorType() || Ty->isIntegerType()) {
- if (!VectorTypesMatch(*this, Ty, VectorTy))
+ if (Ty->isVectorType() || Ty->isIntegralType(Context)) {
+ if (!areLaxCompatibleVectorTypes(Ty, VectorTy))
return Diag(R.getBegin(),
Ty->isVectorType() ?
diag::err_invalid_conversion_between_vectors :
@@ -5445,6 +5602,39 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
return false;
}
+ExprResult Sema::prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr) {
+ QualType DestElemTy = VectorTy->castAs<VectorType>()->getElementType();
+
+ if (DestElemTy == SplattedExpr->getType())
+ return SplattedExpr;
+
+ assert(DestElemTy->isFloatingType() ||
+ DestElemTy->isIntegralOrEnumerationType());
+
+ CastKind CK;
+ if (VectorTy->isExtVectorType() && SplattedExpr->getType()->isBooleanType()) {
+ // OpenCL requires that we convert `true` boolean expressions to -1, but
+ // only when splatting vectors.
+ if (DestElemTy->isFloatingType()) {
+ // To avoid having to have a CK_BooleanToSignedFloating cast kind, we cast
+ // in two steps: boolean to signed integral, then to floating.
+ ExprResult CastExprRes = ImpCastExprToType(SplattedExpr, Context.IntTy,
+ CK_BooleanToSignedIntegral);
+ SplattedExpr = CastExprRes.get();
+ CK = CK_IntegralToFloating;
+ } else {
+ CK = CK_BooleanToSignedIntegral;
+ }
+ } else {
+ ExprResult CastExprRes = SplattedExpr;
+ CK = PrepareScalarCast(CastExprRes, DestElemTy);
+ if (CastExprRes.isInvalid())
+ return ExprError();
+ SplattedExpr = CastExprRes.get();
+ }
+ return ImpCastExprToType(SplattedExpr, DestElemTy, CK);
+}
+
ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
Expr *CastExpr, CastKind &Kind) {
assert(DestTy->isExtVectorType() && "Not an extended vector type!");
@@ -5456,7 +5646,7 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
// In OpenCL, casts between vectors of different types are not allowed.
// (See OpenCL 6.2).
if (SrcTy->isVectorType()) {
- if (!VectorTypesMatch(*this, SrcTy, DestTy)
+ if (!areLaxCompatibleVectorTypes(SrcTy, DestTy)
|| (getLangOpts().OpenCL &&
(DestTy.getCanonicalType() != SrcTy.getCanonicalType()))) {
Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
@@ -5475,15 +5665,8 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
diag::err_invalid_conversion_between_vector_and_scalar)
<< DestTy << SrcTy << R;
- QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType();
- ExprResult CastExprRes = CastExpr;
- CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy);
- if (CastExprRes.isInvalid())
- return ExprError();
- CastExpr = ImpCastExprToType(CastExprRes.get(), DestElemTy, CK).get();
-
Kind = CK_VectorSplat;
- return CastExpr;
+ return prepareVectorSplat(DestTy, CastExpr);
}
ExprResult
@@ -6358,7 +6541,7 @@ QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
static void SuggestParentheses(Sema &Self, SourceLocation Loc,
const PartialDiagnostic &Note,
SourceRange ParenRange) {
- SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd());
+ SourceLocation EndLoc = Self.getLocForEndOfToken(ParenRange.getEnd());
if (ParenRange.getBegin().isFileID() && ParenRange.getEnd().isFileID() &&
EndLoc.isValid()) {
Self.Diag(Loc, Note)
@@ -6371,7 +6554,9 @@ static void SuggestParentheses(Sema &Self, SourceLocation Loc,
}
static bool IsArithmeticOp(BinaryOperatorKind Opc) {
- return Opc >= BO_Mul && Opc <= BO_Shr;
+ return BinaryOperator::isAdditiveOp(Opc) ||
+ BinaryOperator::isMultiplicativeOp(Opc) ||
+ BinaryOperator::isShiftOp(Opc);
}
/// IsArithmeticBinaryExpr - Returns true if E is an arithmetic binary
@@ -6417,10 +6602,6 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode,
return false;
}
-static bool IsLogicOp(BinaryOperatorKind Opc) {
- return (Opc >= BO_LT && Opc <= BO_NE) || (Opc >= BO_LAnd && Opc <= BO_LOr);
-}
-
/// ExprLooksBoolean - Returns true if E looks boolean, i.e. it has boolean type
/// or is a logical expression such as (x==y) which has int type, but is
/// commonly interpreted as boolean.
@@ -6430,7 +6611,7 @@ static bool ExprLooksBoolean(Expr *E) {
if (E->getType()->isBooleanType())
return true;
if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E))
- return IsLogicOp(OP->getOpcode());
+ return OP->isComparisonOp() || OP->isLogicalOp();
if (UnaryOperator *OP = dyn_cast<UnaryOperator>(E))
return OP->getOpcode() == UO_LNot;
if (E->getType()->isPointerType())
@@ -6753,7 +6934,7 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc,
ExprResult RHSPtr = &RHSExpr;
CastKind K = CK_Invalid;
- return CheckAssignmentConstraints(LHSType, RHSPtr, K);
+ return CheckAssignmentConstraints(LHSType, RHSPtr, K, /*ConvertRHS=*/false);
}
/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
@@ -6775,7 +6956,7 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc,
/// Sets 'Kind' for any result kind except Incompatible.
Sema::AssignConvertType
Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
- CastKind &Kind) {
+ CastKind &Kind, bool ConvertRHS) {
QualType RHSType = RHS.get()->getType();
QualType OrigLHSType = LHSType;
@@ -6797,7 +6978,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
CheckAssignmentConstraints(AtomicTy->getValueType(), RHS, Kind);
if (result != Compatible)
return result;
- if (Kind != CK_NoOp)
+ if (Kind != CK_NoOp && ConvertRHS)
RHS = ImpCastExprToType(RHS.get(), AtomicTy->getValueType(), Kind);
Kind = CK_NonAtomicToAtomic;
return Compatible;
@@ -6824,13 +7005,9 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
if (RHSType->isExtVectorType())
return Incompatible;
if (RHSType->isArithmeticType()) {
- // CK_VectorSplat does T -> vector T, so first cast to the
- // element type.
- QualType elType = cast<ExtVectorType>(LHSType)->getElementType();
- if (elType != RHSType) {
- Kind = PrepareScalarCast(RHS, elType);
- RHS = ImpCastExprToType(RHS.get(), elType, Kind);
- }
+ // CK_VectorSplat does T -> vector T, so first cast to the element type.
+ if (ConvertRHS)
+ RHS = prepareVectorSplat(LHSType, RHS.get());
Kind = CK_VectorSplat;
return Compatible;
}
@@ -6860,7 +7037,8 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// Arithmetic conversions.
if (LHSType->isArithmeticType() && RHSType->isArithmeticType() &&
!(getLangOpts().CPlusPlus && LHSType->isEnumeralType())) {
- Kind = PrepareScalarCast(RHS, LHSType);
+ if (ConvertRHS)
+ Kind = PrepareScalarCast(RHS, LHSType);
return Compatible;
}
@@ -6985,7 +7163,8 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// Only under strict condition T^ is compatible with an Objective-C pointer.
if (RHSType->isBlockPointerType() &&
LHSType->isBlockCompatibleObjCPointerType(Context)) {
- maybeExtendBlockObject(RHS);
+ if (ConvertRHS)
+ maybeExtendBlockObject(RHS);
Kind = CK_BlockPointerToObjCPointerCast;
return Compatible;
}
@@ -7111,9 +7290,16 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
}
Sema::AssignConvertType
-Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
+Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
bool Diagnose,
- bool DiagnoseCFAudited) {
+ bool DiagnoseCFAudited,
+ bool ConvertRHS) {
+ // If ConvertRHS is false, we want to leave the caller's RHS untouched. Sadly,
+ // we can't avoid *all* modifications at the moment, so we need some somewhere
+ // to put the updated value.
+ ExprResult LocalRHS = CallerRHS;
+ ExprResult &RHS = ConvertRHS ? CallerRHS : LocalRHS;
+
if (getLangOpts().CPlusPlus) {
if (!LHSType->isRecordType() && !LHSType->isAtomicType()) {
// C++ 5.17p3: If the left operand is not of class type, the
@@ -7151,6 +7337,15 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
// structures.
// FIXME: We also fall through for atomics; not sure what should
// happen there, though.
+ } else if (RHS.get()->getType() == Context.OverloadTy) {
+ // As a set of extensions to C, we support overloading on functions. These
+ // functions need to be resolved here.
+ DeclAccessPair DAP;
+ if (FunctionDecl *FD = ResolveAddressOfOverloadedFunction(
+ RHS.get(), LHSType, /*Complain=*/false, DAP))
+ RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD);
+ else
+ return Incompatible;
}
// C99 6.5.16.1p1: the left operand is a pointer and the right is
@@ -7162,7 +7357,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
CastKind Kind;
CXXCastPath Path;
CheckPointerConversion(RHS.get(), LHSType, Kind, Path, false);
- RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path);
+ if (ConvertRHS)
+ RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path);
return Compatible;
}
@@ -7173,7 +7369,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
//
// Suppress this for references: C++ 8.5.3p5.
if (!LHSType->isReferenceType()) {
- RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
+ // FIXME: We potentially allocate here even if ConvertRHS is false.
+ RHS = DefaultFunctionArrayLvalueConversion(RHS.get(), Diagnose);
if (RHS.isInvalid())
return Incompatible;
}
@@ -7189,7 +7386,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
CastKind Kind = CK_Invalid;
Sema::AssignConvertType result =
- CheckAssignmentConstraints(LHSType, RHS, Kind);
+ CheckAssignmentConstraints(LHSType, RHS, Kind, ConvertRHS);
// C99 6.5.16.1p2: The value of the right operand is converted to the
// type of the assignment expression.
@@ -7211,7 +7408,8 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS,
return Compatible;
}
- RHS = ImpCastExprToType(E, Ty, Kind);
+ if (ConvertRHS)
+ RHS = ImpCastExprToType(E, Ty, Kind);
}
return result;
}
@@ -7374,6 +7572,18 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
return QualType();
}
+ // OpenCL V1.1 6.2.6.p1:
+ // If the operands are of more than one vector type, then an error shall
+ // occur. Implicit conversions between vector types are not permitted, per
+ // section 6.2.1.
+ if (getLangOpts().OpenCL &&
+ RHSVecType && isa<ExtVectorType>(RHSVecType) &&
+ LHSVecType && isa<ExtVectorType>(LHSVecType)) {
+ Diag(Loc, diag::err_opencl_implicit_vector_conversion) << LHSType
+ << RHSType;
+ return QualType();
+ }
+
// Otherwise, use the generic diagnostic.
Diag(Loc, diag::err_typecheck_vector_not_convertable)
<< LHSType << RHSType
@@ -7420,6 +7630,18 @@ static void checkArithmeticNull(Sema &S, ExprResult &LHS, ExprResult &RHS,
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
+static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS,
+ ExprResult &RHS,
+ SourceLocation Loc, bool IsDiv) {
+ // Check for division/remainder by zero.
+ llvm::APSInt RHSValue;
+ if (!RHS.get()->isValueDependent() &&
+ RHS.get()->EvaluateAsInt(RHSValue, S.Context) && RHSValue == 0)
+ S.DiagRuntimeBehavior(Loc, RHS.get(),
+ S.PDiag(diag::warn_remainder_division_by_zero)
+ << IsDiv << RHS.get()->getSourceRange());
+}
+
QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
bool IsCompAssign, bool IsDiv) {
@@ -7438,15 +7660,8 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
if (compType.isNull() || !compType->isArithmeticType())
return InvalidOperands(Loc, LHS, RHS);
-
- // Check for division by zero.
- llvm::APSInt RHSValue;
- if (IsDiv && !RHS.get()->isValueDependent() &&
- RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0)
- DiagRuntimeBehavior(Loc, RHS.get(),
- PDiag(diag::warn_division_by_zero)
- << RHS.get()->getSourceRange());
-
+ if (IsDiv)
+ DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv);
return compType;
}
@@ -7470,15 +7685,7 @@ QualType Sema::CheckRemainderOperands(
if (compType.isNull() || !compType->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
-
- // Check for remainder by zero.
- llvm::APSInt RHSValue;
- if (!RHS.get()->isValueDependent() &&
- RHS.get()->EvaluateAsInt(RHSValue, Context) && RHSValue == 0)
- DiagRuntimeBehavior(Loc, RHS.get(),
- PDiag(diag::warn_remainder_by_zero)
- << RHS.get()->getSourceRange());
-
+ DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, false /* IsDiv */);
return compType;
}
@@ -7596,7 +7803,7 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
if (isRHSPointer) RHSPointeeTy = RHSExpr->getType()->getPointeeType();
// if both are pointers check if operation is valid wrt address spaces
- if (isLHSPointer && isRHSPointer) {
+ if (S.getLangOpts().OpenCL && isLHSPointer && isRHSPointer) {
const PointerType *lhsPtr = LHSExpr->getType()->getAs<PointerType>();
const PointerType *rhsPtr = RHSExpr->getType()->getAs<PointerType>();
if (!lhsPtr->isAddressSpaceOverlapping(*rhsPtr)) {
@@ -7669,7 +7876,7 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
// Only print a fixit for "str" + int, not for int + "str".
if (IndexExpr == RHSExpr) {
- SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd());
+ SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getLocEnd());
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
<< FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
<< FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
@@ -7719,7 +7926,7 @@ static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
// Only print a fixit for str + char, not for char + str.
if (isa<CharacterLiteral>(RHSExpr->IgnoreImpCasts())) {
- SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd());
+ SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getLocEnd());
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
<< FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
<< FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
@@ -7739,9 +7946,10 @@ static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc,
<< RHSExpr->getSourceRange();
}
-QualType Sema::CheckAdditionOperands( // C99 6.5.6
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc,
- QualType* CompLHSTy) {
+// C99 6.5.6
+QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc, BinaryOperatorKind Opc,
+ QualType* CompLHSTy) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
if (LHS.get()->getType()->isVectorType() ||
@@ -7917,7 +8125,7 @@ static bool isScopedEnumerationType(QualType T) {
}
static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, unsigned Opc,
+ SourceLocation Loc, BinaryOperatorKind Opc,
QualType LHSType) {
// OpenCL 6.3j: shift values are effectively % word size of LHS (more defined),
// so skip remaining warnings as we don't want to modify values within Sema.
@@ -8017,7 +8225,7 @@ static QualType checkOpenCLVectorShift(Sema &S,
if (RHS.isInvalid()) return QualType();
QualType LHSType = LHS.get()->getType();
- const VectorType *LHSVecTy = LHSType->getAs<VectorType>();
+ const VectorType *LHSVecTy = LHSType->castAs<VectorType>();
QualType LHSEleType = LHSVecTy->getElementType();
// Note that RHS might not be a vector.
@@ -8060,7 +8268,7 @@ static QualType checkOpenCLVectorShift(Sema &S,
// C99 6.5.7
QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, unsigned Opc,
+ SourceLocation Loc, BinaryOperatorKind Opc,
bool IsCompAssign) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
@@ -8365,9 +8573,9 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
if (BinaryOperator::isEqualityOp(Opc) &&
hasIsEqualMethod(S, LHS.get(), RHS.get())) {
SourceLocation Start = LHS.get()->getLocStart();
- SourceLocation End = S.PP.getLocForEndOfToken(RHS.get()->getLocEnd());
+ SourceLocation End = S.getLocForEndOfToken(RHS.get()->getLocEnd());
CharSourceRange OpRange =
- CharSourceRange::getCharRange(Loc, S.PP.getLocForEndOfToken(Loc));
+ CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
S.Diag(Loc, diag::note_objc_literal_comparison_isequal)
<< FixItHint::CreateInsertion(Start, Opc == BO_EQ ? "[" : "![")
@@ -8379,20 +8587,17 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS,
ExprResult &RHS,
SourceLocation Loc,
- unsigned OpaqueOpc) {
- // This checking requires bools.
- if (!S.getLangOpts().Bool) return;
-
+ BinaryOperatorKind Opc) {
// Check that left hand side is !something.
UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS.get()->IgnoreImpCasts());
if (!UO || UO->getOpcode() != UO_LNot) return;
// Only check if the right hand side is non-bool arithmetic type.
- if (RHS.get()->getType()->isBooleanType()) return;
+ if (RHS.get()->isKnownToHaveBooleanValue()) return;
// Make sure that the something in !something is not bool.
Expr *SubExpr = UO->getSubExpr()->IgnoreImpCasts();
- if (SubExpr->getType()->isBooleanType()) return;
+ if (SubExpr->isKnownToHaveBooleanValue()) return;
// Emit warning.
S.Diag(UO->getOperatorLoc(), diag::warn_logical_not_on_lhs_of_comparison)
@@ -8401,7 +8606,7 @@ static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS,
// First note suggest !(x < y)
SourceLocation FirstOpen = SubExpr->getLocStart();
SourceLocation FirstClose = RHS.get()->getLocEnd();
- FirstClose = S.getPreprocessor().getLocForEndOfToken(FirstClose);
+ FirstClose = S.getLocForEndOfToken(FirstClose);
if (FirstClose.isInvalid())
FirstOpen = SourceLocation();
S.Diag(UO->getOperatorLoc(), diag::note_logical_not_fix)
@@ -8411,7 +8616,7 @@ static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS,
// Second note suggests (!x) < y
SourceLocation SecondOpen = LHS.get()->getLocStart();
SourceLocation SecondClose = LHS.get()->getLocEnd();
- SecondClose = S.getPreprocessor().getLocForEndOfToken(SecondClose);
+ SecondClose = S.getLocForEndOfToken(SecondClose);
if (SecondClose.isInvalid())
SecondOpen = SourceLocation();
S.Diag(UO->getOperatorLoc(), diag::note_logical_not_silence_with_parens)
@@ -8437,12 +8642,10 @@ static ValueDecl *getCompareDecl(Expr *E) {
// C99 6.5.8, C++ [expr.rel]
QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, unsigned OpaqueOpc,
+ SourceLocation Loc, BinaryOperatorKind Opc,
bool IsRelational) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true);
- BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc;
-
// Handle vector comparisons separately.
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType())
@@ -8455,7 +8658,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts();
checkEnumComparison(*this, Loc, LHS.get(), RHS.get());
- diagnoseLogicalNotOnLHSofComparison(*this, LHS, RHS, Loc, OpaqueOpc);
+ diagnoseLogicalNotOnLHSofComparison(*this, LHS, RHS, Loc, Opc);
if (!LHSType->hasFloatingRepresentation() &&
!(LHSType->isBlockPointerType() && IsRelational) &&
@@ -8628,12 +8831,15 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, /*isError*/false);
}
if (LCanPointeeTy != RCanPointeeTy) {
- const PointerType *lhsPtr = LHSType->getAs<PointerType>();
- if (!lhsPtr->isAddressSpaceOverlapping(*RHSType->getAs<PointerType>())) {
- Diag(Loc,
- diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
- << LHSType << RHSType << 0 /* comparison */
- << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ // Treat NULL constant as a special case in OpenCL.
+ if (getLangOpts().OpenCL && !LHSIsNull && !RHSIsNull) {
+ const PointerType *LHSPtr = LHSType->getAs<PointerType>();
+ if (!LHSPtr->isAddressSpaceOverlapping(*RHSType->getAs<PointerType>())) {
+ Diag(Loc,
+ diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
+ << LHSType << RHSType << 0 /* comparison */
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ }
}
unsigned AddrSpaceL = LCanPointeeTy.getAddressSpace();
unsigned AddrSpaceR = RCanPointeeTy.getAddressSpace();
@@ -8941,9 +9147,10 @@ inline QualType Sema::CheckBitwiseOperands(
return InvalidOperands(Loc, LHS, RHS);
}
-inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc) {
-
+// C99 6.5.[13,14]
+inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc,
+ BinaryOperatorKind Opc) {
// Check vector operands differently.
if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType())
return CheckVectorLogicalOperands(LHS, RHS, Loc);
@@ -8972,18 +9179,14 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
Diag(Loc, diag::note_logical_instead_of_bitwise_change_operator)
<< (Opc == BO_LAnd ? "&" : "|")
<< FixItHint::CreateReplacement(SourceRange(
- Loc, Lexer::getLocForEndOfToken(Loc, 0, getSourceManager(),
- getLangOpts())),
+ Loc, getLocForEndOfToken(Loc)),
Opc == BO_LAnd ? "&" : "|");
if (Opc == BO_LAnd)
// Suggest replacing "Foo() && kNonZero" with "Foo()"
Diag(Loc, diag::note_logical_instead_of_bitwise_remove_constant)
<< FixItHint::CreateRemoval(
- SourceRange(
- Lexer::getLocForEndOfToken(LHS.get()->getLocEnd(),
- 0, getSourceManager(),
- getLangOpts()),
- RHS.get()->getLocEnd()));
+ SourceRange(getLocForEndOfToken(LHS.get()->getLocEnd()),
+ RHS.get()->getLocEnd()));
}
}
@@ -9161,7 +9364,7 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E,
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
// Function calls
const FunctionDecl *FD = CE->getDirectCallee();
- if (!IsTypeModifiable(FD->getReturnType(), IsDereference)) {
+ if (FD && !IsTypeModifiable(FD->getReturnType(), IsDereference)) {
if (!DiagnosticEmitted) {
S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange
<< ConstFunction << FD;
@@ -9510,7 +9713,9 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
return QualType();
}
// Increment of bool sets it to true, but is deprecated.
- S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
+ S.Diag(OpLoc, S.getLangOpts().CPlusPlus1z ? diag::ext_increment_bool
+ : diag::warn_increment_bool)
+ << Op->getSourceRange();
} else if (S.getLangOpts().CPlusPlus && ResType->isEnumeralType()) {
// Error on enum increments and decrements in C++ mode
S.Diag(OpLoc, diag::err_increment_decrement_enum) << IsInc << ResType;
@@ -9710,6 +9915,12 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
// expressions here, but the result of one is always an lvalue anyway.
}
ValueDecl *dcl = getPrimaryDecl(op);
+
+ if (auto *FD = dyn_cast_or_null<FunctionDecl>(dcl))
+ if (!checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
+ op->getLocStart()))
+ return QualType();
+
Expr::LValueClassification lval = op->ClassifyLValue(Context);
unsigned AddressOfError = AO_No_Error;
@@ -9763,8 +9974,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
QualType MPTy = Context.getMemberPointerType(
op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ // Under the MS ABI, lock down the inheritance model now.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
- RequireCompleteType(OpLoc, MPTy, 0);
+ (void)isCompleteType(OpLoc, MPTy);
return MPTy;
} else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
// C99 6.5.3.2p1
@@ -9819,8 +10031,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
QualType MPTy = Context.getMemberPointerType(
op->getType(),
Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+ // Under the MS ABI, lock down the inheritance model now.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
- RequireCompleteType(OpLoc, MPTy, 0);
+ (void)isCompleteType(OpLoc, MPTy);
return MPTy;
}
}
@@ -10121,6 +10334,20 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
return ExprError();
}
+ if (getLangOpts().OpenCL) {
+ // OpenCLC v2.0 s6.13.11.1 allows atomic variables to be initialized by
+ // the ATOMIC_VAR_INIT macro.
+ if (LHSExpr->getType()->isAtomicType() ||
+ RHSExpr->getType()->isAtomicType()) {
+ SourceRange SR(LHSExpr->getLocStart(), RHSExpr->getLocEnd());
+ if (BO_Assign == Opc)
+ Diag(OpLoc, diag::err_atomic_init_constant) << SR;
+ else
+ ResultTy = InvalidOperands(OpLoc, LHS, RHS);
+ return ExprError();
+ }
+ }
+
switch (Opc) {
case BO_Assign:
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
@@ -10211,7 +10438,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_AndAssign:
case BO_OrAssign: // fallthrough
- DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
+ DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
case BO_XorAssign:
CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, true);
CompLHSTy = CompResultTy;
@@ -10238,7 +10465,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
&Context.Idents.get("object_setClass"),
SourceLocation(), LookupOrdinaryName);
if (ObjectSetClass && isa<ObjCIsaExpr>(LHS.get())) {
- SourceLocation RHSLocEnd = PP.getLocForEndOfToken(RHS.get()->getLocEnd());
+ SourceLocation RHSLocEnd = getLocForEndOfToken(RHS.get()->getLocEnd());
Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign) <<
FixItHint::CreateInsertion(LHS.get()->getLocStart(), "object_setClass(") <<
FixItHint::CreateReplacement(SourceRange(OISA->getOpLoc(), OpLoc), ",") <<
@@ -10274,17 +10501,17 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
BinaryOperator *LHSBO = dyn_cast<BinaryOperator>(LHSExpr);
BinaryOperator *RHSBO = dyn_cast<BinaryOperator>(RHSExpr);
- // Check that one of the sides is a comparison operator.
+ // Check that one of the sides is a comparison operator and the other isn't.
bool isLeftComp = LHSBO && LHSBO->isComparisonOp();
bool isRightComp = RHSBO && RHSBO->isComparisonOp();
- if (!isLeftComp && !isRightComp)
+ if (isLeftComp == isRightComp)
return;
// Bitwise operations are sometimes used as eager logical ops.
// Don't diagnose this.
bool isLeftBitwise = LHSBO && LHSBO->isBitwiseOp();
bool isRightBitwise = RHSBO && RHSBO->isBitwiseOp();
- if ((isLeftComp || isLeftBitwise) && (isRightComp || isRightBitwise))
+ if (isLeftBitwise || isRightBitwise)
return;
SourceRange DiagRange = isLeftComp ? SourceRange(LHSExpr->getLocStart(),
@@ -10306,21 +10533,6 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
ParensRange);
}
-/// \brief It accepts a '&' expr that is inside a '|' one.
-/// Emit a diagnostic together with a fixit hint that wraps the '&' expression
-/// in parentheses.
-static void
-EmitDiagnosticForBitwiseAndInBitwiseOr(Sema &Self, SourceLocation OpLoc,
- BinaryOperator *Bop) {
- assert(Bop->getOpcode() == BO_And);
- Self.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_and_in_bitwise_or)
- << Bop->getSourceRange() << OpLoc;
- SuggestParentheses(Self, Bop->getOperatorLoc(),
- Self.PDiag(diag::note_precedence_silence)
- << Bop->getOpcodeStr(),
- Bop->getSourceRange());
-}
-
/// \brief It accepts a '&&' expr that is inside a '||' one.
/// Emit a diagnostic together with a fixit hint that wraps the '&&' expression
/// in parentheses.
@@ -10389,12 +10601,21 @@ static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc,
}
}
-/// \brief Look for '&' in the left or right hand of a '|' expr.
-static void DiagnoseBitwiseAndInBitwiseOr(Sema &S, SourceLocation OpLoc,
- Expr *OrArg) {
- if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(OrArg)) {
- if (Bop->getOpcode() == BO_And)
- return EmitDiagnosticForBitwiseAndInBitwiseOr(S, OpLoc, Bop);
+/// \brief Look for bitwise op in the left or right hand of a bitwise op with
+/// lower precedence and emit a diagnostic together with a fixit hint that wraps
+/// the '&' expression in parentheses.
+static void DiagnoseBitwiseOpInBitwiseOp(Sema &S, BinaryOperatorKind Opc,
+ SourceLocation OpLoc, Expr *SubExpr) {
+ if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(SubExpr)) {
+ if (Bop->isBitwiseOp() && Bop->getOpcode() < Opc) {
+ S.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_op_in_bitwise_op)
+ << Bop->getOpcodeStr() << BinaryOperator::getOpcodeStr(Opc)
+ << Bop->getSourceRange() << OpLoc;
+ SuggestParentheses(S, Bop->getOperatorLoc(),
+ S.PDiag(diag::note_precedence_silence)
+ << Bop->getOpcodeStr(),
+ Bop->getSourceRange());
+ }
}
}
@@ -10449,9 +10670,10 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
DiagnoseBitwisePrecedence(Self, Opc, OpLoc, LHSExpr, RHSExpr);
// Diagnose "arg1 & arg2 | arg3"
- if (Opc == BO_Or && !OpLoc.isMacroID()/* Don't warn in macros. */) {
- DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, LHSExpr);
- DiagnoseBitwiseAndInBitwiseOr(Self, OpLoc, RHSExpr);
+ if ((Opc == BO_Or || Opc == BO_Xor) &&
+ !OpLoc.isMacroID()/* Don't warn in macros. */) {
+ DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, LHSExpr);
+ DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, RHSExpr);
}
// Warn about arg1 || arg2 && arg3, as GCC 4.3+ does.
@@ -10593,6 +10815,14 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType resultType;
+ if (getLangOpts().OpenCL) {
+ // The only legal unary operation for atomics is '&'.
+ if (Opc != UO_AddrOf && InputExpr->getType()->isAtomicType()) {
+ return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+ << InputExpr->getType()
+ << Input.get()->getSourceRange());
+ }
+ }
switch (Opc) {
case UO_PreInc:
case UO_PreDec:
@@ -10735,6 +10965,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
}
break;
case UO_Extension:
+ case UO_Coawait:
resultType = Input.get()->getType();
VK = Input.get()->getValueKind();
OK = Input.get()->getObjectKind();
@@ -10778,10 +11009,8 @@ static bool isQualifiedMemberAccess(Expr *E) {
if (!ULE->getQualifier())
return false;
- for (UnresolvedLookupExpr::decls_iterator D = ULE->decls_begin(),
- DEnd = ULE->decls_end();
- D != DEnd; ++D) {
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*D)) {
+ for (NamedDecl *D : ULE->decls()) {
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
if (Method->isInstance())
return true;
} else {
@@ -10971,8 +11200,7 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
TypeSourceInfo *TInfo,
- OffsetOfComponent *CompPtr,
- unsigned NumComponents,
+ ArrayRef<OffsetOfComponent> Components,
SourceLocation RParenLoc) {
QualType ArgTy = TInfo->getType();
bool Dependent = ArgTy->isDependentType();
@@ -10996,17 +11224,15 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// GCC extension, diagnose them.
// FIXME: This diagnostic isn't actually visible because the location is in
// a system header!
- if (NumComponents != 1)
+ if (Components.size() != 1)
Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
- << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
+ << SourceRange(Components[1].LocStart, Components.back().LocEnd);
bool DidWarnAboutNonPOD = false;
QualType CurrentType = ArgTy;
- typedef OffsetOfExpr::OffsetOfNode OffsetOfNode;
SmallVector<OffsetOfNode, 4> Comps;
SmallVector<Expr*, 4> Exprs;
- for (unsigned i = 0; i != NumComponents; ++i) {
- const OffsetOfComponent &OC = CompPtr[i];
+ for (const OffsetOfComponent &OC : Components) {
if (OC.isBrackets) {
// Offset of an array sub-field. TODO: Should we allow vector elements?
if (!CurrentType->isDependentType()) {
@@ -11074,7 +11300,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
if (!IsSafe && !DidWarnAboutNonPOD &&
DiagRuntimeBehavior(BuiltinLoc, nullptr,
PDiag(DiagID)
- << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
+ << SourceRange(Components[0].LocStart, OC.LocEnd)
<< CurrentType))
DidWarnAboutNonPOD = true;
}
@@ -11113,7 +11339,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// If the member was found in a base class, introduce OffsetOfNodes for
// the base class indirections.
CXXBasePaths Paths;
- if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) {
+ if (IsDerivedFrom(OC.LocStart, CurrentType, Context.getTypeDeclType(Parent),
+ Paths)) {
if (Paths.getDetectedVirtual()) {
Diag(OC.LocEnd, diag::err_offsetof_field_of_virtual_base)
<< MemberDecl->getDeclName()
@@ -11122,9 +11349,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
}
CXXBasePath &Path = Paths.front();
- for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end();
- B != BEnd; ++B)
- Comps.push_back(OffsetOfNode(B->Base));
+ for (const CXXBasePathElement &B : Path)
+ Comps.push_back(OffsetOfNode(B.Base));
}
if (IndirectMemberDecl) {
@@ -11147,8 +11373,7 @@ ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
SourceLocation BuiltinLoc,
SourceLocation TypeLoc,
ParsedType ParsedArgTy,
- OffsetOfComponent *CompPtr,
- unsigned NumComponents,
+ ArrayRef<OffsetOfComponent> Components,
SourceLocation RParenLoc) {
TypeSourceInfo *ArgTInfo;
@@ -11159,8 +11384,7 @@ ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
if (!ArgTInfo)
ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
- return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents,
- RParenLoc);
+ return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, Components, RParenLoc);
}
@@ -11394,16 +11618,14 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
// Set the captured variables on the block.
// FIXME: Share capture structure between BlockDecl and CapturingScopeInfo!
SmallVector<BlockDecl::Capture, 4> Captures;
- for (unsigned i = 0, e = BSI->Captures.size(); i != e; i++) {
- CapturingScopeInfo::Capture &Cap = BSI->Captures[i];
+ for (CapturingScopeInfo::Capture &Cap : BSI->Captures) {
if (Cap.isThisCapture())
continue;
BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(),
Cap.isNested(), Cap.getInitExpr());
Captures.push_back(NewCap);
}
- BSI->TheDecl->setCaptures(Context, Captures.begin(), Captures.end(),
- BSI->CXXThisCaptureIndex != 0);
+ BSI->TheDecl->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0);
// If the user wrote a function type in some form, try to use that.
if (!BSI->FunctionType.isNull()) {
@@ -11495,43 +11717,57 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
Expr *E, TypeSourceInfo *TInfo,
SourceLocation RPLoc) {
Expr *OrigExpr = E;
+ bool IsMS = false;
+
+ // It might be a __builtin_ms_va_list. (But don't ever mark a va_arg()
+ // as Microsoft ABI on an actual Microsoft platform, where
+ // __builtin_ms_va_list and __builtin_va_list are the same.)
+ if (!E->isTypeDependent() && Context.getTargetInfo().hasBuiltinMSVaList() &&
+ Context.getTargetInfo().getBuiltinVaListKind() != TargetInfo::CharPtrBuiltinVaList) {
+ QualType MSVaListType = Context.getBuiltinMSVaListType();
+ if (Context.hasSameType(MSVaListType, E->getType())) {
+ if (CheckForModifiableLvalue(E, BuiltinLoc, *this))
+ return ExprError();
+ IsMS = true;
+ }
+ }
// Get the va_list type
QualType VaListType = Context.getBuiltinVaListType();
- if (VaListType->isArrayType()) {
- // Deal with implicit array decay; for example, on x86-64,
- // va_list is an array, but it's supposed to decay to
- // a pointer for va_arg.
- VaListType = Context.getArrayDecayedType(VaListType);
- // Make sure the input expression also decays appropriately.
- ExprResult Result = UsualUnaryConversions(E);
- if (Result.isInvalid())
- return ExprError();
- E = Result.get();
- } else if (VaListType->isRecordType() && getLangOpts().CPlusPlus) {
- // If va_list is a record type and we are compiling in C++ mode,
- // check the argument using reference binding.
- InitializedEntity Entity
- = InitializedEntity::InitializeParameter(Context,
- Context.getLValueReferenceType(VaListType), false);
- ExprResult Init = PerformCopyInitialization(Entity, SourceLocation(), E);
- if (Init.isInvalid())
- return ExprError();
- E = Init.getAs<Expr>();
- } else {
- // Otherwise, the va_list argument must be an l-value because
- // it is modified by va_arg.
- if (!E->isTypeDependent() &&
- CheckForModifiableLvalue(E, BuiltinLoc, *this))
- return ExprError();
+ if (!IsMS) {
+ if (VaListType->isArrayType()) {
+ // Deal with implicit array decay; for example, on x86-64,
+ // va_list is an array, but it's supposed to decay to
+ // a pointer for va_arg.
+ VaListType = Context.getArrayDecayedType(VaListType);
+ // Make sure the input expression also decays appropriately.
+ ExprResult Result = UsualUnaryConversions(E);
+ if (Result.isInvalid())
+ return ExprError();
+ E = Result.get();
+ } else if (VaListType->isRecordType() && getLangOpts().CPlusPlus) {
+ // If va_list is a record type and we are compiling in C++ mode,
+ // check the argument using reference binding.
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, Context.getLValueReferenceType(VaListType), false);
+ ExprResult Init = PerformCopyInitialization(Entity, SourceLocation(), E);
+ if (Init.isInvalid())
+ return ExprError();
+ E = Init.getAs<Expr>();
+ } else {
+ // Otherwise, the va_list argument must be an l-value because
+ // it is modified by va_arg.
+ if (!E->isTypeDependent() &&
+ CheckForModifiableLvalue(E, BuiltinLoc, *this))
+ return ExprError();
+ }
}
- if (!E->isTypeDependent() &&
- !Context.hasSameType(VaListType, E->getType())) {
+ if (!IsMS && !E->isTypeDependent() &&
+ !Context.hasSameType(VaListType, E->getType()))
return ExprError(Diag(E->getLocStart(),
diag::err_first_argument_to_va_arg_not_of_type_va_list)
<< OrigExpr->getType() << E->getSourceRange());
- }
if (!TInfo->getType()->isDependentType()) {
if (RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(),
@@ -11573,7 +11809,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
}
QualType T = TInfo->getType().getNonLValueExprType(Context);
- return new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T);
+ return new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T, IsMS);
}
ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
@@ -11627,6 +11863,25 @@ Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp) {
return true;
}
+static bool maybeDiagnoseAssignmentToFunction(Sema &S, QualType DstType,
+ const Expr *SrcExpr) {
+ if (!DstType->isFunctionPointerType() ||
+ !SrcExpr->getType()->isFunctionType())
+ return false;
+
+ auto *DRE = dyn_cast<DeclRefExpr>(SrcExpr->IgnoreParenImpCasts());
+ if (!DRE)
+ return false;
+
+ auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl());
+ if (!FD)
+ return false;
+
+ return !S.checkAddressOfFunctionIsAvailable(FD,
+ /*Complain=*/true,
+ SrcExpr->getLocStart());
+}
+
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
SourceLocation Loc,
QualType DstType, QualType SrcType,
@@ -11759,6 +12014,12 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
DiagKind = diag::err_arc_weak_unavailable_assign;
break;
case Incompatible:
+ if (maybeDiagnoseAssignmentToFunction(*this, DstType, SrcExpr)) {
+ if (Complained)
+ *Complained = true;
+ return true;
+ }
+
DiagKind = diag::err_typecheck_convert_incompatible;
ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
MayHaveConvFixit = true;
@@ -11797,9 +12058,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
// If we can fix the conversion, suggest the FixIts.
assert(ConvHints.isNull() || Hint.isNull());
if (!ConvHints.isNull()) {
- for (std::vector<FixItHint>::iterator HI = ConvHints.Hints.begin(),
- HE = ConvHints.Hints.end(); HI != HE; ++HI)
- FDiag << *HI;
+ for (FixItHint &H : ConvHints.Hints)
+ FDiag << H;
} else {
FDiag << Hint;
}
@@ -11816,7 +12076,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
if (SecondType == Context.OverloadTy)
NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression,
- FirstType);
+ FirstType, /*TakingAddress=*/true);
if (CheckInferredResultType)
EmitRelatedResultTypeNote(SrcExpr);
@@ -11974,16 +12234,16 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
if (!Folded || !AllowFold) {
if (!Diagnoser.Suppress) {
Diagnoser.diagnoseNotICE(*this, DiagLoc, E->getSourceRange());
- for (unsigned I = 0, N = Notes.size(); I != N; ++I)
- Diag(Notes[I].first, Notes[I].second);
+ for (const PartialDiagnosticAt &Note : Notes)
+ Diag(Note.first, Note.second);
}
return ExprError();
}
Diagnoser.diagnoseFold(*this, DiagLoc, E->getSourceRange());
- for (unsigned I = 0, N = Notes.size(); I != N; ++I)
- Diag(Notes[I].first, Notes[I].second);
+ for (const PartialDiagnosticAt &Note : Notes)
+ Diag(Note.first, Note.second);
if (Result)
*Result = EvalResult.Val.getInt();
@@ -12417,10 +12677,15 @@ static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDec
// Compute the type of an expression that refers to this variable.
DeclRefType = CaptureType.getNonReferenceType();
-
+
+ // Similarly to mutable captures in lambda, all the OpenMP captures by copy
+ // are mutable in the sense that user can change their value - they are
+ // private instances of the captured declarations.
const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var);
if (Cap.isCopyCapture() &&
- !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable))
+ !(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable) &&
+ !(isa<CapturedRegionScopeInfo>(CSI) &&
+ cast<CapturedRegionScopeInfo>(CSI)->CapRegionKind == CR_OpenMP))
DeclRefType.addConst();
return true;
}
@@ -12608,9 +12873,17 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
// By default, capture variables by reference.
bool ByRef = true;
// Using an LValue reference type is consistent with Lambdas (see below).
- if (S.getLangOpts().OpenMP && S.IsOpenMPCapturedVar(Var))
- DeclRefType = DeclRefType.getUnqualifiedType();
- CaptureType = S.Context.getLValueReferenceType(DeclRefType);
+ if (S.getLangOpts().OpenMP) {
+ ByRef = S.IsOpenMPCapturedByRef(Var, RSI);
+ if (S.IsOpenMPCapturedVar(Var))
+ DeclRefType = DeclRefType.getUnqualifiedType();
+ }
+
+ if (ByRef)
+ CaptureType = S.Context.getLValueReferenceType(DeclRefType);
+ else
+ CaptureType = DeclRefType;
+
Expr *CopyExpr = nullptr;
if (BuildAndDiagnose) {
// The current implementation assumes that all variables are captured
@@ -12836,21 +13109,6 @@ bool Sema::tryCaptureVariable(
if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
DeclRefType))
break;
- if (getLangOpts().OpenMP) {
- if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
- // OpenMP private variables should not be captured in outer scope, so
- // just break here.
- if (RSI->CapRegionKind == CR_OpenMP) {
- if (isOpenMPPrivateVar(Var, OpenMPLevel)) {
- Nested = true;
- DeclRefType = DeclRefType.getUnqualifiedType();
- CaptureType = Context.getLValueReferenceType(DeclRefType);
- break;
- }
- ++OpenMPLevel;
- }
- }
- }
// If we are instantiating a generic lambda call operator body,
// we do not want to capture new variables. What was captured
// during either a lambdas transformation or initial parsing
@@ -12904,6 +13162,7 @@ bool Sema::tryCaptureVariable(
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
+ case Type::Pipe:
llvm_unreachable("type class is never variably-modified!");
case Type::Adjusted:
QTy = cast<AdjustedType>(Ty)->getOriginalType();
@@ -12996,6 +13255,29 @@ bool Sema::tryCaptureVariable(
} while (!QTy.isNull() && QTy->isVariablyModifiedType());
}
+ if (getLangOpts().OpenMP) {
+ if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
+ // OpenMP private variables should not be captured in outer scope, so
+ // just break here. Similarly, global variables that are captured in a
+ // target region should not be captured outside the scope of the region.
+ if (RSI->CapRegionKind == CR_OpenMP) {
+ auto isTargetCap = isOpenMPTargetCapturedVar(Var, OpenMPLevel);
+ // When we detect target captures we are looking from inside the
+ // target region, therefore we need to propagate the capture from the
+ // enclosing region. Therefore, the capture is not initially nested.
+ if (isTargetCap)
+ FunctionScopesIndex--;
+
+ if (isTargetCap || isOpenMPPrivateVar(Var, OpenMPLevel)) {
+ Nested = !isTargetCap;
+ DeclRefType = DeclRefType.getUnqualifiedType();
+ CaptureType = Context.getLValueReferenceType(DeclRefType);
+ break;
+ }
+ ++OpenMPLevel;
+ }
+ }
+ }
if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) {
// No capture-default, and this is not an explicit capture
// so cannot capture this variable.
@@ -13152,15 +13434,13 @@ ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
}
void Sema::CleanupVarDeclMarking() {
- for (llvm::SmallPtrSetIterator<Expr*> i = MaybeODRUseExprs.begin(),
- e = MaybeODRUseExprs.end();
- i != e; ++i) {
+ for (Expr *E : MaybeODRUseExprs) {
VarDecl *Var;
SourceLocation Loc;
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*i)) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
Var = cast<VarDecl>(DRE->getDecl());
Loc = DRE->getLocation();
- } else if (MemberExpr *ME = dyn_cast<MemberExpr>(*i)) {
+ } else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
Var = cast<VarDecl>(ME->getMemberDecl());
Loc = ME->getMemberLoc();
} else {
@@ -13217,7 +13497,7 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
}
if (!isTemplateInstantiation(TSK))
- return;
+ return;
// Instantiate, but do not mark as odr-used, variable templates.
MarkODRUsed = false;
@@ -13316,7 +13596,8 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
if (!MD)
return;
// Only attempt to devirtualize if this is truly a virtual call.
- bool IsVirtualCall = MD->isVirtual() && !ME->hasQualifier();
+ bool IsVirtualCall = MD->isVirtual() &&
+ ME->performsVirtualDispatch(SemaRef.getLangOpts());
if (!IsVirtualCall)
return;
const Expr *Base = ME->getBase();
@@ -13350,7 +13631,7 @@ void Sema::MarkMemberReferenced(MemberExpr *E) {
// expression, is odr-used, unless it is a pure virtual function and its
// name is not explicitly qualified.
bool OdrUse = true;
- if (!E->hasQualifier()) {
+ if (E->performsVirtualDispatch(getLangOpts())) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getMemberDecl()))
if (Method->isPure())
OdrUse = false;
@@ -13633,7 +13914,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
Diag(Loc, diagnostic) << E->getSourceRange();
SourceLocation Open = E->getLocStart();
- SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd());
+ SourceLocation Close = getLocForEndOfToken(E->getSourceRange().getEnd());
Diag(Loc, diag::note_condition_assign_silence)
<< FixItHint::CreateInsertion(Open, "(")
<< FixItHint::CreateInsertion(Close, ")");
@@ -14309,6 +14590,11 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
return ExprError();
}
+ // Expressions of unknown type.
+ case BuiltinType::OMPArraySection:
+ Diag(E->getLocStart(), diag::err_omp_array_section_use);
+ return ExprError();
+
// Everything else should be impossible.
#define BUILTIN_TYPE(Id, SingletonId) \
case BuiltinType::Id:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
index 9ad5aa5..38fbea1 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -1031,6 +1031,11 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc);
}
+ // C++14 [expr.type.conv]p2: The expression T(), where T is a
+ // simple-type-specifier or typename-specifier for a non-array complete
+ // object type or the (possibly cv-qualified) void type, creates a prvalue
+ // of the specified type, whose value is that produced by value-initializing
+ // an object of type T.
QualType ElemTy = Ty;
if (Ty->isArrayType()) {
if (!ListInitialization)
@@ -1039,6 +1044,10 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
ElemTy = Context.getBaseElementType(Ty);
}
+ if (!ListInitialization && Ty->isFunctionType())
+ return ExprError(Diag(TyBeginLoc, diag::err_value_init_for_function_type)
+ << FullRange);
+
if (!Ty->isVoidType() &&
RequireCompleteType(TyBeginLoc, ElemTy,
diag::err_invalid_incomplete_type_use, FullRange))
@@ -2256,6 +2265,9 @@ FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc,
"found an unexpected usual deallocation function");
}
+ if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads)
+ EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches);
+
assert(Matches.size() == 1 &&
"unexpectedly have multiple usual deallocation functions");
return Matches.front();
@@ -2287,6 +2299,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
Matches.push_back(F.getPair());
}
+ if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads)
+ EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches);
+
// There's exactly one suitable operator; pick it.
if (Matches.size() == 1) {
Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl());
@@ -2702,6 +2717,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
return ExprError(Diag(StartLoc, diag::err_delete_operand)
<< Type << Ex.get()->getSourceRange());
} else if (!Pointee->isDependentType()) {
+ // FIXME: This can result in errors if the definition was imported from a
+ // module but is hidden.
if (!RequireCompleteType(StartLoc, Pointee,
diag::warn_delete_incomplete, Ex.get())) {
if (const RecordType *RT = PointeeElem->getAs<RecordType>())
@@ -2712,7 +2729,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (Pointee->isArrayType() && !ArrayForm) {
Diag(StartLoc, diag::warn_delete_array_type)
<< Type << Ex.get()->getSourceRange()
- << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]");
+ << FixItHint::CreateInsertion(getLocForEndOfToken(StartLoc), "[]");
ArrayForm = true;
}
@@ -2777,7 +2794,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (!OperatorDelete)
// Look for a global declaration.
OperatorDelete = FindUsualDeallocationFunction(
- StartLoc, !RequireCompleteType(StartLoc, Pointee, 0) &&
+ StartLoc, isCompleteType(StartLoc, Pointee) &&
(!ArrayForm || UsualArrayDeleteWantsSize ||
Pointee.isDestructedType()),
DeleteName);
@@ -3103,6 +3120,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
ToType = ToAtomic->getValueType();
}
+ QualType InitialFromType = FromType;
// Perform the first implicit conversion.
switch (SCS.First) {
case ICK_Identity:
@@ -3293,8 +3311,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// We may not have been able to figure out what this member pointer resolved
// to up until this exact point. Attempt to lock-in it's inheritance model.
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- RequireCompleteType(From->getExprLoc(), From->getType(), 0);
- RequireCompleteType(From->getExprLoc(), ToType, 0);
+ (void)isCompleteType(From->getExprLoc(), From->getType());
+ (void)isCompleteType(From->getExprLoc(), ToType);
}
From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
@@ -3335,20 +3353,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
- case ICK_Vector_Splat:
+ case ICK_Vector_Splat: {
// Vector splat from any arithmetic type to a vector.
- // Cast to the element type.
- {
- QualType elType = ToType->getAs<ExtVectorType>()->getElementType();
- if (elType != From->getType()) {
- ExprResult E = From;
- From = ImpCastExprToType(From, elType,
- PrepareScalarCast(E, elType)).get();
- }
- From = ImpCastExprToType(From, ToType, CK_VectorSplat,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
- }
+ Expr *Elem = prepareVectorSplat(ToType, From).get();
+ From = ImpCastExprToType(Elem, ToType, CK_VectorSplat, VK_RValue,
+ /*BasePath=*/nullptr, CCK).get();
break;
+ }
case ICK_Complex_Real:
// Case 1. x -> _Complex y
@@ -3432,6 +3443,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_Function_To_Pointer:
case ICK_Qualification:
case ICK_Num_Conversion_Kinds:
+ case ICK_C_Only_Conversion:
llvm_unreachable("Improper second standard conversion");
}
@@ -3472,6 +3484,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
VK_RValue, nullptr, CCK).get();
}
+ // If this conversion sequence succeeded and involved implicitly converting a
+ // _Nullable type to a _Nonnull one, complain.
+ if (CCK == CCK_ImplicitConversion)
+ diagnoseNullableToNonnullConversion(ToType, InitialFromType,
+ From->getLocStart());
+
return From;
}
@@ -3534,27 +3552,43 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsVolatile:
case UTT_IsSigned:
case UTT_IsUnsigned:
+
+ // This type trait always returns false, checking the type is moot.
+ case UTT_IsInterfaceClass:
+ return true;
+
+ // C++14 [meta.unary.prop]:
+ // If T is a non-union class type, T shall be a complete type.
+ case UTT_IsEmpty:
+ case UTT_IsPolymorphic:
+ case UTT_IsAbstract:
+ if (const auto *RD = ArgTy->getAsCXXRecordDecl())
+ if (!RD->isUnion())
+ return !S.RequireCompleteType(
+ Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
+ return true;
+
+ // C++14 [meta.unary.prop]:
+ // If T is a class type, T shall be a complete type.
+ case UTT_IsFinal:
+ case UTT_IsSealed:
+ if (ArgTy->getAsCXXRecordDecl())
+ return !S.RequireCompleteType(
+ Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
return true;
- // C++0x [meta.unary.prop] Table 49 requires the following traits to be
- // applied to a complete type.
+ // C++0x [meta.unary.prop] Table 49 requires the following traits to be
+ // applied to a complete type.
case UTT_IsTrivial:
case UTT_IsTriviallyCopyable:
case UTT_IsStandardLayout:
case UTT_IsPOD:
case UTT_IsLiteral:
- case UTT_IsEmpty:
- case UTT_IsPolymorphic:
- case UTT_IsAbstract:
- case UTT_IsInterfaceClass:
+
case UTT_IsDestructible:
case UTT_IsNothrowDestructible:
// Fall-through
- // These traits require a complete type.
- case UTT_IsFinal:
- case UTT_IsSealed:
-
// These trait expressions are designed to help implement predicates in
// [meta.unary.prop] despite not being named the same. They are specified
// by both GCC and the Embarcadero C++ compiler, and require the complete
@@ -3698,39 +3732,36 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
case UTT_IsVolatile:
return T.isVolatileQualified();
case UTT_IsTrivial:
- return T.isTrivialType(Self.Context);
+ return T.isTrivialType(C);
case UTT_IsTriviallyCopyable:
- return T.isTriviallyCopyableType(Self.Context);
+ return T.isTriviallyCopyableType(C);
case UTT_IsStandardLayout:
return T->isStandardLayoutType();
case UTT_IsPOD:
- return T.isPODType(Self.Context);
+ return T.isPODType(C);
case UTT_IsLiteral:
- return T->isLiteralType(Self.Context);
+ return T->isLiteralType(C);
case UTT_IsEmpty:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return !RD->isUnion() && RD->isEmpty();
return false;
case UTT_IsPolymorphic:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->isPolymorphic();
+ return !RD->isUnion() && RD->isPolymorphic();
return false;
case UTT_IsAbstract:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->isAbstract();
+ return !RD->isUnion() && RD->isAbstract();
return false;
+ // __is_interface_class only returns true when CL is invoked in /CLR mode and
+ // even then only when it is used with the 'interface struct ...' syntax
+ // Clang doesn't support /CLR which makes this type trait moot.
case UTT_IsInterfaceClass:
- if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->isInterface();
return false;
case UTT_IsFinal:
- if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- return RD->hasAttr<FinalAttr>();
- return false;
case UTT_IsSealed:
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
- if (FinalAttr *FA = RD->getAttr<FinalAttr>())
- return FA->isSpelledAsSealed();
+ return RD->hasAttr<FinalAttr>();
return false;
case UTT_IsSigned:
return T->isSignedIntegerType();
@@ -3757,7 +3788,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// If __is_pod (type) is true then the trait is true, else if type is
// a cv class or union type (or array thereof) with a trivial default
// constructor ([class.ctor]) then the trait is true, else it is false.
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
return RD->hasTrivialDefaultConstructor() &&
@@ -3767,7 +3798,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// This trait is implemented by MSVC 2012 and needed to parse the
// standard library headers. Specifically this is used as the logic
// behind std::is_trivially_move_constructible (20.9.4.3).
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
return RD->hasTrivialMoveConstructor() && !RD->hasNonTrivialMoveConstructor();
@@ -3778,7 +3809,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// the trait is true, else if type is a cv class or union type
// with a trivial copy constructor ([class.copy]) then the trait
// is true, else it is false.
- if (T.isPODType(Self.Context) || T->isReferenceType())
+ if (T.isPODType(C) || T->isReferenceType())
return true;
if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return RD->hasTrivialCopyConstructor() &&
@@ -3788,7 +3819,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// This trait is implemented by MSVC 2012 and needed to parse the
// standard library headers. Specifically it is used as the logic
// behind std::is_trivially_move_assignable (20.9.4.3)
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
return RD->hasTrivialMoveAssignment() && !RD->hasNonTrivialMoveAssignment();
@@ -3808,7 +3839,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
if (T.isConstQualified())
return false;
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return RD->hasTrivialCopyAssignment() &&
@@ -3816,8 +3847,47 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
case UTT_IsDestructible:
case UTT_IsNothrowDestructible:
- // FIXME: Implement UTT_IsDestructible and UTT_IsNothrowDestructible.
- // For now, let's fall through.
+ // C++14 [meta.unary.prop]:
+ // For reference types, is_destructible<T>::value is true.
+ if (T->isReferenceType())
+ return true;
+
+ // Objective-C++ ARC: autorelease types don't require destruction.
+ if (T->isObjCLifetimeType() &&
+ T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing)
+ return true;
+
+ // C++14 [meta.unary.prop]:
+ // For incomplete types and function types, is_destructible<T>::value is
+ // false.
+ if (T->isIncompleteType() || T->isFunctionType())
+ return false;
+
+ // C++14 [meta.unary.prop]:
+ // For object types and given U equal to remove_all_extents_t<T>, if the
+ // expression std::declval<U&>().~U() is well-formed when treated as an
+ // unevaluated operand (Clause 5), then is_destructible<T>::value is true
+ if (auto *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) {
+ CXXDestructorDecl *Destructor = Self.LookupDestructor(RD);
+ if (!Destructor)
+ return false;
+ // C++14 [dcl.fct.def.delete]p2:
+ // A program that refers to a deleted function implicitly or
+ // explicitly, other than to declare it, is ill-formed.
+ if (Destructor->isDeleted())
+ return false;
+ if (C.getLangOpts().AccessControl && Destructor->getAccess() != AS_public)
+ return false;
+ if (UTT == UTT_IsNothrowDestructible) {
+ const FunctionProtoType *CPT =
+ Destructor->getType()->getAs<FunctionProtoType>();
+ CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+ if (!CPT || !CPT->isNothrow(C))
+ return false;
+ }
+ }
+ return true;
+
case UTT_HasTrivialDestructor:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
// If __is_pod (type) is true or type is a reference type
@@ -3825,7 +3895,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// type (or array thereof) with a trivial destructor
// ([class.dtor]) then the trait is true, else it is
// false.
- if (T.isPODType(Self.Context) || T->isReferenceType())
+ if (T.isPODType(C) || T->isReferenceType())
return true;
// Objective-C++ ARC: autorelease types don't require destruction.
@@ -3849,7 +3919,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
if (T->isReferenceType())
return false;
- if (T.isPODType(Self.Context) || T->isObjCLifetimeType())
+ if (T.isPODType(C) || T->isObjCLifetimeType())
return true;
if (const RecordType *RT = T->getAs<RecordType>())
@@ -3862,7 +3932,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// This trait is implemented by MSVC 2012 and needed to parse the
// standard library headers. Specifically this is used as the logic
// behind std::is_nothrow_move_assignable (20.9.4.3).
- if (T.isPODType(Self.Context))
+ if (T.isPODType(C))
return true;
if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>())
@@ -3886,15 +3956,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
bool FoundConstructor = false;
unsigned FoundTQs;
- DeclContext::lookup_result R = Self.LookupConstructors(RD);
- for (DeclContext::lookup_iterator Con = R.begin(),
- ConEnd = R.end(); Con != ConEnd; ++Con) {
+ for (const auto *ND : Self.LookupConstructors(RD)) {
// A template constructor is never a copy constructor.
// FIXME: However, it may actually be selected at the actual overload
// resolution point.
- if (isa<FunctionTemplateDecl>(*Con))
+ if (isa<FunctionTemplateDecl>(ND))
continue;
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ const CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(ND);
if (Constructor->isCopyConstructor(FoundTQs)) {
FoundConstructor = true;
const FunctionProtoType *CPT
@@ -3904,7 +3972,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
// TODO: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 1)
+ if (!CPT->isNothrow(C) || CPT->getNumParams() > 1)
return false;
}
}
@@ -3926,13 +3994,11 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return true;
bool FoundConstructor = false;
- DeclContext::lookup_result R = Self.LookupConstructors(RD);
- for (DeclContext::lookup_iterator Con = R.begin(),
- ConEnd = R.end(); Con != ConEnd; ++Con) {
+ for (const auto *ND : Self.LookupConstructors(RD)) {
// FIXME: In C++0x, a constructor template can be a default constructor.
- if (isa<FunctionTemplateDecl>(*Con))
+ if (isa<FunctionTemplateDecl>(ND))
continue;
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ const CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(ND);
if (Constructor->isDefaultConstructor()) {
FoundConstructor = true;
const FunctionProtoType *CPT
@@ -3942,7 +4008,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
// FIXME: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
- if (!CPT->isNothrow(Self.Context) || CPT->getNumParams() > 0)
+ if (!CPT->isNothrow(C) || CPT->getNumParams() > 0)
return false;
}
}
@@ -4023,8 +4089,8 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
// Precondition: T and all types in the parameter pack Args shall be
// complete types, (possibly cv-qualified) void, or arrays of
// unknown bound.
- for (unsigned I = 0, N = Args.size(); I != N; ++I) {
- QualType ArgTy = Args[I]->getType();
+ for (const auto *TSI : Args) {
+ QualType ArgTy = TSI->getType();
if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType())
continue;
@@ -4033,12 +4099,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
return false;
}
- // Make sure the first argument is a complete type.
- if (Args[0]->getType()->isIncompleteType())
+ // Make sure the first argument is not incomplete nor a function type.
+ QualType T = Args[0]->getType();
+ if (T->isIncompleteType() || T->isFunctionType())
return false;
// Make sure the first argument is not an abstract type.
- CXXRecordDecl *RD = Args[0]->getType()->getAsCXXRecordDecl();
+ CXXRecordDecl *RD = T->getAsCXXRecordDecl();
if (RD && RD->isAbstract())
return false;
@@ -4046,13 +4113,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
SmallVector<Expr *, 2> ArgExprs;
ArgExprs.reserve(Args.size() - 1);
for (unsigned I = 1, N = Args.size(); I != N; ++I) {
- QualType T = Args[I]->getType();
- if (T->isObjectType() || T->isFunctionType())
- T = S.Context.getRValueReferenceType(T);
+ QualType ArgTy = Args[I]->getType();
+ if (ArgTy->isObjectType() || ArgTy->isFunctionType())
+ ArgTy = S.Context.getRValueReferenceType(ArgTy);
OpaqueArgExprs.push_back(
- OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(),
- T.getNonLValueExprType(S.Context),
- Expr::getValueKindForType(T)));
+ OpaqueValueExpr(Args[I]->getTypeLoc().getLocStart(),
+ ArgTy.getNonLValueExprType(S.Context),
+ Expr::getValueKindForType(ArgTy)));
}
for (Expr &E : OpaqueArgExprs)
ArgExprs.push_back(&E);
@@ -4083,7 +4150,7 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
// Under Objective-C ARC, if the destination has non-trivial Objective-C
// lifetime, this is a non-trivial construction.
if (S.getLangOpts().ObjCAutoRefCount &&
- hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType()))
+ hasNontrivialObjCLifetime(T.getNonReferenceType()))
return false;
// The initialization succeeded; now make sure there are no non-trivial
@@ -4219,8 +4286,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
return LhsT->isVoidType();
// A function definition requires a complete, non-abstract return type.
- if (Self.RequireCompleteType(KeyLoc, RhsT, 0) ||
- Self.RequireNonAbstractType(KeyLoc, RhsT, 0))
+ if (!Self.isCompleteType(KeyLoc, RhsT) || Self.isAbstractType(KeyLoc, RhsT))
return false;
// Compute the result of add_rvalue_reference.
@@ -4506,7 +4572,7 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
return QualType();
}
- if (!IsDerivedFrom(LHSType, Class)) {
+ if (!IsDerivedFrom(Loc, LHSType, Class)) {
Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
<< (int)isIndirect << LHS.get()->getType();
return QualType();
@@ -4634,9 +4700,9 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
const RecordType *FRec = FTy->getAs<RecordType>();
const RecordType *TRec = TTy->getAs<RecordType>();
bool FDerivedFromT = FRec && TRec && FRec != TRec &&
- Self.IsDerivedFrom(FTy, TTy);
- if (FRec && TRec &&
- (FRec == TRec || FDerivedFromT || Self.IsDerivedFrom(TTy, FTy))) {
+ Self.IsDerivedFrom(QuestionLoc, FTy, TTy);
+ if (FRec && TRec && (FRec == TRec || FDerivedFromT ||
+ Self.IsDerivedFrom(QuestionLoc, TTy, FTy))) {
// E1 can be converted to match E2 if the class of T2 is the
// same type as, or a base class of, the class of T1, and
// [cv2 > cv1].
@@ -5671,9 +5737,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
//
// This also indicates that we could be parsing a pseudo-destructor-name.
// Note that Objective-C class and object types can be pseudo-destructor
- // expressions or normal member (ivar or property) access expressions.
+ // expressions or normal member (ivar or property) access expressions, and
+ // it's legal for the type to be incomplete if this is a pseudo-destructor
+ // call. We'll do more incomplete-type checks later in the lookup process,
+ // so just skip this check for ObjC types.
if (BaseType->isObjCObjectOrInterfaceType()) {
+ ObjectType = ParsedType::make(BaseType);
MayBePseudoDestructor = true;
+ return Base;
} else if (!BaseType->isRecordType()) {
ObjectType = ParsedType();
MayBePseudoDestructor = true;
@@ -6331,7 +6402,7 @@ static ExprResult attemptRecovery(Sema &SemaRef,
else if (SS && !TC.WillReplaceSpecifier())
NewSS = *SS;
- if (auto *ND = TC.getCorrectionDecl()) {
+ if (auto *ND = TC.getFoundDecl()) {
R.setLookupName(ND->getDeclName());
R.addDecl(ND);
if (ND->isCXXClassMember()) {
@@ -6364,7 +6435,7 @@ static ExprResult attemptRecovery(Sema &SemaRef,
if (MightBeImplicitMember)
return SemaRef.BuildPossibleImplicitMemberExpr(
NewSS, /*TemplateKWLoc*/ SourceLocation(), R,
- /*TemplateArgs*/ nullptr);
+ /*TemplateArgs*/ nullptr, /*S*/ nullptr);
} else if (auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
return SemaRef.LookupInObjCMethod(R, Consumer.getScope(),
Ivar->getIdentifier());
@@ -6452,9 +6523,9 @@ class TransformTypos : public TreeTransform<TransformTypos> {
if (!E)
return nullptr;
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
- return DRE->getDecl();
+ return DRE->getFoundDecl();
if (auto *ME = dyn_cast<MemberExpr>(E))
- return ME->getMemberDecl();
+ return ME->getFoundDecl();
// FIXME: Add any other expr types that could be be seen by the delayed typo
// correction TreeTransform for which the corresponding TypoCorrection could
// contain multiple decls.
@@ -6494,6 +6565,8 @@ public:
ExprResult TransformLambdaExpr(LambdaExpr *E) { return Owned(E); }
+ ExprResult TransformBlockExpr(BlockExpr *E) { return Owned(E); }
+
ExprResult Transform(Expr *E) {
ExprResult Res;
while (true) {
@@ -6557,7 +6630,7 @@ public:
// For the first TypoExpr and an uncached TypoExpr, find the next likely
// typo correction and return it.
while (TypoCorrection TC = State.Consumer->getNextCorrection()) {
- if (InitDecl && TC.getCorrectionDecl() == InitDecl)
+ if (InitDecl && TC.getFoundDecl() == InitDecl)
continue;
ExprResult NE = State.RecoveryHandler ?
State.RecoveryHandler(SemaRef, E, TC) :
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
index a9f1919..9c345f8 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp
@@ -27,18 +27,15 @@ using namespace clang;
using namespace sema;
typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet;
-static bool BaseIsNotInSet(const CXXRecordDecl *Base, void *BasesPtr) {
- const BaseSet &Bases = *reinterpret_cast<const BaseSet*>(BasesPtr);
- return !Bases.count(Base->getCanonicalDecl());
-}
/// Determines if the given class is provably not derived from all of
/// the prospective base classes.
static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record,
const BaseSet &Bases) {
- void *BasesPtr = const_cast<void*>(reinterpret_cast<const void*>(&Bases));
- return BaseIsNotInSet(Record, BasesPtr) &&
- Record->forallBases(BaseIsNotInSet, BasesPtr);
+ auto BaseIsNotInSet = [&Bases](const CXXRecordDecl *Base) {
+ return !Bases.count(Base->getCanonicalDecl());
+ };
+ return BaseIsNotInSet(Record) && Record->forallBases(BaseIsNotInSet);
}
enum IMAKind {
@@ -105,8 +102,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
bool hasNonInstance = false;
bool isField = false;
BaseSet Classes;
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- NamedDecl *D = *I;
+ for (NamedDecl *D : R) {
+ // Look through any using decls.
+ D = D->getUnderlyingDecl();
if (D->isCXXInstanceMember()) {
isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) ||
@@ -114,8 +112,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
Classes.insert(R->getCanonicalDecl());
- }
- else
+ } else
hasNonInstance = true;
}
@@ -237,15 +234,17 @@ ExprResult
Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
- const TemplateArgumentListInfo *TemplateArgs) {
+ const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S) {
switch (ClassifyImplicitMemberAccess(*this, R)) {
case IMA_Instance:
- return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true);
+ return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S);
case IMA_Mixed:
case IMA_Mixed_Unrelated:
case IMA_Unresolved:
- return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false);
+ return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false,
+ S);
case IMA_Field_Uneval_Context:
Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
@@ -633,6 +632,16 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
DeclarationName Typo = R.getLookupName();
SourceLocation TypoLoc = R.getNameLoc();
+
+ struct QueryState {
+ Sema &SemaRef;
+ DeclarationNameInfo NameInfo;
+ Sema::LookupNameKind LookupKind;
+ Sema::RedeclarationKind Redecl;
+ };
+ QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(),
+ R.isForRedeclaration() ? Sema::ForRedeclaration
+ : Sema::NotForRedeclaration};
TE = SemaRef.CorrectTypoDelayed(
R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS,
llvm::make_unique<RecordMemberExprValidatorCCC>(RTy),
@@ -651,6 +660,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
}
},
[=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable {
+ LookupResult R(Q.SemaRef, Q.NameInfo, Q.LookupKind, Q.Redecl);
R.clear(); // Ensure there's no decls lingering in the shared state.
R.suppressDiagnostics();
R.setLookupName(TC.getCorrection());
@@ -659,7 +669,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
R.resolveKind();
return SemaRef.BuildMemberReferenceExpr(
BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(),
- nullptr, R, nullptr);
+ nullptr, R, nullptr, nullptr);
},
Sema::CTK_ErrorRecovery, DC);
@@ -679,6 +689,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
NamedDecl *FirstQualifierInScope,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S,
ActOnMemberAccessExtraArgs *ExtraArgs) {
if (BaseType->isDependentType() ||
(SS.isSet() && isDependentScopeSpecifier(SS)))
@@ -725,7 +736,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
return BuildMemberReferenceExpr(Base, BaseType,
OpLoc, IsArrow, SS, TemplateKWLoc,
- FirstQualifierInScope, R, TemplateArgs,
+ FirstQualifierInScope, R, TemplateArgs, S,
false, ExtraArgs);
}
@@ -877,6 +888,18 @@ static MemberExpr *BuildMemberExpr(
return E;
}
+/// \brief Determine if the given scope is within a function-try-block handler.
+static bool IsInFnTryBlockHandler(const Scope *S) {
+ // Walk the scope stack until finding a FnTryCatchScope, or leave the
+ // function scope. If a FnTryCatchScope is found, check whether the TryScope
+ // flag is set. If it is not, it's a function-try-block handler.
+ for (; S != S->getFnParent(); S = S->getParent()) {
+ if (S->getFlags() & Scope::FnTryCatchScope)
+ return (S->getFlags() & Scope::TryScope) != Scope::TryScope;
+ }
+ return false;
+}
+
ExprResult
Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
SourceLocation OpLoc, bool IsArrow,
@@ -885,6 +908,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
NamedDecl *FirstQualifierInScope,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S,
bool SuppressQualifierCheck,
ActOnMemberAccessExtraArgs *ExtraArgs) {
QualType BaseType = BaseExprType;
@@ -948,6 +972,17 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
if (R.isAmbiguous())
return ExprError();
+ // [except.handle]p10: Referring to any non-static member or base class of an
+ // object in the handler for a function-try-block of a constructor or
+ // destructor for that object results in undefined behavior.
+ const auto *FD = getCurFunctionDecl();
+ if (S && BaseExpr && FD &&
+ (isa<CXXDestructorDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
+ isa<CXXThisExpr>(BaseExpr->IgnoreImpCasts()) &&
+ IsInFnTryBlockHandler(S))
+ Diag(MemberLoc, diag::warn_cdtor_function_try_handler_mem_expr)
+ << isa<CXXDestructorDecl>(FD);
+
if (R.empty()) {
// Rederive where we looked up.
DeclContext *DC = (SS.isSet()
@@ -1042,16 +1077,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true);
}
- bool ShouldCheckUse = true;
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) {
- // Don't diagnose the use of a virtual member function unless it's
- // explicitly qualified.
- if (MD->isVirtual() && !SS.isSet())
- ShouldCheckUse = false;
- }
-
// Check the use of this member.
- if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc))
+ if (DiagnoseUseOfDecl(MemberDecl, MemberLoc))
return ExprError();
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
@@ -1645,7 +1672,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl};
return BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, IsArrow, SS,
TemplateKWLoc, FirstQualifierInScope,
- NameInfo, TemplateArgs, &ExtraArgs);
+ NameInfo, TemplateArgs, S, &ExtraArgs);
}
static ExprResult
@@ -1718,7 +1745,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
- bool IsKnownInstance) {
+ bool IsKnownInstance, const Scope *S) {
assert(!R.empty() && !R.isAmbiguous());
SourceLocation loc = R.getNameLoc();
@@ -1743,5 +1770,5 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
/*IsArrow*/ true,
SS, TemplateKWLoc,
/*FirstQualifierInScope*/ nullptr,
- R, TemplateArgs);
+ R, TemplateArgs, S);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
index 6cd0626..1d86ca3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp
@@ -32,24 +32,21 @@ using namespace sema;
using llvm::makeArrayRef;
ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
- Expr **strings,
- unsigned NumStrings) {
- StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings);
-
+ ArrayRef<Expr *> Strings) {
// Most ObjC strings are formed out of a single piece. However, we *can*
// have strings formed out of multiple @ strings with multiple pptokens in
// each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one
// StringLiteral for ObjCStringLiteral to hold onto.
- StringLiteral *S = Strings[0];
+ StringLiteral *S = cast<StringLiteral>(Strings[0]);
// If we have a multi-part string, merge it all together.
- if (NumStrings != 1) {
+ if (Strings.size() != 1) {
// Concatenate objc strings.
SmallString<128> StrBuf;
SmallVector<SourceLocation, 8> StrLocs;
- for (unsigned i = 0; i != NumStrings; ++i) {
- S = Strings[i];
+ for (Expr *E : Strings) {
+ S = cast<StringLiteral>(E);
// ObjC strings can't be wide or UTF.
if (!S->isAscii()) {
@@ -168,6 +165,77 @@ static bool validateBoxingMethod(Sema &S, SourceLocation Loc,
return true;
}
+/// \brief Maps ObjCLiteralKind to NSClassIdKindKind
+static NSAPI::NSClassIdKindKind ClassKindFromLiteralKind(
+ Sema::ObjCLiteralKind LiteralKind) {
+ switch (LiteralKind) {
+ case Sema::LK_Array:
+ return NSAPI::ClassId_NSArray;
+ case Sema::LK_Dictionary:
+ return NSAPI::ClassId_NSDictionary;
+ case Sema::LK_Numeric:
+ return NSAPI::ClassId_NSNumber;
+ case Sema::LK_String:
+ return NSAPI::ClassId_NSString;
+ case Sema::LK_Boxed:
+ return NSAPI::ClassId_NSValue;
+
+ // there is no corresponding matching
+ // between LK_None/LK_Block and NSClassIdKindKind
+ case Sema::LK_Block:
+ case Sema::LK_None:
+ break;
+ }
+ llvm_unreachable("LiteralKind can't be converted into a ClassKind");
+}
+
+/// \brief Validates ObjCInterfaceDecl availability.
+/// ObjCInterfaceDecl, used to create ObjC literals, should be defined
+/// if clang not in a debugger mode.
+static bool ValidateObjCLiteralInterfaceDecl(Sema &S, ObjCInterfaceDecl *Decl,
+ SourceLocation Loc,
+ Sema::ObjCLiteralKind LiteralKind) {
+ if (!Decl) {
+ NSAPI::NSClassIdKindKind Kind = ClassKindFromLiteralKind(LiteralKind);
+ IdentifierInfo *II = S.NSAPIObj->getNSClassId(Kind);
+ S.Diag(Loc, diag::err_undeclared_objc_literal_class)
+ << II->getName() << LiteralKind;
+ return false;
+ } else if (!Decl->hasDefinition() && !S.getLangOpts().DebuggerObjCLiteral) {
+ S.Diag(Loc, diag::err_undeclared_objc_literal_class)
+ << Decl->getName() << LiteralKind;
+ S.Diag(Decl->getLocation(), diag::note_forward_class);
+ return false;
+ }
+
+ return true;
+}
+
+/// \brief Looks up ObjCInterfaceDecl of a given NSClassIdKindKind.
+/// Used to create ObjC literals, such as NSDictionary (@{}),
+/// NSArray (@[]) and Boxed Expressions (@())
+static ObjCInterfaceDecl *LookupObjCInterfaceDeclForLiteral(Sema &S,
+ SourceLocation Loc,
+ Sema::ObjCLiteralKind LiteralKind) {
+ NSAPI::NSClassIdKindKind ClassKind = ClassKindFromLiteralKind(LiteralKind);
+ IdentifierInfo *II = S.NSAPIObj->getNSClassId(ClassKind);
+ NamedDecl *IF = S.LookupSingleName(S.TUScope, II, Loc,
+ Sema::LookupOrdinaryName);
+ ObjCInterfaceDecl *ID = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ if (!ID && S.getLangOpts().DebuggerObjCLiteral) {
+ ASTContext &Context = S.Context;
+ TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
+ ID = ObjCInterfaceDecl::Create (Context, TU, SourceLocation(), II,
+ nullptr, nullptr, SourceLocation());
+ }
+
+ if (!ValidateObjCLiteralInterfaceDecl(S, ID, Loc, LiteralKind)) {
+ ID = nullptr;
+ }
+
+ return ID;
+}
+
/// \brief Retrieve the NSNumber factory method that should be used to create
/// an Objective-C literal for the given type.
static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
@@ -197,26 +265,9 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
// Look up the NSNumber class, if we haven't done so already. It's cached
// in the Sema instance.
if (!S.NSNumberDecl) {
- IdentifierInfo *NSNumberId =
- S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber);
- NamedDecl *IF = S.LookupSingleName(S.TUScope, NSNumberId,
- Loc, Sema::LookupOrdinaryName);
- S.NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ S.NSNumberDecl = LookupObjCInterfaceDeclForLiteral(S, Loc,
+ Sema::LK_Numeric);
if (!S.NSNumberDecl) {
- if (S.getLangOpts().DebuggerObjCLiteral) {
- // Create a stub definition of NSNumber.
- S.NSNumberDecl = ObjCInterfaceDecl::Create(CX,
- CX.getTranslationUnitDecl(),
- SourceLocation(), NSNumberId,
- nullptr, nullptr,
- SourceLocation());
- } else {
- // Otherwise, require a declaration of NSNumber.
- S.Diag(Loc, diag::err_undeclared_nsnumber);
- return nullptr;
- }
- } else if (!S.NSNumberDecl->hasDefinition()) {
- S.Diag(Loc, diag::err_undeclared_nsnumber);
return nullptr;
}
}
@@ -268,6 +319,7 @@ ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
// to use to determine the Objective-c literal kind.
switch (Char->getKind()) {
case CharacterLiteral::Ascii:
+ case CharacterLiteral::UTF8:
NumberType = Context.CharTy;
break;
@@ -457,6 +509,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
if (RValue.isInvalid()) {
return ExprError();
}
+ SourceLocation Loc = SR.getBegin();
ValueExpr = RValue.get();
QualType ValueType(ValueExpr->getType());
if (const PointerType *PT = ValueType->getAs<PointerType>()) {
@@ -464,29 +517,11 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) {
if (!NSStringDecl) {
- IdentifierInfo *NSStringId =
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSString);
- NamedDecl *Decl = LookupSingleName(TUScope, NSStringId,
- SR.getBegin(), LookupOrdinaryName);
- NSStringDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl);
+ NSStringDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
+ Sema::LK_String);
if (!NSStringDecl) {
- if (getLangOpts().DebuggerObjCLiteral) {
- // Support boxed expressions in the debugger w/o NSString declaration.
- DeclContext *TU = Context.getTranslationUnitDecl();
- NSStringDecl = ObjCInterfaceDecl::Create(Context, TU,
- SourceLocation(),
- NSStringId,
- nullptr, nullptr,
- SourceLocation());
- } else {
- Diag(SR.getBegin(), diag::err_undeclared_nsstring);
- return ExprError();
- }
- } else if (!NSStringDecl->hasDefinition()) {
- Diag(SR.getBegin(), diag::err_undeclared_nsstring);
return ExprError();
}
- assert(NSStringDecl && "NSStringDecl should not be NULL");
QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl);
NSStringPointer = Context.getObjCObjectPointerType(NSStringObject);
}
@@ -520,7 +555,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
BoxingMethod = M;
}
- if (!validateBoxingMethod(*this, SR.getBegin(), NSStringDecl,
+ if (!validateBoxingMethod(*this, Loc, NSStringDecl,
stringWithUTF8String, BoxingMethod))
return ExprError();
@@ -543,6 +578,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
// to use to determine the Objective-c literal kind.
switch (Char->getKind()) {
case CharacterLiteral::Ascii:
+ case CharacterLiteral::UTF8:
ValueType = Context.CharTy;
break;
@@ -563,16 +599,16 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
// FIXME: Do I need to do anything special with BoolTy expressions?
// Look for the appropriate method within NSNumber.
- BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType);
+ BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ValueType);
BoxedType = NSNumberPointer;
} else if (const EnumType *ET = ValueType->getAs<EnumType>()) {
if (!ET->getDecl()->isComplete()) {
- Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type)
+ Diag(Loc, diag::err_objc_incomplete_boxed_expression_type)
<< ValueType << ValueExpr->getSourceRange();
return ExprError();
}
- BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(),
+ BoxingMethod = getNSNumberFactoryMethod(*this, Loc,
ET->getDecl()->getIntegerType());
BoxedType = NSNumberPointer;
} else if (ValueType->isObjCBoxableRecordType()) {
@@ -582,29 +618,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
// Look up the NSValue class, if we haven't done so already. It's cached
// in the Sema instance.
if (!NSValueDecl) {
- IdentifierInfo *NSValueId =
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSValue);
- NamedDecl *IF = LookupSingleName(TUScope, NSValueId,
- SR.getBegin(), Sema::LookupOrdinaryName);
- NSValueDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
+ NSValueDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
+ Sema::LK_Boxed);
if (!NSValueDecl) {
- if (getLangOpts().DebuggerObjCLiteral) {
- // Create a stub definition of NSValue.
- DeclContext *TU = Context.getTranslationUnitDecl();
- NSValueDecl = ObjCInterfaceDecl::Create(Context, TU,
- SourceLocation(), NSValueId,
- nullptr, nullptr,
- SourceLocation());
- } else {
- // Otherwise, require a declaration of NSValue.
- Diag(SR.getBegin(), diag::err_undeclared_nsvalue);
- return ExprError();
- }
- } else if (!NSValueDecl->hasDefinition()) {
- Diag(SR.getBegin(), diag::err_undeclared_nsvalue);
return ExprError();
}
-
+
// generate the pointer to NSValue type.
QualType NSValueObject = Context.getObjCInterfaceType(NSValueDecl);
NSValuePointer = Context.getObjCObjectPointerType(NSValueObject);
@@ -663,7 +682,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
BoxingMethod = M;
}
- if (!validateBoxingMethod(*this, SR.getBegin(), NSValueDecl,
+ if (!validateBoxingMethod(*this, Loc, NSValueDecl,
ValueWithBytesObjCType, BoxingMethod))
return ExprError();
@@ -671,8 +690,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
}
if (!ValueType.isTriviallyCopyableType(Context)) {
- Diag(SR.getBegin(),
- diag::err_objc_non_trivially_copyable_boxed_expression_type)
+ Diag(Loc, diag::err_objc_non_trivially_copyable_boxed_expression_type)
<< ValueType << ValueExpr->getSourceRange();
return ExprError();
}
@@ -682,12 +700,12 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
}
if (!BoxingMethod) {
- Diag(SR.getBegin(), diag::err_objc_illegal_boxed_expression_type)
+ Diag(Loc, diag::err_objc_illegal_boxed_expression_type)
<< ValueType << ValueExpr->getSourceRange();
return ExprError();
}
- DiagnoseUseOfDecl(BoxingMethod, SR.getBegin());
+ DiagnoseUseOfDecl(BoxingMethod, Loc);
ExprResult ConvertedValueExpr;
if (ValueType->isObjCBoxableRecordType()) {
@@ -740,32 +758,22 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
BaseExpr = Result.get();
// Build the pseudo-object expression.
- return ObjCSubscriptRefExpr::Create(Context, BaseExpr, IndexExpr,
- Context.PseudoObjectTy, getterMethod,
- setterMethod, RB);
+ return new (Context) ObjCSubscriptRefExpr(
+ BaseExpr, IndexExpr, Context.PseudoObjectTy, VK_LValue, OK_ObjCSubscript,
+ getterMethod, setterMethod, RB);
}
ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
- // Look up the NSArray class, if we haven't done so already.
- if (!NSArrayDecl) {
- NamedDecl *IF = LookupSingleName(TUScope,
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
- SR.getBegin(),
- LookupOrdinaryName);
- NSArrayDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
- if (!NSArrayDecl && getLangOpts().DebuggerObjCLiteral)
- NSArrayDecl = ObjCInterfaceDecl::Create (Context,
- Context.getTranslationUnitDecl(),
- SourceLocation(),
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
- nullptr, nullptr, SourceLocation());
+ SourceLocation Loc = SR.getBegin();
+ if (!NSArrayDecl) {
+ NSArrayDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
+ Sema::LK_Array);
if (!NSArrayDecl) {
- Diag(SR.getBegin(), diag::err_undeclared_nsarray);
return ExprError();
}
}
-
+
// Find the arrayWithObjects:count: method, if we haven't done so already.
QualType IdT = Context.getObjCIdType();
if (!ArrayWithObjectsMethod) {
@@ -801,7 +809,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
Method->setMethodParams(Context, Params, None);
}
- if (!validateBoxingMethod(*this, SR.getBegin(), NSArrayDecl, Sel, Method))
+ if (!validateBoxingMethod(*this, Loc, NSArrayDecl, Sel, Method))
return ExprError();
// Dig out the type that all elements should be converted to.
@@ -859,28 +867,18 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
ArrayWithObjectsMethod, SR));
}
-ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
- ObjCDictionaryElement *Elements,
- unsigned NumElements) {
- // Look up the NSDictionary class, if we haven't done so already.
- if (!NSDictionaryDecl) {
- NamedDecl *IF = LookupSingleName(TUScope,
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
- SR.getBegin(), LookupOrdinaryName);
- NSDictionaryDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
- if (!NSDictionaryDecl && getLangOpts().DebuggerObjCLiteral)
- NSDictionaryDecl = ObjCInterfaceDecl::Create (Context,
- Context.getTranslationUnitDecl(),
- SourceLocation(),
- NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
- nullptr, nullptr, SourceLocation());
+ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
+ MutableArrayRef<ObjCDictionaryElement> Elements) {
+ SourceLocation Loc = SR.getBegin();
+ if (!NSDictionaryDecl) {
+ NSDictionaryDecl = LookupObjCInterfaceDeclForLiteral(*this, Loc,
+ Sema::LK_Dictionary);
if (!NSDictionaryDecl) {
- Diag(SR.getBegin(), diag::err_undeclared_nsdictionary);
- return ExprError();
+ return ExprError();
}
}
-
+
// Find the dictionaryWithObjects:forKeys:count: method, if we haven't done
// so already.
QualType IdT = Context.getObjCIdType();
@@ -1007,31 +1005,31 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
// Check that each of the keys and values provided is valid in a collection
// literal, performing conversions as necessary.
bool HasPackExpansions = false;
- for (unsigned I = 0, N = NumElements; I != N; ++I) {
+ for (ObjCDictionaryElement &Element : Elements) {
// Check the key.
- ExprResult Key = CheckObjCCollectionLiteralElement(*this, Elements[I].Key,
+ ExprResult Key = CheckObjCCollectionLiteralElement(*this, Element.Key,
KeyT);
if (Key.isInvalid())
return ExprError();
// Check the value.
ExprResult Value
- = CheckObjCCollectionLiteralElement(*this, Elements[I].Value, ValueT);
+ = CheckObjCCollectionLiteralElement(*this, Element.Value, ValueT);
if (Value.isInvalid())
return ExprError();
- Elements[I].Key = Key.get();
- Elements[I].Value = Value.get();
+ Element.Key = Key.get();
+ Element.Value = Value.get();
- if (Elements[I].EllipsisLoc.isInvalid())
+ if (Element.EllipsisLoc.isInvalid())
continue;
- if (!Elements[I].Key->containsUnexpandedParameterPack() &&
- !Elements[I].Value->containsUnexpandedParameterPack()) {
- Diag(Elements[I].EllipsisLoc,
+ if (!Element.Key->containsUnexpandedParameterPack() &&
+ !Element.Value->containsUnexpandedParameterPack()) {
+ Diag(Element.EllipsisLoc,
diag::err_pack_expansion_without_parameter_packs)
- << SourceRange(Elements[I].Key->getLocStart(),
- Elements[I].Value->getLocEnd());
+ << SourceRange(Element.Key->getLocStart(),
+ Element.Value->getLocEnd());
return ExprError();
}
@@ -1043,7 +1041,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
= Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(NSDictionaryDecl));
return MaybeBindToTemporary(ObjCDictionaryLiteral::Create(
- Context, makeArrayRef(Elements, NumElements), HasPackExpansions, Ty,
+ Context, Elements, HasPackExpansions, Ty,
DictionaryWithObjectsMethod, SR));
}
@@ -1092,7 +1090,7 @@ ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
QualType EncodedType = GetTypeFromParser(ty, &TInfo);
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(EncodedType,
- PP.getLocForEndOfToken(LParenLoc));
+ getLocForEndOfToken(LParenLoc));
return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);
}
@@ -1657,7 +1655,8 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
// Objective-C pointer type, we may need to extend the lifetime
// of the block object.
if (typeArgs && Args[i]->isRValue() && paramType->isBlockPointerType() &&
- origParamType->isBlockCompatibleObjCPointerType(Context)) {
+ Args[i]->getType()->isBlockPointerType() &&
+ origParamType->isObjCObjectPointerType()) {
ExprResult arg = Args[i];
maybeExtendBlockObject(arg);
Args[i] = arg.get();
@@ -1778,8 +1777,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
diag::err_property_not_found_forward_class,
MemberName, BaseRange))
return ExprError();
-
- // Search for a declared property first.
+
if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
// Check whether we can reference this property.
if (DiagnoseUseOfDecl(PD, MemberLoc))
@@ -2726,6 +2724,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// Try to complete the type. Under ARC, this is a hard error from which
// we don't try to recover.
+ // FIXME: In the non-ARC case, this will still be a hard error if the
+ // definition is found in a module that's not visible.
const ObjCInterfaceDecl *forwardClass = nullptr;
if (RequireCompleteType(Loc, OCIType->getPointeeType(),
getLangOpts().ObjCAutoRefCount
@@ -3397,7 +3397,7 @@ static void addFixitForObjCARCConversion(Sema &S,
DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
BridgeCall));
DiagB.AddFixItHint(FixItHint::CreateInsertion(
- S.PP.getLocForEndOfToken(range.getEnd()),
+ S.getLocForEndOfToken(range.getEnd()),
")"));
}
return;
@@ -3430,7 +3430,7 @@ static void addFixitForObjCARCConversion(Sema &S,
DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
castCode));
DiagB.AddFixItHint(FixItHint::CreateInsertion(
- S.PP.getLocForEndOfToken(range.getEnd()),
+ S.getLocForEndOfToken(range.getEnd()),
")"));
}
}
@@ -3471,7 +3471,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
(castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());
if (S.makeUnavailableInSystemHeader(loc,
- "converts between Objective-C and C pointers in -fobjc-arc"))
+ UnavailableAttr::IR_ARCForbiddenConversion))
return;
QualType castExprType = castExpr->getType();
@@ -3498,7 +3498,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
}
// Check whether this could be fixed with a bridge cast.
- SourceLocation afterLParen = S.PP.getLocForEndOfToken(castRange.getBegin());
+ SourceLocation afterLParen = S.getLocForEndOfToken(castRange.getBegin());
SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc;
// Bridge from an ARC type to a CF type.
@@ -3901,7 +3901,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
ExpressionString += RelatedClass->getNameAsString();
ExpressionString += " ";
ExpressionString += ClassMethod->getSelector().getAsString();
- SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd());
+ SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd());
// Provide a fixit: [RelatedClass ClassMethod SrcExpr]
Diag(Loc, diag::err_objc_bridged_related_known_method)
<< SrcType << DestType << ClassMethod->getSelector() << false
@@ -3926,7 +3926,7 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
// Implicit conversion from ObjC type to CF object is needed.
if (InstanceMethod) {
std::string ExpressionString;
- SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd());
+ SourceLocation SrcExprEndLoc = getLocForEndOfToken(SrcExpr->getLocEnd());
if (InstanceMethod->isPropertyAccessor())
if (const ObjCPropertyDecl *PDecl = InstanceMethod->findPropertyDecl()) {
// fixit: ObjectExpr.propertyname when it is aproperty accessor.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp
index 2e327ec..714fbed 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp
@@ -42,7 +42,7 @@ bool ConversionFixItGenerator::compareTypesSimple(CanQualType From,
const CanQualType FromUnq = From.getUnqualifiedType();
const CanQualType ToUnq = To.getUnqualifiedType();
- if ((FromUnq == ToUnq || (S.IsDerivedFrom(FromUnq, ToUnq)) ) &&
+ if ((FromUnq == ToUnq || (S.IsDerivedFrom(Loc, FromUnq, ToUnq)) ) &&
To.isAtLeastAsQualifiedAs(From))
return true;
return false;
@@ -58,8 +58,8 @@ bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr,
const CanQualType FromQTy = S.Context.getCanonicalType(FromTy);
const CanQualType ToQTy = S.Context.getCanonicalType(ToTy);
const SourceLocation Begin = FullExpr->getSourceRange().getBegin();
- const SourceLocation End = S.PP.getLocForEndOfToken(FullExpr->getSourceRange()
- .getEnd());
+ const SourceLocation End = S.getLocForEndOfToken(FullExpr->getSourceRange()
+ .getEnd());
// Strip the implicit casts - those are implied by the compiler, not the
// original source code.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index adec512..c3a8946 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -443,8 +443,11 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef,
if (!VerifyOnly) {
SemaRef.Diag(CtorDecl->getLocation(),
diag::warn_invalid_initializer_from_system_header);
- SemaRef.Diag(Entity.getDecl()->getLocation(),
- diag::note_used_in_initialization_here);
+ if (Entity.getKind() == InitializedEntity::EK_Member)
+ SemaRef.Diag(Entity.getDecl()->getLocation(),
+ diag::note_used_in_initialization_here);
+ else if (Entity.getKind() == InitializedEntity::EK_ArrayElement)
+ SemaRef.Diag(Loc, diag::note_used_in_initialization_here);
}
}
}
@@ -802,7 +805,8 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
// Update the structured sub-object initializer so that it's ending
// range corresponds with the end of the last initializer it used.
- if (EndIndex < ParentIList->getNumInits()) {
+ if (EndIndex < ParentIList->getNumInits() &&
+ ParentIList->getInit(EndIndex)) {
SourceLocation EndLoc
= ParentIList->getInit(EndIndex)->getSourceRange().getEnd();
StructuredSubobjectInitList->setRBraceLoc(EndLoc);
@@ -3008,6 +3012,7 @@ bool InitializationSequence::isAmbiguous() const {
case FK_VariableLengthArrayHasInitializer:
case FK_PlaceholderType:
case FK_ExplicitConstructor:
+ case FK_AddressOfUnaddressableFunction:
return false;
case FK_ReferenceInitOverloadFailed:
@@ -3323,7 +3328,7 @@ static bool TryInitializerListConstruction(Sema &S,
if (!S.isStdInitializerList(DestType, &E))
return false;
- if (S.RequireCompleteType(List->getExprLoc(), E, 0)) {
+ if (!S.isCompleteType(List->getExprLoc(), E)) {
Sequence.setIncompleteTypeFailure(E);
return true;
}
@@ -3433,7 +3438,7 @@ static void TryConstructorInitialization(Sema &S,
"IsListInit must come with a single initializer list argument.");
// The type we're constructing needs to be complete.
- if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+ if (!S.isCompleteType(Kind.getLocation(), DestType)) {
Sequence.setIncompleteTypeFailure(DestType);
return;
}
@@ -3674,7 +3679,7 @@ static void TryListInitialization(Sema &S,
}
if (DestType->isRecordType() &&
- S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) {
+ !S.isCompleteType(InitList->getLocStart(), DestType)) {
Sequence.setIncompleteTypeFailure(DestType);
return;
}
@@ -3694,7 +3699,7 @@ static void TryListInitialization(Sema &S,
if (DestType->isRecordType()) {
QualType InitType = InitList->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
- S.IsDerivedFrom(InitType, DestType)) {
+ S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) {
Expr *InitAsExpr = InitList->getInit(0);
TryConstructorInitialization(S, Entity, Kind, InitAsExpr, DestType,
Sequence, /*InitListSyntax*/ false,
@@ -3728,7 +3733,9 @@ static void TryListInitialization(Sema &S,
// C++11 [dcl.init.list]p3:
// - If T is an aggregate, aggregate initialization is performed.
- if (DestType->isRecordType() && !DestType->isAggregateType()) {
+ if ((DestType->isRecordType() && !DestType->isAggregateType()) ||
+ (S.getLangOpts().CPlusPlus11 &&
+ S.isStdInitializerList(DestType, nullptr))) {
if (S.getLangOpts().CPlusPlus11) {
// - Otherwise, if the initializer list has no elements and T is a
// class type with a default constructor, the object is
@@ -3834,7 +3841,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
const RecordType *T1RecordType = nullptr;
if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) &&
- !S.RequireCompleteType(Kind.getLocation(), T1, 0)) {
+ S.isCompleteType(Kind.getLocation(), T1)) {
// The type we're converting to is a class type. Enumerate its constructors
// to see if there is a suitable conversion.
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
@@ -3870,7 +3877,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
const RecordType *T2RecordType = nullptr;
if ((T2RecordType = T2->getAs<RecordType>()) &&
- !S.RequireCompleteType(Kind.getLocation(), T2, 0)) {
+ S.isCompleteType(Kind.getLocation(), T2)) {
// The type we're converting from is a class type, enumerate its conversion
// functions.
CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
@@ -4455,7 +4462,7 @@ static void TryUserDefinedConversion(Sema &S,
= cast<CXXRecordDecl>(DestRecordType->getDecl());
// Try to complete the type we're converting to.
- if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+ if (S.isCompleteType(Kind.getLocation(), DestType)) {
DeclContext::lookup_result R = S.LookupConstructors(DestRecordDecl);
// The container holding the constructors can under certain conditions
// be changed while iterating. To be safe we copy the lookup results
@@ -4501,7 +4508,7 @@ static void TryUserDefinedConversion(Sema &S,
// We can only enumerate the conversion functions for a complete type; if
// the type isn't complete, simply skip this step.
- if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) {
+ if (S.isCompleteType(DeclLoc, SourceType)) {
CXXRecordDecl *SourceRecordDecl
= cast<CXXRecordDecl>(SourceRecordType->getDecl());
@@ -4798,6 +4805,17 @@ InitializationSequence::InitializationSequence(Sema &S,
InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList);
}
+/// Tries to get a FunctionDecl out of `E`. If it succeeds and we can take the
+/// address of that function, this returns true. Otherwise, it returns false.
+static bool isExprAnUnaddressableFunction(Sema &S, const Expr *E) {
+ auto *DRE = dyn_cast<DeclRefExpr>(E);
+ if (!DRE || !isa<FunctionDecl>(DRE->getDecl()))
+ return false;
+
+ return !S.checkAddressOfFunctionIsAvailable(
+ cast<FunctionDecl>(DRE->getDecl()));
+}
+
void InitializationSequence::InitializeFrom(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4979,7 +4997,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
}
assert(S.getLangOpts().CPlusPlus);
-
+
// - If the destination type is a (possibly cv-qualified) class type:
if (DestType->isRecordType()) {
// - If the initialization is direct-initialization, or if it is
@@ -4989,7 +5007,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
if (Kind.getKind() == InitializationKind::IK_Direct ||
(Kind.getKind() == InitializationKind::IK_Copy &&
(Context.hasSameUnqualifiedType(SourceType, DestType) ||
- S.IsDerivedFrom(SourceType, DestType))))
+ S.IsDerivedFrom(Initializer->getLocStart(), SourceType, DestType))))
TryConstructorInitialization(S, Entity, Kind, Args,
DestType, *this);
// - Otherwise (i.e., for the remaining copy-initialization cases),
@@ -5018,7 +5036,8 @@ void InitializationSequence::InitializeFrom(Sema &S,
bool NeedAtomicConversion = false;
if (const AtomicType *Atomic = DestType->getAs<AtomicType>()) {
if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) ||
- S.IsDerivedFrom(SourceType, Atomic->getValueType())) {
+ S.IsDerivedFrom(Initializer->getLocStart(), SourceType,
+ Atomic->getValueType())) {
DestType = Atomic->getValueType();
NeedAtomicConversion = true;
}
@@ -5076,6 +5095,9 @@ void InitializationSequence::InitializeFrom(Sema &S,
!S.ResolveAddressOfOverloadedFunction(Initializer, DestType,
false, dap))
SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+ else if (Initializer->getType()->isFunctionType() &&
+ isExprAnUnaddressableFunction(S, Initializer))
+ SetFailed(InitializationSequence::FK_AddressOfUnaddressableFunction);
else
SetFailed(InitializationSequence::FK_ConversionFailed);
} else {
@@ -6357,7 +6379,7 @@ InitializationSequence::Perform(Sema &S,
CastKind = CK_ConstructorConversion;
QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
if (S.Context.hasSameUnqualifiedType(SourceType, Class) ||
- S.IsDerivedFrom(SourceType, Class))
+ S.IsDerivedFrom(Loc, SourceType, Class))
IsCopy = true;
CreatedObject = true;
@@ -6596,6 +6618,8 @@ InitializationSequence::Perform(Sema &S,
case SK_CAssignment: {
QualType SourceType = CurInit.get()->getType();
+ // Save off the initial CurInit in case we need to emit a diagnostic
+ ExprResult InitialCurInit = CurInit;
ExprResult Result = CurInit;
Sema::AssignConvertType ConvTy =
S.CheckSingleAssignmentConstraints(Step->Type, Result, true,
@@ -6618,7 +6642,7 @@ InitializationSequence::Perform(Sema &S,
bool Complained;
if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
Step->Type, SourceType,
- CurInit.get(),
+ InitialCurInit.get(),
getAssignmentAction(Entity, true),
&Complained)) {
PrintInitLocationNote(S, Entity);
@@ -6921,6 +6945,13 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
}
+ case FK_AddressOfUnaddressableFunction: {
+ auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(Args[0])->getDecl());
+ S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
+ Args[0]->getLocStart());
+ break;
+ }
+
case FK_ReferenceInitOverloadFailed:
case FK_UserConversionOverloadFailed:
switch (FailedOverloadResult) {
@@ -6943,6 +6974,7 @@ bool InitializationSequence::Diagnose(Sema &S,
diag::err_typecheck_nonviable_condition_incomplete,
Args[0]->getType(), Args[0]->getSourceRange()))
S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
+ << (Entity.getKind() == InitializedEntity::EK_Result)
<< Args[0]->getType() << Args[0]->getSourceRange()
<< DestType.getNonReferenceType();
@@ -7043,10 +7075,12 @@ bool InitializationSequence::Diagnose(Sema &S,
SourceRange R;
auto *InitList = dyn_cast<InitListExpr>(Args[0]);
- if (InitList && InitList->getNumInits() == 1)
+ if (InitList && InitList->getNumInits() >= 1) {
R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd());
- else
+ } else {
+ assert(Args.size() > 1 && "Expected multiple initializers!");
R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd());
+ }
R.setBegin(S.getLocForEndOfToken(R.getBegin()));
if (Kind.isCStyleOrFunctionalCast())
@@ -7240,6 +7274,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "array requires initializer list";
break;
+ case FK_AddressOfUnaddressableFunction:
+ OS << "address of unaddressable function was taken";
+ break;
+
case FK_ArrayNeedsInitListOrStringLiteral:
OS << "array requires initializer list or string literal";
break;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
index 8220641..884add2 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp
@@ -226,15 +226,16 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
if (LSI->GLTemplateParameterList)
return LSI->GLTemplateParameterList;
- if (LSI->AutoTemplateParams.size()) {
+ if (!LSI->AutoTemplateParams.empty()) {
SourceRange IntroRange = LSI->IntroducerRange;
SourceLocation LAngleLoc = IntroRange.getBegin();
SourceLocation RAngleLoc = IntroRange.getEnd();
LSI->GLTemplateParameterList = TemplateParameterList::Create(
SemaRef.Context,
/*Template kw loc*/ SourceLocation(), LAngleLoc,
- (NamedDecl **)LSI->AutoTemplateParams.data(),
- LSI->AutoTemplateParams.size(), RAngleLoc);
+ llvm::makeArrayRef((NamedDecl *const *)LSI->AutoTemplateParams.data(),
+ LSI->AutoTemplateParams.size()),
+ RAngleLoc);
}
return LSI->GLTemplateParameterList;
}
@@ -685,7 +686,8 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
QualType ReturnType =
(RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType();
- if (Context.hasSameType(ReturnType, CSI.ReturnType))
+ if (Context.getCanonicalFunctionResultType(ReturnType) ==
+ Context.getCanonicalFunctionResultType(CSI.ReturnType))
continue;
// FIXME: This is a poor diagnostic for ReturnStmts without expressions.
@@ -698,18 +700,11 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
}
}
-QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc,
- bool ByRef,
- IdentifierInfo *Id,
- Expr *&Init) {
-
- // We do not need to distinguish between direct-list-initialization
- // and copy-list-initialization here, because we will always deduce
- // std::initializer_list<T>, and direct- and copy-list-initialization
- // always behave the same for such a type.
- // FIXME: We should model whether an '=' was present.
- const bool IsDirectInit = isa<ParenListExpr>(Init) || isa<InitListExpr>(Init);
-
+QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc,
+ bool ByRef,
+ IdentifierInfo *Id,
+ bool IsDirectInit,
+ Expr *&Init) {
// Create an 'auto' or 'auto&' TypeSourceInfo that we can use to
// deduce against.
QualType DeductType = Context.getAutoDeductType();
@@ -722,50 +717,16 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc,
}
TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType);
- // Are we a non-list direct initialization?
- ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
-
- Expr *DeduceInit = Init;
- // Initializer could be a C++ direct-initializer. Deduction only works if it
- // contains exactly one expression.
- if (CXXDirectInit) {
- if (CXXDirectInit->getNumExprs() == 0) {
- Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_no_expression)
- << DeclarationName(Id) << TSI->getType() << Loc;
- return QualType();
- } else if (CXXDirectInit->getNumExprs() > 1) {
- Diag(CXXDirectInit->getExpr(1)->getLocStart(),
- diag::err_init_capture_multiple_expressions)
- << DeclarationName(Id) << TSI->getType() << Loc;
- return QualType();
- } else {
- DeduceInit = CXXDirectInit->getExpr(0);
- if (isa<InitListExpr>(DeduceInit))
- Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_paren_braces)
- << DeclarationName(Id) << Loc;
- }
- }
-
- // Now deduce against the initialization expression and store the deduced
- // type below.
- QualType DeducedType;
- if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) {
- if (isa<InitListExpr>(Init))
- Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list)
- << DeclarationName(Id)
- << (DeduceInit->getType().isNull() ? TSI->getType()
- : DeduceInit->getType())
- << DeduceInit->getSourceRange();
- else
- Diag(Loc, diag::err_init_capture_deduction_failure)
- << DeclarationName(Id) << TSI->getType()
- << (DeduceInit->getType().isNull() ? TSI->getType()
- : DeduceInit->getType())
- << DeduceInit->getSourceRange();
- }
+ // Deduce the type of the init capture.
+ QualType DeducedType = deduceVarTypeFromInitializer(
+ /*VarDecl*/nullptr, DeclarationName(Id), DeductType, TSI,
+ SourceRange(Loc, Loc), IsDirectInit, Init);
if (DeducedType.isNull())
return QualType();
+ // Are we a non-list direct initialization?
+ ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
+
// Perform initialization analysis and ensure any implicit conversions
// (such as lvalue-to-rvalue) are enforced.
InitializedEntity Entity =
@@ -802,9 +763,10 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc,
return DeducedType;
}
-VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
- QualType InitCaptureType, IdentifierInfo *Id, Expr *Init) {
-
+VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
+ QualType InitCaptureType,
+ IdentifierInfo *Id,
+ unsigned InitStyle, Expr *Init) {
TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType,
Loc);
// Create a dummy variable representing the init-capture. This is not actually
@@ -815,6 +777,8 @@ VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc,
Loc, Id, InitCaptureType, TSI, SC_Auto);
NewVD->setInitCapture(true);
NewVD->setReferenced(true);
+ // FIXME: Pass in a VarDecl::InitializationStyle.
+ NewVD->setInitStyle(static_cast<VarDecl::InitializationStyle>(InitStyle));
NewVD->markUsed(Context);
NewVD->setInit(Init);
return NewVD;
@@ -1013,8 +977,23 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// in this case.
if (C->InitCaptureType.get().isNull())
continue;
- Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(),
- C->Id, C->Init.get());
+
+ unsigned InitStyle;
+ switch (C->InitKind) {
+ case LambdaCaptureInitKind::NoInit:
+ llvm_unreachable("not an init-capture?");
+ case LambdaCaptureInitKind::CopyInit:
+ InitStyle = VarDecl::CInit;
+ break;
+ case LambdaCaptureInitKind::DirectInit:
+ InitStyle = VarDecl::CallInit;
+ break;
+ case LambdaCaptureInitKind::ListInit:
+ InitStyle = VarDecl::ListInit;
+ break;
+ }
+ Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(),
+ C->Id, InitStyle, C->Init.get());
// C++1y [expr.prim.lambda]p11:
// An init-capture behaves as if it declares and explicitly
// captures a variable [...] whose declarative region is the
@@ -1022,6 +1001,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
if (Var)
PushOnScopeChains(Var, CurScope, false);
} else {
+ assert(C->InitKind == LambdaCaptureInitKind::NoInit &&
+ "init capture has valid but null init?");
+
// C++11 [expr.prim.lambda]p8:
// If a lambda-capture includes a capture-default that is &, the
// identifiers in the lambda-capture shall not be preceded by &.
@@ -1160,6 +1142,12 @@ static void addFunctionPointerConversion(Sema &S,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
+ // This conversion is explicitly disabled if the lambda's function has
+ // pass_object_size attributes on any of its parameters.
+ if (std::any_of(CallOperator->param_begin(), CallOperator->param_end(),
+ std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>)))
+ return;
+
// Add the conversion to function pointer.
const FunctionProtoType *CallOpProto =
CallOperator->getType()->getAs<FunctionProtoType>();
@@ -1700,8 +1688,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
SC_None);
BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false,
/*Nested=*/false, /*Copy=*/Init.get());
- Block->setCaptures(Context, &Capture, &Capture + 1,
- /*CapturesCXXThis=*/false);
+ Block->setCaptures(Context, Capture, /*CapturesCXXThis=*/false);
// Add a fake function body to the block. IR generation is responsible
// for filling in the actual body, which cannot be expressed as an AST.
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index 2e7f891..45dc2e3 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -11,6 +11,7 @@
// Objective-C++.
//
//===----------------------------------------------------------------------===//
+
#include "clang/Sema/Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
@@ -153,7 +154,7 @@ namespace {
// by its using directives, transitively) as if they appeared in
// the given effective context.
void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) {
- SmallVector<DeclContext*,4> queue;
+ SmallVector<DeclContext*, 4> queue;
while (true) {
for (auto UD : DC->using_directives()) {
DeclContext *NS = UD->getNominatedNamespace();
@@ -204,7 +205,7 @@ namespace {
UnqualUsingEntry::Comparator()));
}
};
-}
+} // end anonymous namespace
// Retrieve the set of identifier namespaces that correspond to a
// specific kind of name lookup.
@@ -354,13 +355,114 @@ static DeclContext *getContextForScopeMatching(Decl *D) {
return D->getDeclContext()->getRedeclContext();
}
+/// \brief Determine whether \p D is a better lookup result than \p Existing,
+/// given that they declare the same entity.
+static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind,
+ NamedDecl *D, NamedDecl *Existing) {
+ // When looking up redeclarations of a using declaration, prefer a using
+ // shadow declaration over any other declaration of the same entity.
+ if (Kind == Sema::LookupUsingDeclName && isa<UsingShadowDecl>(D) &&
+ !isa<UsingShadowDecl>(Existing))
+ return true;
+
+ auto *DUnderlying = D->getUnderlyingDecl();
+ auto *EUnderlying = Existing->getUnderlyingDecl();
+
+ // If they have different underlying declarations, prefer a typedef over the
+ // original type (this happens when two type declarations denote the same
+ // type), per a generous reading of C++ [dcl.typedef]p3 and p4. The typedef
+ // might carry additional semantic information, such as an alignment override.
+ // However, per C++ [dcl.typedef]p5, when looking up a tag name, prefer a tag
+ // declaration over a typedef.
+ if (DUnderlying->getCanonicalDecl() != EUnderlying->getCanonicalDecl()) {
+ assert(isa<TypeDecl>(DUnderlying) && isa<TypeDecl>(EUnderlying));
+ bool HaveTag = isa<TagDecl>(EUnderlying);
+ bool WantTag = Kind == Sema::LookupTagName;
+ return HaveTag != WantTag;
+ }
+
+ // Pick the function with more default arguments.
+ // FIXME: In the presence of ambiguous default arguments, we should keep both,
+ // so we can diagnose the ambiguity if the default argument is needed.
+ // See C++ [over.match.best]p3.
+ if (auto *DFD = dyn_cast<FunctionDecl>(DUnderlying)) {
+ auto *EFD = cast<FunctionDecl>(EUnderlying);
+ unsigned DMin = DFD->getMinRequiredArguments();
+ unsigned EMin = EFD->getMinRequiredArguments();
+ // If D has more default arguments, it is preferred.
+ if (DMin != EMin)
+ return DMin < EMin;
+ // FIXME: When we track visibility for default function arguments, check
+ // that we pick the declaration with more visible default arguments.
+ }
+
+ // Pick the template with more default template arguments.
+ if (auto *DTD = dyn_cast<TemplateDecl>(DUnderlying)) {
+ auto *ETD = cast<TemplateDecl>(EUnderlying);
+ unsigned DMin = DTD->getTemplateParameters()->getMinRequiredArguments();
+ unsigned EMin = ETD->getTemplateParameters()->getMinRequiredArguments();
+ // If D has more default arguments, it is preferred. Note that default
+ // arguments (and their visibility) is monotonically increasing across the
+ // redeclaration chain, so this is a quick proxy for "is more recent".
+ if (DMin != EMin)
+ return DMin < EMin;
+ // If D has more *visible* default arguments, it is preferred. Note, an
+ // earlier default argument being visible does not imply that a later
+ // default argument is visible, so we can't just check the first one.
+ for (unsigned I = DMin, N = DTD->getTemplateParameters()->size();
+ I != N; ++I) {
+ if (!S.hasVisibleDefaultArgument(
+ ETD->getTemplateParameters()->getParam(I)) &&
+ S.hasVisibleDefaultArgument(
+ DTD->getTemplateParameters()->getParam(I)))
+ return true;
+ }
+ }
+
+ // For most kinds of declaration, it doesn't really matter which one we pick.
+ if (!isa<FunctionDecl>(DUnderlying) && !isa<VarDecl>(DUnderlying)) {
+ // If the existing declaration is hidden, prefer the new one. Otherwise,
+ // keep what we've got.
+ return !S.isVisible(Existing);
+ }
+
+ // Pick the newer declaration; it might have a more precise type.
+ for (Decl *Prev = DUnderlying->getPreviousDecl(); Prev;
+ Prev = Prev->getPreviousDecl())
+ if (Prev == EUnderlying)
+ return true;
+ return false;
+
+ // If the existing declaration is hidden, prefer the new one. Otherwise,
+ // keep what we've got.
+ return !S.isVisible(Existing);
+}
+
+/// Determine whether \p D can hide a tag declaration.
+static bool canHideTag(NamedDecl *D) {
+ // C++ [basic.scope.declarative]p4:
+ // Given a set of declarations in a single declarative region [...]
+ // exactly one declaration shall declare a class name or enumeration name
+ // that is not a typedef name and the other declarations shall all refer to
+ // the same variable or enumerator, or all refer to functions and function
+ // templates; in this case the class name or enumeration name is hidden.
+ // C++ [basic.scope.hiding]p2:
+ // A class name or enumeration name can be hidden by the name of a
+ // variable, data member, function, or enumerator declared in the same
+ // scope.
+ D = D->getUnderlyingDecl();
+ return isa<VarDecl>(D) || isa<EnumConstantDecl>(D) || isa<FunctionDecl>(D) ||
+ isa<FunctionTemplateDecl>(D) || isa<FieldDecl>(D);
+}
+
/// Resolves the result kind of this lookup.
void LookupResult::resolveKind() {
unsigned N = Decls.size();
// Fast case: no possible ambiguity.
if (N == 0) {
- assert(ResultKind == NotFound || ResultKind == NotFoundInCurrentInstantiation);
+ assert(ResultKind == NotFound ||
+ ResultKind == NotFoundInCurrentInstantiation);
return;
}
@@ -378,12 +480,15 @@ void LookupResult::resolveKind() {
// Don't do any extra resolution if we've already resolved as ambiguous.
if (ResultKind == Ambiguous) return;
- llvm::SmallPtrSet<NamedDecl*, 16> Unique;
- llvm::SmallPtrSet<QualType, 16> UniqueTypes;
+ llvm::SmallDenseMap<NamedDecl*, unsigned, 16> Unique;
+ llvm::SmallDenseMap<QualType, unsigned, 16> UniqueTypes;
bool Ambiguous = false;
- bool HasTag = false, HasFunction = false, HasNonFunction = false;
+ bool HasTag = false, HasFunction = false;
bool HasFunctionTemplate = false, HasUnresolved = false;
+ NamedDecl *HasNonFunction = nullptr;
+
+ llvm::SmallVector<NamedDecl*, 4> EquivalentNonFunctions;
unsigned UniqueTagIndex = 0;
@@ -393,34 +498,43 @@ void LookupResult::resolveKind() {
D = cast<NamedDecl>(D->getCanonicalDecl());
// Ignore an invalid declaration unless it's the only one left.
- if (D->isInvalidDecl() && I < N-1) {
+ if (D->isInvalidDecl() && !(I == 0 && N == 1)) {
Decls[I] = Decls[--N];
continue;
}
+ llvm::Optional<unsigned> ExistingI;
+
// Redeclarations of types via typedef can occur both within a scope
// and, through using declarations and directives, across scopes. There is
// no ambiguity if they all refer to the same type, so unique based on the
// canonical type.
if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
- if (!TD->getDeclContext()->isRecord()) {
- QualType T = getSema().Context.getTypeDeclType(TD);
- if (!UniqueTypes.insert(getSema().Context.getCanonicalType(T)).second) {
- // The type is not unique; pull something off the back and continue
- // at this index.
- Decls[I] = Decls[--N];
- continue;
- }
+ QualType T = getSema().Context.getTypeDeclType(TD);
+ auto UniqueResult = UniqueTypes.insert(
+ std::make_pair(getSema().Context.getCanonicalType(T), I));
+ if (!UniqueResult.second) {
+ // The type is not unique.
+ ExistingI = UniqueResult.first->second;
}
}
- if (!Unique.insert(D).second) {
- // If it's not unique, pull something off the back (and
- // continue at this index).
- // FIXME: This is wrong. We need to take the more recent declaration in
- // order to get the right type, default arguments, etc. We also need to
- // prefer visible declarations to hidden ones (for redeclaration lookup
- // in modules builds).
+ // For non-type declarations, check for a prior lookup result naming this
+ // canonical declaration.
+ if (!ExistingI) {
+ auto UniqueResult = Unique.insert(std::make_pair(D, I));
+ if (!UniqueResult.second) {
+ // We've seen this entity before.
+ ExistingI = UniqueResult.first->second;
+ }
+ }
+
+ if (ExistingI) {
+ // This is not a unique lookup result. Pick one of the results and
+ // discard the other.
+ if (isPreferredLookupResult(getSema(), getLookupKind(), Decls[I],
+ Decls[*ExistingI]))
+ Decls[*ExistingI] = Decls[I];
Decls[I] = Decls[--N];
continue;
}
@@ -440,9 +554,21 @@ void LookupResult::resolveKind() {
} else if (isa<FunctionDecl>(D)) {
HasFunction = true;
} else {
- if (HasNonFunction)
+ if (HasNonFunction) {
+ // If we're about to create an ambiguity between two declarations that
+ // are equivalent, but one is an internal linkage declaration from one
+ // module and the other is an internal linkage declaration from another
+ // module, just skip it.
+ if (getSema().isEquivalentInternalLinkageDeclaration(HasNonFunction,
+ D)) {
+ EquivalentNonFunctions.push_back(D);
+ Decls[I] = Decls[--N];
+ continue;
+ }
+
Ambiguous = true;
- HasNonFunction = true;
+ }
+ HasNonFunction = D;
}
I++;
}
@@ -456,15 +582,24 @@ void LookupResult::resolveKind() {
// wherever the object, function, or enumerator name is visible.
// But it's still an error if there are distinct tag types found,
// even if they're not visible. (ref?)
- if (HideTags && HasTag && !Ambiguous &&
+ if (N > 1 && HideTags && HasTag && !Ambiguous &&
(HasFunction || HasNonFunction || HasUnresolved)) {
- if (getContextForScopeMatching(Decls[UniqueTagIndex])->Equals(
- getContextForScopeMatching(Decls[UniqueTagIndex ? 0 : N - 1])))
+ NamedDecl *OtherDecl = Decls[UniqueTagIndex ? 0 : N - 1];
+ if (isa<TagDecl>(Decls[UniqueTagIndex]->getUnderlyingDecl()) &&
+ getContextForScopeMatching(Decls[UniqueTagIndex])->Equals(
+ getContextForScopeMatching(OtherDecl)) &&
+ canHideTag(OtherDecl))
Decls[UniqueTagIndex] = Decls[--N];
else
Ambiguous = true;
}
+ // FIXME: This diagnostic should really be delayed until we're done with
+ // the lookup result, in case the ambiguity is resolved by the caller.
+ if (!EquivalentNonFunctions.empty() && !Ambiguous)
+ getSema().diagnoseEquivalentInternalLinkageDeclarations(
+ getNameLoc(), HasNonFunction, EquivalentNonFunctions);
+
Decls.set_size(N);
if (HasNonFunction && (HasFunction || HasUnresolved))
@@ -515,6 +650,13 @@ void LookupResult::print(raw_ostream &Out) {
}
}
+LLVM_DUMP_METHOD void LookupResult::dump() {
+ llvm::errs() << "lookup results for " << getLookupName().getAsString()
+ << ":\n";
+ for (NamedDecl *D : *this)
+ D->dump();
+}
+
/// \brief Lookup a builtin function, when name lookup would otherwise
/// fail.
static bool LookupBuiltin(Sema &S, LookupResult &R) {
@@ -534,6 +676,11 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
R.addDecl(S.getASTContext().getFloat128StubType());
return true;
}
+ if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName &&
+ II == S.getASTContext().getMakeIntegerSeqName()) {
+ R.addDecl(S.getASTContext().getMakeIntegerSeqDecl());
+ return true;
+ }
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID()) {
@@ -875,7 +1022,7 @@ struct FindLocalExternScope {
LookupResult &R;
bool OldFindLocalExtern;
};
-}
+} // end anonymous namespace
bool Sema::CppLookupName(LookupResult &R, Scope *S) {
assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup");
@@ -1333,22 +1480,22 @@ bool Sema::hasVisibleDefaultArgument(const NamedDecl *D,
/// your module can see, including those later on in your module).
bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
assert(D->isHidden() && "should not call this: not in slow case");
- Module *DeclModule = SemaRef.getOwningModule(D);
- if (!DeclModule) {
- // getOwningModule() may have decided the declaration should not be hidden.
- assert(!D->isHidden() && "hidden decl not from a module");
- return true;
- }
-
- // If the owning module is visible, and the decl is not module private,
- // then the decl is visible too. (Module private is ignored within the same
- // top-level module.)
- if (!D->isFromASTFile() || !D->isModulePrivate()) {
- if (SemaRef.isModuleVisible(DeclModule))
+ Module *DeclModule = nullptr;
+
+ if (SemaRef.getLangOpts().ModulesLocalVisibility) {
+ DeclModule = SemaRef.getOwningModule(D);
+ if (!DeclModule) {
+ // getOwningModule() may have decided the declaration should not be hidden.
+ assert(!D->isHidden() && "hidden decl not from a module");
return true;
- // Also check merged definitions.
- if (SemaRef.getLangOpts().ModulesLocalVisibility &&
- SemaRef.hasVisibleMergedDefinition(D))
+ }
+
+ // If the owning module is visible, and the decl is not module private,
+ // then the decl is visible too. (Module private is ignored within the same
+ // top-level module.)
+ if ((!D->isFromASTFile() || !D->isModulePrivate()) &&
+ (SemaRef.isModuleVisible(DeclModule) ||
+ SemaRef.hasVisibleMergedDefinition(D)))
return true;
}
@@ -1380,6 +1527,11 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
if (LookupModules.empty())
return false;
+ if (!DeclModule) {
+ DeclModule = SemaRef.getOwningModule(D);
+ assert(DeclModule && "hidden decl not from a module");
+ }
+
// If our lookup set contains the decl's module, it's visible.
if (LookupModules.count(DeclModule))
return true;
@@ -1390,18 +1542,22 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
// Check whether DeclModule is transitively exported to an import of
// the lookup set.
- for (llvm::DenseSet<Module *>::iterator I = LookupModules.begin(),
- E = LookupModules.end();
- I != E; ++I)
- if ((*I)->isModuleVisible(DeclModule))
- return true;
- return false;
+ return std::any_of(LookupModules.begin(), LookupModules.end(),
+ [&](Module *M) { return M->isModuleVisible(DeclModule); });
}
bool Sema::isVisibleSlow(const NamedDecl *D) {
return LookupResult::isVisible(*this, const_cast<NamedDecl*>(D));
}
+bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
+ for (auto *D : R) {
+ if (isVisible(D))
+ return true;
+ }
+ return New->isExternallyVisible();
+}
+
/// \brief Retrieve the visible declaration corresponding to D, if any.
///
/// This routine determines whether the declaration D is visible in the current
@@ -1679,12 +1835,10 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
/// \brief Callback that looks for any member of a class with the given name.
static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *Name) {
+ CXXBasePath &Path, DeclarationName Name) {
RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
- DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
- Path.Decls = BaseRecord->lookup(N);
+ Path.Decls = BaseRecord->lookup(Name);
return !Path.Decls.empty();
}
@@ -1756,7 +1910,18 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
cast<TagDecl>(LookupCtx)->isBeingDefined()) &&
"Declaration context must already be complete!");
- // Perform qualified name lookup into the LookupCtx.
+ struct QualifiedLookupInScope {
+ bool oldVal;
+ DeclContext *Context;
+ // Set flag in DeclContext informing debugger that we're looking for qualified name
+ QualifiedLookupInScope(DeclContext *ctx) : Context(ctx) {
+ oldVal = ctx->setUseQualifiedLookup();
+ }
+ ~QualifiedLookupInScope() {
+ Context->setUseQualifiedLookup(oldVal);
+ }
+ } QL(LookupCtx);
+
if (LookupDirect(*this, R, LookupCtx)) {
R.resolveKind();
if (isa<CXXRecordDecl>(LookupCtx))
@@ -1802,7 +1967,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
Paths.setOrigin(LookupRec);
// Look for this member in our base classes
- CXXRecordDecl::BaseMatchesCallback *BaseCallback = nullptr;
+ bool (*BaseCallback)(const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
+ DeclarationName Name) = nullptr;
switch (R.getLookupKind()) {
case LookupObjCImplicitSelfParam:
case LookupOrdinaryName:
@@ -1835,8 +2001,12 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
break;
}
- if (!LookupRec->lookupInBases(BaseCallback,
- R.getLookupName().getAsOpaquePtr(), Paths))
+ DeclarationName Name = R.getLookupName();
+ if (!LookupRec->lookupInBases(
+ [=](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ return BaseCallback(Specifier, Path, Name);
+ },
+ Paths))
return false;
R.setNamingClass(LookupRec);
@@ -2013,17 +2183,30 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
///
/// @returns True if any decls were found (but possibly ambiguous)
bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) {
+ // The access-control rules we use here are essentially the rules for
+ // doing a lookup in Class that just magically skipped the direct
+ // members of Class itself. That is, the naming class is Class, and the
+ // access includes the access of the base.
for (const auto &BaseSpec : Class->bases()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(
BaseSpec.getType()->castAs<RecordType>()->getDecl());
LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind());
Result.setBaseObjectType(Context.getRecordType(Class));
LookupQualifiedName(Result, RD);
- for (auto *Decl : Result)
- R.addDecl(Decl);
+
+ // Copy the lookup results into the target, merging the base's access into
+ // the path access.
+ for (auto I = Result.begin(), E = Result.end(); I != E; ++I) {
+ R.addDecl(I.getDecl(),
+ CXXRecordDecl::MergeAccess(BaseSpec.getAccessSpecifier(),
+ I.getAccess()));
+ }
+
+ Result.suppressDiagnostics();
}
R.resolveKind();
+ R.setNamingClass(Class);
return !R.empty();
}
@@ -2075,7 +2258,7 @@ void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
case LookupResult::AmbiguousTagHiding: {
Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange;
- llvm::SmallPtrSet<NamedDecl*,8> TagDecls;
+ llvm::SmallPtrSet<NamedDecl*, 8> TagDecls;
for (auto *D : Result)
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
@@ -2121,7 +2304,7 @@ namespace {
Sema::AssociatedClassSet &Classes;
SourceLocation InstantiationLoc;
};
-}
+} // end anonymous namespace
static void
addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T);
@@ -2252,7 +2435,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
}
// Only recurse into base classes for complete types.
- if (!Class->hasDefinition())
+ if (!Result.S.isCompleteType(Result.InstantiationLoc,
+ Result.S.Context.getRecordType(Class)))
return;
// Add direct and indirect base classes along with their associated
@@ -2345,10 +2529,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
// classes. Its associated namespaces are the namespaces in
// which its associated classes are defined.
case Type::Record: {
- Result.S.RequireCompleteType(Result.InstantiationLoc, QualType(T, 0),
- /*no diagnostic*/ 0);
- CXXRecordDecl *Class
- = cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
+ CXXRecordDecl *Class =
+ cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
addAssociatedClassesAndNamespaces(Result, Class);
break;
}
@@ -2441,6 +2623,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
case Type::Atomic:
T = cast<AtomicType>(T)->getValueType().getTypePtr();
continue;
+ case Type::Pipe:
+ T = cast<PipeType>(T)->getElementType().getTypePtr();
+ continue;
}
if (Queue.empty())
@@ -3032,7 +3217,8 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
for (Decl *DI = D; DI; DI = DI->getPreviousDecl()) {
DeclContext *LexDC = DI->getLexicalDeclContext();
if (isa<CXXRecordDecl>(LexDC) &&
- AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) {
+ AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)) &&
+ isVisible(cast<NamedDecl>(DI))) {
DeclaredInAssociatedClass = true;
break;
}
@@ -3129,9 +3315,6 @@ public:
} // end anonymous namespace
NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
- // Look through using declarations.
- ND = ND->getUnderlyingDecl();
-
unsigned IDNS = ND->getIdentifierNamespace();
std::list<ShadowMap>::reverse_iterator SM = ShadowMaps.rbegin();
for (std::list<ShadowMap>::reverse_iterator SMEnd = ShadowMaps.rend();
@@ -3704,7 +3887,12 @@ void TypoCorrectionConsumer::addNamespaces(
if (const Type *T = NNS->getAsType())
SSIsTemplate = T->getTypeClass() == Type::TemplateSpecialization;
}
- for (const auto *TI : SemaRef.getASTContext().types()) {
+ // Do not transform this into an iterator-based loop. The loop body can
+ // trigger the creation of further types (through lazy deserialization) and
+ // invalide iterators into this list.
+ auto &Types = SemaRef.getASTContext().getTypes();
+ for (unsigned I = 0; I != Types.size(); ++I) {
+ const auto *TI = Types[I];
if (CXXRecordDecl *CD = TI->getAsCXXRecordDecl()) {
CD = CD->getCanonicalDecl();
if (!CD->isDependentType() && !CD->isAnonymousStructOrUnion() &&
@@ -3805,7 +3993,8 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
// current correction candidate is the name of that class, then skip
// it as it is unlikely a qualified version of the class' constructor
// is an appropriate correction.
- if (CXXRecordDecl *NSDecl = NSType ? NSType->getAsCXXRecordDecl() : 0) {
+ if (CXXRecordDecl *NSDecl = NSType ? NSType->getAsCXXRecordDecl() :
+ nullptr) {
if (NSDecl->getIdentifier() == QR.getCorrectionAsIdentifierInfo())
continue;
}
@@ -4540,7 +4729,7 @@ void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
if (isKeyword())
CorrectionDecls.clear();
- CorrectionDecls.push_back(CDecl->getUnderlyingDecl());
+ CorrectionDecls.push_back(CDecl);
if (!CorrectionName)
CorrectionName = CDecl->getDeclName();
@@ -4769,7 +4958,7 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
// Maybe we're just missing a module import.
if (Correction.requiresImport()) {
- NamedDecl *Decl = Correction.getCorrectionDecl();
+ NamedDecl *Decl = Correction.getFoundDecl();
assert(Decl && "import required but no declaration to import");
diagnoseMissingImport(Correction.getCorrectionRange().getBegin(), Decl,
@@ -4781,7 +4970,7 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
<< CorrectedQuotedStr << (ErrorRecovery ? FixTypo : FixItHint());
NamedDecl *ChosenDecl =
- Correction.isKeyword() ? nullptr : Correction.getCorrectionDecl();
+ Correction.isKeyword() ? nullptr : Correction.getFoundDecl();
if (PrevNote.getDiagID() && ChosenDecl)
Diag(ChosenDecl->getLocation(), PrevNote)
<< CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo);
@@ -4809,3 +4998,12 @@ const Sema::TypoExprState &Sema::getTypoExprState(TypoExpr *TE) const {
void Sema::clearDelayedTypo(TypoExpr *TE) {
DelayedTypos.erase(TE);
}
+
+void Sema::ActOnPragmaDump(Scope *S, SourceLocation IILoc, IdentifierInfo *II) {
+ DeclarationNameInfo Name(II, IILoc);
+ LookupResult R(*this, Name, LookupAnyName, Sema::NotForRedeclaration);
+ R.suppressDiagnostics();
+ R.setHideTags(false);
+ LookupName(R, S);
+ R.dump();
+}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
index f139c83..1cb84e4 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp
@@ -61,8 +61,10 @@ static Qualifiers::ObjCLifetime getImpliedARCOwnership(
return Qualifiers::OCL_None;
}
-/// Check the internal consistency of a property declaration.
-static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) {
+/// Check the internal consistency of a property declaration with
+/// an explicit ownership qualifier.
+static void checkPropertyDeclWithOwnership(Sema &S,
+ ObjCPropertyDecl *property) {
if (property->isInvalidDecl()) return;
ObjCPropertyDecl::PropertyAttributeKind propertyKind
@@ -70,8 +72,7 @@ static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) {
Qualifiers::ObjCLifetime propertyLifetime
= property->getType().getObjCLifetime();
- // Nothing to do if we don't have a lifetime.
- if (propertyLifetime == Qualifiers::OCL_None) return;
+ assert(propertyLifetime != Qualifiers::OCL_None);
Qualifiers::ObjCLifetime expectedLifetime
= getImpliedARCOwnership(propertyKind, property->getType());
@@ -127,32 +128,71 @@ CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
CheckPropertyAgainstProtocol(S, Prop, P, Known);
}
+static unsigned deducePropertyOwnershipFromType(Sema &S, QualType T) {
+ // In GC mode, just look for the __weak qualifier.
+ if (S.getLangOpts().getGC() != LangOptions::NonGC) {
+ if (T.isObjCGCWeak()) return ObjCDeclSpec::DQ_PR_weak;
+
+ // In ARC/MRC, look for an explicit ownership qualifier.
+ // For some reason, this only applies to __weak.
+ } else if (auto ownership = T.getObjCLifetime()) {
+ switch (ownership) {
+ case Qualifiers::OCL_Weak:
+ return ObjCDeclSpec::DQ_PR_weak;
+ case Qualifiers::OCL_Strong:
+ return ObjCDeclSpec::DQ_PR_strong;
+ case Qualifiers::OCL_ExplicitNone:
+ return ObjCDeclSpec::DQ_PR_unsafe_unretained;
+ case Qualifiers::OCL_Autoreleasing:
+ case Qualifiers::OCL_None:
+ return 0;
+ }
+ llvm_unreachable("bad qualifier");
+ }
+
+ return 0;
+}
+
+static const unsigned OwnershipMask =
+ (ObjCPropertyDecl::OBJC_PR_assign |
+ ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_copy |
+ ObjCPropertyDecl::OBJC_PR_weak |
+ ObjCPropertyDecl::OBJC_PR_strong |
+ ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
+
+static unsigned getOwnershipRule(unsigned attr) {
+ unsigned result = attr & OwnershipMask;
+
+ // From an ownership perspective, assign and unsafe_unretained are
+ // identical; make sure one also implies the other.
+ if (result & (ObjCPropertyDecl::OBJC_PR_assign |
+ ObjCPropertyDecl::OBJC_PR_unsafe_unretained)) {
+ result |= ObjCPropertyDecl::OBJC_PR_assign |
+ ObjCPropertyDecl::OBJC_PR_unsafe_unretained;
+ }
+
+ return result;
+}
+
Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
SourceLocation LParenLoc,
FieldDeclarator &FD,
ObjCDeclSpec &ODS,
Selector GetterSel,
Selector SetterSel,
- bool *isOverridingProperty,
tok::ObjCKeywordKind MethodImplKind,
DeclContext *lexicalDC) {
unsigned Attributes = ODS.getPropertyAttributes();
FD.D.setObjCWeakProperty((Attributes & ObjCDeclSpec::DQ_PR_weak) != 0);
TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
QualType T = TSI->getType();
- Attributes |= deduceWeakPropertyFromType(T);
+ if (!getOwnershipRule(Attributes)) {
+ Attributes |= deducePropertyOwnershipFromType(*this, T);
+ }
bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
// default is readwrite!
!(Attributes & ObjCDeclSpec::DQ_PR_readonly));
- // property is defaulted to 'assign' if it is readwrite and is
- // not retain or copy
- bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
- (isReadWrite &&
- !(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
- !(Attributes & ObjCDeclSpec::DQ_PR_strong) &&
- !(Attributes & ObjCDeclSpec::DQ_PR_copy) &&
- !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) &&
- !(Attributes & ObjCDeclSpec::DQ_PR_weak)));
// Proceed with constructing the ObjCPropertyDecls.
ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
@@ -161,11 +201,10 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
if (CDecl->IsClassExtension()) {
Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
FD, GetterSel, SetterSel,
- isAssign, isReadWrite,
+ isReadWrite,
Attributes,
ODS.getPropertyAttributes(),
- isOverridingProperty, T, TSI,
- MethodImplKind);
+ T, TSI, MethodImplKind);
if (!Res)
return nullptr;
}
@@ -173,7 +212,7 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
if (!Res) {
Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,
- GetterSel, SetterSel, isAssign, isReadWrite,
+ GetterSel, SetterSel, isReadWrite,
Attributes, ODS.getPropertyAttributes(),
T, TSI, MethodImplKind);
if (lexicalDC)
@@ -181,12 +220,13 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
}
// Validate the attributes on the @property.
- CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
+ CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
(isa<ObjCInterfaceDecl>(ClassDecl) ||
isa<ObjCProtocolDecl>(ClassDecl)));
- if (getLangOpts().ObjCAutoRefCount)
- checkARCPropertyDecl(*this, Res);
+ // Check consistency if the type has explicit ownership qualification.
+ if (Res->getType().getObjCLifetime())
+ checkPropertyDeclWithOwnership(*this, Res);
llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos;
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
@@ -220,8 +260,12 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
}
}
} else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
- for (auto *P : Cat->protocols())
- CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
+ // We don't check if class extension. Because properties in class extension
+ // are meant to override some of the attributes and checking has already done
+ // when property in class extension is constructed.
+ if (!Cat->IsClassExtension())
+ for (auto *P : Cat->protocols())
+ CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
} else {
ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);
for (auto *P : Proto->protocols())
@@ -293,13 +337,73 @@ static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
}
-static unsigned getOwnershipRule(unsigned attr) {
- return attr & (ObjCPropertyDecl::OBJC_PR_assign |
- ObjCPropertyDecl::OBJC_PR_retain |
- ObjCPropertyDecl::OBJC_PR_copy |
- ObjCPropertyDecl::OBJC_PR_weak |
- ObjCPropertyDecl::OBJC_PR_strong |
- ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
+/// Check for a mismatch in the atomicity of the given properties.
+static void checkAtomicPropertyMismatch(Sema &S,
+ ObjCPropertyDecl *OldProperty,
+ ObjCPropertyDecl *NewProperty,
+ bool PropagateAtomicity) {
+ // If the atomicity of both matches, we're done.
+ bool OldIsAtomic =
+ (OldProperty->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic)
+ == 0;
+ bool NewIsAtomic =
+ (NewProperty->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic)
+ == 0;
+ if (OldIsAtomic == NewIsAtomic) return;
+
+ // Determine whether the given property is readonly and implicitly
+ // atomic.
+ auto isImplicitlyReadonlyAtomic = [](ObjCPropertyDecl *Property) -> bool {
+ // Is it readonly?
+ auto Attrs = Property->getPropertyAttributes();
+ if ((Attrs & ObjCPropertyDecl::OBJC_PR_readonly) == 0) return false;
+
+ // Is it nonatomic?
+ if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic) return false;
+
+ // Was 'atomic' specified directly?
+ if (Property->getPropertyAttributesAsWritten() &
+ ObjCPropertyDecl::OBJC_PR_atomic)
+ return false;
+
+ return true;
+ };
+
+ // If we're allowed to propagate atomicity, and the new property did
+ // not specify atomicity at all, propagate.
+ const unsigned AtomicityMask =
+ (ObjCPropertyDecl::OBJC_PR_atomic | ObjCPropertyDecl::OBJC_PR_nonatomic);
+ if (PropagateAtomicity &&
+ ((NewProperty->getPropertyAttributesAsWritten() & AtomicityMask) == 0)) {
+ unsigned Attrs = NewProperty->getPropertyAttributes();
+ Attrs = Attrs & ~AtomicityMask;
+ if (OldIsAtomic)
+ Attrs |= ObjCPropertyDecl::OBJC_PR_atomic;
+ else
+ Attrs |= ObjCPropertyDecl::OBJC_PR_nonatomic;
+
+ NewProperty->overwritePropertyAttributes(Attrs);
+ return;
+ }
+
+ // One of the properties is atomic; if it's a readonly property, and
+ // 'atomic' wasn't explicitly specified, we're okay.
+ if ((OldIsAtomic && isImplicitlyReadonlyAtomic(OldProperty)) ||
+ (NewIsAtomic && isImplicitlyReadonlyAtomic(NewProperty)))
+ return;
+
+ // Diagnose the conflict.
+ const IdentifierInfo *OldContextName;
+ auto *OldDC = OldProperty->getDeclContext();
+ if (auto Category = dyn_cast<ObjCCategoryDecl>(OldDC))
+ OldContextName = Category->getClassInterface()->getIdentifier();
+ else
+ OldContextName = cast<ObjCContainerDecl>(OldDC)->getIdentifier();
+
+ S.Diag(NewProperty->getLocation(), diag::warn_property_attribute)
+ << NewProperty->getDeclName() << "atomic"
+ << OldContextName;
+ S.Diag(OldProperty->getLocation(), diag::note_property_declare);
}
ObjCPropertyDecl *
@@ -308,11 +412,9 @@ Sema::HandlePropertyInClassExtension(Scope *S,
SourceLocation LParenLoc,
FieldDeclarator &FD,
Selector GetterSel, Selector SetterSel,
- const bool isAssign,
const bool isReadWrite,
- const unsigned Attributes,
+ unsigned &Attributes,
const unsigned AttributesAsWritten,
- bool *isOverridingProperty,
QualType T,
TypeSourceInfo *TSI,
tok::ObjCKeywordKind MethodImplKind) {
@@ -322,80 +424,102 @@ Sema::HandlePropertyInClassExtension(Scope *S,
IdentifierInfo *PropertyId = FD.D.getIdentifier();
ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
- if (CCPrimary) {
- // Check for duplicate declaration of this property in current and
- // other class extensions.
- for (const auto *Ext : CCPrimary->known_extensions()) {
- if (ObjCPropertyDecl *prevDecl
- = ObjCPropertyDecl::findPropertyDecl(Ext, PropertyId)) {
- Diag(AtLoc, diag::err_duplicate_property);
- Diag(prevDecl->getLocation(), diag::note_property_declare);
- return nullptr;
- }
- }
- }
-
- // Create a new ObjCPropertyDecl with the DeclContext being
- // the class extension.
- // FIXME. We should really be using CreatePropertyDecl for this.
- ObjCPropertyDecl *PDecl =
- ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),
- PropertyId, AtLoc, LParenLoc, T, TSI);
- PDecl->setPropertyAttributesAsWritten(
- makePropertyAttributesAsWritten(AttributesAsWritten));
- if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
- if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
- if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
- if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
- if (Attributes & ObjCDeclSpec::DQ_PR_nullability)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);
- if (Attributes & ObjCDeclSpec::DQ_PR_null_resettable)
- PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_null_resettable);
-
- // Set setter/getter selector name. Needed later.
- PDecl->setGetterName(GetterSel);
- PDecl->setSetterName(SetterSel);
- ProcessDeclAttributes(S, PDecl, FD.D);
- DC->addDecl(PDecl);
-
// We need to look in the @interface to see if the @property was
// already declared.
if (!CCPrimary) {
Diag(CDecl->getLocation(), diag::err_continuation_class);
- *isOverridingProperty = true;
return nullptr;
}
- // Find the property in continuation class's primary class only.
+ // Find the property in the extended class's primary class or
+ // extensions.
ObjCPropertyDecl *PIDecl =
CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId);
+ // If we found a property in an extension, complain.
+ if (PIDecl && isa<ObjCCategoryDecl>(PIDecl->getDeclContext())) {
+ Diag(AtLoc, diag::err_duplicate_property);
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ return nullptr;
+ }
+
+ // Check for consistency with the previous declaration, if there is one.
+ if (PIDecl) {
+ // A readonly property declared in the primary class can be refined
+ // by adding a readwrite property within an extension.
+ // Anything else is an error.
+ if (!(PIDecl->isReadOnly() && isReadWrite)) {
+ // Tailor the diagnostics for the common case where a readwrite
+ // property is declared both in the @interface and the continuation.
+ // This is a common error where the user often intended the original
+ // declaration to be readonly.
+ unsigned diag =
+ (Attributes & ObjCDeclSpec::DQ_PR_readwrite) &&
+ (PIDecl->getPropertyAttributesAsWritten() &
+ ObjCPropertyDecl::OBJC_PR_readwrite)
+ ? diag::err_use_continuation_class_redeclaration_readwrite
+ : diag::err_use_continuation_class;
+ Diag(AtLoc, diag)
+ << CCPrimary->getDeclName();
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ return nullptr;
+ }
+
+ // Check for consistency of getters.
+ if (PIDecl->getGetterName() != GetterSel) {
+ // If the getter was written explicitly, complain.
+ if (AttributesAsWritten & ObjCDeclSpec::DQ_PR_getter) {
+ Diag(AtLoc, diag::warn_property_redecl_getter_mismatch)
+ << PIDecl->getGetterName() << GetterSel;
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
+
+ // Always adopt the getter from the original declaration.
+ GetterSel = PIDecl->getGetterName();
+ Attributes |= ObjCDeclSpec::DQ_PR_getter;
+ }
+
+ // Check consistency of ownership.
+ unsigned ExistingOwnership
+ = getOwnershipRule(PIDecl->getPropertyAttributes());
+ unsigned NewOwnership = getOwnershipRule(Attributes);
+ if (ExistingOwnership && NewOwnership != ExistingOwnership) {
+ // If the ownership was written explicitly, complain.
+ if (getOwnershipRule(AttributesAsWritten)) {
+ Diag(AtLoc, diag::warn_property_attr_mismatch);
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
+
+ // Take the ownership from the original property.
+ Attributes = (Attributes & ~OwnershipMask) | ExistingOwnership;
+ }
+
+ // If the redeclaration is 'weak' but the original property is not,
+ if ((Attributes & ObjCPropertyDecl::OBJC_PR_weak) &&
+ !(PIDecl->getPropertyAttributesAsWritten()
+ & ObjCPropertyDecl::OBJC_PR_weak) &&
+ PIDecl->getType()->getAs<ObjCObjectPointerType>() &&
+ PIDecl->getType().getObjCLifetime() == Qualifiers::OCL_None) {
+ Diag(AtLoc, diag::warn_property_implicitly_mismatched);
+ Diag(PIDecl->getLocation(), diag::note_property_declare);
+ }
+ }
+
+ // Create a new ObjCPropertyDecl with the DeclContext being
+ // the class extension.
+ ObjCPropertyDecl *PDecl = CreatePropertyDecl(S, CDecl, AtLoc, LParenLoc,
+ FD, GetterSel, SetterSel,
+ isReadWrite,
+ Attributes, AttributesAsWritten,
+ T, TSI, MethodImplKind, DC);
+
+ // If there was no declaration of a property with the same name in
+ // the primary class, we're done.
if (!PIDecl) {
- // No matching property found in the primary class. Just fall thru
- // and add property to continuation class's primary class.
- ObjCPropertyDecl *PrimaryPDecl =
- CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc,
- FD, GetterSel, SetterSel, isAssign, isReadWrite,
- Attributes,AttributesAsWritten, T, TSI, MethodImplKind,
- DC);
-
- // A case of continuation class adding a new property in the class. This
- // is not what it was meant for. However, gcc supports it and so should we.
- // Make sure setter/getters are declared here.
- ProcessPropertyDecl(PrimaryPDecl, CCPrimary,
- /* redeclaredProperty = */ nullptr,
- /* lexicalDC = */ CDecl);
- PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl());
- PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl());
- if (ASTMutationListener *L = Context.getASTMutationListener())
- L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/nullptr,
- CDecl);
- return PrimaryPDecl;
+ ProcessPropertyDecl(PDecl);
+ return PDecl;
}
+
if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {
bool IncompatibleObjC = false;
QualType ConvertedType;
@@ -418,103 +542,13 @@ Sema::HandlePropertyInClassExtension(Scope *S,
return nullptr;
}
}
-
- // The property 'PIDecl's readonly attribute will be over-ridden
- // with continuation class's readwrite property attribute!
- unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
- if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
- PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly;
- PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite;
- PIkind |= deduceWeakPropertyFromType(PIDecl->getType());
- unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes);
- unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind);
- if (PrimaryClassMemoryModel && ClassExtensionMemoryModel &&
- (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) {
- Diag(AtLoc, diag::warn_property_attr_mismatch);
- Diag(PIDecl->getLocation(), diag::note_property_declare);
- }
- else if (getLangOpts().ObjCAutoRefCount) {
- QualType PrimaryPropertyQT =
- Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType();
- if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) {
- bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0);
- Qualifiers::ObjCLifetime PrimaryPropertyLifeTime =
- PrimaryPropertyQT.getObjCLifetime();
- if (PrimaryPropertyLifeTime == Qualifiers::OCL_None &&
- (Attributes & ObjCDeclSpec::DQ_PR_weak) &&
- !PropertyIsWeak) {
- Diag(AtLoc, diag::warn_property_implicitly_mismatched);
- Diag(PIDecl->getLocation(), diag::note_property_declare);
- }
- }
- }
-
- DeclContext *DC = cast<DeclContext>(CCPrimary);
- if (!ObjCPropertyDecl::findPropertyDecl(DC,
- PIDecl->getDeclName().getAsIdentifierInfo())) {
- // In mrr mode, 'readwrite' property must have an explicit
- // memory attribute. If none specified, select the default (assign).
- if (!getLangOpts().ObjCAutoRefCount) {
- if (!(PIkind & (ObjCDeclSpec::DQ_PR_assign |
- ObjCDeclSpec::DQ_PR_retain |
- ObjCDeclSpec::DQ_PR_strong |
- ObjCDeclSpec::DQ_PR_copy |
- ObjCDeclSpec::DQ_PR_unsafe_unretained |
- ObjCDeclSpec::DQ_PR_weak)))
- PIkind |= ObjCPropertyDecl::OBJC_PR_assign;
- }
-
- // Protocol is not in the primary class. Must build one for it.
- ObjCDeclSpec ProtocolPropertyODS;
- // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind
- // and ObjCPropertyDecl::PropertyAttributeKind have identical
- // values. Should consolidate both into one enum type.
- ProtocolPropertyODS.
- setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)
- PIkind);
- // Must re-establish the context from class extension to primary
- // class context.
- ContextRAII SavedContext(*this, CCPrimary);
-
- Decl *ProtocolPtrTy =
- ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS,
- PIDecl->getGetterName(),
- PIDecl->getSetterName(),
- isOverridingProperty,
- MethodImplKind,
- /* lexicalDC = */ CDecl);
- PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy);
- }
- PIDecl->makeitReadWriteAttribute();
- if (Attributes & ObjCDeclSpec::DQ_PR_retain)
- PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
- if (Attributes & ObjCDeclSpec::DQ_PR_strong)
- PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
- if (Attributes & ObjCDeclSpec::DQ_PR_copy)
- PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
- PIDecl->setSetterName(SetterSel);
- } else {
- // Tailor the diagnostics for the common case where a readwrite
- // property is declared both in the @interface and the continuation.
- // This is a common error where the user often intended the original
- // declaration to be readonly.
- unsigned diag =
- (Attributes & ObjCDeclSpec::DQ_PR_readwrite) &&
- (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite)
- ? diag::err_use_continuation_class_redeclaration_readwrite
- : diag::err_use_continuation_class;
- Diag(AtLoc, diag)
- << CCPrimary->getDeclName();
- Diag(PIDecl->getLocation(), diag::note_property_declare);
- return nullptr;
- }
- *isOverridingProperty = true;
- // Make sure setter decl is synthesized, and added to primary class's list.
- ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl);
- PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl());
- PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl());
- if (ASTMutationListener *L = Context.getASTMutationListener())
- L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl);
+
+ // Check that atomicity of property in class extension matches the previous
+ // declaration.
+ checkAtomicPropertyMismatch(*this, PIDecl, PDecl, true);
+
+ // Make sure getter/setter are appropriately synthesized.
+ ProcessPropertyDecl(PDecl);
return PDecl;
}
@@ -525,7 +559,6 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
FieldDeclarator &FD,
Selector GetterSel,
Selector SetterSel,
- const bool isAssign,
const bool isReadWrite,
const unsigned Attributes,
const unsigned AttributesAsWritten,
@@ -535,10 +568,23 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
DeclContext *lexicalDC){
IdentifierInfo *PropertyId = FD.D.getIdentifier();
- // Issue a warning if property is 'assign' as default and its object, which is
- // gc'able conforms to NSCopying protocol
+ // Property defaults to 'assign' if it is readwrite, unless this is ARC
+ // and the type is retainable.
+ bool isAssign;
+ if (Attributes & (ObjCDeclSpec::DQ_PR_assign |
+ ObjCDeclSpec::DQ_PR_unsafe_unretained)) {
+ isAssign = true;
+ } else if (getOwnershipRule(Attributes) || !isReadWrite) {
+ isAssign = false;
+ } else {
+ isAssign = (!getLangOpts().ObjCAutoRefCount ||
+ !T->isObjCRetainableType());
+ }
+
+ // Issue a warning if property is 'assign' as default and its
+ // object, which is gc'able conforms to NSCopying protocol
if (getLangOpts().getGC() != LangOptions::NonGC &&
- isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
+ isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) {
if (const ObjCObjectPointerType *ObjPtrTy =
T->getAs<ObjCObjectPointerType>()) {
ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
@@ -548,6 +594,7 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
if (IDecl->ClassImplementsProtocol(PNSCopying, true))
Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
}
+ }
if (T->isObjCObjectType()) {
SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd();
@@ -663,8 +710,10 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
// We're fine if they match.
if (propertyLifetime == ivarLifetime) return;
- // These aren't valid lifetimes for object ivars; don't diagnose twice.
- if (ivarLifetime == Qualifiers::OCL_None ||
+ // None isn't a valid lifetime for an object ivar in ARC, and
+ // __autoreleasing is never valid; don't diagnose twice.
+ if ((ivarLifetime == Qualifiers::OCL_None &&
+ S.getLangOpts().ObjCAutoRefCount) ||
ivarLifetime == Qualifiers::OCL_Autoreleasing)
return;
@@ -797,6 +846,38 @@ DiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc,
S.Diag(AtLoc, diag::note_property_synthesize);
}
+/// Determine whether any storage attributes were written on the property.
+static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop) {
+ if (Prop->getPropertyAttributesAsWritten() & OwnershipMask) return true;
+
+ // If this is a readwrite property in a class extension that refines
+ // a readonly property in the original class definition, check it as
+ // well.
+
+ // If it's a readonly property, we're not interested.
+ if (Prop->isReadOnly()) return false;
+
+ // Is it declared in an extension?
+ auto Category = dyn_cast<ObjCCategoryDecl>(Prop->getDeclContext());
+ if (!Category || !Category->IsClassExtension()) return false;
+
+ // Find the corresponding property in the primary class definition.
+ auto OrigClass = Category->getClassInterface();
+ for (auto Found : OrigClass->lookup(Prop->getDeclName())) {
+ if (ObjCPropertyDecl *OrigProp = dyn_cast<ObjCPropertyDecl>(Found))
+ return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask;
+ }
+
+ // Look through all of the protocols.
+ for (const auto *Proto : OrigClass->all_referenced_protocols()) {
+ if (ObjCPropertyDecl *OrigProp =
+ Proto->FindPropertyDeclaration(Prop->getIdentifier()))
+ return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask;
+ }
+
+ return false;
+}
+
/// ActOnPropertyImplDecl - This routine performs semantic checks and
/// builds the AST node for a property implementation declaration; declared
/// as \@synthesize or \@dynamic.
@@ -953,18 +1034,49 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
ObjCPropertyDecl::PropertyAttributeKind kind
= property->getPropertyAttributes();
- // Add GC __weak to the ivar type if the property is weak.
- if ((kind & ObjCPropertyDecl::OBJC_PR_weak) &&
- getLangOpts().getGC() != LangOptions::NonGC) {
- assert(!getLangOpts().ObjCAutoRefCount);
- if (PropertyIvarType.isObjCGCStrong()) {
- Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type);
- Diag(property->getLocation(), diag::note_property_declare);
+ bool isARCWeak = false;
+ if (kind & ObjCPropertyDecl::OBJC_PR_weak) {
+ // Add GC __weak to the ivar type if the property is weak.
+ if (getLangOpts().getGC() != LangOptions::NonGC) {
+ assert(!getLangOpts().ObjCAutoRefCount);
+ if (PropertyIvarType.isObjCGCStrong()) {
+ Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type);
+ Diag(property->getLocation(), diag::note_property_declare);
+ } else {
+ PropertyIvarType =
+ Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
+ }
+
+ // Otherwise, check whether ARC __weak is enabled and works with
+ // the property type.
} else {
- PropertyIvarType =
- Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
+ if (!getLangOpts().ObjCWeak) {
+ // Only complain here when synthesizing an ivar.
+ if (!Ivar) {
+ Diag(PropertyDiagLoc,
+ getLangOpts().ObjCWeakRuntime
+ ? diag::err_synthesizing_arc_weak_property_disabled
+ : diag::err_synthesizing_arc_weak_property_no_runtime);
+ Diag(property->getLocation(), diag::note_property_declare);
+ }
+ CompleteTypeErr = true; // suppress later diagnostics about the ivar
+ } else {
+ isARCWeak = true;
+ if (const ObjCObjectPointerType *ObjT =
+ PropertyIvarType->getAs<ObjCObjectPointerType>()) {
+ const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
+ if (ObjI && ObjI->isArcWeakrefUnavailable()) {
+ Diag(property->getLocation(),
+ diag::err_arc_weak_unavailable_property)
+ << PropertyIvarType;
+ Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class)
+ << ClassImpDecl->getName();
+ }
+ }
+ }
}
}
+
if (AtLoc.isInvalid()) {
// Check when default synthesizing a property that there is
// an ivar matching property name and issue warning; since this
@@ -987,13 +1099,13 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (!Ivar) {
// In ARC, give the ivar a lifetime qualifier based on the
// property attributes.
- if (getLangOpts().ObjCAutoRefCount &&
+ if ((getLangOpts().ObjCAutoRefCount || isARCWeak) &&
!PropertyIvarType.getObjCLifetime() &&
PropertyIvarType->isObjCRetainableType()) {
// It's an error if we have to do this and the user didn't
// explicitly write an ownership attribute on the property.
- if (!property->hasWrittenStorageAttribute() &&
+ if (!hasWrittenStorageAttribute(property) &&
!(kind & ObjCPropertyDecl::OBJC_PR_strong)) {
Diag(PropertyDiagLoc,
diag::err_arc_objc_property_default_assign_on_object);
@@ -1002,24 +1114,6 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
Qualifiers::ObjCLifetime lifetime =
getImpliedARCOwnership(kind, PropertyIvarType);
assert(lifetime && "no lifetime for property?");
- if (lifetime == Qualifiers::OCL_Weak) {
- bool err = false;
- if (const ObjCObjectPointerType *ObjT =
- PropertyIvarType->getAs<ObjCObjectPointerType>()) {
- const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
- if (ObjI && ObjI->isArcWeakrefUnavailable()) {
- Diag(property->getLocation(),
- diag::err_arc_weak_unavailable_property) << PropertyIvarType;
- Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class)
- << ClassImpDecl->getName();
- err = true;
- }
- }
- if (!err && !getLangOpts().ObjCARCWeak) {
- Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime);
- Diag(property->getLocation(), diag::note_property_declare);
- }
- }
Qualifiers qs;
qs.addObjCLifetime(lifetime);
@@ -1027,13 +1121,6 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
}
}
- if (kind & ObjCPropertyDecl::OBJC_PR_weak &&
- !getLangOpts().ObjCAutoRefCount &&
- getLangOpts().getGC() == LangOptions::NonGC) {
- Diag(PropertyDiagLoc, diag::error_synthesize_weak_non_arc_or_gc);
- Diag(property->getLocation(), diag::note_property_declare);
- }
-
Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
PropertyIvarType, /*Dinfo=*/nullptr,
@@ -1121,7 +1208,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// Fall thru - see previous comment
}
}
- if (getLangOpts().ObjCAutoRefCount)
+ if (getLangOpts().ObjCAutoRefCount || isARCWeak ||
+ Ivar->getType().getObjCLifetime())
checkARCPropertyImpl(*this, PropertyLoc, property, Ivar);
} else if (PropertyIvar)
// @dynamic
@@ -1349,12 +1437,10 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
}
}
- if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
- != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) {
- Diag(Property->getLocation(), diag::warn_property_attribute)
- << Property->getDeclName() << "atomic" << inheritedName;
- Diag(SuperProperty->getLocation(), diag::note_property_declare);
- }
+ // Check for nonatomic; note that nonatomic is effectively
+ // meaningless for readonly properties, so don't diagnose if the
+ // atomic property is 'readonly'.
+ checkAtomicPropertyMismatch(*this, SuperProperty, Property, false);
if (Property->getSetterName() != SuperProperty->getSetterName()) {
Diag(Property->getLocation(), diag::warn_property_attribute)
<< Property->getDeclName() << "setter" << inheritedName;
@@ -1395,12 +1481,11 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
QualType PropertyIvarType = property->getType().getNonReferenceType();
bool compat = Context.hasSameType(PropertyIvarType, GetterType);
if (!compat) {
- if (isa<ObjCObjectPointerType>(PropertyIvarType) &&
- isa<ObjCObjectPointerType>(GetterType))
- compat =
- Context.canAssignObjCInterfaces(
- GetterType->getAs<ObjCObjectPointerType>(),
- PropertyIvarType->getAs<ObjCObjectPointerType>());
+ const ObjCObjectPointerType *propertyObjCPtr = nullptr;
+ const ObjCObjectPointerType *getterObjCPtr = nullptr;
+ if ((propertyObjCPtr = PropertyIvarType->getAs<ObjCObjectPointerType>()) &&
+ (getterObjCPtr = GetterType->getAs<ObjCObjectPointerType>()))
+ compat = Context.canAssignObjCInterfaces(getterObjCPtr, propertyObjCPtr);
else if (CheckAssignmentConstraints(Loc, GetterType, PropertyIvarType)
!= Compatible) {
Diag(Loc, diag::error_property_accessor_type)
@@ -1438,6 +1523,11 @@ static void CollectImmediateProperties(ObjCContainerDecl *CDecl,
if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
for (auto *Prop : IDecl->properties())
PropMap[Prop->getIdentifier()] = Prop;
+
+ // Collect the properties from visible extensions.
+ for (auto *Ext : IDecl->visible_extensions())
+ CollectImmediateProperties(Ext, PropMap, SuperPropMap, IncludeProtocols);
+
if (IncludeProtocols) {
// Scan through class's protocols.
for (auto *PI : IDecl->all_referenced_protocols())
@@ -1445,9 +1535,8 @@ static void CollectImmediateProperties(ObjCContainerDecl *CDecl,
}
}
if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
- if (!CATDecl->IsClassExtension())
- for (auto *Prop : CATDecl->properties())
- PropMap[Prop->getIdentifier()] = Prop;
+ for (auto *Prop : CATDecl->properties())
+ PropMap[Prop->getIdentifier()] = Prop;
if (IncludeProtocols) {
// Scan through class's protocols.
for (auto *PI : CATDecl->protocols())
@@ -1507,6 +1596,14 @@ Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
(Property->getPropertyIvarDecl() == IV))
return true;
}
+ // Also look up property declaration in class extension whose one of its
+ // accessors is implemented by this method.
+ for (const auto *Ext : IFace->known_extensions())
+ for (const auto *Property : Ext->properties())
+ if ((Property->getGetterName() == IMD->getSelector() ||
+ Property->getSetterName() == IMD->getSelector()) &&
+ (Property->getPropertyIvarDecl() == IV))
+ return true;
return false;
}
@@ -1563,7 +1660,7 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
<< Prop->getIdentifier();
- if (!PID->getLocation().isInvalid())
+ if (PID->getLocation().isValid())
Diag(PID->getLocation(), diag::note_property_synthesize);
continue;
}
@@ -1791,11 +1888,20 @@ void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl)
void
Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
- ObjCContainerDecl* IDecl) {
+ ObjCInterfaceDecl* IDecl) {
// Rules apply in non-GC mode only
if (getLangOpts().getGC() != LangOptions::NonGC)
return;
- for (const auto *Property : IDecl->properties()) {
+ ObjCContainerDecl::PropertyMap PM;
+ for (auto *Prop : IDecl->properties())
+ PM[Prop->getIdentifier()] = Prop;
+ for (const auto *Ext : IDecl->known_extensions())
+ for (auto *Prop : Ext->properties())
+ PM[Prop->getIdentifier()] = Prop;
+
+ for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end();
+ I != E; ++I) {
+ const ObjCPropertyDecl *Property = I->second;
ObjCMethodDecl *GetterMethod = nullptr;
ObjCMethodDecl *SetterMethod = nullptr;
bool LookedUpGetterSetter = false;
@@ -1842,30 +1948,23 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
<< Property->getIdentifier() << (GetterMethod != nullptr)
<< (SetterMethod != nullptr);
// fixit stuff.
- if (!AttributesAsWritten) {
- if (Property->getLParenLoc().isValid()) {
- // @property () ... case.
- SourceRange PropSourceRange(Property->getAtLoc(),
- Property->getLParenLoc());
- Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
- FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic");
- }
- else {
- //@property id etc.
- SourceLocation endLoc =
- Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
- endLoc = endLoc.getLocWithOffset(-1);
- SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
- Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
- FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) ");
- }
- }
- else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) {
+ if (Property->getLParenLoc().isValid() &&
+ !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) {
// @property () ... case.
- SourceLocation endLoc = Property->getLParenLoc();
- SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
- Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
- FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, ");
+ SourceLocation AfterLParen =
+ getLocForEndOfToken(Property->getLParenLoc());
+ StringRef NonatomicStr = AttributesAsWritten? "nonatomic, "
+ : "nonatomic";
+ Diag(Property->getLocation(),
+ diag::note_atomic_property_fixup_suggest)
+ << FixItHint::CreateInsertion(AfterLParen, NonatomicStr);
+ } else if (Property->getLParenLoc().isInvalid()) {
+ //@property id etc.
+ SourceLocation startLoc =
+ Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
+ Diag(Property->getLocation(),
+ diag::note_atomic_property_fixup_suggest)
+ << FixItHint::CreateInsertion(startLoc, "(nonatomic) ");
}
else
Diag(MethodLoc, diag::note_atomic_property_fixup_suggest);
@@ -1950,10 +2049,16 @@ void Sema::DiagnoseMissingDesignatedInitOverrides(
I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) {
const ObjCMethodDecl *MD = *I;
if (!InitSelSet.count(MD->getSelector())) {
- Diag(ImplD->getLocation(),
- diag::warn_objc_implementation_missing_designated_init_override)
- << MD->getSelector();
- Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here);
+ bool Ignore = false;
+ if (auto *IMD = IFD->getInstanceMethod(MD->getSelector())) {
+ Ignore = IMD->isUnavailable();
+ }
+ if (!Ignore) {
+ Diag(ImplD->getLocation(),
+ diag::warn_objc_implementation_missing_designated_init_override)
+ << MD->getSelector();
+ Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here);
+ }
}
}
}
@@ -1974,20 +2079,28 @@ static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
/// have the property type and issue diagnostics if they don't.
/// Also synthesize a getter/setter method if none exist (and update the
-/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized
-/// methods is the "right" thing to do.
-void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
- ObjCContainerDecl *CD,
- ObjCPropertyDecl *redeclaredProperty,
- ObjCContainerDecl *lexicalDC) {
-
+/// appropriate lookup tables.
+void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
ObjCMethodDecl *GetterMethod, *SetterMethod;
-
+ ObjCContainerDecl *CD = cast<ObjCContainerDecl>(property->getDeclContext());
if (CD->isInvalidDecl())
return;
GetterMethod = CD->getInstanceMethod(property->getGetterName());
+ // if setter or getter is not found in class extension, it might be
+ // in the primary class.
+ if (!GetterMethod)
+ if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
+ if (CatDecl->IsClassExtension())
+ GetterMethod = CatDecl->getClassInterface()->
+ getInstanceMethod(property->getGetterName());
+
SetterMethod = CD->getInstanceMethod(property->getSetterName());
+ if (!SetterMethod)
+ if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
+ if (CatDecl->IsClassExtension())
+ SetterMethod = CatDecl->getClassInterface()->
+ getInstanceMethod(property->getSetterName());
DiagnosePropertyAccessorMismatch(property, GetterMethod,
property->getLocation());
@@ -2020,9 +2133,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
// No instance method of same name as property getter name was found.
// Declare a getter method and add it to the list of methods
// for this class.
- SourceLocation Loc = redeclaredProperty ?
- redeclaredProperty->getLocation() :
- property->getLocation();
+ SourceLocation Loc = property->getLocation();
// If the property is null_resettable, the getter returns nonnull.
QualType resultTy = property->getType();
@@ -2050,10 +2161,6 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
AddPropertyAttrs(*this, GetterMethod, property);
- // FIXME: Eventually this shouldn't be needed, as the lexical context
- // and the real context should be the same.
- if (lexicalDC)
- GetterMethod->setLexicalDeclContext(lexicalDC);
if (property->hasAttr<NSReturnsNotRetainedAttr>())
GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context,
Loc));
@@ -2082,9 +2189,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
// No instance method of same name as property setter name was found.
// Declare a setter method and add it to the list of methods
// for this class.
- SourceLocation Loc = redeclaredProperty ?
- redeclaredProperty->getLocation() :
- property->getLocation();
+ SourceLocation Loc = property->getLocation();
SetterMethod =
ObjCMethodDecl::Create(Context, Loc, Loc,
@@ -2126,10 +2231,6 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
AddPropertyAttrs(*this, SetterMethod, property);
CD->addDecl(SetterMethod);
- // FIXME: Eventually this shouldn't be needed, as the lexical context
- // and the real context should be the same.
- if (lexicalDC)
- SetterMethod->setLexicalDeclContext(lexicalDC);
if (const SectionAttr *SA = property->getAttr<SectionAttr>())
SetterMethod->addAttr(
SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section,
@@ -2189,15 +2290,6 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
QualType PropertyTy = PropertyDecl->getType();
- unsigned PropertyOwnership = getOwnershipRule(Attributes);
-
- // 'readonly' property with no obvious lifetime.
- // its life time will be determined by its backing ivar.
- if (getLangOpts().ObjCAutoRefCount &&
- Attributes & ObjCDeclSpec::DQ_PR_readonly &&
- PropertyTy->isObjCRetainableType() &&
- !PropertyOwnership)
- return;
// Check for copy or retain on non-object types.
if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy |
@@ -2295,13 +2387,6 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
if (*nullability == NullabilityKind::NonNull)
Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
<< "nonnull" << "weak";
- } else {
- PropertyTy =
- Context.getAttributedType(
- AttributedType::getNullabilityAttrKind(NullabilityKind::Nullable),
- PropertyTy, PropertyTy);
- TypeSourceInfo *TSInfo = PropertyDecl->getTypeSourceInfo();
- PropertyDecl->setType(PropertyTy, TSInfo);
}
}
@@ -2314,16 +2399,14 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
// Warn if user supplied no assignment attribute, property is
// readwrite, and this is an object type.
- if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy |
- ObjCDeclSpec::DQ_PR_unsafe_unretained |
- ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong |
- ObjCDeclSpec::DQ_PR_weak)) &&
- PropertyTy->isObjCObjectPointerType()) {
- if (getLangOpts().ObjCAutoRefCount)
- // With arc, @property definitions should default to (strong) when
- // not specified; including when property is 'readonly'.
- PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
- else if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) {
+ if (!getOwnershipRule(Attributes) && PropertyTy->isObjCRetainableType()) {
+ if (Attributes & ObjCDeclSpec::DQ_PR_readonly) {
+ // do nothing
+ } else if (getLangOpts().ObjCAutoRefCount) {
+ // With arc, @property definitions should default to strong when
+ // not specified.
+ PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
+ } else if (PropertyTy->isObjCObjectPointerType()) {
bool isAnyClassTy =
(PropertyTy->isObjCClassType() ||
PropertyTy->isObjCQualifiedClassType());
@@ -2342,7 +2425,7 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
if (getLangOpts().getGC() == LangOptions::NonGC)
Diag(Loc, diag::warn_objc_property_default_assign_on_object);
}
- }
+ }
// FIXME: Implement warning dependent on NSCopying being
// implemented. See also:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
index ca67a1c..f66e218 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
@@ -77,6 +77,11 @@ public:
ImplicitDSALoc() {}
};
+public:
+ struct MapInfo {
+ Expr *RefExpr;
+ };
+
private:
struct DSAInfo {
OpenMPClauseKind Attributes;
@@ -84,33 +89,41 @@ private:
};
typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy;
typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy;
- typedef llvm::DenseSet<VarDecl *> LoopControlVariablesSetTy;
+ typedef llvm::DenseMap<VarDecl *, unsigned> LoopControlVariablesMapTy;
+ typedef llvm::SmallDenseMap<VarDecl *, MapInfo, 64> MappedDeclsTy;
+ typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>>
+ CriticalsWithHintsTy;
struct SharingMapTy {
DeclSAMapTy SharingMap;
AlignedMapTy AlignedMap;
- LoopControlVariablesSetTy LCVSet;
+ MappedDeclsTy MappedDecls;
+ LoopControlVariablesMapTy LCVMap;
DefaultDataSharingAttributes DefaultAttr;
SourceLocation DefaultAttrLoc;
OpenMPDirectiveKind Directive;
DeclarationNameInfo DirectiveName;
Scope *CurScope;
SourceLocation ConstructLoc;
- bool OrderedRegion;
+ /// \brief first argument (Expr *) contains optional argument of the
+ /// 'ordered' clause, the second one is true if the regions has 'ordered'
+ /// clause, false otherwise.
+ llvm::PointerIntPair<Expr *, 1, bool> OrderedRegion;
bool NowaitRegion;
- unsigned CollapseNumber;
+ bool CancelRegion;
+ unsigned AssociatedLoops;
SourceLocation InnerTeamsRegionLoc;
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
Scope *CurScope, SourceLocation Loc)
- : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified),
+ : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified),
Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope),
- ConstructLoc(Loc), OrderedRegion(false), NowaitRegion(false),
- CollapseNumber(1), InnerTeamsRegionLoc() {}
+ ConstructLoc(Loc), OrderedRegion(), NowaitRegion(false),
+ CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {}
SharingMapTy()
- : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified),
+ : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified),
Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),
- ConstructLoc(), OrderedRegion(false), NowaitRegion(false),
- CollapseNumber(1), InnerTeamsRegionLoc() {}
+ ConstructLoc(), OrderedRegion(), NowaitRegion(false),
+ CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {}
};
typedef SmallVector<SharingMapTy, 64> StackTy;
@@ -122,6 +135,7 @@ private:
OpenMPClauseKind ClauseKindMode;
Sema &SemaRef;
bool ForceCapturing;
+ CriticalsWithHintsTy Criticals;
typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
@@ -152,6 +166,16 @@ public:
Stack.pop_back();
}
+ void addCriticalWithHint(OMPCriticalDirective *D, llvm::APSInt Hint) {
+ Criticals[D->getDirectiveName().getAsString()] = std::make_pair(D, Hint);
+ }
+ const std::pair<OMPCriticalDirective *, llvm::APSInt>
+ getCriticalWithHint(const DeclarationNameInfo &Name) const {
+ auto I = Criticals.find(Name.getAsString());
+ if (I != Criticals.end())
+ return I->second;
+ return std::make_pair(nullptr, llvm::APSInt());
+ }
/// \brief If 'aligned' declaration for given variable \a D was not seen yet,
/// add it and return NULL; otherwise return previous occurrence's expression
/// for diagnostics.
@@ -161,7 +185,17 @@ public:
void addLoopControlVariable(VarDecl *D);
/// \brief Check if the specified variable is a loop control variable for
/// current region.
- bool isLoopControlVariable(VarDecl *D);
+ /// \return The index of the loop control variable in the list of associated
+ /// for-loops (from outer to inner).
+ unsigned isLoopControlVariable(VarDecl *D);
+ /// \brief Check if the specified variable is a loop control variable for
+ /// parent region.
+ /// \return The index of the loop control variable in the list of associated
+ /// for-loops (from outer to inner).
+ unsigned isParentLoopControlVariable(VarDecl *D);
+ /// \brief Get the loop control variable for the I-th loop (or nullptr) in
+ /// parent directive.
+ VarDecl *getParentLoopControlVariable(unsigned I);
/// \brief Adds explicit data sharing attribute to the specified declaration.
void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A);
@@ -190,6 +224,13 @@ public:
bool hasExplicitDSA(VarDecl *D,
const llvm::function_ref<bool(OpenMPClauseKind)> &CPred,
unsigned Level);
+
+ /// \brief Returns true if the directive at level \Level matches in the
+ /// specified \a DPred predicate.
+ bool hasExplicitDirective(
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
+ unsigned Level);
+
/// \brief Finds a directive which matches specified \a DPred predicate.
template <class NamedDirectivesPredicate>
bool hasDirective(NamedDirectivesPredicate DPred, bool FromParent);
@@ -204,6 +245,8 @@ public:
return Stack[Stack.size() - 2].Directive;
return OMPD_unknown;
}
+ /// \brief Return the directive associated with the provided scope.
+ OpenMPDirectiveKind getDirectiveForScope(const Scope *S) const;
/// \brief Set default data sharing attribute to none.
void setDefaultDSANone(SourceLocation Loc) {
@@ -230,16 +273,23 @@ public:
}
/// \brief Marks current region as ordered (it has an 'ordered' clause).
- void setOrderedRegion(bool IsOrdered = true) {
- Stack.back().OrderedRegion = IsOrdered;
+ void setOrderedRegion(bool IsOrdered, Expr *Param) {
+ Stack.back().OrderedRegion.setInt(IsOrdered);
+ Stack.back().OrderedRegion.setPointer(Param);
}
/// \brief Returns true, if parent region is ordered (has associated
/// 'ordered' clause), false - otherwise.
bool isParentOrderedRegion() const {
if (Stack.size() > 2)
- return Stack[Stack.size() - 2].OrderedRegion;
+ return Stack[Stack.size() - 2].OrderedRegion.getInt();
return false;
}
+ /// \brief Returns optional parameter for the ordered region.
+ Expr *getParentOrderedRegionParam() const {
+ if (Stack.size() > 2)
+ return Stack[Stack.size() - 2].OrderedRegion.getPointer();
+ return nullptr;
+ }
/// \brief Marks current region as nowait (it has a 'nowait' clause).
void setNowaitRegion(bool IsNowait = true) {
Stack.back().NowaitRegion = IsNowait;
@@ -251,13 +301,21 @@ public:
return Stack[Stack.size() - 2].NowaitRegion;
return false;
}
+ /// \brief Marks parent region as cancel region.
+ void setParentCancelRegion(bool Cancel = true) {
+ if (Stack.size() > 2)
+ Stack[Stack.size() - 2].CancelRegion =
+ Stack[Stack.size() - 2].CancelRegion || Cancel;
+ }
+ /// \brief Return true if current region has inner cancel construct.
+ bool isCancelRegion() const {
+ return Stack.back().CancelRegion;
+ }
/// \brief Set collapse value for the region.
- void setCollapseNumber(unsigned Val) { Stack.back().CollapseNumber = Val; }
+ void setAssociatedLoops(unsigned Val) { Stack.back().AssociatedLoops = Val; }
/// \brief Return collapse value for region.
- unsigned getCollapseNumber() const {
- return Stack.back().CollapseNumber;
- }
+ unsigned getAssociatedLoops() const { return Stack.back().AssociatedLoops; }
/// \brief Marks current target region as one with closely nested teams
/// region.
@@ -279,10 +337,37 @@ public:
Scope *getCurScope() const { return Stack.back().CurScope; }
Scope *getCurScope() { return Stack.back().CurScope; }
SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
+
+ MapInfo getMapInfoForVar(VarDecl *VD) {
+ MapInfo VarMI = {0};
+ for (auto Cnt = Stack.size() - 1; Cnt > 0; --Cnt) {
+ if (Stack[Cnt].MappedDecls.count(VD)) {
+ VarMI = Stack[Cnt].MappedDecls[VD];
+ break;
+ }
+ }
+ return VarMI;
+ }
+
+ void addMapInfoForVar(VarDecl *VD, MapInfo MI) {
+ if (Stack.size() > 1) {
+ Stack.back().MappedDecls[VD] = MI;
+ }
+ }
+
+ MapInfo IsMappedInCurrentRegion(VarDecl *VD) {
+ assert(Stack.size() > 1 && "Target level is 0");
+ MapInfo VarMI = {0};
+ if (Stack.size() > 1 && Stack.back().MappedDecls.count(VD)) {
+ VarMI = Stack.back().MappedDecls[VD];
+ }
+ return VarMI;
+ }
};
bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
return isOpenMPParallelDirective(DKind) || DKind == OMPD_task ||
- isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown;
+ isOpenMPTeamsDirective(DKind) || DKind == OMPD_unknown ||
+ isOpenMPTaskLoopDirective(DKind);
}
} // namespace
@@ -409,13 +494,32 @@ DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) {
void DSAStackTy::addLoopControlVariable(VarDecl *D) {
assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
D = D->getCanonicalDecl();
- Stack.back().LCVSet.insert(D);
+ Stack.back().LCVMap.insert(std::make_pair(D, Stack.back().LCVMap.size() + 1));
}
-bool DSAStackTy::isLoopControlVariable(VarDecl *D) {
+unsigned DSAStackTy::isLoopControlVariable(VarDecl *D) {
assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
D = D->getCanonicalDecl();
- return Stack.back().LCVSet.count(D) > 0;
+ return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D] : 0;
+}
+
+unsigned DSAStackTy::isParentLoopControlVariable(VarDecl *D) {
+ assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
+ D = D->getCanonicalDecl();
+ return Stack[Stack.size() - 2].LCVMap.count(D) > 0
+ ? Stack[Stack.size() - 2].LCVMap[D]
+ : 0;
+}
+
+VarDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) {
+ assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
+ if (Stack[Stack.size() - 2].LCVMap.size() < I)
+ return nullptr;
+ for (auto &Pair : Stack[Stack.size() - 2].LCVMap) {
+ if (Pair.second == I)
+ return Pair.first;
+ }
+ return nullptr;
}
void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
@@ -452,12 +556,17 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
/// \brief Build a variable declaration for OpenMP loop iteration variable.
static VarDecl *buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
- StringRef Name) {
+ StringRef Name, const AttrVec *Attrs = nullptr) {
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
VarDecl *Decl =
VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
+ if (Attrs) {
+ for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
+ I != E; ++I)
+ Decl->addAttr(*I);
+ }
Decl->setImplicit();
return Decl;
}
@@ -496,41 +605,20 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
}
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
- // in a Construct, C/C++, predetermined, p.1]
- // Variables with automatic storage duration that are declared in a scope
- // inside the construct are private.
- OpenMPDirectiveKind Kind =
- FromParent ? getParentDirective() : getCurrentDirective();
- auto StartI = std::next(Stack.rbegin());
- auto EndI = std::prev(Stack.rend());
- if (FromParent && StartI != EndI) {
- StartI = std::next(StartI);
- }
- if (!isParallelOrTaskRegion(Kind)) {
- if (isOpenMPLocal(D, StartI) &&
- ((D->isLocalVarDecl() && (D->getStorageClass() == SC_Auto ||
- D->getStorageClass() == SC_None)) ||
- isa<ParmVarDecl>(D))) {
- DVar.CKind = OMPC_private;
+ // in a Construct, C/C++, predetermined, p.4]
+ // Static data members are shared.
+ // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
+ // in a Construct, C/C++, predetermined, p.7]
+ // Variables with static storage duration that are declared in a scope
+ // inside the construct are shared.
+ if (D->isStaticDataMember()) {
+ DSAVarData DVarTemp =
+ hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent);
+ if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
return DVar;
- }
- // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
- // in a Construct, C/C++, predetermined, p.4]
- // Static data members are shared.
- // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
- // in a Construct, C/C++, predetermined, p.7]
- // Variables with static storage duration that are declared in a scope
- // inside the construct are shared.
- if (D->isStaticDataMember() || D->isStaticLocal()) {
- DSAVarData DVarTemp =
- hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent);
- if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
- return DVar;
-
- DVar.CKind = OMPC_shared;
- return DVar;
- }
+ DVar.CKind = OMPC_shared;
+ return DVar;
}
QualType Type = D->getType().getNonReferenceType().getCanonicalType();
@@ -542,6 +630,9 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
// shared.
CXXRecordDecl *RD =
SemaRef.getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
+ if (auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
+ if (auto *CTD = CTSD->getSpecializedTemplate())
+ RD = CTD->getTemplatedDecl();
if (IsConstant &&
!(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) {
// Variables with const-qualified type having no mutable member may be
@@ -557,6 +648,11 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
// Explicitly specified attributes and local variables with predetermined
// attributes.
+ auto StartI = std::next(Stack.rbegin());
+ auto EndI = std::prev(Stack.rend());
+ if (FromParent && StartI != EndI) {
+ StartI = std::next(StartI);
+ }
auto I = std::prev(StartI);
if (I->SharingMap.count(D)) {
DVar.RefExpr = I->SharingMap[D].RefExpr;
@@ -635,6 +731,19 @@ bool DSAStackTy::hasExplicitDSA(
CPred(StartI->SharingMap[D].Attributes);
}
+bool DSAStackTy::hasExplicitDirective(
+ const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
+ unsigned Level) {
+ if (isClauseParsingMode())
+ ++Level;
+ auto StartI = Stack.rbegin();
+ auto EndI = std::prev(Stack.rend());
+ if (std::distance(StartI, EndI) <= (int)Level)
+ return false;
+ std::advance(StartI, Level);
+ return DPred(StartI->Directive);
+}
+
template <class NamedDirectivesPredicate>
bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) {
auto StartI = std::next(Stack.rbegin());
@@ -649,15 +758,134 @@ bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) {
return false;
}
+OpenMPDirectiveKind DSAStackTy::getDirectiveForScope(const Scope *S) const {
+ for (auto I = Stack.rbegin(), EE = Stack.rend(); I != EE; ++I)
+ if (I->CurScope == S)
+ return I->Directive;
+ return OMPD_unknown;
+}
+
void Sema::InitDataSharingAttributesStack() {
VarDataSharingAttributesStack = new DSAStackTy(*this);
}
#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
+bool Sema::IsOpenMPCapturedByRef(VarDecl *VD,
+ const CapturedRegionScopeInfo *RSI) {
+ assert(LangOpts.OpenMP && "OpenMP is not allowed");
+
+ auto &Ctx = getASTContext();
+ bool IsByRef = true;
+
+ // Find the directive that is associated with the provided scope.
+ auto DKind = DSAStack->getDirectiveForScope(RSI->TheScope);
+ auto Ty = VD->getType();
+
+ if (isOpenMPTargetDirective(DKind)) {
+ // This table summarizes how a given variable should be passed to the device
+ // given its type and the clauses where it appears. This table is based on
+ // the description in OpenMP 4.5 [2.10.4, target Construct] and
+ // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
+ //
+ // =========================================================================
+ // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
+ // | |(tofrom:scalar)| | pvt | | | |
+ // =========================================================================
+ // | scl | | | | - | | bycopy|
+ // | scl | | - | x | - | - | bycopy|
+ // | scl | | x | - | - | - | null |
+ // | scl | x | | | - | | byref |
+ // | scl | x | - | x | - | - | bycopy|
+ // | scl | x | x | - | - | - | null |
+ // | scl | | - | - | - | x | byref |
+ // | scl | x | - | - | - | x | byref |
+ //
+ // | agg | n.a. | | | - | | byref |
+ // | agg | n.a. | - | x | - | - | byref |
+ // | agg | n.a. | x | - | - | - | null |
+ // | agg | n.a. | - | - | - | x | byref |
+ // | agg | n.a. | - | - | - | x[] | byref |
+ //
+ // | ptr | n.a. | | | - | | bycopy|
+ // | ptr | n.a. | - | x | - | - | bycopy|
+ // | ptr | n.a. | x | - | - | - | null |
+ // | ptr | n.a. | - | - | - | x | byref |
+ // | ptr | n.a. | - | - | - | x[] | bycopy|
+ // | ptr | n.a. | - | - | x | | bycopy|
+ // | ptr | n.a. | - | - | x | x | bycopy|
+ // | ptr | n.a. | - | - | x | x[] | bycopy|
+ // =========================================================================
+ // Legend:
+ // scl - scalar
+ // ptr - pointer
+ // agg - aggregate
+ // x - applies
+ // - - invalid in this combination
+ // [] - mapped with an array section
+ // byref - should be mapped by reference
+ // byval - should be mapped by value
+ // null - initialize a local variable to null on the device
+ //
+ // Observations:
+ // - All scalar declarations that show up in a map clause have to be passed
+ // by reference, because they may have been mapped in the enclosing data
+ // environment.
+ // - If the scalar value does not fit the size of uintptr, it has to be
+ // passed by reference, regardless the result in the table above.
+ // - For pointers mapped by value that have either an implicit map or an
+ // array section, the runtime library may pass the NULL value to the
+ // device instead of the value passed to it by the compiler.
+
+ // FIXME: Right now, only implicit maps are implemented. Properly mapping
+ // values requires having the map, private, and firstprivate clauses SEMA
+ // and parsing in place, which we don't yet.
+
+ if (Ty->isReferenceType())
+ Ty = Ty->castAs<ReferenceType>()->getPointeeType();
+ IsByRef = !Ty->isScalarType();
+ }
+
+ // When passing data by value, we need to make sure it fits the uintptr size
+ // and alignment, because the runtime library only deals with uintptr types.
+ // If it does not fit the uintptr size, we need to pass the data by reference
+ // instead.
+ if (!IsByRef &&
+ (Ctx.getTypeSizeInChars(Ty) >
+ Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) ||
+ Ctx.getDeclAlign(VD) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType())))
+ IsByRef = true;
+
+ return IsByRef;
+}
+
bool Sema::IsOpenMPCapturedVar(VarDecl *VD) {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
VD = VD->getCanonicalDecl();
+
+ // If we are attempting to capture a global variable in a directive with
+ // 'target' we return true so that this global is also mapped to the device.
+ //
+ // FIXME: If the declaration is enclosed in a 'declare target' directive,
+ // then it should not be captured. Therefore, an extra check has to be
+ // inserted here once support for 'declare target' is added.
+ //
+ if (!VD->hasLocalStorage()) {
+ if (DSAStack->getCurrentDirective() == OMPD_target &&
+ !DSAStack->isClauseParsingMode()) {
+ return true;
+ }
+ if (DSAStack->getCurScope() &&
+ DSAStack->hasDirective(
+ [](OpenMPDirectiveKind K, const DeclarationNameInfo &DNI,
+ SourceLocation Loc) -> bool {
+ return isOpenMPTargetDirective(K);
+ },
+ false)) {
+ return true;
+ }
+ }
+
if (DSAStack->getCurrentDirective() != OMPD_unknown &&
(!DSAStack->isClauseParsingMode() ||
DSAStack->getParentDirective() != OMPD_unknown)) {
@@ -682,6 +910,14 @@ bool Sema::isOpenMPPrivateVar(VarDecl *VD, unsigned Level) {
VD, [](OpenMPClauseKind K) -> bool { return K == OMPC_private; }, Level);
}
+bool Sema::isOpenMPTargetCapturedVar(VarDecl *VD, unsigned Level) {
+ assert(LangOpts.OpenMP && "OpenMP is not allowed");
+ // Return true if the current level is no longer enclosed in a target region.
+
+ return !VD->hasLocalStorage() &&
+ DSAStack->hasExplicitDirective(isOpenMPTargetDirective, Level);
+}
+
void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
@@ -715,7 +951,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
continue;
}
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(DE)->getDecl());
- QualType Type = VD->getType();
+ QualType Type = VD->getType().getNonReferenceType();
auto DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind == OMPC_lastprivate) {
// Generate helper private variable and initialize it with the
@@ -723,9 +959,9 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
// by the address of the new private variable in CodeGen. This new
// variable is not added to IdResolver, so the code in the OpenMP
// region uses original variable for proper diagnostics.
- auto *VDPrivate =
- buildVarDecl(*this, DE->getExprLoc(), Type.getUnqualifiedType(),
- VD->getName());
+ auto *VDPrivate = buildVarDecl(
+ *this, DE->getExprLoc(), Type.getUnqualifiedType(),
+ VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr);
ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);
if (VDPrivate->isInvalidDecl())
continue;
@@ -1158,7 +1394,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
switch (DKind) {
case OMPD_parallel: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -1234,7 +1471,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
}
case OMPD_parallel_for: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -1246,7 +1484,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
}
case OMPD_parallel_for_simd: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -1258,7 +1497,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
}
case OMPD_parallel_sections: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -1309,6 +1549,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
+ case OMPD_target_data:
case OMPD_target: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
@@ -1319,7 +1560,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
}
case OMPD_teams: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
- QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty);
+ QualType KmpInt32PtrTy =
+ Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
Sema::CapturedParamNameType Params[] = {
std::make_pair(".global_tid.", KmpInt32PtrTy),
std::make_pair(".bound_tid.", KmpInt32PtrTy),
@@ -1337,6 +1579,30 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
+ case OMPD_taskloop: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_taskloop_simd: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
+ case OMPD_distribute: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
case OMPD_threadprivate:
case OMPD_taskyield:
case OMPD_barrier:
@@ -1356,6 +1622,10 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
ActOnCapturedRegionError();
return StmtError();
}
+
+ OMPOrderedClause *OC = nullptr;
+ OMPScheduleClause *SC = nullptr;
+ SmallVector<OMPLinearClause *, 4> LCs;
// This is required for proper codegen.
for (auto *Clause : Clauses) {
if (isOpenMPPrivate(Clause->getClauseKind()) ||
@@ -1377,10 +1647,49 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
// Required for proper codegen of combined directives.
// TODO: add processing for other clauses.
if (auto *E = cast_or_null<Expr>(
- cast<OMPScheduleClause>(Clause)->getHelperChunkSize())) {
- MarkDeclarationsReferencedInExpr(E);
- }
+ cast<OMPScheduleClause>(Clause)->getHelperChunkSize()))
+ MarkDeclarationsReferencedInExpr(E);
}
+ if (Clause->getClauseKind() == OMPC_schedule)
+ SC = cast<OMPScheduleClause>(Clause);
+ else if (Clause->getClauseKind() == OMPC_ordered)
+ OC = cast<OMPOrderedClause>(Clause);
+ else if (Clause->getClauseKind() == OMPC_linear)
+ LCs.push_back(cast<OMPLinearClause>(Clause));
+ }
+ bool ErrorFound = false;
+ // OpenMP, 2.7.1 Loop Construct, Restrictions
+ // The nonmonotonic modifier cannot be specified if an ordered clause is
+ // specified.
+ if (SC &&
+ (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
+ SC->getSecondScheduleModifier() ==
+ OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
+ OC) {
+ Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
+ ? SC->getFirstScheduleModifierLoc()
+ : SC->getSecondScheduleModifierLoc(),
+ diag::err_omp_schedule_nonmonotonic_ordered)
+ << SourceRange(OC->getLocStart(), OC->getLocEnd());
+ ErrorFound = true;
+ }
+ if (!LCs.empty() && OC && OC->getNumForLoops()) {
+ for (auto *C : LCs) {
+ Diag(C->getLocStart(), diag::err_omp_linear_ordered)
+ << SourceRange(OC->getLocStart(), OC->getLocEnd());
+ }
+ ErrorFound = true;
+ }
+ if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
+ isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
+ OC->getNumForLoops()) {
+ Diag(OC->getLocStart(), diag::err_omp_ordered_simd)
+ << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+ ErrorFound = true;
+ }
+ if (ErrorFound) {
+ ActOnCapturedRegionError();
+ return StmtError();
}
return ActOnCapturedRegionEnd(S.get());
}
@@ -1419,6 +1728,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel | cancellation | |
// | | point | ! |
// | parallel | cancel | ! |
+ // | parallel | taskloop | * |
+ // | parallel | taskloop simd | * |
+ // | parallel | distribute | |
// +------------------+-----------------+------------------------------------+
// | for | parallel | * |
// | for | for | + |
@@ -1445,6 +1757,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for | cancellation | |
// | | point | ! |
// | for | cancel | ! |
+ // | for | taskloop | * |
+ // | for | taskloop simd | * |
+ // | for | distribute | |
// +------------------+-----------------+------------------------------------+
// | master | parallel | * |
// | master | for | + |
@@ -1471,6 +1786,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | master | cancellation | |
// | | point | |
// | master | cancel | |
+ // | master | taskloop | * |
+ // | master | taskloop simd | * |
+ // | master | distribute | |
// +------------------+-----------------+------------------------------------+
// | critical | parallel | * |
// | critical | for | + |
@@ -1496,6 +1814,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | critical | cancellation | |
// | | point | |
// | critical | cancel | |
+ // | critical | taskloop | * |
+ // | critical | taskloop simd | * |
+ // | critical | distribute | |
// +------------------+-----------------+------------------------------------+
// | simd | parallel | |
// | simd | for | |
@@ -1515,13 +1836,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | simd | taskwait | |
// | simd | taskgroup | |
// | simd | flush | |
- // | simd | ordered | |
+ // | simd | ordered | + (with simd clause) |
// | simd | atomic | |
// | simd | target | |
// | simd | teams | |
// | simd | cancellation | |
// | | point | |
// | simd | cancel | |
+ // | simd | taskloop | |
+ // | simd | taskloop simd | |
+ // | simd | distribute | |
// +------------------+-----------------+------------------------------------+
// | for simd | parallel | |
// | for simd | for | |
@@ -1541,13 +1865,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for simd | taskwait | |
// | for simd | taskgroup | |
// | for simd | flush | |
- // | for simd | ordered | |
+ // | for simd | ordered | + (with simd clause) |
// | for simd | atomic | |
// | for simd | target | |
// | for simd | teams | |
// | for simd | cancellation | |
// | | point | |
// | for simd | cancel | |
+ // | for simd | taskloop | |
+ // | for simd | taskloop simd | |
+ // | for simd | distribute | |
// +------------------+-----------------+------------------------------------+
// | parallel for simd| parallel | |
// | parallel for simd| for | |
@@ -1567,13 +1894,16 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel for simd| taskwait | |
// | parallel for simd| taskgroup | |
// | parallel for simd| flush | |
- // | parallel for simd| ordered | |
+ // | parallel for simd| ordered | + (with simd clause) |
// | parallel for simd| atomic | |
// | parallel for simd| target | |
// | parallel for simd| teams | |
// | parallel for simd| cancellation | |
// | | point | |
// | parallel for simd| cancel | |
+ // | parallel for simd| taskloop | |
+ // | parallel for simd| taskloop simd | |
+ // | parallel for simd| distribute | |
// +------------------+-----------------+------------------------------------+
// | sections | parallel | * |
// | sections | for | + |
@@ -1600,6 +1930,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | sections | cancellation | |
// | | point | ! |
// | sections | cancel | ! |
+ // | sections | taskloop | * |
+ // | sections | taskloop simd | * |
+ // | sections | distribute | |
// +------------------+-----------------+------------------------------------+
// | section | parallel | * |
// | section | for | + |
@@ -1626,6 +1959,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | section | cancellation | |
// | | point | ! |
// | section | cancel | ! |
+ // | section | taskloop | * |
+ // | section | taskloop simd | * |
+ // | section | distribute | |
// +------------------+-----------------+------------------------------------+
// | single | parallel | * |
// | single | for | + |
@@ -1652,6 +1988,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | single | cancellation | |
// | | point | |
// | single | cancel | |
+ // | single | taskloop | * |
+ // | single | taskloop simd | * |
+ // | single | distribute | |
// +------------------+-----------------+------------------------------------+
// | parallel for | parallel | * |
// | parallel for | for | + |
@@ -1678,6 +2017,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel for | cancellation | |
// | | point | ! |
// | parallel for | cancel | ! |
+ // | parallel for | taskloop | * |
+ // | parallel for | taskloop simd | * |
+ // | parallel for | distribute | |
// +------------------+-----------------+------------------------------------+
// | parallel sections| parallel | * |
// | parallel sections| for | + |
@@ -1704,6 +2046,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel sections| cancellation | |
// | | point | ! |
// | parallel sections| cancel | ! |
+ // | parallel sections| taskloop | * |
+ // | parallel sections| taskloop simd | * |
+ // | parallel sections| distribute | |
// +------------------+-----------------+------------------------------------+
// | task | parallel | * |
// | task | for | + |
@@ -1730,6 +2075,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | task | cancellation | |
// | | point | ! |
// | task | cancel | ! |
+ // | task | taskloop | * |
+ // | task | taskloop simd | * |
+ // | task | distribute | |
// +------------------+-----------------+------------------------------------+
// | ordered | parallel | * |
// | ordered | for | + |
@@ -1756,6 +2104,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | ordered | cancellation | |
// | | point | |
// | ordered | cancel | |
+ // | ordered | taskloop | * |
+ // | ordered | taskloop simd | * |
+ // | ordered | distribute | |
// +------------------+-----------------+------------------------------------+
// | atomic | parallel | |
// | atomic | for | |
@@ -1782,6 +2133,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | atomic | cancellation | |
// | | point | |
// | atomic | cancel | |
+ // | atomic | taskloop | |
+ // | atomic | taskloop simd | |
+ // | atomic | distribute | |
// +------------------+-----------------+------------------------------------+
// | target | parallel | * |
// | target | for | * |
@@ -1808,6 +2162,9 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | target | cancellation | |
// | | point | |
// | target | cancel | |
+ // | target | taskloop | * |
+ // | target | taskloop simd | * |
+ // | target | distribute | |
// +------------------+-----------------+------------------------------------+
// | teams | parallel | * |
// | teams | for | + |
@@ -1834,6 +2191,95 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | teams | cancellation | |
// | | point | |
// | teams | cancel | |
+ // | teams | taskloop | + |
+ // | teams | taskloop simd | + |
+ // | teams | distribute | ! |
+ // +------------------+-----------------+------------------------------------+
+ // | taskloop | parallel | * |
+ // | taskloop | for | + |
+ // | taskloop | for simd | + |
+ // | taskloop | master | + |
+ // | taskloop | critical | * |
+ // | taskloop | simd | * |
+ // | taskloop | sections | + |
+ // | taskloop | section | + |
+ // | taskloop | single | + |
+ // | taskloop | parallel for | * |
+ // | taskloop |parallel for simd| * |
+ // | taskloop |parallel sections| * |
+ // | taskloop | task | * |
+ // | taskloop | taskyield | * |
+ // | taskloop | barrier | + |
+ // | taskloop | taskwait | * |
+ // | taskloop | taskgroup | * |
+ // | taskloop | flush | * |
+ // | taskloop | ordered | + |
+ // | taskloop | atomic | * |
+ // | taskloop | target | * |
+ // | taskloop | teams | + |
+ // | taskloop | cancellation | |
+ // | | point | |
+ // | taskloop | cancel | |
+ // | taskloop | taskloop | * |
+ // | taskloop | distribute | |
+ // +------------------+-----------------+------------------------------------+
+ // | taskloop simd | parallel | |
+ // | taskloop simd | for | |
+ // | taskloop simd | for simd | |
+ // | taskloop simd | master | |
+ // | taskloop simd | critical | |
+ // | taskloop simd | simd | |
+ // | taskloop simd | sections | |
+ // | taskloop simd | section | |
+ // | taskloop simd | single | |
+ // | taskloop simd | parallel for | |
+ // | taskloop simd |parallel for simd| |
+ // | taskloop simd |parallel sections| |
+ // | taskloop simd | task | |
+ // | taskloop simd | taskyield | |
+ // | taskloop simd | barrier | |
+ // | taskloop simd | taskwait | |
+ // | taskloop simd | taskgroup | |
+ // | taskloop simd | flush | |
+ // | taskloop simd | ordered | + (with simd clause) |
+ // | taskloop simd | atomic | |
+ // | taskloop simd | target | |
+ // | taskloop simd | teams | |
+ // | taskloop simd | cancellation | |
+ // | | point | |
+ // | taskloop simd | cancel | |
+ // | taskloop simd | taskloop | |
+ // | taskloop simd | taskloop simd | |
+ // | taskloop simd | distribute | |
+ // +------------------+-----------------+------------------------------------+
+ // | distribute | parallel | * |
+ // | distribute | for | * |
+ // | distribute | for simd | * |
+ // | distribute | master | * |
+ // | distribute | critical | * |
+ // | distribute | simd | * |
+ // | distribute | sections | * |
+ // | distribute | section | * |
+ // | distribute | single | * |
+ // | distribute | parallel for | * |
+ // | distribute |parallel for simd| * |
+ // | distribute |parallel sections| * |
+ // | distribute | task | * |
+ // | distribute | taskyield | * |
+ // | distribute | barrier | * |
+ // | distribute | taskwait | * |
+ // | distribute | taskgroup | * |
+ // | distribute | flush | * |
+ // | distribute | ordered | + |
+ // | distribute | atomic | * |
+ // | distribute | target | |
+ // | distribute | teams | |
+ // | distribute | cancellation | + |
+ // | | point | |
+ // | distribute | cancel | + |
+ // | distribute | taskloop | * |
+ // | distribute | taskloop simd | * |
+ // | distribute | distribute | |
// +------------------+-----------------+------------------------------------+
if (Stack->getCurScope()) {
auto ParentRegion = Stack->getParentDirective();
@@ -1843,11 +2289,15 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
NoRecommend,
ShouldBeInParallelRegion,
ShouldBeInOrderedRegion,
- ShouldBeInTargetRegion
+ ShouldBeInTargetRegion,
+ ShouldBeInTeamsRegion
} Recommend = NoRecommend;
- if (isOpenMPSimdDirective(ParentRegion)) {
+ if (isOpenMPSimdDirective(ParentRegion) && CurrentRegion != OMPD_ordered) {
// OpenMP [2.16, Nesting of Regions]
// OpenMP constructs may not be nested inside a simd region.
+ // OpenMP [2.8.1,simd Construct, Restrictions]
+ // An ordered construct with the simd clause is the only OpenMP construct
+ // that can appear in the simd region.
SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_simd);
return true;
}
@@ -1890,16 +2340,19 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// construct-type-clause.
NestingProhibited =
!((CancelRegion == OMPD_parallel && ParentRegion == OMPD_parallel) ||
- (CancelRegion == OMPD_for && ParentRegion == OMPD_for) ||
+ (CancelRegion == OMPD_for &&
+ (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for)) ||
(CancelRegion == OMPD_taskgroup && ParentRegion == OMPD_task) ||
(CancelRegion == OMPD_sections &&
- (ParentRegion == OMPD_section || ParentRegion == OMPD_sections)));
+ (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
+ ParentRegion == OMPD_parallel_sections)));
} else if (CurrentRegion == OMPD_master) {
// OpenMP [2.16, Nesting of Regions]
// A master region may not be closely nested inside a worksharing,
// atomic, or explicit task region.
NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
- ParentRegion == OMPD_task;
+ ParentRegion == OMPD_task ||
+ isOpenMPTaskLoopDirective(ParentRegion);
} else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
// OpenMP [2.16, Nesting of Regions]
// A critical region may not be nested (closely or otherwise) inside a
@@ -1936,7 +2389,8 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
NestingProhibited =
isOpenMPWorksharingDirective(ParentRegion) ||
ParentRegion == OMPD_task || ParentRegion == OMPD_master ||
- ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
+ ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered ||
+ isOpenMPTaskLoopDirective(ParentRegion);
} else if (isOpenMPWorksharingDirective(CurrentRegion) &&
!isOpenMPParallelDirective(CurrentRegion)) {
// OpenMP [2.16, Nesting of Regions]
@@ -1945,7 +2399,8 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
NestingProhibited =
isOpenMPWorksharingDirective(ParentRegion) ||
ParentRegion == OMPD_task || ParentRegion == OMPD_master ||
- ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
+ ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered ||
+ isOpenMPTaskLoopDirective(ParentRegion);
Recommend = ShouldBeInParallelRegion;
} else if (CurrentRegion == OMPD_ordered) {
// OpenMP [2.16, Nesting of Regions]
@@ -1953,9 +2408,14 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// atomic, or explicit task region.
// An ordered region must be closely nested inside a loop region (or
// parallel loop region) with an ordered clause.
+ // OpenMP [2.8.1,simd Construct, Restrictions]
+ // An ordered construct with the simd clause is the only OpenMP construct
+ // that can appear in the simd region.
NestingProhibited = ParentRegion == OMPD_critical ||
ParentRegion == OMPD_task ||
- !Stack->isParentOrderedRegion();
+ isOpenMPTaskLoopDirective(ParentRegion) ||
+ !(isOpenMPSimdDirective(ParentRegion) ||
+ Stack->isParentOrderedRegion());
Recommend = ShouldBeInOrderedRegion;
} else if (isOpenMPTeamsDirective(CurrentRegion)) {
// OpenMP [2.16, Nesting of Regions]
@@ -1970,10 +2430,17 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// distribute, parallel, parallel sections, parallel workshare, and the
// parallel loop and parallel loop SIMD constructs are the only OpenMP
// constructs that can be closely nested in the teams region.
- // TODO: add distribute directive.
- NestingProhibited = !isOpenMPParallelDirective(CurrentRegion);
+ NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
+ !isOpenMPDistributeDirective(CurrentRegion);
Recommend = ShouldBeInParallelRegion;
}
+ if (!NestingProhibited && isOpenMPDistributeDirective(CurrentRegion)) {
+ // OpenMP 4.5 [2.17 Nesting of Regions]
+ // The region associated with the distribute construct must be strictly
+ // nested inside a teams region
+ NestingProhibited = !isOpenMPTeamsDirective(ParentRegion);
+ Recommend = ShouldBeInTeamsRegion;
+ }
if (NestingProhibited) {
SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
<< CloseNesting << getOpenMPDirectiveName(ParentRegion) << Recommend
@@ -1984,6 +2451,88 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
return false;
}
+static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
+ ArrayRef<OMPClause *> Clauses,
+ ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
+ bool ErrorFound = false;
+ unsigned NamedModifiersNumber = 0;
+ SmallVector<const OMPIfClause *, OMPC_unknown + 1> FoundNameModifiers(
+ OMPD_unknown + 1);
+ SmallVector<SourceLocation, 4> NameModifierLoc;
+ for (const auto *C : Clauses) {
+ if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
+ // At most one if clause without a directive-name-modifier can appear on
+ // the directive.
+ OpenMPDirectiveKind CurNM = IC->getNameModifier();
+ if (FoundNameModifiers[CurNM]) {
+ S.Diag(C->getLocStart(), diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
+ << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
+ ErrorFound = true;
+ } else if (CurNM != OMPD_unknown) {
+ NameModifierLoc.push_back(IC->getNameModifierLoc());
+ ++NamedModifiersNumber;
+ }
+ FoundNameModifiers[CurNM] = IC;
+ if (CurNM == OMPD_unknown)
+ continue;
+ // Check if the specified name modifier is allowed for the current
+ // directive.
+ // At most one if clause with the particular directive-name-modifier can
+ // appear on the directive.
+ bool MatchFound = false;
+ for (auto NM : AllowedNameModifiers) {
+ if (CurNM == NM) {
+ MatchFound = true;
+ break;
+ }
+ }
+ if (!MatchFound) {
+ S.Diag(IC->getNameModifierLoc(),
+ diag::err_omp_wrong_if_directive_name_modifier)
+ << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
+ ErrorFound = true;
+ }
+ }
+ }
+ // If any if clause on the directive includes a directive-name-modifier then
+ // all if clauses on the directive must include a directive-name-modifier.
+ if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
+ if (NamedModifiersNumber == AllowedNameModifiers.size()) {
+ S.Diag(FoundNameModifiers[OMPD_unknown]->getLocStart(),
+ diag::err_omp_no_more_if_clause);
+ } else {
+ std::string Values;
+ std::string Sep(", ");
+ unsigned AllowedCnt = 0;
+ unsigned TotalAllowedNum =
+ AllowedNameModifiers.size() - NamedModifiersNumber;
+ for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
+ ++Cnt) {
+ OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
+ if (!FoundNameModifiers[NM]) {
+ Values += "'";
+ Values += getOpenMPDirectiveName(NM);
+ Values += "'";
+ if (AllowedCnt + 2 == TotalAllowedNum)
+ Values += " or ";
+ else if (AllowedCnt + 1 != TotalAllowedNum)
+ Values += Sep;
+ ++AllowedCnt;
+ }
+ }
+ S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getLocStart(),
+ diag::err_omp_unnamed_if_clause)
+ << (TotalAllowedNum > 1) << Values;
+ }
+ for (auto Loc : NameModifierLoc) {
+ S.Diag(Loc, diag::note_omp_previous_named_if_clause);
+ }
+ ErrorFound = true;
+ }
+ return ErrorFound;
+}
+
StmtResult Sema::ActOnOpenMPExecutableDirective(
OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
@@ -2020,10 +2569,12 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
}
}
+ llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
switch (Kind) {
case OMPD_parallel:
Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
+ AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_simd:
Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
@@ -2056,25 +2607,28 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
break;
case OMPD_critical:
- assert(ClausesWithImplicit.empty() &&
- "No clauses are allowed for 'omp critical' directive");
- Res = ActOnOpenMPCriticalDirective(DirName, AStmt, StartLoc, EndLoc);
+ Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
+ StartLoc, EndLoc);
break;
case OMPD_parallel_for:
Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_parallel_for_simd:
Res = ActOnOpenMPParallelForSimdDirective(
ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_parallel_sections:
Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
StartLoc, EndLoc);
+ AllowedNameModifiers.push_back(OMPD_parallel);
break;
case OMPD_task:
Res =
ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
+ AllowedNameModifiers.push_back(OMPD_task);
break;
case OMPD_taskyield:
assert(ClausesWithImplicit.empty() &&
@@ -2108,9 +2662,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
break;
case OMPD_ordered:
- assert(ClausesWithImplicit.empty() &&
- "No clauses are allowed for 'omp ordered' directive");
- Res = ActOnOpenMPOrderedDirective(AStmt, StartLoc, EndLoc);
+ Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
break;
case OMPD_atomic:
Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
@@ -2123,6 +2676,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
case OMPD_target:
Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
+ AllowedNameModifiers.push_back(OMPD_target);
break;
case OMPD_cancellation_point:
assert(ClausesWithImplicit.empty() &&
@@ -2132,11 +2686,30 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
break;
case OMPD_cancel:
- assert(ClausesWithImplicit.empty() &&
- "No clauses are allowed for 'omp cancel' directive");
assert(AStmt == nullptr &&
"No associated statement allowed for 'omp cancel' directive");
- Res = ActOnOpenMPCancelDirective(StartLoc, EndLoc, CancelRegion);
+ Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
+ CancelRegion);
+ AllowedNameModifiers.push_back(OMPD_cancel);
+ break;
+ case OMPD_target_data:
+ Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ AllowedNameModifiers.push_back(OMPD_target_data);
+ break;
+ case OMPD_taskloop:
+ Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_taskloop);
+ break;
+ case OMPD_taskloop_simd:
+ Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_taskloop);
+ break;
+ case OMPD_distribute:
+ Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc, VarsWithInheritedDSA);
break;
case OMPD_threadprivate:
llvm_unreachable("OpenMP Directive is not allowed");
@@ -2148,8 +2721,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
<< P.first << P.second->getSourceRange();
}
- if (!VarsWithInheritedDSA.empty())
- return StmtError();
+ ErrorFound = !VarsWithInheritedDSA.empty() || ErrorFound;
+
+ if (!AllowedNameModifiers.empty())
+ ErrorFound = checkIfClauses(*this, Kind, Clauses, AllowedNameModifiers) ||
+ ErrorFound;
if (ErrorFound)
return StmtError();
@@ -2160,7 +2736,9 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -2171,8 +2749,8 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
getCurFunction()->setHasBranchProtectedScope();
- return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses,
- AStmt);
+ return OMPParallelDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ DSAStack->isCancelRegion());
}
namespace {
@@ -2247,6 +2825,9 @@ public:
Expr *BuildPreCond(Scope *S, Expr *Cond) const;
/// \brief Build reference expression to the counter be used for codegen.
Expr *BuildCounterVar() const;
+ /// \brief Build reference expression to the private counter be used for
+ /// codegen.
+ Expr *BuildPrivateCounterVar() const;
/// \brief Build initization of the counter be used for codegen.
Expr *BuildCounterInit() const;
/// \brief Build step of the counter be used for codegen.
@@ -2261,8 +2842,8 @@ private:
/// \brief Helper to set loop counter variable and its initializer.
bool SetVarAndLB(VarDecl *NewVar, DeclRefExpr *NewVarRefExpr, Expr *NewLB);
/// \brief Helper to set upper bound.
- bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, const SourceRange &SR,
- const SourceLocation &SL);
+ bool SetUB(Expr *NewUB, bool LessOp, bool StrictOp, SourceRange SR,
+ SourceLocation SL);
/// \brief Helper to set loop increment.
bool SetStep(Expr *NewStep, bool Subtract);
};
@@ -2313,8 +2894,7 @@ bool OpenMPIterationSpaceChecker::SetVarAndLB(VarDecl *NewVar,
}
bool OpenMPIterationSpaceChecker::SetUB(Expr *NewUB, bool LessOp, bool StrictOp,
- const SourceRange &SR,
- const SourceLocation &SL) {
+ SourceRange SR, SourceLocation SL) {
// State consistency checking to ensure correct usage.
assert(Var != nullptr && LB != nullptr && UB == nullptr && Step == nullptr &&
!TestIsLessOp && !TestIsStrictOp);
@@ -2410,7 +2990,7 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
} else if (auto DS = dyn_cast<DeclStmt>(S)) {
if (DS->isSingleDecl()) {
if (auto Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
- if (Var->hasInit()) {
+ if (Var->hasInit() && !Var->getType()->isReferenceType()) {
// Accept non-canonical init form here but emit ext. warning.
if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
SemaRef.Diag(S->getLocStart(),
@@ -2630,6 +3210,8 @@ public:
NewVD->setPreviousDeclInSameBlockScope(
VD->isPreviousDeclInSameBlockScope());
VD->getDeclContext()->addHiddenDecl(NewVD);
+ if (VD->hasAttrs())
+ NewVD->setAttrs(VD->getAttrs());
transformedLocalDecl(VD, NewVD);
return NewVD;
}
@@ -2802,7 +3384,21 @@ Expr *OpenMPIterationSpaceChecker::BuildPreCond(Scope *S, Expr *Cond) const {
/// \brief Build reference expression to the counter be used for codegen.
Expr *OpenMPIterationSpaceChecker::BuildCounterVar() const {
- return buildDeclRefExpr(SemaRef, Var, Var->getType(), DefaultLoc);
+ return buildDeclRefExpr(SemaRef, Var, Var->getType().getNonReferenceType(),
+ DefaultLoc);
+}
+
+Expr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const {
+ if (Var && !Var->isInvalidDecl()) {
+ auto Type = Var->getType().getNonReferenceType();
+ auto *PrivateVar =
+ buildVarDecl(SemaRef, DefaultLoc, Type, Var->getName(),
+ Var->hasAttrs() ? &Var->getAttrs() : nullptr);
+ if (PrivateVar->isInvalidDecl())
+ return nullptr;
+ return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
+ }
+ return nullptr;
}
/// \brief Build initization of the counter be used for codegen.
@@ -2820,6 +3416,8 @@ struct LoopIterationSpace {
Expr *NumIterations;
/// \brief The loop counter variable.
Expr *CounterVar;
+ /// \brief Private loop counter variable.
+ Expr *PrivateCounterVar;
/// \brief This is initializer for the initial value of #CounterVar.
Expr *CounterInit;
/// \brief This is step for the #CounterVar used to generate its update:
@@ -2840,14 +3438,13 @@ struct LoopIterationSpace {
void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
assert(getLangOpts().OpenMP && "OpenMP is not active.");
assert(Init && "Expected loop in canonical form.");
- unsigned CollapseIteration = DSAStack->getCollapseNumber();
- if (CollapseIteration > 0 &&
+ unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
+ if (AssociatedLoops > 0 &&
isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
OpenMPIterationSpaceChecker ISC(*this, ForLoc);
- if (!ISC.CheckInit(Init, /*EmitDiags=*/false)) {
+ if (!ISC.CheckInit(Init, /*EmitDiags=*/false))
DSAStack->addLoopControlVariable(ISC.GetLoopVar());
- }
- DSAStack->setCollapseNumber(CollapseIteration - 1);
+ DSAStack->setAssociatedLoops(AssociatedLoops - 1);
}
}
@@ -2856,7 +3453,7 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
static bool CheckOpenMPIterationSpace(
OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
- Expr *NestedLoopCountExpr,
+ Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA,
LoopIterationSpace &ResultIterSpace) {
// OpenMP [2.6, Canonical Loop Form]
@@ -2864,13 +3461,24 @@ static bool CheckOpenMPIterationSpace(
auto For = dyn_cast_or_null<ForStmt>(S);
if (!For) {
SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for)
- << (NestedLoopCountExpr != nullptr) << getOpenMPDirectiveName(DKind)
- << NestedLoopCount << (CurrentNestedLoopCount > 0)
- << CurrentNestedLoopCount;
- if (NestedLoopCount > 1)
- SemaRef.Diag(NestedLoopCountExpr->getExprLoc(),
- diag::note_omp_collapse_expr)
- << NestedLoopCountExpr->getSourceRange();
+ << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
+ << getOpenMPDirectiveName(DKind) << NestedLoopCount
+ << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
+ if (NestedLoopCount > 1) {
+ if (CollapseLoopCountExpr && OrderedLoopCountExpr)
+ SemaRef.Diag(DSA.getConstructLoc(),
+ diag::note_omp_collapse_ordered_expr)
+ << 2 << CollapseLoopCountExpr->getSourceRange()
+ << OrderedLoopCountExpr->getSourceRange();
+ else if (CollapseLoopCountExpr)
+ SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
+ diag::note_omp_collapse_ordered_expr)
+ << 0 << CollapseLoopCountExpr->getSourceRange();
+ else
+ SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
+ diag::note_omp_collapse_ordered_expr)
+ << 1 << OrderedLoopCountExpr->getSourceRange();
+ }
return true;
}
assert(For->getBody());
@@ -2893,7 +3501,7 @@ static bool CheckOpenMPIterationSpace(
// A variable of signed or unsigned integer type.
// For C++, a variable of a random access iterator type.
// For C, a variable of a pointer type.
- auto VarType = Var->getType();
+ auto VarType = Var->getType().getNonReferenceType();
if (!VarType->isDependentType() && !VarType->isIntegerType() &&
!VarType->isPointerType() &&
!(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
@@ -2929,12 +3537,12 @@ static bool CheckOpenMPIterationSpace(
? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)
: OMPC_private;
if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
- DVar.CKind != OMPC_threadprivate && DVar.CKind != PredeterminedCKind) ||
- (isOpenMPWorksharingDirective(DKind) && !isOpenMPSimdDirective(DKind) &&
- DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private &&
- DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_threadprivate)) &&
- ((DVar.CKind != OMPC_private && DVar.CKind != OMPC_threadprivate) ||
- DVar.RefExpr != nullptr)) {
+ DVar.CKind != PredeterminedCKind) ||
+ ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
+ isOpenMPDistributeDirective(DKind)) &&
+ !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
+ DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
+ (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa)
<< getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
<< getOpenMPClauseName(PredeterminedCKind);
@@ -2945,7 +3553,8 @@ static bool CheckOpenMPIterationSpace(
} else if (LoopVarRefExpr != nullptr) {
// Make the loop iteration variable private (for worksharing constructs),
// linear (for simd directives with the only one associated loop) or
- // lastprivate (for simd directives with several collapsed loops).
+ // lastprivate (for simd directives with several collapsed or ordered
+ // loops).
if (DVar.CKind == OMPC_unknown)
DVar = DSA.hasDSA(Var, isOpenMPPrivate, MatchesAlways(),
/*FromParent=*/false);
@@ -2966,8 +3575,11 @@ static bool CheckOpenMPIterationSpace(
// Build the loop's iteration space representation.
ResultIterSpace.PreCond = ISC.BuildPreCond(DSA.getCurScope(), For->getCond());
ResultIterSpace.NumIterations = ISC.BuildNumIterations(
- DSA.getCurScope(), /* LimitedType */ isOpenMPWorksharingDirective(DKind));
+ DSA.getCurScope(), (isOpenMPWorksharingDirective(DKind) ||
+ isOpenMPTaskLoopDirective(DKind) ||
+ isOpenMPDistributeDirective(DKind)));
ResultIterSpace.CounterVar = ISC.BuildCounterVar();
+ ResultIterSpace.PrivateCounterVar = ISC.BuildPrivateCounterVar();
ResultIterSpace.CounterInit = ISC.BuildCounterInit();
ResultIterSpace.CounterStep = ISC.BuildCounterStep();
ResultIterSpace.InitSrcRange = ISC.GetInitSrcRange();
@@ -2978,6 +3590,7 @@ static bool CheckOpenMPIterationSpace(
HasErrors |= (ResultIterSpace.PreCond == nullptr ||
ResultIterSpace.NumIterations == nullptr ||
ResultIterSpace.CounterVar == nullptr ||
+ ResultIterSpace.PrivateCounterVar == nullptr ||
ResultIterSpace.CounterInit == nullptr ||
ResultIterSpace.CounterStep == nullptr);
@@ -3091,17 +3704,33 @@ static bool FitsInto(unsigned Bits, bool Signed, Expr *E, Sema &SemaRef) {
/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
/// number of collapsed loops otherwise.
static unsigned
-CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
- Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA,
+CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
+ Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
+ DSAStackTy &DSA,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA,
OMPLoopDirective::HelperExprs &Built) {
unsigned NestedLoopCount = 1;
- if (NestedLoopCountExpr) {
+ if (CollapseLoopCountExpr) {
// Found 'collapse' clause - calculate collapse number.
llvm::APSInt Result;
- if (NestedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))
+ if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))
NestedLoopCount = Result.getLimitedValue();
}
+ if (OrderedLoopCountExpr) {
+ // Found 'ordered' clause - calculate collapse number.
+ llvm::APSInt Result;
+ if (OrderedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
+ if (Result.getLimitedValue() < NestedLoopCount) {
+ SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
+ diag::err_omp_wrong_ordered_loop_count)
+ << OrderedLoopCountExpr->getSourceRange();
+ SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
+ diag::note_collapse_loop_count)
+ << CollapseLoopCountExpr->getSourceRange();
+ }
+ NestedLoopCount = Result.getLimitedValue();
+ }
+ }
// This is helper routine for loop directives (e.g., 'for', 'simd',
// 'for simd', etc.).
SmallVector<LoopIterationSpace, 4> IterSpaces;
@@ -3109,8 +3738,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true);
for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
- NestedLoopCount, NestedLoopCountExpr,
- VarsWithImplicitDSA, IterSpaces[Cnt]))
+ NestedLoopCount, CollapseLoopCountExpr,
+ OrderedLoopCountExpr, VarsWithImplicitDSA,
+ IterSpaces[Cnt]))
return 0;
// Move on to the next nested for loop, or to the loop body.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -3127,11 +3757,12 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
// An example of what is generated for the following code:
//
- // #pragma omp simd collapse(2)
+ // #pragma omp simd collapse(2) ordered(2)
// for (i = 0; i < NI; ++i)
- // for (j = J0; j < NJ; j+=2) {
- // <loop body>
- // }
+ // for (k = 0; k < NK; ++k)
+ // for (j = J0; j < NJ; j+=2) {
+ // <loop body>
+ // }
//
// We generate the code below.
// Note: the loop body may be outlined in CodeGen.
@@ -3254,7 +3885,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
QualType VType = LastIteration.get()->getType();
// Build variables passed into runtime, nesessary for worksharing directives.
ExprResult LB, UB, IL, ST, EUB;
- if (isOpenMPWorksharingDirective(DKind)) {
+ if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
+ isOpenMPDistributeDirective(DKind)) {
// Lower bound variable, initialized with zero.
VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
@@ -3302,7 +3934,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
{
VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.iv");
IV = buildDeclRefExpr(SemaRef, IVDecl, VType, InitLoc);
- Expr *RHS = isOpenMPWorksharingDirective(DKind)
+ Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
+ isOpenMPTaskLoopDirective(DKind) ||
+ isOpenMPDistributeDirective(DKind))
? LB.get()
: SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
@@ -3312,7 +3946,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
// Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops.
SourceLocation CondLoc;
ExprResult Cond =
- isOpenMPWorksharingDirective(DKind)
+ (isOpenMPWorksharingDirective(DKind) ||
+ isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind))
? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get())
: SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
NumIterations.get());
@@ -3332,7 +3967,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
// Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
// Used for directives with static scheduling.
ExprResult NextLB, NextUB;
- if (isOpenMPWorksharingDirective(DKind)) {
+ if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
+ isOpenMPDistributeDirective(DKind)) {
// LB + ST
NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
if (!NextLB.isUsable())
@@ -3437,6 +4073,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
}
// Save results
Built.Counters[Cnt] = IS.CounterVar;
+ Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
Built.Inits[Cnt] = Init.get();
Built.Updates[Cnt] = Update.get();
Built.Finals[Cnt] = Final.get();
@@ -3467,26 +4104,60 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
return NestedLoopCount;
}
-static Expr *GetCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
- auto &&CollapseFilter = [](const OMPClause *C) -> bool {
- return C->getClauseKind() == OMPC_collapse;
- };
- OMPExecutableDirective::filtered_clause_iterator<decltype(CollapseFilter)> I(
- Clauses, std::move(CollapseFilter));
- if (I)
- return cast<OMPCollapseClause>(*I)->getNumForLoops();
+static Expr *getCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
+ auto CollapseClauses =
+ OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
+ if (CollapseClauses.begin() != CollapseClauses.end())
+ return (*CollapseClauses.begin())->getNumForLoops();
+ return nullptr;
+}
+
+static Expr *getOrderedNumberExpr(ArrayRef<OMPClause *> Clauses) {
+ auto OrderedClauses =
+ OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
+ if (OrderedClauses.begin() != OrderedClauses.end())
+ return (*OrderedClauses.begin())->getNumForLoops();
return nullptr;
}
+static bool checkSimdlenSafelenValues(Sema &S, const Expr *Simdlen,
+ const Expr *Safelen) {
+ llvm::APSInt SimdlenRes, SafelenRes;
+ if (Simdlen->isValueDependent() || Simdlen->isTypeDependent() ||
+ Simdlen->isInstantiationDependent() ||
+ Simdlen->containsUnexpandedParameterPack())
+ return false;
+ if (Safelen->isValueDependent() || Safelen->isTypeDependent() ||
+ Safelen->isInstantiationDependent() ||
+ Safelen->containsUnexpandedParameterPack())
+ return false;
+ Simdlen->EvaluateAsInt(SimdlenRes, S.Context);
+ Safelen->EvaluateAsInt(SafelenRes, S.Context);
+ // OpenMP 4.1 [2.8.1, simd Construct, Restrictions]
+ // If both simdlen and safelen clauses are specified, the value of the simdlen
+ // parameter must be less than or equal to the value of the safelen parameter.
+ if (SimdlenRes > SafelenRes) {
+ S.Diag(Simdlen->getExprLoc(), diag::err_omp_wrong_simdlen_safelen_values)
+ << Simdlen->getSourceRange() << Safelen->getSourceRange();
+ return true;
+ }
+ return false;
+}
+
StmtResult Sema::ActOnOpenMPSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
OMPLoopDirective::HelperExprs B;
- // In presence of clause 'collapse', it will define the nested loops number.
- unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_simd, GetCollapseNumberExpr(Clauses), AStmt, *this,
- *DSAStack, VarsWithImplicitDSA, B);
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount = CheckOpenMPLoop(
+ OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
+ AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -3503,6 +4174,24 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
}
}
+ // OpenMP 4.1 [2.8.1, simd Construct, Restrictions]
+ // If both simdlen and safelen clauses are specified, the value of the simdlen
+ // parameter must be less than or equal to the value of the safelen parameter.
+ OMPSafelenClause *Safelen = nullptr;
+ OMPSimdlenClause *Simdlen = nullptr;
+ for (auto *Clause : Clauses) {
+ if (Clause->getClauseKind() == OMPC_safelen)
+ Safelen = cast<OMPSafelenClause>(Clause);
+ else if (Clause->getClauseKind() == OMPC_simdlen)
+ Simdlen = cast<OMPSimdlenClause>(Clause);
+ if (Safelen && Simdlen)
+ break;
+ }
+ if (Simdlen && Safelen &&
+ checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(),
+ Safelen->getSafelen()))
+ return StmtError();
+
getCurFunction()->setHasBranchProtectedScope();
return OMPSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
@@ -3512,31 +4201,52 @@ StmtResult Sema::ActOnOpenMPForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
OMPLoopDirective::HelperExprs B;
- // In presence of clause 'collapse', it will define the nested loops number.
- unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_for, GetCollapseNumberExpr(Clauses), AStmt, *this,
- *DSAStack, VarsWithImplicitDSA, B);
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount = CheckOpenMPLoop(
+ OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
+ AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp for loop exprs were not built");
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope))
+ return StmtError();
+ }
+ }
+
getCurFunction()->setHasBranchProtectedScope();
return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
- Clauses, AStmt, B);
+ Clauses, AStmt, B, DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
OMPLoopDirective::HelperExprs B;
- // In presence of clause 'collapse', it will define the nested loops number.
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_for_simd, GetCollapseNumberExpr(Clauses), AStmt,
- *this, *DSAStack, VarsWithImplicitDSA, B);
+ CheckOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
+ getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -3553,6 +4263,24 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(
}
}
+ // OpenMP 4.1 [2.8.1, simd Construct, Restrictions]
+ // If both simdlen and safelen clauses are specified, the value of the simdlen
+ // parameter must be less than or equal to the value of the safelen parameter.
+ OMPSafelenClause *Safelen = nullptr;
+ OMPSimdlenClause *Simdlen = nullptr;
+ for (auto *Clause : Clauses) {
+ if (Clause->getClauseKind() == OMPC_safelen)
+ Safelen = cast<OMPSafelenClause>(Clause);
+ else if (Clause->getClauseKind() == OMPC_simdlen)
+ Simdlen = cast<OMPSimdlenClause>(Clause);
+ if (Safelen && Simdlen)
+ break;
+ }
+ if (Simdlen && Safelen &&
+ checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(),
+ Safelen->getSafelen()))
+ return StmtError();
+
getCurFunction()->setHasBranchProtectedScope();
return OMPForSimdDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
Clauses, AStmt, B);
@@ -3562,23 +4290,28 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
auto BaseStmt = AStmt;
while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
BaseStmt = CS->getCapturedStmt();
if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
auto S = C->children();
- if (!S)
+ if (S.begin() == S.end())
return StmtError();
// All associated statements must be '#pragma omp section' except for
// the first one.
- for (Stmt *SectionStmt : ++S) {
+ for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) {
if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
if (SectionStmt)
Diag(SectionStmt->getLocStart(),
diag::err_omp_sections_substmt_not_section);
return StmtError();
}
+ cast<OMPSectionDirective>(SectionStmt)
+ ->setHasCancel(DSAStack->isCancelRegion());
}
} else {
Diag(AStmt->getLocStart(), diag::err_omp_sections_not_compound_stmt);
@@ -3587,25 +4320,33 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
getCurFunction()->setHasBranchProtectedScope();
- return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses,
- AStmt);
+ return OMPSectionsDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
+ DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
- return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt);
+ return OMPSectionDirective::Create(Context, StartLoc, EndLoc, AStmt,
+ DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
@@ -3632,30 +4373,81 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
}
-StmtResult
-Sema::ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+StmtResult Sema::ActOnOpenMPCriticalDirective(
+ const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ bool ErrorFound = false;
+ llvm::APSInt Hint;
+ SourceLocation HintLoc;
+ bool DependentHint = false;
+ for (auto *C : Clauses) {
+ if (C->getClauseKind() == OMPC_hint) {
+ if (!DirName.getName()) {
+ Diag(C->getLocStart(), diag::err_omp_hint_clause_no_name);
+ ErrorFound = true;
+ }
+ Expr *E = cast<OMPHintClause>(C)->getHint();
+ if (E->isTypeDependent() || E->isValueDependent() ||
+ E->isInstantiationDependent())
+ DependentHint = true;
+ else {
+ Hint = E->EvaluateKnownConstInt(Context);
+ HintLoc = C->getLocStart();
+ }
+ }
+ }
+ if (ErrorFound)
+ return StmtError();
+ auto Pair = DSAStack->getCriticalWithHint(DirName);
+ if (Pair.first && DirName.getName() && !DependentHint) {
+ if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
+ Diag(StartLoc, diag::err_omp_critical_with_hint);
+ if (HintLoc.isValid()) {
+ Diag(HintLoc, diag::note_omp_critical_hint_here)
+ << 0 << Hint.toString(/*Radix=*/10, /*Signed=*/false);
+ } else
+ Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
+ if (auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
+ Diag(C->getLocStart(), diag::note_omp_critical_hint_here)
+ << 1
+ << C->getHint()->EvaluateKnownConstInt(Context).toString(
+ /*Radix=*/10, /*Signed=*/false);
+ } else
+ Diag(Pair.first->getLocStart(), diag::note_omp_critical_no_hint) << 1;
+ }
+ }
getCurFunction()->setHasBranchProtectedScope();
- return OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
- AStmt);
+ auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
+ Clauses, AStmt);
+ if (!Pair.first && DirName.getName() && !DependentHint)
+ DSAStack->addCriticalWithHint(Dir, Hint);
+ return Dir;
}
StmtResult Sema::ActOnOpenMPParallelForDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -3665,26 +4457,41 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
CS->getCapturedDecl()->setNothrow();
OMPLoopDirective::HelperExprs B;
- // In presence of clause 'collapse', it will define the nested loops number.
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_parallel_for, GetCollapseNumberExpr(Clauses), AStmt,
- *this, *DSAStack, VarsWithImplicitDSA, B);
+ CheckOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
+ getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
assert((CurContext->isDependentContext() || B.builtAll()) &&
"omp parallel for loop exprs were not built");
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope))
+ return StmtError();
+ }
+ }
+
getCurFunction()->setHasBranchProtectedScope();
return OMPParallelForDirective::Create(Context, StartLoc, EndLoc,
- NestedLoopCount, Clauses, AStmt, B);
+ NestedLoopCount, Clauses, AStmt, B,
+ DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc,
llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -3694,10 +4501,12 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
CS->getCapturedDecl()->setNothrow();
OMPLoopDirective::HelperExprs B;
- // In presence of clause 'collapse', it will define the nested loops number.
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
unsigned NestedLoopCount =
- CheckOpenMPLoop(OMPD_parallel_for_simd, GetCollapseNumberExpr(Clauses),
- AStmt, *this, *DSAStack, VarsWithImplicitDSA, B);
+ CheckOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
+ getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
if (NestedLoopCount == 0)
return StmtError();
@@ -3711,6 +4520,24 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
}
}
+ // OpenMP 4.1 [2.8.1, simd Construct, Restrictions]
+ // If both simdlen and safelen clauses are specified, the value of the simdlen
+ // parameter must be less than or equal to the value of the safelen parameter.
+ OMPSafelenClause *Safelen = nullptr;
+ OMPSimdlenClause *Simdlen = nullptr;
+ for (auto *Clause : Clauses) {
+ if (Clause->getClauseKind() == OMPC_safelen)
+ Safelen = cast<OMPSafelenClause>(Clause);
+ else if (Clause->getClauseKind() == OMPC_simdlen)
+ Simdlen = cast<OMPSimdlenClause>(Clause);
+ if (Safelen && Simdlen)
+ break;
+ }
+ if (Simdlen && Safelen &&
+ checkSimdlenSafelenValues(*this, Simdlen->getSimdlen(),
+ Safelen->getSafelen()))
+ return StmtError();
+
getCurFunction()->setHasBranchProtectedScope();
return OMPParallelForSimdDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
@@ -3720,23 +4547,28 @@ StmtResult
Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
auto BaseStmt = AStmt;
while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
BaseStmt = CS->getCapturedStmt();
if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
auto S = C->children();
- if (!S)
+ if (S.begin() == S.end())
return StmtError();
// All associated statements must be '#pragma omp section' except for
// the first one.
- for (Stmt *SectionStmt : ++S) {
+ for (Stmt *SectionStmt : llvm::make_range(std::next(S.begin()), S.end())) {
if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
if (SectionStmt)
Diag(SectionStmt->getLocStart(),
diag::err_omp_parallel_sections_substmt_not_section);
return StmtError();
}
+ cast<OMPSectionDirective>(SectionStmt)
+ ->setHasCancel(DSAStack->isCancelRegion());
}
} else {
Diag(AStmt->getLocStart(),
@@ -3746,14 +4578,16 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
getCurFunction()->setHasBranchProtectedScope();
- return OMPParallelSectionsDirective::Create(Context, StartLoc, EndLoc,
- Clauses, AStmt);
+ return OMPParallelSectionsDirective::Create(
+ Context, StartLoc, EndLoc, Clauses, AStmt, DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -3764,7 +4598,8 @@ StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
getCurFunction()->setHasBranchProtectedScope();
- return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
+ return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ DSAStack->isCancelRegion());
}
StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
@@ -3785,7 +4620,10 @@ StmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
StmtResult Sema::ActOnOpenMPTaskgroupDirective(Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
getCurFunction()->setHasBranchProtectedScope();
@@ -3799,14 +4637,79 @@ StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
}
-StmtResult Sema::ActOnOpenMPOrderedDirective(Stmt *AStmt,
+StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ OMPClause *DependFound = nullptr;
+ OMPClause *DependSourceClause = nullptr;
+ OMPClause *DependSinkClause = nullptr;
+ bool ErrorFound = false;
+ OMPThreadsClause *TC = nullptr;
+ OMPSIMDClause *SC = nullptr;
+ for (auto *C : Clauses) {
+ if (auto *DC = dyn_cast<OMPDependClause>(C)) {
+ DependFound = C;
+ if (DC->getDependencyKind() == OMPC_DEPEND_source) {
+ if (DependSourceClause) {
+ Diag(C->getLocStart(), diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(OMPD_ordered)
+ << getOpenMPClauseName(OMPC_depend) << 2;
+ ErrorFound = true;
+ } else
+ DependSourceClause = C;
+ if (DependSinkClause) {
+ Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed)
+ << 0;
+ ErrorFound = true;
+ }
+ } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) {
+ if (DependSourceClause) {
+ Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed)
+ << 1;
+ ErrorFound = true;
+ }
+ DependSinkClause = C;
+ }
+ } else if (C->getClauseKind() == OMPC_threads)
+ TC = cast<OMPThreadsClause>(C);
+ else if (C->getClauseKind() == OMPC_simd)
+ SC = cast<OMPSIMDClause>(C);
+ }
+ if (!ErrorFound && !SC &&
+ isOpenMPSimdDirective(DSAStack->getParentDirective())) {
+ // OpenMP [2.8.1,simd Construct, Restrictions]
+ // An ordered construct with the simd clause is the only OpenMP construct
+ // that can appear in the simd region.
+ Diag(StartLoc, diag::err_omp_prohibited_region_simd);
+ ErrorFound = true;
+ } else if (DependFound && (TC || SC)) {
+ Diag(DependFound->getLocStart(), diag::err_omp_depend_clause_thread_simd)
+ << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
+ ErrorFound = true;
+ } else if (DependFound && !DSAStack->getParentOrderedRegionParam()) {
+ Diag(DependFound->getLocStart(),
+ diag::err_omp_ordered_directive_without_param);
+ ErrorFound = true;
+ } else if (TC || Clauses.empty()) {
+ if (auto *Param = DSAStack->getParentOrderedRegionParam()) {
+ SourceLocation ErrLoc = TC ? TC->getLocStart() : StartLoc;
+ Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
+ << (TC != nullptr);
+ Diag(Param->getLocStart(), diag::note_omp_ordered_param);
+ ErrorFound = true;
+ }
+ }
+ if ((!AStmt && !DependFound) || ErrorFound)
+ return StmtError();
- getCurFunction()->setHasBranchProtectedScope();
+ if (AStmt) {
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, AStmt);
+ getCurFunction()->setHasBranchProtectedScope();
+ }
+
+ return OMPOrderedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
namespace {
@@ -4006,7 +4909,7 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
NoteLoc = AtomicUnaryOp->getOperatorLoc();
NoteRange = SourceRange(NoteLoc, NoteLoc);
}
- } else {
+ } else if (!AtomicBody->isInstantiationDependent()) {
ErrorFound = NotABinaryOrUnaryExpression;
NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
NoteRange = ErrorRange = AtomicBody->getSourceRange();
@@ -4053,7 +4956,9 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
auto CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -4150,7 +5055,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
NoteLoc = NotScalarExpr->getExprLoc();
NoteRange = NotScalarExpr->getSourceRange();
}
- } else {
+ } else if (!AtomicBody->isInstantiationDependent()) {
ErrorFound = NotAnAssignmentOp;
ErrorLoc = AtomicBody->getExprLoc();
ErrorRange = AtomicBody->getSourceRange();
@@ -4211,7 +5116,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
NoteLoc = NotScalarExpr->getExprLoc();
NoteRange = NotScalarExpr->getSourceRange();
}
- } else {
+ } else if (!AtomicBody->isInstantiationDependent()) {
ErrorFound = NotAnAssignmentOp;
ErrorLoc = AtomicBody->getExprLoc();
ErrorRange = AtomicBody->getSourceRange();
@@ -4289,7 +5194,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
UE = Checker.getUpdateExpr();
IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
IsPostfixUpdate = Checker.isPostfixUpdate();
- } else {
+ } else if (!AtomicBody->isInstantiationDependent()) {
ErrorLoc = AtomicBody->getExprLoc();
ErrorRange = AtomicBody->getSourceRange();
NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
@@ -4396,46 +5301,54 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
}
if (!IsUpdateExprFound) {
// { v = x; x = expr; }
- auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
- if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
- ErrorFound = NotAnAssignmentOp;
- NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
- : First->getLocStart();
- NoteRange = ErrorRange = FirstBinOp
- ? FirstBinOp->getSourceRange()
- : SourceRange(ErrorLoc, ErrorLoc);
- } else {
- auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
- if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
+ auto *FirstExpr = dyn_cast<Expr>(First);
+ auto *SecondExpr = dyn_cast<Expr>(Second);
+ if (!FirstExpr || !SecondExpr ||
+ !(FirstExpr->isInstantiationDependent() ||
+ SecondExpr->isInstantiationDependent())) {
+ auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
+ if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
ErrorFound = NotAnAssignmentOp;
- NoteLoc = ErrorLoc = SecondBinOp ? SecondBinOp->getOperatorLoc()
- : Second->getLocStart();
- NoteRange = ErrorRange = SecondBinOp
- ? SecondBinOp->getSourceRange()
+ NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
+ : First->getLocStart();
+ NoteRange = ErrorRange = FirstBinOp
+ ? FirstBinOp->getSourceRange()
: SourceRange(ErrorLoc, ErrorLoc);
} else {
- auto *PossibleXRHSInFirst =
- FirstBinOp->getRHS()->IgnoreParenImpCasts();
- auto *PossibleXLHSInSecond =
- SecondBinOp->getLHS()->IgnoreParenImpCasts();
- llvm::FoldingSetNodeID X1Id, X2Id;
- PossibleXRHSInFirst->Profile(X1Id, Context, /*Canonical=*/true);
- PossibleXLHSInSecond->Profile(X2Id, Context,
- /*Canonical=*/true);
- IsUpdateExprFound = X1Id == X2Id;
- if (IsUpdateExprFound) {
- V = FirstBinOp->getLHS();
- X = SecondBinOp->getLHS();
- E = SecondBinOp->getRHS();
- UE = nullptr;
- IsXLHSInRHSPart = false;
- IsPostfixUpdate = true;
+ auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
+ if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
+ ErrorFound = NotAnAssignmentOp;
+ NoteLoc = ErrorLoc = SecondBinOp
+ ? SecondBinOp->getOperatorLoc()
+ : Second->getLocStart();
+ NoteRange = ErrorRange =
+ SecondBinOp ? SecondBinOp->getSourceRange()
+ : SourceRange(ErrorLoc, ErrorLoc);
} else {
- ErrorFound = NotASpecificExpression;
- ErrorLoc = FirstBinOp->getExprLoc();
- ErrorRange = FirstBinOp->getSourceRange();
- NoteLoc = SecondBinOp->getLHS()->getExprLoc();
- NoteRange = SecondBinOp->getRHS()->getSourceRange();
+ auto *PossibleXRHSInFirst =
+ FirstBinOp->getRHS()->IgnoreParenImpCasts();
+ auto *PossibleXLHSInSecond =
+ SecondBinOp->getLHS()->IgnoreParenImpCasts();
+ llvm::FoldingSetNodeID X1Id, X2Id;
+ PossibleXRHSInFirst->Profile(X1Id, Context,
+ /*Canonical=*/true);
+ PossibleXLHSInSecond->Profile(X2Id, Context,
+ /*Canonical=*/true);
+ IsUpdateExprFound = X1Id == X2Id;
+ if (IsUpdateExprFound) {
+ V = FirstBinOp->getLHS();
+ X = SecondBinOp->getLHS();
+ E = SecondBinOp->getRHS();
+ UE = nullptr;
+ IsXLHSInRHSPart = false;
+ IsPostfixUpdate = true;
+ } else {
+ ErrorFound = NotASpecificExpression;
+ ErrorLoc = FirstBinOp->getExprLoc();
+ ErrorRange = FirstBinOp->getSourceRange();
+ NoteLoc = SecondBinOp->getLHS()->getExprLoc();
+ NoteRange = SecondBinOp->getRHS()->getSourceRange();
+ }
}
}
}
@@ -4474,7 +5387,16 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
// OpenMP [2.16, Nesting of Regions]
// If specified, a teams construct must be contained within a target
@@ -4511,10 +5433,27 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
return OMPTargetDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
}
+StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPTargetDataDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ AStmt);
+}
+
StmtResult Sema::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
- assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ if (!AStmt)
+ return StmtError();
+
CapturedStmt *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -4550,7 +5489,8 @@ Sema::ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
CancelRegion);
}
-StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc,
+StmtResult Sema::ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
SourceLocation EndLoc,
OpenMPDirectiveKind CancelRegion) {
if (CancelRegion != OMPD_parallel && CancelRegion != OMPD_for &&
@@ -4567,7 +5507,123 @@ StmtResult Sema::ActOnOpenMPCancelDirective(SourceLocation StartLoc,
Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
return StmtError();
}
- return OMPCancelDirective::Create(Context, StartLoc, EndLoc, CancelRegion);
+ DSAStack->setParentCancelRegion(/*Cancel=*/true);
+ return OMPCancelDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ CancelRegion);
+}
+
+static bool checkGrainsizeNumTasksClauses(Sema &S,
+ ArrayRef<OMPClause *> Clauses) {
+ OMPClause *PrevClause = nullptr;
+ bool ErrorFound = false;
+ for (auto *C : Clauses) {
+ if (C->getClauseKind() == OMPC_grainsize ||
+ C->getClauseKind() == OMPC_num_tasks) {
+ if (!PrevClause)
+ PrevClause = C;
+ else if (PrevClause->getClauseKind() != C->getClauseKind()) {
+ S.Diag(C->getLocStart(),
+ diag::err_omp_grainsize_num_tasks_mutually_exclusive)
+ << getOpenMPClauseName(C->getClauseKind())
+ << getOpenMPClauseName(PrevClause->getClauseKind());
+ S.Diag(PrevClause->getLocStart(),
+ diag::note_omp_previous_grainsize_num_tasks)
+ << getOpenMPClauseName(PrevClause->getClauseKind());
+ ErrorFound = true;
+ }
+ }
+ }
+ return ErrorFound;
+}
+
+StmtResult Sema::ActOnOpenMPTaskLoopDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
+ /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp for loop exprs were not built");
+
+ // OpenMP, [2.9.2 taskloop Construct, Restrictions]
+ // The grainsize clause and num_tasks clause are mutually exclusive and may
+ // not appear on the same taskloop directive.
+ if (checkGrainsizeNumTasksClauses(*this, Clauses))
+ return StmtError();
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPTaskLoopDirective::Create(Context, StartLoc, EndLoc,
+ NestedLoopCount, Clauses, AStmt, B);
+}
+
+StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' or 'ordered' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
+ /*OrderedLoopCountExpr=*/nullptr, AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp for loop exprs were not built");
+
+ // OpenMP, [2.9.2 taskloop Construct, Restrictions]
+ // The grainsize clause and num_tasks clause are mutually exclusive and may
+ // not appear on the same taskloop directive.
+ if (checkGrainsizeNumTasksClauses(*this, Clauses))
+ return StmtError();
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPTaskLoopSimdDirective::Create(Context, StartLoc, EndLoc,
+ NestedLoopCount, Clauses, AStmt, B);
+}
+
+StmtResult Sema::ActOnOpenMPDistributeDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, AStmt,
+ *this, *DSAStack, VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp for loop exprs were not built");
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPDistributeDirective::Create(Context, StartLoc, EndLoc,
+ NestedLoopCount, Clauses, AStmt, B);
}
OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
@@ -4576,9 +5632,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation EndLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
- case OMPC_if:
- Res = ActOnOpenMPIfClause(Expr, StartLoc, LParenLoc, EndLoc);
- break;
case OMPC_final:
Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
@@ -4588,9 +5641,37 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_safelen:
Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_simdlen:
+ Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_collapse:
Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_ordered:
+ Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
+ break;
+ case OMPC_device:
+ Res = ActOnOpenMPDeviceClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_num_teams:
+ Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_thread_limit:
+ Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_priority:
+ Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_grainsize:
+ Res = ActOnOpenMPGrainsizeClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_num_tasks:
+ Res = ActOnOpenMPNumTasksClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_hint:
+ Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_if:
case OMPC_default:
case OMPC_proc_bind:
case OMPC_schedule:
@@ -4603,7 +5684,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
- case OMPC_ordered:
case OMPC_nowait:
case OMPC_untied:
case OMPC_mergeable:
@@ -4615,14 +5695,21 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_capture:
case OMPC_seq_cst:
case OMPC_depend:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_map:
+ case OMPC_nogroup:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
return Res;
}
-OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
+OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
+ Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
+ SourceLocation NameModifierLoc,
+ SourceLocation ColonLoc,
SourceLocation EndLoc) {
Expr *ValExpr = Condition;
if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
@@ -4636,7 +5723,8 @@ OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
ValExpr = Val.get();
}
- return new (Context) OMPIfClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+ return new (Context) OMPIfClause(NameModifier, ValExpr, StartLoc, LParenLoc,
+ NameModifierLoc, ColonLoc, EndLoc);
}
OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
@@ -4701,38 +5789,52 @@ ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
}
+static bool IsNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef,
+ OpenMPClauseKind CKind,
+ bool StrictlyPositive) {
+ if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
+ !ValExpr->isInstantiationDependent()) {
+ SourceLocation Loc = ValExpr->getExprLoc();
+ ExprResult Value =
+ SemaRef.PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
+ if (Value.isInvalid())
+ return false;
+
+ ValExpr = Value.get();
+ // The expression must evaluate to a non-negative integer value.
+ llvm::APSInt Result;
+ if (ValExpr->isIntegerConstantExpr(Result, SemaRef.Context) &&
+ Result.isSigned() &&
+ !((!StrictlyPositive && Result.isNonNegative()) ||
+ (StrictlyPositive && Result.isStrictlyPositive()))) {
+ SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
+ << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
+ << ValExpr->getSourceRange();
+ return false;
+ }
+ }
+ return true;
+}
+
OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
Expr *ValExpr = NumThreads;
- if (!NumThreads->isValueDependent() && !NumThreads->isTypeDependent() &&
- !NumThreads->containsUnexpandedParameterPack()) {
- SourceLocation NumThreadsLoc = NumThreads->getLocStart();
- ExprResult Val =
- PerformOpenMPImplicitIntegerConversion(NumThreadsLoc, NumThreads);
- if (Val.isInvalid())
- return nullptr;
- ValExpr = Val.get();
-
- // OpenMP [2.5, Restrictions]
- // The num_threads expression must evaluate to a positive integer value.
- llvm::APSInt Result;
- if (ValExpr->isIntegerConstantExpr(Result, Context) && Result.isSigned() &&
- !Result.isStrictlyPositive()) {
- Diag(NumThreadsLoc, diag::err_omp_negative_expression_in_clause)
- << "num_threads" << NumThreads->getSourceRange();
- return nullptr;
- }
- }
+ // OpenMP [2.5, Restrictions]
+ // The num_threads expression must evaluate to a positive integer value.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_threads,
+ /*StrictlyPositive=*/true))
+ return nullptr;
return new (Context)
OMPNumThreadsClause(ValExpr, StartLoc, LParenLoc, EndLoc);
}
ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
- OpenMPClauseKind CKind) {
+ OpenMPClauseKind CKind,
+ bool StrictlyPositive) {
if (!E)
return ExprError();
if (E->isValueDependent() || E->isTypeDependent() ||
@@ -4742,9 +5844,11 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
ExprResult ICE = VerifyIntegerConstantExpression(E, &Result);
if (ICE.isInvalid())
return ExprError();
- if (!Result.isStrictlyPositive()) {
+ if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
+ (!StrictlyPositive && !Result.isNonNegative())) {
Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
- << getOpenMPClauseName(CKind) << E->getSourceRange();
+ << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
+ << E->getSourceRange();
return ExprError();
}
if (CKind == OMPC_aligned && !Result.isPowerOf2()) {
@@ -4752,9 +5856,10 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
<< E->getSourceRange();
return ExprError();
}
- if (CKind == OMPC_collapse) {
- DSAStack->setCollapseNumber(Result.getExtValue());
- }
+ if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
+ DSAStack->setAssociatedLoops(Result.getExtValue());
+ else if (CKind == OMPC_ordered)
+ DSAStack->setAssociatedLoops(Result.getExtValue());
return ICE;
}
@@ -4771,6 +5876,19 @@ OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
}
+OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ // OpenMP [2.8.1, simd construct, Description]
+ // The parameter of the simdlen clause must be a constant
+ // positive integer expression.
+ ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
+ if (Simdlen.isInvalid())
+ return nullptr;
+ return new (Context)
+ OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -4788,6 +5906,28 @@ OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
}
+OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ SourceLocation LParenLoc,
+ Expr *NumForLoops) {
+ // OpenMP [2.7.1, loop construct, Description]
+ // OpenMP [2.8.1, simd construct, Description]
+ // OpenMP [2.9.6, distribute construct, Description]
+ // The parameter of the ordered clause must be a constant
+ // positive integer expression if any.
+ if (NumForLoops && LParenLoc.isValid()) {
+ ExprResult NumForLoopsResult =
+ VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
+ if (NumForLoopsResult.isInvalid())
+ return nullptr;
+ NumForLoops = NumForLoopsResult.get();
+ } else
+ NumForLoops = nullptr;
+ DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops);
+ return new (Context)
+ OMPOrderedClause(NumForLoops, StartLoc, LParenLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPSimpleClause(
OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
@@ -4807,6 +5947,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
case OMPC_schedule:
case OMPC_private:
@@ -4830,39 +5971,58 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_capture:
case OMPC_seq_cst:
case OMPC_depend:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_map:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
return Res;
}
+static std::string
+getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last,
+ ArrayRef<unsigned> Exclude = llvm::None) {
+ std::string Values;
+ unsigned Bound = Last >= 2 ? Last - 2 : 0;
+ unsigned Skipped = Exclude.size();
+ auto S = Exclude.begin(), E = Exclude.end();
+ for (unsigned i = First; i < Last; ++i) {
+ if (std::find(S, E, i) != E) {
+ --Skipped;
+ continue;
+ }
+ Values += "'";
+ Values += getOpenMPSimpleClauseTypeName(K, i);
+ Values += "'";
+ if (i == Bound - Skipped)
+ Values += " or ";
+ else if (i != Bound + 1 - Skipped)
+ Values += ", ";
+ }
+ return Values;
+}
+
OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
SourceLocation KindKwLoc,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
if (Kind == OMPC_DEFAULT_unknown) {
- std::string Values;
static_assert(OMPC_DEFAULT_unknown > 0,
"OMPC_DEFAULT_unknown not greater than 0");
- std::string Sep(", ");
- for (unsigned i = 0; i < OMPC_DEFAULT_unknown; ++i) {
- Values += "'";
- Values += getOpenMPSimpleClauseTypeName(OMPC_default, i);
- Values += "'";
- switch (i) {
- case OMPC_DEFAULT_unknown - 2:
- Values += " or ";
- break;
- case OMPC_DEFAULT_unknown - 1:
- break;
- default:
- Values += Sep;
- break;
- }
- }
Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
- << Values << getOpenMPClauseName(OMPC_default);
+ << getListOfPossibleValues(OMPC_default, /*First=*/0,
+ /*Last=*/OMPC_DEFAULT_unknown)
+ << getOpenMPClauseName(OMPC_default);
return nullptr;
}
switch (Kind) {
@@ -4886,25 +6046,10 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
if (Kind == OMPC_PROC_BIND_unknown) {
- std::string Values;
- std::string Sep(", ");
- for (unsigned i = 0; i < OMPC_PROC_BIND_unknown; ++i) {
- Values += "'";
- Values += getOpenMPSimpleClauseTypeName(OMPC_proc_bind, i);
- Values += "'";
- switch (i) {
- case OMPC_PROC_BIND_unknown - 2:
- Values += " or ";
- break;
- case OMPC_PROC_BIND_unknown - 1:
- break;
- default:
- Values += Sep;
- break;
- }
- }
Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
- << Values << getOpenMPClauseName(OMPC_proc_bind);
+ << getListOfPossibleValues(OMPC_proc_bind, /*First=*/0,
+ /*Last=*/OMPC_PROC_BIND_unknown)
+ << getOpenMPClauseName(OMPC_proc_bind);
return nullptr;
}
return new (Context)
@@ -4912,21 +6057,33 @@ OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
}
OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
- OpenMPClauseKind Kind, unsigned Argument, Expr *Expr,
+ OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation ArgumentLoc, SourceLocation CommaLoc,
+ ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
SourceLocation EndLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_schedule:
+ enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
+ assert(Argument.size() == NumberOfElements &&
+ ArgumentLoc.size() == NumberOfElements);
Res = ActOnOpenMPScheduleClause(
- static_cast<OpenMPScheduleClauseKind>(Argument), Expr, StartLoc,
- LParenLoc, ArgumentLoc, CommaLoc, EndLoc);
+ static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
+ static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
+ static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
+ StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
+ ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
break;
case OMPC_if:
+ assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
+ Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
+ Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
+ DelimLoc, EndLoc);
+ break;
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
case OMPC_default:
case OMPC_proc_bind:
@@ -4951,38 +6108,91 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_capture:
case OMPC_seq_cst:
case OMPC_depend:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_map:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
return Res;
}
+static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1,
+ OpenMPScheduleClauseModifier M2,
+ SourceLocation M1Loc, SourceLocation M2Loc) {
+ if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
+ SmallVector<unsigned, 2> Excluded;
+ if (M2 != OMPC_SCHEDULE_MODIFIER_unknown)
+ Excluded.push_back(M2);
+ if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
+ Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
+ if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
+ Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
+ S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
+ << getListOfPossibleValues(OMPC_schedule,
+ /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
+ /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
+ Excluded)
+ << getOpenMPClauseName(OMPC_schedule);
+ return true;
+ }
+ return false;
+}
+
OMPClause *Sema::ActOnOpenMPScheduleClause(
+ OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
- SourceLocation EndLoc) {
+ SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
+ SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
+ if (checkScheduleModifiers(*this, M1, M2, M1Loc, M2Loc) ||
+ checkScheduleModifiers(*this, M2, M1, M2Loc, M1Loc))
+ return nullptr;
+ // OpenMP, 2.7.1, Loop Construct, Restrictions
+ // Either the monotonic modifier or the nonmonotonic modifier can be specified
+ // but not both.
+ if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
+ (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
+ M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
+ (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
+ M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
+ Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
+ << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
+ << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
+ return nullptr;
+ }
if (Kind == OMPC_SCHEDULE_unknown) {
std::string Values;
- std::string Sep(", ");
- for (unsigned i = 0; i < OMPC_SCHEDULE_unknown; ++i) {
- Values += "'";
- Values += getOpenMPSimpleClauseTypeName(OMPC_schedule, i);
- Values += "'";
- switch (i) {
- case OMPC_SCHEDULE_unknown - 2:
- Values += " or ";
- break;
- case OMPC_SCHEDULE_unknown - 1:
- break;
- default:
- Values += Sep;
- break;
- }
+ if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
+ unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
+ Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
+ /*Last=*/OMPC_SCHEDULE_MODIFIER_last,
+ Exclude);
+ } else {
+ Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
+ /*Last=*/OMPC_SCHEDULE_unknown);
}
Diag(KindLoc, diag::err_omp_unexpected_clause_value)
<< Values << getOpenMPClauseName(OMPC_schedule);
return nullptr;
}
+ // OpenMP, 2.7.1, Loop Construct, Restrictions
+ // The nonmonotonic modifier can only be specified with schedule(dynamic) or
+ // schedule(guided).
+ if ((M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
+ M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
+ Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
+ Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
+ diag::err_omp_schedule_nonmonotonic_static);
+ return nullptr;
+ }
Expr *ValExpr = ChunkSize;
Expr *HelperValExpr = nullptr;
if (ChunkSize) {
@@ -5004,7 +6214,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
if (ValExpr->isIntegerConstantExpr(Result, Context)) {
if (Result.isSigned() && !Result.isStrictlyPositive()) {
Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
- << "schedule" << ChunkSize->getSourceRange();
+ << "schedule" << 1 << ChunkSize->getSourceRange();
return nullptr;
}
} else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) {
@@ -5018,8 +6228,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClause(
}
}
- return new (Context) OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc,
- EndLoc, Kind, ValExpr, HelperValExpr);
+ return new (Context)
+ OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
+ ValExpr, HelperValExpr, M1, M1Loc, M2, M2Loc);
}
OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
@@ -5054,10 +6265,20 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_seq_cst:
Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
break;
+ case OMPC_threads:
+ Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
+ break;
+ case OMPC_simd:
+ Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
+ break;
+ case OMPC_nogroup:
+ Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
case OMPC_schedule:
case OMPC_private:
@@ -5074,18 +6295,20 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_threadprivate:
case OMPC_flush:
case OMPC_depend:
+ case OMPC_device:
+ case OMPC_map:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_num_tasks:
+ case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
return Res;
}
-OMPClause *Sema::ActOnOpenMPOrderedClause(SourceLocation StartLoc,
- SourceLocation EndLoc) {
- DSAStack->setOrderedRegion();
- return new (Context) OMPOrderedClause(StartLoc, EndLoc);
-}
-
OMPClause *Sema::ActOnOpenMPNowaitClause(SourceLocation StartLoc,
SourceLocation EndLoc) {
DSAStack->setNowaitRegion();
@@ -5127,12 +6350,28 @@ OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
return new (Context) OMPSeqCstClause(StartLoc, EndLoc);
}
+OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPThreadsClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPSIMDClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPSIMDClause(StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPNogroupClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return new (Context) OMPNogroupClause(StartLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPVarListClause(
OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
- SourceLocation DepLoc) {
+ OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier,
+ OpenMPMapClauseKind MapType, SourceLocation DepLinMapLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_private:
@@ -5153,7 +6392,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
break;
case OMPC_linear:
Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
- ColonLoc, EndLoc);
+ LinKind, DepLinMapLoc, ColonLoc, EndLoc);
break;
case OMPC_aligned:
Res = ActOnOpenMPAlignedClause(VarList, TailExpr, StartLoc, LParenLoc,
@@ -5169,13 +6408,18 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_depend:
- Res = ActOnOpenMPDependClause(DepKind, DepLoc, ColonLoc, VarList, StartLoc,
- LParenLoc, EndLoc);
+ Res = ActOnOpenMPDependClause(DepKind, DepLinMapLoc, ColonLoc, VarList,
+ StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_map:
+ Res = ActOnOpenMPMapClause(MapTypeModifier, MapType, DepLinMapLoc, ColonLoc,
+ VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
+ case OMPC_simdlen:
case OMPC_collapse:
case OMPC_default:
case OMPC_proc_bind:
@@ -5190,6 +6434,16 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_device:
+ case OMPC_threads:
+ case OMPC_simd:
+ case OMPC_num_teams:
+ case OMPC_thread_limit:
+ case OMPC_priority:
+ case OMPC_grainsize:
+ case OMPC_nogroup:
+ case OMPC_num_tasks:
+ case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -5240,16 +6494,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
diag::err_omp_private_incomplete_type)) {
continue;
}
- if (Type->isReferenceType()) {
- Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_private) << Type;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- continue;
- }
+ Type = Type.getNonReferenceType();
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct]
@@ -5290,7 +6535,8 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
// IdResolver, so the code in the OpenMP region uses original variable for
// proper diagnostics.
Type = Type.getUnqualifiedType();
- auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName());
+ auto VDPrivate = buildVarDecl(*this, DE->getExprLoc(), Type, VD->getName(),
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto=*/false);
if (VDPrivate->isInvalidDecl())
continue;
@@ -5384,23 +6630,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
diag::err_omp_firstprivate_incomplete_type)) {
continue;
}
- if (Type->isReferenceType()) {
- if (IsImplicitClause) {
- Diag(ImplicitClauseLoc,
- diag::err_omp_task_predetermined_firstprivate_ref_type_arg)
- << Type;
- Diag(RefExpr->getExprLoc(), diag::note_used_here);
- } else {
- Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_firstprivate) << Type;
- }
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- continue;
- }
+ Type = Type.getNonReferenceType();
// OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
// A variable of class type (or array thereof) that appears in a private
@@ -5492,6 +6722,49 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
continue;
}
}
+
+ // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
+ // A list item that is private within a teams region must not appear in a
+ // firstprivate clause on a distribute construct if any of the distribute
+ // regions arising from the distribute construct ever bind to any of the
+ // teams regions arising from the teams construct.
+ // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
+ // A list item that appears in a reduction clause of a teams construct
+ // must not appear in a firstprivate clause on a distribute construct if
+ // any of the distribute regions arising from the distribute construct
+ // ever bind to any of the teams regions arising from the teams construct.
+ // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
+ // A list item may appear in a firstprivate or lastprivate clause but not
+ // both.
+ if (CurrDir == OMPD_distribute) {
+ DVar = DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_private),
+ [](OpenMPDirectiveKind K) -> bool {
+ return isOpenMPTeamsDirective(K);
+ },
+ false);
+ if (DVar.CKind == OMPC_private && isOpenMPTeamsDirective(DVar.DKind)) {
+ Diag(ELoc, diag::err_omp_firstprivate_distribute_private_teams);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ DVar = DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction),
+ [](OpenMPDirectiveKind K) -> bool {
+ return isOpenMPTeamsDirective(K);
+ },
+ false);
+ if (DVar.CKind == OMPC_reduction &&
+ isOpenMPTeamsDirective(DVar.DKind)) {
+ Diag(ELoc, diag::err_omp_firstprivate_distribute_in_teams_reduction);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ DVar = DSAStack->getTopDSA(VD, false);
+ if (DVar.CKind == OMPC_lastprivate) {
+ Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ }
}
// Variably modified types are not supported for tasks.
@@ -5509,7 +6782,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
}
Type = Type.getUnqualifiedType();
- auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName());
+ auto VDPrivate = buildVarDecl(*this, ELoc, Type, VD->getName(),
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
// Generate helper private variable and initialize it with the value of the
// original variable. The address of the original variable is replaced by
// the address of the new private variable in the CodeGen. This new variable
@@ -5536,6 +6810,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
VDPrivate->setInvalidDecl();
else
VDPrivate->setInit(Result.getAs<Expr>());
+ // Remove temp variable declaration.
+ Context.Deallocate(VDInitTemp);
} else {
auto *VDInit =
buildVarDecl(*this, DE->getLocStart(), Type, ".firstprivate.temp");
@@ -5618,16 +6894,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
diag::err_omp_lastprivate_incomplete_type)) {
continue;
}
- if (Type->isReferenceType()) {
- Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_lastprivate) << Type;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
- continue;
- }
+ Type = Type.getNonReferenceType();
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct]
@@ -5674,11 +6941,13 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
// operator for the class type.
Type = Context.getBaseElementType(Type).getNonReferenceType();
auto *SrcVD = buildVarDecl(*this, DE->getLocStart(),
- Type.getUnqualifiedType(), ".lastprivate.src");
+ Type.getUnqualifiedType(), ".lastprivate.src",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoSrcExpr = buildDeclRefExpr(
*this, SrcVD, Type.getUnqualifiedType(), DE->getExprLoc());
auto *DstVD =
- buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst");
+ buildVarDecl(*this, DE->getLocStart(), Type, ".lastprivate.dst",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoDstExpr =
buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc());
// For arrays generate assignment operation for single element and replace
@@ -5692,6 +6961,18 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
if (AssignmentOp.isInvalid())
continue;
+ // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
+ // A list item may appear in a firstprivate or lastprivate clause but not
+ // both.
+ if (CurrDir == OMPD_distribute) {
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
+ if (DVar.CKind == OMPC_firstprivate) {
+ Diag(ELoc, diag::err_omp_firstprivate_and_lastprivate_in_distribute);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ }
+
if (TopDVar.CKind != OMPC_firstprivate)
DSAStack->addDSA(VD, DE, OMPC_lastprivate);
Vars.push_back(DE);
@@ -5879,6 +7160,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
case OO_Call:
case OO_Subscript:
case OO_Conditional:
+ case OO_Coawait:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Unexpected reduction identifier");
case OO_None:
@@ -5903,6 +7185,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
}
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> Privates;
SmallVector<Expr *, 8> LHSs;
SmallVector<Expr *, 8> RHSs;
SmallVector<Expr *, 8> ReductionOps;
@@ -5911,6 +7194,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ Privates.push_back(nullptr);
LHSs.push_back(nullptr);
RHSs.push_back(nullptr);
ReductionOps.push_back(nullptr);
@@ -5922,6 +7206,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
RefExpr->containsUnexpandedParameterPack()) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ Privates.push_back(nullptr);
LHSs.push_back(nullptr);
RHSs.push_back(nullptr);
ReductionOps.push_back(nullptr);
@@ -5937,14 +7222,53 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
// OpenMP [2.14.3.3, Restrictions, p.1]
// A variable that is part of another variable (as an array or
// structure element) cannot appear in a private clause.
- auto DE = dyn_cast<DeclRefExpr>(RefExpr);
- if (!DE || !isa<VarDecl>(DE->getDecl())) {
- Diag(ELoc, diag::err_omp_expected_var_name) << ERange;
+ auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
+ auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr);
+ auto *OASE = dyn_cast<OMPArraySectionExpr>(RefExpr);
+ if (!ASE && !OASE && (!DE || !isa<VarDecl>(DE->getDecl()))) {
+ Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) << ERange;
continue;
}
- auto D = DE->getDecl();
- auto VD = cast<VarDecl>(D);
- auto Type = VD->getType();
+ QualType Type;
+ VarDecl *VD = nullptr;
+ if (DE) {
+ auto D = DE->getDecl();
+ VD = cast<VarDecl>(D);
+ Type = VD->getType();
+ } else if (ASE) {
+ Type = ASE->getType();
+ auto *Base = ASE->getBase()->IgnoreParenImpCasts();
+ while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+ Base = TempASE->getBase()->IgnoreParenImpCasts();
+ DE = dyn_cast<DeclRefExpr>(Base);
+ if (DE)
+ VD = dyn_cast<VarDecl>(DE->getDecl());
+ if (!VD) {
+ Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name)
+ << 0 << Base->getSourceRange();
+ continue;
+ }
+ } else if (OASE) {
+ auto BaseType = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
+ if (auto *ATy = BaseType->getAsArrayTypeUnsafe())
+ Type = ATy->getElementType();
+ else
+ Type = BaseType->getPointeeType();
+ auto *Base = OASE->getBase()->IgnoreParenImpCasts();
+ while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
+ Base = TempOASE->getBase()->IgnoreParenImpCasts();
+ while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
+ Base = TempASE->getBase()->IgnoreParenImpCasts();
+ DE = dyn_cast<DeclRefExpr>(Base);
+ if (DE)
+ VD = dyn_cast<VarDecl>(DE->getDecl());
+ if (!VD) {
+ Diag(Base->getExprLoc(), diag::err_omp_expected_base_var_name)
+ << 1 << Base->getSourceRange();
+ continue;
+ }
+ }
+
// OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
// A variable that appears in a private clause must not have an incomplete
// type or a reference type.
@@ -5955,36 +7279,42 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
// Arrays may not appear in a reduction clause.
if (Type.getNonReferenceType()->isArrayType()) {
Diag(ELoc, diag::err_omp_reduction_type_array) << Type << ERange;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if (!ASE && !OASE) {
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ }
continue;
}
// OpenMP [2.14.3.6, reduction clause, Restrictions]
// A list item that appears in a reduction clause must not be
// const-qualified.
if (Type.getNonReferenceType().isConstant(Context)) {
- Diag(ELoc, diag::err_omp_const_variable)
+ Diag(ELoc, diag::err_omp_const_reduction_list_item)
<< getOpenMPClauseName(OMPC_reduction) << Type << ERange;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if (!ASE && !OASE) {
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ }
continue;
}
// OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
// If a list-item is a reference type then it must bind to the same object
// for all threads of the team.
- VarDecl *VDDef = VD->getDefinition();
- if (Type->isReferenceType() && VDDef) {
- DSARefChecker Check(DSAStack);
- if (Check.Visit(VDDef->getInit())) {
- Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange;
- Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
- continue;
+ if (!ASE && !OASE) {
+ VarDecl *VDDef = VD->getDefinition();
+ if (Type->isReferenceType() && VDDef) {
+ DSARefChecker Check(DSAStack);
+ if (Check.Visit(VDDef->getInit())) {
+ Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange;
+ Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
+ continue;
+ }
}
}
// OpenMP [2.14.3.6, reduction clause, Restrictions]
@@ -6000,21 +7330,25 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
(getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
<< getLangOpts().CPlusPlus;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if (!ASE && !OASE) {
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ }
continue;
}
if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
!getLangOpts().CPlusPlus && Type->isFloatingType()) {
Diag(ELoc, diag::err_omp_clause_floating_type_arg);
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if (!ASE && !OASE) {
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ }
continue;
}
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -6028,7 +7362,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
// Any number of reduction clauses can be specified on the directive,
// but a list item can appear only once in the reduction clauses for that
// directive.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
+ DSAStackTy::DSAVarData DVar;
+ DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind == OMPC_reduction) {
Diag(ELoc, diag::err_omp_once_referenced)
<< getOpenMPClauseName(OMPC_reduction);
@@ -6059,9 +7394,27 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
continue;
}
}
+
Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
- auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs");
- auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName());
+ auto *LHSVD = buildVarDecl(*this, ELoc, Type, ".reduction.lhs",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+ auto *RHSVD = buildVarDecl(*this, ELoc, Type, VD->getName(),
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+ auto PrivateTy = Type;
+ if (OASE) {
+ // For array sections only:
+ // Create pseudo array type for private copy. The size for this array will
+ // be generated during codegen.
+ // For array subscripts or single variables Private Ty is the same as Type
+ // (type of the variable or single array element).
+ PrivateTy = Context.getVariableArrayType(
+ Type, new (Context) OpaqueValueExpr(SourceLocation(),
+ Context.getSizeType(), VK_RValue),
+ ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
+ }
+ // Private copy.
+ auto *PrivateVD = buildVarDecl(*this, ELoc, PrivateTy, VD->getName(),
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
// Add initializer for private variable.
Expr *Init = nullptr;
switch (BOK) {
@@ -6170,21 +7523,27 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
if (Init) {
AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false,
/*TypeMayContainAuto=*/false);
- } else {
+ } else
ActOnUninitializedDecl(RHSVD, /*TypeMayContainAuto=*/false);
- }
if (!RHSVD->hasInit()) {
Diag(ELoc, diag::err_omp_reduction_id_not_compatible) << Type
<< ReductionIdRange;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if (VD) {
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ }
continue;
}
+ // Store initializer for single element in private copy. Will be used during
+ // codegen.
+ PrivateVD->setInit(RHSVD->getInit());
+ PrivateVD->setInitStyle(RHSVD->getInitStyle());
auto *LHSDRE = buildDeclRefExpr(*this, LHSVD, Type, ELoc);
auto *RHSDRE = buildDeclRefExpr(*this, RHSVD, Type, ELoc);
+ auto *PrivateDRE = buildDeclRefExpr(*this, PrivateVD, PrivateTy, ELoc);
ExprResult ReductionOp =
BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(), BOK,
LHSDRE, RHSDRE);
@@ -6201,15 +7560,14 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
BuildBinOp(DSAStack->getCurScope(), ReductionId.getLocStart(),
BO_Assign, LHSDRE, ConditionalOp);
}
- if (ReductionOp.isUsable()) {
- ReductionOp = ActOnFinishFullExpr(ReductionOp.get());
- }
+ ReductionOp = ActOnFinishFullExpr(ReductionOp.get());
}
if (ReductionOp.isInvalid())
continue;
DSAStack->addDSA(VD, DE, OMPC_reduction);
- Vars.push_back(DE);
+ Vars.push_back(RefExpr);
+ Privates.push_back(PrivateDRE);
LHSs.push_back(LHSDRE);
RHSs.push_back(RHSDRE);
ReductionOps.push_back(ReductionOp.get());
@@ -6220,22 +7578,28 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
return OMPReductionClause::Create(
Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars,
- ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, LHSs,
- RHSs, ReductionOps);
+ ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, Privates,
+ LHSs, RHSs, ReductionOps);
}
-OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ColonLoc,
- SourceLocation EndLoc) {
+OMPClause *Sema::ActOnOpenMPLinearClause(
+ ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
+ SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
+ SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
+ SmallVector<Expr *, 8> Privates;
SmallVector<Expr *, 8> Inits;
+ if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
+ LinKind == OMPC_LINEAR_unknown) {
+ Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
+ LinKind = OMPC_LINEAR_val;
+ }
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP linear clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
+ Privates.push_back(nullptr);
Inits.push_back(nullptr);
continue;
}
@@ -6278,6 +7642,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
if (QType->isDependentType() || QType->isInstantiationDependentType()) {
// It will be analyzed later.
Vars.push_back(DE);
+ Privates.push_back(nullptr);
Inits.push_back(nullptr);
continue;
}
@@ -6287,16 +7652,13 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
diag::err_omp_linear_incomplete_type)) {
continue;
}
- if (QType->isReferenceType()) {
- Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_linear) << QType;
- bool IsDecl =
- VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
- IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
+ !QType->isReferenceType()) {
+ Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
+ << QType << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
continue;
}
+ QType = QType.getNonReferenceType();
// A list item must not be const-qualified.
if (QType.isConstant(Context)) {
@@ -6324,14 +7686,25 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
continue;
}
+ // Build private copy of original var.
+ auto *Private = buildVarDecl(*this, ELoc, QType, VD->getName(),
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
+ auto *PrivateRef = buildDeclRefExpr(
+ *this, Private, DE->getType().getUnqualifiedType(), DE->getExprLoc());
// Build var to save initial value.
VarDecl *Init = buildVarDecl(*this, ELoc, QType, ".linear.start");
- AddInitializerToDecl(Init, DefaultLvalueConversion(DE).get(),
+ Expr *InitExpr;
+ if (LinKind == OMPC_LINEAR_uval)
+ InitExpr = VD->getInit();
+ else
+ InitExpr = DE;
+ AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
/*DirectInit*/ false, /*TypeMayContainAuto*/ false);
auto InitRef = buildDeclRefExpr(
*this, Init, DE->getType().getUnqualifiedType(), DE->getExprLoc());
DSAStack->addDSA(VD, DE, OMPC_linear);
Vars.push_back(DE);
+ Privates.push_back(PrivateRef);
Inits.push_back(InitRef);
}
@@ -6356,6 +7729,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc);
ExprResult CalcStep =
BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr);
+ CalcStep = ActOnFinishFullExpr(CalcStep.get());
// Warn about zero linear step (it would be probably better specified as
// making corresponding variables 'const').
@@ -6371,8 +7745,9 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
}
}
- return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc,
- Vars, Inits, StepExpr, CalcStepExpr);
+ return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc,
+ ColonLoc, EndLoc, Vars, Privates, Inits,
+ StepExpr, CalcStepExpr);
}
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
@@ -6391,27 +7766,35 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
Step = cast<BinaryOperator>(CalcStep)->getLHS();
bool HasErrors = false;
auto CurInit = Clause.inits().begin();
+ auto CurPrivate = Clause.privates().begin();
+ auto LinKind = Clause.getModifier();
for (auto &RefExpr : Clause.varlists()) {
Expr *InitExpr = *CurInit;
// Build privatized reference to the current linear var.
auto DE = cast<DeclRefExpr>(RefExpr);
- auto PrivateRef =
- buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
- DE->getType().getUnqualifiedType(), DE->getExprLoc(),
- /*RefersToCapture=*/true);
+ Expr *CapturedRef;
+ if (LinKind == OMPC_LINEAR_uval)
+ CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
+ else
+ CapturedRef =
+ buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
+ DE->getType().getUnqualifiedType(), DE->getExprLoc(),
+ /*RefersToCapture=*/true);
// Build update: Var = InitExpr + IV * Step
ExprResult Update =
- BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef,
+ BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), *CurPrivate,
InitExpr, IV, Step, /* Subtract */ false);
- Update = SemaRef.ActOnFinishFullExpr(Update.get());
+ Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getLocStart(),
+ /*DiscardedValue=*/true);
// Build final: Var = InitExpr + NumIterations * Step
ExprResult Final =
- BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), PrivateRef,
+ BuildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), CapturedRef,
InitExpr, NumIterations, Step, /* Subtract */ false);
- Final = SemaRef.ActOnFinishFullExpr(Final.get());
+ Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getLocStart(),
+ /*DiscardedValue=*/true);
if (!Update.isUsable() || !Final.isUsable()) {
Updates.push_back(nullptr);
Finals.push_back(nullptr);
@@ -6420,7 +7803,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
Updates.push_back(Update.get());
Finals.push_back(Final.get());
}
- ++CurInit;
+ ++CurInit, ++CurPrivate;
}
Clause.setUpdates(Updates);
Clause.setFinals(Finals);
@@ -6557,12 +7940,14 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
// copyin clause requires an accessible, unambiguous copy assignment
// operator for the class type.
auto ElemType = Context.getBaseElementType(Type).getNonReferenceType();
- auto *SrcVD = buildVarDecl(*this, DE->getLocStart(),
- ElemType.getUnqualifiedType(), ".copyin.src");
+ auto *SrcVD =
+ buildVarDecl(*this, DE->getLocStart(), ElemType.getUnqualifiedType(),
+ ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoSrcExpr = buildDeclRefExpr(
*this, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
auto *DstVD =
- buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst");
+ buildVarDecl(*this, DE->getLocStart(), ElemType, ".copyin.dst",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoDstExpr =
buildDeclRefExpr(*this, DstVD, ElemType, DE->getExprLoc());
// For arrays generate assignment operation for single element and replace
@@ -6679,13 +8064,16 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
// A variable of class type (or array thereof) that appears in a
// copyin clause requires an accessible, unambiguous copy assignment
// operator for the class type.
- Type = Context.getBaseElementType(Type).getUnqualifiedType();
+ Type = Context.getBaseElementType(Type.getNonReferenceType())
+ .getUnqualifiedType();
auto *SrcVD =
- buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src");
+ buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.src",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoSrcExpr =
buildDeclRefExpr(*this, SrcVD, Type, DE->getExprLoc());
auto *DstVD =
- buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst");
+ buildVarDecl(*this, DE->getLocStart(), Type, ".copyprivate.dst",
+ VD->hasAttrs() ? &VD->getAttrs() : nullptr);
auto *PseudoDstExpr =
buildDeclRefExpr(*this, DstVD, Type, DE->getExprLoc());
auto AssignmentOp = BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
@@ -6727,61 +8115,430 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
SourceLocation DepLoc, SourceLocation ColonLoc,
ArrayRef<Expr *> VarList, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc) {
- if (DepKind == OMPC_DEPEND_unknown) {
- std::string Values;
- std::string Sep(", ");
- for (unsigned i = 0; i < OMPC_DEPEND_unknown; ++i) {
- Values += "'";
- Values += getOpenMPSimpleClauseTypeName(OMPC_depend, i);
- Values += "'";
- switch (i) {
- case OMPC_DEPEND_unknown - 2:
- Values += " or ";
- break;
- case OMPC_DEPEND_unknown - 1:
- break;
- default:
- Values += Sep;
- break;
- }
- }
+ if (DSAStack->getCurrentDirective() == OMPD_ordered &&
+ DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
+ Diag(DepLoc, diag::err_omp_unexpected_clause_value)
+ << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
+ return nullptr;
+ }
+ if (DSAStack->getCurrentDirective() != OMPD_ordered &&
+ (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
+ DepKind == OMPC_DEPEND_sink)) {
+ unsigned Except[] = {OMPC_DEPEND_source, OMPC_DEPEND_sink};
Diag(DepLoc, diag::err_omp_unexpected_clause_value)
- << Values << getOpenMPClauseName(OMPC_depend);
+ << getListOfPossibleValues(OMPC_depend, /*First=*/0,
+ /*Last=*/OMPC_DEPEND_unknown, Except)
+ << getOpenMPClauseName(OMPC_depend);
return nullptr;
}
SmallVector<Expr *, 8> Vars;
- for (auto &RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP shared clause.");
- if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ llvm::APSInt DepCounter(/*BitWidth=*/32);
+ llvm::APSInt TotalDepCount(/*BitWidth=*/32);
+ if (DepKind == OMPC_DEPEND_sink) {
+ if (auto *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) {
+ TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
+ TotalDepCount.setIsUnsigned(/*Val=*/true);
+ }
+ }
+ if ((DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) ||
+ DSAStack->getParentOrderedRegionParam()) {
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr) ||
+ (DepKind == OMPC_DEPEND_sink && CurContext->isDependentContext())) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ auto *SimpleExpr = RefExpr->IgnoreParenCasts();
+ if (DepKind == OMPC_DEPEND_sink) {
+ if (DepCounter >= TotalDepCount) {
+ Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
+ continue;
+ }
+ ++DepCounter;
+ // OpenMP [2.13.9, Summary]
+ // depend(dependence-type : vec), where dependence-type is:
+ // 'sink' and where vec is the iteration vector, which has the form:
+ // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
+ // where n is the value specified by the ordered clause in the loop
+ // directive, xi denotes the loop iteration variable of the i-th nested
+ // loop associated with the loop directive, and di is a constant
+ // non-negative integer.
+ SimpleExpr = SimpleExpr->IgnoreImplicit();
+ auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
+ if (!DE) {
+ OverloadedOperatorKind OOK = OO_None;
+ SourceLocation OOLoc;
+ Expr *LHS, *RHS;
+ if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
+ OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
+ OOLoc = BO->getOperatorLoc();
+ LHS = BO->getLHS()->IgnoreParenImpCasts();
+ RHS = BO->getRHS()->IgnoreParenImpCasts();
+ } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
+ OOK = OCE->getOperator();
+ OOLoc = OCE->getOperatorLoc();
+ LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
+ RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
+ } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
+ OOK = MCE->getMethodDecl()
+ ->getNameInfo()
+ .getName()
+ .getCXXOverloadedOperator();
+ OOLoc = MCE->getCallee()->getExprLoc();
+ LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
+ RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
+ } else {
+ Diag(ELoc, diag::err_omp_depend_sink_wrong_expr);
+ continue;
+ }
+ DE = dyn_cast<DeclRefExpr>(LHS);
+ if (!DE) {
+ Diag(LHS->getExprLoc(),
+ diag::err_omp_depend_sink_expected_loop_iteration)
+ << DSAStack->getParentLoopControlVariable(
+ DepCounter.getZExtValue());
+ continue;
+ }
+ if (OOK != OO_Plus && OOK != OO_Minus) {
+ Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
+ continue;
+ }
+ ExprResult Res = VerifyPositiveIntegerConstantInClause(
+ RHS, OMPC_depend, /*StrictlyPositive=*/false);
+ if (Res.isInvalid())
+ continue;
+ }
+ auto *VD = dyn_cast<VarDecl>(DE->getDecl());
+ if (!CurContext->isDependentContext() &&
+ DSAStack->getParentOrderedRegionParam() &&
+ (!VD || DepCounter != DSAStack->isParentLoopControlVariable(VD))) {
+ Diag(DE->getExprLoc(),
+ diag::err_omp_depend_sink_expected_loop_iteration)
+ << DSAStack->getParentLoopControlVariable(
+ DepCounter.getZExtValue());
+ continue;
+ }
+ } else {
+ // OpenMP [2.11.1.1, Restrictions, p.3]
+ // A variable that is part of another variable (such as a field of a
+ // structure) but is not an array element or an array section cannot
+ // appear in a depend clause.
+ auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
+ auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
+ auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
+ if (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
+ (!ASE && !DE && !OASE) || (DE && !isa<VarDecl>(DE->getDecl())) ||
+ (ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
+ !ASE->getBase()->getType()->isArrayType())) {
+ Diag(ELoc, diag::err_omp_expected_var_name_or_array_item)
+ << RefExpr->getSourceRange();
+ continue;
+ }
+ }
+
+ Vars.push_back(RefExpr->IgnoreParenImpCasts());
+ }
+
+ if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
+ TotalDepCount > VarList.size() &&
+ DSAStack->getParentOrderedRegionParam()) {
+ Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
+ << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
+ }
+ if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
+ Vars.empty())
+ return nullptr;
+ }
+
+ return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind,
+ DepLoc, ColonLoc, Vars);
+}
+
+OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = Device;
+
+ // OpenMP [2.9.1, Restrictions]
+ // The device expression must evaluate to a non-negative integer value.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
+ /*StrictlyPositive=*/false))
+ return nullptr;
+
+ return new (Context) OMPDeviceClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+static bool IsCXXRecordForMappable(Sema &SemaRef, SourceLocation Loc,
+ DSAStackTy *Stack, CXXRecordDecl *RD) {
+ if (!RD || RD->isInvalidDecl())
+ return true;
+
+ if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ if (auto *CTD = CTSD->getSpecializedTemplate())
+ RD = CTD->getTemplatedDecl();
+ auto QTy = SemaRef.Context.getRecordType(RD);
+ if (RD->isDynamicClass()) {
+ SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy;
+ SemaRef.Diag(RD->getLocation(), diag::note_omp_polymorphic_in_target);
+ return false;
+ }
+ auto *DC = RD;
+ bool IsCorrect = true;
+ for (auto *I : DC->decls()) {
+ if (I) {
+ if (auto *MD = dyn_cast<CXXMethodDecl>(I)) {
+ if (MD->isStatic()) {
+ SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy;
+ SemaRef.Diag(MD->getLocation(),
+ diag::note_omp_static_member_in_target);
+ IsCorrect = false;
+ }
+ } else if (auto *VD = dyn_cast<VarDecl>(I)) {
+ if (VD->isStaticDataMember()) {
+ SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy;
+ SemaRef.Diag(VD->getLocation(),
+ diag::note_omp_static_member_in_target);
+ IsCorrect = false;
+ }
+ }
+ }
+ }
+
+ for (auto &I : RD->bases()) {
+ if (!IsCXXRecordForMappable(SemaRef, I.getLocStart(), Stack,
+ I.getType()->getAsCXXRecordDecl()))
+ IsCorrect = false;
+ }
+ return IsCorrect;
+}
+
+static bool CheckTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
+ DSAStackTy *Stack, QualType QTy) {
+ NamedDecl *ND;
+ if (QTy->isIncompleteType(&ND)) {
+ SemaRef.Diag(SL, diag::err_incomplete_type) << QTy << SR;
+ return false;
+ } else if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(ND)) {
+ if (!RD->isInvalidDecl() &&
+ !IsCXXRecordForMappable(SemaRef, SL, Stack, RD))
+ return false;
+ }
+ return true;
+}
+
+OMPClause *Sema::ActOnOpenMPMapClause(
+ OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType,
+ SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
+ SmallVector<Expr *, 4> Vars;
+
+ for (auto &RE : VarList) {
+ assert(RE && "Null expr in omp map");
+ if (isa<DependentScopeDeclRefExpr>(RE)) {
// It will be analyzed later.
- Vars.push_back(RefExpr);
+ Vars.push_back(RE);
continue;
}
+ SourceLocation ELoc = RE->getExprLoc();
- SourceLocation ELoc = RefExpr->getExprLoc();
- // OpenMP [2.11.1.1, Restrictions, p.3]
- // A variable that is part of another variable (such as a field of a
+ // OpenMP [2.14.5, Restrictions]
+ // A variable that is part of another variable (such as field of a
// structure) but is not an array element or an array section cannot appear
- // in a depend clause.
- auto *SimpleExpr = RefExpr->IgnoreParenCasts();
- DeclRefExpr *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
- ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
- if (!RefExpr->IgnoreParenImpCasts()->isLValue() || (!ASE && !DE) ||
+ // in a map clause.
+ auto *VE = RE->IgnoreParenLValueCasts();
+
+ if (VE->isValueDependent() || VE->isTypeDependent() ||
+ VE->isInstantiationDependent() ||
+ VE->containsUnexpandedParameterPack()) {
+ // It will be analyzed later.
+ Vars.push_back(RE);
+ continue;
+ }
+
+ auto *SimpleExpr = RE->IgnoreParenCasts();
+ auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
+ auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
+ auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
+
+ if (!RE->IgnoreParenImpCasts()->isLValue() ||
+ (!OASE && !ASE && !DE) ||
(DE && !isa<VarDecl>(DE->getDecl())) ||
(ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
!ASE->getBase()->getType()->isArrayType())) {
Diag(ELoc, diag::err_omp_expected_var_name_or_array_item)
- << RefExpr->getSourceRange();
+ << RE->getSourceRange();
continue;
}
- Vars.push_back(RefExpr->IgnoreParenImpCasts());
- }
+ Decl *D = nullptr;
+ if (DE) {
+ D = DE->getDecl();
+ } else if (ASE) {
+ auto *B = ASE->getBase()->IgnoreParenCasts();
+ D = dyn_cast<DeclRefExpr>(B)->getDecl();
+ } else if (OASE) {
+ auto *B = OASE->getBase();
+ D = dyn_cast<DeclRefExpr>(B)->getDecl();
+ }
+ assert(D && "Null decl on map clause.");
+ auto *VD = cast<VarDecl>(D);
+
+ // OpenMP [2.14.5, Restrictions, p.8]
+ // threadprivate variables cannot appear in a map clause.
+ if (DSAStack->isThreadPrivate(VD)) {
+ auto DVar = DSAStack->getTopDSA(VD, false);
+ Diag(ELoc, diag::err_omp_threadprivate_in_map);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+
+ // OpenMP [2.14.5, Restrictions, p.2]
+ // At most one list item can be an array item derived from a given variable
+ // in map clauses of the same construct.
+ // OpenMP [2.14.5, Restrictions, p.3]
+ // List items of map clauses in the same construct must not share original
+ // storage.
+ // OpenMP [2.14.5, Restrictions, C/C++, p.2]
+ // A variable for which the type is pointer, reference to array, or
+ // reference to pointer and an array section derived from that variable
+ // must not appear as list items of map clauses of the same construct.
+ DSAStackTy::MapInfo MI = DSAStack->IsMappedInCurrentRegion(VD);
+ if (MI.RefExpr) {
+ Diag(ELoc, diag::err_omp_map_shared_storage) << ELoc;
+ Diag(MI.RefExpr->getExprLoc(), diag::note_used_here)
+ << MI.RefExpr->getSourceRange();
+ continue;
+ }
+
+ // OpenMP [2.14.5, Restrictions, C/C++, p.3,4]
+ // A variable for which the type is pointer, reference to array, or
+ // reference to pointer must not appear as a list item if the enclosing
+ // device data environment already contains an array section derived from
+ // that variable.
+ // An array section derived from a variable for which the type is pointer,
+ // reference to array, or reference to pointer must not appear as a list
+ // item if the enclosing device data environment already contains that
+ // variable.
+ QualType Type = VD->getType();
+ MI = DSAStack->getMapInfoForVar(VD);
+ if (MI.RefExpr && (isa<DeclRefExpr>(MI.RefExpr->IgnoreParenLValueCasts()) !=
+ isa<DeclRefExpr>(VE)) &&
+ (Type->isPointerType() || Type->isReferenceType())) {
+ Diag(ELoc, diag::err_omp_map_shared_storage) << ELoc;
+ Diag(MI.RefExpr->getExprLoc(), diag::note_used_here)
+ << MI.RefExpr->getSourceRange();
+ continue;
+ }
+ // OpenMP [2.14.5, Restrictions, C/C++, p.7]
+ // A list item must have a mappable type.
+ if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), *this,
+ DSAStack, Type))
+ continue;
+
+ Vars.push_back(RE);
+ MI.RefExpr = RE;
+ DSAStack->addMapInfoForVar(VD, MI);
+ }
if (Vars.empty())
return nullptr;
- return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind,
- DepLoc, ColonLoc, Vars);
+ return OMPMapClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars,
+ MapTypeModifier, MapType, MapLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = NumTeams;
+
+ // OpenMP [teams Constrcut, Restrictions]
+ // The num_teams expression must evaluate to a positive integer value.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_teams,
+ /*StrictlyPositive=*/true))
+ return nullptr;
+
+ return new (Context) OMPNumTeamsClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = ThreadLimit;
+
+ // OpenMP [teams Constrcut, Restrictions]
+ // The thread_limit expression must evaluate to a positive integer value.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_thread_limit,
+ /*StrictlyPositive=*/true))
+ return nullptr;
+
+ return new (Context) OMPThreadLimitClause(ValExpr, StartLoc, LParenLoc,
+ EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = Priority;
+
+ // OpenMP [2.9.1, task Constrcut]
+ // The priority-value is a non-negative numerical scalar expression.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_priority,
+ /*StrictlyPositive=*/false))
+ return nullptr;
+
+ return new (Context) OMPPriorityClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPGrainsizeClause(Expr *Grainsize,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = Grainsize;
+
+ // OpenMP [2.9.2, taskloop Constrcut]
+ // The parameter of the grainsize clause must be a positive integer
+ // expression.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize,
+ /*StrictlyPositive=*/true))
+ return nullptr;
+
+ return new (Context) OMPGrainsizeClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = NumTasks;
+
+ // OpenMP [2.9.2, taskloop Constrcut]
+ // The parameter of the num_tasks clause must be a positive integer
+ // expression.
+ if (!IsNonNegativeIntegerValue(ValExpr, *this, OMPC_num_tasks,
+ /*StrictlyPositive=*/true))
+ return nullptr;
+
+ return new (Context) OMPNumTasksClause(ValExpr, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ // OpenMP [2.13.2, critical construct, Description]
+ // ... where hint-expression is an integer constant expression that evaluates
+ // to a valid lock hint.
+ ExprResult HintExpr = VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint);
+ if (HintExpr.isInvalid())
+ return nullptr;
+ return new (Context)
+ OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
index 31f581d..663da0c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -38,6 +38,11 @@
using namespace clang;
using namespace sema;
+static bool functionHasPassObjectSizeParams(const FunctionDecl *FD) {
+ return std::any_of(FD->param_begin(), FD->param_end(),
+ std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>));
+}
+
/// A convenience routine for creating a decayed reference to a function.
static ExprResult
CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
@@ -60,12 +65,8 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
DRE->setHadMultipleCandidates(true);
S.MarkDeclRefReferenced(DRE);
-
- ExprResult E = DRE;
- E = S.DefaultFunctionArrayConversion(E.get());
- if (E.isInvalid())
- return ExprError();
- return E;
+ return S.ImpCastExprToType(DRE, S.Context.getPointerType(DRE->getType()),
+ CK_FunctionToPointerDecay);
}
static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
@@ -88,7 +89,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
static ImplicitConversionSequence::CompareKind
-CompareStandardConversionSequences(Sema &S,
+CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2);
@@ -98,7 +99,7 @@ CompareQualificationConversions(Sema &S,
const StandardConversionSequence& SCS2);
static ImplicitConversionSequence::CompareKind
-CompareDerivedToBaseConversions(Sema &S,
+CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2);
@@ -130,7 +131,11 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) {
ICR_Complex_Real_Conversion,
ICR_Conversion,
ICR_Conversion,
- ICR_Writeback_Conversion
+ ICR_Writeback_Conversion,
+ ICR_Exact_Match, // NOTE(gbiv): This may not be completely right --
+ // it was omitted by the patch that added
+ // ICK_Zero_Event_Conversion
+ ICR_C_Conversion
};
return Rank[(int)Kind];
}
@@ -162,7 +167,9 @@ static const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
"Complex-real conversion",
"Block Pointer conversion",
"Transparent Union Conversion",
- "Writeback conversion"
+ "Writeback conversion",
+ "OpenCL Zero Event Conversion",
+ "C specific type conversion"
};
return Name[Kind];
}
@@ -251,6 +258,7 @@ static const Expr *IgnoreNarrowingConversion(const Expr *Converted) {
case CK_IntegralCast:
case CK_IntegralToBoolean:
case CK_IntegralToFloating:
+ case CK_BooleanToSignedIntegral:
case CK_FloatingToIntegral:
case CK_FloatingToBoolean:
case CK_FloatingCast:
@@ -536,6 +544,12 @@ namespace {
struct DFIParamWithArguments : DFIArguments {
TemplateParameter Param;
};
+ // Structure used by DeductionFailureInfo to store template argument
+ // information and the index of the problematic call argument.
+ struct DFIDeducedMismatchArgs : DFIArguments {
+ TemplateArgumentList *TemplateArgs;
+ unsigned CallArgIndex;
+ };
}
/// \brief Convert from Sema's representation of template deduction information
@@ -547,13 +561,14 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
Result.HasDiagnostic = false;
- Result.Data = nullptr;
switch (TDK) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
+ case Sema::TDK_MiscellaneousDeductionFailure:
+ Result.Data = nullptr;
break;
case Sema::TDK_Incomplete:
@@ -561,6 +576,17 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
Result.Data = Info.Param.getOpaqueValue();
break;
+ case Sema::TDK_DeducedMismatch: {
+ // FIXME: Should allocate from normal heap so that we can free this later.
+ auto *Saved = new (Context) DFIDeducedMismatchArgs;
+ Saved->FirstArg = Info.FirstArg;
+ Saved->SecondArg = Info.SecondArg;
+ Saved->TemplateArgs = Info.take();
+ Saved->CallArgIndex = Info.CallArgIndex;
+ Result.Data = Saved;
+ break;
+ }
+
case Sema::TDK_NonDeducedMismatch: {
// FIXME: Should allocate from normal heap so that we can free this later.
DFIArguments *Saved = new (Context) DFIArguments;
@@ -594,9 +620,6 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
case Sema::TDK_FailedOverloadResolution:
Result.Data = Info.Expression;
break;
-
- case Sema::TDK_MiscellaneousDeductionFailure:
- break;
}
return Result;
@@ -616,6 +639,7 @@ void DeductionFailureInfo::Destroy() {
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
+ case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
// FIXME: Destroy the data?
Data = nullptr;
@@ -650,6 +674,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_SubstitutionFailure:
+ case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
return TemplateParameter();
@@ -685,6 +710,9 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_FailedOverloadResolution:
return nullptr;
+ case Sema::TDK_DeducedMismatch:
+ return static_cast<DFIDeducedMismatchArgs*>(Data)->TemplateArgs;
+
case Sema::TDK_SubstitutionFailure:
return static_cast<TemplateArgumentList*>(Data);
@@ -711,6 +739,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
+ case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
return &static_cast<DFIArguments*>(Data)->FirstArg;
@@ -737,6 +766,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
+ case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
return &static_cast<DFIArguments*>(Data)->SecondArg;
@@ -756,6 +786,14 @@ Expr *DeductionFailureInfo::getExpr() {
return nullptr;
}
+llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() {
+ if (static_cast<Sema::TemplateDeductionResult>(Result) ==
+ Sema::TDK_DeducedMismatch)
+ return static_cast<DFIDeducedMismatchArgs*>(Data)->CallArgIndex;
+
+ return llvm::None;
+}
+
void OverloadCandidateSet::destroyCandidates() {
for (iterator i = begin(), e = end(); i != e; ++i) {
for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii)
@@ -896,6 +934,11 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
OldD = cast<UsingShadowDecl>(OldD)->getTargetDecl();
}
+ // A using-declaration does not conflict with another declaration
+ // if one of them is hidden.
+ if ((OldIsUsingDecl || NewIsUsingDecl) && !isVisible(*I))
+ continue;
+
// If either declaration was introduced by a using declaration,
// we'll need to use slightly different rules for matching.
// Essentially, these rules are the normal rules, except that
@@ -1051,6 +1094,14 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return true;
}
+ // Though pass_object_size is placed on parameters and takes an argument, we
+ // consider it to be a function-level modifier for the sake of function
+ // identity. Either the function has one or more parameters with
+ // pass_object_size or it doesn't.
+ if (functionHasPassObjectSizeParams(New) !=
+ functionHasPassObjectSizeParams(Old))
+ return true;
+
// enable_if attributes are an order-sensitive part of the signature.
for (specific_attr_iterator<EnableIfAttr>
NewI = New->specific_attr_begin<EnableIfAttr>(),
@@ -1067,6 +1118,25 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return true;
}
+ if (getLangOpts().CUDA && getLangOpts().CUDATargetOverloads) {
+ CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New),
+ OldTarget = IdentifyCUDATarget(Old);
+ if (NewTarget == CFT_InvalidTarget || NewTarget == CFT_Global)
+ return false;
+
+ assert((OldTarget != CFT_InvalidTarget) && "Unexpected invalid target.");
+
+ // Don't allow mixing of HD with other kinds. This guarantees that
+ // we have only one viable function with this signature on any
+ // side of CUDA compilation .
+ if ((NewTarget == CFT_HostDevice) || (OldTarget == CFT_HostDevice))
+ return false;
+
+ // Allow overloading of functions with same signature, but
+ // different CUDA target attributes.
+ return NewTarget != OldTarget;
+ }
+
// The signatures match; this is not an overload.
return false;
}
@@ -1125,7 +1195,8 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
QualType ToCanon
= S.Context.getCanonicalType(ToType).getUnqualifiedType();
if (Constructor->isCopyConstructor() &&
- (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) {
+ (FromCanon == ToCanon ||
+ S.IsDerivedFrom(From->getLocStart(), FromCanon, ToCanon))) {
// Turn this into a "standard" conversion sequence, so that it
// gets ranked with standard conversion sequences.
ICS.setStandard();
@@ -1215,7 +1286,7 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
QualType FromType = From->getType();
if (ToType->getAs<RecordType>() && FromType->getAs<RecordType>() &&
(S.Context.hasSameUnqualifiedType(FromType, ToType) ||
- S.IsDerivedFrom(FromType, ToType))) {
+ S.IsDerivedFrom(From->getLocStart(), FromType, ToType))) {
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(FromType);
@@ -1387,7 +1458,7 @@ static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType,
bool InOverloadResolution,
StandardConversionSequence &SCS,
bool CStyle);
-
+
/// IsStandardConversion - Determines whether there is a standard
/// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the
/// expression From to the type ToType. Standard conversion sequences
@@ -1410,13 +1481,10 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
SCS.CopyConstructor = nullptr;
// There are no standard conversions for class types in C++, so
- // abort early. When overloading in C, however, we do permit
- if (FromType->isRecordType() || ToType->isRecordType()) {
- if (S.getLangOpts().CPlusPlus)
- return false;
-
- // When we're overloading in C, we allow, as standard conversions,
- }
+ // abort early. When overloading in C, however, we do permit them.
+ if (S.getLangOpts().CPlusPlus &&
+ (FromType->isRecordType() || ToType->isRecordType()))
+ return false;
// The first conversion can be an lvalue-to-rvalue conversion,
// array-to-pointer conversion, or function-to-pointer conversion
@@ -1521,6 +1589,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// Function-to-pointer conversion (C++ 4.3).
SCS.First = ICK_Function_To_Pointer;
+ if (auto *DRE = dyn_cast<DeclRefExpr>(From->IgnoreParenCasts()))
+ if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()))
+ if (!S.checkAddressOfFunctionIsAvailable(FD))
+ return false;
+
// An lvalue of function type T can be converted to an rvalue of
// type "pointer to T." The result is a pointer to the
// function. (C++ 4.3p1).
@@ -1625,9 +1698,9 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// tryAtomicConversion has updated the standard conversion sequence
// appropriately.
return true;
- } else if (ToType->isEventT() &&
+ } else if (ToType->isEventT() &&
From->isIntegerConstantExpr(S.getASTContext()) &&
- (From->EvaluateKnownConstInt(S.getASTContext()) == 0)) {
+ From->EvaluateKnownConstInt(S.getASTContext()) == 0) {
SCS.Second = ICK_Zero_Event_Conversion;
FromType = ToType;
} else {
@@ -1666,11 +1739,28 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
}
SCS.setToType(2, FromType);
+ if (CanonFrom == CanonTo)
+ return true;
+
// If we have not converted the argument type to the parameter type,
- // this is a bad conversion sequence.
- if (CanonFrom != CanonTo)
+ // this is a bad conversion sequence, unless we're resolving an overload in C.
+ if (S.getLangOpts().CPlusPlus || !InOverloadResolution)
+ return false;
+
+ ExprResult ER = ExprResult{From};
+ auto Conv = S.CheckSingleAssignmentConstraints(ToType, ER,
+ /*Diagnose=*/false,
+ /*DiagnoseCFAudited=*/false,
+ /*ConvertRHS=*/false);
+ if (Conv != Sema::Compatible)
return false;
+ SCS.setAllToTypes(ToType);
+ // We need to set all three because we want this conversion to rank terribly,
+ // and we don't know what conversions it may overlap with.
+ SCS.First = ICK_C_Only_Conversion;
+ SCS.Second = ICK_C_Only_Conversion;
+ SCS.Third = ICK_C_Only_Conversion;
return true;
}
@@ -1763,7 +1853,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// We have already pre-calculated the promotion type, so this is trivial.
if (ToType->isIntegerType() &&
- !RequireCompleteType(From->getLocStart(), FromType, 0))
+ isCompleteType(From->getLocStart(), FromType))
return Context.hasSameUnqualifiedType(
ToType, FromEnumType->getDecl()->getPromotionType());
}
@@ -2060,7 +2150,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
}
// MSVC allows implicit function to void* type conversion.
- if (getLangOpts().MicrosoftExt && FromPointeeType->isFunctionType() &&
+ if (getLangOpts().MSVCCompat && FromPointeeType->isFunctionType() &&
ToPointeeType->isVoidType()) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
@@ -2094,8 +2184,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
if (getLangOpts().CPlusPlus &&
FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
!Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) &&
- !RequireCompleteType(From->getLocStart(), FromPointeeType, 0) &&
- IsDerivedFrom(FromPointeeType, ToPointeeType)) {
+ IsDerivedFrom(From->getLocStart(), FromPointeeType, ToPointeeType)) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
ToType, Context);
@@ -2467,6 +2556,18 @@ enum {
ft_qualifer_mismatch
};
+/// Attempts to get the FunctionProtoType from a Type. Handles
+/// MemberFunctionPointers properly.
+static const FunctionProtoType *tryGetFunctionProtoType(QualType FromType) {
+ if (auto *FPT = FromType->getAs<FunctionProtoType>())
+ return FPT;
+
+ if (auto *MPT = FromType->getAs<MemberPointerType>())
+ return MPT->getPointeeType()->getAs<FunctionProtoType>();
+
+ return nullptr;
+}
+
/// HandleFunctionTypeMismatch - Gives diagnostic information for differeing
/// function types. Catches different number of parameter, mismatch in
/// parameter types, and different return types.
@@ -2513,8 +2614,8 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
return;
}
- const FunctionProtoType *FromFunction = FromType->getAs<FunctionProtoType>(),
- *ToFunction = ToType->getAs<FunctionProtoType>();
+ const FunctionProtoType *FromFunction = tryGetFunctionProtoType(FromType),
+ *ToFunction = tryGetFunctionProtoType(ToType);
// Both types need to be function types.
if (!FromFunction || !ToFunction) {
@@ -2621,6 +2722,14 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
// The conversion was successful.
Kind = CK_DerivedToBase;
}
+
+ if (!IsCStyleOrFunctionalCast && FromPointeeType->isFunctionType() &&
+ ToPointeeType->isVoidType()) {
+ assert(getLangOpts().MSVCCompat &&
+ "this should only be possible with MSVCCompat!");
+ Diag(From->getExprLoc(), diag::ext_ms_impcast_fn_obj)
+ << From->getSourceRange();
+ }
}
} else if (const ObjCObjectPointerType *ToPtrType =
ToType->getAs<ObjCObjectPointerType>()) {
@@ -2681,8 +2790,7 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
QualType ToClass(ToTypePtr->getClass(), 0);
if (!Context.hasSameUnqualifiedType(FromClass, ToClass) &&
- !RequireCompleteType(From->getLocStart(), ToClass, 0) &&
- IsDerivedFrom(ToClass, FromClass)) {
+ IsDerivedFrom(From->getLocStart(), ToClass, FromClass)) {
ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
ToClass.getTypePtr());
return true;
@@ -2725,7 +2833,8 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
- bool DerivationOkay = IsDerivedFrom(ToClass, FromClass, Paths);
+ bool DerivationOkay =
+ IsDerivedFrom(From->getLocStart(), ToClass, FromClass, Paths);
assert(DerivationOkay &&
"Should not have been called if derivation isn't OK.");
(void)DerivationOkay;
@@ -3004,14 +3113,10 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// the parentheses of the initializer.
if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) ||
(From->getType()->getAs<RecordType>() &&
- S.IsDerivedFrom(From->getType(), ToType)))
+ S.IsDerivedFrom(From->getLocStart(), From->getType(), ToType)))
ConstructorsOnly = true;
- S.RequireCompleteType(From->getExprLoc(), ToType, 0);
- // RequireCompleteType may have returned true due to some invalid decl
- // during template instantiation, but ToType may be complete enough now
- // to try to recover.
- if (ToType->isIncompleteType()) {
+ if (!S.isCompleteType(From->getExprLoc(), ToType)) {
// We're not going to find any constructors.
} else if (CXXRecordDecl *ToRecordDecl
= dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
@@ -3085,7 +3190,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// Enumerate conversion functions, if we're allowed to.
if (ConstructorsOnly || isa<InitListExpr>(From)) {
- } else if (S.RequireCompleteType(From->getLocStart(), From->getType(), 0)) {
+ } else if (!S.isCompleteType(From->getLocStart(), From->getType())) {
// No conversion functions from incomplete types.
} else if (const RecordType *FromRecordType
= From->getType()->getAs<RecordType>()) {
@@ -3212,7 +3317,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
diag::err_typecheck_nonviable_condition_incomplete,
From->getType(), From->getSourceRange()))
Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition)
- << From->getType() << From->getSourceRange() << ToType;
+ << false << From->getType() << From->getSourceRange() << ToType;
} else
return false;
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From);
@@ -3264,7 +3369,7 @@ static bool hasDeprecatedStringLiteralToCharPtrConversion(
/// conversion sequences to determine whether one is better than the
/// other or if they are indistinguishable (C++ 13.3.3.2).
static ImplicitConversionSequence::CompareKind
-CompareImplicitConversionSequences(Sema &S,
+CompareImplicitConversionSequences(Sema &S, SourceLocation Loc,
const ImplicitConversionSequence& ICS1,
const ImplicitConversionSequence& ICS2)
{
@@ -3344,7 +3449,7 @@ CompareImplicitConversionSequences(Sema &S,
if (ICS1.isStandard())
// Standard conversion sequence S1 is a better conversion sequence than
// standard conversion sequence S2 if [...]
- Result = CompareStandardConversionSequences(S,
+ Result = CompareStandardConversionSequences(S, Loc,
ICS1.Standard, ICS2.Standard);
else if (ICS1.isUserDefined()) {
// User-defined conversion sequence U1 is a better conversion
@@ -3355,7 +3460,7 @@ CompareImplicitConversionSequences(Sema &S,
// U2 (C++ 13.3.3.2p3).
if (ICS1.UserDefined.ConversionFunction ==
ICS2.UserDefined.ConversionFunction)
- Result = CompareStandardConversionSequences(S,
+ Result = CompareStandardConversionSequences(S, Loc,
ICS1.UserDefined.After,
ICS2.UserDefined.After);
else
@@ -3453,7 +3558,7 @@ isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
/// conversion sequences to determine whether one is better than the
/// other or if they are indistinguishable (C++ 13.3.3.2p3).
static ImplicitConversionSequence::CompareKind
-CompareStandardConversionSequences(Sema &S,
+CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2)
{
@@ -3509,7 +3614,7 @@ CompareStandardConversionSequences(Sema &S,
// Neither conversion sequence converts to a void pointer; compare
// their derived-to-base conversions.
if (ImplicitConversionSequence::CompareKind DerivedCK
- = CompareDerivedToBaseConversions(S, SCS1, SCS2))
+ = CompareDerivedToBaseConversions(S, Loc, SCS1, SCS2))
return DerivedCK;
} else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid &&
!S.Context.hasSameType(SCS1.getFromType(), SCS2.getFromType())) {
@@ -3529,9 +3634,9 @@ CompareStandardConversionSequences(Sema &S,
QualType FromPointee1 = FromType1->getPointeeType().getUnqualifiedType();
QualType FromPointee2 = FromType2->getPointeeType().getUnqualifiedType();
- if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+ if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+ else if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2))
return ImplicitConversionSequence::Worse;
// Objective-C++: If one interface is more specific than the
@@ -3739,7 +3844,7 @@ CompareQualificationConversions(Sema &S,
/// [over.ics.rank]p4b3). As part of these checks, we also look at
/// conversions between Objective-C interface types.
static ImplicitConversionSequence::CompareKind
-CompareDerivedToBaseConversions(Sema &S,
+CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2) {
QualType FromType1 = SCS1.getFromType();
@@ -3782,17 +3887,17 @@ CompareDerivedToBaseConversions(Sema &S,
// -- conversion of C* to B* is better than conversion of C* to A*,
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
- if (S.IsDerivedFrom(ToPointee1, ToPointee2))
+ if (S.IsDerivedFrom(Loc, ToPointee1, ToPointee2))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
+ else if (S.IsDerivedFrom(Loc, ToPointee2, ToPointee1))
return ImplicitConversionSequence::Worse;
}
// -- conversion of B* to A* is better than conversion of C* to A*,
if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) {
- if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+ if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+ else if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2))
return ImplicitConversionSequence::Worse;
}
} else if (SCS1.Second == ICK_Pointer_Conversion &&
@@ -3889,16 +3994,16 @@ CompareDerivedToBaseConversions(Sema &S,
QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType();
// conversion of A::* to B::* is better than conversion of A::* to C::*,
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
- if (S.IsDerivedFrom(ToPointee1, ToPointee2))
+ if (S.IsDerivedFrom(Loc, ToPointee1, ToPointee2))
return ImplicitConversionSequence::Worse;
- else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
+ else if (S.IsDerivedFrom(Loc, ToPointee2, ToPointee1))
return ImplicitConversionSequence::Better;
}
// conversion of B::* to C::* is better than conversion of A::* to C::*
if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) {
- if (S.IsDerivedFrom(FromPointee1, FromPointee2))
+ if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(FromPointee2, FromPointee1))
+ else if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1))
return ImplicitConversionSequence::Worse;
}
}
@@ -3910,9 +4015,9 @@ CompareDerivedToBaseConversions(Sema &S,
// reference of type A&,
if (S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
!S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
- if (S.IsDerivedFrom(ToType1, ToType2))
+ if (S.IsDerivedFrom(Loc, ToType1, ToType2))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(ToType2, ToType1))
+ else if (S.IsDerivedFrom(Loc, ToType2, ToType1))
return ImplicitConversionSequence::Worse;
}
@@ -3922,9 +4027,9 @@ CompareDerivedToBaseConversions(Sema &S,
// reference of type A&,
if (!S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
- if (S.IsDerivedFrom(FromType2, FromType1))
+ if (S.IsDerivedFrom(Loc, FromType2, FromType1))
return ImplicitConversionSequence::Better;
- else if (S.IsDerivedFrom(FromType1, FromType2))
+ else if (S.IsDerivedFrom(Loc, FromType1, FromType2))
return ImplicitConversionSequence::Worse;
}
}
@@ -3973,9 +4078,9 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
ObjCLifetimeConversion = false;
if (UnqualT1 == UnqualT2) {
// Nothing to do.
- } else if (!RequireCompleteType(Loc, OrigT2, 0) &&
+ } else if (isCompleteType(Loc, OrigT2) &&
isTypeValid(UnqualT1) && isTypeValid(UnqualT2) &&
- IsDerivedFrom(UnqualT2, UnqualT1))
+ IsDerivedFrom(Loc, UnqualT2, UnqualT1))
DerivedToBase = true;
else if (UnqualT1->isObjCObjectOrInterfaceType() &&
UnqualT2->isObjCObjectOrInterfaceType() &&
@@ -4240,7 +4345,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// conversion functions (13.3.1.6) and choosing the best
// one through overload resolution (13.3)),
if (!SuppressUserConversions && T2->isRecordType() &&
- !S.RequireCompleteType(DeclLoc, T2, 0) &&
+ S.isCompleteType(DeclLoc, T2) &&
RefRelationship == Sema::Ref_Incompatible) {
if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
Init, T2, /*AllowRvalues=*/false,
@@ -4303,7 +4408,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// in the second case (or, in either case, to an appropriate base
// class subobject).
if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
- T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) &&
+ T2->isRecordType() && S.isCompleteType(DeclLoc, T2) &&
FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
Init, T2, /*AllowRvalues=*/true,
AllowExplicit)) {
@@ -4441,7 +4546,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
// We need a complete type for what follows. Incomplete types can never be
// initialized from init lists.
- if (S.RequireCompleteType(From->getLocStart(), ToType, 0))
+ if (!S.isCompleteType(From->getLocStart(), ToType))
return Result;
// Per DR1467:
@@ -4458,7 +4563,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
if (ToType->isRecordType()) {
QualType InitType = From->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, ToType) ||
- S.IsDerivedFrom(InitType, ToType))
+ S.IsDerivedFrom(From->getLocStart(), InitType, ToType))
return TryCopyInitialization(S, From->getInit(0), ToType,
SuppressUserConversions,
InOverloadResolution,
@@ -4515,7 +4620,8 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
}
// Otherwise, look for the worst conversion.
if (Result.isBad() ||
- CompareImplicitConversionSequences(S, ICS, Result) ==
+ CompareImplicitConversionSequences(S, From->getLocStart(), ICS,
+ Result) ==
ImplicitConversionSequence::Worse)
Result = ICS;
}
@@ -4722,7 +4828,7 @@ static bool TryCopyInitialization(const CanQualType FromQTy,
/// parameter of the given member function (@c Method) from the
/// expression @p From.
static ImplicitConversionSequence
-TryObjectArgumentInitialization(Sema &S, QualType FromType,
+TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType,
Expr::Classification FromClassification,
CXXMethodDecl *Method,
CXXRecordDecl *ActingContext) {
@@ -4782,7 +4888,7 @@ TryObjectArgumentInitialization(Sema &S, QualType FromType,
ImplicitConversionKind SecondKind;
if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
SecondKind = ICK_Identity;
- } else if (S.IsDerivedFrom(FromType, ClassType))
+ } else if (S.IsDerivedFrom(Loc, FromType, ClassType))
SecondKind = ICK_Derived_To_Base;
else {
ICS.setBad(BadConversionSequence::unrelated_class,
@@ -4857,7 +4963,8 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
// Note that we always use the true parent context when performing
// the actual argument initialization.
ImplicitConversionSequence ICS = TryObjectArgumentInitialization(
- *this, From->getType(), FromClassification, Method, Method->getParent());
+ *this, From->getLocStart(), From->getType(), FromClassification, Method,
+ Method->getParent());
if (ICS.isBad()) {
if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
Qualifiers FromQs = FromRecordType.getQualifiers();
@@ -4969,6 +5076,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
case ICK_TransparentUnionConversion:
case ICK_Writeback_Conversion:
case ICK_Zero_Event_Conversion:
+ case ICK_C_Only_Conversion:
return false;
case ICK_Lvalue_To_Rvalue:
@@ -5372,14 +5480,15 @@ ExprResult Sema::PerformContextualImplicitConversion(
Expr *From;
TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From)
- : TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {}
+ : Converter(Converter), From(From) {}
void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();
}
} IncompleteDiagnoser(Converter, From);
- if (RequireCompleteType(Loc, T, IncompleteDiagnoser))
+ if (Converter.Suppress ? !isCompleteType(Loc, T)
+ : RequireCompleteType(Loc, T, IncompleteDiagnoser))
return From;
// Look for a conversion to an integral or enumeration type.
@@ -5637,10 +5746,10 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// A member function template is never instantiated to perform the copy
// of a class object to an object of its class type.
QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
- if (Args.size() == 1 &&
- Constructor->isSpecializationCopyingObject() &&
+ if (Args.size() == 1 && Constructor->isSpecializationCopyingObject() &&
(Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) ||
- IsDerivedFrom(Args[0]->getType(), ClassType))) {
+ IsDerivedFrom(Args[0]->getLocStart(), Args[0]->getType(),
+ ClassType))) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_illegal_constructor;
return;
@@ -5761,7 +5870,7 @@ ObjCMethodDecl *Sema::SelectBestMethod(Selector Sel, MultiExprArg Args,
Match = false;
break;
}
-
+
ImplicitConversionSequence ConversionState
= TryCopyInitialization(*this, argExpr, param->getType(),
/*SuppressUserConversions*/false,
@@ -5809,27 +5918,36 @@ ObjCMethodDecl *Sema::SelectBestMethod(Selector Sel, MultiExprArg Args,
return nullptr;
}
-static bool IsNotEnableIfAttr(Attr *A) { return !isa<EnableIfAttr>(A); }
+// specific_attr_iterator iterates over enable_if attributes in reverse, and
+// enable_if is order-sensitive. As a result, we need to reverse things
+// sometimes. Size of 4 elements is arbitrary.
+static SmallVector<EnableIfAttr *, 4>
+getOrderedEnableIfAttrs(const FunctionDecl *Function) {
+ SmallVector<EnableIfAttr *, 4> Result;
+ if (!Function->hasAttrs())
+ return Result;
+
+ const auto &FuncAttrs = Function->getAttrs();
+ for (Attr *Attr : FuncAttrs)
+ if (auto *EnableIf = dyn_cast<EnableIfAttr>(Attr))
+ Result.push_back(EnableIf);
+
+ std::reverse(Result.begin(), Result.end());
+ return Result;
+}
EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
bool MissingImplicitThis) {
- // FIXME: specific_attr_iterator<EnableIfAttr> iterates in reverse order, but
- // we need to find the first failing one.
- if (!Function->hasAttrs())
- return nullptr;
- AttrVec Attrs = Function->getAttrs();
- AttrVec::iterator E = std::remove_if(Attrs.begin(), Attrs.end(),
- IsNotEnableIfAttr);
- if (Attrs.begin() == E)
+ auto EnableIfAttrs = getOrderedEnableIfAttrs(Function);
+ if (EnableIfAttrs.empty())
return nullptr;
- std::reverse(Attrs.begin(), E);
SFINAETrap Trap(*this);
-
- // Convert the arguments.
SmallVector<Expr *, 16> ConvertedArgs;
bool InitializationFailed = false;
bool ContainsValueDependentExpr = false;
+
+ // Convert the arguments.
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
if (i == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) &&
!cast<CXXMethodDecl>(Function)->isStatic() &&
@@ -5861,11 +5979,32 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
}
if (InitializationFailed || Trap.hasErrorOccurred())
- return cast<EnableIfAttr>(Attrs[0]);
+ return EnableIfAttrs[0];
+
+ // Push default arguments if needed.
+ if (!Function->isVariadic() && Args.size() < Function->getNumParams()) {
+ for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) {
+ ParmVarDecl *P = Function->getParamDecl(i);
+ ExprResult R = PerformCopyInitialization(
+ InitializedEntity::InitializeParameter(Context,
+ Function->getParamDecl(i)),
+ SourceLocation(),
+ P->hasUninstantiatedDefaultArg() ? P->getUninstantiatedDefaultArg()
+ : P->getDefaultArg());
+ if (R.isInvalid()) {
+ InitializationFailed = true;
+ break;
+ }
+ ContainsValueDependentExpr |= R.get()->isValueDependent();
+ ConvertedArgs.push_back(R.get());
+ }
+
+ if (InitializationFailed || Trap.hasErrorOccurred())
+ return EnableIfAttrs[0];
+ }
- for (AttrVec::iterator I = Attrs.begin(); I != E; ++I) {
+ for (auto *EIA : EnableIfAttrs) {
APValue Result;
- EnableIfAttr *EIA = cast<EnableIfAttr>(*I);
if (EIA->getCond()->isValueDependent()) {
// Don't even try now, we'll examine it after instantiation.
continue;
@@ -6027,9 +6166,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
else {
// Determine the implicit conversion sequence for the object
// parameter.
- Candidate.Conversions[0]
- = TryObjectArgumentInitialization(*this, ObjectType, ObjectClassification,
- Method, ActingContext);
+ Candidate.Conversions[0] = TryObjectArgumentInitialization(
+ *this, CandidateSet.getLocation(), ObjectType, ObjectClassification,
+ Method, ActingContext);
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -6286,10 +6425,9 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
CXXRecordDecl *ConversionContext
= cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl());
- Candidate.Conversions[0]
- = TryObjectArgumentInitialization(*this, From->getType(),
- From->Classify(Context),
- Conversion, ConversionContext);
+ Candidate.Conversions[0] = TryObjectArgumentInitialization(
+ *this, CandidateSet.getLocation(), From->getType(),
+ From->Classify(Context), Conversion, ConversionContext);
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
@@ -6303,7 +6441,8 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
QualType FromCanon
= Context.getCanonicalType(From->getType().getUnqualifiedType());
QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
- if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) {
+ if (FromCanon == ToCanon ||
+ IsDerivedFrom(CandidateSet.getLocation(), FromCanon, ToCanon)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_trivial_conversion;
return;
@@ -6325,7 +6464,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
&ConversionRef, VK_RValue);
QualType ConversionType = Conversion->getConversionType();
- if (RequireCompleteType(From->getLocStart(), ConversionType, 0)) {
+ if (!isCompleteType(From->getLocStart(), ConversionType)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_final_conversion;
return;
@@ -6463,10 +6602,9 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
// Determine the implicit conversion sequence for the implicit
// object parameter.
- ImplicitConversionSequence ObjectInit
- = TryObjectArgumentInitialization(*this, Object->getType(),
- Object->Classify(Context),
- Conversion, ActingContext);
+ ImplicitConversionSequence ObjectInit = TryObjectArgumentInitialization(
+ *this, CandidateSet.getLocation(), Object->getType(),
+ Object->Classify(Context), Conversion, ActingContext);
if (ObjectInit.isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -6575,7 +6713,8 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
// the set of member candidates is empty.
if (const RecordType *T1Rec = T1->getAs<RecordType>()) {
// Complete the type if it can be completed.
- RequireCompleteType(OpLoc, T1, 0);
+ if (!isCompleteType(OpLoc, T1) && !T1Rec->isBeingDefined())
+ return;
// If the type is neither complete nor being defined, bail out now.
if (!T1Rec->getDecl()->getDefinition())
return;
@@ -6924,7 +7063,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
HasNullPtrType = true;
} else if (AllowUserConversions && TyRec) {
// No conversion functions in incomplete types.
- if (SemaRef.RequireCompleteType(Loc, Ty, 0))
+ if (!SemaRef.isCompleteType(Loc, Ty))
return;
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
@@ -7527,7 +7666,7 @@ public:
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (int Arg = 0; Arg < 2; ++Arg) {
- QualType AsymetricParamTypes[2] = {
+ QualType AsymmetricParamTypes[2] = {
S.Context.getPointerDiffType(),
S.Context.getPointerDiffType(),
};
@@ -7539,11 +7678,11 @@ public:
if (!PointeeTy->isObjectType())
continue;
- AsymetricParamTypes[Arg] = *Ptr;
+ AsymmetricParamTypes[Arg] = *Ptr;
if (Arg == 0 || Op == OO_Plus) {
// operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t)
// T* operator+(ptrdiff_t, T*);
- S.AddBuiltinCandidate(*Ptr, AsymetricParamTypes, Args, CandidateSet);
+ S.AddBuiltinCandidate(*Ptr, AsymmetricParamTypes, Args, CandidateSet);
}
if (Op == OO_Minus) {
// ptrdiff_t operator-(T, T);
@@ -8013,7 +8152,7 @@ public:
const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr);
QualType C2 = QualType(mptr->getClass(), 0);
C2 = C2.getUnqualifiedType();
- if (C1 != C2 && !S.IsDerivedFrom(C1, C2))
+ if (C1 != C2 && !S.IsDerivedFrom(CandidateSet.getLocation(), C1, C2))
break;
QualType ParamTypes[2] = { *Ptr, *MemPtr };
// build CV12 T&
@@ -8157,9 +8296,11 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
case OO_Comma:
case OO_Arrow:
+ case OO_Coawait:
// C++ [over.match.oper]p3:
- // -- For the operator ',', the unary operator '&', or the
- // operator '->', the built-in candidates set is empty.
+ // -- For the operator ',', the unary operator '&', the
+ // operator '->', or the operator 'co_await', the
+ // built-in candidates set is empty.
break;
case OO_Plus: // '+' is either unary or binary
@@ -8328,6 +8469,44 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
}
}
+// Determines whether Cand1 is "better" in terms of its enable_if attrs than
+// Cand2 for overloading. This function assumes that all of the enable_if attrs
+// on Cand1 and Cand2 have conditions that evaluate to true.
+//
+// Cand1's set of enable_if attributes are said to be "better" than Cand2's iff
+// Cand1's first N enable_if attributes have precisely the same conditions as
+// Cand2's first N enable_if attributes (where N = the number of enable_if
+// attributes on Cand2), and Cand1 has more than N enable_if attributes.
+static bool hasBetterEnableIfAttrs(Sema &S, const FunctionDecl *Cand1,
+ const FunctionDecl *Cand2) {
+
+ // FIXME: The next several lines are just
+ // specific_attr_iterator<EnableIfAttr> but going in declaration order,
+ // instead of reverse order which is how they're stored in the AST.
+ auto Cand1Attrs = getOrderedEnableIfAttrs(Cand1);
+ auto Cand2Attrs = getOrderedEnableIfAttrs(Cand2);
+
+ // Candidate 1 is better if it has strictly more attributes and
+ // the common sequence is identical.
+ if (Cand1Attrs.size() <= Cand2Attrs.size())
+ return false;
+
+ auto Cand1I = Cand1Attrs.begin();
+ llvm::FoldingSetNodeID Cand1ID, Cand2ID;
+ for (auto &Cand2A : Cand2Attrs) {
+ Cand1ID.clear();
+ Cand2ID.clear();
+
+ auto &Cand1A = *Cand1I++;
+ Cand1A->getCond()->Profile(Cand1ID, S.getASTContext(), true);
+ Cand2A->getCond()->Profile(Cand2ID, S.getASTContext(), true);
+ if (Cand1ID != Cand2ID)
+ return false;
+ }
+
+ return true;
+}
+
/// isBetterOverloadCandidate - Determines whether the first overload
/// candidate is a better candidate than the second (C++ 13.3.3p1).
bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
@@ -8359,7 +8538,7 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch");
bool HasBetterConversion = false;
for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
- switch (CompareImplicitConversionSequences(S,
+ switch (CompareImplicitConversionSequences(S, Loc,
Cand1.Conversions[ArgIdx],
Cand2.Conversions[ArgIdx])) {
case ImplicitConversionSequence::Better:
@@ -8398,7 +8577,7 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
ImplicitConversionSequence::CompareKind Result =
compareConversionFunctions(S, Cand1.Function, Cand2.Function);
if (Result == ImplicitConversionSequence::Indistinguishable)
- Result = CompareStandardConversionSequences(S,
+ Result = CompareStandardConversionSequences(S, Loc,
Cand1.FinalConversion,
Cand2.FinalConversion);
@@ -8438,51 +8617,90 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
// Check for enable_if value-based overload resolution.
if (Cand1.Function && Cand2.Function &&
(Cand1.Function->hasAttr<EnableIfAttr>() ||
- Cand2.Function->hasAttr<EnableIfAttr>())) {
- // FIXME: The next several lines are just
- // specific_attr_iterator<EnableIfAttr> but going in declaration order,
- // instead of reverse order which is how they're stored in the AST.
- AttrVec Cand1Attrs;
- if (Cand1.Function->hasAttrs()) {
- Cand1Attrs = Cand1.Function->getAttrs();
- Cand1Attrs.erase(std::remove_if(Cand1Attrs.begin(), Cand1Attrs.end(),
- IsNotEnableIfAttr),
- Cand1Attrs.end());
- std::reverse(Cand1Attrs.begin(), Cand1Attrs.end());
- }
-
- AttrVec Cand2Attrs;
- if (Cand2.Function->hasAttrs()) {
- Cand2Attrs = Cand2.Function->getAttrs();
- Cand2Attrs.erase(std::remove_if(Cand2Attrs.begin(), Cand2Attrs.end(),
- IsNotEnableIfAttr),
- Cand2Attrs.end());
- std::reverse(Cand2Attrs.begin(), Cand2Attrs.end());
- }
-
- // Candidate 1 is better if it has strictly more attributes and
- // the common sequence is identical.
- if (Cand1Attrs.size() <= Cand2Attrs.size())
- return false;
+ Cand2.Function->hasAttr<EnableIfAttr>()))
+ return hasBetterEnableIfAttrs(S, Cand1.Function, Cand2.Function);
+
+ if (S.getLangOpts().CUDA && S.getLangOpts().CUDATargetOverloads &&
+ Cand1.Function && Cand2.Function) {
+ FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext);
+ return S.IdentifyCUDAPreference(Caller, Cand1.Function) >
+ S.IdentifyCUDAPreference(Caller, Cand2.Function);
+ }
+
+ bool HasPS1 = Cand1.Function != nullptr &&
+ functionHasPassObjectSizeParams(Cand1.Function);
+ bool HasPS2 = Cand2.Function != nullptr &&
+ functionHasPassObjectSizeParams(Cand2.Function);
+ return HasPS1 != HasPS2 && HasPS1;
+}
+
+/// Determine whether two declarations are "equivalent" for the purposes of
+/// name lookup and overload resolution. This applies when the same internal/no
+/// linkage entity is defined by two modules (probably by textually including
+/// the same header). In such a case, we don't consider the declarations to
+/// declare the same entity, but we also don't want lookups with both
+/// declarations visible to be ambiguous in some cases (this happens when using
+/// a modularized libstdc++).
+bool Sema::isEquivalentInternalLinkageDeclaration(const NamedDecl *A,
+ const NamedDecl *B) {
+ auto *VA = dyn_cast_or_null<ValueDecl>(A);
+ auto *VB = dyn_cast_or_null<ValueDecl>(B);
+ if (!VA || !VB)
+ return false;
- auto Cand1I = Cand1Attrs.begin();
- for (auto &Cand2A : Cand2Attrs) {
- auto &Cand1A = *Cand1I++;
- llvm::FoldingSetNodeID Cand1ID, Cand2ID;
- cast<EnableIfAttr>(Cand1A)->getCond()->Profile(Cand1ID,
- S.getASTContext(), true);
- cast<EnableIfAttr>(Cand2A)->getCond()->Profile(Cand2ID,
- S.getASTContext(), true);
- if (Cand1ID != Cand2ID)
- return false;
- }
+ // The declarations must be declaring the same name as an internal linkage
+ // entity in different modules.
+ if (!VA->getDeclContext()->getRedeclContext()->Equals(
+ VB->getDeclContext()->getRedeclContext()) ||
+ getOwningModule(const_cast<ValueDecl *>(VA)) ==
+ getOwningModule(const_cast<ValueDecl *>(VB)) ||
+ VA->isExternallyVisible() || VB->isExternallyVisible())
+ return false;
+ // Check that the declarations appear to be equivalent.
+ //
+ // FIXME: Checking the type isn't really enough to resolve the ambiguity.
+ // For constants and functions, we should check the initializer or body is
+ // the same. For non-constant variables, we shouldn't allow it at all.
+ if (Context.hasSameType(VA->getType(), VB->getType()))
return true;
+
+ // Enum constants within unnamed enumerations will have different types, but
+ // may still be similar enough to be interchangeable for our purposes.
+ if (auto *EA = dyn_cast<EnumConstantDecl>(VA)) {
+ if (auto *EB = dyn_cast<EnumConstantDecl>(VB)) {
+ // Only handle anonymous enums. If the enumerations were named and
+ // equivalent, they would have been merged to the same type.
+ auto *EnumA = cast<EnumDecl>(EA->getDeclContext());
+ auto *EnumB = cast<EnumDecl>(EB->getDeclContext());
+ if (EnumA->hasNameForLinkage() || EnumB->hasNameForLinkage() ||
+ !Context.hasSameType(EnumA->getIntegerType(),
+ EnumB->getIntegerType()))
+ return false;
+ // Allow this only if the value is the same for both enumerators.
+ return llvm::APSInt::isSameValue(EA->getInitVal(), EB->getInitVal());
+ }
}
+ // Nothing else is sufficiently similar.
return false;
}
+void Sema::diagnoseEquivalentInternalLinkageDeclarations(
+ SourceLocation Loc, const NamedDecl *D, ArrayRef<const NamedDecl *> Equiv) {
+ Diag(Loc, diag::ext_equivalent_internal_linkage_decl_in_modules) << D;
+
+ Module *M = getOwningModule(const_cast<NamedDecl*>(D));
+ Diag(D->getLocation(), diag::note_equivalent_internal_linkage_decl)
+ << !M << (M ? M->getFullModuleName() : "");
+
+ for (auto *E : Equiv) {
+ Module *M = getOwningModule(const_cast<NamedDecl*>(E));
+ Diag(E->getLocation(), diag::note_equivalent_internal_linkage_decl)
+ << !M << (M ? M->getFullModuleName() : "");
+ }
+}
+
/// \brief Computes the best viable function (C++ 13.3.3)
/// within an overload candidate set.
///
@@ -8510,6 +8728,8 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
if (Best == end())
return OR_No_Viable_Function;
+ llvm::SmallVector<const NamedDecl *, 4> EquivalentCands;
+
// Make sure that this function is better than every other viable
// function. If not, we have an ambiguity.
for (iterator Cand = begin(); Cand != end(); ++Cand) {
@@ -8517,6 +8737,12 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
Cand != Best &&
!isBetterOverloadCandidate(S, *Best, *Cand, Loc,
UserDefinedConversion)) {
+ if (S.isEquivalentInternalLinkageDeclaration(Best->Function,
+ Cand->Function)) {
+ EquivalentCands.push_back(Cand->Function);
+ continue;
+ }
+
Best = end();
return OR_Ambiguous;
}
@@ -8528,6 +8754,10 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
S.isFunctionConsideredUnavailable(Best->Function)))
return OR_Deleted;
+ if (!EquivalentCands.empty())
+ S.diagnoseEquivalentInternalLinkageDeclarations(Loc, Best->Function,
+ EquivalentCands);
+
return OR_Success;
}
@@ -8608,12 +8838,85 @@ void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) {
} // end anonymous namespace
+static bool isFunctionAlwaysEnabled(const ASTContext &Ctx,
+ const FunctionDecl *FD) {
+ for (auto *EnableIf : FD->specific_attrs<EnableIfAttr>()) {
+ bool AlwaysTrue;
+ if (!EnableIf->getCond()->EvaluateAsBooleanCondition(AlwaysTrue, Ctx))
+ return false;
+ if (!AlwaysTrue)
+ return false;
+ }
+ return true;
+}
+
+/// \brief Returns true if we can take the address of the function.
+///
+/// \param Complain - If true, we'll emit a diagnostic
+/// \param InOverloadResolution - For the purposes of emitting a diagnostic, are
+/// we in overload resolution?
+/// \param Loc - The location of the statement we're complaining about. Ignored
+/// if we're not complaining, or if we're in overload resolution.
+static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
+ bool Complain,
+ bool InOverloadResolution,
+ SourceLocation Loc) {
+ if (!isFunctionAlwaysEnabled(S.Context, FD)) {
+ if (Complain) {
+ if (InOverloadResolution)
+ S.Diag(FD->getLocStart(),
+ diag::note_addrof_ovl_candidate_disabled_by_enable_if_attr);
+ else
+ S.Diag(Loc, diag::err_addrof_function_disabled_by_enable_if_attr) << FD;
+ }
+ return false;
+ }
+
+ auto I = std::find_if(FD->param_begin(), FD->param_end(),
+ std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>));
+ if (I == FD->param_end())
+ return true;
+
+ if (Complain) {
+ // Add one to ParamNo because it's user-facing
+ unsigned ParamNo = std::distance(FD->param_begin(), I) + 1;
+ if (InOverloadResolution)
+ S.Diag(FD->getLocation(),
+ diag::note_ovl_candidate_has_pass_object_size_params)
+ << ParamNo;
+ else
+ S.Diag(Loc, diag::err_address_of_function_with_pass_object_size_params)
+ << FD << ParamNo;
+ }
+ return false;
+}
+
+static bool checkAddressOfCandidateIsAvailable(Sema &S,
+ const FunctionDecl *FD) {
+ return checkAddressOfFunctionIsAvailable(S, FD, /*Complain=*/true,
+ /*InOverloadResolution=*/true,
+ /*Loc=*/SourceLocation());
+}
+
+bool Sema::checkAddressOfFunctionIsAvailable(const FunctionDecl *Function,
+ bool Complain,
+ SourceLocation Loc) {
+ return ::checkAddressOfFunctionIsAvailable(*this, Function, Complain,
+ /*InOverloadResolution=*/false,
+ Loc);
+}
+
// Notes the location of an overload candidate.
-void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) {
+void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType,
+ bool TakingAddress) {
+ if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn))
+ return;
+
std::string FnDesc;
OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc);
PartialDiagnostic PD = PDiag(diag::note_ovl_candidate)
<< (unsigned) K << FnDesc;
+
HandleFunctionTypeMismatch(PD, Fn->getType(), DestType);
Diag(Fn->getLocation(), PD);
MaybeEmitInheritedConstructorNote(*this, Fn);
@@ -8621,7 +8924,8 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) {
// Notes the location of all overload candidates designated through
// OverloadedExpr
-void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) {
+void Sema::NoteAllOverloadCandidates(Expr *OverloadedExpr, QualType DestType,
+ bool TakingAddress) {
assert(OverloadedExpr->getType() == Context.OverloadTy);
OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr);
@@ -8632,10 +8936,11 @@ void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) {
I != IEnd; ++I) {
if (FunctionTemplateDecl *FunTmpl =
dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) {
- NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType);
+ NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType,
+ TakingAddress);
} else if (FunctionDecl *Fun
= dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) {
- NoteOverloadCandidate(Fun, DestType);
+ NoteOverloadCandidate(Fun, DestType, TakingAddress);
}
}
}
@@ -8666,7 +8971,7 @@ void ImplicitConversionSequence::DiagnoseAmbiguousConversion(
}
static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
- unsigned I) {
+ unsigned I, bool TakingCandidateAddress) {
const ImplicitConversionSequence &Conv = Cand->Conversions[I];
assert(Conv.isBad());
assert(Cand->Function && "for now, candidate must be a function");
@@ -8808,7 +9113,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
FromPtrTy->getPointeeType()) &&
!FromPtrTy->getPointeeType()->isIncompleteType() &&
!ToPtrTy->getPointeeType()->isIncompleteType() &&
- S.IsDerivedFrom(ToPtrTy->getPointeeType(),
+ S.IsDerivedFrom(SourceLocation(), ToPtrTy->getPointeeType(),
FromPtrTy->getPointeeType()))
BaseToDerivedConversion = 1;
}
@@ -8826,7 +9131,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) &&
!FromTy->isIncompleteType() &&
!ToRefTy->getPointeeType()->isIncompleteType() &&
- S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy)) {
+ S.IsDerivedFrom(SourceLocation(), ToRefTy->getPointeeType(), FromTy)) {
BaseToDerivedConversion = 3;
} else if (ToTy->isLValueReferenceType() && !FromExpr->isLValue() &&
ToTy.getNonReferenceType().getCanonicalType() ==
@@ -8864,7 +9169,11 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
return;
}
}
-
+
+ if (TakingCandidateAddress &&
+ !checkAddressOfCandidateIsAvailable(S, Cand->Function))
+ return;
+
// Emit the generic diagnostic and, optionally, add the hints to it.
PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv);
FDiag << (unsigned) FnKind << FnDesc
@@ -8975,7 +9284,8 @@ static TemplateDecl *getDescribedTemplate(Decl *Templated) {
/// Diagnose a failed template-argument deduction.
static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
DeductionFailureInfo &DeductionFailure,
- unsigned NumArgs) {
+ unsigned NumArgs,
+ bool TakingCandidateAddress) {
TemplateParameter Param = DeductionFailure.getTemplateParameter();
NamedDecl *ParamD;
(ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
@@ -9118,6 +9428,23 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
return;
}
+ case Sema::TDK_DeducedMismatch: {
+ // Format the template argument list into the argument string.
+ SmallString<128> TemplateArgString;
+ if (TemplateArgumentList *Args =
+ DeductionFailure.getTemplateArgumentList()) {
+ TemplateArgString = " ";
+ TemplateArgString += S.getTemplateArgumentBindingsText(
+ getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
+ }
+
+ S.Diag(Templated->getLocation(), diag::note_ovl_candidate_deduced_mismatch)
+ << (*DeductionFailure.getCallArgIndex() + 1)
+ << *DeductionFailure.getFirstArg() << *DeductionFailure.getSecondArg()
+ << TemplateArgString;
+ break;
+ }
+
case Sema::TDK_NonDeducedMismatch: {
// FIXME: Provide a source location to indicate what we couldn't match.
TemplateArgument FirstTA = *DeductionFailure.getFirstArg();
@@ -9143,6 +9470,11 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
}
}
}
+
+ if (TakingCandidateAddress && isa<FunctionDecl>(Templated) &&
+ !checkAddressOfCandidateIsAvailable(S, cast<FunctionDecl>(Templated)))
+ return;
+
// FIXME: For generic lambda parameters, check if the function is a lambda
// call operator, and if so, emit a prettier and more informative
// diagnostic that mentions 'auto' and lambda in addition to
@@ -9163,14 +9495,15 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
/// Diagnose a failed template-argument deduction, for function calls.
static void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
- unsigned NumArgs) {
+ unsigned NumArgs,
+ bool TakingCandidateAddress) {
unsigned TDK = Cand->DeductionFailure.Result;
if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) {
if (CheckArityMismatch(S, Cand, NumArgs))
return;
}
DiagnoseBadDeduction(S, Cand->Function, // pattern
- Cand->DeductionFailure, NumArgs);
+ Cand->DeductionFailure, NumArgs, TakingCandidateAddress);
}
/// CUDA: diagnose an invalid call across targets.
@@ -9251,7 +9584,8 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
/// more richly for those diagnostic clients that cared, but we'd
/// still have to be just as careful with the default diagnostics.
static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
- unsigned NumArgs) {
+ unsigned NumArgs,
+ bool TakingCandidateAddress) {
FunctionDecl *Fn = Cand->Function;
// Note deleted candidates, but only if they're viable.
@@ -9279,7 +9613,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
return DiagnoseArityMismatch(S, Cand, NumArgs);
case ovl_fail_bad_deduction:
- return DiagnoseBadDeduction(S, Cand, NumArgs);
+ return DiagnoseBadDeduction(S, Cand, NumArgs, TakingCandidateAddress);
case ovl_fail_illegal_constructor: {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_illegal_constructor)
@@ -9297,7 +9631,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
for (unsigned N = Cand->NumConversions; I != N; ++I)
if (Cand->Conversions[I].isBad())
- return DiagnoseBadConversion(S, Cand, I);
+ return DiagnoseBadConversion(S, Cand, I, TakingCandidateAddress);
// FIXME: this currently happens when we're called from SemaInit
// when user-conversion overload fails. Figure out how to handle
@@ -9310,6 +9644,13 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
case ovl_fail_enable_if:
return DiagnoseFailedEnableIfAttr(S, Cand);
+
+ case ovl_fail_addr_not_available: {
+ bool Available = checkAddressOfCandidateIsAvailable(S, Cand->Function);
+ (void)Available;
+ assert(!Available);
+ break;
+ }
}
}
@@ -9400,6 +9741,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
return 2;
case Sema::TDK_SubstitutionFailure:
+ case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_MiscellaneousDeductionFailure:
return 3;
@@ -9421,9 +9763,10 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
namespace {
struct CompareOverloadCandidatesForDisplay {
Sema &S;
+ SourceLocation Loc;
size_t NumArgs;
- CompareOverloadCandidatesForDisplay(Sema &S, size_t nArgs)
+ CompareOverloadCandidatesForDisplay(Sema &S, SourceLocation Loc, size_t nArgs)
: S(S), NumArgs(nArgs) {}
bool operator()(const OverloadCandidate *L,
@@ -9494,7 +9837,7 @@ struct CompareOverloadCandidatesForDisplay {
int leftBetter = 0;
unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument);
for (unsigned E = L->NumConversions; I != E; ++I) {
- switch (CompareImplicitConversionSequences(S,
+ switch (CompareImplicitConversionSequences(S, Loc,
L->Conversions[I],
R->Conversions[I])) {
case ImplicitConversionSequence::Better:
@@ -9649,7 +9992,7 @@ void OverloadCandidateSet::NoteCandidates(Sema &S,
}
std::sort(Cands.begin(), Cands.end(),
- CompareOverloadCandidatesForDisplay(S, Args.size()));
+ CompareOverloadCandidatesForDisplay(S, OpLoc, Args.size()));
bool ReportedAmbiguousConversions = false;
@@ -9668,7 +10011,8 @@ void OverloadCandidateSet::NoteCandidates(Sema &S,
++CandsShown;
if (Cand->Function)
- NoteFunctionCandidate(S, Cand, Args.size());
+ NoteFunctionCandidate(S, Cand, Args.size(),
+ /*TakingCandidateAddress=*/false);
else if (Cand->IsSurrogate)
NoteSurrogateCandidate(S, Cand);
else {
@@ -9736,9 +10080,10 @@ struct CompareTemplateSpecCandidatesForDisplay {
/// Diagnose a template argument deduction failure.
/// We are treating these failures as overload failures due to bad
/// deductions.
-void TemplateSpecCandidate::NoteDeductionFailure(Sema &S) {
+void TemplateSpecCandidate::NoteDeductionFailure(Sema &S,
+ bool ForTakingAddress) {
DiagnoseBadDeduction(S, Specialization, // pattern
- DeductionFailure, /*NumArgs=*/0);
+ DeductionFailure, /*NumArgs=*/0, ForTakingAddress);
}
void TemplateSpecCandidateSet::destroyCandidates() {
@@ -9791,7 +10136,7 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
assert(Cand->Specialization &&
"Non-matching built-in candidates are not added to Cands.");
- Cand->NoteDeductionFailure(S);
+ Cand->NoteDeductionFailure(S, ForTakingAddress);
}
if (I != E)
@@ -9836,6 +10181,7 @@ class AddressOfFunctionResolver {
bool TargetTypeIsNonStaticMemberFunction;
bool FoundNonTemplateFunction;
bool StaticMemberFunctionFromBoundPointer;
+ bool HasComplained;
OverloadExpr::FindResult OvlExprInfo;
OverloadExpr *OvlExpr;
@@ -9852,9 +10198,10 @@ public:
!!TargetType->getAs<MemberPointerType>()),
FoundNonTemplateFunction(false),
StaticMemberFunctionFromBoundPointer(false),
+ HasComplained(false),
OvlExprInfo(OverloadExpr::find(SourceExpr)),
OvlExpr(OvlExprInfo.Expression),
- FailedCandidates(OvlExpr->getNameLoc()) {
+ FailedCandidates(OvlExpr->getNameLoc(), /*ForTakingAddress=*/true) {
ExtractUnqualifiedFunctionTypeFromTargetType();
if (TargetFunctionType->isFunctionType()) {
@@ -9885,21 +10232,57 @@ public:
}
if (OvlExpr->hasExplicitTemplateArgs())
- OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs);
+ OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs);
if (FindAllFunctionsThatMatchTargetTypeExactly()) {
// C++ [over.over]p4:
// If more than one function is selected, [...]
- if (Matches.size() > 1) {
+ if (Matches.size() > 1 && !eliminiateSuboptimalOverloadCandidates()) {
if (FoundNonTemplateFunction)
EliminateAllTemplateMatches();
else
EliminateAllExceptMostSpecializedTemplate();
}
}
+
+ if (S.getLangOpts().CUDA && S.getLangOpts().CUDATargetOverloads &&
+ Matches.size() > 1)
+ EliminateSuboptimalCudaMatches();
}
-
+
+ bool hasComplained() const { return HasComplained; }
+
private:
+ // Is A considered a better overload candidate for the desired type than B?
+ bool isBetterCandidate(const FunctionDecl *A, const FunctionDecl *B) {
+ return hasBetterEnableIfAttrs(S, A, B);
+ }
+
+ // Returns true if we've eliminated any (read: all but one) candidates, false
+ // otherwise.
+ bool eliminiateSuboptimalOverloadCandidates() {
+ // Same algorithm as overload resolution -- one pass to pick the "best",
+ // another pass to be sure that nothing is better than the best.
+ auto Best = Matches.begin();
+ for (auto I = Matches.begin()+1, E = Matches.end(); I != E; ++I)
+ if (isBetterCandidate(I->second, Best->second))
+ Best = I;
+
+ const FunctionDecl *BestFn = Best->second;
+ auto IsBestOrInferiorToBest = [this, BestFn](
+ const std::pair<DeclAccessPair, FunctionDecl *> &Pair) {
+ return BestFn == Pair.second || isBetterCandidate(BestFn, Pair.second);
+ };
+
+ // Note: We explicitly leave Matches unmodified if there isn't a clear best
+ // option, so we can potentially give the user a better error
+ if (!std::all_of(Matches.begin(), Matches.end(), IsBestOrInferiorToBest))
+ return false;
+ Matches[0] = *Best;
+ Matches.resize(1);
+ return true;
+ }
+
bool isTargetTypeAFunction() const {
return TargetFunctionType->isFunctionType();
}
@@ -9953,6 +10336,10 @@ private:
assert(S.isSameOrCompatibleFunctionType(
Context.getCanonicalType(Specialization->getType()),
Context.getCanonicalType(TargetFunctionType)));
+
+ if (!S.checkAddressOfFunctionIsAvailable(Specialization))
+ return false;
+
Matches.push_back(std::make_pair(CurAccessFunPair, Specialization));
return true;
}
@@ -9978,16 +10365,22 @@ private:
// now.
if (S.getLangOpts().CPlusPlus14 &&
FunDecl->getReturnType()->isUndeducedType() &&
- S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain))
+ S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain)) {
+ HasComplained |= Complain;
+ return false;
+ }
+
+ if (!S.checkAddressOfFunctionIsAvailable(FunDecl))
return false;
QualType ResultTy;
if (Context.hasSameUnqualifiedType(TargetFunctionType,
FunDecl->getType()) ||
S.IsNoReturnConversion(FunDecl->getType(), TargetFunctionType,
- ResultTy)) {
- Matches.push_back(std::make_pair(CurAccessFunPair,
- cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
+ ResultTy) ||
+ (!S.getLangOpts().CPlusPlus && TargetType->isVoidPointerType())) {
+ Matches.push_back(std::make_pair(
+ CurAccessFunPair, cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
FoundNonTemplateFunction = true;
return true;
}
@@ -10061,7 +10454,8 @@ private:
Matches[0].first = Matches[Result - MatchesCopy.begin()].first;
Matches[0].second = cast<FunctionDecl>(*Result);
Matches.resize(1);
- }
+ } else
+ HasComplained |= Complain;
}
void EliminateAllTemplateMatches() {
@@ -10072,11 +10466,15 @@ private:
++I;
else {
Matches[I] = Matches[--N];
- Matches.set_size(N);
+ Matches.resize(N);
}
}
}
+ void EliminateSuboptimalCudaMatches() {
+ S.EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(S.CurContext), Matches);
+ }
+
public:
void ComplainNoMatchesFound() const {
assert(Matches.empty());
@@ -10084,7 +10482,8 @@ public:
<< OvlExpr->getName() << TargetFunctionType
<< OvlExpr->getSourceRange();
if (FailedCandidates.empty())
- S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
+ S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType,
+ /*TakingAddress=*/true);
else {
// We have some deduction failure messages. Use them to diagnose
// the function templates, and diagnose the non-template candidates
@@ -10094,7 +10493,9 @@ public:
I != IEnd; ++I)
if (FunctionDecl *Fun =
dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()))
- S.NoteOverloadCandidate(Fun, TargetFunctionType);
+ if (!functionHasPassObjectSizeParams(Fun))
+ S.NoteOverloadCandidate(Fun, TargetFunctionType,
+ /*TakingAddress=*/true);
FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart());
}
}
@@ -10132,7 +10533,8 @@ public:
S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous)
<< OvlExpr->getName()
<< OvlExpr->getSourceRange();
- S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
+ S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType,
+ /*TakingAddress=*/true);
}
bool hadMultipleCandidates() const { return (OvlExpr->getNumDecls() > 1); }
@@ -10178,13 +10580,14 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
Complain);
int NumMatches = Resolver.getNumMatches();
FunctionDecl *Fn = nullptr;
- if (NumMatches == 0 && Complain) {
+ bool ShouldComplain = Complain && !Resolver.hasComplained();
+ if (NumMatches == 0 && ShouldComplain) {
if (Resolver.IsInvalidFormOfPointerToMemberFunction())
Resolver.ComplainIsInvalidFormOfPointerToMemberFunction();
else
Resolver.ComplainNoMatchesFound();
}
- else if (NumMatches > 1 && Complain)
+ else if (NumMatches > 1 && ShouldComplain)
Resolver.ComplainMultipleMatchesFound();
else if (NumMatches == 1) {
Fn = Resolver.getMatchingFunctionDecl();
@@ -10229,7 +10632,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
return nullptr;
TemplateArgumentListInfo ExplicitTemplateArgs;
- ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+ ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc());
// Look through all of the overloaded functions, searching for one
@@ -10303,7 +10706,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
// returns true if 'complain' is set.
bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
ExprResult &SrcExpr, bool doFunctionPointerConverion,
- bool complain, const SourceRange& OpRangeForComplaining,
+ bool complain, SourceRange OpRangeForComplaining,
QualType DestTypeForComplaining,
unsigned DiagIDForComplaining) {
assert(SrcExpr.get()->getType() == Context.OverloadTy);
@@ -10678,8 +11081,8 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
// casts and such from the call, we don't really care.
ExprResult NewFn = ExprError();
if ((*R.begin())->isCXXClassMember())
- NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
- R, ExplicitTemplateArgs);
+ NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R,
+ ExplicitTemplateArgs, S);
else if (ExplicitTemplateArgs || TemplateKWLoc.isValid())
NewFn = SemaRef.BuildTemplateIdExpr(SS, TemplateKWLoc, R, false,
ExplicitTemplateArgs);
@@ -10749,6 +11152,8 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
CallExpr *CE = new (Context) CallExpr(
Context, Fn, Args, Context.DependentTy, VK_RValue, RParenLoc);
CE->setTypeDependent(true);
+ CE->setValueDependent(true);
+ CE->setInstantiationDependent(true);
*Result = CE;
return true;
}
@@ -10800,9 +11205,23 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
if (!Recovery.isInvalid())
return Recovery;
- SemaRef.Diag(Fn->getLocStart(),
- diag::err_ovl_no_viable_function_in_call)
- << ULE->getName() << Fn->getSourceRange();
+ // If the user passes in a function that we can't take the address of, we
+ // generally end up emitting really bad error messages. Here, we attempt to
+ // emit better ones.
+ for (const Expr *Arg : Args) {
+ if (!Arg->getType()->isFunctionType())
+ continue;
+ if (auto *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenImpCasts())) {
+ auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl());
+ if (FD &&
+ !SemaRef.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
+ Arg->getExprLoc()))
+ return ExprError();
+ }
+ }
+
+ SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_no_viable_function_in_call)
+ << ULE->getName() << Fn->getSourceRange();
CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args);
break;
}
@@ -10834,6 +11253,17 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
return ExprError();
}
+static void markUnaddressableCandidatesUnviable(Sema &S,
+ OverloadCandidateSet &CS) {
+ for (auto I = CS.begin(), E = CS.end(); I != E; ++I) {
+ if (I->Viable &&
+ !S.checkAddressOfFunctionIsAvailable(I->Function, /*Complain=*/false)) {
+ I->Viable = false;
+ I->FailureKind = ovl_fail_addr_not_available;
+ }
+ }
+}
+
/// BuildOverloadedCallExpr - Given the call expression that calls Fn
/// (which eventually refers to the declaration Func) and the call
/// arguments Args/NumArgs, attempt to resolve the function call down
@@ -10846,7 +11276,8 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
MultiExprArg Args,
SourceLocation RParenLoc,
Expr *ExecConfig,
- bool AllowTypoCorrection) {
+ bool AllowTypoCorrection,
+ bool CalleesAddressIsTaken) {
OverloadCandidateSet CandidateSet(Fn->getExprLoc(),
OverloadCandidateSet::CSK_Normal);
ExprResult result;
@@ -10855,6 +11286,11 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
&result))
return result;
+ // If the user handed us something like `(&Foo)(Bar)`, we need to ensure that
+ // functions that aren't addressible are considered unviable.
+ if (CalleesAddressIsTaken)
+ markUnaddressableCandidatesUnviable(*this, CandidateSet);
+
OverloadCandidateSet::iterator Best;
OverloadingResult OverloadResult =
CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best);
@@ -10875,8 +11311,7 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
///
/// \param OpLoc The location of the operator itself (e.g., '*').
///
-/// \param OpcIn The UnaryOperator::Opcode that describes this
-/// operator.
+/// \param Opc The UnaryOperatorKind that describes this operator.
///
/// \param Fns The set of non-member functions that will be
/// considered by overload resolution. The caller needs to build this
@@ -10887,11 +11322,9 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
///
/// \param Input The input argument.
ExprResult
-Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
+Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
Expr *Input) {
- UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn);
-
OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc);
assert(Op != OO_None && "Invalid opcode for overloaded unary operator");
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
@@ -11062,8 +11495,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
///
/// \param OpLoc The location of the operator itself (e.g., '+').
///
-/// \param OpcIn The BinaryOperator::Opcode that describes this
-/// operator.
+/// \param Opc The BinaryOperatorKind that describes this operator.
///
/// \param Fns The set of non-member functions that will be
/// considered by overload resolution. The caller needs to build this
@@ -11076,13 +11508,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
/// \param RHS Right-hand argument.
ExprResult
Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
- unsigned OpcIn,
+ BinaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
Expr *LHS, Expr *RHS) {
Expr *Args[2] = { LHS, RHS };
LHS=RHS=nullptr; // Please use only Args instead of LHS/RHS couple
- BinaryOperator::Opcode Opc = static_cast<BinaryOperator::Opcode>(OpcIn);
OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
@@ -11565,10 +11996,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
<< (qualsString.find(' ') == std::string::npos ? 1 : 2);
}
- if (resultType->isMemberPointerType())
- if (Context.getTargetInfo().getCXXABI().isMicrosoft())
- RequireCompleteType(LParenLoc, resultType, 0);
-
CXXMemberCallExpr *call
= new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
resultType, valueKind, RParenLoc);
@@ -11767,18 +12194,39 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
if (CheckFunctionCall(Method, TheCall, Proto))
return ExprError();
+ // In the case the method to call was not selected by the overloading
+ // resolution process, we still need to handle the enable_if attribute. Do
+ // that here, so it will not hide previous -- and more relevant -- errors
+ if (isa<MemberExpr>(NakedMemExpr)) {
+ if (const EnableIfAttr *Attr = CheckEnableIf(Method, Args, true)) {
+ Diag(MemExprE->getLocStart(),
+ diag::err_ovl_no_viable_member_function_in_call)
+ << Method << Method->getSourceRange();
+ Diag(Method->getLocation(),
+ diag::note_ovl_candidate_disabled_by_enable_if_attr)
+ << Attr->getCond()->getSourceRange() << Attr->getMessage();
+ return ExprError();
+ }
+ }
+
if ((isa<CXXConstructorDecl>(CurContext) ||
isa<CXXDestructorDecl>(CurContext)) &&
TheCall->getMethodDecl()->isPure()) {
const CXXMethodDecl *MD = TheCall->getMethodDecl();
- if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts())) {
- Diag(MemExpr->getLocStart(),
+ if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts()) &&
+ MemExpr->performsVirtualDispatch(getLangOpts())) {
+ Diag(MemExpr->getLocStart(),
diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor)
<< MD->getDeclName() << isa<CXXDestructorDecl>(CurContext)
<< MD->getParent()->getDeclName();
Diag(MD->getLocStart(), diag::note_previous_decl) << MD->getDeclName();
+ if (getLangOpts().AppleKext)
+ Diag(MemExpr->getLocStart(),
+ diag::note_pure_qualified_call_kext)
+ << MD->getParent()->getDeclName()
+ << MD->getDeclName();
}
}
return MaybeBindToTemporary(TheCall);
@@ -12267,13 +12715,14 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
/// otherwise CallExpr is set to ExprError() and some non-success value
/// is returned.
Sema::ForRangeStatus
-Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
- SourceLocation RangeLoc, VarDecl *Decl,
- BeginEndFunction BEF,
+Sema::BuildForRangeBeginEndCall(SourceLocation Loc,
+ SourceLocation RangeLoc,
const DeclarationNameInfo &NameInfo,
LookupResult &MemberLookup,
OverloadCandidateSet *CandidateSet,
Expr *Range, ExprResult *CallExpr) {
+ Scope *S = nullptr;
+
CandidateSet->clear();
if (!MemberLookup.empty()) {
ExprResult MemberRef =
@@ -12282,18 +12731,14 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
/*TemplateKWLoc=*/SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
MemberLookup,
- /*TemplateArgs=*/nullptr);
+ /*TemplateArgs=*/nullptr, S);
if (MemberRef.isInvalid()) {
*CallExpr = ExprError();
- Diag(Range->getLocStart(), diag::note_in_for_range)
- << RangeLoc << BEF << Range->getType();
return FRS_DiagnosticIssued;
}
*CallExpr = ActOnCallExpr(S, MemberRef.get(), Loc, None, Loc, nullptr);
if (CallExpr->isInvalid()) {
*CallExpr = ExprError();
- Diag(Range->getLocStart(), diag::note_in_for_range)
- << RangeLoc << BEF << Range->getType();
return FRS_DiagnosticIssued;
}
} else {
@@ -12324,8 +12769,6 @@ Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
/*AllowTypoCorrection=*/false);
if (CallExpr->isInvalid() || OverloadResult != OR_Success) {
*CallExpr = ExprError();
- Diag(Range->getLocStart(), diag::note_in_for_range)
- << RangeLoc << BEF << Range->getType();
return FRS_DiagnosticIssued;
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
index fec9748..e5d51f1 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp
@@ -44,17 +44,76 @@ using namespace sema;
namespace {
// Basically just a very focused copy of TreeTransform.
- template <class T> struct Rebuilder {
+ struct Rebuilder {
Sema &S;
- Rebuilder(Sema &S) : S(S) {}
+ unsigned MSPropertySubscriptCount;
+ typedef llvm::function_ref<Expr *(Expr *, unsigned)> SpecificRebuilderRefTy;
+ const SpecificRebuilderRefTy &SpecificCallback;
+ Rebuilder(Sema &S, const SpecificRebuilderRefTy &SpecificCallback)
+ : S(S), MSPropertySubscriptCount(0),
+ SpecificCallback(SpecificCallback) {}
+
+ Expr *rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr *refExpr) {
+ // Fortunately, the constraint that we're rebuilding something
+ // with a base limits the number of cases here.
+ if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
+ return refExpr;
+
+ if (refExpr->isExplicitProperty()) {
+ return new (S.Context) ObjCPropertyRefExpr(
+ refExpr->getExplicitProperty(), refExpr->getType(),
+ refExpr->getValueKind(), refExpr->getObjectKind(),
+ refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
+ }
+ return new (S.Context) ObjCPropertyRefExpr(
+ refExpr->getImplicitPropertyGetter(),
+ refExpr->getImplicitPropertySetter(), refExpr->getType(),
+ refExpr->getValueKind(), refExpr->getObjectKind(),
+ refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
+ }
+ Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) {
+ assert(refExpr->getBaseExpr());
+ assert(refExpr->getKeyExpr());
+
+ return new (S.Context) ObjCSubscriptRefExpr(
+ SpecificCallback(refExpr->getBaseExpr(), 0),
+ SpecificCallback(refExpr->getKeyExpr(), 1), refExpr->getType(),
+ refExpr->getValueKind(), refExpr->getObjectKind(),
+ refExpr->getAtIndexMethodDecl(), refExpr->setAtIndexMethodDecl(),
+ refExpr->getRBracket());
+ }
+ Expr *rebuildMSPropertyRefExpr(MSPropertyRefExpr *refExpr) {
+ assert(refExpr->getBaseExpr());
- T &getDerived() { return static_cast<T&>(*this); }
+ return new (S.Context) MSPropertyRefExpr(
+ SpecificCallback(refExpr->getBaseExpr(), 0),
+ refExpr->getPropertyDecl(), refExpr->isArrow(), refExpr->getType(),
+ refExpr->getValueKind(), refExpr->getQualifierLoc(),
+ refExpr->getMemberLoc());
+ }
+ Expr *rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr *refExpr) {
+ assert(refExpr->getBase());
+ assert(refExpr->getIdx());
+
+ auto *NewBase = rebuild(refExpr->getBase());
+ ++MSPropertySubscriptCount;
+ return new (S.Context) MSPropertySubscriptExpr(
+ NewBase,
+ SpecificCallback(refExpr->getIdx(), MSPropertySubscriptCount),
+ refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(),
+ refExpr->getRBracketLoc());
+ }
Expr *rebuild(Expr *e) {
// Fast path: nothing to look through.
- if (typename T::specific_type *specific
- = dyn_cast<typename T::specific_type>(e))
- return getDerived().rebuildSpecific(specific);
+ if (auto *PRE = dyn_cast<ObjCPropertyRefExpr>(e))
+ return rebuildObjCPropertyRefExpr(PRE);
+ if (auto *SRE = dyn_cast<ObjCSubscriptRefExpr>(e))
+ return rebuildObjCSubscriptRefExpr(SRE);
+ if (auto *MSPRE = dyn_cast<MSPropertyRefExpr>(e))
+ return rebuildMSPropertyRefExpr(MSPRE);
+ if (auto *MSPSE = dyn_cast<MSPropertySubscriptExpr>(e))
+ return rebuildMSPropertySubscriptExpr(MSPSE);
// Otherwise, we should look through and rebuild anything that
// IgnoreParens would.
@@ -125,72 +184,6 @@ namespace {
}
};
- struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> {
- Expr *NewBase;
- ObjCPropertyRefRebuilder(Sema &S, Expr *newBase)
- : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {}
-
- typedef ObjCPropertyRefExpr specific_type;
- Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) {
- // Fortunately, the constraint that we're rebuilding something
- // with a base limits the number of cases here.
- assert(refExpr->isObjectReceiver());
-
- if (refExpr->isExplicitProperty()) {
- return new (S.Context)
- ObjCPropertyRefExpr(refExpr->getExplicitProperty(),
- refExpr->getType(), refExpr->getValueKind(),
- refExpr->getObjectKind(), refExpr->getLocation(),
- NewBase);
- }
- return new (S.Context)
- ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(),
- refExpr->getImplicitPropertySetter(),
- refExpr->getType(), refExpr->getValueKind(),
- refExpr->getObjectKind(),refExpr->getLocation(),
- NewBase);
- }
- };
-
- struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> {
- Expr *NewBase;
- Expr *NewKeyExpr;
- ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr)
- : Rebuilder<ObjCSubscriptRefRebuilder>(S),
- NewBase(newBase), NewKeyExpr(newKeyExpr) {}
-
- typedef ObjCSubscriptRefExpr specific_type;
- Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) {
- assert(refExpr->getBaseExpr());
- assert(refExpr->getKeyExpr());
-
- return new (S.Context)
- ObjCSubscriptRefExpr(NewBase,
- NewKeyExpr,
- refExpr->getType(), refExpr->getValueKind(),
- refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(),
- refExpr->setAtIndexMethodDecl(),
- refExpr->getRBracket());
- }
- };
-
- struct MSPropertyRefRebuilder : Rebuilder<MSPropertyRefRebuilder> {
- Expr *NewBase;
- MSPropertyRefRebuilder(Sema &S, Expr *newBase)
- : Rebuilder<MSPropertyRefRebuilder>(S), NewBase(newBase) {}
-
- typedef MSPropertyRefExpr specific_type;
- Expr *rebuildSpecific(MSPropertyRefExpr *refExpr) {
- assert(refExpr->getBaseExpr());
-
- return new (S.Context)
- MSPropertyRefExpr(NewBase, refExpr->getPropertyDecl(),
- refExpr->isArrow(), refExpr->getType(),
- refExpr->getValueKind(), refExpr->getQualifierLoc(),
- refExpr->getMemberLoc());
- }
- };
-
class PseudoOpBuilder {
public:
Sema &S;
@@ -236,7 +229,7 @@ namespace {
}
/// Return true if assignments have a non-void result.
- bool CanCaptureValue(Expr *exp) {
+ static bool CanCaptureValue(Expr *exp) {
if (exp->isGLValue())
return true;
QualType ty = exp->getType();
@@ -252,6 +245,20 @@ namespace {
virtual ExprResult buildGet() = 0;
virtual ExprResult buildSet(Expr *, SourceLocation,
bool captureSetValueAsResult) = 0;
+ /// \brief Should the result of an assignment be the formal result of the
+ /// setter call or the value that was passed to the setter?
+ ///
+ /// Different pseudo-object language features use different language rules
+ /// for this.
+ /// The default is to use the set value. Currently, this affects the
+ /// behavior of simple assignments, compound assignments, and prefix
+ /// increment and decrement.
+ /// Postfix increment and decrement always use the getter result as the
+ /// expression result.
+ ///
+ /// If this method returns true, and the set value isn't capturable for
+ /// some reason, the result of the expression will be void.
+ virtual bool captureSetValueAsResult() const { return true; }
};
/// A PseudoOpBuilder for Objective-C \@properties.
@@ -328,15 +335,25 @@ namespace {
class MSPropertyOpBuilder : public PseudoOpBuilder {
MSPropertyRefExpr *RefExpr;
+ OpaqueValueExpr *InstanceBase;
+ SmallVector<Expr *, 4> CallArgs;
+
+ MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);
public:
MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) :
PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
- RefExpr(refExpr) {}
+ RefExpr(refExpr), InstanceBase(nullptr) {}
+ MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr)
+ : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
+ InstanceBase(nullptr) {
+ RefExpr = getBaseMSProperty(refExpr);
+ }
Expr *rebuildAndCaptureObject(Expr *) override;
ExprResult buildGet() override;
ExprResult buildSet(Expr *op, SourceLocation, bool) override;
+ bool captureSetValueAsResult() const override { return false; }
};
}
@@ -406,19 +423,27 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
BinaryOperatorKind opcode,
Expr *LHS, Expr *RHS) {
assert(BinaryOperator::isAssignmentOp(opcode));
-
- // Recover from user error
- if (isa<UnresolvedLookupExpr>(RHS))
- return ExprError();
Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
OpaqueValueExpr *capturedRHS = capture(RHS);
+ // In some very specific cases, semantic analysis of the RHS as an
+ // expression may require it to be rewritten. In these cases, we
+ // cannot safely keep the OVE around. Fortunately, we don't really
+ // need to: we don't use this particular OVE in multiple places, and
+ // no clients rely that closely on matching up expressions in the
+ // semantic expression with expressions from the syntactic form.
+ Expr *semanticRHS = capturedRHS;
+ if (RHS->hasPlaceholderType() || isa<InitListExpr>(RHS)) {
+ semanticRHS = RHS;
+ Semantics.pop_back();
+ }
+
Expr *syntactic;
ExprResult result;
if (opcode == BO_Assign) {
- result = capturedRHS;
+ result = semanticRHS;
syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
opcode, capturedRHS->getType(),
capturedRHS->getValueKind(),
@@ -430,8 +455,7 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
// Build an ordinary, non-compound operation.
BinaryOperatorKind nonCompound =
BinaryOperator::getOpForCompoundAssignment(opcode);
- result = S.BuildBinOp(Sc, opcLoc, nonCompound,
- opLHS.get(), capturedRHS);
+ result = S.BuildBinOp(Sc, opcLoc, nonCompound, opLHS.get(), semanticRHS);
if (result.isInvalid()) return ExprError();
syntactic =
@@ -446,9 +470,12 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
// The result of the assignment, if not void, is the value set into
// the l-value.
- result = buildSet(result.get(), opcLoc, /*captureSetValueAsResult*/ true);
+ result = buildSet(result.get(), opcLoc, captureSetValueAsResult());
if (result.isInvalid()) return ExprError();
addSemanticExpr(result.get());
+ if (!captureSetValueAsResult() && !result.get()->getType()->isVoidType() &&
+ (result.get()->isTypeDependent() || CanCaptureValue(result.get())))
+ setResultToLastSemantic();
return complete(syntactic);
}
@@ -490,9 +517,14 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
// Store that back into the result. The value stored is the result
// of a prefix operation.
- result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode));
+ result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode) &&
+ captureSetValueAsResult());
if (result.isInvalid()) return ExprError();
addSemanticExpr(result.get());
+ if (UnaryOperator::isPrefix(opcode) && !captureSetValueAsResult() &&
+ !result.get()->getType()->isVoidType() &&
+ (result.get()->isTypeDependent() || CanCaptureValue(result.get())))
+ setResultToLastSemantic();
UnaryOperator *syntactic =
new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
@@ -666,9 +698,9 @@ Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
// form to use the OVE as its base.
if (RefExpr->isObjectReceiver()) {
InstanceReceiver = capture(RefExpr->getBase());
-
- syntacticBase =
- ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
+ syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * {
+ return InstanceReceiver;
+ }).rebuild(syntacticBase);
}
if (ObjCPropertyRefExpr *
@@ -745,16 +777,6 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
op = opResult.get();
assert(op && "successful assignment left argument invalid?");
}
- else if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(op)) {
- Expr *Initializer = OVE->getSourceExpr();
- // passing C++11 style initialized temporaries to objc++ properties
- // requires special treatment by removing OpaqueValueExpr so type
- // conversion takes place and adding the OpaqueValueExpr later on.
- if (isa<InitListExpr>(Initializer) &&
- Initializer->getType()->isVoidType()) {
- op = Initializer;
- }
- }
}
// Arguments.
@@ -996,11 +1018,19 @@ Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
// form to use the OVE as its base expression.
InstanceBase = capture(RefExpr->getBaseExpr());
InstanceKey = capture(RefExpr->getKeyExpr());
-
+
syntacticBase =
- ObjCSubscriptRefRebuilder(S, InstanceBase,
- InstanceKey).rebuild(syntacticBase);
-
+ Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
+ switch (Idx) {
+ case 0:
+ return InstanceBase;
+ case 1:
+ return InstanceKey;
+ default:
+ llvm_unreachable("Unexpected index for ObjCSubscriptExpr");
+ }
+ }).rebuild(syntacticBase);
+
return syntacticBase;
}
@@ -1402,11 +1432,30 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
// MSVC __declspec(property) references
//===----------------------------------------------------------------------===//
-Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
- Expr *NewBase = capture(RefExpr->getBaseExpr());
+MSPropertyRefExpr *
+MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) {
+ CallArgs.insert(CallArgs.begin(), E->getIdx());
+ Expr *Base = E->getBase()->IgnoreParens();
+ while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) {
+ CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx());
+ Base = MSPropSubscript->getBase()->IgnoreParens();
+ }
+ return cast<MSPropertyRefExpr>(Base);
+}
- syntacticBase =
- MSPropertyRefRebuilder(S, NewBase).rebuild(syntacticBase);
+Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
+ InstanceBase = capture(RefExpr->getBaseExpr());
+ std::for_each(CallArgs.begin(), CallArgs.end(),
+ [this](Expr *&Arg) { Arg = capture(Arg); });
+ syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
+ switch (Idx) {
+ case 0:
+ return InstanceBase;
+ default:
+ assert(Idx <= CallArgs.size());
+ return CallArgs[Idx - 1];
+ }
+ }).rebuild(syntacticBase);
return syntacticBase;
}
@@ -1423,10 +1472,10 @@ ExprResult MSPropertyOpBuilder::buildGet() {
GetterName.setIdentifier(II, RefExpr->getMemberLoc());
CXXScopeSpec SS;
SS.Adopt(RefExpr->getQualifierLoc());
- ExprResult GetterExpr = S.ActOnMemberAccessExpr(
- S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
- RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
- GetterName, nullptr);
+ ExprResult GetterExpr =
+ S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
+ RefExpr->isArrow() ? tok::arrow : tok::period, SS,
+ SourceLocation(), GetterName, nullptr);
if (GetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::error_cannot_find_suitable_accessor) << 0 /* getter */
@@ -1434,9 +1483,8 @@ ExprResult MSPropertyOpBuilder::buildGet() {
return ExprError();
}
- MultiExprArg ArgExprs;
return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(),
- RefExpr->getSourceRange().getBegin(), ArgExprs,
+ RefExpr->getSourceRange().getBegin(), CallArgs,
RefExpr->getSourceRange().getEnd());
}
@@ -1453,10 +1501,10 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
SetterName.setIdentifier(II, RefExpr->getMemberLoc());
CXXScopeSpec SS;
SS.Adopt(RefExpr->getQualifierLoc());
- ExprResult SetterExpr = S.ActOnMemberAccessExpr(
- S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(),
- RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(),
- SetterName, nullptr);
+ ExprResult SetterExpr =
+ S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
+ RefExpr->isArrow() ? tok::arrow : tok::period, SS,
+ SourceLocation(), SetterName, nullptr);
if (SetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::error_cannot_find_suitable_accessor) << 1 /* setter */
@@ -1464,7 +1512,8 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
return ExprError();
}
- SmallVector<Expr*, 1> ArgExprs;
+ SmallVector<Expr*, 4> ArgExprs;
+ ArgExprs.append(CallArgs.begin(), CallArgs.end());
ArgExprs.push_back(op);
return S.ActOnCallExpr(S.getCurScope(), SetterExpr.get(),
RefExpr->getSourceRange().getBegin(), ArgExprs,
@@ -1490,6 +1539,10 @@ ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
MSPropertyOpBuilder builder(*this, refExpr);
return builder.buildRValueOperation(E);
+ } else if (MSPropertySubscriptExpr *RefExpr =
+ dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
+ MSPropertyOpBuilder Builder(*this, RefExpr);
+ return Builder.buildRValueOperation(E);
} else {
llvm_unreachable("unknown pseudo-object kind!");
}
@@ -1516,6 +1569,10 @@ ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
MSPropertyOpBuilder builder(*this, refExpr);
return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
+ } else if (MSPropertySubscriptExpr *RefExpr
+ = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
+ MSPropertyOpBuilder Builder(*this, RefExpr);
+ return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
} else {
llvm_unreachable("unknown pseudo-object kind!");
}
@@ -1547,8 +1604,12 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else if (MSPropertyRefExpr *refExpr
= dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- MSPropertyOpBuilder builder(*this, refExpr);
- return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
+ MSPropertyOpBuilder builder(*this, refExpr);
+ return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
+ } else if (MSPropertySubscriptExpr *RefExpr
+ = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
+ MSPropertyOpBuilder Builder(*this, RefExpr);
+ return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
} else {
llvm_unreachable("unknown pseudo-object kind!");
}
@@ -1558,29 +1619,11 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
/// values. Basically, undo the behavior of rebuildAndCaptureObject.
/// This should never operate in-place.
static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
- Expr *opaqueRef = E->IgnoreParens();
- if (ObjCPropertyRefExpr *refExpr
- = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
- // Class and super property references don't have opaque values in them.
- if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
- return E;
-
- assert(refExpr->isObjectReceiver() && "Unknown receiver kind?");
- OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
- return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
- } else if (ObjCSubscriptRefExpr *refExpr
- = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
- OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
- OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr());
- return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(),
- keyOVE->getSourceExpr()).rebuild(E);
- } else if (MSPropertyRefExpr *refExpr
- = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
- OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
- return MSPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
- } else {
- llvm_unreachable("unknown pseudo-object kind!");
- }
+ return Rebuilder(S,
+ [=](Expr *E, unsigned) -> Expr * {
+ return cast<OpaqueValueExpr>(E)->getSourceExpr();
+ })
+ .rebuild(E);
}
/// Given a pseudo-object expression, recreate what it looks like
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
index c4f6fd8..e1b1a47 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -195,7 +195,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
if (isUnevaluatedContext())
return;
- SourceLocation ExprLoc = E->IgnoreParens()->getExprLoc();
+ SourceLocation ExprLoc = E->IgnoreParenImpCasts()->getExprLoc();
// In most cases, we don't want to warn if the expression is written in a
// macro body, or if the macro comes from a system header. If the offending
// expression is a call to a function with the warn_unused_result attribute,
@@ -218,6 +218,15 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
if (isa<StmtExpr>(E) && Loc.isMacroID())
return;
+ // Check if this is the UNREFERENCED_PARAMETER from the Microsoft headers.
+ // That macro is frequently used to suppress "unused parameter" warnings,
+ // but its implementation makes clang's -Wunused-value fire. Prevent this.
+ if (isa<ParenExpr>(E->IgnoreImpCasts()) && Loc.isMacroID()) {
+ SourceLocation SpellLoc = Loc;
+ if (findMacroSpelling(SpellLoc, "UNREFERENCED_PARAMETER"))
+ return;
+ }
+
// Okay, we have an unused result. Depending on what the base expression is,
// we might want to make a more specific diagnostic. Check for one of these
// cases now.
@@ -483,13 +492,6 @@ StmtResult
Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
Stmt *thenStmt, SourceLocation ElseLoc,
Stmt *elseStmt) {
- // If the condition was invalid, discard the if statement. We could recover
- // better by replacing it with a valid expr, but don't do that yet.
- if (!CondVal.get() && !CondVar) {
- getCurFunction()->setHasDroppedStmt();
- return StmtError();
- }
-
ExprResult CondResult(CondVal.release());
VarDecl *ConditionVar = nullptr;
@@ -497,22 +499,23 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);
CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc);
- if (CondResult.isInvalid())
- return StmtError();
}
Expr *ConditionExpr = CondResult.getAs<Expr>();
- if (!ConditionExpr)
- return StmtError();
+ if (ConditionExpr) {
+ DiagnoseUnusedExprResult(thenStmt);
- DiagnoseUnusedExprResult(thenStmt);
+ if (!elseStmt) {
+ DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,
+ diag::warn_empty_if_body);
+ }
- if (!elseStmt) {
- DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,
- diag::warn_empty_if_body);
+ DiagnoseUnusedExprResult(elseStmt);
+ } else {
+ // Create a dummy Expr for the condition for error recovery
+ ConditionExpr = new (Context) OpaqueValueExpr(SourceLocation(),
+ Context.BoolTy, VK_RValue);
}
- DiagnoseUnusedExprResult(elseStmt);
-
return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
thenStmt, ElseLoc, elseStmt);
}
@@ -698,8 +701,6 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
EnumValsTy::iterator &EI,
EnumValsTy::iterator &EIEnd,
const llvm::APSInt &Val) {
- bool FlagType = ED->hasAttr<FlagEnumAttr>();
-
if (const DeclRefExpr *DRE =
dyn_cast<DeclRefExpr>(CaseExpr->IgnoreParenImpCasts())) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
@@ -711,7 +712,7 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
}
}
- if (FlagType) {
+ if (ED->hasAttr<FlagEnumAttr>()) {
return !S.IsValueInFlagEnum(ED, Val, false);
} else {
while (EI != EIEnd && EI->first < Val)
@@ -1349,7 +1350,7 @@ namespace {
}; // end class DeclExtractor
- // DeclMatcher checks to see if the decls are used in a non-evauluated
+ // DeclMatcher checks to see if the decls are used in a non-evaluated
// context.
class DeclMatcher : public EvaluatedExprVisitor<DeclMatcher> {
llvm::SmallPtrSetImpl<VarDecl*> &Decls;
@@ -1705,11 +1706,10 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
// If we have a forward-declared type, we can't do this check.
// Under ARC, it is an error not to have a forward-declared class.
if (iface &&
- RequireCompleteType(forLoc, QualType(objectType, 0),
- getLangOpts().ObjCAutoRefCount
- ? diag::err_arc_collection_forward
- : 0,
- collection)) {
+ (getLangOpts().ObjCAutoRefCount
+ ? RequireCompleteType(forLoc, QualType(objectType, 0),
+ diag::err_arc_collection_forward, collection)
+ : !isCompleteType(forLoc, QualType(objectType, 0)))) {
// Otherwise, if we have any useful type information, check that
// the type declares the appropriate method.
} else if (iface || !objectType->qual_empty()) {
@@ -1867,13 +1867,19 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init,
}
namespace {
+// An enum to represent whether something is dealing with a call to begin()
+// or a call to end() in a range-based for loop.
+enum BeginEndFunction {
+ BEF_begin,
+ BEF_end
+};
/// Produce a note indicating which begin/end function was implicitly called
/// by a C++11 for-range statement. This is often not obvious from the code,
/// nor from the diagnostics produced when analysing the implicit expressions
/// required in a for-range statement.
void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E,
- Sema::BeginEndFunction BEF) {
+ BeginEndFunction BEF) {
CallExpr *CE = dyn_cast<CallExpr>(E);
if (!CE)
return;
@@ -1931,10 +1937,11 @@ static bool ObjCEnumerationCollection(Expr *Collection) {
///
/// The body of the loop is not available yet, since it cannot be analysed until
/// we have determined the type of the for-range-declaration.
-StmtResult
-Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
- Stmt *First, SourceLocation ColonLoc, Expr *Range,
- SourceLocation RParenLoc, BuildForRangeKind Kind) {
+StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
+ SourceLocation CoawaitLoc, Stmt *First,
+ SourceLocation ColonLoc, Expr *Range,
+ SourceLocation RParenLoc,
+ BuildForRangeKind Kind) {
if (!First)
return StmtError();
@@ -1956,6 +1963,13 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
return StmtError();
}
+ // Coroutines: 'for co_await' implicitly co_awaits its range.
+ if (CoawaitLoc.isValid()) {
+ ExprResult Coawait = ActOnCoawaitExpr(S, CoawaitLoc, Range);
+ if (Coawait.isInvalid()) return StmtError();
+ Range = Coawait.get();
+ }
+
// Build auto && __range = range-init
SourceLocation RangeLoc = Range->getLocStart();
VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc,
@@ -1977,7 +1991,7 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
return StmtError();
}
- return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(),
+ return BuildCXXForRangeStmt(ForLoc, CoawaitLoc, ColonLoc, RangeDecl.get(),
/*BeginEndDecl=*/nullptr, /*Cond=*/nullptr,
/*Inc=*/nullptr, DS, RParenLoc, Kind);
}
@@ -1991,7 +2005,7 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc,
/// BeginExpr and EndExpr are set and FRS_Success is returned on success;
/// CandidateSet and BEF are set and some non-success value is returned on
/// failure.
-static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S,
+static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef,
Expr *BeginRange, Expr *EndRange,
QualType RangeType,
VarDecl *BeginVar,
@@ -2000,7 +2014,7 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S,
OverloadCandidateSet *CandidateSet,
ExprResult *BeginExpr,
ExprResult *EndExpr,
- Sema::BeginEndFunction *BEF) {
+ BeginEndFunction *BEF) {
DeclarationNameInfo BeginNameInfo(
&SemaRef.PP.getIdentifierTable().get("begin"), ColonLoc);
DeclarationNameInfo EndNameInfo(&SemaRef.PP.getIdentifierTable().get("end"),
@@ -2021,7 +2035,7 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S,
if (BeginMemberLookup.empty() != EndMemberLookup.empty()) {
SourceLocation RangeLoc = BeginVar->getLocation();
- *BEF = BeginMemberLookup.empty() ? Sema::BEF_end : Sema::BEF_begin;
+ *BEF = BeginMemberLookup.empty() ? BEF_end : BEF_begin;
SemaRef.Diag(RangeLoc, diag::err_for_range_member_begin_end_mismatch)
<< RangeLoc << BeginRange->getType() << *BEF;
@@ -2035,29 +2049,35 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S,
}
- *BEF = Sema::BEF_begin;
+ *BEF = BEF_begin;
Sema::ForRangeStatus RangeStatus =
- SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc, BeginVar,
- Sema::BEF_begin, BeginNameInfo,
+ SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, BeginNameInfo,
BeginMemberLookup, CandidateSet,
BeginRange, BeginExpr);
- if (RangeStatus != Sema::FRS_Success)
+ if (RangeStatus != Sema::FRS_Success) {
+ if (RangeStatus == Sema::FRS_DiagnosticIssued)
+ SemaRef.Diag(BeginRange->getLocStart(), diag::note_in_for_range)
+ << ColonLoc << BEF_begin << BeginRange->getType();
return RangeStatus;
+ }
if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc,
diag::err_for_range_iter_deduction_failure)) {
NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF);
return Sema::FRS_DiagnosticIssued;
}
- *BEF = Sema::BEF_end;
+ *BEF = BEF_end;
RangeStatus =
- SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc, EndVar,
- Sema::BEF_end, EndNameInfo,
+ SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, EndNameInfo,
EndMemberLookup, CandidateSet,
EndRange, EndExpr);
- if (RangeStatus != Sema::FRS_Success)
+ if (RangeStatus != Sema::FRS_Success) {
+ if (RangeStatus == Sema::FRS_DiagnosticIssued)
+ SemaRef.Diag(EndRange->getLocStart(), diag::note_in_for_range)
+ << ColonLoc << BEF_end << EndRange->getType();
return RangeStatus;
+ }
if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc,
diag::err_for_range_iter_deduction_failure)) {
NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF);
@@ -2071,6 +2091,7 @@ static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S,
/// and emit no diagnostics.
static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,
SourceLocation ForLoc,
+ SourceLocation CoawaitLoc,
Stmt *LoopVarDecl,
SourceLocation ColonLoc,
Expr *Range,
@@ -2086,10 +2107,9 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,
if (AdjustedRange.isInvalid())
return StmtResult();
- StmtResult SR =
- SemaRef.ActOnCXXForRangeStmt(ForLoc, LoopVarDecl, ColonLoc,
- AdjustedRange.get(), RParenLoc,
- Sema::BFRK_Check);
+ StmtResult SR = SemaRef.ActOnCXXForRangeStmt(
+ S, ForLoc, CoawaitLoc, LoopVarDecl, ColonLoc, AdjustedRange.get(),
+ RParenLoc, Sema::BFRK_Check);
if (SR.isInvalid())
return StmtResult();
}
@@ -2099,8 +2119,8 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,
// case there are any other (non-fatal) problems with it.
SemaRef.Diag(RangeLoc, diag::err_for_range_dereference)
<< Range->getType() << FixItHint::CreateInsertion(RangeLoc, "*");
- return SemaRef.ActOnCXXForRangeStmt(ForLoc, LoopVarDecl, ColonLoc,
- AdjustedRange.get(), RParenLoc,
+ return SemaRef.ActOnCXXForRangeStmt(S, ForLoc, CoawaitLoc, LoopVarDecl,
+ ColonLoc, AdjustedRange.get(), RParenLoc,
Sema::BFRK_Rebuild);
}
@@ -2122,10 +2142,20 @@ struct InvalidateOnErrorScope {
/// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement.
StmtResult
-Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
+Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
+ SourceLocation ColonLoc,
Stmt *RangeDecl, Stmt *BeginEnd, Expr *Cond,
Expr *Inc, Stmt *LoopVarDecl,
SourceLocation RParenLoc, BuildForRangeKind Kind) {
+ // FIXME: This should not be used during template instantiation. We should
+ // pick up the set of unqualified lookup results for the != and + operators
+ // in the initial parse.
+ //
+ // Testcase (accepts-invalid):
+ // template<typename T> void f() { for (auto x : T()) {} }
+ // namespace N { struct X { X begin(); X end(); int operator*(); }; }
+ // bool operator!=(N::X, N::X); void operator++(N::X);
+ // void g() { f<N::X>(); }
Scope *S = getCurScope();
DeclStmt *RangeDS = cast<DeclStmt>(RangeDecl);
@@ -2225,9 +2255,9 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
} else {
OverloadCandidateSet CandidateSet(RangeLoc,
OverloadCandidateSet::CSK_Normal);
- Sema::BeginEndFunction BEFFailure;
+ BeginEndFunction BEFFailure;
ForRangeStatus RangeStatus =
- BuildNonArrayForRange(*this, S, BeginRangeRef.get(),
+ BuildNonArrayForRange(*this, BeginRangeRef.get(),
EndRangeRef.get(), RangeType,
BeginVar, EndVar, ColonLoc, &CandidateSet,
&BeginExpr, &EndExpr, &BEFFailure);
@@ -2252,6 +2282,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
// If building the range failed, try dereferencing the range expression
// unless a diagnostic was issued or the end function is problematic.
StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc,
+ CoawaitLoc,
LoopVarDecl, ColonLoc,
Range, RangeLoc,
RParenLoc);
@@ -2322,7 +2353,10 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
return StmtError();
IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get());
- IncrExpr = ActOnFinishFullExpr(IncrExpr.get());
+ if (!IncrExpr.isInvalid() && CoawaitLoc.isValid())
+ IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get());
+ if (!IncrExpr.isInvalid())
+ IncrExpr = ActOnFinishFullExpr(IncrExpr.get());
if (IncrExpr.isInvalid()) {
Diag(RangeLoc, diag::note_for_range_invalid_iterator)
<< RangeLoc << 2 << BeginRangeRef.get()->getType() ;
@@ -2361,7 +2395,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
return new (Context) CXXForRangeStmt(
RangeDS, cast_or_null<DeclStmt>(BeginEndDecl.get()), NotEqExpr.get(),
- IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, ColonLoc, RParenLoc);
+ IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, CoawaitLoc,
+ ColonLoc, RParenLoc);
}
/// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach
@@ -2919,6 +2954,9 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (CurCap->HasImplicitReturnType || NRVOCandidate)
FunctionScopes.back()->Returns.push_back(Result);
+ if (FunctionScopes.back()->FirstReturnLoc.isInvalid())
+ FunctionScopes.back()->FirstReturnLoc = ReturnLoc;
+
return Result;
}
@@ -2989,14 +3027,9 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
// statement with a non-type-dependent operand.
assert(AT->isDeduced() && "should have deduced to dependent type");
return false;
- } else if (RetExpr) {
- // If the deduction is for a return statement and the initializer is
- // a braced-init-list, the program is ill-formed.
- if (isa<InitListExpr>(RetExpr)) {
- Diag(RetExpr->getExprLoc(), diag::err_auto_fn_return_init_list);
- return true;
- }
+ }
+ if (RetExpr) {
// Otherwise, [...] deduce a value for U using the rules of template
// argument deduction.
DeduceAutoResult DAR = DeduceAutoType(OrigResultType, RetExpr, Deduced);
@@ -3035,8 +3068,11 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
// the program is ill-formed.
if (AT->isDeduced() && !FD->isInvalidDecl()) {
AutoType *NewAT = Deduced->getContainedAutoType();
- if (!FD->isDependentContext() &&
- !Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) {
+ CanQualType OldDeducedType = Context.getCanonicalFunctionResultType(
+ AT->getDeducedType());
+ CanQualType NewDeducedType = Context.getCanonicalFunctionResultType(
+ NewAT->getDeducedType());
+ if (!FD->isDependentContext() && OldDeducedType != NewDeducedType) {
const LambdaScopeInfo *LambdaSI = getCurLambda();
if (LambdaSI && LambdaSI->HasImplicitReturnType) {
Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible)
@@ -3179,7 +3215,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
// return (some void expression); is legal in C++.
else if (D != diag::ext_return_has_void_expr ||
- !getLangOpts().CPlusPlus) {
+ !getLangOpts().CPlusPlus) {
NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
int FunctionKind = 0;
@@ -3287,6 +3323,9 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (Result->getNRVOCandidate())
FunctionScopes.back()->Returns.push_back(Result);
+ if (FunctionScopes.back()->FirstReturnLoc.isInvalid())
+ FunctionScopes.back()->FirstReturnLoc = ReturnLoc;
+
return Result;
}
@@ -3512,16 +3551,14 @@ public:
CXXCatchStmt *getFoundHandler() const { return FoundHandler; }
CanQualType getFoundHandlerType() const { return FoundHandlerType; }
- static bool FindPublicBasesOfType(const CXXBaseSpecifier *S, CXXBasePath &,
- void *User) {
- auto &PBOT = *reinterpret_cast<CatchTypePublicBases *>(User);
+ bool operator()(const CXXBaseSpecifier *S, CXXBasePath &) {
if (S->getAccessSpecifier() == AccessSpecifier::AS_public) {
- CatchHandlerType Check(S->getType(), PBOT.CheckAgainstPointer);
- auto M = PBOT.TypesToCheck;
+ CatchHandlerType Check(S->getType(), CheckAgainstPointer);
+ auto M = TypesToCheck;
auto I = M.find(Check);
if (I != M.end()) {
- PBOT.FoundHandler = I->second;
- PBOT.FoundHandlerType = PBOT.Ctx.getCanonicalType(S->getType());
+ FoundHandler = I->second;
+ FoundHandlerType = Ctx.getCanonicalType(S->getType());
return true;
}
}
@@ -3589,8 +3626,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
CXXBasePaths Paths;
Paths.setOrigin(RD);
CatchTypePublicBases CTPB(Context, HandledTypes, HandlerCHT.isPointer());
- if (RD->lookupInBases(CatchTypePublicBases::FindPublicBasesOfType, &CTPB,
- Paths)) {
+ if (RD->lookupInBases(CTPB, Paths)) {
const CXXCatchStmt *Problem = CTPB.getFoundHandler();
if (!Paths.isAmbiguous(CTPB.getFoundHandlerType())) {
Diag(H->getExceptionDecl()->getTypeSpecStartLoc(),
@@ -3766,11 +3802,10 @@ static void buildCapturedStmtCaptureList(
continue;
}
- assert(Cap->isReferenceCapture() &&
- "non-reference capture not yet implemented");
-
Captures.push_back(CapturedStmt::Capture(Cap->getLocation(),
- CapturedStmt::VCK_ByRef,
+ Cap->isReferenceCapture()
+ ? CapturedStmt::VCK_ByRef
+ : CapturedStmt::VCK_ByCopy,
Cap->getVariable()));
CaptureInits.push_back(Cap->getInitExpr());
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
index 8e3e89f..11a4f8b 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp
@@ -107,6 +107,37 @@ static bool CheckNakedParmReference(Expr *E, Sema &S) {
return false;
}
+/// \brief Returns true if given expression is not compatible with inline
+/// assembly's memory constraint; false otherwise.
+static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
+ TargetInfo::ConstraintInfo &Info,
+ bool is_input_expr) {
+ enum {
+ ExprBitfield = 0,
+ ExprVectorElt,
+ ExprGlobalRegVar,
+ ExprSafeType
+ } EType = ExprSafeType;
+
+ // Bitfields, vector elements and global register variables are not
+ // compatible.
+ if (E->refersToBitField())
+ EType = ExprBitfield;
+ else if (E->refersToVectorElement())
+ EType = ExprVectorElt;
+ else if (E->refersToGlobalRegisterVar())
+ EType = ExprGlobalRegVar;
+
+ if (EType != ExprSafeType) {
+ S.Diag(E->getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint)
+ << EType << is_input_expr << Info.getConstraintStr()
+ << E->getSourceRange();
+ return true;
+ }
+
+ return false;
+}
+
StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
bool IsVolatile, unsigned NumOutputs,
unsigned NumInputs, IdentifierInfo **Names,
@@ -124,8 +155,14 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
// The parser verifies that there is a string literal here.
assert(AsmString->isAscii());
- bool ValidateConstraints =
- DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl());
+ // If we're compiling CUDA file and function attributes indicate that it's not
+ // for this compilation side, skip all the checks.
+ if (!DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl())) {
+ GCCAsmStmt *NS = new (Context) GCCAsmStmt(
+ Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
+ Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc);
+ return NS;
+ }
for (unsigned i = 0; i != NumOutputs; i++) {
StringLiteral *Literal = Constraints[i];
@@ -136,8 +173,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
OutputName = Names[i]->getName();
TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
- if (ValidateConstraints &&
- !Context.getTargetInfo().validateOutputConstraint(Info))
+ if (!Context.getTargetInfo().validateOutputConstraint(Info))
return StmtError(Diag(Literal->getLocStart(),
diag::err_asm_invalid_output_constraint)
<< Info.getConstraintStr());
@@ -154,13 +190,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (CheckNakedParmReference(OutputExpr, *this))
return StmtError();
- // Bitfield can't be referenced with a pointer.
- if (Info.allowsMemory() && OutputExpr->refersToBitField())
- return StmtError(Diag(OutputExpr->getLocStart(),
- diag::err_asm_bitfield_in_memory_constraint)
- << 1
- << Info.getConstraintStr()
- << OutputExpr->getSourceRange());
+ // Check that the output expression is compatible with memory constraint.
+ if (Info.allowsMemory() &&
+ checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false))
+ return StmtError();
OutputConstraintInfos.push_back(Info);
@@ -219,9 +252,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
InputName = Names[i]->getName();
TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
- if (ValidateConstraints &&
- !Context.getTargetInfo().validateInputConstraint(
- OutputConstraintInfos.data(), NumOutputs, Info)) {
+ if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos,
+ Info)) {
return StmtError(Diag(Literal->getLocStart(),
diag::err_asm_invalid_input_constraint)
<< Info.getConstraintStr());
@@ -238,13 +270,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
if (CheckNakedParmReference(InputExpr, *this))
return StmtError();
- // Bitfield can't be referenced with a pointer.
- if (Info.allowsMemory() && InputExpr->refersToBitField())
- return StmtError(Diag(InputExpr->getLocStart(),
- diag::err_asm_bitfield_in_memory_constraint)
- << 0
- << Info.getConstraintStr()
- << InputExpr->getSourceRange());
+ // Check that the input expression is compatible with memory constraint.
+ if (Info.allowsMemory() &&
+ checkExprMemoryConstraintCompat(*this, InputExpr, Info, true))
+ return StmtError();
// Only allow void types for memory constraints.
if (Info.allowsMemory() && !Info.allowsRegister()) {
@@ -260,8 +289,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return StmtError(
Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
<< Info.getConstraintStr() << InputExpr->getSourceRange());
- if (Result.slt(Info.getImmConstantMin()) ||
- Result.sgt(Info.getImmConstantMax()))
+ if (!Info.isValidAsmImmediate(Result))
return StmtError(Diag(InputExpr->getLocStart(),
diag::err_invalid_asm_value_for_constraint)
<< Result.toString(10) << Info.getConstraintStr()
@@ -392,6 +420,8 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
diag::err_asm_unexpected_constraint_alternatives)
<< NumAlternatives << AltCount);
}
+ SmallVector<size_t, 4> InputMatchedToOutput(OutputConstraintInfos.size(),
+ ~0U);
for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
StringRef ConstraintStr = Info.getConstraintStr();
@@ -413,6 +443,19 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
Expr *OutputExpr = Exprs[TiedTo];
Expr *InputExpr = Exprs[InputOpNo];
+ // Make sure no more than one input constraint matches each output.
+ assert(TiedTo < InputMatchedToOutput.size() && "TiedTo value out of range");
+ if (InputMatchedToOutput[TiedTo] != ~0U) {
+ Diag(NS->getInputExpr(i)->getLocStart(),
+ diag::err_asm_input_duplicate_match)
+ << TiedTo;
+ Diag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getLocStart(),
+ diag::note_asm_input_duplicate_first)
+ << TiedTo;
+ return StmtError();
+ }
+ InputMatchedToOutput[TiedTo] = i;
+
if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
continue;
@@ -504,6 +547,17 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return NS;
}
+static void fillInlineAsmTypeInfo(const ASTContext &Context, QualType T,
+ llvm::InlineAsmIdentifierInfo &Info) {
+ // Compute the type size (and array length if applicable?).
+ Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
+ if (T->isArrayType()) {
+ const ArrayType *ATy = Context.getAsArrayType(T);
+ Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
+ Info.Length = Info.Size / Info.Type;
+ }
+}
+
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
UnqualifiedId &Id,
@@ -535,10 +589,8 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
QualType T = Result.get()->getType();
- // For now, reject dependent types.
if (T->isDependentType()) {
- Diag(Id.getLocStart(), diag::err_asm_incomplete_type) << T;
- return ExprError();
+ return Result;
}
// Any sort of function type is fine.
@@ -551,13 +603,7 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
return ExprError();
}
- // Compute the type size (and array length if applicable?).
- Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
- if (T->isArrayType()) {
- const ArrayType *ATy = Context.getAsArrayType(T);
- Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
- Info.Length = Info.Size / Info.Type;
- }
+ fillInlineAsmTypeInfo(Context, T, Info);
// We can work with the expression as long as it's not an r-value.
if (!Result.get()->isRValue())
@@ -569,47 +615,111 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
unsigned &Offset, SourceLocation AsmLoc) {
Offset = 0;
+ SmallVector<StringRef, 2> Members;
+ Member.split(Members, ".");
+
LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(),
LookupOrdinaryName);
if (!LookupName(BaseResult, getCurScope()))
return true;
- if (!BaseResult.isSingleResult())
- return true;
+ LookupResult CurrBaseResult(BaseResult);
- const RecordType *RT = nullptr;
- NamedDecl *FoundDecl = BaseResult.getFoundDecl();
- if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
- RT = VD->getType()->getAs<RecordType>();
- else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) {
- MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
- RT = TD->getUnderlyingType()->getAs<RecordType>();
- } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
- RT = TD->getTypeForDecl()->getAs<RecordType>();
- if (!RT)
- return true;
+ for (StringRef NextMember : Members) {
- if (RequireCompleteType(AsmLoc, QualType(RT, 0), 0))
- return true;
+ if (!CurrBaseResult.isSingleResult())
+ return true;
+
+ const RecordType *RT = nullptr;
+ NamedDecl *FoundDecl = CurrBaseResult.getFoundDecl();
+ if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
+ RT = VD->getType()->getAs<RecordType>();
+ else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) {
+ MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
+ RT = TD->getUnderlyingType()->getAs<RecordType>();
+ } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
+ RT = TD->getTypeForDecl()->getAs<RecordType>();
+ else if (FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
+ RT = TD->getType()->getAs<RecordType>();
+ if (!RT)
+ return true;
+
+ if (RequireCompleteType(AsmLoc, QualType(RT, 0),
+ diag::err_asm_incomplete_type))
+ return true;
+
+ LookupResult FieldResult(*this, &Context.Idents.get(NextMember),
+ SourceLocation(), LookupMemberName);
+
+ if (!LookupQualifiedName(FieldResult, RT->getDecl()))
+ return true;
+
+ // FIXME: Handle IndirectFieldDecl?
+ FieldDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
+ if (!FD)
+ return true;
+
+ CurrBaseResult = FieldResult;
+
+ const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl());
+ unsigned i = FD->getFieldIndex();
+ CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i));
+ Offset += (unsigned)Result.getQuantity();
+ }
+
+ return false;
+}
+
+ExprResult
+Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
+ llvm::InlineAsmIdentifierInfo &Info,
+ SourceLocation AsmLoc) {
+ Info.clear();
- LookupResult FieldResult(*this, &Context.Idents.get(Member), SourceLocation(),
+ QualType T = E->getType();
+ if (T->isDependentType()) {
+ DeclarationNameInfo NameInfo;
+ NameInfo.setLoc(AsmLoc);
+ NameInfo.setName(&Context.Idents.get(Member));
+ return CXXDependentScopeMemberExpr::Create(
+ Context, E, T, /*IsArrow=*/false, AsmLoc, NestedNameSpecifierLoc(),
+ SourceLocation(),
+ /*FirstQualifierInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr);
+ }
+
+ const RecordType *RT = T->getAs<RecordType>();
+ // FIXME: Diagnose this as field access into a scalar type.
+ if (!RT)
+ return ExprResult();
+
+ LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc,
LookupMemberName);
if (!LookupQualifiedName(FieldResult, RT->getDecl()))
- return true;
+ return ExprResult();
- // FIXME: Handle IndirectFieldDecl?
- FieldDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
+ // Only normal and indirect field results will work.
+ ValueDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
if (!FD)
- return true;
+ FD = dyn_cast<IndirectFieldDecl>(FieldResult.getFoundDecl());
+ if (!FD)
+ return ExprResult();
- const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl());
- unsigned i = FD->getFieldIndex();
- CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i));
- Offset = (unsigned)Result.getQuantity();
+ // Make an Expr to thread through OpDecl.
+ ExprResult Result = BuildMemberReferenceExpr(
+ E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(),
+ SourceLocation(), nullptr, FieldResult, nullptr, nullptr);
+ if (Result.isInvalid())
+ return Result;
+ Info.OpDecl = Result.get();
- return false;
+ fillInlineAsmTypeInfo(Context, Result.get()->getType(), Info);
+
+ // Fields are "variables" as far as inline assembly is concerned.
+ Info.IsVarDecl = true;
+
+ return Result;
}
StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
@@ -646,7 +756,15 @@ LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
// Create an internal name for the label. The name should not be a valid mangled
// name, and should be unique. We use a dot to make the name an invalid mangled
// name.
- OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__" << ExternalLabelName;
+ OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__";
+ for (auto it = ExternalLabelName.begin(); it != ExternalLabelName.end();
+ ++it) {
+ OS << *it;
+ if (*it == '$') {
+ // We escape '$' in asm strings by replacing it with "$$"
+ OS << '$';
+ }
+ }
Label->setMSAsmLabel(OS.str());
}
if (AlwaysCreate) {
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
index 5b71c11..984bd07 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmtAttr.cpp
@@ -65,19 +65,32 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
return nullptr;
}
- LoopHintAttr::OptionType Option;
LoopHintAttr::Spelling Spelling;
- if (PragmaUnroll) {
- Option = ValueExpr ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll;
- Spelling = LoopHintAttr::Pragma_unroll;
- } else if (PragmaNoUnroll) {
- Option = LoopHintAttr::Unroll;
+ LoopHintAttr::OptionType Option;
+ LoopHintAttr::LoopHintState State;
+ if (PragmaNoUnroll) {
+ // #pragma nounroll
Spelling = LoopHintAttr::Pragma_nounroll;
+ Option = LoopHintAttr::Unroll;
+ State = LoopHintAttr::Disable;
+ } else if (PragmaUnroll) {
+ Spelling = LoopHintAttr::Pragma_unroll;
+ if (ValueExpr) {
+ // #pragma unroll N
+ Option = LoopHintAttr::UnrollCount;
+ State = LoopHintAttr::Numeric;
+ } else {
+ // #pragma unroll
+ Option = LoopHintAttr::Unroll;
+ State = LoopHintAttr::Enable;
+ }
} else {
+ // #pragma clang loop ...
+ Spelling = LoopHintAttr::Pragma_clang_loop;
assert(OptionLoc && OptionLoc->Ident &&
"Attribute must have valid option info.");
- IdentifierInfo *OptionInfo = OptionLoc->Ident;
- Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName())
+ Option = llvm::StringSwitch<LoopHintAttr::OptionType>(
+ OptionLoc->Ident->getName())
.Case("vectorize", LoopHintAttr::Vectorize)
.Case("vectorize_width", LoopHintAttr::VectorizeWidth)
.Case("interleave", LoopHintAttr::Interleave)
@@ -85,31 +98,29 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
.Case("unroll", LoopHintAttr::Unroll)
.Case("unroll_count", LoopHintAttr::UnrollCount)
.Default(LoopHintAttr::Vectorize);
- Spelling = LoopHintAttr::Pragma_clang_loop;
- }
-
- LoopHintAttr::LoopHintState State = LoopHintAttr::Default;
- if (PragmaNoUnroll) {
- State = LoopHintAttr::Disable;
- } else if (Option == LoopHintAttr::VectorizeWidth ||
- Option == LoopHintAttr::InterleaveCount ||
- Option == LoopHintAttr::UnrollCount) {
- assert(ValueExpr && "Attribute must have a valid value expression.");
- if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
- return nullptr;
- } else if (Option == LoopHintAttr::Vectorize ||
- Option == LoopHintAttr::Interleave ||
- Option == LoopHintAttr::Unroll) {
- // Default state is assumed if StateLoc is not specified, such as with
- // '#pragma unroll'.
- if (StateLoc && StateLoc->Ident) {
+ if (Option == LoopHintAttr::VectorizeWidth ||
+ Option == LoopHintAttr::InterleaveCount ||
+ Option == LoopHintAttr::UnrollCount) {
+ assert(ValueExpr && "Attribute must have a valid value expression.");
+ if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart()))
+ return nullptr;
+ State = LoopHintAttr::Numeric;
+ } else if (Option == LoopHintAttr::Vectorize ||
+ Option == LoopHintAttr::Interleave ||
+ Option == LoopHintAttr::Unroll) {
+ assert(StateLoc && StateLoc->Ident && "Loop hint must have an argument");
if (StateLoc->Ident->isStr("disable"))
State = LoopHintAttr::Disable;
else if (StateLoc->Ident->isStr("assume_safety"))
State = LoopHintAttr::AssumeSafety;
- else
+ else if (StateLoc->Ident->isStr("full"))
+ State = LoopHintAttr::Full;
+ else if (StateLoc->Ident->isStr("enable"))
State = LoopHintAttr::Enable;
- }
+ else
+ llvm_unreachable("bad loop hint argument");
+ } else
+ llvm_unreachable("bad loop hint");
}
return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, State,
@@ -139,9 +150,8 @@ CheckForIncompatibleAttributes(Sema &S,
if (!LH)
continue;
- int Option = LH->getOption();
- int Category;
- enum { Vectorize, Interleave, Unroll };
+ LoopHintAttr::OptionType Option = LH->getOption();
+ enum { Vectorize, Interleave, Unroll } Category;
switch (Option) {
case LoopHintAttr::Vectorize:
case LoopHintAttr::VectorizeWidth:
@@ -183,7 +193,8 @@ CheckForIncompatibleAttributes(Sema &S,
CategoryState.StateAttr->getState() == LoopHintAttr::Disable)) {
// Disable hints are not compatible with numeric hints of the same
// category. As a special case, numeric unroll hints are also not
- // compatible with "enable" form of the unroll pragma, unroll(full).
+ // compatible with enable or full form of the unroll pragma because these
+ // directives indicate full unrolling.
S.Diag(OptionLoc, diag::err_pragma_loop_compatibility)
<< /*Duplicate=*/false
<< CategoryState.StateAttr->getDiagnosticName(Policy)
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index 035c37c..5715607 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeVisitor.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
@@ -208,7 +209,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
R.suppressDiagnostics();
} else {
assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||
- isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD));
+ isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD) ||
+ isa<BuiltinTemplateDecl>(TD));
TemplateKind =
isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template;
}
@@ -327,8 +329,8 @@ void Sema::LookupTemplateName(LookupResult &Found,
Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS,
std::move(FilterCCC), CTK_ErrorRecovery, LookupCtx)) {
Found.setLookupName(Corrected.getCorrection());
- if (Corrected.getCorrectionDecl())
- Found.addDecl(Corrected.getCorrectionDecl());
+ if (auto *ND = Corrected.getFoundDecl())
+ Found.addDecl(ND);
FilterAcceptableTemplateNames(Found);
if (!Found.empty()) {
if (LookupCtx) {
@@ -812,14 +814,15 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
SourceLocation ExportLoc,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- Decl **Params, unsigned NumParams,
+ ArrayRef<Decl *> Params,
SourceLocation RAngleLoc) {
if (ExportLoc.isValid())
Diag(ExportLoc, diag::warn_template_export_unsupported);
- return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
- (NamedDecl**)Params, NumParams,
- RAngleLoc);
+ return TemplateParameterList::Create(
+ Context, TemplateLoc, LAngleLoc,
+ llvm::makeArrayRef((NamedDecl *const *)Params.data(), Params.size()),
+ RAngleLoc);
}
static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
@@ -1089,9 +1092,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
/*DelayTypeCreation=*/true);
SetNestedNameSpecifier(NewClass, SS);
if (NumOuterTemplateParamLists > 0)
- NewClass->setTemplateParameterListsInfo(Context,
- NumOuterTemplateParamLists,
- OuterTemplateParamLists);
+ NewClass->setTemplateParameterListsInfo(
+ Context, llvm::makeArrayRef(OuterTemplateParamLists,
+ NumOuterTemplateParamLists));
// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
@@ -1936,7 +1939,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// Fabricate an empty template parameter list for the invented header.
return TemplateParameterList::Create(Context, SourceLocation(),
- SourceLocation(), nullptr, 0,
+ SourceLocation(), None,
SourceLocation());
}
@@ -2017,6 +2020,58 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {
}
}
+static QualType
+checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
+ const SmallVectorImpl<TemplateArgument> &Converted,
+ SourceLocation TemplateLoc,
+ TemplateArgumentListInfo &TemplateArgs) {
+ ASTContext &Context = SemaRef.getASTContext();
+ switch (BTD->getBuiltinTemplateKind()) {
+ case BTK__make_integer_seq:
+ // Specializations of __make_integer_seq<S, T, N> are treated like
+ // S<T, 0, ..., N-1>.
+
+ // C++14 [inteseq.intseq]p1:
+ // T shall be an integer type.
+ if (!Converted[1].getAsType()->isIntegralType(Context)) {
+ SemaRef.Diag(TemplateArgs[1].getLocation(),
+ diag::err_integer_sequence_integral_element_type);
+ return QualType();
+ }
+
+ // C++14 [inteseq.make]p1:
+ // If N is negative the program is ill-formed.
+ TemplateArgument NumArgsArg = Converted[2];
+ llvm::APSInt NumArgs = NumArgsArg.getAsIntegral();
+ if (NumArgs < 0) {
+ SemaRef.Diag(TemplateArgs[2].getLocation(),
+ diag::err_integer_sequence_negative_length);
+ return QualType();
+ }
+
+ QualType ArgTy = NumArgsArg.getIntegralType();
+ TemplateArgumentListInfo SyntheticTemplateArgs;
+ // The type argument gets reused as the first template argument in the
+ // synthetic template argument list.
+ SyntheticTemplateArgs.addArgument(TemplateArgs[1]);
+ // Expand N into 0 ... N-1.
+ for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned());
+ I < NumArgs; ++I) {
+ TemplateArgument TA(Context, I, ArgTy);
+ Expr *E = SemaRef.BuildExpressionFromIntegralTemplateArgument(
+ TA, TemplateArgs[2].getLocation())
+ .getAs<Expr>();
+ SyntheticTemplateArgs.addArgument(
+ TemplateArgumentLoc(TemplateArgument(E), E));
+ }
+ // The first template argument will be reused as the template decl that
+ // our synthetic template arguments will be applied to.
+ return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(),
+ TemplateLoc, SyntheticTemplateArgs);
+ }
+ llvm_unreachable("unexpected BuiltinTemplateDecl!");
+}
+
QualType Sema::CheckTemplateIdType(TemplateName Name,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
@@ -2171,6 +2226,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
CanonType = Context.getTypeDeclType(Decl);
assert(isa<RecordType>(CanonType) &&
"type of non-dependent specialization is not a RecordType");
+ } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
+ CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc,
+ TemplateArgs);
}
// Build the fully-sugared type for this class template
@@ -2469,25 +2527,6 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
false, Converted))
return true;
- // Check that the type of this variable template specialization
- // matches the expected type.
- TypeSourceInfo *ExpectedDI;
- {
- // Do substitution on the type of the declaration
- TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack,
- Converted.data(), Converted.size());
- InstantiatingTemplate Inst(*this, TemplateKWLoc, VarTemplate);
- if (Inst.isInvalid())
- return true;
- VarDecl *Templated = VarTemplate->getTemplatedDecl();
- ExpectedDI =
- SubstType(Templated->getTypeSourceInfo(),
- MultiLevelTemplateArgumentList(TemplateArgList),
- Templated->getTypeSpecStartLoc(), Templated->getDeclName());
- }
- if (!ExpectedDI)
- return true;
-
// Find the variable template (partial) specialization declaration that
// corresponds to these arguments.
if (IsPartialSpecialization) {
@@ -2710,7 +2749,8 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
typedef PartialSpecMatchResult MatchResult;
SmallVector<MatchResult, 4> Matched;
SourceLocation PointOfInstantiation = TemplateNameLoc;
- TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
+ TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation,
+ /*ForTakingAddress=*/false);
// 1. Attempt to find the closest partial specialization that this
// specializes, if any.
@@ -3242,7 +3282,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateArgLists.addOuterTemplateArguments(None);
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+ EnterExpressionEvaluationContext ConstantEvaluated(SemaRef,
+ Sema::ConstantEvaluated);
return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists);
}
@@ -3733,9 +3774,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// We're done with this parameter pack. Pack up its arguments and add
// them to the list.
Converted.push_back(
- TemplateArgument::CreatePackCopy(Context,
- ArgumentPack.data(),
- ArgumentPack.size()));
+ TemplateArgument::CreatePackCopy(Context, ArgumentPack));
ArgumentPack.clear();
// This argument is assigned to the next parameter.
@@ -3816,10 +3855,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// If we're checking a partial template argument list, we're done.
if (PartialTemplateArgs) {
if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty())
- Converted.push_back(TemplateArgument::CreatePackCopy(Context,
- ArgumentPack.data(),
- ArgumentPack.size()));
-
+ Converted.push_back(
+ TemplateArgument::CreatePackCopy(Context, ArgumentPack));
+
return false;
}
@@ -3835,9 +3873,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (Param + 1 != ParamEnd)
return true;
- Converted.push_back(TemplateArgument::CreatePackCopy(Context,
- ArgumentPack.data(),
- ArgumentPack.size()));
+ Converted.push_back(
+ TemplateArgument::CreatePackCopy(Context, ArgumentPack));
ArgumentPack.clear();
++Param;
@@ -3946,7 +3983,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// No problems found with the new argument list, propagate changes back
// to caller.
- TemplateArgs = NewArgs;
+ TemplateArgs = std::move(NewArgs);
return false;
}
@@ -4147,6 +4184,10 @@ bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) {
return Visit(T->getValueType());
}
+bool UnnamedLocalNoLinkageFinder::VisitPipeType(const PipeType* T) {
+ return false;
+}
+
bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
if (Tag->getDeclContext()->isFunctionOrMethod()) {
S.Diag(SR.getBegin(),
@@ -4245,7 +4286,11 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
QualType ParamType, Expr *Arg) {
if (Arg->isValueDependent() || Arg->isTypeDependent())
return NPV_NotNullPointer;
-
+
+ if (!S.isCompleteType(Arg->getExprLoc(), ParamType))
+ llvm_unreachable(
+ "Incomplete parameter type in isNullPointerValueTemplateArgument!");
+
if (!S.getLangOpts().CPlusPlus11)
return NPV_NotNullPointer;
@@ -4693,8 +4738,6 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
Converted = TemplateArgument(S.Context.getCanonicalType(ParamType),
/*isNullPtr*/true);
- if (S.Context.getTargetInfo().getCXXABI().isMicrosoft())
- S.RequireCompleteType(Arg->getExprLoc(), ParamType, 0);
return false;
case NPV_NotNullPointer:
break;
@@ -5464,6 +5507,8 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
Expr *E;
if (T->isAnyCharacterType()) {
+ // This does not need to handle u8 character literals because those are
+ // of type char, and so can also be covered by an ASCII character literal.
CharacterLiteral::CharacterKind Kind;
if (T->isWideCharType())
Kind = CharacterLiteral::Wide;
@@ -6311,9 +6356,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
PrevPartial);
SetNestedNameSpecifier(Partial, SS);
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
- Partial->setTemplateParameterListsInfo(Context,
- TemplateParameterLists.size() - 1,
- TemplateParameterLists.data());
+ Partial->setTemplateParameterListsInfo(
+ Context, TemplateParameterLists.drop_back(1));
}
if (!PrevPartial)
@@ -6367,14 +6411,23 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
SetNestedNameSpecifier(Specialization, SS);
if (TemplateParameterLists.size() > 0) {
Specialization->setTemplateParameterListsInfo(Context,
- TemplateParameterLists.size(),
- TemplateParameterLists.data());
+ TemplateParameterLists);
}
if (!PrevDecl)
ClassTemplate->AddSpecialization(Specialization, InsertPos);
- CanonType = Context.getTypeDeclType(Specialization);
+ if (CurContext->isDependentContext()) {
+ // -fms-extensions permits specialization of nested classes without
+ // fully specializing the outer class(es).
+ assert(getLangOpts().MicrosoftExt &&
+ "Only possible with -fms-extensions!");
+ TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
+ CanonType = Context.getTemplateSpecializationType(
+ CanonTemplate, Converted.data(), Converted.size());
+ } else {
+ CanonType = Context.getTypeDeclType(Specialization);
+ }
}
// C++ [temp.expl.spec]p6:
@@ -6497,24 +6550,6 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
return NewDecl;
}
-Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
- MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D) {
- assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
- DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
-
- if (FTI.hasPrototype) {
- // FIXME: Diagnose arguments without names in C.
- }
-
- Scope *ParentScope = FnBodyScope->getParent();
-
- D.setFunctionDefinitionKind(FDK_Definition);
- Decl *DP = HandleDeclarator(ParentScope, D,
- TemplateParameterLists);
- return ActOnStartOfFunctionDef(FnBodyScope, DP);
-}
-
/// \brief Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D) {
@@ -6795,7 +6830,11 @@ bool Sema::CheckFunctionTemplateSpecialization(
// The set of function template specializations that could match this
// explicit function template specialization.
UnresolvedSet<8> Candidates;
- TemplateSpecCandidateSet FailedCandidates(FD->getLocation());
+ TemplateSpecCandidateSet FailedCandidates(FD->getLocation(),
+ /*ForTakingAddress=*/false);
+
+ llvm::SmallDenseMap<FunctionDecl *, TemplateArgumentListInfo, 8>
+ ConvertedTemplateArgs;
DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
@@ -6826,6 +6865,10 @@ bool Sema::CheckFunctionTemplateSpecialization(
}
}
+ TemplateArgumentListInfo Args;
+ if (ExplicitTemplateArgs)
+ Args = *ExplicitTemplateArgs;
+
// C++ [temp.expl.spec]p11:
// A trailing template-argument can be left unspecified in the
// template-id naming an explicit function template specialization
@@ -6837,7 +6880,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult TDK = DeduceTemplateArguments(
cast<FunctionTemplateDecl>(FunTmpl->getFirstDecl()),
- ExplicitTemplateArgs, FT, Specialization, Info)) {
+ ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, Info)) {
// Template argument deduction failed; record why it failed, so
// that we can provide nifty diagnostics.
FailedCandidates.addCandidate()
@@ -6848,6 +6891,8 @@ bool Sema::CheckFunctionTemplateSpecialization(
}
// Record this candidate.
+ if (ExplicitTemplateArgs)
+ ConvertedTemplateArgs[Specialization] = std::move(Args);
Candidates.addDecl(Specialization, I.getAccess());
}
}
@@ -6926,10 +6971,10 @@ bool Sema::CheckFunctionTemplateSpecialization(
// Take copies of (semantic and syntactic) template argument lists.
const TemplateArgumentList* TemplArgs = new (Context)
TemplateArgumentList(Specialization->getTemplateSpecializationArgs());
- FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(),
- TemplArgs, /*InsertPos=*/nullptr,
- SpecInfo->getTemplateSpecializationKind(),
- ExplicitTemplateArgs);
+ FD->setFunctionTemplateSpecialization(
+ Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/nullptr,
+ SpecInfo->getTemplateSpecializationKind(),
+ ExplicitTemplateArgs ? &ConvertedTemplateArgs[Specialization] : nullptr);
// The "previous declaration" for this function template specialization is
// the prior function template specialization.
@@ -7429,11 +7474,16 @@ Sema::ActOnExplicitInstantiation(Scope *S,
}
}
+ // Set the template specialization kind. Make sure it is set before
+ // instantiating the members which will trigger ASTConsumer callbacks.
+ Specialization->setTemplateSpecializationKind(TSK);
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
+ } else {
+
+ // Set the template specialization kind.
+ Specialization->setTemplateSpecializationKind(TSK);
}
- // Set the template specialization kind.
- Specialization->setTemplateSpecializationKind(TSK);
return Specialization;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index ae8157e..71faafc 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -679,7 +679,7 @@ public:
new (S.Context) TemplateArgument[Pack.New.size()];
std::copy(Pack.New.begin(), Pack.New.end(), ArgumentPack);
NewPack = DeducedTemplateArgument(
- TemplateArgument(ArgumentPack, Pack.New.size()),
+ TemplateArgument(llvm::makeArrayRef(ArgumentPack, Pack.New.size())),
Pack.New[0].wasDeducedFromArrayBound());
}
@@ -1440,7 +1440,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// We cannot inspect base classes as part of deduction when the type
// is incomplete, so either instantiate any templates necessary to
// complete the type, or skip over it if it cannot be completed.
- if (S.RequireCompleteType(Info.getLocation(), Arg, 0))
+ if (!S.isCompleteType(Info.getLocation(), Arg))
return Result;
// Use data recursion to crawl through the list of base classes.
@@ -1517,10 +1517,19 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (!MemPtrArg)
return Sema::TDK_NonDeducedMismatch;
+ QualType ParamPointeeType = MemPtrParam->getPointeeType();
+ if (ParamPointeeType->isFunctionType())
+ S.adjustMemberFunctionCC(ParamPointeeType, /*IsStatic=*/true,
+ /*IsCtorOrDtor=*/false, Info.getLocation());
+ QualType ArgPointeeType = MemPtrArg->getPointeeType();
+ if (ArgPointeeType->isFunctionType())
+ S.adjustMemberFunctionCC(ArgPointeeType, /*IsStatic=*/true,
+ /*IsCtorOrDtor=*/false, Info.getLocation());
+
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
- MemPtrParam->getPointeeType(),
- MemPtrArg->getPointeeType(),
+ ParamPointeeType,
+ ArgPointeeType,
Info, Deduced,
TDF & TDF_IgnoreQualifiers))
return Result;
@@ -1643,6 +1652,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
case Type::Auto:
case Type::DependentTemplateSpecialization:
case Type::PackExpansion:
+ case Type::Pipe:
// No template argument deduction for these types
return Sema::TDK_Success;
}
@@ -2075,9 +2085,8 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
}
// Create the resulting argument pack.
- Output.push_back(TemplateArgument::CreatePackCopy(S.Context,
- PackedArgsBuilder.data(),
- PackedArgsBuilder.size()));
+ Output.push_back(
+ TemplateArgument::CreatePackCopy(S.Context, PackedArgsBuilder));
return false;
}
@@ -2730,7 +2739,7 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
return false;
if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
- S.IsDerivedFrom(A, DeducedA))
+ S.IsDerivedFrom(SourceLocation(), A, DeducedA))
return false;
return true;
@@ -2850,7 +2859,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
&NumExplicitArgs)
== Param) {
- Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
+ Builder.push_back(TemplateArgument(
+ llvm::makeArrayRef(ExplicitArgs, NumExplicitArgs)));
// Forget the partially-substituted pack; it's substitution is now
// complete.
@@ -2945,8 +2955,12 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
continue;
QualType DeducedA = Specialization->getParamDecl(ParamIdx)->getType();
- if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA))
- return Sema::TDK_SubstitutionFailure;
+ if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA)) {
+ Info.FirstArg = TemplateArgument(DeducedA);
+ Info.SecondArg = TemplateArgument(OriginalArg.OriginalArgType);
+ Info.CallArgIndex = OriginalArg.ArgIdx;
+ return TDK_DeducedMismatch;
+ }
}
}
@@ -3028,7 +3042,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
// Gather the explicit template arguments, if any.
TemplateArgumentListInfo ExplicitTemplateArgs;
if (Ovl->hasExplicitTemplateArgs())
- Ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+ Ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
QualType Match;
for (UnresolvedSetIterator I = Ovl->decls_begin(),
E = Ovl->decls_end(); I != E; ++I) {
@@ -3123,8 +3137,10 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
if (ParamRefType) {
// If the argument has incomplete array type, try to complete its type.
- if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
+ if (ArgType->isIncompleteArrayType()) {
+ S.completeExprArrayBound(Arg);
ArgType = Arg->getType();
+ }
// C++0x [temp.deduct.call]p3:
// If P is an rvalue reference to a cv-unqualified template
@@ -3203,24 +3219,63 @@ DeduceFromInitializerList(Sema &S, TemplateParameterList *TemplateParams,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF, Sema::TemplateDeductionResult &Result) {
- // If the argument is an initializer list then the parameter is an undeduced
- // context, unless the parameter type is (reference to cv)
- // std::initializer_list<P'>, in which case deduction is done for each element
- // of the initializer list as-if it were an argument in a function call, and
- // the result is the deduced type if it's the same for all elements.
- QualType X;
- if (!S.isStdInitializerList(AdjustedParamType, &X))
+
+ // [temp.deduct.call] p1 (post CWG-1591)
+ // If removing references and cv-qualifiers from P gives
+ // std::initializer_list<P0> or P0[N] for some P0 and N and the argument is a
+ // non-empty initializer list (8.5.4), then deduction is performed instead for
+ // each element of the initializer list, taking P0 as a function template
+ // parameter type and the initializer element as its argument, and in the
+ // P0[N] case, if N is a non-type template parameter, N is deduced from the
+ // length of the initializer list. Otherwise, an initializer list argument
+ // causes the parameter to be considered a non-deduced context
+
+ const bool IsConstSizedArray = AdjustedParamType->isConstantArrayType();
+
+ const bool IsDependentSizedArray =
+ !IsConstSizedArray && AdjustedParamType->isDependentSizedArrayType();
+
+ QualType ElTy; // The element type of the std::initializer_list or the array.
+
+ const bool IsSTDList = !IsConstSizedArray && !IsDependentSizedArray &&
+ S.isStdInitializerList(AdjustedParamType, &ElTy);
+
+ if (!IsConstSizedArray && !IsDependentSizedArray && !IsSTDList)
return false;
Result = Sema::TDK_Success;
-
- // Recurse down into the init list.
- for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
- if ((Result = DeduceTemplateArgumentByListElement(
- S, TemplateParams, X, ILE->getInit(i), Info, Deduced, TDF)))
- return true;
+ // If we are not deducing against the 'T' in a std::initializer_list<T> then
+ // deduce against the 'T' in T[N].
+ if (ElTy.isNull()) {
+ assert(!IsSTDList);
+ ElTy = S.Context.getAsArrayType(AdjustedParamType)->getElementType();
}
+ // Deduction only needs to be done for dependent types.
+ if (ElTy->isDependentType()) {
+ for (Expr *E : ILE->inits()) {
+ if ((Result = DeduceTemplateArgumentByListElement(S, TemplateParams, ElTy,
+ E, Info, Deduced, TDF)))
+ return true;
+ }
+ }
+ if (IsDependentSizedArray) {
+ const DependentSizedArrayType *ArrTy =
+ S.Context.getAsDependentSizedArrayType(AdjustedParamType);
+ // Determine the array bound is something we can deduce.
+ if (NonTypeTemplateParmDecl *NTTP =
+ getDeducedParameterFromExpr(ArrTy->getSizeExpr())) {
+ // We can perform template argument deduction for the given non-type
+ // template parameter.
+ assert(NTTP->getDepth() == 0 &&
+ "Cannot deduce non-type template argument at depth > 0");
+ llvm::APInt Size(S.Context.getIntWidth(NTTP->getType()),
+ ILE->getNumInits());
+ Result = DeduceNonTypeTemplateArgument(
+ S, NTTP, llvm::APSInt(Size), NTTP->getType(),
+ /*ArrayBound=*/true, Info, Deduced);
+ }
+ }
return true;
}
@@ -3908,7 +3963,7 @@ namespace {
!Replacement.isNull() && Replacement->isDependentType();
QualType Result =
SemaRef.Context.getAutoType(Dependent ? QualType() : Replacement,
- TL.getTypePtr()->isDecltypeAuto(),
+ TL.getTypePtr()->getKeyword(),
Dependent);
AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
@@ -3976,6 +4031,11 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
if (Result.isNull())
return DAR_FailedAlreadyDiagnosed;
return DAR_Succeeded;
+ } else if (!getLangOpts().CPlusPlus) {
+ if (isa<InitListExpr>(Init)) {
+ Diag(Init->getLocStart(), diag::err_auto_init_list_from_c);
+ return DAR_FailedAlreadyDiagnosed;
+ }
}
}
@@ -3989,8 +4049,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
nullptr, false, false);
QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0);
NamedDecl *TemplParamPtr = TemplParam;
- FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
- Loc);
+ FixedSizeTemplateParameterListStorage<1> TemplateParamsSt(
+ Loc, Loc, TemplParamPtr, Loc);
QualType FuncParam = SubstituteAutoTransform(*this, TemplArg).Apply(Type);
assert(!FuncParam.isNull() &&
@@ -4007,20 +4067,24 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
if (InitList) {
for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
- if (DeduceTemplateArgumentByListElement(*this, &TemplateParams,
- TemplArg,
- InitList->getInit(i),
+ if (DeduceTemplateArgumentByListElement(*this, TemplateParamsSt.get(),
+ TemplArg, InitList->getInit(i),
Info, Deduced, TDF))
return DAR_Failed;
}
} else {
- if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams,
- FuncParam, InitType, Init,
- TDF))
+ if (!getLangOpts().CPlusPlus && Init->refersToBitField()) {
+ Diag(Loc, diag::err_auto_bitfield);
+ return DAR_FailedAlreadyDiagnosed;
+ }
+
+ if (AdjustFunctionParmAndArgTypesForDeduction(
+ *this, TemplateParamsSt.get(), FuncParam, InitType, Init, TDF))
return DAR_Failed;
- if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
- InitType, Info, Deduced, TDF))
+ if (DeduceTemplateArgumentsByTypeMatch(*this, TemplateParamsSt.get(),
+ FuncParam, InitType, Info, Deduced,
+ TDF))
return DAR_Failed;
}
@@ -4828,19 +4892,23 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
break;
case Type::DependentTemplateSpecialization: {
+ // C++14 [temp.deduct.type]p5:
+ // The non-deduced contexts are:
+ // -- The nested-name-specifier of a type that was specified using a
+ // qualified-id
+ //
+ // C++14 [temp.deduct.type]p6:
+ // When a type name is specified in a way that includes a non-deduced
+ // context, all of the types that comprise that type name are also
+ // non-deduced.
+ if (OnlyDeduced)
+ break;
+
const DependentTemplateSpecializationType *Spec
= cast<DependentTemplateSpecializationType>(T);
- if (!OnlyDeduced)
- MarkUsedTemplateParameters(Ctx, Spec->getQualifier(),
- OnlyDeduced, Depth, Used);
- // C++0x [temp.deduct.type]p9:
- // If the template argument list of P contains a pack expansion that is not
- // the last template argument, the entire template argument list is a
- // non-deduced context.
- if (OnlyDeduced &&
- hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
- break;
+ MarkUsedTemplateParameters(Ctx, Spec->getQualifier(),
+ OnlyDeduced, Depth, Used);
for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
MarkUsedTemplateParameters(Ctx, Spec->getArg(I), OnlyDeduced, Depth,
@@ -4897,6 +4965,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
case Type::ObjCObject:
case Type::ObjCObjectPointer:
case Type::UnresolvedUsing:
+ case Type::Pipe:
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index c1961e5..fb7fc10 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -817,14 +817,6 @@ namespace {
QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
SubstTemplateTypeParmPackTypeLoc TL);
- ExprResult TransformCallExpr(CallExpr *CE) {
- getSema().CallsUndergoingInstantiation.push_back(CE);
- ExprResult Result =
- TreeTransform<TemplateInstantiator>::TransformCallExpr(CE);
- getSema().CallsUndergoingInstantiation.pop_back();
- return Result;
- }
-
ExprResult TransformLambdaExpr(LambdaExpr *E) {
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
return TreeTransform<TemplateInstantiator>::TransformLambdaExpr(E);
@@ -1231,7 +1223,7 @@ TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
// Transform each of the parameter expansions into the corresponding
// parameters in the instantiation of the function decl.
- SmallVector<Decl *, 8> Parms;
+ SmallVector<ParmVarDecl *, 8> Parms;
Parms.reserve(E->getNumExpansions());
for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
I != End; ++I) {
@@ -1682,15 +1674,17 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
} else if (Expr *Arg = OldParm->getDefaultArg()) {
FunctionDecl *OwningFunc = cast<FunctionDecl>(OldParm->getDeclContext());
- CXXRecordDecl *ClassD = dyn_cast<CXXRecordDecl>(OwningFunc->getDeclContext());
- if (ClassD && ClassD->isLocalClass() && !ClassD->isLambda()) {
- // If this is a method of a local class, as per DR1484 its default
- // arguments must be instantiated.
- Sema::ContextRAII SavedContext(*this, ClassD);
+ if (OwningFunc->isLexicallyWithinFunctionOrMethod()) {
+ // Instantiate default arguments for methods of local classes (DR1484)
+ // and non-defining declarations.
+ Sema::ContextRAII SavedContext(*this, OwningFunc);
LocalInstantiationScope Local(*this);
ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
- if (NewArg.isUsable())
- NewParm->setDefaultArg(NewArg.get());
+ if (NewArg.isUsable()) {
+ // It would be nice if we still had this.
+ SourceLocation EqualLoc = NewArg.get()->getLocStart();
+ SetParamDefaultArgument(NewParm, NewArg.get(), EqualLoc);
+ }
} else {
// FIXME: if we non-lazily instantiated non-dependent default args for
// non-dependent parameter types we could remove a bunch of duplicate
@@ -1843,9 +1837,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
Invalid = true;
}
- if (!Invalid &&
- AttachBaseSpecifiers(Instantiation, InstantiatedBases.data(),
- InstantiatedBases.size()))
+ if (!Invalid && AttachBaseSpecifiers(Instantiation, InstantiatedBases))
Invalid = true;
return Invalid;
@@ -2050,7 +2042,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// Default arguments are parsed, if not instantiated. We can go instantiate
// default arg exprs for default constructors if necessary now.
- ActOnFinishCXXMemberDefaultArgs(Instantiation);
+ ActOnFinishCXXNonNestedClass(Instantiation);
// Instantiate late parsed attributes, and attach them to their decls.
// See Sema::InstantiateAttrs
@@ -2672,16 +2664,17 @@ ExprResult Sema::SubstInitializer(Expr *Init,
return Instantiator.TransformInitializer(Init, CXXDirectInit);
}
-bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall,
+bool Sema::SubstExprs(ArrayRef<Expr *> Exprs, bool IsCall,
const MultiLevelTemplateArgumentList &TemplateArgs,
SmallVectorImpl<Expr *> &Outputs) {
- if (NumExprs == 0)
+ if (Exprs.empty())
return false;
TemplateInstantiator Instantiator(*this, TemplateArgs,
SourceLocation(),
DeclarationName());
- return Instantiator.TransformExprs(Exprs, NumExprs, IsCall, Outputs);
+ return Instantiator.TransformExprs(Exprs.data(), Exprs.size(),
+ IsCall, Outputs);
}
NestedNameSpecifierLoc
@@ -2806,14 +2799,14 @@ void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
#endif
Stored = Inst;
} else if (DeclArgumentPack *Pack = Stored.dyn_cast<DeclArgumentPack *>()) {
- Pack->push_back(Inst);
+ Pack->push_back(cast<ParmVarDecl>(Inst));
} else {
assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
}
}
-void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
- Decl *Inst) {
+void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
+ ParmVarDecl *Inst) {
D = getCanonicalParmVarDecl(D);
DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>();
Pack->push_back(Inst);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index aff2d1c..7a452af 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -813,6 +813,14 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
Enum->setAccess(D->getAccess());
// Forward the mangling number from the template to the instantiated decl.
SemaRef.Context.setManglingNumber(Enum, SemaRef.Context.getManglingNumber(D));
+ // See if the old tag was defined along with a declarator.
+ // If it did, mark the new tag as being associated with that declarator.
+ if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D))
+ SemaRef.Context.addDeclaratorForUnnamedTagDecl(Enum, DD);
+ // See if the old tag was defined along with a typedef.
+ // If it did, mark the new tag as being associated with that typedef.
+ if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D))
+ SemaRef.Context.addTypedefNameForUnnamedTagDecl(Enum, TND);
if (SubstQualifier(D, Enum)) return nullptr;
Owner->addDecl(Enum);
@@ -827,7 +835,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
SemaRef.SubstType(TI->getType(), TemplateArgs,
UnderlyingLoc, DeclarationName());
SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(),
- DefnUnderlying, Enum);
+ DefnUnderlying,
+ /*EnumUnderlyingIsImplicit=*/false, Enum);
}
}
@@ -913,6 +922,11 @@ Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
llvm_unreachable("EnumConstantDecls can only occur within EnumDecls.");
}
+Decl *
+TemplateDeclInstantiator::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
+ llvm_unreachable("BuiltinTemplateDecls cannot be instantiated.");
+}
+
Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
@@ -1143,6 +1157,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
VarDecl *VarInst =
cast_or_null<VarDecl>(VisitVarDecl(Pattern,
/*InstantiatingVarTemplate=*/true));
+ if (!VarInst) return nullptr;
DeclContext *DC = Owner;
@@ -1297,6 +1312,16 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
SemaRef.Context.setManglingNumber(Record,
SemaRef.Context.getManglingNumber(D));
+ // See if the old tag was defined along with a declarator.
+ // If it did, mark the new tag as being associated with that declarator.
+ if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D))
+ SemaRef.Context.addDeclaratorForUnnamedTagDecl(Record, DD);
+
+ // See if the old tag was defined along with a typedef.
+ // If it did, mark the new tag as being associated with that typedef.
+ if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D))
+ SemaRef.Context.addTypedefNameForUnnamedTagDecl(Record, TND);
+
Owner->addDecl(Record);
// DR1484 clarifies that the members of a local class are instantiated as part
@@ -1657,7 +1682,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
SmallVector<TemplateParameterList *, 4> TempParamLists;
unsigned NumTempParamLists = 0;
if (isFriend && (NumTempParamLists = D->getNumTemplateParameterLists())) {
- TempParamLists.set_size(NumTempParamLists);
+ TempParamLists.resize(NumTempParamLists);
for (unsigned I = 0; I != NumTempParamLists; ++I) {
TemplateParameterList *TempParams = D->getTemplateParameterList(I);
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
@@ -1809,9 +1834,9 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
// context (which will be a namespace scope) as the template.
if (isFriend) {
if (NumTempParamLists)
- Method->setTemplateParameterListsInfo(SemaRef.Context,
- NumTempParamLists,
- TempParamLists.data());
+ Method->setTemplateParameterListsInfo(
+ SemaRef.Context,
+ llvm::makeArrayRef(TempParamLists.data(), NumTempParamLists));
Method->setLexicalDeclContext(Owner);
Method->setObjectOfFriendDecl();
@@ -2742,7 +2767,7 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
TemplateParameterList *InstL
= TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
- L->getLAngleLoc(), &Params.front(), N,
+ L->getLAngleLoc(), Params,
L->getRAngleLoc());
return InstL;
}
@@ -3246,16 +3271,11 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
// exception specification.
// DR1484: Local classes and their members are instantiated along with the
// containing function.
- bool RequireInstantiation = false;
- if (CXXRecordDecl *Cls = dyn_cast<CXXRecordDecl>(Tmpl->getDeclContext())) {
- if (Cls->isLocalClass())
- RequireInstantiation = true;
- }
if (SemaRef.getLangOpts().CPlusPlus11 &&
EPI.ExceptionSpec.Type != EST_None &&
EPI.ExceptionSpec.Type != EST_DynamicNone &&
EPI.ExceptionSpec.Type != EST_BasicNoexcept &&
- !RequireInstantiation) {
+ !Tmpl->isLexicallyWithinFunctionOrMethod()) {
FunctionDecl *ExceptionSpecTemplate = Tmpl;
if (EPI.ExceptionSpec.Type == EST_Uninstantiated)
ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate;
@@ -3619,19 +3639,6 @@ void Sema::BuildVariableInstantiation(
NewVar->setReferenced(OldVar->isReferenced());
}
- // See if the old variable had a type-specifier that defined an anonymous tag.
- // If it did, mark the new variable as being the declarator for the new
- // anonymous tag.
- if (const TagType *OldTagType = OldVar->getType()->getAs<TagType>()) {
- TagDecl *OldTag = OldTagType->getDecl();
- if (OldTag->getDeclaratorForAnonDecl() == OldVar) {
- TagDecl *NewTag = NewVar->getType()->castAs<TagType>()->getDecl();
- assert(!NewTag->hasNameForLinkage() &&
- !NewTag->hasDeclaratorForAnonDecl());
- NewTag->setDeclaratorForAnonDecl(NewVar);
- }
- }
-
InstantiateAttrs(TemplateArgs, OldVar, NewVar, LateAttrs, StartingScope);
LookupResult Previous(
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
index fd3ba35..cb67d71 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -737,6 +737,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_interface:
case TST_class:
case TST_auto:
+ case TST_auto_type:
case TST_decltype_auto:
case TST_unknown_anytype:
case TST_error:
@@ -749,6 +750,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case DeclaratorChunk::Pointer:
case DeclaratorChunk::Reference:
case DeclaratorChunk::Paren:
+ case DeclaratorChunk::Pipe:
case DeclaratorChunk::BlockPointer:
// These declarator chunks cannot contain any parameter packs.
break;
@@ -867,8 +869,8 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
MarkAnyDeclReferenced(OpLoc, ParameterPack, true);
- return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc,
- ParameterPack, NameLoc, RParenLoc);
+ return SizeOfPackExpr::Create(Context, OpLoc, ParameterPack, NameLoc,
+ RParenLoc);
}
TemplateArgumentLoc
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
index 02a31ef..f6ad132 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -26,7 +26,6 @@
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
@@ -211,10 +210,8 @@ namespace {
/// Diagnose all the ignored type attributes, given that the
/// declarator worked out to the given type.
void diagnoseIgnoredTypeAttrs(QualType type) const {
- for (SmallVectorImpl<AttributeList*>::const_iterator
- i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end();
- i != e; ++i)
- diagnoseBadTypeAttribute(getSema(), **i, type);
+ for (auto *Attr : ignoredTypeAttrs)
+ diagnoseBadTypeAttribute(getSema(), *Attr, type);
}
~TypeProcessingState() {
@@ -338,6 +335,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
case DeclaratorChunk::Array:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
return result;
// If we do find a function declarator, scan inwards from that,
@@ -350,6 +348,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
case DeclaratorChunk::Array:
case DeclaratorChunk::Function:
case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Pipe:
continue;
case DeclaratorChunk::MemberPointer:
@@ -430,6 +429,7 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
// Don't walk through these.
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
goto error;
}
}
@@ -462,6 +462,7 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Paren:
case DeclaratorChunk::Array:
+ case DeclaratorChunk::Pipe:
continue;
case DeclaratorChunk::Function:
@@ -523,6 +524,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state,
case DeclaratorChunk::Array:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
continue;
}
}
@@ -702,7 +704,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*VolatileQualifierLoc=*/NoLoc,
/*RestrictQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc, EST_None,
- /*ESpecLoc=*/NoLoc,
+ /*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
@@ -792,18 +794,33 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
TypeSourceInfo *typeArgInfo = typeArgs[i];
QualType typeArg = typeArgInfo->getType();
- // Type arguments cannot explicitly specify nullability.
- if (auto nullability = AttributedType::stripOuterNullability(typeArg)) {
- SourceLocation nullabilityLoc
- = typeArgInfo->getTypeLoc().findNullabilityLoc();
- SourceLocation diagLoc = nullabilityLoc.isValid()? nullabilityLoc
- : typeArgInfo->getTypeLoc().getLocStart();
- S.Diag(diagLoc,
- diag::err_type_arg_explicit_nullability)
- << typeArg
- << FixItHint::CreateRemoval(nullabilityLoc);
+ // Type arguments cannot have explicit qualifiers or nullability.
+ // We ignore indirect sources of these, e.g. behind typedefs or
+ // template arguments.
+ if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) {
+ bool diagnosed = false;
+ SourceRange rangeToRemove;
+ if (auto attr = qual.getAs<AttributedTypeLoc>()) {
+ rangeToRemove = attr.getLocalSourceRange();
+ if (attr.getTypePtr()->getImmediateNullability()) {
+ typeArg = attr.getTypePtr()->getModifiedType();
+ S.Diag(attr.getLocStart(),
+ diag::err_objc_type_arg_explicit_nullability)
+ << typeArg << FixItHint::CreateRemoval(rangeToRemove);
+ diagnosed = true;
+ }
+ }
+
+ if (!diagnosed) {
+ S.Diag(qual.getLocStart(), diag::err_objc_type_arg_qualified)
+ << typeArg << typeArg.getQualifiers().getAsString()
+ << FixItHint::CreateRemoval(rangeToRemove);
+ }
}
+ // Remove qualifiers even if they're non-local.
+ typeArg = typeArg.getUnqualifiedType();
+
finalTypeArgs.push_back(typeArg);
if (typeArg->getAs<PackExpansionType>())
@@ -1260,6 +1277,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// value being declared, poison it as invalid so we don't get chains of
// errors.
declarator.setInvalidType(true);
+ } else if (S.getLangOpts().OpenCLVersion >= 200 && DS.isTypeSpecPipe()){
+ S.Diag(DeclLoc, diag::err_missing_actual_pipe_type)
+ << DS.getSourceRange();
+ declarator.setInvalidType(true);
} else {
S.Diag(DeclLoc, diag::ext_missing_type_specifier)
<< DS.getSourceRange();
@@ -1377,11 +1398,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
if (Result.isNull()) {
declarator.setInvalidType(true);
} else if (S.getLangOpts().OpenCL) {
- if (const AtomicType *AT = Result->getAs<AtomicType>()) {
- const BuiltinType *BT = AT->getValueType()->getAs<BuiltinType>();
- bool NoExtTypes = BT && (BT->getKind() == BuiltinType::Int ||
- BT->getKind() == BuiltinType::UInt ||
- BT->getKind() == BuiltinType::Float);
+ if (Result->getAs<AtomicType>()) {
+ StringRef TypeName = Result.getBaseTypeIdentifier()->getName();
+ bool NoExtTypes =
+ llvm::StringSwitch<bool>(TypeName)
+ .Cases("atomic_int", "atomic_uint", "atomic_float",
+ "atomic_flag", true)
+ .Default(false);
if (!S.getOpenCLOptions().cl_khr_int64_base_atomics && !NoExtTypes) {
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
<< Result << "cl_khr_int64_base_atomics";
@@ -1393,12 +1416,19 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
<< Result << "cl_khr_int64_extended_atomics";
declarator.setInvalidType(true);
}
- if (!S.getOpenCLOptions().cl_khr_fp64 && BT &&
- BT->getKind() == BuiltinType::Double) {
+ if (!S.getOpenCLOptions().cl_khr_fp64 &&
+ !TypeName.compare("atomic_double")) {
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
<< Result << "cl_khr_fp64";
declarator.setInvalidType(true);
}
+ } else if (!S.getOpenCLOptions().cl_khr_gl_msaa_sharing &&
+ (Result->isImage2dMSAAT() || Result->isImage2dArrayMSAAT() ||
+ Result->isImage2dArrayMSAATDepth() ||
+ Result->isImage2dMSAATDepth())) {
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
+ << Result << "cl_khr_gl_msaa_sharing";
+ declarator.setInvalidType(true);
}
}
@@ -1482,14 +1512,17 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// template type parameter.
Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0);
} else {
- Result = Context.getAutoType(QualType(), /*decltype(auto)*/false, false);
+ Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
}
break;
+ case DeclSpec::TST_auto_type:
+ Result = Context.getAutoType(QualType(), AutoTypeKeyword::GNUAutoType, false);
+ break;
+
case DeclSpec::TST_decltype_auto:
- Result = Context.getAutoType(QualType(),
- /*decltype(auto)*/true,
- /*IsDependent*/ false);
+ Result = Context.getAutoType(QualType(), AutoTypeKeyword::DecltypeAuto,
+ /*IsDependent*/ false);
break;
case DeclSpec::TST_unknown_anytype:
@@ -1540,8 +1573,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// Apply any type attributes from the decl spec. This may cause the
// list of type attributes to be temporarily saved while the type
// attributes are pushed around.
- if (AttributeList *attrs = DS.getAttributes().getList())
- processTypeAttrs(state, Result, TAL_DeclSpec, attrs);
+ // pipe attributes will be handled later ( at GetFullTypeForDeclarator )
+ if (!DS.isTypeSpecPipe())
+ processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList());
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@@ -1901,6 +1935,21 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
return Context.getRValueReferenceType(T);
}
+/// \brief Build a Pipe type.
+///
+/// \param T The type to which we'll be building a Pipe.
+///
+/// \param Loc We do not use it for now.
+///
+/// \returns A suitable pipe type, if there are no errors. Otherwise, returns a
+/// NULL type.
+QualType Sema::BuildPipeType(QualType T, SourceLocation Loc) {
+ assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
+
+ // Build the pipe type.
+ return Context.getPipeType(T);
+}
+
/// Check whether the specified array size makes the array type a VLA. If so,
/// return true, if not, return the size of the array in SizeVal.
static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
@@ -1975,7 +2024,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
if (!MPTy->getClass()->isDependentType())
- RequireCompleteType(Loc, T, 0);
+ (void)isCompleteType(Loc, T);
} else {
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
@@ -2103,12 +2152,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (T->isVariableArrayType()) {
// Prohibit the use of non-POD types in VLAs.
QualType BaseT = Context.getBaseElementType(T);
- if (!T->isDependentType() &&
- !RequireCompleteType(Loc, BaseT, 0) &&
- !BaseT.isPODType(Context) &&
- !BaseT->isObjCLifetimeType()) {
- Diag(Loc, diag::err_vla_non_pod)
- << BaseT;
+ if (!T->isDependentType() && isCompleteType(Loc, BaseT) &&
+ !BaseT.isPODType(Context) && !BaseT->isObjCLifetimeType()) {
+ Diag(Loc, diag::err_vla_non_pod) << BaseT;
return QualType();
}
// Prohibit the use of VLAs during template argument deduction.
@@ -2122,7 +2168,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
} else if (ASM != ArrayType::Normal || Quals != 0)
Diag(Loc,
getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx
- : diag::ext_c99_array_usage) << ASM;
+ : diag::ext_c99_array_usage) << ASM;
}
if (T->isVariableArrayType()) {
@@ -2271,8 +2317,11 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
// Adjust the default free function calling convention to the default method
// calling convention.
+ bool IsCtorOrDtor =
+ (Entity.getNameKind() == DeclarationName::CXXConstructorName) ||
+ (Entity.getNameKind() == DeclarationName::CXXDestructorName);
if (T->isFunctionType())
- adjustMemberFunctionCC(T, /*IsStatic=*/false);
+ adjustMemberFunctionCC(T, /*IsStatic=*/false, IsCtorOrDtor, Loc);
return Context.getMemberPointerType(T, Class.getTypePtr());
}
@@ -2370,6 +2419,7 @@ static void inferARCWriteback(TypeProcessingState &state,
case DeclaratorChunk::Array: // suppress if written (id[])?
case DeclaratorChunk::Function:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
return;
}
}
@@ -2432,14 +2482,14 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
return;
struct Qual {
- unsigned Mask;
const char *Name;
+ unsigned Mask;
SourceLocation Loc;
} const QualKinds[4] = {
- { DeclSpec::TQ_const, "const", ConstQualLoc },
- { DeclSpec::TQ_volatile, "volatile", VolatileQualLoc },
- { DeclSpec::TQ_restrict, "restrict", RestrictQualLoc },
- { DeclSpec::TQ_atomic, "_Atomic", AtomicQualLoc }
+ { "const", DeclSpec::TQ_const, ConstQualLoc },
+ { "volatile", DeclSpec::TQ_volatile, VolatileQualLoc },
+ { "restrict", DeclSpec::TQ_restrict, RestrictQualLoc },
+ { "_Atomic", DeclSpec::TQ_atomic, AtomicQualLoc }
};
SmallString<32> QualStr;
@@ -2455,7 +2505,7 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
// If we have a location for the qualifier, offer a fixit.
SourceLocation QualLoc = QualKinds[I].Loc;
- if (!QualLoc.isInvalid()) {
+ if (QualLoc.isValid()) {
FixIts[NumQuals] = FixItHint::CreateRemoval(QualLoc);
if (Loc.isInvalid() ||
getSourceManager().isBeforeInTranslationUnit(QualLoc, Loc))
@@ -2509,6 +2559,7 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
case DeclaratorChunk::Reference:
case DeclaratorChunk::Array:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
// FIXME: We can't currently provide an accurate source location and a
// fix-it hint for these.
unsigned AtomicQual = RetTy->isAtomicType() ? DeclSpec::TQ_atomic : 0;
@@ -2548,8 +2599,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// The TagDecl owned by the DeclSpec.
TagDecl *OwnedTagDecl = nullptr;
- bool ContainsPlaceholderType = false;
-
switch (D.getName().getKind()) {
case UnqualifiedId::IK_ImplicitSelfParam:
case UnqualifiedId::IK_OperatorFunctionId:
@@ -2557,7 +2606,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case UnqualifiedId::IK_LiteralOperatorId:
case UnqualifiedId::IK_TemplateId:
T = ConvertDeclSpecToType(state);
- ContainsPlaceholderType = D.getDeclSpec().containsPlaceholderType();
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
@@ -2572,8 +2620,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// Constructors and destructors don't have return types. Use
// "void" instead.
T = SemaRef.Context.VoidTy;
- if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList())
- processTypeAttrs(state, T, TAL_DeclSpec, attrs);
+ processTypeAttrs(state, T, TAL_DeclSpec,
+ D.getDeclSpec().getAttributes().getList());
break;
case UnqualifiedId::IK_ConversionFunctionId:
@@ -2581,7 +2629,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// converts to.
T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
&ReturnTypeInfo);
- ContainsPlaceholderType = T->getContainedAutoType();
break;
}
@@ -2589,17 +2636,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
distributeTypeAttrsFromDeclarator(state, T);
// C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
- // In C++11, a function declarator using 'auto' must have a trailing return
- // type (this is checked later) and we can skip this. In other languages
- // using auto, we need to check regardless.
- // C++14 In generic lambdas allow 'auto' in their parameters.
- if (ContainsPlaceholderType &&
- (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) {
+ if (D.getDeclSpec().containsPlaceholderType()) {
int Error = -1;
switch (D.getContext()) {
- case Declarator::KNRTypeListContext:
- llvm_unreachable("K&R type lists aren't allowed in C++");
case Declarator::LambdaExprContext:
llvm_unreachable("Can't specify a type specifier in lambda grammar");
case Declarator::ObjCParameterContext:
@@ -2608,69 +2648,88 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 0;
break;
case Declarator::LambdaExprParameterContext:
+ // In C++14, generic lambdas allow 'auto' in their parameters.
if (!(SemaRef.getLangOpts().CPlusPlus14
&& D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto))
- Error = 14;
+ Error = 16;
break;
- case Declarator::MemberContext:
- if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
+ case Declarator::MemberContext: {
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
+ D.isFunctionDeclarator())
break;
+ bool Cxx = SemaRef.getLangOpts().CPlusPlus;
switch (cast<TagDecl>(SemaRef.CurContext)->getTagKind()) {
case TTK_Enum: llvm_unreachable("unhandled tag kind");
- case TTK_Struct: Error = 1; /* Struct member */ break;
- case TTK_Union: Error = 2; /* Union member */ break;
- case TTK_Class: Error = 3; /* Class member */ break;
- case TTK_Interface: Error = 4; /* Interface member */ break;
+ case TTK_Struct: Error = Cxx ? 1 : 2; /* Struct member */ break;
+ case TTK_Union: Error = Cxx ? 3 : 4; /* Union member */ break;
+ case TTK_Class: Error = 5; /* Class member */ break;
+ case TTK_Interface: Error = 6; /* Interface member */ break;
}
break;
+ }
case Declarator::CXXCatchContext:
case Declarator::ObjCCatchContext:
- Error = 5; // Exception declaration
+ Error = 7; // Exception declaration
break;
case Declarator::TemplateParamContext:
- Error = 6; // Template parameter
+ Error = 8; // Template parameter
break;
case Declarator::BlockLiteralContext:
- Error = 7; // Block literal
+ Error = 9; // Block literal
break;
case Declarator::TemplateTypeArgContext:
- Error = 8; // Template type argument
+ Error = 10; // Template type argument
break;
case Declarator::AliasDeclContext:
case Declarator::AliasTemplateContext:
- Error = 10; // Type alias
+ Error = 12; // Type alias
break;
case Declarator::TrailingReturnContext:
- if (!SemaRef.getLangOpts().CPlusPlus14)
- Error = 11; // Function return type
+ if (!SemaRef.getLangOpts().CPlusPlus14 ||
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
+ Error = 13; // Function return type
break;
case Declarator::ConversionIdContext:
- if (!SemaRef.getLangOpts().CPlusPlus14)
- Error = 12; // conversion-type-id
+ if (!SemaRef.getLangOpts().CPlusPlus14 ||
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
+ Error = 14; // conversion-type-id
break;
case Declarator::TypeNameContext:
- Error = 13; // Generic
+ Error = 15; // Generic
break;
case Declarator::FileContext:
case Declarator::BlockContext:
case Declarator::ForContext:
case Declarator::ConditionContext:
+ break;
case Declarator::CXXNewContext:
+ if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
+ Error = 17; // 'new' type
+ break;
+ case Declarator::KNRTypeListContext:
+ Error = 18; // K&R function parameter
break;
}
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
- Error = 9;
-
- // In Objective-C it is an error to use 'auto' on a function declarator.
- if (D.isFunctionDeclarator())
Error = 11;
+ // In Objective-C it is an error to use 'auto' on a function declarator
+ // (and everywhere for '__auto_type').
+ if (D.isFunctionDeclarator() &&
+ (!SemaRef.getLangOpts().CPlusPlus11 ||
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type))
+ Error = 13;
+
+ bool HaveTrailing = false;
+
// C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator
// contains a trailing return type. That is only legal at the outermost
// level. Check all declarator chunks (outermost first) anyway, to give
// better diagnostics.
- if (SemaRef.getLangOpts().CPlusPlus11 && Error != -1) {
+ // We don't support '__auto_type' with trailing return types.
+ if (SemaRef.getLangOpts().CPlusPlus11 &&
+ D.getDeclSpec().getTypeSpecType() != DeclSpec::TST_auto_type) {
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
unsigned chunkIndex = e - i - 1;
state.setCurrentChunkIndex(chunkIndex);
@@ -2678,6 +2737,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
if (DeclType.Kind == DeclaratorChunk::Function) {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
if (FTI.hasTrailingReturnType()) {
+ HaveTrailing = true;
Error = -1;
break;
}
@@ -2690,22 +2750,31 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
AutoRange = D.getName().getSourceRange();
if (Error != -1) {
- const bool IsDeclTypeAuto =
- D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_decltype_auto;
+ unsigned Keyword;
+ switch (D.getDeclSpec().getTypeSpecType()) {
+ case DeclSpec::TST_auto: Keyword = 0; break;
+ case DeclSpec::TST_decltype_auto: Keyword = 1; break;
+ case DeclSpec::TST_auto_type: Keyword = 2; break;
+ default: llvm_unreachable("unknown auto TypeSpecType");
+ }
SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
- << IsDeclTypeAuto << Error << AutoRange;
+ << Keyword << Error << AutoRange;
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
- } else
+ } else if (!HaveTrailing) {
+ // If there was a trailing return type, we already got
+ // warn_cxx98_compat_trailing_return_type in the parser.
SemaRef.Diag(AutoRange.getBegin(),
diag::warn_cxx98_compat_auto_type_specifier)
<< AutoRange;
+ }
}
if (SemaRef.getLangOpts().CPlusPlus &&
OwnedTagDecl && OwnedTagDecl->isCompleteDefinition()) {
// Check the contexts where C++ forbids the declaration of a new class
// or enumeration in a type-specifier-seq.
+ unsigned DiagID = 0;
switch (D.getContext()) {
case Declarator::TrailingReturnContext:
// Class and enumeration definitions are syntactically not allowed in
@@ -2725,10 +2794,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::AliasDeclContext:
break;
case Declarator::AliasTemplateContext:
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_alias_template)
- << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
- D.setInvalidType(true);
+ DiagID = diag::err_type_defined_in_alias_template;
break;
case Declarator::TypeNameContext:
case Declarator::ConversionIdContext:
@@ -2737,10 +2803,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::CXXCatchContext:
case Declarator::ObjCCatchContext:
case Declarator::TemplateTypeArgContext:
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_type_specifier)
- << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
- D.setInvalidType(true);
+ DiagID = diag::err_type_defined_in_type_specifier;
break;
case Declarator::PrototypeContext:
case Declarator::LambdaExprParameterContext:
@@ -2749,20 +2812,21 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case Declarator::KNRTypeListContext:
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_param_type)
- << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
- D.setInvalidType(true);
+ DiagID = diag::err_type_defined_in_param_type;
break;
case Declarator::ConditionContext:
// C++ 6.4p2:
// The type-specifier-seq shall not contain typedef and shall not declare
// a new class or enumeration.
- SemaRef.Diag(OwnedTagDecl->getLocation(),
- diag::err_type_defined_in_condition);
- D.setInvalidType(true);
+ DiagID = diag::err_type_defined_in_condition;
break;
}
+
+ if (DiagID != 0) {
+ SemaRef.Diag(OwnedTagDecl->getLocation(), DiagID)
+ << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
+ D.setInvalidType(true);
+ }
}
assert(!T.isNull() && "This function should not return a null type");
@@ -3021,6 +3085,7 @@ static PointerDeclaratorKind classifyPointerDeclarator(Sema &S,
switch (chunk.Kind) {
case DeclaratorChunk::Array:
case DeclaratorChunk::Function:
+ case DeclaratorChunk::Pipe:
break;
case DeclaratorChunk::BlockPointer:
@@ -3269,6 +3334,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorChunk::Array:
DiagKind = 2;
break;
+ case DeclaratorChunk::Pipe:
+ break;
}
S.Diag(DeclChunk.Loc, DiagId) << DiagKind;
@@ -3286,14 +3353,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Are we in an assume-nonnull region?
bool inAssumeNonNullRegion = false;
- if (S.PP.getPragmaAssumeNonNullLoc().isValid() &&
- !state.getDeclarator().isObjCWeakProperty() &&
- !S.deduceWeakPropertyFromType(T)) {
+ if (S.PP.getPragmaAssumeNonNullLoc().isValid()) {
inAssumeNonNullRegion = true;
// Determine which file we saw the assume-nonnull region in.
FileID file = getNullabilityCompletenessCheckFileID(
S, S.PP.getPragmaAssumeNonNullLoc());
- if (!file.isInvalid()) {
+ if (file.isValid()) {
FileNullability &fileNullability = S.NullabilityMap[file];
// If we haven't seen any type nullability before, now we have.
@@ -3336,6 +3401,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
switch (chunk.Kind) {
case DeclaratorChunk::Array:
case DeclaratorChunk::Function:
+ case DeclaratorChunk::Pipe:
break;
case DeclaratorChunk::BlockPointer:
@@ -3367,6 +3433,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
complainAboutMissingNullability = CAMN_No;
break;
}
+
+ // Weak properties are inferred to be nullable.
+ if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) {
+ inferNullability = NullabilityKind::Nullable;
+ break;
+ }
+
// fallthrough
case Declarator::FileContext:
@@ -3648,6 +3721,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
case DeclaratorChunk::Function:
case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::Pipe:
// These are invalid anyway, so just ignore.
break;
}
@@ -3699,7 +3773,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType(true);
} else if (D.getContext() != Declarator::LambdaExprContext &&
(T.hasQualifiers() || !isa<AutoType>(T) ||
- cast<AutoType>(T)->isDecltypeAuto())) {
+ cast<AutoType>(T)->getKeyword() != AutoTypeKeyword::Auto)) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_trailing_return_without_auto)
<< T << D.getDeclSpec().getSourceRange();
@@ -3835,9 +3909,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Exception specs are not allowed in typedefs. Complain, but add it
// anyway.
if (IsTypedefName && FTI.getExceptionSpecType())
- S.Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef)
- << (D.getContext() == Declarator::AliasDeclContext ||
- D.getContext() == Declarator::AliasTemplateContext);
+ S.Diag(FTI.getExceptionSpecLocBeg(),
+ diag::err_exception_spec_in_typedef)
+ << (D.getContext() == Declarator::AliasDeclContext ||
+ D.getContext() == Declarator::AliasTemplateContext);
// If we see "T var();" or "T var(T());" at block scope, it is probably
// an attempt to initialize a variable, not a function declaration.
@@ -3996,7 +4071,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
}
- case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::MemberPointer: {
// The scope spec must refer to a class, or be dependent.
CXXScopeSpec &SS = DeclType.Mem.Scope();
QualType ClsType;
@@ -4056,14 +4131,20 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
}
+ case DeclaratorChunk::Pipe: {
+ T = S.BuildPipeType(T, DeclType.Loc );
+ break;
+ }
+ }
+
if (T.isNull()) {
D.setInvalidType(true);
T = Context.IntTy;
}
// See if there are any attributes on this declarator chunk.
- if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs()))
- processTypeAttrs(state, T, TAL_DeclChunk, attrs);
+ processTypeAttrs(state, T, TAL_DeclChunk,
+ const_cast<AttributeList *>(DeclType.getAttrs()));
}
assert(!T.isNull() && "T must not be null after this point");
@@ -4156,8 +4237,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// Apply any undistributed attributes from the declarator.
- if (AttributeList *attrs = D.getAttributes())
- processTypeAttrs(state, T, TAL_DeclName, attrs);
+ processTypeAttrs(state, T, TAL_DeclName, D.getAttributes());
// Diagnose any ignored type attributes.
state.diagnoseIgnoredTypeAttrs(T);
@@ -4351,6 +4431,7 @@ static void transferARCOwnership(TypeProcessingState &state,
case DeclaratorChunk::Function:
case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
return;
}
}
@@ -4377,7 +4458,7 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
- if (getLangOpts().ObjCAutoRefCount) {
+ if (getLangOpts().ObjC1) {
Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy);
if (ownership != Qualifiers::OCL_None)
transferARCOwnership(state, declSpecTy, ownership);
@@ -4402,6 +4483,7 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
case AttributedType::attr_objc_gc:
return AttributeList::AT_ObjCGC;
case AttributedType::attr_objc_ownership:
+ case AttributedType::attr_objc_inert_unsafe_unretained:
return AttributeList::AT_ObjCOwnership;
case AttributedType::attr_noreturn:
return AttributeList::AT_NoReturn;
@@ -4640,6 +4722,14 @@ namespace {
}
}
+ void VisitPipeTypeLoc(PipeTypeLoc TL) {
+ TL.setKWLoc(DS.getTypeSpecTypeLoc());
+
+ TypeSourceInfo *TInfo = 0;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
+ }
+
void VisitTypeLoc(TypeLoc TL) {
// FIXME: add other typespec types and change this to an assert.
TL.initialize(Context, DS.getTypeSpecTypeLoc());
@@ -4760,6 +4850,10 @@ namespace {
TL.setLParenLoc(Chunk.Loc);
TL.setRParenLoc(Chunk.EndLoc);
}
+ void VisitPipeTypeLoc(PipeTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Pipe);
+ TL.setKWLoc(Chunk.Loc);
+ }
void VisitTypeLoc(TypeLoc TL) {
llvm_unreachable("unsupported TypeLoc kind in declarator!");
@@ -4773,6 +4867,7 @@ static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) {
case DeclaratorChunk::Function:
case DeclaratorChunk::Array:
case DeclaratorChunk::Paren:
+ case DeclaratorChunk::Pipe:
llvm_unreachable("cannot be _Atomic qualified");
case DeclaratorChunk::Pointer:
@@ -5061,11 +5156,6 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
return true;
}
- // Consume lifetime attributes without further comment outside of
- // ARC mode.
- if (!S.getLangOpts().ObjCAutoRefCount)
- return true;
-
IdentifierInfo *II = attr.getArgAsIdent(0)->Ident;
Qualifiers::ObjCLifetime lifetime;
if (II->isStr("none"))
@@ -5083,6 +5173,14 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
return true;
}
+ // Just ignore lifetime attributes other than __weak and __unsafe_unretained
+ // outside of ARC mode.
+ if (!S.getLangOpts().ObjCAutoRefCount &&
+ lifetime != Qualifiers::OCL_Weak &&
+ lifetime != Qualifiers::OCL_ExplicitNone) {
+ return true;
+ }
+
SplitQualType underlyingType = type.split();
// Check for redundant/conflicting ownership qualifiers.
@@ -5123,6 +5221,25 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
<< TDS_ObjCObjOrBlock << type;
}
+ // Don't actually add the __unsafe_unretained qualifier in non-ARC files,
+ // because having both 'T' and '__unsafe_unretained T' exist in the type
+ // system causes unfortunate widespread consistency problems. (For example,
+ // they're not considered compatible types, and we mangle them identicially
+ // as template arguments.) These problems are all individually fixable,
+ // but it's easier to just not add the qualifier and instead sniff it out
+ // in specific places using isObjCInertUnsafeUnretainedType().
+ //
+ // Doing this does means we miss some trivial consistency checks that
+ // would've triggered in ARC, but that's better than trying to solve all
+ // the coexistence problems with __unsafe_unretained.
+ if (!S.getLangOpts().ObjCAutoRefCount &&
+ lifetime == Qualifiers::OCL_ExplicitNone) {
+ type = S.Context.getAttributedType(
+ AttributedType::attr_objc_inert_unsafe_unretained,
+ type, type);
+ return true;
+ }
+
QualType origType = type;
if (!NonObjCPointer)
type = S.Context.getQualifiedType(underlyingType);
@@ -5133,19 +5250,29 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
origType, type);
- // Forbid __weak if the runtime doesn't support it.
- if (lifetime == Qualifiers::OCL_Weak &&
- !S.getLangOpts().ObjCARCWeak && !NonObjCPointer) {
-
- // Actually, delay this until we know what we're parsing.
+ auto diagnoseOrDelay = [](Sema &S, SourceLocation loc,
+ unsigned diagnostic, QualType type) {
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
S.DelayedDiagnostics.add(
sema::DelayedDiagnostic::makeForbiddenType(
- S.getSourceManager().getExpansionLoc(AttrLoc),
- diag::err_arc_weak_no_runtime, type, /*ignored*/ 0));
+ S.getSourceManager().getExpansionLoc(loc),
+ diagnostic, type, /*ignored*/ 0));
} else {
- S.Diag(AttrLoc, diag::err_arc_weak_no_runtime);
+ S.Diag(loc, diagnostic);
}
+ };
+
+ // Sometimes, __weak isn't allowed.
+ if (lifetime == Qualifiers::OCL_Weak &&
+ !S.getLangOpts().ObjCWeak && !NonObjCPointer) {
+
+ // Use a specialized diagnostic if the runtime just doesn't support them.
+ unsigned diagnostic =
+ (S.getLangOpts().ObjCWeakRuntime ? diag::err_arc_weak_disabled
+ : diag::err_arc_weak_no_runtime);
+
+ // In any case, delay the diagnostic until we know what we're parsing.
+ diagnoseOrDelay(S, AttrLoc, diagnostic, type);
attr.setInvalid();
return true;
@@ -5158,9 +5285,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
type->getAs<ObjCObjectPointerType>()) {
if (ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl()) {
if (Class->isArcWeakrefUnavailable()) {
- S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
- S.Diag(ObjT->getInterfaceDecl()->getLocation(),
- diag::note_class_declared);
+ S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
+ S.Diag(ObjT->getInterfaceDecl()->getLocation(),
+ diag::note_class_declared);
}
}
}
@@ -5402,9 +5529,12 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
// Pointer type qualifiers can only operate on pointer types, but not
// pointer-to-member types.
if (!isa<PointerType>(Desugared)) {
- S.Diag(Attr.getLoc(), Type->isMemberPointerType() ?
- diag::err_attribute_no_member_pointers :
- diag::err_attribute_pointers_only) << Attr.getName();
+ if (Type->isMemberPointerType())
+ S.Diag(Attr.getLoc(), diag::err_attribute_no_member_pointers)
+ << Attr.getName();
+ else
+ S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
+ << Attr.getName() << 0;
return true;
}
@@ -5661,6 +5791,7 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
// Don't walk through these.
case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Pipe:
return false;
}
}
@@ -5843,25 +5974,41 @@ bool Sema::hasExplicitCallingConv(QualType &T) {
return false;
}
-void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) {
+void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
+ SourceLocation Loc) {
FunctionTypeUnwrapper Unwrapped(*this, T);
const FunctionType *FT = Unwrapped.get();
bool IsVariadic = (isa<FunctionProtoType>(FT) &&
cast<FunctionProtoType>(FT)->isVariadic());
-
- // Only adjust types with the default convention. For example, on Windows we
- // should adjust a __cdecl type to __thiscall for instance methods, and a
- // __thiscall type to __cdecl for static methods.
CallingConv CurCC = FT->getCallConv();
- CallingConv FromCC =
- Context.getDefaultCallingConvention(IsVariadic, IsStatic);
CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
- if (CurCC != FromCC || FromCC == ToCC)
- return;
- if (hasExplicitCallingConv(T))
+ if (CurCC == ToCC)
return;
+ // MS compiler ignores explicit calling convention attributes on structors. We
+ // should do the same.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft() && IsCtorOrDtor) {
+ // Issue a warning on ignored calling convention -- except of __stdcall.
+ // Again, this is what MS compiler does.
+ if (CurCC != CC_X86StdCall)
+ Diag(Loc, diag::warn_cconv_structors)
+ << FunctionType::getNameForCallConv(CurCC);
+ // Default adjustment.
+ } else {
+ // Only adjust types with the default convention. For example, on Windows
+ // we should adjust a __cdecl type to __thiscall for instance methods, and a
+ // __thiscall type to __cdecl for static methods.
+ CallingConv DefaultCC =
+ Context.getDefaultCallingConvention(IsVariadic, IsStatic);
+
+ if (CurCC != DefaultCC || DefaultCC == ToCC)
+ return;
+
+ if (hasExplicitCallingConv(T))
+ return;
+ }
+
FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(ToCC));
QualType Wrapped = Unwrapped.wrap(*this, FT);
T = Context.getAdjustedType(T, Wrapped);
@@ -6077,10 +6224,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// type, but others can be present in the type specifiers even though they
// apply to the decl. Here we apply type attributes and ignore the rest.
- AttributeList *next;
- do {
+ bool hasOpenCLAddressSpace = false;
+ while (attrs) {
AttributeList &attr = *attrs;
- next = attr.getNext();
+ attrs = attr.getNext(); // reset to the next here due to early loop continue
+ // stmts
// Skip attributes that were marked to be invalid.
if (attr.isInvalid())
@@ -6139,6 +6287,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case AttributeList::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
+ hasOpenCLAddressSpace = true;
break;
OBJC_POINTER_TYPE_ATTRS_CASELIST:
if (!handleObjCPointerTypeAttr(state, attr, type))
@@ -6233,7 +6382,83 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
distributeFunctionTypeAttr(state, attr, type);
break;
}
- } while ((attrs = next));
+ }
+
+ // If address space is not set, OpenCL 2.0 defines non private default
+ // address spaces for some cases:
+ // OpenCL 2.0, section 6.5:
+ // The address space for a variable at program scope or a static variable
+ // inside a function can either be __global or __constant, but defaults to
+ // __global if not specified.
+ // (...)
+ // Pointers that are declared without pointing to a named address space point
+ // to the generic address space.
+ if (state.getSema().getLangOpts().OpenCLVersion >= 200 &&
+ !hasOpenCLAddressSpace && type.getAddressSpace() == 0 &&
+ (TAL == TAL_DeclSpec || TAL == TAL_DeclChunk)) {
+ Declarator &D = state.getDeclarator();
+ if (state.getCurrentChunkIndex() > 0 &&
+ D.getTypeObject(state.getCurrentChunkIndex() - 1).Kind ==
+ DeclaratorChunk::Pointer) {
+ type = state.getSema().Context.getAddrSpaceQualType(
+ type, LangAS::opencl_generic);
+ } else if (state.getCurrentChunkIndex() == 0 &&
+ D.getContext() == Declarator::FileContext &&
+ !D.isFunctionDeclarator() && !D.isFunctionDefinition() &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ !type->isSamplerT())
+ type = state.getSema().Context.getAddrSpaceQualType(
+ type, LangAS::opencl_global);
+ else if (state.getCurrentChunkIndex() == 0 &&
+ D.getContext() == Declarator::BlockContext &&
+ D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
+ type = state.getSema().Context.getAddrSpaceQualType(
+ type, LangAS::opencl_global);
+ }
+}
+
+void Sema::completeExprArrayBound(Expr *E) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
+ if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
+ SourceLocation PointOfInstantiation = E->getExprLoc();
+
+ if (MemberSpecializationInfo *MSInfo =
+ Var->getMemberSpecializationInfo()) {
+ // If we don't already have a point of instantiation, this is it.
+ if (MSInfo->getPointOfInstantiation().isInvalid()) {
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+
+ // This is a modification of an existing AST node. Notify
+ // listeners.
+ if (ASTMutationListener *L = getASTMutationListener())
+ L->StaticDataMemberInstantiated(Var);
+ }
+ } else {
+ VarTemplateSpecializationDecl *VarSpec =
+ cast<VarTemplateSpecializationDecl>(Var);
+ if (VarSpec->getPointOfInstantiation().isInvalid())
+ VarSpec->setPointOfInstantiation(PointOfInstantiation);
+ }
+
+ InstantiateVariableDefinition(PointOfInstantiation, Var);
+
+ // Update the type to the newly instantiated definition's type both
+ // here and within the expression.
+ if (VarDecl *Def = Var->getDefinition()) {
+ DRE->setDecl(Def);
+ QualType T = Def->getType();
+ DRE->setType(T);
+ // FIXME: Update the type on all intervening expressions.
+ E->setType(T);
+ }
+
+ // We still go on to try to complete the type independently, as it
+ // may also require instantiations or diagnostics if it remains
+ // incomplete.
+ }
+ }
+ }
}
/// \brief Ensure that the type of the given expression is complete.
@@ -6250,87 +6475,26 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
///
/// \returns \c true if the type of \p E is incomplete and diagnosed, \c false
/// otherwise.
-bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser){
+bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser) {
QualType T = E->getType();
- // Fast path the case where the type is already complete.
- if (!T->isIncompleteType())
- // FIXME: The definition might not be visible.
- return false;
-
// Incomplete array types may be completed by the initializer attached to
// their definitions. For static data members of class templates and for
// variable templates, we need to instantiate the definition to get this
// initializer and complete the type.
if (T->isIncompleteArrayType()) {
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
- if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
- SourceLocation PointOfInstantiation = E->getExprLoc();
-
- if (MemberSpecializationInfo *MSInfo =
- Var->getMemberSpecializationInfo()) {
- // If we don't already have a point of instantiation, this is it.
- if (MSInfo->getPointOfInstantiation().isInvalid()) {
- MSInfo->setPointOfInstantiation(PointOfInstantiation);
-
- // This is a modification of an existing AST node. Notify
- // listeners.
- if (ASTMutationListener *L = getASTMutationListener())
- L->StaticDataMemberInstantiated(Var);
- }
- } else {
- VarTemplateSpecializationDecl *VarSpec =
- cast<VarTemplateSpecializationDecl>(Var);
- if (VarSpec->getPointOfInstantiation().isInvalid())
- VarSpec->setPointOfInstantiation(PointOfInstantiation);
- }
-
- InstantiateVariableDefinition(PointOfInstantiation, Var);
-
- // Update the type to the newly instantiated definition's type both
- // here and within the expression.
- if (VarDecl *Def = Var->getDefinition()) {
- DRE->setDecl(Def);
- T = Def->getType();
- DRE->setType(T);
- E->setType(T);
- }
-
- // We still go on to try to complete the type independently, as it
- // may also require instantiations or diagnostics if it remains
- // incomplete.
- }
- }
- }
+ completeExprArrayBound(E);
+ T = E->getType();
}
// FIXME: Are there other cases which require instantiating something other
// than the type to complete the type of an expression?
- // Look through reference types and complete the referred type.
- if (const ReferenceType *Ref = T->getAs<ReferenceType>())
- T = Ref->getPointeeType();
-
return RequireCompleteType(E->getExprLoc(), T, Diagnoser);
}
-namespace {
- struct TypeDiagnoserDiag : Sema::TypeDiagnoser {
- unsigned DiagID;
-
- TypeDiagnoserDiag(unsigned DiagID)
- : Sema::TypeDiagnoser(DiagID == 0), DiagID(DiagID) {}
-
- void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
- if (Suppressed) return;
- S.Diag(Loc, DiagID) << T;
- }
- };
-}
-
bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
- TypeDiagnoserDiag Diagnoser(DiagID);
+ BoundTypeDiagnoser<> Diagnoser(DiagID);
return RequireCompleteExprType(E, Diagnoser);
}
@@ -6353,7 +6517,7 @@ bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
/// @c false otherwise.
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
- if (RequireCompleteTypeImpl(Loc, T, Diagnoser))
+ if (RequireCompleteTypeImpl(Loc, T, &Diagnoser))
return true;
if (const TagType *Tag = T->getAs<TagType>()) {
if (!Tag->getDecl()->isCompleteDefinitionRequired()) {
@@ -6457,7 +6621,7 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
/// \brief The implementation of RequireCompleteType
bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
- TypeDiagnoser &Diagnoser) {
+ TypeDiagnoser *Diagnoser) {
// FIXME: Add this assertion to make sure we always get instantiation points.
// assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
// FIXME: Add this assertion to help us flush out problems with
@@ -6466,24 +6630,31 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// assert(!T->isDependentType() &&
// "Can't ask whether a dependent type is complete");
+ // We lock in the inheritance model once somebody has asked us to ensure
+ // that a pointer-to-member type is complete.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
+ if (!MPTy->getClass()->isDependentType()) {
+ (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
+ assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
+ }
+ }
+ }
+
// If we have a complete type, we're done.
NamedDecl *Def = nullptr;
if (!T->isIncompleteType(&Def)) {
// If we know about the definition but it is not visible, complain.
NamedDecl *SuggestedDef = nullptr;
- if (!Diagnoser.Suppressed && Def &&
- !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true))
- diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true);
-
- // We lock in the inheritance model once somebody has asked us to ensure
- // that a pointer-to-member type is complete.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
- if (!MPTy->getClass()->isDependentType()) {
- RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0);
- assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
- }
- }
+ if (Def &&
+ !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true)) {
+ // If the user is going to see an error here, recover by making the
+ // definition visible.
+ bool TreatAsComplete = Diagnoser && !isSFINAEContext();
+ if (Diagnoser)
+ diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true,
+ /*Recover*/TreatAsComplete);
+ return !TreatAsComplete;
}
return false;
@@ -6500,6 +6671,9 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
// chain for a declaration that can be accessed through a mechanism other
// than name lookup (eg, referenced in a template, or a variable whose type
// could be completed by the module)?
+ //
+ // FIXME: Should we map through to the base array element type before
+ // checking for a tag type?
if (Tag || IFace) {
NamedDecl *D =
Tag ? static_cast<NamedDecl *>(Tag->getDecl()) : IFace->getDecl();
@@ -6530,12 +6704,16 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
= Context.getAsConstantArrayType(MaybeTemplate))
MaybeTemplate = Array->getElementType();
if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
+ bool Instantiated = false;
+ bool Diagnosed = false;
if (ClassTemplateSpecializationDecl *ClassTemplateSpec
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
- if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
- return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec,
- TSK_ImplicitInstantiation,
- /*Complain=*/!Diagnoser.Suppressed);
+ if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
+ Diagnosed = InstantiateClassTemplateSpecialization(
+ Loc, ClassTemplateSpec, TSK_ImplicitInstantiation,
+ /*Complain=*/Diagnoser);
+ Instantiated = true;
+ }
} else if (CXXRecordDecl *Rec
= dyn_cast<CXXRecordDecl>(Record->getDecl())) {
CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass();
@@ -6543,16 +6721,31 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
MemberSpecializationInfo *MSI = Rec->getMemberSpecializationInfo();
assert(MSI && "Missing member specialization information?");
// This record was instantiated from a class within a template.
- if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
- return InstantiateClass(Loc, Rec, Pattern,
- getTemplateInstantiationArgs(Rec),
- TSK_ImplicitInstantiation,
- /*Complain=*/!Diagnoser.Suppressed);
+ if (MSI->getTemplateSpecializationKind() !=
+ TSK_ExplicitSpecialization) {
+ Diagnosed = InstantiateClass(Loc, Rec, Pattern,
+ getTemplateInstantiationArgs(Rec),
+ TSK_ImplicitInstantiation,
+ /*Complain=*/Diagnoser);
+ Instantiated = true;
+ }
}
}
+
+ if (Instantiated) {
+ // Instantiate* might have already complained that the template is not
+ // defined, if we asked it to.
+ if (Diagnoser && Diagnosed)
+ return true;
+ // If we instantiated a definition, check that it's usable, even if
+ // instantiation produced an error, so that repeated calls to this
+ // function give consistent answers.
+ if (!T->isIncompleteType())
+ return RequireCompleteTypeImpl(Loc, T, Diagnoser);
+ }
}
- if (Diagnoser.Suppressed)
+ if (!Diagnoser)
return true;
// We have an incomplete type. Produce a diagnostic.
@@ -6562,7 +6755,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
return true;
}
- Diagnoser.diagnose(*this, Loc, T);
+ Diagnoser->diagnose(*this, Loc, T);
// If the type was a forward declaration of a class/struct/union
// type, produce a note.
@@ -6586,7 +6779,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
unsigned DiagID) {
- TypeDiagnoserDiag Diagnoser(DiagID);
+ BoundTypeDiagnoser<> Diagnoser(DiagID);
return RequireCompleteType(Loc, T, Diagnoser);
}
@@ -6627,14 +6820,10 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
assert(!T->isDependentType() && "type should not be dependent");
QualType ElemType = Context.getBaseElementType(T);
- RequireCompleteType(Loc, ElemType, 0);
-
- if (T->isLiteralType(Context))
+ if ((isCompleteType(Loc, ElemType) || ElemType->isVoidType()) &&
+ T->isLiteralType(Context))
return false;
- if (Diagnoser.Suppressed)
- return true;
-
Diagnoser.diagnose(*this, Loc, T);
if (T->isVariableArrayType())
@@ -6649,10 +6838,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
// A partially-defined class type can't be a literal type, because a literal
// class type must have a trivial destructor (which can't be checked until
// the class definition is complete).
- if (!RD->isCompleteDefinition()) {
- RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T);
+ if (RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T))
return true;
- }
// If the class has virtual base classes, then it's not an aggregate, and
// cannot have any constexpr constructors or a trivial default constructor,
@@ -6704,7 +6891,7 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
}
bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) {
- TypeDiagnoserDiag Diagnoser(DiagID);
+ BoundTypeDiagnoser<> Diagnoser(DiagID);
return RequireLiteralType(Loc, T, Diagnoser);
}
@@ -6730,6 +6917,9 @@ QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
if (ER.isInvalid()) return QualType();
E = ER.get();
+ if (!getLangOpts().CPlusPlus && E->refersToBitField())
+ Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2;
+
if (!E->isTypeDependent()) {
QualType T = E->getType();
if (const TagType *TT = T->getAs<TagType>())
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
index 6e193a3..935304f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
@@ -21,6 +21,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
@@ -390,7 +391,7 @@ public:
/// due to transformation.
///
/// \returns true if an error occurred, false otherwise.
- bool TransformExprs(Expr **Inputs, unsigned NumInputs, bool IsCall,
+ bool TransformExprs(Expr *const *Inputs, unsigned NumInputs, bool IsCall,
SmallVectorImpl<Expr *> &Outputs,
bool *ArgChanged = nullptr);
@@ -503,7 +504,8 @@ public:
///
/// Returns true if there was an error.
bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
- TemplateArgumentLoc &Output);
+ TemplateArgumentLoc &Output,
+ bool Uneval = false);
/// \brief Transform the given set of template arguments.
///
@@ -525,8 +527,10 @@ public:
/// Returns true if an error occurred.
bool TransformTemplateArguments(const TemplateArgumentLoc *Inputs,
unsigned NumInputs,
- TemplateArgumentListInfo &Outputs) {
- return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs);
+ TemplateArgumentListInfo &Outputs,
+ bool Uneval = false) {
+ return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs,
+ Uneval);
}
/// \brief Transform the given set of template arguments.
@@ -546,7 +550,8 @@ public:
template<typename InputIterator>
bool TransformTemplateArguments(InputIterator First,
InputIterator Last,
- TemplateArgumentListInfo &Outputs);
+ TemplateArgumentListInfo &Outputs,
+ bool Uneval = false);
/// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument.
void InventTemplateArgumentLoc(const TemplateArgument &Arg,
@@ -843,11 +848,11 @@ public:
/// \brief Build a new C++11 auto type.
///
/// By default, builds a new AutoType with the given deduced type.
- QualType RebuildAutoType(QualType Deduced, bool IsDecltypeAuto) {
+ QualType RebuildAutoType(QualType Deduced, AutoTypeKeyword Keyword) {
// Note, IsDependent is always false here: we implicitly convert an 'auto'
// which has been deduced to a dependent type into an undeduced 'auto', so
// that we'll retry deduction after the transformation.
- return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto,
+ return SemaRef.Context.getAutoType(Deduced, Keyword,
/*IsDependent*/ false);
}
@@ -1041,6 +1046,9 @@ public:
/// Subclasses may override this routine to provide different behavior.
QualType RebuildAtomicType(QualType ValueType, SourceLocation KWLoc);
+ /// \brief Build a new pipe type given its value type.
+ QualType RebuildPipeType(QualType ValueType, SourceLocation KWLoc);
+
/// \brief Build a new template name given a nested name specifier, a flag
/// indicating whether the "template" keyword was provided, and the template
/// that the template name refers to.
@@ -1282,6 +1290,30 @@ public:
Constraints, Clobbers, Exprs, EndLoc);
}
+ /// \brief Build a new co_return statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildCoreturnStmt(SourceLocation CoreturnLoc, Expr *Result) {
+ return getSema().BuildCoreturnStmt(CoreturnLoc, Result);
+ }
+
+ /// \brief Build a new co_await expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCoawaitExpr(SourceLocation CoawaitLoc, Expr *Result) {
+ return getSema().BuildCoawaitExpr(CoawaitLoc, Result);
+ }
+
+ /// \brief Build a new co_yield expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildCoyieldExpr(SourceLocation CoyieldLoc, Expr *Result) {
+ return getSema().BuildCoyieldExpr(CoyieldLoc, Result);
+ }
+
/// \brief Build a new Objective-C \@try statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -1354,12 +1386,15 @@ public:
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
- OMPClause *RebuildOMPIfClause(Expr *Condition,
- SourceLocation StartLoc,
+ OMPClause *RebuildOMPIfClause(OpenMPDirectiveKind NameModifier,
+ Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
+ SourceLocation NameModifierLoc,
+ SourceLocation ColonLoc,
SourceLocation EndLoc) {
- return getSema().ActOnOpenMPIfClause(Condition, StartLoc,
- LParenLoc, EndLoc);
+ return getSema().ActOnOpenMPIfClause(NameModifier, Condition, StartLoc,
+ LParenLoc, NameModifierLoc, ColonLoc,
+ EndLoc);
}
/// \brief Build a new OpenMP 'final' clause.
@@ -1395,6 +1430,16 @@ public:
return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc);
}
+ /// \brief Build a new OpenMP 'simdlen' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPSimdlenClause(Len, StartLoc, LParenLoc, EndLoc);
+ }
+
/// \brief Build a new OpenMP 'collapse' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@@ -1436,15 +1481,24 @@ public:
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
- OMPClause *RebuildOMPScheduleClause(OpenMPScheduleClauseKind Kind,
- Expr *ChunkSize,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation KindLoc,
- SourceLocation CommaLoc,
- SourceLocation EndLoc) {
+ OMPClause *RebuildOMPScheduleClause(
+ OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
+ OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
+ SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
return getSema().ActOnOpenMPScheduleClause(
- Kind, ChunkSize, StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc);
+ M1, M2, Kind, ChunkSize, StartLoc, LParenLoc, M1Loc, M2Loc, KindLoc,
+ CommaLoc, EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'ordered' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPOrderedClause(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ SourceLocation LParenLoc, Expr *Num) {
+ return getSema().ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Num);
}
/// \brief Build a new OpenMP 'private' clause.
@@ -1518,10 +1572,13 @@ public:
OMPClause *RebuildOMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
SourceLocation StartLoc,
SourceLocation LParenLoc,
+ OpenMPLinearClauseKind Modifier,
+ SourceLocation ModifierLoc,
SourceLocation ColonLoc,
SourceLocation EndLoc) {
return getSema().ActOnOpenMPLinearClause(VarList, Step, StartLoc, LParenLoc,
- ColonLoc, EndLoc);
+ Modifier, ModifierLoc, ColonLoc,
+ EndLoc);
}
/// \brief Build a new OpenMP 'aligned' clause.
@@ -1586,6 +1643,97 @@ public:
StartLoc, LParenLoc, EndLoc);
}
+ /// \brief Build a new OpenMP 'device' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPDeviceClause(Expr *Device, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPDeviceClause(Device, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'map' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPMapClause(
+ OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType,
+ SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPMapClause(MapTypeModifier, MapType, MapLoc,
+ ColonLoc, VarList,StartLoc,
+ LParenLoc, EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'num_teams' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPNumTeamsClause(NumTeams, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'thread_limit' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPThreadLimitClause(Expr *ThreadLimit,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPThreadLimitClause(ThreadLimit, StartLoc,
+ LParenLoc, EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'priority' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPPriorityClause(Expr *Priority, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPPriorityClause(Priority, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'grainsize' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPGrainsizeClause(Expr *Grainsize, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPGrainsizeClause(Grainsize, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'num_tasks' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPNumTasksClause(NumTasks, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// \brief Build a new OpenMP 'hint' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPHintClause(Expr *Hint, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPHintClause(Hint, StartLoc, LParenLoc, EndLoc);
+ }
+
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -1673,6 +1821,7 @@ public:
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildCXXForRangeStmt(SourceLocation ForLoc,
+ SourceLocation CoawaitLoc,
SourceLocation ColonLoc,
Stmt *Range, Stmt *BeginEnd,
Expr *Cond, Expr *Inc,
@@ -1695,7 +1844,8 @@ public:
}
}
- return getSema().BuildCXXForRangeStmt(ForLoc, ColonLoc, Range, BeginEnd,
+ return getSema().BuildCXXForRangeStmt(ForLoc, CoawaitLoc, ColonLoc,
+ Range, BeginEnd,
Cond, Inc, LoopVar, RParenLoc,
Sema::BFRK_Rebuild);
}
@@ -1808,12 +1958,11 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildOffsetOfExpr(SourceLocation OperatorLoc,
- TypeSourceInfo *Type,
- Sema::OffsetOfComponent *Components,
- unsigned NumComponents,
- SourceLocation RParenLoc) {
+ TypeSourceInfo *Type,
+ ArrayRef<Sema::OffsetOfComponent> Components,
+ SourceLocation RParenLoc) {
return getSema().BuildBuiltinOffsetOf(OperatorLoc, Type, Components,
- NumComponents, RParenLoc);
+ RParenLoc);
}
/// \brief Build a new sizeof, alignof or vec_step expression with a
@@ -1857,6 +2006,18 @@ public:
RBracketLoc);
}
+ /// \brief Build a new array section expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildOMPArraySectionExpr(Expr *Base, SourceLocation LBracketLoc,
+ Expr *LowerBound,
+ SourceLocation ColonLoc, Expr *Length,
+ SourceLocation RBracketLoc) {
+ return getSema().ActOnOMPArraySectionExpr(Base, LBracketLoc, LowerBound,
+ ColonLoc, Length, RBracketLoc);
+ }
+
/// \brief Build a new call expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -1921,7 +2082,8 @@ public:
return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow,
SS, TemplateKWLoc,
FirstQualifierInScope,
- R, ExplicitTemplateArgs);
+ R, ExplicitTemplateArgs,
+ /*S*/nullptr);
}
/// \brief Build a new binary operator expression.
@@ -1987,7 +2149,8 @@ public:
SS, SourceLocation(),
/*FirstQualifierInScope*/ nullptr,
NameInfo,
- /* TemplateArgs */ nullptr);
+ /* TemplateArgs */ nullptr,
+ /*S*/ nullptr);
}
/// \brief Build a new initializer list expression.
@@ -2435,7 +2598,7 @@ public:
TemplateArgs);
return getSema().BuildQualifiedDeclarationNameExpr(
- SS, NameInfo, IsAddressOfOperand, RecoveryTSI);
+ SS, NameInfo, IsAddressOfOperand, /*S*/nullptr, RecoveryTSI);
}
/// \brief Build a new template-id expression.
@@ -2529,7 +2692,7 @@ public:
SS, TemplateKWLoc,
FirstQualifierInScope,
MemberNameInfo,
- TemplateArgs);
+ TemplateArgs, /*S*/nullptr);
}
/// \brief Build a new member reference expression.
@@ -2551,7 +2714,7 @@ public:
OperatorLoc, IsArrow,
SS, TemplateKWLoc,
FirstQualifierInScope,
- R, TemplateArgs);
+ R, TemplateArgs, /*S*/nullptr);
}
/// \brief Build a new noexcept expression.
@@ -2563,18 +2726,14 @@ public:
}
/// \brief Build a new expression to compute the length of a parameter pack.
- ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, NamedDecl *Pack,
+ ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc,
+ NamedDecl *Pack,
SourceLocation PackLoc,
SourceLocation RParenLoc,
- Optional<unsigned> Length) {
- if (Length)
- return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(),
- OperatorLoc, Pack, PackLoc,
- RParenLoc, *Length);
-
- return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(),
- OperatorLoc, Pack, PackLoc,
- RParenLoc);
+ Optional<unsigned> Length,
+ ArrayRef<TemplateArgument> PartialArgs) {
+ return SizeOfPackExpr::Create(SemaRef.Context, OperatorLoc, Pack, PackLoc,
+ RParenLoc, Length, PartialArgs);
}
/// \brief Build a new Objective-C boxed expression.
@@ -2608,9 +2767,8 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildObjCDictionaryLiteral(SourceRange Range,
- ObjCDictionaryElement *Elements,
- unsigned NumElements) {
- return getSema().BuildObjCDictionaryLiteral(Range, Elements, NumElements);
+ MutableArrayRef<ObjCDictionaryElement> Elements) {
+ return getSema().BuildObjCDictionaryLiteral(Range, Elements);
}
/// \brief Build a new Objective-C \@encode expression.
@@ -2657,20 +2815,18 @@ public:
ExprResult RebuildObjCMessageExpr(SourceLocation SuperLoc,
Selector Sel,
ArrayRef<SourceLocation> SelectorLocs,
+ QualType SuperType,
ObjCMethodDecl *Method,
SourceLocation LBracLoc,
MultiExprArg Args,
SourceLocation RBracLoc) {
- ObjCInterfaceDecl *Class = Method->getClassInterface();
- QualType ReceiverTy = SemaRef.Context.getObjCInterfaceType(Class);
-
return Method->isInstanceMethod() ? SemaRef.BuildInstanceMessage(nullptr,
- ReceiverTy,
+ SuperType,
SuperLoc,
Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, Args)
: SemaRef.BuildClassMessage(nullptr,
- ReceiverTy,
+ SuperType,
SuperLoc,
Sel, Method, LBracLoc, SelectorLocs,
RBracLoc, Args);
@@ -2693,7 +2849,8 @@ public:
SS, SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
NameInfo,
- /*TemplateArgs=*/nullptr);
+ /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
}
/// \brief Build a new Objective-C property reference expression.
@@ -2711,7 +2868,8 @@ public:
SS, SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
NameInfo,
- /*TemplateArgs=*/nullptr);
+ /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
}
/// \brief Build a new Objective-C property reference expression.
@@ -2743,7 +2901,8 @@ public:
SS, SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
NameInfo,
- /*TemplateArgs=*/nullptr);
+ /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
}
/// \brief Build a new shuffle vector expression.
@@ -3043,7 +3202,7 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
}
template<typename Derived>
-bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
+bool TreeTransform<Derived>::TransformExprs(Expr *const *Inputs,
unsigned NumInputs,
bool IsCall,
SmallVectorImpl<Expr *> &Outputs,
@@ -3424,7 +3583,7 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc(
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion: {
NestedNameSpecifierLocBuilder Builder;
- TemplateName Template = Arg.getAsTemplate();
+ TemplateName Template = Arg.getAsTemplateOrTemplatePattern();
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
Builder.MakeTrivial(SemaRef.Context, DTN->getQualifier(), Loc);
else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
@@ -3458,7 +3617,7 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc(
template<typename Derived>
bool TreeTransform<Derived>::TransformTemplateArgument(
const TemplateArgumentLoc &Input,
- TemplateArgumentLoc &Output) {
+ TemplateArgumentLoc &Output, bool Uneval) {
const TemplateArgument &Arg = Input.getArgument();
switch (Arg.getKind()) {
case TemplateArgument::Null:
@@ -3506,8 +3665,8 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
case TemplateArgument::Expression: {
// Template argument expressions are constant expressions.
- EnterExpressionEvaluationContext Unevaluated(getSema(),
- Sema::ConstantEvaluated);
+ EnterExpressionEvaluationContext Unevaluated(
+ getSema(), Uneval ? Sema::Unevaluated : Sema::ConstantEvaluated);
Expr *InputExpr = Input.getSourceExpression();
if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
@@ -3585,9 +3744,9 @@ public:
template<typename Derived>
template<typename InputIterator>
-bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
- InputIterator Last,
- TemplateArgumentListInfo &Outputs) {
+bool TreeTransform<Derived>::TransformTemplateArguments(
+ InputIterator First, InputIterator Last, TemplateArgumentListInfo &Outputs,
+ bool Uneval) {
for (; First != Last; ++First) {
TemplateArgumentLoc Out;
TemplateArgumentLoc In = *First;
@@ -3605,7 +3764,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
In.getArgument().pack_begin()),
PackLocIterator(*this,
In.getArgument().pack_end()),
- Outputs))
+ Outputs, Uneval))
return true;
continue;
@@ -3643,7 +3802,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
// expansion.
TemplateArgumentLoc OutPattern;
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
- if (getDerived().TransformTemplateArgument(Pattern, OutPattern))
+ if (getDerived().TransformTemplateArgument(Pattern, OutPattern, Uneval))
return true;
Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis,
@@ -3660,7 +3819,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
for (unsigned I = 0; I != *NumExpansions; ++I) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
- if (getDerived().TransformTemplateArgument(Pattern, Out))
+ if (getDerived().TransformTemplateArgument(Pattern, Out, Uneval))
return true;
if (Out.getArgument().containsUnexpandedParameterPack()) {
@@ -3678,7 +3837,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
if (RetainExpansion) {
ForgetPartiallySubstitutedPackRAII Forget(getDerived());
- if (getDerived().TransformTemplateArgument(Pattern, Out))
+ if (getDerived().TransformTemplateArgument(Pattern, Out, Uneval))
return true;
Out = getDerived().RebuildPackExpansion(Out, Ellipsis,
@@ -3693,7 +3852,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First,
}
// The simple case:
- if (getDerived().TransformTemplateArgument(In, Out))
+ if (getDerived().TransformTemplateArgument(In, Out, Uneval))
return true;
Outputs.addArgument(Out);
@@ -3810,7 +3969,7 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
Qs.removeObjCLifetime();
Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(),
Qs);
- Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(),
+ Result = SemaRef.Context.getAutoType(Deduced, AutoTy->getKeyword(),
AutoTy->isDependentType());
TLB.TypeWasModifiedSafely(Result);
} else {
@@ -4700,9 +4859,7 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType(
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() || ResultType != T->getReturnType() ||
- T->getNumParams() != ParamTypes.size() ||
- !std::equal(T->param_type_begin(), T->param_type_end(),
- ParamTypes.begin()) || EPIChanged) {
+ T->getParamTypes() != llvm::makeArrayRef(ParamTypes) || EPIChanged) {
Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes, EPI);
if (Result.isNull())
return QualType();
@@ -5015,7 +5172,7 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() || NewDeduced != OldDeduced ||
T->isDependentType()) {
- Result = getDerived().RebuildAutoType(NewDeduced, T->isDecltypeAuto());
+ Result = getDerived().RebuildAutoType(NewDeduced, T->getKeyword());
if (Result.isNull())
return QualType();
}
@@ -5170,6 +5327,26 @@ QualType TreeTransform<Derived>::TransformAtomicType(TypeLocBuilder &TLB,
return Result;
}
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformPipeType(TypeLocBuilder &TLB,
+ PipeTypeLoc TL) {
+ QualType ValueType = getDerived().TransformType(TLB, TL.getValueLoc());
+ if (ValueType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || ValueType != TL.getValueLoc().getType()) {
+ Result = getDerived().RebuildPipeType(ValueType, TL.getKWLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ PipeTypeLoc NewTL = TLB.push<PipeTypeLoc>(Result);
+ NewTL.setKWLoc(TL.getKWLoc());
+
+ return Result;
+}
+
/// \brief Simple iterator that traverses the template arguments in a
/// container that provides a \c getArgLoc() member function.
///
@@ -5974,7 +6151,7 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
}
}
- Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get()));
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get(), S->getIfLoc()));
if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
return StmtError();
@@ -6069,7 +6246,8 @@ TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
}
}
- Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get()));
+ Sema::FullExprArg FullCond(
+ getSema().MakeFullExpr(Cond.get(), S->getWhileLoc()));
if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
return StmtError();
@@ -6119,6 +6297,11 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
if (Init.isInvalid())
return StmtError();
+ // In OpenMP loop region loop control variable must be captured and be
+ // private. Perform analysis of first part (if any).
+ if (getSema().getLangOpts().OpenMP && Init.isUsable())
+ getSema().ActOnOpenMPLoopInitialization(S->getForLoc(), Init.get());
+
// Transform the condition
ExprResult Cond;
VarDecl *ConditionVar = nullptr;
@@ -6148,7 +6331,8 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
}
}
- Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get()));
+ Sema::FullExprArg FullCond(
+ getSema().MakeFullExpr(Cond.get(), S->getForLoc()));
if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
return StmtError();
@@ -6351,6 +6535,56 @@ TreeTransform<Derived>::TransformMSAsmStmt(MSAsmStmt *S) {
TransformedExprs, S->getEndLoc());
}
+// C++ Coroutines TS
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
+ // The coroutine body should be re-formed by the caller if necessary.
+ return getDerived().TransformStmt(S->getBody());
+}
+
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformCoreturnStmt(CoreturnStmt *S) {
+ ExprResult Result = getDerived().TransformInitializer(S->getOperand(),
+ /*NotCopyInit*/false);
+ if (Result.isInvalid())
+ return StmtError();
+
+ // Always rebuild; we don't know if this needs to be injected into a new
+ // context or if the promise type has changed.
+ return getDerived().RebuildCoreturnStmt(S->getKeywordLoc(), Result.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCoawaitExpr(CoawaitExpr *E) {
+ ExprResult Result = getDerived().TransformInitializer(E->getOperand(),
+ /*NotCopyInit*/false);
+ if (Result.isInvalid())
+ return ExprError();
+
+ // Always rebuild; we don't know if this needs to be injected into a new
+ // context or if the promise type has changed.
+ return getDerived().RebuildCoawaitExpr(E->getKeywordLoc(), Result.get());
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCoyieldExpr(CoyieldExpr *E) {
+ ExprResult Result = getDerived().TransformInitializer(E->getOperand(),
+ /*NotCopyInit*/false);
+ if (Result.isInvalid())
+ return ExprError();
+
+ // Always rebuild; we don't know if this needs to be injected into a new
+ // context or if the promise type has changed.
+ return getDerived().RebuildCoyieldExpr(E->getKeywordLoc(), Result.get());
+}
+
+// Objective-C Statements.
+
template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) {
@@ -6640,6 +6874,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
Inc.get() != S->getInc() ||
LoopVar.get() != S->getLoopVarStmt()) {
NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(),
+ S->getCoawaitLoc(),
S->getColonLoc(), Range.get(),
BeginEnd.get(), Cond.get(),
Inc.get(), LoopVar.get(),
@@ -6656,6 +6891,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
// it now so we have a new statement to attach the body to.
if (Body.get() != S->getBody() && NewStmt.get() == S) {
NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(),
+ S->getCoawaitLoc(),
S->getColonLoc(), Range.get(),
BeginEnd.get(), Cond.get(),
Inc.get(), LoopVar.get(),
@@ -6766,6 +7002,25 @@ TreeTransform<Derived>::TransformMSPropertyRefExpr(MSPropertyRefExpr *E) {
}
template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformMSPropertySubscriptExpr(
+ MSPropertySubscriptExpr *E) {
+ auto BaseRes = getDerived().TransformExpr(E->getBase());
+ if (BaseRes.isInvalid())
+ return ExprError();
+ auto IdxRes = getDerived().TransformExpr(E->getIdx());
+ if (IdxRes.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ BaseRes.get() == E->getBase() &&
+ IdxRes.get() == E->getIdx())
+ return E;
+
+ return getDerived().RebuildArraySubscriptExpr(
+ BaseRes.get(), SourceLocation(), IdxRes.get(), E->getRBracketLoc());
+}
+
+template <typename Derived>
StmtResult TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) {
StmtResult TryBlock = getDerived().TransformCompoundStmt(S->getTryBlock());
if (TryBlock.isInvalid())
@@ -6844,10 +7099,7 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
}
}
StmtResult AssociatedStmt;
- if (D->hasAssociatedStmt()) {
- if (!D->getAssociatedStmt()) {
- return StmtError();
- }
+ if (D->hasAssociatedStmt() && D->getAssociatedStmt()) {
getDerived().getSema().ActOnOpenMPRegionStart(D->getDirectiveKind(),
/*CurScope=*/nullptr);
StmtResult Body;
@@ -7115,6 +7367,17 @@ TreeTransform<Derived>::TransformOMPTargetDirective(OMPTargetDirective *D) {
}
template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTargetDataDirective(
+ OMPTargetDataDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_target_data, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPTeamsDirective(OMPTeamsDirective *D) {
DeclarationNameInfo DirName;
@@ -7147,6 +7410,39 @@ TreeTransform<Derived>::TransformOMPCancelDirective(OMPCancelDirective *D) {
return Res;
}
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPTaskLoopDirective(OMPTaskLoopDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_taskloop, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTaskLoopSimdDirective(
+ OMPTaskLoopSimdDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_taskloop_simd, DirName,
+ nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPDistributeDirective(
+ OMPDistributeDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_distribute, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clause transformation
//===----------------------------------------------------------------------===//
@@ -7155,8 +7451,9 @@ OMPClause *TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) {
ExprResult Cond = getDerived().TransformExpr(C->getCondition());
if (Cond.isInvalid())
return nullptr;
- return getDerived().RebuildOMPIfClause(Cond.get(), C->getLocStart(),
- C->getLParenLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPIfClause(
+ C->getNameModifier(), Cond.get(), C->getLocStart(), C->getLParenLoc(),
+ C->getNameModifierLoc(), C->getColonLoc(), C->getLocEnd());
}
template <typename Derived>
@@ -7190,10 +7487,20 @@ TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) {
template <typename Derived>
OMPClause *
+TreeTransform<Derived>::TransformOMPSimdlenClause(OMPSimdlenClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getSimdlen());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPSimdlenClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
TreeTransform<Derived>::TransformOMPCollapseClause(OMPCollapseClause *C) {
ExprResult E = getDerived().TransformExpr(C->getNumForLoops());
if (E.isInvalid())
- return 0;
+ return nullptr;
return getDerived().RebuildOMPCollapseClause(
E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
}
@@ -7221,15 +7528,23 @@ TreeTransform<Derived>::TransformOMPScheduleClause(OMPScheduleClause *C) {
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPScheduleClause(
+ C->getFirstScheduleModifier(), C->getSecondScheduleModifier(),
C->getScheduleKind(), E.get(), C->getLocStart(), C->getLParenLoc(),
+ C->getFirstScheduleModifierLoc(), C->getSecondScheduleModifierLoc(),
C->getScheduleKindLoc(), C->getCommaLoc(), C->getLocEnd());
}
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPOrderedClause(OMPOrderedClause *C) {
- // No need to rebuild this clause, no template-dependent parameters.
- return C;
+ ExprResult E;
+ if (auto *Num = C->getNumForLoops()) {
+ E = getDerived().TransformExpr(Num);
+ if (E.isInvalid())
+ return nullptr;
+ }
+ return getDerived().RebuildOMPOrderedClause(C->getLocStart(), C->getLocEnd(),
+ C->getLParenLoc(), E.get());
}
template <typename Derived>
@@ -7288,6 +7603,26 @@ TreeTransform<Derived>::TransformOMPSeqCstClause(OMPSeqCstClause *C) {
template <typename Derived>
OMPClause *
+TreeTransform<Derived>::TransformOMPThreadsClause(OMPThreadsClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPSIMDClause(OMPSIMDClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNogroupClause(OMPNogroupClause *C) {
+ // No need to rebuild this clause, no template-dependent parameters.
+ return C;
+}
+
+template <typename Derived>
+OMPClause *
TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
@@ -7385,9 +7720,9 @@ TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) {
ExprResult Step = getDerived().TransformExpr(C->getStep());
if (Step.isInvalid())
return nullptr;
- return getDerived().RebuildOMPLinearClause(Vars, Step.get(), C->getLocStart(),
- C->getLParenLoc(),
- C->getColonLoc(), C->getLocEnd());
+ return getDerived().RebuildOMPLinearClause(
+ Vars, Step.get(), C->getLocStart(), C->getLParenLoc(), C->getModifier(),
+ C->getModifierLoc(), C->getColonLoc(), C->getLocEnd());
}
template <typename Derived>
@@ -7469,6 +7804,91 @@ TreeTransform<Derived>::TransformOMPDependClause(OMPDependClause *C) {
C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPDeviceClause(OMPDeviceClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getDevice());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPDeviceClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPMapClause(OMPMapClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPMapClause(
+ C->getMapTypeModifier(), C->getMapType(), C->getMapLoc(),
+ C->getColonLoc(), Vars, C->getLocStart(), C->getLParenLoc(),
+ C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNumTeamsClause(OMPNumTeamsClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getNumTeams());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPNumTeamsClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPThreadLimitClause(OMPThreadLimitClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getThreadLimit());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPThreadLimitClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPPriorityClause(OMPPriorityClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getPriority());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPPriorityClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPGrainsizeClause(OMPGrainsizeClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getGrainsize());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPGrainsizeClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNumTasksClause(OMPNumTasksClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getNumTasks());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPNumTasksClause(
+ E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPHintClause(OMPHintClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getHint());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPHintClause(E.get(), C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
+}
+
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
@@ -7668,16 +8088,15 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
// template code that we don't care.
bool ExprChanged = false;
typedef Sema::OffsetOfComponent Component;
- typedef OffsetOfExpr::OffsetOfNode Node;
SmallVector<Component, 4> Components;
for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
- const Node &ON = E->getComponent(I);
+ const OffsetOfNode &ON = E->getComponent(I);
Component Comp;
Comp.isBrackets = true;
Comp.LocStart = ON.getSourceRange().getBegin();
Comp.LocEnd = ON.getSourceRange().getEnd();
switch (ON.getKind()) {
- case Node::Array: {
+ case OffsetOfNode::Array: {
Expr *FromIndex = E->getIndexExpr(ON.getArrayExprIndex());
ExprResult Index = getDerived().TransformExpr(FromIndex);
if (Index.isInvalid())
@@ -7689,8 +8108,8 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
break;
}
- case Node::Field:
- case Node::Identifier:
+ case OffsetOfNode::Field:
+ case OffsetOfNode::Identifier:
Comp.isBrackets = false;
Comp.U.IdentInfo = ON.getFieldName();
if (!Comp.U.IdentInfo)
@@ -7698,7 +8117,7 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
break;
- case Node::Base:
+ case OffsetOfNode::Base:
// Will be recomputed during the rebuild.
continue;
}
@@ -7714,14 +8133,13 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
// Build a new offsetof expression.
return getDerived().RebuildOffsetOfExpr(E->getOperatorLoc(), Type,
- Components.data(), Components.size(),
- E->getRParenLoc());
+ Components, E->getRParenLoc());
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) {
- assert(getDerived().AlreadyTransformed(E->getType()) &&
+ assert((!E->getSourceExpr() || getDerived().AlreadyTransformed(E->getType())) &&
"opaque value expression requires transformation");
return E;
}
@@ -7829,6 +8247,36 @@ TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
E->getRBracketLoc());
}
+template <typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformOMPArraySectionExpr(OMPArraySectionExpr *E) {
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
+ if (Base.isInvalid())
+ return ExprError();
+
+ ExprResult LowerBound;
+ if (E->getLowerBound()) {
+ LowerBound = getDerived().TransformExpr(E->getLowerBound());
+ if (LowerBound.isInvalid())
+ return ExprError();
+ }
+
+ ExprResult Length;
+ if (E->getLength()) {
+ Length = getDerived().TransformExpr(E->getLength());
+ if (Length.isInvalid())
+ return ExprError();
+ }
+
+ if (!getDerived().AlwaysRebuild() && Base.get() == E->getBase() &&
+ LowerBound.get() == E->getLowerBound() && Length.get() == E->getLength())
+ return E;
+
+ return getDerived().RebuildOMPArraySectionExpr(
+ Base.get(), E->getBase()->getLocEnd(), LowerBound.get(), E->getColonLoc(),
+ Length.get(), E->getRBracketLoc());
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
@@ -8995,9 +9443,20 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc();
// If we have neither explicit template arguments, nor the template keyword,
- // it's a normal declaration name.
- if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid())
+ // it's a normal declaration name or member reference.
+ if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) {
+ NamedDecl *D = R.getAsSingle<NamedDecl>();
+ // In a C++11 unevaluated context, an UnresolvedLookupExpr might refer to an
+ // instance member. In other contexts, BuildPossibleImplicitMemberExpr will
+ // give a good diagnostic.
+ if (D && D->isCXXInstanceMember()) {
+ return SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R,
+ /*TemplateArgs=*/nullptr,
+ /*Scope=*/nullptr);
+ }
+
return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL());
+ }
// If we have template arguments, rebuild them, then rebuild the
// templateid expression.
@@ -9404,9 +9863,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
VarDecl *OldVD = C->getCapturedVar();
QualType NewInitCaptureType =
- getSema().performLambdaInitCaptureInitialization(C->getLocation(),
- OldVD->getType()->isReferenceType(), OldVD->getIdentifier(),
- NewExprInit);
+ getSema().buildLambdaInitCaptureInitialization(
+ C->getLocation(), OldVD->getType()->isReferenceType(),
+ OldVD->getIdentifier(),
+ C->getCapturedVar()->getInitStyle() != VarDecl::CInit, NewExprInit);
NewExprInitResult = NewExprInit;
InitCaptureExprsAndTypes[C - E->capture_begin()] =
std::make_pair(NewExprInitResult, NewInitCaptureType);
@@ -9513,8 +9973,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
}
VarDecl *OldVD = C->getCapturedVar();
VarDecl *NewVD = getSema().createLambdaInitCaptureVarDecl(
- OldVD->getLocation(), InitExprTypePair.second,
- OldVD->getIdentifier(), Init.get());
+ OldVD->getLocation(), InitExprTypePair.second, OldVD->getIdentifier(),
+ OldVD->getInitStyle(), Init.get());
if (!NewVD)
Invalid = true;
else {
@@ -9886,36 +10346,86 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
if (!E->isValueDependent())
return E;
- // Note: None of the implementations of TryExpandParameterPacks can ever
- // produce a diagnostic when given only a single unexpanded parameter pack,
- // so
- UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc());
- bool ShouldExpand = false;
- bool RetainExpansion = false;
- Optional<unsigned> NumExpansions;
- if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(),
- Unexpanded,
- ShouldExpand, RetainExpansion,
- NumExpansions))
- return ExprError();
+ EnterExpressionEvaluationContext Unevaluated(getSema(), Sema::Unevaluated);
- if (RetainExpansion)
- return E;
+ ArrayRef<TemplateArgument> PackArgs;
+ TemplateArgument ArgStorage;
+
+ // Find the argument list to transform.
+ if (E->isPartiallySubstituted()) {
+ PackArgs = E->getPartialArguments();
+ } else if (E->isValueDependent()) {
+ UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc());
+ bool ShouldExpand = false;
+ bool RetainExpansion = false;
+ Optional<unsigned> NumExpansions;
+ if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(),
+ Unexpanded,
+ ShouldExpand, RetainExpansion,
+ NumExpansions))
+ return ExprError();
+
+ // If we need to expand the pack, build a template argument from it and
+ // expand that.
+ if (ShouldExpand) {
+ auto *Pack = E->getPack();
+ if (auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Pack)) {
+ ArgStorage = getSema().Context.getPackExpansionType(
+ getSema().Context.getTypeDeclType(TTPD), None);
+ } else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Pack)) {
+ ArgStorage = TemplateArgument(TemplateName(TTPD), None);
+ } else {
+ auto *VD = cast<ValueDecl>(Pack);
+ ExprResult DRE = getSema().BuildDeclRefExpr(VD, VD->getType(),
+ VK_RValue, E->getPackLoc());
+ if (DRE.isInvalid())
+ return ExprError();
+ ArgStorage = new (getSema().Context) PackExpansionExpr(
+ getSema().Context.DependentTy, DRE.get(), E->getPackLoc(), None);
+ }
+ PackArgs = ArgStorage;
+ }
+ }
- NamedDecl *Pack = E->getPack();
- if (!ShouldExpand) {
- Pack = cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getPackLoc(),
- Pack));
+ // If we're not expanding the pack, just transform the decl.
+ if (!PackArgs.size()) {
+ auto *Pack = cast_or_null<NamedDecl>(
+ getDerived().TransformDecl(E->getPackLoc(), E->getPack()));
if (!Pack)
return ExprError();
+ return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), Pack,
+ E->getPackLoc(),
+ E->getRParenLoc(), None, None);
+ }
+
+ TemplateArgumentListInfo TransformedPackArgs(E->getPackLoc(),
+ E->getPackLoc());
+ {
+ TemporaryBase Rebase(*this, E->getPackLoc(), getBaseEntity());
+ typedef TemplateArgumentLocInventIterator<
+ Derived, const TemplateArgument*> PackLocIterator;
+ if (TransformTemplateArguments(PackLocIterator(*this, PackArgs.begin()),
+ PackLocIterator(*this, PackArgs.end()),
+ TransformedPackArgs, /*Uneval*/true))
+ return ExprError();
+ }
+
+ SmallVector<TemplateArgument, 8> Args;
+ bool PartialSubstitution = false;
+ for (auto &Loc : TransformedPackArgs.arguments()) {
+ Args.push_back(Loc.getArgument());
+ if (Loc.getArgument().isPackExpansion())
+ PartialSubstitution = true;
}
+ if (PartialSubstitution)
+ return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(),
+ E->getPackLoc(),
+ E->getRParenLoc(), None, Args);
- // We now know the length of the parameter pack, so build a new expression
- // that stores that length.
- return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), Pack,
+ return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(),
E->getPackLoc(), E->getRParenLoc(),
- NumExpansions);
+ Args.size(), None);
}
template<typename Derived>
@@ -10242,8 +10752,7 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
return SemaRef.MaybeBindToTemporary(E);
return getDerived().RebuildObjCDictionaryLiteral(E->getSourceRange(),
- Elements.data(),
- Elements.size());
+ Elements);
}
template<typename Derived>
@@ -10337,6 +10846,7 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
return getDerived().RebuildObjCMessageExpr(E->getSuperLoc(),
E->getSelector(),
SelLocs,
+ E->getReceiverType(),
E->getMethodDecl(),
E->getLeftLoc(),
Args,
@@ -10863,6 +11373,12 @@ QualType TreeTransform<Derived>::RebuildAtomicType(QualType ValueType,
}
template<typename Derived>
+QualType TreeTransform<Derived>::RebuildPipeType(QualType ValueType,
+ SourceLocation KWLoc) {
+ return SemaRef.BuildPipeType(ValueType, KWLoc);
+}
+
+template<typename Derived>
TemplateName
TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
bool TemplateKW,
@@ -11075,7 +11591,8 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
SS, TemplateKWLoc,
/*FIXME: FirstQualifier*/ nullptr,
NameInfo,
- /*TemplateArgs*/ nullptr);
+ /*TemplateArgs*/ nullptr,
+ /*S*/nullptr);
}
template<typename Derived>
@@ -11114,4 +11631,4 @@ TreeTransform<Derived>::TransformCapturedStmt(CapturedStmt *S) {
} // end namespace clang
-#endif
+#endif // LLVM_CLANG_LIB_SEMA_TREETRANSFORM_H
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
index b1bf4a6..2b78d74 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
@@ -27,52 +27,166 @@ serialization::TypeIdx
serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
unsigned ID = 0;
switch (BT->getKind()) {
- case BuiltinType::Void: ID = PREDEF_TYPE_VOID_ID; break;
- case BuiltinType::Bool: ID = PREDEF_TYPE_BOOL_ID; break;
- case BuiltinType::Char_U: ID = PREDEF_TYPE_CHAR_U_ID; break;
- case BuiltinType::UChar: ID = PREDEF_TYPE_UCHAR_ID; break;
- case BuiltinType::UShort: ID = PREDEF_TYPE_USHORT_ID; break;
- case BuiltinType::UInt: ID = PREDEF_TYPE_UINT_ID; break;
- case BuiltinType::ULong: ID = PREDEF_TYPE_ULONG_ID; break;
- case BuiltinType::ULongLong: ID = PREDEF_TYPE_ULONGLONG_ID; break;
- case BuiltinType::UInt128: ID = PREDEF_TYPE_UINT128_ID; break;
- case BuiltinType::Char_S: ID = PREDEF_TYPE_CHAR_S_ID; break;
- case BuiltinType::SChar: ID = PREDEF_TYPE_SCHAR_ID; break;
+ case BuiltinType::Void:
+ ID = PREDEF_TYPE_VOID_ID;
+ break;
+ case BuiltinType::Bool:
+ ID = PREDEF_TYPE_BOOL_ID;
+ break;
+ case BuiltinType::Char_U:
+ ID = PREDEF_TYPE_CHAR_U_ID;
+ break;
+ case BuiltinType::UChar:
+ ID = PREDEF_TYPE_UCHAR_ID;
+ break;
+ case BuiltinType::UShort:
+ ID = PREDEF_TYPE_USHORT_ID;
+ break;
+ case BuiltinType::UInt:
+ ID = PREDEF_TYPE_UINT_ID;
+ break;
+ case BuiltinType::ULong:
+ ID = PREDEF_TYPE_ULONG_ID;
+ break;
+ case BuiltinType::ULongLong:
+ ID = PREDEF_TYPE_ULONGLONG_ID;
+ break;
+ case BuiltinType::UInt128:
+ ID = PREDEF_TYPE_UINT128_ID;
+ break;
+ case BuiltinType::Char_S:
+ ID = PREDEF_TYPE_CHAR_S_ID;
+ break;
+ case BuiltinType::SChar:
+ ID = PREDEF_TYPE_SCHAR_ID;
+ break;
case BuiltinType::WChar_S:
- case BuiltinType::WChar_U: ID = PREDEF_TYPE_WCHAR_ID; break;
- case BuiltinType::Short: ID = PREDEF_TYPE_SHORT_ID; break;
- case BuiltinType::Int: ID = PREDEF_TYPE_INT_ID; break;
- case BuiltinType::Long: ID = PREDEF_TYPE_LONG_ID; break;
- case BuiltinType::LongLong: ID = PREDEF_TYPE_LONGLONG_ID; break;
- case BuiltinType::Int128: ID = PREDEF_TYPE_INT128_ID; break;
- case BuiltinType::Half: ID = PREDEF_TYPE_HALF_ID; break;
- case BuiltinType::Float: ID = PREDEF_TYPE_FLOAT_ID; break;
- case BuiltinType::Double: ID = PREDEF_TYPE_DOUBLE_ID; break;
- case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break;
- case BuiltinType::NullPtr: ID = PREDEF_TYPE_NULLPTR_ID; break;
- case BuiltinType::Char16: ID = PREDEF_TYPE_CHAR16_ID; break;
- case BuiltinType::Char32: ID = PREDEF_TYPE_CHAR32_ID; break;
- case BuiltinType::Overload: ID = PREDEF_TYPE_OVERLOAD_ID; break;
- case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER; break;
- case BuiltinType::PseudoObject:ID = PREDEF_TYPE_PSEUDO_OBJECT;break;
- case BuiltinType::Dependent: ID = PREDEF_TYPE_DEPENDENT_ID; break;
- case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY; break;
+ case BuiltinType::WChar_U:
+ ID = PREDEF_TYPE_WCHAR_ID;
+ break;
+ case BuiltinType::Short:
+ ID = PREDEF_TYPE_SHORT_ID;
+ break;
+ case BuiltinType::Int:
+ ID = PREDEF_TYPE_INT_ID;
+ break;
+ case BuiltinType::Long:
+ ID = PREDEF_TYPE_LONG_ID;
+ break;
+ case BuiltinType::LongLong:
+ ID = PREDEF_TYPE_LONGLONG_ID;
+ break;
+ case BuiltinType::Int128:
+ ID = PREDEF_TYPE_INT128_ID;
+ break;
+ case BuiltinType::Half:
+ ID = PREDEF_TYPE_HALF_ID;
+ break;
+ case BuiltinType::Float:
+ ID = PREDEF_TYPE_FLOAT_ID;
+ break;
+ case BuiltinType::Double:
+ ID = PREDEF_TYPE_DOUBLE_ID;
+ break;
+ case BuiltinType::LongDouble:
+ ID = PREDEF_TYPE_LONGDOUBLE_ID;
+ break;
+ case BuiltinType::NullPtr:
+ ID = PREDEF_TYPE_NULLPTR_ID;
+ break;
+ case BuiltinType::Char16:
+ ID = PREDEF_TYPE_CHAR16_ID;
+ break;
+ case BuiltinType::Char32:
+ ID = PREDEF_TYPE_CHAR32_ID;
+ break;
+ case BuiltinType::Overload:
+ ID = PREDEF_TYPE_OVERLOAD_ID;
+ break;
+ case BuiltinType::BoundMember:
+ ID = PREDEF_TYPE_BOUND_MEMBER;
+ break;
+ case BuiltinType::PseudoObject:
+ ID = PREDEF_TYPE_PSEUDO_OBJECT;
+ break;
+ case BuiltinType::Dependent:
+ ID = PREDEF_TYPE_DEPENDENT_ID;
+ break;
+ case BuiltinType::UnknownAny:
+ ID = PREDEF_TYPE_UNKNOWN_ANY;
+ break;
case BuiltinType::ARCUnbridgedCast:
- ID = PREDEF_TYPE_ARC_UNBRIDGED_CAST; break;
- case BuiltinType::ObjCId: ID = PREDEF_TYPE_OBJC_ID; break;
- case BuiltinType::ObjCClass: ID = PREDEF_TYPE_OBJC_CLASS; break;
- case BuiltinType::ObjCSel: ID = PREDEF_TYPE_OBJC_SEL; break;
- case BuiltinType::OCLImage1d: ID = PREDEF_TYPE_IMAGE1D_ID; break;
- case BuiltinType::OCLImage1dArray: ID = PREDEF_TYPE_IMAGE1D_ARR_ID; break;
- case BuiltinType::OCLImage1dBuffer: ID = PREDEF_TYPE_IMAGE1D_BUFF_ID; break;
- case BuiltinType::OCLImage2d: ID = PREDEF_TYPE_IMAGE2D_ID; break;
- case BuiltinType::OCLImage2dArray: ID = PREDEF_TYPE_IMAGE2D_ARR_ID; break;
- case BuiltinType::OCLImage3d: ID = PREDEF_TYPE_IMAGE3D_ID; break;
- case BuiltinType::OCLSampler: ID = PREDEF_TYPE_SAMPLER_ID; break;
- case BuiltinType::OCLEvent: ID = PREDEF_TYPE_EVENT_ID; break;
+ ID = PREDEF_TYPE_ARC_UNBRIDGED_CAST;
+ break;
+ case BuiltinType::ObjCId:
+ ID = PREDEF_TYPE_OBJC_ID;
+ break;
+ case BuiltinType::ObjCClass:
+ ID = PREDEF_TYPE_OBJC_CLASS;
+ break;
+ case BuiltinType::ObjCSel:
+ ID = PREDEF_TYPE_OBJC_SEL;
+ break;
+ case BuiltinType::OCLImage1d:
+ ID = PREDEF_TYPE_IMAGE1D_ID;
+ break;
+ case BuiltinType::OCLImage1dArray:
+ ID = PREDEF_TYPE_IMAGE1D_ARR_ID;
+ break;
+ case BuiltinType::OCLImage1dBuffer:
+ ID = PREDEF_TYPE_IMAGE1D_BUFF_ID;
+ break;
+ case BuiltinType::OCLImage2d:
+ ID = PREDEF_TYPE_IMAGE2D_ID;
+ break;
+ case BuiltinType::OCLImage2dArray:
+ ID = PREDEF_TYPE_IMAGE2D_ARR_ID;
+ break;
+ case BuiltinType::OCLImage2dDepth:
+ ID = PREDEF_TYPE_IMAGE2D_DEP_ID;
+ break;
+ case BuiltinType::OCLImage2dArrayDepth:
+ ID = PREDEF_TYPE_IMAGE2D_ARR_DEP_ID;
+ break;
+ case BuiltinType::OCLImage2dMSAA:
+ ID = PREDEF_TYPE_IMAGE2D_MSAA_ID;
+ break;
+ case BuiltinType::OCLImage2dArrayMSAA:
+ ID = PREDEF_TYPE_IMAGE2D_ARR_MSAA_ID;
+ break;
+ case BuiltinType::OCLImage2dMSAADepth:
+ ID = PREDEF_TYPE_IMAGE2D_MSAA_DEP_ID;
+ break;
+ case BuiltinType::OCLImage2dArrayMSAADepth:
+ ID = PREDEF_TYPE_IMAGE2D_ARR_MSAA_DEPTH_ID;
+ break;
+ case BuiltinType::OCLImage3d:
+ ID = PREDEF_TYPE_IMAGE3D_ID;
+ break;
+ case BuiltinType::OCLSampler:
+ ID = PREDEF_TYPE_SAMPLER_ID;
+ break;
+ case BuiltinType::OCLEvent:
+ ID = PREDEF_TYPE_EVENT_ID;
+ break;
+ case BuiltinType::OCLClkEvent:
+ ID = PREDEF_TYPE_CLK_EVENT_ID;
+ break;
+ case BuiltinType::OCLQueue:
+ ID = PREDEF_TYPE_QUEUE_ID;
+ break;
+ case BuiltinType::OCLNDRange:
+ ID = PREDEF_TYPE_NDRANGE_ID;
+ break;
+ case BuiltinType::OCLReserveID:
+ ID = PREDEF_TYPE_RESERVE_ID_ID;
+ break;
case BuiltinType::BuiltinFn:
- ID = PREDEF_TYPE_BUILTIN_FN; break;
-
+ ID = PREDEF_TYPE_BUILTIN_FN;
+ break;
+ case BuiltinType::OMPArraySection:
+ ID = PREDEF_TYPE_OMP_ARRAY_SECTION;
+ break;
}
return TypeIdx(ID);
@@ -215,6 +329,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::ClassScopeFunctionSpecialization:
case Decl::Import:
case Decl::OMPThreadPrivate:
+ case Decl::BuiltinTemplate:
return false;
// These indirectly derive from Redeclarable<T> but are not actually
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
index f21e8a7..64f583c 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.h
@@ -29,6 +29,7 @@ enum DeclUpdateKind {
UPD_CXX_ADDED_FUNCTION_DEFINITION,
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
UPD_CXX_INSTANTIATED_CLASS_DEFINITION,
+ UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT,
UPD_CXX_RESOLVED_DTOR_DELETE,
UPD_CXX_RESOLVED_EXCEPTION_SPEC,
UPD_CXX_DEDUCED_RETURN_TYPE,
@@ -62,8 +63,6 @@ TypeID MakeTypeID(ASTContext &Context, QualType T, IdxForTypeTy IdxForType) {
return TypeIdx(PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals);
if (T == Context.AutoRRefDeductTy)
return TypeIdx(PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals);
- if (T == Context.VaListTagTy)
- return TypeIdx(PREDEF_TYPE_VA_LIST_TAG).asTypeID(FastQuals);
return IdxForType(T).asTypeID(FastQuals);
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
index 9fbf55b..833ff57 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
@@ -138,23 +139,33 @@ bool ChainedASTReaderListener::needsSystemInputFileVisitation() {
return First->needsSystemInputFileVisitation() ||
Second->needsSystemInputFileVisitation();
}
-void ChainedASTReaderListener::visitModuleFile(StringRef Filename) {
- First->visitModuleFile(Filename);
- Second->visitModuleFile(Filename);
+void ChainedASTReaderListener::visitModuleFile(StringRef Filename,
+ ModuleKind Kind) {
+ First->visitModuleFile(Filename, Kind);
+ Second->visitModuleFile(Filename, Kind);
}
bool ChainedASTReaderListener::visitInputFile(StringRef Filename,
bool isSystem,
- bool isOverridden) {
+ bool isOverridden,
+ bool isExplicitModule) {
bool Continue = false;
if (First->needsInputFileVisitation() &&
(!isSystem || First->needsSystemInputFileVisitation()))
- Continue |= First->visitInputFile(Filename, isSystem, isOverridden);
+ Continue |= First->visitInputFile(Filename, isSystem, isOverridden,
+ isExplicitModule);
if (Second->needsInputFileVisitation() &&
(!isSystem || Second->needsSystemInputFileVisitation()))
- Continue |= Second->visitInputFile(Filename, isSystem, isOverridden);
+ Continue |= Second->visitInputFile(Filename, isSystem, isOverridden,
+ isExplicitModule);
return Continue;
}
+void ChainedASTReaderListener::readModuleFileExtension(
+ const ModuleFileExtensionMetadata &Metadata) {
+ First->readModuleFileExtension(Metadata);
+ Second->readModuleFileExtension(Metadata);
+}
+
//===----------------------------------------------------------------------===//
// PCH validator implementation
//===----------------------------------------------------------------------===//
@@ -735,13 +746,26 @@ ASTIdentifierLookupTraitBase::ReadKey(const unsigned char* d, unsigned n) {
}
/// \brief Whether the given identifier is "interesting".
-static bool isInterestingIdentifier(IdentifierInfo &II) {
- return II.isPoisoned() ||
- II.isExtensionToken() ||
- II.getObjCOrBuiltinID() ||
+static bool isInterestingIdentifier(ASTReader &Reader, IdentifierInfo &II,
+ bool IsModule) {
+ return II.hadMacroDefinition() ||
+ II.isPoisoned() ||
+ (IsModule ? II.hasRevertedBuiltin() : II.getObjCOrBuiltinID()) ||
II.hasRevertedTokenIDToIdentifier() ||
- II.hadMacroDefinition() ||
- II.getFETokenInfo<void>();
+ (!(IsModule && Reader.getContext().getLangOpts().CPlusPlus) &&
+ II.getFETokenInfo<void>());
+}
+
+static bool readBit(unsigned &Bits) {
+ bool Value = Bits & 0x1;
+ Bits >>= 1;
+ return Value;
+}
+
+IdentID ASTIdentifierLookupTrait::ReadIdentifierID(const unsigned char *d) {
+ using namespace llvm::support;
+ unsigned RawID = endian::readNext<uint32_t, little, unaligned>(d);
+ return Reader.getGlobalIdentifierID(F, RawID >> 1);
}
IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
@@ -754,62 +778,52 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
// Wipe out the "is interesting" bit.
RawID = RawID >> 1;
+ // Build the IdentifierInfo and link the identifier ID with it.
+ IdentifierInfo *II = KnownII;
+ if (!II) {
+ II = &Reader.getIdentifierTable().getOwn(k);
+ KnownII = II;
+ }
+ if (!II->isFromAST()) {
+ II->setIsFromAST();
+ bool IsModule = Reader.PP.getCurrentModule() != nullptr;
+ if (isInterestingIdentifier(Reader, *II, IsModule))
+ II->setChangedSinceDeserialization();
+ }
+ Reader.markIdentifierUpToDate(II);
+
IdentID ID = Reader.getGlobalIdentifierID(F, RawID);
if (!IsInteresting) {
- // For uninteresting identifiers, just build the IdentifierInfo
- // and associate it with the persistent ID.
- IdentifierInfo *II = KnownII;
- if (!II) {
- II = &Reader.getIdentifierTable().getOwn(k);
- KnownII = II;
- }
+ // For uninteresting identifiers, there's nothing else to do. Just notify
+ // the reader that we've finished loading this identifier.
Reader.SetIdentifierInfo(ID, II);
- if (!II->isFromAST()) {
- bool WasInteresting = isInterestingIdentifier(*II);
- II->setIsFromAST();
- if (WasInteresting)
- II->setChangedSinceDeserialization();
- }
- Reader.markIdentifierUpToDate(II);
return II;
}
unsigned ObjCOrBuiltinID = endian::readNext<uint16_t, little, unaligned>(d);
unsigned Bits = endian::readNext<uint16_t, little, unaligned>(d);
- bool CPlusPlusOperatorKeyword = Bits & 0x01;
- Bits >>= 1;
- bool HasRevertedTokenIDToIdentifier = Bits & 0x01;
- Bits >>= 1;
- bool Poisoned = Bits & 0x01;
- Bits >>= 1;
- bool ExtensionToken = Bits & 0x01;
- Bits >>= 1;
- bool hadMacroDefinition = Bits & 0x01;
- Bits >>= 1;
+ bool CPlusPlusOperatorKeyword = readBit(Bits);
+ bool HasRevertedTokenIDToIdentifier = readBit(Bits);
+ bool HasRevertedBuiltin = readBit(Bits);
+ bool Poisoned = readBit(Bits);
+ bool ExtensionToken = readBit(Bits);
+ bool HadMacroDefinition = readBit(Bits);
assert(Bits == 0 && "Extra bits in the identifier?");
DataLen -= 8;
- // Build the IdentifierInfo itself and link the identifier ID with
- // the new IdentifierInfo.
- IdentifierInfo *II = KnownII;
- if (!II) {
- II = &Reader.getIdentifierTable().getOwn(StringRef(k));
- KnownII = II;
- }
- Reader.markIdentifierUpToDate(II);
- if (!II->isFromAST()) {
- bool WasInteresting = isInterestingIdentifier(*II);
- II->setIsFromAST();
- if (WasInteresting)
- II->setChangedSinceDeserialization();
- }
-
// Set or check the various bits in the IdentifierInfo structure.
// Token IDs are read-only.
if (HasRevertedTokenIDToIdentifier && II->getTokenID() != tok::identifier)
- II->RevertTokenIDToIdentifier();
- II->setObjCOrBuiltinID(ObjCOrBuiltinID);
+ II->revertTokenIDToIdentifier();
+ if (!F.isModule())
+ II->setObjCOrBuiltinID(ObjCOrBuiltinID);
+ else if (HasRevertedBuiltin && II->getBuiltinID()) {
+ II->revertBuiltin();
+ assert((II->hasRevertedBuiltin() ||
+ II->getObjCOrBuiltinID() == ObjCOrBuiltinID) &&
+ "Incorrect ObjC keyword or builtin ID");
+ }
assert(II->isExtensionToken() == ExtensionToken &&
"Incorrect extension token flag");
(void)ExtensionToken;
@@ -821,7 +835,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
// If this identifier is a macro, deserialize the macro
// definition.
- if (hadMacroDefinition) {
+ if (HadMacroDefinition) {
uint32_t MacroDirectivesOffset =
endian::readNext<uint32_t, little, unaligned>(d);
DataLen -= 4;
@@ -844,168 +858,187 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
return II;
}
-unsigned
-ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) {
- llvm::FoldingSetNodeID ID;
- ID.AddInteger(Key.Kind);
-
- switch (Key.Kind) {
+DeclarationNameKey::DeclarationNameKey(DeclarationName Name)
+ : Kind(Name.getNameKind()) {
+ switch (Kind) {
case DeclarationName::Identifier:
- case DeclarationName::CXXLiteralOperatorName:
- ID.AddString(((IdentifierInfo*)Key.Data)->getName());
+ Data = (uint64_t)Name.getAsIdentifierInfo();
break;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
- ID.AddInteger(serialization::ComputeHash(Selector(Key.Data)));
+ Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr();
break;
case DeclarationName::CXXOperatorName:
- ID.AddInteger((OverloadedOperatorKind)Key.Data);
+ Data = Name.getCXXOverloadedOperator();
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ Data = (uint64_t)Name.getCXXLiteralIdentifier();
break;
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXUsingDirective:
+ Data = 0;
break;
}
-
- return ID.ComputeHash();
}
-ASTDeclContextNameLookupTrait::internal_key_type
-ASTDeclContextNameLookupTrait::GetInternalKey(
- const external_key_type& Name) {
- DeclNameKey Key;
- Key.Kind = Name.getNameKind();
- switch (Name.getNameKind()) {
+unsigned DeclarationNameKey::getHash() const {
+ llvm::FoldingSetNodeID ID;
+ ID.AddInteger(Kind);
+
+ switch (Kind) {
case DeclarationName::Identifier:
- Key.Data = (uint64_t)Name.getAsIdentifierInfo();
+ case DeclarationName::CXXLiteralOperatorName:
+ ID.AddString(((IdentifierInfo*)Data)->getName());
break;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
- Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr();
+ ID.AddInteger(serialization::ComputeHash(Selector(Data)));
break;
case DeclarationName::CXXOperatorName:
- Key.Data = Name.getCXXOverloadedOperator();
- break;
- case DeclarationName::CXXLiteralOperatorName:
- Key.Data = (uint64_t)Name.getCXXLiteralIdentifier();
+ ID.AddInteger((OverloadedOperatorKind)Data);
break;
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXUsingDirective:
- Key.Data = 0;
break;
}
- return Key;
+ return ID.ComputeHash();
+}
+
+ModuleFile *
+ASTDeclContextNameLookupTrait::ReadFileRef(const unsigned char *&d) {
+ using namespace llvm::support;
+ uint32_t ModuleFileID = endian::readNext<uint32_t, little, unaligned>(d);
+ return Reader.getLocalModuleFile(F, ModuleFileID);
}
std::pair<unsigned, unsigned>
-ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
+ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char *&d) {
using namespace llvm::support;
unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d);
unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d);
return std::make_pair(KeyLen, DataLen);
}
-ASTDeclContextNameLookupTrait::internal_key_type
-ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) {
+ASTDeclContextNameLookupTrait::internal_key_type
+ASTDeclContextNameLookupTrait::ReadKey(const unsigned char *d, unsigned) {
using namespace llvm::support;
- DeclNameKey Key;
- Key.Kind = (DeclarationName::NameKind)*d++;
- switch (Key.Kind) {
+ auto Kind = (DeclarationName::NameKind)*d++;
+ uint64_t Data;
+ switch (Kind) {
case DeclarationName::Identifier:
- Key.Data = (uint64_t)Reader.getLocalIdentifier(
+ Data = (uint64_t)Reader.getLocalIdentifier(
F, endian::readNext<uint32_t, little, unaligned>(d));
break;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
- Key.Data =
+ Data =
(uint64_t)Reader.getLocalSelector(
F, endian::readNext<uint32_t, little, unaligned>(
d)).getAsOpaquePtr();
break;
case DeclarationName::CXXOperatorName:
- Key.Data = *d++; // OverloadedOperatorKind
+ Data = *d++; // OverloadedOperatorKind
break;
case DeclarationName::CXXLiteralOperatorName:
- Key.Data = (uint64_t)Reader.getLocalIdentifier(
+ Data = (uint64_t)Reader.getLocalIdentifier(
F, endian::readNext<uint32_t, little, unaligned>(d));
break;
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXUsingDirective:
- Key.Data = 0;
+ Data = 0;
break;
}
- return Key;
+ return DeclarationNameKey(Kind, Data);
}
-ASTDeclContextNameLookupTrait::data_type
-ASTDeclContextNameLookupTrait::ReadData(internal_key_type,
- const unsigned char* d,
- unsigned DataLen) {
+void ASTDeclContextNameLookupTrait::ReadDataInto(internal_key_type,
+ const unsigned char *d,
+ unsigned DataLen,
+ data_type_builder &Val) {
using namespace llvm::support;
- unsigned NumDecls = endian::readNext<uint16_t, little, unaligned>(d);
- LE32DeclID *Start = reinterpret_cast<LE32DeclID *>(
- const_cast<unsigned char *>(d));
- return std::make_pair(Start, Start + NumDecls);
+ for (unsigned NumDecls = DataLen / 4; NumDecls; --NumDecls) {
+ uint32_t LocalID = endian::readNext<uint32_t, little, unaligned>(d);
+ Val.insert(Reader.getGlobalDeclID(F, LocalID));
+ }
}
-bool ASTReader::ReadDeclContextStorage(ModuleFile &M,
- BitstreamCursor &Cursor,
- const std::pair<uint64_t, uint64_t> &Offsets,
- DeclContextInfo &Info) {
- SavedStreamPosition SavedPosition(Cursor);
- // First the lexical decls.
- if (Offsets.first != 0) {
- Cursor.JumpToBit(Offsets.first);
+bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M,
+ BitstreamCursor &Cursor,
+ uint64_t Offset,
+ DeclContext *DC) {
+ assert(Offset != 0);
- RecordData Record;
- StringRef Blob;
- unsigned Code = Cursor.ReadCode();
- unsigned RecCode = Cursor.readRecord(Code, Record, &Blob);
- if (RecCode != DECL_CONTEXT_LEXICAL) {
- Error("Expected lexical block");
- return true;
- }
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(Offset);
- Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair*>(Blob.data());
- Info.NumLexicalDecls = Blob.size() / sizeof(KindDeclIDPair);
+ RecordData Record;
+ StringRef Blob;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.readRecord(Code, Record, &Blob);
+ if (RecCode != DECL_CONTEXT_LEXICAL) {
+ Error("Expected lexical block");
+ return true;
}
- // Now the lookup table.
- if (Offsets.second != 0) {
- Cursor.JumpToBit(Offsets.second);
+ assert(!isa<TranslationUnitDecl>(DC) &&
+ "expected a TU_UPDATE_LEXICAL record for TU");
+ // If we are handling a C++ class template instantiation, we can see multiple
+ // lexical updates for the same record. It's important that we select only one
+ // of them, so that field numbering works properly. Just pick the first one we
+ // see.
+ auto &Lex = LexicalDecls[DC];
+ if (!Lex.first) {
+ Lex = std::make_pair(
+ &M, llvm::makeArrayRef(
+ reinterpret_cast<const llvm::support::unaligned_uint32_t *>(
+ Blob.data()),
+ Blob.size() / 4));
+ }
+ DC->setHasExternalLexicalStorage(true);
+ return false;
+}
+
+bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M,
+ BitstreamCursor &Cursor,
+ uint64_t Offset,
+ DeclID ID) {
+ assert(Offset != 0);
- RecordData Record;
- StringRef Blob;
- unsigned Code = Cursor.ReadCode();
- unsigned RecCode = Cursor.readRecord(Code, Record, &Blob);
- if (RecCode != DECL_CONTEXT_VISIBLE) {
- Error("Expected visible lookup table block");
- return true;
- }
- Info.NameLookupTableData = ASTDeclContextNameLookupTable::Create(
- (const unsigned char *)Blob.data() + Record[0],
- (const unsigned char *)Blob.data() + sizeof(uint32_t),
- (const unsigned char *)Blob.data(),
- ASTDeclContextNameLookupTrait(*this, M));
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(Offset);
+
+ RecordData Record;
+ StringRef Blob;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.readRecord(Code, Record, &Blob);
+ if (RecCode != DECL_CONTEXT_VISIBLE) {
+ Error("Expected visible lookup table block");
+ return true;
}
+ // We can't safely determine the primary context yet, so delay attaching the
+ // lookup table until we're done with recursive deserialization.
+ auto *Data = (const unsigned char*)Blob.data();
+ PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{&M, Data});
return false;
}
void ASTReader::Error(StringRef Msg) {
Error(diag::err_fe_pch_malformed, Msg);
- if (Context.getLangOpts().Modules && !Diags.isDiagnosticInFlight()) {
+ if (Context.getLangOpts().Modules && !Diags.isDiagnosticInFlight() &&
+ !PP.getHeaderSearchInfo().getModuleCachePath().empty()) {
Diag(diag::note_module_cache_path)
<< PP.getHeaderSearchInfo().getModuleCachePath();
}
@@ -1032,11 +1065,12 @@ bool ASTReader::ParseLineTable(ModuleFile &F,
// Parse the file names
std::map<int, int> FileIDs;
- for (int I = 0, N = Record[Idx++]; I != N; ++I) {
+ for (unsigned I = 0; Record[Idx]; ++I) {
// Extract the file name
auto Filename = ReadPath(F, Record, Idx);
FileIDs[I] = LineTable.getLineTableFilenameID(Filename);
}
+ ++Idx;
// Parse the line entries
std::vector<LineEntry> Entries;
@@ -1048,7 +1082,7 @@ bool ASTReader::ParseLineTable(ModuleFile &F,
// Extract the line entries
unsigned NumEntries = Record[Idx++];
- assert(NumEntries && "Numentries is 00000");
+ assert(NumEntries && "no line entries for file ID");
Entries.clear();
Entries.reserve(NumEntries);
for (unsigned I = 0; I != NumEntries; ++I) {
@@ -1225,7 +1259,8 @@ bool ASTReader::ReadSLocEntry(int ID) {
= SourceMgr.getOrCreateContentCache(File,
/*isSystemFile=*/FileCharacter != SrcMgr::C_User);
if (OverriddenBuffer && !ContentCache->BufferOverridden &&
- ContentCache->ContentsEntry == ContentCache->OrigEntry) {
+ ContentCache->ContentsEntry == ContentCache->OrigEntry &&
+ !ContentCache->getRawBuffer()) {
unsigned Code = SLocEntryCursor.ReadCode();
Record.clear();
unsigned RecCode = SLocEntryCursor.readRecord(Code, Record, &Blob);
@@ -1313,7 +1348,7 @@ SourceLocation ASTReader::getImportLocation(ModuleFile *F) {
// location of its includer.
if (F->ImportedBy.empty() || !F->ImportedBy[0]) {
// Main file is the importer.
- assert(!SourceMgr.getMainFileID().isInvalid() && "missing main file");
+ assert(SourceMgr.getMainFileID().isValid() && "missing main file");
return SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
}
return F->ImportedBy[0]->FirstLoc;
@@ -1323,10 +1358,8 @@ SourceLocation ASTReader::getImportLocation(ModuleFile *F) {
/// specified cursor. Read the abbreviations that are at the top of the block
/// and then leave the cursor pointing into the block.
bool ASTReader::ReadBlockAbbrevs(BitstreamCursor &Cursor, unsigned BlockID) {
- if (Cursor.EnterSubBlock(BlockID)) {
- Error("malformed block record in AST file");
- return Failure;
- }
+ if (Cursor.EnterSubBlock(BlockID))
+ return true;
while (true) {
uint64_t Offset = Cursor.GetCurrentBitNo();
@@ -1425,8 +1458,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
if (isC99VarArgs) MI->setIsC99Varargs();
if (isGNUVarArgs) MI->setIsGNUVarargs();
if (hasCommaPasting) MI->setHasCommaPasting();
- MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
- PP.getPreprocessorAllocator());
+ MI->setArgumentList(MacroArgs, PP.getPreprocessorAllocator());
}
// Remember that we saw this macro last so that we add the tokens that
@@ -1481,13 +1513,14 @@ unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) {
HeaderFileInfoTrait::internal_key_type
HeaderFileInfoTrait::GetInternalKey(const FileEntry *FE) {
- internal_key_type ikey = { FE->getSize(), FE->getModificationTime(),
- FE->getName(), /*Imported*/false };
+ internal_key_type ikey = {FE->getSize(),
+ M.HasTimestamps ? FE->getModificationTime() : 0,
+ FE->getName(), /*Imported*/ false};
return ikey;
}
bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) {
- if (a.Size != b.Size || a.ModTime != b.ModTime)
+ if (a.Size != b.Size || (a.ModTime && b.ModTime && a.ModTime != b.ModTime))
return false;
if (llvm::sys::path::is_absolute(a.Filename) &&
@@ -1536,14 +1569,15 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
using namespace llvm::support;
HeaderFileInfo HFI;
unsigned Flags = *d++;
- HFI.HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>
- ((Flags >> 6) & 0x03);
- HFI.isImport = (Flags >> 5) & 0x01;
- HFI.isPragmaOnce = (Flags >> 4) & 0x01;
- HFI.DirInfo = (Flags >> 2) & 0x03;
- HFI.Resolved = (Flags >> 1) & 0x01;
+ // FIXME: Refactor with mergeHeaderFileInfo in HeaderSearch.cpp.
+ HFI.isImport |= (Flags >> 4) & 0x01;
+ HFI.isPragmaOnce |= (Flags >> 3) & 0x01;
+ HFI.DirInfo = (Flags >> 1) & 0x03;
HFI.IndexHeaderMapHeader = Flags & 0x01;
- HFI.NumIncludes = endian::readNext<uint16_t, little, unaligned>(d);
+ // FIXME: Find a better way to handle this. Maybe just store a
+ // "has been included" flag?
+ HFI.NumIncludes = std::max(endian::readNext<uint16_t, little, unaligned>(d),
+ HFI.NumIncludes);
HFI.ControllingMacroID = Reader.getGlobalIdentifierID(
M, endian::readNext<uint32_t, little, unaligned>(d));
if (unsigned FrameworkOffset =
@@ -1553,34 +1587,36 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
}
-
- if (d != End) {
+
+ assert((End - d) % 4 == 0 &&
+ "Wrong data length in HeaderFileInfo deserialization");
+ while (d != End) {
uint32_t LocalSMID = endian::readNext<uint32_t, little, unaligned>(d);
- if (LocalSMID) {
- // This header is part of a module. Associate it with the module to enable
- // implicit module import.
- SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID);
- Module *Mod = Reader.getSubmodule(GlobalSMID);
- HFI.isModuleHeader = true;
- FileManager &FileMgr = Reader.getFileManager();
- ModuleMap &ModMap =
- Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap();
- // FIXME: This information should be propagated through the
- // SUBMODULE_HEADER etc records rather than from here.
- // FIXME: We don't ever mark excluded headers.
- std::string Filename = key.Filename;
- if (key.Imported)
- Reader.ResolveImportedPath(M, Filename);
- Module::Header H = { key.Filename, FileMgr.getFile(Filename) };
- ModMap.addHeader(Mod, H, HFI.getHeaderRole());
- }
- }
-
- assert(End == d && "Wrong data length in HeaderFileInfo deserialization");
- (void)End;
-
+ auto HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>(LocalSMID & 3);
+ LocalSMID >>= 2;
+
+ // This header is part of a module. Associate it with the module to enable
+ // implicit module import.
+ SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID);
+ Module *Mod = Reader.getSubmodule(GlobalSMID);
+ FileManager &FileMgr = Reader.getFileManager();
+ ModuleMap &ModMap =
+ Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap();
+
+ std::string Filename = key.Filename;
+ if (key.Imported)
+ Reader.ResolveImportedPath(M, Filename);
+ // FIXME: This is not always the right filename-as-written, but we're not
+ // going to use this information to rebuild the module, so it doesn't make
+ // a lot of difference.
+ Module::Header H = { key.Filename, FileMgr.getFile(Filename) };
+ ModMap.addHeader(Mod, H, HeaderRole, /*Imported*/true);
+ HFI.isModuleHeader |= !(HeaderRole & ModuleMap::TextualHeader);
+ }
+
// This HeaderFileInfo was externally loaded.
HFI.External = true;
+ HFI.IsValid = true;
return HFI;
}
@@ -1595,16 +1631,15 @@ void ASTReader::ReadDefinedMacros() {
// Note that we are loading defined macros.
Deserializing Macros(this);
- for (ModuleReverseIterator I = ModuleMgr.rbegin(),
- E = ModuleMgr.rend(); I != E; ++I) {
- BitstreamCursor &MacroCursor = (*I)->MacroCursor;
+ for (auto &I : llvm::reverse(ModuleMgr)) {
+ BitstreamCursor &MacroCursor = I->MacroCursor;
// If there was no preprocessor block, skip this file.
if (!MacroCursor.getBitStreamReader())
continue;
BitstreamCursor Cursor = MacroCursor;
- Cursor.JumpToBit((*I)->MacroStartOffset);
+ Cursor.JumpToBit(I->MacroStartOffset);
RecordData Record;
while (true) {
@@ -1626,7 +1661,7 @@ void ASTReader::ReadDefinedMacros() {
case PP_MACRO_OBJECT_LIKE:
case PP_MACRO_FUNCTION_LIKE:
- getLocalIdentifier(**I, Record[0]);
+ getLocalIdentifier(*I, Record[0]);
break;
case PP_TOKEN:
@@ -1661,33 +1696,30 @@ namespace {
Found()
{
}
-
- static bool visit(ModuleFile &M, void *UserData) {
- IdentifierLookupVisitor *This
- = static_cast<IdentifierLookupVisitor *>(UserData);
-
+
+ bool operator()(ModuleFile &M) {
// If we've already searched this module file, skip it now.
- if (M.Generation <= This->PriorGeneration)
+ if (M.Generation <= PriorGeneration)
return true;
ASTIdentifierLookupTable *IdTable
= (ASTIdentifierLookupTable *)M.IdentifierLookupTable;
if (!IdTable)
return false;
-
- ASTIdentifierLookupTrait Trait(IdTable->getInfoObj().getReader(),
- M, This->Found);
- ++This->NumIdentifierLookups;
+
+ ASTIdentifierLookupTrait Trait(IdTable->getInfoObj().getReader(), M,
+ Found);
+ ++NumIdentifierLookups;
ASTIdentifierLookupTable::iterator Pos =
- IdTable->find_hashed(This->Name, This->NameHash, &Trait);
+ IdTable->find_hashed(Name, NameHash, &Trait);
if (Pos == IdTable->end())
return false;
// Dereferencing the iterator has the effect of building the
// IdentifierInfo node and populating it with the various
// declarations it needs.
- ++This->NumIdentifierLookupHits;
- This->Found = *Pos;
+ ++NumIdentifierLookupHits;
+ Found = *Pos;
return true;
}
@@ -1718,7 +1750,7 @@ void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
IdentifierLookupVisitor Visitor(II.getName(), PriorGeneration,
NumIdentifierLookups,
NumIdentifierLookupHits);
- ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor, HitsPtr);
+ ModuleMgr.visit(Visitor, HitsPtr);
markIdentifierUpToDate(&II);
}
@@ -1859,26 +1891,17 @@ ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) {
"invalid record type for input file");
(void)Result;
- std::string Filename;
- off_t StoredSize;
- time_t StoredTime;
- bool Overridden;
-
assert(Record[0] == ID && "Bogus stored ID or offset");
- StoredSize = static_cast<off_t>(Record[1]);
- StoredTime = static_cast<time_t>(Record[2]);
- Overridden = static_cast<bool>(Record[3]);
- Filename = Blob;
- ResolveImportedPath(F, Filename);
-
- InputFileInfo R = { std::move(Filename), StoredSize, StoredTime, Overridden };
+ InputFileInfo R;
+ R.StoredSize = static_cast<off_t>(Record[1]);
+ R.StoredTime = static_cast<time_t>(Record[2]);
+ R.Overridden = static_cast<bool>(Record[3]);
+ R.Transient = static_cast<bool>(Record[4]);
+ R.Filename = Blob;
+ ResolveImportedPath(F, R.Filename);
return R;
}
-std::string ASTReader::getInputFileName(ModuleFile &F, unsigned int ID) {
- return readInputFileInfo(F, ID).Filename;
-}
-
InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// If this ID is bogus, just return an empty input file.
if (ID == 0 || ID > F.InputFilesLoaded.size())
@@ -1900,11 +1923,10 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
off_t StoredSize = FI.StoredSize;
time_t StoredTime = FI.StoredTime;
bool Overridden = FI.Overridden;
+ bool Transient = FI.Transient;
StringRef Filename = FI.Filename;
- const FileEntry *File
- = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime)
- : FileMgr.getFile(Filename, /*OpenFile=*/false);
+ const FileEntry *File = FileMgr.getFile(Filename, /*OpenFile=*/false);
// If we didn't find the file, resolve it relative to the
// original directory from which this AST file was created.
@@ -1919,15 +1941,16 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// For an overridden file, create a virtual file with the stored
// size/timestamp.
- if (Overridden && File == nullptr) {
+ if ((Overridden || Transient) && File == nullptr)
File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime);
- }
if (File == nullptr) {
if (Complain) {
std::string ErrorStr = "could not find file '";
ErrorStr += Filename;
- ErrorStr += "' referenced by AST file";
+ ErrorStr += "' referenced by AST file '";
+ ErrorStr += F.FileName;
+ ErrorStr += "'";
Error(ErrorStr.c_str());
}
// Record that we didn't find the file.
@@ -1940,11 +1963,17 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// can lead to problems when lexing using the source locations from the
// PCH.
SourceManager &SM = getSourceManager();
- if (!Overridden && SM.isFileOverridden(File)) {
+ // FIXME: Reject if the overrides are different.
+ if ((!Overridden && !Transient) && SM.isFileOverridden(File)) {
if (Complain)
Error(diag::err_fe_pch_file_overridden, Filename);
// After emitting the diagnostic, recover by disabling the override so
// that the original file will be used.
+ //
+ // FIXME: This recovery is just as broken as the original state; there may
+ // be another precompiled module that's using the overridden contents, or
+ // we might be half way through parsing it. Instead, we should treat the
+ // overridden contents as belonging to a separate FileEntry.
SM.disableFileContentsOverride(File);
// The FileEntry is a virtual file entry with the size of the contents
// that would override the original contents. Set it to the original's
@@ -1965,14 +1994,9 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// have inconsistent modification times that sometimes
// erroneously trigger this error-handling path.
//
- // This also happens in networked file systems, so disable this
- // check if validation is disabled or if we have an explicitly
- // built PCM file.
- //
- // FIXME: Should we also do this for PCH files? They could also
- // reasonably get shared across a network during a distributed build.
- (StoredTime != File->getModificationTime() && !DisableValidation &&
- F.Kind != MK_ExplicitModule)
+ // FIXME: This probably also breaks HeaderFileInfo lookups on Windows.
+ (StoredTime && StoredTime != File->getModificationTime() &&
+ !DisableValidation)
#endif
)) {
if (Complain) {
@@ -2000,8 +2024,10 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
IsOutOfDate = true;
}
+ // FIXME: If the file is overridden and we've already opened it,
+ // issue an error (or split it into a separate FileEntry).
- InputFile IF = InputFile(File, Overridden, IsOutOfDate);
+ InputFile IF = InputFile(File, Overridden || Transient, IsOutOfDate);
// Note that we've loaded this input file.
F.InputFilesLoaded[ID-1] = IF;
@@ -2026,24 +2052,114 @@ void ASTReader::ResolveImportedPath(std::string &Filename, StringRef Prefix) {
Filename.assign(Buffer.begin(), Buffer.end());
}
+static bool isDiagnosedResult(ASTReader::ASTReadResult ARR, unsigned Caps) {
+ switch (ARR) {
+ case ASTReader::Failure: return true;
+ case ASTReader::Missing: return !(Caps & ASTReader::ARR_Missing);
+ case ASTReader::OutOfDate: return !(Caps & ASTReader::ARR_OutOfDate);
+ case ASTReader::VersionMismatch: return !(Caps & ASTReader::ARR_VersionMismatch);
+ case ASTReader::ConfigurationMismatch:
+ return !(Caps & ASTReader::ARR_ConfigurationMismatch);
+ case ASTReader::HadErrors: return true;
+ case ASTReader::Success: return false;
+ }
+
+ llvm_unreachable("unknown ASTReadResult");
+}
+
+ASTReader::ASTReadResult ASTReader::ReadOptionsBlock(
+ BitstreamCursor &Stream, unsigned ClientLoadCapabilities,
+ bool AllowCompatibleConfigurationMismatch, ASTReaderListener &Listener,
+ std::string &SuggestedPredefines) {
+ if (Stream.EnterSubBlock(OPTIONS_BLOCK_ID))
+ return Failure;
+
+ // Read all of the records in the options block.
+ RecordData Record;
+ ASTReadResult Result = Success;
+ while (1) {
+ llvm::BitstreamEntry Entry = Stream.advance();
+
+ switch (Entry.Kind) {
+ case llvm::BitstreamEntry::Error:
+ case llvm::BitstreamEntry::SubBlock:
+ return Failure;
+
+ case llvm::BitstreamEntry::EndBlock:
+ return Result;
+
+ case llvm::BitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read and process a record.
+ Record.clear();
+ switch ((OptionsRecordTypes)Stream.readRecord(Entry.ID, Record)) {
+ case LANGUAGE_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
+ if (ParseLanguageOptions(Record, Complain, Listener,
+ AllowCompatibleConfigurationMismatch))
+ Result = ConfigurationMismatch;
+ break;
+ }
+
+ case TARGET_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
+ if (ParseTargetOptions(Record, Complain, Listener,
+ AllowCompatibleConfigurationMismatch))
+ Result = ConfigurationMismatch;
+ break;
+ }
+
+ case DIAGNOSTIC_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
+ if (!AllowCompatibleConfigurationMismatch &&
+ ParseDiagnosticOptions(Record, Complain, Listener))
+ return OutOfDate;
+ break;
+ }
+
+ case FILE_SYSTEM_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
+ if (!AllowCompatibleConfigurationMismatch &&
+ ParseFileSystemOptions(Record, Complain, Listener))
+ Result = ConfigurationMismatch;
+ break;
+ }
+
+ case HEADER_SEARCH_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
+ if (!AllowCompatibleConfigurationMismatch &&
+ ParseHeaderSearchOptions(Record, Complain, Listener))
+ Result = ConfigurationMismatch;
+ break;
+ }
+
+ case PREPROCESSOR_OPTIONS:
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
+ if (!AllowCompatibleConfigurationMismatch &&
+ ParsePreprocessorOptions(Record, Complain, Listener,
+ SuggestedPredefines))
+ Result = ConfigurationMismatch;
+ break;
+ }
+ }
+}
+
ASTReader::ASTReadResult
ASTReader::ReadControlBlock(ModuleFile &F,
SmallVectorImpl<ImportedModule> &Loaded,
const ModuleFile *ImportedBy,
unsigned ClientLoadCapabilities) {
BitstreamCursor &Stream = F.Stream;
+ ASTReadResult Result = Success;
if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
Error("malformed block record in AST file");
return Failure;
}
- // Should we allow the configuration of the module file to differ from the
- // configuration of the current translation unit in a compatible way?
- //
- // FIXME: Allow this for files explicitly specified with -include-pch too.
- bool AllowCompatibleConfigurationMismatch = F.Kind == MK_ExplicitModule;
-
// Read all of the records and blocks in the control block.
RecordData Record;
unsigned NumInputs = 0;
@@ -2061,8 +2177,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
PP.getHeaderSearchInfo().getHeaderSearchOpts();
// All user input files reside at the index range [0, NumUserInputs), and
- // system input files reside at [NumUserInputs, NumInputs).
- if (!DisableValidation) {
+ // system input files reside at [NumUserInputs, NumInputs). For explicitly
+ // loaded module files, ignore missing inputs.
+ if (!DisableValidation && F.Kind != MK_ExplicitModule) {
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
// If we are reading a module, we will create a verification timestamp,
@@ -2084,7 +2201,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
}
if (Listener)
- Listener->visitModuleFile(F.FileName);
+ Listener->visitModuleFile(F.FileName, F.Kind);
if (Listener && Listener->needsInputFileVisitation()) {
unsigned N = Listener->needsSystemInputFileVisitation() ? NumInputs
@@ -2092,11 +2209,12 @@ ASTReader::ReadControlBlock(ModuleFile &F,
for (unsigned I = 0; I < N; ++I) {
bool IsSystem = I >= NumUserInputs;
InputFileInfo FI = readInputFileInfo(F, I+1);
- Listener->visitInputFile(FI.Filename, IsSystem, FI.Overridden);
+ Listener->visitInputFile(FI.Filename, IsSystem, FI.Overridden,
+ F.Kind == MK_ExplicitModule);
}
}
- return Success;
+ return Result;
}
case llvm::BitstreamEntry::SubBlock:
@@ -2110,6 +2228,41 @@ ASTReader::ReadControlBlock(ModuleFile &F,
return Failure;
}
continue;
+
+ case OPTIONS_BLOCK_ID:
+ // If we're reading the first module for this group, check its options
+ // are compatible with ours. For modules it imports, no further checking
+ // is required, because we checked them when we built it.
+ if (Listener && !ImportedBy) {
+ // Should we allow the configuration of the module file to differ from
+ // the configuration of the current translation unit in a compatible
+ // way?
+ //
+ // FIXME: Allow this for files explicitly specified with -include-pch.
+ bool AllowCompatibleConfigurationMismatch =
+ F.Kind == MK_ExplicitModule;
+
+ Result = ReadOptionsBlock(Stream, ClientLoadCapabilities,
+ AllowCompatibleConfigurationMismatch,
+ *Listener, SuggestedPredefines);
+ if (Result == Failure) {
+ Error("malformed block record in AST file");
+ return Result;
+ }
+
+ if (DisableValidation ||
+ (AllowConfigurationMismatch && Result == ConfigurationMismatch))
+ Result = Success;
+
+ // If we've diagnosed a problem, we're done.
+ if (Result != Success &&
+ isDiagnosedResult(Result, ClientLoadCapabilities))
+ return Result;
+ } else if (Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+ continue;
default:
if (Stream.SkipBlock()) {
@@ -2136,7 +2289,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
return VersionMismatch;
}
- bool hasErrors = Record[5];
+ bool hasErrors = Record[6];
if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
Diag(diag::err_pch_with_compiler_errors);
return HadErrors;
@@ -2147,6 +2300,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
if (F.RelocatablePCH)
F.BaseDirectory = isysroot.empty() ? "/" : isysroot;
+ F.HasTimestamps = Record[5];
+
const std::string &CurBranch = getClangFullRepositoryVersion();
StringRef ASTBranch = Blob;
if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
@@ -2178,10 +2333,23 @@ ASTReader::ReadControlBlock(ModuleFile &F,
ASTFileSignature StoredSignature = Record[Idx++];
auto ImportedFile = ReadPath(F, Record, Idx);
+ // If our client can't cope with us being out of date, we can't cope with
+ // our dependency being missing.
+ unsigned Capabilities = ClientLoadCapabilities;
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Capabilities &= ~ARR_Missing;
+
// Load the AST file.
- switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded,
- StoredSize, StoredModTime, StoredSignature,
- ClientLoadCapabilities)) {
+ auto Result = ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F,
+ Loaded, StoredSize, StoredModTime,
+ StoredSignature, Capabilities);
+
+ // If we diagnosed a problem, produce a backtrace.
+ if (isDiagnosedResult(Result, Capabilities))
+ Diag(diag::note_module_file_imported_by)
+ << F.FileName << !F.ModuleName.empty() << F.ModuleName;
+
+ switch (Result) {
case Failure: return Failure;
// If we have to ignore the dependency, we'll have to ignore this too.
case Missing:
@@ -2195,71 +2363,6 @@ ASTReader::ReadControlBlock(ModuleFile &F,
break;
}
- case KNOWN_MODULE_FILES:
- break;
-
- case LANGUAGE_OPTIONS: {
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
- // FIXME: The &F == *ModuleMgr.begin() check is wrong for modules.
- if (Listener && &F == *ModuleMgr.begin() &&
- ParseLanguageOptions(Record, Complain, *Listener,
- AllowCompatibleConfigurationMismatch) &&
- !DisableValidation && !AllowConfigurationMismatch)
- return ConfigurationMismatch;
- break;
- }
-
- case TARGET_OPTIONS: {
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
- if (Listener && &F == *ModuleMgr.begin() &&
- ParseTargetOptions(Record, Complain, *Listener,
- AllowCompatibleConfigurationMismatch) &&
- !DisableValidation && !AllowConfigurationMismatch)
- return ConfigurationMismatch;
- break;
- }
-
- case DIAGNOSTIC_OPTIONS: {
- bool Complain = (ClientLoadCapabilities & ARR_OutOfDate)==0;
- if (Listener && &F == *ModuleMgr.begin() &&
- !AllowCompatibleConfigurationMismatch &&
- ParseDiagnosticOptions(Record, Complain, *Listener) &&
- !DisableValidation)
- return OutOfDate;
- break;
- }
-
- case FILE_SYSTEM_OPTIONS: {
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
- if (Listener && &F == *ModuleMgr.begin() &&
- !AllowCompatibleConfigurationMismatch &&
- ParseFileSystemOptions(Record, Complain, *Listener) &&
- !DisableValidation && !AllowConfigurationMismatch)
- return ConfigurationMismatch;
- break;
- }
-
- case HEADER_SEARCH_OPTIONS: {
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
- if (Listener && &F == *ModuleMgr.begin() &&
- !AllowCompatibleConfigurationMismatch &&
- ParseHeaderSearchOptions(Record, Complain, *Listener) &&
- !DisableValidation && !AllowConfigurationMismatch)
- return ConfigurationMismatch;
- break;
- }
-
- case PREPROCESSOR_OPTIONS: {
- bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
- if (Listener && &F == *ModuleMgr.begin() &&
- !AllowCompatibleConfigurationMismatch &&
- ParsePreprocessorOptions(Record, Complain, *Listener,
- SuggestedPredefines) &&
- !DisableValidation && !AllowConfigurationMismatch)
- return ConfigurationMismatch;
- break;
- }
-
case ORIGINAL_FILE:
F.OriginalSourceFileID = FileID::get(Record[0]);
F.ActualOriginalSourceFileName = Blob;
@@ -2499,10 +2602,11 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case TU_UPDATE_LEXICAL: {
DeclContext *TU = Context.getTranslationUnitDecl();
- DeclContextInfo &Info = F.DeclContextInfos[TU];
- Info.LexicalDecls = reinterpret_cast<const KindDeclIDPair *>(Blob.data());
- Info.NumLexicalDecls
- = static_cast<unsigned int>(Blob.size() / sizeof(KindDeclIDPair));
+ LexicalContents Contents(
+ reinterpret_cast<const llvm::support::unaligned_uint32_t *>(
+ Blob.data()),
+ static_cast<unsigned int>(Blob.size() / 4));
+ TULexicalDecls.push_back(std::make_pair(&F, Contents));
TU->setHasExternalLexicalStorage(true);
break;
}
@@ -2510,20 +2614,12 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case UPDATE_VISIBLE: {
unsigned Idx = 0;
serialization::DeclID ID = ReadDeclID(F, Record, Idx);
- ASTDeclContextNameLookupTable *Table =
- ASTDeclContextNameLookupTable::Create(
- (const unsigned char *)Blob.data() + Record[Idx++],
- (const unsigned char *)Blob.data() + sizeof(uint32_t),
- (const unsigned char *)Blob.data(),
- ASTDeclContextNameLookupTrait(*this, F));
- if (Decl *D = GetExistingDecl(ID)) {
- auto *DC = cast<DeclContext>(D);
- DC->getPrimaryContext()->setHasExternalVisibleStorage(true);
- auto *&LookupTable = F.DeclContextInfos[DC].NameLookupTableData;
- delete LookupTable;
- LookupTable = Table;
- } else
- PendingVisibleUpdates[ID].push_back(std::make_pair(Table, &F));
+ auto *Data = (const unsigned char*)Blob.data();
+ PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{&F, Data});
+ // If we've already loaded the decl, perform the updates when we finish
+ // loading this block.
+ if (Decl *D = GetExistingDecl(ID))
+ PendingUpdateRecords.push_back(std::make_pair(ID, D));
break;
}
@@ -2568,6 +2664,10 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
+ case INTERESTING_IDENTIFIERS:
+ F.PreloadIdentifierOffsets.assign(Record.begin(), Record.end());
+ break;
+
case EAGERLY_DESERIALIZED_DECLS:
// FIXME: Skip reading this record if our ASTConsumer doesn't care
// about "interesting" decls (for instance, if we're building a module).
@@ -2696,6 +2796,10 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
std::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) =
SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries,
SLocSpaceSize);
+ if (!F.SLocEntryBaseID) {
+ Error("ran out of source locations");
+ break;
+ }
// Make our entry in the range map. BaseID is negative and growing, so
// we invert it. Because we invert it, though, we need the other end of
// the range.
@@ -2744,7 +2848,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
RemapBuilder DeclRemap(F.DeclRemap);
RemapBuilder TypeRemap(F.TypeRemap);
- while(Data < DataEnd) {
+ while (Data < DataEnd) {
using namespace llvm::support;
uint16_t Len = endian::readNext<uint16_t, little, unaligned>(Data);
StringRef Name = StringRef((const char*)Data, Len);
@@ -3060,22 +3164,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
- case LOCAL_REDECLARATIONS: {
- F.RedeclarationChains.swap(Record);
- break;
- }
-
- case LOCAL_REDECLARATIONS_MAP: {
- if (F.LocalNumRedeclarationsInMap != 0) {
- Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file");
- return Failure;
- }
-
- F.LocalNumRedeclarationsInMap = Record[0];
- F.RedeclarationsMap = (const LocalRedeclarationsInfo *)Blob.data();
- break;
- }
-
case MACRO_OFFSET: {
if (F.LocalNumMacros != 0) {
Error("duplicate MACRO_OFFSET record in AST file");
@@ -3150,11 +3238,18 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr;
if (!ModMap) {
assert(ImportedBy && "top-level import should be verified");
- if ((ClientLoadCapabilities & ARR_Missing) == 0)
- Diag(diag::err_imported_module_not_found) << F.ModuleName << F.FileName
- << ImportedBy->FileName
- << F.ModuleMapPath;
- return Missing;
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) {
+ if (auto *ASTFE = M ? M->getASTFile() : nullptr)
+ // This module was defined by an imported (explicit) module.
+ Diag(diag::err_module_file_conflict) << F.ModuleName << F.FileName
+ << ASTFE->getName();
+ else
+ // This module was built with a different module map.
+ Diag(diag::err_imported_module_not_found)
+ << F.ModuleName << F.FileName << ImportedBy->FileName
+ << F.ModuleMapPath;
+ }
+ return OutOfDate;
}
assert(M->Name == F.ModuleName && "found module with different name");
@@ -3342,6 +3437,36 @@ static void updateModuleTimestamp(ModuleFile &MF) {
OS << "Timestamp file\n";
}
+/// \brief Given a cursor at the start of an AST file, scan ahead and drop the
+/// cursor into the start of the given block ID, returning false on success and
+/// true on failure.
+static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) {
+ while (1) {
+ llvm::BitstreamEntry Entry = Cursor.advance();
+ switch (Entry.Kind) {
+ case llvm::BitstreamEntry::Error:
+ case llvm::BitstreamEntry::EndBlock:
+ return true;
+
+ case llvm::BitstreamEntry::Record:
+ // Ignore top-level records.
+ Cursor.skipRecord(Entry.ID);
+ break;
+
+ case llvm::BitstreamEntry::SubBlock:
+ if (Entry.ID == BlockID) {
+ if (Cursor.EnterSubBlock(BlockID))
+ return true;
+ // Found it!
+ return false;
+ }
+
+ if (Cursor.SkipBlock())
+ return true;
+ }
+ }
+}
+
ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
ModuleKind Type,
SourceLocation ImportLoc,
@@ -3399,6 +3524,12 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
if (ASTReadResult Result = ReadASTBlock(F, ClientLoadCapabilities))
return Result;
+ // Read the extension blocks.
+ while (!SkipCursorToBlock(F.Stream, EXTENSION_BLOCK_ID)) {
+ if (ASTReadResult Result = ReadExtensionBlock(F))
+ return Result;
+ }
+
// Once read, set the ModuleFile bit base offset and update the size in
// bits of all files we've seen.
F.GlobalBitOffset = TotalModulesSizeInBits;
@@ -3414,6 +3545,32 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
// SourceManager.
SourceMgr.getLoadedSLocEntryByID(Index);
}
+
+ // Preload all the pending interesting identifiers by marking them out of
+ // date.
+ for (auto Offset : F.PreloadIdentifierOffsets) {
+ const unsigned char *Data = reinterpret_cast<const unsigned char *>(
+ F.IdentifierTableData + Offset);
+
+ ASTIdentifierLookupTrait Trait(*this, F);
+ auto KeyDataLen = Trait.ReadKeyDataLength(Data);
+ auto Key = Trait.ReadKey(Data, KeyDataLen.first);
+ auto &II = PP.getIdentifierTable().getOwn(Key);
+ II.setOutOfDate(true);
+
+ // Mark this identifier as being from an AST file so that we can track
+ // whether we need to serialize it.
+ if (!II.isFromAST()) {
+ II.setIsFromAST();
+ bool IsModule = PP.getCurrentModule() != nullptr;
+ if (isInterestingIdentifier(*this, II, IsModule))
+ II.setChangedSinceDeserialization();
+ }
+
+ // Associate the ID with the identifier so that the writer can reuse it.
+ auto ID = Trait.ReadIdentifierID(Data + KeyDataLen.first);
+ SetIdentifierInfo(ID, &II);
+ }
}
// Setup the import locations and notify the module manager that we've
@@ -3434,13 +3591,20 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
M->ImportLoc.getRawEncoding());
}
- // Mark all of the identifiers in the identifier table as being out of date,
- // so that various accessors know to check the loaded modules when the
- // identifier is used.
- for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
- IdEnd = PP.getIdentifierTable().end();
- Id != IdEnd; ++Id)
- Id->second->setOutOfDate(true);
+ if (!Context.getLangOpts().CPlusPlus ||
+ (Type != MK_ImplicitModule && Type != MK_ExplicitModule)) {
+ // Mark all of the identifiers in the identifier table as being out of date,
+ // so that various accessors know to check the loaded modules when the
+ // identifier is used.
+ //
+ // For C++ modules, we don't need information on many identifiers (just
+ // those that provide macros or are poisoned), so we mark all of
+ // the interesting ones via PreloadIdentifierOffsets.
+ for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
+ IdEnd = PP.getIdentifierTable().end();
+ Id != IdEnd; ++Id)
+ Id->second->setOutOfDate(true);
+ }
// Resolve any unresolved module exports.
for (unsigned I = 0, N = UnresolvedModuleRefs.size(); I != N; ++I) {
@@ -3485,7 +3649,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
DeserializationListener->ReaderInitialized(this);
ModuleFile &PrimaryModule = ModuleMgr.getPrimaryModule();
- if (!PrimaryModule.OriginalSourceFileID.isInvalid()) {
+ if (PrimaryModule.OriginalSourceFileID.isValid()) {
PrimaryModule.OriginalSourceFileID
= FileID::get(PrimaryModule.SLocEntryBaseID
+ PrimaryModule.OriginalSourceFileID.getOpaqueValue() - 1);
@@ -3536,6 +3700,20 @@ static bool startsWithASTFileMagic(BitstreamCursor &Stream) {
Stream.Read(8) == 'H';
}
+static unsigned moduleKindForDiagnostic(ModuleKind Kind) {
+ switch (Kind) {
+ case MK_PCH:
+ return 0; // PCH
+ case MK_ImplicitModule:
+ case MK_ExplicitModule:
+ return 1; // module
+ case MK_MainFile:
+ case MK_Preamble:
+ return 2; // main source file
+ }
+ llvm_unreachable("unknown module kind");
+}
+
ASTReader::ASTReadResult
ASTReader::ReadASTCore(StringRef FileName,
ModuleKind Type,
@@ -3568,11 +3746,9 @@ ASTReader::ReadASTCore(StringRef FileName,
return Missing;
// Otherwise, return an error.
- {
- std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
- + ErrorStr;
- Error(Msg);
- }
+ Diag(diag::err_module_file_not_found) << moduleKindForDiagnostic(Type)
+ << FileName << ErrorStr.empty()
+ << ErrorStr;
return Failure;
case ModuleManager::OutOfDate:
@@ -3582,11 +3758,9 @@ ASTReader::ReadASTCore(StringRef FileName,
return OutOfDate;
// Otherwise, return an error.
- {
- std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
- + ErrorStr;
- Error(Msg);
- }
+ Diag(diag::err_module_file_out_of_date) << moduleKindForDiagnostic(Type)
+ << FileName << ErrorStr.empty()
+ << ErrorStr;
return Failure;
}
@@ -3607,20 +3781,20 @@ ASTReader::ReadASTCore(StringRef FileName,
// Sniff for the signature.
if (!startsWithASTFileMagic(Stream)) {
- Diag(diag::err_not_a_pch_file) << FileName;
+ Diag(diag::err_module_file_invalid) << moduleKindForDiagnostic(Type)
+ << FileName;
return Failure;
}
// This is used for compatibility with older PCH formats.
bool HaveReadControlBlock = false;
-
while (1) {
llvm::BitstreamEntry Entry = Stream.advance();
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
- case llvm::BitstreamEntry::EndBlock:
case llvm::BitstreamEntry::Record:
+ case llvm::BitstreamEntry::EndBlock:
Error("invalid record at top-level of AST file");
return Failure;
@@ -3628,18 +3802,23 @@ ASTReader::ReadASTCore(StringRef FileName,
break;
}
- // We only know the control subblock ID.
switch (Entry.ID) {
- case llvm::bitc::BLOCKINFO_BLOCK_ID:
- if (Stream.ReadBlockInfoBlock()) {
- Error("malformed BlockInfoBlock in AST file");
- return Failure;
- }
- break;
case CONTROL_BLOCK_ID:
HaveReadControlBlock = true;
switch (ReadControlBlock(F, Loaded, ImportedBy, ClientLoadCapabilities)) {
case Success:
+ // Check that we didn't try to load a non-module AST file as a module.
+ //
+ // FIXME: Should we also perform the converse check? Loading a module as
+ // a PCH file sort of works, but it's a bit wonky.
+ if ((Type == MK_ImplicitModule || Type == MK_ExplicitModule) &&
+ F.ModuleName.empty()) {
+ auto Result = (Type == MK_ImplicitModule) ? OutOfDate : Failure;
+ if (Result != OutOfDate ||
+ (ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Diag(diag::err_module_file_not_module) << FileName;
+ return Result;
+ }
break;
case Failure: return Failure;
@@ -3650,6 +3829,7 @@ ASTReader::ReadASTCore(StringRef FileName,
case HadErrors: return HadErrors;
}
break;
+
case AST_BLOCK_ID:
if (!HaveReadControlBlock) {
if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
@@ -3669,7 +3849,78 @@ ASTReader::ReadASTCore(StringRef FileName,
break;
}
}
-
+
+ return Success;
+}
+
+/// Parse a record and blob containing module file extension metadata.
+static bool parseModuleFileExtensionMetadata(
+ const SmallVectorImpl<uint64_t> &Record,
+ StringRef Blob,
+ ModuleFileExtensionMetadata &Metadata) {
+ if (Record.size() < 4) return true;
+
+ Metadata.MajorVersion = Record[0];
+ Metadata.MinorVersion = Record[1];
+
+ unsigned BlockNameLen = Record[2];
+ unsigned UserInfoLen = Record[3];
+
+ if (BlockNameLen + UserInfoLen > Blob.size()) return true;
+
+ Metadata.BlockName = std::string(Blob.data(), Blob.data() + BlockNameLen);
+ Metadata.UserInfo = std::string(Blob.data() + BlockNameLen,
+ Blob.data() + BlockNameLen + UserInfoLen);
+ return false;
+}
+
+ASTReader::ASTReadResult ASTReader::ReadExtensionBlock(ModuleFile &F) {
+ BitstreamCursor &Stream = F.Stream;
+
+ RecordData Record;
+ while (true) {
+ llvm::BitstreamEntry Entry = Stream.advance();
+ switch (Entry.Kind) {
+ case llvm::BitstreamEntry::SubBlock:
+ if (Stream.SkipBlock())
+ return Failure;
+
+ continue;
+
+ case llvm::BitstreamEntry::EndBlock:
+ return Success;
+
+ case llvm::BitstreamEntry::Error:
+ return HadErrors;
+
+ case llvm::BitstreamEntry::Record:
+ break;
+ }
+
+ Record.clear();
+ StringRef Blob;
+ unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
+ switch (RecCode) {
+ case EXTENSION_METADATA: {
+ ModuleFileExtensionMetadata Metadata;
+ if (parseModuleFileExtensionMetadata(Record, Blob, Metadata))
+ return Failure;
+
+ // Find a module file extension with this block name.
+ auto Known = ModuleFileExtensions.find(Metadata.BlockName);
+ if (Known == ModuleFileExtensions.end()) break;
+
+ // Form a reader.
+ if (auto Reader = Known->second->createExtensionReader(Metadata, *this,
+ F, Stream)) {
+ F.ExtensionReaders.push_back(std::move(Reader));
+ }
+
+ break;
+ }
+ }
+ }
+
return Success;
}
@@ -3811,36 +4062,6 @@ void ASTReader::finalizeForWriting() {
// Nothing to do for now.
}
-/// \brief Given a cursor at the start of an AST file, scan ahead and drop the
-/// cursor into the start of the given block ID, returning false on success and
-/// true on failure.
-static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) {
- while (1) {
- llvm::BitstreamEntry Entry = Cursor.advance();
- switch (Entry.Kind) {
- case llvm::BitstreamEntry::Error:
- case llvm::BitstreamEntry::EndBlock:
- return true;
-
- case llvm::BitstreamEntry::Record:
- // Ignore top-level records.
- Cursor.skipRecord(Entry.ID);
- break;
-
- case llvm::BitstreamEntry::SubBlock:
- if (Entry.ID == BlockID) {
- if (Cursor.EnterSubBlock(BlockID))
- return true;
- // Found it!
- return false;
- }
-
- if (Cursor.SkipBlock())
- return true;
- }
- }
-}
-
/// \brief Reads and return the signature record from \p StreamFile's control
/// block, or else returns 0.
static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){
@@ -3968,6 +4189,7 @@ namespace {
bool ASTReader::readASTFileControlBlock(
StringRef Filename, FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr,
+ bool FindModuleFileExtensions,
ASTReaderListener &Listener) {
// Open the AST file.
// FIXME: This allows use of the VFS; we do not allow use of the
@@ -3994,36 +4216,55 @@ bool ASTReader::readASTFileControlBlock(
bool NeedsSystemInputFiles = Listener.needsSystemInputFileVisitation();
bool NeedsImports = Listener.needsImportVisitation();
BitstreamCursor InputFilesCursor;
- if (NeedsInputFiles) {
- InputFilesCursor = Stream;
- if (SkipCursorToBlock(InputFilesCursor, INPUT_FILES_BLOCK_ID))
- return true;
- // Read the abbreviations
- while (true) {
- uint64_t Offset = InputFilesCursor.GetCurrentBitNo();
- unsigned Code = InputFilesCursor.ReadCode();
+ RecordData Record;
+ std::string ModuleDir;
+ bool DoneWithControlBlock = false;
+ while (!DoneWithControlBlock) {
+ llvm::BitstreamEntry Entry = Stream.advance();
- // We expect all abbrevs to be at the start of the block.
- if (Code != llvm::bitc::DEFINE_ABBREV) {
- InputFilesCursor.JumpToBit(Offset);
+ switch (Entry.Kind) {
+ case llvm::BitstreamEntry::SubBlock: {
+ switch (Entry.ID) {
+ case OPTIONS_BLOCK_ID: {
+ std::string IgnoredSuggestedPredefines;
+ if (ReadOptionsBlock(Stream, ARR_ConfigurationMismatch | ARR_OutOfDate,
+ /*AllowCompatibleConfigurationMismatch*/ false,
+ Listener, IgnoredSuggestedPredefines) != Success)
+ return true;
break;
}
- InputFilesCursor.ReadAbbrevRecord();
+
+ case INPUT_FILES_BLOCK_ID:
+ InputFilesCursor = Stream;
+ if (Stream.SkipBlock() ||
+ (NeedsInputFiles &&
+ ReadBlockAbbrevs(InputFilesCursor, INPUT_FILES_BLOCK_ID)))
+ return true;
+ break;
+
+ default:
+ if (Stream.SkipBlock())
+ return true;
+ break;
+ }
+
+ continue;
}
- }
-
- // Scan for ORIGINAL_FILE inside the control block.
- RecordData Record;
- std::string ModuleDir;
- while (1) {
- llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
- if (Entry.Kind == llvm::BitstreamEntry::EndBlock)
- return false;
-
- if (Entry.Kind != llvm::BitstreamEntry::Record)
+
+ case llvm::BitstreamEntry::EndBlock:
+ DoneWithControlBlock = true;
+ break;
+
+ case llvm::BitstreamEntry::Error:
return true;
-
+
+ case llvm::BitstreamEntry::Record:
+ break;
+ }
+
+ if (DoneWithControlBlock) break;
+
Record.clear();
StringRef Blob;
unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
@@ -4050,41 +4291,6 @@ bool ASTReader::readASTFileControlBlock(
Listener.ReadModuleMapFile(Path);
break;
}
- case LANGUAGE_OPTIONS:
- if (ParseLanguageOptions(Record, false, Listener,
- /*AllowCompatibleConfigurationMismatch*/false))
- return true;
- break;
-
- case TARGET_OPTIONS:
- if (ParseTargetOptions(Record, false, Listener,
- /*AllowCompatibleConfigurationMismatch*/ false))
- return true;
- break;
-
- case DIAGNOSTIC_OPTIONS:
- if (ParseDiagnosticOptions(Record, false, Listener))
- return true;
- break;
-
- case FILE_SYSTEM_OPTIONS:
- if (ParseFileSystemOptions(Record, false, Listener))
- return true;
- break;
-
- case HEADER_SEARCH_OPTIONS:
- if (ParseHeaderSearchOptions(Record, false, Listener))
- return true;
- break;
-
- case PREPROCESSOR_OPTIONS: {
- std::string IgnoredSuggestedPredefines;
- if (ParsePreprocessorOptions(Record, false, Listener,
- IgnoredSuggestedPredefines))
- return true;
- break;
- }
-
case INPUT_FILE_OFFSETS: {
if (!NeedsInputFiles)
break;
@@ -4112,8 +4318,8 @@ bool ASTReader::readASTFileControlBlock(
bool Overridden = static_cast<bool>(Record[3]);
std::string Filename = Blob;
ResolveImportedPath(Filename, ModuleDir);
- shouldContinue =
- Listener.visitInputFile(Filename, isSystemFile, Overridden);
+ shouldContinue = Listener.visitInputFile(
+ Filename, isSystemFile, Overridden, /*IsExplicitModule*/false);
break;
}
if (!shouldContinue)
@@ -4137,25 +4343,55 @@ bool ASTReader::readASTFileControlBlock(
break;
}
- case KNOWN_MODULE_FILES: {
- // Known-but-not-technically-used module files are treated as imports.
- if (!NeedsImports)
- break;
-
- unsigned Idx = 0, N = Record.size();
- while (Idx < N) {
- std::string Filename = ReadString(Record, Idx);
- ResolveImportedPath(Filename, ModuleDir);
- Listener.visitImport(Filename);
- }
- break;
- }
-
default:
// No other validation to perform.
break;
}
}
+
+ // Look for module file extension blocks, if requested.
+ if (FindModuleFileExtensions) {
+ while (!SkipCursorToBlock(Stream, EXTENSION_BLOCK_ID)) {
+ bool DoneWithExtensionBlock = false;
+ while (!DoneWithExtensionBlock) {
+ llvm::BitstreamEntry Entry = Stream.advance();
+
+ switch (Entry.Kind) {
+ case llvm::BitstreamEntry::SubBlock:
+ if (Stream.SkipBlock())
+ return true;
+
+ continue;
+
+ case llvm::BitstreamEntry::EndBlock:
+ DoneWithExtensionBlock = true;
+ continue;
+
+ case llvm::BitstreamEntry::Error:
+ return true;
+
+ case llvm::BitstreamEntry::Record:
+ break;
+ }
+
+ Record.clear();
+ StringRef Blob;
+ unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
+ switch (RecCode) {
+ case EXTENSION_METADATA: {
+ ModuleFileExtensionMetadata Metadata;
+ if (parseModuleFileExtensionMetadata(Record, Blob, Metadata))
+ return true;
+
+ Listener.readModuleFileExtension(Metadata);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
}
bool ASTReader::isAcceptableASTFile(
@@ -4166,6 +4402,7 @@ bool ASTReader::isAcceptableASTFile(
SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts,
ExistingModuleCachePath, FileMgr);
return !readASTFileControlBlock(Filename, FileMgr, PCHContainerRdr,
+ /*FindModuleFileExtensions=*/false,
validator);
}
@@ -4462,6 +4699,13 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record,
}
LangOpts.CommentOpts.ParseAllComments = Record[Idx++];
+ // OpenMP offloading options.
+ for (unsigned N = Record[Idx++]; N; --N) {
+ LangOpts.OMPTargetTriples.push_back(llvm::Triple(ReadString(Record, Idx)));
+ }
+
+ LangOpts.OMPHostIRFile = ReadString(Record, Idx);
+
return Listener.ReadLanguageOptions(LangOpts, Complain,
AllowCompatibleDifferences);
}
@@ -4846,22 +5090,19 @@ namespace {
public:
explicit HeaderFileInfoVisitor(const FileEntry *FE)
: FE(FE) { }
-
- static bool visit(ModuleFile &M, void *UserData) {
- HeaderFileInfoVisitor *This
- = static_cast<HeaderFileInfoVisitor *>(UserData);
-
+
+ bool operator()(ModuleFile &M) {
HeaderFileInfoLookupTable *Table
= static_cast<HeaderFileInfoLookupTable *>(M.HeaderFileInfoTable);
if (!Table)
return false;
// Look in the on-disk hash table for an entry for this file name.
- HeaderFileInfoLookupTable::iterator Pos = Table->find(This->FE);
+ HeaderFileInfoLookupTable::iterator Pos = Table->find(FE);
if (Pos == Table->end())
return false;
- This->HFI = *Pos;
+ HFI = *Pos;
return true;
}
@@ -4871,7 +5112,7 @@ namespace {
HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {
HeaderFileInfoVisitor Visitor(FE);
- ModuleMgr.visit(&HeaderFileInfoVisitor::visit, &Visitor);
+ ModuleMgr.visit(Visitor);
if (Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo())
return *HFI;
@@ -5181,9 +5422,9 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
case TYPE_AUTO: {
QualType Deduced = readType(*Loc.F, Record, Idx);
- bool IsDecltypeAuto = Record[Idx++];
+ AutoTypeKeyword Keyword = (AutoTypeKeyword)Record[Idx++];
bool IsDependent = Deduced.isNull() ? Record[Idx++] : false;
- return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent);
+ return Context.getAutoType(Deduced, Keyword, IsDependent);
}
case TYPE_RECORD: {
@@ -5335,7 +5576,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
unsigned Idx = 0;
ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
- const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx);
+ const IdentifierInfo *Name = GetIdentifierInfo(*Loc.F, Record, Idx);
QualType Canon = readType(*Loc.F, Record, Idx);
if (!Canon.isNull())
Canon = Context.getCanonicalType(Canon);
@@ -5346,7 +5587,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
unsigned Idx = 0;
ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
NestedNameSpecifier *NNS = ReadNestedNameSpecifier(*Loc.F, Record, Idx);
- const IdentifierInfo *Name = this->GetIdentifierInfo(*Loc.F, Record, Idx);
+ const IdentifierInfo *Name = GetIdentifierInfo(*Loc.F, Record, Idx);
unsigned NumArgs = Record[Idx++];
SmallVector<TemplateArgument, 8> Args;
Args.reserve(NumArgs);
@@ -5399,6 +5640,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
QualType ValueType = readType(*Loc.F, Record, Idx);
return Context.getAtomicType(ValueType);
}
+
+ case TYPE_PIPE: {
+ if (Record.size() != 1) {
+ Error("Incorrect encoding of pipe type");
+ return QualType();
+ }
+
+ // Reading the pipe element type.
+ QualType ElementType = readType(*Loc.F, Record, Idx);
+ return Context.getPipeType(ElementType);
+ }
}
llvm_unreachable("Invalid TypeCode!");
}
@@ -5670,6 +5922,9 @@ void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
TL.setLParenLoc(ReadSourceLocation(Record, Idx));
TL.setRParenLoc(ReadSourceLocation(Record, Idx));
}
+void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) {
+ TL.setKWLoc(ReadSourceLocation(Record, Idx));
+}
TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F,
const RecordData &Record,
@@ -5692,9 +5947,14 @@ QualType ASTReader::GetType(TypeID ID) {
if (Index < NUM_PREDEF_TYPE_IDS) {
QualType T;
switch ((PredefinedTypeIDs)Index) {
- case PREDEF_TYPE_NULL_ID: return QualType();
- case PREDEF_TYPE_VOID_ID: T = Context.VoidTy; break;
- case PREDEF_TYPE_BOOL_ID: T = Context.BoolTy; break;
+ case PREDEF_TYPE_NULL_ID:
+ return QualType();
+ case PREDEF_TYPE_VOID_ID:
+ T = Context.VoidTy;
+ break;
+ case PREDEF_TYPE_BOOL_ID:
+ T = Context.BoolTy;
+ break;
case PREDEF_TYPE_CHAR_U_ID:
case PREDEF_TYPE_CHAR_S_ID:
@@ -5702,59 +5962,163 @@ QualType ASTReader::GetType(TypeID ID) {
T = Context.CharTy;
break;
- case PREDEF_TYPE_UCHAR_ID: T = Context.UnsignedCharTy; break;
- case PREDEF_TYPE_USHORT_ID: T = Context.UnsignedShortTy; break;
- case PREDEF_TYPE_UINT_ID: T = Context.UnsignedIntTy; break;
- case PREDEF_TYPE_ULONG_ID: T = Context.UnsignedLongTy; break;
- case PREDEF_TYPE_ULONGLONG_ID: T = Context.UnsignedLongLongTy; break;
- case PREDEF_TYPE_UINT128_ID: T = Context.UnsignedInt128Ty; break;
- case PREDEF_TYPE_SCHAR_ID: T = Context.SignedCharTy; break;
- case PREDEF_TYPE_WCHAR_ID: T = Context.WCharTy; break;
- case PREDEF_TYPE_SHORT_ID: T = Context.ShortTy; break;
- case PREDEF_TYPE_INT_ID: T = Context.IntTy; break;
- case PREDEF_TYPE_LONG_ID: T = Context.LongTy; break;
- case PREDEF_TYPE_LONGLONG_ID: T = Context.LongLongTy; break;
- case PREDEF_TYPE_INT128_ID: T = Context.Int128Ty; break;
- case PREDEF_TYPE_HALF_ID: T = Context.HalfTy; break;
- case PREDEF_TYPE_FLOAT_ID: T = Context.FloatTy; break;
- case PREDEF_TYPE_DOUBLE_ID: T = Context.DoubleTy; break;
- case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
- case PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;
- case PREDEF_TYPE_BOUND_MEMBER: T = Context.BoundMemberTy; break;
- case PREDEF_TYPE_PSEUDO_OBJECT: T = Context.PseudoObjectTy; break;
- case PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;
- case PREDEF_TYPE_UNKNOWN_ANY: T = Context.UnknownAnyTy; break;
- case PREDEF_TYPE_NULLPTR_ID: T = Context.NullPtrTy; break;
- case PREDEF_TYPE_CHAR16_ID: T = Context.Char16Ty; break;
- case PREDEF_TYPE_CHAR32_ID: T = Context.Char32Ty; break;
- case PREDEF_TYPE_OBJC_ID: T = Context.ObjCBuiltinIdTy; break;
- case PREDEF_TYPE_OBJC_CLASS: T = Context.ObjCBuiltinClassTy; break;
- case PREDEF_TYPE_OBJC_SEL: T = Context.ObjCBuiltinSelTy; break;
- case PREDEF_TYPE_IMAGE1D_ID: T = Context.OCLImage1dTy; break;
- case PREDEF_TYPE_IMAGE1D_ARR_ID: T = Context.OCLImage1dArrayTy; break;
- case PREDEF_TYPE_IMAGE1D_BUFF_ID: T = Context.OCLImage1dBufferTy; break;
- case PREDEF_TYPE_IMAGE2D_ID: T = Context.OCLImage2dTy; break;
- case PREDEF_TYPE_IMAGE2D_ARR_ID: T = Context.OCLImage2dArrayTy; break;
- case PREDEF_TYPE_IMAGE3D_ID: T = Context.OCLImage3dTy; break;
- case PREDEF_TYPE_SAMPLER_ID: T = Context.OCLSamplerTy; break;
- case PREDEF_TYPE_EVENT_ID: T = Context.OCLEventTy; break;
- case PREDEF_TYPE_AUTO_DEDUCT: T = Context.getAutoDeductType(); break;
-
- case PREDEF_TYPE_AUTO_RREF_DEDUCT:
- T = Context.getAutoRRefDeductType();
+ case PREDEF_TYPE_UCHAR_ID:
+ T = Context.UnsignedCharTy;
+ break;
+ case PREDEF_TYPE_USHORT_ID:
+ T = Context.UnsignedShortTy;
+ break;
+ case PREDEF_TYPE_UINT_ID:
+ T = Context.UnsignedIntTy;
+ break;
+ case PREDEF_TYPE_ULONG_ID:
+ T = Context.UnsignedLongTy;
+ break;
+ case PREDEF_TYPE_ULONGLONG_ID:
+ T = Context.UnsignedLongLongTy;
+ break;
+ case PREDEF_TYPE_UINT128_ID:
+ T = Context.UnsignedInt128Ty;
+ break;
+ case PREDEF_TYPE_SCHAR_ID:
+ T = Context.SignedCharTy;
+ break;
+ case PREDEF_TYPE_WCHAR_ID:
+ T = Context.WCharTy;
+ break;
+ case PREDEF_TYPE_SHORT_ID:
+ T = Context.ShortTy;
+ break;
+ case PREDEF_TYPE_INT_ID:
+ T = Context.IntTy;
+ break;
+ case PREDEF_TYPE_LONG_ID:
+ T = Context.LongTy;
+ break;
+ case PREDEF_TYPE_LONGLONG_ID:
+ T = Context.LongLongTy;
+ break;
+ case PREDEF_TYPE_INT128_ID:
+ T = Context.Int128Ty;
+ break;
+ case PREDEF_TYPE_HALF_ID:
+ T = Context.HalfTy;
+ break;
+ case PREDEF_TYPE_FLOAT_ID:
+ T = Context.FloatTy;
+ break;
+ case PREDEF_TYPE_DOUBLE_ID:
+ T = Context.DoubleTy;
+ break;
+ case PREDEF_TYPE_LONGDOUBLE_ID:
+ T = Context.LongDoubleTy;
+ break;
+ case PREDEF_TYPE_OVERLOAD_ID:
+ T = Context.OverloadTy;
+ break;
+ case PREDEF_TYPE_BOUND_MEMBER:
+ T = Context.BoundMemberTy;
+ break;
+ case PREDEF_TYPE_PSEUDO_OBJECT:
+ T = Context.PseudoObjectTy;
+ break;
+ case PREDEF_TYPE_DEPENDENT_ID:
+ T = Context.DependentTy;
+ break;
+ case PREDEF_TYPE_UNKNOWN_ANY:
+ T = Context.UnknownAnyTy;
+ break;
+ case PREDEF_TYPE_NULLPTR_ID:
+ T = Context.NullPtrTy;
+ break;
+ case PREDEF_TYPE_CHAR16_ID:
+ T = Context.Char16Ty;
+ break;
+ case PREDEF_TYPE_CHAR32_ID:
+ T = Context.Char32Ty;
+ break;
+ case PREDEF_TYPE_OBJC_ID:
+ T = Context.ObjCBuiltinIdTy;
+ break;
+ case PREDEF_TYPE_OBJC_CLASS:
+ T = Context.ObjCBuiltinClassTy;
+ break;
+ case PREDEF_TYPE_OBJC_SEL:
+ T = Context.ObjCBuiltinSelTy;
+ break;
+ case PREDEF_TYPE_IMAGE1D_ID:
+ T = Context.OCLImage1dTy;
+ break;
+ case PREDEF_TYPE_IMAGE1D_ARR_ID:
+ T = Context.OCLImage1dArrayTy;
+ break;
+ case PREDEF_TYPE_IMAGE1D_BUFF_ID:
+ T = Context.OCLImage1dBufferTy;
+ break;
+ case PREDEF_TYPE_IMAGE2D_ID:
+ T = Context.OCLImage2dTy;
+ break;
+ case PREDEF_TYPE_IMAGE2D_ARR_ID:
+ T = Context.OCLImage2dArrayTy;
+ break;
+ case PREDEF_TYPE_IMAGE2D_DEP_ID:
+ T = Context.OCLImage2dDepthTy;
+ break;
+ case PREDEF_TYPE_IMAGE2D_ARR_DEP_ID:
+ T = Context.OCLImage2dArrayDepthTy;
+ break;
+ case PREDEF_TYPE_IMAGE2D_MSAA_ID:
+ T = Context.OCLImage2dMSAATy;
+ break;
+ case PREDEF_TYPE_IMAGE2D_ARR_MSAA_ID:
+ T = Context.OCLImage2dArrayMSAATy;
+ break;
+ case PREDEF_TYPE_IMAGE2D_MSAA_DEP_ID:
+ T = Context.OCLImage2dMSAADepthTy;
+ break;
+ case PREDEF_TYPE_IMAGE2D_ARR_MSAA_DEPTH_ID:
+ T = Context.OCLImage2dArrayMSAADepthTy;
+ break;
+ case PREDEF_TYPE_IMAGE3D_ID:
+ T = Context.OCLImage3dTy;
+ break;
+ case PREDEF_TYPE_SAMPLER_ID:
+ T = Context.OCLSamplerTy;
+ break;
+ case PREDEF_TYPE_EVENT_ID:
+ T = Context.OCLEventTy;
+ break;
+ case PREDEF_TYPE_CLK_EVENT_ID:
+ T = Context.OCLClkEventTy;
+ break;
+ case PREDEF_TYPE_QUEUE_ID:
+ T = Context.OCLQueueTy;
+ break;
+ case PREDEF_TYPE_NDRANGE_ID:
+ T = Context.OCLNDRangeTy;
+ break;
+ case PREDEF_TYPE_RESERVE_ID_ID:
+ T = Context.OCLReserveIDTy;
+ break;
+ case PREDEF_TYPE_AUTO_DEDUCT:
+ T = Context.getAutoDeductType();
break;
- case PREDEF_TYPE_ARC_UNBRIDGED_CAST:
- T = Context.ARCUnbridgedCastTy;
+ case PREDEF_TYPE_AUTO_RREF_DEDUCT:
+ T = Context.getAutoRRefDeductType();
break;
- case PREDEF_TYPE_VA_LIST_TAG:
- T = Context.getVaListTagType();
+ case PREDEF_TYPE_ARC_UNBRIDGED_CAST:
+ T = Context.ARCUnbridgedCastTy;
break;
case PREDEF_TYPE_BUILTIN_FN:
T = Context.BuiltinFnTy;
break;
+
+ case PREDEF_TYPE_OMP_ARRAY_SECTION:
+ T = Context.OMPArraySectionTy;
+ break;
}
assert(!T.isNull() && "Unknown predefined type");
@@ -5889,17 +6253,25 @@ void ASTReader::CompleteRedeclChain(const Decl *D) {
if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC) ||
isa<CXXRecordDecl>(DC) || isa<EnumDecl>(DC)) {
if (DeclarationName Name = cast<NamedDecl>(D)->getDeclName()) {
- auto *II = Name.getAsIdentifierInfo();
- if (isa<TranslationUnitDecl>(DC) && II) {
+ if (!getContext().getLangOpts().CPlusPlus &&
+ isa<TranslationUnitDecl>(DC)) {
// Outside of C++, we don't have a lookup table for the TU, so update
- // the identifier instead. In C++, either way should work fine.
+ // the identifier instead. (For C++ modules, we don't store decls
+ // in the serialized identifier table, so we do the lookup in the TU.)
+ auto *II = Name.getAsIdentifierInfo();
+ assert(II && "non-identifier name in C?");
if (II->isOutOfDate())
updateOutOfDateIdentifier(*II);
} else
DC->lookup(Name);
} else if (needsAnonymousDeclarationNumber(cast<NamedDecl>(D))) {
- // FIXME: It'd be nice to do something a bit more targeted here.
- D->getDeclContext()->decls_begin();
+ // Find all declarations of this kind from the relevant context.
+ for (auto *DCDecl : cast<Decl>(D->getLexicalDeclContext())->redecls()) {
+ auto *DC = cast<DeclContext>(DCDecl);
+ SmallVector<Decl*, 8> Decls;
+ FindExternalLexicalDecls(
+ DC, [&](Decl::Kind K) { return K == D->getKind(); }, Decls);
+ }
}
}
@@ -6061,8 +6433,17 @@ static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) {
case PREDEF_DECL_BUILTIN_VA_LIST_ID:
return Context.getBuiltinVaListDecl();
+ case PREDEF_DECL_VA_LIST_TAG:
+ return Context.getVaListTagDecl();
+
+ case PREDEF_DECL_BUILTIN_MS_VA_LIST_ID:
+ return Context.getBuiltinMSVaListDecl();
+
case PREDEF_DECL_EXTERN_C_CONTEXT_ID:
return Context.getExternCContextDecl();
+
+ case PREDEF_DECL_MAKE_INTEGER_SEQ_ID:
+ return Context.getMakeIntegerSeqDecl();
}
llvm_unreachable("PredefinedDeclIDs unknown enum value");
}
@@ -6155,71 +6536,47 @@ Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {
return ReadStmtFromStream(*Loc.F);
}
-namespace {
- class FindExternalLexicalDeclsVisitor {
- ASTReader &Reader;
- const DeclContext *DC;
- bool (*isKindWeWant)(Decl::Kind);
-
- SmallVectorImpl<Decl*> &Decls;
- bool PredefsVisited[NUM_PREDEF_DECL_IDS];
-
- public:
- FindExternalLexicalDeclsVisitor(ASTReader &Reader, const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Decls)
- : Reader(Reader), DC(DC), isKindWeWant(isKindWeWant), Decls(Decls)
- {
- for (unsigned I = 0; I != NUM_PREDEF_DECL_IDS; ++I)
- PredefsVisited[I] = false;
- }
+void ASTReader::FindExternalLexicalDecls(
+ const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Decls) {
+ bool PredefsVisited[NUM_PREDEF_DECL_IDS] = {};
- static bool visitPostorder(ModuleFile &M, void *UserData) {
- FindExternalLexicalDeclsVisitor *This
- = static_cast<FindExternalLexicalDeclsVisitor *>(UserData);
+ auto Visit = [&] (ModuleFile *M, LexicalContents LexicalDecls) {
+ assert(LexicalDecls.size() % 2 == 0 && "expected an even number of entries");
+ for (int I = 0, N = LexicalDecls.size(); I != N; I += 2) {
+ auto K = (Decl::Kind)+LexicalDecls[I];
+ if (!IsKindWeWant(K))
+ continue;
- ModuleFile::DeclContextInfosMap::iterator Info
- = M.DeclContextInfos.find(This->DC);
- if (Info == M.DeclContextInfos.end() || !Info->second.LexicalDecls)
- return false;
+ auto ID = (serialization::DeclID)+LexicalDecls[I + 1];
- // Load all of the declaration IDs
- for (const KindDeclIDPair *ID = Info->second.LexicalDecls,
- *IDE = ID + Info->second.NumLexicalDecls;
- ID != IDE; ++ID) {
- if (This->isKindWeWant && !This->isKindWeWant((Decl::Kind)ID->first))
+ // Don't add predefined declarations to the lexical context more
+ // than once.
+ if (ID < NUM_PREDEF_DECL_IDS) {
+ if (PredefsVisited[ID])
continue;
- // Don't add predefined declarations to the lexical context more
- // than once.
- if (ID->second < NUM_PREDEF_DECL_IDS) {
- if (This->PredefsVisited[ID->second])
- continue;
-
- This->PredefsVisited[ID->second] = true;
- }
-
- if (Decl *D = This->Reader.GetLocalDecl(M, ID->second)) {
- if (!This->DC->isDeclInLexicalTraversal(D))
- This->Decls.push_back(D);
- }
+ PredefsVisited[ID] = true;
}
- return false;
+ if (Decl *D = GetLocalDecl(*M, ID)) {
+ assert(D->getKind() == K && "wrong kind for lexical decl");
+ if (!DC->isDeclInLexicalTraversal(D))
+ Decls.push_back(D);
+ }
}
};
-}
-ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Decls) {
- // There might be lexical decls in multiple modules, for the TU at
- // least. Walk all of the modules in the order they were loaded.
- FindExternalLexicalDeclsVisitor Visitor(*this, DC, isKindWeWant, Decls);
- ModuleMgr.visitDepthFirst(
- nullptr, &FindExternalLexicalDeclsVisitor::visitPostorder, &Visitor);
+ if (isa<TranslationUnitDecl>(DC)) {
+ for (auto Lexical : TULexicalDecls)
+ Visit(Lexical.first, Lexical.second);
+ } else {
+ auto I = LexicalDecls.find(DC);
+ if (I != LexicalDecls.end())
+ Visit(I->second.first, I->second.second);
+ }
+
++NumLexicalDeclContextsRead;
- return ELR_Success;
}
namespace {
@@ -6298,168 +6655,26 @@ void ASTReader::FindFileRegionDecls(FileID File,
Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));
}
-/// \brief Retrieve the "definitive" module file for the definition of the
-/// given declaration context, if there is one.
-///
-/// The "definitive" module file is the only place where we need to look to
-/// find information about the declarations within the given declaration
-/// context. For example, C++ and Objective-C classes, C structs/unions, and
-/// Objective-C protocols, categories, and extensions are all defined in a
-/// single place in the source code, so they have definitive module files
-/// associated with them. C++ namespaces, on the other hand, can have
-/// definitions in multiple different module files.
-///
-/// Note: this needs to be kept in sync with ASTWriter::AddedVisibleDecl's
-/// NDEBUG checking.
-static ModuleFile *getDefinitiveModuleFileFor(const DeclContext *DC,
- ASTReader &Reader) {
- if (const DeclContext *DefDC = getDefinitiveDeclContext(DC))
- return Reader.getOwningModuleFile(cast<Decl>(DefDC));
-
- return nullptr;
-}
-
-namespace {
- /// \brief ModuleFile visitor used to perform name lookup into a
- /// declaration context.
- class DeclContextNameLookupVisitor {
- ASTReader &Reader;
- ArrayRef<const DeclContext *> Contexts;
- DeclarationName Name;
- ASTDeclContextNameLookupTrait::DeclNameKey NameKey;
- unsigned NameHash;
- SmallVectorImpl<NamedDecl *> &Decls;
- llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet;
-
- public:
- DeclContextNameLookupVisitor(ASTReader &Reader,
- DeclarationName Name,
- SmallVectorImpl<NamedDecl *> &Decls,
- llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet)
- : Reader(Reader), Name(Name),
- NameKey(ASTDeclContextNameLookupTrait::GetInternalKey(Name)),
- NameHash(ASTDeclContextNameLookupTrait::ComputeHash(NameKey)),
- Decls(Decls), DeclSet(DeclSet) {}
-
- void visitContexts(ArrayRef<const DeclContext*> Contexts) {
- if (Contexts.empty())
- return;
- this->Contexts = Contexts;
-
- // If we can definitively determine which module file to look into,
- // only look there. Otherwise, look in all module files.
- ModuleFile *Definitive;
- if (Contexts.size() == 1 &&
- (Definitive = getDefinitiveModuleFileFor(Contexts[0], Reader))) {
- visit(*Definitive, this);
- } else {
- Reader.getModuleManager().visit(&visit, this);
- }
- }
-
- private:
- static bool visit(ModuleFile &M, void *UserData) {
- DeclContextNameLookupVisitor *This
- = static_cast<DeclContextNameLookupVisitor *>(UserData);
-
- // Check whether we have any visible declaration information for
- // this context in this module.
- ModuleFile::DeclContextInfosMap::iterator Info;
- bool FoundInfo = false;
- for (auto *DC : This->Contexts) {
- Info = M.DeclContextInfos.find(DC);
- if (Info != M.DeclContextInfos.end() &&
- Info->second.NameLookupTableData) {
- FoundInfo = true;
- break;
- }
- }
-
- if (!FoundInfo)
- return false;
-
- // Look for this name within this module.
- ASTDeclContextNameLookupTable *LookupTable =
- Info->second.NameLookupTableData;
- ASTDeclContextNameLookupTable::iterator Pos
- = LookupTable->find_hashed(This->NameKey, This->NameHash);
- if (Pos == LookupTable->end())
- return false;
-
- bool FoundAnything = false;
- ASTDeclContextNameLookupTrait::data_type Data = *Pos;
- for (; Data.first != Data.second; ++Data.first) {
- NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M, *Data.first);
- if (!ND)
- continue;
-
- if (ND->getDeclName() != This->Name) {
- // A name might be null because the decl's redeclarable part is
- // currently read before reading its name. The lookup is triggered by
- // building that decl (likely indirectly), and so it is later in the
- // sense of "already existing" and can be ignored here.
- // FIXME: This should not happen; deserializing declarations should
- // not perform lookups since that can lead to deserialization cycles.
- continue;
- }
-
- // Record this declaration.
- FoundAnything = true;
- if (This->DeclSet.insert(ND).second)
- This->Decls.push_back(ND);
- }
-
- return FoundAnything;
- }
- };
-}
-
bool
ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) {
- assert(DC->hasExternalVisibleStorage() &&
+ assert(DC->hasExternalVisibleStorage() && DC == DC->getPrimaryContext() &&
"DeclContext has no visible decls in storage");
if (!Name)
return false;
+ auto It = Lookups.find(DC);
+ if (It == Lookups.end())
+ return false;
+
Deserializing LookupResults(this);
+ // Load the list of declarations.
SmallVector<NamedDecl *, 64> Decls;
- llvm::SmallPtrSet<NamedDecl*, 64> DeclSet;
-
- // Compute the declaration contexts we need to look into. Multiple such
- // declaration contexts occur when two declaration contexts from disjoint
- // modules get merged, e.g., when two namespaces with the same name are
- // independently defined in separate modules.
- SmallVector<const DeclContext *, 2> Contexts;
- Contexts.push_back(DC);
-
- if (DC->isNamespace()) {
- auto Key = KeyDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
- if (Key != KeyDecls.end()) {
- for (unsigned I = 0, N = Key->second.size(); I != N; ++I)
- Contexts.push_back(cast<DeclContext>(GetDecl(Key->second[I])));
- }
- }
-
- DeclContextNameLookupVisitor Visitor(*this, Name, Decls, DeclSet);
- Visitor.visitContexts(Contexts);
-
- // If this might be an implicit special member function, then also search
- // all merged definitions of the surrounding class. We need to search them
- // individually, because finding an entity in one of them doesn't imply that
- // we can't find a different entity in another one.
- if (isa<CXXRecordDecl>(DC)) {
- auto Merged = MergedLookups.find(DC);
- if (Merged != MergedLookups.end()) {
- for (unsigned I = 0; I != Merged->second.size(); ++I) {
- const DeclContext *Context = Merged->second[I];
- Visitor.visitContexts(Context);
- // We might have just added some more merged lookups. If so, our
- // iterator is now invalid, so grab a fresh one before continuing.
- Merged = MergedLookups.find(DC);
- }
- }
+ for (DeclID ID : It->second.Table.find(Name)) {
+ NamedDecl *ND = cast<NamedDecl>(GetDecl(ID));
+ if (ND->getDeclName() == Name)
+ Decls.push_back(ND);
}
++NumVisibleDeclContextsRead;
@@ -6467,92 +6682,21 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
return !Decls.empty();
}
-namespace {
- /// \brief ModuleFile visitor used to retrieve all visible names in a
- /// declaration context.
- class DeclContextAllNamesVisitor {
- ASTReader &Reader;
- SmallVectorImpl<const DeclContext *> &Contexts;
- DeclsMap &Decls;
- llvm::SmallPtrSet<NamedDecl *, 256> DeclSet;
- bool VisitAll;
-
- public:
- DeclContextAllNamesVisitor(ASTReader &Reader,
- SmallVectorImpl<const DeclContext *> &Contexts,
- DeclsMap &Decls, bool VisitAll)
- : Reader(Reader), Contexts(Contexts), Decls(Decls), VisitAll(VisitAll) { }
-
- static bool visit(ModuleFile &M, void *UserData) {
- DeclContextAllNamesVisitor *This
- = static_cast<DeclContextAllNamesVisitor *>(UserData);
-
- // Check whether we have any visible declaration information for
- // this context in this module.
- ModuleFile::DeclContextInfosMap::iterator Info;
- bool FoundInfo = false;
- for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
- Info = M.DeclContextInfos.find(This->Contexts[I]);
- if (Info != M.DeclContextInfos.end() &&
- Info->second.NameLookupTableData) {
- FoundInfo = true;
- break;
- }
- }
-
- if (!FoundInfo)
- return false;
-
- ASTDeclContextNameLookupTable *LookupTable =
- Info->second.NameLookupTableData;
- bool FoundAnything = false;
- for (ASTDeclContextNameLookupTable::data_iterator
- I = LookupTable->data_begin(), E = LookupTable->data_end();
- I != E;
- ++I) {
- ASTDeclContextNameLookupTrait::data_type Data = *I;
- for (; Data.first != Data.second; ++Data.first) {
- NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M,
- *Data.first);
- if (!ND)
- continue;
-
- // Record this declaration.
- FoundAnything = true;
- if (This->DeclSet.insert(ND).second)
- This->Decls[ND->getDeclName()].push_back(ND);
- }
- }
-
- return FoundAnything && !This->VisitAll;
- }
- };
-}
-
void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
if (!DC->hasExternalVisibleStorage())
return;
- DeclsMap Decls;
- // Compute the declaration contexts we need to look into. Multiple such
- // declaration contexts occur when two declaration contexts from disjoint
- // modules get merged, e.g., when two namespaces with the same name are
- // independently defined in separate modules.
- SmallVector<const DeclContext *, 2> Contexts;
- Contexts.push_back(DC);
+ auto It = Lookups.find(DC);
+ assert(It != Lookups.end() &&
+ "have external visible storage but no lookup tables");
- if (DC->isNamespace()) {
- KeyDeclsMap::iterator Key =
- KeyDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
- if (Key != KeyDecls.end()) {
- for (unsigned I = 0, N = Key->second.size(); I != N; ++I)
- Contexts.push_back(cast<DeclContext>(GetDecl(Key->second[I])));
- }
+ DeclsMap Decls;
+
+ for (DeclID ID : It->second.Table.findAll()) {
+ NamedDecl *ND = cast<NamedDecl>(GetDecl(ID));
+ Decls[ND->getDeclName()].push_back(ND);
}
- DeclContextAllNamesVisitor Visitor(*this, Contexts, Decls,
- /*VisitAll=*/DC->isFileContext());
- ModuleMgr.visit(&DeclContextAllNamesVisitor::visit, &Visitor);
++NumVisibleDeclContextsRead;
for (DeclsMap::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) {
@@ -6561,6 +6705,12 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
const_cast<DeclContext *>(DC)->setHasExternalVisibleStorage(false);
}
+const serialization::reader::DeclContextLookupTable *
+ASTReader::getLoadedLookupTables(DeclContext *Primary) const {
+ auto I = Lookups.find(Primary);
+ return I == Lookups.end() ? nullptr : &I->second;
+}
+
/// \brief Under non-PCH compilation the consumer receives the objc methods
/// before receiving the implementation, and codegen depends on this.
/// We simulate this by deserializing and passing to consumer the methods of the
@@ -6824,24 +6974,36 @@ void ASTReader::UpdateSema() {
SemaObj->ActOnPragmaOptimize(/* IsOn = */ false, OptimizeOffPragmaLocation);
}
-IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
+IdentifierInfo *ASTReader::get(StringRef Name) {
// Note that we are loading an identifier.
Deserializing AnIdentifier(this);
- StringRef Name(NameStart, NameEnd - NameStart);
- // If there is a global index, look there first to determine which modules
- // provably do not have any results for this identifier.
- GlobalModuleIndex::HitSet Hits;
- GlobalModuleIndex::HitSet *HitsPtr = nullptr;
- if (!loadGlobalIndex()) {
- if (GlobalIndex->lookupIdentifier(Name, Hits)) {
- HitsPtr = &Hits;
- }
- }
IdentifierLookupVisitor Visitor(Name, /*PriorGeneration=*/0,
NumIdentifierLookups,
NumIdentifierLookupHits);
- ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor, HitsPtr);
+
+ // We don't need to do identifier table lookups in C++ modules (we preload
+ // all interesting declarations, and don't need to use the scope for name
+ // lookups). Perform the lookup in PCH files, though, since we don't build
+ // a complete initial identifier table if we're carrying on from a PCH.
+ if (Context.getLangOpts().CPlusPlus) {
+ for (auto F : ModuleMgr.pch_modules())
+ if (Visitor(*F))
+ break;
+ } else {
+ // If there is a global index, look there first to determine which modules
+ // provably do not have any results for this identifier.
+ GlobalModuleIndex::HitSet Hits;
+ GlobalModuleIndex::HitSet *HitsPtr = nullptr;
+ if (!loadGlobalIndex()) {
+ if (GlobalIndex->lookupIdentifier(Name, Hits)) {
+ HitsPtr = &Hits;
+ }
+ }
+
+ ModuleMgr.visit(Visitor, HitsPtr);
+ }
+
IdentifierInfo *II = Visitor.getIdentifierInfo();
markIdentifierUpToDate(II);
return II;
@@ -6928,41 +7090,37 @@ namespace clang { namespace serialization {
InstanceBits(0), FactoryBits(0), InstanceHasMoreThanOneDecl(false),
FactoryHasMoreThanOneDecl(false) {}
- static bool visit(ModuleFile &M, void *UserData) {
- ReadMethodPoolVisitor *This
- = static_cast<ReadMethodPoolVisitor *>(UserData);
-
+ bool operator()(ModuleFile &M) {
if (!M.SelectorLookupTable)
return false;
// If we've already searched this module file, skip it now.
- if (M.Generation <= This->PriorGeneration)
+ if (M.Generation <= PriorGeneration)
return true;
- ++This->Reader.NumMethodPoolTableLookups;
+ ++Reader.NumMethodPoolTableLookups;
ASTSelectorLookupTable *PoolTable
= (ASTSelectorLookupTable*)M.SelectorLookupTable;
- ASTSelectorLookupTable::iterator Pos = PoolTable->find(This->Sel);
+ ASTSelectorLookupTable::iterator Pos = PoolTable->find(Sel);
if (Pos == PoolTable->end())
return false;
- ++This->Reader.NumMethodPoolTableHits;
- ++This->Reader.NumSelectorsRead;
+ ++Reader.NumMethodPoolTableHits;
+ ++Reader.NumSelectorsRead;
// FIXME: Not quite happy with the statistics here. We probably should
// disable this tracking when called via LoadSelector.
// Also, should entries without methods count as misses?
- ++This->Reader.NumMethodPoolEntriesRead;
+ ++Reader.NumMethodPoolEntriesRead;
ASTSelectorLookupTrait::data_type Data = *Pos;
- if (This->Reader.DeserializationListener)
- This->Reader.DeserializationListener->SelectorRead(Data.ID,
- This->Sel);
-
- This->InstanceMethods.append(Data.Instance.begin(), Data.Instance.end());
- This->FactoryMethods.append(Data.Factory.begin(), Data.Factory.end());
- This->InstanceBits = Data.InstanceBits;
- This->FactoryBits = Data.FactoryBits;
- This->InstanceHasMoreThanOneDecl = Data.InstanceHasMoreThanOneDecl;
- This->FactoryHasMoreThanOneDecl = Data.FactoryHasMoreThanOneDecl;
+ if (Reader.DeserializationListener)
+ Reader.DeserializationListener->SelectorRead(Data.ID, Sel);
+
+ InstanceMethods.append(Data.Instance.begin(), Data.Instance.end());
+ FactoryMethods.append(Data.Factory.begin(), Data.Factory.end());
+ InstanceBits = Data.InstanceBits;
+ FactoryBits = Data.FactoryBits;
+ InstanceHasMoreThanOneDecl = Data.InstanceHasMoreThanOneDecl;
+ FactoryHasMoreThanOneDecl = Data.FactoryHasMoreThanOneDecl;
return true;
}
@@ -7002,8 +7160,8 @@ void ASTReader::ReadMethodPool(Selector Sel) {
// Search for methods defined with this selector.
++NumMethodPoolLookups;
ReadMethodPoolVisitor Visitor(*this, Sel, PriorGeneration);
- ModuleMgr.visit(&ReadMethodPoolVisitor::visit, &Visitor);
-
+ ModuleMgr.visit(Visitor);
+
if (Visitor.getInstanceMethods().empty() &&
Visitor.getFactoryMethods().empty())
return;
@@ -7384,33 +7542,47 @@ Module *ASTReader::getModule(unsigned ID) {
return getSubmodule(ID);
}
-ExternalASTSource::ASTSourceDescriptor
-ASTReader::getSourceDescriptor(const Module &M) {
- StringRef Dir, Filename;
- if (M.Directory)
- Dir = M.Directory->getName();
- if (auto *File = M.getASTFile())
- Filename = File->getName();
- return ASTReader::ASTSourceDescriptor{
- M.getFullModuleName(), Dir, Filename,
- M.Signature
- };
+ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &F, unsigned ID) {
+ if (ID & 1) {
+ // It's a module, look it up by submodule ID.
+ auto I = GlobalSubmoduleMap.find(getGlobalSubmoduleID(F, ID >> 1));
+ return I == GlobalSubmoduleMap.end() ? nullptr : I->second;
+ } else {
+ // It's a prefix (preamble, PCH, ...). Look it up by index.
+ unsigned IndexFromEnd = ID >> 1;
+ assert(IndexFromEnd && "got reference to unknown module file");
+ return getModuleManager().pch_modules().end()[-IndexFromEnd];
+ }
+}
+
+unsigned ASTReader::getModuleFileID(ModuleFile *F) {
+ if (!F)
+ return 1;
+
+ // For a file representing a module, use the submodule ID of the top-level
+ // module as the file ID. For any other kind of file, the number of such
+ // files loaded beforehand will be the same on reload.
+ // FIXME: Is this true even if we have an explicit module file and a PCH?
+ if (F->isModule())
+ return ((F->BaseSubmoduleID + NUM_PREDEF_SUBMODULE_IDS) << 1) | 1;
+
+ auto PCHModules = getModuleManager().pch_modules();
+ auto I = std::find(PCHModules.begin(), PCHModules.end(), F);
+ assert(I != PCHModules.end() && "emitting reference to unknown file");
+ return (I - PCHModules.end()) << 1;
}
llvm::Optional<ExternalASTSource::ASTSourceDescriptor>
ASTReader::getSourceDescriptor(unsigned ID) {
if (const Module *M = getSubmodule(ID))
- return getSourceDescriptor(*M);
+ return ExternalASTSource::ASTSourceDescriptor(*M);
// If there is only a single PCH, return it instead.
// Chained PCH are not suported.
if (ModuleMgr.size() == 1) {
ModuleFile &MF = ModuleMgr.getPrimaryModule();
- return ASTReader::ASTSourceDescriptor{
- MF.OriginalSourceFileName, MF.OriginalDir,
- MF.FileName,
- MF.Signature
- };
+ return ASTReader::ASTSourceDescriptor(
+ MF.OriginalSourceFileName, MF.OriginalDir, MF.FileName, MF.Signature);
}
return None;
}
@@ -7619,9 +7791,19 @@ ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record,
llvm_unreachable("Unhandled template name kind!");
}
-TemplateArgument
-ASTReader::ReadTemplateArgument(ModuleFile &F,
- const RecordData &Record, unsigned &Idx) {
+TemplateArgument ASTReader::ReadTemplateArgument(ModuleFile &F,
+ const RecordData &Record,
+ unsigned &Idx,
+ bool Canonicalize) {
+ if (Canonicalize) {
+ // The caller wants a canonical template argument. Sometimes the AST only
+ // wants template arguments in canonical form (particularly as the template
+ // argument lists of template specializations) so ensure we preserve that
+ // canonical form across serialization.
+ TemplateArgument Arg = ReadTemplateArgument(F, Record, Idx, false);
+ return Context.getCanonicalTemplateArgument(Arg);
+ }
+
TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
switch (Kind) {
case TemplateArgument::Null:
@@ -7655,7 +7837,7 @@ ASTReader::ReadTemplateArgument(ModuleFile &F,
TemplateArgument *Args = new (Context) TemplateArgument[NumArgs];
for (unsigned I = 0; I != NumArgs; ++I)
Args[I] = ReadTemplateArgument(F, Record, Idx);
- return TemplateArgument(Args, NumArgs);
+ return TemplateArgument(llvm::makeArrayRef(Args, NumArgs));
}
}
@@ -7677,7 +7859,7 @@ ASTReader::ReadTemplateParameterList(ModuleFile &F,
TemplateParameterList* TemplateParams =
TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
- Params.data(), Params.size(), RAngleLoc);
+ Params, RAngleLoc);
return TemplateParams;
}
@@ -7685,11 +7867,11 @@ void
ASTReader::
ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
ModuleFile &F, const RecordData &Record,
- unsigned &Idx) {
+ unsigned &Idx, bool Canonicalize) {
unsigned NumTemplateArgs = Record[Idx++];
TemplArgs.reserve(NumTemplateArgs);
while (NumTemplateArgs--)
- TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx));
+ TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx, Canonicalize));
}
/// \brief Read a UnresolvedSet structure.
@@ -8070,14 +8252,6 @@ void ASTReader::ReadComments() {
}
}
-void ASTReader::getInputFiles(ModuleFile &F,
- SmallVectorImpl<serialization::InputFile> &Files) {
- for (unsigned I = 0, E = F.InputFilesLoaded.size(); I != E; ++I) {
- unsigned ID = I+1;
- Files.push_back(getInputFile(F, ID));
- }
-}
-
std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) {
// If we know the owning module, use it.
if (Module *M = D->getImportedOwningModule())
@@ -8119,11 +8293,8 @@ void ASTReader::finishPendingActions() {
PendingIncompleteDeclChains.clear();
// Load pending declaration chains.
- for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
- PendingDeclChainsKnown.erase(PendingDeclChains[I]);
- loadPendingDeclChain(PendingDeclChains[I]);
- }
- assert(PendingDeclChainsKnown.empty());
+ for (unsigned I = 0; I != PendingDeclChains.size(); ++I)
+ loadPendingDeclChain(PendingDeclChains[I].first, PendingDeclChains[I].second);
PendingDeclChains.clear();
// Make the most recent of the top-level declarations visible.
@@ -8232,9 +8403,8 @@ void ASTReader::finishPendingActions() {
// Load the bodies of any functions or methods we've encountered. We do
// this now (delayed) so that we can be sure that the declaration chains
- // have been fully wired up.
- // FIXME: There seems to be no point in delaying this, it does not depend
- // on the redecl chains having been wired up.
+ // have been fully wired up (hasBody relies on this).
+ // FIXME: We shouldn't require complete redeclaration chains here.
for (PendingBodiesMap::iterator PB = PendingBodies.begin(),
PBEnd = PendingBodies.end();
PB != PBEnd; ++PB) {
@@ -8310,21 +8480,26 @@ void ASTReader::diagnoseOdrViolations() {
if (Found)
continue;
+ // Quick check failed, time to do the slow thing. Note, we can't just
+ // look up the name of D in CanonDef here, because the member that is
+ // in CanonDef might not be found by name lookup (it might have been
+ // replaced by a more recent declaration in the lookup table), and we
+ // can't necessarily find it in the redeclaration chain because it might
+ // be merely mergeable, not redeclarable.
llvm::SmallVector<const NamedDecl*, 4> Candidates;
- DeclContext::lookup_result R = CanonDef->lookup(D->getDeclName());
- for (DeclContext::lookup_iterator I = R.begin(), E = R.end();
- !Found && I != E; ++I) {
- for (auto RI : (*I)->redecls()) {
- if (RI->getLexicalDeclContext() == CanonDef) {
- // This declaration is present in the canonical definition. If it's
- // in the same redecl chain, it's the one we're looking for.
- if (RI->getCanonicalDecl() == DCanon)
- Found = true;
- else
- Candidates.push_back(cast<NamedDecl>(RI));
- break;
- }
+ for (auto *CanonMember : CanonDef->decls()) {
+ if (CanonMember->getCanonicalDecl() == DCanon) {
+ // This can happen if the declaration is merely mergeable and not
+ // actually redeclarable (we looked for redeclarations earlier).
+ //
+ // FIXME: We should be able to detect this more efficiently, without
+ // pulling in all of the members of CanonDef.
+ Found = true;
+ break;
}
+ if (auto *ND = dyn_cast<NamedDecl>(CanonMember))
+ if (ND->getDeclName() == D->getDeclName())
+ Candidates.push_back(ND);
}
if (!Found) {
@@ -8428,16 +8603,19 @@ void ASTReader::FinishedDeserializing() {
PendingExceptionSpecUpdates.clear();
for (auto Update : Updates) {
auto *FPT = Update.second->getType()->castAs<FunctionProtoType>();
- SemaObj->UpdateExceptionSpec(Update.second,
- FPT->getExtProtoInfo().ExceptionSpec);
+ auto ESI = FPT->getExtProtoInfo().ExceptionSpec;
+ if (auto *Listener = Context.getASTMutationListener())
+ Listener->ResolvedExceptionSpec(cast<FunctionDecl>(Update.second));
+ for (auto *Redecl : Update.second->redecls())
+ Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
}
}
- diagnoseOdrViolations();
-
if (ReadTimer)
ReadTimer->stopTimer();
+ diagnoseOdrViolations();
+
// We are not in recursive loading, so it's safe to pass the "interesting"
// decls to the consumer.
if (Consumer)
@@ -8450,7 +8628,7 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
// Remove any fake results before adding any real ones.
auto It = PendingFakeLookupResults.find(II);
if (It != PendingFakeLookupResults.end()) {
- for (auto *ND : PendingFakeLookupResults[II])
+ for (auto *ND : It->second)
SemaObj->IdResolver.RemoveDecl(ND);
// FIXME: this works around module+PCH performance issue.
// Rather than erase the result from the map, which is O(n), just clear
@@ -8471,13 +8649,15 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
}
}
-ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
- const PCHContainerReader &PCHContainerRdr,
- StringRef isysroot, bool DisableValidation,
- bool AllowASTWithCompilerErrors,
- bool AllowConfigurationMismatch, bool ValidateSystemInputs,
- bool UseGlobalIndex,
- std::unique_ptr<llvm::Timer> ReadTimer)
+ASTReader::ASTReader(
+ Preprocessor &PP, ASTContext &Context,
+ const PCHContainerReader &PCHContainerRdr,
+ ArrayRef<IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
+ StringRef isysroot, bool DisableValidation,
+ bool AllowASTWithCompilerErrors,
+ bool AllowConfigurationMismatch, bool ValidateSystemInputs,
+ bool UseGlobalIndex,
+ std::unique_ptr<llvm::Timer> ReadTimer)
: Listener(new PCHValidator(PP, *this)), DeserializationListener(nullptr),
OwnsDeserializationListener(false), SourceMgr(PP.getSourceManager()),
FileMgr(PP.getFileManager()), PCHContainerRdr(PCHContainerRdr),
@@ -8501,19 +8681,21 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0),
PassingDeclsToConsumer(false), ReadingKind(Read_None) {
SourceMgr.setExternalSLocEntrySource(this);
+
+ for (const auto &Ext : Extensions) {
+ auto BlockName = Ext->getExtensionMetadata().BlockName;
+ auto Known = ModuleFileExtensions.find(BlockName);
+ if (Known != ModuleFileExtensions.end()) {
+ Diags.Report(diag::warn_duplicate_module_file_extension)
+ << BlockName;
+ continue;
+ }
+
+ ModuleFileExtensions.insert({BlockName, Ext});
+ }
}
ASTReader::~ASTReader() {
if (OwnsDeserializationListener)
delete DeserializationListener;
-
- for (DeclContextVisibleUpdatesPending::iterator
- I = PendingVisibleUpdates.begin(),
- E = PendingVisibleUpdates.end();
- I != E; ++I) {
- for (DeclContextVisibleUpdates::iterator J = I->second.begin(),
- F = I->second.end();
- J != F; ++J)
- delete J->first;
- }
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
index 1a0c5b5..5bf95f8 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -26,6 +26,7 @@
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/Support/SaveAndRestore.h"
+
using namespace clang;
using namespace clang::serialization;
@@ -120,45 +121,20 @@ namespace clang {
static void setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC,
unsigned Index, NamedDecl *D);
- /// \brief RAII class used to capture the first ID within a redeclaration
- /// chain and to introduce it into the list of pending redeclaration chains
- /// on destruction.
+ /// Results from loading a RedeclarableDecl.
class RedeclarableResult {
- ASTReader &Reader;
GlobalDeclID FirstID;
Decl *MergeWith;
- mutable bool Owning;
bool IsKeyDecl;
- Decl::Kind DeclKind;
-
- void operator=(RedeclarableResult &) = delete;
public:
- RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID,
- Decl *MergeWith, Decl::Kind DeclKind,
- bool IsKeyDecl)
- : Reader(Reader), FirstID(FirstID), MergeWith(MergeWith),
- Owning(true), IsKeyDecl(IsKeyDecl), DeclKind(DeclKind) {}
-
- RedeclarableResult(RedeclarableResult &&Other)
- : Reader(Other.Reader), FirstID(Other.FirstID),
- MergeWith(Other.MergeWith), Owning(Other.Owning),
- IsKeyDecl(Other.IsKeyDecl), DeclKind(Other.DeclKind) {
- Other.Owning = false;
- }
-
- ~RedeclarableResult() {
- if (FirstID && Owning && isRedeclarableDeclKind(DeclKind)) {
- auto Canon = Reader.GetDecl(FirstID)->getCanonicalDecl();
- if (Reader.PendingDeclChainsKnown.insert(Canon).second)
- Reader.PendingDeclChains.push_back(Canon);
- }
- }
+ RedeclarableResult(GlobalDeclID FirstID, Decl *MergeWith, bool IsKeyDecl)
+ : FirstID(FirstID), MergeWith(MergeWith), IsKeyDecl(IsKeyDecl) {}
/// \brief Retrieve the first ID.
GlobalDeclID getFirstID() const { return FirstID; }
- /// \brief Is this declaration the key declaration?
+ /// \brief Is this declaration a key declaration?
bool isKeyDecl() const { return IsKeyDecl; }
/// \brief Get a known declaration that this should be merged with, if
@@ -185,7 +161,7 @@ namespace clang {
public:
FindExistingResult(ASTReader &Reader)
: Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false),
- AnonymousDeclNumber(0), TypedefNameForLinkage(0) {}
+ AnonymousDeclNumber(0), TypedefNameForLinkage(nullptr) {}
FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing,
unsigned AnonymousDeclNumber,
@@ -317,6 +293,7 @@ namespace clang {
DeclID VisitTemplateDecl(TemplateDecl *D);
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
void VisitClassTemplateDecl(ClassTemplateDecl *D);
+ void VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D);
void VisitVarTemplateDecl(VarTemplateDecl *D);
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
@@ -395,7 +372,7 @@ namespace clang {
}
}
};
-}
+} // end namespace clang
namespace {
/// Iterator over the redeclarations of a declaration that have already
@@ -431,12 +408,12 @@ public:
return A.Current != B.Current;
}
};
-}
+} // end anonymous namespace
+
template<typename DeclT>
llvm::iterator_range<MergedRedeclIterator<DeclT>> merged_redecls(DeclT *D) {
- return llvm::iterator_range<MergedRedeclIterator<DeclT>>(
- MergedRedeclIterator<DeclT>(D),
- MergedRedeclIterator<DeclT>());
+ return llvm::make_range(MergedRedeclIterator<DeclT>(D),
+ MergedRedeclIterator<DeclT>());
}
uint64_t ASTDeclReader::GetCurrentCursorOffset() {
@@ -465,8 +442,8 @@ void ASTDeclReader::Visit(Decl *D) {
// If this is a tag declaration with a typedef name for linkage, it's safe
// to load that typedef now.
if (NamedDeclForTagDecl)
- cast<TagDecl>(D)->NamedDeclOrQualifier =
- cast<NamedDecl>(Reader.GetDecl(NamedDeclForTagDecl));
+ cast<TagDecl>(D)->TypedefNameDeclOrQualifier =
+ cast<TypedefNameDecl>(Reader.GetDecl(NamedDeclForTagDecl));
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
// if we have a fully initialized TypeDecl, we can safely read its type now.
ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull();
@@ -499,6 +476,8 @@ void ASTDeclReader::VisitDecl(Decl *D) {
// placeholder.
GlobalDeclID SemaDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
GlobalDeclID LexicalDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
+ if (!LexicalDCIDForTemplateParmDecl)
+ LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl;
Reader.addPendingDeclContextInfo(D,
SemaDCIDForTemplateParmDecl,
LexicalDCIDForTemplateParmDecl);
@@ -506,6 +485,8 @@ void ASTDeclReader::VisitDecl(Decl *D) {
} else {
DeclContext *SemaDC = ReadDeclAs<DeclContext>(Record, Idx);
DeclContext *LexicalDC = ReadDeclAs<DeclContext>(Record, Idx);
+ if (!LexicalDC)
+ LexicalDC = SemaDC;
DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC);
// Avoid calling setLexicalDeclContext() directly because it uses
// Decl::getASTContext() internally which is unsafe during derialization.
@@ -619,16 +600,13 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
case 1: { // ExtInfo
TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo();
ReadQualifierInfo(*Info, Record, Idx);
- TD->NamedDeclOrQualifier = Info;
+ TD->TypedefNameDeclOrQualifier = Info;
break;
}
case 2: // TypedefNameForAnonDecl
NamedDeclForTagDecl = ReadDeclID(Record, Idx);
TypedefNameForLinkage = Reader.GetIdentifierInfo(F, Record, Idx);
break;
- case 3: // DeclaratorForAnonDecl
- NamedDeclForTagDecl = ReadDeclID(Record, Idx);
- break;
default:
llvm_unreachable("unexpected tag info kind");
}
@@ -771,8 +749,9 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
// Template arguments.
SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
-
+ Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
+ /*Canonicalize*/ true);
+
// Template args as written.
SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
SourceLocation LAngleLoc, RAngleLoc;
@@ -909,6 +888,7 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
void ASTDeclReader::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
VisitTypedefNameDecl(D);
+
D->Variance = Record[Idx++];
D->Index = Record[Idx++];
D->VarianceLoc = ReadSourceLocation(Record, Idx);
@@ -1121,7 +1101,6 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
D->IvarInitializers = Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
}
-
void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
VisitDecl(D);
D->setAtLoc(ReadSourceLocation(Record, Idx));
@@ -1168,6 +1147,8 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
for (unsigned I = 0; I != FD->ChainingSize; ++I)
FD->Chaining[I] = ReadDeclAs<NamedDecl>(Record, Idx);
+
+ mergeMergeable(FD);
}
ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
@@ -1208,8 +1189,9 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
};
switch ((VarKind)Record[Idx++]) {
case VarNotTemplate:
- // Only true variables (not parameters or implicit parameters) can be merged
- if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam &&
+ // Only true variables (not parameters or implicit parameters) can be
+ // merged; the other kinds are not really redeclarable at all.
+ if (!isa<ParmVarDecl>(VD) && !isa<ImplicitParamDecl>(VD) &&
!isa<VarTemplateSpecializationDecl>(VD))
mergeRedeclarable(VD, Redecl);
break;
@@ -1290,8 +1272,7 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
captures.push_back(BlockDecl::Capture(decl, byRef, nested, copyExpr));
}
- BD->setCaptures(Reader.getContext(), captures.begin(),
- captures.end(), capturesCXXThis);
+ BD->setCaptures(Reader.getContext(), captures, capturesCXXThis);
}
void ASTDeclReader::VisitCapturedDecl(CapturedDecl *CD) {
@@ -1319,7 +1300,6 @@ void ASTDeclReader::VisitLabelDecl(LabelDecl *D) {
D->setLocStart(ReadSourceLocation(Record, Idx));
}
-
void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
RedeclarableResult Redecl = VisitRedeclarable(D);
VisitNamedDecl(D);
@@ -1506,21 +1486,14 @@ void ASTDeclReader::MergeDefinitionData(
auto &DD = *D->DefinitionData.getNotUpdated();
if (DD.Definition != MergeDD.Definition) {
- // If the new definition has new special members, let the name lookup
- // code know that it needs to look in the new definition too.
- //
- // FIXME: We only need to do this if the merged definition declares members
- // that this definition did not declare, or if it defines members that this
- // definition did not define.
- Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition);
- DD.Definition->setHasExternalVisibleStorage();
-
// Track that we merged the definitions.
Reader.MergedDeclContexts.insert(std::make_pair(MergeDD.Definition,
DD.Definition));
Reader.PendingDefinitions.erase(MergeDD.Definition);
MergeDD.Definition->IsCompleteDefinition = false;
mergeDefinitionVisibility(DD.Definition, MergeDD.Definition);
+ assert(Reader.Lookups.find(MergeDD.Definition) == Reader.Lookups.end() &&
+ "already loaded pending lookups for merged definition");
}
auto PFDI = Reader.PendingFakeDefinitionData.find(&DD);
@@ -1758,7 +1731,7 @@ void ASTDeclReader::VisitImportDecl(ImportDecl *D) {
VisitDecl(D);
D->ImportedAndComplete.setPointer(readModule(Record, Idx));
D->ImportedAndComplete.setInt(Record[Idx++]);
- SourceLocation *StoredLocs = reinterpret_cast<SourceLocation *>(D + 1);
+ SourceLocation *StoredLocs = D->getTrailingObjects<SourceLocation>();
for (unsigned I = 0, N = Record.back(); I != N; ++I)
StoredLocs[I] = ReadSourceLocation(Record, Idx);
++Idx; // The number of stored source locations.
@@ -1776,7 +1749,8 @@ void ASTDeclReader::VisitFriendDecl(FriendDecl *D) {
else
D->Friend = GetTypeSourceInfo(Record, Idx);
for (unsigned i = 0; i != D->NumTPLists; ++i)
- D->getTPLists()[i] = Reader.ReadTemplateParameterList(F, Record, Idx);
+ D->getTrailingObjects<TemplateParameterList *>()[i] =
+ Reader.ReadTemplateParameterList(F, Record, Idx);
D->NextFriend = ReadDeclID(Record, Idx);
D->UnsupportedFriend = (Record[Idx++] != 0);
D->FriendLoc = ReadSourceLocation(Record, Idx);
@@ -1887,6 +1861,10 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
}
}
+void ASTDeclReader::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
+ llvm_unreachable("BuiltinTemplates are not serialized");
+}
+
/// TODO: Unify with ClassTemplateDecl version?
/// May require unifying ClassTemplateDecl and
/// VarTemplateDecl beyond TemplateDecl...
@@ -1933,7 +1911,8 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
}
SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+ Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
+ /*Canonicalize*/ true);
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs.data(),
TemplArgs.size());
D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
@@ -2060,7 +2039,8 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
}
SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+ Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
+ /*Canonicalize*/ true);
D->TemplateArgs =
TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size());
D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
@@ -2070,6 +2050,7 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
if (writtenAsCanonicalDecl) {
VarTemplateDecl *CanonPattern = ReadDeclAs<VarTemplateDecl>(Record, Idx);
if (D->isCanonicalDecl()) { // It's kept in the folding set.
+ // FIXME: If it's already present, merge it.
if (VarTemplatePartialSpecializationDecl *Partial =
dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
CanonPattern->getCommonPtr()->PartialSpecializations
@@ -2118,10 +2099,11 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
D->setDepth(Record[Idx++]);
D->setPosition(Record[Idx++]);
if (D->isExpandedParameterPack()) {
- void **Data = reinterpret_cast<void **>(D + 1);
+ auto TypesAndInfos =
+ D->getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
- Data[2*I] = Reader.readType(F, Record, Idx).getAsOpaquePtr();
- Data[2*I + 1] = GetTypeSourceInfo(Record, Idx);
+ new (&TypesAndInfos[I].first) QualType(Reader.readType(F, Record, Idx));
+ TypesAndInfos[I].second = GetTypeSourceInfo(Record, Idx);
}
} else {
// Rest of NonTypeTemplateParmDecl.
@@ -2137,7 +2119,8 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
D->setDepth(Record[Idx++]);
D->setPosition(Record[Idx++]);
if (D->isExpandedParameterPack()) {
- void **Data = reinterpret_cast<void **>(D + 1);
+ TemplateParameterList **Data =
+ D->getTrailingObjects<TemplateParameterList *>();
for (unsigned I = 0, N = D->getNumExpansionTemplateParameters();
I != N; ++I)
Data[I] = Reader.ReadTemplateParameterList(F, Record, Idx);
@@ -2178,23 +2161,37 @@ ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
DeclID FirstDeclID = ReadDeclID(Record, Idx);
Decl *MergeWith = nullptr;
+
bool IsKeyDecl = ThisDeclID == FirstDeclID;
+ bool IsFirstLocalDecl = false;
+
+ uint64_t RedeclOffset = 0;
// 0 indicates that this declaration was the only declaration of its entity,
// and is used for space optimization.
if (FirstDeclID == 0) {
FirstDeclID = ThisDeclID;
IsKeyDecl = true;
+ IsFirstLocalDecl = true;
} else if (unsigned N = Record[Idx++]) {
- IsKeyDecl = false;
+ // This declaration was the first local declaration, but may have imported
+ // other declarations.
+ IsKeyDecl = N == 1;
+ IsFirstLocalDecl = true;
// We have some declarations that must be before us in our redeclaration
// chain. Read them now, and remember that we ought to merge with one of
// them.
// FIXME: Provide a known merge target to the second and subsequent such
// declaration.
- for (unsigned I = 0; I != N; ++I)
+ for (unsigned I = 0; I != N - 1; ++I)
MergeWith = ReadDecl(Record, Idx/*, MergeWith*/);
+
+ RedeclOffset = Record[Idx++];
+ } else {
+ // This declaration was not the first local declaration. Read the first
+ // local declaration now, to trigger the import of other redeclarations.
+ (void)ReadDecl(Record, Idx);
}
T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
@@ -2206,14 +2203,17 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(FirstDecl);
D->First = FirstDecl->getCanonicalDecl();
}
-
- // Note that this declaration has been deserialized.
- Reader.RedeclsDeserialized.insert(static_cast<T *>(D));
-
- // The result structure takes care to note that we need to load the
- // other declaration chains for this ID.
- return RedeclarableResult(Reader, FirstDeclID, MergeWith,
- static_cast<T *>(D)->getKind(), IsKeyDecl);
+
+ T *DAsT = static_cast<T*>(D);
+
+ // Note that we need to load local redeclarations of this decl and build a
+ // decl chain for them. This must happen *after* we perform the preloading
+ // above; this ensures that the redeclaration chain is built in the correct
+ // order.
+ if (IsFirstLocalDecl)
+ Reader.PendingDeclChains.push_back(std::make_pair(DAsT, RedeclOffset));
+
+ return RedeclarableResult(FirstDeclID, MergeWith, IsKeyDecl);
}
/// \brief Attempts to merge the given declaration (D) with another declaration
@@ -2255,9 +2255,8 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
DeclID DsID, bool IsKeyDecl) {
auto *DPattern = D->getTemplatedDecl();
auto *ExistingPattern = Existing->getTemplatedDecl();
- RedeclarableResult Result(Reader, DPattern->getCanonicalDecl()->getGlobalID(),
- /*MergeWith*/ExistingPattern, DPattern->getKind(),
- IsKeyDecl);
+ RedeclarableResult Result(DPattern->getCanonicalDecl()->getGlobalID(),
+ /*MergeWith*/ ExistingPattern, IsKeyDecl);
if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) {
// Merge with any existing definition.
@@ -2323,11 +2322,8 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
TemplatePatternID, Redecl.isKeyDecl());
// If this declaration is a key declaration, make a note of that.
- if (Redecl.isKeyDecl()) {
+ if (Redecl.isKeyDecl())
Reader.KeyDecls[ExistingCanon].push_back(Redecl.getFirstID());
- if (Reader.PendingDeclChainsKnown.insert(ExistingCanon).second)
- Reader.PendingDeclChains.push_back(ExistingCanon);
- }
}
}
@@ -2626,6 +2622,13 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
return X->getASTContext().hasSameType(FDX->getType(), FDY->getType());
}
+ // Indirect fields with the same target field match.
+ if (auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) {
+ auto *IFDY = cast<IndirectFieldDecl>(Y);
+ return IFDX->getAnonField()->getCanonicalDecl() ==
+ IFDY->getAnonField()->getCanonicalDecl();
+ }
+
// Enumerators with the same name match.
if (isa<EnumConstantDecl>(X))
// FIXME: Also check the value is odr-equivalent.
@@ -2749,12 +2752,12 @@ static NamedDecl *getDeclForMerging(NamedDecl *Found,
// declaration, then we want that inner declaration. Declarations from
// AST files are handled via ImportedTypedefNamesForLinkage.
if (Found->isFromASTFile())
- return 0;
+ return nullptr;
if (auto *TND = dyn_cast<TypedefNameDecl>(Found))
return TND->getAnonDeclWithTypedefName();
- return 0;
+ return nullptr;
}
NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader,
@@ -2924,6 +2927,7 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
D->RedeclLink.setPrevious(cast<DeclT>(Previous));
D->First = cast<DeclT>(Previous)->First;
}
+
namespace clang {
template<>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
@@ -2969,7 +2973,8 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
std::make_pair(Canon, IsUnresolved ? PrevFD : FD));
}
}
-}
+} // end namespace clang
+
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) {
llvm_unreachable("attachPreviousDecl on non-redeclarable declaration");
}
@@ -3319,37 +3324,13 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
// If this declaration is also a declaration context, get the
// offsets for its tables of lexical and visible declarations.
if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
- // FIXME: This should really be
- // DeclContext *LookupDC = DC->getPrimaryContext();
- // but that can walk the redeclaration chain, which might not work yet.
- DeclContext *LookupDC = DC;
- if (isa<NamespaceDecl>(DC))
- LookupDC = DC->getPrimaryContext();
std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
- if (Offsets.first || Offsets.second) {
- if (Offsets.first != 0)
- DC->setHasExternalLexicalStorage(true);
- if (Offsets.second != 0)
- LookupDC->setHasExternalVisibleStorage(true);
- if (ReadDeclContextStorage(*Loc.F, DeclsCursor, Offsets,
- Loc.F->DeclContextInfos[DC]))
- return nullptr;
- }
-
- // Now add the pending visible updates for this decl context, if it has any.
- DeclContextVisibleUpdatesPending::iterator I =
- PendingVisibleUpdates.find(ID);
- if (I != PendingVisibleUpdates.end()) {
- // There are updates. This means the context has external visible
- // storage, even if the original stored version didn't.
- LookupDC->setHasExternalVisibleStorage(true);
- for (const auto &Update : I->second) {
- DeclContextInfo &Info = Update.second->DeclContextInfos[DC];
- delete Info.NameLookupTableData;
- Info.NameLookupTableData = Update.first;
- }
- PendingVisibleUpdates.erase(I);
- }
+ if (Offsets.first &&
+ ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, Offsets.first, DC))
+ return nullptr;
+ if (Offsets.second &&
+ ReadVisibleDeclContextStorage(*Loc.F, DeclsCursor, Offsets.second, ID))
+ return nullptr;
}
assert(Idx == Record.size());
@@ -3372,17 +3353,32 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
}
void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
+ // Load the pending visible updates for this decl context, if it has any.
+ auto I = PendingVisibleUpdates.find(ID);
+ if (I != PendingVisibleUpdates.end()) {
+ auto VisibleUpdates = std::move(I->second);
+ PendingVisibleUpdates.erase(I);
+
+ auto *DC = cast<DeclContext>(D)->getPrimaryContext();
+ for (const PendingVisibleUpdate &Update : VisibleUpdates)
+ Lookups[DC].Table.add(
+ Update.Mod, Update.Data,
+ reader::ASTDeclContextNameLookupTrait(*this, *Update.Mod));
+ DC->setHasExternalVisibleStorage(true);
+ }
+
// The declaration may have been modified by files later in the chain.
// If this is the case, read the record containing the updates from each file
// and pass it to ASTDeclReader to make the modifications.
DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);
if (UpdI != DeclUpdateOffsets.end()) {
- FileOffsetsTy &UpdateOffsets = UpdI->second;
+ auto UpdateOffsets = std::move(UpdI->second);
+ DeclUpdateOffsets.erase(UpdI);
+
bool WasInteresting = isConsumerInterestedIn(D, false);
- for (FileOffsetsTy::iterator
- I = UpdateOffsets.begin(), E = UpdateOffsets.end(); I != E; ++I) {
- ModuleFile *F = I->first;
- uint64_t Offset = I->second;
+ for (auto &FileAndOffset : UpdateOffsets) {
+ ModuleFile *F = FileAndOffset.first;
+ uint64_t Offset = FileAndOffset.second;
llvm::BitstreamCursor &Cursor = F->DeclsCursor;
SavedStreamPosition SavedPosition(Cursor);
Cursor.JumpToBit(Offset);
@@ -3407,154 +3403,42 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
}
}
-namespace {
- /// \brief Module visitor class that finds all of the redeclarations of a
- /// redeclarable declaration.
- class RedeclChainVisitor {
- ASTReader &Reader;
- SmallVectorImpl<DeclID> &SearchDecls;
- llvm::SmallPtrSetImpl<Decl *> &Deserialized;
- GlobalDeclID CanonID;
- SmallVector<Decl *, 4> Chain;
-
- public:
- RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls,
- llvm::SmallPtrSetImpl<Decl *> &Deserialized,
- GlobalDeclID CanonID)
- : Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized),
- CanonID(CanonID) {
- // Ensure that the canonical ID goes at the start of the chain.
- addToChain(Reader.GetDecl(CanonID));
- }
-
- static ModuleManager::DFSPreorderControl
- visitPreorder(ModuleFile &M, void *UserData) {
- return static_cast<RedeclChainVisitor *>(UserData)->visitPreorder(M);
- }
-
- static bool visitPostorder(ModuleFile &M, void *UserData) {
- return static_cast<RedeclChainVisitor *>(UserData)->visitPostorder(M);
- }
-
- void addToChain(Decl *D) {
- if (!D)
- return;
-
- if (Deserialized.erase(D))
- Chain.push_back(D);
- }
-
- void searchForID(ModuleFile &M, GlobalDeclID GlobalID) {
- // Map global ID of the first declaration down to the local ID
- // used in this module file.
- DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID);
- if (!ID)
- return;
-
- // If the search decl was from this module, add it to the chain before any
- // of its redeclarations in this module or users of it, and after any from
- // imported modules.
- if (CanonID != GlobalID && Reader.isDeclIDFromModule(GlobalID, M))
- addToChain(Reader.GetDecl(GlobalID));
-
- // Perform a binary search to find the local redeclarations for this
- // declaration (if any).
- const LocalRedeclarationsInfo Compare = { ID, 0 };
- const LocalRedeclarationsInfo *Result
- = std::lower_bound(M.RedeclarationsMap,
- M.RedeclarationsMap + M.LocalNumRedeclarationsInMap,
- Compare);
- if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap ||
- Result->FirstID != ID)
- return;
-
- // Dig out all of the redeclarations.
- unsigned Offset = Result->Offset;
- unsigned N = M.RedeclarationChains[Offset];
- M.RedeclarationChains[Offset++] = 0; // Don't try to deserialize again
- for (unsigned I = 0; I != N; ++I)
- addToChain(Reader.GetLocalDecl(M, M.RedeclarationChains[Offset++]));
- }
-
- bool needsToVisitImports(ModuleFile &M, GlobalDeclID GlobalID) {
- DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID);
- if (!ID)
- return false;
-
- const LocalRedeclarationsInfo Compare = {ID, 0};
- const LocalRedeclarationsInfo *Result = std::lower_bound(
- M.RedeclarationsMap,
- M.RedeclarationsMap + M.LocalNumRedeclarationsInMap, Compare);
- if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap ||
- Result->FirstID != ID) {
- return true;
- }
- unsigned Offset = Result->Offset;
- unsigned N = M.RedeclarationChains[Offset];
- // We don't need to visit a module or any of its imports if we've already
- // deserialized the redecls from this module.
- return N != 0;
- }
+void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) {
+ // Attach FirstLocal to the end of the decl chain.
+ Decl *CanonDecl = FirstLocal->getCanonicalDecl();
+ if (FirstLocal != CanonDecl) {
+ Decl *PrevMostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl);
+ ASTDeclReader::attachPreviousDecl(
+ *this, FirstLocal, PrevMostRecent ? PrevMostRecent : CanonDecl,
+ CanonDecl);
+ }
- ModuleManager::DFSPreorderControl visitPreorder(ModuleFile &M) {
- for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) {
- if (needsToVisitImports(M, SearchDecls[I]))
- return ModuleManager::Continue;
- }
- return ModuleManager::SkipImports;
- }
+ if (!LocalOffset) {
+ ASTDeclReader::attachLatestDecl(CanonDecl, FirstLocal);
+ return;
+ }
- bool visitPostorder(ModuleFile &M) {
- // Visit each of the declarations.
- for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
- searchForID(M, SearchDecls[I]);
- return false;
- }
-
- ArrayRef<Decl *> getChain() const {
- return Chain;
- }
- };
-}
+ // Load the list of other redeclarations from this module file.
+ ModuleFile *M = getOwningModuleFile(FirstLocal);
+ assert(M && "imported decl from no module file");
-void ASTReader::loadPendingDeclChain(Decl *CanonDecl) {
- // The decl might have been merged into something else after being added to
- // our list. If it was, just skip it.
- if (!CanonDecl->isCanonicalDecl())
- return;
+ llvm::BitstreamCursor &Cursor = M->DeclsCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(LocalOffset);
- // Determine the set of declaration IDs we'll be searching for.
- SmallVector<DeclID, 16> SearchDecls;
- GlobalDeclID CanonID = CanonDecl->getGlobalID();
- if (CanonID)
- SearchDecls.push_back(CanonDecl->getGlobalID()); // Always first.
- KeyDeclsMap::iterator KeyPos = KeyDecls.find(CanonDecl);
- if (KeyPos != KeyDecls.end())
- SearchDecls.append(KeyPos->second.begin(), KeyPos->second.end());
-
- // Build up the list of redeclarations.
- RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized, CanonID);
- ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visitPreorder,
- &RedeclChainVisitor::visitPostorder, &Visitor);
-
- // Retrieve the chains.
- ArrayRef<Decl *> Chain = Visitor.getChain();
- if (Chain.empty() || (Chain.size() == 1 && Chain[0] == CanonDecl))
- return;
+ RecordData Record;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.readRecord(Code, Record);
+ (void)RecCode;
+ assert(RecCode == LOCAL_REDECLARATIONS && "expected LOCAL_REDECLARATIONS record!");
- // Hook up the chains.
- //
- // FIXME: We have three different dispatches on decl kind here; maybe
+ // FIXME: We have several different dispatches on decl kind here; maybe
// we should instead generate one loop per kind and dispatch up-front?
- Decl *MostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl);
- if (!MostRecent)
- MostRecent = CanonDecl;
- for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
- if (Chain[I] == CanonDecl)
- continue;
-
- ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent, CanonDecl);
- MostRecent = Chain[I];
+ Decl *MostRecent = FirstLocal;
+ for (unsigned I = 0, N = Record.size(); I != N; ++I) {
+ auto *D = GetLocalDecl(*M, Record[N - I - 1]);
+ ASTDeclReader::attachPreviousDecl(*this, D, MostRecent, CanonDecl);
+ MostRecent = D;
}
ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent);
}
@@ -3630,11 +3514,7 @@ namespace {
}
}
- static bool visit(ModuleFile &M, void *UserData) {
- return static_cast<ObjCCategoriesVisitor *>(UserData)->visit(M);
- }
-
- bool visit(ModuleFile &M) {
+ bool operator()(ModuleFile &M) {
// If we've loaded all of the category information we care about from
// this module file, we're done.
if (M.Generation <= PreviousGeneration)
@@ -3672,14 +3552,14 @@ namespace {
return true;
}
};
-}
+} // end anonymous namespace
void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID,
ObjCInterfaceDecl *D,
unsigned PreviousGeneration) {
ObjCCategoriesVisitor Visitor(*this, ID, D, CategoriesDeserialized,
PreviousGeneration);
- ModuleMgr.visit(ObjCCategoriesVisitor::visit, &Visitor);
+ ModuleMgr.visit(Visitor);
}
template<typename DeclT, typename Fn>
@@ -3716,17 +3596,6 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
// FIXME: We should call addHiddenDecl instead, to add the member
// to its DeclContext.
RD->addedMember(MD);
-
- // If we've added a new special member to a class definition that is not
- // the canonical definition, then we need special member lookups in the
- // canonical definition to also look into our class.
- auto *DD = RD->DefinitionData.getNotUpdated();
- if (DD && DD->Definition != RD) {
- auto &Merged = Reader.MergedLookups[DD->Definition];
- // FIXME: Avoid the linear-time scan here.
- if (std::find(Merged.begin(), Merged.end(), RD) == Merged.end())
- Merged.push_back(RD);
- }
break;
}
@@ -3757,6 +3626,21 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
Reader.ReadSourceLocation(ModuleFile, Record, Idx));
break;
+ case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: {
+ auto Param = cast<ParmVarDecl>(D);
+
+ // We have to read the default argument regardless of whether we use it
+ // so that hypothetical further update records aren't messed up.
+ // TODO: Add a function to skip over the next expr record.
+ auto DefaultArg = Reader.ReadExpr(F);
+
+ // Only apply the update if the parameter still has an uninstantiated
+ // default argument.
+ if (Param->hasUninstantiatedDefaultArg())
+ Param->setDefaultArg(DefaultArg);
+ break;
+ }
+
case UPD_CXX_ADDED_FUNCTION_DEFINITION: {
FunctionDecl *FD = cast<FunctionDecl>(D);
if (Reader.PendingBodies[FD]) {
@@ -3798,10 +3682,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
// Visible update is handled separately.
uint64_t LexicalOffset = Record[Idx++];
if (!HadRealDefinition && LexicalOffset) {
- RD->setHasExternalLexicalStorage(true);
- Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor,
- std::make_pair(LexicalOffset, 0),
- ModuleFile.DeclContextInfos[RD]);
+ Reader.ReadLexicalDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor,
+ LexicalOffset, RD);
Reader.PendingFakeDefinitionData.erase(OldDD);
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
index 5b1c4f4..d392364 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
@@ -15,8 +15,12 @@
#include "clang/AST/DeclarationName.h"
#include "clang/Serialization/ASTBitCodes.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/OnDiskHashTable.h"
+#include "MultiOnDiskHashTable.h"
#include <utility>
namespace clang {
@@ -39,45 +43,86 @@ class ASTDeclContextNameLookupTrait {
ModuleFile &F;
public:
- /// \brief Pair of begin/end iterators for DeclIDs.
- ///
- /// Note that these declaration IDs are local to the module that contains this
- /// particular lookup t
- typedef llvm::support::ulittle32_t LE32DeclID;
- typedef std::pair<LE32DeclID *, LE32DeclID *> data_type;
- typedef unsigned hash_value_type;
- typedef unsigned offset_type;
+ // Maximum number of lookup tables we allow before condensing the tables.
+ static const int MaxTables = 4;
+
+ /// The lookup result is a list of global declaration IDs.
+ typedef llvm::SmallVector<DeclID, 4> data_type;
+ struct data_type_builder {
+ data_type &Data;
+ llvm::DenseSet<DeclID> Found;
- /// \brief Special internal key for declaration names.
- /// The hash table creates keys for comparison; we do not create
- /// a DeclarationName for the internal key to avoid deserializing types.
- struct DeclNameKey {
- DeclarationName::NameKind Kind;
- uint64_t Data;
- DeclNameKey() : Kind((DeclarationName::NameKind)0), Data(0) { }
+ data_type_builder(data_type &D) : Data(D) {}
+ void insert(DeclID ID) {
+ // Just use a linear scan unless we have more than a few IDs.
+ if (Found.empty() && !Data.empty()) {
+ if (Data.size() <= 4) {
+ for (auto I : Found)
+ if (I == ID)
+ return;
+ Data.push_back(ID);
+ return;
+ }
+
+ // Switch to tracking found IDs in the set.
+ Found.insert(Data.begin(), Data.end());
+ }
+
+ if (Found.insert(ID).second)
+ Data.push_back(ID);
+ }
};
+ typedef unsigned hash_value_type;
+ typedef unsigned offset_type;
+ typedef ModuleFile *file_type;
typedef DeclarationName external_key_type;
- typedef DeclNameKey internal_key_type;
+ typedef DeclarationNameKey internal_key_type;
explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, ModuleFile &F)
: Reader(Reader), F(F) { }
- static bool EqualKey(const internal_key_type& a,
- const internal_key_type& b) {
- return a.Kind == b.Kind && a.Data == b.Data;
+ static bool EqualKey(const internal_key_type &a, const internal_key_type &b) {
+ return a == b;
}
- static hash_value_type ComputeHash(const DeclNameKey &Key);
- static internal_key_type GetInternalKey(const external_key_type& Name);
+ static hash_value_type ComputeHash(const internal_key_type &Key) {
+ return Key.getHash();
+ }
+ static internal_key_type GetInternalKey(const external_key_type &Name) {
+ return Name;
+ }
static std::pair<unsigned, unsigned>
- ReadKeyDataLength(const unsigned char*& d);
+ ReadKeyDataLength(const unsigned char *&d);
- internal_key_type ReadKey(const unsigned char* d, unsigned);
+ internal_key_type ReadKey(const unsigned char *d, unsigned);
- data_type ReadData(internal_key_type, const unsigned char* d,
- unsigned DataLen);
+ void ReadDataInto(internal_key_type, const unsigned char *d,
+ unsigned DataLen, data_type_builder &Val);
+
+ static void MergeDataInto(const data_type &From, data_type_builder &To) {
+ To.Data.reserve(To.Data.size() + From.size());
+ for (DeclID ID : From)
+ To.insert(ID);
+ }
+
+ file_type ReadFileRef(const unsigned char *&d);
+};
+
+struct DeclContextLookupTable {
+ MultiOnDiskHashTable<ASTDeclContextNameLookupTrait> Table;
+
+ // These look redundant, but don't remove them -- they work around MSVC 2013's
+ // inability to synthesize move operations. Without them, the
+ // MultiOnDiskHashTable will be copied (despite being move-only!).
+ DeclContextLookupTable() : Table() {}
+ DeclContextLookupTable(DeclContextLookupTable &&O)
+ : Table(std::move(O.Table)) {}
+ DeclContextLookupTable &operator=(DeclContextLookupTable &&O) {
+ Table = std::move(O.Table);
+ return *this;
+ }
};
/// \brief Base class for the trait describing the on-disk hash table for the
@@ -137,6 +182,8 @@ public:
const unsigned char* d,
unsigned DataLen);
+ IdentID ReadIdentifierID(const unsigned char *d);
+
ASTReader &getReader() const { return Reader; }
};
@@ -226,7 +273,7 @@ public:
: Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings) { }
static hash_value_type ComputeHash(internal_key_ref ikey);
- static internal_key_type GetInternalKey(const FileEntry *FE);
+ internal_key_type GetInternalKey(const FileEntry *FE);
bool EqualKey(internal_key_ref a, internal_key_ref b);
static std::pair<unsigned, unsigned>
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
index 76e8334..ad81ac8 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -93,6 +93,7 @@ namespace clang {
/// \brief Read and initialize a ExplicitTemplateArgumentList structure.
void ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args,
+ TemplateArgumentLoc *ArgsLocArray,
unsigned NumTemplateArgs);
/// \brief Read and initialize a ExplicitTemplateArgumentList structure.
void ReadExplicitTemplateArgumentList(ASTTemplateArgumentListInfo &ArgList,
@@ -105,9 +106,9 @@ namespace clang {
};
}
-void ASTStmtReader::
-ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args,
- unsigned NumTemplateArgs) {
+void ASTStmtReader::ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args,
+ TemplateArgumentLoc *ArgsLocArray,
+ unsigned NumTemplateArgs) {
SourceLocation TemplateKWLoc = ReadSourceLocation(Record, Idx);
TemplateArgumentListInfo ArgInfo;
ArgInfo.setLAngleLoc(ReadSourceLocation(Record, Idx));
@@ -115,7 +116,7 @@ ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args,
for (unsigned i = 0; i != NumTemplateArgs; ++i)
ArgInfo.addArgument(
Reader.ReadTemplateArgumentLoc(F, Record, Idx));
- Args.initializeFrom(TemplateKWLoc, ArgInfo);
+ Args.initializeFrom(TemplateKWLoc, ArgInfo, ArgsLocArray);
}
void ASTStmtReader::VisitStmt(Stmt *S) {
@@ -134,7 +135,7 @@ void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) {
unsigned NumStmts = Record[Idx++];
while (NumStmts--)
Stmts.push_back(Reader.ReadSubStmt());
- S->setStmts(Reader.getContext(), Stmts.data(), Stmts.size());
+ S->setStmts(Reader.getContext(), Stmts);
S->LBraceLoc = ReadSourceLocation(Record, Idx);
S->RBraceLoc = ReadSourceLocation(Record, Idx);
}
@@ -381,6 +382,26 @@ void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) {
Constraints, Exprs, Clobbers);
}
+void ASTStmtReader::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {
+ // FIXME: Implement coroutine serialization.
+ llvm_unreachable("unimplemented");
+}
+
+void ASTStmtReader::VisitCoreturnStmt(CoreturnStmt *S) {
+ // FIXME: Implement coroutine serialization.
+ llvm_unreachable("unimplemented");
+}
+
+void ASTStmtReader::VisitCoawaitExpr(CoawaitExpr *S) {
+ // FIXME: Implement coroutine serialization.
+ llvm_unreachable("unimplemented");
+}
+
+void ASTStmtReader::VisitCoyieldExpr(CoyieldExpr *S) {
+ // FIXME: Implement coroutine serialization.
+ llvm_unreachable("unimplemented");
+}
+
void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) {
VisitStmt(S);
++Idx;
@@ -439,15 +460,17 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
NumTemplateArgs = Record[Idx++];
if (E->hasQualifier())
- E->getInternalQualifierLoc()
- = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
+ new (E->getTrailingObjects<NestedNameSpecifierLoc>())
+ NestedNameSpecifierLoc(
+ Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
if (E->hasFoundDecl())
- E->getInternalFoundDecl() = ReadDeclAs<NamedDecl>(Record, Idx);
+ *E->getTrailingObjects<NamedDecl *>() = ReadDeclAs<NamedDecl>(Record, Idx);
if (E->hasTemplateKWAndArgsInfo())
- ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(),
- NumTemplateArgs);
+ ReadTemplateKWAndArgsInfo(
+ *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
+ E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs);
E->setDecl(ReadDeclAs<ValueDecl>(Record, Idx));
E->setLocation(ReadSourceLocation(Record, Idx));
@@ -527,7 +550,6 @@ void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) {
}
void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
- typedef OffsetOfExpr::OffsetOfNode Node;
VisitExpr(E);
assert(E->getNumComponents() == Record[Idx]);
++Idx;
@@ -537,29 +559,29 @@ void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
E->setRParenLoc(ReadSourceLocation(Record, Idx));
E->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
- Node::Kind Kind = static_cast<Node::Kind>(Record[Idx++]);
+ OffsetOfNode::Kind Kind = static_cast<OffsetOfNode::Kind>(Record[Idx++]);
SourceLocation Start = ReadSourceLocation(Record, Idx);
SourceLocation End = ReadSourceLocation(Record, Idx);
switch (Kind) {
- case Node::Array:
- E->setComponent(I, Node(Start, Record[Idx++], End));
+ case OffsetOfNode::Array:
+ E->setComponent(I, OffsetOfNode(Start, Record[Idx++], End));
break;
-
- case Node::Field:
- E->setComponent(I, Node(Start, ReadDeclAs<FieldDecl>(Record, Idx), End));
+
+ case OffsetOfNode::Field:
+ E->setComponent(
+ I, OffsetOfNode(Start, ReadDeclAs<FieldDecl>(Record, Idx), End));
break;
- case Node::Identifier:
- E->setComponent(I,
- Node(Start,
- Reader.GetIdentifierInfo(F, Record, Idx),
- End));
+ case OffsetOfNode::Identifier:
+ E->setComponent(
+ I,
+ OffsetOfNode(Start, Reader.GetIdentifierInfo(F, Record, Idx), End));
break;
-
- case Node::Base: {
+
+ case OffsetOfNode::Base: {
CXXBaseSpecifier *Base = new (Reader.getContext()) CXXBaseSpecifier();
*Base = Reader.ReadCXXBaseSpecifier(F, Record, Idx);
- E->setComponent(I, Node(Base));
+ E->setComponent(I, OffsetOfNode(Base));
break;
}
}
@@ -589,6 +611,15 @@ void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
E->setRBracketLoc(ReadSourceLocation(Record, Idx));
}
+void ASTStmtReader::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) {
+ VisitExpr(E);
+ E->setBase(Reader.ReadSubExpr());
+ E->setLowerBound(Reader.ReadSubExpr());
+ E->setLength(Reader.ReadSubExpr());
+ E->setColonLoc(ReadSourceLocation(Record, Idx));
+ E->setRBracketLoc(ReadSourceLocation(Record, Idx));
+}
+
void ASTStmtReader::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
E->setNumArgs(Reader.getContext(), Record[Idx++]);
@@ -821,6 +852,7 @@ void ASTStmtReader::VisitVAArgExpr(VAArgExpr *E) {
E->setWrittenTypeInfo(GetTypeSourceInfo(Record, Idx));
E->setBuiltinLoc(ReadSourceLocation(Record, Idx));
E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setIsMicrosoftABI(Record[Idx++]);
}
void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
@@ -955,8 +987,10 @@ void ASTStmtReader::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
assert(NumElements == E->getNumElements() && "Wrong number of elements");
bool HasPackExpansions = Record[Idx++];
assert(HasPackExpansions == E->HasPackExpansions &&"Pack expansion mismatch");
- ObjCDictionaryLiteral::KeyValuePair *KeyValues = E->getKeyValues();
- ObjCDictionaryLiteral::ExpansionData *Expansions = E->getExpansionData();
+ ObjCDictionaryLiteral::KeyValuePair *KeyValues =
+ E->getTrailingObjects<ObjCDictionaryLiteral::KeyValuePair>();
+ ObjCDictionaryLiteral::ExpansionData *Expansions =
+ E->getTrailingObjects<ObjCDictionaryLiteral::ExpansionData>();
for (unsigned I = 0; I != NumElements; ++I) {
KeyValues[I].Key = Reader.ReadSubExpr();
KeyValues[I].Value = Reader.ReadSubExpr();
@@ -1168,9 +1202,10 @@ void ASTStmtReader::VisitCXXTryStmt(CXXTryStmt *S) {
void ASTStmtReader::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
VisitStmt(S);
- S->setForLoc(ReadSourceLocation(Record, Idx));
- S->setColonLoc(ReadSourceLocation(Record, Idx));
- S->setRParenLoc(ReadSourceLocation(Record, Idx));
+ S->ForLoc = ReadSourceLocation(Record, Idx);
+ S->CoawaitLoc = ReadSourceLocation(Record, Idx);
+ S->ColonLoc = ReadSourceLocation(Record, Idx);
+ S->RParenLoc = ReadSourceLocation(Record, Idx);
S->setRangeStmt(Reader.ReadSubStmt());
S->setBeginEndStmt(Reader.ReadSubStmt());
S->setCond(Reader.ReadSubExpr());
@@ -1329,10 +1364,7 @@ void ASTStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) {
void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
VisitExpr(E);
-
- assert((bool)Record[Idx] == E->Param.getInt() && "We messed up at creation ?");
- ++Idx; // HasOtherExprStored and SubExpr was handled during creation.
- E->Param.setPointer(ReadDeclAs<ParmVarDecl>(Record, Idx));
+ E->Param = ReadDeclAs<ParmVarDecl>(Record, Idx);
E->Loc = ReadSourceLocation(Record, Idx);
}
@@ -1412,7 +1444,8 @@ void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) {
unsigned NumObjects = Record[Idx++];
assert(NumObjects == E->getNumObjects());
for (unsigned i = 0; i != NumObjects; ++i)
- E->getObjectsBuffer()[i] = ReadDeclAs<BlockDecl>(Record, Idx);
+ E->getTrailingObjects<BlockDecl *>()[i] =
+ ReadDeclAs<BlockDecl>(Record, Idx);
E->SubExpr = Reader.ReadSubExpr();
}
@@ -1422,8 +1455,10 @@ ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
VisitExpr(E);
if (Record[Idx++]) // HasTemplateKWAndArgsInfo
- ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(),
- /*NumTemplateArgs=*/Record[Idx++]);
+ ReadTemplateKWAndArgsInfo(
+ *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
+ E->getTrailingObjects<TemplateArgumentLoc>(),
+ /*NumTemplateArgs=*/Record[Idx++]);
E->Base = Reader.ReadSubExpr();
E->BaseType = Reader.readType(F, Record, Idx);
@@ -1439,8 +1474,10 @@ ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
VisitExpr(E);
if (Record[Idx++]) // HasTemplateKWAndArgsInfo
- ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(),
- /*NumTemplateArgs=*/Record[Idx++]);
+ ReadTemplateKWAndArgsInfo(
+ *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
+ E->getTrailingObjects<TemplateArgumentLoc>(),
+ /*NumTemplateArgs=*/Record[Idx++]);
E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
ReadDeclarationNameInfo(E->NameInfo, Record, Idx);
@@ -1462,7 +1499,8 @@ void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) {
VisitExpr(E);
if (Record[Idx++]) // HasTemplateKWAndArgsInfo
- ReadTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo(),
+ ReadTemplateKWAndArgsInfo(*E->getTrailingASTTemplateKWAndArgsInfo(),
+ E->getTrailingTemplateArgumentLoc(),
/*NumTemplateArgs=*/Record[Idx++]);
unsigned NumDecls = Record[Idx++];
@@ -1503,7 +1541,7 @@ void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) {
E->Loc = Range.getBegin();
E->RParenLoc = Range.getEnd();
- TypeSourceInfo **Args = E->getTypeSourceInfos();
+ TypeSourceInfo **Args = E->getTrailingObjects<TypeSourceInfo *>();
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
Args[I] = GetTypeSourceInfo(Record, Idx);
}
@@ -1544,11 +1582,20 @@ void ASTStmtReader::VisitPackExpansionExpr(PackExpansionExpr *E) {
void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
VisitExpr(E);
+ unsigned NumPartialArgs = Record[Idx++];
E->OperatorLoc = ReadSourceLocation(Record, Idx);
E->PackLoc = ReadSourceLocation(Record, Idx);
E->RParenLoc = ReadSourceLocation(Record, Idx);
- E->Length = Record[Idx++];
- E->Pack = ReadDeclAs<NamedDecl>(Record, Idx);
+ E->Pack = Reader.ReadDeclAs<NamedDecl>(F, Record, Idx);
+ if (E->isPartiallySubstituted()) {
+ assert(E->Length == NumPartialArgs);
+ for (auto *I = E->getTrailingObjects<TemplateArgument>(),
+ *E = I + NumPartialArgs;
+ I != E; ++I)
+ new (I) TemplateArgument(Reader.ReadTemplateArgument(F, Record, Idx));
+ } else if (!E->isValueDependent()) {
+ E->Length = Record[Idx++];
+ }
}
void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr(
@@ -1577,7 +1624,7 @@ void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
E->NumParameters = Record[Idx++];
E->ParamPack = ReadDeclAs<ParmVarDecl>(Record, Idx);
E->NameLoc = ReadSourceLocation(Record, Idx);
- ParmVarDecl **Parms = reinterpret_cast<ParmVarDecl**>(E+1);
+ ParmVarDecl **Parms = E->getTrailingObjects<ParmVarDecl *>();
for (unsigned i = 0, n = E->NumParameters; i != n; ++i)
Parms[i] = ReadDeclAs<ParmVarDecl>(Record, Idx);
}
@@ -1622,6 +1669,13 @@ void ASTStmtReader::VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
E->TheDecl = ReadDeclAs<MSPropertyDecl>(Record, Idx);
}
+void ASTStmtReader::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) {
+ VisitExpr(E);
+ E->setBase(Reader.ReadSubExpr());
+ E->setIdx(Reader.ReadSubExpr());
+ E->setRBracketLoc(ReadSourceLocation(Record, Idx));
+}
+
void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
VisitExpr(E);
E->setSourceRange(ReadSourceRange(Record, Idx));
@@ -1716,6 +1770,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_safelen:
C = new (Context) OMPSafelenClause();
break;
+ case OMPC_simdlen:
+ C = new (Context) OMPSimdlenClause();
+ break;
case OMPC_collapse:
C = new (Context) OMPCollapseClause();
break;
@@ -1755,6 +1812,15 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_seq_cst:
C = new (Context) OMPSeqCstClause();
break;
+ case OMPC_threads:
+ C = new (Context) OMPThreadsClause();
+ break;
+ case OMPC_simd:
+ C = new (Context) OMPSIMDClause();
+ break;
+ case OMPC_nogroup:
+ C = new (Context) OMPNogroupClause();
+ break;
case OMPC_private:
C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]);
break;
@@ -1788,6 +1854,30 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_depend:
C = OMPDependClause::CreateEmpty(Context, Record[Idx++]);
break;
+ case OMPC_device:
+ C = new (Context) OMPDeviceClause();
+ break;
+ case OMPC_map:
+ C = OMPMapClause::CreateEmpty(Context, Record[Idx++]);
+ break;
+ case OMPC_num_teams:
+ C = new (Context) OMPNumTeamsClause();
+ break;
+ case OMPC_thread_limit:
+ C = new (Context) OMPThreadLimitClause();
+ break;
+ case OMPC_priority:
+ C = new (Context) OMPPriorityClause();
+ break;
+ case OMPC_grainsize:
+ C = new (Context) OMPGrainsizeClause();
+ break;
+ case OMPC_num_tasks:
+ C = new (Context) OMPNumTasksClause();
+ break;
+ case OMPC_hint:
+ C = new (Context) OMPHintClause();
+ break;
}
Visit(C);
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
@@ -1797,6 +1887,9 @@ OMPClause *OMPClauseReader::readClause() {
}
void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) {
+ C->setNameModifier(static_cast<OpenMPDirectiveKind>(Record[Idx++]));
+ C->setNameModifierLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
C->setCondition(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}
@@ -1816,6 +1909,11 @@ void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}
+void OMPClauseReader::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
+ C->setSimdlen(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
void OMPClauseReader::VisitOMPCollapseClause(OMPCollapseClause *C) {
C->setNumForLoops(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
@@ -1838,14 +1936,23 @@ void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) {
void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) {
C->setScheduleKind(
static_cast<OpenMPScheduleClauseKind>(Record[Idx++]));
+ C->setFirstScheduleModifier(
+ static_cast<OpenMPScheduleClauseModifier>(Record[Idx++]));
+ C->setSecondScheduleModifier(
+ static_cast<OpenMPScheduleClauseModifier>(Record[Idx++]));
C->setChunkSize(Reader->Reader.ReadSubExpr());
C->setHelperChunkSize(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setFirstScheduleModifierLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setSecondScheduleModifierLoc(Reader->ReadSourceLocation(Record, Idx));
C->setScheduleKindLoc(Reader->ReadSourceLocation(Record, Idx));
C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx));
}
-void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *) {}
+void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *C) {
+ C->setNumForLoops(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
void OMPClauseReader::VisitOMPNowaitClause(OMPNowaitClause *) {}
@@ -1863,6 +1970,12 @@ void OMPClauseReader::VisitOMPCaptureClause(OMPCaptureClause *) {}
void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
+void OMPClauseReader::VisitOMPThreadsClause(OMPThreadsClause *) {}
+
+void OMPClauseReader::VisitOMPSIMDClause(OMPSIMDClause *) {}
+
+void OMPClauseReader::VisitOMPNogroupClause(OMPNogroupClause *) {}
+
void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
unsigned NumVars = C->varlist_size();
@@ -1950,6 +2063,10 @@ void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) {
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setPrivates(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
C->setLHSExprs(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
@@ -1964,6 +2081,8 @@ void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) {
void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setModifier(static_cast<OpenMPLinearClauseKind>(Record[Idx++]));
+ C->setModifierLoc(Reader->ReadSourceLocation(Record, Idx));
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
@@ -1973,6 +2092,10 @@ void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setPrivates(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
C->setInits(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
@@ -2065,6 +2188,58 @@ void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
C->setVarRefs(Vars);
}
+void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ C->setDevice(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
+void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) {
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setMapTypeModifier(
+ static_cast<OpenMPMapClauseKind>(Record[Idx++]));
+ C->setMapType(
+ static_cast<OpenMPMapClauseKind>(Record[Idx++]));
+ C->setMapLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
+ auto NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i) {
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ }
+ C->setVarRefs(Vars);
+}
+
+void OMPClauseReader::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) {
+ C->setNumTeams(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
+void OMPClauseReader::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) {
+ C->setThreadLimit(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
+void OMPClauseReader::VisitOMPPriorityClause(OMPPriorityClause *C) {
+ C->setPriority(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
+void OMPClauseReader::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
+ C->setGrainsize(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
+void OMPClauseReader::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
+ C->setNumTasks(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
+void OMPClauseReader::VisitOMPHintClause(OMPHintClause *C) {
+ C->setHint(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
@@ -2110,6 +2285,10 @@ void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) {
Sub.clear();
for (unsigned i = 0; i < CollapsedNum; ++i)
Sub.push_back(Reader.ReadSubExpr());
+ D->setPrivateCounters(Sub);
+ Sub.clear();
+ for (unsigned i = 0; i < CollapsedNum; ++i)
+ Sub.push_back(Reader.ReadSubExpr());
D->setInits(Sub);
Sub.clear();
for (unsigned i = 0; i < CollapsedNum; ++i)
@@ -2126,6 +2305,7 @@ void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) {
// The NumClauses field was read in ReadStmtFromStream.
++Idx;
VisitOMPExecutableDirective(D);
+ D->setHasCancel(Record[Idx++]);
}
void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) {
@@ -2134,6 +2314,7 @@ void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) {
void ASTStmtReader::VisitOMPForDirective(OMPForDirective *D) {
VisitOMPLoopDirective(D);
+ D->setHasCancel(Record[Idx++]);
}
void ASTStmtReader::VisitOMPForSimdDirective(OMPForSimdDirective *D) {
@@ -2145,11 +2326,13 @@ void ASTStmtReader::VisitOMPSectionsDirective(OMPSectionsDirective *D) {
// The NumClauses field was read in ReadStmtFromStream.
++Idx;
VisitOMPExecutableDirective(D);
+ D->setHasCancel(Record[Idx++]);
}
void ASTStmtReader::VisitOMPSectionDirective(OMPSectionDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
+ D->setHasCancel(Record[Idx++]);
}
void ASTStmtReader::VisitOMPSingleDirective(OMPSingleDirective *D) {
@@ -2166,12 +2349,15 @@ void ASTStmtReader::VisitOMPMasterDirective(OMPMasterDirective *D) {
void ASTStmtReader::VisitOMPCriticalDirective(OMPCriticalDirective *D) {
VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ ++Idx;
VisitOMPExecutableDirective(D);
ReadDeclarationNameInfo(D->DirName, Record, Idx);
}
void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) {
VisitOMPLoopDirective(D);
+ D->setHasCancel(Record[Idx++]);
}
void ASTStmtReader::VisitOMPParallelForSimdDirective(
@@ -2185,6 +2371,7 @@ void ASTStmtReader::VisitOMPParallelSectionsDirective(
// The NumClauses field was read in ReadStmtFromStream.
++Idx;
VisitOMPExecutableDirective(D);
+ D->setHasCancel(Record[Idx++]);
}
void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) {
@@ -2192,6 +2379,7 @@ void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) {
// The NumClauses field was read in ReadStmtFromStream.
++Idx;
VisitOMPExecutableDirective(D);
+ D->setHasCancel(Record[Idx++]);
}
void ASTStmtReader::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) {
@@ -2223,6 +2411,8 @@ void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) {
void ASTStmtReader::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ ++Idx;
VisitOMPExecutableDirective(D);
}
@@ -2246,6 +2436,12 @@ void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) {
VisitOMPExecutableDirective(D);
}
+void ASTStmtReader::VisitOMPTargetDataDirective(OMPTargetDataDirective *D) {
+ VisitStmt(D);
+ ++Idx;
+ VisitOMPExecutableDirective(D);
+}
+
void ASTStmtReader::VisitOMPTeamsDirective(OMPTeamsDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
@@ -2262,10 +2458,24 @@ void ASTStmtReader::VisitOMPCancellationPointDirective(
void ASTStmtReader::VisitOMPCancelDirective(OMPCancelDirective *D) {
VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ ++Idx;
VisitOMPExecutableDirective(D);
D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record[Idx++]));
}
+void ASTStmtReader::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void ASTStmtReader::VisitOMPTaskLoopSimdDirective(OMPTaskLoopSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void ASTStmtReader::VisitOMPDistributeDirective(OMPDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
//===----------------------------------------------------------------------===//
// ASTReader Implementation
//===----------------------------------------------------------------------===//
@@ -2497,6 +2707,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = new (Context) ArraySubscriptExpr(Empty);
break;
+ case EXPR_OMP_ARRAY_SECTION:
+ S = new (Context) OMPArraySectionExpr(Empty);
+ break;
+
case EXPR_CALL:
S = new (Context) CallExpr(Context, Stmt::CallExprClass, Empty);
break;
@@ -2800,7 +3014,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_OMP_CRITICAL_DIRECTIVE:
- S = OMPCriticalDirective::CreateEmpty(Context, Empty);
+ S = OMPCriticalDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
case STMT_OMP_PARALLEL_FOR_DIRECTIVE: {
@@ -2851,7 +3066,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_OMP_ORDERED_DIRECTIVE:
- S = OMPOrderedDirective::CreateEmpty(Context, Empty);
+ S = OMPOrderedDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
case STMT_OMP_ATOMIC_DIRECTIVE:
@@ -2864,6 +3080,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
+ case STMT_OMP_TARGET_DATA_DIRECTIVE:
+ S = OMPTargetDataDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
case STMT_OMP_TEAMS_DIRECTIVE:
S = OMPTeamsDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);
@@ -2874,9 +3095,34 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_OMP_CANCEL_DIRECTIVE:
- S = OMPCancelDirective::CreateEmpty(Context, Empty);
+ S = OMPCancelDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
+ case STMT_OMP_TASKLOOP_DIRECTIVE: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPTaskLoopDirective::CreateEmpty(Context, NumClauses, CollapsedNum,
+ Empty);
+ break;
+ }
+
+ case STMT_OMP_TASKLOOP_SIMD_DIRECTIVE: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPTaskLoopSimdDirective::CreateEmpty(Context, NumClauses,
+ CollapsedNum, Empty);
+ break;
+ }
+
+ case STMT_OMP_DISTRIBUTE_DIRECTIVE: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPDistributeDirective::CreateEmpty(Context, NumClauses, CollapsedNum,
+ Empty);
+ break;
+ }
+
case EXPR_CXX_OPERATOR_CALL:
S = new (Context) CXXOperatorCallExpr(Context, Empty);
break;
@@ -2944,6 +3190,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_CXX_PROPERTY_REF_EXPR:
S = new (Context) MSPropertyRefExpr(Empty);
break;
+ case EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR:
+ S = new (Context) MSPropertySubscriptExpr(Empty);
+ break;
case EXPR_CXX_UUIDOF_TYPE:
S = new (Context) CXXUuidofExpr(Empty, false);
break;
@@ -2953,16 +3202,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_CXX_THROW:
S = new (Context) CXXThrowExpr(Empty);
break;
- case EXPR_CXX_DEFAULT_ARG: {
- bool HasOtherExprStored = Record[ASTStmtReader::NumExprFields];
- if (HasOtherExprStored) {
- Expr *SubExpr = ReadSubExpr();
- S = CXXDefaultArgExpr::Create(Context, SourceLocation(), nullptr,
- SubExpr);
- } else
- S = new (Context) CXXDefaultArgExpr(Empty);
+ case EXPR_CXX_DEFAULT_ARG:
+ S = new (Context) CXXDefaultArgExpr(Empty);
break;
- }
case EXPR_CXX_DEFAULT_INIT:
S = new (Context) CXXDefaultInitExpr(Empty);
break;
@@ -3047,7 +3289,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_SIZEOF_PACK:
- S = new (Context) SizeOfPackExpr(Empty);
+ S = SizeOfPackExpr::CreateDeserialized(
+ Context,
+ /*NumPartialArgs=*/Record[ASTStmtReader::NumExprFields]);
break;
case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM:
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
index 8b68638..ec04cd6 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
@@ -1,4 +1,4 @@
-//===--- ASTWriter.cpp - AST File Writer ----------------------------------===//
+//===--- ASTWriter.cpp - AST File Writer ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,7 +12,10 @@
//===----------------------------------------------------------------------===//
#include "clang/Serialization/ASTWriter.h"
+#include "clang/Serialization/ModuleFileExtension.h"
#include "ASTCommon.h"
+#include "ASTReaderInternals.h"
+#include "MultiOnDiskHashTable.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
@@ -41,6 +44,7 @@
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Sema/Sema.h"
#include "clang/Serialization/ASTReader.h"
+#include "clang/Serialization/SerializationDiagnostic.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/Hashing.h"
@@ -56,6 +60,7 @@
#include <cstdio>
#include <string.h>
#include <utility>
+
using namespace clang;
using namespace clang::serialization;
@@ -98,7 +103,7 @@ namespace {
#define ABSTRACT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"
};
-}
+} // end anonymous namespace
void ASTTypeWriter::VisitBuiltinType(const BuiltinType *T) {
llvm_unreachable("Built-in types are never serialized");
@@ -277,7 +282,7 @@ void ASTTypeWriter::VisitUnaryTransformType(const UnaryTransformType *T) {
void ASTTypeWriter::VisitAutoType(const AutoType *T) {
Writer.AddTypeRef(T->getDeducedType(), Record);
- Record.push_back(T->isDecltypeAuto());
+ Record.push_back((unsigned)T->getKeyword());
if (T->getDeducedType().isNull())
Record.push_back(T->isDependentType());
Code = TYPE_AUTO;
@@ -329,9 +334,8 @@ ASTTypeWriter::VisitTemplateSpecializationType(
Record.push_back(T->isDependentType());
Writer.AddTemplateName(T->getTemplateName(), Record);
Record.push_back(T->getNumArgs());
- for (TemplateSpecializationType::iterator ArgI = T->begin(), ArgE = T->end();
- ArgI != ArgE; ++ArgI)
- Writer.AddTemplateArgument(*ArgI, Record);
+ for (const auto &ArgI : *T)
+ Writer.AddTemplateArgument(ArgI, Record);
Writer.AddTypeRef(T->isTypeAlias() ? T->getAliasedType() :
T->isCanonicalUnqualified() ? QualType()
: T->getCanonicalTypeInternal(),
@@ -381,9 +385,8 @@ ASTTypeWriter::VisitDependentTemplateSpecializationType(
Writer.AddNestedNameSpecifier(T->getQualifier(), Record);
Writer.AddIdentifierRef(T->getIdentifier(), Record);
Record.push_back(T->getNumArgs());
- for (DependentTemplateSpecializationType::iterator
- I = T->begin(), E = T->end(); I != E; ++I)
- Writer.AddTemplateArgument(*I, Record);
+ for (const auto &I : *T)
+ Writer.AddTemplateArgument(I, Record);
Code = TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION;
}
@@ -443,6 +446,12 @@ ASTTypeWriter::VisitAtomicType(const AtomicType *T) {
Code = TYPE_ATOMIC;
}
+void
+ASTTypeWriter::VisitPipeType(const PipeType *T) {
+ Writer.AddTypeRef(T->getElementType(), Record);
+ Code = TYPE_PIPE;
+}
+
namespace {
class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
@@ -462,7 +471,7 @@ public:
void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);
};
-}
+} // end anonymous namespace
void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
// nothing to do
@@ -669,6 +678,9 @@ void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
Writer.AddSourceLocation(TL.getLParenLoc(), Record);
Writer.AddSourceLocation(TL.getRParenLoc(), Record);
}
+void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getKWLoc(), Record);
+}
void ASTWriter::WriteTypeAbbrevs() {
using namespace llvm;
@@ -875,15 +887,17 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(METADATA);
RECORD(SIGNATURE);
RECORD(MODULE_NAME);
+ RECORD(MODULE_DIRECTORY);
RECORD(MODULE_MAP_FILE);
RECORD(IMPORTS);
- RECORD(KNOWN_MODULE_FILES);
- RECORD(LANGUAGE_OPTIONS);
- RECORD(TARGET_OPTIONS);
RECORD(ORIGINAL_FILE);
RECORD(ORIGINAL_PCH_DIR);
RECORD(ORIGINAL_FILE_ID);
RECORD(INPUT_FILE_OFFSETS);
+
+ BLOCK(OPTIONS_BLOCK);
+ RECORD(LANGUAGE_OPTIONS);
+ RECORD(TARGET_OPTIONS);
RECORD(DIAGNOSTIC_OPTIONS);
RECORD(FILE_SYSTEM_OPTIONS);
RECORD(HEADER_SEARCH_OPTIONS);
@@ -902,17 +916,17 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(SPECIAL_TYPES);
RECORD(STATISTICS);
RECORD(TENTATIVE_DEFINITIONS);
- RECORD(UNUSED_FILESCOPED_DECLS);
RECORD(SELECTOR_OFFSETS);
RECORD(METHOD_POOL);
RECORD(PP_COUNTER_VALUE);
RECORD(SOURCE_LOCATION_OFFSETS);
RECORD(SOURCE_LOCATION_PRELOADS);
RECORD(EXT_VECTOR_DECLS);
+ RECORD(UNUSED_FILESCOPED_DECLS);
RECORD(PPD_ENTITIES_OFFSETS);
+ RECORD(VTABLE_USES);
RECORD(REFERENCED_SELECTOR_POOL);
RECORD(TU_UPDATE_LEXICAL);
- RECORD(LOCAL_REDECLARATIONS_MAP);
RECORD(SEMA_DECL_REFS);
RECORD(WEAK_UNDECLARED_IDENTIFIERS);
RECORD(PENDING_IMPLICIT_INSTANTIATIONS);
@@ -928,17 +942,20 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(OPENCL_EXTENSIONS);
RECORD(DELEGATING_CTORS);
RECORD(KNOWN_NAMESPACES);
- RECORD(UNDEFINED_BUT_USED);
RECORD(MODULE_OFFSET_MAP);
RECORD(SOURCE_MANAGER_LINE_TABLE);
RECORD(OBJC_CATEGORIES_MAP);
RECORD(FILE_SORTED_DECLS);
RECORD(IMPORTED_MODULES);
- RECORD(LOCAL_REDECLARATIONS);
RECORD(OBJC_CATEGORIES);
RECORD(MACRO_OFFSET);
+ RECORD(INTERESTING_IDENTIFIERS);
+ RECORD(UNDEFINED_BUT_USED);
RECORD(LATE_PARSED_TEMPLATE);
RECORD(OPTIMIZE_PRAGMA_OPTIONS);
+ RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES);
+ RECORD(CXX_CTOR_INITIALIZERS_OFFSETS);
+ RECORD(DELETE_EXPRS_TO_ANALYZE);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@@ -955,6 +972,29 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(PP_MODULE_MACRO);
RECORD(PP_TOKEN);
+ // Submodule Block.
+ BLOCK(SUBMODULE_BLOCK);
+ RECORD(SUBMODULE_METADATA);
+ RECORD(SUBMODULE_DEFINITION);
+ RECORD(SUBMODULE_UMBRELLA_HEADER);
+ RECORD(SUBMODULE_HEADER);
+ RECORD(SUBMODULE_TOPHEADER);
+ RECORD(SUBMODULE_UMBRELLA_DIR);
+ RECORD(SUBMODULE_IMPORTS);
+ RECORD(SUBMODULE_EXPORTS);
+ RECORD(SUBMODULE_REQUIRES);
+ RECORD(SUBMODULE_EXCLUDED_HEADER);
+ RECORD(SUBMODULE_LINK_LIBRARY);
+ RECORD(SUBMODULE_CONFIG_MACRO);
+ RECORD(SUBMODULE_CONFLICT);
+ RECORD(SUBMODULE_PRIVATE_HEADER);
+ RECORD(SUBMODULE_TEXTUAL_HEADER);
+ RECORD(SUBMODULE_PRIVATE_TEXTUAL_HEADER);
+
+ // Comments Block.
+ BLOCK(COMMENTS_BLOCK);
+ RECORD(COMMENTS_RAW_COMMENT);
+
// Decls and Types block.
BLOCK(DECLTYPES_BLOCK);
RECORD(TYPE_EXT_QUAL);
@@ -998,6 +1038,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(TYPE_ATOMIC);
RECORD(TYPE_DECAYED);
RECORD(TYPE_ADJUSTED);
+ RECORD(LOCAL_REDECLARATIONS);
RECORD(DECL_TYPEDEF);
RECORD(DECL_TYPEALIAS);
RECORD(DECL_ENUM);
@@ -1062,7 +1103,11 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(PPD_MACRO_EXPANSION);
RECORD(PPD_MACRO_DEFINITION);
RECORD(PPD_INCLUSION_DIRECTIVE);
-
+
+ // Decls and Types block.
+ BLOCK(EXTENSION_BLOCK);
+ RECORD(EXTENSION_METADATA);
+
#undef RECORD
#undef BLOCK
Stream.ExitBlock();
@@ -1074,14 +1119,8 @@ void ASTWriter::WriteBlockInfoBlock() {
/// \return \c true if the path was changed.
static bool cleanPathForOutput(FileManager &FileMgr,
SmallVectorImpl<char> &Path) {
- bool Changed = false;
-
- if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
- llvm::sys::fs::make_absolute(Path);
- Changed = true;
- }
-
- return Changed | FileMgr.removeDotPaths(Path);
+ bool Changed = FileMgr.makeAbsolutePath(Path);
+ return Changed | llvm::sys::path::remove_dots(Path);
}
/// \brief Adjusts the given filename to only write out the portion of the
@@ -1140,69 +1179,78 @@ static ASTFileSignature getSignature() {
}
/// \brief Write the control block.
-void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
- StringRef isysroot,
- const std::string &OutputFile) {
+uint64_t ASTWriter::WriteControlBlock(Preprocessor &PP,
+ ASTContext &Context,
+ StringRef isysroot,
+ const std::string &OutputFile) {
+ ASTFileSignature Signature = 0;
+
using namespace llvm;
Stream.EnterSubblock(CONTROL_BLOCK_ID, 5);
RecordData Record;
// Metadata
- BitCodeAbbrev *MetadataAbbrev = new BitCodeAbbrev();
+ auto *MetadataAbbrev = new BitCodeAbbrev();
MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA));
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Major
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Minor
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang maj.
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min.
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable
+ MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
unsigned MetadataAbbrevCode = Stream.EmitAbbrev(MetadataAbbrev);
- Record.push_back(METADATA);
- Record.push_back(VERSION_MAJOR);
- Record.push_back(VERSION_MINOR);
- Record.push_back(CLANG_VERSION_MAJOR);
- Record.push_back(CLANG_VERSION_MINOR);
assert((!WritingModule || isysroot.empty()) &&
"writing module as a relocatable PCH?");
- Record.push_back(!isysroot.empty());
- Record.push_back(ASTHasCompilerErrors);
- Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
- getClangFullRepositoryVersion());
-
+ {
+ RecordData::value_type Record[] = {METADATA, VERSION_MAJOR, VERSION_MINOR,
+ CLANG_VERSION_MAJOR, CLANG_VERSION_MINOR,
+ !isysroot.empty(), IncludeTimestamps,
+ ASTHasCompilerErrors};
+ Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
+ getClangFullRepositoryVersion());
+ }
if (WritingModule) {
// For implicit modules we output a signature that we can use to ensure
// duplicate module builds don't collide in the cache as their output order
// is non-deterministic.
// FIXME: Remove this when output is deterministic.
if (Context.getLangOpts().ImplicitModules) {
- Record.clear();
- Record.push_back(getSignature());
+ Signature = getSignature();
+ RecordData::value_type Record[] = {Signature};
Stream.EmitRecord(SIGNATURE, Record);
}
// Module name
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
- RecordData Record;
- Record.push_back(MODULE_NAME);
+ RecordData::value_type Record[] = {MODULE_NAME};
Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name);
}
if (WritingModule && WritingModule->Directory) {
- // Module directory.
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory
- unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
- RecordData Record;
- Record.push_back(MODULE_DIRECTORY);
-
SmallString<128> BaseDir(WritingModule->Directory->getName());
cleanPathForOutput(Context.getSourceManager().getFileManager(), BaseDir);
- Stream.EmitRecordWithBlob(AbbrevCode, Record, BaseDir);
+
+ // If the home of the module is the current working directory, then we
+ // want to pick up the cwd of the build process loading the module, not
+ // our cwd, when we load this module.
+ if (!PP.getHeaderSearchInfo()
+ .getHeaderSearchOpts()
+ .ModuleMapFileHomeIsCwd ||
+ WritingModule->Directory->getName() != StringRef(".")) {
+ // Module directory.
+ auto *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory
+ unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
+
+ RecordData::value_type Record[] = {MODULE_DIRECTORY};
+ Stream.EmitRecordWithBlob(AbbrevCode, Record, BaseDir);
+ }
// Write out all other paths relative to the base directory if possible.
BaseDirectory.assign(BaseDir.begin(), BaseDir.end());
@@ -1246,22 +1294,16 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Record.push_back((unsigned)M->Kind); // FIXME: Stable encoding
AddSourceLocation(M->ImportLoc, Record);
Record.push_back(M->File->getSize());
- Record.push_back(M->File->getModificationTime());
+ Record.push_back(getTimestampForOutput(M->File));
Record.push_back(M->Signature);
AddPath(M->FileName, Record);
}
Stream.EmitRecord(IMPORTS, Record);
-
- // Also emit a list of known module files that were not imported,
- // but are made available by this module.
- // FIXME: Should we also include a signature here?
- Record.clear();
- for (auto *E : Mgr.getAdditionalKnownModuleFiles())
- AddPath(E->getName(), Record);
- if (!Record.empty())
- Stream.EmitRecord(KNOWN_MODULE_FILES, Record);
}
+ // Write the options block.
+ Stream.EnterSubblock(OPTIONS_BLOCK_ID, 4);
+
// Language options.
Record.clear();
const LangOptions &LangOpts = Context.getLangOpts();
@@ -1285,14 +1327,18 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
// Comment options.
Record.push_back(LangOpts.CommentOpts.BlockCommandNames.size());
- for (CommentOptions::BlockCommandNamesTy::const_iterator
- I = LangOpts.CommentOpts.BlockCommandNames.begin(),
- IEnd = LangOpts.CommentOpts.BlockCommandNames.end();
- I != IEnd; ++I) {
- AddString(*I, Record);
+ for (const auto &I : LangOpts.CommentOpts.BlockCommandNames) {
+ AddString(I, Record);
}
Record.push_back(LangOpts.CommentOpts.ParseAllComments);
+ // OpenMP offloading options.
+ Record.push_back(LangOpts.OMPTargetTriples.size());
+ for (auto &T : LangOpts.OMPTargetTriples)
+ AddString(T.getTriple(), Record);
+
+ AddString(LangOpts.OMPHostIRFile, Record);
+
Stream.EmitRecord(LANGUAGE_OPTIONS, Record);
// Target options.
@@ -1332,8 +1378,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
// File system options.
Record.clear();
- const FileSystemOptions &FSOpts
- = Context.getSourceManager().getFileManager().getFileSystemOptions();
+ const FileSystemOptions &FSOpts =
+ Context.getSourceManager().getFileManager().getFileSystemOpts();
AddString(FSOpts.WorkingDir, Record);
Stream.EmitRecord(FILE_SYSTEM_OPTIONS, Record);
@@ -1401,10 +1447,13 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Record.push_back(static_cast<unsigned>(PPOpts.ObjCXXARCStandardLibrary));
Stream.EmitRecord(PREPROCESSOR_OPTIONS, Record);
+ // Leave the options block.
+ Stream.ExitBlock();
+
// Original file name and file ID
SourceManager &SM = Context.getSourceManager();
if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
- BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev();
+ auto *FileAbbrev = new BitCodeAbbrev();
FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE));
FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File ID
FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
@@ -1422,18 +1471,17 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
// Original PCH directory
if (!OutputFile.empty() && OutputFile != "-") {
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(ORIGINAL_PCH_DIR));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
SmallString<128> OutputPath(OutputFile);
- llvm::sys::fs::make_absolute(OutputPath);
+ SM.getFileManager().makeAbsolutePath(OutputPath);
StringRef origDir = llvm::sys::path::parent_path(OutputPath);
- RecordData Record;
- Record.push_back(ORIGINAL_PCH_DIR);
+ RecordData::value_type Record[] = {ORIGINAL_PCH_DIR};
Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir);
}
@@ -1441,6 +1489,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
PP.getHeaderSearchInfo().getHeaderSearchOpts(),
PP.getLangOpts().Modules);
Stream.ExitBlock();
+ return Signature;
}
namespace {
@@ -1448,24 +1497,25 @@ namespace {
struct InputFileEntry {
const FileEntry *File;
bool IsSystemFile;
+ bool IsTransient;
bool BufferOverridden;
};
-}
+} // end anonymous namespace
void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
HeaderSearchOptions &HSOpts,
bool Modules) {
using namespace llvm;
Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4);
- RecordData Record;
-
+
// Create input-file abbreviation.
- BitCodeAbbrev *IFAbbrev = new BitCodeAbbrev();
+ auto *IFAbbrev = new BitCodeAbbrev();
IFAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE));
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Overridden
+ IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Transient
IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
unsigned IFAbbrevCode = Stream.EmitAbbrev(IFAbbrev);
@@ -1487,6 +1537,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
InputFileEntry Entry;
Entry.File = Cache->OrigEntry;
Entry.IsSystemFile = Cache->IsSystemFile;
+ Entry.IsTransient = Cache->IsTransient;
Entry.BufferOverridden = Cache->BufferOverridden;
if (Cache->IsSystemFile)
SortedFiles.push_back(Entry);
@@ -1497,10 +1548,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
unsigned UserFilesNum = 0;
// Write out all of the input files.
std::vector<uint64_t> InputFileOffsets;
- for (std::deque<InputFileEntry>::iterator
- I = SortedFiles.begin(), E = SortedFiles.end(); I != E; ++I) {
- const InputFileEntry &Entry = *I;
-
+ for (const auto &Entry : SortedFiles) {
uint32_t &InputFileID = InputFileIDs[Entry.File];
if (InputFileID != 0)
continue; // already recorded this file.
@@ -1513,16 +1561,15 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
if (!Entry.IsSystemFile)
++UserFilesNum;
- Record.clear();
- Record.push_back(INPUT_FILE);
- Record.push_back(InputFileOffsets.size());
-
// Emit size/modification time for this file.
- Record.push_back(Entry.File->getSize());
- Record.push_back(Entry.File->getModificationTime());
-
- // Whether this file was overridden.
- Record.push_back(Entry.BufferOverridden);
+ // And whether this file was overridden.
+ RecordData::value_type Record[] = {
+ INPUT_FILE,
+ InputFileOffsets.size(),
+ (uint64_t)Entry.File->getSize(),
+ (uint64_t)getTimestampForOutput(Entry.File),
+ Entry.BufferOverridden,
+ Entry.IsTransient};
EmitRecordWithPath(IFAbbrevCode, Record, Entry.File->getName());
}
@@ -1530,7 +1577,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
Stream.ExitBlock();
// Create input file offsets abbreviation.
- BitCodeAbbrev *OffsetsAbbrev = new BitCodeAbbrev();
+ auto *OffsetsAbbrev = new BitCodeAbbrev();
OffsetsAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_OFFSETS));
OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # input files
OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # non-system
@@ -1539,10 +1586,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
unsigned OffsetsAbbrevCode = Stream.EmitAbbrev(OffsetsAbbrev);
// Write input file offsets.
- Record.clear();
- Record.push_back(INPUT_FILE_OFFSETS);
- Record.push_back(InputFileOffsets.size());
- Record.push_back(UserFilesNum);
+ RecordData::value_type Record[] = {INPUT_FILE_OFFSETS,
+ InputFileOffsets.size(), UserFilesNum};
Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, bytes(InputFileOffsets));
}
@@ -1554,7 +1599,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
/// file.
static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_FILE_ENTRY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
@@ -1572,7 +1618,8 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
/// buffer.
static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_ENTRY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
@@ -1586,7 +1633,8 @@ static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
/// buffer's blob.
static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream) {
using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_BLOB));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
return Stream.EmitAbbrev(Abbrev);
@@ -1596,7 +1644,8 @@ static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream) {
/// expansion.
static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) {
using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_EXPANSION_ENTRY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
@@ -1631,27 +1680,25 @@ namespace {
typedef unsigned hash_value_type;
typedef unsigned offset_type;
- static hash_value_type ComputeHash(key_type_ref key) {
+ hash_value_type ComputeHash(key_type_ref key) {
// The hash is based only on size/time of the file, so that the reader can
// match even when symlinking or excess path elements ("foo/../", "../")
// change the form of the name. However, complete path is still the key.
- //
- // FIXME: Using the mtime here will cause problems for explicit module
- // imports.
return llvm::hash_combine(key.FE->getSize(),
- key.FE->getModificationTime());
+ Writer.getTimestampForOutput(key.FE));
}
std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
using namespace llvm::support;
- endian::Writer<little> Writer(Out);
+ endian::Writer<little> LE(Out);
unsigned KeyLen = strlen(key.Filename) + 1 + 8 + 8;
- Writer.write<uint16_t>(KeyLen);
+ LE.write<uint16_t>(KeyLen);
unsigned DataLen = 1 + 2 + 4 + 4;
- if (Data.isModuleHeader)
- DataLen += 4;
- Writer.write<uint8_t>(DataLen);
+ for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE))
+ if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule()))
+ DataLen += 4;
+ LE.write<uint8_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
@@ -1660,7 +1707,7 @@ namespace {
endian::Writer<little> LE(Out);
LE.write<uint64_t>(key.FE->getSize());
KeyLen -= 8;
- LE.write<uint64_t>(key.FE->getModificationTime());
+ LE.write<uint64_t>(Writer.getTimestampForOutput(key.FE));
KeyLen -= 8;
Out.write(key.Filename, KeyLen);
}
@@ -1671,11 +1718,9 @@ namespace {
endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
- unsigned char Flags = (Data.HeaderRole << 6)
- | (Data.isImport << 5)
- | (Data.isPragmaOnce << 4)
- | (Data.DirInfo << 2)
- | (Data.Resolved << 1)
+ unsigned char Flags = (Data.isImport << 4)
+ | (Data.isPragmaOnce << 3)
+ | (Data.DirInfo << 1)
| Data.IndexHeaderMapHeader;
LE.write<uint8_t>(Flags);
LE.write<uint16_t>(Data.NumIncludes);
@@ -1702,9 +1747,15 @@ namespace {
}
LE.write<uint32_t>(Offset);
- if (Data.isModuleHeader) {
- Module *Mod = HS.findModuleForHeader(key.FE).getModule();
- LE.write<uint32_t>(Writer.getExistingSubmoduleID(Mod));
+ // FIXME: If the header is excluded, we should write out some
+ // record of that fact.
+ for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE)) {
+ if (uint32_t ModID =
+ Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) {
+ uint32_t Value = (ModID << 2) | (unsigned)ModInfo.getRole();
+ assert((Value >> 2) == ModID && "overflow in header module info");
+ LE.write<uint32_t>(Value);
+ }
}
assert(Out.tell() - Start == DataLen && "Wrong data length");
@@ -1734,12 +1785,15 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
if (!File)
continue;
- // Use HeaderSearch's getFileInfo to make sure we get the HeaderFileInfo
- // from the external source if it was not provided already.
- HeaderFileInfo HFI;
- if (!HS.tryGetFileInfo(File, HFI) ||
- (HFI.External && Chain) ||
- (HFI.isModuleHeader && !HFI.isCompilingModuleHeader))
+ // Get the file info. This will load info from the external source if
+ // necessary. Skip emitting this file if we have no information on it
+ // as a header file (in which case HFI will be null) or if it hasn't
+ // changed since it was loaded. Also skip it if it's for a modular header
+ // from a different module; in that case, we rely on the module(s)
+ // containing the header to provide this information.
+ const HeaderFileInfo *HFI =
+ HS.getExistingFileInfo(File, /*WantExternal*/!Chain);
+ if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader))
continue;
// Massage the file path into an appropriate form.
@@ -1753,7 +1807,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
}
HeaderFileInfoTrait::key_type key = { File, Filename };
- Generator.insert(key, HFI, GeneratorTrait);
+ Generator.insert(key, *HFI, GeneratorTrait);
++NumHeaderSearchEntries;
}
@@ -1770,7 +1824,8 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
// Create a blob abbreviation
using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_TABLE));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
@@ -1779,11 +1834,8 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
unsigned TableAbbrev = Stream.EmitAbbrev(Abbrev);
// Write the header search table
- RecordData Record;
- Record.push_back(HEADER_SEARCH_TABLE);
- Record.push_back(BucketOffset);
- Record.push_back(NumHeaderSearchEntries);
- Record.push_back(TableData.size());
+ RecordData::value_type Record[] = {HEADER_SEARCH_TABLE, BucketOffset,
+ NumHeaderSearchEntries, TableData.size()};
TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end());
Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData);
@@ -1871,9 +1923,8 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record);
- if (Content->BufferOverridden) {
- Record.clear();
- Record.push_back(SM_SLOC_BUFFER_BLOB);
+ if (Content->BufferOverridden || Content->IsTransient) {
+ RecordData::value_type Record[] = {SM_SLOC_BUFFER_BLOB};
const llvm::MemoryBuffer *Buffer
= Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager());
Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
@@ -1892,8 +1943,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
const char *Name = Buffer->getBufferIdentifier();
Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,
StringRef(Name, strlen(Name) + 1));
- Record.clear();
- Record.push_back(SM_SLOC_BUFFER_BLOB);
+ RecordData::value_type Record[] = {SM_SLOC_BUFFER_BLOB};
Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
StringRef(Buffer->getBufferStart(),
Buffer->getBufferSize() + 1));
@@ -1927,19 +1977,20 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
// Write the source-location offsets table into the AST block. This
// table is used for lazily loading source-location information.
using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_OFFSETS));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // total size
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets
unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev);
-
- Record.clear();
- Record.push_back(SOURCE_LOCATION_OFFSETS);
- Record.push_back(SLocEntryOffsets.size());
- Record.push_back(SourceMgr.getNextLocalOffset() - 1); // skip dummy
- Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, bytes(SLocEntryOffsets));
-
+ {
+ RecordData::value_type Record[] = {
+ SOURCE_LOCATION_OFFSETS, SLocEntryOffsets.size(),
+ SourceMgr.getNextLocalOffset() - 1 /* skip dummy */};
+ Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record,
+ bytes(SLocEntryOffsets));
+ }
// Write the source location entry preloads array, telling the AST
// reader which source locations entries it should load eagerly.
Stream.EmitRecord(SOURCE_LOCATION_PRELOADS, PreloadSLocs);
@@ -1950,33 +2001,40 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
LineTableInfo &LineTable = SourceMgr.getLineTable();
Record.clear();
- // Emit the file names.
- Record.push_back(LineTable.getNumFilenames());
- for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I)
- AddPath(LineTable.getFilename(I), Record);
+
+ // Emit the needed file names.
+ llvm::DenseMap<int, int> FilenameMap;
+ for (const auto &L : LineTable) {
+ if (L.first.ID < 0)
+ continue;
+ for (auto &LE : L.second) {
+ if (FilenameMap.insert(std::make_pair(LE.FilenameID,
+ FilenameMap.size())).second)
+ AddPath(LineTable.getFilename(LE.FilenameID), Record);
+ }
+ }
+ Record.push_back(0);
// Emit the line entries
- for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();
- L != LEnd; ++L) {
+ for (const auto &L : LineTable) {
// Only emit entries for local files.
- if (L->first.ID < 0)
+ if (L.first.ID < 0)
continue;
// Emit the file ID
- Record.push_back(L->first.ID);
+ Record.push_back(L.first.ID);
// Emit the line entries
- Record.push_back(L->second.size());
- for (std::vector<LineEntry>::iterator LE = L->second.begin(),
- LEEnd = L->second.end();
- LE != LEEnd; ++LE) {
- Record.push_back(LE->FileOffset);
- Record.push_back(LE->LineNo);
- Record.push_back(LE->FilenameID);
- Record.push_back((unsigned)LE->FileKind);
- Record.push_back(LE->IncludeOffset);
+ Record.push_back(L.second.size());
+ for (const auto &LE : L.second) {
+ Record.push_back(LE.FileOffset);
+ Record.push_back(LE.LineNo);
+ Record.push_back(FilenameMap[LE.FilenameID]);
+ Record.push_back((unsigned)LE.FileKind);
+ Record.push_back(LE.IncludeOffset);
}
}
+
Stream.EmitRecord(SOURCE_MANAGER_LINE_TABLE, Record);
}
}
@@ -2015,19 +2073,17 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
// If the preprocessor __COUNTER__ value has been bumped, remember it.
if (PP.getCounterValue() != 0) {
- Record.push_back(PP.getCounterValue());
+ RecordData::value_type Record[] = {PP.getCounterValue()};
Stream.EmitRecord(PP_COUNTER_VALUE, Record);
- Record.clear();
}
// Enter the preprocessor block.
Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3);
// If the AST file contains __DATE__ or __TIME__ emit a warning about this.
- // FIXME: use diagnostics subsystem for localization etc.
+ // FIXME: Include a location for the use, and say which one was used.
if (PP.SawDateOrTime())
- fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n");
-
+ PP.Diag(SourceLocation(), diag::warn_module_uses_date_time) << IsModule;
// Loop over all the macro directives that are live at the end of the file,
// emitting each to the PP section.
@@ -2177,6 +2233,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
// Write the offsets table for macro IDs.
using namespace llvm;
+
auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros
@@ -2184,12 +2241,11 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned MacroOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
- Record.clear();
- Record.push_back(MACRO_OFFSET);
- Record.push_back(MacroOffsets.size());
- Record.push_back(FirstMacroID - NUM_PREDEF_MACRO_IDS);
- Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record,
- bytes(MacroOffsets));
+ {
+ RecordData::value_type Record[] = {MACRO_OFFSET, MacroOffsets.size(),
+ FirstMacroID - NUM_PREDEF_MACRO_IDS};
+ Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, bytes(MacroOffsets));
+ }
}
void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
@@ -2208,7 +2264,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
// Set up the abbreviation for
unsigned InclusionAbbrev = 0;
{
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(PPD_INCLUSION_DIRECTIVE));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes
@@ -2232,7 +2288,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
PreprocessedEntityOffsets.push_back(
PPEntityOffset((*E)->getSourceRange(), Stream.GetCurrentBitNo()));
- if (MacroDefinitionRecord *MD = dyn_cast<MacroDefinitionRecord>(*E)) {
+ if (auto *MD = dyn_cast<MacroDefinitionRecord>(*E)) {
// Record this macro definition's ID.
MacroDefinitions[MD] = NextPreprocessorEntityID;
@@ -2241,7 +2297,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
continue;
}
- if (MacroExpansion *ME = dyn_cast<MacroExpansion>(*E)) {
+ if (auto *ME = dyn_cast<MacroExpansion>(*E)) {
Record.push_back(ME->isBuiltinMacro());
if (ME->isBuiltinMacro())
AddIdentifierRef(ME->getName(), Record);
@@ -2251,7 +2307,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
continue;
}
- if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) {
+ if (auto *ID = dyn_cast<InclusionDirective>(*E)) {
Record.push_back(PPD_INCLUSION_DIRECTIVE);
Record.push_back(ID->getFileName().size());
Record.push_back(ID->wasInQuotes());
@@ -2277,46 +2333,50 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
// Write the offsets table for identifier IDs.
using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(PPD_ENTITIES_OFFSETS));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first pp entity
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned PPEOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
- Record.clear();
- Record.push_back(PPD_ENTITIES_OFFSETS);
- Record.push_back(FirstPreprocessorEntityID - NUM_PREDEF_PP_ENTITY_IDS);
+ RecordData::value_type Record[] = {PPD_ENTITIES_OFFSETS,
+ FirstPreprocessorEntityID -
+ NUM_PREDEF_PP_ENTITY_IDS};
Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record,
bytes(PreprocessedEntityOffsets));
}
}
-unsigned ASTWriter::getSubmoduleID(Module *Mod) {
+unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) {
+ if (!Mod)
+ return 0;
+
llvm::DenseMap<Module *, unsigned>::iterator Known = SubmoduleIDs.find(Mod);
if (Known != SubmoduleIDs.end())
return Known->second;
-
- return SubmoduleIDs[Mod] = NextSubmoduleID++;
-}
-unsigned ASTWriter::getExistingSubmoduleID(Module *Mod) const {
- if (!Mod)
+ if (Mod->getTopLevelModule() != WritingModule)
return 0;
- llvm::DenseMap<Module *, unsigned>::const_iterator
- Known = SubmoduleIDs.find(Mod);
- if (Known != SubmoduleIDs.end())
- return Known->second;
+ return SubmoduleIDs[Mod] = NextSubmoduleID++;
+}
- return 0;
+unsigned ASTWriter::getSubmoduleID(Module *Mod) {
+ // FIXME: This can easily happen, if we have a reference to a submodule that
+ // did not result in us loading a module file for that submodule. For
+ // instance, a cross-top-level-module 'conflict' declaration will hit this.
+ unsigned ID = getLocalOrImportedSubmoduleID(Mod);
+ assert((ID || !Mod) &&
+ "asked for module ID for non-local, non-imported module");
+ return ID;
}
/// \brief Compute the number of modules within the given tree (including the
/// given module).
static unsigned getNumberOfModules(Module *Mod) {
unsigned ChildModules = 0;
- for (Module::submodule_iterator Sub = Mod->submodule_begin(),
- SubEnd = Mod->submodule_end();
+ for (auto Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end();
Sub != SubEnd; ++Sub)
ChildModules += getNumberOfModules(*Sub);
@@ -2329,7 +2389,8 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
// Write the abbreviations needed for the submodules block.
using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent
@@ -2408,9 +2469,9 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
unsigned ConflictAbbrev = Stream.EmitAbbrev(Abbrev);
// Write the submodule metadata block.
- RecordData Record;
- Record.push_back(getNumberOfModules(WritingModule));
- Record.push_back(FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS);
+ RecordData::value_type Record[] = {getNumberOfModules(WritingModule),
+ FirstSubmoduleID -
+ NUM_PREDEF_SUBMODULE_IDS};
Stream.EmitRecord(SUBMODULE_METADATA, Record);
// Write all of the submodules.
@@ -2420,46 +2481,37 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Module *Mod = Q.front();
Q.pop();
unsigned ID = getSubmoduleID(Mod);
-
- // Emit the definition of the block.
- Record.clear();
- Record.push_back(SUBMODULE_DEFINITION);
- Record.push_back(ID);
+
+ uint64_t ParentID = 0;
if (Mod->Parent) {
assert(SubmoduleIDs[Mod->Parent] && "Submodule parent not written?");
- Record.push_back(SubmoduleIDs[Mod->Parent]);
- } else {
- Record.push_back(0);
+ ParentID = SubmoduleIDs[Mod->Parent];
}
- Record.push_back(Mod->IsFramework);
- Record.push_back(Mod->IsExplicit);
- Record.push_back(Mod->IsSystem);
- Record.push_back(Mod->IsExternC);
- Record.push_back(Mod->InferSubmodules);
- Record.push_back(Mod->InferExplicitSubmodules);
- Record.push_back(Mod->InferExportWildcard);
- Record.push_back(Mod->ConfigMacrosExhaustive);
- Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
-
+
+ // Emit the definition of the block.
+ {
+ RecordData::value_type Record[] = {
+ SUBMODULE_DEFINITION, ID, ParentID, Mod->IsFramework, Mod->IsExplicit,
+ Mod->IsSystem, Mod->IsExternC, Mod->InferSubmodules,
+ Mod->InferExplicitSubmodules, Mod->InferExportWildcard,
+ Mod->ConfigMacrosExhaustive};
+ Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
+ }
+
// Emit the requirements.
- for (unsigned I = 0, N = Mod->Requirements.size(); I != N; ++I) {
- Record.clear();
- Record.push_back(SUBMODULE_REQUIRES);
- Record.push_back(Mod->Requirements[I].second);
- Stream.EmitRecordWithBlob(RequiresAbbrev, Record,
- Mod->Requirements[I].first);
+ for (const auto &R : Mod->Requirements) {
+ RecordData::value_type Record[] = {SUBMODULE_REQUIRES, R.second};
+ Stream.EmitRecordWithBlob(RequiresAbbrev, Record, R.first);
}
// Emit the umbrella header, if there is one.
if (auto UmbrellaHeader = Mod->getUmbrellaHeader()) {
- Record.clear();
- Record.push_back(SUBMODULE_UMBRELLA_HEADER);
+ RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_HEADER};
Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record,
UmbrellaHeader.NameAsWritten);
} else if (auto UmbrellaDir = Mod->getUmbrellaDir()) {
- Record.clear();
- Record.push_back(SUBMODULE_UMBRELLA_DIR);
- Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record,
+ RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_DIR};
+ Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record,
UmbrellaDir.NameAsWritten);
}
@@ -2477,8 +2529,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
{SUBMODULE_EXCLUDED_HEADER, ExcludedHeaderAbbrev, Module::HK_Excluded}
};
for (auto &HL : HeaderLists) {
- Record.clear();
- Record.push_back(HL.RecordKind);
+ RecordData::value_type Record[] = {HL.RecordKind};
for (auto &H : Mod->Headers[HL.HeaderKind])
Stream.EmitRecordWithBlob(HL.Abbrev, Record, H.NameAsWritten);
}
@@ -2486,35 +2537,27 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
// Emit the top headers.
{
auto TopHeaders = Mod->getTopHeaders(PP->getFileManager());
- Record.clear();
- Record.push_back(SUBMODULE_TOPHEADER);
+ RecordData::value_type Record[] = {SUBMODULE_TOPHEADER};
for (auto *H : TopHeaders)
Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, H->getName());
}
// Emit the imports.
if (!Mod->Imports.empty()) {
- Record.clear();
- for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) {
- unsigned ImportedID = getSubmoduleID(Mod->Imports[I]);
- assert(ImportedID && "Unknown submodule!");
- Record.push_back(ImportedID);
- }
+ RecordData Record;
+ for (auto *I : Mod->Imports)
+ Record.push_back(getSubmoduleID(I));
Stream.EmitRecord(SUBMODULE_IMPORTS, Record);
}
// Emit the exports.
if (!Mod->Exports.empty()) {
- Record.clear();
- for (unsigned I = 0, N = Mod->Exports.size(); I != N; ++I) {
- if (Module *Exported = Mod->Exports[I].getPointer()) {
- unsigned ExportedID = getSubmoduleID(Exported);
- Record.push_back(ExportedID);
- } else {
- Record.push_back(0);
- }
-
- Record.push_back(Mod->Exports[I].getInt());
+ RecordData Record;
+ for (const auto &E : Mod->Exports) {
+ // FIXME: This may fail; we don't require that all exported modules
+ // are local or imported.
+ Record.push_back(getSubmoduleID(E.getPointer()));
+ Record.push_back(E.getInt());
}
Stream.EmitRecord(SUBMODULE_EXPORTS, Record);
}
@@ -2524,45 +2567,34 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
// module itself.
// Emit the link libraries.
- for (unsigned I = 0, N = Mod->LinkLibraries.size(); I != N; ++I) {
- Record.clear();
- Record.push_back(SUBMODULE_LINK_LIBRARY);
- Record.push_back(Mod->LinkLibraries[I].IsFramework);
- Stream.EmitRecordWithBlob(LinkLibraryAbbrev, Record,
- Mod->LinkLibraries[I].Library);
+ for (const auto &LL : Mod->LinkLibraries) {
+ RecordData::value_type Record[] = {SUBMODULE_LINK_LIBRARY,
+ LL.IsFramework};
+ Stream.EmitRecordWithBlob(LinkLibraryAbbrev, Record, LL.Library);
}
// Emit the conflicts.
- for (unsigned I = 0, N = Mod->Conflicts.size(); I != N; ++I) {
- Record.clear();
- Record.push_back(SUBMODULE_CONFLICT);
- unsigned OtherID = getSubmoduleID(Mod->Conflicts[I].Other);
- assert(OtherID && "Unknown submodule!");
- Record.push_back(OtherID);
- Stream.EmitRecordWithBlob(ConflictAbbrev, Record,
- Mod->Conflicts[I].Message);
+ for (const auto &C : Mod->Conflicts) {
+ // FIXME: This may fail; we don't require that all conflicting modules
+ // are local or imported.
+ RecordData::value_type Record[] = {SUBMODULE_CONFLICT,
+ getSubmoduleID(C.Other)};
+ Stream.EmitRecordWithBlob(ConflictAbbrev, Record, C.Message);
}
// Emit the configuration macros.
- for (unsigned I = 0, N = Mod->ConfigMacros.size(); I != N; ++I) {
- Record.clear();
- Record.push_back(SUBMODULE_CONFIG_MACRO);
- Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record,
- Mod->ConfigMacros[I]);
+ for (const auto &CM : Mod->ConfigMacros) {
+ RecordData::value_type Record[] = {SUBMODULE_CONFIG_MACRO};
+ Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM);
}
// Queue up the submodules of this module.
- for (Module::submodule_iterator Sub = Mod->submodule_begin(),
- SubEnd = Mod->submodule_end();
- Sub != SubEnd; ++Sub)
- Q.push(*Sub);
+ for (auto *M : Mod->submodules())
+ Q.push(M);
}
Stream.ExitBlock();
- // FIXME: This can easily happen, if we have a reference to a submodule that
- // did not result in us loading a module file for that submodule. For
- // instance, a cross-top-level-module 'conflict' declaration will hit this.
assert((NextSubmoduleID - FirstSubmoduleID ==
getNumberOfModules(WritingModule)) &&
"Wrong # of submodules; found a reference to a non-local, "
@@ -2614,11 +2646,10 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
if (DiagStateID == 0) {
DiagStateID = ++CurrID;
- for (DiagnosticsEngine::DiagState::const_iterator
- I = point.State->begin(), E = point.State->end(); I != E; ++I) {
- if (I->second.isPragma()) {
- Record.push_back(I->first);
- Record.push_back((unsigned)I->second.getSeverity());
+ for (const auto &I : *(point.State)) {
+ if (I.second.isPragma()) {
+ Record.push_back(I.first);
+ Record.push_back((unsigned)I.second.getSeverity());
}
}
Record.push_back(-1); // mark the end of the diag/map pairs for this
@@ -2634,21 +2665,18 @@ void ASTWriter::WriteCXXCtorInitializersOffsets() {
if (CXXCtorInitializersOffsets.empty())
return;
- RecordData Record;
-
// Create a blob abbreviation for the C++ ctor initializer offsets.
using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(CXX_CTOR_INITIALIZERS_OFFSETS));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned CtorInitializersOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
// Write the base specifier offsets table.
- Record.clear();
- Record.push_back(CXX_CTOR_INITIALIZERS_OFFSETS);
- Record.push_back(CXXCtorInitializersOffsets.size());
+ RecordData::value_type Record[] = {CXX_CTOR_INITIALIZERS_OFFSETS,
+ CXXCtorInitializersOffsets.size()};
Stream.EmitRecordWithBlob(CtorInitializersOffsetAbbrev, Record,
bytes(CXXCtorInitializersOffsets));
}
@@ -2657,21 +2685,18 @@ void ASTWriter::WriteCXXBaseSpecifiersOffsets() {
if (CXXBaseSpecifiersOffsets.empty())
return;
- RecordData Record;
-
// Create a blob abbreviation for the C++ base specifiers offsets.
using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(CXX_BASE_SPECIFIER_OFFSETS));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned BaseSpecifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
// Write the base specifier offsets table.
- Record.clear();
- Record.push_back(CXX_BASE_SPECIFIER_OFFSETS);
- Record.push_back(CXXBaseSpecifiersOffsets.size());
+ RecordData::value_type Record[] = {CXX_BASE_SPECIFIER_OFFSETS,
+ CXXBaseSpecifiersOffsets.size()};
Stream.EmitRecordWithBlob(BaseSpecifierOffsetAbbrev, Record,
bytes(CXXBaseSpecifiersOffsets));
}
@@ -2742,33 +2767,34 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
return 0;
uint64_t Offset = Stream.GetCurrentBitNo();
- RecordData Record;
- Record.push_back(DECL_CONTEXT_LEXICAL);
- SmallVector<KindDeclIDPair, 64> Decls;
- for (const auto *D : DC->decls())
- Decls.push_back(std::make_pair(D->getKind(), GetDeclRef(D)));
+ SmallVector<uint32_t, 128> KindDeclPairs;
+ for (const auto *D : DC->decls()) {
+ KindDeclPairs.push_back(D->getKind());
+ KindDeclPairs.push_back(GetDeclRef(D));
+ }
++NumLexicalDeclContexts;
- Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, bytes(Decls));
+ RecordData::value_type Record[] = {DECL_CONTEXT_LEXICAL};
+ Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record,
+ bytes(KindDeclPairs));
return Offset;
}
void ASTWriter::WriteTypeDeclOffsets() {
using namespace llvm;
- RecordData Record;
// Write the type offsets array
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(TYPE_OFFSET));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base type index
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block
unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
- Record.clear();
- Record.push_back(TYPE_OFFSET);
- Record.push_back(TypeOffsets.size());
- Record.push_back(FirstTypeID - NUM_PREDEF_TYPE_IDS);
- Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets));
+ {
+ RecordData::value_type Record[] = {TYPE_OFFSET, TypeOffsets.size(),
+ FirstTypeID - NUM_PREDEF_TYPE_IDS};
+ Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets));
+ }
// Write the declaration offsets array
Abbrev = new BitCodeAbbrev();
@@ -2777,16 +2803,15 @@ void ASTWriter::WriteTypeDeclOffsets() {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base decl ID
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block
unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
- Record.clear();
- Record.push_back(DECL_OFFSET);
- Record.push_back(DeclOffsets.size());
- Record.push_back(FirstDeclID - NUM_PREDEF_DECL_IDS);
- Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets));
+ {
+ RecordData::value_type Record[] = {DECL_OFFSET, DeclOffsets.size(),
+ FirstDeclID - NUM_PREDEF_DECL_IDS};
+ Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets));
+ }
}
void ASTWriter::WriteFileDeclIDsMap() {
using namespace llvm;
- RecordData Record;
SmallVector<std::pair<FileID, DeclIDInFileInfo *>, 64> SortedFileDeclIDs(
FileDeclIDs.begin(), FileDeclIDs.end());
@@ -2802,13 +2827,13 @@ void ASTWriter::WriteFileDeclIDsMap() {
FileGroupedDeclIDs.push_back(LocDeclEntry.second);
}
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(FILE_SORTED_DECLS));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
- Record.push_back(FILE_SORTED_DECLS);
- Record.push_back(FileGroupedDeclIDs.size());
+ RecordData::value_type Record[] = {FILE_SORTED_DECLS,
+ FileGroupedDeclIDs.size()};
Stream.EmitRecordWithBlob(AbbrevCode, Record, bytes(FileGroupedDeclIDs));
}
@@ -2816,14 +2841,12 @@ void ASTWriter::WriteComments() {
Stream.EnterSubblock(COMMENTS_BLOCK_ID, 3);
ArrayRef<RawComment *> RawComments = Context->Comments.getComments();
RecordData Record;
- for (ArrayRef<RawComment *>::iterator I = RawComments.begin(),
- E = RawComments.end();
- I != E; ++I) {
+ for (const auto *I : RawComments) {
Record.clear();
- AddSourceRange((*I)->getSourceRange(), Record);
- Record.push_back((*I)->getKind());
- Record.push_back((*I)->isTrailingComment());
- Record.push_back((*I)->isAlmostTrailingComment());
+ AddSourceRange(I->getSourceRange(), Record);
+ Record.push_back(I->getKind());
+ Record.push_back(I->isTrailingComment());
+ Record.push_back(I->isAlmostTrailingComment());
Stream.EmitRecord(COMMENTS_RAW_COMMENT, Record);
}
Stream.ExitBlock();
@@ -3010,7 +3033,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
}
// Create a blob abbreviation
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(METHOD_POOL));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
@@ -3018,11 +3041,11 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
unsigned MethodPoolAbbrev = Stream.EmitAbbrev(Abbrev);
// Write the method pool
- RecordData Record;
- Record.push_back(METHOD_POOL);
- Record.push_back(BucketOffset);
- Record.push_back(NumTableEntries);
- Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool);
+ {
+ RecordData::value_type Record[] = {METHOD_POOL, BucketOffset,
+ NumTableEntries};
+ Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool);
+ }
// Create a blob abbreviation for the selector table offsets.
Abbrev = new BitCodeAbbrev();
@@ -3033,12 +3056,13 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
// Write the selector offsets table.
- Record.clear();
- Record.push_back(SELECTOR_OFFSETS);
- Record.push_back(SelectorOffsets.size());
- Record.push_back(FirstSelectorID - NUM_PREDEF_SELECTOR_IDS);
- Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,
- bytes(SelectorOffsets));
+ {
+ RecordData::value_type Record[] = {
+ SELECTOR_OFFSETS, SelectorOffsets.size(),
+ FirstSelectorID - NUM_PREDEF_SELECTOR_IDS};
+ Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,
+ bytes(SelectorOffsets));
+ }
}
}
@@ -3102,18 +3126,20 @@ class ASTIdentifierTableTrait {
ASTWriter &Writer;
Preprocessor &PP;
IdentifierResolver &IdResolver;
+ bool IsModule;
+ bool NeedDecls;
+ ASTWriter::RecordData *InterestingIdentifierOffsets;
/// \brief Determines whether this is an "interesting" identifier that needs a
/// full IdentifierInfo structure written into the hash table. Notably, this
/// doesn't check whether the name has macros defined; use PublicMacroIterator
/// to check that.
- bool isInterestingIdentifier(IdentifierInfo *II, uint64_t MacroOffset) {
+ bool isInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset) {
if (MacroOffset ||
II->isPoisoned() ||
- II->isExtensionToken() ||
- II->getObjCOrBuiltinID() ||
+ (IsModule ? II->hasRevertedBuiltin() : II->getObjCOrBuiltinID()) ||
II->hasRevertedTokenIDToIdentifier() ||
- II->getFETokenInfo<void>())
+ (NeedDecls && II->getFETokenInfo<void>()))
return true;
return false;
@@ -3130,13 +3156,24 @@ public:
typedef unsigned offset_type;
ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP,
- IdentifierResolver &IdResolver)
- : Writer(Writer), PP(PP), IdResolver(IdResolver) {}
+ IdentifierResolver &IdResolver, bool IsModule,
+ ASTWriter::RecordData *InterestingIdentifierOffsets)
+ : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule),
+ NeedDecls(!IsModule || !Writer.getLangOpts().CPlusPlus),
+ InterestingIdentifierOffsets(InterestingIdentifierOffsets) {}
static hash_value_type ComputeHash(const IdentifierInfo* II) {
return llvm::HashString(II->getName());
}
+ bool isInterestingIdentifier(const IdentifierInfo *II) {
+ auto MacroOffset = Writer.getMacroDirectivesOffset(II);
+ return isInterestingIdentifier(II, MacroOffset);
+ }
+ bool isInterestingNonMacroIdentifier(const IdentifierInfo *II) {
+ return isInterestingIdentifier(II, 0);
+ }
+
std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) {
unsigned KeyLen = II->getLength() + 1;
@@ -3148,10 +3185,12 @@ public:
if (MacroOffset)
DataLen += 4; // MacroDirectives offset.
- for (IdentifierResolver::iterator D = IdResolver.begin(II),
- DEnd = IdResolver.end();
- D != DEnd; ++D)
- DataLen += 4;
+ if (NeedDecls) {
+ for (IdentifierResolver::iterator D = IdResolver.begin(II),
+ DEnd = IdResolver.end();
+ D != DEnd; ++D)
+ DataLen += 4;
+ }
}
using namespace llvm::support;
endian::Writer<little> LE(Out);
@@ -3170,6 +3209,12 @@ public:
// Record the location of the key data. This is used when generating
// the mapping from persistent IDs to strings.
Writer.SetIdentifierOffset(II, Out.tell());
+
+ // Emit the offset of the key/data length information to the interesting
+ // identifiers table if necessary.
+ if (InterestingIdentifierOffsets && isInterestingIdentifier(II))
+ InterestingIdentifierOffsets->push_back(Out.tell() - 4);
+
Out.write(II->getNameStart(), KeyLen);
}
@@ -3193,6 +3238,7 @@ public:
Bits = (Bits << 1) | unsigned(HadMacroDefinition);
Bits = (Bits << 1) | unsigned(II->isExtensionToken());
Bits = (Bits << 1) | unsigned(II->isPoisoned());
+ Bits = (Bits << 1) | unsigned(II->hasRevertedBuiltin());
Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
LE.write<uint16_t>(Bits);
@@ -3200,18 +3246,21 @@ public:
if (HadMacroDefinition)
LE.write<uint32_t>(MacroOffset);
- // Emit the declaration IDs in reverse order, because the
- // IdentifierResolver provides the declarations as they would be
- // visible (e.g., the function "stat" would come before the struct
- // "stat"), but the ASTReader adds declarations to the end of the list
- // (so we need to see the struct "stat" before the function "stat").
- // Only emit declarations that aren't from a chained PCH, though.
- SmallVector<NamedDecl *, 16> Decls(IdResolver.begin(II), IdResolver.end());
- for (SmallVectorImpl<NamedDecl *>::reverse_iterator D = Decls.rbegin(),
- DEnd = Decls.rend();
- D != DEnd; ++D)
- LE.write<uint32_t>(
- Writer.getDeclID(getDeclForLocalLookup(PP.getLangOpts(), *D)));
+ if (NeedDecls) {
+ // Emit the declaration IDs in reverse order, because the
+ // IdentifierResolver provides the declarations as they would be
+ // visible (e.g., the function "stat" would come before the struct
+ // "stat"), but the ASTReader adds declarations to the end of the list
+ // (so we need to see the struct "stat" before the function "stat").
+ // Only emit declarations that aren't from a chained PCH, though.
+ SmallVector<NamedDecl *, 16> Decls(IdResolver.begin(II),
+ IdResolver.end());
+ for (SmallVectorImpl<NamedDecl *>::reverse_iterator D = Decls.rbegin(),
+ DEnd = Decls.rend();
+ D != DEnd; ++D)
+ LE.write<uint32_t>(
+ Writer.getDeclID(getDeclForLocalLookup(PP.getLangOpts(), *D)));
+ }
}
};
} // end anonymous namespace
@@ -3226,11 +3275,15 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
bool IsModule) {
using namespace llvm;
+ RecordData InterestingIdents;
+
// Create and write out the blob that contains the identifier
// strings.
{
llvm::OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
- ASTIdentifierTableTrait Trait(*this, PP, IdResolver);
+ ASTIdentifierTableTrait Trait(
+ *this, PP, IdResolver, IsModule,
+ (getLangOpts().CPlusPlus && IsModule) ? &InterestingIdents : nullptr);
// Look for any identifiers that were named while processing the
// headers, but are otherwise not needed. We add these to the hash
@@ -3238,21 +3291,20 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
// where the user adds new macro definitions when building the AST
// file.
SmallVector<const IdentifierInfo *, 128> IIs;
- for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(),
- IDEnd = PP.getIdentifierTable().end();
- ID != IDEnd; ++ID)
- IIs.push_back(ID->second);
+ for (const auto &ID : PP.getIdentifierTable())
+ IIs.push_back(ID.second);
// Sort the identifiers lexicographically before getting them references so
// that their order is stable.
std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
for (const IdentifierInfo *II : IIs)
- getIdentifierRef(II);
+ if (Trait.isInterestingNonMacroIdentifier(II))
+ getIdentifierRef(II);
// Create the on-disk hash table representation. We only store offsets
// for identifiers that appear here for the first time.
IdentifierOffsets.resize(NextIdentID - FirstIdentID);
for (auto IdentIDPair : IdentifierIDs) {
- IdentifierInfo *II = const_cast<IdentifierInfo *>(IdentIDPair.first);
+ auto *II = const_cast<IdentifierInfo *>(IdentIDPair.first);
IdentID ID = IdentIDPair.second;
assert(II && "NULL identifier in identifier table");
if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization())
@@ -3271,21 +3323,19 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
}
// Create a blob abbreviation
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_TABLE));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev);
// Write the identifier table
- RecordData Record;
- Record.push_back(IDENTIFIER_TABLE);
- Record.push_back(BucketOffset);
+ RecordData::value_type Record[] = {IDENTIFIER_TABLE, BucketOffset};
Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable);
}
// Write the offsets table for identifier IDs.
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_OFFSET));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID
@@ -3296,13 +3346,17 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
for (unsigned I = 0, N = IdentifierOffsets.size(); I != N; ++I)
assert(IdentifierOffsets[I] && "Missing identifier offset?");
#endif
-
- RecordData Record;
- Record.push_back(IDENTIFIER_OFFSET);
- Record.push_back(IdentifierOffsets.size());
- Record.push_back(FirstIdentID - NUM_PREDEF_IDENT_IDS);
+
+ RecordData::value_type Record[] = {IDENTIFIER_OFFSET,
+ IdentifierOffsets.size(),
+ FirstIdentID - NUM_PREDEF_IDENT_IDS};
Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,
bytes(IdentifierOffsets));
+
+ // In C++, write the list of interesting identifiers (those that are
+ // defined as macros, poisoned, or similar unusual things).
+ if (!InterestingIdents.empty())
+ Stream.EmitRecord(INTERESTING_IDENTIFIERS, InterestingIdents);
}
//===----------------------------------------------------------------------===//
@@ -3313,12 +3367,14 @@ namespace {
// Trait used for the on-disk hash table used in the method pool.
class ASTDeclContextNameLookupTrait {
ASTWriter &Writer;
+ llvm::SmallVector<DeclID, 64> DeclIDs;
public:
- typedef DeclarationName key_type;
+ typedef DeclarationNameKey key_type;
typedef key_type key_type_ref;
- typedef DeclContext::lookup_result data_type;
+ /// A start and end index into DeclIDs, representing a sequence of decls.
+ typedef std::pair<unsigned, unsigned> data_type;
typedef const data_type& data_type_ref;
typedef unsigned hash_value_type;
@@ -3326,42 +3382,47 @@ public:
explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) { }
- hash_value_type ComputeHash(DeclarationName Name) {
- llvm::FoldingSetNodeID ID;
- ID.AddInteger(Name.getNameKind());
-
- switch (Name.getNameKind()) {
- case DeclarationName::Identifier:
- ID.AddString(Name.getAsIdentifierInfo()->getName());
- break;
- case DeclarationName::ObjCZeroArgSelector:
- case DeclarationName::ObjCOneArgSelector:
- case DeclarationName::ObjCMultiArgSelector:
- ID.AddInteger(serialization::ComputeHash(Name.getObjCSelector()));
- break;
- case DeclarationName::CXXConstructorName:
- case DeclarationName::CXXDestructorName:
- case DeclarationName::CXXConversionFunctionName:
- break;
- case DeclarationName::CXXOperatorName:
- ID.AddInteger(Name.getCXXOverloadedOperator());
- break;
- case DeclarationName::CXXLiteralOperatorName:
- ID.AddString(Name.getCXXLiteralIdentifier()->getName());
- case DeclarationName::CXXUsingDirective:
- break;
+ template<typename Coll>
+ data_type getData(const Coll &Decls) {
+ unsigned Start = DeclIDs.size();
+ for (NamedDecl *D : Decls) {
+ DeclIDs.push_back(
+ Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), D)));
}
+ return std::make_pair(Start, DeclIDs.size());
+ }
- return ID.ComputeHash();
+ data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) {
+ unsigned Start = DeclIDs.size();
+ for (auto ID : FromReader)
+ DeclIDs.push_back(ID);
+ return std::make_pair(Start, DeclIDs.size());
}
- std::pair<unsigned,unsigned>
- EmitKeyDataLength(raw_ostream& Out, DeclarationName Name,
- data_type_ref Lookup) {
+ static bool EqualKey(key_type_ref a, key_type_ref b) {
+ return a == b;
+ }
+
+ hash_value_type ComputeHash(DeclarationNameKey Name) {
+ return Name.getHash();
+ }
+
+ void EmitFileRef(raw_ostream &Out, ModuleFile *F) const {
+ assert(Writer.hasChain() &&
+ "have reference to loaded module file but no chain?");
+
+ using namespace llvm::support;
+ endian::Writer<little>(Out)
+ .write<uint32_t>(Writer.getChain()->getModuleFileID(F));
+ }
+
+ std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out,
+ DeclarationNameKey Name,
+ data_type_ref Lookup) {
using namespace llvm::support;
endian::Writer<little> LE(Out);
unsigned KeyLen = 1;
- switch (Name.getNameKind()) {
+ switch (Name.getKind()) {
case DeclarationName::Identifier:
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
@@ -3380,33 +3441,33 @@ public:
}
LE.write<uint16_t>(KeyLen);
- // 2 bytes for num of decls and 4 for each DeclID.
- unsigned DataLen = 2 + 4 * Lookup.size();
+ // 4 bytes for each DeclID.
+ unsigned DataLen = 4 * (Lookup.second - Lookup.first);
+ assert(uint16_t(DataLen) == DataLen &&
+ "too many decls for serialized lookup result");
LE.write<uint16_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
- void EmitKey(raw_ostream& Out, DeclarationName Name, unsigned) {
+ void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) {
using namespace llvm::support;
endian::Writer<little> LE(Out);
- LE.write<uint8_t>(Name.getNameKind());
- switch (Name.getNameKind()) {
+ LE.write<uint8_t>(Name.getKind());
+ switch (Name.getKind()) {
case DeclarationName::Identifier:
- LE.write<uint32_t>(Writer.getIdentifierRef(Name.getAsIdentifierInfo()));
+ case DeclarationName::CXXLiteralOperatorName:
+ LE.write<uint32_t>(Writer.getIdentifierRef(Name.getIdentifier()));
return;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
- LE.write<uint32_t>(Writer.getSelectorRef(Name.getObjCSelector()));
+ LE.write<uint32_t>(Writer.getSelectorRef(Name.getSelector()));
return;
case DeclarationName::CXXOperatorName:
- assert(Name.getCXXOverloadedOperator() < NUM_OVERLOADED_OPERATORS &&
+ assert(Name.getOperatorKind() < NUM_OVERLOADED_OPERATORS &&
"Invalid operator?");
- LE.write<uint8_t>(Name.getCXXOverloadedOperator());
- return;
- case DeclarationName::CXXLiteralOperatorName:
- LE.write<uint32_t>(Writer.getIdentifierRef(Name.getCXXLiteralIdentifier()));
+ LE.write<uint8_t>(Name.getOperatorKind());
return;
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
@@ -3418,17 +3479,13 @@ public:
llvm_unreachable("Invalid name kind?");
}
- void EmitData(raw_ostream& Out, key_type_ref,
- data_type Lookup, unsigned DataLen) {
+ void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup,
+ unsigned DataLen) {
using namespace llvm::support;
endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
- LE.write<uint16_t>(Lookup.size());
- for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end();
- I != E; ++I)
- LE.write<uint32_t>(
- Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), *I)));
-
+ for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I)
+ LE.write<uint32_t>(DeclIDs[I]);
assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
};
@@ -3448,7 +3505,7 @@ bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result,
return true;
}
-uint32_t
+void
ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
llvm::SmallVectorImpl<char> &LookupTable) {
assert(!ConstDC->HasLazyLocalLexicalLookups &&
@@ -3456,12 +3513,12 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
"must call buildLookups first");
// FIXME: We need to build the lookups table, which is logically const.
- DeclContext *DC = const_cast<DeclContext*>(ConstDC);
+ auto *DC = const_cast<DeclContext*>(ConstDC);
assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table");
// Create the on-disk hash table representation.
- llvm::OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait>
- Generator;
+ MultiOnDiskHashTableGenerator<reader::ASTDeclContextNameLookupTrait,
+ ASTDeclContextNameLookupTrait> Generator;
ASTDeclContextNameLookupTrait Trait(*this);
// The first step is to collect the declaration names which we need to
@@ -3477,11 +3534,11 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
auto &Name = Lookup.first;
auto &Result = Lookup.second;
- // If there are no local declarations in our lookup result, we don't
- // need to write an entry for the name at all unless we're rewriting
- // the decl context. If we can't write out a lookup set without
- // performing more deserialization, just skip this entry.
- if (isLookupResultExternal(Result, DC) && !isRewritten(cast<Decl>(DC)) &&
+ // If there are no local declarations in our lookup result, we
+ // don't need to write an entry for the name at all. If we can't
+ // write out a lookup set without performing more deserialization,
+ // just skip this entry.
+ if (isLookupResultExternal(Result, DC) &&
isLookupResultEntirelyExternal(Result, DC))
continue;
@@ -3596,7 +3653,7 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
switch (Name.getNameKind()) {
default:
- Generator.insert(Name, Result, Trait);
+ Generator.insert(Name, Trait.getData(Result), Trait);
break;
case DeclarationName::CXXConstructorName:
@@ -3614,17 +3671,15 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
// the key, only the kind of name is used.
if (!ConstructorDecls.empty())
Generator.insert(ConstructorDecls.front()->getDeclName(),
- DeclContext::lookup_result(ConstructorDecls), Trait);
+ Trait.getData(ConstructorDecls), Trait);
if (!ConversionDecls.empty())
Generator.insert(ConversionDecls.front()->getDeclName(),
- DeclContext::lookup_result(ConversionDecls), Trait);
+ Trait.getData(ConversionDecls), Trait);
- // Create the on-disk hash table in a buffer.
- llvm::raw_svector_ostream Out(LookupTable);
- // Make sure that no bucket is at offset 0
- using namespace llvm::support;
- endian::Writer<little>(Out).write<uint32_t>(0);
- return Generator.Emit(Out, Trait);
+ // Create the on-disk hash table. Also emit the existing imported and
+ // merged table if there is one.
+ auto *Lookups = Chain ? Chain->getLoadedLookupTables(DC) : nullptr;
+ Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr);
}
/// \brief Write the block containing all of the declaration IDs
@@ -3640,7 +3695,7 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
if (isa<NamespaceDecl>(DC) && Chain &&
Chain->getKeyDeclaration(cast<Decl>(DC))->isFromASTFile()) {
// Only do this once, for the first local declaration of the namespace.
- for (NamespaceDecl *Prev = cast<NamespaceDecl>(DC)->getPreviousDecl(); Prev;
+ for (auto *Prev = cast<NamespaceDecl>(DC)->getPreviousDecl(); Prev;
Prev = Prev->getPreviousDecl())
if (!Prev->isFromASTFile())
return 0;
@@ -3707,12 +3762,10 @@ uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
// Create the on-disk hash table in a buffer.
SmallString<4096> LookupTable;
- uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable);
+ GenerateNameLookupTable(DC, LookupTable);
// Write the lookup table
- RecordData Record;
- Record.push_back(DECL_CONTEXT_VISIBLE);
- Record.push_back(BucketOffset);
+ RecordData::value_type Record[] = {DECL_CONTEXT_VISIBLE};
Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record,
LookupTable);
++NumVisibleDeclContexts;
@@ -3732,7 +3785,7 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
// Create the on-disk hash table in a buffer.
SmallString<4096> LookupTable;
- uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable);
+ GenerateNameLookupTable(DC, LookupTable);
// If we're updating a namespace, select a key declaration as the key for the
// update record; those are the only ones that will be checked on reload.
@@ -3740,17 +3793,13 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
DC = cast<DeclContext>(Chain->getKeyDeclaration(cast<Decl>(DC)));
// Write the lookup table
- RecordData Record;
- Record.push_back(UPDATE_VISIBLE);
- Record.push_back(getDeclID(cast<Decl>(DC)));
- Record.push_back(BucketOffset);
+ RecordData::value_type Record[] = {UPDATE_VISIBLE, getDeclID(cast<Decl>(DC))};
Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable);
}
/// \brief Write an FP_PRAGMA_OPTIONS block for the given FPOptions.
void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) {
- RecordData Record;
- Record.push_back(Opts.fp_contract);
+ RecordData::value_type Record[] = {Opts.fp_contract};
Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record);
}
@@ -3766,81 +3815,6 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {
Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
}
-void ASTWriter::WriteRedeclarations() {
- RecordData LocalRedeclChains;
- SmallVector<serialization::LocalRedeclarationsInfo, 2> LocalRedeclsMap;
-
- for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) {
- const Decl *Key = Redeclarations[I];
- assert((Chain ? Chain->getKeyDeclaration(Key) == Key
- : Key->isFirstDecl()) &&
- "not the key declaration");
-
- const Decl *First = Key->getCanonicalDecl();
- const Decl *MostRecent = First->getMostRecentDecl();
-
- assert((getDeclID(First) >= NUM_PREDEF_DECL_IDS || First == Key) &&
- "should not have imported key decls for predefined decl");
-
- // If we only have a single declaration, there is no point in storing
- // a redeclaration chain.
- if (First == MostRecent)
- continue;
-
- unsigned Offset = LocalRedeclChains.size();
- unsigned Size = 0;
- LocalRedeclChains.push_back(0); // Placeholder for the size.
-
- // Collect the set of local redeclarations of this declaration.
- for (const Decl *Prev = MostRecent; Prev;
- Prev = Prev->getPreviousDecl()) {
- if (!Prev->isFromASTFile() && Prev != Key) {
- AddDeclRef(Prev, LocalRedeclChains);
- ++Size;
- }
- }
-
- LocalRedeclChains[Offset] = Size;
-
- // Reverse the set of local redeclarations, so that we store them in
- // order (since we found them in reverse order).
- std::reverse(LocalRedeclChains.end() - Size, LocalRedeclChains.end());
-
- // Add the mapping from the first ID from the AST to the set of local
- // declarations.
- LocalRedeclarationsInfo Info = { getDeclID(Key), Offset };
- LocalRedeclsMap.push_back(Info);
-
- assert(N == Redeclarations.size() &&
- "Deserialized a declaration we shouldn't have");
- }
-
- if (LocalRedeclChains.empty())
- return;
-
- // Sort the local redeclarations map by the first declaration ID,
- // since the reader will be performing binary searches on this information.
- llvm::array_pod_sort(LocalRedeclsMap.begin(), LocalRedeclsMap.end());
-
- // Emit the local redeclarations map.
- using namespace llvm;
- llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(LOCAL_REDECLARATIONS_MAP));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
- unsigned AbbrevID = Stream.EmitAbbrev(Abbrev);
-
- RecordData Record;
- Record.push_back(LOCAL_REDECLARATIONS_MAP);
- Record.push_back(LocalRedeclsMap.size());
- Stream.EmitRecordWithBlob(AbbrevID, Record,
- reinterpret_cast<char*>(LocalRedeclsMap.data()),
- LocalRedeclsMap.size() * sizeof(LocalRedeclarationsInfo));
-
- // Emit the redeclaration chains.
- Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedeclChains);
-}
-
void ASTWriter::WriteObjCCategories() {
SmallVector<ObjCCategoriesInfo, 2> CategoriesMap;
RecordData Categories;
@@ -3877,19 +3851,18 @@ void ASTWriter::WriteObjCCategories() {
// Emit the categories map.
using namespace llvm;
- llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(OBJC_CATEGORIES_MAP));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned AbbrevID = Stream.EmitAbbrev(Abbrev);
-
- RecordData Record;
- Record.push_back(OBJC_CATEGORIES_MAP);
- Record.push_back(CategoriesMap.size());
- Stream.EmitRecordWithBlob(AbbrevID, Record,
- reinterpret_cast<char*>(CategoriesMap.data()),
+
+ RecordData::value_type Record[] = {OBJC_CATEGORIES_MAP, CategoriesMap.size()};
+ Stream.EmitRecordWithBlob(AbbrevID, Record,
+ reinterpret_cast<char *>(CategoriesMap.data()),
CategoriesMap.size() * sizeof(ObjCCategoriesInfo));
-
+
// Emit the category lists.
Stream.EmitRecord(OBJC_CATEGORIES, Categories);
}
@@ -3908,10 +3881,8 @@ void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) {
AddDeclRef(LPT->D, Record);
Record.push_back(LPT->Toks.size());
- for (CachedTokens::iterator TokIt = LPT->Toks.begin(),
- TokEnd = LPT->Toks.end();
- TokIt != TokEnd; ++TokIt) {
- AddToken(*TokIt, Record);
+ for (const auto &Tok : LPT->Toks) {
+ AddToken(Tok, Record);
}
}
Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record);
@@ -3925,6 +3896,41 @@ void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) {
Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record);
}
+void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,
+ ModuleFileExtensionWriter &Writer) {
+ // Enter the extension block.
+ Stream.EnterSubblock(EXTENSION_BLOCK_ID, 4);
+
+ // Emit the metadata record abbreviation.
+ auto *Abv = new llvm::BitCodeAbbrev();
+ Abv->Add(llvm::BitCodeAbbrevOp(EXTENSION_METADATA));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
+ unsigned Abbrev = Stream.EmitAbbrev(Abv);
+
+ // Emit the metadata record.
+ RecordData Record;
+ auto Metadata = Writer.getExtension()->getExtensionMetadata();
+ Record.push_back(EXTENSION_METADATA);
+ Record.push_back(Metadata.MajorVersion);
+ Record.push_back(Metadata.MinorVersion);
+ Record.push_back(Metadata.BlockName.size());
+ Record.push_back(Metadata.UserInfo.size());
+ SmallString<64> Buffer;
+ Buffer += Metadata.BlockName;
+ Buffer += Metadata.UserInfo;
+ Stream.EmitRecordWithBlob(Abbrev, Record, Buffer);
+
+ // Emit the contents of the extension block.
+ Writer.writeExtensionContents(SemaRef, Stream);
+
+ // Exit the extension block.
+ Stream.ExitBlock();
+}
+
//===----------------------------------------------------------------------===//
// General Serialization Routines
//===----------------------------------------------------------------------===//
@@ -3933,9 +3939,7 @@ void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) {
void ASTWriter::WriteAttributes(ArrayRef<const Attr*> Attrs,
RecordDataImpl &Record) {
Record.push_back(Attrs.size());
- for (ArrayRef<const Attr *>::iterator i = Attrs.begin(),
- e = Attrs.end(); i != e; ++i){
- const Attr *A = *i;
+ for (const auto *A : Attrs) {
Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs
AddSourceRange(A->getRange(), Record);
@@ -3986,7 +3990,7 @@ void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) {
AddString(FilePath, Record);
}
-void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataImpl &Record,
+void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record,
StringRef Path) {
SmallString<128> FilePath(Path);
PreparePathForOutput(FilePath);
@@ -4028,28 +4032,35 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
SelectorOffsets[ID - FirstSelectorID] = Offset;
}
-ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
+ASTWriter::ASTWriter(
+ llvm::BitstreamWriter &Stream,
+ ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
+ bool IncludeTimestamps)
: Stream(Stream), Context(nullptr), PP(nullptr), Chain(nullptr),
- WritingModule(nullptr), WritingAST(false),
- DoneWritingDeclsAndTypes(false), ASTHasCompilerErrors(false),
- FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID),
- FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
- FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID),
- FirstMacroID(NUM_PREDEF_MACRO_IDS), NextMacroID(FirstMacroID),
- FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS),
+ WritingModule(nullptr), IncludeTimestamps(IncludeTimestamps),
+ WritingAST(false), DoneWritingDeclsAndTypes(false),
+ ASTHasCompilerErrors(false), FirstDeclID(NUM_PREDEF_DECL_IDS),
+ NextDeclID(FirstDeclID), FirstTypeID(NUM_PREDEF_TYPE_IDS),
+ NextTypeID(FirstTypeID), FirstIdentID(NUM_PREDEF_IDENT_IDS),
+ NextIdentID(FirstIdentID), FirstMacroID(NUM_PREDEF_MACRO_IDS),
+ NextMacroID(FirstMacroID), FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS),
NextSubmoduleID(FirstSubmoduleID),
FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID),
CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0),
NumLexicalDeclContexts(0), NumVisibleDeclContexts(0),
NextCXXBaseSpecifiersID(1), NextCXXCtorInitializersID(1),
- TypeExtQualAbbrev(0),
- TypeFunctionProtoAbbrev(0), DeclParmVarAbbrev(0),
+ TypeExtQualAbbrev(0), TypeFunctionProtoAbbrev(0), DeclParmVarAbbrev(0),
DeclContextLexicalAbbrev(0), DeclContextVisibleLookupAbbrev(0),
UpdateVisibleAbbrev(0), DeclRecordAbbrev(0), DeclTypedefAbbrev(0),
DeclVarAbbrev(0), DeclFieldAbbrev(0), DeclEnumAbbrev(0),
DeclObjCIvarAbbrev(0), DeclCXXMethodAbbrev(0), DeclRefExprAbbrev(0),
CharacterLiteralAbbrev(0), IntegerLiteralAbbrev(0),
- ExprImplicitCastAbbrev(0) {}
+ ExprImplicitCastAbbrev(0) {
+ for (const auto &Ext : Extensions) {
+ if (auto Writer = Ext->createExtensionWriter(*this))
+ ModuleFileExtensionWriters.push_back(std::move(Writer));
+ }
+}
ASTWriter::~ASTWriter() {
llvm::DeleteContainerSeconds(FileDeclIDs);
@@ -4060,12 +4071,15 @@ const LangOptions &ASTWriter::getLangOpts() const {
return Context->getLangOpts();
}
-void ASTWriter::WriteAST(Sema &SemaRef,
- const std::string &OutputFile,
- Module *WritingModule, StringRef isysroot,
- bool hasErrors) {
+time_t ASTWriter::getTimestampForOutput(const FileEntry *E) const {
+ return IncludeTimestamps ? E->getModificationTime() : 0;
+}
+
+uint64_t ASTWriter::WriteAST(Sema &SemaRef, const std::string &OutputFile,
+ Module *WritingModule, StringRef isysroot,
+ bool hasErrors) {
WritingAST = true;
-
+
ASTHasCompilerErrors = hasErrors;
// Emit the file header.
@@ -4079,13 +4093,15 @@ void ASTWriter::WriteAST(Sema &SemaRef,
Context = &SemaRef.Context;
PP = &SemaRef.PP;
this->WritingModule = WritingModule;
- WriteASTCore(SemaRef, isysroot, OutputFile, WritingModule);
+ ASTFileSignature Signature =
+ WriteASTCore(SemaRef, isysroot, OutputFile, WritingModule);
Context = nullptr;
PP = nullptr;
this->WritingModule = nullptr;
this->BaseDirectory.clear();
WritingAST = false;
+ return Signature;
}
template<typename Vector>
@@ -4097,10 +4113,9 @@ static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec,
}
}
-void ASTWriter::WriteASTCore(Sema &SemaRef,
- StringRef isysroot,
- const std::string &OutputFile,
- Module *WritingModule) {
+uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
+ const std::string &OutputFile,
+ Module *WritingModule) {
using namespace llvm;
bool isModule = WritingModule != nullptr;
@@ -4117,8 +4132,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
if (D) {
assert(D->isCanonicalDecl() && "predefined decl is not canonical");
DeclIDs[D] = ID;
- if (D->getMostRecentDecl() != D)
- Redeclarations.push_back(D);
}
};
RegisterPredefDecl(Context.getTranslationUnitDecl(),
@@ -4133,7 +4146,12 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
RegisterPredefDecl(Context.ObjCInstanceTypeDecl,
PREDEF_DECL_OBJC_INSTANCETYPE_ID);
RegisterPredefDecl(Context.BuiltinVaListDecl, PREDEF_DECL_BUILTIN_VA_LIST_ID);
+ RegisterPredefDecl(Context.VaListTagDecl, PREDEF_DECL_VA_LIST_TAG);
+ RegisterPredefDecl(Context.BuiltinMSVaListDecl,
+ PREDEF_DECL_BUILTIN_MS_VA_LIST_ID);
RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID);
+ RegisterPredefDecl(Context.MakeIntegerSeqDecl,
+ PREDEF_DECL_MAKE_INTEGER_SEQ_ID);
// Build a record containing all of the tentative definitions in this file, in
// TentativeDefinitions order. Generally, this record will be empty for
@@ -4187,11 +4205,9 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// Build a record containing all of pending implicit instantiations.
RecordData PendingInstantiations;
- for (std::deque<Sema::PendingImplicitInstantiation>::iterator
- I = SemaRef.PendingInstantiations.begin(),
- N = SemaRef.PendingInstantiations.end(); I != N; ++I) {
- AddDeclRef(I->first, PendingInstantiations);
- AddSourceLocation(I->second, PendingInstantiations);
+ for (const auto &I : SemaRef.PendingInstantiations) {
+ AddDeclRef(I.first, PendingInstantiations);
+ AddSourceLocation(I.second, PendingInstantiations);
}
assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
"There are local ones at end of translation unit!");
@@ -4210,12 +4226,9 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// Build a record containing all of the known namespaces.
RecordData KnownNamespaces;
- for (llvm::MapVector<NamespaceDecl*, bool>::iterator
- I = SemaRef.KnownNamespaces.begin(),
- IEnd = SemaRef.KnownNamespaces.end();
- I != IEnd; ++I) {
- if (!I->second)
- AddDeclRef(I->first, KnownNamespaces);
+ for (const auto &I : SemaRef.KnownNamespaces) {
+ if (!I.second)
+ AddDeclRef(I.first, KnownNamespaces);
}
// Build a record of all used, undefined objects that require definitions.
@@ -4223,10 +4236,9 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;
SemaRef.getUndefinedButUsed(Undefined);
- for (SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> >::iterator
- I = Undefined.begin(), E = Undefined.end(); I != E; ++I) {
- AddDeclRef(I->first, UndefinedButUsed);
- AddSourceLocation(I->second, UndefinedButUsed);
+ for (const auto &I : Undefined) {
+ AddDeclRef(I.first, UndefinedButUsed);
+ AddSourceLocation(I.second, UndefinedButUsed);
}
// Build a record containing all delete-expressions that we would like to
@@ -4244,41 +4256,43 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
}
// Write the control block
- WriteControlBlock(PP, Context, isysroot, OutputFile);
+ uint64_t Signature = WriteControlBlock(PP, Context, isysroot, OutputFile);
// Write the remaining AST contents.
- RecordData Record;
Stream.EnterSubblock(AST_BLOCK_ID, 5);
// This is so that older clang versions, before the introduction
// of the control block, can read and reject the newer PCH format.
- Record.clear();
- Record.push_back(VERSION_MAJOR);
- Stream.EmitRecord(METADATA_OLD_FORMAT, Record);
+ {
+ RecordData Record = {VERSION_MAJOR};
+ Stream.EmitRecord(METADATA_OLD_FORMAT, Record);
+ }
// Create a lexical update block containing all of the declarations in the
// translation unit that do not come from other AST files.
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
- SmallVector<KindDeclIDPair, 64> NewGlobalDecls;
- for (const auto *I : TU->noload_decls()) {
- if (!I->isFromASTFile())
- NewGlobalDecls.push_back(std::make_pair(I->getKind(), GetDeclRef(I)));
+ SmallVector<uint32_t, 128> NewGlobalKindDeclPairs;
+ for (const auto *D : TU->noload_decls()) {
+ if (!D->isFromASTFile()) {
+ NewGlobalKindDeclPairs.push_back(D->getKind());
+ NewGlobalKindDeclPairs.push_back(GetDeclRef(D));
+ }
}
- llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev();
+ auto *Abv = new llvm::BitCodeAbbrev();
Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));
Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(Abv);
- Record.clear();
- Record.push_back(TU_UPDATE_LEXICAL);
- Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
- bytes(NewGlobalDecls));
-
+ {
+ RecordData::value_type Record[] = {TU_UPDATE_LEXICAL};
+ Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
+ bytes(NewGlobalKindDeclPairs));
+ }
+
// And a visible updates block for the translation unit.
Abv = new llvm::BitCodeAbbrev();
Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));
Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
- Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, 32));
Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
UpdateVisibleAbbrev = Stream.EmitAbbrev(Abv);
WriteDeclContextVisibleUpdate(TU);
@@ -4310,29 +4324,27 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// Make sure visible decls, added to DeclContexts previously loaded from
// an AST file, are registered for serialization.
- for (SmallVectorImpl<const Decl *>::iterator
- I = UpdatingVisibleDecls.begin(),
- E = UpdatingVisibleDecls.end(); I != E; ++I) {
- GetDeclRef(*I);
+ for (const auto *I : UpdatingVisibleDecls) {
+ GetDeclRef(I);
}
// Make sure all decls associated with an identifier are registered for
- // serialization.
- llvm::SmallVector<const IdentifierInfo*, 256> IIs;
- for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(),
- IDEnd = PP.getIdentifierTable().end();
- ID != IDEnd; ++ID) {
- const IdentifierInfo *II = ID->second;
- if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization())
- IIs.push_back(II);
- }
- // Sort the identifiers to visit based on their name.
- std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
- for (const IdentifierInfo *II : IIs) {
- for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II),
- DEnd = SemaRef.IdResolver.end();
- D != DEnd; ++D) {
- GetDeclRef(*D);
+ // serialization, if we're storing decls with identifiers.
+ if (!WritingModule || !getLangOpts().CPlusPlus) {
+ llvm::SmallVector<const IdentifierInfo*, 256> IIs;
+ for (const auto &ID : PP.getIdentifierTable()) {
+ const IdentifierInfo *II = ID.second;
+ if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization())
+ IIs.push_back(II);
+ }
+ // Sort the identifiers to visit based on their name.
+ std::sort(IIs.begin(), IIs.end(), llvm::less_ptr<IdentifierInfo>());
+ for (const IdentifierInfo *II : IIs) {
+ for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II),
+ DEnd = SemaRef.IdResolver.end();
+ D != DEnd; ++D) {
+ GetDeclRef(*D);
+ }
}
}
@@ -4363,7 +4375,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// c++-base-specifiers-id:i32
// type-id:i32)
//
- llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ auto *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(Abbrev);
@@ -4402,8 +4414,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
writeBaseIDOrNone(M->BaseTypeIndex, M->LocalNumTypes);
}
}
- Record.clear();
- Record.push_back(MODULE_OFFSET_MAP);
+ RecordData::value_type Record[] = {MODULE_OFFSET_MAP};
Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record,
Buffer.data(), Buffer.size());
}
@@ -4415,10 +4426,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5);
WriteTypeAbbrevs();
WriteDeclAbbrevs();
- for (DeclsToRewriteTy::iterator I = DeclsToRewrite.begin(),
- E = DeclsToRewrite.end();
- I != E; ++I)
- DeclTypesToEmit.push(const_cast<Decl*>(*I));
do {
WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord);
while (!DeclTypesToEmit.empty()) {
@@ -4442,12 +4449,12 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
WriteCXXCtorInitializersOffsets();
WriteFileDeclIDsMap();
WriteSourceManagerBlock(Context.getSourceManager(), PP);
-
WriteComments();
WritePreprocessor(PP, isModule);
WriteHeaderSearch(PP.getHeaderSearchInfo());
WriteSelectors(SemaRef);
WriteReferencedSelectorsPool(SemaRef);
+ WriteLateParsedTemplates(SemaRef);
WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);
WriteFPPragmaOptions(SemaRef.getFPOptions());
WriteOpenCLExtensions(SemaRef);
@@ -4561,20 +4568,21 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
}
WriteDeclReplacementsBlock();
- WriteRedeclarations();
WriteObjCCategories();
- WriteLateParsedTemplates(SemaRef);
if(!WritingModule)
WriteOptimizePragmaOptions(SemaRef);
// Some simple statistics
- Record.clear();
- Record.push_back(NumStatements);
- Record.push_back(NumMacros);
- Record.push_back(NumLexicalDeclContexts);
- Record.push_back(NumVisibleDeclContexts);
+ RecordData::value_type Record[] = {
+ NumStatements, NumMacros, NumLexicalDeclContexts, NumVisibleDeclContexts};
Stream.EmitRecord(STATISTICS, Record);
Stream.ExitBlock();
+
+ // Write the module file extension blocks.
+ for (const auto &ExtWriter : ModuleFileExtensionWriters)
+ WriteModuleFileExtension(SemaRef, *ExtWriter);
+
+ return Signature;
}
void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
@@ -4586,8 +4594,6 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
for (auto &DeclUpdate : LocalUpdates) {
const Decl *D = DeclUpdate.first;
- if (isRewritten(D))
- continue; // The decl will be written completely,no need to store updates.
bool HasUpdatedBody = false;
RecordData Record;
@@ -4614,6 +4620,11 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
AddSourceLocation(Update.getLoc(), Record);
break;
+ case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT:
+ AddStmt(const_cast<Expr*>(
+ cast<ParmVarDecl>(Update.getDecl())->getDefaultArg()));
+ break;
+
case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
auto *RD = cast<CXXRecordDecl>(D);
UpdatedDeclContexts.insert(RD->getPrimaryContext());
@@ -4699,7 +4710,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
}
if (HasUpdatedBody) {
- const FunctionDecl *Def = cast<FunctionDecl>(D);
+ const auto *Def = cast<FunctionDecl>(D);
Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION);
Record.push_back(Def->isInlined());
AddSourceLocation(Def->getInnerLocStart(), Record);
@@ -4720,11 +4731,10 @@ void ASTWriter::WriteDeclReplacementsBlock() {
return;
RecordData Record;
- for (SmallVectorImpl<ReplacedDeclInfo>::iterator
- I = ReplacedDecls.begin(), E = ReplacedDecls.end(); I != E; ++I) {
- Record.push_back(I->ID);
- Record.push_back(I->Offset);
- Record.push_back(I->Loc);
+ for (const auto &I : ReplacedDecls) {
+ Record.push_back(I.ID);
+ Record.push_back(I.Offset);
+ Record.push_back(I.Loc);
}
Stream.EmitRecord(DECL_REPLACEMENTS, Record);
}
@@ -5247,9 +5257,8 @@ void ASTWriter::AddTemplateName(TemplateName Name, RecordDataImpl &Record) {
case TemplateName::OverloadedTemplate: {
OverloadedTemplateStorage *OvT = Name.getAsOverloadedTemplate();
Record.push_back(OvT->size());
- for (OverloadedTemplateStorage::iterator I = OvT->begin(), E = OvT->end();
- I != E; ++I)
- AddDeclRef(*I, Record);
+ for (const auto &I : *OvT)
+ AddDeclRef(I, Record);
break;
}
@@ -5339,10 +5348,8 @@ ASTWriter::AddTemplateParameterList(const TemplateParameterList *TemplateParams,
AddSourceLocation(TemplateParams->getLAngleLoc(), Record);
AddSourceLocation(TemplateParams->getRAngleLoc(), Record);
Record.push_back(TemplateParams->size());
- for (TemplateParameterList::const_iterator
- P = TemplateParams->begin(), PEnd = TemplateParams->end();
- P != PEnd; ++P)
- AddDeclRef(*P, Record);
+ for (const auto &P : *TemplateParams)
+ AddDeclRef(P, Record);
}
/// \brief Emit a template argument list.
@@ -5657,7 +5664,7 @@ void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) {
void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
assert(D->isCompleteDefinition());
assert(!WritingAST && "Already writing the AST!");
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+ if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
// We are interested when a PCH decl is modified.
if (RD->isFromASTFile()) {
// A forward reference was mutated into a definition. Rewrite it.
@@ -5671,26 +5678,52 @@ void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
}
}
+static bool isImportedDeclContext(ASTReader *Chain, const Decl *D) {
+ if (D->isFromASTFile())
+ return true;
+
+ // If we've not loaded any modules, this can't be imported.
+ if (!Chain || !Chain->getModuleManager().size())
+ return false;
+
+ // The predefined __va_list_tag struct is imported if we imported any decls.
+ // FIXME: This is a gross hack.
+ return D == D->getASTContext().getVaListTagDecl();
+}
+
void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
// TU and namespaces are handled elsewhere.
if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC))
return;
- if (!(!D->isFromASTFile() && cast<Decl>(DC)->isFromASTFile()))
- return; // Not a source decl added to a DeclContext from PCH.
+ // We're only interested in cases where a local declaration is added to an
+ // imported context.
+ if (D->isFromASTFile() || !isImportedDeclContext(Chain, cast<Decl>(DC)))
+ return;
+ assert(DC == DC->getPrimaryContext() && "added to non-primary context");
assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!");
assert(!WritingAST && "Already writing the AST!");
- UpdatedDeclContexts.insert(DC);
+ if (UpdatedDeclContexts.insert(DC) && !cast<Decl>(DC)->isFromASTFile()) {
+ // We're adding a visible declaration to a predefined decl context. Ensure
+ // that we write out all of its lookup results so we don't get a nasty
+ // surprise when we try to emit its lookup table.
+ for (auto *Child : DC->decls())
+ UpdatingVisibleDecls.push_back(Child);
+ }
UpdatingVisibleDecls.push_back(D);
}
void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
assert(D->isImplicit());
- if (!(!D->isFromASTFile() && RD->isFromASTFile()))
- return; // Not a source member added to a class from PCH.
+
+ // We're only interested in cases where a local declaration is added to an
+ // imported context.
+ if (D->isFromASTFile() || !isImportedDeclContext(Chain, RD))
+ return;
+
if (!isa<CXXMethodDecl>(D))
- return; // We are interested in lazily declared implicit methods.
+ return;
// A decl coming from PCH was modified.
assert(RD->isCompleteDefinition());
@@ -5698,42 +5731,6 @@ void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
DeclUpdates[RD].push_back(DeclUpdate(UPD_CXX_ADDED_IMPLICIT_MEMBER, D));
}
-void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
- const ClassTemplateSpecializationDecl *D) {
- // The specializations set is kept in the canonical template.
- TD = TD->getCanonicalDecl();
- if (!(!D->isFromASTFile() && TD->isFromASTFile()))
- return; // Not a source specialization added to a template from PCH.
-
- assert(!WritingAST && "Already writing the AST!");
- DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
- D));
-}
-
-void ASTWriter::AddedCXXTemplateSpecialization(
- const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {
- // The specializations set is kept in the canonical template.
- TD = TD->getCanonicalDecl();
- if (!(!D->isFromASTFile() && TD->isFromASTFile()))
- return; // Not a source specialization added to a template from PCH.
-
- assert(!WritingAST && "Already writing the AST!");
- DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
- D));
-}
-
-void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
- const FunctionDecl *D) {
- // The specializations set is kept in the canonical template.
- TD = TD->getCanonicalDecl();
- if (!(!D->isFromASTFile() && TD->isFromASTFile()))
- return; // Not a source specialization added to a template from PCH.
-
- assert(!WritingAST && "Already writing the AST!");
- DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
- D));
-}
-
void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
assert(!DoneWritingDeclsAndTypes && "Already done writing updates!");
if (!Chain) return;
@@ -5796,6 +5793,15 @@ void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
D->getMemberSpecializationInfo()->getPointOfInstantiation()));
}
+void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {
+ assert(!WritingAST && "Already writing the AST!");
+ if (!D->isFromASTFile())
+ return;
+
+ DeclUpdates[D].push_back(
+ DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT, D));
+}
+
void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {
assert(!WritingAST && "Already writing the AST!");
@@ -5807,21 +5813,6 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const_cast<ObjCInterfaceDecl *>(IFD->getDefinition()));
}
-
-void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
- const ObjCPropertyDecl *OrigProp,
- const ObjCCategoryDecl *ClassExt) {
- const ObjCInterfaceDecl *D = ClassExt->getClassInterface();
- if (!D)
- return;
-
- assert(!WritingAST && "Already writing the AST!");
- if (!D->isFromASTFile())
- return; // Declaration not imported from PCH.
-
- RewriteDecl(D);
-}
-
void ASTWriter::DeclarationMarkedUsed(const Decl *D) {
assert(!WritingAST && "Already writing the AST!");
if (!D->isFromASTFile())
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
index fd6708d..54bba28 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -159,6 +159,22 @@ namespace clang {
Writer.AddStmt(FD->getBody());
}
+ /// Add to the record the first declaration from each module file that
+ /// provides a declaration of D. The intent is to provide a sufficient
+ /// set such that reloading this set will load all current redeclarations.
+ void AddFirstDeclFromEachModule(const Decl *D, bool IncludeLocal) {
+ llvm::MapVector<ModuleFile*, const Decl*> Firsts;
+ // FIXME: We can skip entries that we know are implied by others.
+ for (const Decl *R = D->getMostRecentDecl(); R; R = R->getPreviousDecl()) {
+ if (R->isFromASTFile())
+ Firsts[Writer.Chain->getOwningModuleFile(R)] = R;
+ else if (IncludeLocal)
+ Firsts[nullptr] = R;
+ }
+ for (const auto &F : Firsts)
+ Writer.AddDeclRef(F.second, Record);
+ }
+
/// Get the specialization decl from an entry in the specialization list.
template <typename EntryType>
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
@@ -192,22 +208,48 @@ namespace clang {
auto &&PartialSpecializations = getPartialSpecializations(Common);
ArrayRef<DeclID> LazySpecializations;
if (auto *LS = Common->LazySpecializations)
- LazySpecializations = ArrayRef<DeclID>(LS + 1, LS + 1 + LS[0]);
+ LazySpecializations = llvm::makeArrayRef(LS + 1, LS[0]);
+
+ // Add a slot to the record for the number of specializations.
+ unsigned I = Record.size();
+ Record.push_back(0);
- Record.push_back(Specializations.size() +
- PartialSpecializations.size() +
- LazySpecializations.size());
for (auto &Entry : Specializations) {
auto *D = getSpecializationDecl(Entry);
assert(D->isCanonicalDecl() && "non-canonical decl in set");
- Writer.AddDeclRef(D, Record);
+ AddFirstDeclFromEachModule(D, /*IncludeLocal*/true);
}
for (auto &Entry : PartialSpecializations) {
auto *D = getSpecializationDecl(Entry);
assert(D->isCanonicalDecl() && "non-canonical decl in set");
- Writer.AddDeclRef(D, Record);
+ AddFirstDeclFromEachModule(D, /*IncludeLocal*/true);
}
Record.append(LazySpecializations.begin(), LazySpecializations.end());
+
+ // Update the size entry we added earlier.
+ Record[I] = Record.size() - I - 1;
+ }
+
+ /// Ensure that this template specialization is associated with the specified
+ /// template on reload.
+ void RegisterTemplateSpecialization(const Decl *Template,
+ const Decl *Specialization) {
+ Template = Template->getCanonicalDecl();
+
+ // If the canonical template is local, we'll write out this specialization
+ // when we emit it.
+ // FIXME: We can do the same thing if there is any local declaration of
+ // the template, to avoid emitting an update record.
+ if (!Template->isFromASTFile())
+ return;
+
+ // We only need to associate the first local declaration of the
+ // specialization. The other declarations will get pulled in by it.
+ if (Writer.getFirstLocalDecl(Specialization) != Specialization)
+ return;
+
+ Writer.DeclUpdates[Template].push_back(ASTWriter::DeclUpdate(
+ UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, Specialization));
}
};
}
@@ -218,7 +260,7 @@ void ASTDeclWriter::Visit(Decl *D) {
// Source locations require array (variable-length) abbreviations. The
// abbreviation infrastructure requires that arrays are encoded last, so
// we handle it here in the case of those classes derived from DeclaratorDecl
- if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)){
+ if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
Writer.AddTypeSourceInfo(DD->getTypeSourceInfo(), Record);
}
@@ -234,7 +276,10 @@ void ASTDeclWriter::Visit(Decl *D) {
void ASTDeclWriter::VisitDecl(Decl *D) {
Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
- Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
+ if (D->getDeclContext() != D->getLexicalDeclContext())
+ Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
+ else
+ Record.push_back(0);
Record.push_back(D->isInvalidDecl());
Record.push_back(D->hasAttrs());
if (D->hasAttrs())
@@ -298,7 +343,8 @@ void ASTDeclWriter::VisitTypedefNameDecl(TypedefNameDecl *D) {
void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
VisitTypedefNameDecl(D);
- if (!D->hasAttrs() &&
+ if (D->getDeclContext() == D->getLexicalDeclContext() &&
+ !D->hasAttrs() &&
!D->isImplicit() &&
D->getFirstDecl() == D->getMostRecentDecl() &&
!D->isInvalidDecl() &&
@@ -336,9 +382,6 @@ void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
Record.push_back(2);
Writer.AddDeclRef(TD, Record);
Writer.AddIdentifierRef(TD->getDeclName().getAsIdentifierInfo(), Record);
- } else if (auto *DD = D->getDeclaratorForAnonDecl()) {
- Record.push_back(3);
- Writer.AddDeclRef(DD, Record);
} else {
Record.push_back(0);
}
@@ -363,12 +406,12 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
Writer.AddDeclRef(nullptr, Record);
}
- if (!D->hasAttrs() &&
+ if (D->getDeclContext() == D->getLexicalDeclContext() &&
+ !D->hasAttrs() &&
!D->isImplicit() &&
!D->isUsed(false) &&
!D->hasExtInfo() &&
!D->getTypedefNameForAnonDecl() &&
- !D->getDeclaratorForAnonDecl() &&
D->getFirstDecl() == D->getMostRecentDecl() &&
!D->isInvalidDecl() &&
!D->isReferenced() &&
@@ -392,12 +435,12 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
Record.push_back(D->hasObjectMember());
Record.push_back(D->hasVolatileMember());
- if (!D->hasAttrs() &&
+ if (D->getDeclContext() == D->getLexicalDeclContext() &&
+ !D->hasAttrs() &&
!D->isImplicit() &&
!D->isUsed(false) &&
!D->hasExtInfo() &&
!D->getTypedefNameForAnonDecl() &&
- !D->getDeclaratorForAnonDecl() &&
D->getFirstDecl() == D->getMostRecentDecl() &&
!D->isInvalidDecl() &&
!D->isReferenced() &&
@@ -479,6 +522,9 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
case FunctionDecl::TK_FunctionTemplateSpecialization: {
FunctionTemplateSpecializationInfo *
FTSInfo = D->getTemplateSpecializationInfo();
+
+ RegisterTemplateSpecialization(FTSInfo->getTemplate(), D);
+
Writer.AddDeclRef(FTSInfo->getTemplate(), Record);
Record.push_back(FTSInfo->getTemplateSpecializationKind());
@@ -648,7 +694,8 @@ void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
Record.push_back(D->getAccessControl());
Record.push_back(D->getSynthesize());
- if (!D->hasAttrs() &&
+ if (D->getDeclContext() == D->getLexicalDeclContext() &&
+ !D->hasAttrs() &&
!D->isImplicit() &&
!D->isUsed(false) &&
!D->isInvalidDecl() &&
@@ -780,7 +827,8 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
if (!D->getDeclName())
Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record);
- if (!D->hasAttrs() &&
+ if (D->getDeclContext() == D->getLexicalDeclContext() &&
+ !D->hasAttrs() &&
!D->isImplicit() &&
!D->isUsed(false) &&
!D->isInvalidDecl() &&
@@ -854,7 +902,8 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
Record.push_back(VarNotTemplate);
}
- if (!D->hasAttrs() &&
+ if (D->getDeclContext() == D->getLexicalDeclContext() &&
+ !D->hasAttrs() &&
!D->isImplicit() &&
!D->isUsed(false) &&
!D->isInvalidDecl() &&
@@ -902,7 +951,8 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
// If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here
// we dynamically check for the properties that we optimize for, but don't
// know are true of all PARM_VAR_DECLs.
- if (!D->hasAttrs() &&
+ if (D->getDeclContext() == D->getLexicalDeclContext() &&
+ !D->hasAttrs() &&
!D->hasExtInfo() &&
!D->isImplicit() &&
!D->isUsed(false) &&
@@ -1122,7 +1172,8 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
Record.push_back(0);
}
- if (D->getFirstDecl() == D->getMostRecentDecl() &&
+ if (D->getDeclContext() == D->getLexicalDeclContext() &&
+ D->getFirstDecl() == D->getMostRecentDecl() &&
!D->isInvalidDecl() &&
!D->hasAttrs() &&
!D->isTopLevelDeclInObjCContainer() &&
@@ -1249,6 +1300,8 @@ void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl *D) {
+ RegisterTemplateSpecialization(D->getSpecializedTemplate(), D);
+
VisitCXXRecordDecl(D);
llvm::PointerUnion<ClassTemplateDecl *,
@@ -1308,6 +1361,8 @@ void ASTDeclWriter::VisitVarTemplateDecl(VarTemplateDecl *D) {
void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
VarTemplateSpecializationDecl *D) {
+ RegisterTemplateSpecialization(D->getSpecializedTemplate(), D);
+
VisitVarDecl(D);
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
@@ -1478,48 +1533,77 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
Record.push_back(VisibleOffset);
}
-/// Determine whether D is the first declaration in its redeclaration chain that
-/// is not from an AST file.
-template <typename T>
-static bool isFirstLocalDecl(Redeclarable<T> *D) {
- assert(D && !static_cast<T*>(D)->isFromASTFile());
- do
- D = D->getPreviousDecl();
- while (D && static_cast<T*>(D)->isFromASTFile());
- return !D;
+const Decl *ASTWriter::getFirstLocalDecl(const Decl *D) {
+ /// \brief Is this a local declaration (that is, one that will be written to
+ /// our AST file)? This is the case for declarations that are neither imported
+ /// from another AST file nor predefined.
+ auto IsLocalDecl = [&](const Decl *D) -> bool {
+ if (D->isFromASTFile())
+ return false;
+ auto I = DeclIDs.find(D);
+ return (I == DeclIDs.end() || I->second >= NUM_PREDEF_DECL_IDS);
+ };
+
+ assert(IsLocalDecl(D) && "expected a local declaration");
+
+ const Decl *Canon = D->getCanonicalDecl();
+ if (IsLocalDecl(Canon))
+ return Canon;
+
+ const Decl *&CacheEntry = FirstLocalDeclCache[Canon];
+ if (CacheEntry)
+ return CacheEntry;
+
+ for (const Decl *Redecl = D; Redecl; Redecl = Redecl->getPreviousDecl())
+ if (IsLocalDecl(Redecl))
+ D = Redecl;
+ return CacheEntry = D;
}
template <typename T>
void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
T *First = D->getFirstDecl();
T *MostRecent = First->getMostRecentDecl();
+ T *DAsT = static_cast<T *>(D);
if (MostRecent != First) {
- assert(isRedeclarableDeclKind(static_cast<T *>(D)->getKind()) &&
+ assert(isRedeclarableDeclKind(DAsT->getKind()) &&
"Not considered redeclarable?");
Writer.AddDeclRef(First, Record);
- // In a modules build, emit a list of all imported key declarations
- // (excluding First, if it was imported), so that we can be sure that all
- // redeclarations visible to this module are before D in the redecl chain.
- unsigned I = Record.size();
- Record.push_back(0);
- if (Context.getLangOpts().Modules && Writer.Chain) {
- if (isFirstLocalDecl(D)) {
- Writer.Chain->forEachImportedKeyDecl(First, [&](const Decl *D) {
- if (D != First)
- Writer.AddDeclRef(D, Record);
- });
- Record[I] = Record.size() - I - 1;
-
- // Write a redeclaration chain, attached to the first key decl.
- Writer.Redeclarations.push_back(Writer.Chain->getKeyDeclaration(First));
+ // Write out a list of local redeclarations of this declaration if it's the
+ // first local declaration in the chain.
+ const Decl *FirstLocal = Writer.getFirstLocalDecl(DAsT);
+ if (DAsT == FirstLocal) {
+ // Emit a list of all imported first declarations so that we can be sure
+ // that all redeclarations visible to this module are before D in the
+ // redecl chain.
+ unsigned I = Record.size();
+ Record.push_back(0);
+ if (Writer.Chain)
+ AddFirstDeclFromEachModule(DAsT, /*IncludeLocal*/false);
+ // This is the number of imported first declarations + 1.
+ Record[I] = Record.size() - I;
+
+ // Collect the set of local redeclarations of this declaration, from
+ // newest to oldest.
+ RecordData LocalRedecls;
+ for (const Decl *Prev = FirstLocal->getMostRecentDecl();
+ Prev != FirstLocal; Prev = Prev->getPreviousDecl())
+ if (!Prev->isFromASTFile())
+ Writer.AddDeclRef(Prev, LocalRedecls);
+
+ // If we have any redecls, write them now as a separate record preceding
+ // the declaration itself.
+ if (LocalRedecls.empty())
+ Record.push_back(0);
+ else {
+ Record.push_back(Writer.Stream.GetCurrentBitNo());
+ Writer.Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedecls);
}
- } else if (D == First || D->getPreviousDecl()->isFromASTFile()) {
- assert(isFirstLocalDecl(D) && "imported decl after local decl");
-
- // Write a redeclaration chain attached to the first decl.
- Writer.Redeclarations.push_back(First);
+ } else {
+ Record.push_back(0);
+ Writer.AddDeclRef(FirstLocal, Record);
}
// Make sure that we serialize both the previous and the most-recent
@@ -1558,7 +1642,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(serialization::DECL_FIELD));
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
+ Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext
Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
@@ -1591,7 +1675,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(serialization::DECL_OBJC_IVAR));
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
+ Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext
Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
@@ -1629,7 +1713,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
+ Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext
Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
@@ -1677,7 +1761,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
+ Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext
Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
@@ -1720,7 +1804,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
+ Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext
Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
@@ -1767,7 +1851,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
+ Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext
Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
@@ -1796,7 +1880,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
+ Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext
Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
@@ -1842,7 +1926,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
+ Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext
Abv->Add(BitCodeAbbrevOp(0)); // Invalid
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Implicit
@@ -1949,7 +2033,7 @@ void ASTWriter::WriteDeclAbbrevs() {
//Character Literal
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getValue
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // getKind
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // getKind
CharacterLiteralAbbrev = Stream.EmitAbbrev(Abv);
// Abbreviation for EXPR_IMPLICIT_CAST
@@ -1977,7 +2061,6 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_VISIBLE));
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
DeclContextVisibleLookupAbbrev = Stream.EmitAbbrev(Abv);
}
@@ -1994,14 +2077,19 @@ void ASTWriter::WriteDeclAbbrevs() {
/// clients to use a separate API call to "realize" the decl. This should be
/// relatively painless since they would presumably only do it for top-level
/// decls.
-static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
+static bool isRequiredDecl(const Decl *D, ASTContext &Context,
+ bool WritingModule) {
// An ObjCMethodDecl is never considered as "required" because its
// implementation container always is.
- // File scoped assembly or obj-c implementation must be seen. ImportDecl is
- // used by codegen to determine the set of imported modules to search for
- // inputs for automatic linking.
- if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D) || isa<ImportDecl>(D))
+ // File scoped assembly or obj-c implementation must be seen.
+ if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplDecl>(D))
+ return true;
+
+ // ImportDecl is used by codegen to determine the set of imported modules to
+ // search for inputs for automatic linking; include it if it has a semantic
+ // effect.
+ if (isa<ImportDecl>(D) && !WritingModule)
return true;
return Context.DeclMustBeEmitted(D);
@@ -2016,16 +2104,12 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
// Determine the ID for this declaration.
serialization::DeclID ID;
- if (D->isFromASTFile()) {
- assert(isRewritten(D) && "should not be emitting imported decl");
- ID = getDeclID(D);
- } else {
- serialization::DeclID &IDR = DeclIDs[D];
- if (IDR == 0)
- IDR = NextDeclID++;
+ assert(!D->isFromASTFile() && "should not be emitting imported decl");
+ serialization::DeclID &IDR = DeclIDs[D];
+ if (IDR == 0)
+ IDR = NextDeclID++;
- ID= IDR;
- }
+ ID = IDR;
bool isReplacingADecl = ID < FirstDeclID;
@@ -2050,6 +2134,13 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
}
+ // Build a record for this declaration
+ Record.clear();
+ W.Code = (serialization::DeclCode)0;
+ W.AbbrevToUse = 0;
+ W.Visit(D);
+ if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
+
if (isReplacingADecl) {
// We're replacing a decl in a previous file.
ReplacedDecls.push_back(ReplacedDeclInfo(ID, Stream.GetCurrentBitNo(),
@@ -2066,19 +2157,12 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
DeclOffsets[Index].setLocation(Loc);
DeclOffsets[Index].BitOffset = Stream.GetCurrentBitNo();
}
-
+
SourceManager &SM = Context.getSourceManager();
if (Loc.isValid() && SM.isLocalSourceLocation(Loc))
associateDeclWithFile(D, ID);
}
- // Build and emit a record for this declaration
- Record.clear();
- W.Code = (serialization::DeclCode)0;
- W.AbbrevToUse = 0;
- W.Visit(D);
- if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
-
if (!W.Code)
llvm::report_fatal_error(StringRef("unexpected declaration kind '") +
D->getDeclKindName() + "'");
@@ -2090,7 +2174,7 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
// Note declarations that should be deserialized eagerly so that we can add
// them to a record in the AST file later.
- if (isRequiredDecl(D, Context))
+ if (isRequiredDecl(D, Context, WritingModule))
EagerlyDeserializedDecls.push_back(ID);
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
index 0dd8090..000a218 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -40,7 +40,8 @@ namespace clang {
ASTStmtWriter(ASTWriter &Writer, ASTWriter::RecordData &Record)
: Writer(Writer), Record(Record) { }
- void AddTemplateKWAndArgsInfo(const ASTTemplateKWAndArgsInfo &Args);
+ void AddTemplateKWAndArgsInfo(const ASTTemplateKWAndArgsInfo &ArgInfo,
+ const TemplateArgumentLoc *Args);
void VisitStmt(Stmt *S);
#define STMT(Type, Base) \
@@ -49,13 +50,13 @@ namespace clang {
};
}
-void ASTStmtWriter::
-AddTemplateKWAndArgsInfo(const ASTTemplateKWAndArgsInfo &Args) {
- Writer.AddSourceLocation(Args.getTemplateKeywordLoc(), Record);
- Writer.AddSourceLocation(Args.LAngleLoc, Record);
- Writer.AddSourceLocation(Args.RAngleLoc, Record);
- for (unsigned i=0; i != Args.NumTemplateArgs; ++i)
- Writer.AddTemplateArgumentLoc(Args.getTemplateArgs()[i], Record);
+void ASTStmtWriter::AddTemplateKWAndArgsInfo(
+ const ASTTemplateKWAndArgsInfo &ArgInfo, const TemplateArgumentLoc *Args) {
+ Writer.AddSourceLocation(ArgInfo.TemplateKWLoc, Record);
+ Writer.AddSourceLocation(ArgInfo.LAngleLoc, Record);
+ Writer.AddSourceLocation(ArgInfo.RAngleLoc, Record);
+ for (unsigned i = 0; i != ArgInfo.NumTemplateArgs; ++i)
+ Writer.AddTemplateArgumentLoc(Args[i], Record);
}
void ASTStmtWriter::VisitStmt(Stmt *S) {
@@ -287,6 +288,26 @@ void ASTStmtWriter::VisitMSAsmStmt(MSAsmStmt *S) {
Code = serialization::STMT_MSASM;
}
+void ASTStmtWriter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {
+ // FIXME: Implement coroutine serialization.
+ llvm_unreachable("unimplemented");
+}
+
+void ASTStmtWriter::VisitCoreturnStmt(CoreturnStmt *S) {
+ // FIXME: Implement coroutine serialization.
+ llvm_unreachable("unimplemented");
+}
+
+void ASTStmtWriter::VisitCoawaitExpr(CoawaitExpr *S) {
+ // FIXME: Implement coroutine serialization.
+ llvm_unreachable("unimplemented");
+}
+
+void ASTStmtWriter::VisitCoyieldExpr(CoyieldExpr *S) {
+ // FIXME: Implement coroutine serialization.
+ llvm_unreachable("unimplemented");
+}
+
void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) {
VisitStmt(S);
// NumCaptures
@@ -366,7 +387,8 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
Writer.AddDeclRef(E->getFoundDecl(), Record);
if (E->hasTemplateKWAndArgsInfo())
- AddTemplateKWAndArgsInfo(*E->getTemplateKWAndArgsInfo());
+ AddTemplateKWAndArgsInfo(*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
+ E->getTrailingObjects<TemplateArgumentLoc>());
Writer.AddDeclRef(E->getDecl(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
@@ -462,24 +484,24 @@ void ASTStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) {
Writer.AddSourceLocation(E->getRParenLoc(), Record);
Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
- const OffsetOfExpr::OffsetOfNode &ON = E->getComponent(I);
+ const OffsetOfNode &ON = E->getComponent(I);
Record.push_back(ON.getKind()); // FIXME: Stable encoding
Writer.AddSourceLocation(ON.getSourceRange().getBegin(), Record);
Writer.AddSourceLocation(ON.getSourceRange().getEnd(), Record);
switch (ON.getKind()) {
- case OffsetOfExpr::OffsetOfNode::Array:
+ case OffsetOfNode::Array:
Record.push_back(ON.getArrayExprIndex());
break;
-
- case OffsetOfExpr::OffsetOfNode::Field:
+
+ case OffsetOfNode::Field:
Writer.AddDeclRef(ON.getField(), Record);
break;
-
- case OffsetOfExpr::OffsetOfNode::Identifier:
+
+ case OffsetOfNode::Identifier:
Writer.AddIdentifierRef(ON.getFieldName(), Record);
break;
-
- case OffsetOfExpr::OffsetOfNode::Base:
+
+ case OffsetOfNode::Base:
Writer.AddCXXBaseSpecifier(*ON.getBase(), Record);
break;
}
@@ -511,6 +533,16 @@ void ASTStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
Code = serialization::EXPR_ARRAY_SUBSCRIPT;
}
+void ASTStmtWriter::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getBase());
+ Writer.AddStmt(E->getLowerBound());
+ Writer.AddStmt(E->getLength());
+ Writer.AddSourceLocation(E->getColonLoc(), Record);
+ Writer.AddSourceLocation(E->getRBracketLoc(), Record);
+ Code = serialization::EXPR_OMP_ARRAY_SECTION;
+}
+
void ASTStmtWriter::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumArgs());
@@ -761,6 +793,7 @@ void ASTStmtWriter::VisitVAArgExpr(VAArgExpr *E) {
Writer.AddTypeSourceInfo(E->getWrittenTypeInfo(), Record);
Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
+ Record.push_back(E->isMicrosoftABI());
Code = serialization::EXPR_VA_ARG;
}
@@ -1124,6 +1157,7 @@ void ASTStmtWriter::VisitCXXTryStmt(CXXTryStmt *S) {
void ASTStmtWriter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
VisitStmt(S);
Writer.AddSourceLocation(S->getForLoc(), Record);
+ Writer.AddSourceLocation(S->getCoawaitLoc(), Record);
Writer.AddSourceLocation(S->getColonLoc(), Record);
Writer.AddSourceLocation(S->getRParenLoc(), Record);
Writer.AddStmt(S->getRangeStmt());
@@ -1302,15 +1336,8 @@ void ASTStmtWriter::VisitCXXThrowExpr(CXXThrowExpr *E) {
void ASTStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
VisitExpr(E);
-
- bool HasOtherExprStored = E->Param.getInt();
- // Store these first, the reader reads them before creation.
- Record.push_back(HasOtherExprStored);
- if (HasOtherExprStored)
- Writer.AddStmt(E->getExpr());
Writer.AddDeclRef(E->getParam(), Record);
Writer.AddSourceLocation(E->getUsedLocation(), Record);
-
Code = serialization::EXPR_CXX_DEFAULT_ARG;
}
@@ -1408,9 +1435,11 @@ ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
Record.push_back(E->HasTemplateKWAndArgsInfo);
if (E->HasTemplateKWAndArgsInfo) {
- const ASTTemplateKWAndArgsInfo &Args = *E->getTemplateKWAndArgsInfo();
- Record.push_back(Args.NumTemplateArgs);
- AddTemplateKWAndArgsInfo(Args);
+ const ASTTemplateKWAndArgsInfo &ArgInfo =
+ *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
+ Record.push_back(ArgInfo.NumTemplateArgs);
+ AddTemplateKWAndArgsInfo(ArgInfo,
+ E->getTrailingObjects<TemplateArgumentLoc>());
}
if (!E->isImplicitAccess())
@@ -1435,9 +1464,11 @@ ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
Record.push_back(E->HasTemplateKWAndArgsInfo);
if (E->HasTemplateKWAndArgsInfo) {
- const ASTTemplateKWAndArgsInfo &Args = *E->getTemplateKWAndArgsInfo();
- Record.push_back(Args.NumTemplateArgs);
- AddTemplateKWAndArgsInfo(Args);
+ const ASTTemplateKWAndArgsInfo &ArgInfo =
+ *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
+ Record.push_back(ArgInfo.NumTemplateArgs);
+ AddTemplateKWAndArgsInfo(ArgInfo,
+ E->getTrailingObjects<TemplateArgumentLoc>());
}
Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record);
@@ -1466,9 +1497,10 @@ void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) {
Record.push_back(E->HasTemplateKWAndArgsInfo);
if (E->HasTemplateKWAndArgsInfo) {
- const ASTTemplateKWAndArgsInfo &Args = *E->getTemplateKWAndArgsInfo();
- Record.push_back(Args.NumTemplateArgs);
- AddTemplateKWAndArgsInfo(Args);
+ const ASTTemplateKWAndArgsInfo &ArgInfo =
+ *E->getTrailingASTTemplateKWAndArgsInfo();
+ Record.push_back(ArgInfo.NumTemplateArgs);
+ AddTemplateKWAndArgsInfo(ArgInfo, E->getTrailingTemplateArgumentLoc());
}
Record.push_back(E->getNumDecls());
@@ -1547,11 +1579,18 @@ void ASTStmtWriter::VisitPackExpansionExpr(PackExpansionExpr *E) {
void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
VisitExpr(E);
+ Record.push_back(E->isPartiallySubstituted() ? E->getPartialArguments().size()
+ : 0);
Writer.AddSourceLocation(E->OperatorLoc, Record);
Writer.AddSourceLocation(E->PackLoc, Record);
Writer.AddSourceLocation(E->RParenLoc, Record);
- Record.push_back(E->Length);
Writer.AddDeclRef(E->Pack, Record);
+ if (E->isPartiallySubstituted()) {
+ for (const auto &TA : E->getPartialArguments())
+ Writer.AddTemplateArgument(TA, Record);
+ } else if (!E->isValueDependent()) {
+ Record.push_back(E->getPackLength());
+ }
Code = serialization::EXPR_SIZEOF_PACK;
}
@@ -1650,6 +1689,14 @@ void ASTStmtWriter::VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
Code = serialization::EXPR_CXX_PROPERTY_REF_EXPR;
}
+void ASTStmtWriter::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) {
+ VisitExpr(E);
+ Writer.AddStmt(E->getBase());
+ Writer.AddStmt(E->getIdx());
+ Writer.AddSourceLocation(E->getRBracketLoc(), Record);
+ Code = serialization::EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR;
+}
+
void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
VisitExpr(E);
Writer.AddSourceRange(E->getSourceRange(), Record);
@@ -1718,6 +1765,9 @@ void OMPClauseWriter::writeClause(OMPClause *C) {
}
void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) {
+ Record.push_back(C->getNameModifier());
+ Writer->Writer.AddSourceLocation(C->getNameModifierLoc(), Record);
+ Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
Writer->Writer.AddStmt(C->getCondition());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}
@@ -1737,6 +1787,11 @@ void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) {
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}
+void OMPClauseWriter::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
+ Writer->Writer.AddStmt(C->getSimdlen());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) {
Writer->Writer.AddStmt(C->getNumForLoops());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
@@ -1756,14 +1811,21 @@ void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) {
void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {
Record.push_back(C->getScheduleKind());
+ Record.push_back(C->getFirstScheduleModifier());
+ Record.push_back(C->getSecondScheduleModifier());
Writer->Writer.AddStmt(C->getChunkSize());
Writer->Writer.AddStmt(C->getHelperChunkSize());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+ Writer->Writer.AddSourceLocation(C->getFirstScheduleModifierLoc(), Record);
+ Writer->Writer.AddSourceLocation(C->getSecondScheduleModifierLoc(), Record);
Writer->Writer.AddSourceLocation(C->getScheduleKindLoc(), Record);
Writer->Writer.AddSourceLocation(C->getCommaLoc(), Record);
}
-void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *) {}
+void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) {
+ Writer->Writer.AddStmt(C->getNumForLoops());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
void OMPClauseWriter::VisitOMPNowaitClause(OMPNowaitClause *) {}
@@ -1781,6 +1843,12 @@ void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {}
void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
+void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {}
+
+void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {}
+
+void OMPClauseWriter::VisitOMPNogroupClause(OMPNogroupClause *) {}
+
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
@@ -1836,6 +1904,8 @@ void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) {
Writer->Writer.AddDeclarationNameInfo(C->getNameInfo(), Record);
for (auto *VE : C->varlists())
Writer->Writer.AddStmt(VE);
+ for (auto *VE : C->privates())
+ Writer->Writer.AddStmt(VE);
for (auto *E : C->lhs_exprs())
Writer->Writer.AddStmt(E);
for (auto *E : C->rhs_exprs())
@@ -1848,9 +1918,14 @@ void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
+ Record.push_back(C->getModifier());
+ Writer->Writer.AddSourceLocation(C->getModifierLoc(), Record);
for (auto *VE : C->varlists()) {
Writer->Writer.AddStmt(VE);
}
+ for (auto *VE : C->privates()) {
+ Writer->Writer.AddStmt(VE);
+ }
for (auto *VE : C->inits()) {
Writer->Writer.AddStmt(VE);
}
@@ -1916,6 +1991,52 @@ void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
Writer->Writer.AddStmt(VE);
}
+void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ Writer->Writer.AddStmt(C->getDevice());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
+void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) {
+ Record.push_back(C->varlist_size());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+ Record.push_back(C->getMapTypeModifier());
+ Record.push_back(C->getMapType());
+ Writer->Writer.AddSourceLocation(C->getMapLoc(), Record);
+ Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
+ for (auto *VE : C->varlists())
+ Writer->Writer.AddStmt(VE);
+}
+
+void OMPClauseWriter::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) {
+ Writer->Writer.AddStmt(C->getNumTeams());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
+void OMPClauseWriter::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) {
+ Writer->Writer.AddStmt(C->getThreadLimit());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
+void OMPClauseWriter::VisitOMPPriorityClause(OMPPriorityClause *C) {
+ Writer->Writer.AddStmt(C->getPriority());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
+void OMPClauseWriter::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
+ Writer->Writer.AddStmt(C->getGrainsize());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
+void OMPClauseWriter::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
+ Writer->Writer.AddStmt(C->getNumTasks());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
+void OMPClauseWriter::VisitOMPHintClause(OMPHintClause *C) {
+ Writer->Writer.AddStmt(C->getHint());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
@@ -1954,6 +2075,9 @@ void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) {
for (auto I : D->counters()) {
Writer.AddStmt(I);
}
+ for (auto I : D->private_counters()) {
+ Writer.AddStmt(I);
+ }
for (auto I : D->inits()) {
Writer.AddStmt(I);
}
@@ -1969,6 +2093,7 @@ void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) {
VisitStmt(D);
Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
+ Record.push_back(D->hasCancel() ? 1 : 0);
Code = serialization::STMT_OMP_PARALLEL_DIRECTIVE;
}
@@ -1979,6 +2104,7 @@ void ASTStmtWriter::VisitOMPSimdDirective(OMPSimdDirective *D) {
void ASTStmtWriter::VisitOMPForDirective(OMPForDirective *D) {
VisitOMPLoopDirective(D);
+ Record.push_back(D->hasCancel() ? 1 : 0);
Code = serialization::STMT_OMP_FOR_DIRECTIVE;
}
@@ -1991,12 +2117,14 @@ void ASTStmtWriter::VisitOMPSectionsDirective(OMPSectionsDirective *D) {
VisitStmt(D);
Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
+ Record.push_back(D->hasCancel() ? 1 : 0);
Code = serialization::STMT_OMP_SECTIONS_DIRECTIVE;
}
void ASTStmtWriter::VisitOMPSectionDirective(OMPSectionDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
+ Record.push_back(D->hasCancel() ? 1 : 0);
Code = serialization::STMT_OMP_SECTION_DIRECTIVE;
}
@@ -2015,6 +2143,7 @@ void ASTStmtWriter::VisitOMPMasterDirective(OMPMasterDirective *D) {
void ASTStmtWriter::VisitOMPCriticalDirective(OMPCriticalDirective *D) {
VisitStmt(D);
+ Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
Writer.AddDeclarationNameInfo(D->getDirectiveName(), Record);
Code = serialization::STMT_OMP_CRITICAL_DIRECTIVE;
@@ -2022,6 +2151,7 @@ void ASTStmtWriter::VisitOMPCriticalDirective(OMPCriticalDirective *D) {
void ASTStmtWriter::VisitOMPParallelForDirective(OMPParallelForDirective *D) {
VisitOMPLoopDirective(D);
+ Record.push_back(D->hasCancel() ? 1 : 0);
Code = serialization::STMT_OMP_PARALLEL_FOR_DIRECTIVE;
}
@@ -2036,6 +2166,7 @@ void ASTStmtWriter::VisitOMPParallelSectionsDirective(
VisitStmt(D);
Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
+ Record.push_back(D->hasCancel() ? 1 : 0);
Code = serialization::STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE;
}
@@ -2043,6 +2174,7 @@ void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) {
VisitStmt(D);
Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
+ Record.push_back(D->hasCancel() ? 1 : 0);
Code = serialization::STMT_OMP_TASK_DIRECTIVE;
}
@@ -2066,6 +2198,13 @@ void ASTStmtWriter::VisitOMPTargetDirective(OMPTargetDirective *D) {
Code = serialization::STMT_OMP_TARGET_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPTargetDataDirective(OMPTargetDataDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_TARGET_DATA_DIRECTIVE;
+}
+
void ASTStmtWriter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
@@ -2099,6 +2238,7 @@ void ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective *D) {
void ASTStmtWriter::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
VisitStmt(D);
+ Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
Code = serialization::STMT_OMP_ORDERED_DIRECTIVE;
}
@@ -2120,11 +2260,27 @@ void ASTStmtWriter::VisitOMPCancellationPointDirective(
void ASTStmtWriter::VisitOMPCancelDirective(OMPCancelDirective *D) {
VisitStmt(D);
+ Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
Record.push_back(D->getCancelRegion());
Code = serialization::STMT_OMP_CANCEL_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_TASKLOOP_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTaskLoopSimdDirective(OMPTaskLoopSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_TASKLOOP_SIMD_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPDistributeDirective(OMPDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_DISTRIBUTE_DIRECTIVE;
+}
+
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp
index c461fe9..4a2255a 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/GeneratePCH.cpp
@@ -23,12 +23,15 @@
using namespace clang;
-PCHGenerator::PCHGenerator(const Preprocessor &PP, StringRef OutputFile,
- clang::Module *Module, StringRef isysroot,
- std::shared_ptr<PCHBuffer> Buffer,
- bool AllowASTWithErrors)
+PCHGenerator::PCHGenerator(
+ const Preprocessor &PP, StringRef OutputFile,
+ clang::Module *Module, StringRef isysroot,
+ std::shared_ptr<PCHBuffer> Buffer,
+ ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
+ bool AllowASTWithErrors, bool IncludeTimestamps)
: PP(PP), OutputFile(OutputFile), Module(Module), isysroot(isysroot.str()),
- SemaPtr(nullptr), Buffer(Buffer), Stream(Buffer->Data), Writer(Stream),
+ SemaPtr(nullptr), Buffer(Buffer), Stream(Buffer->Data),
+ Writer(Stream, Extensions, IncludeTimestamps),
AllowASTWithErrors(AllowASTWithErrors) {
Buffer->IsComplete = false;
}
@@ -47,7 +50,8 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
// Emit the PCH file to the Buffer.
assert(SemaPtr && "No Sema?");
- Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot, hasErrors);
+ Buffer->Signature =
+ Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot, hasErrors);
Buffer->IsComplete = true;
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
index 17c7914..af5f94a 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/GlobalModuleIndex.cpp
@@ -757,9 +757,7 @@ void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev);
// Write the identifier table
- Record.clear();
- Record.push_back(IDENTIFIER_INDEX);
- Record.push_back(BucketOffset);
+ uint64_t Record[] = {IDENTIFIER_INDEX, BucketOffset};
Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable);
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp
index 3b237d5..4884f0b 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/Module.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/Module.cpp
@@ -40,19 +40,11 @@ ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation)
LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(nullptr),
LocalNumCXXCtorInitializers(0), CXXCtorInitializersOffsets(nullptr),
FileSortedDecls(nullptr), NumFileSortedDecls(0),
- RedeclarationsMap(nullptr), LocalNumRedeclarationsInMap(0),
ObjCCategoriesMap(nullptr), LocalNumObjCCategoriesInMap(0),
LocalNumTypes(0), TypeOffsets(nullptr), BaseTypeIndex(0)
{}
ModuleFile::~ModuleFile() {
- for (DeclContextInfosMap::iterator I = DeclContextInfos.begin(),
- E = DeclContextInfos.end();
- I != E; ++I) {
- if (I->second.NameLookupTableData)
- delete I->second.NameLookupTableData;
- }
-
delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable);
delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable);
delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable);
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ModuleFileExtension.cpp b/contrib/llvm/tools/clang/lib/Serialization/ModuleFileExtension.cpp
new file mode 100644
index 0000000..81dcfd6
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Serialization/ModuleFileExtension.cpp
@@ -0,0 +1,22 @@
+//===-- ModuleFileExtension.cpp - Module File Extensions ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Serialization/ModuleFileExtension.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+ModuleFileExtension::~ModuleFileExtension() { }
+
+llvm::hash_code ModuleFileExtension::hashExtension(llvm::hash_code Code) const {
+ return Code;
+}
+
+ModuleFileExtensionWriter::~ModuleFileExtensionWriter() { }
+
+ModuleFileExtensionReader::~ModuleFileExtensionReader() { }
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
index 2716194..74f75a1 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp
@@ -95,6 +95,8 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
New->File = Entry;
New->ImportLoc = ImportLoc;
Chain.push_back(New);
+ if (!New->isModule())
+ PCHChain.push_back(New);
if (!ImportedBy)
Roots.push_back(New);
NewModule = true;
@@ -159,6 +161,8 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
Modules.erase(Entry);
assert(Chain.back() == ModuleEntry);
Chain.pop_back();
+ if (!ModuleEntry->isModule())
+ PCHChain.pop_back();
if (Roots.back() == ModuleEntry)
Roots.pop_back();
else
@@ -190,6 +194,9 @@ void ModuleManager::removeModules(
if (first == last)
return;
+ // Explicitly clear VisitOrder since we might not notice it is stale.
+ VisitOrder.clear();
+
// Collect the set of module file pointers that we'll be removing.
llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last);
@@ -203,6 +210,15 @@ void ModuleManager::removeModules(
Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim),
Roots.end());
+ // Remove the modules from the PCH chain.
+ for (auto I = first; I != last; ++I) {
+ if (!(*I)->isModule()) {
+ PCHChain.erase(std::find(PCHChain.begin(), PCHChain.end(), *I),
+ PCHChain.end());
+ break;
+ }
+ }
+
// Delete the modules and erase them from the various structures.
for (ModuleIterator victim = first; victim != last; ++victim) {
Modules.erase((*victim)->File);
@@ -236,15 +252,6 @@ ModuleManager::addInMemoryBuffer(StringRef FileName,
InMemoryBuffers[Entry] = std::move(Buffer);
}
-bool ModuleManager::addKnownModuleFile(StringRef FileName) {
- const FileEntry *File;
- if (lookupModuleFile(FileName, 0, 0, File))
- return true;
- if (!Modules.count(File))
- AdditionalKnownModuleFiles.insert(File);
- return false;
-}
-
ModuleManager::VisitState *ModuleManager::allocateVisitState() {
// Fast path: if we have a cached state, use it.
if (FirstVisitState) {
@@ -281,8 +288,6 @@ void ModuleManager::setGlobalIndex(GlobalModuleIndex *Index) {
}
void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
- AdditionalKnownModuleFiles.remove(MF->File);
-
if (!GlobalIndex || GlobalIndex->loadedModuleFile(MF))
return;
@@ -300,10 +305,8 @@ ModuleManager::~ModuleManager() {
delete FirstVisitState;
}
-void
-ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
- void *UserData,
- llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
+void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
+ llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
// If the visitation order vector is the wrong size, recompute the order.
if (VisitOrder.size() != Chain.size()) {
unsigned N = size();
@@ -316,28 +319,24 @@ ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
SmallVector<ModuleFile *, 4> Queue;
Queue.reserve(N);
llvm::SmallVector<unsigned, 4> UnusedIncomingEdges;
- UnusedIncomingEdges.reserve(size());
- for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) {
- if (unsigned Size = (*M)->ImportedBy.size())
- UnusedIncomingEdges.push_back(Size);
- else {
- UnusedIncomingEdges.push_back(0);
+ UnusedIncomingEdges.resize(size());
+ for (auto M = rbegin(), MEnd = rend(); M != MEnd; ++M) {
+ unsigned Size = (*M)->ImportedBy.size();
+ UnusedIncomingEdges[(*M)->Index] = Size;
+ if (!Size)
Queue.push_back(*M);
- }
}
// Traverse the graph, making sure to visit a module before visiting any
// of its dependencies.
- unsigned QueueStart = 0;
- while (QueueStart < Queue.size()) {
- ModuleFile *CurrentModule = Queue[QueueStart++];
+ while (!Queue.empty()) {
+ ModuleFile *CurrentModule = Queue.pop_back_val();
VisitOrder.push_back(CurrentModule);
// For any module that this module depends on, push it on the
// stack (if it hasn't already been marked as visited).
- for (llvm::SetVector<ModuleFile *>::iterator
- M = CurrentModule->Imports.begin(),
- MEnd = CurrentModule->Imports.end();
+ for (auto M = CurrentModule->Imports.rbegin(),
+ MEnd = CurrentModule->Imports.rend();
M != MEnd; ++M) {
// Remove our current module as an impediment to visiting the
// module we depend on. If we were the last unvisited module
@@ -379,7 +378,7 @@ ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
// Visit the module.
assert(State->VisitNumber[CurrentModule->Index] == VisitNumber - 1);
State->VisitNumber[CurrentModule->Index] = VisitNumber;
- if (!Visitor(*CurrentModule, UserData))
+ if (!Visitor(*CurrentModule))
continue;
// The visitor has requested that cut off visitation of any
@@ -410,71 +409,6 @@ ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
returnVisitState(State);
}
-static void markVisitedDepthFirst(ModuleFile &M,
- SmallVectorImpl<bool> &Visited) {
- for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(),
- IMEnd = M.Imports.end();
- IM != IMEnd; ++IM) {
- if (Visited[(*IM)->Index])
- continue;
- Visited[(*IM)->Index] = true;
- if (!M.DirectlyImported)
- markVisitedDepthFirst(**IM, Visited);
- }
-}
-
-/// \brief Perform a depth-first visit of the current module.
-static bool visitDepthFirst(
- ModuleFile &M,
- ModuleManager::DFSPreorderControl (*PreorderVisitor)(ModuleFile &M,
- void *UserData),
- bool (*PostorderVisitor)(ModuleFile &M, void *UserData), void *UserData,
- SmallVectorImpl<bool> &Visited) {
- if (PreorderVisitor) {
- switch (PreorderVisitor(M, UserData)) {
- case ModuleManager::Abort:
- return true;
- case ModuleManager::SkipImports:
- markVisitedDepthFirst(M, Visited);
- return false;
- case ModuleManager::Continue:
- break;
- }
- }
-
- // Visit children
- for (llvm::SetVector<ModuleFile *>::iterator IM = M.Imports.begin(),
- IMEnd = M.Imports.end();
- IM != IMEnd; ++IM) {
- if (Visited[(*IM)->Index])
- continue;
- Visited[(*IM)->Index] = true;
-
- if (visitDepthFirst(**IM, PreorderVisitor, PostorderVisitor, UserData, Visited))
- return true;
- }
-
- if (PostorderVisitor)
- return PostorderVisitor(M, UserData);
-
- return false;
-}
-
-void ModuleManager::visitDepthFirst(
- ModuleManager::DFSPreorderControl (*PreorderVisitor)(ModuleFile &M,
- void *UserData),
- bool (*PostorderVisitor)(ModuleFile &M, void *UserData), void *UserData) {
- SmallVector<bool, 16> Visited(size(), false);
- for (unsigned I = 0, N = Roots.size(); I != N; ++I) {
- if (Visited[Roots[I]->Index])
- continue;
- Visited[Roots[I]->Index] = true;
-
- if (::visitDepthFirst(*Roots[I], PreorderVisitor, PostorderVisitor, UserData, Visited))
- return;
- }
-}
-
bool ModuleManager::lookupModuleFile(StringRef FileName,
off_t ExpectedSize,
time_t ExpectedModTime,
diff --git a/contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h b/contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h
new file mode 100644
index 0000000..04dea83
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Serialization/MultiOnDiskHashTable.h
@@ -0,0 +1,330 @@
+//===--- MultiOnDiskHashTable.h - Merged set of hash tables -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a hash table data structure suitable for incremental and
+// distributed storage across a set of files.
+//
+// Multiple hash tables from different files are implicitly merged to improve
+// performance, and on reload the merged table will override those from other
+// files.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H
+#define LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H
+
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/OnDiskHashTable.h"
+
+namespace clang {
+namespace serialization {
+
+class ModuleFile;
+
+/// \brief A collection of on-disk hash tables, merged when relevant for performance.
+template<typename Info> class MultiOnDiskHashTable {
+public:
+ /// A handle to a file, used when overriding tables.
+ typedef typename Info::file_type file_type;
+ /// A pointer to an on-disk representation of the hash table.
+ typedef const unsigned char *storage_type;
+
+ typedef typename Info::external_key_type external_key_type;
+ typedef typename Info::internal_key_type internal_key_type;
+ typedef typename Info::data_type data_type;
+ typedef typename Info::data_type_builder data_type_builder;
+ typedef unsigned hash_value_type;
+
+private:
+ /// \brief A hash table stored on disk.
+ struct OnDiskTable {
+ typedef llvm::OnDiskIterableChainedHashTable<Info> HashTable;
+
+ file_type File;
+ HashTable Table;
+
+ OnDiskTable(file_type File, unsigned NumBuckets, unsigned NumEntries,
+ storage_type Buckets, storage_type Payload, storage_type Base,
+ const Info &InfoObj)
+ : File(File),
+ Table(NumBuckets, NumEntries, Buckets, Payload, Base, InfoObj) {}
+ };
+
+ struct MergedTable {
+ std::vector<file_type> Files;
+ llvm::DenseMap<internal_key_type, data_type> Data;
+ };
+
+ typedef llvm::PointerUnion<OnDiskTable*, MergedTable*> Table;
+ typedef llvm::TinyPtrVector<void*> TableVector;
+
+ /// \brief The current set of on-disk and merged tables.
+ /// We manually store the opaque value of the Table because TinyPtrVector
+ /// can't cope with holding a PointerUnion directly.
+ /// There can be at most one MergedTable in this vector, and if present,
+ /// it is the first table.
+ TableVector Tables;
+
+ /// \brief Files corresponding to overridden tables that we've not yet
+ /// discarded.
+ llvm::TinyPtrVector<file_type> PendingOverrides;
+
+ struct AsOnDiskTable {
+ typedef OnDiskTable *result_type;
+ result_type operator()(void *P) const {
+ return Table::getFromOpaqueValue(P).template get<OnDiskTable *>();
+ }
+ };
+ typedef llvm::mapped_iterator<TableVector::iterator, AsOnDiskTable>
+ table_iterator;
+ typedef llvm::iterator_range<table_iterator> table_range;
+
+ /// \brief The current set of on-disk tables.
+ table_range tables() {
+ auto Begin = Tables.begin(), End = Tables.end();
+ if (getMergedTable())
+ ++Begin;
+ return llvm::make_range(llvm::map_iterator(Begin, AsOnDiskTable()),
+ llvm::map_iterator(End, AsOnDiskTable()));
+ }
+
+ MergedTable *getMergedTable() const {
+ // If we already have a merged table, it's the first one.
+ return Tables.empty() ? nullptr : Table::getFromOpaqueValue(*Tables.begin())
+ .template dyn_cast<MergedTable*>();
+ }
+
+ /// \brief Delete all our current on-disk tables.
+ void clear() {
+ for (auto *T : tables())
+ delete T;
+ if (auto *M = getMergedTable())
+ delete M;
+ Tables.clear();
+ }
+
+ void removeOverriddenTables() {
+ llvm::DenseSet<file_type> Files;
+ Files.insert(PendingOverrides.begin(), PendingOverrides.end());
+ // Explicitly capture Files to work around an MSVC 2015 rejects-valid bug.
+ auto ShouldRemove = [&Files](void *T) -> bool {
+ auto *ODT = Table::getFromOpaqueValue(T).template get<OnDiskTable *>();
+ bool Remove = Files.count(ODT->File);
+ if (Remove)
+ delete ODT;
+ return Remove;
+ };
+ Tables.erase(std::remove_if(tables().begin().getCurrent(), Tables.end(),
+ ShouldRemove),
+ Tables.end());
+ PendingOverrides.clear();
+ }
+
+ void condense() {
+ MergedTable *Merged = getMergedTable();
+ if (!Merged)
+ Merged = new MergedTable;
+
+ // Read in all the tables and merge them together.
+ // FIXME: Be smarter about which tables we merge.
+ for (auto *ODT : tables()) {
+ auto &HT = ODT->Table;
+ Info &InfoObj = HT.getInfoObj();
+
+ for (auto I = HT.data_begin(), E = HT.data_end(); I != E; ++I) {
+ auto *LocalPtr = I.getItem();
+
+ // FIXME: Don't rely on the OnDiskHashTable format here.
+ auto L = InfoObj.ReadKeyDataLength(LocalPtr);
+ const internal_key_type &Key = InfoObj.ReadKey(LocalPtr, L.first);
+ data_type_builder ValueBuilder(Merged->Data[Key]);
+ InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second,
+ ValueBuilder);
+ }
+
+ Merged->Files.push_back(ODT->File);
+ delete ODT;
+ }
+
+ Tables.clear();
+ Tables.push_back(Table(Merged).getOpaqueValue());
+ }
+
+ /// The generator is permitted to read our merged table.
+ template<typename ReaderInfo, typename WriterInfo>
+ friend class MultiOnDiskHashTableGenerator;
+
+public:
+ MultiOnDiskHashTable() {}
+ MultiOnDiskHashTable(MultiOnDiskHashTable &&O)
+ : Tables(std::move(O.Tables)),
+ PendingOverrides(std::move(O.PendingOverrides)) {
+ O.Tables.clear();
+ }
+ MultiOnDiskHashTable &operator=(MultiOnDiskHashTable &&O) {
+ if (&O == this)
+ return *this;
+ clear();
+ Tables = std::move(O.Tables);
+ O.Tables.clear();
+ PendingOverrides = std::move(O.PendingOverrides);
+ return *this;
+ }
+ ~MultiOnDiskHashTable() { clear(); }
+
+ /// \brief Add the table \p Data loaded from file \p File.
+ void add(file_type File, storage_type Data, Info InfoObj = Info()) {
+ using namespace llvm::support;
+ storage_type Ptr = Data;
+
+ uint32_t BucketOffset = endian::readNext<uint32_t, little, unaligned>(Ptr);
+
+ // Read the list of overridden files.
+ uint32_t NumFiles = endian::readNext<uint32_t, little, unaligned>(Ptr);
+ // FIXME: Add a reserve() to TinyPtrVector so that we don't need to make
+ // an additional copy.
+ llvm::SmallVector<file_type, 16> OverriddenFiles;
+ OverriddenFiles.reserve(NumFiles);
+ for (/**/; NumFiles != 0; --NumFiles)
+ OverriddenFiles.push_back(InfoObj.ReadFileRef(Ptr));
+ PendingOverrides.insert(PendingOverrides.end(), OverriddenFiles.begin(),
+ OverriddenFiles.end());
+
+ // Read the OnDiskChainedHashTable header.
+ storage_type Buckets = Data + BucketOffset;
+ auto NumBucketsAndEntries =
+ OnDiskTable::HashTable::readNumBucketsAndEntries(Buckets);
+
+ // Register the table.
+ Table NewTable = new OnDiskTable(File, NumBucketsAndEntries.first,
+ NumBucketsAndEntries.second,
+ Buckets, Ptr, Data, std::move(InfoObj));
+ Tables.push_back(NewTable.getOpaqueValue());
+ }
+
+ /// \brief Find and read the lookup results for \p EKey.
+ data_type find(const external_key_type &EKey) {
+ data_type Result;
+
+ if (!PendingOverrides.empty())
+ removeOverriddenTables();
+
+ if (Tables.size() > static_cast<unsigned>(Info::MaxTables))
+ condense();
+
+ internal_key_type Key = Info::GetInternalKey(EKey);
+ auto KeyHash = Info::ComputeHash(Key);
+
+ if (MergedTable *M = getMergedTable()) {
+ auto It = M->Data.find(Key);
+ if (It != M->Data.end())
+ Result = It->second;
+ }
+
+ data_type_builder ResultBuilder(Result);
+
+ for (auto *ODT : tables()) {
+ auto &HT = ODT->Table;
+ auto It = HT.find_hashed(Key, KeyHash);
+ if (It != HT.end())
+ HT.getInfoObj().ReadDataInto(Key, It.getDataPtr(), It.getDataLen(),
+ ResultBuilder);
+ }
+
+ return Result;
+ }
+
+ /// \brief Read all the lookup results into a single value. This only makes
+ /// sense if merging values across keys is meaningful.
+ data_type findAll() {
+ data_type Result;
+ data_type_builder ResultBuilder(Result);
+
+ if (!PendingOverrides.empty())
+ removeOverriddenTables();
+
+ if (MergedTable *M = getMergedTable()) {
+ for (auto &KV : M->Data)
+ Info::MergeDataInto(KV.second, ResultBuilder);
+ }
+
+ for (auto *ODT : tables()) {
+ auto &HT = ODT->Table;
+ Info &InfoObj = HT.getInfoObj();
+ for (auto I = HT.data_begin(), E = HT.data_end(); I != E; ++I) {
+ auto *LocalPtr = I.getItem();
+
+ // FIXME: Don't rely on the OnDiskHashTable format here.
+ auto L = InfoObj.ReadKeyDataLength(LocalPtr);
+ const internal_key_type &Key = InfoObj.ReadKey(LocalPtr, L.first);
+ InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second, ResultBuilder);
+ }
+ }
+
+ return Result;
+ }
+};
+
+/// \brief Writer for the on-disk hash table.
+template<typename ReaderInfo, typename WriterInfo>
+class MultiOnDiskHashTableGenerator {
+ typedef MultiOnDiskHashTable<ReaderInfo> BaseTable;
+ typedef llvm::OnDiskChainedHashTableGenerator<WriterInfo> Generator;
+
+ Generator Gen;
+
+public:
+ MultiOnDiskHashTableGenerator() : Gen() {}
+
+ void insert(typename WriterInfo::key_type_ref Key,
+ typename WriterInfo::data_type_ref Data, WriterInfo &Info) {
+ Gen.insert(Key, Data, Info);
+ }
+
+ void emit(llvm::SmallVectorImpl<char> &Out, WriterInfo &Info,
+ const BaseTable *Base) {
+ using namespace llvm::support;
+ llvm::raw_svector_ostream OutStream(Out);
+
+ // Write our header information.
+ {
+ endian::Writer<little> Writer(OutStream);
+
+ // Reserve four bytes for the bucket offset.
+ Writer.write<uint32_t>(0);
+
+ if (auto *Merged = Base ? Base->getMergedTable() : nullptr) {
+ // Write list of overridden files.
+ Writer.write<uint32_t>(Merged->Files.size());
+ for (const auto &F : Merged->Files)
+ Info.EmitFileRef(OutStream, F);
+
+ // Add all merged entries from Base to the generator.
+ for (auto &KV : Merged->Data) {
+ if (!Gen.contains(KV.first, Info))
+ Gen.insert(KV.first, Info.ImportData(KV.second), Info);
+ }
+ } else {
+ Writer.write<uint32_t>(0);
+ }
+ }
+
+ // Write the table itself.
+ uint32_t BucketOffset = Gen.Emit(OutStream, Info);
+
+ // Replace the first four bytes with the bucket offset.
+ endian::write32le(Out.data(), BucketOffset);
+ }
+};
+
+} // end namespace clang::serialization
+} // end namespace clang
+
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
index 166471a..a052d83 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
@@ -101,7 +101,7 @@ void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G,
else if (isa<BlockDecl>(D)) {
output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn();
}
-
+
NumBlocksUnreachable += unreachable;
NumBlocks += total;
std::string NameOfRootFunction = output.str();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
index 557439b..c092610 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
@@ -23,7 +23,7 @@ using namespace clang;
using namespace ento;
namespace {
-class ArrayBoundChecker :
+class ArrayBoundChecker :
public Checker<check::Location> {
mutable std::unique_ptr<BuiltinBug> BT;
@@ -55,17 +55,17 @@ void ArrayBoundChecker::checkLocation(SVal l, bool isLoad, const Stmt* LoadS,
ProgramStateRef state = C.getState();
// Get the size of the array.
- DefinedOrUnknownSVal NumElements
- = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
+ DefinedOrUnknownSVal NumElements
+ = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
ER->getValueType());
ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false);
if (StOutBound && !StInBound) {
- ExplodedNode *N = C.generateSink(StOutBound);
+ ExplodedNode *N = C.generateErrorNode(StOutBound);
if (!N)
return;
-
+
if (!BT)
BT.reset(new BuiltinBug(
this, "Out-of-bound array access",
@@ -82,7 +82,7 @@ void ArrayBoundChecker::checkLocation(SVal l, bool isLoad, const Stmt* LoadS,
C.emitReport(std::move(report));
return;
}
-
+
// Array bound check succeeded. From this point forward the array bound
// should always succeed.
C.addTransition(StInBound);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
index d8dc2aa..f4de733 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -26,15 +26,15 @@ using namespace clang;
using namespace ento;
namespace {
-class ArrayBoundCheckerV2 :
+class ArrayBoundCheckerV2 :
public Checker<check::Location> {
mutable std::unique_ptr<BuiltinBug> BT;
enum OOB_Kind { OOB_Precedes, OOB_Excedes, OOB_Tainted };
-
+
void reportOOB(CheckerContext &C, ProgramStateRef errorState,
OOB_Kind kind) const;
-
+
public:
void checkLocation(SVal l, bool isLoad, const Stmt*S,
CheckerContext &C) const;
@@ -55,7 +55,7 @@ public:
NonLoc getByteOffset() const { return byteOffset.castAs<NonLoc>(); }
const SubRegion *getRegion() const { return baseRegion; }
-
+
static RegionRawOffsetV2 computeOffset(ProgramStateRef state,
SValBuilder &svalBuilder,
SVal location);
@@ -65,12 +65,12 @@ public:
};
}
-static SVal computeExtentBegin(SValBuilder &svalBuilder,
+static SVal computeExtentBegin(SValBuilder &svalBuilder,
const MemRegion *region) {
while (true)
switch (region->getKind()) {
default:
- return svalBuilder.makeZeroArrayIndex();
+ return svalBuilder.makeZeroArrayIndex();
case MemRegion::SymbolicRegionKind:
// FIXME: improve this later by tracking symbolic lower bounds
// for symbolic regions.
@@ -94,22 +94,22 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
// memory access is within the extent of the base region. Since we
// have some flexibility in defining the base region, we can achieve
// various levels of conservatism in our buffer overflow checking.
- ProgramStateRef state = checkerContext.getState();
+ ProgramStateRef state = checkerContext.getState();
ProgramStateRef originalState = state;
SValBuilder &svalBuilder = checkerContext.getSValBuilder();
- const RegionRawOffsetV2 &rawOffset =
+ const RegionRawOffsetV2 &rawOffset =
RegionRawOffsetV2::computeOffset(state, svalBuilder, location);
if (!rawOffset.getRegion())
return;
- // CHECK LOWER BOUND: Is byteOffset < extent begin?
+ // CHECK LOWER BOUND: Is byteOffset < extent begin?
// If so, we are doing a load/store
// before the first valid offset in the memory region.
SVal extentBegin = computeExtentBegin(svalBuilder, rawOffset.getRegion());
-
+
if (Optional<NonLoc> NV = extentBegin.getAs<NonLoc>()) {
SVal lowerBound =
svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(), *NV,
@@ -118,7 +118,7 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
Optional<NonLoc> lowerBoundToCheck = lowerBound.getAs<NonLoc>();
if (!lowerBoundToCheck)
return;
-
+
ProgramStateRef state_precedesLowerBound, state_withinLowerBound;
std::tie(state_precedesLowerBound, state_withinLowerBound) =
state->assume(*lowerBoundToCheck);
@@ -128,12 +128,12 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
reportOOB(checkerContext, state_precedesLowerBound, OOB_Precedes);
return;
}
-
+
// Otherwise, assume the constraint of the lower bound.
assert(state_withinLowerBound);
state = state_withinLowerBound;
}
-
+
do {
// CHECK UPPER BOUND: Is byteOffset >= extent(baseRegion)? If so,
// we are doing a load/store after the last valid offset.
@@ -146,11 +146,11 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
= svalBuilder.evalBinOpNN(state, BO_GE, rawOffset.getByteOffset(),
extentVal.castAs<NonLoc>(),
svalBuilder.getConditionType());
-
+
Optional<NonLoc> upperboundToCheck = upperbound.getAs<NonLoc>();
if (!upperboundToCheck)
break;
-
+
ProgramStateRef state_exceedsUpperBound, state_withinUpperBound;
std::tie(state_exceedsUpperBound, state_withinUpperBound) =
state->assume(*upperboundToCheck);
@@ -161,19 +161,19 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
reportOOB(checkerContext, state_exceedsUpperBound, OOB_Tainted);
return;
}
-
+
// If we are constrained enough to definitely exceed the upper bound, report.
if (state_exceedsUpperBound) {
assert(!state_withinUpperBound);
reportOOB(checkerContext, state_exceedsUpperBound, OOB_Excedes);
return;
}
-
+
assert(state_withinUpperBound);
state = state_withinUpperBound;
}
while (false);
-
+
if (state != originalState)
checkerContext.addTransition(state);
}
@@ -181,8 +181,8 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext,
ProgramStateRef errorState,
OOB_Kind kind) const {
-
- ExplodedNode *errorNode = checkerContext.generateSink(errorState);
+
+ ExplodedNode *errorNode = checkerContext.generateErrorNode(errorState);
if (!errorNode)
return;
@@ -259,7 +259,7 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(ProgramStateRef state,
{
const MemRegion *region = location.getAsRegion();
SVal offset = UndefinedVal();
-
+
while (region) {
switch (region->getKind()) {
default: {
@@ -280,7 +280,7 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(ProgramStateRef state,
ASTContext &astContext = svalBuilder.getContext();
if (elemType->isIncompleteType())
return RegionRawOffsetV2();
-
+
// Update the offset.
offset = addValue(state,
getValue(offset, svalBuilder),
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index f763284..26d42ba 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -140,10 +140,10 @@ void NilArgChecker::warnIfNilExpr(const Expr *E,
ProgramStateRef State = C.getState();
if (State->isNull(C.getSVal(E)).isConstrainedTrue()) {
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
generateBugReport(N, Msg, E->getSourceRange(), E, C);
}
-
+
}
}
@@ -156,8 +156,8 @@ void NilArgChecker::warnIfNilArg(CheckerContext &C,
ProgramStateRef State = C.getState();
if (!State->isNull(msg.getArgSVal(Arg)).isConstrainedTrue())
return;
-
- if (ExplodedNode *N = C.generateSink()) {
+
+ if (ExplodedNode *N = C.generateErrorNode()) {
SmallString<128> sbuf;
llvm::raw_svector_ostream os(sbuf);
@@ -193,7 +193,7 @@ void NilArgChecker::warnIfNilArg(CheckerContext &C,
os << "' cannot be nil";
}
}
-
+
generateBugReport(N, os.str(), msg.getArgSourceRange(Arg),
msg.getArgExpr(Arg), C);
}
@@ -224,7 +224,7 @@ void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
static const unsigned InvalidArgIndex = UINT_MAX;
unsigned Arg = InvalidArgIndex;
bool CanBeSubscript = false;
-
+
if (Class == FC_NSString) {
Selector S = msg.getSelector();
@@ -307,8 +307,7 @@ void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
warnIfNilArg(C, msg, /* Arg */1, Class);
} else if (S == SetObjectForKeyedSubscriptSel) {
CanBeSubscript = true;
- Arg = 0;
- warnIfNilArg(C, msg, /* Arg */1, Class, CanBeSubscript);
+ Arg = 1;
} else if (S == RemoveObjectForKeySel) {
Arg = 0;
}
@@ -433,7 +432,7 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
const FunctionDecl *FD = C.getCalleeDecl(CE);
if (!FD)
return;
-
+
ASTContext &Ctx = C.getASTContext();
if (!II)
II = &Ctx.Idents.get("CFNumberCreate");
@@ -489,23 +488,24 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
if (SourceSize == TargetSize)
return;
- // Generate an error. Only generate a sink if 'SourceSize < TargetSize';
- // otherwise generate a regular node.
+ // Generate an error. Only generate a sink error node
+ // if 'SourceSize < TargetSize'; otherwise generate a non-fatal error node.
//
// FIXME: We can actually create an abstract "CFNumber" object that has
// the bits initialized to the provided values.
//
- if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink()
- : C.addTransition()) {
+ ExplodedNode *N = SourceSize < TargetSize ? C.generateErrorNode()
+ : C.generateNonFatalErrorNode();
+ if (N) {
SmallString<128> sbuf;
llvm::raw_svector_ostream os(sbuf);
-
+
os << (SourceSize == 8 ? "An " : "A ")
<< SourceSize << " bit integer is used to initialize a CFNumber "
"object that represents "
<< (TargetSize == 8 ? "an " : "a ")
<< TargetSize << " bit integer. ";
-
+
if (SourceSize < TargetSize)
os << (TargetSize - SourceSize)
<< " bits of the CFNumber value will be garbage." ;
@@ -549,7 +549,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
const FunctionDecl *FD = C.getCalleeDecl(CE);
if (!FD)
return;
-
+
if (!BT) {
ASTContext &Ctx = C.getASTContext();
Retain = &Ctx.Idents.get("CFRetain");
@@ -589,7 +589,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
std::tie(stateTrue, stateFalse) = state->assume(ArgIsNull);
if (stateTrue && !stateFalse) {
- ExplodedNode *N = C.generateSink(stateTrue);
+ ExplodedNode *N = C.generateErrorNode(stateTrue);
if (!N)
return;
@@ -635,7 +635,7 @@ public:
void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const {
-
+
if (!BT) {
BT.reset(new APIMisuse(
this, "message incorrectly sent to class instead of class instance"));
@@ -646,7 +646,7 @@ void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
autoreleaseS = GetNullarySelector("autorelease", Ctx);
drainS = GetNullarySelector("drain", Ctx);
}
-
+
if (msg.isInstanceMessage())
return;
const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
@@ -655,8 +655,8 @@ void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
Selector S = msg.getSelector();
if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
return;
-
- if (ExplodedNode *N = C.addTransition()) {
+
+ if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
SmallString<200> buf;
llvm::raw_svector_ostream os(buf);
@@ -665,7 +665,7 @@ void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
os << "' message should be sent to instances "
"of class '" << Class->getName()
<< "' and not the class directly";
-
+
auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
report->addRange(msg.getSourceRange());
C.emitReport(std::move(report));
@@ -699,12 +699,12 @@ public:
bool
VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const {
const ObjCMethodDecl *MD = msg.getDecl();
-
+
if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
return false;
-
+
Selector S = msg.getSelector();
-
+
if (msg.isInstanceMessage()) {
// FIXME: Ideally we'd look at the receiver interface here, but that's not
// useful for init, because alloc returns 'id'. In theory, this could lead
@@ -751,7 +751,7 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
ASTContext &Ctx = C.getASTContext();
arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx);
- dictionaryWithObjectsAndKeysS =
+ dictionaryWithObjectsAndKeysS =
GetUnarySelector("dictionaryWithObjectsAndKeys", Ctx);
setWithObjectsS = GetUnarySelector("setWithObjects", Ctx);
orderedSetWithObjectsS = GetUnarySelector("orderedSetWithObjects", Ctx);
@@ -789,18 +789,18 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
// Ignore pointer constants.
if (msg.getArgSVal(I).getAs<loc::ConcreteInt>())
continue;
-
+
// Ignore pointer types annotated with 'NSObject' attribute.
if (C.getASTContext().isObjCNSObjectType(ArgTy))
continue;
-
+
// Ignore CF references, which can be toll-free bridged.
if (coreFoundation::isCFObjectRef(ArgTy))
continue;
// Generate only one error node to use for all bug reports.
if (!errorNode.hasValue())
- errorNode = C.addTransition();
+ errorNode = C.generateNonFatalErrorNode();
if (!errorNode.getValue())
continue;
@@ -861,7 +861,7 @@ static bool isKnownNonNilCollectionType(QualType T) {
const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
if (!PT)
return false;
-
+
const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
if (!ID)
return false;
@@ -992,9 +992,7 @@ static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N,
ProgramPoint P = N->getLocation();
if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
- if (BE->getSrc()->getLoopTarget() == FCS)
- return true;
- return false;
+ return BE->getSrc()->getLoopTarget() == FCS;
}
// Keep looking for a block edge.
@@ -1023,9 +1021,9 @@ void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
State = checkElementNonNil(C, State, FCS);
State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/true);
}
-
+
if (!State)
- C.generateSink();
+ C.generateSink(C.getState(), C.getPredecessor());
else if (State != C.getState())
C.addTransition(State);
}
@@ -1038,11 +1036,8 @@ bool ObjCLoopChecker::isCollectionCountMethod(const ObjCMethodCall &M,
CountSelectorII = &C.getASTContext().Idents.get("count");
// If the method returns collection count, record the value.
- if (S.isUnarySelector() &&
- (S.getIdentifierInfoForSlot(0) == CountSelectorII))
- return true;
-
- return false;
+ return S.isUnarySelector() &&
+ (S.getIdentifierInfoForSlot(0) == CountSelectorII);
}
void ObjCLoopChecker::checkPostObjCMessage(const ObjCMethodCall &M,
@@ -1069,7 +1064,7 @@ void ObjCLoopChecker::checkPostObjCMessage(const ObjCMethodCall &M,
// a call to "count" and add it to the map.
if (!isCollectionCountMethod(M, C))
return;
-
+
const Expr *MsgExpr = M.getOriginExpr();
SymbolRef CountS = C.getSVal(MsgExpr).getAsSymbol();
if (CountS) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
index e945c38..f26f731 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
@@ -32,7 +32,7 @@ namespace {
void BoolAssignmentChecker::emitReport(ProgramStateRef state,
CheckerContext &C) const {
- if (ExplodedNode *N = C.addTransition(state)) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
if (!BT)
BT.reset(new BuiltinBug(this, "Assignment of a non-Boolean value"));
C.emitReport(llvm::make_unique<BugReport>(*BT, BT->getDescription(), N));
@@ -42,45 +42,45 @@ void BoolAssignmentChecker::emitReport(ProgramStateRef state,
static bool isBooleanType(QualType Ty) {
if (Ty->isBooleanType()) // C++ or C99
return true;
-
+
if (const TypedefType *TT = Ty->getAs<TypedefType>())
return TT->getDecl()->getName() == "BOOL" || // Objective-C
TT->getDecl()->getName() == "_Bool" || // stdbool.h < C99
TT->getDecl()->getName() == "Boolean"; // MacTypes.h
-
+
return false;
}
void BoolAssignmentChecker::checkBind(SVal loc, SVal val, const Stmt *S,
CheckerContext &C) const {
-
+
// We are only interested in stores into Booleans.
const TypedValueRegion *TR =
dyn_cast_or_null<TypedValueRegion>(loc.getAsRegion());
-
+
if (!TR)
return;
-
+
QualType valTy = TR->getValueType();
-
+
if (!isBooleanType(valTy))
return;
-
+
// Get the value of the right-hand side. We only care about values
// that are defined (UnknownVals and UndefinedVals are handled by other
// checkers).
Optional<DefinedSVal> DV = val.getAs<DefinedSVal>();
if (!DV)
return;
-
+
// Check if the assigned value meets our criteria for correctness. It must
// be a value that is either 0 or 1. One way to check this is to see if
// the value is possibly < 0 (for a negative value) or greater than 1.
- ProgramStateRef state = C.getState();
+ ProgramStateRef state = C.getState();
SValBuilder &svalBuilder = C.getSValBuilder();
ConstraintManager &CM = C.getConstraintManager();
-
- // First, ensure that the value is >= 0.
+
+ // First, ensure that the value is >= 0.
DefinedSVal zeroVal = svalBuilder.makeIntVal(0, valTy);
SVal greaterThanOrEqualToZeroVal =
svalBuilder.evalBinOp(state, BO_GE, *DV, zeroVal,
@@ -91,13 +91,13 @@ void BoolAssignmentChecker::checkBind(SVal loc, SVal val, const Stmt *S,
if (!greaterThanEqualToZero) {
// The SValBuilder cannot construct a valid SVal for this condition.
- // This means we cannot properly reason about it.
+ // This means we cannot properly reason about it.
return;
}
-
+
ProgramStateRef stateLT, stateGE;
std::tie(stateGE, stateLT) = CM.assumeDual(state, *greaterThanEqualToZero);
-
+
// Is it possible for the value to be less than zero?
if (stateLT) {
// It is possible for the value to be less than zero. We only
@@ -106,15 +106,15 @@ void BoolAssignmentChecker::checkBind(SVal loc, SVal val, const Stmt *S,
// value is underconstrained and there is nothing left to be done.
if (!stateGE)
emitReport(stateLT, C);
-
+
// In either case, we are done.
return;
}
-
+
// If we reach here, it must be the case that the value is constrained
// to only be >= 0.
assert(stateGE == state);
-
+
// At this point we know that the value is >= 0.
// Now check to ensure that the value is <= 1.
DefinedSVal OneVal = svalBuilder.makeIntVal(1, valTy);
@@ -127,13 +127,13 @@ void BoolAssignmentChecker::checkBind(SVal loc, SVal val, const Stmt *S,
if (!lessThanEqToOne) {
// The SValBuilder cannot construct a valid SVal for this condition.
- // This means we cannot properly reason about it.
+ // This means we cannot properly reason about it.
return;
}
-
+
ProgramStateRef stateGT, stateLE;
std::tie(stateLE, stateGT) = CM.assumeDual(state, *lessThanEqToOne);
-
+
// Is it possible for the value to be greater than one?
if (stateGT) {
// It is possible for the value to be greater than one. We only
@@ -142,11 +142,11 @@ void BoolAssignmentChecker::checkBind(SVal loc, SVal val, const Stmt *S,
// value is underconstrained and there is nothing left to be done.
if (!stateLE)
emitReport(stateGT, C);
-
+
// In either case, we are done.
return;
}
-
+
// If we reach here, it must be the case that the value is constrained
// to only be <= 1.
assert(stateLE == state);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
index 104a81e..dab2f61 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -41,11 +41,12 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
default:
return false;
+ case Builtin::BI__builtin_unpredictable:
case Builtin::BI__builtin_expect:
case Builtin::BI__builtin_assume_aligned:
case Builtin::BI__builtin_addressof: {
- // For __builtin_expect and __builtin_assume_aligned, just return the value
- // of the subexpression.
+ // For __builtin_unpredictable, __builtin_expect, and
+ // __builtin_assume_aligned, just return the value of the subexpression.
// __builtin_addressof is going from a reference to a pointer, but those
// are represented the same way in the analyzer.
assert (CE->arg_begin() != CE->arg_end());
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 54b1241..1753744 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -65,7 +65,7 @@ public:
void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
bool wantsRegionChangeUpdate(ProgramStateRef state) const;
- ProgramStateRef
+ ProgramStateRef
checkRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *,
ArrayRef<const MemRegion *> ExplicitRegions,
@@ -92,7 +92,7 @@ public:
void evalstrLength(CheckerContext &C, const CallExpr *CE) const;
void evalstrnLength(CheckerContext &C, const CallExpr *CE) const;
void evalstrLengthCommon(CheckerContext &C,
- const CallExpr *CE,
+ const CallExpr *CE,
bool IsStrnlen = false) const;
void evalStrcpy(CheckerContext &C, const CallExpr *CE) const;
@@ -137,15 +137,16 @@ public:
SVal Buf,
bool hypothetical = false) const;
- const StringLiteral *getCStringLiteral(CheckerContext &C,
+ const StringLiteral *getCStringLiteral(CheckerContext &C,
ProgramStateRef &state,
- const Expr *expr,
+ const Expr *expr,
SVal val) const;
static ProgramStateRef InvalidateBuffer(CheckerContext &C,
ProgramStateRef state,
const Expr *Ex, SVal V,
- bool IsSourceBuffer);
+ bool IsSourceBuffer,
+ const Expr *Size);
static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
const MemRegion *MR);
@@ -193,6 +194,14 @@ public:
ProgramStateRef state,
NonLoc left,
NonLoc right) const;
+
+ // Return true if the destination buffer of the copy function may be in bound.
+ // Expects SVal of Size to be positive and unsigned.
+ // Expects SVal of FirstBuf to be a FieldRegion.
+ static bool IsFirstBufInBound(CheckerContext &C,
+ ProgramStateRef state,
+ const Expr *FirstBuf,
+ const Expr *Size);
};
} //end anonymous namespace
@@ -229,7 +238,7 @@ ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C,
if (!Filter.CheckCStringNullArg)
return nullptr;
- ExplodedNode *N = C.generateSink(stateNull);
+ ExplodedNode *N = C.generateErrorNode(stateNull);
if (!N)
return nullptr;
@@ -282,7 +291,7 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
// Get the size of the array.
const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
SValBuilder &svalBuilder = C.getSValBuilder();
- SVal Extent =
+ SVal Extent =
svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
DefinedOrUnknownSVal Size = Extent.castAs<DefinedOrUnknownSVal>();
@@ -292,7 +301,7 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
ProgramStateRef StInBound = state->assumeInBound(Idx, Size, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, Size, false);
if (StOutBound && !StInBound) {
- ExplodedNode *N = C.generateSink(StOutBound);
+ ExplodedNode *N = C.generateErrorNode(StOutBound);
if (!N)
return nullptr;
@@ -327,7 +336,7 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
C.emitReport(std::move(report));
return nullptr;
}
-
+
// Array bound check succeeded. From this point forward the array bound
// should always succeed.
return StInBound;
@@ -442,7 +451,7 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
return state;
// Are the two values the same?
- SValBuilder &svalBuilder = C.getSValBuilder();
+ SValBuilder &svalBuilder = C.getSValBuilder();
std::tie(stateTrue, stateFalse) =
state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc));
@@ -489,7 +498,7 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
// Bail out if the cast fails.
ASTContext &Ctx = svalBuilder.getContext();
QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
- SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy,
+ SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy,
First->getType());
Optional<Loc> FirstStartLoc = FirstStart.getAs<Loc>();
if (!FirstStartLoc)
@@ -525,7 +534,7 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,
const Stmt *First, const Stmt *Second) const {
- ExplodedNode *N = C.generateSink(state);
+ ExplodedNode *N = C.generateErrorNode(state);
if (!N)
return;
@@ -568,7 +577,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
} else {
// Try switching the operands. (The order of these two assignments is
// important!)
- maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, left,
+ maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, left,
sizeTy);
left = right;
}
@@ -585,7 +594,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
if (stateOverflow && !stateOkay) {
// We have an overflow. Emit a bug report.
- ExplodedNode *N = C.generateSink(stateOverflow);
+ ExplodedNode *N = C.generateErrorNode(stateOverflow);
if (!N)
return nullptr;
@@ -706,7 +715,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
if (!Filter.CheckCStringNotNullTerm)
return UndefinedVal();
- if (ExplodedNode *N = C.addTransition(state)) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
if (!BT_NotCString)
BT_NotCString.reset(new BuiltinBug(
Filter.CheckNameCStringNotNullTerm, categories::UnixAPI,
@@ -723,7 +732,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
report->addRange(Ex->getSourceRange());
- C.emitReport(std::move(report));
+ C.emitReport(std::move(report));
}
return UndefinedVal();
@@ -766,7 +775,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
if (!Filter.CheckCStringNotNullTerm)
return UndefinedVal();
- if (ExplodedNode *N = C.addTransition(state)) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
if (!BT_NotCString)
BT_NotCString.reset(new BuiltinBug(
Filter.CheckNameCStringNotNullTerm, categories::UnixAPI,
@@ -787,7 +796,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
auto report = llvm::make_unique<BugReport>(*BT_NotCString, os.str(), N);
report->addRange(Ex->getSourceRange());
- C.emitReport(std::move(report));
+ C.emitReport(std::move(report));
}
return UndefinedVal();
@@ -814,10 +823,74 @@ const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,
return strRegion->getStringLiteral();
}
+bool CStringChecker::IsFirstBufInBound(CheckerContext &C,
+ ProgramStateRef state,
+ const Expr *FirstBuf,
+ const Expr *Size) {
+ // If we do not know that the buffer is long enough we return 'true'.
+ // Otherwise the parent region of this field region would also get
+ // invalidated, which would lead to warnings based on an unknown state.
+
+ // Originally copied from CheckBufferAccess and CheckLocation.
+ SValBuilder &svalBuilder = C.getSValBuilder();
+ ASTContext &Ctx = svalBuilder.getContext();
+ const LocationContext *LCtx = C.getLocationContext();
+
+ QualType sizeTy = Size->getType();
+ QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
+ SVal BufVal = state->getSVal(FirstBuf, LCtx);
+
+ SVal LengthVal = state->getSVal(Size, LCtx);
+ Optional<NonLoc> Length = LengthVal.getAs<NonLoc>();
+ if (!Length)
+ return true; // cf top comment.
+
+ // Compute the offset of the last element to be accessed: size-1.
+ NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
+ NonLoc LastOffset =
+ svalBuilder.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy)
+ .castAs<NonLoc>();
+
+ // Check that the first buffer is sufficiently long.
+ SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType());
+ Optional<Loc> BufLoc = BufStart.getAs<Loc>();
+ if (!BufLoc)
+ return true; // cf top comment.
+
+ SVal BufEnd =
+ svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, LastOffset, PtrTy);
+
+ // Check for out of bound array element access.
+ const MemRegion *R = BufEnd.getAsRegion();
+ if (!R)
+ return true; // cf top comment.
+
+ const ElementRegion *ER = dyn_cast<ElementRegion>(R);
+ if (!ER)
+ return true; // cf top comment.
+
+ assert(ER->getValueType() == C.getASTContext().CharTy &&
+ "IsFirstBufInBound should only be called with char* ElementRegions");
+
+ // Get the size of the array.
+ const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
+ SVal Extent =
+ svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
+ DefinedOrUnknownSVal ExtentSize = Extent.castAs<DefinedOrUnknownSVal>();
+
+ // Get the index of the accessed element.
+ DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
+
+ ProgramStateRef StInBound = state->assumeInBound(Idx, ExtentSize, true);
+
+ return static_cast<bool>(StInBound);
+}
+
ProgramStateRef CStringChecker::InvalidateBuffer(CheckerContext &C,
ProgramStateRef state,
const Expr *E, SVal V,
- bool IsSourceBuffer) {
+ bool IsSourceBuffer,
+ const Expr *Size) {
Optional<Loc> L = V.getAs<Loc>();
if (!L)
return state;
@@ -843,13 +916,23 @@ ProgramStateRef CStringChecker::InvalidateBuffer(CheckerContext &C,
// Invalidate and escape only indirect regions accessible through the source
// buffer.
if (IsSourceBuffer) {
- ITraits.setTrait(R,
+ ITraits.setTrait(R,
RegionAndSymbolInvalidationTraits::TK_PreserveContents);
ITraits.setTrait(R, RegionAndSymbolInvalidationTraits::TK_SuppressEscape);
CausesPointerEscape = true;
+ } else {
+ const MemRegion::Kind& K = R->getKind();
+ if (K == MemRegion::FieldRegionKind)
+ if (Size && IsFirstBufInBound(C, state, E, Size)) {
+ // If destination buffer is a field region and access is in bound,
+ // do not invalidate its super region.
+ ITraits.setTrait(
+ R,
+ RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
+ }
}
- return state->invalidateRegions(R, E, C.blockCount(), LCtx,
+ return state->invalidateRegions(R, E, C.blockCount(), LCtx,
CausesPointerEscape, nullptr, nullptr,
&ITraits);
}
@@ -865,15 +948,15 @@ bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR);
switch (MR->getKind()) {
- case MemRegion::FunctionTextRegionKind: {
- const NamedDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
+ case MemRegion::FunctionCodeRegionKind: {
+ const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
if (FD)
os << "the address of the function '" << *FD << '\'';
else
os << "the address of a function";
return true;
}
- case MemRegion::BlockTextRegionKind:
+ case MemRegion::BlockCodeRegionKind:
os << "block text";
return true;
case MemRegion::BlockDataRegionKind:
@@ -901,7 +984,7 @@ bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
// evaluation of individual function calls.
//===----------------------------------------------------------------------===//
-void CStringChecker::evalCopyCommon(CheckerContext &C,
+void CStringChecker::evalCopyCommon(CheckerContext &C,
const CallExpr *CE,
ProgramStateRef state,
const Expr *Size, const Expr *Dest,
@@ -941,7 +1024,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
// Get the value of the Src.
SVal srcVal = state->getSVal(Source, LCtx);
-
+
// Ensure the source is not null. If it is NULL there will be a
// NULL pointer dereference.
state = checkNonNull(C, state, Source, srcVal);
@@ -959,11 +1042,11 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
if (!state)
return;
- // If this is mempcpy, get the byte after the last byte copied and
+ // If this is mempcpy, get the byte after the last byte copied and
// bind the expr.
if (IsMempcpy) {
loc::MemRegionVal destRegVal = destVal.castAs<loc::MemRegionVal>();
-
+
// Get the length to copy.
if (Optional<NonLoc> lenValNonLoc = sizeVal.getAs<NonLoc>()) {
// Get the byte after the last byte copied.
@@ -972,11 +1055,11 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
loc::MemRegionVal DestRegCharVal = SvalBuilder.evalCast(destRegVal,
CharPtrTy, Dest->getType()).castAs<loc::MemRegionVal>();
- SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add,
+ SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add,
DestRegCharVal,
- *lenValNonLoc,
+ *lenValNonLoc,
Dest->getType());
-
+
// The byte after the last byte copied is the return value.
state = state->BindExpr(CE, LCtx, lastElement);
} else {
@@ -999,13 +1082,13 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
// can use LazyCompoundVals to copy the source values into the destination.
// This would probably remove any existing bindings past the end of the
// copied region, but that's still an improvement over blank invalidation.
- state = InvalidateBuffer(C, state, Dest, C.getSVal(Dest),
- /*IsSourceBuffer*/false);
+ state = InvalidateBuffer(C, state, Dest, C.getSVal(Dest),
+ /*IsSourceBuffer*/false, Size);
// Invalidate the source (const-invalidation without const-pointer-escaping
// the address of the top-level region).
- state = InvalidateBuffer(C, state, Source, C.getSVal(Source),
- /*IsSourceBuffer*/true);
+ state = InvalidateBuffer(C, state, Source, C.getSVal(Source),
+ /*IsSourceBuffer*/true, nullptr);
C.addTransition(state);
}
@@ -1032,7 +1115,7 @@ void CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const {
// The return value is a pointer to the byte following the last written byte.
const Expr *Dest = CE->getArg(0);
ProgramStateRef state = C.getState();
-
+
evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true, true);
}
@@ -1053,7 +1136,7 @@ void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const {
return;
// void bcopy(const void *src, void *dst, size_t n);
- evalCopyCommon(C, CE, C.getState(),
+ evalCopyCommon(C, CE, C.getState(),
CE->getArg(2), CE->getArg(1), CE->getArg(0));
}
@@ -1244,7 +1327,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
state, BO_LE, resultNL, *strLengthNL, cmpTy)
.castAs<DefinedOrUnknownSVal>(), true);
}
-
+
if (maxlenValNL) {
state = state->assume(C.getSValBuilder().evalBinOpNN(
state, BO_LE, resultNL, *maxlenValNL, cmpTy)
@@ -1275,8 +1358,8 @@ void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const {
return;
// char *strcpy(char *restrict dst, const char *restrict src);
- evalStrcpyCommon(C, CE,
- /* returnEnd = */ false,
+ evalStrcpyCommon(C, CE,
+ /* returnEnd = */ false,
/* isBounded = */ false,
/* isAppending = */ false);
}
@@ -1286,8 +1369,8 @@ void CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const {
return;
// char *strncpy(char *restrict dst, const char *restrict src, size_t n);
- evalStrcpyCommon(C, CE,
- /* returnEnd = */ false,
+ evalStrcpyCommon(C, CE,
+ /* returnEnd = */ false,
/* isBounded = */ true,
/* isAppending = */ false);
}
@@ -1297,8 +1380,8 @@ void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const {
return;
// char *stpcpy(char *restrict dst, const char *restrict src);
- evalStrcpyCommon(C, CE,
- /* returnEnd = */ true,
+ evalStrcpyCommon(C, CE,
+ /* returnEnd = */ true,
/* isBounded = */ false,
/* isAppending = */ false);
}
@@ -1308,8 +1391,8 @@ void CStringChecker::evalStrcat(CheckerContext &C, const CallExpr *CE) const {
return;
//char *strcat(char *restrict s1, const char *restrict s2);
- evalStrcpyCommon(C, CE,
- /* returnEnd = */ false,
+ evalStrcpyCommon(C, CE,
+ /* returnEnd = */ false,
/* isBounded = */ false,
/* isAppending = */ true);
}
@@ -1319,8 +1402,8 @@ void CStringChecker::evalStrncat(CheckerContext &C, const CallExpr *CE) const {
return;
//char *strncat(char *restrict s1, const char *restrict s2, size_t n);
- evalStrcpyCommon(C, CE,
- /* returnEnd = */ false,
+ evalStrcpyCommon(C, CE,
+ /* returnEnd = */ false,
/* isBounded = */ true,
/* isAppending = */ true);
}
@@ -1515,7 +1598,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
Optional<NonLoc> srcStrLengthNL = amountCopied.getAs<NonLoc>();
Optional<NonLoc> dstStrLengthNL = dstStrLength.getAs<NonLoc>();
-
+
// If we know both string lengths, we might know the final string length.
if (srcStrLengthNL && dstStrLengthNL) {
// Make sure the two lengths together don't overflow a size_t.
@@ -1523,7 +1606,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
if (!state)
return;
- finalStrLength = svalBuilder.evalBinOpNN(state, BO_Add, *srcStrLengthNL,
+ finalStrLength = svalBuilder.evalBinOpNN(state, BO_Add, *srcStrLengthNL,
*dstStrLengthNL, sizeTy);
}
@@ -1586,7 +1669,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
if (Optional<NonLoc> maxLastNL = maxLastElementIndex.getAs<NonLoc>()) {
SVal maxLastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
*maxLastNL, ptrTy);
- state = CheckLocation(C, state, CE->getArg(2), maxLastElement,
+ state = CheckLocation(C, state, CE->getArg(2), maxLastElement,
boundWarning);
if (!state)
return;
@@ -1620,11 +1703,12 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
// This would probably remove any existing bindings past the end of the
// string, but that's still an improvement over blank invalidation.
state = InvalidateBuffer(C, state, Dst, *dstRegVal,
- /*IsSourceBuffer*/false);
+ /*IsSourceBuffer*/false, nullptr);
// Invalidate the source (const-invalidation without const-pointer-escaping
// the address of the top-level region).
- state = InvalidateBuffer(C, state, srcExpr, srcVal, /*IsSourceBuffer*/true);
+ state = InvalidateBuffer(C, state, srcExpr, srcVal, /*IsSourceBuffer*/true,
+ nullptr);
// Set the C string length of the destination, if we know it.
if (isBounded && !isAppending) {
@@ -1667,7 +1751,7 @@ void CStringChecker::evalStrncmp(CheckerContext &C, const CallExpr *CE) const {
evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ false);
}
-void CStringChecker::evalStrcasecmp(CheckerContext &C,
+void CStringChecker::evalStrcasecmp(CheckerContext &C,
const CallExpr *CE) const {
if (CE->getNumArgs() < 2)
return;
@@ -1676,7 +1760,7 @@ void CStringChecker::evalStrcasecmp(CheckerContext &C,
evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ true);
}
-void CStringChecker::evalStrncasecmp(CheckerContext &C,
+void CStringChecker::evalStrncasecmp(CheckerContext &C,
const CallExpr *CE) const {
if (CE->getNumArgs() < 3)
return;
@@ -1848,7 +1932,7 @@ void CStringChecker::evalStrsep(CheckerContext &C, const CallExpr *CE) const {
// Invalidate the search string, representing the change of one delimiter
// character to NUL.
State = InvalidateBuffer(C, State, SearchStrPtr, Result,
- /*IsSourceBuffer*/false);
+ /*IsSourceBuffer*/false, nullptr);
// Overwrite the search string pointer. The new value is either an address
// further along in the same string, or NULL if there are no more tokens.
@@ -1915,7 +1999,7 @@ bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
evalFunction = &CStringChecker::evalBcopy;
else if (C.isCLibraryFunction(FDecl, "bcmp"))
evalFunction = &CStringChecker::evalMemcmp;
-
+
// If the callee isn't a string function, let another checker handle it.
if (!evalFunction)
return false;
@@ -1929,10 +2013,7 @@ bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
// properties are held. However, if the user chooses to turn off some of these
// checks, we ignore the issues and leave the call evaluation to a generic
// handler.
- if (!C.isDifferent())
- return false;
-
- return true;
+ return C.isDifferent();
}
void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
@@ -1975,7 +2056,7 @@ bool CStringChecker::wantsRegionChangeUpdate(ProgramStateRef state) const {
return !Entries.isEmpty();
}
-ProgramStateRef
+ProgramStateRef
CStringChecker::checkRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *,
ArrayRef<const MemRegion *> ExplicitRegions,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 26423b7..1459083 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -40,6 +40,7 @@ class CallAndMessageChecker
: public Checker< check::PreStmt<CallExpr>,
check::PreStmt<CXXDeleteExpr>,
check::PreObjCMessage,
+ check::ObjCMessageNil,
check::PreCall > {
mutable std::unique_ptr<BugType> BT_call_null;
mutable std::unique_ptr<BugType> BT_call_undef;
@@ -60,6 +61,12 @@ public:
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const;
void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
+
+ /// Fill in the return value that results from messaging nil based on the
+ /// return type and architecture and diagnose if the return value will be
+ /// garbage.
+ void checkObjCMessageNil(const ObjCMethodCall &msg, CheckerContext &C) const;
+
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
private:
@@ -82,7 +89,7 @@ private:
BT.reset(new BuiltinBug(this, desc));
}
bool uninitRefOrPointer(CheckerContext &C, const SVal &V,
- const SourceRange &ArgRange,
+ SourceRange ArgRange,
const Expr *ArgEx, std::unique_ptr<BugType> &BT,
const ParmVarDecl *ParamDecl, const char *BD) const;
};
@@ -90,7 +97,7 @@ private:
void CallAndMessageChecker::emitBadCall(BugType *BT, CheckerContext &C,
const Expr *BadE) {
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
@@ -131,7 +138,7 @@ static StringRef describeUninitializedArgumentInCall(const CallEvent &Call,
bool CallAndMessageChecker::uninitRefOrPointer(CheckerContext &C,
const SVal &V,
- const SourceRange &ArgRange,
+ SourceRange ArgRange,
const Expr *ArgEx,
std::unique_ptr<BugType> &BT,
const ParmVarDecl *ParamDecl,
@@ -162,7 +169,7 @@ bool CallAndMessageChecker::uninitRefOrPointer(CheckerContext &C,
const ProgramStateRef State = C.getState();
const SVal PSV = State->getSVal(SValMemRegion);
if (PSV.isUndef()) {
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
LazyInit_BT(BD, BT);
auto R = llvm::make_unique<BugReport>(*BT, Message, N);
R->addRange(ArgRange);
@@ -193,7 +200,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
return true;
if (V.isUndef()) {
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
LazyInit_BT(BD, BT);
// Generate a report for this bug.
@@ -258,7 +265,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
D->getStore());
if (F.Find(D->getRegion())) {
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
LazyInit_BT(BD, BT);
SmallString<512> Str;
llvm::raw_svector_ostream os(Str);
@@ -331,7 +338,7 @@ void CallAndMessageChecker::checkPreStmt(const CXXDeleteExpr *DE,
SVal Arg = C.getSVal(DE->getArgument());
if (Arg.isUndef()) {
StringRef Desc;
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
if (!BT_cxx_delete_undef)
@@ -388,7 +395,7 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
// the function.
unsigned Params = FD->getNumParams();
if (Call.getNumArgs() < Params) {
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
@@ -436,7 +443,7 @@ void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const {
SVal recVal = msg.getReceiverSVal();
if (recVal.isUndef()) {
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
BugType *BT = nullptr;
switch (msg.getMessageKind()) {
case OCM_Message:
@@ -471,22 +478,14 @@ void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
C.emitReport(std::move(R));
}
return;
- } else {
- // Bifurcate the state into nil and non-nil ones.
- DefinedOrUnknownSVal receiverVal = recVal.castAs<DefinedOrUnknownSVal>();
-
- ProgramStateRef state = C.getState();
- ProgramStateRef notNilState, nilState;
- std::tie(notNilState, nilState) = state->assume(receiverVal);
-
- // Handle receiver must be nil.
- if (nilState && !notNilState) {
- HandleNilReceiver(C, state, msg);
- return;
- }
}
}
+void CallAndMessageChecker::checkObjCMessageNil(const ObjCMethodCall &msg,
+ CheckerContext &C) const {
+ HandleNilReceiver(C, C.getState(), msg);
+}
+
void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
const ObjCMethodCall &msg,
ExplodedNode *N) const {
@@ -523,7 +522,8 @@ void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
return (triple.getVendor() == llvm::Triple::Apple &&
- (triple.isiOS() || !triple.isMacOSXVersionLT(10,5)));
+ (triple.isiOS() || triple.isWatchOS() ||
+ !triple.isMacOSXVersionLT(10,5)));
}
void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
@@ -560,7 +560,7 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
Ctx.LongDoubleTy == CanRetTy ||
Ctx.LongLongTy == CanRetTy ||
Ctx.UnsignedLongLongTy == CanRetTy)))) {
- if (ExplodedNode *N = C.generateSink(state, nullptr, &Tag))
+ if (ExplodedNode *N = C.generateErrorNode(state, &Tag))
emitNilReceiverBug(C, Msg, N);
return;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index 0d683f9..2337400 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -82,10 +82,7 @@ static bool evenFlexibleArraySize(ASTContext &Ctx, CharUnits RegionSize,
if (Left.isNegative())
return false;
- if (Left % FlexSize == 0)
- return true;
-
- return false;
+ return Left % FlexSize == 0;
}
void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
@@ -131,7 +128,7 @@ void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
if (evenFlexibleArraySize(Ctx, regionSize, typeSize, ToPointeeTy))
return;
- if (ExplodedNode *errorNode = C.generateSink()) {
+ if (ExplodedNode *errorNode = C.generateErrorNode()) {
if (!BT)
BT.reset(new BuiltinBug(this, "Cast region with wrong size.",
"Cast a region whose size is not a multiple"
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
index ba3024d..fa78413 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
@@ -56,7 +56,7 @@ void CastToStructChecker::checkPreStmt(const CastExpr *CE,
// Now the cast-to-type is struct pointer, the original type is not void*.
if (!OrigPointeeTy->isRecordType()) {
- if (ExplodedNode *N = C.addTransition()) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
if (!BT)
BT.reset(
new BuiltinBug(this, "Cast from non-struct type to struct type",
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
index 12eb0bd..25caa00 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
@@ -51,7 +51,7 @@ static bool scan_ivar_release(Stmt *S, ObjCIvarDecl *ID,
if (E->getDecl()->getIdentifier() == SelfII)
if (ME->getMethodDecl() == PD->getSetterMethodDecl() &&
ME->getNumArgs() == 1 &&
- ME->getArg(0)->isNullPointerConstant(Ctx,
+ ME->getArg(0)->isNullPointerConstant(Ctx,
Expr::NPC_ValueDependentIsNull))
return true;
@@ -61,7 +61,7 @@ static bool scan_ivar_release(Stmt *S, ObjCIvarDecl *ID,
if (ObjCPropertyRefExpr *PRE =
dyn_cast<ObjCPropertyRefExpr>(BO->getLHS()->IgnoreParenCasts()))
if (PRE->isExplicitProperty() && PRE->getExplicitProperty() == PD)
- if (BO->getRHS()->isNullPointerConstant(Ctx,
+ if (BO->getRHS()->isNullPointerConstant(Ctx,
Expr::NPC_ValueDependentIsNull)) {
// This is only a 'release' if the property kind is not
// 'assign'.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
index e0c113c..60f1618 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
@@ -86,8 +86,7 @@ public:
// Helpers.
bool checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD);
- typedef void (WalkAST::*FnCheck)(const CallExpr *,
- const FunctionDecl *);
+ typedef void (WalkAST::*FnCheck)(const CallExpr *, const FunctionDecl *);
// Checker-specific methods.
void checkLoopConditionForFloat(const ForStmt *FS);
@@ -115,7 +114,7 @@ void WalkAST::VisitChildren(Stmt *S) {
}
void WalkAST::VisitCallExpr(CallExpr *CE) {
- // Get the callee.
+ // Get the callee.
const FunctionDecl *FD = CE->getDirectCallee();
if (!FD)
@@ -307,7 +306,7 @@ void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) {
void WalkAST::checkCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
if (!filter.check_gets)
return;
-
+
const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
if (!FPT)
return;
@@ -434,18 +433,18 @@ void WalkAST::checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD) {
.Case("mkdtemp", std::make_pair(0,-1))
.Case("mkstemps", std::make_pair(0,1))
.Default(std::make_pair(-1, -1));
-
+
assert(ArgSuffix.first >= 0 && "Unsupported function");
// Check if the number of arguments is consistent with out expectations.
unsigned numArgs = CE->getNumArgs();
if ((signed) numArgs <= ArgSuffix.first)
return;
-
+
const StringLiteral *strArg =
dyn_cast<StringLiteral>(CE->getArg((unsigned)ArgSuffix.first)
->IgnoreParenImpCasts());
-
+
// Currently we only handle string literals. It is possible to do better,
// either by looking at references to const variables, or by doing real
// flow analysis.
@@ -470,13 +469,13 @@ void WalkAST::checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD) {
suffix = (unsigned) Result.getZExtValue();
n = (n > suffix) ? n - suffix : 0;
}
-
+
for (unsigned i = 0; i < n; ++i)
if (str[i] == 'X') ++numX;
-
+
if (numX >= 6)
return;
-
+
// Issue a warning.
PathDiagnosticLocation CELoc =
PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
@@ -502,13 +501,13 @@ void WalkAST::checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD) {
//===----------------------------------------------------------------------===//
// Check: Any use of 'strcpy' is insecure.
//
-// CWE-119: Improper Restriction of Operations within
-// the Bounds of a Memory Buffer
+// CWE-119: Improper Restriction of Operations within
+// the Bounds of a Memory Buffer
//===----------------------------------------------------------------------===//
void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) {
if (!filter.check_strcpy)
return;
-
+
if (!checkCall_strCommon(CE, FD))
return;
@@ -529,8 +528,8 @@ void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) {
//===----------------------------------------------------------------------===//
// Check: Any use of 'strcat' is insecure.
//
-// CWE-119: Improper Restriction of Operations within
-// the Bounds of a Memory Buffer
+// CWE-119: Improper Restriction of Operations within
+// the Bounds of a Memory Buffer
//===----------------------------------------------------------------------===//
void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) {
if (!filter.check_strcpy)
@@ -684,7 +683,7 @@ void WalkAST::checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD) {
void WalkAST::checkUncheckedReturnValue(CallExpr *CE) {
if (!filter.check_UncheckedReturn)
return;
-
+
const FunctionDecl *FD = CE->getDirectCallee();
if (!FD)
return;
@@ -749,7 +748,7 @@ namespace {
class SecuritySyntaxChecker : public Checker<check::ASTCodeBody> {
public:
ChecksFilter filter;
-
+
void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
BugReporter &BR) const {
WalkAST walker(BR, mgr.getAnalysisDeclContext(D), filter);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
index 81a2006..e079a8c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
@@ -55,8 +55,8 @@ void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
QualType T = E->getTypeOfArgument();
if (T->isPointerType()) {
- // Many false positives have the form 'sizeof *p'. This is reasonable
- // because people know what they are doing when they intentionally
+ // Many false positives have the form 'sizeof *p'. This is reasonable
+ // because people know what they are doing when they intentionally
// dereference the pointer.
Expr *ArgEx = E->getArgumentExpr();
if (!isa<DeclRefExpr>(ArgEx->IgnoreParens()))
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
index 956dca7..37b8448 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
@@ -38,6 +38,7 @@ class CheckerDocumentation : public Checker< check::PreStmt<ReturnStmt>,
check::PostStmt<DeclStmt>,
check::PreObjCMessage,
check::PostObjCMessage,
+ check::ObjCMessageNil,
check::PreCall,
check::PostCall,
check::BranchCondition,
@@ -95,6 +96,15 @@ public:
/// check::PostObjCMessage
void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const {}
+ /// \brief Visit an Objective-C message whose receiver is nil.
+ ///
+ /// This will be called when the analyzer core processes a method call whose
+ /// receiver is definitely nil. In this case, check{Pre/Post}ObjCMessage and
+ /// check{Pre/Post}Call will not be called.
+ ///
+ /// check::ObjCMessageNil
+ void checkObjCMessageNil(const ObjCMethodCall &M, CheckerContext &C) const {}
+
/// \brief Pre-visit an abstract "call" event.
///
/// This is used for checkers that want to check arguments or attributed
@@ -222,7 +232,7 @@ public:
/// changed, this allows the analyzer core to skip the more expensive
/// #checkRegionChanges when no checkers are tracking any state.
bool wantsRegionChangeUpdate(ProgramStateRef St) const { return true; }
-
+
/// \brief Called when the contents of one or more regions change.
///
/// This can occur in many different ways: an explicit bind, a blanket
@@ -246,7 +256,7 @@ public:
/// #wantsRegionChangeUpdate returns \c true.
///
/// check::RegionChanges
- ProgramStateRef
+ ProgramStateRef
checkRegionChanges(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
@@ -259,12 +269,12 @@ public:
///
/// This notifies the checkers about pointer escape, which occurs whenever
/// the analyzer cannot track the symbol any more. For example, as a
- /// result of assigning a pointer into a global or when it's passed to a
+ /// result of assigning a pointer into a global or when it's passed to a
/// function call the analyzer cannot model.
- ///
+ ///
/// \param State The state at the point of escape.
/// \param Escaped The list of escaped symbols.
- /// \param Call The corresponding CallEvent, if the symbols escape as
+ /// \param Call The corresponding CallEvent, if the symbols escape as
/// parameters to the given call.
/// \param Kind How the symbols have escaped.
/// \returns Checkers can modify the state by returning a new state.
@@ -285,7 +295,7 @@ public:
PointerEscapeKind Kind) const {
return State;
}
-
+
/// check::Event<ImplicitNullDerefEvent>
void checkEvent(ImplicitNullDerefEvent Event) const {}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
index d1d6ac2..8133d29 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
@@ -13,6 +13,11 @@ include "clang/StaticAnalyzer/Checkers/CheckerBase.td"
// Packages.
//===----------------------------------------------------------------------===//
+// The Alpha package is for checkers that have too many false positives to be
+// turned on by default. The hierarchy under Alpha should be organized in the
+// hierarchy checkers would have had if they were truly at the top level.
+// (For example, a Cocoa-specific checker that is alpha should be in
+// alpha.osx.cocoa).
def Alpha : Package<"alpha">;
def Core : Package<"core">;
@@ -20,16 +25,33 @@ def CoreBuiltin : Package<"builtin">, InPackage<Core>;
def CoreUninitialized : Package<"uninitialized">, InPackage<Core>;
def CoreAlpha : Package<"core">, InPackage<Alpha>, Hidden;
+// The OptIn package is for checkers that are not alpha and that would normally
+// be on by default but where the driver does not have enough information to
+// determine when they are applicable. For example, localizability checkers fit
+// this criterion because the driver cannot determine whether a project is
+// localized or not -- this is best determined at the IDE or build-system level.
+//
+// The checker hierarchy under OptIn should mirror that in Alpha: checkers
+// should be organized as if they were at the top level.
+//
+// Note: OptIn is *not* intended for checkers that are too noisy to be on by
+// default. Such checkers belong in the alpha package.
+def OptIn : Package<"optin">;
+
+def Nullability : Package<"nullability">;
+
def Cplusplus : Package<"cplusplus">;
def CplusplusAlpha : Package<"cplusplus">, InPackage<Alpha>, Hidden;
def DeadCode : Package<"deadcode">;
def DeadCodeAlpha : Package<"deadcode">, InPackage<Alpha>, Hidden;
+def Performance : Package<"performance">, InPackage<OptIn>;
+
def Security : Package <"security">;
def InsecureAPI : Package<"insecureAPI">, InPackage<Security>;
def SecurityAlpha : Package<"security">, InPackage<Alpha>, Hidden;
-def Taint : Package<"taint">, InPackage<SecurityAlpha>, Hidden;
+def Taint : Package<"taint">, InPackage<SecurityAlpha>, Hidden;
def Unix : Package<"unix">;
def UnixAlpha : Package<"unix">, InPackage<Alpha>, Hidden;
@@ -38,11 +60,18 @@ def CStringAlpha : Package<"cstring">, InPackage<UnixAlpha>, Hidden;
def OSX : Package<"osx">;
def OSXAlpha : Package<"osx">, InPackage<Alpha>, Hidden;
+def OSXOptIn : Package<"osx">, InPackage<OptIn>;
+
def Cocoa : Package<"cocoa">, InPackage<OSX>;
def CocoaAlpha : Package<"cocoa">, InPackage<OSXAlpha>, Hidden;
+def CocoaOptIn : Package<"cocoa">, InPackage<OSXOptIn>;
+
def CoreFoundation : Package<"coreFoundation">, InPackage<OSX>;
def Containers : Package<"containers">, InPackage<CoreFoundation>;
+def LocalizabilityAlpha : Package<"localizability">, InPackage<CocoaAlpha>;
+def LocalizabilityOptIn : Package<"localizability">, InPackage<CocoaOptIn>;
+
def LLVM : Package<"llvm">;
def Debug : Package<"debug">;
@@ -128,8 +157,36 @@ def TestAfterDivZeroChecker : Checker<"TestAfterDivZero">,
HelpText<"Check for division by variable that is later compared against 0. Either the comparison is useless or there is division by zero.">,
DescFile<"TestAfterDivZeroChecker.cpp">;
+def DynamicTypeChecker : Checker<"DynamicTypeChecker">,
+ HelpText<"Check for cases where the dynamic and the static type of an object are unrelated.">,
+ DescFile<"DynamicTypeChecker.cpp">;
+
} // end "alpha.core"
+let ParentPackage = Nullability in {
+
+def NullPassedToNonnullChecker : Checker<"NullPassedToNonnull">,
+ HelpText<"Warns when a null pointer is passed to a pointer which has a _Nonnull type.">,
+ DescFile<"NullabilityChecker.cpp">;
+
+def NullReturnedFromNonnullChecker : Checker<"NullReturnedFromNonnull">,
+ HelpText<"Warns when a null pointer is returned from a function that has _Nonnull return type.">,
+ DescFile<"NullabilityChecker.cpp">;
+
+def NullableDereferencedChecker : Checker<"NullableDereferenced">,
+ HelpText<"Warns when a nullable pointer is dereferenced.">,
+ DescFile<"NullabilityChecker.cpp">;
+
+def NullablePassedToNonnullChecker : Checker<"NullablePassedToNonnull">,
+ HelpText<"Warns when a nullable pointer is passed to a pointer which has a _Nonnull type.">,
+ DescFile<"NullabilityChecker.cpp">;
+
+def NullableReturnedFromNonnullChecker : Checker<"NullablePassedToNonnull">,
+ HelpText<"Warns when a nullable pointer is returned from a function that has _Nonnull return type.">,
+ DescFile<"NullabilityChecker.cpp">;
+
+} // end "nullability"
+
//===----------------------------------------------------------------------===//
// Evaluate "builtin" functions.
//===----------------------------------------------------------------------===//
@@ -167,7 +224,7 @@ def UndefBranchChecker : Checker<"Branch">,
def UndefCapturedBlockVarChecker : Checker<"CapturedBlockVariable">,
HelpText<"Check for blocks that capture uninitialized values">,
DescFile<"UndefCapturedBlockVarChecker.cpp">;
-
+
def ReturnUndefChecker : Checker<"UndefReturn">,
HelpText<"Check for uninitialized values being returned to the caller">,
DescFile<"ReturnUndefChecker.cpp">;
@@ -181,11 +238,11 @@ def ReturnUndefChecker : Checker<"UndefReturn">,
let ParentPackage = Cplusplus in {
def NewDeleteChecker : Checker<"NewDelete">,
- HelpText<"Check for double-free and use-after-free problems. Traces memory managed by new/delete.">,
+ HelpText<"Check for double-free and use-after-free problems. Traces memory managed by new/delete.">,
DescFile<"MallocChecker.cpp">;
def NewDeleteLeaksChecker : Checker<"NewDeleteLeaks">,
- HelpText<"Check for memory leaks. Traces memory managed by new/delete.">,
+ HelpText<"Check for memory leaks. Traces memory managed by new/delete.">,
DescFile<"MallocChecker.cpp">;
} // end: "cplusplus"
@@ -193,7 +250,7 @@ def NewDeleteLeaksChecker : Checker<"NewDeleteLeaks">,
let ParentPackage = CplusplusAlpha in {
def VirtualCallChecker : Checker<"VirtualCall">,
- HelpText<"Check virtual function calls during construction or destruction">,
+ HelpText<"Check virtual function calls during construction or destruction">,
DescFile<"VirtualCallChecker.cpp">;
} // end: "alpha.cplusplus"
@@ -218,6 +275,18 @@ def UnreachableCodeChecker : Checker<"UnreachableCode">,
} // end "alpha.deadcode"
//===----------------------------------------------------------------------===//
+// Performance checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = Performance in {
+
+def PaddingChecker : Checker<"Padding">,
+ HelpText<"Check for excessively padded structs.">,
+ DescFile<"PaddingChecker.cpp">;
+
+} // end: "padding"
+
+//===----------------------------------------------------------------------===//
// Security checkers.
//===----------------------------------------------------------------------===//
@@ -257,7 +326,7 @@ let ParentPackage = SecurityAlpha in {
def ArrayBoundChecker : Checker<"ArrayBound">,
HelpText<"Warn about buffer overflows (older checker)">,
- DescFile<"ArrayBoundChecker.cpp">;
+ DescFile<"ArrayBoundChecker.cpp">;
def ArrayBoundCheckerV2 : Checker<"ArrayBoundV2">,
HelpText<"Warn about buffer overflows (newer checker)">,
@@ -298,7 +367,7 @@ def UnixAPIChecker : Checker<"API">,
def MallocChecker: Checker<"Malloc">,
HelpText<"Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free().">,
DescFile<"MallocChecker.cpp">;
-
+
def MallocSizeofChecker : Checker<"MallocSizeof">,
HelpText<"Check for dubious malloc arguments involving sizeof">,
DescFile<"MallocSizeofChecker.cpp">;
@@ -306,7 +375,11 @@ def MallocSizeofChecker : Checker<"MallocSizeof">,
def MismatchedDeallocatorChecker : Checker<"MismatchedDeallocator">,
HelpText<"Check for mismatched deallocators.">,
DescFile<"MallocChecker.cpp">;
-
+
+def VforkChecker : Checker<"Vfork">,
+ HelpText<"Check for proper usage of vfork">,
+ DescFile<"VforkChecker.cpp">;
+
} // end "unix"
let ParentPackage = UnixAlpha in {
@@ -337,7 +410,7 @@ def CStringNullArg : Checker<"NullArg">,
def CStringSyntaxChecker : Checker<"BadSizeArg">,
HelpText<"Check the size argument passed into C string functions for common erroneous patterns">,
- DescFile<"CStringSyntaxChecker.cpp">;
+ DescFile<"CStringSyntaxChecker.cpp">;
}
let ParentPackage = CStringAlpha in {
@@ -428,6 +501,10 @@ def RetainCountChecker : Checker<"RetainCount">,
HelpText<"Check for leaks and improper reference count management">,
DescFile<"RetainCountChecker.cpp">;
+def ObjCGenericsChecker : Checker<"ObjCGenerics">,
+ HelpText<"Check for type errors when using Objective-C generics">,
+ DescFile<"DynamicTypePropagation.cpp">;
+
} // end "osx.cocoa"
let ParentPackage = CocoaAlpha in {
@@ -477,8 +554,25 @@ def ObjCContainersASTChecker : Checker<"PointerSizedValues">,
def ObjCContainersChecker : Checker<"OutOfBounds">,
HelpText<"Checks for index out-of-bounds when using 'CFArray' API">,
DescFile<"ObjCContainersChecker.cpp">;
-
+
}
+
+let ParentPackage = LocalizabilityOptIn in {
+def NonLocalizedStringChecker : Checker<"NonLocalizedStringChecker">,
+ HelpText<"Warns about uses of non-localized NSStrings passed to UI methods expecting localized NSStrings">,
+ DescFile<"LocalizationChecker.cpp">;
+
+def EmptyLocalizationContextChecker : Checker<"EmptyLocalizationContextChecker">,
+ HelpText<"Check that NSLocalizedString macros include a comment for context">,
+ DescFile<"LocalizationChecker.cpp">;
+}
+
+let ParentPackage = LocalizabilityAlpha in {
+def PluralMisuseChecker : Checker<"PluralMisuseChecker">,
+ HelpText<"Warns against using one vs. many plural pattern in code when generating localized strings.">,
+ DescFile<"LocalizationChecker.cpp">;
+}
+
//===----------------------------------------------------------------------===//
// Checkers for LLVM development.
//===----------------------------------------------------------------------===//
@@ -546,4 +640,8 @@ def ExplodedGraphViewer : Checker<"ViewExplodedGraph">,
HelpText<"View Exploded Graphs using GraphViz">,
DescFile<"DebugCheckers.cpp">;
+def BugHashDumper : Checker<"DumpBugHash">,
+ HelpText<"Dump the bug hash for all statements.">,
+ DescFile<"DebugCheckers.cpp">;
+
} // end "debug"
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
index 804e83c..3ad1996 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -27,7 +27,7 @@ namespace {
// enum value that represent the jail state
enum Kind { NO_CHROOT, ROOT_CHANGED, JAIL_ENTERED };
-
+
bool isRootChanged(intptr_t k) { return k == ROOT_CHANGED; }
//bool isJailEntered(intptr_t k) { return k == JAIL_ENTERED; }
@@ -50,7 +50,7 @@ public:
static int x;
return &x;
}
-
+
bool evalCall(const CallExpr *CE, CheckerContext &C) const;
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
@@ -87,8 +87,8 @@ bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) const {
ProgramStateRef state = C.getState();
ProgramStateManager &Mgr = state->getStateManager();
-
- // Once encouter a chroot(), set the enum value ROOT_CHANGED directly in
+
+ // Once encouter a chroot(), set the enum value ROOT_CHANGED directly in
// the GDM.
state = Mgr.addGDM(state, ChrootChecker::getTag(), (void*) ROOT_CHANGED);
C.addTransition(state);
@@ -106,7 +106,7 @@ void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const {
// After chdir("/"), enter the jail, set the enum value JAIL_ENTERED.
const Expr *ArgExpr = CE->getArg(0);
SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext());
-
+
if (const MemRegion *R = ArgVal.getAsRegion()) {
R = R->StripCasts();
if (const StringRegion* StrRegion= dyn_cast<StringRegion>(R)) {
@@ -135,12 +135,12 @@ void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
// Ingnore chroot and chdir.
if (FD->getIdentifier() == II_chroot || FD->getIdentifier() == II_chdir)
return;
-
+
// If jail state is ROOT_CHANGED, generate BugReport.
void *const* k = C.getState()->FindGDM(ChrootChecker::getTag());
if (k)
if (isRootChanged((intptr_t) *k))
- if (ExplodedNode *N = C.addTransition()) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
if (!BT_BreakJail)
BT_BreakJail.reset(new BuiltinBug(
this, "Break out of jail", "No call of chdir(\"/\") immediately "
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index f4be5b3..f2a269a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -28,36 +28,36 @@
using namespace clang;
using namespace ento;
-namespace {
-
+namespace {
+
/// A simple visitor to record what VarDecls occur in EH-handling code.
class EHCodeVisitor : public RecursiveASTVisitor<EHCodeVisitor> {
public:
bool inEH;
llvm::DenseSet<const VarDecl *> &S;
-
+
bool TraverseObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
SaveAndRestore<bool> inFinally(inEH, true);
return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtFinallyStmt(S);
}
-
+
bool TraverseObjCAtCatchStmt(ObjCAtCatchStmt *S) {
SaveAndRestore<bool> inCatch(inEH, true);
return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtCatchStmt(S);
}
-
+
bool TraverseCXXCatchStmt(CXXCatchStmt *S) {
SaveAndRestore<bool> inCatch(inEH, true);
return TraverseStmt(S->getHandlerBlock());
}
-
+
bool VisitDeclRefExpr(DeclRefExpr *DR) {
if (inEH)
if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl()))
S.insert(D);
return true;
}
-
+
EHCodeVisitor(llvm::DenseSet<const VarDecl *> &S) :
inEH(false), S(S) {}
};
@@ -70,9 +70,9 @@ class ReachableCode {
public:
ReachableCode(const CFG &cfg)
: cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {}
-
+
void computeReachableBlocks();
-
+
bool isReachable(const CFGBlock *block) const {
return reachable[block->getBlockID()];
}
@@ -82,7 +82,7 @@ public:
void ReachableCode::computeReachableBlocks() {
if (!cfg.getNumBlockIDs())
return;
-
+
SmallVector<const CFGBlock*, 10> worklist;
worklist.push_back(&cfg.getEntry());
@@ -160,19 +160,19 @@ public:
// to analyze that yet.
return InEH->count(D);
}
-
+
void Report(const VarDecl *V, DeadStoreKind dsk,
PathDiagnosticLocation L, SourceRange R) {
if (Escaped.count(V))
return;
-
+
// Compute reachable blocks within the CFG for trivial cases
// where a bogus dead store can be reported because itself is unreachable.
if (!reachableCode.get()) {
reachableCode.reset(new ReachableCode(cfg));
reachableCode->computeReachableBlocks();
}
-
+
if (!reachableCode->isReachable(currentBlock))
return;
@@ -196,7 +196,7 @@ public:
case Enclosing:
// Don't report issues in this case, e.g.: "if (x = foo())",
- // where 'x' is unused later. We have yet to see a case where
+ // where 'x' is unused later. We have yet to see a case where
// this is a real bug.
return;
}
@@ -259,7 +259,7 @@ public:
const LiveVariables::LivenessValues &Live) override {
currentBlock = block;
-
+
// Skip statements in macros.
if (S->getLocStart().isMacroID())
return;
@@ -276,7 +276,7 @@ public:
const Expr *RHS =
LookThroughTransitiveAssignmentsAndCommaOperators(B->getRHS());
RHS = RHS->IgnoreParenCasts();
-
+
QualType T = VD->getType();
if (T->isPointerType() || T->isObjCObjectPointerType()) {
if (RHS->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNull))
@@ -318,27 +318,27 @@ public:
if (!V)
continue;
-
- if (V->hasLocalStorage()) {
+
+ if (V->hasLocalStorage()) {
// Reference types confuse the dead stores checker. Skip them
// for now.
if (V->getType()->getAs<ReferenceType>())
return;
-
+
if (const Expr *E = V->getInit()) {
while (const ExprWithCleanups *exprClean =
dyn_cast<ExprWithCleanups>(E))
E = exprClean->getSubExpr();
-
+
// Look through transitive assignments, e.g.:
// int x = y = 0;
E = LookThroughTransitiveAssignmentsAndCommaOperators(E);
-
+
// Don't warn on C++ objects (yet) until we can show that their
// constructors/destructors don't have side effects.
if (isa<CXXConstructExpr>(E))
return;
-
+
// A dead initialization is a variable that is dead after it
// is initialized. We don't flag warnings for those variables
// marked 'unused' or 'objc_precise_lifetime'.
@@ -401,6 +401,11 @@ public:
// Check for '&'. Any VarDecl whose address has been taken we treat as
// escaped.
// FIXME: What about references?
+ if (auto *LE = dyn_cast<LambdaExpr>(S)) {
+ findLambdaReferenceCaptures(LE);
+ return;
+ }
+
const UnaryOperator *U = dyn_cast<UnaryOperator>(S);
if (!U)
return;
@@ -412,6 +417,28 @@ public:
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
Escaped.insert(VD);
}
+
+ // Treat local variables captured by reference in C++ lambdas as escaped.
+ void findLambdaReferenceCaptures(const LambdaExpr *LE) {
+ const CXXRecordDecl *LambdaClass = LE->getLambdaClass();
+ llvm::DenseMap<const VarDecl *, FieldDecl *> CaptureFields;
+ FieldDecl *ThisCaptureField;
+ LambdaClass->getCaptureFields(CaptureFields, ThisCaptureField);
+
+ for (const LambdaCapture &C : LE->captures()) {
+ if (!C.capturesVariable())
+ continue;
+
+ VarDecl *VD = C.getCapturedVar();
+ const FieldDecl *FD = CaptureFields[VD];
+ if (!FD)
+ continue;
+
+ // If the capture field is a reference type, it is capture-by-reference.
+ if (FD->getType()->isReferenceType())
+ Escaped.insert(VD);
+ }
+ }
};
} // end anonymous namespace
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
index 51e7a3d..2eef168 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
@@ -16,7 +16,10 @@
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/CallGraph.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/IssueHash.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/Support/Process.h"
@@ -209,3 +212,36 @@ public:
void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
mgr.registerChecker<ExplodedGraphViewer>();
}
+
+//===----------------------------------------------------------------------===//
+// DumpBugHash
+//===----------------------------------------------------------------------===//
+
+namespace {
+class BugHashDumper : public Checker<check::PostStmt<Stmt>> {
+public:
+ mutable std::unique_ptr<BugType> BT;
+
+ void checkPostStmt(const Stmt *S, CheckerContext &C) const {
+ if (!BT)
+ BT.reset(new BugType(this, "Dump hash components", "debug"));
+
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ return;
+
+ const LangOptions &Opts = C.getLangOpts();
+ const SourceManager &SM = C.getSourceManager();
+ FullSourceLoc FL(S->getLocStart(), SM);
+ std::string HashContent =
+ GetIssueString(SM, FL, getCheckName().getName(), BT->getCategory(),
+ C.getLocationContext()->getDecl(), Opts);
+
+ C.emitReport(llvm::make_unique<BugReport>(*BT, HashContent, N));
+ }
+};
+}
+
+void ento::registerBugHashDumper(CheckerManager &mgr) {
+ mgr.registerChecker<BugHashDumper>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
index 2ba7ea4..f216f69 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -14,10 +14,12 @@
#include "ClangSACheckers.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
@@ -32,8 +34,7 @@ class DereferenceChecker
mutable std::unique_ptr<BuiltinBug> BT_null;
mutable std::unique_ptr<BuiltinBug> BT_undef;
- void reportBug(ProgramStateRef State, const Stmt *S, CheckerContext &C,
- bool IsBind = false) const;
+ void reportBug(ProgramStateRef State, const Stmt *S, CheckerContext &C) const;
public:
void checkLocation(SVal location, bool isLoad, const Stmt* S,
@@ -83,14 +84,37 @@ DereferenceChecker::AddDerefSource(raw_ostream &os,
SourceLocation L = IV->getLocation();
Ranges.push_back(SourceRange(L, L));
break;
- }
+ }
}
}
+static const Expr *getDereferenceExpr(const Stmt *S, bool IsBind=false){
+ const Expr *E = nullptr;
+
+ // Walk through lvalue casts to get the original expression
+ // that syntactically caused the load.
+ if (const Expr *expr = dyn_cast<Expr>(S))
+ E = expr->IgnoreParenLValueCasts();
+
+ if (IsBind) {
+ const VarDecl *VD;
+ const Expr *Init;
+ std::tie(VD, Init) = parseAssignment(S);
+ if (VD && Init)
+ E = Init;
+ }
+ return E;
+}
+
+static bool suppressReport(const Expr *E) {
+ // Do not report dereferences on memory in non-default address spaces.
+ return E->getType().getQualifiers().hasAddressSpace();
+}
+
void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
- CheckerContext &C, bool IsBind) const {
+ CheckerContext &C) const {
// Generate an error node.
- ExplodedNode *N = C.generateSink(State);
+ ExplodedNode *N = C.generateErrorNode(State);
if (!N)
return;
@@ -104,23 +128,6 @@ void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
SmallVector<SourceRange, 2> Ranges;
- // Walk through lvalue casts to get the original expression
- // that syntactically caused the load.
- if (const Expr *expr = dyn_cast<Expr>(S))
- S = expr->IgnoreParenLValueCasts();
-
- if (IsBind) {
- if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) {
- if (BO->isAssignmentOp())
- S = BO->getRHS();
- } else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
- assert(DS->isSingleDecl() && "We process decls one by one");
- if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
- if (const Expr *Init = VD->getAnyInitializer())
- S = Init;
- }
- }
-
switch (S->getStmtClass()) {
case Stmt::ArraySubscriptExprClass: {
os << "Array access";
@@ -130,6 +137,14 @@ void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
os << " results in a null pointer dereference";
break;
}
+ case Stmt::OMPArraySectionExprClass: {
+ os << "Array access";
+ const OMPArraySectionExpr *AE = cast<OMPArraySectionExpr>(S);
+ AddDerefSource(os, Ranges, AE->getBase()->IgnoreParenCasts(),
+ State.get(), N->getLocationContext());
+ os << " results in a null pointer dereference";
+ break;
+ }
case Stmt::UnaryOperatorClass: {
os << "Dereference of null pointer";
const UnaryOperator *U = cast<UnaryOperator>(S);
@@ -159,7 +174,6 @@ void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
break;
}
- os.flush();
auto report = llvm::make_unique<BugReport>(
*BT_null, buf.empty() ? BT_null->getDescription() : StringRef(buf), N);
@@ -176,7 +190,7 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
CheckerContext &C) const {
// Check for dereference of an undefined value.
if (l.isUndef()) {
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
if (!BT_undef)
BT_undef.reset(
new BuiltinBug(this, "Dereference of undefined pointer value"));
@@ -204,15 +218,19 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
// The explicit NULL case.
if (nullState) {
if (!notNullState) {
- reportBug(nullState, S, C);
- return;
+ const Expr *expr = getDereferenceExpr(S);
+ if (!suppressReport(expr)) {
+ reportBug(nullState, expr, C);
+ return;
+ }
}
// Otherwise, we have the case where the location could either be
// null or not-null. Record the error node as an "implicit" null
// dereference.
- if (ExplodedNode *N = C.generateSink(nullState)) {
- ImplicitNullDerefEvent event = { l, isLoad, N, &C.getBugReporter() };
+ if (ExplodedNode *N = C.generateSink(nullState, C.getPredecessor())) {
+ ImplicitNullDerefEvent event = {l, isLoad, N, &C.getBugReporter(),
+ /*IsDirectDereference=*/false};
dispatchEvent(event);
}
}
@@ -242,15 +260,19 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S,
if (StNull) {
if (!StNonNull) {
- reportBug(StNull, S, C, /*isBind=*/true);
- return;
+ const Expr *expr = getDereferenceExpr(S, /*IsBind=*/true);
+ if (!suppressReport(expr)) {
+ reportBug(StNull, expr, C);
+ return;
+ }
}
// At this point the value could be either null or non-null.
// Record this as an "implicit" null dereference.
- if (ExplodedNode *N = C.generateSink(StNull)) {
- ImplicitNullDerefEvent event = { V, /*isLoad=*/true, N,
- &C.getBugReporter() };
+ if (ExplodedNode *N = C.generateSink(StNull, C.getPredecessor())) {
+ ImplicitNullDerefEvent event = {V, /*isLoad=*/true, N,
+ &C.getBugReporter(),
+ /*IsDirectDereference=*/false};
dispatchEvent(event);
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
index a71def2..ad478cb 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
@@ -41,13 +41,12 @@ namespace {
/// Checks for the init, dealloc, and any other functions that might be allowed
/// to perform direct instance variable assignment based on their name.
static bool DefaultMethodFilter(const ObjCMethodDecl *M) {
- if (M->getMethodFamily() == OMF_init || M->getMethodFamily() == OMF_dealloc ||
- M->getMethodFamily() == OMF_copy ||
- M->getMethodFamily() == OMF_mutableCopy ||
- M->getSelector().getNameForSlot(0).find("init") != StringRef::npos ||
- M->getSelector().getNameForSlot(0).find("Init") != StringRef::npos)
- return true;
- return false;
+ return M->getMethodFamily() == OMF_init ||
+ M->getMethodFamily() == OMF_dealloc ||
+ M->getMethodFamily() == OMF_copy ||
+ M->getMethodFamily() == OMF_mutableCopy ||
+ M->getSelector().getNameForSlot(0).find("init") != StringRef::npos ||
+ M->getSelector().getNameForSlot(0).find("Init") != StringRef::npos;
}
class DirectIvarAssignment :
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
index 79f9479b..5985023 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
@@ -29,13 +29,13 @@ class DivZeroChecker : public Checker< check::PreStmt<BinaryOperator> > {
CheckerContext &C) const ;
public:
void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
-};
+};
} // end anonymous namespace
void DivZeroChecker::reportBug(const char *Msg,
ProgramStateRef StateZero,
CheckerContext &C) const {
- if (ExplodedNode *N = C.generateSink(StateZero)) {
+ if (ExplodedNode *N = C.generateErrorNode(StateZero)) {
if (!BT)
BT.reset(new BuiltinBug(this, "Division by zero"));
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
new file mode 100644
index 0000000..7e0cb8e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
@@ -0,0 +1,213 @@
+//== DynamicTypeChecker.cpp ------------------------------------ -*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker looks for cases where the dynamic type of an object is unrelated
+// to its static type. The type information utilized by this check is collected
+// by the DynamicTypePropagation checker. This check does not report any type
+// error for ObjC Generic types, in order to avoid duplicate erros from the
+// ObjC Generics checker. This checker is not supposed to modify the program
+// state, it is just the observer of the type information provided by other
+// checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class DynamicTypeChecker : public Checker<check::PostStmt<ImplicitCastExpr>> {
+ mutable std::unique_ptr<BugType> BT;
+ void initBugType() const {
+ if (!BT)
+ BT.reset(
+ new BugType(this, "Dynamic and static type mismatch", "Type Error"));
+ }
+
+ class DynamicTypeBugVisitor
+ : public BugReporterVisitorImpl<DynamicTypeBugVisitor> {
+ public:
+ DynamicTypeBugVisitor(const MemRegion *Reg) : Reg(Reg) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int X = 0;
+ ID.AddPointer(&X);
+ ID.AddPointer(Reg);
+ }
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+ private:
+ // The tracked region.
+ const MemRegion *Reg;
+ };
+
+ void reportTypeError(QualType DynamicType, QualType StaticType,
+ const MemRegion *Reg, const Stmt *ReportedNode,
+ CheckerContext &C) const;
+
+public:
+ void checkPostStmt(const ImplicitCastExpr *CE, CheckerContext &C) const;
+};
+}
+
+void DynamicTypeChecker::reportTypeError(QualType DynamicType,
+ QualType StaticType,
+ const MemRegion *Reg,
+ const Stmt *ReportedNode,
+ CheckerContext &C) const {
+ initBugType();
+ SmallString<192> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ OS << "Object has a dynamic type '";
+ QualType::print(DynamicType.getTypePtr(), Qualifiers(), OS, C.getLangOpts(),
+ llvm::Twine());
+ OS << "' which is incompatible with static type '";
+ QualType::print(StaticType.getTypePtr(), Qualifiers(), OS, C.getLangOpts(),
+ llvm::Twine());
+ OS << "'";
+ std::unique_ptr<BugReport> R(
+ new BugReport(*BT, OS.str(), C.generateNonFatalErrorNode()));
+ R->markInteresting(Reg);
+ R->addVisitor(llvm::make_unique<DynamicTypeBugVisitor>(Reg));
+ R->addRange(ReportedNode->getSourceRange());
+ C.emitReport(std::move(R));
+}
+
+PathDiagnosticPiece *DynamicTypeChecker::DynamicTypeBugVisitor::VisitNode(
+ const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
+ BugReport &BR) {
+ ProgramStateRef State = N->getState();
+ ProgramStateRef StatePrev = PrevN->getState();
+
+ DynamicTypeInfo TrackedType = getDynamicTypeInfo(State, Reg);
+ DynamicTypeInfo TrackedTypePrev = getDynamicTypeInfo(StatePrev, Reg);
+ if (!TrackedType.isValid())
+ return nullptr;
+
+ if (TrackedTypePrev.isValid() &&
+ TrackedTypePrev.getType() == TrackedType.getType())
+ return nullptr;
+
+ // Retrieve the associated statement.
+ const Stmt *S = nullptr;
+ ProgramPoint ProgLoc = N->getLocation();
+ if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
+ S = SP->getStmt();
+ }
+
+ if (!S)
+ return nullptr;
+
+ const LangOptions &LangOpts = BRC.getASTContext().getLangOpts();
+
+ SmallString<256> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ OS << "Type '";
+ QualType::print(TrackedType.getType().getTypePtr(), Qualifiers(), OS,
+ LangOpts, llvm::Twine());
+ OS << "' is inferred from ";
+
+ if (const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
+ OS << "explicit cast (from '";
+ QualType::print(ExplicitCast->getSubExpr()->getType().getTypePtr(),
+ Qualifiers(), OS, LangOpts, llvm::Twine());
+ OS << "' to '";
+ QualType::print(ExplicitCast->getType().getTypePtr(), Qualifiers(), OS,
+ LangOpts, llvm::Twine());
+ OS << "')";
+ } else if (const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
+ OS << "implicit cast (from '";
+ QualType::print(ImplicitCast->getSubExpr()->getType().getTypePtr(),
+ Qualifiers(), OS, LangOpts, llvm::Twine());
+ OS << "' to '";
+ QualType::print(ImplicitCast->getType().getTypePtr(), Qualifiers(), OS,
+ LangOpts, llvm::Twine());
+ OS << "')";
+ } else {
+ OS << "this context";
+ }
+
+ // Generate the extra diagnostic.
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+ N->getLocationContext());
+ return new PathDiagnosticEventPiece(Pos, OS.str(), true, nullptr);
+}
+
+static bool hasDefinition(const ObjCObjectPointerType *ObjPtr) {
+ const ObjCInterfaceDecl *Decl = ObjPtr->getInterfaceDecl();
+ if (!Decl)
+ return false;
+
+ return Decl->getDefinition();
+}
+
+// TODO: consider checking explicit casts?
+void DynamicTypeChecker::checkPostStmt(const ImplicitCastExpr *CE,
+ CheckerContext &C) const {
+ // TODO: C++ support.
+ if (CE->getCastKind() != CK_BitCast)
+ return;
+
+ const MemRegion *Region = C.getSVal(CE).getAsRegion();
+ if (!Region)
+ return;
+
+ ProgramStateRef State = C.getState();
+ DynamicTypeInfo DynTypeInfo = getDynamicTypeInfo(State, Region);
+
+ if (!DynTypeInfo.isValid())
+ return;
+
+ QualType DynType = DynTypeInfo.getType();
+ QualType StaticType = CE->getType();
+
+ const auto *DynObjCType = DynType->getAs<ObjCObjectPointerType>();
+ const auto *StaticObjCType = StaticType->getAs<ObjCObjectPointerType>();
+
+ if (!DynObjCType || !StaticObjCType)
+ return;
+
+ if (!hasDefinition(DynObjCType) || !hasDefinition(StaticObjCType))
+ return;
+
+ ASTContext &ASTCtxt = C.getASTContext();
+
+ // Strip kindeofness to correctly detect subtyping relationships.
+ DynObjCType = DynObjCType->stripObjCKindOfTypeAndQuals(ASTCtxt);
+ StaticObjCType = StaticObjCType->stripObjCKindOfTypeAndQuals(ASTCtxt);
+
+ // Specialized objects are handled by the generics checker.
+ if (StaticObjCType->isSpecialized())
+ return;
+
+ if (ASTCtxt.canAssignObjCInterfaces(StaticObjCType, DynObjCType))
+ return;
+
+ if (DynTypeInfo.canBeASubClass() &&
+ ASTCtxt.canAssignObjCInterfaces(DynObjCType, StaticObjCType))
+ return;
+
+ reportTypeError(DynType, StaticType, Region, CE, C);
+}
+
+void ento::registerDynamicTypeChecker(CheckerManager &mgr) {
+ mgr.registerChecker<DynamicTypeChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index 43a2812..30f6298 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -7,42 +7,139 @@
//
//===----------------------------------------------------------------------===//
//
+// This file contains two checkers. One helps the static analyzer core to track
+// types, the other does type inference on Obj-C generics and report type
+// errors.
+//
+// Dynamic Type Propagation:
// This checker defines the rules for dynamic type gathering and propagation.
//
+// Generics Checker for Objective-C:
+// This checker tries to find type errors that the compiler is not able to catch
+// due to the implicit conversions that were introduced for backward
+// compatibility.
+//
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
using namespace clang;
using namespace ento;
+// ProgramState trait - The type inflation is tracked by DynamicTypeMap. This is
+// an auxiliary map that tracks more information about generic types, because in
+// some cases the most derived type is not the most informative one about the
+// type parameters. This types that are stored for each symbol in this map must
+// be specialized.
+// TODO: In some case the type stored in this map is exactly the same that is
+// stored in DynamicTypeMap. We should no store duplicated information in those
+// cases.
+REGISTER_MAP_WITH_PROGRAMSTATE(MostSpecializedTypeArgsMap, SymbolRef,
+ const ObjCObjectPointerType *)
+
namespace {
class DynamicTypePropagation:
public Checker< check::PreCall,
check::PostCall,
- check::PostStmt<ImplicitCastExpr>,
- check::PostStmt<CXXNewExpr> > {
+ check::DeadSymbols,
+ check::PostStmt<CastExpr>,
+ check::PostStmt<CXXNewExpr>,
+ check::PreObjCMessage,
+ check::PostObjCMessage > {
const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
CheckerContext &C) const;
/// \brief Return a better dynamic type if one can be derived from the cast.
const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE,
CheckerContext &C) const;
+
+ ExplodedNode *dynamicTypePropagationOnCasts(const CastExpr *CE,
+ ProgramStateRef &State,
+ CheckerContext &C) const;
+
+ mutable std::unique_ptr<BugType> ObjCGenericsBugType;
+ void initBugType() const {
+ if (!ObjCGenericsBugType)
+ ObjCGenericsBugType.reset(
+ new BugType(this, "Generics", categories::CoreFoundationObjectiveC));
+ }
+
+ class GenericsBugVisitor : public BugReporterVisitorImpl<GenericsBugVisitor> {
+ public:
+ GenericsBugVisitor(SymbolRef S) : Sym(S) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int X = 0;
+ ID.AddPointer(&X);
+ ID.AddPointer(Sym);
+ }
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+ private:
+ // The tracked symbol.
+ SymbolRef Sym;
+ };
+
+ void reportGenericsBug(const ObjCObjectPointerType *From,
+ const ObjCObjectPointerType *To, ExplodedNode *N,
+ SymbolRef Sym, CheckerContext &C,
+ const Stmt *ReportedNode = nullptr) const;
public:
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
- void checkPostStmt(const ImplicitCastExpr *CastE, CheckerContext &C) const;
+ void checkPostStmt(const CastExpr *CastE, CheckerContext &C) const;
void checkPostStmt(const CXXNewExpr *NewE, CheckerContext &C) const;
+ void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+ void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
+ void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
+
+ /// This value is set to true, when the Generics checker is turned on.
+ DefaultBool CheckGenerics;
};
}
+void DynamicTypePropagation::checkDeadSymbols(SymbolReaper &SR,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ DynamicTypeMapImpl TypeMap = State->get<DynamicTypeMap>();
+ for (DynamicTypeMapImpl::iterator I = TypeMap.begin(), E = TypeMap.end();
+ I != E; ++I) {
+ if (!SR.isLiveRegion(I->first)) {
+ State = State->remove<DynamicTypeMap>(I->first);
+ }
+ }
+
+ if (!SR.hasDeadSymbols()) {
+ C.addTransition(State);
+ return;
+ }
+
+ MostSpecializedTypeArgsMapTy TyArgMap =
+ State->get<MostSpecializedTypeArgsMap>();
+ for (MostSpecializedTypeArgsMapTy::iterator I = TyArgMap.begin(),
+ E = TyArgMap.end();
+ I != E; ++I) {
+ if (SR.isDead(I->first)) {
+ State = State->remove<MostSpecializedTypeArgsMap>(I->first);
+ }
+ }
+
+ C.addTransition(State);
+}
+
static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD,
CheckerContext &C) {
assert(Region);
@@ -52,7 +149,7 @@ static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD,
QualType Ty = Ctx.getPointerType(Ctx.getRecordType(MD->getParent()));
ProgramStateRef State = C.getState();
- State = State->setDynamicTypeInfo(Region, Ty, /*CanBeSubclass=*/false);
+ State = setDynamicTypeInfo(State, Region, Ty, /*CanBeSubclass=*/false);
C.addTransition(State);
return;
}
@@ -113,7 +210,7 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
ProgramStateRef State = C.getState();
const ObjCMethodDecl *D = Msg->getDecl();
-
+
if (D && D->hasRelatedResultType()) {
switch (Msg->getMethodFamily()) {
default:
@@ -131,7 +228,7 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
return;
QualType DynResTy =
C.getASTContext().getObjCObjectPointerType(QualType(ObjTy, 0));
- C.addTransition(State->setDynamicTypeInfo(RetReg, DynResTy, false));
+ C.addTransition(setDynamicTypeInfo(State, RetReg, DynResTy, false));
break;
}
case OMF_init: {
@@ -140,8 +237,8 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion();
if (!RecReg)
return;
- DynamicTypeInfo RecDynType = State->getDynamicTypeInfo(RecReg);
- C.addTransition(State->setDynamicTypeInfo(RetReg, RecDynType));
+ DynamicTypeInfo RecDynType = getDynamicTypeInfo(State, RecReg);
+ C.addTransition(setDynamicTypeInfo(State, RetReg, RecDynType));
break;
}
}
@@ -173,23 +270,25 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
}
}
-void DynamicTypePropagation::checkPostStmt(const ImplicitCastExpr *CastE,
- CheckerContext &C) const {
- // We only track dynamic type info for regions.
- const MemRegion *ToR = C.getSVal(CastE).getAsRegion();
+/// TODO: Handle explicit casts.
+/// Handle C++ casts.
+///
+/// Precondition: the cast is between ObjCObjectPointers.
+ExplodedNode *DynamicTypePropagation::dynamicTypePropagationOnCasts(
+ const CastExpr *CE, ProgramStateRef &State, CheckerContext &C) const {
+ // We only track type info for regions.
+ const MemRegion *ToR = C.getSVal(CE).getAsRegion();
if (!ToR)
- return;
+ return C.getPredecessor();
+
+ if (isa<ExplicitCastExpr>(CE))
+ return C.getPredecessor();
- switch (CastE->getCastKind()) {
- default:
- break;
- case CK_BitCast:
- // Only handle ObjCObjects for now.
- if (const Type *NewTy = getBetterObjCType(CastE, C))
- C.addTransition(C.getState()->setDynamicTypeInfo(ToR, QualType(NewTy,0)));
- break;
+ if (const Type *NewTy = getBetterObjCType(CE, C)) {
+ State = setDynamicTypeInfo(State, ToR, QualType(NewTy, 0));
+ return C.addTransition(State);
}
- return;
+ return C.getPredecessor();
}
void DynamicTypePropagation::checkPostStmt(const CXXNewExpr *NewE,
@@ -201,9 +300,9 @@ void DynamicTypePropagation::checkPostStmt(const CXXNewExpr *NewE,
const MemRegion *MR = C.getSVal(NewE).getAsRegion();
if (!MR)
return;
-
- C.addTransition(C.getState()->setDynamicTypeInfo(MR, NewE->getType(),
- /*CanBeSubclass=*/false));
+
+ C.addTransition(setDynamicTypeInfo(C.getState(), MR, NewE->getType(),
+ /*CanBeSubclass=*/false));
}
const ObjCObjectType *
@@ -254,7 +353,7 @@ DynamicTypePropagation::getBetterObjCType(const Expr *CastE,
CastE->getType()->getAs<ObjCObjectPointerType>();
if (!NewTy)
return nullptr;
- QualType OldDTy = C.getState()->getDynamicTypeInfo(ToR).getType();
+ QualType OldDTy = getDynamicTypeInfo(C.getState(), ToR).getType();
if (OldDTy.isNull()) {
return NewTy;
}
@@ -276,6 +375,566 @@ DynamicTypePropagation::getBetterObjCType(const Expr *CastE,
return nullptr;
}
+static const ObjCObjectPointerType *getMostInformativeDerivedClassImpl(
+ const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
+ const ObjCObjectPointerType *MostInformativeCandidate, ASTContext &C) {
+ // Checking if from and to are the same classes modulo specialization.
+ if (From->getInterfaceDecl()->getCanonicalDecl() ==
+ To->getInterfaceDecl()->getCanonicalDecl()) {
+ if (To->isSpecialized()) {
+ assert(MostInformativeCandidate->isSpecialized());
+ return MostInformativeCandidate;
+ }
+ return From;
+ }
+ const auto *SuperOfTo =
+ To->getObjectType()->getSuperClassType()->getAs<ObjCObjectType>();
+ assert(SuperOfTo);
+ QualType SuperPtrOfToQual =
+ C.getObjCObjectPointerType(QualType(SuperOfTo, 0));
+ const auto *SuperPtrOfTo = SuperPtrOfToQual->getAs<ObjCObjectPointerType>();
+ if (To->isUnspecialized())
+ return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo, SuperPtrOfTo,
+ C);
+ else
+ return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo,
+ MostInformativeCandidate, C);
+}
+
+/// A downcast may loose specialization information. E. g.:
+/// MutableMap<T, U> : Map
+/// The downcast to MutableMap looses the information about the types of the
+/// Map (due to the type parameters are not being forwarded to Map), and in
+/// general there is no way to recover that information from the
+/// declaration. In order to have to most information, lets find the most
+/// derived type that has all the type parameters forwarded.
+///
+/// Get the a subclass of \p From (which has a lower bound \p To) that do not
+/// loose information about type parameters. \p To has to be a subclass of
+/// \p From. From has to be specialized.
+static const ObjCObjectPointerType *
+getMostInformativeDerivedClass(const ObjCObjectPointerType *From,
+ const ObjCObjectPointerType *To, ASTContext &C) {
+ return getMostInformativeDerivedClassImpl(From, To, To, C);
+}
+
+/// Inputs:
+/// \param StaticLowerBound Static lower bound for a symbol. The dynamic lower
+/// bound might be the subclass of this type.
+/// \param StaticUpperBound A static upper bound for a symbol.
+/// \p StaticLowerBound expected to be the subclass of \p StaticUpperBound.
+/// \param Current The type that was inferred for a symbol in a previous
+/// context. Might be null when this is the first time that inference happens.
+/// Precondition:
+/// \p StaticLowerBound or \p StaticUpperBound is specialized. If \p Current
+/// is not null, it is specialized.
+/// Possible cases:
+/// (1) The \p Current is null and \p StaticLowerBound <: \p StaticUpperBound
+/// (2) \p StaticLowerBound <: \p Current <: \p StaticUpperBound
+/// (3) \p Current <: \p StaticLowerBound <: \p StaticUpperBound
+/// (4) \p StaticLowerBound <: \p StaticUpperBound <: \p Current
+/// Effect:
+/// Use getMostInformativeDerivedClass with the upper and lower bound of the
+/// set {\p StaticLowerBound, \p Current, \p StaticUpperBound}. The computed
+/// lower bound must be specialized. If the result differs from \p Current or
+/// \p Current is null, store the result.
+static bool
+storeWhenMoreInformative(ProgramStateRef &State, SymbolRef Sym,
+ const ObjCObjectPointerType *const *Current,
+ const ObjCObjectPointerType *StaticLowerBound,
+ const ObjCObjectPointerType *StaticUpperBound,
+ ASTContext &C) {
+ // Precondition
+ assert(StaticUpperBound->isSpecialized() ||
+ StaticLowerBound->isSpecialized());
+ assert(!Current || (*Current)->isSpecialized());
+
+ // Case (1)
+ if (!Current) {
+ if (StaticUpperBound->isUnspecialized()) {
+ State = State->set<MostSpecializedTypeArgsMap>(Sym, StaticLowerBound);
+ return true;
+ }
+ // Upper bound is specialized.
+ const ObjCObjectPointerType *WithMostInfo =
+ getMostInformativeDerivedClass(StaticUpperBound, StaticLowerBound, C);
+ State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
+ return true;
+ }
+
+ // Case (3)
+ if (C.canAssignObjCInterfaces(StaticLowerBound, *Current)) {
+ return false;
+ }
+
+ // Case (4)
+ if (C.canAssignObjCInterfaces(*Current, StaticUpperBound)) {
+ // The type arguments might not be forwarded at any point of inheritance.
+ const ObjCObjectPointerType *WithMostInfo =
+ getMostInformativeDerivedClass(*Current, StaticUpperBound, C);
+ WithMostInfo =
+ getMostInformativeDerivedClass(WithMostInfo, StaticLowerBound, C);
+ if (WithMostInfo == *Current)
+ return false;
+ State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
+ return true;
+ }
+
+ // Case (2)
+ const ObjCObjectPointerType *WithMostInfo =
+ getMostInformativeDerivedClass(*Current, StaticLowerBound, C);
+ if (WithMostInfo != *Current) {
+ State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
+ return true;
+ }
+
+ return false;
+}
+
+/// Type inference based on static type information that is available for the
+/// cast and the tracked type information for the given symbol. When the tracked
+/// symbol and the destination type of the cast are unrelated, report an error.
+void DynamicTypePropagation::checkPostStmt(const CastExpr *CE,
+ CheckerContext &C) const {
+ if (CE->getCastKind() != CK_BitCast)
+ return;
+
+ QualType OriginType = CE->getSubExpr()->getType();
+ QualType DestType = CE->getType();
+
+ const auto *OrigObjectPtrType = OriginType->getAs<ObjCObjectPointerType>();
+ const auto *DestObjectPtrType = DestType->getAs<ObjCObjectPointerType>();
+
+ if (!OrigObjectPtrType || !DestObjectPtrType)
+ return;
+
+ ProgramStateRef State = C.getState();
+ ExplodedNode *AfterTypeProp = dynamicTypePropagationOnCasts(CE, State, C);
+
+ ASTContext &ASTCtxt = C.getASTContext();
+
+ // This checker detects the subtyping relationships using the assignment
+ // rules. In order to be able to do this the kindofness must be stripped
+ // first. The checker treats every type as kindof type anyways: when the
+ // tracked type is the subtype of the static type it tries to look up the
+ // methods in the tracked type first.
+ OrigObjectPtrType = OrigObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
+ DestObjectPtrType = DestObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
+
+ // TODO: erase tracked information when there is a cast to unrelated type
+ // and everything is unspecialized statically.
+ if (OrigObjectPtrType->isUnspecialized() &&
+ DestObjectPtrType->isUnspecialized())
+ return;
+
+ SymbolRef Sym = State->getSVal(CE, C.getLocationContext()).getAsSymbol();
+ if (!Sym)
+ return;
+
+ // Check which assignments are legal.
+ bool OrigToDest =
+ ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, OrigObjectPtrType);
+ bool DestToOrig =
+ ASTCtxt.canAssignObjCInterfaces(OrigObjectPtrType, DestObjectPtrType);
+ const ObjCObjectPointerType *const *TrackedType =
+ State->get<MostSpecializedTypeArgsMap>(Sym);
+
+ // Downcasts and upcasts handled in an uniform way regardless of being
+ // explicit. Explicit casts however can happen between mismatched types.
+ if (isa<ExplicitCastExpr>(CE) && !OrigToDest && !DestToOrig) {
+ // Mismatched types. If the DestType specialized, store it. Forget the
+ // tracked type otherwise.
+ if (DestObjectPtrType->isSpecialized()) {
+ State = State->set<MostSpecializedTypeArgsMap>(Sym, DestObjectPtrType);
+ C.addTransition(State, AfterTypeProp);
+ } else if (TrackedType) {
+ State = State->remove<MostSpecializedTypeArgsMap>(Sym);
+ C.addTransition(State, AfterTypeProp);
+ }
+ return;
+ }
+
+ // The tracked type should be the sub or super class of the static destination
+ // type. When an (implicit) upcast or a downcast happens according to static
+ // types, and there is no subtyping relationship between the tracked and the
+ // static destination types, it indicates an error.
+ if (TrackedType &&
+ !ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, *TrackedType) &&
+ !ASTCtxt.canAssignObjCInterfaces(*TrackedType, DestObjectPtrType)) {
+ static CheckerProgramPointTag IllegalConv(this, "IllegalConversion");
+ ExplodedNode *N = C.addTransition(State, AfterTypeProp, &IllegalConv);
+ reportGenericsBug(*TrackedType, DestObjectPtrType, N, Sym, C);
+ return;
+ }
+
+ // Handle downcasts and upcasts.
+
+ const ObjCObjectPointerType *LowerBound = DestObjectPtrType;
+ const ObjCObjectPointerType *UpperBound = OrigObjectPtrType;
+ if (OrigToDest && !DestToOrig)
+ std::swap(LowerBound, UpperBound);
+
+ // The id type is not a real bound. Eliminate it.
+ LowerBound = LowerBound->isObjCIdType() ? UpperBound : LowerBound;
+ UpperBound = UpperBound->isObjCIdType() ? LowerBound : UpperBound;
+
+ if (storeWhenMoreInformative(State, Sym, TrackedType, LowerBound, UpperBound,
+ ASTCtxt)) {
+ C.addTransition(State, AfterTypeProp);
+ }
+}
+
+static const Expr *stripCastsAndSugar(const Expr *E) {
+ E = E->IgnoreParenImpCasts();
+ if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
+ E = POE->getSyntacticForm()->IgnoreParenImpCasts();
+ if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
+ E = OVE->getSourceExpr()->IgnoreParenImpCasts();
+ return E;
+}
+
+static bool isObjCTypeParamDependent(QualType Type) {
+ // It is illegal to typedef parameterized types inside an interface. Therfore
+ // an Objective-C type can only be dependent on a type parameter when the type
+ // parameter structurally present in the type itself.
+ class IsObjCTypeParamDependentTypeVisitor
+ : public RecursiveASTVisitor<IsObjCTypeParamDependentTypeVisitor> {
+ public:
+ IsObjCTypeParamDependentTypeVisitor() : Result(false) {}
+ bool VisitTypedefType(const TypedefType *Type) {
+ if (isa<ObjCTypeParamDecl>(Type->getDecl())) {
+ Result = true;
+ return false;
+ }
+ return true;
+ }
+
+ bool Result;
+ };
+
+ IsObjCTypeParamDependentTypeVisitor Visitor;
+ Visitor.TraverseType(Type);
+ return Visitor.Result;
+}
+
+/// A method might not be available in the interface indicated by the static
+/// type. However it might be available in the tracked type. In order to
+/// properly substitute the type parameters we need the declaration context of
+/// the method. The more specialized the enclosing class of the method is, the
+/// more likely that the parameter substitution will be successful.
+static const ObjCMethodDecl *
+findMethodDecl(const ObjCMessageExpr *MessageExpr,
+ const ObjCObjectPointerType *TrackedType, ASTContext &ASTCtxt) {
+ const ObjCMethodDecl *Method = nullptr;
+
+ QualType ReceiverType = MessageExpr->getReceiverType();
+ const auto *ReceiverObjectPtrType =
+ ReceiverType->getAs<ObjCObjectPointerType>();
+
+ // Do this "devirtualization" on instance and class methods only. Trust the
+ // static type on super and super class calls.
+ if (MessageExpr->getReceiverKind() == ObjCMessageExpr::Instance ||
+ MessageExpr->getReceiverKind() == ObjCMessageExpr::Class) {
+ // When the receiver type is id, Class, or some super class of the tracked
+ // type, look up the method in the tracked type, not in the receiver type.
+ // This way we preserve more information.
+ if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType() ||
+ ASTCtxt.canAssignObjCInterfaces(ReceiverObjectPtrType, TrackedType)) {
+ const ObjCInterfaceDecl *InterfaceDecl = TrackedType->getInterfaceDecl();
+ // The method might not be found.
+ Selector Sel = MessageExpr->getSelector();
+ Method = InterfaceDecl->lookupInstanceMethod(Sel);
+ if (!Method)
+ Method = InterfaceDecl->lookupClassMethod(Sel);
+ }
+ }
+
+ // Fallback to statick method lookup when the one based on the tracked type
+ // failed.
+ return Method ? Method : MessageExpr->getMethodDecl();
+}
+
+/// Get the returned ObjCObjectPointerType by a method based on the tracked type
+/// information, or null pointer when the returned type is not an
+/// ObjCObjectPointerType.
+static QualType getReturnTypeForMethod(
+ const ObjCMethodDecl *Method, ArrayRef<QualType> TypeArgs,
+ const ObjCObjectPointerType *SelfType, ASTContext &C) {
+ QualType StaticResultType = Method->getReturnType();
+
+ // Is the return type declared as instance type?
+ if (StaticResultType == C.getObjCInstanceType())
+ return QualType(SelfType, 0);
+
+ // Check whether the result type depends on a type parameter.
+ if (!isObjCTypeParamDependent(StaticResultType))
+ return QualType();
+
+ QualType ResultType = StaticResultType.substObjCTypeArgs(
+ C, TypeArgs, ObjCSubstitutionContext::Result);
+
+ return ResultType;
+}
+
+/// When the receiver has a tracked type, use that type to validate the
+/// argumments of the message expression and the return value.
+void DynamicTypePropagation::checkPreObjCMessage(const ObjCMethodCall &M,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ SymbolRef Sym = M.getReceiverSVal().getAsSymbol();
+ if (!Sym)
+ return;
+
+ const ObjCObjectPointerType *const *TrackedType =
+ State->get<MostSpecializedTypeArgsMap>(Sym);
+ if (!TrackedType)
+ return;
+
+ // Get the type arguments from tracked type and substitute type arguments
+ // before do the semantic check.
+
+ ASTContext &ASTCtxt = C.getASTContext();
+ const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
+ const ObjCMethodDecl *Method =
+ findMethodDecl(MessageExpr, *TrackedType, ASTCtxt);
+
+ // It is possible to call non-existent methods in Obj-C.
+ if (!Method)
+ return;
+
+ Optional<ArrayRef<QualType>> TypeArgs =
+ (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
+ // This case might happen when there is an unspecialized override of a
+ // specialized method.
+ if (!TypeArgs)
+ return;
+
+ for (unsigned i = 0; i < Method->param_size(); i++) {
+ const Expr *Arg = MessageExpr->getArg(i);
+ const ParmVarDecl *Param = Method->parameters()[i];
+
+ QualType OrigParamType = Param->getType();
+ if (!isObjCTypeParamDependent(OrigParamType))
+ continue;
+
+ QualType ParamType = OrigParamType.substObjCTypeArgs(
+ ASTCtxt, *TypeArgs, ObjCSubstitutionContext::Parameter);
+ // Check if it can be assigned
+ const auto *ParamObjectPtrType = ParamType->getAs<ObjCObjectPointerType>();
+ const auto *ArgObjectPtrType =
+ stripCastsAndSugar(Arg)->getType()->getAs<ObjCObjectPointerType>();
+ if (!ParamObjectPtrType || !ArgObjectPtrType)
+ continue;
+
+ // Check if we have more concrete tracked type that is not a super type of
+ // the static argument type.
+ SVal ArgSVal = M.getArgSVal(i);
+ SymbolRef ArgSym = ArgSVal.getAsSymbol();
+ if (ArgSym) {
+ const ObjCObjectPointerType *const *TrackedArgType =
+ State->get<MostSpecializedTypeArgsMap>(ArgSym);
+ if (TrackedArgType &&
+ ASTCtxt.canAssignObjCInterfaces(ArgObjectPtrType, *TrackedArgType)) {
+ ArgObjectPtrType = *TrackedArgType;
+ }
+ }
+
+ // Warn when argument is incompatible with the parameter.
+ if (!ASTCtxt.canAssignObjCInterfaces(ParamObjectPtrType,
+ ArgObjectPtrType)) {
+ static CheckerProgramPointTag Tag(this, "ArgTypeMismatch");
+ ExplodedNode *N = C.addTransition(State, &Tag);
+ reportGenericsBug(ArgObjectPtrType, ParamObjectPtrType, N, Sym, C, Arg);
+ return;
+ }
+ }
+}
+
+/// This callback is used to infer the types for Class variables. This info is
+/// used later to validate messages that sent to classes. Class variables are
+/// initialized with by invoking the 'class' method on a class.
+/// This method is also used to infer the type information for the return
+/// types.
+// TODO: right now it only tracks generic types. Extend this to track every
+// type in the DynamicTypeMap and diagnose type errors!
+void DynamicTypePropagation::checkPostObjCMessage(const ObjCMethodCall &M,
+ CheckerContext &C) const {
+ const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
+
+ SymbolRef RetSym = M.getReturnValue().getAsSymbol();
+ if (!RetSym)
+ return;
+
+ Selector Sel = MessageExpr->getSelector();
+ ProgramStateRef State = C.getState();
+ // Inference for class variables.
+ // We are only interested in cases where the class method is invoked on a
+ // class. This method is provided by the runtime and available on all classes.
+ if (MessageExpr->getReceiverKind() == ObjCMessageExpr::Class &&
+ Sel.getAsString() == "class") {
+
+ QualType ReceiverType = MessageExpr->getClassReceiver();
+ const auto *ReceiverClassType = ReceiverType->getAs<ObjCObjectType>();
+ QualType ReceiverClassPointerType =
+ C.getASTContext().getObjCObjectPointerType(
+ QualType(ReceiverClassType, 0));
+
+ if (!ReceiverClassType->isSpecialized())
+ return;
+ const auto *InferredType =
+ ReceiverClassPointerType->getAs<ObjCObjectPointerType>();
+ assert(InferredType);
+
+ State = State->set<MostSpecializedTypeArgsMap>(RetSym, InferredType);
+ C.addTransition(State);
+ return;
+ }
+
+ // Tracking for return types.
+ SymbolRef RecSym = M.getReceiverSVal().getAsSymbol();
+ if (!RecSym)
+ return;
+
+ const ObjCObjectPointerType *const *TrackedType =
+ State->get<MostSpecializedTypeArgsMap>(RecSym);
+ if (!TrackedType)
+ return;
+
+ ASTContext &ASTCtxt = C.getASTContext();
+ const ObjCMethodDecl *Method =
+ findMethodDecl(MessageExpr, *TrackedType, ASTCtxt);
+ if (!Method)
+ return;
+
+ Optional<ArrayRef<QualType>> TypeArgs =
+ (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
+ if (!TypeArgs)
+ return;
+
+ QualType ResultType =
+ getReturnTypeForMethod(Method, *TypeArgs, *TrackedType, ASTCtxt);
+ // The static type is the same as the deduced type.
+ if (ResultType.isNull())
+ return;
+
+ const MemRegion *RetRegion = M.getReturnValue().getAsRegion();
+ ExplodedNode *Pred = C.getPredecessor();
+ // When there is an entry available for the return symbol in DynamicTypeMap,
+ // the call was inlined, and the information in the DynamicTypeMap is should
+ // be precise.
+ if (RetRegion && !State->get<DynamicTypeMap>(RetRegion)) {
+ // TODO: we have duplicated information in DynamicTypeMap and
+ // MostSpecializedTypeArgsMap. We should only store anything in the later if
+ // the stored data differs from the one stored in the former.
+ State = setDynamicTypeInfo(State, RetRegion, ResultType,
+ /*CanBeSubclass=*/true);
+ Pred = C.addTransition(State);
+ }
+
+ const auto *ResultPtrType = ResultType->getAs<ObjCObjectPointerType>();
+
+ if (!ResultPtrType || ResultPtrType->isUnspecialized())
+ return;
+
+ // When the result is a specialized type and it is not tracked yet, track it
+ // for the result symbol.
+ if (!State->get<MostSpecializedTypeArgsMap>(RetSym)) {
+ State = State->set<MostSpecializedTypeArgsMap>(RetSym, ResultPtrType);
+ C.addTransition(State, Pred);
+ }
+}
+
+void DynamicTypePropagation::reportGenericsBug(
+ const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
+ ExplodedNode *N, SymbolRef Sym, CheckerContext &C,
+ const Stmt *ReportedNode) const {
+ if (!CheckGenerics)
+ return;
+
+ initBugType();
+ SmallString<192> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ OS << "Conversion from value of type '";
+ QualType::print(From, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
+ OS << "' to incompatible type '";
+ QualType::print(To, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
+ OS << "'";
+ std::unique_ptr<BugReport> R(
+ new BugReport(*ObjCGenericsBugType, OS.str(), N));
+ R->markInteresting(Sym);
+ R->addVisitor(llvm::make_unique<GenericsBugVisitor>(Sym));
+ if (ReportedNode)
+ R->addRange(ReportedNode->getSourceRange());
+ C.emitReport(std::move(R));
+}
+
+PathDiagnosticPiece *DynamicTypePropagation::GenericsBugVisitor::VisitNode(
+ const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
+ BugReport &BR) {
+ ProgramStateRef state = N->getState();
+ ProgramStateRef statePrev = PrevN->getState();
+
+ const ObjCObjectPointerType *const *TrackedType =
+ state->get<MostSpecializedTypeArgsMap>(Sym);
+ const ObjCObjectPointerType *const *TrackedTypePrev =
+ statePrev->get<MostSpecializedTypeArgsMap>(Sym);
+ if (!TrackedType)
+ return nullptr;
+
+ if (TrackedTypePrev && *TrackedTypePrev == *TrackedType)
+ return nullptr;
+
+ // Retrieve the associated statement.
+ const Stmt *S = nullptr;
+ ProgramPoint ProgLoc = N->getLocation();
+ if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
+ S = SP->getStmt();
+ }
+
+ if (!S)
+ return nullptr;
+
+ const LangOptions &LangOpts = BRC.getASTContext().getLangOpts();
+
+ SmallString<256> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ OS << "Type '";
+ QualType::print(*TrackedType, Qualifiers(), OS, LangOpts, llvm::Twine());
+ OS << "' is inferred from ";
+
+ if (const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
+ OS << "explicit cast (from '";
+ QualType::print(ExplicitCast->getSubExpr()->getType().getTypePtr(),
+ Qualifiers(), OS, LangOpts, llvm::Twine());
+ OS << "' to '";
+ QualType::print(ExplicitCast->getType().getTypePtr(), Qualifiers(), OS,
+ LangOpts, llvm::Twine());
+ OS << "')";
+ } else if (const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
+ OS << "implicit cast (from '";
+ QualType::print(ImplicitCast->getSubExpr()->getType().getTypePtr(),
+ Qualifiers(), OS, LangOpts, llvm::Twine());
+ OS << "' to '";
+ QualType::print(ImplicitCast->getType().getTypePtr(), Qualifiers(), OS,
+ LangOpts, llvm::Twine());
+ OS << "')";
+ } else {
+ OS << "this context";
+ }
+
+ // Generate the extra diagnostic.
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+ N->getLocationContext());
+ return new PathDiagnosticEventPiece(Pos, OS.str(), true, nullptr);
+}
+
+/// Register checkers.
+void ento::registerObjCGenericsChecker(CheckerManager &mgr) {
+ DynamicTypePropagation *checker =
+ mgr.registerChecker<DynamicTypePropagation>();
+ checker->CheckGenerics = true;
+}
+
void ento::registerDynamicTypePropagation(CheckerManager &mgr) {
mgr.registerChecker<DynamicTypePropagation>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 7dc0a87..8f6c20a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -17,22 +17,26 @@ using namespace clang;
using namespace ento;
namespace {
-class ExprInspectionChecker : public Checker< eval::Call > {
+class ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols> {
mutable std::unique_ptr<BugType> BT;
void analyzerEval(const CallExpr *CE, CheckerContext &C) const;
void analyzerCheckInlined(const CallExpr *CE, CheckerContext &C) const;
void analyzerWarnIfReached(const CallExpr *CE, CheckerContext &C) const;
void analyzerCrash(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerWarnOnDeadSymbol(const CallExpr *CE, CheckerContext &C) const;
typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *,
CheckerContext &C) const;
public:
bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+ void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
};
}
+REGISTER_SET_WITH_PROGRAMSTATE(MarkedSymbols, const void *)
+
bool ExprInspectionChecker::evalCall(const CallExpr *CE,
CheckerContext &C) const {
// These checks should have no effect on the surrounding environment
@@ -42,7 +46,10 @@ bool ExprInspectionChecker::evalCall(const CallExpr *CE,
.Case("clang_analyzer_checkInlined",
&ExprInspectionChecker::analyzerCheckInlined)
.Case("clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash)
- .Case("clang_analyzer_warnIfReached", &ExprInspectionChecker::analyzerWarnIfReached)
+ .Case("clang_analyzer_warnIfReached",
+ &ExprInspectionChecker::analyzerWarnIfReached)
+ .Case("clang_analyzer_warnOnDeadSymbol",
+ &ExprInspectionChecker::analyzerWarnOnDeadSymbol)
.Default(nullptr);
if (!Handler)
@@ -86,8 +93,7 @@ static const char *getArgumentValueString(const CallExpr *CE,
void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
CheckerContext &C) const {
- ExplodedNode *N = C.getPredecessor();
- const LocationContext *LC = N->getLocationContext();
+ const LocationContext *LC = C.getPredecessor()->getLocationContext();
// A specific instantiation of an inlined function may have more constrained
// values than can generally be assumed. Skip the check.
@@ -97,24 +103,28 @@ void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
if (!BT)
BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ return;
C.emitReport(
llvm::make_unique<BugReport>(*BT, getArgumentValueString(CE, C), N));
}
void ExprInspectionChecker::analyzerWarnIfReached(const CallExpr *CE,
CheckerContext &C) const {
- ExplodedNode *N = C.getPredecessor();
if (!BT)
BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ return;
C.emitReport(llvm::make_unique<BugReport>(*BT, "REACHABLE", N));
}
void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
CheckerContext &C) const {
- ExplodedNode *N = C.getPredecessor();
- const LocationContext *LC = N->getLocationContext();
+ const LocationContext *LC = C.getPredecessor()->getLocationContext();
// An inlined function could conceivably also be analyzed as a top-level
// function. We ignore this case and only emit a message (TRUE or FALSE)
@@ -127,10 +137,48 @@ void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
if (!BT)
BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ return;
C.emitReport(
llvm::make_unique<BugReport>(*BT, getArgumentValueString(CE, C), N));
}
+void ExprInspectionChecker::analyzerWarnOnDeadSymbol(const CallExpr *CE,
+ CheckerContext &C) const {
+ if (CE->getNumArgs() == 0)
+ return;
+ SVal Val = C.getSVal(CE->getArg(0));
+ SymbolRef Sym = Val.getAsSymbol();
+ if (!Sym)
+ return;
+
+ ProgramStateRef State = C.getState();
+ State = State->add<MarkedSymbols>(Sym);
+ C.addTransition(State);
+}
+
+void ExprInspectionChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ const MarkedSymbolsTy &Syms = State->get<MarkedSymbols>();
+ for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
+ SymbolRef Sym = static_cast<SymbolRef>(*I);
+ if (!SymReaper.isDead(Sym))
+ continue;
+
+ if (!BT)
+ BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
+
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ return;
+
+ C.emitReport(llvm::make_unique<BugReport>(*BT, "SYMBOL DEAD", N));
+ C.addTransition(State->remove<MarkedSymbols>(Sym), N);
+ }
+}
+
void ExprInspectionChecker::analyzerCrash(const CallExpr *CE,
CheckerContext &C) const {
LLVM_BUILTIN_TRAP;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
index 48d6bd4..3fe89f9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
@@ -23,7 +23,7 @@ using namespace clang;
using namespace ento;
namespace {
-class FixedAddressChecker
+class FixedAddressChecker
: public Checker< check::PreStmt<BinaryOperator> > {
mutable std::unique_ptr<BuiltinBug> BT;
@@ -50,7 +50,7 @@ void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
if (!RV.isConstant() || RV.isZeroConstant())
return;
- if (ExplodedNode *N = C.addTransition()) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
if (!BT)
BT.reset(
new BuiltinBug(this, "Use fixed address",
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 2cf508f..8c8acc6 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -100,8 +100,8 @@ private:
/// Generate a report if the expression is tainted or points to tainted data.
bool generateReportIfTainted(const Expr *E, const char Msg[],
CheckerContext &C) const;
-
-
+
+
typedef SmallVector<unsigned, 2> ArgVector;
/// \brief A struct used to specify taint propagation rules for a function.
@@ -441,7 +441,7 @@ SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C,
return Val.getAsSymbol();
}
-ProgramStateRef
+ProgramStateRef
GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
@@ -640,7 +640,7 @@ bool GenericTaintChecker::generateReportIfTainted(const Expr *E,
return false;
// Generate diagnostic.
- if (ExplodedNode *N = C.addTransition()) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
initBugType();
auto report = llvm::make_unique<BugReport>(*BT, Msg, N);
report->addRange(E->getSourceRange());
@@ -658,17 +658,15 @@ bool GenericTaintChecker::checkUncontrolledFormatString(const CallExpr *CE,
return false;
// If either the format string content or the pointer itself are tainted, warn.
- if (generateReportIfTainted(CE->getArg(ArgNum),
- MsgUncontrolledFormatString, C))
- return true;
- return false;
+ return generateReportIfTainted(CE->getArg(ArgNum),
+ MsgUncontrolledFormatString, C);
}
bool GenericTaintChecker::checkSystemCall(const CallExpr *CE,
StringRef Name,
CheckerContext &C) const {
- // TODO: It might make sense to run this check on demand. In some cases,
- // we should check if the environment has been cleansed here. We also might
+ // TODO: It might make sense to run this check on demand. In some cases,
+ // we should check if the environment has been cleansed here. We also might
// need to know if the user was reset before these calls(seteuid).
unsigned ArgNum = llvm::StringSwitch<unsigned>(Name)
.Case("system", 0)
@@ -686,11 +684,7 @@ bool GenericTaintChecker::checkSystemCall(const CallExpr *CE,
if (ArgNum == UINT_MAX || CE->getNumArgs() < (ArgNum + 1))
return false;
- if (generateReportIfTainted(CE->getArg(ArgNum),
- MsgSanitizeSystemArgs, C))
- return true;
-
- return false;
+ return generateReportIfTainted(CE->getArg(ArgNum), MsgSanitizeSystemArgs, C);
}
// TODO: Should this check be a part of the CString checker?
@@ -728,11 +722,8 @@ bool GenericTaintChecker::checkTaintedBufferSize(const CallExpr *CE,
ArgNum = 2;
}
- if (ArgNum != InvalidArgIndex && CE->getNumArgs() > ArgNum &&
- generateReportIfTainted(CE->getArg(ArgNum), MsgTaintedBufferSize, C))
- return true;
-
- return false;
+ return ArgNum != InvalidArgIndex && CE->getNumArgs() > ArgNum &&
+ generateReportIfTainted(CE->getArg(ArgNum), MsgTaintedBufferSize, C);
}
void ento::registerGenericTaintChecker(CheckerManager &mgr) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
index 58d0783..0c3bff5 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
@@ -96,7 +96,7 @@ void FindIdenticalExprVisitor::checkBitwiseOrLogicalOp(const BinaryOperator *B,
}
LHS = B2->getLHS();
}
-
+
if (isIdenticalStmt(AC->getASTContext(), RHS, LHS)) {
Sr[0] = RHS->getSourceRange();
Sr[1] = LHS->getSourceRange();
@@ -108,6 +108,24 @@ bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) {
const Stmt *Stmt1 = I->getThen();
const Stmt *Stmt2 = I->getElse();
+ // Check for identical inner condition:
+ //
+ // if (x<10) {
+ // if (x<10) {
+ // ..
+ if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(Stmt1)) {
+ if (!CS->body_empty()) {
+ const IfStmt *InnerIf = dyn_cast<IfStmt>(*CS->body_begin());
+ if (InnerIf && isIdenticalStmt(AC->getASTContext(), I->getCond(), InnerIf->getCond(), /*ignoreSideEffects=*/ false)) {
+ PathDiagnosticLocation ELoc(InnerIf->getCond(), BR.getSourceManager(), AC);
+ BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions",
+ categories::LogicError,
+ "conditions of the inner and outer statements are identical",
+ ELoc);
+ }
+ }
+ }
+
// Check for identical conditions:
//
// if (b) {
@@ -287,9 +305,7 @@ static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
const Stmt *Stmt2, bool IgnoreSideEffects) {
if (!Stmt1 || !Stmt2) {
- if (!Stmt1 && !Stmt2)
- return true;
- return false;
+ return !Stmt1 && !Stmt2;
}
// If Stmt1 & Stmt2 are of different class then they are not
@@ -332,6 +348,7 @@ static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
return false;
case Stmt::CallExprClass:
case Stmt::ArraySubscriptExprClass:
+ case Stmt::OMPArraySectionExprClass:
case Stmt::ImplicitCastExprClass:
case Stmt::ParenExprClass:
case Stmt::BreakStmtClass:
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
index 3df5fa0..dffff38 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
@@ -20,8 +20,8 @@
// been called on them. An invalidation method should either invalidate all
// the ivars or call another invalidation method (on self).
//
-// Partial invalidor annotation allows to addess cases when ivars are
-// invalidated by other methods, which might or might not be called from
+// Partial invalidor annotation allows to addess cases when ivars are
+// invalidated by other methods, which might or might not be called from
// the invalidation method. The checker checks that each invalidation
// method and all the partial methods cumulatively invalidate all ivars.
// __attribute__((annotate("objc_instance_variable_invalidator_partial")));
@@ -310,7 +310,7 @@ const ObjCIvarDecl *IvarInvalidationCheckerImpl::findPropertyBackingIvar(
// Lookup for the synthesized case.
IvarD = Prop->getPropertyIvarDecl();
- // We only track the ivars/properties that are defined in the current
+ // We only track the ivars/properties that are defined in the current
// class (not the parent).
if (IvarD && IvarD->getContainingInterface() == InterfaceD) {
if (TrackedIvars.count(IvarD)) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
index 4e3f9b7..db4fbca 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
@@ -276,7 +276,6 @@ void ASTFieldVisitor::ReportError(QualType T) {
}
}
os << " (type " << FieldChain.back()->getType().getAsString() << ")";
- os.flush();
// Note that this will fire for every translation unit that uses this
// class. This is suboptimal, but at least scan-build will merge
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
new file mode 100644
index 0000000..56346cd
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
@@ -0,0 +1,1201 @@
+//=- LocalizationChecker.cpp -------------------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a set of checks for localizability including:
+// 1) A checker that warns about uses of non-localized NSStrings passed to
+// UI methods expecting localized strings
+// 2) A syntactic checker that warns against the bad practice of
+// not including a comment in NSLocalizedString macros.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "llvm/Support/Unicode.h"
+#include "llvm/ADT/StringSet.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+struct LocalizedState {
+private:
+ enum Kind { NonLocalized, Localized } K;
+ LocalizedState(Kind InK) : K(InK) {}
+
+public:
+ bool isLocalized() const { return K == Localized; }
+ bool isNonLocalized() const { return K == NonLocalized; }
+
+ static LocalizedState getLocalized() { return LocalizedState(Localized); }
+ static LocalizedState getNonLocalized() {
+ return LocalizedState(NonLocalized);
+ }
+
+ // Overload the == operator
+ bool operator==(const LocalizedState &X) const { return K == X.K; }
+
+ // LLVMs equivalent of a hash function
+ void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(K); }
+};
+
+class NonLocalizedStringChecker
+ : public Checker<check::PostCall, check::PreObjCMessage,
+ check::PostObjCMessage,
+ check::PostStmt<ObjCStringLiteral>> {
+
+ mutable std::unique_ptr<BugType> BT;
+
+ // Methods that require a localized string
+ mutable llvm::DenseMap<const IdentifierInfo *,
+ llvm::DenseMap<Selector, uint8_t>> UIMethods;
+ // Methods that return a localized string
+ mutable llvm::SmallSet<std::pair<const IdentifierInfo *, Selector>, 12> LSM;
+ // C Functions that return a localized string
+ mutable llvm::SmallSet<const IdentifierInfo *, 5> LSF;
+
+ void initUIMethods(ASTContext &Ctx) const;
+ void initLocStringsMethods(ASTContext &Ctx) const;
+
+ bool hasNonLocalizedState(SVal S, CheckerContext &C) const;
+ bool hasLocalizedState(SVal S, CheckerContext &C) const;
+ void setNonLocalizedState(SVal S, CheckerContext &C) const;
+ void setLocalizedState(SVal S, CheckerContext &C) const;
+
+ bool isAnnotatedAsLocalized(const Decl *D) const;
+ void reportLocalizationError(SVal S, const ObjCMethodCall &M,
+ CheckerContext &C, int argumentNumber = 0) const;
+
+ int getLocalizedArgumentForSelector(const IdentifierInfo *Receiver,
+ Selector S) const;
+
+public:
+ NonLocalizedStringChecker();
+
+ // When this parameter is set to true, the checker assumes all
+ // methods that return NSStrings are unlocalized. Thus, more false
+ // positives will be reported.
+ DefaultBool IsAggressive;
+
+ void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
+ void checkPostObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
+ void checkPostStmt(const ObjCStringLiteral *SL, CheckerContext &C) const;
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+};
+
+} // end anonymous namespace
+
+REGISTER_MAP_WITH_PROGRAMSTATE(LocalizedMemMap, const MemRegion *,
+ LocalizedState)
+
+NonLocalizedStringChecker::NonLocalizedStringChecker() {
+ BT.reset(new BugType(this, "Unlocalizable string",
+ "Localizability Issue (Apple)"));
+}
+
+#define NEW_RECEIVER(receiver) \
+ llvm::DenseMap<Selector, uint8_t> &receiver##M = \
+ UIMethods.insert({&Ctx.Idents.get(#receiver), \
+ llvm::DenseMap<Selector, uint8_t>()}) \
+ .first->second;
+#define ADD_NULLARY_METHOD(receiver, method, argument) \
+ receiver##M.insert( \
+ {Ctx.Selectors.getNullarySelector(&Ctx.Idents.get(#method)), argument});
+#define ADD_UNARY_METHOD(receiver, method, argument) \
+ receiver##M.insert( \
+ {Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(#method)), argument});
+#define ADD_METHOD(receiver, method_list, count, argument) \
+ receiver##M.insert({Ctx.Selectors.getSelector(count, method_list), argument});
+
+/// Initializes a list of methods that require a localized string
+/// Format: {"ClassName", {{"selectorName:", LocStringArg#}, ...}, ...}
+void NonLocalizedStringChecker::initUIMethods(ASTContext &Ctx) const {
+ if (!UIMethods.empty())
+ return;
+
+ // UI Methods
+ NEW_RECEIVER(UISearchDisplayController)
+ ADD_UNARY_METHOD(UISearchDisplayController, setSearchResultsTitle, 0)
+
+ NEW_RECEIVER(UITabBarItem)
+ IdentifierInfo *initWithTitleUITabBarItemTag[] = {
+ &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("image"),
+ &Ctx.Idents.get("tag")};
+ ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemTag, 3, 0)
+ IdentifierInfo *initWithTitleUITabBarItemImage[] = {
+ &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("image"),
+ &Ctx.Idents.get("selectedImage")};
+ ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemImage, 3, 0)
+
+ NEW_RECEIVER(NSDockTile)
+ ADD_UNARY_METHOD(NSDockTile, setBadgeLabel, 0)
+
+ NEW_RECEIVER(NSStatusItem)
+ ADD_UNARY_METHOD(NSStatusItem, setTitle, 0)
+ ADD_UNARY_METHOD(NSStatusItem, setToolTip, 0)
+
+ NEW_RECEIVER(UITableViewRowAction)
+ IdentifierInfo *rowActionWithStyleUITableViewRowAction[] = {
+ &Ctx.Idents.get("rowActionWithStyle"), &Ctx.Idents.get("title"),
+ &Ctx.Idents.get("handler")};
+ ADD_METHOD(UITableViewRowAction, rowActionWithStyleUITableViewRowAction, 3, 1)
+ ADD_UNARY_METHOD(UITableViewRowAction, setTitle, 0)
+
+ NEW_RECEIVER(NSBox)
+ ADD_UNARY_METHOD(NSBox, setTitle, 0)
+
+ NEW_RECEIVER(NSButton)
+ ADD_UNARY_METHOD(NSButton, setTitle, 0)
+ ADD_UNARY_METHOD(NSButton, setAlternateTitle, 0)
+
+ NEW_RECEIVER(NSSavePanel)
+ ADD_UNARY_METHOD(NSSavePanel, setPrompt, 0)
+ ADD_UNARY_METHOD(NSSavePanel, setTitle, 0)
+ ADD_UNARY_METHOD(NSSavePanel, setNameFieldLabel, 0)
+ ADD_UNARY_METHOD(NSSavePanel, setNameFieldStringValue, 0)
+ ADD_UNARY_METHOD(NSSavePanel, setMessage, 0)
+
+ NEW_RECEIVER(UIPrintInfo)
+ ADD_UNARY_METHOD(UIPrintInfo, setJobName, 0)
+
+ NEW_RECEIVER(NSTabViewItem)
+ ADD_UNARY_METHOD(NSTabViewItem, setLabel, 0)
+ ADD_UNARY_METHOD(NSTabViewItem, setToolTip, 0)
+
+ NEW_RECEIVER(NSBrowser)
+ IdentifierInfo *setTitleNSBrowser[] = {&Ctx.Idents.get("setTitle"),
+ &Ctx.Idents.get("ofColumn")};
+ ADD_METHOD(NSBrowser, setTitleNSBrowser, 2, 0)
+
+ NEW_RECEIVER(UIAccessibilityElement)
+ ADD_UNARY_METHOD(UIAccessibilityElement, setAccessibilityLabel, 0)
+ ADD_UNARY_METHOD(UIAccessibilityElement, setAccessibilityHint, 0)
+ ADD_UNARY_METHOD(UIAccessibilityElement, setAccessibilityValue, 0)
+
+ NEW_RECEIVER(UIAlertAction)
+ IdentifierInfo *actionWithTitleUIAlertAction[] = {
+ &Ctx.Idents.get("actionWithTitle"), &Ctx.Idents.get("style"),
+ &Ctx.Idents.get("handler")};
+ ADD_METHOD(UIAlertAction, actionWithTitleUIAlertAction, 3, 0)
+
+ NEW_RECEIVER(NSPopUpButton)
+ ADD_UNARY_METHOD(NSPopUpButton, addItemWithTitle, 0)
+ IdentifierInfo *insertItemWithTitleNSPopUpButton[] = {
+ &Ctx.Idents.get("insertItemWithTitle"), &Ctx.Idents.get("atIndex")};
+ ADD_METHOD(NSPopUpButton, insertItemWithTitleNSPopUpButton, 2, 0)
+ ADD_UNARY_METHOD(NSPopUpButton, removeItemWithTitle, 0)
+ ADD_UNARY_METHOD(NSPopUpButton, selectItemWithTitle, 0)
+ ADD_UNARY_METHOD(NSPopUpButton, setTitle, 0)
+
+ NEW_RECEIVER(NSTableViewRowAction)
+ IdentifierInfo *rowActionWithStyleNSTableViewRowAction[] = {
+ &Ctx.Idents.get("rowActionWithStyle"), &Ctx.Idents.get("title"),
+ &Ctx.Idents.get("handler")};
+ ADD_METHOD(NSTableViewRowAction, rowActionWithStyleNSTableViewRowAction, 3, 1)
+ ADD_UNARY_METHOD(NSTableViewRowAction, setTitle, 0)
+
+ NEW_RECEIVER(NSImage)
+ ADD_UNARY_METHOD(NSImage, setAccessibilityDescription, 0)
+
+ NEW_RECEIVER(NSUserActivity)
+ ADD_UNARY_METHOD(NSUserActivity, setTitle, 0)
+
+ NEW_RECEIVER(NSPathControlItem)
+ ADD_UNARY_METHOD(NSPathControlItem, setTitle, 0)
+
+ NEW_RECEIVER(NSCell)
+ ADD_UNARY_METHOD(NSCell, initTextCell, 0)
+ ADD_UNARY_METHOD(NSCell, setTitle, 0)
+ ADD_UNARY_METHOD(NSCell, setStringValue, 0)
+
+ NEW_RECEIVER(NSPathControl)
+ ADD_UNARY_METHOD(NSPathControl, setPlaceholderString, 0)
+
+ NEW_RECEIVER(UIAccessibility)
+ ADD_UNARY_METHOD(UIAccessibility, setAccessibilityLabel, 0)
+ ADD_UNARY_METHOD(UIAccessibility, setAccessibilityHint, 0)
+ ADD_UNARY_METHOD(UIAccessibility, setAccessibilityValue, 0)
+
+ NEW_RECEIVER(NSTableColumn)
+ ADD_UNARY_METHOD(NSTableColumn, setTitle, 0)
+ ADD_UNARY_METHOD(NSTableColumn, setHeaderToolTip, 0)
+
+ NEW_RECEIVER(NSSegmentedControl)
+ IdentifierInfo *setLabelNSSegmentedControl[] = {
+ &Ctx.Idents.get("setLabel"), &Ctx.Idents.get("forSegment")};
+ ADD_METHOD(NSSegmentedControl, setLabelNSSegmentedControl, 2, 0)
+
+ NEW_RECEIVER(NSButtonCell)
+ ADD_UNARY_METHOD(NSButtonCell, setTitle, 0)
+ ADD_UNARY_METHOD(NSButtonCell, setAlternateTitle, 0)
+
+ NEW_RECEIVER(NSSliderCell)
+ ADD_UNARY_METHOD(NSSliderCell, setTitle, 0)
+
+ NEW_RECEIVER(NSControl)
+ ADD_UNARY_METHOD(NSControl, setStringValue, 0)
+
+ NEW_RECEIVER(NSAccessibility)
+ ADD_UNARY_METHOD(NSAccessibility, setAccessibilityValueDescription, 0)
+ ADD_UNARY_METHOD(NSAccessibility, setAccessibilityLabel, 0)
+ ADD_UNARY_METHOD(NSAccessibility, setAccessibilityTitle, 0)
+ ADD_UNARY_METHOD(NSAccessibility, setAccessibilityPlaceholderValue, 0)
+ ADD_UNARY_METHOD(NSAccessibility, setAccessibilityHelp, 0)
+
+ NEW_RECEIVER(NSMatrix)
+ IdentifierInfo *setToolTipNSMatrix[] = {&Ctx.Idents.get("setToolTip"),
+ &Ctx.Idents.get("forCell")};
+ ADD_METHOD(NSMatrix, setToolTipNSMatrix, 2, 0)
+
+ NEW_RECEIVER(NSPrintPanel)
+ ADD_UNARY_METHOD(NSPrintPanel, setDefaultButtonTitle, 0)
+
+ NEW_RECEIVER(UILocalNotification)
+ ADD_UNARY_METHOD(UILocalNotification, setAlertBody, 0)
+ ADD_UNARY_METHOD(UILocalNotification, setAlertAction, 0)
+ ADD_UNARY_METHOD(UILocalNotification, setAlertTitle, 0)
+
+ NEW_RECEIVER(NSSlider)
+ ADD_UNARY_METHOD(NSSlider, setTitle, 0)
+
+ NEW_RECEIVER(UIMenuItem)
+ IdentifierInfo *initWithTitleUIMenuItem[] = {&Ctx.Idents.get("initWithTitle"),
+ &Ctx.Idents.get("action")};
+ ADD_METHOD(UIMenuItem, initWithTitleUIMenuItem, 2, 0)
+ ADD_UNARY_METHOD(UIMenuItem, setTitle, 0)
+
+ NEW_RECEIVER(UIAlertController)
+ IdentifierInfo *alertControllerWithTitleUIAlertController[] = {
+ &Ctx.Idents.get("alertControllerWithTitle"), &Ctx.Idents.get("message"),
+ &Ctx.Idents.get("preferredStyle")};
+ ADD_METHOD(UIAlertController, alertControllerWithTitleUIAlertController, 3, 1)
+ ADD_UNARY_METHOD(UIAlertController, setTitle, 0)
+ ADD_UNARY_METHOD(UIAlertController, setMessage, 0)
+
+ NEW_RECEIVER(UIApplicationShortcutItem)
+ IdentifierInfo *initWithTypeUIApplicationShortcutItemIcon[] = {
+ &Ctx.Idents.get("initWithType"), &Ctx.Idents.get("localizedTitle"),
+ &Ctx.Idents.get("localizedSubtitle"), &Ctx.Idents.get("icon"),
+ &Ctx.Idents.get("userInfo")};
+ ADD_METHOD(UIApplicationShortcutItem,
+ initWithTypeUIApplicationShortcutItemIcon, 5, 1)
+ IdentifierInfo *initWithTypeUIApplicationShortcutItem[] = {
+ &Ctx.Idents.get("initWithType"), &Ctx.Idents.get("localizedTitle")};
+ ADD_METHOD(UIApplicationShortcutItem, initWithTypeUIApplicationShortcutItem,
+ 2, 1)
+
+ NEW_RECEIVER(UIActionSheet)
+ IdentifierInfo *initWithTitleUIActionSheet[] = {
+ &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("delegate"),
+ &Ctx.Idents.get("cancelButtonTitle"),
+ &Ctx.Idents.get("destructiveButtonTitle"),
+ &Ctx.Idents.get("otherButtonTitles")};
+ ADD_METHOD(UIActionSheet, initWithTitleUIActionSheet, 5, 0)
+ ADD_UNARY_METHOD(UIActionSheet, addButtonWithTitle, 0)
+ ADD_UNARY_METHOD(UIActionSheet, setTitle, 0)
+
+ NEW_RECEIVER(NSURLSessionTask)
+ ADD_UNARY_METHOD(NSURLSessionTask, setTaskDescription, 0)
+
+ NEW_RECEIVER(UIAccessibilityCustomAction)
+ IdentifierInfo *initWithNameUIAccessibilityCustomAction[] = {
+ &Ctx.Idents.get("initWithName"), &Ctx.Idents.get("target"),
+ &Ctx.Idents.get("selector")};
+ ADD_METHOD(UIAccessibilityCustomAction,
+ initWithNameUIAccessibilityCustomAction, 3, 0)
+ ADD_UNARY_METHOD(UIAccessibilityCustomAction, setName, 0)
+
+ NEW_RECEIVER(UISearchBar)
+ ADD_UNARY_METHOD(UISearchBar, setText, 0)
+ ADD_UNARY_METHOD(UISearchBar, setPrompt, 0)
+ ADD_UNARY_METHOD(UISearchBar, setPlaceholder, 0)
+
+ NEW_RECEIVER(UIBarItem)
+ ADD_UNARY_METHOD(UIBarItem, setTitle, 0)
+
+ NEW_RECEIVER(UITextView)
+ ADD_UNARY_METHOD(UITextView, setText, 0)
+
+ NEW_RECEIVER(NSView)
+ ADD_UNARY_METHOD(NSView, setToolTip, 0)
+
+ NEW_RECEIVER(NSTextField)
+ ADD_UNARY_METHOD(NSTextField, setPlaceholderString, 0)
+
+ NEW_RECEIVER(NSAttributedString)
+ ADD_UNARY_METHOD(NSAttributedString, initWithString, 0)
+ IdentifierInfo *initWithStringNSAttributedString[] = {
+ &Ctx.Idents.get("initWithString"), &Ctx.Idents.get("attributes")};
+ ADD_METHOD(NSAttributedString, initWithStringNSAttributedString, 2, 0)
+
+ NEW_RECEIVER(NSText)
+ ADD_UNARY_METHOD(NSText, setString, 0)
+
+ NEW_RECEIVER(UIKeyCommand)
+ IdentifierInfo *keyCommandWithInputUIKeyCommand[] = {
+ &Ctx.Idents.get("keyCommandWithInput"), &Ctx.Idents.get("modifierFlags"),
+ &Ctx.Idents.get("action"), &Ctx.Idents.get("discoverabilityTitle")};
+ ADD_METHOD(UIKeyCommand, keyCommandWithInputUIKeyCommand, 4, 3)
+ ADD_UNARY_METHOD(UIKeyCommand, setDiscoverabilityTitle, 0)
+
+ NEW_RECEIVER(UILabel)
+ ADD_UNARY_METHOD(UILabel, setText, 0)
+
+ NEW_RECEIVER(NSAlert)
+ IdentifierInfo *alertWithMessageTextNSAlert[] = {
+ &Ctx.Idents.get("alertWithMessageText"), &Ctx.Idents.get("defaultButton"),
+ &Ctx.Idents.get("alternateButton"), &Ctx.Idents.get("otherButton"),
+ &Ctx.Idents.get("informativeTextWithFormat")};
+ ADD_METHOD(NSAlert, alertWithMessageTextNSAlert, 5, 0)
+ ADD_UNARY_METHOD(NSAlert, addButtonWithTitle, 0)
+ ADD_UNARY_METHOD(NSAlert, setMessageText, 0)
+ ADD_UNARY_METHOD(NSAlert, setInformativeText, 0)
+ ADD_UNARY_METHOD(NSAlert, setHelpAnchor, 0)
+
+ NEW_RECEIVER(UIMutableApplicationShortcutItem)
+ ADD_UNARY_METHOD(UIMutableApplicationShortcutItem, setLocalizedTitle, 0)
+ ADD_UNARY_METHOD(UIMutableApplicationShortcutItem, setLocalizedSubtitle, 0)
+
+ NEW_RECEIVER(UIButton)
+ IdentifierInfo *setTitleUIButton[] = {&Ctx.Idents.get("setTitle"),
+ &Ctx.Idents.get("forState")};
+ ADD_METHOD(UIButton, setTitleUIButton, 2, 0)
+
+ NEW_RECEIVER(NSWindow)
+ ADD_UNARY_METHOD(NSWindow, setTitle, 0)
+ IdentifierInfo *minFrameWidthWithTitleNSWindow[] = {
+ &Ctx.Idents.get("minFrameWidthWithTitle"), &Ctx.Idents.get("styleMask")};
+ ADD_METHOD(NSWindow, minFrameWidthWithTitleNSWindow, 2, 0)
+ ADD_UNARY_METHOD(NSWindow, setMiniwindowTitle, 0)
+
+ NEW_RECEIVER(NSPathCell)
+ ADD_UNARY_METHOD(NSPathCell, setPlaceholderString, 0)
+
+ NEW_RECEIVER(UIDocumentMenuViewController)
+ IdentifierInfo *addOptionWithTitleUIDocumentMenuViewController[] = {
+ &Ctx.Idents.get("addOptionWithTitle"), &Ctx.Idents.get("image"),
+ &Ctx.Idents.get("order"), &Ctx.Idents.get("handler")};
+ ADD_METHOD(UIDocumentMenuViewController,
+ addOptionWithTitleUIDocumentMenuViewController, 4, 0)
+
+ NEW_RECEIVER(UINavigationItem)
+ ADD_UNARY_METHOD(UINavigationItem, initWithTitle, 0)
+ ADD_UNARY_METHOD(UINavigationItem, setTitle, 0)
+ ADD_UNARY_METHOD(UINavigationItem, setPrompt, 0)
+
+ NEW_RECEIVER(UIAlertView)
+ IdentifierInfo *initWithTitleUIAlertView[] = {
+ &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("message"),
+ &Ctx.Idents.get("delegate"), &Ctx.Idents.get("cancelButtonTitle"),
+ &Ctx.Idents.get("otherButtonTitles")};
+ ADD_METHOD(UIAlertView, initWithTitleUIAlertView, 5, 0)
+ ADD_UNARY_METHOD(UIAlertView, addButtonWithTitle, 0)
+ ADD_UNARY_METHOD(UIAlertView, setTitle, 0)
+ ADD_UNARY_METHOD(UIAlertView, setMessage, 0)
+
+ NEW_RECEIVER(NSFormCell)
+ ADD_UNARY_METHOD(NSFormCell, initTextCell, 0)
+ ADD_UNARY_METHOD(NSFormCell, setTitle, 0)
+ ADD_UNARY_METHOD(NSFormCell, setPlaceholderString, 0)
+
+ NEW_RECEIVER(NSUserNotification)
+ ADD_UNARY_METHOD(NSUserNotification, setTitle, 0)
+ ADD_UNARY_METHOD(NSUserNotification, setSubtitle, 0)
+ ADD_UNARY_METHOD(NSUserNotification, setInformativeText, 0)
+ ADD_UNARY_METHOD(NSUserNotification, setActionButtonTitle, 0)
+ ADD_UNARY_METHOD(NSUserNotification, setOtherButtonTitle, 0)
+ ADD_UNARY_METHOD(NSUserNotification, setResponsePlaceholder, 0)
+
+ NEW_RECEIVER(NSToolbarItem)
+ ADD_UNARY_METHOD(NSToolbarItem, setLabel, 0)
+ ADD_UNARY_METHOD(NSToolbarItem, setPaletteLabel, 0)
+ ADD_UNARY_METHOD(NSToolbarItem, setToolTip, 0)
+
+ NEW_RECEIVER(NSProgress)
+ ADD_UNARY_METHOD(NSProgress, setLocalizedDescription, 0)
+ ADD_UNARY_METHOD(NSProgress, setLocalizedAdditionalDescription, 0)
+
+ NEW_RECEIVER(NSSegmentedCell)
+ IdentifierInfo *setLabelNSSegmentedCell[] = {&Ctx.Idents.get("setLabel"),
+ &Ctx.Idents.get("forSegment")};
+ ADD_METHOD(NSSegmentedCell, setLabelNSSegmentedCell, 2, 0)
+ IdentifierInfo *setToolTipNSSegmentedCell[] = {&Ctx.Idents.get("setToolTip"),
+ &Ctx.Idents.get("forSegment")};
+ ADD_METHOD(NSSegmentedCell, setToolTipNSSegmentedCell, 2, 0)
+
+ NEW_RECEIVER(NSUndoManager)
+ ADD_UNARY_METHOD(NSUndoManager, setActionName, 0)
+ ADD_UNARY_METHOD(NSUndoManager, undoMenuTitleForUndoActionName, 0)
+ ADD_UNARY_METHOD(NSUndoManager, redoMenuTitleForUndoActionName, 0)
+
+ NEW_RECEIVER(NSMenuItem)
+ IdentifierInfo *initWithTitleNSMenuItem[] = {
+ &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("action"),
+ &Ctx.Idents.get("keyEquivalent")};
+ ADD_METHOD(NSMenuItem, initWithTitleNSMenuItem, 3, 0)
+ ADD_UNARY_METHOD(NSMenuItem, setTitle, 0)
+ ADD_UNARY_METHOD(NSMenuItem, setToolTip, 0)
+
+ NEW_RECEIVER(NSPopUpButtonCell)
+ IdentifierInfo *initTextCellNSPopUpButtonCell[] = {
+ &Ctx.Idents.get("initTextCell"), &Ctx.Idents.get("pullsDown")};
+ ADD_METHOD(NSPopUpButtonCell, initTextCellNSPopUpButtonCell, 2, 0)
+ ADD_UNARY_METHOD(NSPopUpButtonCell, addItemWithTitle, 0)
+ IdentifierInfo *insertItemWithTitleNSPopUpButtonCell[] = {
+ &Ctx.Idents.get("insertItemWithTitle"), &Ctx.Idents.get("atIndex")};
+ ADD_METHOD(NSPopUpButtonCell, insertItemWithTitleNSPopUpButtonCell, 2, 0)
+ ADD_UNARY_METHOD(NSPopUpButtonCell, removeItemWithTitle, 0)
+ ADD_UNARY_METHOD(NSPopUpButtonCell, selectItemWithTitle, 0)
+ ADD_UNARY_METHOD(NSPopUpButtonCell, setTitle, 0)
+
+ NEW_RECEIVER(NSViewController)
+ ADD_UNARY_METHOD(NSViewController, setTitle, 0)
+
+ NEW_RECEIVER(NSMenu)
+ ADD_UNARY_METHOD(NSMenu, initWithTitle, 0)
+ IdentifierInfo *insertItemWithTitleNSMenu[] = {
+ &Ctx.Idents.get("insertItemWithTitle"), &Ctx.Idents.get("action"),
+ &Ctx.Idents.get("keyEquivalent"), &Ctx.Idents.get("atIndex")};
+ ADD_METHOD(NSMenu, insertItemWithTitleNSMenu, 4, 0)
+ IdentifierInfo *addItemWithTitleNSMenu[] = {
+ &Ctx.Idents.get("addItemWithTitle"), &Ctx.Idents.get("action"),
+ &Ctx.Idents.get("keyEquivalent")};
+ ADD_METHOD(NSMenu, addItemWithTitleNSMenu, 3, 0)
+ ADD_UNARY_METHOD(NSMenu, setTitle, 0)
+
+ NEW_RECEIVER(UIMutableUserNotificationAction)
+ ADD_UNARY_METHOD(UIMutableUserNotificationAction, setTitle, 0)
+
+ NEW_RECEIVER(NSForm)
+ ADD_UNARY_METHOD(NSForm, addEntry, 0)
+ IdentifierInfo *insertEntryNSForm[] = {&Ctx.Idents.get("insertEntry"),
+ &Ctx.Idents.get("atIndex")};
+ ADD_METHOD(NSForm, insertEntryNSForm, 2, 0)
+
+ NEW_RECEIVER(NSTextFieldCell)
+ ADD_UNARY_METHOD(NSTextFieldCell, setPlaceholderString, 0)
+
+ NEW_RECEIVER(NSUserNotificationAction)
+ IdentifierInfo *actionWithIdentifierNSUserNotificationAction[] = {
+ &Ctx.Idents.get("actionWithIdentifier"), &Ctx.Idents.get("title")};
+ ADD_METHOD(NSUserNotificationAction,
+ actionWithIdentifierNSUserNotificationAction, 2, 1)
+
+ NEW_RECEIVER(NSURLSession)
+ ADD_UNARY_METHOD(NSURLSession, setSessionDescription, 0)
+
+ NEW_RECEIVER(UITextField)
+ ADD_UNARY_METHOD(UITextField, setText, 0)
+ ADD_UNARY_METHOD(UITextField, setPlaceholder, 0)
+
+ NEW_RECEIVER(UIBarButtonItem)
+ IdentifierInfo *initWithTitleUIBarButtonItem[] = {
+ &Ctx.Idents.get("initWithTitle"), &Ctx.Idents.get("style"),
+ &Ctx.Idents.get("target"), &Ctx.Idents.get("action")};
+ ADD_METHOD(UIBarButtonItem, initWithTitleUIBarButtonItem, 4, 0)
+
+ NEW_RECEIVER(UIViewController)
+ ADD_UNARY_METHOD(UIViewController, setTitle, 0)
+
+ NEW_RECEIVER(UISegmentedControl)
+ IdentifierInfo *insertSegmentWithTitleUISegmentedControl[] = {
+ &Ctx.Idents.get("insertSegmentWithTitle"), &Ctx.Idents.get("atIndex"),
+ &Ctx.Idents.get("animated")};
+ ADD_METHOD(UISegmentedControl, insertSegmentWithTitleUISegmentedControl, 3, 0)
+ IdentifierInfo *setTitleUISegmentedControl[] = {
+ &Ctx.Idents.get("setTitle"), &Ctx.Idents.get("forSegmentAtIndex")};
+ ADD_METHOD(UISegmentedControl, setTitleUISegmentedControl, 2, 0)
+}
+
+#define LSF_INSERT(function_name) LSF.insert(&Ctx.Idents.get(function_name));
+#define LSM_INSERT_NULLARY(receiver, method_name) \
+ LSM.insert({&Ctx.Idents.get(receiver), Ctx.Selectors.getNullarySelector( \
+ &Ctx.Idents.get(method_name))});
+#define LSM_INSERT_UNARY(receiver, method_name) \
+ LSM.insert({&Ctx.Idents.get(receiver), \
+ Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(method_name))});
+#define LSM_INSERT_SELECTOR(receiver, method_list, arguments) \
+ LSM.insert({&Ctx.Idents.get(receiver), \
+ Ctx.Selectors.getSelector(arguments, method_list)});
+
+/// Initializes a list of methods and C functions that return a localized string
+void NonLocalizedStringChecker::initLocStringsMethods(ASTContext &Ctx) const {
+ if (!LSM.empty())
+ return;
+
+ IdentifierInfo *LocalizedStringMacro[] = {
+ &Ctx.Idents.get("localizedStringForKey"), &Ctx.Idents.get("value"),
+ &Ctx.Idents.get("table")};
+ LSM_INSERT_SELECTOR("NSBundle", LocalizedStringMacro, 3)
+ LSM_INSERT_UNARY("NSDateFormatter", "stringFromDate")
+ IdentifierInfo *LocalizedStringFromDate[] = {
+ &Ctx.Idents.get("localizedStringFromDate"), &Ctx.Idents.get("dateStyle"),
+ &Ctx.Idents.get("timeStyle")};
+ LSM_INSERT_SELECTOR("NSDateFormatter", LocalizedStringFromDate, 3)
+ LSM_INSERT_UNARY("NSNumberFormatter", "stringFromNumber")
+ LSM_INSERT_NULLARY("UITextField", "text")
+ LSM_INSERT_NULLARY("UITextView", "text")
+ LSM_INSERT_NULLARY("UILabel", "text")
+
+ LSF_INSERT("CFDateFormatterCreateStringWithDate");
+ LSF_INSERT("CFDateFormatterCreateStringWithAbsoluteTime");
+ LSF_INSERT("CFNumberFormatterCreateStringWithNumber");
+}
+
+/// Checks to see if the method / function declaration includes
+/// __attribute__((annotate("returns_localized_nsstring")))
+bool NonLocalizedStringChecker::isAnnotatedAsLocalized(const Decl *D) const {
+ if (!D)
+ return false;
+ return std::any_of(
+ D->specific_attr_begin<AnnotateAttr>(),
+ D->specific_attr_end<AnnotateAttr>(), [](const AnnotateAttr *Ann) {
+ return Ann->getAnnotation() == "returns_localized_nsstring";
+ });
+}
+
+/// Returns true if the given SVal is marked as Localized in the program state
+bool NonLocalizedStringChecker::hasLocalizedState(SVal S,
+ CheckerContext &C) const {
+ const MemRegion *mt = S.getAsRegion();
+ if (mt) {
+ const LocalizedState *LS = C.getState()->get<LocalizedMemMap>(mt);
+ if (LS && LS->isLocalized())
+ return true;
+ }
+ return false;
+}
+
+/// Returns true if the given SVal is marked as NonLocalized in the program
+/// state
+bool NonLocalizedStringChecker::hasNonLocalizedState(SVal S,
+ CheckerContext &C) const {
+ const MemRegion *mt = S.getAsRegion();
+ if (mt) {
+ const LocalizedState *LS = C.getState()->get<LocalizedMemMap>(mt);
+ if (LS && LS->isNonLocalized())
+ return true;
+ }
+ return false;
+}
+
+/// Marks the given SVal as Localized in the program state
+void NonLocalizedStringChecker::setLocalizedState(const SVal S,
+ CheckerContext &C) const {
+ const MemRegion *mt = S.getAsRegion();
+ if (mt) {
+ ProgramStateRef State =
+ C.getState()->set<LocalizedMemMap>(mt, LocalizedState::getLocalized());
+ C.addTransition(State);
+ }
+}
+
+/// Marks the given SVal as NonLocalized in the program state
+void NonLocalizedStringChecker::setNonLocalizedState(const SVal S,
+ CheckerContext &C) const {
+ const MemRegion *mt = S.getAsRegion();
+ if (mt) {
+ ProgramStateRef State = C.getState()->set<LocalizedMemMap>(
+ mt, LocalizedState::getNonLocalized());
+ C.addTransition(State);
+ }
+}
+
+/// Reports a localization error for the passed in method call and SVal
+void NonLocalizedStringChecker::reportLocalizationError(
+ SVal S, const ObjCMethodCall &M, CheckerContext &C,
+ int argumentNumber) const {
+
+ ExplodedNode *ErrNode = C.getPredecessor();
+ static CheckerProgramPointTag Tag("NonLocalizedStringChecker",
+ "UnlocalizedString");
+ ErrNode = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
+
+ if (!ErrNode)
+ return;
+
+ // Generate the bug report.
+ std::unique_ptr<BugReport> R(new BugReport(
+ *BT, "User-facing text should use localized string macro", ErrNode));
+ if (argumentNumber) {
+ R->addRange(M.getArgExpr(argumentNumber - 1)->getSourceRange());
+ } else {
+ R->addRange(M.getSourceRange());
+ }
+ R->markInteresting(S);
+ C.emitReport(std::move(R));
+}
+
+/// Returns the argument number requiring localized string if it exists
+/// otherwise, returns -1
+int NonLocalizedStringChecker::getLocalizedArgumentForSelector(
+ const IdentifierInfo *Receiver, Selector S) const {
+ auto method = UIMethods.find(Receiver);
+
+ if (method == UIMethods.end())
+ return -1;
+
+ auto argumentIterator = method->getSecond().find(S);
+
+ if (argumentIterator == method->getSecond().end())
+ return -1;
+
+ int argumentNumber = argumentIterator->getSecond();
+ return argumentNumber;
+}
+
+/// Check if the string being passed in has NonLocalized state
+void NonLocalizedStringChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
+ CheckerContext &C) const {
+ initUIMethods(C.getASTContext());
+
+ const ObjCInterfaceDecl *OD = msg.getReceiverInterface();
+ if (!OD)
+ return;
+ const IdentifierInfo *odInfo = OD->getIdentifier();
+
+ Selector S = msg.getSelector();
+
+ std::string SelectorString = S.getAsString();
+ StringRef SelectorName = SelectorString;
+ assert(!SelectorName.empty());
+
+ if (odInfo->isStr("NSString")) {
+ // Handle the case where the receiver is an NSString
+ // These special NSString methods draw to the screen
+
+ if (!(SelectorName.startswith("drawAtPoint") ||
+ SelectorName.startswith("drawInRect") ||
+ SelectorName.startswith("drawWithRect")))
+ return;
+
+ SVal svTitle = msg.getReceiverSVal();
+
+ bool isNonLocalized = hasNonLocalizedState(svTitle, C);
+
+ if (isNonLocalized) {
+ reportLocalizationError(svTitle, msg, C);
+ }
+ }
+
+ int argumentNumber = getLocalizedArgumentForSelector(odInfo, S);
+ // Go up each hierarchy of superclasses and their protocols
+ while (argumentNumber < 0 && OD->getSuperClass() != nullptr) {
+ for (const auto *P : OD->all_referenced_protocols()) {
+ argumentNumber = getLocalizedArgumentForSelector(P->getIdentifier(), S);
+ if (argumentNumber >= 0)
+ break;
+ }
+ if (argumentNumber < 0) {
+ OD = OD->getSuperClass();
+ argumentNumber = getLocalizedArgumentForSelector(OD->getIdentifier(), S);
+ }
+ }
+
+ if (argumentNumber < 0) // There was no match in UIMethods
+ return;
+
+ SVal svTitle = msg.getArgSVal(argumentNumber);
+
+ if (const ObjCStringRegion *SR =
+ dyn_cast_or_null<ObjCStringRegion>(svTitle.getAsRegion())) {
+ StringRef stringValue =
+ SR->getObjCStringLiteral()->getString()->getString();
+ if ((stringValue.trim().size() == 0 && stringValue.size() > 0) ||
+ stringValue.empty())
+ return;
+ if (!IsAggressive && llvm::sys::unicode::columnWidthUTF8(stringValue) < 2)
+ return;
+ }
+
+ bool isNonLocalized = hasNonLocalizedState(svTitle, C);
+
+ if (isNonLocalized) {
+ reportLocalizationError(svTitle, msg, C, argumentNumber + 1);
+ }
+}
+
+static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
+
+ const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
+ if (!PT)
+ return false;
+
+ ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();
+ if (!Cls)
+ return false;
+
+ IdentifierInfo *ClsName = Cls->getIdentifier();
+
+ // FIXME: Should we walk the chain of classes?
+ return ClsName == &Ctx.Idents.get("NSString") ||
+ ClsName == &Ctx.Idents.get("NSMutableString");
+}
+
+/// Marks a string being returned by any call as localized
+/// if it is in LocStringFunctions (LSF) or the function is annotated.
+/// Otherwise, we mark it as NonLocalized (Aggressive) or
+/// NonLocalized only if it is not backed by a SymRegion (Non-Aggressive),
+/// basically leaving only string literals as NonLocalized.
+void NonLocalizedStringChecker::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ initLocStringsMethods(C.getASTContext());
+
+ if (!Call.getOriginExpr())
+ return;
+
+ // Anything that takes in a localized NSString as an argument
+ // and returns an NSString will be assumed to be returning a
+ // localized NSString. (Counter: Incorrectly combining two LocalizedStrings)
+ const QualType RT = Call.getResultType();
+ if (isNSStringType(RT, C.getASTContext())) {
+ for (unsigned i = 0; i < Call.getNumArgs(); ++i) {
+ SVal argValue = Call.getArgSVal(i);
+ if (hasLocalizedState(argValue, C)) {
+ SVal sv = Call.getReturnValue();
+ setLocalizedState(sv, C);
+ return;
+ }
+ }
+ }
+
+ const Decl *D = Call.getDecl();
+ if (!D)
+ return;
+
+ const IdentifierInfo *Identifier = Call.getCalleeIdentifier();
+
+ SVal sv = Call.getReturnValue();
+ if (isAnnotatedAsLocalized(D) || LSF.count(Identifier) != 0) {
+ setLocalizedState(sv, C);
+ } else if (isNSStringType(RT, C.getASTContext()) &&
+ !hasLocalizedState(sv, C)) {
+ if (IsAggressive) {
+ setNonLocalizedState(sv, C);
+ } else {
+ const SymbolicRegion *SymReg =
+ dyn_cast_or_null<SymbolicRegion>(sv.getAsRegion());
+ if (!SymReg)
+ setNonLocalizedState(sv, C);
+ }
+ }
+}
+
+/// Marks a string being returned by an ObjC method as localized
+/// if it is in LocStringMethods or the method is annotated
+void NonLocalizedStringChecker::checkPostObjCMessage(const ObjCMethodCall &msg,
+ CheckerContext &C) const {
+ initLocStringsMethods(C.getASTContext());
+
+ if (!msg.isInstanceMessage())
+ return;
+
+ const ObjCInterfaceDecl *OD = msg.getReceiverInterface();
+ if (!OD)
+ return;
+ const IdentifierInfo *odInfo = OD->getIdentifier();
+
+ Selector S = msg.getSelector();
+ std::string SelectorName = S.getAsString();
+
+ std::pair<const IdentifierInfo *, Selector> MethodDescription = {odInfo, S};
+
+ if (LSM.count(MethodDescription) || isAnnotatedAsLocalized(msg.getDecl())) {
+ SVal sv = msg.getReturnValue();
+ setLocalizedState(sv, C);
+ }
+}
+
+/// Marks all empty string literals as localized
+void NonLocalizedStringChecker::checkPostStmt(const ObjCStringLiteral *SL,
+ CheckerContext &C) const {
+ SVal sv = C.getSVal(SL);
+ setNonLocalizedState(sv, C);
+}
+
+namespace {
+class EmptyLocalizationContextChecker
+ : public Checker<check::ASTDecl<ObjCImplementationDecl>> {
+
+ // A helper class, which walks the AST
+ class MethodCrawler : public ConstStmtVisitor<MethodCrawler> {
+ const ObjCMethodDecl *MD;
+ BugReporter &BR;
+ AnalysisManager &Mgr;
+ const CheckerBase *Checker;
+ LocationOrAnalysisDeclContext DCtx;
+
+ public:
+ MethodCrawler(const ObjCMethodDecl *InMD, BugReporter &InBR,
+ const CheckerBase *Checker, AnalysisManager &InMgr,
+ AnalysisDeclContext *InDCtx)
+ : MD(InMD), BR(InBR), Mgr(InMgr), Checker(Checker), DCtx(InDCtx) {}
+
+ void VisitStmt(const Stmt *S) { VisitChildren(S); }
+
+ void VisitObjCMessageExpr(const ObjCMessageExpr *ME);
+
+ void reportEmptyContextError(const ObjCMessageExpr *M) const;
+
+ void VisitChildren(const Stmt *S) {
+ for (const Stmt *Child : S->children()) {
+ if (Child)
+ this->Visit(Child);
+ }
+ }
+ };
+
+public:
+ void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager &Mgr,
+ BugReporter &BR) const;
+};
+} // end anonymous namespace
+
+void EmptyLocalizationContextChecker::checkASTDecl(
+ const ObjCImplementationDecl *D, AnalysisManager &Mgr,
+ BugReporter &BR) const {
+
+ for (const ObjCMethodDecl *M : D->methods()) {
+ AnalysisDeclContext *DCtx = Mgr.getAnalysisDeclContext(M);
+
+ const Stmt *Body = M->getBody();
+ assert(Body);
+
+ MethodCrawler MC(M->getCanonicalDecl(), BR, this, Mgr, DCtx);
+ MC.VisitStmt(Body);
+ }
+}
+
+/// This check attempts to match these macros, assuming they are defined as
+/// follows:
+///
+/// #define NSLocalizedString(key, comment) \
+/// [[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]
+/// #define NSLocalizedStringFromTable(key, tbl, comment) \
+/// [[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:(tbl)]
+/// #define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \
+/// [bundle localizedStringForKey:(key) value:@"" table:(tbl)]
+/// #define NSLocalizedStringWithDefaultValue(key, tbl, bundle, val, comment)
+///
+/// We cannot use the path sensitive check because the macro argument we are
+/// checking for (comment) is not used and thus not present in the AST,
+/// so we use Lexer on the original macro call and retrieve the value of
+/// the comment. If it's empty or nil, we raise a warning.
+void EmptyLocalizationContextChecker::MethodCrawler::VisitObjCMessageExpr(
+ const ObjCMessageExpr *ME) {
+
+ const ObjCInterfaceDecl *OD = ME->getReceiverInterface();
+ if (!OD)
+ return;
+
+ const IdentifierInfo *odInfo = OD->getIdentifier();
+
+ if (!(odInfo->isStr("NSBundle") &&
+ ME->getSelector().getAsString() ==
+ "localizedStringForKey:value:table:")) {
+ return;
+ }
+
+ SourceRange R = ME->getSourceRange();
+ if (!R.getBegin().isMacroID())
+ return;
+
+ // getImmediateMacroCallerLoc gets the location of the immediate macro
+ // caller, one level up the stack toward the initial macro typed into the
+ // source, so SL should point to the NSLocalizedString macro.
+ SourceLocation SL =
+ Mgr.getSourceManager().getImmediateMacroCallerLoc(R.getBegin());
+ std::pair<FileID, unsigned> SLInfo =
+ Mgr.getSourceManager().getDecomposedLoc(SL);
+
+ SrcMgr::SLocEntry SE = Mgr.getSourceManager().getSLocEntry(SLInfo.first);
+
+ // If NSLocalizedString macro is wrapped in another macro, we need to
+ // unwrap the expansion until we get to the NSLocalizedStringMacro.
+ while (SE.isExpansion()) {
+ SL = SE.getExpansion().getSpellingLoc();
+ SLInfo = Mgr.getSourceManager().getDecomposedLoc(SL);
+ SE = Mgr.getSourceManager().getSLocEntry(SLInfo.first);
+ }
+
+ llvm::MemoryBuffer *BF = SE.getFile().getContentCache()->getRawBuffer();
+ Lexer TheLexer(SL, LangOptions(), BF->getBufferStart(),
+ BF->getBufferStart() + SLInfo.second, BF->getBufferEnd());
+
+ Token I;
+ Token Result; // This will hold the token just before the last ')'
+ int p_count = 0; // This is for parenthesis matching
+ while (!TheLexer.LexFromRawLexer(I)) {
+ if (I.getKind() == tok::l_paren)
+ ++p_count;
+ if (I.getKind() == tok::r_paren) {
+ if (p_count == 1)
+ break;
+ --p_count;
+ }
+ Result = I;
+ }
+
+ if (isAnyIdentifier(Result.getKind())) {
+ if (Result.getRawIdentifier().equals("nil")) {
+ reportEmptyContextError(ME);
+ return;
+ }
+ }
+
+ if (!isStringLiteral(Result.getKind()))
+ return;
+
+ StringRef Comment =
+ StringRef(Result.getLiteralData(), Result.getLength()).trim("\"");
+
+ if ((Comment.trim().size() == 0 && Comment.size() > 0) || // Is Whitespace
+ Comment.empty()) {
+ reportEmptyContextError(ME);
+ }
+}
+
+void EmptyLocalizationContextChecker::MethodCrawler::reportEmptyContextError(
+ const ObjCMessageExpr *ME) const {
+ // Generate the bug report.
+ BR.EmitBasicReport(MD, Checker, "Context Missing",
+ "Localizability Issue (Apple)",
+ "Localized string macro should include a non-empty "
+ "comment for translators",
+ PathDiagnosticLocation(ME, BR.getSourceManager(), DCtx));
+}
+
+namespace {
+class PluralMisuseChecker : public Checker<check::ASTCodeBody> {
+
+ // A helper class, which walks the AST
+ class MethodCrawler : public RecursiveASTVisitor<MethodCrawler> {
+ BugReporter &BR;
+ const CheckerBase *Checker;
+ AnalysisDeclContext *AC;
+
+ // This functions like a stack. We push on any IfStmt or
+ // ConditionalOperator that matches the condition
+ // and pop it off when we leave that statement
+ llvm::SmallVector<const clang::Stmt *, 8> MatchingStatements;
+ // This is true when we are the direct-child of a
+ // matching statement
+ bool InMatchingStatement = false;
+
+ public:
+ explicit MethodCrawler(BugReporter &InBR, const CheckerBase *Checker,
+ AnalysisDeclContext *InAC)
+ : BR(InBR), Checker(Checker), AC(InAC) {}
+
+ bool VisitIfStmt(const IfStmt *I);
+ bool EndVisitIfStmt(IfStmt *I);
+ bool TraverseIfStmt(IfStmt *x);
+ bool VisitConditionalOperator(const ConditionalOperator *C);
+ bool TraverseConditionalOperator(ConditionalOperator *C);
+ bool VisitCallExpr(const CallExpr *CE);
+ bool VisitObjCMessageExpr(const ObjCMessageExpr *ME);
+
+ private:
+ void reportPluralMisuseError(const Stmt *S) const;
+ bool isCheckingPlurality(const Expr *E) const;
+ };
+
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
+ BugReporter &BR) const {
+ MethodCrawler Visitor(BR, this, Mgr.getAnalysisDeclContext(D));
+ Visitor.TraverseDecl(const_cast<Decl *>(D));
+ }
+};
+} // end anonymous namespace
+
+// Checks the condition of the IfStmt and returns true if one
+// of the following heuristics are met:
+// 1) The conidtion is a variable with "singular" or "plural" in the name
+// 2) The condition is a binary operator with 1 or 2 on the right-hand side
+bool PluralMisuseChecker::MethodCrawler::isCheckingPlurality(
+ const Expr *Condition) const {
+ const BinaryOperator *BO = nullptr;
+ // Accounts for when a VarDecl represents a BinaryOperator
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Condition)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ const Expr *InitExpr = VD->getInit();
+ if (InitExpr) {
+ if (const BinaryOperator *B =
+ dyn_cast<BinaryOperator>(InitExpr->IgnoreParenImpCasts())) {
+ BO = B;
+ }
+ }
+ if (VD->getName().lower().find("plural") != StringRef::npos ||
+ VD->getName().lower().find("singular") != StringRef::npos) {
+ return true;
+ }
+ }
+ } else if (const BinaryOperator *B = dyn_cast<BinaryOperator>(Condition)) {
+ BO = B;
+ }
+
+ if (BO == nullptr)
+ return false;
+
+ if (IntegerLiteral *IL = dyn_cast_or_null<IntegerLiteral>(
+ BO->getRHS()->IgnoreParenImpCasts())) {
+ llvm::APInt Value = IL->getValue();
+ if (Value == 1 || Value == 2) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// A CallExpr with "LOC" in its identifier that takes in a string literal
+// has been shown to almost always be a function that returns a localized
+// string. Raise a diagnostic when this is in a statement that matches
+// the condition.
+bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(const CallExpr *CE) {
+ if (InMatchingStatement) {
+ if (const FunctionDecl *FD = CE->getDirectCallee()) {
+ std::string NormalizedName =
+ StringRef(FD->getNameInfo().getAsString()).lower();
+ if (NormalizedName.find("loc") != std::string::npos) {
+ for (const Expr *Arg : CE->arguments()) {
+ if (isa<ObjCStringLiteral>(Arg))
+ reportPluralMisuseError(CE);
+ }
+ }
+ }
+ }
+ return true;
+}
+
+// The other case is for NSLocalizedString which also returns
+// a localized string. It's a macro for the ObjCMessageExpr
+// [NSBundle localizedStringForKey:value:table:] Raise a
+// diagnostic when this is in a statement that matches
+// the condition.
+bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr(
+ const ObjCMessageExpr *ME) {
+ const ObjCInterfaceDecl *OD = ME->getReceiverInterface();
+ if (!OD)
+ return true;
+
+ const IdentifierInfo *odInfo = OD->getIdentifier();
+
+ if (odInfo->isStr("NSBundle") &&
+ ME->getSelector().getAsString() == "localizedStringForKey:value:table:") {
+ if (InMatchingStatement) {
+ reportPluralMisuseError(ME);
+ }
+ }
+ return true;
+}
+
+/// Override TraverseIfStmt so we know when we are done traversing an IfStmt
+bool PluralMisuseChecker::MethodCrawler::TraverseIfStmt(IfStmt *I) {
+ RecursiveASTVisitor<MethodCrawler>::TraverseIfStmt(I);
+ return EndVisitIfStmt(I);
+}
+
+// EndVisit callbacks are not provided by the RecursiveASTVisitor
+// so we override TraverseIfStmt and make a call to EndVisitIfStmt
+// after traversing the IfStmt
+bool PluralMisuseChecker::MethodCrawler::EndVisitIfStmt(IfStmt *I) {
+ MatchingStatements.pop_back();
+ if (!MatchingStatements.empty()) {
+ if (MatchingStatements.back() != nullptr) {
+ InMatchingStatement = true;
+ return true;
+ }
+ }
+ InMatchingStatement = false;
+ return true;
+}
+
+bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(const IfStmt *I) {
+ const Expr *Condition = I->getCond()->IgnoreParenImpCasts();
+ if (isCheckingPlurality(Condition)) {
+ MatchingStatements.push_back(I);
+ InMatchingStatement = true;
+ } else {
+ MatchingStatements.push_back(nullptr);
+ InMatchingStatement = false;
+ }
+
+ return true;
+}
+
+// Preliminary support for conditional operators.
+bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator(
+ ConditionalOperator *C) {
+ RecursiveASTVisitor<MethodCrawler>::TraverseConditionalOperator(C);
+ MatchingStatements.pop_back();
+ if (!MatchingStatements.empty()) {
+ if (MatchingStatements.back() != nullptr)
+ InMatchingStatement = true;
+ else
+ InMatchingStatement = false;
+ } else {
+ InMatchingStatement = false;
+ }
+ return true;
+}
+
+bool PluralMisuseChecker::MethodCrawler::VisitConditionalOperator(
+ const ConditionalOperator *C) {
+ const Expr *Condition = C->getCond()->IgnoreParenImpCasts();
+ if (isCheckingPlurality(Condition)) {
+ MatchingStatements.push_back(C);
+ InMatchingStatement = true;
+ } else {
+ MatchingStatements.push_back(nullptr);
+ InMatchingStatement = false;
+ }
+ return true;
+}
+
+void PluralMisuseChecker::MethodCrawler::reportPluralMisuseError(
+ const Stmt *S) const {
+ // Generate the bug report.
+ BR.EmitBasicReport(AC->getDecl(), Checker, "Plural Misuse",
+ "Localizability Issue (Apple)",
+ "Plural cases are not supported accross all languages. "
+ "Use a .stringsdict file instead",
+ PathDiagnosticLocation(S, BR.getSourceManager(), AC));
+}
+
+//===----------------------------------------------------------------------===//
+// Checker registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerNonLocalizedStringChecker(CheckerManager &mgr) {
+ NonLocalizedStringChecker *checker =
+ mgr.registerChecker<NonLocalizedStringChecker>();
+ checker->IsAggressive =
+ mgr.getAnalyzerOptions().getBooleanOption("AggressiveReport", false);
+}
+
+void ento::registerEmptyLocalizationContextChecker(CheckerManager &mgr) {
+ mgr.registerChecker<EmptyLocalizationContextChecker>();
+}
+
+void ento::registerPluralMisuseChecker(CheckerManager &mgr) {
+ mgr.registerChecker<PluralMisuseChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
index 7838901..1e56d70 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -118,7 +118,7 @@ private:
SValBuilder &Builder) const {
return definitelyReturnedError(RetSym, State, Builder, true);
}
-
+
/// Mark an AllocationPair interesting for diagnostic reporting.
void markInteresting(BugReport *R, const AllocationPair &AP) const {
R->markInteresting(AP.first);
@@ -136,7 +136,6 @@ private:
public:
SecKeychainBugVisitor(SymbolRef S) : Sym(S) {}
- ~SecKeychainBugVisitor() override {}
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int X = 0;
@@ -202,12 +201,8 @@ unsigned MacOSKeychainAPIChecker::getTrackedFunctionIndex(StringRef Name,
static bool isBadDeallocationArgument(const MemRegion *Arg) {
if (!Arg)
return false;
- if (isa<AllocaRegion>(Arg) ||
- isa<BlockDataRegion>(Arg) ||
- isa<TypedRegion>(Arg)) {
- return true;
- }
- return false;
+ return isa<AllocaRegion>(Arg) || isa<BlockDataRegion>(Arg) ||
+ isa<TypedRegion>(Arg);
}
/// Given the address expression, retrieve the value it's pointing to. Assume
@@ -241,11 +236,7 @@ bool MacOSKeychainAPIChecker::definitelyReturnedError(SymbolRef RetSym,
DefinedOrUnknownSVal NoErr = Builder.evalEQ(State, NoErrVal,
nonloc::SymbolVal(RetSym));
ProgramStateRef ErrState = State->assume(NoErr, noError);
- if (ErrState == State) {
- return true;
- }
-
- return false;
+ return ErrState == State;
}
// Report deallocator mismatch. Remove the region from tracking - reporting a
@@ -256,7 +247,7 @@ void MacOSKeychainAPIChecker::
CheckerContext &C) const {
ProgramStateRef State = C.getState();
State = State->remove<AllocatedData>(AP.first);
- ExplodedNode *N = C.addTransition(State);
+ ExplodedNode *N = C.generateNonFatalErrorNode(State);
if (!N)
return;
@@ -283,7 +274,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
const FunctionDecl *FD = C.getCalleeDecl(CE);
if (!FD || FD->getKind() != Decl::Function)
return;
-
+
StringRef funName = C.getCalleeName(FD);
if (funName.empty())
return;
@@ -302,7 +293,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
// Remove the value from the state. The new symbol will be added for
// tracking when the second allocator is processed in checkPostStmt().
State = State->remove<AllocatedData>(V);
- ExplodedNode *N = C.addTransition(State);
+ ExplodedNode *N = C.generateNonFatalErrorNode(State);
if (!N)
return;
initBugType();
@@ -365,7 +356,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
if (isEnclosingFunctionParam(ArgExpr))
return;
- ExplodedNode *N = C.addTransition(State);
+ ExplodedNode *N = C.generateNonFatalErrorNode(State);
if (!N)
return;
initBugType();
@@ -431,7 +422,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
// report a bad call to free.
if (State->assume(ArgSVal.castAs<DefinedSVal>(), false) &&
!definitelyDidnotReturnError(AS->Region, State, C.getSValBuilder())) {
- ExplodedNode *N = C.addTransition(State);
+ ExplodedNode *N = C.generateNonFatalErrorNode(State);
if (!N)
return;
initBugType();
@@ -585,10 +576,12 @@ void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR,
}
static CheckerProgramPointTag Tag(this, "DeadSymbolsLeak");
- ExplodedNode *N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
+ ExplodedNode *N = C.generateNonFatalErrorNode(C.getState(), &Tag);
+ if (!N)
+ return;
// Generate the error reports.
- for (const auto P : Errors)
+ for (const auto &P : Errors)
C.emitReport(generateAllocatedDataNotReleasedReport(P, N, C));
// Generate the new, cleaned up state.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
index 11ba609..4cbe97b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
@@ -62,7 +62,7 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
return;
- ExplodedNode *N = C.generateSink(state);
+ ExplodedNode *N = C.generateErrorNode(state);
if (!N)
return;
@@ -79,7 +79,7 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
if (TrimmedFName != FName)
FName = TrimmedFName;
}
-
+
SmallString<256> S;
llvm::raw_svector_ostream os(S);
os << "Call to '" << FName << "' uses";
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index a9e0865..fee030f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -65,10 +65,10 @@ class RefState {
const Stmt *S;
unsigned K : 3; // Kind enum, but stored as a bitfield.
- unsigned Family : 29; // Rest of 32-bit word, currently just an allocation
+ unsigned Family : 29; // Rest of 32-bit word, currently just an allocation
// family.
- RefState(Kind k, const Stmt *s, unsigned family)
+ RefState(Kind k, const Stmt *s, unsigned family)
: S(s), K(k), Family(family) {
assert(family != AF_None);
}
@@ -94,7 +94,7 @@ public:
return RefState(AllocatedOfSizeZero, RS->getStmt(),
RS->getAllocationFamily());
}
- static RefState getReleased(unsigned family, const Stmt *s) {
+ static RefState getReleased(unsigned family, const Stmt *s) {
return RefState(Released, s, family);
}
static RefState getRelinquished(unsigned family, const Stmt *s) {
@@ -169,9 +169,9 @@ class MallocChecker : public Checker<check::DeadSymbols,
{
public:
MallocChecker()
- : II_alloca(nullptr), II_malloc(nullptr), II_free(nullptr),
+ : II_alloca(nullptr), II_malloc(nullptr), II_free(nullptr),
II_realloc(nullptr), II_calloc(nullptr), II_valloc(nullptr),
- II_reallocf(nullptr), II_strndup(nullptr), II_strdup(nullptr),
+ II_reallocf(nullptr), II_strndup(nullptr), II_strdup(nullptr),
II_kmalloc(nullptr), II_if_nameindex(nullptr),
II_if_freenameindex(nullptr) {}
@@ -185,7 +185,7 @@ public:
CK_NumCheckKinds
};
- enum class MemoryOperationKind {
+ enum class MemoryOperationKind {
MOK_Allocate,
MOK_Free,
MOK_Any
@@ -245,19 +245,19 @@ private:
/// \brief Print names of allocators and deallocators.
///
/// \returns true on success.
- bool printAllocDeallocName(raw_ostream &os, CheckerContext &C,
+ bool printAllocDeallocName(raw_ostream &os, CheckerContext &C,
const Expr *E) const;
/// \brief Print expected name of an allocator based on the deallocator's
/// family derived from the DeallocExpr.
- void printExpectedAllocName(raw_ostream &os, CheckerContext &C,
+ void printExpectedAllocName(raw_ostream &os, CheckerContext &C,
const Expr *DeallocExpr) const;
- /// \brief Print expected name of a deallocator based on the allocator's
+ /// \brief Print expected name of a deallocator based on the allocator's
/// family.
void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family) const;
///@{
- /// Check if this is one of the functions which can allocate/reallocate memory
+ /// Check if this is one of the functions which can allocate/reallocate memory
/// pointed to by one of its arguments.
bool isMemFunction(const FunctionDecl *FD, ASTContext &C) const;
bool isCMemFunction(const FunctionDecl *FD,
@@ -292,7 +292,7 @@ private:
const ProgramStateRef &State) const;
/// Update the RefState to reflect the new memory allocation.
- static ProgramStateRef
+ static ProgramStateRef
MallocUpdateRefState(CheckerContext &C, const Expr *E, ProgramStateRef State,
AllocationFamily Family = AF_Malloc);
@@ -312,17 +312,17 @@ private:
bool ReturnsNullOnFailure = false) const;
ProgramStateRef ReallocMem(CheckerContext &C, const CallExpr *CE,
- bool FreesMemOnFailure,
+ bool FreesMemOnFailure,
ProgramStateRef State) const;
static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE,
ProgramStateRef State);
-
+
///\brief Check if the memory associated with this symbol was released.
bool isReleased(SymbolRef Sym, CheckerContext &C) const;
bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const;
- void checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C,
+ void checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C,
const Stmt *S) const;
bool checkDoubleDelete(SymbolRef Sym, CheckerContext &C) const;
@@ -330,7 +330,7 @@ private:
/// Check if the function is known free memory, or if it is
/// "interesting" and should be modeled explicitly.
///
- /// \param [out] EscapingSymbol A function might not free memory in general,
+ /// \param [out] EscapingSymbol A function might not free memory in general,
/// but could be known to free a particular symbol. In this case, false is
/// returned and the single escaping symbol is returned through the out
/// parameter.
@@ -357,20 +357,20 @@ private:
Optional<CheckKind> getCheckIfTracked(CheckerContext &C,
const Stmt *AllocDeallocStmt,
bool IsALeakCheck = false) const;
- Optional<CheckKind> getCheckIfTracked(CheckerContext &C, SymbolRef Sym,
+ Optional<CheckKind> getCheckIfTracked(CheckerContext &C, SymbolRef Sym,
bool IsALeakCheck = false) const;
///@}
static bool SummarizeValue(raw_ostream &os, SVal V);
static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);
- void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
+ void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
const Expr *DeallocExpr) const;
void ReportFreeAlloca(CheckerContext &C, SVal ArgVal,
SourceRange Range) const;
void ReportMismatchedDealloc(CheckerContext &C, SourceRange Range,
const Expr *DeallocExpr, const RefState *RS,
SymbolRef Sym, bool OwnershipTransferred) const;
- void ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
- const Expr *DeallocExpr,
+ void ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
+ const Expr *DeallocExpr,
const Expr *AllocExpr = nullptr) const;
void ReportUseAfterFree(CheckerContext &C, SourceRange Range,
SymbolRef Sym) const;
@@ -392,7 +392,8 @@ private:
/// The bug visitor which allows us to print extra diagnostics along the
/// BugReport path. For example, showing the allocation site of the leaked
/// region.
- class MallocBugVisitor : public BugReporterVisitorImpl<MallocBugVisitor> {
+ class MallocBugVisitor final
+ : public BugReporterVisitorImpl<MallocBugVisitor> {
protected:
enum NotificationMode {
Normal,
@@ -414,8 +415,6 @@ private:
MallocBugVisitor(SymbolRef S, bool isLeak = false)
: Sym(S), Mode(Normal), FailedReallocSymbol(nullptr), IsLeak(isLeak) {}
- ~MallocBugVisitor() override {}
-
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int X = 0;
ID.AddPointer(&X);
@@ -426,8 +425,8 @@ private:
const Stmt *Stmt) {
// Did not track -> allocated. Other state (released) -> allocated.
return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXNewExpr>(Stmt)) &&
- (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
- (!SPrev || !(SPrev->isAllocated() ||
+ (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
+ (!SPrev || !(SPrev->isAllocated() ||
SPrev->isAllocatedOfSizeZero())));
}
@@ -509,13 +508,14 @@ private:
REGISTER_MAP_WITH_PROGRAMSTATE(RegionState, SymbolRef, RefState)
REGISTER_MAP_WITH_PROGRAMSTATE(ReallocPairs, SymbolRef, ReallocPair)
+REGISTER_SET_WITH_PROGRAMSTATE(ReallocSizeZeroSymbols, SymbolRef)
-// A map from the freed symbol to the symbol representing the return value of
+// A map from the freed symbol to the symbol representing the return value of
// the free function.
REGISTER_MAP_WITH_PROGRAMSTATE(FreeReturnValue, SymbolRef, SymbolRef)
namespace {
-class StopTrackingCallback : public SymbolVisitor {
+class StopTrackingCallback final : public SymbolVisitor {
ProgramStateRef state;
public:
StopTrackingCallback(ProgramStateRef st) : state(st) {}
@@ -634,7 +634,7 @@ bool MallocChecker::isStandardNewDelete(const FunctionDecl *FD,
return false;
OverloadedOperatorKind Kind = FD->getOverloadedOperator();
- if (Kind != OO_New && Kind != OO_Array_New &&
+ if (Kind != OO_New && Kind != OO_Array_New &&
Kind != OO_Delete && Kind != OO_Array_Delete)
return false;
@@ -799,8 +799,8 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
State = ProcessZeroAllocation(C, CE, 0, State);
} else if (isStandardNewDelete(FD, C.getASTContext())) {
// Process direct calls to operator new/new[]/delete/delete[] functions
- // as distinct from new/new[]/delete/delete[] expressions that are
- // processed by the checkPostStmt callbacks for CXXNewExpr and
+ // as distinct from new/new[]/delete/delete[] expressions that are
+ // processed by the checkPostStmt callbacks for CXXNewExpr and
// CXXDeleteExpr.
OverloadedOperatorKind K = FD->getOverloadedOperator();
if (K == OO_New) {
@@ -870,7 +870,7 @@ ProgramStateRef MallocChecker::ProcessZeroAllocation(CheckerContext &C,
assert(Arg);
- Optional<DefinedSVal> DefArgVal =
+ Optional<DefinedSVal> DefArgVal =
State->getSVal(Arg, C.getLocationContext()).getAs<DefinedSVal>();
if (!DefArgVal)
@@ -882,7 +882,7 @@ ProgramStateRef MallocChecker::ProcessZeroAllocation(CheckerContext &C,
DefinedSVal Zero =
SvalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
- std::tie(TrueState, FalseState) =
+ std::tie(TrueState, FalseState) =
State->assume(SvalBuilder.evalEQ(State, *DefArgVal, Zero));
if (TrueState && !FalseState) {
@@ -892,15 +892,19 @@ ProgramStateRef MallocChecker::ProcessZeroAllocation(CheckerContext &C,
return State;
const RefState *RS = State->get<RegionState>(Sym);
- if (!RS)
- return State; // TODO: change to assert(RS); after realloc() will
- // guarantee have a RegionState attached.
-
- if (!RS->isAllocated())
- return State;
-
- return TrueState->set<RegionState>(Sym,
- RefState::getAllocatedOfSizeZero(RS));
+ if (RS) {
+ if (RS->isAllocated())
+ return TrueState->set<RegionState>(Sym,
+ RefState::getAllocatedOfSizeZero(RS));
+ else
+ return State;
+ } else {
+ // Case of zero-size realloc. Historically 'realloc(ptr, 0)' is treated as
+ // 'free(ptr)' and the returned value from 'realloc(ptr, 0)' is not
+ // tracked. Add zero-reallocated Sym to the state to catch references
+ // to zero-allocated memory.
+ return TrueState->add<ReallocSizeZeroSymbols>(Sym);
+ }
}
// Assume the value is non-zero going forward.
@@ -944,7 +948,7 @@ static bool treatUnusedNewEscaped(const CXXNewExpr *NE) {
return false;
}
-void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
+void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
CheckerContext &C) const {
if (NE->getNumPlacementArgs())
@@ -961,17 +965,17 @@ void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
return;
ProgramStateRef State = C.getState();
- // The return value from operator new is bound to a specified initialization
- // value (if any) and we don't want to loose this value. So we call
- // MallocUpdateRefState() instead of MallocMemAux() which breakes the
+ // The return value from operator new is bound to a specified initialization
+ // value (if any) and we don't want to loose this value. So we call
+ // MallocUpdateRefState() instead of MallocMemAux() which breakes the
// existing binding.
- State = MallocUpdateRefState(C, NE, State, NE->isArray() ? AF_CXXNewArray
+ State = MallocUpdateRefState(C, NE, State, NE->isArray() ? AF_CXXNewArray
: AF_CXXNew);
State = ProcessZeroAllocation(C, NE, 0, State);
C.addTransition(State);
}
-void MallocChecker::checkPreStmt(const CXXDeleteExpr *DE,
+void MallocChecker::checkPreStmt(const CXXDeleteExpr *DE,
CheckerContext &C) const {
if (!ChecksEnabled[CK_NewDeleteChecker])
@@ -996,12 +1000,9 @@ static bool isKnownDeallocObjCMethodName(const ObjCMethodCall &Call) {
// Ex: [NSData dataWithBytesNoCopy:bytes length:10];
// (...unless a 'freeWhenDone' parameter is false, but that's checked later.)
StringRef FirstSlot = Call.getSelector().getNameForSlot(0);
- if (FirstSlot == "dataWithBytesNoCopy" ||
- FirstSlot == "initWithBytesNoCopy" ||
- FirstSlot == "initWithCharactersNoCopy")
- return true;
-
- return false;
+ return FirstSlot == "dataWithBytesNoCopy" ||
+ FirstSlot == "initWithBytesNoCopy" ||
+ FirstSlot == "initWithCharactersNoCopy";
}
static Optional<bool> getFreeWhenDoneArg(const ObjCMethodCall &Call) {
@@ -1038,7 +1039,7 @@ void MallocChecker::checkPostObjCMessage(const ObjCMethodCall &Call,
ProgramStateRef
MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
- const OwnershipAttr *Att,
+ const OwnershipAttr *Att,
ProgramStateRef State) const {
if (!State)
return nullptr;
@@ -1105,7 +1106,7 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
State = State->assume(extentMatchesSize, true);
assert(State);
}
-
+
return MallocUpdateRefState(C, CE, State, Family);
}
@@ -1132,7 +1133,7 @@ ProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C,
ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
const CallExpr *CE,
- const OwnershipAttr *Att,
+ const OwnershipAttr *Att,
ProgramStateRef State) const {
if (!State)
return nullptr;
@@ -1184,7 +1185,7 @@ static bool didPreviousFreeFail(ProgramStateRef State,
return false;
}
-AllocationFamily MallocChecker::getAllocationFamily(CheckerContext &C,
+AllocationFamily MallocChecker::getAllocationFamily(CheckerContext &C,
const Stmt *S) const {
if (!S)
return AF_None;
@@ -1229,14 +1230,14 @@ AllocationFamily MallocChecker::getAllocationFamily(CheckerContext &C,
return AF_None;
}
-bool MallocChecker::printAllocDeallocName(raw_ostream &os, CheckerContext &C,
+bool MallocChecker::printAllocDeallocName(raw_ostream &os, CheckerContext &C,
const Expr *E) const {
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
// FIXME: This doesn't handle indirect calls.
const FunctionDecl *FD = CE->getDirectCallee();
if (!FD)
return false;
-
+
os << *FD;
if (!FD->isOverloadedOperator())
os << "()";
@@ -1253,14 +1254,14 @@ bool MallocChecker::printAllocDeallocName(raw_ostream &os, CheckerContext &C,
}
if (const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
- os << "'"
+ os << "'"
<< getOperatorSpelling(NE->getOperatorNew()->getOverloadedOperator())
<< "'";
return true;
}
if (const CXXDeleteExpr *DE = dyn_cast<CXXDeleteExpr>(E)) {
- os << "'"
+ os << "'"
<< getOperatorSpelling(DE->getOperatorDelete()->getOverloadedOperator())
<< "'";
return true;
@@ -1283,7 +1284,7 @@ void MallocChecker::printExpectedAllocName(raw_ostream &os, CheckerContext &C,
}
}
-void MallocChecker::printExpectedDeallocName(raw_ostream &os,
+void MallocChecker::printExpectedDeallocName(raw_ostream &os,
AllocationFamily Family) const {
switch(Family) {
case AF_Malloc: os << "free()"; return;
@@ -1327,25 +1328,25 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
return nullptr;
const MemRegion *R = ArgVal.getAsRegion();
-
+
// Nonlocs can't be freed, of course.
// Non-region locations (labels and fixed addresses) also shouldn't be freed.
if (!R) {
ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
return nullptr;
}
-
+
R = R->StripCasts();
-
+
// Blocks might show up as heap data, but should not be free()d
if (isa<BlockDataRegion>(R)) {
ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
return nullptr;
}
-
+
const MemSpaceRegion *MS = R->getMemorySpace();
-
- // Parameters, locals, statics, globals, and memory returned by
+
+ // Parameters, locals, statics, globals, and memory returned by
// __builtin_alloca() shouldn't be freed.
if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
// FIXME: at the time this code was written, malloc() regions were
@@ -1391,7 +1392,7 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
// If the pointer is allocated or escaped, but we are now trying to free it,
// check that the call to free is proper.
- } else if (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero() ||
+ } else if (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero() ||
RsBase->isEscaped()) {
// Check if an expected deallocation function matches the real one.
@@ -1410,20 +1411,20 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
!Offset.hasSymbolicOffset() &&
Offset.getOffset() != 0) {
const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
- ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
+ ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
AllocExpr);
return nullptr;
}
}
}
- ReleasedAllocated = (RsBase != nullptr) && (RsBase->isAllocated() ||
+ ReleasedAllocated = (RsBase != nullptr) && (RsBase->isAllocated() ||
RsBase->isAllocatedOfSizeZero());
// Clean out the info on previous call to free return info.
State = State->remove<FreeReturnValue>(SymBase);
- // Keep track of the return value. If it is NULL, we will know that free
+ // Keep track of the return value. If it is NULL, we will know that free
// failed.
if (ReturnsNullOnFailure) {
SVal RetVal = C.getSVal(ParentExpr);
@@ -1463,7 +1464,7 @@ MallocChecker::getCheckIfTracked(AllocationFamily Family,
if (IsALeakCheck) {
if (ChecksEnabled[CK_NewDeleteLeaksChecker])
return CK_NewDeleteLeaksChecker;
- }
+ }
else {
if (ChecksEnabled[CK_NewDeleteChecker])
return CK_NewDeleteChecker;
@@ -1488,6 +1489,9 @@ MallocChecker::getCheckIfTracked(CheckerContext &C,
Optional<MallocChecker::CheckKind>
MallocChecker::getCheckIfTracked(CheckerContext &C, SymbolRef Sym,
bool IsALeakCheck) const {
+ if (C.getState()->contains<ReallocSizeZeroSymbols>(Sym))
+ return CK_MallocChecker;
+
const RefState *RS = C.getState()->get<RegionState>(Sym);
assert(RS);
return getCheckIfTracked(RS->getAllocationFamily(), IsALeakCheck);
@@ -1502,22 +1506,22 @@ bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
os << "the address of the label '" << Label->getLabel()->getName() << "'";
else
return false;
-
+
return true;
}
bool MallocChecker::SummarizeRegion(raw_ostream &os,
const MemRegion *MR) {
switch (MR->getKind()) {
- case MemRegion::FunctionTextRegionKind: {
- const NamedDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
+ case MemRegion::FunctionCodeRegionKind: {
+ const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
if (FD)
os << "the address of the function '" << *FD << '\'';
else
os << "the address of a function";
return true;
}
- case MemRegion::BlockTextRegionKind:
+ case MemRegion::BlockCodeRegionKind:
os << "block text";
return true;
case MemRegion::BlockDataRegionKind:
@@ -1526,7 +1530,7 @@ bool MallocChecker::SummarizeRegion(raw_ostream &os,
return true;
default: {
const MemSpaceRegion *MS = MR->getMemorySpace();
-
+
if (isa<StackLocalsSpaceRegion>(MS)) {
const VarRegion *VR = dyn_cast<VarRegion>(MR);
const VarDecl *VD;
@@ -1580,8 +1584,8 @@ bool MallocChecker::SummarizeRegion(raw_ostream &os,
}
}
-void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
- SourceRange Range,
+void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
+ SourceRange Range,
const Expr *DeallocExpr) const {
if (!ChecksEnabled[CK_MallocChecker] &&
@@ -1593,7 +1597,7 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
if (!CheckKind.hasValue())
return;
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
if (!BT_BadFree[*CheckKind])
BT_BadFree[*CheckKind].reset(
new BugType(CheckNames[*CheckKind], "Bad free", "Memory Error"));
@@ -1610,7 +1614,7 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
os << "deallocator";
os << " is ";
- bool Summarized = MR ? SummarizeRegion(os, MR)
+ bool Summarized = MR ? SummarizeRegion(os, MR)
: SummarizeValue(os, ArgVal);
if (Summarized)
os << ", which is not memory allocated by ";
@@ -1626,7 +1630,7 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
}
}
-void MallocChecker::ReportFreeAlloca(CheckerContext &C, SVal ArgVal,
+void MallocChecker::ReportFreeAlloca(CheckerContext &C, SVal ArgVal,
SourceRange Range) const {
Optional<MallocChecker::CheckKind> CheckKind;
@@ -1638,7 +1642,7 @@ void MallocChecker::ReportFreeAlloca(CheckerContext &C, SVal ArgVal,
else
return;
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
if (!BT_FreeAlloca[*CheckKind])
BT_FreeAlloca[*CheckKind].reset(
new BugType(CheckNames[*CheckKind], "Free alloca()", "Memory Error"));
@@ -1652,17 +1656,17 @@ void MallocChecker::ReportFreeAlloca(CheckerContext &C, SVal ArgVal,
}
}
-void MallocChecker::ReportMismatchedDealloc(CheckerContext &C,
+void MallocChecker::ReportMismatchedDealloc(CheckerContext &C,
SourceRange Range,
- const Expr *DeallocExpr,
+ const Expr *DeallocExpr,
const RefState *RS,
- SymbolRef Sym,
+ SymbolRef Sym,
bool OwnershipTransferred) const {
if (!ChecksEnabled[CK_MismatchedDeallocatorChecker])
return;
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
if (!BT_MismatchedDealloc)
BT_MismatchedDealloc.reset(
new BugType(CheckNames[CK_MismatchedDeallocatorChecker],
@@ -1680,7 +1684,7 @@ void MallocChecker::ReportMismatchedDealloc(CheckerContext &C,
if (OwnershipTransferred) {
if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
os << DeallocOs.str() << " cannot";
- else
+ else
os << "Cannot";
os << " take ownership of memory";
@@ -1721,7 +1725,7 @@ void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal,
if (!CheckKind.hasValue())
return;
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
@@ -1775,7 +1779,7 @@ void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range,
if (!CheckKind.hasValue())
return;
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
if (!BT_UseFree[*CheckKind])
BT_UseFree[*CheckKind].reset(new BugType(
CheckNames[*CheckKind], "Use-after-free", "Memory Error"));
@@ -1791,7 +1795,7 @@ void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range,
}
void MallocChecker::ReportDoubleFree(CheckerContext &C, SourceRange Range,
- bool Released, SymbolRef Sym,
+ bool Released, SymbolRef Sym,
SymbolRef PrevSym) const {
if (!ChecksEnabled[CK_MallocChecker] &&
@@ -1802,7 +1806,7 @@ void MallocChecker::ReportDoubleFree(CheckerContext &C, SourceRange Range,
if (!CheckKind.hasValue())
return;
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
if (!BT_DoubleFree[*CheckKind])
BT_DoubleFree[*CheckKind].reset(
new BugType(CheckNames[*CheckKind], "Double free", "Memory Error"));
@@ -1830,7 +1834,7 @@ void MallocChecker::ReportDoubleDelete(CheckerContext &C, SymbolRef Sym) const {
if (!CheckKind.hasValue())
return;
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
if (!BT_DoubleDelete)
BT_DoubleDelete.reset(new BugType(CheckNames[CK_NewDeleteChecker],
"Double delete", "Memory Error"));
@@ -1857,7 +1861,7 @@ void MallocChecker::ReportUseZeroAllocated(CheckerContext &C,
if (!CheckKind.hasValue())
return;
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
if (!BT_UseZerroAllocated[*CheckKind])
BT_UseZerroAllocated[*CheckKind].reset(new BugType(
CheckNames[*CheckKind], "Use of zero allocated", "Memory Error"));
@@ -1921,7 +1925,7 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
- // If the ptr is NULL and the size is not 0, the call is equivalent to
+ // If the ptr is NULL and the size is not 0, the call is equivalent to
// malloc(size).
if ( PrtIsNull && !SizeIsZero) {
ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1),
@@ -1930,7 +1934,7 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
}
if (PrtIsNull && SizeIsZero)
- return nullptr;
+ return State;
// Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
assert(!PrtIsNull);
@@ -1979,7 +1983,7 @@ ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
return nullptr;
}
-ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE,
+ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE,
ProgramStateRef State) {
if (!State)
return nullptr;
@@ -1992,7 +1996,7 @@ ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE,
SVal count = State->getSVal(CE->getArg(0), LCtx);
SVal elementSize = State->getSVal(CE->getArg(1), LCtx);
SVal TotalSize = svalBuilder.evalBinOp(State, BO_Mul, count, elementSize,
- svalBuilder.getContext().getSizeType());
+ svalBuilder.getContext().getSizeType());
SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
return MallocMemAux(C, CE, TotalSize, zeroVal, State);
@@ -2079,7 +2083,7 @@ void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
const ExplodedNode *AllocNode = nullptr;
const MemRegion *Region = nullptr;
std::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
-
+
ProgramPoint P = AllocNode->getLocation();
const Stmt *AllocationStmt = nullptr;
if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
@@ -2128,7 +2132,7 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
}
}
-
+
// Cleanup the Realloc Pairs Map.
ReallocPairsTy RP = state->get<ReallocPairs>();
for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
@@ -2151,10 +2155,12 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
ExplodedNode *N = C.getPredecessor();
if (!Errors.empty()) {
static CheckerProgramPointTag Tag("MallocChecker", "DeadSymbolsLeak");
- N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
- for (SmallVectorImpl<SymbolRef>::iterator
+ N = C.generateNonFatalErrorNode(C.getState(), &Tag);
+ if (N) {
+ for (SmallVectorImpl<SymbolRef>::iterator
I = Errors.begin(), E = Errors.end(); I != E; ++I) {
- reportLeak(*I, N, C);
+ reportLeak(*I, N, C);
+ }
}
}
@@ -2233,7 +2239,7 @@ void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
}
// TODO: Blocks should be either inlined or should call invalidate regions
-// upon invocation. After that's in place, special casing here will not be
+// upon invocation. After that's in place, special casing here will not be
// needed.
void MallocChecker::checkPostStmt(const BlockExpr *BE,
CheckerContext &C) const {
@@ -2292,10 +2298,14 @@ bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
void MallocChecker::checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C,
const Stmt *S) const {
assert(Sym);
- const RefState *RS = C.getState()->get<RegionState>(Sym);
- if (RS && RS->isAllocatedOfSizeZero())
- ReportUseZeroAllocated(C, RS->getStmt()->getSourceRange(), Sym);
+ if (const RefState *RS = C.getState()->get<RegionState>(Sym)) {
+ if (RS->isAllocatedOfSizeZero())
+ ReportUseZeroAllocated(C, RS->getStmt()->getSourceRange(), Sym);
+ }
+ else if (C.getState()->contains<ReallocSizeZeroSymbols>(Sym)) {
+ ReportUseZeroAllocated(C, S->getSourceRange(), Sym);
+ }
}
bool MallocChecker::checkDoubleDelete(SymbolRef Sym, CheckerContext &C) const {
@@ -2377,7 +2387,7 @@ bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
// If it's not a framework call, or if it takes a callback, assume it
// can free memory.
- if (!Call->isInSystemHeader() || Call->hasNonZeroCallbackArg())
+ if (!Call->isInSystemHeader() || Call->argumentsMayEscape())
return true;
// If it's a method we know about, handle it explicitly post-call.
@@ -2447,7 +2457,7 @@ bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
StringRef FName = II->getName();
// White list the 'XXXNoCopy' CoreFoundation functions.
- // We specifically check these before
+ // We specifically check these before
if (FName.endswith("NoCopy")) {
// Look for the deallocator argument. We know that the memory ownership
// is not transferred only if the deallocator argument is
@@ -2498,6 +2508,16 @@ bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
return true;
}
+ if (FName == "postEvent" &&
+ FD->getQualifiedNameAsString() == "QCoreApplication::postEvent") {
+ return true;
+ }
+
+ if (FName == "postEvent" &&
+ FD->getQualifiedNameAsString() == "QCoreApplication::postEvent") {
+ return true;
+ }
+
// Handle cases where we know a buffer's /address/ can escape.
// Note that the above checks handle some special cases where we know that
// even though the address escapes, it's still our responsibility to free the
@@ -2556,7 +2576,7 @@ ProgramStateRef MallocChecker::checkPointerEscapeAux(ProgramStateRef State,
if (EscapingSymbol && EscapingSymbol != sym)
continue;
-
+
if (const RefState *RS = State->get<RegionState>(sym)) {
if ((RS->isAllocated() || RS->isAllocatedOfSizeZero()) &&
CheckRefState(RS)) {
@@ -2703,7 +2723,7 @@ void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] = true;
checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] =
mgr.getCurrentCheckName();
- // We currently treat NewDeleteLeaks checker as a subchecker of NewDelete
+ // We currently treat NewDeleteLeaks checker as a subchecker of NewDelete
// checker.
if (!checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker])
checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker] = true;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
index e913479..99ba90d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp
@@ -23,19 +23,22 @@
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
using namespace clang;
using namespace ento;
+using llvm::APInt;
+using llvm::APSInt;
namespace {
struct MallocOverflowCheck {
const BinaryOperator *mulop;
const Expr *variable;
+ APSInt maxVal;
- MallocOverflowCheck (const BinaryOperator *m, const Expr *v)
- : mulop(m), variable (v)
- {}
+ MallocOverflowCheck(const BinaryOperator *m, const Expr *v, APSInt val)
+ : mulop(m), variable(v), maxVal(val) {}
};
class MallocOverflowSecurityChecker : public Checker<check::ASTCodeBody> {
@@ -54,6 +57,11 @@ public:
};
} // end anonymous namespace
+// Return true for computations which evaluate to zero: e.g., mult by 0.
+static inline bool EvaluatesToZero(APSInt &Val, BinaryOperatorKind op) {
+ return (op == BO_Mul) && (Val == 0);
+}
+
void MallocOverflowSecurityChecker::CheckMallocArgument(
SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows,
const Expr *TheArgument,
@@ -64,13 +72,14 @@ void MallocOverflowSecurityChecker::CheckMallocArgument(
Reject anything that applies to the variable: an explicit cast,
conditional expression, an operation that could reduce the range
of the result, or anything too complicated :-). */
- const Expr * e = TheArgument;
+ const Expr *e = TheArgument;
const BinaryOperator * mulop = nullptr;
+ APSInt maxVal;
for (;;) {
+ maxVal = 0;
e = e->IgnoreParenImpCasts();
- if (isa<BinaryOperator>(e)) {
- const BinaryOperator * binop = dyn_cast<BinaryOperator>(e);
+ if (const BinaryOperator *binop = dyn_cast<BinaryOperator>(e)) {
BinaryOperatorKind opc = binop->getOpcode();
// TODO: ignore multiplications by 1, reject if multiplied by 0.
if (mulop == nullptr && opc == BO_Mul)
@@ -80,12 +89,18 @@ void MallocOverflowSecurityChecker::CheckMallocArgument(
const Expr *lhs = binop->getLHS();
const Expr *rhs = binop->getRHS();
- if (rhs->isEvaluatable(Context))
+ if (rhs->isEvaluatable(Context)) {
e = lhs;
- else if ((opc == BO_Add || opc == BO_Mul)
- && lhs->isEvaluatable(Context))
+ maxVal = rhs->EvaluateKnownConstInt(Context);
+ if (EvaluatesToZero(maxVal, opc))
+ return;
+ } else if ((opc == BO_Add || opc == BO_Mul) &&
+ lhs->isEvaluatable(Context)) {
+ maxVal = lhs->EvaluateKnownConstInt(Context);
+ if (EvaluatesToZero(maxVal, opc))
+ return;
e = rhs;
- else
+ } else
return;
}
else if (isa<DeclRefExpr>(e) || isa<MemberExpr>(e))
@@ -103,7 +118,7 @@ void MallocOverflowSecurityChecker::CheckMallocArgument(
// TODO: Could push this into the innermost scope where 'e' is
// defined, rather than the whole function.
- PossibleMallocOverflows.push_back(MallocOverflowCheck(mulop, e));
+ PossibleMallocOverflows.push_back(MallocOverflowCheck(mulop, e, maxVal));
}
namespace {
@@ -126,33 +141,84 @@ private:
return false;
}
- void CheckExpr(const Expr *E_p) {
- const Expr *E = E_p->IgnoreParenImpCasts();
+ const Decl *getDecl(const DeclRefExpr *DR) { return DR->getDecl(); }
+
+ const Decl *getDecl(const MemberExpr *ME) { return ME->getMemberDecl(); }
+ template <typename T1>
+ void Erase(const T1 *DR, std::function<bool(theVecType::iterator)> pred) {
theVecType::iterator i = toScanFor.end();
theVecType::iterator e = toScanFor.begin();
-
- if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
- const Decl * EdreD = DR->getDecl();
- while (i != e) {
- --i;
- if (const DeclRefExpr *DR_i = dyn_cast<DeclRefExpr>(i->variable)) {
- if (DR_i->getDecl() == EdreD)
- i = toScanFor.erase(i);
- }
+ while (i != e) {
+ --i;
+ if (const T1 *DR_i = dyn_cast<T1>(i->variable)) {
+ if ((getDecl(DR_i) == getDecl(DR)) && pred(i))
+ i = toScanFor.erase(i);
}
}
+ }
+
+ void CheckExpr(const Expr *E_p) {
+ auto PredTrue = [](theVecType::iterator) -> bool { return true; };
+ const Expr *E = E_p->IgnoreParenImpCasts();
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
+ Erase<DeclRefExpr>(DR, PredTrue);
else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
- // No points-to analysis, just look at the member
- const Decl *EmeMD = ME->getMemberDecl();
- while (i != e) {
- --i;
- if (const auto *ME_i = dyn_cast<MemberExpr>(i->variable)) {
- if (ME_i->getMemberDecl() == EmeMD)
- i = toScanFor.erase (i);
- }
+ Erase<MemberExpr>(ME, PredTrue);
+ }
+ }
+
+ // Check if the argument to malloc is assigned a value
+ // which cannot cause an overflow.
+ // e.g., malloc (mul * x) and,
+ // case 1: mul = <constant value>
+ // case 2: mul = a/b, where b > x
+ void CheckAssignmentExpr(BinaryOperator *AssignEx) {
+ bool assignKnown = false;
+ bool numeratorKnown = false, denomKnown = false;
+ APSInt denomVal;
+ denomVal = 0;
+
+ // Erase if the multiplicand was assigned a constant value.
+ const Expr *rhs = AssignEx->getRHS();
+ if (rhs->isEvaluatable(Context))
+ assignKnown = true;
+
+ // Discard the report if the multiplicand was assigned a value,
+ // that can never overflow after multiplication. e.g., the assignment
+ // is a division operator and the denominator is > other multiplicand.
+ const Expr *rhse = rhs->IgnoreParenImpCasts();
+ if (const BinaryOperator *BOp = dyn_cast<BinaryOperator>(rhse)) {
+ if (BOp->getOpcode() == BO_Div) {
+ const Expr *denom = BOp->getRHS()->IgnoreParenImpCasts();
+ if (denom->EvaluateAsInt(denomVal, Context))
+ denomKnown = true;
+ const Expr *numerator = BOp->getLHS()->IgnoreParenImpCasts();
+ if (numerator->isEvaluatable(Context))
+ numeratorKnown = true;
}
}
+ if (!assignKnown && !denomKnown)
+ return;
+ auto denomExtVal = denomVal.getExtValue();
+
+ // Ignore negative denominator.
+ if (denomExtVal < 0)
+ return;
+
+ const Expr *lhs = AssignEx->getLHS();
+ const Expr *E = lhs->IgnoreParenImpCasts();
+
+ auto pred = [assignKnown, numeratorKnown,
+ denomExtVal](theVecType::iterator i) {
+ return assignKnown ||
+ (numeratorKnown && (denomExtVal >= i->maxVal.getExtValue()));
+ };
+
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
+ Erase<DeclRefExpr>(DR, pred);
+ else if (const auto *ME = dyn_cast<MemberExpr>(E))
+ Erase<MemberExpr>(ME, pred);
}
public:
@@ -162,11 +228,13 @@ private:
const Expr * rhs = E->getRHS();
// Ignore comparisons against zero, since they generally don't
// protect against an overflow.
- if (!isIntZeroExpr(lhs) && ! isIntZeroExpr(rhs)) {
+ if (!isIntZeroExpr(lhs) && !isIntZeroExpr(rhs)) {
CheckExpr(lhs);
CheckExpr(rhs);
}
}
+ if (E->isAssignmentOp())
+ CheckAssignmentExpr(E);
EvaluatedExprVisitor<CheckOverflowOps>::VisitBinaryOperator(E);
}
@@ -243,12 +311,12 @@ void MallocOverflowSecurityChecker::checkASTCodeBody(const Decl *D,
const FunctionDecl *FD = TheCall->getDirectCallee();
if (!FD)
- return;
+ continue;
// Get the name of the callee. If it's a builtin, strip off the prefix.
IdentifierInfo *FnInfo = FD->getIdentifier();
if (!FnInfo)
- return;
+ continue;
if (FnInfo->isStr ("malloc") || FnInfo->isStr ("_MALLOC")) {
if (TheCall->getNumArgs() == 1)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
index fb07484..80a3fbe 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
@@ -143,20 +143,20 @@ static bool typesCompatible(ASTContext &C, QualType A, QualType B) {
while (true) {
A = A.getCanonicalType();
B = B.getCanonicalType();
-
+
if (A.getTypePtr() == B.getTypePtr())
return true;
-
+
if (const PointerType *ptrA = A->getAs<PointerType>())
if (const PointerType *ptrB = B->getAs<PointerType>()) {
A = ptrA->getPointeeType();
B = ptrB->getPointeeType();
continue;
}
-
+
break;
}
-
+
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
index d23708e..0e78947 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
@@ -11,7 +11,7 @@
// about subpar uses of NSAutoreleasePool. Note that while the check itself
// (in its current form) could be written as a flow-insensitive check, in
// can be potentially enhanced in the future with flow-sensitive information.
-// It is also a good example of the CheckerVisitor interface.
+// It is also a good example of the CheckerVisitor interface.
//
//===----------------------------------------------------------------------===//
@@ -48,7 +48,7 @@ void NSAutoreleasePoolChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
const ObjCInterfaceDecl *OD = msg.getReceiverInterface();
if (!OD)
- return;
+ return;
if (!OD->getIdentifier()->isStr("NSAutoreleasePool"))
return;
@@ -62,7 +62,7 @@ void NSAutoreleasePoolChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
BT.reset(new BugType(this, "Use -drain instead of -release",
"API Upgrade (Apple)"));
- ExplodedNode *N = C.addTransition();
+ ExplodedNode *N = C.generateNonFatalErrorNode();
if (!N) {
assert(0);
return;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
index c351c6e..dab068b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
@@ -58,7 +58,7 @@ void NSErrorMethodChecker::checkASTDecl(const ObjCMethodDecl *D,
return;
if (!II)
- II = &D->getASTContext().Idents.get("NSError");
+ II = &D->getASTContext().Idents.get("NSError");
bool hasNSError = false;
for (const auto *I : D->params()) {
@@ -105,7 +105,7 @@ void CFErrorFunctionChecker::checkASTDecl(const FunctionDecl *D,
return;
if (!II)
- II = &D->getASTContext().Idents.get("CFErrorRef");
+ II = &D->getASTContext().Idents.get("CFErrorRef");
bool hasCFError = false;
for (auto I : D->params()) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
index ba82d1d..c1deade 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
@@ -66,6 +66,7 @@ void NoReturnFunctionChecker::checkPostCall(const CallEvent &CE,
.Case("assfail", true)
.Case("db_error", true)
.Case("__assert", true)
+ .Case("__assert2", true)
// For the purpose of static analysis, we do not care that
// this MSVC function will return if the user decides to continue.
.Case("_wassert", true)
@@ -81,7 +82,7 @@ void NoReturnFunctionChecker::checkPostCall(const CallEvent &CE,
}
if (BuildSinks)
- C.generateSink();
+ C.generateSink(C.getState(), C.getPredecessor());
}
void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
@@ -90,7 +91,7 @@ void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
if (const ObjCMethodDecl *MD = Msg.getDecl()) {
MD = MD->getCanonicalDecl();
if (MD->hasAttr<AnalyzerNoReturnAttr>()) {
- C.generateSink();
+ C.generateSink(C.getState(), C.getPredecessor());
return;
}
}
@@ -136,7 +137,7 @@ void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
}
// If we got here, it's one of the messages we care about.
- C.generateSink();
+ C.generateSink(C.getState(), C.getPredecessor());
}
void ento::registerNoReturnFunctionChecker(CheckerManager &mgr) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
index 73f8087..1f82ab9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -28,7 +28,7 @@ using namespace ento;
namespace {
class NonNullParamChecker
- : public Checker< check::PreCall > {
+ : public Checker< check::PreCall, EventDispatcher<ImplicitNullDerefEvent> > {
mutable std::unique_ptr<BugType> BTAttrNonNull;
mutable std::unique_ptr<BugType> BTNullRefArg;
@@ -139,26 +139,34 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call,
ProgramStateRef stateNotNull, stateNull;
std::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
- if (stateNull && !stateNotNull) {
- // Generate an error node. Check for a null node in case
- // we cache out.
- if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
+ if (stateNull) {
+ if (!stateNotNull) {
+ // Generate an error node. Check for a null node in case
+ // we cache out.
+ if (ExplodedNode *errorNode = C.generateErrorNode(stateNull)) {
- std::unique_ptr<BugReport> R;
- if (haveAttrNonNull)
- R = genReportNullAttrNonNull(errorNode, ArgE);
- else if (haveRefTypeParam)
- R = genReportReferenceToNullPointer(errorNode, ArgE);
+ std::unique_ptr<BugReport> R;
+ if (haveAttrNonNull)
+ R = genReportNullAttrNonNull(errorNode, ArgE);
+ else if (haveRefTypeParam)
+ R = genReportReferenceToNullPointer(errorNode, ArgE);
- // Highlight the range of the argument that was null.
- R->addRange(Call.getArgSourceRange(idx));
+ // Highlight the range of the argument that was null.
+ R->addRange(Call.getArgSourceRange(idx));
- // Emit the bug report.
- C.emitReport(std::move(R));
- }
+ // Emit the bug report.
+ C.emitReport(std::move(R));
+ }
- // Always return. Either we cached out or we just emitted an error.
- return;
+ // Always return. Either we cached out or we just emitted an error.
+ return;
+ }
+ if (ExplodedNode *N = C.generateSink(stateNull, C.getPredecessor())) {
+ ImplicitNullDerefEvent event = {
+ V, false, N, &C.getBugReporter(),
+ /*IsDirectDereference=*/haveRefTypeParam};
+ dispatchEvent(event);
+ }
}
// If a pointer value passed the check we should assume that it is
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
new file mode 100644
index 0000000..bb86ea4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -0,0 +1,1066 @@
+//== Nullabilityhecker.cpp - Nullability checker ----------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker tries to find nullability violations. There are several kinds of
+// possible violations:
+// * Null pointer is passed to a pointer which has a _Nonnull type.
+// * Null pointer is returned from a function which has a _Nonnull return type.
+// * Nullable pointer is passed to a pointer which has a _Nonnull type.
+// * Nullable pointer is returned from a function which has a _Nonnull return
+// type.
+// * Nullable pointer is dereferenced.
+//
+// This checker propagates the nullability information of the pointers and looks
+// for the patterns that are described above. Explicit casts are trusted and are
+// considered a way to suppress false positives for this checker. The other way
+// to suppress warnings would be to add asserts or guarding if statements to the
+// code. In addition to the nullability propagation this checker also uses some
+// heuristics to suppress potential false positives.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "llvm/Support/Path.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+// Do not reorder! The getMostNullable method relies on the order.
+// Optimization: Most pointers expected to be unspecified. When a symbol has an
+// unspecified or nonnull type non of the rules would indicate any problem for
+// that symbol. For this reason only nullable and contradicted nullability are
+// stored for a symbol. When a symbol is already contradicted, it can not be
+// casted back to nullable.
+enum class Nullability : char {
+ Contradicted, // Tracked nullability is contradicted by an explicit cast. Do
+ // not report any nullability related issue for this symbol.
+ // This nullability is propagated agressively to avoid false
+ // positive results. See the comment on getMostNullable method.
+ Nullable,
+ Unspecified,
+ Nonnull
+};
+
+/// Returns the most nullable nullability. This is used for message expressions
+/// like [reciever method], where the nullability of this expression is either
+/// the nullability of the receiver or the nullability of the return type of the
+/// method, depending on which is more nullable. Contradicted is considered to
+/// be the most nullable, to avoid false positive results.
+Nullability getMostNullable(Nullability Lhs, Nullability Rhs) {
+ return static_cast<Nullability>(
+ std::min(static_cast<char>(Lhs), static_cast<char>(Rhs)));
+}
+
+const char *getNullabilityString(Nullability Nullab) {
+ switch (Nullab) {
+ case Nullability::Contradicted:
+ return "contradicted";
+ case Nullability::Nullable:
+ return "nullable";
+ case Nullability::Unspecified:
+ return "unspecified";
+ case Nullability::Nonnull:
+ return "nonnull";
+ }
+ llvm_unreachable("Unexpected enumeration.");
+ return "";
+}
+
+// These enums are used as an index to ErrorMessages array.
+enum class ErrorKind : int {
+ NilAssignedToNonnull,
+ NilPassedToNonnull,
+ NilReturnedToNonnull,
+ NullableAssignedToNonnull,
+ NullableReturnedToNonnull,
+ NullableDereferenced,
+ NullablePassedToNonnull
+};
+
+const char *const ErrorMessages[] = {
+ "Null is assigned to a pointer which is expected to have non-null value",
+ "Null passed to a callee that requires a non-null argument",
+ "Null is returned from a function that is expected to return a non-null "
+ "value",
+ "Nullable pointer is assigned to a pointer which is expected to have "
+ "non-null value",
+ "Nullable pointer is returned from a function that is expected to return a "
+ "non-null value",
+ "Nullable pointer is dereferenced",
+ "Nullable pointer is passed to a callee that requires a non-null argument"};
+
+class NullabilityChecker
+ : public Checker<check::Bind, check::PreCall, check::PreStmt<ReturnStmt>,
+ check::PostCall, check::PostStmt<ExplicitCastExpr>,
+ check::PostObjCMessage, check::DeadSymbols,
+ check::Event<ImplicitNullDerefEvent>> {
+ mutable std::unique_ptr<BugType> BT;
+
+public:
+ void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
+ void checkPostStmt(const ExplicitCastExpr *CE, CheckerContext &C) const;
+ void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+ void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+ void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
+ void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+ void checkEvent(ImplicitNullDerefEvent Event) const;
+
+ void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
+ const char *Sep) const override;
+
+ struct NullabilityChecksFilter {
+ DefaultBool CheckNullPassedToNonnull;
+ DefaultBool CheckNullReturnedFromNonnull;
+ DefaultBool CheckNullableDereferenced;
+ DefaultBool CheckNullablePassedToNonnull;
+ DefaultBool CheckNullableReturnedFromNonnull;
+
+ CheckName CheckNameNullPassedToNonnull;
+ CheckName CheckNameNullReturnedFromNonnull;
+ CheckName CheckNameNullableDereferenced;
+ CheckName CheckNameNullablePassedToNonnull;
+ CheckName CheckNameNullableReturnedFromNonnull;
+ };
+
+ NullabilityChecksFilter Filter;
+ // When set to false no nullability information will be tracked in
+ // NullabilityMap. It is possible to catch errors like passing a null pointer
+ // to a callee that expects nonnull argument without the information that is
+ // stroed in the NullabilityMap. This is an optimization.
+ DefaultBool NeedTracking;
+
+private:
+ class NullabilityBugVisitor
+ : public BugReporterVisitorImpl<NullabilityBugVisitor> {
+ public:
+ NullabilityBugVisitor(const MemRegion *M) : Region(M) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int X = 0;
+ ID.AddPointer(&X);
+ ID.AddPointer(Region);
+ }
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+ private:
+ // The tracked region.
+ const MemRegion *Region;
+ };
+
+ /// When any of the nonnull arguments of the analyzed function is null, do not
+ /// report anything and turn off the check.
+ ///
+ /// When \p SuppressPath is set to true, no more bugs will be reported on this
+ /// path by this checker.
+ void reportBugIfPreconditionHolds(ErrorKind Error, ExplodedNode *N,
+ const MemRegion *Region, CheckerContext &C,
+ const Stmt *ValueExpr = nullptr,
+ bool SuppressPath = false) const;
+
+ void reportBug(ErrorKind Error, ExplodedNode *N, const MemRegion *Region,
+ BugReporter &BR, const Stmt *ValueExpr = nullptr) const {
+ if (!BT)
+ BT.reset(new BugType(this, "Nullability", "Memory error"));
+ const char *Msg = ErrorMessages[static_cast<int>(Error)];
+ std::unique_ptr<BugReport> R(new BugReport(*BT, Msg, N));
+ if (Region) {
+ R->markInteresting(Region);
+ R->addVisitor(llvm::make_unique<NullabilityBugVisitor>(Region));
+ }
+ if (ValueExpr) {
+ R->addRange(ValueExpr->getSourceRange());
+ if (Error == ErrorKind::NilAssignedToNonnull ||
+ Error == ErrorKind::NilPassedToNonnull ||
+ Error == ErrorKind::NilReturnedToNonnull)
+ bugreporter::trackNullOrUndefValue(N, ValueExpr, *R);
+ }
+ BR.emitReport(std::move(R));
+ }
+
+ /// If an SVal wraps a region that should be tracked, it will return a pointer
+ /// to the wrapped region. Otherwise it will return a nullptr.
+ const SymbolicRegion *getTrackRegion(SVal Val,
+ bool CheckSuperRegion = false) const;
+};
+
+class NullabilityState {
+public:
+ NullabilityState(Nullability Nullab, const Stmt *Source = nullptr)
+ : Nullab(Nullab), Source(Source) {}
+
+ const Stmt *getNullabilitySource() const { return Source; }
+
+ Nullability getValue() const { return Nullab; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(static_cast<char>(Nullab));
+ ID.AddPointer(Source);
+ }
+
+ void print(raw_ostream &Out) const {
+ Out << getNullabilityString(Nullab) << "\n";
+ }
+
+private:
+ Nullability Nullab;
+ // Source is the expression which determined the nullability. For example in a
+ // message like [nullable nonnull_returning] has nullable nullability, because
+ // the receiver is nullable. Here the receiver will be the source of the
+ // nullability. This is useful information when the diagnostics are generated.
+ const Stmt *Source;
+};
+
+bool operator==(NullabilityState Lhs, NullabilityState Rhs) {
+ return Lhs.getValue() == Rhs.getValue() &&
+ Lhs.getNullabilitySource() == Rhs.getNullabilitySource();
+}
+
+} // end anonymous namespace
+
+REGISTER_MAP_WITH_PROGRAMSTATE(NullabilityMap, const MemRegion *,
+ NullabilityState)
+
+// If the nullability precondition of a function is violated, we should not
+// report nullability related issues on that path. For this reason once a
+// precondition is not met on a path, this checker will be esentially turned off
+// for the rest of the analysis. We do not want to generate a sink node however,
+// so this checker would not lead to reduced coverage.
+REGISTER_TRAIT_WITH_PROGRAMSTATE(PreconditionViolated, bool)
+
+enum class NullConstraint { IsNull, IsNotNull, Unknown };
+
+static NullConstraint getNullConstraint(DefinedOrUnknownSVal Val,
+ ProgramStateRef State) {
+ ConditionTruthVal Nullness = State->isNull(Val);
+ if (Nullness.isConstrainedFalse())
+ return NullConstraint::IsNotNull;
+ if (Nullness.isConstrainedTrue())
+ return NullConstraint::IsNull;
+ return NullConstraint::Unknown;
+}
+
+const SymbolicRegion *
+NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
+ if (!NeedTracking)
+ return nullptr;
+
+ auto RegionSVal = Val.getAs<loc::MemRegionVal>();
+ if (!RegionSVal)
+ return nullptr;
+
+ const MemRegion *Region = RegionSVal->getRegion();
+
+ if (CheckSuperRegion) {
+ if (auto FieldReg = Region->getAs<FieldRegion>())
+ return dyn_cast<SymbolicRegion>(FieldReg->getSuperRegion());
+ if (auto ElementReg = Region->getAs<ElementRegion>())
+ return dyn_cast<SymbolicRegion>(ElementReg->getSuperRegion());
+ }
+
+ return dyn_cast<SymbolicRegion>(Region);
+}
+
+PathDiagnosticPiece *NullabilityChecker::NullabilityBugVisitor::VisitNode(
+ const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
+ BugReport &BR) {
+ ProgramStateRef State = N->getState();
+ ProgramStateRef StatePrev = PrevN->getState();
+
+ const NullabilityState *TrackedNullab = State->get<NullabilityMap>(Region);
+ const NullabilityState *TrackedNullabPrev =
+ StatePrev->get<NullabilityMap>(Region);
+ if (!TrackedNullab)
+ return nullptr;
+
+ if (TrackedNullabPrev &&
+ TrackedNullabPrev->getValue() == TrackedNullab->getValue())
+ return nullptr;
+
+ // Retrieve the associated statement.
+ const Stmt *S = TrackedNullab->getNullabilitySource();
+ if (!S) {
+ ProgramPoint ProgLoc = N->getLocation();
+ if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
+ S = SP->getStmt();
+ }
+ }
+
+ if (!S)
+ return nullptr;
+
+ std::string InfoText =
+ (llvm::Twine("Nullability '") +
+ getNullabilityString(TrackedNullab->getValue()) + "' is infered")
+ .str();
+
+ // Generate the extra diagnostic.
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+ N->getLocationContext());
+ return new PathDiagnosticEventPiece(Pos, InfoText, true, nullptr);
+}
+
+static Nullability getNullabilityAnnotation(QualType Type) {
+ const auto *AttrType = Type->getAs<AttributedType>();
+ if (!AttrType)
+ return Nullability::Unspecified;
+ if (AttrType->getAttrKind() == AttributedType::attr_nullable)
+ return Nullability::Nullable;
+ else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
+ return Nullability::Nonnull;
+ return Nullability::Unspecified;
+}
+
+template <typename ParamVarDeclRange>
+static bool
+checkParamsForPreconditionViolation(const ParamVarDeclRange &Params,
+ ProgramStateRef State,
+ const LocationContext *LocCtxt) {
+ for (const auto *ParamDecl : Params) {
+ if (ParamDecl->isParameterPack())
+ break;
+
+ if (getNullabilityAnnotation(ParamDecl->getType()) != Nullability::Nonnull)
+ continue;
+
+ auto RegVal = State->getLValue(ParamDecl, LocCtxt)
+ .template getAs<loc::MemRegionVal>();
+ if (!RegVal)
+ continue;
+
+ auto ParamValue = State->getSVal(RegVal->getRegion())
+ .template getAs<DefinedOrUnknownSVal>();
+ if (!ParamValue)
+ continue;
+
+ if (getNullConstraint(*ParamValue, State) == NullConstraint::IsNull) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool checkPreconditionViolation(ProgramStateRef State, ExplodedNode *N,
+ CheckerContext &C) {
+ if (State->get<PreconditionViolated>())
+ return true;
+
+ const LocationContext *LocCtxt = C.getLocationContext();
+ const Decl *D = LocCtxt->getDecl();
+ if (!D)
+ return false;
+
+ if (const auto *BlockD = dyn_cast<BlockDecl>(D)) {
+ if (checkParamsForPreconditionViolation(BlockD->parameters(), State,
+ LocCtxt)) {
+ if (!N->isSink())
+ C.addTransition(State->set<PreconditionViolated>(true), N);
+ return true;
+ }
+ return false;
+ }
+
+ if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {
+ if (checkParamsForPreconditionViolation(FuncDecl->parameters(), State,
+ LocCtxt)) {
+ if (!N->isSink())
+ C.addTransition(State->set<PreconditionViolated>(true), N);
+ return true;
+ }
+ return false;
+ }
+ return false;
+}
+
+void NullabilityChecker::reportBugIfPreconditionHolds(
+ ErrorKind Error, ExplodedNode *N, const MemRegion *Region,
+ CheckerContext &C, const Stmt *ValueExpr, bool SuppressPath) const {
+ ProgramStateRef OriginalState = N->getState();
+
+ if (checkPreconditionViolation(OriginalState, N, C))
+ return;
+ if (SuppressPath) {
+ OriginalState = OriginalState->set<PreconditionViolated>(true);
+ N = C.addTransition(OriginalState, N);
+ }
+
+ reportBug(Error, N, Region, C.getBugReporter(), ValueExpr);
+}
+
+/// Cleaning up the program state.
+void NullabilityChecker::checkDeadSymbols(SymbolReaper &SR,
+ CheckerContext &C) const {
+ if (!SR.hasDeadSymbols())
+ return;
+
+ ProgramStateRef State = C.getState();
+ NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
+ for (NullabilityMapTy::iterator I = Nullabilities.begin(),
+ E = Nullabilities.end();
+ I != E; ++I) {
+ const auto *Region = I->first->getAs<SymbolicRegion>();
+ assert(Region && "Non-symbolic region is tracked.");
+ if (SR.isDead(Region->getSymbol())) {
+ State = State->remove<NullabilityMap>(I->first);
+ }
+ }
+ // When one of the nonnull arguments are constrained to be null, nullability
+ // preconditions are violated. It is not enough to check this only when we
+ // actually report an error, because at that time interesting symbols might be
+ // reaped.
+ if (checkPreconditionViolation(State, C.getPredecessor(), C))
+ return;
+ C.addTransition(State);
+}
+
+/// This callback triggers when a pointer is dereferenced and the analyzer does
+/// not know anything about the value of that pointer. When that pointer is
+/// nullable, this code emits a warning.
+void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event) const {
+ if (Event.SinkNode->getState()->get<PreconditionViolated>())
+ return;
+
+ const MemRegion *Region =
+ getTrackRegion(Event.Location, /*CheckSuperregion=*/true);
+ if (!Region)
+ return;
+
+ ProgramStateRef State = Event.SinkNode->getState();
+ const NullabilityState *TrackedNullability =
+ State->get<NullabilityMap>(Region);
+
+ if (!TrackedNullability)
+ return;
+
+ if (Filter.CheckNullableDereferenced &&
+ TrackedNullability->getValue() == Nullability::Nullable) {
+ BugReporter &BR = *Event.BR;
+ // Do not suppress errors on defensive code paths, because dereferencing
+ // a nullable pointer is always an error.
+ if (Event.IsDirectDereference)
+ reportBug(ErrorKind::NullableDereferenced, Event.SinkNode, Region, BR);
+ else
+ reportBug(ErrorKind::NullablePassedToNonnull, Event.SinkNode, Region, BR);
+ }
+}
+
+/// This method check when nullable pointer or null value is returned from a
+/// function that has nonnull return type.
+///
+/// TODO: when nullability preconditons are violated, it is ok to violate the
+/// nullability postconditons (i.e.: when one of the nonnull parameters are null
+/// this check should not report any nullability related issue).
+void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
+ CheckerContext &C) const {
+ auto RetExpr = S->getRetValue();
+ if (!RetExpr)
+ return;
+
+ if (!RetExpr->getType()->isAnyPointerType())
+ return;
+
+ ProgramStateRef State = C.getState();
+ if (State->get<PreconditionViolated>())
+ return;
+
+ auto RetSVal =
+ State->getSVal(S, C.getLocationContext()).getAs<DefinedOrUnknownSVal>();
+ if (!RetSVal)
+ return;
+
+ AnalysisDeclContext *DeclCtxt =
+ C.getLocationContext()->getAnalysisDeclContext();
+ const FunctionType *FuncType = DeclCtxt->getDecl()->getFunctionType();
+ if (!FuncType)
+ return;
+
+ NullConstraint Nullness = getNullConstraint(*RetSVal, State);
+
+ Nullability RequiredNullability =
+ getNullabilityAnnotation(FuncType->getReturnType());
+
+ // If the returned value is null but the type of the expression
+ // generating it is nonnull then we will suppress the diagnostic.
+ // This enables explicit suppression when returning a nil literal in a
+ // function with a _Nonnull return type:
+ // return (NSString * _Nonnull)0;
+ Nullability RetExprTypeLevelNullability =
+ getNullabilityAnnotation(RetExpr->getType());
+
+ if (Filter.CheckNullReturnedFromNonnull &&
+ Nullness == NullConstraint::IsNull &&
+ RetExprTypeLevelNullability != Nullability::Nonnull &&
+ RequiredNullability == Nullability::Nonnull) {
+ static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
+ ExplodedNode *N = C.generateErrorNode(State, &Tag);
+ if (!N)
+ return;
+ reportBugIfPreconditionHolds(ErrorKind::NilReturnedToNonnull, N, nullptr, C,
+ RetExpr);
+ return;
+ }
+
+ const MemRegion *Region = getTrackRegion(*RetSVal);
+ if (!Region)
+ return;
+
+ const NullabilityState *TrackedNullability =
+ State->get<NullabilityMap>(Region);
+ if (TrackedNullability) {
+ Nullability TrackedNullabValue = TrackedNullability->getValue();
+ if (Filter.CheckNullableReturnedFromNonnull &&
+ Nullness != NullConstraint::IsNotNull &&
+ TrackedNullabValue == Nullability::Nullable &&
+ RequiredNullability == Nullability::Nonnull) {
+ static CheckerProgramPointTag Tag(this, "NullableReturnedFromNonnull");
+ ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
+ reportBugIfPreconditionHolds(ErrorKind::NullableReturnedToNonnull, N,
+ Region, C);
+ }
+ return;
+ }
+ if (RequiredNullability == Nullability::Nullable) {
+ State = State->set<NullabilityMap>(Region,
+ NullabilityState(RequiredNullability,
+ S));
+ C.addTransition(State);
+ }
+}
+
+/// This callback warns when a nullable pointer or a null value is passed to a
+/// function that expects its argument to be nonnull.
+void NullabilityChecker::checkPreCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ if (!Call.getDecl())
+ return;
+
+ ProgramStateRef State = C.getState();
+ if (State->get<PreconditionViolated>())
+ return;
+
+ ProgramStateRef OrigState = State;
+
+ unsigned Idx = 0;
+ for (const ParmVarDecl *Param : Call.parameters()) {
+ if (Param->isParameterPack())
+ break;
+
+ const Expr *ArgExpr = nullptr;
+ if (Idx < Call.getNumArgs())
+ ArgExpr = Call.getArgExpr(Idx);
+ auto ArgSVal = Call.getArgSVal(Idx++).getAs<DefinedOrUnknownSVal>();
+ if (!ArgSVal)
+ continue;
+
+ if (!Param->getType()->isAnyPointerType() &&
+ !Param->getType()->isReferenceType())
+ continue;
+
+ NullConstraint Nullness = getNullConstraint(*ArgSVal, State);
+
+ Nullability RequiredNullability =
+ getNullabilityAnnotation(Param->getType());
+ Nullability ArgExprTypeLevelNullability =
+ getNullabilityAnnotation(ArgExpr->getType());
+
+ if (Filter.CheckNullPassedToNonnull && Nullness == NullConstraint::IsNull &&
+ ArgExprTypeLevelNullability != Nullability::Nonnull &&
+ RequiredNullability == Nullability::Nonnull) {
+ ExplodedNode *N = C.generateErrorNode(State);
+ if (!N)
+ return;
+ reportBugIfPreconditionHolds(ErrorKind::NilPassedToNonnull, N, nullptr, C,
+ ArgExpr);
+ return;
+ }
+
+ const MemRegion *Region = getTrackRegion(*ArgSVal);
+ if (!Region)
+ continue;
+
+ const NullabilityState *TrackedNullability =
+ State->get<NullabilityMap>(Region);
+
+ if (TrackedNullability) {
+ if (Nullness == NullConstraint::IsNotNull ||
+ TrackedNullability->getValue() != Nullability::Nullable)
+ continue;
+
+ if (Filter.CheckNullablePassedToNonnull &&
+ RequiredNullability == Nullability::Nonnull) {
+ ExplodedNode *N = C.addTransition(State);
+ reportBugIfPreconditionHolds(ErrorKind::NullablePassedToNonnull, N,
+ Region, C, ArgExpr, /*SuppressPath=*/true);
+ return;
+ }
+ if (Filter.CheckNullableDereferenced &&
+ Param->getType()->isReferenceType()) {
+ ExplodedNode *N = C.addTransition(State);
+ reportBugIfPreconditionHolds(ErrorKind::NullableDereferenced, N, Region,
+ C, ArgExpr, /*SuppressPath=*/true);
+ return;
+ }
+ continue;
+ }
+ // No tracked nullability yet.
+ if (ArgExprTypeLevelNullability != Nullability::Nullable)
+ continue;
+ State = State->set<NullabilityMap>(
+ Region, NullabilityState(ArgExprTypeLevelNullability, ArgExpr));
+ }
+ if (State != OrigState)
+ C.addTransition(State);
+}
+
+/// Suppress the nullability warnings for some functions.
+void NullabilityChecker::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ auto Decl = Call.getDecl();
+ if (!Decl)
+ return;
+ // ObjC Messages handles in a different callback.
+ if (Call.getKind() == CE_ObjCMessage)
+ return;
+ const FunctionType *FuncType = Decl->getFunctionType();
+ if (!FuncType)
+ return;
+ QualType ReturnType = FuncType->getReturnType();
+ if (!ReturnType->isAnyPointerType())
+ return;
+ ProgramStateRef State = C.getState();
+ if (State->get<PreconditionViolated>())
+ return;
+
+ const MemRegion *Region = getTrackRegion(Call.getReturnValue());
+ if (!Region)
+ return;
+
+ // CG headers are misannotated. Do not warn for symbols that are the results
+ // of CG calls.
+ const SourceManager &SM = C.getSourceManager();
+ StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getLocStart()));
+ if (llvm::sys::path::filename(FilePath).startswith("CG")) {
+ State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
+ C.addTransition(State);
+ return;
+ }
+
+ const NullabilityState *TrackedNullability =
+ State->get<NullabilityMap>(Region);
+
+ if (!TrackedNullability &&
+ getNullabilityAnnotation(ReturnType) == Nullability::Nullable) {
+ State = State->set<NullabilityMap>(Region, Nullability::Nullable);
+ C.addTransition(State);
+ }
+}
+
+static Nullability getReceiverNullability(const ObjCMethodCall &M,
+ ProgramStateRef State) {
+ if (M.isReceiverSelfOrSuper()) {
+ // For super and super class receivers we assume that the receiver is
+ // nonnull.
+ return Nullability::Nonnull;
+ }
+ // Otherwise look up nullability in the state.
+ SVal Receiver = M.getReceiverSVal();
+ if (auto DefOrUnknown = Receiver.getAs<DefinedOrUnknownSVal>()) {
+ // If the receiver is constrained to be nonnull, assume that it is nonnull
+ // regardless of its type.
+ NullConstraint Nullness = getNullConstraint(*DefOrUnknown, State);
+ if (Nullness == NullConstraint::IsNotNull)
+ return Nullability::Nonnull;
+ }
+ auto ValueRegionSVal = Receiver.getAs<loc::MemRegionVal>();
+ if (ValueRegionSVal) {
+ const MemRegion *SelfRegion = ValueRegionSVal->getRegion();
+ assert(SelfRegion);
+
+ const NullabilityState *TrackedSelfNullability =
+ State->get<NullabilityMap>(SelfRegion);
+ if (TrackedSelfNullability)
+ return TrackedSelfNullability->getValue();
+ }
+ return Nullability::Unspecified;
+}
+
+/// Calculate the nullability of the result of a message expr based on the
+/// nullability of the receiver, the nullability of the return value, and the
+/// constraints.
+void NullabilityChecker::checkPostObjCMessage(const ObjCMethodCall &M,
+ CheckerContext &C) const {
+ auto Decl = M.getDecl();
+ if (!Decl)
+ return;
+ QualType RetType = Decl->getReturnType();
+ if (!RetType->isAnyPointerType())
+ return;
+
+ ProgramStateRef State = C.getState();
+ if (State->get<PreconditionViolated>())
+ return;
+
+ const MemRegion *ReturnRegion = getTrackRegion(M.getReturnValue());
+ if (!ReturnRegion)
+ return;
+
+ auto Interface = Decl->getClassInterface();
+ auto Name = Interface ? Interface->getName() : "";
+ // In order to reduce the noise in the diagnostics generated by this checker,
+ // some framework and programming style based heuristics are used. These
+ // heuristics are for Cocoa APIs which have NS prefix.
+ if (Name.startswith("NS")) {
+ // Developers rely on dynamic invariants such as an item should be available
+ // in a collection, or a collection is not empty often. Those invariants can
+ // not be inferred by any static analysis tool. To not to bother the users
+ // with too many false positives, every item retrieval function should be
+ // ignored for collections. The instance methods of dictionaries in Cocoa
+ // are either item retrieval related or not interesting nullability wise.
+ // Using this fact, to keep the code easier to read just ignore the return
+ // value of every instance method of dictionaries.
+ if (M.isInstanceMessage() && Name.find("Dictionary") != StringRef::npos) {
+ State =
+ State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
+ C.addTransition(State);
+ return;
+ }
+ // For similar reasons ignore some methods of Cocoa arrays.
+ StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);
+ if (Name.find("Array") != StringRef::npos &&
+ (FirstSelectorSlot == "firstObject" ||
+ FirstSelectorSlot == "lastObject")) {
+ State =
+ State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);
+ C.addTransition(State);
+ return;
+ }
+
+ // Encoding related methods of string should not fail when lossless
+ // encodings are used. Using lossless encodings is so frequent that ignoring
+ // this class of methods reduced the emitted diagnostics by about 30% on
+ // some projects (and all of that was false positives).
+ if (Name.find("String") != StringRef::npos) {
+ for (auto Param : M.parameters()) {
+ if (Param->getName() == "encoding") {
+ State = State->set<NullabilityMap>(ReturnRegion,
+ Nullability::Contradicted);
+ C.addTransition(State);
+ return;
+ }
+ }
+ }
+ }
+
+ const ObjCMessageExpr *Message = M.getOriginExpr();
+ Nullability SelfNullability = getReceiverNullability(M, State);
+
+ const NullabilityState *NullabilityOfReturn =
+ State->get<NullabilityMap>(ReturnRegion);
+
+ if (NullabilityOfReturn) {
+ // When we have a nullability tracked for the return value, the nullability
+ // of the expression will be the most nullable of the receiver and the
+ // return value.
+ Nullability RetValTracked = NullabilityOfReturn->getValue();
+ Nullability ComputedNullab =
+ getMostNullable(RetValTracked, SelfNullability);
+ if (ComputedNullab != RetValTracked &&
+ ComputedNullab != Nullability::Unspecified) {
+ const Stmt *NullabilitySource =
+ ComputedNullab == RetValTracked
+ ? NullabilityOfReturn->getNullabilitySource()
+ : Message->getInstanceReceiver();
+ State = State->set<NullabilityMap>(
+ ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
+ C.addTransition(State);
+ }
+ return;
+ }
+
+ // No tracked information. Use static type information for return value.
+ Nullability RetNullability = getNullabilityAnnotation(RetType);
+
+ // Properties might be computed. For this reason the static analyzer creates a
+ // new symbol each time an unknown property is read. To avoid false pozitives
+ // do not treat unknown properties as nullable, even when they explicitly
+ // marked nullable.
+ if (M.getMessageKind() == OCM_PropertyAccess && !C.wasInlined)
+ RetNullability = Nullability::Nonnull;
+
+ Nullability ComputedNullab = getMostNullable(RetNullability, SelfNullability);
+ if (ComputedNullab == Nullability::Nullable) {
+ const Stmt *NullabilitySource = ComputedNullab == RetNullability
+ ? Message
+ : Message->getInstanceReceiver();
+ State = State->set<NullabilityMap>(
+ ReturnRegion, NullabilityState(ComputedNullab, NullabilitySource));
+ C.addTransition(State);
+ }
+}
+
+/// Explicit casts are trusted. If there is a disagreement in the nullability
+/// annotations in the destination and the source or '0' is casted to nonnull
+/// track the value as having contraditory nullability. This will allow users to
+/// suppress warnings.
+void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
+ CheckerContext &C) const {
+ QualType OriginType = CE->getSubExpr()->getType();
+ QualType DestType = CE->getType();
+ if (!OriginType->isAnyPointerType())
+ return;
+ if (!DestType->isAnyPointerType())
+ return;
+
+ ProgramStateRef State = C.getState();
+ if (State->get<PreconditionViolated>())
+ return;
+
+ Nullability DestNullability = getNullabilityAnnotation(DestType);
+
+ // No explicit nullability in the destination type, so this cast does not
+ // change the nullability.
+ if (DestNullability == Nullability::Unspecified)
+ return;
+
+ auto RegionSVal =
+ State->getSVal(CE, C.getLocationContext()).getAs<DefinedOrUnknownSVal>();
+ const MemRegion *Region = getTrackRegion(*RegionSVal);
+ if (!Region)
+ return;
+
+ // When 0 is converted to nonnull mark it as contradicted.
+ if (DestNullability == Nullability::Nonnull) {
+ NullConstraint Nullness = getNullConstraint(*RegionSVal, State);
+ if (Nullness == NullConstraint::IsNull) {
+ State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
+ C.addTransition(State);
+ return;
+ }
+ }
+
+ const NullabilityState *TrackedNullability =
+ State->get<NullabilityMap>(Region);
+
+ if (!TrackedNullability) {
+ if (DestNullability != Nullability::Nullable)
+ return;
+ State = State->set<NullabilityMap>(Region,
+ NullabilityState(DestNullability, CE));
+ C.addTransition(State);
+ return;
+ }
+
+ if (TrackedNullability->getValue() != DestNullability &&
+ TrackedNullability->getValue() != Nullability::Contradicted) {
+ State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
+ C.addTransition(State);
+ }
+}
+
+/// For a given statement performing a bind, attempt to syntactically
+/// match the expression resulting in the bound value.
+static const Expr * matchValueExprForBind(const Stmt *S) {
+ // For `x = e` the value expression is the right-hand side.
+ if (auto *BinOp = dyn_cast<BinaryOperator>(S)) {
+ if (BinOp->getOpcode() == BO_Assign)
+ return BinOp->getRHS();
+ }
+
+ // For `int x = e` the value expression is the initializer.
+ if (auto *DS = dyn_cast<DeclStmt>(S)) {
+ if (DS->isSingleDecl()) {
+ auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+ if (!VD)
+ return nullptr;
+
+ if (const Expr *Init = VD->getInit())
+ return Init;
+ }
+ }
+
+ return nullptr;
+}
+
+/// Returns true if \param S is a DeclStmt for a local variable that
+/// ObjC automated reference counting initialized with zero.
+static bool isARCNilInitializedLocal(CheckerContext &C, const Stmt *S) {
+ // We suppress diagnostics for ARC zero-initialized _Nonnull locals. This
+ // prevents false positives when a _Nonnull local variable cannot be
+ // initialized with an initialization expression:
+ // NSString * _Nonnull s; // no-warning
+ // @autoreleasepool {
+ // s = ...
+ // }
+ //
+ // FIXME: We should treat implicitly zero-initialized _Nonnull locals as
+ // uninitialized in Sema's UninitializedValues analysis to warn when a use of
+ // the zero-initialized definition will unexpectedly yield nil.
+
+ // Locals are only zero-initialized when automated reference counting
+ // is turned on.
+ if (!C.getASTContext().getLangOpts().ObjCAutoRefCount)
+ return false;
+
+ auto *DS = dyn_cast<DeclStmt>(S);
+ if (!DS || !DS->isSingleDecl())
+ return false;
+
+ auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
+ if (!VD)
+ return false;
+
+ // Sema only zero-initializes locals with ObjCLifetimes.
+ if(!VD->getType().getQualifiers().hasObjCLifetime())
+ return false;
+
+ const Expr *Init = VD->getInit();
+ assert(Init && "ObjC local under ARC without initializer");
+
+ // Return false if the local is explicitly initialized (e.g., with '= nil').
+ if (!isa<ImplicitValueInitExpr>(Init))
+ return false;
+
+ return true;
+}
+
+/// Propagate the nullability information through binds and warn when nullable
+/// pointer or null symbol is assigned to a pointer with a nonnull type.
+void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
+ CheckerContext &C) const {
+ const TypedValueRegion *TVR =
+ dyn_cast_or_null<TypedValueRegion>(L.getAsRegion());
+ if (!TVR)
+ return;
+
+ QualType LocType = TVR->getValueType();
+ if (!LocType->isAnyPointerType())
+ return;
+
+ ProgramStateRef State = C.getState();
+ if (State->get<PreconditionViolated>())
+ return;
+
+ auto ValDefOrUnknown = V.getAs<DefinedOrUnknownSVal>();
+ if (!ValDefOrUnknown)
+ return;
+
+ NullConstraint RhsNullness = getNullConstraint(*ValDefOrUnknown, State);
+
+ Nullability ValNullability = Nullability::Unspecified;
+ if (SymbolRef Sym = ValDefOrUnknown->getAsSymbol())
+ ValNullability = getNullabilityAnnotation(Sym->getType());
+
+ Nullability LocNullability = getNullabilityAnnotation(LocType);
+ if (Filter.CheckNullPassedToNonnull &&
+ RhsNullness == NullConstraint::IsNull &&
+ ValNullability != Nullability::Nonnull &&
+ LocNullability == Nullability::Nonnull &&
+ !isARCNilInitializedLocal(C, S)) {
+ static CheckerProgramPointTag Tag(this, "NullPassedToNonnull");
+ ExplodedNode *N = C.generateErrorNode(State, &Tag);
+ if (!N)
+ return;
+
+ const Stmt *ValueExpr = matchValueExprForBind(S);
+ if (!ValueExpr)
+ ValueExpr = S;
+
+ reportBugIfPreconditionHolds(ErrorKind::NilAssignedToNonnull, N, nullptr, C,
+ ValueExpr);
+ return;
+ }
+ // Intentionally missing case: '0' is bound to a reference. It is handled by
+ // the DereferenceChecker.
+
+ const MemRegion *ValueRegion = getTrackRegion(*ValDefOrUnknown);
+ if (!ValueRegion)
+ return;
+
+ const NullabilityState *TrackedNullability =
+ State->get<NullabilityMap>(ValueRegion);
+
+ if (TrackedNullability) {
+ if (RhsNullness == NullConstraint::IsNotNull ||
+ TrackedNullability->getValue() != Nullability::Nullable)
+ return;
+ if (Filter.CheckNullablePassedToNonnull &&
+ LocNullability == Nullability::Nonnull) {
+ static CheckerProgramPointTag Tag(this, "NullablePassedToNonnull");
+ ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
+ reportBugIfPreconditionHolds(ErrorKind::NullableAssignedToNonnull, N,
+ ValueRegion, C);
+ }
+ return;
+ }
+
+ const auto *BinOp = dyn_cast<BinaryOperator>(S);
+
+ if (ValNullability == Nullability::Nullable) {
+ // Trust the static information of the value more than the static
+ // information on the location.
+ const Stmt *NullabilitySource = BinOp ? BinOp->getRHS() : S;
+ State = State->set<NullabilityMap>(
+ ValueRegion, NullabilityState(ValNullability, NullabilitySource));
+ C.addTransition(State);
+ return;
+ }
+
+ if (LocNullability == Nullability::Nullable) {
+ const Stmt *NullabilitySource = BinOp ? BinOp->getLHS() : S;
+ State = State->set<NullabilityMap>(
+ ValueRegion, NullabilityState(LocNullability, NullabilitySource));
+ C.addTransition(State);
+ }
+}
+
+void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep) const {
+
+ NullabilityMapTy B = State->get<NullabilityMap>();
+
+ if (B.isEmpty())
+ return;
+
+ Out << Sep << NL;
+
+ for (NullabilityMapTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ Out << I->first << " : ";
+ I->second.print(Out);
+ Out << NL;
+ }
+}
+
+#define REGISTER_CHECKER(name, trackingRequired) \
+ void ento::register##name##Checker(CheckerManager &mgr) { \
+ NullabilityChecker *checker = mgr.registerChecker<NullabilityChecker>(); \
+ checker->Filter.Check##name = true; \
+ checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \
+ checker->NeedTracking = checker->NeedTracking || trackingRequired; \
+ }
+
+// The checks are likely to be turned on by default and it is possible to do
+// them without tracking any nullability related information. As an optimization
+// no nullability information will be tracked when only these two checks are
+// enables.
+REGISTER_CHECKER(NullPassedToNonnull, false)
+REGISTER_CHECKER(NullReturnedFromNonnull, false)
+
+REGISTER_CHECKER(NullableDereferenced, true)
+REGISTER_CHECKER(NullablePassedToNonnull, true)
+REGISTER_CHECKER(NullableReturnedFromNonnull, true)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
index a7b92b4..cbaa5c2 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
@@ -43,7 +43,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
// Uninitialized value used for the mutex?
if (V.getAs<UndefinedVal>()) {
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
if (!BT_undef)
BT_undef.reset(new BuiltinBug(this, "Uninitialized value used as mutex "
"for @synchronized"));
@@ -66,7 +66,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
if (!notNullState) {
// Generate an error node. This isn't a sink since
// a null mutex just means no synchronization occurs.
- if (ExplodedNode *N = C.addTransition(nullState)) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode(nullState)) {
if (!BT_null)
BT_null.reset(new BuiltinBug(
this, "Nil value used as mutex for @synchronized() "
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
index 224251b..b10ec84 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp
@@ -66,9 +66,8 @@ class WalkAST : public StmtVisitor<WalkAST> {
// The type must be an array/pointer type.
// This could be a null constant, which is allowed.
- if (E->isNullPointerConstant(ASTC, Expr::NPC_ValueDependentIsNull))
- return true;
- return false;
+ return static_cast<bool>(
+ E->isNullPointerConstant(ASTC, Expr::NPC_ValueDependentIsNull));
}
public:
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
index 53e1598..0203d79 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
@@ -133,13 +133,13 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
if (IdxVal.isUnknownOrUndef())
return;
DefinedSVal Idx = IdxVal.castAs<DefinedSVal>();
-
+
// Now, check if 'Idx in [0, Size-1]'.
const QualType T = IdxExpr->getType();
ProgramStateRef StInBound = State->assumeInBound(Idx, *Size, true, T);
ProgramStateRef StOutBound = State->assumeInBound(Idx, *Size, false, T);
if (StOutBound && !StInBound) {
- ExplodedNode *N = C.generateSink(StOutBound);
+ ExplodedNode *N = C.generateErrorNode(StOutBound);
if (!N)
return;
initBugType();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
index 016cb14..32a1adb 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp
@@ -49,7 +49,7 @@ public:
DoesCallSuper = true;
// Recurse if we didn't find the super call yet.
- return !DoesCallSuper;
+ return !DoesCallSuper;
}
bool DoesCallSuper;
@@ -59,7 +59,7 @@ private:
};
//===----------------------------------------------------------------------===//
-// ObjCSuperCallChecker
+// ObjCSuperCallChecker
//===----------------------------------------------------------------------===//
class ObjCSuperCallChecker : public Checker<
@@ -88,7 +88,7 @@ private:
/// \param[out] SuperclassName On return, the found superclass name.
bool ObjCSuperCallChecker::isCheckableClass(const ObjCImplementationDecl *D,
StringRef &SuperclassName) const {
- const ObjCInterfaceDecl *ID = D->getClassInterface();
+ const ObjCInterfaceDecl *ID = D->getClassInterface()->getSuperClass();
for ( ; ID ; ID = ID->getSuperClass())
{
SuperclassName = ID->getIdentifier()->getName();
@@ -202,7 +202,7 @@ void ObjCSuperCallChecker::checkASTDecl(const ObjCImplementationDecl *D,
SmallString<320> Buf;
llvm::raw_svector_ostream os(Buf);
- os << "The '" << S.getAsString()
+ os << "The '" << S.getAsString()
<< "' instance method in " << SuperclassName.str() << " subclass '"
<< *D << "' is missing a [super " << S.getAsString() << "] call";
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index 93b0553..ffa3a27 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -145,15 +145,15 @@ void ObjCSelfInitChecker::checkForInvalidSelf(const Expr *E, CheckerContext &C,
const char *errorStr) const {
if (!E)
return;
-
+
if (!C.getState()->get<CalledInit>())
return;
-
+
if (!isInvalidSelf(E, C))
return;
-
+
// Generate an error node.
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
@@ -177,12 +177,12 @@ void ObjCSelfInitChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
if (isInitMessage(Msg)) {
// Tag the return value as the result of an initializer.
ProgramStateRef state = C.getState();
-
+
// FIXME this really should be context sensitive, where we record
// the current stack frame (for IPA). Also, we need to clean this
// value out when we return from this method.
state = state->set<CalledInit>(true);
-
+
SVal V = state->getSVal(Msg.getOriginExpr(), C.getLocationContext());
addSelfFlag(state, V, SelfFlag_InitRes, C);
return;
@@ -318,7 +318,7 @@ void ObjCSelfInitChecker::checkBind(SVal loc, SVal val, const Stmt *S,
CheckerContext &C) const {
// Allow assignment of anything to self. Self is a local variable in the
// initializer, so it is legal to assign anything to it, like results of
- // static functions/method calls. After self is assigned something we cannot
+ // static functions/method calls. After self is assigned something we cannot
// reason about, stop enforcing the rules.
// (Only continue checking if the assigned value should be treated as self.)
if ((isSelfVar(loc, C)) &&
@@ -404,15 +404,12 @@ static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND) {
if (II == NSObjectII)
break;
}
- if (!ID)
- return false;
-
- return true;
+ return ID != nullptr;
}
/// \brief Returns true if the location is 'self'.
static bool isSelfVar(SVal location, CheckerContext &C) {
- AnalysisDeclContext *analCtx = C.getCurrentAnalysisDeclContext();
+ AnalysisDeclContext *analCtx = C.getCurrentAnalysisDeclContext();
if (!analCtx->getSelfDecl())
return false;
if (!location.getAs<loc::MemRegionVal>())
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
new file mode 100644
index 0000000..8ce3735
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -0,0 +1,314 @@
+//=======- PaddingChecker.cpp ------------------------------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a checker that checks for padding that could be
+// removed by re-ordering members.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include <numeric>
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class PaddingChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
+private:
+ mutable std::unique_ptr<BugType> PaddingBug;
+ mutable int64_t AllowedPad;
+ mutable BugReporter *BR;
+
+public:
+ void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
+ BugReporter &BRArg) const {
+ BR = &BRArg;
+ AllowedPad =
+ MGR.getAnalyzerOptions().getOptionAsInteger("AllowedPad", 24, this);
+ assert(AllowedPad >= 0 && "AllowedPad option should be non-negative");
+
+ // The calls to checkAST* from AnalysisConsumer don't
+ // visit template instantiations or lambda classes. We
+ // want to visit those, so we make our own RecursiveASTVisitor.
+ struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {
+ const PaddingChecker *Checker;
+ bool shouldVisitTemplateInstantiations() const { return true; }
+ bool shouldVisitImplicitCode() const { return true; }
+ explicit LocalVisitor(const PaddingChecker *Checker) : Checker(Checker) {}
+ bool VisitRecordDecl(const RecordDecl *RD) {
+ Checker->visitRecord(RD);
+ return true;
+ }
+ bool VisitVarDecl(const VarDecl *VD) {
+ Checker->visitVariable(VD);
+ return true;
+ }
+ // TODO: Visit array new and mallocs for arrays.
+ };
+
+ LocalVisitor visitor(this);
+ visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));
+ }
+
+ /// \brief Look for records of overly padded types. If padding *
+ /// PadMultiplier exceeds AllowedPad, then generate a report.
+ /// PadMultiplier is used to share code with the array padding
+ /// checker.
+ void visitRecord(const RecordDecl *RD, uint64_t PadMultiplier = 1) const {
+ if (shouldSkipDecl(RD))
+ return;
+
+ auto &ASTContext = RD->getASTContext();
+ const ASTRecordLayout &RL = ASTContext.getASTRecordLayout(RD);
+ assert(llvm::isPowerOf2_64(RL.getAlignment().getQuantity()));
+
+ CharUnits BaselinePad = calculateBaselinePad(RD, ASTContext, RL);
+ if (BaselinePad.isZero())
+ return;
+ CharUnits OptimalPad = calculateOptimalPad(RD, ASTContext, RL);
+
+ CharUnits DiffPad = PadMultiplier * (BaselinePad - OptimalPad);
+ if (DiffPad.getQuantity() <= AllowedPad) {
+ assert(!DiffPad.isNegative() && "DiffPad should not be negative");
+ // There is not enough excess padding to trigger a warning.
+ return;
+ }
+ reportRecord(RD, BaselinePad, OptimalPad);
+ }
+
+ /// \brief Look for arrays of overly padded types. If the padding of the
+ /// array type exceeds AllowedPad, then generate a report.
+ void visitVariable(const VarDecl *VD) const {
+ const ArrayType *ArrTy = VD->getType()->getAsArrayTypeUnsafe();
+ if (ArrTy == nullptr)
+ return;
+ uint64_t Elts = 0;
+ if (const ConstantArrayType *CArrTy = dyn_cast<ConstantArrayType>(ArrTy))
+ Elts = CArrTy->getSize().getZExtValue();
+ if (Elts == 0)
+ return;
+ const RecordType *RT = ArrTy->getElementType()->getAs<RecordType>();
+ if (RT == nullptr)
+ return;
+
+ // TODO: Recurse into the fields and base classes to see if any
+ // of those have excess padding.
+ visitRecord(RT->getDecl(), Elts);
+ }
+
+ bool shouldSkipDecl(const RecordDecl *RD) const {
+ auto Location = RD->getLocation();
+ // If the construct doesn't have a source file, then it's not something
+ // we want to diagnose.
+ if (!Location.isValid())
+ return true;
+ SrcMgr::CharacteristicKind Kind =
+ BR->getSourceManager().getFileCharacteristic(Location);
+ // Throw out all records that come from system headers.
+ if (Kind != SrcMgr::C_User)
+ return true;
+
+ // Not going to attempt to optimize unions.
+ if (RD->isUnion())
+ return true;
+ // How do you reorder fields if you haven't got any?
+ if (RD->field_empty())
+ return true;
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ // Tail padding with base classes ends up being very complicated.
+ // We will skip objects with base classes for now.
+ if (CXXRD->getNumBases() != 0)
+ return true;
+ // Virtual bases are complicated, skipping those for now.
+ if (CXXRD->getNumVBases() != 0)
+ return true;
+ // Can't layout a template, so skip it. We do still layout the
+ // instantiations though.
+ if (CXXRD->getTypeForDecl()->isDependentType())
+ return true;
+ if (CXXRD->getTypeForDecl()->isInstantiationDependentType())
+ return true;
+ }
+ auto IsTrickyField = [](const FieldDecl *FD) -> bool {
+ // Bitfield layout is hard.
+ if (FD->isBitField())
+ return true;
+
+ // Variable length arrays are tricky too.
+ QualType Ty = FD->getType();
+ if (Ty->isIncompleteArrayType())
+ return true;
+ return false;
+ };
+
+ if (std::any_of(RD->field_begin(), RD->field_end(), IsTrickyField))
+ return true;
+ return false;
+ }
+
+ static CharUnits calculateBaselinePad(const RecordDecl *RD,
+ const ASTContext &ASTContext,
+ const ASTRecordLayout &RL) {
+ CharUnits PaddingSum;
+ CharUnits Offset = ASTContext.toCharUnitsFromBits(RL.getFieldOffset(0));
+ for (const auto &FD : RD->fields()) {
+ // This checker only cares about the padded size of the
+ // field, and not the data size. If the field is a record
+ // with tail padding, then we won't put that number in our
+ // total because reordering fields won't fix that problem.
+ CharUnits FieldSize = ASTContext.getTypeSizeInChars(FD->getType());
+ auto FieldOffsetBits = RL.getFieldOffset(FD->getFieldIndex());
+ CharUnits FieldOffset = ASTContext.toCharUnitsFromBits(FieldOffsetBits);
+ PaddingSum += (FieldOffset - Offset);
+ Offset = FieldOffset + FieldSize;
+ }
+ PaddingSum += RL.getSize() - Offset;
+ return PaddingSum;
+ }
+
+ /// Optimal padding overview:
+ /// 1. Find a close approximation to where we can place our first field.
+ /// This will usually be at offset 0.
+ /// 2. Try to find the best field that can legally be placed at the current
+ /// offset.
+ /// a. "Best" is the largest alignment that is legal, but smallest size.
+ /// This is to account for overly aligned types.
+ /// 3. If no fields can fit, pad by rounding the current offset up to the
+ /// smallest alignment requirement of our fields. Measure and track the
+ // amount of padding added. Go back to 2.
+ /// 4. Increment the current offset by the size of the chosen field.
+ /// 5. Remove the chosen field from the set of future possibilities.
+ /// 6. Go back to 2 if there are still unplaced fields.
+ /// 7. Add tail padding by rounding the current offset up to the structure
+ /// alignment. Track the amount of padding added.
+
+ static CharUnits calculateOptimalPad(const RecordDecl *RD,
+ const ASTContext &ASTContext,
+ const ASTRecordLayout &RL) {
+ struct CharUnitPair {
+ CharUnits Align;
+ CharUnits Size;
+ bool operator<(const CharUnitPair &RHS) const {
+ // Order from small alignments to large alignments,
+ // then large sizes to small sizes.
+ return std::make_pair(Align, -Size) <
+ std::make_pair(RHS.Align, -RHS.Size);
+ }
+ };
+ SmallVector<CharUnitPair, 20> Fields;
+ auto GatherSizesAndAlignments = [](const FieldDecl *FD) {
+ CharUnitPair RetVal;
+ auto &Ctx = FD->getASTContext();
+ std::tie(RetVal.Size, RetVal.Align) =
+ Ctx.getTypeInfoInChars(FD->getType());
+ assert(llvm::isPowerOf2_64(RetVal.Align.getQuantity()));
+ if (auto Max = FD->getMaxAlignment())
+ RetVal.Align = std::max(Ctx.toCharUnitsFromBits(Max), RetVal.Align);
+ return RetVal;
+ };
+ std::transform(RD->field_begin(), RD->field_end(),
+ std::back_inserter(Fields), GatherSizesAndAlignments);
+ std::sort(Fields.begin(), Fields.end());
+
+ // This lets us skip over vptrs and non-virtual bases,
+ // so that we can just worry about the fields in our object.
+ // Note that this does cause us to miss some cases where we
+ // could pack more bytes in to a base class's tail padding.
+ CharUnits NewOffset = ASTContext.toCharUnitsFromBits(RL.getFieldOffset(0));
+ CharUnits NewPad;
+
+ while (!Fields.empty()) {
+ unsigned TrailingZeros =
+ llvm::countTrailingZeros((unsigned long long)NewOffset.getQuantity());
+ // If NewOffset is zero, then countTrailingZeros will be 64. Shifting
+ // 64 will overflow our unsigned long long. Shifting 63 will turn
+ // our long long (and CharUnits internal type) negative. So shift 62.
+ long long CurAlignmentBits = 1ull << (std::min)(TrailingZeros, 62u);
+ CharUnits CurAlignment = CharUnits::fromQuantity(CurAlignmentBits);
+ CharUnitPair InsertPoint = {CurAlignment, CharUnits::Zero()};
+ auto CurBegin = Fields.begin();
+ auto CurEnd = Fields.end();
+
+ // In the typical case, this will find the last element
+ // of the vector. We won't find a middle element unless
+ // we started on a poorly aligned address or have an overly
+ // aligned field.
+ auto Iter = std::upper_bound(CurBegin, CurEnd, InsertPoint);
+ if (Iter != CurBegin) {
+ // We found a field that we can layout with the current alignment.
+ --Iter;
+ NewOffset += Iter->Size;
+ Fields.erase(Iter);
+ } else {
+ // We are poorly aligned, and we need to pad in order to layout another
+ // field. Round up to at least the smallest field alignment that we
+ // currently have.
+ CharUnits NextOffset = NewOffset.RoundUpToAlignment(Fields[0].Align);
+ NewPad += NextOffset - NewOffset;
+ NewOffset = NextOffset;
+ }
+ }
+ // Calculate tail padding.
+ CharUnits NewSize = NewOffset.RoundUpToAlignment(RL.getAlignment());
+ NewPad += NewSize - NewOffset;
+ return NewPad;
+ }
+
+ void reportRecord(const RecordDecl *RD, CharUnits BaselinePad,
+ CharUnits TargetPad) const {
+ if (!PaddingBug)
+ PaddingBug =
+ llvm::make_unique<BugType>(this, "Excessive Padding", "Performance");
+
+ SmallString<100> Buf;
+ llvm::raw_svector_ostream Os(Buf);
+
+ Os << "Excessive padding in '";
+ Os << QualType::getAsString(RD->getTypeForDecl(), Qualifiers()) << "'";
+
+ if (auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+ // TODO: make this show up better in the console output and in
+ // the HTML. Maybe just make it show up in HTML like the path
+ // diagnostics show.
+ SourceLocation ILoc = TSD->getPointOfInstantiation();
+ if (ILoc.isValid())
+ Os << " instantiated here: "
+ << ILoc.printToString(BR->getSourceManager());
+ }
+
+ Os << " (" << BaselinePad.getQuantity() << " padding bytes, where "
+ << TargetPad.getQuantity() << " is optimal). Consider reordering "
+ << "the fields or adding explicit padding members.";
+
+ PathDiagnosticLocation CELoc =
+ PathDiagnosticLocation::create(RD, BR->getSourceManager());
+
+ auto Report = llvm::make_unique<BugReport>(*PaddingBug, Os.str(), CELoc);
+ Report->setDeclWithIssue(RD);
+ Report->addRange(RD->getSourceRange());
+
+ BR->emitReport(std::move(Report));
+ }
+};
+}
+
+void ento::registerPaddingChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<PaddingChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
index 8063124..e336967 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
@@ -22,7 +22,7 @@ using namespace clang;
using namespace ento;
namespace {
-class PointerArithChecker
+class PointerArithChecker
: public Checker< check::PreStmt<BinaryOperator> > {
mutable std::unique_ptr<BuiltinBug> BT;
@@ -48,10 +48,10 @@ void PointerArithChecker::checkPreStmt(const BinaryOperator *B,
// If pointer arithmetic is done on variables of non-array type, this often
// means behavior rely on memory organization, which is dangerous.
- if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) ||
+ if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) ||
isa<CompoundLiteralRegion>(LR)) {
- if (ExplodedNode *N = C.addTransition()) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
if (!BT)
BT.reset(
new BuiltinBug(this, "Dangerous pointer arithmetic",
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
index cf1f88a..2d33ebc 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// This files defines PointerSubChecker, a builtin checker that checks for
-// pointer subtractions on two pointers pointing to different memory chunks.
+// pointer subtractions on two pointers pointing to different memory chunks.
// This check corresponds to CWE-469.
//
//===----------------------------------------------------------------------===//
@@ -23,7 +23,7 @@ using namespace clang;
using namespace ento;
namespace {
-class PointerSubChecker
+class PointerSubChecker
: public Checker< check::PreStmt<BinaryOperator> > {
mutable std::unique_ptr<BuiltinBug> BT;
@@ -60,7 +60,7 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
return;
- if (ExplodedNode *N = C.addTransition()) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
if (!BT)
BT.reset(
new BuiltinBug(this, "Pointer subtraction",
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
index 4209017..28a4a08 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -32,9 +32,9 @@ private:
LockState(Kind K) : K(K) {}
public:
- static LockState getLocked(void) { return LockState(Locked); }
- static LockState getUnlocked(void) { return LockState(Unlocked); }
- static LockState getDestroyed(void) { return LockState(Destroyed); }
+ static LockState getLocked() { return LockState(Locked); }
+ static LockState getUnlocked() { return LockState(Unlocked); }
+ static LockState getDestroyed() { return LockState(Destroyed); }
bool operator==(const LockState &X) const {
return K == X.K;
@@ -62,10 +62,10 @@ class PthreadLockChecker : public Checker< check::PostStmt<CallExpr> > {
};
public:
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
-
+
void AcquireLock(CheckerContext &C, const CallExpr *CE, SVal lock,
bool isTryLock, enum LockingSemantics semantics) const;
-
+
void ReleaseLock(CheckerContext &C, const CallExpr *CE, SVal lock) const;
void DestroyLock(CheckerContext &C, const CallExpr *CE, SVal Lock) const;
void InitLock(CheckerContext &C, const CallExpr *CE, SVal Lock) const;
@@ -96,7 +96,7 @@ void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
false, PthreadSemantics);
else if (FName == "lck_mtx_lock" ||
FName == "lck_rw_lock_exclusive" ||
- FName == "lck_rw_lock_shared")
+ FName == "lck_rw_lock_shared")
AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
false, XNUSemantics);
else if (FName == "pthread_mutex_trylock" ||
@@ -124,17 +124,17 @@ void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
SVal lock, bool isTryLock,
enum LockingSemantics semantics) const {
-
+
const MemRegion *lockR = lock.getAsRegion();
if (!lockR)
return;
-
+
ProgramStateRef state = C.getState();
-
+
SVal X = state->getSVal(CE, C.getLocationContext());
if (X.isUnknownOrUndef())
return;
-
+
DefinedSVal retVal = X.castAs<DefinedSVal>();
if (const LockState *LState = state->get<LockMap>(lockR)) {
@@ -142,7 +142,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
if (!BT_doublelock)
BT_doublelock.reset(new BugType(this, "Double locking",
"Lock checker"));
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
auto report = llvm::make_unique<BugReport>(
@@ -183,8 +183,8 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
assert((semantics == XNUSemantics) && "Unknown locking semantics");
lockSucc = state;
}
-
- // Record that the lock was acquired.
+
+ // Record that the lock was acquired.
lockSucc = lockSucc->add<LockSet>(lockR);
lockSucc = lockSucc->set<LockMap>(lockR, LockState::getLocked());
C.addTransition(lockSucc);
@@ -196,7 +196,7 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
const MemRegion *lockR = lock.getAsRegion();
if (!lockR)
return;
-
+
ProgramStateRef state = C.getState();
if (const LockState *LState = state->get<LockMap>(lockR)) {
@@ -204,7 +204,7 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
if (!BT_doubleunlock)
BT_doubleunlock.reset(new BugType(this, "Double unlocking",
"Lock checker"));
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
auto Report = llvm::make_unique<BugReport>(
@@ -227,7 +227,7 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
if (firstLockR != lockR) {
if (!BT_lor)
BT_lor.reset(new BugType(this, "Lock order reversal", "Lock checker"));
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
auto report = llvm::make_unique<BugReport>(
@@ -272,7 +272,7 @@ void PthreadLockChecker::DestroyLock(CheckerContext &C, const CallExpr *CE,
if (!BT_destroylock)
BT_destroylock.reset(new BugType(this, "Destroy invalid lock",
"Lock checker"));
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
auto Report = llvm::make_unique<BugReport>(*BT_destroylock, Message, N);
@@ -307,7 +307,7 @@ void PthreadLockChecker::InitLock(CheckerContext &C, const CallExpr *CE,
if (!BT_initlock)
BT_initlock.reset(new BugType(this, "Init invalid lock",
"Lock checker"));
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
auto Report = llvm::make_unique<BugReport>(*BT_initlock, Message, N);
@@ -320,7 +320,7 @@ void PthreadLockChecker::reportUseDestroyedBug(CheckerContext &C,
if (!BT_destroylock)
BT_destroylock.reset(new BugType(this, "Use destroyed lock",
"Lock checker"));
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
auto Report = llvm::make_unique<BugReport>(
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index 6ee87a5..f983c30 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -234,6 +234,7 @@ public:
return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
getType(), IvarAccessHistory::AccessedDirectly);
}
+
RefVal releaseViaIvar() const {
assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
@@ -250,7 +251,7 @@ public:
bool operator==(const RefVal& X) const {
return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
}
-
+
void Profile(llvm::FoldingSetNodeID& ID) const {
ID.Add(T);
ID.AddInteger(RawKind);
@@ -426,16 +427,16 @@ public:
/// setRetEffect - Set the effect of the return value of the call.
void setRetEffect(RetEffect E) { Ret = E; }
-
+
/// Sets the effect on the receiver of the message.
void setReceiverEffect(ArgEffect e) { Receiver = e; }
-
+
/// getReceiverEffect - Returns the effect on the receiver of the call.
/// This is only meaningful if the summary applies to an ObjCMessageExpr*.
ArgEffect getReceiverEffect() const { return Receiver; }
/// Test if two retain summaries are identical. Note that merely equivalent
- /// summaries are not necessarily identical (for example, if an explicit
+ /// summaries are not necessarily identical (for example, if an explicit
/// argument effect matches the default effect).
bool operator==(const RetainSummary &Other) const {
return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
@@ -484,7 +485,7 @@ public:
IdentifierInfo *getIdentifier() const { return II; }
Selector getSelector() const { return S; }
};
-}
+} // end anonymous namespace
namespace llvm {
template <> struct DenseMapInfo<ObjCSummaryKey> {
@@ -621,7 +622,7 @@ class RetainSummaryManager {
ArgEffects::Factory AF;
/// ScratchArgs - A holding buffer for construct ArgEffects.
- ArgEffects ScratchArgs;
+ ArgEffects ScratchArgs;
/// ObjCAllocRetE - Default return effect for methods returning Objective-C
/// objects.
@@ -644,7 +645,7 @@ class RetainSummaryManager {
ArgEffects getArgEffects();
enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable };
-
+
const RetainSummary *getUnarySummary(const FunctionType* FT,
UnaryFuncKind func);
@@ -664,7 +665,7 @@ class RetainSummaryManager {
const RetainSummary *getDoNothingSummary() {
return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
-
+
const RetainSummary *getDefaultSummary() {
return getPersistentSummary(RetEffect::MakeNoRet(),
DoNothing, MayEscape);
@@ -689,7 +690,7 @@ private:
void addClassMethSummary(const char* Cls, const char* name,
const RetainSummary *Summ, bool isNullary = true) {
IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
- Selector S = isNullary ? GetNullarySelector(name, Ctx)
+ Selector S = isNullary ? GetNullarySelector(name, Ctx)
: GetUnarySelector(name, Ctx);
ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
}
@@ -739,7 +740,7 @@ public:
? RetEffect::MakeGCNotOwned()
: (usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)
: RetEffect::MakeOwned(RetEffect::ObjC, true))),
- ObjCInitRetE(gcenabled
+ ObjCInitRetE(gcenabled
? RetEffect::MakeGCNotOwned()
: (usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)
: RetEffect::MakeOwnedWhenTrackedReceiver())) {
@@ -803,7 +804,7 @@ public:
bool isGCEnabled() const { return GCEnabled; }
bool isARCEnabled() const { return ARCEnabled; }
-
+
bool isARCorGCEnabled() const { return GCEnabled || ARCEnabled; }
RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
@@ -966,7 +967,7 @@ void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
// Additionally, our Self Init checker already warns about it. To avoid
// overwhelming the user with messages from both checkers, we model the case
// of '[super init]' in cases when it is not consumed by another expression
- // as if the call preserves the value of 'self'; essentially, assuming it can
+ // as if the call preserves the value of 'self'; essentially, assuming it can
// never fail and return 'nil'.
// Note, we don't want to just stop tracking the value since we want the
// RetainCount checker to report leaks and use-after-free if SelfInit checker
@@ -985,7 +986,6 @@ void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
}
}
-
}
}
@@ -1150,7 +1150,7 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
if (S)
break;
- if (RetTy->isPointerType()) {
+ if (RetTy->isPointerType()) {
// For CoreFoundation ('CF') types.
if (cocoa::isRefType(RetTy, "CF", FName)) {
if (isRetain(FD, FName)) {
@@ -1278,14 +1278,14 @@ RetainSummaryManager::getUnarySummary(const FunctionType* FT,
return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
-const RetainSummary *
+const RetainSummary *
RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {
assert (ScratchArgs.isEmpty());
return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
}
-const RetainSummary *
+const RetainSummary *
RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {
assert (ScratchArgs.isEmpty());
return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
@@ -1331,7 +1331,7 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
// Effects on the parameters.
unsigned parm_idx = 0;
- for (FunctionDecl::param_const_iterator pi = FD->param_begin(),
+ for (FunctionDecl::param_const_iterator pi = FD->param_begin(),
pe = FD->param_end(); pi != pe; ++pi, ++parm_idx) {
const ParmVarDecl *pd = *pi;
if (pd->hasAttr<NSConsumedAttr>())
@@ -1367,8 +1367,8 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
// Effects on the receiver.
if (MD->hasAttr<NSConsumesSelfAttr>())
- Template->setReceiverEffect(DecRefMsg);
-
+ Template->setReceiverEffect(DecRefMsg);
+
// Effects on the parameters.
unsigned parm_idx = 0;
for (ObjCMethodDecl::param_const_iterator
@@ -1376,9 +1376,9 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
pi != pe; ++pi, ++parm_idx) {
const ParmVarDecl *pd = *pi;
if (pd->hasAttr<NSConsumedAttr>())
- Template->addArg(AF, parm_idx, DecRefMsg);
+ Template->addArg(AF, parm_idx, DecRefMsg);
else if (pd->hasAttr<CFConsumedAttr>()) {
- Template->addArg(AF, parm_idx, DecRef);
+ Template->addArg(AF, parm_idx, DecRef);
} else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
QualType PointeeTy = pd->getType()->getPointeeType();
if (!PointeeTy.isNull())
@@ -1415,7 +1415,7 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
if (cocoa::isCocoaObjectRef(RetTy))
ResultEff = RetEffect::MakeNotOwned(RetEffect::ObjC);
else if (coreFoundation::isCFObjectRef(RetTy)) {
- // ObjCMethodDecl currently doesn't consider CF objects as valid return
+ // ObjCMethodDecl currently doesn't consider CF objects as valid return
// values for alloc, new, copy, or mutableCopy, so we have to
// double-check with the selector. This is ugly, but there aren't that
// many Objective-C methods that return CF objects, right?
@@ -1428,11 +1428,11 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
ResultEff = RetEffect::MakeOwned(RetEffect::CF, true);
break;
default:
- ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
+ ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
break;
}
} else {
- ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
+ ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
}
}
break;
@@ -1749,7 +1749,7 @@ namespace {
SymbolRef Sym;
const SummaryLogTy &SummaryLog;
bool GCEnabled;
-
+
public:
CFRefReportVisitor(SymbolRef sym, bool gcEnabled, const SummaryLogTy &log)
: Sym(sym), SummaryLog(log), GCEnabled(gcEnabled) {}
@@ -1869,7 +1869,7 @@ void CFRefReport::addGCModeDescription(const LangOptions &LOpts,
static bool isNumericLiteralExpression(const Expr *E) {
// FIXME: This set of cases was copied from SemaExprObjC.
- return isa<IntegerLiteral>(E) ||
+ return isa<IntegerLiteral>(E) ||
isa<CharacterLiteral>(E) ||
isa<FloatingLiteral>(E) ||
isa<ObjCBoolLiteralExpr>(E) ||
@@ -1948,7 +1948,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
else if (isa<ObjCIvarRefExpr>(S)) {
os << "Object loaded from instance variable";
}
- else {
+ else {
if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
// Get the name of the callee (if it is available).
SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
@@ -2192,6 +2192,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
return P;
}
+namespace {
// Find the first node in the current function context that referred to the
// tracked symbol and the memory location that value was stored to. Note, the
// value is only reported if the allocation occurred in the same function as
@@ -2206,6 +2207,7 @@ struct AllocationInfo {
const LocationContext *InInterestingMethodContext) :
N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
};
+} // end anonymous namespace
static AllocationInfo
GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
@@ -2228,7 +2230,7 @@ GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
StoreManager::FindUniqueBinding FB(Sym);
StateMgr.iterBindings(St, FB);
-
+
if (FB) {
const MemRegion *R = FB.getRegion();
const VarRegion *VR = R->getBaseRegion()->getAs<VarRegion>();
@@ -2345,10 +2347,10 @@ CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
// objects. Only "copy", "alloc", "retain" and "new" transfer ownership
// to the caller for NS objects.
const Decl *D = &EndN->getCodeDecl();
-
+
os << (isa<ObjCMethodDecl>(D) ? " is returned from a method "
: " is returned from a function ");
-
+
if (D->hasAttr<CFReturnsNotRetainedAttr>())
os << "that is annotated as CF_RETURNS_NOT_RETAINED";
else if (D->hasAttr<NSReturnsNotRetainedAttr>())
@@ -2385,7 +2387,7 @@ CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
}
CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
- bool GCEnabled, const SummaryLogTy &Log,
+ bool GCEnabled, const SummaryLogTy &Log,
ExplodedNode *n, SymbolRef sym,
CheckerContext &Ctx,
bool IncludeAllocationLine)
@@ -2414,7 +2416,7 @@ CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
// FIXME: This will crash the analyzer if an allocation comes from an
// implicit call (ex: a destructor call).
// (Currently there are no such allocations in Cocoa, though.)
- const Stmt *AllocStmt = 0;
+ const Stmt *AllocStmt = nullptr;
ProgramPoint P = AllocNode->getLocation();
if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
AllocStmt = Exit->getCalleeContext()->getCallSite();
@@ -2492,7 +2494,7 @@ class RetainCountChecker
/// the allocation line.
mutable bool IncludeAllocationLine;
-public:
+public:
RetainCountChecker(AnalyzerOptions &AO)
: ShouldResetSummaryLog(false),
IncludeAllocationLine(shouldIncludeAllocationSiteInLeakDiagnostics(AO)) {}
@@ -2617,7 +2619,7 @@ public:
void checkPostStmt(const ObjCIvarRefExpr *IRE, CheckerContext &C) const;
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
-
+
void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
CheckerContext &C) const;
@@ -2630,13 +2632,13 @@ public:
ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
bool Assumption) const;
- ProgramStateRef
+ ProgramStateRef
checkRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call) const;
-
+
bool wantsRegionChangeUpdate(ProgramStateRef state) const {
return true;
}
@@ -2645,7 +2647,7 @@ public:
void checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
ExplodedNode *Pred, RetEffect RE, RefVal X,
SymbolRef Sym, ProgramStateRef state) const;
-
+
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
void checkEndFunction(CheckerContext &C) const;
@@ -2656,7 +2658,7 @@ public:
void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
RefVal::Kind ErrorKind, SymbolRef Sym,
CheckerContext &C) const;
-
+
void processObjCLiterals(CheckerContext &C, const Expr *Ex) const;
const ProgramPointTag *getDeadSymbolTag(SymbolRef sym) const;
@@ -2678,7 +2680,7 @@ public:
} // end anonymous namespace
namespace {
-class StopTrackingCallback : public SymbolVisitor {
+class StopTrackingCallback final : public SymbolVisitor {
ProgramStateRef state;
public:
StopTrackingCallback(ProgramStateRef st) : state(st) {}
@@ -2740,21 +2742,21 @@ void RetainCountChecker::checkPostStmt(const CastExpr *CE,
const ObjCBridgedCastExpr *BE = dyn_cast<ObjCBridgedCastExpr>(CE);
if (!BE)
return;
-
+
ArgEffect AE = IncRef;
-
+
switch (BE->getBridgeKind()) {
case clang::OBC_Bridge:
// Do nothing.
return;
case clang::OBC_BridgeRetained:
AE = IncRef;
- break;
+ break;
case clang::OBC_BridgeTransfer:
AE = DecRefBridgedTransferred;
break;
}
-
+
ProgramStateRef state = C.getState();
SymbolRef Sym = state->getSVal(CE, C.getLocationContext()).getAsLocSymbol();
if (!Sym)
@@ -2765,7 +2767,7 @@ void RetainCountChecker::checkPostStmt(const CastExpr *CE,
RefVal::Kind hasErr = (RefVal::Kind) 0;
state = updateSymbol(state, Sym, *T, AE, hasErr, C);
-
+
if (hasErr) {
// FIXME: If we get an error during a bridge cast, should we report it?
return;
@@ -2777,7 +2779,7 @@ void RetainCountChecker::checkPostStmt(const CastExpr *CE,
void RetainCountChecker::processObjCLiterals(CheckerContext &C,
const Expr *Ex) const {
ProgramStateRef state = C.getState();
- const ExplodedNode *pred = C.getPredecessor();
+ const ExplodedNode *pred = C.getPredecessor();
for (const Stmt *Child : Ex->children()) {
SVal V = state->getSVal(Child, pred->getLocationContext());
if (SymbolRef sym = V.getAsSymbol())
@@ -2790,17 +2792,17 @@ void RetainCountChecker::processObjCLiterals(CheckerContext &C,
}
}
}
-
+
// Return the object as autoreleased.
// RetEffect RE = RetEffect::MakeNotOwned(RetEffect::ObjC);
- if (SymbolRef sym =
+ if (SymbolRef sym =
state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) {
QualType ResultTy = Ex->getType();
state = setRefBinding(state, sym,
RefVal::makeNotOwned(RetEffect::ObjC, ResultTy));
}
-
- C.addTransition(state);
+
+ C.addTransition(state);
}
void RetainCountChecker::checkPostStmt(const ObjCArrayLiteral *AL,
@@ -2817,7 +2819,7 @@ void RetainCountChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
void RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex,
CheckerContext &C) const {
- const ExplodedNode *Pred = C.getPredecessor();
+ const ExplodedNode *Pred = C.getPredecessor();
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
@@ -2966,7 +2968,7 @@ void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
if (Sym)
state = removeRefBinding(state, Sym);
}
-
+
C.addTransition(state);
}
@@ -3062,7 +3064,7 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
if (ReceiverIsTracked)
- RE = getSummaryManager(C).getObjAllocRetEffect();
+ RE = getSummaryManager(C).getObjAllocRetEffect();
else
RE = RetEffect::MakeNoRet();
}
@@ -3129,8 +3131,7 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
}
}
-
-ProgramStateRef
+ProgramStateRef
RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
RefVal V, ArgEffect E, RefVal::Kind &hasErr,
CheckerContext &C) const {
@@ -3306,7 +3307,7 @@ void RetainCountChecker::processNonLeakError(ProgramStateRef St,
if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
return;
- ExplodedNode *N = C.generateSink(St);
+ ExplodedNode *N = C.generateErrorNode(St);
if (!N)
return;
@@ -3388,7 +3389,7 @@ bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
isMakeCollectable(FD, FName);
}
}
-
+
if (!canEval)
return false;
@@ -3531,7 +3532,7 @@ void RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
ExplodedNode *Pred,
RetEffect RE, RefVal X,
SymbolRef Sym,
- ProgramStateRef state) const {
+ ProgramStateRef state) const {
// HACK: Ignore retain-count issues on values accessed through ivars,
// because of cases like this:
// [_contentView retain];
@@ -3669,7 +3670,6 @@ void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
SVal Cond,
bool Assumption) const {
-
// FIXME: We may add to the interface of evalAssume the list of symbols
// whose assumptions have changed. For now we just iterate through the
// bindings and check if any of the tracked symbols are NULL. This isn't
@@ -3700,7 +3700,7 @@ ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
return state;
}
-ProgramStateRef
+ProgramStateRef
RetainCountChecker::checkRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
@@ -3810,7 +3810,7 @@ RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state,
return nullptr;
}
-ProgramStateRef
+ProgramStateRef
RetainCountChecker::handleSymbolDeath(ProgramStateRef state,
SymbolRef sid, RefVal V,
SmallVectorImpl<SymbolRef> &Leaked) const {
@@ -3890,7 +3890,7 @@ void RetainCountChecker::checkEndFunction(CheckerContext &Ctx) const {
// and suggest annotations.
if (LCtx->getParent())
return;
-
+
B = state->get<RefBindings>();
SmallVector<SymbolRef, 10> Leaked;
@@ -3910,7 +3910,7 @@ RetainCountChecker::getDeadSymbolTag(SymbolRef sym) const {
sym->dumpToStream(out);
tag = new CheckerProgramPointTag(this, out.str());
}
- return tag;
+ return tag;
}
void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper,
@@ -3993,7 +3993,9 @@ void ento::registerRetainCountChecker(CheckerManager &Mgr) {
// Implementation of the CallEffects API.
//===----------------------------------------------------------------------===//
-namespace clang { namespace ento { namespace objc_retain {
+namespace clang {
+namespace ento {
+namespace objc_retain {
// This is a bit gross, but it allows us to populate CallEffects without
// creating a bunch of accessors. This kind is very localized, so the
@@ -4022,4 +4024,6 @@ CallEffects CallEffects::getEffect(const FunctionDecl *FD) {
#undef createCallEffect
-}}}
+} // end namespace objc_retain
+} // end namespace ento
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
index acbd0d9..19fa0fb 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
@@ -23,7 +23,7 @@ using namespace clang;
using namespace ento;
namespace {
-class ReturnPointerRangeChecker :
+class ReturnPointerRangeChecker :
public Checker< check::PreStmt<ReturnStmt> > {
mutable std::unique_ptr<BuiltinBug> BT;
@@ -39,7 +39,7 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
const Expr *RetE = RS->getRetValue();
if (!RetE)
return;
-
+
SVal V = state->getSVal(RetE, C.getLocationContext());
const MemRegion *R = V.getAsRegion();
@@ -62,11 +62,11 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false);
if (StOutBound && !StInBound) {
- ExplodedNode *N = C.generateSink(StOutBound);
+ ExplodedNode *N = C.generateErrorNode(StOutBound);
if (!N)
return;
-
+
// FIXME: This bug correspond to CWE-466. Eventually we should have bug
// types explicitly reference such exploit categories (when applicable).
if (!BT)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
index 2668ac1..c5e826a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
@@ -80,7 +80,7 @@ void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS,
static void emitBug(CheckerContext &C, BuiltinBug &BT, const Expr *RetE,
const Expr *TrackingE = nullptr) {
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
index c22e78b..7026a2e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
@@ -92,7 +92,7 @@ public:
REGISTER_MAP_WITH_PROGRAMSTATE(StreamMap, SymbolRef, StreamState)
namespace {
-class StopTrackingCallback : public SymbolVisitor {
+class StopTrackingCallback final : public SymbolVisitor {
ProgramStateRef state;
public:
StopTrackingCallback(ProgramStateRef st) : state(st) {}
@@ -200,7 +200,9 @@ void SimpleStreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
State = State->remove<StreamMap>(Sym);
}
- ExplodedNode *N = C.addTransition(State);
+ ExplodedNode *N = C.generateNonFatalErrorNode(State);
+ if (!N)
+ return;
reportLeaks(LeakedStreams, C, N);
}
@@ -208,7 +210,7 @@ void SimpleStreamChecker::reportDoubleClose(SymbolRef FileDescSym,
const CallEvent &Call,
CheckerContext &C) const {
// We reached a bug, stop exploring the path here by generating a sink.
- ExplodedNode *ErrNode = C.generateSink();
+ ExplodedNode *ErrNode = C.generateErrorNode();
// If we've already reached this node on another path, return.
if (!ErrNode)
return;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index 813c811..79fc701 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines stack address leak checker, which checks if an invalid
+// This file defines stack address leak checker, which checks if an invalid
// stack address is stored into a global or heap location. See CERT DCL30-C.
//
//===----------------------------------------------------------------------===//
@@ -49,20 +49,20 @@ SourceRange StackAddrEscapeChecker::genName(raw_ostream &os, const MemRegion *R,
SourceManager &SM = Ctx.getSourceManager();
SourceRange range;
os << "Address of ";
-
+
// Check if the region is a compound literal.
- if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) {
+ if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) {
const CompoundLiteralExpr *CL = CR->getLiteralExpr();
os << "stack memory associated with a compound literal "
"declared on line "
<< SM.getExpansionLineNumber(CL->getLocStart())
- << " returned to caller";
+ << " returned to caller";
range = CL->getSourceRange();
}
else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) {
const Expr *ARE = AR->getExpr();
SourceLocation L = ARE->getLocStart();
- range = ARE->getSourceRange();
+ range = ARE->getSourceRange();
os << "stack memory allocated by call to alloca() on line "
<< SM.getExpansionLineNumber(L);
}
@@ -87,14 +87,14 @@ SourceRange StackAddrEscapeChecker::genName(raw_ostream &os, const MemRegion *R,
}
else {
llvm_unreachable("Invalid region in ReturnStackAddressChecker.");
- }
-
+ }
+
return range;
}
void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
const Expr *RetE) const {
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
@@ -118,7 +118,7 @@ void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *
void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
CheckerContext &C) const {
-
+
const Expr *RetE = RS->getRetValue();
if (!RetE)
return;
@@ -130,10 +130,10 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
if (!R)
return;
-
+
const StackSpaceRegion *SS =
dyn_cast_or_null<StackSpaceRegion>(R->getMemorySpace());
-
+
if (!SS)
return;
@@ -156,6 +156,15 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
if (isa<CXXConstructExpr>(RetE) && RetE->getType()->isRecordType())
return;
+ // The CK_CopyAndAutoreleaseBlockObject cast causes the block to be copied
+ // so the stack address is not escaping here.
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(RetE)) {
+ if (isa<BlockDataRegion>(R) &&
+ ICE->getCastKind() == CK_CopyAndAutoreleaseBlockObject) {
+ return;
+ }
+ }
+
EmitStackError(C, R, RetE);
}
@@ -175,35 +184,35 @@ void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const {
Ctx(CC),
CurSFC(CC.getLocationContext()->getCurrentStackFrame())
{}
-
+
bool HandleBinding(StoreManager &SMgr, Store store,
const MemRegion *region, SVal val) override {
if (!isa<GlobalsSpaceRegion>(region->getMemorySpace()))
return true;
-
+
const MemRegion *vR = val.getAsRegion();
if (!vR)
return true;
-
+
// Under automated retain release, it is okay to assign a block
// directly to a global variable.
if (Ctx.getASTContext().getLangOpts().ObjCAutoRefCount &&
isa<BlockDataRegion>(vR))
return true;
- if (const StackSpaceRegion *SSR =
+ if (const StackSpaceRegion *SSR =
dyn_cast<StackSpaceRegion>(vR->getMemorySpace())) {
// If the global variable holds a location in the current stack frame,
// record the binding to emit a warning.
if (SSR->getStackFrame() == CurSFC)
V.push_back(std::make_pair(region, vR));
}
-
+
return true;
}
};
-
+
CallBack cb(Ctx);
state->getStateManager().getStoreManager().iterBindings(state->getStore(),cb);
@@ -211,7 +220,7 @@ void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const {
return;
// Generate an error node.
- ExplodedNode *N = Ctx.addTransition(state);
+ ExplodedNode *N = Ctx.generateNonFatalErrorNode(state);
if (!N)
return;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 2109a75..82b01fe 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -43,8 +43,8 @@ struct StreamState {
static StreamState getOpened(const Stmt *s) { return StreamState(Opened, s); }
static StreamState getClosed(const Stmt *s) { return StreamState(Closed, s); }
- static StreamState getOpenFailed(const Stmt *s) {
- return StreamState(OpenFailed, s);
+ static StreamState getOpenFailed(const Stmt *s) {
+ return StreamState(OpenFailed, s);
}
static StreamState getEscaped(const Stmt *s) {
return StreamState(Escaped, s);
@@ -59,14 +59,14 @@ struct StreamState {
class StreamChecker : public Checker<eval::Call,
check::DeadSymbols > {
mutable IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread,
- *II_fwrite,
- *II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos,
+ *II_fwrite,
+ *II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos,
*II_clearerr, *II_feof, *II_ferror, *II_fileno;
mutable std::unique_ptr<BuiltinBug> BT_nullfp, BT_illegalwhence,
BT_doubleclose, BT_ResourceLeak;
public:
- StreamChecker()
+ StreamChecker()
: II_fopen(nullptr), II_tmpfile(nullptr), II_fclose(nullptr),
II_fread(nullptr), II_fwrite(nullptr), II_fseek(nullptr),
II_ftell(nullptr), II_rewind(nullptr), II_fgetpos(nullptr),
@@ -93,10 +93,10 @@ private:
void Fileno(CheckerContext &C, const CallExpr *CE) const;
void OpenFileAux(CheckerContext &C, const CallExpr *CE) const;
-
- ProgramStateRef CheckNullStream(SVal SV, ProgramStateRef state,
+
+ ProgramStateRef CheckNullStream(SVal SV, ProgramStateRef state,
CheckerContext &C) const;
- ProgramStateRef CheckDoubleClose(const CallExpr *CE, ProgramStateRef state,
+ ProgramStateRef CheckDoubleClose(const CallExpr *CE, ProgramStateRef state,
CheckerContext &C) const;
};
@@ -216,13 +216,13 @@ void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const {
C.blockCount())
.castAs<DefinedSVal>();
state = state->BindExpr(CE, C.getLocationContext(), RetVal);
-
+
ConstraintManager &CM = C.getConstraintManager();
// Bifurcate the state into two: one with a valid FILE* pointer, the other
// with a NULL.
ProgramStateRef stateNotNull, stateNull;
std::tie(stateNotNull, stateNull) = CM.assumeDual(state, RetVal);
-
+
if (SymbolRef Sym = RetVal.getAsSymbol()) {
// if RetVal is not NULL, set the symbol's state to Opened.
stateNotNull =
@@ -271,7 +271,7 @@ void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
if (x >= 0 && x <= 2)
return;
- if (ExplodedNode *N = C.addTransition(state)) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
if (!BT_illegalwhence)
BT_illegalwhence.reset(
new BuiltinBug(this, "Illegal whence argument",
@@ -349,7 +349,7 @@ ProgramStateRef StreamChecker::CheckNullStream(SVal SV, ProgramStateRef state,
std::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
if (!stateNotNull && stateNull) {
- if (ExplodedNode *N = C.generateSink(stateNull)) {
+ if (ExplodedNode *N = C.generateErrorNode(stateNull)) {
if (!BT_nullfp)
BT_nullfp.reset(new BuiltinBug(this, "NULL stream pointer",
"Stream pointer might be NULL."));
@@ -368,17 +368,17 @@ ProgramStateRef StreamChecker::CheckDoubleClose(const CallExpr *CE,
state->getSVal(CE->getArg(0), C.getLocationContext()).getAsSymbol();
if (!Sym)
return state;
-
+
const StreamState *SS = state->get<StreamMap>(Sym);
// If the file stream is not tracked, return.
if (!SS)
return state;
-
+
// Check: Double close a File Descriptor could cause undefined behaviour.
// Conforming to man-pages
if (SS->isClosed()) {
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (N) {
if (!BT_doubleclose)
BT_doubleclose.reset(new BuiltinBug(
@@ -389,7 +389,7 @@ ProgramStateRef StreamChecker::CheckDoubleClose(const CallExpr *CE,
}
return nullptr;
}
-
+
// Close the File Descriptor.
return state->set<StreamMap>(Sym, StreamState::getClosed(CE));
}
@@ -406,7 +406,7 @@ void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
continue;
if (SS->isOpened()) {
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (N) {
if (!BT_ResourceLeak)
BT_ResourceLeak.reset(new BuiltinBug(
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
index 6e24775..2e05290 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
@@ -48,7 +48,7 @@ void TaintTesterChecker::checkPostStmt(const Expr *E,
return;
if (State->isTainted(E, C.getLocationContext())) {
- if (ExplodedNode *N = C.addTransition()) {
+ if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
initBugType();
auto report = llvm::make_unique<BugReport>(*BT, "tainted",N);
report->addRange(E->getSourceRange());
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
index 638701d..b794d2f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
@@ -167,7 +167,7 @@ bool TestAfterDivZeroChecker::hasDivZeroMap(SVal Var,
}
void TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const {
- if (ExplodedNode *N = C.generateSink(C.getState())) {
+ if (ExplodedNode *N = C.generateErrorNode(C.getState())) {
if (!DivZeroBug)
DivZeroBug.reset(new BuiltinBug(this, "Division by zero"));
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
index 1d8ef99..ed17610 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -30,7 +30,7 @@ class UndefBranchChecker : public Checker<check::BranchCondition> {
ProgramStateRef St;
const LocationContext *LCtx;
- FindUndefExpr(ProgramStateRef S, const LocationContext *L)
+ FindUndefExpr(ProgramStateRef S, const LocationContext *L)
: St(S), LCtx(L) {}
const Expr *FindExpr(const Expr *Ex) {
@@ -45,7 +45,7 @@ class UndefBranchChecker : public Checker<check::BranchCondition> {
return Ex;
}
- bool MatchesCriteria(const Expr *Ex) {
+ bool MatchesCriteria(const Expr *Ex) {
return St->getSVal(Ex, LCtx).isUndef();
}
};
@@ -62,7 +62,7 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
if (X.isUndef()) {
// Generate a sink node, which implicitly marks both outgoing branches as
// infeasible.
- ExplodedNode *N = Ctx.generateSink();
+ ExplodedNode *N = Ctx.generateErrorNode();
if (N) {
if (!BT)
BT.reset(new BuiltinBug(
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
index 53fd069..17fe861 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -74,7 +74,7 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
// Get the VarRegion associated with VD in the local stack frame.
if (Optional<UndefinedVal> V =
state->getSVal(I.getOriginalRegion()).getAs<UndefinedVal>()) {
- if (ExplodedNode *N = C.generateSink()) {
+ if (ExplodedNode *N = C.generateErrorNode()) {
if (!BT)
BT.reset(
new BuiltinBug(this, "uninitialized variable captured by block"));
@@ -83,7 +83,7 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
SmallString<128> buf;
llvm::raw_svector_ostream os(buf);
- os << "Variable '" << VD->getName()
+ os << "Variable '" << VD->getName()
<< "' is uninitialized when captured by block";
auto R = llvm::make_unique<BugReport>(*BT, os.str(), N);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
index 5353310..38d2aa6 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This defines UndefResultChecker, a builtin check in ExprEngine that
+// This defines UndefResultChecker, a builtin check in ExprEngine that
// performs checks for undefined results of non-assignment binary operators.
//
//===----------------------------------------------------------------------===//
@@ -25,7 +25,7 @@ using namespace clang;
using namespace ento;
namespace {
-class UndefResultChecker
+class UndefResultChecker
: public Checker< check::PostStmt<BinaryOperator> > {
mutable std::unique_ptr<BugType> BT;
@@ -50,10 +50,10 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
return;
// Generate an error node.
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
-
+
if (!BT)
BT.reset(
new BuiltinBug(this, "Result of operation is garbage or undefined"));
@@ -62,7 +62,7 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
llvm::raw_svector_ostream OS(sbuf);
const Expr *Ex = nullptr;
bool isLeft = true;
-
+
if (state->getSVal(B->getLHS(), LCtx).isUndef()) {
Ex = B->getLHS()->IgnoreParenCasts();
isLeft = true;
@@ -71,13 +71,13 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
Ex = B->getRHS()->IgnoreParenCasts();
isLeft = false;
}
-
+
if (Ex) {
OS << "The " << (isLeft ? "left" : "right")
<< " operand of '"
<< BinaryOperator::getOpcodeStr(B->getOpcode())
<< "' is a garbage value";
- }
+ }
else {
// Neither operand was undefined, but the result is undefined.
OS << "The result of the '"
@@ -91,7 +91,7 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
}
else
bugreporter::trackNullOrUndefValue(N, B, *report);
-
+
C.emitReport(std::move(report));
}
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
index ba4daf8..fe07eaf 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
@@ -32,7 +32,7 @@ public:
};
} // end anonymous namespace
-void
+void
UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
CheckerContext &C) const {
const Expr *Index = A->getIdx();
@@ -46,7 +46,7 @@ UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
if (Ctor->isDefaulted())
return;
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
if (!BT)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
index 81c96c4..7a31efc 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
@@ -46,7 +46,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
if (C.getCalleeName(EnclosingFunctionDecl) == "swap")
return;
- ExplodedNode *N = C.generateSink();
+ ExplodedNode *N = C.generateErrorNode();
if (!N)
return;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index a799b4c..4b78c20 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -77,7 +77,7 @@ void UnixAPIChecker::ReportOpenBug(CheckerContext &C,
ProgramStateRef State,
const char *Msg,
SourceRange SR) const {
- ExplodedNode *N = C.generateSink(State);
+ ExplodedNode *N = C.generateErrorNode(State);
if (!N)
return;
@@ -114,7 +114,7 @@ void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
// The definition of O_CREAT is platform specific. We need a better way
// of querying this information from the checking environment.
if (!Val_O_CREAT.hasValue()) {
- if (C.getASTContext().getTargetInfo().getTriple().getVendor()
+ if (C.getASTContext().getTargetInfo().getTriple().getVendor()
== llvm::Triple::Apple)
Val_O_CREAT = 0x0200;
else {
@@ -182,7 +182,7 @@ void UnixAPIChecker::CheckPthreadOnce(CheckerContext &C,
if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
return;
- ExplodedNode *N = C.generateSink(state);
+ ExplodedNode *N = C.generateErrorNode(state);
if (!N)
return;
@@ -220,7 +220,7 @@ static bool IsZeroByteAllocation(ProgramStateRef state,
ProgramStateRef *falseState) {
std::tie(*trueState, *falseState) =
state->assume(argVal.castAs<DefinedSVal>());
-
+
return (*falseState && !*trueState);
}
@@ -231,7 +231,7 @@ bool UnixAPIChecker::ReportZeroByteAllocation(CheckerContext &C,
ProgramStateRef falseState,
const Expr *arg,
const char *fn_name) const {
- ExplodedNode *N = C.generateSink(falseState);
+ ExplodedNode *N = C.generateErrorNode(falseState);
if (!N)
return false;
@@ -239,7 +239,7 @@ bool UnixAPIChecker::ReportZeroByteAllocation(CheckerContext &C,
"Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)");
SmallString<256> S;
- llvm::raw_svector_ostream os(S);
+ llvm::raw_svector_ostream os(S);
os << "Call to '" << fn_name << "' has an allocation size of 0 bytes";
auto report = llvm::make_unique<BugReport>(*BT_mallocZero, os.str(), N);
@@ -272,13 +272,13 @@ void UnixAPIChecker::BasicAllocationCheck(CheckerContext &C,
// Is the value perfectly constrained to zero?
if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
- (void) ReportZeroByteAllocation(C, falseState, arg, fn);
+ (void) ReportZeroByteAllocation(C, falseState, arg, fn);
return;
}
// Assume the value is non-zero going forward.
assert(trueState);
if (trueState != state)
- C.addTransition(trueState);
+ C.addTransition(trueState);
}
void UnixAPIChecker::CheckCallocZero(CheckerContext &C,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
index d78de3c..a03abce 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -54,7 +54,7 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
BugReporter &B,
ExprEngine &Eng) const {
CFGBlocksSet reachable, visited;
-
+
if (Eng.hasWorkRemaining())
return;
@@ -88,7 +88,7 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
// Bail out if we didn't get the CFG or the ParentMap.
if (!D || !C || !PM)
return;
-
+
// Don't do anything for template instantiations. Proving that code
// in a template instantiation is unreachable means proving that it is
// unreachable in all instantiations.
@@ -235,12 +235,9 @@ bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB,
return false;
// Run each of the checks on the conditions
- if (containsMacro(cond) || containsEnum(cond)
- || containsStaticLocal(cond) || containsBuiltinOffsetOf(cond)
- || containsStmt<UnaryExprOrTypeTraitExpr>(cond))
- return true;
-
- return false;
+ return containsMacro(cond) || containsEnum(cond) ||
+ containsStaticLocal(cond) || containsBuiltinOffsetOf(cond) ||
+ containsStmt<UnaryExprOrTypeTraitExpr>(cond);
}
// Returns true if the given CFGBlock is empty
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
index 80384bb..e3b2ed2 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This defines VLASizeChecker, a builtin check in ExprEngine that
+// This defines VLASizeChecker, a builtin check in ExprEngine that
// performs checks for declaration of VLA of undefined or zero size.
// In addition, VLASizeChecker is responsible for defining the extent
// of the MemRegion that represents a VLA.
@@ -46,7 +46,7 @@ void VLASizeChecker::reportBug(VLASize_Kind Kind,
ProgramStateRef State,
CheckerContext &C) const {
// Generate an error node.
- ExplodedNode *N = C.generateSink(State);
+ ExplodedNode *N = C.generateErrorNode(State);
if (!N)
return;
@@ -82,7 +82,7 @@ void VLASizeChecker::reportBug(VLASize_Kind Kind,
void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
if (!DS->isSingleDecl())
return;
-
+
const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
if (!VD)
return;
@@ -106,7 +106,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
// warned about that already.
if (sizeV.isUnknown())
return;
-
+
// Check if the size is tainted.
if (state->isTainted(sizeV)) {
reportBug(VLA_Tainted, SE, nullptr, C);
@@ -123,7 +123,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
reportBug(VLA_Zero, SE, stateZero, C);
return;
}
-
+
// From this point on, assume that the size is not zero.
state = stateNotZero;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp
new file mode 100644
index 0000000..26ffee8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp
@@ -0,0 +1,218 @@
+//===- VforkChecker.cpp -------- Vfork usage checks --------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines vfork checker which checks for dangerous uses of vfork.
+// Vforked process shares memory (including stack) with parent so it's
+// range of actions is significantly limited: can't write variables,
+// can't call functions not in whitelist, etc. For more details, see
+// http://man7.org/linux/man-pages/man2/vfork.2.html
+//
+// This checker checks for prohibited constructs in vforked process.
+// The state transition diagram:
+// PARENT ---(vfork() == 0)--> CHILD
+// |
+// --(*p = ...)--> bug
+// |
+// --foo()--> bug
+// |
+// --return--> bug
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/AST/ParentMap.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class VforkChecker : public Checker<check::PreCall, check::PostCall,
+ check::Bind, check::PreStmt<ReturnStmt>> {
+ mutable std::unique_ptr<BuiltinBug> BT;
+ mutable llvm::SmallSet<const IdentifierInfo *, 10> VforkWhitelist;
+ mutable const IdentifierInfo *II_vfork;
+
+ static bool isChildProcess(const ProgramStateRef State);
+
+ bool isVforkCall(const Decl *D, CheckerContext &C) const;
+ bool isCallWhitelisted(const IdentifierInfo *II, CheckerContext &C) const;
+
+ void reportBug(const char *What, CheckerContext &C,
+ const char *Details = 0) const;
+
+public:
+ VforkChecker() : II_vfork(0) {}
+
+ void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+ void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
+ void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
+};
+
+} // end anonymous namespace
+
+// This trait holds region of variable that is assigned with vfork's
+// return value (this is the only region child is allowed to write).
+// VFORK_RESULT_INVALID means that we are in parent process.
+// VFORK_RESULT_NONE means that vfork's return value hasn't been assigned.
+// Other values point to valid regions.
+REGISTER_TRAIT_WITH_PROGRAMSTATE(VforkResultRegion, const void *)
+#define VFORK_RESULT_INVALID 0
+#define VFORK_RESULT_NONE ((void *)(uintptr_t)1)
+
+bool VforkChecker::isChildProcess(const ProgramStateRef State) {
+ return State->get<VforkResultRegion>() != VFORK_RESULT_INVALID;
+}
+
+bool VforkChecker::isVforkCall(const Decl *D, CheckerContext &C) const {
+ auto FD = dyn_cast_or_null<FunctionDecl>(D);
+ if (!FD || !C.isCLibraryFunction(FD))
+ return false;
+
+ if (!II_vfork) {
+ ASTContext &AC = C.getASTContext();
+ II_vfork = &AC.Idents.get("vfork");
+ }
+
+ return FD->getIdentifier() == II_vfork;
+}
+
+// Returns true iff ok to call function after successful vfork.
+bool VforkChecker::isCallWhitelisted(const IdentifierInfo *II,
+ CheckerContext &C) const {
+ if (VforkWhitelist.empty()) {
+ // According to manpage.
+ const char *ids[] = {
+ "_exit",
+ "_Exit",
+ "execl",
+ "execlp",
+ "execle",
+ "execv",
+ "execvp",
+ "execvpe",
+ 0,
+ };
+
+ ASTContext &AC = C.getASTContext();
+ for (const char **id = ids; *id; ++id)
+ VforkWhitelist.insert(&AC.Idents.get(*id));
+ }
+
+ return VforkWhitelist.count(II);
+}
+
+void VforkChecker::reportBug(const char *What, CheckerContext &C,
+ const char *Details) const {
+ if (ExplodedNode *N = C.generateErrorNode(C.getState())) {
+ if (!BT)
+ BT.reset(new BuiltinBug(this,
+ "Dangerous construct in a vforked process"));
+
+ SmallString<256> buf;
+ llvm::raw_svector_ostream os(buf);
+
+ os << What << " is prohibited after a successful vfork";
+
+ if (Details)
+ os << "; " << Details;
+
+ auto Report = llvm::make_unique<BugReport>(*BT, os.str(), N);
+ // TODO: mark vfork call in BugReportVisitor
+ C.emitReport(std::move(Report));
+ }
+}
+
+// Detect calls to vfork and split execution appropriately.
+void VforkChecker::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ // We can't call vfork in child so don't bother
+ // (corresponding warning has already been emitted in checkPreCall).
+ ProgramStateRef State = C.getState();
+ if (isChildProcess(State))
+ return;
+
+ if (!isVforkCall(Call.getDecl(), C))
+ return;
+
+ // Get return value of vfork.
+ SVal VforkRetVal = Call.getReturnValue();
+ Optional<DefinedOrUnknownSVal> DVal =
+ VforkRetVal.getAs<DefinedOrUnknownSVal>();
+ if (!DVal)
+ return;
+
+ // Get assigned variable.
+ const ParentMap &PM = C.getLocationContext()->getParentMap();
+ const Stmt *P = PM.getParentIgnoreParenCasts(Call.getOriginExpr());
+ const VarDecl *LhsDecl;
+ std::tie(LhsDecl, std::ignore) = parseAssignment(P);
+
+ // Get assigned memory region.
+ MemRegionManager &M = C.getStoreManager().getRegionManager();
+ const MemRegion *LhsDeclReg =
+ LhsDecl
+ ? M.getVarRegion(LhsDecl, C.getLocationContext())
+ : (const MemRegion *)VFORK_RESULT_NONE;
+
+ // Parent branch gets nonzero return value (according to manpage).
+ ProgramStateRef ParentState, ChildState;
+ std::tie(ParentState, ChildState) = C.getState()->assume(*DVal);
+ C.addTransition(ParentState);
+ ChildState = ChildState->set<VforkResultRegion>(LhsDeclReg);
+ C.addTransition(ChildState);
+}
+
+// Prohibit calls to non-whitelist functions in child process.
+void VforkChecker::checkPreCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ if (isChildProcess(State)
+ && !isCallWhitelisted(Call.getCalleeIdentifier(), C))
+ reportBug("This function call", C);
+}
+
+// Prohibit writes in child process (except for vfork's lhs).
+void VforkChecker::checkBind(SVal L, SVal V, const Stmt *S,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ if (!isChildProcess(State))
+ return;
+
+ const MemRegion *VforkLhs =
+ static_cast<const MemRegion *>(State->get<VforkResultRegion>());
+ const MemRegion *MR = L.getAsRegion();
+
+ // Child is allowed to modify only vfork's lhs.
+ if (!MR || MR == VforkLhs)
+ return;
+
+ reportBug("This assignment", C);
+}
+
+// Prohibit return from function in child process.
+void VforkChecker::checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ if (isChildProcess(State))
+ reportBug("Return", C, "call _exit() instead");
+}
+
+void ento::registerVforkChecker(CheckerManager &mgr) {
+ mgr.registerChecker<VforkChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
index f6ef4ae..55025030 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines a checker that checks virtual function calls during
+// This file defines a checker that checks virtual function calls during
// construction or destruction of C++ objects.
//
//===----------------------------------------------------------------------===//
@@ -37,13 +37,13 @@ class WalkAST : public StmtVisitor<WalkAST> {
/// A vector representing the worklist which has a chain of CallExprs.
DFSWorkList WList;
-
+
// PreVisited : A CallExpr to this FunctionDecl is in the worklist, but the
// body has not been visited yet.
// PostVisited : A CallExpr to this FunctionDecl is in the worklist, and the
// body has been visited.
enum Kind { NotVisited,
- PreVisited, /**< A CallExpr to this FunctionDecl is in the
+ PreVisited, /**< A CallExpr to this FunctionDecl is in the
worklist, but the body has not yet been
visited. */
PostVisited /**< A CallExpr to this FunctionDecl is in the
@@ -57,7 +57,7 @@ class WalkAST : public StmtVisitor<WalkAST> {
/// generating bug reports. This is null while visiting the body of a
/// constructor or destructor.
const CallExpr *visitingCallExpr;
-
+
public:
WalkAST(const CheckerBase *checker, BugReporter &br,
AnalysisDeclContext *ac)
@@ -70,7 +70,7 @@ public:
void Enqueue(WorkListUnit WLUnit) {
const FunctionDecl *FD = WLUnit->getDirectCallee();
if (!FD || !FD->getBody())
- return;
+ return;
Kind &K = VisitedFunctions[FD];
if (K != NotVisited)
return;
@@ -81,9 +81,9 @@ public:
/// This method returns an item from the worklist without removing it.
WorkListUnit Dequeue() {
assert(!WList.empty());
- return WList.back();
+ return WList.back();
}
-
+
void Execute() {
while (hasWork()) {
WorkListUnit WLUnit = Dequeue();
@@ -95,7 +95,7 @@ public:
// Visit the body.
SaveAndRestore<const CallExpr *> SaveCall(visitingCallExpr, WLUnit);
Visit(FD->getBody());
-
+
// Mark the function as being PostVisited to indicate we have
// scanned the body.
VisitedFunctions[FD] = PostVisited;
@@ -114,7 +114,7 @@ public:
void VisitCXXMemberCallExpr(CallExpr *CE);
void VisitStmt(Stmt *S) { VisitChildren(S); }
void VisitChildren(Stmt *S);
-
+
void ReportVirtualCall(const CallExpr *CE, bool isPure);
};
@@ -138,7 +138,7 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
void WalkAST::VisitCXXMemberCallExpr(CallExpr *CE) {
VisitChildren(CE);
bool callIsNonVirtual = false;
-
+
// Several situations to elide for checking.
if (MemberExpr *CME = dyn_cast<MemberExpr>(CE->getCallee())) {
// If the member access is fully qualified (i.e., X::F), then treat
@@ -170,7 +170,7 @@ void WalkAST::VisitCXXMemberCallExpr(CallExpr *CE) {
void WalkAST::ReportVirtualCall(const CallExpr *CE, bool isPure) {
SmallString<100> buf;
llvm::raw_svector_ostream os(buf);
-
+
os << "Call Path : ";
// Name of current visiting CallExpr.
os << *CE->getDirectCallee();
@@ -190,7 +190,7 @@ void WalkAST::ReportVirtualCall(const CallExpr *CE, bool isPure) {
PathDiagnosticLocation CELoc =
PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
SourceRange R = CE->getCallee()->getSourceRange();
-
+
if (isPure) {
os << "\n" << "Call pure virtual functions during construction or "
<< "destruction may leads undefined behaviour";
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
index 5798f01..54634fd 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -18,7 +18,7 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
const LangOptions &lang,
const PathDiagnosticConsumers &PDC,
StoreManagerCreator storemgr,
- ConstraintManagerCreator constraintmgr,
+ ConstraintManagerCreator constraintmgr,
CheckerManager *checkerMgr,
AnalyzerOptions &Options,
CodeInjector *injector)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 1696bcf..54c668c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -65,7 +65,7 @@ IPAKind AnalyzerOptions::getIPAMode() {
// Set the member variable.
IPAMode = IPAConfig;
}
-
+
return IPAMode;
}
@@ -295,6 +295,13 @@ unsigned AnalyzerOptions::getMaxTimesInlineLarge() {
return MaxTimesInlineLarge.getValue();
}
+unsigned AnalyzerOptions::getMinCFGSizeTreatFunctionsAsLarge() {
+ if (!MinCFGSizeTreatFunctionsAsLarge.hasValue())
+ MinCFGSizeTreatFunctionsAsLarge = getOptionAsInteger(
+ "min-cfg-size-treat-functions-as-large", 14);
+ return MinCFGSizeTreatFunctionsAsLarge.getValue();
+}
+
unsigned AnalyzerOptions::getMaxNodesPerTopLevelFunction() {
if (!MaxNodesPerTopLevelFunction.hasValue()) {
int DefaultValue = 0;
@@ -325,3 +332,15 @@ bool AnalyzerOptions::shouldPrunePaths() {
bool AnalyzerOptions::shouldConditionalizeStaticInitializers() {
return getBooleanOption("cfg-conditional-static-initializers", true);
}
+
+bool AnalyzerOptions::shouldInlineLambdas() {
+ if (!InlineLambdas.hasValue())
+ InlineLambdas = getBooleanOption("inline-lambdas", /*Default=*/true);
+ return InlineLambdas.getValue();
+}
+
+bool AnalyzerOptions::shouldWidenLoops() {
+ if (!WidenLoops.hasValue())
+ WidenLoops = getBooleanOption("widen-loops", /*Default=*/false);
+ return WidenLoops.getValue();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BlockCounter.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BlockCounter.cpp
index c1ac03d..8c99bd8 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BlockCounter.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BlockCounter.cpp
@@ -26,7 +26,7 @@ class CountKey {
unsigned BlockID;
public:
- CountKey(const StackFrameContext *CS, unsigned ID)
+ CountKey(const StackFrameContext *CS, unsigned ID)
: CallSite(CS), BlockID(ID) {}
bool operator==(const CountKey &RHS) const {
@@ -55,7 +55,7 @@ static inline CountMap::Factory& GetFactory(void *F) {
return *static_cast<CountMap::Factory*>(F);
}
-unsigned BlockCounter::getNumVisited(const StackFrameContext *CallSite,
+unsigned BlockCounter::getNumVisited(const StackFrameContext *CallSite,
unsigned BlockID) const {
CountMap M = GetMap(Data);
CountMap::data_type* T = M.lookup(CountKey(CallSite, BlockID));
@@ -71,10 +71,10 @@ BlockCounter::Factory::~Factory() {
}
BlockCounter
-BlockCounter::Factory::IncrementCount(BlockCounter BC,
+BlockCounter::Factory::IncrementCount(BlockCounter BC,
const StackFrameContext *CallSite,
unsigned BlockID) {
- return BlockCounter(GetFactory(F).add(GetMap(BC.Data),
+ return BlockCounter(GetFactory(F).add(GetMap(BC.Data),
CountKey(CallSite, BlockID),
BC.getNumVisited(CallSite, BlockID)+1).getRoot());
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index e4db64f..11be764 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -81,13 +81,13 @@ eventsDescribeSameCondition(PathDiagnosticEventPiece *X,
// those that came from TrackConstraintBRVisitor.
const void *tagPreferred = ConditionBRVisitor::getTag();
const void *tagLesser = TrackConstraintBRVisitor::getTag();
-
+
if (X->getLocation() != Y->getLocation())
return nullptr;
if (X->getTag() == tagPreferred && Y->getTag() == tagLesser)
return X;
-
+
if (Y->getTag() == tagPreferred && X->getTag() == tagLesser)
return Y;
@@ -110,7 +110,7 @@ static void removeRedundantMsgs(PathPieces &path) {
for (unsigned i = 0; i < N; ++i) {
IntrusiveRefCntPtr<PathDiagnosticPiece> piece(path.front());
path.pop_front();
-
+
switch (piece->getKind()) {
case clang::ento::PathDiagnosticPiece::Call:
removeRedundantMsgs(cast<PathDiagnosticCallPiece>(piece)->path);
@@ -123,7 +123,7 @@ static void removeRedundantMsgs(PathPieces &path) {
case clang::ento::PathDiagnosticPiece::Event: {
if (i == N-1)
break;
-
+
if (PathDiagnosticEventPiece *nextEvent =
dyn_cast<PathDiagnosticEventPiece>(path.front().get())) {
PathDiagnosticEventPiece *event =
@@ -157,13 +157,13 @@ static bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
LocationContextMap &LCM) {
bool containsSomethingInteresting = false;
const unsigned N = pieces.size();
-
+
for (unsigned i = 0 ; i < N ; ++i) {
// Remove the front piece from the path. If it is still something we
// want to keep once we are done, we will push it back on the end.
IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front());
pieces.pop_front();
-
+
switch (piece->getKind()) {
case PathDiagnosticPiece::Call: {
PathDiagnosticCallPiece *call = cast<PathDiagnosticCallPiece>(piece);
@@ -176,7 +176,7 @@ static bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
if (!removeUnneededCalls(call->path, R, LCM))
continue;
-
+
containsSomethingInteresting = true;
break;
}
@@ -189,7 +189,7 @@ static bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
}
case PathDiagnosticPiece::Event: {
PathDiagnosticEventPiece *event = cast<PathDiagnosticEventPiece>(piece);
-
+
// We never throw away an event, but we do throw it away wholesale
// as part of a path if we throw the entire path away.
containsSomethingInteresting |= !event->isPrunable();
@@ -198,10 +198,10 @@ static bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
case PathDiagnosticPiece::ControlFlow:
break;
}
-
+
pieces.push_back(piece);
}
-
+
return containsSomethingInteresting;
}
@@ -213,7 +213,7 @@ static bool hasImplicitBody(const Decl *D) {
}
/// Recursively scan through a path and make sure that all call pieces have
-/// valid locations.
+/// valid locations.
static void
adjustCallLocations(PathPieces &Pieces,
PathDiagnosticLocation *LastCallLocation = nullptr) {
@@ -323,7 +323,7 @@ class PathDiagnosticBuilder : public BugReporterContext {
NodeMapClosure NMC;
public:
const LocationContext *LC;
-
+
PathDiagnosticBuilder(GRBugReporter &br,
BugReport *r, InterExplodedGraphMap &Backmap,
PathDiagnosticConsumer *pdc)
@@ -339,7 +339,7 @@ public:
BugReport *getBugReport() { return R; }
Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); }
-
+
ParentMap& getParentMap() { return LC->getParentMap(); }
const Stmt *getParent(const Stmt *S) {
@@ -957,7 +957,7 @@ static PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L,
if (firstCharOnly)
L = PathDiagnosticLocation::createSingleLocation(L);
-
+
return L;
}
@@ -1001,7 +1001,7 @@ public:
~EdgeBuilder() {
while (!CLocs.empty()) popLocation();
-
+
// Finally, add an initial edge from the start location of the first
// statement (if it doesn't already exist).
PathDiagnosticLocation L = PathDiagnosticLocation::createDeclBegin(
@@ -1016,7 +1016,7 @@ public:
popLocation();
PrevLoc = PathDiagnosticLocation();
}
-
+
void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false,
bool IsPostJump = false);
@@ -1101,7 +1101,7 @@ void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
PrevLoc = NewLoc;
return;
}
-
+
if (NewLocClean.asLocation() == PrevLocClean.asLocation())
return;
@@ -1242,7 +1242,7 @@ static void reversePropagateIntererstingSymbols(BugReport &R,
SVal V = State->getSVal(Ex, LCtx);
if (!(R.isInteresting(V) || IE.count(Ex)))
return;
-
+
switch (Ex->getStmtClass()) {
default:
if (!isa<CastExpr>(Ex))
@@ -1260,7 +1260,7 @@ static void reversePropagateIntererstingSymbols(BugReport &R,
break;
}
}
-
+
R.markInteresting(V);
}
@@ -1275,7 +1275,7 @@ static void reversePropagateInterestingSymbols(BugReport &R,
const Stmt *CallSite = Callee->getCallSite();
if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite)) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) {
- FunctionDecl::param_const_iterator PI = FD->param_begin(),
+ FunctionDecl::param_const_iterator PI = FD->param_begin(),
PE = FD->param_end();
CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
for (; AI != AE && PI != PE; ++AI, ++PI) {
@@ -1406,7 +1406,7 @@ static bool GenerateExtensivePathDiagnostic(
N->getState().get(), Ex,
N->getLocationContext());
}
-
+
if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
const Stmt *S = CE->getCalleeContext()->getCallSite();
if (const Expr *Ex = dyn_cast_or_null<Expr>(S)) {
@@ -1414,7 +1414,7 @@ static bool GenerateExtensivePathDiagnostic(
N->getState().get(), Ex,
N->getLocationContext());
}
-
+
PathDiagnosticCallPiece *C =
PathDiagnosticCallPiece::construct(N, *CE, SM);
LCM[&C->path] = CE->getCalleeContext();
@@ -1427,7 +1427,7 @@ static bool GenerateExtensivePathDiagnostic(
CallStack.push_back(StackDiagPair(C, N));
break;
}
-
+
// Pop the call hierarchy if we are done walking the contents
// of a function call.
if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
@@ -1436,7 +1436,7 @@ static bool GenerateExtensivePathDiagnostic(
PathDiagnosticLocation pos =
PathDiagnosticLocation::createBegin(D, SM);
EB.addEdge(pos);
-
+
// Flush all locations, and pop the active path.
bool VisitedEntireCall = PD.isWithinCall();
EB.flushLocations();
@@ -1466,7 +1466,7 @@ static bool GenerateExtensivePathDiagnostic(
}
break;
}
-
+
// Note that is important that we update the LocationContext
// after looking at CallExits. CallExit basically adds an
// edge in the *caller*, so we don't want to update the LocationContext
@@ -1486,7 +1486,7 @@ static bool GenerateExtensivePathDiagnostic(
CalleeCtx, CallerCtx);
}
}
-
+
// Are we jumping to the head of a loop? Add a special diagnostic.
if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
PathDiagnosticLocation L(Loop, SM, PDB.LC);
@@ -1552,11 +1552,11 @@ static bool GenerateExtensivePathDiagnostic(
else
EB.addExtendedContext(PDB.getEnclosingStmtLocation(stmt).asStmt());
}
-
+
break;
}
-
-
+
+
} while (0);
if (!NextNode)
@@ -2410,7 +2410,7 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM,
// Trim edges on expressions that are consumed by
// the parent expression.
if (isa<Expr>(s1End) && PM.isConsumedExpr(cast<Expr>(s1End))) {
- removeEdge = true;
+ removeEdge = true;
}
// Trim edges where a lexical containment doesn't exist.
// For example:
@@ -2557,7 +2557,7 @@ BugReport::~BugReport() {
const Decl *BugReport::getDeclWithIssue() const {
if (DeclWithIssue)
return DeclWithIssue;
-
+
const ExplodedNode *N = getErrorNode();
if (!N)
return nullptr;
@@ -2579,9 +2579,7 @@ void BugReport::Profile(llvm::FoldingSetNodeID& hash) const {
hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode));
}
- for (SmallVectorImpl<SourceRange>::const_iterator I =
- Ranges.begin(), E = Ranges.end(); I != E; ++I) {
- const SourceRange range = *I;
+ for (SourceRange range : Ranges) {
if (!range.isValid())
continue;
hash.AddInteger(range.getBegin().getRawEncoding());
@@ -2714,8 +2712,7 @@ llvm::iterator_range<BugReport::ranges_iterator> BugReport::getRanges() {
if (Ranges.size() == 1 && !Ranges.begin()->isValid())
return llvm::make_range(ranges_iterator(), ranges_iterator());
- return llvm::iterator_range<BugReport::ranges_iterator>(Ranges.begin(),
- Ranges.end());
+ return llvm::make_range(Ranges.begin(), Ranges.end());
}
PathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const {
@@ -2973,14 +2970,14 @@ static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
for (PathPieces::const_iterator I = path.begin(), E = path.end();
I!=E; ++I) {
-
+
PathDiagnosticPiece *piece = I->get();
// Recursively compact calls.
if (PathDiagnosticCallPiece *call=dyn_cast<PathDiagnosticCallPiece>(piece)){
CompactPathDiagnostic(call->path, SM);
}
-
+
// Get the location of the PathDiagnosticPiece.
const FullSourceLoc Loc = piece->getLocation().asLocation();
@@ -3126,7 +3123,7 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD,
PD.resetPath();
origReportConfigToken = R->getConfigurationChangeToken();
- // Generate the very last diagnostic piece - the piece is visible before
+ // Generate the very last diagnostic piece - the piece is visible before
// the trace is expanded.
std::unique_ptr<PathDiagnosticPiece> LastPiece;
for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end();
@@ -3224,6 +3221,11 @@ void BugReporter::Register(BugType *BT) {
void BugReporter::emitReport(std::unique_ptr<BugReport> R) {
if (const ExplodedNode *E = R->getErrorNode()) {
+ // An error node must either be a sink or have a tag, otherwise
+ // it could get reclaimed before the path diagnostic is created.
+ assert((E->isSink() || E->getLocation().getTag()) &&
+ "Error node must either be a sink or have a tag");
+
const AnalysisDeclContext *DeclCtx =
E->getLocationContext()->getAnalysisDeclContext();
// The source of autosynthesized body can be handcrafted AST or a model
@@ -3234,7 +3236,7 @@ void BugReporter::emitReport(std::unique_ptr<BugReport> R) {
!DeclCtx->isBodyAutosynthesizedFromModelFile())
return;
}
-
+
bool ValidSourceLoc = R->getLocation(getSourceManager()).isValid();
assert(ValidSourceLoc);
// If we mess up in a release build, we'd still prefer to just drop the bug
@@ -3269,10 +3271,10 @@ namespace {
struct FRIEC_WLItem {
const ExplodedNode *N;
ExplodedNode::const_succ_iterator I, E;
-
+
FRIEC_WLItem(const ExplodedNode *n)
: N(n), I(N->succ_begin()), E(N->succ_end()) {}
-};
+};
}
static BugReport *
@@ -3287,11 +3289,11 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
// post-dominated by a sink, simply add all the nodes in the equivalence class
// to 'Nodes'. Any of the reports will serve as a "representative" report.
if (!BT.isSuppressOnSink()) {
- BugReport *R = I;
+ BugReport *R = &*I;
for (BugReportEquivClass::iterator I=EQ.begin(), E=EQ.end(); I!=E; ++I) {
const ExplodedNode *N = I->getErrorNode();
if (N) {
- R = I;
+ R = &*I;
bugReports.push_back(R);
}
}
@@ -3317,35 +3319,35 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
}
// No successors? By definition this nodes isn't post-dominated by a sink.
if (errorNode->succ_empty()) {
- bugReports.push_back(I);
+ bugReports.push_back(&*I);
if (!exampleReport)
- exampleReport = I;
+ exampleReport = &*I;
continue;
}
// At this point we know that 'N' is not a sink and it has at least one
- // successor. Use a DFS worklist to find a non-sink end-of-path node.
+ // successor. Use a DFS worklist to find a non-sink end-of-path node.
typedef FRIEC_WLItem WLItem;
typedef SmallVector<WLItem, 10> DFSWorkList;
llvm::DenseMap<const ExplodedNode *, unsigned> Visited;
-
+
DFSWorkList WL;
WL.push_back(errorNode);
Visited[errorNode] = 1;
-
+
while (!WL.empty()) {
WLItem &WI = WL.back();
assert(!WI.N->succ_empty());
-
+
for (; WI.I != WI.E; ++WI.I) {
- const ExplodedNode *Succ = *WI.I;
+ const ExplodedNode *Succ = *WI.I;
// End-of-path node?
if (Succ->succ_empty()) {
// If we found an end-of-path node that is not a sink.
if (!Succ->isSink()) {
- bugReports.push_back(I);
+ bugReports.push_back(&*I);
if (!exampleReport)
- exampleReport = I;
+ exampleReport = &*I;
WL.clear();
break;
}
@@ -3426,7 +3428,7 @@ void BugReporter::FlushReport(BugReport *exampleReport,
PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager());
auto piece = llvm::make_unique<PathDiagnosticEventPiece>(
L, exampleReport->getDescription());
- for (const SourceRange &Range : exampleReport->getRanges())
+ for (SourceRange Range : exampleReport->getRanges())
piece->addRange(Range);
D->setEndOfPath(std::move(piece));
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index f2915ed..cf1e0a6 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -117,7 +117,7 @@ std::unique_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
// special ranges for this report.
auto P = llvm::make_unique<PathDiagnosticEventPiece>(
L, BR.getDescription(), Ranges.begin() == Ranges.end());
- for (const SourceRange &Range : Ranges)
+ for (SourceRange Range : Ranges)
P->addRange(Range);
return std::move(P);
@@ -169,7 +169,7 @@ public:
bool InEnableNullFPSuppression) {
if (!CallEvent::isCallStmt(S))
return;
-
+
// First, find when we processed the statement.
do {
if (Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>())
@@ -192,11 +192,11 @@ public:
Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>();
if (!CEE)
return;
-
+
const StackFrameContext *CalleeContext = CEE->getCalleeContext();
if (CalleeContext->getCallSite() != S)
return;
-
+
// Check the return value.
ProgramStateRef State = Node->getState();
SVal RetVal = State->getSVal(S, Node->getLocationContext());
@@ -281,7 +281,7 @@ public:
EnableNullFPSuppression);
return nullptr;
}
-
+
// If we're returning 0, we should track where that 0 came from.
bugreporter::trackNullOrUndefValue(N, RetE, BR, /*IsArg*/ false,
EnableNullFPSuppression);
@@ -472,7 +472,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
InitE = PIP->getInitializer()->getInit();
}
}
-
+
// Otherwise, see if this is the store site:
// (1) Succ has this binding and Pred does not, i.e. this is
// where the binding first occurred.
@@ -504,7 +504,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) {
if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl());
-
+
ProgramStateManager &StateMgr = BRC.getStateManager();
CallEventManager &CallMgr = StateMgr.getCallEventManager();
@@ -681,7 +681,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
else
os << "Assigning value";
}
-
+
if (R->canPrintPretty()) {
os << " to ";
R->printPretty(os);
@@ -931,7 +931,7 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
if (!N)
return false;
}
-
+
ProgramStateRef state = N->getState();
// The message send could be nil due to the receiver being nil.
@@ -959,7 +959,7 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
assert(LVNode && "Unable to find the lvalue node.");
ProgramStateRef LVState = LVNode->getState();
SVal LVal = LVState->getSVal(Inner, LVNode->getLocationContext());
-
+
if (LVState->isNull(LVal).isConstrainedTrue()) {
// In case of C++ references, we want to differentiate between a null
// reference and reference to null pointer.
@@ -1162,11 +1162,11 @@ PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
const ExplodedNode *Prev,
BugReporterContext &BRC,
BugReport &BR) {
-
+
ProgramPoint progPoint = N->getLocation();
ProgramStateRef CurrentState = N->getState();
ProgramStateRef PrevState = Prev->getState();
-
+
// Compare the GDMs of the state, because that is where constraints
// are managed. Note that ensure that we only look at nodes that
// were generated by the analyzer engine proper, not checkers.
@@ -1177,16 +1177,16 @@ PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
// If an assumption was made on a branch, it should be caught
// here by looking at the state transition.
if (Optional<BlockEdge> BE = progPoint.getAs<BlockEdge>()) {
- const CFGBlock *srcBlk = BE->getSrc();
+ const CFGBlock *srcBlk = BE->getSrc();
if (const Stmt *term = srcBlk->getTerminator())
return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
return nullptr;
}
-
+
if (Optional<PostStmt> PS = progPoint.getAs<PostStmt>()) {
// FIXME: Assuming that BugReporter is a GRBugReporter is a layering
// violation.
- const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
+ const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
cast<GRBugReporter>(BRC.getBugReporter()).
getEngine().geteagerlyAssumeBinOpBifurcationTags();
@@ -1222,7 +1222,7 @@ ConditionBRVisitor::VisitTerminator(const Stmt *Term,
case Stmt::ConditionalOperatorClass:
Cond = cast<ConditionalOperator>(Term)->getCond();
break;
- }
+ }
assert(Cond);
assert(srcBlk->succ_size() == 2);
@@ -1236,9 +1236,9 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
BugReporterContext &BRC,
BugReport &R,
const ExplodedNode *N) {
-
+
const Expr *Ex = Cond;
-
+
while (true) {
Ex = Ex->IgnoreParenCasts();
switch (Ex->getStmtClass()) {
@@ -1294,7 +1294,7 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out,
Out << '\'';
return quotes;
}
-
+
if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
QualType OriginalTy = OriginalExpr->getType();
if (OriginalTy->isPointerType()) {
@@ -1309,11 +1309,11 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out,
return false;
}
}
-
+
Out << IL->getValue();
return false;
}
-
+
return false;
}
@@ -1324,10 +1324,10 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
BugReporterContext &BRC,
BugReport &R,
const ExplodedNode *N) {
-
+
bool shouldInvert = false;
Optional<bool> shouldPrune;
-
+
SmallString<128> LhsString, RhsString;
{
llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
@@ -1335,10 +1335,10 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
shouldPrune);
const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N,
shouldPrune);
-
- shouldInvert = !isVarLHS && isVarRHS;
+
+ shouldInvert = !isVarLHS && isVarRHS;
}
-
+
BinaryOperator::Opcode Op = BExpr->getOpcode();
if (BinaryOperator::isAssignmentOp(Op)) {
@@ -1380,7 +1380,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
default:
return nullptr;
}
-
+
switch (Op) {
case BO_EQ:
Out << "equal to ";
@@ -1392,7 +1392,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
Out << BinaryOperator::getOpcodeStr(Op) << ' ';
break;
}
-
+
Out << (shouldInvert ? LhsString : RhsString);
const LocationContext *LCtx = N->getLocationContext();
PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
@@ -1416,7 +1416,7 @@ ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
SmallString<256> buf;
llvm::raw_svector_ostream Out(buf);
Out << "Assuming " << LhsString << " is ";
-
+
QualType Ty = CondVarExpr->getType();
if (Ty->isPointerType())
@@ -1444,10 +1444,10 @@ ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
}
}
}
-
+
return event;
}
-
+
PathDiagnosticPiece *
ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
const DeclRefExpr *DR,
@@ -1462,11 +1462,11 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
SmallString<256> Buf;
llvm::raw_svector_ostream Out(Buf);
-
+
Out << "Assuming '" << VD->getDeclName() << "' is ";
-
+
QualType VDTy = VD->getType();
-
+
if (VDTy->isPointerType())
Out << (tookTrue ? "non-null" : "null");
else if (VDTy->isObjCObjectPointerType())
@@ -1480,7 +1480,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
PathDiagnosticEventPiece *event =
new PathDiagnosticEventPiece(Loc, Out.str());
-
+
const ProgramState *state = N->getState().get();
if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
if (report.isInteresting(R))
@@ -1542,6 +1542,16 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
}
}
+ // The analyzer issues a false positive when the constructor of
+ // std::__independent_bits_engine from algorithms is used.
+ if (const CXXConstructorDecl *MD = dyn_cast<CXXConstructorDecl>(D)) {
+ const CXXRecordDecl *CD = MD->getParent();
+ if (CD->getName() == "__independent_bits_engine") {
+ BR.markInvalid(getTag(), nullptr);
+ return nullptr;
+ }
+ }
+
// The analyzer issues a false positive on
// std::basic_string<uint8_t> v; v.push_back(1);
// and
@@ -1615,13 +1625,13 @@ UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N,
// Function can only change the value passed in by address.
continue;
}
-
+
// If it is a const pointer value, the function does not intend to
// change the value.
if (T->getPointeeType().isConstQualified())
continue;
- // Mark the call site (LocationContext) as interesting if the value of the
+ // Mark the call site (LocationContext) as interesting if the value of the
// argument is undefined or '0'/'NULL'.
SVal BoundVal = State->getSVal(R);
if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 8542f7d..69af09b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/ParentMap.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
@@ -49,11 +50,7 @@ QualType CallEvent::getResultType() const {
return ResultTy;
}
-static bool isCallbackArg(SVal V, QualType T) {
- // If the parameter is 0, it's harmless.
- if (V.isZeroConstant())
- return false;
-
+static bool isCallback(QualType T) {
// If a parameter is a block or a callback, assume it can modify pointer.
if (T->isBlockPointerType() ||
T->isFunctionPointerType() ||
@@ -74,32 +71,53 @@ static bool isCallbackArg(SVal V, QualType T) {
return true;
}
}
-
return false;
}
-bool CallEvent::hasNonZeroCallbackArg() const {
+static bool isVoidPointerToNonConst(QualType T) {
+ if (const PointerType *PT = T->getAs<PointerType>()) {
+ QualType PointeeTy = PT->getPointeeType();
+ if (PointeeTy.isConstQualified())
+ return false;
+ return PointeeTy->isVoidType();
+ } else
+ return false;
+}
+
+bool CallEvent::hasNonNullArgumentsWithType(bool (*Condition)(QualType)) const {
unsigned NumOfArgs = getNumArgs();
// If calling using a function pointer, assume the function does not
- // have a callback. TODO: We could check the types of the arguments here.
+ // satisfy the callback.
+ // TODO: We could check the types of the arguments here.
if (!getDecl())
return false;
unsigned Idx = 0;
for (CallEvent::param_type_iterator I = param_type_begin(),
- E = param_type_end();
+ E = param_type_end();
I != E && Idx < NumOfArgs; ++I, ++Idx) {
if (NumOfArgs <= Idx)
break;
- if (isCallbackArg(getArgSVal(Idx), *I))
+ // If the parameter is 0, it's harmless.
+ if (getArgSVal(Idx).isZeroConstant())
+ continue;
+
+ if (Condition(*I))
return true;
}
-
return false;
}
+bool CallEvent::hasNonZeroCallbackArg() const {
+ return hasNonNullArgumentsWithType(isCallback);
+}
+
+bool CallEvent::hasVoidPointerToNonConstArg() const {
+ return hasNonNullArgumentsWithType(isVoidPointerToNonConst);
+}
+
bool CallEvent::isGlobalCFunction(StringRef FunctionName) const {
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(getDecl());
if (!FD)
@@ -147,7 +165,7 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
SmallVector<SVal, 8> ValuesToInvalidate;
RegionAndSymbolInvalidationTraits ETraits;
- getExtraInvalidatedValues(ValuesToInvalidate);
+ getExtraInvalidatedValues(ValuesToInvalidate, &ETraits);
// Indexes of arguments whose values will be preserved by the call.
llvm::SmallSet<unsigned, 4> PreserveArgs;
@@ -159,7 +177,7 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
// below for efficiency.
if (PreserveArgs.count(Idx))
if (const MemRegion *MR = getArgSVal(Idx).getAsRegion())
- ETraits.setTrait(MR->StripCasts(),
+ ETraits.setTrait(MR->StripCasts(),
RegionAndSymbolInvalidationTraits::TK_PreserveContents);
// TODO: Factor this out + handle the lower level const pointers.
@@ -184,7 +202,7 @@ ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
}
const Decl *D = getDecl();
- assert(D && "Cannot get a program point without a statement or decl");
+ assert(D && "Cannot get a program point without a statement or decl");
SourceLocation Loc = getSourceRange().getBegin();
if (IsPreVisit)
@@ -265,7 +283,7 @@ QualType CallEvent::getDeclaredResultType(const Decl *D) {
return QualType();
}
-
+
llvm_unreachable("unknown callable kind");
}
@@ -325,7 +343,7 @@ void AnyFunctionCall::getInitialStackFrameContents(
}
bool AnyFunctionCall::argumentsMayEscape() const {
- if (hasNonZeroCallbackArg())
+ if (CallEvent::argumentsMayEscape() || hasVoidPointerToNonConstArg())
return true;
const FunctionDecl *D = getDecl();
@@ -336,7 +354,7 @@ bool AnyFunctionCall::argumentsMayEscape() const {
if (!II)
return false;
- // This set of "escaping" APIs is
+ // This set of "escaping" APIs is
// - 'int pthread_setspecific(ptheread_key k, const void *)' stores a
// value into thread local storage. The value can later be retrieved with
@@ -402,8 +420,30 @@ const FunctionDecl *CXXInstanceCall::getDecl() const {
return getSVal(CE->getCallee()).getAsFunctionDecl();
}
-void CXXInstanceCall::getExtraInvalidatedValues(ValueList &Values) const {
- Values.push_back(getCXXThisVal());
+void CXXInstanceCall::getExtraInvalidatedValues(
+ ValueList &Values, RegionAndSymbolInvalidationTraits *ETraits) const {
+ SVal ThisVal = getCXXThisVal();
+ Values.push_back(ThisVal);
+
+ // Don't invalidate if the method is const and there are no mutable fields.
+ if (const CXXMethodDecl *D = cast_or_null<CXXMethodDecl>(getDecl())) {
+ if (!D->isConst())
+ return;
+ // Get the record decl for the class of 'This'. D->getParent() may return a
+ // base class decl, rather than the class of the instance which needs to be
+ // checked for mutable fields.
+ const Expr *Ex = getCXXThisExpr()->ignoreParenBaseCasts();
+ const CXXRecordDecl *ParentRecord = Ex->getType()->getAsCXXRecordDecl();
+ if (!ParentRecord || ParentRecord->hasMutableFields())
+ return;
+ // Preserve CXXThis.
+ const MemRegion *ThisRegion = ThisVal.getAsRegion();
+ if (!ThisRegion)
+ return;
+
+ ETraits->setTrait(ThisRegion->getBaseRegion(),
+ RegionAndSymbolInvalidationTraits::TK_PreserveContents);
+ }
}
SVal CXXInstanceCall::getCXXThisVal() const {
@@ -435,7 +475,7 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
return RuntimeDefinition();
// Do we know anything about the type of 'this'?
- DynamicTypeInfo DynType = getState()->getDynamicTypeInfo(R);
+ DynamicTypeInfo DynType = getDynamicTypeInfo(getState(), R);
if (!DynType.isValid())
return RuntimeDefinition();
@@ -455,7 +495,7 @@ RuntimeDefinition CXXInstanceCall::getRuntimeDefinition() const {
// However, we should at least be able to search up and down our own class
// hierarchy, and some real bugs have been caught by checking this.
assert(!RD->isDerivedFrom(MD->getParent()) && "Couldn't find known method");
-
+
// FIXME: This is checking that our DynamicTypeInfo is at least as good as
// the static type. However, because we currently don't update
// DynamicTypeInfo when an object is cast, we can't actually be sure the
@@ -525,7 +565,7 @@ RuntimeDefinition CXXMemberCall::getRuntimeDefinition() const {
if (const MemberExpr *ME = dyn_cast<MemberExpr>(getOriginExpr()->getCallee()))
if (ME->hasQualifier())
return AnyFunctionCall::getRuntimeDefinition();
-
+
return CXXInstanceCall::getRuntimeDefinition();
}
@@ -549,7 +589,8 @@ ArrayRef<ParmVarDecl*> BlockCall::parameters() const {
return D->parameters();
}
-void BlockCall::getExtraInvalidatedValues(ValueList &Values) const {
+void BlockCall::getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const {
// FIXME: This also needs to invalidate captured globals.
if (const MemRegion *R = getBlockRegion())
Values.push_back(loc::MemRegionVal(R));
@@ -557,10 +598,25 @@ void BlockCall::getExtraInvalidatedValues(ValueList &Values) const {
void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
BindingsTy &Bindings) const {
- const BlockDecl *D = cast<BlockDecl>(CalleeCtx->getDecl());
SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
+ ArrayRef<ParmVarDecl*> Params;
+ if (isConversionFromLambda()) {
+ auto *LambdaOperatorDecl = cast<CXXMethodDecl>(CalleeCtx->getDecl());
+ Params = LambdaOperatorDecl->parameters();
+
+ // For blocks converted from a C++ lambda, the callee declaration is the
+ // operator() method on the lambda so we bind "this" to
+ // the lambda captured by the block.
+ const VarRegion *CapturedLambdaRegion = getRegionStoringCapturedLambda();
+ SVal ThisVal = loc::MemRegionVal(CapturedLambdaRegion);
+ Loc ThisLoc = SVB.getCXXThis(LambdaOperatorDecl, CalleeCtx);
+ Bindings.push_back(std::make_pair(ThisLoc, ThisVal));
+ } else {
+ Params = cast<BlockDecl>(CalleeCtx->getDecl())->parameters();
+ }
+
addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this,
- D->parameters());
+ Params);
}
@@ -570,7 +626,8 @@ SVal CXXConstructorCall::getCXXThisVal() const {
return UnknownVal();
}
-void CXXConstructorCall::getExtraInvalidatedValues(ValueList &Values) const {
+void CXXConstructorCall::getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const {
if (Data)
Values.push_back(loc::MemRegionVal(static_cast<const MemRegion *>(Data)));
}
@@ -612,7 +669,8 @@ ArrayRef<ParmVarDecl*> ObjCMethodCall::parameters() const {
}
void
-ObjCMethodCall::getExtraInvalidatedValues(ValueList &Values) const {
+ObjCMethodCall::getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const {
Values.push_back(getReceiverSVal());
}
@@ -628,7 +686,7 @@ SVal ObjCMethodCall::getReceiverSVal() const {
// FIXME: Is this the best way to handle class receivers?
if (!isInstanceMessage())
return UnknownVal();
-
+
if (const Expr *RecE = getOriginExpr()->getInstanceReceiver())
return getSVal(RecE);
@@ -709,7 +767,7 @@ ObjCMessageKind ObjCMethodCall::getMessageKind() const {
return K;
}
}
-
+
const_cast<ObjCMethodCall *>(this)->Data
= ObjCMessageDataTy(nullptr, 1).getOpaqueValue();
assert(getMessageKind() == OCM_Message);
@@ -730,7 +788,7 @@ bool ObjCMethodCall::canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
getState()->getStateManager().getContext().getSourceManager();
// If the class interface is declared inside the main file, assume it is not
- // subcassed.
+ // subcassed.
// TODO: It could actually be subclassed if the subclass is private as well.
// This is probably very rare.
SourceLocation InterfLoc = IDecl->getEndOfDefinitionLoc();
@@ -800,7 +858,7 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
if (!Receiver)
return RuntimeDefinition();
- DynamicTypeInfo DTI = getState()->getDynamicTypeInfo(Receiver);
+ DynamicTypeInfo DTI = getDynamicTypeInfo(getState(), Receiver);
QualType DynType = DTI.getType();
CanBeSubClassed = DTI.canBeASubClass();
ReceiverT = dyn_cast<ObjCObjectPointerType>(DynType);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp
index 2235211..b422a88 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp
@@ -23,7 +23,7 @@ StringRef CheckerBase::getTagDescription() const {
CheckName CheckerBase::getCheckName() const { return Name; }
-CheckerProgramPointTag::CheckerProgramPointTag(StringRef CheckerName,
+CheckerProgramPointTag::CheckerProgramPointTag(StringRef CheckerName,
StringRef Msg)
: SimpleProgramPointTag(CheckerName, Msg) {}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
index 6b22bf4..5ec8bfa 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
@@ -45,7 +45,7 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD,
if (BId != 0) {
if (Name.empty())
return true;
- StringRef BName = FD->getASTContext().BuiltinInfo.GetName(BId);
+ StringRef BName = FD->getASTContext().BuiltinInfo.getName(BId);
if (BName.find(Name) != StringRef::npos)
return true;
}
@@ -57,12 +57,8 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD,
return false;
// Look through 'extern "C"' and anything similar invented in the future.
- const DeclContext *DC = FD->getDeclContext();
- while (DC->isTransparentContext())
- DC = DC->getParent();
-
- // If this function is in a namespace, it is not a C library function.
- if (!DC->isTranslationUnit())
+ // If this function is not in TU directly, it is not a C library function.
+ if (!FD->getDeclContext()->getRedeclContext()->isTranslationUnit())
return false;
// If this function is not externally visible, it is not a C library function.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
index 3d9a815..d6aeceb 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
// Recursively find any substatements containing macros
@@ -70,3 +71,26 @@ bool clang::ento::containsBuiltinOffsetOf(const Stmt *S) {
return false;
}
+
+// Extract lhs and rhs from assignment statement
+std::pair<const clang::VarDecl *, const clang::Expr *>
+clang::ento::parseAssignment(const Stmt *S) {
+ const VarDecl *VD = 0;
+ const Expr *RHS = 0;
+
+ if (auto Assign = dyn_cast_or_null<BinaryOperator>(S)) {
+ if (Assign->isAssignmentOp()) {
+ // Ordinary assignment
+ RHS = Assign->getRHS();
+ if (auto DE = dyn_cast_or_null<DeclRefExpr>(Assign->getLHS()))
+ VD = dyn_cast_or_null<VarDecl>(DE->getDecl());
+ }
+ } else if (auto PD = dyn_cast_or_null<DeclStmt>(S)) {
+ // Initialization
+ assert(PD->isSingleDecl() && "We process decls one by one");
+ VD = dyn_cast_or_null<VarDecl>(PD->getSingleDecl());
+ RHS = VD->getAnyInitializer();
+ }
+
+ return std::make_pair(VD, RHS);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 2684cc7..008e8ef 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -177,7 +177,9 @@ void CheckerManager::runCheckersForStmt(bool isPreVisit,
namespace {
struct CheckObjCMessageContext {
typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
- bool IsPreVisit, WasInlined;
+
+ ObjCMessageVisitKind Kind;
+ bool WasInlined;
const CheckersTy &Checkers;
const ObjCMethodCall &Msg;
ExprEngine &Eng;
@@ -185,14 +187,28 @@ namespace {
CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
- CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
+ CheckObjCMessageContext(ObjCMessageVisitKind visitKind,
+ const CheckersTy &checkers,
const ObjCMethodCall &msg, ExprEngine &eng,
bool wasInlined)
- : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
+ : Kind(visitKind), WasInlined(wasInlined), Checkers(checkers),
Msg(msg), Eng(eng) { }
void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
+
+ bool IsPreVisit;
+
+ switch (Kind) {
+ case ObjCMessageVisitKind::Pre:
+ IsPreVisit = true;
+ break;
+ case ObjCMessageVisitKind::MessageNil:
+ case ObjCMessageVisitKind::Post:
+ IsPreVisit = false;
+ break;
+ }
+
const ProgramPoint &L = Msg.getProgramPoint(IsPreVisit,checkFn.Checker);
CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
@@ -202,19 +218,30 @@ namespace {
}
/// \brief Run checkers for visiting obj-c messages.
-void CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
+void CheckerManager::runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
const ObjCMethodCall &msg,
ExprEngine &Eng,
bool WasInlined) {
- CheckObjCMessageContext C(isPreVisit,
- isPreVisit ? PreObjCMessageCheckers
- : PostObjCMessageCheckers,
- msg, Eng, WasInlined);
+ auto &checkers = getObjCMessageCheckers(visitKind);
+ CheckObjCMessageContext C(visitKind, checkers, msg, Eng, WasInlined);
expandGraphWithCheckers(C, Dst, Src);
}
+const std::vector<CheckerManager::CheckObjCMessageFunc> &
+CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) {
+ switch (Kind) {
+ case ObjCMessageVisitKind::Pre:
+ return PreObjCMessageCheckers;
+ break;
+ case ObjCMessageVisitKind::Post:
+ return PostObjCMessageCheckers;
+ case ObjCMessageVisitKind::MessageNil:
+ return ObjCMessageNilCheckers;
+ }
+ llvm_unreachable("Unknown Kind");
+}
namespace {
// FIXME: This has all the same signatures as CheckObjCMessageContext.
// Is there a way we can merge the two?
@@ -357,9 +384,9 @@ void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC,
ExplodedNodeSet &Dst,
ExplodedNode *Pred,
ExprEngine &Eng) {
-
+
// We define the builder outside of the loop bacause if at least one checkers
- // creates a sucsessor for Pred, we do not need to generate an
+ // creates a sucsessor for Pred, we do not need to generate an
// autotransition for it.
NodeBuilder Bldr(Pred, Dst, BC);
for (unsigned i = 0, e = EndFunctionCheckers.size(); i != e; ++i) {
@@ -467,7 +494,7 @@ bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) {
}
/// \brief Run checkers for region changes.
-ProgramStateRef
+ProgramStateRef
CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
@@ -478,7 +505,7 @@ CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
// bail out.
if (!state)
return nullptr;
- state = RegionChangesCheckers[i].CheckFn(state, invalidated,
+ state = RegionChangesCheckers[i].CheckFn(state, invalidated,
ExplicitRegions, Regions, Call);
}
return state;
@@ -506,7 +533,7 @@ CheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
}
/// \brief Run checkers for handling assumptions on symbolic values.
-ProgramStateRef
+ProgramStateRef
CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
SVal Cond, bool Assumption) {
for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
@@ -558,7 +585,7 @@ void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
#endif
}
}
-
+
// If none of the checkers evaluated the call, ask ExprEngine to handle it.
if (!anyEvaluated) {
NodeBuilder B(Pred, Dst, Eng.getBuilderContext());
@@ -616,6 +643,11 @@ void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
PreObjCMessageCheckers.push_back(checkfn);
}
+
+void CheckerManager::_registerForObjCMessageNil(CheckObjCMessageFunc checkfn) {
+ ObjCMessageNilCheckers.push_back(checkfn);
+}
+
void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
PostObjCMessageCheckers.push_back(checkfn);
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
index 6ba64f5..a15e157 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
@@ -94,7 +94,7 @@ void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
}
}
-void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
+void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
SmallVectorImpl<CheckerOptInfo> &opts) const {
// Sort checkers for efficient collection.
std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
index 4dec526..b7db833 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
@@ -26,7 +26,7 @@ static DefinedSVal getLocFromSymbol(const ProgramStateRef &State,
}
ConditionTruthVal ConstraintManager::checkNull(ProgramStateRef State,
- SymbolRef Sym) {
+ SymbolRef Sym) {
QualType Ty = Sym->getType();
DefinedSVal V = Loc::isLocType(Ty) ? getLocFromSymbol(State, Sym)
: nonloc::SymbolVal(Sym);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 7844ad4..39cf7e7 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -271,7 +271,7 @@ void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
bool CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
unsigned Steps,
- ProgramStateRef InitState,
+ ProgramStateRef InitState,
ExplodedNodeSet &Dst) {
bool DidNotFinish = ExecuteWorkList(L, Steps, InitState);
for (ExplodedGraph::eop_iterator I = G.eop_begin(), E = G.eop_end(); I != E;
@@ -386,7 +386,7 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
}
return;
}
-
+
case Stmt::DoStmtClass:
HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
return;
@@ -456,7 +456,7 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
Pred->State, Pred);
}
-void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term,
+void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term,
const CFGBlock * B, ExplodedNode *Pred) {
assert(B->succ_size() == 2);
NodeBuilderContext Ctx(*this, B, Pred);
@@ -491,7 +491,7 @@ void CoreEngine::HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
}
-void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
+void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
ExplodedNode *Pred) {
assert(B);
assert(!B->empty());
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
new file mode 100644
index 0000000..fd35b66
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
@@ -0,0 +1,51 @@
+//==- DynamicTypeMap.cpp - Dynamic Type Info related APIs ----------*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines APIs that track and query dynamic type information. This
+// information can be used to devirtualize calls during the symbolic exection
+// or do type checking.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+
+namespace clang {
+namespace ento {
+
+DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
+ const MemRegion *Reg) {
+ Reg = Reg->StripCasts();
+
+ // Look up the dynamic type in the GDM.
+ const DynamicTypeInfo *GDMType = State->get<DynamicTypeMap>(Reg);
+ if (GDMType)
+ return *GDMType;
+
+ // Otherwise, fall back to what we know about the region.
+ if (const TypedRegion *TR = dyn_cast<TypedRegion>(Reg))
+ return DynamicTypeInfo(TR->getLocationType(), /*CanBeSubclass=*/false);
+
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) {
+ SymbolRef Sym = SR->getSymbol();
+ return DynamicTypeInfo(Sym->getType());
+ }
+
+ return DynamicTypeInfo();
+}
+
+ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
+ DynamicTypeInfo NewTy) {
+ Reg = Reg->StripCasts();
+ ProgramStateRef NewState = State->set<DynamicTypeMap>(Reg, NewTy);
+ assert(NewState);
+ return NewState;
+}
+
+} // namespace ento
+} // namespace clang
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
index ae5a4cc..e2cb52cb 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
@@ -90,6 +90,7 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry,
case Stmt::CXXNullPtrLiteralExprClass:
case Stmt::ObjCStringLiteralClass:
case Stmt::StringLiteralClass:
+ case Stmt::TypeTraitExprClass:
// Known constants; defer to SValBuilder.
return svalBuilder.getConstantVal(cast<Expr>(S)).getValue();
@@ -97,9 +98,9 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry,
const ReturnStmt *RS = cast<ReturnStmt>(S);
if (const Expr *RE = RS->getRetValue())
return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder);
- return UndefinedVal();
+ return UndefinedVal();
}
-
+
// Handle all other Stmt* using a lookup.
default:
return lookupExpr(EnvironmentEntry(S, LCtx));
@@ -120,7 +121,7 @@ Environment EnvironmentManager::bindExpr(Environment Env,
}
namespace {
-class MarkLiveCallback : public SymbolVisitor {
+class MarkLiveCallback final : public SymbolVisitor {
SymbolReaper &SymReaper;
public:
MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
@@ -170,10 +171,6 @@ EnvironmentManager::removeDeadBindings(Environment Env,
// Copy the binding to the new map.
EBMapRef = EBMapRef.add(BlkExpr, X);
- // If the block expr's value is a memory region, then mark that region.
- if (Optional<loc::MemRegionVal> R = X.getAs<loc::MemRegionVal>())
- SymReaper.markLive(R->getRegion());
-
// Mark all symbols in the block expr's value live.
RSScaner.scan(X);
continue;
@@ -194,16 +191,16 @@ void Environment::print(raw_ostream &Out, const char *NL,
for (Environment::iterator I = begin(), E = end(); I != E; ++I) {
const EnvironmentEntry &En = I.getKey();
-
+
if (isFirst) {
Out << NL << NL
<< "Expressions:"
- << NL;
+ << NL;
isFirst = false;
} else {
Out << NL;
}
-
+
const Stmt *S = En.getStmt();
assert(S != nullptr && "Expected non-null Stmt");
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 010d26e..8a09720 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -90,8 +90,8 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
// (7) The LocationContext is the same as the predecessor.
// (8) Expressions that are *not* lvalue expressions.
// (9) The PostStmt isn't for a non-consumed Stmt or Expr.
- // (10) The successor is neither a CallExpr StmtPoint nor a CallEnter or
- // PreImplicitCall (so that we would be able to find it when retrying a
+ // (10) The successor is neither a CallExpr StmtPoint nor a CallEnter or
+ // PreImplicitCall (so that we would be able to find it when retrying a
// call with no inlining).
// FIXME: It may be safe to reclaim PreCall and PostCall nodes as well.
@@ -102,7 +102,7 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
const ExplodedNode *pred = *(node->pred_begin());
if (pred->succ_size() != 1)
return false;
-
+
const ExplodedNode *succ = *(node->succ_begin());
if (succ->pred_size() != 1)
return false;
@@ -123,7 +123,7 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
// Conditions 5, 6, and 7.
ProgramStateRef state = node->getState();
- ProgramStateRef pred_state = pred->getState();
+ ProgramStateRef pred_state = pred->getState();
if (state->store != pred_state->store || state->GDM != pred_state->GDM ||
progPoint.getLocationContext() != pred->getLocationContext())
return false;
@@ -174,7 +174,7 @@ void ExplodedGraph::collectNode(ExplodedNode *node) {
FreeNodes.push_back(node);
Nodes.RemoveNode(node);
--NumNodes;
- node->~ExplodedNode();
+ node->~ExplodedNode();
}
void ExplodedGraph::reclaimRecentlyAllocatedNodes() {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index a3239f5..662b0a2 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -26,6 +26,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
@@ -174,7 +175,7 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
}
}
}
-
+
return state;
}
@@ -265,7 +266,7 @@ bool ExprEngine::wantsRegionChangeUpdate(ProgramStateRef state) {
return getCheckerManager().wantsRegionChangeUpdate(state);
}
-ProgramStateRef
+ProgramStateRef
ExprEngine::processRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> Explicits,
@@ -315,7 +316,7 @@ static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
const CFGStmt S,
const ExplodedNode *Pred,
const LocationContext *LC) {
-
+
// Are we never purging state values?
if (AMgr.options.AnalysisPurgeOpt == PurgeNone)
return false;
@@ -327,7 +328,7 @@ static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
// Is this on a non-expression?
if (!isa<Expr>(S.getStmt()))
return true;
-
+
// Run before processing a call.
if (CallEvent::isCallStmt(S.getStmt()))
return true;
@@ -475,8 +476,12 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
if (BMI->isAnyMemberInitializer()) {
// Constructors build the object directly in the field,
// but non-objects must be copied in from the initializer.
- const Expr *Init = BMI->getInit()->IgnoreImplicit();
- if (!isa<CXXConstructExpr>(Init)) {
+ if (auto *CtorExpr = findDirectConstructorForCurrentCFGElement()) {
+ assert(BMI->getInit()->IgnoreImplicit() == CtorExpr);
+ (void)CtorExpr;
+ // The field was directly constructed, so there is no need to bind.
+ } else {
+ const Expr *Init = BMI->getInit()->IgnoreImplicit();
const ValueDecl *Field;
if (BMI->isIndirectMemberInitializer()) {
Field = BMI->getIndirectMember();
@@ -512,7 +517,7 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
assert(Tmp.size() == 1 && "have not generated any new nodes yet");
assert(*Tmp.begin() == Pred && "have not generated any new nodes yet");
Tmp.clear();
-
+
PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);
evalBind(Tmp, Init, Pred, FieldLoc, InitVal, /*isInit=*/true, &PP);
}
@@ -754,9 +759,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::CXXUuidofExprClass:
case Stmt::CXXFoldExprClass:
case Stmt::MSPropertyRefExprClass:
+ case Stmt::MSPropertySubscriptExprClass:
case Stmt::CXXUnresolvedConstructExprClass:
case Stmt::DependentScopeDeclRefExprClass:
- case Stmt::TypeTraitExprClass:
case Stmt::ArrayTypeTraitExprClass:
case Stmt::ExpressionTraitExprClass:
case Stmt::UnresolvedLookupExprClass:
@@ -766,16 +771,19 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::PackExpansionExprClass:
case Stmt::SubstNonTypeTemplateParmPackExprClass:
case Stmt::FunctionParmPackExprClass:
+ case Stmt::CoroutineBodyStmtClass:
+ case Stmt::CoawaitExprClass:
+ case Stmt::CoreturnStmtClass:
+ case Stmt::CoyieldExprClass:
case Stmt::SEHTryStmtClass:
case Stmt::SEHExceptStmtClass:
case Stmt::SEHLeaveStmtClass:
- case Stmt::LambdaExprClass:
case Stmt::SEHFinallyStmtClass: {
const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
Engine.addAbortedBlock(node, currBldrCtx->getBlock());
break;
}
-
+
case Stmt::ParenExprClass:
llvm_unreachable("ParenExprs already handled.");
case Stmt::GenericSelectionExprClass:
@@ -821,9 +829,13 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OMPOrderedDirectiveClass:
case Stmt::OMPAtomicDirectiveClass:
case Stmt::OMPTargetDirectiveClass:
+ case Stmt::OMPTargetDataDirectiveClass:
case Stmt::OMPTeamsDirectiveClass:
case Stmt::OMPCancellationPointDirectiveClass:
case Stmt::OMPCancelDirectiveClass:
+ case Stmt::OMPTaskLoopDirectiveClass:
+ case Stmt::OMPTaskLoopSimdDirectiveClass:
+ case Stmt::OMPDistributeDirectiveClass:
llvm_unreachable("Stmt should not be in analyzer evaluation loop");
case Stmt::ObjCSubscriptRefExprClass:
@@ -901,7 +913,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::ObjCStringLiteralClass:
case Stmt::CXXPseudoDestructorExprClass:
case Stmt::SubstNonTypeTemplateParmExprClass:
- case Stmt::CXXNullPtrLiteralExprClass: {
+ case Stmt::CXXNullPtrLiteralExprClass:
+ case Stmt::OMPArraySectionExprClass:
+ case Stmt::TypeTraitExprClass: {
Bldr.takeNodes(Pred);
ExplodedNodeSet preVisit;
getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
@@ -964,7 +978,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet preVisit;
getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
-
+
ExplodedNodeSet Tmp;
StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx);
@@ -972,7 +986,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
QualType resultType = Ex->getType();
for (ExplodedNodeSet::iterator it = preVisit.begin(), et = preVisit.end();
- it != et; ++it) {
+ it != et; ++it) {
ExplodedNode *N = *it;
const LocationContext *LCtx = N->getLocationContext();
SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
@@ -981,10 +995,10 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ProgramStateRef state = N->getState()->BindExpr(Ex, LCtx, result);
Bldr2.generateNode(S, N, state);
}
-
+
getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
Bldr.addNodes(Dst);
- break;
+ break;
}
case Stmt::ArraySubscriptExprClass:
@@ -1011,6 +1025,17 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
Bldr.addNodes(Dst);
break;
+ case Stmt::LambdaExprClass:
+ if (AMgr.options.shouldInlineLambdas()) {
+ Bldr.takeNodes(Pred);
+ VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ } else {
+ const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
+ Engine.addAbortedBlock(node, currBldrCtx->getBlock());
+ }
+ break;
+
case Stmt::BinaryOperatorClass: {
const BinaryOperator* B = cast<BinaryOperator>(S);
if (B->isLogicalOp()) {
@@ -1029,7 +1054,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
}
Bldr.takeNodes(Pred);
-
+
if (AMgr.options.eagerlyAssumeBinOpBifurcation &&
(B->isRelationalOp() || B->isEqualityOp())) {
ExplodedNodeSet Tmp;
@@ -1074,7 +1099,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
Bldr.addNodes(Dst);
break;
}
-
+
case Stmt::CXXCatchStmtClass: {
Bldr.takeNodes(Pred);
VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);
@@ -1083,7 +1108,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
}
case Stmt::CXXTemporaryObjectExprClass:
- case Stmt::CXXConstructExprClass: {
+ case Stmt::CXXConstructExprClass: {
Bldr.takeNodes(Pred);
VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);
Bldr.addNodes(Dst);
@@ -1105,7 +1130,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
const CXXDeleteExpr *CDE = cast<CXXDeleteExpr>(S);
getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
- for (ExplodedNodeSet::iterator i = PreVisit.begin(),
+ for (ExplodedNodeSet::iterator i = PreVisit.begin(),
e = PreVisit.end(); i != e ; ++i)
VisitCXXDeleteExpr(CDE, *i, Dst);
@@ -1171,18 +1196,18 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::CXXDynamicCastExprClass:
case Stmt::CXXReinterpretCastExprClass:
case Stmt::CXXConstCastExprClass:
- case Stmt::CXXFunctionalCastExprClass:
+ case Stmt::CXXFunctionalCastExprClass:
case Stmt::ObjCBridgedCastExprClass: {
Bldr.takeNodes(Pred);
const CastExpr *C = cast<CastExpr>(S);
// Handle the previsit checks.
ExplodedNodeSet dstPrevisit;
getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, C, *this);
-
+
// Handle the expression itself.
ExplodedNodeSet dstExpr;
for (ExplodedNodeSet::iterator i = dstPrevisit.begin(),
- e = dstPrevisit.end(); i != e ; ++i) {
+ e = dstPrevisit.end(); i != e ; ++i) {
VisitCast(C, C->getSubExpr(), *i, dstExpr);
}
@@ -1199,7 +1224,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
Bldr.addNodes(Dst);
break;
}
-
+
case Stmt::InitListExprClass:
Bldr.takeNodes(Pred);
VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
@@ -1294,7 +1319,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
Bldr.takeNodes(Pred);
ProgramStateRef state = Pred->getState();
const PseudoObjectExpr *PE = cast<PseudoObjectExpr>(S);
- if (const Expr *Result = PE->getResultExpr()) {
+ if (const Expr *Result = PE->getResultExpr()) {
SVal V = state->getSVal(Result, Pred->getLocationContext());
Bldr.generateNode(S, Pred,
state->BindExpr(S, Pred->getLocationContext(), V));
@@ -1375,12 +1400,29 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
/// Block entrance. (Update counters).
void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
- NodeBuilderWithSinks &nodeBuilder,
+ NodeBuilderWithSinks &nodeBuilder,
ExplodedNode *Pred) {
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
+ // If this block is terminated by a loop and it has already been visited the
+ // maximum number of times, widen the loop.
+ unsigned int BlockCount = nodeBuilder.getContext().blockCount();
+ if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
+ AMgr.options.shouldWidenLoops()) {
+ const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
+ if (!(Term &&
+ (isa<ForStmt>(Term) || isa<WhileStmt>(Term) || isa<DoStmt>(Term))))
+ return;
+ // Widen.
+ const LocationContext *LCtx = Pred->getLocationContext();
+ ProgramStateRef WidenedState =
+ getWidenedLoopState(Pred->getState(), LCtx, BlockCount, Term);
+ nodeBuilder.generateNode(WidenedState, Pred);
+ return;
+ }
+
// FIXME: Refactor this into a checker.
- if (nodeBuilder.getContext().blockCount() >= AMgr.options.maxBlockVisitOnPath) {
+ if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {
static SimpleProgramPointTag tag(TagProviderName, "Block count exceeded");
const ExplodedNode *Sink =
nodeBuilder.generateSink(Pred->getState(), Pred, &tag);
@@ -1537,7 +1579,6 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
return;
}
-
if (const Expr *Ex = dyn_cast<Expr>(Condition))
Condition = Ex->IgnoreParens();
@@ -1583,7 +1624,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
}
}
}
-
+
// If the condition is still unknown, give up.
if (X.isUnknownOrUndef()) {
builder.generateNode(PrevState, true, PredI);
@@ -1750,7 +1791,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
DefinedOrUnknownSVal CondV = CondV_untested.castAs<DefinedOrUnknownSVal>();
ProgramStateRef DefaultSt = state;
-
+
iterator I = builder.begin(), EI = builder.end();
bool defaultIsFeasible = I == EI;
@@ -1758,7 +1799,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
// Successor may be pruned out during CFG construction.
if (!I.getBlock())
continue;
-
+
const CaseStmt *Case = I.getCase();
// Evaluate the LHS of the case value.
@@ -1772,47 +1813,24 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
else
V2 = V1;
- // FIXME: Eventually we should replace the logic below with a range
- // comparison, rather than concretize the values within the range.
- // This should be easy once we have "ranges" for NonLVals.
-
- do {
- nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1));
- DefinedOrUnknownSVal Res = svalBuilder.evalEQ(DefaultSt ? DefaultSt : state,
- CondV, CaseVal);
-
- // Now "assume" that the case matches.
- if (ProgramStateRef stateNew = state->assume(Res, true)) {
- builder.generateCaseStmtNode(I, stateNew);
-
- // If CondV evaluates to a constant, then we know that this
- // is the *only* case that we can take, so stop evaluating the
- // others.
- if (CondV.getAs<nonloc::ConcreteInt>())
- return;
- }
-
- // Now "assume" that the case doesn't match. Add this state
- // to the default state (if it is feasible).
- if (DefaultSt) {
- if (ProgramStateRef stateNew = DefaultSt->assume(Res, false)) {
- defaultIsFeasible = true;
- DefaultSt = stateNew;
- }
- else {
- defaultIsFeasible = false;
- DefaultSt = nullptr;
- }
- }
-
- // Concretize the next value in the range.
- if (V1 == V2)
- break;
-
- ++V1;
- assert (V1 <= V2);
-
- } while (true);
+ ProgramStateRef StateCase;
+ if (Optional<NonLoc> NL = CondV.getAs<NonLoc>())
+ std::tie(StateCase, DefaultSt) =
+ DefaultSt->assumeWithinInclusiveRange(*NL, V1, V2);
+ else // UnknownVal
+ StateCase = DefaultSt;
+
+ if (StateCase)
+ builder.generateCaseStmtNode(I, StateCase);
+
+ // Now "assume" that the case doesn't match. Add this state
+ // to the default state (if it is feasible).
+ if (DefaultSt)
+ defaultIsFeasible = true;
+ else {
+ defaultIsFeasible = false;
+ break;
+ }
}
if (!defaultIsFeasible)
@@ -1849,13 +1867,44 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
// C permits "extern void v", and if you cast the address to a valid type,
- // you can even do things with it. We simply pretend
+ // you can even do things with it. We simply pretend
assert(Ex->isGLValue() || VD->getType()->isVoidType());
- SVal V = state->getLValue(VD, Pred->getLocationContext());
+ const LocationContext *LocCtxt = Pred->getLocationContext();
+ const Decl *D = LocCtxt->getDecl();
+ const auto *MD = D ? dyn_cast<CXXMethodDecl>(D) : nullptr;
+ const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
+ SVal V;
+ bool IsReference;
+ if (AMgr.options.shouldInlineLambdas() && DeclRefEx &&
+ DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
+ MD->getParent()->isLambda()) {
+ // Lookup the field of the lambda.
+ const CXXRecordDecl *CXXRec = MD->getParent();
+ llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
+ FieldDecl *LambdaThisCaptureField;
+ CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
+ const FieldDecl *FD = LambdaCaptureFields[VD];
+ if (!FD) {
+ // When a constant is captured, sometimes no corresponding field is
+ // created in the lambda object.
+ assert(VD->getType().isConstQualified());
+ V = state->getLValue(VD, LocCtxt);
+ IsReference = false;
+ } else {
+ Loc CXXThis =
+ svalBuilder.getCXXThis(MD, LocCtxt->getCurrentStackFrame());
+ SVal CXXThisVal = state->getSVal(CXXThis);
+ V = state->getLValue(FD, CXXThisVal);
+ IsReference = FD->getType()->isReferenceType();
+ }
+ } else {
+ V = state->getLValue(VD, LocCtxt);
+ IsReference = VD->getType()->isReferenceType();
+ }
// For references, the 'lvalue' is the pointer address stored in the
// reference region.
- if (VD->getType()->isReferenceType()) {
+ if (IsReference) {
if (const MemRegion *R = V.getAsRegion())
V = state->getSVal(R);
else
@@ -1900,7 +1949,6 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
const Expr *Base = A->getBase()->IgnoreParens();
const Expr *Idx = A->getIdx()->IgnoreParens();
-
ExplodedNodeSet checkerPreStmt;
getCheckerManager().runCheckersForPreStmt(checkerPreStmt, Pred, A, *this);
@@ -2005,8 +2053,9 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
}
namespace {
-class CollectReachableSymbolsCallback : public SymbolVisitor {
+class CollectReachableSymbolsCallback final : public SymbolVisitor {
InvalidatedSymbols Symbols;
+
public:
CollectReachableSymbolsCallback(ProgramStateRef State) {}
const InvalidatedSymbols &getSymbols() const { return Symbols; }
@@ -2064,14 +2113,14 @@ ProgramStateRef ExprEngine::processPointerEscapedOnBind(ProgramStateRef State,
return State;
}
-ProgramStateRef
+ProgramStateRef
ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call,
RegionAndSymbolInvalidationTraits &ITraits) {
-
+
if (!Invalidated || Invalidated->empty())
return State;
@@ -2082,7 +2131,7 @@ ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
PSK_EscapeOther,
&ITraits);
- // If the symbols were invalidated by a call, we want to find out which ones
+ // If the symbols were invalidated by a call, we want to find out which ones
// were invalidated directly due to being arguments to the call.
InvalidatedSymbols SymbolsDirectlyInvalidated;
for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
@@ -2129,7 +2178,6 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val,
StoreE, *this, *PP);
-
StmtNodeBuilder Bldr(CheckedSet, Dst, *currBldrCtx);
// If the location is not a 'Loc', it will already be handled by
@@ -2142,13 +2190,12 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
Bldr.generateNode(L, state, Pred);
return;
}
-
for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
I!=E; ++I) {
ExplodedNode *PredI = *I;
ProgramStateRef state = PredI->getState();
-
+
state = processPointerEscapedOnBind(state, location, Val);
// When binding the value, pass on the hint that this is a initialization.
@@ -2301,7 +2348,7 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
// "p = 0" is not noted as "Null pointer value stored to 'p'" but
// instead "int *p" is noted as
// "Variable 'p' initialized to a null pointer value"
-
+
static SimpleProgramPointTag tag(TagProviderName, "Location");
Bldr.generateNode(NodeEx, Pred, state, &tag);
}
@@ -2326,7 +2373,7 @@ void ExprEngine::evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst,
ExplodedNodeSet &Src,
const Expr *Ex) {
StmtNodeBuilder Bldr(Src, Dst, *currBldrCtx);
-
+
for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {
ExplodedNode *Pred = *I;
// Test if the previous node was as the same expression. This can happen
@@ -2349,7 +2396,7 @@ void ExprEngine::evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst,
// First assume that the condition is true.
if (StateTrue) {
- SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());
+ SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());
StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);
Bldr.generateNode(Ex, Pred, StateTrue, tags.first);
}
@@ -2641,10 +2688,10 @@ struct DOTGraphTraits<ExplodedNode*> :
<< " NodeID: " << (const void*) N << "\\|";
state->printDOT(Out);
- Out << "\\l";
+ Out << "\\l";
if (const ProgramPointTag *tag = Loc.getTag()) {
- Out << "\\|Tag: " << tag->getTagDescription();
+ Out << "\\|Tag: " << tag->getTagDescription();
Out << "\\l";
}
return Out.str();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 1777ea9..175225b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -25,23 +25,23 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
Expr *LHS = B->getLHS()->IgnoreParens();
Expr *RHS = B->getRHS()->IgnoreParens();
-
+
// FIXME: Prechecks eventually go in ::Visit().
ExplodedNodeSet CheckedSet;
ExplodedNodeSet Tmp2;
getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, B, *this);
-
+
// With both the LHS and RHS evaluated, process the operation itself.
for (ExplodedNodeSet::iterator it=CheckedSet.begin(), ei=CheckedSet.end();
it != ei; ++it) {
-
+
ProgramStateRef state = (*it)->getState();
const LocationContext *LCtx = (*it)->getLocationContext();
SVal LeftV = state->getSVal(LHS, LCtx);
SVal RightV = state->getSVal(RHS, LCtx);
-
+
BinaryOperator::Opcode Op = B->getOpcode();
-
+
if (Op == BO_Assign) {
// EXPERIMENTAL: "Conjured" symbols.
// FIXME: Handle structs.
@@ -57,7 +57,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
LeftV, RightV);
continue;
}
-
+
if (!B->isAssignmentOp()) {
StmtNodeBuilder Bldr(*it, Tmp2, *currBldrCtx);
@@ -90,19 +90,19 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// Process non-assignments except commas or short-circuited
// logical expressions (LAnd and LOr).
- SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
+ SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
if (Result.isUnknown()) {
Bldr.generateNode(B, *it, state);
continue;
- }
+ }
- state = state->BindExpr(B, LCtx, Result);
+ state = state->BindExpr(B, LCtx, Result);
Bldr.generateNode(B, *it, state);
continue;
}
-
+
assert (B->isCompoundAssignmentOp());
-
+
switch (Op) {
default:
llvm_unreachable("Invalid opcode for compound assignment.");
@@ -117,43 +117,43 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
case BO_XorAssign: Op = BO_Xor; break;
case BO_OrAssign: Op = BO_Or; break;
}
-
+
// Perform a load (the LHS). This performs the checks for
// null dereferences, and so on.
ExplodedNodeSet Tmp;
SVal location = LeftV;
evalLoad(Tmp, B, LHS, *it, state, location);
-
+
for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E;
++I) {
state = (*I)->getState();
const LocationContext *LCtx = (*I)->getLocationContext();
SVal V = state->getSVal(LHS, LCtx);
-
+
// Get the computation type.
QualType CTy =
cast<CompoundAssignOperator>(B)->getComputationResultType();
CTy = getContext().getCanonicalType(CTy);
-
+
QualType CLHSTy =
cast<CompoundAssignOperator>(B)->getComputationLHSType();
CLHSTy = getContext().getCanonicalType(CLHSTy);
-
+
QualType LTy = getContext().getCanonicalType(LHS->getType());
-
+
// Promote LHS.
V = svalBuilder.evalCast(V, CLHSTy, LTy);
-
+
// Compute the result of the operation.
SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy),
B->getType(), CTy);
-
+
// EXPERIMENTAL: "Conjured" symbols.
// FIXME: Handle structs.
-
+
SVal LHSVal;
-
+
if (Result.isUnknown()) {
// The symbolic value is actually for the type of the left-hand side
// expression, not the computation type, as this is the value the
@@ -168,52 +168,74 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// computation type.
LHSVal = svalBuilder.evalCast(Result, LTy, CTy);
}
-
- // In C++, assignment and compound assignment operators return an
+
+ // In C++, assignment and compound assignment operators return an
// lvalue.
if (B->isGLValue())
state = state->BindExpr(B, LCtx, location);
else
state = state->BindExpr(B, LCtx, Result);
-
+
evalStore(Tmp2, B, LHS, *I, state, location, LHSVal);
}
}
-
+
// FIXME: postvisits eventually go in ::Visit()
getCheckerManager().runCheckersForPostStmt(Dst, Tmp2, B, *this);
}
void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
-
+
CanQualType T = getContext().getCanonicalType(BE->getType());
+ const BlockDecl *BD = BE->getBlockDecl();
// Get the value of the block itself.
- SVal V = svalBuilder.getBlockPointer(BE->getBlockDecl(), T,
+ SVal V = svalBuilder.getBlockPointer(BD, T,
Pred->getLocationContext(),
currBldrCtx->blockCount());
-
+
ProgramStateRef State = Pred->getState();
-
+
// If we created a new MemRegion for the block, we should explicitly bind
// the captured variables.
if (const BlockDataRegion *BDR =
dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
-
+
BlockDataRegion::referenced_vars_iterator I = BDR->referenced_vars_begin(),
E = BDR->referenced_vars_end();
-
+
+ auto CI = BD->capture_begin();
+ auto CE = BD->capture_end();
for (; I != E; ++I) {
- const MemRegion *capturedR = I.getCapturedRegion();
- const MemRegion *originalR = I.getOriginalRegion();
+ const VarRegion *capturedR = I.getCapturedRegion();
+ const VarRegion *originalR = I.getOriginalRegion();
+
+ // If the capture had a copy expression, use the result of evaluating
+ // that expression, otherwise use the original value.
+ // We rely on the invariant that the block declaration's capture variables
+ // are a prefix of the BlockDataRegion's referenced vars (which may include
+ // referenced globals, etc.) to enable fast lookup of the capture for a
+ // given referenced var.
+ const Expr *copyExpr = nullptr;
+ if (CI != CE) {
+ assert(CI->getVariable() == capturedR->getDecl());
+ copyExpr = CI->getCopyExpr();
+ CI++;
+ }
+
if (capturedR != originalR) {
- SVal originalV = State->getSVal(loc::MemRegionVal(originalR));
+ SVal originalV;
+ if (copyExpr) {
+ originalV = State->getSVal(copyExpr, Pred->getLocationContext());
+ } else {
+ originalV = State->getSVal(loc::MemRegionVal(originalR));
+ }
State = State->bindLoc(loc::MemRegionVal(capturedR), originalV);
}
}
}
-
+
ExplodedNodeSet Tmp;
StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
Bldr.generateNode(BE, Pred,
@@ -224,12 +246,12 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this);
}
-void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
+void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
-
+
ExplodedNodeSet dstPreStmt;
getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this);
-
+
if (CastE->getCastKind() == CK_LValueToRValue) {
for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
I!=E; ++I) {
@@ -240,18 +262,18 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
}
return;
}
-
- // All other casts.
+
+ // All other casts.
QualType T = CastE->getType();
QualType ExTy = Ex->getType();
-
+
if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
T = ExCast->getTypeAsWritten();
-
+
StmtNodeBuilder Bldr(dstPreStmt, Dst, *currBldrCtx);
for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
I != E; ++I) {
-
+
Pred = *I;
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
@@ -294,7 +316,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_ArrayToPointerDecay:
case CK_BitCast:
case CK_AddressSpaceConversion:
- case CK_IntegralCast:
+ case CK_BooleanToSignedIntegral:
case CK_NullToPointer:
case CK_IntegralToPointer:
case CK_PointerToIntegral:
@@ -316,13 +338,24 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_IntegralComplexToFloatingComplex:
case CK_CPointerToObjCPointerCast:
case CK_BlockPointerToObjCPointerCast:
- case CK_AnyPointerToBlockPointerCast:
- case CK_ObjCObjectLValueCast:
+ case CK_AnyPointerToBlockPointerCast:
+ case CK_ObjCObjectLValueCast:
case CK_ZeroToOCLEvent:
case CK_LValueBitCast: {
// Delegate to SValBuilder to process.
SVal V = state->getSVal(Ex, LCtx);
V = svalBuilder.evalCast(V, T, ExTy);
+ // Negate the result if we're treating the boolean as a signed i1
+ if (CastE->getCastKind() == CK_BooleanToSignedIntegral)
+ V = evalMinus(V);
+ state = state->BindExpr(CastE, LCtx, V);
+ Bldr.generateNode(CastE, Pred, state);
+ continue;
+ }
+ case CK_IntegralCast: {
+ // Delegate to SValBuilder to process.
+ SVal V = state->getSVal(Ex, LCtx);
+ V = svalBuilder.evalIntegralCast(state, V, T, ExTy);
state = state->BindExpr(CastE, LCtx, V);
Bldr.generateNode(CastE, Pred, state);
continue;
@@ -371,7 +404,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
currBldrCtx->blockCount());
state = state->BindExpr(CastE, LCtx, NewSym);
- } else
+ } else
// Else, bind to the derived region value.
state = state->BindExpr(CastE, LCtx, val);
}
@@ -417,7 +450,7 @@ void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
const Expr *Init = CL->getInitializer();
SVal V = State->getSVal(CL->getInitializer(), LCtx);
-
+
if (isa<CXXConstructExpr>(Init)) {
// No work needed. Just pass the value up to this expression.
} else {
@@ -450,11 +483,11 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
Dst.insert(Pred);
return;
}
-
+
// FIXME: all pre/post visits should eventually be handled by ::Visit().
ExplodedNodeSet dstPreVisit;
getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this);
-
+
ExplodedNodeSet dstEvaluated;
StmtNodeBuilder B(dstPreVisit, dstEvaluated, *currBldrCtx);
for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end();
@@ -470,7 +503,10 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
ExplodedNode *UpdatedN = N;
SVal InitVal = state->getSVal(InitEx, LC);
- if (isa<CXXConstructExpr>(InitEx->IgnoreImplicit())) {
+ assert(DS->isSingleDecl());
+ if (auto *CtorExpr = findDirectConstructorForCurrentCFGElement()) {
+ assert(InitEx->IgnoreImplicit() == CtorExpr);
+ (void)CtorExpr;
// We constructed the object directly in the variable.
// No need to bind anything.
B.generateNode(DS, UpdatedN, state);
@@ -485,7 +521,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
assert(InitVal.getAs<nonloc::LazyCompoundVal>());
}
}
-
+
// Recover some path-sensitivity if a scalar value evaluated to
// UnknownVal.
if (InitVal.isUnknown()) {
@@ -596,7 +632,7 @@ void ExprEngine::VisitInitListExpr(const InitListExpr *IE,
(T->isArrayType() || T->isRecordType() || T->isVectorType() ||
T->isAnyComplexType())) {
llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList();
-
+
// Handle base case where the initializer has no elements.
// e.g: static int* myArray[] = {};
if (NumInitElements == 0) {
@@ -604,13 +640,13 @@ void ExprEngine::VisitInitListExpr(const InitListExpr *IE,
B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V));
return;
}
-
+
for (InitListExpr::const_reverse_iterator it = IE->rbegin(),
ei = IE->rend(); it != ei; ++it) {
SVal V = state->getSVal(cast<Expr>(*it), LCtx);
vals = getBasicVals().consVals(V, vals);
}
-
+
B.generateNode(IE, Pred,
state->BindExpr(IE, LCtx,
svalBuilder.makeCompoundVal(T, vals)));
@@ -632,7 +668,7 @@ void ExprEngine::VisitInitListExpr(const InitListExpr *IE,
}
void ExprEngine::VisitGuardedExpr(const Expr *Ex,
- const Expr *L,
+ const Expr *L,
const Expr *R,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
@@ -663,9 +699,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
bool hasValue = false;
SVal V;
- for (CFGBlock::const_reverse_iterator I = SrcBlock->rbegin(),
- E = SrcBlock->rend(); I != E; ++I) {
- CFGElement CE = *I;
+ for (CFGElement CE : llvm::reverse(*SrcBlock)) {
if (Optional<CFGStmt> CS = CE.getAs<CFGStmt>()) {
const Expr *ValEx = cast<Expr>(CS->getStmt());
ValEx = ValEx->IgnoreParens();
@@ -694,7 +728,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
}
void ExprEngine::
-VisitOffsetOfExpr(const OffsetOfExpr *OOE,
+VisitOffsetOfExpr(const OffsetOfExpr *OOE,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
APSInt IV;
@@ -730,7 +764,7 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
if (Ex->getKind() == UETT_SizeOf) {
if (!T->isIncompleteType() && !T->isConstantSizeType()) {
assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
-
+
// FIXME: Add support for VLA type arguments and VLA expressions.
// When that happens, we should probably refactor VLASizeChecker's code.
continue;
@@ -741,10 +775,10 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
continue;
}
}
-
+
APSInt Value = Ex->EvaluateKnownConstInt(getContext());
CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue());
-
+
ProgramStateRef state = (*I)->getState();
state = state->BindExpr(Ex, (*I)->getLocationContext(),
svalBuilder.makeIntVal(amt.getQuantity(),
@@ -755,7 +789,7 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this);
}
-void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
+void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
// FIXME: Prechecks eventually go in ::Visit().
@@ -777,13 +811,13 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
}
case UO_Real: {
const Expr *Ex = U->getSubExpr()->IgnoreParens();
-
+
// FIXME: We don't have complex SValues yet.
if (Ex->getType()->isAnyComplexType()) {
// Just report "Unknown."
break;
}
-
+
// For all other types, UO_Real is an identity operation.
assert (U->getType() == Ex->getType());
ProgramStateRef state = (*I)->getState();
@@ -792,8 +826,8 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
state->getSVal(Ex, LCtx)));
break;
}
-
- case UO_Imag: {
+
+ case UO_Imag: {
const Expr *Ex = U->getSubExpr()->IgnoreParens();
// FIXME: We don't have complex SValues yet.
if (Ex->getType()->isAnyComplexType()) {
@@ -807,7 +841,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, X));
break;
}
-
+
case UO_Plus:
assert(!U->isGLValue());
// FALL-THROUGH.
@@ -820,7 +854,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
// Unary "+" is a no-op, similar to a parentheses. We still have places
// where it may be a block-level expression, so we need to
// generate an extra node that just propagates the value of the
- // subexpression.
+ // subexpression.
const Expr *Ex = U->getSubExpr()->IgnoreParens();
ProgramStateRef state = (*I)->getState();
const LocationContext *LCtx = (*I)->getLocationContext();
@@ -828,7 +862,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
state->getSVal(Ex, LCtx)));
break;
}
-
+
case UO_LNot:
case UO_Minus:
case UO_Not: {
@@ -836,15 +870,15 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
const Expr *Ex = U->getSubExpr()->IgnoreParens();
ProgramStateRef state = (*I)->getState();
const LocationContext *LCtx = (*I)->getLocationContext();
-
+
// Get the value of the subexpression.
SVal V = state->getSVal(Ex, LCtx);
-
+
if (V.isUnknownOrUndef()) {
Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V));
break;
}
-
+
switch (U->getOpcode()) {
default:
llvm_unreachable("Invalid Opcode.");
@@ -861,7 +895,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
//
// Note: technically we do "E == 0", but this is the same in the
// transfer functions as "0 == E".
- SVal Result;
+ SVal Result;
if (Optional<Loc> LV = V.getAs<Loc>()) {
Loc X = svalBuilder.makeNull();
Result = evalBinOp(state, BO_EQ, *LV, X, U->getType());
@@ -874,8 +908,8 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
Result = evalBinOp(state, BO_EQ, V.castAs<NonLoc>(), X,
U->getType());
}
-
- state = state->BindExpr(U, LCtx, Result);
+
+ state = state->BindExpr(U, LCtx, Result);
break;
}
Bldr.generateNode(U, *I, state);
@@ -893,81 +927,81 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
// Handle ++ and -- (both pre- and post-increment).
assert (U->isIncrementDecrementOp());
const Expr *Ex = U->getSubExpr()->IgnoreParens();
-
+
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef state = Pred->getState();
SVal loc = state->getSVal(Ex, LCtx);
-
+
// Perform a load.
ExplodedNodeSet Tmp;
evalLoad(Tmp, U, Ex, Pred, state, loc);
-
+
ExplodedNodeSet Dst2;
StmtNodeBuilder Bldr(Tmp, Dst2, *currBldrCtx);
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end();I!=E;++I) {
-
+
state = (*I)->getState();
assert(LCtx == (*I)->getLocationContext());
SVal V2_untested = state->getSVal(Ex, LCtx);
-
+
// Propagate unknown and undefined values.
if (V2_untested.isUnknownOrUndef()) {
Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V2_untested));
continue;
}
DefinedSVal V2 = V2_untested.castAs<DefinedSVal>();
-
+
// Handle all other values.
BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add : BO_Sub;
-
+
// If the UnaryOperator has non-location type, use its type to create the
// constant value. If the UnaryOperator has location type, create the
// constant with int type and pointer width.
SVal RHS;
-
+
if (U->getType()->isAnyPointerType())
RHS = svalBuilder.makeArrayIndex(1);
else if (U->getType()->isIntegralOrEnumerationType())
RHS = svalBuilder.makeIntVal(1, U->getType());
else
RHS = UnknownVal();
-
+
SVal Result = evalBinOp(state, Op, V2, RHS, U->getType());
-
+
// Conjure a new symbol if necessary to recover precision.
if (Result.isUnknown()){
DefinedOrUnknownSVal SymVal =
svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
currBldrCtx->blockCount());
Result = SymVal;
-
+
// If the value is a location, ++/-- should always preserve
// non-nullness. Check if the original value was non-null, and if so
// propagate that constraint.
if (Loc::isLocType(U->getType())) {
DefinedOrUnknownSVal Constraint =
svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType()));
-
+
if (!state->assume(Constraint, true)) {
// It isn't feasible for the original value to be null.
// Propagate this constraint.
Constraint = svalBuilder.evalEQ(state, SymVal,
svalBuilder.makeZeroVal(U->getType()));
-
-
+
+
state = state->assume(Constraint, false);
assert(state);
}
}
}
-
+
// Since the lvalue-to-rvalue conversion is explicit in the AST,
// we bind an l-value if the operator is prefix and an lvalue (in C++).
if (U->isGLValue())
state = state->BindExpr(U, LCtx, loc);
else
state = state->BindExpr(U, LCtx, U->isPostfix() ? V2 : Result);
-
+
// Perform the store.
Bldr.takeNodes(*I);
ExplodedNodeSet Dst3;
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 2a76621..556e223 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -103,49 +103,32 @@ static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue,
}
-static const MemRegion *getRegionForConstructedObject(
- const CXXConstructExpr *CE, ExplodedNode *Pred, ExprEngine &Eng,
- unsigned int CurrStmtIdx) {
+const MemRegion *
+ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE,
+ ExplodedNode *Pred) {
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
- const NodeBuilderContext &CurrBldrCtx = Eng.getBuilderContext();
// See if we're constructing an existing region by looking at the next
// element in the CFG.
- const CFGBlock *B = CurrBldrCtx.getBlock();
- unsigned int NextStmtIdx = CurrStmtIdx + 1;
- if (NextStmtIdx < B->size()) {
- CFGElement Next = (*B)[NextStmtIdx];
-
- // Is this a destructor? If so, we might be in the middle of an assignment
- // to a local or member: look ahead one more element to see what we find.
- while (Next.getAs<CFGImplicitDtor>() && NextStmtIdx + 1 < B->size()) {
- ++NextStmtIdx;
- Next = (*B)[NextStmtIdx];
- }
- // Is this a constructor for a local variable?
- if (Optional<CFGStmt> StmtElem = Next.getAs<CFGStmt>()) {
- if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) {
- if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) {
- if (Var->getInit() && Var->getInit()->IgnoreImplicit() == CE) {
- SVal LValue = State->getLValue(Var, LCtx);
- QualType Ty = Var->getType();
- LValue = makeZeroElementRegion(State, LValue, Ty);
- return LValue.getAsRegion();
- }
+ if (auto Elem = findElementDirectlyInitializedByCurrentConstructor()) {
+ if (Optional<CFGStmt> StmtElem = Elem->getAs<CFGStmt>()) {
+ auto *DS = cast<DeclStmt>(StmtElem->getStmt());
+ if (const auto *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) {
+ if (Var->getInit() && Var->getInit()->IgnoreImplicit() == CE) {
+ SVal LValue = State->getLValue(Var, LCtx);
+ QualType Ty = Var->getType();
+ LValue = makeZeroElementRegion(State, LValue, Ty);
+ return LValue.getAsRegion();
}
}
- }
-
- // Is this a constructor for a member?
- if (Optional<CFGInitializer> InitElem = Next.getAs<CFGInitializer>()) {
+ } else if (Optional<CFGInitializer> InitElem = Elem->getAs<CFGInitializer>()) {
const CXXCtorInitializer *Init = InitElem->getInitializer();
assert(Init->isAnyMemberInitializer());
-
const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
- Loc ThisPtr = Eng.getSValBuilder().getCXXThis(CurCtor,
- LCtx->getCurrentStackFrame());
+ Loc ThisPtr =
+ getSValBuilder().getCXXThis(CurCtor, LCtx->getCurrentStackFrame());
SVal ThisVal = State->getSVal(ThisPtr);
const ValueDecl *Field;
@@ -167,13 +150,86 @@ static const MemRegion *getRegionForConstructedObject(
// Don't forget to update the pre-constructor initialization code in
// ExprEngine::VisitCXXConstructExpr.
}
-
// If we couldn't find an existing region to construct into, assume we're
// constructing a temporary.
- MemRegionManager &MRMgr = Eng.getSValBuilder().getRegionManager();
+ MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
return MRMgr.getCXXTempObjectRegion(CE, LCtx);
}
+/// Returns true if the initializer for \Elem can be a direct
+/// constructor.
+static bool canHaveDirectConstructor(CFGElement Elem){
+ // DeclStmts and CXXCtorInitializers for fields can be directly constructed.
+
+ if (Optional<CFGStmt> StmtElem = Elem.getAs<CFGStmt>()) {
+ if (isa<DeclStmt>(StmtElem->getStmt())) {
+ return true;
+ }
+ }
+
+ if (Elem.getKind() == CFGElement::Initializer) {
+ return true;
+ }
+
+ return false;
+}
+
+Optional<CFGElement>
+ExprEngine::findElementDirectlyInitializedByCurrentConstructor() {
+ const NodeBuilderContext &CurrBldrCtx = getBuilderContext();
+ // See if we're constructing an existing region by looking at the next
+ // element in the CFG.
+ const CFGBlock *B = CurrBldrCtx.getBlock();
+ assert(isa<CXXConstructExpr>(((*B)[currStmtIdx]).castAs<CFGStmt>().getStmt()));
+ unsigned int NextStmtIdx = currStmtIdx + 1;
+ if (NextStmtIdx >= B->size())
+ return None;
+
+ CFGElement Next = (*B)[NextStmtIdx];
+
+ // Is this a destructor? If so, we might be in the middle of an assignment
+ // to a local or member: look ahead one more element to see what we find.
+ while (Next.getAs<CFGImplicitDtor>() && NextStmtIdx + 1 < B->size()) {
+ ++NextStmtIdx;
+ Next = (*B)[NextStmtIdx];
+ }
+
+ if (canHaveDirectConstructor(Next))
+ return Next;
+
+ return None;
+}
+
+const CXXConstructExpr *
+ExprEngine::findDirectConstructorForCurrentCFGElement() {
+ // Go backward in the CFG to see if the previous element (ignoring
+ // destructors) was a CXXConstructExpr. If so, that constructor
+ // was constructed directly into an existing region.
+ // This process is essentially the inverse of that performed in
+ // findElementDirectlyInitializedByCurrentConstructor().
+ if (currStmtIdx == 0)
+ return nullptr;
+
+ const CFGBlock *B = getBuilderContext().getBlock();
+ assert(canHaveDirectConstructor((*B)[currStmtIdx]));
+
+ unsigned int PreviousStmtIdx = currStmtIdx - 1;
+ CFGElement Previous = (*B)[PreviousStmtIdx];
+
+ while (Previous.getAs<CFGImplicitDtor>() && PreviousStmtIdx > 0) {
+ --PreviousStmtIdx;
+ Previous = (*B)[PreviousStmtIdx];
+ }
+
+ if (Optional<CFGStmt> PrevStmtElem = Previous.getAs<CFGStmt>()) {
+ if (auto *CtorExpr = dyn_cast<CXXConstructExpr>(PrevStmtElem->getStmt())) {
+ return CtorExpr;
+ }
+ }
+
+ return nullptr;
+}
+
void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
ExplodedNode *Pred,
ExplodedNodeSet &destNodes) {
@@ -188,7 +244,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
switch (CE->getConstructionKind()) {
case CXXConstructExpr::CK_Complete: {
- Target = getRegionForConstructedObject(CE, Pred, *this, currStmtIdx);
+ Target = getRegionForConstructedObject(CE, Pred);
break;
}
case CXXConstructExpr::CK_VirtualBase:
@@ -300,7 +356,7 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType,
const MemRegion *Dest,
const Stmt *S,
bool IsBaseDtor,
- ExplodedNode *Pred,
+ ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
@@ -373,7 +429,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
// Also, we need to decide how allocators actually work -- they're not
// really part of the CXXNewExpr because they happen BEFORE the
// CXXConstructExpr subexpression. See PR12014 for some discussion.
-
+
unsigned blockCount = currBldrCtx->blockCount();
const LocationContext *LCtx = Pred->getLocationContext();
DefinedOrUnknownSVal symVal = UnknownVal();
@@ -392,8 +448,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
IsStandardGlobalOpNewFunction = (FD->getNumParams() == 1);
}
- // We assume all standard global 'operator new' functions allocate memory in
- // heap. We realize this is an approximation that might not correctly model
+ // We assume all standard global 'operator new' functions allocate memory in
+ // heap. We realize this is an approximation that might not correctly model
// a custom global allocator.
if (IsStandardGlobalOpNewFunction)
symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount);
@@ -472,7 +528,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
}
}
-void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
+void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
ProgramStateRef state = Pred->getState();
@@ -513,3 +569,55 @@ void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
SVal V = state->getSVal(loc::MemRegionVal(R));
Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
}
+
+void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ const LocationContext *LocCtxt = Pred->getLocationContext();
+
+ // Get the region of the lambda itself.
+ const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion(
+ LE, LocCtxt);
+ SVal V = loc::MemRegionVal(R);
+
+ ProgramStateRef State = Pred->getState();
+
+ // If we created a new MemRegion for the lambda, we should explicitly bind
+ // the captures.
+ CXXRecordDecl::field_iterator CurField = LE->getLambdaClass()->field_begin();
+ for (LambdaExpr::const_capture_init_iterator i = LE->capture_init_begin(),
+ e = LE->capture_init_end();
+ i != e; ++i, ++CurField) {
+ FieldDecl *FieldForCapture = *CurField;
+ SVal FieldLoc = State->getLValue(FieldForCapture, V);
+
+ SVal InitVal;
+ if (!FieldForCapture->hasCapturedVLAType()) {
+ Expr *InitExpr = *i;
+ assert(InitExpr && "Capture missing initialization expression");
+ InitVal = State->getSVal(InitExpr, LocCtxt);
+ } else {
+ // The field stores the length of a captured variable-length array.
+ // These captures don't have initialization expressions; instead we
+ // get the length from the VLAType size expression.
+ Expr *SizeExpr = FieldForCapture->getCapturedVLAType()->getSizeExpr();
+ InitVal = State->getSVal(SizeExpr, LocCtxt);
+ }
+
+ State = State->bindLoc(FieldLoc, InitVal);
+ }
+
+ // Decay the Loc into an RValue, because there might be a
+ // MaterializeTemporaryExpr node above this one which expects the bound value
+ // to be an RValue.
+ SVal LambdaRVal = State->getSVal(R);
+
+ ExplodedNodeSet Tmp;
+ StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
+ // FIXME: is this the right program point kind?
+ Bldr.generateNode(LE, Pred,
+ State->BindExpr(LE, LocCtxt, LambdaRVal),
+ nullptr, ProgramPoint::PostLValueKind);
+
+ // FIXME: Move all post/pre visits to ::Visit().
+ getCheckerManager().runCheckersForPostStmt(Dst, Tmp, LE, *this);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 3f608ba..74cc8d2 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -44,19 +44,19 @@ void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
const CFG *CalleeCFG = calleeCtx->getCFG();
const CFGBlock *Entry = &(CalleeCFG->getEntry());
-
+
// Validate the CFG.
assert(Entry->empty());
assert(Entry->succ_size() == 1);
-
+
// Get the solitary successor.
const CFGBlock *Succ = *(Entry->succ_begin());
-
+
// Construct an edge representing the starting location in the callee.
BlockEdge Loc(Entry, Succ, calleeCtx);
ProgramStateRef state = Pred->getState();
-
+
// Construct a new node and add it to the worklist.
bool isNew;
ExplodedNode *Node = G.getNode(Loc, state, false, &isNew);
@@ -207,8 +207,8 @@ static bool isTemporaryPRValue(const CXXConstructExpr *E, SVal V) {
return isa<CXXTempObjectRegion>(MR);
}
-/// The call exit is simulated with a sequence of nodes, which occur between
-/// CallExitBegin and CallExitEnd. The following operations occur between the
+/// The call exit is simulated with a sequence of nodes, which occur between
+/// CallExitBegin and CallExitEnd. The following operations occur between the
/// two program points:
/// 1. CallExitBegin (triggers the start of call exit sequence)
/// 2. Bind the return value
@@ -220,12 +220,12 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
PrettyStackTraceLocationContext CrashInfo(CEBNode->getLocationContext());
const StackFrameContext *calleeCtx =
CEBNode->getLocationContext()->getCurrentStackFrame();
-
+
// The parent context might not be a stack frame, so make sure we
// look up the first enclosing stack frame.
const StackFrameContext *callerCtx =
calleeCtx->getParent()->getCurrentStackFrame();
-
+
const Stmt *CE = calleeCtx->getCallSite();
ProgramStateRef state = CEBNode->getState();
// Find the last statement in the function and the corresponding basic block.
@@ -421,7 +421,8 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
const LocationContext *CurLC = Pred->getLocationContext();
const StackFrameContext *CallerSFC = CurLC->getCurrentStackFrame();
const LocationContext *ParentOfCallee = CallerSFC;
- if (Call.getKind() == CE_Block) {
+ if (Call.getKind() == CE_Block &&
+ !cast<BlockCall>(Call).isConversionFromLambda()) {
const BlockDataRegion *BR = cast<BlockCall>(Call).getBlockRegion();
assert(BR && "If we have the block definition we should have its region");
AnalysisDeclContext *BlockCtx = AMgr.getAnalysisDeclContext(D);
@@ -429,7 +430,7 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
cast<BlockDecl>(D),
BR);
}
-
+
// This may be NULL, but that's fine.
const Expr *CallE = Call.getOriginExpr();
@@ -439,8 +440,8 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
CalleeADC->getStackFrame(ParentOfCallee, CallE,
currBldrCtx->getBlock(),
currStmtIdx);
-
-
+
+
CallEnter Loc(CallE, CalleeSFC, CurLC);
// Construct a new state which contains the mapping from actual to
@@ -690,9 +691,11 @@ static bool hasMember(const ASTContext &Ctx, const CXXRecordDecl *RD,
return true;
CXXBasePaths Paths(false, false, false);
- if (RD->lookupInBases(&CXXRecordDecl::FindOrdinaryMember,
- DeclName.getAsOpaquePtr(),
- Paths))
+ if (RD->lookupInBases(
+ [DeclName](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+ return CXXRecordDecl::FindOrdinaryMember(Specifier, Path, DeclName);
+ },
+ Paths))
return true;
return false;
@@ -767,7 +770,7 @@ static bool mayInlineDecl(AnalysisDeclContext *CalleeADC,
if (!Ctx.getSourceManager().isInMainFile(FD->getLocation()))
if (isContainerMethod(Ctx, FD))
return false;
-
+
// Conditionally control the inlining of the destructor of C++ shared_ptr.
// We don't currently do a good job modeling shared_ptr because we can't
// see the reference count, so treating as opaque is probably the best
@@ -868,7 +871,8 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
// Do not inline large functions too many times.
if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
Opts.getMaxTimesInlineLarge()) &&
- CalleeCFG->getNumBlockIDs() > 13) {
+ CalleeCFG->getNumBlockIDs() >=
+ Opts.getMinCFGSizeTreatFunctionsAsLarge()) {
NumReachedInlineCountMax++;
return false;
}
@@ -990,12 +994,12 @@ void ExprEngine::BifurcateCall(const MemRegion *BifurReg,
void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
-
+
ExplodedNodeSet dstPreVisit;
getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, RS, *this);
StmtNodeBuilder B(dstPreVisit, Dst, *currBldrCtx);
-
+
if (RS->getRetValue()) {
for (ExplodedNodeSet::iterator it = dstPreVisit.begin(),
ei = dstPreVisit.end(); it != ei; ++it) {
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
index a6611e0..92c5fe6 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
@@ -19,18 +19,18 @@
using namespace clang;
using namespace ento;
-void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex,
+void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
SVal baseVal = state->getSVal(Ex->getBase(), LCtx);
SVal location = state->getLValue(Ex->getDecl(), baseVal);
-
+
ExplodedNodeSet dstIvar;
StmtNodeBuilder Bldr(Pred, dstIvar, *currBldrCtx);
Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, location));
-
+
// Perform the post-condition check of the ObjCIvarRefExpr and store
// the created nodes in 'Dst'.
getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this);
@@ -45,7 +45,7 @@ void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
-
+
// ObjCForCollectionStmts are processed in two places. This method
// handles the case where an ObjCForCollectionStmt* occurs as one of the
// statements within a basic block. This transfer function does two things:
@@ -74,7 +74,7 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
const Stmt *elem = S->getElement();
ProgramStateRef state = Pred->getState();
SVal elementV;
-
+
if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
assert(elemD->getInit() == nullptr);
@@ -83,7 +83,7 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
else {
elementV = state->getSVal(elem, Pred->getLocationContext());
}
-
+
ExplodedNodeSet dstLocation;
evalLocation(dstLocation, S, elem, Pred, state, elementV, nullptr, false);
@@ -95,17 +95,17 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
Pred = *NI;
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
-
+
// Handle the case where the container still has elements.
SVal TrueV = svalBuilder.makeTruthVal(1);
ProgramStateRef hasElems = state->BindExpr(S, LCtx, TrueV);
-
+
// Handle the case where the container has no elements.
SVal FalseV = svalBuilder.makeTruthVal(0);
ProgramStateRef noElems = state->BindExpr(S, LCtx, FalseV);
if (Optional<loc::MemRegionVal> MV = elementV.getAs<loc::MemRegionVal>())
- if (const TypedValueRegion *R =
+ if (const TypedValueRegion *R =
dyn_cast<TypedValueRegion>(MV->getRegion())) {
// FIXME: The proper thing to do is to really iterate over the
// container. We will do this with dispatch logic to the store.
@@ -116,12 +116,12 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
currBldrCtx->blockCount());
SVal V = svalBuilder.makeLoc(Sym);
hasElems = hasElems->bindLoc(elementV, V);
-
+
// Bind the location to 'nil' on the false branch.
SVal nilV = svalBuilder.makeIntVal(0, T);
noElems = noElems->bindLoc(elementV, nilV);
}
-
+
// Create the new nodes.
Bldr.generateNode(S, Pred, hasElems);
Bldr.generateNode(S, Pred, noElems);
@@ -139,6 +139,76 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
CallEventRef<ObjCMethodCall> Msg =
CEMgr.getObjCMethodCall(ME, Pred->getState(), Pred->getLocationContext());
+ // There are three cases for the receiver:
+ // (1) it is definitely nil,
+ // (2) it is definitely non-nil, and
+ // (3) we don't know.
+ //
+ // If the receiver is definitely nil, we skip the pre/post callbacks and
+ // instead call the ObjCMessageNil callbacks and return.
+ //
+ // If the receiver is definitely non-nil, we call the pre- callbacks,
+ // evaluate the call, and call the post- callbacks.
+ //
+ // If we don't know, we drop the potential nil flow and instead
+ // continue from the assumed non-nil state as in (2). This approach
+ // intentionally drops coverage in order to prevent false alarms
+ // in the following scenario:
+ //
+ // id result = [o someMethod]
+ // if (result) {
+ // if (!o) {
+ // // <-- This program point should be unreachable because if o is nil
+ // // it must the case that result is nil as well.
+ // }
+ // }
+ //
+ // We could avoid dropping coverage by performing an explicit case split
+ // on each method call -- but this would get very expensive. An alternative
+ // would be to introduce lazy constraints.
+ // FIXME: This ignores many potential bugs (<rdar://problem/11733396>).
+ // Revisit once we have lazier constraints.
+ if (Msg->isInstanceMessage()) {
+ SVal recVal = Msg->getReceiverSVal();
+ if (!recVal.isUndef()) {
+ // Bifurcate the state into nil and non-nil ones.
+ DefinedOrUnknownSVal receiverVal =
+ recVal.castAs<DefinedOrUnknownSVal>();
+ ProgramStateRef State = Pred->getState();
+
+ ProgramStateRef notNilState, nilState;
+ std::tie(notNilState, nilState) = State->assume(receiverVal);
+
+ // Receiver is definitely nil, so run ObjCMessageNil callbacks and return.
+ if (nilState && !notNilState) {
+ StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
+ bool HasTag = Pred->getLocation().getTag();
+ Pred = Bldr.generateNode(ME, Pred, nilState, nullptr,
+ ProgramPoint::PreStmtKind);
+ assert((Pred || HasTag) && "Should have cached out already!");
+ (void)HasTag;
+ if (!Pred)
+ return;
+ getCheckerManager().runCheckersForObjCMessageNil(Dst, Pred,
+ *Msg, *this);
+ return;
+ }
+
+ ExplodedNodeSet dstNonNil;
+ StmtNodeBuilder Bldr(Pred, dstNonNil, *currBldrCtx);
+ // Generate a transition to the non-nil state, dropping any potential
+ // nil flow.
+ if (notNilState != State) {
+ bool HasTag = Pred->getLocation().getTag();
+ Pred = Bldr.generateNode(ME, Pred, notNilState);
+ assert((Pred || HasTag) && "Should have cached out already!");
+ (void)HasTag;
+ if (!Pred)
+ return;
+ }
+ }
+ }
+
// Handle the previsits checks.
ExplodedNodeSet dstPrevisit;
getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred,
@@ -156,39 +226,16 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
ExplodedNode *Pred = *DI;
ProgramStateRef State = Pred->getState();
CallEventRef<ObjCMethodCall> UpdatedMsg = Msg.cloneWithState(State);
-
+
if (UpdatedMsg->isInstanceMessage()) {
SVal recVal = UpdatedMsg->getReceiverSVal();
if (!recVal.isUndef()) {
- // Bifurcate the state into nil and non-nil ones.
- DefinedOrUnknownSVal receiverVal =
- recVal.castAs<DefinedOrUnknownSVal>();
-
- ProgramStateRef notNilState, nilState;
- std::tie(notNilState, nilState) = State->assume(receiverVal);
-
- // There are three cases: can be nil or non-nil, must be nil, must be
- // non-nil. We ignore must be nil, and merge the rest two into non-nil.
- // FIXME: This ignores many potential bugs (<rdar://problem/11733396>).
- // Revisit once we have lazier constraints.
- if (nilState && !notNilState) {
- continue;
- }
-
- // Check if the "raise" message was sent.
- assert(notNilState);
if (ObjCNoRet.isImplicitNoReturn(ME)) {
// If we raise an exception, for now treat it as a sink.
// Eventually we will want to handle exceptions properly.
Bldr.generateSink(ME, Pred, State);
continue;
}
-
- // Generate a transition to non-Nil state.
- if (notNilState != State) {
- Pred = Bldr.generateNode(ME, Pred, notNilState);
- assert(Pred && "Should have cached out already!");
- }
}
} else {
// Check for special class methods that are known to not return
@@ -203,7 +250,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
defaultEvalCall(Bldr, Pred, *UpdatedMsg);
}
-
+
ExplodedNodeSet dstPostvisit;
getCheckerManager().runCheckersForPostCall(dstPostvisit, dstEval,
*Msg, *this);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index cfcf7c6..b3edb85 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/FileManager.h"
@@ -22,6 +21,8 @@
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/IssueHash.h"
+#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -122,11 +123,11 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
// The path as already been prechecked that all parts of the path are
// from the same file and that it is non-empty.
- const SourceManager &SMgr = (*path.begin())->getLocation().getManager();
+ const SourceManager &SMgr = path.front()->getLocation().getManager();
assert(!path.empty());
FileID FID =
- (*path.begin())->getLocation().asLocation().getExpansionLoc().getFileID();
- assert(!FID.isInvalid());
+ path.front()->getLocation().asLocation().getExpansionLoc().getFileID();
+ assert(FID.isValid());
// Create a new rewriter to generate HTML.
Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOpts());
@@ -143,7 +144,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
// Retrieve the relative position of the declaration which will be used
// for the file name
FullSourceLoc L(
- SMgr.getExpansionLoc((*path.rbegin())->getLocation().asLocation()),
+ SMgr.getExpansionLoc(path.back()->getLocation().asLocation()),
SMgr);
FullSourceLoc FunL(SMgr.getExpansionLoc(Body->getLocStart()), SMgr);
offsetDecl = L.getExpansionLineNumber() - FunL.getExpansionLineNumber();
@@ -187,8 +188,8 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
DirName += '/';
}
- int LineNumber = (*path.rbegin())->getLocation().asLocation().getExpansionLineNumber();
- int ColumnNumber = (*path.rbegin())->getLocation().asLocation().getExpansionColumnNumber();
+ int LineNumber = path.back()->getLocation().asLocation().getExpansionLineNumber();
+ int ColumnNumber = path.back()->getLocation().asLocation().getExpansionColumnNumber();
// Add the name of the file as an <h1> tag.
@@ -236,6 +237,13 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
if (!BugType.empty())
os << "\n<!-- BUGTYPE " << BugType << " -->\n";
+ PathDiagnosticLocation UPDLoc = D.getUniqueingLoc();
+ FullSourceLoc L(SMgr.getExpansionLoc(UPDLoc.isValid()
+ ? UPDLoc.asLocation()
+ : D.getLocation().asLocation()),
+ SMgr);
+ const Decl *DeclWithIssue = D.getDeclWithIssue();
+
StringRef BugCategory = D.getCategory();
if (!BugCategory.empty())
os << "\n<!-- BUGCATEGORY " << BugCategory << " -->\n";
@@ -246,6 +254,10 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
os << "\n<!-- FUNCTIONNAME " << declName << " -->\n";
+ os << "\n<!-- ISSUEHASHCONTENTOFLINEINCONTEXT "
+ << GetIssueHash(SMgr, L, D.getCheckName(), D.getBugType(), DeclWithIssue,
+ PP.getLangOpts()) << " -->\n";
+
os << "\n<!-- BUGLINE "
<< LineNumber
<< " -->\n";
@@ -281,7 +293,12 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
if (!AnalyzerOpts.shouldWriteStableReportFilename()) {
llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
-
+ if (std::error_code EC =
+ llvm::sys::fs::make_absolute(Model)) {
+ llvm::errs() << "warning: could not make '" << Model
+ << "' absolute: " << EC.message() << '\n';
+ return;
+ }
if (std::error_code EC =
llvm::sys::fs::createUniqueFile(Model, FD, ResultPath)) {
llvm::errs() << "warning: could not create file in '" << Directory
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp
new file mode 100644
index 0000000..0a3af3d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/IssueHash.cpp
@@ -0,0 +1,196 @@
+//===---------- IssueHash.cpp - Generate identification hashes --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/StaticAnalyzer/Core/IssueHash.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/Path.h"
+
+#include <functional>
+#include <sstream>
+#include <string>
+
+using namespace clang;
+
+// Get a string representation of the parts of the signature that can be
+// overloaded on.
+static std::string GetSignature(const FunctionDecl *Target) {
+ if (!Target)
+ return "";
+ std::string Signature;
+
+ if (!isa<CXXConstructorDecl>(Target) && !isa<CXXDestructorDecl>(Target) &&
+ !isa<CXXConversionDecl>(Target))
+ Signature.append(Target->getReturnType().getAsString()).append(" ");
+ Signature.append(Target->getQualifiedNameAsString()).append("(");
+
+ for (int i = 0, paramsCount = Target->getNumParams(); i < paramsCount; ++i) {
+ if (i)
+ Signature.append(", ");
+ Signature.append(Target->getParamDecl(i)->getType().getAsString());
+ }
+
+ if (Target->isVariadic())
+ Signature.append(", ...");
+ Signature.append(")");
+
+ const auto *TargetT =
+ llvm::dyn_cast_or_null<FunctionType>(Target->getType().getTypePtr());
+
+ if (!TargetT || !isa<CXXMethodDecl>(Target))
+ return Signature;
+
+ if (TargetT->isConst())
+ Signature.append(" const");
+ if (TargetT->isVolatile())
+ Signature.append(" volatile");
+ if (TargetT->isRestrict())
+ Signature.append(" restrict");
+
+ if (const auto *TargetPT =
+ dyn_cast_or_null<FunctionProtoType>(Target->getType().getTypePtr())) {
+ switch (TargetPT->getRefQualifier()) {
+ case RQ_LValue:
+ Signature.append(" &");
+ break;
+ case RQ_RValue:
+ Signature.append(" &&");
+ break;
+ default:
+ break;
+ }
+ }
+
+ return Signature;
+}
+
+static std::string GetEnclosingDeclContextSignature(const Decl *D) {
+ if (!D)
+ return "";
+
+ if (const auto *ND = dyn_cast<NamedDecl>(D)) {
+ std::string DeclName;
+
+ switch (ND->getKind()) {
+ case Decl::Namespace:
+ case Decl::Record:
+ case Decl::CXXRecord:
+ case Decl::Enum:
+ DeclName = ND->getQualifiedNameAsString();
+ break;
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion:
+ case Decl::CXXMethod:
+ case Decl::Function:
+ DeclName = GetSignature(dyn_cast_or_null<FunctionDecl>(ND));
+ break;
+ case Decl::ObjCMethod:
+ // ObjC Methods can not be overloaded, qualified name uniquely identifies
+ // the method.
+ DeclName = ND->getQualifiedNameAsString();
+ break;
+ default:
+ break;
+ }
+
+ return DeclName;
+ }
+
+ return "";
+}
+
+static StringRef GetNthLineOfFile(llvm::MemoryBuffer *Buffer, int Line) {
+ if (!Buffer)
+ return "";
+
+ llvm::line_iterator LI(*Buffer, false);
+ for (; !LI.is_at_eof() && LI.line_number() != Line; ++LI)
+ ;
+
+ return *LI;
+}
+
+static std::string NormalizeLine(const SourceManager &SM, FullSourceLoc &L,
+ const LangOptions &LangOpts) {
+ static StringRef Whitespaces = " \t\n";
+
+ StringRef Str = GetNthLineOfFile(SM.getBuffer(L.getFileID(), L),
+ L.getExpansionLineNumber());
+ unsigned col = Str.find_first_not_of(Whitespaces);
+ col++;
+ SourceLocation StartOfLine =
+ SM.translateLineCol(SM.getFileID(L), L.getExpansionLineNumber(), col);
+ llvm::MemoryBuffer *Buffer =
+ SM.getBuffer(SM.getFileID(StartOfLine), StartOfLine);
+ if (!Buffer)
+ return {};
+
+ const char *BufferPos = SM.getCharacterData(StartOfLine);
+
+ Token Token;
+ Lexer Lexer(SM.getLocForStartOfFile(SM.getFileID(StartOfLine)), LangOpts,
+ Buffer->getBufferStart(), BufferPos, Buffer->getBufferEnd());
+
+ size_t NextStart = 0;
+ std::ostringstream LineBuff;
+ while (!Lexer.LexFromRawLexer(Token) && NextStart < 2) {
+ if (Token.isAtStartOfLine() && NextStart++ > 0)
+ continue;
+ LineBuff << std::string(SM.getCharacterData(Token.getLocation()),
+ Token.getLength());
+ }
+
+ return LineBuff.str();
+}
+
+static llvm::SmallString<32> GetHashOfContent(StringRef Content) {
+ llvm::MD5 Hash;
+ llvm::MD5::MD5Result MD5Res;
+ SmallString<32> Res;
+
+ Hash.update(Content);
+ Hash.final(MD5Res);
+ llvm::MD5::stringifyResult(MD5Res, Res);
+
+ return Res;
+}
+
+std::string clang::GetIssueString(const SourceManager &SM,
+ FullSourceLoc &IssueLoc,
+ StringRef CheckerName, StringRef BugType,
+ const Decl *D,
+ const LangOptions &LangOpts) {
+ static StringRef Delimiter = "$";
+
+ return (llvm::Twine(CheckerName) + Delimiter +
+ GetEnclosingDeclContextSignature(D) + Delimiter +
+ llvm::utostr(IssueLoc.getExpansionColumnNumber()) + Delimiter +
+ NormalizeLine(SM, IssueLoc, LangOpts) + Delimiter + BugType)
+ .str();
+}
+
+SmallString<32> clang::GetIssueHash(const SourceManager &SM,
+ FullSourceLoc &IssueLoc,
+ StringRef CheckerName, StringRef BugType,
+ const Decl *D,
+ const LangOptions &LangOpts) {
+
+ return GetHashOfContent(
+ GetIssueString(SM, IssueLoc, CheckerName, BugType, D, LangOpts));
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
new file mode 100644
index 0000000..05865c2
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/LoopWidening.cpp
@@ -0,0 +1,68 @@
+//===--- LoopWidening.cpp - Widen loops -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// This file contains functions which are used to widen loops. A loop may be
+/// widened to approximate the exit state(s), without analyzing every
+/// iteration. The widening is done by invalidating anything which might be
+/// modified by the body of the loop.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
+
+using namespace clang;
+using namespace ento;
+
+/// Return the loops condition Stmt or NULL if LoopStmt is not a loop
+static const Expr *getLoopCondition(const Stmt *LoopStmt) {
+ switch (LoopStmt->getStmtClass()) {
+ default:
+ return nullptr;
+ case Stmt::ForStmtClass:
+ return cast<ForStmt>(LoopStmt)->getCond();
+ case Stmt::WhileStmtClass:
+ return cast<WhileStmt>(LoopStmt)->getCond();
+ case Stmt::DoStmtClass:
+ return cast<DoStmt>(LoopStmt)->getCond();
+ }
+}
+
+namespace clang {
+namespace ento {
+
+ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
+ const LocationContext *LCtx,
+ unsigned BlockCount, const Stmt *LoopStmt) {
+
+ assert(isa<ForStmt>(LoopStmt) || isa<WhileStmt>(LoopStmt) ||
+ isa<DoStmt>(LoopStmt));
+
+ // Invalidate values in the current state.
+ // TODO Make this more conservative by only invalidating values that might
+ // be modified by the body of the loop.
+ // TODO Nested loops are currently widened as a result of the invalidation
+ // being so inprecise. When the invalidation is improved, the handling
+ // of nested loops will also need to be improved.
+ const StackFrameContext *STC = LCtx->getCurrentStackFrame();
+ MemRegionManager &MRMgr = PrevState->getStateManager().getRegionManager();
+ const MemRegion *Regions[] = {MRMgr.getStackLocalsRegion(STC),
+ MRMgr.getStackArgumentsRegion(STC),
+ MRMgr.getGlobalsRegion()};
+ RegionAndSymbolInvalidationTraits ITraits;
+ for (auto *Region : Regions) {
+ ITraits.setTrait(Region,
+ RegionAndSymbolInvalidationTraits::TK_EntireMemSpace);
+ }
+ return PrevState->invalidateRegions(Regions, getLoopCondition(LoopStmt),
+ BlockCount, LCtx, true, nullptr, nullptr,
+ &ITraits);
+}
+
+} // end namespace ento
+} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 5ac8458..30052cc 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -245,7 +245,7 @@ QualType CXXBaseObjectRegion::getValueType() const {
// FoldingSet profiling.
//===----------------------------------------------------------------------===//
-void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+void MemSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger((unsigned)getKind());
}
@@ -357,31 +357,31 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion);
}
-void FunctionTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
+void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const NamedDecl *FD,
const MemRegion*) {
- ID.AddInteger(MemRegion::FunctionTextRegionKind);
+ ID.AddInteger(MemRegion::FunctionCodeRegionKind);
ID.AddPointer(FD);
}
-void FunctionTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- FunctionTextRegion::ProfileRegion(ID, FD, superRegion);
+void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ FunctionCodeRegion::ProfileRegion(ID, FD, superRegion);
}
-void BlockTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
+void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const BlockDecl *BD, CanQualType,
const AnalysisDeclContext *AC,
const MemRegion*) {
- ID.AddInteger(MemRegion::BlockTextRegionKind);
+ ID.AddInteger(MemRegion::BlockCodeRegionKind);
ID.AddPointer(BD);
}
-void BlockTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- BlockTextRegion::ProfileRegion(ID, BD, locTy, AC, superRegion);
+void BlockCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC, superRegion);
}
void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- const BlockTextRegion *BC,
+ const BlockCodeRegion *BC,
const LocationContext *LC,
unsigned BlkCount,
const MemRegion *sReg) {
@@ -457,11 +457,11 @@ void AllocaRegion::dumpToStream(raw_ostream &os) const {
os << "alloca{" << (const void*) Ex << ',' << Cnt << '}';
}
-void FunctionTextRegion::dumpToStream(raw_ostream &os) const {
+void FunctionCodeRegion::dumpToStream(raw_ostream &os) const {
os << "code{" << getDecl()->getDeclName().getAsString() << '}';
}
-void BlockTextRegion::dumpToStream(raw_ostream &os) const {
+void BlockCodeRegion::dumpToStream(raw_ostream &os) const {
os << "block_code{" << (const void*) this << '}';
}
@@ -533,6 +533,10 @@ void RegionRawOffset::dumpToStream(raw_ostream &os) const {
os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}';
}
+void CodeSpaceRegion::dumpToStream(raw_ostream &os) const {
+ os << "CodeSpaceRegion";
+}
+
void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const {
os << "StaticGlobalsMemSpace{" << CR << '}';
}
@@ -711,11 +715,11 @@ const HeapSpaceRegion *MemRegionManager::getHeapRegion() {
return LazyAllocate(heap);
}
-const MemSpaceRegion *MemRegionManager::getUnknownRegion() {
+const UnknownSpaceRegion *MemRegionManager::getUnknownRegion() {
return LazyAllocate(unknown);
}
-const MemSpaceRegion *MemRegionManager::getCodeRegion() {
+const CodeSpaceRegion *MemRegionManager::getCodeRegion() {
return LazyAllocate(code);
}
@@ -756,7 +760,7 @@ getStackOrCaptureRegionForDeclContext(const LocationContext *LC,
return cast<VarRegion>(I.getCapturedRegion());
}
}
-
+
LC = LC->getParent();
}
return (const StackFrameContext *)nullptr;
@@ -788,18 +792,18 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
else
sReg = getGlobalsRegion();
}
-
- // Finally handle static locals.
+
+ // Finally handle static locals.
} else {
// FIXME: Once we implement scope handling, we will need to properly lookup
// 'D' to the proper LocationContext.
const DeclContext *DC = D->getDeclContext();
llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V =
getStackOrCaptureRegionForDeclContext(LC, DC, D);
-
+
if (V.is<const VarRegion*>())
return V.get<const VarRegion*>();
-
+
const StackFrameContext *STC = V.get<const StackFrameContext*>();
if (!STC)
@@ -815,11 +819,11 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
const Decl *STCD = STC->getDecl();
if (isa<FunctionDecl>(STCD) || isa<ObjCMethodDecl>(STCD))
sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
- getFunctionTextRegion(cast<NamedDecl>(STCD)));
+ getFunctionCodeRegion(cast<NamedDecl>(STCD)));
else if (const BlockDecl *BD = dyn_cast<BlockDecl>(STCD)) {
// FIXME: The fallback type here is totally bogus -- though it should
// never be queried, it will prevent uniquing with the real
- // BlockTextRegion. Ideally we'd fix the AST so that we always had a
+ // BlockCodeRegion. Ideally we'd fix the AST so that we always had a
// signature.
QualType T;
if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten())
@@ -830,8 +834,8 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
T = getContext().getFunctionNoProtoType(T);
T = getContext().getBlockPointerType(T);
- const BlockTextRegion *BTR =
- getBlockTextRegion(BD, C.getCanonicalType(T),
+ const BlockCodeRegion *BTR =
+ getBlockCodeRegion(BD, C.getCanonicalType(T),
STC->getAnalysisDeclContext());
sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
BTR);
@@ -852,7 +856,7 @@ const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
}
const BlockDataRegion *
-MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
+MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC,
const LocationContext *LC,
unsigned blockCount) {
const MemRegion *sReg = nullptr;
@@ -925,15 +929,15 @@ MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
return R;
}
-const FunctionTextRegion *
-MemRegionManager::getFunctionTextRegion(const NamedDecl *FD) {
- return getSubRegion<FunctionTextRegion>(FD, getCodeRegion());
+const FunctionCodeRegion *
+MemRegionManager::getFunctionCodeRegion(const NamedDecl *FD) {
+ return getSubRegion<FunctionCodeRegion>(FD, getCodeRegion());
}
-const BlockTextRegion *
-MemRegionManager::getBlockTextRegion(const BlockDecl *BD, CanQualType locTy,
+const BlockCodeRegion *
+MemRegionManager::getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy,
AnalysisDeclContext *AC) {
- return getSubRegion<BlockTextRegion>(BD, locTy, AC, getCodeRegion());
+ return getSubRegion<BlockCodeRegion>(BD, locTy, AC, getCodeRegion());
}
@@ -1013,10 +1017,22 @@ MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD,
const CXXThisRegion*
MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
const LocationContext *LC) {
- const StackFrameContext *STC = LC->getCurrentStackFrame();
- assert(STC);
const PointerType *PT = thisPointerTy->getAs<PointerType>();
assert(PT);
+ // Inside the body of the operator() of a lambda a this expr might refer to an
+ // object in one of the parent location contexts.
+ const auto *D = dyn_cast<CXXMethodDecl>(LC->getDecl());
+ // FIXME: when operator() of lambda is analyzed as a top level function and
+ // 'this' refers to a this to the enclosing scope, there is no right region to
+ // return.
+ while (!LC->inTopFrame() &&
+ (!D || D->isStatic() ||
+ PT != D->getThisType(getContext())->getAs<PointerType>())) {
+ LC = LC->getParent();
+ D = dyn_cast<CXXMethodDecl>(LC->getDecl());
+ }
+ const StackFrameContext *STC = LC->getCurrentStackFrame();
+ assert(STC);
return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC));
}
@@ -1165,6 +1181,7 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
/// Returns true if \p Base is an immediate base class of \p Child
static bool isImmediateBase(const CXXRecordDecl *Child,
const CXXRecordDecl *Base) {
+ assert(Child && "Child must not be null");
// Note that we do NOT canonicalize the base class here, because
// ASTRecordLayout doesn't either. If that leads us down the wrong path,
// so be it; at least we won't crash.
@@ -1183,7 +1200,7 @@ RegionOffset MemRegion::getAsOffset() const {
while (1) {
switch (R->getKind()) {
- case GenericMemSpaceRegionKind:
+ case CodeSpaceRegionKind:
case StackLocalsSpaceRegionKind:
case StackArgumentsSpaceRegionKind:
case HeapSpaceRegionKind:
@@ -1196,8 +1213,8 @@ RegionOffset MemRegion::getAsOffset() const {
assert(Offset == 0 && !SymbolicOffsetBase);
goto Finish;
- case FunctionTextRegionKind:
- case BlockTextRegionKind:
+ case FunctionCodeRegionKind:
+ case BlockCodeRegionKind:
case BlockDataRegionKind:
// These will never have bindings, but may end up having values requested
// if the user does some strange casting.
@@ -1239,23 +1256,23 @@ RegionOffset MemRegion::getAsOffset() const {
Ty = SR->getSymbol()->getType()->getPointeeType();
RootIsSymbolic = true;
}
-
+
const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl();
if (!Child) {
// We cannot compute the offset of the base class.
SymbolicOffsetBase = R;
- }
-
- if (RootIsSymbolic) {
- // Base layers on symbolic regions may not be type-correct.
- // Double-check the inheritance here, and revert to a symbolic offset
- // if it's invalid (e.g. due to a reinterpret_cast).
- if (BOR->isVirtual()) {
- if (!Child->isVirtuallyDerivedFrom(BOR->getDecl()))
- SymbolicOffsetBase = R;
- } else {
- if (!isImmediateBase(Child, BOR->getDecl()))
- SymbolicOffsetBase = R;
+ } else {
+ if (RootIsSymbolic) {
+ // Base layers on symbolic regions may not be type-correct.
+ // Double-check the inheritance here, and revert to a symbolic offset
+ // if it's invalid (e.g. due to a reinterpret_cast).
+ if (BOR->isVirtual()) {
+ if (!Child->isVirtuallyDerivedFrom(BOR->getDecl()))
+ SymbolicOffsetBase = R;
+ } else {
+ if (!isImmediateBase(Child, BOR->getDecl()))
+ SymbolicOffsetBase = R;
+ }
}
}
@@ -1290,7 +1307,7 @@ RegionOffset MemRegion::getAsOffset() const {
if (Optional<nonloc::ConcreteInt> CI =
Index.getAs<nonloc::ConcreteInt>()) {
// Don't bother calculating precise offsets if we already have a
- // symbolic offset somewhere in the chain.
+ // symbolic offset somewhere in the chain.
if (SymbolicOffsetBase)
continue;
@@ -1324,7 +1341,7 @@ RegionOffset MemRegion::getAsOffset() const {
// Get the field number.
unsigned idx = 0;
- for (RecordDecl::field_iterator FI = RD->field_begin(),
+ for (RecordDecl::field_iterator FI = RD->field_begin(),
FE = RD->field_end(); FI != FE; ++FI, ++idx)
if (FR->getDecl() == *FI)
break;
@@ -1420,7 +1437,7 @@ BlockDataRegion::referenced_vars_begin() const {
BumpVector<const MemRegion*> *VecOriginal =
static_cast<BumpVector<const MemRegion*>*>(OriginalVars);
-
+
return BlockDataRegion::referenced_vars_iterator(Vec->begin(),
VecOriginal->begin());
}
@@ -1456,12 +1473,12 @@ const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const {
// RegionAndSymbolInvalidationTraits
//===----------------------------------------------------------------------===//
-void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym,
+void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym,
InvalidationKinds IK) {
SymTraitsMap[Sym] |= IK;
}
-void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR,
+void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR,
InvalidationKinds IK) {
assert(MR);
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
@@ -1470,13 +1487,13 @@ void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR,
MRTraitsMap[MR] |= IK;
}
-bool RegionAndSymbolInvalidationTraits::hasTrait(SymbolRef Sym,
+bool RegionAndSymbolInvalidationTraits::hasTrait(SymbolRef Sym,
InvalidationKinds IK) {
const_symbol_iterator I = SymTraitsMap.find(Sym);
if (I != SymTraitsMap.end())
return I->second & IK;
- return false;
+ return false;
}
bool RegionAndSymbolInvalidationTraits::hasTrait(const MemRegion *MR,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index c490031..504df30 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -62,8 +62,6 @@ PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {}
-PathPieces::~PathPieces() {}
-
void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
bool ShouldFlattenMacros) const {
for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
@@ -181,7 +179,7 @@ void PathDiagnostic::resetDiagnosticLocationToMainFile() {
// Reset the report containing declaration and location.
DeclWithIssue = CP->getCaller();
Loc = CP->getLocation();
-
+
return;
}
}
@@ -201,7 +199,7 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(
std::unique_ptr<PathDiagnostic> D) {
if (!D || D->path.empty())
return;
-
+
// We need to flatten the locations (convert Stmt* to locations) because
// the referenced statements may be freed by the time the diagnostics
// are emitted.
@@ -223,12 +221,12 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(
++I) {
const PathDiagnosticPiece *piece = I->get();
FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
-
+
if (FID.isInvalid()) {
FID = SMgr.getFileID(L);
} else if (SMgr.getFileID(L) != FID)
return; // FIXME: Emit a warning?
-
+
// Check the source ranges.
ArrayRef<SourceRange> Ranges = piece->getRanges();
for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
@@ -240,7 +238,7 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(
if (!L.isFileID() || SMgr.getFileID(L) != FID)
return; // FIXME: Emit a warning?
}
-
+
if (const PathDiagnosticCallPiece *call =
dyn_cast<PathDiagnosticCallPiece>(piece)) {
WorkList.push_back(&call->path);
@@ -251,10 +249,10 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(
}
}
}
-
+
if (FID.isInvalid())
return; // FIXME: Emit a warning?
- }
+ }
// Profile the node to see if we already have something matching it
llvm::FoldingSetNodeID profile;
@@ -320,7 +318,7 @@ static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
const PathDiagnosticPiece &Y) {
if (X.getKind() != Y.getKind())
return X.getKind() < Y.getKind();
-
+
FullSourceLoc XL = X.getLocation().asLocation();
FullSourceLoc YL = Y.getLocation().asLocation();
if (XL != YL)
@@ -333,7 +331,7 @@ static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
return X.getRanges().size() < Y.getRanges().size();
const SourceManager &SM = XL.getManager();
-
+
for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
SourceRange XR = X.getRanges()[i];
SourceRange YR = Y.getRanges()[i];
@@ -343,7 +341,7 @@ static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
}
}
-
+
switch (X.getKind()) {
case clang::ento::PathDiagnosticPiece::ControlFlow:
return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
@@ -420,9 +418,9 @@ void PathDiagnosticConsumer::FlushDiagnostics(
PathDiagnosticConsumer::FilesMade *Files) {
if (flushed)
return;
-
+
flushed = true;
-
+
std::vector<const PathDiagnostic *> BatchDiags;
for (llvm::FoldingSet<PathDiagnostic>::iterator it = Diags.begin(),
et = Diags.end(); it != et; ++it) {
@@ -450,7 +448,7 @@ void PathDiagnosticConsumer::FlushDiagnostics(
const PathDiagnostic *D = *it;
delete D;
}
-
+
// Clear out the FoldingSet.
Diags.clear();
}
@@ -472,7 +470,7 @@ void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
Entry = new (Entry) PDFileEntry(NodeID);
Set.InsertNode(Entry, InsertPos);
}
-
+
// Allocate persistent storage for the file name.
char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
memcpy(FileName_cstr, FileName.data(), FileName.size());
@@ -847,7 +845,7 @@ PathDiagnosticRange
SourceRange R = S->getSourceRange();
if (R.isValid())
return R;
- break;
+ break;
}
case DeclK:
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
@@ -949,7 +947,7 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
Out << "constructor";
describeClass(Out, MD->getParent(), " for ");
-
+
} else if (isa<CXXDestructorDecl>(MD)) {
if (!MD->isUserProvided()) {
Out << "destructor";
@@ -1041,7 +1039,7 @@ static void compute_path_size(const PathPieces &pieces, unsigned &size) {
for (PathPieces::const_iterator it = pieces.begin(),
et = pieces.end(); it != et; ++it) {
const PathDiagnosticPiece *piece = it->get();
- if (const PathDiagnosticCallPiece *cp =
+ if (const PathDiagnosticCallPiece *cp =
dyn_cast<PathDiagnosticCallPiece>(piece)) {
compute_path_size(cp->path, size);
}
@@ -1077,12 +1075,12 @@ void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
I != E; ++I) {
ID.AddInteger(I->getBegin().getRawEncoding());
ID.AddInteger(I->getEnd().getRawEncoding());
- }
+ }
}
void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
PathDiagnosticPiece::Profile(ID);
- for (PathPieces::const_iterator it = path.begin(),
+ for (PathPieces::const_iterator it = path.begin(),
et = path.end(); it != et; ++it) {
ID.Add(**it);
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index e0aff58..55e1222 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -11,13 +11,13 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/PlistSupport.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
@@ -171,7 +171,7 @@ static void ReportEvent(raw_ostream &o, const PathDiagnosticPiece& P,
--indent;
Indent(o, indent) << "</array>\n";
}
-
+
// Output the call depth.
Indent(o, indent) << "<key>depth</key>";
EmitInteger(o, depth) << '\n';
@@ -187,7 +187,7 @@ static void ReportEvent(raw_ostream &o, const PathDiagnosticPiece& P,
Indent(o, indent) << "<key>message</key>\n";
Indent(o, indent);
EmitString(o, P.getString()) << '\n';
-
+
// Finish up.
--indent;
Indent(o, indent); o << "</dict>\n";
@@ -208,9 +208,9 @@ static void ReportCall(raw_ostream &o,
const LangOptions &LangOpts,
unsigned indent,
unsigned depth) {
-
+
IntrusiveRefCntPtr<PathDiagnosticEventPiece> callEnter =
- P.getCallEnterEvent();
+ P.getCallEnterEvent();
if (callEnter)
ReportPiece(o, *callEnter, FM, SM, LangOpts, indent, depth, true,
@@ -218,18 +218,18 @@ static void ReportCall(raw_ostream &o,
IntrusiveRefCntPtr<PathDiagnosticEventPiece> callEnterWithinCaller =
P.getCallEnterWithinCallerEvent();
-
+
++depth;
-
+
if (callEnterWithinCaller)
ReportPiece(o, *callEnterWithinCaller, FM, SM, LangOpts,
indent, depth, true);
-
+
for (PathPieces::const_iterator I = P.path.begin(), E = P.path.end();I!=E;++I)
ReportPiece(o, **I, FM, SM, LangOpts, indent, depth, true);
--depth;
-
+
IntrusiveRefCntPtr<PathDiagnosticEventPiece> callExit =
P.getCallExitEvent();
@@ -295,9 +295,9 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
const SourceManager* SM = nullptr;
if (!Diags.empty())
- SM = &(*(*Diags.begin())->path.begin())->getLocation().getManager();
+ SM = &Diags.front()->path.front()->getLocation().getManager();
+
-
for (std::vector<const PathDiagnostic*>::iterator DI = Diags.begin(),
DE = Diags.end(); DI != DE; ++DI) {
@@ -374,7 +374,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
o << " <array>\n";
- for (PathPieces::const_iterator I = D->path.begin(), E = D->path.end();
+ for (PathPieces::const_iterator I = D->path.begin(), E = D->path.end();
I != E; ++I)
ReportDiag(o, **I, FM, *SM, LangOpts);
@@ -389,7 +389,19 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
EmitString(o, D->getBugType()) << '\n';
o << " <key>check_name</key>";
EmitString(o, D->getCheckName()) << '\n';
-
+
+ o << " <!-- This hash is experimental and going to change! -->\n";
+ o << " <key>issue_hash_content_of_line_in_context</key>";
+ PathDiagnosticLocation UPDLoc = D->getUniqueingLoc();
+ FullSourceLoc L(SM->getExpansionLoc(UPDLoc.isValid()
+ ? UPDLoc.asLocation()
+ : D->getLocation().asLocation()),
+ *SM);
+ const Decl *DeclWithIssue = D->getDeclWithIssue();
+ EmitString(o, GetIssueHash(*SM, L, D->getCheckName(), D->getBugType(),
+ DeclWithIssue, LangOpts))
+ << '\n';
+
// Output information about the semantic context where
// the issue occurred.
if (const Decl *DeclWithIssue = D->getDeclWithIssue()) {
@@ -423,28 +435,23 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
// Output the bug hash for issue unique-ing. Currently, it's just an
// offset from the beginning of the function.
if (const Stmt *Body = DeclWithIssue->getBody()) {
-
+
// If the bug uniqueing location exists, use it for the hash.
// For example, this ensures that two leaks reported on the same line
// will have different issue_hashes and that the hash will identify
// the leak location even after code is added between the allocation
// site and the end of scope (leak report location).
- PathDiagnosticLocation UPDLoc = D->getUniqueingLoc();
if (UPDLoc.isValid()) {
- FullSourceLoc UL(SM->getExpansionLoc(UPDLoc.asLocation()),
- *SM);
FullSourceLoc UFunL(SM->getExpansionLoc(
D->getUniqueingDecl()->getBody()->getLocStart()), *SM);
- o << " <key>issue_hash</key><string>"
- << UL.getExpansionLineNumber() - UFunL.getExpansionLineNumber()
+ o << " <key>issue_hash_function_offset</key><string>"
+ << L.getExpansionLineNumber() - UFunL.getExpansionLineNumber()
<< "</string>\n";
// Otherwise, use the location on which the bug is reported.
} else {
- FullSourceLoc L(SM->getExpansionLoc(D->getLocation().asLocation()),
- *SM);
FullSourceLoc FunL(SM->getExpansionLoc(Body->getLocStart()), *SM);
- o << " <key>issue_hash</key><string>"
+ o << " <key>issue_hash_function_offset</key><string>"
<< L.getExpansionLineNumber() - FunL.getExpansionLineNumber()
<< "</string>\n";
}
@@ -486,5 +493,5 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
o << " </array>\n";
// Finish.
- o << "</dict>\n</plist>";
+ o << "</dict>\n</plist>";
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
index 60b32c7..100fa75 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -36,7 +36,7 @@ void ProgramStateRelease(const ProgramState *state) {
if (--s->refCount == 0) {
ProgramStateManager &Mgr = s->getStateManager();
Mgr.StateSet.RemoveNode(s);
- s->~ProgramState();
+ s->~ProgramState();
Mgr.freeStates.push_back(s);
}
}
@@ -86,7 +86,7 @@ ProgramStateManager::~ProgramStateManager() {
I->second.second(I->second.first);
}
-ProgramStateRef
+ProgramStateRef
ProgramStateManager::removeDeadBindings(ProgramStateRef state,
const StackFrameContext *LCtx,
SymbolReaper& SymReaper) {
@@ -113,7 +113,7 @@ ProgramStateManager::removeDeadBindings(ProgramStateRef state,
ProgramStateRef ProgramState::bindLoc(Loc LV, SVal V, bool notifyChanges) const {
ProgramStateManager &Mgr = getStateManager();
- ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(),
+ ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(),
LV, V));
const MemRegion *MR = LV.getAsRegion();
if (MR && Mgr.getOwningEngine() && notifyChanges)
@@ -127,15 +127,15 @@ ProgramStateRef ProgramState::bindDefault(SVal loc, SVal V) const {
const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
const StoreRef &newStore = Mgr.StoreMgr->BindDefault(getStore(), R, V);
ProgramStateRef new_state = makeWithStore(newStore);
- return Mgr.getOwningEngine() ?
- Mgr.getOwningEngine()->processRegionChange(new_state, R) :
+ return Mgr.getOwningEngine() ?
+ Mgr.getOwningEngine()->processRegionChange(new_state, R) :
new_state;
}
typedef ArrayRef<const MemRegion *> RegionList;
typedef ArrayRef<SVal> ValueList;
-ProgramStateRef
+ProgramStateRef
ProgramState::invalidateRegions(RegionList Regions,
const Expr *E, unsigned Count,
const LocationContext *LCtx,
@@ -197,11 +197,11 @@ ProgramState::invalidateRegionsImpl(ValueList Values,
if (CausedByPointerEscape) {
newState = Eng->notifyCheckersOfPointerEscape(newState, IS,
TopLevelInvalidated,
- Invalidated, Call,
+ Invalidated, Call,
*ITraits);
}
- return Eng->processRegionChanges(newState, IS, TopLevelInvalidated,
+ return Eng->processRegionChanges(newState, IS, TopLevelInvalidated,
Invalidated, Call);
}
@@ -224,7 +224,7 @@ ProgramStateRef ProgramState::killBinding(Loc LV) const {
return makeWithStore(newStore);
}
-ProgramStateRef
+ProgramStateRef
ProgramState::enterStackFrame(const CallEvent &Call,
const StackFrameContext *CalleeCtx) const {
const StoreRef &NewStore =
@@ -275,7 +275,7 @@ SVal ProgramState::getSVal(Loc location, QualType T) const {
// symbol for the call to foo(); the type of that symbol is 'char',
// not unsigned.
const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
-
+
if (V.getAs<Loc>())
return loc::ConcreteInt(NewV);
else
@@ -283,7 +283,7 @@ SVal ProgramState::getSVal(Loc location, QualType T) const {
}
}
}
-
+
return V;
}
@@ -353,11 +353,11 @@ ConditionTruthVal ProgramState::isNull(SVal V) const {
if (V.isConstant())
return false;
-
+
SymbolRef Sym = V.getAsSymbol(/* IncludeBaseRegion */ true);
if (!Sym)
return ConditionTruthVal();
-
+
return getStateManager().ConstraintMgr->isNull(this, Sym);
}
@@ -390,7 +390,7 @@ ProgramStateRef ProgramStateManager::getPersistentState(ProgramState &State) {
ProgramState *newState = nullptr;
if (!freeStates.empty()) {
newState = freeStates.back();
- freeStates.pop_back();
+ freeStates.pop_back();
}
else {
newState = (ProgramState*) Alloc.Allocate<ProgramState>();
@@ -530,25 +530,25 @@ bool ScanReachableSymbols::scan(const SymExpr *sym) {
bool wasVisited = !visited.insert(sym).second;
if (wasVisited)
return true;
-
+
if (!visitor.VisitSymbol(sym))
return false;
-
+
// TODO: should be rewritten using SymExpr::symbol_iterator.
switch (sym->getKind()) {
- case SymExpr::RegionValueKind:
- case SymExpr::ConjuredKind:
- case SymExpr::DerivedKind:
- case SymExpr::ExtentKind:
- case SymExpr::MetadataKind:
+ case SymExpr::SymbolRegionValueKind:
+ case SymExpr::SymbolConjuredKind:
+ case SymExpr::SymbolDerivedKind:
+ case SymExpr::SymbolExtentKind:
+ case SymExpr::SymbolMetadataKind:
break;
- case SymExpr::CastSymbolKind:
+ case SymExpr::SymbolCastKind:
return scan(cast<SymbolCast>(sym)->getOperand());
- case SymExpr::SymIntKind:
+ case SymExpr::SymIntExprKind:
return scan(cast<SymIntExpr>(sym)->getLHS());
- case SymExpr::IntSymKind:
+ case SymExpr::IntSymExprKind:
return scan(cast<IntSymExpr>(sym)->getRHS());
- case SymExpr::SymSymKind: {
+ case SymExpr::SymSymExprKind: {
const SymSymExpr *x = cast<SymSymExpr>(sym);
return scan(x->getLHS()) && scan(x->getRHS());
}
@@ -582,11 +582,11 @@ bool ScanReachableSymbols::scan(SVal val) {
bool ScanReachableSymbols::scan(const MemRegion *R) {
if (isa<MemSpaceRegion>(R))
return true;
-
+
bool wasVisited = !visited.insert(R).second;
if (wasVisited)
return true;
-
+
if (!visitor.VisitMemRegion(R))
return false;
@@ -722,14 +722,14 @@ bool ProgramState::isTainted(const MemRegion *Reg, TaintTagType K) const {
bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const {
if (!Sym)
return false;
-
+
// Traverse all the symbols this symbol depends on to see if any are tainted.
bool Tainted = false;
for (SymExpr::symbol_iterator SI = Sym->symbol_begin(), SE =Sym->symbol_end();
SI != SE; ++SI) {
if (!isa<SymbolData>(*SI))
continue;
-
+
const TaintTagType *Tag = get<TaintMap>(*SI);
Tainted = (Tag && *Tag == Kind);
@@ -748,40 +748,7 @@ bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const {
if (Tainted)
return true;
}
-
- return Tainted;
-}
-
-/// The GDM component containing the dynamic type info. This is a map from a
-/// symbol to its most likely type.
-REGISTER_TRAIT_WITH_PROGRAMSTATE(DynamicTypeMap,
- CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *,
- DynamicTypeInfo))
-
-DynamicTypeInfo ProgramState::getDynamicTypeInfo(const MemRegion *Reg) const {
- Reg = Reg->StripCasts();
-
- // Look up the dynamic type in the GDM.
- const DynamicTypeInfo *GDMType = get<DynamicTypeMap>(Reg);
- if (GDMType)
- return *GDMType;
-
- // Otherwise, fall back to what we know about the region.
- if (const TypedRegion *TR = dyn_cast<TypedRegion>(Reg))
- return DynamicTypeInfo(TR->getLocationType(), /*CanBeSubclass=*/false);
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) {
- SymbolRef Sym = SR->getSymbol();
- return DynamicTypeInfo(Sym->getType());
- }
-
- return DynamicTypeInfo();
+ return Tainted;
}
-ProgramStateRef ProgramState::setDynamicTypeInfo(const MemRegion *Reg,
- DynamicTypeInfo NewTy) const {
- Reg = Reg->StripCasts();
- ProgramStateRef NewState = set<DynamicTypeMap>(Reg, NewTy);
- assert(NewState);
- return NewState;
-}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 170f7c0..77b0ad3 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -81,6 +81,15 @@ public:
RangeSet(PrimRangeSet RS) : ranges(RS) {}
+ /// Create a new set with all ranges of this set and RS.
+ /// Possible intersections are not checked here.
+ RangeSet addRange(Factory &F, const RangeSet &RS) {
+ PrimRangeSet Ranges(RS.ranges);
+ for (const auto &range : ranges)
+ Ranges = F.add(Ranges, range);
+ return RangeSet(Ranges);
+ }
+
iterator begin() const { return ranges.begin(); }
iterator end() const { return ranges.end(); }
@@ -162,7 +171,7 @@ private:
case APSIntType::RTR_Below:
// The entire range is outside the symbol's set of possible values.
// If this is a conventionally-ordered range, the state is infeasible.
- if (Lower < Upper)
+ if (Lower <= Upper)
return false;
// However, if the range wraps around, it spans all possible values.
@@ -213,7 +222,7 @@ private:
case APSIntType::RTR_Above:
// The entire range is outside the symbol's set of possible values.
// If this is a conventionally-ordered range, the state is infeasible.
- if (Lower < Upper)
+ if (Lower <= Upper)
return false;
// However, if the range wraps around, it spans all possible values.
@@ -312,6 +321,14 @@ public:
const llvm::APSInt& Int,
const llvm::APSInt& Adjustment) override;
+ ProgramStateRef assumeSymbolWithinInclusiveRange(
+ ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
+ const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
+
+ ProgramStateRef assumeSymbolOutOfInclusiveRange(
+ ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
+ const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
+
const llvm::APSInt* getSymVal(ProgramStateRef St,
SymbolRef sym) const override;
ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
@@ -324,6 +341,20 @@ public:
private:
RangeSet::Factory F;
+ RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment);
+ RangeSet getSymGTRange(ProgramStateRef St, SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment);
+ RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment);
+ RangeSet getSymLERange(const RangeSet &RS, const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment);
+ RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment);
};
} // end anonymous namespace
@@ -365,7 +396,7 @@ ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State,
/// Scan all symbols referenced by the constraints. If the symbol is not alive
/// as marked in LSymbols, mark it as dead in DSymbols.
-ProgramStateRef
+ProgramStateRef
RangeConstraintManager::removeDeadBindings(ProgramStateRef state,
SymbolReaper& SymReaper) {
@@ -415,7 +446,7 @@ RangeConstraintManager::GetRange(ProgramStateRef state, SymbolRef sym) {
// As an example, the range [UINT_MAX-1, 3) contains five values: UINT_MAX-1,
// UINT_MAX, 0, 1, and 2.
-ProgramStateRef
+ProgramStateRef
RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment) {
@@ -435,7 +466,7 @@ RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym,
return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
-ProgramStateRef
+ProgramStateRef
RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment) {
@@ -450,122 +481,199 @@ RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym,
return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
-ProgramStateRef
-RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym,
- const llvm::APSInt &Int,
- const llvm::APSInt &Adjustment) {
+RangeSet RangeConstraintManager::getSymLTRange(ProgramStateRef St,
+ SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment) {
// Before we do any real work, see if the value can even show up.
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
case APSIntType::RTR_Below:
- return nullptr;
+ return F.getEmptySet();
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
- return St;
+ return GetRange(St, Sym);
}
// Special case for Int == Min. This is always false.
llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
llvm::APSInt Min = AdjustmentType.getMinValue();
if (ComparisonVal == Min)
- return nullptr;
+ return F.getEmptySet();
- llvm::APSInt Lower = Min-Adjustment;
- llvm::APSInt Upper = ComparisonVal-Adjustment;
+ llvm::APSInt Lower = Min - Adjustment;
+ llvm::APSInt Upper = ComparisonVal - Adjustment;
--Upper;
- RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
- return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
+ return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
}
-ProgramStateRef
-RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym,
+ProgramStateRef
+RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment) {
+ RangeSet New = getSymLTRange(St, Sym, Int, Adjustment);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
+}
+
+RangeSet
+RangeConstraintManager::getSymGTRange(ProgramStateRef St, SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment) {
// Before we do any real work, see if the value can even show up.
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
case APSIntType::RTR_Below:
- return St;
+ return GetRange(St, Sym);
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
- return nullptr;
+ return F.getEmptySet();
}
// Special case for Int == Max. This is always false.
llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
llvm::APSInt Max = AdjustmentType.getMaxValue();
if (ComparisonVal == Max)
- return nullptr;
+ return F.getEmptySet();
- llvm::APSInt Lower = ComparisonVal-Adjustment;
- llvm::APSInt Upper = Max-Adjustment;
+ llvm::APSInt Lower = ComparisonVal - Adjustment;
+ llvm::APSInt Upper = Max - Adjustment;
++Lower;
- RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
- return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
+ return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
}
-ProgramStateRef
-RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym,
+ProgramStateRef
+RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment) {
+ RangeSet New = getSymGTRange(St, Sym, Int, Adjustment);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
+}
+
+RangeSet
+RangeConstraintManager::getSymGERange(ProgramStateRef St, SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment) {
// Before we do any real work, see if the value can even show up.
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
case APSIntType::RTR_Below:
- return St;
+ return GetRange(St, Sym);
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
- return nullptr;
+ return F.getEmptySet();
}
// Special case for Int == Min. This is always feasible.
llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
llvm::APSInt Min = AdjustmentType.getMinValue();
if (ComparisonVal == Min)
- return St;
+ return GetRange(St, Sym);
llvm::APSInt Max = AdjustmentType.getMaxValue();
- llvm::APSInt Lower = ComparisonVal-Adjustment;
- llvm::APSInt Upper = Max-Adjustment;
+ llvm::APSInt Lower = ComparisonVal - Adjustment;
+ llvm::APSInt Upper = Max - Adjustment;
- RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
- return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
+ return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
}
-ProgramStateRef
-RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym,
+ProgramStateRef
+RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment) {
+ RangeSet New = getSymGERange(St, Sym, Int, Adjustment);
+ return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
+}
+
+RangeSet
+RangeConstraintManager::getSymLERange(const RangeSet &RS,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment) {
// Before we do any real work, see if the value can even show up.
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
case APSIntType::RTR_Below:
- return nullptr;
+ return F.getEmptySet();
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
- return St;
+ return RS;
}
// Special case for Int == Max. This is always feasible.
llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
llvm::APSInt Max = AdjustmentType.getMaxValue();
if (ComparisonVal == Max)
- return St;
+ return RS;
+
+ llvm::APSInt Min = AdjustmentType.getMinValue();
+ llvm::APSInt Lower = Min - Adjustment;
+ llvm::APSInt Upper = ComparisonVal - Adjustment;
+
+ return RS.Intersect(getBasicVals(), F, Lower, Upper);
+}
+
+RangeSet
+RangeConstraintManager::getSymLERange(ProgramStateRef St, SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment) {
+ // Before we do any real work, see if the value can even show up.
+ APSIntType AdjustmentType(Adjustment);
+ switch (AdjustmentType.testInRange(Int, true)) {
+ case APSIntType::RTR_Below:
+ return F.getEmptySet();
+ case APSIntType::RTR_Within:
+ break;
+ case APSIntType::RTR_Above:
+ return GetRange(St, Sym);
+ }
+
+ // Special case for Int == Max. This is always feasible.
+ llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
+ llvm::APSInt Max = AdjustmentType.getMaxValue();
+ if (ComparisonVal == Max)
+ return GetRange(St, Sym);
llvm::APSInt Min = AdjustmentType.getMinValue();
- llvm::APSInt Lower = Min-Adjustment;
- llvm::APSInt Upper = ComparisonVal-Adjustment;
+ llvm::APSInt Lower = Min - Adjustment;
+ llvm::APSInt Upper = ComparisonVal - Adjustment;
+
+ return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
+}
- RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
+ProgramStateRef
+RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment) {
+ RangeSet New = getSymLERange(St, Sym, Int, Adjustment);
return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
+ProgramStateRef
+RangeConstraintManager::assumeSymbolWithinInclusiveRange(
+ ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
+ const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
+ RangeSet New = getSymGERange(State, Sym, From, Adjustment);
+ if (New.isEmpty())
+ return nullptr;
+ New = getSymLERange(New, To, Adjustment);
+ return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New);
+}
+
+ProgramStateRef
+RangeConstraintManager::assumeSymbolOutOfInclusiveRange(
+ ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
+ const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
+ RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
+ RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment);
+ RangeSet New(RangeLT.addRange(F, RangeGT));
+ return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New);
+}
+
//===------------------------------------------------------------------------===
// Pretty-printing.
//===------------------------------------------------------------------------===/
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 6d41fc2..a63f6e4 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -149,7 +149,8 @@ typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
namespace {
class RegionBindingsRef : public llvm::ImmutableMapRef<const MemRegion *,
ClusterBindings> {
- ClusterBindings::Factory &CBFactory;
+ ClusterBindings::Factory *CBFactory;
+
public:
typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
ParentTy;
@@ -157,21 +158,21 @@ public:
RegionBindingsRef(ClusterBindings::Factory &CBFactory,
const RegionBindings::TreeTy *T,
RegionBindings::TreeTy::Factory *F)
- : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(T, F),
- CBFactory(CBFactory) {}
+ : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(T, F),
+ CBFactory(&CBFactory) {}
RegionBindingsRef(const ParentTy &P, ClusterBindings::Factory &CBFactory)
- : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(P),
- CBFactory(CBFactory) {}
+ : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(P),
+ CBFactory(&CBFactory) {}
RegionBindingsRef add(key_type_ref K, data_type_ref D) const {
- return RegionBindingsRef(static_cast<const ParentTy*>(this)->add(K, D),
- CBFactory);
+ return RegionBindingsRef(static_cast<const ParentTy *>(this)->add(K, D),
+ *CBFactory);
}
RegionBindingsRef remove(key_type_ref K) const {
- return RegionBindingsRef(static_cast<const ParentTy*>(this)->remove(K),
- CBFactory);
+ return RegionBindingsRef(static_cast<const ParentTy *>(this)->remove(K),
+ *CBFactory);
}
RegionBindingsRef addBinding(BindingKey K, SVal V) const;
@@ -179,16 +180,9 @@ public:
RegionBindingsRef addBinding(const MemRegion *R,
BindingKey::Kind k, SVal V) const;
- RegionBindingsRef &operator=(const RegionBindingsRef &X) {
- *static_cast<ParentTy*>(this) = X;
- return *this;
- }
-
const SVal *lookup(BindingKey K) const;
const SVal *lookup(const MemRegion *R, BindingKey::Kind k) const;
- const ClusterBindings *lookup(const MemRegion *R) const {
- return static_cast<const ParentTy*>(this)->lookup(R);
- }
+ using llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>::lookup;
RegionBindingsRef removeBinding(BindingKey K);
@@ -245,10 +239,10 @@ RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K, SVal V) const {
const MemRegion *Base = K.getBaseRegion();
const ClusterBindings *ExistingCluster = lookup(Base);
- ClusterBindings Cluster = (ExistingCluster ? *ExistingCluster
- : CBFactory.getEmptyMap());
+ ClusterBindings Cluster =
+ (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
- ClusterBindings NewCluster = CBFactory.add(Cluster, K, V);
+ ClusterBindings NewCluster = CBFactory->add(Cluster, K, V);
return add(Base, NewCluster);
}
@@ -277,7 +271,7 @@ RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
if (!Cluster)
return *this;
- ClusterBindings NewCluster = CBFactory.remove(*Cluster, K);
+ ClusterBindings NewCluster = CBFactory->remove(*Cluster, K);
if (NewCluster.isEmpty())
return remove(Base);
return add(Base, NewCluster);
@@ -470,9 +464,9 @@ public: // Part of public interface to class.
StoreRef killBinding(Store ST, Loc L) override;
void incrementReferenceCount(Store store) override {
- getRegionBindings(store).manualRetain();
+ getRegionBindings(store).manualRetain();
}
-
+
/// If the StoreManager supports it, decrement the reference count of
/// the specified Store object. If the reference count hits 0, the memory
/// associated with the object is recycled.
@@ -514,7 +508,7 @@ public: // Part of public interface to class.
SVal getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
const TypedValueRegion *R,
QualType Ty);
-
+
SVal getLazyBinding(const SubRegion *LazyBindingRegion,
RegionBindingsRef LazyBinding);
@@ -656,35 +650,25 @@ protected:
RegionBindingsRef B;
-private:
- GlobalsFilterKind GlobalsFilter;
protected:
const ClusterBindings *getCluster(const MemRegion *R) {
return B.lookup(R);
}
- /// Returns true if the memory space of the given region is one of the global
- /// regions specially included at the start of analysis.
- bool isInitiallyIncludedGlobalRegion(const MemRegion *R) {
- switch (GlobalsFilter) {
- case GFK_None:
- return false;
- case GFK_SystemOnly:
- return isa<GlobalSystemSpaceRegion>(R->getMemorySpace());
- case GFK_All:
- return isa<NonStaticGlobalSpaceRegion>(R->getMemorySpace());
- }
-
- llvm_unreachable("unknown globals filter");
+ /// Returns true if all clusters in the given memspace should be initially
+ /// included in the cluster analysis. Subclasses may provide their
+ /// own implementation.
+ bool includeEntireMemorySpace(const MemRegion *Base) {
+ return false;
}
public:
ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
- RegionBindingsRef b, GlobalsFilterKind GFK)
+ RegionBindingsRef b )
: RM(rm), Ctx(StateMgr.getContext()),
svalBuilder(StateMgr.getSValBuilder()),
- B(b), GlobalsFilter(GFK) {}
+ B(b) {}
RegionBindingsRef getRegionBindings() const { return B; }
@@ -702,8 +686,9 @@ public:
assert(!Cluster.isEmpty() && "Empty clusters should be removed");
static_cast<DERIVED*>(this)->VisitAddedToCluster(Base, Cluster);
- // If this is an interesting global region, add it the work list up front.
- if (isInitiallyIncludedGlobalRegion(Base))
+ // If the base's memspace should be entirely invalidated, add the cluster
+ // to the workspace up front.
+ if (static_cast<DERIVED*>(this)->includeEntireMemorySpace(Base))
AddToWorkList(WorkListElement(Base), &Cluster);
}
}
@@ -716,8 +701,7 @@ public:
}
bool AddToWorkList(const MemRegion *R) {
- const MemRegion *BaseR = R->getBaseRegion();
- return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
+ return static_cast<DERIVED*>(this)->AddToWorkList(R);
}
void RunWorkList() {
@@ -947,6 +931,7 @@ class invalidateRegionsWorker : public ClusterAnalysis<invalidateRegionsWorker>
InvalidatedSymbols &IS;
RegionAndSymbolInvalidationTraits &ITraits;
StoreManager::InvalidatedRegions *Regions;
+ GlobalsFilterKind GlobalsFilter;
public:
invalidateRegionsWorker(RegionStoreManager &rm,
ProgramStateManager &stateMgr,
@@ -957,14 +942,34 @@ public:
RegionAndSymbolInvalidationTraits &ITraitsIn,
StoreManager::InvalidatedRegions *r,
GlobalsFilterKind GFK)
- : ClusterAnalysis<invalidateRegionsWorker>(rm, stateMgr, b, GFK),
- Ex(ex), Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r){}
+ : ClusterAnalysis<invalidateRegionsWorker>(rm, stateMgr, b),
+ Ex(ex), Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),
+ GlobalsFilter(GFK) {}
void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);
void VisitBinding(SVal V);
+
+ using ClusterAnalysis::AddToWorkList;
+
+ bool AddToWorkList(const MemRegion *R);
+
+ /// Returns true if all clusters in the memory space for \p Base should be
+ /// be invalidated.
+ bool includeEntireMemorySpace(const MemRegion *Base);
+
+ /// Returns true if the memory space of the given region is one of the global
+ /// regions specially included at the start of invalidation.
+ bool isInitiallyIncludedGlobalRegion(const MemRegion *R);
};
}
+bool invalidateRegionsWorker::AddToWorkList(const MemRegion *R) {
+ bool doNotInvalidateSuperRegion = ITraits.hasTrait(
+ R, RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
+ const MemRegion *BaseR = doNotInvalidateSuperRegion ? R : R->getBaseRegion();
+ return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
+}
+
void invalidateRegionsWorker::VisitBinding(SVal V) {
// A symbol? Mark it touched by the invalidation.
if (SymbolRef Sym = V.getAsSymbol())
@@ -993,8 +998,8 @@ void invalidateRegionsWorker::VisitBinding(SVal V) {
void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
const ClusterBindings *C) {
- bool PreserveRegionsContents =
- ITraits.hasTrait(baseR,
+ bool PreserveRegionsContents =
+ ITraits.hasTrait(baseR,
RegionAndSymbolInvalidationTraits::TK_PreserveContents);
if (C) {
@@ -1077,6 +1082,70 @@ void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
}
if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
+ bool doNotInvalidateSuperRegion = ITraits.hasTrait(
+ baseR,
+ RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
+
+ if (doNotInvalidateSuperRegion) {
+ // We are not doing blank invalidation of the whole array region so we
+ // have to manually invalidate each elements.
+ Optional<uint64_t> NumElements;
+
+ // Compute lower and upper offsets for region within array.
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
+ NumElements = CAT->getSize().getZExtValue();
+ if (!NumElements) // We are not dealing with a constant size array
+ goto conjure_default;
+ QualType ElementTy = AT->getElementType();
+ uint64_t ElemSize = Ctx.getTypeSize(ElementTy);
+ const RegionOffset &RO = baseR->getAsOffset();
+ const MemRegion *SuperR = baseR->getBaseRegion();
+ if (RO.hasSymbolicOffset()) {
+ // If base region has a symbolic offset,
+ // we revert to invalidating the super region.
+ if (SuperR)
+ AddToWorkList(SuperR);
+ goto conjure_default;
+ }
+
+ uint64_t LowerOffset = RO.getOffset();
+ uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
+ bool UpperOverflow = UpperOffset < LowerOffset;
+
+ // Invalidate regions which are within array boundaries,
+ // or have a symbolic offset.
+ if (!SuperR)
+ goto conjure_default;
+
+ const ClusterBindings *C = B.lookup(SuperR);
+ if (!C)
+ goto conjure_default;
+
+ for (ClusterBindings::iterator I = C->begin(), E = C->end(); I != E;
+ ++I) {
+ const BindingKey &BK = I.getKey();
+ Optional<uint64_t> ROffset =
+ BK.hasSymbolicOffset() ? Optional<uint64_t>() : BK.getOffset();
+
+ // Check offset is not symbolic and within array's boundaries.
+ // Handles arrays of 0 elements and of 0-sized elements as well.
+ if (!ROffset ||
+ (ROffset &&
+ ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
+ (UpperOverflow &&
+ (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
+ (LowerOffset == UpperOffset && *ROffset == LowerOffset)))) {
+ B = B.removeBinding(I.getKey());
+ // Bound symbolic regions need to be invalidated for dead symbol
+ // detection.
+ SVal V = I.getData();
+ const MemRegion *R = V.getAsRegion();
+ if (R && isa<SymbolicRegion>(R))
+ VisitBinding(V);
+ }
+ }
+ }
+ conjure_default:
// Set the default value of the array to conjured symbol.
DefinedOrUnknownSVal V =
svalBuilder.conjureSymbolVal(baseR, Ex, LCtx,
@@ -1091,6 +1160,29 @@ void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
B = B.addBinding(baseR, BindingKey::Direct, V);
}
+bool invalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
+ const MemRegion *R) {
+ switch (GlobalsFilter) {
+ case GFK_None:
+ return false;
+ case GFK_SystemOnly:
+ return isa<GlobalSystemSpaceRegion>(R->getMemorySpace());
+ case GFK_All:
+ return isa<NonStaticGlobalSpaceRegion>(R->getMemorySpace());
+ }
+
+ llvm_unreachable("unknown globals filter");
+}
+
+bool invalidateRegionsWorker::includeEntireMemorySpace(const MemRegion *Base) {
+ if (isInitiallyIncludedGlobalRegion(Base))
+ return true;
+
+ const MemSpaceRegion *MemSpace = Base->getMemorySpace();
+ return ITraits.hasTrait(MemSpace,
+ RegionAndSymbolInvalidationTraits::TK_EntireMemSpace);
+}
+
RegionBindingsRef
RegionStoreManager::invalidateGlobalRegion(MemRegion::Kind K,
const Expr *Ex,
@@ -1273,6 +1365,10 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
const MemRegion *MR = L.castAs<loc::MemRegionVal>().getRegion();
+ if (isa<BlockDataRegion>(MR)) {
+ return UnknownVal();
+ }
+
if (isa<AllocaRegion>(MR) ||
isa<SymbolicRegion>(MR) ||
isa<CodeTextRegion>(MR)) {
@@ -1462,7 +1558,7 @@ RegionStoreManager::findLazyBinding(RegionBindingsConstRef B,
// through to look for lazy compound value. It is like a field region.
Result = findLazyBinding(B, cast<SubRegion>(BaseReg->getSuperRegion()),
originalRegion);
-
+
if (Result.second)
Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
Result.second);
@@ -1508,7 +1604,7 @@ SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,
return svalBuilder.makeIntVal(c, T);
}
}
-
+
// Check for loads from a code text region. For such loads, just give up.
if (isa<CodeTextRegion>(superR))
return UnknownVal();
@@ -1520,12 +1616,12 @@ SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,
// return *y;
// FIXME: This is a hack, and doesn't do anything really intelligent yet.
const RegionRawOffset &O = R->getAsArrayOffset();
-
+
// If we cannot reason about the offset, return an unknown value.
if (!O.getRegion())
return UnknownVal();
-
- if (const TypedValueRegion *baseR =
+
+ if (const TypedValueRegion *baseR =
dyn_cast_or_null<TypedValueRegion>(O.getRegion())) {
QualType baseT = baseR->getValueType();
if (baseT->isScalarType()) {
@@ -1616,7 +1712,7 @@ SVal RegionStoreManager::getLazyBinding(const SubRegion *LazyBindingRegion,
return Result;
}
-
+
SVal
RegionStoreManager::getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
const TypedValueRegion *R,
@@ -1670,7 +1766,7 @@ RegionStoreManager::getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
if (!index.isConstant())
hasSymbolicIndex = true;
}
-
+
// If our super region is a field or element itself, walk up the region
// hierarchy to see if there is a default value installed in an ancestor.
SR = dyn_cast<SubRegion>(Base);
@@ -1680,7 +1776,7 @@ RegionStoreManager::getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
if (isa<ElementRegion>(R)) {
// Currently we don't reason specially about Clang-style vectors. Check
// if superR is a vector and if so return Unknown.
- if (const TypedValueRegion *typedSuperR =
+ if (const TypedValueRegion *typedSuperR =
dyn_cast<TypedValueRegion>(R->getSuperRegion())) {
if (typedSuperR->getValueType()->isVectorType())
return UnknownVal();
@@ -1807,7 +1903,7 @@ RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
List.insert(List.end(), InnerList.begin(), InnerList.end());
continue;
}
-
+
List.push_back(V);
}
@@ -1844,7 +1940,7 @@ SVal RegionStoreManager::getBindingForArray(RegionBindingsConstRef B,
const TypedValueRegion *R) {
assert(Ctx.getAsConstantArrayType(R->getValueType()) &&
"Only constant array types can have compound bindings.");
-
+
return createLazyBinding(B, R);
}
@@ -2018,11 +2114,11 @@ RegionBindingsRef RegionStoreManager::bindVector(RegionBindingsConstRef B,
QualType T = R->getValueType();
assert(T->isVectorType());
const VectorType *VT = T->getAs<VectorType>(); // Use getAs for typedefs.
-
+
// Handle lazy compound values and symbolic values.
if (V.getAs<nonloc::LazyCompoundVal>() || V.getAs<nonloc::SymbolVal>())
return bindAggregate(B, R, V);
-
+
// We may get non-CompoundVal accidentally due to imprecise cast logic or
// that we are binding symbolic struct value. Kill the field values, and if
// the value is symbolic go and bind it as a "default" binding.
@@ -2039,7 +2135,7 @@ RegionBindingsRef RegionStoreManager::bindVector(RegionBindingsConstRef B,
for ( ; index != numElements ; ++index) {
if (VI == VE)
break;
-
+
NonLoc Idx = svalBuilder.makeArrayIndex(index);
const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
@@ -2081,7 +2177,7 @@ RegionStoreManager::tryBindSmallStruct(RegionBindingsConstRef B,
}
RegionBindingsRef NewB = B;
-
+
for (FieldVector::iterator I = Fields.begin(), E = Fields.end(); I != E; ++I){
const FieldRegion *SourceFR = MRMgr.getFieldRegion(*I, LCV.getRegion());
SVal V = getBindingForField(getRegionBindings(LCV.getStore()), SourceFR);
@@ -2185,7 +2281,7 @@ public:
ProgramStateManager &stateMgr,
RegionBindingsRef b, SymbolReaper &symReaper,
const StackFrameContext *LCtx)
- : ClusterAnalysis<removeDeadBindingsWorker>(rm, stateMgr, b, GFK_None),
+ : ClusterAnalysis<removeDeadBindingsWorker>(rm, stateMgr, b),
SymReaper(symReaper), CurrentLCtx(LCtx) {}
// Called by ClusterAnalysis.
@@ -2193,11 +2289,20 @@ public:
void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);
using ClusterAnalysis<removeDeadBindingsWorker>::VisitCluster;
+ using ClusterAnalysis::AddToWorkList;
+
+ bool AddToWorkList(const MemRegion *R);
+
bool UpdatePostponed();
void VisitBinding(SVal V);
};
}
+bool removeDeadBindingsWorker::AddToWorkList(const MemRegion *R) {
+ const MemRegion *BaseR = R->getBaseRegion();
+ return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
+}
+
void removeDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
const ClusterBindings &C) {
@@ -2243,8 +2348,12 @@ void removeDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
SymReaper.markLive(SymR->getSymbol());
- for (ClusterBindings::iterator I = C->begin(), E = C->end(); I != E; ++I)
+ for (ClusterBindings::iterator I = C->begin(), E = C->end(); I != E; ++I) {
+ // Element index of a binding key is live.
+ SymReaper.markElementIndicesLive(I.getKey().getRegion());
+
VisitBinding(I.getData());
+ }
}
void removeDeadBindingsWorker::VisitBinding(SVal V) {
@@ -2265,7 +2374,8 @@ void removeDeadBindingsWorker::VisitBinding(SVal V) {
// If V is a region, then add it to the worklist.
if (const MemRegion *R = V.getAsRegion()) {
AddToWorkList(R);
-
+ SymReaper.markLive(R);
+
// All regions captured by a block are also live.
if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
BlockDataRegion::referenced_vars_iterator I = BR->referenced_vars_begin(),
@@ -2274,7 +2384,7 @@ void removeDeadBindingsWorker::VisitBinding(SVal V) {
AddToWorkList(I.getCapturedRegion());
}
}
-
+
// Update the set of live symbols.
for (SymExpr::symbol_iterator SI = V.symbol_begin(), SE = V.symbol_end();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 3ed2bde..1831522 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -91,10 +91,13 @@ nonloc::ConcreteInt SValBuilder::makeBoolVal(const CXXBoolLiteralExpr *boolean){
return makeTruthVal(boolean->getValue());
}
-DefinedOrUnknownSVal
+DefinedOrUnknownSVal
SValBuilder::getRegionValueSymbolVal(const TypedValueRegion* region) {
QualType T = region->getValueType();
+ if (T->isNullPtrType())
+ return makeZeroVal(T);
+
if (!SymbolManager::canSymbolicate(T))
return UnknownVal();
@@ -112,6 +115,9 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag,
unsigned Count) {
QualType T = Ex->getType();
+ if (T->isNullPtrType())
+ return makeZeroVal(T);
+
// Compute the type of the result. If the expression is not an R-value, the
// result should be a location.
QualType ExType = Ex->getType();
@@ -126,6 +132,9 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag,
const LocationContext *LCtx,
QualType type,
unsigned count) {
+ if (type->isNullPtrType())
+ return makeZeroVal(type);
+
if (!SymbolManager::canSymbolicate(type))
return UnknownVal();
@@ -142,14 +151,17 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const Stmt *stmt,
const LocationContext *LCtx,
QualType type,
unsigned visitCount) {
+ if (type->isNullPtrType())
+ return makeZeroVal(type);
+
if (!SymbolManager::canSymbolicate(type))
return UnknownVal();
SymbolRef sym = SymMgr.conjureSymbol(stmt, LCtx, type, visitCount);
-
+
if (Loc::isLocType(type))
return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
-
+
return nonloc::SymbolVal(sym);
}
@@ -160,6 +172,8 @@ SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
QualType T = E->getType();
assert(Loc::isLocType(T));
assert(SymbolManager::canSymbolicate(T));
+ if (T->isNullPtrType())
+ return makeZeroVal(T);
SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount);
return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
@@ -185,6 +199,9 @@ SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
const TypedValueRegion *region) {
QualType T = region->getValueType();
+ if (T->isNullPtrType())
+ return makeZeroVal(T);
+
if (!SymbolManager::canSymbolicate(T))
return UnknownVal();
@@ -197,15 +214,15 @@ SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
}
DefinedSVal SValBuilder::getFunctionPointer(const FunctionDecl *func) {
- return loc::MemRegionVal(MemMgr.getFunctionTextRegion(func));
+ return loc::MemRegionVal(MemMgr.getFunctionCodeRegion(func));
}
DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *block,
CanQualType locTy,
const LocationContext *locContext,
unsigned blockCount) {
- const BlockTextRegion *BC =
- MemMgr.getBlockTextRegion(block, locTy, locContext->getAnalysisDeclContext());
+ const BlockCodeRegion *BC =
+ MemMgr.getBlockCodeRegion(block, locTy, locContext->getAnalysisDeclContext());
const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, locContext,
blockCount);
return loc::MemRegionVal(BD);
@@ -259,6 +276,11 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
case Stmt::CXXBoolLiteralExprClass:
return makeBoolVal(cast<CXXBoolLiteralExpr>(E));
+ case Stmt::TypeTraitExprClass: {
+ const TypeTraitExpr *TE = cast<TypeTraitExpr>(E);
+ return makeTruthVal(TE->getValue(), TE->getType());
+ }
+
case Stmt::IntegerLiteralClass:
return makeIntVal(cast<IntegerLiteral>(E));
@@ -270,11 +292,17 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
case Stmt::ImplicitCastExprClass: {
const CastExpr *CE = cast<CastExpr>(E);
- if (CE->getCastKind() == CK_ArrayToPointerDecay) {
- Optional<SVal> ArrayVal = getConstantVal(CE->getSubExpr());
- if (!ArrayVal)
+ switch (CE->getCastKind()) {
+ default:
+ break;
+ case CK_ArrayToPointerDecay:
+ case CK_BitCast: {
+ const Expr *SE = CE->getSubExpr();
+ Optional<SVal> Val = getConstantVal(SE);
+ if (!Val)
return None;
- return evalCast(*ArrayVal, CE->getType(), CE->getSubExpr()->getType());
+ return evalCast(*Val, CE->getType(), SE->getType());
+ }
}
// FALLTHROUGH
}
@@ -307,7 +335,7 @@ SVal SValBuilder::makeSymExprValNN(ProgramStateRef State,
QualType ResultTy) {
if (!State->isTainted(RHS) && !State->isTainted(LHS))
return UnknownVal();
-
+
const SymExpr *symLHS = LHS.getAsSymExpr();
const SymExpr *symRHS = RHS.getAsSymExpr();
// TODO: When the Max Complexity is reached, we should conjure a symbol
@@ -395,6 +423,45 @@ static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy,
return true;
}
+// Handles casts of type CK_IntegralCast.
+// At the moment, this function will redirect to evalCast, except when the range
+// of the original value is known to be greater than the max of the target type.
+SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val,
+ QualType castTy, QualType originalTy) {
+
+ // No truncations if target type is big enough.
+ if (getContext().getTypeSize(castTy) >= getContext().getTypeSize(originalTy))
+ return evalCast(val, castTy, originalTy);
+
+ const SymExpr *se = val.getAsSymbolicExpression();
+ if (!se) // Let evalCast handle non symbolic expressions.
+ return evalCast(val, castTy, originalTy);
+
+ // Find the maximum value of the target type.
+ APSIntType ToType(getContext().getTypeSize(castTy),
+ castTy->isUnsignedIntegerType());
+ llvm::APSInt ToTypeMax = ToType.getMaxValue();
+ NonLoc ToTypeMaxVal =
+ makeIntVal(ToTypeMax.isUnsigned() ? ToTypeMax.getZExtValue()
+ : ToTypeMax.getSExtValue(),
+ castTy)
+ .castAs<NonLoc>();
+ // Check the range of the symbol being casted against the maximum value of the
+ // target type.
+ NonLoc FromVal = val.castAs<NonLoc>();
+ QualType CmpTy = getConditionType();
+ NonLoc CompVal =
+ evalBinOpNN(state, BO_LT, FromVal, ToTypeMaxVal, CmpTy).castAs<NonLoc>();
+ ProgramStateRef IsNotTruncated, IsTruncated;
+ std::tie(IsNotTruncated, IsTruncated) = state->assume(CompVal);
+ if (!IsNotTruncated && IsTruncated) {
+ // Symbol is truncated so we evaluate it as a cast.
+ NonLoc CastVal = makeNonLoc(se, originalTy, castTy);
+ return CastVal;
+ }
+ return evalCast(val, castTy, originalTy);
+}
+
// FIXME: should rewrite according to the cast kind.
SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
castTy = Context.getCanonicalType(castTy);
@@ -430,7 +497,7 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
if (shouldBeModeledWithNoOp(Context, Context.getPointerType(castTy),
Context.getPointerType(originalTy)))
return val;
-
+
// Check for casts from pointers to integers.
if (castTy->isIntegralOrEnumerationType() && Loc::isLocType(originalTy))
return evalCastFromLoc(val.castAs<Loc>(), castTy);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
index 8de939f..dffee6c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
@@ -51,7 +51,7 @@ bool SVal::hasConjuredSymbol() const {
const FunctionDecl *SVal::getAsFunctionDecl() const {
if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
const MemRegion* R = X->getRegion();
- if (const FunctionTextRegion *CTR = R->getAs<FunctionTextRegion>())
+ if (const FunctionCodeRegion *CTR = R->getAs<FunctionCodeRegion>())
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
return FD;
}
@@ -240,7 +240,7 @@ void SVal::dump() const { dumpToStream(llvm::errs()); }
void SVal::dumpToStream(raw_ostream &os) const {
switch (getBaseKind()) {
- case UnknownKind:
+ case UnknownValKind:
os << "Unknown";
break;
case NonLocKind:
@@ -249,7 +249,7 @@ void SVal::dumpToStream(raw_ostream &os) const {
case LocKind:
castAs<Loc>().dumpToStream(os);
break;
- case UndefinedKind:
+ case UndefinedValKind:
os << "Undefined";
break;
}
@@ -313,7 +313,7 @@ void Loc::dumpToStream(raw_ostream &os) const {
case loc::GotoLabelKind:
os << "&&" << castAs<loc::GotoLabel>().getLabel()->getName();
break;
- case loc::MemRegionKind:
+ case loc::MemRegionValKind:
os << '&' << castAs<loc::MemRegionVal>().getRegion()->getString();
break;
default:
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
index 35930e4..4051242 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
@@ -190,6 +190,42 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
} // end switch
}
+ProgramStateRef SimpleConstraintManager::assumeWithinInclusiveRange(
+ ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
+ const llvm::APSInt &To, bool InRange) {
+
+ assert(From.isUnsigned() == To.isUnsigned() &&
+ From.getBitWidth() == To.getBitWidth() &&
+ "Values should have same types!");
+
+ if (!canReasonAbout(Value)) {
+ // Just add the constraint to the expression without trying to simplify.
+ SymbolRef Sym = Value.getAsSymExpr();
+ assert(Sym);
+ return assumeSymWithinInclusiveRange(State, Sym, From, To, InRange);
+ }
+
+ switch (Value.getSubKind()) {
+ default:
+ llvm_unreachable("'assumeWithinInclusiveRange' is not implemented"
+ "for this NonLoc");
+
+ case nonloc::LocAsIntegerKind:
+ case nonloc::SymbolValKind: {
+ if (SymbolRef Sym = Value.getAsSymbol())
+ return assumeSymWithinInclusiveRange(State, Sym, From, To, InRange);
+ return State;
+ } // end switch
+
+ case nonloc::ConcreteIntKind: {
+ const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue();
+ bool IsInRange = IntVal >= From && IntVal <= To;
+ bool isFeasible = (IsInRange == InRange);
+ return isFeasible ? State : nullptr;
+ }
+ } // end switch
+}
+
static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment) {
// Is it a "($sym+constant1)" expression?
if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
@@ -262,6 +298,37 @@ ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,
} // end switch
}
+ProgramStateRef
+SimpleConstraintManager::assumeSymWithinInclusiveRange(ProgramStateRef State,
+ SymbolRef Sym,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool InRange) {
+ // Get the type used for calculating wraparound.
+ BasicValueFactory &BVF = getBasicVals();
+ APSIntType WraparoundType = BVF.getAPSIntType(Sym->getType());
+
+ llvm::APSInt Adjustment = WraparoundType.getZeroValue();
+ SymbolRef AdjustedSym = Sym;
+ computeAdjustment(AdjustedSym, Adjustment);
+
+ // Convert the right-hand side integer as necessary.
+ APSIntType ComparisonType = std::max(WraparoundType, APSIntType(From));
+ llvm::APSInt ConvertedFrom = ComparisonType.convert(From);
+ llvm::APSInt ConvertedTo = ComparisonType.convert(To);
+
+ // Prefer unsigned comparisons.
+ if (ComparisonType.getBitWidth() == WraparoundType.getBitWidth() &&
+ ComparisonType.isUnsigned() && !WraparoundType.isUnsigned())
+ Adjustment.setIsSigned(false);
+
+ if (InRange)
+ return assumeSymbolWithinInclusiveRange(State, AdjustedSym, ConvertedFrom,
+ ConvertedTo, Adjustment);
+ return assumeSymbolOutOfInclusiveRange(State, AdjustedSym, ConvertedFrom,
+ ConvertedTo, Adjustment);
+}
+
} // end of namespace ento
} // end of namespace clang
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
index 135cd4e..b26bc94 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
@@ -38,11 +38,24 @@ public:
ProgramStateRef assume(ProgramStateRef state, NonLoc Cond, bool Assumption);
+ ProgramStateRef assumeWithinInclusiveRange(ProgramStateRef State,
+ NonLoc Value,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool InRange) override;
+
ProgramStateRef assumeSymRel(ProgramStateRef state,
const SymExpr *LHS,
BinaryOperator::Opcode op,
const llvm::APSInt& Int);
+ ProgramStateRef assumeSymWithinInclusiveRange(ProgramStateRef State,
+ SymbolRef Sym,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool InRange);
+
+
protected:
//===------------------------------------------------------------------===//
@@ -75,6 +88,14 @@ protected:
const llvm::APSInt& V,
const llvm::APSInt& Adjustment) = 0;
+
+ virtual ProgramStateRef assumeSymbolWithinInclusiveRange(
+ ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
+ const llvm::APSInt &To, const llvm::APSInt &Adjustment) = 0;
+
+ virtual ProgramStateRef assumeSymbolOutOfInclusiveRange(
+ ProgramStateRef state, SymbolRef Sym, const llvm::APSInt &From,
+ const llvm::APSInt &To, const llvm::APSInt &Adjustment) = 0;
//===------------------------------------------------------------------===//
// Internal implementation.
//===------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index b3cab87c..72b852b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -141,9 +141,9 @@ SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) {
// unless this is a weak function or a symbolic region.
if (castTy->isBooleanType()) {
switch (val.getSubKind()) {
- case loc::MemRegionKind: {
+ case loc::MemRegionValKind: {
const MemRegion *R = val.castAs<loc::MemRegionVal>().getRegion();
- if (const FunctionTextRegion *FTR = dyn_cast<FunctionTextRegion>(R))
+ if (const FunctionCodeRegion *FTR = dyn_cast<FunctionCodeRegion>(R))
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FTR->getDecl()))
if (FD->isWeak())
// FIXME: Currently we are using an extent symbol here,
@@ -638,7 +638,7 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
// on the ABI).
// FIXME: we can probably do a comparison against other MemRegions, though.
// FIXME: is there a way to tell if two labels refer to the same location?
- return UnknownVal();
+ return UnknownVal();
case loc::ConcreteIntKind: {
// If one of the operands is a symbol and the other is a constant,
@@ -689,7 +689,7 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
// completely unknowable.
return UnknownVal();
}
- case loc::MemRegionKind: {
+ case loc::MemRegionValKind: {
if (Optional<loc::ConcreteInt> rInt = rhs.getAs<loc::ConcreteInt>()) {
// If one of the operands is a symbol and the other is a constant,
// build an expression for use by the constraint manager.
@@ -718,7 +718,7 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
// Get both values as regions, if possible.
const MemRegion *LeftMR = lhs.getAsRegion();
- assert(LeftMR && "MemRegionKind SVal doesn't have a region!");
+ assert(LeftMR && "MemRegionValKind SVal doesn't have a region!");
const MemRegion *RightMR = rhs.getAsRegion();
if (!RightMR)
@@ -863,7 +863,7 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
// Special case: rhs is a zero constant.
if (rhs.isZeroConstant())
return lhs;
-
+
// We are dealing with pointer arithmetic.
// Handle pointer arithmetic on constant values.
@@ -880,7 +880,7 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
// Offset the increment by the pointer size.
llvm::APSInt Multiplicand(rightI.getBitWidth(), /* isUnsigned */ true);
rightI *= Multiplicand;
-
+
// Compute the adjusted pointer.
switch (op) {
case BO_Add:
@@ -911,8 +911,9 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
elementType = elemReg->getElementType();
}
else if (isa<SubRegion>(region)) {
+ assert(op == BO_Add || op == BO_Sub);
+ index = (op == BO_Add) ? rhs : evalMinus(rhs);
superR = region;
- index = rhs;
if (resultTy->isAnyPointerType())
elementType = resultTy->getPointeeType();
}
@@ -922,7 +923,7 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
superR, getContext()));
}
}
- return UnknownVal();
+ return UnknownVal();
}
const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp
index 99ec1e7..de29f0e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Store.cpp
@@ -52,7 +52,7 @@ StoreRef StoreManager::BindDefault(Store store, const MemRegion *R, SVal V) {
return StoreRef(store, *this);
}
-const ElementRegion *StoreManager::GetElementZeroRegion(const MemRegion *R,
+const ElementRegion *StoreManager::GetElementZeroRegion(const MemRegion *R,
QualType T) {
NonLoc idx = svalBuilder.makeZeroArrayIndex();
assert(!T.isNull());
@@ -100,7 +100,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
// Process region cast according to the kind of the region being cast.
switch (R->getKind()) {
case MemRegion::CXXThisRegionKind:
- case MemRegion::GenericMemSpaceRegionKind:
+ case MemRegion::CodeSpaceRegionKind:
case MemRegion::StackLocalsSpaceRegionKind:
case MemRegion::StackArgumentsSpaceRegionKind:
case MemRegion::HeapSpaceRegionKind:
@@ -112,8 +112,8 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy)
llvm_unreachable("Invalid region cast");
}
- case MemRegion::FunctionTextRegionKind:
- case MemRegion::BlockTextRegionKind:
+ case MemRegion::FunctionCodeRegionKind:
+ case MemRegion::BlockCodeRegionKind:
case MemRegion::BlockDataRegionKind:
case MemRegion::StringRegionKind:
// FIXME: Need to handle arbitrary downcasts.
@@ -366,22 +366,22 @@ SVal StoreManager::evalDynamicCast(SVal Base, QualType TargetType,
/// as another region.
SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
QualType castTy, bool performTestOnly) {
-
+
if (castTy.isNull() || V.isUnknownOrUndef())
return V;
-
+
ASTContext &Ctx = svalBuilder.getContext();
- if (performTestOnly) {
+ if (performTestOnly) {
// Automatically translate references to pointers.
QualType T = R->getValueType();
if (const ReferenceType *RT = T->getAs<ReferenceType>())
T = Ctx.getPointerType(RT->getPointeeType());
-
+
assert(svalBuilder.getContext().hasSameUnqualifiedType(castTy, T));
return V;
}
-
+
return svalBuilder.dispatchCast(V, castTy);
}
@@ -393,7 +393,7 @@ SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {
const MemRegion* BaseR = nullptr;
switch (BaseL.getSubKind()) {
- case loc::MemRegionKind:
+ case loc::MemRegionValKind:
BaseR = BaseL.castAs<loc::MemRegionVal>().getRegion();
break;
@@ -424,7 +424,7 @@ SVal StoreManager::getLValueIvar(const ObjCIvarDecl *decl, SVal base) {
return getLValueFieldOrIvar(decl, base);
}
-SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
+SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset,
SVal Base) {
// If the base is an unknown or undefined value, just return it back.
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
index cca0461..2dd252c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -115,22 +115,22 @@ void SymExpr::symbol_iterator::expand() {
const SymExpr *SE = itr.pop_back_val();
switch (SE->getKind()) {
- case SymExpr::RegionValueKind:
- case SymExpr::ConjuredKind:
- case SymExpr::DerivedKind:
- case SymExpr::ExtentKind:
- case SymExpr::MetadataKind:
+ case SymExpr::SymbolRegionValueKind:
+ case SymExpr::SymbolConjuredKind:
+ case SymExpr::SymbolDerivedKind:
+ case SymExpr::SymbolExtentKind:
+ case SymExpr::SymbolMetadataKind:
return;
- case SymExpr::CastSymbolKind:
+ case SymExpr::SymbolCastKind:
itr.push_back(cast<SymbolCast>(SE)->getOperand());
return;
- case SymExpr::SymIntKind:
+ case SymExpr::SymIntExprKind:
itr.push_back(cast<SymIntExpr>(SE)->getLHS());
return;
- case SymExpr::IntSymKind:
+ case SymExpr::IntSymExprKind:
itr.push_back(cast<IntSymExpr>(SE)->getRHS());
return;
- case SymExpr::SymSymKind: {
+ case SymExpr::SymSymExprKind: {
const SymSymExpr *x = cast<SymSymExpr>(SE);
itr.push_back(x->getLHS());
itr.push_back(x->getRHS());
@@ -391,6 +391,18 @@ void SymbolReaper::markLive(SymbolRef sym) {
void SymbolReaper::markLive(const MemRegion *region) {
RegionRoots.insert(region);
+ markElementIndicesLive(region);
+}
+
+void SymbolReaper::markElementIndicesLive(const MemRegion *region) {
+ for (auto SR = dyn_cast<SubRegion>(region); SR;
+ SR = dyn_cast<SubRegion>(SR->getSuperRegion())) {
+ if (auto ER = dyn_cast<ElementRegion>(SR)) {
+ SVal Idx = ER->getIndex();
+ for (auto SI = Idx.symbol_begin(), SE = Idx.symbol_end(); SI != SE; ++SI)
+ markLive(*SI);
+ }
+ }
}
void SymbolReaper::markInUse(SymbolRef sym) {
@@ -409,7 +421,7 @@ bool SymbolReaper::maybeDead(SymbolRef sym) {
bool SymbolReaper::isLiveRegion(const MemRegion *MR) {
if (RegionRoots.count(MR))
return true;
-
+
MR = MR->getBaseRegion();
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
@@ -442,39 +454,39 @@ bool SymbolReaper::isLive(SymbolRef sym) {
markDependentsLive(sym);
return true;
}
-
+
bool KnownLive;
-
+
switch (sym->getKind()) {
- case SymExpr::RegionValueKind:
+ case SymExpr::SymbolRegionValueKind:
KnownLive = isLiveRegion(cast<SymbolRegionValue>(sym)->getRegion());
break;
- case SymExpr::ConjuredKind:
+ case SymExpr::SymbolConjuredKind:
KnownLive = false;
break;
- case SymExpr::DerivedKind:
+ case SymExpr::SymbolDerivedKind:
KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol());
break;
- case SymExpr::ExtentKind:
+ case SymExpr::SymbolExtentKind:
KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion());
break;
- case SymExpr::MetadataKind:
+ case SymExpr::SymbolMetadataKind:
KnownLive = MetadataInUse.count(sym) &&
isLiveRegion(cast<SymbolMetadata>(sym)->getRegion());
if (KnownLive)
MetadataInUse.erase(sym);
break;
- case SymExpr::SymIntKind:
+ case SymExpr::SymIntExprKind:
KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS());
break;
- case SymExpr::IntSymKind:
+ case SymExpr::IntSymExprKind:
KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS());
break;
- case SymExpr::SymSymKind:
+ case SymExpr::SymSymExprKind:
KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) &&
isLive(cast<SymSymExpr>(sym)->getRHS());
break;
- case SymExpr::CastSymbolKind:
+ case SymExpr::SymbolCastKind:
KnownLive = isLive(cast<SymbolCast>(sym)->getOperand());
break;
}
@@ -525,7 +537,7 @@ bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
if (!includeStoreBindings)
return false;
-
+
unsigned &cachedQuery =
const_cast<SymbolReaper*>(this)->includedRegionCache[VR];
@@ -535,16 +547,14 @@ bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
// Query the store to see if the region occurs in any live bindings.
if (Store store = reapedStore.getStore()) {
- bool hasRegion =
+ bool hasRegion =
reapedStore.getStoreManager().includedInBindings(store, VR);
cachedQuery = hasRegion ? 1 : 2;
return hasRegion;
}
-
+
return false;
}
return VarContext->isParentOf(CurrentContext);
}
-
-SymbolVisitor::~SymbolVisitor() {}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index c957a65..d144685 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -14,7 +14,7 @@
#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
#include "ModelInjector.h"
#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/DataRecursiveASTVisitor.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -141,7 +141,7 @@ public:
namespace {
class AnalysisConsumer : public AnalysisASTConsumer,
- public DataRecursiveASTVisitor<AnalysisConsumer> {
+ public RecursiveASTVisitor<AnalysisConsumer> {
enum {
AM_None = 0,
AM_Syntax = 0x1,
@@ -168,7 +168,7 @@ public:
/// The local declaration to all declarations ratio might be very small when
/// working with a PCH file.
SetOfDecls LocalTUDecls;
-
+
// Set of PathDiagnosticConsumers. Owned by AnalysisManager.
PathDiagnosticConsumers PathConsumers;
@@ -364,11 +364,15 @@ public:
}
return true;
}
-
+
bool VisitBlockDecl(BlockDecl *BD) {
if (BD->hasBody()) {
assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false);
- HandleCode(BD, RecVisitorMode);
+ // Since we skip function template definitions, we should skip blocks
+ // declared in those functions as well.
+ if (!BD->isDependentContext()) {
+ HandleCode(BD, RecVisitorMode);
+ }
}
return true;
}
@@ -475,7 +479,7 @@ void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
CallGraphNode *N = *I;
Decl *D = N->getDecl();
-
+
// Skip the abstract root node.
if (!D)
continue;
@@ -492,10 +496,11 @@ void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
(Mgr->options.InliningMode == All ? nullptr : &VisitedCallees));
// Add the visited callees to the global visited set.
- for (SetOfConstDecls::iterator I = VisitedCallees.begin(),
- E = VisitedCallees.end(); I != E; ++I) {
- Visited.insert(*I);
- }
+ for (const Decl *Callee : VisitedCallees)
+ // Decls from CallGraph are already canonical. But Decls coming from
+ // CallExprs may be not. We should canonicalize them manually.
+ Visited.insert(isa<ObjCMethodDecl>(Callee) ? Callee
+ : Callee->getCanonicalDecl());
VisitedAsTopLevel.insert(D);
}
}
@@ -588,8 +593,8 @@ AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
// - Header files: run non-path-sensitive checks only.
// - System headers: don't run any checks.
SourceManager &SM = Ctx->getSourceManager();
- SourceLocation SL = D->hasBody() ? D->getBody()->getLocStart()
- : D->getLocation();
+ const Stmt *Body = D->getBody();
+ SourceLocation SL = Body ? Body->getLocStart() : D->getLocation();
SL = SM.getExpansionLoc(SL);
if (!Opts->AnalyzeAll && !SM.isWrittenInMainFile(SL)) {
@@ -679,11 +684,11 @@ void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
case LangOptions::NonGC:
ActionExprEngine(D, false, IMode, Visited);
break;
-
+
case LangOptions::GCOnly:
ActionExprEngine(D, true, IMode, Visited);
break;
-
+
case LangOptions::HybridGC:
ActionExprEngine(D, false, IMode, Visited);
ActionExprEngine(D, true, IMode, Visited);
@@ -778,8 +783,9 @@ void UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) {
<< ", ('arrow','true'), ('oriented', 'true'))\n";
}
-UbigraphViz::UbigraphViz(std::unique_ptr<raw_ostream> Out, StringRef Filename)
- : Out(std::move(Out)), Filename(Filename), Cntr(0) {
+UbigraphViz::UbigraphViz(std::unique_ptr<raw_ostream> OutStream,
+ StringRef Filename)
+ : Out(std::move(OutStream)), Filename(Filename), Cntr(0) {
*Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
*Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
index 7fced1e..75fa4c6 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -42,7 +42,7 @@ public:
ClangCheckerRegistry(ArrayRef<std::string> plugins,
DiagnosticsEngine *diags = nullptr);
};
-
+
} // end anonymous namespace
ClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins,
@@ -52,7 +52,12 @@ ClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins,
for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end();
i != e; ++i) {
// Get access to the plugin.
- DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str());
+ std::string err;
+ DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str(), &err);
+ if (!lib.isValid()) {
+ diags->Report(diag::err_fe_unable_to_load_plugin) << *i << err;
+ continue;
+ }
// See if it's compatible with this build of clang.
const char *pluginAPIVersion =
@@ -78,10 +83,7 @@ bool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) {
// For now, none of the static analyzer API is considered stable.
// Versions must match exactly.
- if (strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0)
- return true;
-
- return false;
+ return strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0;
}
void ClangCheckerRegistry::warnIncompatible(DiagnosticsEngine *diags,
diff --git a/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp b/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp
index 1722ede..2f3d829 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/ArgumentsAdjusters.cpp
@@ -13,15 +13,13 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/ArgumentsAdjusters.h"
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/StringRef.h"
namespace clang {
namespace tooling {
/// Add -fsyntax-only option to the commnand line arguments.
ArgumentsAdjuster getClangSyntaxOnlyAdjuster() {
- return [](const CommandLineArguments &Args) {
+ return [](const CommandLineArguments &Args, StringRef /*unused*/) {
CommandLineArguments AdjustedArgs;
for (size_t i = 0, e = Args.size(); i != e; ++i) {
StringRef Arg = Args[i];
@@ -36,7 +34,7 @@ ArgumentsAdjuster getClangSyntaxOnlyAdjuster() {
}
ArgumentsAdjuster getClangStripOutputAdjuster() {
- return [](const CommandLineArguments &Args) {
+ return [](const CommandLineArguments &Args, StringRef /*unused*/) {
CommandLineArguments AdjustedArgs;
for (size_t i = 0, e = Args.size(); i < e; ++i) {
StringRef Arg = Args[i];
@@ -55,7 +53,7 @@ ArgumentsAdjuster getClangStripOutputAdjuster() {
ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra,
ArgumentInsertPosition Pos) {
- return [Extra, Pos](const CommandLineArguments &Args) {
+ return [Extra, Pos](const CommandLineArguments &Args, StringRef /*unused*/) {
CommandLineArguments Return(Args);
CommandLineArguments::iterator I;
@@ -78,8 +76,8 @@ ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra,
ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
ArgumentsAdjuster Second) {
- return [First, Second](const CommandLineArguments &Args) {
- return Second(First(Args));
+ return [First, Second](const CommandLineArguments &Args, StringRef File) {
+ return Second(First(Args, File), File);
};
}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp b/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp
index adae178..82f5601 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/CommonOptionsParser.cpp
@@ -86,22 +86,22 @@ private:
adjustCommands(std::vector<CompileCommand> Commands) const {
for (CompileCommand &Command : Commands)
for (const auto &Adjuster : Adjusters)
- Command.CommandLine = Adjuster(Command.CommandLine);
+ Command.CommandLine = Adjuster(Command.CommandLine, Command.Filename);
return Commands;
}
};
} // namespace
-CommonOptionsParser::CommonOptionsParser(int &argc, const char **argv,
- cl::OptionCategory &Category,
- const char *Overview) {
+CommonOptionsParser::CommonOptionsParser(
+ int &argc, const char **argv, cl::OptionCategory &Category,
+ llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) {
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
static cl::opt<std::string> BuildPath("p", cl::desc("Build path"),
cl::Optional, cl::cat(Category));
static cl::list<std::string> SourcePaths(
- cl::Positional, cl::desc("<source0> [... <sourceN>]"), cl::OneOrMore,
+ cl::Positional, cl::desc("<source0> [... <sourceN>]"), OccurrencesFlag,
cl::cat(Category));
static cl::list<std::string> ArgsAfter(
@@ -116,10 +116,12 @@ CommonOptionsParser::CommonOptionsParser(int &argc, const char **argv,
cl::HideUnrelatedOptions(Category);
- Compilations.reset(FixedCompilationDatabase::loadFromCommandLine(argc,
- argv));
+ Compilations.reset(FixedCompilationDatabase::loadFromCommandLine(argc, argv));
cl::ParseCommandLineOptions(argc, argv, Overview);
SourcePathList = SourcePaths;
+ if ((OccurrencesFlag == cl::ZeroOrMore || OccurrencesFlag == cl::Optional) &&
+ SourcePathList.empty())
+ return;
if (!Compilations) {
std::string ErrorMessage;
if (!BuildPath.empty()) {
@@ -129,8 +131,12 @@ CommonOptionsParser::CommonOptionsParser(int &argc, const char **argv,
Compilations = CompilationDatabase::autoDetectFromSource(SourcePaths[0],
ErrorMessage);
}
- if (!Compilations)
- llvm::report_fatal_error(ErrorMessage);
+ if (!Compilations) {
+ llvm::errs() << "Error while trying to load a compilation database:\n"
+ << ErrorMessage << "Running without flags.\n";
+ Compilations.reset(
+ new FixedCompilationDatabase(".", std::vector<std::string>()));
+ }
}
auto AdjustingCompilations =
llvm::make_unique<ArgumentsAdjustingCompilations>(
diff --git a/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp b/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
index 2272be6..957e401 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/CompilationDatabase.cpp
@@ -299,13 +299,15 @@ FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
std::vector<std::string> ToolCommandLine(1, "clang-tool");
ToolCommandLine.insert(ToolCommandLine.end(),
CommandLine.begin(), CommandLine.end());
- CompileCommands.emplace_back(Directory, std::move(ToolCommandLine));
+ CompileCommands.emplace_back(Directory, StringRef(),
+ std::move(ToolCommandLine));
}
std::vector<CompileCommand>
FixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
std::vector<CompileCommand> Result(CompileCommands);
Result[0].CommandLine.push_back(FilePath);
+ Result[0].Filename = FilePath;
return Result;
}
@@ -325,7 +327,7 @@ namespace tooling {
// This anchor is used to force the linker to link in the generated object file
// and thus register the JSONCompilationDatabasePlugin.
extern volatile int JSONAnchorSource;
-static int JSONAnchorDest = JSONAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED JSONAnchorDest = JSONAnchorSource;
} // end namespace tooling
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Core/Lookup.cpp b/contrib/llvm/tools/clang/lib/Tooling/Core/Lookup.cpp
new file mode 100644
index 0000000..697eeb4
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Tooling/Core/Lookup.cpp
@@ -0,0 +1,113 @@
+//===--- Lookup.cpp - Framework for clang refactoring tools ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines helper methods for clang tools performing name lookup.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Core/Lookup.h"
+#include "clang/AST/Decl.h"
+using namespace clang;
+using namespace clang::tooling;
+
+static bool isInsideDifferentNamespaceWithSameName(const DeclContext *DeclA,
+ const DeclContext *DeclB) {
+ while (true) {
+ // Look past non-namespaces on DeclA.
+ while (DeclA && !isa<NamespaceDecl>(DeclA))
+ DeclA = DeclA->getParent();
+
+ // Look past non-namespaces on DeclB.
+ while (DeclB && !isa<NamespaceDecl>(DeclB))
+ DeclB = DeclB->getParent();
+
+ // We hit the root, no namespace collision.
+ if (!DeclA || !DeclB)
+ return false;
+
+ // Literally the same namespace, not a collision.
+ if (DeclA == DeclB)
+ return false;
+
+ // Now check the names. If they match we have a different namespace with the
+ // same name.
+ if (cast<NamespaceDecl>(DeclA)->getDeclName() ==
+ cast<NamespaceDecl>(DeclB)->getDeclName())
+ return true;
+
+ DeclA = DeclA->getParent();
+ DeclB = DeclB->getParent();
+ }
+}
+
+static StringRef getBestNamespaceSubstr(const DeclContext *DeclA,
+ StringRef NewName,
+ bool HadLeadingColonColon) {
+ while (true) {
+ while (DeclA && !isa<NamespaceDecl>(DeclA))
+ DeclA = DeclA->getParent();
+
+ // Fully qualified it is! Leave :: in place if it's there already.
+ if (!DeclA)
+ return HadLeadingColonColon ? NewName : NewName.substr(2);
+
+ // Otherwise strip off redundant namespace qualifications from the new name.
+ // We use the fully qualified name of the namespace and remove that part
+ // from NewName if it has an identical prefix.
+ std::string NS =
+ "::" + cast<NamespaceDecl>(DeclA)->getQualifiedNameAsString() + "::";
+ if (NewName.startswith(NS))
+ return NewName.substr(NS.size());
+
+ // No match yet. Strip of a namespace from the end of the chain and try
+ // again. This allows to get optimal qualifications even if the old and new
+ // decl only share common namespaces at a higher level.
+ DeclA = DeclA->getParent();
+ }
+}
+
+/// Check if the name specifier begins with a written "::".
+static bool isFullyQualified(const NestedNameSpecifier *NNS) {
+ while (NNS) {
+ if (NNS->getKind() == NestedNameSpecifier::Global)
+ return true;
+ NNS = NNS->getPrefix();
+ }
+ return false;
+}
+
+std::string tooling::replaceNestedName(const NestedNameSpecifier *Use,
+ const DeclContext *UseContext,
+ const NamedDecl *FromDecl,
+ StringRef ReplacementString) {
+ assert(ReplacementString.startswith("::") &&
+ "Expected fully-qualified name!");
+
+ // We can do a raw name replacement when we are not inside the namespace for
+ // the original function and it is not in the global namespace. The
+ // assumption is that outside the original namespace we must have a using
+ // statement that makes this work out and that other parts of this refactor
+ // will automatically fix using statements to point to the new function
+ const bool class_name_only = !Use;
+ const bool in_global_namespace =
+ isa<TranslationUnitDecl>(FromDecl->getDeclContext());
+ if (class_name_only && !in_global_namespace &&
+ !isInsideDifferentNamespaceWithSameName(FromDecl->getDeclContext(),
+ UseContext)) {
+ auto Pos = ReplacementString.rfind("::");
+ return Pos != StringRef::npos ? ReplacementString.substr(Pos + 2)
+ : ReplacementString;
+ }
+ // We did not match this because of a using statement, so we will need to
+ // figure out how good a namespace match we have with our destination type.
+ // We work backwards (from most specific possible namespace to least
+ // specific).
+ return getBestNamespaceSubstr(UseContext, ReplacementString,
+ isFullyQualified(Use));
+}
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp b/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
index 6d37a49..47bbdeb 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Core/Replacement.cpp
@@ -113,15 +113,7 @@ void Replacement::setFromSourceLocation(const SourceManager &Sources,
const std::pair<FileID, unsigned> DecomposedLocation =
Sources.getDecomposedLoc(Start);
const FileEntry *Entry = Sources.getFileEntryForID(DecomposedLocation.first);
- if (Entry) {
- // Make FilePath absolute so replacements can be applied correctly when
- // relative paths for files are used.
- llvm::SmallString<256> FilePath(Entry->getName());
- std::error_code EC = llvm::sys::fs::make_absolute(FilePath);
- this->FilePath = EC ? FilePath.c_str() : Entry->getName();
- } else {
- this->FilePath = InvalidLocation;
- }
+ this->FilePath = Entry ? Entry->getName() : InvalidLocation;
this->ReplacementRange = Range(DecomposedLocation.second, Length);
this->ReplacementText = ReplacementText;
}
@@ -151,34 +143,32 @@ void Replacement::setFromSourceRange(const SourceManager &Sources,
ReplacementText);
}
-unsigned shiftedCodePosition(const Replacements &Replaces, unsigned Position) {
- unsigned NewPosition = Position;
- for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E;
- ++I) {
- if (I->getOffset() >= Position)
- break;
- if (I->getOffset() + I->getLength() > Position)
- NewPosition += I->getOffset() + I->getLength() - Position;
- NewPosition += I->getReplacementText().size() - I->getLength();
+template <typename T>
+unsigned shiftedCodePositionInternal(const T &Replaces, unsigned Position) {
+ unsigned Offset = 0;
+ for (const auto& R : Replaces) {
+ if (R.getOffset() + R.getLength() <= Position) {
+ Offset += R.getReplacementText().size() - R.getLength();
+ continue;
+ }
+ if (R.getOffset() < Position &&
+ R.getOffset() + R.getReplacementText().size() <= Position) {
+ Position = R.getOffset() + R.getReplacementText().size() - 1;
+ }
+ break;
}
- return NewPosition;
+ return Position + Offset;
+}
+
+unsigned shiftedCodePosition(const Replacements &Replaces, unsigned Position) {
+ return shiftedCodePositionInternal(Replaces, Position);
}
// FIXME: Remove this function when Replacements is implemented as std::vector
// instead of std::set.
unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces,
unsigned Position) {
- unsigned NewPosition = Position;
- for (std::vector<Replacement>::const_iterator I = Replaces.begin(),
- E = Replaces.end();
- I != E; ++I) {
- if (I->getOffset() >= Position)
- break;
- if (I->getOffset() + I->getLength() > Position)
- NewPosition += I->getOffset() + I->getLength() - Position;
- NewPosition += I->getReplacementText().size() - I->getLength();
- }
- return NewPosition;
+ return shiftedCodePositionInternal(Replaces, Position);
}
void deduplicate(std::vector<Replacement> &Replaces,
@@ -265,19 +255,18 @@ bool applyAllReplacements(const std::vector<Replacement> &Replaces,
}
std::string applyAllReplacements(StringRef Code, const Replacements &Replaces) {
- FileManager Files((FileSystemOptions()));
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ FileManager Files(FileSystemOptions(), InMemoryFileSystem);
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
new DiagnosticOptions);
SourceManager SourceMgr(Diagnostics, Files);
Rewriter Rewrite(SourceMgr, LangOptions());
- std::unique_ptr<llvm::MemoryBuffer> Buf =
- llvm::MemoryBuffer::getMemBuffer(Code, "<stdin>");
- const clang::FileEntry *Entry =
- Files.getVirtualFile("<stdin>", Buf->getBufferSize(), 0);
- SourceMgr.overrideFileContents(Entry, std::move(Buf));
- FileID ID =
- SourceMgr.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User);
+ InMemoryFileSystem->addFile(
+ "<stdin>", 0, llvm::MemoryBuffer::getMemBuffer(Code, "<stdin>"));
+ FileID ID = SourceMgr.createFileID(Files.getFile("<stdin>"), SourceLocation(),
+ clang::SrcMgr::C_User);
for (Replacements::const_iterator I = Replaces.begin(), E = Replaces.end();
I != E; ++I) {
Replacement Replace("<stdin>", I->getOffset(), I->getLength(),
@@ -292,6 +281,139 @@ std::string applyAllReplacements(StringRef Code, const Replacements &Replaces) {
return Result;
}
+namespace {
+// Represents a merged replacement, i.e. a replacement consisting of multiple
+// overlapping replacements from 'First' and 'Second' in mergeReplacements.
+//
+// Position projection:
+// Offsets and lengths of the replacements can generally refer to two different
+// coordinate spaces. Replacements from 'First' refer to the original text
+// whereas replacements from 'Second' refer to the text after applying 'First'.
+//
+// MergedReplacement always operates in the coordinate space of the original
+// text, i.e. transforms elements from 'Second' to take into account what was
+// changed based on the elements from 'First'.
+//
+// We can correctly calculate this projection as we look at the replacements in
+// order of strictly increasing offsets.
+//
+// Invariants:
+// * We always merge elements from 'First' into elements from 'Second' and vice
+// versa. Within each set, the replacements are non-overlapping.
+// * We only extend to the right, i.e. merge elements with strictly increasing
+// offsets.
+class MergedReplacement {
+public:
+ MergedReplacement(const Replacement &R, bool MergeSecond, int D)
+ : MergeSecond(MergeSecond), Delta(D), FilePath(R.getFilePath()),
+ Offset(R.getOffset() + (MergeSecond ? 0 : Delta)), Length(R.getLength()),
+ Text(R.getReplacementText()) {
+ Delta += MergeSecond ? 0 : Text.size() - Length;
+ DeltaFirst = MergeSecond ? Text.size() - Length : 0;
+ }
+
+ // Merges the next element 'R' into this merged element. As we always merge
+ // from 'First' into 'Second' or vice versa, the MergedReplacement knows what
+ // set the next element is coming from.
+ void merge(const Replacement &R) {
+ if (MergeSecond) {
+ unsigned REnd = R.getOffset() + Delta + R.getLength();
+ unsigned End = Offset + Text.size();
+ if (REnd > End) {
+ Length += REnd - End;
+ MergeSecond = false;
+ }
+ StringRef TextRef = Text;
+ StringRef Head = TextRef.substr(0, R.getOffset() + Delta - Offset);
+ StringRef Tail = TextRef.substr(REnd - Offset);
+ Text = (Head + R.getReplacementText() + Tail).str();
+ Delta += R.getReplacementText().size() - R.getLength();
+ } else {
+ unsigned End = Offset + Length;
+ StringRef RText = R.getReplacementText();
+ StringRef Tail = RText.substr(End - R.getOffset());
+ Text = (Text + Tail).str();
+ if (R.getOffset() + RText.size() > End) {
+ Length = R.getOffset() + R.getLength() - Offset;
+ MergeSecond = true;
+ } else {
+ Length += R.getLength() - RText.size();
+ }
+ DeltaFirst += RText.size() - R.getLength();
+ }
+ }
+
+ // Returns 'true' if 'R' starts strictly after the MergedReplacement and thus
+ // doesn't need to be merged.
+ bool endsBefore(const Replacement &R) const {
+ if (MergeSecond)
+ return Offset + Text.size() < R.getOffset() + Delta;
+ return Offset + Length < R.getOffset();
+ }
+
+ // Returns 'true' if an element from the second set should be merged next.
+ bool mergeSecond() const { return MergeSecond; }
+ int deltaFirst() const { return DeltaFirst; }
+ Replacement asReplacement() const { return {FilePath, Offset, Length, Text}; }
+
+private:
+ bool MergeSecond;
+
+ // Amount of characters that elements from 'Second' need to be shifted by in
+ // order to refer to the original text.
+ int Delta;
+
+ // Sum of all deltas (text-length - length) of elements from 'First' merged
+ // into this element. This is used to update 'Delta' once the
+ // MergedReplacement is completed.
+ int DeltaFirst;
+
+ // Data of the actually merged replacement. FilePath and Offset aren't changed
+ // as the element is only extended to the right.
+ const StringRef FilePath;
+ const unsigned Offset;
+ unsigned Length;
+ std::string Text;
+};
+} // namespace
+
+Replacements mergeReplacements(const Replacements &First,
+ const Replacements &Second) {
+ if (First.empty() || Second.empty())
+ return First.empty() ? Second : First;
+
+ // Delta is the amount of characters that replacements from 'Second' need to
+ // be shifted so that their offsets refer to the original text.
+ int Delta = 0;
+ Replacements Result;
+
+ // Iterate over both sets and always add the next element (smallest total
+ // Offset) from either 'First' or 'Second'. Merge that element with
+ // subsequent replacements as long as they overlap. See more details in the
+ // comment on MergedReplacement.
+ for (auto FirstI = First.begin(), SecondI = Second.begin();
+ FirstI != First.end() || SecondI != Second.end();) {
+ bool NextIsFirst = SecondI == Second.end() ||
+ (FirstI != First.end() &&
+ FirstI->getOffset() < SecondI->getOffset() + Delta);
+ MergedReplacement Merged(NextIsFirst ? *FirstI : *SecondI, NextIsFirst,
+ Delta);
+ ++(NextIsFirst ? FirstI : SecondI);
+
+ while ((Merged.mergeSecond() && SecondI != Second.end()) ||
+ (!Merged.mergeSecond() && FirstI != First.end())) {
+ auto &I = Merged.mergeSecond() ? SecondI : FirstI;
+ if (Merged.endsBefore(*I))
+ break;
+ Merged.merge(*I);
+ ++I;
+ }
+ Delta -= Merged.deltaFirst();
+ Result.insert(Merged.asReplacement());
+ }
+ return Result;
+}
+
} // end namespace tooling
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp b/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp
index 454a2ff..299fbdc 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/JSONCompilationDatabase.cpp
@@ -206,24 +206,33 @@ JSONCompilationDatabase::getAllFiles() const {
std::vector<CompileCommand>
JSONCompilationDatabase::getAllCompileCommands() const {
std::vector<CompileCommand> Commands;
- for (llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
- CommandsRefI = IndexByFile.begin(), CommandsRefEnd = IndexByFile.end();
- CommandsRefI != CommandsRefEnd; ++CommandsRefI) {
- getCommands(CommandsRefI->getValue(), Commands);
- }
+ getCommands(AllCommands, Commands);
return Commands;
}
+static std::vector<std::string>
+nodeToCommandLine(const std::vector<llvm::yaml::ScalarNode *> &Nodes) {
+ SmallString<1024> Storage;
+ if (Nodes.size() == 1) {
+ return unescapeCommandLine(Nodes[0]->getValue(Storage));
+ }
+ std::vector<std::string> Arguments;
+ for (auto *Node : Nodes) {
+ Arguments.push_back(Node->getValue(Storage));
+ }
+ return Arguments;
+}
+
void JSONCompilationDatabase::getCommands(
- ArrayRef<CompileCommandRef> CommandsRef,
- std::vector<CompileCommand> &Commands) const {
+ ArrayRef<CompileCommandRef> CommandsRef,
+ std::vector<CompileCommand> &Commands) const {
for (int I = 0, E = CommandsRef.size(); I != E; ++I) {
SmallString<8> DirectoryStorage;
- SmallString<1024> CommandStorage;
+ SmallString<32> FilenameStorage;
Commands.emplace_back(
- // FIXME: Escape correctly:
- CommandsRef[I].first->getValue(DirectoryStorage),
- unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage)));
+ std::get<0>(CommandsRef[I])->getValue(DirectoryStorage),
+ std::get<1>(CommandsRef[I])->getValue(FilenameStorage),
+ nodeToCommandLine(std::get<2>(CommandsRef[I])));
}
}
@@ -243,43 +252,56 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
ErrorMessage = "Expected array.";
return false;
}
- for (llvm::yaml::SequenceNode::iterator AI = Array->begin(),
- AE = Array->end();
- AI != AE; ++AI) {
- llvm::yaml::MappingNode *Object = dyn_cast<llvm::yaml::MappingNode>(&*AI);
+ for (auto& NextObject : *Array) {
+ llvm::yaml::MappingNode *Object = dyn_cast<llvm::yaml::MappingNode>(&NextObject);
if (!Object) {
ErrorMessage = "Expected object.";
return false;
}
llvm::yaml::ScalarNode *Directory = nullptr;
- llvm::yaml::ScalarNode *Command = nullptr;
+ llvm::Optional<std::vector<llvm::yaml::ScalarNode *>> Command;
llvm::yaml::ScalarNode *File = nullptr;
- for (llvm::yaml::MappingNode::iterator KVI = Object->begin(),
- KVE = Object->end();
- KVI != KVE; ++KVI) {
- llvm::yaml::Node *Value = (*KVI).getValue();
+ for (auto& NextKeyValue : *Object) {
+ llvm::yaml::ScalarNode *KeyString =
+ dyn_cast<llvm::yaml::ScalarNode>(NextKeyValue.getKey());
+ if (!KeyString) {
+ ErrorMessage = "Expected strings as key.";
+ return false;
+ }
+ SmallString<10> KeyStorage;
+ StringRef KeyValue = KeyString->getValue(KeyStorage);
+ llvm::yaml::Node *Value = NextKeyValue.getValue();
if (!Value) {
ErrorMessage = "Expected value.";
return false;
}
llvm::yaml::ScalarNode *ValueString =
dyn_cast<llvm::yaml::ScalarNode>(Value);
- if (!ValueString) {
- ErrorMessage = "Expected string as value.";
+ llvm::yaml::SequenceNode *SequenceString =
+ dyn_cast<llvm::yaml::SequenceNode>(Value);
+ if (KeyValue == "arguments" && !SequenceString) {
+ ErrorMessage = "Expected sequence as value.";
return false;
- }
- llvm::yaml::ScalarNode *KeyString =
- dyn_cast<llvm::yaml::ScalarNode>((*KVI).getKey());
- if (!KeyString) {
- ErrorMessage = "Expected strings as key.";
+ } else if (KeyValue != "arguments" && !ValueString) {
+ ErrorMessage = "Expected string as value.";
return false;
}
- SmallString<8> KeyStorage;
- if (KeyString->getValue(KeyStorage) == "directory") {
+ if (KeyValue == "directory") {
Directory = ValueString;
- } else if (KeyString->getValue(KeyStorage) == "command") {
- Command = ValueString;
- } else if (KeyString->getValue(KeyStorage) == "file") {
+ } else if (KeyValue == "arguments") {
+ Command = std::vector<llvm::yaml::ScalarNode *>();
+ for (auto &Argument : *SequenceString) {
+ auto Scalar = dyn_cast<llvm::yaml::ScalarNode>(&Argument);
+ if (!Scalar) {
+ ErrorMessage = "Only strings are allowed in 'arguments'.";
+ return false;
+ }
+ Command->push_back(Scalar);
+ }
+ } else if (KeyValue == "command") {
+ if (!Command)
+ Command = std::vector<llvm::yaml::ScalarNode *>(1, ValueString);
+ } else if (KeyValue == "file") {
File = ValueString;
} else {
ErrorMessage = ("Unknown key: \"" +
@@ -292,7 +314,7 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
return false;
}
if (!Command) {
- ErrorMessage = "Missing key: \"command\".";
+ ErrorMessage = "Missing key: \"command\" or \"arguments\".";
return false;
}
if (!Directory) {
@@ -311,8 +333,9 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
} else {
llvm::sys::path::native(FileName, NativeFilePath);
}
- IndexByFile[NativeFilePath].push_back(
- CompileCommandRef(Directory, Command));
+ auto Cmd = CompileCommandRef(Directory, File, *Command);
+ IndexByFile[NativeFilePath].push_back(Cmd);
+ AllCommands.push_back(Cmd);
MatchTrie.insert(NativeFilePath);
}
return true;
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
index f9cb7c6..fd5596e 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
@@ -17,6 +17,7 @@
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
@@ -31,13 +32,6 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"
-// For chdir, see the comment in ClangTool::run for more information.
-#ifdef LLVM_ON_WIN32
-# include <direct.h>
-#else
-# include <unistd.h>
-#endif
-
#define DEBUG_TYPE "clang-tooling"
namespace clang {
@@ -52,10 +46,11 @@ FrontendActionFactory::~FrontendActionFactory() {}
// it to be based on the same framework.
/// \brief Builds a clang driver initialized for running clang tools.
-static clang::driver::Driver *newDriver(clang::DiagnosticsEngine *Diagnostics,
- const char *BinaryName) {
+static clang::driver::Driver *newDriver(
+ clang::DiagnosticsEngine *Diagnostics, const char *BinaryName,
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
clang::driver::Driver *CompilerDriver = new clang::driver::Driver(
- BinaryName, llvm::sys::getDefaultTargetTriple(), *Diagnostics);
+ BinaryName, llvm::sys::getDefaultTargetTriple(), *Diagnostics, VFS);
CompilerDriver->setTitle("clang_based_tool");
return CompilerDriver;
}
@@ -130,18 +125,25 @@ bool runToolOnCodeWithArgs(
SmallString<16> FileNameStorage;
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
+ new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
llvm::IntrusiveRefCntPtr<FileManager> Files(
- new FileManager(FileSystemOptions()));
+ new FileManager(FileSystemOptions(), OverlayFileSystem));
ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef),
ToolAction, Files.get(), PCHContainerOps);
SmallString<1024> CodeStorage;
- Invocation.mapVirtualFile(FileNameRef,
- Code.toNullTerminatedStringRef(CodeStorage));
+ InMemoryFileSystem->addFile(FileNameRef, 0,
+ llvm::MemoryBuffer::getMemBuffer(
+ Code.toNullTerminatedStringRef(CodeStorage)));
for (auto &FilenameWithContent : VirtualMappedFiles) {
- Invocation.mapVirtualFile(FilenameWithContent.first,
- FilenameWithContent.second);
+ InMemoryFileSystem->addFile(
+ FilenameWithContent.first, 0,
+ llvm::MemoryBuffer::getMemBuffer(FilenameWithContent.second));
}
return Invocation.run();
@@ -162,6 +164,31 @@ std::string getAbsolutePath(StringRef File) {
return AbsolutePath.str();
}
+void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
+ StringRef InvokedAs) {
+ if (!CommandLine.empty() && !InvokedAs.empty()) {
+ bool AlreadyHasTarget = false;
+ bool AlreadyHasMode = false;
+ // Skip CommandLine[0].
+ for (auto Token = ++CommandLine.begin(); Token != CommandLine.end();
+ ++Token) {
+ StringRef TokenRef(*Token);
+ AlreadyHasTarget |=
+ (TokenRef == "-target" || TokenRef.startswith("-target="));
+ AlreadyHasMode |= (TokenRef == "--driver-mode" ||
+ TokenRef.startswith("--driver-mode="));
+ }
+ auto TargetMode =
+ clang::driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs);
+ if (!AlreadyHasMode && !TargetMode.second.empty()) {
+ CommandLine.insert(++CommandLine.begin(), TargetMode.second);
+ }
+ if (!AlreadyHasTarget && !TargetMode.first.empty()) {
+ CommandLine.insert(++CommandLine.begin(), {"-target", TargetMode.first});
+ }
+ }
+}
+
namespace {
class SingleFrontendActionFactory : public FrontendActionFactory {
@@ -212,7 +239,7 @@ bool ToolInvocation::run() {
DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);
const std::unique_ptr<clang::driver::Driver> Driver(
- newDriver(&Diagnostics, BinaryName));
+ newDriver(&Diagnostics, BinaryName, Files->getVirtualFileSystem()));
// Since the input might only be virtual, don't check whether it exists.
Driver->setCheckInputsExist(false);
const std::unique_ptr<clang::driver::Compilation> Compilation(
@@ -224,6 +251,7 @@ bool ToolInvocation::run() {
}
std::unique_ptr<clang::CompilerInvocation> Invocation(
newInvocation(&Diagnostics, *CC1Args));
+ // FIXME: remove this when all users have migrated!
for (const auto &It : MappedFileContents) {
// Inject the code as the given file name into the preprocessor options.
std::unique_ptr<llvm::MemoryBuffer> Input =
@@ -282,7 +310,11 @@ ClangTool::ClangTool(const CompilationDatabase &Compilations,
std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: Compilations(Compilations), SourcePaths(SourcePaths),
PCHContainerOps(PCHContainerOps),
- Files(new FileManager(FileSystemOptions())), DiagConsumer(nullptr) {
+ OverlayFileSystem(new vfs::OverlayFileSystem(vfs::getRealFileSystem())),
+ InMemoryFileSystem(new vfs::InMemoryFileSystem),
+ Files(new FileManager(FileSystemOptions(), OverlayFileSystem)),
+ DiagConsumer(nullptr) {
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
appendArgumentsAdjuster(getClangStripOutputAdjuster());
appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster());
}
@@ -320,6 +352,16 @@ int ClangTool::run(ToolAction *Action) {
if (std::error_code EC = llvm::sys::fs::current_path(InitialDirectory))
llvm::report_fatal_error("Cannot detect current path: " +
Twine(EC.message()));
+
+ // First insert all absolute paths into the in-memory VFS. These are global
+ // for all compile commands.
+ if (SeenWorkingDirectories.insert("/").second)
+ for (const auto &MappedFile : MappedFileContents)
+ if (llvm::sys::path::is_absolute(MappedFile.first))
+ InMemoryFileSystem->addFile(
+ MappedFile.first, 0,
+ llvm::MemoryBuffer::getMemBuffer(MappedFile.second));
+
bool ProcessingFailed = false;
for (const auto &SourcePath : SourcePaths) {
std::string File(getAbsolutePath(SourcePath));
@@ -350,12 +392,24 @@ int ClangTool::run(ToolAction *Action) {
// difference for example on network filesystems, where symlinks might be
// switched during runtime of the tool. Fixing this depends on having a
// file system abstraction that allows openat() style interactions.
- if (chdir(CompileCommand.Directory.c_str()))
+ if (OverlayFileSystem->setCurrentWorkingDirectory(
+ CompileCommand.Directory))
llvm::report_fatal_error("Cannot chdir into \"" +
Twine(CompileCommand.Directory) + "\n!");
+
+ // Now fill the in-memory VFS with the relative file mappings so it will
+ // have the correct relative paths. We never remove mappings but that
+ // should be fine.
+ if (SeenWorkingDirectories.insert(CompileCommand.Directory).second)
+ for (const auto &MappedFile : MappedFileContents)
+ if (!llvm::sys::path::is_absolute(MappedFile.first))
+ InMemoryFileSystem->addFile(
+ MappedFile.first, 0,
+ llvm::MemoryBuffer::getMemBuffer(MappedFile.second));
+
std::vector<std::string> CommandLine = CompileCommand.CommandLine;
if (ArgsAdjuster)
- CommandLine = ArgsAdjuster(CommandLine);
+ CommandLine = ArgsAdjuster(CommandLine, CompileCommand.Filename);
assert(!CommandLine.empty());
CommandLine[0] = MainExecutable;
// FIXME: We need a callback mechanism for the tool writer to output a
@@ -364,8 +418,7 @@ int ClangTool::run(ToolAction *Action) {
ToolInvocation Invocation(std::move(CommandLine), Action, Files.get(),
PCHContainerOps);
Invocation.setDiagnosticConsumer(DiagConsumer);
- for (const auto &MappedFile : MappedFileContents)
- Invocation.mapVirtualFile(MappedFile.first, MappedFile.second);
+
if (!Invocation.run()) {
// FIXME: Diagnostics should be used instead.
llvm::errs() << "Error while processing " << File << ".\n";
@@ -373,7 +426,7 @@ int ClangTool::run(ToolAction *Action) {
}
// Return to the initial directory to correctly resolve next file by
// relative path.
- if (chdir(InitialDirectory.c_str()))
+ if (OverlayFileSystem->setCurrentWorkingDirectory(InitialDirectory.c_str()))
llvm::report_fatal_error("Cannot chdir into \"" +
Twine(InitialDirectory) + "\n!");
}
@@ -392,12 +445,12 @@ public:
bool runInvocation(CompilerInvocation *Invocation, FileManager *Files,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) override {
- // FIXME: This should use the provided FileManager.
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation(
Invocation, PCHContainerOps,
CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts(),
DiagConsumer,
- /*ShouldOwnClient=*/false));
+ /*ShouldOwnClient=*/false),
+ Files);
if (!AST)
return false;
@@ -429,12 +482,20 @@ std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
std::vector<std::unique_ptr<ASTUnit>> ASTs;
ASTBuilderAction Action(ASTs);
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
+ new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
+ llvm::IntrusiveRefCntPtr<FileManager> Files(
+ new FileManager(FileSystemOptions(), OverlayFileSystem));
ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), &Action,
- nullptr, PCHContainerOps);
+ Files.get(), PCHContainerOps);
SmallString<1024> CodeStorage;
- Invocation.mapVirtualFile(FileNameRef,
- Code.toNullTerminatedStringRef(CodeStorage));
+ InMemoryFileSystem->addFile(FileNameRef, 0,
+ llvm::MemoryBuffer::getMemBuffer(
+ Code.toNullTerminatedStringRef(CodeStorage)));
if (!Invocation.run())
return nullptr;
diff --git a/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp b/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp
index 9068ac1..59b7af5 100644
--- a/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp
+++ b/contrib/llvm/tools/clang/tools/driver/cc1as_main.cpp
@@ -125,6 +125,10 @@ struct AssemblerInvocation {
unsigned RelaxAll : 1;
unsigned NoExecStack : 1;
unsigned FatalWarnings : 1;
+ unsigned IncrementalLinkerCompatible : 1;
+
+ /// The name of the relocation model to use.
+ std::string RelocationModel;
/// @}
@@ -141,7 +145,8 @@ public:
RelaxAll = 0;
NoExecStack = 0;
FatalWarnings = 0;
- DwarfVersion = 2;
+ IncrementalLinkerCompatible = 0;
+ DwarfVersion = 0;
}
static bool CreateFromArgs(AssemblerInvocation &Res,
@@ -192,14 +197,10 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Opts.IncludePaths = Args.getAllArgValues(OPT_I);
Opts.NoInitialTextSection = Args.hasArg(OPT_n);
Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels);
- Opts.GenDwarfForAssembly = Args.hasArg(OPT_g_Flag);
+ // Any DebugInfoKind implies GenDwarfForAssembly.
+ Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ);
Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections);
- if (Args.hasArg(OPT_gdwarf_2))
- Opts.DwarfVersion = 2;
- if (Args.hasArg(OPT_gdwarf_3))
- Opts.DwarfVersion = 3;
- if (Args.hasArg(OPT_gdwarf_4))
- Opts.DwarfVersion = 4;
+ Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 0, Diags);
Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
Opts.DwarfDebugProducer = Args.getLastArgValue(OPT_dwarf_debug_producer);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
@@ -248,6 +249,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
+ Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
+ Opts.IncrementalLinkerCompatible =
+ Args.hasArg(OPT_mincremental_linker_compatible);
return Success;
}
@@ -321,8 +325,19 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr);
- // FIXME: Assembler behavior can change with -static.
- MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), Reloc::Default,
+
+ llvm::Reloc::Model RM = llvm::Reloc::Default;
+ if (Opts.RelocationModel == "static") {
+ RM = llvm::Reloc::Static;
+ } else if (Opts.RelocationModel == "pic") {
+ RM = llvm::Reloc::PIC_;
+ } else {
+ assert(Opts.RelocationModel == "dynamic-no-pic" &&
+ "Invalid PIC model!");
+ RM = llvm::Reloc::DynamicNoPIC;
+ }
+
+ MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), RM,
CodeModel::Default, Ctx);
if (Opts.SaveTemporaryLabels)
Ctx.setAllowTemporaryLabels(false);
@@ -383,9 +398,10 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple,
Opts.CPU);
Triple T(Opts.Triple);
- Str.reset(TheTarget->createMCObjectStreamer(T, Ctx, *MAB, *Out, CE, *STI,
- Opts.RelaxAll,
- /*DWARFMustBeAtTheEnd*/ true));
+ Str.reset(TheTarget->createMCObjectStreamer(
+ T, Ctx, *MAB, *Out, CE, *STI, Opts.RelaxAll,
+ Opts.IncrementalLinkerCompatible,
+ /*DWARFMustBeAtTheEnd*/ true));
Str.get()->InitSections(Opts.NoExecStack);
}
@@ -496,4 +512,3 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
return !!Failed;
}
-
diff --git a/contrib/llvm/tools/clang/tools/driver/driver.cpp b/contrib/llvm/tools/clang/tools/driver/driver.cpp
index 5925447..ea218d5 100644
--- a/contrib/llvm/tools/clang/tools/driver/driver.cpp
+++ b/contrib/llvm/tools/clang/tools/driver/driver.cpp
@@ -18,6 +18,7 @@
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/ToolChain.h"
#include "clang/Frontend/ChainedDiagnosticConsumer.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/SerializedDiagnosticPrinter.h"
@@ -44,7 +45,6 @@
#include "llvm/Support/Regex.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/StringSaver.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
@@ -201,94 +201,33 @@ extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0,
extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
void *MainAddr);
-struct DriverSuffix {
- const char *Suffix;
- const char *ModeFlag;
-};
-
-static const DriverSuffix *FindDriverSuffix(StringRef ProgName) {
- // A list of known driver suffixes. Suffixes are compared against the
- // program name in order. If there is a match, the frontend type if updated as
- // necessary by applying the ModeFlag.
- static const DriverSuffix DriverSuffixes[] = {
- {"clang", nullptr},
- {"clang++", "--driver-mode=g++"},
- {"clang-c++", "--driver-mode=g++"},
- {"clang-cc", nullptr},
- {"clang-cpp", "--driver-mode=cpp"},
- {"clang-g++", "--driver-mode=g++"},
- {"clang-gcc", nullptr},
- {"clang-cl", "--driver-mode=cl"},
- {"cc", nullptr},
- {"cpp", "--driver-mode=cpp"},
- {"cl", "--driver-mode=cl"},
- {"++", "--driver-mode=g++"},
- };
-
- for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i)
- if (ProgName.endswith(DriverSuffixes[i].Suffix))
- return &DriverSuffixes[i];
- return nullptr;
-}
-
-static void ParseProgName(SmallVectorImpl<const char *> &ArgVector,
- std::set<std::string> &SavedStrings) {
- // Try to infer frontend type and default target from the program name by
- // comparing it against DriverSuffixes in order.
-
- // If there is a match, the function tries to identify a target as prefix.
- // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target
- // prefix "x86_64-linux". If such a target prefix is found, is gets added via
- // -target as implicit first argument.
-
- std::string ProgName =llvm::sys::path::stem(ArgVector[0]);
-#ifdef LLVM_ON_WIN32
- // Transform to lowercase for case insensitive file systems.
- ProgName = StringRef(ProgName).lower();
-#endif
-
- StringRef ProgNameRef = ProgName;
- const DriverSuffix *DS = FindDriverSuffix(ProgNameRef);
-
- if (!DS) {
- // Try again after stripping any trailing version number:
- // clang++3.5 -> clang++
- ProgNameRef = ProgNameRef.rtrim("0123456789.");
- DS = FindDriverSuffix(ProgNameRef);
+static void insertTargetAndModeArgs(StringRef Target, StringRef Mode,
+ SmallVectorImpl<const char *> &ArgVector,
+ std::set<std::string> &SavedStrings) {
+ if (!Mode.empty()) {
+ // Add the mode flag to the arguments.
+ auto it = ArgVector.begin();
+ if (it != ArgVector.end())
+ ++it;
+ ArgVector.insert(it, GetStableCStr(SavedStrings, Mode));
}
- if (!DS) {
- // Try again after stripping trailing -component.
- // clang++-tot -> clang++
- ProgNameRef = ProgNameRef.slice(0, ProgNameRef.rfind('-'));
- DS = FindDriverSuffix(ProgNameRef);
+ if (!Target.empty()) {
+ auto it = ArgVector.begin();
+ if (it != ArgVector.end())
+ ++it;
+ const char *arr[] = {"-target", GetStableCStr(SavedStrings, Target)};
+ ArgVector.insert(it, std::begin(arr), std::end(arr));
}
+}
- if (DS) {
- if (const char *Flag = DS->ModeFlag) {
- // Add Flag to the arguments.
- auto it = ArgVector.begin();
- if (it != ArgVector.end())
- ++it;
- ArgVector.insert(it, Flag);
- }
-
- StringRef::size_type LastComponent = ProgNameRef.rfind(
- '-', ProgNameRef.size() - strlen(DS->Suffix));
- if (LastComponent == StringRef::npos)
- return;
-
- // Infer target from the prefix.
- StringRef Prefix = ProgNameRef.slice(0, LastComponent);
- std::string IgnoredError;
- if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
- auto it = ArgVector.begin();
- if (it != ArgVector.end())
- ++it;
- const char *arr[] = { "-target", GetStableCStr(SavedStrings, Prefix) };
- ArgVector.insert(it, std::begin(arr), std::end(arr));
- }
- }
+static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver,
+ SmallVectorImpl<const char *> &Opts) {
+ llvm::cl::TokenizeWindowsCommandLine(EnvValue, Saver, Opts);
+ // The first instance of '#' should be replaced with '=' in each option.
+ for (const char *Opt : Opts)
+ if (char *NumberSignPtr = const_cast<char *>(::strchr(Opt, '#')))
+ *NumberSignPtr = '=';
}
static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) {
@@ -335,7 +274,7 @@ CreateAndPopulateDiagOpts(ArrayRef<const char *> argv) {
}
static void SetInstallDir(SmallVectorImpl<const char *> &argv,
- Driver &TheDriver) {
+ Driver &TheDriver, bool CanonicalPrefixes) {
// Attempt to find the original path used to invoke the driver, to determine
// the installed path. We do this manually, because we want to support that
// path being a symlink.
@@ -346,7 +285,11 @@ static void SetInstallDir(SmallVectorImpl<const char *> &argv,
if (llvm::ErrorOr<std::string> Tmp = llvm::sys::findProgramByName(
llvm::sys::path::filename(InstalledPath.str())))
InstalledPath = *Tmp;
- llvm::sys::fs::make_absolute(InstalledPath);
+
+ // FIXME: We don't actually canonicalize this, we just make it absolute.
+ if (CanonicalPrefixes)
+ llvm::sys::fs::make_absolute(InstalledPath);
+
InstalledPath = llvm::sys::path::parent_path(InstalledPath);
if (llvm::sys::fs::exists(InstalledPath.c_str()))
TheDriver.setInstalledDir(InstalledPath);
@@ -380,16 +323,35 @@ int main(int argc_, const char **argv_) {
return 1;
}
+ llvm::InitializeAllTargets();
+ std::string ProgName = argv[0];
+ std::pair<std::string, std::string> TargetAndMode =
+ ToolChain::getTargetAndModeFromProgramName(ProgName);
+
llvm::BumpPtrAllocator A;
- llvm::BumpPtrStringSaver Saver(A);
+ llvm::StringSaver Saver(A);
+
+ // Parse response files using the GNU syntax, unless we're in CL mode. There
+ // are two ways to put clang in CL compatibility mode: argv[0] is either
+ // clang-cl or cl, or --driver-mode=cl is on the command line. The normal
+ // command line parsing can't happen until after response file parsing, so we
+ // have to manually search for a --driver-mode=cl argument the hard way.
+ // Finally, our -cc1 tools don't care which tokenization mode we use because
+ // response files written by clang will tokenize the same way in either mode.
+ llvm::cl::TokenizerCallback Tokenizer = &llvm::cl::TokenizeGNUCommandLine;
+ if (TargetAndMode.second == "--driver-mode=cl" ||
+ std::find_if(argv.begin(), argv.end(), [](const char *F) {
+ return F && strcmp(F, "--driver-mode=cl") == 0;
+ }) != argv.end()) {
+ Tokenizer = &llvm::cl::TokenizeWindowsCommandLine;
+ }
// Determines whether we want nullptr markers in argv to indicate response
// files end-of-lines. We only use this for the /LINK driver argument.
bool MarkEOLs = true;
if (argv.size() > 1 && StringRef(argv[1]).startswith("-cc1"))
MarkEOLs = false;
- llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, argv,
- MarkEOLs);
+ llvm::cl::ExpandResponseFiles(Saver, Tokenizer, argv, MarkEOLs);
// Handle -cc1 integrated tools, even if -cc1 was expanded from a response
// file.
@@ -415,6 +377,29 @@ int main(int argc_, const char **argv_) {
}
}
+ // Handle CL and _CL_ which permits additional command line options to be
+ // prepended or appended.
+ if (Tokenizer == &llvm::cl::TokenizeWindowsCommandLine) {
+ // Arguments in "CL" are prepended.
+ llvm::Optional<std::string> OptCL = llvm::sys::Process::GetEnv("CL");
+ if (OptCL.hasValue()) {
+ SmallVector<const char *, 8> PrependedOpts;
+ getCLEnvVarOptions(OptCL.getValue(), Saver, PrependedOpts);
+
+ // Insert right after the program name to prepend to the argument list.
+ argv.insert(argv.begin() + 1, PrependedOpts.begin(), PrependedOpts.end());
+ }
+ // Arguments in "_CL_" are appended.
+ llvm::Optional<std::string> Opt_CL_ = llvm::sys::Process::GetEnv("_CL_");
+ if (Opt_CL_.hasValue()) {
+ SmallVector<const char *, 8> AppendedOpts;
+ getCLEnvVarOptions(Opt_CL_.getValue(), Saver, AppendedOpts);
+
+ // Insert at the end of the argument list to append.
+ argv.append(AppendedOpts.begin(), AppendedOpts.end());
+ }
+ }
+
std::set<std::string> SavedStrings;
// Handle CCC_OVERRIDE_OPTIONS, used for editing a command line behind the
// scenes.
@@ -447,10 +432,10 @@ int main(int argc_, const char **argv_) {
ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);
Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags);
- SetInstallDir(argv, TheDriver);
+ SetInstallDir(argv, TheDriver, CanonicalPrefixes);
- llvm::InitializeAllTargets();
- ParseProgName(argv, SavedStrings);
+ insertTargetAndModeArgs(TargetAndMode.first, TargetAndMode.second, argv,
+ SavedStrings);
SetBackdoorDriverOutputsFromEnvVars(TheDriver);
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp
index f2aa400..f70bff2 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -54,7 +54,7 @@ public:
const std::string &nameSpace() const { return NS; }
bool knownToGCC() const { return K; }
};
-} // namespace
+} // end anonymous namespace
static std::vector<FlattenedSpelling>
GetFlattenedSpellings(const Record &Attr) {
@@ -166,17 +166,18 @@ namespace {
std::string lowerName, upperName;
StringRef attrName;
bool isOpt;
+ bool Fake;
public:
Argument(const Record &Arg, StringRef Attr)
: lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
- attrName(Attr), isOpt(false) {
+ attrName(Attr), isOpt(false), Fake(false) {
if (!lowerName.empty()) {
lowerName[0] = std::tolower(lowerName[0]);
upperName[0] = std::toupper(upperName[0]);
}
}
- virtual ~Argument() {}
+ virtual ~Argument() = default;
StringRef getLowerName() const { return lowerName; }
StringRef getUpperName() const { return upperName; }
@@ -185,6 +186,9 @@ namespace {
bool isOptional() const { return isOpt; }
void setOptional(bool set) { isOpt = set; }
+ bool isFake() const { return Fake; }
+ void setFake(bool fake) { Fake = fake; }
+
// These functions print the argument contents formatted in different ways.
virtual void writeAccessors(raw_ostream &OS) const = 0;
virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
@@ -275,6 +279,8 @@ namespace {
OS << " OS << \" \";\n";
OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
} else if (type == "IdentifierInfo *") {
+ if (isOptional())
+ OS << " if (SA->get" << getUpperName() << "())\n ";
OS << " OS << \" \" << SA->get" << getUpperName()
<< "()->getName();\n";
} else if (type == "TypeSourceInfo *") {
@@ -348,7 +354,7 @@ namespace {
<< "Length])";
}
void writeCtorDefaultInitializers(raw_ostream &OS) const override {
- OS << getLowerName() << "Length(0)," << getLowerName() << "(0)";
+ OS << getLowerName() << "Length(0)," << getLowerName() << "(nullptr)";
}
void writeCtorParameters(raw_ostream &OS) const override {
OS << "llvm::StringRef " << getUpperName();
@@ -491,7 +497,7 @@ namespace {
// The aligned attribute argument expression is optional.
OS << " if (is" << getLowerName() << "Expr && "
<< getLowerName() << "Expr)\n";
- OS << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n";
+ OS << " " << getLowerName() << "Expr->printPretty(OS, nullptr, Policy);\n";
OS << " OS << \"";
}
void writeDump(raw_ostream &OS) const override {
@@ -613,7 +619,7 @@ namespace {
std::vector<std::string> uniques;
std::set<std::string> unique_set(enums.begin(), enums.end());
for (const auto &i : enums) {
- std::set<std::string>::iterator set_i = unique_set.find(i);
+ auto set_i = unique_set.find(i);
if (set_i != unique_set.end()) {
uniques.push_back(i);
unique_set.erase(set_i);
@@ -659,8 +665,7 @@ namespace {
OS << type << " " << getUpperName();
}
void writeDeclarations(raw_ostream &OS) const override {
- std::vector<std::string>::const_iterator i = uniques.begin(),
- e = uniques.end();
+ auto i = uniques.cbegin(), e = uniques.cend();
// The last one needs to not have a comma.
--e;
@@ -765,8 +770,7 @@ namespace {
bool isVariadicEnumArg() const override { return true; }
void writeDeclarations(raw_ostream &OS) const override {
- std::vector<std::string>::const_iterator i = uniques.begin(),
- e = uniques.end();
+ auto i = uniques.cbegin(), e = uniques.cend();
// The last one needs to not have a comma.
--e;
@@ -952,7 +956,7 @@ namespace {
}
void writeTemplateInstantiation(raw_ostream &OS) const override {
- OS << " " << getType() << " *tempInst" << getUpperName()
+ OS << " auto *tempInst" << getUpperName()
<< " = new (C, 16) " << getType()
<< "[A->" << getLowerName() << "_size()];\n";
OS << " {\n";
@@ -1018,7 +1022,7 @@ namespace {
getType(), "SA->get" + std::string(getUpperName()) + "Loc()");
}
};
-}
+} // end anonymous namespace
static std::unique_ptr<Argument>
createArgument(const Record &Arg, StringRef Attr,
@@ -1078,6 +1082,9 @@ createArgument(const Record &Arg, StringRef Attr,
if (Ptr && Arg.getValueAsBit("Optional"))
Ptr->setOptional(true);
+ if (Ptr && Arg.getValueAsBit("Fake"))
+ Ptr->setFake(true);
+
return Ptr;
}
@@ -1180,28 +1187,39 @@ writePrettyPrintFunction(Record &R,
if (Variety == "Pragma") {
OS << " \";\n";
OS << " printPrettyPragma(OS, Policy);\n";
+ OS << " OS << \"\\n\";";
OS << " break;\n";
OS << " }\n";
continue;
}
+ // Fake arguments aren't part of the parsed form and should not be
+ // pretty-printed.
+ bool hasNonFakeArgs = false;
+ for (const auto &arg : Args) {
+ if (arg->isFake()) continue;
+ hasNonFakeArgs = true;
+ }
+
// FIXME: always printing the parenthesis isn't the correct behavior for
// attributes which have optional arguments that were not provided. For
// instance: __attribute__((aligned)) will be pretty printed as
// __attribute__((aligned())). The logic should check whether there is only
// a single argument, and if it is optional, whether it has been provided.
- if (!Args.empty())
+ if (hasNonFakeArgs)
OS << "(";
if (Spelling == "availability") {
writeAvailabilityValue(OS);
} else {
- for (auto I = Args.begin(), E = Args.end(); I != E; ++ I) {
- if (I != Args.begin()) OS << ", ";
- (*I)->writeValue(OS);
+ unsigned index = 0;
+ for (const auto &arg : Args) {
+ if (arg->isFake()) continue;
+ if (index++) OS << ", ";
+ arg->writeValue(OS);
}
}
- if (!Args.empty())
+ if (hasNonFakeArgs)
OS << ")";
OS << Suffix + "\";\n";
@@ -1473,10 +1491,19 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
std::vector<std::unique_ptr<Argument>> Args;
Args.reserve(ArgRecords.size());
+ bool HasOptArg = false;
+ bool HasFakeArg = false;
for (const auto *ArgRecord : ArgRecords) {
Args.emplace_back(createArgument(*ArgRecord, R.getName()));
Args.back()->writeDeclarations(OS);
OS << "\n\n";
+
+ // For these purposes, fake takes priority over optional.
+ if (Args.back()->isFake()) {
+ HasFakeArg = true;
+ } else if (Args.back()->isOptional()) {
+ HasOptArg = true;
+ }
}
OS << "\npublic:\n";
@@ -1495,69 +1522,53 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
if (!ElideSpelling)
OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
- OS << " static " << R.getName() << "Attr *CreateImplicit(";
- OS << "ASTContext &Ctx";
- if (!ElideSpelling)
- OS << ", Spelling S";
- for (auto const &ai : Args) {
- OS << ", ";
- ai->writeCtorParameters(OS);
- }
- OS << ", SourceRange Loc = SourceRange()";
- OS << ") {\n";
- OS << " " << R.getName() << "Attr *A = new (Ctx) " << R.getName();
- OS << "Attr(Loc, Ctx, ";
- for (auto const &ai : Args) {
- ai->writeImplicitCtorArgs(OS);
- OS << ", ";
- }
- OS << (ElideSpelling ? "0" : "S") << ");\n";
- OS << " A->setImplicit(true);\n";
- OS << " return A;\n }\n\n";
-
- OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
-
- bool HasOpt = false;
- for (auto const &ai : Args) {
- OS << " , ";
- ai->writeCtorParameters(OS);
- OS << "\n";
- if (ai->isOptional())
- HasOpt = true;
- }
-
- OS << " , ";
- OS << "unsigned SI\n";
+ // Emit CreateImplicit factory methods.
+ auto emitCreateImplicit = [&](bool emitFake) {
+ OS << " static " << R.getName() << "Attr *CreateImplicit(";
+ OS << "ASTContext &Ctx";
+ if (!ElideSpelling)
+ OS << ", Spelling S";
+ for (auto const &ai : Args) {
+ if (ai->isFake() && !emitFake) continue;
+ OS << ", ";
+ ai->writeCtorParameters(OS);
+ }
+ OS << ", SourceRange Loc = SourceRange()";
+ OS << ") {\n";
+ OS << " auto *A = new (Ctx) " << R.getName();
+ OS << "Attr(Loc, Ctx, ";
+ for (auto const &ai : Args) {
+ if (ai->isFake() && !emitFake) continue;
+ ai->writeImplicitCtorArgs(OS);
+ OS << ", ";
+ }
+ OS << (ElideSpelling ? "0" : "S") << ");\n";
+ OS << " A->setImplicit(true);\n";
+ OS << " return A;\n }\n\n";
+ };
- OS << " )\n";
- OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, "
- << R.getValueAsBit("LateParsed") << ", "
- << R.getValueAsBit("DuplicatesAllowedWhileMerging") << ")\n";
+ // Emit a CreateImplicit that takes all the arguments.
+ emitCreateImplicit(true);
- for (auto const &ai : Args) {
- OS << " , ";
- ai->writeCtorInitializers(OS);
- OS << "\n";
+ // Emit a CreateImplicit that takes all the non-fake arguments.
+ if (HasFakeArg) {
+ emitCreateImplicit(false);
}
- OS << " {\n";
-
- for (auto const &ai : Args) {
- ai->writeCtorBody(OS);
- OS << "\n";
- }
- OS << " }\n\n";
+ // Emit constructors.
+ auto emitCtor = [&](bool emitOpt, bool emitFake) {
+ auto shouldEmitArg = [=](const std::unique_ptr<Argument> &arg) {
+ if (arg->isFake()) return emitFake;
+ if (arg->isOptional()) return emitOpt;
+ return true;
+ };
- // If there are optional arguments, write out a constructor that elides the
- // optional arguments as well.
- if (HasOpt) {
OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
for (auto const &ai : Args) {
- if (!ai->isOptional()) {
- OS << " , ";
- ai->writeCtorParameters(OS);
- OS << "\n";
- }
+ if (!shouldEmitArg(ai)) continue;
+ OS << " , ";
+ ai->writeCtorParameters(OS);
+ OS << "\n";
}
OS << " , ";
@@ -1570,19 +1581,37 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
for (auto const &ai : Args) {
OS << " , ";
- ai->writeCtorDefaultInitializers(OS);
+ if (!shouldEmitArg(ai)) {
+ ai->writeCtorDefaultInitializers(OS);
+ } else {
+ ai->writeCtorInitializers(OS);
+ }
OS << "\n";
}
OS << " {\n";
for (auto const &ai : Args) {
- if (!ai->isOptional()) {
- ai->writeCtorBody(OS);
- OS << "\n";
- }
+ if (!shouldEmitArg(ai)) continue;
+ ai->writeCtorBody(OS);
+ OS << "\n";
}
OS << " }\n\n";
+
+ };
+
+ // Emit a constructor that includes all the arguments.
+ // This is necessary for cloning.
+ emitCtor(true, true);
+
+ // Emit a constructor that takes all the non-fake arguments.
+ if (HasFakeArg) {
+ emitCtor(true, false);
+ }
+
+ // Emit a constructor that takes all the non-fake, non-optional arguments.
+ if (HasOptArg) {
+ emitCtor(false, false);
}
OS << " " << R.getName() << "Attr *clone(ASTContext &C) const;\n";
@@ -1604,6 +1633,9 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
ai->writeAccessors(OS);
OS << "\n\n";
+ // Don't write conversion routines for fake arguments.
+ if (ai->isFake()) continue;
+
if (ai->isEnumArg())
static_cast<const EnumArgument *>(ai.get())->writeConversion(OS);
else if (ai->isVariadicEnumArg())
@@ -1620,7 +1652,7 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
OS << "};\n\n";
}
- OS << "#endif\n";
+ OS << "#endif // LLVM_CLANG_ATTR_CLASSES_INC\n";
}
// Emits the class method definitions for attributes.
@@ -1695,7 +1727,7 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
static void EmitAttrList(raw_ostream &OS, StringRef Class,
const std::vector<Record*> &AttrList) {
- std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
+ auto i = AttrList.cbegin(), e = AttrList.cend();
if (i != e) {
// Move the end iterator back to emit the last attribute.
@@ -1847,7 +1879,7 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
OS << " case attr::" << R.getName() << ": {\n";
Args = R.getValueAsListOfDefs("Args");
if (R.isSubClassOf(InhClass) || !Args.empty())
- OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
+ OS << " const auto *SA = cast<" << R.getName()
<< "Attr>(A);\n";
if (R.isSubClassOf(InhClass))
OS << " Record.push_back(SA->isInherited());\n";
@@ -1862,6 +1894,65 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
OS << " }\n";
}
+// Generate a conditional expression to check if the current target satisfies
+// the conditions for a TargetSpecificAttr record, and append the code for
+// those checks to the Test string. If the FnName string pointer is non-null,
+// append a unique suffix to distinguish this set of target checks from other
+// TargetSpecificAttr records.
+static void GenerateTargetSpecificAttrChecks(const Record *R,
+ std::vector<std::string> &Arches,
+ std::string &Test,
+ std::string *FnName) {
+ // It is assumed that there will be an llvm::Triple object
+ // named "T" and a TargetInfo object named "Target" within
+ // scope that can be used to determine whether the attribute exists in
+ // a given target.
+ Test += "(";
+
+ for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
+ std::string Part = *I;
+ Test += "T.getArch() == llvm::Triple::" + Part;
+ if (I + 1 != E)
+ Test += " || ";
+ if (FnName)
+ *FnName += Part;
+ }
+ Test += ")";
+
+ // If the attribute is specific to particular OSes, check those.
+ if (!R->isValueUnset("OSes")) {
+ // We know that there was at least one arch test, so we need to and in the
+ // OS tests.
+ Test += " && (";
+ std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
+ for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
+ std::string Part = *I;
+
+ Test += "T.getOS() == llvm::Triple::" + Part;
+ if (I + 1 != E)
+ Test += " || ";
+ if (FnName)
+ *FnName += Part;
+ }
+ Test += ")";
+ }
+
+ // If one or more CXX ABIs are specified, check those as well.
+ if (!R->isValueUnset("CXXABIs")) {
+ Test += " && (";
+ std::vector<std::string> CXXABIs = R->getValueAsListOfStrings("CXXABIs");
+ for (auto I = CXXABIs.begin(), E = CXXABIs.end(); I != E; ++I) {
+ std::string Part = *I;
+ Test += "Target.getCXXABI().getKind() == TargetCXXABI::" + Part;
+ if (I + 1 != E)
+ Test += " || ";
+ if (FnName)
+ *FnName += Part;
+ }
+ Test += ")";
+ }
+}
+
static void GenerateHasAttrSpellingStringSwitch(
const std::vector<Record *> &Attrs, raw_ostream &OS,
const std::string &Variety = "", const std::string &Scope = "") {
@@ -1887,37 +1978,12 @@ static void GenerateHasAttrSpellingStringSwitch(
}
}
- // It is assumed that there will be an llvm::Triple object named T within
- // scope that can be used to determine whether the attribute exists in
- // a given target.
std::string Test;
if (Attr->isSubClassOf("TargetSpecificAttr")) {
const Record *R = Attr->getValueAsDef("Target");
std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
+ GenerateTargetSpecificAttrChecks(R, Arches, Test, nullptr);
- Test += "(";
- for (auto AI = Arches.begin(), AE = Arches.end(); AI != AE; ++AI) {
- std::string Part = *AI;
- Test += "T.getArch() == llvm::Triple::" + Part;
- if (AI + 1 != AE)
- Test += " || ";
- }
- Test += ")";
-
- std::vector<std::string> OSes;
- if (!R->isValueUnset("OSes")) {
- Test += " && (";
- std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
- for (auto AI = OSes.begin(), AE = OSes.end(); AI != AE; ++AI) {
- std::string Part = *AI;
-
- Test += "T.getOS() == llvm::Triple::" + Part;
- if (AI + 1 != AE)
- Test += " || ";
- }
- Test += ")";
- }
-
// If this is the C++11 variety, also add in the LangOpts test.
if (Variety == "CXX11")
Test += " && LangOpts.CPlusPlus11";
@@ -1964,6 +2030,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
}
}
+ OS << "const llvm::Triple &T = Target.getTriple();\n";
OS << "switch (Syntax) {\n";
OS << "case AttrSyntax::GNU:\n";
OS << " return llvm::StringSwitch<int>(Name)\n";
@@ -1976,9 +2043,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma");
OS << "case AttrSyntax::CXX: {\n";
// C++11-style attributes are further split out based on the Scope.
- for (std::map<std::string, std::vector<Record *>>::iterator I = CXX.begin(),
- E = CXX.end();
- I != E; ++I) {
+ for (auto I = CXX.cbegin(), E = CXX.cend(); I != E; ++I) {
if (I != CXX.begin())
OS << " else ";
if (I->first.empty())
@@ -2049,7 +2114,7 @@ void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
OS << " bool Visit"
<< R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
<< " return true; \n"
- << " };\n";
+ << " }\n";
}
OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";
@@ -2123,12 +2188,12 @@ void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
bool ShouldClone = R.getValueAsBit("Clone");
if (!ShouldClone) {
- OS << " return NULL;\n";
+ OS << " return nullptr;\n";
OS << " }\n";
continue;
}
- OS << " const " << R.getName() << "Attr *A = cast<"
+ OS << " const auto *A = cast<"
<< R.getName() << "Attr>(At);\n";
bool TDependent = R.getValueAsBit("TemplateDependent");
@@ -2157,7 +2222,7 @@ void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
}
OS << " } // end switch\n"
<< " llvm_unreachable(\"Unknown attribute!\");\n"
- << " return 0;\n"
+ << " return nullptr;\n"
<< "}\n\n"
<< "} // end namespace sema\n"
<< "} // end namespace clang\n";
@@ -2328,6 +2393,7 @@ static std::string GetSubjectWithSuffix(const Record *R) {
return "Decl";
return B + "Decl";
}
+
static std::string GenerateCustomAppertainsTo(const Record &Subject,
raw_ostream &OS) {
std::string FnName = "is" + Subject.getName();
@@ -2335,7 +2401,7 @@ static std::string GenerateCustomAppertainsTo(const Record &Subject,
// If this code has already been generated, simply return the previous
// instance of it.
static std::set<std::string> CustomSubjectSet;
- std::set<std::string>::iterator I = CustomSubjectSet.find(FnName);
+ auto I = CustomSubjectSet.find(FnName);
if (I != CustomSubjectSet.end())
return *I;
@@ -2349,7 +2415,7 @@ static std::string GenerateCustomAppertainsTo(const Record &Subject,
}
OS << "static bool " << FnName << "(const Decl *D) {\n";
- OS << " if (const " << GetSubjectWithSuffix(Base) << " *S = dyn_cast<";
+ OS << " if (const auto *S = dyn_cast<";
OS << GetSubjectWithSuffix(Base);
OS << ">(D))\n";
OS << " return " << Subject.getValueAsString("CheckCode") << ";\n";
@@ -2449,7 +2515,7 @@ static std::string GenerateLangOptRequirements(const Record &R,
// If this code has already been generated, simply return the previous
// instance of it.
static std::set<std::string> CustomLangOptsSet;
- std::set<std::string>::iterator I = CustomLangOptsSet.find(FnName);
+ auto I = CustomLangOptsSet.find(FnName);
if (I != CustomLangOptsSet.end())
return *I;
@@ -2466,7 +2532,7 @@ static std::string GenerateLangOptRequirements(const Record &R,
}
static void GenerateDefaultTargetRequirements(raw_ostream &OS) {
- OS << "static bool defaultTargetRequirements(const llvm::Triple &) {\n";
+ OS << "static bool defaultTargetRequirements(const TargetInfo &) {\n";
OS << " return true;\n";
OS << "}\n\n";
}
@@ -2505,47 +2571,19 @@ static std::string GenerateTargetRequirements(const Record &Attr,
}
}
- std::string FnName = "isTarget", Test = "(";
- for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
- std::string Part = *I;
- Test += "Arch == llvm::Triple::" + Part;
- if (I + 1 != E)
- Test += " || ";
- FnName += Part;
- }
- Test += ")";
-
- // If the target also requires OS testing, generate those tests as well.
- bool UsesOS = false;
- if (!R->isValueUnset("OSes")) {
- UsesOS = true;
-
- // We know that there was at least one arch test, so we need to and in the
- // OS tests.
- Test += " && (";
- std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
- for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
- std::string Part = *I;
-
- Test += "OS == llvm::Triple::" + Part;
- if (I + 1 != E)
- Test += " || ";
- FnName += Part;
- }
- Test += ")";
- }
+ std::string FnName = "isTarget";
+ std::string Test;
+ GenerateTargetSpecificAttrChecks(R, Arches, Test, &FnName);
// If this code has already been generated, simply return the previous
// instance of it.
static std::set<std::string> CustomTargetSet;
- std::set<std::string>::iterator I = CustomTargetSet.find(FnName);
+ auto I = CustomTargetSet.find(FnName);
if (I != CustomTargetSet.end())
return *I;
- OS << "static bool " << FnName << "(const llvm::Triple &T) {\n";
- OS << " llvm::Triple::ArchType Arch = T.getArch();\n";
- if (UsesOS)
- OS << " llvm::Triple::OSType OS = T.getOS();\n";
+ OS << "static bool " << FnName << "(const TargetInfo &Target) {\n";
+ OS << " const llvm::Triple &T = Target.getTriple();\n";
OS << " return " << Test << ";\n";
OS << "}\n\n";
@@ -2758,13 +2796,13 @@ void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
Args = R.getValueAsListOfDefs("Args");
if (!Args.empty()) {
- OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
+ OS << " const auto *SA = cast<" << R.getName()
<< "Attr>(A);\n";
for (const auto *Arg : Args)
createArgument(*Arg, R.getName())->writeDump(OS);
- for (auto AI = Args.begin(), AE = Args.end(); AI != AE; ++AI)
- createArgument(**AI, R.getName())->writeDumpChildren(OS);
+ for (const auto *AI : Args)
+ createArgument(*AI, R.getName())->writeDumpChildren(OS);
}
OS <<
" break;\n"
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
index 3349030..3522cd4 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
@@ -72,7 +72,7 @@ void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n"
<< " StringRef Name) {\n";
StringMatcher("Name", Matches, OS).Emit();
- OS << " return NULL;\n"
+ OS << " return nullptr;\n"
<< "}\n\n";
}
@@ -123,4 +123,3 @@ void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) {
}
}
} // end namespace clang
-
diff --git a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp
index 7644ae2..6e7bc90 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/NeonEmitter.cpp
@@ -36,6 +36,7 @@
#include "llvm/TableGen/SetTheory.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <algorithm>
+#include <deque>
#include <map>
#include <sstream>
#include <string>
@@ -393,7 +394,7 @@ public:
/// Return true if the prototype has a scalar argument.
/// This does not return true for the "splat" code ('a').
- bool protoHasScalar();
+ bool protoHasScalar() const;
/// Return the index that parameter PIndex will sit at
/// in a generated function call. This is often just PIndex,
@@ -431,9 +432,9 @@ public:
/// Return the name, mangled with type information.
/// If ForceClassS is true, use ClassS (u32/s32) instead
/// of the intrinsic's own type class.
- std::string getMangledName(bool ForceClassS = false);
+ std::string getMangledName(bool ForceClassS = false) const;
/// Return the type code for a builtin function call.
- std::string getInstTypeCode(Type T, ClassKind CK);
+ std::string getInstTypeCode(Type T, ClassKind CK) const;
/// Return the type string for a BUILTIN() macro in Builtins.def.
std::string getBuiltinTypeStr();
@@ -444,7 +445,7 @@ public:
void indexBody();
private:
- std::string mangleName(std::string Name, ClassKind CK);
+ std::string mangleName(std::string Name, ClassKind CK) const;
void initVariables();
std::string replaceParamsIn(std::string S);
@@ -494,7 +495,7 @@ private:
class NeonEmitter {
RecordKeeper &Records;
DenseMap<Record *, ClassKind> ClassMap;
- std::map<std::string, std::vector<Intrinsic *>> IntrinsicMap;
+ std::map<std::string, std::deque<Intrinsic>> IntrinsicMap;
unsigned UniqueNumber;
void createIntrinsic(Record *R, SmallVectorImpl<Intrinsic *> &Out);
@@ -507,7 +508,7 @@ class NeonEmitter {
public:
/// Called by Intrinsic - this attempts to get an intrinsic that takes
/// the given types as arguments.
- Intrinsic *getIntrinsic(StringRef Name, ArrayRef<Type> Types);
+ Intrinsic &getIntrinsic(StringRef Name, ArrayRef<Type> Types);
/// Called by Intrinsic - returns a globally-unique number.
unsigned getUniqueNumber() { return UniqueNumber++; }
@@ -836,10 +837,6 @@ void Type::applyModifier(char Mod) {
Float = true;
break;
case 'f':
- // Special case - if we're half-precision, a floating
- // point argument needs to be 128-bits (double size).
- if (isHalf())
- Bitwidth = 128;
Float = true;
ElementBitwidth = 32;
break;
@@ -954,7 +951,7 @@ void Type::applyModifier(char Mod) {
// Intrinsic implementation
//===----------------------------------------------------------------------===//
-std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) {
+std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const {
char typeCode = '\0';
bool printNumber = true;
@@ -992,6 +989,10 @@ std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) {
return S;
}
+static bool isFloatingPointProtoModifier(char Mod) {
+ return Mod == 'F' || Mod == 'f';
+}
+
std::string Intrinsic::getBuiltinTypeStr() {
ClassKind LocalCK = getClassKind(true);
std::string S;
@@ -1013,7 +1014,7 @@ std::string Intrinsic::getBuiltinTypeStr() {
if (!RetT.isScalar() && !RetT.isSigned())
RetT.makeSigned();
- bool ForcedVectorFloatingType = Proto[0] == 'F' || Proto[0] == 'f';
+ bool ForcedVectorFloatingType = isFloatingPointProtoModifier(Proto[0]);
if (LocalCK == ClassB && !RetT.isScalar() && !ForcedVectorFloatingType)
// Cast to vector of 8-bit elements.
RetT.makeInteger(8, true);
@@ -1026,7 +1027,7 @@ std::string Intrinsic::getBuiltinTypeStr() {
if (T.isPoly())
T.makeInteger(T.getElementSizeInBits(), false);
- bool ForcedFloatingType = Proto[I + 1] == 'F' || Proto[I + 1] == 'f';
+ bool ForcedFloatingType = isFloatingPointProtoModifier(Proto[I + 1]);
if (LocalCK == ClassB && !T.isScalar() && !ForcedFloatingType)
T.makeInteger(8, true);
// Halves always get converted to 8-bit elements.
@@ -1049,7 +1050,7 @@ std::string Intrinsic::getBuiltinTypeStr() {
return S;
}
-std::string Intrinsic::getMangledName(bool ForceClassS) {
+std::string Intrinsic::getMangledName(bool ForceClassS) const {
// Check if the prototype has a scalar operand with the type of the vector
// elements. If not, bitcasting the args will take care of arg checking.
// The actual signedness etc. will be taken care of with special enums.
@@ -1060,12 +1061,12 @@ std::string Intrinsic::getMangledName(bool ForceClassS) {
return mangleName(Name, ForceClassS ? ClassS : LocalCK);
}
-std::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) {
+std::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) const {
std::string typeCode = getInstTypeCode(BaseType, LocalCK);
std::string S = Name;
- if (Name == "vcvt_f32_f16" || Name == "vcvt_f32_f64" ||
- Name == "vcvt_f64_f32")
+ if (Name == "vcvt_f16_f32" || Name == "vcvt_f32_f16" ||
+ Name == "vcvt_f32_f64" || Name == "vcvt_f64_f32")
return Name;
if (typeCode.size() > 0) {
@@ -1278,7 +1279,7 @@ void Intrinsic::emitShadowedArgs() {
// We don't check 'a' in this function, because for builtin function the
// argument matching to 'a' uses a vector type splatted from a scalar type.
-bool Intrinsic::protoHasScalar() {
+bool Intrinsic::protoHasScalar() const {
return (Proto.find('s') != std::string::npos ||
Proto.find('z') != std::string::npos ||
Proto.find('r') != std::string::npos ||
@@ -1363,7 +1364,7 @@ void Intrinsic::emitBodyAsBuiltinCall() {
// Extra constant integer to hold type class enum for this function, e.g. s8
if (getClassKind(true) == ClassB) {
Type ThisTy = getReturnType();
- if (Proto[0] == 'v' || Proto[0] == 'f' || Proto[0] == 'F')
+ if (Proto[0] == 'v' || isFloatingPointProtoModifier(Proto[0]))
ThisTy = getParamType(0);
if (ThisTy.isPointer())
ThisTy = getParamType(1);
@@ -1491,15 +1492,14 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) {
N = SI->getAsUnquotedString();
else
N = emitDagArg(DI->getArg(0), "").second;
- Intrinsic *Callee = Intr.Emitter.getIntrinsic(N, Types);
- assert(Callee && "getIntrinsic should not return us nullptr!");
+ Intrinsic &Callee = Intr.Emitter.getIntrinsic(N, Types);
// Make sure the callee is known as an early def.
- Callee->setNeededEarly();
- Intr.Dependencies.insert(Callee);
+ Callee.setNeededEarly();
+ Intr.Dependencies.insert(&Callee);
// Now create the call itself.
- std::string S = CallPrefix.str() + Callee->getMangledName(true) + "(";
+ std::string S = CallPrefix.str() + Callee.getMangledName(true) + "(";
for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) {
if (I != 0)
S += ", ";
@@ -1507,7 +1507,7 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) {
}
S += ")";
- return std::make_pair(Callee->getReturnType(), S);
+ return std::make_pair(Callee.getReturnType(), S);
}
std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI,
@@ -1855,11 +1855,11 @@ void Intrinsic::indexBody() {
// NeonEmitter implementation
//===----------------------------------------------------------------------===//
-Intrinsic *NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) {
+Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) {
// First, look up the name in the intrinsic map.
assert_with_loc(IntrinsicMap.find(Name.str()) != IntrinsicMap.end(),
("Intrinsic '" + Name + "' not found!").str());
- std::vector<Intrinsic *> &V = IntrinsicMap[Name.str()];
+ auto &V = IntrinsicMap.find(Name.str())->second;
std::vector<Intrinsic *> GoodVec;
// Create a string to print if we end up failing.
@@ -1874,35 +1874,35 @@ Intrinsic *NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) {
// Now, look through each intrinsic implementation and see if the types are
// compatible.
- for (auto *I : V) {
- ErrMsg += " - " + I->getReturnType().str() + " " + I->getMangledName();
+ for (auto &I : V) {
+ ErrMsg += " - " + I.getReturnType().str() + " " + I.getMangledName();
ErrMsg += "(";
- for (unsigned A = 0; A < I->getNumParams(); ++A) {
+ for (unsigned A = 0; A < I.getNumParams(); ++A) {
if (A != 0)
ErrMsg += ", ";
- ErrMsg += I->getParamType(A).str();
+ ErrMsg += I.getParamType(A).str();
}
ErrMsg += ")\n";
- if (I->getNumParams() != Types.size())
+ if (I.getNumParams() != Types.size())
continue;
bool Good = true;
for (unsigned Arg = 0; Arg < Types.size(); ++Arg) {
- if (I->getParamType(Arg) != Types[Arg]) {
+ if (I.getParamType(Arg) != Types[Arg]) {
Good = false;
break;
}
}
if (Good)
- GoodVec.push_back(I);
+ GoodVec.push_back(&I);
}
assert_with_loc(GoodVec.size() > 0,
"No compatible intrinsic found - " + ErrMsg);
assert_with_loc(GoodVec.size() == 1, "Multiple overloads found - " + ErrMsg);
- return GoodVec.front();
+ return *GoodVec.front();
}
void NeonEmitter::createIntrinsic(Record *R,
@@ -1947,13 +1947,12 @@ void NeonEmitter::createIntrinsic(Record *R,
std::sort(NewTypeSpecs.begin(), NewTypeSpecs.end());
NewTypeSpecs.erase(std::unique(NewTypeSpecs.begin(), NewTypeSpecs.end()),
NewTypeSpecs.end());
+ auto &Entry = IntrinsicMap[Name];
for (auto &I : NewTypeSpecs) {
- Intrinsic *IT = new Intrinsic(R, Name, Proto, I.first, I.second, CK, Body,
- *this, Guard, IsUnavailable, BigEndianSafe);
-
- IntrinsicMap[Name].push_back(IT);
- Out.push_back(IT);
+ Entry.emplace_back(R, Name, Proto, I.first, I.second, CK, Body, *this,
+ Guard, IsUnavailable, BigEndianSafe);
+ Out.push_back(&Entry.back());
}
CurrentRecord = nullptr;
@@ -2023,8 +2022,8 @@ void NeonEmitter::genOverloadTypeCheckCode(raw_ostream &OS,
uint64_t Mask = 0ULL;
Type Ty = Def->getReturnType();
- if (Def->getProto()[0] == 'v' || Def->getProto()[0] == 'f' ||
- Def->getProto()[0] == 'F')
+ if (Def->getProto()[0] == 'v' ||
+ isFloatingPointProtoModifier(Def->getProto()[0]))
Ty = Def->getParamType(0);
if (Ty.isPointer())
Ty = Def->getParamType(1);
diff --git a/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp b/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp
index 4484e65..724b0e1 100644
--- a/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp
+++ b/contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp
@@ -13,6 +13,7 @@
#include "TableGenBackends.h" // Declares all backends.
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/TableGen/Error.h"
@@ -244,6 +245,8 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv);
cl::ParseCommandLineOptions(argc, argv);
+ llvm_shutdown_obj Y;
+
return TableGenMain(argv[0], &ClangTableGenMain);
}
diff --git a/contrib/llvm/tools/llc/llc.cpp b/contrib/llvm/tools/llc/llc.cpp
index e33cd79..bffa39f 100644
--- a/contrib/llvm/tools/llc/llc.cpp
+++ b/contrib/llvm/tools/llc/llc.cpp
@@ -45,6 +45,7 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetSubtargetInfo.h"
+#include "llvm/Transforms/Utils/Cloning.h"
#include <memory>
using namespace llvm;
@@ -96,6 +97,12 @@ static cl::opt<bool> AsmVerbose("asm-verbose",
cl::desc("Add comments to directives."),
cl::init(true));
+static cl::opt<bool>
+ CompileTwice("compile-twice", cl::Hidden,
+ cl::desc("Run everything twice, re-using the same pass "
+ "manager and verify the result is the same."),
+ cl::init(false));
+
static int compileModule(char **, LLVMContext &);
static std::unique_ptr<tool_output_file>
@@ -312,8 +319,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
PM.add(new TargetLibraryInfoWrapperPass(TLII));
// Add the target data from the target machine, if it exists, or the module.
- if (const DataLayout *DL = Target->getDataLayout())
- M->setDataLayout(*DL);
+ M->setDataLayout(Target->createDataLayout());
// Override function attributes based on CPUStr, FeaturesStr, and command line
// flags.
@@ -326,10 +332,15 @@ static int compileModule(char **argv, LLVMContext &Context) {
{
raw_pwrite_stream *OS = &Out->os();
- std::unique_ptr<buffer_ostream> BOS;
- if (FileType != TargetMachine::CGFT_AssemblyFile &&
- !Out->os().supportsSeeking()) {
- BOS = make_unique<buffer_ostream>(*OS);
+
+ // Manually do the buffering rather than using buffer_ostream,
+ // so we can memcmp the contents in CompileTwice mode
+ SmallVector<char, 0> Buffer;
+ std::unique_ptr<raw_svector_ostream> BOS;
+ if ((FileType != TargetMachine::CGFT_AssemblyFile &&
+ !Out->os().supportsSeeking()) ||
+ CompileTwice) {
+ BOS = make_unique<raw_svector_ostream>(Buffer);
OS = BOS.get();
}
@@ -379,7 +390,39 @@ static int compileModule(char **argv, LLVMContext &Context) {
// Before executing passes, print the final values of the LLVM options.
cl::PrintOptionValues();
+ // If requested, run the pass manager over the same module again,
+ // to catch any bugs due to persistent state in the passes. Note that
+ // opt has the same functionality, so it may be worth abstracting this out
+ // in the future.
+ SmallVector<char, 0> CompileTwiceBuffer;
+ if (CompileTwice) {
+ std::unique_ptr<Module> M2(llvm::CloneModule(M.get()));
+ PM.run(*M2);
+ CompileTwiceBuffer = Buffer;
+ Buffer.clear();
+ }
+
PM.run(*M);
+
+ // Compare the two outputs and make sure they're the same
+ if (CompileTwice) {
+ if (Buffer.size() != CompileTwiceBuffer.size() ||
+ (memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) !=
+ 0)) {
+ errs()
+ << "Running the pass manager twice changed the output.\n"
+ "Writing the result of the second run to the specified output\n"
+ "To generate the one-run comparison binary, just run without\n"
+ "the compile-twice option\n";
+ Out->os() << Buffer;
+ Out->keep();
+ return 1;
+ }
+ }
+
+ if (BOS) {
+ Out->os() << Buffer;
+ }
}
// Declare success.
diff --git a/contrib/llvm/tools/lldb/docs/lldb.1 b/contrib/llvm/tools/lldb/docs/lldb.1
index b6084e7..a28cabe 100644
--- a/contrib/llvm/tools/lldb/docs/lldb.1
+++ b/contrib/llvm/tools/lldb/docs/lldb.1
@@ -1,10 +1,10 @@
-.Dd December 16, 2015 \" DATE
+.Dd December 16, 2015 \" DATE
.Dt LLDB 1 \" Program name and manual section number
.Os
-.Sh NAME \" Section Header - required - don't modify
+.Sh NAME \" Section Header - required - do not modify
.Nm lldb
.Nd The debugger
-.Sh SYNOPSIS \" Section Header - required - don't modify
+.Sh SYNOPSIS \" Section Header - required - do not modify
.Nm lldb
.Op Fl hvdexw
.Op Fl a Ar arch
@@ -14,7 +14,7 @@
.Op Fl n Ar process-name
.Op Fl p Ar pid
.Ar [[--] <PROGRAM-ARG1> <PROGRAM-ARG2> ...]
-.Sh DESCRIPTION \" Section Header - required - don't modify
+.Sh DESCRIPTION \" Section Header - required - do not modify
.Nm
is the command line interface for the LLDB debugger library.
.Nm
@@ -25,7 +25,10 @@ The following options are available:
.It Fl h, -help
Prints out the usage information for the
.Nm
-debugger. The \fB\-\-help\fR text may be more up-to-date and
+debugger.
+The
+.Fl -help
+text may be more up-to-date and
authoritative than the command line options described in this man
page.
.It Fl v, -version
@@ -43,9 +46,13 @@ Specifies the executable file that
will be launching / attaching to.
.It Fl n, -attach-name Ar process-name
Specifies the name of a currently-running process to attach to.
-(or the name of a process to wait for if \fB\-w\fR is used.)
+(or the name of a process to wait for if
+.Fl w
+is used.)
.It Fl w, -wait-for
-When used in concert with \&\fB\-n process-name\-E\fR, indicates that
+When used in concert with
+.Fl n Ar process-name ,
+indicates that
.Nm
should wait for a new process of that name to be started -- and attach
to it as early in the process-launch as possible.
@@ -57,7 +64,8 @@ should attach to.
Specifies the core file to examine.
.It Fl l, -script-language Ar language
Tells the debugger to use the specified scripting language for
-user-defined scripts, rather than the default. Valid scripting
+user-defined scripts, rather than the default.
+Valid scripting
languages that can be specified include Python, Perl, Ruby and Tcl.
Currently only the Python extensions have been implemented.
.It Fl d, -debug
@@ -65,8 +73,9 @@ Tells the debugger to print out extra information for debugging itself.
.It Fl s, -source Ar filename
Tells
.Nm
-to read in and execute the file "\fBfilename\fR", which
-should contain
+to read in and execute the file
+.Qq Ar filename ,
+which should contain
.Nm
commands.
.It Fl e, -editor
@@ -76,39 +85,62 @@ to open source files using the host's "external editor" mechanism.
.It Fl x, -no-lldbinit
Do not automatically parse any '.lldbinit' files.
.Pp
-(If you don't provide -f then the first argument will be the file to be debugged
+(If you do not provide -f then the first argument will be the file to
+be debugged
so 'lldb -- <filename> [<ARG1> [<ARG2>]]' also works.
-Remember to end the options with "--" if any of your arguments have a "-" in them.)
+Remember to end the options with "--" if any of your arguments have
+a "-" in them.)
.El
.Sh USING LLDB
In
.Nm
-there is a \fBhelp\fR command which can be used to find descriptions and examples of
-all
+there is a
+.Cm help
+command which can be used to find descriptions and examples of all
.Nm
-commands. To get help on "\fBbreakpoint set\fR" you would type "\fBhelp breakpoint set\fR".
+commands.
+To get help on
+.Qq Cm breakpoint set
+you would type
+.Qq Cm help breakpoint set .
.Pp
-There is also an \fBapropos\fR command which will search the help text of all commands
-for a given term -- this is useful for locating a command by topic. For instance, "\fBapropos breakpoint\fR"
-will list any command that has the word \fBbreakpoint\fR in its help text.
+There is also an
+.Cm apropos
+command which will search the help text of all commands
+for a given term -- this is useful for locating a command by topic.
+For instance,
+.Qq Cm apropos breakpoint
+will list any command that has the word
+.Qq Cm breakpoint
+in its help text.
.Sh FILES
.Nm
will read settings/aliases/commands from three files at startup, if they exist.
.Pp
-First, it will read a \fB~/.lldbinit-\fIdebugger\fR command file. If you are using the
+First, it will read a
+.Pa ~/.lldbinit-debugger
+command file.
+If you are using the
.Nm
-command line interface, this is \fB~/.lldbinit-lldb\fR. If you are using
+command line interface, this is
+.Pa ~/.lldbinit-lldb .
+If you are using
.Nm
inside a GUI debugger like
.Nm Xcode
-this will be \fB~/.lldbinit-Xcode\fR. This is a useful place to put settings that you
-want to apply only when a given
+this will be
+.Pa ~/.lldbinit-Xcode .
+This is a useful place to put settings that you want to apply only when a given
.Nm
command interpreter is used.
.Pp
-Second, \fB~/.lldbinit\fR is read.
+Second,
+.Pa ~/.lldbinit
+is read.
.Pp
-Third, an \fR.lldbinit\fR file in the current working directory (where
+Third, an
+.Pa .lldbinit
+file in the current working directory (where
.Nm
is started) will be read.
.Sh SEE ALSO
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/LLDB.h b/contrib/llvm/tools/lldb/include/lldb/API/LLDB.h
index 66e0953..eed10d0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/LLDB.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/LLDB.h
@@ -16,6 +16,7 @@
// Project includes
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBAddress.h"
+#include "lldb/API/SBAttachInfo.h"
#include "lldb/API/SBBlock.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBBreakpointLocation.h"
@@ -30,28 +31,47 @@
#include "lldb/API/SBError.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBExecutionContext.h"
+#include "lldb/API/SBExpressionOptions.h"
#include "lldb/API/SBFileSpec.h"
+#include "lldb/API/SBFileSpecList.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBFunction.h"
#include "lldb/API/SBHostOS.h"
#include "lldb/API/SBInstruction.h"
#include "lldb/API/SBInstructionList.h"
+#include "lldb/API/SBLanguageRuntime.h"
+#include "lldb/API/SBLaunchInfo.h"
#include "lldb/API/SBLineEntry.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBModule.h"
+#include "lldb/API/SBModuleSpec.h"
+#include "lldb/API/SBPlatform.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBQueue.h"
#include "lldb/API/SBQueueItem.h"
+#include "lldb/API/SBSection.h"
#include "lldb/API/SBSourceManager.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBSymbol.h"
#include "lldb/API/SBSymbolContext.h"
+#include "lldb/API/SBSymbolContextList.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
+#include "lldb/API/SBThreadCollection.h"
+#include "lldb/API/SBThreadPlan.h"
#include "lldb/API/SBType.h"
+#include "lldb/API/SBTypeCategory.h"
+#include "lldb/API/SBTypeEnumMember.h"
+#include "lldb/API/SBTypeFilter.h"
+#include "lldb/API/SBTypeFormat.h"
+#include "lldb/API/SBTypeNameSpecifier.h"
+#include "lldb/API/SBTypeSummary.h"
+#include "lldb/API/SBTypeSynthetic.h"
+#include "lldb/API/SBUnixSignals.h"
#include "lldb/API/SBValue.h"
#include "lldb/API/SBValueList.h"
#include "lldb/API/SBVariablesOptions.h"
+#include "lldb/API/SBWatchpoint.h"
#endif // LLDB_LLDB_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBAttachInfo.h b/contrib/llvm/tools/lldb/include/lldb/API/SBAttachInfo.h
index 712150e..a246d99 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBAttachInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBAttachInfo.h
@@ -23,8 +23,47 @@ public:
SBAttachInfo (lldb::pid_t pid);
+ //------------------------------------------------------------------
+ /// Attach to a process by name.
+ ///
+ /// This function implies that a future call to SBTarget::Attach(...)
+ /// will be synchronous.
+ ///
+ /// @param[in] path
+ /// A full or partial name for the process to attach to.
+ ///
+ /// @param[in] wait_for
+ /// If \b false, attach to an existing process whose name matches.
+ /// If \b true, then wait for the next process whose name matches.
+ //------------------------------------------------------------------
SBAttachInfo (const char *path, bool wait_for);
+ //------------------------------------------------------------------
+ /// Attach to a process by name.
+ ///
+ /// Future calls to SBTarget::Attach(...) will be synchronous or
+ /// asynchronous depending on the \a async argument.
+ ///
+ /// @param[in] path
+ /// A full or partial name for the process to attach to.
+ ///
+ /// @param[in] wait_for
+ /// If \b false, attach to an existing process whose name matches.
+ /// If \b true, then wait for the next process whose name matches.
+ ///
+ /// @param[in] async
+ /// If \b false, then the SBTarget::Attach(...) call will be a
+ /// synchronous call with no way to cancel the attach in
+ /// progress.
+ /// If \b true, then the SBTarget::Attach(...) function will
+ /// return immediately and clients are expected to wait for a
+ /// process eStateStopped event if a suitable process is
+ /// eventually found. If the client wants to cancel the event,
+ /// SBProcess::Stop() can be called and an eStateExited process
+ /// event will be delivered.
+ //------------------------------------------------------------------
+ SBAttachInfo (const char *path, bool wait_for, bool async);
+
SBAttachInfo (const SBAttachInfo &rhs);
~SBAttachInfo();
@@ -47,9 +86,45 @@ public:
bool
GetWaitForLaunch ();
+ //------------------------------------------------------------------
+ /// Set attach by process name settings.
+ ///
+ /// Designed to be used after a call to SBAttachInfo::SetExecutable().
+ /// This function implies that a call to SBTarget::Attach(...) will
+ /// be synchronous.
+ ///
+ /// @param[in] wait_for
+ /// If \b false, attach to an existing process whose name matches.
+ /// If \b true, then wait for the next process whose name matches.
+ //------------------------------------------------------------------
void
SetWaitForLaunch (bool b);
+ //------------------------------------------------------------------
+ /// Set attach by process name settings.
+ ///
+ /// Designed to be used after a call to SBAttachInfo::SetExecutable().
+ /// Future calls to SBTarget::Attach(...) will be synchronous or
+ /// asynchronous depending on the \a async argument.
+ ///
+ /// @param[in] wait_for
+ /// If \b false, attach to an existing process whose name matches.
+ /// If \b true, then wait for the next process whose name matches.
+ ///
+ /// @param[in] async
+ /// If \b false, then the SBTarget::Attach(...) call will be a
+ /// synchronous call with no way to cancel the attach in
+ /// progress.
+ /// If \b true, then the SBTarget::Attach(...) function will
+ /// return immediately and clients are expected to wait for a
+ /// process eStateStopped event if a suitable process is
+ /// eventually found. If the client wants to cancel the event,
+ /// SBProcess::Stop() can be called and an eStateExited process
+ /// event will be delivered.
+ //------------------------------------------------------------------
+ void
+ SetWaitForLaunch (bool b, bool async);
+
bool
GetIgnoreExisting ();
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBCommandInterpreter.h b/contrib/llvm/tools/lldb/include/lldb/API/SBCommandInterpreter.h
index 235a2f3..a8e9bf7 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBCommandInterpreter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBCommandInterpreter.h
@@ -10,6 +10,12 @@
#ifndef LLDB_SBCommandInterpreter_h_
#define LLDB_SBCommandInterpreter_h_
+// C Includes
+// C++ Includes
+#include <memory>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBDebugger.h"
@@ -59,6 +65,7 @@ public:
void
SetAddToHistory (bool);
+
private:
lldb_private::CommandInterpreterRunOptions *
get () const;
@@ -84,11 +91,11 @@ public:
SBCommandInterpreter (const lldb::SBCommandInterpreter &rhs);
+ ~SBCommandInterpreter ();
+
const lldb::SBCommandInterpreter &
operator = (const lldb::SBCommandInterpreter &rhs);
- ~SBCommandInterpreter ();
-
static const char *
GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type);
@@ -187,7 +194,7 @@ public:
lldb::CommandOverrideCallback callback,
void *baton);
- SBCommandInterpreter (lldb_private::CommandInterpreter *interpreter_ptr = NULL); // Access using SBDebugger::GetCommandInterpreter();
+ SBCommandInterpreter(lldb_private::CommandInterpreter *interpreter_ptr = nullptr); // Access using SBDebugger::GetCommandInterpreter();
//----------------------------------------------------------------------
/// Return true if the command interpreter is the active IO handler.
@@ -213,7 +220,7 @@ public:
///
/// @return
/// The string that should be written into the file handle that is
- /// feeding the input stream for the debugger, or NULL if there is
+ /// feeding the input stream for the debugger, or nullptr if there is
/// no string for this control key.
//----------------------------------------------------------------------
const char *
@@ -233,7 +240,6 @@ public:
ResolveCommand(const char *command_line, SBCommandReturnObject &result);
protected:
-
lldb_private::CommandInterpreter &
ref ();
@@ -242,6 +248,7 @@ protected:
void
reset (lldb_private::CommandInterpreter *);
+
private:
friend class SBDebugger;
@@ -254,6 +261,9 @@ private:
class SBCommandPluginInterface
{
public:
+ virtual
+ ~SBCommandPluginInterface() = default;
+
virtual bool
DoExecute (lldb::SBDebugger /*debugger*/,
char** /*command*/,
@@ -261,16 +271,11 @@ public:
{
return false;
}
-
- virtual
- ~SBCommandPluginInterface ()
- {}
};
class SBCommand
{
public:
-
SBCommand ();
bool
@@ -298,13 +303,12 @@ public:
SetFlags (uint32_t flags);
lldb::SBCommand
- AddMultiwordCommand (const char* name, const char* help = NULL);
+ AddMultiwordCommand(const char* name, const char* help = nullptr);
lldb::SBCommand
- AddCommand (const char* name, lldb::SBCommandPluginInterface* impl, const char* help = NULL);
+ AddCommand(const char* name, lldb::SBCommandPluginInterface* impl, const char* help = nullptr);
private:
-
friend class SBDebugger;
friend class SBCommandInterpreter;
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBCommandReturnObject.h b/contrib/llvm/tools/lldb/include/lldb/API/SBCommandReturnObject.h
index c51d6bc..b45eb9c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBCommandReturnObject.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBCommandReturnObject.h
@@ -10,8 +10,14 @@
#ifndef LLDB_SBCommandReturnObject_h_
#define LLDB_SBCommandReturnObject_h_
+// C Includes
#include <stdio.h>
+// C++ Includes
+#include <memory>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/API/SBDefines.h"
namespace lldb {
@@ -19,22 +25,20 @@ namespace lldb {
class LLDB_API SBCommandReturnObject
{
public:
-
SBCommandReturnObject ();
SBCommandReturnObject (const lldb::SBCommandReturnObject &rhs);
+ ~SBCommandReturnObject ();
+
const lldb::SBCommandReturnObject &
operator = (const lldb::SBCommandReturnObject &rhs);
-
SBCommandReturnObject (lldb_private::CommandReturnObject *ptr);
lldb_private::CommandReturnObject *
Release ();
- ~SBCommandReturnObject ();
-
bool
IsValid() const;
@@ -99,8 +103,8 @@ public:
GetError (bool only_if_no_immediate);
void
- SetError (lldb::SBError &error,
- const char *fallback_error_cstr = NULL);
+ SetError(lldb::SBError &error,
+ const char *fallback_error_cstr = nullptr);
void
SetError (const char* error_cstr);
@@ -124,10 +128,10 @@ protected:
void
SetLLDBObjectPtr (lldb_private::CommandReturnObject *ptr);
- private:
+private:
std::unique_ptr<lldb_private::CommandReturnObject> m_opaque_ap;
};
} // namespace lldb
-#endif // LLDB_SBCommandReturnObject_h_
+#endif // LLDB_SBCommandReturnObject_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBDebugger.h b/contrib/llvm/tools/lldb/include/lldb/API/SBDebugger.h
index 4f2c1d7..7588cfc 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBDebugger.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBDebugger.h
@@ -16,13 +16,13 @@
#include "lldb/API/SBPlatform.h"
namespace lldb {
-
class LLDB_API SBInputReader
{
public:
- SBInputReader();
- ~SBInputReader();
+ SBInputReader() = default;
+ ~SBInputReader() = default;
+
SBError Initialize(lldb::SBDebugger&, unsigned long (*)(void*, lldb::SBInputReader*, lldb::InputReaderAction, char const*, unsigned long), void*, lldb::InputReaderGranularity, char const*, char const*, bool);
void SetIsDone(bool);
bool IsActive() const;
@@ -31,6 +31,16 @@ public:
class LLDB_API SBDebugger
{
public:
+ SBDebugger();
+
+ SBDebugger(const lldb::SBDebugger &rhs);
+
+ SBDebugger(const lldb::DebuggerSP &debugger_sp);
+
+ ~SBDebugger();
+
+ lldb::SBDebugger &
+ operator = (const lldb::SBDebugger &rhs);
static void
Initialize();
@@ -54,17 +64,6 @@ public:
static void
MemoryPressureDetected ();
- SBDebugger();
-
- SBDebugger(const lldb::SBDebugger &rhs);
-
- SBDebugger(const lldb::DebuggerSP &debugger_sp);
-
- lldb::SBDebugger &
- operator = (const lldb::SBDebugger &rhs);
-
- ~SBDebugger();
-
bool
IsValid() const;
@@ -288,6 +287,9 @@ public:
GetCategory (const char* category_name);
SBTypeCategory
+ GetCategory (lldb::LanguageType lang_type);
+
+ SBTypeCategory
CreateCategory (const char* category_name);
bool
@@ -329,8 +331,11 @@ public:
int &num_errors,
bool &quit_requested,
bool &stopped_for_crash);
-private:
+
+ SBError
+ RunREPL (lldb::LanguageType language, const char *repl_options);
+private:
friend class SBCommandInterpreter;
friend class SBInputReader;
friend class SBListener;
@@ -357,7 +362,6 @@ private:
}; // class SBDebugger
-
} // namespace lldb
#endif // LLDB_SBDebugger_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBDefines.h b/contrib/llvm/tools/lldb/include/lldb/API/SBDefines.h
index 09bea50..d81bba5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBDefines.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBDefines.h
@@ -86,9 +86,7 @@ class LLDB_API SBTypeMemberFunction;
class LLDB_API SBTypeNameSpecifier;
class LLDB_API SBTypeSummary;
class LLDB_API SBTypeSummaryOptions;
-#ifndef LLDB_DISABLE_PYTHON
class LLDB_API SBTypeSynthetic;
-#endif
class LLDB_API SBTypeList;
class LLDB_API SBValue;
class LLDB_API SBValueList;
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBFunction.h b/contrib/llvm/tools/lldb/include/lldb/API/SBFunction.h
index 86cfeb4..f76c77c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBFunction.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBFunction.h
@@ -53,6 +53,9 @@ public:
lldb::SBAddress
GetEndAddress ();
+ const char *
+ GetArgumentName (uint32_t arg_idx);
+
uint32_t
GetPrologueByteSize ();
@@ -66,6 +69,9 @@ public:
GetLanguage ();
bool
+ GetIsOptimized ();
+
+ bool
operator == (const lldb::SBFunction &rhs) const;
bool
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBProcess.h b/contrib/llvm/tools/lldb/include/lldb/API/SBProcess.h
index 71bca4f..1a9cc80 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBProcess.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBProcess.h
@@ -294,8 +294,56 @@ public:
uint32_t
GetNumSupportedHardwareWatchpoints (lldb::SBError &error) const;
+ //------------------------------------------------------------------
+ /// Load a shared library into this process.
+ ///
+ /// @param[in] remote_image_spec
+ /// The path for the shared library on the target what you want
+ /// to load.
+ ///
+ /// @param[out] error
+ /// An error object that gets filled in with any errors that
+ /// might occur when trying to load the shared library.
+ ///
+ /// @return
+ /// A token that represents the shared library that can be
+ /// later used to unload the shared library. A value of
+ /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
+ /// library can't be opened.
+ //------------------------------------------------------------------
uint32_t
- LoadImage (lldb::SBFileSpec &image_spec, lldb::SBError &error);
+ LoadImage (lldb::SBFileSpec &remote_image_spec, lldb::SBError &error);
+
+ //------------------------------------------------------------------
+ /// Load a shared library into this process.
+ ///
+ /// @param[in] local_image_spec
+ /// The file spec that points to the shared library that you
+ /// want to load if the library is located on the host. The
+ /// library will be copied over to the location specified by
+ /// remote_image_spec or into the current working directory with
+ /// the same filename if the remote_image_spec isn't specified.
+ ///
+ /// @param[in] remote_image_spec
+ /// If local_image_spec is specified then the location where the
+ /// library should be copied over from the host. If
+ /// local_image_spec isn't specified, then the path for the
+ /// shared library on the target what you want to load.
+ ///
+ /// @param[out] error
+ /// An error object that gets filled in with any errors that
+ /// might occur when trying to load the shared library.
+ ///
+ /// @return
+ /// A token that represents the shared library that can be
+ /// later used to unload the shared library. A value of
+ /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
+ /// library can't be opened.
+ //------------------------------------------------------------------
+ uint32_t
+ LoadImage (const lldb::SBFileSpec &local_image_spec,
+ const lldb::SBFileSpec &remote_image_spec,
+ lldb::SBError &error);
lldb::SBError
UnloadImage (uint32_t image_token);
@@ -341,6 +389,10 @@ public:
bool
IsInstrumentationRuntimePresent(InstrumentationRuntimeType type);
+ // Save the state of the process in a core file (or mini dump on Windows).
+ lldb::SBError
+ SaveCore(const char *file_name);
+
protected:
friend class SBAddress;
friend class SBBreakpoint;
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBStream.h b/contrib/llvm/tools/lldb/include/lldb/API/SBStream.h
index 2b25cd2..e62723c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBStream.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBStream.h
@@ -21,7 +21,9 @@ class LLDB_API SBStream
public:
SBStream ();
-
+
+ SBStream (SBStream &&rhs);
+
~SBStream ();
bool
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBTarget.h b/contrib/llvm/tools/lldb/include/lldb/API/SBTarget.h
index 2ca0b12..723c433 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBTarget.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBTarget.h
@@ -10,6 +10,10 @@
#ifndef LLDB_SBTarget_h_
#define LLDB_SBTarget_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBAttachInfo.h"
@@ -50,14 +54,14 @@ public:
SBTarget (const lldb::TargetSP& target_sp);
- const lldb::SBTarget&
- operator = (const lldb::SBTarget& rhs);
-
//------------------------------------------------------------------
// Destructor
//------------------------------------------------------------------
~SBTarget();
+ const lldb::SBTarget&
+ operator = (const lldb::SBTarget& rhs);
+
bool
IsValid() const;
@@ -135,17 +139,17 @@ public:
///
/// @param[in] stdin_path
/// The path to use when re-directing the STDIN of the new
- /// process. If all stdXX_path arguments are NULL, a pseudo
+ /// process. If all stdXX_path arguments are nullptr, a pseudo
/// terminal will be used.
///
/// @param[in] stdout_path
/// The path to use when re-directing the STDOUT of the new
- /// process. If all stdXX_path arguments are NULL, a pseudo
+ /// process. If all stdXX_path arguments are nullptr, a pseudo
/// terminal will be used.
///
/// @param[in] stderr_path
/// The path to use when re-directing the STDERR of the new
- /// process. If all stdXX_path arguments are NULL, a pseudo
+ /// process. If all stdXX_path arguments are nullptr, a pseudo
/// terminal will be used.
///
/// @param[in] working_directory
@@ -175,8 +179,10 @@ public:
uint32_t launch_flags, // See LaunchFlags
bool stop_at_entry,
lldb::SBError& error);
-
-
+
+ SBProcess
+ LoadCore (const char *core_file);
+
//------------------------------------------------------------------
/// Launch a new process with sensible defaults.
///
@@ -212,9 +218,6 @@ public:
Launch (SBLaunchInfo &launch_info, SBError& error);
SBProcess
- LoadCore (const char *core_file);
-
- SBProcess
Attach (SBAttachInfo &attach_info, SBError& error);
//------------------------------------------------------------------
@@ -248,6 +251,7 @@ public:
::pid_t pid, // 32 bit int process ID
lldb::SBError& error); // DEPRECATED
#endif
+
//------------------------------------------------------------------
/// Attach to process with name.
///
@@ -288,7 +292,7 @@ public:
/// The url to connect to, e.g., 'connect://localhost:12345'.
///
/// @param[in] plugin_name
- /// The plugin name to be used; can be NULL.
+ /// The plugin name to be used; can be nullptr.
///
/// @param[out] error
/// An error explaining what went wrong if the connect fails.
@@ -421,7 +425,6 @@ public:
lldb::SBError
SetModuleLoadAddress (lldb::SBModule module,
int64_t sections_offset);
-
//------------------------------------------------------------------
/// Clear the section base load addresses for all sections in a module.
@@ -618,7 +621,7 @@ public:
BreakpointCreateByLocation (const lldb::SBFileSpec &file_spec, uint32_t line);
lldb::SBBreakpoint
- BreakpointCreateByName (const char *symbol_name, const char *module_name = NULL);
+ BreakpointCreateByName(const char *symbol_name, const char *module_name = nullptr);
// This version uses name_type_mask = eFunctionNameTypeAuto
lldb::SBBreakpoint
@@ -633,14 +636,29 @@ public:
const SBFileSpecList &comp_unit_list);
lldb::SBBreakpoint
+ BreakpointCreateByName (const char *symbol_name,
+ uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits
+ lldb::LanguageType symbol_language,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &comp_unit_list);
+
+ lldb::SBBreakpoint
+ BreakpointCreateByNames (const char *symbol_name[],
+ uint32_t num_names,
+ uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &comp_unit_list);
+
+ lldb::SBBreakpoint
BreakpointCreateByNames (const char *symbol_name[],
uint32_t num_names,
uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits
+ lldb::LanguageType symbol_language,
const SBFileSpecList &module_list,
const SBFileSpecList &comp_unit_list);
lldb::SBBreakpoint
- BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name = NULL);
+ BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name = nullptr);
lldb::SBBreakpoint
BreakpointCreateByRegex (const char *symbol_name_regex,
@@ -648,9 +666,15 @@ public:
const SBFileSpecList &comp_unit_list);
lldb::SBBreakpoint
- BreakpointCreateBySourceRegex (const char *source_regex,
- const SBFileSpec &source_file,
- const char *module_name = NULL);
+ BreakpointCreateByRegex (const char *symbol_name_regex,
+ lldb::LanguageType symbol_language,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &comp_unit_list);
+
+ lldb::SBBreakpoint
+ BreakpointCreateBySourceRegex(const char *source_regex,
+ const SBFileSpec &source_file,
+ const char *module_name = nullptr);
lldb::SBBreakpoint
BreakpointCreateBySourceRegex (const char *source_regex,
@@ -665,6 +689,9 @@ public:
lldb::SBBreakpoint
BreakpointCreateByAddress (addr_t address);
+ lldb::SBBreakpoint
+ BreakpointCreateBySBAddress (SBAddress &address);
+
uint32_t
GetNumBreakpoints () const;
@@ -808,15 +835,10 @@ protected:
void
SetSP (const lldb::TargetSP& target_sp);
-
private:
- //------------------------------------------------------------------
- // For Target only
- //------------------------------------------------------------------
-
lldb::TargetSP m_opaque_sp;
};
} // namespace lldb
-#endif // LLDB_SBTarget_h_
+#endif // LLDB_SBTarget_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBType.h b/contrib/llvm/tools/lldb/include/lldb/API/SBType.h
index 01f0c6a..ed3c2ff 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBType.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBType.h
@@ -85,7 +85,13 @@ public:
const char *
GetName ();
-
+
+ const char *
+ GetDemangledName ();
+
+ const char *
+ GetMangledName ();
+
lldb::SBType
GetType ();
@@ -158,6 +164,9 @@ public:
bool
IsTypedefType ();
+ bool
+ IsAnonymousType ();
+
lldb::SBType
GetPointerType();
@@ -290,7 +299,7 @@ protected:
friend class SBTypeList;
friend class SBValue;
- SBType (const lldb_private::ClangASTType &);
+ SBType (const lldb_private::CompilerType &);
SBType (const lldb::TypeSP &);
SBType (const lldb::TypeImplSP &);
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBTypeCategory.h b/contrib/llvm/tools/lldb/include/lldb/API/SBTypeCategory.h
index 30c338b..997b3fc 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBTypeCategory.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBTypeCategory.h
@@ -36,6 +36,15 @@ namespace lldb {
const char*
GetName();
+ lldb::LanguageType
+ GetLanguageAtIndex (uint32_t idx);
+
+ uint32_t
+ GetNumLanguages ();
+
+ void
+ AddLanguage (lldb::LanguageType language);
+
bool
GetDescription (lldb::SBStream &description,
lldb::DescriptionLevel description_level);
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBTypeSummary.h b/contrib/llvm/tools/lldb/include/lldb/API/SBTypeSummary.h
index 9b367ba..f4c6661 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBTypeSummary.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBTypeSummary.h
@@ -12,8 +12,6 @@
#include "lldb/API/SBDefines.h"
-#ifndef LLDB_DISABLE_PYTHON
-
namespace lldb {
class LLDB_API SBTypeSummaryOptions
{
@@ -71,6 +69,9 @@ namespace lldb {
public:
SBTypeSummary();
+
+ // Native function summary formatter callback
+ typedef bool (*FormatCallback) (SBValue, SBTypeSummaryOptions, SBStream&);
static SBTypeSummary
CreateWithSummaryString (const char* data,
@@ -83,6 +84,11 @@ namespace lldb {
static SBTypeSummary
CreateWithScriptCode (const char* data,
uint32_t options = 0); // see lldb::eTypeOption values
+
+ static SBTypeSummary
+ CreateWithCallback (FormatCallback cb,
+ uint32_t options = 0,
+ const char* description = nullptr);
SBTypeSummary (const lldb::SBTypeSummary &rhs);
@@ -126,6 +132,9 @@ namespace lldb {
operator = (const lldb::SBTypeSummary &rhs);
bool
+ DoesPrintValue (lldb::SBValue value);
+
+ bool
IsEqualTo (lldb::SBTypeSummary &rhs);
bool
@@ -160,6 +169,4 @@ namespace lldb {
} // namespace lldb
-#endif // LLDB_DISABLE_PYTHON
-
#endif // LLDB_SBTypeSummary_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SBValue.h b/contrib/llvm/tools/lldb/include/lldb/API/SBValue.h
index a070b14..a7e0150 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SBValue.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SBValue.h
@@ -139,10 +139,8 @@ public:
lldb::SBTypeFormat
GetTypeFormat ();
-#ifndef LLDB_DISABLE_PYTHON
lldb::SBTypeSummary
GetTypeSummary ();
-#endif
lldb::SBTypeFilter
GetTypeFilter ();
@@ -206,7 +204,11 @@ public:
/// pointer to a 'Point' type, then the child at index zero will be
/// the 'x' member, and the child at index 1 will be the 'y' member
/// (the child at index zero won't be a 'Point' instance).
- ///
+ ///
+ /// If you actually need an SBValue that represents the type pointed
+ /// to by a SBValue for which GetType().IsPointeeType() returns true,
+ /// regardless of the pointee type, you can do that with SBValue::Dereference.
+ ///
/// Arrays have a preset number of children that can be accessed by
/// index and will returns invalid child values for indexes that are
/// out of bounds unless the \a synthetic_allowed is \b true. In this
@@ -332,6 +334,9 @@ public:
uint32_t
GetNumChildren ();
+ uint32_t
+ GetNumChildren (uint32_t max);
+
void *
GetOpaqueType();
@@ -350,6 +355,7 @@ public:
lldb::SBValue
Dereference ();
+ // Deprecated - please use GetType().IsPointerType() instead.
bool
TypeIsPointerType ();
diff --git a/contrib/llvm/tools/lldb/include/lldb/API/SystemInitializerFull.h b/contrib/llvm/tools/lldb/include/lldb/API/SystemInitializerFull.h
index 6280fe8..9e37611 100644
--- a/contrib/llvm/tools/lldb/include/lldb/API/SystemInitializerFull.h
+++ b/contrib/llvm/tools/lldb/include/lldb/API/SystemInitializerFull.h
@@ -26,15 +26,15 @@ class SystemInitializerFull : public SystemInitializerCommon
{
public:
SystemInitializerFull();
- virtual ~SystemInitializerFull();
+ ~SystemInitializerFull() override;
void Initialize() override;
void Terminate() override;
private:
void InitializeSWIG();
- void TerminateSWIG();
};
-}
-#endif
+} // namespace lldb_private
+
+#endif // LLDB_API_SYSTEM_INITIALIZER_FULL_H
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Breakpoint.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Breakpoint.h
index a70c278..7fdf06d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Breakpoint.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Breakpoint.h
@@ -12,7 +12,10 @@
// C Includes
// C++ Includes
+#include <memory>
+#include <string>
#include <unordered_set>
+#include <vector>
// Other libraries and framework includes
// Project includes
@@ -81,11 +84,9 @@ class Breakpoint:
public Stoppoint
{
public:
-
static const ConstString &
GetEventIdentifier ();
-
//------------------------------------------------------------------
/// An enum specifying the match style for breakpoint settings. At
/// present only used for function name style breakpoints.
@@ -101,18 +102,16 @@ public:
public EventData
{
public:
+ BreakpointEventData (lldb::BreakpointEventType sub_type,
+ const lldb::BreakpointSP &new_breakpoint_sp);
+
+ ~BreakpointEventData() override;
static const ConstString &
GetFlavorString ();
- virtual const ConstString &
- GetFlavor () const;
-
- BreakpointEventData (lldb::BreakpointEventType sub_type,
- const lldb::BreakpointSP &new_breakpoint_sp);
-
- virtual
- ~BreakpointEventData();
+ const ConstString &
+ GetFlavor() const override;
lldb::BreakpointEventType
GetBreakpointEventType () const;
@@ -126,9 +125,8 @@ public:
return m_locations;
}
-
- virtual void
- Dump (Stream *s) const;
+ void
+ Dump(Stream *s) const override;
static lldb::BreakpointEventType
GetBreakpointEventTypeFromEvent (const lldb::EventSP &event_sp);
@@ -146,7 +144,6 @@ public:
GetEventDataFromEvent (const Event *event_sp);
private:
-
lldb::BreakpointEventType m_breakpoint_event;
lldb::BreakpointSP m_new_breakpoint_sp;
BreakpointLocationCollection m_locations;
@@ -154,11 +151,10 @@ public:
DISALLOW_COPY_AND_ASSIGN (BreakpointEventData);
};
-
class BreakpointPrecondition
{
public:
- virtual ~BreakpointPrecondition() {}
+ virtual ~BreakpointPrecondition() = default;
virtual bool
EvaluatePrecondition(StoppointCallbackContext &context);
@@ -167,7 +163,7 @@ public:
ConfigurePrecondition(Args &options);
virtual void
- DescribePrecondition(Stream &stream, lldb::DescriptionLevel level);
+ GetDescription(Stream &stream, lldb::DescriptionLevel level);
};
typedef std::shared_ptr<BreakpointPrecondition> BreakpointPreconditionSP;
@@ -179,7 +175,7 @@ public:
/// breakpoints. The varieties of breakpoints are specified instead by
/// providing different resolvers & filters.
//------------------------------------------------------------------
- ~Breakpoint();
+ ~Breakpoint() override;
//------------------------------------------------------------------
// Methods
@@ -197,14 +193,13 @@ public:
/// Standard "Dump" method. At present it does nothing.
//------------------------------------------------------------------
void
- Dump (Stream *s);
+ Dump(Stream *s) override;
//------------------------------------------------------------------
// The next set of methods provide ways to tell the breakpoint to update
// it's location list - usually done when modules appear or disappear.
//------------------------------------------------------------------
-
//------------------------------------------------------------------
/// Tell this breakpoint to clear all its breakpoint sites. Done
/// when the process holding the breakpoint sites is destroyed.
@@ -262,7 +257,6 @@ public:
bool load_event,
bool delete_locations = false);
-
//------------------------------------------------------------------
/// Tells the breakpoint the old module \a old_module_sp has been
/// replaced by new_module_sp (usually because the underlying file has been
@@ -294,8 +288,8 @@ public:
/// Returns a pointer to the new location.
//------------------------------------------------------------------
lldb::BreakpointLocationSP
- AddLocation (const Address &addr,
- bool *new_location = NULL);
+ AddLocation(const Address &addr,
+ bool *new_location = nullptr);
//------------------------------------------------------------------
/// Find a breakpoint location by Address.
@@ -304,7 +298,7 @@ public:
/// The Address specifying the location.
/// @return
/// Returns a shared pointer to the location at \a addr. The pointer
- /// in the shared pointer will be NULL if there is no location at that address.
+ /// in the shared pointer will be nullptr if there is no location at that address.
//------------------------------------------------------------------
lldb::BreakpointLocationSP
FindLocationByAddress (const Address &addr);
@@ -328,7 +322,7 @@ public:
/// The ID specifying the location.
/// @return
/// Returns a shared pointer to the location with ID \a bp_loc_id. The pointer
- /// in the shared pointer will be NULL if there is no location with that ID.
+ /// in the shared pointer will be nullptr if there is no location with that ID.
//------------------------------------------------------------------
lldb::BreakpointLocationSP
FindLocationByID (lldb::break_id_t bp_loc_id);
@@ -341,7 +335,7 @@ public:
///
/// @return
/// Returns a shared pointer to the location with index \a
- /// index. The shared pointer might contain NULL if \a index is
+ /// index. The shared pointer might contain nullptr if \a index is
/// greater than then number of actual locations.
//------------------------------------------------------------------
lldb::BreakpointLocationSP
@@ -373,7 +367,7 @@ public:
/// If \a enable is \b true, enable the breakpoint, if \b false disable it.
//------------------------------------------------------------------
void
- SetEnabled (bool enable);
+ SetEnabled(bool enable) override;
//------------------------------------------------------------------
/// Check the Enable/Disable state.
@@ -381,7 +375,7 @@ public:
/// \b true if the breakpoint is enabled, \b false if disabled.
//------------------------------------------------------------------
bool
- IsEnabled ();
+ IsEnabled() override;
//------------------------------------------------------------------
/// Set the breakpoint to ignore the next \a count breakpoint hits.
@@ -407,7 +401,6 @@ public:
uint32_t
GetHitCount () const;
-
//------------------------------------------------------------------
/// If \a one_shot is \b true, breakpoint will be deleted on first hit.
//------------------------------------------------------------------
@@ -490,7 +483,7 @@ public:
///
/// @param[in] condition
/// The condition expression to evaluate when the breakpoint is hit.
- /// Pass in NULL to clear the condition.
+ /// Pass in nullptr to clear the condition.
//------------------------------------------------------------------
void SetCondition (const char *condition);
@@ -498,7 +491,7 @@ public:
/// Return a pointer to the text of the condition expression.
///
/// @return
- /// A pointer to the condition expression text, or NULL if no
+ /// A pointer to the condition expression text, or nullptr if no
// condition has been set.
//------------------------------------------------------------------
const char *GetConditionText () const;
@@ -560,7 +553,7 @@ public:
/// Return the "kind" description for a breakpoint.
///
/// @return
- /// The breakpoint kind, or NULL if none is set.
+ /// The breakpoint kind, or nullptr if none is set.
//------------------------------------------------------------------
const char *GetBreakpointKind () const
{
@@ -619,7 +612,6 @@ public:
BreakpointOptions *
GetOptions ();
-
//------------------------------------------------------------------
/// Invoke the callback action when the breakpoint is hit.
///
@@ -713,7 +705,6 @@ protected:
// Protected Methods
//------------------------------------------------------------------
-
//------------------------------------------------------------------
/// Constructors and Destructors
/// Only the Target can make a breakpoint, and it owns the breakpoint lifespans.
@@ -807,4 +798,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_Breakpoint_h_
+#endif // liblldb_Breakpoint_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocation.h
index c3e620d..58d144c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocation.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocation.h
@@ -11,12 +11,10 @@
#define liblldb_BreakpointLocation_h_
// C Includes
-
// C++ Includes
-#include <list>
+#include <memory>
// Other libraries and framework includes
-
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Breakpoint/StoppointLocation.h"
@@ -49,7 +47,7 @@ class BreakpointLocation :
public StoppointLocation
{
public:
- ~BreakpointLocation ();
+ ~BreakpointLocation() override;
//------------------------------------------------------------------
/// Gets the load address for this breakpoint location
@@ -58,7 +56,7 @@ public:
/// LLDB_INVALID_ADDRESS if not yet set.
//------------------------------------------------------------------
lldb::addr_t
- GetLoadAddress () const;
+ GetLoadAddress() const override;
//------------------------------------------------------------------
/// Gets the Address for this breakpoint location
@@ -74,6 +72,9 @@ public:
//------------------------------------------------------------------
Breakpoint &
GetBreakpoint ();
+
+ Target &
+ GetTarget();
//------------------------------------------------------------------
/// Determines whether we should stop due to a hit at this
@@ -88,7 +89,7 @@ public:
/// \b false otherwise.
//------------------------------------------------------------------
bool
- ShouldStop (StoppointCallbackContext *context);
+ ShouldStop(StoppointCallbackContext *context) override;
//------------------------------------------------------------------
// The next section deals with various breakpoint options.
@@ -169,16 +170,15 @@ public:
/// Return a pointer to the text of the condition expression.
///
/// @return
- /// A pointer to the condition expression text, or NULL if no
+ /// A pointer to the condition expression text, or nullptr if no
// condition has been set.
//------------------------------------------------------------------
const char *
- GetConditionText (size_t *hash = NULL) const;
+ GetConditionText(size_t *hash = nullptr) const;
bool
ConditionSaysStop (ExecutionContext &exe_ctx, Error &error);
-
//------------------------------------------------------------------
/// Set the valid thread to be checked when the breakpoint is hit.
///
@@ -270,7 +270,7 @@ public:
/// Standard "Dump" method. At present it does nothing.
//------------------------------------------------------------------
void
- Dump (Stream *s) const;
+ Dump(Stream *s) const override;
//------------------------------------------------------------------
/// Use this to set location specific breakpoint options.
@@ -299,7 +299,6 @@ public:
bool
ValidForThisThread (Thread *thread);
-
//------------------------------------------------------------------
/// Invoke the callback action when the breakpoint is hit.
///
@@ -418,7 +417,6 @@ private:
void
UndoBumpHitCount();
-
//------------------------------------------------------------------
// Constructors and Destructors
//
@@ -459,9 +457,9 @@ private:
bool m_is_indirect;
Address m_address; ///< The address defining this location.
Breakpoint &m_owner; ///< The breakpoint that produced this object.
- std::unique_ptr<BreakpointOptions> m_options_ap; ///< Breakpoint options pointer, NULL if we're using our breakpoint's options.
+ std::unique_ptr<BreakpointOptions> m_options_ap; ///< Breakpoint options pointer, nullptr if we're using our breakpoint's options.
lldb::BreakpointSiteSP m_bp_site_sp; ///< Our breakpoint site (it may be shared by more than one location.)
- lldb::ClangUserExpressionSP m_user_expression_sp; ///< The compiled expression to use in testing our condition.
+ lldb::UserExpressionSP m_user_expression_sp; ///< The compiled expression to use in testing our condition.
Mutex m_condition_mutex; ///< Guards parsing and evaluation of the condition, which could be evaluated by multiple processes.
size_t m_condition_hash; ///< For testing whether the condition source code changed.
@@ -479,4 +477,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_BreakpointLocation_h_
+#endif // liblldb_BreakpointLocation_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationList.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
index f67ef89..8152608 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointLocationList.h
@@ -12,8 +12,9 @@
// C Includes
// C++ Includes
-#include <vector>
#include <map>
+#include <vector>
+
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@@ -56,7 +57,7 @@ public:
/// The address to look for.
///
/// @result
- /// A shared pointer to the breakpoint. May contain a NULL
+ /// A shared pointer to the breakpoint. May contain a nullptr
/// pointer if the breakpoint doesn't exist.
//------------------------------------------------------------------
const lldb::BreakpointLocationSP
@@ -70,7 +71,7 @@ public:
/// The breakpoint location ID to seek for.
///
/// @result
- /// A shared pointer to the breakpoint. May contain a NULL
+ /// A shared pointer to the breakpoint. May contain a nullptr
/// pointer if the breakpoint doesn't exist.
//------------------------------------------------------------------
lldb::BreakpointLocationSP
@@ -116,7 +117,7 @@ public:
/// The breakpoint location index to seek for.
///
/// @result
- /// A shared pointer to the breakpoint. May contain a NULL
+ /// A shared pointer to the breakpoint. May contain a nullptr
/// pointer if the breakpoint doesn't exist.
//------------------------------------------------------------------
lldb::BreakpointLocationSP
@@ -130,7 +131,7 @@ public:
/// The breakpoint location index to seek for.
///
/// @result
- /// A shared pointer to the breakpoint. May contain a NULL
+ /// A shared pointer to the breakpoint. May contain a nullptr
/// pointer if the breakpoint doesn't exist.
//------------------------------------------------------------------
const lldb::BreakpointLocationSP
@@ -216,7 +217,6 @@ public:
lldb::DescriptionLevel level);
protected:
-
//------------------------------------------------------------------
/// This is the standard constructor.
///
@@ -246,9 +246,9 @@ protected:
StopRecordingNewLocations();
lldb::BreakpointLocationSP
- AddLocation (const Address &addr,
- bool resolve_indirect_symbols,
- bool *new_location = NULL);
+ AddLocation(const Address &addr,
+ bool resolve_indirect_symbols,
+ bool *new_location = nullptr);
void
SwapLocation (lldb::BreakpointLocationSP to_location_sp, lldb::BreakpointLocationSP from_location_sp);
@@ -273,16 +273,17 @@ protected:
mutable Mutex m_mutex;
lldb::break_id_t m_next_id;
BreakpointLocationCollection *m_new_location_recorder;
+
public:
typedef AdaptedIterable<collection, lldb::BreakpointLocationSP, vector_adapter> BreakpointLocationIterable;
+
BreakpointLocationIterable
BreakpointLocations()
{
return BreakpointLocationIterable(m_locations);
}
-
};
} // namespace lldb_private
-#endif // liblldb_BreakpointLocationList_h_
+#endif // liblldb_BreakpointLocationList_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointOptions.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointOptions.h
index bf10fc0..e788214 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointOptions.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointOptions.h
@@ -12,6 +12,9 @@
// C Includes
// C++ Includes
+#include <memory>
+#include <string>
+
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@@ -115,7 +118,6 @@ public:
//------------------------------------------------------------------
void SetCallback (BreakpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous = false);
-
//------------------------------------------------------------------
/// Remove the callback from this option set.
//------------------------------------------------------------------
@@ -184,10 +186,10 @@ public:
/// Return a pointer to the text of the condition expression.
///
/// @return
- /// A pointer to the condition expression text, or NULL if no
+ /// A pointer to the condition expression text, or nullptr if no
// condition has been set.
//------------------------------------------------------------------
- const char *GetConditionText (size_t *hash = NULL) const;
+ const char *GetConditionText(size_t *hash = nullptr) const;
//------------------------------------------------------------------
// Enabled/Ignore Count
@@ -257,10 +259,10 @@ public:
}
//------------------------------------------------------------------
- /// Return the current thread spec for this option. This will return NULL if the no thread
+ /// Return the current thread spec for this option. This will return nullptr if the no thread
/// specifications have been set for this Option yet.
/// @return
- /// The thread specification pointer for this option, or NULL if none has
+ /// The thread specification pointer for this option, or nullptr if none has
/// been set yet.
//------------------------------------------------------------------
const ThreadSpec *
@@ -298,7 +300,6 @@ public:
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
-
struct CommandData
{
CommandData () :
@@ -308,10 +309,8 @@ public:
{
}
- ~CommandData ()
- {
- }
-
+ ~CommandData() = default;
+
StringList user_source;
std::string script_source;
bool stop_on_error;
@@ -325,16 +324,14 @@ public:
{
}
- virtual
- ~CommandBaton ()
+ ~CommandBaton() override
{
delete ((CommandData *)m_data);
- m_data = NULL;
+ m_data = nullptr;
}
- virtual void
- GetDescription (Stream *s, lldb::DescriptionLevel level) const;
-
+ void
+ GetDescription (Stream *s, lldb::DescriptionLevel level) const override;
};
protected:
@@ -359,4 +356,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_BreakpointOptions_h_
+#endif // liblldb_BreakpointOptions_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolver.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolver.h
index 6ba53ea..198abed 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolver.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolver.h
@@ -66,8 +66,7 @@ public:
/// The Destructor is virtual, all significant breakpoint resolvers derive
/// from this class.
//------------------------------------------------------------------
- virtual
- ~BreakpointResolver ();
+ ~BreakpointResolver() override;
//------------------------------------------------------------------
/// This sets the breakpoint for this resolver.
@@ -105,8 +104,8 @@ public:
/// @param[in] s
/// Stream to which the output is copied.
//------------------------------------------------------------------
- virtual void
- GetDescription (Stream *s) = 0;
+ void
+ GetDescription(Stream *s) override = 0;
//------------------------------------------------------------------
/// Standard "Dump" method. At present it does nothing.
@@ -157,4 +156,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_BreakpointResolver_h_
+#endif // liblldb_BreakpointResolver_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h
index c8f034d..8ec1e39 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h
@@ -15,6 +15,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Core/ModuleSpec.h"
namespace lldb_private {
@@ -31,8 +32,11 @@ public:
BreakpointResolverAddress (Breakpoint *bkpt,
const Address &addr);
- virtual
- ~BreakpointResolverAddress ();
+ BreakpointResolverAddress (Breakpoint *bkpt,
+ const Address &addr,
+ const FileSpec &module_spec);
+
+ ~BreakpointResolverAddress() override;
void
ResolveBreakpoint (SearchFilter &filter) override;
@@ -66,12 +70,15 @@ public:
CopyForBreakpoint (Breakpoint &breakpoint) override;
protected:
- Address m_addr;
-
+ Address m_addr; // The address - may be Section Offset or may be just an offset
+ lldb::addr_t m_resolved_addr; // The current value of the resolved load address for this breakpoint,
+ FileSpec m_module_filespec; // If this filespec is Valid, and m_addr is an offset, then it will be converted
+ // to a Section+Offset address in this module, whenever that module gets around to
+ // being loaded.
private:
DISALLOW_COPY_AND_ASSIGN(BreakpointResolverAddress);
};
} // namespace lldb_private
-#endif // liblldb_BreakpointResolverAddress_h_
+#endif // liblldb_BreakpointResolverAddress_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h
index 2403d24..2dde154 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h
@@ -35,8 +35,7 @@ public:
bool skip_prologue,
bool exact_match);
- virtual
- ~BreakpointResolverFileLine ();
+ ~BreakpointResolverFileLine() override;
Searcher::CallbackReturn
SearchCallback (SearchFilter &filter,
@@ -76,4 +75,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_BreakpointResolverFileLine_h_
+#endif // liblldb_BreakpointResolverFileLine_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
index 8e18fff..a8d7a50 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
@@ -32,8 +32,7 @@ public:
RegularExpression &regex,
bool exact_match);
- virtual
- ~BreakpointResolverFileRegex ();
+ ~BreakpointResolverFileRegex() override;
Searcher::CallbackReturn
SearchCallback (SearchFilter &filter,
@@ -70,4 +69,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_BreakpointResolverFileRegex_h_
+#endif // liblldb_BreakpointResolverFileRegex_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverName.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverName.h
index c2a5b18..aaae9c1 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverName.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointResolverName.h
@@ -14,6 +14,7 @@
// C++ Includes
#include <vector>
#include <string>
+
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointResolver.h"
@@ -34,6 +35,7 @@ public:
BreakpointResolverName (Breakpoint *bkpt,
const char *name,
uint32_t name_type_mask,
+ lldb::LanguageType language,
Breakpoint::MatchType type,
bool skip_prologue);
@@ -42,17 +44,20 @@ public:
const char *names[],
size_t num_names,
uint32_t name_type_mask,
+ lldb::LanguageType language,
bool skip_prologue);
// This one takes a C++ array of names. It is always MatchType = Exact.
BreakpointResolverName (Breakpoint *bkpt,
std::vector<std::string> names,
uint32_t name_type_mask,
+ lldb::LanguageType language,
bool skip_prologue);
// Creates a function breakpoint by regular expression. Takes over control of the lifespan of func_regex.
BreakpointResolverName (Breakpoint *bkpt,
RegularExpression &func_regex,
+ lldb::LanguageType language,
bool skip_prologue);
BreakpointResolverName (Breakpoint *bkpt,
@@ -61,8 +66,7 @@ public:
Breakpoint::MatchType type,
bool skip_prologue);
- virtual
- ~BreakpointResolverName ();
+ ~BreakpointResolverName() override;
Searcher::CallbackReturn
SearchCallback (SearchFilter &filter,
@@ -114,6 +118,7 @@ protected:
ConstString m_class_name;
RegularExpression m_regex;
Breakpoint::MatchType m_match_type;
+ lldb::LanguageType m_language;
bool m_skip_prologue;
void
@@ -122,4 +127,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_BreakpointResolverName_h_
+#endif // liblldb_BreakpointResolverName_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSite.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSite.h
index d67fc8b..6cebcab 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSite.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/BreakpointSite.h
@@ -55,7 +55,7 @@ public:
// display any breakpoint opcodes.
};
- virtual ~BreakpointSite ();
+ ~BreakpointSite() override;
//----------------------------------------------------------------------
// This section manages the breakpoint traps
@@ -139,8 +139,8 @@ public:
/// @return
/// \b true if we should stop, \b false otherwise.
//------------------------------------------------------------------
- virtual bool
- ShouldStop (StoppointCallbackContext *context);
+ bool
+ ShouldStop(StoppointCallbackContext *context) override;
//------------------------------------------------------------------
/// Standard Dump method
@@ -149,7 +149,7 @@ public:
/// The stream to dump this output.
//------------------------------------------------------------------
void
- Dump (Stream *s) const;
+ Dump(Stream *s) const override;
//------------------------------------------------------------------
/// The "Owners" are the breakpoint locations that share this
@@ -187,6 +187,20 @@ public:
GetOwnerAtIndex (size_t idx);
//------------------------------------------------------------------
+ /// This method copies the breakpoint site's owners into a new collection.
+ /// It does this while the owners mutex is locked.
+ ///
+ /// @param[out] out_collection
+ /// The BreakpointLocationCollection into which to put the owners
+ /// of this breakpoint site.
+ ///
+ /// @return
+ /// The number of elements copied into out_collection.
+ //------------------------------------------------------------------
+ size_t
+ CopyOwnersList (BreakpointLocationCollection &out_collection);
+
+ //------------------------------------------------------------------
/// Check whether the owners of this breakpoint site have any
/// thread specifiers, and if yes, is \a thread contained in any
/// of these specifiers.
@@ -201,7 +215,6 @@ public:
bool
ValidForThisThread (Thread *thread);
-
//------------------------------------------------------------------
/// Print a description of this breakpoint site to the stream \a s.
/// GetDescription tells you about the breakpoint site's owners.
@@ -301,4 +314,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_BreakpointSite_h_
+#endif // liblldb_BreakpointSite_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Watchpoint.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Watchpoint.h
index 926e0b5..34df24a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Watchpoint.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/Watchpoint.h
@@ -11,19 +11,17 @@
#define liblldb_Watchpoint_h_
// C Includes
-
// C++ Includes
-#include <list>
+#include <memory>
#include <string>
// Other libraries and framework includes
-
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Breakpoint/WatchpointOptions.h"
#include "lldb/Breakpoint/StoppointLocation.h"
#include "lldb/Core/UserID.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Target.h"
namespace lldb_private {
@@ -33,23 +31,20 @@ class Watchpoint :
public StoppointLocation
{
public:
-
class WatchpointEventData :
public EventData
{
public:
+ WatchpointEventData (lldb::WatchpointEventType sub_type,
+ const lldb::WatchpointSP &new_watchpoint_sp);
+
+ ~WatchpointEventData() override;
static const ConstString &
GetFlavorString ();
- virtual const ConstString &
- GetFlavor () const;
-
- WatchpointEventData (lldb::WatchpointEventType sub_type,
- const lldb::WatchpointSP &new_watchpoint_sp);
-
- virtual
- ~WatchpointEventData();
+ const ConstString &
+ GetFlavor() const override;
lldb::WatchpointEventType
GetWatchpointEventType () const;
@@ -57,8 +52,8 @@ public:
lldb::WatchpointSP &
GetWatchpoint ();
- virtual void
- Dump (Stream *s) const;
+ void
+ Dump(Stream *s) const override;
static lldb::WatchpointEventType
GetWatchpointEventTypeFromEvent (const lldb::EventSP &event_sp);
@@ -70,15 +65,15 @@ public:
GetEventDataFromEvent (const Event *event_sp);
private:
-
lldb::WatchpointEventType m_watchpoint_event;
lldb::WatchpointSP m_new_watchpoint_sp;
DISALLOW_COPY_AND_ASSIGN (WatchpointEventData);
};
- Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const ClangASTType *type, bool hardware = true);
- ~Watchpoint ();
+ Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const CompilerType *type, bool hardware = true);
+
+ ~Watchpoint() override;
void
IncrementFalseAlarmsAndReviseHitCount();
@@ -89,11 +84,11 @@ public:
void
SetEnabled (bool enabled, bool notify = true);
- virtual bool
- IsHardware () const;
+ bool
+ IsHardware() const override;
- virtual bool
- ShouldStop (StoppointCallbackContext *context);
+ bool
+ ShouldStop(StoppointCallbackContext *context) override;
bool WatchpointRead () const;
bool WatchpointWrite () const;
@@ -110,8 +105,8 @@ public:
bool CaptureWatchedValue (const ExecutionContext &exe_ctx);
void GetDescription (Stream *s, lldb::DescriptionLevel level);
- void Dump (Stream *s) const;
- void DumpSnapshots (Stream *s, const char * prefix = NULL) const;
+ void Dump (Stream *s) const override;
+ void DumpSnapshots(Stream *s, const char *prefix = nullptr) const;
void DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const;
Target &GetTarget() { return m_target; }
const Error &GetError() { return m_error; }
@@ -173,7 +168,7 @@ public:
///
/// @param[in] condition
/// The condition expression to evaluate when the watchpoint is hit.
- /// Pass in NULL to clear the condition.
+ /// Pass in nullptr to clear the condition.
//------------------------------------------------------------------
void SetCondition (const char *condition);
@@ -181,7 +176,7 @@ public:
/// Return a pointer to the text of the condition expression.
///
/// @return
- /// A pointer to the condition expression text, or NULL if no
+ /// A pointer to the condition expression text, or nullptr if no
// condition has been set.
//------------------------------------------------------------------
const char *GetConditionText () const;
@@ -195,13 +190,12 @@ public:
bool
IsDisabledDuringEphemeralMode();
- const ClangASTType &
- GetClangASTType()
+ const CompilerType &
+ GetCompilerType()
{
return m_type;
}
-
private:
friend class Target;
friend class WatchpointList;
@@ -240,13 +234,13 @@ private:
std::string m_watch_spec_str; // Spec for the watchpoint.
lldb::ValueObjectSP m_old_value_sp;
lldb::ValueObjectSP m_new_value_sp;
- ClangASTType m_type;
+ CompilerType m_type;
Error m_error; // An error object describing errors associated with this watchpoint.
WatchpointOptions m_options; // Settable watchpoint options, which is a delegate to handle
// the callback machinery.
bool m_being_created;
- std::unique_ptr<ClangUserExpression> m_condition_ap; // The condition to test.
+ std::unique_ptr<UserExpression> m_condition_ap; // The condition to test.
void SetID(lldb::watch_id_t id) { m_loc_id = id; }
@@ -261,4 +255,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_Watchpoint_h_
+#endif // liblldb_Watchpoint_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointOptions.h b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointOptions.h
index 64c65f9..eb08bb3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointOptions.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Breakpoint/WatchpointOptions.h
@@ -12,6 +12,9 @@
// C Includes
// C++ Includes
+#include <memory>
+#include <string>
+
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@@ -99,7 +102,6 @@ public:
//------------------------------------------------------------------
void SetCallback (WatchpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous = false);
-
//------------------------------------------------------------------
/// Remove the callback from this option set.
//------------------------------------------------------------------
@@ -150,10 +152,10 @@ public:
const Baton *GetBaton () const;
//------------------------------------------------------------------
- /// Return the current thread spec for this option. This will return NULL if the no thread
+ /// Return the current thread spec for this option. This will return nullptr if the no thread
/// specifications have been set for this Option yet.
/// @return
- /// The thread specification pointer for this option, or NULL if none has
+ /// The thread specification pointer for this option, or nullptr if none has
/// been set yet.
//------------------------------------------------------------------
const ThreadSpec *
@@ -196,7 +198,6 @@ public:
StoppointCallbackContext *context,
lldb::user_id_t watch_id);
-
struct CommandData
{
CommandData () :
@@ -206,10 +207,8 @@ public:
{
}
- ~CommandData ()
- {
- }
-
+ ~CommandData() = default;
+
StringList user_source;
std::string script_source;
bool stop_on_error;
@@ -223,16 +222,14 @@ public:
{
}
- virtual
- ~CommandBaton ()
+ ~CommandBaton() override
{
delete ((CommandData *)m_data);
- m_data = NULL;
+ m_data = nullptr;
}
- virtual void
- GetDescription (Stream *s, lldb::DescriptionLevel level) const;
-
+ void
+ GetDescription(Stream *s, lldb::DescriptionLevel level) const override;
};
protected:
@@ -252,4 +249,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_WatchpointOptions_h_
+#endif // liblldb_WatchpointOptions_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Address.h b/contrib/llvm/tools/lldb/include/lldb/Core/Address.h
index cfa16c3..0afe55b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Address.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Address.h
@@ -13,6 +13,7 @@
// C Includes
// C++ Includes
#include <atomic>
+
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@@ -108,7 +109,6 @@ public:
{
}
-
//------------------------------------------------------------------
/// Copy constructor
///
@@ -176,6 +176,7 @@ public:
const Address&
operator= (const Address& rhs);
#endif
+
//------------------------------------------------------------------
/// Clear the object's state.
///
@@ -216,7 +217,7 @@ public:
class ModulePointerAndOffsetLessThanFunctionObject
{
public:
- ModulePointerAndOffsetLessThanFunctionObject () {}
+ ModulePointerAndOffsetLessThanFunctionObject() = default;
bool
operator() (const Address& a, const Address& b) const
@@ -326,7 +327,8 @@ public:
/// not loaded.
//------------------------------------------------------------------
lldb::addr_t
- GetOpcodeLoadAddress (Target *target) const;
+ GetOpcodeLoadAddress (Target *target,
+ lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const;
//------------------------------------------------------------------
/// Get the section relative offset value.
@@ -354,7 +356,7 @@ public:
bool
IsSectionOffset() const
{
- return IsValid() && (GetSection().get() != NULL);
+ return IsValid() && (GetSection().get() != nullptr);
}
//------------------------------------------------------------------
@@ -374,7 +376,6 @@ public:
return m_offset != LLDB_INVALID_ADDRESS;
}
-
//------------------------------------------------------------------
/// Get the memory cost of this object.
///
@@ -425,7 +426,9 @@ public:
SetLoadAddress (lldb::addr_t load_addr, Target *target);
bool
- SetOpcodeLoadAddress (lldb::addr_t load_addr, Target *target);
+ SetOpcodeLoadAddress (lldb::addr_t load_addr,
+ Target *target,
+ lldb::AddressClass addr_class = lldb::eAddressClassInvalid);
bool
SetCallableLoadAddress (lldb::addr_t load_addr, Target *target);
@@ -505,6 +508,7 @@ public:
{
m_section_wp.reset();
}
+
//------------------------------------------------------------------
/// Reconstruct a symbol context from an address.
///
@@ -564,10 +568,8 @@ protected:
//------------------------------------------------------------------
bool
SectionWasDeletedPrivate() const;
-
};
-
//----------------------------------------------------------------------
// NOTE: Be careful using this operator. It can correctly compare two
// addresses from the same Module correctly. It can't compare two
@@ -584,12 +586,9 @@ protected:
//----------------------------------------------------------------------
bool operator< (const Address& lhs, const Address& rhs);
bool operator> (const Address& lhs, const Address& rhs);
-
-
-
bool operator== (const Address& lhs, const Address& rhs);
bool operator!= (const Address& lhs, const Address& rhs);
} // namespace lldb_private
-#endif // liblldb_Address_h_
+#endif // liblldb_Address_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/AddressRange.h b/contrib/llvm/tools/lldb/include/lldb/Core/AddressRange.h
index 9d781f3..31e3286 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/AddressRange.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/AddressRange.h
@@ -10,6 +10,10 @@
#ifndef liblldb_AddressRange_h_
#define liblldb_AddressRange_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Address.h"
namespace lldb_private {
@@ -62,7 +66,7 @@ public:
/// @param[in] section_list
/// A list of sections, one of which may contain the \a vaddr.
//------------------------------------------------------------------
- AddressRange (lldb::addr_t file_addr, lldb::addr_t byte_size, const SectionList *section_list = NULL);
+ AddressRange(lldb::addr_t file_addr, lldb::addr_t byte_size, const SectionList *section_list = nullptr);
//------------------------------------------------------------------
/// Construct with a Address object address and byte size.
@@ -281,4 +285,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_AddressRange_h_
+#endif // liblldb_AddressRange_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolver.h b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolver.h
index e5fe276..711cc57 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolver.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolver.h
@@ -54,8 +54,7 @@ public:
AddressResolver ();
- virtual
- ~AddressResolver ();
+ ~AddressResolver () override;
virtual void
ResolveAddress (SearchFilter &filter);
@@ -64,8 +63,8 @@ public:
ResolveAddressInModules (SearchFilter &filter,
ModuleList &modules);
- virtual void
- GetDescription (Stream *s) = 0;
+ void
+ GetDescription (Stream *s) override = 0;
std::vector<AddressRange> &
GetAddressRanges ();
@@ -86,4 +85,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_AddressResolver_h_
+#endif // liblldb_AddressResolver_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverFileLine.h b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverFileLine.h
index ddeb0e0..5b47379 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverFileLine.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverFileLine.h
@@ -30,20 +30,19 @@ public:
uint32_t line_no,
bool check_inlines);
- virtual
- ~AddressResolverFileLine ();
+ ~AddressResolverFileLine () override;
- virtual Searcher::CallbackReturn
+ Searcher::CallbackReturn
SearchCallback (SearchFilter &filter,
SymbolContext &context,
Address *addr,
- bool containing);
+ bool containing) override;
- virtual Searcher::Depth
- GetDepth ();
+ Searcher::Depth
+ GetDepth () override;
- virtual void
- GetDescription (Stream *s);
+ void
+ GetDescription (Stream *s) override;
protected:
FileSpec m_file_spec; // This is the file spec we are looking for.
@@ -56,4 +55,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_AddressResolverFileLine_h_
+#endif // liblldb_AddressResolverFileLine_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverName.h b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverName.h
index afde675..cf792f5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverName.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/AddressResolverName.h
@@ -38,20 +38,19 @@ public:
const char *method,
AddressResolver::MatchType type);
- virtual
- ~AddressResolverName ();
+ ~AddressResolverName () override;
- virtual Searcher::CallbackReturn
+ Searcher::CallbackReturn
SearchCallback (SearchFilter &filter,
SymbolContext &context,
Address *addr,
- bool containing);
+ bool containing) override;
- virtual Searcher::Depth
- GetDepth ();
+ Searcher::Depth
+ GetDepth () override;
- virtual void
- GetDescription (Stream *s);
+ void
+ GetDescription (Stream *s) override;
protected:
ConstString m_func_name;
@@ -65,4 +64,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_AddressResolverName_h_
+#endif // liblldb_AddressResolverName_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ArchSpec.h b/contrib/llvm/tools/lldb/include/lldb/Core/ArchSpec.h
index 0b818a0..13ff436 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ArchSpec.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ArchSpec.h
@@ -65,7 +65,11 @@ public:
eMIPSAse_mips16 = 0x00000400, // MIPS16 ASE
eMIPSAse_micromips = 0x00000800, // MICROMIPS ASE
eMIPSAse_xpa = 0x00001000, // XPA ASE
- eMIPSAse_mask = 0x00001fff
+ eMIPSAse_mask = 0x00001fff,
+ eMIPSABI_O32 = 0x00002000,
+ eMIPSABI_N32 = 0x00004000,
+ eMIPSABI_N64 = 0x00008000,
+ eMIPSABI_mask = 0x000ff000
};
enum Core
@@ -208,7 +212,11 @@ public:
kCore_mips64_last = eCore_mips64r6,
kCore_mips64el_first = eCore_mips64el,
- kCore_mips64el_last = eCore_mips64r6el
+ kCore_mips64el_last = eCore_mips64r6el,
+
+ kCore_mips_first = eCore_mips32,
+ kCore_mips_last = eCore_mips64r6el
+
};
typedef void (* StopInfoOverrideCallbackType)(lldb_private::Thread &thread);
@@ -337,10 +345,28 @@ public:
}
bool
+ TripleVendorIsUnspecifiedUnknown() const
+ {
+ return m_triple.getVendor() == llvm::Triple::UnknownVendor && m_triple.getVendorName().empty();
+ }
+
+ bool
TripleOSWasSpecified() const
{
return !m_triple.getOSName().empty();
}
+
+ bool
+ TripleEnvironmentWasSpecified () const
+ {
+ return !m_triple.getEnvironmentName().empty();
+ }
+
+ bool
+ TripleOSIsUnspecifiedUnknown() const
+ {
+ return m_triple.getOS() == llvm::Triple::UnknownOS && m_triple.getOSName().empty();
+ }
//------------------------------------------------------------------
/// Merges fields from another ArchSpec into this ArchSpec.
@@ -480,6 +506,9 @@ public:
return m_triple;
}
+ void
+ DumpTriple(Stream &s) const;
+
//------------------------------------------------------------------
/// Architecture tripple setter.
///
@@ -564,7 +593,18 @@ public:
//------------------------------------------------------------------
StopInfoOverrideCallbackType
GetStopInfoOverrideCallback () const;
+
+ bool
+ IsFullySpecifiedTriple () const;
+ void
+ PiecewiseTripleCompare (const ArchSpec &other,
+ bool &arch_different,
+ bool &vendor_different,
+ bool &os_different,
+ bool &os_version_different,
+ bool &env_different);
+
uint32_t
GetFlags () const
{
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Broadcaster.h b/contrib/llvm/tools/lldb/include/lldb/Core/Broadcaster.h
index 6d54b1b..8e59a41 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Broadcaster.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Broadcaster.h
@@ -42,7 +42,7 @@ public:
BroadcastEventSpec (const BroadcastEventSpec &rhs);
- ~BroadcastEventSpec() {}
+ ~BroadcastEventSpec() = default;
const ConstString &GetBroadcasterClass() const
{
@@ -89,7 +89,7 @@ public:
BroadcasterManager ();
- ~BroadcasterManager () {}
+ ~BroadcasterManager() = default;
uint32_t
RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec);
@@ -128,7 +128,7 @@ private:
{
}
- ~BroadcasterClassMatches () {}
+ ~BroadcasterClassMatches() = default;
bool operator() (const event_listener_key input) const
{
@@ -147,7 +147,7 @@ private:
{
}
- ~BroadcastEventSpecMatches () {}
+ ~BroadcastEventSpecMatches() = default;
bool operator() (const event_listener_key input) const
{
@@ -168,7 +168,7 @@ private:
{
}
- ~ListenerMatchesAndSharedBits () {}
+ ~ListenerMatchesAndSharedBits() = default;
bool operator() (const event_listener_key input) const
{
@@ -190,7 +190,7 @@ private:
{
}
- ~ListenerMatches() {}
+ ~ListenerMatches() = default;
bool operator () (const event_listener_key input) const
{
@@ -204,7 +204,6 @@ private:
const Listener *m_listener;
};
-
};
//----------------------------------------------------------------------
@@ -286,10 +285,10 @@ public:
BroadcastEventIfUnique (lldb::EventSP &event_sp);
void
- BroadcastEvent (uint32_t event_type, EventData *event_data = NULL);
+ BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr);
void
- BroadcastEventIfUnique (uint32_t event_type, EventData *event_data = NULL);
+ BroadcastEventIfUnique(uint32_t event_type, EventData *event_data = nullptr);
void
Clear();
@@ -332,7 +331,6 @@ public:
const ConstString &
GetBroadcasterName ();
-
//------------------------------------------------------------------
/// Get the event name(s) for one or more event bits.
///
@@ -364,10 +362,10 @@ public:
const char *
GetEventName (uint32_t event_mask) const
{
- event_names_map::const_iterator pos = m_event_names.find (event_mask);
+ const auto pos = m_event_names.find (event_mask);
if (pos != m_event_names.end())
return pos->second.c_str();
- return NULL;
+ return nullptr;
}
bool
@@ -437,8 +435,6 @@ public:
BroadcasterManager *GetManager();
protected:
-
-
void
PrivateBroadcastEvent (lldb::EventSP &event_sp, bool unique);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ClangForward.h b/contrib/llvm/tools/lldb/include/lldb/Core/ClangForward.h
index 6c627c2..80abc15 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ClangForward.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ClangForward.h
@@ -132,6 +132,8 @@ namespace clang
namespace llvm
{
+ class APInt;
+ class APSInt;
class LLVMContext;
class ExecutionEngine;
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Communication.h b/contrib/llvm/tools/lldb/include/lldb/Core/Communication.h
index 7924ed2..d29aaca 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Communication.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Communication.h
@@ -100,7 +100,6 @@ public:
typedef void (*ReadThreadBytesReceived) (void *baton, const void *src, size_t src_len);
-
//------------------------------------------------------------------
/// Construct the Communication object with the specified name for
/// the Broadcaster that this object inherits from.
@@ -118,8 +117,7 @@ public:
///
/// The destructor is virtual since this class gets subclassed.
//------------------------------------------------------------------
- virtual
- ~Communication();
+ ~Communication() override;
void
Clear ();
@@ -157,7 +155,7 @@ public:
/// @see bool Connection::Disconnect ();
//------------------------------------------------------------------
lldb::ConnectionStatus
- Disconnect (Error *error_ptr = NULL);
+ Disconnect(Error *error_ptr = nullptr);
//------------------------------------------------------------------
/// Check if the connection is valid.
@@ -177,6 +175,7 @@ public:
{
return m_connection_sp.get();
}
+
//------------------------------------------------------------------
/// Read bytes from the current connection.
///
@@ -278,7 +277,7 @@ public:
/// @see void Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast);
//------------------------------------------------------------------
virtual bool
- StartReadThread (Error *error_ptr = NULL);
+ StartReadThread(Error *error_ptr = nullptr);
//------------------------------------------------------------------
/// Stops the read thread by cancelling it.
@@ -288,10 +287,10 @@ public:
/// false otherwise.
//------------------------------------------------------------------
virtual bool
- StopReadThread (Error *error_ptr = NULL);
+ StopReadThread(Error *error_ptr = nullptr);
virtual bool
- JoinReadThread (Error *error_ptr = NULL);
+ JoinReadThread(Error *error_ptr = nullptr);
//------------------------------------------------------------------
/// Checks if there is a currently running read thread.
///
@@ -323,7 +322,6 @@ public:
SetReadThreadBytesReceivedCallback (ReadThreadBytesReceived callback,
void *callback_baton);
-
//------------------------------------------------------------------
/// Wait for the read thread to process all outstanding data.
///
@@ -350,18 +348,11 @@ public:
static ConstString &GetStaticBroadcasterClass ();
- virtual ConstString &GetBroadcasterClass() const
+ ConstString &GetBroadcasterClass() const override
{
return GetStaticBroadcasterClass();
}
-private:
- //------------------------------------------------------------------
- // For Communication only
- //------------------------------------------------------------------
- DISALLOW_COPY_AND_ASSIGN (Communication);
-
-
protected:
lldb::ConnectionSP m_connection_sp; ///< The connection that is current in use by this communications class.
HostThread m_read_thread; ///< The read thread handle in case we need to cancel the thread.
@@ -381,6 +372,7 @@ protected:
uint32_t timeout_usec,
lldb::ConnectionStatus &status,
Error *error_ptr);
+
//------------------------------------------------------------------
/// Append new bytes that get read from the read thread into the
/// internal object byte cache. This will cause a \b
@@ -424,8 +416,11 @@ protected:
//------------------------------------------------------------------
size_t
GetCachedBytes (void *dst, size_t dst_len);
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (Communication);
};
} // namespace lldb_private
-#endif // liblldb_Communication_h_
+#endif // liblldb_Communication_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Connection.h b/contrib/llvm/tools/lldb/include/lldb/Core/Connection.h
index 121395c..4b3024e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Connection.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Connection.h
@@ -58,7 +58,7 @@ public:
///
/// @param[out] error_ptr
/// A pointer to an error object that should be given an
- /// approriate error value if this method returns false. This
+ /// appropriate error value if this method returns false. This
/// value can be NULL if the error value should be ignored.
///
/// @return
@@ -77,7 +77,7 @@ public:
///
/// @param[out] error_ptr
/// A pointer to an error object that should be given an
- /// approriate error value if this method returns false. This
+ /// appropriate error value if this method returns false. This
/// value can be NULL if the error value should be ignored.
///
/// @return
@@ -115,12 +115,12 @@ public:
/// The number of microseconds to wait for the data.
///
/// @param[out] status
- /// On return, indicates whether the call was sucessful or terminated
+ /// On return, indicates whether the call was successful or terminated
/// due to some error condition.
///
/// @param[out] error_ptr
/// A pointer to an error object that should be given an
- /// approriate error value if this method returns zero. This
+ /// appropriate error value if this method returns zero. This
/// value can be NULL if the error value should be ignored.
///
/// @return
@@ -151,7 +151,7 @@ public:
///
/// @param[out] error_ptr
/// A pointer to an error object that should be given an
- /// approriate error value if this method returns zero. This
+ /// appropriate error value if this method returns zero. This
/// value can be NULL if the error value should be ignored.
///
/// @return
@@ -182,7 +182,7 @@ public:
/// operation).
///
/// @return
- /// Returns true is the interrupt request was sucessful.
+ /// Returns true is the interrupt request was successful.
//------------------------------------------------------------------
virtual bool
InterruptRead() = 0;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ConnectionSharedMemory.h b/contrib/llvm/tools/lldb/include/lldb/Core/ConnectionSharedMemory.h
index 48e6214..d055369 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ConnectionSharedMemory.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ConnectionSharedMemory.h
@@ -28,33 +28,32 @@ public:
ConnectionSharedMemory ();
- virtual
- ~ConnectionSharedMemory ();
+ ~ConnectionSharedMemory () override;
- virtual bool
- IsConnected () const;
+ bool
+ IsConnected () const override;
virtual lldb::ConnectionStatus
BytesAvailable (uint32_t timeout_usec, Error *error_ptr);
- virtual lldb::ConnectionStatus
- Connect (const char *s, Error *error_ptr);
+ lldb::ConnectionStatus
+ Connect (const char *s, Error *error_ptr) override;
- virtual lldb::ConnectionStatus
- Disconnect (Error *error_ptr);
+ lldb::ConnectionStatus
+ Disconnect (Error *error_ptr) override;
- virtual size_t
+ size_t
Read (void *dst,
size_t dst_len,
uint32_t timeout_usec,
lldb::ConnectionStatus &status,
- Error *error_ptr);
+ Error *error_ptr) override;
- virtual size_t
- Write (const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr);
+ size_t
+ Write (const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr) override;
- virtual std::string
- GetURI();
+ std::string
+ GetURI() override;
lldb::ConnectionStatus
Open (bool create, const char *name, size_t size, Error *error_ptr);
@@ -64,10 +63,12 @@ protected:
std::string m_name;
int m_fd; // One buffer that contains all we need
DataBufferMemoryMap m_mmap;
+
private:
+
DISALLOW_COPY_AND_ASSIGN (ConnectionSharedMemory);
};
} // namespace lldb_private
-#endif // liblldb_ConnectionSharedMemory_h_
+#endif // liblldb_ConnectionSharedMemory_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ConstString.h b/contrib/llvm/tools/lldb/include/lldb/Core/ConstString.h
index cfe8ea2..6e234da 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ConstString.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ConstString.h
@@ -9,13 +9,14 @@
#ifndef liblldb_ConstString_h_
#define liblldb_ConstString_h_
-#if defined(__cplusplus)
-#include <assert.h>
-
-#include "lldb/lldb-private.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
+// Project includes
+#include "lldb/lldb-private.h"
namespace lldb_private {
@@ -41,12 +42,11 @@ public:
///
/// Initializes the string to an empty string.
//------------------------------------------------------------------
- ConstString ():
- m_string (NULL)
+ ConstString():
+ m_string(nullptr)
{
}
-
//------------------------------------------------------------------
/// Copy constructor
///
@@ -105,10 +105,7 @@ public:
/// Since constant string values are currently not reference counted,
/// there isn't much to do here.
//------------------------------------------------------------------
- ~ConstString ()
- {
- }
-
+ ~ConstString() = default;
//----------------------------------------------------------------------
/// C string equality binary predicate function object for ConstString
@@ -224,18 +221,16 @@ public:
/// Get the value of the contained string as a NULL terminated C
/// string value.
///
- /// If \a value_if_empty is NULL, then NULL will be returned.
+ /// If \a value_if_empty is nullptr, then nullptr will be returned.
///
/// @return
/// Returns \a value_if_empty if the string is empty, otherwise
/// the C string value contained in this object.
//------------------------------------------------------------------
const char *
- AsCString(const char *value_if_empty = NULL) const
+ AsCString(const char *value_if_empty = nullptr) const
{
- if (IsEmpty())
- return value_if_empty;
- return m_string;
+ return (IsEmpty() ? value_if_empty : m_string);
}
//------------------------------------------------------------------
@@ -256,12 +251,12 @@ public:
///
/// Get the value of the contained string as a NULL terminated C
/// string value. Similar to the ConstString::AsCString() function,
- /// yet this function will always return NULL if the string is not
+ /// yet this function will always return nullptr if the string is not
/// valid. So this function is a direct accessor to the string
/// pointer value.
///
/// @return
- /// Returns NULL the string is invalid, otherwise the C string
+ /// Returns nullptr the string is invalid, otherwise the C string
/// value contained in this object.
//------------------------------------------------------------------
const char *
@@ -270,7 +265,6 @@ public:
return m_string;
}
-
//------------------------------------------------------------------
/// Get the length in bytes of string value.
///
@@ -293,7 +287,7 @@ public:
void
Clear ()
{
- m_string = NULL;
+ m_string = nullptr;
}
//------------------------------------------------------------------
@@ -326,18 +320,18 @@ public:
///
/// Dump the string value to the stream \a s. If the contained string
/// is empty, print \a value_if_empty to the stream instead. If
- /// \a value_if_empty is NULL, then nothing will be dumped to the
+ /// \a value_if_empty is nullptr, then nothing will be dumped to the
/// stream.
///
/// @param[in] s
/// The stream that will be used to dump the object description.
///
/// @param[in] value_if_empty
- /// The value to dump if the string is empty. If NULL, nothing
+ /// The value to dump if the string is empty. If nullptr, nothing
/// will be output to the stream.
//------------------------------------------------------------------
void
- Dump (Stream *s, const char *value_if_empty = NULL) const;
+ Dump(Stream *s, const char *value_if_empty = nullptr) const;
//------------------------------------------------------------------
/// Dump the object debug description to a stream.
@@ -358,7 +352,7 @@ public:
bool
IsEmpty () const
{
- return m_string == NULL || m_string[0] == '\0';
+ return m_string == nullptr || m_string[0] == '\0';
}
//------------------------------------------------------------------
@@ -473,7 +467,6 @@ public:
{
return sizeof(ConstString);
}
-
//------------------------------------------------------------------
/// Get the size in bytes of the current global string pool.
@@ -503,5 +496,4 @@ Stream& operator << (Stream& s, const ConstString& str);
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif // liblldb_ConstString_h_
+#endif // liblldb_ConstString_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/DataBufferHeap.h b/contrib/llvm/tools/lldb/include/lldb/Core/DataBufferHeap.h
index ad73fab..d379c4c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/DataBufferHeap.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/DataBufferHeap.h
@@ -9,7 +9,6 @@
#ifndef liblldb_DataBufferHeap_h_
#define liblldb_DataBufferHeap_h_
-#if defined(__cplusplus)
#include <vector>
@@ -69,26 +68,25 @@ public:
/// Virtual destructor since this class inherits from a pure virtual
/// base class #DataBuffer.
//------------------------------------------------------------------
- virtual
- ~DataBufferHeap();
+ ~DataBufferHeap() override;
//------------------------------------------------------------------
/// @copydoc DataBuffer::GetBytes()
//------------------------------------------------------------------
- virtual uint8_t *
- GetBytes ();
+ uint8_t *
+ GetBytes () override;
//------------------------------------------------------------------
/// @copydoc DataBuffer::GetBytes() const
//------------------------------------------------------------------
- virtual const uint8_t *
- GetBytes () const;
+ const uint8_t *
+ GetBytes () const override;
//------------------------------------------------------------------
/// @copydoc DataBuffer::GetByteSize() const
//------------------------------------------------------------------
- virtual lldb::offset_t
- GetByteSize () const;
+ lldb::offset_t
+ GetByteSize () const override;
//------------------------------------------------------------------
/// Set the number of bytes in the data buffer.
@@ -138,5 +136,4 @@ private:
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif // liblldb_DataBufferHeap_h_
+#endif // liblldb_DataBufferHeap_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/DataBufferMemoryMap.h b/contrib/llvm/tools/lldb/include/lldb/Core/DataBufferMemoryMap.h
index 944b975..9479d4e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/DataBufferMemoryMap.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/DataBufferMemoryMap.h
@@ -9,8 +9,6 @@
#ifndef liblldb_DataBufferMemoryMap_h_
#define liblldb_DataBufferMemoryMap_h_
-#if defined(__cplusplus)
-
#include "lldb/lldb-private.h"
#include "lldb/Core/DataBuffer.h"
@@ -45,8 +43,7 @@ public:
/// Virtual destructor since this class inherits from a pure virtual
/// base class #DataBuffer.
//------------------------------------------------------------------
- virtual
- ~DataBufferMemoryMap ();
+ ~DataBufferMemoryMap () override;
//------------------------------------------------------------------
/// Reverts this object to an empty state by unmapping any memory
@@ -58,20 +55,20 @@ public:
//------------------------------------------------------------------
/// @copydoc DataBuffer::GetBytes()
//------------------------------------------------------------------
- virtual uint8_t *
- GetBytes ();
+ uint8_t *
+ GetBytes () override;
//------------------------------------------------------------------
/// @copydoc DataBuffer::GetBytes() const
//------------------------------------------------------------------
- virtual const uint8_t *
- GetBytes () const;
+ const uint8_t *
+ GetBytes () const override;
//------------------------------------------------------------------
/// @copydoc DataBuffer::GetByteSize() const
//------------------------------------------------------------------
- virtual lldb::offset_t
- GetByteSize () const;
+ lldb::offset_t
+ GetByteSize () const override;
//------------------------------------------------------------------
/// Error get accessor.
@@ -161,5 +158,4 @@ private:
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif // liblldb_DataBufferMemoryMap_h_
+#endif // liblldb_DataBufferMemoryMap_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/DataEncoder.h b/contrib/llvm/tools/lldb/include/lldb/Core/DataEncoder.h
index 7889f41..8b4727e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/DataEncoder.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/DataEncoder.h
@@ -252,7 +252,7 @@ public:
/// The offset in bytes into the contained data at which to
/// start encoding.
///
- /// @param[int] src
+ /// @param[in] src
/// The buffer that contains the bytes to encode.
///
/// @param[in] src_len
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/DataExtractor.h b/contrib/llvm/tools/lldb/include/lldb/Core/DataExtractor.h
index e61189b..d5cb5e8 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/DataExtractor.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/DataExtractor.h
@@ -9,17 +9,18 @@
#ifndef liblldb_DataExtractor_h_
#define liblldb_DataExtractor_h_
-#if defined (__cplusplus)
-
-
-#include "lldb/lldb-private.h"
-
-#include "llvm/ADT/SmallVector.h"
+// C Includes
#include <limits.h>
#include <stdint.h>
#include <string.h>
-#include <vector>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/ADT/SmallVector.h"
+
+// Project includes
+#include "lldb/lldb-private.h"
namespace lldb_private {
@@ -64,6 +65,7 @@ public:
size_t src_len,
uint32_t bytes_per_line,
lldb::addr_t base_addr); // Pass LLDB_INVALID_ADDRESS to not show address at start of line
+
//------------------------------------------------------------------
/// Default constructor.
///
@@ -146,6 +148,7 @@ public:
DataExtractor (const DataExtractor& data, lldb::offset_t offset, lldb::offset_t length, uint32_t target_byte_size = 1);
DataExtractor (const DataExtractor& rhs);
+
//------------------------------------------------------------------
/// Assignment operator.
///
@@ -183,14 +186,14 @@ public:
//------------------------------------------------------------------
/// Dumps the binary data as \a type objects to stream \a s (or to
- /// Log() if \a s is NULL) starting \a offset bytes into the data
+ /// Log() if \a s is nullptr) starting \a offset bytes into the data
/// and stopping after dumping \a length bytes. The offset into the
/// data is displayed at the beginning of each line and can be
/// offset by base address \a base_addr. \a num_per_line objects
/// will be displayed on each line.
///
/// @param[in] s
- /// The stream to dump the output to. If NULL the output will
+ /// The stream to dump the output to. If nullptr the output will
/// be dumped to Log().
///
/// @param[in] offset
@@ -212,19 +215,19 @@ public:
///
/// @param[in] type_format
/// The optional format to use for the \a type objects. If this
- /// is NULL, the default format for the \a type will be used.
+ /// is nullptr, the default format for the \a type will be used.
///
/// @return
/// The offset at which dumping ended.
//------------------------------------------------------------------
lldb::offset_t
- PutToLog (Log *log,
- lldb::offset_t offset,
- lldb::offset_t length,
- uint64_t base_addr,
- uint32_t num_per_line,
- Type type,
- const char *type_format = NULL) const;
+ PutToLog(Log *log,
+ lldb::offset_t offset,
+ lldb::offset_t length,
+ uint64_t base_addr,
+ uint32_t num_per_line,
+ Type type,
+ const char *type_format = nullptr) const;
//------------------------------------------------------------------
/// Dumps \a item_count objects into the stream \a s.
@@ -241,7 +244,7 @@ public:
/// item_bit_size and \a item_bit_offset values.
///
/// @param[in] s
- /// The stream to dump the output to. This value can not be NULL.
+ /// The stream to dump the output to. This value can not be nullptr.
///
/// @param[in] offset
/// The offset into the data at which to start dumping.
@@ -287,25 +290,25 @@ public:
/// The offset at which dumping ended.
//------------------------------------------------------------------
lldb::offset_t
- Dump (Stream *s,
- lldb::offset_t offset,
- lldb::Format item_format,
- size_t item_byte_size,
- size_t item_count,
- size_t num_per_line,
- uint64_t base_addr,
- uint32_t item_bit_size,
- uint32_t item_bit_offset,
- ExecutionContextScope *exe_scope = NULL) const;
+ Dump(Stream *s,
+ lldb::offset_t offset,
+ lldb::Format item_format,
+ size_t item_byte_size,
+ size_t item_count,
+ size_t num_per_line,
+ uint64_t base_addr,
+ uint32_t item_bit_size,
+ uint32_t item_bit_offset,
+ ExecutionContextScope *exe_scope = nullptr) const;
//------------------------------------------------------------------
/// Dump a UUID value at \a offset.
///
/// Dump a UUID starting at \a offset bytes into this object's data.
- /// If the stream \a s is NULL, the output will be sent to Log().
+ /// If the stream \a s is nullptr, the output will be sent to Log().
///
/// @param[in] s
- /// The stream to dump the output to. If NULL the output will
+ /// The stream to dump the output to. If nullptr the output will
/// be dumped to Log().
///
/// @param[in] offset
@@ -418,7 +421,7 @@ public:
/// A pointer to the C string value in the data. If the offset
/// pointed to by \a offset_ptr is out of bounds, or if the
/// offset plus the length of the C string is out of bounds,
- /// NULL will be returned.
+ /// nullptr will be returned.
//------------------------------------------------------------------
const char *
GetCStr (lldb::offset_t *offset_ptr) const;
@@ -443,7 +446,7 @@ public:
/// A pointer to the C string value in the data. If the offset
/// pointed to by \a offset_ptr is out of bounds, or if the
/// offset plus the length of the field is out of bounds, or if
- /// the field does not contain a NULL terminator byte, NULL will
+ /// the field does not contain a NULL terminator byte, nullptr will
/// be returned.
const char *
GetCStr (lldb::offset_t *offset_ptr, lldb::offset_t len) const;
@@ -454,7 +457,7 @@ public:
/// Returns a pointer to a bytes in this object's data at the offset
/// pointed to by \a offset_ptr. If \a length is zero or too large,
/// then the offset pointed to by \a offset_ptr will not be updated
- /// and NULL will be returned.
+ /// and nullptr will be returned.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
@@ -469,7 +472,7 @@ public:
///
/// @return
/// A pointer to the bytes in this object's data if the offset
- /// and length are valid, or NULL otherwise.
+ /// and length are valid, or nullptr otherwise.
//------------------------------------------------------------------
const void*
GetData (lldb::offset_t *offset_ptr, lldb::offset_t length) const
@@ -552,7 +555,7 @@ public:
///
/// @return
/// Returns a pointer to the next byte contained in this
- /// object's data, or NULL of there is no data in this object.
+ /// object's data, or nullptr of there is no data in this object.
//------------------------------------------------------------------
const uint8_t *
GetDataEnd () const
@@ -578,7 +581,7 @@ public:
///
/// @return
/// Returns a pointer to the first byte contained in this
- /// object's data, or NULL of there is no data in this object.
+ /// object's data, or nullptr of there is no data in this object.
//------------------------------------------------------------------
const uint8_t *
GetDataStart () const
@@ -586,7 +589,6 @@ public:
return m_start;
}
-
//------------------------------------------------------------------
/// Extract a float from \a *offset_ptr.
///
@@ -908,7 +910,7 @@ public:
///
/// @return
/// \a dst if all values were properly extracted and copied,
- /// NULL otherwise.
+ /// nullptr otherwise.
//------------------------------------------------------------------
void *
GetU8 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const;
@@ -955,7 +957,7 @@ public:
///
/// @return
/// \a dst if all values were properly extracted and copied,
- /// NULL otherwise.
+ /// nullptr otherwise.
//------------------------------------------------------------------
void *
GetU16 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const;
@@ -1002,7 +1004,7 @@ public:
///
/// @return
/// \a dst if all values were properly extracted and copied,
- /// NULL otherwise.
+ /// nullptr otherwise.
//------------------------------------------------------------------
void *
GetU32 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const;
@@ -1049,7 +1051,7 @@ public:
///
/// @return
/// \a dst if all values were properly extracted and copied,
- /// NULL otherwise.
+ /// nullptr otherwise.
//------------------------------------------------------------------
void *
GetU64 ( lldb::offset_t *offset_ptr, void *dst, uint32_t count) const;
@@ -1113,8 +1115,8 @@ public:
/// An offset into the data.
///
/// @return
- /// A non-NULL C string pointer if \a offset is a valid offset,
- /// NULL otherwise.
+ /// A non-nullptr C string pointer if \a offset is a valid offset,
+ /// nullptr otherwise.
//------------------------------------------------------------------
const char *
PeekCStr (lldb::offset_t offset) const;
@@ -1126,8 +1128,8 @@ public:
/// there are \a length bytes available starting at \a offset.
///
/// @return
- /// A non-NULL data pointer if \a offset is a valid offset and
- /// there are \a length bytes available at that offset, NULL
+ /// A non-nullptr data pointer if \a offset is a valid offset and
+ /// there are \a length bytes available at that offset, nullptr
/// otherwise.
//------------------------------------------------------------------
const uint8_t*
@@ -1135,7 +1137,7 @@ public:
{
if (length > 0 && ValidOffsetForDataOfSize(offset, length))
return m_start + offset;
- return NULL;
+ return nullptr;
}
//------------------------------------------------------------------
@@ -1150,6 +1152,9 @@ public:
void
SetAddressByteSize (uint32_t addr_size)
{
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert (addr_size == 4 || addr_size == 8);
+#endif
m_addr_size = addr_size;
}
@@ -1159,7 +1164,7 @@ public:
/// Use data that is owned by the caller when extracting values.
/// The data must stay around as long as this object, or any object
/// that copies a subset of this object's data, is valid. If \a
- /// bytes is NULL, or \a length is zero, this object will contain
+ /// bytes is nullptr, or \a length is zero, this object will contain
/// no data.
///
/// @param[in] bytes
@@ -1317,10 +1322,8 @@ public:
void
Checksum (llvm::SmallVectorImpl<uint8_t> &dest,
uint64_t max_data = 0);
-
protected:
-
//------------------------------------------------------------------
// Member variables
//------------------------------------------------------------------
@@ -1334,5 +1337,4 @@ protected:
} // namespace lldb_private
-#endif // #if defined (__cplusplus)
-#endif // #ifndef liblldb_DataExtractor_h_
+#endif // liblldb_DataExtractor_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Debugger.h b/contrib/llvm/tools/lldb/include/lldb/Core/Debugger.h
index 0d9b90c..4ca648c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Debugger.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Debugger.h
@@ -9,11 +9,17 @@
#ifndef liblldb_Debugger_h_
#define liblldb_Debugger_h_
-#if defined(__cplusplus)
-
+// C Includes
#include <stdint.h>
+// C++ Includes
+#include <memory>
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/FormatEntity.h"
@@ -32,8 +38,8 @@ namespace llvm
namespace sys
{
class DynamicLibrary;
-}
-}
+} // namespace sys
+} // namespace llvm
namespace lldb_private {
@@ -44,7 +50,6 @@ namespace lldb_private {
/// Provides a global root objects for the debugger core.
//----------------------------------------------------------------------
-
class Debugger :
public std::enable_shared_from_this<Debugger>,
public UserID,
@@ -54,9 +59,10 @@ class Debugger :
friend class SourceManager; // For GetSourceFileCache.
public:
+ ~Debugger() override;
static lldb::DebuggerSP
- CreateInstance (lldb::LogOutputCallback log_callback = NULL, void *baton = NULL);
+ CreateInstance(lldb::LogOutputCallback log_callback = nullptr, void *baton = nullptr);
static lldb::TargetSP
FindTargetWithProcessID (lldb::pid_t pid);
@@ -79,9 +85,26 @@ public:
static void
Destroy (lldb::DebuggerSP &debugger_sp);
- virtual
- ~Debugger ();
+ static lldb::DebuggerSP
+ FindDebuggerWithID(lldb::user_id_t id);
+ static lldb::DebuggerSP
+ FindDebuggerWithInstanceName(const ConstString &instance_name);
+
+ static size_t
+ GetNumDebuggers();
+
+ static lldb::DebuggerSP
+ GetDebuggerAtIndex(size_t index);
+
+ static bool
+ FormatDisassemblerAddress(const FormatEntity::Entry *format,
+ const SymbolContext *sc,
+ const SymbolContext *prev_sc,
+ const ExecutionContext *exe_ctx,
+ const Address *addr,
+ Stream &s);
+
void Clear();
bool
@@ -108,8 +131,6 @@ public:
return m_error_file_sp;
}
-
-
void
SetInputFileHandle (FILE *fh, bool tranfer_ownership);
@@ -209,6 +230,10 @@ public:
bool
IsTopIOHandler (const lldb::IOHandlerSP& reader_sp);
+
+ bool
+ CheckTopIOHandlerTypes (IOHandler::Type top_type,
+ IOHandler::Type second_top_type);
void
PrintAsync (const char *s, size_t len, bool is_stdout);
@@ -222,26 +247,6 @@ public:
const char *
GetIOHandlerHelpPrologue();
- static lldb::DebuggerSP
- FindDebuggerWithID (lldb::user_id_t id);
-
- static lldb::DebuggerSP
- FindDebuggerWithInstanceName (const ConstString &instance_name);
-
- static size_t
- GetNumDebuggers();
-
- static lldb::DebuggerSP
- GetDebuggerAtIndex (size_t index);
-
- static bool
- FormatDisassemblerAddress (const FormatEntity::Entry *format,
- const SymbolContext *sc,
- const SymbolContext *prev_sc,
- const ExecutionContext *exe_ctx,
- const Address *addr,
- Stream &s);
-
void
ClearIOHandlers ();
@@ -257,22 +262,22 @@ public:
void
SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton);
-
//----------------------------------------------------------------------
// Properties Functions
//----------------------------------------------------------------------
enum StopDisassemblyType
{
eStopDisassemblyTypeNever = 0,
+ eStopDisassemblyTypeNoDebugInfo,
eStopDisassemblyTypeNoSource,
eStopDisassemblyTypeAlways
};
- virtual Error
- SetPropertyValue (const ExecutionContext *exe_ctx,
- VarSetOperationType op,
- const char *property_path,
- const char *value);
+ Error
+ SetPropertyValue(const ExecutionContext *exe_ctx,
+ VarSetOperationType op,
+ const char *property_path,
+ const char *value) override;
bool
GetAutoConfirm () const;
@@ -329,6 +334,24 @@ public:
GetAutoOneLineSummaries () const;
bool
+ GetAutoIndent () const;
+
+ bool
+ SetAutoIndent (bool b);
+
+ bool
+ GetPrintDecls () const;
+
+ bool
+ SetPrintDecls (bool b);
+
+ uint32_t
+ GetTabSize () const;
+
+ bool
+ SetTabSize (uint32_t tab_size);
+
+ bool
GetEscapeNonPrintables () const;
bool
@@ -360,6 +383,9 @@ public:
{
return m_event_handler_thread.IsJoinable();
}
+
+ Error
+ RunREPL (lldb::LanguageType language, const char *repl_options);
// This is for use in the command interpreter, when you either want the selected target, or if no target
// is present you want to prime the dummy target with entities that will be copied over to new targets.
@@ -367,8 +393,8 @@ public:
Target *GetDummyTarget();
protected:
-
friend class CommandInterpreter;
+ friend class REPL;
bool
StartEventHandlerThread();
@@ -380,11 +406,17 @@ protected:
EventHandlerThread (lldb::thread_arg_t arg);
bool
+ HasIOHandlerThread();
+
+ bool
StartIOHandlerThread();
void
StopIOHandlerThread();
+ void
+ JoinIOHandlerThread();
+
static lldb::thread_result_t
IOHandlerThread (lldb::thread_arg_t arg);
@@ -450,16 +482,13 @@ protected:
};
private:
-
// Use Debugger::CreateInstance() to get a shared pointer to a new
// debugger object
Debugger (lldb::LogOutputCallback m_log_callback, void *baton);
DISALLOW_COPY_AND_ASSIGN (Debugger);
-
};
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif // liblldb_Debugger_h_
+#endif // liblldb_Debugger_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Disassembler.h b/contrib/llvm/tools/lldb/include/lldb/Core/Disassembler.h
index e08e2de..bfa99de 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Disassembler.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Disassembler.h
@@ -48,6 +48,7 @@ public:
CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx);
return m_opcode_name.c_str();
}
+
const char *
GetOperands (const ExecutionContext* exe_ctx)
{
@@ -127,7 +128,6 @@ public:
/// so this method can properly align the instruction opcodes.
/// May be 0 to indicate no indentation/alignment of the opcodes.
//------------------------------------------------------------------
-
virtual void
Dump (Stream *s,
uint32_t max_opcode_byte_size,
@@ -142,6 +142,9 @@ public:
virtual bool
DoesBranch () = 0;
+ virtual bool
+ HasDelaySlot ();
+
virtual size_t
Decode (const Disassembler &disassembler,
const DataExtractor& data,
@@ -208,7 +211,6 @@ protected:
}
};
-
class InstructionList
{
public:
@@ -260,30 +262,32 @@ public:
PseudoInstruction ();
- virtual
- ~PseudoInstruction ();
+ ~PseudoInstruction() override;
- virtual bool
- DoesBranch ();
+ bool
+ DoesBranch() override;
- virtual void
- CalculateMnemonicOperandsAndComment (const ExecutionContext* exe_ctx)
+ bool
+ HasDelaySlot() override;
+
+ void
+ CalculateMnemonicOperandsAndComment(const ExecutionContext* exe_ctx) override
{
// TODO: fill this in and put opcode name into Instruction::m_opcode_name,
// mnemonic into Instruction::m_mnemonics, and any comment into
// Instruction::m_comment
}
- virtual size_t
- Decode (const Disassembler &disassembler,
- const DataExtractor &data,
- lldb::offset_t data_offset);
+ size_t
+ Decode(const Disassembler &disassembler,
+ const DataExtractor &data,
+ lldb::offset_t data_offset) override;
void
SetOpcode (size_t opcode_size, void *opcode_data);
- virtual void
- SetDescription (const char *description);
+ void
+ SetDescription(const char *description) override;
protected:
std::string m_description;
@@ -405,7 +409,7 @@ public:
// Constructors and Destructors
//------------------------------------------------------------------
Disassembler(const ArchSpec &arch, const char *flavor);
- virtual ~Disassembler();
+ ~Disassembler() override;
typedef const char * (*SummaryCallback)(const Instruction& inst, ExecutionContext *exe_context, void *user_data);
@@ -478,4 +482,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_Disassembler_h_
+#endif // liblldb_Disassembler_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/EmulateInstruction.h b/contrib/llvm/tools/lldb/include/lldb/Core/EmulateInstruction.h
index 774d809..c5e6002 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/EmulateInstruction.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/EmulateInstruction.h
@@ -19,6 +19,8 @@
#include "lldb/Core/Opcode.h"
#include "lldb/Core/RegisterValue.h"
+namespace lldb_private {
+
//----------------------------------------------------------------------
/// @class EmulateInstruction EmulateInstruction.h "lldb/Core/EmulateInstruction.h"
/// @brief A class that allows emulation of CPU opcodes.
@@ -79,8 +81,6 @@
/// and emulating the instruction is just a bonus.
//----------------------------------------------------------------------
-namespace lldb_private {
-
class EmulateInstruction :
public PluginInterface
{
@@ -233,7 +233,6 @@ public:
} ISAAndImmediateSigned;
uint32_t isa;
-
} info;
Context () :
@@ -387,9 +386,8 @@ public:
EmulateInstruction (const ArchSpec &arch);
- virtual ~EmulateInstruction()
- {
- }
+ ~EmulateInstruction() override = default;
+
//----------------------------------------------------------------------
// Mandatory overrides
//----------------------------------------------------------------------
@@ -404,7 +402,10 @@ public:
virtual bool
EvaluateInstruction (uint32_t evaluate_options) = 0;
-
+
+ virtual bool
+ IsInstructionConditional() { return false; }
+
virtual bool
TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) = 0;
@@ -527,7 +528,6 @@ public:
return m_arch;
}
-
static size_t
ReadMemoryFrame (EmulateInstruction *instruction,
void *baton,
@@ -628,7 +628,6 @@ protected:
lldb::addr_t m_addr;
Opcode m_opcode;
-
private:
//------------------------------------------------------------------
// For EmulateInstruction only
@@ -636,6 +635,6 @@ private:
DISALLOW_COPY_AND_ASSIGN (EmulateInstruction);
};
-} // namespace lldb_private
+} // namespace lldb_private
-#endif // lldb_EmulateInstruction_h_
+#endif // lldb_EmulateInstruction_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Event.h b/contrib/llvm/tools/lldb/include/lldb/Core/Event.h
index 1c3eec0..e8867c0e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Event.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Event.h
@@ -12,7 +12,7 @@
// C Includes
// C++ Includes
-#include <list>
+#include <memory>
#include <string>
// Other libraries and framework includes
@@ -49,7 +49,6 @@ private:
}
DISALLOW_COPY_AND_ASSIGN (EventData);
-
};
//----------------------------------------------------------------------
@@ -67,17 +66,16 @@ public:
EventDataBytes (const void *src, size_t src_len);
- virtual
- ~EventDataBytes();
+ ~EventDataBytes() override;
//------------------------------------------------------------------
// Member functions
//------------------------------------------------------------------
- virtual const ConstString &
- GetFlavor () const;
+ const ConstString &
+ GetFlavor () const override;
- virtual void
- Dump (Stream *s) const;
+ void
+ Dump (Stream *s) const override;
const void *
GetBytes() const;
@@ -113,7 +111,6 @@ private:
std::string m_bytes;
DISALLOW_COPY_AND_ASSIGN (EventDataBytes);
-
};
//----------------------------------------------------------------------
@@ -126,10 +123,9 @@ class Event
friend class EventData;
public:
+ Event(Broadcaster *broadcaster, uint32_t event_type, EventData *data = nullptr);
- Event (Broadcaster *broadcaster, uint32_t event_type, EventData *data = NULL);
-
- Event (uint32_t event_type, EventData *data = NULL);
+ Event(uint32_t event_type, EventData *data = nullptr);
~Event ();
@@ -184,7 +180,6 @@ public:
m_data_ap.reset();
}
-
private:
// This is only called by Listener when it pops an event off the queue for
// the listener. It calls the Event Data's DoOnRemoval() method, which is
@@ -202,7 +197,6 @@ private:
m_broadcaster = broadcaster;
}
-
Broadcaster * m_broadcaster; // The broadcaster that sent this event
uint32_t m_type; // The bit describing this event
std::unique_ptr<EventData> m_data_ap; // User specific data for this event
@@ -214,4 +208,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_Event_h_
+#endif // liblldb_Event_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/FileLineResolver.h b/contrib/llvm/tools/lldb/include/lldb/Core/FileLineResolver.h
index e1928f1..f0f7fbd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/FileLineResolver.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/FileLineResolver.h
@@ -38,20 +38,19 @@ public:
uint32_t line_no,
bool check_inlines);
- virtual
- ~FileLineResolver ();
+ ~FileLineResolver () override;
- virtual Searcher::CallbackReturn
+ Searcher::CallbackReturn
SearchCallback (SearchFilter &filter,
SymbolContext &context,
Address *addr,
- bool containing);
+ bool containing) override;
- virtual Searcher::Depth
- GetDepth ();
+ Searcher::Depth
+ GetDepth () override;
- virtual void
- GetDescription (Stream *s);
+ void
+ GetDescription (Stream *s) override;
const SymbolContextList &
GetFileLineMatches()
@@ -78,4 +77,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_FileLineResolver_h_
+#endif // liblldb_FileLineResolver_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/FormatEntity.h b/contrib/llvm/tools/lldb/include/lldb/Core/FormatEntity.h
index db4f591..659b696 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/FormatEntity.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/FormatEntity.h
@@ -9,18 +9,21 @@
#ifndef liblldb_FormatEntity_h_
#define liblldb_FormatEntity_h_
-#if defined(__cplusplus)
+// C Includes
+// C++ Includes
#include <string>
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/Error.h"
namespace llvm
{
class StringRef;
-}
+} // namespace llvm
namespace lldb_private
{
@@ -81,6 +84,7 @@ namespace lldb_private
FunctionPCOffset,
FunctionInitial,
FunctionChanged,
+ FunctionIsOptimized,
LineEntryFile,
LineEntryLineNumber,
LineEntryStartAddress,
@@ -108,13 +112,13 @@ namespace lldb_private
bool keep_separator;
};
- Entry (Type t = Type::Invalid,
- const char *s = NULL,
- const char *f = NULL) :
+ Entry(Type t = Type::Invalid,
+ const char *s = nullptr,
+ const char *f = nullptr) :
string (s ? s : ""),
printf_format (f ? f : ""),
children (),
- definition (NULL),
+ definition (nullptr),
type (t),
fmt (lldb::eFormatDefault),
number (0),
@@ -146,7 +150,7 @@ namespace lldb_private
string.clear();
printf_format.clear();
children.clear();
- definition = NULL;
+ definition = nullptr;
type = Type::Invalid;
fmt = lldb::eFormatDefault;
number = 0;
@@ -252,12 +256,10 @@ namespace lldb_private
static bool
FormatFileSpec (const FileSpec &file, Stream &s, llvm::StringRef elements, llvm::StringRef element_format);
protected:
-
static Error
ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint32_t depth);
};
+} // namespace lldb_private
-}
-#endif // #if defined(__cplusplus)
-#endif // liblldb_FormatEntity_h_
+#endif // liblldb_FormatEntity_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/History.h b/contrib/llvm/tools/lldb/include/lldb/Core/History.h
index b362688..fbb7bd8 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/History.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/History.h
@@ -82,7 +82,6 @@ private:
collection m_events;
DISALLOW_COPY_AND_ASSIGN (HistorySource);
-
};
//----------------------------------------------------------------------
@@ -103,8 +102,7 @@ class HistorySourceUInt : public HistorySource
{
}
- virtual
- ~HistorySourceUInt()
+ ~HistorySourceUInt() override
{
}
@@ -112,44 +110,44 @@ class HistorySourceUInt : public HistorySource
// in the subclass of this class to produce a history event and push it
// onto the end of the history stack.
- virtual HistoryEvent
- CreateHistoryEvent ()
+ HistoryEvent
+ CreateHistoryEvent () override
{
++m_curr_id;
return (HistoryEvent)m_curr_id;
}
- virtual void
- DeleteHistoryEvent (HistoryEvent event)
+ void
+ DeleteHistoryEvent (HistoryEvent event) override
{
// Nothing to delete, the event contains the integer
}
- virtual void
- DumpHistoryEvent (Stream &strm, HistoryEvent event);
+ void
+ DumpHistoryEvent (Stream &strm, HistoryEvent event) override;
- virtual size_t
- GetHistoryEventCount()
+ size_t
+ GetHistoryEventCount() override
{
return m_curr_id;
}
- virtual HistoryEvent
- GetHistoryEventAtIndex (uint32_t idx)
+ HistoryEvent
+ GetHistoryEventAtIndex (uint32_t idx) override
{
return (HistoryEvent)((uintptr_t)idx);
}
- virtual HistoryEvent
- GetCurrentHistoryEvent ()
+ HistoryEvent
+ GetCurrentHistoryEvent () override
{
return (HistoryEvent)m_curr_id;
}
// Return 0 when lhs == rhs, 1 if lhs > rhs, or -1 if lhs < rhs.
- virtual int
+ int
CompareHistoryEvents (const HistoryEvent lhs,
- const HistoryEvent rhs)
+ const HistoryEvent rhs) override
{
uintptr_t lhs_uint = (uintptr_t)lhs;
uintptr_t rhs_uint = (uintptr_t)rhs;
@@ -160,8 +158,8 @@ class HistorySourceUInt : public HistorySource
return 0;
}
- virtual bool
- IsCurrentHistoryEvent (const HistoryEvent event)
+ bool
+ IsCurrentHistoryEvent (const HistoryEvent event) override
{
return (uintptr_t)event == m_curr_id;
}
@@ -171,7 +169,6 @@ protected:
uintptr_t m_curr_id; // The current value of the history unsigned unteger
};
-
} // namespace lldb_private
-#endif // lldb_History_h_
+#endif // lldb_History_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/IOHandler.h b/contrib/llvm/tools/lldb/include/lldb/Core/IOHandler.h
index b617d8e..3eba1c3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/IOHandler.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/IOHandler.h
@@ -10,10 +10,16 @@
#ifndef liblldb_IOHandler_h_
#define liblldb_IOHandler_h_
+// C Includes
#include <string.h>
-#include <stack>
+// C++ Includes
+#include <memory>
+#include <string>
+#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-public.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/Core/ConstString.h"
@@ -29,7 +35,7 @@ namespace curses
{
class Application;
typedef std::unique_ptr<Application> ApplicationAP;
-}
+} // namespace curses
namespace lldb_private {
@@ -42,6 +48,7 @@ namespace lldb_private {
Confirm,
Curses,
Expression,
+ REPL,
ProcessIO,
PythonInterpreter,
PythonCode,
@@ -123,7 +130,7 @@ namespace lldb_private {
GetPrompt ()
{
// Prompt support isn't mandatory
- return NULL;
+ return nullptr;
}
virtual bool
@@ -142,13 +149,13 @@ namespace lldb_private {
virtual const char *
GetCommandPrefix ()
{
- return NULL;
+ return nullptr;
}
virtual const char *
GetHelpPrologue()
{
- return NULL;
+ return nullptr;
}
int
@@ -257,7 +264,6 @@ namespace lldb_private {
private:
DISALLOW_COPY_AND_ASSIGN (IOHandler);
};
-
//------------------------------------------------------------------
/// A delegate class for use with IOHandler subclasses.
@@ -283,9 +289,7 @@ namespace lldb_private {
}
virtual
- ~IOHandlerDelegate()
- {
- }
+ ~IOHandlerDelegate() = default;
virtual void
IOHandlerActivated (IOHandler &io_handler)
@@ -309,7 +313,7 @@ namespace lldb_private {
virtual const char *
IOHandlerGetFixIndentationCharacters ()
{
- return NULL;
+ return nullptr;
}
//------------------------------------------------------------------
@@ -395,13 +399,13 @@ namespace lldb_private {
virtual const char *
IOHandlerGetCommandPrefix ()
{
- return NULL;
+ return nullptr;
}
virtual const char *
IOHandlerGetHelpPrologue ()
{
- return NULL;
+ return nullptr;
}
//------------------------------------------------------------------
@@ -415,6 +419,7 @@ namespace lldb_private {
{
return false;
}
+
protected:
Completion m_completion; // Support for common builtin completions
bool m_io_handler_done;
@@ -438,10 +443,7 @@ namespace lldb_private {
{
}
- virtual
- ~IOHandlerDelegateMultiline ()
- {
- }
+ ~IOHandlerDelegateMultiline() override = default;
ConstString
IOHandlerGetControlSequence (char ch) override
@@ -467,11 +469,11 @@ namespace lldb_private {
}
return false;
}
+
protected:
const std::string m_end_line;
};
-
class IOHandlerEditline : public IOHandler
{
public:
@@ -499,8 +501,7 @@ namespace lldb_private {
uint32_t line_number_start, // If non-zero show line numbers starting at 'line_number_start'
IOHandlerDelegate &delegate);
- virtual
- ~IOHandlerEditline ();
+ ~IOHandlerEditline() override;
void
Run () override;
@@ -632,8 +633,7 @@ namespace lldb_private {
const char *prompt,
bool default_response);
- virtual
- ~IOHandlerConfirm ();
+ ~IOHandlerConfirm() override;
bool
GetResponse () const
@@ -694,14 +694,14 @@ namespace lldb_private {
public:
IOHandlerCursesValueObjectList (Debugger &debugger, ValueObjectList &valobj_list);
- virtual
- ~IOHandlerCursesValueObjectList ();
+ ~IOHandlerCursesValueObjectList() override;
void
Run () override;
void
GotEOF() override;
+
protected:
ValueObjectList m_valobj_list;
};
@@ -709,17 +709,14 @@ namespace lldb_private {
class IOHandlerStack
{
public:
-
IOHandlerStack () :
m_stack(),
m_mutex(Mutex::eMutexTypeRecursive),
- m_top (NULL)
+ m_top (nullptr)
{
}
- ~IOHandlerStack ()
- {
- }
+ ~IOHandlerStack() = default;
size_t
GetSize () const
@@ -771,10 +768,8 @@ namespace lldb_private {
sp->SetPopped (true);
}
// Set m_top the non-locking IsTop() call
- if (m_stack.empty())
- m_top = NULL;
- else
- m_top = m_stack.back().get();
+
+ m_top = (m_stack.empty() ? nullptr : m_stack.back().get());
}
Mutex &
@@ -794,53 +789,42 @@ namespace lldb_private {
{
Mutex::Locker locker (m_mutex);
const size_t num_io_handlers = m_stack.size();
- if (num_io_handlers >= 2 &&
- m_stack[num_io_handlers-1]->GetType() == top_type &&
- m_stack[num_io_handlers-2]->GetType() == second_top_type)
- {
- return true;
- }
- return false;
+ return (num_io_handlers >= 2 &&
+ m_stack[num_io_handlers-1]->GetType() == top_type &&
+ m_stack[num_io_handlers-2]->GetType() == second_top_type);
}
+
ConstString
GetTopIOHandlerControlSequence (char ch)
{
- if (m_top)
- return m_top->GetControlSequence(ch);
- return ConstString();
+ return ((m_top != nullptr) ? m_top->GetControlSequence(ch) : ConstString());
}
const char *
GetTopIOHandlerCommandPrefix()
{
- if (m_top)
- return m_top->GetCommandPrefix();
- return NULL;
+ return ((m_top != nullptr) ? m_top->GetCommandPrefix() : nullptr);
}
const char *
GetTopIOHandlerHelpPrologue()
{
- if (m_top)
- return m_top->GetHelpPrologue();
- return NULL;
+ return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr);
}
void
PrintAsync (Stream *stream, const char *s, size_t len);
protected:
-
typedef std::vector<lldb::IOHandlerSP> collection;
collection m_stack;
mutable Mutex m_mutex;
IOHandler *m_top;
private:
-
DISALLOW_COPY_AND_ASSIGN (IOHandlerStack);
};
} // namespace lldb_private
-#endif // #ifndef liblldb_IOHandler_h_
+#endif // liblldb_IOHandler_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Language.h b/contrib/llvm/tools/lldb/include/lldb/Core/Language.h
deleted file mode 100644
index 670c6aa..0000000
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Language.h
+++ /dev/null
@@ -1,117 +0,0 @@
-//===-- Language.h ----------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_Language_h_
-#define liblldb_Language_h_
-
-#include "lldb/lldb-private.h"
-
-namespace lldb_private {
-
-//----------------------------------------------------------------------
-/// @class Language Language.h "lldb/Core/Language.h"
-/// @brief Encapsulates the programming language for an lldb object.
-///
-/// Languages are represented by an enumeration value.
-///
-/// The enumeration values used when describing the programming language
-/// are the same values as the latest DWARF specification.
-//----------------------------------------------------------------------
-class Language
-{
-public:
- //------------------------------------------------------------------
- /// Construct with optional language enumeration.
- //------------------------------------------------------------------
- Language(lldb::LanguageType language = lldb::eLanguageTypeUnknown);
-
- //------------------------------------------------------------------
- /// Destructor.
- ///
- /// The destructor is virtual in case this class is subclassed.
- //------------------------------------------------------------------
- virtual
- ~Language();
-
- //------------------------------------------------------------------
- /// Get the language value as a NULL termianted C string.
- ///
- /// @return
- /// The C string representation of the language. The returned
- /// string does not need to be freed as it comes from constant
- /// strings. NULL can be returned when the language is set to
- /// a value that doesn't match of of the lldb::LanguageType
- /// enumerations.
- //------------------------------------------------------------------
- const char *
- AsCString (lldb::DescriptionLevel level = lldb::eDescriptionLevelBrief) const;
-
- void
- Clear();
-
- void
- GetDescription (Stream *s, lldb::DescriptionLevel level) const;
-
- //------------------------------------------------------------------
- /// Dump the language value to the stream \a s.
- ///
- /// @param[in] s
- /// The stream to which to dump the language description.
- //------------------------------------------------------------------
- void
- Dump(Stream *s) const;
-
- //------------------------------------------------------------------
- /// Get accessor for the language.
- ///
- /// @return
- /// The enumeration value that describes the programming
- /// language that an object is associated with.
- //------------------------------------------------------------------
- virtual lldb::LanguageType
- GetLanguage() const;
-
- //------------------------------------------------------------------
- /// Set accessor for the language.
- ///
- /// @param[in] language
- /// The new enumeration value that describes the programming
- /// language that an object is associated with.
- //------------------------------------------------------------------
- void
- SetLanguage(lldb::LanguageType language);
-
- //------------------------------------------------------------------
- /// Set accessor for the language.
- ///
- /// @param[in] language_cstr
- /// The language name as a C string.
- //------------------------------------------------------------------
- bool
- SetLanguageFromCString(const char *language_cstr);
-
-
-protected:
- //------------------------------------------------------------------
- // Member variables
- //------------------------------------------------------------------
- lldb::LanguageType m_language; ///< The programming language enumeration value.
- ///< The enumeration values are the same as the
- ///< latest DWARF specification.
-};
-
-//--------------------------------------------------------------
-/// Stream the language enumeration as a string object to a
-/// Stream.
-//--------------------------------------------------------------
-Stream& operator << (Stream& s, const Language& language);
-
-} // namespace lldb_private
-
-#endif // liblldb_Language_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Listener.h b/contrib/llvm/tools/lldb/include/lldb/Core/Listener.h
index 2dbd2eb..b11c164 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Listener.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Listener.h
@@ -14,11 +14,9 @@
// C++ Includes
#include <list>
#include <map>
-#include <set>
#include <string>
#include <vector>
-
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@@ -118,13 +116,12 @@ public:
HandleBroadcastEvent (lldb::EventSP &event_sp);
private:
-
//------------------------------------------------------------------
// Classes that inherit from Listener can see and modify these
//------------------------------------------------------------------
struct BroadcasterInfo
{
- BroadcasterInfo(uint32_t mask, HandleBroadcastCallback cb = NULL, void *ud = NULL) :
+ BroadcasterInfo(uint32_t mask, HandleBroadcastCallback cb = nullptr, void *ud = nullptr) :
event_mask (mask),
callback (cb),
callback_user_data (ud)
@@ -141,28 +138,28 @@ private:
typedef std::vector<BroadcasterManager *> broadcaster_manager_collection;
bool
- FindNextEventInternal (Broadcaster *broadcaster, // NULL for any broadcaster
- const ConstString *sources, // NULL for any event
- uint32_t num_sources,
- uint32_t event_type_mask,
- lldb::EventSP &event_sp,
- bool remove);
+ FindNextEventInternal(Broadcaster *broadcaster, // nullptr for any broadcaster
+ const ConstString *sources, // nullptr for any event
+ uint32_t num_sources,
+ uint32_t event_type_mask,
+ lldb::EventSP &event_sp,
+ bool remove);
+
+ bool
+ GetNextEventInternal(Broadcaster *broadcaster, // nullptr for any broadcaster
+ const ConstString *sources, // nullptr for any event
+ uint32_t num_sources,
+ uint32_t event_type_mask,
+ lldb::EventSP &event_sp);
bool
- GetNextEventInternal (Broadcaster *broadcaster, // NULL for any broadcaster
- const ConstString *sources, // NULL for any event
+ WaitForEventsInternal(const TimeValue *timeout,
+ Broadcaster *broadcaster, // nullptr for any broadcaster
+ const ConstString *sources, // nullptr for any event
uint32_t num_sources,
uint32_t event_type_mask,
lldb::EventSP &event_sp);
- bool
- WaitForEventsInternal (const TimeValue *timeout,
- Broadcaster *broadcaster, // NULL for any broadcaster
- const ConstString *sources, // NULL for any event
- uint32_t num_sources,
- uint32_t event_type_mask,
- lldb::EventSP &event_sp);
-
std::string m_name;
broadcaster_collection m_broadcasters;
Mutex m_broadcasters_mutex; // Protects m_broadcasters
@@ -191,4 +188,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_Select_h_
+#endif // liblldb_Select_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/LoadedModuleInfoList.h b/contrib/llvm/tools/lldb/include/lldb/Core/LoadedModuleInfoList.h
new file mode 100644
index 0000000..6ba5c28
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/LoadedModuleInfoList.h
@@ -0,0 +1,152 @@
+//===-- LoadedModuleInfoList.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_LoadedModuleInfoList_h_
+#define liblldb_LoadedModuleInfoList_h_
+
+// C Includes
+
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "lldb/lldb-private-forward.h"
+
+namespace lldb_private {
+class LoadedModuleInfoList
+{
+public:
+
+ class LoadedModuleInfo
+ {
+ public:
+
+ enum e_data_point
+ {
+ e_has_name = 0,
+ e_has_base ,
+ e_has_dynamic ,
+ e_has_link_map ,
+ e_num
+ };
+
+ LoadedModuleInfo ()
+ {
+ for (uint32_t i = 0; i < e_num; ++i)
+ m_has[i] = false;
+ };
+
+ void set_name (const std::string & name)
+ {
+ m_name = name;
+ m_has[e_has_name] = true;
+ }
+ bool get_name (std::string & out) const
+ {
+ out = m_name;
+ return m_has[e_has_name];
+ }
+
+ void set_base (const lldb::addr_t base)
+ {
+ m_base = base;
+ m_has[e_has_base] = true;
+ }
+ bool get_base (lldb::addr_t & out) const
+ {
+ out = m_base;
+ return m_has[e_has_base];
+ }
+
+ void set_base_is_offset (bool is_offset)
+ {
+ m_base_is_offset = is_offset;
+ }
+ bool get_base_is_offset(bool & out) const
+ {
+ out = m_base_is_offset;
+ return m_has[e_has_base];
+ }
+
+ void set_link_map (const lldb::addr_t addr)
+ {
+ m_link_map = addr;
+ m_has[e_has_link_map] = true;
+ }
+ bool get_link_map (lldb::addr_t & out) const
+ {
+ out = m_link_map;
+ return m_has[e_has_link_map];
+ }
+
+ void set_dynamic (const lldb::addr_t addr)
+ {
+ m_dynamic = addr;
+ m_has[e_has_dynamic] = true;
+ }
+ bool get_dynamic (lldb::addr_t & out) const
+ {
+ out = m_dynamic;
+ return m_has[e_has_dynamic];
+ }
+
+ bool has_info (e_data_point datum) const
+ {
+ assert (datum < e_num);
+ return m_has[datum];
+ }
+
+ bool
+ operator == (LoadedModuleInfo const &rhs) const
+ {
+ if (e_num != rhs.e_num)
+ return false;
+
+ for (size_t i = 0; i < e_num; ++i)
+ {
+ if (m_has[i] != rhs.m_has[i])
+ return false;
+ }
+
+ return (m_base == rhs.m_base) &&
+ (m_link_map == rhs.m_link_map) &&
+ (m_dynamic == rhs.m_dynamic) &&
+ (m_name == rhs.m_name);
+ }
+ protected:
+
+ bool m_has[e_num];
+ std::string m_name;
+ lldb::addr_t m_link_map;
+ lldb::addr_t m_base;
+ bool m_base_is_offset;
+ lldb::addr_t m_dynamic;
+ };
+
+ LoadedModuleInfoList ()
+ : m_list ()
+ , m_link_map (LLDB_INVALID_ADDRESS)
+ {}
+
+ void add (const LoadedModuleInfo & mod)
+ {
+ m_list.push_back (mod);
+ }
+
+ void clear ()
+ {
+ m_list.clear ();
+ }
+
+ std::vector<LoadedModuleInfo> m_list;
+ lldb::addr_t m_link_map;
+};
+} // namespace lldb_private
+
+#endif // liblldb_LoadedModuleInfoList_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Log.h b/contrib/llvm/tools/lldb/include/lldb/Core/Log.h
index 3aa4b4d..674fdfd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Log.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Log.h
@@ -182,17 +182,16 @@ private:
DISALLOW_COPY_AND_ASSIGN(Log);
};
-
class LogChannel : public PluginInterface
{
public:
LogChannel();
- virtual ~LogChannel();
+ ~LogChannel() override;
static lldb::LogChannelSP FindPlugin(const char *plugin_name);
- // categories is a an array of chars that ends with a NULL element.
+ // categories is an array of chars that ends with a NULL element.
virtual void Disable(const char **categories, Stream *feedback_strm) = 0;
virtual bool Enable(
@@ -209,7 +208,6 @@ private:
DISALLOW_COPY_AND_ASSIGN(LogChannel);
};
-
} // namespace lldb_private
-#endif // liblldb_Log_H_
+#endif // liblldb_Log_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Logging.h b/contrib/llvm/tools/lldb/include/lldb/Core/Logging.h
index a4dd76f..ca04c84 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Logging.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Logging.h
@@ -48,6 +48,7 @@
#define LIBLLDB_LOG_SYSTEM_RUNTIME (1u << 26)
#define LIBLLDB_LOG_JIT_LOADER (1u << 27)
#define LIBLLDB_LOG_LANGUAGE (1u << 28)
+#define LIBLLDB_LOG_DATAFORMATTERS (1u << 29)
#define LIBLLDB_LOG_ALL (UINT32_MAX)
#define LIBLLDB_LOG_DEFAULT (LIBLLDB_LOG_PROCESS |\
LIBLLDB_LOG_THREAD |\
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/MappedHash.h b/contrib/llvm/tools/lldb/include/lldb/Core/MappedHash.h
index 4b77ff1..5a52ab2 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/MappedHash.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/MappedHash.h
@@ -1,29 +1,38 @@
+//===-- MappedHash.h --------------------------------------------*- C++ -*-===//
//
-// MappedHash.h
+// The LLVM Compiler Infrastructure
//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
#ifndef liblldb_MappedHash_h_
#define liblldb_MappedHash_h_
+// C Includes
#include <assert.h>
#include <stdint.h>
+// C++ Includes
+#include <algorithm>
+#include <functional>
#include <map>
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Stream.h"
class MappedHash
{
public:
-
enum HashFunctionType
{
eHashFunctionDJB = 0u // Daniel J Bernstein hash function that is also used by the ELF GNU_HASH sections
};
-
static uint32_t
HashStringUsingDJB (const char *s)
{
@@ -50,7 +59,6 @@ public:
return 0;
}
-
static const uint32_t HASH_MAGIC = 0x48415348u;
static const uint32_t HASH_CIGAM = 0x48534148u;
@@ -77,11 +85,9 @@ public:
header_data ()
{
}
-
+
virtual
- ~Header()
- {
- }
+ ~Header() = default;
size_t
GetByteSize() const
@@ -254,8 +260,7 @@ public:
header.bucket_count = num_unique_hashes;
if (header.bucket_count == 0)
header.bucket_count = 1;
-
-
+
std::vector<HashToHashData> hash_buckets;
std::vector<uint32_t> hash_indexes (header.bucket_count, 0);
std::vector<uint32_t> hash_values;
@@ -345,10 +350,12 @@ public:
}
}
}
+
protected:
typedef std::vector<Entry> collection;
collection m_entries;
};
+
// A class for reading and using a saved hash table from a block of data
// in memory
template <typename __KeyType, class __HeaderType, class __HashData>
@@ -375,9 +382,9 @@ public:
MemoryTable (lldb_private::DataExtractor &data) :
m_header (),
- m_hash_indexes (NULL),
- m_hash_values (NULL),
- m_hash_offsets (NULL)
+ m_hash_indexes (nullptr),
+ m_hash_values (nullptr),
+ m_hash_offsets (nullptr)
{
lldb::offset_t offset = m_header.Read (data, 0);
if (offset != LLDB_INVALID_OFFSET && IsValid ())
@@ -387,12 +394,10 @@ public:
m_hash_offsets = (const uint32_t *)data.GetData (&offset, m_header.hashes_count * sizeof(uint32_t));
}
}
-
+
virtual
- ~MemoryTable ()
- {
- }
-
+ ~MemoryTable() = default;
+
bool
IsValid () const
{
@@ -483,7 +488,6 @@ public:
// subclass and return a valie "const char *" given a "key". The value
// could also be a C string pointer, in which case just returning "key"
// will suffice.
-
virtual const char *
GetStringForKeyType (KeyType key) const = 0;
@@ -506,7 +510,6 @@ public:
// should be returned. If anything else goes wrong during parsing,
// return "eResultError" and the corresponding "Find()" function will
// be canceled and return false.
-
virtual Result
GetHashDataForName (const char *name,
lldb::offset_t* hash_data_offset_ptr,
@@ -518,7 +521,6 @@ public:
return m_header;
}
-
void
ForEach (std::function <bool(const HashData &hash_data)> const &callback) const
{
@@ -546,7 +548,6 @@ public:
const uint32_t *m_hash_values;
const uint32_t *m_hash_offsets;
};
-
};
-#endif // #ifndef liblldb_MappedHash_h_
+#endif // liblldb_MappedHash_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Module.h b/contrib/llvm/tools/lldb/include/lldb/Core/Module.h
index 127ddae..35b182a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Module.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Module.h
@@ -10,6 +10,14 @@
#ifndef liblldb_Module_h_
#define liblldb_Module_h_
+// C Includes
+// C++ Includes
+#include <atomic>
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-forward.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/UUID.h"
@@ -17,6 +25,7 @@
#include "lldb/Host/Mutex.h"
#include "lldb/Host/TimeValue.h"
#include "lldb/Symbol/SymbolContextScope.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/PathMappingList.h"
namespace lldb_private {
@@ -85,11 +94,11 @@ public:
/// module within a module (.a files and modules that contain
/// multiple architectures).
//------------------------------------------------------------------
- Module (const FileSpec& file_spec,
- const ArchSpec& arch,
- const ConstString *object_name = NULL,
- lldb::offset_t object_offset = 0,
- const TimeValue *object_mod_time_ptr = NULL);
+ Module(const FileSpec& file_spec,
+ const ArchSpec& arch,
+ const ConstString *object_name = nullptr,
+ lldb::offset_t object_offset = 0,
+ const TimeValue *object_mod_time_ptr = nullptr);
Module (const ModuleSpec &module_spec);
@@ -99,8 +108,7 @@ public:
//------------------------------------------------------------------
/// Destructor.
//------------------------------------------------------------------
- virtual
- ~Module ();
+ ~Module() override;
bool
MatchesModuleSpec (const ModuleSpec &module_ref);
@@ -154,11 +162,11 @@ public:
///
/// @see SymbolContextScope
//------------------------------------------------------------------
- virtual void
- CalculateSymbolContext (SymbolContext* sc);
+ void
+ CalculateSymbolContext(SymbolContext* sc) override;
- virtual lldb::ModuleSP
- CalculateSymbolContextModule ();
+ lldb::ModuleSP
+ CalculateSymbolContextModule() override;
void
GetDescription (Stream *s,
@@ -207,10 +215,9 @@ public:
///
/// @see SymbolContextScope
//------------------------------------------------------------------
- virtual void
- DumpSymbolContext (Stream *s);
+ void
+ DumpSymbolContext(Stream *s) override;
-
//------------------------------------------------------------------
/// Find a symbol in the object file's symbol table.
///
@@ -225,7 +232,7 @@ public:
///
/// @return
/// Returns a valid symbol pointer if a symbol was found,
- /// NULL otherwise.
+ /// nullptr otherwise.
//------------------------------------------------------------------
const Symbol *
FindFirstSymbolWithNameAndType (const ConstString &name,
@@ -288,7 +295,6 @@ public:
FindCompileUnits (const FileSpec &path,
bool append,
SymbolContextList &sc_list);
-
//------------------------------------------------------------------
/// Find functions by name.
@@ -323,7 +329,7 @@ public:
//------------------------------------------------------------------
size_t
FindFunctions (const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
uint32_t name_type_mask,
bool symbols_ok,
bool inlines_ok,
@@ -392,8 +398,8 @@ public:
/// The name of the global or static variable we are looking
/// for.
///
- /// @param[in] namespace_decl
- /// If valid, a namespace to search in.
+ /// @param[in] parent_decl_ctx
+ /// If valid, a decl context that results must exist within
///
/// @param[in] append
/// If \b true, any matches will be appended to \a
@@ -413,7 +419,7 @@ public:
//------------------------------------------------------------------
size_t
FindGlobalVariables (const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
bool append,
size_t max_matches,
VariableList& variable_list);
@@ -524,7 +530,7 @@ public:
size_t
FindTypesInNamespace (const SymbolContext& sc,
const ConstString &type_name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
size_t max_matches,
TypeList& type_list);
@@ -646,10 +652,10 @@ public:
IsLoadedInTarget (Target *target);
bool
- LoadScriptingResourceInTarget (Target *target,
- Error& error,
- Stream* feedback_stream = NULL);
-
+ LoadScriptingResourceInTarget(Target *target,
+ Error& error,
+ Stream* feedback_stream = nullptr);
+
//------------------------------------------------------------------
/// Get the number of compile units for this module.
///
@@ -682,7 +688,7 @@ public:
/// @return
/// If Module::m_file does not exist, or no plug-in was found
/// that can parse the file, or the object file doesn't contain
- /// the current architecture in Module::m_arch, NULL will be
+ /// the current architecture in Module::m_arch, nullptr will be
/// returned, else a valid object file interface will be
/// returned. The returned pointer is owned by this object and
/// remains valid as long as the object is around.
@@ -730,7 +736,7 @@ public:
/// process.
///
/// @return
- /// The object file loaded from memory or NULL, if the operation
+ /// The object file loaded from memory or nullptr, if the operation
/// failed (see the `error` for more information in that case).
//------------------------------------------------------------------
ObjectFile *
@@ -747,20 +753,20 @@ public:
///
/// @return
/// If this module does not have a valid object file, or no
- /// plug-in can be found that can use the object file, NULL will
+ /// plug-in can be found that can use the object file, nullptr will
/// be returned, else a valid symbol vendor plug-in interface
/// will be returned. The returned pointer is owned by this
/// object and remains valid as long as the object is around.
//------------------------------------------------------------------
virtual SymbolVendor*
GetSymbolVendor(bool can_create = true,
- lldb_private::Stream *feedback_strm = NULL);
+ lldb_private::Stream *feedback_strm = nullptr);
//------------------------------------------------------------------
/// Get accessor the type list for this module.
///
/// @return
- /// A valid type list pointer, or NULL if there is no valid
+ /// A valid type list pointer, or nullptr if there is no valid
/// symbol vendor for this module.
//------------------------------------------------------------------
TypeList*
@@ -935,7 +941,6 @@ public:
uint32_t
ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list);
-
void
SetFileSpecAndObjectName (const FileSpec &file,
const ConstString &object_name);
@@ -943,8 +948,8 @@ public:
bool
GetIsDynamicLinkEditor ();
- ClangASTContext &
- GetClangASTContext ();
+ TypeSystem *
+ GetTypeSystemForLanguage (lldb::LanguageType language);
// Special error functions that can do printf style formatting that will prepend the message with
// something appropriate for this module (like the architecture, path and object name (if any)).
@@ -1041,7 +1046,6 @@ public:
bool
RemapSourceFile (const char *path, std::string &new_path) const;
-
//------------------------------------------------------------------
/// Prepare to do a function name lookup.
///
@@ -1067,6 +1071,10 @@ public:
/// The mask of bits from lldb::FunctionNameType enumerations
/// that tell us what kind of name we are looking for.
///
+ /// @param[out] language
+ /// If known, the language to use for determining the
+ /// lookup_name_type_mask.
+ ///
/// @param[out] lookup_name
/// The actual name that will be used when calling
/// SymbolVendor::FindFunctions() or Symtab::FindFunctionSymbols()
@@ -1087,6 +1095,7 @@ public:
static void
PrepareForFunctionNameLookup (const ConstString &name,
uint32_t name_type_mask,
+ lldb::LanguageType language,
ConstString &lookup_name,
uint32_t &lookup_name_type_mask,
bool &match_name_after_lookup);
@@ -1110,17 +1119,16 @@ protected:
lldb::SymbolVendorUP m_symfile_ap; ///< A pointer to the symbol vendor for this module.
std::vector<lldb::SymbolVendorUP> m_old_symfiles; ///< If anyone calls Module::SetSymbolFileFileSpec() and changes the symbol file,
///< we need to keep all old symbol files around in case anyone has type references to them
- lldb::ClangASTContextUP m_ast; ///< The AST context for this module.
+ TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module
PathMappingList m_source_mappings; ///< Module specific source remappings for when you have debug info for a module that doesn't match where the sources currently are
lldb::SectionListUP m_sections_ap; ///< Unified section list for module that is used by the ObjectFile and and ObjectFile instances for the debug info
- bool m_did_load_objfile:1,
- m_did_load_symbol_vendor:1,
- m_did_parse_uuid:1,
- m_did_init_ast:1;
+ std::atomic<bool> m_did_load_objfile;
+ std::atomic<bool> m_did_load_symbol_vendor;
+ std::atomic<bool> m_did_parse_uuid;
mutable bool m_file_has_changed:1,
m_first_file_changed_log:1; /// See if the module was modified after it was initially opened.
-
+
//------------------------------------------------------------------
/// Resolve a file or load virtual address.
///
@@ -1178,21 +1186,19 @@ protected:
friend class SymbolFile;
private:
-
Module (); // Only used internally by CreateJITModule ()
size_t
FindTypes_Impl (const SymbolContext& sc,
const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
bool append,
size_t max_matches,
- TypeList& types);
+ TypeMap& types);
-
DISALLOW_COPY_AND_ASSIGN (Module);
};
} // namespace lldb_private
-#endif // liblldb_Module_h_
+#endif // liblldb_Module_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ModuleList.h b/contrib/llvm/tools/lldb/include/lldb/Core/ModuleList.h
index f4c12cf..a0dd432 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ModuleList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ModuleList.h
@@ -10,10 +10,14 @@
#ifndef liblldb_ModuleList_h_
#define liblldb_ModuleList_h_
-#include <vector>
-#include <list>
+// C Includes
+// C++ Includes
#include <functional>
+#include <list>
+#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Utility/Iterable.h"
@@ -30,10 +34,12 @@ namespace lldb_private {
class ModuleList
{
public:
-
class Notifier
{
public:
+ virtual
+ ~Notifier() = default;
+
virtual void
ModuleAdded (const ModuleList& module_list, const lldb::ModuleSP& module_sp) = 0;
virtual void
@@ -43,10 +49,6 @@ public:
const lldb::ModuleSP& new_module_sp) = 0;
virtual void
WillClearList (const ModuleList& module_list) = 0;
-
- virtual
- ~Notifier ()
- {}
};
//------------------------------------------------------------------
@@ -144,6 +146,7 @@ public:
//------------------------------------------------------------------
void
Destroy();
+
//------------------------------------------------------------------
/// Dump the description of each module contained in this list.
///
@@ -209,7 +212,7 @@ public:
/// An index into this module collection.
///
/// @return
- /// A pointer to a Module which can by NULL if \a idx is out
+ /// A pointer to a Module which can by nullptr if \a idx is out
/// of range.
///
/// @see ModuleList::GetSize()
@@ -226,7 +229,7 @@ public:
/// An index into this module collection.
///
/// @return
- /// A pointer to a Module which can by NULL if \a idx is out
+ /// A pointer to a Module which can by nullptr if \a idx is out
/// of range.
///
/// @see ModuleList::GetSize()
@@ -534,10 +537,10 @@ public:
GetSize () const;
bool
- LoadScriptingResourcesInTarget (Target *target,
- std::list<Error>& errors,
- Stream* feedback_stream = NULL,
- bool continue_on_error = true);
+ LoadScriptingResourcesInTarget(Target *target,
+ std::list<Error>& errors,
+ Stream* feedback_stream = nullptr,
+ bool continue_on_error = true);
static bool
ModuleIsInCache (const Module *module_ptr);
@@ -606,9 +609,8 @@ public:
{
return ModuleIterableNoLocking(m_modules);
}
-
};
} // namespace lldb_private
-#endif // liblldb_ModuleList_h_
+#endif // liblldb_ModuleList_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ModuleSpec.h b/contrib/llvm/tools/lldb/include/lldb/Core/ModuleSpec.h
index be70419..95de7f3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ModuleSpec.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ModuleSpec.h
@@ -10,6 +10,12 @@
#ifndef liblldb_ModuleSpec_h_
#define liblldb_ModuleSpec_h_
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/UUID.h"
@@ -100,17 +106,13 @@ public:
FileSpec *
GetFileSpecPtr ()
{
- if (m_file)
- return &m_file;
- return NULL;
+ return (m_file ? &m_file : nullptr);
}
const FileSpec *
GetFileSpecPtr () const
{
- if (m_file)
- return &m_file;
- return NULL;
+ return (m_file ? &m_file : nullptr);
}
FileSpec &
@@ -118,6 +120,7 @@ public:
{
return m_file;
}
+
const FileSpec &
GetFileSpec () const
{
@@ -127,17 +130,13 @@ public:
FileSpec *
GetPlatformFileSpecPtr ()
{
- if (m_platform_file)
- return &m_platform_file;
- return NULL;
+ return (m_platform_file ? &m_platform_file : nullptr);
}
const FileSpec *
GetPlatformFileSpecPtr () const
{
- if (m_platform_file)
- return &m_platform_file;
- return NULL;
+ return (m_platform_file ? &m_platform_file : nullptr);
}
FileSpec &
@@ -155,17 +154,13 @@ public:
FileSpec *
GetSymbolFileSpecPtr ()
{
- if (m_symbol_file)
- return &m_symbol_file;
- return NULL;
+ return (m_symbol_file ? &m_symbol_file : nullptr);
}
const FileSpec *
GetSymbolFileSpecPtr () const
{
- if (m_symbol_file)
- return &m_symbol_file;
- return NULL;
+ return (m_symbol_file ? &m_symbol_file : nullptr);
}
FileSpec &
@@ -180,21 +175,16 @@ public:
return m_symbol_file;
}
-
ArchSpec *
GetArchitecturePtr ()
{
- if (m_arch.IsValid())
- return &m_arch;
- return NULL;
+ return (m_arch.IsValid() ? &m_arch : nullptr);
}
const ArchSpec *
GetArchitecturePtr () const
{
- if (m_arch.IsValid())
- return &m_arch;
- return NULL;
+ return (m_arch.IsValid() ? &m_arch : nullptr);
}
ArchSpec &
@@ -212,17 +202,13 @@ public:
UUID *
GetUUIDPtr ()
{
- if (m_uuid.IsValid())
- return &m_uuid;
- return NULL;
+ return (m_uuid.IsValid() ? &m_uuid : nullptr);
}
const UUID *
GetUUIDPtr () const
{
- if (m_uuid.IsValid())
- return &m_uuid;
- return NULL;
+ return (m_uuid.IsValid() ? &m_uuid : nullptr);
}
UUID &
@@ -306,7 +292,6 @@ public:
m_object_mod_time.Clear();
}
-
explicit operator bool () const
{
if (m_file)
@@ -329,7 +314,7 @@ public:
}
void
- Dump (Stream &strm)
+ Dump (Stream &strm) const
{
bool dumped_something = false;
if (m_file)
@@ -361,7 +346,8 @@ public:
{
if (dumped_something)
strm.PutCString(", ");
- strm.Printf("arch = %s", m_arch.GetTriple().str().c_str());
+ strm.Printf("arch = ");
+ m_arch.DumpTriple(strm);
dumped_something = true;
}
if (m_uuid.IsValid())
@@ -476,9 +462,7 @@ public:
m_specs = rhs.m_specs;
}
- ~ModuleSpecList ()
- {
- }
+ ~ModuleSpecList() = default;
ModuleSpecList &
operator = (const ModuleSpecList &rhs)
@@ -528,6 +512,7 @@ public:
{
return m_specs[i];
}
+
bool
GetModuleSpecAtIndex (size_t i, ModuleSpec &module_spec) const
{
@@ -540,8 +525,7 @@ public:
module_spec.Clear();
return false;
}
-
-
+
bool
FindMatchingModuleSpec (const ModuleSpec &module_spec, ModuleSpec &match_module_spec) const
{
@@ -620,4 +604,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_ModuleSpec_h_
+#endif // liblldb_ModuleSpec_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Opcode.h b/contrib/llvm/tools/lldb/include/lldb/Core/Opcode.h
index 57b8077..eac0746b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Opcode.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Opcode.h
@@ -16,6 +16,7 @@
// C++ Includes
// Other libraries and framework includes
#include "llvm/Support/MathExtras.h"
+
// Project includes
#include "lldb/Host/Endian.h"
#include "lldb/lldb-public.h"
@@ -23,7 +24,7 @@
namespace lldb
{
class SBInstruction;
-}
+} // namespace lldb
namespace lldb_private {
@@ -76,6 +77,7 @@ namespace lldb_private {
m_byte_order = lldb::eByteOrderInvalid;
m_type = Opcode::eTypeInvalid;
}
+
Opcode::Type
GetType () const
{
@@ -189,7 +191,7 @@ namespace lldb_private {
void
SetOpcodeBytes (const void *bytes, size_t length)
{
- if (bytes && length > 0)
+ if (bytes != nullptr && length > 0)
{
m_type = eTypeBytes;
m_data.inst.length = length;
@@ -210,9 +212,7 @@ namespace lldb_private {
const void *
GetOpcodeBytes () const
{
- if (m_type == Opcode::eTypeBytes)
- return m_data.inst.bytes;
- return NULL;
+ return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr);
}
uint32_t
@@ -252,7 +252,7 @@ namespace lldb_private {
case Opcode::eType64: return &m_data.inst64;
case Opcode::eTypeBytes: return m_data.inst.bytes;
}
- return NULL;
+ return nullptr;
}
lldb::ByteOrder
@@ -261,8 +261,8 @@ namespace lldb_private {
bool
GetEndianSwap() const
{
- return (m_byte_order == lldb::eByteOrderBig && lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle) ||
- (m_byte_order == lldb::eByteOrderLittle && lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig);
+ return (m_byte_order == lldb::eByteOrderBig && endian::InlHostByteOrder() == lldb::eByteOrderLittle) ||
+ (m_byte_order == lldb::eByteOrderLittle && endian::InlHostByteOrder() == lldb::eByteOrderBig);
}
lldb::ByteOrder m_byte_order;
@@ -284,4 +284,4 @@ namespace lldb_private {
} // namespace lldb_private
-#endif // lldb_Opcode_h
+#endif // lldb_Opcode_h
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/PluginManager.h b/contrib/llvm/tools/lldb/include/lldb/Core/PluginManager.h
index af940d7..6f8001f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/PluginManager.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/PluginManager.h
@@ -7,10 +7,13 @@
//
//===----------------------------------------------------------------------===//
-
#ifndef liblldb_PluginManager_h_
#define liblldb_PluginManager_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Host/FileSpec.h"
@@ -42,7 +45,6 @@ public:
static ABICreateInstance
GetABICreateCallbackForPluginName (const ConstString &name);
-
//------------------------------------------------------------------
// Disassembler
//------------------------------------------------------------------
@@ -60,15 +62,14 @@ public:
static DisassemblerCreateInstance
GetDisassemblerCreateCallbackForPluginName (const ConstString &name);
-
//------------------------------------------------------------------
// DynamicLoader
//------------------------------------------------------------------
static bool
- RegisterPlugin (const ConstString &name,
- const char *description,
- DynamicLoaderCreateInstance create_callback,
- DebuggerInitializeCallback debugger_init_callback = NULL);
+ RegisterPlugin(const ConstString &name,
+ const char *description,
+ DynamicLoaderCreateInstance create_callback,
+ DebuggerInitializeCallback debugger_init_callback = nullptr);
static bool
UnregisterPlugin (DynamicLoaderCreateInstance create_callback);
@@ -83,10 +84,10 @@ public:
// JITLoader
//------------------------------------------------------------------
static bool
- RegisterPlugin (const ConstString &name,
- const char *description,
- JITLoaderCreateInstance create_callback,
- DebuggerInitializeCallback debugger_init_callback = NULL);
+ RegisterPlugin(const ConstString &name,
+ const char *description,
+ JITLoaderCreateInstance create_callback,
+ DebuggerInitializeCallback debugger_init_callback = nullptr);
static bool
UnregisterPlugin (JITLoaderCreateInstance create_callback);
@@ -117,11 +118,10 @@ public:
//------------------------------------------------------------------
// OperatingSystem
//------------------------------------------------------------------
- static bool
- RegisterPlugin (const ConstString &name,
- const char *description,
- OperatingSystemCreateInstance create_callback);
-
+ static bool RegisterPlugin(const ConstString &name, const char *description,
+ OperatingSystemCreateInstance create_callback,
+ DebuggerInitializeCallback debugger_init_callback);
+
static bool
UnregisterPlugin (OperatingSystemCreateInstance create_callback);
@@ -132,6 +132,23 @@ public:
GetOperatingSystemCreateCallbackForPluginName (const ConstString &name);
//------------------------------------------------------------------
+ // Language
+ //------------------------------------------------------------------
+ static bool
+ RegisterPlugin (const ConstString &name,
+ const char *description,
+ LanguageCreateInstance create_callback);
+
+ static bool
+ UnregisterPlugin (LanguageCreateInstance create_callback);
+
+ static LanguageCreateInstance
+ GetLanguageCreateCallbackAtIndex (uint32_t idx);
+
+ static LanguageCreateInstance
+ GetLanguageCreateCallbackForPluginName (const ConstString &name);
+
+ //------------------------------------------------------------------
// LanguageRuntime
//------------------------------------------------------------------
static bool
@@ -152,7 +169,6 @@ public:
static LanguageRuntimeCreateInstance
GetLanguageRuntimeCreateCallbackForPluginName (const ConstString &name);
-
//------------------------------------------------------------------
// SystemRuntime
//------------------------------------------------------------------
@@ -170,17 +186,16 @@ public:
static SystemRuntimeCreateInstance
GetSystemRuntimeCreateCallbackForPluginName (const ConstString &name);
-
//------------------------------------------------------------------
// ObjectFile
//------------------------------------------------------------------
static bool
- RegisterPlugin (const ConstString &name,
- const char *description,
- ObjectFileCreateInstance create_callback,
- ObjectFileCreateMemoryInstance create_memory_callback,
- ObjectFileGetModuleSpecifications get_module_specifications,
- ObjectFileSaveCore save_core = NULL);
+ RegisterPlugin(const ConstString &name,
+ const char *description,
+ ObjectFileCreateInstance create_callback,
+ ObjectFileCreateMemoryInstance create_memory_callback,
+ ObjectFileGetModuleSpecifications get_module_specifications,
+ ObjectFileSaveCore save_core = nullptr);
static bool
UnregisterPlugin (ObjectFileCreateInstance create_callback);
@@ -248,10 +263,10 @@ public:
// Platform
//------------------------------------------------------------------
static bool
- RegisterPlugin (const ConstString &name,
- const char *description,
- PlatformCreateInstance create_callback,
- DebuggerInitializeCallback debugger_init_callback = NULL);
+ RegisterPlugin(const ConstString &name,
+ const char *description,
+ PlatformCreateInstance create_callback,
+ DebuggerInitializeCallback debugger_init_callback = nullptr);
static bool
UnregisterPlugin (PlatformCreateInstance create_callback);
@@ -275,10 +290,10 @@ public:
// Process
//------------------------------------------------------------------
static bool
- RegisterPlugin (const ConstString &name,
- const char *description,
- ProcessCreateInstance create_callback,
- DebuggerInitializeCallback debugger_init_callback = NULL);
+ RegisterPlugin(const ConstString &name,
+ const char *description,
+ ProcessCreateInstance create_callback,
+ DebuggerInitializeCallback debugger_init_callback = nullptr);
static bool
UnregisterPlugin (ProcessCreateInstance create_callback);
@@ -296,12 +311,30 @@ public:
GetProcessPluginDescriptionAtIndex (uint32_t idx);
//------------------------------------------------------------------
+ // ScriptInterpreter
+ //------------------------------------------------------------------
+ static bool
+ RegisterPlugin(const ConstString &name, const char *description, lldb::ScriptLanguage script_lang,
+ ScriptInterpreterCreateInstance create_callback);
+
+ static bool
+ UnregisterPlugin(ScriptInterpreterCreateInstance create_callback);
+
+ static ScriptInterpreterCreateInstance
+ GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx);
+
+ static lldb::ScriptInterpreterSP
+ GetScriptInterpreterForLanguage(lldb::ScriptLanguage script_lang,
+ CommandInterpreter &interpreter);
+
+ //------------------------------------------------------------------
// SymbolFile
//------------------------------------------------------------------
static bool
RegisterPlugin (const ConstString &name,
const char *description,
- SymbolFileCreateInstance create_callback);
+ SymbolFileCreateInstance create_callback,
+ DebuggerInitializeCallback debugger_init_callback = nullptr);
static bool
UnregisterPlugin (SymbolFileCreateInstance create_callback);
@@ -312,7 +345,6 @@ public:
static SymbolFileCreateInstance
GetSymbolFileCreateCallbackForPluginName (const ConstString &name);
-
//------------------------------------------------------------------
// SymbolVendor
//------------------------------------------------------------------
@@ -385,6 +417,53 @@ public:
static InstrumentationRuntimeCreateInstance
GetInstrumentationRuntimeCreateCallbackForPluginName (const ConstString &name);
+ //------------------------------------------------------------------
+ // TypeSystem
+ //------------------------------------------------------------------
+ static bool
+ RegisterPlugin (const ConstString &name,
+ const char *description,
+ TypeSystemCreateInstance create_callback,
+ TypeSystemEnumerateSupportedLanguages enumerate_languages_callback);
+
+ static bool
+ UnregisterPlugin (TypeSystemCreateInstance create_callback);
+
+ static TypeSystemCreateInstance
+ GetTypeSystemCreateCallbackAtIndex (uint32_t idx);
+
+ static TypeSystemCreateInstance
+ GetTypeSystemCreateCallbackForPluginName (const ConstString &name);
+
+ static TypeSystemEnumerateSupportedLanguages
+ GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx);
+
+ static TypeSystemEnumerateSupportedLanguages
+ GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name);
+
+ //------------------------------------------------------------------
+ // REPL
+ //------------------------------------------------------------------
+ static bool
+ RegisterPlugin (const ConstString &name,
+ const char *description,
+ REPLCreateInstance create_callback,
+ REPLEnumerateSupportedLanguages enumerate_languages_callback);
+
+ static bool
+ UnregisterPlugin (REPLCreateInstance create_callback);
+
+ static REPLCreateInstance
+ GetREPLCreateCallbackAtIndex (uint32_t idx);
+
+ static REPLCreateInstance
+ GetREPLCreateCallbackForPluginName (const ConstString &name);
+
+ static REPLEnumerateSupportedLanguages
+ GetREPLEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx);
+
+ static REPLEnumerateSupportedLanguages
+ GetREPLSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name);
//------------------------------------------------------------------
// Some plug-ins might register a DebuggerInitializeCallback
@@ -419,16 +498,41 @@ public:
static lldb::OptionValuePropertiesSP
GetSettingForProcessPlugin (Debugger &debugger,
const ConstString &setting_name);
-
+
static bool
CreateSettingForProcessPlugin (Debugger &debugger,
const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description,
bool is_global_property);
-};
+ static lldb::OptionValuePropertiesSP
+ GetSettingForSymbolFilePlugin (Debugger &debugger,
+ const ConstString &setting_name);
+
+ static bool
+ CreateSettingForSymbolFilePlugin (Debugger &debugger,
+ const lldb::OptionValuePropertiesSP &properties_sp,
+ const ConstString &description,
+ bool is_global_property);
+
+ static lldb::OptionValuePropertiesSP
+ GetSettingForJITLoaderPlugin (Debugger &debugger,
+ const ConstString &setting_name);
+ static bool
+ CreateSettingForJITLoaderPlugin (Debugger &debugger,
+ const lldb::OptionValuePropertiesSP &properties_sp,
+ const ConstString &description,
+ bool is_global_property);
+
+ static lldb::OptionValuePropertiesSP GetSettingForOperatingSystemPlugin(Debugger &debugger,
+ const ConstString &setting_name);
+
+ static bool CreateSettingForOperatingSystemPlugin(Debugger &debugger,
+ const lldb::OptionValuePropertiesSP &properties_sp,
+ const ConstString &description, bool is_global_property);
+};
} // namespace lldb_private
-#endif // liblldb_PluginManager_h_
+#endif // liblldb_PluginManager_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h b/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h
index d2c43a5..b2e3f06 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h
@@ -10,16 +10,21 @@
#ifndef liblldb_RangeMap_h_
#define liblldb_RangeMap_h_
+// C Includes
+// C++ Includes
+#include <algorithm>
#include <vector>
-#include "lldb/lldb-private.h"
+// Other libraries and framework includes
#include "llvm/ADT/SmallVector.h"
+// Project includes
+#include "lldb/lldb-private.h"
+
// Uncomment to make sure all Range objects are sorted when needed
//#define ASSERT_RANGEMAP_ARE_SORTED
namespace lldb_private {
-
//----------------------------------------------------------------------
// Templatized classes for dealing with generic ranges and also
@@ -187,16 +192,11 @@ namespace lldb_private {
typedef S SizeType;
typedef Range<B,S> Entry;
typedef llvm::SmallVector<Entry, N> Collection;
-
- RangeArray () :
- m_entries ()
- {
- }
-
- ~RangeArray()
- {
- }
-
+
+ RangeArray() = default;
+
+ ~RangeArray() = default;
+
void
Append (const Entry &entry)
{
@@ -236,6 +236,7 @@ namespace lldb_private {
return true;
}
#endif
+
void
CombineConsecutiveRanges ()
{
@@ -281,7 +282,6 @@ namespace lldb_private {
}
}
-
BaseType
GetMinRangeBase (BaseType fail_value) const
{
@@ -337,9 +337,7 @@ namespace lldb_private {
const Entry *
GetEntryAtIndex (size_t i) const
{
- if (i<m_entries.size())
- return &m_entries[i];
- return NULL;
+ return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
}
// Clients must ensure that "i" is a valid index prior to calling this function
@@ -352,17 +350,13 @@ namespace lldb_private {
Entry *
Back()
{
- if (m_entries.empty())
- return NULL;
- return &m_entries.back();
+ return (m_entries.empty() ? nullptr : &m_entries.back());
}
const Entry *
Back() const
{
- if (m_entries.empty())
- return NULL;
- return &m_entries.back();
+ return (m_entries.empty() ? nullptr : &m_entries.back());
}
static bool
@@ -424,7 +418,7 @@ namespace lldb_private {
}
}
}
- return NULL;
+ return nullptr;
}
const Entry *
@@ -452,7 +446,7 @@ namespace lldb_private {
}
}
}
- return NULL;
+ return nullptr;
}
protected:
@@ -467,16 +461,11 @@ namespace lldb_private {
typedef S SizeType;
typedef Range<B,S> Entry;
typedef std::vector<Entry> Collection;
-
- RangeVector () :
- m_entries ()
- {
- }
-
- ~RangeVector()
- {
- }
-
+
+ RangeVector() = default;
+
+ ~RangeVector() = default;
+
void
Append (const Entry &entry)
{
@@ -516,6 +505,7 @@ namespace lldb_private {
return true;
}
#endif
+
void
CombineConsecutiveRanges ()
{
@@ -560,8 +550,7 @@ namespace lldb_private {
}
}
}
-
-
+
BaseType
GetMinRangeBase (BaseType fail_value) const
{
@@ -623,9 +612,7 @@ namespace lldb_private {
const Entry *
GetEntryAtIndex (size_t i) const
{
- if (i<m_entries.size())
- return &m_entries[i];
- return NULL;
+ return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
}
// Clients must ensure that "i" is a valid index prior to calling this function
@@ -638,17 +625,13 @@ namespace lldb_private {
Entry *
Back()
{
- if (m_entries.empty())
- return NULL;
- return &m_entries.back();
+ return (m_entries.empty() ? nullptr : &m_entries.back());
}
const Entry *
Back() const
{
- if (m_entries.empty())
- return NULL;
- return &m_entries.back();
+ return (m_entries.empty() ? nullptr : &m_entries.back());
}
static bool
@@ -710,7 +693,7 @@ namespace lldb_private {
}
}
}
- return NULL;
+ return nullptr;
}
const Entry *
@@ -738,7 +721,7 @@ namespace lldb_private {
}
}
}
- return NULL;
+ return nullptr;
}
protected:
@@ -812,15 +795,10 @@ namespace lldb_private {
typedef RangeData<B,S,T> Entry;
typedef llvm::SmallVector<Entry, N> Collection;
+ RangeDataArray() = default;
+
+ ~RangeDataArray() = default;
- RangeDataArray ()
- {
- }
-
- ~RangeDataArray()
- {
- }
-
void
Append (const Entry &entry)
{
@@ -911,9 +889,7 @@ namespace lldb_private {
const Entry *
GetEntryAtIndex (size_t i) const
{
- if (i<m_entries.size())
- return &m_entries[i];
- return NULL;
+ return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
}
// Clients must ensure that "i" is a valid index prior to calling this function
@@ -984,8 +960,9 @@ namespace lldb_private {
}
}
}
- return NULL;
+ return nullptr;
}
+
const Entry *
FindEntryThatContains (B addr) const
{
@@ -1014,7 +991,7 @@ namespace lldb_private {
}
}
}
- return NULL;
+ return nullptr;
}
const Entry *
@@ -1042,23 +1019,19 @@ namespace lldb_private {
}
}
}
- return NULL;
+ return nullptr;
}
Entry *
Back()
{
- if (!m_entries.empty())
- return &m_entries.back();
- return NULL;
+ return (m_entries.empty() ? nullptr : &m_entries.back());
}
const Entry *
Back() const
{
- if (!m_entries.empty())
- return &m_entries.back();
- return NULL;
+ return (m_entries.empty() ? nullptr : &m_entries.back());
}
protected:
@@ -1073,15 +1046,11 @@ namespace lldb_private {
public:
typedef RangeData<B,S,T> Entry;
typedef std::vector<Entry> Collection;
-
- RangeDataVector ()
- {
- }
-
- ~RangeDataVector()
- {
- }
-
+
+ RangeDataVector() = default;
+
+ ~RangeDataVector() = default;
+
void
Append (const Entry &entry)
{
@@ -1181,7 +1150,6 @@ namespace lldb_private {
}
}
}
-
}
void
@@ -1211,9 +1179,7 @@ namespace lldb_private {
const Entry *
GetEntryAtIndex (size_t i) const
{
- if (i<m_entries.size())
- return &m_entries[i];
- return NULL;
+ return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
}
// Clients must ensure that "i" is a valid index prior to calling this function
@@ -1272,8 +1238,9 @@ namespace lldb_private {
if (pos != end && pos->Contains(addr))
return &(*pos);
}
- return NULL;
+ return nullptr;
}
+
const Entry *
FindEntryThatContains (B addr) const
{
@@ -1295,7 +1262,7 @@ namespace lldb_private {
if (pos != end && pos->Contains(addr))
return &(*pos);
}
- return NULL;
+ return nullptr;
}
const Entry *
@@ -1316,30 +1283,25 @@ namespace lldb_private {
if (pos != end && pos->Contains(range))
return &(*pos);
}
- return NULL;
+ return nullptr;
}
Entry *
Back()
{
- if (!m_entries.empty())
- return &m_entries.back();
- return NULL;
+ return (m_entries.empty() ? nullptr : &m_entries.back());
}
const Entry *
Back() const
{
- if (!m_entries.empty())
- return &m_entries.back();
- return NULL;
+ return (m_entries.empty() ? nullptr : &m_entries.back());
}
protected:
Collection m_entries;
};
-
-
+
//----------------------------------------------------------------------
// A simple range with data class where you get to define the type of
// the range base "B", the type used for the range byte size "S", and
@@ -1389,7 +1351,6 @@ namespace lldb_private {
}
};
-
template <typename B, typename T, unsigned N>
class AddressDataArray
{
@@ -1397,15 +1358,10 @@ namespace lldb_private {
typedef AddressData<B,T> Entry;
typedef llvm::SmallVector<Entry, N> Collection;
+ AddressDataArray() = default;
+
+ ~AddressDataArray() = default;
- AddressDataArray ()
- {
- }
-
- ~AddressDataArray()
- {
- }
-
void
Append (const Entry &entry)
{
@@ -1456,9 +1412,7 @@ namespace lldb_private {
const Entry *
GetEntryAtIndex (size_t i) const
{
- if (i<m_entries.size())
- return &m_entries[i];
- return NULL;
+ return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
}
// Clients must ensure that "i" is a valid index prior to calling this function
@@ -1497,7 +1451,7 @@ namespace lldb_private {
return &(*pos);
}
}
- return NULL;
+ return nullptr;
}
const Entry *
@@ -1505,23 +1459,19 @@ namespace lldb_private {
{
if (entry >= &*m_entries.begin() && entry + 1 < &*m_entries.end())
return entry + 1;
- return NULL;
+ return nullptr;
}
Entry *
Back()
{
- if (!m_entries.empty())
- return &m_entries.back();
- return NULL;
+ return (m_entries.empty() ? nullptr : &m_entries.back());
}
const Entry *
Back() const
{
- if (!m_entries.empty())
- return &m_entries.back();
- return NULL;
+ return (m_entries.empty() ? nullptr : &m_entries.back());
}
protected:
@@ -1530,4 +1480,4 @@ namespace lldb_private {
} // namespace lldb_private
-#endif // liblldb_RangeMap_h_
+#endif // liblldb_RangeMap_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/RegisterValue.h b/contrib/llvm/tools/lldb/include/lldb/Core/RegisterValue.h
index 1b1a71a..030b849 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/RegisterValue.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/RegisterValue.h
@@ -1,4 +1,4 @@
-//===-- RegisterValue.h ------------------------------------------*- C++ -*-===//
+//===-- RegisterValue.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,12 +15,14 @@
// C++ Includes
// Other libraries and framework includes
+#include "llvm/ADT/APInt.h"
+
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/lldb-private.h"
#include "lldb/Host/Endian.h"
+#include "lldb/Core/Scalar.h"
-//#define ENABLE_128_BIT_SUPPORT 1
namespace lldb_private {
class RegisterValue
@@ -30,6 +32,7 @@ namespace lldb_private {
{
kMaxRegisterByteSize = 32u
};
+
enum Type
{
eTypeInvalid,
@@ -37,9 +40,7 @@ namespace lldb_private {
eTypeUInt16,
eTypeUInt32,
eTypeUInt64,
-#if defined (ENABLE_128_BIT_SUPPORT)
eTypeUInt128,
-#endif
eTypeFloat,
eTypeDouble,
eTypeLongDouble,
@@ -47,7 +48,8 @@ namespace lldb_private {
};
RegisterValue () :
- m_type (eTypeInvalid)
+ m_type (eTypeInvalid),
+ m_scalar ((unsigned long)0)
{
}
@@ -55,57 +57,56 @@ namespace lldb_private {
RegisterValue (uint8_t inst) :
m_type (eTypeUInt8)
{
- m_data.uint8 = inst;
+ m_scalar = inst;
}
explicit
RegisterValue (uint16_t inst) :
m_type (eTypeUInt16)
{
- m_data.uint16 = inst;
+ m_scalar = inst;
}
explicit
RegisterValue (uint32_t inst) :
m_type (eTypeUInt32)
{
- m_data.uint32 = inst;
+ m_scalar = inst;
}
explicit
RegisterValue (uint64_t inst) :
m_type (eTypeUInt64)
{
- m_data.uint64 = inst;
+ m_scalar = inst;
}
-#if defined (ENABLE_128_BIT_SUPPORT)
explicit
- RegisterValue (__uint128_t inst) :
+ RegisterValue (llvm::APInt inst) :
m_type (eTypeUInt128)
{
- m_data.uint128 = inst;
+ m_scalar = llvm::APInt(inst);
}
-#endif
+
explicit
RegisterValue (float value) :
m_type (eTypeFloat)
{
- m_data.ieee_float = value;
+ m_scalar = value;
}
explicit
RegisterValue (double value) :
m_type (eTypeDouble)
{
- m_data.ieee_double = value;
+ m_scalar = value;
}
explicit
RegisterValue (long double value) :
m_type (eTypeLongDouble)
{
- m_data.ieee_long_double = value;
+ m_scalar = value;
}
explicit
@@ -161,13 +162,13 @@ namespace lldb_private {
GetScalarValue (Scalar &scalar) const;
uint8_t
- GetAsUInt8 (uint8_t fail_value = UINT8_MAX, bool *success_ptr = NULL) const
+ GetAsUInt8(uint8_t fail_value = UINT8_MAX, bool *success_ptr = nullptr) const
{
if (m_type == eTypeUInt8)
{
if (success_ptr)
*success_ptr = true;
- return m_data.uint8;
+ return m_scalar.UChar(fail_value);
}
if (success_ptr)
*success_ptr = true;
@@ -175,27 +176,25 @@ namespace lldb_private {
}
uint16_t
- GetAsUInt16 (uint16_t fail_value = UINT16_MAX, bool *success_ptr = NULL) const;
+ GetAsUInt16(uint16_t fail_value = UINT16_MAX, bool *success_ptr = nullptr) const;
uint32_t
- GetAsUInt32 (uint32_t fail_value = UINT32_MAX, bool *success_ptr = NULL) const;
+ GetAsUInt32(uint32_t fail_value = UINT32_MAX, bool *success_ptr = nullptr) const;
uint64_t
- GetAsUInt64 (uint64_t fail_value = UINT64_MAX, bool *success_ptr = NULL) const;
+ GetAsUInt64(uint64_t fail_value = UINT64_MAX, bool *success_ptr = nullptr) const;
-#if defined (ENABLE_128_BIT_SUPPORT)
- __uint128_t
- GetAsUInt128 (__uint128_t fail_value = ~((__uint128_t)0), bool *success_ptr = NULL) const;
-#endif
+ llvm::APInt
+ GetAsUInt128(const llvm::APInt& fail_value, bool *success_ptr = nullptr) const;
float
- GetAsFloat (float fail_value = 0.0f, bool *success_ptr = NULL) const;
+ GetAsFloat(float fail_value = 0.0f, bool *success_ptr = nullptr) const;
double
- GetAsDouble (double fail_value = 0.0, bool *success_ptr = NULL) const;
+ GetAsDouble(double fail_value = 0.0, bool *success_ptr = nullptr) const;
long double
- GetAsLongDouble (long double fail_value = 0.0, bool *success_ptr = NULL) const;
+ GetAsLongDouble(long double fail_value = 0.0, bool *success_ptr = nullptr) const;
void
SetValueToInvalid ()
@@ -219,95 +218,93 @@ namespace lldb_private {
operator = (uint8_t uint)
{
m_type = eTypeUInt8;
- m_data.uint8 = uint;
+ m_scalar = uint;
}
void
operator = (uint16_t uint)
{
m_type = eTypeUInt16;
- m_data.uint16 = uint;
+ m_scalar = uint;
}
void
operator = (uint32_t uint)
{
m_type = eTypeUInt32;
- m_data.uint32 = uint;
+ m_scalar = uint;
}
void
operator = (uint64_t uint)
{
m_type = eTypeUInt64;
- m_data.uint64 = uint;
+ m_scalar = uint;
}
-#if defined (ENABLE_128_BIT_SUPPORT)
void
- operator = (__uint128_t uint)
+ operator = (llvm::APInt uint)
{
m_type = eTypeUInt128;
- m_data.uint128 = uint;
+ m_scalar = llvm::APInt(uint);
}
-#endif
+
void
operator = (float f)
{
m_type = eTypeFloat;
- m_data.ieee_float = f;
+ m_scalar = f;
}
void
operator = (double f)
{
m_type = eTypeDouble;
- m_data.ieee_double = f;
+ m_scalar = f;
}
void
operator = (long double f)
{
m_type = eTypeLongDouble;
- m_data.ieee_long_double = f;
+ m_scalar = f;
}
void
SetUInt8 (uint8_t uint)
{
m_type = eTypeUInt8;
- m_data.uint8 = uint;
+ m_scalar = uint;
}
void
SetUInt16 (uint16_t uint)
{
m_type = eTypeUInt16;
- m_data.uint16 = uint;
+ m_scalar = uint;
}
void
SetUInt32 (uint32_t uint, Type t = eTypeUInt32)
{
m_type = t;
- m_data.uint32 = uint;
+ m_scalar = uint;
}
void
SetUInt64 (uint64_t uint, Type t = eTypeUInt64)
{
m_type = t;
- m_data.uint64 = uint;
+ m_scalar = uint;
}
-#if defined (ENABLE_128_BIT_SUPPORT)
void
- SetUInt128 (__uint128_t uint)
+ SetUInt128 (llvm::APInt uint)
{
m_type = eTypeUInt128;
- m_data.uint128 = uint;
+ m_scalar = uint;
}
-#endif
+
bool
SetUInt (uint64_t uint, uint32_t byte_size);
@@ -315,21 +312,21 @@ namespace lldb_private {
SetFloat (float f)
{
m_type = eTypeFloat;
- m_data.ieee_float = f;
+ m_scalar = f;
}
void
SetDouble (double f)
{
m_type = eTypeDouble;
- m_data.ieee_double = f;
+ m_scalar = f;
}
void
SetLongDouble (long double f)
{
m_type = eTypeLongDouble;
- m_data.ieee_long_double = f;
+ m_scalar = f;
}
void
@@ -367,8 +364,8 @@ namespace lldb_private {
GetByteOrder () const
{
if (m_type == eTypeBytes)
- return m_data.buffer.byte_order;
- return lldb::endian::InlHostByteOrder();
+ return buffer.byte_order;
+ return endian::InlHostByteOrder();
}
uint32_t
@@ -384,29 +381,17 @@ namespace lldb_private {
Clear();
protected:
-
RegisterValue::Type m_type;
- union
- {
- uint8_t uint8;
- uint16_t uint16;
- uint32_t uint32;
- uint64_t uint64;
-#if defined (ENABLE_128_BIT_SUPPORT)
- __uint128_t uint128;
-#endif
- float ieee_float;
- double ieee_double;
- long double ieee_long_double;
- struct
- {
- uint8_t bytes[kMaxRegisterByteSize]; // This must be big enough to hold any register for any supported target.
- uint8_t length;
- lldb::ByteOrder byte_order;
- } buffer;
- } m_data;
+ Scalar m_scalar;
+
+ struct
+ {
+ uint8_t bytes[kMaxRegisterByteSize]; // This must be big enough to hold any register for any supported target.
+ uint8_t length;
+ lldb::ByteOrder byte_order;
+ } buffer;
};
} // namespace lldb_private
-#endif // lldb_RegisterValue_h
+#endif // lldb_RegisterValue_h
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/RegularExpression.h b/contrib/llvm/tools/lldb/include/lldb/Core/RegularExpression.h
index a58d17b..b0ece51 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/RegularExpression.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/RegularExpression.h
@@ -7,9 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_DBRegex_h_
-#define liblldb_DBRegex_h_
-#if defined(__cplusplus)
+#ifndef liblldb_RegularExpression_h_
+#define liblldb_RegularExpression_h_
#ifdef _WIN32
#include "../lib/Support/regex_impl.h"
@@ -37,7 +36,6 @@ inline void regfree(llvm_regex_t * a)
{
llvm_regfree(a);
}
-
#else
#if __ANDROID_NDK__
#include <regex>
@@ -52,7 +50,7 @@ inline void regfree(llvm_regex_t * a)
namespace llvm
{
class StringRef;
-}
+} // namespace llvm
namespace lldb_private {
@@ -95,9 +93,7 @@ public:
regmatch_t *
GetData ()
{
- if (m_matches.empty())
- return NULL;
- return m_matches.data();
+ return (m_matches.empty() ? nullptr : m_matches.data());
}
bool
@@ -110,9 +106,9 @@ public:
GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const;
protected:
-
std::vector<regmatch_t> m_matches; ///< Where parenthesized subexpressions results are stored
};
+
//------------------------------------------------------------------
/// Default constructor.
///
@@ -172,14 +168,14 @@ public:
/// @param[in] match
/// A pointer to a RegularExpression::Match structure that was
/// properly initialized with the desired number of maximum
- /// matches, or NULL if no parenthesized matching is needed.
+ /// matches, or nullptr if no parenthesized matching is needed.
///
/// @return
/// \b true if \a string matches the compiled regular
/// expression, \b false otherwise.
//------------------------------------------------------------------
bool
- Execute (const char* string, Match *match = NULL) const;
+ Execute(const char* string, Match *match = nullptr) const;
size_t
GetErrorAsCString (char *err_str, size_t err_str_max_len) const;
@@ -246,5 +242,4 @@ private:
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif // liblldb_DBRegex_h_
+#endif // liblldb_RegularExpression_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/STLUtils.h b/contrib/llvm/tools/lldb/include/lldb/Core/STLUtils.h
index 9321e05..b3c2124 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/STLUtils.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/STLUtils.h
@@ -9,14 +9,18 @@
#ifndef liblldb_STLUtils_h_
#define liblldb_STLUtils_h_
-#if defined(__cplusplus)
+// C Includes
#include <string.h>
+// C++ Includes
#include <map>
#include <ostream>
#include <vector>
+// Other libraries and framework includes
+// Project includes
+
//----------------------------------------------------------------------
// C string less than compare function object
//----------------------------------------------------------------------
@@ -28,7 +32,6 @@ struct CStringCompareFunctionObject
}
};
-
//----------------------------------------------------------------------
// C string equality function object (binary predicate).
//----------------------------------------------------------------------
@@ -40,7 +43,6 @@ struct CStringEqualBinaryPredicate
}
};
-
//----------------------------------------------------------------------
// Templated type for finding an entry in a std::map<F,S> whose value
// is equal to something
@@ -48,21 +50,26 @@ struct CStringEqualBinaryPredicate
template <class F, class S>
class ValueEquals
{
-private:
- S second_value;
-
public:
ValueEquals (const S& val) : second_value(val)
{}
+
// Compare the second item
bool operator() (std::pair<const F, S> elem)
{
return elem.second == second_value;
}
+
+private:
+ S second_value;
};
template <class T>
-inline void PrintAllCollectionElements (std::ostream &s, const T& coll, const char* header_cstr=NULL, const char* separator_cstr=" ")
+inline void
+PrintAllCollectionElements(std::ostream &s,
+ const T& coll,
+ const char* header_cstr = nullptr,
+ const char* separator_cstr = " ")
{
typename T::const_iterator pos;
@@ -88,7 +95,4 @@ struct for_each_cplusplus_delete
typedef std::vector<std::string> STLStringArray;
typedef std::vector<const char *> CStringArray;
-
-
-#endif // #if defined(__cplusplus)
-#endif // liblldb_STLUtils_h_
+#endif // liblldb_STLUtils_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Scalar.h b/contrib/llvm/tools/lldb/include/lldb/Core/Scalar.h
index 821a0fb..a476cd3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Scalar.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Scalar.h
@@ -11,6 +11,11 @@
#define liblldb_Scalar_h_
#include "lldb/lldb-private.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APFloat.h"
+
+#define NUM_OF_WORDS_INT128 2
+#define BITWIDTH_INT128 128
namespace lldb_private {
@@ -34,22 +39,60 @@ public:
e_ulonglong,
e_float,
e_double,
- e_long_double
+ e_long_double,
+ e_uint128,
+ e_sint128
};
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
Scalar();
- Scalar(int v) : m_type(e_sint), m_data() { m_data.sint = v; }
- Scalar(unsigned int v) : m_type(e_uint), m_data() { m_data.uint = v; }
- Scalar(long v) : m_type(e_slong), m_data() { m_data.slong = v; }
- Scalar(unsigned long v) : m_type(e_ulong), m_data() { m_data.ulong = v; }
- Scalar(long long v) : m_type(e_slonglong), m_data() { m_data.slonglong = v; }
- Scalar(unsigned long long v): m_type(e_ulonglong), m_data() { m_data.ulonglong = v; }
- Scalar(float v) : m_type(e_float), m_data() { m_data.flt = v; }
- Scalar(double v) : m_type(e_double), m_data() { m_data.dbl = v; }
- Scalar(long double v) : m_type(e_long_double), m_data() { m_data.ldbl = v; }
+ Scalar(int v) : m_type(e_sint), m_float((float)0) { m_integer = llvm::APInt(sizeof(int) * 8, v, true);}
+ Scalar(unsigned int v) : m_type(e_uint), m_float((float)0) { m_integer = llvm::APInt(sizeof(int) * 8, v);}
+ Scalar(long v) : m_type(e_slong), m_float((float)0) { m_integer = llvm::APInt(sizeof(long) * 8, v, true);}
+ Scalar(unsigned long v) : m_type(e_ulong), m_float((float)0) { m_integer = llvm::APInt(sizeof(long) * 8, v);}
+ Scalar(long long v) : m_type(e_slonglong), m_float((float)0) { m_integer = llvm::APInt(sizeof(long long) * 8, v, true);}
+ Scalar(unsigned long long v): m_type(e_ulonglong), m_float((float)0) { m_integer = llvm::APInt(sizeof(long long) * 8, v);}
+ Scalar(float v) : m_type(e_float), m_float(v) { m_float = llvm::APFloat(v); }
+ Scalar(double v) : m_type(e_double), m_float(v) { m_float = llvm::APFloat(v); }
+ Scalar(long double v, bool ieee_quad)
+ : m_type(e_long_double), m_float((float)0), m_ieee_quad(ieee_quad)
+ {
+ if(ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x));
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x));
+ }
+ Scalar(llvm::APInt v) :
+ m_type(),
+ m_float((float)0)
+ {
+ m_integer = llvm::APInt(v);
+ switch(m_integer.getBitWidth())
+ {
+ case 8:
+ case 16:
+ case 32:
+ if(m_integer.isSignedIntN(sizeof(sint_t) * 8))
+ m_type = e_sint;
+ else
+ m_type = e_uint;
+ break;
+ case 64:
+ if(m_integer.isSignedIntN(sizeof(slonglong_t) * 8))
+ m_type = e_slonglong;
+ else
+ m_type = e_ulonglong;
+ break;
+ case 128:
+ if(m_integer.isSignedIntN(BITWIDTH_INT128))
+ m_type = e_sint128;
+ else
+ m_type = e_uint128;
+ break;
+ }
+ }
Scalar(const Scalar& rhs);
//Scalar(const RegisterValue& reg_value);
virtual ~Scalar();
@@ -61,15 +104,18 @@ public:
ExtractBitfield (uint32_t bit_size,
uint32_t bit_offset);
+ bool
+ SetBit(uint32_t bit);
+
+ bool
+ ClearBit(uint32_t bit);
+
+ void *
+ GetBytes() const;
+
size_t
GetByteSize() const;
- static size_t
- GetMaxByteSize()
- {
- return sizeof(ValueData);
- }
-
bool
GetData (DataExtractor &data, size_t limit_byte_size = UINT32_MAX) const;
@@ -83,7 +129,7 @@ public:
IsZero() const;
void
- Clear() { m_type = e_void; m_data.ulonglong = 0; }
+ Clear() { m_type = e_void; m_integer.clearAllBits(); }
const char *
GetTypeAsCString() const;
@@ -133,6 +179,7 @@ public:
Scalar& operator= (float v);
Scalar& operator= (double v);
Scalar& operator= (long double v);
+ Scalar& operator= (llvm::APInt v);
Scalar& operator= (const Scalar& rhs); // Assignment operator
Scalar& operator+= (const Scalar& rhs);
Scalar& operator<<= (const Scalar& rhs); // Shift left
@@ -174,6 +221,9 @@ public:
Scalar::Type
GetType() const { return m_type; }
+ void
+ SetType(const RegisterInfo*);
+
//----------------------------------------------------------------------
// Returns a casted value of the current contained data without
// modifying the current value. FAIL_VALUE will be returned if the type
@@ -194,6 +244,18 @@ public:
unsigned long long
RawULongLong () const;
+ unsigned char
+ UChar(unsigned char fail_value = 0) const;
+
+ char
+ SChar(char fail_value = 0) const;
+
+ unsigned short
+ UShort(unsigned short fail_value = 0) const;
+
+ short
+ SShort(short fail_value = 0) const;
+
unsigned int
UInt(unsigned int fail_value = 0) const;
@@ -209,6 +271,12 @@ public:
unsigned long long
ULongLong(unsigned long long fail_value = 0) const;
+ llvm::APInt
+ SInt128(llvm::APInt& fail_value) const;
+
+ llvm::APInt
+ UInt128(const llvm::APInt& fail_value) const;
+
float
Float(float fail_value = 0.0f) const;
@@ -255,6 +323,10 @@ public:
}
protected:
+ typedef char schar_t;
+ typedef unsigned char uchar_t;
+ typedef short sshort_t;
+ typedef unsigned short ushort_t;
typedef int sint_t;
typedef unsigned int uint_t;
typedef long slong_t;
@@ -265,24 +337,13 @@ protected:
typedef double double_t;
typedef long double long_double_t;
- union ValueData
- {
- int sint;
- unsigned int uint;
- long slong;
- unsigned long ulong;
- long long slonglong;
- unsigned long long ulonglong;
- float flt;
- double dbl;
- long double ldbl;
- };
-
//------------------------------------------------------------------
// Classes that inherit from Scalar can see and modify these
//------------------------------------------------------------------
Scalar::Type m_type;
- ValueData m_data;
+ llvm::APInt m_integer;
+ llvm::APFloat m_float;
+ bool m_ieee_quad = false;
private:
friend const Scalar operator+ (const Scalar& lhs, const Scalar& rhs);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/SearchFilter.h b/contrib/llvm/tools/lldb/include/lldb/Core/SearchFilter.h
index bbb7509..3d5e1fb 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/SearchFilter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/SearchFilter.h
@@ -272,7 +272,7 @@ class SearchFilterForUnconstrainedSearches :
{
public:
SearchFilterForUnconstrainedSearches (const lldb::TargetSP &target_sp) : SearchFilter(target_sp) {}
- ~SearchFilterForUnconstrainedSearches () {}
+ ~SearchFilterForUnconstrainedSearches() override = default;
bool
ModulePasses (const FileSpec &module_spec) override;
@@ -283,7 +283,6 @@ public:
protected:
lldb::SearchFilterSP
DoCopyForBreakpoint (Breakpoint &breakpoint) override;
-
};
//----------------------------------------------------------------------
@@ -311,8 +310,7 @@ public:
SearchFilterByModule (const SearchFilterByModule& rhs);
- virtual
- ~SearchFilterByModule ();
+ ~SearchFilterByModule() override;
const SearchFilterByModule&
operator=(const SearchFilterByModule& rhs);
@@ -372,8 +370,7 @@ public:
SearchFilterByModuleList (const SearchFilterByModuleList& rhs);
- virtual
- ~SearchFilterByModuleList ();
+ ~SearchFilterByModuleList() override;
const SearchFilterByModuleList&
operator=(const SearchFilterByModuleList& rhs);
@@ -409,7 +406,7 @@ protected:
lldb::SearchFilterSP
DoCopyForBreakpoint (Breakpoint &breakpoint) override;
-private:
+protected:
FileSpecList m_module_spec_list;
};
@@ -434,8 +431,7 @@ public:
SearchFilterByModuleListAndCU (const SearchFilterByModuleListAndCU& rhs);
- virtual
- ~SearchFilterByModuleListAndCU ();
+ ~SearchFilterByModuleListAndCU() override;
const SearchFilterByModuleListAndCU&
operator=(const SearchFilterByModuleListAndCU& rhs);
@@ -466,10 +462,9 @@ protected:
DoCopyForBreakpoint (Breakpoint &breakpoint) override;
private:
- FileSpecList m_module_spec_list;
FileSpecList m_cu_spec_list;
};
} // namespace lldb_private
-#endif // liblldb_SearchFilter_h_
+#endif // liblldb_SearchFilter_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Section.h b/contrib/llvm/tools/lldb/include/lldb/Core/Section.h
index 65d408e..8c92f1b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Section.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Section.h
@@ -64,9 +64,6 @@ public:
lldb::SectionSP
FindSectionContainingFileAddress (lldb::addr_t addr, uint32_t depth = UINT32_MAX) const;
- bool
- GetSectionData (const DataExtractor& module_data, DataExtractor& section_data) const;
-
// Get the number of sections in this list only
size_t
GetSize () const
@@ -288,6 +285,46 @@ public:
return m_obj_file;
}
+ //------------------------------------------------------------------
+ /// Read the section data from the object file that the section
+ /// resides in.
+ ///
+ /// @param[in] dst
+ /// Where to place the data
+ ///
+ /// @param[in] dst_len
+ /// How many bytes of section data to read
+ ///
+ /// @param[in] offset
+ /// The offset in bytes within this section's data at which to
+ /// start copying data from.
+ ///
+ /// @return
+ /// The number of bytes read from the section, or zero if the
+ /// section has no data or \a offset is not a valid offset
+ /// in this section.
+ //------------------------------------------------------------------
+ lldb::offset_t
+ GetSectionData (void *dst, lldb::offset_t dst_len, lldb::offset_t offset = 0);
+
+ //------------------------------------------------------------------
+ /// Get the shared reference to the section data from the object
+ /// file that the section resides in. No copies of the data will be
+ /// make unless the object file has been read from memory. If the
+ /// object file is on disk, it will shared the mmap data for the
+ /// entire object file.
+ ///
+ /// @param[in] data
+ /// Where to place the data, address byte size, and byte order
+ ///
+ /// @return
+ /// The number of bytes read from the section, or zero if the
+ /// section has no data or \a offset is not a valid offset
+ /// in this section.
+ //------------------------------------------------------------------
+ lldb::offset_t
+ GetSectionData (DataExtractor& data) const;
+
uint32_t GetLog2Align()
{
return m_log2align;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/SourceManager.h b/contrib/llvm/tools/lldb/include/lldb/Core/SourceManager.h
index 0f65be1..5504baf 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/SourceManager.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/SourceManager.h
@@ -13,6 +13,7 @@
// C Includes
// C++ Includes
#include <map>
+#include <memory>
#include <vector>
// Other libraries and framework includes
@@ -26,15 +27,17 @@ class SourceManager
{
public:
#ifndef SWIG
-
class File
{
- friend bool operator== (const SourceManager::File &lhs, const SourceManager::File &rhs);
+ friend bool operator== (const SourceManager::File &lhs, const SourceManager::File &rhs);
+
public:
-
File (const FileSpec &file_spec, Target *target);
~File();
+ void
+ UpdateIfNeeded ();
+
size_t
DisplaySourceLines (uint32_t line,
uint32_t context_before,
@@ -80,7 +83,6 @@ public:
GetNumLines ();
protected:
-
bool
CalculateLineOffsets (uint32_t line = UINT32_MAX);
@@ -92,20 +94,18 @@ public:
typedef std::vector<uint32_t> LineOffsets;
LineOffsets m_offsets;
};
-
#endif // SWIG
typedef std::shared_ptr<File> FileSP;
#ifndef SWIG
-
// The SourceFileCache class separates the source manager from the cache of source files, so the
// cache can be stored in the Debugger, but the source managers can be per target.
class SourceFileCache
{
public:
- SourceFileCache () {}
- ~SourceFileCache() {}
+ SourceFileCache() = default;
+ ~SourceFileCache() = default;
void AddSourceFile (const FileSP &file_sp);
FileSP FindSourceFile (const FileSpec &file_spec) const;
@@ -114,8 +114,7 @@ public:
typedef std::map <FileSpec, FileSP> FileCache;
FileCache m_file_cache;
};
-#endif
-
+#endif // SWIG
//------------------------------------------------------------------
// Constructors and Destructors
@@ -127,7 +126,6 @@ public:
~SourceManager();
-
FileSP
GetLastFile ()
{
@@ -135,28 +133,28 @@ public:
}
size_t
- DisplaySourceLinesWithLineNumbers (const FileSpec &file,
- uint32_t line,
- uint32_t context_before,
- uint32_t context_after,
- const char* current_line_cstr,
- Stream *s,
- const SymbolContextList *bp_locs = NULL);
+ DisplaySourceLinesWithLineNumbers(const FileSpec &file,
+ uint32_t line,
+ uint32_t context_before,
+ uint32_t context_after,
+ const char* current_line_cstr,
+ Stream *s,
+ const SymbolContextList *bp_locs = nullptr);
// This variant uses the last file we visited.
size_t
- DisplaySourceLinesWithLineNumbersUsingLastFile (uint32_t start_line,
- uint32_t count,
- uint32_t curr_line,
- const char* current_line_cstr,
- Stream *s,
- const SymbolContextList *bp_locs = NULL);
+ DisplaySourceLinesWithLineNumbersUsingLastFile(uint32_t start_line,
+ uint32_t count,
+ uint32_t curr_line,
+ const char* current_line_cstr,
+ Stream *s,
+ const SymbolContextList *bp_locs = nullptr);
size_t
- DisplayMoreWithLineNumbers (Stream *s,
- uint32_t count,
- bool reverse,
- const SymbolContextList *bp_locs = NULL);
+ DisplayMoreWithLineNumbers(Stream *s,
+ uint32_t count,
+ bool reverse,
+ const SymbolContextList *bp_locs = nullptr);
bool
SetDefaultFileAndLine (const FileSpec &file_spec, uint32_t line);
@@ -167,7 +165,7 @@ public:
bool
DefaultFileAndLineSet ()
{
- return (m_last_file_sp.get() != NULL);
+ return (m_last_file_sp.get() != nullptr);
}
void
@@ -181,10 +179,6 @@ public:
GetFile (const FileSpec &file_spec);
protected:
-
- //------------------------------------------------------------------
- // Classes that inherit from SourceManager can see and modify these
- //------------------------------------------------------------------
FileSP m_last_file_sp;
uint32_t m_last_line;
uint32_t m_last_count;
@@ -193,13 +187,11 @@ protected:
lldb::DebuggerWP m_debugger_wp;
private:
- //------------------------------------------------------------------
- // For SourceManager only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (SourceManager);
};
bool operator== (const SourceManager::File &lhs, const SourceManager::File &rhs);
+
} // namespace lldb_private
-#endif // liblldb_SourceManager_h_
+#endif // liblldb_SourceManager_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Stream.h b/contrib/llvm/tools/lldb/include/lldb/Core/Stream.h
index 11780aa..f784069 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Stream.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Stream.h
@@ -9,11 +9,15 @@
#ifndef liblldb_Stream_h_
#define liblldb_Stream_h_
-#if defined(__cplusplus)
+// C Includes
+#include <stdarg.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/Flags.h"
-#include <stdarg.h>
namespace lldb_private {
@@ -221,7 +225,7 @@ public:
/// in one statement.
//------------------------------------------------------------------
Stream&
- operator<< (void *p);
+ operator<< (const void *p);
//------------------------------------------------------------------
/// Output a character \a ch to the stream \a s.
@@ -353,13 +357,13 @@ public:
/// Size in bytes of the address, used for formatting.
///
/// @param[in] prefix
- /// A prefix C string. If NULL, no prefix will be output.
+ /// A prefix C string. If nullptr, no prefix will be output.
///
/// @param[in] suffix
- /// A suffix C string. If NULL, no suffix will be output.
+ /// A suffix C string. If nullptr, no suffix will be output.
//------------------------------------------------------------------
void
- Address (uint64_t addr, uint32_t addr_size, const char *prefix = NULL, const char *suffix = NULL);
+ Address(uint64_t addr, uint32_t addr_size, const char *prefix = nullptr, const char *suffix = nullptr);
//------------------------------------------------------------------
/// Output an address range to this stream.
@@ -377,13 +381,13 @@ public:
/// Size in bytes of the address, used for formatting.
///
/// @param[in] prefix
- /// A prefix C string. If NULL, no prefix will be output.
+ /// A prefix C string. If nullptr, no prefix will be output.
///
/// @param[in] suffix
- /// A suffix C string. If NULL, no suffix will be output.
+ /// A suffix C string. If nullptr, no suffix will be output.
//------------------------------------------------------------------
void
- AddressRange(uint64_t lo_addr, uint64_t hi_addr, uint32_t addr_size, const char *prefix = NULL, const char *suffix = NULL);
+ AddressRange(uint64_t lo_addr, uint64_t hi_addr, uint32_t addr_size, const char *prefix = nullptr, const char *suffix = nullptr);
//------------------------------------------------------------------
/// Output a C string to the stream.
@@ -475,11 +479,11 @@ public:
/// print an optional string following the indentation spaces.
///
/// @param[in] s
- /// A C string to print following the indentation. If NULL, just
+ /// A C string to print following the indentation. If nullptr, just
/// output the indentation characters.
//------------------------------------------------------------------
size_t
- Indent(const char *s = NULL);
+ Indent(const char *s = nullptr);
//------------------------------------------------------------------
/// Decrement the current indentation level.
@@ -607,6 +611,4 @@ protected:
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
#endif // liblldb_Stream_h_
-
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/StreamAsynchronousIO.h b/contrib/llvm/tools/lldb/include/lldb/Core/StreamAsynchronousIO.h
index d3b0544..b069cfd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/StreamAsynchronousIO.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/StreamAsynchronousIO.h
@@ -22,14 +22,13 @@ class StreamAsynchronousIO :
public:
StreamAsynchronousIO (Debugger &debugger, bool for_stdout);
- virtual ~StreamAsynchronousIO ();
+ ~StreamAsynchronousIO () override;
- virtual void
- Flush ();
-
- virtual size_t
- Write (const void *src, size_t src_len);
+ void
+ Flush () override;
+ size_t
+ Write (const void *src, size_t src_len) override;
private:
Debugger &m_debugger;
@@ -38,4 +37,5 @@ private:
};
} // namespace lldb_private
-#endif // #ifndef liblldb_StreamAsynchronousIO_h
+
+#endif // liblldb_StreamAsynchronousIO_h
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/StreamCallback.h b/contrib/llvm/tools/lldb/include/lldb/Core/StreamCallback.h
index b5fb91c..e5a9da7 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/StreamCallback.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/StreamCallback.h
@@ -24,14 +24,13 @@ class StreamCallback :
public:
StreamCallback (lldb::LogOutputCallback callback, void *baton);
- virtual ~StreamCallback ();
+ ~StreamCallback () override;
- virtual void
- Flush ();
-
- virtual size_t
- Write (const void *src, size_t src_len);
+ void
+ Flush () override;
+ size_t
+ Write (const void *src, size_t src_len) override;
private:
typedef std::map<lldb::tid_t, StreamString> collection;
@@ -44,4 +43,5 @@ private:
};
} // namespace lldb_private
-#endif // #ifndef liblldb_StreamCallback_h
+
+#endif // liblldb_StreamCallback_h
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/StreamFile.h b/contrib/llvm/tools/lldb/include/lldb/Core/StreamFile.h
index 55bb361..781f0a5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/StreamFile.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/StreamFile.h
@@ -43,8 +43,7 @@ public:
StreamFile (FILE *fh, bool transfer_ownership);
- virtual
- ~StreamFile();
+ ~StreamFile() override;
File &
GetFile ()
@@ -58,11 +57,11 @@ public:
return m_file;
}
- virtual void
- Flush ();
+ void
+ Flush () override;
- virtual size_t
- Write (const void *s, size_t length);
+ size_t
+ Write (const void *s, size_t length) override;
protected:
//------------------------------------------------------------------
@@ -76,4 +75,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_StreamFile_h_
+#endif // liblldb_StreamFile_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/StreamGDBRemote.h b/contrib/llvm/tools/lldb/include/lldb/Core/StreamGDBRemote.h
index 3fdb6f6..834f412 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/StreamGDBRemote.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/StreamGDBRemote.h
@@ -29,8 +29,7 @@ namespace lldb_private {
uint32_t addr_size,
lldb::ByteOrder byte_order);
- virtual
- ~StreamGDBRemote ();
+ ~StreamGDBRemote() override;
//------------------------------------------------------------------
/// Output a block of data to the stream performing GDB-remote escaping.
@@ -51,4 +50,4 @@ namespace lldb_private {
} // namespace lldb_private
-#endif // liblldb_StreamGDBRemote_h_
+#endif // liblldb_StreamGDBRemote_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/StreamString.h b/contrib/llvm/tools/lldb/include/lldb/Core/StreamString.h
index 1aa46dd..5b6bde7 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/StreamString.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/StreamString.h
@@ -25,14 +25,13 @@ public:
uint32_t addr_size,
lldb::ByteOrder byte_order);
- virtual
- ~StreamString ();
+ ~StreamString () override;
- virtual void
- Flush ();
+ void
+ Flush () override;
- virtual size_t
- Write (const void *s, size_t length);
+ size_t
+ Write (const void *s, size_t length) override;
void
Clear();
@@ -60,8 +59,8 @@ public:
protected:
std::string m_packet;
-
};
} // namespace lldb_private
-#endif // #ifndef liblldb_StreamString_h_
+
+#endif // liblldb_StreamString_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/StreamTee.h b/contrib/llvm/tools/lldb/include/lldb/Core/StreamTee.h
index e2a29a3..7ab619b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/StreamTee.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/StreamTee.h
@@ -59,8 +59,7 @@ public:
m_streams = rhs.m_streams;
}
- virtual
- ~StreamTee ()
+ ~StreamTee () override
{
}
@@ -76,8 +75,8 @@ public:
return *this;
}
- virtual void
- Flush ()
+ void
+ Flush () override
{
Mutex::Locker locker (m_streams_mutex);
collection::iterator pos, end;
@@ -93,8 +92,8 @@ public:
}
}
- virtual size_t
- Write (const void *s, size_t length)
+ size_t
+ Write (const void *s, size_t length) override
{
Mutex::Locker locker (m_streams_mutex);
if (m_streams.empty())
@@ -164,7 +163,6 @@ public:
m_streams[idx] = stream_sp;
}
-
protected:
typedef std::vector<lldb::StreamSP> collection;
mutable Mutex m_streams_mutex;
@@ -172,4 +170,5 @@ protected:
};
} // namespace lldb_private
-#endif // #ifndef liblldb_StreamTee_h_
+
+#endif // liblldb_StreamTee_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/StringList.h b/contrib/llvm/tools/lldb/include/lldb/Core/StringList.h
index c69ed87..53bdb69 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/StringList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/StringList.h
@@ -10,18 +10,24 @@
#ifndef liblldb_StringList_h_
#define liblldb_StringList_h_
+// C Includes
#include <stdint.h>
-#include "lldb/Core/STLUtils.h"
-#include "lldb/lldb-forward.h"
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
+// Project includes
+#include "lldb/lldb-forward.h"
+#include "lldb/Core/STLUtils.h"
+
namespace lldb_private {
class StringList
{
public:
-
StringList ();
StringList (const char *str);
@@ -120,15 +126,22 @@ public:
SplitIntoLines (const char *lines, size_t len);
std::string
- CopyList(const char* item_preamble = NULL,
+ CopyList(const char* item_preamble = nullptr,
const char* items_sep = "\n") const;
StringList&
operator << (const char* str);
StringList&
+ operator << (const std::string &s);
+
+ StringList&
operator << (StringList strings);
+ // Copy assignment for a vector of strings
+ StringList&
+ operator = (const std::vector<std::string> &rhs);
+
// This string list contains a list of valid auto completion
// strings, and the "s" is passed in. "matches" is filled in
// with zero or more string values that start with "s", and
@@ -141,8 +154,24 @@ public:
StringList &matches,
size_t &exact_matches_idx) const;
-private:
+ // Dump the StringList to the given lldb_private::Log, `log`, one item per line.
+ // If given, `name` will be used to identify the start and end of the list in the output.
+ virtual void LogDump(Log *log, const char *name = nullptr);
+ // Static helper to convert an iterable of strings to a StringList, and then
+ // dump it with the semantics of the `LogDump` method.
+ template<typename T> static void LogDump(Log *log, T s_iterable, const char *name = nullptr)
+ {
+ if (!log)
+ return;
+ // Make a copy of the iterable as a StringList
+ StringList l{};
+ for (const auto &s : s_iterable)
+ l << s;
+
+ l.LogDump(log, name);
+ }
+private:
STLStringArray m_strings;
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/StructuredData.h b/contrib/llvm/tools/lldb/include/lldb/Core/StructuredData.h
index 7da29e4..52f3452 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/StructuredData.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/StructuredData.h
@@ -12,16 +12,16 @@
// C Includes
// C++ Includes
-
#include <functional>
#include <map>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
+// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-// Other libraries and framework includes
// Project includes
#include "lldb/lldb-defines.h"
#include "lldb/Core/ConstString.h"
@@ -47,7 +47,6 @@ namespace lldb_private {
class StructuredData
{
public:
-
class Object;
class Array;
class Integer;
@@ -89,9 +88,7 @@ public:
{
}
- virtual ~Object ()
- {
- }
+ virtual ~Object() = default;
virtual bool
IsValid() const
@@ -120,80 +117,62 @@ public:
Array *
GetAsArray ()
{
- if (m_type == Type::eTypeArray)
- return (Array *)this;
- return NULL;
+ return ((m_type == Type::eTypeArray) ? static_cast<Array *>(this) : nullptr);
}
Dictionary *
GetAsDictionary ()
{
- if (m_type == Type::eTypeDictionary)
- return (Dictionary *)this;
- return NULL;
+ return ((m_type == Type::eTypeDictionary) ? static_cast<Dictionary *>(this) : nullptr);
}
Integer *
GetAsInteger ()
{
- if (m_type == Type::eTypeInteger)
- return (Integer *)this;
- return NULL;
+ return ((m_type == Type::eTypeInteger) ? static_cast<Integer *>(this) : nullptr);
}
uint64_t
GetIntegerValue (uint64_t fail_value = 0)
{
Integer *integer = GetAsInteger ();
- if (integer)
- return integer->GetValue();
- return fail_value;
+ return ((integer != nullptr) ? integer->GetValue() : fail_value);
}
Float *
GetAsFloat ()
{
- if (m_type == Type::eTypeFloat)
- return (Float *)this;
- return NULL;
+ return ((m_type == Type::eTypeFloat) ? static_cast<Float *>(this) : nullptr);
}
double
GetFloatValue (double fail_value = 0.0)
{
Float *f = GetAsFloat ();
- if (f)
- return f->GetValue();
- return fail_value;
+ return ((f != nullptr) ? f->GetValue() : fail_value);
}
Boolean *
GetAsBoolean ()
{
- if (m_type == Type::eTypeBoolean)
- return (Boolean *)this;
- return NULL;
+ return ((m_type == Type::eTypeBoolean) ? static_cast<Boolean *>(this) : nullptr);
}
bool
GetBooleanValue (bool fail_value = false)
{
Boolean *b = GetAsBoolean ();
- if (b)
- return b->GetValue();
- return fail_value;
+ return ((b != nullptr) ? b->GetValue() : fail_value);
}
String *
GetAsString ()
{
- if (m_type == Type::eTypeString)
- return (String *)this;
- return NULL;
+ return ((m_type == Type::eTypeString) ? static_cast<String *>(this) : nullptr);
}
std::string
- GetStringValue(const char *fail_value = NULL)
+ GetStringValue(const char *fail_value = nullptr)
{
String *s = GetAsString ();
if (s)
@@ -208,9 +187,7 @@ public:
Generic *
GetAsGeneric()
{
- if (m_type == Type::eTypeGeneric)
- return (Generic *)this;
- return NULL;
+ return ((m_type == Type::eTypeGeneric) ? static_cast<Generic *>(this) : nullptr);
}
ObjectSP
@@ -233,10 +210,7 @@ public:
{
}
- virtual
- ~Array()
- {
- }
+ ~Array() override = default;
bool
ForEach (std::function <bool(Object* object)> const &foreach_callback) const
@@ -249,7 +223,6 @@ public:
return true;
}
-
size_t
GetSize() const
{
@@ -277,11 +250,14 @@ public:
bool
GetItemAtIndexAsInteger(size_t idx, IntType &result) const
{
- ObjectSP value = GetItemAtIndex(idx);
- if (auto int_value = value->GetAsInteger())
+ ObjectSP value_sp = GetItemAtIndex(idx);
+ if (value_sp.get())
{
- result = static_cast<IntType>(int_value->GetValue());
- return true;
+ if (auto int_value = value_sp->GetAsInteger())
+ {
+ result = static_cast<IntType>(int_value->GetValue());
+ return true;
+ }
}
return false;
}
@@ -299,11 +275,14 @@ public:
bool
GetItemAtIndexAsString(size_t idx, std::string &result) const
{
- ObjectSP value = GetItemAtIndex(idx);
- if (auto string_value = value->GetAsString())
+ ObjectSP value_sp = GetItemAtIndex(idx);
+ if (value_sp.get())
{
- result = string_value->GetValue();
- return true;
+ if (auto string_value = value_sp->GetAsString())
+ {
+ result = string_value->GetValue();
+ return true;
+ }
}
return false;
}
@@ -320,13 +299,13 @@ public:
bool
GetItemAtIndexAsString(size_t idx, ConstString &result) const
{
- ObjectSP value = GetItemAtIndex(idx);
- if (!value)
- return false;
- if (auto string_value = value->GetAsString())
- {
- result = ConstString(string_value->GetValue());
- return true;
+ ObjectSP value_sp = GetItemAtIndex(idx);
+ if (value_sp.get()) {
+ if (auto string_value = value_sp->GetAsString())
+ {
+ result = ConstString(string_value->GetValue());
+ return true;
+ }
}
return false;
}
@@ -343,17 +322,27 @@ public:
bool
GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const
{
- ObjectSP value = GetItemAtIndex(idx);
- result = value->GetAsDictionary();
- return (result != nullptr);
+ result = nullptr;
+ ObjectSP value_sp = GetItemAtIndex(idx);
+ if (value_sp.get())
+ {
+ result = value_sp->GetAsDictionary();
+ return (result != nullptr);
+ }
+ return false;
}
bool
GetItemAtIndexAsArray(size_t idx, Array *&result) const
{
- ObjectSP value = GetItemAtIndex(idx);
- result = value->GetAsArray();
- return (result != nullptr);
+ result = nullptr;
+ ObjectSP value_sp = GetItemAtIndex(idx);
+ if (value_sp.get())
+ {
+ result = value_sp->GetAsArray();
+ return (result != nullptr);
+ }
+ return false;
}
void
@@ -375,8 +364,7 @@ public:
collection m_items;
};
-
- class Integer : public Object
+ class Integer : public Object
{
public:
Integer (uint64_t i = 0) :
@@ -385,9 +373,7 @@ public:
{
}
- virtual ~Integer()
- {
- }
+ ~Integer() override = default;
void
SetValue (uint64_t value)
@@ -407,7 +393,7 @@ public:
uint64_t m_value;
};
- class Float : public Object
+ class Float : public Object
{
public:
Float (double d = 0.0) :
@@ -416,9 +402,7 @@ public:
{
}
- virtual ~Float()
- {
- }
+ ~Float() override = default;
void
SetValue (double value)
@@ -438,7 +422,7 @@ public:
double m_value;
};
- class Boolean : public Object
+ class Boolean : public Object
{
public:
Boolean (bool b = false) :
@@ -447,9 +431,7 @@ public:
{
}
- virtual ~Boolean()
- {
- }
+ ~Boolean() override = default;
void
SetValue (bool value)
@@ -469,12 +451,10 @@ public:
bool m_value;
};
-
-
- class String : public Object
+ class String : public Object
{
public:
- String (const char *cstr = NULL) :
+ String(const char *cstr = nullptr) :
Object (Type::eTypeString),
m_value ()
{
@@ -522,9 +502,7 @@ public:
{
}
- virtual ~Dictionary()
- {
- }
+ ~Dictionary() override = default;
size_t
GetSize() const
@@ -580,13 +558,13 @@ public:
bool
GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const
{
- ObjectSP value = GetValueForKey(key);
- if (!value)
- return false;
- if (auto int_value = value->GetAsInteger())
- {
- result = static_cast<IntType>(int_value->GetValue());
- return true;
+ ObjectSP value_sp = GetValueForKey(key);
+ if (value_sp) {
+ if (auto int_value = value_sp->GetAsInteger())
+ {
+ result = static_cast<IntType>(int_value->GetValue());
+ return true;
+ }
}
return false;
}
@@ -604,13 +582,14 @@ public:
bool
GetValueForKeyAsString(llvm::StringRef key, std::string &result) const
{
- ObjectSP value = GetValueForKey(key);
- if (!value)
- return false;
- if (auto string_value = value->GetAsString())
+ ObjectSP value_sp = GetValueForKey(key);
+ if (value_sp.get())
{
- result = string_value->GetValue();
- return true;
+ if (auto string_value = value_sp->GetAsString())
+ {
+ result = string_value->GetValue();
+ return true;
+ }
}
return false;
}
@@ -632,13 +611,14 @@ public:
bool
GetValueForKeyAsString(llvm::StringRef key, ConstString &result) const
{
- ObjectSP value = GetValueForKey(key);
- if (!value)
- return false;
- if (auto string_value = value->GetAsString())
+ ObjectSP value_sp = GetValueForKey(key);
+ if (value_sp.get())
{
- result = ConstString(string_value->GetValue());
- return true;
+ if (auto string_value = value_sp->GetAsString())
+ {
+ result = ConstString(string_value->GetValue());
+ return true;
+ }
}
return false;
}
@@ -656,22 +636,26 @@ public:
GetValueForKeyAsDictionary(llvm::StringRef key, Dictionary *&result) const
{
result = nullptr;
- ObjectSP value = GetValueForKey(key);
- if (!value)
- return false;
- result = value->GetAsDictionary();
- return true;
+ ObjectSP value_sp = GetValueForKey(key);
+ if (value_sp.get())
+ {
+ result = value_sp->GetAsDictionary();
+ return (result != nullptr);
+ }
+ return false;
}
bool
GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const
{
result = nullptr;
- ObjectSP value = GetValueForKey(key);
- if (!value)
- return false;
- result = value->GetAsArray();
- return true;
+ ObjectSP value_sp = GetValueForKey(key);
+ if (value_sp.get())
+ {
+ result = value_sp->GetAsArray();
+ return (result != nullptr);
+ }
+ return false;
}
bool
@@ -683,10 +667,10 @@ public:
}
void
- AddItem (llvm::StringRef key, ObjectSP value)
+ AddItem (llvm::StringRef key, ObjectSP value_sp)
{
ConstString key_cs(key);
- m_dict[key_cs] = value;
+ m_dict[key_cs] = value_sp;
}
void
@@ -728,9 +712,7 @@ public:
{
}
- virtual ~Null()
- {
- }
+ ~Null() override = default;
bool
IsValid() const override
@@ -739,13 +721,11 @@ public:
}
void Dump(Stream &s) const override;
-
- protected:
};
class Generic : public Object
{
- public:
+ public:
explicit Generic(void *object = nullptr) :
Object (Type::eTypeGeneric),
m_object (object)
@@ -772,16 +752,14 @@ public:
void Dump(Stream &s) const override;
- private:
+ private:
void *m_object;
};
static ObjectSP
ParseJSON (std::string json_text);
-
-}; // class StructuredData
-
+};
} // namespace lldb_private
-#endif // liblldb_StructuredData_h_
+#endif // liblldb_StructuredData_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseMap.h b/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseMap.h
index f5a7ccf..6b2b59b7 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseMap.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseMap.h
@@ -54,7 +54,27 @@ public:
Mutex::Locker locker(m_mutex);
return m_map.lookup(k);
}
-
+
+ bool
+ Lookup (_KeyType k,
+ _ValueType& v)
+ {
+ Mutex::Locker locker(m_mutex);
+ auto iter = m_map.find(k),
+ end = m_map.end();
+ if (iter == end)
+ return false;
+ v = iter->second;
+ return true;
+ }
+
+ void
+ Clear ()
+ {
+ Mutex::Locker locker(m_mutex);
+ m_map.clear();
+ }
+
protected:
LLVMMapType m_map;
Mutex m_mutex;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseSet.h b/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseSet.h
index 19c67b6..e019c70 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseSet.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ThreadSafeDenseSet.h
@@ -55,6 +55,13 @@ namespace lldb_private {
return (m_set.count(e) > 0);
}
+ void
+ Clear ()
+ {
+ Mutex::Locker locker(m_mutex);
+ m_set.clear();
+ }
+
protected:
LLVMSetType m_set;
Mutex m_mutex;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Timer.h b/contrib/llvm/tools/lldb/include/lldb/Core/Timer.h
index e354d91..ffaeba6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Timer.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Timer.h
@@ -9,11 +9,17 @@
#ifndef liblldb_Timer_h_
#define liblldb_Timer_h_
-#if defined(__cplusplus)
+// C Includes
#include <stdarg.h>
#include <stdio.h>
-#include <string>
+
+// C++ Includes
+#include <atomic>
+#include <mutex>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Host/TimeValue.h"
@@ -34,19 +40,19 @@ namespace lldb_private {
class Timer
{
public:
- static void
- Initialize ();
-
//--------------------------------------------------------------
/// Default constructor.
//--------------------------------------------------------------
Timer(const char *category, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
//--------------------------------------------------------------
- /// Desstructor
+ /// Destructor
//--------------------------------------------------------------
~Timer();
+ static void
+ Initialize ();
+
void
Dump ();
@@ -63,7 +69,6 @@ public:
ResetCategoryTimes ();
protected:
-
void
ChildStarted (const TimeValue& time);
@@ -76,17 +81,17 @@ protected:
uint64_t
GetTimerElapsedNanoSeconds();
- //--------------------------------------------------------------
- /// Member variables
- //--------------------------------------------------------------
const char *m_category;
TimeValue m_total_start;
TimeValue m_timer_start;
uint64_t m_total_ticks; // Total running time for this timer including when other timers below this are running
uint64_t m_timer_ticks; // Ticks for this timer that do not include when other timers below this one are running
- static uint32_t g_depth;
- static uint32_t g_display_depth;
- static FILE * g_file;
+
+ static std::atomic<bool> g_quiet;
+ static std::atomic<unsigned> g_display_depth;
+ static std::mutex g_file_mutex;
+ static FILE* g_file;
+
private:
Timer();
DISALLOW_COPY_AND_ASSIGN (Timer);
@@ -99,10 +104,8 @@ public:
m_start (TimeValue::Now())
{
}
-
- ~IntervalTimer()
- {
- }
+
+ ~IntervalTimer() = default;
uint64_t
GetElapsedNanoSeconds() const
@@ -121,7 +124,7 @@ public:
{
TimeValue now (TimeValue::Now());
const uint64_t elapsed_nsec = now - m_start;
- const char *unit = NULL;
+ const char *unit = nullptr;
float elapsed_value;
if (elapsed_nsec < 1000)
{
@@ -150,11 +153,11 @@ public:
va_end (args);
return result;
}
+
protected:
TimeValue m_start;
};
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif // #ifndef liblldb_Timer_h_
+#endif // liblldb_Timer_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/UUID.h b/contrib/llvm/tools/lldb/include/lldb/Core/UUID.h
index 3bb1442..88426cf 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/UUID.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/UUID.h
@@ -16,7 +16,6 @@
// Other libraries and framework includes
// Project includes
-
#include "lldb/lldb-private.h"
namespace lldb_private {
@@ -58,7 +57,7 @@ public:
SetBytes (const void *uuid_bytes, uint32_t num_uuid_bytes = 16);
std::string
- GetAsString (const char *separator = NULL) const;
+ GetAsString(const char *separator = nullptr) const;
size_t
SetFromCString (const char *c_str, uint32_t num_uuid_bytes = 16);
@@ -80,7 +79,7 @@ public:
/// decoded UUID.
///
/// @param[out] end
- /// If \a end is not NULL, it will be filled in with the a
+ /// If \a end is not nullptr, it will be filled in with the a
/// pointer to the character after the last successfully decoded
/// byte.
///
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/UniqueCStringMap.h b/contrib/llvm/tools/lldb/include/lldb/Core/UniqueCStringMap.h
index 972c0d5..1e50f74 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/UniqueCStringMap.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/UniqueCStringMap.h
@@ -9,18 +9,18 @@
#ifndef liblldb_UniqueCStringMap_h_
#define liblldb_UniqueCStringMap_h_
-#if defined(__cplusplus)
-#include <assert.h>
+// C Includes
+// C++ Includes
#include <algorithm>
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/RegularExpression.h"
namespace lldb_private {
-
-
//----------------------------------------------------------------------
// Templatized uniqued string map.
//
@@ -37,7 +37,7 @@ public:
struct Entry
{
Entry () :
- cstring(NULL),
+ cstring(nullptr),
value()
{
}
@@ -146,9 +146,7 @@ public:
const char *
GetCStringAtIndex (uint32_t idx) const
{
- if (idx < m_map.size())
- return m_map[idx].cstring;
- return NULL;
+ return ((idx < m_map.size()) ? m_map[idx].cstring : nullptr);
}
//------------------------------------------------------------------
@@ -172,8 +170,9 @@ public:
}
return fail_value;
}
+
//------------------------------------------------------------------
- // Get a pointer to the first entry that matches "name". NULL will
+ // Get a pointer to the first entry that matches "name". nullptr will
// be returned if there is no entry that matches "name".
//
// The caller is responsible for ensuring that the collection does
@@ -191,12 +190,12 @@ public:
if (pos_cstr == unique_cstr)
return &(*pos);
}
- return NULL;
+ return nullptr;
}
//------------------------------------------------------------------
// Get a pointer to the next entry that matches "name" from a
- // previously returned Entry pointer. NULL will be returned if there
+ // previously returned Entry pointer. nullptr will be returned if there
// is no subsequent entry that matches "name".
//
// The caller is responsible for ensuring that the collection does
@@ -216,7 +215,7 @@ public:
return next_entry;
}
}
- return NULL;
+ return nullptr;
}
size_t
@@ -261,7 +260,6 @@ public:
return m_map.size();
}
-
//------------------------------------------------------------------
// Returns true if this map is empty.
//------------------------------------------------------------------
@@ -346,6 +344,7 @@ public:
}
return num_removed;
}
+
protected:
typedef std::vector<Entry> collection;
typedef typename collection::iterator iterator;
@@ -353,9 +352,6 @@ protected:
collection m_map;
};
-
-
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif // liblldb_UniqueCStringMap_h_
+#endif // liblldb_UniqueCStringMap_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/Value.h b/contrib/llvm/tools/lldb/include/lldb/Core/Value.h
index 957cede..a6d934a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/Value.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/Value.h
@@ -12,23 +12,21 @@
// C Includes
// C++ Includes
-#include <string>
#include <vector>
+
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
-#include "lldb/Core/ClangForward.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Scalar.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
namespace lldb_private {
class Value
{
public:
-
// Values Less than zero are an error, greater than or equal to zero
// returns what the Scalar result is.
enum ValueType
@@ -101,6 +99,7 @@ public:
// Casts a vector, if valid, to an unsigned int of matching or largest supported size.
// Truncates to the beginning of the vector if required.
// Returns a default constructed Scalar if the Vector data is internally inconsistent.
+ llvm::APInt rhs = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)bytes)->x);
Scalar
GetAsScalar() const
{
@@ -111,11 +110,7 @@ public:
else if (length == 2) scalar = *(const uint16_t *)bytes;
else if (length == 4) scalar = *(const uint32_t *)bytes;
else if (length == 8) scalar = *(const uint64_t *)bytes;
-#if defined (ENABLE_128_BIT_SUPPORT)
- else if (length >= 16) scalar = *(const __uint128_t *)bytes;
-#else
- else if (length >= 16) scalar = *(const uint64_t *)bytes;
-#endif
+ else if (length >= 16) scalar = rhs;
}
return scalar;
}
@@ -136,11 +131,11 @@ public:
Value &
operator=(const Value &rhs);
- const ClangASTType &
- GetClangType();
+ const CompilerType &
+ GetCompilerType();
void
- SetClangType (const ClangASTType &clang_type);
+ SetCompilerType (const CompilerType &compiler_type);
ValueType
GetValueType() const;
@@ -163,7 +158,7 @@ public:
void
ClearContext ()
{
- m_context = NULL;
+ m_context = nullptr;
m_context_type = eContextTypeInvalid;
}
@@ -269,13 +264,13 @@ public:
GetValueDefaultFormat ();
uint64_t
- GetValueByteSize (Error *error_ptr);
+ GetValueByteSize (Error *error_ptr, ExecutionContext *exe_ctx);
Error
- GetValueAsData (ExecutionContext *exe_ctx,
- DataExtractor &data,
- uint32_t data_offset,
- Module *module); // Can be NULL
+ GetValueAsData(ExecutionContext *exe_ctx,
+ DataExtractor &data,
+ uint32_t data_offset,
+ Module *module); // Can be nullptr
static const char *
GetValueTypeAsCString (ValueType context_type);
@@ -292,7 +287,7 @@ public:
protected:
Scalar m_value;
Vector m_vector;
- ClangASTType m_clang_type;
+ CompilerType m_compiler_type;
void * m_context;
ValueType m_value_type;
ContextType m_context_type;
@@ -309,9 +304,7 @@ public:
ValueList (const ValueList &rhs);
- ~ValueList ()
- {
- }
+ ~ValueList() = default;
const ValueList & operator= (const ValueList &rhs);
@@ -322,8 +315,6 @@ public:
Value *GetValueAtIndex(size_t idx);
void Clear();
-protected:
-
private:
typedef std::vector<Value> collection;
@@ -332,4 +323,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_Value_h_
+#endif // liblldb_Value_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObject.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObject.h
index cdc5070..c066cc7 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObject.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObject.h
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <functional>
+#include <initializer_list>
#include <map>
#include <vector>
@@ -27,7 +29,7 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/UserID.h"
#include "lldb/Core/Value.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/Process.h"
@@ -69,7 +71,6 @@ namespace lldb_private {
class ValueObject : public UserID
{
public:
-
enum GetExpressionPathFormat
{
eGetExpressionPathFormatDereferencePointers = 1,
@@ -221,13 +222,11 @@ public:
return g_default_options;
}
-
};
class EvaluationPoint
{
public:
-
EvaluationPoint ();
EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected = false);
@@ -326,6 +325,8 @@ public:
bool m_needs_update;
};
+ virtual ~ValueObject();
+
const EvaluationPoint &
GetUpdatePoint () const
{
@@ -371,10 +372,8 @@ public:
void
SetNeedsUpdate ();
- virtual ~ValueObject();
-
- ClangASTType
- GetClangType ();
+ CompilerType
+ GetCompilerType ();
// this vends a TypeImpl that is useful at the SB API layer
virtual TypeImpl
@@ -408,7 +407,7 @@ public:
GetObjectRuntimeLanguage();
virtual uint32_t
- GetTypeInfo (ClangASTType *pointee_or_element_clang_type = NULL);
+ GetTypeInfo(CompilerType *pointee_or_element_compiler_type = nullptr);
virtual bool
IsPointerType ();
@@ -425,8 +424,11 @@ public:
virtual bool
IsPossibleDynamicType ();
- virtual bool
- IsObjCNil ();
+ bool
+ IsNilReference ();
+
+ bool
+ IsUninitializedReference ();
virtual bool
IsBaseClass ()
@@ -454,20 +456,20 @@ public:
lldb::ValueObjectSP
GetValueForExpressionPath(const char* expression,
- const char** first_unparsed = NULL,
- ExpressionPathScanEndReason* reason_to_stop = NULL,
- ExpressionPathEndResultType* final_value_type = NULL,
+ const char** first_unparsed = nullptr,
+ ExpressionPathScanEndReason* reason_to_stop = nullptr,
+ ExpressionPathEndResultType* final_value_type = nullptr,
const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(),
- ExpressionPathAftermath* final_task_on_target = NULL);
+ ExpressionPathAftermath* final_task_on_target = nullptr);
int
GetValuesForExpressionPath(const char* expression,
lldb::ValueObjectListSP& list,
- const char** first_unparsed = NULL,
- ExpressionPathScanEndReason* reason_to_stop = NULL,
- ExpressionPathEndResultType* final_value_type = NULL,
+ const char** first_unparsed = nullptr,
+ ExpressionPathScanEndReason* reason_to_stop = nullptr,
+ ExpressionPathEndResultType* final_value_type = nullptr,
const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(),
- ExpressionPathAftermath* final_task_on_target = NULL);
+ ExpressionPathAftermath* final_task_on_target = nullptr);
virtual bool
IsInScope ()
@@ -517,10 +519,10 @@ public:
std::string& destination);
virtual uint64_t
- GetValueAsUnsigned (uint64_t fail_value, bool *success = NULL);
+ GetValueAsUnsigned(uint64_t fail_value, bool *success = nullptr);
virtual int64_t
- GetValueAsSigned (int64_t fail_value, bool *success = NULL);
+ GetValueAsSigned(int64_t fail_value, bool *success = nullptr);
virtual bool
SetValueFromCString (const char *value_str, Error& error);
@@ -556,37 +558,37 @@ public:
// this will always create the children if necessary
lldb::ValueObjectSP
- GetChildAtIndexPath (const std::initializer_list<size_t> &idxs,
- size_t* index_of_error = NULL);
+ GetChildAtIndexPath(const std::initializer_list<size_t> &idxs,
+ size_t* index_of_error = nullptr);
lldb::ValueObjectSP
- GetChildAtIndexPath (const std::vector<size_t> &idxs,
- size_t* index_of_error = NULL);
+ GetChildAtIndexPath(const std::vector<size_t> &idxs,
+ size_t* index_of_error = nullptr);
lldb::ValueObjectSP
- GetChildAtIndexPath (const std::initializer_list< std::pair<size_t, bool> > &idxs,
- size_t* index_of_error = NULL);
+ GetChildAtIndexPath(const std::initializer_list< std::pair<size_t, bool> > &idxs,
+ size_t* index_of_error = nullptr);
lldb::ValueObjectSP
- GetChildAtIndexPath (const std::vector< std::pair<size_t, bool> > &idxs,
- size_t* index_of_error = NULL);
+ GetChildAtIndexPath(const std::vector< std::pair<size_t, bool> > &idxs,
+ size_t* index_of_error = nullptr);
// this will always create the children if necessary
lldb::ValueObjectSP
- GetChildAtNamePath (const std::initializer_list<ConstString> &names,
- ConstString* name_of_error = NULL);
+ GetChildAtNamePath(const std::initializer_list<ConstString> &names,
+ ConstString* name_of_error = nullptr);
lldb::ValueObjectSP
- GetChildAtNamePath (const std::vector<ConstString> &names,
- ConstString* name_of_error = NULL);
+ GetChildAtNamePath(const std::vector<ConstString> &names,
+ ConstString* name_of_error = nullptr);
lldb::ValueObjectSP
- GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names,
- ConstString* name_of_error = NULL);
+ GetChildAtNamePath(const std::initializer_list< std::pair<ConstString, bool> > &names,
+ ConstString* name_of_error = nullptr);
lldb::ValueObjectSP
- GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names,
- ConstString* name_of_error = NULL);
+ GetChildAtNamePath(const std::vector< std::pair<ConstString, bool> > &names,
+ ConstString* name_of_error = nullptr);
virtual lldb::ValueObjectSP
GetChildMemberWithName (const ConstString &name, bool can_create);
@@ -595,7 +597,7 @@ public:
GetIndexOfChildWithName (const ConstString &name);
size_t
- GetNumChildren ();
+ GetNumChildren (uint32_t max=UINT32_MAX);
const Value &
GetValue() const;
@@ -606,15 +608,22 @@ public:
virtual bool
ResolveValue (Scalar &scalar);
+ // return 'false' whenever you set the error, otherwise
+ // callers may assume true means everything is OK - this will
+ // break breakpoint conditions among potentially a few others
+ virtual bool
+ IsLogicalTrue (Error& error);
+
virtual const char *
GetLocationAsCString ();
const char *
- GetSummaryAsCString ();
+ GetSummaryAsCString (lldb::LanguageType lang = lldb::eLanguageTypeUnknown);
bool
GetSummaryAsCString (TypeSummaryImpl* summary_ptr,
- std::string& destination);
+ std::string& destination,
+ lldb::LanguageType lang = lldb::eLanguageTypeUnknown);
bool
GetSummaryAsCString (std::string& destination,
@@ -671,11 +680,11 @@ public:
SetName (const ConstString &name);
virtual lldb::addr_t
- GetAddressOf (bool scalar_is_load_address = true,
- AddressType *address_type = NULL);
+ GetAddressOf(bool scalar_is_load_address = true,
+ AddressType *address_type = nullptr);
lldb::addr_t
- GetPointerValue (AddressType *address_type = NULL);
+ GetPointerValue(AddressType *address_type = nullptr);
lldb::ValueObjectSP
GetSyntheticChild (const ConstString &key) const;
@@ -690,10 +699,10 @@ public:
GetSyntheticExpressionPathChild(const char* expression, bool can_create);
virtual lldb::ValueObjectSP
- GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create);
+ GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create);
virtual lldb::ValueObjectSP
- GetSyntheticBase (uint32_t offset, const ClangASTType& type, bool can_create);
+ GetSyntheticBase (uint32_t offset, const CompilerType& type, bool can_create);
virtual lldb::ValueObjectSP
GetDynamicValue (lldb::DynamicValueType valueType);
@@ -746,11 +755,11 @@ public:
GetCPPVTableAddress(AddressType &address_type);
virtual lldb::ValueObjectSP
- Cast (const ClangASTType &clang_ast_type);
+ Cast (const CompilerType &compiler_type);
virtual lldb::ValueObjectSP
CastPointerType (const char *name,
- ClangASTType &ast_type);
+ CompilerType &ast_type);
virtual lldb::ValueObjectSP
CastPointerType (const char *name,
@@ -809,13 +818,13 @@ public:
CreateValueObjectFromAddress (const char* name,
uint64_t address,
const ExecutionContext& exe_ctx,
- ClangASTType type);
+ CompilerType type);
static lldb::ValueObjectSP
CreateValueObjectFromData (const char* name,
const DataExtractor& data,
const ExecutionContext& exe_ctx,
- ClangASTType type);
+ CompilerType type);
void
LogValueObject (Log *log);
@@ -834,7 +843,7 @@ public:
bool
IsCStringContainer (bool check_pointer = false);
- size_t
+ std::pair<size_t,bool>
ReadPointedString (lldb::DataBufferSP& buffer_sp,
Error& error,
uint32_t max_length = 0,
@@ -861,7 +870,7 @@ public:
bool
NeedsUpdating ()
{
- const bool accept_invalid_exe_ctx = CanUpdateWithInvalidExecutionContext();
+ const bool accept_invalid_exe_ctx = (CanUpdateWithInvalidExecutionContext() == eLazyBoolYes);
return m_update_point.NeedsUpdating(accept_invalid_exe_ctx);
}
@@ -881,8 +890,7 @@ public:
ClearUserVisibleData(eClearUserVisibleDataItemsValue);
m_format = format;
}
-
-
+
virtual lldb::LanguageType
GetPreferredDisplayLanguage ();
@@ -999,8 +1007,20 @@ public:
virtual bool
MightHaveChildren();
+ virtual lldb::VariableSP
+ GetVariable ()
+ {
+ return nullptr;
+ }
+
virtual bool
IsRuntimeSupportValue ();
+
+ virtual uint64_t
+ GetLanguageFlags ();
+
+ virtual void
+ SetLanguageFlags (uint64_t flags);
protected:
typedef ClusterManager<ValueObject> ValueObjectManager;
@@ -1018,21 +1038,15 @@ protected:
HasChildAtIndex (size_t idx)
{
Mutex::Locker locker(m_mutex);
- ChildrenIterator iter = m_children.find(idx);
- ChildrenIterator end = m_children.end();
- return (iter != end);
+ return (m_children.find(idx) != m_children.end());
}
ValueObject*
GetChildAtIndex (size_t idx)
{
Mutex::Locker locker(m_mutex);
- ChildrenIterator iter = m_children.find(idx);
- ChildrenIterator end = m_children.end();
- if (iter == end)
- return NULL;
- else
- return iter->second;
+ const auto iter = m_children.find(idx);
+ return ((iter == m_children.end()) ? nullptr : iter->second);
}
void
@@ -1075,8 +1089,8 @@ protected:
//------------------------------------------------------------------
// Classes that inherit from ValueObject can see and modify these
//------------------------------------------------------------------
- ValueObject * m_parent; // The parent value object, or NULL if this has no parent
- ValueObject * m_root; // The root of the hierarchy for this ValueObject (or NULL if never calculated)
+ ValueObject * m_parent; // The parent value object, or nullptr if this has no parent
+ ValueObject * m_root; // The root of the hierarchy for this ValueObject (or nullptr if never calculated)
EvaluationPoint m_update_point; // Stores both the stop id and the full context at which this value was last
// updated. When we are asked to update the value object, we check whether
// the context & stop id are the same before updating.
@@ -1093,7 +1107,7 @@ protected:
llvm::Optional<std::pair<TypeValidatorResult, std::string>> m_validation_result;
- ClangASTType m_override_type;// If the type of the value object should be overridden, the type to impose.
+ CompilerType m_override_type;// If the type of the value object should be overridden, the type to impose.
ValueObjectManager *m_manager; // This object is managed by the root object (any ValueObject that gets created
// without a parent.) The manager gets passed through all the generations of
@@ -1125,6 +1139,8 @@ protected:
lldb::LanguageType m_preferred_display_language;
+ uint64_t m_language_flags;
+
bool m_value_is_valid:1,
m_value_did_change:1,
m_children_count_valid:1,
@@ -1139,7 +1155,7 @@ protected:
friend class ValueObjectChild;
friend class ClangExpressionDeclMap; // For GetValue
- friend class ClangExpressionVariable; // For SetName
+ friend class ExpressionVariable; // For SetName
friend class Target; // For SetName
friend class ValueObjectConstResultImpl;
friend class ValueObjectSynthetic; // For ClearUserVisibleData
@@ -1172,10 +1188,10 @@ protected:
virtual bool
UpdateValue () = 0;
- virtual bool
+ virtual LazyBool
CanUpdateWithInvalidExecutionContext ()
{
- return false;
+ return eLazyBoolCalculate;
}
virtual void
@@ -1203,7 +1219,7 @@ protected:
// Should only be called by ValueObject::GetNumChildren()
virtual size_t
- CalculateNumChildren() = 0;
+ CalculateNumChildren(uint32_t max=UINT32_MAX) = 0;
void
SetNumChildren (size_t num_children);
@@ -1231,8 +1247,8 @@ protected:
// Subclasses must implement the functions below.
//------------------------------------------------------------------
- virtual ClangASTType
- GetClangTypeImpl () = 0;
+ virtual CompilerType
+ GetCompilerTypeImpl () = 0;
const char *
GetLocationAsCStringImpl (const Value& value,
@@ -1241,12 +1257,11 @@ protected:
bool
IsChecksumEmpty ();
-private:
- //------------------------------------------------------------------
- // For ValueObject only
- //------------------------------------------------------------------
+ void
+ SetPreferredDisplayLanguageIfNeeded (lldb::LanguageType);
- virtual ClangASTType
+private:
+ virtual CompilerType
MaybeCalculateCompleteType ();
lldb::ValueObjectSP
@@ -1270,12 +1285,10 @@ private:
ExpressionPathEndResultType* final_value_type,
const GetValueForExpressionPathOptions& options,
ExpressionPathAftermath* final_task_on_target);
-
-
- DISALLOW_COPY_AND_ASSIGN (ValueObject);
+ DISALLOW_COPY_AND_ASSIGN (ValueObject);
};
} // namespace lldb_private
-#endif // liblldb_ValueObject_h_
+#endif // liblldb_ValueObject_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectCast.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectCast.h
index 1538d7a..8c7ffe5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectCast.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectCast.h
@@ -1,4 +1,4 @@
-//===-- ValueObjectDynamicValue.h -----------------------------------*- C++ -*-===//
+//===-- ValueObjectDynamicValue.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -24,64 +24,54 @@ namespace lldb_private {
class ValueObjectCast : public ValueObject
{
public:
+ ~ValueObjectCast() override;
+
static lldb::ValueObjectSP
Create (ValueObject &parent,
const ConstString &name,
- const ClangASTType &cast_type);
+ const CompilerType &cast_type);
- virtual
- ~ValueObjectCast();
-
- virtual uint64_t
- GetByteSize();
+ uint64_t
+ GetByteSize() override;
- virtual size_t
- CalculateNumChildren();
+ size_t
+ CalculateNumChildren(uint32_t max) override;
- virtual lldb::ValueType
- GetValueType() const;
+ lldb::ValueType
+ GetValueType() const override;
- virtual bool
- IsInScope ();
+ bool
+ IsInScope() override;
- virtual ValueObject *
- GetParent()
+ ValueObject *
+ GetParent() override
{
- if (m_parent)
- return m_parent->GetParent();
- else
- return NULL;
+ return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
}
- virtual const ValueObject *
- GetParent() const
+ const ValueObject *
+ GetParent() const override
{
- if (m_parent)
- return m_parent->GetParent();
- else
- return NULL;
+ return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
}
protected:
- virtual bool
- UpdateValue ();
+ ValueObjectCast(ValueObject &parent,
+ const ConstString &name,
+ const CompilerType &cast_type);
+
+ bool
+ UpdateValue () override;
- virtual ClangASTType
- GetClangTypeImpl ();
+ CompilerType
+ GetCompilerTypeImpl () override;
- ClangASTType m_cast_type;
+ CompilerType m_cast_type;
private:
- ValueObjectCast (ValueObject &parent,
- const ConstString &name,
- const ClangASTType &cast_type);
-
- //------------------------------------------------------------------
- // For ValueObject only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (ValueObjectCast);
};
} // namespace lldb_private
-#endif // liblldb_ValueObjectCast_h_
+#endif // liblldb_ValueObjectCast_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectChild.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectChild.h
index bf8707e..13e26c6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectChild.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectChild.h
@@ -16,6 +16,8 @@
// Project includes
#include "lldb/Core/ValueObject.h"
+#include "llvm/ADT/Optional.h"
+
namespace lldb_private {
//----------------------------------------------------------------------
@@ -24,76 +26,76 @@ namespace lldb_private {
class ValueObjectChild : public ValueObject
{
public:
- virtual ~ValueObjectChild();
+ ~ValueObjectChild() override;
- virtual uint64_t
- GetByteSize()
+ uint64_t
+ GetByteSize() override
{
return m_byte_size;
}
- virtual lldb::offset_t
- GetByteOffset()
+ lldb::offset_t
+ GetByteOffset() override
{
return m_byte_offset;
}
- virtual uint32_t
- GetBitfieldBitSize()
+ uint32_t
+ GetBitfieldBitSize() override
{
return m_bitfield_bit_size;
}
- virtual uint32_t
- GetBitfieldBitOffset()
+ uint32_t
+ GetBitfieldBitOffset() override
{
return m_bitfield_bit_offset;
}
- virtual lldb::ValueType
- GetValueType() const;
+ lldb::ValueType
+ GetValueType() const override;
- virtual size_t
- CalculateNumChildren();
+ size_t
+ CalculateNumChildren(uint32_t max) override;
- virtual ConstString
- GetTypeName();
+ ConstString
+ GetTypeName() override;
- virtual ConstString
- GetQualifiedTypeName();
+ ConstString
+ GetQualifiedTypeName() override;
- virtual ConstString
- GetDisplayTypeName();
+ ConstString
+ GetDisplayTypeName() override;
- virtual bool
- IsInScope ();
+ bool
+ IsInScope() override;
- virtual bool
- IsBaseClass ()
+ bool
+ IsBaseClass() override
{
return m_is_base_class;
}
- virtual bool
- IsDereferenceOfParent ()
+ bool
+ IsDereferenceOfParent() override
{
return m_is_deref_of_parent;
}
protected:
- virtual bool
- UpdateValue ();
+ bool
+ UpdateValue() override;
- virtual bool
- CanUpdateWithInvalidExecutionContext ();
+ LazyBool
+ CanUpdateWithInvalidExecutionContext() override;
- virtual ClangASTType
- GetClangTypeImpl ()
+ CompilerType
+ GetCompilerTypeImpl() override
{
- return m_clang_type;
+ return m_compiler_type;
}
- ClangASTType m_clang_type;
+ CompilerType m_compiler_type;
ConstString m_type_name;
uint64_t m_byte_size;
int32_t m_byte_offset;
@@ -101,6 +103,7 @@ protected:
uint8_t m_bitfield_bit_offset;
bool m_is_base_class;
bool m_is_deref_of_parent;
+ llvm::Optional<LazyBool> m_can_update_with_invalid_exe_ctx;
//
// void
@@ -110,8 +113,9 @@ protected:
friend class ValueObject;
friend class ValueObjectConstResult;
friend class ValueObjectConstResultImpl;
+
ValueObjectChild (ValueObject &parent,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
uint64_t byte_size,
int32_t byte_offset,
@@ -119,11 +123,12 @@ protected:
uint32_t bitfield_bit_offset,
bool is_base_class,
bool is_deref_of_parent,
- AddressType child_ptr_or_ref_addr_type);
+ AddressType child_ptr_or_ref_addr_type,
+ uint64_t language_flags);
DISALLOW_COPY_AND_ASSIGN (ValueObjectChild);
};
} // namespace lldb_private
-#endif // liblldb_ValueObjectChild_h_
+#endif // liblldb_ValueObjectChild_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResult.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResult.h
index 4e05d501..f63ee83 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResult.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResult.h
@@ -26,6 +26,8 @@ namespace lldb_private {
class ValueObjectConstResult : public ValueObject
{
public:
+ ~ValueObjectConstResult() override;
+
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope,
lldb::ByteOrder byte_order,
@@ -34,14 +36,14 @@ public:
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
const DataExtractor &data,
lldb::addr_t address = LLDB_INVALID_ADDRESS);
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
const lldb::DataBufferSP &result_data_sp,
lldb::ByteOrder byte_order,
@@ -50,7 +52,7 @@ public:
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
lldb::addr_t address,
AddressType address_type,
@@ -67,76 +69,76 @@ public:
Create (ExecutionContextScope *exe_scope,
const Error& error);
- virtual ~ValueObjectConstResult();
-
- virtual uint64_t
- GetByteSize();
+ uint64_t
+ GetByteSize() override;
- virtual lldb::ValueType
- GetValueType() const;
+ lldb::ValueType
+ GetValueType() const override;
- virtual size_t
- CalculateNumChildren();
+ size_t
+ CalculateNumChildren(uint32_t max) override;
- virtual ConstString
- GetTypeName();
+ ConstString
+ GetTypeName() override;
- virtual ConstString
- GetDisplayTypeName();
+ ConstString
+ GetDisplayTypeName() override;
- virtual bool
- IsInScope ();
+ bool
+ IsInScope() override;
void
SetByteSize (size_t size);
- virtual lldb::ValueObjectSP
- Dereference (Error &error);
+ lldb::ValueObjectSP
+ Dereference(Error &error) override;
- virtual ValueObject *
- CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index);
+ ValueObject *
+ CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) override;
- virtual lldb::ValueObjectSP
- GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create);
+ lldb::ValueObjectSP
+ GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create) override;
- virtual lldb::ValueObjectSP
- AddressOf (Error &error);
+ lldb::ValueObjectSP
+ AddressOf(Error &error) override;
- virtual lldb::addr_t
- GetAddressOf (bool scalar_is_load_address = true,
- AddressType *address_type = NULL);
+ lldb::addr_t
+ GetAddressOf(bool scalar_is_load_address = true,
+ AddressType *address_type = nullptr) override;
- virtual size_t
- GetPointeeData (DataExtractor& data,
- uint32_t item_idx = 0,
- uint32_t item_count = 1);
+ size_t
+ GetPointeeData(DataExtractor& data,
+ uint32_t item_idx = 0,
+ uint32_t item_count = 1) override;
- virtual lldb::addr_t
- GetLiveAddress()
+ lldb::addr_t
+ GetLiveAddress() override
{
return m_impl.GetLiveAddress();
}
- virtual void
+ void
SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS,
- AddressType address_type = eAddressTypeLoad)
+ AddressType address_type = eAddressTypeLoad) override
{
- m_impl.SetLiveAddress(addr,
- address_type);
+ m_impl.SetLiveAddress(addr, address_type);
}
- virtual lldb::ValueObjectSP
- GetDynamicValue (lldb::DynamicValueType valueType);
+ lldb::ValueObjectSP
+ GetDynamicValue(lldb::DynamicValueType valueType) override;
- virtual lldb::LanguageType
- GetPreferredDisplayLanguage ();
+ lldb::LanguageType
+ GetPreferredDisplayLanguage() override;
+
+ lldb::ValueObjectSP
+ Cast(const CompilerType &compiler_type) override;
protected:
- virtual bool
- UpdateValue ();
+ bool
+ UpdateValue() override;
- virtual ClangASTType
- GetClangTypeImpl ();
+ CompilerType
+ GetCompilerTypeImpl() override;
ConstString m_type_name;
uint64_t m_byte_size;
@@ -145,19 +147,20 @@ protected:
private:
friend class ValueObjectConstResultImpl;
+
ValueObjectConstResult (ExecutionContextScope *exe_scope,
lldb::ByteOrder byte_order,
uint32_t addr_byte_size,
lldb::addr_t address);
ValueObjectConstResult (ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
const DataExtractor &data,
lldb::addr_t address);
ValueObjectConstResult (ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
const lldb::DataBufferSP &result_data_sp,
lldb::ByteOrder byte_order,
@@ -165,7 +168,7 @@ private:
lldb::addr_t address);
ValueObjectConstResult (ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
lldb::addr_t address,
AddressType address_type,
@@ -184,4 +187,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ValueObjectConstResult_h_
+#endif // liblldb_ValueObjectConstResult_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultCast.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultCast.h
new file mode 100644
index 0000000..395820d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultCast.h
@@ -0,0 +1,76 @@
+//===-- ValueObjectConstResultCast.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ValueObjectConstResultCast_h_
+#define liblldb_ValueObjectConstResultCast_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ValueObjectCast.h"
+#include "lldb/Core/ValueObjectConstResultImpl.h"
+
+namespace lldb_private {
+
+class ValueObjectConstResultCast : public ValueObjectCast
+{
+public:
+ ValueObjectConstResultCast (
+ ValueObject &parent,
+ const ConstString &name,
+ const CompilerType &cast_type,
+ lldb::addr_t live_address = LLDB_INVALID_ADDRESS);
+
+ ~ValueObjectConstResultCast() override;
+
+ lldb::ValueObjectSP
+ Dereference(Error &error) override;
+
+ ValueObject *
+ CreateChildAtIndex(size_t idx,
+ bool synthetic_array_member,
+ int32_t synthetic_index) override;
+
+ virtual CompilerType
+ GetCompilerType ()
+ {
+ return ValueObjectCast::GetCompilerType();
+ }
+
+ lldb::ValueObjectSP
+ GetSyntheticChildAtOffset(uint32_t offset,
+ const CompilerType& type,
+ bool can_create) override;
+
+ lldb::ValueObjectSP
+ AddressOf (Error &error) override;
+
+ size_t
+ GetPointeeData (DataExtractor& data,
+ uint32_t item_idx = 0,
+ uint32_t item_count = 1) override;
+
+ lldb::ValueObjectSP
+ Cast (const CompilerType &compiler_type) override;
+
+protected:
+ ValueObjectConstResultImpl m_impl;
+
+private:
+ friend class ValueObject;
+ friend class ValueObjectConstResult;
+ friend class ValueObjectConstResultImpl;
+
+ DISALLOW_COPY_AND_ASSIGN (ValueObjectConstResultCast);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ValueObjectConstResultCast_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultChild.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultChild.h
index 9063276..356d175 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultChild.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultChild.h
@@ -27,39 +27,44 @@ class ValueObjectConstResultChild : public ValueObjectChild
public:
ValueObjectConstResultChild (ValueObject &parent,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
uint32_t byte_size,
int32_t byte_offset,
uint32_t bitfield_bit_size,
uint32_t bitfield_bit_offset,
bool is_base_class,
- bool is_deref_of_parent);
+ bool is_deref_of_parent,
+ lldb::addr_t live_address,
+ uint64_t language_flags);
- virtual ~ValueObjectConstResultChild();
+ ~ValueObjectConstResultChild() override;
- virtual lldb::ValueObjectSP
- Dereference (Error &error);
+ lldb::ValueObjectSP
+ Dereference(Error &error) override;
- virtual ValueObject *
- CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index);
+ ValueObject *
+ CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) override;
- virtual ClangASTType
- GetClangType ()
+ virtual CompilerType
+ GetCompilerType ()
{
- return ValueObjectChild::GetClangType();
+ return ValueObjectChild::GetCompilerType();
}
- virtual lldb::ValueObjectSP
- GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create);
+ lldb::ValueObjectSP
+ GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create) override;
- virtual lldb::ValueObjectSP
- AddressOf (Error &error);
+ lldb::ValueObjectSP
+ AddressOf (Error &error) override;
- virtual size_t
+ size_t
GetPointeeData (DataExtractor& data,
uint32_t item_idx = 0,
- uint32_t item_count = 1);
+ uint32_t item_count = 1) override;
+
+ lldb::ValueObjectSP
+ Cast (const CompilerType &compiler_type) override;
protected:
ValueObjectConstResultImpl m_impl;
@@ -74,4 +79,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ValueObjectConstResultChild_h_
+#endif // liblldb_ValueObjectConstResultChild_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultImpl.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultImpl.h
index e3574e8..36b82f0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultImpl.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectConstResultImpl.h
@@ -1,4 +1,4 @@
-//===-- ValueObjectConstResultImpl.h -----------------------------*- C++ -*-===//
+//===-- ValueObjectConstResultImpl.h ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -26,15 +26,12 @@ namespace lldb_private {
class ValueObjectConstResultImpl
{
public:
-
ValueObjectConstResultImpl (ValueObject* valobj,
lldb::addr_t live_address = LLDB_INVALID_ADDRESS);
-
+
virtual
- ~ValueObjectConstResultImpl()
- {
- }
-
+ ~ValueObjectConstResultImpl() = default;
+
lldb::ValueObjectSP
Dereference (Error &error);
@@ -42,7 +39,7 @@ public:
CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index);
lldb::ValueObjectSP
- GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create);
+ GetSyntheticChildAtOffset (uint32_t offset, const CompilerType& type, bool can_create);
lldb::ValueObjectSP
AddressOf (Error &error);
@@ -52,6 +49,9 @@ public:
{
return m_live_address;
}
+
+ lldb::ValueObjectSP
+ Cast (const CompilerType &compiler_type);
void
SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS,
@@ -62,16 +62,15 @@ public:
}
virtual lldb::addr_t
- GetAddressOf (bool scalar_is_load_address = true,
- AddressType *address_type = NULL);
+ GetAddressOf(bool scalar_is_load_address = true,
+ AddressType *address_type = nullptr);
virtual size_t
- GetPointeeData (DataExtractor& data,
- uint32_t item_idx = 0,
- uint32_t item_count = 1);
+ GetPointeeData(DataExtractor& data,
+ uint32_t item_idx = 0,
+ uint32_t item_count = 1);
private:
-
ValueObject *m_impl_backend;
lldb::addr_t m_live_address;
AddressType m_live_address_type;
@@ -83,4 +82,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ValueObjectConstResultImpl_h_
+#endif // liblldb_ValueObjectConstResultImpl_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectDynamicValue.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectDynamicValue.h
index 8d42706..80f37f1 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectDynamicValue.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectDynamicValue.h
@@ -1,4 +1,4 @@
-//===-- ValueObjectDynamicValue.h -----------------------------------*- C++ -*-===//
+//===-- ValueObjectDynamicValue.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -26,109 +26,131 @@ namespace lldb_private {
class ValueObjectDynamicValue : public ValueObject
{
public:
- virtual
- ~ValueObjectDynamicValue();
+ ~ValueObjectDynamicValue() override;
- virtual uint64_t
- GetByteSize();
+ uint64_t
+ GetByteSize() override;
- virtual ConstString
- GetTypeName();
+ ConstString
+ GetTypeName() override;
- virtual ConstString
- GetQualifiedTypeName();
+ ConstString
+ GetQualifiedTypeName() override;
- virtual ConstString
- GetDisplayTypeName();
+ ConstString
+ GetDisplayTypeName() override;
- virtual size_t
- CalculateNumChildren();
+ size_t
+ CalculateNumChildren(uint32_t max) override;
- virtual lldb::ValueType
- GetValueType() const;
+ lldb::ValueType
+ GetValueType() const override;
- virtual bool
- IsInScope ();
+ bool
+ IsInScope() override;
- virtual bool
- IsDynamic ()
+ bool
+ IsDynamic() override
{
return true;
}
- virtual bool
- GetIsConstant () const
+ bool
+ IsBaseClass () override
{
+ if (m_parent)
+ return m_parent->IsBaseClass();
return false;
}
- virtual ValueObject *
- GetParent()
+ bool
+ GetIsConstant() const override
{
- if (m_parent)
- return m_parent->GetParent();
- else
- return NULL;
+ return false;
+ }
+
+ ValueObject *
+ GetParent() override
+ {
+ return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
}
- virtual const ValueObject *
- GetParent() const
+ const ValueObject *
+ GetParent() const override
{
- if (m_parent)
- return m_parent->GetParent();
- else
- return NULL;
+ return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
}
- virtual lldb::ValueObjectSP
- GetStaticValue ()
+ lldb::ValueObjectSP
+ GetStaticValue() override
{
return m_parent->GetSP();
}
-
+
void
SetOwningSP (lldb::ValueObjectSP &owning_sp)
{
if (m_owning_valobj_sp == owning_sp)
return;
- assert (m_owning_valobj_sp.get() == NULL);
+ assert (m_owning_valobj_sp.get() == nullptr);
m_owning_valobj_sp = owning_sp;
}
- virtual bool
- SetValueFromCString (const char *value_str, Error& error);
+ bool
+ SetValueFromCString(const char *value_str, Error& error) override;
+
+ bool
+ SetData(DataExtractor &data, Error &error) override;
+
+ TypeImpl
+ GetTypeImpl() override;
+
+ lldb::VariableSP
+ GetVariable () override
+ {
+ return m_parent ? m_parent->GetVariable() : nullptr;
+ }
+
+ lldb::LanguageType
+ GetPreferredDisplayLanguage() override;
- virtual bool
- SetData (DataExtractor &data, Error &error);
+ void
+ SetPreferredDisplayLanguage (lldb::LanguageType);
+
+ bool
+ GetDeclaration(Declaration &decl) override;
- virtual TypeImpl
- GetTypeImpl ();
+ uint64_t
+ GetLanguageFlags () override;
+ void
+ SetLanguageFlags (uint64_t flags) override;
+
protected:
- virtual bool
- UpdateValue ();
+ bool
+ UpdateValue() override;
- virtual bool
- CanUpdateWithInvalidExecutionContext ()
+ LazyBool
+ CanUpdateWithInvalidExecutionContext() override
{
- return true;
+ return eLazyBoolYes;
}
- virtual lldb::DynamicValueType
- GetDynamicValueTypeImpl ()
+ lldb::DynamicValueType
+ GetDynamicValueTypeImpl() override
{
return m_use_dynamic;
}
- virtual bool
- HasDynamicValueTypeInfo ()
+ bool
+ HasDynamicValueTypeInfo() override
{
return true;
}
- virtual ClangASTType
- GetClangTypeImpl ();
+ CompilerType
+ GetCompilerTypeImpl() override;
Address m_address; ///< The variable that this value object is based upon
TypeAndOrName m_dynamic_type_info; // We can have a type_sp or just a name
@@ -141,12 +163,9 @@ private:
friend class ValueObjectConstResult;
ValueObjectDynamicValue (ValueObject &parent, lldb::DynamicValueType use_dynamic);
- //------------------------------------------------------------------
- // For ValueObject only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (ValueObjectDynamicValue);
};
} // namespace lldb_private
-#endif // liblldb_ValueObjectDynamicValue_h_
+#endif // liblldb_ValueObjectDynamicValue_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectList.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectList.h
index 6565367..4f5e7b2 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectList.h
@@ -17,7 +17,6 @@
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
-#include "lldb/Core/ClangForward.h"
#include "lldb/Core/UserID.h"
#include "lldb/Target/ExecutionContextScope.h"
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectMemory.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectMemory.h
index 41b4318..0e12fc7 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectMemory.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectMemory.h
@@ -15,7 +15,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
namespace lldb_private {
@@ -26,6 +26,8 @@ namespace lldb_private {
class ValueObjectMemory : public ValueObject
{
public:
+ ~ValueObjectMemory() override;
+
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope,
const char *name,
@@ -36,42 +38,39 @@ public:
Create (ExecutionContextScope *exe_scope,
const char *name,
const Address &address,
- const ClangASTType &ast_type);
-
- virtual
- ~ValueObjectMemory();
+ const CompilerType &ast_type);
- virtual uint64_t
- GetByteSize();
+ uint64_t
+ GetByteSize() override;
- virtual ConstString
- GetTypeName();
+ ConstString
+ GetTypeName() override;
- virtual ConstString
- GetDisplayTypeName();
+ ConstString
+ GetDisplayTypeName() override;
- virtual size_t
- CalculateNumChildren();
+ size_t
+ CalculateNumChildren(uint32_t max) override;
- virtual lldb::ValueType
- GetValueType() const;
+ lldb::ValueType
+ GetValueType() const override;
- virtual bool
- IsInScope ();
+ bool
+ IsInScope() override;
- virtual lldb::ModuleSP
- GetModule();
+ lldb::ModuleSP
+ GetModule() override;
protected:
- virtual bool
- UpdateValue ();
+ bool
+ UpdateValue() override;
- virtual ClangASTType
- GetClangTypeImpl ();
+ CompilerType
+ GetCompilerTypeImpl() override;
Address m_address; ///< The variable that this value object is based upon
lldb::TypeSP m_type_sp;
- ClangASTType m_clang_type;
+ CompilerType m_compiler_type;
private:
ValueObjectMemory (ExecutionContextScope *exe_scope,
@@ -82,7 +81,7 @@ private:
ValueObjectMemory (ExecutionContextScope *exe_scope,
const char *name,
const Address &address,
- const ClangASTType &ast_type);
+ const CompilerType &ast_type);
//------------------------------------------------------------------
// For ValueObject only
//------------------------------------------------------------------
@@ -91,4 +90,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ValueObjectMemory_h_
+#endif // liblldb_ValueObjectMemory_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectRegister.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectRegister.h
index f7c7683..ac76f9e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectRegister.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectRegister.h
@@ -27,40 +27,38 @@ namespace lldb_private {
class ValueObjectRegisterContext : public ValueObject
{
public:
+ ~ValueObjectRegisterContext() override;
- virtual
- ~ValueObjectRegisterContext();
+ uint64_t
+ GetByteSize() override;
- virtual uint64_t
- GetByteSize();
-
- virtual lldb::ValueType
- GetValueType () const
+ lldb::ValueType
+ GetValueType() const override
{
return lldb::eValueTypeRegisterSet;
}
- virtual ConstString
- GetTypeName();
+ ConstString
+ GetTypeName() override;
- virtual ConstString
- GetQualifiedTypeName();
+ ConstString
+ GetQualifiedTypeName() override;
- virtual ConstString
- GetDisplayTypeName();
+ ConstString
+ GetDisplayTypeName() override;
- virtual size_t
- CalculateNumChildren();
+ size_t
+ CalculateNumChildren(uint32_t max) override;
- virtual ValueObject *
- CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index);
+ ValueObject *
+ CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) override;
protected:
- virtual bool
- UpdateValue ();
+ bool
+ UpdateValue() override;
- virtual ClangASTType
- GetClangTypeImpl ();
+ CompilerType
+ GetCompilerTypeImpl() override;
lldb::RegisterContextSP m_reg_ctx_sp;
@@ -75,46 +73,44 @@ private:
class ValueObjectRegisterSet : public ValueObject
{
public:
+ ~ValueObjectRegisterSet() override;
+
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP &reg_ctx_sp, uint32_t set_idx);
- virtual
- ~ValueObjectRegisterSet();
-
- virtual uint64_t
- GetByteSize();
+ uint64_t
+ GetByteSize() override;
- virtual lldb::ValueType
- GetValueType () const
+ lldb::ValueType
+ GetValueType() const override
{
return lldb::eValueTypeRegisterSet;
}
- virtual ConstString
- GetTypeName();
+ ConstString
+ GetTypeName() override;
- virtual ConstString
- GetQualifiedTypeName();
+ ConstString
+ GetQualifiedTypeName() override;
- virtual size_t
- CalculateNumChildren();
+ size_t
+ CalculateNumChildren(uint32_t max) override;
- virtual ValueObject *
- CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index);
+ ValueObject *
+ CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) override;
- virtual lldb::ValueObjectSP
- GetChildMemberWithName (const ConstString &name, bool can_create);
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ lldb::ValueObjectSP
+ GetChildMemberWithName(const ConstString &name, bool can_create) override;
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
protected:
- virtual bool
- UpdateValue ();
+ bool
+ UpdateValue() override;
- virtual ClangASTType
- GetClangTypeImpl ();
+ CompilerType
+ GetCompilerTypeImpl() override;
lldb::RegisterContextSP m_reg_ctx_sp;
const RegisterSet *m_reg_set;
@@ -122,6 +118,7 @@ protected:
private:
friend class ValueObjectRegisterContext;
+
ValueObjectRegisterSet (ExecutionContextScope *exe_scope, lldb::RegisterContextSP &reg_ctx_sp, uint32_t set_idx);
//------------------------------------------------------------------
@@ -133,57 +130,58 @@ private:
class ValueObjectRegister : public ValueObject
{
public:
+ ~ValueObjectRegister() override;
+
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP &reg_ctx_sp, uint32_t reg_num);
- virtual
- ~ValueObjectRegister();
-
- virtual uint64_t
- GetByteSize();
+ uint64_t
+ GetByteSize() override;
- virtual lldb::ValueType
- GetValueType () const
+ lldb::ValueType
+ GetValueType() const override
{
return lldb::eValueTypeRegister;
}
- virtual ConstString
- GetTypeName();
+ ConstString
+ GetTypeName() override;
- virtual size_t
- CalculateNumChildren();
+ size_t
+ CalculateNumChildren(uint32_t max) override;
- virtual bool
- SetValueFromCString (const char *value_str, Error& error);
+ bool
+ SetValueFromCString(const char *value_str, Error& error) override;
- virtual bool
- SetData (DataExtractor &data, Error &error);
+ bool
+ SetData(DataExtractor &data, Error &error) override;
- virtual bool
- ResolveValue (Scalar &scalar);
+ bool
+ ResolveValue(Scalar &scalar) override;
- virtual void
- GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat = eGetExpressionPathFormatDereferencePointers);
+ void
+ GetExpressionPath(Stream &s, bool qualify_cxx_base_classes,
+ GetExpressionPathFormat epformat = eGetExpressionPathFormatDereferencePointers) override;
protected:
- virtual bool
- UpdateValue ();
+ bool
+ UpdateValue() override;
- virtual ClangASTType
- GetClangTypeImpl ();
+ CompilerType
+ GetCompilerTypeImpl() override;
lldb::RegisterContextSP m_reg_ctx_sp;
RegisterInfo m_reg_info;
RegisterValue m_reg_value;
ConstString m_type_name;
- ClangASTType m_clang_type;
+ CompilerType m_compiler_type;
private:
void
ConstructObject (uint32_t reg_num);
friend class ValueObjectRegisterSet;
+
ValueObjectRegister (ValueObject &parent, lldb::RegisterContextSP &reg_ctx_sp, uint32_t reg_num);
ValueObjectRegister (ExecutionContextScope *exe_scope, lldb::RegisterContextSP &reg_ctx_sp, uint32_t reg_num);
@@ -195,4 +193,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ValueObjectRegister_h_
+#endif // liblldb_ValueObjectRegister_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
index 88824ef..05bc3781 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
@@ -1,4 +1,4 @@
-//===-- ValueObjectSyntheticFilter.h -------------------------------*- C++ -*-===//
+//===-- ValueObjectSyntheticFilter.h ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,7 +12,8 @@
// C Includes
// C++ Includes
-#include <vector>
+#include <memory>
+
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ThreadSafeSTLMap.h"
@@ -30,140 +31,142 @@ namespace lldb_private {
class ValueObjectSynthetic : public ValueObject
{
public:
- virtual
- ~ValueObjectSynthetic();
+ ~ValueObjectSynthetic() override;
- virtual uint64_t
- GetByteSize();
+ uint64_t
+ GetByteSize() override;
- virtual ConstString
- GetTypeName();
+ ConstString
+ GetTypeName() override;
- virtual ConstString
- GetQualifiedTypeName();
+ ConstString
+ GetQualifiedTypeName() override;
- virtual ConstString
- GetDisplayTypeName();
+ ConstString
+ GetDisplayTypeName() override;
- virtual bool
- MightHaveChildren();
+ bool
+ MightHaveChildren() override;
- virtual size_t
- CalculateNumChildren();
+ size_t
+ CalculateNumChildren(uint32_t max) override;
- virtual lldb::ValueType
- GetValueType() const;
+ lldb::ValueType
+ GetValueType() const override;
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx, bool can_create);
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx, bool can_create) override;
- virtual lldb::ValueObjectSP
- GetChildMemberWithName (const ConstString &name, bool can_create);
+ lldb::ValueObjectSP
+ GetChildMemberWithName(const ConstString &name, bool can_create) override;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
- virtual lldb::ValueObjectSP
- GetDynamicValue (lldb::DynamicValueType valueType);
+ lldb::ValueObjectSP
+ GetDynamicValue(lldb::DynamicValueType valueType) override;
- virtual bool
- IsInScope ();
+ bool
+ IsInScope() override;
- virtual bool
- HasSyntheticValue()
+ bool
+ HasSyntheticValue() override
{
return false;
}
- virtual bool
- IsSynthetic() { return true; }
+ bool
+ IsSynthetic() override
+ {
+ return true;
+ }
- virtual void
- CalculateSyntheticValue (bool use_synthetic)
+ void
+ CalculateSyntheticValue(bool use_synthetic) override
{
}
- virtual bool
- IsDynamic ()
+ bool
+ IsDynamic() override
{
- if (m_parent)
- return m_parent->IsDynamic();
- else
- return false;
+ return ((m_parent != nullptr) ? m_parent->IsDynamic() : false);
}
- virtual lldb::ValueObjectSP
- GetStaticValue ()
+ lldb::ValueObjectSP
+ GetStaticValue() override
{
- if (m_parent)
- return m_parent->GetStaticValue();
- else
- return GetSP();
+ return ((m_parent != nullptr) ? m_parent->GetStaticValue() : GetSP());
}
virtual lldb::DynamicValueType
GetDynamicValueType ()
{
- if (m_parent)
- return m_parent->GetDynamicValueType();
- else
- return lldb::eNoDynamicValues;
+ return ((m_parent != nullptr) ? m_parent->GetDynamicValueType() : lldb::eNoDynamicValues);
}
- virtual ValueObject *
- GetParent()
+ ValueObject *
+ GetParent() override
{
- if (m_parent)
- return m_parent->GetParent();
- else
- return NULL;
+ return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
}
- virtual const ValueObject *
- GetParent() const
+ const ValueObject *
+ GetParent() const override
{
- if (m_parent)
- return m_parent->GetParent();
- else
- return NULL;
+ return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
}
- virtual lldb::ValueObjectSP
- GetNonSyntheticValue ();
+ lldb::ValueObjectSP
+ GetNonSyntheticValue() override;
- virtual bool
- CanProvideValue ();
+ bool
+ CanProvideValue() override;
- virtual bool
- DoesProvideSyntheticValue ()
+ bool
+ DoesProvideSyntheticValue() override
{
return (UpdateValueIfNeeded(), m_provides_value == eLazyBoolYes);
}
- virtual bool
- GetIsConstant () const
+ bool
+ GetIsConstant() const override
{
return false;
}
- virtual bool
- SetValueFromCString (const char *value_str, Error& error);
+ bool
+ SetValueFromCString(const char *value_str, Error& error) override;
- virtual void
- SetFormat (lldb::Format format);
+ void
+ SetFormat(lldb::Format format) override;
+
+ lldb::LanguageType
+ GetPreferredDisplayLanguage() override;
+
+ void
+ SetPreferredDisplayLanguage (lldb::LanguageType);
+
+ bool
+ GetDeclaration(Declaration &decl) override;
+
+ uint64_t
+ GetLanguageFlags () override;
+
+ void
+ SetLanguageFlags (uint64_t flags) override;
protected:
- virtual bool
- UpdateValue ();
+ bool
+ UpdateValue() override;
- virtual bool
- CanUpdateWithInvalidExecutionContext ()
+ LazyBool
+ CanUpdateWithInvalidExecutionContext() override
{
- return true;
+ return eLazyBoolYes;
}
- virtual ClangASTType
- GetClangTypeImpl ();
+ CompilerType
+ GetCompilerTypeImpl() override;
virtual void
CreateSynthFilter ();
@@ -195,12 +198,9 @@ private:
void
CopyValueData (ValueObject *source);
- //------------------------------------------------------------------
- // For ValueObject only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (ValueObjectSynthetic);
};
} // namespace lldb_private
-#endif // liblldb_ValueObjectSyntheticFilter_h_
+#endif // liblldb_ValueObjectSyntheticFilter_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectVariable.h b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectVariable.h
index 0e32d09..4adb6ba 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectVariable.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/ValueObjectVariable.h
@@ -25,61 +25,66 @@ namespace lldb_private {
class ValueObjectVariable : public ValueObject
{
public:
+ ~ValueObjectVariable() override;
+
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp);
- virtual
- ~ValueObjectVariable();
-
- virtual uint64_t
- GetByteSize();
+ uint64_t
+ GetByteSize() override;
- virtual ConstString
- GetTypeName();
+ ConstString
+ GetTypeName() override;
- virtual ConstString
- GetQualifiedTypeName();
+ ConstString
+ GetQualifiedTypeName() override;
- virtual ConstString
- GetDisplayTypeName();
+ ConstString
+ GetDisplayTypeName() override;
- virtual size_t
- CalculateNumChildren();
+ size_t
+ CalculateNumChildren(uint32_t max) override;
- virtual lldb::ValueType
- GetValueType() const;
+ lldb::ValueType
+ GetValueType() const override;
- virtual bool
- IsInScope ();
+ bool
+ IsInScope() override;
- virtual lldb::ModuleSP
- GetModule();
+ lldb::ModuleSP
+ GetModule() override;
- virtual SymbolContextScope *
- GetSymbolContextScope();
+ SymbolContextScope *
+ GetSymbolContextScope() override;
- virtual bool
- GetDeclaration (Declaration &decl);
+ bool
+ GetDeclaration(Declaration &decl) override;
- virtual const char *
- GetLocationAsCString ();
+ const char *
+ GetLocationAsCString() override;
- virtual bool
- SetValueFromCString (const char *value_str, Error& error);
+ bool
+ SetValueFromCString(const char *value_str, Error& error) override;
- virtual bool
- SetData (DataExtractor &data, Error &error);
+ bool
+ SetData(DataExtractor &data, Error &error) override;
+
+ virtual lldb::VariableSP
+ GetVariable () override
+ {
+ return m_variable_sp;
+ }
protected:
- virtual bool
- UpdateValue ();
+ bool
+ UpdateValue() override;
- virtual ClangASTType
- GetClangTypeImpl ();
+ CompilerType
+ GetCompilerTypeImpl() override;
lldb::VariableSP m_variable_sp; ///< The variable that this value object is based upon
Value m_resolved_value; ///< The value that DWARFExpression resolves this variable to before we patch it up
-
+
private:
ValueObjectVariable (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp);
//------------------------------------------------------------------
@@ -90,4 +95,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ValueObjectVariable_h_
+#endif // liblldb_ValueObjectVariable_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Core/dwarf.h b/contrib/llvm/tools/lldb/include/lldb/Core/dwarf.h
index 9fa8816..649a931 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Core/dwarf.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Core/dwarf.h
@@ -14,13 +14,16 @@
// Get the DWARF constant definitions from llvm
#include "llvm/Support/Dwarf.h"
+
+#include "lldb/Core/RangeMap.h"
+
// and stuff them in our default namespace
using namespace llvm::dwarf;
typedef uint32_t dw_uleb128_t;
typedef int32_t dw_sleb128_t;
typedef uint16_t dw_attr_t;
-typedef uint8_t dw_form_t;
+typedef uint16_t dw_form_t;
typedef uint16_t dw_tag_t;
typedef uint64_t dw_addr_t; // Dwarf address define that must be big enough for any addresses in the compile units that get parsed
@@ -59,5 +62,6 @@ typedef uint32_t dw_offset_t; // Dwarf Debug Information Entry offset for
//#define DW_OP_APPLE_clear 0xFE // clears the entire expression stack, ok if the stack is empty
//#define DW_OP_APPLE_error 0xFF // Stops expression evaluation and returns an error (no args)
+typedef lldb_private::RangeArray<dw_addr_t, dw_addr_t, 2> DWARFRangeList;
#endif // DebugBase_dwarf_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/CXXFormatterFunctions.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/CXXFormatterFunctions.h
deleted file mode 100644
index a175e1a..0000000
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/CXXFormatterFunctions.h
+++ /dev/null
@@ -1,375 +0,0 @@
-//===-- CXXFormatterFunctions.h------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_CXXFormatterFunctions_h_
-#define liblldb_CXXFormatterFunctions_h_
-
-#include <stdint.h>
-#include <time.h>
-
-#include "lldb/lldb-forward.h"
-
-#include "lldb/Core/ConstString.h"
-#include "lldb/DataFormatters/FormatClasses.h"
-#include "lldb/DataFormatters/TypeSynthetic.h"
-#include "lldb/DataFormatters/VectorType.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/Target.h"
-
-#include "clang/AST/ASTContext.h"
-
-namespace lldb_private {
- namespace formatters
- {
- StackFrame*
- GetViableFrame (ExecutionContext exe_ctx);
-
- bool
- ExtractValueFromObjCExpression (ValueObject &valobj,
- const char* target_type,
- const char* selector,
- uint64_t &value);
-
- bool
- ExtractSummaryFromObjCExpression (ValueObject &valobj,
- const char* target_type,
- const char* selector,
- Stream &stream);
-
- lldb::ValueObjectSP
- CallSelectorOnObject (ValueObject &valobj,
- const char* return_type,
- const char* selector,
- uint64_t index);
-
- lldb::ValueObjectSP
- CallSelectorOnObject (ValueObject &valobj,
- const char* return_type,
- const char* selector,
- const char* key);
-
- size_t
- ExtractIndexFromString (const char* item_name);
-
- time_t
- GetOSXEpoch ();
-
- bool
- FunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // C++ function pointer
-
- bool
- Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t* and unichar*
-
- bool
- Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t*
-
- bool
- WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t*
-
- bool
- Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t and unichar
-
- bool
- Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t
-
- bool
- WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t
-
- bool
- LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::string
-
- bool
- LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::wstring
-
- bool
- LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::shared_ptr<> and std::weak_ptr<>
-
- bool
- ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- SyntheticChildrenFrontEnd* ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- template<bool name_entries>
- bool
- NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- template<bool cf_style>
- bool
- NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- template<bool needs_at>
- bool
- NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream);
-
- bool
- NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- template <bool is_sel_ptr>
- bool
- ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- bool
- RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- extern template bool
- NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
-
- extern template bool
- NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
-
- extern template bool
- NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
-
- extern template bool
- NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
-
- extern template bool
- ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&);
-
- extern template bool
- ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&);
-
- bool
- CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- SyntheticChildrenFrontEnd* NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- SyntheticChildrenFrontEnd* NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- SyntheticChildrenFrontEnd* NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd
- {
- public:
- LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
-
- virtual bool
- MightHaveChildren ();
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
-
- virtual
- ~LibcxxVectorBoolSyntheticFrontEnd ();
- private:
- ClangASTType m_bool_type;
- ExecutionContextRef m_exe_ctx_ref;
- uint64_t m_count;
- lldb::addr_t m_base_data_address;
- std::map<size_t,lldb::ValueObjectSP> m_children;
- };
-
- SyntheticChildrenFrontEnd* LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- bool
- LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
-
- class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
- {
- public:
- LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
-
- virtual bool
- MightHaveChildren ();
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
-
- virtual
- ~LibstdcppMapIteratorSyntheticFrontEnd ();
- private:
- ExecutionContextRef m_exe_ctx_ref;
- lldb::addr_t m_pair_address;
- ClangASTType m_pair_type;
- EvaluateExpressionOptions m_options;
- lldb::ValueObjectSP m_pair_sp;
- };
-
- SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
- {
- public:
- LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
-
- virtual bool
- MightHaveChildren ();
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
-
- virtual
- ~LibCxxMapIteratorSyntheticFrontEnd ();
- private:
- ValueObject *m_pair_ptr;
- };
-
- SyntheticChildrenFrontEnd* LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
- {
- public:
- VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
- ConstString item_name);
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
-
- virtual bool
- MightHaveChildren ();
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
-
- virtual
- ~VectorIteratorSyntheticFrontEnd ();
- private:
- ExecutionContextRef m_exe_ctx_ref;
- ConstString m_item_name;
- lldb::ValueObjectSP m_item_sp;
- };
-
- SyntheticChildrenFrontEnd* LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd
- {
- public:
- LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
-
- virtual bool
- MightHaveChildren ();
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
-
- virtual
- ~LibcxxSharedPtrSyntheticFrontEnd ();
- private:
- ValueObject* m_cntrl;
- lldb::ValueObjectSP m_count_sp;
- lldb::ValueObjectSP m_weak_count_sp;
- uint8_t m_ptr_size;
- lldb::ByteOrder m_byte_order;
- };
-
- SyntheticChildrenFrontEnd* LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- SyntheticChildrenFrontEnd* LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- SyntheticChildrenFrontEnd* LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- SyntheticChildrenFrontEnd* LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- SyntheticChildrenFrontEnd* LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
- SyntheticChildrenFrontEnd* VectorTypeSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
- } // namespace formatters
-} // namespace lldb_private
-
-#endif // liblldb_CXXFormatterFunctions_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/CXXFunctionPointer.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/CXXFunctionPointer.h
new file mode 100644
index 0000000..eaa3958
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/CXXFunctionPointer.h
@@ -0,0 +1,23 @@
+//===-- CXXFunctionPointer.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CXXFunctionPointer_h_
+#define liblldb_CXXFunctionPointer_h_
+
+#include "lldb/lldb-forward.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ bool
+ CXXFunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CXXFunctionPointer_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/DataVisualization.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/DataVisualization.h
index a0b2e58..8561566 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/DataVisualization.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/DataVisualization.h
@@ -1,4 +1,4 @@
-//===-- DataVisualization.h ----------------------------------------*- C++ -*-===//
+//===-- DataVisualization.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -28,7 +28,6 @@ namespace lldb_private {
class DataVisualization
{
public:
-
// use this call to force the FM to consider itself updated even when there is no apparent reason for that
static void
ForceUpdate();
@@ -83,8 +82,8 @@ public:
AnyMatches(ConstString type_name,
TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES,
bool only_enabled = true,
- const char** matching_category = NULL,
- TypeCategoryImpl::FormatCategoryItems* matching_type = NULL);
+ const char** matching_category = nullptr,
+ TypeCategoryImpl::FormatCategoryItems* matching_type = nullptr);
class NamedSummaryFormats
{
@@ -102,7 +101,7 @@ public:
Clear ();
static void
- LoopThrough (TypeSummaryImpl::SummaryCallback callback, void* callback_baton);
+ ForEach (std::function<bool(ConstString, const lldb::TypeSummaryImplSP&)> callback);
static uint32_t
GetCount ();
@@ -111,12 +110,15 @@ public:
class Categories
{
public:
-
static bool
GetCategory (const ConstString &category,
lldb::TypeCategoryImplSP &entry,
bool allow_create = true);
+ static bool
+ GetCategory (lldb::LanguageType language,
+ lldb::TypeCategoryImplSP &entry);
+
static void
Add (const ConstString &category);
@@ -134,7 +136,13 @@ public:
TypeCategoryMap::Position = TypeCategoryMap::Default);
static void
+ Enable (lldb::LanguageType lang_type);
+
+ static void
Disable (const ConstString& category);
+
+ static void
+ Disable (lldb::LanguageType lang_type);
static void
Enable (const lldb::TypeCategoryImplSP& category,
@@ -150,7 +158,7 @@ public:
DisableStar ();
static void
- LoopThrough (FormatManager::CategoryCallback callback, void* callback_baton);
+ ForEach (TypeCategoryMap::ForEachCallback callback);
static uint32_t
GetCount ();
@@ -160,7 +168,6 @@ public:
};
};
-
} // namespace lldb_private
-#endif // lldb_DataVisualization_h_
+#endif// lldb_DataVisualization_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h
new file mode 100644
index 0000000..f65ee7b
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h
@@ -0,0 +1,185 @@
+//===-- DumpValueObjectOptions.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_DumpValueObjectOptions_h_
+#define lldb_DumpValueObjectOptions_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/lldb-public.h"
+
+#include <functional>
+#include <string>
+
+namespace lldb_private {
+
+class DumpValueObjectOptions
+{
+public:
+ struct PointerDepth
+ {
+ enum class Mode
+ {
+ Always,
+ Formatters,
+ Default,
+ Never
+ } m_mode;
+ uint32_t m_count;
+
+ PointerDepth
+ operator --() const
+ {
+ if (m_count > 0)
+ return PointerDepth {m_mode,m_count-1};
+ return PointerDepth {m_mode,m_count};
+ }
+
+ bool
+ CanAllowExpansion () const;
+
+ bool
+ CanAllowExpansion (bool is_root,
+ TypeSummaryImpl* entry,
+ ValueObject *valobj,
+ const std::string& summary);
+ };
+
+ typedef std::function<bool(ConstString,
+ ConstString,
+ const DumpValueObjectOptions &,
+ Stream&)> DeclPrintingHelper;
+
+ static const DumpValueObjectOptions
+ DefaultOptions()
+ {
+ static DumpValueObjectOptions g_default_options;
+
+ return g_default_options;
+ }
+
+ DumpValueObjectOptions();
+
+ DumpValueObjectOptions (const DumpValueObjectOptions& rhs) = default;
+
+ DumpValueObjectOptions (ValueObject& valobj);
+
+ DumpValueObjectOptions&
+ SetMaximumPointerDepth(PointerDepth depth = {PointerDepth::Mode::Never,0});
+
+ DumpValueObjectOptions&
+ SetMaximumDepth(uint32_t depth = 0);
+
+ DumpValueObjectOptions&
+ SetDeclPrintingHelper(DeclPrintingHelper helper);
+
+ DumpValueObjectOptions&
+ SetShowTypes(bool show = false);
+
+ DumpValueObjectOptions&
+ SetShowLocation(bool show = false);
+
+ DumpValueObjectOptions&
+ SetUseObjectiveC(bool use = false);
+
+ DumpValueObjectOptions&
+ SetShowSummary(bool show = true);
+
+ DumpValueObjectOptions&
+ SetUseDynamicType(lldb::DynamicValueType dyn = lldb::eNoDynamicValues);
+
+ DumpValueObjectOptions&
+ SetUseSyntheticValue(bool use_synthetic = true);
+
+ DumpValueObjectOptions&
+ SetScopeChecked(bool check = true);
+
+ DumpValueObjectOptions&
+ SetFlatOutput(bool flat = false);
+
+ DumpValueObjectOptions&
+ SetOmitSummaryDepth(uint32_t depth = 0);
+
+ DumpValueObjectOptions&
+ SetIgnoreCap(bool ignore = false);
+
+ DumpValueObjectOptions&
+ SetRawDisplay();
+
+ DumpValueObjectOptions&
+ SetFormat (lldb::Format format = lldb::eFormatDefault);
+
+ DumpValueObjectOptions&
+ SetSummary (lldb::TypeSummaryImplSP summary = lldb::TypeSummaryImplSP());
+
+ DumpValueObjectOptions&
+ SetRootValueObjectName(const char* name = nullptr);
+
+ DumpValueObjectOptions&
+ SetHideRootType (bool hide_root_type = false);
+
+ DumpValueObjectOptions&
+ SetHideName (bool hide_name = false);
+
+ DumpValueObjectOptions&
+ SetHideValue (bool hide_value = false);
+
+ DumpValueObjectOptions&
+ SetHidePointerValue (bool hide = false);
+
+ DumpValueObjectOptions&
+ SetVariableFormatDisplayLanguage (lldb::LanguageType lang = lldb::eLanguageTypeUnknown);
+
+ DumpValueObjectOptions&
+ SetRunValidator (bool run = true);
+
+ DumpValueObjectOptions&
+ SetUseTypeDisplayName (bool dis = false);
+
+ DumpValueObjectOptions&
+ SetAllowOnelinerMode (bool oneliner = false);
+
+ DumpValueObjectOptions&
+ SetRevealEmptyAggregates (bool reveal = true);
+
+public:
+ uint32_t m_max_depth = UINT32_MAX;
+ lldb::DynamicValueType m_use_dynamic = lldb::eNoDynamicValues;
+ uint32_t m_omit_summary_depth = 0;
+ lldb::Format m_format = lldb::eFormatDefault;
+ lldb::TypeSummaryImplSP m_summary_sp;
+ std::string m_root_valobj_name;
+ lldb::LanguageType m_varformat_language = lldb::eLanguageTypeUnknown;
+ PointerDepth m_max_ptr_depth;
+ DeclPrintingHelper m_decl_printing_helper;
+ bool m_use_synthetic : 1;
+ bool m_scope_already_checked : 1;
+ bool m_flat_output : 1;
+ bool m_ignore_cap : 1;
+ bool m_show_types : 1;
+ bool m_show_location : 1;
+ bool m_use_objc : 1;
+ bool m_hide_root_type : 1;
+ bool m_hide_name : 1;
+ bool m_hide_value : 1;
+ bool m_run_validator : 1;
+ bool m_use_type_display_name : 1;
+ bool m_allow_oneliner_mode : 1;
+ bool m_hide_pointer_value : 1;
+ bool m_reveal_empty_aggregates : 1;
+};
+
+} // namespace lldb_private
+
+#endif // lldb_DumpValueObjectOptions_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatCache.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatCache.h
index fa46306..9f1e078 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatCache.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatCache.h
@@ -19,7 +19,6 @@
#include "lldb/lldb-public.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Host/Mutex.h"
-#include "lldb/DataFormatters/FormatClasses.h"
namespace lldb_private {
class FormatCache
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatClasses.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatClasses.h
index 6511603..b5ac41c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatClasses.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatClasses.h
@@ -10,25 +10,45 @@
#ifndef lldb_FormatClasses_h_
#define lldb_FormatClasses_h_
+// C Includes
// C++ Includes
+#include <functional>
+#include <memory>
#include <string>
#include <vector>
// Other libraries and framework includes
-
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/lldb-enumerations.h"
-
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/DataFormatters/TypeFormat.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/DataFormatters/TypeValidator.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Type.h"
namespace lldb_private {
+class HardcodedFormatters {
+public:
+ template <typename FormatterType>
+ using HardcodedFormatterFinder = std::function<typename FormatterType::SharedPointer (lldb_private::ValueObject&,
+ lldb::DynamicValueType,
+ FormatManager&)>;
+
+ template <typename FormatterType>
+ using HardcodedFormatterFinders = std::vector<HardcodedFormatterFinder<FormatterType>>;
+
+ typedef HardcodedFormatterFinders<TypeFormatImpl> HardcodedFormatFinder;
+ typedef HardcodedFormatterFinders<TypeSummaryImpl> HardcodedSummaryFinder;
+ typedef HardcodedFormatterFinders<SyntheticChildren> HardcodedSyntheticFinder;
+ typedef HardcodedFormatterFinders<TypeValidatorImpl> HardcodedValidatorFinder;
+};
+
class FormattersMatchCandidate
{
public:
-
FormattersMatchCandidate (ConstString name,
uint32_t reason,
bool strip_ptr,
@@ -41,10 +61,9 @@ public:
m_stripped_typedef(strip_tydef)
{
}
-
- ~FormattersMatchCandidate ()
- {}
-
+
+ ~FormattersMatchCandidate() = default;
+
ConstString
GetTypeName () const
{
@@ -99,6 +118,36 @@ private:
};
typedef std::vector<FormattersMatchCandidate> FormattersMatchVector;
+typedef std::vector<lldb::LanguageType> CandidateLanguagesVector;
+
+class FormattersMatchData
+{
+public:
+ FormattersMatchData (ValueObject&,
+ lldb::DynamicValueType);
+
+ FormattersMatchVector
+ GetMatchesVector ();
+
+ ConstString
+ GetTypeForCache ();
+
+ CandidateLanguagesVector
+ GetCandidateLanguages ();
+
+ ValueObject&
+ GetValueObject ();
+
+ lldb::DynamicValueType
+ GetDynamicValueType ();
+
+private:
+ ValueObject& m_valobj;
+ lldb::DynamicValueType m_dynamic_value_type;
+ std::pair<FormattersMatchVector,bool> m_formatters_match_vector;
+ ConstString m_type_for_cache;
+ CandidateLanguagesVector m_candidate_languages;
+};
class TypeNameSpecifierImpl
{
@@ -130,7 +179,7 @@ public:
}
}
- TypeNameSpecifierImpl (ClangASTType type) :
+ TypeNameSpecifierImpl (CompilerType type) :
m_is_regex(false),
m_type()
{
@@ -146,7 +195,7 @@ public:
{
if (m_type.m_type_name.size())
return m_type.m_type_name.c_str();
- return NULL;
+ return nullptr;
}
lldb::TypeSP
@@ -157,12 +206,12 @@ public:
return lldb::TypeSP();
}
- ClangASTType
- GetClangASTType ()
+ CompilerType
+ GetCompilerType ()
{
if (m_type.m_type_pair.IsValid())
- return m_type.m_type_pair.GetClangASTType();
- return ClangASTType();
+ return m_type.m_type_pair.GetCompilerType();
+ return CompilerType();
}
bool
@@ -174,19 +223,18 @@ public:
private:
bool m_is_regex;
// this works better than TypeAndOrName because the latter only wraps a TypeSP
- // whereas TypePair can also be backed by a ClangASTType
+ // whereas TypePair can also be backed by a CompilerType
struct TypeOrName
{
std::string m_type_name;
TypePair m_type_pair;
};
TypeOrName m_type;
-
-
+
private:
DISALLOW_COPY_AND_ASSIGN(TypeNameSpecifierImpl);
};
} // namespace lldb_private
-#endif // lldb_FormatClasses_h_
+#endif // lldb_FormatClasses_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatManager.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatManager.h
index a1f4b59..24ba5a7 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatManager.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormatManager.h
@@ -1,4 +1,4 @@
-//===-- FormatManager.h -------------------------------------------*- C++ -*-===//
+//===-- FormatManager.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,6 +12,10 @@
// C Includes
// C++ Includes
+#include <atomic>
+#include <initializer_list>
+#include <map>
+#include <vector>
// Other libraries and framework includes
// Project includes
@@ -21,12 +25,10 @@
#include "lldb/DataFormatters/FormatCache.h"
#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/DataFormatters/FormattersContainer.h"
+#include "lldb/DataFormatters/LanguageCategory.h"
#include "lldb/DataFormatters/TypeCategory.h"
#include "lldb/DataFormatters/TypeCategoryMap.h"
-#include <atomic>
-#include <functional>
-
namespace lldb_private {
// this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization
@@ -39,19 +41,12 @@ class FormatManager : public IFormatChangeListener
typedef FormatMap<ConstString, TypeSummaryImpl> NamedSummariesMap;
typedef TypeCategoryMap::MapType::iterator CategoryMapIterator;
public:
+ typedef std::map<lldb::LanguageType, LanguageCategory::UniquePointer> LanguageCategories;
- template <typename FormatterType>
- using HardcodedFormatterFinder = std::function<typename FormatterType::SharedPointer (lldb_private::ValueObject&,
- lldb::DynamicValueType,
- FormatManager&)>;
-
- template <typename FormatterType>
- using HardcodedFormatterFinders = std::vector<HardcodedFormatterFinder<FormatterType>>;
-
- typedef TypeCategoryMap::CallbackType CategoryCallback;
-
- FormatManager ();
+ FormatManager();
+ ~FormatManager() override = default;
+
NamedSummariesMap&
GetNamedSummaryContainer ()
{
@@ -62,8 +57,34 @@ public:
EnableCategory (const ConstString& category_name,
TypeCategoryMap::Position pos = TypeCategoryMap::Default)
{
- m_categories_map.Enable(category_name,
- pos);
+ EnableCategory(category_name,
+ pos,
+ std::initializer_list<lldb::LanguageType>());
+ }
+
+ void
+ EnableCategory (const ConstString& category_name,
+ TypeCategoryMap::Position pos,
+ lldb::LanguageType lang)
+ {
+ std::initializer_list<lldb::LanguageType> langs = {lang};
+ EnableCategory(category_name,
+ pos,
+ langs);
+ }
+
+ void
+ EnableCategory (const ConstString& category_name,
+ TypeCategoryMap::Position pos = TypeCategoryMap::Default,
+ std::initializer_list<lldb::LanguageType> langs = {})
+ {
+ TypeCategoryMap::ValueSP category_sp;
+ if (m_categories_map.Get(category_name, category_sp) && category_sp)
+ {
+ m_categories_map.Enable(category_sp, pos);
+ for (const lldb::LanguageType lang : langs)
+ category_sp->AddLanguage(lang);
+ }
}
void
@@ -87,16 +108,10 @@ public:
}
void
- EnableAllCategories ()
- {
- m_categories_map.EnableAllCategories ();
- }
+ EnableAllCategories ();
void
- DisableAllCategories ()
- {
- m_categories_map.DisableAllCategories ();
- }
+ DisableAllCategories ();
bool
DeleteCategory (const ConstString& category_name)
@@ -123,14 +138,11 @@ public:
}
void
- LoopThroughCategories (CategoryCallback callback, void* param)
- {
- m_categories_map.LoopThrough(callback, param);
- }
+ ForEachCategory (TypeCategoryMap::ForEachCallback callback);
lldb::TypeCategoryImplSP
- GetCategory (const char* category_name = NULL,
- bool can_create = true)
+ GetCategory(const char* category_name = nullptr,
+ bool can_create = true)
{
if (!category_name)
return GetCategory(m_default_category_name);
@@ -182,11 +194,11 @@ public:
lldb::DynamicValueType use_dynamic);
bool
- AnyMatches (ConstString type_name,
- TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES,
- bool only_enabled = true,
- const char** matching_category = NULL,
- TypeCategoryImpl::FormatCategoryItems* matching_type = NULL)
+ AnyMatches(ConstString type_name,
+ TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES,
+ bool only_enabled = true,
+ const char** matching_category = nullptr,
+ TypeCategoryImpl::FormatCategoryItems* matching_type = nullptr)
{
return m_categories_map.AnyMatches(type_name,
items,
@@ -226,29 +238,21 @@ public:
ShouldPrintAsOneLiner (ValueObject& valobj);
void
- Changed ()
- {
- ++m_last_revision;
- m_format_cache.Clear ();
- }
+ Changed () override;
uint32_t
- GetCurrentRevision ()
+ GetCurrentRevision () override
{
return m_last_revision;
}
-
- ~FormatManager ()
- {
- }
-
+
static FormattersMatchVector
GetPossibleMatches (ValueObject& valobj,
lldb::DynamicValueType use_dynamic)
{
FormattersMatchVector matches;
GetPossibleMatches (valobj,
- valobj.GetClangType(),
+ valobj.GetCompilerType(),
lldb_private::eFormatterChoiceCriterionDirectChoice,
use_dynamic,
matches,
@@ -258,12 +262,23 @@ public:
true);
return matches;
}
+
+ static ConstString
+ GetTypeForCache (ValueObject&, lldb::DynamicValueType);
+
+ LanguageCategory*
+ GetCategoryForLanguage (lldb::LanguageType lang_type);
+
+ static std::vector<lldb::LanguageType>
+ GetCandidateLanguages (lldb::LanguageType lang_type);
private:
+ static std::vector<lldb::LanguageType>
+ GetCandidateLanguages (ValueObject& valobj);
static void
GetPossibleMatches (ValueObject& valobj,
- ClangASTType clang_type,
+ CompilerType compiler_type,
uint32_t reason,
lldb::DynamicValueType use_dynamic,
FormattersMatchVector& entries,
@@ -271,40 +286,29 @@ private:
bool did_strip_ref,
bool did_strip_typedef,
bool root_level = false);
-
+
+ std::atomic<uint32_t> m_last_revision;
FormatCache m_format_cache;
+ Mutex m_language_categories_mutex;
+ LanguageCategories m_language_categories_map;
NamedSummariesMap m_named_summaries_map;
- std::atomic<uint32_t> m_last_revision;
TypeCategoryMap m_categories_map;
ConstString m_default_category_name;
ConstString m_system_category_name;
- ConstString m_gnu_cpp_category_name;
- ConstString m_libcxx_category_name;
- ConstString m_objc_category_name;
- ConstString m_corefoundation_category_name;
- ConstString m_coregraphics_category_name;
- ConstString m_coreservices_category_name;
ConstString m_vectortypes_category_name;
- ConstString m_appkit_category_name;
- ConstString m_coremedia_category_name;
-
- HardcodedFormatterFinders<TypeFormatImpl> m_hardcoded_formats;
- HardcodedFormatterFinders<TypeSummaryImpl> m_hardcoded_summaries;
- HardcodedFormatterFinders<SyntheticChildren> m_hardcoded_synthetics;
- HardcodedFormatterFinders<TypeValidatorImpl> m_hardcoded_validators;
lldb::TypeFormatImplSP
- GetHardcodedFormat (ValueObject&,lldb::DynamicValueType);
+ GetHardcodedFormat (FormattersMatchData&);
lldb::TypeSummaryImplSP
- GetHardcodedSummaryFormat (ValueObject&,lldb::DynamicValueType);
+ GetHardcodedSummaryFormat (FormattersMatchData&);
lldb::SyntheticChildrenSP
- GetHardcodedSyntheticChildren (ValueObject&,lldb::DynamicValueType);
+ GetHardcodedSyntheticChildren (FormattersMatchData&);
lldb::TypeValidatorImplSP
- GetHardcodedValidator (ValueObject&,lldb::DynamicValueType);
+ GetHardcodedValidator (FormattersMatchData&);
TypeCategoryMap&
GetCategories ()
@@ -312,29 +316,20 @@ private:
return m_categories_map;
}
- // WARNING: these are temporary functions that setup formatters
- // while a few of these actually should be globally available and setup by LLDB itself
- // most would actually belong to the users' lldbinit file or to some other form of configurable
- // storage
- void
- LoadLibStdcppFormatters ();
-
- void
- LoadLibcxxFormatters ();
-
+ // These functions are meant to initialize formatters that are very low-level/global in nature
+ // and do not naturally belong in any language. The intent is that most formatters go in
+ // language-specific categories. Eventually, the runtimes should also be allowed to vend their
+ // own formatters, and then one could put formatters that depend on specific library load events
+ // in the language runtimes, on an as-needed basis
void
LoadSystemFormatters ();
void
- LoadObjCFormatters ();
-
- void
- LoadCoreMediaFormatters ();
+ LoadVectorFormatters ();
- void
- LoadHardcodedFormatters ();
+ friend class FormattersMatchData;
};
} // namespace lldb_private
-#endif // lldb_FormatManager_h_
+#endif // lldb_FormatManager_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h
index daf2f24..dcd0821 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h
@@ -1,4 +1,4 @@
-//===-- FormattersContainer.h ----------------------------------------*- C++ -*-===//
+//===-- FormattersContainer.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,53 +12,38 @@
// C Includes
// C++ Includes
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
// Other libraries and framework includes
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Type.h"
-#include "clang/AST/DeclObjC.h"
-
// Project includes
#include "lldb/lldb-public.h"
-#include "lldb/Core/Log.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/ValueObject.h"
-
#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/DataFormatters/TypeFormat.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
#include "lldb/DataFormatters/TypeValidator.h"
-
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangASTType.h"
-
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/TargetList.h"
-
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Utility/StringLexer.h"
namespace lldb_private {
-// this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization
-// class DataVisualization is the high-level front-end of this feature
-// clients should refer to that class as the entry-point into the data formatters
-// unless they have a good reason to bypass it and prefer to use this file's objects directly
class IFormatChangeListener
{
public:
+ virtual
+ ~IFormatChangeListener() = default;
+
virtual void
Changed () = 0;
-
- virtual
- ~IFormatChangeListener () {}
-
+
virtual uint32_t
GetCurrentRevision () = 0;
-
};
// if the user tries to add formatters for, say, "struct Foo"
@@ -92,11 +77,10 @@ template<typename KeyType, typename ValueType>
class FormatMap
{
public:
-
typedef typename ValueType::SharedPointer ValueSP;
typedef std::map<KeyType, ValueSP> MapType;
typedef typename MapType::iterator MapIterator;
- typedef bool(*CallbackType)(void*, KeyType, const ValueSP&);
+ typedef std::function<bool(KeyType, const ValueSP&)> ForEachCallback;
FormatMap(IFormatChangeListener* lst) :
m_map(),
@@ -155,7 +139,7 @@ public:
}
void
- LoopThrough (CallbackType callback, void* param)
+ ForEach (ForEachCallback callback)
{
if (callback)
{
@@ -164,7 +148,7 @@ public:
for (pos = m_map.begin(); pos != end; pos++)
{
KeyType type = pos->first;
- if (!callback(param, type, pos->second))
+ if (!callback(type, pos->second))
break;
}
}
@@ -227,7 +211,6 @@ protected:
friend class FormattersContainer<KeyType, ValueType>;
friend class FormatManager;
-
};
template<typename KeyType, typename ValueType>
@@ -241,7 +224,7 @@ public:
typedef typename MapType::iterator MapIterator;
typedef typename MapType::key_type MapKeyType;
typedef typename MapType::mapped_type MapValueType;
- typedef typename BackEndType::CallbackType CallbackType;
+ typedef typename BackEndType::ForEachCallback ForEachCallback;
typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType> > SharedPointer;
friend class TypeCategoryImpl;
@@ -256,23 +239,23 @@ public:
void
Add (const MapKeyType &type, const MapValueType& entry)
{
- Add_Impl(type, entry, (KeyType*)NULL);
+ Add_Impl(type, entry, static_cast<KeyType*>(nullptr));
}
bool
Delete (ConstString type)
{
- return Delete_Impl(type, (KeyType*)NULL);
+ return Delete_Impl(type, static_cast<KeyType*>(nullptr));
}
bool
Get(ValueObject& valobj,
MapValueType& entry,
lldb::DynamicValueType use_dynamic,
- uint32_t* why = NULL)
+ uint32_t* why = nullptr)
{
uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
- ClangASTType ast_type(valobj.GetClangType());
+ CompilerType ast_type(valobj.GetCompilerType());
bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
if (ret)
entry = MapValueType(entry);
@@ -286,13 +269,13 @@ public:
bool
Get (ConstString type, MapValueType& entry)
{
- return Get_Impl(type, entry, (KeyType*)NULL);
+ return Get_Impl(type, entry, static_cast<KeyType*>(nullptr));
}
bool
GetExact (ConstString type, MapValueType& entry)
{
- return GetExact_Impl(type, entry, (KeyType*)NULL);
+ return GetExact_Impl(type, entry, static_cast<KeyType*>(nullptr));
}
MapValueType
@@ -304,7 +287,7 @@ public:
lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierAtIndex (size_t index)
{
- return GetTypeNameSpecifierAtIndex_Impl(index, (KeyType*)NULL);
+ return GetTypeNameSpecifierAtIndex_Impl(index, static_cast<KeyType*>(nullptr));
}
void
@@ -314,9 +297,9 @@ public:
}
void
- LoopThrough (CallbackType callback, void* param)
+ ForEach (ForEachCallback callback)
{
- m_format_map.LoopThrough(callback,param);
+ m_format_map.ForEach(callback);
}
uint32_t
@@ -377,7 +360,7 @@ protected:
bool
GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
{
- return Get_Impl(type,entry, (KeyType*)0);
+ return Get_Impl(type, entry, static_cast<KeyType*>(nullptr));
}
lldb::TypeNameSpecifierImplSP
@@ -395,7 +378,7 @@ protected:
GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy)
{
lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
- if (regex.get() == NULL)
+ if (regex.get() == nullptr)
return lldb::TypeNameSpecifierImplSP();
return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(),
true));
@@ -447,7 +430,6 @@ protected:
{
for (const FormattersMatchCandidate& candidate : candidates)
{
- // FIXME: could we do the IsMatch() check first?
if (Get(candidate.GetTypeName(),entry))
{
if (candidate.IsMatch(entry) == false)
@@ -469,4 +451,4 @@ protected:
} // namespace lldb_private
-#endif // lldb_FormattersContainer_h_
+#endif // lldb_FormattersContainer_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersHelpers.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersHelpers.h
new file mode 100644
index 0000000..4627a61
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersHelpers.h
@@ -0,0 +1,279 @@
+//===-- FormattersHelpers.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_FormattersHelpers_h_
+#define lldb_FormattersHelpers_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-enumerations.h"
+
+#include "lldb/DataFormatters/TypeCategory.h"
+#include "lldb/DataFormatters/TypeFormat.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+namespace lldb_private {
+ namespace formatters {
+ void
+ AddFormat (TypeCategoryImpl::SharedPointer category_sp,
+ lldb::Format format,
+ ConstString type_name,
+ TypeFormatImpl::Flags flags,
+ bool regex = false);
+
+ void
+ AddSummary(TypeCategoryImpl::SharedPointer category_sp,
+ lldb::TypeSummaryImplSP summary_sp,
+ ConstString type_name,
+ bool regex = false);
+
+ void
+ AddStringSummary(TypeCategoryImpl::SharedPointer category_sp,
+ const char* string,
+ ConstString type_name,
+ TypeSummaryImpl::Flags flags,
+ bool regex = false);
+
+ void
+ AddOneLineSummary (TypeCategoryImpl::SharedPointer category_sp,
+ ConstString type_name,
+ TypeSummaryImpl::Flags flags,
+ bool regex = false);
+
+#ifndef LLDB_DISABLE_PYTHON
+ void
+ AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp,
+ CXXFunctionSummaryFormat::Callback funct,
+ const char* description,
+ ConstString type_name,
+ TypeSummaryImpl::Flags flags,
+ bool regex = false);
+
+ void
+ AddCXXSynthetic (TypeCategoryImpl::SharedPointer category_sp,
+ CXXSyntheticChildren::CreateFrontEndCallback generator,
+ const char* description,
+ ConstString type_name,
+ ScriptedSyntheticChildren::Flags flags,
+ bool regex = false);
+
+ void
+ AddFilter (TypeCategoryImpl::SharedPointer category_sp,
+ std::vector<std::string> children,
+ const char* description,
+ ConstString type_name,
+ ScriptedSyntheticChildren::Flags flags,
+ bool regex = false);
+#endif
+
+ StackFrame*
+ GetViableFrame (ExecutionContext exe_ctx);
+
+ bool
+ ExtractValueFromObjCExpression (ValueObject &valobj,
+ const char* target_type,
+ const char* selector,
+ uint64_t &value);
+
+ bool
+ ExtractSummaryFromObjCExpression (ValueObject &valobj,
+ const char* target_type,
+ const char* selector,
+ Stream &stream,
+ lldb::LanguageType lang_type);
+
+ lldb::ValueObjectSP
+ CallSelectorOnObject (ValueObject &valobj,
+ const char* return_type,
+ const char* selector,
+ uint64_t index);
+
+ lldb::ValueObjectSP
+ CallSelectorOnObject (ValueObject &valobj,
+ const char* return_type,
+ const char* selector,
+ const char* key);
+
+ size_t
+ ExtractIndexFromString (const char* item_name);
+
+ lldb::addr_t
+ GetArrayAddressOrPointerValue (ValueObject& valobj);
+
+ time_t
+ GetOSXEpoch ();
+
+ struct InferiorSizedWord {
+
+ InferiorSizedWord(const InferiorSizedWord& word) : ptr_size(word.ptr_size)
+ {
+ if (ptr_size == 4)
+ thirty_two = word.thirty_two;
+ else
+ sixty_four = word.sixty_four;
+ }
+
+ InferiorSizedWord
+ operator = (const InferiorSizedWord& word)
+ {
+ ptr_size = word.ptr_size;
+ if (ptr_size == 4)
+ thirty_two = word.thirty_two;
+ else
+ sixty_four = word.sixty_four;
+ return *this;
+ }
+
+ InferiorSizedWord(uint64_t val, Process& process) : ptr_size(process.GetAddressByteSize())
+ {
+ if (ptr_size == 4)
+ thirty_two = (uint32_t)val;
+ else if (ptr_size == 8)
+ sixty_four = val;
+ else
+ assert (false && "new pointer size is unknown");
+ }
+
+ bool
+ IsNegative () const
+ {
+ if (ptr_size == 4)
+ return ((int32_t)thirty_two) < 0;
+ else
+ return ((int64_t)sixty_four) < 0;
+ }
+
+ bool
+ IsZero () const
+ {
+ if (ptr_size == 4)
+ return thirty_two == 0;
+ else
+ return sixty_four == 0;
+ }
+
+ static InferiorSizedWord
+ GetMaximum (Process& process)
+ {
+ if (process.GetAddressByteSize() == 4)
+ return InferiorSizedWord(UINT32_MAX,4);
+ else
+ return InferiorSizedWord(UINT64_MAX,8);
+ }
+
+ InferiorSizedWord
+ operator >> (int rhs) const
+ {
+ if (ptr_size == 4)
+ return InferiorSizedWord(thirty_two >> rhs,4);
+ return InferiorSizedWord(sixty_four>>rhs,8);
+ }
+
+ InferiorSizedWord
+ operator << (int rhs) const
+ {
+ if (ptr_size == 4)
+ return InferiorSizedWord(thirty_two << rhs,4);
+ return InferiorSizedWord(sixty_four << rhs,8);
+ }
+
+ InferiorSizedWord
+ operator & (const InferiorSizedWord& word) const
+ {
+ if (ptr_size != word.ptr_size)
+ return InferiorSizedWord(0,ptr_size);
+ if (ptr_size == 4)
+ return InferiorSizedWord(thirty_two & word.thirty_two,4);
+ return InferiorSizedWord(sixty_four & word.sixty_four,8);
+ }
+
+ InferiorSizedWord
+ operator & (int x) const
+ {
+ if (ptr_size == 4)
+ return InferiorSizedWord(thirty_two & x,4);
+ return InferiorSizedWord(sixty_four & x,8);
+ }
+
+ size_t
+ GetBitSize () const
+ {
+ return ptr_size << 3;
+ }
+
+ size_t
+ GetByteSize () const
+ {
+ return ptr_size;
+ }
+
+ uint64_t
+ GetValue () const
+ {
+ if (ptr_size == 4)
+ return (uint64_t)thirty_two;
+ return sixty_four;
+ }
+
+ InferiorSizedWord
+ SignExtend () const
+ {
+ if (ptr_size == 4)
+ return InferiorSizedWord ((int32_t)thirty_two,4);
+ return InferiorSizedWord((int64_t)sixty_four,8);
+ }
+
+ uint8_t*
+ CopyToBuffer (uint8_t* buffer) const
+ {
+ if (ptr_size == 4)
+ {
+ memcpy(buffer, &thirty_two, 4);
+ return buffer + 4;
+ }
+ else
+ {
+ memcpy(buffer, &sixty_four, 8);
+ return buffer + 8;
+ }
+ }
+
+ DataExtractor
+ GetAsData (lldb::ByteOrder byte_order = lldb::eByteOrderInvalid) const
+ {
+ if (ptr_size == 4)
+ return DataExtractor(&thirty_two, 4, byte_order, 4);
+ else
+ return DataExtractor(&sixty_four, 8, byte_order, 8);
+ }
+
+ private:
+
+ InferiorSizedWord(uint64_t val, size_t psz) : ptr_size(psz)
+ {
+ if (ptr_size == 4)
+ thirty_two = (uint32_t)val;
+ else
+ sixty_four = val;
+ }
+
+ size_t ptr_size;
+ union {
+ uint32_t thirty_two;
+ uint64_t sixty_four;
+ };
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // lldb_FormattersHelpers_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/LanguageCategory.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/LanguageCategory.h
new file mode 100644
index 0000000..a704009
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/LanguageCategory.h
@@ -0,0 +1,99 @@
+//===-- LanguageCategory.h----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_LanguageCategory_h_
+#define lldb_LanguageCategory_h_
+
+// C Includes
+// C++ Includes
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/DataFormatters/FormatCache.h"
+#include "lldb/DataFormatters/FormatClasses.h"
+
+#include <memory>
+
+namespace lldb_private {
+
+class LanguageCategory
+{
+public:
+ typedef std::unique_ptr<LanguageCategory> UniquePointer;
+
+ LanguageCategory (lldb::LanguageType lang_type);
+
+ bool
+ Get (FormattersMatchData& match_data,
+ lldb::TypeFormatImplSP& format_sp);
+
+ bool
+ Get (FormattersMatchData& match_data,
+ lldb::TypeSummaryImplSP& format_sp);
+
+ bool
+ Get (FormattersMatchData& match_data,
+ lldb::SyntheticChildrenSP& format_sp);
+
+ bool
+ Get (FormattersMatchData& match_data,
+ lldb::TypeValidatorImplSP& format_sp);
+
+ bool
+ GetHardcoded (FormatManager& fmt_mgr,
+ FormattersMatchData& match_data,
+ lldb::TypeFormatImplSP& format_sp);
+
+ bool
+ GetHardcoded (FormatManager& fmt_mgr,
+ FormattersMatchData& match_data,
+ lldb::TypeSummaryImplSP& format_sp);
+
+ bool
+ GetHardcoded (FormatManager& fmt_mgr,
+ FormattersMatchData& match_data,
+ lldb::SyntheticChildrenSP& format_sp);
+
+ bool
+ GetHardcoded (FormatManager& fmt_mgr,
+ FormattersMatchData& match_data,
+ lldb::TypeValidatorImplSP& format_sp);
+
+ lldb::TypeCategoryImplSP
+ GetCategory () const;
+
+ FormatCache&
+ GetFormatCache ();
+
+ void
+ Enable ();
+
+ void
+ Disable ();
+
+ bool
+ IsEnabled ();
+
+private:
+ lldb::TypeCategoryImplSP m_category_sp;
+
+ HardcodedFormatters::HardcodedFormatFinder m_hardcoded_formats;
+ HardcodedFormatters::HardcodedSummaryFinder m_hardcoded_summaries;
+ HardcodedFormatters::HardcodedSyntheticFinder m_hardcoded_synthetics;
+ HardcodedFormatters::HardcodedValidatorFinder m_hardcoded_validators;
+
+ lldb_private::FormatCache m_format_cache;
+
+ bool m_enabled;
+};
+
+} // namespace lldb_private
+
+#endif // lldb_LanguageCategory_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/StringPrinter.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/StringPrinter.h
index 48e27ac..a849c4e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/StringPrinter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/StringPrinter.h
@@ -10,6 +10,13 @@
#ifndef liblldb_StringPrinter_h_
#define liblldb_StringPrinter_h_
+// C Includes
+// C++ Includes
+#include <functional>
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-forward.h"
#include "lldb/Core/DataExtractor.h"
@@ -17,273 +24,505 @@
namespace lldb_private {
namespace formatters
{
-
- enum class StringElementType {
- ASCII,
- UTF8,
- UTF16,
- UTF32
- };
-
- class ReadStringAndDumpToStreamOptions
+ class StringPrinter
{
public:
-
- ReadStringAndDumpToStreamOptions () :
- m_location(0),
- m_process_sp(),
- m_stream(NULL),
- m_prefix_token(0),
- m_quote('"'),
- m_source_size(0),
- m_needs_zero_termination(true),
- m_escape_non_printables(true),
- m_ignore_max_length(false)
- {
- }
-
- ReadStringAndDumpToStreamOptions (ValueObject& valobj);
-
- ReadStringAndDumpToStreamOptions&
- SetLocation (uint64_t l)
- {
- m_location = l;
- return *this;
- }
-
- uint64_t
- GetLocation () const
- {
- return m_location;
- }
-
- ReadStringAndDumpToStreamOptions&
- SetProcessSP (lldb::ProcessSP p)
- {
- m_process_sp = p;
- return *this;
- }
-
- lldb::ProcessSP
- GetProcessSP () const
- {
- return m_process_sp;
- }
-
- ReadStringAndDumpToStreamOptions&
- SetStream (Stream* s)
- {
- m_stream = s;
- return *this;
- }
-
- Stream*
- GetStream () const
- {
- return m_stream;
- }
-
- ReadStringAndDumpToStreamOptions&
- SetPrefixToken (char p)
- {
- m_prefix_token = p;
- return *this;
- }
-
- char
- GetPrefixToken () const
- {
- return m_prefix_token;
- }
-
- ReadStringAndDumpToStreamOptions&
- SetQuote (char q)
- {
- m_quote = q;
- return *this;
- }
-
- char
- GetQuote () const
- {
- return m_quote;
- }
-
- ReadStringAndDumpToStreamOptions&
- SetSourceSize (uint32_t s)
- {
- m_source_size = s;
- return *this;
- }
-
- uint32_t
- GetSourceSize () const
- {
- return m_source_size;
- }
-
- ReadStringAndDumpToStreamOptions&
- SetNeedsZeroTermination (bool z)
- {
- m_needs_zero_termination = z;
- return *this;
- }
-
- bool
- GetNeedsZeroTermination () const
- {
- return m_needs_zero_termination;
- }
-
- ReadStringAndDumpToStreamOptions&
- SetEscapeNonPrintables (bool e)
- {
- m_escape_non_printables = e;
- return *this;
- }
-
- bool
- GetEscapeNonPrintables () const
- {
- return m_escape_non_printables;
- }
-
- ReadStringAndDumpToStreamOptions&
- SetIgnoreMaxLength (bool e)
- {
- m_ignore_max_length = e;
- return *this;
- }
-
- bool
- GetIgnoreMaxLength () const
- {
- return m_ignore_max_length;
- }
-
- private:
- uint64_t m_location;
- lldb::ProcessSP m_process_sp;
- Stream* m_stream;
- char m_prefix_token;
- char m_quote;
- uint32_t m_source_size;
- bool m_needs_zero_termination;
- bool m_escape_non_printables;
- bool m_ignore_max_length;
- };
-
- class ReadBufferAndDumpToStreamOptions
- {
- public:
-
- ReadBufferAndDumpToStreamOptions () :
- m_data(),
- m_stream(NULL),
- m_prefix_token(0),
- m_quote('"'),
- m_source_size(0),
- m_escape_non_printables(true)
- {
- }
-
- ReadBufferAndDumpToStreamOptions (ValueObject& valobj);
-
- ReadBufferAndDumpToStreamOptions&
- SetData (DataExtractor d)
- {
- m_data = d;
- return *this;
- }
-
- lldb_private::DataExtractor
- GetData () const
- {
- return m_data;
- }
-
- ReadBufferAndDumpToStreamOptions&
- SetStream (Stream* s)
- {
- m_stream = s;
- return *this;
- }
-
- Stream*
- GetStream () const
- {
- return m_stream;
- }
-
- ReadBufferAndDumpToStreamOptions&
- SetPrefixToken (char p)
- {
- m_prefix_token = p;
- return *this;
- }
-
- char
- GetPrefixToken () const
- {
- return m_prefix_token;
- }
-
- ReadBufferAndDumpToStreamOptions&
- SetQuote (char q)
- {
- m_quote = q;
- return *this;
- }
-
- char
- GetQuote () const
- {
- return m_quote;
- }
-
- ReadBufferAndDumpToStreamOptions&
- SetSourceSize (uint32_t s)
- {
- m_source_size = s;
- return *this;
- }
-
- uint32_t
- GetSourceSize () const
- {
- return m_source_size;
- }
-
- ReadBufferAndDumpToStreamOptions&
- SetEscapeNonPrintables (bool e)
- {
- m_escape_non_printables = e;
- return *this;
- }
-
- bool
- GetEscapeNonPrintables () const
- {
- return m_escape_non_printables;
- }
-
- private:
- DataExtractor m_data;
- Stream* m_stream;
- char m_prefix_token;
- char m_quote;
- uint32_t m_source_size;
- bool m_escape_non_printables;
+ enum class StringElementType
+ {
+ ASCII,
+ UTF8,
+ UTF16,
+ UTF32
+ };
+
+ enum class GetPrintableElementType
+ {
+ ASCII,
+ UTF8
+ };
+
+ class ReadStringAndDumpToStreamOptions
+ {
+ public:
+ ReadStringAndDumpToStreamOptions () :
+ m_location(0),
+ m_process_sp(),
+ m_stream(nullptr),
+ m_prefix_token(),
+ m_suffix_token(),
+ m_quote('"'),
+ m_source_size(0),
+ m_needs_zero_termination(true),
+ m_escape_non_printables(true),
+ m_ignore_max_length(false),
+ m_zero_is_terminator(true),
+ m_language_type(lldb::eLanguageTypeUnknown)
+ {
+ }
+
+ ReadStringAndDumpToStreamOptions (ValueObject& valobj);
+
+ ReadStringAndDumpToStreamOptions&
+ SetLocation (uint64_t l)
+ {
+ m_location = l;
+ return *this;
+ }
+
+ uint64_t
+ GetLocation () const
+ {
+ return m_location;
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetProcessSP (lldb::ProcessSP p)
+ {
+ m_process_sp = p;
+ return *this;
+ }
+
+ lldb::ProcessSP
+ GetProcessSP () const
+ {
+ return m_process_sp;
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetStream (Stream* s)
+ {
+ m_stream = s;
+ return *this;
+ }
+
+ Stream*
+ GetStream () const
+ {
+ return m_stream;
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetPrefixToken (const std::string& p)
+ {
+ m_prefix_token = p;
+ return *this;
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetPrefixToken (std::nullptr_t)
+ {
+ m_prefix_token.clear();
+ return *this;
+ }
+
+ const char*
+ GetPrefixToken () const
+ {
+ return m_prefix_token.c_str();
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetSuffixToken (const std::string& p)
+ {
+ m_suffix_token = p;
+ return *this;
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetSuffixToken (std::nullptr_t)
+ {
+ m_suffix_token.clear();
+ return *this;
+ }
+
+ const char*
+ GetSuffixToken () const
+ {
+ return m_suffix_token.c_str();
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetQuote (char q)
+ {
+ m_quote = q;
+ return *this;
+ }
+
+ char
+ GetQuote () const
+ {
+ return m_quote;
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetSourceSize (uint32_t s)
+ {
+ m_source_size = s;
+ return *this;
+ }
+
+ uint32_t
+ GetSourceSize () const
+ {
+ return m_source_size;
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetNeedsZeroTermination (bool z)
+ {
+ m_needs_zero_termination = z;
+ return *this;
+ }
+
+ bool
+ GetNeedsZeroTermination () const
+ {
+ return m_needs_zero_termination;
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetBinaryZeroIsTerminator (bool e)
+ {
+ m_zero_is_terminator = e;
+ return *this;
+ }
+
+ bool
+ GetBinaryZeroIsTerminator () const
+ {
+ return m_zero_is_terminator;
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetEscapeNonPrintables (bool e)
+ {
+ m_escape_non_printables = e;
+ return *this;
+ }
+
+ bool
+ GetEscapeNonPrintables () const
+ {
+ return m_escape_non_printables;
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetIgnoreMaxLength (bool e)
+ {
+ m_ignore_max_length = e;
+ return *this;
+ }
+
+ bool
+ GetIgnoreMaxLength () const
+ {
+ return m_ignore_max_length;
+ }
+
+ ReadStringAndDumpToStreamOptions&
+ SetLanguage (lldb::LanguageType l)
+ {
+ m_language_type = l;
+ return *this;
+ }
+
+ lldb::LanguageType
+ GetLanguage () const
+
+ {
+ return m_language_type;
+ }
+
+ private:
+ uint64_t m_location;
+ lldb::ProcessSP m_process_sp;
+ Stream* m_stream;
+ std::string m_prefix_token;
+ std::string m_suffix_token;
+ char m_quote;
+ uint32_t m_source_size;
+ bool m_needs_zero_termination;
+ bool m_escape_non_printables;
+ bool m_ignore_max_length;
+ bool m_zero_is_terminator;
+ lldb::LanguageType m_language_type;
+ };
+
+ class ReadBufferAndDumpToStreamOptions
+ {
+ public:
+ ReadBufferAndDumpToStreamOptions () :
+ m_data(),
+ m_stream(nullptr),
+ m_prefix_token(),
+ m_suffix_token(),
+ m_quote('"'),
+ m_source_size(0),
+ m_escape_non_printables(true),
+ m_zero_is_terminator(true),
+ m_is_truncated(false),
+ m_language_type(lldb::eLanguageTypeUnknown)
+ {
+ }
+
+ ReadBufferAndDumpToStreamOptions (ValueObject& valobj);
+
+ ReadBufferAndDumpToStreamOptions (const ReadStringAndDumpToStreamOptions& options);
+
+ ReadBufferAndDumpToStreamOptions&
+ SetData (DataExtractor d)
+ {
+ m_data = d;
+ return *this;
+ }
+
+ lldb_private::DataExtractor
+ GetData () const
+ {
+ return m_data;
+ }
+
+ ReadBufferAndDumpToStreamOptions&
+ SetStream (Stream* s)
+ {
+ m_stream = s;
+ return *this;
+ }
+
+ Stream*
+ GetStream () const
+ {
+ return m_stream;
+ }
+
+ ReadBufferAndDumpToStreamOptions&
+ SetPrefixToken (const std::string& p)
+ {
+ m_prefix_token = p;
+ return *this;
+ }
+
+ ReadBufferAndDumpToStreamOptions&
+ SetPrefixToken (std::nullptr_t)
+ {
+ m_prefix_token.clear();
+ return *this;
+ }
+
+ const char*
+ GetPrefixToken () const
+ {
+ return m_prefix_token.c_str();
+ }
+
+ ReadBufferAndDumpToStreamOptions&
+ SetSuffixToken (const std::string& p)
+ {
+ m_suffix_token = p;
+ return *this;
+ }
+
+ ReadBufferAndDumpToStreamOptions&
+ SetSuffixToken (std::nullptr_t)
+ {
+ m_suffix_token.clear();
+ return *this;
+ }
+
+ const char*
+ GetSuffixToken () const
+ {
+ return m_suffix_token.c_str();
+ }
+
+ ReadBufferAndDumpToStreamOptions&
+ SetQuote (char q)
+ {
+ m_quote = q;
+ return *this;
+ }
+
+ char
+ GetQuote () const
+ {
+ return m_quote;
+ }
+
+ ReadBufferAndDumpToStreamOptions&
+ SetSourceSize (uint32_t s)
+ {
+ m_source_size = s;
+ return *this;
+ }
+
+ uint32_t
+ GetSourceSize () const
+ {
+ return m_source_size;
+ }
+
+ ReadBufferAndDumpToStreamOptions&
+ SetEscapeNonPrintables (bool e)
+ {
+ m_escape_non_printables = e;
+ return *this;
+ }
+
+ bool
+ GetEscapeNonPrintables () const
+ {
+ return m_escape_non_printables;
+ }
+
+ ReadBufferAndDumpToStreamOptions&
+ SetBinaryZeroIsTerminator (bool e)
+ {
+ m_zero_is_terminator = e;
+ return *this;
+ }
+
+ bool
+ GetBinaryZeroIsTerminator () const
+ {
+ return m_zero_is_terminator;
+ }
+
+ ReadBufferAndDumpToStreamOptions&
+ SetIsTruncated (bool t)
+ {
+ m_is_truncated = t;
+ return *this;
+ }
+
+ bool
+ GetIsTruncated () const
+ {
+ return m_is_truncated;
+ }
+
+ ReadBufferAndDumpToStreamOptions&
+ SetLanguage (lldb::LanguageType l)
+ {
+ m_language_type = l;
+ return *this;
+ }
+
+ lldb::LanguageType
+ GetLanguage () const
+
+ {
+ return m_language_type;
+ }
+
+ private:
+ DataExtractor m_data;
+ Stream* m_stream;
+ std::string m_prefix_token;
+ std::string m_suffix_token;
+ char m_quote;
+ uint32_t m_source_size;
+ bool m_escape_non_printables;
+ bool m_zero_is_terminator;
+ bool m_is_truncated;
+ lldb::LanguageType m_language_type;
+ };
+
+ // I can't use a std::unique_ptr for this because the Deleter is a template argument there
+ // and I want the same type to represent both pointers I want to free and pointers I don't need
+ // to free - which is what this class essentially is
+ // It's very specialized to the needs of this file, and not suggested for general use
+ template <typename T = uint8_t, typename U = char, typename S = size_t>
+ struct StringPrinterBufferPointer
+ {
+ public:
+ typedef std::function<void(const T*)> Deleter;
+
+ StringPrinterBufferPointer (std::nullptr_t ptr) :
+ m_data(nullptr),
+ m_size(0),
+ m_deleter()
+ {}
+
+ StringPrinterBufferPointer(const T* bytes, S size, Deleter deleter = nullptr) :
+ m_data(bytes),
+ m_size(size),
+ m_deleter(deleter)
+ {}
+
+ StringPrinterBufferPointer(const U* bytes, S size, Deleter deleter = nullptr) :
+ m_data(reinterpret_cast<const T*>(bytes)),
+ m_size(size),
+ m_deleter(deleter)
+ {}
+
+ StringPrinterBufferPointer(StringPrinterBufferPointer&& rhs) :
+ m_data(rhs.m_data),
+ m_size(rhs.m_size),
+ m_deleter(rhs.m_deleter)
+ {
+ rhs.m_data = nullptr;
+ }
+
+ StringPrinterBufferPointer(const StringPrinterBufferPointer& rhs) :
+ m_data(rhs.m_data),
+ m_size(rhs.m_size),
+ m_deleter(rhs.m_deleter)
+ {
+ rhs.m_data = nullptr; // this is why m_data has to be mutable
+ }
+
+ ~StringPrinterBufferPointer()
+ {
+ if (m_data && m_deleter)
+ m_deleter(m_data);
+ m_data = nullptr;
+ }
+
+ const T*
+ GetBytes () const
+ {
+ return m_data;
+ }
+
+ const S
+ GetSize () const
+ {
+ return m_size;
+ }
+
+ StringPrinterBufferPointer&
+ operator = (const StringPrinterBufferPointer& rhs)
+ {
+ if (m_data && m_deleter)
+ m_deleter(m_data);
+ m_data = rhs.m_data;
+ m_size = rhs.m_size;
+ m_deleter = rhs.m_deleter;
+ rhs.m_data = nullptr;
+ return *this;
+ }
+
+ private:
+ mutable const T* m_data;
+ size_t m_size;
+ Deleter m_deleter;
+ };
+
+ typedef std::function<StringPrinter::StringPrinterBufferPointer<uint8_t,char,size_t>(uint8_t*, uint8_t*, uint8_t*&)> EscapingHelper;
+ typedef std::function<EscapingHelper(GetPrintableElementType)> EscapingHelperGenerator;
+
+ static EscapingHelper
+ GetDefaultEscapingHelper (GetPrintableElementType elem_type);
+
+ template <StringElementType element_type>
+ static bool
+ ReadStringAndDumpToStream (const ReadStringAndDumpToStreamOptions& options);
+
+ template <StringElementType element_type>
+ static bool
+ ReadBufferAndDumpToStream (const ReadBufferAndDumpToStreamOptions& options);
};
- template <StringElementType element_type>
- bool
- ReadStringAndDumpToStream (ReadStringAndDumpToStreamOptions options);
-
- template <StringElementType element_type>
- bool
- ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOptions options);
-
} // namespace formatters
} // namespace lldb_private
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeCategory.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeCategory.h
index e32efa4..075d31d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeCategory.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeCategory.h
@@ -1,4 +1,4 @@
-//===-- TypeCategory.h -------------------------------------------*- C++ -*-===//
+//===-- TypeCategory.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,6 +12,10 @@
// C Includes
// C++ Includes
+#include <initializer_list>
+#include <memory>
+#include <string>
+#include <vector>
// Other libraries and framework includes
// Project includes
@@ -38,6 +42,9 @@ namespace lldb_private {
typedef typename ExactMatchContainer::SharedPointer ExactMatchContainerSP;
typedef typename RegexMatchContainer::SharedPointer RegexMatchContainerSP;
+ typedef typename ExactMatchContainer::ForEachCallback ExactMatchForEachCallback;
+ typedef typename RegexMatchContainer::ForEachCallback RegexMatchForEachCallback;
+
FormatterContainerPair (const char* exact_name,
const char* regex_name,
IFormatChangeListener* clist) :
@@ -60,6 +67,12 @@ namespace lldb_private {
return m_regex_sp;
}
+ uint32_t
+ GetCount ()
+ {
+ return GetExactMatch()->GetCount() + GetRegexMatch()->GetCount();
+ }
+
private:
ExactMatchContainerSP m_exact_sp;
RegexMatchContainerSP m_regex_sp;
@@ -74,11 +87,10 @@ namespace lldb_private {
typedef FormatterContainerPair<TypeValidatorImpl> ValidatorContainer;
#ifndef LLDB_DISABLE_PYTHON
- typedef FormatterContainerPair<ScriptedSyntheticChildren> SynthContainer;
-#endif // #ifndef LLDB_DISABLE_PYTHON
+ typedef FormatterContainerPair<SyntheticChildren> SynthContainer;
+#endif // LLDB_DISABLE_PYTHON
public:
-
typedef uint16_t FormatCategoryItems;
static const uint16_t ALL_ITEM_TYPES = UINT16_MAX;
@@ -93,13 +105,195 @@ namespace lldb_private {
#ifndef LLDB_DISABLE_PYTHON
typedef SynthContainer::ExactMatchContainerSP SynthContainerSP;
typedef SynthContainer::RegexMatchContainerSP RegexSynthContainerSP;
-#endif // #ifndef LLDB_DISABLE_PYTHON
+#endif // LLDB_DISABLE_PYTHON
typedef ValidatorContainer::ExactMatchContainerSP ValidatorContainerSP;
typedef ValidatorContainer::RegexMatchContainerSP RegexValidatorContainerSP;
+ template <typename T>
+ class ForEachCallbacks
+ {
+ public:
+ ForEachCallbacks () = default;
+ ~ForEachCallbacks () = default;
+
+ template<typename U = TypeFormatImpl>
+ typename std::enable_if<std::is_same<U,T>::value, ForEachCallbacks&>::type
+ SetExact (FormatContainer::ExactMatchForEachCallback callback)
+ {
+ m_format_exact = callback;
+ return *this;
+ }
+ template<typename U = TypeFormatImpl>
+ typename std::enable_if<std::is_same<U,T>::value, ForEachCallbacks&>::type
+ SetWithRegex (FormatContainer::RegexMatchForEachCallback callback)
+ {
+ m_format_regex = callback;
+ return *this;
+ }
+
+ template<typename U = TypeSummaryImpl>
+ typename std::enable_if<std::is_same<U,T>::value, ForEachCallbacks&>::type
+ SetExact (SummaryContainer::ExactMatchForEachCallback callback)
+ {
+ m_summary_exact = callback;
+ return *this;
+ }
+ template<typename U = TypeSummaryImpl>
+ typename std::enable_if<std::is_same<U,T>::value, ForEachCallbacks&>::type
+ SetWithRegex (SummaryContainer::RegexMatchForEachCallback callback)
+ {
+ m_summary_regex = callback;
+ return *this;
+ }
+
+ template<typename U = TypeFilterImpl>
+ typename std::enable_if<std::is_same<U,T>::value, ForEachCallbacks&>::type
+ SetExact (FilterContainer::ExactMatchForEachCallback callback)
+ {
+ m_filter_exact = callback;
+ return *this;
+ }
+ template<typename U = TypeFilterImpl>
+ typename std::enable_if<std::is_same<U,T>::value, ForEachCallbacks&>::type
+ SetWithRegex (FilterContainer::RegexMatchForEachCallback callback)
+ {
+ m_filter_regex = callback;
+ return *this;
+ }
+
+#ifndef LLDB_DISABLE_PYTHON
+ template<typename U = SyntheticChildren>
+ typename std::enable_if<std::is_same<U,T>::value, ForEachCallbacks&>::type
+ SetExact (SynthContainer::ExactMatchForEachCallback callback)
+ {
+ m_synth_exact = callback;
+ return *this;
+ }
+ template<typename U = SyntheticChildren>
+ typename std::enable_if<std::is_same<U,T>::value, ForEachCallbacks&>::type
+ SetWithRegex (SynthContainer::RegexMatchForEachCallback callback)
+ {
+ m_synth_regex = callback;
+ return *this;
+ }
+#endif // LLDB_DISABLE_PYTHON
+ template<typename U = TypeValidatorImpl>
+ typename std::enable_if<std::is_same<U,T>::value, ForEachCallbacks&>::type
+ SetExact (ValidatorContainer::ExactMatchForEachCallback callback)
+ {
+ m_validator_exact = callback;
+ return *this;
+ }
+ template<typename U = TypeValidatorImpl>
+ typename std::enable_if<std::is_same<U,T>::value, ForEachCallbacks&>::type
+ SetWithRegex (ValidatorContainer::RegexMatchForEachCallback callback)
+ {
+ m_validator_regex = callback;
+ return *this;
+ }
+
+ FormatContainer::ExactMatchForEachCallback
+ GetFormatExactCallback () const
+ {
+ return m_format_exact;
+ }
+ FormatContainer::RegexMatchForEachCallback
+ GetFormatRegexCallback () const
+ {
+ return m_format_regex;
+ }
+
+ SummaryContainer::ExactMatchForEachCallback
+ GetSummaryExactCallback () const
+ {
+ return m_summary_exact;
+ }
+ SummaryContainer::RegexMatchForEachCallback
+ GetSummaryRegexCallback () const
+ {
+ return m_summary_regex;
+ }
+
+ FilterContainer::ExactMatchForEachCallback
+ GetFilterExactCallback () const
+ {
+ return m_filter_exact;
+ }
+ FilterContainer::RegexMatchForEachCallback
+ GetFilterRegexCallback () const
+ {
+ return m_filter_regex;
+ }
+
+#ifndef LLDB_DISABLE_PYTHON
+ SynthContainer::ExactMatchForEachCallback
+ GetSynthExactCallback () const
+ {
+ return m_synth_exact;
+ }
+ SynthContainer::RegexMatchForEachCallback
+ GetSynthRegexCallback () const
+ {
+ return m_synth_regex;
+ }
+#endif // LLDB_DISABLE_PYTHON
+
+ ValidatorContainer::ExactMatchForEachCallback
+ GetValidatorExactCallback () const
+ {
+ return m_validator_exact;
+ }
+ ValidatorContainer::RegexMatchForEachCallback
+ GetValidatorRegexCallback () const
+ {
+ return m_validator_regex;
+ }
+
+ private:
+ FormatContainer::ExactMatchForEachCallback m_format_exact;
+ FormatContainer::RegexMatchForEachCallback m_format_regex;
+
+ SummaryContainer::ExactMatchForEachCallback m_summary_exact;
+ SummaryContainer::RegexMatchForEachCallback m_summary_regex;
+
+ FilterContainer::ExactMatchForEachCallback m_filter_exact;
+ FilterContainer::RegexMatchForEachCallback m_filter_regex;
+
+#ifndef LLDB_DISABLE_PYTHON
+ SynthContainer::ExactMatchForEachCallback m_synth_exact;
+ SynthContainer::RegexMatchForEachCallback m_synth_regex;
+#endif // LLDB_DISABLE_PYTHON
+
+ ValidatorContainer::ExactMatchForEachCallback m_validator_exact;
+ ValidatorContainer::RegexMatchForEachCallback m_validator_regex;
+ };
+
TypeCategoryImpl (IFormatChangeListener* clist,
- ConstString name);
+ ConstString name,
+ std::initializer_list<lldb::LanguageType> langs = {});
+
+ template <typename T>
+ void
+ ForEach (const ForEachCallbacks<T> &foreach)
+ {
+ GetTypeFormatsContainer()->ForEach(foreach.GetFormatExactCallback());
+ GetRegexTypeFormatsContainer()->ForEach(foreach.GetFormatRegexCallback());
+
+ GetTypeSummariesContainer()->ForEach(foreach.GetSummaryExactCallback());
+ GetRegexTypeSummariesContainer()->ForEach(foreach.GetSummaryRegexCallback());
+
+ GetTypeFiltersContainer()->ForEach(foreach.GetFilterExactCallback());
+ GetRegexTypeFiltersContainer()->ForEach(foreach.GetFilterRegexCallback());
+
+#ifndef LLDB_DISABLE_PYTHON
+ GetTypeSyntheticsContainer()->ForEach(foreach.GetSynthExactCallback());
+ GetRegexTypeSyntheticsContainer()->ForEach(foreach.GetSynthRegexCallback());
+#endif // LLDB_DISABLE_PYTHON
+
+ GetTypeValidatorsContainer()->ForEach(foreach.GetValidatorExactCallback());
+ GetRegexTypeValidatorsContainer()->ForEach(foreach.GetValidatorRegexCallback());
+ }
FormatContainerSP
GetTypeFormatsContainer ()
@@ -113,6 +307,12 @@ namespace lldb_private {
return m_format_cont.GetRegexMatch();
}
+ FormatContainer&
+ GetFormatContainer ()
+ {
+ return m_format_cont;
+ }
+
SummaryContainerSP
GetTypeSummariesContainer ()
{
@@ -125,6 +325,12 @@ namespace lldb_private {
return m_summary_cont.GetRegexMatch();
}
+ SummaryContainer&
+ GetSummaryContainer ()
+ {
+ return m_summary_cont;
+ }
+
FilterContainerSP
GetTypeFiltersContainer ()
{
@@ -136,6 +342,12 @@ namespace lldb_private {
{
return m_filter_cont.GetRegexMatch();
}
+
+ FilterContainer&
+ GetFilterContainer ()
+ {
+ return m_filter_cont;
+ }
FormatContainer::MapValueType
GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp);
@@ -185,12 +397,18 @@ namespace lldb_private {
return m_synth_cont.GetRegexMatch();
}
+ SynthContainer&
+ GetSyntheticsContainer ()
+ {
+ return m_synth_cont;
+ }
+
SynthContainer::MapValueType
GetSyntheticAtIndex (size_t index);
lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForSyntheticAtIndex (size_t index);
-#endif // #ifndef LLDB_DISABLE_PYTHON
+#endif // LLDB_DISABLE_PYTHON
ValidatorContainerSP
GetTypeValidatorsContainer ()
@@ -226,28 +444,28 @@ namespace lldb_private {
}
bool
- Get (ValueObject& valobj,
- const FormattersMatchVector& candidates,
- lldb::TypeFormatImplSP& entry,
- uint32_t* reason = NULL);
+ Get(ValueObject& valobj,
+ const FormattersMatchVector& candidates,
+ lldb::TypeFormatImplSP& entry,
+ uint32_t* reason = nullptr);
bool
- Get (ValueObject& valobj,
- const FormattersMatchVector& candidates,
- lldb::TypeSummaryImplSP& entry,
- uint32_t* reason = NULL);
+ Get(ValueObject& valobj,
+ const FormattersMatchVector& candidates,
+ lldb::TypeSummaryImplSP& entry,
+ uint32_t* reason = nullptr);
bool
- Get (ValueObject& valobj,
- const FormattersMatchVector& candidates,
- lldb::SyntheticChildrenSP& entry,
- uint32_t* reason = NULL);
+ Get(ValueObject& valobj,
+ const FormattersMatchVector& candidates,
+ lldb::SyntheticChildrenSP& entry,
+ uint32_t* reason = nullptr);
bool
- Get (ValueObject& valobj,
- const FormattersMatchVector& candidates,
- lldb::TypeValidatorImplSP& entry,
- uint32_t* reason = NULL);
+ Get(ValueObject& valobj,
+ const FormattersMatchVector& candidates,
+ lldb::TypeValidatorImplSP& entry,
+ uint32_t* reason = nullptr);
void
Clear (FormatCategoryItems items = ALL_ITEM_TYPES);
@@ -264,13 +482,28 @@ namespace lldb_private {
{
return m_name.GetCString();
}
+
+ size_t
+ GetNumLanguages ();
+
+ lldb::LanguageType
+ GetLanguageAtIndex (size_t idx);
+
+ void
+ AddLanguage (lldb::LanguageType lang);
bool
- AnyMatches (ConstString type_name,
- FormatCategoryItems items = ALL_ITEM_TYPES,
- bool only_enabled = true,
- const char** matching_category = NULL,
- FormatCategoryItems* matching_type = NULL);
+ HasLanguage (lldb::LanguageType lang);
+
+ std::string
+ GetDescription ();
+
+ bool
+ AnyMatches(ConstString type_name,
+ FormatCategoryItems items = ALL_ITEM_TYPES,
+ bool only_enabled = true,
+ const char** matching_category = nullptr,
+ FormatCategoryItems* matching_type = nullptr);
typedef std::shared_ptr<TypeCategoryImpl> SharedPointer;
@@ -280,7 +513,7 @@ namespace lldb_private {
FilterContainer m_filter_cont;
#ifndef LLDB_DISABLE_PYTHON
SynthContainer m_synth_cont;
-#endif // #ifndef LLDB_DISABLE_PYTHON
+#endif // LLDB_DISABLE_PYTHON
ValidatorContainer m_validator_cont;
bool m_enabled;
@@ -291,6 +524,8 @@ namespace lldb_private {
ConstString m_name;
+ std::vector<lldb::LanguageType> m_languages;
+
uint32_t m_enabled_position;
void
@@ -302,6 +537,9 @@ namespace lldb_private {
Enable(false, UINT32_MAX);
}
+ bool
+ IsApplicable (ValueObject& valobj);
+
uint32_t
GetLastEnabledPosition ()
{
@@ -314,6 +552,8 @@ namespace lldb_private {
m_enabled_position = p;
}
+ friend class FormatManager;
+ friend class LanguageCategory;
friend class TypeCategoryMap;
friend class FormattersContainer<ConstString, TypeFormatImpl>;
@@ -328,7 +568,7 @@ namespace lldb_private {
#ifndef LLDB_DISABLE_PYTHON
friend class FormattersContainer<ConstString, ScriptedSyntheticChildren>;
friend class FormattersContainer<lldb::RegularExpressionSP, ScriptedSyntheticChildren>;
-#endif // #ifndef LLDB_DISABLE_PYTHON
+#endif // LLDB_DISABLE_PYTHON
friend class FormattersContainer<ConstString, TypeValidatorImpl>;
friend class FormattersContainer<lldb::RegularExpressionSP, TypeValidatorImpl>;
@@ -336,4 +576,4 @@ namespace lldb_private {
} // namespace lldb_private
-#endif // lldb_TypeCategory_h_
+#endif // lldb_TypeCategory_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeCategoryMap.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeCategoryMap.h
index 41b170d..8afeaf8 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeCategoryMap.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeCategoryMap.h
@@ -1,4 +1,4 @@
-//===-- TypeCategoryMap.h ----------------------------------------*- C++ -*-===//
+//===-- TypeCategoryMap.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,6 +12,9 @@
// C Includes
// C++ Includes
+#include <functional>
+#include <list>
+#include <map>
// Other libraries and framework includes
// Project includes
@@ -34,7 +37,8 @@ namespace lldb_private {
public:
typedef std::map<KeyType, ValueSP> MapType;
typedef MapType::iterator MapIterator;
- typedef bool(*CallbackType)(void*, const ValueSP&);
+ typedef std::function<bool(const ValueSP&)> ForEachCallback;
+
typedef uint32_t Position;
static const Position First = 0;
@@ -82,17 +86,17 @@ namespace lldb_private {
ValueSP& entry);
void
- LoopThrough (CallbackType callback, void* param);
+ ForEach (ForEachCallback callback);
lldb::TypeCategoryImplSP
GetAtIndex (uint32_t);
bool
- AnyMatches (ConstString type_name,
- TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES,
- bool only_enabled = true,
- const char** matching_category = NULL,
- TypeCategoryImpl::FormatCategoryItems* matching_type = NULL);
+ AnyMatches(ConstString type_name,
+ TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES,
+ bool only_enabled = true,
+ const char** matching_category = nullptr,
+ TypeCategoryImpl::FormatCategoryItems* matching_type = nullptr);
uint32_t
GetCount ()
@@ -101,25 +105,20 @@ namespace lldb_private {
}
lldb::TypeFormatImplSP
- GetFormat (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic);
+ GetFormat (FormattersMatchData& match_data);
lldb::TypeSummaryImplSP
- GetSummaryFormat (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic);
+ GetSummaryFormat (FormattersMatchData& match_data);
#ifndef LLDB_DISABLE_PYTHON
lldb::SyntheticChildrenSP
- GetSyntheticChildren (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic);
+ GetSyntheticChildren (FormattersMatchData& match_data);
#endif
- lldb::TypeValidatorImplSP
- GetValidator (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic);
+ lldb::TypeValidatorImplSP
+ GetValidator(FormattersMatchData& match_data);
private:
-
class delete_matching_categories
{
lldb::TypeCategoryImplSP ptr;
@@ -159,4 +158,4 @@ namespace lldb_private {
};
} // namespace lldb_private
-#endif // lldb_TypeCategoryMap_h_
+#endif // lldb_TypeCategoryMap_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeFormat.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeFormat.h
index 8aa7c60..4ed28b6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeFormat.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeFormat.h
@@ -13,6 +13,7 @@
// C Includes
// C++ Includes
+#include <functional>
#include <string>
#include <unordered_map>
@@ -150,7 +151,6 @@ namespace lldb_private {
TypeFormatImpl (const Flags& flags = Flags());
typedef std::shared_ptr<TypeFormatImpl> SharedPointer;
- typedef bool(*ValueCallback)(void*, ConstString, const lldb::TypeFormatImplSP&);
virtual ~TypeFormatImpl ();
@@ -159,16 +159,19 @@ namespace lldb_private {
{
return m_flags.GetCascades();
}
+
bool
SkipsPointers () const
{
return m_flags.GetSkipPointers();
}
+
bool
SkipsReferences () const
{
return m_flags.GetSkipReferences();
}
+
bool
NonCacheable () const
{
@@ -255,9 +258,8 @@ namespace lldb_private {
const TypeFormatImpl::Flags& flags = Flags());
typedef std::shared_ptr<TypeFormatImpl_Format> SharedPointer;
- typedef bool(*ValueCallback)(void*, ConstString, const TypeFormatImpl_Format::SharedPointer&);
- virtual ~TypeFormatImpl_Format ();
+ ~TypeFormatImpl_Format() override;
lldb::Format
GetFormat () const
@@ -271,18 +273,18 @@ namespace lldb_private {
m_format = fmt;
}
- virtual TypeFormatImpl::Type
- GetType ()
+ TypeFormatImpl::Type
+ GetType() override
{
return TypeFormatImpl::Type::eTypeFormat;
}
- virtual bool
- FormatObject (ValueObject *valobj,
- std::string& dest) const;
+ bool
+ FormatObject(ValueObject *valobj,
+ std::string& dest) const override;
- virtual std::string
- GetDescription();
+ std::string
+ GetDescription() override;
protected:
lldb::Format m_format;
@@ -298,9 +300,8 @@ namespace lldb_private {
const TypeFormatImpl::Flags& flags = Flags());
typedef std::shared_ptr<TypeFormatImpl_EnumType> SharedPointer;
- typedef bool(*ValueCallback)(void*, ConstString, const TypeFormatImpl_EnumType::SharedPointer&);
- ~TypeFormatImpl_EnumType ();
+ ~TypeFormatImpl_EnumType() override;
ConstString
GetTypeName ()
@@ -314,26 +315,26 @@ namespace lldb_private {
m_enum_type = enum_type;
}
- virtual TypeFormatImpl::Type
- GetType ()
+ TypeFormatImpl::Type
+ GetType() override
{
return TypeFormatImpl::Type::eTypeEnum;
}
- virtual bool
- FormatObject (ValueObject *valobj,
- std::string& dest) const;
+ bool
+ FormatObject(ValueObject *valobj,
+ std::string& dest) const override;
- virtual std::string
- GetDescription();
+ std::string
+ GetDescription() override;
protected:
ConstString m_enum_type;
- mutable std::unordered_map<void*,ClangASTType> m_types;
+ mutable std::unordered_map<void*,CompilerType> m_types;
private:
DISALLOW_COPY_AND_ASSIGN(TypeFormatImpl_EnumType);
};
} // namespace lldb_private
-#endif // lldb_TypeFormat_h_
+#endif // lldb_TypeFormat_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSummary.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSummary.h
index c2838ea..e5bf4ec 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSummary.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSummary.h
@@ -1,4 +1,4 @@
-//===-- TypeSummary.h --------------------------------------------*- C++ -*-===//
+//===-- TypeSummary.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,11 +14,11 @@
#include <stdint.h>
// C++ Includes
+#include <functional>
+#include <memory>
#include <string>
-#include <vector>
// Other libraries and framework includes
-
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/lldb-enumerations.h"
@@ -26,8 +26,6 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/StructuredData.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/Type.h"
namespace lldb_private {
class TypeSummaryOptions
@@ -36,6 +34,8 @@ namespace lldb_private {
TypeSummaryOptions ();
TypeSummaryOptions (const TypeSummaryOptions& rhs);
+ ~TypeSummaryOptions() = default;
+
TypeSummaryOptions&
operator = (const TypeSummaryOptions& rhs);
@@ -50,8 +50,7 @@ namespace lldb_private {
TypeSummaryOptions&
SetCapping (lldb::TypeSummaryCapping);
-
- ~TypeSummaryOptions() = default;
+
private:
lldb::LanguageType m_lang;
lldb::TypeSummaryCapping m_capping;
@@ -60,10 +59,26 @@ namespace lldb_private {
class TypeSummaryImpl
{
public:
+ enum class Kind
+ {
+ eSummaryString,
+ eScript,
+ eCallback,
+ eInternal
+ };
+
+ virtual
+ ~TypeSummaryImpl() = default;
+
+ Kind
+ GetKind () const
+ {
+ return m_kind;
+ }
+
class Flags
{
public:
-
Flags () :
m_flags (lldb::eTypeOptionCascade)
{}
@@ -162,6 +177,22 @@ namespace lldb_private {
m_flags &= ~lldb::eTypeOptionHideChildren;
return *this;
}
+
+ bool
+ GetHideEmptyAggregates () const
+ {
+ return (m_flags & lldb::eTypeOptionHideEmptyAggregates) == lldb::eTypeOptionHideEmptyAggregates;
+ }
+
+ Flags&
+ SetHideEmptyAggregates (bool value = true)
+ {
+ if (value)
+ m_flags |= lldb::eTypeOptionHideEmptyAggregates;
+ else
+ m_flags &= ~lldb::eTypeOptionHideEmptyAggregates;
+ return *this;
+ }
bool
GetDontShowValue () const
@@ -243,31 +274,24 @@ namespace lldb_private {
uint32_t m_flags;
};
- typedef enum Type
- {
- eTypeUnknown,
- eTypeString,
- eTypeScript,
- eTypeCallback
- } Type;
-
- TypeSummaryImpl (const TypeSummaryImpl::Flags& flags);
-
bool
Cascades () const
{
return m_flags.GetCascades();
}
+
bool
SkipsPointers () const
{
return m_flags.GetSkipPointers();
}
+
bool
SkipsReferences () const
{
return m_flags.GetSkipReferences();
}
+
bool
NonCacheable () const
{
@@ -279,6 +303,12 @@ namespace lldb_private {
{
return !m_flags.GetDontShowChildren();
}
+
+ virtual bool
+ DoesPrintEmptyAggregates () const
+ {
+ return !m_flags.GetHideEmptyAggregates();
+ }
virtual bool
DoesPrintValue (ValueObject* valobj) const
@@ -358,11 +388,6 @@ namespace lldb_private {
m_flags.SetValue(value);
}
- virtual
- ~TypeSummaryImpl ()
- {
- }
-
// we are using a ValueObject* instead of a ValueObjectSP because we do not need to hold on to this for
// extended periods of time and we trust the ValueObject to stay around for as long as it is required
// for us to generate its summary
@@ -374,12 +399,6 @@ namespace lldb_private {
virtual std::string
GetDescription () = 0;
- virtual bool
- IsScripted () = 0;
-
- virtual Type
- GetType () = 0;
-
uint32_t&
GetRevision ()
{
@@ -387,14 +406,16 @@ namespace lldb_private {
}
typedef std::shared_ptr<TypeSummaryImpl> SharedPointer;
- typedef bool(*SummaryCallback)(void*, ConstString, const lldb::TypeSummaryImplSP&);
- typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const lldb::TypeSummaryImplSP&);
protected:
uint32_t m_my_revision;
Flags m_flags;
+ TypeSummaryImpl (Kind kind,
+ const TypeSummaryImpl::Flags& flags);
+
private:
+ Kind m_kind;
DISALLOW_COPY_AND_ASSIGN(TypeSummaryImpl);
};
@@ -407,11 +428,8 @@ namespace lldb_private {
StringSummaryFormat(const TypeSummaryImpl::Flags& flags,
const char* f);
-
- virtual
- ~StringSummaryFormat()
- {
- }
+
+ ~StringSummaryFormat() override = default;
const char*
GetSummaryString () const
@@ -422,25 +440,17 @@ namespace lldb_private {
void
SetSummaryString (const char* f);
- virtual bool
+ bool
FormatObject(ValueObject *valobj,
std::string& dest,
- const TypeSummaryOptions& options);
-
- virtual std::string
- GetDescription();
-
- virtual bool
- IsScripted ()
- {
- return false;
- }
+ const TypeSummaryOptions& options) override;
+ std::string
+ GetDescription() override;
- virtual Type
- GetType ()
+ static bool classof(const TypeSummaryImpl* S)
{
- return TypeSummaryImpl::eTypeString;
+ return S->GetKind() == Kind::eSummaryString;
}
private:
@@ -452,9 +462,9 @@ namespace lldb_private {
{
// we should convert these to SBValue and SBStream if we ever cross
// the boundary towards the external world
- typedef bool (*Callback)(ValueObject&,
- Stream&,
- const TypeSummaryOptions&);
+ typedef std::function<bool(ValueObject&,
+ Stream&,
+ const TypeSummaryOptions&)> Callback;
Callback m_impl;
std::string m_description;
@@ -462,7 +472,9 @@ namespace lldb_private {
CXXFunctionSummaryFormat (const TypeSummaryImpl::Flags& flags,
Callback impl,
const char* description);
-
+
+ ~CXXFunctionSummaryFormat() override = default;
+
Callback
GetBackendFunction () const
{
@@ -489,30 +501,18 @@ namespace lldb_private {
else
m_description.clear();
}
+
+ bool
+ FormatObject(ValueObject *valobj,
+ std::string& dest,
+ const TypeSummaryOptions& options) override;
- virtual
- ~CXXFunctionSummaryFormat ()
- {
- }
-
- virtual bool
- FormatObject (ValueObject *valobj,
- std::string& dest,
- const TypeSummaryOptions& options);
-
- virtual std::string
- GetDescription ();
-
- virtual bool
- IsScripted ()
- {
- return false;
- }
+ std::string
+ GetDescription() override;
- virtual Type
- GetType ()
+ static bool classof(const TypeSummaryImpl* S)
{
- return TypeSummaryImpl::eTypeCallback;
+ return S->GetKind() == Kind::eCallback;
}
typedef std::shared_ptr<CXXFunctionSummaryFormat> SharedPointer;
@@ -521,8 +521,6 @@ namespace lldb_private {
DISALLOW_COPY_AND_ASSIGN(CXXFunctionSummaryFormat);
};
-#ifndef LLDB_DISABLE_PYTHON
-
// Python-based summaries, running script code to show data
struct ScriptSummaryFormat : public TypeSummaryImpl
{
@@ -532,8 +530,10 @@ namespace lldb_private {
ScriptSummaryFormat(const TypeSummaryImpl::Flags& flags,
const char *function_name,
- const char* python_script = NULL);
-
+ const char* python_script = nullptr);
+
+ ~ScriptSummaryFormat() override = default;
+
const char*
GetFunctionName () const
{
@@ -565,38 +565,24 @@ namespace lldb_private {
m_python_script.clear();
}
- virtual
- ~ScriptSummaryFormat ()
- {
- }
-
- virtual bool
- FormatObject (ValueObject *valobj,
- std::string& dest,
- const TypeSummaryOptions& options);
-
- virtual std::string
- GetDescription ();
+ bool
+ FormatObject(ValueObject *valobj,
+ std::string& dest,
+ const TypeSummaryOptions& options) override;
- virtual bool
- IsScripted ()
- {
- return true;
- }
+ std::string
+ GetDescription() override;
- virtual Type
- GetType ()
+ static bool classof(const TypeSummaryImpl* S)
{
- return TypeSummaryImpl::eTypeScript;
+ return S->GetKind() == Kind::eScript;
}
typedef std::shared_ptr<ScriptSummaryFormat> SharedPointer;
-
private:
DISALLOW_COPY_AND_ASSIGN(ScriptSummaryFormat);
};
-#endif
} // namespace lldb_private
-#endif // lldb_TypeSummary_h_
+#endif // lldb_TypeSummary_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSynthetic.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSynthetic.h
index ff6691c..90e5730 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSynthetic.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeSynthetic.h
@@ -1,4 +1,4 @@
-//===-- TypeSynthetic.h -------------------------------------------*- C++ -*-===//
+//===-- TypeSynthetic.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,11 +14,13 @@
#include <stdint.h>
// C++ Includes
+#include <initializer_list>
+#include <functional>
+#include <memory>
#include <string>
#include <vector>
// Other libraries and framework includes
-
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/lldb-enumerations.h"
@@ -45,23 +47,27 @@ namespace lldb_private {
}
public:
-
SyntheticChildrenFrontEnd (ValueObject &backend) :
m_backend(backend),
m_valid(true)
{}
-
+
virtual
- ~SyntheticChildrenFrontEnd ()
- {
- }
-
+ ~SyntheticChildrenFrontEnd() = default;
+
virtual size_t
CalculateNumChildren () = 0;
+
+ virtual size_t
+ CalculateNumChildren (uint32_t max)
+ {
+ auto count = CalculateNumChildren ();
+ return count <= max ? count : max;
+ }
virtual lldb::ValueObjectSP
GetChildAtIndex (size_t idx) = 0;
-
+
virtual size_t
GetIndexOfChildWithName (const ConstString &name) = 0;
@@ -98,13 +104,13 @@ namespace lldb_private {
CreateValueObjectFromAddress (const char* name,
uint64_t address,
const ExecutionContext& exe_ctx,
- ClangASTType type);
+ CompilerType type);
lldb::ValueObjectSP
CreateValueObjectFromData (const char* name,
const DataExtractor& data,
const ExecutionContext& exe_ctx,
- ClangASTType type);
+ CompilerType type);
private:
bool m_valid;
@@ -117,29 +123,26 @@ namespace lldb_private {
SyntheticValueProviderFrontEnd (ValueObject &backend) :
SyntheticChildrenFrontEnd(backend)
{}
+
+ ~SyntheticValueProviderFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override { return 0; }
- virtual
- ~SyntheticValueProviderFrontEnd ()
- {
- }
-
- virtual size_t
- CalculateNumChildren () { return 0; }
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx) { return nullptr; }
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override { return nullptr; }
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name) { return UINT32_MAX; }
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override { return UINT32_MAX; }
- virtual bool
- Update () { return false; }
+ bool
+ Update() override { return false; }
- virtual bool
- MightHaveChildren () { return false; }
+ bool
+ MightHaveChildren () override { return false; }
- virtual lldb::ValueObjectSP
- GetSyntheticValue () = 0;
+ lldb::ValueObjectSP
+ GetSyntheticValue() override = 0;
private:
DISALLOW_COPY_AND_ASSIGN(SyntheticValueProviderFrontEnd);
@@ -148,7 +151,6 @@ namespace lldb_private {
class SyntheticChildren
{
public:
-
class Flags
{
public:
@@ -272,27 +274,28 @@ namespace lldb_private {
m_flags(flags)
{
}
-
+
virtual
- ~SyntheticChildren ()
- {
- }
-
+ ~SyntheticChildren() = default;
+
bool
Cascades () const
{
return m_flags.GetCascades();
}
+
bool
SkipsPointers () const
{
return m_flags.GetSkipPointers();
}
+
bool
SkipsReferences () const
{
return m_flags.GetSkipReferences();
}
+
bool
NonCacheable () const
{
@@ -345,7 +348,6 @@ namespace lldb_private {
GetFrontEnd (ValueObject &backend) = 0;
typedef std::shared_ptr<SyntheticChildren> SharedPointer;
- typedef bool(*SyntheticChildrenCallback)(void*, ConstString, const SyntheticChildren::SharedPointer&);
uint32_t&
GetRevision ()
@@ -417,69 +419,67 @@ namespace lldb_private {
SetExpressionPathAtIndex (size_t i, const std::string& path);
bool
- IsScripted ()
+ IsScripted() override
{
return false;
}
std::string
- GetDescription ();
+ GetDescription() override;
class FrontEnd : public SyntheticChildrenFrontEnd
{
- private:
- TypeFilterImpl* filter;
public:
-
FrontEnd(TypeFilterImpl* flt,
ValueObject &backend) :
SyntheticChildrenFrontEnd(backend),
filter(flt)
{}
-
- virtual
- ~FrontEnd ()
- {
- }
-
- virtual size_t
- CalculateNumChildren ()
+
+ ~FrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override
{
return filter->GetCount();
}
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx)
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
{
if (idx >= filter->GetCount())
return lldb::ValueObjectSP();
return m_backend.GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx), true);
}
+
+ bool
+ Update() override { return false; }
- virtual bool
- Update() { return false; }
-
- virtual bool
- MightHaveChildren ()
+ bool
+ MightHaveChildren() override
{
return filter->GetCount() > 0;
}
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
private:
+ TypeFilterImpl* filter;
+
DISALLOW_COPY_AND_ASSIGN(FrontEnd);
};
- virtual SyntheticChildrenFrontEnd::AutoPointer
- GetFrontEnd(ValueObject &backend)
+ SyntheticChildrenFrontEnd::AutoPointer
+ GetFrontEnd(ValueObject &backend) override
{
return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend));
}
+ typedef std::shared_ptr<TypeFilterImpl> SharedPointer;
+
private:
DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl);
};
@@ -487,11 +487,7 @@ namespace lldb_private {
class CXXSyntheticChildren : public SyntheticChildren
{
public:
- typedef SyntheticChildrenFrontEnd* (*CreateFrontEndCallback) (CXXSyntheticChildren*, lldb::ValueObjectSP);
- protected:
- CreateFrontEndCallback m_create_callback;
- std::string m_description;
- public:
+ typedef std::function<SyntheticChildrenFrontEnd*(CXXSyntheticChildren*, lldb::ValueObjectSP)> CreateFrontEndCallback;
CXXSyntheticChildren (const SyntheticChildren::Flags& flags,
const char* description,
CreateFrontEndCallback callback) :
@@ -502,20 +498,24 @@ namespace lldb_private {
}
bool
- IsScripted ()
+ IsScripted() override
{
return false;
}
std::string
- GetDescription ();
+ GetDescription() override;
- virtual SyntheticChildrenFrontEnd::AutoPointer
- GetFrontEnd (ValueObject &backend)
+ SyntheticChildrenFrontEnd::AutoPointer
+ GetFrontEnd(ValueObject &backend) override
{
return SyntheticChildrenFrontEnd::AutoPointer(m_create_callback(this, backend.GetSP()));
}
+ protected:
+ CreateFrontEndCallback m_create_callback;
+ std::string m_description;
+
private:
DISALLOW_COPY_AND_ASSIGN(CXXSyntheticChildren);
};
@@ -528,9 +528,9 @@ namespace lldb_private {
std::string m_python_code;
public:
- ScriptedSyntheticChildren (const SyntheticChildren::Flags& flags,
- const char* pclass,
- const char* pcode = NULL) :
+ ScriptedSyntheticChildren(const SyntheticChildren::Flags& flags,
+ const char* pclass,
+ const char* pcode = nullptr) :
SyntheticChildren(flags),
m_python_class(),
m_python_code()
@@ -567,62 +567,63 @@ namespace lldb_private {
}
std::string
- GetDescription ();
+ GetDescription() override;
bool
- IsScripted ()
+ IsScripted() override
{
return true;
}
class FrontEnd : public SyntheticChildrenFrontEnd
{
- private:
- std::string m_python_class;
- StructuredData::ObjectSP m_wrapper_sp;
- ScriptInterpreter *m_interpreter;
public:
-
FrontEnd (std::string pclass,
ValueObject &backend);
+ ~FrontEnd() override;
+
bool
IsValid ();
- virtual
- ~FrontEnd ();
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
+ size_t
+ CalculateNumChildren() override;
+
+ size_t
+ CalculateNumChildren(uint32_t max) override;
- virtual bool
- Update ();
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
- virtual bool
- MightHaveChildren ();
+ bool
+ MightHaveChildren() override;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
- virtual lldb::ValueObjectSP
- GetSyntheticValue ();
+ lldb::ValueObjectSP
+ GetSyntheticValue() override;
typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
private:
+ std::string m_python_class;
+ StructuredData::ObjectSP m_wrapper_sp;
+ ScriptInterpreter *m_interpreter;
+
DISALLOW_COPY_AND_ASSIGN(FrontEnd);
};
- virtual SyntheticChildrenFrontEnd::AutoPointer
- GetFrontEnd(ValueObject &backend)
+ SyntheticChildrenFrontEnd::AutoPointer
+ GetFrontEnd(ValueObject &backend) override
{
auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend));
if (synth_ptr && ((FrontEnd*)synth_ptr.get())->IsValid())
return synth_ptr;
- return NULL;
+ return nullptr;
}
private:
@@ -631,4 +632,4 @@ namespace lldb_private {
#endif
} // namespace lldb_private
-#endif // lldb_TypeSynthetic_h_
+#endif // lldb_TypeSynthetic_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeValidator.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeValidator.h
index d06fac0..f1f9a11 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeValidator.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/TypeValidator.h
@@ -13,8 +13,8 @@
// C Includes
// C++ Includes
-#include <string>
#include <functional>
+#include <string>
// Other libraries and framework includes
@@ -150,7 +150,6 @@ public:
TypeValidatorImpl (const Flags& flags = Flags());
typedef std::shared_ptr<TypeValidatorImpl> SharedPointer;
- typedef bool(*ValueCallback)(void*, ConstString, const lldb::TypeValidatorImplSP&);
virtual ~TypeValidatorImpl ();
@@ -265,9 +264,8 @@ public:
TypeValidatorImpl_CXX (ValidatorFunction f, std::string d, const TypeValidatorImpl::Flags& flags = Flags());
typedef std::shared_ptr<TypeValidatorImpl_CXX> SharedPointer;
- typedef bool(*ValueCallback)(void*, ConstString, const TypeValidatorImpl_CXX::SharedPointer&);
- virtual ~TypeValidatorImpl_CXX ();
+ ~TypeValidatorImpl_CXX() override;
ValidatorFunction
GetValidatorFunction () const
@@ -281,17 +279,17 @@ public:
m_validator_function = f;
}
- virtual TypeValidatorImpl::Type
- GetType ()
+ TypeValidatorImpl::Type
+ GetType() override
{
return TypeValidatorImpl::Type::eTypeCXX;
}
- virtual ValidationResult
- FormatObject (ValueObject *valobj) const;
+ ValidationResult
+ FormatObject(ValueObject *valobj) const override;
- virtual std::string
- GetDescription();
+ std::string
+ GetDescription() override;
protected:
std::string m_description;
@@ -304,4 +302,4 @@ private:
} // namespace lldb_private
-#endif // lldb_TypeValidator_h_
+#endif // lldb_TypeValidator_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
index dc05fd4..23d7ee2 100644
--- a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
@@ -18,232 +18,15 @@
#include "lldb/lldb-private.h"
#include "lldb/lldb-public.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Core/Flags.h"
+#include "lldb/DataFormatters/DumpValueObjectOptions.h"
+#include "lldb/Symbol/CompilerType.h"
-namespace lldb_private {
+//#include <functional>
+//#include <memory>
+//#include <set>
-struct DumpValueObjectOptions
-{
- uint32_t m_max_ptr_depth = 0;
- uint32_t m_max_depth = UINT32_MAX;
- lldb::DynamicValueType m_use_dynamic = lldb::eNoDynamicValues;
- uint32_t m_omit_summary_depth = 0;
- lldb::Format m_format = lldb::eFormatDefault;
- lldb::TypeSummaryImplSP m_summary_sp;
- std::string m_root_valobj_name;
- bool m_use_synthetic : 1;
- bool m_scope_already_checked : 1;
- bool m_flat_output : 1;
- bool m_ignore_cap : 1;
- bool m_show_types : 1;
- bool m_show_location : 1;
- bool m_use_objc : 1;
- bool m_hide_root_type : 1;
- bool m_hide_name : 1;
- bool m_hide_value : 1;
- bool m_run_validator : 1;
- bool m_use_type_display_name : 1;
- bool m_allow_oneliner_mode : 1;
-
- DumpValueObjectOptions() :
- m_summary_sp(),
- m_root_valobj_name(),
- m_use_synthetic(true),
- m_scope_already_checked(false),
- m_flat_output(false),
- m_ignore_cap(false),
- m_show_types(false),
- m_show_location(false),
- m_use_objc(false),
- m_hide_root_type(false),
- m_hide_name(false),
- m_hide_value(false),
- m_run_validator(false),
- m_use_type_display_name(true),
- m_allow_oneliner_mode(true)
- {}
-
- static const DumpValueObjectOptions
- DefaultOptions()
- {
- static DumpValueObjectOptions g_default_options;
-
- return g_default_options;
- }
-
- DumpValueObjectOptions (const DumpValueObjectOptions& rhs) = default;
-
- DumpValueObjectOptions (ValueObject& valobj);
-
- DumpValueObjectOptions&
- SetMaximumPointerDepth(uint32_t depth = 0)
- {
- m_max_ptr_depth = depth;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetMaximumDepth(uint32_t depth = 0)
- {
- m_max_depth = depth;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetShowTypes(bool show = false)
- {
- m_show_types = show;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetShowLocation(bool show = false)
- {
- m_show_location = show;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetUseObjectiveC(bool use = false)
- {
- m_use_objc = use;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetShowSummary(bool show = true)
- {
- if (show == false)
- SetOmitSummaryDepth(UINT32_MAX);
- else
- SetOmitSummaryDepth(0);
- return *this;
- }
-
- DumpValueObjectOptions&
- SetUseDynamicType(lldb::DynamicValueType dyn = lldb::eNoDynamicValues)
- {
- m_use_dynamic = dyn;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetUseSyntheticValue(bool use_synthetic = true)
- {
- m_use_synthetic = use_synthetic;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetScopeChecked(bool check = true)
- {
- m_scope_already_checked = check;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetFlatOutput(bool flat = false)
- {
- m_flat_output = flat;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetOmitSummaryDepth(uint32_t depth = 0)
- {
- m_omit_summary_depth = depth;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetIgnoreCap(bool ignore = false)
- {
- m_ignore_cap = ignore;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetRawDisplay()
- {
- SetUseSyntheticValue(false);
- SetOmitSummaryDepth(UINT32_MAX);
- SetIgnoreCap(true);
- SetHideName(false);
- SetHideValue(false);
- SetUseTypeDisplayName(false);
- SetAllowOnelinerMode(false);
- return *this;
- }
-
- DumpValueObjectOptions&
- SetFormat (lldb::Format format = lldb::eFormatDefault)
- {
- m_format = format;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetSummary (lldb::TypeSummaryImplSP summary = lldb::TypeSummaryImplSP())
- {
- m_summary_sp = summary;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetRootValueObjectName (const char* name = NULL)
- {
- if (name)
- m_root_valobj_name.assign(name);
- else
- m_root_valobj_name.clear();
- return *this;
- }
-
- DumpValueObjectOptions&
- SetHideRootType (bool hide_root_type = false)
- {
- m_hide_root_type = hide_root_type;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetHideName (bool hide_name = false)
- {
- m_hide_name = hide_name;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetHideValue (bool hide_value = false)
- {
- m_hide_value = hide_value;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetRunValidator (bool run = true)
- {
- m_run_validator = run;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetUseTypeDisplayName (bool dis = false)
- {
- m_use_type_display_name = dis;
- return *this;
- }
-
- DumpValueObjectOptions&
- SetAllowOnelinerMode (bool oneliner = false)
- {
- m_allow_oneliner_mode = oneliner;
- return *this;
- }
-
-};
+namespace lldb_private {
class ValueObjectPrinter
{
@@ -262,14 +45,19 @@ public:
PrintValueObject ();
protected:
+ typedef std::set<uint64_t> InstancePointersSet;
+ typedef std::shared_ptr<InstancePointersSet> InstancePointersSetSP;
+ InstancePointersSetSP m_printed_instance_pointers;
+
// only this class (and subclasses, if any) should ever be concerned with
// the depth mechanism
ValueObjectPrinter (ValueObject* valobj,
Stream* s,
const DumpValueObjectOptions& options,
- uint32_t ptr_depth,
- uint32_t curr_depth);
+ const DumpValueObjectOptions::PointerDepth& ptr_depth,
+ uint32_t curr_depth,
+ InstancePointersSetSP printed_instance_pointers);
// we should actually be using delegating constructors here
// but some versions of GCC still have trouble with those
@@ -277,8 +65,9 @@ protected:
Init (ValueObject* valobj,
Stream* s,
const DumpValueObjectOptions& options,
- uint32_t ptr_depth,
- uint32_t curr_depth);
+ const DumpValueObjectOptions::PointerDepth& ptr_depth,
+ uint32_t curr_depth,
+ InstancePointersSetSP printed_instance_pointers);
bool
GetMostSpecializedValue ();
@@ -299,12 +88,18 @@ protected:
IsNil ();
bool
+ IsUninitialized ();
+
+ bool
IsPtr ();
bool
IsRef ();
bool
+ IsInstancePointer ();
+
+ bool
IsAggregate ();
bool
@@ -316,17 +111,18 @@ protected:
bool
PrintLocationIfNeeded ();
- bool
- PrintTypeIfNeeded ();
+ void
+ PrintDecl ();
bool
- PrintNameIfNeeded (bool show_type);
+ CheckScopeIfNeeded ();
bool
- CheckScopeIfNeeded ();
+ ShouldPrintEmptyBrackets (bool value_printed,
+ bool summary_printed);
TypeSummaryImpl*
- GetSummaryFormatter ();
+ GetSummaryFormatter (bool null_if_omitted = true);
void
GetValueSummaryError (std::string& value,
@@ -343,7 +139,10 @@ protected:
bool
ShouldPrintChildren (bool is_failed_description,
- uint32_t& curr_ptr_depth);
+ DumpValueObjectOptions::PointerDepth& curr_ptr_depth);
+
+ bool
+ ShouldExpandEmptyAggregates ();
ValueObject*
GetValueObjectForChildrenGeneration ();
@@ -356,13 +155,15 @@ protected:
void
PrintChild (lldb::ValueObjectSP child_sp,
- uint32_t curr_ptr_depth);
+ const DumpValueObjectOptions::PointerDepth& curr_ptr_depth);
uint32_t
GetMaxNumChildrenToPrint (bool& print_dotdotdot);
void
- PrintChildren (uint32_t curr_ptr_depth);
+ PrintChildren (bool value_printed,
+ bool summary_printed,
+ const DumpValueObjectOptions::PointerDepth& curr_ptr_depth);
void
PrintChildrenIfNeeded (bool value_printed,
@@ -376,20 +177,23 @@ private:
ValueObject *m_orig_valobj;
ValueObject *m_valobj;
Stream *m_stream;
- DumpValueObjectOptions options;
+ DumpValueObjectOptions m_options;
Flags m_type_flags;
- ClangASTType m_clang_type;
- uint32_t m_ptr_depth;
+ CompilerType m_compiler_type;
+ DumpValueObjectOptions::PointerDepth m_ptr_depth;
uint32_t m_curr_depth;
LazyBool m_should_print;
LazyBool m_is_nil;
+ LazyBool m_is_uninit;
LazyBool m_is_ptr;
LazyBool m_is_ref;
LazyBool m_is_aggregate;
+ LazyBool m_is_instance_ptr;
std::pair<TypeSummaryImpl*,bool> m_summary_formatter;
std::string m_value;
std::string m_summary;
std::string m_error;
+ bool m_val_summary_ok;
std::pair<TypeValidatorResult,std::string> m_validation;
friend struct StringSummaryFormat;
diff --git a/contrib/llvm/tools/lldb/include/lldb/DataFormatters/VectorIterator.h b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/VectorIterator.h
new file mode 100644
index 0000000..3d96ee4
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/DataFormatters/VectorIterator.h
@@ -0,0 +1,53 @@
+//===-- VectorIterator.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_VectorIterator_h_
+#define liblldb_VectorIterator_h_
+
+#include "lldb/lldb-forward.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Target/ExecutionContext.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
+ ConstString item_name);
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ ~VectorIteratorSyntheticFrontEnd() override;
+
+ private:
+ ExecutionContextRef m_exe_ctx_ref;
+ ConstString m_item_name;
+ lldb::ValueObjectSP m_item_sp;
+ };
+
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CF_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/DWARFExpression.h b/contrib/llvm/tools/lldb/include/lldb/Expression/DWARFExpression.h
index 9ddecc0..3527c3b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/DWARFExpression.h
@@ -11,18 +11,19 @@
#define liblldb_DWARFExpression_h_
#include "lldb/lldb-private.h"
-#include "lldb/Core/ClangForward.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Scalar.h"
+class DWARFCompileUnit;
+
namespace lldb_private {
+class ClangExpressionDeclMap;
class ClangExpressionVariable;
class ClangExpressionVariableList;
-class ClangExpressionDeclMap;
//----------------------------------------------------------------------
/// @class DWARFExpression DWARFExpression.h "lldb/Expression/DWARFExpression.h"
@@ -40,10 +41,17 @@ class ClangExpressionDeclMap;
class DWARFExpression
{
public:
+ enum LocationListFormat : uint8_t
+ {
+ NonLocationList, // Not a location list
+ RegularLocationList, // Location list format used in non-split dwarf files
+ SplitDwarfLocationList, // Location list format used in split dwarf files
+ };
+
//------------------------------------------------------------------
/// Constructor
//------------------------------------------------------------------
- DWARFExpression();
+ explicit DWARFExpression(DWARFCompileUnit* dwarf_cu);
//------------------------------------------------------------------
/// Constructor
@@ -60,6 +68,7 @@ public:
//------------------------------------------------------------------
DWARFExpression(lldb::ModuleSP module,
const DataExtractor& data,
+ DWARFCompileUnit* dwarf_cu,
lldb::offset_t data_offset,
lldb::offset_t data_length);
@@ -356,6 +365,7 @@ public:
RegisterContext *reg_ctx,
lldb::ModuleSP opcode_ctx,
const DataExtractor& opcodes,
+ DWARFCompileUnit* dwarf_cu,
const lldb::offset_t offset,
const lldb::offset_t length,
const lldb::RegisterKind reg_set,
@@ -397,6 +407,24 @@ public:
lldb::addr_t address,
ABI *abi);
+ static size_t
+ LocationListSize(const DWARFCompileUnit* dwarf_cu,
+ const DataExtractor& debug_loc_data,
+ lldb::offset_t offset);
+
+ static bool
+ PrintDWARFExpression(Stream &s,
+ const DataExtractor& data,
+ int address_size,
+ int dwarf_ref_size,
+ bool location_expression);
+
+ static void
+ PrintDWARFLocationList(Stream &s,
+ const DWARFCompileUnit* cu,
+ const DataExtractor& debug_loc_data,
+ lldb::offset_t offset);
+
protected:
//------------------------------------------------------------------
/// Pretty-prints the location expression to a stream
@@ -430,17 +458,26 @@ protected:
lldb::offset_t &offset,
lldb::offset_t &len);
+ static bool
+ AddressRangeForLocationListEntry(const DWARFCompileUnit* dwarf_cu,
+ const DataExtractor& debug_loc_data,
+ lldb::offset_t* offset_ptr,
+ lldb::addr_t& low_pc,
+ lldb::addr_t& high_pc);
+
//------------------------------------------------------------------
/// Classes that inherit from DWARFExpression can see and modify these
//------------------------------------------------------------------
lldb::ModuleWP m_module_wp; ///< Module which defined this expression.
DataExtractor m_data; ///< A data extractor capable of reading opcode bytes
+ DWARFCompileUnit* m_dwarf_cu; ///< The DWARF compile unit this expression belongs to. It is used
+ ///< to evaluate values indexing into the .debug_addr section (e.g.
+ ///< DW_OP_GNU_addr_index, DW_OP_GNU_const_index)
lldb::RegisterKind m_reg_kind; ///< One of the defines that starts with LLDB_REGKIND_
lldb::addr_t m_loclist_slide; ///< A value used to slide the location list offsets so that
///< they are relative to the object that owns the location list
///< (the function for frame base and variable location lists)
-
};
} // namespace lldb_private
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpression.h b/contrib/llvm/tools/lldb/include/lldb/Expression/Expression.h
index 6e831e4..b5c2d57 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpression.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/Expression.h
@@ -1,4 +1,4 @@
-//===-- ClangExpression.h ---------------------------------------*- C++ -*-===//
+//===-- Expression.h --------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_ClangExpression_h_
-#define liblldb_ClangExpression_h_
+#ifndef liblldb_Expression_h_
+#define liblldb_Expression_h_
// C Includes
// C++ Includes
@@ -21,23 +21,23 @@
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
-#include "lldb/Core/ClangForward.h"
-#include "lldb/Target/Process.h"
+#include "lldb/Expression/ExpressionTypeSystemHelper.h"
namespace lldb_private {
class RecordingMemoryManager;
//----------------------------------------------------------------------
-/// @class ClangExpression ClangExpression.h "lldb/Expression/ClangExpression.h"
-/// @brief Encapsulates a single expression for use with Clang
+/// @class Expression Expression.h "lldb/Expression/Expression.h"
+/// @brief Encapsulates a single expression for use in lldb
///
/// LLDB uses expressions for various purposes, notably to call functions
-/// and as a backend for the expr command. ClangExpression encapsulates
+/// and as a backend for the expr command. Expression encapsulates
/// the objects needed to parse and interpret or JIT an expression. It
-/// uses the Clang parser to produce LLVM IR from the expression.
+/// uses the expression parser appropriate to the language of the expression
+/// to produce LLVM IR from the expression.
//----------------------------------------------------------------------
-class ClangExpression
+class Expression
{
public:
enum ResultType {
@@ -45,17 +45,14 @@ public:
eResultTypeId
};
- ClangExpression () :
- m_jit_process_wp(),
- m_jit_start_addr (LLDB_INVALID_ADDRESS),
- m_jit_end_addr (LLDB_INVALID_ADDRESS)
- {
- }
-
+ Expression (Target &target);
+
+ Expression (ExecutionContextScope &exe_scope);
+
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- virtual ~ClangExpression ()
+ virtual ~Expression ()
{
}
@@ -85,24 +82,6 @@ public:
}
//------------------------------------------------------------------
- /// Return the object that the parser should use when resolving external
- /// values. May be NULL if everything should be self-contained.
- //------------------------------------------------------------------
- virtual ClangExpressionDeclMap *
- DeclMap () = 0;
-
- //------------------------------------------------------------------
- /// Return the object that the parser should allow to access ASTs.
- /// May be NULL if the ASTs do not need to be transformed.
- ///
- /// @param[in] passthrough
- /// The ASTConsumer that the returned transformer should send
- /// the ASTs to after transformation.
- //------------------------------------------------------------------
- virtual clang::ASTConsumer *
- ASTTransformer (clang::ASTConsumer *passthrough) = 0;
-
- //------------------------------------------------------------------
/// Return the desired result type of the function, or
/// eResultTypeAny if indifferent.
//------------------------------------------------------------------
@@ -130,6 +109,8 @@ public:
virtual bool
NeedsVariableResolution () = 0;
+ virtual EvaluateExpressionOptions *GetOptions() { return nullptr; };
+
//------------------------------------------------------------------
/// Return the address of the function's JIT-compiled code, or
/// LLDB_INVALID_ADDRESS if the function is not JIT compiled
@@ -139,10 +120,17 @@ public:
{
return m_jit_start_addr;
}
+
+ virtual ExpressionTypeSystemHelper *
+ GetTypeSystemHelper ()
+ {
+ return nullptr;
+ }
protected:
- lldb::ProcessWP m_jit_process_wp;
+ lldb::TargetWP m_target_wp; /// Expression's always have to have a target...
+ lldb::ProcessWP m_jit_process_wp; /// An expression might have a process, but it doesn't need to (e.g. calculator mode.)
lldb::addr_t m_jit_start_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid.
lldb::addr_t m_jit_end_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid.
@@ -150,4 +138,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_ClangExpression_h_
+#endif // liblldb_Expression_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionParser.h b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionParser.h
new file mode 100644
index 0000000..49333e7
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionParser.h
@@ -0,0 +1,123 @@
+//===-- ExpressionParser.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ExpressionParser_h_
+#define liblldb_ExpressionParser_h_
+
+#include "lldb/lldb-public.h"
+#include "lldb/Core/Error.h"
+
+namespace lldb_private
+{
+
+class IRExecutionUnit;
+
+//----------------------------------------------------------------------
+/// @class ExpressionParser ExpressionParser.h "lldb/Expression/ExpressionParser.h"
+/// @brief Encapsulates an instance of a compiler that can parse expressions.
+///
+/// ExpressionParser is the base class for llvm based Expression parsers.
+//----------------------------------------------------------------------
+class ExpressionParser
+{
+public:
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// Initializes class variables.
+ ///
+ /// @param[in] exe_scope,
+ /// If non-NULL, an execution context scope that can help to
+ /// correctly create an expression with a valid process for
+ /// optional tuning Objective-C runtime support. Can be NULL.
+ ///
+ /// @param[in] expr
+ /// The expression to be parsed.
+ //------------------------------------------------------------------
+ ExpressionParser (ExecutionContextScope *exe_scope,
+ Expression &expr,
+ bool generate_debug_info) :
+ m_expr(expr),
+ m_generate_debug_info(generate_debug_info)
+ {
+ }
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ virtual ~ExpressionParser () {};
+
+ //------------------------------------------------------------------
+ /// Parse a single expression and convert it to IR using Clang. Don't
+ /// wrap the expression in anything at all.
+ ///
+ /// @param[in] stream
+ /// The stream to print errors to.
+ ///
+ /// @return
+ /// The number of errors encountered during parsing. 0 means
+ /// success.
+ //------------------------------------------------------------------
+ virtual unsigned
+ Parse (Stream &stream) = 0;
+
+ //------------------------------------------------------------------
+ /// Ready an already-parsed expression for execution, possibly
+ /// evaluating it statically.
+ ///
+ /// @param[out] func_addr
+ /// The address to which the function has been written.
+ ///
+ /// @param[out] func_end
+ /// The end of the function's allocated memory region. (func_addr
+ /// and func_end do not delimit an allocated region; the allocated
+ /// region may begin before func_addr.)
+ ///
+ /// @param[in] execution_unit_sp
+ /// After parsing, ownership of the execution unit for
+ /// for the expression is handed to this shared pointer.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to write the function into.
+ ///
+ /// @param[out] can_interpret
+ /// Set to true if the expression could be interpreted statically;
+ /// untouched otherwise.
+ ///
+ /// @param[in] execution_policy
+ /// Determines whether the expression must be JIT-compiled, must be
+ /// evaluated statically, or whether this decision may be made
+ /// opportunistically.
+ ///
+ /// @return
+ /// An error code indicating the success or failure of the operation.
+ /// Test with Success().
+ //------------------------------------------------------------------
+ virtual Error
+ PrepareForExecution (lldb::addr_t &func_addr,
+ lldb::addr_t &func_end,
+ std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
+ ExecutionContext &exe_ctx,
+ bool &can_interpret,
+ lldb_private::ExecutionPolicy execution_policy) = 0;
+
+ bool
+ GetGenerateDebugInfo () const
+ {
+ return m_generate_debug_info;
+ }
+
+protected:
+ Expression & m_expr; ///< The expression to be parsed
+ bool m_generate_debug_info;
+};
+
+}
+
+#endif // liblldb_ExpressionParser_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h
new file mode 100644
index 0000000..cb560c9
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h
@@ -0,0 +1,54 @@
+//===-- ExpressionTypeSystemHelper.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ExpressionTypeSystemHelper_h
+#define ExpressionTypeSystemHelper_h
+
+#include "llvm/Support/Casting.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class ExpressionTypeSystemHelper ExpressionTypeSystemHelper.h "lldb/Expression/ExpressionTypeSystemHelper.h"
+/// @brief A helper object that the Expression can pass to its ExpressionParser to provide generic information that
+/// any type of expression will need to supply. It's only job is to support dyn_cast so that the expression parser
+/// can cast it back to the requisite specific type.
+///
+//----------------------------------------------------------------------
+
+class ExpressionTypeSystemHelper
+{
+public:
+ enum LLVMCastKind {
+ eKindClangHelper,
+ eKindSwiftHelper,
+ eKindGoHelper,
+ kNumKinds
+ };
+
+ LLVMCastKind getKind() const { return m_kind; }
+
+ ExpressionTypeSystemHelper (LLVMCastKind kind) :
+ m_kind(kind)
+ {
+ }
+
+ ~ExpressionTypeSystemHelper () {}
+
+protected:
+ LLVMCastKind m_kind;
+};
+
+
+
+
+} // namespace lldb_private
+
+#endif /* ExpressionTypeSystemHelper_h */
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionVariable.h b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionVariable.h
new file mode 100644
index 0000000..d8030ba
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/ExpressionVariable.h
@@ -0,0 +1,320 @@
+//===-- ExpressionVariable.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ExpressionVariable_h_
+#define liblldb_ExpressionVariable_h_
+
+// C Includes
+// C++ Includes
+#include <memory>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/ValueObject.h"
+
+namespace lldb_private
+{
+
+class ClangExpressionVariable;
+
+class ExpressionVariable :
+ public std::enable_shared_from_this<ExpressionVariable>
+{
+public:
+ //----------------------------------------------------------------------
+ // See TypeSystem.h for how to add subclasses to this.
+ //----------------------------------------------------------------------
+ enum LLVMCastKind {
+ eKindClang,
+ eKindSwift,
+ eKindGo,
+ kNumKinds
+ };
+
+ LLVMCastKind getKind() const { return m_kind; }
+
+ ExpressionVariable(LLVMCastKind kind) :
+ m_flags(0),
+ m_kind(kind)
+ {
+ }
+
+ virtual ~ExpressionVariable();
+
+ size_t
+ GetByteSize ()
+ {
+ return m_frozen_sp->GetByteSize();
+ }
+
+ const ConstString &
+ GetName ()
+ {
+ return m_frozen_sp->GetName();
+ }
+
+ lldb::ValueObjectSP
+ GetValueObject()
+ {
+ return m_frozen_sp;
+ }
+
+ uint8_t *GetValueBytes();
+
+ void
+ ValueUpdated ()
+ {
+ m_frozen_sp->ValueUpdated ();
+ }
+
+ RegisterInfo *
+ GetRegisterInfo()
+ {
+ return m_frozen_sp->GetValue().GetRegisterInfo();
+ }
+
+ void
+ SetRegisterInfo (const RegisterInfo *reg_info)
+ {
+ return m_frozen_sp->GetValue().SetContext (Value::eContextTypeRegisterInfo, const_cast<RegisterInfo *>(reg_info));
+ }
+
+ CompilerType
+ GetCompilerType()
+ {
+ return m_frozen_sp->GetCompilerType();
+ }
+
+ void
+ SetCompilerType(const CompilerType &compiler_type)
+ {
+ m_frozen_sp->GetValue().SetCompilerType(compiler_type);
+ }
+
+ void
+ SetName (const ConstString &name)
+ {
+ m_frozen_sp->SetName (name);
+ }
+
+ // this function is used to copy the address-of m_live_sp into m_frozen_sp
+ // this is necessary because the results of certain cast and pointer-arithmetic
+ // operations (such as those described in bugzilla issues 11588 and 11618) generate
+ // frozen objects that do not have a valid address-of, which can be troublesome when
+ // using synthetic children providers. Transferring the address-of the live object
+ // solves these issues and provides the expected user-level behavior
+ void
+ TransferAddress (bool force = false)
+ {
+ if (m_live_sp.get() == nullptr)
+ return;
+
+ if (m_frozen_sp.get() == nullptr)
+ return;
+
+ if (force || (m_frozen_sp->GetLiveAddress() == LLDB_INVALID_ADDRESS))
+ m_frozen_sp->SetLiveAddress(m_live_sp->GetLiveAddress());
+ }
+
+ enum Flags
+ {
+ EVNone = 0,
+ EVIsLLDBAllocated = 1 << 0, ///< This variable is resident in a location specifically allocated for it by LLDB in the target process
+ EVIsProgramReference = 1 << 1, ///< This variable is a reference to a (possibly invalid) area managed by the target program
+ EVNeedsAllocation = 1 << 2, ///< Space for this variable has yet to be allocated in the target process
+ EVIsFreezeDried = 1 << 3, ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results)
+ EVNeedsFreezeDry = 1 << 4, ///< Copy from m_live_sp to m_frozen_sp during dematerialization
+ EVKeepInTarget = 1 << 5, ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it
+ EVTypeIsReference = 1 << 6, ///< The original type of this variable is a reference, so materialize the value rather than the location
+ EVUnknownType = 1 << 7, ///< This is a symbol of unknown type, and the type must be resolved after parsing is complete
+ EVBareRegister = 1 << 8 ///< This variable is a direct reference to $pc or some other entity.
+ };
+
+ typedef uint16_t FlagType;
+
+ FlagType m_flags; // takes elements of Flags
+
+ // these should be private
+ lldb::ValueObjectSP m_frozen_sp;
+ lldb::ValueObjectSP m_live_sp;
+ LLVMCastKind m_kind;
+};
+
+//----------------------------------------------------------------------
+/// @class ExpressionVariableList ExpressionVariable.h "lldb/Expression/ExpressionVariable.h"
+/// @brief A list of variable references.
+///
+/// This class stores variables internally, acting as the permanent store.
+//----------------------------------------------------------------------
+class ExpressionVariableList
+{
+public:
+ //----------------------------------------------------------------------
+ /// Implementation of methods in ExpressionVariableListBase
+ //----------------------------------------------------------------------
+ size_t
+ GetSize()
+ {
+ return m_variables.size();
+ }
+
+ lldb::ExpressionVariableSP
+ GetVariableAtIndex(size_t index)
+ {
+ lldb::ExpressionVariableSP var_sp;
+ if (index < m_variables.size())
+ var_sp = m_variables[index];
+ return var_sp;
+ }
+
+ size_t
+ AddVariable (const lldb::ExpressionVariableSP &var_sp)
+ {
+ m_variables.push_back(var_sp);
+ return m_variables.size() - 1;
+ }
+
+ lldb::ExpressionVariableSP
+ AddNewlyConstructedVariable (ExpressionVariable *var)
+ {
+ lldb::ExpressionVariableSP var_sp(var);
+ m_variables.push_back(var_sp);
+ return m_variables.back();
+ }
+
+ bool
+ ContainsVariable (const lldb::ExpressionVariableSP &var_sp)
+ {
+ const size_t size = m_variables.size();
+ for (size_t index = 0; index < size; ++index)
+ {
+ if (m_variables[index].get() == var_sp.get())
+ return true;
+ }
+ return false;
+ }
+
+ //----------------------------------------------------------------------
+ /// Finds a variable by name in the list.
+ ///
+ /// @param[in] name
+ /// The name of the requested variable.
+ ///
+ /// @return
+ /// The variable requested, or nullptr if that variable is not in the list.
+ //----------------------------------------------------------------------
+ lldb::ExpressionVariableSP
+ GetVariable (const ConstString &name)
+ {
+ lldb::ExpressionVariableSP var_sp;
+ for (size_t index = 0, size = GetSize(); index < size; ++index)
+ {
+ var_sp = GetVariableAtIndex(index);
+ if (var_sp->GetName() == name)
+ return var_sp;
+ }
+ var_sp.reset();
+ return var_sp;
+ }
+
+ lldb::ExpressionVariableSP
+ GetVariable (const char *name)
+ {
+ lldb::ExpressionVariableSP var_sp;
+ if (name && name[0])
+ {
+ for (size_t index = 0, size = GetSize(); index < size; ++index)
+ {
+ var_sp = GetVariableAtIndex(index);
+ const char *var_name_cstr = var_sp->GetName().GetCString();
+ if (!var_name_cstr || !name)
+ continue;
+ if (::strcmp (var_name_cstr, name) == 0)
+ return var_sp;
+ }
+ var_sp.reset();
+ }
+ return var_sp;
+ }
+
+ void
+ RemoveVariable (lldb::ExpressionVariableSP var_sp)
+ {
+ for (std::vector<lldb::ExpressionVariableSP>::iterator vi = m_variables.begin(), ve = m_variables.end();
+ vi != ve;
+ ++vi)
+ {
+ if (vi->get() == var_sp.get())
+ {
+ m_variables.erase(vi);
+ return;
+ }
+ }
+ }
+
+ void
+ Clear()
+ {
+ m_variables.clear();
+ }
+
+private:
+ std::vector <lldb::ExpressionVariableSP> m_variables;
+};
+
+class PersistentExpressionState : public ExpressionVariableList {
+public:
+ //----------------------------------------------------------------------
+ // See TypeSystem.h for how to add subclasses to this.
+ //----------------------------------------------------------------------
+ enum LLVMCastKind {
+ eKindClang,
+ eKindSwift,
+ eKindGo,
+ kNumKinds
+ };
+
+ LLVMCastKind getKind() const { return m_kind; }
+
+ PersistentExpressionState(LLVMCastKind kind) :
+ m_kind(kind)
+ {
+ }
+
+ virtual ~PersistentExpressionState();
+
+ virtual lldb::ExpressionVariableSP
+ CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) = 0;
+
+ virtual lldb::ExpressionVariableSP
+ CreatePersistentVariable (ExecutionContextScope *exe_scope,
+ const ConstString &name,
+ const CompilerType &type,
+ lldb::ByteOrder byte_order,
+ uint32_t addr_byte_size) = 0;
+
+ virtual ConstString
+ GetNextPersistentVariableName () = 0;
+
+ virtual void
+ RemovePersistentVariable (lldb::ExpressionVariableSP variable) = 0;
+
+ virtual lldb::addr_t
+ LookupSymbol (const ConstString &name) = 0;
+
+private:
+ LLVMCastKind m_kind;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ExpressionVariable_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangFunction.h b/contrib/llvm/tools/lldb/include/lldb/Expression/FunctionCaller.h
index cf7e259..c9a4581 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangFunction.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/FunctionCaller.h
@@ -1,4 +1,4 @@
-//===-- ClangFunction.h -----------------------------------------*- C++ -*-===//
+//===-- FunctionCaller.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,35 +7,32 @@
//
//===----------------------------------------------------------------------===//
-#ifndef lldb_ClangFunction_h_
-#define lldb_ClangFunction_h_
+#ifndef liblldb_FunctionCaller_h_
+#define liblldb_FunctionCaller_h_
// C Includes
// C++ Includes
-#include <vector>
#include <list>
+#include <memory>
+#include <string>
+#include <vector>
+
// Other libraries and framework includes
// Project includes
-#include "lldb/Core/ClangForward.h"
#include "lldb/Core/Address.h"
-#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Value.h"
-#include "lldb/Core/ValueObjectList.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Symbol/ClangASTType.h"
-#include "lldb/Target/Process.h"
+#include "lldb/Expression/Expression.h"
+#include "lldb/Expression/ExpressionParser.h"
+#include "lldb/Symbol/CompilerType.h"
namespace lldb_private
{
-class ASTStructExtractor;
-class ClangExpressionParser;
-
//----------------------------------------------------------------------
-/// @class ClangFunction ClangFunction.h "lldb/Expression/ClangFunction.h"
+/// @class FunctionCaller FunctionCaller.h "lldb/Expression/FunctionCaller.h"
/// @brief Encapsulates a function that can be called.
///
-/// A given ClangFunction object can handle a single function signature.
+/// A given FunctionCaller object can handle a single function signature.
/// Once constructed, it can set up any number of concurrent calls to
/// functions with that signature.
///
@@ -46,7 +43,7 @@ class ClangExpressionParser;
/// struct with the written arguments. This method lets Clang handle the
/// vagaries of function calling conventions.
///
-/// The simplest use of the ClangFunction is to construct it with a
+/// The simplest use of the FunctionCaller is to construct it with a
/// function representative of the signature you want to use, then call
/// ExecuteFunction(ExecutionContext &, Stream &, Value &).
///
@@ -61,12 +58,11 @@ class ClangExpressionParser;
/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated
/// and its address returned in that variable.
///
-/// Any of the methods that take arg_addr_ptr can be passed NULL, and the
+/// Any of the methods that take arg_addr_ptr can be passed nullptr, and the
/// argument space will be managed for you.
//----------------------------------------------------------------------
-class ClangFunction : public ClangExpression
+class FunctionCaller : public Expression
{
- friend class ASTStructExtractor;
public:
//------------------------------------------------------------------
/// Constructor
@@ -75,30 +71,6 @@ public:
/// An execution context scope that gets us at least a target and
/// process.
///
- /// @param[in] function_ptr
- /// The default function to be called. Can be overridden using
- /// WriteFunctionArguments().
- ///
- /// @param[in] ast_context
- /// The AST context to evaluate argument types in.
- ///
- /// @param[in] arg_value_list
- /// The default values to use when calling this function. Can
- /// be overridden using WriteFunctionArguments().
- //------------------------------------------------------------------
- ClangFunction (ExecutionContextScope &exe_scope,
- Function &function_ptr,
- ClangASTContext *ast_context,
- const ValueList &arg_value_list,
- const char *name);
-
- //------------------------------------------------------------------
- /// Constructor
- ///
- /// @param[in] exe_scope
- /// An execution context scope that gets us at least a target and
- /// process.
- ///
/// @param[in] ast_context
/// The AST context to evaluate argument types in.
///
@@ -113,8 +85,8 @@ public:
/// The default values to use when calling this function. Can
/// be overridden using WriteFunctionArguments().
//------------------------------------------------------------------
- ClangFunction (ExecutionContextScope &exe_scope,
- const ClangASTType &return_type,
+ FunctionCaller (ExecutionContextScope &exe_scope,
+ const CompilerType &return_type,
const Address& function_address,
const ValueList &arg_value_list,
const char *name);
@@ -122,8 +94,7 @@ public:
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- virtual
- ~ClangFunction();
+ ~FunctionCaller() override;
//------------------------------------------------------------------
/// Compile the wrapper function
@@ -134,8 +105,8 @@ public:
/// @return
/// The number of errors.
//------------------------------------------------------------------
- unsigned
- CompileFunction (Stream &errors);
+ virtual unsigned
+ CompileFunction (Stream &errors) = 0;
//------------------------------------------------------------------
/// Insert the default function wrapper and its default argument struct
@@ -209,10 +180,7 @@ public:
/// @param[in,out] args_addr_ref
/// The address of the structure to write the arguments into. May
/// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated
- /// and args_addr_ref is pointed to it.
- ///
- /// @param[in] function_address
- /// The address of the function to call.
+ /// and args_addr_ref is pointed at it.
///
/// @param[in] arg_values
/// The values of the function's arguments.
@@ -225,12 +193,11 @@ public:
//------------------------------------------------------------------
bool WriteFunctionArguments (ExecutionContext &exe_ctx,
lldb::addr_t &args_addr_ref,
- Address function_address,
- ValueList &arg_values,
+ ValueList &arg_values,
Stream &errors);
//------------------------------------------------------------------
- /// Run the function this ClangFunction was created with.
+ /// Run the function this FunctionCaller was created with.
///
/// This is the full version.
///
@@ -238,7 +205,7 @@ public:
/// The thread & process in which this function will run.
///
/// @param[in] args_addr_ptr
- /// If NULL, the function will take care of allocating & deallocating the wrapper
+ /// If nullptr, the function will take care of allocating & deallocating the wrapper
/// args structure. Otherwise, if set to LLDB_INVALID_ADDRESS, a new structure
/// will be allocated, filled and the address returned to you. You are responsible
/// for deallocating it. And if passed in with a value other than LLDB_INVALID_ADDRESS,
@@ -264,7 +231,7 @@ public:
Value &results);
//------------------------------------------------------------------
- /// Get a thread plan to run the function this ClangFunction was created with.
+ /// Get a thread plan to run the function this FunctionCaller was created with.
///
/// @param[in] exe_ctx
/// The execution context to insert the function and its arguments
@@ -335,7 +302,7 @@ public:
/// translation unit.
//------------------------------------------------------------------
const char *
- Text ()
+ Text() override
{
return m_wrapper_function_text.c_str();
}
@@ -346,48 +313,27 @@ public:
/// function.
//------------------------------------------------------------------
const char *
- FunctionName ()
+ FunctionName() override
{
return m_wrapper_function_name.c_str();
}
//------------------------------------------------------------------
- /// Return the object that the parser should use when resolving external
- /// values. May be NULL if everything should be self-contained.
- //------------------------------------------------------------------
- ClangExpressionDeclMap *
- DeclMap ()
- {
- return NULL;
- }
-
- //------------------------------------------------------------------
/// Return the object that the parser should use when registering
- /// local variables. May be NULL if the Expression doesn't care.
+ /// local variables. May be nullptr if the Expression doesn't care.
//------------------------------------------------------------------
- ClangExpressionVariableList *
+ ExpressionVariableList *
LocalVariables ()
{
- return NULL;
+ return nullptr;
}
//------------------------------------------------------------------
- /// Return the object that the parser should allow to access ASTs.
- /// May be NULL if the ASTs do not need to be transformed.
- ///
- /// @param[in] passthrough
- /// The ASTConsumer that the returned transformer should send
- /// the ASTs to after transformation.
- //------------------------------------------------------------------
- clang::ASTConsumer *
- ASTTransformer (clang::ASTConsumer *passthrough);
-
- //------------------------------------------------------------------
/// Return true if validation code should be inserted into the
/// expression.
//------------------------------------------------------------------
bool
- NeedsValidation ()
+ NeedsValidation() override
{
return false;
}
@@ -397,7 +343,7 @@ public:
/// resolved.
//------------------------------------------------------------------
bool
- NeedsVariableResolution ()
+ NeedsVariableResolution() override
{
return false;
}
@@ -407,29 +353,27 @@ public:
{
return m_arg_values;
}
-private:
- //------------------------------------------------------------------
- // For ClangFunction only
- //------------------------------------------------------------------
+protected:
// Note: the parser needs to be destructed before the execution unit, so
// declare the execution unit first.
std::shared_ptr<IRExecutionUnit> m_execution_unit_sp;
- std::unique_ptr<ClangExpressionParser> m_parser; ///< The parser responsible for compiling the function.
+ std::unique_ptr<ExpressionParser> m_parser; ///< The parser responsible for compiling the function.
+ ///< This will get made in CompileFunction, so it is
+ ///< safe to access it after that.
+
lldb::ModuleWP m_jit_module_wp;
std::string m_name; ///< The name of this clang function - for debugging purposes.
- Function *m_function_ptr; ///< The function we're going to call. May be NULL if we don't have debug info for the function.
+ Function *m_function_ptr; ///< The function we're going to call. May be nullptr if we don't have debug info for the function.
Address m_function_addr; ///< If we don't have the FunctionSP, we at least need the address & return type.
- ClangASTType m_function_return_type; ///< The opaque clang qual type for the function return type.
+ CompilerType m_function_return_type; ///< The opaque clang qual type for the function return type.
std::string m_wrapper_function_name; ///< The name of the wrapper function.
std::string m_wrapper_function_text; ///< The contents of the wrapper function.
std::string m_wrapper_struct_name; ///< The name of the struct that contains the target function address, arguments, and result.
std::list<lldb::addr_t> m_wrapper_args_addrs; ///< The addresses of the arguments to the wrapper function.
- std::unique_ptr<ASTStructExtractor> m_struct_extractor; ///< The class that generates the argument struct below.
-
bool m_struct_valid; ///< True if the ASTStructExtractor has populated the variables below.
//------------------------------------------------------------------
@@ -446,6 +390,6 @@ private:
bool m_JITted; ///< True if the wrapper function has already been JIT-compiled.
};
-} // Namespace lldb_private
+} // namespace lldb_private
-#endif // lldb_ClangFunction_h_
+#endif // liblldb_FunctionCaller_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/IRDynamicChecks.h b/contrib/llvm/tools/lldb/include/lldb/Expression/IRDynamicChecks.h
index 226f5c9..ef77d55 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/IRDynamicChecks.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/IRDynamicChecks.h
@@ -24,11 +24,10 @@ namespace llvm {
class Value;
}
-namespace lldb_private
+namespace lldb_private
{
class ClangExpressionDeclMap;
-class ClangUtilityFunction;
class ExecutionContext;
class Stream;
@@ -77,8 +76,8 @@ public:
bool DoCheckersExplainStop (lldb::addr_t addr, Stream &message);
- std::unique_ptr<ClangUtilityFunction> m_valid_pointer_check;
- std::unique_ptr<ClangUtilityFunction> m_objc_object_check;
+ std::unique_ptr<UtilityFunction> m_valid_pointer_check;
+ std::unique_ptr<UtilityFunction> m_objc_object_check;
};
//----------------------------------------------------------------------
@@ -114,7 +113,7 @@ public:
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- virtual ~IRDynamicChecks();
+ ~IRDynamicChecks() override;
//------------------------------------------------------------------
/// Run this IR transformer on a single module
@@ -127,18 +126,19 @@ public:
/// @return
/// True on success; false otherwise
//------------------------------------------------------------------
- bool runOnModule(llvm::Module &M);
+ bool runOnModule(llvm::Module &M) override;
//------------------------------------------------------------------
/// Interface stub
//------------------------------------------------------------------
void assignPassManager(llvm::PMStack &PMS,
- llvm::PassManagerType T = llvm::PMT_ModulePassManager);
+ llvm::PassManagerType T = llvm::PMT_ModulePassManager) override;
//------------------------------------------------------------------
/// Returns PMT_ModulePassManager
//------------------------------------------------------------------
- llvm::PassManagerType getPotentialPassManagerType() const;
+ llvm::PassManagerType getPotentialPassManagerType() const override;
+
private:
//------------------------------------------------------------------
/// A basic block-level pass to find all pointer dereferences and
@@ -164,6 +164,6 @@ private:
DynamicCheckerFunctions &m_checker_functions; ///< The checker functions for the process
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_IRDynamicChecks_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/IRExecutionUnit.h b/contrib/llvm/tools/lldb/include/lldb/Expression/IRExecutionUnit.h
index bd1a795..86744b7 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/IRExecutionUnit.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/IRExecutionUnit.h
@@ -7,27 +7,24 @@
//
//===----------------------------------------------------------------------===//
-#ifndef lldb_IRExecutionUnit_h_
-#define lldb_IRExecutionUnit_h_
+#ifndef liblldb_IRExecutionUnit_h_
+#define liblldb_IRExecutionUnit_h_
// C Includes
// C++ Includes
#include <atomic>
+#include <memory>
#include <string>
#include <vector>
-#include <map>
// Other libraries and framework includes
#include "llvm/IR/Module.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
// Project includes
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
-#include "lldb/Core/ClangForward.h"
#include "lldb/Core/DataBufferHeap.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangExpressionParser.h"
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -37,7 +34,7 @@ namespace llvm {
class Module;
class ExecutionEngine;
-}
+} // namespace llvm
namespace lldb_private {
@@ -79,7 +76,7 @@ public:
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- ~IRExecutionUnit();
+ ~IRExecutionUnit() override;
llvm::Module *
GetModule()
@@ -90,10 +87,7 @@ public:
llvm::Function *
GetFunction()
{
- if (m_module)
- return m_module->getFunction (m_name.AsCString());
- else
- return NULL;
+ return ((m_module != nullptr) ? m_module->getFunction(m_name.AsCString()) : nullptr);
}
void
@@ -118,22 +112,22 @@ public:
//------------------------------------------------------------------
/// ObjectFileJITDelegate overrides
//------------------------------------------------------------------
- virtual lldb::ByteOrder
- GetByteOrder () const;
+ lldb::ByteOrder
+ GetByteOrder() const override;
- virtual uint32_t
- GetAddressByteSize () const;
+ uint32_t
+ GetAddressByteSize() const override;
- virtual void
- PopulateSymtab (lldb_private::ObjectFile *obj_file,
- lldb_private::Symtab &symtab);
+ void
+ PopulateSymtab(lldb_private::ObjectFile *obj_file,
+ lldb_private::Symtab &symtab) override;
- virtual void
- PopulateSectionList (lldb_private::ObjectFile *obj_file,
- lldb_private::SectionList &section_list);
+ void
+ PopulateSectionList(lldb_private::ObjectFile *obj_file,
+ lldb_private::SectionList &section_list) override;
- virtual bool
- GetArchitecture (lldb_private::ArchSpec &arch);
+ bool
+ GetArchitecture(lldb_private::ArchSpec &arch) override;
lldb::ModuleSP
GetJITModule ();
@@ -215,7 +209,7 @@ private:
public:
MemoryManager (IRExecutionUnit &parent);
- virtual ~MemoryManager();
+ ~MemoryManager() override;
//------------------------------------------------------------------
/// Allocate space for executable code, and add it to the
@@ -233,9 +227,9 @@ private:
/// @return
/// Allocated space.
//------------------------------------------------------------------
- virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID,
- llvm::StringRef SectionName);
+ uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ llvm::StringRef SectionName) override;
//------------------------------------------------------------------
/// Allocate space for data, and add it to the m_spaceBlocks map
@@ -255,10 +249,10 @@ private:
/// @return
/// Allocated space.
//------------------------------------------------------------------
- virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID,
- llvm::StringRef SectionName,
- bool IsReadOnly);
+ uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ llvm::StringRef SectionName,
+ bool IsReadOnly) override;
//------------------------------------------------------------------
/// Called when object loading is complete and section page
@@ -270,7 +264,7 @@ private:
/// @return
/// True in case of failure, false in case of success.
//------------------------------------------------------------------
- virtual bool finalizeMemory(std::string *ErrMsg) {
+ bool finalizeMemory(std::string *ErrMsg) override {
// TODO: Ensure that the instruction cache is flushed because
// relocations are updated by dy-load. See:
// sys::Memory::InvalidateInstructionCache
@@ -278,17 +272,17 @@ private:
return false;
}
- virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
- return;
+ void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {
}
//------------------------------------------------------------------
/// Passthrough interface stub
//------------------------------------------------------------------
- virtual uint64_t getSymbolAddress(const std::string &Name);
+ uint64_t getSymbolAddress(const std::string &Name) override;
+
+ void *getPointerToNamedFunction(const std::string &Name,
+ bool AbortOnFailure = true) override;
- virtual void *getPointerToNamedFunction(const std::string &Name,
- bool AbortOnFailure = true);
private:
std::unique_ptr<SectionMemoryManager> m_default_mm_ap; ///< The memory allocator to use in actually creating space. All calls are passed through to it.
IRExecutionUnit &m_parent; ///< The execution unit this is a proxy for.
@@ -403,4 +397,4 @@ private:
} // namespace lldb_private
-#endif // lldb_IRExecutionUnit_h_
+#endif // liblldb_IRExecutionUnit_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/IRInterpreter.h b/contrib/llvm/tools/lldb/include/lldb/Expression/IRInterpreter.h
index c314bf1..4eb81bc 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/IRInterpreter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/IRInterpreter.h
@@ -13,7 +13,6 @@
#include "lldb/lldb-public.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Stream.h"
-#include "lldb/Symbol/TaggedASTType.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Pass.h"
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/IRMemoryMap.h b/contrib/llvm/tools/lldb/include/lldb/Expression/IRMemoryMap.h
index 80add46..6fb718a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/IRMemoryMap.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/IRMemoryMap.h
@@ -50,7 +50,12 @@ public:
eAllocationPolicyProcessOnly ///< The intent is that this allocation exist only in the process.
};
- lldb::addr_t Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error);
+ lldb::addr_t Malloc (size_t size,
+ uint8_t alignment,
+ uint32_t permissions,
+ AllocationPolicy policy,
+ bool zero_memory,
+ Error &error);
void Leak (lldb::addr_t process_address, Error &error);
void Free (lldb::addr_t process_address, Error &error);
@@ -124,7 +129,7 @@ private:
typedef std::map<lldb::addr_t, Allocation> AllocationMap;
AllocationMap m_allocations;
- lldb::addr_t FindSpace (size_t size);
+ lldb::addr_t FindSpace (size_t size, bool zero_memory = false);
bool ContainsHostOnlyAllocations ();
AllocationMap::iterator FindAllocation (lldb::addr_t addr, size_t size);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/IRToDWARF.h b/contrib/llvm/tools/lldb/include/lldb/Expression/IRToDWARF.h
deleted file mode 100644
index a4ae9b7..0000000
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/IRToDWARF.h
+++ /dev/null
@@ -1,111 +0,0 @@
-//===-- IRToDWARF.h ---------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_IRToDWARF_h_
-#define liblldb_IRToDWARF_h_
-
-#include "llvm/Pass.h"
-#include "llvm/IR/LegacyPassManager.h"
-
-#include "lldb/lldb-public.h"
-
-class Relocator;
-//----------------------------------------------------------------------
-/// @class IRToDWARF IRToDWARF.h "lldb/Expression/IRToDWARF.h"
-/// @brief Transforms the IR for a function into a DWARF location expression
-///
-/// Once an expression has been parsed and converted to IR, it can run
-/// in two contexts: interpreted by LLDB as a DWARF location expression,
-/// or compiled by the JIT and inserted into the target process for
-/// execution.
-///
-/// IRToDWARF makes the first possible, by traversing the control flow
-/// graph and writing the code for each basic block out as location
-/// expression bytecode. To ensure that the links between the basic blocks
-/// remain intact, it uses a relocator that records the location of every
-/// location expression instruction that has a relocatable operand, the
-/// target of that operand (as a basic block), and the mapping of each basic
-/// block to an actual location. After all code has been written out, the
-/// relocator post-processes it and performs all necessary relocations.
-//----------------------------------------------------------------------
-class IRToDWARF : public llvm::ModulePass
-{
-public:
- //------------------------------------------------------------------
- /// Constructor
- ///
- /// @param[in] local_vars
- /// A list of variables to populate with the local variables this
- /// expression uses.
- ///
- /// @param[in] decl_map
- /// The list of externally-referenced variables for the expression,
- /// for use in looking up globals.
- ///
- /// @param[in] stream
- /// The stream to dump DWARF bytecode onto.
- ///
- /// @param[in] func_name
- /// The name of the function to translate to DWARF.
- //------------------------------------------------------------------
- IRToDWARF(lldb_private::ClangExpressionVariableList &local_vars,
- lldb_private::ClangExpressionDeclMap *decl_map,
- lldb_private::StreamString &strm,
- const char* func_name = "$__lldb_expr");
-
- //------------------------------------------------------------------
- /// Destructor
- //------------------------------------------------------------------
- virtual ~IRToDWARF();
-
- //------------------------------------------------------------------
- /// Run this IR transformer on a single module
- ///
- /// @param[in] M
- /// The module to run on. This module is searched for the function
- /// $__lldb_expr, and that function is converted to a location
- /// expression.
- ///
- /// @return
- /// True on success; false otherwise
- //------------------------------------------------------------------
- bool runOnModule(llvm::Module &M);
-
- //------------------------------------------------------------------
- /// Interface stub
- //------------------------------------------------------------------
- void assignPassManager(llvm::PMStack &PMS,
- llvm::PassManagerType T = llvm::PMT_ModulePassManager);
-
- //------------------------------------------------------------------
- /// Returns PMT_ModulePassManager
- //------------------------------------------------------------------
- llvm::PassManagerType getPotentialPassManagerType() const;
-private:
- //------------------------------------------------------------------
- /// Run this IR transformer on a single basic block
- ///
- /// @param[in] BB
- /// The basic block to transform.
- ///
- /// @param[in] Relocator
- /// The relocator to use when registering branches.
- ///
- /// @return
- /// True on success; false otherwise
- //------------------------------------------------------------------
- bool runOnBasicBlock(llvm::BasicBlock &BB, Relocator &Relocator);
-
- std::string m_func_name; ///< The name of the function to translate
- lldb_private::ClangExpressionVariableList &m_local_vars; ///< The list of local variables to populate while transforming
- lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The list of external variables
- lldb_private::StreamString &m_strm; ///< The stream to write bytecode to
-};
-
-#endif
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/LLVMUserExpression.h b/contrib/llvm/tools/lldb/include/lldb/Expression/LLVMUserExpression.h
new file mode 100644
index 0000000..e3d1798
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/LLVMUserExpression.h
@@ -0,0 +1,118 @@
+//===-- LLVMUserExpression.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_LLVMUserExpression_h
+#define liblldb_LLVMUserExpression_h
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+#include <vector>
+
+// Project includes
+#include "lldb/Expression/UserExpression.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class LLVMUserExpression LLVMUserExpression.h "lldb/Expression/LLVMUserExpression.h"
+/// @brief Encapsulates a one-time expression for use in lldb.
+///
+/// LLDB uses expressions for various purposes, notably to call functions
+/// and as a backend for the expr command. LLVMUserExpression is a virtual base
+/// class that encapsulates the objects needed to parse and JIT an expression.
+/// The actual parsing part will be provided by the specific implementations
+/// of LLVMUserExpression - which will be vended through the appropriate TypeSystem.
+//----------------------------------------------------------------------
+class LLVMUserExpression : public UserExpression
+{
+ public:
+ LLVMUserExpression(ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type,
+ const EvaluateExpressionOptions &options);
+ ~LLVMUserExpression() override;
+
+ lldb::ExpressionResults Execute(Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions &options,
+ lldb::UserExpressionSP &shared_ptr_to_me,
+ lldb::ExpressionVariableSP &result) override;
+
+ bool FinalizeJITExecution(Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb::ExpressionVariableSP &result,
+ lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
+ lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override;
+
+ bool
+ CanInterpret() override
+ {
+ return m_can_interpret;
+ }
+
+ //------------------------------------------------------------------
+ /// Return the string that the parser should parse. Must be a full
+ /// translation unit.
+ //------------------------------------------------------------------
+ const char *
+ Text() override
+ {
+ return m_transformed_text.c_str();
+ }
+
+ lldb::ModuleSP GetJITModule() override;
+
+ protected:
+ virtual void ScanContext(ExecutionContext &exe_ctx, lldb_private::Error &err) = 0;
+
+ bool PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx, lldb::addr_t &struct_address);
+
+ virtual bool
+ AddArguments (ExecutionContext &exe_ctx,
+ std::vector<lldb::addr_t> &args,
+ lldb::addr_t struct_address,
+ Stream &error_stream) = 0;
+
+
+ lldb::addr_t m_stack_frame_bottom; ///< The bottom of the allocated stack frame.
+ lldb::addr_t m_stack_frame_top; ///< The top of the allocated stack frame.
+
+ bool m_allow_cxx; ///< True if the language allows C++.
+ bool m_allow_objc; ///< True if the language allows Objective-C.
+ std::string m_transformed_text; ///< The text of the expression, as send to the parser
+
+ std::shared_ptr<IRExecutionUnit> m_execution_unit_sp; ///< The execution unit the expression is stored in.
+ std::unique_ptr<Materializer> m_materializer_ap; ///< The materializer to use when running the expression.
+ lldb::ModuleWP m_jit_module_wp;
+ bool m_enforce_valid_object; ///< True if the expression parser should enforce the presence of a valid class pointer
+ ///in order to generate the expression as a method.
+ bool m_in_cplusplus_method; ///< True if the expression is compiled as a C++ member function (true if it was parsed
+ ///when exe_ctx was in a C++ method).
+ bool m_in_objectivec_method; ///< True if the expression is compiled as an Objective-C method (true if it was parsed
+ ///when exe_ctx was in an Objective-C method).
+ bool m_in_static_method; ///< True if the expression is compiled as a static (or class) method (currently true if it
+ ///was parsed when exe_ctx was in an Objective-C class method).
+ bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and passed in. False if the expression
+ ///doesn't really use them and they can be NULL.
+ bool m_const_object; ///< True if "this" is const.
+ Target *m_target; ///< The target for storing persistent data like types and variables.
+
+ bool m_can_interpret; ///< True if the expression could be evaluated statically; false otherwise.
+ lldb::addr_t
+ m_materialized_address; ///< The address at which the arguments to the expression have been materialized.
+ Materializer::DematerializerSP m_dematerializer_sp; ///< The dematerializer.
+};
+
+} // namespace lldb_private
+#endif
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/Materializer.h b/contrib/llvm/tools/lldb/include/lldb/Expression/Materializer.h
index 208a081..f293fdd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/Materializer.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/Materializer.h
@@ -7,18 +7,22 @@
//
//===----------------------------------------------------------------------===//
-#ifndef lldb_Materializer_h
-#define lldb_Materializer_h
+#ifndef liblldb_Materializer_h
+#define liblldb_Materializer_h
+// C Includes
+// C++ Includes
+#include <memory>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private-types.h"
#include "lldb/Core/Error.h"
#include "lldb/Expression/IRMemoryMap.h"
-#include "lldb/Host/Mutex.h"
-#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/TaggedASTType.h"
#include "lldb/Target/StackFrame.h"
-#include <vector>
-
namespace lldb_private
{
@@ -32,8 +36,8 @@ public:
{
public:
Dematerializer () :
- m_materializer(NULL),
- m_map(NULL),
+ m_materializer(nullptr),
+ m_map(nullptr),
m_process_address(LLDB_INVALID_ADDRESS)
{
}
@@ -44,7 +48,6 @@ public:
}
void Dematerialize (Error &err,
- lldb::ClangExpressionVariableSP &result_sp,
lldb::addr_t frame_top,
lldb::addr_t frame_bottom);
@@ -54,6 +57,7 @@ public:
{
return m_materializer && m_map && (m_process_address != LLDB_INVALID_ADDRESS);
}
+
private:
friend class Materializer;
@@ -84,11 +88,28 @@ public:
DematerializerSP Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err);
- uint32_t AddPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp, Error &err);
- uint32_t AddVariable (lldb::VariableSP &variable_sp, Error &err);
- uint32_t AddResultVariable (const TypeFromUser &type, bool is_lvalue, bool keep_in_memory, Error &err);
- uint32_t AddSymbol (const Symbol &symbol_sp, Error &err);
- uint32_t AddRegister (const RegisterInfo &register_info, Error &err);
+ class PersistentVariableDelegate
+ {
+ public:
+ virtual ~PersistentVariableDelegate();
+ virtual ConstString GetName() = 0;
+ virtual void DidDematerialize(lldb::ExpressionVariableSP &variable) = 0;
+ };
+
+ uint32_t AddPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp,
+ PersistentVariableDelegate *delegate,
+ Error &err);
+ uint32_t AddVariable (lldb::VariableSP &variable_sp,
+ Error &err);
+ uint32_t AddResultVariable (const CompilerType &type,
+ bool is_lvalue,
+ bool keep_in_memory,
+ PersistentVariableDelegate *delegate,
+ Error &err);
+ uint32_t AddSymbol (const Symbol &symbol_sp,
+ Error &err);
+ uint32_t AddRegister (const RegisterInfo &register_info,
+ Error &err);
uint32_t GetStructAlignment ()
{
@@ -100,14 +121,6 @@ public:
return m_current_offset;
}
- uint32_t GetResultOffset ()
- {
- if (m_result_entity)
- return m_result_entity->GetOffset();
- else
- return UINT32_MAX;
- }
-
class Entity
{
public:
@@ -117,11 +130,9 @@ public:
m_offset(0)
{
}
-
- virtual ~Entity ()
- {
- }
-
+
+ virtual ~Entity() = default;
+
virtual void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) = 0;
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address,
lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err) = 0;
@@ -147,8 +158,9 @@ public:
{
m_offset = offset;
}
+
protected:
- void SetSizeAndAlignmentFromType (ClangASTType &type);
+ void SetSizeAndAlignmentFromType (CompilerType &type);
uint32_t m_alignment;
uint32_t m_size;
@@ -163,11 +175,10 @@ private:
DematerializerWP m_dematerializer_wp;
EntityVector m_entities;
- Entity *m_result_entity;
uint32_t m_current_offset;
uint32_t m_struct_alignment;
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_Materializer_h
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/REPL.h b/contrib/llvm/tools/lldb/include/lldb/Expression/REPL.h
new file mode 100644
index 0000000..21d22de
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/REPL.h
@@ -0,0 +1,211 @@
+//===-- REPL.h --------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_REPL_h
+#define lldb_REPL_h
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/OptionGroupFormat.h"
+#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
+#include "lldb/../../source/Commands/CommandObjectExpression.h"
+
+namespace lldb_private
+{
+
+class REPL : public IOHandlerDelegate
+{
+public:
+ //----------------------------------------------------------------------
+ // See TypeSystem.h for how to add subclasses to this.
+ //----------------------------------------------------------------------
+ enum LLVMCastKind {
+ eKindClang,
+ eKindSwift,
+ eKindGo,
+ kNumKinds
+ };
+
+ LLVMCastKind getKind() const { return m_kind; }
+
+ REPL(LLVMCastKind kind, Target &target);
+
+ ~REPL() override;
+
+ //------------------------------------------------------------------
+ /// Get a REPL with an existing target (or, failing that, a debugger to use), and (optional) extra arguments for the compiler.
+ ///
+ /// @param[out] error
+ /// If this language is supported but the REPL couldn't be created, this error is populated with the reason.
+ ///
+ /// @param[in] language
+ /// The language to create a REPL for.
+ ///
+ /// @param[in] debugger
+ /// If provided, and target is nullptr, the debugger to use when setting up a top-level REPL.
+ ///
+ /// @param[in] target
+ /// If provided, the target to put the REPL inside.
+ ///
+ /// @param[in] repl_options
+ /// If provided, additional options for the compiler when parsing REPL expressions.
+ ///
+ /// @return
+ /// The range of the containing object in the target process.
+ //------------------------------------------------------------------
+ static lldb::REPLSP
+ Create (Error &Error, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options);
+
+ void
+ SetFormatOptions (const OptionGroupFormat &options)
+ {
+ m_format_options = options;
+ }
+
+ void
+ SetValueObjectDisplayOptions (const OptionGroupValueObjectDisplay &options)
+ {
+ m_varobj_options = options;
+ }
+
+ void
+ SetCommandOptions (const CommandObjectExpression::CommandOptions &options)
+ {
+ m_command_options = options;
+ }
+
+ void
+ SetCompilerOptions (const char *options)
+ {
+ if (options)
+ m_compiler_options = options;
+ }
+
+ lldb::IOHandlerSP
+ GetIOHandler ();
+
+ Error
+ RunLoop ();
+
+ //------------------------------------------------------------------
+ // IOHandler::Delegate functions
+ //------------------------------------------------------------------
+ void
+ IOHandlerActivated (IOHandler &io_handler) override;
+
+ bool
+ IOHandlerInterrupt (IOHandler &io_handler) override;
+
+ void
+ IOHandlerInputInterrupted (IOHandler &io_handler,
+ std::string &line) override;
+
+ const char *
+ IOHandlerGetFixIndentationCharacters () override;
+
+ ConstString
+ IOHandlerGetControlSequence (char ch) override;
+
+ const char *
+ IOHandlerGetCommandPrefix () override;
+
+ const char *
+ IOHandlerGetHelpPrologue () override;
+
+ bool
+ IOHandlerIsInputComplete (IOHandler &io_handler,
+ StringList &lines) override;
+
+ int
+ IOHandlerFixIndentation (IOHandler &io_handler,
+ const StringList &lines,
+ int cursor_position) override;
+
+ void
+ IOHandlerInputComplete (IOHandler &io_handler,
+ std::string &line) override;
+
+ int
+ IOHandlerComplete (IOHandler &io_handler,
+ const char *current_line,
+ const char *cursor,
+ const char *last_char,
+ int skip_first_n_matches,
+ int max_matches,
+ StringList &matches) override;
+
+protected:
+ static int
+ CalculateActualIndentation (const StringList &lines);
+
+ //----------------------------------------------------------------------
+ // Subclasses should override these functions to implement a functional REPL.
+ //----------------------------------------------------------------------
+
+ virtual Error
+ DoInitialization () = 0;
+
+ virtual ConstString
+ GetSourceFileBasename () = 0;
+
+ virtual const char *
+ GetAutoIndentCharacters () = 0;
+
+ virtual bool
+ SourceIsComplete (const std::string &source) = 0;
+
+ virtual lldb::offset_t
+ GetDesiredIndentation (const StringList &lines,
+ int cursor_position,
+ int tab_size) = 0; // LLDB_INVALID_OFFSET means no change
+
+ virtual lldb::LanguageType
+ GetLanguage () = 0;
+
+ virtual bool
+ PrintOneVariable (Debugger &debugger,
+ lldb::StreamFileSP &output_sp,
+ lldb::ValueObjectSP &valobj_sp,
+ ExpressionVariable *var = nullptr) = 0;
+
+ virtual int
+ CompleteCode(const std::string &current_code,
+ StringList &matches) = 0;
+
+ OptionGroupFormat m_format_options = OptionGroupFormat(lldb::eFormatDefault);
+ OptionGroupValueObjectDisplay m_varobj_options;
+ CommandObjectExpression::CommandOptions m_command_options;
+ std::string m_compiler_options;
+
+ bool m_enable_auto_indent = true;
+ std::string m_indent_str; // Use this string for each level of indentation
+ std::string m_current_indent_str;
+ uint32_t m_current_indent_level = 0;
+
+ std::string m_repl_source_path;
+ bool m_dedicated_repl_mode = false;
+
+ StringList m_code; // All accumulated REPL statements are saved here
+
+ Target &m_target;
+ lldb::IOHandlerSP m_io_handler_sp;
+ LLVMCastKind m_kind;
+
+private:
+ std::string
+ GetSourcePath();
+};
+
+} // namespace lldb_private
+
+#endif // lldb_REPL_h
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangUserExpression.h b/contrib/llvm/tools/lldb/include/lldb/Expression/UserExpression.h
index a549f5e..517dfcd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangUserExpression.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/UserExpression.h
@@ -1,4 +1,4 @@
-//===-- ClangUserExpression.h -----------------------------------*- C++ -*-===//
+//===-- UserExpression.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,46 +7,44 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_ClangUserExpression_h_
-#define liblldb_ClangUserExpression_h_
+#ifndef liblldb_UserExpression_h_
+#define liblldb_UserExpression_h_
// C Includes
// C++ Includes
+#include <memory>
#include <string>
-#include <map>
#include <vector>
// Other libraries and framework includes
// Project includes
-
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
#include "lldb/Core/Address.h"
-#include "lldb/Core/ClangForward.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
-#include "lldb/Expression/IRForTarget.h"
+#include "lldb/Expression/Expression.h"
#include "lldb/Expression/Materializer.h"
-#include "lldb/Symbol/TaggedASTType.h"
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
namespace lldb_private
{
//----------------------------------------------------------------------
-/// @class ClangUserExpression ClangUserExpression.h "lldb/Expression/ClangUserExpression.h"
-/// @brief Encapsulates a single expression for use with Clang
+/// @class UserExpression UserExpression.h "lldb/Expression/UserExpression.h"
+/// @brief Encapsulates a one-time expression for use in lldb.
///
/// LLDB uses expressions for various purposes, notably to call functions
-/// and as a backend for the expr command. ClangUserExpression encapsulates
-/// the objects needed to parse and interpret or JIT an expression. It
-/// uses the Clang parser to produce LLVM IR from the expression.
+/// and as a backend for the expr command. UserExpression is a virtual base
+/// class that encapsulates the objects needed to parse and interpret or
+/// JIT an expression. The actual parsing part will be provided by the specific
+/// implementations of UserExpression - which will be vended through the
+/// appropriate TypeSystem.
//----------------------------------------------------------------------
-class ClangUserExpression : public ClangExpression
+class UserExpression : public Expression
{
public:
-
enum { kDefaultTimeout = 500000u };
+
//------------------------------------------------------------------
/// Constructor
///
@@ -54,7 +52,7 @@ public:
/// The expression to parse.
///
/// @param[in] expr_prefix
- /// If non-NULL, a C string containing translation-unit level
+ /// If non-nullptr, a C string containing translation-unit level
/// definitions to be included when the expression is parsed.
///
/// @param[in] language
@@ -66,16 +64,17 @@ public:
/// If not eResultTypeAny, the type to use for the expression
/// result.
//------------------------------------------------------------------
- ClangUserExpression (const char *expr,
- const char *expr_prefix,
- lldb::LanguageType language,
- ResultType desired_type);
+ UserExpression (ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type,
+ const EvaluateExpressionOptions &options);
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- virtual
- ~ClangUserExpression ();
+ ~UserExpression() override;
//------------------------------------------------------------------
/// Parse the expression
@@ -98,18 +97,14 @@ public:
/// @return
/// True on success (no errors); false otherwise.
//------------------------------------------------------------------
- bool
+ virtual bool
Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory,
- bool generate_debug_info);
+ bool generate_debug_info) = 0;
- bool
- CanInterpret ()
- {
- return m_can_interpret;
- }
+ virtual bool CanInterpret() = 0;
bool
MatchesContext (ExecutionContext &exe_ctx);
@@ -128,9 +123,9 @@ public:
/// Expression evaluation options.
///
/// @param[in] shared_ptr_to_me
- /// This is a shared pointer to this ClangUserExpression. This is
+ /// This is a shared pointer to this UserExpression. This is
/// needed because Execute can push a thread plan that will hold onto
- /// the ClangUserExpression for an unbounded period of time. So you
+ /// the UserExpression for an unbounded period of time. So you
/// need to give the thread plan a reference to this object that can
/// keep it alive.
///
@@ -141,12 +136,10 @@ public:
/// @return
/// A Process::Execution results value.
//------------------------------------------------------------------
- lldb::ExpressionResults
- Execute (Stream &error_stream,
- ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions& options,
- lldb::ClangUserExpressionSP &shared_ptr_to_me,
- lldb::ClangExpressionVariableSP &result);
+ virtual lldb::ExpressionResults Execute(Stream &error_stream, ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions &options,
+ lldb::UserExpressionSP &shared_ptr_to_me,
+ lldb::ExpressionVariableSP &result) = 0;
//------------------------------------------------------------------
/// Apply the side effects of the function to program state.
@@ -171,21 +164,18 @@ public:
/// @return
/// A Process::Execution results value.
//------------------------------------------------------------------
- bool
- FinalizeJITExecution (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb::ClangExpressionVariableSP &result,
- lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
- lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS);
+ virtual bool FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx,
+ lldb::ExpressionVariableSP &result,
+ lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
+ lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) = 0;
//------------------------------------------------------------------
- /// Return the string that the parser should parse. Must be a full
- /// translation unit.
+ /// Return the string that the parser should parse.
//------------------------------------------------------------------
const char *
- Text ()
+ Text() override
{
- return m_transformed_text.c_str();
+ return m_expr_text.c_str();
}
//------------------------------------------------------------------
@@ -203,7 +193,7 @@ public:
/// function.
//------------------------------------------------------------------
const char *
- FunctionName ()
+ FunctionName() override
{
return "$__lldb_expr";
}
@@ -212,39 +202,18 @@ public:
/// Return the language that should be used when parsing. To use
/// the default, return eLanguageTypeUnknown.
//------------------------------------------------------------------
- virtual lldb::LanguageType
- Language ()
+ lldb::LanguageType
+ Language() override
{
return m_language;
}
//------------------------------------------------------------------
- /// Return the object that the parser should use when resolving external
- /// values. May be NULL if everything should be self-contained.
- //------------------------------------------------------------------
- ClangExpressionDeclMap *
- DeclMap ()
- {
- return m_expr_decl_map.get();
- }
-
- //------------------------------------------------------------------
- /// Return the object that the parser should allow to access ASTs.
- /// May be NULL if the ASTs do not need to be transformed.
- ///
- /// @param[in] passthrough
- /// The ASTConsumer that the returned transformer should send
- /// the ASTs to after transformation.
- //------------------------------------------------------------------
- clang::ASTConsumer *
- ASTTransformer (clang::ASTConsumer *passthrough);
-
- //------------------------------------------------------------------
/// Return the desired result type of the function, or
/// eResultTypeAny if indifferent.
//------------------------------------------------------------------
- virtual ResultType
- DesiredResultType ()
+ ResultType
+ DesiredResultType() override
{
return m_desired_type;
}
@@ -254,7 +223,7 @@ public:
/// expression.
//------------------------------------------------------------------
bool
- NeedsValidation ()
+ NeedsValidation() override
{
return true;
}
@@ -264,63 +233,87 @@ public:
/// resolved.
//------------------------------------------------------------------
bool
- NeedsVariableResolution ()
+ NeedsVariableResolution() override
{
return true;
}
+
+ EvaluateExpressionOptions *
+ GetOptions() override
+ {
+ return &m_options;
+ }
+
+ virtual lldb::ExpressionVariableSP
+ GetResultAfterDematerialization(ExecutionContextScope *exe_scope)
+ {
+ return lldb::ExpressionVariableSP();
+ }
+
+ virtual lldb::ModuleSP
+ GetJITModule()
+ {
+ return lldb::ModuleSP();
+ }
//------------------------------------------------------------------
- /// Evaluate one expression and return its result.
+ /// Evaluate one expression in the scratch context of the
+ /// target passed in the exe_ctx and return its result.
///
/// @param[in] exe_ctx
/// The execution context to use when evaluating the expression.
///
/// @param[in] options
- /// Expression evaluation options.
+ /// Expression evaluation options. N.B. The language in the
+ /// evaluation options will be used to determine the language used for
+ /// expression evaluation.
///
/// @param[in] expr_cstr
/// A C string containing the expression to be evaluated.
///
/// @param[in] expr_prefix
- /// If non-NULL, a C string containing translation-unit level
+ /// If non-nullptr, a C string containing translation-unit level
/// definitions to be included when the expression is parsed.
///
- /// @param[in/out] result_valobj_sp
+ /// @param[in,out] result_valobj_sp
/// If execution is successful, the result valobj is placed here.
///
- /// @param[out]
+ /// @param[out] error
/// Filled in with an error in case the expression evaluation
/// fails to parse, run, or evaluated.
///
+ /// @param[in] line_offset
+ /// The offset of the first line of the expression from the "beginning" of a virtual source file used for error reporting and debug info.
+ ///
+ /// @param[out] jit_module_sp_ptr
+ /// If non-nullptr, used to persist the generated IR module.
+ ///
/// @result
/// A Process::ExpressionResults value. eExpressionCompleted for success.
//------------------------------------------------------------------
static lldb::ExpressionResults
- Evaluate (ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions& options,
- const char *expr_cstr,
- const char *expr_prefix,
- lldb::ValueObjectSP &result_valobj_sp,
- Error &error);
+ Evaluate(ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions& options,
+ const char *expr_cstr,
+ const char *expr_prefix,
+ lldb::ValueObjectSP &result_valobj_sp,
+ Error &error,
+ uint32_t line_offset = 0,
+ lldb::ModuleSP *jit_module_sp_ptr = nullptr);
static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression.
-private:
+
+protected:
+ static lldb::addr_t
+ GetObjectPointer (lldb::StackFrameSP frame_sp,
+ ConstString &object_name,
+ Error &err);
+
//------------------------------------------------------------------
/// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment.
//------------------------------------------------------------------
void
- ScanContext (ExecutionContext &exe_ctx,
- lldb_private::Error &err);
-
- bool
- PrepareToExecuteJITExpression (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb::addr_t &struct_address,
- lldb::addr_t &object_ptr,
- lldb::addr_t &cmd_ptr);
-
- void
InstallContext (ExecutionContext &exe_ctx);
bool
@@ -329,37 +322,14 @@ private:
lldb::ProcessSP &process_sp,
lldb::StackFrameSP &frame_sp);
- lldb::ProcessWP m_process_wp; ///< The process used as the context for the expression.
Address m_address; ///< The address the process is stopped in.
- lldb::addr_t m_stack_frame_bottom; ///< The bottom of the allocated stack frame.
- lldb::addr_t m_stack_frame_top; ///< The top of the allocated stack frame.
-
std::string m_expr_text; ///< The text of the expression, as typed by the user
std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user
lldb::LanguageType m_language; ///< The language to use when parsing (eLanguageTypeUnknown means use defaults)
- bool m_allow_cxx; ///< True if the language allows C++.
- bool m_allow_objc; ///< True if the language allows Objective-C.
- std::string m_transformed_text; ///< The text of the expression, as send to the parser
ResultType m_desired_type; ///< The type to coerce the expression's result to. If eResultTypeAny, inferred from the expression.
-
- std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing the expression.
- std::shared_ptr<IRExecutionUnit> m_execution_unit_sp; ///< The execution unit the expression is stored in.
- std::unique_ptr<Materializer> m_materializer_ap; ///< The materializer to use when running the expression.
- std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer; ///< The result synthesizer, if one is needed.
- lldb::ModuleWP m_jit_module_wp;
- bool m_enforce_valid_object; ///< True if the expression parser should enforce the presence of a valid class pointer in order to generate the expression as a method.
- bool m_in_cplusplus_method; ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method).
- bool m_in_objectivec_method; ///< True if the expression is compiled as an Objective-C method (true if it was parsed when exe_ctx was in an Objective-C method).
- bool m_in_static_method; ///< True if the expression is compiled as a static (or class) method (currently true if it was parsed when exe_ctx was in an Objective-C class method).
- bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and passed in. False if the expression doesn't really use them and they can be NULL.
- bool m_const_object; ///< True if "this" is const.
- Target *m_target; ///< The target for storing persistent data like types and variables.
-
- bool m_can_interpret; ///< True if the expression could be evaluated statically; false otherwise.
- lldb::addr_t m_materialized_address; ///< The address at which the arguments to the expression have been materialized.
- Materializer::DematerializerSP m_dematerializer_sp; ///< The dematerializer.
+ EvaluateExpressionOptions m_options; ///< Additional options provided by the user.
};
} // namespace lldb_private
-#endif // liblldb_ClangUserExpression_h_
+#endif // liblldb_UserExpression_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangUtilityFunction.h b/contrib/llvm/tools/lldb/include/lldb/Expression/UtilityFunction.h
index bb5601f..bee83d8 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangUtilityFunction.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Expression/UtilityFunction.h
@@ -1,4 +1,4 @@
-//===-- ClangUtilityFunction.h ----------------------------------*- C++ -*-===//
+//===-- UtilityFunction.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,36 +7,33 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_ClangUtilityFunction_h_
-#define liblldb_ClangUtilityFunction_h_
+#ifndef liblldb_UtilityFunction_h_
+#define liblldb_UtilityFunction_h_
// C Includes
// C++ Includes
+#include <memory>
#include <string>
-#include <map>
-#include <vector>
// Other libraries and framework includes
// Project includes
-
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
-#include "lldb/Core/ClangForward.h"
-#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/Expression.h"
namespace lldb_private
{
//----------------------------------------------------------------------
-/// @class ClangUtilityFunction ClangUtilityFunction.h "lldb/Expression/ClangUtilityFunction.h"
-/// @brief Encapsulates a single expression for use with Clang
+/// @class UtilityFunction UtilityFunction.h "lldb/Expression/UtilityFunction.h"
+/// @brief Encapsulates a bit of source code that provides a function that is callable
///
/// LLDB uses expressions for various purposes, notably to call functions
-/// and as a backend for the expr command. ClangUtilityFunction encapsulates
+/// and as a backend for the expr command. UtilityFunction encapsulates
/// a self-contained function meant to be used from other code. Utility
/// functions can perform error-checking for ClangUserExpressions,
//----------------------------------------------------------------------
-class ClangUtilityFunction : public ClangExpression
+class UtilityFunction : public Expression
{
public:
//------------------------------------------------------------------
@@ -48,11 +45,11 @@ public:
/// @param[in] name
/// The name of the function, as used in the text.
//------------------------------------------------------------------
- ClangUtilityFunction (const char *text,
- const char *name);
+ UtilityFunction (ExecutionContextScope &exe_scope,
+ const char *text,
+ const char *name);
- virtual
- ~ClangUtilityFunction ();
+ ~UtilityFunction() override;
//------------------------------------------------------------------
/// Install the utility function into a process
@@ -66,13 +63,13 @@ public:
/// @return
/// True on success (no errors); false otherwise.
//------------------------------------------------------------------
- bool
- Install (Stream &error_stream, ExecutionContext &exe_ctx);
+ virtual bool
+ Install (Stream &error_stream, ExecutionContext &exe_ctx) = 0;
//------------------------------------------------------------------
/// Check whether the given PC is inside the function
///
- /// Especially useful if the function dereferences NULL to indicate a failed
+ /// Especially useful if the function dereferences nullptr to indicate a failed
/// assert.
///
/// @param[in] pc
@@ -89,14 +86,13 @@ public:
// so this always returns false if the function is not JIT compiled yet
return (address >= m_jit_start_addr && address < m_jit_end_addr);
}
-
-
+
//------------------------------------------------------------------
/// Return the string that the parser should parse. Must be a full
/// translation unit.
//------------------------------------------------------------------
const char *
- Text ()
+ Text() override
{
return m_function_text.c_str();
}
@@ -107,43 +103,19 @@ public:
/// function.
//------------------------------------------------------------------
const char *
- FunctionName ()
+ FunctionName() override
{
return m_function_name.c_str();
}
//------------------------------------------------------------------
- /// Return the object that the parser should use when resolving external
- /// values. May be NULL if everything should be self-contained.
- //------------------------------------------------------------------
- ClangExpressionDeclMap *
- DeclMap ()
- {
- return m_expr_decl_map.get();
- }
-
- //------------------------------------------------------------------
/// Return the object that the parser should use when registering
- /// local variables. May be NULL if the Expression doesn't care.
+ /// local variables. May be nullptr if the Expression doesn't care.
//------------------------------------------------------------------
- ClangExpressionVariableList *
+ ExpressionVariableList *
LocalVariables ()
{
- return NULL;
- }
-
- //------------------------------------------------------------------
- /// Return the object that the parser should allow to access ASTs.
- /// May be NULL if the ASTs do not need to be transformed.
- ///
- /// @param[in] passthrough
- /// The ASTConsumer that the returned transformer should send
- /// the ASTs to after transformation.
- //------------------------------------------------------------------
- clang::ASTConsumer *
- ASTTransformer (clang::ASTConsumer *passthrough)
- {
- return NULL;
+ return nullptr;
}
//------------------------------------------------------------------
@@ -151,7 +123,7 @@ public:
/// expression.
//------------------------------------------------------------------
bool
- NeedsValidation ()
+ NeedsValidation() override
{
return false;
}
@@ -161,19 +133,30 @@ public:
/// resolved.
//------------------------------------------------------------------
bool
- NeedsVariableResolution ()
+ NeedsVariableResolution() override
{
return false;
}
-private:
- std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression.
+ // This makes the function caller function.
+ FunctionCaller *
+ MakeFunctionCaller(const CompilerType &return_type, const ValueList &arg_value_list, Error &error);
+
+ // This one retrieves the function caller that is already made. If you haven't made it yet, this returns nullptr
+ FunctionCaller *
+ GetFunctionCaller()
+ {
+ return m_caller_up.get();
+ }
+
+protected:
std::shared_ptr<IRExecutionUnit> m_execution_unit_sp;
lldb::ModuleWP m_jit_module_wp;
std::string m_function_text; ///< The text of the function. Must be a well-formed translation unit.
std::string m_function_name; ///< The name of the function.
+ std::unique_ptr<FunctionCaller> m_caller_up;
};
} // namespace lldb_private
-#endif // liblldb_ClangUtilityFunction_h_
+#endif // liblldb_UtilityFunction_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Condition.h b/contrib/llvm/tools/lldb/include/lldb/Host/Condition.h
index 7431315c..bd793c6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Condition.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Condition.h
@@ -7,11 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_DBCondition_h_
-#define liblldb_DBCondition_h_
-#if defined(__cplusplus)
-
+#ifndef liblldb_Condition_h_
+#define liblldb_Condition_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-types.h"
#include "lldb/Host/Mutex.h"
@@ -31,7 +33,6 @@ class TimeValue;
class Condition
{
public:
-
//------------------------------------------------------------------
/// Default constructor
///
@@ -73,9 +74,9 @@ public:
/// \a mutex. The waiting thread unblocks only after another thread
/// signals or broadcasts this object's condition variable.
///
- /// If \a abstime is non-NULL, this function will return when the
+ /// If \a abstime is non-nullptr, this function will return when the
/// system time reaches the time specified in \a abstime if the
- /// condition variable doesn't get unblocked. If \a abstime is NULL
+ /// condition variable doesn't get unblocked. If \a abstime is nullptr
/// this function will wait for an infinite amount of time for the
/// condition variable to be unblocked.
///
@@ -87,19 +88,19 @@ public:
/// \c pthread_cond_wait() calls.
///
/// @param[in] abstime
- /// An absolute time at which to stop waiting if non-NULL, else
+ /// An absolute time at which to stop waiting if non-nullptr, else
/// wait an infinite amount of time for the condition variable
/// toget signaled.
///
/// @param[out] timed_out
- /// If not NULL, will be set to true if the wait timed out, and
+ /// If not nullptr, will be set to true if the wait timed out, and
// false otherwise.
///
/// @see Condition::Broadcast()
/// @see Condition::Signal()
//------------------------------------------------------------------
int
- Wait (Mutex &mutex, const TimeValue *abstime = NULL, bool *timed_out = NULL);
+ Wait(Mutex &mutex, const TimeValue *abstime = nullptr, bool *timed_out = nullptr);
protected:
//------------------------------------------------------------------
@@ -119,6 +120,4 @@ protected:
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif
-
+#endif // liblldb_Condition_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Config.h b/contrib/llvm/tools/lldb/include/lldb/Host/Config.h
index 7872eb9..f70f4de 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Config.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Config.h
@@ -22,10 +22,14 @@
#include "lldb/Host/linux/Config.h"
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
#include "lldb/Host/freebsd/Config.h"
+#elif defined(__NetBSD__)
+
+#include "lldb/Host/netbsd/Config.h"
+
#elif defined(__MINGW__) || defined (__MINGW32__)
#include "lldb/Host/mingw/Config.h"
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Debug.h b/contrib/llvm/tools/lldb/include/lldb/Host/Debug.h
index 87dffb9..7954ee0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Debug.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Debug.h
@@ -10,7 +10,12 @@
#ifndef liblldb_Debug_h_
#define liblldb_Debug_h_
+// C Includes
+// C++ Includes
#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
namespace lldb_private {
@@ -59,9 +64,7 @@ namespace lldb_private {
}
}
- ~ResumeActionList()
- {
- }
+ ~ResumeActionList() = default;
bool
IsEmpty() const
@@ -114,7 +117,7 @@ namespace lldb_private {
}
if (default_ok && tid != LLDB_INVALID_THREAD_ID)
return GetActionForThread (LLDB_INVALID_THREAD_ID, false);
- return NULL;
+ return nullptr;
}
size_t
@@ -133,7 +136,7 @@ namespace lldb_private {
bool
SetDefaultThreadActionIfNeeded (lldb::StateType action, int signal)
{
- if (GetActionForThread (LLDB_INVALID_THREAD_ID, true) == NULL)
+ if (GetActionForThread (LLDB_INVALID_THREAD_ID, true) == nullptr)
{
// There isn't a default action so we do need to set it.
ResumeAction default_action = {LLDB_INVALID_THREAD_ID, action, signal };
@@ -203,4 +206,5 @@ namespace lldb_private {
} details;
};
}
-#endif // #ifndef liblldb_Debug_h_
+
+#endif // liblldb_Debug_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Endian.h b/contrib/llvm/tools/lldb/include/lldb/Host/Endian.h
index 1ae3c40..df0796b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Endian.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Endian.h
@@ -12,7 +12,7 @@
#include "lldb/lldb-enumerations.h"
-namespace lldb {
+namespace lldb_private {
namespace endian {
@@ -22,7 +22,7 @@ namespace endian {
uint8_t bytes[sizeof(uint32_t)];
} const endianTest = { 0x01020304 };
- inline ByteOrder InlHostByteOrder() { return (ByteOrder)endianTest.bytes[0]; }
+ inline lldb::ByteOrder InlHostByteOrder() { return (lldb::ByteOrder)endianTest.bytes[0]; }
// ByteOrder const InlHostByteOrder = (ByteOrder)endianTest.bytes[0];
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/File.h b/contrib/llvm/tools/lldb/include/lldb/Host/File.h
index 5747cb5..27f3f40 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/File.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/File.h
@@ -9,12 +9,15 @@
#ifndef liblldb_File_h_
#define liblldb_File_h_
-#if defined(__cplusplus)
+// C Includes
+// C++ Includes
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Host/IOObject.h"
@@ -73,13 +76,11 @@ public:
File (const File &rhs);
- File &
- operator= (const File &rhs);
//------------------------------------------------------------------
/// Constructor with path.
///
/// Takes a path to a file which can be just a filename, or a full
- /// path. If \a path is not NULL or empty, this function will call
+ /// path. If \a path is not nullptr or empty, this function will call
/// File::Open (const char *path, uint32_t options, uint32_t permissions).
///
/// @param[in] path
@@ -101,10 +102,10 @@ public:
/// Constructor with FileSpec.
///
/// Takes a FileSpec pointing to a file which can be just a filename, or a full
- /// path. If \a path is not NULL or empty, this function will call
+ /// path. If \a path is not nullptr or empty, this function will call
/// File::Open (const char *path, uint32_t options, uint32_t permissions).
///
- /// @param[in] path
+ /// @param[in] filespec
/// The FileSpec for this file.
///
/// @param[in] options
@@ -124,7 +125,9 @@ public:
m_descriptor (fd),
m_stream (kInvalidStream),
m_options (0),
- m_own_stream (false)
+ m_own_stream (false),
+ m_is_interactive (eLazyBoolCalculate),
+ m_is_real_terminal (eLazyBoolCalculate)
{
}
@@ -133,11 +136,13 @@ public:
///
/// The destructor is virtual in case this class is subclassed.
//------------------------------------------------------------------
- virtual
- ~File ();
+ ~File() override;
+
+ File &
+ operator= (const File &rhs);
bool
- IsValid () const
+ IsValid() const override
{
return DescriptorIsValid() || StreamIsValid();
}
@@ -156,7 +161,7 @@ public:
///
/// @return
/// A pointer to this object if either the directory or filename
- /// is valid, NULL otherwise.
+ /// is valid, nullptr otherwise.
//------------------------------------------------------------------
operator
bool () const
@@ -216,7 +221,7 @@ public:
uint32_t permissions = lldb::eFilePermissionsFileDefault);
Error
- Close ();
+ Close() override;
Error
Duplicate (const File &rhs);
@@ -225,8 +230,7 @@ public:
GetDescriptor() const;
WaitableHandle
- GetWaitableHandle();
-
+ GetWaitableHandle() override;
void
SetDescriptor(int fd, bool transfer_ownership);
@@ -247,7 +251,7 @@ public:
/// @param[in] buf
/// A buffer where to put the bytes that are read.
///
- /// @param[in/out] num_bytes
+ /// @param[in,out] num_bytes
/// The number of bytes to read form the current file position
/// which gets modified with the number of bytes that were read.
///
@@ -256,7 +260,7 @@ public:
/// failure.
//------------------------------------------------------------------
Error
- Read (void *buf, size_t &num_bytes);
+ Read(void *buf, size_t &num_bytes) override;
//------------------------------------------------------------------
/// Write bytes to a file at the current file position.
@@ -268,7 +272,7 @@ public:
/// @param[in] buf
/// A buffer where to put the bytes that are read.
///
- /// @param[in/out] num_bytes
+ /// @param[in,out] num_bytes
/// The number of bytes to write to the current file position
/// which gets modified with the number of bytes that were
/// written.
@@ -278,7 +282,7 @@ public:
/// failure.
//------------------------------------------------------------------
Error
- Write (const void *buf, size_t &num_bytes);
+ Write(const void *buf, size_t &num_bytes) override;
//------------------------------------------------------------------
/// Seek to an offset relative to the beginning of the file.
@@ -295,13 +299,13 @@ public:
///
/// @param[in] error_ptr
/// A pointer to a lldb_private::Error object that will be
- /// filled in if non-NULL.
+ /// filled in if non-nullptr.
///
/// @return
/// The resulting seek offset, or -1 on error.
//------------------------------------------------------------------
off_t
- SeekFromStart (off_t offset, Error *error_ptr = NULL);
+ SeekFromStart(off_t offset, Error *error_ptr = nullptr);
//------------------------------------------------------------------
/// Seek to an offset relative to the current file position.
@@ -318,13 +322,13 @@ public:
///
/// @param[in] error_ptr
/// A pointer to a lldb_private::Error object that will be
- /// filled in if non-NULL.
+ /// filled in if non-nullptr.
///
/// @return
/// The resulting seek offset, or -1 on error.
//------------------------------------------------------------------
off_t
- SeekFromCurrent (off_t offset, Error *error_ptr = NULL);
+ SeekFromCurrent(off_t offset, Error *error_ptr = nullptr);
//------------------------------------------------------------------
/// Seek to an offset relative to the end of the file.
@@ -335,20 +339,20 @@ public:
/// @see File::Read (void *, size_t, off_t &)
/// @see File::Write (const void *, size_t, off_t &)
///
- /// @param[in/out] offset
+ /// @param[in,out] offset
/// The offset to seek to within the file relative to the
/// end of the file which gets filled in with the resulting
/// absolute file offset.
///
/// @param[in] error_ptr
/// A pointer to a lldb_private::Error object that will be
- /// filled in if non-NULL.
+ /// filled in if non-nullptr.
///
/// @return
/// The resulting seek offset, or -1 on error.
//------------------------------------------------------------------
off_t
- SeekFromEnd (off_t offset, Error *error_ptr = NULL);
+ SeekFromEnd(off_t offset, Error *error_ptr = nullptr);
//------------------------------------------------------------------
/// Read bytes from a file from the specified file offset.
@@ -357,14 +361,14 @@ public:
/// own file position markers and reads on other threads won't mess
/// up the current read.
///
- /// @param[in] buf
+ /// @param[in] dst
/// A buffer where to put the bytes that are read.
///
- /// @param[in/out] num_bytes
+ /// @param[in,out] num_bytes
/// The number of bytes to read form the current file position
/// which gets modified with the number of bytes that were read.
///
- /// @param[in/out] offset
+ /// @param[in,out] offset
/// The offset within the file from which to read \a num_bytes
/// bytes. This offset gets incremented by the number of bytes
/// that were read.
@@ -383,11 +387,11 @@ public:
/// own file position markers and reads on other threads won't mess
/// up the current read.
///
- /// @param[in/out] num_bytes
+ /// @param[in,out] num_bytes
/// The number of bytes to read form the current file position
/// which gets modified with the number of bytes that were read.
///
- /// @param[in/out] offset
+ /// @param[in,out] offset
/// The offset within the file from which to read \a num_bytes
/// bytes. This offset gets incremented by the number of bytes
/// that were read.
@@ -419,15 +423,15 @@ public:
/// their own locking externally to avoid multiple people writing
/// to the file at the same time.
///
- /// @param[in] buf
+ /// @param[in] src
/// A buffer containing the bytes to write.
///
- /// @param[in/out] num_bytes
+ /// @param[in,out] num_bytes
/// The number of bytes to write to the file at offset \a offset.
/// \a num_bytes gets modified with the number of bytes that
/// were read.
///
- /// @param[in/out] offset
+ /// @param[in,out] offset
/// The offset within the file at which to write \a num_bytes
/// bytes. This offset gets incremented by the number of bytes
/// that were written.
@@ -472,7 +476,6 @@ public:
static uint32_t
GetPermissions(const FileSpec &file_spec, Error &error);
-
//------------------------------------------------------------------
/// Return true if this file is interactive.
///
@@ -497,6 +500,9 @@ public:
//------------------------------------------------------------------
bool
GetIsRealTerminal ();
+
+ bool
+ GetIsTerminalWithColors ();
//------------------------------------------------------------------
/// Output printf formatted output to the stream.
@@ -516,15 +522,13 @@ public:
size_t
PrintfVarArg(const char *format, va_list args);
-
void
SetOptions (uint32_t options)
{
m_options = options;
}
+
protected:
-
-
bool
DescriptorIsValid () const
{
@@ -549,9 +553,9 @@ protected:
bool m_own_stream;
LazyBool m_is_interactive;
LazyBool m_is_real_terminal;
+ LazyBool m_supports_colors;
};
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif // liblldb_File_h_
+#endif // liblldb_File_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/FileSpec.h b/contrib/llvm/tools/lldb/include/lldb/Host/FileSpec.h
index d0338d4..0ff1bc9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/FileSpec.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/FileSpec.h
@@ -9,10 +9,14 @@
#ifndef liblldb_FileSpec_h_
#define liblldb_FileSpec_h_
-#if defined(__cplusplus)
+// C Includes
+// C++ Includes
#include <functional>
+#include <string>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/STLUtils.h"
@@ -66,14 +70,14 @@ public:
/// Constructor with path.
///
/// Takes a path to a file which can be just a filename, or a full
- /// path. If \a path is not NULL or empty, this function will call
+ /// path. If \a path is not nullptr or empty, this function will call
/// FileSpec::SetFile (const char *path, bool resolve).
///
/// @param[in] path
/// The full or partial path to a file.
///
/// @param[in] resolve_path
- /// If \b true, then we resolve the path with realpath,
+ /// If \b true, then we resolve the path, removing stray ../.. and so forth,
/// if \b false we trust the path is in canonical form already.
///
/// @see FileSpec::SetFile (const char *path, bool resolve)
@@ -101,10 +105,10 @@ public:
/// Copy constructor
///
/// Makes a copy of the uniqued directory and filename strings from
- /// \a rhs if it is not NULL.
+ /// \a rhs if it is not nullptr.
///
/// @param[in] rhs
- /// A const FileSpec object pointer to copy if non-NULL.
+ /// A const FileSpec object pointer to copy if non-nullptr.
//------------------------------------------------------------------
FileSpec (const FileSpec* rhs);
@@ -190,7 +194,7 @@ public:
///
/// @return
/// A pointer to this object if either the directory or filename
- /// is valid, NULL otherwise.
+ /// is valid, nullptr otherwise.
//------------------------------------------------------------------
explicit operator bool() const;
@@ -444,7 +448,7 @@ public:
///
/// Returns a ConstString that represents the extension of the filename
/// for this FileSpec object. If this object does not represent a file,
- /// or the filename has no extension, ConstString(NULL) is returned.
+ /// or the filename has no extension, ConstString(nullptr) is returned.
/// The dot ('.') character is not returned as part of the extension
///
/// @return
@@ -510,10 +514,7 @@ public:
}
bool
- IsSymbolicLink () const
- {
- return GetFileType() == FileSpec::eFileTypeSymbolicLink;
- }
+ IsSymbolicLink () const;
//------------------------------------------------------------------
/// Get the memory cost of this object.
@@ -555,13 +556,12 @@ public:
///
/// @return
/// A shared pointer to the memory mapped data. This shared
- /// pointer can contain a NULL DataBuffer pointer, so the contained
+ /// pointer can contain a nullptr DataBuffer pointer, so the contained
/// pointer must be checked prior to using it.
//------------------------------------------------------------------
lldb::DataBufferSP
MemoryMapFileContents (off_t offset = 0, size_t length = SIZE_MAX) const;
-
//------------------------------------------------------------------
/// Memory map part of, or the entire contents of, a file only if
/// the file is local (not on a network mount).
@@ -594,7 +594,7 @@ public:
///
/// @return
/// A shared pointer to the memory mapped data. This shared
- /// pointer can contain a NULL DataBuffer pointer, so the contained
+ /// pointer can contain a nullptr DataBuffer pointer, so the contained
/// pointer must be checked prior to using it.
//------------------------------------------------------------------
lldb::DataBufferSP
@@ -624,16 +624,15 @@ public:
///
/// @return
/// A shared pointer to the memory mapped data. This shared
- /// pointer can contain a NULL DataBuffer pointer, so the contained
+ /// pointer can contain a nullptr DataBuffer pointer, so the contained
/// pointer must be checked prior to using it.
//------------------------------------------------------------------
lldb::DataBufferSP
- ReadFileContents (off_t offset = 0, size_t length = SIZE_MAX, Error *error_ptr = NULL) const;
+ ReadFileContents(off_t offset = 0, size_t length = SIZE_MAX, Error *error_ptr = nullptr) const;
size_t
ReadFileContents (off_t file_offset, void *dst, size_t dst_len, Error *error_ptr) const;
-
//------------------------------------------------------------------
/// Read the entire contents of a file as data that can be used
/// as a C string.
@@ -643,11 +642,11 @@ public:
///
/// @return
/// A shared pointer to the data. This shared pointer can
- /// contain a NULL DataBuffer pointer, so the contained pointer
+ /// contain a nullptr DataBuffer pointer, so the contained pointer
/// must be checked prior to using it.
//------------------------------------------------------------------
lldb::DataBufferSP
- ReadFileContentsAsCString(Error *error_ptr = NULL);
+ ReadFileContentsAsCString(Error *error_ptr = nullptr);
//------------------------------------------------------------------
/// Normalize a pathname by collapsing redundant separators and
@@ -719,6 +718,7 @@ public:
{
m_is_resolved = is_resolved;
}
+
//------------------------------------------------------------------
/// Read the file into an array of strings, one per line.
///
@@ -835,5 +835,4 @@ Stream& operator << (Stream& s, const FileSpec& f);
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif // liblldb_FileSpec_h_
+#endif // liblldb_FileSpec_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/FileSystem.h b/contrib/llvm/tools/lldb/include/lldb/Host/FileSystem.h
index bea1ec8..465ad45 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/FileSystem.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/FileSystem.h
@@ -22,6 +22,8 @@ namespace lldb_private
class FileSystem
{
public:
+ static const char *DEV_NULL;
+
static FileSpec::PathSyntax GetNativePathSyntax();
static Error MakeDirectory(const FileSpec &file_spec, uint32_t mode);
@@ -35,9 +37,12 @@ class FileSystem
static bool GetFileExists(const FileSpec &file_spec);
static Error Hardlink(const FileSpec &src, const FileSpec &dst);
+ static int GetHardlinkCount(const FileSpec &file_spec);
static Error Symlink(const FileSpec &src, const FileSpec &dst);
static Error Readlink(const FileSpec &src, FileSpec &dst);
static Error Unlink(const FileSpec &file_spec);
+
+ static Error ResolveSymbolicLink(const FileSpec &src, FileSpec &dst);
static bool CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high);
static bool CalculateMD5(const FileSpec &file_spec,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/HostGetOpt.h b/contrib/llvm/tools/lldb/include/lldb/Host/HostGetOpt.h
index 761c1a1..6f51291 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/HostGetOpt.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/HostGetOpt.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#pragma once
-#ifndef _MSC_VER
+#if !defined(_MSC_VER) && !defined(__NetBSD__)
#ifdef _WIN32
#define _BSD_SOURCE // Required so that getopt.h defines optreset
@@ -19,6 +19,6 @@
#else
-#include <lldb/Host/windows/getopt/GetOptInc.h>
+#include <lldb/Host/common/GetOptInc.h>
#endif
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/HostInfo.h b/contrib/llvm/tools/lldb/include/lldb/Host/HostInfo.h
index 6bb0099..9609438 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/HostInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/HostInfo.h
@@ -48,6 +48,9 @@
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include "lldb/Host/freebsd/HostInfoFreeBSD.h"
#define HOST_INFO_TYPE HostInfoFreeBSD
+#elif defined(__NetBSD__)
+#include "lldb/Host/netbsd/HostInfoNetBSD.h"
+#define HOST_INFO_TYPE HostInfoNetBSD
#elif defined(__APPLE__)
#include "lldb/Host/macosx/HostInfoMacOSX.h"
#define HOST_INFO_TYPE HostInfoMacOSX
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/HostNativeThread.h b/contrib/llvm/tools/lldb/include/lldb/Host/HostNativeThread.h
index f39c775..b0411ca 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/HostNativeThread.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/HostNativeThread.h
@@ -18,6 +18,8 @@
#include "lldb/Host/linux/HostThreadLinux.h"
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include "lldb/Host/freebsd/HostThreadFreeBSD.h"
+#elif defined(__NetBSD__)
+#include "lldb/Host/netbsd/HostThreadNetBSD.h"
#elif defined(__APPLE__)
#include "lldb/Host/macosx/HostThreadMacOSX.h"
#endif
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/HostNativeThreadForward.h b/contrib/llvm/tools/lldb/include/lldb/Host/HostNativeThreadForward.h
index e6bd426..520031a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/HostNativeThreadForward.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/HostNativeThreadForward.h
@@ -21,6 +21,9 @@ typedef HostThreadLinux HostNativeThread;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
class HostThreadFreeBSD;
typedef HostThreadFreeBSD HostNativeThread;
+#elif defined(__NetBSD__)
+class HostThreadNetBSD;
+typedef HostThreadNetBSD HostNativeThread;
#elif defined(__APPLE__)
class HostThreadMacOSX;
typedef HostThreadMacOSX HostNativeThread;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/MainLoopBase.h b/contrib/llvm/tools/lldb/include/lldb/Host/MainLoopBase.h
index bff2ce7..da14349 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/MainLoopBase.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/MainLoopBase.h
@@ -60,25 +60,25 @@ public:
protected:
ReadHandleUP
CreateReadHandle(const lldb::IOObjectSP &object_sp)
- { return ReadHandleUP(new ReadHandle(*this, object_sp)); }
+ { return ReadHandleUP(new ReadHandle(*this, object_sp->GetWaitableHandle())); }
virtual void
- UnregisterReadObject(const lldb::IOObjectSP &object_sp)
+ UnregisterReadObject(IOObject::WaitableHandle handle)
{ llvm_unreachable("Not implemented"); }
private:
class ReadHandle
{
public:
- ~ReadHandle() { m_mainloop.UnregisterReadObject(m_object_sp); }
+ ~ReadHandle() { m_mainloop.UnregisterReadObject(m_handle); }
private:
- ReadHandle(MainLoopBase &mainloop, const lldb::IOObjectSP &object_sp)
- : m_mainloop(mainloop), m_object_sp(object_sp)
+ ReadHandle(MainLoopBase &mainloop, IOObject::WaitableHandle handle)
+ : m_mainloop(mainloop), m_handle(handle)
{ }
MainLoopBase &m_mainloop;
- lldb::IOObjectSP m_object_sp;
+ IOObject::WaitableHandle m_handle;
friend class MainLoopBase;
DISALLOW_COPY_AND_ASSIGN(ReadHandle);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/MonitoringProcessLauncher.h b/contrib/llvm/tools/lldb/include/lldb/Host/MonitoringProcessLauncher.h
index 3c3e661..f5d0a92 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/MonitoringProcessLauncher.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/MonitoringProcessLauncher.h
@@ -10,6 +10,10 @@
#ifndef lldb_Host_MonitoringProcessLauncher_h_
#define lldb_Host_MonitoringProcessLauncher_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Host/ProcessLauncher.h"
namespace lldb_private
@@ -20,11 +24,12 @@ class MonitoringProcessLauncher : public ProcessLauncher
public:
explicit MonitoringProcessLauncher(std::unique_ptr<ProcessLauncher> delegate_launcher);
- virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error);
+ HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) override;
private:
std::unique_ptr<ProcessLauncher> m_delegate_launcher;
};
-}
-#endif
+} // namespace lldb_private
+
+#endif // lldb_Host_MonitoringProcessLauncher_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Mutex.h b/contrib/llvm/tools/lldb/include/lldb/Host/Mutex.h
index 496dd04..5a529fb 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Mutex.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Mutex.h
@@ -9,15 +9,17 @@
#ifndef liblldb_Mutex_h_
#define liblldb_Mutex_h_
-#if defined(__cplusplus)
-
-#include "lldb/lldb-types.h"
-#include <assert.h>
+// C Includes
+// C++ Includes
#ifdef LLDB_CONFIGURATION_DEBUG
#include <string>
#endif
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-types.h"
+
namespace lldb_private {
//----------------------------------------------------------------------
@@ -85,7 +87,7 @@ public:
Locker(Mutex* m);
//--------------------------------------------------------------
- /// Desstructor
+ /// Destructor
///
/// Unlocks any valid pthread_mutex_t that this object may
/// contain.
@@ -97,7 +99,7 @@ public:
///
/// Unlock the current mutex in this object (if it contains a
/// valid mutex) and lock the new \a mutex object if it is
- /// non-NULL.
+ /// non-nullptr.
//--------------------------------------------------------------
void
Lock (Mutex &mutex);
@@ -120,15 +122,15 @@ public:
/// will not take ownership of the mutex.
///
/// @return
- /// Returns \b true if the lock was aquired and the this
+ /// Returns \b true if the lock was acquired and the this
/// object will unlock the mutex when it goes out of scope,
/// returns \b false otherwise.
//--------------------------------------------------------------
bool
- TryLock (Mutex &mutex, const char *failure_message = NULL);
+ TryLock(Mutex &mutex, const char *failure_message = nullptr);
bool
- TryLock (Mutex *mutex, const char *failure_message = NULL)
+ TryLock(Mutex *mutex, const char *failure_message = nullptr)
{
if (mutex)
return TryLock(*mutex, failure_message);
@@ -150,7 +152,6 @@ public:
const Locker& operator=(const Locker&);
};
-
//------------------------------------------------------------------
/// Default constructor.
///
@@ -213,7 +214,7 @@ public:
virtual
#endif
int
- TryLock(const char *failure_message = NULL);
+ TryLock(const char *failure_message = nullptr);
//------------------------------------------------------------------
/// Unlock the mutex.
@@ -262,16 +263,16 @@ public:
TrackingMutex(Mutex::Type type) : Mutex (type) {}
virtual
- ~TrackingMutex() {}
+ ~TrackingMutex() = default;
virtual int
Unlock ();
virtual int
- TryLock (const char *failure_message = NULL)
+ TryLock(const char *failure_message = nullptr)
{
int return_value = Mutex::TryLock();
- if (return_value != 0 && failure_message != NULL)
+ if (return_value != 0 && failure_message != nullptr)
{
m_failure_message.assign(failure_message);
m_thread_that_tried = pthread_self();
@@ -291,7 +292,7 @@ public:
LoggingMutex(Mutex::Type type) : Mutex (type),m_locked(false) {}
virtual
- ~LoggingMutex() {}
+ ~LoggingMutex() = default;
virtual int
Lock ();
@@ -300,13 +301,13 @@ public:
Unlock ();
virtual int
- TryLock (const char *failure_message = NULL);
+ TryLock(const char *failure_message = nullptr);
+
protected:
bool m_locked;
};
-#endif
+#endif // LLDB_CONFIGURATION_DEBUG
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif
+#endif // liblldb_Mutex_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/OptionParser.h b/contrib/llvm/tools/lldb/include/lldb/Host/OptionParser.h
index 5aa7db5..175a197 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/OptionParser.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/OptionParser.h
@@ -11,6 +11,7 @@
#define liblldb_OptionParser_h_
#include <string>
+#include "lldb/Host/Mutex.h"
struct option;
@@ -38,7 +39,7 @@ public:
eOptionalArgument
};
- static void Prepare();
+ static void Prepare(Mutex::Locker &locker);
static void EnableError(bool error);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Predicate.h b/contrib/llvm/tools/lldb/include/lldb/Host/Predicate.h
index ae6c991..4f386dc 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Predicate.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Predicate.h
@@ -9,13 +9,17 @@
#ifndef liblldb_Predicate_h_
#define liblldb_Predicate_h_
-#if defined(__cplusplus)
+// C Includes
+#include <stdint.h>
+#include <time.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-defines.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Host/Condition.h"
-#include <stdint.h>
-#include <time.h>
//#define DB_PTHREAD_LOG_EVENTS
@@ -29,7 +33,6 @@ typedef enum
eBroadcastNever, ///< No broadcast will be sent when the value is modified.
eBroadcastAlways, ///< Always send a broadcast when the value is modified.
eBroadcastOnChange ///< Only broadcast if the value changes when the value is modified.
-
} PredicateBroadcastType;
//----------------------------------------------------------------------
@@ -46,7 +49,6 @@ template <class T>
class Predicate
{
public:
-
//------------------------------------------------------------------
/// Default constructor.
///
@@ -81,10 +83,7 @@ public:
///
/// Destroy the condition, mutex, and T objects.
//------------------------------------------------------------------
- ~Predicate ()
- {
- }
-
+ ~Predicate() = default;
//------------------------------------------------------------------
/// Value get accessor.
@@ -205,7 +204,7 @@ public:
/// The bits we are waiting to be set in \a m_value.
///
/// @param[in] abstime
- /// If non-NULL, the absolute time at which we should stop
+ /// If non-nullptr, the absolute time at which we should stop
/// waiting, else wait an infinite amount of time.
///
/// @return
@@ -214,7 +213,7 @@ public:
/// occurred.
//------------------------------------------------------------------
T
- WaitForSetValueBits (T bits, const TimeValue *abstime = NULL)
+ WaitForSetValueBits(T bits, const TimeValue *abstime = nullptr)
{
int err = 0;
// pthread_cond_timedwait() or pthread_cond_wait() will atomically
@@ -255,7 +254,7 @@ public:
/// The bits we are waiting to be reset in \a m_value.
///
/// @param[in] abstime
- /// If non-NULL, the absolute time at which we should stop
+ /// If non-nullptr, the absolute time at which we should stop
/// waiting, else wait an infinite amount of time.
///
/// @return
@@ -263,7 +262,7 @@ public:
/// unrecoverable error occurs.
//------------------------------------------------------------------
T
- WaitForResetValueBits (T bits, const TimeValue *abstime = NULL)
+ WaitForResetValueBits(T bits, const TimeValue *abstime = nullptr)
{
int err = 0;
@@ -306,7 +305,7 @@ public:
/// The value we want \a m_value to be equal to.
///
/// @param[in] abstime
- /// If non-NULL, the absolute time at which we should stop
+ /// If non-nullptr, the absolute time at which we should stop
/// waiting, else wait an infinite amount of time.
///
/// @param[out] timed_out
@@ -318,7 +317,7 @@ public:
/// @li \b false otherwise
//------------------------------------------------------------------
bool
- WaitForValueEqualTo (T value, const TimeValue *abstime = NULL, bool *timed_out = NULL)
+ WaitForValueEqualTo(T value, const TimeValue *abstime = nullptr, bool *timed_out = nullptr)
{
int err = 0;
// pthread_cond_timedwait() or pthread_cond_wait() will atomically
@@ -366,7 +365,7 @@ public:
/// returned.
///
/// @param[in] abstime
- /// If non-NULL, the absolute time at which we should stop
+ /// If non-nullptr, the absolute time at which we should stop
/// waiting, else wait an infinite amount of time.
///
/// @param[out] timed_out
@@ -378,7 +377,9 @@ public:
/// @li \b false otherwise
//------------------------------------------------------------------
bool
- WaitForValueEqualToAndSetValueTo (T wait_value, T new_value, const TimeValue *abstime = NULL, bool *timed_out = NULL)
+ WaitForValueEqualToAndSetValueTo(T wait_value, T new_value,
+ const TimeValue *abstime = nullptr,
+ bool *timed_out = nullptr)
{
int err = 0;
// pthread_cond_timedwait() or pthread_cond_wait() will atomically
@@ -408,7 +409,6 @@ public:
return false;
}
-
//------------------------------------------------------------------
/// Wait for \a m_value to not be equal to \a value.
///
@@ -430,7 +430,7 @@ public:
/// The new value if \b true is returned.
///
/// @param[in] abstime
- /// If non-NULL, the absolute time at which we should stop
+ /// If non-nullptr, the absolute time at which we should stop
/// waiting, else wait an infinite amount of time.
///
/// @return
@@ -438,7 +438,7 @@ public:
/// @li \b false otherwise
//------------------------------------------------------------------
bool
- WaitForValueNotEqualTo (T value, T &new_value, const TimeValue *abstime = NULL)
+ WaitForValueNotEqualTo(T value, T &new_value, const TimeValue *abstime = nullptr)
{
int err = 0;
// pthread_cond_timedwait() or pthread_cond_wait() will atomically
@@ -473,7 +473,6 @@ protected:
Condition m_condition; ///< The pthread condition variable to use for signaling that data available or changed.
private:
-
//------------------------------------------------------------------
/// Broadcast if needed.
///
@@ -500,11 +499,9 @@ private:
m_condition.Broadcast();
}
-
DISALLOW_COPY_AND_ASSIGN(Predicate);
};
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif // #ifndef liblldb_Predicate_h_
+#endif // liblldb_Predicate_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/ProcessRunLock.h b/contrib/llvm/tools/lldb/include/lldb/Host/ProcessRunLock.h
index eca1ad3..ceb1e90 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/ProcessRunLock.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/ProcessRunLock.h
@@ -9,13 +9,17 @@
#ifndef liblldb_ProcessRunLock_h_
#define liblldb_ProcessRunLock_h_
-#if defined(__cplusplus)
+// C Includes
+#include <stdint.h>
+#include <time.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-defines.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Host/Condition.h"
-#include <stdint.h>
-#include <time.h>
//----------------------------------------------------------------------
/// Enumerations for broadcasting.
@@ -34,17 +38,18 @@ class ProcessRunLock
public:
ProcessRunLock();
~ProcessRunLock();
+
bool ReadTryLock ();
bool ReadUnlock ();
bool SetRunning ();
bool TrySetRunning ();
bool SetStopped ();
-public:
+
class ProcessRunLocker
{
public:
ProcessRunLocker () :
- m_lock (NULL)
+ m_lock (nullptr)
{
}
@@ -82,11 +87,12 @@ public:
if (m_lock)
{
m_lock->ReadUnlock();
- m_lock = NULL;
+ m_lock = nullptr;
}
}
ProcessRunLock *m_lock;
+
private:
DISALLOW_COPY_AND_ASSIGN(ProcessRunLocker);
};
@@ -94,11 +100,11 @@ public:
protected:
lldb::rwlock_t m_rwlock;
bool m_running;
+
private:
DISALLOW_COPY_AND_ASSIGN(ProcessRunLock);
};
} // namespace lldb_private
-#endif // #if defined(__cplusplus)
-#endif // #ifndef liblldb_ProcessRunLock_h_
+#endif // liblldb_ProcessRunLock_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Socket.h b/contrib/llvm/tools/lldb/include/lldb/Host/Socket.h
index f4599b5..a38b42f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Socket.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Socket.h
@@ -10,6 +10,7 @@
#ifndef liblldb_Host_Socket_h_
#define liblldb_Host_Socket_h_
+#include <memory>
#include <string>
#include "lldb/lldb-private.h"
@@ -45,13 +46,19 @@ public:
{
ProtocolTcp,
ProtocolUdp,
- ProtocolUnixDomain
+ ProtocolUnixDomain,
+ ProtocolUnixAbstract
} SocketProtocol;
static const NativeSocket kInvalidSocketValue;
- Socket(NativeSocket socket, SocketProtocol protocol, bool should_close);
- ~Socket();
+ ~Socket() override;
+
+ static std::unique_ptr<Socket> Create(const SocketProtocol protocol, bool child_processes_inherit, Error &error);
+
+ virtual Error Connect(llvm::StringRef name) = 0;
+ virtual Error Listen(llvm::StringRef name, int backlog) = 0;
+ virtual Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) = 0;
// Initialize a Tcp Socket object in listening mode. listen and accept are implemented
// separately because the caller may wish to manipulate or query the socket after it is
@@ -66,43 +73,23 @@ public:
static Error UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket);
static Error UnixDomainConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket);
static Error UnixDomainAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket);
-
- // Blocks on a listening socket until a connection is received. This method assumes that
- // |this->m_socket| is a listening socket, created via either TcpListen() or via the native
- // constructor that takes a NativeSocket, which itself was created via a call to |listen()|
- Error BlockingAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket);
+ static Error UnixAbstractConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket);
+ static Error UnixAbstractAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket);
int GetOption (int level, int option_name, int &option_value);
int SetOption (int level, int option_name, int option_value);
- // returns port number or 0 if error
- static uint16_t GetLocalPortNumber (const NativeSocket& socket);
-
- // returns port number or 0 if error
- uint16_t GetLocalPortNumber () const;
-
- // returns ip address string or empty string if error
- std::string GetLocalIPAddress () const;
-
- // must be connected
- // returns port number or 0 if error
- uint16_t GetRemotePortNumber () const;
-
- // must be connected
- // returns ip address string or empty string if error
- std::string GetRemoteIPAddress () const;
-
NativeSocket GetNativeSocket () const { return m_socket; }
SocketProtocol GetSocketProtocol () const { return m_protocol; }
- virtual Error Read (void *buf, size_t &num_bytes);
- virtual Error Write (const void *buf, size_t &num_bytes);
+ Error Read (void *buf, size_t &num_bytes) override;
+ Error Write (const void *buf, size_t &num_bytes) override;
virtual Error PreDisconnect ();
- virtual Error Close ();
+ Error Close() override;
- virtual bool IsValid () const { return m_socket != kInvalidSocketValue; }
- virtual WaitableHandle GetWaitableHandle ();
+ bool IsValid () const override { return m_socket != kInvalidSocketValue; }
+ WaitableHandle GetWaitableHandle () override;
static bool
DecodeHostAndPort (llvm::StringRef host_and_port,
@@ -112,10 +99,20 @@ public:
Error *error_ptr);
protected:
+ Socket(NativeSocket socket, SocketProtocol protocol, bool should_close);
+
+ virtual size_t Send(const void *buf, const size_t num_bytes);
+
+ static void SetLastError(Error &error);
+ static NativeSocket CreateSocket(
+ const int domain, const int type, const int protocol, bool child_processes_inherit, Error& error);
+ static NativeSocket AcceptSocket(
+ NativeSocket sockfd, struct sockaddr *addr, socklen_t *addrlen, bool child_processes_inherit, Error& error);
+
SocketProtocol m_protocol;
NativeSocket m_socket;
- SocketAddress m_udp_send_sockaddr; // Send address used for UDP connections.
};
-}
-#endif
+} // namespace lldb_private
+
+#endif // liblldb_Host_Socket_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/Symbols.h b/contrib/llvm/tools/lldb/include/lldb/Host/Symbols.h
index d6c8633..0ca864c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/Symbols.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/Symbols.h
@@ -29,7 +29,7 @@ public:
// Locating the file should happen only on the local computer or using
// the current computers global settings.
//----------------------------------------------------------------------
- static FileSpec
+ static ModuleSpec
LocateExecutableObjectFile (const ModuleSpec &module_spec);
//----------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/XML.h b/contrib/llvm/tools/lldb/include/lldb/Host/XML.h
index e3547d8..3ebd2c6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/XML.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/XML.h
@@ -11,25 +11,23 @@
#define liblldb_XML_h_
// C Includes
-
#if defined( LIBXML2_DEFINED )
#include <libxml/xmlreader.h>
#endif
// C++ Includes
-
#include <functional>
#include <string>
#include <vector>
// Other libraries and framework includes
+#include "llvm/ADT/StringRef.h"
+
// Project includes
#include "lldb/lldb-private.h"
-#include "llvm/ADT/StringRef.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/StructuredData.h"
-
namespace lldb_private {
#if defined( LIBXML2_DEFINED )
@@ -94,7 +92,7 @@ namespace lldb_private {
GetChild () const;
llvm::StringRef
- GetAttributeValue(const char *name, const char *fail_value = NULL) const;
+ GetAttributeValue(const char *name, const char *fail_value = nullptr) const;
XMLNode
FindFirstChildElementWithName (const char *name) const;
@@ -140,7 +138,6 @@ namespace lldb_private {
class XMLDocument
{
public:
-
XMLDocument ();
~XMLDocument ();
@@ -163,7 +160,7 @@ namespace lldb_private {
ParseMemory (const char *xml, size_t xml_length, const char *url = "untitled.xml");
//----------------------------------------------------------------------
- // If \a name is NULL, just get the root element node, else only return
+ // If \a name is nullptr, just get the root element node, else only return
// a value XMLNode if the name of the root element matches \a name.
//----------------------------------------------------------------------
XMLNode
@@ -216,7 +213,6 @@ namespace lldb_private {
GetStructuredData();
protected:
-
// Using a node returned from GetValueNode() extract its value as a
// string (if possible). Array and dictionary nodes will return false
// as they have no string value. Boolean nodes will return true and
@@ -229,6 +225,7 @@ namespace lldb_private {
XMLDocument m_xml_doc;
XMLNode m_dict_node;
};
+
} // namespace lldb_private
#endif // liblldb_XML_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/common/GetOptInc.h b/contrib/llvm/tools/lldb/include/lldb/Host/common/GetOptInc.h
new file mode 100644
index 0000000..f796440
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/common/GetOptInc.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include "lldb/lldb-defines.h"
+
+#if defined(_MSC_VER)
+#define REPLACE_GETOPT
+#define REPLACE_GETOPT_LONG
+#endif
+#if defined(_MSC_VER) || defined(__NetBSD__)
+#define REPLACE_GETOPT_LONG_ONLY
+#endif
+
+#if defined(REPLACE_GETOPT)
+// from getopt.h
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+// option structure
+struct option
+{
+ const char *name;
+ // has_arg can't be an enum because some compilers complain about
+ // type mismatches in all the code that assumes it is an int.
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+int getopt( int argc, char * const argv[], const char *optstring );
+
+// from getopt.h
+extern char * optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+
+// defined in unistd.h
+extern int optreset;
+#else
+# include <unistd.h>
+# include <getopt.h>
+#endif
+
+#if defined(REPLACE_GETOPT_LONG)
+int getopt_long
+(
+ int argc,
+ char * const *argv,
+ const char *optstring,
+ const struct option *longopts,
+ int *longindex
+);
+#endif
+
+#if defined(REPLACE_GETOPT_LONG_ONLY)
+int getopt_long_only
+(
+ int argc,
+ char * const *argv,
+ const char *optstring,
+ const struct option *longopts,
+ int *longindex
+);
+#endif
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeProcessProtocol.h
index 4f0f3a9..7236bf6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeProcessProtocol.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/common/NativeProcessProtocol.h
@@ -16,6 +16,7 @@
#include "lldb/lldb-types.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/Mutex.h"
+#include "lldb/Host/MainLoop.h"
#include "llvm/ADT/StringRef.h"
#include "NativeBreakpointList.h"
@@ -284,10 +285,6 @@ namespace lldb_private
bool
UnregisterNativeDelegate (NativeDelegate &native_delegate);
- // Called before termination of NativeProcessProtocol's instance.
- virtual void
- Terminate ();
-
virtual Error
GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) = 0;
@@ -307,6 +304,11 @@ namespace lldb_private
/// inferior. Must outlive the NativeProcessProtocol
/// instance.
///
+ /// @param[in] mainloop
+ /// The mainloop instance with which the process can register
+ /// callbacks. Must outlive the NativeProcessProtocol
+ /// instance.
+ ///
/// @param[out] process_sp
/// On successful return from the method, this parameter
/// contains the shared pointer to the
@@ -320,6 +322,7 @@ namespace lldb_private
static Error
Launch (ProcessLaunchInfo &launch_info,
NativeDelegate &native_delegate,
+ MainLoop &mainloop,
NativeProcessProtocolSP &process_sp);
//------------------------------------------------------------------
@@ -335,6 +338,11 @@ namespace lldb_private
/// inferior. Must outlive the NativeProcessProtocol
/// instance.
///
+ /// @param[in] mainloop
+ /// The mainloop instance with which the process can register
+ /// callbacks. Must outlive the NativeProcessProtocol
+ /// instance.
+ ///
/// @param[out] process_sp
/// On successful return from the method, this parameter
/// contains the shared pointer to the
@@ -348,6 +356,7 @@ namespace lldb_private
static Error
Attach (lldb::pid_t pid,
NativeDelegate &native_delegate,
+ MainLoop &mainloop,
NativeProcessProtocolSP &process_sp);
protected:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/common/TCPSocket.h b/contrib/llvm/tools/lldb/include/lldb/Host/common/TCPSocket.h
new file mode 100644
index 0000000..0ffe9c8
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/common/TCPSocket.h
@@ -0,0 +1,46 @@
+//===-- TCPSocket.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_TCPSocket_h_
+#define liblldb_TCPSocket_h_
+
+#include "lldb/Host/Socket.h"
+
+namespace lldb_private
+{
+ class TCPSocket: public Socket
+ {
+ public:
+ TCPSocket(NativeSocket socket, bool should_close);
+ TCPSocket(bool child_processes_inherit, Error &error);
+
+ // returns port number or 0 if error
+ uint16_t GetLocalPortNumber () const;
+
+ // returns ip address string or empty string if error
+ std::string GetLocalIPAddress () const;
+
+ // must be connected
+ // returns port number or 0 if error
+ uint16_t GetRemotePortNumber () const;
+
+ // must be connected
+ // returns ip address string or empty string if error
+ std::string GetRemoteIPAddress () const;
+
+ int SetOptionNoDelay();
+ int SetOptionReuseAddress();
+
+ Error Connect(llvm::StringRef name) override;
+ Error Listen(llvm::StringRef name, int backlog) override;
+ Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&conn_socket) override;
+ };
+}
+
+#endif // ifndef liblldb_TCPSocket_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/common/UDPSocket.h b/contrib/llvm/tools/lldb/include/lldb/Host/common/UDPSocket.h
new file mode 100644
index 0000000..afc1ec7
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/common/UDPSocket.h
@@ -0,0 +1,35 @@
+//===-- UDPSocket.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_UDPSocket_h_
+#define liblldb_UDPSocket_h_
+
+#include "lldb/Host/Socket.h"
+
+namespace lldb_private
+{
+ class UDPSocket: public Socket
+ {
+ public:
+ UDPSocket(bool child_processes_inherit, Error &error);
+
+ static Error Connect(llvm::StringRef name, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket);
+ private:
+ UDPSocket(NativeSocket socket);
+
+ size_t Send(const void *buf, const size_t num_bytes) override;
+ Error Connect(llvm::StringRef name) override;
+ Error Listen(llvm::StringRef name, int backlog) override;
+ Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) override;
+
+ SocketAddress m_send_sockaddr;
+ };
+}
+
+#endif // ifndef liblldb_UDPSocket_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/Config.h b/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/Config.h
new file mode 100644
index 0000000..1e9f552
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/Config.h
@@ -0,0 +1,28 @@
+//===-- Config.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//----------------------------------------------------------------------
+// LLDB currently doesn't have a dynamic configuration mechanism, so we
+// are going to hardcode things for now. Eventually these files will
+// be auto generated by some configuration script that can detect
+// platform functionality availability.
+//----------------------------------------------------------------------
+
+#ifndef liblldb_Platform_Config_h_
+#define liblldb_Platform_Config_h_
+
+#define LLDB_CONFIG_TERMIOS_SUPPORTED 1
+
+#define LLDB_CONFIG_TILDE_RESOLVES_TO_USER 1
+
+//#define LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 1
+
+//#define LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED 1
+
+#endif // #ifndef liblldb_Platform_Config_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h b/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h
new file mode 100644
index 0000000..34a2934
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h
@@ -0,0 +1,30 @@
+//===-- HostInfoNetBSD.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Host_netbsd_HostInfoNetBSD_h_
+#define lldb_Host_netbsd_HostInfoNetBSD_h_
+
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/posix/HostInfoPosix.h"
+
+namespace lldb_private
+{
+
+class HostInfoNetBSD : public HostInfoPosix
+{
+ public:
+ static uint32_t GetMaxThreadNameLength();
+ static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update);
+ static bool GetOSBuildString(std::string &s);
+ static bool GetOSKernelDescription(std::string &s);
+ static FileSpec GetProgramFileSpec();
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostThreadNetBSD.h b/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostThreadNetBSD.h
new file mode 100644
index 0000000..2ce1e48
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/netbsd/HostThreadNetBSD.h
@@ -0,0 +1,32 @@
+//===-- HostThreadNetBSD.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Host_netbsd_HostThreadNetBSD_h_
+#define lldb_Host_netbsd_HostThreadNetBSD_h_
+
+#include "lldb/Host/posix/HostThreadPosix.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
+
+namespace lldb_private
+{
+
+class HostThreadNetBSD : public HostThreadPosix
+{
+ public:
+ HostThreadNetBSD();
+ HostThreadNetBSD(lldb::thread_t thread);
+
+ static void SetName(lldb::thread_t tid, llvm::StringRef &name);
+ static void GetName(lldb::thread_t tid, llvm::SmallVectorImpl<char> &name);
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h b/contrib/llvm/tools/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
index 2e0fd70..7e7904c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
@@ -34,13 +34,24 @@ class SocketAddress;
class ConnectionFileDescriptor : public Connection
{
public:
+ static const char* LISTEN_SCHEME;
+ static const char* ACCEPT_SCHEME;
+ static const char* UNIX_ACCEPT_SCHEME;
+ static const char* CONNECT_SCHEME;
+ static const char* TCP_CONNECT_SCHEME;
+ static const char* UDP_SCHEME;
+ static const char* UNIX_CONNECT_SCHEME;
+ static const char* UNIX_ABSTRACT_CONNECT_SCHEME;
+ static const char* FD_SCHEME;
+ static const char* FILE_SCHEME;
+
ConnectionFileDescriptor(bool child_processes_inherit = false);
ConnectionFileDescriptor(int fd, bool owns_fd);
ConnectionFileDescriptor(Socket* socket);
- virtual ~ConnectionFileDescriptor();
+ ~ConnectionFileDescriptor() override;
bool IsConnected() const override;
@@ -84,6 +95,8 @@ class ConnectionFileDescriptor : public Connection
lldb::ConnectionStatus NamedSocketAccept(const char *socket_name, Error *error_ptr);
+ lldb::ConnectionStatus UnixAbstractSocketConnect(const char *socket_name, Error *error_ptr);
+
lldb::IOObjectSP m_read_sp;
lldb::IOObjectSP m_write_sp;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/posix/DomainSocket.h b/contrib/llvm/tools/lldb/include/lldb/Host/posix/DomainSocket.h
new file mode 100644
index 0000000..76f58e4
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/posix/DomainSocket.h
@@ -0,0 +1,37 @@
+//===-- DomainSocket.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DomainSocket_h_
+#define liblldb_DomainSocket_h_
+
+#include "lldb/Host/Socket.h"
+
+namespace lldb_private
+{
+ class DomainSocket: public Socket
+ {
+ public:
+ DomainSocket(bool child_processes_inherit, Error &error);
+
+ Error Connect(llvm::StringRef name) override;
+ Error Listen(llvm::StringRef name, int backlog) override;
+ Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) override;
+
+ protected:
+ DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error);
+
+ virtual size_t GetNameOffset() const;
+ virtual void DeleteSocketFile(llvm::StringRef name);
+
+ private:
+ DomainSocket(NativeSocket socket);
+ };
+}
+
+#endif // ifndef liblldb_DomainSocket_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostProcessPosix.h b/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostProcessPosix.h
index c953499..5db49d1 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostProcessPosix.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostProcessPosix.h
@@ -10,6 +10,10 @@
#ifndef lldb_Host_HostProcesPosix_h_
#define lldb_Host_HostProcesPosix_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-types.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/HostNativeProcessBase.h"
@@ -24,7 +28,7 @@ class HostProcessPosix : public HostNativeProcessBase
public:
HostProcessPosix();
HostProcessPosix(lldb::process_t process);
- virtual ~HostProcessPosix();
+ ~HostProcessPosix() override;
virtual Error Signal(int signo) const;
static Error Signal(lldb::process_t process, int signo);
@@ -37,6 +41,7 @@ class HostProcessPosix : public HostNativeProcessBase
HostThread StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) override;
};
-}
-#endif
+} // namespace lldb_private
+
+#endif // lldb_Host_HostProcesPosix_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostThreadPosix.h b/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostThreadPosix.h
index 8839b8d..e044313 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostThreadPosix.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/posix/HostThreadPosix.h
@@ -22,13 +22,14 @@ class HostThreadPosix : public HostNativeThreadBase
public:
HostThreadPosix();
HostThreadPosix(lldb::thread_t thread);
- virtual ~HostThreadPosix();
+ ~HostThreadPosix() override;
Error Join(lldb::thread_result_t *result) override;
Error Cancel() override;
Error Detach();
};
-}
-#endif
+} // namespace lldb_private
+
+#endif // lldb_Host_posix_HostThreadPosix_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/posix/LockFilePosix.h b/contrib/llvm/tools/lldb/include/lldb/Host/posix/LockFilePosix.h
index 999397e..628571c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/posix/LockFilePosix.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/posix/LockFilePosix.h
@@ -18,7 +18,7 @@ class LockFilePosix : public LockFileBase
{
public:
explicit LockFilePosix (int fd);
- ~LockFilePosix ();
+ ~LockFilePosix () override;
protected:
Error
@@ -37,6 +37,6 @@ protected:
DoUnlock () override;
};
-} // namespace lldb_private
+} // namespace lldb_private
-#endif // liblldb_Host_posix_LockFilePosix_h_
+#endif // liblldb_Host_posix_LockFilePosix_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Host/posix/MainLoopPosix.h b/contrib/llvm/tools/lldb/include/lldb/Host/posix/MainLoopPosix.h
index 9a665de..225cebd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Host/posix/MainLoopPosix.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Host/posix/MainLoopPosix.h
@@ -60,7 +60,7 @@ public:
protected:
void
- UnregisterReadObject(const lldb::IOObjectSP &object_sp) override;
+ UnregisterReadObject(IOObject::WaitableHandle handle) override;
void
UnregisterSignal(int signo);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Initialization/SystemInitializerCommon.h b/contrib/llvm/tools/lldb/include/lldb/Initialization/SystemInitializerCommon.h
index af66c93..b46bf50 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Initialization/SystemInitializerCommon.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Initialization/SystemInitializerCommon.h
@@ -28,11 +28,12 @@ class SystemInitializerCommon : public SystemInitializer
{
public:
SystemInitializerCommon();
- virtual ~SystemInitializerCommon();
+ ~SystemInitializerCommon() override;
void Initialize() override;
void Terminate() override;
};
-}
-#endif
+} // namespace lldb_private
+
+#endif // LLDB_INITIALIZATION_SYSTEM_INITIALIZER_COMMON_H
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/Args.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/Args.h
index e11636b..e79318b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/Args.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/Args.h
@@ -424,6 +424,9 @@ public:
static void
ExpandEscapedCharacters (const char *src, std::string &dst);
+ static std::string
+ EscapeLLDBCommandArgument (const std::string& arg, char quote_char);
+
// This one isn't really relevant to Arguments per se, but we're using the Args as a
// general strings container, so...
void
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandCompletions.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandCompletions.h
index 9df3041..27ab45b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandCompletions.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandCompletions.h
@@ -54,7 +54,6 @@ public:
// so you can add custom enums starting from here in your Option class.
// Also if you & in this bit the base code will not process the option.
eCustomCompletion = (1u << 9)
-
} CommonCompletionTypes;
struct CommonCompletionElement
@@ -83,6 +82,7 @@ public:
SearchFilter *searcher,
bool &word_complete,
StringList &matches);
+
static int
DiskDirectories (CommandInterpreter &interpreter,
const char *partial_file_name,
@@ -170,16 +170,16 @@ public:
int max_return_elements,
StringList &matches);
- virtual ~Completer ();
+ ~Completer() override;
- virtual CallbackReturn
- SearchCallback (SearchFilter &filter,
- SymbolContext &context,
- Address *addr,
- bool complete) = 0;
+ CallbackReturn
+ SearchCallback(SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool complete) override = 0;
- virtual Depth
- GetDepth () = 0;
+ Depth
+ GetDepth() override = 0;
virtual size_t
DoCompletion (SearchFilter *filter) = 0;
@@ -190,8 +190,9 @@ public:
int m_match_start_point;
int m_max_return_elements;
StringList &m_matches;
+
private:
- DISALLOW_COPY_AND_ASSIGN (Completer);
+ DISALLOW_COPY_AND_ASSIGN(Completer);
};
//----------------------------------------------------------------------
@@ -200,7 +201,6 @@ public:
class SourceFileCompleter : public Completer
{
public:
-
SourceFileCompleter (CommandInterpreter &interpreter,
bool include_support_files,
const char *completion_str,
@@ -208,24 +208,24 @@ public:
int max_return_elements,
StringList &matches);
- virtual Searcher::Depth GetDepth ();
+ Searcher::Depth GetDepth() override;
- virtual Searcher::CallbackReturn
- SearchCallback (SearchFilter &filter,
- SymbolContext &context,
- Address *addr,
- bool complete);
+ Searcher::CallbackReturn
+ SearchCallback(SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool complete) override;
size_t
- DoCompletion (SearchFilter *filter);
+ DoCompletion(SearchFilter *filter) override;
private:
bool m_include_support_files;
FileSpecList m_matching_files;
const char *m_file_name;
const char *m_dir_name;
- DISALLOW_COPY_AND_ASSIGN (SourceFileCompleter);
+ DISALLOW_COPY_AND_ASSIGN(SourceFileCompleter);
};
//----------------------------------------------------------------------
@@ -234,29 +234,28 @@ public:
class ModuleCompleter : public Completer
{
public:
-
ModuleCompleter (CommandInterpreter &interpreter,
const char *completion_str,
int match_start_point,
int max_return_elements,
StringList &matches);
- virtual Searcher::Depth GetDepth ();
+ Searcher::Depth GetDepth() override;
- virtual Searcher::CallbackReturn
- SearchCallback (SearchFilter &filter,
- SymbolContext &context,
- Address *addr,
- bool complete);
+ Searcher::CallbackReturn
+ SearchCallback(SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool complete) override;
size_t
- DoCompletion (SearchFilter *filter);
+ DoCompletion(SearchFilter *filter) override;
private:
const char *m_file_name;
const char *m_dir_name;
- DISALLOW_COPY_AND_ASSIGN (ModuleCompleter);
+ DISALLOW_COPY_AND_ASSIGN(ModuleCompleter);
};
//----------------------------------------------------------------------
@@ -265,23 +264,22 @@ public:
class SymbolCompleter : public Completer
{
public:
-
SymbolCompleter (CommandInterpreter &interpreter,
const char *completion_str,
int match_start_point,
int max_return_elements,
StringList &matches);
- virtual Searcher::Depth GetDepth ();
+ Searcher::Depth GetDepth() override;
- virtual Searcher::CallbackReturn
- SearchCallback (SearchFilter &filter,
- SymbolContext &context,
- Address *addr,
- bool complete);
+ Searcher::CallbackReturn
+ SearchCallback(SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool complete) override;
size_t
- DoCompletion (SearchFilter *filter);
+ DoCompletion(SearchFilter *filter) override;
private:
// struct NameCmp {
@@ -294,14 +292,14 @@ public:
RegularExpression m_regex;
typedef std::set<ConstString> collection;
collection m_match_set;
- DISALLOW_COPY_AND_ASSIGN (SymbolCompleter);
+ DISALLOW_COPY_AND_ASSIGN(SymbolCompleter);
};
private:
static CommonCompletionElement g_common_completions[];
-
};
} // namespace lldb_private
-#endif // lldb_CommandCompletions_h_
+
+#endif // lldb_CommandCompletions_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandHistory.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandHistory.h
index dbe6e99..db5db15 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandHistory.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandHistory.h
@@ -17,7 +17,6 @@
// Other libraries and framework includes
// Project includes
-
#include "lldb/lldb-private.h"
#include "lldb/Core/Stream.h"
#include "lldb/Host/Mutex.h"
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandInterpreter.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandInterpreter.h
index 1962050..dd5c189 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandInterpreter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandInterpreter.h
@@ -14,6 +14,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Debugger.h"
@@ -199,8 +200,6 @@ class CommandInterpreter :
public IOHandlerDelegate
{
public:
-
-
typedef std::map<std::string, OptionArgVectorSP> OptionArgMap;
enum
@@ -228,11 +227,17 @@ public:
eCommandTypesAllThem = 0xFFFF // all commands
};
+ CommandInterpreter(Debugger &debugger,
+ lldb::ScriptLanguage script_language,
+ bool synchronous_execution);
+
+ ~CommandInterpreter() override;
+
// These two functions fill out the Broadcaster interface:
static ConstString &GetStaticBroadcasterClass ();
- virtual ConstString &GetBroadcasterClass() const
+ ConstString &GetBroadcasterClass() const override
{
return GetStaticBroadcasterClass();
}
@@ -241,13 +246,6 @@ public:
SourceInitFile (bool in_cwd,
CommandReturnObject &result);
- CommandInterpreter (Debugger &debugger,
- lldb::ScriptLanguage script_language,
- bool synchronous_execution);
-
- virtual
- ~CommandInterpreter ();
-
bool
AddCommand (const char *name,
const lldb::CommandObjectSP &cmd_sp,
@@ -267,8 +265,8 @@ public:
bool include_aliases);
CommandObject *
- GetCommandObject (const char *cmd,
- StringList *matches = NULL);
+ GetCommandObject(const char *cmd,
+ StringList *matches = nullptr);
bool
CommandExists (const char *cmd);
@@ -305,7 +303,6 @@ public:
OptionArgVectorSP
GetAliasOptions (const char *alias_name);
-
bool
ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
const char *options_args,
@@ -325,20 +322,20 @@ public:
CommandReturnObject &result);
bool
- HandleCommand (const char *command_line,
- LazyBool add_to_history,
- CommandReturnObject &result,
- ExecutionContext *override_context = NULL,
- bool repeat_on_empty_command = true,
- bool no_context_switching = false);
+ HandleCommand(const char *command_line,
+ LazyBool add_to_history,
+ CommandReturnObject &result,
+ ExecutionContext *override_context = nullptr,
+ bool repeat_on_empty_command = true,
+ bool no_context_switching = false);
//------------------------------------------------------------------
/// Execute a list of commands in sequence.
///
/// @param[in] commands
/// The list of commands to execute.
- /// @param[in/out] context
- /// The execution context in which to run the commands. Can be NULL in which case the default
+ /// @param[in,out] context
+ /// The execution context in which to run the commands. Can be nullptr in which case the default
/// context will be used.
/// @param[in] options
/// This object holds the options used to control when to stop, whether to execute commands,
@@ -358,8 +355,8 @@ public:
///
/// @param[in] file
/// The file from which to read in commands.
- /// @param[in/out] context
- /// The execution context in which to run the commands. Can be NULL in which case the default
+ /// @param[in,out] context
+ /// The execution context in which to run the commands. Can be nullptr in which case the default
/// context will be used.
/// @param[in] options
/// This object holds the options used to control when to stop, whether to execute commands,
@@ -393,7 +390,6 @@ public:
// Otherwise, returns the number of matches.
//
// FIXME: Only max_return_elements == -1 is supported at present.
-
int
HandleCompletion (const char *current_line,
const char *cursor,
@@ -406,7 +402,6 @@ public:
// Help command can call it for the first argument.
// word_complete tells whether the completions are considered a "complete" response (so the
// completer should complete the quote & put a space after the word.
-
int
HandleCompletionMatches (Args &input,
int &cursor_index,
@@ -416,7 +411,6 @@ public:
bool &word_complete,
StringList &matches);
-
int
GetCommandNamesMatchingPartialString (const char *cmd_cstr,
bool include_aliases,
@@ -496,7 +490,6 @@ public:
void
SetScriptLanguage (lldb::ScriptLanguage lang);
-
bool
HasCommands ();
@@ -520,7 +513,10 @@ public:
GetOptionArgumentPosition (const char *in_string);
ScriptInterpreter *
- GetScriptInterpreter (bool can_create = true);
+ GetScriptInterpreter(bool can_create = true);
+
+ void
+ SetScriptInterpreter();
void
SkipLLDBInitFiles (bool skip_lldbinit_files)
@@ -647,7 +643,7 @@ public:
}
lldb::IOHandlerSP
- GetIOHandler(bool force_create = false, CommandInterpreterRunOptions *options = NULL);
+ GetIOHandler(bool force_create = false, CommandInterpreterRunOptions *options = nullptr);
bool
GetStoppedForCrash () const
@@ -655,26 +651,29 @@ public:
return m_stopped_for_crash;
}
+ bool
+ GetSpaceReplPrompts () const;
+
protected:
friend class Debugger;
//------------------------------------------------------------------
// IOHandlerDelegate functions
//------------------------------------------------------------------
- virtual void
- IOHandlerInputComplete (IOHandler &io_handler,
- std::string &line);
+ void
+ IOHandlerInputComplete(IOHandler &io_handler,
+ std::string &line) override;
- virtual ConstString
- IOHandlerGetControlSequence (char ch)
+ ConstString
+ IOHandlerGetControlSequence(char ch) override
{
if (ch == 'd')
return ConstString("quit\n");
return ConstString();
}
- virtual bool
- IOHandlerInterrupt (IOHandler &io_handler);
+ bool
+ IOHandlerInterrupt(IOHandler &io_handler) override;
size_t
GetProcessOutput ();
@@ -683,11 +682,9 @@ protected:
SetSynchronous (bool value);
lldb::CommandObjectSP
- GetCommandSP (const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = NULL);
-
+ GetCommandSP(const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = nullptr);
private:
-
Error
PreprocessCommand (std::string &command);
@@ -697,7 +694,6 @@ private:
CommandObject *
ResolveCommandImpl(std::string &command_line, CommandReturnObject &result);
-
Debugger &m_debugger; // The debugger session that this interpreter is associated with
ExecutionContextRef m_exe_ctx_ref; // The current execution context to use when handling commands
bool m_synchronous_execution;
@@ -709,7 +705,7 @@ private:
OptionArgMap m_alias_options; // Stores any options (with or without arguments) that go with any alias.
CommandHistory m_command_history;
std::string m_repeat_command; // Stores the command that will be executed for an empty command string.
- std::unique_ptr<ScriptInterpreter> m_script_interpreter_ap;
+ lldb::ScriptInterpreterSP m_script_interpreter_sp;
lldb::IOHandlerSP m_command_io_handler_sp;
char m_comment_char;
bool m_batch_command_mode;
@@ -719,10 +715,8 @@ private:
uint32_t m_num_errors;
bool m_quit_requested;
bool m_stopped_for_crash;
-
};
-
} // namespace lldb_private
-#endif // liblldb_CommandInterpreter_h_
+#endif // liblldb_CommandInterpreter_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObject.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObject.h
index 023de29..8015fec 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObject.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObject.h
@@ -10,11 +10,14 @@
#ifndef liblldb_CommandObject_h_
#define liblldb_CommandObject_h_
+// C Includes
+// C++ Includes
#include <map>
-#include <set>
#include <string>
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandCompletions.h"
@@ -28,7 +31,6 @@ namespace lldb_private {
class CommandObject
{
public:
-
typedef const char *(ArgumentHelpCallbackFunction) ();
struct ArgumentHelpCallback
@@ -44,9 +46,8 @@ public:
explicit operator bool() const
{
- return (help_callback != NULL);
+ return (help_callback != nullptr);
}
-
};
struct ArgumentTableEntry // Entries in the main argument information table
@@ -76,16 +77,15 @@ public:
typedef std::map<std::string, lldb::CommandObjectSP> CommandMap;
- CommandObject (CommandInterpreter &interpreter,
- const char *name,
- const char *help = NULL,
- const char *syntax = NULL,
- uint32_t flags = 0);
+ CommandObject(CommandInterpreter &interpreter,
+ const char *name,
+ const char *help = nullptr,
+ const char *syntax = nullptr,
+ uint32_t flags = 0);
virtual
~CommandObject ();
-
static const char *
GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type);
@@ -141,15 +141,15 @@ public:
IsMultiwordObject () { return false; }
virtual lldb::CommandObjectSP
- GetSubcommandSP (const char *sub_cmd, StringList *matches = NULL)
+ GetSubcommandSP(const char *sub_cmd, StringList *matches = nullptr)
{
return lldb::CommandObjectSP();
}
virtual CommandObject *
- GetSubcommandObject (const char *sub_cmd, StringList *matches = NULL)
+ GetSubcommandObject(const char *sub_cmd, StringList *matches = nullptr)
{
- return NULL;
+ return nullptr;
}
virtual void
@@ -326,7 +326,6 @@ public:
/// @return
/// The number of completions.
//------------------------------------------------------------------
-
virtual int
HandleArgumentCompletion (Args &input,
int &cursor_index,
@@ -374,13 +373,13 @@ public:
/// The complete current command line.
///
/// @return
- /// NULL if there is no special repeat command - it will use the current command line.
+ /// nullptr if there is no special repeat command - it will use the current command line.
/// Otherwise a pointer to the command to be repeated.
/// If the returned string is the empty string, the command won't be repeated.
//------------------------------------------------------------------
virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
{
- return NULL;
+ return nullptr;
}
bool
@@ -488,62 +487,61 @@ protected:
// to the specified command argument entry.
static void
AddIDsArgumentData(CommandArgumentEntry &arg, lldb::CommandArgumentType ID, lldb::CommandArgumentType IDRange);
-
};
class CommandObjectParsed : public CommandObject
{
public:
-
- CommandObjectParsed (CommandInterpreter &interpreter,
- const char *name,
- const char *help = NULL,
- const char *syntax = NULL,
- uint32_t flags = 0) :
+ CommandObjectParsed(CommandInterpreter &interpreter,
+ const char *name,
+ const char *help = nullptr,
+ const char *syntax = nullptr,
+ uint32_t flags = 0) :
CommandObject (interpreter, name, help, syntax, flags) {}
- virtual
- ~CommandObjectParsed () {};
+ ~CommandObjectParsed() override = default;
- virtual bool
- Execute (const char *args_string, CommandReturnObject &result);
+ bool
+ Execute(const char *args_string, CommandReturnObject &result) override;
protected:
virtual bool
DoExecute (Args& command,
CommandReturnObject &result) = 0;
- virtual bool
- WantsRawCommandString() { return false; };
+ bool
+ WantsRawCommandString() override
+ {
+ return false;
+ }
};
class CommandObjectRaw : public CommandObject
{
public:
-
- CommandObjectRaw (CommandInterpreter &interpreter,
- const char *name,
- const char *help = NULL,
- const char *syntax = NULL,
- uint32_t flags = 0) :
+ CommandObjectRaw(CommandInterpreter &interpreter,
+ const char *name,
+ const char *help = nullptr,
+ const char *syntax = nullptr,
+ uint32_t flags = 0) :
CommandObject (interpreter, name, help, syntax, flags) {}
- virtual
- ~CommandObjectRaw () {};
+ ~CommandObjectRaw() override = default;
- virtual bool
- Execute (const char *args_string, CommandReturnObject &result);
+ bool
+ Execute(const char *args_string, CommandReturnObject &result) override;
protected:
virtual bool
DoExecute (const char *command, CommandReturnObject &result) = 0;
- virtual bool
- WantsRawCommandString() { return true; };
+ bool
+ WantsRawCommandString() override
+ {
+ return true;
+ }
};
-
} // namespace lldb_private
-
-#endif // liblldb_CommandObject_h_
+#endif // liblldb_CommandObject_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectMultiword.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectMultiword.h
index 491d43c..e1ad294 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectMultiword.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectMultiword.h
@@ -12,8 +12,6 @@
// C Includes
// C++ Includes
-#include <map>
-
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/CommandObject.h"
@@ -30,57 +28,66 @@ class CommandObjectMultiword : public CommandObject
friend class CommandInterpreter;
friend class CommandObjectSyntax;
public:
- CommandObjectMultiword (CommandInterpreter &interpreter,
- const char *name,
- const char *help = NULL,
- const char *syntax = NULL,
- uint32_t flags = 0);
+ CommandObjectMultiword(CommandInterpreter &interpreter,
+ const char *name,
+ const char *help = nullptr,
+ const char *syntax = nullptr,
+ uint32_t flags = 0);
- virtual
- ~CommandObjectMultiword ();
+ ~CommandObjectMultiword() override;
- virtual bool
- IsMultiwordObject () { return true; }
+ bool
+ IsMultiwordObject() override
+ {
+ return true;
+ }
- virtual bool
- LoadSubCommand (const char *cmd_name,
- const lldb::CommandObjectSP& command_obj);
+ bool
+ LoadSubCommand(const char *cmd_name,
+ const lldb::CommandObjectSP& command_obj) override;
- virtual void
- GenerateHelpText (Stream &output_stream);
+ void
+ GenerateHelpText(Stream &output_stream) override;
- virtual lldb::CommandObjectSP
- GetSubcommandSP (const char *sub_cmd, StringList *matches = NULL);
+ lldb::CommandObjectSP
+ GetSubcommandSP(const char *sub_cmd, StringList *matches = nullptr) override;
- virtual CommandObject *
- GetSubcommandObject (const char *sub_cmd, StringList *matches = NULL);
-
- virtual void
- AproposAllSubCommands (const char *prefix,
- const char *search_word,
- StringList &commands_found,
- StringList &commands_help);
-
- virtual bool
- WantsRawCommandString() { return false; };
-
- virtual int
- HandleCompletion (Args &input,
- int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches);
-
- virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index);
-
- virtual bool
- Execute (const char *args_string,
- CommandReturnObject &result);
+ CommandObject *
+ GetSubcommandObject(const char *sub_cmd, StringList *matches = nullptr) override;
+
+ void
+ AproposAllSubCommands(const char *prefix,
+ const char *search_word,
+ StringList &commands_found,
+ StringList &commands_help) override;
+
+ bool
+ WantsRawCommandString() override
+ {
+ return false;
+ }
+
+ int
+ HandleCompletion(Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) override;
+
+ const char *
+ GetRepeatCommand (Args &current_command_args, uint32_t index) override;
+
+ bool
+ Execute(const char *args_string,
+ CommandReturnObject &result) override;
- virtual bool
- IsRemovable() const { return m_can_be_removed; }
+ bool
+ IsRemovable() const override
+ {
+ return m_can_be_removed;
+ }
void
SetRemovable (bool removable)
@@ -93,95 +100,93 @@ protected:
CommandObject::CommandMap m_subcommand_dict;
bool m_can_be_removed;
};
-
class CommandObjectProxy : public CommandObject
{
public:
- CommandObjectProxy (CommandInterpreter &interpreter,
- const char *name,
- const char *help = NULL,
- const char *syntax = NULL,
- uint32_t flags = 0);
+ CommandObjectProxy(CommandInterpreter &interpreter,
+ const char *name,
+ const char *help = nullptr,
+ const char *syntax = nullptr,
+ uint32_t flags = 0);
- virtual
- ~CommandObjectProxy ();
+ ~CommandObjectProxy() override;
// Subclasses must provide a command object that will be transparently
// used for this object.
virtual CommandObject *
GetProxyCommandObject() = 0;
- virtual const char *
- GetHelpLong ();
+ const char *
+ GetHelpLong() override;
- virtual bool
- IsRemovable() const;
+ bool
+ IsRemovable() const override;
- virtual bool
- IsMultiwordObject ();
-
- virtual lldb::CommandObjectSP
- GetSubcommandSP (const char *sub_cmd, StringList *matches = NULL);
-
- virtual CommandObject *
- GetSubcommandObject (const char *sub_cmd, StringList *matches = NULL);
+ bool
+ IsMultiwordObject() override;
- virtual void
- AproposAllSubCommands (const char *prefix,
- const char *search_word,
- StringList &commands_found,
- StringList &commands_help);
-
- virtual bool
- LoadSubCommand (const char *cmd_name,
- const lldb::CommandObjectSP& command_obj);
-
- virtual bool
- WantsRawCommandString();
+ void
+ GenerateHelpText (Stream &result) override;
- virtual bool
- WantsCompletion();
+ lldb::CommandObjectSP
+ GetSubcommandSP(const char *sub_cmd, StringList *matches = nullptr) override;
- virtual Options *
- GetOptions ();
+ CommandObject *
+ GetSubcommandObject(const char *sub_cmd, StringList *matches = nullptr) override;
-
- virtual int
- HandleCompletion (Args &input,
- int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches);
-
- virtual int
- HandleArgumentCompletion (Args &input,
- int &cursor_index,
- int &cursor_char_position,
- OptionElementVector &opt_element_vector,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches);
-
- virtual const char *
- GetRepeatCommand (Args &current_command_args,
- uint32_t index);
-
- virtual bool
- Execute (const char *args_string,
- CommandReturnObject &result);
+ void
+ AproposAllSubCommands(const char *prefix,
+ const char *search_word,
+ StringList &commands_found,
+ StringList &commands_help) override;
+
+ bool
+ LoadSubCommand(const char *cmd_name,
+ const lldb::CommandObjectSP& command_obj) override;
+
+ bool
+ WantsRawCommandString() override;
+
+ bool
+ WantsCompletion() override;
+
+ Options *
+ GetOptions() override;
+
+ int
+ HandleCompletion(Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) override;
+
+ int
+ HandleArgumentCompletion(Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ OptionElementVector &opt_element_vector,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) override;
+
+ const char *
+ GetRepeatCommand(Args &current_command_args,
+ uint32_t index) override;
+
+ bool
+ Execute(const char *args_string,
+ CommandReturnObject &result) override;
protected:
-
// These two want to iterate over the subcommand dictionary.
friend class CommandInterpreter;
friend class CommandObjectSyntax;
-
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectMultiword_h_
+#endif // liblldb_CommandObjectMultiword_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectRegexCommand.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectRegexCommand.h
index d865446..9f8974a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectRegexCommand.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandObjectRegexCommand.h
@@ -28,7 +28,6 @@ namespace lldb_private {
class CommandObjectRegexCommand : public CommandObjectRaw
{
public:
-
CommandObjectRegexCommand (CommandInterpreter &interpreter,
const char *name,
const char *help,
@@ -37,8 +36,7 @@ public:
uint32_t completion_type_mask,
bool is_removable);
- virtual
- ~CommandObjectRegexCommand ();
+ ~CommandObjectRegexCommand() override;
bool
IsRemovable () const override { return m_is_removable; }
@@ -83,4 +81,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_CommandObjectRegexCommand_h_
+#endif // liblldb_CommandObjectRegexCommand_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandOptionValidators.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandOptionValidators.h
index 6be247a..395cb8e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandOptionValidators.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandOptionValidators.h
@@ -10,6 +10,10 @@
#ifndef liblldb_CommandOptionValidators_h_
#define liblldb_CommandOptionValidators_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private-types.h"
namespace lldb_private {
@@ -19,12 +23,11 @@ class ExecutionContext;
class PosixPlatformCommandOptionValidator : public OptionValidator
{
- virtual bool IsValid(Platform &platform, const ExecutionContext &target) const;
- virtual const char* ShortConditionString() const;
- virtual const char* LongConditionString() const;
+ bool IsValid(Platform &platform, const ExecutionContext &target) const override;
+ const char* ShortConditionString() const override;
+ const char* LongConditionString() const override;
};
} // namespace lldb_private
-
-#endif // liblldb_CommandOptionValidators_h_
+#endif // liblldb_CommandOptionValidators_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandReturnObject.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandReturnObject.h
index b922e17..e3a1d9f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandReturnObject.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/CommandReturnObject.h
@@ -22,11 +22,9 @@
namespace lldb_private {
-
class CommandReturnObject
{
public:
-
CommandReturnObject ();
~CommandReturnObject ();
@@ -142,8 +140,8 @@ public:
AppendErrorWithFormat (const char *format, ...) __attribute__ ((format (printf, 2, 3)));
void
- SetError (const Error &error,
- const char *fallback_error_cstr = NULL);
+ SetError(const Error &error,
+ const char *fallback_error_cstr = nullptr);
void
SetError (const char *error_cstr);
@@ -171,6 +169,18 @@ public:
void
SetInteractive (bool b);
+
+ bool
+ GetAbnormalStopWasExpected() const
+ {
+ return m_abnormal_stop_was_expected;
+ }
+
+ void
+ SetAbnormalStopWasExpected(bool signal_was_expected)
+ {
+ m_abnormal_stop_was_expected = signal_was_expected;
+ }
private:
enum
@@ -184,9 +194,15 @@ private:
lldb::ReturnStatus m_status;
bool m_did_change_process_state;
- bool m_interactive; // If true, then the input handle from the debugger will be hooked up
+ bool m_interactive; // If true, then the input handle from the debugger will be hooked up
+ bool m_abnormal_stop_was_expected; // This is to support eHandleCommandFlagStopOnCrash vrs. attach.
+ // The attach command often ends up with the process stopped due to a signal.
+ // Normally that would mean stop on crash should halt batch execution, but we
+ // obviously don't want that for attach. Using this flag, the attach command
+ // (and anything else for which this is relevant) can say that the signal is
+ // expected, and batch command execution can continue.
};
} // namespace lldb_private
-#endif // liblldb_CommandReturnObject_h_
+#endif // liblldb_CommandReturnObject_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupArchitecture.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupArchitecture.h
index 7cd1ca3..5ee6085 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupArchitecture.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupArchitecture.h
@@ -26,26 +26,23 @@ namespace lldb_private {
class OptionGroupArchitecture : public OptionGroup
{
public:
-
OptionGroupArchitecture ();
- virtual
- ~OptionGroupArchitecture ();
+ ~OptionGroupArchitecture() override;
+ uint32_t
+ GetNumDefinitions() override;
- virtual uint32_t
- GetNumDefinitions ();
-
- virtual const OptionDefinition*
- GetDefinitions ();
+ const OptionDefinition*
+ GetDefinitions() override;
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
bool
GetArchitecture (Platform *platform, ArchSpec &arch);
@@ -55,19 +52,17 @@ public:
{
return !m_arch_str.empty();
}
+
const char *
- GetArchitectureName ()
+ GetArchitectureName()
{
- if (m_arch_str.empty())
- return NULL;
- return m_arch_str.c_str();
+ return (m_arch_str.empty() ? nullptr : m_arch_str.c_str());
}
protected:
-
std::string m_arch_str; // Save the arch triple in case a platform is specified after the architecture
};
} // namespace lldb_private
-#endif // liblldb_OptionGroupArchitecture_h_
+#endif // liblldb_OptionGroupArchitecture_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupBoolean.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupBoolean.h
index 0d861b2..881a1bd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupBoolean.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupBoolean.h
@@ -36,29 +36,27 @@ namespace lldb_private {
bool default_value,
bool no_argument_toggle_default);
- virtual
- ~OptionGroupBoolean ();
-
-
- virtual uint32_t
- GetNumDefinitions ()
+ ~OptionGroupBoolean() override;
+
+ uint32_t
+ GetNumDefinitions() override
{
return 1;
}
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions() override
{
return &m_option_definition;
}
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
OptionValueBoolean &
GetOptionValue ()
@@ -75,9 +73,8 @@ namespace lldb_private {
protected:
OptionValueBoolean m_value;
OptionDefinition m_option_definition;
-
};
} // namespace lldb_private
-#endif // liblldb_OptionGroupBoolean_h_
+#endif // liblldb_OptionGroupBoolean_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupFile.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupFile.h
index 632a2db..9e35dd4 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupFile.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupFile.h
@@ -1,4 +1,4 @@
-//===-- OptionGroupFile.h -------------------------------*- C++ -*-===//
+//===-- OptionGroupFile.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -27,7 +27,6 @@ namespace lldb_private {
class OptionGroupFile : public OptionGroup
{
public:
-
OptionGroupFile (uint32_t usage_mask,
bool required,
const char *long_option,
@@ -36,29 +35,27 @@ public:
lldb::CommandArgumentType argument_type,
const char *usage_text);
- virtual
- ~OptionGroupFile ();
+ ~OptionGroupFile() override;
-
- virtual uint32_t
- GetNumDefinitions ()
+ uint32_t
+ GetNumDefinitions() override
{
return 1;
}
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions() override
{
return &m_option_definition;
}
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
OptionValueFileSpec &
GetOptionValue ()
@@ -75,7 +72,6 @@ public:
protected:
OptionValueFileSpec m_file;
OptionDefinition m_option_definition;
-
};
//-------------------------------------------------------------------------
@@ -94,30 +90,27 @@ public:
lldb::CommandArgumentType argument_type,
const char *usage_text);
- virtual
- ~OptionGroupFileList ();
+ ~OptionGroupFileList() override;
-
- virtual uint32_t
- GetNumDefinitions ()
+ uint32_t
+ GetNumDefinitions() override
{
return 1;
}
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions() override
{
return &m_option_definition;
}
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
-
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
OptionValueFileSpecList &
GetOptionValue ()
@@ -134,9 +127,8 @@ public:
protected:
OptionValueFileSpecList m_file_list;
OptionDefinition m_option_definition;
-
};
} // namespace lldb_private
-#endif // liblldb_OptionGroupFile_h_
+#endif // liblldb_OptionGroupFile_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupFormat.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupFormat.h
index 7419b04..9a96cc5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupFormat.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupFormat.h
@@ -1,4 +1,4 @@
-//===-- OptionGroupFormat.h -------------------------------*- C++ -*-===//
+//===-- OptionGroupFormat.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -37,23 +37,21 @@ public:
uint64_t default_byte_size = UINT64_MAX, // Pass UINT64_MAX to disable the "--size" option
uint64_t default_count = UINT64_MAX); // Pass UINT64_MAX to disable the "--count" option
- virtual
- ~OptionGroupFormat ();
+ ~OptionGroupFormat() override;
+ uint32_t
+ GetNumDefinitions() override;
- virtual uint32_t
- GetNumDefinitions ();
+ const OptionDefinition*
+ GetDefinitions() override;
- virtual const OptionDefinition*
- GetDefinitions ();
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
-
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
lldb::Format
GetFormat () const
@@ -112,7 +110,6 @@ public:
}
protected:
-
bool
ParserGDBFormatLetter (CommandInterpreter &interpreter,
char format_letter,
@@ -124,10 +121,9 @@ protected:
OptionValueUInt64 m_count;
char m_prev_gdb_format;
char m_prev_gdb_size;
-
bool m_has_gdb_format;
};
} // namespace lldb_private
-#endif // liblldb_OptionGroupFormat_h_
+#endif // liblldb_OptionGroupFormat_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupOutputFile.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupOutputFile.h
index 533cd6e..e608371 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupOutputFile.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupOutputFile.h
@@ -1,4 +1,4 @@
-//===-- OptionGroupOutputFile.h -------------------------------*- C++ -*-===//
+//===-- OptionGroupOutputFile.h ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -26,26 +26,23 @@ namespace lldb_private {
class OptionGroupOutputFile : public OptionGroup
{
public:
-
OptionGroupOutputFile ();
- virtual
- ~OptionGroupOutputFile ();
+ ~OptionGroupOutputFile() override;
+ uint32_t
+ GetNumDefinitions() override;
- virtual uint32_t
- GetNumDefinitions ();
-
- virtual const OptionDefinition*
- GetDefinitions ();
+ const OptionDefinition*
+ GetDefinitions() override;
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
const OptionValueFileSpec &
GetFile ()
@@ -68,9 +65,8 @@ public:
protected:
OptionValueFileSpec m_file;
OptionValueBoolean m_append;
-
};
} // namespace lldb_private
-#endif // liblldb_OptionGroupOutputFile_h_
+#endif // liblldb_OptionGroupOutputFile_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupPlatform.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupPlatform.h
index f7de50c..6888023 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupPlatform.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupPlatform.h
@@ -27,7 +27,6 @@ namespace lldb_private {
class OptionGroupPlatform : public OptionGroup
{
public:
-
OptionGroupPlatform (bool include_platform_option) :
OptionGroup(),
m_platform_name (),
@@ -39,24 +38,21 @@ public:
{
}
- virtual
- ~OptionGroupPlatform ()
- {
- }
+ ~OptionGroupPlatform() override = default;
- virtual uint32_t
- GetNumDefinitions ();
+ uint32_t
+ GetNumDefinitions() override;
- virtual const OptionDefinition*
- GetDefinitions ();
+ const OptionDefinition*
+ GetDefinitions() override;
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
lldb::PlatformSP
CreatePlatformWithOptions (CommandInterpreter &interpreter,
@@ -119,4 +115,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionGroupPlatform_h_
+#endif // liblldb_OptionGroupPlatform_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupString.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupString.h
index e62a81b..6f46bdb 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupString.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupString.h
@@ -1,4 +1,4 @@
-//===-- OptionGroupString.h ------------------------------------*- C++ -*-===//
+//===-- OptionGroupString.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -25,7 +25,6 @@ namespace lldb_private {
class OptionGroupString : public OptionGroup
{
public:
-
OptionGroupString (uint32_t usage_mask,
bool required,
const char *long_option,
@@ -35,29 +34,27 @@ namespace lldb_private {
const char *usage_text,
const char *default_value);
- virtual
- ~OptionGroupString ();
-
-
- virtual uint32_t
- GetNumDefinitions ()
+ ~OptionGroupString() override;
+
+ uint32_t
+ GetNumDefinitions() override
{
return 1;
}
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions() override
{
return &m_option_definition;
}
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
OptionValueString &
GetOptionValue ()
@@ -74,9 +71,8 @@ namespace lldb_private {
protected:
OptionValueString m_value;
OptionDefinition m_option_definition;
-
};
} // namespace lldb_private
-#endif // liblldb_OptionGroupString_h_
+#endif // liblldb_OptionGroupString_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupUInt64.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupUInt64.h
index c5f9e85..b03c1ff 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupUInt64.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupUInt64.h
@@ -1,4 +1,4 @@
-//===-- OptionGroupUInt64.h ------------------------------------*- C++ -*-===//
+//===-- OptionGroupUInt64.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,6 +18,7 @@
#include "lldb/Interpreter/OptionValueUInt64.h"
namespace lldb_private {
+
//-------------------------------------------------------------------------
// OptionGroupUInt64
//-------------------------------------------------------------------------
@@ -25,7 +26,6 @@ namespace lldb_private {
class OptionGroupUInt64 : public OptionGroup
{
public:
-
OptionGroupUInt64 (uint32_t usage_mask,
bool required,
const char *long_option,
@@ -35,29 +35,27 @@ namespace lldb_private {
const char *usage_text,
uint64_t default_value);
- virtual
- ~OptionGroupUInt64 ();
-
-
- virtual uint32_t
- GetNumDefinitions ()
+ ~OptionGroupUInt64() override;
+
+ uint32_t
+ GetNumDefinitions() override
{
return 1;
}
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions() override
{
return &m_option_definition;
}
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
OptionValueUInt64 &
GetOptionValue ()
@@ -74,9 +72,8 @@ namespace lldb_private {
protected:
OptionValueUInt64 m_value;
OptionDefinition m_option_definition;
-
};
} // namespace lldb_private
-#endif // liblldb_OptionGroupUInt64_h_
+#endif // liblldb_OptionGroupUInt64_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupUUID.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupUUID.h
index ea968d7..6495699 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupUUID.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupUUID.h
@@ -18,6 +18,7 @@
#include "lldb/Interpreter/OptionValueUUID.h"
namespace lldb_private {
+
//-------------------------------------------------------------------------
// OptionGroupUUID
//-------------------------------------------------------------------------
@@ -25,26 +26,23 @@ namespace lldb_private {
class OptionGroupUUID : public OptionGroup
{
public:
-
OptionGroupUUID ();
- virtual
- ~OptionGroupUUID ();
+ ~OptionGroupUUID() override;
+ uint32_t
+ GetNumDefinitions() override;
- virtual uint32_t
- GetNumDefinitions ();
-
- virtual const OptionDefinition*
- GetDefinitions ();
+ const OptionDefinition*
+ GetDefinitions() override;
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
const OptionValueUUID &
GetOptionValue () const
@@ -58,4 +56,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionGroupUUID_h_
+#endif // liblldb_OptionGroupUUID_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
index 5cce126..53c8550 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
@@ -1,4 +1,4 @@
-//===-- OptionGroupValueObjectDisplay.h -------------------------------*- C++ -*-===//
+//===-- OptionGroupValueObjectDisplay.h -------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -26,41 +26,38 @@ namespace lldb_private {
class OptionGroupValueObjectDisplay : public OptionGroup
{
public:
-
OptionGroupValueObjectDisplay ();
- virtual
- ~OptionGroupValueObjectDisplay ();
+ ~OptionGroupValueObjectDisplay() override;
+ uint32_t
+ GetNumDefinitions() override;
- virtual uint32_t
- GetNumDefinitions ();
-
- virtual const OptionDefinition*
- GetDefinitions ();
+ const OptionDefinition*
+ GetDefinitions() override;
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
bool
AnyOptionWasSet () const
{
- return show_types == true ||
- no_summary_depth != 0 ||
- show_location == true ||
- flat_output == true ||
- use_objc == true ||
+ return show_types ||
+ no_summary_depth != 0 ||
+ show_location ||
+ flat_output ||
+ use_objc ||
max_depth != UINT32_MAX ||
ptr_depth != 0 ||
- use_synth == false ||
- be_raw == true ||
- ignore_cap == true ||
- run_validator == true;
+ !use_synth ||
+ be_raw ||
+ ignore_cap ||
+ run_validator;
}
DumpValueObjectOptions
@@ -85,4 +82,4 @@ public:
} // namespace lldb_private
-#endif // liblldb_OptionGroupValueObjectDisplay_h_
+#endif // liblldb_OptionGroupValueObjectDisplay_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupVariable.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupVariable.h
index 40f4d43..fd338f1 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupVariable.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupVariable.h
@@ -26,25 +26,23 @@ namespace lldb_private {
class OptionGroupVariable : public OptionGroup
{
public:
-
OptionGroupVariable (bool show_frame_options);
- virtual
- ~OptionGroupVariable ();
-
- virtual uint32_t
- GetNumDefinitions ();
+ ~OptionGroupVariable() override;
+
+ uint32_t
+ GetNumDefinitions() override;
- virtual const OptionDefinition*
- GetDefinitions ();
+ const OptionDefinition*
+ GetDefinitions() override;
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_arg);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
bool include_frame_options:1,
show_args:1, // Frame option only (include_frame_options == true)
@@ -62,4 +60,4 @@ namespace lldb_private {
} // namespace lldb_private
-#endif // liblldb_OptionGroupVariable_h_
+#endif // liblldb_OptionGroupVariable_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupWatchpoint.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupWatchpoint.h
index 1298da8..ddc4393 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupWatchpoint.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionGroupWatchpoint.h
@@ -25,28 +25,26 @@ namespace lldb_private {
class OptionGroupWatchpoint : public OptionGroup
{
public:
-
+ OptionGroupWatchpoint ();
+
+ ~OptionGroupWatchpoint() override;
+
static bool
IsWatchSizeSupported(uint32_t watch_size);
- OptionGroupWatchpoint ();
-
- virtual
- ~OptionGroupWatchpoint ();
-
- virtual uint32_t
- GetNumDefinitions ();
+ uint32_t
+ GetNumDefinitions() override;
- virtual const OptionDefinition*
- GetDefinitions ();
+ const OptionDefinition*
+ GetDefinitions() override;
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_arg);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
// Note:
// eWatchRead == LLDB_WATCH_TYPE_READ; and
@@ -68,4 +66,4 @@ namespace lldb_private {
} // namespace lldb_private
-#endif // liblldb_OptionGroupWatchpoint_h_
+#endif // liblldb_OptionGroupWatchpoint_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValue.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValue.h
index fd751f7..a05a0fb 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValue.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValue.h
@@ -1,4 +1,4 @@
-//===-- OptionValue.h --------------------------------------*- C++ -*-===//
+//===-- OptionValue.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -61,7 +61,6 @@ namespace lldb_private {
eDumpGroupHelp = (eDumpOptionName | eDumpOptionType | eDumpOptionDescription)
};
-
OptionValue () :
m_callback (nullptr),
m_baton(nullptr),
@@ -76,9 +75,8 @@ namespace lldb_private {
{
}
- virtual ~OptionValue ()
- {
- }
+ virtual ~OptionValue() = default;
+
//-----------------------------------------------------------------
// Subclasses should override these functions
//-----------------------------------------------------------------
@@ -99,7 +97,6 @@ namespace lldb_private {
return GetBuiltinTypeAsCString(GetType());
}
-
static const char *
GetBuiltinTypeAsCString (Type t);
@@ -156,6 +153,7 @@ namespace lldb_private {
virtual bool
DumpQualifiedName (Stream &strm) const;
+
//-----------------------------------------------------------------
// Subclasses should NOT override these functions as they use the
// above functions to implement functionality
@@ -376,7 +374,7 @@ namespace lldb_private {
SetSInt64Value (int64_t new_value);
const char *
- GetStringValue (const char *fail_value = NULL) const;
+ GetStringValue(const char *fail_value = nullptr) const;
bool
SetStringValue (const char *new_value);
@@ -415,7 +413,7 @@ namespace lldb_private {
SetValueChangedCallback (OptionValueChangedCallback callback,
void *baton)
{
- assert (m_callback == NULL);
+ assert (m_callback == nullptr);
m_callback = callback;
m_baton = baton;
}
@@ -426,6 +424,7 @@ namespace lldb_private {
if (m_callback)
m_callback (m_baton, this);
}
+
protected:
lldb::OptionValueWP m_parent_wp;
OptionValueChangedCallback m_callback;
@@ -436,9 +435,8 @@ namespace lldb_private {
// the command line or as a setting, versus if we
// just have the default value that was already
// populated in the option value.
-
};
} // namespace lldb_private
-#endif // liblldb_OptionValue_h_
+#endif // liblldb_OptionValue_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArch.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArch.h
index 3d5d726..c83dc85 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArch.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArch.h
@@ -52,8 +52,7 @@ public:
{
}
- virtual
- ~OptionValueArch()
+ ~OptionValueArch() override
{
}
@@ -61,37 +60,37 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeArch;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
- virtual size_t
- AutoComplete (CommandInterpreter &interpreter,
- const char *s,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches);
+ size_t
+ AutoComplete(CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) override;
//---------------------------------------------------------------------
// Subclass specific functions
@@ -136,4 +135,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueArch_h_
+#endif // liblldb_OptionValueArch_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArgs.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArgs.h
index 365a52a..ad9505a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArgs.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArgs.h
@@ -26,16 +26,15 @@ public:
{
}
- virtual
- ~OptionValueArgs()
+ ~OptionValueArgs() override
{
}
size_t
GetArgs (Args &args);
- virtual Type
- GetType() const
+ Type
+ GetType() const override
{
return eTypeArgs;
}
@@ -43,4 +42,4 @@ public:
} // namespace lldb_private
-#endif // liblldb_OptionValueArgs_h_
+#endif // liblldb_OptionValueArgs_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArray.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArray.h
index 2e44f9f..38b9e3c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArray.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueArray.h
@@ -30,8 +30,7 @@ public:
{
}
- virtual
- ~OptionValueArray()
+ ~OptionValueArray() override
{
}
@@ -39,41 +38,41 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeArray;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_values.clear();
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
- virtual bool
- IsAggregateValue () const
+ bool
+ IsAggregateValue() const override
{
return true;
}
- virtual lldb::OptionValueSP
- GetSubValue (const ExecutionContext *exe_ctx,
- const char *name,
- bool will_modify,
- Error &error) const;
+ lldb::OptionValueSP
+ GetSubValue(const ExecutionContext *exe_ctx,
+ const char *name,
+ bool will_modify,
+ Error &error) const override;
//---------------------------------------------------------------------
// Subclass specific functions
@@ -175,4 +174,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueArray_h_
+#endif // liblldb_OptionValueArray_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueBoolean.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueBoolean.h
index 214fd16..52d39a9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueBoolean.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueBoolean.h
@@ -35,8 +35,7 @@ public:
{
}
- virtual
- ~OptionValueBoolean()
+ ~OptionValueBoolean() override
{
}
@@ -44,34 +43,34 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeBoolean;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
- virtual size_t
- AutoComplete (CommandInterpreter &interpreter,
- const char *s,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches);
+ size_t
+ AutoComplete(CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) override;
//---------------------------------------------------------------------
// Subclass specific functions
@@ -128,8 +127,8 @@ public:
m_default_value = value;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
protected:
bool m_current_value;
@@ -138,4 +137,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueBoolean_h_
+#endif // liblldb_OptionValueBoolean_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueChar.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueChar.h
index 8fc0209..b05d9ca 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueChar.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueChar.h
@@ -27,6 +27,7 @@ public:
m_default_value (value)
{
}
+
OptionValueChar (char current_value,
char default_value) :
OptionValue(),
@@ -35,8 +36,7 @@ public:
{
}
- virtual
- ~OptionValueChar()
+ ~OptionValueChar() override
{
}
@@ -44,21 +44,21 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeChar;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_current_value = m_default_value;
m_value_was_set = false;
@@ -100,8 +100,8 @@ public:
m_default_value = value;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
protected:
char m_current_value;
@@ -110,4 +110,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueChar_h_
+#endif // liblldb_OptionValueChar_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueDictionary.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueDictionary.h
index efa15dd..8ee8397 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueDictionary.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueDictionary.h
@@ -31,8 +31,7 @@ public:
{
}
- virtual
- ~OptionValueDictionary()
+ ~OptionValueDictionary() override
{
}
@@ -40,32 +39,32 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeDictionary;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_values.clear();
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
- virtual bool
- IsAggregateValue () const
+ bool
+ IsAggregateValue() const override
{
return true;
}
@@ -89,17 +88,17 @@ public:
lldb::OptionValueSP
GetValueForKey (const ConstString &key) const;
- virtual lldb::OptionValueSP
- GetSubValue (const ExecutionContext *exe_ctx,
- const char *name,
- bool will_modify,
- Error &error) const;
-
- virtual Error
- SetSubValue (const ExecutionContext *exe_ctx,
- VarSetOperationType op,
- const char *name,
- const char *value);
+ lldb::OptionValueSP
+ GetSubValue(const ExecutionContext *exe_ctx,
+ const char *name,
+ bool will_modify,
+ Error &error) const override;
+
+ Error
+ SetSubValue(const ExecutionContext *exe_ctx,
+ VarSetOperationType op,
+ const char *name,
+ const char *value) override;
//---------------------------------------------------------------------
// String value getters and setters
@@ -136,4 +135,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueDictionary_h_
+#endif // liblldb_OptionValueDictionary_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueEnumeration.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueEnumeration.h
index e820729..b3fc481 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueEnumeration.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueEnumeration.h
@@ -23,7 +23,6 @@
namespace lldb_private {
-
class OptionValueEnumeration : public OptionValue
{
public:
@@ -38,44 +37,43 @@ public:
OptionValueEnumeration (const OptionEnumValueElement *enumerators, enum_type value);
- virtual
- ~OptionValueEnumeration();
+ ~OptionValueEnumeration() override;
//---------------------------------------------------------------------
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeEnum;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
- virtual size_t
- AutoComplete (CommandInterpreter &interpreter,
- const char *s,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches);
+ size_t
+ AutoComplete(CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) override;
//---------------------------------------------------------------------
// Subclass specific functions
@@ -123,4 +121,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueEnumeration_h_
+#endif // liblldb_OptionValueEnumeration_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpec.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpec.h
index 80dd77e..274c4d0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpec.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpec.h
@@ -31,8 +31,7 @@ public:
const FileSpec &default_value,
bool resolve = true);
- virtual
- ~OptionValueFileSpec()
+ ~OptionValueFileSpec() override
{
}
@@ -40,21 +39,21 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeFileSpec;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_current_value = m_default_value;
m_value_was_set = false;
@@ -63,16 +62,16 @@ public:
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
- virtual size_t
- AutoComplete (CommandInterpreter &interpreter,
- const char *s,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches);
+ size_t
+ AutoComplete(CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) override;
//---------------------------------------------------------------------
// Subclass specific functions
@@ -131,4 +130,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueFileSpec_h_
+#endif // liblldb_OptionValueFileSpec_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpecList.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpecList.h
index a105d22..2051323 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpecList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFileSpecList.h
@@ -34,9 +34,7 @@ public:
{
}
-
- virtual
- ~OptionValueFileSpecList()
+ ~OptionValueFileSpecList() override
{
}
@@ -44,32 +42,32 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeFileSpecList;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_current_value.Clear();
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
- virtual bool
- IsAggregateValue () const
+ bool
+ IsAggregateValue() const override
{
return true;
}
@@ -102,4 +100,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueFileSpecList_h_
+#endif // liblldb_OptionValueFileSpecList_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormat.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormat.h
index 06ed128..1c29094 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormat.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormat.h
@@ -36,8 +36,7 @@ public:
{
}
- virtual
- ~OptionValueFormat()
+ ~OptionValueFormat() override
{
}
@@ -45,29 +44,29 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeFormat;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
//---------------------------------------------------------------------
// Subclass specific functions
@@ -104,4 +103,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueFormat_h_
+#endif // liblldb_OptionValueFormat_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h
index 18ace3a..10a456a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h
@@ -24,8 +24,7 @@ class OptionValueFormatEntity : public OptionValue
public:
OptionValueFormatEntity (const char *default_format);
- virtual
- ~OptionValueFormatEntity()
+ ~OptionValueFormatEntity() override
{
}
@@ -94,7 +93,6 @@ public:
return m_default_entry;
}
-
protected:
std::string m_current_format;
std::string m_default_format;
@@ -104,4 +102,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueFormatEntity_h_
+#endif // liblldb_OptionValueFormatEntity_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueLanguage.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueLanguage.h
index fba5e22..bd6df3e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueLanguage.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueLanguage.h
@@ -37,8 +37,7 @@ public:
{
}
- virtual
- ~OptionValueLanguage ()
+ ~OptionValueLanguage() override
{
}
@@ -104,4 +103,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueLanguage_h_
+#endif // liblldb_OptionValueLanguage_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValuePathMappings.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValuePathMappings.h
index 7b476a9..4ed1c8c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValuePathMappings.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValuePathMappings.h
@@ -29,8 +29,7 @@ public:
{
}
- virtual
- ~OptionValuePathMappings()
+ ~OptionValuePathMappings() override
{
}
@@ -38,32 +37,32 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypePathMap;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_path_mappings.Clear(m_notify_changes);
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
- virtual bool
- IsAggregateValue () const
+ bool
+ IsAggregateValue() const override
{
return true;
}
@@ -91,4 +90,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValuePathMappings_h_
+#endif // liblldb_OptionValuePathMappings_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueProperties.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueProperties.h
index 405beef..c8783bc 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueProperties.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueProperties.h
@@ -1,4 +1,4 @@
-//===-- OptionValueProperties.h --------------------------------------*- C++ -*-===//
+//===-- OptionValueProperties.h ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <vector>
+
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ConstString.h"
@@ -27,10 +29,6 @@ class OptionValueProperties :
public std::enable_shared_from_this<OptionValueProperties>
{
public:
-
- //---------------------------------------------------------------------
- // OptionValueProperties
- //---------------------------------------------------------------------
OptionValueProperties () :
OptionValue(),
m_name (),
@@ -42,34 +40,32 @@ public:
OptionValueProperties (const ConstString &name);
OptionValueProperties (const OptionValueProperties &global_properties);
-
- virtual
- ~OptionValueProperties()
- {
- }
-
- virtual Type
- GetType () const
+
+ ~OptionValueProperties() override = default;
+
+ Type
+ GetType() const override
{
return eTypeProperties;
}
- virtual bool
- Clear ();
+ bool
+ Clear() override;
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
- virtual Error
- SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual void
- DumpValue (const ExecutionContext *exe_ctx,
- Stream &strm,
- uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx,
+ Stream &strm,
+ uint32_t dump_mask) override;
- virtual ConstString
- GetName () const
+ ConstString
+ GetName() const override
{
return m_name;
}
@@ -149,16 +145,16 @@ public:
bool value_will_be_modified) const;
lldb::OptionValueSP
- GetSubValue (const ExecutionContext *exe_ctx,
- const char *name,
- bool value_will_be_modified,
- Error &error) const;
+ GetSubValue(const ExecutionContext *exe_ctx,
+ const char *name,
+ bool value_will_be_modified,
+ Error &error) const override;
- virtual Error
- SetSubValue (const ExecutionContext *exe_ctx,
- VarSetOperationType op,
- const char *path,
- const char *value);
+ Error
+ SetSubValue(const ExecutionContext *exe_ctx,
+ VarSetOperationType op,
+ const char *path,
+ const char *value) override;
virtual bool
PredicateMatches (const ExecutionContext *exe_ctx,
@@ -171,6 +167,9 @@ public:
OptionValueArch *
GetPropertyAtIndexAsOptionValueArch (const ExecutionContext *exe_ctx, uint32_t idx) const;
+ OptionValueLanguage *
+ GetPropertyAtIndexAsOptionValueLanguage (const ExecutionContext *exe_ctx, uint32_t idx) const;
+
bool
GetPropertyAtIndexAsArgs (const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const;
@@ -251,22 +250,18 @@ public:
SetValueChangedCallback (uint32_t property_idx,
OptionValueChangedCallback callback,
void *baton);
-protected:
+protected:
Property *
- ProtectedGetPropertyAtIndex (uint32_t idx)
+ ProtectedGetPropertyAtIndex(uint32_t idx)
{
- if (idx < m_properties.size())
- return &m_properties[idx];
- return NULL;
+ return ((idx < m_properties.size()) ? &m_properties[idx] : nullptr);
}
const Property *
- ProtectedGetPropertyAtIndex (uint32_t idx) const
+ ProtectedGetPropertyAtIndex(uint32_t idx) const
{
- if (idx < m_properties.size())
- return &m_properties[idx];
- return NULL;
+ return ((idx < m_properties.size()) ? &m_properties[idx] : nullptr);
}
typedef UniqueCStringMap<size_t> NameToIndex;
@@ -278,4 +273,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueProperties_h_
+#endif // liblldb_OptionValueProperties_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueRegex.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueRegex.h
index 5e04218..a094a40 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueRegex.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueRegex.h
@@ -12,8 +12,6 @@
// C Includes
// C++ Includes
-#include <string>
-
// Other libraries and framework includes
// Project includes
#include "lldb/Core/RegularExpression.h"
@@ -24,44 +22,41 @@ namespace lldb_private {
class OptionValueRegex : public OptionValue
{
public:
- OptionValueRegex (const char *value = NULL) :
+ OptionValueRegex(const char *value = nullptr) :
OptionValue(),
m_regex (value)
{
}
- virtual
- ~OptionValueRegex()
- {
- }
-
+ ~OptionValueRegex() override = default;
+
//---------------------------------------------------------------------
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeRegex;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_regex.Clear();
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
//---------------------------------------------------------------------
// Subclass specific functions
@@ -69,9 +64,7 @@ public:
const RegularExpression *
GetCurrentValue() const
{
- if (m_regex.IsValid())
- return &m_regex;
- return NULL;
+ return (m_regex.IsValid() ? &m_regex : nullptr);
}
void
@@ -95,4 +88,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueRegex_h_
+#endif // liblldb_OptionValueRegex_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueSInt64.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueSInt64.h
index 36ae97c..8c8b201 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueSInt64.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueSInt64.h
@@ -58,8 +58,7 @@ public:
{
}
- virtual
- ~OptionValueSInt64()
+ ~OptionValueSInt64() override
{
}
@@ -67,29 +66,29 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeSInt64;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
//---------------------------------------------------------------------
// Subclass specific functions
@@ -169,4 +168,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueSInt64_h_
+#endif // liblldb_OptionValueSInt64_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueString.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueString.h
index c75745d..bbdd0c8 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueString.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueString.h
@@ -1,4 +1,4 @@
-//===-- OptionValueString.h --------------------------------------*- C++ -*-===//
+//===-- OptionValueString.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -24,7 +24,6 @@ namespace lldb_private {
class OptionValueString : public OptionValue
{
public:
-
typedef Error (*ValidatorCallback) (const char* string,
void* baton);
@@ -43,8 +42,8 @@ public:
{
}
- OptionValueString (ValidatorCallback validator,
- void* baton = NULL) :
+ OptionValueString(ValidatorCallback validator,
+ void* baton = nullptr) :
OptionValue(),
m_current_value (),
m_default_value (),
@@ -84,9 +83,9 @@ public:
m_default_value.assign (default_value);
}
- OptionValueString (const char *value,
- ValidatorCallback validator,
- void* baton = NULL) :
+ OptionValueString(const char *value,
+ ValidatorCallback validator,
+ void* baton = nullptr) :
OptionValue(),
m_current_value (),
m_default_value (),
@@ -101,10 +100,10 @@ public:
}
}
- OptionValueString (const char *current_value,
- const char *default_value,
- ValidatorCallback validator,
- void* baton = NULL) :
+ OptionValueString(const char *current_value,
+ const char *default_value,
+ ValidatorCallback validator,
+ void* baton = nullptr) :
OptionValue(),
m_current_value (),
m_default_value (),
@@ -118,38 +117,35 @@ public:
m_default_value.assign (default_value);
}
- virtual
- ~OptionValueString()
- {
- }
-
+ ~OptionValueString() override = default;
+
//---------------------------------------------------------------------
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeString;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
//---------------------------------------------------------------------
// Subclass specific functions
@@ -213,7 +209,6 @@ public:
return m_default_value.empty();
}
-
protected:
std::string m_current_value;
std::string m_default_value;
@@ -224,4 +219,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueString_h_
+#endif // liblldb_OptionValueString_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUInt64.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUInt64.h
index 51ff881..874e8ca 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUInt64.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUInt64.h
@@ -43,8 +43,7 @@ public:
{
}
- virtual
- ~OptionValueUInt64()
+ ~OptionValueUInt64() override
{
}
@@ -60,29 +59,29 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeUInt64;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_current_value = m_default_value;
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
//---------------------------------------------------------------------
// Subclass specific functions
@@ -131,4 +130,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueUInt64_h_
+#endif // liblldb_OptionValueUInt64_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUUID.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUUID.h
index c6ab48a..4aecc39 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUUID.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/OptionValueUUID.h
@@ -34,8 +34,7 @@ public:
{
}
- virtual
- ~OptionValueUUID()
+ ~OptionValueUUID() override
{
}
@@ -43,29 +42,29 @@ public:
// Virtual subclass pure virtual overrides
//---------------------------------------------------------------------
- virtual OptionValue::Type
- GetType () const
+ OptionValue::Type
+ GetType() const override
{
return eTypeUUID;
}
- virtual void
- DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask);
+ void
+ DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
- virtual Error
- SetValueFromString (llvm::StringRef value,
- VarSetOperationType op = eVarSetOperationAssign);
+ Error
+ SetValueFromString(llvm::StringRef value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
- virtual bool
- Clear ()
+ bool
+ Clear() override
{
m_uuid.Clear();
m_value_was_set = false;
return true;
}
- virtual lldb::OptionValueSP
- DeepCopy () const;
+ lldb::OptionValueSP
+ DeepCopy() const override;
//---------------------------------------------------------------------
// Subclass specific functions
@@ -89,13 +88,13 @@ public:
m_uuid = value;
}
- virtual size_t
- AutoComplete (CommandInterpreter &interpreter,
- const char *s,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches);
+ size_t
+ AutoComplete(CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) override;
protected:
UUID m_uuid;
@@ -103,4 +102,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_OptionValueUUID_h_
+#endif // liblldb_OptionValueUUID_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/Options.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/Options.h
index 6ecf08d..bac2630 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/Options.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/Options.h
@@ -11,7 +11,6 @@
#define liblldb_Options_h_
// C Includes
-
// C++ Includes
#include <set>
#include <vector>
@@ -32,7 +31,6 @@ namespace lldb_private {
return isprint(ch);
}
-
//----------------------------------------------------------------------
/// @class Options Options.h "lldb/Interpreter/Options.h"
/// @brief A command line option parsing protocol class.
@@ -72,7 +70,7 @@ namespace lldb_private {
/// case 'g': debug = true; break;
/// case 'v': verbose = true; break;
/// case 'l': log_file = option_arg; break;
-/// case 'f': log_flags = strtoull(option_arg, NULL, 0); break;
+/// case 'f': log_flags = strtoull(option_arg, nullptr, 0); break;
/// default:
/// error.SetErrorStringWithFormat("unrecognized short option %c", option_val);
/// break;
@@ -95,11 +93,11 @@ namespace lldb_private {
///
/// struct option CommandOptions::g_options[] =
/// {
-/// { "debug", no_argument, NULL, 'g' },
-/// { "log-file", required_argument, NULL, 'l' },
-/// { "log-flags", required_argument, NULL, 'f' },
-/// { "verbose", no_argument, NULL, 'v' },
-/// { NULL, 0, NULL, 0 }
+/// { "debug", no_argument, nullptr, 'g' },
+/// { "log-file", required_argument, nullptr, 'l' },
+/// { "log-flags", required_argument, nullptr, 'f' },
+/// { "verbose", no_argument, nullptr, 'v' },
+/// { nullptr, 0, nullptr, 0 }
/// };
///
/// int main (int argc, const char **argv, const char **envp)
@@ -119,7 +117,6 @@ namespace lldb_private {
class Options
{
public:
-
Options (CommandInterpreter &interpreter);
virtual
@@ -153,7 +150,6 @@ public:
// Verify that the options given are in the options table and can
// be used together, but there may be some required options that are
// missing (used to verify options that get folded into command aliases).
-
bool
VerifyPartialOptions (CommandReturnObject &result);
@@ -173,7 +169,10 @@ public:
// class that inherits from this class.
virtual const OptionDefinition*
- GetDefinitions () { return NULL; }
+ GetDefinitions()
+ {
+ return nullptr;
+ }
// Call this prior to parsing any options. This call will call the
// subclass OptionParsingStarting() and will avoid the need for all
@@ -195,7 +194,7 @@ public:
///
/// @param[in] option_arg
/// The argument value for the option that the user entered, or
- /// NULL if there is no argument for the current option.
+ /// nullptr if there is no argument for the current option.
///
///
/// @see Args::ParseOptions (Options&)
@@ -359,15 +358,11 @@ protected:
class OptionGroup
{
public:
- OptionGroup ()
- {
- }
-
+ OptionGroup() = default;
+
virtual
- ~OptionGroup ()
- {
- }
-
+ ~OptionGroup() = default;
+
virtual uint32_t
GetNumDefinitions () = 0;
@@ -395,7 +390,6 @@ protected:
class OptionGroupOptions : public Options
{
public:
-
OptionGroupOptions (CommandInterpreter &interpreter) :
Options (interpreter),
m_option_defs (),
@@ -404,12 +398,8 @@ protected:
{
}
- virtual
- ~OptionGroupOptions ()
- {
- }
-
-
+ ~OptionGroupOptions() override = default;
+
//----------------------------------------------------------------------
/// Append options from a OptionGroup class.
///
@@ -459,18 +449,18 @@ protected:
return m_did_finalize;
}
- virtual Error
- SetOptionValue (uint32_t option_idx,
- const char *option_arg);
+ Error
+ SetOptionValue(uint32_t option_idx,
+ const char *option_arg) override;
- virtual void
- OptionParsingStarting ();
+ void
+ OptionParsingStarting() override;
- virtual Error
- OptionParsingFinished ();
+ Error
+ OptionParsingFinished() override;
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions() override
{
assert (m_did_finalize);
return &m_option_defs[0];
@@ -495,8 +485,7 @@ protected:
OptionInfos m_option_infos;
bool m_did_finalize;
};
-
} // namespace lldb_private
-#endif // liblldb_Options_h_
+#endif // liblldb_Options_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/PythonDataObjects.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/PythonDataObjects.h
deleted file mode 100644
index df281b5..0000000
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/PythonDataObjects.h
+++ /dev/null
@@ -1,280 +0,0 @@
-//===-- PythonDataObjects.h----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_PythonDataObjects_h_
-#define liblldb_PythonDataObjects_h_
-
-// C Includes
-// C++ Includes
-
-// Other libraries and framework includes
-// Project includes
-#include "lldb/lldb-defines.h"
-#include "lldb/Core/ConstString.h"
-#include "lldb/Core/StructuredData.h"
-#include "lldb/Core/Flags.h"
-#include "lldb/Interpreter/OptionValue.h"
-#include "lldb/lldb-python.h"
-
-namespace lldb_private {
-class PythonString;
-class PythonList;
-class PythonDictionary;
-class PythonObject;
-class PythonInteger;
-
-class StructuredPythonObject : public StructuredData::Generic
-{
- public:
- StructuredPythonObject()
- : StructuredData::Generic()
- {
- }
-
- StructuredPythonObject(void *obj)
- : StructuredData::Generic(obj)
- {
- Py_XINCREF(GetValue());
- }
-
- virtual ~StructuredPythonObject()
- {
- if (Py_IsInitialized())
- Py_XDECREF(GetValue());
- SetValue(nullptr);
- }
-
- bool
- IsValid() const override
- {
- return GetValue() && GetValue() != Py_None;
- }
-
- void Dump(Stream &s) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
-};
-
-enum class PyObjectType
-{
- Unknown,
- None,
- Integer,
- Dictionary,
- List,
- String
-};
-
- class PythonObject
- {
- public:
- PythonObject () :
- m_py_obj(NULL)
- {
- }
-
- explicit PythonObject (PyObject* py_obj) :
- m_py_obj(NULL)
- {
- Reset (py_obj);
- }
-
- PythonObject (const PythonObject &rhs) :
- m_py_obj(NULL)
- {
- Reset (rhs.m_py_obj);
- }
-
- virtual
- ~PythonObject ()
- {
- Reset (NULL);
- }
-
- bool
- Reset (const PythonObject &object)
- {
- return Reset(object.get());
- }
-
- virtual bool
- Reset (PyObject* py_obj = NULL)
- {
- if (py_obj != m_py_obj)
- {
- if (Py_IsInitialized())
- Py_XDECREF(m_py_obj);
- m_py_obj = py_obj;
- if (Py_IsInitialized())
- Py_XINCREF(m_py_obj);
- }
- return true;
- }
-
- void
- Dump () const
- {
- if (m_py_obj)
- _PyObject_Dump (m_py_obj);
- else
- puts ("NULL");
- }
-
- void
- Dump (Stream &strm) const;
-
- PyObject*
- get () const
- {
- return m_py_obj;
- }
-
- PyObjectType GetObjectType() const;
-
- PythonString
- Repr ();
-
- PythonString
- Str ();
-
- explicit operator bool () const
- {
- return m_py_obj != NULL;
- }
-
- bool
- IsNULLOrNone () const;
-
- StructuredData::ObjectSP CreateStructuredObject() const;
-
- protected:
- PyObject* m_py_obj;
- };
-
- class PythonString: public PythonObject
- {
- public:
- PythonString ();
- PythonString (PyObject *o);
- PythonString (const PythonObject &object);
- PythonString (llvm::StringRef string);
- PythonString (const char *string);
- virtual ~PythonString ();
-
- virtual bool
- Reset (PyObject* py_obj = NULL);
-
- llvm::StringRef
- GetString() const;
-
- size_t
- GetSize() const;
-
- void SetString(llvm::StringRef string);
-
- StructuredData::StringSP CreateStructuredString() const;
- };
-
- class PythonInteger: public PythonObject
- {
- public:
-
- PythonInteger ();
- PythonInteger (PyObject* py_obj);
- PythonInteger (const PythonObject &object);
- PythonInteger (int64_t value);
- virtual ~PythonInteger ();
-
- virtual bool
- Reset (PyObject* py_obj = NULL);
-
- int64_t GetInteger() const;
-
- void
- SetInteger (int64_t value);
-
- StructuredData::IntegerSP CreateStructuredInteger() const;
- };
-
- class PythonList: public PythonObject
- {
- public:
-
- PythonList (bool create_empty);
- PythonList (PyObject* py_obj);
- PythonList (const PythonObject &object);
- PythonList (uint32_t count);
- virtual ~PythonList ();
-
- virtual bool
- Reset (PyObject* py_obj = NULL);
-
- uint32_t GetSize() const;
-
- PythonObject GetItemAtIndex(uint32_t index) const;
-
- void
- SetItemAtIndex (uint32_t index, const PythonObject &object);
-
- void
- AppendItem (const PythonObject &object);
-
- StructuredData::ArraySP CreateStructuredArray() const;
- };
-
- class PythonDictionary: public PythonObject
- {
- public:
-
- explicit PythonDictionary (bool create_empty);
- PythonDictionary (PyObject* object);
- PythonDictionary (const PythonObject &object);
- virtual ~PythonDictionary ();
-
- virtual bool
- Reset (PyObject* object = NULL);
-
- uint32_t GetSize() const;
-
- PythonObject
- GetItemForKey (const PythonString &key) const;
-
- const char *
- GetItemForKeyAsString (const PythonString &key, const char *fail_value = NULL) const;
-
- int64_t
- GetItemForKeyAsInteger (const PythonString &key, int64_t fail_value = 0) const;
-
- PythonObject
- GetItemForKey (const char *key) const;
-
- typedef bool (*DictionaryIteratorCallback)(PythonString* key, PythonDictionary* dict);
-
- PythonList
- GetKeys () const;
-
- PythonString
- GetKeyAtPosition (uint32_t pos) const;
-
- PythonObject
- GetValueAtPosition (uint32_t pos) const;
-
- void
- SetItemForKey (const PythonString &key, PyObject *value);
-
- void
- SetItemForKey (const PythonString &key, const PythonObject& value);
-
- StructuredData::DictionarySP CreateStructuredDictionary() const;
- };
-
-} // namespace lldb_private
-
-#endif // liblldb_PythonDataObjects_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 0f45dd8..eafc03a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -10,37 +10,36 @@
#ifndef liblldb_ScriptInterpreter_h_
#define liblldb_ScriptInterpreter_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Error.h"
+#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Utility/PseudoTerminal.h"
-
namespace lldb_private {
class ScriptInterpreterLocker
{
public:
- ScriptInterpreterLocker ()
- {
- }
+ ScriptInterpreterLocker() = default;
- virtual ~ScriptInterpreterLocker ()
- {
- }
+ virtual ~ScriptInterpreterLocker() = default;
+
private:
DISALLOW_COPY_AND_ASSIGN (ScriptInterpreterLocker);
};
-
-class ScriptInterpreter
+class ScriptInterpreter : public PluginInterface
{
public:
-
typedef enum
{
eScriptReturnTypeCharPtr,
@@ -62,7 +61,7 @@ public:
ScriptInterpreter (CommandInterpreter &interpreter, lldb::ScriptLanguage script_lang);
- virtual ~ScriptInterpreter ();
+ ~ScriptInterpreter() override;
struct ExecuteScriptOptions
{
@@ -174,13 +173,13 @@ public:
}
virtual bool
- GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token = NULL)
+ GenerateTypeScriptFunction(const char* oneliner, std::string& output, const void* name_token = nullptr)
{
return false;
}
virtual bool
- GenerateTypeScriptFunction (StringList &input, std::string& output, const void* name_token = NULL)
+ GenerateTypeScriptFunction(StringList &input, std::string& output, const void* name_token = nullptr)
{
return false;
}
@@ -192,13 +191,13 @@ public:
}
virtual bool
- GenerateTypeSynthClass (StringList &input, std::string& output, const void* name_token = NULL)
+ GenerateTypeSynthClass(StringList &input, std::string& output, const void* name_token = nullptr)
{
return false;
}
virtual bool
- GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token = NULL)
+ GenerateTypeSynthClass(const char* oneliner, std::string& output, const void* name_token = nullptr)
{
return false;
}
@@ -324,7 +323,6 @@ public:
SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options,
const char *function_name)
{
- return;
}
/// Set a one-liner as the callback for the watchpoint.
@@ -332,7 +330,6 @@ public:
SetWatchpointCommandCallback (WatchpointOptions *wp_options,
const char *oneliner)
{
- return;
}
virtual bool
@@ -349,7 +346,7 @@ public:
}
virtual size_t
- CalculateNumChildren(const StructuredData::ObjectSP &implementor)
+ CalculateNumChildren(const StructuredData::ObjectSP &implementor, uint32_t max)
{
return 0;
}
@@ -459,7 +456,7 @@ public:
virtual bool
GetDocumentationForItem (const char* item, std::string& dest)
{
- dest.clear();
+ dest.clear();
return false;
}
@@ -514,8 +511,8 @@ public:
int
GetMasterFileDescriptor ();
- CommandInterpreter &
- GetCommandInterpreter ();
+ CommandInterpreter &
+ GetCommandInterpreter();
static std::string
LanguageToString (lldb::ScriptLanguage language);
@@ -530,4 +527,4 @@ protected:
} // namespace lldb_private
-#endif // #ifndef liblldb_ScriptInterpreter_h_
+#endif // liblldb_ScriptInterpreter_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreterNone.h b/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreterNone.h
deleted file mode 100644
index 6c82b60..0000000
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreterNone.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===-- ScriptInterpreterNone.h ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ScriptInterpreterNone_h_
-#define liblldb_ScriptInterpreterNone_h_
-
-#include "lldb/Interpreter/ScriptInterpreter.h"
-
-namespace lldb_private {
-
-class ScriptInterpreterNone : public ScriptInterpreter
-{
-public:
-
- ScriptInterpreterNone (CommandInterpreter &interpreter);
-
- ~ScriptInterpreterNone ();
-
- bool
- ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options = ExecuteScriptOptions());
-
- void
- ExecuteInterpreterLoop ();
-
-};
-
-} // namespace lldb_private
-
-#endif // #ifndef liblldb_ScriptInterpreterNone_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ArmUnwindInfo.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ArmUnwindInfo.h
new file mode 100644
index 0000000..b19af23
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ArmUnwindInfo.h
@@ -0,0 +1,77 @@
+//===-- ArmUnwindInfo.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ArmUnwindInfo_h_
+#define liblldb_ArmUnwindInfo_h_
+
+#include <vector>
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RangeMap.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/lldb-private.h"
+
+/*
+ * Unwind information reader and parser for the ARM exception handling ABI
+ *
+ * Implemented based on:
+ * Exception Handling ABI for the ARM Architecture
+ * Document number: ARM IHI 0038A (current through ABI r2.09)
+ * Date of Issue: 25th January 2007, reissued 30th November 2012
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
+ */
+
+namespace lldb_private {
+
+class ArmUnwindInfo
+{
+public:
+ ArmUnwindInfo(const ObjectFile& objfile,
+ lldb::SectionSP& arm_exidx,
+ lldb::SectionSP& arm_extab);
+
+ ~ArmUnwindInfo();
+
+ bool
+ GetUnwindPlan(Target &target, const Address& addr, UnwindPlan& unwind_plan);
+
+private:
+ struct ArmExidxEntry
+ {
+ ArmExidxEntry(uint32_t f, lldb::addr_t a, uint32_t d);
+
+ bool
+ operator<(const ArmExidxEntry& other) const;
+
+ uint32_t file_address;
+ lldb::addr_t address;
+ uint32_t data;
+ };
+
+ const uint8_t*
+ GetExceptionHandlingTableEntry(const Address& addr);
+
+ uint8_t
+ GetByteAtOffset(const uint32_t* data, uint16_t offset) const;
+
+ uint64_t
+ GetULEB128(const uint32_t* data, uint16_t& offset, uint16_t max_offset) const;
+
+ const lldb::ByteOrder m_byte_order;
+ lldb::SectionSP m_arm_exidx_sp; // .ARM.exidx section
+ lldb::SectionSP m_arm_extab_sp; // .ARM.extab section
+ DataExtractor m_arm_exidx_data; // .ARM.exidx section data
+ DataExtractor m_arm_extab_data; // .ARM.extab section data
+ std::vector<ArmExidxEntry> m_exidx_entries;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ArmUnwindInfo_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Block.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Block.h
index 59671b0..6c0793d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Block.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Block.h
@@ -10,6 +10,12 @@
#ifndef liblldb_Block_h_
#define liblldb_Block_h_
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/RangeMap.h"
@@ -17,7 +23,7 @@
#include "lldb/Core/UserID.h"
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Symbol/SymbolContext.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
namespace lldb_private {
@@ -76,7 +82,7 @@ public:
//------------------------------------------------------------------
/// Destructor.
//------------------------------------------------------------------
- virtual ~Block ();
+ ~Block() override;
//------------------------------------------------------------------
/// Add a child to this object.
@@ -110,20 +116,20 @@ public:
///
/// @see SymbolContextScope
//------------------------------------------------------------------
- virtual void
- CalculateSymbolContext(SymbolContext* sc);
+ void
+ CalculateSymbolContext(SymbolContext* sc) override;
- virtual lldb::ModuleSP
- CalculateSymbolContextModule ();
+ lldb::ModuleSP
+ CalculateSymbolContextModule() override;
- virtual CompileUnit *
- CalculateSymbolContextCompileUnit ();
+ CompileUnit *
+ CalculateSymbolContextCompileUnit() override;
- virtual Function *
- CalculateSymbolContextFunction ();
+ Function *
+ CalculateSymbolContextFunction() override;
- virtual Block *
- CalculateSymbolContextBlock ();
+ Block *
+ CalculateSymbolContextBlock() override;
//------------------------------------------------------------------
/// Check if an offset is in one of the block offset ranges.
@@ -192,8 +198,8 @@ public:
///
/// @see SymbolContextScope
//------------------------------------------------------------------
- virtual void
- DumpSymbolContext(Stream *s);
+ void
+ DumpSymbolContext(Stream *s) override;
void
DumpAddressRanges (Stream *s,
@@ -209,20 +215,19 @@ public:
/// Get the parent block.
///
/// @return
- /// The parent block pointer, or NULL if this block has no
+ /// The parent block pointer, or nullptr if this block has no
/// parent.
//------------------------------------------------------------------
Block *
GetParent () const;
-
//------------------------------------------------------------------
/// Get the inlined block that contains this block.
///
/// @return
/// If this block contains inlined function info, it will return
/// this block, else parent blocks will be searched to see if
- /// any contain this block. NULL will be returned if this block
+ /// any contain this block. nullptr will be returned if this block
/// nor any parent blocks are inlined function blocks.
//------------------------------------------------------------------
Block *
@@ -232,7 +237,7 @@ public:
/// Get the inlined parent block for this block.
///
/// @return
- /// The parent block pointer, or NULL if this block has no
+ /// The parent block pointer, or nullptr if this block has no
/// parent.
//------------------------------------------------------------------
Block *
@@ -242,7 +247,7 @@ public:
/// Get the sibling block for this block.
///
/// @return
- /// The sibling block pointer, or NULL if this block has no
+ /// The sibling block pointer, or nullptr if this block has no
/// sibling.
//------------------------------------------------------------------
Block *
@@ -252,15 +257,13 @@ public:
/// Get the first child block.
///
/// @return
- /// The first child block pointer, or NULL if this block has no
+ /// The first child block pointer, or nullptr if this block has no
/// children.
//------------------------------------------------------------------
Block *
GetFirstChild () const
{
- if (m_children.empty())
- return NULL;
- return m_children.front().get();
+ return (m_children.empty() ? nullptr : m_children.front().get());
}
//------------------------------------------------------------------
@@ -278,7 +281,6 @@ public:
lldb::VariableListSP
GetBlockVariableList (bool can_create);
-
//------------------------------------------------------------------
/// Get the variable list for this block and optionally all child
/// blocks if \a get_child_variables is \b true.
@@ -330,7 +332,7 @@ public:
/// added to the variable list until there are no parent blocks
/// or the parent block has inlined function info.
///
- /// @param[in/out] variable_list
+ /// @param[in,out] variable_list
/// All variables in this block, and optionally all parent
/// blocks will be added to this list.
///
@@ -348,7 +350,7 @@ public:
/// Get const accessor for any inlined function information.
///
/// @return
- /// A const pointer to any inlined function information, or NULL
+ /// A const pointer to any inlined function information, or nullptr
/// if this is a regular block.
//------------------------------------------------------------------
const InlineFunctionInfo*
@@ -357,8 +359,8 @@ public:
return m_inlineInfoSP.get();
}
- clang::DeclContext *
- GetClangDeclContext();
+ CompilerDeclContext
+ GetDeclContext();
//------------------------------------------------------------------
/// Get the memory cost of this object.
@@ -377,16 +379,16 @@ public:
///
/// @param[in] name
/// The method name for the inlined function. This value should
- /// not be NULL.
+ /// not be nullptr.
///
/// @param[in] mangled
/// The mangled method name for the inlined function. This can
- /// be NULL if there is no mangled name for an inlined function
+ /// be nullptr if there is no mangled name for an inlined function
/// or if the name is the same as \a name.
///
/// @param[in] decl_ptr
/// A optional pointer to declaration information for the
- /// inlined function information. This value can be NULL to
+ /// inlined function information. This value can be nullptr to
/// indicate that no declaration information is available.
///
/// @param[in] call_decl_ptr
@@ -399,7 +401,6 @@ public:
const Declaration *decl_ptr,
const Declaration *call_decl_ptr);
-
void
SetParentScope (SymbolContextScope *parent_scope)
{
@@ -422,8 +423,6 @@ public:
m_variable_list_sp = variable_list_sp;
}
-
-
bool
BlockInfoHasBeenParsed() const
{
@@ -491,7 +490,6 @@ private:
DISALLOW_COPY_AND_ASSIGN (Block);
};
-
} // namespace lldb_private
-#endif // liblldb_Block_h_
+#endif // liblldb_Block_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTContext.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTContext.h
index a411e42..bd3a113 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTContext.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTContext.h
@@ -14,7 +14,11 @@
#include <stdint.h>
// C++ Includes
+#include <functional>
#include <initializer_list>
+#include <map>
+#include <memory>
+#include <set>
#include <string>
#include <vector>
#include <utility>
@@ -24,36 +28,71 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/TemplateBase.h"
-
// Project includes
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/ConstString.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/TypeSystem.h"
namespace lldb_private {
class Declaration;
-class ClangASTContext
+class ClangASTContext : public TypeSystem
{
public:
typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *);
typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton, clang::ObjCInterfaceDecl *);
-
+
+ //------------------------------------------------------------------
+ // llvm casting support
+ //------------------------------------------------------------------
+ static bool classof(const TypeSystem *ts)
+ {
+ return ts->getKind() == TypeSystem::eKindClang;
+ }
+
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- ClangASTContext (const char *triple = NULL);
+ ClangASTContext(const char *triple = nullptr);
+
+ ~ClangASTContext() override;
+
+ //------------------------------------------------------------------
+ // PluginInterface functions
+ //------------------------------------------------------------------
+ ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+
+ static ConstString
+ GetPluginNameStatic ();
- ~ClangASTContext();
+ static lldb::TypeSystemSP
+ CreateInstance (lldb::LanguageType language, Module *module, Target *target);
+ static void
+ EnumerateSupportedLanguages(std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
static ClangASTContext*
GetASTContext (clang::ASTContext* ast_ctx);
clang::ASTContext *
getASTContext();
-
+
+ void setASTContext(clang::ASTContext* ast_ctx);
+
clang::Builtin::Context *
getBuiltinContext();
@@ -78,6 +117,9 @@ public:
clang::DiagnosticConsumer *
getDiagnosticConsumer();
+ clang::MangleContext *
+ getMangleContext();
+
std::shared_ptr<clang::TargetOptions> &getTargetOptions();
clang::TargetInfo *
@@ -109,7 +151,16 @@ public:
{
return ClangASTContext::GetCompleteDecl(getASTContext(), decl);
}
-
+
+ static void
+ DumpDeclHiearchy (clang::Decl *decl);
+
+ static void
+ DumpDeclContextHiearchy (clang::DeclContext *decl_ctx);
+
+ static bool
+ DeclsAreEquivalent (clang::Decl *lhs_decl, clang::Decl *rhs_decl);
+
static bool
GetCompleteDecl (clang::ASTContext *ast,
clang::Decl *decl);
@@ -141,47 +192,53 @@ public:
//------------------------------------------------------------------
// Basic Types
//------------------------------------------------------------------
- ClangASTType
+ CompilerType
GetBuiltinTypeForEncodingAndBitSize (lldb::Encoding encoding,
- uint32_t bit_size);
+ size_t bit_size) override;
- static ClangASTType
+ static CompilerType
GetBuiltinTypeForEncodingAndBitSize (clang::ASTContext *ast,
lldb::Encoding encoding,
uint32_t bit_size);
- ClangASTType
+ CompilerType
GetBasicType (lldb::BasicType type);
- static ClangASTType
+ static CompilerType
GetBasicType (clang::ASTContext *ast, lldb::BasicType type);
- static ClangASTType
+ static CompilerType
GetBasicType (clang::ASTContext *ast, const ConstString &name);
static lldb::BasicType
GetBasicTypeEnumeration (const ConstString &name);
- ClangASTType
+ CompilerType
GetBuiltinTypeForDWARFEncodingAndBitSize (
const char *type_name,
uint32_t dw_ate,
uint32_t bit_size);
- ClangASTType
+ CompilerType
GetCStringType(bool is_const);
- static ClangASTType
+ static CompilerType
GetUnknownAnyType(clang::ASTContext *ast);
- ClangASTType
+ CompilerType
GetUnknownAnyType()
{
return ClangASTContext::GetUnknownAnyType(getASTContext());
}
+ static clang::DeclContext *
+ GetDeclContextForType (clang::QualType type);
+
+ static clang::DeclContext *
+ GetDeclContextForType (const CompilerType& type);
+
uint32_t
- GetPointerByteSize ();
+ GetPointerByteSize () override;
static clang::DeclContext *
GetTranslationUnitDecl (clang::ASTContext *ast);
@@ -192,40 +249,30 @@ public:
return GetTranslationUnitDecl (getASTContext());
}
- static bool
- GetClassMethodInfoForDeclContext (clang::DeclContext *decl_ctx,
- lldb::LanguageType &language,
- bool &is_instance_method,
- ConstString &language_object_name);
-
- static ClangASTType
- CopyType(clang::ASTContext *dest_context,
- ClangASTType source_type);
-
static clang::Decl *
CopyDecl (clang::ASTContext *dest_context,
clang::ASTContext *source_context,
clang::Decl *source_decl);
static bool
- AreTypesSame(ClangASTType type1,
- ClangASTType type2,
+ AreTypesSame(CompilerType type1,
+ CompilerType type2,
bool ignore_qualifiers = false);
- static ClangASTType
+ static CompilerType
GetTypeForDecl (clang::NamedDecl *decl);
- static ClangASTType
+ static CompilerType
GetTypeForDecl (clang::TagDecl *decl);
- static ClangASTType
+ static CompilerType
GetTypeForDecl (clang::ObjCInterfaceDecl *objc_decl);
template <typename RecordDeclType>
- ClangASTType
+ CompilerType
GetTypeForIdentifier (const ConstString &type_name)
{
- ClangASTType clang_type;
+ CompilerType compiler_type;
if (type_name.GetLength())
{
@@ -241,17 +288,17 @@ public:
{
clang::NamedDecl *named_decl = result[0];
if (const RecordDeclType *record_decl = llvm::dyn_cast<RecordDeclType>(named_decl))
- clang_type.SetClangType(ast, clang::QualType(record_decl->getTypeForDecl(), 0));
+ compiler_type.SetCompilerType(ast, clang::QualType(record_decl->getTypeForDecl(), 0));
}
}
}
- return clang_type;
+ return compiler_type;
}
- ClangASTType
+ CompilerType
GetOrCreateStructForIdentifier (const ConstString &type_name,
- const std::initializer_list< std::pair < const char *, ClangASTType > >& type_fields,
+ const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields,
bool packed = false);
//------------------------------------------------------------------
@@ -268,18 +315,13 @@ public:
GetNumBaseClasses (const clang::CXXRecordDecl *cxx_record_decl,
bool omit_empty_base_classes);
- static uint32_t
- GetIndexForRecordBase (const clang::RecordDecl *record_decl,
- const clang::CXXBaseSpecifier *base_spec,
- bool omit_empty_base_classes);
-
- ClangASTType
- CreateRecordType (clang::DeclContext *decl_ctx,
- lldb::AccessType access_type,
- const char *name,
- int kind,
- lldb::LanguageType language,
- ClangASTMetadata *metadata = NULL);
+ CompilerType
+ CreateRecordType(clang::DeclContext *decl_ctx,
+ lldb::AccessType access_type,
+ const char *name,
+ int kind,
+ lldb::LanguageType language,
+ ClangASTMetadata *metadata = nullptr);
class TemplateParameterInfos
{
@@ -328,7 +370,7 @@ public:
int kind,
const TemplateParameterInfos &infos);
- ClangASTType
+ CompilerType
CreateClassTemplateSpecializationType (clang::ClassTemplateSpecializationDecl *class_template_specialization_decl);
static clang::DeclContext *
@@ -354,17 +396,24 @@ public:
static bool
RecordHasFields (const clang::RecordDecl *record_decl);
-
- ClangASTType
- CreateObjCClass (const char *name,
- clang::DeclContext *decl_ctx,
- bool isForwardDecl,
- bool isInternal,
- ClangASTMetadata *metadata = NULL);
+ CompilerType
+ CreateObjCClass(const char *name,
+ clang::DeclContext *decl_ctx,
+ bool isForwardDecl,
+ bool isInternal,
+ ClangASTMetadata *metadata = nullptr);
+
+ bool
+ SetTagTypeKind (clang::QualType type, int kind) const;
+
+ bool
+ SetDefaultAccessForRecordFields (clang::RecordDecl* record_decl,
+ int default_accessibility,
+ int *assigned_accessibilities,
+ size_t num_assigned_accessibilities);
// Returns a mask containing bits from the ClangASTContext::eTypeXXX enumerations
-
//------------------------------------------------------------------
// Namespace Declarations
//------------------------------------------------------------------
@@ -380,21 +429,21 @@ public:
clang::FunctionDecl *
CreateFunctionDeclaration (clang::DeclContext *decl_ctx,
const char *name,
- const ClangASTType &function_Type,
+ const CompilerType &function_Type,
int storage,
bool is_inline);
- static ClangASTType
+ static CompilerType
CreateFunctionType (clang::ASTContext *ast,
- const ClangASTType &result_type,
- const ClangASTType *args,
+ const CompilerType &result_type,
+ const CompilerType *args,
unsigned num_args,
bool is_variadic,
unsigned type_quals);
- ClangASTType
- CreateFunctionType (const ClangASTType &result_type,
- const ClangASTType *args,
+ CompilerType
+ CreateFunctionType (const CompilerType &result_type,
+ const CompilerType *args,
unsigned num_args,
bool is_variadic,
unsigned type_quals)
@@ -409,7 +458,7 @@ public:
clang::ParmVarDecl *
CreateParameterDeclaration (const char *name,
- const ClangASTType &param_type,
+ const CompilerType &param_type,
int storage);
void
@@ -421,57 +470,735 @@ public:
// Array Types
//------------------------------------------------------------------
- ClangASTType
- CreateArrayType (const ClangASTType &element_type,
+ CompilerType
+ CreateArrayType (const CompilerType &element_type,
size_t element_count,
bool is_vector);
//------------------------------------------------------------------
// Enumeration Types
//------------------------------------------------------------------
- ClangASTType
+ CompilerType
CreateEnumerationType (const char *name,
clang::DeclContext *decl_ctx,
const Declaration &decl,
- const ClangASTType &integer_qual_type);
+ const CompilerType &integer_qual_type);
//------------------------------------------------------------------
// Integer type functions
//------------------------------------------------------------------
-
- ClangASTType
- GetIntTypeFromBitSize (size_t bit_size, bool is_signed)
- {
- return GetIntTypeFromBitSize (getASTContext(), bit_size, is_signed);
- }
-
- static ClangASTType
+
+ static CompilerType
GetIntTypeFromBitSize (clang::ASTContext *ast,
size_t bit_size, bool is_signed);
- ClangASTType
+ CompilerType
GetPointerSizedIntType (bool is_signed)
{
return GetPointerSizedIntType (getASTContext(), is_signed);
}
- static ClangASTType
+ static CompilerType
GetPointerSizedIntType (clang::ASTContext *ast, bool is_signed);
//------------------------------------------------------------------
// Floating point functions
//------------------------------------------------------------------
+
+ static CompilerType
+ GetFloatTypeFromBitSize (clang::ASTContext *ast,
+ size_t bit_size);
+
+ //------------------------------------------------------------------
+ // TypeSystem methods
+ //------------------------------------------------------------------
+ DWARFASTParser *
+ GetDWARFParser () override;
+
+ //------------------------------------------------------------------
+ // ClangASTContext callbacks for external source lookups.
+ //------------------------------------------------------------------
+ static void
+ CompleteTagDecl (void *baton, clang::TagDecl *);
+
+ static void
+ CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *);
+
+ static bool
+ LayoutRecordType(void *baton,
+ const clang::RecordDecl *record_decl,
+ uint64_t &size,
+ uint64_t &alignment,
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
+
+ //----------------------------------------------------------------------
+ // CompilerDecl override functions
+ //----------------------------------------------------------------------
+ lldb::VariableSP
+ DeclGetVariable (void *opaque_decl) override;
+
+ void
+ DeclLinkToObject (void *opaque_decl, std::shared_ptr<void> object) override;
+
+ ConstString
+ DeclGetName (void *opaque_decl) override;
+
+ ConstString
+ DeclGetMangledName (void *opaque_decl) override;
+
+ CompilerDeclContext
+ DeclGetDeclContext (void *opaque_decl) override;
+
+ CompilerType
+ DeclGetFunctionReturnType(void *opaque_decl) override;
+
+ size_t
+ DeclGetFunctionNumArguments(void *opaque_decl) override;
+
+ CompilerType
+ DeclGetFunctionArgumentType (void *opaque_decl, size_t arg_idx) override;
+
+ //----------------------------------------------------------------------
+ // CompilerDeclContext override functions
+ //----------------------------------------------------------------------
+
+ std::vector<CompilerDecl>
+ DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name) override;
+
+ bool
+ DeclContextIsStructUnionOrClass (void *opaque_decl_ctx) override;
+
+ ConstString
+ DeclContextGetName (void *opaque_decl_ctx) override;
+
+ ConstString
+ DeclContextGetScopeQualifiedName (void *opaque_decl_ctx) override;
+
+ bool
+ DeclContextIsClassMethod (void *opaque_decl_ctx,
+ lldb::LanguageType *language_ptr,
+ bool *is_instance_method_ptr,
+ ConstString *language_object_name_ptr) override;
+
+ //----------------------------------------------------------------------
+ // Clang specific CompilerType predicates
+ //----------------------------------------------------------------------
- ClangASTType
- GetFloatTypeFromBitSize (size_t bit_size)
+ static bool
+ IsClangType (const CompilerType &ct)
{
- return GetFloatTypeFromBitSize (getASTContext(), bit_size);
+ return llvm::dyn_cast_or_null<ClangASTContext>(ct.GetTypeSystem()) != nullptr && ct.GetOpaqueQualType() != nullptr;
}
- static ClangASTType
- GetFloatTypeFromBitSize (clang::ASTContext *ast,
- size_t bit_size);
+ //----------------------------------------------------------------------
+ // Clang specific clang::DeclContext functions
+ //----------------------------------------------------------------------
+
+ static clang::DeclContext *
+ DeclContextGetAsDeclContext (const CompilerDeclContext &dc);
+
+ static clang::ObjCMethodDecl *
+ DeclContextGetAsObjCMethodDecl (const CompilerDeclContext &dc);
+
+ static clang::CXXMethodDecl *
+ DeclContextGetAsCXXMethodDecl (const CompilerDeclContext &dc);
+
+ static clang::FunctionDecl *
+ DeclContextGetAsFunctionDecl (const CompilerDeclContext &dc);
+
+ static clang::NamespaceDecl *
+ DeclContextGetAsNamespaceDecl (const CompilerDeclContext &dc);
+
+ static ClangASTMetadata *
+ DeclContextGetMetaData (const CompilerDeclContext &dc, const void *object);
+
+ static clang::ASTContext *
+ DeclContextGetClangASTContext (const CompilerDeclContext &dc);
+
+ //----------------------------------------------------------------------
+ // Tests
+ //----------------------------------------------------------------------
+
+ bool
+ IsArrayType (lldb::opaque_compiler_type_t type,
+ CompilerType *element_type,
+ uint64_t *size,
+ bool *is_incomplete) override;
+
+ bool
+ IsVectorType (lldb::opaque_compiler_type_t type,
+ CompilerType *element_type,
+ uint64_t *size) override;
+
+ bool
+ IsAggregateType (lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsAnonymousType (lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsBeingDefined (lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsCharType (lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsCompleteType (lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsConst(lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsCStringType (lldb::opaque_compiler_type_t type, uint32_t &length) override;
+
+ static bool
+ IsCXXClassType (const CompilerType& type);
+
+ bool
+ IsDefined(lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsFloatingPointType (lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) override;
+
+ bool
+ IsFunctionType (lldb::opaque_compiler_type_t type, bool *is_variadic_ptr) override;
+
+ uint32_t
+ IsHomogeneousAggregate (lldb::opaque_compiler_type_t type, CompilerType* base_type_ptr) override;
+
+ size_t
+ GetNumberOfFunctionArguments (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ GetFunctionArgumentAtIndex (lldb::opaque_compiler_type_t type, const size_t index) override;
+
+ bool
+ IsFunctionPointerType (lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_signed) override;
+
+ static bool
+ IsObjCClassType (const CompilerType& type);
+
+ static bool
+ IsObjCClassTypeAndHasIVars (const CompilerType& type, bool check_superclass);
+
+ static bool
+ IsObjCObjectOrInterfaceType (const CompilerType& type);
+
+ static bool
+ IsObjCObjectPointerType(const CompilerType& type, CompilerType *target_type = nullptr);
+
+ bool
+ IsPolymorphicClass (lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
+ CompilerType *target_type, // Can pass nullptr
+ bool check_cplusplus,
+ bool check_objc) override;
+
+ bool
+ IsRuntimeGeneratedType (lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsPointerType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type) override;
+
+ bool
+ IsPointerOrReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type) override;
+
+ bool
+ IsReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool* is_rvalue) override;
+
+ bool
+ IsScalarType (lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsTypedefType (lldb::opaque_compiler_type_t type) override;
+
+ bool
+ IsVoidType (lldb::opaque_compiler_type_t type) override;
+
+ bool
+ SupportsLanguage (lldb::LanguageType language) override;
+
+ static bool
+ GetCXXClassName (const CompilerType& type, std::string &class_name);
+
+ static bool
+ GetObjCClassName (const CompilerType& type, std::string &class_name);
+
+ //----------------------------------------------------------------------
+ // Type Completion
+ //----------------------------------------------------------------------
+
+ bool
+ GetCompleteType (lldb::opaque_compiler_type_t type) override;
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+
+ ConstString
+ GetTypeName (lldb::opaque_compiler_type_t type) override;
+
+ uint32_t
+ GetTypeInfo (lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type) override;
+
+ lldb::LanguageType
+ GetMinimumLanguage (lldb::opaque_compiler_type_t type) override;
+
+ lldb::TypeClass
+ GetTypeClass (lldb::opaque_compiler_type_t type) override;
+
+ unsigned
+ GetTypeQualifiers(lldb::opaque_compiler_type_t type) override;
+
+ //----------------------------------------------------------------------
+ // Creating related types
+ //----------------------------------------------------------------------
+
+ // Using the current type, create a new typedef to that type using "typedef_name"
+ // as the name and "decl_ctx" as the decl context.
+ static CompilerType
+ CreateTypedefType (const CompilerType& type,
+ const char *typedef_name,
+ const CompilerDeclContext &compiler_decl_ctx);
+
+ CompilerType
+ GetArrayElementType (lldb::opaque_compiler_type_t type, uint64_t *stride) override;
+
+ CompilerType
+ GetCanonicalType (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ GetFullyUnqualifiedType (lldb::opaque_compiler_type_t type) override;
+
+ // Returns -1 if this isn't a function of if the function doesn't have a prototype
+ // Returns a value >= 0 if there is a prototype.
+ int
+ GetFunctionArgumentCount (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ GetFunctionArgumentTypeAtIndex (lldb::opaque_compiler_type_t type, size_t idx) override;
+
+ CompilerType
+ GetFunctionReturnType (lldb::opaque_compiler_type_t type) override;
+
+ size_t
+ GetNumMemberFunctions (lldb::opaque_compiler_type_t type) override;
+
+ TypeMemberFunctionImpl
+ GetMemberFunctionAtIndex (lldb::opaque_compiler_type_t type, size_t idx) override;
+
+ CompilerType
+ GetNonReferenceType (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ GetPointeeType (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ GetPointerType (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ GetLValueReferenceType (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ GetRValueReferenceType (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ AddConstModifier (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ AddVolatileModifier (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ AddRestrictModifier (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ CreateTypedef (lldb::opaque_compiler_type_t type, const char *name, const CompilerDeclContext &decl_ctx) override;
+
+ // If the current object represents a typedef type, get the underlying type
+ CompilerType
+ GetTypedefedType (lldb::opaque_compiler_type_t type) override;
+
+ static CompilerType
+ RemoveFastQualifiers (const CompilerType& type);
+
+ //----------------------------------------------------------------------
+ // Create related types using the current type's AST
+ //----------------------------------------------------------------------
+ CompilerType
+ GetBasicTypeFromAST (lldb::BasicType basic_type) override;
+
+ //----------------------------------------------------------------------
+ // Exploring the type
+ //----------------------------------------------------------------------
+
+ uint64_t
+ GetByteSize (lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope)
+ {
+ return (GetBitSize (type, exe_scope) + 7) / 8;
+ }
+
+ uint64_t
+ GetBitSize (lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) override;
+
+ lldb::Encoding
+ GetEncoding (lldb::opaque_compiler_type_t type, uint64_t &count) override;
+
+ lldb::Format
+ GetFormat (lldb::opaque_compiler_type_t type) override;
+
+ size_t
+ GetTypeBitAlign (lldb::opaque_compiler_type_t type) override;
+
+ uint32_t
+ GetNumChildren (lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) override;
+
+ CompilerType
+ GetBuiltinTypeByName (const ConstString &name) override;
+
+ lldb::BasicType
+ GetBasicTypeEnumeration (lldb::opaque_compiler_type_t type) override;
+
+ static lldb::BasicType
+ GetBasicTypeEnumeration (lldb::opaque_compiler_type_t type, const ConstString &name);
+
+ void
+ ForEachEnumerator (lldb::opaque_compiler_type_t type, std::function <bool (const CompilerType &integer_type, const ConstString &name, const llvm::APSInt &value)> const &callback) override;
+
+ uint32_t
+ GetNumFields (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ GetFieldAtIndex (lldb::opaque_compiler_type_t type,
+ size_t idx,
+ std::string& name,
+ uint64_t *bit_offset_ptr,
+ uint32_t *bitfield_bit_size_ptr,
+ bool *is_bitfield_ptr) override;
+
+ uint32_t
+ GetNumDirectBaseClasses (lldb::opaque_compiler_type_t type) override;
+
+ uint32_t
+ GetNumVirtualBaseClasses (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ GetDirectBaseClassAtIndex (lldb::opaque_compiler_type_t type,
+ size_t idx,
+ uint32_t *bit_offset_ptr) override;
+
+ CompilerType
+ GetVirtualBaseClassAtIndex (lldb::opaque_compiler_type_t type,
+ size_t idx,
+ uint32_t *bit_offset_ptr) override;
+
+ static uint32_t
+ GetNumPointeeChildren (clang::QualType type);
+
+ CompilerType
+ GetChildCompilerTypeAtIndex (lldb::opaque_compiler_type_t type,
+ ExecutionContext *exe_ctx,
+ size_t idx,
+ bool transparent_pointers,
+ bool omit_empty_base_classes,
+ bool ignore_array_bounds,
+ std::string& child_name,
+ uint32_t &child_byte_size,
+ int32_t &child_byte_offset,
+ uint32_t &child_bitfield_bit_size,
+ uint32_t &child_bitfield_bit_offset,
+ bool &child_is_base_class,
+ bool &child_is_deref_of_parent,
+ ValueObject *valobj,
+ uint64_t &language_flags) override;
+
+ // Lookup a child given a name. This function will match base class names
+ // and member member names in "clang_type" only, not descendants.
+ uint32_t
+ GetIndexOfChildWithName (lldb::opaque_compiler_type_t type,
+ const char *name,
+ bool omit_empty_base_classes) override;
+
+ // Lookup a child member given a name. This function will match member names
+ // only and will descend into "clang_type" children in search for the first
+ // member in this class, or any base class that matches "name".
+ // TODO: Return all matches for a given name by returning a vector<vector<uint32_t>>
+ // so we catch all names that match a given child name, not just the first.
+ size_t
+ GetIndexOfChildMemberWithName (lldb::opaque_compiler_type_t type,
+ const char *name,
+ bool omit_empty_base_classes,
+ std::vector<uint32_t>& child_indexes) override;
+
+ size_t
+ GetNumTemplateArguments (lldb::opaque_compiler_type_t type) override;
+
+ CompilerType
+ GetTemplateArgument (lldb::opaque_compiler_type_t type,
+ size_t idx,
+ lldb::TemplateArgumentKind &kind) override;
+
+ CompilerType
+ GetTypeForFormatters (void* type) override;
+
+#define LLDB_INVALID_DECL_LEVEL UINT32_MAX
+ // LLDB_INVALID_DECL_LEVEL is returned by CountDeclLevels if
+ // child_decl_ctx could not be found in decl_ctx.
+ uint32_t
+ CountDeclLevels (clang::DeclContext *frame_decl_ctx,
+ clang::DeclContext *child_decl_ctx,
+ ConstString *child_name = nullptr,
+ CompilerType *child_type = nullptr);
+
+ //----------------------------------------------------------------------
+ // Modifying RecordType
+ //----------------------------------------------------------------------
+ static clang::FieldDecl *
+ AddFieldToRecordType (const CompilerType& type,
+ const char *name,
+ const CompilerType &field_type,
+ lldb::AccessType access,
+ uint32_t bitfield_bit_size);
+
+ static void
+ BuildIndirectFields (const CompilerType& type);
+
+ static void
+ SetIsPacked (const CompilerType& type);
+
+ static clang::VarDecl *
+ AddVariableToRecordType (const CompilerType& type,
+ const char *name,
+ const CompilerType &var_type,
+ lldb::AccessType access);
+
+ clang::CXXMethodDecl *
+ AddMethodToCXXRecordType (lldb::opaque_compiler_type_t type,
+ const char *name,
+ const CompilerType &method_type,
+ lldb::AccessType access,
+ bool is_virtual,
+ bool is_static,
+ bool is_inline,
+ bool is_explicit,
+ bool is_attr_used,
+ bool is_artificial);
+
+ // C++ Base Classes
+ clang::CXXBaseSpecifier *
+ CreateBaseClassSpecifier (lldb::opaque_compiler_type_t type,
+ lldb::AccessType access,
+ bool is_virtual,
+ bool base_of_class);
+
+ static void
+ DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes,
+ unsigned num_base_classes);
+
+ bool
+ SetBaseClassesForClassType (lldb::opaque_compiler_type_t type,
+ clang::CXXBaseSpecifier const * const *base_classes,
+ unsigned num_base_classes);
+
+ static bool
+ SetObjCSuperClass (const CompilerType& type,
+ const CompilerType &superclass_compiler_type);
+
+ static bool
+ AddObjCClassProperty (const CompilerType& type,
+ const char *property_name,
+ const CompilerType &property_compiler_type,
+ clang::ObjCIvarDecl *ivar_decl,
+ const char *property_setter_name,
+ const char *property_getter_name,
+ uint32_t property_attributes,
+ ClangASTMetadata *metadata);
+
+ static clang::ObjCMethodDecl *
+ AddMethodToObjCObjectType (const CompilerType& type,
+ const char *name, // the full symbol name as seen in the symbol table (lldb::opaque_compiler_type_t type, "-[NString stringWithCString:]")
+ const CompilerType &method_compiler_type,
+ lldb::AccessType access,
+ bool is_artificial);
+
+ static bool
+ SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool has_extern);
+
+
+ static bool
+ CanImport (const CompilerType &type, lldb_private::ClangASTImporter &importer);
+
+ static bool
+ Import (const CompilerType &type, lldb_private::ClangASTImporter &importer);
+
+ static bool
+ GetHasExternalStorage (const CompilerType &type);
+ //------------------------------------------------------------------
+ // Tag Declarations
+ //------------------------------------------------------------------
+ static bool
+ StartTagDeclarationDefinition (const CompilerType &type);
+
+ static bool
+ CompleteTagDeclarationDefinition (const CompilerType &type);
+
+ //----------------------------------------------------------------------
+ // Modifying Enumeration types
+ //----------------------------------------------------------------------
+ bool
+ AddEnumerationValueToEnumerationType (lldb::opaque_compiler_type_t type,
+ const CompilerType &enumerator_qual_type,
+ const Declaration &decl,
+ const char *name,
+ int64_t enum_value,
+ uint32_t enum_value_bit_size);
+
+ CompilerType
+ GetEnumerationIntegerType (lldb::opaque_compiler_type_t type);
+
+ //------------------------------------------------------------------
+ // Pointers & References
+ //------------------------------------------------------------------
+
+ // Call this function using the class type when you want to make a
+ // member pointer type to pointee_type.
+ static CompilerType
+ CreateMemberPointerType (const CompilerType& type, const CompilerType &pointee_type);
+
+ // Converts "s" to a floating point value and place resulting floating
+ // point bytes in the "dst" buffer.
+ size_t
+ ConvertStringToFloatValue (lldb::opaque_compiler_type_t type,
+ const char *s,
+ uint8_t *dst,
+ size_t dst_size) override;
+
+ //----------------------------------------------------------------------
+ // Dumping types
+ //----------------------------------------------------------------------
+ void
+ DumpValue (lldb::opaque_compiler_type_t type,
+ ExecutionContext *exe_ctx,
+ Stream *s,
+ lldb::Format format,
+ const DataExtractor &data,
+ lldb::offset_t data_offset,
+ size_t data_byte_size,
+ uint32_t bitfield_bit_size,
+ uint32_t bitfield_bit_offset,
+ bool show_types,
+ bool show_summary,
+ bool verbose,
+ uint32_t depth) override;
+
+ bool
+ DumpTypeValue (lldb::opaque_compiler_type_t type,
+ Stream *s,
+ lldb::Format format,
+ const DataExtractor &data,
+ lldb::offset_t data_offset,
+ size_t data_byte_size,
+ uint32_t bitfield_bit_size,
+ uint32_t bitfield_bit_offset,
+ ExecutionContextScope *exe_scope) override;
+
+ void
+ DumpSummary (lldb::opaque_compiler_type_t type,
+ ExecutionContext *exe_ctx,
+ Stream *s,
+ const DataExtractor &data,
+ lldb::offset_t data_offset,
+ size_t data_byte_size) override;
+
+ void
+ DumpTypeDescription (lldb::opaque_compiler_type_t type) override; // Dump to stdout
+
+ void
+ DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream *s) override;
+
+ static void
+ DumpTypeName (const CompilerType &type);
+
+ static clang::EnumDecl *
+ GetAsEnumDecl (const CompilerType& type);
+
+ static clang::RecordDecl *
+ GetAsRecordDecl (const CompilerType& type);
+
+ static clang::TagDecl *
+ GetAsTagDecl (const CompilerType& type);
+
+ clang::CXXRecordDecl *
+ GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type);
+
+ static clang::ObjCInterfaceDecl *
+ GetAsObjCInterfaceDecl (const CompilerType& type);
+
+ static clang::QualType
+ GetQualType (const CompilerType& type)
+ {
+ // Make sure we have a clang type before making a clang::QualType
+ if (type.GetOpaqueQualType())
+ {
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
+ if (ast)
+ return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType());
+ }
+ return clang::QualType();
+ }
+
+ static clang::QualType
+ GetCanonicalQualType (const CompilerType& type)
+ {
+ // Make sure we have a clang type before making a clang::QualType
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
+ if (ast)
+ return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType()).getCanonicalType();
+ return clang::QualType();
+ }
+
+ clang::ClassTemplateDecl *
+ ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
+ lldb::AccessType access_type,
+ const char *parent_name,
+ int tag_decl_kind,
+ const ClangASTContext::TemplateParameterInfos &template_param_infos);
+
+ clang::BlockDecl *
+ CreateBlockDeclaration (clang::DeclContext *ctx);
+
+ clang::UsingDirectiveDecl *
+ CreateUsingDirectiveDeclaration (clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl);
+
+ clang::UsingDecl *
+ CreateUsingDeclaration (clang::DeclContext *current_decl_ctx, clang::NamedDecl *target);
+
+ clang::VarDecl *
+ CreateVariableDeclaration (clang::DeclContext *decl_context, const char *name, clang::QualType type);
+
protected:
+ static clang::QualType
+ GetQualType (lldb::opaque_compiler_type_t type)
+ {
+ if (type)
+ return clang::QualType::getFromOpaquePtr(type);
+ return clang::QualType();
+ }
+
+ static clang::QualType
+ GetCanonicalQualType (lldb::opaque_compiler_type_t type)
+ {
+ if (type)
+ return clang::QualType::getFromOpaquePtr(type).getCanonicalType();
+ return clang::QualType();
+ }
+
//------------------------------------------------------------------
// Classes that inherit from ClangASTContext can see and modify these
//------------------------------------------------------------------
@@ -488,10 +1215,17 @@ protected:
std::unique_ptr<clang::IdentifierTable> m_identifier_table_ap;
std::unique_ptr<clang::SelectorTable> m_selector_table_ap;
std::unique_ptr<clang::Builtin::Context> m_builtins_ap;
+ std::unique_ptr<DWARFASTParser> m_dwarf_ast_parser_ap;
+ std::unique_ptr<ClangASTSource> m_scratch_ast_source_ap;
+ std::unique_ptr<clang::MangleContext> m_mangle_ctx_ap;
CompleteTagDeclCallback m_callback_tag_decl;
CompleteObjCInterfaceDeclCallback m_callback_objc_decl;
void * m_callback_baton;
uint32_t m_pointer_byte_size;
+ bool m_ast_owned;
+ bool m_can_evaluate_expressions;
+ std::map<void *, std::shared_ptr<void>> m_decl_objects;
+
private:
//------------------------------------------------------------------
// For ClangASTContext only
@@ -500,6 +1234,36 @@ private:
const ClangASTContext& operator=(const ClangASTContext&);
};
+class ClangASTContextForExpressions : public ClangASTContext
+{
+public:
+ ClangASTContextForExpressions (Target &target);
+
+ ~ClangASTContextForExpressions() override = default;
+
+ UserExpression *
+ GetUserExpression (const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ Expression::ResultType desired_type,
+ const EvaluateExpressionOptions &options) override;
+
+ FunctionCaller *
+ GetFunctionCaller (const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name) override;
+
+ UtilityFunction *
+ GetUtilityFunction(const char *text, const char *name) override;
+
+ PersistentExpressionState *
+ GetPersistentExpressionState() override;
+private:
+ lldb::TargetWP m_target_wp;
+ lldb::ClangPersistentVariablesUP m_persistent_variables; ///< These are the persistent variables associated with this process for the expression parser.
+};
+
} // namespace lldb_private
-#endif // liblldb_ClangASTContext_h_
+#endif // liblldb_ClangASTContext_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTImporter.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTImporter.h
index ee4fcad..8c3f873 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTImporter.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTImporter.h
@@ -10,14 +10,21 @@
#ifndef liblldb_ClangASTImporter_h_
#define liblldb_ClangASTImporter_h_
+// C Includes
+// C++ Includes
#include <map>
+#include <memory>
#include <set>
+#include <vector>
-#include "lldb/lldb-types.h"
+// Other libraries and framework includes
#include "clang/AST/ASTImporter.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
+
+// Project includes
+#include "lldb/lldb-types.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
namespace lldb_private {
@@ -96,20 +103,24 @@ public:
clang::ASTContext *src_ctx,
clang::QualType type);
- lldb::clang_type_t
+ lldb::opaque_compiler_type_t
CopyType (clang::ASTContext *dst_ctx,
clang::ASTContext *src_ctx,
- lldb::clang_type_t type);
-
+ lldb::opaque_compiler_type_t type);
+
+ CompilerType
+ CopyType (ClangASTContext &dst,
+ const CompilerType &src_type);
+
clang::Decl *
CopyDecl (clang::ASTContext *dst_ctx,
clang::ASTContext *src_ctx,
clang::Decl *decl);
- lldb::clang_type_t
+ lldb::opaque_compiler_type_t
DeportType (clang::ASTContext *dst_ctx,
clang::ASTContext *src_ctx,
- lldb::clang_type_t type);
+ lldb::opaque_compiler_type_t type);
clang::Decl *
DeportDecl (clang::ASTContext *dst_ctx,
@@ -127,7 +138,10 @@ public:
bool
CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl);
-
+
+ bool
+ CompleteAndFetchChildren (clang::QualType type);
+
bool
RequireCompleteType (clang::QualType type);
@@ -155,7 +169,7 @@ public:
// Namespace maps
//
- typedef std::vector < std::pair<lldb::ModuleSP, ClangNamespaceDecl> > NamespaceMap;
+ typedef std::vector < std::pair<lldb::ModuleSP, CompilerDeclContext> > NamespaceMap;
typedef std::shared_ptr<NamespaceMap> NamespaceMapSP;
void RegisterNamespaceMap (const clang::NamespaceDecl *decl,
@@ -199,12 +213,13 @@ public:
void ForgetDestination (clang::ASTContext *dst_ctx);
void ForgetSource (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
+
private:
struct DeclOrigin
{
DeclOrigin () :
- ctx(NULL),
- decl(NULL)
+ ctx(nullptr),
+ decl(nullptr)
{
}
@@ -230,7 +245,7 @@ private:
bool
Valid ()
{
- return (ctx != NULL || decl != NULL);
+ return (ctx != nullptr || decl != nullptr);
}
clang::ASTContext *ctx;
@@ -250,8 +265,8 @@ private:
*source_ctx,
master.m_file_manager,
true /*minimal*/),
- m_decls_to_deport(NULL),
- m_decls_already_deported(NULL),
+ m_decls_to_deport(nullptr),
+ m_decls_already_deported(nullptr),
m_master(master),
m_source_ctx(source_ctx)
{
@@ -276,9 +291,9 @@ private:
void ImportDefinitionTo (clang::Decl *to, clang::Decl *from);
- clang::Decl *Imported (clang::Decl *from, clang::Decl *to);
+ clang::Decl *Imported(clang::Decl *from, clang::Decl *to) override;
- clang::Decl *GetOriginalDecl (clang::Decl *To);
+ clang::Decl *GetOriginalDecl(clang::Decl *To) override;
std::set<clang::NamedDecl *> *m_decls_to_deport;
std::set<clang::NamedDecl *> *m_decls_already_deported;
@@ -297,7 +312,7 @@ private:
m_minions (),
m_origins (),
m_namespace_maps (),
- m_map_completer (NULL)
+ m_map_completer (nullptr)
{
}
@@ -368,6 +383,6 @@ private:
clang::FileManager m_file_manager;
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_ClangASTImporter_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
index 41bb235..5a00aa0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
@@ -11,18 +11,17 @@
#define liblldb_ClangExternalASTSourceCallbacks_h_
// C Includes
-// C++ Includes
-#include <string>
-#include <vector>
#include <stdint.h>
+// C++ Includes
// Other libraries and framework includes
+#include "llvm/ADT/DenseMap.h"
#include "clang/AST/CharUnits.h"
// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/Core/ClangForward.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
namespace lldb_private {
@@ -30,7 +29,6 @@ namespace lldb_private {
class ClangExternalASTSourceCallbacks : public ClangExternalASTSourceCommon
{
public:
-
typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *);
typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton, clang::ObjCInterfaceDecl *);
typedef void (*FindExternalVisibleDeclsByNameCallback)(void *baton, const clang::DeclContext *DC, clang::DeclarationName Name, llvm::SmallVectorImpl <clang::NamedDecl *> *results);
@@ -62,7 +60,7 @@ public:
{
// This method only needs to be implemented if the AST source ever
// passes back decl sets as VisibleDeclaration objects.
- return 0;
+ return nullptr;
}
clang::Stmt *
@@ -71,7 +69,7 @@ public:
// This operation is meant to be used via a LazyOffsetPtr. It only
// needs to be implemented if the AST source uses methods like
// FunctionDecl::setLazyBody when building decls.
- return 0;
+ return nullptr;
}
clang::Selector
@@ -91,23 +89,18 @@ public:
clang::CXXBaseSpecifier *
GetExternalCXXBaseSpecifiers(uint64_t Offset) override
{
- return NULL;
+ return nullptr;
}
virtual void
MaterializeVisibleDecls (const clang::DeclContext *decl_ctx)
{
- return;
}
- clang::ExternalLoadResult
- FindExternalLexicalDecls(const clang::DeclContext *decl_ctx, bool (*isKindWeWant)(clang::Decl::Kind),
- llvm::SmallVectorImpl<clang::Decl *> &decls) override
- {
- // This is used to support iterating through an entire lexical context,
- // which isn't something the debugger should ever need to do.
- return clang::ELR_Failure;
- }
+ void
+ FindExternalLexicalDecls(const clang::DeclContext *DC,
+ llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
+ llvm::SmallVectorImpl<clang::Decl *> &Result) override;
bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx, clang::DeclarationName decl_name) override;
@@ -119,6 +112,7 @@ public:
llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override;
+
void
SetExternalSourceCallbacks (CompleteTagDeclCallback tag_decl_callback,
CompleteObjCInterfaceDeclCallback objc_decl_callback,
@@ -138,10 +132,10 @@ public:
{
if (callback_baton == m_callback_baton)
{
- m_callback_tag_decl = NULL;
- m_callback_objc_decl = NULL;
- m_callback_find_by_name = NULL;
- m_callback_layout_record_type = NULL;
+ m_callback_tag_decl = nullptr;
+ m_callback_objc_decl = nullptr;
+ m_callback_find_by_name = nullptr;
+ m_callback_layout_record_type = nullptr;
}
}
@@ -158,4 +152,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_ClangExternalASTSourceCallbacks_h_
+#endif // liblldb_ClangExternalASTSourceCallbacks_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h
index 17650f7..711be42 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h
@@ -20,6 +20,7 @@
// file. So we have to define NDEBUG when including clang headers to avoid any
// mismatches. This is covered by rdar://problem/8691220
+// C Includes
#if !defined(NDEBUG) && !defined(LLVM_NDEBUG_OFF)
#define LLDB_DEFINED_NDEBUG_FOR_CLANG
#define NDEBUG
@@ -27,8 +28,6 @@
#include <assert.h>
#endif
-#include "clang/AST/ExternalASTSource.h"
-
#ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG
#undef NDEBUG
#undef LLDB_DEFINED_NDEBUG_FOR_CLANG
@@ -36,6 +35,11 @@
#include <assert.h>
#endif
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/ExternalASTSource.h"
+
+// Project includes
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/Core/dwarf.h"
@@ -124,8 +128,8 @@ public:
return lldb::eLanguageTypeC_plus_plus;
}
return lldb::eLanguageTypeUnknown;
-
}
+
const char *
GetObjectPtrName() const
{
@@ -137,7 +141,7 @@ public:
return "this";
}
else
- return NULL;
+ return nullptr;
}
bool
@@ -155,19 +159,19 @@ private:
lldb::user_id_t m_user_id;
uint64_t m_isa_ptr;
};
+
bool m_union_is_user_id : 1,
m_union_is_isa_ptr : 1,
m_has_object_ptr : 1,
m_is_self : 1,
m_is_dynamic_cxx : 1;
-
};
class ClangExternalASTSourceCommon : public clang::ExternalASTSource
{
public:
ClangExternalASTSourceCommon();
- ~ClangExternalASTSourceCommon();
+ ~ClangExternalASTSourceCommon() override;
ClangASTMetadata *GetMetadata(const void *object);
void SetMetadata(const void *object, ClangASTMetadata &metadata);
@@ -175,12 +179,13 @@ public:
static ClangExternalASTSourceCommon *
Lookup(clang::ExternalASTSource *source);
+
private:
typedef llvm::DenseMap<const void *, ClangASTMetadata> MetadataMap;
MetadataMap m_metadata;
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_ClangExternalASTSourceCommon_h
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangNamespaceDecl.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangNamespaceDecl.h
deleted file mode 100644
index 13a4c00..0000000
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangNamespaceDecl.h
+++ /dev/null
@@ -1,105 +0,0 @@
-//===-- ClangNamespaceDecl.h ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ClangNamespaceDecl_h_
-#define liblldb_ClangNamespaceDecl_h_
-
-#include <string>
-
-#include "lldb/lldb-public.h"
-#include "lldb/Core/ClangForward.h"
-
-namespace lldb_private {
-
-class ClangNamespaceDecl
-{
-public:
- ClangNamespaceDecl () :
- m_ast (NULL),
- m_namespace_decl (NULL)
- {
- }
-
- ClangNamespaceDecl (clang::ASTContext *ast, clang::NamespaceDecl *namespace_decl) :
- m_ast (ast),
- m_namespace_decl (namespace_decl)
- {
- }
-
- ClangNamespaceDecl (const ClangNamespaceDecl &rhs) :
- m_ast (rhs.m_ast),
- m_namespace_decl (rhs.m_namespace_decl)
- {
- }
-
- const ClangNamespaceDecl &
- operator = (const ClangNamespaceDecl &rhs)
- {
- m_ast = rhs.m_ast;
- m_namespace_decl = rhs.m_namespace_decl;
- return *this;
- }
-
- //------------------------------------------------------------------
- /// Convert to bool operator.
- ///
- /// This allows code to check a ClangNamespaceDecl object to see if
- /// it contains a valid namespace decl using code such as:
- ///
- /// @code
- /// ClangNamespaceDecl ns_decl(...);
- /// if (ns_decl)
- /// { ...
- /// @endcode
- ///
- /// @return
- /// /b True this object contains a valid namespace decl, \b
- /// false otherwise.
- //------------------------------------------------------------------
- explicit operator bool() const
- {
- return m_ast != NULL && m_namespace_decl != NULL;
- }
-
- clang::ASTContext *
- GetASTContext() const
- {
- return m_ast;
- }
-
- void
- SetASTContext (clang::ASTContext *ast)
- {
- m_ast = ast;
- }
-
- clang::NamespaceDecl *
- GetNamespaceDecl () const
- {
- return m_namespace_decl;
- }
-
- void
- SetNamespaceDecl (clang::NamespaceDecl *namespace_decl)
- {
- m_namespace_decl = namespace_decl;
- }
-
- std::string
- GetQualifiedName () const;
-
-protected:
- clang::ASTContext *m_ast;
- clang::NamespaceDecl *m_namespace_decl;
-};
-
-
-} // namespace lldb_private
-
-#endif // #ifndef liblldb_ClangNamespaceDecl_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/CompileUnit.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompileUnit.h
index e0c0693..0c331c3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompileUnit.h
@@ -11,6 +11,7 @@
#define liblldb_CompUnit_h_
#include "lldb/lldb-enumerations.h"
+#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/ModuleChild.h"
@@ -66,9 +67,12 @@ public:
/// A language enumeration type that describes the main language
/// of this compile unit.
///
+ /// @param[in] is_optimized
+ /// true if this compile unit was compiled with optimization.
+ ///
/// @see lldb::LanguageType
//------------------------------------------------------------------
- CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, lldb::user_id_t uid, lldb::LanguageType language);
+ CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, lldb::user_id_t uid, lldb::LanguageType language, bool is_optimized);
//------------------------------------------------------------------
/// Construct with a module, file spec, UID and language.
@@ -98,15 +102,17 @@ public:
/// A language enumeration type that describes the main language
/// of this compile unit.
///
+ /// @param[in] is_optimized
+ /// true if this compile unit was compiled with optimization.
+ ///
/// @see lldb::LanguageType
//------------------------------------------------------------------
- CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &file_spec, lldb::user_id_t uid, lldb::LanguageType language);
+ CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &file_spec, lldb::user_id_t uid, lldb::LanguageType language, bool is_optimized);
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- virtual
- ~CompileUnit();
+ ~CompileUnit() override;
//------------------------------------------------------------------
/// Add a function to this compile unit.
@@ -125,22 +131,22 @@ public:
///
/// @see SymbolContextScope
//------------------------------------------------------------------
- virtual void
- CalculateSymbolContext(SymbolContext* sc);
+ void
+ CalculateSymbolContext(SymbolContext* sc) override;
- virtual lldb::ModuleSP
- CalculateSymbolContextModule ();
+ lldb::ModuleSP
+ CalculateSymbolContextModule() override;
- virtual CompileUnit *
- CalculateSymbolContextCompileUnit ();
+ CompileUnit *
+ CalculateSymbolContextCompileUnit() override;
//------------------------------------------------------------------
/// @copydoc SymbolContextScope::DumpSymbolContext(Stream*)
///
/// @see SymbolContextScope
//------------------------------------------------------------------
- virtual void
- DumpSymbolContext(Stream *s);
+ void
+ DumpSymbolContext(Stream *s) override;
lldb::LanguageType
GetLanguage();
@@ -245,6 +251,9 @@ public:
LineTable*
GetLineTable ();
+ DebugMacros*
+ GetDebugMacros ();
+
//------------------------------------------------------------------
/// Get the compile unit's support file list.
///
@@ -339,6 +348,9 @@ public:
void
SetLineTable(LineTable* line_table);
+ void
+ SetDebugMacros(const DebugMacrosSP &debug_macros);
+
//------------------------------------------------------------------
/// Set accessor for the variable list.
///
@@ -406,6 +418,22 @@ public:
SymbolContextList &sc_list);
+ //------------------------------------------------------------------
+ /// Get whether compiler optimizations were enabled for this compile unit
+ ///
+ /// "optimized" means that the debug experience may be difficult
+ /// for the user to understand. Variables may not be available when
+ /// the developer would expect them, stepping through the source lines
+ /// in the function may appear strange, etc.
+ ///
+ /// @return
+ /// Returns 'true' if this compile unit was compiled with
+ /// optimization. 'false' indicates that either the optimization
+ /// is unknown, or this compile unit was built without optimization.
+ //------------------------------------------------------------------
+ bool
+ GetIsOptimized ();
+
protected:
void *m_user_data; ///< User data for the SymbolFile parser to store information into.
lldb::LanguageType m_language; ///< The programming language enumeration value.
@@ -416,7 +444,9 @@ protected:
///< compile unit.
FileSpecList m_support_files; ///< Files associated with this compile unit's line table and declarations.
std::unique_ptr<LineTable> m_line_table_ap; ///< Line table that will get parsed on demand.
+ DebugMacrosSP m_debug_macros_sp; ///< Debug macros that will get parsed on demand.
lldb::VariableListSP m_variables; ///< Global and static variable list that will get parsed on demand.
+ bool m_is_optimized; /// eLazyBoolYes if this compile unit was compiled with optimization.
private:
enum
@@ -425,8 +455,9 @@ private:
flagsParsedVariables = (1u << 1), ///< Have we already parsed globals and statics?
flagsParsedSupportFiles = (1u << 2), ///< Have we already parsed the support files for this compile unit?
flagsParsedLineTable = (1u << 3), ///< Have we parsed the line table already?
- flagsParsedLanguage = (1u << 4), ///< Have we parsed the line table already?
- flagsParsedImportedModules = (1u << 5) ///< Have we parsed the imported modules already?
+ flagsParsedLanguage = (1u << 4), ///< Have we parsed the language already?
+ flagsParsedImportedModules = (1u << 5), ///< Have we parsed the imported modules already?
+ flagsParsedDebugMacros = (1u << 6) ///< Have we parsed the debug macros already?
};
DISALLOW_COPY_AND_ASSIGN (CompileUnit);
@@ -434,4 +465,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_CompUnit_h_
+#endif // liblldb_CompUnit_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerDecl.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerDecl.h
new file mode 100644
index 0000000..b749e79
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerDecl.h
@@ -0,0 +1,135 @@
+//===-- CompilerDecl.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CompilerDecl_h_
+#define liblldb_CompilerDecl_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Symbol/CompilerType.h"
+
+namespace lldb_private {
+
+class CompilerDecl
+{
+public:
+ //----------------------------------------------------------------------
+ // Constructors and Destructors
+ //----------------------------------------------------------------------
+ CompilerDecl () :
+ m_type_system (nullptr),
+ m_opaque_decl (nullptr)
+ {
+ }
+
+ CompilerDecl (TypeSystem *type_system, void *decl) :
+ m_type_system (type_system),
+ m_opaque_decl (decl)
+ {
+ }
+
+ ~CompilerDecl ()
+ {
+ }
+
+ //----------------------------------------------------------------------
+ // Tests
+ //----------------------------------------------------------------------
+
+ explicit operator bool () const
+ {
+ return IsValid ();
+ }
+
+ bool
+ operator < (const CompilerDecl &rhs) const
+ {
+ if (m_type_system == rhs.m_type_system)
+ return m_opaque_decl < rhs.m_opaque_decl;
+ return m_type_system < rhs.m_type_system;
+ }
+
+ bool
+ IsValid () const
+ {
+ return m_type_system != nullptr && m_opaque_decl != nullptr;
+ }
+
+ bool
+ IsClang () const;
+
+ //----------------------------------------------------------------------
+ // Object linked to the decl
+ //----------------------------------------------------------------------
+ lldb::VariableSP
+ GetAsVariable ();
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+
+ TypeSystem *
+ GetTypeSystem() const
+ {
+ return m_type_system;
+ }
+
+ void *
+ GetOpaqueDecl() const
+ {
+ return m_opaque_decl;
+ }
+
+ void
+ SetDecl (TypeSystem* type_system, void* decl)
+ {
+ m_type_system = type_system;
+ m_opaque_decl = decl;
+ }
+
+ void
+ Clear()
+ {
+ m_type_system = nullptr;
+ m_opaque_decl = nullptr;
+ }
+
+ ConstString
+ GetName () const;
+
+ ConstString
+ GetMangledName () const;
+
+ CompilerDeclContext
+ GetDeclContext() const;
+
+ // If this decl represents a function, return the return type
+ CompilerType
+ GetFunctionReturnType() const;
+
+ // If this decl represents a function, return the number of arguments for the function
+ size_t
+ GetNumFunctionArguments() const;
+
+ // If this decl represents a function, return the argument type given a zero based argument index
+ CompilerType
+ GetFunctionArgumentType (size_t arg_idx) const;
+
+private:
+ TypeSystem *m_type_system;
+ void *m_opaque_decl;
+};
+
+bool operator == (const CompilerDecl &lhs, const CompilerDecl &rhs);
+bool operator != (const CompilerDecl &lhs, const CompilerDecl &rhs);
+
+
+} // namespace lldb_private
+
+#endif // #ifndef liblldb_CompilerDecl_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerDeclContext.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerDeclContext.h
new file mode 100644
index 0000000..9135b44
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerDeclContext.h
@@ -0,0 +1,149 @@
+//===-- CompilerDeclContext.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CompilerDeclContext_h_
+#define liblldb_CompilerDeclContext_h_
+
+#include <vector>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+
+namespace lldb_private {
+
+class CompilerDeclContext
+{
+public:
+ //----------------------------------------------------------------------
+ // Constructors and Destructors
+ //----------------------------------------------------------------------
+ CompilerDeclContext () :
+ m_type_system (nullptr),
+ m_opaque_decl_ctx (nullptr)
+ {
+ }
+
+ CompilerDeclContext (TypeSystem *type_system, void *decl_ctx) :
+ m_type_system (type_system),
+ m_opaque_decl_ctx (decl_ctx)
+ {
+ }
+
+ ~CompilerDeclContext()
+ {
+ }
+
+ //----------------------------------------------------------------------
+ // Tests
+ //----------------------------------------------------------------------
+
+ explicit operator bool () const
+ {
+ return IsValid ();
+ }
+
+ bool
+ operator < (const CompilerDeclContext &rhs) const
+ {
+ if (m_type_system == rhs.m_type_system)
+ return m_opaque_decl_ctx < rhs.m_opaque_decl_ctx;
+ return m_type_system < rhs.m_type_system;
+ }
+
+ bool
+ IsValid () const
+ {
+ return m_type_system != nullptr && m_opaque_decl_ctx != nullptr;
+ }
+
+ bool
+ IsClang () const;
+
+ std::vector<CompilerDecl>
+ FindDeclByName (ConstString name);
+
+ //----------------------------------------------------------------------
+ /// Checks if this decl context represents a method of a class.
+ ///
+ /// @param[out] language_ptr
+ /// If non NULL and \b true is returned from this function,
+ /// this will indicate if the language that respresents the method.
+ ///
+ /// @param[out] is_instance_method_ptr
+ /// If non NULL and \b true is returned from this function,
+ /// this will indicate if the method is an instance function (true)
+ /// or a class method (false indicating the function is static, or
+ /// doesn't require an instance of the class to be called).
+ ///
+ /// @param[out] language_object_name_ptr
+ /// If non NULL and \b true is returned from this function,
+ /// this will indicate if implicit object name for the language
+ /// like "this" for C++, and "self" for Objective C.
+ ///
+ /// @return
+ /// Returns true if this is a decl context that represents a method
+ /// in a struct, union or class.
+ //----------------------------------------------------------------------
+ bool
+ IsClassMethod (lldb::LanguageType *language_ptr,
+ bool *is_instance_method_ptr,
+ ConstString *language_object_name_ptr);
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+
+ TypeSystem *
+ GetTypeSystem() const
+ {
+ return m_type_system;
+ }
+
+ void *
+ GetOpaqueDeclContext() const
+ {
+ return m_opaque_decl_ctx;
+ }
+
+ void
+ SetDeclContext (TypeSystem* type_system, void* decl_ctx)
+ {
+ m_type_system = type_system;
+ m_opaque_decl_ctx = decl_ctx;
+ }
+
+ void
+ Clear()
+ {
+ m_type_system = nullptr;
+ m_opaque_decl_ctx = nullptr;
+ }
+
+ ConstString
+ GetName () const;
+
+ ConstString
+ GetScopeQualifiedName() const;
+
+ bool
+ IsStructUnionOrClass () const;
+
+private:
+ TypeSystem *m_type_system;
+ void *m_opaque_decl_ctx;
+
+};
+
+bool operator == (const CompilerDeclContext &lhs, const CompilerDeclContext &rhs);
+bool operator != (const CompilerDeclContext &lhs, const CompilerDeclContext &rhs);
+
+
+} // namespace lldb_private
+
+#endif // #ifndef liblldb_CompilerDeclContext_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTType.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerType.h
index 2524751..4f3ecc5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ClangASTType.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/CompilerType.h
@@ -1,4 +1,4 @@
-//===-- ClangASTType.h ------------------------------------------*- C++ -*-===//
+//===-- CompilerType.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,13 +7,19 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_ClangASTType_h_
-#define liblldb_ClangASTType_h_
+#ifndef liblldb_CompilerType_h_
+#define liblldb_CompilerType_h_
+// C Includes
+// C++ Includes
+#include <functional>
#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/ClangForward.h"
-#include "clang/AST/Type.h"
namespace lldb_private {
@@ -27,46 +33,40 @@ namespace lldb_private {
// and the opaque clang QualType to be specified for ease of use and
// to avoid code duplication.
//----------------------------------------------------------------------
-class ClangASTType
+class CompilerType
{
public:
//----------------------------------------------------------------------
// Constructors and Destructors
//----------------------------------------------------------------------
- ClangASTType (clang::ASTContext *ast_context, lldb::clang_type_t type) :
- m_type (type),
- m_ast (ast_context)
- {
- }
+ CompilerType (TypeSystem *type_system, lldb::opaque_compiler_type_t type);
+ CompilerType (clang::ASTContext *ast_context, clang::QualType qual_type);
- ClangASTType (clang::ASTContext *ast_context, clang::QualType qual_type);
-
- ClangASTType (const ClangASTType &rhs) :
+ CompilerType (const CompilerType &rhs) :
m_type (rhs.m_type),
- m_ast (rhs.m_ast)
+ m_type_system (rhs.m_type_system)
{
}
- ClangASTType () :
- m_type (0),
- m_ast (0)
+ CompilerType () :
+ m_type (nullptr),
+ m_type_system (nullptr)
{
}
- ~ClangASTType();
+ ~CompilerType();
//----------------------------------------------------------------------
// Operators
//----------------------------------------------------------------------
- const ClangASTType &
- operator= (const ClangASTType &rhs)
+ const CompilerType &
+ operator= (const CompilerType &rhs)
{
m_type = rhs.m_type;
- m_ast = rhs.m_ast;
+ m_type_system = rhs.m_type_system;
return *this;
}
-
//----------------------------------------------------------------------
// Tests
@@ -74,30 +74,30 @@ public:
explicit operator bool () const
{
- return m_type != NULL && m_ast != NULL;
+ return m_type != nullptr && m_type_system != nullptr;
}
bool
- operator < (const ClangASTType &rhs) const
+ operator < (const CompilerType &rhs) const
{
- if (m_ast == rhs.m_ast)
+ if (m_type_system == rhs.m_type_system)
return m_type < rhs.m_type;
- return m_ast < rhs.m_ast;
+ return m_type_system < rhs.m_type_system;
}
bool
IsValid () const
{
- return m_type != NULL && m_ast != NULL;
+ return m_type != nullptr && m_type_system != nullptr;
}
bool
- IsArrayType (ClangASTType *element_type,
+ IsArrayType (CompilerType *element_type,
uint64_t *size,
bool *is_incomplete) const;
bool
- IsVectorType (ClangASTType *element_type,
+ IsVectorType (CompilerType *element_type,
uint64_t *size) const;
bool
@@ -107,6 +107,9 @@ public:
IsAggregateType () const;
bool
+ IsAnonymousType () const;
+
+ bool
IsBeingDefined () const;
bool
@@ -122,24 +125,21 @@ public:
IsCStringType (uint32_t &length) const;
bool
- IsCXXClassType () const;
-
- bool
IsDefined() const;
bool
IsFloatingPointType (uint32_t &count, bool &is_complex) const;
bool
- IsFunctionType (bool *is_variadic_ptr = NULL) const;
+ IsFunctionType(bool *is_variadic_ptr = nullptr) const;
uint32_t
- IsHomogeneousAggregate (ClangASTType* base_type_ptr) const;
+ IsHomogeneousAggregate (CompilerType* base_type_ptr) const;
size_t
GetNumberOfFunctionArguments () const;
- ClangASTType
+ CompilerType
GetFunctionArgumentAtIndex (const size_t index) const;
bool
@@ -150,33 +150,20 @@ public:
bool
IsIntegerType (bool &is_signed) const;
-
- bool
- IsObjCClassType () const;
-
- bool
- IsObjCClassTypeAndHasIVars (bool check_superclass) const;
-
- bool
- IsObjCObjectOrInterfaceType () const;
-
- bool
- IsObjCObjectPointerType (ClangASTType *target_type = NULL);
bool
IsPolymorphicClass () const;
bool
- IsPossibleCPlusPlusDynamicType (ClangASTType *target_type = NULL) const
+ IsPossibleCPlusPlusDynamicType(CompilerType *target_type = nullptr) const
{
return IsPossibleDynamicType (target_type, true, false);
}
bool
- IsPossibleDynamicType (ClangASTType *target_type, // Can pass NULL
- bool check_cplusplus,
- bool check_objc) const;
-
+ IsPossibleDynamicType(CompilerType *target_type, // Can pass nullptr
+ bool check_cplusplus,
+ bool check_objc) const;
bool
IsPointerToScalarType () const;
@@ -185,13 +172,16 @@ public:
IsRuntimeGeneratedType () const;
bool
- IsPointerType (ClangASTType *pointee_type = NULL) const;
+ IsPointerType(CompilerType *pointee_type = nullptr) const;
bool
- IsPointerOrReferenceType (ClangASTType *pointee_type = NULL) const;
+ IsPointerOrReferenceType(CompilerType *pointee_type = nullptr) const;
bool
- IsReferenceType (ClangASTType *pointee_type = nullptr, bool* is_rvalue = nullptr) const;
+ IsReferenceType(CompilerType *pointee_type = nullptr, bool* is_rvalue = nullptr) const;
+
+ bool
+ ShouldTreatScalarValueAsAddress () const;
bool
IsScalarType () const;
@@ -202,13 +192,6 @@ public:
bool
IsVoidType () const;
- bool
- GetCXXClassName (std::string &class_name) const;
-
- bool
- GetObjCClassName (std::string &class_name);
-
-
//----------------------------------------------------------------------
// Type Completion
//----------------------------------------------------------------------
@@ -227,10 +210,10 @@ public:
// Accessors
//----------------------------------------------------------------------
- clang::ASTContext *
- GetASTContext() const
+ TypeSystem *
+ GetTypeSystem() const
{
- return m_ast;
+ return m_type_system;
}
ConstString
@@ -246,12 +229,12 @@ public:
GetDisplayTypeName () const;
uint32_t
- GetTypeInfo (ClangASTType *pointee_or_element_clang_type = NULL) const;
+ GetTypeInfo(CompilerType *pointee_or_element_compiler_type = nullptr) const;
lldb::LanguageType
GetMinimumLanguage ();
- lldb::clang_type_t
+ lldb::opaque_compiler_type_t
GetOpaqueQualType() const
{
return m_type;
@@ -261,14 +244,10 @@ public:
GetTypeClass () const;
void
- SetClangType (clang::ASTContext *ast, lldb::clang_type_t type)
- {
- m_ast = ast;
- m_type = type;
- }
+ SetCompilerType (TypeSystem* type_system, lldb::opaque_compiler_type_t type);
void
- SetClangType (clang::ASTContext *ast, clang::QualType qual_type);
+ SetCompilerType (clang::ASTContext *ast, clang::QualType qual_type);
unsigned
GetTypeQualifiers() const;
@@ -276,29 +255,14 @@ public:
//----------------------------------------------------------------------
// Creating related types
//----------------------------------------------------------------------
-
- ClangASTType
- AddConstModifier () const;
-
- ClangASTType
- AddRestrictModifier () const;
-
- ClangASTType
- AddVolatileModifier () const;
- // Using the current type, create a new typedef to that type using "typedef_name"
- // as the name and "decl_ctx" as the decl context.
- ClangASTType
- CreateTypedefType (const char *typedef_name,
- clang::DeclContext *decl_ctx) const;
+ CompilerType
+ GetArrayElementType(uint64_t *stride = nullptr) const;
- ClangASTType
- GetArrayElementType (uint64_t *stride = nullptr) const;
-
- ClangASTType
+ CompilerType
GetCanonicalType () const;
- ClangASTType
+ CompilerType
GetFullyUnqualifiedType () const;
// Returns -1 if this isn't a function of if the function doesn't have a prototype
@@ -306,10 +270,10 @@ public:
int
GetFunctionArgumentCount () const;
- ClangASTType
+ CompilerType
GetFunctionArgumentTypeAtIndex (size_t idx) const;
- ClangASTType
+ CompilerType
GetFunctionReturnType () const;
size_t
@@ -318,32 +282,83 @@ public:
TypeMemberFunctionImpl
GetMemberFunctionAtIndex (size_t idx);
- ClangASTType
- GetLValueReferenceType () const;
-
- ClangASTType
+ //----------------------------------------------------------------------
+ // If this type is a reference to a type (L value or R value reference),
+ // return a new type with the reference removed, else return the current
+ // type itself.
+ //----------------------------------------------------------------------
+ CompilerType
GetNonReferenceType () const;
- ClangASTType
+ //----------------------------------------------------------------------
+ // If this type is a pointer type, return the type that the pointer
+ // points to, else return an invalid type.
+ //----------------------------------------------------------------------
+ CompilerType
GetPointeeType () const;
- ClangASTType
+ //----------------------------------------------------------------------
+ // Return a new CompilerType that is a pointer to this type
+ //----------------------------------------------------------------------
+ CompilerType
GetPointerType () const;
-
- ClangASTType
+
+ //----------------------------------------------------------------------
+ // Return a new CompilerType that is a L value reference to this type if
+ // this type is valid and the type system supports L value references,
+ // else return an invalid type.
+ //----------------------------------------------------------------------
+ CompilerType
+ GetLValueReferenceType () const;
+
+ //----------------------------------------------------------------------
+ // Return a new CompilerType that is a R value reference to this type if
+ // this type is valid and the type system supports R value references,
+ // else return an invalid type.
+ //----------------------------------------------------------------------
+ CompilerType
GetRValueReferenceType () const;
+ //----------------------------------------------------------------------
+ // Return a new CompilerType adds a const modifier to this type if
+ // this type is valid and the type system supports const modifiers,
+ // else return an invalid type.
+ //----------------------------------------------------------------------
+ CompilerType
+ AddConstModifier () const;
+
+ //----------------------------------------------------------------------
+ // Return a new CompilerType adds a volatile modifier to this type if
+ // this type is valid and the type system supports volatile modifiers,
+ // else return an invalid type.
+ //----------------------------------------------------------------------
+ CompilerType
+ AddVolatileModifier () const;
+
+ //----------------------------------------------------------------------
+ // Return a new CompilerType adds a restrict modifier to this type if
+ // this type is valid and the type system supports restrict modifiers,
+ // else return an invalid type.
+ //----------------------------------------------------------------------
+ CompilerType
+ AddRestrictModifier () const;
+
+ //----------------------------------------------------------------------
+ // Create a typedef to this type using "name" as the name of the typedef
+ // this type is valid and the type system supports typedefs, else return
+ // an invalid type.
+ //----------------------------------------------------------------------
+ CompilerType
+ CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const;
+
// If the current object represents a typedef type, get the underlying type
- ClangASTType
+ CompilerType
GetTypedefedType () const;
-
- ClangASTType
- RemoveFastQualifiers () const;
//----------------------------------------------------------------------
// Create related types using the current type's AST
//----------------------------------------------------------------------
- ClangASTType
+ CompilerType
GetBasicTypeFromAST (lldb::BasicType basic_type) const;
//----------------------------------------------------------------------
@@ -374,54 +389,62 @@ public:
static lldb::BasicType
GetBasicTypeEnumeration (const ConstString &name);
- uint32_t
- GetNumDirectBaseClasses () const;
-
- uint32_t
- GetNumVirtualBaseClasses () const;
-
+ //----------------------------------------------------------------------
+ // If this type is an enumeration, iterate through all of its enumerators
+ // using a callback. If the callback returns true, keep iterating, else
+ // abort the iteration.
+ //----------------------------------------------------------------------
+ void
+ ForEachEnumerator (std::function <bool (const CompilerType &integer_type,
+ const ConstString &name,
+ const llvm::APSInt &value)> const &callback) const;
+
uint32_t
GetNumFields () const;
- ClangASTType
- GetDirectBaseClassAtIndex (size_t idx,
- uint32_t *bit_offset_ptr) const;
-
- ClangASTType
- GetVirtualBaseClassAtIndex (size_t idx,
- uint32_t *bit_offset_ptr) const;
-
- ClangASTType
+ CompilerType
GetFieldAtIndex (size_t idx,
std::string& name,
uint64_t *bit_offset_ptr,
uint32_t *bitfield_bit_size_ptr,
bool *is_bitfield_ptr) const;
-
+
uint32_t
- GetIndexOfFieldWithName (const char* name,
- ClangASTType* field_clang_type = NULL,
- uint64_t *bit_offset_ptr = NULL,
- uint32_t *bitfield_bit_size_ptr = NULL,
- bool *is_bitfield_ptr = NULL) const;
-
+ GetNumDirectBaseClasses () const;
+
+ uint32_t
+ GetNumVirtualBaseClasses () const;
+
+ CompilerType
+ GetDirectBaseClassAtIndex (size_t idx,
+ uint32_t *bit_offset_ptr) const;
+
+ CompilerType
+ GetVirtualBaseClassAtIndex (size_t idx,
+ uint32_t *bit_offset_ptr) const;
+
uint32_t
- GetNumPointeeChildren () const;
-
- ClangASTType
- GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
- size_t idx,
- bool transparent_pointers,
- bool omit_empty_base_classes,
- bool ignore_array_bounds,
- std::string& child_name,
- uint32_t &child_byte_size,
- int32_t &child_byte_offset,
- uint32_t &child_bitfield_bit_size,
- uint32_t &child_bitfield_bit_offset,
- bool &child_is_base_class,
- bool &child_is_deref_of_parent,
- ValueObject *valobj) const;
+ GetIndexOfFieldWithName(const char* name,
+ CompilerType* field_compiler_type = nullptr,
+ uint64_t *bit_offset_ptr = nullptr,
+ uint32_t *bitfield_bit_size_ptr = nullptr,
+ bool *is_bitfield_ptr = nullptr) const;
+
+ CompilerType
+ GetChildCompilerTypeAtIndex (ExecutionContext *exe_ctx,
+ size_t idx,
+ bool transparent_pointers,
+ bool omit_empty_base_classes,
+ bool ignore_array_bounds,
+ std::string& child_name,
+ uint32_t &child_byte_size,
+ int32_t &child_byte_offset,
+ uint32_t &child_bitfield_bit_size,
+ uint32_t &child_bitfield_bit_offset,
+ bool &child_is_base_class,
+ bool &child_is_deref_of_parent,
+ ValueObject *valobj,
+ uint64_t &language_flags) const;
// Lookup a child given a name. This function will match base class names
// and member member names in "clang_type" only, not descendants.
@@ -442,136 +465,30 @@ public:
size_t
GetNumTemplateArguments () const;
- ClangASTType
+ CompilerType
GetTemplateArgument (size_t idx,
lldb::TemplateArgumentKind &kind) const;
-
-
- //----------------------------------------------------------------------
- // Modifying RecordType
- //----------------------------------------------------------------------
- clang::FieldDecl *
- AddFieldToRecordType (const char *name,
- const ClangASTType &field_type,
- lldb::AccessType access,
- uint32_t bitfield_bit_size);
-
- void
- BuildIndirectFields ();
-
- void
- SetIsPacked ();
-
- clang::VarDecl *
- AddVariableToRecordType (const char *name,
- const ClangASTType &var_type,
- lldb::AccessType access);
-
- clang::CXXMethodDecl *
- AddMethodToCXXRecordType (const char *name,
- const ClangASTType &method_type,
- lldb::AccessType access,
- bool is_virtual,
- bool is_static,
- bool is_inline,
- bool is_explicit,
- bool is_attr_used,
- bool is_artificial);
-
- // C++ Base Classes
- clang::CXXBaseSpecifier *
- CreateBaseClassSpecifier (lldb::AccessType access,
- bool is_virtual,
- bool base_of_class);
-
- static void
- DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes,
- unsigned num_base_classes);
-
- bool
- SetBaseClassesForClassType (clang::CXXBaseSpecifier const * const *base_classes,
- unsigned num_base_classes);
-
-
- bool
- SetObjCSuperClass (const ClangASTType &superclass_clang_type);
-
- bool
- AddObjCClassProperty (const char *property_name,
- const ClangASTType &property_clang_type,
- clang::ObjCIvarDecl *ivar_decl,
- const char *property_setter_name,
- const char *property_getter_name,
- uint32_t property_attributes,
- ClangASTMetadata *metadata);
-
- clang::ObjCMethodDecl *
- AddMethodToObjCObjectType (const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]")
- const ClangASTType &method_clang_type,
- lldb::AccessType access,
- bool is_artificial);
-
- clang::DeclContext *
- GetDeclContextForType () const;
-
-
- bool
- SetDefaultAccessForRecordFields (int default_accessibility,
- int *assigned_accessibilities,
- size_t num_assigned_accessibilities);
- bool
- SetHasExternalStorage (bool has_extern);
+ CompilerType
+ GetTypeForFormatters () const;
+ LazyBool
+ ShouldPrintAsOneLiner (ValueObject* valobj) const;
- //------------------------------------------------------------------
- // clang::TagType
- //------------------------------------------------------------------
-
- bool
- SetTagTypeKind (int kind) const;
-
- //------------------------------------------------------------------
- // Tag Declarations
- //------------------------------------------------------------------
- bool
- StartTagDeclarationDefinition ();
-
- bool
- CompleteTagDeclarationDefinition ();
-
- //----------------------------------------------------------------------
- // Modifying Enumeration types
- //----------------------------------------------------------------------
bool
- AddEnumerationValueToEnumerationType (const ClangASTType &enumerator_qual_type,
- const Declaration &decl,
- const char *name,
- int64_t enum_value,
- uint32_t enum_value_bit_size);
-
-
-
- ClangASTType
- GetEnumerationIntegerType () const;
-
+ IsMeaninglessWithoutDynamicResolution () const;
//------------------------------------------------------------------
// Pointers & References
//------------------------------------------------------------------
- // Call this function using the class type when you want to make a
- // member pointer type to pointee_type.
- ClangASTType
- CreateMemberPointerType (const ClangASTType &pointee_type) const;
-
-
// Converts "s" to a floating point value and place resulting floating
// point bytes in the "dst" buffer.
size_t
ConvertStringToFloatValue (const char *s,
uint8_t *dst,
size_t dst_size) const;
+
//----------------------------------------------------------------------
// Dumping types
//----------------------------------------------------------------------
@@ -633,52 +550,22 @@ public:
lldb::addr_t addr,
AddressType address_type,
StreamString &new_value);
-
- clang::EnumDecl *
- GetAsEnumDecl () const;
-
-
- clang::RecordDecl *
- GetAsRecordDecl () const;
- clang::CXXRecordDecl *
- GetAsCXXRecordDecl () const;
-
- clang::ObjCInterfaceDecl *
- GetAsObjCInterfaceDecl () const;
-
void
Clear()
{
- m_type = NULL;
- m_ast = NULL;
- }
-
- clang::QualType
- GetQualType () const
- {
- if (m_type)
- return clang::QualType::getFromOpaquePtr(m_type);
- return clang::QualType();
- }
- clang::QualType
- GetCanonicalQualType () const
- {
- if (m_type)
- return clang::QualType::getFromOpaquePtr(m_type).getCanonicalType();
- return clang::QualType();
+ m_type = nullptr;
+ m_type_system = nullptr;
}
private:
- lldb::clang_type_t m_type;
- clang::ASTContext *m_ast;
-
+ lldb::opaque_compiler_type_t m_type;
+ TypeSystem *m_type_system;
};
-bool operator == (const ClangASTType &lhs, const ClangASTType &rhs);
-bool operator != (const ClangASTType &lhs, const ClangASTType &rhs);
+bool operator == (const CompilerType &lhs, const CompilerType &rhs);
+bool operator != (const CompilerType &lhs, const CompilerType &rhs);
-
} // namespace lldb_private
-#endif // #ifndef liblldb_ClangASTType_h_
+#endif // liblldb_CompilerType_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/DebugMacros.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/DebugMacros.h
new file mode 100644
index 0000000..24bf03a
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/DebugMacros.h
@@ -0,0 +1,140 @@
+//===-- DebugMacros.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DebugMacros_h_
+#define liblldb_DebugMacros_h_
+
+// C Includes
+// C++ Includes
+#include <memory>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+
+namespace lldb_private {
+
+class CompileUnit;
+class DebugMacros;
+typedef std::shared_ptr<DebugMacros> DebugMacrosSP;
+
+class DebugMacroEntry
+{
+public:
+ enum EntryType
+ {
+ INVALID,
+ DEFINE,
+ UNDEF,
+ START_FILE,
+ END_FILE,
+ INDIRECT
+ };
+
+public:
+ static DebugMacroEntry
+ CreateDefineEntry(uint32_t line, const char *str);
+
+ static DebugMacroEntry
+ CreateUndefEntry(uint32_t line, const char *str);
+
+ static DebugMacroEntry
+ CreateStartFileEntry(uint32_t line, uint32_t debug_line_file_idx);
+
+ static DebugMacroEntry
+ CreateEndFileEntry();
+
+ static DebugMacroEntry
+ CreateIndirectEntry(const DebugMacrosSP &debug_macros_sp);
+
+ DebugMacroEntry() : m_type(INVALID) { }
+
+ ~DebugMacroEntry() = default;
+
+ EntryType
+ GetType() const
+ {
+ return m_type;
+ }
+
+ uint64_t
+ GetLineNumber() const
+ {
+ return m_line;
+ }
+
+ ConstString
+ GetMacroString() const
+ {
+ return m_str;
+ }
+
+ const FileSpec& GetFileSpec(CompileUnit *comp_unit) const;
+
+ DebugMacros *
+ GetIndirectDebugMacros() const
+ {
+ return m_debug_macros_sp.get();
+ }
+
+private:
+ DebugMacroEntry(EntryType type,
+ uint32_t line,
+ uint32_t debug_line_file_idx,
+ const char *str);
+
+ DebugMacroEntry(EntryType type,
+ const DebugMacrosSP &debug_macros_sp);
+
+ EntryType m_type:3;
+ uint32_t m_line:29;
+ uint32_t m_debug_line_file_idx;
+ ConstString m_str;
+ DebugMacrosSP m_debug_macros_sp;
+};
+
+class DebugMacros
+{
+public:
+ DebugMacros() = default;
+
+ ~DebugMacros() = default;
+
+ void
+ AddMacroEntry(const DebugMacroEntry &entry)
+ {
+ m_macro_entries.push_back(entry);
+ }
+
+ size_t
+ GetNumMacroEntries() const
+ {
+ return m_macro_entries.size();
+ }
+
+ DebugMacroEntry
+ GetMacroEntryAtIndex(const size_t index) const
+ {
+ if (index < m_macro_entries.size())
+ return m_macro_entries[index];
+ else
+ return DebugMacroEntry();
+ }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(DebugMacros);
+
+ std::vector<DebugMacroEntry> m_macro_entries;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_DebugMacros_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/FuncUnwinders.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/FuncUnwinders.h
index 0d4aabb..728b4c6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/FuncUnwinders.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/FuncUnwinders.h
@@ -103,6 +103,9 @@ public:
GetCompactUnwindUnwindPlan (Target &target, int current_offset);
lldb::UnwindPlanSP
+ GetArmUnwindUnwindPlan (Target &target, int current_offset);
+
+ lldb::UnwindPlanSP
GetArchDefaultUnwindPlan (Thread &thread);
lldb::UnwindPlanSP
@@ -122,6 +125,7 @@ private:
lldb::UnwindPlanSP m_unwind_plan_eh_frame_sp;
lldb::UnwindPlanSP m_unwind_plan_eh_frame_augmented_sp; // augmented by assembly inspection so it's valid everywhere
std::vector<lldb::UnwindPlanSP> m_unwind_plan_compact_unwind;
+ lldb::UnwindPlanSP m_unwind_plan_arm_unwind_sp;
lldb::UnwindPlanSP m_unwind_plan_fast_sp;
lldb::UnwindPlanSP m_unwind_plan_arch_default_sp;
lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp;
@@ -132,6 +136,7 @@ private:
m_tried_unwind_plan_eh_frame:1,
m_tried_unwind_plan_eh_frame_augmented:1,
m_tried_unwind_plan_compact_unwind:1,
+ m_tried_unwind_plan_arm_unwind:1,
m_tried_unwind_fast:1,
m_tried_unwind_arch_default:1,
m_tried_unwind_arch_default_at_func_entry:1;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Function.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Function.h
index 30c8f16..cd2df9b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Function.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Function.h
@@ -10,7 +10,6 @@
#ifndef liblldb_Function_h_
#define liblldb_Function_h_
-#include "lldb/Core/ClangForward.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Declaration.h"
@@ -147,7 +146,6 @@ protected:
Declaration m_declaration; ///< Information describing where this function information was defined.
};
-
//----------------------------------------------------------------------
/// @class InlineFunctionInfo Function.h "lldb/Symbol/Function.h"
/// @brief A class that describes information for an inlined function.
@@ -203,7 +201,7 @@ public:
//------------------------------------------------------------------
/// Destructor.
//------------------------------------------------------------------
- ~InlineFunctionInfo();
+ ~InlineFunctionInfo() override;
//------------------------------------------------------------------
/// Compare two inlined function information objects.
@@ -294,8 +292,8 @@ public:
///
/// @see ConstString::StaticMemorySize ()
//------------------------------------------------------------------
- virtual size_t
- MemorySize() const;
+ size_t
+ MemorySize() const override;
private:
//------------------------------------------------------------------
@@ -415,24 +413,24 @@ public:
//------------------------------------------------------------------
/// Destructor.
//------------------------------------------------------------------
- ~Function ();
+ ~Function() override;
//------------------------------------------------------------------
/// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*)
///
/// @see SymbolContextScope
//------------------------------------------------------------------
- virtual void
- CalculateSymbolContext(SymbolContext* sc);
+ void
+ CalculateSymbolContext(SymbolContext* sc) override;
- virtual lldb::ModuleSP
- CalculateSymbolContextModule ();
+ lldb::ModuleSP
+ CalculateSymbolContextModule() override;
- virtual CompileUnit *
- CalculateSymbolContextCompileUnit ();
+ CompileUnit *
+ CalculateSymbolContextCompileUnit() override;
- virtual Function *
- CalculateSymbolContextFunction ();
+ Function *
+ CalculateSymbolContextFunction() override;
const AddressRange &
GetAddressRange()
@@ -550,8 +548,8 @@ public:
/// @return
/// The DeclContext, or NULL if none exists.
//------------------------------------------------------------------
- clang::DeclContext *
- GetClangDeclContext();
+ CompilerDeclContext
+ GetDeclContext();
//------------------------------------------------------------------
/// Get accessor for the type that describes the function
@@ -573,8 +571,8 @@ public:
const Type*
GetType() const;
- ClangASTType
- GetClangType ();
+ CompilerType
+ GetCompilerType ();
uint32_t
GetPrologueByteSize ();
@@ -600,8 +598,8 @@ public:
///
/// @see SymbolContextScope
//------------------------------------------------------------------
- virtual void
- DumpSymbolContext(Stream *s);
+ void
+ DumpSymbolContext(Stream *s) override;
//------------------------------------------------------------------
/// Get the memory cost of this object.
@@ -616,6 +614,42 @@ public:
size_t
MemorySize () const;
+ //------------------------------------------------------------------
+ /// Get whether compiler optimizations were enabled for this function
+ ///
+ /// The debug information may provide information about whether this
+ /// function was compiled with optimization or not. In this case,
+ /// "optimized" means that the debug experience may be difficult
+ /// for the user to understand. Variables may not be available when
+ /// the developer would expect them, stepping through the source lines
+ /// in the function may appear strange, etc.
+ ///
+ /// @return
+ /// Returns 'true' if this function was compiled with
+ /// optimization. 'false' indicates that either the optimization
+ /// is unknown, or this function was built without optimization.
+ //------------------------------------------------------------------
+ bool
+ GetIsOptimized ();
+
+ //------------------------------------------------------------------
+ /// Get whether this function represents a 'top-level' function
+ ///
+ /// The concept of a top-level function is language-specific, mostly
+ /// meant to represent the notion of scripting-style code that has
+ /// global visibility of the variables/symbols/functions/...
+ /// defined within the containing file/module
+ ///
+ /// If stopped in a top-level function, LLDB will expose global variables
+ /// as-if locals in the 'frame variable' command
+ ///
+ /// @return
+ /// Returns 'true' if this function is a top-level function,
+ /// 'false' otherwise.
+ //------------------------------------------------------------------
+ bool
+ IsTopLevelFunction ();
+
lldb::DisassemblerSP
GetInstructions (const ExecutionContext &exe_ctx,
const char *flavor,
@@ -634,8 +668,6 @@ protected:
flagsCalculatedPrologueSize = (1 << 0) ///< Have we already tried to calculate the prologue size?
};
-
-
//------------------------------------------------------------------
// Member variables.
//------------------------------------------------------------------
@@ -654,4 +686,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_Function_h_
+#endif // liblldb_Function_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/GoASTContext.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/GoASTContext.h
new file mode 100644
index 0000000..09d79ba
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/GoASTContext.h
@@ -0,0 +1,408 @@
+//===-- GoASTContext.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoASTContext_h_
+#define liblldb_GoASTContext_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ConstString.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Symbol/CompilerType.h"
+
+namespace lldb_private
+{
+
+class Declaration;
+class GoType;
+
+class GoASTContext : public TypeSystem
+{
+ public:
+ GoASTContext();
+ ~GoASTContext() override;
+
+ //------------------------------------------------------------------
+ // PluginInterface functions
+ //------------------------------------------------------------------
+ ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+
+ static ConstString
+ GetPluginNameStatic ();
+
+ static lldb::TypeSystemSP
+ CreateInstance (lldb::LanguageType language, Module *module, Target *target);
+
+ static void
+ EnumerateSupportedLanguages(std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ DWARFASTParser *GetDWARFParser() override;
+
+ void
+ SetAddressByteSize(int byte_size)
+ {
+ m_pointer_byte_size = byte_size;
+ }
+
+ //------------------------------------------------------------------
+ // llvm casting support
+ //------------------------------------------------------------------
+ static bool classof(const TypeSystem *ts)
+ {
+ return ts->getKind() == TypeSystem::eKindGo;
+ }
+
+ //----------------------------------------------------------------------
+ // CompilerDecl functions
+ //----------------------------------------------------------------------
+ ConstString
+ DeclGetName (void *opaque_decl) override
+ {
+ return ConstString();
+ }
+
+ lldb::VariableSP
+ DeclGetVariable (void *opaque_decl) override
+ {
+ return lldb::VariableSP();
+ }
+
+ void
+ DeclLinkToObject (void *opaque_decl, std::shared_ptr<void> object) override
+ {
+ }
+
+ //----------------------------------------------------------------------
+ // CompilerDeclContext functions
+ //----------------------------------------------------------------------
+
+ bool
+ DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) override
+ {
+ return false;
+ }
+
+ ConstString
+ DeclContextGetName(void *opaque_decl_ctx) override
+ {
+ return ConstString();
+ }
+
+ ConstString
+ DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) override
+ {
+ return ConstString();
+ }
+
+ bool
+ DeclContextIsClassMethod(void *opaque_decl_ctx, lldb::LanguageType *language_ptr, bool *is_instance_method_ptr,
+ ConstString *language_object_name_ptr) override
+ {
+ return false;
+ }
+
+ //----------------------------------------------------------------------
+ // Creating Types
+ //----------------------------------------------------------------------
+
+ CompilerType CreateArrayType(const ConstString &name, const CompilerType &element_type, uint64_t length);
+
+ CompilerType CreateBaseType(int go_kind, const ConstString &type_name_const_str, uint64_t byte_size);
+
+ // For interface, map, chan.
+ CompilerType CreateTypedefType(int kind, const ConstString &name, CompilerType impl);
+
+ CompilerType CreateVoidType(const ConstString &name);
+ CompilerType CreateFunctionType(const lldb_private::ConstString &name, CompilerType *params, size_t params_count,
+ bool is_variadic);
+
+ CompilerType CreateStructType(int kind, const ConstString &name, uint32_t byte_size);
+
+ void CompleteStructType(const CompilerType &type);
+
+ void AddFieldToStruct(const CompilerType &struct_type, const ConstString &name, const CompilerType &field_type,
+ uint32_t byte_offset);
+
+ //----------------------------------------------------------------------
+ // Tests
+ //----------------------------------------------------------------------
+
+ static bool IsGoString(const CompilerType &type);
+ static bool IsGoSlice(const CompilerType &type);
+ static bool IsGoInterface(const CompilerType &type);
+ static bool IsDirectIface(uint8_t kind);
+ static bool IsPointerKind(uint8_t kind);
+
+ bool IsArrayType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size, bool *is_incomplete) override;
+
+ bool IsAggregateType(lldb::opaque_compiler_type_t type) override;
+
+ bool IsCharType(lldb::opaque_compiler_type_t type) override;
+
+ bool IsCompleteType(lldb::opaque_compiler_type_t type) override;
+
+ bool IsDefined(lldb::opaque_compiler_type_t type) override;
+
+ bool IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) override;
+
+ bool IsFunctionType(lldb::opaque_compiler_type_t type, bool *is_variadic_ptr = nullptr) override;
+
+ size_t GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) override;
+
+ CompilerType GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, const size_t index) override;
+
+ bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) override;
+
+ bool IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) override;
+
+ bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
+ CompilerType *target_type, // Can pass nullptr
+ bool check_cplusplus, bool check_objc) override;
+
+ bool IsPointerType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type = nullptr) override;
+
+ bool IsScalarType(lldb::opaque_compiler_type_t type) override;
+
+ bool IsVoidType(lldb::opaque_compiler_type_t type) override;
+
+ bool SupportsLanguage (lldb::LanguageType language) override;
+
+ //----------------------------------------------------------------------
+ // Type Completion
+ //----------------------------------------------------------------------
+
+ bool GetCompleteType(lldb::opaque_compiler_type_t type) override;
+
+ //----------------------------------------------------------------------
+ // AST related queries
+ //----------------------------------------------------------------------
+
+ uint32_t GetPointerByteSize() override;
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+
+ ConstString GetTypeName(lldb::opaque_compiler_type_t type) override;
+
+ uint32_t GetTypeInfo(lldb::opaque_compiler_type_t type,
+ CompilerType *pointee_or_element_compiler_type = nullptr) override;
+
+ lldb::LanguageType GetMinimumLanguage(lldb::opaque_compiler_type_t type) override;
+
+ lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) override;
+
+ //----------------------------------------------------------------------
+ // Creating related types
+ //----------------------------------------------------------------------
+
+ CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type, uint64_t *stride = nullptr) override;
+
+ CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) override;
+
+ // Returns -1 if this isn't a function of if the function doesn't have a prototype
+ // Returns a value >= 0 if there is a prototype.
+ int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override;
+
+ CompilerType GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, size_t idx) override;
+
+ CompilerType GetFunctionReturnType(lldb::opaque_compiler_type_t type) override;
+
+ size_t GetNumMemberFunctions(lldb::opaque_compiler_type_t type) override;
+
+ TypeMemberFunctionImpl GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx) override;
+
+ CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) override;
+
+ CompilerType GetPointerType(lldb::opaque_compiler_type_t type) override;
+
+ //----------------------------------------------------------------------
+ // Exploring the type
+ //----------------------------------------------------------------------
+
+ uint64_t GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) override;
+
+ lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count) override;
+
+ lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override;
+
+ uint32_t GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) override;
+
+ lldb::BasicType GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override;
+
+ CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size) override;
+
+ uint32_t GetNumFields(lldb::opaque_compiler_type_t type) override;
+
+ CompilerType GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx, std::string &name, uint64_t *bit_offset_ptr,
+ uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) override;
+
+ uint32_t
+ GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) override
+ {
+ return 0;
+ }
+
+ uint32_t
+ GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) override
+ {
+ return 0;
+ }
+
+ CompilerType
+ GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) override
+ {
+ return CompilerType();
+ }
+
+ CompilerType
+ GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) override
+ {
+ return CompilerType();
+ }
+
+ CompilerType GetChildCompilerTypeAtIndex(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
+ bool transparent_pointers, bool omit_empty_base_classes,
+ bool ignore_array_bounds, std::string &child_name,
+ uint32_t &child_byte_size, int32_t &child_byte_offset,
+ uint32_t &child_bitfield_bit_size,
+ uint32_t &child_bitfield_bit_offset, bool &child_is_base_class,
+ bool &child_is_deref_of_parent, ValueObject *valobj, uint64_t &language_flags) override;
+
+ // Lookup a child given a name. This function will match base class names
+ // and member member names in "clang_type" only, not descendants.
+ uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes) override;
+
+ // Lookup a child member given a name. This function will match member names
+ // only and will descend into "clang_type" children in search for the first
+ // member in this class, or any base class that matches "name".
+ // TODO: Return all matches for a given name by returning a vector<vector<uint32_t>>
+ // so we catch all names that match a given child name, not just the first.
+ size_t GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes,
+ std::vector<uint32_t> &child_indexes) override;
+
+ size_t
+ GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override
+ {
+ return 0;
+ }
+
+ CompilerType
+ GetTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, lldb::TemplateArgumentKind &kind) override
+ {
+ return CompilerType();
+ }
+
+ //----------------------------------------------------------------------
+ // Dumping types
+ //----------------------------------------------------------------------
+ void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format,
+ const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size,
+ uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, bool show_summary,
+ bool verbose, uint32_t depth) override;
+
+ bool DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, const DataExtractor &data,
+ lldb::offset_t data_offset, size_t data_byte_size, uint32_t bitfield_bit_size,
+ uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) override;
+
+ void DumpTypeDescription(lldb::opaque_compiler_type_t type) override; // Dump to stdout
+
+ void DumpTypeDescription(lldb::opaque_compiler_type_t type, Stream *s) override;
+
+ //----------------------------------------------------------------------
+ // TODO: These methods appear unused. Should they be removed?
+ //----------------------------------------------------------------------
+
+ bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) override;
+
+ void DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, const DataExtractor &data,
+ lldb::offset_t data_offset, size_t data_byte_size) override;
+
+ // Converts "s" to a floating point value and place resulting floating
+ // point bytes in the "dst" buffer.
+ size_t ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst, size_t dst_size) override;
+
+ //----------------------------------------------------------------------
+ // TODO: Determine if these methods should move to ClangASTContext.
+ //----------------------------------------------------------------------
+
+ bool IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
+ CompilerType *pointee_type = nullptr) override;
+
+ unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) override;
+
+ bool IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length) override;
+
+ size_t GetTypeBitAlign(lldb::opaque_compiler_type_t type) override;
+
+ CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override;
+
+ bool IsBeingDefined(lldb::opaque_compiler_type_t type) override;
+
+ bool IsConst(lldb::opaque_compiler_type_t type) override;
+
+ uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, CompilerType *base_type_ptr) override;
+
+ bool IsPolymorphicClass(lldb::opaque_compiler_type_t type) override;
+
+ bool IsTypedefType(lldb::opaque_compiler_type_t type) override;
+
+ // If the current object represents a typedef type, get the underlying type
+ CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) override;
+
+ bool IsVectorType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size) override;
+
+ CompilerType GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) override;
+
+ CompilerType GetNonReferenceType(lldb::opaque_compiler_type_t type) override;
+
+ bool IsReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type = nullptr, bool *is_rvalue = nullptr) override;
+
+ private:
+ typedef std::map<ConstString, std::unique_ptr<GoType>> TypeMap;
+ int m_pointer_byte_size;
+ int m_int_byte_size;
+ std::unique_ptr<TypeMap> m_types;
+ std::unique_ptr<DWARFASTParser> m_dwarf_ast_parser_ap;
+
+ GoASTContext(const GoASTContext &) = delete;
+ const GoASTContext &operator=(const GoASTContext &) = delete;
+};
+
+class GoASTContextForExpr : public GoASTContext
+{
+ public:
+ GoASTContextForExpr(lldb::TargetSP target) : m_target_wp(target) {}
+ UserExpression *GetUserExpression(const char *expr, const char *expr_prefix, lldb::LanguageType language,
+ Expression::ResultType desired_type,
+ const EvaluateExpressionOptions &options) override;
+
+ private:
+ lldb::TargetWP m_target_wp;
+};
+}
+#endif // liblldb_GoASTContext_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/LineEntry.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/LineEntry.h
index 082caea..374c04a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/LineEntry.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/LineEntry.h
@@ -140,6 +140,32 @@ struct LineEntry
static int
Compare (const LineEntry& lhs, const LineEntry& rhs);
+ //------------------------------------------------------------------
+ /// Give the range for this LineEntry + any additional LineEntries for
+ /// this same source line that are contiguous.
+ ///
+ /// A compiler may emit multiple line entries for a single source line,
+ /// e.g. to indicate subexpressions at different columns. This method
+ /// will get the AddressRange for all of the LineEntries for this source
+ /// line that are contiguous.
+ //
+ /// Line entries with a line number of 0 are treated specially - these
+ /// are compiler-generated line table entries that the user did not
+ /// write in their source code, and we want to skip past in the debugger.
+ /// If this LineEntry is for line 32, and the following LineEntry is for
+ /// line 0, we will extend the range to include the AddressRange of the
+ /// line 0 LineEntry (and it will include the range of the following
+ /// LineEntries that match either 32 or 0.)
+ ///
+ /// If the initial LineEntry this method is called on is a line #0, only
+ /// the range of contiuous LineEntries with line #0 will be included in
+ /// the complete range.
+ ///
+ /// @return
+ /// The contiguous AddressRange for this source line.
+ //------------------------------------------------------------------
+ AddressRange
+ GetSameLineContiguousAddressRange () const;
//------------------------------------------------------------------
// Member variables.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/LineTable.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/LineTable.h
index 3e25ad1..cbad9bf 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/LineTable.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/LineTable.h
@@ -10,8 +10,12 @@
#ifndef liblldb_LineTable_h_
#define liblldb_LineTable_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Core/ModuleChild.h"
@@ -30,7 +34,7 @@ public:
LineSequence ();
virtual
- ~LineSequence() {}
+ ~LineSequence() = default;
virtual void
Clear() = 0;
@@ -143,14 +147,14 @@ public:
///
/// @param[out] index_ptr
/// A pointer to a 32 bit integer that will get the actual line
- /// entry index if it is not NULL.
+ /// entry index if it is not nullptr.
///
/// @return
/// Returns \b true if \a so_addr is contained in a line entry
/// in this line table, \b false otherwise.
//------------------------------------------------------------------
bool
- FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr = NULL);
+ FindLineEntryByAddress(const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr = nullptr);
//------------------------------------------------------------------
/// Find a line entry index that has a matching file index and
@@ -269,7 +273,6 @@ public:
LinkLineTable (const FileRangeMap &file_range_map);
protected:
-
struct Entry
{
Entry () :
@@ -343,12 +346,12 @@ protected:
return 0;
}
-
class LessThanBinaryPredicate
{
public:
LessThanBinaryPredicate(LineTable *line_table);
bool operator() (const LineTable::Entry&, const LineTable::Entry&) const;
+
protected:
LineTable *m_line_table;
};
@@ -396,16 +399,12 @@ protected:
class LineSequenceImpl : public LineSequence
{
public:
- LineSequenceImpl() :
- LineSequence()
- {}
+ LineSequenceImpl() = default;
- virtual
- ~LineSequenceImpl()
- {}
+ ~LineSequenceImpl() override = default;
- virtual void
- Clear();
+ void
+ Clear() override;
entry_collection m_entries; ///< The collection of line entries in this sequence.
};
@@ -419,4 +418,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_LineTable_h_
+#endif // liblldb_LineTable_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectContainer.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectContainer.h
index 679e8f0..eeda1c4 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectContainer.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectContainer.h
@@ -14,7 +14,6 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-
#include "lldb/lldb-private.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Host/FileSpec.h"
@@ -71,10 +70,7 @@ public:
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
- virtual
- ~ObjectContainer()
- {
- }
+ ~ObjectContainer() override = default;
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
@@ -188,7 +184,7 @@ public:
///
/// @return
/// Returns a pointer to the object file of the requested \a
- /// arch and optional \a name. Returns NULL of no such object
+ /// arch and optional \a name. Returns nullptr of no such object
/// file exists in the container.
//------------------------------------------------------------------
virtual lldb::ObjectFileSP
@@ -203,19 +199,19 @@ public:
virtual ObjectFile *
GetObjectFileAtIndex (uint32_t object_idx)
{
- return NULL;
+ return nullptr;
}
virtual ObjectContainer *
GetObjectContainerAtIndex (uint32_t object_idx)
{
- return NULL;
+ return nullptr;
}
virtual const char *
GetObjectNameAtIndex (uint32_t object_idx) const
{
- return NULL;
+ return nullptr;
}
protected:
@@ -233,4 +229,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ObjectContainer_h_
+#endif // liblldb_ObjectContainer_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectFile.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectFile.h
index ff00ac2..4b0a2f9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/ObjectFile.h
@@ -125,8 +125,7 @@ public:
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
- virtual
- ~ObjectFile();
+ ~ObjectFile() override;
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
@@ -369,12 +368,11 @@ public:
/// The list of sections contained in this object file.
//------------------------------------------------------------------
virtual SectionList *
- GetSectionList ();
+ GetSectionList (bool update_module_section_list = true);
virtual void
CreateSections (SectionList &unified_section_list) = 0;
-
//------------------------------------------------------------------
/// Notify the ObjectFile that the file addresses in the Sections
/// for this module have been changed.
@@ -595,7 +593,6 @@ public:
virtual lldb_private::Address
GetHeaderAddress () { return Address(m_memory_addr);}
-
virtual uint32_t
GetNumThreadContexts ()
{
@@ -767,7 +764,6 @@ public:
return 0;
}
-
//------------------------------------------------------------------
/// Return true if this file is a dynamic link editor (dyld)
///
@@ -823,6 +819,7 @@ public:
lldb::offset_t section_offset,
void *dst,
size_t dst_len) const;
+
virtual size_t
ReadSectionData (const Section *section,
DataExtractor& section_data) const;
@@ -843,7 +840,11 @@ public:
{
return symbol_name.str();
}
-
+
+ static lldb::SymbolType
+ GetSymbolTypeFromName (llvm::StringRef name,
+ lldb::SymbolType symbol_type_hint = lldb::eSymbolTypeUndefined);
+
protected:
//------------------------------------------------------------------
// Member variables.
@@ -880,5 +881,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ObjectFile_h_
-
+#endif // liblldb_ObjectFile_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Symbol.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Symbol.h
index f9438b0..c77d3de 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Symbol.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Symbol.h
@@ -333,6 +333,7 @@ public:
{
return m_demangled_is_synthesized;
}
+
void
SetDemangledNameIsSynthesized(bool b)
{
@@ -354,22 +355,22 @@ public:
///
/// @see SymbolContextScope
//------------------------------------------------------------------
- virtual void
- CalculateSymbolContext (SymbolContext *sc);
+ void
+ CalculateSymbolContext(SymbolContext *sc) override;
- virtual lldb::ModuleSP
- CalculateSymbolContextModule ();
+ lldb::ModuleSP
+ CalculateSymbolContextModule() override;
- virtual Symbol *
- CalculateSymbolContextSymbol ();
+ Symbol *
+ CalculateSymbolContextSymbol() override;
//------------------------------------------------------------------
/// @copydoc SymbolContextScope::DumpSymbolContext(Stream*)
///
/// @see SymbolContextScope
//------------------------------------------------------------------
- virtual void
- DumpSymbolContext (Stream *s);
+ void
+ DumpSymbolContext(Stream *s) override;
lldb::DisassemblerSP
GetInstructions (const ExecutionContext &exe_ctx,
@@ -411,4 +412,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_Symbol_h_
+#endif // liblldb_Symbol_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContext.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContext.h
index c48505e..9cb709d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContext.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContext.h
@@ -7,12 +7,17 @@
//
//===----------------------------------------------------------------------===//
-
#ifndef liblldb_SymbolContext_h_
#define liblldb_SymbolContext_h_
+// C Includes
+// C++ Includes
+#include <memory>
+#include <string>
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Mangled.h"
@@ -22,6 +27,7 @@
namespace lldb_private {
class SymbolContextScope;
+
//----------------------------------------------------------------------
/// @class SymbolContext SymbolContext.h "lldb/Symbol/SymbolContext.h"
/// @brief Defines a symbol context baton that can be handed other debug
@@ -36,11 +42,10 @@ class SymbolContextScope;
class SymbolContext
{
public:
-
//------------------------------------------------------------------
/// Default constructor.
///
- /// Initialize all pointer members to NULL and all struct members
+ /// Initialize all pointer members to nullptr and all struct members
/// to their default state.
//------------------------------------------------------------------
SymbolContext ();
@@ -81,24 +86,23 @@ public:
/// A Symbol pointer to the symbol for this context.
//------------------------------------------------------------------
explicit
- SymbolContext (const lldb::TargetSP &target_sp,
- const lldb::ModuleSP &module_sp,
- CompileUnit *comp_unit = NULL,
- Function *function = NULL,
- Block *block = NULL,
- LineEntry *line_entry = NULL,
- Symbol *symbol = NULL);
+ SymbolContext(const lldb::TargetSP &target_sp,
+ const lldb::ModuleSP &module_sp,
+ CompileUnit *comp_unit = nullptr,
+ Function *function = nullptr,
+ Block *block = nullptr,
+ LineEntry *line_entry = nullptr,
+ Symbol *symbol = nullptr);
// This version sets the target to a NULL TargetSP if you don't know it.
explicit
- SymbolContext (const lldb::ModuleSP &module_sp,
- CompileUnit *comp_unit = NULL,
- Function *function = NULL,
- Block *block = NULL,
- LineEntry *line_entry = NULL,
- Symbol *symbol = NULL);
+ SymbolContext(const lldb::ModuleSP &module_sp,
+ CompileUnit *comp_unit = nullptr,
+ Function *function = nullptr,
+ Block *block = nullptr,
+ LineEntry *line_entry = nullptr,
+ Symbol *symbol = nullptr);
- ~SymbolContext ();
//------------------------------------------------------------------
/// Copy constructor
///
@@ -109,6 +113,8 @@ public:
//------------------------------------------------------------------
SymbolContext (const SymbolContext& rhs);
+ ~SymbolContext ();
+
//------------------------------------------------------------------
/// Assignment operator.
///
@@ -127,7 +133,7 @@ public:
//------------------------------------------------------------------
/// Clear the object's state.
///
- /// Resets all pointer members to NULL, and clears any class objects
+ /// Resets all pointer members to nullptr, and clears any class objects
/// to their default state.
//------------------------------------------------------------------
void
@@ -203,14 +209,14 @@ public:
///
/// Address range priority is as follows:
/// - line_entry address range if line_entry is valid and eSymbolContextLineEntry is set in \a scope
- /// - block address range if block is not NULL and eSymbolContextBlock is set in \a scope
- /// - function address range if function is not NULL and eSymbolContextFunction is set in \a scope
- /// - symbol address range if symbol is not NULL and eSymbolContextSymbol is set in \a scope
+ /// - block address range if block is not nullptr and eSymbolContextBlock is set in \a scope
+ /// - function address range if function is not nullptr and eSymbolContextFunction is set in \a scope
+ /// - symbol address range if symbol is not nullptr and eSymbolContextSymbol is set in \a scope
///
/// @param[in] scope
/// A mask of symbol context bits telling this function which
/// address ranges it can use when trying to extract one from
- /// the valid (non-NULL) symbol context classes.
+ /// the valid (non-nullptr) symbol context classes.
///
/// @param[in] range_idx
/// The address range index to grab. Since many functions and
@@ -239,7 +245,6 @@ public:
bool use_inline_block_range,
AddressRange &range) const;
-
void
GetDescription(Stream *s,
lldb::DescriptionLevel level,
@@ -248,7 +253,9 @@ public:
uint32_t
GetResolvedMask () const;
-
+ lldb::LanguageType
+ GetLanguage () const;
+
//------------------------------------------------------------------
/// Find a block that defines the function represented by this
/// symbol context.
@@ -268,12 +275,11 @@ public:
///
/// @return
/// The block object pointer that defines the function that is
- /// represented by this symbol context object, NULL otherwise.
+ /// represented by this symbol context object, nullptr otherwise.
//------------------------------------------------------------------
Block *
GetFunctionBlock ();
-
//------------------------------------------------------------------
/// If this symbol context represents a function that is a method,
/// return true and provide information about the method.
@@ -299,6 +305,14 @@ public:
ConstString &language_object_name);
//------------------------------------------------------------------
+ /// Sorts the types in TypeMap according to SymbolContext
+ /// to TypeList
+ ///
+ //------------------------------------------------------------------
+ void
+ SortTypeList(TypeMap &type_map, TypeList &type_list) const;
+
+ //------------------------------------------------------------------
/// Find a name of the innermost function for the symbol context.
///
/// For instance, if the symbol context contains an inlined block,
@@ -315,7 +329,6 @@ public:
ConstString
GetFunctionName (Mangled::NamePreference preference = Mangled::ePreferDemangled) const;
-
//------------------------------------------------------------------
/// Get the line entry that corresponds to the function.
///
@@ -377,7 +390,6 @@ public:
Variable * variable; ///< The global variable matching the given query
};
-
class SymbolContextSpecifier
{
public:
@@ -427,7 +439,6 @@ private:
std::string m_class_name;
std::unique_ptr<AddressRange> m_address_range_ap;
uint32_t m_type; // Or'ed bits from SpecificationType
-
};
//----------------------------------------------------------------------
@@ -479,6 +490,7 @@ public:
uint32_t
AppendIfUnique (const SymbolContextList& sc_list,
bool merge_symbol_into_function);
+
//------------------------------------------------------------------
/// Clear the object's state.
///
@@ -558,6 +570,7 @@ public:
bool
RemoveContextAtIndex (size_t idx);
+
//------------------------------------------------------------------
/// Get accessor for a symbol context list size.
///
@@ -600,4 +613,4 @@ bool operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs);
} // namespace lldb_private
-#endif // liblldb_SymbolContext_h_
+#endif // liblldb_SymbolContext_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContextScope.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContextScope.h
index a02b452..212d8e6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContextScope.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolContextScope.h
@@ -72,7 +72,7 @@ class SymbolContextScope
{
public:
virtual
- ~SymbolContextScope () {}
+ ~SymbolContextScope() = default;
//------------------------------------------------------------------
/// Reconstruct the object's symbol context into \a sc.
@@ -87,7 +87,6 @@ public:
virtual void
CalculateSymbolContext (SymbolContext *sc) = 0;
-
virtual lldb::ModuleSP
CalculateSymbolContextModule ()
{
@@ -97,25 +96,25 @@ public:
virtual CompileUnit *
CalculateSymbolContextCompileUnit ()
{
- return NULL;
+ return nullptr;
}
virtual Function *
CalculateSymbolContextFunction ()
{
- return NULL;
+ return nullptr;
}
virtual Block *
CalculateSymbolContextBlock ()
{
- return NULL;
+ return nullptr;
}
virtual Symbol *
CalculateSymbolContextSymbol ()
{
- return NULL;
+ return nullptr;
}
//------------------------------------------------------------------
@@ -134,4 +133,4 @@ public:
} // namespace lldb_private
-#endif // liblldb_SymbolContextScope_h_
+#endif // liblldb_SymbolContextScope_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolFile.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolFile.h
index 0efe034..fe74ad4 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolFile.h
@@ -12,8 +12,9 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/PluginInterface.h"
-#include "lldb/Symbol/ClangASTType.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/Type.h"
namespace lldb_private {
@@ -55,8 +56,7 @@ public:
{
}
- virtual
- ~SymbolFile()
+ ~SymbolFile() override
{
}
@@ -123,33 +123,44 @@ public:
virtual lldb::LanguageType ParseCompileUnitLanguage (const SymbolContext& sc) = 0;
virtual size_t ParseCompileUnitFunctions (const SymbolContext& sc) = 0;
virtual bool ParseCompileUnitLineTable (const SymbolContext& sc) = 0;
+ virtual bool ParseCompileUnitDebugMacros (const SymbolContext& sc) = 0;
virtual bool ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files) = 0;
virtual bool ParseImportedModules (const SymbolContext &sc, std::vector<ConstString> &imported_modules) = 0;
virtual size_t ParseFunctionBlocks (const SymbolContext& sc) = 0;
virtual size_t ParseTypes (const SymbolContext& sc) = 0;
virtual size_t ParseVariablesForContext (const SymbolContext& sc) = 0;
virtual Type* ResolveTypeUID (lldb::user_id_t type_uid) = 0;
- virtual bool ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type) = 0;
- virtual clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) { return NULL; }
- virtual clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) { return NULL; }
+ virtual bool CompleteType (CompilerType &compiler_type) = 0;
+ virtual void ParseDeclsForContext (CompilerDeclContext decl_ctx) {}
+ virtual CompilerDecl GetDeclForUID (lldb::user_id_t uid) { return CompilerDecl(); }
+ virtual CompilerDeclContext GetDeclContextForUID (lldb::user_id_t uid) { return CompilerDeclContext(); }
+ virtual CompilerDeclContext GetDeclContextContainingUID (lldb::user_id_t uid) { return CompilerDeclContext(); }
virtual uint32_t ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) = 0;
- virtual uint32_t ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) = 0;
- virtual uint32_t FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables) = 0;
- virtual uint32_t FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables) = 0;
- virtual uint32_t FindFunctions (const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list) = 0;
- virtual uint32_t FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list) = 0;
- virtual uint32_t FindTypes (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, TypeList& types) = 0;
+ virtual uint32_t ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list);
+ virtual uint32_t FindGlobalVariables (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, VariableList& variables);
+ virtual uint32_t FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables);
+ virtual uint32_t FindFunctions (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list);
+ virtual uint32_t FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list);
+ virtual uint32_t FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, TypeMap& types);
+ virtual size_t FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types);
+
+ virtual void GetMangledNamesForFunction(const std::string &scope_qualified_name, std::vector<ConstString> &mangled_names);
// virtual uint32_t FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types) = 0;
virtual TypeList * GetTypeList ();
virtual size_t GetTypes (lldb_private::SymbolContextScope *sc_scope,
uint32_t type_mask,
lldb_private::TypeList &type_list) = 0;
- virtual ClangASTContext &
- GetClangASTContext ();
- virtual ClangNamespaceDecl
+
+ virtual lldb_private::TypeSystem *
+ GetTypeSystemForLanguage (lldb::LanguageType language);
+
+ virtual CompilerDeclContext
FindNamespace (const SymbolContext& sc,
const ConstString &name,
- const ClangNamespaceDecl *parent_namespace_decl) = 0;
+ const CompilerDeclContext *parent_decl_ctx)
+ {
+ return CompilerDeclContext();
+ }
ObjectFile* GetObjectFile() { return m_obj_file; }
const ObjectFile* GetObjectFile() const { return m_obj_file; }
@@ -163,16 +174,15 @@ public:
{
}
-
protected:
ObjectFile* m_obj_file; // The object file that symbols can be extracted from.
uint32_t m_abilities;
bool m_calculated_abilities;
+
private:
DISALLOW_COPY_AND_ASSIGN (SymbolFile);
};
-
} // namespace lldb_private
-#endif // liblldb_SymbolFile_h_
+#endif // liblldb_SymbolFile_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolVendor.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolVendor.h
index 248918a..1946171 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolVendor.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/SymbolVendor.h
@@ -15,9 +15,8 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/ModuleChild.h"
#include "lldb/Core/PluginInterface.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/TypeList.h"
-
+#include "lldb/Symbol/TypeMap.h"
namespace lldb_private {
@@ -45,8 +44,7 @@ public:
//------------------------------------------------------------------
SymbolVendor(const lldb::ModuleSP &module_sp);
- virtual
- ~SymbolVendor();
+ ~SymbolVendor() override;
void
AddSymbolFileRepresentation(const lldb::ObjectFileSP &objfile_sp);
@@ -64,6 +62,9 @@ public:
ParseCompileUnitLineTable (const SymbolContext& sc);
virtual bool
+ ParseCompileUnitDebugMacros (const SymbolContext& sc);
+
+ virtual bool
ParseCompileUnitSupportFiles (const SymbolContext& sc,
FileSpecList& support_files);
@@ -97,7 +98,7 @@ public:
virtual size_t
FindGlobalVariables (const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
bool append,
size_t max_matches,
VariableList& variables);
@@ -110,7 +111,7 @@ public:
virtual size_t
FindFunctions (const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
uint32_t name_type_mask,
bool include_inlines,
bool append,
@@ -125,15 +126,18 @@ public:
virtual size_t
FindTypes (const SymbolContext& sc,
const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
bool append,
size_t max_matches,
- TypeList& types);
+ TypeMap& types);
- virtual ClangNamespaceDecl
+ virtual size_t
+ FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types);
+
+ virtual CompilerDeclContext
FindNamespace (const SymbolContext& sc,
const ConstString &name,
- const ClangNamespaceDecl *parent_namespace_decl);
+ const CompilerDeclContext *parent_decl_ctx);
virtual size_t
GetNumCompileUnits();
@@ -189,11 +193,11 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual ConstString
- GetPluginName();
+ ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
protected:
//------------------------------------------------------------------
@@ -215,7 +219,6 @@ private:
DISALLOW_COPY_AND_ASSIGN (SymbolVendor);
};
-
} // namespace lldb_private
-#endif // liblldb_SymbolVendor_h_
+#endif // liblldb_SymbolVendor_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/TaggedASTType.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/TaggedASTType.h
index c44a535..82431a5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/TaggedASTType.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/TaggedASTType.h
@@ -10,33 +10,33 @@
#ifndef liblldb_TaggedASTType_h_
#define liblldb_TaggedASTType_h_
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
namespace lldb_private
{
// For cases in which there are multiple classes of types that are not
// interchangeable, to allow static type checking.
-template <unsigned int C> class TaggedASTType : public ClangASTType
+template <unsigned int C> class TaggedASTType : public CompilerType
{
public:
- TaggedASTType (const ClangASTType &clang_type) :
- ClangASTType(clang_type)
+ TaggedASTType (const CompilerType &compiler_type) :
+ CompilerType(compiler_type)
{
}
- TaggedASTType (lldb::clang_type_t type, clang::ASTContext *ast_context) :
- ClangASTType(ast_context, type)
+ TaggedASTType (lldb::opaque_compiler_type_t type, TypeSystem * type_system) :
+ CompilerType(type_system, type)
{
}
TaggedASTType (const TaggedASTType<C> &tw) :
- ClangASTType(tw)
+ CompilerType(tw)
{
}
TaggedASTType () :
- ClangASTType()
+ CompilerType()
{
}
@@ -47,7 +47,7 @@ public:
TaggedASTType<C> &operator= (const TaggedASTType<C> &tw)
{
- ClangASTType::operator= (tw);
+ CompilerType::operator= (tw);
return *this;
}
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Type.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Type.h
index c1784cb..224e0a1 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Type.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Type.h
@@ -14,7 +14,8 @@
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/UserID.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Declaration.h"
#include "llvm/ADT/APSInt.h"
@@ -23,6 +24,31 @@
namespace lldb_private {
+//----------------------------------------------------------------------
+// CompilerContext allows an array of these items to be passed to
+// perform detailed lookups in SymbolVendor and SymbolFile functions.
+//----------------------------------------------------------------------
+struct CompilerContext
+{
+ CompilerContext (CompilerContextKind t, const ConstString &n) :
+ type(t),
+ name(n)
+ {
+ }
+
+ bool
+ operator == (const CompilerContext &rhs) const
+ {
+ return type == rhs.type && name == rhs.name;
+ }
+
+ void
+ Dump () const;
+
+ CompilerContextKind type;
+ ConstString name;
+};
+
class SymbolFileType :
public std::enable_shared_from_this<SymbolFileType>,
public UserID
@@ -34,6 +60,9 @@ class SymbolFileType :
{
}
+ SymbolFileType (SymbolFile &symbol_file, const lldb::TypeSP &type_sp);
+
+
~SymbolFileType ()
{
}
@@ -92,8 +121,8 @@ public:
lldb::user_id_t encoding_uid,
EncodingDataType encoding_uid_type,
const Declaration& decl,
- const ClangASTType &clang_qual_type,
- ResolveState clang_type_resolve_state);
+ const CompilerType &compiler_qual_type,
+ ResolveState compiler_type_resolve_state);
// This makes an invalid type. Used for functions that return a Type when they
// get an error.
@@ -239,22 +268,19 @@ public:
// Get the clang type, and resolve definitions for any
// class/struct/union/enum types completely.
- ClangASTType
- GetClangFullType ();
+ CompilerType
+ GetFullCompilerType ();
// Get the clang type, and resolve definitions enough so that the type could
// have layout performed. This allows ptrs and refs to class/struct/union/enum
// types remain forward declarations.
- ClangASTType
- GetClangLayoutType ();
+ CompilerType
+ GetLayoutCompilerType ();
// Get the clang type and leave class/struct/union/enum types as forward
// declarations if they haven't already been fully defined.
- ClangASTType
- GetClangForwardType ();
-
- ClangASTContext &
- GetClangASTContext ();
+ CompilerType
+ GetForwardCompilerType ();
static int
Compare(const Type &a, const Type &b);
@@ -275,12 +301,6 @@ public:
uint32_t
GetEncodingMask ();
- ClangASTType
- CreateClangTypedefType (Type *typedef_type, Type *base_type);
-
- bool
- IsRealObjCClass();
-
bool
IsCompleteObjCClass()
{
@@ -302,14 +322,14 @@ protected:
EncodingDataType m_encoding_uid_type;
uint64_t m_byte_size;
Declaration m_decl;
- ClangASTType m_clang_type;
+ CompilerType m_compiler_type;
struct Flags {
#ifdef __GNUC__
// using unsigned type here to work around a very noisy gcc warning
- unsigned clang_type_resolve_state : 2;
+ unsigned compiler_type_resolve_state : 2;
#else
- ResolveState clang_type_resolve_state : 2;
+ ResolveState compiler_type_resolve_state : 2;
#endif
bool is_complete_objc_class : 1;
} m_flags;
@@ -318,7 +338,7 @@ protected:
GetEncodingType ();
bool
- ResolveClangType (ResolveState clang_type_resolve_state);
+ ResolveClangType (ResolveState compiler_type_resolve_state);
};
// these classes are used to back the SBType* objects
@@ -327,28 +347,28 @@ class TypePair
{
public:
TypePair () :
- clang_type(),
+ compiler_type(),
type_sp()
{
}
- TypePair (ClangASTType type) :
- clang_type(type),
+ TypePair (CompilerType type) :
+ compiler_type(type),
type_sp()
{
}
TypePair (lldb::TypeSP type) :
- clang_type(),
- type_sp(type)
+ compiler_type(),
+ type_sp(type)
{
- clang_type = type_sp->GetClangForwardType();
+ compiler_type = type_sp->GetForwardCompilerType ();
}
bool
IsValid () const
{
- return clang_type.IsValid() || (type_sp.get() != nullptr);
+ return compiler_type.IsValid() || (type_sp.get() != nullptr);
}
explicit operator bool () const
@@ -359,21 +379,21 @@ public:
bool
operator == (const TypePair& rhs) const
{
- return clang_type == rhs.clang_type &&
+ return compiler_type == rhs.compiler_type &&
type_sp.get() == rhs.type_sp.get();
}
bool
operator != (const TypePair& rhs) const
{
- return clang_type != rhs.clang_type ||
+ return compiler_type != rhs.compiler_type ||
type_sp.get() != rhs.type_sp.get();
}
void
Clear ()
{
- clang_type.Clear();
+ compiler_type.Clear();
type_sp.reset();
}
@@ -382,8 +402,8 @@ public:
{
if (type_sp)
return type_sp->GetName();
- if (clang_type)
- return clang_type.GetTypeName();
+ if (compiler_type)
+ return compiler_type.GetTypeName();
return ConstString ();
}
@@ -391,24 +411,24 @@ public:
GetDisplayTypeName () const
{
if (type_sp)
- return type_sp->GetClangForwardType().GetDisplayTypeName();
- if (clang_type)
- return clang_type.GetDisplayTypeName();
+ return type_sp->GetForwardCompilerType ().GetDisplayTypeName();
+ if (compiler_type)
+ return compiler_type.GetDisplayTypeName();
return ConstString();
}
void
- SetType (ClangASTType type)
+ SetType (CompilerType type)
{
type_sp.reset();
- clang_type = type;
+ compiler_type = type;
}
void
SetType (lldb::TypeSP type)
{
type_sp = type;
- clang_type = type_sp->GetClangForwardType();
+ compiler_type = type_sp->GetForwardCompilerType ();
}
lldb::TypeSP
@@ -417,72 +437,76 @@ public:
return type_sp;
}
- ClangASTType
- GetClangASTType () const
+ CompilerType
+ GetCompilerType () const
{
- return clang_type;
+ return compiler_type;
}
- ClangASTType
+ CompilerType
GetPointerType () const
{
if (type_sp)
- return type_sp->GetClangLayoutType().GetPointerType();
- return clang_type.GetPointerType();
+ return type_sp->GetForwardCompilerType().GetPointerType();
+ return compiler_type.GetPointerType();
}
- ClangASTType
+ CompilerType
GetPointeeType () const
{
if (type_sp)
- return type_sp->GetClangFullType().GetPointeeType();
- return clang_type.GetPointeeType();
+ return type_sp->GetForwardCompilerType ().GetPointeeType();
+ return compiler_type.GetPointeeType();
}
- ClangASTType
+ CompilerType
GetReferenceType () const
{
if (type_sp)
- return type_sp->GetClangLayoutType().GetLValueReferenceType();
- return clang_type.GetLValueReferenceType();
+ return type_sp->GetForwardCompilerType ().GetLValueReferenceType();
+ else
+ return compiler_type.GetLValueReferenceType();
}
- ClangASTType
+ CompilerType
GetTypedefedType () const
{
if (type_sp)
- return type_sp->GetClangFullType().GetTypedefedType();
- return clang_type.GetTypedefedType();
+ return type_sp->GetForwardCompilerType ().GetTypedefedType();
+ else
+ return compiler_type.GetTypedefedType();
}
- ClangASTType
+ CompilerType
GetDereferencedType () const
{
if (type_sp)
- return type_sp->GetClangFullType().GetNonReferenceType();
- return clang_type.GetNonReferenceType();
+ return type_sp->GetForwardCompilerType ().GetNonReferenceType();
+ else
+ return compiler_type.GetNonReferenceType();
}
- ClangASTType
+ CompilerType
GetUnqualifiedType () const
{
if (type_sp)
- return type_sp->GetClangLayoutType().GetFullyUnqualifiedType();
- return clang_type.GetFullyUnqualifiedType();
+ return type_sp->GetForwardCompilerType ().GetFullyUnqualifiedType();
+ else
+ return compiler_type.GetFullyUnqualifiedType();
}
- ClangASTType
+ CompilerType
GetCanonicalType () const
{
if (type_sp)
- return type_sp->GetClangFullType().GetCanonicalType();
- return clang_type.GetCanonicalType();
+ return type_sp->GetForwardCompilerType ().GetCanonicalType();
+ return compiler_type.GetCanonicalType();
}
- clang::ASTContext *
- GetClangASTContext () const
+ TypeSystem *
+ GetTypeSystem () const
{
- return clang_type.GetASTContext();
+ return compiler_type.GetTypeSystem();
}
lldb::ModuleSP
@@ -493,10 +517,13 @@ public:
return lldb::ModuleSP();
}
protected:
- ClangASTType clang_type;
+ CompilerType compiler_type;
lldb::TypeSP type_sp;
};
+// the two classes here are used by the public API as a backend to
+// the SBType and SBTypeList classes
+
class TypeImpl
{
public:
@@ -509,28 +536,28 @@ public:
TypeImpl (const lldb::TypeSP &type_sp);
- TypeImpl (const ClangASTType &clang_type);
+ TypeImpl (const CompilerType &compiler_type);
- TypeImpl (const lldb::TypeSP &type_sp, const ClangASTType &dynamic);
+ TypeImpl (const lldb::TypeSP &type_sp, const CompilerType &dynamic);
- TypeImpl (const ClangASTType &clang_type, const ClangASTType &dynamic);
+ TypeImpl (const CompilerType &compiler_type, const CompilerType &dynamic);
- TypeImpl (const TypePair &pair, const ClangASTType &dynamic);
+ TypeImpl (const TypePair &pair, const CompilerType &dynamic);
void
SetType (const lldb::TypeSP &type_sp);
void
- SetType (const ClangASTType &clang_type);
+ SetType (const CompilerType &compiler_type);
void
- SetType (const lldb::TypeSP &type_sp, const ClangASTType &dynamic);
+ SetType (const lldb::TypeSP &type_sp, const CompilerType &dynamic);
void
- SetType (const ClangASTType &clang_type, const ClangASTType &dynamic);
+ SetType (const CompilerType &compiler_type, const CompilerType &dynamic);
void
- SetType (const TypePair &pair, const ClangASTType &dynamic);
+ SetType (const TypePair &pair, const CompilerType &dynamic);
TypeImpl&
operator = (const TypeImpl& rhs);
@@ -575,11 +602,11 @@ public:
TypeImpl
GetCanonicalType() const;
- ClangASTType
- GetClangASTType (bool prefer_dynamic);
+ CompilerType
+ GetCompilerType (bool prefer_dynamic);
- clang::ASTContext *
- GetClangASTContext (bool prefer_dynamic);
+ TypeSystem *
+ GetTypeSystem (bool prefer_dynamic);
bool
GetDescription (lldb_private::Stream &strm,
@@ -592,7 +619,7 @@ private:
lldb::ModuleWP m_module_wp;
TypePair m_static_type;
- ClangASTType m_dynamic_type;
+ CompilerType m_dynamic_type;
};
class TypeListImpl
@@ -750,7 +777,7 @@ class TypeAndOrName
public:
TypeAndOrName ();
TypeAndOrName (lldb::TypeSP &type_sp);
- TypeAndOrName (const ClangASTType &clang_type);
+ TypeAndOrName (const CompilerType &compiler_type);
TypeAndOrName (const char *type_str);
TypeAndOrName (const TypeAndOrName &rhs);
TypeAndOrName (ConstString &type_const_string);
@@ -772,10 +799,10 @@ public:
return m_type_pair.GetTypeSP();
}
- ClangASTType
- GetClangASTType () const
+ CompilerType
+ GetCompilerType () const
{
- return m_type_pair.GetClangASTType();
+ return m_type_pair.GetCompilerType();
}
void
@@ -788,7 +815,7 @@ public:
SetTypeSP (lldb::TypeSP type_sp);
void
- SetClangASTType (ClangASTType clang_type);
+ SetCompilerType (CompilerType compiler_type);
bool
IsEmpty () const;
@@ -800,12 +827,12 @@ public:
HasTypeSP () const;
bool
- HasClangASTType () const;
+ HasCompilerType () const;
bool
HasType () const
{
- return HasTypeSP() || HasClangASTType();
+ return HasTypeSP() || HasCompilerType();
}
void
@@ -825,60 +852,43 @@ class TypeMemberFunctionImpl
{
public:
TypeMemberFunctionImpl() :
- m_type(),
- m_objc_method_decl(nullptr),
+ m_type (),
+ m_decl (),
m_name(),
- m_kind(lldb::eMemberFunctionKindUnknown)
+ m_kind (lldb::eMemberFunctionKindUnknown)
{
}
- TypeMemberFunctionImpl (const ClangASTType& type,
+ TypeMemberFunctionImpl (const CompilerType& type,
+ const CompilerDecl& decl,
const std::string& name,
const lldb::MemberFunctionKind& kind) :
- m_type(type),
- m_objc_method_decl(nullptr),
+ m_type (type),
+ m_decl (decl),
m_name(name),
- m_kind(kind)
- {
- }
-
- TypeMemberFunctionImpl (clang::ObjCMethodDecl *method,
- const std::string& name,
- const lldb::MemberFunctionKind& kind) :
- m_type(),
- m_objc_method_decl(method),
- m_name(name),
- m_kind(kind)
- {
- }
-
- TypeMemberFunctionImpl (const TypeMemberFunctionImpl& rhs) :
- m_type(rhs.m_type),
- m_objc_method_decl(rhs.m_objc_method_decl),
- m_name(rhs.m_name),
- m_kind(rhs.m_kind)
+ m_kind (kind)
{
}
- TypeMemberFunctionImpl&
- operator = (const TypeMemberFunctionImpl& rhs);
-
bool
IsValid ();
ConstString
GetName () const;
-
- ClangASTType
+
+ ConstString
+ GetMangledName () const;
+
+ CompilerType
GetType () const;
- ClangASTType
+ CompilerType
GetReturnType () const;
size_t
GetNumArguments () const;
- ClangASTType
+ CompilerType
GetArgumentAtIndex (size_t idx) const;
lldb::MemberFunctionKind
@@ -892,8 +902,8 @@ protected:
GetPrintableTypeName ();
private:
- ClangASTType m_type;
- clang::ObjCMethodDecl *m_objc_method_decl;
+ CompilerType m_type;
+ CompilerDecl m_decl;
ConstString m_name;
lldb::MemberFunctionKind m_kind;
};
@@ -909,8 +919,9 @@ public:
{
}
- TypeEnumMemberImpl (const clang::EnumConstantDecl* enum_member_decl,
- const lldb_private::ClangASTType& integer_type);
+ TypeEnumMemberImpl (const lldb::TypeImplSP &integer_type_sp,
+ const ConstString &name,
+ const llvm::APSInt &value);
TypeEnumMemberImpl (const TypeEnumMemberImpl& rhs) :
m_integer_type_sp(rhs.m_integer_type_sp),
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeList.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeList.h
index 4f3f2c9..f364257 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeList.h
@@ -13,7 +13,7 @@
#include "lldb/lldb-private.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Utility/Iterable.h"
-#include <map>
+#include <vector>
#include <functional>
namespace lldb_private {
@@ -24,7 +24,7 @@ public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- TypeList();
+ TypeList();
virtual
~TypeList();
@@ -44,17 +44,14 @@ public:
void
Insert (const lldb::TypeSP& type);
- bool
- InsertUnique (const lldb::TypeSP& type);
-
uint32_t
GetSize() const;
lldb::TypeSP
GetTypeAtIndex(uint32_t idx);
- typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection;
- typedef AdaptedIterable<collection, lldb::TypeSP, map_adapter> TypeIterable;
+ typedef std::vector<lldb::TypeSP> collection;
+ typedef AdaptedIterable<collection, lldb::TypeSP, vector_adapter> TypeIterable;
TypeIterable
Types ()
@@ -68,8 +65,6 @@ public:
void
ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback);
- bool
- RemoveTypeWithUID (lldb::user_id_t uid);
void
RemoveMismatchedTypes (const char *qualified_typename,
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeMap.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeMap.h
new file mode 100644
index 0000000..4398acd
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeMap.h
@@ -0,0 +1,98 @@
+//===-- TypeMap.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_TypeMap_h_
+#define liblldb_TypeMap_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Utility/Iterable.h"
+#include <map>
+#include <functional>
+
+namespace lldb_private {
+
+class TypeMap
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ TypeMap();
+
+ virtual
+ ~TypeMap();
+
+ void
+ Clear();
+
+ void
+ Dump(Stream *s, bool show_context);
+
+ TypeMap
+ FindTypes(const ConstString &name);
+
+ void
+ Insert (const lldb::TypeSP& type);
+
+ bool
+ Empty() const;
+
+ bool
+ InsertUnique (const lldb::TypeSP& type);
+
+ uint32_t
+ GetSize() const;
+
+ lldb::TypeSP
+ GetTypeAtIndex(uint32_t idx);
+
+ typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection;
+ typedef AdaptedIterable<collection, lldb::TypeSP, map_adapter> TypeIterable;
+
+ TypeIterable
+ Types ()
+ {
+ return TypeIterable(m_types);
+ }
+
+ void
+ ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const;
+
+ void
+ ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback);
+
+ bool
+ Remove (const lldb::TypeSP &type_sp);
+
+ void
+ RemoveMismatchedTypes (const char *qualified_typename,
+ bool exact_match);
+
+ void
+ RemoveMismatchedTypes (const std::string &type_scope,
+ const std::string &type_basename,
+ lldb::TypeClass type_class,
+ bool exact_match);
+
+ void
+ RemoveMismatchedTypes (lldb::TypeClass type_class);
+
+private:
+ typedef collection::iterator iterator;
+ typedef collection::const_iterator const_iterator;
+
+ collection m_types;
+
+ DISALLOW_COPY_AND_ASSIGN (TypeMap);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_TypeMap_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeSystem.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeSystem.h
new file mode 100644
index 0000000..9b43b9d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/TypeSystem.h
@@ -0,0 +1,607 @@
+//===-- TypeSystem.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_TypeSystem_h_
+#define liblldb_TypeSystem_h_
+
+// C Includes
+// C++ Includes
+#include <functional>
+#include <map>
+#include <string>
+
+// Other libraries and framework includes
+#include "llvm/ADT/APSInt.h"
+#include "llvm/Support/Casting.h"
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Expression/Expression.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
+
+class DWARFDIE;
+class DWARFASTParser;
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+// Interface for representing the Type Systems in different languages.
+//----------------------------------------------------------------------
+class TypeSystem : public PluginInterface
+{
+public:
+ //----------------------------------------------------------------------
+ // Intrusive type system that allows us to use llvm casting.
+ //
+ // To add a new type system:
+ //
+ // 1 - Add a new enumeration for llvm casting below for your TypeSystem
+ // subclass, here we will use eKindFoo
+ //
+ // 2 - Your TypeSystem subclass will inherit from TypeSystem and needs
+ // to implement a static classof() function that returns your
+ // enumeration:
+ //
+ // class Foo : public lldb_private::TypeSystem
+ // {
+ // static bool classof(const TypeSystem *ts)
+ // {
+ // return ts->getKind() == TypeSystem::eKindFoo;
+ // }
+ // };
+ //
+ // 3 - Contruct your TypeSystem subclass with the enumeration from below
+ //
+ // Foo() :
+ // TypeSystem(TypeSystem::eKindFoo),
+ // ...
+ // {
+ // }
+ //
+ // Then you can use the llvm casting on any "TypeSystem *" to get an
+ // instance of your subclass.
+ //----------------------------------------------------------------------
+ enum LLVMCastKind {
+ eKindClang,
+ eKindSwift,
+ eKindGo,
+ kNumKinds
+ };
+
+ //----------------------------------------------------------------------
+ // Constructors and Destructors
+ //----------------------------------------------------------------------
+ TypeSystem(LLVMCastKind kind);
+
+ ~TypeSystem() override;
+
+ LLVMCastKind getKind() const { return m_kind; }
+
+ static lldb::TypeSystemSP
+ CreateInstance (lldb::LanguageType language, Module *module);
+
+ static lldb::TypeSystemSP
+ CreateInstance (lldb::LanguageType language, Target *target);
+
+ virtual DWARFASTParser *
+ GetDWARFParser ()
+ {
+ return nullptr;
+ }
+
+ virtual SymbolFile *
+ GetSymbolFile () const
+ {
+ return m_sym_file;
+ }
+
+ // Returns true if the symbol file changed during the set accessor.
+ virtual void
+ SetSymbolFile (SymbolFile *sym_file)
+ {
+ m_sym_file = sym_file;
+ }
+
+ //----------------------------------------------------------------------
+ // CompilerDecl functions
+ //----------------------------------------------------------------------
+ virtual ConstString
+ DeclGetName (void *opaque_decl) = 0;
+
+ virtual ConstString
+ DeclGetMangledName (void *opaque_decl);
+
+ virtual lldb::VariableSP
+ DeclGetVariable (void *opaque_decl) = 0;
+
+ virtual void
+ DeclLinkToObject (void *opaque_decl, std::shared_ptr<void> object) = 0;
+
+ virtual CompilerDeclContext
+ DeclGetDeclContext (void *opaque_decl);
+
+ virtual CompilerType
+ DeclGetFunctionReturnType(void *opaque_decl);
+
+ virtual size_t
+ DeclGetFunctionNumArguments(void *opaque_decl);
+
+ virtual CompilerType
+ DeclGetFunctionArgumentType (void *opaque_decl, size_t arg_idx);
+
+ //----------------------------------------------------------------------
+ // CompilerDeclContext functions
+ //----------------------------------------------------------------------
+
+ virtual std::vector<CompilerDecl>
+ DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name);
+
+ virtual bool
+ DeclContextIsStructUnionOrClass (void *opaque_decl_ctx) = 0;
+
+ virtual ConstString
+ DeclContextGetName (void *opaque_decl_ctx) = 0;
+
+ virtual ConstString
+ DeclContextGetScopeQualifiedName (void *opaque_decl_ctx) = 0;
+
+ virtual bool
+ DeclContextIsClassMethod (void *opaque_decl_ctx,
+ lldb::LanguageType *language_ptr,
+ bool *is_instance_method_ptr,
+ ConstString *language_object_name_ptr) = 0;
+
+ //----------------------------------------------------------------------
+ // Tests
+ //----------------------------------------------------------------------
+
+ virtual bool
+ IsArrayType (lldb::opaque_compiler_type_t type,
+ CompilerType *element_type,
+ uint64_t *size,
+ bool *is_incomplete) = 0;
+
+ virtual bool
+ IsAggregateType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual bool
+ IsAnonymousType (lldb::opaque_compiler_type_t type);
+
+ virtual bool
+ IsCharType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual bool
+ IsCompleteType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual bool
+ IsDefined(lldb::opaque_compiler_type_t type) = 0;
+
+ virtual bool
+ IsFloatingPointType (lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) = 0;
+
+ virtual bool
+ IsFunctionType (lldb::opaque_compiler_type_t type, bool *is_variadic_ptr) = 0;
+
+ virtual size_t
+ GetNumberOfFunctionArguments (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual CompilerType
+ GetFunctionArgumentAtIndex (lldb::opaque_compiler_type_t type, const size_t index) = 0;
+
+ virtual bool
+ IsFunctionPointerType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual bool
+ IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_signed) = 0;
+
+ virtual bool
+ IsPossibleDynamicType (lldb::opaque_compiler_type_t type,
+ CompilerType *target_type, // Can pass NULL
+ bool check_cplusplus,
+ bool check_objc) = 0;
+
+ virtual bool
+ IsPointerType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type) = 0;
+
+ virtual bool
+ IsScalarType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual bool
+ IsVoidType (lldb::opaque_compiler_type_t type) = 0;
+
+ // TypeSystems can support more than one language
+ virtual bool
+ SupportsLanguage (lldb::LanguageType language) = 0;
+
+ //----------------------------------------------------------------------
+ // Type Completion
+ //----------------------------------------------------------------------
+
+ virtual bool
+ GetCompleteType (lldb::opaque_compiler_type_t type) = 0;
+
+ //----------------------------------------------------------------------
+ // AST related queries
+ //----------------------------------------------------------------------
+
+ virtual uint32_t
+ GetPointerByteSize () = 0;
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+
+ virtual ConstString
+ GetTypeName (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual uint32_t
+ GetTypeInfo (lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type) = 0;
+
+ virtual lldb::LanguageType
+ GetMinimumLanguage (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual lldb::TypeClass
+ GetTypeClass (lldb::opaque_compiler_type_t type) = 0;
+
+ //----------------------------------------------------------------------
+ // Creating related types
+ //----------------------------------------------------------------------
+
+ virtual CompilerType
+ GetArrayElementType (lldb::opaque_compiler_type_t type, uint64_t *stride) = 0;
+
+ virtual CompilerType
+ GetCanonicalType (lldb::opaque_compiler_type_t type) = 0;
+
+ // Returns -1 if this isn't a function of if the function doesn't have a prototype
+ // Returns a value >= 0 if there is a prototype.
+ virtual int
+ GetFunctionArgumentCount (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual CompilerType
+ GetFunctionArgumentTypeAtIndex (lldb::opaque_compiler_type_t type, size_t idx) = 0;
+
+ virtual CompilerType
+ GetFunctionReturnType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual size_t
+ GetNumMemberFunctions (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual TypeMemberFunctionImpl
+ GetMemberFunctionAtIndex (lldb::opaque_compiler_type_t type, size_t idx) = 0;
+
+ virtual CompilerType
+ GetPointeeType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual CompilerType
+ GetPointerType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual CompilerType
+ GetLValueReferenceType (lldb::opaque_compiler_type_t type);
+
+ virtual CompilerType
+ GetRValueReferenceType (lldb::opaque_compiler_type_t type);
+
+ virtual CompilerType
+ AddConstModifier (lldb::opaque_compiler_type_t type);
+
+ virtual CompilerType
+ AddVolatileModifier (lldb::opaque_compiler_type_t type);
+
+ virtual CompilerType
+ AddRestrictModifier (lldb::opaque_compiler_type_t type);
+
+ virtual CompilerType
+ CreateTypedef (lldb::opaque_compiler_type_t type, const char *name, const CompilerDeclContext &decl_ctx);
+
+ //----------------------------------------------------------------------
+ // Exploring the type
+ //----------------------------------------------------------------------
+
+ virtual uint64_t
+ GetBitSize (lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) = 0;
+
+ virtual lldb::Encoding
+ GetEncoding (lldb::opaque_compiler_type_t type, uint64_t &count) = 0;
+
+ virtual lldb::Format
+ GetFormat (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual uint32_t
+ GetNumChildren (lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) = 0;
+
+ virtual CompilerType
+ GetBuiltinTypeByName (const ConstString &name);
+
+ virtual lldb::BasicType
+ GetBasicTypeEnumeration (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual void
+ ForEachEnumerator (lldb::opaque_compiler_type_t type, std::function <bool (const CompilerType &integer_type, const ConstString &name, const llvm::APSInt &value)> const &callback)
+ {
+ }
+
+ virtual uint32_t
+ GetNumFields (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual CompilerType
+ GetFieldAtIndex (lldb::opaque_compiler_type_t type,
+ size_t idx,
+ std::string& name,
+ uint64_t *bit_offset_ptr,
+ uint32_t *bitfield_bit_size_ptr,
+ bool *is_bitfield_ptr) = 0;
+
+ virtual uint32_t
+ GetNumDirectBaseClasses (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual uint32_t
+ GetNumVirtualBaseClasses (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual CompilerType
+ GetDirectBaseClassAtIndex (lldb::opaque_compiler_type_t type,
+ size_t idx,
+ uint32_t *bit_offset_ptr) = 0;
+
+ virtual CompilerType
+ GetVirtualBaseClassAtIndex (lldb::opaque_compiler_type_t type,
+ size_t idx,
+ uint32_t *bit_offset_ptr) = 0;
+
+ virtual CompilerType
+ GetChildCompilerTypeAtIndex (lldb::opaque_compiler_type_t type,
+ ExecutionContext *exe_ctx,
+ size_t idx,
+ bool transparent_pointers,
+ bool omit_empty_base_classes,
+ bool ignore_array_bounds,
+ std::string& child_name,
+ uint32_t &child_byte_size,
+ int32_t &child_byte_offset,
+ uint32_t &child_bitfield_bit_size,
+ uint32_t &child_bitfield_bit_offset,
+ bool &child_is_base_class,
+ bool &child_is_deref_of_parent,
+ ValueObject *valobj,
+ uint64_t &language_flags) = 0;
+
+ // Lookup a child given a name. This function will match base class names
+ // and member member names in "clang_type" only, not descendants.
+ virtual uint32_t
+ GetIndexOfChildWithName (lldb::opaque_compiler_type_t type,
+ const char *name,
+ bool omit_empty_base_classes) = 0;
+
+ // Lookup a child member given a name. This function will match member names
+ // only and will descend into "clang_type" children in search for the first
+ // member in this class, or any base class that matches "name".
+ // TODO: Return all matches for a given name by returning a vector<vector<uint32_t>>
+ // so we catch all names that match a given child name, not just the first.
+ virtual size_t
+ GetIndexOfChildMemberWithName (lldb::opaque_compiler_type_t type,
+ const char *name,
+ bool omit_empty_base_classes,
+ std::vector<uint32_t>& child_indexes) = 0;
+
+ virtual size_t
+ GetNumTemplateArguments (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual CompilerType
+ GetTemplateArgument (lldb::opaque_compiler_type_t type,
+ size_t idx,
+ lldb::TemplateArgumentKind &kind) = 0;
+
+ //----------------------------------------------------------------------
+ // Dumping types
+ //----------------------------------------------------------------------
+
+ virtual void
+ DumpValue (lldb::opaque_compiler_type_t type,
+ ExecutionContext *exe_ctx,
+ Stream *s,
+ lldb::Format format,
+ const DataExtractor &data,
+ lldb::offset_t data_offset,
+ size_t data_byte_size,
+ uint32_t bitfield_bit_size,
+ uint32_t bitfield_bit_offset,
+ bool show_types,
+ bool show_summary,
+ bool verbose,
+ uint32_t depth) = 0;
+
+ virtual bool
+ DumpTypeValue (lldb::opaque_compiler_type_t type,
+ Stream *s,
+ lldb::Format format,
+ const DataExtractor &data,
+ lldb::offset_t data_offset,
+ size_t data_byte_size,
+ uint32_t bitfield_bit_size,
+ uint32_t bitfield_bit_offset,
+ ExecutionContextScope *exe_scope) = 0;
+
+ virtual void
+ DumpTypeDescription (lldb::opaque_compiler_type_t type) = 0; // Dump to stdout
+
+ virtual void
+ DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream *s) = 0;
+
+ //----------------------------------------------------------------------
+ // TODO: These methods appear unused. Should they be removed?
+ //----------------------------------------------------------------------
+
+ virtual bool
+ IsRuntimeGeneratedType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual void
+ DumpSummary (lldb::opaque_compiler_type_t type,
+ ExecutionContext *exe_ctx,
+ Stream *s,
+ const DataExtractor &data,
+ lldb::offset_t data_offset,
+ size_t data_byte_size) = 0;
+
+ // Converts "s" to a floating point value and place resulting floating
+ // point bytes in the "dst" buffer.
+ virtual size_t
+ ConvertStringToFloatValue (lldb::opaque_compiler_type_t type,
+ const char *s,
+ uint8_t *dst,
+ size_t dst_size) = 0;
+
+ //----------------------------------------------------------------------
+ // TODO: Determine if these methods should move to ClangASTContext.
+ //----------------------------------------------------------------------
+
+ virtual bool
+ IsPointerOrReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type) = 0;
+
+ virtual unsigned
+ GetTypeQualifiers(lldb::opaque_compiler_type_t type) = 0;
+
+ virtual bool
+ IsCStringType (lldb::opaque_compiler_type_t type, uint32_t &length) = 0;
+
+ virtual size_t
+ GetTypeBitAlign (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual CompilerType
+ GetBasicTypeFromAST (lldb::BasicType basic_type) = 0;
+
+ virtual CompilerType
+ GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
+ size_t bit_size) = 0;
+
+ virtual bool
+ IsBeingDefined (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual bool
+ IsConst(lldb::opaque_compiler_type_t type) = 0;
+
+ virtual uint32_t
+ IsHomogeneousAggregate (lldb::opaque_compiler_type_t type, CompilerType* base_type_ptr) = 0;
+
+ virtual bool
+ IsPolymorphicClass (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual bool
+ IsTypedefType (lldb::opaque_compiler_type_t type) = 0;
+
+ // If the current object represents a typedef type, get the underlying type
+ virtual CompilerType
+ GetTypedefedType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual bool
+ IsVectorType (lldb::opaque_compiler_type_t type,
+ CompilerType *element_type,
+ uint64_t *size) = 0;
+
+ virtual CompilerType
+ GetFullyUnqualifiedType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual CompilerType
+ GetNonReferenceType (lldb::opaque_compiler_type_t type) = 0;
+
+ virtual bool
+ IsReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool* is_rvalue) = 0;
+
+ virtual bool
+ ShouldTreatScalarValueAsAddress (lldb::opaque_compiler_type_t type)
+ {
+ return IsPointerOrReferenceType(type, nullptr);
+ }
+
+ virtual UserExpression *
+ GetUserExpression (const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ Expression::ResultType desired_type,
+ const EvaluateExpressionOptions &options)
+ {
+ return nullptr;
+ }
+
+ virtual FunctionCaller *
+ GetFunctionCaller (const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name)
+ {
+ return nullptr;
+ }
+
+ virtual UtilityFunction *
+ GetUtilityFunction(const char *text, const char *name)
+ {
+ return nullptr;
+ }
+
+ virtual PersistentExpressionState *
+ GetPersistentExpressionState()
+ {
+ return nullptr;
+ }
+
+ virtual CompilerType
+ GetTypeForFormatters (void* type);
+
+ virtual LazyBool
+ ShouldPrintAsOneLiner (void* type, ValueObject* valobj);
+
+ // Type systems can have types that are placeholder types, which are meant to indicate
+ // the presence of a type, but offer no actual information about said types, and leave
+ // the burden of actually figuring type information out to dynamic type resolution. For instance
+ // a language with a generics system, can use placeholder types to indicate "type argument goes here",
+ // without promising uniqueness of the placeholder, nor attaching any actually idenfiable information
+ // to said placeholder. This API allows type systems to tell LLDB when such a type has been encountered
+ // In response, the debugger can react by not using this type as a cache entry in any type-specific way
+ // For instance, LLDB will currently not cache any formatters that are discovered on such a type as
+ // attributable to the meaningless type itself, instead preferring to use the dynamic type
+ virtual bool
+ IsMeaninglessWithoutDynamicResolution (void* type);
+
+protected:
+ const LLVMCastKind m_kind; // Support for llvm casting
+ SymbolFile *m_sym_file;
+
+};
+
+ class TypeSystemMap
+ {
+ public:
+ TypeSystemMap ();
+ ~TypeSystemMap();
+
+ void
+ Clear ();
+
+ // Iterate through all of the type systems that are created. Return true
+ // from callback to keep iterating, false to stop iterating.
+ void
+ ForEach (std::function <bool(TypeSystem *)> const &callback);
+
+ TypeSystem *
+ GetTypeSystemForLanguage (lldb::LanguageType language, Module *module, bool can_create);
+
+ TypeSystem *
+ GetTypeSystemForLanguage (lldb::LanguageType language, Target *target, bool can_create);
+
+ protected:
+ typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> collection;
+ mutable Mutex m_mutex; ///< A mutex to keep this object happy in multi-threaded environments.
+ collection m_map;
+ };
+
+} // namespace lldb_private
+
+#endif // liblldb_TypeSystem_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h
index bfc008a..7110013 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h
@@ -1,14 +1,28 @@
+//===-- UnwindPlan.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
#ifndef liblldb_UnwindPlan_h
#define liblldb_UnwindPlan_h
+// C Includes
+// C++ Includes
+#include <map>
+#include <memory>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ConstString.h"
-#include <map>
-#include <vector>
-
namespace lldb_private {
// The UnwindPlan object specifies how to unwind out of a function - where
@@ -38,13 +52,11 @@ namespace lldb_private {
class UnwindPlan {
public:
-
class Row {
public:
class RegisterLocation
{
public:
-
enum RestoreType
{
unspecified, // not specified, we may be able to assume this
@@ -187,7 +199,7 @@ public:
}
else
{
- *opcodes = NULL;
+ *opcodes = nullptr;
len = 0;
}
}
@@ -203,7 +215,7 @@ public:
{
if (m_type == atDWARFExpression || m_type == isDWARFExpression)
return m_location.expr.opcodes;
- return NULL;
+ return nullptr;
}
int
@@ -240,7 +252,6 @@ public:
class CFAValue
{
public:
-
enum ValueType
{
unspecified, // not specified
@@ -361,7 +372,7 @@ public:
}
else
{
- *opcodes = NULL;
+ *opcodes = nullptr;
len = 0;
}
}
@@ -371,7 +382,7 @@ public:
{
if (m_type == isDWARFExpression)
return m_value.expr.opcodes;
- return NULL;
+ return nullptr;
}
int
@@ -488,7 +499,6 @@ public:
}; // class Row
public:
-
typedef std::shared_ptr<Row> RowSP;
UnwindPlan (lldb::RegisterKind reg_kind) :
@@ -520,9 +530,7 @@ public:
m_row_list.emplace_back (new Row (*row_sp));
}
- ~UnwindPlan ()
- {
- }
+ ~UnwindPlan() = default;
void
Dump (Stream& s, Thread* thread, lldb::addr_t base_addr) const;
@@ -676,8 +684,6 @@ public:
}
private:
-
-
typedef std::vector<RowSP> collection;
collection m_row_list;
AddressRange m_plan_valid_address_range;
@@ -697,4 +703,4 @@ private:
} // namespace lldb_private
-#endif //liblldb_UnwindPlan_h
+#endif // liblldb_UnwindPlan_h
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindTable.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindTable.h
index 38d3ff6..f69e466 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindTable.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindTable.h
@@ -34,6 +34,9 @@ public:
lldb_private::CompactUnwindInfo *
GetCompactUnwindInfo ();
+ ArmUnwindInfo *
+ GetArmUnwindInfo ();
+
lldb::FuncUnwindersSP
GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc);
@@ -65,9 +68,10 @@ private:
bool m_initialized; // delay some initialization until ObjectFile is set up
Mutex m_mutex;
- DWARFCallFrameInfo* m_eh_frame;
- CompactUnwindInfo *m_compact_unwind;
-
+ std::unique_ptr<DWARFCallFrameInfo> m_eh_frame_up;
+ std::unique_ptr<CompactUnwindInfo> m_compact_unwind_up;
+ std::unique_ptr<ArmUnwindInfo> m_arm_unwind_up;
+
DISALLOW_COPY_AND_ASSIGN (UnwindTable);
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/Variable.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/Variable.h
index 8d413ca..1cac5d0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/Variable.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/Variable.h
@@ -1,4 +1,5 @@
-//===-- Variable.h ----------------------------------------------*- C++ -*-===//
+//===-- Variable.h ----------------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,6 +11,7 @@
#ifndef liblldb_Variable_h_
#define liblldb_Variable_h_
+#include <memory>
#include <vector>
#include "lldb/lldb-private.h"
@@ -21,7 +23,8 @@
namespace lldb_private {
-class Variable : public UserID
+class Variable : public UserID,
+ public std::enable_shared_from_this<Variable>
{
public:
//------------------------------------------------------------------
@@ -36,7 +39,8 @@ public:
Declaration* decl,
const DWARFExpression& location,
bool external,
- bool artificial);
+ bool artificial,
+ bool static_member = false);
virtual
~Variable();
@@ -58,6 +62,9 @@ public:
ConstString
GetName() const;
+ ConstString
+ GetUnqualifiedName() const;
+
SymbolContextScope *
GetSymbolContextScope() const
{
@@ -99,6 +106,11 @@ public:
return m_artificial;
}
+ bool IsStaticMember() const
+ {
+ return m_static_member;
+ }
+
DWARFExpression &
LocationExpression()
{
@@ -161,6 +173,11 @@ public:
StringList &matches,
bool &word_complete);
+ CompilerDeclContext
+ GetDeclContext ();
+
+ CompilerDecl
+ GetDecl ();
protected:
ConstString m_name; // The basename of the variable (no namespaces)
Mangled m_mangled; // The mangled name of the variable
@@ -171,7 +188,8 @@ protected:
DWARFExpression m_location; // The location of this variable that can be fed to DWARFExpression::Evaluate()
uint8_t m_external:1, // Visible outside the containing compile unit?
m_artificial:1, // Non-zero if the variable is not explicitly declared in source
- m_loc_is_const_data:1; // The m_location expression contains the constant variable value data, not a DWARF location
+ m_loc_is_const_data:1, // The m_location expression contains the constant variable value data, not a DWARF location
+ m_static_member:1; // Non-zero if variable is static member of a class or struct.
private:
Variable(const Variable& rhs);
Variable& operator=(const Variable& rhs);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Symbol/VariableList.h b/contrib/llvm/tools/lldb/include/lldb/Symbol/VariableList.h
index 5f8f2a2..1c1d5df 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Symbol/VariableList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Symbol/VariableList.h
@@ -48,10 +48,10 @@ public:
RemoveVariableAtIndex (size_t idx);
lldb::VariableSP
- FindVariable (const ConstString& name);
+ FindVariable (const ConstString& name, bool include_static_members = true);
lldb::VariableSP
- FindVariable (const ConstString& name, lldb::ValueType value_type);
+ FindVariable (const ConstString& name, lldb::ValueType value_type, bool include_static_members = true);
uint32_t
FindVariableIndex (const lldb::VariableSP &var_sp);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ABI.h b/contrib/llvm/tools/lldb/include/lldb/Target/ABI.h
index 89d4f6b..94826d1 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ABI.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ABI.h
@@ -44,8 +44,7 @@ public:
std::unique_ptr<uint8_t[]> data_ap; /* host data pointer */
};
- virtual
- ~ABI();
+ ~ABI() override;
virtual size_t
GetRedZoneSize () const = 0;
@@ -78,7 +77,7 @@ public:
lldb::ValueObjectSP
GetReturnValueObject (Thread &thread,
- ClangASTType &type,
+ CompilerType &type,
bool persistent = true) const;
// specialized to work with llvm IR types
@@ -95,7 +94,7 @@ protected:
// This is the method the ABI will call to actually calculate the return value.
// Don't put it in a persistent value object, that will be done by the ABI::GetReturnValueObject.
virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type) const = 0;
+ GetReturnValueObjectImpl (Thread &thread, CompilerType &ast_type) const = 0;
// specialized to work with llvm IR types
virtual lldb::ValueObjectSP
@@ -148,14 +147,17 @@ public:
FindPlugin (const ArchSpec &arch);
protected:
+
//------------------------------------------------------------------
// Classes that inherit from ABI can see and modify these
//------------------------------------------------------------------
ABI();
+
private:
+
DISALLOW_COPY_AND_ASSIGN (ABI);
};
} // namespace lldb_private
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABI_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/CPPLanguageRuntime.h b/contrib/llvm/tools/lldb/include/lldb/Target/CPPLanguageRuntime.h
index 3e51453..788f4e6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/CPPLanguageRuntime.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/CPPLanguageRuntime.h
@@ -25,100 +25,10 @@ class CPPLanguageRuntime :
public LanguageRuntime
{
public:
+ ~CPPLanguageRuntime() override;
- class MethodName
- {
- public:
- enum Type
- {
- eTypeInvalid,
- eTypeUnknownMethod,
- eTypeClassMethod,
- eTypeInstanceMethod
- };
-
- MethodName () :
- m_full(),
- m_basename(),
- m_context(),
- m_arguments(),
- m_qualifiers(),
- m_type (eTypeInvalid),
- m_parsed (false),
- m_parse_error (false)
- {
- }
-
- MethodName (const ConstString &s) :
- m_full(s),
- m_basename(),
- m_context(),
- m_arguments(),
- m_qualifiers(),
- m_type (eTypeInvalid),
- m_parsed (false),
- m_parse_error (false)
- {
- }
-
- void
- Clear();
-
- bool
- IsValid ()
- {
- if (!m_parsed)
- Parse();
- if (m_parse_error)
- return false;
- if (m_type == eTypeInvalid)
- return false;
- return (bool)m_full;
- }
-
- Type
- GetType () const
- {
- return m_type;
- }
-
- const ConstString &
- GetFullName () const
- {
- return m_full;
- }
-
- llvm::StringRef
- GetBasename ();
-
- llvm::StringRef
- GetContext ();
-
- llvm::StringRef
- GetArguments ();
-
- llvm::StringRef
- GetQualifiers ();
-
- protected:
- void
- Parse();
-
- ConstString m_full; // Full name: "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) const"
- llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex"
- llvm::StringRef m_context; // Decl context: "lldb::SBTarget"
- llvm::StringRef m_arguments; // Arguments: "(unsigned int)"
- llvm::StringRef m_qualifiers; // Qualifiers: "const"
- Type m_type;
- bool m_parsed;
- bool m_parse_error;
- };
-
- virtual
- ~CPPLanguageRuntime();
-
- virtual lldb::LanguageType
- GetLanguageType () const
+ lldb::LanguageType
+ GetLanguageType() const override
{
return lldb::eLanguageTypeC_plus_plus;
}
@@ -126,45 +36,24 @@ public:
virtual bool
IsVTableName (const char *name) = 0;
- virtual bool
- GetObjectDescription (Stream &str, ValueObject &object);
+ bool
+ GetObjectDescription(Stream &str, ValueObject &object) override;
- virtual bool
- GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope);
+ bool
+ GetObjectDescription(Stream &str, Value &value, ExecutionContextScope *exe_scope) override;
- static bool
- IsCPPMangledName(const char *name);
-
- // Extract C++ context and identifier from a string using heuristic matching (as opposed to
- // CPPLanguageRuntime::MethodName which has to have a fully qualified C++ name with parens and arguments.
- // If the name is a lone C identifier (e.g. C) or a qualified C identifier (e.g. A::B::C) it will return true,
- // and identifier will be the identifier (C and C respectively) and the context will be "" and "A::B::" respectively.
- // If the name fails the heuristic matching for a qualified or unqualified C/C++ identifier, then it will return false
- // and identifier and context will be unchanged.
-
- static bool
- ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier);
-
- // in some cases, compilers will output different names for one same type. when that happens, it might be impossible
- // to construct SBType objects for a valid type, because the name that is available is not the same as the name that
- // can be used as a search key in FindTypes(). the equivalents map here is meant to return possible alternative names
- // for a type through which a search can be conducted. Currently, this is only enabled for C++ but can be extended
- // to ObjC or other languages if necessary
- static uint32_t
- FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents);
-
- virtual size_t
- GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) = 0;
-
protected:
+
//------------------------------------------------------------------
// Classes that inherit from CPPLanguageRuntime can see and modify these
//------------------------------------------------------------------
CPPLanguageRuntime(Process *process);
+
private:
+
DISALLOW_COPY_AND_ASSIGN (CPPLanguageRuntime);
};
} // namespace lldb_private
-#endif // liblldb_CPPLanguageRuntime_h_
+#endif // liblldb_CPPLanguageRuntime_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/DynamicLoader.h b/contrib/llvm/tools/lldb/include/lldb/Target/DynamicLoader.h
index 6652a5e..5eada03 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/DynamicLoader.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/DynamicLoader.h
@@ -71,8 +71,7 @@ public:
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
- virtual
- ~DynamicLoader ();
+ ~DynamicLoader() override;
//------------------------------------------------------------------
/// Called after attaching a process.
@@ -264,12 +263,14 @@ protected:
virtual void
UpdateLoadedSections(lldb::ModuleSP module,
lldb::addr_t link_map_addr,
- lldb::addr_t base_addr);
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset);
// Utility method so base classes can share implementation of UpdateLoadedSections
void
UpdateLoadedSectionsCommon(lldb::ModuleSP module,
- lldb::addr_t base_addr);
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset);
/// Removes the loaded sections from the target in @p module.
///
@@ -283,8 +284,11 @@ protected:
/// Locates or creates a module given by @p file and updates/loads the
/// resulting module at the virtual base address @p base_addr.
- lldb::ModuleSP
- LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr);
+ virtual lldb::ModuleSP
+ LoadModuleAtAddress(const lldb_private::FileSpec &file,
+ lldb::addr_t link_map_addr,
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset);
const lldb_private::SectionList *
GetSectionListFromModule(const lldb::ModuleSP module) const;
@@ -303,11 +307,12 @@ protected:
// Member variables.
//------------------------------------------------------------------
Process* m_process; ///< The process that this dynamic loader plug-in is tracking.
+
private:
- DISALLOW_COPY_AND_ASSIGN (DynamicLoader);
+ DISALLOW_COPY_AND_ASSIGN (DynamicLoader);
};
} // namespace lldb_private
-#endif // liblldb_DynamicLoader_h_
+#endif // liblldb_DynamicLoader_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContext.h b/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContext.h
index 50f2bea..cdf55e3 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContext.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ExecutionContext.h
@@ -6,6 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ExecutionContext_h_
+#define liblldb_ExecutionContext_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/StackID.h"
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private {
+
+//===----------------------------------------------------------------------===//
/// Execution context objects refer to objects in the execution of the
/// program that is being debugged. The consist of one or more of the
/// following objects: target, process, thread, and frame. Many objects
@@ -30,17 +45,6 @@
/// to a wide variety of functions that require execution contexts.
//===----------------------------------------------------------------------===//
-
-
-#ifndef liblldb_ExecutionContext_h_
-#define liblldb_ExecutionContext_h_
-
-#include "lldb/lldb-private.h"
-#include "lldb/Target/StackID.h"
-#include "lldb/Host/Mutex.h"
-
-namespace lldb_private {
-
//----------------------------------------------------------------------
/// @class ExecutionContextRef ExecutionContext.h "lldb/Target/ExecutionContext.h"
/// @brief A class that holds a weak reference to an execution context.
@@ -86,7 +90,7 @@ public:
ExecutionContextRef (const ExecutionContextRef &rhs);
//------------------------------------------------------------------
- /// Construct using an ExecutionContext object that might be NULL.
+ /// Construct using an ExecutionContext object that might be nullptr.
///
/// If \a exe_ctx_ptr is valid, then make weak references to any
/// valid objects in the ExecutionContext, otherwise no weak
@@ -102,22 +106,6 @@ public:
ExecutionContextRef (const ExecutionContext &exe_ctx);
//------------------------------------------------------------------
- /// Assignment operator
- ///
- /// Copy all weak references in \a rhs.
- //------------------------------------------------------------------
- ExecutionContextRef &
- operator =(const ExecutionContextRef &rhs);
-
- //------------------------------------------------------------------
- /// Assignment operator from a ExecutionContext
- ///
- /// Make weak references to any strongly referenced objects in \a exe_ctx.
- //------------------------------------------------------------------
- ExecutionContextRef &
- operator =(const ExecutionContext &exe_ctx);
-
- //------------------------------------------------------------------
/// Construct using the target and all the selected items inside of it
/// (the process and its selected thread, and the thread's selected
/// frame). If there is no selected thread, default to the first thread
@@ -154,10 +142,27 @@ public:
ExecutionContextRef (ExecutionContextScope &exe_scope);
~ExecutionContextRef();
+
+ //------------------------------------------------------------------
+ /// Assignment operator
+ ///
+ /// Copy all weak references in \a rhs.
+ //------------------------------------------------------------------
+ ExecutionContextRef &
+ operator =(const ExecutionContextRef &rhs);
+
+ //------------------------------------------------------------------
+ /// Assignment operator from a ExecutionContext
+ ///
+ /// Make weak references to any strongly referenced objects in \a exe_ctx.
+ //------------------------------------------------------------------
+ ExecutionContextRef &
+ operator =(const ExecutionContext &exe_ctx);
+
//------------------------------------------------------------------
/// Clear the object's state.
///
- /// Sets the process and thread to NULL, and the frame index to an
+ /// Sets the process and thread to nullptr, and the frame index to an
/// invalid value.
//------------------------------------------------------------------
void
@@ -394,6 +399,7 @@ public:
ExecutionContext (const lldb::ProcessSP &process_sp);
ExecutionContext (const lldb::ThreadSP &thread_sp);
ExecutionContext (const lldb::StackFrameSP &frame_sp);
+
//------------------------------------------------------------------
// Create execution contexts from weak pointers
//------------------------------------------------------------------
@@ -413,16 +419,6 @@ public:
//------------------------------------------------------------------
ExecutionContext (ExecutionContextScope *exe_scope);
ExecutionContext (ExecutionContextScope &exe_scope);
-
-
- ExecutionContext &
- operator =(const ExecutionContext &rhs);
-
- bool
- operator ==(const ExecutionContext &rhs) const;
-
- bool
- operator !=(const ExecutionContext &rhs) const;
//------------------------------------------------------------------
/// Construct with process, thread, and frame index.
@@ -438,16 +434,26 @@ public:
/// @param[in] frame
/// The frame index for this execution context.
//------------------------------------------------------------------
- ExecutionContext (Process* process,
- Thread *thread = NULL,
- StackFrame * frame = NULL);
+ ExecutionContext(Process* process,
+ Thread *thread = nullptr,
+ StackFrame * frame = nullptr);
~ExecutionContext();
+
+ ExecutionContext &
+ operator =(const ExecutionContext &rhs);
+
+ bool
+ operator ==(const ExecutionContext &rhs) const;
+
+ bool
+ operator !=(const ExecutionContext &rhs) const;
+
//------------------------------------------------------------------
/// Clear the object's state.
///
- /// Sets the process and thread to NULL, and the frame index to an
+ /// Sets the process and thread to nullptr, and the frame index to an
/// invalid value.
//------------------------------------------------------------------
void
@@ -468,10 +474,10 @@ public:
//------------------------------------------------------------------
/// Returns a pointer to the target object.
///
- /// The returned pointer might be NULL. Calling HasTargetScope(),
+ /// The returned pointer might be nullptr. Calling HasTargetScope(),
/// HasProcessScope(), HasThreadScope(), or HasFrameScope()
/// can help to pre-validate this pointer so that this accessor can
- /// freely be used without having to check for NULL each time.
+ /// freely be used without having to check for nullptr each time.
///
/// @see ExecutionContext::HasTargetScope() const
/// @see ExecutionContext::HasProcessScope() const
@@ -484,10 +490,10 @@ public:
//------------------------------------------------------------------
/// Returns a pointer to the process object.
///
- /// The returned pointer might be NULL. Calling HasProcessScope(),
+ /// The returned pointer might be nullptr. Calling HasProcessScope(),
/// HasThreadScope(), or HasFrameScope() can help to pre-validate
/// this pointer so that this accessor can freely be used without
- /// having to check for NULL each time.
+ /// having to check for nullptr each time.
///
/// @see ExecutionContext::HasProcessScope() const
/// @see ExecutionContext::HasThreadScope() const
@@ -499,10 +505,10 @@ public:
//------------------------------------------------------------------
/// Returns a pointer to the thread object.
///
- /// The returned pointer might be NULL. Calling HasThreadScope() or
+ /// The returned pointer might be nullptr. Calling HasThreadScope() or
/// HasFrameScope() can help to pre-validate this pointer so that
/// this accessor can freely be used without having to check for
- /// NULL each time.
+ /// nullptr each time.
///
/// @see ExecutionContext::HasThreadScope() const
/// @see ExecutionContext::HasFrameScope() const
@@ -516,9 +522,9 @@ public:
//------------------------------------------------------------------
/// Returns a pointer to the frame object.
///
- /// The returned pointer might be NULL. Calling HasFrameScope(),
+ /// The returned pointer might be nullptr. Calling HasFrameScope(),
/// can help to pre-validate this pointer so that this accessor can
- /// freely be used without having to check for NULL each time.
+ /// freely be used without having to check for nullptr each time.
///
/// @see ExecutionContext::HasFrameScope() const
//------------------------------------------------------------------
@@ -776,6 +782,7 @@ protected:
lldb::ThreadSP m_thread_sp; ///< The thread that owns the frame
lldb::StackFrameSP m_frame_sp; ///< The stack frame in thread.
};
+
} // namespace lldb_private
-#endif // liblldb_ExecutionContext_h_
+#endif // liblldb_ExecutionContext_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h b/contrib/llvm/tools/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h
index 624267c..df1b937 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h
@@ -25,18 +25,24 @@ class InstrumentationRuntimeStopInfo : public StopInfo
{
public:
- virtual ~InstrumentationRuntimeStopInfo()
+ ~InstrumentationRuntimeStopInfo() override
{
}
- virtual lldb::StopReason
- GetStopReason () const
+ lldb::StopReason
+ GetStopReason() const override
{
return lldb::eStopReasonInstrumentation;
}
- virtual const char *
- GetDescription ();
+ const char *
+ GetDescription() override;
+
+ bool
+ DoShouldNotify(Event *event_ptr) override
+ {
+ return true;
+ }
static lldb::StopInfoSP
CreateStopReasonWithInstrumentationData (Thread &thread, std::string description, StructuredData::ObjectSP additional_data);
@@ -44,9 +50,8 @@ public:
private:
InstrumentationRuntimeStopInfo(Thread &thread, std::string description, StructuredData::ObjectSP additional_data);
-
};
} // namespace lldb_private
-#endif // liblldb_InstrumentationRuntimeStopInfo_h_
+#endif // liblldb_InstrumentationRuntimeStopInfo_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/JITLoader.h b/contrib/llvm/tools/lldb/include/lldb/Target/JITLoader.h
index c15ae5a..8a2d682 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/JITLoader.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/JITLoader.h
@@ -50,8 +50,7 @@ public:
//------------------------------------------------------------------
JITLoader (Process *process);
- virtual
- ~JITLoader ();
+ ~JITLoader() override;
//------------------------------------------------------------------
/// Called after attaching a process.
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Language.h b/contrib/llvm/tools/lldb/include/lldb/Target/Language.h
new file mode 100644
index 0000000..492425e
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Language.h
@@ -0,0 +1,206 @@
+//===-- Language.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Language_h_
+#define liblldb_Language_h_
+
+// C Includes
+// C++ Includes
+#include <functional>
+#include <memory>
+#include <set>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/DataFormatters/DumpValueObjectOptions.h"
+#include "lldb/DataFormatters/FormatClasses.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+
+namespace lldb_private {
+
+class Language :
+public PluginInterface
+{
+public:
+ class TypeScavenger
+ {
+ public:
+ class Result
+ {
+ public:
+ virtual bool
+ IsValid () = 0;
+
+ virtual bool
+ DumpToStream (Stream& stream,
+ bool print_help_if_available) = 0;
+
+ virtual ~Result() = default;
+ };
+
+ typedef std::set<std::unique_ptr<Result>> ResultSet;
+
+ virtual ~TypeScavenger () = default;
+
+ size_t
+ Find (ExecutionContextScope *exe_scope,
+ const char *key,
+ ResultSet &results,
+ bool append = true);
+
+ protected:
+ TypeScavenger () = default;
+
+ virtual bool
+ Find_Impl (ExecutionContextScope *exe_scope,
+ const char *key,
+ ResultSet &results) = 0;
+ };
+
+ enum class FunctionNameRepresentation
+ {
+ eName,
+ eNameWithArgs,
+ eNameWithNoArgs
+ };
+
+ ~Language() override;
+
+ static Language*
+ FindPlugin (lldb::LanguageType language);
+
+ // return false from callback to stop iterating
+ static void
+ ForEach (std::function<bool(Language*)> callback);
+
+ virtual lldb::LanguageType
+ GetLanguageType () const = 0;
+
+ virtual bool
+ IsTopLevelFunction (Function& function);
+
+ virtual lldb::TypeCategoryImplSP
+ GetFormatters ();
+
+ virtual HardcodedFormatters::HardcodedFormatFinder
+ GetHardcodedFormats ();
+
+ virtual HardcodedFormatters::HardcodedSummaryFinder
+ GetHardcodedSummaries ();
+
+ virtual HardcodedFormatters::HardcodedSyntheticFinder
+ GetHardcodedSynthetics ();
+
+ virtual HardcodedFormatters::HardcodedValidatorFinder
+ GetHardcodedValidators ();
+
+ virtual std::vector<ConstString>
+ GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic);
+
+ virtual lldb_private::formatters::StringPrinter::EscapingHelper
+ GetStringPrinterEscapingHelper (lldb_private::formatters::StringPrinter::GetPrintableElementType);
+
+ virtual std::unique_ptr<TypeScavenger>
+ GetTypeScavenger ();
+
+ // if an individual data formatter can apply to several types and cross a language boundary
+ // it makes sense for individual languages to want to customize the printing of values of that
+ // type by appending proper prefix/suffix information in language-specific ways
+ virtual bool
+ GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint,
+ std::string& prefix, std::string& suffix);
+
+ // if a language has a custom format for printing variable declarations that it wants LLDB to honor
+ // it should return an appropriate closure here
+ virtual DumpValueObjectOptions::DeclPrintingHelper
+ GetDeclPrintingHelper ();
+
+ virtual LazyBool
+ IsLogicalTrue (ValueObject& valobj,
+ Error& error);
+
+ // for a ValueObject of some "reference type", if the value points to the
+ // nil/null object, this method returns true
+ virtual bool
+ IsNilReference (ValueObject& valobj);
+
+ // for a ValueObject of some "reference type", if the language provides a technique
+ // to decide whether the reference has ever been assigned to some object, this method
+ // will return true if such detection is possible, and if the reference has never been assigned
+ virtual bool
+ IsUninitializedReference (ValueObject& valobj);
+
+ virtual bool
+ GetFunctionDisplayName (const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ FunctionNameRepresentation representation,
+ Stream& s);
+
+ virtual void
+ GetExceptionResolverDescription(bool catch_on, bool throw_on, Stream &s);
+
+ static void
+ GetDefaultExceptionResolverDescription(bool catch_on, bool throw_on, Stream &s);
+
+ // These are accessors for general information about the Languages lldb knows about:
+
+ static lldb::LanguageType
+ GetLanguageTypeFromString (const char *string);
+
+ static const char *
+ GetNameForLanguageType (lldb::LanguageType language);
+
+ static void
+ PrintAllLanguages (Stream &s, const char *prefix, const char *suffix);
+
+ // return false from callback to stop iterating
+ static void
+ ForAllLanguages (std::function<bool(lldb::LanguageType)> callback);
+
+ static bool
+ LanguageIsCPlusPlus (lldb::LanguageType language);
+
+ static bool
+ LanguageIsObjC (lldb::LanguageType language);
+
+ static bool
+ LanguageIsC (lldb::LanguageType language);
+
+ static bool
+ LanguageIsPascal (lldb::LanguageType language);
+
+ // return the primary language, so if LanguageIsC(l), return eLanguageTypeC, etc.
+ static lldb::LanguageType
+ GetPrimaryLanguage (lldb::LanguageType language);
+
+ static void
+ GetLanguagesSupportingTypeSystems (std::set<lldb::LanguageType> &languages,
+ std::set<lldb::LanguageType> &languages_for_expressions);
+
+ static void
+ GetLanguagesSupportingREPLs (std::set<lldb::LanguageType> &languages);
+
+protected:
+ //------------------------------------------------------------------
+ // Classes that inherit from Language can see and modify these
+ //------------------------------------------------------------------
+
+ Language();
+private:
+
+ DISALLOW_COPY_AND_ASSIGN (Language);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Language_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/LanguageRuntime.h b/contrib/llvm/tools/lldb/include/lldb/Target/LanguageRuntime.h
index d8e5ada..686ec5e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/LanguageRuntime.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/LanguageRuntime.h
@@ -29,8 +29,8 @@ class LanguageRuntime :
public PluginInterface
{
public:
- virtual
- ~LanguageRuntime();
+
+ ~LanguageRuntime() override;
static LanguageRuntime*
FindPlugin (Process *process, lldb::LanguageType language);
@@ -52,12 +52,31 @@ public:
GetDynamicTypeAndAddress (ValueObject &in_value,
lldb::DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name,
- Address &address) = 0;
+ Address &address,
+ Value::ValueType &value_type) = 0;
+
+ // This call should return a CompilerType given a generic type name
+ // and an ExecutionContextScope in which one can actually fetch
+ // any specialization information required.
+ virtual CompilerType
+ GetConcreteType (ExecutionContextScope *exe_scope,
+ ConstString abstract_type_name)
+ {
+ return CompilerType();
+ }
// This should be a fast test to determine whether it is likely that this value would
// have a dynamic type.
virtual bool
CouldHaveDynamicValue (ValueObject &in_value) = 0;
+
+ // The contract for GetDynamicTypeAndAddress() is to return a "bare-bones" dynamic type
+ // For instance, given a Base* pointer, GetDynamicTypeAndAddress() will return the type of
+ // Derived, not Derived*. The job of this API is to correct this misalignment between the
+ // static type and the discovered dynamic type
+ virtual TypeAndOrName
+ FixUpDynamicType (const TypeAndOrName& type_and_or_name,
+ ValueObject& static_value) = 0;
virtual void
SetExceptionBreakpoints ()
@@ -92,24 +111,17 @@ public:
CreateExceptionPrecondition (lldb::LanguageType language,
bool catch_bp,
bool throw_bp);
-
- static lldb::LanguageType
- GetLanguageTypeFromString (const char *string);
-
- static const char *
- GetNameForLanguageType (lldb::LanguageType language);
-
- static void
- PrintAllLanguages (Stream &s, const char *prefix, const char *suffix);
-
- static bool
- LanguageIsCPlusPlus (lldb::LanguageType language);
-
Process *
GetProcess()
{
return m_process;
}
+
+ Target&
+ GetTargetRef()
+ {
+ return m_process->GetTarget();
+ }
virtual lldb::BreakpointResolverSP
CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp) = 0;
@@ -118,7 +130,7 @@ public:
CreateExceptionSearchFilter ();
virtual bool
- GetTypeBitSize (const ClangASTType& clang_type,
+ GetTypeBitSize (const CompilerType& compiler_type,
uint64_t &size)
{
return false;
@@ -133,7 +145,6 @@ public:
virtual void
ModulesDidLoad (const ModuleList &module_list)
{
- return;
}
protected:
@@ -144,9 +155,10 @@ protected:
LanguageRuntime(Process *process);
Process *m_process;
private:
+
DISALLOW_COPY_AND_ASSIGN (LanguageRuntime);
};
} // namespace lldb_private
-#endif // liblldb_LanguageRuntime_h_
+#endif // liblldb_LanguageRuntime_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ObjCLanguageRuntime.h b/contrib/llvm/tools/lldb/include/lldb/Target/ObjCLanguageRuntime.h
index 88874c7..75f096f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ObjCLanguageRuntime.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ObjCLanguageRuntime.h
@@ -1,4 +1,4 @@
-//===-- ObjCLanguageRuntime.h ---------------------------------------------------*- C++ -*-===//
+//===-- ObjCLanguageRuntime.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,14 +14,17 @@
// C++ Includes
#include <functional>
#include <map>
+#include <memory>
#include <unordered_set>
// Other libraries and framework includes
+#include "llvm/Support/Casting.h"
+
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/ThreadSafeDenseMap.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/DeclVendor.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/LanguageRuntime.h"
@@ -30,115 +33,19 @@ class CommandObjectObjC_ClassTable_Dump;
namespace lldb_private {
-class ClangUtilityFunction;
+class UtilityFunction;
class ObjCLanguageRuntime :
public LanguageRuntime
{
public:
- class MethodName
+ enum class ObjCRuntimeVersions
{
- public:
- enum Type
- {
- eTypeUnspecified,
- eTypeClassMethod,
- eTypeInstanceMethod
- };
-
- MethodName () :
- m_full(),
- m_class(),
- m_category(),
- m_selector(),
- m_type (eTypeUnspecified),
- m_category_is_valid (false)
- {
- }
-
- MethodName (const char *name, bool strict) :
- m_full(),
- m_class(),
- m_category(),
- m_selector(),
- m_type (eTypeUnspecified),
- m_category_is_valid (false)
- {
- SetName (name, strict);
- }
-
- void
- Clear();
-
- bool
- IsValid (bool strict) const
- {
- // If "strict" is true, the name must have everything specified including
- // the leading "+" or "-" on the method name
- if (strict && m_type == eTypeUnspecified)
- return false;
- // Other than that, m_full will only be filled in if the objective C
- // name is valid.
- return (bool)m_full;
- }
-
- bool
- HasCategory()
- {
- return (bool)GetCategory();
- }
-
- Type
- GetType () const
- {
- return m_type;
- }
-
- const ConstString &
- GetFullName () const
- {
- return m_full;
- }
-
- ConstString
- GetFullNameWithoutCategory (bool empty_if_no_category);
-
- bool
- SetName (const char *name, bool strict);
-
- const ConstString &
- GetClassName ();
-
- const ConstString &
- GetClassNameWithCategory ();
-
- const ConstString &
- GetCategory ();
-
- const ConstString &
- GetSelector ();
-
- // Get all possible names for a method. Examples:
- // If name is "+[NSString(my_additions) myStringWithCString:]"
- // names[0] => "+[NSString(my_additions) myStringWithCString:]"
- // names[1] => "+[NSString myStringWithCString:]"
- // If name is specified without the leading '+' or '-' like "[NSString(my_additions) myStringWithCString:]"
- // names[0] => "+[NSString(my_additions) myStringWithCString:]"
- // names[1] => "-[NSString(my_additions) myStringWithCString:]"
- // names[2] => "+[NSString myStringWithCString:]"
- // names[3] => "-[NSString myStringWithCString:]"
- size_t
- GetFullNames (std::vector<ConstString> &names, bool append);
- protected:
- ConstString m_full; // Full name: "+[NSString(my_additions) myStringWithCString:]"
- ConstString m_class; // Class name: "NSString"
- ConstString m_class_category; // Class with category: "NSString(my_additions)"
- ConstString m_category; // Category: "my_additions"
- ConstString m_selector; // Selector: "myStringWithCString:"
- Type m_type;
- bool m_category_is_valid;
-
+ eObjC_VersionUnknown = 0,
+ eAppleObjC_V1 = 1,
+ eAppleObjC_V2 = 2
};
+
typedef lldb::addr_t ObjCISA;
class ClassDescriptor;
@@ -150,7 +57,6 @@ public:
class ClassDescriptor
{
public:
-
ClassDescriptor() :
m_is_kvo (eLazyBoolCalculate),
m_is_cf (eLazyBoolCalculate),
@@ -159,10 +65,8 @@ public:
}
virtual
- ~ClassDescriptor ()
- {
- }
-
+ ~ClassDescriptor() = default;
+
virtual ConstString
GetClassName () = 0;
@@ -203,12 +107,12 @@ public:
virtual bool
IsValid () = 0;
-
+
virtual bool
- GetTaggedPointerInfo (uint64_t* info_bits = NULL,
- uint64_t* value_bits = NULL,
- uint64_t* payload = NULL) = 0;
-
+ GetTaggedPointerInfo(uint64_t* info_bits = nullptr,
+ uint64_t* value_bits = nullptr,
+ uint64_t* payload = nullptr) = 0;
+
virtual uint64_t
GetInstanceSize () = 0;
@@ -247,7 +151,7 @@ public:
struct iVarDescriptor {
ConstString m_name;
- ClangASTType m_type;
+ CompilerType m_type;
uint64_t m_size;
int32_t m_offset;
};
@@ -281,12 +185,12 @@ public:
class EncodingToType
{
public:
- virtual ClangASTType RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression);
- virtual ClangASTType RealizeType (const char* name, bool for_expression);
-
- virtual ClangASTType RealizeType (clang::ASTContext& ast_ctx, const char* name, bool for_expression) = 0;
-
virtual ~EncodingToType();
+
+ virtual CompilerType RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression);
+ virtual CompilerType RealizeType (const char* name, bool for_expression);
+
+ virtual CompilerType RealizeType (clang::ASTContext& ast_ctx, const char* name, bool for_expression) = 0;
protected:
std::unique_ptr<ClangASTContext> m_scratch_ast_ctx_ap;
@@ -297,10 +201,10 @@ public:
public:
ObjCExceptionPrecondition();
- virtual ~ObjCExceptionPrecondition() {}
+ ~ObjCExceptionPrecondition() override = default;
bool EvaluatePrecondition(StoppointCallbackContext &context) override;
- void DescribePrecondition(Stream &stream, lldb::DescriptionLevel level) override;
+ void GetDescription(Stream &stream, lldb::DescriptionLevel level) override;
Error ConfigurePrecondition(Args &args) override;
protected:
@@ -313,21 +217,24 @@ public:
class TaggedPointerVendor
{
public:
+ virtual
+ ~TaggedPointerVendor() = default;
+
virtual bool
IsPossibleTaggedPointer (lldb::addr_t ptr) = 0;
virtual ObjCLanguageRuntime::ClassDescriptorSP
GetClassDescriptor (lldb::addr_t ptr) = 0;
-
- virtual
- ~TaggedPointerVendor () { }
+
protected:
- TaggedPointerVendor () = default;
+ TaggedPointerVendor() = default;
private:
DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendor);
};
+ ~ObjCLanguageRuntime() override;
+
virtual TaggedPointerVendor*
GetTaggedPointerVendor ()
{
@@ -354,9 +261,6 @@ public:
ClassDescriptorSP
GetNonKVOClassDescriptor (ObjCISA isa);
- virtual
- ~ObjCLanguageRuntime();
-
lldb::LanguageType
GetLanguageType () const override
{
@@ -393,13 +297,13 @@ public:
lldb::TypeSP
LookupInCompleteClassCache (ConstString &name);
- virtual ClangUtilityFunction *
+ virtual UtilityFunction *
CreateObjectChecker (const char *) = 0;
virtual ObjCRuntimeVersions
- GetRuntimeVersion ()
+ GetRuntimeVersion () const
{
- return eObjC_VersionUnknown;
+ return ObjCRuntimeVersions::eObjC_VersionUnknown;
}
bool
@@ -433,14 +337,14 @@ public:
virtual DeclVendor *
GetDeclVendor()
{
- return NULL;
+ return nullptr;
}
// Finds the byte offset of the child_type ivar in parent_type. If it can't find the
// offset, returns LLDB_INVALID_IVAR_OFFSET.
virtual size_t
- GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name);
+ GetByteOffsetForIvar (CompilerType &parent_qual_type, const char *ivar_name);
// Given the name of an Objective-C runtime symbol (e.g., ivar offset symbol),
// try to determine from the runtime what the value of that symbol would be.
@@ -451,94 +355,6 @@ public:
return LLDB_INVALID_ADDRESS;
}
- //------------------------------------------------------------------
- /// Chop up an objective C function prototype.
- ///
- /// Chop up an objective C function fullname and optionally fill in
- /// any non-NULL ConstString objects. If a ConstString * is NULL,
- /// then this name doesn't get filled in
- ///
- /// @param[in] name
- /// A fully specified objective C function name. The string might
- /// contain a category and it includes the leading "+" or "-" and
- /// the square brackets, no types for the arguments, just the plain
- /// selector. A few examples:
- /// "-[NSStringDrawingContext init]"
- /// "-[NSStringDrawingContext addString:inRect:]"
- /// "-[NSString(NSStringDrawing) sizeWithAttributes:]"
- /// "+[NSString(NSStringDrawing) usesFontLeading]"
- ///
- /// @param[out] class_name
- /// If non-NULL, this string will be filled in with the class
- /// name including the category. The examples above would return:
- /// "NSStringDrawingContext"
- /// "NSStringDrawingContext"
- /// "NSString(NSStringDrawing)"
- /// "NSString(NSStringDrawing)"
- ///
- /// @param[out] selector_name
- /// If non-NULL, this string will be filled in with the selector
- /// name. The examples above would return:
- /// "init"
- /// "addString:inRect:"
- /// "sizeWithAttributes:"
- /// "usesFontLeading"
- ///
- /// @param[out] name_sans_category
- /// If non-NULL, this string will be filled in with the class
- /// name _without_ the category. If there is no category, and empty
- /// string will be returned (as the result would be normally returned
- /// in the "class_name" argument). The examples above would return:
- /// <empty>
- /// <empty>
- /// "-[NSString sizeWithAttributes:]"
- /// "+[NSString usesFontLeading]"
- ///
- /// @param[out] class_name_sans_category
- /// If non-NULL, this string will be filled in with the prototype
- /// name _without_ the category. If there is no category, and empty
- /// string will be returned (as this is already the value that was
- /// passed in). The examples above would return:
- /// <empty>
- /// <empty>
- /// "NSString"
- /// "NSString"
- ///
- /// @return
- /// Returns the number of strings that were successfully filled
- /// in.
- //------------------------------------------------------------------
-// static uint32_t
-// ParseMethodName (const char *name,
-// ConstString *class_name, // Class name (with category if there is one)
-// ConstString *selector_name, // selector only
-// ConstString *name_sans_category, // full function name with no category (empty if no category)
-// ConstString *class_name_sans_category);// Class name without category (empty if no category)
-
- static bool
- IsPossibleObjCMethodName (const char *name)
- {
- if (!name)
- return false;
- bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '[';
- bool ends_right = (name[strlen(name) - 1] == ']');
- return (starts_right && ends_right);
- }
-
- static bool
- IsPossibleObjCSelector (const char *name)
- {
- if (!name)
- return false;
-
- if (strchr(name, ':') == NULL)
- return true;
- else if (name[strlen(name) - 1] == ':')
- return true;
- else
- return false;
- }
-
bool
HasNewLiteralsAndIndexing ()
{
@@ -560,7 +376,7 @@ public:
}
bool
- GetTypeBitSize (const ClangASTType& clang_type,
+ GetTypeBitSize (const CompilerType& compiler_type,
uint64_t &size) override;
protected:
@@ -568,13 +384,12 @@ protected:
// Classes that inherit from ObjCLanguageRuntime can see and modify these
//------------------------------------------------------------------
ObjCLanguageRuntime(Process *process);
-
+
virtual bool CalculateHasNewLiteralsAndIndexing()
{
return false;
}
-
bool
ISAIsCached (ObjCISA isa) const
{
@@ -621,11 +436,13 @@ private:
sel_addr = LLDB_INVALID_ADDRESS;
class_addr = LLDB_INVALID_ADDRESS;
}
+
ClassAndSel (lldb::addr_t in_sel_addr, lldb::addr_t in_class_addr) :
class_addr (in_class_addr),
sel_addr(in_sel_addr)
{
}
+
bool operator== (const ClassAndSel &rhs)
{
if (class_addr == rhs.class_addr
@@ -702,4 +519,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_ObjCLanguageRuntime_h_
+#endif // liblldb_ObjCLanguageRuntime_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/OperatingSystem.h b/contrib/llvm/tools/lldb/include/lldb/Target/OperatingSystem.h
index f1c0eb0..74de564 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/OperatingSystem.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/OperatingSystem.h
@@ -32,7 +32,6 @@ namespace lldb_private {
class OperatingSystem :
public PluginInterface
-
{
public:
//------------------------------------------------------------------
@@ -58,8 +57,7 @@ public:
//------------------------------------------------------------------
OperatingSystem (Process *process);
- virtual
- ~OperatingSystem();
+ ~OperatingSystem() override;
//------------------------------------------------------------------
// Plug-in Methods
@@ -98,4 +96,4 @@ private:
} // namespace lldb_private
-#endif // #ifndef liblldb_OperatingSystem_h_
+#endif // liblldb_OperatingSystem_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Platform.h b/contrib/llvm/tools/lldb/include/lldb/Target/Platform.h
index feaac57..53c17a6 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/Platform.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Platform.h
@@ -37,7 +37,6 @@
namespace lldb_private {
class ModuleCache;
-
enum MmapFlags {
eMmapFlagsPrivate = 1,
eMmapFlagsAnon = 2
@@ -46,11 +45,11 @@ class ModuleCache;
class PlatformProperties : public Properties
{
public:
+ PlatformProperties();
+
static ConstString
GetSettingName ();
- PlatformProperties();
-
bool
GetUseModuleCache () const;
bool
@@ -81,6 +80,19 @@ class ModuleCache;
public PluginInterface
{
public:
+ //------------------------------------------------------------------
+ /// Default Constructor
+ //------------------------------------------------------------------
+ Platform (bool is_host_platform);
+
+ //------------------------------------------------------------------
+ /// Destructor.
+ ///
+ /// The destructor is virtual since this class is designed to be
+ /// inherited from by the plug-in instance.
+ //------------------------------------------------------------------
+ ~Platform() override;
+
static void
Initialize ();
@@ -131,20 +143,6 @@ class ModuleCache;
GetConnectedRemotePlatformAtIndex (uint32_t idx);
//------------------------------------------------------------------
- /// Default Constructor
- //------------------------------------------------------------------
- Platform (bool is_host_platform);
-
- //------------------------------------------------------------------
- /// Destructor.
- ///
- /// The destructor is virtual since this class is designed to be
- /// inherited from by the plug-in instance.
- //------------------------------------------------------------------
- virtual
- ~Platform();
-
- //------------------------------------------------------------------
/// Find a platform plugin for a given process.
///
/// Scans the installed Platform plug-ins and tries to find
@@ -156,7 +154,7 @@ class ModuleCache;
///
/// @param[in] plugin_name
/// An optional name of a specific platform plug-in that
- /// should be used. If NULL, pick the best plug-in.
+ /// should be used. If nullptr, pick the best plug-in.
//------------------------------------------------------------------
// static lldb::PlatformSP
// FindPlugin (Process *process, const ConstString &plugin_name);
@@ -185,7 +183,6 @@ class ModuleCache;
lldb::ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr);
-
//------------------------------------------------------------------
/// Find a symbol file given a symbol file module specification.
///
@@ -247,10 +244,21 @@ class ModuleCache;
ResolveRemotePath (const FileSpec &platform_path,
FileSpec &resolved_platform_path);
- bool
+ //------------------------------------------------------------------
+ /// Get the OS version from a connected platform.
+ ///
+ /// Some platforms might not be connected to a remote platform, but
+ /// can figure out the OS version for a process. This is common for
+ /// simulator platforms that will run native programs on the current
+ /// host, but the simulator might be simulating a different OS. The
+ /// \a process parameter might be specified to help to determine
+ /// the OS version.
+ //------------------------------------------------------------------
+ virtual bool
GetOSVersion (uint32_t &major,
uint32_t &minor,
- uint32_t &update);
+ uint32_t &update,
+ Process *process = nullptr);
bool
SetOSVersion (uint32_t major,
@@ -269,6 +277,9 @@ class ModuleCache;
virtual const char *
GetHostname ();
+
+ virtual ConstString
+ GetFullNameForDylib (ConstString basename);
virtual const char *
GetDescription () = 0;
@@ -473,9 +484,16 @@ class ModuleCache;
virtual lldb::ProcessSP
DebugProcess (ProcessLaunchInfo &launch_info,
Debugger &debugger,
- Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ Target *target, // Can be nullptr, if nullptr create a new target, else use existing one
Error &error);
+ virtual lldb::ProcessSP
+ ConnectProcess (const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error);
+
//------------------------------------------------------------------
/// Attach to an existing process using a process ID.
///
@@ -497,7 +515,7 @@ class ModuleCache;
virtual lldb::ProcessSP
Attach (ProcessAttachInfo &attach_info,
Debugger &debugger,
- Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ Target *target, // Can be nullptr, if nullptr create a new target, else use existing one
Error &error) = 0;
//------------------------------------------------------------------
@@ -593,6 +611,7 @@ class ModuleCache;
{
return m_max_uid_name_len;
}
+
// Used for column widths
size_t
GetMaxGroupIDNameLength() const
@@ -829,15 +848,15 @@ class ModuleCache;
virtual lldb_private::OptionGroupOptions *
GetConnectionOptions (CommandInterpreter& interpreter)
{
- return NULL;
+ return nullptr;
}
virtual lldb_private::Error
- RunShellCommand(const char *command, // Shouldn't be NULL
+ RunShellCommand(const char *command, // Shouldn't be nullptr
const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory
- int *status_ptr, // Pass NULL if you don't want the process exit status
- int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
- std::string *command_output, // Pass NULL if you don't want the command output
+ int *status_ptr, // Pass nullptr if you don't want the process exit status
+ int *signo_ptr, // Pass nullptr if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass nullptr if you don't want the command output
uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
virtual void
@@ -945,9 +964,105 @@ class ModuleCache;
virtual const std::vector<ConstString> &
GetTrapHandlerSymbolNames ();
+ //------------------------------------------------------------------
+ /// Find a support executable that may not live within in the
+ /// standard locations related to LLDB.
+ ///
+ /// Executable might exist within the Platform SDK directories, or
+ /// in standard tool directories within the current IDE that is
+ /// running LLDB.
+ ///
+ /// @param[in] basename
+ /// The basename of the executable to locate in the current
+ /// platform.
+ ///
+ /// @return
+ /// A FileSpec pointing to the executable on disk, or an invalid
+ /// FileSpec if the executable cannot be found.
+ //------------------------------------------------------------------
+ virtual FileSpec
+ LocateExecutable (const char *basename)
+ {
+ return FileSpec();
+ }
+
+ //------------------------------------------------------------------
+ /// Allow the platform to set preferred memory cache line size. If non-zero (and the user
+ /// has not set cache line size explicitly), this value will be used as the cache line
+ /// size for memory reads.
+ //------------------------------------------------------------------
+ virtual uint32_t
+ GetDefaultMemoryCacheLineSize() { return 0; }
+
+ //------------------------------------------------------------------
+ /// Load a shared library into this process.
+ ///
+ /// Try and load a shared library into the current process. This
+ /// call might fail in the dynamic loader plug-in says it isn't safe
+ /// to try and load shared libraries at the moment.
+ ///
+ /// @param[in] process
+ /// The process to load the image.
+ ///
+ /// @param[in] local_file
+ /// The file spec that points to the shared library that you want
+ /// to load if the library is located on the host. The library will
+ /// be copied over to the location specified by remote_file or into
+ /// the current working directory with the same filename if the
+ /// remote_file isn't specified.
+ ///
+ /// @param[in] remote_file
+ /// If local_file is specified then the location where the library
+ /// should be copied over from the host. If local_file isn't
+ /// specified, then the path for the shared library on the target
+ /// what you want to load.
+ ///
+ /// @param[out] error
+ /// An error object that gets filled in with any errors that
+ /// might occur when trying to load the shared library.
+ ///
+ /// @return
+ /// A token that represents the shared library that can be
+ /// later used to unload the shared library. A value of
+ /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
+ /// library can't be opened.
+ //------------------------------------------------------------------
+ uint32_t
+ LoadImage (lldb_private::Process* process,
+ const lldb_private::FileSpec& local_file,
+ const lldb_private::FileSpec& remote_file,
+ lldb_private::Error& error);
+
+ virtual uint32_t
+ DoLoadImage (lldb_private::Process* process,
+ const lldb_private::FileSpec& remote_file,
+ lldb_private::Error& error);
+
+ virtual Error
+ UnloadImage (lldb_private::Process* process, uint32_t image_token);
+
+ //------------------------------------------------------------------
+ /// Connect to all processes waiting for a debugger to attach
+ ///
+ /// If the platform have a list of processes waiting for a debugger
+ /// to connect to them then connect to all of these pending processes.
+ ///
+ /// @param[in] debugger
+ /// The debugger used for the connect.
+ ///
+ /// @param[out] error
+ /// If an error occurred during the connect then this object will
+ /// contain the error message.
+ ///
+ /// @return
+ /// The number of processes we are succesfully connected to.
+ //------------------------------------------------------------------
+ virtual size_t
+ ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& error);
+
protected:
bool m_is_host;
- // Set to true when we are able to actually set the OS version while
+ // Set to true when we are able to actually set the OS version while
// being connected. For remote platforms, we might set the version ahead
// of time before we actually connect and this version might change when
// we actually connect to a remote platform. For the host platform this
@@ -1000,16 +1115,12 @@ class ModuleCache;
GetCachedUserName (uint32_t uid)
{
Mutex::Locker locker (m_mutex);
- IDToNameMap::iterator pos = m_uid_map.find (uid);
- if (pos != m_uid_map.end())
- {
- // return the empty string if our string is NULL
- // so we can tell when things were in the negative
- // cached (didn't find a valid user name, don't keep
- // trying)
- return pos->second.AsCString("");
- }
- return NULL;
+ // return the empty string if our string is NULL
+ // so we can tell when things were in the negative
+ // cached (didn't find a valid user name, don't keep
+ // trying)
+ const auto pos = m_uid_map.find(uid);
+ return ((pos != m_uid_map.end()) ? pos->second.AsCString("") : nullptr);
}
const char *
@@ -1030,7 +1141,6 @@ class ModuleCache;
Mutex::Locker locker (m_mutex);
m_uid_map[uid] = ConstString();
}
-
void
ClearCachedUserNames ()
@@ -1043,16 +1153,12 @@ class ModuleCache;
GetCachedGroupName (uint32_t gid)
{
Mutex::Locker locker (m_mutex);
- IDToNameMap::iterator pos = m_gid_map.find (gid);
- if (pos != m_gid_map.end())
- {
- // return the empty string if our string is NULL
- // so we can tell when things were in the negative
- // cached (didn't find a valid group name, don't keep
- // trying)
- return pos->second.AsCString("");
- }
- return NULL;
+ // return the empty string if our string is NULL
+ // so we can tell when things were in the negative
+ // cached (didn't find a valid group name, don't keep
+ // trying)
+ const auto pos = m_gid_map.find(gid);
+ return ((pos != m_gid_map.end()) ? pos->second.AsCString("") : nullptr);
}
const char *
@@ -1092,6 +1198,10 @@ class ModuleCache;
const uint64_t src_offset,
const uint64_t src_size,
const FileSpec& dst_file_spec);
+
+ virtual Error
+ DownloadSymbolFile (const lldb::ModuleSP& module_sp,
+ const FileSpec& dst_file_spec);
virtual const char *
GetCacheHostname ();
@@ -1123,7 +1233,6 @@ class ModuleCache;
DISALLOW_COPY_AND_ASSIGN (Platform);
};
-
class PlatformList
{
public:
@@ -1133,11 +1242,9 @@ class ModuleCache;
m_selected_platform_sp()
{
}
-
- ~PlatformList()
- {
- }
-
+
+ ~PlatformList() = default;
+
void
Append (const lldb::PlatformSP &platform_sp, bool set_selected)
{
@@ -1220,22 +1327,21 @@ class ModuleCache;
public:
OptionGroupPlatformRSync ();
- virtual
- ~OptionGroupPlatformRSync ();
+ ~OptionGroupPlatformRSync() override;
- virtual lldb_private::Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ lldb_private::Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
const lldb_private::OptionDefinition*
- GetDefinitions ();
+ GetDefinitions() override;
- virtual uint32_t
- GetNumDefinitions ();
+ uint32_t
+ GetNumDefinitions() override;
// Options table: Required for subclasses of Options.
@@ -1256,22 +1362,21 @@ class ModuleCache;
public:
OptionGroupPlatformSSH ();
- virtual
- ~OptionGroupPlatformSSH ();
+ ~OptionGroupPlatformSSH() override;
- virtual lldb_private::Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ lldb_private::Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
- virtual uint32_t
- GetNumDefinitions ();
+ uint32_t
+ GetNumDefinitions() override;
const lldb_private::OptionDefinition*
- GetDefinitions ();
+ GetDefinitions() override;
// Options table: Required for subclasses of Options.
@@ -1283,7 +1388,6 @@ class ModuleCache;
std::string m_ssh_opts;
private:
-
DISALLOW_COPY_AND_ASSIGN(OptionGroupPlatformSSH);
};
@@ -1292,22 +1396,21 @@ class ModuleCache;
public:
OptionGroupPlatformCaching ();
- virtual
- ~OptionGroupPlatformCaching ();
+ ~OptionGroupPlatformCaching() override;
- virtual lldb_private::Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ lldb_private::Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
- virtual uint32_t
- GetNumDefinitions ();
+ uint32_t
+ GetNumDefinitions() override;
const lldb_private::OptionDefinition*
- GetDefinitions ();
+ GetDefinitions() override;
// Options table: Required for subclasses of Options.
@@ -1316,10 +1419,11 @@ class ModuleCache;
// Instance variables to hold the values for command options.
std::string m_cache_dir;
+
private:
DISALLOW_COPY_AND_ASSIGN(OptionGroupPlatformCaching);
};
} // namespace lldb_private
-#endif // liblldb_Platform_h_
+#endif // liblldb_Platform_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Process.h b/contrib/llvm/tools/lldb/include/lldb/Target/Process.h
index f75b3cd..6bb7a3d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/Process.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Process.h
@@ -17,8 +17,10 @@
// C++ Includes
#include <list>
-#include <iosfwd>
+#include <memory>
+#include <string>
#include <vector>
+#include <unordered_set>
// Other libraries and framework includes
// Project includes
@@ -28,6 +30,7 @@
#include "lldb/Core/Communication.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Event.h"
+#include "lldb/Core/LoadedModuleInfoList.h"
#include "lldb/Core/ThreadSafeValue.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/StructuredData.h"
@@ -55,11 +58,10 @@ struct Range;
class ProcessProperties : public Properties
{
public:
- // Pass NULL for "process" if the ProcessProperties are to be the global copy
+ // Pass nullptr for "process" if the ProcessProperties are to be the global copy
ProcessProperties (lldb_private::Process *process);
- virtual
- ~ProcessProperties();
+ ~ProcessProperties() override;
bool
GetDisableMemoryCache() const;
@@ -103,12 +105,14 @@ public:
void
SetDetachKeepsStopped (bool keep_stopped);
-protected:
+ bool
+ GetWarningsOptimization () const;
+protected:
static void
OptionValueChangedCallback (void *baton, OptionValue *option_value);
- Process * m_process; // Can be NULL for global ProcessProperties
+ Process * m_process; // Can be nullptr for global ProcessProperties
};
typedef std::shared_ptr<ProcessProperties> ProcessPropertiesSP;
@@ -236,7 +240,8 @@ public:
m_wait_for_launch (false),
m_ignore_existing (true),
m_continue_once_attached (false),
- m_detach_on_error (true)
+ m_detach_on_error (true),
+ m_async (false)
{
}
@@ -249,7 +254,8 @@ public:
m_wait_for_launch (false),
m_ignore_existing (true),
m_continue_once_attached (false),
- m_detach_on_error(true)
+ m_detach_on_error (true),
+ m_async (false)
{
ProcessInfo::operator= (launch_info);
SetProcessPluginName (launch_info.GetProcessPluginName());
@@ -272,6 +278,18 @@ public:
}
bool
+ GetAsync () const
+ {
+ return m_async;
+ }
+
+ void
+ SetAsync (bool b)
+ {
+ m_async = b;
+ }
+
+ bool
GetIgnoreExisting () const
{
return m_ignore_existing;
@@ -310,9 +328,7 @@ public:
const char *
GetProcessPluginName () const
{
- if (m_plugin_name.empty())
- return NULL;
- return m_plugin_name.c_str();
+ return (m_plugin_name.empty() ? nullptr : m_plugin_name.c_str());
}
void
@@ -384,7 +400,6 @@ public:
m_listener_sp = listener_sp;
}
-
Listener &
GetListenerForProcess (Debugger &debugger);
@@ -397,35 +412,33 @@ protected:
bool m_ignore_existing;
bool m_continue_once_attached; // Supports the use-case scenario of immediately continuing the process once attached.
bool m_detach_on_error; // If we are debugging remotely, instruct the stub to detach rather than killing the target on error.
+ bool m_async; // Use an async attach where we start the attach and return immediately (used by GUI programs with --waitfor so they can call SBProcess::Stop() to cancel attach)
};
class ProcessLaunchCommandOptions : public Options
{
public:
-
ProcessLaunchCommandOptions (CommandInterpreter &interpreter) :
Options(interpreter)
{
// Keep default values of all options in one place: OptionParsingStarting ()
OptionParsingStarting ();
}
-
- ~ProcessLaunchCommandOptions ()
- {
- }
-
+
+ ~ProcessLaunchCommandOptions() override = default;
+
Error
- SetOptionValue (uint32_t option_idx, const char *option_arg);
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override;
void
- OptionParsingStarting ()
+ OptionParsingStarting() override
{
launch_info.Clear();
disable_aslr = eLazyBoolCalculate;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions() override
{
return g_option_table;
}
@@ -521,11 +534,8 @@ protected:
class ProcessInstanceInfoList
{
public:
- ProcessInstanceInfoList () :
- m_infos()
- {
- }
-
+ ProcessInstanceInfoList() = default;
+
void
Clear()
{
@@ -547,25 +557,19 @@ public:
const char *
GetProcessNameAtIndex (size_t idx)
{
- if (idx < m_infos.size())
- return m_infos[idx].GetName();
- return NULL;
+ return ((idx < m_infos.size()) ? m_infos[idx].GetName() : nullptr);
}
size_t
GetProcessNameLengthAtIndex (size_t idx)
{
- if (idx < m_infos.size())
- return m_infos[idx].GetNameLength();
- return 0;
+ return ((idx < m_infos.size()) ? m_infos[idx].GetNameLength() : 0);
}
lldb::pid_t
GetProcessIDAtIndex (size_t idx)
{
- if (idx < m_infos.size())
- return m_infos[idx].GetProcessID();
- return 0;
+ return ((idx < m_infos.size()) ? m_infos[idx].GetProcessID() : 0);
}
bool
@@ -592,7 +596,6 @@ protected:
collection m_infos;
};
-
// This class tracks the Modification state of the process. Things that can currently modify
// the program are running the program (which will up the StopID) and writing memory (which
// will up the MemoryID.)
@@ -600,7 +603,7 @@ protected:
class ProcessModID
{
-friend bool operator== (const ProcessModID &lhs, const ProcessModID &rhs);
+ friend bool operator== (const ProcessModID &lhs, const ProcessModID &rhs);
public:
ProcessModID () :
m_stop_id (0),
@@ -626,7 +629,7 @@ public:
return *this;
}
- ~ProcessModID () {}
+ ~ProcessModID() = default;
void BumpStopID () {
m_stop_id++;
@@ -709,6 +712,7 @@ private:
uint32_t m_running_user_expression;
lldb::EventSP m_last_natural_stop_event;
};
+
inline bool operator== (const ProcessModID &lhs, const ProcessModID &rhs)
{
if (lhs.StopIDEqual (rhs)
@@ -720,11 +724,7 @@ inline bool operator== (const ProcessModID &lhs, const ProcessModID &rhs)
inline bool operator!= (const ProcessModID &lhs, const ProcessModID &rhs)
{
- if (!lhs.StopIDEqual (rhs)
- || !lhs.MemoryIDEqual (rhs))
- return true;
- else
- return false;
+ return (!lhs.StopIDEqual (rhs) || !lhs.MemoryIDEqual (rhs));
}
//----------------------------------------------------------------------
@@ -739,7 +739,7 @@ class Process :
public ExecutionContextScope,
public PluginInterface
{
- friend class ClangFunction; // For WaitForStateChangeEventsPrivate
+ friend class FunctionCaller; // For WaitForStateChangeEventsPrivate
friend class Debugger; // For PopProcessIOHandler and ProcessIOHandlerIsActive
friend class ProcessEventData;
friend class StopInfo;
@@ -747,7 +747,6 @@ class Process :
friend class ThreadList;
public:
-
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
//------------------------------------------------------------------
@@ -766,6 +765,14 @@ public:
eBroadcastInternalStateControlPause = (1<<1),
eBroadcastInternalStateControlResume = (1<<2)
};
+
+ //------------------------------------------------------------------
+ /// Process warning types.
+ //------------------------------------------------------------------
+ enum Warnings
+ {
+ eWarningsOptimization = 1
+ };
typedef Range<lldb::addr_t, lldb::addr_t> LoadRange;
// We use a read/write lock to allow on or more clients to
@@ -781,12 +788,11 @@ public:
static ConstString &GetStaticBroadcasterClass ();
- virtual ConstString &GetBroadcasterClass() const
+ ConstString &GetBroadcasterClass() const override
{
return GetStaticBroadcasterClass();
}
-
//------------------------------------------------------------------
/// A notification structure that can be used by clients to listen
/// for changes in a process's lifetime.
@@ -811,13 +817,13 @@ public:
ProcessEventData ();
ProcessEventData (const lldb::ProcessSP &process, lldb::StateType state);
- virtual ~ProcessEventData();
+ ~ProcessEventData() override;
static const ConstString &
GetFlavorString ();
- virtual const ConstString &
- GetFlavor () const;
+ const ConstString &
+ GetFlavor() const override;
lldb::ProcessSP
GetProcessSP() const
@@ -845,10 +851,7 @@ public:
const char *
GetRestartedReasonAtIndex(size_t idx)
{
- if (idx > m_restarted_reasons.size())
- return NULL;
- else
- return m_restarted_reasons[idx].c_str();
+ return ((idx < m_restarted_reasons.size()) ? m_restarted_reasons[idx].c_str() : nullptr);
}
bool
@@ -857,11 +860,11 @@ public:
return m_interrupted;
}
- virtual void
- Dump (Stream *s) const;
+ void
+ Dump(Stream *s) const override;
- virtual void
- DoOnRemoval (Event *event_ptr);
+ void
+ DoOnRemoval(Event *event_ptr) override;
static const Process::ProcessEventData *
GetEventDataFromEvent (const Event *event_ptr);
@@ -897,22 +900,24 @@ public:
SetUpdateStateOnRemoval (Event *event_ptr);
private:
-
void
SetUpdateStateOnRemoval()
{
m_update_state++;
}
+
void
SetRestarted (bool new_value)
{
m_restarted = new_value;
}
+
void
SetInterrupted (bool new_value)
{
m_interrupted = new_value;
}
+
void
AddRestartedReason (const char *reason)
{
@@ -925,32 +930,22 @@ public:
bool m_restarted; // For "eStateStopped" events, this is true if the target was automatically restarted.
int m_update_state;
bool m_interrupted;
- DISALLOW_COPY_AND_ASSIGN (ProcessEventData);
+ DISALLOW_COPY_AND_ASSIGN (ProcessEventData);
};
-
-#endif
-
- static void
- SettingsInitialize ();
-
- static void
- SettingsTerminate ();
-
- static const ProcessPropertiesSP &
- GetGlobalProperties();
+#endif // SWIG
//------------------------------------------------------------------
/// Construct with a shared pointer to a target, and the Process listener.
/// Uses the Host UnixSignalsSP by default.
//------------------------------------------------------------------
- Process(Target &target, Listener &listener);
+ Process(lldb::TargetSP target_sp, Listener &listener);
//------------------------------------------------------------------
/// Construct with a shared pointer to a target, the Process listener,
/// and the appropriate UnixSignalsSP for the process.
//------------------------------------------------------------------
- Process(Target &target, Listener &listener, const lldb::UnixSignalsSP &unix_signals_sp);
+ Process(lldb::TargetSP target_sp, Listener &listener, const lldb::UnixSignalsSP &unix_signals_sp);
//------------------------------------------------------------------
/// Destructor.
@@ -958,8 +953,16 @@ public:
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
- virtual
- ~Process();
+ ~Process() override;
+
+ static void
+ SettingsInitialize ();
+
+ static void
+ SettingsTerminate ();
+
+ static const ProcessPropertiesSP &
+ GetGlobalProperties();
//------------------------------------------------------------------
/// Find a Process plug-in that can debug \a module using the
@@ -973,20 +976,18 @@ public:
/// The module shared pointer that this process will debug.
///
/// @param[in] plugin_name
- /// If NULL, select the best plug-in for the binary. If non-NULL
+ /// If nullptr, select the best plug-in for the binary. If non-nullptr
/// then look for a plugin whose PluginInfo's name matches
/// this string.
///
/// @see Process::CanDebug ()
//------------------------------------------------------------------
static lldb::ProcessSP
- FindPlugin (Target &target,
+ FindPlugin (lldb::TargetSP target_sp,
const char *plugin_name,
Listener &listener,
const FileSpec *crash_file_path);
-
-
//------------------------------------------------------------------
/// Static function that can be used with the \b host function
/// Host::StartMonitoringChildProcess ().
@@ -997,16 +998,16 @@ public:
/// Subclasses should call Host::StartMonitoringChildProcess ()
/// with:
/// callback = Process::SetHostProcessExitStatus
- /// callback_baton = NULL
+ /// callback_baton = nullptr
/// pid = Process::GetID()
/// monitor_signals = false
//------------------------------------------------------------------
static bool
- SetProcessExitStatus (void *callback_baton, // The callback baton which should be set to NULL
- lldb::pid_t pid, // The process ID we want to monitor
- bool exited,
- int signo, // Zero for no signal
- int status); // Exit value of process if signal is zero
+ SetProcessExitStatus(void *callback_baton, // The callback baton which should be set to nullptr
+ lldb::pid_t pid, // The process ID we want to monitor
+ bool exited,
+ int signo, // Zero for no signal
+ int status); // Exit value of process if signal is zero
lldb::ByteOrder
GetByteOrder () const;
@@ -1019,6 +1020,7 @@ public:
{
return m_process_unique_id;
}
+
//------------------------------------------------------------------
/// Check if a plug-in instance can debug the file in \a module.
///
@@ -1031,10 +1033,9 @@ public:
/// debug the executable, \b false otherwise.
//------------------------------------------------------------------
virtual bool
- CanDebug (Target &target,
+ CanDebug (lldb::TargetSP target,
bool plugin_specified_by_name) = 0;
-
//------------------------------------------------------------------
/// This object is about to be destroyed, do any necessary cleanup.
///
@@ -1043,8 +1044,7 @@ public:
//------------------------------------------------------------------
virtual void
Finalize();
-
-
+
//------------------------------------------------------------------
/// Return whether this object is valid (i.e. has not been finalized.)
///
@@ -1075,7 +1075,7 @@ public:
virtual CommandObject *
GetPluginCommandObject()
{
- return NULL;
+ return nullptr;
}
//------------------------------------------------------------------
@@ -1153,6 +1153,12 @@ public:
return 0;
}
+ virtual size_t
+ LoadModules (LoadedModuleInfoList &)
+ {
+ return 0;
+ }
+
protected:
virtual JITLoaderList &
GetJITLoaders ();
@@ -1163,7 +1169,7 @@ public:
///
/// @return
/// Returns a pointer to the SystemRuntime plugin for this Process
- /// if one is available. Else returns NULL.
+ /// if one is available. Else returns nullptr.
//------------------------------------------------------------------
virtual SystemRuntime *
GetSystemRuntime ();
@@ -1194,7 +1200,7 @@ public:
/// @param[in] strm
/// A stream where output intended for the user
/// (if the driver has a way to display that) generated during
- /// the connection. This may be NULL if no output is needed.A
+ /// the connection. This may be nullptr if no output is needed.A
///
/// @param[in] remote_url
/// The URL format that we are connecting to.
@@ -1236,31 +1242,24 @@ public:
GetImageInfoAddress ();
//------------------------------------------------------------------
- /// Load a shared library into this process.
- ///
- /// Try and load a shared library into the current process. This
- /// call might fail in the dynamic loader plug-in says it isn't safe
- /// to try and load shared libraries at the moment.
+ /// Called when the process is about to broadcast a public stop.
///
- /// @param[in] image_spec
- /// The image file spec that points to the shared library that
- /// you want to load.
- ///
- /// @param[out] error
- /// An error object that gets filled in with any errors that
- /// might occur when trying to load the shared library.
- ///
- /// @return
- /// A token that represents the shared library that can be
- /// later used to unload the shared library. A value of
- /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
- /// library can't be opened.
+ /// There are public and private stops. Private stops are when the
+ /// process is doing things like stepping and the client doesn't
+ /// need to know about starts and stop that implement a thread plan.
+ /// Single stepping over a source line in code might end up being
+ /// implemented by one or more process starts and stops. Public stops
+ /// are when clients will be notified that the process is stopped.
+ /// These events typically trigger UI updates (thread stack frames to
+ /// be displayed, variables to be displayed, and more). This function
+ /// can be overriden and allows process subclasses to do something
+ /// before the eBroadcastBitStateChanged event is sent to public
+ /// clients.
//------------------------------------------------------------------
- virtual uint32_t
- LoadImage (const FileSpec &image_spec, Error &error);
-
- virtual Error
- UnloadImage (uint32_t image_token);
+ virtual void
+ WillPublicStop ()
+ {
+ }
//------------------------------------------------------------------
/// Register for process and thread notifications.
@@ -1278,6 +1277,7 @@ public:
void
RegisterNotificationCallbacks (const Process::Notifications& callbacks);
#endif
+
//------------------------------------------------------------------
/// Unregister for process and thread notifications.
///
@@ -1298,6 +1298,7 @@ public:
bool
UnregisterNotificationCallbacks (const Process::Notifications& callbacks);
#endif
+
//==================================================================
// Built in Process Control functions
//==================================================================
@@ -1334,6 +1335,7 @@ public:
Error
ResumeSynchronous (Stream *stream);
+
//------------------------------------------------------------------
/// Halts a running process.
///
@@ -1346,12 +1348,15 @@ public:
/// @param[in] clear_thread_plans
/// If true, when the process stops, clear all thread plans.
///
+ /// @param[in] use_run_lock
+ /// Whether to release the run lock after the stop.
+ ///
/// @return
/// Returns an error object. If the error is empty, the process is halted.
/// otherwise the halt has failed.
//------------------------------------------------------------------
Error
- Halt (bool clear_thread_plans = false);
+ Halt (bool clear_thread_plans = false, bool use_run_lock = true);
//------------------------------------------------------------------
/// Detaches from a running or stopped process.
@@ -1402,7 +1407,7 @@ public:
Signal (int signal);
void
- SetUnixSignals(const lldb::UnixSignalsSP &signals_sp);
+ SetUnixSignals(lldb::UnixSignalsSP &&signals_sp);
const lldb::UnixSignalsSP &
GetUnixSignals();
@@ -1447,7 +1452,7 @@ public:
/// @param[in] strm
/// A stream where output intended for the user
/// (if the driver has a way to display that) generated during
- /// the connection. This may be NULL if no output is needed.A
+ /// the connection. This may be nullptr if no output is needed.A
///
/// @param[in] remote_url
/// The URL format that we are connecting to.
@@ -1525,7 +1530,6 @@ public:
process_arch.Clear();
}
-
//------------------------------------------------------------------
/// Called after a process re-execs itself.
///
@@ -1590,7 +1594,6 @@ public:
return error;
}
-
//------------------------------------------------------------------
/// Called after launching a process.
///
@@ -1600,8 +1603,6 @@ public:
virtual void
DidLaunch () {}
-
-
//------------------------------------------------------------------
/// Called before resuming to a process.
///
@@ -1639,7 +1640,6 @@ public:
return error;
}
-
//------------------------------------------------------------------
/// Called after resuming a process.
///
@@ -1649,7 +1649,6 @@ public:
virtual void
DidResume () {}
-
//------------------------------------------------------------------
/// Called before halting to a process.
///
@@ -1668,9 +1667,8 @@ public:
/// DoHalt must produce one and only one stop StateChanged event if it actually
/// stops the process. If the stop happens through some natural event (for
/// instance a SIGSTOP), then forwarding that event will do. Otherwise, you must
- /// generate the event manually. Note also, the private event thread is stopped when
- /// DoHalt is run to prevent the events generated while halting to trigger
- /// other state changes before the halt is complete.
+ /// generate the event manually. This function is called from the context of the
+ /// private state thread.
///
/// @param[out] caused_stop
/// If true, then this Halt caused the stop, otherwise, the
@@ -1688,7 +1686,6 @@ public:
return error;
}
-
//------------------------------------------------------------------
/// Called after halting a process.
///
@@ -1728,7 +1725,6 @@ public:
return error;
}
-
//------------------------------------------------------------------
/// Called after detaching from a process.
///
@@ -1781,7 +1777,6 @@ public:
virtual bool
DestroyRequiresHalt() { return true; }
-
//------------------------------------------------------------------
/// Called after sending a signal to a process.
///
@@ -1808,6 +1803,41 @@ public:
RefreshStateAfterStop () = 0;
//------------------------------------------------------------------
+ /// Sometimes the connection to a process can detect the host OS
+ /// version that the process is running on. The current platform
+ /// should be checked first in case the platform is connected, but
+ /// clients can fall back onto this function if the platform fails
+ /// to identify the host OS version. The platform should be checked
+ /// first in case you are running a simulator platform that might
+ /// itself be running natively, but have different heuristics for
+ /// figuring out which OS is is emulating.
+ ///
+ /// @param[out] major
+ /// The major OS version, or UINT32_MAX if it can't be determined
+ ///
+ /// @param[out] minor
+ /// The minor OS version, or UINT32_MAX if it can't be determined
+ ///
+ /// @param[out] update
+ /// The update OS version, or UINT32_MAX if it can't be determined
+ ///
+ /// @return
+ /// Returns \b true if the host OS version info was filled in
+ /// and \b false otherwise.
+ //------------------------------------------------------------------
+ virtual bool
+ GetHostOSVersion(uint32_t &major,
+ uint32_t &minor,
+ uint32_t &update)
+ {
+ major = UINT32_MAX;
+ minor = UINT32_MAX;
+ update = UINT32_MAX;
+ return false;
+ }
+
+
+ //------------------------------------------------------------------
/// Get the target object pointer for this module.
///
/// @return
@@ -1817,7 +1847,7 @@ public:
Target &
GetTarget ()
{
- return m_target;
+ return *m_target_sp.lock();
}
//------------------------------------------------------------------
@@ -1830,7 +1860,7 @@ public:
const Target &
GetTarget () const
{
- return m_target;
+ return *m_target_sp.lock();
}
//------------------------------------------------------------------
@@ -1888,7 +1918,6 @@ public:
virtual void
ModulesDidLoad (ModuleList &module_list);
-
//------------------------------------------------------------------
/// Retrieve the list of shared libraries that are loaded for this process
///
@@ -1919,30 +1948,20 @@ public:
return StructuredData::ObjectSP();
}
-protected:
-
- void
- SetState (lldb::EventSP &event_sp);
-
- lldb::StateType
- GetPrivateState ();
-
//------------------------------------------------------------------
- /// The "private" side of resuming a process. This doesn't alter the
- /// state of m_run_lock, but just causes the process to resume.
+ /// Print a user-visible warning about a module being built with optimization
///
- /// @return
- /// An Error object describing the success or failure of the resume.
- //------------------------------------------------------------------
- Error
- PrivateResume ();
-
- //------------------------------------------------------------------
- // Called internally
+ /// Prints a async warning message to the user one time per Module
+ /// where a function is found that was compiled with optimization, per
+ /// Process.
+ ///
+ /// @param [in] sc
+ /// A SymbolContext with eSymbolContextFunction and eSymbolContextModule
+ /// pre-computed.
//------------------------------------------------------------------
void
- CompleteAttach ();
-
+ PrintWarningOptimization (const SymbolContext &sc);
+
public:
//------------------------------------------------------------------
/// Get the exit status for a process.
@@ -1958,13 +1977,12 @@ public:
/// Get a textual description of what the process exited.
///
/// @return
- /// The textual description of why the process exited, or NULL
+ /// The textual description of why the process exited, or nullptr
/// if there is no description available.
//------------------------------------------------------------------
const char *
GetExitDescription ();
-
virtual void
DidExit ()
{
@@ -2045,7 +2063,7 @@ public:
/// otherwise.
//------------------------------------------------------------------
virtual bool
- IsAlive () = 0;
+ IsAlive ();
//------------------------------------------------------------------
/// Before lldb detaches from a process, it warns the user that they are about to lose their debug session.
@@ -2255,7 +2273,6 @@ public:
return 0;
}
-
//------------------------------------------------------------------
/// Write all or part of a scalar value to memory.
///
@@ -2329,7 +2346,6 @@ public:
size_t
WriteMemory (lldb::addr_t vm_addr, const void *buf, size_t size, Error &error);
-
//------------------------------------------------------------------
/// Actually allocate memory in the process.
///
@@ -2352,7 +2368,6 @@ public:
return LLDB_INVALID_ADDRESS;
}
-
//------------------------------------------------------------------
/// The public interface to allocating memory in the process.
///
@@ -2369,16 +2384,41 @@ public:
/// that a block that isn't set writable can still be written on from lldb,
/// just not by the process itself.
///
- /// @param[in/out] error
+ /// @param[in,out] error
/// An error object to fill in if things go wrong.
/// @return
/// The address of the allocated buffer in the process, or
/// LLDB_INVALID_ADDRESS if the allocation failed.
//------------------------------------------------------------------
-
lldb::addr_t
AllocateMemory (size_t size, uint32_t permissions, Error &error);
+ //------------------------------------------------------------------
+ /// The public interface to allocating memory in the process, this also
+ /// clears the allocated memory.
+ ///
+ /// This function will allocate memory in the process's address
+ /// space. This can't rely on the generic function calling mechanism,
+ /// since that requires this function.
+ ///
+ /// @param[in] size
+ /// The size of the allocation requested.
+ ///
+ /// @param[in] permissions
+ /// Or together any of the lldb::Permissions bits. The permissions on
+ /// a given memory allocation can't be changed after allocation. Note
+ /// that a block that isn't set writable can still be written on from lldb,
+ /// just not by the process itself.
+ ///
+ /// @param[in/out] error
+ /// An error object to fill in if things go wrong.
+ /// @return
+ /// The address of the allocated buffer in the process, or
+ /// LLDB_INVALID_ADDRESS if the allocation failed.
+ //------------------------------------------------------------------
+
+ lldb::addr_t
+ CallocateMemory (size_t size, uint32_t permissions, Error &error);
//------------------------------------------------------------------
/// Resolve dynamically loaded indirect functions.
@@ -2393,7 +2433,6 @@ public:
/// The address of the resolved function.
/// LLDB_INVALID_ADDRESS if the resolution failed.
//------------------------------------------------------------------
-
virtual lldb::addr_t
ResolveIndirectFunction(const Address *address, Error &error);
@@ -2518,7 +2557,6 @@ public:
/// @return
/// \btrue if the memory was deallocated, \bfalse otherwise.
//------------------------------------------------------------------
-
virtual Error
DoDeallocateMemory (lldb::addr_t ptr)
{
@@ -2527,7 +2565,6 @@ public:
return error;
}
-
//------------------------------------------------------------------
/// The public interface to deallocating memory in the process.
///
@@ -2541,7 +2578,6 @@ public:
/// @return
/// \btrue if the memory was deallocated, \bfalse otherwise.
//------------------------------------------------------------------
-
Error
DeallocateMemory (lldb::addr_t ptr);
@@ -2671,7 +2707,6 @@ public:
return error;
}
-
virtual Error
DisableBreakpointSite (BreakpointSite *bp_site)
{
@@ -2680,7 +2715,6 @@ public:
return error;
}
-
// This is implemented completely using the lldb::Process API. Subclasses
// don't need to implement this function unless the standard flow of
// read existing opcode, write breakpoint opcode, verify breakpoint opcode
@@ -2717,7 +2751,6 @@ public:
Error
EnableBreakpointSiteByID (lldb::user_id_t break_id);
-
// BreakpointLocations use RemoveOwnerFromBreakpointSite to remove
// themselves from the owner's list of this breakpoint sites.
void
@@ -2811,12 +2844,16 @@ public:
// Returns the process state when it is stopped. If specified, event_sp_ptr
// is set to the event which triggered the stop. If wait_always = false,
// and the process is already stopped, this function returns immediately.
+ // If the process is hijacked and use_run_lock is true (the default), then this
+ // function releases the run lock after the stop. Setting use_run_lock to false
+ // will avoid this behavior.
lldb::StateType
- WaitForProcessToStop (const TimeValue *timeout,
- lldb::EventSP *event_sp_ptr = NULL,
- bool wait_always = true,
- Listener *hijack_listener = NULL,
- Stream *stream = NULL);
+ WaitForProcessToStop(const TimeValue *timeout,
+ lldb::EventSP *event_sp_ptr = nullptr,
+ bool wait_always = true,
+ Listener *hijack_listener = nullptr,
+ Stream *stream = nullptr,
+ bool use_run_lock = true);
uint32_t
GetIOHandlerID () const
@@ -2838,9 +2875,9 @@ public:
SyncIOHandler (uint32_t iohandler_id, uint64_t timeout_msec);
lldb::StateType
- WaitForStateChangedEvents (const TimeValue *timeout,
- lldb::EventSP &event_sp,
- Listener *hijack_listener); // Pass NULL to use builtin listener
+ WaitForStateChangedEvents(const TimeValue *timeout,
+ lldb::EventSP &event_sp,
+ Listener *hijack_listener); // Pass nullptr to use builtin listener
//--------------------------------------------------------------------------------------
/// Centralize the code that handles and prints descriptions for process state changes.
@@ -2851,7 +2888,7 @@ public:
/// @param[in] stream
/// The output stream to get the state change description
///
- /// @param[inout] pop_process_io_handler
+ /// @param[in,out] pop_process_io_handler
/// If this value comes in set to \b true, then pop the Process IOHandler if needed.
/// Else this variable will be set to \b true or \b false to indicate if the process
/// needs to have its process IOHandler popped.
@@ -2863,9 +2900,9 @@ public:
HandleProcessStateChangedEvent (const lldb::EventSP &event_sp,
Stream *stream,
bool &pop_process_io_handler);
+
Event *
PeekAtStateChangedEvents ();
-
class
ProcessEventHijacker
@@ -2876,6 +2913,7 @@ public:
{
m_process.HijackProcessEvents (listener);
}
+
~ProcessEventHijacker ()
{
m_process.RestoreProcessEvents();
@@ -2884,6 +2922,7 @@ public:
private:
Process &m_process;
};
+
friend class ProcessEventHijacker;
friend class ProcessProperties;
//------------------------------------------------------------------
@@ -2910,27 +2949,6 @@ public:
void
RestoreProcessEvents ();
-private:
- //------------------------------------------------------------------
- /// This is the part of the event handling that for a process event.
- /// It decides what to do with the event and returns true if the
- /// event needs to be propagated to the user, and false otherwise.
- /// If the event is not propagated, this call will most likely set
- /// the target to executing again.
- /// There is only one place where this call should be called, HandlePrivateEvent.
- /// Don't call it from anywhere else...
- ///
- /// @param[in] event_ptr
- /// This is the event we are handling.
- ///
- /// @return
- /// Returns \b true if the event should be reported to the
- /// user, \b false otherwise.
- //------------------------------------------------------------------
- bool
- ShouldBroadcastEvent (Event *event_ptr);
-
-public:
const lldb::ABISP &
GetABI ();
@@ -3004,29 +3022,29 @@ public:
//------------------------------------------------------------------
// lldb::ExecutionContextScope pure virtual functions
//------------------------------------------------------------------
- virtual lldb::TargetSP
- CalculateTarget ();
+ lldb::TargetSP
+ CalculateTarget() override;
- virtual lldb::ProcessSP
- CalculateProcess ()
+ lldb::ProcessSP
+ CalculateProcess() override
{
return shared_from_this();
}
- virtual lldb::ThreadSP
- CalculateThread ()
+ lldb::ThreadSP
+ CalculateThread() override
{
return lldb::ThreadSP();
}
- virtual lldb::StackFrameSP
- CalculateStackFrame ()
+ lldb::StackFrameSP
+ CalculateStackFrame() override
{
return lldb::StackFrameSP();
}
- virtual void
- CalculateExecutionContext (ExecutionContext &exe_ctx);
+ void
+ CalculateExecutionContext(ExecutionContext &exe_ctx) override;
void
SetSTDIOFileDescriptor (int file_descriptor);
@@ -3129,9 +3147,98 @@ public:
return Error("Not supported");
}
+ size_t
+ AddImageToken(lldb::addr_t image_ptr);
+
+ lldb::addr_t
+ GetImagePtrFromToken(size_t token) const;
+
+ void
+ ResetImageToken(size_t token);
+
+ //------------------------------------------------------------------
+ /// Find the next branch instruction to set a breakpoint on
+ ///
+ /// When instruction stepping through a source line, instead of
+ /// stepping through each instruction, we can put a breakpoint on
+ /// the next branch instruction (within the range of instructions
+ /// we are stepping through) and continue the process to there,
+ /// yielding significant performance benefits over instruction
+ /// stepping.
+ ///
+ /// @param[in] default_stop_addr
+ /// The address of the instruction where lldb would put a
+ /// breakpoint normally.
+ ///
+ /// @param[in] range_bounds
+ /// The range which the breakpoint must be contained within.
+ /// Typically a source line.
+ ///
+ /// @return
+ /// The address of the next branch instruction, or the end of
+ /// the range provided in range_bounds. If there are any
+ /// problems with the disassembly or getting the instructions,
+ /// the original default_stop_addr will be returned.
+ //------------------------------------------------------------------
+ Address
+ AdvanceAddressToNextBranchInstruction (Address default_stop_addr,
+ AddressRange range_bounds);
+
protected:
+ void
+ SetState (lldb::EventSP &event_sp);
+
+ lldb::StateType
+ GetPrivateState ();
//------------------------------------------------------------------
+ /// The "private" side of resuming a process. This doesn't alter the
+ /// state of m_run_lock, but just causes the process to resume.
+ ///
+ /// @return
+ /// An Error object describing the success or failure of the resume.
+ //------------------------------------------------------------------
+ Error
+ PrivateResume ();
+
+ //------------------------------------------------------------------
+ // Called internally
+ //------------------------------------------------------------------
+ void
+ CompleteAttach ();
+
+ //------------------------------------------------------------------
+ /// Print a user-visible warning one time per Process
+ ///
+ /// A facility for printing a warning to the user once per repeat_key.
+ ///
+ /// warning_type is from the Process::Warnings enums.
+ /// repeat_key is a pointer value that will be used to ensure that the
+ /// warning message is not printed multiple times. For instance, with a
+ /// warning about a function being optimized, you can pass the CompileUnit
+ /// pointer to have the warning issued for only the first function in a
+ /// CU, or the Function pointer to have it issued once for every function,
+ /// or a Module pointer to have it issued once per Module.
+ ///
+ /// Classes outside Process should call a specific PrintWarning method
+ /// so that the warning strings are all centralized in Process, instead of
+ /// calling PrintWarning() directly.
+ ///
+ /// @param [in] warning_type
+ /// One of the types defined in Process::Warnings.
+ ///
+ /// @param [in] repeat_key
+ /// A pointer value used to ensure that the warning is only printed once.
+ /// May be nullptr, indicating that the warning is printed unconditionally
+ /// every time.
+ ///
+ /// @param [in] fmt
+ /// printf style format string
+ //------------------------------------------------------------------
+ void
+ PrintWarning (uint64_t warning_type, const void *repeat_key, const char *fmt, ...) __attribute__((format(printf, 4, 5)));
+
+ //------------------------------------------------------------------
// NextEventAction provides a way to register an action on the next
// event that is delivered to this process. There is currently only
// one next event action allowed in the process at one time. If a
@@ -3158,10 +3265,8 @@ protected:
}
virtual
- ~NextEventAction()
- {
- }
-
+ ~NextEventAction() = default;
+
virtual EventActionResult PerformAction (lldb::EventSP &event_sp) = 0;
virtual void HandleBeingUnshipped () {}
virtual EventActionResult HandleBeingInterrupted () = 0;
@@ -3170,6 +3275,7 @@ protected:
{
m_process->m_resume_requested = true;
}
+
protected:
Process *m_process;
};
@@ -3188,25 +3294,17 @@ protected:
public:
AttachCompletionHandler (Process *process, uint32_t exec_count);
- virtual
- ~AttachCompletionHandler()
- {
- }
-
- virtual EventActionResult PerformAction (lldb::EventSP &event_sp);
- virtual EventActionResult HandleBeingInterrupted ();
- virtual const char *GetExitString();
+ ~AttachCompletionHandler() override = default;
+
+ EventActionResult PerformAction(lldb::EventSP &event_sp) override;
+ EventActionResult HandleBeingInterrupted() override;
+ const char *GetExitString() override;
+
private:
uint32_t m_exec_count;
std::string m_exit_string;
};
- bool
- HijackPrivateProcessEvents (Listener *listener);
-
- void
- RestorePrivateProcessEvents ();
-
bool
PrivateStateThreadIsValid () const
{
@@ -3223,6 +3321,8 @@ protected:
// Type definitions
//------------------------------------------------------------------
typedef std::map<lldb::LanguageType, lldb::LanguageRuntimeSP> LanguageRuntimeCollection;
+ typedef std::unordered_set<const void *> WarningsPointerSet;
+ typedef std::map<uint64_t, WarningsPointerSet> WarningsCollection;
struct PreResumeCallbackAndBaton
{
@@ -3238,7 +3338,7 @@ protected:
//------------------------------------------------------------------
// Member variables
//------------------------------------------------------------------
- Target & m_target; ///< The target that owns this process.
+ std::weak_ptr<Target> m_target_sp; ///< The target that owns this process.
ThreadSafeValue<lldb::StateType> m_public_state;
ThreadSafeValue<lldb::StateType> m_private_state; // The actual state of our process
Broadcaster m_private_state_broadcaster; // This broadcaster feeds state changed events into the private state thread's listener.
@@ -3290,7 +3390,6 @@ protected:
std::vector<PreResumeCallbackAndBaton> m_pre_resume_actions;
ProcessRunLock m_public_run_lock;
ProcessRunLock m_private_run_lock;
- Predicate<bool> m_currently_handling_event; // This predicate is set in HandlePrivateEvent while all its business is being done.
ArchSpec::StopInfoOverrideCallbackType m_stop_info_override_callback;
bool m_currently_handling_do_on_removals;
bool m_resume_requested; // If m_currently_handling_event or m_currently_handling_do_on_removals are true, Resume will only request a resume, using this flag to check.
@@ -3302,6 +3401,7 @@ protected:
std::map<lldb::addr_t,lldb::addr_t> m_resolved_indirect_addresses;
bool m_destroy_in_process;
bool m_can_interpret_function_calls; // Some targets, e.g the OSX kernel, don't support the ability to modify the stack.
+ WarningsCollection m_warnings_issued; // A set of object pointers which have already had warnings printed
enum {
eCanJITDontKnow= 0,
@@ -3353,6 +3453,9 @@ protected:
void
HandlePrivateEvent (lldb::EventSP &event_sp);
+ Error
+ HaltPrivate();
+
lldb::StateType
WaitForProcessStopPrivate (const TimeValue *timeout, lldb::EventSP &event_sp);
@@ -3401,23 +3504,39 @@ protected:
}
Error
- HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp);
+ StopForDestroyOrDetach(lldb::EventSP &exit_event_sp);
bool
StateChangedIsExternallyHijacked();
void
LoadOperatingSystemPlugin(bool flush);
+
private:
//------------------------------------------------------------------
- // For Process only
+ /// This is the part of the event handling that for a process event.
+ /// It decides what to do with the event and returns true if the
+ /// event needs to be propagated to the user, and false otherwise.
+ /// If the event is not propagated, this call will most likely set
+ /// the target to executing again.
+ /// There is only one place where this call should be called, HandlePrivateEvent.
+ /// Don't call it from anywhere else...
+ ///
+ /// @param[in] event_ptr
+ /// This is the event we are handling.
+ ///
+ /// @return
+ /// Returns \b true if the event should be reported to the
+ /// user, \b false otherwise.
//------------------------------------------------------------------
+ bool
+ ShouldBroadcastEvent (Event *event_ptr);
+
void ControlPrivateStateThread (uint32_t signal);
DISALLOW_COPY_AND_ASSIGN (Process);
-
};
} // namespace lldb_private
-#endif // liblldb_Process_h_
+#endif // liblldb_Process_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/QueueItem.h b/contrib/llvm/tools/lldb/include/lldb/Target/QueueItem.h
index c69c825..aea5066 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/QueueItem.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/QueueItem.h
@@ -10,8 +10,14 @@
#ifndef liblldb_QueueItem_h_
#define liblldb_QueueItem_h_
+// C Includes
+// C++ Includes
+#include <memory>
+#include <string>
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
@@ -19,7 +25,6 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/ConstString.h"
-
namespace lldb_private {
//------------------------------------------------------------------
@@ -32,12 +37,10 @@ namespace lldb_private {
// execution of the item begins.
//------------------------------------------------------------------
-
class QueueItem :
public std::enable_shared_from_this<QueueItem>
{
public:
-
QueueItem (lldb::QueueSP queue_sp, lldb::ProcessSP process_sp, lldb::addr_t item_ref, lldb_private::Address address);
~QueueItem ();
@@ -98,7 +101,7 @@ public:
bool
IsValid ()
{
- return m_queue_wp.lock() != NULL;
+ return m_queue_wp.lock() != nullptr;
}
//------------------------------------------------------------------
@@ -200,7 +203,6 @@ protected:
void
FetchEntireItem ();
-
lldb::QueueWP m_queue_wp;
lldb::ProcessWP m_process_wp;
@@ -220,16 +222,10 @@ protected:
std::string m_queue_label;
std::string m_target_queue_label;
-
private:
- //------------------------------------------------------------------
- // For QueueItem only
- //------------------------------------------------------------------
-
DISALLOW_COPY_AND_ASSIGN (QueueItem);
-
};
} // namespace lldb_private
-#endif // liblldb_QueueItem_h_
+#endif // liblldb_QueueItem_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/RegisterContext.h b/contrib/llvm/tools/lldb/include/lldb/Target/RegisterContext.h
index 9108d45..037c27a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/RegisterContext.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/RegisterContext.h
@@ -29,8 +29,7 @@ public:
//------------------------------------------------------------------
RegisterContext (Thread &thread, uint32_t concrete_frame_idx);
- virtual
- ~RegisterContext ();
+ ~RegisterContext() override;
void
InvalidateIfNeeded (bool force);
@@ -93,7 +92,7 @@ public:
///
/// There may be multiple ways to enumerate the registers for a given
/// architecture. ABI references will specify one to be used with
- /// DWARF, the register numberings from stabs (aka "gcc"), there may
+ /// DWARF, the register numberings from process plugin, there may
/// be a variation used for eh_frame unwind instructions (e.g. on Darwin),
/// and so on. Register 5 by itself is meaningless - RegisterKind
/// enumeration tells you what context that number should be translated as.
@@ -213,26 +212,27 @@ public:
bool
WriteRegisterFromUnsigned (const RegisterInfo *reg_info, uint64_t uval);
+
bool
ConvertBetweenRegisterKinds (lldb::RegisterKind source_rk, uint32_t source_regnum, lldb::RegisterKind target_rk, uint32_t& target_regnum);
//------------------------------------------------------------------
// lldb::ExecutionContextScope pure virtual functions
//------------------------------------------------------------------
- virtual lldb::TargetSP
- CalculateTarget ();
+ lldb::TargetSP
+ CalculateTarget() override;
- virtual lldb::ProcessSP
- CalculateProcess ();
+ lldb::ProcessSP
+ CalculateProcess() override;
- virtual lldb::ThreadSP
- CalculateThread ();
+ lldb::ThreadSP
+ CalculateThread() override;
- virtual lldb::StackFrameSP
- CalculateStackFrame ();
+ lldb::StackFrameSP
+ CalculateStackFrame() override;
- virtual void
- CalculateExecutionContext (ExecutionContext &exe_ctx);
+ void
+ CalculateExecutionContext(ExecutionContext &exe_ctx) override;
uint32_t
GetStopID () const
@@ -262,4 +262,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_RegisterContext_h_
+#endif // liblldb_RegisterContext_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadList.h b/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadList.h
index 6a9bbab..5f5d39e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/SectionLoadList.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/DenseMap.h"
// Project includes
#include "lldb/lldb-public.h"
+#include "lldb/Core/Section.h"
#include "lldb/Host/Mutex.h"
namespace lldb_private {
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/StackFrame.h b/contrib/llvm/tools/lldb/include/lldb/Target/StackFrame.h
index 95e2144..b65b018 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/StackFrame.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/StackFrame.h
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <memory>
+
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Error.h"
@@ -45,11 +47,12 @@ class StackFrame :
public:
enum ExpressionPathOption
{
- eExpressionPathOptionCheckPtrVsMember = (1u << 0),
- eExpressionPathOptionsNoFragileObjcIvar = (1u << 1),
- eExpressionPathOptionsNoSyntheticChildren = (1u << 2),
- eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3),
- eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4)
+ eExpressionPathOptionCheckPtrVsMember = (1u << 0),
+ eExpressionPathOptionsNoFragileObjcIvar = (1u << 1),
+ eExpressionPathOptionsNoSyntheticChildren = (1u << 2),
+ eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3),
+ eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4),
+ eExpressionPathOptionsInspectAnonymousUnions = (1u << 5)
};
//------------------------------------------------------------------
@@ -135,7 +138,7 @@ public:
const Address& pc,
const SymbolContext *sc_ptr);
- virtual ~StackFrame ();
+ ~StackFrame() override;
lldb::ThreadSP
GetThread () const
@@ -223,7 +226,7 @@ public:
/// executing.
///
/// @return
- /// A pointer to the current Block. NULL is returned if this can
+ /// A pointer to the current Block. nullptr is returned if this can
/// not be provided.
//------------------------------------------------------------------
Block *
@@ -351,7 +354,7 @@ public:
/// Optional string that will be prepended to the frame output description.
//------------------------------------------------------------------
void
- DumpUsingSettingsFormat (Stream *strm, const char *frame_marker = NULL);
+ DumpUsingSettingsFormat(Stream *strm, const char *frame_marker = nullptr);
//------------------------------------------------------------------
/// Print a description for this frame using a default format.
@@ -388,10 +391,10 @@ public:
/// Returns true if successful.
//------------------------------------------------------------------
bool
- GetStatus (Stream &strm,
- bool show_frame_info,
- bool show_source,
- const char *frame_marker = NULL);
+ GetStatus(Stream &strm,
+ bool show_frame_info,
+ bool show_source,
+ const char *frame_marker = nullptr);
//------------------------------------------------------------------
/// Query whether this frame is a concrete frame on the call stack,
@@ -466,22 +469,32 @@ public:
TrackGlobalVariable (const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic);
//------------------------------------------------------------------
+ /// Query this frame to determine what the default language should be
+ /// when parsing expressions given the execution context.
+ ///
+ /// @return
+ /// The language of the frame if known, else lldb::eLanguageTypeUnknown.
+ //------------------------------------------------------------------
+ lldb::LanguageType
+ GetLanguage ();
+
+ //------------------------------------------------------------------
// lldb::ExecutionContextScope pure virtual functions
//------------------------------------------------------------------
- virtual lldb::TargetSP
- CalculateTarget ();
+ lldb::TargetSP
+ CalculateTarget() override;
- virtual lldb::ProcessSP
- CalculateProcess ();
+ lldb::ProcessSP
+ CalculateProcess() override;
- virtual lldb::ThreadSP
- CalculateThread ();
+ lldb::ThreadSP
+ CalculateThread() override;
- virtual lldb::StackFrameSP
- CalculateStackFrame ();
+ lldb::StackFrameSP
+ CalculateStackFrame() override;
void
- CalculateExecutionContext (ExecutionContext &exe_ctx);
+ CalculateExecutionContext(ExecutionContext &exe_ctx) override;
protected:
friend class StackFrameList;
@@ -520,9 +533,10 @@ private:
ValueObjectList m_variable_list_value_objects; // Value objects for each variable in m_variable_list_sp
StreamString m_disassembly;
Mutex m_mutex;
+
DISALLOW_COPY_AND_ASSIGN (StackFrame);
};
} // namespace lldb_private
-#endif // liblldb_StackFrame_h_
+#endif // liblldb_StackFrame_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/StackFrameList.h b/contrib/llvm/tools/lldb/include/lldb/Target/StackFrameList.h
index 2680be3..50a656d 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/StackFrameList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/StackFrameList.h
@@ -12,6 +12,7 @@
// C Includes
// C++ Includes
+#include <memory>
#include <vector>
// Other libraries and framework includes
@@ -84,15 +85,14 @@ public:
GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr);
size_t
- GetStatus (Stream &strm,
- uint32_t first_frame,
- uint32_t num_frames,
- bool show_frame_info,
- uint32_t num_frames_with_source,
- const char *frame_marker = NULL);
+ GetStatus(Stream &strm,
+ uint32_t first_frame,
+ uint32_t num_frames,
+ bool show_frame_info,
+ uint32_t num_frames_with_source,
+ const char *frame_marker = nullptr);
protected:
-
friend class Thread;
bool
@@ -129,9 +129,6 @@ protected:
void
SetCurrentInlinedDepth (uint32_t new_depth);
- //------------------------------------------------------------------
- // Classes that inherit from StackFrameList can see and modify these
- //------------------------------------------------------------------
typedef std::vector<lldb::StackFrameSP> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
@@ -147,12 +144,9 @@ protected:
bool m_show_inlined_frames;
private:
- //------------------------------------------------------------------
- // For StackFrameList only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (StackFrameList);
};
} // namespace lldb_private
-#endif // liblldb_StackFrameList_h_
+#endif // liblldb_StackFrameList_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/StackID.h b/contrib/llvm/tools/lldb/include/lldb/Target/StackID.h
index 75ad8ab..aad9d0c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/StackID.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/StackID.h
@@ -28,7 +28,7 @@ public:
StackID () :
m_pc (LLDB_INVALID_ADDRESS),
m_cfa (LLDB_INVALID_ADDRESS),
- m_symbol_scope (NULL)
+ m_symbol_scope (nullptr)
{
}
@@ -47,9 +47,7 @@ public:
{
}
- ~StackID()
- {
- }
+ ~StackID() = default;
lldb::addr_t
GetPC() const
@@ -80,7 +78,7 @@ public:
{
m_pc = LLDB_INVALID_ADDRESS;
m_cfa = LLDB_INVALID_ADDRESS;
- m_symbol_scope = NULL;
+ m_symbol_scope = nullptr;
}
bool
@@ -108,7 +106,6 @@ public:
}
protected:
-
friend class StackFrame;
void
@@ -123,18 +120,15 @@ protected:
m_cfa = cfa;
}
- //------------------------------------------------------------------
- // Classes that inherit from StackID can see and modify these
- //------------------------------------------------------------------
lldb::addr_t m_pc; // The pc value for the function/symbol for this frame. This will
- // only get used if the symbol scope is NULL (the code where we are
+ // only get used if the symbol scope is nullptr (the code where we are
// stopped is not represented by any function or symbol in any
// shared library).
lldb::addr_t m_cfa; // The call frame address (stack pointer) value
// at the beginning of the function that uniquely
// identifies this frame (along with m_symbol_scope below)
- SymbolContextScope *m_symbol_scope; // If NULL, there is no block or symbol for this frame.
- // If not NULL, this will either be the scope for the
+ SymbolContextScope *m_symbol_scope; // If nullptr, there is no block or symbol for this frame.
+ // If not nullptr, this will either be the scope for the
// lexical block for the frame, or the scope
// for the symbol. Symbol context scopes are
// always be unique pointers since the are part
@@ -151,4 +145,4 @@ bool operator< (const StackID& lhs, const StackID& rhs);
} // namespace lldb_private
-#endif // liblldb_StackID_h_
+#endif // liblldb_StackID_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/StopInfo.h b/contrib/llvm/tools/lldb/include/lldb/Target/StopInfo.h
index 2553887..dfc9860 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/StopInfo.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/StopInfo.h
@@ -172,7 +172,7 @@ public:
static lldb::StopInfoSP
CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan,
lldb::ValueObjectSP return_valobj_sp,
- lldb::ClangExpressionVariableSP expression_variable_sp);
+ lldb::ExpressionVariableSP expression_variable_sp);
static lldb::StopInfoSP
CreateStopReasonWithException (Thread &thread, const char *description);
@@ -183,7 +183,7 @@ public:
static lldb::ValueObjectSP
GetReturnValueObject (lldb::StopInfoSP &stop_info_sp);
- static lldb::ClangExpressionVariableSP
+ static lldb::ExpressionVariableSP
GetExpressionVariable (lldb::StopInfoSP &stop_info_sp);
protected:
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/SystemRuntime.h b/contrib/llvm/tools/lldb/include/lldb/Target/SystemRuntime.h
index 18f38f7..cefd724 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/SystemRuntime.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/SystemRuntime.h
@@ -75,8 +75,7 @@ public:
/// The destructor is virtual since this class is designed to be
/// inherited by the plug-in instance.
//------------------------------------------------------------------
- virtual
- ~SystemRuntime();
+ ~SystemRuntime() override;
//------------------------------------------------------------------
/// Called after attaching to a process.
@@ -276,6 +275,23 @@ public:
return LLDB_INVALID_ADDRESS;
}
+
+ //------------------------------------------------------------------
+ /// Retrieve the Queue kind for the queue at a thread's dispatch_qaddr.
+ ///
+ /// Retrieve the Queue kind - either eQueueKindSerial or
+ /// eQueueKindConcurrent, indicating that this queue processes work
+ /// items serially or concurrently.
+ ///
+ /// @return
+ /// The Queue kind, if it could be read, else eQueueKindUnknown.
+ //------------------------------------------------------------------
+ virtual lldb::QueueKind
+ GetQueueKind (lldb::addr_t dispatch_qaddr)
+ {
+ return lldb::eQueueKindUnknown;
+ }
+
//------------------------------------------------------------------
/// Get the pending work items for a libdispatch Queue
///
@@ -354,9 +370,10 @@ protected:
std::vector<ConstString> m_types;
private:
+
DISALLOW_COPY_AND_ASSIGN (SystemRuntime);
};
} // namespace lldb_private
-#endif // liblldb_SystemRuntime_h_
+#endif // liblldb_SystemRuntime_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Target.h b/contrib/llvm/tools/lldb/include/lldb/Target/Target.h
index 427f68e..0cdb248 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/Target.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Target.h
@@ -13,6 +13,10 @@
// C Includes
// C++ Includes
#include <list>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
// Other libraries and framework includes
// Project includes
@@ -24,6 +28,8 @@
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/UserSettingsController.h"
+#include "lldb/Expression/Expression.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/PathMappingList.h"
#include "lldb/Target/ProcessLaunchInfo.h"
@@ -55,8 +61,7 @@ class TargetProperties : public Properties
public:
TargetProperties(Target *target);
- virtual
- ~TargetProperties();
+ ~TargetProperties() override;
ArchSpec
GetDefaultArchitecture () const;
@@ -169,6 +174,9 @@ public:
bool
GetBreakpointsConsultPlatformAvoidList ();
+ lldb::LanguageType
+ GetLanguage () const;
+
const char *
GetExpressionPrefixContentsAsCString ();
@@ -229,7 +237,6 @@ private:
static void DisableASLRValueChangedCallback(void *target_property_ptr, OptionValue *);
static void DisableSTDIOValueChangedCallback(void *target_property_ptr, OptionValue *);
-private:
//------------------------------------------------------------------
// Member variables.
//------------------------------------------------------------------
@@ -295,9 +302,7 @@ public:
const char *
GetPrefix () const
{
- if (m_prefix.empty())
- return NULL;
- return m_prefix.c_str();
+ return (m_prefix.empty() ? nullptr : m_prefix.c_str());
}
void
@@ -438,6 +443,18 @@ public:
}
bool
+ GetColorizeErrors () const
+ {
+ return m_ansi_color_errors;
+ }
+
+ void
+ SetColorizeErrors (bool b)
+ {
+ m_ansi_color_errors = b;
+ }
+
+ bool
GetTrapExceptions() const
{
return m_trap_exceptions;
@@ -449,6 +466,18 @@ public:
m_trap_exceptions = b;
}
+ bool
+ GetREPLEnabled() const
+ {
+ return m_repl;
+ }
+
+ void
+ SetREPLEnabled (bool b)
+ {
+ m_repl = b;
+ }
+
void
SetCancelCallback (lldb::ExpressionCancelCallback callback, void *baton)
{
@@ -459,10 +488,36 @@ public:
bool
InvokeCancelCallback (lldb::ExpressionEvaluationPhase phase) const
{
- if (m_cancel_callback == nullptr)
- return false;
+ return ((m_cancel_callback != nullptr) ? m_cancel_callback(phase, m_cancel_callback_baton) : false);
+ }
+
+ // Allows the expression contents to be remapped to point to the specified file and line
+ // using #line directives.
+ void
+ SetPoundLine (const char *path, uint32_t line) const
+ {
+ if (path && path[0])
+ {
+ m_pound_line_file = path;
+ m_pound_line_line = line;
+ }
else
- return m_cancel_callback (phase, m_cancel_callback_baton);
+ {
+ m_pound_line_file.clear();
+ m_pound_line_line = 0;
+ }
+ }
+
+ const char *
+ GetPoundLineFilePath () const
+ {
+ return (m_pound_line_file.empty() ? nullptr : m_pound_line_file.c_str());
+ }
+
+ uint32_t
+ GetPoundLineLine () const
+ {
+ return m_pound_line_line;
}
void
@@ -489,13 +544,20 @@ private:
bool m_stop_others;
bool m_debug;
bool m_trap_exceptions;
+ bool m_repl;
bool m_generate_debug_info;
+ bool m_ansi_color_errors;
bool m_result_is_internal;
lldb::DynamicValueType m_use_dynamic;
uint32_t m_timeout_usec;
uint32_t m_one_thread_timeout_usec;
lldb::ExpressionCancelCallback m_cancel_callback;
void *m_cancel_callback_baton;
+ // If m_pound_line_file is not empty and m_pound_line_line is non-zero,
+ // use #line %u "%s" before the expression content to remap where the source
+ // originates
+ mutable std::string m_pound_line_file;
+ mutable uint32_t m_pound_line_line;
};
//----------------------------------------------------------------------
@@ -527,7 +589,7 @@ public:
static ConstString &GetStaticBroadcasterClass ();
- virtual ConstString &GetBroadcasterClass() const
+ ConstString &GetBroadcasterClass() const override
{
return GetStaticBroadcasterClass();
}
@@ -540,20 +602,19 @@ public:
TargetEventData (const lldb::TargetSP &target_sp, const ModuleList &module_list);
- virtual
- ~TargetEventData();
+ ~TargetEventData() override;
static const ConstString &
GetFlavorString ();
- virtual const ConstString &
- GetFlavor () const
+ const ConstString &
+ GetFlavor() const override
{
return TargetEventData::GetFlavorString ();
}
- virtual void
- Dump (Stream *s) const;
+ void
+ Dump(Stream *s) const override;
static const TargetEventData *
GetEventDataFromEvent (const Event *event_ptr);
@@ -583,6 +644,8 @@ public:
DISALLOW_COPY_AND_ASSIGN (TargetEventData);
};
+ ~Target() override;
+
static void
SettingsInitialize ();
@@ -608,8 +671,8 @@ public:
// UpdateInstanceName ();
lldb::ModuleSP
- GetSharedModule (const ModuleSpec &module_spec,
- Error *error_ptr = NULL);
+ GetSharedModule(const ModuleSpec &module_spec,
+ Error *error_ptr = nullptr);
//----------------------------------------------------------------------
// Settings accessors
@@ -618,36 +681,6 @@ public:
static const lldb::TargetPropertiesSP &
GetGlobalProperties();
-
-private:
- //------------------------------------------------------------------
- /// Construct with optional file and arch.
- ///
- /// This member is private. Clients must use
- /// TargetList::CreateTarget(const FileSpec*, const ArchSpec*)
- /// so all targets can be tracked from the central target list.
- ///
- /// @see TargetList::CreateTarget(const FileSpec*, const ArchSpec*)
- //------------------------------------------------------------------
- Target (Debugger &debugger,
- const ArchSpec &target_arch,
- const lldb::PlatformSP &platform_sp,
- bool is_dummy_target);
-
- // Helper function.
- bool
- ProcessIsValid ();
-
- // Copy breakpoints, stop hooks and so forth from the dummy target:
- void
- PrimeFromDummyTarget(Target *dummy_target);
-
- void
- AddBreakpoint(lldb::BreakpointSP breakpoint_sp, bool internal);
-
-public:
- ~Target();
-
Mutex &
GetAPIMutex ()
{
@@ -659,6 +692,7 @@ public:
void
CleanupProcess ();
+
//------------------------------------------------------------------
/// Dump a description of this object to a Stream.
///
@@ -718,7 +752,7 @@ public:
lldb::BreakpointSP
GetBreakpointByID (lldb::break_id_t break_id);
- // Use this to create a file and line breakpoint to a given module or all module it is NULL
+ // Use this to create a file and line breakpoint to a given module or all module it is nullptr
lldb::BreakpointSP
CreateBreakpoint (const FileSpecList *containingModules,
const FileSpec &file,
@@ -744,24 +778,32 @@ public:
bool internal,
bool request_hardware);
+ // Use this to create a breakpoint from a load address and a module file spec
+ lldb::BreakpointSP
+ CreateAddressInModuleBreakpoint (lldb::addr_t file_addr,
+ bool internal,
+ const FileSpec *file_spec,
+ bool request_hardware);
+
// Use this to create Address breakpoints:
lldb::BreakpointSP
- CreateBreakpoint (Address &addr,
+ CreateBreakpoint (const Address &addr,
bool internal,
bool request_hardware);
- // Use this to create a function breakpoint by regexp in containingModule/containingSourceFiles, or all modules if it is NULL
+ // Use this to create a function breakpoint by regexp in containingModule/containingSourceFiles, or all modules if it is nullptr
// When "skip_prologue is set to eLazyBoolCalculate, we use the current target
// setting, else we use the values passed in
lldb::BreakpointSP
CreateFuncRegexBreakpoint (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
RegularExpression &func_regexp,
+ lldb::LanguageType requested_language,
LazyBool skip_prologue,
bool internal,
bool request_hardware);
- // Use this to create a function breakpoint by name in containingModule, or all modules if it is NULL
+ // Use this to create a function breakpoint by name in containingModule, or all modules if it is nullptr
// When "skip_prologue is set to eLazyBoolCalculate, we use the current target
// setting, else we use the values passed in.
// func_name_type_mask is or'ed values from the FunctionNameType enum.
@@ -770,17 +812,18 @@ public:
const FileSpecList *containingSourceFiles,
const char *func_name,
uint32_t func_name_type_mask,
+ lldb::LanguageType language,
LazyBool skip_prologue,
bool internal,
bool request_hardware);
lldb::BreakpointSP
- CreateExceptionBreakpoint (enum lldb::LanguageType language,
- bool catch_bp,
- bool throw_bp,
- bool internal,
- Args *additional_args = nullptr,
- Error *additional_args_error = nullptr);
+ CreateExceptionBreakpoint(enum lldb::LanguageType language,
+ bool catch_bp,
+ bool throw_bp,
+ bool internal,
+ Args *additional_args = nullptr,
+ Error *additional_args_error = nullptr);
// This is the same as the func_name breakpoint except that you can specify a vector of names. This is cheaper
// than a regular expression breakpoint in the case where you just want to set a breakpoint on a set of names
@@ -792,6 +835,7 @@ public:
const char *func_names[],
size_t num_names,
uint32_t func_name_type_mask,
+ lldb::LanguageType language,
LazyBool skip_prologue,
bool internal,
bool request_hardware);
@@ -801,11 +845,11 @@ public:
const FileSpecList *containingSourceFiles,
const std::vector<std::string> &func_names,
uint32_t func_name_type_mask,
+ lldb::LanguageType language,
LazyBool skip_prologue,
bool internal,
bool request_hardware);
-
// Use this to create a general breakpoint:
lldb::BreakpointSP
CreateBreakpoint (lldb::SearchFilterSP &filter_sp,
@@ -818,7 +862,7 @@ public:
lldb::WatchpointSP
CreateWatchpoint (lldb::addr_t addr,
size_t size,
- const ClangASTType *type,
+ const CompilerType *type,
uint32_t kind,
Error &error);
@@ -914,26 +958,14 @@ public:
lldb::addr_t
GetOpcodeLoadAddress (lldb::addr_t load_addr, lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const;
-protected:
- //------------------------------------------------------------------
- /// Implementing of ModuleList::Notifier.
- //------------------------------------------------------------------
-
- virtual void
- ModuleAdded (const ModuleList& module_list, const lldb::ModuleSP& module_sp);
-
- virtual void
- ModuleRemoved (const ModuleList& module_list, const lldb::ModuleSP& module_sp);
-
- virtual void
- ModuleUpdated (const ModuleList& module_list,
- const lldb::ModuleSP& old_module_sp,
- const lldb::ModuleSP& new_module_sp);
- virtual void
- WillClearList (const ModuleList& module_list);
+ // Get load_addr as breakable load address for this target.
+ // Take a addr and check if for any reason there is a better address than this to put a breakpoint on.
+ // If there is then return that address.
+ // For MIPS, if instruction at addr is a delay slot instruction then this method will find the address of its
+ // previous instruction and return that address.
+ lldb::addr_t
+ GetBreakableLoadAddress (lldb::addr_t addr);
-public:
-
void
ModulesDidLoad (ModuleList &module_list);
@@ -970,7 +1002,7 @@ public:
///
/// @return
/// The shared pointer to the executable module which can
- /// contains a NULL Module object if no executable has been
+ /// contains a nullptr Module object if no executable has been
/// set.
///
/// @see DynamicLoader
@@ -1014,9 +1046,9 @@ public:
SetExecutableModule (lldb::ModuleSP& module_sp, bool get_dependent_files);
bool
- LoadScriptingResources (std::list<Error>& errors,
- Stream* feedback_stream = NULL,
- bool continue_on_error = true)
+ LoadScriptingResources(std::list<Error>& errors,
+ Stream* feedback_stream = nullptr,
+ bool continue_on_error = true)
{
return m_images.LoadScriptingResourcesInTarget(this,errors,feedback_stream,continue_on_error);
}
@@ -1146,12 +1178,12 @@ public:
// 2 - if there is a valid process, try and read from its memory
// 3 - if (prefer_file_cache == false) then read from object file cache
size_t
- ReadMemory (const Address& addr,
- bool prefer_file_cache,
- void *dst,
- size_t dst_len,
- Error &error,
- lldb::addr_t *load_addr_ptr = NULL);
+ ReadMemory(const Address& addr,
+ bool prefer_file_cache,
+ void *dst,
+ size_t dst_len,
+ Error &error,
+ lldb::addr_t *load_addr_ptr = nullptr);
size_t
ReadCStringFromMemory (const Address& addr, std::string &out_str, Error &error);
@@ -1199,28 +1231,70 @@ public:
//------------------------------------------------------------------
// lldb::ExecutionContextScope pure virtual functions
//------------------------------------------------------------------
- virtual lldb::TargetSP
- CalculateTarget ();
+ lldb::TargetSP
+ CalculateTarget() override;
- virtual lldb::ProcessSP
- CalculateProcess ();
+ lldb::ProcessSP
+ CalculateProcess() override;
- virtual lldb::ThreadSP
- CalculateThread ();
+ lldb::ThreadSP
+ CalculateThread() override;
- virtual lldb::StackFrameSP
- CalculateStackFrame ();
+ lldb::StackFrameSP
+ CalculateStackFrame() override;
- virtual void
- CalculateExecutionContext (ExecutionContext &exe_ctx);
+ void
+ CalculateExecutionContext(ExecutionContext &exe_ctx) override;
PathMappingList &
GetImageSearchPathList ();
+ TypeSystem *
+ GetScratchTypeSystemForLanguage (Error *error, lldb::LanguageType language, bool create_on_demand = true);
+
+ PersistentExpressionState *
+ GetPersistentExpressionStateForLanguage (lldb::LanguageType language);
+
+ // Creates a UserExpression for the given language, the rest of the parameters have the
+ // same meaning as for the UserExpression constructor.
+ // Returns a new-ed object which the caller owns.
+
+ UserExpression *
+ GetUserExpressionForLanguage(const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ Expression::ResultType desired_type,
+ const EvaluateExpressionOptions &options,
+ Error &error);
+
+ // Creates a FunctionCaller for the given language, the rest of the parameters have the
+ // same meaning as for the FunctionCaller constructor. Since a FunctionCaller can't be
+ // IR Interpreted, it makes no sense to call this with an ExecutionContextScope that lacks
+ // a Process.
+ // Returns a new-ed object which the caller owns.
+
+ FunctionCaller *
+ GetFunctionCallerForLanguage (lldb::LanguageType language,
+ const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name,
+ Error &error);
+
+ // Creates a UtilityFunction for the given language, the rest of the parameters have the
+ // same meaning as for the UtilityFunction constructor.
+ // Returns a new-ed object which the caller owns.
+
+ UtilityFunction *
+ GetUtilityFunctionForLanguage (const char *expr,
+ lldb::LanguageType language,
+ const char *name,
+ Error &error);
+
ClangASTContext *
GetScratchClangASTContext(bool create_on_demand=true);
- ClangASTImporter *
+ lldb::ClangASTImporterSP
GetClangASTImporter();
//----------------------------------------------------------------------
@@ -1266,23 +1340,26 @@ public:
// in in th execution context.
lldb::ExpressionResults
EvaluateExpression (const char *expression,
- StackFrame *frame,
+ ExecutionContextScope *exe_scope,
lldb::ValueObjectSP &result_valobj_sp,
const EvaluateExpressionOptions& options = EvaluateExpressionOptions());
- ClangPersistentVariables &
- GetPersistentVariables();
-
+ lldb::ExpressionVariableSP
+ GetPersistentVariable(const ConstString &name);
+
+ lldb::addr_t
+ GetPersistentSymbol(const ConstString &name);
+
//------------------------------------------------------------------
// Target Stop Hooks
//------------------------------------------------------------------
class StopHook : public UserID
{
public:
- ~StopHook ();
-
StopHook (const StopHook &rhs);
-
+
+ ~StopHook ();
+
StringList *
GetCommandPointer ()
{
@@ -1448,9 +1525,32 @@ public:
lldb::SearchFilterSP
GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles);
+
+ lldb::REPLSP
+ GetREPL (Error &err, lldb::LanguageType language, const char *repl_options, bool can_create);
+
+ void
+ SetREPL (lldb::LanguageType language, lldb::REPLSP repl_sp);
protected:
//------------------------------------------------------------------
+ /// Implementing of ModuleList::Notifier.
+ //------------------------------------------------------------------
+
+ void
+ ModuleAdded(const ModuleList& module_list, const lldb::ModuleSP& module_sp) override;
+
+ void
+ ModuleRemoved(const ModuleList& module_list, const lldb::ModuleSP& module_sp) override;
+
+ void
+ ModuleUpdated(const ModuleList& module_list,
+ const lldb::ModuleSP& old_module_sp,
+ const lldb::ModuleSP& new_module_sp) override;
+ void
+ WillClearList(const ModuleList& module_list) override;
+
+ //------------------------------------------------------------------
// Member variables.
//------------------------------------------------------------------
Debugger & m_debugger;
@@ -1470,11 +1570,13 @@ protected:
lldb::ProcessSP m_process_sp;
lldb::SearchFilterSP m_search_filter_sp;
PathMappingList m_image_search_paths;
- lldb::ClangASTContextUP m_scratch_ast_context_ap;
- lldb::ClangASTSourceUP m_scratch_ast_source_ap;
- lldb::ClangASTImporterUP m_ast_importer_ap;
+ TypeSystemMap m_scratch_type_system_map;
+
+ typedef std::map<lldb::LanguageType, lldb::REPLSP> REPLMap;
+ REPLMap m_repl_map;
+
+ lldb::ClangASTImporterSP m_ast_importer_sp;
lldb::ClangModulesDeclVendorUP m_clang_modules_decl_vendor_ap;
- lldb::ClangPersistentVariablesUP m_persistent_variables; ///< These are the persistent variables associated with this process for the expression parser.
lldb::SourceManagerUP m_source_manager_ap;
@@ -1490,9 +1592,34 @@ protected:
void *baton);
private:
+ //------------------------------------------------------------------
+ /// Construct with optional file and arch.
+ ///
+ /// This member is private. Clients must use
+ /// TargetList::CreateTarget(const FileSpec*, const ArchSpec*)
+ /// so all targets can be tracked from the central target list.
+ ///
+ /// @see TargetList::CreateTarget(const FileSpec*, const ArchSpec*)
+ //------------------------------------------------------------------
+ Target (Debugger &debugger,
+ const ArchSpec &target_arch,
+ const lldb::PlatformSP &platform_sp,
+ bool is_dummy_target);
+
+ // Helper function.
+ bool
+ ProcessIsValid ();
+
+ // Copy breakpoints, stop hooks and so forth from the dummy target:
+ void
+ PrimeFromDummyTarget(Target *dummy_target);
+
+ void
+ AddBreakpoint(lldb::BreakpointSP breakpoint_sp, bool internal);
+
DISALLOW_COPY_AND_ASSIGN (Target);
};
} // namespace lldb_private
-#endif // liblldb_Target_h_
+#endif // liblldb_Target_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/TargetList.h b/contrib/llvm/tools/lldb/include/lldb/Target/TargetList.h
index 27e46ba..fddb715 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/TargetList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/TargetList.h
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <vector>
+
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Broadcaster.h"
@@ -37,7 +39,6 @@ private:
TargetList(Debugger &debugger);
public:
-
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
//------------------------------------------------------------------
@@ -51,12 +52,12 @@ public:
static ConstString &GetStaticBroadcasterClass ();
- virtual ConstString &GetBroadcasterClass() const
+ ConstString &GetBroadcasterClass() const override
{
return GetStaticBroadcasterClass();
}
- virtual ~TargetList();
+ ~TargetList() override;
//------------------------------------------------------------------
/// Create a new Target.
@@ -72,12 +73,12 @@ public:
///
/// @param[in] file_spec
/// The main executable file for a debug target. This value
- /// can be NULL and the file can be set later using:
+ /// can be nullptr and the file can be set later using:
/// Target::SetExecutableModule (ModuleSP&)
///
/// @param[in] triple_cstr
/// A target triple string to be used for the target. This can
- /// be NULL if the triple is not known or when attaching to a
+ /// be nullptr if the triple is not known or when attaching to a
/// process.
///
/// @param[in] get_dependent_modules
@@ -86,7 +87,7 @@ public:
///
/// @param[in] platform_options
/// A pointer to the platform options to use when creating this
- /// target. If this value is NULL, then the currently selected
+ /// target. If this value is nullptr, then the currently selected
/// platform will be used.
///
/// @param[out] target_sp
@@ -149,7 +150,7 @@ public:
//------------------------------------------------------------------
/// Find the target that contains has an executable whose path
/// matches \a exe_file_spec, and whose architecture matches
- /// \a arch_ptr if arch_ptr is not NULL.
+ /// \a arch_ptr if arch_ptr is not nullptr.
///
/// @param[in] exe_file_spec
/// A file spec containing a basename, or a full path (directory
@@ -160,18 +161,18 @@ public:
/// directory, then both must match.
///
/// @param[in] exe_arch_ptr
- /// If not NULL then the architecture also needs to match, else
+ /// If not nullptr then the architecture also needs to match, else
/// the architectures will be compared.
///
/// @return
/// A shared pointer to a target object. The returned shared
- /// pointer will contain NULL if no target objects have a
+ /// pointer will contain nullptr if no target objects have a
/// executable whose full or partial path matches
/// with a matching process ID.
//------------------------------------------------------------------
lldb::TargetSP
- FindTargetWithExecutableAndArchitecture (const FileSpec &exe_file_spec,
- const ArchSpec *exe_arch_ptr = NULL) const;
+ FindTargetWithExecutableAndArchitecture(const FileSpec &exe_file_spec,
+ const ArchSpec *exe_arch_ptr = nullptr) const;
//------------------------------------------------------------------
/// Find the target that contains a process with process ID \a
@@ -182,7 +183,7 @@ public:
///
/// @return
/// A shared pointer to a target object. The returned shared
- /// pointer will contain NULL if no target objects own a process
+ /// pointer will contain nullptr if no target objects own a process
/// with a matching process ID.
//------------------------------------------------------------------
lldb::TargetSP
@@ -230,6 +231,7 @@ protected:
lldb::TargetSP m_dummy_target_sp;
mutable Mutex m_target_list_mutex;
uint32_t m_selected_target_idx;
+
private:
lldb::TargetSP
GetDummyTarget (lldb_private::Debugger &debugger);
@@ -262,4 +264,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_TargetList_h_
+#endif // liblldb_TargetList_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/Thread.h b/contrib/llvm/tools/lldb/include/lldb/Target/Thread.h
index c6a3c8e..ba73e0b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/Thread.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/Thread.h
@@ -10,6 +10,14 @@
#ifndef liblldb_Thread_h_
#define liblldb_Thread_h_
+// C Includes
+// C++ Includes
+#include <memory>
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Core/Broadcaster.h"
@@ -30,8 +38,7 @@ class ThreadProperties : public Properties
public:
ThreadProperties(bool is_global);
- virtual
- ~ThreadProperties();
+ ~ThreadProperties() override;
//------------------------------------------------------------------
/// The regular expression returned determines symbols that this
@@ -39,7 +46,7 @@ public:
///
/// @return
/// A pointer to a regular expression to compare against symbols,
- /// or NULL if all symbols are allowed.
+ /// or nullptr if all symbols are allowed.
///
//------------------------------------------------------------------
const RegularExpression *
@@ -82,7 +89,7 @@ public:
static ConstString &GetStaticBroadcasterClass ();
- virtual ConstString &GetBroadcasterClass() const
+ ConstString &GetBroadcasterClass() const override
{
return GetStaticBroadcasterClass();
}
@@ -97,19 +104,19 @@ public:
ThreadEventData();
- virtual ~ThreadEventData();
+ ~ThreadEventData() override;
static const ConstString &
GetFlavorString ();
- virtual const ConstString &
- GetFlavor () const
+ const ConstString &
+ GetFlavor() const override
{
return ThreadEventData::GetFlavorString ();
}
- virtual void
- Dump (Stream *s) const;
+ void
+ Dump(Stream *s) const override;
static const ThreadEventData *
GetEventDataFromEvent (const Event *event_ptr);
@@ -138,9 +145,9 @@ public:
private:
lldb::ThreadSP m_thread_sp;
StackID m_stack_id;
- DISALLOW_COPY_AND_ASSIGN (ThreadEventData);
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadEventData);
};
-
struct ThreadStateCheckpoint
{
@@ -151,15 +158,6 @@ public:
lldb::addr_t current_inlined_pc;
};
- static void
- SettingsInitialize ();
-
- static void
- SettingsTerminate ();
-
- static const ThreadPropertiesSP &
- GetGlobalProperties();
-
//------------------------------------------------------------------
/// Constructor
///
@@ -179,7 +177,16 @@ public:
//------------------------------------------------------------------
Thread (Process &process, lldb::tid_t tid, bool use_invalid_index_id = false);
- virtual ~Thread();
+ ~Thread() override;
+
+ static void
+ SettingsInitialize ();
+
+ static void
+ SettingsTerminate ();
+
+ static const ThreadPropertiesSP &
+ GetGlobalProperties();
lldb::ProcessSP
GetProcess() const
@@ -303,6 +310,9 @@ public:
lldb::StopReason
GetStopReason();
+ bool
+ StopInfoIsUpToDate() const;
+
// This sets the stop reason to a "blank" stop reason, so you can call functions on the thread
// without having the called function run with whatever stop reason you stopped with.
void
@@ -320,7 +330,7 @@ public:
virtual const char *
GetInfo ()
{
- return NULL;
+ return nullptr;
}
//------------------------------------------------------------------
@@ -348,7 +358,7 @@ public:
virtual const char *
GetName ()
{
- return NULL;
+ return nullptr;
}
virtual void
@@ -357,6 +367,35 @@ public:
}
//------------------------------------------------------------------
+ /// Whether this thread can be associated with a libdispatch queue
+ ///
+ /// The Thread may know if it is associated with a libdispatch queue,
+ /// it may know definitively that it is NOT associated with a libdispatch
+ /// queue, or it may be unknown whether it is associated with a libdispatch
+ /// queue.
+ ///
+ /// @return
+ /// eLazyBoolNo if this thread is definitely not associated with a
+ /// libdispatch queue (e.g. on a non-Darwin system where GCD aka
+ /// libdispatch is not available).
+ ///
+ /// eLazyBoolYes this thread is associated with a libdispatch queue.
+ ///
+ /// eLazyBoolCalculate this thread may be associated with a libdispatch
+ /// queue but the thread doesn't know one way or the other.
+ //------------------------------------------------------------------
+ virtual lldb_private::LazyBool
+ GetAssociatedWithLibdispatchQueue ()
+ {
+ return eLazyBoolNo;
+ }
+
+ virtual void
+ SetAssociatedWithLibdispatchQueue (lldb_private::LazyBool associated_with_libdispatch_queue)
+ {
+ }
+
+ //------------------------------------------------------------------
/// Retrieve the Queue ID for the queue currently using this Thread
///
/// If this Thread is doing work on behalf of a libdispatch/GCD queue,
@@ -390,12 +429,12 @@ public:
///
/// @return
/// The Queue name, if the Thread subclass implements this, else
- /// NULL.
+ /// nullptr.
//------------------------------------------------------------------
virtual const char *
GetQueueName ()
{
- return NULL;
+ return nullptr;
}
virtual void
@@ -404,6 +443,29 @@ public:
}
//------------------------------------------------------------------
+ /// Retrieve the Queue kind for the queue currently using this Thread
+ ///
+ /// If this Thread is doing work on behalf of a libdispatch/GCD queue,
+ /// retrieve the Queue kind - either eQueueKindSerial or
+ /// eQueueKindConcurrent, indicating that this queue processes work
+ /// items serially or concurrently.
+ ///
+ /// @return
+ /// The Queue kind, if the Thread subclass implements this, else
+ /// eQueueKindUnknown.
+ //------------------------------------------------------------------
+ virtual lldb::QueueKind
+ GetQueueKind ()
+ {
+ return lldb::eQueueKindUnknown;
+ }
+
+ virtual void
+ SetQueueKind (lldb::QueueKind kind)
+ {
+ }
+
+ //------------------------------------------------------------------
/// Retrieve the Queue for this thread, if any.
///
/// @return
@@ -441,6 +503,30 @@ public:
return LLDB_INVALID_ADDRESS;
}
+ virtual void
+ SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t)
+ {
+ }
+
+ //------------------------------------------------------------------
+ /// Whether this Thread already has all the Queue information cached or not
+ ///
+ /// A Thread may be associated with a libdispatch work Queue at a given
+ /// public stop event. If so, the thread can satisify requests like
+ /// GetQueueLibdispatchQueueAddress, GetQueueKind, GetQueueName, and GetQueueID
+ /// either from information from the remote debug stub when it is initially
+ /// created, or it can query the SystemRuntime for that information.
+ ///
+ /// This method allows the SystemRuntime to discover if a thread has this
+ /// information already, instead of calling the thread to get the information
+ /// and having the thread call the SystemRuntime again.
+ //------------------------------------------------------------------
+ virtual bool
+ ThreadHasQueueInformation () const
+ {
+ return false;
+ }
+
virtual uint32_t
GetStackFrameCount()
{
@@ -475,7 +561,7 @@ public:
ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp, bool broadcast = false);
Error
- JumpToLine (const FileSpec &file, uint32_t line, bool can_leave_function, std::string *warnings = NULL);
+ JumpToLine(const FileSpec &file, uint32_t line, bool can_leave_function, std::string *warnings = nullptr);
virtual lldb::StackFrameSP
GetFrameWithStackID (const StackID &stack_id)
@@ -492,16 +578,11 @@ public:
}
lldb::StackFrameSP
- GetSelectedFrame ()
- {
- lldb::StackFrameListSP stack_frame_list_sp(GetStackFrameList());
- return stack_frame_list_sp->GetFrameAtIndex (stack_frame_list_sp->GetSelectedFrameIndex());
- }
+ GetSelectedFrame ();
uint32_t
SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast = false);
-
bool
SetSelectedFrameByIndex (uint32_t frame_idx, bool broadcast = false);
@@ -608,6 +689,7 @@ public:
//------------------------------------------------------------------
virtual Error
StepOut ();
+
//------------------------------------------------------------------
/// Retrieves the per-thread data area.
/// Most OSs maintain a per-thread pointer (e.g. the FS register on
@@ -684,7 +766,7 @@ public:
/// Otherwise this plan will go on the end of the plan stack.
///
/// @return
- /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueFundamentalPlan (bool abort_other_plans);
@@ -703,7 +785,7 @@ public:
/// \b true if we will stop other threads while we single step this one.
///
/// @return
- /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForStepSingleInstruction (bool step_over,
@@ -739,7 +821,7 @@ public:
/// If eLazyBoolCalculate, we will consult the default set in the thread.
///
/// @return
- /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForStepOverRange (bool abort_other_plans,
@@ -748,6 +830,15 @@ public:
lldb::RunMode stop_other_threads,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
+ // Helper function that takes a LineEntry to step, insted of an AddressRange. This may combine multiple
+ // LineEntries of the same source line number to step over a longer address range in a single operation.
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForStepOverRange (bool abort_other_plans,
+ const LineEntry &line_entry,
+ const SymbolContext &addr_context,
+ lldb::RunMode stop_other_threads,
+ LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
+
//------------------------------------------------------------------
/// Queues the plan used to step through an address range, stepping into functions.
///
@@ -783,7 +874,7 @@ public:
/// If eLazyBoolCalculate, it will consult the default set in the thread.
///
/// @return
- /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForStepInRange (bool abort_other_plans,
@@ -794,6 +885,17 @@ public:
LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
+ // Helper function that takes a LineEntry to step, insted of an AddressRange. This may combine multiple
+ // LineEntries of the same source line number to step over a longer address range in a single operation.
+ virtual lldb::ThreadPlanSP
+ QueueThreadPlanForStepInRange (bool abort_other_plans,
+ const LineEntry &line_entry,
+ const SymbolContext &addr_context,
+ const char *step_in_target,
+ lldb::RunMode stop_other_threads,
+ LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
+ LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
+
//------------------------------------------------------------------
/// Queue the plan used to step out of the function at the current PC of
/// \a thread.
@@ -824,7 +926,7 @@ public:
/// If eLazyBoolCalculate, it will consult the default set in the thread.
///
/// @return
- /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForStepOut (bool abort_other_plans,
@@ -862,8 +964,18 @@ public:
/// @param[in] run_vote
/// See standard meanings for the stop & run votes in ThreadPlan.h.
///
+ /// @param[in] continue_to_next_branch
+ /// Normally this will enqueue a plan that will put a breakpoint on the return address and continue
+ /// to there. If continue_to_next_branch is true, this is an operation not involving the user --
+ /// e.g. stepping "next" in a source line and we instruction stepped into another function --
+ /// so instead of putting a breakpoint on the return address, advance the breakpoint to the
+ /// end of the source line that is doing the call, or until the next flow control instruction.
+ /// If the return value from the function call is to be retrieved / displayed to the user, you must stop
+ /// on the return address. The return value may be stored in volatile registers which are overwritten
+ /// before the next branch instruction.
+ ///
/// @return
- /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForStepOutNoShouldStop (bool abort_other_plans,
@@ -872,7 +984,8 @@ public:
bool stop_other_threads,
Vote stop_vote, // = eVoteYes,
Vote run_vote, // = eVoteNoOpinion);
- uint32_t frame_idx);
+ uint32_t frame_idx,
+ bool continue_to_next_branch = false);
//------------------------------------------------------------------
/// Gets the plan used to step through the code that steps from a function
@@ -891,7 +1004,7 @@ public:
/// \b true if we will stop other threads while we single step this one.
///
/// @return
- /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForStepThrough (StackID &return_stack_id,
@@ -914,7 +1027,7 @@ public:
/// \b true if we will stop other threads while we single step this one.
///
/// @return
- /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForRunToAddress (bool abort_other_plans,
@@ -957,15 +1070,6 @@ public:
Error
UnwindInnermostExpression();
-private:
- bool
- PlanIsBasePlan (ThreadPlan *plan_ptr);
-
- void
- BroadcastSelectedFrameChange(StackID &new_frame_id);
-
-public:
-
//------------------------------------------------------------------
/// Gets the outer-most plan that was popped off the plan stack in the
/// most recent stop. Useful for printing the stop reason accurately.
@@ -990,11 +1094,11 @@ public:
/// Gets the outer-most expression variable from the completed plans
///
/// @return
- /// A ClangExpressionVariableSP, either empty if there is no
+ /// A ExpressionVariableSP, either empty if there is no
/// plan completed an expression during the current stop
/// or the expression variable that was made for the completed expression.
//------------------------------------------------------------------
- lldb::ClangExpressionVariableSP
+ lldb::ExpressionVariableSP
GetExpressionVariable ();
//------------------------------------------------------------------
@@ -1041,7 +1145,6 @@ public:
void
QueueThreadPlan (lldb::ThreadPlanSP &plan_sp, bool abort_other_plans);
-
//------------------------------------------------------------------
/// Discards the plans queued on the plan stack of the current thread. This is
/// arbitrated by the "Master" ThreadPlans, using the "OkayToDiscard" call.
@@ -1147,20 +1250,20 @@ public:
//------------------------------------------------------------------
// lldb::ExecutionContextScope pure virtual functions
//------------------------------------------------------------------
- virtual lldb::TargetSP
- CalculateTarget ();
+ lldb::TargetSP
+ CalculateTarget() override;
- virtual lldb::ProcessSP
- CalculateProcess ();
+ lldb::ProcessSP
+ CalculateProcess() override;
- virtual lldb::ThreadSP
- CalculateThread ();
+ lldb::ThreadSP
+ CalculateThread() override;
- virtual lldb::StackFrameSP
- CalculateStackFrame ();
+ lldb::StackFrameSP
+ CalculateStackFrame() override;
- virtual void
- CalculateExecutionContext (ExecutionContext &exe_ctx);
+ void
+ CalculateExecutionContext(ExecutionContext &exe_ctx) override;
lldb::StackFrameSP
GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr);
@@ -1271,7 +1374,6 @@ public:
}
protected:
-
friend class ThreadPlan;
friend class ThreadList;
friend class ThreadEventData;
@@ -1323,7 +1425,15 @@ protected:
lldb::StackFrameListSP
GetStackFrameList ();
-
+
+ void
+ SetTemporaryResumeState(lldb::StateType new_state)
+ {
+ m_temporary_resume_state = new_state;
+ }
+
+ void
+ FunctionOptimizationWarning (lldb_private::StackFrame *frame);
//------------------------------------------------------------------
// Classes that inherit from Process can see and modify these
@@ -1353,14 +1463,17 @@ protected:
private:
bool m_extended_info_fetched; // Have we tried to retrieve the m_extended_info for this thread?
StructuredData::ObjectSP m_extended_info; // The extended info for this thread
- //------------------------------------------------------------------
- // For Thread only
- //------------------------------------------------------------------
- DISALLOW_COPY_AND_ASSIGN (Thread);
+private:
+ bool
+ PlanIsBasePlan (ThreadPlan *plan_ptr);
+ void
+ BroadcastSelectedFrameChange(StackID &new_frame_id);
+
+ DISALLOW_COPY_AND_ASSIGN (Thread);
};
} // namespace lldb_private
-#endif // liblldb_Thread_h_
+#endif // liblldb_Thread_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadList.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadList.h
index 12c430c..e6489b2 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadList.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadList.h
@@ -32,8 +32,7 @@ public:
ThreadList (const ThreadList &rhs);
- virtual
- ~ThreadList ();
+ ~ThreadList() override;
const ThreadList&
operator = (const ThreadList& rhs);
@@ -128,8 +127,8 @@ public:
void
SetStopID (uint32_t stop_id);
- virtual Mutex &
- GetMutex ();
+ Mutex &
+ GetMutex() override;
void
Update (ThreadList &rhs);
@@ -150,9 +149,10 @@ protected:
lldb::tid_t m_selected_tid; ///< For targets that need the notion of a current thread.
private:
+
ThreadList ();
};
} // namespace lldb_private
-#endif // liblldb_ThreadList_h_
+#endif // liblldb_ThreadList_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlan.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlan.h
index db2e798..e6f9aeb 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlan.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlan.h
@@ -13,6 +13,7 @@
// C Includes
// C++ Includes
#include <string>
+
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@@ -518,10 +519,10 @@ public:
// the user regained control at that point) a subsequent process control command step/continue/etc. might
// complete the expression evaluations. If so, the result of the expression evaluation will show up here.
- virtual lldb::ClangExpressionVariableSP
+ virtual lldb::ExpressionVariableSP
GetExpressionVariable ()
{
- return lldb::ClangExpressionVariableSP();
+ return lldb::ExpressionVariableSP();
}
// If a thread plan stores the state before it was run, then you might
@@ -562,13 +563,14 @@ public:
else
return m_iteration_count;
}
+
protected:
//------------------------------------------------------------------
// Classes that inherit from ThreadPlan can see and modify these
//------------------------------------------------------------------
virtual bool
- DoWillResume (lldb::StateType resume_state, bool current_plan) { return true; };
+ DoWillResume (lldb::StateType resume_state, bool current_plan) { return true; }
virtual bool
DoPlanExplainsStop (Event *event_ptr) = 0;
@@ -613,6 +615,9 @@ protected:
virtual lldb::StateType
GetPlanRunState () = 0;
+ bool
+ IsUsuallyUnexplainedStopReason(lldb::StopReason);
+
Thread &m_thread;
Vote m_stop_vote;
Vote m_run_vote;
@@ -653,47 +658,46 @@ class ThreadPlanNull : public ThreadPlan
{
public:
ThreadPlanNull (Thread &thread);
- virtual ~ThreadPlanNull ();
+ ~ThreadPlanNull() override;
- virtual void
- GetDescription (Stream *s,
- lldb::DescriptionLevel level);
+ void
+ GetDescription(Stream *s,
+ lldb::DescriptionLevel level) override;
- virtual bool
- ValidatePlan (Stream *error);
+ bool
+ ValidatePlan(Stream *error) override;
- virtual bool
- ShouldStop (Event *event_ptr);
+ bool
+ ShouldStop(Event *event_ptr) override;
- virtual bool
- MischiefManaged ();
+ bool
+ MischiefManaged() override;
- virtual bool
- WillStop ();
+ bool
+ WillStop() override;
- virtual bool
- IsBasePlan()
+ bool
+ IsBasePlan() override
{
return true;
}
- virtual bool
- OkayToDiscard ()
+ bool
+ OkayToDiscard() override
{
return false;
}
protected:
- virtual bool
- DoPlanExplainsStop (Event *event_ptr);
+ bool
+ DoPlanExplainsStop(Event *event_ptr) override;
- virtual lldb::StateType
- GetPlanRunState ();
+ lldb::StateType
+ GetPlanRunState() override;
DISALLOW_COPY_AND_ASSIGN(ThreadPlanNull);
};
-
} // namespace lldb_private
-#endif // liblldb_ThreadPlan_h_
+#endif // liblldb_ThreadPlan_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanBase.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanBase.h
index 69959e1..a0d30b5 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanBase.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanBase.h
@@ -31,31 +31,32 @@ class ThreadPlanBase : public ThreadPlan
{
friend class Process; // RunThreadPlan manages "stopper" base plans.
public:
- virtual ~ThreadPlanBase ();
+ ~ThreadPlanBase() override;
- virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
- virtual bool ValidatePlan (Stream *error);
- virtual bool ShouldStop (Event *event_ptr);
- virtual Vote ShouldReportStop (Event *event_ptr);
- virtual bool StopOthers ();
- virtual lldb::StateType GetPlanRunState ();
- virtual bool WillStop ();
- virtual bool MischiefManaged ();
+ void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
+ bool ValidatePlan(Stream *error) override;
+ bool ShouldStop(Event *event_ptr) override;
+ Vote ShouldReportStop(Event *event_ptr) override;
+ bool StopOthers() override;
+ lldb::StateType GetPlanRunState() override;
+ bool WillStop() override;
+ bool MischiefManaged() override;
- virtual bool OkayToDiscard()
+ bool
+ OkayToDiscard() override
{
return false;
}
- virtual bool
- IsBasePlan()
+ bool
+ IsBasePlan() override
{
return true;
}
protected:
- virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
- virtual bool DoPlanExplainsStop (Event *event_ptr);
+ bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
+ bool DoPlanExplainsStop(Event *event_ptr) override;
ThreadPlanBase (Thread &thread);
private:
@@ -65,7 +66,6 @@ private:
DISALLOW_COPY_AND_ASSIGN (ThreadPlanBase);
};
-
} // namespace lldb_private
-#endif // liblldb_ThreadPlanFundamental_h_
+#endif // liblldb_ThreadPlanFundamental_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunction.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunction.h
index 36e4d6e..47eee28 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunction.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunction.h
@@ -26,11 +26,11 @@ class ThreadPlanCallFunction : public ThreadPlan
{
// Create a thread plan to call a function at the address passed in the "function"
// argument. If you plan to call GetReturnValueObject, then pass in the
- // return type, otherwise just pass in an invalid ClangASTType.
+ // return type, otherwise just pass in an invalid CompilerType.
public:
ThreadPlanCallFunction (Thread &thread,
const Address &function,
- const ClangASTType &return_type,
+ const CompilerType &return_type,
llvm::ArrayRef<lldb::addr_t> args,
const EvaluateExpressionOptions &options);
@@ -38,35 +38,34 @@ public:
const Address &function,
const EvaluateExpressionOptions &options);
- virtual
- ~ThreadPlanCallFunction ();
+ ~ThreadPlanCallFunction() override;
- virtual void
- GetDescription (Stream *s, lldb::DescriptionLevel level);
+ void
+ GetDescription(Stream *s, lldb::DescriptionLevel level) override;
- virtual bool
- ValidatePlan (Stream *error);
+ bool
+ ValidatePlan(Stream *error) override;
- virtual bool
- ShouldStop (Event *event_ptr);
+ bool
+ ShouldStop(Event *event_ptr) override;
- virtual Vote
- ShouldReportStop(Event *event_ptr);
+ Vote
+ ShouldReportStop(Event *event_ptr) override;
- virtual bool
- StopOthers ();
+ bool
+ StopOthers() override;
- virtual lldb::StateType
- GetPlanRunState ();
+ lldb::StateType
+ GetPlanRunState() override;
- virtual void
- DidPush ();
+ void
+ DidPush() override;
- virtual bool
- WillStop ();
+ bool
+ WillStop() override;
- virtual bool
- MischiefManaged ();
+ bool
+ MischiefManaged() override;
// To get the return value from a function call you must create a
// lldb::ValueSP that contains a valid clang type in its context and call
@@ -77,8 +76,8 @@ public:
// plan is complete, you can call "GetReturnValue()" to retrieve the value
// that was extracted.
- virtual lldb::ValueObjectSP
- GetReturnValueObject ()
+ lldb::ValueObjectSP
+ GetReturnValueObject() override
{
return m_return_valobj_sp;
}
@@ -93,11 +92,11 @@ public:
return m_function_sp;
}
- // Classes that derive from ClangFunction, and implement
+ // Classes that derive from FunctionCaller, and implement
// their own WillPop methods should call this so that the
// thread state gets restored if the plan gets discarded.
- virtual void
- WillPop ();
+ void
+ WillPop() override;
// If the thread plan stops mid-course, this will be the stop reason that interrupted us.
// Once DoTakedown is called, this will be the real stop reason at the end of the function call.
@@ -105,8 +104,8 @@ public:
// This is needed because we want the CallFunction thread plans not to show up as the stop reason.
// But if something bad goes wrong, it is nice to be able to tell the user what really happened.
- virtual lldb::StopInfoSP
- GetRealStopInfo()
+ lldb::StopInfoSP
+ GetRealStopInfo() override
{
if (m_real_stop_info_sp)
return m_real_stop_info_sp;
@@ -120,23 +119,23 @@ public:
return m_stop_address;
}
- virtual bool
- RestoreThreadState();
+ bool
+ RestoreThreadState() override;
- virtual void
- ThreadDestroyed ()
+ void
+ ThreadDestroyed() override
{
m_takedown_done = true;
}
- virtual void
- SetStopOthers (bool new_value);
+ void
+ SetStopOthers(bool new_value) override;
protected:
void ReportRegisterState (const char *message);
- virtual bool
- DoPlanExplainsStop (Event *event_ptr);
+ bool
+ DoPlanExplainsStop(Event *event_ptr) override;
virtual void
SetReturnValue();
@@ -184,10 +183,10 @@ protected:
lldb::addr_t m_stop_address; // This is the address we stopped at. Also set in DoTakedown;
private:
- ClangASTType m_return_type;
+ CompilerType m_return_type;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction);
};
} // namespace lldb_private
-#endif // liblldb_ThreadPlanCallFunction_h_
+#endif // liblldb_ThreadPlanCallFunction_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h
index 83d78a5..5290571 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h
@@ -38,7 +38,7 @@ public:
llvm::ArrayRef<ABI::CallArgument> args,
const EvaluateExpressionOptions &options);
- ~ThreadPlanCallFunctionUsingABI ();
+ ~ThreadPlanCallFunctionUsingABI() override;
void
GetDescription (Stream *s, lldb::DescriptionLevel level) override;
@@ -47,7 +47,6 @@ protected:
void
SetReturnValue () override;
-
private:
llvm::Type &m_return_type;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunctionUsingABI);
@@ -55,4 +54,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ThreadPlanCallFunctionUsingABI_h_
+#endif // liblldb_ThreadPlanCallFunctionUsingABI_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h
index e40762c..bb261d9 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h
@@ -30,22 +30,21 @@ public:
Address &function,
llvm::ArrayRef<lldb::addr_t> args,
const EvaluateExpressionOptions &options,
- lldb::ClangUserExpressionSP &user_expression_sp);
+ lldb::UserExpressionSP &user_expression_sp);
- virtual
- ~ThreadPlanCallUserExpression ();
+ ~ThreadPlanCallUserExpression() override;
- virtual void
- GetDescription (Stream *s, lldb::DescriptionLevel level);
+ void
+ GetDescription(Stream *s, lldb::DescriptionLevel level) override;
- virtual void
- WillPop ();
+ void
+ WillPop() override;
- virtual lldb::StopInfoSP
- GetRealStopInfo();
+ lldb::StopInfoSP
+ GetRealStopInfo() override;
- virtual bool
- MischiefManaged ();
+ bool
+ MischiefManaged() override;
void
TransferExpressionOwnership ()
@@ -53,19 +52,19 @@ public:
m_manage_materialization = true;
}
- virtual lldb::ClangExpressionVariableSP
- GetExpressionVariable ()
+ lldb::ExpressionVariableSP
+ GetExpressionVariable() override
{
return m_result_var_sp;
}
protected:
private:
- lldb::ClangUserExpressionSP m_user_expression_sp; // This is currently just used to ensure the
+ lldb::UserExpressionSP m_user_expression_sp; // This is currently just used to ensure the
// User expression the initiated this ThreadPlan
// lives as long as the thread plan does.
bool m_manage_materialization = false;
- lldb::ClangExpressionVariableSP m_result_var_sp; // If we are left to manage the materialization,
+ lldb::ExpressionVariableSP m_result_var_sp; // If we are left to manage the materialization,
// then stuff the result expression variable here.
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallUserExpression);
@@ -73,4 +72,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ThreadPlanCallUserExpression_h_
+#endif // liblldb_ThreadPlanCallUserExpression_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanPython.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanPython.h
index ffcee01..ab3fbbd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanPython.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanPython.h
@@ -13,6 +13,7 @@
// C Includes
// C++ Includes
#include <string>
+
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@@ -37,45 +38,44 @@ class ThreadPlanPython : public ThreadPlan
{
public:
ThreadPlanPython (Thread &thread, const char *class_name);
- virtual ~ThreadPlanPython ();
+ ~ThreadPlanPython() override;
- virtual void
- GetDescription (Stream *s,
- lldb::DescriptionLevel level);
+ void
+ GetDescription(Stream *s,
+ lldb::DescriptionLevel level) override;
- virtual bool
- ValidatePlan (Stream *error);
+ bool
+ ValidatePlan(Stream *error) override;
- virtual bool
- ShouldStop (Event *event_ptr);
+ bool
+ ShouldStop(Event *event_ptr) override;
- virtual bool
- MischiefManaged ();
+ bool
+ MischiefManaged() override;
- virtual bool
- WillStop ();
+ bool
+ WillStop() override;
- virtual bool
- StopOthers ();
+ bool
+ StopOthers() override;
- virtual void
- DidPush ();
+ void
+ DidPush() override;
protected:
- virtual bool
- DoPlanExplainsStop (Event *event_ptr);
+ bool
+ DoPlanExplainsStop(Event *event_ptr) override;
- virtual lldb::StateType
- GetPlanRunState ();
+ lldb::StateType
+ GetPlanRunState() override;
private:
- std::string m_class_name;
- StructuredData::ObjectSP m_implementation_sp;
+ std::string m_class_name;
+ StructuredData::ObjectSP m_implementation_sp;
DISALLOW_COPY_AND_ASSIGN(ThreadPlanPython);
};
-
} // namespace lldb_private
-#endif // liblldb_ThreadPlan_Python_h_
+#endif // liblldb_ThreadPlan_Python_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanRunToAddress.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanRunToAddress.h
index d948206..a1b9746 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanRunToAddress.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanRunToAddress.h
@@ -36,37 +36,35 @@ public:
const std::vector<lldb::addr_t> &addresses,
bool stop_others);
+ ~ThreadPlanRunToAddress() override;
- virtual
- ~ThreadPlanRunToAddress ();
+ void
+ GetDescription(Stream *s, lldb::DescriptionLevel level) override;
- virtual void
- GetDescription (Stream *s, lldb::DescriptionLevel level);
+ bool
+ ValidatePlan(Stream *error) override;
- virtual bool
- ValidatePlan (Stream *error);
+ bool
+ ShouldStop(Event *event_ptr) override;
- virtual bool
- ShouldStop (Event *event_ptr);
-
- virtual bool
- StopOthers ();
+ bool
+ StopOthers() override;
- virtual void
- SetStopOthers (bool new_value);
+ void
+ SetStopOthers(bool new_value) override;
- virtual lldb::StateType
- GetPlanRunState ();
+ lldb::StateType
+ GetPlanRunState() override;
- virtual bool
- WillStop ();
+ bool
+ WillStop() override;
- virtual bool
- MischiefManaged ();
+ bool
+ MischiefManaged() override;
protected:
- virtual bool
- DoPlanExplainsStop (Event *event_ptr);
+ bool
+ DoPlanExplainsStop(Event *event_ptr) override;
void SetInitialBreakpoints();
bool AtOurAddress();
@@ -77,9 +75,8 @@ private:
std::vector<lldb::break_id_t> m_break_ids; // This is the breakpoint we are using to stop us at m_address.
DISALLOW_COPY_AND_ASSIGN (ThreadPlanRunToAddress);
-
};
} // namespace lldb_private
-#endif // liblldb_ThreadPlanRunToAddress_h_
+#endif // liblldb_ThreadPlanRunToAddress_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanShouldStopHere.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanShouldStopHere.h
index 26e4a1e..a52d9e4 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanShouldStopHere.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanShouldStopHere.h
@@ -74,9 +74,9 @@ public:
//------------------------------------------------------------------
ThreadPlanShouldStopHere (ThreadPlan *owner);
- ThreadPlanShouldStopHere (ThreadPlan *owner,
- const ThreadPlanShouldStopHereCallbacks *callbacks,
- void *baton = NULL);
+ ThreadPlanShouldStopHere(ThreadPlan *owner,
+ const ThreadPlanShouldStopHereCallbacks *callbacks,
+ void *baton = nullptr);
virtual
~ThreadPlanShouldStopHere();
@@ -139,23 +139,15 @@ protected:
// Implement this, and call it in the plan's constructor to set the default flags.
virtual void SetFlagsToDefault () = 0;
- //------------------------------------------------------------------
- // Classes that inherit from ThreadPlanShouldStopHere can see and modify these
- //------------------------------------------------------------------
ThreadPlanShouldStopHereCallbacks m_callbacks;
void * m_baton;
ThreadPlan *m_owner;
lldb_private::Flags m_flags;
private:
- //------------------------------------------------------------------
- // For ThreadPlanShouldStopHere only
- //------------------------------------------------------------------
-
DISALLOW_COPY_AND_ASSIGN (ThreadPlanShouldStopHere);
-
};
} // namespace lldb_private
-#endif // liblldb_ThreadPlanShouldStopHere_h_
+#endif // liblldb_ThreadPlanShouldStopHere_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepInRange.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepInRange.h
index 3a22e97..b31d355 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepInRange.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepInRange.h
@@ -42,14 +42,13 @@ public:
LazyBool step_in_avoids_code_without_debug_info,
LazyBool step_out_avoids_code_without_debug_info);
- virtual
- ~ThreadPlanStepInRange ();
+ ~ThreadPlanStepInRange() override;
- virtual void
- GetDescription (Stream *s, lldb::DescriptionLevel level);
+ void
+ GetDescription(Stream *s, lldb::DescriptionLevel level) override;
- virtual bool
- ShouldStop (Event *event_ptr);
+ bool
+ ShouldStop(Event *event_ptr) override;
void SetAvoidRegexp(const char *name);
@@ -62,19 +61,19 @@ public:
SetDefaultFlagValue (uint32_t new_value);
bool
- IsVirtualStep();
+ IsVirtualStep() override;
protected:
static bool
DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton);
- virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+ bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
- virtual bool
- DoPlanExplainsStop (Event *event_ptr);
+ bool
+ DoPlanExplainsStop(Event *event_ptr) override;
- virtual void
- SetFlagsToDefault ()
+ void
+ SetFlagsToDefault() override
{
GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values);
}
@@ -119,9 +118,8 @@ private:
bool m_virtual_step; // true if we've just done a "virtual step", i.e. just moved the inline stack depth.
ConstString m_step_into_target;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepInRange);
-
};
} // namespace lldb_private
-#endif // liblldb_ThreadPlanStepInRange_h_
+#endif // liblldb_ThreadPlanStepInRange_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepInstruction.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepInstruction.h
index 86069ff..da83eca 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepInstruction.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepInstruction.h
@@ -23,19 +23,19 @@ namespace lldb_private {
class ThreadPlanStepInstruction : public ThreadPlan
{
public:
- virtual ~ThreadPlanStepInstruction ();
+ ~ThreadPlanStepInstruction() override;
- virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
- virtual bool ValidatePlan (Stream *error);
- virtual bool ShouldStop (Event *event_ptr);
- virtual bool StopOthers ();
- virtual lldb::StateType GetPlanRunState ();
- virtual bool WillStop ();
- virtual bool MischiefManaged ();
- virtual bool IsPlanStale ();
+ void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
+ bool ValidatePlan(Stream *error) override;
+ bool ShouldStop(Event *event_ptr) override;
+ bool StopOthers() override;
+ lldb::StateType GetPlanRunState() override;
+ bool WillStop() override;
+ bool MischiefManaged() override;
+ bool IsPlanStale() override;
protected:
- virtual bool DoPlanExplainsStop (Event *event_ptr);
+ bool DoPlanExplainsStop(Event *event_ptr) override;
ThreadPlanStepInstruction (Thread &thread,
bool step_over,
@@ -57,10 +57,8 @@ private:
StackID m_parent_frame_id;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepInstruction);
-
};
-
} // namespace lldb_private
-#endif // liblldb_ThreadPlanStepInstruction_h_
+#endif // liblldb_ThreadPlanStepInstruction_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOut.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOut.h
index 8c140dc..ccf829f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOut.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOut.h
@@ -31,34 +31,35 @@ public:
Vote stop_vote,
Vote run_vote,
uint32_t frame_idx,
- LazyBool step_out_avoids_code_without_debug_info);
+ LazyBool step_out_avoids_code_without_debug_info,
+ bool continue_to_next_branch = false);
- virtual ~ThreadPlanStepOut ();
+ ~ThreadPlanStepOut() override;
- virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
- virtual bool ValidatePlan (Stream *error);
- virtual bool ShouldStop (Event *event_ptr);
- virtual bool StopOthers ();
- virtual lldb::StateType GetPlanRunState ();
- virtual bool WillStop ();
- virtual bool MischiefManaged ();
- virtual void DidPush();
- virtual bool IsPlanStale();
+ void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
+ bool ValidatePlan(Stream *error) override;
+ bool ShouldStop(Event *event_ptr) override;
+ bool StopOthers() override;
+ lldb::StateType GetPlanRunState() override;
+ bool WillStop() override;
+ bool MischiefManaged() override;
+ void DidPush() override;
+ bool IsPlanStale() override;
- virtual lldb::ValueObjectSP GetReturnValueObject()
+ lldb::ValueObjectSP GetReturnValueObject() override
{
return m_return_valobj_sp;
}
protected:
- virtual void
- SetFlagsToDefault ()
+ void
+ SetFlagsToDefault() override
{
GetFlags().Set(ThreadPlanStepOut::s_default_flag_values);
}
- virtual bool DoPlanExplainsStop (Event *event_ptr);
- virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+ bool DoPlanExplainsStop (Event *event_ptr) override;
+ bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
bool QueueInlinedStepPlan (bool queue_now);
private:
@@ -95,9 +96,8 @@ private:
CalculateReturnValue();
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOut);
-
};
} // namespace lldb_private
-#endif // liblldb_ThreadPlanStepOut_h_
+#endif // liblldb_ThreadPlanStepOut_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
index a480605..944f0e0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
@@ -22,29 +22,31 @@ namespace lldb_private {
class ThreadPlanStepOverBreakpoint : public ThreadPlan
{
public:
- virtual ~ThreadPlanStepOverBreakpoint ();
-
ThreadPlanStepOverBreakpoint (Thread &thread);
- virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
- virtual bool ValidatePlan (Stream *error);
- virtual bool ShouldStop (Event *event_ptr);
- virtual bool StopOthers ();
- virtual lldb::StateType GetPlanRunState ();
- virtual bool WillStop ();
- virtual bool MischiefManaged ();
- virtual void ThreadDestroyed ();
- void SetAutoContinue (bool do_it);
- virtual bool ShouldAutoContinue(Event *event_ptr);
- virtual bool IsPlanStale();
+
+ ~ThreadPlanStepOverBreakpoint() override;
+
+ void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
+ bool ValidatePlan(Stream *error) override;
+ bool ShouldStop(Event *event_ptr) override;
+ bool StopOthers() override;
+ lldb::StateType GetPlanRunState() override;
+ bool WillStop() override;
+ bool MischiefManaged() override;
+ void ThreadDestroyed() override;
+ void SetAutoContinue(bool do_it);
+ bool ShouldAutoContinue(Event *event_ptr) override;
+ bool IsPlanStale() override;
lldb::addr_t
GetBreakpointLoadAddress() const
{
return m_breakpoint_addr;
}
+
protected:
- virtual bool DoPlanExplainsStop (Event *event_ptr);
- virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+ bool DoPlanExplainsStop(Event *event_ptr) override;
+ bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
void ReenableBreakpointSite ();
private:
@@ -55,9 +57,8 @@ private:
bool m_reenabled_breakpoint_site;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverBreakpoint);
-
};
} // namespace lldb_private
-#endif // liblldb_ThreadPlanStepOverBreakpoint_h_
+#endif // liblldb_ThreadPlanStepOverBreakpoint_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverRange.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverRange.h
index d47c6c9..7defaef 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverRange.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepOverRange.h
@@ -25,32 +25,28 @@ class ThreadPlanStepOverRange : public ThreadPlanStepRange,
ThreadPlanShouldStopHere
{
public:
-
ThreadPlanStepOverRange (Thread &thread,
const AddressRange &range,
const SymbolContext &addr_context,
lldb::RunMode stop_others,
LazyBool step_out_avoids_no_debug);
- virtual ~ThreadPlanStepOverRange ();
+ ~ThreadPlanStepOverRange() override;
- virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
- virtual bool ShouldStop (Event *event_ptr);
+ void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
+ bool ShouldStop(Event *event_ptr) override;
protected:
- virtual bool DoPlanExplainsStop (Event *event_ptr);
- virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+ bool DoPlanExplainsStop(Event *event_ptr) override;
+ bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
- virtual void
- SetFlagsToDefault ()
+ void
+ SetFlagsToDefault() override
{
GetFlags().Set(ThreadPlanStepOverRange::s_default_flag_values);
}
-
-
-
-private:
+private:
static uint32_t s_default_flag_values;
void SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info);
@@ -59,9 +55,8 @@ private:
bool m_first_resume;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverRange);
-
};
} // namespace lldb_private
-#endif // liblldb_ThreadPlanStepOverRange_h_
+#endif // liblldb_ThreadPlanStepOverRange_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepRange.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepRange.h
index 43c55c2..8f6685f 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepRange.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepRange.h
@@ -33,24 +33,22 @@ public:
lldb::RunMode stop_others,
bool given_ranges_only = false);
- virtual ~ThreadPlanStepRange ();
-
- virtual void GetDescription (Stream *s, lldb::DescriptionLevel level) = 0;
- virtual bool ValidatePlan (Stream *error);
- virtual bool ShouldStop (Event *event_ptr) = 0;
- virtual Vote ShouldReportStop (Event *event_ptr);
- virtual bool StopOthers ();
- virtual lldb::StateType GetPlanRunState ();
- virtual bool WillStop ();
- virtual bool MischiefManaged ();
- virtual void DidPush ();
- virtual bool IsPlanStale ();
+ ~ThreadPlanStepRange() override;
+ void GetDescription(Stream *s, lldb::DescriptionLevel level) override = 0;
+ bool ValidatePlan(Stream *error) override;
+ bool ShouldStop(Event *event_ptr) override = 0;
+ Vote ShouldReportStop(Event *event_ptr) override;
+ bool StopOthers() override;
+ lldb::StateType GetPlanRunState() override;
+ bool WillStop() override;
+ bool MischiefManaged() override;
+ void DidPush() override;
+ bool IsPlanStale() override;
void AddRange(const AddressRange &new_range);
protected:
-
bool InRange();
lldb::FrameComparison CompareCurrentFrameToStartFrame();
bool InSymbol();
@@ -88,10 +86,10 @@ protected:
private:
std::vector<lldb::DisassemblerSP> m_instruction_ranges;
- DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepRange);
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepRange);
};
} // namespace lldb_private
-#endif // liblldb_ThreadPlanStepRange_h_
+#endif // liblldb_ThreadPlanStepRange_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepThrough.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepThrough.h
index 1697966..43af37c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepThrough.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepThrough.h
@@ -22,20 +22,20 @@ namespace lldb_private {
class ThreadPlanStepThrough : public ThreadPlan
{
public:
- virtual ~ThreadPlanStepThrough ();
+ ~ThreadPlanStepThrough() override;
- virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
- virtual bool ValidatePlan (Stream *error);
- virtual bool ShouldStop (Event *event_ptr);
- virtual bool StopOthers ();
- virtual lldb::StateType GetPlanRunState ();
- virtual bool WillStop ();
- virtual bool MischiefManaged ();
- virtual void DidPush();
+ void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
+ bool ValidatePlan(Stream *error) override;
+ bool ShouldStop(Event *event_ptr) override;
+ bool StopOthers() override;
+ lldb::StateType GetPlanRunState() override;
+ bool WillStop() override;
+ bool MischiefManaged() override;
+ void DidPush() override;
protected:
- virtual bool DoPlanExplainsStop (Event *event_ptr);
- virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
+ bool DoPlanExplainsStop(Event *event_ptr) override;
+ bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
ThreadPlanStepThrough (Thread &thread,
StackID &return_stack_id,
@@ -49,6 +49,7 @@ protected:
private:
friend lldb::ThreadPlanSP
+
Thread::QueueThreadPlanForStepThrough (StackID &return_stack_id,
bool abort_other_plans,
bool stop_others);
@@ -63,9 +64,8 @@ private:
bool m_stop_others;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepThrough);
-
};
} // namespace lldb_private
-#endif // liblldb_ThreadPlanStepThrough_h_
+#endif // liblldb_ThreadPlanStepThrough_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepUntil.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepUntil.h
index 5aa3876..3c1bd8c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepUntil.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanStepUntil.h
@@ -19,33 +19,32 @@
namespace lldb_private {
-
class ThreadPlanStepUntil : public ThreadPlan
{
public:
- virtual ~ThreadPlanStepUntil ();
+ ~ThreadPlanStepUntil() override;
- virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
- virtual bool ValidatePlan (Stream *error);
- virtual bool ShouldStop (Event *event_ptr);
- virtual bool StopOthers ();
- virtual lldb::StateType GetPlanRunState ();
- virtual bool WillStop ();
- virtual bool MischiefManaged ();
+ void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
+ bool ValidatePlan(Stream *error) override;
+ bool ShouldStop(Event *event_ptr) override;
+ bool StopOthers() override;
+ lldb::StateType GetPlanRunState() override;
+ bool WillStop() override;
+ bool MischiefManaged() override;
protected:
- virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan);
- virtual bool DoPlanExplainsStop (Event *event_ptr);
+ bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
+ bool DoPlanExplainsStop(Event *event_ptr) override;
ThreadPlanStepUntil (Thread &thread,
lldb::addr_t *address_list,
size_t num_addresses,
bool stop_others,
uint32_t frame_idx = 0);
- void AnalyzeStop(void);
-private:
+ void AnalyzeStop();
+private:
StackID m_stack_id;
lldb::addr_t m_step_from_insn;
lldb::break_id_t m_return_bp_id;
@@ -72,9 +71,8 @@ private:
// from step in.
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepUntil);
-
};
} // namespace lldb_private
-#endif // liblldb_ThreadPlanStepUntil_h_
+#endif // liblldb_ThreadPlanStepUntil_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanTracer.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanTracer.h
index 4eb0c78..6d06413 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanTracer.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadPlanTracer.h
@@ -26,7 +26,6 @@ class ThreadPlanTracer
friend class ThreadPlan;
public:
-
typedef enum ThreadPlanTracerStyle
{
eLocation = 0,
@@ -34,21 +33,18 @@ public:
eCheckFrames,
ePython
} ThreadPlanTracerStyle;
+
ThreadPlanTracer (Thread &thread, lldb::StreamSP &stream_sp);
ThreadPlanTracer (Thread &thread);
- virtual ~ThreadPlanTracer()
- {
- }
+ virtual ~ThreadPlanTracer() = default;
virtual void TracingStarted ()
{
-
}
virtual void TracingEnded ()
{
-
}
bool
@@ -90,8 +86,6 @@ protected:
Stream *
GetLogStream ();
-
-
virtual void Log();
private:
@@ -108,12 +102,13 @@ class ThreadPlanAssemblyTracer : public ThreadPlanTracer
public:
ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp);
ThreadPlanAssemblyTracer (Thread &thread);
- virtual ~ThreadPlanAssemblyTracer ();
- virtual void TracingStarted ();
- virtual void TracingEnded ();
- virtual void Log();
+ ~ThreadPlanAssemblyTracer() override;
+
+ void TracingStarted() override;
+ void TracingEnded() override;
+ void Log() override;
+
private:
-
Disassembler *
GetDisassembler ();
@@ -128,4 +123,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ThreadPlanTracer_h_
+#endif // liblldb_ThreadPlanTracer_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadSpec.h b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadSpec.h
index e0d3093..95f509a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/ThreadSpec.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/ThreadSpec.h
@@ -1,4 +1,4 @@
-//===-- ThreadSpec.h ------------------------------------------------*- C++ -*-===//
+//===-- ThreadSpec.h --------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,9 +10,12 @@
#ifndef liblldb_ThreadSpec_h_
#define liblldb_ThreadSpec_h_
-#include <map>
+// C Includes
+// C++ Includes
#include <string>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
namespace lldb_private {
@@ -110,7 +113,7 @@ public:
{
if (m_name.empty())
return true;
- else if (name == NULL)
+ else if (name == nullptr)
return false;
else
return m_name == name;
@@ -124,7 +127,7 @@ public:
{
if (m_queue_name.empty())
return true;
- else if (queue_name == NULL)
+ else if (queue_name == nullptr)
return false;
else
return m_queue_name == queue_name;
@@ -142,7 +145,6 @@ public:
void
GetDescription (Stream *s, lldb::DescriptionLevel level) const;
-protected:
private:
uint32_t m_index;
lldb::tid_t m_tid;
@@ -152,4 +154,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_ThreadSpec_h_
+#endif // liblldb_ThreadSpec_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/UnixSignals.h b/contrib/llvm/tools/lldb/include/lldb/Target/UnixSignals.h
index 76955de..7a02f557 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/UnixSignals.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/UnixSignals.h
@@ -98,6 +98,9 @@ public:
int32_t
GetSignalAtIndex(int32_t index) const;
+ ConstString
+ GetShortName(ConstString name) const;
+
// We assume that the elements of this object are constant once it is constructed,
// since a process should never need to add or remove symbols as it runs. So don't
// call these functions anywhere but the constructor of your subclass of UnixSignals or in
@@ -106,11 +109,11 @@ public:
void
AddSignal (int signo,
const char *name,
- const char *short_name,
bool default_suppress,
bool default_stop,
bool default_notify,
- const char *description);
+ const char *description,
+ const char *alias = nullptr);
void
RemoveSignal (int signo);
@@ -123,18 +126,18 @@ protected:
struct Signal
{
ConstString m_name;
- ConstString m_short_name;
+ ConstString m_alias;
std::string m_description;
bool m_suppress:1,
m_stop:1,
m_notify:1;
Signal (const char *name,
- const char *short_name,
bool default_suppress,
bool default_stop,
bool default_notify,
- const char *description);
+ const char *description,
+ const char *alias);
~Signal () {}
};
diff --git a/contrib/llvm/tools/lldb/include/lldb/Target/UnwindAssembly.h b/contrib/llvm/tools/lldb/include/lldb/Target/UnwindAssembly.h
index 963949c..6f53e7e 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Target/UnwindAssembly.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Target/UnwindAssembly.h
@@ -24,8 +24,7 @@ public:
static lldb::UnwindAssemblySP
FindPlugin (const ArchSpec &arch);
- virtual
- ~UnwindAssembly();
+ ~UnwindAssembly() override;
virtual bool
GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func,
@@ -59,6 +58,4 @@ private:
} // namespace lldb_private
-#endif //utility_UnwindAssembly_h_
-
-
+#endif // utility_UnwindAssembly_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/AnsiTerminal.h b/contrib/llvm/tools/lldb/include/lldb/Utility/AnsiTerminal.h
index 9a5117a..a43dd1b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/AnsiTerminal.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/AnsiTerminal.h
@@ -41,8 +41,13 @@
#define ANSI_CTRL_CONCEAL 8
#define ANSI_CTRL_CROSSED_OUT 9
-#define ANSI_ESC_START "\033["
-#define ANSI_ESC_END "m"
+#define ANSI_ESC_START "\033["
+#define ANSI_ESC_END "m"
+
+#define ANSI_STR(s) #s
+#define ANSI_DEF_STR(s) ANSI_STR(s)
+
+#define ANSI_ESCAPE1(s) ANSI_ESC_START ANSI_DEF_STR(s) ANSI_ESC_END
#define ANSI_1_CTRL(ctrl1) "\033["##ctrl1 ANSI_ESC_END
#define ANSI_2_CTRL(ctrl1,ctrl2) "\033["##ctrl1";"##ctrl2 ANSI_ESC_END
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Either.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Either.h
new file mode 100644
index 0000000..ae64736
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Either.h
@@ -0,0 +1,154 @@
+//===-- Either.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Either_h_
+#define liblldb_Either_h_
+
+#include "llvm/ADT/Optional.h"
+
+#include <functional>
+
+namespace lldb_utility {
+ template <typename T1, typename T2>
+ class Either
+ {
+ private:
+ enum class Selected
+ {
+ One, Two
+ };
+
+ Selected m_selected;
+ union
+ {
+ T1 m_t1;
+ T2 m_t2;
+ };
+
+ public:
+ Either (const T1& t1)
+ {
+ m_t1 = t1;
+ m_selected = Selected::One;
+ }
+
+ Either (const T2& t2)
+ {
+ m_t2 = t2;
+ m_selected = Selected::Two;
+ }
+
+ Either (const Either<T1,T2>& rhs)
+ {
+ switch (rhs.m_selected)
+ {
+ case Selected::One:
+ m_t1 = rhs.GetAs<T1>().getValue();
+ m_selected = Selected::One;
+ break;
+ case Selected::Two:
+ m_t2 = rhs.GetAs<T2>().getValue();
+ m_selected = Selected::Two;
+ break;
+ }
+ }
+
+ template <class X, typename std::enable_if<std::is_same<T1,X>::value>::type * = nullptr>
+ llvm::Optional<T1>
+ GetAs() const
+ {
+ switch (m_selected)
+ {
+ case Selected::One:
+ return m_t1;
+ default:
+ return llvm::Optional<T1>();
+ }
+ }
+
+ template <class X, typename std::enable_if<std::is_same<T2,X>::value>::type * = nullptr>
+ llvm::Optional<T2>
+ GetAs() const
+ {
+ switch (m_selected)
+ {
+ case Selected::Two:
+ return m_t2;
+ default:
+ return llvm::Optional<T2>();
+ }
+ }
+
+ template <class ResultType>
+ ResultType
+ Apply (std::function<ResultType(T1)> if_T1,
+ std::function<ResultType(T2)> if_T2) const
+ {
+ switch (m_selected)
+ {
+ case Selected::One:
+ return if_T1(m_t1);
+ case Selected::Two:
+ return if_T2(m_t2);
+ }
+ }
+
+ bool
+ operator == (const Either<T1,T2>& rhs)
+ {
+ return (GetAs<T1>() == rhs.GetAs<T1>()) && (GetAs<T2>() == rhs.GetAs<T2>());
+ }
+
+ explicit
+ operator bool ()
+ {
+ switch (m_selected)
+ {
+ case Selected::One:
+ return (bool)m_t1;
+ case Selected::Two:
+ return (bool)m_t2;
+ }
+ }
+
+ Either<T1,T2>&
+ operator = (const Either<T1,T2>& rhs)
+ {
+ switch (rhs.m_selected)
+ {
+ case Selected::One:
+ m_t1 = rhs.GetAs<T1>().getValue();
+ m_selected = Selected::One;
+ break;
+ case Selected::Two:
+ m_t2 = rhs.GetAs<T2>().getValue();
+ m_selected = Selected::Two;
+ break;
+ }
+ return *this;
+ }
+
+ ~Either ()
+ {
+ switch (m_selected)
+ {
+ case Selected::One:
+ m_t1.T1::~T1();
+ break;
+ case Selected::Two:
+ m_t2.T2::~T2();
+ break;
+ }
+ }
+ };
+
+} // namespace lldb_utility
+
+#endif // #ifndef liblldb_Either_h_
+
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Iterable.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Iterable.h
index 17c8cf4..2317225 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/Iterable.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Iterable.h
@@ -10,6 +10,12 @@
#ifndef liblldb_Iterable_h_
#define liblldb_Iterable_h_
+// C Includes
+// C++ Includes
+#include <utility>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/Host/Mutex.h"
namespace lldb_private
@@ -34,9 +40,7 @@ template <typename C, typename E, E (*A)(typename C::const_iterator &)> class Ad
{
public:
typedef typename C::const_iterator BackingIterator;
-private:
- BackingIterator m_iter;
-public:
+
// Wrapping constructor
AdaptedConstIterator (BackingIterator backing_iterator) :
m_iter(backing_iterator)
@@ -63,7 +67,7 @@ public:
}
// Destructible
- ~AdaptedConstIterator () { }
+ ~AdaptedConstIterator() = default;
// Comparable
bool operator== (const AdaptedConstIterator &rhs)
@@ -160,6 +164,9 @@ public:
template <typename C1, typename E1, E1 (*A1)(typename C1::const_iterator &)>
friend void swap(AdaptedConstIterator<C1, E1, A1> &, AdaptedConstIterator<C1, E1, A1> &);
+
+private:
+ BackingIterator m_iter;
};
template <typename C, typename E, E (*A)(typename C::const_iterator &)>
@@ -203,8 +210,6 @@ public:
template <typename C, typename E, E (*A)(typename C::const_iterator &)> class LockingAdaptedIterable : public AdaptedIterable<C, E, A>
{
-private:
- Mutex *m_mutex = nullptr;
public:
LockingAdaptedIterable (C &container, Mutex &mutex) :
AdaptedIterable<C,E,A>(container),
@@ -217,7 +222,7 @@ public:
AdaptedIterable<C,E,A>(rhs),
m_mutex(rhs.m_mutex)
{
- rhs.m_mutex = NULL;
+ rhs.m_mutex = nullptr;
}
~LockingAdaptedIterable ()
@@ -227,9 +232,11 @@ public:
}
private:
+ Mutex *m_mutex = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(LockingAdaptedIterable);
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_Iterable_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/JSON.h b/contrib/llvm/tools/lldb/include/lldb/Utility/JSON.h
index da5e26d..e61c5ee 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/JSON.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/JSON.h
@@ -71,8 +71,8 @@ namespace lldb_private {
JSONString&
operator = (const JSONString& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONString> SP;
@@ -84,8 +84,7 @@ namespace lldb_private {
return V->GetKind() == JSONValue::Kind::String;
}
- virtual
- ~JSONString () = default;
+ ~JSONString() override = default;
private:
@@ -98,43 +97,79 @@ namespace lldb_private {
class JSONNumber : public JSONValue
{
public:
- JSONNumber ();
- explicit JSONNumber (uint64_t i);
- explicit JSONNumber (double d);
+ typedef std::shared_ptr<JSONNumber> SP;
+
+ // We cretae a constructor for all integer and floating point type with using templates and
+ // SFINAE to avoid having ambiguous overloads because of the implicit type promotion. If we
+ // would have constructors only with int64_t, uint64_t and double types then constructing a
+ // JSONNumber from an int32_t (or any other similar type) would fail to compile.
+
+ template <typename T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_unsigned<T>::value>::type* = nullptr>
+ explicit JSONNumber (T u) :
+ JSONValue(JSONValue::Kind::Number),
+ m_data_type(DataType::Unsigned)
+ {
+ m_data.m_unsigned = u;
+ }
+
+ template <typename T,
+ typename std::enable_if<std::is_integral<T>::value &&
+ std::is_signed<T>::value>::type* = nullptr>
+ explicit JSONNumber (T s) :
+ JSONValue(JSONValue::Kind::Number),
+ m_data_type(DataType::Signed)
+ {
+ m_data.m_signed = s;
+ }
+
+ template <typename T,
+ typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
+ explicit JSONNumber (T d) :
+ JSONValue(JSONValue::Kind::Number),
+ m_data_type(DataType::Double)
+ {
+ m_data.m_double = d;
+ }
+
+ ~JSONNumber() override = default;
JSONNumber (const JSONNumber& s) = delete;
JSONNumber&
operator = (const JSONNumber& s) = delete;
- virtual void
- Write (Stream& s);
-
- typedef std::shared_ptr<JSONNumber> SP;
+ void
+ Write(Stream& s) override;
uint64_t
- GetData () { return m_data; }
+ GetAsUnsigned() const;
+
+ int64_t
+ GetAsSigned() const;
double
- GetAsDouble()
- {
- if (m_is_integer)
- return (double)m_data;
- else
- return m_double;
- }
+ GetAsDouble() const;
static bool classof(const JSONValue *V)
{
return V->GetKind() == JSONValue::Kind::Number;
}
-
- virtual
- ~JSONNumber () = default;
-
+
private:
- bool m_is_integer;
- uint64_t m_data;
- double m_double;
+ enum class DataType : uint8_t
+ {
+ Unsigned,
+ Signed,
+ Double
+ } m_data_type;
+
+ union
+ {
+ uint64_t m_unsigned;
+ int64_t m_signed;
+ double m_double;
+ } m_data;
};
class JSONTrue : public JSONValue
@@ -146,8 +181,8 @@ namespace lldb_private {
JSONTrue&
operator = (const JSONTrue& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONTrue> SP;
@@ -156,8 +191,7 @@ namespace lldb_private {
return V->GetKind() == JSONValue::Kind::True;
}
- virtual
- ~JSONTrue () = default;
+ ~JSONTrue() override = default;
};
class JSONFalse : public JSONValue
@@ -169,8 +203,8 @@ namespace lldb_private {
JSONFalse&
operator = (const JSONFalse& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONFalse> SP;
@@ -179,8 +213,7 @@ namespace lldb_private {
return V->GetKind() == JSONValue::Kind::False;
}
- virtual
- ~JSONFalse () = default;
+ ~JSONFalse() override = default;
};
class JSONNull : public JSONValue
@@ -192,8 +225,8 @@ namespace lldb_private {
JSONNull&
operator = (const JSONNull& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONNull> SP;
@@ -202,8 +235,7 @@ namespace lldb_private {
return V->GetKind() == JSONValue::Kind::Null;
}
- virtual
- ~JSONNull () = default;
+ ~JSONNull() override = default;
};
class JSONObject : public JSONValue
@@ -215,8 +247,8 @@ namespace lldb_private {
JSONObject&
operator = (const JSONObject& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONObject> SP;
@@ -232,8 +264,7 @@ namespace lldb_private {
JSONValue::SP
GetObject (const std::string& key);
- virtual
- ~JSONObject () = default;
+ ~JSONObject() override = default;
private:
typedef std::map<std::string, JSONValue::SP> Map;
@@ -250,8 +281,8 @@ namespace lldb_private {
JSONArray&
operator = (const JSONArray& s) = delete;
- virtual void
- Write (Stream& s);
+ void
+ Write(Stream& s) override;
typedef std::shared_ptr<JSONArray> SP;
@@ -280,13 +311,11 @@ namespace lldb_private {
Size
GetNumElements ();
- virtual
- ~JSONArray () = default;
+ ~JSONArray() override = default;
Vector m_elements;
};
-
class JSONParser : public StringExtractor
{
public:
@@ -327,6 +356,6 @@ namespace lldb_private {
JSONValue::SP
ParseJSONArray ();
};
-}
+} // namespace lldb_private
-#endif // utility_ProcessStructReader_h_
+#endif // utility_JSON_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/ProcessStructReader.h b/contrib/llvm/tools/lldb/include/lldb/Utility/ProcessStructReader.h
index d053b70..80f90fe 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/ProcessStructReader.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/ProcessStructReader.h
@@ -16,7 +16,7 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Error.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Process.h"
#include <initializer_list>
@@ -29,7 +29,7 @@ namespace lldb_private {
protected:
struct FieldImpl
{
- ClangASTType type;
+ CompilerType type;
size_t offset;
size_t size;
};
@@ -40,7 +40,7 @@ namespace lldb_private {
size_t m_addr_byte_size;
public:
- ProcessStructReader (Process *process, lldb::addr_t base_addr, ClangASTType struct_type)
+ ProcessStructReader (Process *process, lldb::addr_t base_addr, CompilerType struct_type)
{
if (!process)
return;
@@ -55,7 +55,7 @@ namespace lldb_private {
uint64_t bit_offset;
uint32_t bitfield_bit_size;
bool is_bitfield;
- ClangASTType field_type = struct_type.GetFieldAtIndex(idx,name,&bit_offset,&bitfield_bit_size,&is_bitfield);
+ CompilerType field_type = struct_type.GetFieldAtIndex(idx,name,&bit_offset,&bitfield_bit_size,&is_bitfield);
// no support for bitfields in here (yet)
if (is_bitfield)
return;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/PseudoTerminal.h b/contrib/llvm/tools/lldb/include/lldb/Utility/PseudoTerminal.h
index 595b2fc..d732534 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/PseudoTerminal.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/PseudoTerminal.h
@@ -260,7 +260,7 @@ private:
};
-} // namespace lldb
+} // namespace lldb_utility
#endif // #if defined(__cplusplus)
#endif // #ifndef liblldb_PseudoTerminal_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/PythonPointer.h b/contrib/llvm/tools/lldb/include/lldb/Utility/PythonPointer.h
deleted file mode 100644
index fe90670..0000000
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/PythonPointer.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//===---------------------PythonPointer.h ------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef utility_PythonPointer_h_
-#define utility_PythonPointer_h_
-
-#include <algorithm>
-
-#include "lldb/lldb-python.h"
-
-namespace lldb_private {
-
-template<class T>
-class PythonPointer
-{
-public:
- typedef PyObject* element_type;
-private:
- element_type* ptr_;
- bool my_ref;
-public:
-
- PythonPointer(element_type p, bool steal_ref = false) :
- ptr_(p),
- my_ref(!steal_ref)
- {
- if (my_ref)
- Py_INCREF(ptr_);
- }
-
- PythonPointer(const PythonPointer& r, bool steal_ref = false) :
- ptr_(r.ptr_),
- my_ref(!steal_ref)
- {
- if (my_ref)
- Py_INCREF(ptr_);
- }
-
- ~PythonPointer()
- {
- if (my_ref)
- Py_XDECREF(ptr_);
- }
-
- PythonPointer
- StealReference()
- {
- return PythonPointer(ptr_,true);
- }
-
- PythonPointer
- DuplicateReference()
- {
- return PythonPointer(ptr_, false);
- }
-
- element_type get() const {return ptr_;}
-
- bool IsNull() { return ptr_ == NULL; }
- bool IsNone() { return ptr_ == Py_None; }
-
- operator PyObject* () { return ptr_; }
-};
-
-} // namespace lldb
-
-#endif // utility_PythonPointer_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/SharedCluster.h b/contrib/llvm/tools/lldb/include/lldb/Utility/SharedCluster.h
index 3a34d8d..2c03c40 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/SharedCluster.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/SharedCluster.h
@@ -27,14 +27,15 @@ namespace imp
shared_ptr_refcount() : shared_count (0) {}
- virtual ~shared_ptr_refcount ()
+ ~shared_ptr_refcount() override
{
}
- virtual void on_zero_shared ()
+ void on_zero_shared() override
{
manager->DecrementRefCount();
}
+
private:
T *manager;
};
@@ -100,4 +101,5 @@ private:
};
} // namespace lldb_private
+
#endif // utility_SharedCluster_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h b/contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h
index 5c77dad..29538bc 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/SharingPtr.h
@@ -10,6 +10,8 @@
#ifndef utility_SharingPtr_h_
#define utility_SharingPtr_h_
+// C Includes
+// C++ Includes
#include <algorithm>
#include <memory>
@@ -22,6 +24,9 @@
#include <atomic>
#endif
+// Other libraries and framework includes
+// Project includes
+
//#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT
#if defined (ENABLE_SP_LOGGING)
@@ -38,6 +43,13 @@ class shared_count
shared_count(const shared_count&);
shared_count& operator=(const shared_count&);
+public:
+ explicit shared_count(long refs = 0)
+ : shared_owners_(refs) {}
+
+ void add_shared();
+ void release_shared();
+ long use_count() const {return shared_owners_ + 1;}
protected:
#ifdef _MSC_VER
long shared_owners_;
@@ -45,16 +57,9 @@ protected:
std::atomic<long> shared_owners_;
#endif
virtual ~shared_count();
+
private:
virtual void on_zero_shared() = 0;
-
-public:
- explicit shared_count(long refs = 0)
- : shared_owners_(refs) {}
-
- void add_shared();
- void release_shared();
- long use_count() const {return shared_owners_ + 1;}
};
template <class T>
@@ -67,7 +72,7 @@ public:
: data_(p) {}
private:
- virtual void on_zero_shared();
+ void on_zero_shared() override;
// Outlaw copy constructor and assignment operator to keep effective C++
// warnings down to a minimum
@@ -113,7 +118,8 @@ public:
: data_(a0, a1, a2, a3, a4) {}
private:
- virtual void on_zero_shared();
+ void on_zero_shared() override;
+
public:
T* get() {return &data_;}
};
@@ -124,18 +130,20 @@ shared_ptr_emplace<T>::on_zero_shared()
{
}
-} // namespace
+} // namespace imp
template<class T>
class SharingPtr
{
public:
typedef T element_type;
+
private:
element_type* ptr_;
imp::shared_count* cntrl_;
struct nat {int for_bool_;};
+
public:
SharingPtr();
SharingPtr(std::nullptr_t);
@@ -161,7 +169,7 @@ public:
element_type* operator->() const {return ptr_;}
long use_count() const {return cntrl_ ? cntrl_->use_count() : 0;}
bool unique() const {return use_count() == 1;}
- bool empty() const {return cntrl_ == 0;}
+ bool empty() const {return cntrl_ == nullptr;}
operator nat*() const {return (nat*)get();}
static SharingPtr<T> make_shared();
@@ -182,30 +190,29 @@ public:
static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&, A4&);
private:
-
template <class U> friend class SharingPtr;
};
template<class T>
inline
SharingPtr<T>::SharingPtr()
- : ptr_(0),
- cntrl_(0)
+ : ptr_(nullptr),
+ cntrl_(nullptr)
{
}
template<class T>
inline
SharingPtr<T>::SharingPtr(std::nullptr_t)
-: ptr_(0),
-cntrl_(0)
+: ptr_(nullptr),
+cntrl_(nullptr)
{
}
template<class T>
template<class Y>
SharingPtr<T>::SharingPtr(Y* p)
- : ptr_(p), cntrl_(0)
+ : ptr_(p), cntrl_(nullptr)
{
std::unique_ptr<Y> hold(p);
typedef imp::shared_ptr_pointer<Y*> _CntrlBlk;
@@ -431,7 +438,6 @@ make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4);
}
-
template<class T, class U>
inline
bool
@@ -490,12 +496,8 @@ public:
// action: false means increment just happened
// true means decrement is about to happen
-private:
- Callback cb_;
- void* baton_;
+ LoggingSharingPtr() : cb_(0), baton_(nullptr) {}
-public:
- LoggingSharingPtr() : cb_(0), baton_(0) {}
LoggingSharingPtr(Callback cb, void* baton)
: cb_(cb), baton_(baton)
{
@@ -505,7 +507,7 @@ public:
template <class Y>
LoggingSharingPtr(Y* p)
- : base(p), cb_(0), baton_(0) {}
+ : base(p), cb_(0), baton_(nullptr) {}
template <class Y>
LoggingSharingPtr(Y* p, Callback cb, void* baton)
@@ -568,9 +570,12 @@ public:
cb_ = 0;
baton_ = 0;
}
+
+private:
+ Callback cb_;
+ void* baton_;
};
-
-
+
template <class T>
class IntrusiveSharingPtr;
@@ -637,14 +642,10 @@ public:
imp::shared_count(-1)
{
}
-
- virtual
- ~ReferenceCountedBaseVirtual ()
- {
- }
-
- virtual void on_zero_shared ();
-
+
+ ~ReferenceCountedBaseVirtual() override = default;
+
+ void on_zero_shared() override;
};
template <class T>
@@ -716,7 +717,7 @@ public:
// those would be builds for release. But for debug and release builds
// that are for development, we NULL out the pointers to catch potential
// issues.
- ptr_ = NULL;
+ ptr_ = nullptr;
#endif // #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE)
}
@@ -754,7 +755,7 @@ public:
}
void
- reset(T* ptr = NULL)
+ reset(T* ptr = nullptr)
{
IntrusiveSharingPtr(ptr).swap(*this);
}
@@ -793,7 +794,7 @@ private:
if (ptr_)
{
#if defined (ENABLE_SP_LOGGING)
- track_sp (this, NULL, ptr_->use_count() - 1);
+ track_sp (this, nullptr, ptr_->use_count() - 1);
#endif
ptr_->release_shared();
}
@@ -838,4 +839,4 @@ inline bool operator!= (T* lhs, const IntrusiveSharingPtr<U>& rhs)
} // namespace lldb_private
-#endif // utility_SharingPtr_h_
+#endif // utility_SharingPtr_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractor.h b/contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractor.h
index 0f2dbb1..db1b83b 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractor.h
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/StringExtractor.h
@@ -115,6 +115,9 @@ public:
GetHexU8 (uint8_t fail_value = 0, bool set_eof_on_fail = true);
bool
+ GetHexU8Ex (uint8_t& ch, bool set_eof_on_fail = true);
+
+ bool
GetNameColonValue (std::string &name, std::string &value);
int32_t
diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/TaskPool.h b/contrib/llvm/tools/lldb/include/lldb/Utility/TaskPool.h
new file mode 100644
index 0000000..443e2a5
--- /dev/null
+++ b/contrib/llvm/tools/lldb/include/lldb/Utility/TaskPool.h
@@ -0,0 +1,221 @@
+//===--------------------- TaskPool.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_TaskPool_h_
+#define utility_TaskPool_h_
+
+#if defined(__cplusplus) && defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0)
+// Compiling MSVC libraries with _HAS_EXCEPTIONS=0, eliminates most but not all
+// calls to __uncaught_exception. Unfortunately, it does seem to eliminate
+// the delcaration of __uncaught_excpeiton. Including <eh.h> ensures that it is
+// declared. This may not be necessary after MSVC 12.
+#include <eh.h>
+#endif
+
+#if defined(_MSC_VER)
+// Due to another bug in MSVC 2013, including <future> will generate hundreds of
+// warnings in the Concurrency Runtime. This can be removed when we switch to
+// MSVC 2015
+#pragma warning(push)
+#pragma warning(disable:4062)
+#endif
+
+#include <cassert>
+#include <cstdint>
+#include <future>
+#include <list>
+#include <queue>
+#include <thread>
+#include <vector>
+
+// Global TaskPool class for running tasks in parallel on a set of worker thread created the first
+// time the task pool is used. The TaskPool provide no gurantee about the order the task will be run
+// and about what tasks will run in parrallel. None of the task added to the task pool should block
+// on something (mutex, future, condition variable) what will be set only by the completion of an
+// other task on the task pool as they may run on the same thread sequentally.
+class TaskPool
+{
+public:
+ // Add a new task to the task pool and return a std::future belonging to the newly created task.
+ // The caller of this function has to wait on the future for this task to complete.
+ template<typename F, typename... Args>
+ static std::future<typename std::result_of<F(Args...)>::type>
+ AddTask(F&& f, Args&&... args);
+
+ // Run all of the specified tasks on the task pool and wait until all of them are finished
+ // before returning. This method is intended to be used for small number tasks where listing
+ // them as function arguments is acceptable. For running large number of tasks you should use
+ // AddTask for each task and then call wait() on each returned future.
+ template<typename... T>
+ static void
+ RunTasks(T&&... tasks);
+
+private:
+ TaskPool() = delete;
+
+ template<typename... T>
+ struct RunTaskImpl;
+
+ static void
+ AddTaskImpl(std::function<void()>&& task_fn);
+};
+
+// Wrapper class around the global TaskPool implementation to make it possible to create a set of
+// tasks and then wait for the tasks to be completed by the WaitForNextCompletedTask call. This
+// class should be used when WaitForNextCompletedTask is needed because this class add no other
+// extra functionality to the TaskPool class and it have a very minor performance overhead.
+template <typename T> // The return type of the tasks what will be added to this task runner
+class TaskRunner
+{
+public:
+ // Add a task to the task runner what will also add the task to the global TaskPool. The
+ // function doesn't return the std::future for the task because it will be supplied by the
+ // WaitForNextCompletedTask after the task is completed.
+ template<typename F, typename... Args>
+ void
+ AddTask(F&& f, Args&&... args);
+
+ // Wait for the next task in this task runner to finish and then return the std::future what
+ // belongs to the finished task. If there is no task in this task runner (neither pending nor
+ // comleted) then this function will return an invalid future. Usually this function should be
+ // called in a loop processing the results of the tasks until it returns an invalid std::future
+ // what means that all task in this task runner is completed.
+ std::future<T>
+ WaitForNextCompletedTask();
+
+ // Convenience method to wait for all task in this TaskRunner to finish. Do NOT use this class
+ // just because of this method. Use TaskPool instead and wait for each std::future returned by
+ // AddTask in a loop.
+ void
+ WaitForAllTasks();
+
+private:
+ std::list<std::future<T>> m_ready;
+ std::list<std::future<T>> m_pending;
+ std::mutex m_mutex;
+ std::condition_variable m_cv;
+};
+
+template<typename F, typename... Args>
+std::future<typename std::result_of<F(Args...)>::type>
+TaskPool::AddTask(F&& f, Args&&... args)
+{
+ auto task_sp = std::make_shared<std::packaged_task<typename std::result_of<F(Args...)>::type()>>(
+ std::bind(std::forward<F>(f), std::forward<Args>(args)...));
+
+ AddTaskImpl([task_sp]() { (*task_sp)(); });
+
+ return task_sp->get_future();
+}
+
+template<typename... T>
+void
+TaskPool::RunTasks(T&&... tasks)
+{
+ RunTaskImpl<T...>::Run(std::forward<T>(tasks)...);
+}
+
+template<typename Head, typename... Tail>
+struct TaskPool::RunTaskImpl<Head, Tail...>
+{
+ static void
+ Run(Head&& h, Tail&&... t)
+ {
+ auto f = AddTask(std::forward<Head>(h));
+ RunTaskImpl<Tail...>::Run(std::forward<Tail>(t)...);
+ f.wait();
+ }
+};
+
+template<>
+struct TaskPool::RunTaskImpl<>
+{
+ static void
+ Run() {}
+};
+
+template <typename T>
+template<typename F, typename... Args>
+void
+TaskRunner<T>::AddTask(F&& f, Args&&... args)
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ auto it = m_pending.emplace(m_pending.end());
+ *it = std::move(TaskPool::AddTask(
+ [this, it](F f, Args... args)
+ {
+ T&& r = f(std::forward<Args>(args)...);
+
+ std::unique_lock<std::mutex> lock(this->m_mutex);
+ this->m_ready.splice(this->m_ready.end(), this->m_pending, it);
+ lock.unlock();
+
+ this->m_cv.notify_one();
+ return r;
+ },
+ std::forward<F>(f),
+ std::forward<Args>(args)...));
+}
+
+template <>
+template<typename F, typename... Args>
+void
+TaskRunner<void>::AddTask(F&& f, Args&&... args)
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ auto it = m_pending.emplace(m_pending.end());
+ *it = std::move(TaskPool::AddTask(
+ [this, it](F f, Args... args)
+ {
+ f(std::forward<Args>(args)...);
+
+ std::unique_lock<std::mutex> lock(this->m_mutex);
+ this->m_ready.emplace_back(std::move(*it));
+ this->m_pending.erase(it);
+ lock.unlock();
+
+ this->m_cv.notify_one();
+ },
+ std::forward<F>(f),
+ std::forward<Args>(args)...));
+}
+
+template <typename T>
+std::future<T>
+TaskRunner<T>::WaitForNextCompletedTask()
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ if (m_ready.empty() && m_pending.empty())
+ return std::future<T>(); // No more tasks
+
+ if (m_ready.empty())
+ m_cv.wait(lock, [this](){ return !this->m_ready.empty(); });
+
+ std::future<T> res = std::move(m_ready.front());
+ m_ready.pop_front();
+
+ lock.unlock();
+ res.wait();
+
+ return std::move(res);
+}
+
+template <typename T>
+void
+TaskRunner<T>::WaitForAllTasks()
+{
+ while (WaitForNextCompletedTask().valid());
+}
+
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif // #ifndef utility_TaskPool_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-defines.h b/contrib/llvm/tools/lldb/include/lldb/lldb-defines.h
index 9dce69a..175cecd 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-defines.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-defines.h
@@ -137,6 +137,8 @@
#define __attribute__(X)
#endif
+#define UNUSED_IF_ASSERT_DISABLED(x) ((void)(x))
+
#if defined(__cplusplus)
//----------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-enumerations.h b/contrib/llvm/tools/lldb/include/lldb/lldb-enumerations.h
index 28614ff..ea31752 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-enumerations.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-enumerations.h
@@ -146,6 +146,7 @@ namespace lldb {
eFormatVectorOfUInt32,
eFormatVectorOfSInt64,
eFormatVectorOfUInt64,
+ eFormatVectorOfFloat16,
eFormatVectorOfFloat32,
eFormatVectorOfFloat64,
eFormatVectorOfUInt128,
@@ -188,11 +189,11 @@ namespace lldb {
//----------------------------------------------------------------------
enum RegisterKind
{
- eRegisterKindGCC = 0, // the register numbers seen in eh_frame
- eRegisterKindDWARF, // the register numbers seen DWARF
- eRegisterKindGeneric, // insn ptr reg, stack ptr reg, etc not specific to any particular target
- eRegisterKindGDB, // the register numbers gdb uses (matches stabs numbers)
- eRegisterKindLLDB, // lldb's internal register numbers
+ eRegisterKindEHFrame = 0, // the register numbers seen in eh_frame
+ eRegisterKindDWARF, // the register numbers seen DWARF
+ eRegisterKindGeneric, // insn ptr reg, stack ptr reg, etc not specific to any particular target
+ eRegisterKindProcessPlugin, // num used by the process plugin - e.g. by the remote gdb-protocol stub program
+ eRegisterKindLLDB, // lldb's internal register numbers
kNumRegisterKinds
};
@@ -421,7 +422,7 @@ namespace lldb {
eLanguageTypeFortran03 = 0x0022, ///< ISO Fortran 2003.
eLanguageTypeFortran08 = 0x0023, ///< ISO Fortran 2008.
// Vendor Extensions
- // Note: LanguageRuntime::GetNameForLanguageType
+ // Note: Language::GetNameForLanguageType
// assumes these can be used as indexes into array language_names, and
// Language::SetLanguageFromCString and Language::AsCString
// assume these can be used as indexes into array g_languages.
@@ -595,16 +596,19 @@ namespace lldb {
eSectionTypeDataObjCMessageRefs, // Pointer to function pointer + selector
eSectionTypeDataObjCCFStrings, // Objective C const CFString/NSString objects
eSectionTypeDWARFDebugAbbrev,
+ eSectionTypeDWARFDebugAddr,
eSectionTypeDWARFDebugAranges,
eSectionTypeDWARFDebugFrame,
eSectionTypeDWARFDebugInfo,
eSectionTypeDWARFDebugLine,
eSectionTypeDWARFDebugLoc,
eSectionTypeDWARFDebugMacInfo,
+ eSectionTypeDWARFDebugMacro,
eSectionTypeDWARFDebugPubNames,
eSectionTypeDWARFDebugPubTypes,
eSectionTypeDWARFDebugRanges,
eSectionTypeDWARFDebugStr,
+ eSectionTypeDWARFDebugStrOffsets,
eSectionTypeDWARFAppleNames,
eSectionTypeDWARFAppleTypes,
eSectionTypeDWARFAppleNamespaces,
@@ -614,7 +618,10 @@ namespace lldb {
eSectionTypeELFRelocationEntries, // Elf SHT_REL or SHT_REL section
eSectionTypeELFDynamicLinkInfo, // Elf SHT_DYNAMIC section
eSectionTypeEHFrame,
+ eSectionTypeARMexidx,
+ eSectionTypeARMextab,
eSectionTypeCompactUnwind, // compact unwind section in Mach-O, __TEXT,__unwind_info
+ eSectionTypeGoSymtab,
eSectionTypeOther
};
@@ -729,15 +736,16 @@ namespace lldb {
//----------------------------------------------------------------------
FLAGS_ENUM(TypeOptions)
{
- eTypeOptionNone = (0u),
- eTypeOptionCascade = (1u << 0),
- eTypeOptionSkipPointers = (1u << 1),
- eTypeOptionSkipReferences = (1u << 2),
- eTypeOptionHideChildren = (1u << 3),
- eTypeOptionHideValue = (1u << 4),
- eTypeOptionShowOneLiner = (1u << 5),
- eTypeOptionHideNames = (1u << 6),
- eTypeOptionNonCacheable = (1u << 7)
+ eTypeOptionNone = (0u),
+ eTypeOptionCascade = (1u << 0),
+ eTypeOptionSkipPointers = (1u << 1),
+ eTypeOptionSkipReferences = (1u << 2),
+ eTypeOptionHideChildren = (1u << 3),
+ eTypeOptionHideValue = (1u << 4),
+ eTypeOptionShowOneLiner = (1u << 5),
+ eTypeOptionHideNames = (1u << 6),
+ eTypeOptionNonCacheable = (1u << 7),
+ eTypeOptionHideEmptyAggregates = (1u << 8)
};
//----------------------------------------------------------------------
@@ -953,7 +961,8 @@ namespace lldb {
eTypeIsInteger = (1u << 18),
eTypeIsFloat = (1u << 19),
eTypeIsComplex = (1u << 20),
- eTypeIsSigned = (1u << 21)
+ eTypeIsSigned = (1u << 21),
+ eTypeInstanceIsPointer = (1u << 22)
};
FLAGS_ENUM(CommandFlags)
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-forward.h b/contrib/llvm/tools/lldb/include/lldb/lldb-forward.h
index da90ac4..516f319 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-forward.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-forward.h
@@ -25,8 +25,10 @@ class AddressImpl;
class AddressRange;
class AddressResolver;
class ArchSpec;
+class ArmUnwindInfo;
class Args;
class ASTResultSynthesizer;
+class ASTStructExtractor;
class Baton;
class Block;
class Breakpoint;
@@ -48,26 +50,22 @@ class ClangASTContext;
class ClangASTImporter;
class ClangASTMetadata;
class ClangASTSource;
-class ClangASTType;
-class ClangNamespaceDecl;
-class ClangExpression;
class ClangExpressionDeclMap;
class ClangExpressionParser;
class ClangExpressionVariable;
-class ClangExpressionVariableList;
-class ClangExpressionVariableList;
class ClangExpressionVariables;
-class ClangFunction;
class ClangModulesDeclVendor;
class ClangPersistentVariables;
-class ClangUserExpression;
-class ClangUtilityFunction;
class CommandInterpreter;
class CommandInterpreterRunOptions;
class CommandObject;
class CommandReturnObject;
class Communication;
class CompactUnwindInfo;
+struct CompilerContext;
+class CompilerDecl;
+class CompilerDeclContext;
+class CompilerType;
class CompileUnit;
class Condition;
class Connection;
@@ -82,7 +80,7 @@ class DataExtractor;
class Debugger;
class Declaration;
class Disassembler;
-struct DumpValueObjectOptions;
+class DumpValueObjectOptions;
class DynamicCheckerFunctions;
class DynamicLoader;
class Editline;
@@ -95,10 +93,15 @@ class ExecutionContext;
class ExecutionContextRef;
class ExecutionContextRefLocker;
class ExecutionContextScope;
+class Expression;
+class ExpressionVariable;
+class ExpressionVariableList;
+class ExpressionTypeSystemHelper;
class File;
class FileSpec;
class FileSpecList;
class Flags;
+class GoASTContext;
class TypeCategoryImpl;
class FormatManager;
class FormattersMatchCandidate;
@@ -114,6 +117,8 @@ class IOObject;
class IRExecutionUnit;
class JITLoader;
class JITLoaderList;
+class Language;
+class LanguageCategory;
class LanguageRuntime;
class MemoryRegionInfo;
class LineTable;
@@ -130,6 +135,7 @@ class ModuleSpecList;
class Mutex;
struct NameSearchContext;
class ObjCLanguageRuntime;
+class ObjCRuntimeSyntheticProvider;
class ObjectContainer;
class OptionGroup;
class OptionGroupOptions;
@@ -160,6 +166,8 @@ class OptionValueUInt64;
class OptionValueUUID;
class NamedOption;
class PathMappingList;
+class FunctionCaller;
+class PersistentExpressionState;
class Platform;
class Process;
class ProcessAttachInfo;
@@ -177,12 +185,11 @@ class RegisterLocation;
class RegisterLocationList;
class RegisterValue;
class RegularExpression;
+class REPL;
class Scalar;
class ScriptInterpreter;
class ScriptInterpreterLocker;
-#ifndef LLDB_DISABLE_PYTHON
struct ScriptSummaryFormat;
-#endif
class SearchFilter;
class Section;
class SectionImpl;
@@ -221,6 +228,7 @@ class Symtab;
class SyntheticChildren;
class SyntheticChildrenFrontEnd;
class TypeFilterImpl;
+class TypeSystem;
#ifndef LLDB_DISABLE_PYTHON
class ScriptedSyntheticChildren;
#endif
@@ -249,6 +257,7 @@ class TypeAndOrName;
class TypeCategoryMap;
class TypeImpl;
class TypeList;
+class TypeMap;
class TypeListImpl;
class TypeMemberImpl;
class TypeMemberFunctionImpl;
@@ -264,6 +273,8 @@ class Unwind;
class UnwindAssembly;
class UnwindPlan;
class UnwindTable;
+class UserExpression;
+class UtilityFunction;
class VMRange;
class Value;
class ValueList;
@@ -300,12 +311,10 @@ namespace lldb {
typedef std::shared_ptr<lldb_private::BreakpointResolver> BreakpointResolverSP;
typedef std::shared_ptr<lldb_private::Broadcaster> BroadcasterSP;
typedef std::unique_ptr<lldb_private::ClangASTContext> ClangASTContextUP;
- typedef std::unique_ptr<lldb_private::ClangASTImporter> ClangASTImporterUP;
- typedef std::unique_ptr<lldb_private::ClangASTSource> ClangASTSourceUP;
- typedef std::shared_ptr<lldb_private::ClangExpressionVariable> ClangExpressionVariableSP;
+ typedef std::shared_ptr<lldb_private::ClangASTImporter> ClangASTImporterSP;
typedef std::unique_ptr<lldb_private::ClangModulesDeclVendor> ClangModulesDeclVendorUP;
typedef std::unique_ptr<lldb_private::ClangPersistentVariables> ClangPersistentVariablesUP;
- typedef std::shared_ptr<lldb_private::ClangUserExpression> ClangUserExpressionSP;
+ typedef std::shared_ptr<lldb_private::UserExpression> UserExpressionSP;
typedef std::shared_ptr<lldb_private::CommandObject> CommandObjectSP;
typedef std::shared_ptr<lldb_private::Communication> CommunicationSP;
typedef std::shared_ptr<lldb_private::Connection> ConnectionSP;
@@ -320,14 +329,18 @@ namespace lldb {
typedef std::unique_ptr<lldb_private::DynamicLoader> DynamicLoaderUP;
typedef std::shared_ptr<lldb_private::Event> EventSP;
typedef std::shared_ptr<lldb_private::ExecutionContextRef> ExecutionContextRefSP;
+ typedef std::shared_ptr<lldb_private::ExpressionVariable> ExpressionVariableSP;
typedef std::shared_ptr<lldb_private::File> FileSP;
typedef std::shared_ptr<lldb_private::Function> FunctionSP;
+ typedef std::shared_ptr<lldb_private::FunctionCaller> FunctionCallerSP;
typedef std::shared_ptr<lldb_private::FuncUnwinders> FuncUnwindersSP;
+ typedef std::unique_ptr<lldb_private::GoASTContext> GoASTContextUP;
typedef std::shared_ptr<lldb_private::InlineFunctionInfo> InlineFunctionInfoSP;
typedef std::shared_ptr<lldb_private::Instruction> InstructionSP;
typedef std::shared_ptr<lldb_private::InstrumentationRuntime> InstrumentationRuntimeSP;
typedef std::shared_ptr<lldb_private::IOHandler> IOHandlerSP;
typedef std::shared_ptr<lldb_private::IOObject> IOObjectSP;
+ typedef std::shared_ptr<lldb_private::IRExecutionUnit> IRExecutionUnitSP;
typedef std::shared_ptr<lldb_private::JITLoader> JITLoaderSP;
typedef std::unique_ptr<lldb_private::JITLoaderList> JITLoaderListUP;
typedef std::shared_ptr<lldb_private::LanguageRuntime> LanguageRuntimeSP;
@@ -373,9 +386,10 @@ namespace lldb {
typedef std::shared_ptr<lldb_private::Queue> QueueSP;
typedef std::weak_ptr<lldb_private::Queue> QueueWP;
typedef std::shared_ptr<lldb_private::QueueItem> QueueItemSP;
-#ifndef LLDB_DISABLE_PYTHON
+ typedef std::shared_ptr<lldb_private::REPL> REPLSP;
typedef std::shared_ptr<lldb_private::ScriptSummaryFormat> ScriptSummaryFormatSP;
-#endif // #ifndef LLDB_DISABLE_PYTHON
+ typedef std::shared_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterSP;
+ typedef std::unique_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterUP;
typedef std::shared_ptr<lldb_private::Section> SectionSP;
typedef std::unique_ptr<lldb_private::SectionList> SectionListUP;
typedef std::weak_ptr<lldb_private::Section> SectionWP;
@@ -415,6 +429,7 @@ namespace lldb {
typedef std::shared_ptr<lldb_private::TypeMemberFunctionImpl> TypeMemberFunctionImplSP;
typedef std::shared_ptr<lldb_private::TypeEnumMemberImpl> TypeEnumMemberImplSP;
typedef std::shared_ptr<lldb_private::TypeFilterImpl> TypeFilterImplSP;
+ typedef std::shared_ptr<lldb_private::TypeSystem> TypeSystemSP;
typedef std::shared_ptr<lldb_private::TypeFormatImpl> TypeFormatImplSP;
typedef std::shared_ptr<lldb_private::TypeNameSpecifierImpl> TypeNameSpecifierImplSP;
typedef std::shared_ptr<lldb_private::TypeSummaryImpl> TypeSummaryImplSP;
@@ -427,6 +442,7 @@ namespace lldb {
typedef std::weak_ptr<lldb_private::UnixSignals> UnixSignalsWP;
typedef std::shared_ptr<lldb_private::UnwindAssembly> UnwindAssemblySP;
typedef std::shared_ptr<lldb_private::UnwindPlan> UnwindPlanSP;
+ typedef std::shared_ptr<lldb_private::UtilityFunction> UtilityFunctionSP;
typedef lldb_private::SharingPtr<lldb_private::ValueObject> ValueObjectSP;
typedef std::shared_ptr<lldb_private::Value> ValueSP;
typedef std::shared_ptr<lldb_private::ValueList> ValueListSP;
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-private-enumerations.h b/contrib/llvm/tools/lldb/include/lldb/lldb-private-enumerations.h
index c62863d..5f8f96c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-private-enumerations.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-private-enumerations.h
@@ -106,13 +106,6 @@ typedef enum SortOrder
eSortOrderByName
} SortOrder;
-typedef enum ObjCRuntimeVersions {
- eObjC_VersionUnknown = 0,
- eAppleObjC_V1 = 1,
- eAppleObjC_V2 = 2
-} ObjCRuntimeVersions;
-
-
//----------------------------------------------------------------------
// LazyBool is for boolean values that need to be calculated lazily.
// Values start off set to eLazyBoolCalculate, and then they can be
@@ -188,7 +181,7 @@ typedef enum FormatterChoiceCriterion
eFormatterChoiceCriterionNavigatedTypedefs = 0x00000002,
eFormatterChoiceCriterionRegularExpressionSummary = 0x00000004,
eFormatterChoiceCriterionRegularExpressionFilter = 0x00000004,
- eFormatterChoiceCriterionDynamicObjCDiscovery = 0x00000008,
+ eFormatterChoiceCriterionLanguagePlugin = 0x00000008,
eFormatterChoiceCriterionStrippedBitField = 0x00000010,
eFormatterChoiceCriterionWentToStaticValue = 0x00000020
} FormatterChoiceCriterion;
@@ -248,6 +241,25 @@ enum class TypeValidatorResult : bool {
Success = true,
Failure = false
};
+
+//----------------------------------------------------------------------
+// Enumerations that can be used to specify scopes types when looking up
+// types.
+//----------------------------------------------------------------------
+enum class CompilerContextKind
+{
+ Invalid = 0,
+ TranslationUnit,
+ Module,
+ Namespace,
+ Class,
+ Structure,
+ Union,
+ Function,
+ Variable,
+ Enumeration,
+ Typedef
+};
} // namespace lldb_private
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-private-interfaces.h b/contrib/llvm/tools/lldb/include/lldb/lldb-private-interfaces.h
index 7b5c1c9..6bc8dad 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-private-interfaces.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-private-interfaces.h
@@ -14,6 +14,8 @@
#include "lldb/lldb-private.h"
+#include <set>
+
namespace lldb_private
{
typedef lldb::ABISP (*ABICreateInstance) (const ArchSpec &arch);
@@ -28,11 +30,13 @@ namespace lldb_private
typedef LogChannel* (*LogChannelCreateInstance) ();
typedef EmulateInstruction * (*EmulateInstructionCreateInstance) (const ArchSpec &arch, InstructionType inst_type);
typedef OperatingSystem* (*OperatingSystemCreateInstance) (Process *process, bool force);
+ typedef Language *(*LanguageCreateInstance) (lldb::LanguageType language);
typedef LanguageRuntime *(*LanguageRuntimeCreateInstance) (Process *process, lldb::LanguageType language);
typedef lldb::CommandObjectSP (*LanguageRuntimeGetCommandObject) (CommandInterpreter& interpreter);
typedef SystemRuntime *(*SystemRuntimeCreateInstance) (Process *process);
typedef lldb::PlatformSP (*PlatformCreateInstance) (bool force, const ArchSpec *arch);
- typedef lldb::ProcessSP (*ProcessCreateInstance) (Target &target, Listener &listener, const FileSpec *crash_file_path);
+ typedef lldb::ProcessSP (*ProcessCreateInstance) (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file_path);
+ typedef lldb::ScriptInterpreterSP (*ScriptInterpreterCreateInstance)(CommandInterpreter &interpreter);
typedef SymbolFile* (*SymbolFileCreateInstance) (ObjectFile* obj_file);
typedef SymbolVendor* (*SymbolVendorCreateInstance) (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm); // Module can be NULL for default system symbol vendor
typedef bool (*BreakpointHitCallback) (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
@@ -44,6 +48,10 @@ namespace lldb_private
typedef lldb::MemoryHistorySP (*MemoryHistoryCreateInstance) (const lldb::ProcessSP &process_sp);
typedef lldb::InstrumentationRuntimeType (*InstrumentationRuntimeGetType) ();
typedef lldb::InstrumentationRuntimeSP (*InstrumentationRuntimeCreateInstance) (const lldb::ProcessSP &process_sp);
+ typedef lldb::TypeSystemSP (*TypeSystemCreateInstance) (lldb::LanguageType language, Module *module, Target *target);
+ typedef lldb::REPLSP (*REPLCreateInstance) (Error &error, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options);
+ typedef void (*TypeSystemEnumerateSupportedLanguages) (std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions);
+ typedef void (*REPLEnumerateSupportedLanguages) (std::set<lldb::LanguageType> &languages);
typedef int (*ComparisonFunction)(const void *, const void *);
typedef void (*DebuggerInitializeCallback)(Debugger &debugger);
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-private-types.h b/contrib/llvm/tools/lldb/include/lldb/lldb-private-types.h
index cce637f..685034a 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-private-types.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-private-types.h
@@ -35,7 +35,7 @@ namespace lldb_private
// name (optional), encoding, size in bytes and the default display
// format.
//----------------------------------------------------------------------
- typedef struct
+ struct RegisterInfo
{
const char *name; // Name of this register, can't be NULL
const char *alt_name; // Alternate name of this register, can be NULL
@@ -51,15 +51,15 @@ namespace lldb_private
// for this register will be valid. For example, the value list for ah
// would be eax (x86) or rax (x64).
uint32_t *invalidate_regs; // List of registers (terminated with LLDB_INVALID_REGNUM). If this value is not
- // null, all registers in this list will be invalidateed when the value of this
+ // null, all registers in this list will be invalidated when the value of this
// register changes. For example, the invalidate list for eax would be rax
// ax, ah, and al.
- } RegisterInfo;
+ };
//----------------------------------------------------------------------
// Registers are grouped into register sets
//----------------------------------------------------------------------
- typedef struct
+ struct RegisterSet
{
const char *name; // Name of this register set
const char *short_name; // A short name for this register set
@@ -69,14 +69,14 @@ namespace lldb_private
// register array. For example, if eax is defined at index 4 for a
// particular RegisterContext, eax would be included in this RegisterSet
// by adding the value 4. Not by adding the value lldb_eax_i386.
- } RegisterSet;
+ };
- typedef struct
+ struct OptionEnumValueElement
{
int64_t value;
const char *string_value;
const char *usage;
- } OptionEnumValueElement;
+ };
struct OptionValidator
{
@@ -85,7 +85,7 @@ namespace lldb_private
virtual const char * ShortConditionString() const = 0;
virtual const char * LongConditionString() const = 0;
};
-
+
struct OptionDefinition
{
uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0
@@ -102,6 +102,8 @@ namespace lldb_private
// pass it.
};
+ typedef struct type128 { uint64_t x[2]; } type128;
+
} // namespace lldb_private
#endif // #if defined(__cplusplus)
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-python.h b/contrib/llvm/tools/lldb/include/lldb/lldb-python.h
deleted file mode 100644
index c8ef054..0000000
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-python.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===-- lldb-python.h --------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_lldb_python_h_
-#define LLDB_lldb_python_h_
-
-// Python.h needs to be included before any system headers in order to avoid redefinition of macros
-
-#ifdef LLDB_DISABLE_PYTHON
-// Python is disabled in this build
-#else
- #if defined(__linux__)
- // features.h will define _POSIX_C_SOURCE if _GNU_SOURCE is defined. This value
- // may be different from the value that Python defines it to be which results
- // in a warning. Undefine _POSIX_C_SOURCE before including Python.h The same
- // holds for _XOPEN_SOURCE.
- #undef _POSIX_C_SOURCE
- #undef _XOPEN_SOURCE
- #endif
-
- // Include python for non windows machines
- #include <Python.h>
-#endif // LLDB_DISABLE_PYTHON
-
-#endif // LLDB_lldb_python_h_
diff --git a/contrib/llvm/tools/lldb/include/lldb/lldb-types.h b/contrib/llvm/tools/lldb/include/lldb/lldb-types.h
index fe90207..2cf9904 100644
--- a/contrib/llvm/tools/lldb/include/lldb/lldb-types.h
+++ b/contrib/llvm/tools/lldb/include/lldb/lldb-types.h
@@ -110,7 +110,7 @@ namespace lldb
typedef uint64_t offset_t;
typedef int32_t break_id_t;
typedef int32_t watch_id_t;
- typedef void * clang_type_t;
+ typedef void * opaque_compiler_type_t;
typedef uint64_t queue_id_t;
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBAttachInfo.cpp b/contrib/llvm/tools/lldb/source/API/SBAttachInfo.cpp
index 07446df..0f2ab7a 100644
--- a/contrib/llvm/tools/lldb/source/API/SBAttachInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBAttachInfo.cpp
@@ -36,6 +36,15 @@ SBAttachInfo::SBAttachInfo (const char *path, bool wait_for) :
m_opaque_sp->SetWaitForLaunch (wait_for);
}
+SBAttachInfo::SBAttachInfo (const char *path, bool wait_for, bool async) :
+ m_opaque_sp (new ProcessAttachInfo())
+{
+ if (path && path[0])
+ m_opaque_sp->GetExecutableFile().SetFile(path, false);
+ m_opaque_sp->SetWaitForLaunch (wait_for);
+ m_opaque_sp->SetAsync(async);
+}
+
SBAttachInfo::SBAttachInfo (const SBAttachInfo &rhs) :
m_opaque_sp (new ProcessAttachInfo())
{
@@ -127,6 +136,13 @@ SBAttachInfo::SetWaitForLaunch (bool b)
m_opaque_sp->SetWaitForLaunch (b);
}
+void
+SBAttachInfo::SetWaitForLaunch (bool b, bool async)
+{
+ m_opaque_sp->SetWaitForLaunch (b);
+ m_opaque_sp->SetAsync(async);
+}
+
bool
SBAttachInfo::GetIgnoreExisting ()
{
diff --git a/contrib/llvm/tools/lldb/source/API/SBBreakpoint.cpp b/contrib/llvm/tools/lldb/source/API/SBBreakpoint.cpp
index dd4c80c..1f58ddb 100644
--- a/contrib/llvm/tools/lldb/source/API/SBBreakpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBBreakpoint.cpp
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBBreakpointLocation.h"
#include "lldb/API/SBDebugger.h"
@@ -32,7 +36,6 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
-
#include "lldb/lldb-enumerations.h"
using namespace lldb;
@@ -47,7 +50,6 @@ struct CallbackData
class SBBreakpointCallbackBaton : public Baton
{
public:
-
SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) :
Baton (new CallbackData)
{
@@ -56,19 +58,18 @@ public:
data->callback_baton = baton;
}
- virtual ~SBBreakpointCallbackBaton()
+ ~SBBreakpointCallbackBaton() override
{
CallbackData *data = (CallbackData *)m_data;
if (data)
{
delete data;
- m_data = NULL;
+ m_data = nullptr;
}
}
};
-
SBBreakpoint::SBBreakpoint () :
m_opaque_sp ()
{
@@ -79,15 +80,12 @@ SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) :
{
}
-
SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) :
m_opaque_sp (bp_sp)
{
}
-SBBreakpoint::~SBBreakpoint()
-{
-}
+SBBreakpoint::~SBBreakpoint() = default;
const SBBreakpoint &
SBBreakpoint::operator = (const SBBreakpoint& rhs)
@@ -135,7 +133,6 @@ SBBreakpoint::GetID () const
return break_id;
}
-
bool
SBBreakpoint::IsValid() const
{
@@ -169,7 +166,7 @@ SBBreakpoint::FindLocationByAddress (addr_t vm_addr)
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
Address address;
Target &target = m_opaque_sp->GetTarget();
- if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false)
+ if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address))
{
address.SetRawAddress (vm_addr);
}
@@ -189,7 +186,7 @@ SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr)
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
Address address;
Target &target = m_opaque_sp->GetTarget();
- if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false)
+ if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address))
{
address.SetRawAddress (vm_addr);
}
@@ -329,7 +326,7 @@ SBBreakpoint::GetCondition ()
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
return m_opaque_sp->GetConditionText ();
}
- return NULL;
+ return nullptr;
}
uint32_t
@@ -380,7 +377,6 @@ SBBreakpoint::SetThreadID (tid_t tid)
if (log)
log->Printf ("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4" PRIx64 ")",
static_cast<void*>(m_opaque_sp.get()), tid);
-
}
tid_t
@@ -422,7 +418,7 @@ SBBreakpoint::GetThreadIndex() const
{
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
- if (thread_spec != NULL)
+ if (thread_spec != nullptr)
thread_idx = thread_spec->GetIndex();
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -451,12 +447,12 @@ SBBreakpoint::SetThreadName (const char *thread_name)
const char *
SBBreakpoint::GetThreadName () const
{
- const char *name = NULL;
+ const char *name = nullptr;
if (m_opaque_sp)
{
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
- if (thread_spec != NULL)
+ if (thread_spec != nullptr)
name = thread_spec->GetName();
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -484,7 +480,7 @@ SBBreakpoint::SetQueueName (const char *queue_name)
const char *
SBBreakpoint::GetQueueName () const
{
- const char *name = NULL;
+ const char *name = nullptr;
if (m_opaque_sp)
{
Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
@@ -552,13 +548,10 @@ SBBreakpoint::GetDescription (SBStream &s)
}
bool
-SBBreakpoint::PrivateBreakpointHitCallback
-(
- void *baton,
- StoppointCallbackContext *ctx,
- lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id
-)
+SBBreakpoint::PrivateBreakpointHitCallback(void *baton,
+ StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id)
{
ExecutionContext exe_ctx (ctx->exe_ctx_ref);
BreakpointSP bp_sp(exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id));
@@ -758,8 +751,7 @@ SBBreakpoint::operator *() const
bool
SBBreakpoint::EventIsBreakpointEvent (const lldb::SBEvent &event)
{
- return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != NULL;
-
+ return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != nullptr;
}
BreakpointEventType
@@ -796,5 +788,3 @@ SBBreakpoint::GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event)
num_locations = (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent (event.GetSP()));
return num_locations;
}
-
-
diff --git a/contrib/llvm/tools/lldb/source/API/SBCommandInterpreter.cpp b/contrib/llvm/tools/lldb/source/API/SBCommandInterpreter.cpp
index d901e72..21f431d 100644
--- a/contrib/llvm/tools/lldb/source/API/SBCommandInterpreter.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBCommandInterpreter.cpp
@@ -7,8 +7,12 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-types.h"
-#include "lldb/Core/SourceManager.h"
+
#include "lldb/Core/Listener.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
@@ -34,10 +38,7 @@ SBCommandInterpreterRunOptions::SBCommandInterpreterRunOptions()
m_opaque_up.reset(new CommandInterpreterRunOptions());
}
-SBCommandInterpreterRunOptions::~SBCommandInterpreterRunOptions()
-{
-
-}
+SBCommandInterpreterRunOptions::~SBCommandInterpreterRunOptions() = default;
bool
SBCommandInterpreterRunOptions::GetStopOnContinue () const
@@ -126,21 +127,24 @@ SBCommandInterpreterRunOptions::ref () const
class CommandPluginInterfaceImplementation : public CommandObjectParsed
{
public:
- CommandPluginInterfaceImplementation (CommandInterpreter &interpreter,
- const char *name,
- lldb::SBCommandPluginInterface* backend,
- const char *help = NULL,
- const char *syntax = NULL,
- uint32_t flags = 0) :
+ CommandPluginInterfaceImplementation(CommandInterpreter &interpreter,
+ const char *name,
+ lldb::SBCommandPluginInterface* backend,
+ const char *help = nullptr,
+ const char *syntax = nullptr,
+ uint32_t flags = 0) :
CommandObjectParsed (interpreter, name, help, syntax, flags),
m_backend(backend) {}
- virtual bool
- IsRemovable() const { return true; }
+ bool
+ IsRemovable() const override
+ {
+ return true;
+ }
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute(Args& command, CommandReturnObject &result) override
{
SBCommandReturnObject sb_return(&result);
SBCommandInterpreter sb_interpreter(&m_interpreter);
@@ -169,6 +173,8 @@ SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs) :
{
}
+SBCommandInterpreter::~SBCommandInterpreter() = default;
+
const SBCommandInterpreter &
SBCommandInterpreter::operator = (const SBCommandInterpreter &rhs)
{
@@ -176,47 +182,34 @@ SBCommandInterpreter::operator = (const SBCommandInterpreter &rhs)
return *this;
}
-SBCommandInterpreter::~SBCommandInterpreter ()
-{
-}
-
bool
SBCommandInterpreter::IsValid() const
{
- return m_opaque_ptr != NULL;
+ return m_opaque_ptr != nullptr;
}
-
bool
-SBCommandInterpreter::CommandExists (const char *cmd)
+SBCommandInterpreter::CommandExists(const char *cmd)
{
- if (cmd && m_opaque_ptr)
- return m_opaque_ptr->CommandExists (cmd);
- return false;
+ return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd) : false);
}
bool
SBCommandInterpreter::AliasExists (const char *cmd)
{
- if (cmd && m_opaque_ptr)
- return m_opaque_ptr->AliasExists (cmd);
- return false;
+ return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd) : false);
}
bool
-SBCommandInterpreter::IsActive ()
+SBCommandInterpreter::IsActive()
{
- if (m_opaque_ptr)
- return m_opaque_ptr->IsActive ();
- return false;
+ return (IsValid() ? m_opaque_ptr->IsActive() : false);
}
const char *
SBCommandInterpreter::GetIOHandlerControlSequence(char ch)
{
- if (m_opaque_ptr)
- return m_opaque_ptr->GetDebugger().GetTopIOHandlerControlSequence (ch).GetCString();
- return NULL;
+ return (IsValid() ? m_opaque_ptr->GetDebugger().GetTopIOHandlerControlSequence(ch).GetCString() : nullptr);
}
lldb::ReturnStatus
@@ -247,7 +240,7 @@ SBCommandInterpreter::HandleCommand (const char *command_line, SBExecutionContex
result.Clear();
- if (command_line && m_opaque_ptr)
+ if (command_line && IsValid())
{
result.ref().SetInteractive(false);
m_opaque_ptr->HandleCommand (command_line, add_to_history ? eLazyBoolYes : eLazyBoolNo, result.ref(), ctx_ptr);
@@ -290,7 +283,7 @@ SBCommandInterpreter::HandleCommandsFromFile (lldb::SBFileSpec &file,
static_cast<void*>(result.get()));
}
- if (!m_opaque_ptr)
+ if (!IsValid())
{
result->AppendError ("SBCommandInterpreter is not valid.");
result->SetStatus (eReturnStatusFailed);
@@ -315,12 +308,9 @@ SBCommandInterpreter::HandleCommandsFromFile (lldb::SBFileSpec &file,
else
ctx_ptr = nullptr;
-
m_opaque_ptr->HandleCommandsFromFile (tmp_spec, ctx_ptr, options.ref(), result.ref());
-
}
-
int
SBCommandInterpreter::HandleCompletion (const char *current_line,
const char *cursor,
@@ -334,7 +324,7 @@ SBCommandInterpreter::HandleCompletion (const char *current_line,
// Sanity check the arguments that are passed in:
// cursor & last_char have to be within the current_line.
- if (current_line == NULL || cursor == NULL || last_char == NULL)
+ if (current_line == nullptr || cursor == nullptr || last_char == nullptr)
return 0;
if (cursor < current_line || last_char < current_line)
@@ -352,11 +342,11 @@ SBCommandInterpreter::HandleCompletion (const char *current_line,
static_cast<uint64_t>(last_char - current_line),
match_start_point, max_return_elements);
- if (m_opaque_ptr)
+ if (IsValid())
{
lldb_private::StringList lldb_matches;
- num_completions = m_opaque_ptr->HandleCompletion (current_line, cursor, last_char, match_start_point,
- max_return_elements, lldb_matches);
+ num_completions = m_opaque_ptr->HandleCompletion(current_line, cursor, last_char, match_start_point,
+ max_return_elements, lldb_matches);
SBStringList temp_list (&lldb_matches);
matches.AppendList (temp_list);
@@ -381,27 +371,21 @@ SBCommandInterpreter::HandleCompletion (const char *current_line,
}
bool
-SBCommandInterpreter::HasCommands ()
+SBCommandInterpreter::HasCommands()
{
- if (m_opaque_ptr)
- return m_opaque_ptr->HasCommands();
- return false;
+ return (IsValid() ? m_opaque_ptr->HasCommands() : false);
}
bool
-SBCommandInterpreter::HasAliases ()
+SBCommandInterpreter::HasAliases()
{
- if (m_opaque_ptr)
- return m_opaque_ptr->HasAliases();
- return false;
+ return (IsValid() ? m_opaque_ptr->HasAliases() : false);
}
bool
-SBCommandInterpreter::HasAliasOptions ()
+SBCommandInterpreter::HasAliasOptions()
{
- if (m_opaque_ptr)
- return m_opaque_ptr->HasAliasOptions ();
- return false;
+ return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false);
}
SBProcess
@@ -409,7 +393,7 @@ SBCommandInterpreter::GetProcess ()
{
SBProcess sb_process;
ProcessSP process_sp;
- if (m_opaque_ptr)
+ if (IsValid())
{
TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
if (target_sp)
@@ -433,7 +417,7 @@ SBDebugger
SBCommandInterpreter::GetDebugger ()
{
SBDebugger sb_debugger;
- if (m_opaque_ptr)
+ if (IsValid())
sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this());
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -448,15 +432,13 @@ SBCommandInterpreter::GetDebugger ()
bool
SBCommandInterpreter::GetPromptOnQuit()
{
- if (m_opaque_ptr)
- return m_opaque_ptr->GetPromptOnQuit();
- return false;
+ return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false);
}
void
SBCommandInterpreter::SetPromptOnQuit (bool b)
{
- if (m_opaque_ptr)
+ if (IsValid())
m_opaque_ptr->SetPromptOnQuit(b);
}
@@ -464,7 +446,7 @@ void
SBCommandInterpreter::ResolveCommand(const char *command_line, SBCommandReturnObject &result)
{
result.Clear();
- if (command_line && m_opaque_ptr)
+ if (command_line && IsValid())
{
m_opaque_ptr->ResolveCommand(command_line, result.ref());
}
@@ -475,7 +457,6 @@ SBCommandInterpreter::ResolveCommand(const char *command_line, SBCommandReturnOb
}
}
-
CommandInterpreter *
SBCommandInterpreter::get ()
{
@@ -499,7 +480,7 @@ void
SBCommandInterpreter::SourceInitFileInHomeDirectory (SBCommandReturnObject &result)
{
result.Clear();
- if (m_opaque_ptr)
+ if (IsValid())
{
TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
Mutex::Locker api_locker;
@@ -524,7 +505,7 @@ void
SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory (SBCommandReturnObject &result)
{
result.Clear();
- if (m_opaque_ptr)
+ if (IsValid())
{
TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
Mutex::Locker api_locker;
@@ -588,7 +569,7 @@ SBCommandInterpreter::SetCommandOverrideCallback (const char *command_name,
lldb::CommandOverrideCallback callback,
void *baton)
{
- if (command_name && command_name[0] && m_opaque_ptr)
+ if (command_name && command_name[0] && IsValid())
{
std::string command_name_str (command_name);
CommandObject *cmd_obj = m_opaque_ptr->GetCommandObjectForCommand(command_name_str);
@@ -605,7 +586,7 @@ SBCommandInterpreter::SetCommandOverrideCallback (const char *command_name,
lldb::SBCommand
SBCommandInterpreter::AddMultiwordCommand (const char* name, const char* help)
{
- CommandObjectMultiword *new_command = new CommandObjectMultiword(*m_opaque_ptr,name,help);
+ CommandObjectMultiword *new_command = new CommandObjectMultiword(*m_opaque_ptr, name, help);
new_command->SetRemovable (true);
lldb::CommandObjectSP new_command_sp(new_command);
if (new_command_sp && m_opaque_ptr->AddUserCommand(name, new_command_sp, true))
@@ -617,47 +598,40 @@ lldb::SBCommand
SBCommandInterpreter::AddCommand (const char* name, lldb::SBCommandPluginInterface* impl, const char* help)
{
lldb::CommandObjectSP new_command_sp;
- new_command_sp.reset(new CommandPluginInterfaceImplementation(*m_opaque_ptr,name,impl,help));
+ new_command_sp.reset(new CommandPluginInterfaceImplementation(*m_opaque_ptr,name, impl, help));
if (new_command_sp && m_opaque_ptr->AddUserCommand(name, new_command_sp, true))
return lldb::SBCommand(new_command_sp);
return lldb::SBCommand();
}
-SBCommand::SBCommand ()
-{}
+SBCommand::SBCommand() = default;
SBCommand::SBCommand (lldb::CommandObjectSP cmd_sp) : m_opaque_sp (cmd_sp)
{}
bool
-SBCommand::IsValid ()
+SBCommand::IsValid()
{
- return (bool)m_opaque_sp;
+ return m_opaque_sp.get() != nullptr;
}
const char*
-SBCommand::GetName ()
+SBCommand::GetName()
{
- if (IsValid ())
- return m_opaque_sp->GetCommandName ();
- return NULL;
+ return (IsValid() ? m_opaque_sp->GetCommandName() : nullptr);
}
const char*
-SBCommand::GetHelp ()
+SBCommand::GetHelp()
{
- if (IsValid ())
- return m_opaque_sp->GetHelp ();
- return NULL;
+ return (IsValid() ? m_opaque_sp->GetHelp() : nullptr);
}
const char*
-SBCommand::GetHelpLong ()
+SBCommand::GetHelpLong()
{
- if (IsValid ())
- return m_opaque_sp->GetHelpLong ();
- return NULL;
+ return (IsValid() ? m_opaque_sp->GetHelpLong() : nullptr);
}
void
@@ -679,7 +653,7 @@ SBCommand::AddMultiwordCommand (const char* name, const char* help)
{
if (!IsValid ())
return lldb::SBCommand();
- if (m_opaque_sp->IsMultiwordObject() == false)
+ if (!m_opaque_sp->IsMultiwordObject())
return lldb::SBCommand();
CommandObjectMultiword *new_command = new CommandObjectMultiword(m_opaque_sp->GetCommandInterpreter(),name,help);
new_command->SetRemovable (true);
@@ -694,7 +668,7 @@ SBCommand::AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, c
{
if (!IsValid ())
return lldb::SBCommand();
- if (m_opaque_sp->IsMultiwordObject() == false)
+ if (!m_opaque_sp->IsMultiwordObject())
return lldb::SBCommand();
lldb::CommandObjectSP new_command_sp;
new_command_sp.reset(new CommandPluginInterfaceImplementation(m_opaque_sp->GetCommandInterpreter(),name,impl,help));
@@ -706,9 +680,7 @@ SBCommand::AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, c
uint32_t
SBCommand::GetFlags ()
{
- if (!IsValid())
- return 0;
- return m_opaque_sp->GetFlags().Get();
+ return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0);
}
void
diff --git a/contrib/llvm/tools/lldb/source/API/SBCommandReturnObject.cpp b/contrib/llvm/tools/lldb/source/API/SBCommandReturnObject.cpp
index 1ae2df7..a2ed4d6 100644
--- a/contrib/llvm/tools/lldb/source/API/SBCommandReturnObject.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBCommandReturnObject.cpp
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBStream.h"
@@ -26,7 +30,7 @@ SBCommandReturnObject::SBCommandReturnObject () :
SBCommandReturnObject::SBCommandReturnObject (const SBCommandReturnObject &rhs):
m_opaque_ap ()
{
- if (rhs.m_opaque_ap.get())
+ if (rhs.m_opaque_ap)
m_opaque_ap.reset (new CommandReturnObject (*rhs.m_opaque_ap));
}
@@ -35,6 +39,8 @@ SBCommandReturnObject::SBCommandReturnObject (CommandReturnObject *ptr) :
{
}
+SBCommandReturnObject::~SBCommandReturnObject() = default;
+
CommandReturnObject *
SBCommandReturnObject::Release ()
{
@@ -46,7 +52,7 @@ SBCommandReturnObject::operator = (const SBCommandReturnObject &rhs)
{
if (this != &rhs)
{
- if (rhs.m_opaque_ap.get())
+ if (rhs.m_opaque_ap)
m_opaque_ap.reset (new CommandReturnObject (*rhs.m_opaque_ap));
else
m_opaque_ap.reset();
@@ -54,25 +60,18 @@ SBCommandReturnObject::operator = (const SBCommandReturnObject &rhs)
return *this;
}
-
-SBCommandReturnObject::~SBCommandReturnObject ()
-{
- // m_opaque_ap will automatically delete any pointer it owns
-}
-
bool
SBCommandReturnObject::IsValid() const
{
- return m_opaque_ap.get() != NULL;
+ return m_opaque_ap.get() != nullptr;
}
-
const char *
SBCommandReturnObject::GetOutput ()
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
{
if (log)
log->Printf ("SBCommandReturnObject(%p)::GetOutput () => \"%s\"",
@@ -83,10 +82,10 @@ SBCommandReturnObject::GetOutput ()
}
if (log)
- log->Printf ("SBCommandReturnObject(%p)::GetOutput () => NULL",
+ log->Printf ("SBCommandReturnObject(%p)::GetOutput () => nullptr",
static_cast<void*>(m_opaque_ap.get()));
- return NULL;
+ return nullptr;
}
const char *
@@ -94,7 +93,7 @@ SBCommandReturnObject::GetError ()
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
{
if (log)
log->Printf ("SBCommandReturnObject(%p)::GetError () => \"%s\"",
@@ -105,26 +104,22 @@ SBCommandReturnObject::GetError ()
}
if (log)
- log->Printf ("SBCommandReturnObject(%p)::GetError () => NULL",
+ log->Printf ("SBCommandReturnObject(%p)::GetError () => nullptr",
static_cast<void*>(m_opaque_ap.get()));
- return NULL;
+ return nullptr;
}
size_t
-SBCommandReturnObject::GetOutputSize ()
+SBCommandReturnObject::GetOutputSize()
{
- if (m_opaque_ap.get())
- return strlen (m_opaque_ap->GetOutputData());
- return 0;
+ return (m_opaque_ap ? strlen(m_opaque_ap->GetOutputData()) : 0);
}
size_t
-SBCommandReturnObject::GetErrorSize ()
+SBCommandReturnObject::GetErrorSize()
{
- if (m_opaque_ap.get())
- return strlen(m_opaque_ap->GetErrorData());
- return 0;
+ return (m_opaque_ap ? strlen(m_opaque_ap->GetErrorData()) : 0);
}
size_t
@@ -154,52 +149,46 @@ SBCommandReturnObject::PutError (FILE *fh)
void
SBCommandReturnObject::Clear()
{
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
m_opaque_ap->Clear();
}
lldb::ReturnStatus
SBCommandReturnObject::GetStatus()
{
- if (m_opaque_ap.get())
- return m_opaque_ap->GetStatus();
- return lldb::eReturnStatusInvalid;
+ return (m_opaque_ap ? m_opaque_ap->GetStatus() : lldb::eReturnStatusInvalid);
}
void
SBCommandReturnObject::SetStatus(lldb::ReturnStatus status)
{
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
m_opaque_ap->SetStatus(status);
}
bool
-SBCommandReturnObject::Succeeded ()
+SBCommandReturnObject::Succeeded()
{
- if (m_opaque_ap.get())
- return m_opaque_ap->Succeeded();
- return false;
+ return (m_opaque_ap ? m_opaque_ap->Succeeded() : false);
}
bool
-SBCommandReturnObject::HasResult ()
+SBCommandReturnObject::HasResult()
{
- if (m_opaque_ap.get())
- return m_opaque_ap->HasResult();
- return false;
+ return (m_opaque_ap ? m_opaque_ap->HasResult() : false);
}
void
SBCommandReturnObject::AppendMessage (const char *message)
{
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
m_opaque_ap->AppendMessage (message);
}
void
SBCommandReturnObject::AppendWarning (const char *message)
{
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
m_opaque_ap->AppendWarning (message);
}
@@ -222,7 +211,6 @@ SBCommandReturnObject::operator *() const
return *(m_opaque_ap.get());
}
-
CommandReturnObject &
SBCommandReturnObject::ref() const
{
@@ -230,11 +218,10 @@ SBCommandReturnObject::ref() const
return *(m_opaque_ap.get());
}
-
void
SBCommandReturnObject::SetLLDBObjectPtr (CommandReturnObject *ptr)
{
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
m_opaque_ap.reset (ptr);
}
@@ -243,7 +230,7 @@ SBCommandReturnObject::GetDescription (SBStream &description)
{
Stream &strm = description.ref();
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
{
description.Printf ("Status: ");
lldb::ReturnStatus status = m_opaque_ap->GetStatus();
@@ -269,25 +256,25 @@ SBCommandReturnObject::GetDescription (SBStream &description)
}
void
-SBCommandReturnObject::SetImmediateOutputFile (FILE *fh)
+SBCommandReturnObject::SetImmediateOutputFile(FILE *fh)
{
- if (m_opaque_ap.get())
- m_opaque_ap->SetImmediateOutputFile (fh);
+ if (m_opaque_ap)
+ m_opaque_ap->SetImmediateOutputFile(fh);
}
void
-SBCommandReturnObject::SetImmediateErrorFile (FILE *fh)
+SBCommandReturnObject::SetImmediateErrorFile(FILE *fh)
{
- if (m_opaque_ap.get())
- m_opaque_ap->SetImmediateErrorFile (fh);
+ if (m_opaque_ap)
+ m_opaque_ap->SetImmediateErrorFile(fh);
}
void
SBCommandReturnObject::PutCString(const char* string, int len)
{
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
{
- if (len == 0 || string == NULL || *string == 0)
+ if (len == 0 || string == nullptr || *string == 0)
{
return;
}
@@ -304,27 +291,27 @@ SBCommandReturnObject::PutCString(const char* string, int len)
const char *
SBCommandReturnObject::GetOutput (bool only_if_no_immediate)
{
- if (!m_opaque_ap.get())
- return NULL;
- if (only_if_no_immediate == false || m_opaque_ap->GetImmediateOutputStream().get() == NULL)
+ if (!m_opaque_ap)
+ return nullptr;
+ if (!only_if_no_immediate || m_opaque_ap->GetImmediateOutputStream().get() == nullptr)
return GetOutput();
- return NULL;
+ return nullptr;
}
const char *
SBCommandReturnObject::GetError (bool only_if_no_immediate)
{
- if (!m_opaque_ap.get())
- return NULL;
- if (only_if_no_immediate == false || m_opaque_ap->GetImmediateErrorStream().get() == NULL)
+ if (!m_opaque_ap)
+ return nullptr;
+ if (!only_if_no_immediate || m_opaque_ap->GetImmediateErrorStream().get() == nullptr)
return GetError();
- return NULL;
+ return nullptr;
}
size_t
SBCommandReturnObject::Printf(const char* format, ...)
{
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
{
va_list args;
va_start (args, format);
@@ -338,7 +325,7 @@ SBCommandReturnObject::Printf(const char* format, ...)
void
SBCommandReturnObject::SetError (lldb::SBError &error, const char *fallback_error_cstr)
{
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
{
if (error.IsValid())
m_opaque_ap->SetError(error.ref(), fallback_error_cstr);
@@ -350,7 +337,6 @@ SBCommandReturnObject::SetError (lldb::SBError &error, const char *fallback_erro
void
SBCommandReturnObject::SetError (const char *error_cstr)
{
- if (m_opaque_ap.get() && error_cstr)
+ if (m_opaque_ap && error_cstr)
m_opaque_ap->SetError(error_cstr);
}
-
diff --git a/contrib/llvm/tools/lldb/source/API/SBDebugger.cpp b/contrib/llvm/tools/lldb/source/API/SBDebugger.cpp
index df2019f..1645294 100644
--- a/contrib/llvm/tools/lldb/source/API/SBDebugger.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBDebugger.cpp
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/API/SBDebugger.h"
#include "lldb/lldb-private.h"
@@ -43,13 +47,13 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/DynamicLibrary.h"
using namespace lldb;
using namespace lldb_private;
-
static llvm::sys::DynamicLibrary
LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& error)
{
@@ -86,13 +90,6 @@ LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& er
static llvm::ManagedStatic<SystemLifetimeManager> g_debugger_lifetime;
-SBInputReader::SBInputReader()
-{
-}
-SBInputReader::~SBInputReader()
-{
-}
-
SBError
SBInputReader::Initialize(lldb::SBDebugger &sb_debugger,
unsigned long (*)(void *, lldb::SBInputReader *, lldb::InputReaderAction, char const *,
@@ -106,12 +103,37 @@ void
SBInputReader::SetIsDone(bool)
{
}
+
bool
SBInputReader::IsActive() const
{
return false;
}
+SBDebugger::SBDebugger() = default;
+
+SBDebugger::SBDebugger(const lldb::DebuggerSP &debugger_sp) :
+ m_opaque_sp(debugger_sp)
+{
+}
+
+SBDebugger::SBDebugger(const SBDebugger &rhs) :
+ m_opaque_sp (rhs.m_opaque_sp)
+{
+}
+
+SBDebugger::~SBDebugger() = default;
+
+SBDebugger &
+SBDebugger::operator = (const SBDebugger &rhs)
+{
+ if (this != &rhs)
+ {
+ m_opaque_sp = rhs.m_opaque_sp;
+ }
+ return *this;
+}
+
void
SBDebugger::Initialize ()
{
@@ -147,13 +169,13 @@ SBDebugger::Clear ()
SBDebugger
SBDebugger::Create()
{
- return SBDebugger::Create(false, NULL, NULL);
+ return SBDebugger::Create(false, nullptr, nullptr);
}
SBDebugger
SBDebugger::Create(bool source_init_files)
{
- return SBDebugger::Create (source_init_files, NULL, NULL);
+ return SBDebugger::Create (source_init_files, nullptr, nullptr);
}
SBDebugger
@@ -215,7 +237,7 @@ SBDebugger::Destroy (SBDebugger &debugger)
Debugger::Destroy (debugger.m_opaque_sp);
- if (debugger.m_opaque_sp.get() != NULL)
+ if (debugger.m_opaque_sp.get() != nullptr)
debugger.m_opaque_sp.reset();
}
@@ -237,42 +259,12 @@ SBDebugger::MemoryPressureDetected ()
ModuleList::RemoveOrphanSharedModules(mandatory);
}
-SBDebugger::SBDebugger () :
- m_opaque_sp ()
-{
-}
-
-SBDebugger::SBDebugger(const lldb::DebuggerSP &debugger_sp) :
- m_opaque_sp(debugger_sp)
-{
-}
-
-SBDebugger::SBDebugger(const SBDebugger &rhs) :
- m_opaque_sp (rhs.m_opaque_sp)
-{
-}
-
-SBDebugger &
-SBDebugger::operator = (const SBDebugger &rhs)
-{
- if (this != &rhs)
- {
- m_opaque_sp = rhs.m_opaque_sp;
- }
- return *this;
-}
-
-SBDebugger::~SBDebugger ()
-{
-}
-
bool
SBDebugger::IsValid() const
{
- return m_opaque_sp.get() != NULL;
+ return m_opaque_sp.get() != nullptr;
}
-
void
SBDebugger::SetAsync (bool b)
{
@@ -281,12 +273,9 @@ SBDebugger::SetAsync (bool b)
}
bool
-SBDebugger::GetAsync ()
+SBDebugger::GetAsync()
{
- if (m_opaque_sp)
- return m_opaque_sp->GetAsyncExecution();
- else
- return false;
+ return (m_opaque_sp ? m_opaque_sp->GetAsyncExecution() : false);
}
void
@@ -358,7 +347,7 @@ SBDebugger::GetInputFileHandle ()
if (stream_file_sp)
return stream_file_sp->GetFile().GetStream();
}
- return NULL;
+ return nullptr;
}
FILE *
@@ -370,20 +359,19 @@ SBDebugger::GetOutputFileHandle ()
if (stream_file_sp)
return stream_file_sp->GetFile().GetStream();
}
- return NULL;
+ return nullptr;
}
FILE *
SBDebugger::GetErrorFileHandle ()
{
if (m_opaque_sp)
- if (m_opaque_sp)
- {
- StreamFileSP stream_file_sp (m_opaque_sp->GetErrorFile());
- if (stream_file_sp)
- return stream_file_sp->GetFile().GetStream();
- }
- return NULL;
+ {
+ StreamFileSP stream_file_sp(m_opaque_sp->GetErrorFile());
+ if (stream_file_sp)
+ return stream_file_sp->GetFile().GetStream();
+ }
+ return nullptr;
}
void
@@ -432,12 +420,12 @@ SBDebugger::HandleCommand (const char *command)
sb_interpreter.HandleCommand (command, result, false);
- if (GetErrorFileHandle() != NULL)
+ if (GetErrorFileHandle() != nullptr)
result.PutError (GetErrorFileHandle());
- if (GetOutputFileHandle() != NULL)
+ if (GetOutputFileHandle() != nullptr)
result.PutOutput (GetOutputFileHandle());
- if (m_opaque_sp->GetAsyncExecution() == false)
+ if (!m_opaque_sp->GetAsyncExecution())
{
SBProcess process(GetCommandInterpreter().GetProcess ());
ProcessSP process_sp (process.GetSP());
@@ -492,7 +480,7 @@ SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event,
{
// Drain stdout when we stop just in case we have any bytes
while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
- if (out != NULL)
+ if (out != nullptr)
::fwrite (stdio_buffer, 1, len, out);
}
@@ -500,7 +488,7 @@ SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event,
{
// Drain stderr when we stop just in case we have any bytes
while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
- if (err != NULL)
+ if (err != nullptr)
::fwrite (stdio_buffer, 1, len, err);
}
@@ -524,7 +512,6 @@ SBDebugger::GetSourceManager ()
return sb_source_manager;
}
-
bool
SBDebugger::GetDefaultArchitecture (char *arch_name, size_t arch_name_len)
{
@@ -547,7 +534,6 @@ SBDebugger::GetDefaultArchitecture (char *arch_name, size_t arch_name_len)
return false;
}
-
bool
SBDebugger::SetDefaultArchitecture (const char *arch_name)
{
@@ -564,12 +550,11 @@ SBDebugger::SetDefaultArchitecture (const char *arch_name)
}
ScriptLanguage
-SBDebugger::GetScriptingLanguage (const char *script_language_name)
+SBDebugger::GetScriptingLanguage(const char *script_language_name)
{
-
- return Args::StringToScriptLanguage (script_language_name,
- eScriptLanguageDefault,
- NULL);
+ return Args::StringToScriptLanguage(script_language_name,
+ eScriptLanguageDefault,
+ nullptr);
}
const char *
@@ -637,7 +622,7 @@ SBDebugger::CreateTarget (const char *filename,
}
else
{
- sb_error.SetErrorString("invalid target");
+ sb_error.SetErrorString("invalid debugger");
}
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -659,12 +644,12 @@ SBDebugger::CreateTargetWithFileAndTargetTriple (const char *filename,
if (m_opaque_sp)
{
const bool add_dependent_modules = true;
- Error error (m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp,
- filename,
- target_triple,
- add_dependent_modules,
- NULL,
- target_sp));
+ Error error (m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp,
+ filename,
+ target_triple,
+ add_dependent_modules,
+ nullptr,
+ target_sp));
sb_target.SetSP (target_sp);
}
@@ -689,12 +674,12 @@ SBDebugger::CreateTargetWithFileAndArch (const char *filename, const char *arch_
Error error;
const bool add_dependent_modules = true;
- error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp,
- filename,
- arch_cstr,
- add_dependent_modules,
- NULL,
- target_sp);
+ error = m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp,
+ filename,
+ arch_cstr,
+ add_dependent_modules,
+ nullptr,
+ target_sp);
if (error.Success())
{
@@ -720,12 +705,12 @@ SBDebugger::CreateTarget (const char *filename)
{
Error error;
const bool add_dependent_modules = true;
- error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp,
- filename,
- NULL,
- add_dependent_modules,
- NULL,
- target_sp);
+ error = m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp,
+ filename,
+ nullptr,
+ add_dependent_modules,
+ nullptr,
+ target_sp);
if (error.Success())
{
@@ -767,6 +752,7 @@ SBDebugger::DeleteTarget (lldb::SBTarget &target)
return result;
}
+
SBTarget
SBDebugger::GetTargetAtIndex (uint32_t idx)
{
@@ -813,7 +799,7 @@ SBDebugger::FindTargetWithFileAndArch (const char *filename, const char *arch_na
{
// No need to lock, the target list is thread safe
ArchSpec arch (arch_name, m_opaque_sp->GetPlatformList().GetSelectedPlatform().get());
- TargetSP target_sp (m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture (FileSpec(filename, false), arch_name ? &arch : NULL));
+ TargetSP target_sp (m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture(FileSpec(filename, false), arch_name ? &arch : nullptr));
sb_target.SetSP (target_sp);
}
return sb_target;
@@ -831,7 +817,6 @@ SBDebugger::FindTargetWithLLDBProcess (const ProcessSP &process_sp)
return sb_target;
}
-
uint32_t
SBDebugger::GetNumTargets ()
{
@@ -1000,6 +985,17 @@ SBDebugger::RunCommandInterpreter (bool auto_handle_events,
}
}
+SBError
+SBDebugger::RunREPL (lldb::LanguageType language, const char *repl_options)
+{
+ SBError error;
+ if (m_opaque_sp)
+ error.ref() = m_opaque_sp->RunREPL(language, repl_options);
+ else
+ error.SetErrorString ("invalid debugger");
+ return error;
+}
+
void
SBDebugger::reset (const DebuggerSP &debugger_sp)
{
@@ -1039,10 +1035,7 @@ SBDebugger::FindDebuggerWithID (int id)
const char *
SBDebugger::GetInstanceName()
{
- if (m_opaque_sp)
- return m_opaque_sp->GetInstanceName().AsCString();
- else
- return NULL;
+ return (m_opaque_sp ? m_opaque_sp->GetInstanceName().AsCString() : nullptr);
}
SBError
@@ -1098,11 +1091,9 @@ SBDebugger::GetInternalVariableValue (const char *var_name, const char *debugger
}
uint32_t
-SBDebugger::GetTerminalWidth () const
+SBDebugger::GetTerminalWidth() const
{
- if (m_opaque_sp)
- return m_opaque_sp->GetTerminalWidth ();
- return 0;
+ return (m_opaque_sp ? m_opaque_sp->GetTerminalWidth() : 0);
}
void
@@ -1122,9 +1113,7 @@ SBDebugger::GetPrompt() const
static_cast<void*>(m_opaque_sp.get()),
(m_opaque_sp ? m_opaque_sp->GetPrompt() : ""));
- if (m_opaque_sp)
- return m_opaque_sp->GetPrompt ();
- return 0;
+ return (m_opaque_sp ? m_opaque_sp->GetPrompt() : nullptr);
}
void
@@ -1133,14 +1122,11 @@ SBDebugger::SetPrompt (const char *prompt)
if (m_opaque_sp)
m_opaque_sp->SetPrompt (prompt);
}
-
ScriptLanguage
SBDebugger::GetScriptLanguage() const
{
- if (m_opaque_sp)
- return m_opaque_sp->GetScriptLanguage ();
- return eScriptLanguageNone;
+ return (m_opaque_sp ? m_opaque_sp->GetScriptLanguage() : eScriptLanguageNone);
}
void
@@ -1153,35 +1139,27 @@ SBDebugger::SetScriptLanguage (ScriptLanguage script_lang)
}
bool
-SBDebugger::SetUseExternalEditor (bool value)
+SBDebugger::SetUseExternalEditor(bool value)
{
- if (m_opaque_sp)
- return m_opaque_sp->SetUseExternalEditor (value);
- return false;
+ return (m_opaque_sp ? m_opaque_sp->SetUseExternalEditor(value) : false);
}
bool
-SBDebugger::GetUseExternalEditor ()
+SBDebugger::GetUseExternalEditor()
{
- if (m_opaque_sp)
- return m_opaque_sp->GetUseExternalEditor ();
- return false;
+ return (m_opaque_sp ? m_opaque_sp->GetUseExternalEditor() : false);
}
bool
-SBDebugger::SetUseColor (bool value)
+SBDebugger::SetUseColor(bool value)
{
- if (m_opaque_sp)
- return m_opaque_sp->SetUseColor (value);
- return false;
+ return (m_opaque_sp ? m_opaque_sp->SetUseColor(value) : false);
}
bool
-SBDebugger::GetUseColor () const
+SBDebugger::GetUseColor() const
{
- if (m_opaque_sp)
- return m_opaque_sp->GetUseColor ();
- return false;
+ return (m_opaque_sp ? m_opaque_sp->GetUseColor() : false);
}
bool
@@ -1204,12 +1182,9 @@ SBDebugger::GetDescription (SBStream &description)
user_id_t
SBDebugger::GetID()
{
- if (m_opaque_sp)
- return m_opaque_sp->GetID();
- return LLDB_INVALID_UID;
+ return (m_opaque_sp ? m_opaque_sp->GetID() : LLDB_INVALID_UID);
}
-
SBError
SBDebugger::SetCurrentPlatform (const char *platform_name_cstr)
{
@@ -1267,11 +1242,9 @@ SBDebugger::SetCurrentPlatformSDKRoot (const char *sysroot)
}
bool
-SBDebugger::GetCloseInputOnEOF () const
+SBDebugger::GetCloseInputOnEOF() const
{
- if (m_opaque_sp)
- return m_opaque_sp->GetCloseInputOnEOF ();
- return false;
+ return (m_opaque_sp ? m_opaque_sp->GetCloseInputOnEOF() : false);
}
void
@@ -1296,6 +1269,16 @@ SBDebugger::GetCategory (const char* category_name)
}
SBTypeCategory
+SBDebugger::GetCategory (lldb::LanguageType lang_type)
+{
+ TypeCategoryImplSP category_sp;
+ if (DataVisualization::Categories::GetCategory(lang_type, category_sp))
+ return SBTypeCategory(category_sp);
+ else
+ return SBTypeCategory();
+}
+
+SBTypeCategory
SBDebugger::CreateCategory (const char* category_name)
{
if (!category_name || *category_name == 0)
@@ -1349,7 +1332,7 @@ SBDebugger::GetFormatForType (SBTypeNameSpecifier type_name)
SBTypeSummary
SBDebugger::GetSummaryForType (SBTypeNameSpecifier type_name)
{
- if (type_name.IsValid() == false)
+ if (!type_name.IsValid())
return SBTypeSummary();
return SBTypeSummary(DataVisualization::GetSummaryForType(type_name.GetSP()));
}
@@ -1358,7 +1341,7 @@ SBDebugger::GetSummaryForType (SBTypeNameSpecifier type_name)
SBTypeFilter
SBDebugger::GetFilterForType (SBTypeNameSpecifier type_name)
{
- if (type_name.IsValid() == false)
+ if (!type_name.IsValid())
return SBTypeFilter();
return SBTypeFilter(DataVisualization::GetFilterForType(type_name.GetSP()));
}
@@ -1367,7 +1350,7 @@ SBDebugger::GetFilterForType (SBTypeNameSpecifier type_name)
SBTypeSynthetic
SBDebugger::GetSyntheticForType (SBTypeNameSpecifier type_name)
{
- if (type_name.IsValid() == false)
+ if (!type_name.IsValid())
return SBTypeSynthetic();
return SBTypeSynthetic(DataVisualization::GetSyntheticForType(type_name.GetSP()));
}
@@ -1380,8 +1363,7 @@ SBDebugger::EnableLog (const char *channel, const char **categories)
{
uint32_t log_options = LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
StreamString errors;
- return m_opaque_sp->EnableLog (channel, categories, NULL, log_options, errors);
-
+ return m_opaque_sp->EnableLog(channel, categories, nullptr, log_options, errors);
}
else
return false;
@@ -1395,5 +1377,3 @@ SBDebugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *bato
return m_opaque_sp->SetLoggingCallback (log_callback, baton);
}
}
-
-
diff --git a/contrib/llvm/tools/lldb/source/API/SBFrame.cpp b/contrib/llvm/tools/lldb/source/API/SBFrame.cpp
index 08a5822..02a215b 100644
--- a/contrib/llvm/tools/lldb/source/API/SBFrame.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBFrame.cpp
@@ -7,10 +7,14 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/API/SBFrame.h"
-
-#include <string>
+// C Includes
+// C++ Includes
#include <algorithm>
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/API/SBFrame.h"
#include "lldb/lldb-types.h"
@@ -21,8 +25,8 @@
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectVariable.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Function.h"
@@ -50,7 +54,6 @@
using namespace lldb;
using namespace lldb_private;
-
SBFrame::SBFrame () :
m_opaque_sp (new ExecutionContextRef())
{
@@ -76,6 +79,8 @@ SBFrame::SBFrame(const SBFrame &rhs) :
{
}
+SBFrame::~SBFrame() = default;
+
const SBFrame &
SBFrame::operator = (const SBFrame &rhs)
{
@@ -84,16 +89,10 @@ SBFrame::operator = (const SBFrame &rhs)
return *this;
}
-SBFrame::~SBFrame()
-{
-}
-
StackFrameSP
SBFrame::GetFrameSP() const
{
- if (m_opaque_sp)
- return m_opaque_sp->GetFrameSP();
- return StackFrameSP();
+ return (m_opaque_sp ? m_opaque_sp->GetFrameSP() : StackFrameSP());
}
void
@@ -105,7 +104,7 @@ SBFrame::SetFrameSP (const StackFrameSP &lldb_object_sp)
bool
SBFrame::IsValid() const
{
- return GetFrameSP().get() != NULL;
+ return GetFrameSP().get() != nullptr;
}
SBSymbolContext
@@ -116,7 +115,7 @@ SBFrame::GetSymbolContext (uint32_t resolve_scope) const
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -159,7 +158,7 @@ SBFrame::GetModule () const
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -202,7 +201,7 @@ SBFrame::GetCompileUnit () const
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -243,7 +242,7 @@ SBFrame::GetFunction () const
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -284,7 +283,7 @@ SBFrame::GetSymbol () const
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -324,7 +323,7 @@ SBFrame::GetBlock () const
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -364,7 +363,7 @@ SBFrame::GetFrameBlock () const
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
Process *process = exe_ctx.GetProcessPtr();
@@ -405,7 +404,7 @@ SBFrame::GetLineEntry () const
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -464,7 +463,6 @@ SBFrame::GetCFA () const
return LLDB_INVALID_ADDRESS;
}
-
addr_t
SBFrame::GetPC () const
{
@@ -473,7 +471,7 @@ SBFrame::GetPC () const
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -484,7 +482,7 @@ SBFrame::GetPC () const
frame = exe_ctx.GetFramePtr();
if (frame)
{
- addr = frame->GetFrameCodeAddress().GetOpcodeLoadAddress (target);
+ addr = frame->GetFrameCodeAddress().GetOpcodeLoadAddress (target, eAddressClassCode);
}
else
{
@@ -514,7 +512,7 @@ SBFrame::SetPC (addr_t new_pc)
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -555,7 +553,7 @@ SBFrame::GetSP () const
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -587,7 +585,6 @@ SBFrame::GetSP () const
return addr;
}
-
addr_t
SBFrame::GetFP () const
{
@@ -596,7 +593,7 @@ SBFrame::GetFP () const
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -628,7 +625,6 @@ SBFrame::GetFP () const
return addr;
}
-
SBAddress
SBFrame::GetPCAddress () const
{
@@ -696,7 +692,7 @@ SBFrame::GetValueForVariablePath (const char *var_path, DynamicValueType use_dyn
SBValue sb_value;
Mutex::Locker api_locker;
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- if (var_path == NULL || var_path[0] == '\0')
+ if (var_path == nullptr || var_path[0] == '\0')
{
if (log)
log->Printf ("SBFrame::GetValueForVariablePath called with empty variable path.");
@@ -705,7 +701,7 @@ SBFrame::GetValueForVariablePath (const char *var_path, DynamicValueType use_dyn
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -762,7 +758,7 @@ SBFrame::FindVariable (const char *name, lldb::DynamicValueType use_dynamic)
VariableSP var_sp;
SBValue sb_value;
- if (name == NULL || name[0] == '\0')
+ if (name == nullptr || name[0] == '\0')
{
if (log)
log->Printf ("SBFrame::FindVariable called with empty name");
@@ -773,7 +769,7 @@ SBFrame::FindVariable (const char *name, lldb::DynamicValueType use_dynamic)
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -850,7 +846,7 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBValue sb_value;
- if (name == NULL || name[0] == '\0')
+ if (name == nullptr || name[0] == '\0')
{
if (log)
log->Printf ("SBFrame::FindValue called with empty name.");
@@ -861,7 +857,7 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -956,7 +952,7 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy
case eValueTypeConstResult: // constant result variables
{
ConstString const_name(name);
- ClangExpressionVariableSP expr_var_sp (target->GetPersistentVariables().GetVariable (const_name));
+ ExpressionVariableSP expr_var_sp (target->GetPersistentVariable (const_name));
if (expr_var_sp)
{
value_sp = expr_var_sp->GetValueObject();
@@ -1035,11 +1031,11 @@ const char *
SBFrame::Disassemble () const
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- const char *disassembly = NULL;
+ const char *disassembly = nullptr;
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -1072,7 +1068,6 @@ SBFrame::Disassemble () const
return disassembly;
}
-
SBValueList
SBFrame::GetVariables (bool arguments,
bool locals,
@@ -1130,7 +1125,7 @@ SBFrame::GetVariables (const lldb::SBVariablesOptions& options)
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
const bool statics = options.GetIncludeStatics();
@@ -1156,7 +1151,7 @@ SBFrame::GetVariables (const lldb::SBVariablesOptions& options)
if (frame)
{
size_t i;
- VariableList *variable_list = NULL;
+ VariableList *variable_list = nullptr;
variable_list = frame->GetVariableList(true);
if (variable_list)
{
@@ -1194,9 +1189,9 @@ SBFrame::GetVariables (const lldb::SBVariablesOptions& options)
ValueObjectSP valobj_sp(frame->GetValueObjectForFrameVariable (variable_sp, eNoDynamicValues));
- if (false == include_runtime_support_values &&
- valobj_sp &&
- true == valobj_sp->IsRuntimeSupportValue())
+ if (!include_runtime_support_values &&
+ valobj_sp != nullptr &&
+ valobj_sp->IsRuntimeSupportValue())
continue;
SBValue value_sb;
@@ -1238,7 +1233,7 @@ SBFrame::GetRegisters ()
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -1290,7 +1285,7 @@ SBFrame::FindRegister (const char *name)
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -1394,6 +1389,10 @@ SBFrame::EvaluateExpression (const char *expr)
lldb::DynamicValueType fetch_dynamic_value = frame->CalculateTarget()->GetPreferDynamicValue();
options.SetFetchDynamicValue (fetch_dynamic_value);
options.SetUnwindOnError (true);
+ if (target->GetLanguage() != eLanguageTypeUnknown)
+ options.SetLanguage(target->GetLanguage());
+ else
+ options.SetLanguage(frame->GetLanguage());
return EvaluateExpression (expr, options);
}
return result;
@@ -1405,6 +1404,13 @@ SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dyna
SBExpressionOptions options;
options.SetFetchDynamicValue (fetch_dynamic_value);
options.SetUnwindOnError (true);
+ ExecutionContext exe_ctx(m_opaque_sp.get());
+ StackFrame *frame = exe_ctx.GetFramePtr();
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target && target->GetLanguage() != eLanguageTypeUnknown)
+ options.SetLanguage(target->GetLanguage());
+ else if (frame)
+ options.SetLanguage(frame->GetLanguage());
return EvaluateExpression (expr, options);
}
@@ -1412,8 +1418,15 @@ SBValue
SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dynamic_value, bool unwind_on_error)
{
SBExpressionOptions options;
+ ExecutionContext exe_ctx(m_opaque_sp.get());
options.SetFetchDynamicValue (fetch_dynamic_value);
options.SetUnwindOnError (unwind_on_error);
+ StackFrame *frame = exe_ctx.GetFramePtr();
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target && target->GetLanguage() != eLanguageTypeUnknown)
+ options.SetLanguage(target->GetLanguage());
+ else if (frame)
+ options.SetLanguage(frame->GetLanguage());
return EvaluateExpression (expr, options);
}
@@ -1427,7 +1440,7 @@ SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &option
ExpressionResults exe_results = eExpressionSetupError;
SBValue expr_result;
- if (expr == NULL || expr[0] == '\0')
+ if (expr == nullptr || expr[0] == '\0')
{
if (log)
log->Printf ("SBFrame::EvaluateExpression called with an empty expression");
@@ -1442,7 +1455,7 @@ SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &option
if (log)
log->Printf ("SBFrame()::EvaluateExpression (expr=\"%s\")...", expr);
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
@@ -1469,7 +1482,7 @@ SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &option
expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue());
if (target->GetDisplayExpressionsInCrashlogs())
- Host::SetCrashDescription (NULL);
+ Host::SetCrashDescription(nullptr);
}
else
{
@@ -1509,7 +1522,7 @@ SBFrame::IsInlined() const
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
ExecutionContext exe_ctx(m_opaque_sp.get());
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -1523,7 +1536,7 @@ SBFrame::IsInlined() const
Block *block = frame->GetSymbolContext(eSymbolContextBlock).block;
if (block)
- return block->GetContainingInlinedBlock () != NULL;
+ return block->GetContainingInlinedBlock() != nullptr;
}
else
{
@@ -1551,9 +1564,9 @@ const char *
SBFrame::GetFunctionName() const
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- const char *name = NULL;
+ const char *name = nullptr;
ExecutionContext exe_ctx(m_opaque_sp.get());
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -1575,13 +1588,13 @@ SBFrame::GetFunctionName() const
}
}
- if (name == NULL)
+ if (name == nullptr)
{
if (sc.function)
name = sc.function->GetName().GetCString();
}
- if (name == NULL)
+ if (name == nullptr)
{
if (sc.symbol)
name = sc.symbol->GetName().GetCString();
@@ -1607,9 +1620,9 @@ const char *
SBFrame::GetDisplayFunctionName()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- const char *name = NULL;
+ const char *name = nullptr;
ExecutionContext exe_ctx(m_opaque_sp.get());
- StackFrame *frame = NULL;
+ StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
@@ -1631,13 +1644,13 @@ SBFrame::GetDisplayFunctionName()
}
}
- if (name == NULL)
+ if (name == nullptr)
{
if (sc.function)
name = sc.function->GetDisplayName().GetCString();
}
- if (name == NULL)
+ if (name == nullptr)
{
if (sc.symbol)
name = sc.symbol->GetDisplayName().GetCString();
diff --git a/contrib/llvm/tools/lldb/source/API/SBFunction.cpp b/contrib/llvm/tools/lldb/source/API/SBFunction.cpp
index 2ec6072..2d03d53 100644
--- a/contrib/llvm/tools/lldb/source/API/SBFunction.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBFunction.cpp
@@ -16,6 +16,7 @@
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
@@ -216,6 +217,24 @@ SBFunction::GetEndAddress ()
return addr;
}
+const char *
+SBFunction::GetArgumentName (uint32_t arg_idx)
+{
+ if (m_opaque_ptr)
+ {
+ Block &block = m_opaque_ptr->GetBlock(true);
+ VariableListSP variable_list_sp = block.GetBlockVariableList(true);
+ if (variable_list_sp)
+ {
+ VariableList arguments;
+ variable_list_sp->AppendVariablesWithScope (eValueTypeVariableArgument, arguments, true);
+ lldb::VariableSP variable_sp = arguments.GetVariableAtIndex(arg_idx);
+ if (variable_sp)
+ return variable_sp->GetName().GetCString();
+ }
+ }
+ return nullptr;
+}
uint32_t
SBFunction::GetPrologueByteSize ()
@@ -258,4 +277,13 @@ SBFunction::GetLanguage ()
return lldb::eLanguageTypeUnknown;
}
-
+bool
+SBFunction::GetIsOptimized ()
+{
+ if (m_opaque_ptr)
+ {
+ if (m_opaque_ptr->GetCompileUnit())
+ return m_opaque_ptr->GetCompileUnit()->GetIsOptimized();
+ }
+ return false;
+}
diff --git a/contrib/llvm/tools/lldb/source/API/SBLanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/API/SBLanguageRuntime.cpp
index 93a54cd..743343e 100644
--- a/contrib/llvm/tools/lldb/source/API/SBLanguageRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBLanguageRuntime.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/API/SBLanguageRuntime.h"
-#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/Language.h"
using namespace lldb;
using namespace lldb_private;
@@ -16,11 +16,11 @@ using namespace lldb_private;
lldb::LanguageType
SBLanguageRuntime::GetLanguageTypeFromString (const char *string)
{
- return LanguageRuntime::GetLanguageTypeFromString(string);
+ return Language::GetLanguageTypeFromString(string);
}
const char *
SBLanguageRuntime::GetNameForLanguageType (lldb::LanguageType language)
{
- return LanguageRuntime::GetNameForLanguageType(language);
+ return Language::GetNameForLanguageType(language);
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBModule.cpp b/contrib/llvm/tools/lldb/source/API/SBModule.cpp
index 0249a7e..a810940 100644
--- a/contrib/llvm/tools/lldb/source/API/SBModule.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBModule.cpp
@@ -20,10 +20,10 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Core/ValueObjectVariable.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Symtab.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Target.h"
@@ -521,7 +521,11 @@ SBModule::FindFirstType (const char *name_cstr)
sb_type = SBType (module_sp->FindFirstType(sc, name, exact_match));
if (!sb_type.IsValid())
- sb_type = SBType (ClangASTContext::GetBasicType (module_sp->GetClangASTContext().getASTContext(), name));
+ {
+ TypeSystem *type_system = module_sp->GetTypeSystemForLanguage(eLanguageTypeC);
+ if (type_system)
+ sb_type = SBType (type_system->GetBuiltinTypeByName(name));
+ }
}
return sb_type;
}
@@ -531,7 +535,11 @@ SBModule::GetBasicType(lldb::BasicType type)
{
ModuleSP module_sp (GetSP ());
if (module_sp)
- return SBType (ClangASTContext::GetBasicType (module_sp->GetClangASTContext().getASTContext(), type));
+ {
+ TypeSystem *type_system = module_sp->GetTypeSystemForLanguage(eLanguageTypeC);
+ if (type_system)
+ return SBType (type_system->GetBasicTypeFromAST(type));
+ }
return SBType();
}
@@ -564,9 +572,13 @@ SBModule::FindTypes (const char *type)
}
else
{
- SBType sb_type(ClangASTContext::GetBasicType (module_sp->GetClangASTContext().getASTContext(), name));
- if (sb_type.IsValid())
- retval.Append(sb_type);
+ TypeSystem *type_system = module_sp->GetTypeSystemForLanguage(eLanguageTypeC);
+ if (type_system)
+ {
+ CompilerType compiler_type = type_system->GetBuiltinTypeByName(name);
+ if (compiler_type)
+ retval.Append(SBType(compiler_type));
+ }
}
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBPlatform.cpp b/contrib/llvm/tools/lldb/source/API/SBPlatform.cpp
index 97ffcf1..b8dc01b 100644
--- a/contrib/llvm/tools/lldb/source/API/SBPlatform.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBPlatform.cpp
@@ -189,7 +189,7 @@ SBPlatformShellCommand::~SBPlatformShellCommand()
void
SBPlatformShellCommand::Clear()
{
- m_opaque_ptr->m_output = std::move(std::string());
+ m_opaque_ptr->m_output = std::string();
m_opaque_ptr->m_status = 0;
m_opaque_ptr->m_signo = 0;
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBProcess.cpp b/contrib/llvm/tools/lldb/source/API/SBProcess.cpp
index 01bfaf9..4255472 100644
--- a/contrib/llvm/tools/lldb/source/API/SBProcess.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBProcess.cpp
@@ -19,6 +19,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
@@ -409,7 +410,7 @@ SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
- log->Printf ("SBProcess(%p)::GetProfileData (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64,
+ log->Printf ("SBProcess(%p)::GetAsyncProfileData (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64,
static_cast<void*>(process_sp.get()),
static_cast<int>(bytes_read), dst,
static_cast<uint64_t>(dst_len),
@@ -994,7 +995,14 @@ SBProcess::GetStateFromEvent (const SBEvent &event)
bool
SBProcess::GetRestartedFromEvent (const SBEvent &event)
{
- return Process::ProcessEventData::GetRestartedFromEvent (event.get());
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ bool ret_val = Process::ProcessEventData::GetRestartedFromEvent (event.get());
+
+ if (log)
+ log->Printf ("SBProcess::%s (event.sp=%p) => %d", __FUNCTION__, event.get(), ret_val);
+
+ return ret_val;
}
size_t
@@ -1287,7 +1295,15 @@ SBProcess::GetNumSupportedHardwareWatchpoints (lldb::SBError &sb_error) const
}
uint32_t
-SBProcess::LoadImage (lldb::SBFileSpec &sb_image_spec, lldb::SBError &sb_error)
+SBProcess::LoadImage (lldb::SBFileSpec &sb_remote_image_spec, lldb::SBError &sb_error)
+{
+ return LoadImage(SBFileSpec(), sb_remote_image_spec, sb_error);
+}
+
+uint32_t
+SBProcess::LoadImage (const lldb::SBFileSpec &sb_local_image_spec,
+ const lldb::SBFileSpec &sb_remote_image_spec,
+ lldb::SBError &sb_error)
{
ProcessSP process_sp(GetSP());
if (process_sp)
@@ -1296,7 +1312,11 @@ SBProcess::LoadImage (lldb::SBFileSpec &sb_image_spec, lldb::SBError &sb_error)
if (stop_locker.TryLock(&process_sp->GetRunLock()))
{
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- return process_sp->LoadImage (*sb_image_spec, sb_error.ref());
+ PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();
+ return platform_sp->LoadImage (process_sp.get(),
+ *sb_local_image_spec,
+ *sb_remote_image_spec,
+ sb_error.ref());
}
else
{
@@ -1321,7 +1341,8 @@ SBProcess::UnloadImage (uint32_t image_token)
if (stop_locker.TryLock(&process_sp->GetRunLock()))
{
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
- sb_error.SetError (process_sp->UnloadImage (image_token));
+ PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();
+ sb_error.SetError (platform_sp->UnloadImage (process_sp.get(), image_token));
}
else
{
@@ -1425,3 +1446,27 @@ SBProcess::IsInstrumentationRuntimePresent(InstrumentationRuntimeType type)
return runtime_sp->IsActive();
}
+
+lldb::SBError
+SBProcess::SaveCore(const char *file_name)
+{
+ lldb::SBError error;
+ ProcessSP process_sp(GetSP());
+ if (!process_sp)
+ {
+ error.SetErrorString("SBProcess is invalid");
+ return error;
+ }
+
+ Mutex::Locker api_locker(process_sp->GetTarget().GetAPIMutex());
+
+ if (process_sp->GetState() != eStateStopped)
+ {
+ error.SetErrorString("the process is not stopped");
+ return error;
+ }
+
+ FileSpec core_file(file_name, false);
+ error.ref() = PluginManager::SaveCore(process_sp, core_file);
+ return error;
+}
diff --git a/contrib/llvm/tools/lldb/source/API/SBStream.cpp b/contrib/llvm/tools/lldb/source/API/SBStream.cpp
index f50334f..f3be3be 100644
--- a/contrib/llvm/tools/lldb/source/API/SBStream.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBStream.cpp
@@ -23,6 +23,13 @@ SBStream::SBStream () :
{
}
+SBStream::SBStream (SBStream &&rhs) :
+ m_opaque_ap (std::move(rhs.m_opaque_ap)),
+ m_is_file (rhs.m_is_file)
+{
+}
+
+
SBStream::~SBStream ()
{
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBTarget.cpp b/contrib/llvm/tools/lldb/source/API/SBTarget.cpp
index 6597d4e..c7595c3 100644
--- a/contrib/llvm/tools/lldb/source/API/SBTarget.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBTarget.cpp
@@ -52,6 +52,7 @@
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ABI.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
@@ -847,11 +848,11 @@ SBTarget::BreakpointCreateByName (const char *symbol_name,
{
FileSpecList module_spec_list;
module_spec_list.Append (FileSpec (module_name, false));
- *sb_bp = target_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal, hardware);
+ *sb_bp = target_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto, eLanguageTypeUnknown, skip_prologue, internal, hardware);
}
else
{
- *sb_bp = target_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal, hardware);
+ *sb_bp = target_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeAuto, eLanguageTypeUnknown, skip_prologue, internal, hardware);
}
}
@@ -869,7 +870,7 @@ SBTarget::BreakpointCreateByName (const char *symbol_name,
const SBFileSpecList &comp_unit_list)
{
uint32_t name_type_mask = eFunctionNameTypeAuto;
- return BreakpointCreateByName (symbol_name, name_type_mask, module_list, comp_unit_list);
+ return BreakpointCreateByName (symbol_name, name_type_mask, eLanguageTypeUnknown, module_list, comp_unit_list);
}
lldb::SBBreakpoint
@@ -878,6 +879,16 @@ SBTarget::BreakpointCreateByName (const char *symbol_name,
const SBFileSpecList &module_list,
const SBFileSpecList &comp_unit_list)
{
+ return BreakpointCreateByName (symbol_name, name_type_mask, eLanguageTypeUnknown, module_list, comp_unit_list);
+}
+
+lldb::SBBreakpoint
+SBTarget::BreakpointCreateByName (const char *symbol_name,
+ uint32_t name_type_mask,
+ LanguageType symbol_language,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &comp_unit_list)
+{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBBreakpoint sb_bp;
@@ -892,6 +903,7 @@ SBTarget::BreakpointCreateByName (const char *symbol_name,
comp_unit_list.get(),
symbol_name,
name_type_mask,
+ symbol_language,
skip_prologue,
internal,
hardware);
@@ -912,6 +924,17 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[],
const SBFileSpecList &module_list,
const SBFileSpecList &comp_unit_list)
{
+ return BreakpointCreateByNames(symbol_names, num_names, name_type_mask, eLanguageTypeUnknown, module_list, comp_unit_list);
+}
+
+lldb::SBBreakpoint
+SBTarget::BreakpointCreateByNames (const char *symbol_names[],
+ uint32_t num_names,
+ uint32_t name_type_mask,
+ LanguageType symbol_language,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &comp_unit_list)
+{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBBreakpoint sb_bp;
@@ -923,13 +946,14 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[],
const bool hardware = false;
const LazyBool skip_prologue = eLazyBoolCalculate;
*sb_bp = target_sp->CreateBreakpoint (module_list.get(),
- comp_unit_list.get(),
- symbol_names,
- num_names,
- name_type_mask,
- skip_prologue,
- internal,
- hardware);
+ comp_unit_list.get(),
+ symbol_names,
+ num_names,
+ name_type_mask,
+ symbol_language,
+ skip_prologue,
+ internal,
+ hardware);
}
if (log)
@@ -959,6 +983,30 @@ SBBreakpoint
SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
const char *module_name)
{
+ SBFileSpecList module_spec_list;
+ SBFileSpecList comp_unit_list;
+ if (module_name && module_name[0])
+ {
+ module_spec_list.Append (FileSpec (module_name, false));
+
+ }
+ return BreakpointCreateByRegex (symbol_name_regex, eLanguageTypeUnknown, module_spec_list, comp_unit_list);
+}
+
+lldb::SBBreakpoint
+SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &comp_unit_list)
+{
+ return BreakpointCreateByRegex (symbol_name_regex, eLanguageTypeUnknown, module_list, comp_unit_list);
+}
+
+lldb::SBBreakpoint
+SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
+ LanguageType symbol_language,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &comp_unit_list)
+{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBBreakpoint sb_bp;
@@ -970,75 +1018,72 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
const bool internal = false;
const bool hardware = false;
const LazyBool skip_prologue = eLazyBoolCalculate;
-
- if (module_name && module_name[0])
- {
- FileSpecList module_spec_list;
- module_spec_list.Append (FileSpec (module_name, false));
-
- *sb_bp = target_sp->CreateFuncRegexBreakpoint (&module_spec_list, NULL, regexp, skip_prologue, internal, hardware);
- }
- else
- {
- *sb_bp = target_sp->CreateFuncRegexBreakpoint (NULL, NULL, regexp, skip_prologue, internal, hardware);
- }
+
+ *sb_bp = target_sp->CreateFuncRegexBreakpoint (module_list.get(), comp_unit_list.get(), regexp, symbol_language, skip_prologue, internal, hardware);
}
if (log)
- log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)",
+ log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\") => SBBreakpoint(%p)",
static_cast<void*>(target_sp.get()), symbol_name_regex,
- module_name, static_cast<void*>(sb_bp.get()));
+ static_cast<void*>(sb_bp.get()));
return sb_bp;
}
-lldb::SBBreakpoint
-SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex,
- const SBFileSpecList &module_list,
- const SBFileSpecList &comp_unit_list)
+SBBreakpoint
+SBTarget::BreakpointCreateByAddress (addr_t address)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBBreakpoint sb_bp;
TargetSP target_sp(GetSP());
- if (target_sp && symbol_name_regex && symbol_name_regex[0])
+ if (target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
- RegularExpression regexp(symbol_name_regex);
- const bool internal = false;
const bool hardware = false;
- const LazyBool skip_prologue = eLazyBoolCalculate;
-
- *sb_bp = target_sp->CreateFuncRegexBreakpoint (module_list.get(), comp_unit_list.get(), regexp, skip_prologue, internal, hardware);
+ *sb_bp = target_sp->CreateBreakpoint (address, false, hardware);
}
if (log)
- log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\") => SBBreakpoint(%p)",
- static_cast<void*>(target_sp.get()), symbol_name_regex,
+ log->Printf ("SBTarget(%p)::BreakpointCreateByAddress (address=%" PRIu64 ") => SBBreakpoint(%p)",
+ static_cast<void*>(target_sp.get()),
+ static_cast<uint64_t>(address),
static_cast<void*>(sb_bp.get()));
return sb_bp;
}
SBBreakpoint
-SBTarget::BreakpointCreateByAddress (addr_t address)
+SBTarget::BreakpointCreateBySBAddress (SBAddress &sb_address)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBBreakpoint sb_bp;
TargetSP target_sp(GetSP());
+ if (!sb_address.IsValid())
+ {
+ if (log)
+ log->Printf ("SBTarget(%p)::BreakpointCreateBySBAddress called with invalid address",
+ static_cast<void*>(target_sp.get()));
+ return sb_bp;
+ }
+
if (target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
const bool hardware = false;
- *sb_bp = target_sp->CreateBreakpoint (address, false, hardware);
+ *sb_bp = target_sp->CreateBreakpoint (sb_address.ref(), false, hardware);
}
if (log)
- log->Printf ("SBTarget(%p)::BreakpointCreateByAddress (address=%" PRIu64 ") => SBBreakpoint(%p)",
+ {
+ SBStream s;
+ sb_address.GetDescription(s);
+ log->Printf ("SBTarget(%p)::BreakpointCreateBySBAddress (address=%s) => SBBreakpoint(%p)",
static_cast<void*>(target_sp.get()),
- static_cast<uint64_t>(address),
+ s.GetData(),
static_cast<void*>(sb_bp.get()));
+ }
return sb_bp;
}
@@ -1131,7 +1176,7 @@ SBTarget::BreakpointCreateForException (lldb::LanguageType language,
if (log)
log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (Language: %s, catch: %s throw: %s) => SBBreakpoint(%p)",
static_cast<void*>(target_sp.get()),
- LanguageRuntime::GetNameForLanguageType(language),
+ Language::GetNameForLanguageType(language),
catch_bp ? "on" : "off", throw_bp ? "on" : "off",
static_cast<void*>(sb_bp.get()));
@@ -1344,7 +1389,7 @@ SBTarget::WatchAddress (lldb::addr_t addr, size_t size, bool read, bool write, S
// Target::CreateWatchpoint() is thread safe.
Error cw_error;
// This API doesn't take in a type, so we can't figure out what it is.
- ClangASTType *type = NULL;
+ CompilerType *type = NULL;
watchpoint_sp = target_sp->CreateWatchpoint(addr, size, type, watch_type, cw_error);
error.SetError(cw_error);
sb_watchpoint.SetSP (watchpoint_sp);
@@ -1398,7 +1443,7 @@ SBTarget::CreateValueFromAddress (const char *name, SBAddress addr, SBType type)
{
lldb::addr_t load_addr(addr.GetLoadAddress(*this));
ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false)));
- ClangASTType ast_type(type.GetSP()->GetClangASTType(true));
+ CompilerType ast_type(type.GetSP()->GetCompilerType(true));
new_value_sp = ValueObject::CreateValueObjectFromAddress(name, load_addr, exe_ctx, ast_type);
}
sb_value.SetSP(new_value_sp);
@@ -1425,7 +1470,7 @@ SBTarget::CreateValueFromData (const char *name, lldb::SBData data, lldb::SBType
{
DataExtractorSP extractor(*data);
ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false)));
- ClangASTType ast_type(type.GetSP()->GetClangASTType(true));
+ CompilerType ast_type(type.GetSP()->GetCompilerType(true));
new_value_sp = ValueObject::CreateValueObjectFromData(name, *extractor, exe_ctx, ast_type);
}
sb_value.SetSP(new_value_sp);
@@ -1806,7 +1851,7 @@ SBTarget::FindFirstType (const char* typename_cstr)
if (objc_decl_vendor->FindDecls(const_typename, true, 1, decls) > 0)
{
- if (ClangASTType type = ClangASTContext::GetTypeForDecl(decls[0]))
+ if (CompilerType type = ClangASTContext::GetTypeForDecl(decls[0]))
{
return SBType(type);
}
@@ -1886,7 +1931,7 @@ SBTarget::FindTypes (const char* typename_cstr)
{
for (clang::NamedDecl *decl : decls)
{
- if (ClangASTType type = ClangASTContext::GetTypeForDecl(decl))
+ if (CompilerType type = ClangASTContext::GetTypeForDecl(decl))
{
sb_type_list.Append(SBType(type));
}
diff --git a/contrib/llvm/tools/lldb/source/API/SBThread.cpp b/contrib/llvm/tools/lldb/source/API/SBThread.cpp
index 42b5c9a..2f3887e 100644
--- a/contrib/llvm/tools/lldb/source/API/SBThread.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBThread.cpp
@@ -747,7 +747,7 @@ SBThread::StepOver (lldb::RunMode stop_other_threads)
const LazyBool avoid_no_debug = eLazyBoolCalculate;
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
- sc.line_entry.range,
+ sc.line_entry,
sc,
stop_other_threads,
avoid_no_debug);
@@ -799,7 +799,7 @@ SBThread::StepInto (const char *target_name, lldb::RunMode stop_other_threads)
const LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate;
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
- sc.line_entry.range,
+ sc.line_entry,
sc,
target_name,
stop_other_threads,
@@ -826,7 +826,6 @@ SBThread::StepOut ()
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
-
if (log)
log->Printf ("SBThread(%p)::StepOut ()",
static_cast<void*>(exe_ctx.GetThreadPtr()));
@@ -861,6 +860,14 @@ SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame)
Mutex::Locker api_locker;
ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
+ if (!sb_frame.IsValid())
+ {
+ if (log)
+ log->Printf("SBThread(%p)::StepOutOfFrame passed an invalid frame, returning.",
+ static_cast<void*>(exe_ctx.GetThreadPtr()));
+ return;
+ }
+
StackFrameSP frame_sp (sb_frame.GetFrameSP());
if (log)
{
@@ -877,6 +884,13 @@ SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame)
bool abort_other_plans = false;
bool stop_other_threads = false;
Thread *thread = exe_ctx.GetThreadPtr();
+ if (sb_frame.GetThread().GetThreadID() != thread->GetID())
+ {
+ log->Printf("SBThread(%p)::StepOutOfFrame passed a frame from another thread (0x%" PRIx64 " vrs. 0x%" PRIx64 ", returning.",
+ static_cast<void*>(exe_ctx.GetThreadPtr()),
+ sb_frame.GetThread().GetThreadID(),
+ thread->GetID());
+ }
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut (abort_other_plans,
NULL,
diff --git a/contrib/llvm/tools/lldb/source/API/SBType.cpp b/contrib/llvm/tools/lldb/source/API/SBType.cpp
index 31a4eba..4922b49 100644
--- a/contrib/llvm/tools/lldb/source/API/SBType.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBType.cpp
@@ -13,24 +13,24 @@
#include "lldb/API/SBStream.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Mangled.h"
#include "lldb/Core/Stream.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeSystem.h"
-#include "clang/AST/Decl.h"
+#include "llvm/ADT/APSInt.h"
using namespace lldb;
using namespace lldb_private;
-using namespace clang;
SBType::SBType() :
m_opaque_sp()
{
}
-SBType::SBType (const ClangASTType &type) :
- m_opaque_sp(new TypeImpl(ClangASTType(type.GetASTContext(),
+SBType::SBType (const CompilerType &type) :
+ m_opaque_sp(new TypeImpl(CompilerType(type.GetTypeSystem(),
type.GetOpaqueQualType())))
{
}
@@ -143,7 +143,7 @@ SBType::GetByteSize()
if (!IsValid())
return 0;
- return m_opaque_sp->GetClangASTType(false).GetByteSize(nullptr);
+ return m_opaque_sp->GetCompilerType(false).GetByteSize(nullptr);
}
@@ -152,7 +152,7 @@ SBType::IsPointerType()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType(true).IsPointerType();
+ return m_opaque_sp->GetCompilerType(true).IsPointerType();
}
bool
@@ -160,7 +160,7 @@ SBType::IsArrayType()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType(true).IsArrayType(nullptr, nullptr, nullptr);
+ return m_opaque_sp->GetCompilerType(true).IsArrayType(nullptr, nullptr, nullptr);
}
bool
@@ -168,7 +168,7 @@ SBType::IsVectorType()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType(true).IsVectorType(nullptr, nullptr);
+ return m_opaque_sp->GetCompilerType(true).IsVectorType(nullptr, nullptr);
}
bool
@@ -176,7 +176,7 @@ SBType::IsReferenceType()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType(true).IsReferenceType();
+ return m_opaque_sp->GetCompilerType(true).IsReferenceType();
}
SBType
@@ -225,7 +225,7 @@ SBType::GetArrayElementType()
{
if (!IsValid())
return SBType();
- return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetClangASTType(true).GetArrayElementType())));
+ return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetCompilerType(true).GetArrayElementType())));
}
SBType
@@ -234,8 +234,8 @@ SBType::GetVectorElementType ()
SBType type_sb;
if (IsValid())
{
- ClangASTType vector_element_type;
- if (m_opaque_sp->GetClangASTType(true).IsVectorType(&vector_element_type, nullptr))
+ CompilerType vector_element_type;
+ if (m_opaque_sp->GetCompilerType(true).IsVectorType(&vector_element_type, nullptr))
type_sb.SetSP(TypeImplSP(new TypeImpl(vector_element_type)));
}
return type_sb;
@@ -246,7 +246,7 @@ SBType::IsFunctionType ()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType(true).IsFunctionType();
+ return m_opaque_sp->GetCompilerType(true).IsFunctionType();
}
bool
@@ -254,7 +254,7 @@ SBType::IsPolymorphicClass ()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType(true).IsPolymorphicClass();
+ return m_opaque_sp->GetCompilerType(true).IsPolymorphicClass();
}
bool
@@ -262,7 +262,15 @@ SBType::IsTypedefType ()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType(true).IsTypedefType();
+ return m_opaque_sp->GetCompilerType(true).IsTypedefType();
+}
+
+bool
+SBType::IsAnonymousType ()
+{
+ if (!IsValid())
+ return false;
+ return m_opaque_sp->GetCompilerType(true).IsAnonymousType();
}
lldb::SBType
@@ -270,9 +278,9 @@ SBType::GetFunctionReturnType ()
{
if (IsValid())
{
- ClangASTType return_clang_type (m_opaque_sp->GetClangASTType(true).GetFunctionReturnType());
- if (return_clang_type.IsValid())
- return SBType(return_clang_type);
+ CompilerType return_type (m_opaque_sp->GetCompilerType(true).GetFunctionReturnType());
+ if (return_type.IsValid())
+ return SBType(return_type);
}
return lldb::SBType();
}
@@ -283,7 +291,7 @@ SBType::GetFunctionArgumentTypes ()
SBTypeList sb_type_list;
if (IsValid())
{
- ClangASTType func_type(m_opaque_sp->GetClangASTType(true));
+ CompilerType func_type(m_opaque_sp->GetCompilerType(true));
size_t count = func_type.GetNumberOfFunctionArguments();
for (size_t i = 0;
i < count;
@@ -300,7 +308,7 @@ SBType::GetNumberOfMemberFunctions ()
{
if (IsValid())
{
- return m_opaque_sp->GetClangASTType(true).GetNumMemberFunctions();
+ return m_opaque_sp->GetCompilerType(true).GetNumMemberFunctions();
}
return 0;
}
@@ -310,7 +318,7 @@ SBType::GetMemberFunctionAtIndex (uint32_t idx)
{
SBTypeMemberFunction sb_func_type;
if (IsValid())
- sb_func_type.reset(new TypeMemberFunctionImpl(m_opaque_sp->GetClangASTType(true).GetMemberFunctionAtIndex(idx)));
+ sb_func_type.reset(new TypeMemberFunctionImpl(m_opaque_sp->GetCompilerType(true).GetMemberFunctionAtIndex(idx)));
return sb_func_type;
}
@@ -335,15 +343,15 @@ lldb::BasicType
SBType::GetBasicType()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType(false).GetBasicTypeEnumeration ();
+ return m_opaque_sp->GetCompilerType(false).GetBasicTypeEnumeration ();
return eBasicTypeInvalid;
}
SBType
SBType::GetBasicType(lldb::BasicType basic_type)
{
- if (IsValid())
- return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetClangASTContext(false), basic_type));
+ if (IsValid() && m_opaque_sp->IsValid())
+ return SBType(m_opaque_sp->GetTypeSystem(false)->GetBasicTypeFromAST(basic_type));
return SBType();
}
@@ -351,7 +359,7 @@ uint32_t
SBType::GetNumberOfDirectBaseClasses ()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType(true).GetNumDirectBaseClasses();
+ return m_opaque_sp->GetCompilerType(true).GetNumDirectBaseClasses();
return 0;
}
@@ -359,7 +367,7 @@ uint32_t
SBType::GetNumberOfVirtualBaseClasses ()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType(true).GetNumVirtualBaseClasses();
+ return m_opaque_sp->GetCompilerType(true).GetNumVirtualBaseClasses();
return 0;
}
@@ -367,7 +375,7 @@ uint32_t
SBType::GetNumberOfFields ()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType(true).GetNumFields();
+ return m_opaque_sp->GetCompilerType(true).GetNumFields();
return 0;
}
@@ -394,16 +402,10 @@ SBType::GetDirectBaseClassAtIndex (uint32_t idx)
SBTypeMember sb_type_member;
if (IsValid())
{
- ClangASTType this_type (m_opaque_sp->GetClangASTType (true));
- if (this_type.IsValid())
- {
- uint32_t bit_offset = 0;
- ClangASTType base_class_type (this_type.GetDirectBaseClassAtIndex(idx, &bit_offset));
- if (base_class_type.IsValid())
- {
- sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset));
- }
- }
+ uint32_t bit_offset = 0;
+ CompilerType base_class_type = m_opaque_sp->GetCompilerType (true).GetDirectBaseClassAtIndex(idx, &bit_offset);
+ if (base_class_type.IsValid())
+ sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset));
}
return sb_type_member;
@@ -415,16 +417,10 @@ SBType::GetVirtualBaseClassAtIndex (uint32_t idx)
SBTypeMember sb_type_member;
if (IsValid())
{
- ClangASTType this_type (m_opaque_sp->GetClangASTType (true));
- if (this_type.IsValid())
- {
- uint32_t bit_offset = 0;
- ClangASTType base_class_type (this_type.GetVirtualBaseClassAtIndex(idx, &bit_offset));
- if (base_class_type.IsValid())
- {
- sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset));
- }
- }
+ uint32_t bit_offset = 0;
+ CompilerType base_class_type = m_opaque_sp->GetCompilerType (true).GetVirtualBaseClassAtIndex(idx, &bit_offset);
+ if (base_class_type.IsValid())
+ sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset));
}
return sb_type_member;
}
@@ -435,16 +431,14 @@ SBType::GetEnumMembers ()
SBTypeEnumMemberList sb_enum_member_list;
if (IsValid())
{
- const clang::EnumDecl *enum_decl = m_opaque_sp->GetClangASTType(true).GetFullyUnqualifiedType().GetAsEnumDecl();
- if (enum_decl)
+ CompilerType this_type (m_opaque_sp->GetCompilerType (true));
+ if (this_type.IsValid())
{
- clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
- for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
- {
- SBTypeEnumMember enum_member;
- enum_member.reset(new TypeEnumMemberImpl(*enum_pos, ClangASTType(m_opaque_sp->GetClangASTContext(true), enum_decl->getIntegerType())));
+ this_type.ForEachEnumerator([&sb_enum_member_list] (const CompilerType &integer_type, const ConstString &name, const llvm::APSInt &value) -> bool {
+ SBTypeEnumMember enum_member (lldb::TypeEnumMemberImplSP (new TypeEnumMemberImpl(lldb::TypeImplSP(new TypeImpl(integer_type)), name, value)));
sb_enum_member_list.Append(enum_member);
- }
+ return true; // Keep iterating
+ });
}
}
return sb_enum_member_list;
@@ -456,14 +450,14 @@ SBType::GetFieldAtIndex (uint32_t idx)
SBTypeMember sb_type_member;
if (IsValid())
{
- ClangASTType this_type (m_opaque_sp->GetClangASTType (false));
+ CompilerType this_type (m_opaque_sp->GetCompilerType (false));
if (this_type.IsValid())
{
uint64_t bit_offset = 0;
uint32_t bitfield_bit_size = 0;
bool is_bitfield = false;
std::string name_sstr;
- ClangASTType field_type (this_type.GetFieldAtIndex (idx,
+ CompilerType field_type (this_type.GetFieldAtIndex (idx,
name_sstr,
&bit_offset,
&bitfield_bit_size,
@@ -489,7 +483,7 @@ SBType::IsTypeComplete()
{
if (!IsValid())
return false;
- return m_opaque_sp->GetClangASTType(false).IsCompleteType();
+ return m_opaque_sp->GetCompilerType(false).IsCompleteType();
}
uint32_t
@@ -497,7 +491,7 @@ SBType::GetTypeFlags ()
{
if (!IsValid())
return 0;
- return m_opaque_sp->GetClangASTType(true).GetTypeInfo();
+ return m_opaque_sp->GetCompilerType(true).GetTypeInfo();
}
const char*
@@ -520,7 +514,7 @@ lldb::TypeClass
SBType::GetTypeClass ()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType(true).GetTypeClass();
+ return m_opaque_sp->GetCompilerType(true).GetTypeClass();
return lldb::eTypeClassInvalid;
}
@@ -528,7 +522,7 @@ uint32_t
SBType::GetNumberOfTemplateArguments ()
{
if (IsValid())
- return m_opaque_sp->GetClangASTType(false).GetNumTemplateArguments();
+ return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments();
return 0;
}
@@ -538,7 +532,7 @@ SBType::GetTemplateArgumentType (uint32_t idx)
if (IsValid())
{
TemplateArgumentKind kind = eTemplateArgumentKindNull;
- ClangASTType template_arg_type = m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind);
+ CompilerType template_arg_type = m_opaque_sp->GetCompilerType(false).GetTemplateArgument(idx, kind);
if (template_arg_type.IsValid())
return SBType(template_arg_type);
}
@@ -551,7 +545,7 @@ SBType::GetTemplateArgumentKind (uint32_t idx)
{
TemplateArgumentKind kind = eTemplateArgumentKindNull;
if (IsValid())
- m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind);
+ m_opaque_sp->GetCompilerType(false).GetTemplateArgument(idx, kind);
return kind;
}
@@ -791,6 +785,30 @@ SBTypeMemberFunction::GetName ()
return NULL;
}
+const char *
+SBTypeMemberFunction::GetDemangledName ()
+{
+ if (m_opaque_sp)
+ {
+ ConstString mangled_str = m_opaque_sp->GetMangledName();
+ if (mangled_str)
+ {
+ Mangled mangled(mangled_str, true);
+ return mangled.GetDemangledName(mangled.GuessLanguage()).GetCString();
+ }
+ }
+ return NULL;
+}
+
+const char *
+SBTypeMemberFunction::GetMangledName()
+{
+ if (m_opaque_sp)
+ return m_opaque_sp->GetMangledName().GetCString();
+ return NULL;
+}
+
+
SBType
SBTypeMemberFunction::GetType ()
{
diff --git a/contrib/llvm/tools/lldb/source/API/SBTypeCategory.cpp b/contrib/llvm/tools/lldb/source/API/SBTypeCategory.cpp
index ee9553c..33dada8 100644
--- a/contrib/llvm/tools/lldb/source/API/SBTypeCategory.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBTypeCategory.cpp
@@ -79,6 +79,29 @@ SBTypeCategory::GetName()
return m_opaque_sp->GetName();
}
+lldb::LanguageType
+SBTypeCategory::GetLanguageAtIndex (uint32_t idx)
+{
+ if (IsValid())
+ return m_opaque_sp->GetLanguageAtIndex(idx);
+ return lldb::eLanguageTypeUnknown;
+}
+
+uint32_t
+SBTypeCategory::GetNumLanguages ()
+{
+ if (IsValid())
+ return m_opaque_sp->GetNumLanguages();
+ return 0;
+}
+
+void
+SBTypeCategory::AddLanguage (lldb::LanguageType language)
+{
+ if (IsValid())
+ m_opaque_sp->AddLanguage(language);
+}
+
uint32_t
SBTypeCategory::GetNumFormats ()
{
@@ -157,7 +180,7 @@ SBTypeCategory::GetFilterForType (SBTypeNameSpecifier spec)
if (!spec.IsValid())
return SBTypeFilter();
- lldb::SyntheticChildrenSP children_sp;
+ lldb::TypeFilterImplSP children_sp;
if (spec.IsRegex())
m_opaque_sp->GetRegexTypeFiltersContainer()->GetExact(ConstString(spec.GetName()), children_sp);
diff --git a/contrib/llvm/tools/lldb/source/API/SBTypeEnumMember.cpp b/contrib/llvm/tools/lldb/source/API/SBTypeEnumMember.cpp
index 47c57dd..c23f7ea 100644
--- a/contrib/llvm/tools/lldb/source/API/SBTypeEnumMember.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBTypeEnumMember.cpp
@@ -12,12 +12,11 @@
#include "lldb/API/SBTypeEnumMember.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Stream.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Type.h"
using namespace lldb;
using namespace lldb_private;
-using namespace clang;
SBTypeEnumMember::SBTypeEnumMember() :
m_opaque_sp()
diff --git a/contrib/llvm/tools/lldb/source/API/SBTypeNameSpecifier.cpp b/contrib/llvm/tools/lldb/source/API/SBTypeNameSpecifier.cpp
index c587471..6f68010 100644
--- a/contrib/llvm/tools/lldb/source/API/SBTypeNameSpecifier.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBTypeNameSpecifier.cpp
@@ -34,7 +34,7 @@ SBTypeNameSpecifier::SBTypeNameSpecifier (SBType type) :
m_opaque_sp()
{
if (type.IsValid())
- m_opaque_sp = TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(type.m_opaque_sp->GetClangASTType(true)));
+ m_opaque_sp = TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(type.m_opaque_sp->GetCompilerType(true)));
}
SBTypeNameSpecifier::SBTypeNameSpecifier (const lldb::SBTypeNameSpecifier &rhs) :
@@ -65,7 +65,7 @@ SBTypeNameSpecifier::GetType ()
{
if (!IsValid())
return SBType();
- lldb_private::ClangASTType c_type = m_opaque_sp->GetClangASTType();
+ lldb_private::CompilerType c_type = m_opaque_sp->GetCompilerType();
if (c_type.IsValid())
return SBType(c_type);
return SBType();
diff --git a/contrib/llvm/tools/lldb/source/API/SBTypeSummary.cpp b/contrib/llvm/tools/lldb/source/API/SBTypeSummary.cpp
index 2c11454..2985b76 100644
--- a/contrib/llvm/tools/lldb/source/API/SBTypeSummary.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBTypeSummary.cpp
@@ -8,16 +8,15 @@
//===----------------------------------------------------------------------===//
#include "lldb/API/SBTypeSummary.h"
-
#include "lldb/API/SBStream.h"
-
+#include "lldb/API/SBValue.h"
#include "lldb/DataFormatters/DataVisualization.h"
+#include "llvm/Support/Casting.h"
+
using namespace lldb;
using namespace lldb_private;
-#ifndef LLDB_DISABLE_PYTHON
-
SBTypeSummaryOptions::SBTypeSummaryOptions()
{
m_opaque_ap.reset(new TypeSummaryOptions());
@@ -147,6 +146,28 @@ SBTypeSummary::CreateWithScriptCode (const char* data, uint32_t options)
return SBTypeSummary(TypeSummaryImplSP(new ScriptSummaryFormat(options, "", data)));
}
+SBTypeSummary
+SBTypeSummary::CreateWithCallback (FormatCallback cb, uint32_t options, const char* description)
+{
+ SBTypeSummary retval;
+ if (cb)
+ {
+ retval.SetSP(TypeSummaryImplSP(new CXXFunctionSummaryFormat(options,
+ [cb] (ValueObject& valobj, Stream& stm, const TypeSummaryOptions& opt) -> bool {
+ SBStream stream;
+ SBValue sb_value(valobj.GetSP());
+ SBTypeSummaryOptions options(&opt);
+ if (!cb(sb_value, options, stream))
+ return false;
+ stm.Write(stream.GetData(), stream.GetSize());
+ return true;
+ },
+ description ? description : "callback summary formatter")));
+ }
+
+ return retval;
+}
+
SBTypeSummary::SBTypeSummary (const lldb::SBTypeSummary &rhs) :
m_opaque_sp(rhs.m_opaque_sp)
{
@@ -167,9 +188,8 @@ SBTypeSummary::IsFunctionCode()
{
if (!IsValid())
return false;
- if (m_opaque_sp->IsScripted())
+ if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
{
- ScriptSummaryFormat* script_summary_ptr = (ScriptSummaryFormat*)m_opaque_sp.get();
const char* ftext = script_summary_ptr->GetPythonScript();
return (ftext && *ftext != 0);
}
@@ -181,9 +201,8 @@ SBTypeSummary::IsFunctionName()
{
if (!IsValid())
return false;
- if (m_opaque_sp->IsScripted())
+ if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
{
- ScriptSummaryFormat* script_summary_ptr = (ScriptSummaryFormat*)m_opaque_sp.get();
const char* ftext = script_summary_ptr->GetPythonScript();
return (!ftext || *ftext == 0);
}
@@ -196,10 +215,7 @@ SBTypeSummary::IsSummaryString()
if (!IsValid())
return false;
- if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback)
- return false;
-
- return !m_opaque_sp->IsScripted();
+ return m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eSummaryString;
}
const char*
@@ -207,22 +223,17 @@ SBTypeSummary::GetData ()
{
if (!IsValid())
return NULL;
- if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback)
- return NULL;
- if (m_opaque_sp->IsScripted())
+ if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
{
- ScriptSummaryFormat* script_summary_ptr = (ScriptSummaryFormat*)m_opaque_sp.get();
const char* fname = script_summary_ptr->GetFunctionName();
const char* ftext = script_summary_ptr->GetPythonScript();
if (ftext && *ftext)
return ftext;
return fname;
}
- else
- {
- StringSummaryFormat* string_summary_ptr = (StringSummaryFormat*)m_opaque_sp.get();
+ else if (StringSummaryFormat* string_summary_ptr = llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
return string_summary_ptr->GetSummaryString();
- }
+ return nullptr;
}
uint32_t
@@ -246,9 +257,10 @@ SBTypeSummary::SetSummaryString (const char* data)
{
if (!IsValid())
return;
- if (m_opaque_sp->IsScripted() || (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback))
+ if (!llvm::isa<StringSummaryFormat>(m_opaque_sp.get()))
ChangeSummaryType(false);
- ((StringSummaryFormat*)m_opaque_sp.get())->SetSummaryString(data);
+ if (StringSummaryFormat* string_summary_ptr = llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
+ string_summary_ptr->SetSummaryString(data);
}
void
@@ -256,9 +268,10 @@ SBTypeSummary::SetFunctionName (const char* data)
{
if (!IsValid())
return;
- if (!m_opaque_sp->IsScripted())
+ if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
ChangeSummaryType(true);
- ((ScriptSummaryFormat*)m_opaque_sp.get())->SetFunctionName(data);
+ if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
+ script_summary_ptr->SetFunctionName(data);
}
void
@@ -266,9 +279,10 @@ SBTypeSummary::SetFunctionCode (const char* data)
{
if (!IsValid())
return;
- if (!m_opaque_sp->IsScripted())
+ if (!llvm::isa<ScriptSummaryFormat>(m_opaque_sp.get()))
ChangeSummaryType(true);
- ((ScriptSummaryFormat*)m_opaque_sp.get())->SetPythonScript(data);
+ if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
+ script_summary_ptr->SetPythonScript(data);
}
bool
@@ -284,6 +298,15 @@ SBTypeSummary::GetDescription (lldb::SBStream &description,
}
}
+bool
+SBTypeSummary::DoesPrintValue (lldb::SBValue value)
+{
+ if (!IsValid())
+ return false;
+ lldb::ValueObjectSP value_sp = value.GetSP();
+ return m_opaque_sp->DoesPrintValue(value_sp.get());
+}
+
lldb::SBTypeSummary &
SBTypeSummary::operator = (const lldb::SBTypeSummary &rhs)
{
@@ -305,36 +328,44 @@ SBTypeSummary::operator == (lldb::SBTypeSummary &rhs)
bool
SBTypeSummary::IsEqualTo (lldb::SBTypeSummary &rhs)
{
- if (IsValid() == false)
- return !rhs.IsValid();
-
- if (m_opaque_sp->GetType() != rhs.m_opaque_sp->GetType())
- return false;
-
- if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback)
+ if (IsValid())
{
- lldb_private::CXXFunctionSummaryFormat *self_cxx = (lldb_private::CXXFunctionSummaryFormat*)m_opaque_sp.get();
- lldb_private::CXXFunctionSummaryFormat *other_cxx = (lldb_private::CXXFunctionSummaryFormat*)rhs.m_opaque_sp.get();
- return (self_cxx->m_impl == other_cxx->m_impl);
+ // valid and invalid are different
+ if (!rhs.IsValid())
+ return false;
+ }
+ else
+ {
+ // invalid and valid are different
+ if (rhs.IsValid())
+ return false;
+ else
+ // both invalid are the same
+ return true;
}
-
- if (m_opaque_sp->IsScripted() != rhs.m_opaque_sp->IsScripted())
- return false;
-
- if (IsFunctionCode() != rhs.IsFunctionCode())
- return false;
-
- if (IsSummaryString() != rhs.IsSummaryString())
- return false;
- if (IsFunctionName() != rhs.IsFunctionName())
- return false;
-
- if ( GetData() == NULL || rhs.GetData() == NULL || strcmp(GetData(), rhs.GetData()) )
+ if (m_opaque_sp->GetKind() != rhs.m_opaque_sp->GetKind())
return false;
- return GetOptions() == rhs.GetOptions();
+ switch (m_opaque_sp->GetKind())
+ {
+ case TypeSummaryImpl::Kind::eCallback:
+ return llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get()) == llvm::dyn_cast<CXXFunctionSummaryFormat>(rhs.m_opaque_sp.get());
+ case TypeSummaryImpl::Kind::eScript:
+ if (IsFunctionCode() != rhs.IsFunctionCode())
+ return false;
+ if (IsFunctionName() != rhs.IsFunctionName())
+ return false;
+ return GetOptions() == rhs.GetOptions();
+ case TypeSummaryImpl::Kind::eSummaryString:
+ if (IsSummaryString() != rhs.IsSummaryString())
+ return false;
+ return GetOptions() == rhs.GetOptions();
+ case TypeSummaryImpl::Kind::eInternal:
+ return (m_opaque_sp.get() == rhs.m_opaque_sp.get());
+ }
+ return false;
}
bool
@@ -373,29 +404,27 @@ SBTypeSummary::CopyOnWrite_Impl()
TypeSummaryImplSP new_sp;
- if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback)
+ if (CXXFunctionSummaryFormat* current_summary_ptr = llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get()))
{
- CXXFunctionSummaryFormat* current_summary_ptr = (CXXFunctionSummaryFormat*)m_opaque_sp.get();
new_sp = TypeSummaryImplSP(new CXXFunctionSummaryFormat(GetOptions(),
current_summary_ptr->m_impl,
current_summary_ptr->m_description.c_str()));
}
- else if (m_opaque_sp->IsScripted())
+ else if (ScriptSummaryFormat* current_summary_ptr = llvm::dyn_cast<ScriptSummaryFormat>(m_opaque_sp.get()))
{
- ScriptSummaryFormat* current_summary_ptr = (ScriptSummaryFormat*)m_opaque_sp.get();
new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(),
current_summary_ptr->GetFunctionName(),
current_summary_ptr->GetPythonScript()));
}
- else {
- StringSummaryFormat* current_summary_ptr = (StringSummaryFormat*)m_opaque_sp.get();
+ else if (StringSummaryFormat* current_summary_ptr = llvm::dyn_cast<StringSummaryFormat>(m_opaque_sp.get()))
+ {
new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(),
current_summary_ptr->GetSummaryString()));
}
-
+
SetSP(new_sp);
- return true;
+ return nullptr != new_sp.get();
}
bool
@@ -406,9 +435,9 @@ SBTypeSummary::ChangeSummaryType (bool want_script)
TypeSummaryImplSP new_sp;
- if (want_script == m_opaque_sp->IsScripted())
+ if (want_script == (m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eScript))
{
- if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback && !want_script)
+ if (m_opaque_sp->GetKind() == lldb_private::TypeSummaryImpl::Kind::eCallback && !want_script)
new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), ""));
else
return CopyOnWrite_Impl();
@@ -426,5 +455,3 @@ SBTypeSummary::ChangeSummaryType (bool want_script)
return true;
}
-
-#endif // LLDB_DISABLE_PYTHON
diff --git a/contrib/llvm/tools/lldb/source/API/SBValue.cpp b/contrib/llvm/tools/lldb/source/API/SBValue.cpp
index ef62c30..a8584c5 100644
--- a/contrib/llvm/tools/lldb/source/API/SBValue.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBValue.cpp
@@ -632,7 +632,6 @@ SBValue::GetValueDidChange ()
return result;
}
-#ifndef LLDB_DISABLE_PYTHON
const char *
SBValue::GetSummary ()
{
@@ -681,7 +680,6 @@ SBValue::GetSummary (lldb::SBStream& stream,
}
return cstr;
}
-#endif // LLDB_DISABLE_PYTHON
const char *
SBValue::GetLocation ()
@@ -753,7 +751,6 @@ SBValue::GetTypeFormat ()
return format;
}
-#ifndef LLDB_DISABLE_PYTHON
lldb::SBTypeSummary
SBValue::GetTypeSummary ()
{
@@ -771,7 +768,6 @@ SBValue::GetTypeSummary ()
}
return summary;
}
-#endif // LLDB_DISABLE_PYTHON
lldb::SBTypeFilter
SBValue::GetTypeFilter ()
@@ -831,7 +827,7 @@ SBValue::CreateChildAtOffset (const char *name, uint32_t offset, SBType type)
TypeImplSP type_sp (type.GetSP());
if (type.IsValid())
{
- sb_value.SetSP(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetClangASTType(false), true),GetPreferDynamicValue(),GetPreferSyntheticValue(), name);
+ sb_value.SetSP(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetCompilerType(false), true),GetPreferDynamicValue(),GetPreferSyntheticValue(), name);
}
}
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -856,7 +852,7 @@ SBValue::Cast (SBType type)
lldb::ValueObjectSP value_sp(GetSP(locker));
TypeImplSP type_sp (type.GetSP());
if (value_sp && type_sp)
- sb_value.SetSP(value_sp->Cast(type_sp->GetClangASTType(false)),GetPreferDynamicValue(),GetPreferSyntheticValue());
+ sb_value.SetSP(value_sp->Cast(type_sp->GetCompilerType(false)),GetPreferDynamicValue(),GetPreferSyntheticValue());
return sb_value;
}
@@ -907,7 +903,7 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType s
lldb::TypeImplSP type_impl_sp (sb_type.GetSP());
if (value_sp && type_impl_sp)
{
- ClangASTType ast_type(type_impl_sp->GetClangASTType(true));
+ CompilerType ast_type(type_impl_sp->GetCompilerType(true));
ExecutionContext exe_ctx (value_sp->GetExecutionContextRef());
new_value_sp = ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, ast_type);
}
@@ -936,7 +932,7 @@ SBValue::CreateValueFromData (const char* name, SBData data, SBType type)
if (value_sp)
{
ExecutionContext exe_ctx (value_sp->GetExecutionContextRef());
- new_value_sp = ValueObject::CreateValueObjectFromData(name, **data, exe_ctx, type.GetSP()->GetClangASTType(true));
+ new_value_sp = ValueObject::CreateValueObjectFromData(name, **data, exe_ctx, type.GetSP()->GetCompilerType(true));
new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);
}
sb_value.SetSP(new_value_sp);
@@ -1270,22 +1266,27 @@ SBValue::IsRuntimeSupportValue ()
uint32_t
SBValue::GetNumChildren ()
{
+ return GetNumChildren (UINT32_MAX);
+}
+
+uint32_t
+SBValue::GetNumChildren (uint32_t max)
+{
uint32_t num_children = 0;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
- num_children = value_sp->GetNumChildren();
+ num_children = value_sp->GetNumChildren(max);
if (log)
- log->Printf ("SBValue(%p)::GetNumChildren () => %u",
- static_cast<void*>(value_sp.get()), num_children);
+ log->Printf ("SBValue(%p)::GetNumChildren (%u) => %u",
+ static_cast<void*>(value_sp.get()), max, num_children);
return num_children;
}
-
SBValue
SBValue::Dereference ()
{
@@ -1306,22 +1307,11 @@ SBValue::Dereference ()
return sb_value;
}
+// Deprecated - please use GetType().IsPointerType() instead.
bool
SBValue::TypeIsPointerType ()
{
- bool is_ptr_type = false;
-
- ValueLocker locker;
- lldb::ValueObjectSP value_sp(GetSP(locker));
- if (value_sp)
- is_ptr_type = value_sp->IsPointerType();
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- if (log)
- log->Printf ("SBValue(%p)::TypeIsPointerType () => %i",
- static_cast<void*>(value_sp.get()), is_ptr_type);
-
- return is_ptr_type;
+ return GetType().IsPointerType();
}
void *
@@ -1330,7 +1320,7 @@ SBValue::GetOpaqueType()
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
if (value_sp)
- return value_sp->GetClangType().GetOpaqueQualType();
+ return value_sp->GetCompilerType().GetOpaqueQualType();
return NULL;
}
@@ -1435,7 +1425,10 @@ lldb::ValueObjectSP
SBValue::GetSP (ValueLocker &locker) const
{
if (!m_opaque_sp || !m_opaque_sp->IsValid())
+ {
+ locker.GetError().SetErrorString("No value");
return ValueObjectSP();
+ }
return locker.GetLockedSP(*m_opaque_sp.get());
}
@@ -1823,7 +1816,7 @@ SBValue::Watch (bool resolve_location, bool read, bool write, SBError &error)
watch_type |= LLDB_WATCH_TYPE_WRITE;
Error rc;
- ClangASTType type (value_sp->GetClangType());
+ CompilerType type (value_sp->GetCompilerType());
WatchpointSP watchpoint_sp = target_sp->CreateWatchpoint(addr, byte_size, &type, watch_type, rc);
error.SetError(rc);
diff --git a/contrib/llvm/tools/lldb/source/API/SBValueList.cpp b/contrib/llvm/tools/lldb/source/API/SBValueList.cpp
index 71fabe0..5461b05 100644
--- a/contrib/llvm/tools/lldb/source/API/SBValueList.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SBValueList.cpp
@@ -39,7 +39,7 @@ public:
return *this;
m_values = rhs.m_values;
return *this;
- };
+ }
uint32_t
GetSize ()
@@ -297,5 +297,3 @@ SBValueList::ref ()
CreateIfNeeded();
return *m_opaque_ap.get();
}
-
-
diff --git a/contrib/llvm/tools/lldb/source/API/SystemInitializerFull.cpp b/contrib/llvm/tools/lldb/source/API/SystemInitializerFull.cpp
index 80a87d4..1616b47 100644
--- a/contrib/llvm/tools/lldb/source/API/SystemInitializerFull.cpp
+++ b/contrib/llvm/tools/lldb/source/API/SystemInitializerFull.cpp
@@ -7,12 +7,25 @@
//
//===----------------------------------------------------------------------===//
+#if !defined(LLDB_DISABLE_PYTHON)
+#include "Plugins/ScriptInterpreter/Python/lldb-python.h"
+#endif
+
#include "lldb/API/SystemInitializerFull.h"
+#include "lldb/API/SBCommandInterpreter.h"
+
+#if !defined(LLDB_DISABLE_PYTHON)
+#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
+#endif
+
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Timer.h"
#include "lldb/Host/Host.h"
#include "lldb/Initialization/SystemInitializerCommon.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/GoASTContext.h"
#include "Plugins/ABI/SysV-arm/ABISysV_arm.h"
#include "Plugins/ABI/SysV-arm64/ABISysV_arm64.h"
@@ -27,11 +40,13 @@
#include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h"
#include "Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h"
#include "Plugins/JITLoader/GDB/JITLoaderGDB.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h"
#include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h"
#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"
#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
+#include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h"
#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
@@ -42,6 +57,10 @@
#if defined(__APPLE__)
#include "Plugins/Process/mach-core/ProcessMachCore.h"
#include "Plugins/Process/MacOSX-Kernel/ProcessKDP.h"
+#include "Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h"
+#include "Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h"
+#include "Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h"
+#include "Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h"
#endif
#if defined(__FreeBSD__)
@@ -50,11 +69,8 @@
#if defined(_MSC_VER)
#include "lldb/Host/windows/windows.h"
-#include "Plugins/Process/Windows/ProcessWindows.h"
-#endif
-
-#if !defined(LLDB_DISABLE_PYTHON)
-#include "lldb/Interpreter/ScriptInterpreterPython.h"
+#include "Plugins/Process/Windows/Live/ProcessWindowsLive.h"
+#include "Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h"
#endif
#include "llvm/Support/TargetSelect.h"
@@ -66,9 +82,19 @@ using namespace lldb_private;
#ifndef LLDB_DISABLE_PYTHON
// Defined in the SWIG source file
-extern "C" void
+#if PY_MAJOR_VERSION >= 3
+extern "C" PyObject*
+PyInit__lldb(void);
+
+#define LLDBSwigPyInit PyInit__lldb
+
+#else
+extern "C" void
init_lldb(void);
+#define LLDBSwigPyInit init_lldb
+#endif
+
// these are the Pythonic implementations of the required callbacks
// these are scripting-language specific, which is why they belong here
// we still need to use function pointers to them instead of relying
@@ -116,7 +142,7 @@ LLDBSWIGPythonCallThreadPlan (void *implementor,
bool &got_error);
extern "C" size_t
-LLDBSwigPython_CalculateNumChildren (void *implementor);
+LLDBSwigPython_CalculateNumChildren (void *implementor, uint32_t max);
extern "C" void *
LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx);
@@ -213,9 +239,17 @@ SystemInitializerFull::~SystemInitializerFull()
void
SystemInitializerFull::Initialize()
{
+ SystemInitializerCommon::Initialize();
+ ScriptInterpreterNone::Initialize();
+
+#if !defined(LLDB_DISABLE_PYTHON)
InitializeSWIG();
- SystemInitializerCommon::Initialize();
+ // ScriptInterpreterPython::Initialize() depends on things like HostInfo being initialized
+ // so it can compute the python directory etc, so we need to do this after
+ // SystemInitializerCommon::Initialize().
+ ScriptInterpreterPython::Initialize();
+#endif
// Initialize LLVM and Clang
llvm::InitializeAllTargets();
@@ -223,6 +257,9 @@ SystemInitializerFull::Initialize()
llvm::InitializeAllTargetMCs();
llvm::InitializeAllDisassemblers();
+ ClangASTContext::Initialize();
+ GoASTContext::Initialize();
+
ABISysV_arm::Initialize();
ABISysV_arm64::Initialize();
ABISysV_i386::Initialize();
@@ -235,6 +272,9 @@ SystemInitializerFull::Initialize()
JITLoaderGDB::Initialize();
ProcessElfCore::Initialize();
+#if defined(_MSC_VER)
+ ProcessWinMiniDump::Initialize();
+#endif
MemoryHistoryASan::Initialize();
AddressSanitizerRuntime::Initialize();
@@ -247,8 +287,10 @@ SystemInitializerFull::Initialize()
SymbolFileDWARFDebugMap::Initialize();
ItaniumABILanguageRuntime::Initialize();
+ CPlusPlusLanguage::Initialize();
+
#if defined(_MSC_VER)
- ProcessWindows::Initialize();
+ ProcessWindowsLive::Initialize();
#endif
#if defined(__FreeBSD__)
ProcessFreeBSD::Initialize();
@@ -257,6 +299,10 @@ SystemInitializerFull::Initialize()
SymbolVendorMacOSX::Initialize();
ProcessKDP::Initialize();
ProcessMachCore::Initialize();
+ PlatformAppleTVSimulator::Initialize();
+ PlatformAppleWatchSimulator::Initialize();
+ PlatformRemoteAppleTV::Initialize();
+ PlatformRemoteAppleWatch::Initialize();
#endif
//----------------------------------------------------------------------
// Platform agnostic plugins
@@ -279,7 +325,7 @@ void SystemInitializerFull::InitializeSWIG()
{
#if !defined(LLDB_DISABLE_PYTHON)
ScriptInterpreterPython::InitializeInterpreter(
- init_lldb,
+ LLDBSwigPyInit,
LLDBSwigPythonBreakpointCallbackFunction,
LLDBSwigPythonWatchpointCallbackFunction,
LLDBSwigPythonCallTypeScript,
@@ -317,6 +363,10 @@ SystemInitializerFull::Terminate()
// Terminate and unload and loaded system or user LLDB plug-ins
PluginManager::Terminate();
+
+ ClangASTContext::Terminate();
+ GoASTContext::Terminate();
+
ABISysV_arm::Terminate();
ABISysV_arm64::Terminate();
ABISysV_i386::Terminate();
@@ -329,6 +379,9 @@ SystemInitializerFull::Terminate()
JITLoaderGDB::Terminate();
ProcessElfCore::Terminate();
+#if defined(_MSC_VER)
+ ProcessWinMiniDump::Terminate();
+#endif
MemoryHistoryASan::Terminate();
AddressSanitizerRuntime::Terminate();
SymbolVendorELF::Terminate();
@@ -340,10 +393,16 @@ SystemInitializerFull::Terminate()
SymbolFileDWARFDebugMap::Terminate();
ItaniumABILanguageRuntime::Terminate();
+ CPlusPlusLanguage::Terminate();
+
#if defined(__APPLE__)
ProcessMachCore::Terminate();
ProcessKDP::Terminate();
SymbolVendorMacOSX::Terminate();
+ PlatformAppleTVSimulator::Terminate();
+ PlatformAppleWatchSimulator::Terminate();
+ PlatformRemoteAppleTV::Terminate();
+ PlatformRemoteAppleWatch::Terminate();
#endif
#if defined(__FreeBSD__)
@@ -358,8 +417,3 @@ SystemInitializerFull::Terminate()
// Now shutdown the common parts, in reverse order.
SystemInitializerCommon::Terminate();
}
-
-void SystemInitializerFull::TerminateSWIG()
-{
-
-}
diff --git a/contrib/llvm/tools/lldb/source/API/liblldb.exports b/contrib/llvm/tools/lldb/source/API/liblldb.exports
new file mode 100644
index 0000000..fd234d1
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/API/liblldb.exports
@@ -0,0 +1,3 @@
+_ZN4lldb*
+_ZNK4lldb*
+init_lld*
diff --git a/contrib/llvm/tools/lldb/source/API/liblldb.xcode.exports b/contrib/llvm/tools/lldb/source/API/liblldb.xcode.exports
new file mode 100644
index 0000000..9c194fa
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/API/liblldb.xcode.exports
@@ -0,0 +1,3 @@
+__ZN4lldb*
+__ZNK4lldb*
+_init_lld*
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/Breakpoint.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/Breakpoint.cpp
index 23d484f..54f67b9 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/Breakpoint.cpp
@@ -7,12 +7,12 @@
//
//===----------------------------------------------------------------------===//
-
// C Includes
// C++ Includes
// Other libraries and framework includes
-// Project includes
+#include "llvm/Support/Casting.h"
+// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -31,7 +31,6 @@
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
-#include "llvm/Support/Casting.h"
using namespace lldb;
using namespace lldb_private;
@@ -83,9 +82,7 @@ Breakpoint::Breakpoint (Target &new_target, Breakpoint &source_bp) :
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-Breakpoint::~Breakpoint()
-{
-}
+Breakpoint::~Breakpoint() = default;
const lldb::TargetSP
Breakpoint::GetTargetSP ()
@@ -236,7 +233,7 @@ Breakpoint::SetThreadID (lldb::tid_t thread_id)
lldb::tid_t
Breakpoint::GetThreadID () const
{
- if (m_options.GetThreadSpecNoCreate() == NULL)
+ if (m_options.GetThreadSpecNoCreate() == nullptr)
return LLDB_INVALID_THREAD_ID;
else
return m_options.GetThreadSpecNoCreate()->GetTID();
@@ -255,7 +252,7 @@ Breakpoint::SetThreadIndex (uint32_t index)
uint32_t
Breakpoint::GetThreadIndex() const
{
- if (m_options.GetThreadSpecNoCreate() == NULL)
+ if (m_options.GetThreadSpecNoCreate() == nullptr)
return 0;
else
return m_options.GetThreadSpecNoCreate()->GetIndex();
@@ -264,7 +261,7 @@ Breakpoint::GetThreadIndex() const
void
Breakpoint::SetThreadName (const char *thread_name)
{
- if (m_options.GetThreadSpec()->GetName() != NULL
+ if (m_options.GetThreadSpec()->GetName() != nullptr
&& ::strcmp (m_options.GetThreadSpec()->GetName(), thread_name) == 0)
return;
@@ -275,8 +272,8 @@ Breakpoint::SetThreadName (const char *thread_name)
const char *
Breakpoint::GetThreadName () const
{
- if (m_options.GetThreadSpecNoCreate() == NULL)
- return NULL;
+ if (m_options.GetThreadSpecNoCreate() == nullptr)
+ return nullptr;
else
return m_options.GetThreadSpecNoCreate()->GetName();
}
@@ -284,7 +281,7 @@ Breakpoint::GetThreadName () const
void
Breakpoint::SetQueueName (const char *queue_name)
{
- if (m_options.GetThreadSpec()->GetQueueName() != NULL
+ if (m_options.GetThreadSpec()->GetQueueName() != nullptr
&& ::strcmp (m_options.GetThreadSpec()->GetQueueName(), queue_name) == 0)
return;
@@ -295,8 +292,8 @@ Breakpoint::SetQueueName (const char *queue_name)
const char *
Breakpoint::GetQueueName () const
{
- if (m_options.GetThreadSpecNoCreate() == NULL)
- return NULL;
+ if (m_options.GetThreadSpecNoCreate() == nullptr)
+ return nullptr;
else
return m_options.GetThreadSpecNoCreate()->GetQueueName();
}
@@ -456,7 +453,6 @@ Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_loca
if (!seen)
new_modules.AppendIfNeeded (module_sp);
-
}
if (new_modules.GetSize() > 0)
@@ -474,7 +470,7 @@ Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_loca
removed_locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsRemoved,
shared_from_this());
else
- removed_locations_event = NULL;
+ removed_locations_event = nullptr;
size_t num_modules = module_list.GetSize();
for (size_t i = 0; i < num_modules; i++)
@@ -502,7 +498,6 @@ Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_loca
}
if (delete_locations)
locations_to_remove.Add (break_loc_sp);
-
}
}
@@ -568,7 +563,7 @@ SymbolContextsMightBeEquivalent(SymbolContext &old_sc, SymbolContext &new_sc)
}
return equivalent_scs;
}
-}
+} // anonymous namespace
void
Breakpoint::ModuleReplaced (ModuleSP old_module_sp, ModuleSP new_module_sp)
@@ -740,7 +735,7 @@ Breakpoint::ModuleReplaced (ModuleSP old_module_sp, ModuleSP new_module_sp)
locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsRemoved,
shared_from_this());
else
- locations_event = NULL;
+ locations_event = nullptr;
for (BreakpointLocationSP loc_sp : locations_to_remove.BreakpointLocations())
{
@@ -804,7 +799,7 @@ Breakpoint::AddName (const char *new_name, Error &error)
void
Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations)
{
- assert (s != NULL);
+ assert (s != nullptr);
if (!m_kind_description.empty())
{
@@ -849,6 +844,9 @@ Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_l
GetOptions()->GetDescription(s, level);
+ if (m_precondition_sp)
+ m_precondition_sp->GetDescription(*s, level);
+
if (level == lldb::eDescriptionLevelFull)
{
if (!m_name_list.empty())
@@ -876,7 +874,7 @@ Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_l
{
s->Printf ("no locations (pending).");
}
- else if (num_locations == 1 && show_locations == false)
+ else if (num_locations == 1 && !show_locations)
{
// There is only one location, so we'll just print that location information.
GetLocationAtIndex(0)->GetDescription(s, level);
@@ -922,7 +920,6 @@ Breakpoint::GetResolverDescription (Stream *s)
m_resolver_sp->GetDescription (s);
}
-
bool
Breakpoint::GetMatchingFileLine (const ConstString &filename, uint32_t line_number, BreakpointLocationCollection &loc_coll)
{
@@ -965,7 +962,7 @@ Breakpoint::BreakpointPrecondition::EvaluatePrecondition(StoppointCallbackContex
}
void
-Breakpoint::BreakpointPrecondition::DescribePrecondition(Stream &stream, lldb::DescriptionLevel level)
+Breakpoint::BreakpointPrecondition::GetDescription(Stream &stream, lldb::DescriptionLevel level)
{
}
@@ -993,8 +990,7 @@ Breakpoint::SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind)
void
Breakpoint::SendBreakpointChangedEvent (BreakpointEventData *data)
{
-
- if (data == NULL)
+ if (data == nullptr)
return;
if (!m_being_created
@@ -1013,9 +1009,7 @@ Breakpoint::BreakpointEventData::BreakpointEventData (BreakpointEventType sub_ty
{
}
-Breakpoint::BreakpointEventData::~BreakpointEventData ()
-{
-}
+Breakpoint::BreakpointEventData::~BreakpointEventData() = default;
const ConstString &
Breakpoint::BreakpointEventData::GetFlavorString ()
@@ -1030,7 +1024,6 @@ Breakpoint::BreakpointEventData::GetFlavor () const
return BreakpointEventData::GetFlavorString ();
}
-
BreakpointSP &
Breakpoint::BreakpointEventData::GetBreakpoint ()
{
@@ -1057,7 +1050,7 @@ Breakpoint::BreakpointEventData::GetEventDataFromEvent (const Event *event)
if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
return static_cast <const BreakpointEventData *> (event->GetData());
}
- return NULL;
+ return nullptr;
}
BreakpointEventType
@@ -1065,7 +1058,7 @@ Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (const EventSP
{
const BreakpointEventData *data = GetEventDataFromEvent (event_sp.get());
- if (data == NULL)
+ if (data == nullptr)
return eBreakpointEventTypeInvalidType;
else
return data->GetBreakpointEventType();
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointID.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointID.cpp
index 3182388..81a3dfe 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointID.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointID.cpp
@@ -7,14 +7,12 @@
//
//===----------------------------------------------------------------------===//
-
// C Includes
#include <stdio.h>
// C++ Includes
// Other libraries and framework includes
// Project includes
-
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Core/Stream.h"
@@ -29,11 +27,9 @@ BreakpointID::BreakpointID (break_id_t bp_id, break_id_t loc_id) :
{
}
-BreakpointID::~BreakpointID ()
-{
-}
+BreakpointID::~BreakpointID() = default;
-const char *BreakpointID::g_range_specifiers[] = { "-", "to", "To", "TO", NULL };
+const char *BreakpointID::g_range_specifiers[] = { "-", "to", "To", "TO", nullptr };
// Tells whether or not STR is valid to use between two strings representing breakpoint IDs, to
// indicate a range of breakpoint IDs. This is broken out into a separate function so that we can
@@ -43,7 +39,7 @@ bool
BreakpointID::IsRangeIdentifier (const char *str)
{
int specifier_count = 0;
- for (int i = 0; g_range_specifiers[i] != NULL; ++i)
+ for (int i = 0; g_range_specifiers[i] != nullptr; ++i)
++specifier_count;
for (int i = 0; i < specifier_count; ++i)
@@ -62,10 +58,7 @@ BreakpointID::IsValidIDExpression (const char *str)
break_id_t loc_id;
BreakpointID::ParseCanonicalReference (str, &bp_id, &loc_id);
- if (bp_id == LLDB_INVALID_BREAK_ID)
- return false;
- else
- return true;
+ return (bp_id != LLDB_INVALID_BREAK_ID);
}
void
@@ -99,7 +92,7 @@ BreakpointID::ParseCanonicalReference (const char *input, break_id_t *break_id_p
*break_id_ptr = LLDB_INVALID_BREAK_ID;
*break_loc_id_ptr = LLDB_INVALID_BREAK_ID;
- if (input == NULL || *input == '\0')
+ if (input == nullptr || *input == '\0')
return false;
const char *format = "%i%n.%i%n";
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointIDList.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointIDList.cpp
index b8b5067..ebf0697 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointIDList.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointIDList.cpp
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/Breakpoint.h"
@@ -27,9 +31,7 @@ m_invalid_id (LLDB_INVALID_BREAK_ID, LLDB_INVALID_BREAK_ID)
{
}
-BreakpointIDList::~BreakpointIDList ()
-{
-}
+BreakpointIDList::~BreakpointIDList() = default;
size_t
BreakpointIDList::GetSize()
@@ -38,12 +40,9 @@ BreakpointIDList::GetSize()
}
BreakpointID &
-BreakpointIDList::GetBreakpointIDAtIndex (size_t index)
+BreakpointIDList::GetBreakpointIDAtIndex(size_t index)
{
- if (index < m_breakpoint_ids.size())
- return m_breakpoint_ids[index];
- else
- return m_invalid_id;
+ return ((index < m_breakpoint_ids.size()) ? m_breakpoint_ids[index] : m_invalid_id);
}
bool
@@ -124,7 +123,7 @@ BreakpointIDList::FindBreakpointID (const char *bp_id_str, size_t *position)
void
BreakpointIDList::InsertStringArray (const char **string_array, size_t array_size, CommandReturnObject &result)
{
- if (string_array == NULL)
+ if (string_array == nullptr)
return;
for (uint32_t i = 0; i < array_size; ++i)
@@ -385,7 +384,6 @@ BreakpointIDList::FindAndReplaceIDRanges (Args &old_args,
}
result.SetStatus (eReturnStatusSuccessFinishNoResult);
- return;
}
bool
@@ -402,7 +400,7 @@ BreakpointIDList::StringContainsIDRangeExpression (const char *in_string,
*range_end_pos = 0;
int specifiers_size = 0;
- for (int i = 0; BreakpointID::g_range_specifiers[i] != NULL; ++i)
+ for (int i = 0; BreakpointID::g_range_specifiers[i] != nullptr; ++i)
++specifiers_size;
for (int i = 0; i < specifiers_size && !is_range_expression; ++i)
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocation.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocation.cpp
index a199d39..5ff9110 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -9,8 +9,6 @@
// C Includes
// C++ Includes
-#include <string>
-
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -21,9 +19,11 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
@@ -88,12 +88,18 @@ BreakpointLocation::GetBreakpoint ()
return m_owner;
}
+Target &
+BreakpointLocation::GetTarget()
+{
+ return m_owner.GetTarget();
+}
+
bool
BreakpointLocation::IsEnabled () const
{
if (!m_owner.IsEnabled())
return false;
- else if (m_options_ap.get() != NULL)
+ else if (m_options_ap.get() != nullptr)
return m_options_ap->IsEnabled();
else
return true;
@@ -123,7 +129,7 @@ BreakpointLocation::SetThreadID (lldb::tid_t thread_id)
{
// If we're resetting this to an invalid thread id, then
// don't make an options pointer just to do that.
- if (m_options_ap.get() != NULL)
+ if (m_options_ap.get() != nullptr)
m_options_ap->SetThreadID (thread_id);
}
SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
@@ -147,11 +153,10 @@ BreakpointLocation::SetThreadIndex (uint32_t index)
{
// If we're resetting this to an invalid thread id, then
// don't make an options pointer just to do that.
- if (m_options_ap.get() != NULL)
+ if (m_options_ap.get() != nullptr)
m_options_ap->GetThreadSpec()->SetIndex(index);
}
SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
-
}
uint32_t
@@ -166,13 +171,13 @@ BreakpointLocation::GetThreadIndex() const
void
BreakpointLocation::SetThreadName (const char *thread_name)
{
- if (thread_name != NULL)
+ if (thread_name != nullptr)
GetLocationOptions()->GetThreadSpec()->SetName(thread_name);
else
{
// If we're resetting this to an invalid thread id, then
// don't make an options pointer just to do that.
- if (m_options_ap.get() != NULL)
+ if (m_options_ap.get() != nullptr)
m_options_ap->GetThreadSpec()->SetName(thread_name);
}
SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
@@ -184,19 +189,19 @@ BreakpointLocation::GetThreadName () const
if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetName();
else
- return NULL;
+ return nullptr;
}
void
BreakpointLocation::SetQueueName (const char *queue_name)
{
- if (queue_name != NULL)
+ if (queue_name != nullptr)
GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name);
else
{
// If we're resetting this to an invalid thread id, then
// don't make an options pointer just to do that.
- if (m_options_ap.get() != NULL)
+ if (m_options_ap.get() != nullptr)
m_options_ap->GetThreadSpec()->SetQueueName(queue_name);
}
SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
@@ -208,13 +213,13 @@ BreakpointLocation::GetQueueName () const
if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetQueueName();
else
- return NULL;
+ return nullptr;
}
bool
BreakpointLocation::InvokeCallback (StoppointCallbackContext *context)
{
- if (m_options_ap.get() != NULL && m_options_ap->HasCallback())
+ if (m_options_ap.get() != nullptr && m_options_ap->HasCallback())
return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID());
else
return m_owner.InvokeCallback (context, GetID());
@@ -238,7 +243,6 @@ BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &
SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged);
}
-
void
BreakpointLocation::ClearCallback ()
{
@@ -278,11 +282,27 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
!m_user_expression_sp ||
!m_user_expression_sp->MatchesContext(exe_ctx))
{
- m_user_expression_sp.reset(new ClangUserExpression(condition_text,
- NULL,
- lldb::eLanguageTypeUnknown,
- ClangUserExpression::eResultTypeAny));
+ LanguageType language = eLanguageTypeUnknown;
+ // See if we can figure out the language from the frame, otherwise use the default language:
+ CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit();
+ if (comp_unit)
+ language = comp_unit->GetLanguage();
+ Error error;
+ m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(condition_text,
+ nullptr,
+ language,
+ Expression::eResultTypeAny,
+ EvaluateExpressionOptions(),
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("Error getting condition expression: %s.", error.AsCString());
+ m_user_expression_sp.reset();
+ return true;
+ }
+
StreamString errors;
if (!m_user_expression_sp->Parse(errors,
@@ -314,7 +334,7 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
StreamString execution_errors;
- ClangExpressionVariableSP result_variable_sp;
+ ExpressionVariableSP result_variable_sp;
ExpressionResults result_code =
m_user_expression_sp->Execute(execution_errors,
@@ -337,21 +357,20 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
if (result_value_sp)
{
- Scalar scalar_value;
- if (result_value_sp->ResolveValue (scalar_value))
+ ret = result_value_sp->IsLogicalTrue(error);
+ if (log)
{
- if (scalar_value.ULongLong(1) == 0)
- ret = false;
- else
- ret = true;
- if (log)
+ if (error.Success())
+ {
log->Printf("Condition successfully evaluated, result is %s.\n",
ret ? "true" : "false");
- }
- else
- {
- ret = false;
- error.SetErrorString("Failed to get an integer result from the expression");
+ }
+ else
+ {
+ error.SetErrorString("Failed to get an integer result from the expression");
+ ret = false;
+ }
+
}
}
else
@@ -385,7 +404,7 @@ BreakpointLocation::SetIgnoreCount (uint32_t n)
void
BreakpointLocation::DecrementIgnoreCount()
{
- if (m_options_ap.get() != NULL)
+ if (m_options_ap.get() != nullptr)
{
uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
if (loc_ignore != 0)
@@ -396,7 +415,7 @@ BreakpointLocation::DecrementIgnoreCount()
bool
BreakpointLocation::IgnoreCountShouldStop()
{
- if (m_options_ap.get() != NULL)
+ if (m_options_ap.get() != nullptr)
{
uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
if (loc_ignore != 0)
@@ -413,7 +432,7 @@ BreakpointLocation::IgnoreCountShouldStop()
const BreakpointOptions *
BreakpointLocation::GetOptionsNoCreate () const
{
- if (m_options_ap.get() != NULL)
+ if (m_options_ap.get() != nullptr)
return m_options_ap.get();
else
return m_owner.GetOptions ();
@@ -425,7 +444,7 @@ BreakpointLocation::GetLocationOptions ()
// If we make the copy we don't copy the callbacks because that is potentially
// expensive and we don't want to do that for the simple case where someone is
// just disabling the location.
- if (m_options_ap.get() == NULL)
+ if (m_options_ap.get() == nullptr)
m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ()));
return m_options_ap.get();
@@ -497,7 +516,7 @@ BreakpointLocation::UndoBumpHitCount()
bool
BreakpointLocation::IsResolved () const
{
- return m_bp_site_sp.get() != NULL;
+ return m_bp_site_sp.get() != nullptr;
}
lldb::BreakpointSiteSP
@@ -513,7 +532,7 @@ BreakpointLocation::ResolveBreakpointSite ()
return true;
Process *process = m_owner.GetTarget().GetProcessSP().get();
- if (process == NULL)
+ if (process == nullptr)
return false;
lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), m_owner.IsHardware());
@@ -601,13 +620,13 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
sc.module_sp->GetFileSpec().Dump (s);
}
- if (sc.comp_unit != NULL)
+ if (sc.comp_unit != nullptr)
{
s->EOL();
s->Indent("compile unit = ");
static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
- if (sc.function != NULL)
+ if (sc.function != nullptr)
{
s->EOL();
s->Indent("function = ");
@@ -648,11 +667,11 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
s->Printf (", ");
s->Printf ("address = ");
- ExecutionContextScope *exe_scope = NULL;
+ ExecutionContextScope *exe_scope = nullptr;
Target *target = &m_owner.GetTarget();
if (target)
exe_scope = target->GetProcessSP().get();
- if (exe_scope == NULL)
+ if (exe_scope == nullptr)
exe_scope = target;
if (level == eDescriptionLevelInitial)
@@ -710,7 +729,7 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
void
BreakpointLocation::Dump(Stream *s) const
{
- if (s == NULL)
+ if (s == nullptr)
return;
s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint "
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp
index 06b270a..d57cfa6 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-
// C Includes
// C++ Includes
// Other libraries and framework includes
@@ -22,7 +21,6 @@
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
-
using namespace lldb;
using namespace lldb_private;
@@ -32,13 +30,11 @@ BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) :
m_address_to_location (),
m_mutex (Mutex::eMutexTypeRecursive),
m_next_id (0),
- m_new_location_recorder (NULL)
+ m_new_location_recorder (nullptr)
{
}
-BreakpointLocationList::~BreakpointLocationList()
-{
-}
+BreakpointLocationList::~BreakpointLocationList() = default;
BreakpointLocationSP
BreakpointLocationList::Create (const Address &addr, bool resolve_indirect_symbols)
@@ -163,7 +159,6 @@ BreakpointLocationList::Dump (Stream *s) const
s->IndentLess();
}
-
BreakpointLocationSP
BreakpointLocationList::GetByIndex (size_t i)
{
@@ -285,7 +280,6 @@ BreakpointLocationList::SwapLocation (BreakpointLocationSP to_location_sp, Break
to_location_sp->ResolveBreakpointSite();
}
-
bool
BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp)
{
@@ -304,7 +298,7 @@ BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc
return true;
}
}
- }
+ }
return false;
}
@@ -348,7 +342,7 @@ void
BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations)
{
Mutex::Locker locker (m_mutex);
- assert (m_new_location_recorder == NULL);
+ assert(m_new_location_recorder == nullptr);
m_new_location_recorder = &new_locations;
}
@@ -356,7 +350,7 @@ void
BreakpointLocationList::StopRecordingNewLocations ()
{
Mutex::Locker locker (m_mutex);
- m_new_location_recorder = NULL;
+ m_new_location_recorder = nullptr;
}
void
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointOptions.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointOptions.cpp
index db76ffb..d2a9197 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointOptions.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -7,12 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Breakpoint/BreakpointOptions.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Breakpoint/BreakpointOptions.h"
+
#include "lldb/Core/Stream.h"
#include "lldb/Core/StringList.h"
#include "lldb/Core/Value.h"
@@ -20,7 +20,6 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
-#include "lldb/Expression/ClangUserExpression.h"
using namespace lldb;
using namespace lldb_private;
@@ -59,7 +58,7 @@ BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) :
m_ignore_count (rhs.m_ignore_count),
m_thread_spec_ap ()
{
- if (rhs.m_thread_spec_ap.get() != NULL)
+ if (rhs.m_thread_spec_ap.get() != nullptr)
m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get()));
m_condition_text = rhs.m_condition_text;
m_condition_text_hash = rhs.m_condition_text_hash;
@@ -77,7 +76,7 @@ BreakpointOptions::operator=(const BreakpointOptions& rhs)
m_enabled = rhs.m_enabled;
m_one_shot = rhs.m_one_shot;
m_ignore_count = rhs.m_ignore_count;
- if (rhs.m_thread_spec_ap.get() != NULL)
+ if (rhs.m_thread_spec_ap.get() != nullptr)
m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
m_condition_text = rhs.m_condition_text;
m_condition_text_hash = rhs.m_condition_text_hash;
@@ -102,9 +101,7 @@ BreakpointOptions::CopyOptionsNoCallback (BreakpointOptions &orig)
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-BreakpointOptions::~BreakpointOptions()
-{
-}
+BreakpointOptions::~BreakpointOptions() = default;
//------------------------------------------------------------------
// Callbacks
@@ -144,10 +141,10 @@ BreakpointOptions::InvokeCallback (StoppointCallbackContext *context,
{
if (m_callback && context->is_synchronous == IsCallbackSynchronous())
{
- return m_callback (m_callback_baton_sp ? m_callback_baton_sp->m_data : NULL,
- context,
- break_id,
- break_loc_id);
+ return m_callback(m_callback_baton_sp ? m_callback_baton_sp->m_data : nullptr,
+ context,
+ break_id,
+ break_loc_id);
}
else
return true;
@@ -182,7 +179,7 @@ BreakpointOptions::GetConditionText (size_t *hash) const
}
else
{
- return NULL;
+ return nullptr;
}
}
@@ -195,7 +192,7 @@ BreakpointOptions::GetThreadSpecNoCreate () const
ThreadSpec *
BreakpointOptions::GetThreadSpec ()
{
- if (m_thread_spec_ap.get() == NULL)
+ if (m_thread_spec_ap.get() == nullptr)
m_thread_spec_ap.reset (new ThreadSpec());
return m_thread_spec_ap.get();
@@ -210,11 +207,10 @@ BreakpointOptions::SetThreadID (lldb::tid_t thread_id)
void
BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) const
{
-
// Figure out if there are any options not at their default value, and only print
// anything if there are:
- if (m_ignore_count != 0 || !m_enabled || m_one_shot || (GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ()))
+ if (m_ignore_count != 0 || !m_enabled || m_one_shot || (GetThreadSpecNoCreate() != nullptr && GetThreadSpecNoCreate()->HasSpecification ()))
{
if (level == lldb::eDescriptionLevelVerbose)
{
@@ -294,4 +290,3 @@ BreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLev
s->IndentLess ();
s->IndentLess ();
}
-
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverAddress.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverAddress.cpp
index 193bc41..8a0469a 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverAddress.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverAddress.cpp
@@ -16,6 +16,7 @@
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -29,10 +30,25 @@ using namespace lldb_private;
BreakpointResolverAddress::BreakpointResolverAddress
(
Breakpoint *bkpt,
+ const Address &addr,
+ const FileSpec &module_spec
+) :
+ BreakpointResolver (bkpt, BreakpointResolver::AddressResolver),
+ m_addr (addr),
+ m_resolved_addr(LLDB_INVALID_ADDRESS),
+ m_module_filespec(module_spec)
+{
+}
+
+BreakpointResolverAddress::BreakpointResolverAddress
+(
+ Breakpoint *bkpt,
const Address &addr
) :
BreakpointResolver (bkpt, BreakpointResolver::AddressResolver),
- m_addr (addr)
+ m_addr (addr),
+ m_resolved_addr(LLDB_INVALID_ADDRESS),
+ m_module_filespec()
{
}
@@ -44,10 +60,16 @@ BreakpointResolverAddress::~BreakpointResolverAddress ()
void
BreakpointResolverAddress::ResolveBreakpoint (SearchFilter &filter)
{
- // The address breakpoint only takes once, so if we've already set it we're done.
- if (m_breakpoint->GetNumLocations() > 0)
- return;
- else
+ // If the address is not section relative, then we should not try to re-resolve it, it is just some
+ // random address and we wouldn't know what to do on reload. But if it is section relative, we need to
+ // re-resolve it since the section it's in may have shifted on re-run.
+ bool re_resolve = false;
+ if (m_addr.GetSection() || m_module_filespec)
+ re_resolve = true;
+ else if (m_breakpoint->GetNumLocations() == 0)
+ re_resolve = true;
+
+ if (re_resolve)
BreakpointResolver::ResolveBreakpoint(filter);
}
@@ -58,10 +80,14 @@ BreakpointResolverAddress::ResolveBreakpointInModules
ModuleList &modules
)
{
- // The address breakpoint only takes once, so if we've already set it we're done.
- if (m_breakpoint->GetNumLocations() > 0)
- return;
- else
+ // See comment in ResolveBreakpoint.
+ bool re_resolve = false;
+ if (m_addr.GetSection())
+ re_resolve = true;
+ else if (m_breakpoint->GetNumLocations() == 0)
+ re_resolve = true;
+
+ if (re_resolve)
BreakpointResolver::ResolveBreakpointInModules (filter, modules);
}
@@ -78,14 +104,44 @@ BreakpointResolverAddress::SearchCallback
if (filter.AddressPasses (m_addr))
{
- BreakpointLocationSP bp_loc_sp(m_breakpoint->AddLocation(m_addr));
- if (bp_loc_sp && !m_breakpoint->IsInternal())
+ if (m_breakpoint->GetNumLocations() == 0)
+ {
+ // If the address is just an offset, and we're given a module, see if we can find the appropriate module
+ // loaded in the binary, and fix up m_addr to use that.
+ if (!m_addr.IsSectionOffset() && m_module_filespec)
+ {
+ Target &target = m_breakpoint->GetTarget();
+ ModuleSpec module_spec(m_module_filespec);
+ ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec);
+ if (module_sp)
+ {
+ Address tmp_address;
+ if (module_sp->ResolveFileAddress(m_addr.GetOffset(), tmp_address))
+ m_addr = tmp_address;
+ }
+ }
+
+ BreakpointLocationSP bp_loc_sp(m_breakpoint->AddLocation(m_addr));
+ m_resolved_addr = m_addr.GetLoadAddress(&m_breakpoint->GetTarget());
+ if (bp_loc_sp && !m_breakpoint->IsInternal())
+ {
+ StreamString s;
+ bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf ("Added location: %s\n", s.GetData());
+ }
+ }
+ else
{
- StreamString s;
- bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf ("Added location: %s\n", s.GetData());
+ BreakpointLocationSP loc_sp = m_breakpoint->GetLocationAtIndex(0);
+ lldb::addr_t cur_load_location = m_addr.GetLoadAddress(&m_breakpoint->GetTarget());
+ if (cur_load_location != m_resolved_addr)
+ {
+ m_resolved_addr = cur_load_location;
+ loc_sp->ClearBreakpointSite();
+ loc_sp->ResolveBreakpointSite();
+ }
}
}
return Searcher::eCallbackReturnStop;
@@ -101,7 +157,7 @@ void
BreakpointResolverAddress::GetDescription (Stream *s)
{
s->PutCString ("address = ");
- m_addr.Dump(s, m_breakpoint->GetTarget().GetProcessSP().get(), Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
+ m_addr.Dump(s, m_breakpoint->GetTarget().GetProcessSP().get(), Address::DumpStyleModuleWithFileAddress, Address::DumpStyleLoadAddress);
}
void
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverName.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverName.cpp
index 581f7b0..9ae3fe5 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverName.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointResolverName.cpp
@@ -7,22 +7,21 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Breakpoint/BreakpointResolverName.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Breakpoint/BreakpointResolverName.h"
+
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
using namespace lldb;
using namespace lldb_private;
@@ -30,15 +29,16 @@ using namespace lldb_private;
BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
const char *name_cstr,
uint32_t name_type_mask,
+ LanguageType language,
Breakpoint::MatchType type,
bool skip_prologue) :
BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
m_class_name (),
m_regex (),
m_match_type (type),
+ m_language (language),
m_skip_prologue (skip_prologue)
{
-
if (m_match_type == Breakpoint::Regexp)
{
if (!m_regex.Compile (name_cstr))
@@ -59,9 +59,11 @@ BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
const char *names[],
size_t num_names,
uint32_t name_type_mask,
+ LanguageType language,
bool skip_prologue) :
BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
m_match_type (Breakpoint::Exact),
+ m_language (language),
m_skip_prologue (skip_prologue)
{
for (size_t i = 0; i < num_names; i++)
@@ -73,9 +75,11 @@ BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
std::vector<std::string> names,
uint32_t name_type_mask,
+ LanguageType language,
bool skip_prologue) :
BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
m_match_type (Breakpoint::Exact),
+ m_language (language),
m_skip_prologue (skip_prologue)
{
for (const std::string& name : names)
@@ -86,27 +90,27 @@ BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
RegularExpression &func_regex,
+ lldb::LanguageType language,
bool skip_prologue) :
BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
- m_class_name (NULL),
+ m_class_name (nullptr),
m_regex (func_regex),
m_match_type (Breakpoint::Regexp),
+ m_language (language),
m_skip_prologue (skip_prologue)
{
}
-BreakpointResolverName::BreakpointResolverName
-(
- Breakpoint *bkpt,
- const char *class_name,
- const char *method,
- Breakpoint::MatchType type,
- bool skip_prologue
-) :
+BreakpointResolverName::BreakpointResolverName(Breakpoint *bkpt,
+ const char *class_name,
+ const char *method,
+ Breakpoint::MatchType type,
+ bool skip_prologue ) :
BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
m_class_name (class_name),
m_regex (),
m_match_type (type),
+ m_language (eLanguageTypeUnknown),
m_skip_prologue (skip_prologue)
{
LookupInfo lookup;
@@ -117,9 +121,7 @@ BreakpointResolverName::BreakpointResolverName
m_lookups.push_back (lookup);
}
-BreakpointResolverName::~BreakpointResolverName ()
-{
-}
+BreakpointResolverName::~BreakpointResolverName() = default;
BreakpointResolverName::BreakpointResolverName(const BreakpointResolverName &rhs) :
BreakpointResolver(rhs.m_breakpoint, BreakpointResolver::NameResolver),
@@ -127,15 +129,15 @@ BreakpointResolverName::BreakpointResolverName(const BreakpointResolverName &rhs
m_class_name(rhs.m_class_name),
m_regex(rhs.m_regex),
m_match_type (rhs.m_match_type),
+ m_language (rhs.m_language),
m_skip_prologue (rhs.m_skip_prologue)
{
-
}
void
BreakpointResolverName::AddNameLookup (const ConstString &name, uint32_t name_type_mask)
{
- ObjCLanguageRuntime::MethodName objc_method(name.GetCString(), false);
+ ObjCLanguage::MethodName objc_method(name.GetCString(), false);
if (objc_method.IsValid(false))
{
std::vector<ConstString> objc_names;
@@ -154,12 +156,11 @@ BreakpointResolverName::AddNameLookup (const ConstString &name, uint32_t name_ty
{
LookupInfo lookup;
lookup.name = name;
- Module::PrepareForFunctionNameLookup(lookup.name, name_type_mask, lookup.lookup_name, lookup.name_type_mask, lookup.match_name_after_lookup);
+ Module::PrepareForFunctionNameLookup(lookup.name, name_type_mask, m_language, lookup.lookup_name, lookup.name_type_mask, lookup.match_name_after_lookup);
m_lookups.push_back (lookup);
}
}
-
void
BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t start_idx) const
{
@@ -172,7 +173,7 @@ BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t st
if (!sc_list.GetContextAtIndex(i, sc))
break;
ConstString full_name (sc.GetFunctionName());
- if (full_name && ::strstr(full_name.GetCString(), name.GetCString()) == NULL)
+ if (full_name && ::strstr(full_name.GetCString(), name.GetCString()) == nullptr)
{
sc_list.RemoveContextAtIndex(i);
}
@@ -184,19 +185,15 @@ BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t st
}
}
-
// FIXME: Right now we look at the module level, and call the module's "FindFunctions".
// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
// lookup. At that point, we should switch the depth to CompileUnit, and look in these tables.
Searcher::CallbackReturn
-BreakpointResolverName::SearchCallback
-(
- SearchFilter &filter,
- SymbolContext &context,
- Address *addr,
- bool containing
-)
+BreakpointResolverName::SearchCallback(SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool containing)
{
SymbolContextList func_list;
//SymbolContextList sym_list;
@@ -204,7 +201,7 @@ BreakpointResolverName::SearchCallback
uint32_t i;
bool new_location;
Address break_addr;
- assert (m_breakpoint != NULL);
+ assert (m_breakpoint != nullptr);
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
@@ -215,7 +212,8 @@ BreakpointResolverName::SearchCallback
return Searcher::eCallbackReturnStop;
}
bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0;
- const bool include_symbols = filter_by_cu == false;
+ bool filter_by_language = (m_language != eLanguageTypeUnknown);
+ const bool include_symbols = !filter_by_cu;
const bool include_inlines = true;
const bool append = true;
@@ -227,13 +225,13 @@ BreakpointResolverName::SearchCallback
for (const LookupInfo &lookup : m_lookups)
{
const size_t start_func_idx = func_list.GetSize();
- context.module_sp->FindFunctions (lookup.lookup_name,
- NULL,
- lookup.name_type_mask,
- include_symbols,
- include_inlines,
- append,
- func_list);
+ context.module_sp->FindFunctions(lookup.lookup_name,
+ nullptr,
+ lookup.name_type_mask,
+ include_symbols,
+ include_inlines,
+ append,
+ func_list);
const size_t end_func_idx = func_list.GetSize();
if (start_func_idx < end_func_idx)
@@ -258,15 +256,33 @@ BreakpointResolverName::SearchCallback
}
// If the filter specifies a Compilation Unit, remove the ones that don't pass at this point.
- if (filter_by_cu)
+ if (filter_by_cu || filter_by_language)
{
uint32_t num_functions = func_list.GetSize();
for (size_t idx = 0; idx < num_functions; idx++)
{
+ bool remove_it = false;
SymbolContext sc;
func_list.GetContextAtIndex(idx, sc);
- if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit))
+ if (filter_by_cu)
+ {
+ if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit))
+ remove_it = true;
+ }
+
+ if (filter_by_language)
+ {
+ LanguageType sym_language = sc.GetLanguage();
+ if ((Language::GetPrimaryLanguage(sym_language) !=
+ Language::GetPrimaryLanguage(m_language)) &&
+ (sym_language != eLanguageTypeUnknown))
+ {
+ remove_it = true;
+ }
+ }
+
+ if (remove_it)
{
func_list.RemoveContextAtIndex(idx);
num_functions--;
@@ -374,12 +390,15 @@ BreakpointResolverName::GetDescription (Stream *s)
s->Printf ("'%s'}", m_lookups[num_names - 1].name.GetCString());
}
}
+ if (m_language != eLanguageTypeUnknown)
+ {
+ s->Printf (", language = %s", Language::GetNameForLanguageType(m_language));
+ }
}
void
BreakpointResolverName::Dump (Stream *s) const
{
-
}
lldb::BreakpointResolverSP
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointSite.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointSite.cpp
index e9ce812..d2aaea0 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointSite.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointSite.cpp
@@ -7,14 +7,14 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Breakpoint/BreakpointSite.h"
-
// C Includes
// C++ Includes
#include <inttypes.h>
// Other libraries and framework includes
// Project includes
+#include "lldb/Breakpoint/BreakpointSite.h"
+
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSiteList.h"
@@ -23,13 +23,10 @@
using namespace lldb;
using namespace lldb_private;
-BreakpointSite::BreakpointSite
-(
- BreakpointSiteList *list,
- const BreakpointLocationSP& owner,
- lldb::addr_t addr,
- bool use_hardware
-) :
+BreakpointSite::BreakpointSite(BreakpointSiteList *list,
+ const BreakpointLocationSP& owner,
+ lldb::addr_t addr,
+ bool use_hardware) :
StoppointLocation(GetNextID(), addr, 0, use_hardware),
m_type (eSoftware), // Process subclasses need to set this correctly using SetType()
m_saved_opcode(),
@@ -85,7 +82,7 @@ BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id)
void
BreakpointSite::Dump(Stream *s) const
{
- if (s == NULL)
+ if (s == nullptr)
return;
s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64 " type = %s breakpoint hw_index = %i hit_count = %-4u",
@@ -205,6 +202,7 @@ BreakpointSite::ValidForThisThread (Thread *thread)
void
BreakpointSite::BumpHitCounts()
{
+ Mutex::Locker locker(m_owners_mutex);
for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations())
{
loc_sp->BumpHitCount();
@@ -253,3 +251,14 @@ BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *in
}
return false;
}
+
+size_t
+BreakpointSite::CopyOwnersList (BreakpointLocationCollection &out_collection)
+{
+ Mutex::Locker locker(m_owners_mutex);
+ for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations())
+ {
+ out_collection.Add(loc_sp);
+ }
+ return out_collection.GetSize();
+}
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/StoppointCallbackContext.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/StoppointCallbackContext.cpp
index 2266c3e..9932843 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/StoppointCallbackContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/StoppointCallbackContext.cpp
@@ -7,17 +7,16 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Breakpoint/StoppointCallbackContext.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
using namespace lldb_private;
StoppointCallbackContext::StoppointCallbackContext() :
- event (NULL),
+ event (nullptr),
exe_ctx_ref (),
is_synchronous (false)
{
@@ -33,7 +32,7 @@ StoppointCallbackContext::StoppointCallbackContext(Event *e, const ExecutionCont
void
StoppointCallbackContext::Clear()
{
- event = NULL;
+ event = nullptr;
exe_ctx_ref.Clear();
is_synchronous = false;
}
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/Watchpoint.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/Watchpoint.cpp
index 45559b1..00a328e 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/Watchpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/Watchpoint.cpp
@@ -7,12 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Breakpoint/Watchpoint.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Breakpoint/Watchpoint.h"
+
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/Value.h"
@@ -22,12 +22,12 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/UserExpression.h"
using namespace lldb;
using namespace lldb_private;
-Watchpoint::Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const ClangASTType *type, bool hardware) :
+Watchpoint::Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const CompilerType *type, bool hardware) :
StoppointLocation (0, addr, size, hardware),
m_target(target),
m_enabled(false),
@@ -67,9 +67,7 @@ Watchpoint::Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const
m_being_created = false;
}
-Watchpoint::~Watchpoint()
-{
-}
+Watchpoint::~Watchpoint() = default;
// This function is used when "baton" doesn't need to be freed
void
@@ -102,7 +100,6 @@ void
Watchpoint::SetDeclInfo (const std::string &str)
{
m_decl_str = str;
- return;
}
std::string
@@ -115,7 +112,6 @@ void
Watchpoint::SetWatchSpec (const std::string &str)
{
m_watch_spec_str = str;
- return;
}
// Override default impl of StoppointLocation::IsHardware() since m_is_hardware
@@ -154,10 +150,7 @@ Watchpoint::CaptureWatchedValue (const ExecutionContext &exe_ctx)
}
m_new_value_sp = ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(), watch_name.AsCString(), watch_address, m_type);
m_new_value_sp = m_new_value_sp->CreateConstantValue(watch_name);
- if (m_new_value_sp && m_new_value_sp->GetError().Success())
- return true;
- else
- return false;
+ return (m_new_value_sp && m_new_value_sp->GetError().Success());
}
void
@@ -190,9 +183,6 @@ Watchpoint::ShouldStop (StoppointCallbackContext *context)
if (!IsEnabled())
return false;
- if (GetHitCount() <= GetIgnoreCount())
- return false;
-
return true;
}
@@ -200,7 +190,6 @@ void
Watchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
DumpWithLevel(s, level);
- return;
}
void
@@ -209,7 +198,7 @@ Watchpoint::Dump(Stream *s) const
DumpWithLevel(s, lldb::eDescriptionLevelBrief);
}
-// If prefix is NULL, we display the watch id and ignore the prefix altogether.
+// If prefix is nullptr, we display the watch id and ignore the prefix altogether.
void
Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const
{
@@ -218,21 +207,38 @@ Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const
s->Printf("\nWatchpoint %u hit:", GetID());
prefix = "";
}
-
+
if (m_old_value_sp)
{
- s->Printf("\n%sold value: %s", prefix, m_old_value_sp->GetValueAsCString());
+ const char *old_value_cstr = m_old_value_sp->GetValueAsCString();
+ if (old_value_cstr && old_value_cstr[0])
+ s->Printf("\n%sold value: %s", prefix, old_value_cstr);
+ else
+ {
+ const char *old_summary_cstr = m_old_value_sp-> GetSummaryAsCString();
+ if (old_summary_cstr && old_summary_cstr[0])
+ s->Printf("\n%sold value: %s", prefix, old_summary_cstr);
+ }
}
+
if (m_new_value_sp)
{
- s->Printf("\n%snew value: %s", prefix, m_new_value_sp->GetValueAsCString());
+ const char *new_value_cstr = m_new_value_sp->GetValueAsCString();
+ if (new_value_cstr && new_value_cstr[0])
+ s->Printf("\n%snew value: %s", prefix, new_value_cstr);
+ else
+ {
+ const char *new_summary_cstr = m_new_value_sp-> GetSummaryAsCString();
+ if (new_summary_cstr && new_summary_cstr[0])
+ s->Printf("\n%snew value: %s", prefix, new_summary_cstr);
+ }
}
}
void
Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const
{
- if (s == NULL)
+ if (s == nullptr)
return;
assert(description_level >= lldb::eDescriptionLevelBrief &&
@@ -334,11 +340,13 @@ Watchpoint::WatchpointRead () const
{
return m_watch_read != 0;
}
+
bool
Watchpoint::WatchpointWrite () const
{
return m_watch_write != 0;
}
+
uint32_t
Watchpoint::GetIgnoreCount () const
{
@@ -363,15 +371,26 @@ Watchpoint::InvokeCallback (StoppointCallbackContext *context)
void
Watchpoint::SetCondition (const char *condition)
{
- if (condition == NULL || condition[0] == '\0')
+ if (condition == nullptr || condition[0] == '\0')
{
if (m_condition_ap.get())
m_condition_ap.reset();
}
else
{
- // Pass NULL for expr_prefix (no translation-unit level definitions).
- m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
+ // Pass nullptr for expr_prefix (no translation-unit level definitions).
+ Error error;
+ m_condition_ap.reset(m_target.GetUserExpressionForLanguage(condition,
+ nullptr,
+ lldb::eLanguageTypeUnknown,
+ UserExpression::eResultTypeAny,
+ EvaluateExpressionOptions(),
+ error));
+ if (error.Fail())
+ {
+ // FIXME: Log something...
+ m_condition_ap.reset();
+ }
}
SendWatchpointChangedEvent (eWatchpointEventTypeConditionChanged);
}
@@ -382,7 +401,7 @@ Watchpoint::GetConditionText () const
if (m_condition_ap.get())
return m_condition_ap->GetUserText();
else
- return NULL;
+ return nullptr;
}
void
@@ -399,8 +418,7 @@ Watchpoint::SendWatchpointChangedEvent (lldb::WatchpointEventType eventKind)
void
Watchpoint::SendWatchpointChangedEvent (WatchpointEventData *data)
{
-
- if (data == NULL)
+ if (data == nullptr)
return;
if (!m_being_created
@@ -418,9 +436,7 @@ Watchpoint::WatchpointEventData::WatchpointEventData (WatchpointEventType sub_ty
{
}
-Watchpoint::WatchpointEventData::~WatchpointEventData ()
-{
-}
+Watchpoint::WatchpointEventData::~WatchpointEventData() = default;
const ConstString &
Watchpoint::WatchpointEventData::GetFlavorString ()
@@ -435,7 +451,6 @@ Watchpoint::WatchpointEventData::GetFlavor () const
return WatchpointEventData::GetFlavorString ();
}
-
WatchpointSP &
Watchpoint::WatchpointEventData::GetWatchpoint ()
{
@@ -462,7 +477,7 @@ Watchpoint::WatchpointEventData::GetEventDataFromEvent (const Event *event)
if (event_data && event_data->GetFlavor() == WatchpointEventData::GetFlavorString())
return static_cast <const WatchpointEventData *> (event->GetData());
}
- return NULL;
+ return nullptr;
}
WatchpointEventType
@@ -470,7 +485,7 @@ Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent (const EventSP
{
const WatchpointEventData *data = GetEventDataFromEvent (event_sp.get());
- if (data == NULL)
+ if (data == nullptr)
return eWatchpointEventTypeInvalidType;
else
return data->GetWatchpointEventType();
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointList.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointList.cpp
index 472bae0..64bf5cd 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointList.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointList.cpp
@@ -75,10 +75,15 @@ WatchpointList::FindByAddress (lldb::addr_t addr) const
{
wp_collection::const_iterator pos, end = m_watchpoints.end();
for (pos = m_watchpoints.begin(); pos != end; ++pos)
- if ((*pos)->GetLoadAddress() == addr) {
+ {
+ lldb::addr_t wp_addr = (*pos)->GetLoadAddress();
+ uint32_t wp_bytesize = (*pos)->GetByteSize();
+ if ((wp_addr <= addr) && ((wp_addr + wp_bytesize) > addr))
+ {
wp_sp = *pos;
break;
}
+ }
}
return wp_sp;
diff --git a/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointOptions.cpp b/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointOptions.cpp
index c2c9696..365d884 100644
--- a/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointOptions.cpp
+++ b/contrib/llvm/tools/lldb/source/Breakpoint/WatchpointOptions.cpp
@@ -7,12 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Breakpoint/WatchpointOptions.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Breakpoint/WatchpointOptions.h"
+
#include "lldb/Core/Stream.h"
#include "lldb/Core/StringList.h"
#include "lldb/Core/Value.h"
@@ -20,7 +20,6 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
-#include "lldb/Expression/ClangUserExpression.h"
using namespace lldb;
using namespace lldb_private;
@@ -51,7 +50,7 @@ WatchpointOptions::WatchpointOptions(const WatchpointOptions& rhs) :
m_callback_is_synchronous (rhs.m_callback_is_synchronous),
m_thread_spec_ap ()
{
- if (rhs.m_thread_spec_ap.get() != NULL)
+ if (rhs.m_thread_spec_ap.get() != nullptr)
m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get()));
}
@@ -64,7 +63,7 @@ WatchpointOptions::operator=(const WatchpointOptions& rhs)
m_callback = rhs.m_callback;
m_callback_baton_sp = rhs.m_callback_baton_sp;
m_callback_is_synchronous = rhs.m_callback_is_synchronous;
- if (rhs.m_thread_spec_ap.get() != NULL)
+ if (rhs.m_thread_spec_ap.get() != nullptr)
m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
return *this;
}
@@ -87,9 +86,7 @@ WatchpointOptions::CopyOptionsNoCallback (WatchpointOptions &orig)
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-WatchpointOptions::~WatchpointOptions()
-{
-}
+WatchpointOptions::~WatchpointOptions() = default;
//------------------------------------------------------------------
// Callbacks
@@ -128,9 +125,9 @@ WatchpointOptions::InvokeCallback (StoppointCallbackContext *context,
{
if (m_callback && context->is_synchronous == IsCallbackSynchronous())
{
- return m_callback (m_callback_baton_sp ? m_callback_baton_sp->m_data : NULL,
- context,
- watch_id);
+ return m_callback(m_callback_baton_sp ? m_callback_baton_sp->m_data : nullptr,
+ context,
+ watch_id);
}
else
return true;
@@ -151,7 +148,7 @@ WatchpointOptions::GetThreadSpecNoCreate () const
ThreadSpec *
WatchpointOptions::GetThreadSpec ()
{
- if (m_thread_spec_ap.get() == NULL)
+ if (m_thread_spec_ap.get() == nullptr)
m_thread_spec_ap.reset (new ThreadSpec());
return m_thread_spec_ap.get();
@@ -172,14 +169,14 @@ WatchpointOptions::GetCallbackDescription (Stream *s, lldb::DescriptionLevel lev
m_callback_baton_sp->GetDescription (s, level);
}
}
+
void
WatchpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) const
{
-
// Figure out if there are any options not at their default value, and only print
// anything if there are:
- if ((GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ()))
+ if ((GetThreadSpecNoCreate() != nullptr && GetThreadSpecNoCreate()->HasSpecification ()))
{
if (level == lldb::eDescriptionLevelVerbose)
{
@@ -238,4 +235,3 @@ WatchpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLev
s->IndentLess ();
s->IndentLess ();
}
-
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectApropos.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectApropos.h
index f515417..d04620b 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectApropos.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectApropos.h
@@ -28,17 +28,14 @@ public:
CommandObjectApropos (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectApropos ();
+ ~CommandObjectApropos() override;
protected:
- virtual bool
- DoExecute (Args& command,
- CommandReturnObject &result);
-
-
+ bool
+ DoExecute(Args& command,
+ CommandReturnObject &result) override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectApropos_h_
+#endif // liblldb_CommandObjectApropos_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp
index cf32d10..9f22bba 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp
@@ -17,9 +17,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangFunction.h"
+#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -148,8 +146,14 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
result.SetStatus (eReturnStatusFailed);
return false;
}
-
- ClangASTContext &ast_context = thread_module_sp->GetClangASTContext();
+
+ TypeSystem *type_system = thread_module_sp->GetTypeSystemForLanguage(eLanguageTypeC);
+ if (type_system == nullptr)
+ {
+ result.AppendError ("Unable to create C type system.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
ValueList value_list;
@@ -158,7 +162,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
const char *arg_type_cstr = args.GetArgumentAtIndex(arg_index);
Value value;
value.SetValueType(Value::eValueTypeScalar);
- ClangASTType clang_type;
+ CompilerType compiler_type;
char *int_pos;
if ((int_pos = strstr (const_cast<char*>(arg_type_cstr), "int")))
@@ -200,10 +204,9 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
result.SetStatus (eReturnStatusFailed);
return false;
}
+ compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize(encoding, width);
- clang_type = ast_context.GetBuiltinTypeForEncodingAndBitSize(encoding, width);
-
- if (!clang_type.IsValid())
+ if (!compiler_type.IsValid())
{
result.AppendErrorWithFormat ("Couldn't get Clang type for format %s (%s integer, width %d).\n",
arg_type_cstr,
@@ -217,9 +220,9 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
else if (strchr (arg_type_cstr, '*'))
{
if (!strcmp (arg_type_cstr, "void*"))
- clang_type = ast_context.GetBasicType(eBasicTypeVoid).GetPointerType();
+ compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType();
else if (!strcmp (arg_type_cstr, "char*"))
- clang_type = ast_context.GetCStringType (false);
+ compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeChar).GetPointerType();
else
{
result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
@@ -234,7 +237,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
return false;
}
- value.SetClangType (clang_type);
+ value.SetCompilerType (compiler_type);
value_list.PushValue(value);
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.h
index 6691283..4a4e1c3 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.h
@@ -16,7 +16,6 @@
// Project includes
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/Options.h"
-#include "lldb/Core/Language.h"
namespace lldb_private {
@@ -30,17 +29,16 @@ namespace lldb_private {
CommandOptions (CommandInterpreter &interpreter);
- virtual
- ~CommandOptions ();
+ ~CommandOptions() override;
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg);
+ Error
+ SetOptionValue(uint32_t option_idx, const char *option_arg) override;
void
- OptionParsingStarting ();
+ OptionParsingStarting() override;
const OptionDefinition*
- GetDefinitions ();
+ GetDefinitions() override;
// Options table: Required for subclasses of Options.
@@ -49,24 +47,20 @@ namespace lldb_private {
CommandObjectArgs (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectArgs ();
+ ~CommandObjectArgs() override;
- virtual
Options *
- GetOptions ();
-
+ GetOptions() override;
protected:
CommandOptions m_options;
- virtual bool
- DoExecute ( Args& command,
- CommandReturnObject &result);
-
+ bool
+ DoExecute(Args& command,
+ CommandReturnObject &result) override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectArgs_h_
+#endif // liblldb_CommandObjectArgs_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.cpp
index 162bfb4..bb59e1f 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -26,7 +26,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/Target.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Target/StackFrame.h"
@@ -77,11 +77,10 @@ public:
}
- virtual
- ~CommandObjectBreakpointSet () {}
+ ~CommandObjectBreakpointSet () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -111,6 +110,7 @@ public:
m_throw_bp (true),
m_hardware (false),
m_exception_language (eLanguageTypeUnknown),
+ m_language (lldb::eLanguageTypeUnknown),
m_skip_prologue (eLazyBoolCalculate),
m_one_shot (false),
m_all_files (false),
@@ -119,11 +119,10 @@ public:
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -164,7 +163,7 @@ public:
case 'E':
{
- LanguageType language = LanguageRuntime::GetLanguageTypeFromString (option_arg);
+ LanguageType language = Language::GetLanguageTypeFromString (option_arg);
switch (language)
{
@@ -249,6 +248,12 @@ public:
break;
}
+ case 'L':
+ m_language = Language::GetLanguageTypeFromString (option_arg);
+ if (m_language == eLanguageTypeUnknown)
+ error.SetErrorStringWithFormat ("Unknown language type: '%s' for breakpoint", option_arg);
+ break;
+
case 'm':
{
bool success;
@@ -349,7 +354,7 @@ public:
return error;
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_condition.clear();
m_filenames.Clear();
@@ -370,6 +375,7 @@ public:
m_throw_bp = true;
m_hardware = false;
m_exception_language = eLanguageTypeUnknown;
+ m_language = lldb::eLanguageTypeUnknown;
m_skip_prologue = eLazyBoolCalculate;
m_one_shot = false;
m_use_dummy = false;
@@ -380,7 +386,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -411,6 +417,7 @@ public:
bool m_throw_bp;
bool m_hardware; // Request to use hardware breakpoints
lldb::LanguageType m_exception_language;
+ lldb::LanguageType m_language;
LazyBool m_skip_prologue;
bool m_one_shot;
bool m_use_dummy;
@@ -421,9 +428,9 @@ public:
};
protected:
- virtual bool
+ bool
DoExecute (Args& command,
- CommandReturnObject &result)
+ CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
@@ -500,11 +507,32 @@ protected:
break;
case eSetTypeAddress: // Breakpoint by address
- bp = target->CreateBreakpoint (m_options.m_load_addr,
- internal,
- m_options.m_hardware).get();
+ {
+ // If a shared library has been specified, make an lldb_private::Address with the library, and
+ // use that. That way the address breakpoint will track the load location of the library.
+ size_t num_modules_specified = m_options.m_modules.GetSize();
+ if (num_modules_specified == 1)
+ {
+ const FileSpec *file_spec = m_options.m_modules.GetFileSpecPointerAtIndex(0);
+ bp = target->CreateAddressInModuleBreakpoint (m_options.m_load_addr,
+ internal,
+ file_spec,
+ m_options.m_hardware).get();
+ }
+ else if (num_modules_specified == 0)
+ {
+ bp = target->CreateBreakpoint (m_options.m_load_addr,
+ internal,
+ m_options.m_hardware).get();
+ }
+ else
+ {
+ result.AppendError("Only one shared library can be specified for address breakpoints.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
break;
-
+ }
case eSetTypeFunctionName: // Breakpoint by function name
{
uint32_t name_type_mask = m_options.m_func_name_type_mask;
@@ -516,6 +544,7 @@ protected:
&(m_options.m_filenames),
m_options.m_func_names,
name_type_mask,
+ m_options.m_language,
m_options.m_skip_prologue,
internal,
m_options.m_hardware).get();
@@ -538,6 +567,7 @@ protected:
bp = target->CreateFuncRegexBreakpoint (&(m_options.m_modules),
&(m_options.m_filenames),
regexp,
+ m_options.m_language,
m_options.m_skip_prologue,
internal,
m_options.m_hardware).get();
@@ -709,6 +739,7 @@ private:
#define LLDB_OPT_NOT_10 ( LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10 )
#define LLDB_OPT_SKIP_PROLOGUE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3,8) )
#define LLDB_OPT_MOVE_TO_NEAREST_CODE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_9 )
+#define LLDB_OPT_EXPR_LANGUAGE ( LLDB_OPT_SET_FROM_TO(3, 8) )
OptionDefinition
CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
@@ -756,14 +787,21 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
// "Set the breakpoint by source location at this particular column."},
{ LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression,
- "Set the breakpoint by address, at the specified address."},
+ "Set the breakpoint at the specified address. "
+ "If the address maps uniquely to a particular "
+ "binary, then the address will be converted to a \"file\" address, so that the breakpoint will track that binary+offset no matter where "
+ "the binary eventually loads. "
+ "Alternately, if you also specify the module - with the -s option - then the address will be treated as "
+ "a file address in that module, and resolved accordingly. Again, this will allow lldb to track that offset on "
+ "subsequent reloads. The module need not have been loaded at the time you specify this breakpoint, and will "
+ "get resolved when the module is loaded."},
{ LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
"Set the breakpoint by function name. Can be repeated multiple times to make one breakpoint for multiple names" },
{ LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName,
"Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguments, and "
- "for Objective C this means a full function prototype with class and selector. "
+ "for Objective C this means a full function prototype with class and selector. "
"Can be repeated multiple times to make one breakpoint for multiple names." },
{ LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeSelector,
@@ -800,6 +838,9 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
// { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeTypeName,
// "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" },
+ { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,
+ "Specifies the Language to use when interpreting the breakpoint's expression (note: currently only implemented for setting breakpoints on identifiers). If not set the target.language setting is used." },
+
{ LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
"sKip the prologue if the breakpoint is at the beginning of a function. If not set the target.skip-prologue setting is used." },
@@ -840,11 +881,10 @@ public:
}
- virtual
- ~CommandObjectBreakpointModify () {}
+ ~CommandObjectBreakpointModify () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -874,11 +914,10 @@ public:
{
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -979,7 +1018,7 @@ public:
return error;
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_ignore_count = 0;
m_thread_id = LLDB_INVALID_THREAD_ID;
@@ -999,7 +1038,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1031,8 +1070,8 @@ public:
};
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
if (target == NULL)
@@ -1159,12 +1198,11 @@ public:
}
- virtual
- ~CommandObjectBreakpointEnable () {}
+ ~CommandObjectBreakpointEnable () override {}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget();
if (target == NULL)
@@ -1279,12 +1317,11 @@ the second re-enables the first location."
}
- virtual
- ~CommandObjectBreakpointDisable () {}
+ ~CommandObjectBreakpointDisable () override {}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget();
if (target == NULL)
@@ -1389,11 +1426,10 @@ public:
}
- virtual
- ~CommandObjectBreakpointList () {}
+ ~CommandObjectBreakpointList () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -1409,11 +1445,10 @@ public:
{
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1444,7 +1479,7 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_level = lldb::eDescriptionLevelFull;
m_internal = false;
@@ -1452,7 +1487,7 @@ public:
}
const OptionDefinition *
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1470,8 +1505,8 @@ public:
};
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
@@ -1586,11 +1621,10 @@ public:
{
}
- virtual
- ~CommandObjectBreakpointClear () {}
+ ~CommandObjectBreakpointClear () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -1606,11 +1640,10 @@ public:
{
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1634,14 +1667,14 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_filename.clear();
m_line_num = 0;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1658,8 +1691,8 @@ public:
};
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget();
if (target == NULL)
@@ -1786,11 +1819,10 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectBreakpointDelete () {}
+ ~CommandObjectBreakpointDelete () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -1806,11 +1838,10 @@ public:
{
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1834,14 +1865,14 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_use_dummy = false;
m_force = false;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1856,8 +1887,8 @@ public:
};
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
@@ -1976,27 +2007,26 @@ public:
}
- virtual
- ~BreakpointNameOptionGroup ()
+ ~BreakpointNameOptionGroup () override
{
}
- virtual uint32_t
- GetNumDefinitions ()
+ uint32_t
+ GetNumDefinitions () override
{
return sizeof (g_breakpoint_name_options) / sizeof (OptionDefinition);
}
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions () override
{
return g_breakpoint_name_options;
}
- virtual Error
+ Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
- const char *option_value)
+ const char *option_value) override
{
Error error;
const int short_option = g_breakpoint_name_options[option_idx].short_option;
@@ -2024,8 +2054,8 @@ public:
return error;
}
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter)
+ void
+ OptionParsingStarting (CommandInterpreter &interpreter) override
{
m_name.Clear();
m_breakpoint.Clear();
@@ -2062,18 +2092,17 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectBreakpointNameAdd () {}
+ ~CommandObjectBreakpointNameAdd () override {}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_option_group;
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
if (!m_name_options.m_name.OptionWasSet())
{
@@ -2158,18 +2187,17 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectBreakpointNameDelete () {}
+ ~CommandObjectBreakpointNameDelete () override {}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_option_group;
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
if (!m_name_options.m_name.OptionWasSet())
{
@@ -2243,18 +2271,17 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectBreakpointNameList () {}
+ ~CommandObjectBreakpointNameList () override {}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_option_group;
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
@@ -2339,8 +2366,7 @@ public:
}
- virtual
- ~CommandObjectBreakpointName ()
+ ~CommandObjectBreakpointName () override
{
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.h
index 3fdd2a5..123e823 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpoint.h
@@ -34,8 +34,7 @@ class CommandObjectMultiwordBreakpoint : public CommandObjectMultiword
public:
CommandObjectMultiwordBreakpoint (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectMultiwordBreakpoint ();
+ ~CommandObjectMultiwordBreakpoint() override;
static void
VerifyBreakpointOrLocationIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids)
@@ -56,4 +55,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_CommandObjectBreakpoint_h_
+#endif // liblldb_CommandObjectBreakpoint_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
index ac9c9a6..7b58bf9 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -178,17 +178,16 @@ are no syntax errors may indicate that a function was declared but never called.
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectBreakpointCommandAdd () {}
+ ~CommandObjectBreakpointCommandAdd () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
- virtual void
- IOHandlerActivated (IOHandler &io_handler)
+ void
+ IOHandlerActivated (IOHandler &io_handler) override
{
StreamFileSP output_sp(io_handler.GetOutputStreamFile());
if (output_sp)
@@ -199,8 +198,8 @@ are no syntax errors may indicate that a function was declared but never called.
}
- virtual void
- IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+ void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override
{
io_handler.SetIsDone(true);
@@ -315,11 +314,10 @@ are no syntax errors may indicate that a function was declared but never called.
{
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -374,7 +372,7 @@ are no syntax errors may indicate that a function was declared but never called.
return error;
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_use_commands = true;
m_use_script_language = false;
@@ -388,7 +386,7 @@ are no syntax errors may indicate that a function was declared but never called.
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -412,8 +410,8 @@ are no syntax errors may indicate that a function was declared but never called.
};
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
@@ -596,11 +594,10 @@ public:
}
- virtual
- ~CommandObjectBreakpointCommandDelete () {}
+ ~CommandObjectBreakpointCommandDelete () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -615,11 +612,10 @@ public:
{
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -639,13 +635,13 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_use_dummy = false;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -659,8 +655,8 @@ public:
};
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
@@ -764,13 +760,12 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectBreakpointCommandList () {}
+ ~CommandObjectBreakpointCommandList () override {}
protected:
- virtual bool
+ bool
DoExecute (Args& command,
- CommandReturnObject &result)
+ CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.h
index e917907..94afc78 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.h
@@ -13,7 +13,6 @@
// C Includes
// C++ Includes
-
// Other libraries and framework includes
// Project includes
@@ -23,7 +22,6 @@
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
-
namespace lldb_private {
//-------------------------------------------------------------------------
@@ -35,11 +33,9 @@ class CommandObjectBreakpointCommand : public CommandObjectMultiword
public:
CommandObjectBreakpointCommand (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectBreakpointCommand ();
-
+ ~CommandObjectBreakpointCommand() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectBreakpointCommand_h_
+#endif // liblldb_CommandObjectBreakpointCommand_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBugreport.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBugreport.cpp
index f171d2f..3d00cb8 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBugreport.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBugreport.cpp
@@ -43,7 +43,7 @@ public:
m_option_group.Finalize();
}
- ~CommandObjectBugreportUnwind()
+ ~CommandObjectBugreportUnwind() override
{
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBugreport.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBugreport.h
index d062e0d..3adde51 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBugreport.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBugreport.h
@@ -27,10 +27,9 @@ class CommandObjectMultiwordBugreport : public CommandObjectMultiword
public:
CommandObjectMultiwordBugreport(CommandInterpreter &interpreter);
- virtual
- ~CommandObjectMultiwordBugreport();
+ ~CommandObjectMultiwordBugreport() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectBugreport_h_
+#endif // liblldb_CommandObjectBugreport_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp
index f56d089..e859b5d 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp
@@ -47,10 +47,10 @@ public:
{
}
- ~CommandObjectCommandsHistory () {}
+ ~CommandObjectCommandsHistory () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -70,11 +70,10 @@ protected:
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -109,7 +108,7 @@ protected:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_start_idx.Clear();
m_stop_idx.Clear();
@@ -118,7 +117,7 @@ protected:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -136,7 +135,7 @@ protected:
};
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
if (m_options.m_clear.GetCurrentValue() && m_options.m_clear.OptionWasSet())
{
@@ -259,15 +258,15 @@ public:
m_arguments.push_back (arg);
}
- ~CommandObjectCommandsSource () {}
+ ~CommandObjectCommandsSource () override {}
- virtual const char*
- GetRepeatCommand (Args &current_command_args, uint32_t index)
+ const char*
+ GetRepeatCommand (Args &current_command_args, uint32_t index) override
{
return "";
}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -275,7 +274,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
@@ -291,8 +290,8 @@ public:
return matches.GetSize();
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -311,11 +310,10 @@ protected:
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -343,7 +341,7 @@ protected:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_stop_on_error.Clear();
m_silent_run.Clear();
@@ -351,7 +349,7 @@ protected:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -368,7 +366,7 @@ protected:
};
bool
- DoExecute(Args& command, CommandReturnObject &result)
+ DoExecute(Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
if (argc == 1)
@@ -553,13 +551,13 @@ rather than using a positional placeholder:" R"(
m_arguments.push_back (arg3);
}
- ~CommandObjectCommandsAlias ()
+ ~CommandObjectCommandsAlias () override
{
}
protected:
- virtual bool
- DoExecute (const char *raw_command_line, CommandReturnObject &result)
+ bool
+ DoExecute (const char *raw_command_line, CommandReturnObject &result) override
{
Args args (raw_command_line);
std::string raw_command_string (raw_command_line);
@@ -820,13 +818,13 @@ public:
m_arguments.push_back (arg);
}
- ~CommandObjectCommandsUnalias()
+ ~CommandObjectCommandsUnalias() override
{
}
protected:
bool
- DoExecute (Args& args, CommandReturnObject &result)
+ DoExecute (Args& args, CommandReturnObject &result) override
{
CommandObject::CommandMap::iterator pos;
CommandObject *cmd_obj;
@@ -913,13 +911,13 @@ public:
m_arguments.push_back (arg);
}
- ~CommandObjectCommandsDelete()
+ ~CommandObjectCommandsDelete() override
{
}
protected:
bool
- DoExecute (Args& args, CommandReturnObject &result)
+ DoExecute (Args& args, CommandReturnObject &result) override
{
CommandObject::CommandMap::iterator pos;
@@ -1000,7 +998,7 @@ a number follows 'f':" R"(
);
}
- ~CommandObjectCommandsAddRegex()
+ ~CommandObjectCommandsAddRegex() override
{
}
@@ -1250,11 +1248,10 @@ private:
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1277,14 +1274,14 @@ private:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_help.clear();
m_syntax.clear();
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1363,13 +1360,12 @@ public:
}
}
- virtual
- ~CommandObjectPythonFunction ()
+ ~CommandObjectPythonFunction () override
{
}
- virtual bool
- IsRemovable () const
+ bool
+ IsRemovable () const override
{
return true;
}
@@ -1386,8 +1382,8 @@ public:
return m_synchro;
}
- virtual const char *
- GetHelpLong ()
+ const char *
+ GetHelpLong () override
{
if (!m_fetched_help_long)
{
@@ -1404,8 +1400,8 @@ public:
}
protected:
- virtual bool
- DoExecute (const char *raw_command_line, CommandReturnObject &result)
+ bool
+ DoExecute (const char *raw_command_line, CommandReturnObject &result) override
{
ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
@@ -1470,13 +1466,12 @@ public:
GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
}
- virtual
- ~CommandObjectScriptingObject ()
+ ~CommandObjectScriptingObject () override
{
}
- virtual bool
- IsRemovable () const
+ bool
+ IsRemovable () const override
{
return true;
}
@@ -1493,8 +1488,8 @@ public:
return m_synchro;
}
- virtual const char *
- GetHelp ()
+ const char *
+ GetHelp () override
{
if (!m_fetched_help_short)
{
@@ -1510,8 +1505,8 @@ public:
return CommandObjectRaw::GetHelp();
}
- virtual const char *
- GetHelpLong ()
+ const char *
+ GetHelpLong () override
{
if (!m_fetched_help_long)
{
@@ -1528,8 +1523,8 @@ public:
}
protected:
- virtual bool
- DoExecute (const char *raw_command_line, CommandReturnObject &result)
+ bool
+ DoExecute (const char *raw_command_line, CommandReturnObject &result) override
{
ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
@@ -1592,11 +1587,11 @@ public:
m_arguments.push_back (arg1);
}
- ~CommandObjectCommandsScriptImport ()
+ ~CommandObjectCommandsScriptImport () override
{
}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -1604,7 +1599,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
@@ -1620,8 +1615,8 @@ public:
return matches.GetSize();
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -1637,11 +1632,10 @@ protected:
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1660,13 +1654,13 @@ protected:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_allow_reload = true;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1681,7 +1675,7 @@ protected:
};
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
{
@@ -1772,12 +1766,12 @@ public:
m_arguments.push_back (arg1);
}
- ~CommandObjectCommandsScriptAdd ()
+ ~CommandObjectCommandsScriptAdd () override
{
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -1797,11 +1791,10 @@ protected:
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1834,7 +1827,7 @@ protected:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_class_name.clear();
m_funct_name.clear();
@@ -1843,7 +1836,7 @@ protected:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1860,8 +1853,8 @@ protected:
ScriptedCommandSynchronicity m_synchronicity;
};
- virtual void
- IOHandlerActivated (IOHandler &io_handler)
+ void
+ IOHandlerActivated (IOHandler &io_handler) override
{
StreamFileSP output_sp(io_handler.GetOutputStreamFile());
if (output_sp)
@@ -1872,8 +1865,8 @@ protected:
}
- virtual void
- IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+ void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override
{
StreamFileSP error_sp = io_handler.GetErrorStreamFile();
@@ -1935,7 +1928,7 @@ protected:
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
@@ -2064,12 +2057,12 @@ public:
{
}
- ~CommandObjectCommandsScriptList ()
+ ~CommandObjectCommandsScriptList () override
{
}
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
m_interpreter.GetHelp(result,
@@ -2100,13 +2093,13 @@ public:
{
}
- ~CommandObjectCommandsScriptClear ()
+ ~CommandObjectCommandsScriptClear () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
m_interpreter.RemoveAllUser();
@@ -2144,13 +2137,13 @@ public:
m_arguments.push_back (arg1);
}
- ~CommandObjectCommandsScriptDelete ()
+ ~CommandObjectCommandsScriptDelete () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
size_t argc = command.GetArgumentCount();
@@ -2202,7 +2195,7 @@ public:
LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter)));
}
- ~CommandObjectMultiwordCommandsScript ()
+ ~CommandObjectMultiwordCommandsScript () override
{
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.h
index 8a56e8d..c12c710 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.h
@@ -30,11 +30,9 @@ public:
CommandObjectMultiwordCommands (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectMultiwordCommands ();
-
+ ~CommandObjectMultiwordCommands() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectCommands_h_
+#endif // liblldb_CommandObjectCommands_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp
index 1e575fe..100d869 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp
@@ -289,7 +289,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
if (!m_options.arch.IsValid())
{
- result.AppendError ("use the --arch option or set the target architecure to disassemble");
+ result.AppendError ("use the --arch option or set the target architecture to disassemble");
result.SetStatus (eReturnStatusFailed);
return false;
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.h
index 7a75098..d892824 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.h
@@ -33,17 +33,16 @@ public:
CommandOptions (CommandInterpreter &interpreter);
- virtual
- ~CommandOptions ();
+ ~CommandOptions() override;
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg);
+ Error
+ SetOptionValue(uint32_t option_idx, const char *option_arg) override;
void
- OptionParsingStarting ();
+ OptionParsingStarting() override;
const OptionDefinition*
- GetDefinitions ();
+ GetDefinitions() override;
const char *
GetPluginName ()
@@ -61,8 +60,8 @@ public:
return flavor_string.c_str();
}
- virtual Error
- OptionParsingFinished ();
+ Error
+ OptionParsingFinished() override;
bool show_mixed; // Show mixed source/assembly
bool show_bytes;
@@ -86,25 +85,22 @@ public:
CommandObjectDisassemble (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectDisassemble ();
+ ~CommandObjectDisassemble() override;
- virtual
Options *
- GetOptions ()
+ GetOptions() override
{
return &m_options;
}
protected:
- virtual bool
- DoExecute (Args& command,
- CommandReturnObject &result);
+ bool
+ DoExecute(Args& command,
+ CommandReturnObject &result) override;
CommandOptions m_options;
-
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectDisassemble_h_
+#endif // liblldb_CommandObjectDisassemble_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp
index 1be17a0..7f0b03b 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp
@@ -16,16 +16,16 @@
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangUserExpression.h"
-#include "lldb/Expression/ClangFunction.h"
+#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Expression/REPL.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Language.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/Process.h"
@@ -63,6 +63,7 @@ CommandObjectExpression::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."},
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."},
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language setting is used." },
{ LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, NULL, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."},
};
@@ -84,12 +85,11 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int
switch (short_option)
{
- //case 'l':
- //if (language.SetLanguageFromCString (option_arg) == false)
- //{
- // error.SetErrorStringWithFormat("invalid language option argument '%s'", option_arg);
- //}
- //break;
+ case 'l':
+ language = Language::GetLanguageTypeFromString (option_arg);
+ if (language == eLanguageTypeUnknown)
+ error.SetErrorStringWithFormat ("unknown language type: '%s' for expression", option_arg);
+ break;
case 'a':
{
@@ -180,6 +180,7 @@ CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpret
try_all_threads = true;
timeout = 0;
debug = false;
+ language = eLanguageTypeUnknown;
m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
}
@@ -192,12 +193,13 @@ CommandObjectExpression::CommandOptions::GetDefinitions ()
CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) :
CommandObjectRaw (interpreter,
"expression",
- "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.",
+ "Evaluate an expression in the current program context, using user defined variables and variables currently in scope.",
NULL,
eCommandProcessMustBePaused | eCommandTryTargetAPILock),
IOHandlerDelegate (IOHandlerDelegate::Completion::Expression),
m_option_group (interpreter),
m_format_options (eFormatDefault),
+ m_repl_option (LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false, true),
m_command_options (),
m_expr_line_count (0),
m_expr_lines ()
@@ -253,6 +255,7 @@ Examples:
m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1);
m_option_group.Append (&m_command_options);
m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
+ m_option_group.Append (&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
m_option_group.Finalize();
}
@@ -288,8 +291,8 @@ CommandObjectExpression::EvaluateExpression
if (target)
{
lldb::ValueObjectSP result_valobj_sp;
-
bool keep_in_memory = true;
+ StackFrame *frame = exe_ctx.GetFramePtr();
EvaluateExpressionOptions options;
options.SetCoerceToId(m_varobj_options.use_objc);
@@ -299,7 +302,8 @@ CommandObjectExpression::EvaluateExpression
options.SetUseDynamic(m_varobj_options.use_dynamic);
options.SetTryAllThreads(m_command_options.try_all_threads);
options.SetDebug(m_command_options.debug);
-
+ options.SetLanguage(m_command_options.language);
+
// If there is any chance we are going to stop and want to see
// what went wrong with our expression, we should generate debug info
if (!m_command_options.ignore_breakpoints ||
@@ -311,8 +315,7 @@ CommandObjectExpression::EvaluateExpression
else
options.SetTimeoutUsec(0);
- target->EvaluateExpression(expr, exe_ctx.GetFramePtr(),
- result_valobj_sp, options);
+ target->EvaluateExpression(expr, frame, result_valobj_sp, options);
if (result_valobj_sp)
{
@@ -326,6 +329,7 @@ CommandObjectExpression::EvaluateExpression
result_valobj_sp->SetFormat (format);
DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format));
+ options.SetVariableFormatDisplayLanguage(result_valobj_sp->GetPreferredDisplayLanguage());
result_valobj_sp->Dump(*output_stream,options);
@@ -335,7 +339,7 @@ CommandObjectExpression::EvaluateExpression
}
else
{
- if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult)
+ if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult)
{
if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid())
{
@@ -501,8 +505,70 @@ CommandObjectExpression::DoExecute
return false;
}
+ if (m_repl_option.GetOptionValue().GetCurrentValue())
+ {
+ Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
+ if (target)
+ {
+ // Drop into REPL
+ m_expr_lines.clear();
+ m_expr_line_count = 0;
+
+ Debugger &debugger = target->GetDebugger();
+
+ // Check if the LLDB command interpreter is sitting on top of a REPL that
+ // launched it...
+ if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter, IOHandler::Type::REPL))
+ {
+ // the LLDB command interpreter is sitting on top of a REPL that launched it,
+ // so just say the command interpreter is done and fall back to the existing REPL
+ m_interpreter.GetIOHandler(false)->SetIsDone(true);
+ }
+ else
+ {
+ // We are launching the REPL on top of the current LLDB command interpreter,
+ // so just push one
+ bool initialize = false;
+ Error repl_error;
+ REPLSP repl_sp (target->GetREPL(repl_error, m_command_options.language, nullptr, false));
+
+ if (!repl_sp)
+ {
+ initialize = true;
+ repl_sp = target->GetREPL(repl_error, m_command_options.language, nullptr, true);
+ if (!repl_error.Success())
+ {
+ result.SetError(repl_error);
+ return result.Succeeded();
+ }
+ }
+
+ if (repl_sp)
+ {
+ if (initialize)
+ {
+ repl_sp->SetCommandOptions(m_command_options);
+ repl_sp->SetFormatOptions(m_format_options);
+ repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
+ }
+
+ IOHandlerSP io_handler_sp (repl_sp->GetIOHandler());
+
+ io_handler_sp->SetIsDone(false);
+
+ debugger.PushIOHandler(io_handler_sp);
+ }
+ else
+ {
+ repl_error.SetErrorStringWithFormat("Couldn't create a REPL for %s", Language::GetNameForLanguageType(m_command_options.language));
+ result.SetError(repl_error);
+ return result.Succeeded();
+ }
+ }
+ }
+ }
// No expression following options
- if (expr == NULL || expr[0] == '\0')
+ else if (expr == NULL || expr[0] == '\0')
{
GetMultilineExpression ();
return result.Succeeded();
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h
index 168140d..7103675 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h
@@ -16,6 +16,7 @@
// Project includes
#include "lldb/Core/IOHandler.h"
#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Target/ExecutionContext.h"
@@ -34,22 +35,21 @@ public:
CommandOptions ();
- virtual
- ~CommandOptions ();
+ ~CommandOptions() override;
- virtual uint32_t
- GetNumDefinitions ();
+ uint32_t
+ GetNumDefinitions() override;
- virtual const OptionDefinition*
- GetDefinitions ();
+ const OptionDefinition*
+ GetDefinitions() override;
- virtual Error
- SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_value);
+ Error
+ SetOptionValue(CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override;
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter);
+ void
+ OptionParsingStarting(CommandInterpreter &interpreter) override;
// Options table: Required for subclasses of Options.
@@ -61,35 +61,34 @@ public:
bool debug;
uint32_t timeout;
bool try_all_threads;
+ lldb::LanguageType language;
LanguageRuntimeDescriptionDisplayVerbosity m_verbosity;
};
CommandObjectExpression (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectExpression ();
+ ~CommandObjectExpression() override;
- virtual
Options *
- GetOptions ();
+ GetOptions() override;
protected:
//------------------------------------------------------------------
// IOHandler::Delegate functions
//------------------------------------------------------------------
- virtual void
- IOHandlerInputComplete (IOHandler &io_handler,
- std::string &line);
+ void
+ IOHandlerInputComplete(IOHandler &io_handler,
+ std::string &line) override;
virtual LineStatus
IOHandlerLinesUpdated (IOHandler &io_handler,
StringList &lines,
uint32_t line_idx,
Error &error);
- virtual bool
- DoExecute (const char *command,
- CommandReturnObject &result);
+ bool
+ DoExecute(const char *command,
+ CommandReturnObject &result) override;
bool
EvaluateExpression (const char *expr,
@@ -103,6 +102,7 @@ protected:
OptionGroupOptions m_option_group;
OptionGroupFormat m_format_options;
OptionGroupValueObjectDisplay m_varobj_options;
+ OptionGroupBoolean m_repl_option;
CommandOptions m_command_options;
uint32_t m_expr_line_count;
std::string m_expr_lines; // Multi-line expression support
@@ -110,4 +110,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_CommandObjectExpression_h_
+#endif // liblldb_CommandObjectExpression_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp
index d8b65e3..9477b50 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.cpp
@@ -33,8 +33,9 @@
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionGroupVariable.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
@@ -70,13 +71,13 @@ public:
{
}
- ~CommandObjectFrameInfo ()
+ ~CommandObjectFrameInfo () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat (&result.GetOutputStream());
result.SetStatus (eReturnStatusSuccessFinishResult);
@@ -104,13 +105,12 @@ public:
OptionParsingStarting ();
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
bool success = false;
@@ -132,13 +132,13 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
relative_frame_offset = INT32_MIN;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -174,13 +174,12 @@ public:
m_arguments.push_back (arg);
}
- ~CommandObjectFrameSelect ()
+ ~CommandObjectFrameSelect () override
{
}
- virtual
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
@@ -188,7 +187,7 @@ public:
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
// No need to check "thread" for validity as eCommandRequiresThread ensures it is valid
Thread *thread = m_exe_ctx.GetThreadPtr();
@@ -263,8 +262,10 @@ protected:
}
else
{
- result.AppendError ("invalid arguments.\n");
+ result.AppendErrorWithFormat ("too many arguments; expected frame-index, saw '%s'.\n",
+ command.GetArgumentAtIndex(0));
m_options.GenerateOptionUsage (result.GetErrorStream(), this);
+ return false;
}
}
@@ -341,20 +342,18 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectFrameVariable ()
+ ~CommandObjectFrameVariable () override
{
}
- virtual
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_option_group;
}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -362,7 +361,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
// Arguments are the standard source file completer.
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
@@ -380,8 +379,8 @@ public:
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
// No need to check "frame" for validity as eCommandRequiresFrame ensures it is valid
StackFrame *frame = m_exe_ctx.GetFramePtr();
@@ -409,6 +408,10 @@ protected:
DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,eFormatDefault,summary_format_sp));
+ const SymbolContext& sym_ctx = frame->GetSymbolContext(eSymbolContextFunction);
+ if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
+ m_option_variable.show_globals = true;
+
if (variable_list)
{
const Format format = m_option_format.GetFormat();
@@ -477,7 +480,8 @@ protected:
{
Error error;
uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember |
- StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
+ StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
+ StackFrame::eExpressionPathOptionsInspectAnonymousUnions;
lldb::VariableSP var_sp;
valobj_sp = frame->GetValueForVariableExpressionPath (name_cstr,
m_varobj_options.use_dynamic,
@@ -495,6 +499,7 @@ protected:
}
options.SetFormat(format);
+ options.SetVariableFormatDisplayLanguage(valobj_sp->GetPreferredDisplayLanguage());
Stream &output_stream = result.GetOutputStream();
options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : NULL);
@@ -581,6 +586,7 @@ protected:
}
options.SetFormat(format);
+ options.SetVariableFormatDisplayLanguage(valobj_sp->GetPreferredDisplayLanguage());
options.SetRootValueObjectName(name_cstr);
valobj_sp->Dump(result.GetOutputStream(),options);
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.h
index ea7c808..a729880 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectFrame.h
@@ -30,11 +30,9 @@ public:
CommandObjectMultiwordFrame (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectMultiwordFrame ();
-
+ ~CommandObjectMultiwordFrame() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectFrame_h_
+#endif // liblldb_CommandObjectFrame_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectGUI.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectGUI.h
index 72ddb96..494bcc4 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectGUI.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectGUI.h
@@ -28,16 +28,14 @@ public:
CommandObjectGUI (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectGUI ();
+ ~CommandObjectGUI() override;
protected:
- virtual bool
- DoExecute (Args& args,
- CommandReturnObject &result);
-
+ bool
+ DoExecute(Args& args,
+ CommandReturnObject &result) override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectGUI_h_
+#endif // liblldb_CommandObjectGUI_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.h
index 7db659c..1dd7b9b 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectHelp.h
@@ -29,17 +29,16 @@ public:
CommandObjectHelp (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectHelp ();
+ ~CommandObjectHelp() override;
- virtual int
- HandleCompletion (Args &input,
- int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches);
+ int
+ HandleCompletion(Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) override;
class CommandOptions : public Options
{
@@ -50,11 +49,10 @@ public:
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions() override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue(uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -79,7 +77,7 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting() override
{
m_show_aliases = true;
m_show_user_defined = true;
@@ -87,7 +85,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions() override
{
return g_option_table;
}
@@ -103,22 +101,21 @@ public:
bool m_show_hidden;
};
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions() override
{
return &m_options;
}
protected:
- virtual bool
- DoExecute (Args& command,
- CommandReturnObject &result);
+ bool
+ DoExecute(Args& command,
+ CommandReturnObject &result) override;
private:
CommandOptions m_options;
-
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectHelp_h_
+#endif // liblldb_CommandObjectHelp_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectLanguage.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectLanguage.cpp
index 9d4b856..5a8f166 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectLanguage.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectLanguage.cpp
@@ -14,6 +14,7 @@
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
using namespace lldb;
@@ -33,10 +34,6 @@ CommandObjectMultiword (interpreter,
void
CommandObjectLanguage::GenerateHelpText (Stream &output_stream) {
CommandObjectMultiword::GenerateHelpText(output_stream);
-
- output_stream << "\nlanguage name can be one of the following:\n";
-
- LanguageRuntime::PrintAllLanguages(output_stream, " ", "\n");
}
CommandObjectLanguage::~CommandObjectLanguage ()
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectLanguage.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectLanguage.h
index 751fe14..15902bb 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectLanguage.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectLanguage.h
@@ -13,7 +13,6 @@
// C Includes
// C++ Includes
-
// Other libraries and framework includes
// Project includes
@@ -26,11 +25,10 @@ namespace lldb_private {
public:
CommandObjectLanguage (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectLanguage ();
+ ~CommandObjectLanguage() override;
- virtual void
- GenerateHelpText (Stream &output_stream);
+ void
+ GenerateHelpText(Stream &output_stream) override;
protected:
bool
@@ -38,4 +36,4 @@ namespace lldb_private {
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectLanguage_h_
+#endif // liblldb_CommandObjectLanguage_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.cpp
index e68eaf1..8e29cd5 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.cpp
@@ -77,13 +77,12 @@ public:
m_arguments.push_back (arg2);
}
- virtual
- ~CommandObjectLogEnable()
+ ~CommandObjectLogEnable() override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
@@ -122,13 +121,12 @@ public:
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -154,14 +152,14 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
log_file.Clear();
log_options = 0;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -177,9 +175,9 @@ public:
};
protected:
- virtual bool
+ bool
DoExecute (Args& args,
- CommandReturnObject &result)
+ CommandReturnObject &result) override
{
if (args.GetArgumentCount() < 2)
{
@@ -260,15 +258,14 @@ public:
m_arguments.push_back (arg2);
}
- virtual
- ~CommandObjectLogDisable()
+ ~CommandObjectLogDisable() override
{
}
protected:
- virtual bool
+ bool
DoExecute (Args& args,
- CommandReturnObject &result)
+ CommandReturnObject &result) override
{
const size_t argc = args.GetArgumentCount();
if (argc == 0)
@@ -332,15 +329,14 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectLogList()
+ ~CommandObjectLogList() override
{
}
protected:
- virtual bool
+ bool
DoExecute (Args& args,
- CommandReturnObject &result)
+ CommandReturnObject &result) override
{
const size_t argc = args.GetArgumentCount();
if (argc == 0)
@@ -396,15 +392,14 @@ public:
{
}
- virtual
- ~CommandObjectLogTimer()
+ ~CommandObjectLogTimer() override
{
}
protected:
- virtual bool
+ bool
DoExecute (Args& args,
- CommandReturnObject &result)
+ CommandReturnObject &result) override
{
const size_t argc = args.GetArgumentCount();
result.SetStatus(eReturnStatusFailed);
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.h
index 3e731fa..be5215f2 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectLog.h
@@ -33,8 +33,7 @@ public:
//------------------------------------------------------------------
CommandObjectLog(CommandInterpreter &interpreter);
- virtual
- ~CommandObjectLog();
+ ~CommandObjectLog() override;
private:
//------------------------------------------------------------------
@@ -45,4 +44,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_CommandObjectLog_h_
+#endif // liblldb_CommandObjectLog_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.cpp
index d589800..f8fe456 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.cpp
@@ -23,7 +23,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -33,6 +33,7 @@
#include "lldb/Interpreter/OptionGroupOutputFile.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionValueString.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/MemoryHistory.h"
#include "lldb/Target/Process.h"
@@ -48,6 +49,7 @@ g_option_table[] =
{ LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
{ LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."},
{ LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
+ { LLDB_OPT_SET_3, false , "offset" ,'E', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount ,"How many elements of the specified type to skip before starting to display data."},
{ LLDB_OPT_SET_1|
LLDB_OPT_SET_2|
LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
@@ -62,32 +64,32 @@ public:
OptionGroupReadMemory () :
m_num_per_line (1,1),
m_output_as_binary (false),
- m_view_as_type()
+ m_view_as_type(),
+ m_offset(0,0)
{
}
- virtual
- ~OptionGroupReadMemory ()
+ ~OptionGroupReadMemory () override
{
}
- virtual uint32_t
- GetNumDefinitions ()
+ uint32_t
+ GetNumDefinitions () override
{
return sizeof (g_option_table) / sizeof (OptionDefinition);
}
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions () override
{
return g_option_table;
}
- virtual Error
+ Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
- const char *option_arg)
+ const char *option_arg) override
{
Error error;
const int short_option = g_option_table[option_idx].short_option;
@@ -112,6 +114,10 @@ public:
m_force = true;
break;
+ case 'E':
+ error = m_offset.SetValueFromString(option_arg);
+ break;
+
default:
error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
break;
@@ -119,13 +125,14 @@ public:
return error;
}
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter)
+ void
+ OptionParsingStarting (CommandInterpreter &interpreter) override
{
m_num_per_line.Clear();
m_output_as_binary = false;
m_view_as_type.Clear();
m_force = false;
+ m_offset.Clear();
}
Error
@@ -271,6 +278,7 @@ public:
case eFormatVectorOfUInt32:
case eFormatVectorOfSInt64:
case eFormatVectorOfUInt64:
+ case eFormatVectorOfFloat16:
case eFormatVectorOfFloat32:
case eFormatVectorOfFloat64:
case eFormatVectorOfUInt128:
@@ -290,13 +298,15 @@ public:
{
return m_num_per_line.OptionWasSet() ||
m_output_as_binary ||
- m_view_as_type.OptionWasSet();
+ m_view_as_type.OptionWasSet() ||
+ m_offset.OptionWasSet();
}
OptionValueUInt64 m_num_per_line;
bool m_output_as_binary;
OptionValueString m_view_as_type;
bool m_force;
+ OptionValueUInt64 m_offset;
};
@@ -366,25 +376,25 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectMemoryRead ()
+ ~CommandObjectMemoryRead () override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_option_group;
}
- virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
+ const char *
+ GetRepeatCommand (Args &current_command_args, uint32_t index) override
{
return m_cmd_name.c_str();
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
// No need to check "target" for validity as eCommandRequiresTarget ensures it is valid
Target *target = m_exe_ctx.GetTargetPtr();
@@ -399,7 +409,7 @@ protected:
return false;
}
- ClangASTType clang_ast_type;
+ CompilerType clang_ast_type;
Error error;
const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
@@ -526,16 +536,21 @@ protected:
1,
type_list);
}
-
+
if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
{
- clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
- if (tdecl)
+ if (ClangPersistentVariables *persistent_vars = llvm::dyn_cast_or_null<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)))
{
- clang_ast_type.SetClangType(&tdecl->getASTContext(),(const lldb::clang_type_t)tdecl->getTypeForDecl());
+ clang::TypeDecl *tdecl = persistent_vars->GetPersistentType(ConstString(lookup_type_name));
+
+ if (tdecl)
+ {
+ clang_ast_type.SetCompilerType(ClangASTContext::GetASTContext(&tdecl->getASTContext()),
+ reinterpret_cast<lldb::opaque_compiler_type_t>(const_cast<clang::Type*>(tdecl->getTypeForDecl())));
+ }
}
}
-
+
if (clang_ast_type.IsValid() == false)
{
if (type_list.GetSize() == 0)
@@ -549,13 +564,13 @@ protected:
else
{
TypeSP type_sp (type_list.GetTypeAtIndex(0));
- clang_ast_type = type_sp->GetClangFullType();
+ clang_ast_type = type_sp->GetFullCompilerType ();
}
}
while (pointer_count > 0)
{
- ClangASTType pointer_type = clang_ast_type.GetPointerType();
+ CompilerType pointer_type = clang_ast_type.GetPointerType();
if (pointer_type.IsValid())
clang_ast_type = pointer_type;
else
@@ -691,6 +706,9 @@ protected:
m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue();
+
+ if (argc > 0)
+ addr = addr + (clang_ast_type.GetByteSize(nullptr) * m_memory_options.m_offset.GetCurrentValue());
}
else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
{
@@ -932,7 +950,7 @@ protected:
OptionGroupReadMemory m_prev_memory_options;
OptionGroupOutputFile m_prev_outfile_options;
OptionGroupValueObjectDisplay m_prev_varobj_options;
- ClangASTType m_prev_clang_ast_type;
+ CompilerType m_prev_clang_ast_type;
};
OptionDefinition
@@ -961,27 +979,26 @@ public:
{
}
- virtual
- ~OptionGroupFindMemory ()
+ ~OptionGroupFindMemory () override
{
}
- virtual uint32_t
- GetNumDefinitions ()
+ uint32_t
+ GetNumDefinitions () override
{
return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
}
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions () override
{
return g_memory_find_option_table;
}
- virtual Error
+ Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
- const char *option_arg)
+ const char *option_arg) override
{
Error error;
const int short_option = g_memory_find_option_table[option_idx].short_option;
@@ -1013,8 +1030,8 @@ public:
return error;
}
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter)
+ void
+ OptionParsingStarting (CommandInterpreter &interpreter) override
{
m_expr.Clear();
m_string.Clear();
@@ -1042,15 +1059,15 @@ public:
CommandArgumentData value_arg;
// Define the first (and only) variant of this arg.
- addr_arg.arg_type = eArgTypeAddress;
+ addr_arg.arg_type = eArgTypeAddressOrExpression;
addr_arg.arg_repetition = eArgRepeatPlain;
// There is only one variant this argument could be; put it into the argument entry.
arg1.push_back (addr_arg);
// Define the first (and only) variant of this arg.
- value_arg.arg_type = eArgTypeValue;
- value_arg.arg_repetition = eArgRepeatPlus;
+ value_arg.arg_type = eArgTypeAddressOrExpression;
+ value_arg.arg_repetition = eArgRepeatPlain;
// There is only one variant this argument could be; put it into the argument entry.
arg2.push_back (value_arg);
@@ -1063,20 +1080,19 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectMemoryFind ()
+ ~CommandObjectMemoryFind () override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_option_group;
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
// No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Process *process = m_exe_ctx.GetProcessPtr();
@@ -1119,10 +1135,11 @@ protected:
{
StackFrame* frame = m_exe_ctx.GetFramePtr();
ValueObjectSP result_sp;
- if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get())
+ if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
+ result_sp.get())
{
uint64_t value = result_sp->GetValueAsUnsigned(0);
- switch (result_sp->GetClangType().GetByteSize(nullptr))
+ switch (result_sp->GetCompilerType().GetByteSize(nullptr))
{
case 1: {
uint8_t byte = (uint8_t)value;
@@ -1150,13 +1167,13 @@ protected:
result.AppendError("unknown type. pass a string instead");
return false;
default:
- result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead");
+ result.AppendError("result size larger than 8 bytes. pass a string instead");
return false;
}
}
else
{
- result.AppendError("expression evaluation failed. pass a string instead?");
+ result.AppendError("expression evaluation failed. pass a string instead");
return false;
}
}
@@ -1176,14 +1193,14 @@ protected:
{
if (!ever_found)
{
- result.AppendMessage("Your data was not found within the range.\n");
+ result.AppendMessage("data not found within the range.\n");
result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
}
else
- result.AppendMessage("No more matches found within the range.\n");
+ result.AppendMessage("no more matches within the range.\n");
break;
}
- result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location);
+ result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location);
DataBufferHeap dumpbuffer(32,0);
process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
@@ -1211,27 +1228,16 @@ protected:
{
Process *process = m_exe_ctx.GetProcessPtr();
DataBufferHeap heap(buffer_size, 0);
- lldb::addr_t fictional_ptr = low;
for (auto ptr = low;
- low < high;
- fictional_ptr++)
+ ptr < high;
+ ptr++)
{
Error error;
- if (ptr == low || buffer_size == 1)
- process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
- else
- {
- memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1);
- process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error);
- }
+ process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
if (error.Fail())
return LLDB_INVALID_ADDRESS;
if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
- return fictional_ptr;
- if (ptr == low)
- ptr += buffer_size;
- else
- ptr += 1;
+ return ptr;
}
return LLDB_INVALID_ADDRESS;
}
@@ -1263,27 +1269,26 @@ public:
{
}
- virtual
- ~OptionGroupWriteMemory ()
+ ~OptionGroupWriteMemory () override
{
}
- virtual uint32_t
- GetNumDefinitions ()
+ uint32_t
+ GetNumDefinitions () override
{
return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
}
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions () override
{
return g_memory_write_option_table;
}
- virtual Error
+ Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
- const char *option_arg)
+ const char *option_arg) override
{
Error error;
const int short_option = g_memory_write_option_table[option_idx].short_option;
@@ -1317,8 +1322,8 @@ public:
return error;
}
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter)
+ void
+ OptionParsingStarting (CommandInterpreter &interpreter) override
{
m_infile.Clear();
m_infile_offset = 0;
@@ -1368,13 +1373,12 @@ public:
}
- virtual
- ~CommandObjectMemoryWrite ()
+ ~CommandObjectMemoryWrite () override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_option_group;
}
@@ -1407,8 +1411,8 @@ public:
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
// No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Process *process = m_exe_ctx.GetProcessPtr();
@@ -1528,6 +1532,7 @@ protected:
case eFormatVectorOfUInt32:
case eFormatVectorOfSInt64:
case eFormatVectorOfUInt64:
+ case eFormatVectorOfFloat16:
case eFormatVectorOfFloat32:
case eFormatVectorOfFloat64:
case eFormatVectorOfUInt128:
@@ -1716,19 +1721,19 @@ public:
m_arguments.push_back (arg1);
}
- virtual
- ~CommandObjectMemoryHistory ()
+ ~CommandObjectMemoryHistory () override
{
}
- virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
+ const char *
+ GetRepeatCommand (Args &current_command_args, uint32_t index) override
{
return m_cmd_name.c_str();
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.h
index b044921..cf5b441 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMemory.h
@@ -23,11 +23,9 @@ class CommandObjectMemory : public CommandObjectMultiword
public:
CommandObjectMemory (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectMemory ();
+ ~CommandObjectMemory() override;
};
-
} // namespace lldb_private
-#endif // liblldb_CommandObjectMemory_h_
+#endif // liblldb_CommandObjectMemory_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp
index 2f0e2a7..206f3b6 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp
@@ -382,6 +382,14 @@ CommandObjectProxy::IsMultiwordObject ()
return false;
}
+void
+CommandObjectProxy::GenerateHelpText (Stream &result)
+{
+ CommandObject *proxy_command = GetProxyCommandObject();
+ if (proxy_command)
+ return proxy_command->GenerateHelpText(result);
+}
+
lldb::CommandObjectSP
CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches)
{
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.cpp
index a0979d0..aad8bea 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -86,15 +86,14 @@ public:
{
}
- virtual
- ~OptionPermissions ()
+ ~OptionPermissions () override
{
}
- virtual lldb_private::Error
+ lldb_private::Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
- const char *option_arg)
+ const char *option_arg) override
{
Error error;
char short_option = (char) GetDefinitions()[option_idx].short_option;
@@ -155,19 +154,19 @@ public:
}
void
- OptionParsingStarting (CommandInterpreter &interpreter)
+ OptionParsingStarting (CommandInterpreter &interpreter) override
{
m_permissions = 0;
}
- virtual uint32_t
- GetNumDefinitions ()
+ uint32_t
+ GetNumDefinitions () override
{
return llvm::array_lengthof(g_permissions_options);
}
const lldb_private::OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_permissions_options;
}
@@ -198,19 +197,18 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectPlatformSelect ()
+ ~CommandObjectPlatformSelect () override
{
}
- virtual int
+ int
HandleCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
@@ -225,15 +223,15 @@ public:
return matches.GetSize();
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_option_group;
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
if (args.GetArgumentCount() == 1)
{
@@ -291,14 +289,13 @@ public:
{
}
- virtual
- ~CommandObjectPlatformList ()
+ ~CommandObjectPlatformList () override
{
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
Stream &ostrm = result.GetOutputStream();
ostrm.Printf("Available platforms:\n");
@@ -346,14 +343,13 @@ public:
{
}
- virtual
- ~CommandObjectPlatformStatus ()
+ ~CommandObjectPlatformStatus () override
{
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
Stream &ostrm = result.GetOutputStream();
@@ -396,14 +392,13 @@ public:
{
}
- virtual
- ~CommandObjectPlatformConnect ()
+ ~CommandObjectPlatformConnect () override
{
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
Stream &ostrm = result.GetOutputStream();
@@ -414,12 +409,19 @@ protected:
if (error.Success())
{
platform_sp->GetStatus (ostrm);
- result.SetStatus (eReturnStatusSuccessFinishResult);
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+
+ platform_sp->ConnectToWaitingProcesses(m_interpreter.GetDebugger(), error);
+ if (error.Fail())
+ {
+ result.AppendError (error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
}
else
{
result.AppendErrorWithFormat ("%s\n", error.AsCString());
- result.SetStatus (eReturnStatusFailed);
+ result.SetStatus (eReturnStatusFailed);
}
}
else
@@ -430,8 +432,8 @@ protected:
return result.Succeeded();
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
OptionGroupOptions* m_platform_options = NULL;
@@ -461,14 +463,13 @@ public:
{
}
- virtual
- ~CommandObjectPlatformDisconnect ()
+ ~CommandObjectPlatformDisconnect () override
{
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
if (platform_sp)
@@ -543,14 +544,13 @@ public:
m_options.Append (&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
}
- virtual
- ~CommandObjectPlatformSettings ()
+ ~CommandObjectPlatformSettings () override
{
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
if (platform_sp)
@@ -566,8 +566,8 @@ protected:
return result.Succeeded();
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
if (m_options.DidFinalize() == false)
m_options.Finalize();
@@ -597,13 +597,12 @@ public:
{
}
- virtual
- ~CommandObjectPlatformMkDir ()
+ ~CommandObjectPlatformMkDir () override
{
}
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
if (platform_sp)
@@ -635,8 +634,8 @@ public:
return result.Succeeded();
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
if (m_options.DidFinalize() == false)
{
@@ -665,13 +664,12 @@ public:
{
}
- virtual
- ~CommandObjectPlatformFOpen ()
+ ~CommandObjectPlatformFOpen () override
{
}
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
if (platform_sp)
@@ -708,8 +706,8 @@ public:
}
return result.Succeeded();
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
if (m_options.DidFinalize() == false)
{
@@ -736,13 +734,12 @@ public:
{
}
- virtual
- ~CommandObjectPlatformFClose ()
+ ~CommandObjectPlatformFClose () override
{
}
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
if (platform_sp)
@@ -788,13 +785,12 @@ public:
{
}
- virtual
- ~CommandObjectPlatformFRead ()
+ ~CommandObjectPlatformFRead () override
{
}
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
if (platform_sp)
@@ -816,8 +812,8 @@ public:
}
return result.Succeeded();
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -832,13 +828,12 @@ protected:
{
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
char short_option = (char) m_getopt_table[option_idx].val;
@@ -866,14 +861,14 @@ protected:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_offset = 0;
m_count = 1;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -914,13 +909,12 @@ public:
{
}
- virtual
- ~CommandObjectPlatformFWrite ()
+ ~CommandObjectPlatformFWrite () override
{
}
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
if (platform_sp)
@@ -944,8 +938,8 @@ public:
}
return result.Succeeded();
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -960,13 +954,12 @@ protected:
{
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
char short_option = (char) m_getopt_table[option_idx].val;
@@ -992,14 +985,14 @@ protected:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_offset = 0;
m_data.clear();
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1041,8 +1034,7 @@ public:
LoadSubCommand ("write", CommandObjectSP (new CommandObjectPlatformFWrite (interpreter)));
}
- virtual
- ~CommandObjectPlatformFile ()
+ ~CommandObjectPlatformFile () override
{
}
@@ -1094,13 +1086,12 @@ R"(Examples:
m_arguments.push_back (arg2);
}
- virtual
- ~CommandObjectPlatformGetFile ()
+ ~CommandObjectPlatformGetFile () override
{
}
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
// If the number of arguments is incorrect, issue an error message.
if (args.GetArgumentCount() != 2)
@@ -1172,13 +1163,12 @@ R"(Examples:
m_arguments.push_back (arg1);
}
- virtual
- ~CommandObjectPlatformGetSize ()
+ ~CommandObjectPlatformGetSize () override
{
}
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
// If the number of arguments is incorrect, issue an error message.
if (args.GetArgumentCount() != 1)
@@ -1228,13 +1218,12 @@ public:
{
}
- virtual
- ~CommandObjectPlatformPutFile ()
+ ~CommandObjectPlatformPutFile () override
{
}
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
const char* src = args.GetArgumentAtIndex(0);
const char* dst = args.GetArgumentAtIndex(1);
@@ -1281,20 +1270,19 @@ public:
{
}
- virtual
- ~CommandObjectPlatformProcessLaunch ()
+ ~CommandObjectPlatformProcessLaunch () override
{
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
PlatformSP platform_sp;
@@ -1398,20 +1386,19 @@ public:
{
}
- virtual
- ~CommandObjectPlatformProcessList ()
+ ~CommandObjectPlatformProcessList () override
{
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
PlatformSP platform_sp;
@@ -1524,13 +1511,12 @@ protected:
{
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1620,7 +1606,7 @@ protected:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
match_info.Clear();
show_args = false;
@@ -1628,7 +1614,7 @@ protected:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1698,14 +1684,13 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectPlatformProcessInfo ()
+ ~CommandObjectPlatformProcessInfo () override
{
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
PlatformSP platform_sp;
@@ -1793,12 +1778,12 @@ public:
OptionParsingStarting ();
}
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
char short_option = (char) m_getopt_table[option_idx].val;
@@ -1839,18 +1824,18 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
attach_info.Clear();
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
- virtual bool
+ bool
HandleOptionArgumentCompletion (Args &input,
int cursor_index,
int char_pos,
@@ -1859,7 +1844,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
@@ -1921,13 +1906,13 @@ public:
{
}
- ~CommandObjectPlatformProcessAttach ()
+ ~CommandObjectPlatformProcessAttach () override
{
}
bool
DoExecute (Args& command,
- CommandReturnObject &result)
+ CommandReturnObject &result) override
{
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
if (platform_sp)
@@ -1957,7 +1942,7 @@ public:
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
@@ -1998,8 +1983,7 @@ public:
}
- virtual
- ~CommandObjectPlatformProcess ()
+ ~CommandObjectPlatformProcess () override
{
}
@@ -2027,8 +2011,7 @@ public:
{
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
@@ -2038,15 +2021,15 @@ public:
return 1;
}
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions () override
{
return g_option_table;
}
- virtual Error
+ Error
SetOptionValue (uint32_t option_idx,
- const char *option_value)
+ const char *option_value) override
{
Error error;
@@ -2070,8 +2053,8 @@ public:
return error;
}
- virtual void
- OptionParsingStarting ()
+ void
+ OptionParsingStarting () override
{
}
@@ -2091,20 +2074,18 @@ public:
{
}
- virtual
- ~CommandObjectPlatformShell ()
+ ~CommandObjectPlatformShell () override
{
}
- virtual
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
- virtual bool
- DoExecute (const char *raw_command_line, CommandReturnObject &result)
+ bool
+ DoExecute (const char *raw_command_line, CommandReturnObject &result) override
{
m_options.NotifyOptionParsingStarting();
@@ -2218,13 +2199,12 @@ public:
{
}
- virtual
- ~CommandObjectPlatformInstall ()
+ ~CommandObjectPlatformInstall () override
{
}
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
if (args.GetArgumentCount() != 2)
{
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.h
index f3bd758..023dff9 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlatform.h
@@ -28,13 +28,12 @@ class CommandObjectPlatform : public CommandObjectMultiword
public:
CommandObjectPlatform(CommandInterpreter &interpreter);
- virtual
- ~CommandObjectPlatform();
+ ~CommandObjectPlatform() override;
- private:
+private:
DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatform);
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectPlatform_h_
+#endif // liblldb_CommandObjectPlatform_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.cpp
index 63fa4a8..4c5a089 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.cpp
@@ -41,7 +41,7 @@ public:
m_arguments.push_back (arg1);
}
- ~CommandObjectPluginLoad ()
+ ~CommandObjectPluginLoad () override
{
}
@@ -53,7 +53,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
@@ -71,7 +71,7 @@ public:
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
size_t argc = command.GetArgumentCount();
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.h
index 9d0f0fc..0a96041 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectPlugin.h
@@ -13,7 +13,6 @@
// C Includes
// C++ Includes
-
// Other libraries and framework includes
// Project includes
@@ -27,10 +26,9 @@ namespace lldb_private {
public:
CommandObjectPlugin (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectPlugin ();
+ ~CommandObjectPlugin() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectPlugin_h_
+#endif // liblldb_CommandObjectPlugin_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp
index e587ead..a85ea17 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp
@@ -47,7 +47,7 @@ public:
CommandObjectParsed (interpreter, name, help, syntax, flags),
m_new_process_action (new_process_action) {}
- virtual ~CommandObjectProcessLaunchOrAttach () {}
+ ~CommandObjectProcessLaunchOrAttach () override {}
protected:
bool
StopProcessIfNecessary (Process *process, StateType &state, CommandReturnObject &result)
@@ -142,11 +142,11 @@ public:
}
- ~CommandObjectProcessLaunch ()
+ ~CommandObjectProcessLaunch () override
{
}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -154,7 +154,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
@@ -171,12 +171,13 @@ public:
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
- virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
+ const char *
+ GetRepeatCommand (Args &current_command_args, uint32_t index) override
{
// No repeat for "process launch"...
return "";
@@ -184,7 +185,7 @@ public:
protected:
bool
- DoExecute (Args& launch_args, CommandReturnObject &result)
+ DoExecute (Args& launch_args, CommandReturnObject &result) override
{
Debugger &debugger = m_interpreter.GetDebugger();
Target *target = debugger.GetSelectedTarget().get();
@@ -338,12 +339,12 @@ public:
OptionParsingStarting ();
}
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -392,18 +393,18 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
attach_info.Clear();
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
- virtual bool
+ bool
HandleOptionArgumentCompletion (Args &input,
int cursor_index,
int char_pos,
@@ -412,7 +413,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
@@ -476,20 +477,19 @@ public:
{
}
- ~CommandObjectProcessAttach ()
+ ~CommandObjectProcessAttach () override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
@@ -550,6 +550,7 @@ protected:
result.AppendMessage(stream.GetData());
result.SetStatus (eReturnStatusSuccessFinishNoResult);
result.SetDidChangeProcessState (true);
+ result.SetAbnormalStopWasExpected(true);
}
else
{
@@ -646,7 +647,7 @@ public:
}
- ~CommandObjectProcessContinue ()
+ ~CommandObjectProcessContinue () override
{
}
@@ -663,12 +664,12 @@ protected:
OptionParsingStarting ();
}
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -689,13 +690,13 @@ protected:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_ignore = 0;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -708,7 +709,7 @@ protected:
};
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Process *process = m_exe_ctx.GetProcessPtr();
bool synchronous_execution = m_interpreter.GetSynchronous ();
@@ -807,7 +808,7 @@ protected:
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
@@ -842,12 +843,12 @@ public:
OptionParsingStarting ();
}
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -876,13 +877,13 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_keep_stopped = eLazyBoolCalculate;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -907,12 +908,12 @@ public:
{
}
- ~CommandObjectProcessDetach ()
+ ~CommandObjectProcessDetach () override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
@@ -920,7 +921,7 @@ public:
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Process *process = m_exe_ctx.GetProcessPtr();
// FIXME: This will be a Command Option:
@@ -982,12 +983,12 @@ public:
OptionParsingStarting ();
}
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1006,13 +1007,13 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
plugin_name.clear();
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1036,94 +1037,61 @@ public:
{
}
- ~CommandObjectProcessConnect ()
+ ~CommandObjectProcessConnect () override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
-
- TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
- Error error;
- Process *process = m_exe_ctx.GetProcessPtr();
- if (process)
+ if (command.GetArgumentCount() != 1)
{
- if (process->IsAlive())
- {
- result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n",
- process->GetID());
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
+ result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n",
+ m_cmd_name.c_str(),
+ m_cmd_syntax.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
}
+
- if (!target_sp)
+ Process *process = m_exe_ctx.GetProcessPtr();
+ if (process && process->IsAlive())
{
- // If there isn't a current target create one.
-
- error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
- NULL,
- NULL,
- false,
- NULL, // No platform options
- target_sp);
- if (!target_sp || error.Fail())
- {
- result.AppendError(error.AsCString("Error creating target"));
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
+ result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n",
+ process->GetID());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
}
-
- if (command.GetArgumentCount() == 1)
- {
- const char *plugin_name = NULL;
- if (!m_options.plugin_name.empty())
- plugin_name = m_options.plugin_name.c_str();
- const char *remote_url = command.GetArgumentAtIndex(0);
- process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
-
- if (process)
- {
- error = process->ConnectRemote (process->GetTarget().GetDebugger().GetOutputFile().get(), remote_url);
+ const char *plugin_name = nullptr;
+ if (!m_options.plugin_name.empty())
+ plugin_name = m_options.plugin_name.c_str();
- if (error.Fail())
- {
- result.AppendError(error.AsCString("Remote connect failed"));
- result.SetStatus (eReturnStatusFailed);
- target_sp->DeleteCurrentProcess();
- return false;
- }
- }
- else
- {
- result.AppendErrorWithFormat ("Unable to find process plug-in for remote URL '%s'.\nPlease specify a process plug-in name with the --plugin option, or specify an object file using the \"file\" command.\n",
- remote_url);
- result.SetStatus (eReturnStatusFailed);
- }
- }
- else
+ Error error;
+ Debugger& debugger = m_interpreter.GetDebugger();
+ PlatformSP platform_sp = m_interpreter.GetPlatform(true);
+ ProcessSP process_sp = platform_sp->ConnectProcess(command.GetArgumentAtIndex(0),
+ plugin_name,
+ debugger,
+ debugger.GetSelectedTarget().get(),
+ error);
+ if (error.Fail() || process_sp == nullptr)
{
- result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n",
- m_cmd_name.c_str(),
- m_cmd_syntax.c_str());
+ result.AppendError(error.AsCString("Error connecting to the process"));
result.SetStatus (eReturnStatusFailed);
+ return false;
}
- return result.Succeeded();
+ return true;
}
-
+
CommandOptions m_options;
};
@@ -1152,12 +1120,12 @@ public:
{
}
- ~CommandObjectProcessPlugin ()
+ ~CommandObjectProcessPlugin () override
{
}
- virtual CommandObject *
- GetProxyCommandObject()
+ CommandObject *
+ GetProxyCommandObject() override
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
if (process)
@@ -1175,6 +1143,57 @@ public:
class CommandObjectProcessLoad : public CommandObjectParsed
{
public:
+ class CommandOptions : public Options
+ {
+ public:
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options(interpreter)
+ {
+ // Keep default values of all options in one place: OptionParsingStarting ()
+ OptionParsingStarting ();
+ }
+
+ ~CommandOptions () override = default;
+
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+ switch (short_option)
+ {
+ case 'i':
+ do_install = true;
+ if (option_arg && option_arg[0])
+ install_path.SetFile(option_arg, false);
+ break;
+ default:
+ error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
+ break;
+ }
+ return error;
+ }
+
+ void
+ OptionParsingStarting () override
+ {
+ do_install = false;
+ install_path.Clear();
+ }
+
+ const OptionDefinition*
+ GetDefinitions () override
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ bool do_install;
+ FileSpec install_path;
+ };
CommandObjectProcessLoad (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
@@ -1184,33 +1203,54 @@ public:
eCommandRequiresProcess |
eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched |
- eCommandProcessMustBePaused )
+ eCommandProcessMustBePaused ),
+ m_options (interpreter)
{
}
- ~CommandObjectProcessLoad ()
+ ~CommandObjectProcessLoad () override = default;
+
+ Options *
+ GetOptions () override
{
+ return &m_options;
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Process *process = m_exe_ctx.GetProcessPtr();
const size_t argc = command.GetArgumentCount();
-
for (uint32_t i=0; i<argc; ++i)
{
Error error;
+ PlatformSP platform = process->GetTarget().GetPlatform();
const char *image_path = command.GetArgumentAtIndex(i);
- FileSpec image_spec (image_path, false);
- process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec);
- uint32_t image_token = process->LoadImage(image_spec, error);
+ uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
+
+ if (!m_options.do_install)
+ {
+ FileSpec image_spec (image_path, false);
+ platform->ResolveRemotePath(image_spec, image_spec);
+ image_token = platform->LoadImage(process, FileSpec(), image_spec, error);
+ }
+ else if (m_options.install_path)
+ {
+ FileSpec image_spec (image_path, true);
+ platform->ResolveRemotePath(m_options.install_path, m_options.install_path);
+ image_token = platform->LoadImage(process, image_spec, m_options.install_path, error);
+ }
+ else
+ {
+ FileSpec image_spec (image_path, true);
+ image_token = platform->LoadImage(process, image_spec, FileSpec(), error);
+ }
+
if (image_token != LLDB_INVALID_IMAGE_TOKEN)
{
- result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
+ result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
result.SetStatus (eReturnStatusSuccessFinishResult);
}
else
@@ -1221,8 +1261,16 @@ protected:
}
return result.Succeeded();
}
+
+ CommandOptions m_options;
};
+OptionDefinition
+CommandObjectProcessLoad::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypePath, "Install the shared library to the target. If specified without an argument then the library will installed in the current working directory."},
+ { 0, false, nullptr, 0 , 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
+};
//-------------------------------------------------------------------------
// CommandObjectProcessUnload
@@ -1245,14 +1293,13 @@ public:
{
}
- ~CommandObjectProcessUnload ()
+ ~CommandObjectProcessUnload () override
{
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Process *process = m_exe_ctx.GetProcessPtr();
@@ -1270,7 +1317,7 @@ protected:
}
else
{
- Error error (process->UnloadImage(image_token));
+ Error error (process->GetTarget().GetPlatform()->UnloadImage(process, image_token));
if (error.Success())
{
result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
@@ -1318,14 +1365,13 @@ public:
m_arguments.push_back (arg);
}
- ~CommandObjectProcessSignal ()
+ ~CommandObjectProcessSignal () override
{
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Process *process = m_exe_ctx.GetProcessPtr();
@@ -1390,14 +1436,13 @@ public:
{
}
- ~CommandObjectProcessInterrupt ()
+ ~CommandObjectProcessInterrupt () override
{
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Process *process = m_exe_ctx.GetProcessPtr();
if (process == NULL)
@@ -1452,14 +1497,13 @@ public:
{
}
- ~CommandObjectProcessKill ()
+ ~CommandObjectProcessKill () override
{
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Process *process = m_exe_ctx.GetProcessPtr();
if (process == NULL)
@@ -1513,14 +1557,14 @@ public:
{
}
- ~CommandObjectProcessSaveCore ()
+ ~CommandObjectProcessSaveCore () override
{
}
protected:
bool
DoExecute (Args& command,
- CommandReturnObject &result)
+ CommandReturnObject &result) override
{
ProcessSP process_sp = m_exe_ctx.GetProcessSP();
if (process_sp)
@@ -1575,13 +1619,13 @@ public:
{
}
- ~CommandObjectProcessStatus()
+ ~CommandObjectProcessStatus() override
{
}
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Stream &strm = result.GetOutputStream();
result.SetStatus (eReturnStatusSuccessFinishNoResult);
@@ -1620,12 +1664,12 @@ public:
OptionParsingStarting ();
}
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1649,7 +1693,7 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
stop.clear();
notify.clear();
@@ -1657,7 +1701,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1694,12 +1738,12 @@ public:
m_arguments.push_back (arg);
}
- ~CommandObjectProcessHandle ()
+ ~CommandObjectProcessHandle () override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
@@ -1781,7 +1825,7 @@ public:
protected:
bool
- DoExecute (Args &signal_args, CommandReturnObject &result)
+ DoExecute (Args &signal_args, CommandReturnObject &result) override
{
TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.h
index 0aaa74d..804c342 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.h
@@ -27,11 +27,9 @@ class CommandObjectMultiwordProcess : public CommandObjectMultiword
public:
CommandObjectMultiwordProcess (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectMultiwordProcess ();
-
+ ~CommandObjectMultiwordProcess() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectProcess_h_
+#endif // liblldb_CommandObjectProcess_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.h
index aab0e26..df9216b 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.h
@@ -28,19 +28,17 @@ public:
CommandObjectQuit (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectQuit ();
+ ~CommandObjectQuit() override;
protected:
- virtual bool
- DoExecute (Args& args,
- CommandReturnObject &result);
+ bool
+ DoExecute(Args& args,
+ CommandReturnObject &result) override;
bool
ShouldAskForConfirmation (bool& is_a_detach);
-
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectQuit_h_
+#endif // liblldb_CommandObjectQuit_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp
index fae5af4..23a2157 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp
@@ -74,13 +74,12 @@ public:
}
- virtual
- ~CommandObjectRegisterRead ()
+ ~CommandObjectRegisterRead () override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_option_group;
}
@@ -170,8 +169,8 @@ public:
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Stream &strm = result.GetOutputStream();
RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
@@ -271,33 +270,32 @@ protected:
{
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual uint32_t
- GetNumDefinitions ();
+ uint32_t
+ GetNumDefinitions () override;
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions () override
{
return g_option_table;
}
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter)
+ void
+ OptionParsingStarting (CommandInterpreter &interpreter) override
{
set_indexes.Clear();
dump_all_sets.Clear();
alternate_name.Clear();
}
- virtual Error
+ Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
- const char *option_value)
+ const char *option_value) override
{
Error error;
const int short_option = g_option_table[option_idx].short_option;
@@ -404,14 +402,13 @@ public:
m_arguments.push_back (arg2);
}
- virtual
- ~CommandObjectRegisterWrite ()
+ ~CommandObjectRegisterWrite () override
{
}
protected:
- virtual bool
- DoExecute(Args& command, CommandReturnObject &result)
+ bool
+ DoExecute(Args& command, CommandReturnObject &result) override
{
DataExtractor reg_data;
RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.h
index 7f856c2..e7b6974 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.h
@@ -30,8 +30,7 @@ public:
//------------------------------------------------------------------
CommandObjectRegister(CommandInterpreter &interpreter);
- virtual
- ~CommandObjectRegister();
+ ~CommandObjectRegister() override;
private:
//------------------------------------------------------------------
@@ -42,4 +41,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_CommandObjectRegister_h_
+#endif // liblldb_CommandObjectRegister_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.cpp
index 8ed783b..890d770 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.cpp
@@ -83,15 +83,14 @@ insert-before or insert-after."
}
- virtual
- ~CommandObjectSettingsSet () {}
+ ~CommandObjectSettingsSet () override {}
// Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
- virtual bool
- WantsCompletion() { return true; }
+ bool
+ WantsCompletion() override { return true; }
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -106,11 +105,10 @@ insert-before or insert-after."
{
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -129,13 +127,13 @@ insert-before or insert-after."
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_global = false;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -149,7 +147,7 @@ insert-before or insert-after."
bool m_global;
};
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -157,7 +155,7 @@ insert-before or insert-after."
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
@@ -215,8 +213,8 @@ insert-before or insert-after."
}
protected:
- virtual bool
- DoExecute (const char *command, CommandReturnObject &result)
+ bool
+ DoExecute (const char *command, CommandReturnObject &result) override
{
Args cmd_args(command);
@@ -321,11 +319,10 @@ public:
m_arguments.push_back (arg1);
}
- virtual
- ~CommandObjectSettingsShow () {}
+ ~CommandObjectSettingsShow () override {}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -333,7 +330,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
@@ -349,8 +346,8 @@ public:
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
result.SetStatus (eReturnStatusSuccessFinishResult);
@@ -414,10 +411,9 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectSettingsList () {}
+ ~CommandObjectSettingsList () override {}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -425,7 +421,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
@@ -441,8 +437,8 @@ public:
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
result.SetStatus (eReturnStatusSuccessFinishResult);
@@ -521,10 +517,9 @@ public:
m_arguments.push_back (arg2);
}
- virtual
- ~CommandObjectSettingsRemove () {}
+ ~CommandObjectSettingsRemove () override {}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -532,7 +527,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
@@ -551,8 +546,8 @@ public:
}
protected:
- virtual bool
- DoExecute (const char *command, CommandReturnObject &result)
+ bool
+ DoExecute (const char *command, CommandReturnObject &result) override
{
result.SetStatus (eReturnStatusSuccessFinishNoResult);
@@ -652,14 +647,13 @@ public:
}
- virtual
- ~CommandObjectSettingsReplace () {}
+ ~CommandObjectSettingsReplace () override {}
// Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
- virtual bool
- WantsCompletion() { return true; }
+ bool
+ WantsCompletion() override { return true; }
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -667,7 +661,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
@@ -686,8 +680,8 @@ public:
}
protected:
- virtual bool
- DoExecute (const char *command, CommandReturnObject &result)
+ bool
+ DoExecute (const char *command, CommandReturnObject &result) override
{
result.SetStatus (eReturnStatusSuccessFinishNoResult);
@@ -773,14 +767,13 @@ public:
m_arguments.push_back (arg3);
}
- virtual
- ~CommandObjectSettingsInsertBefore () {}
+ ~CommandObjectSettingsInsertBefore () override {}
// Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
- virtual bool
- WantsCompletion() { return true; }
+ bool
+ WantsCompletion() override { return true; }
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -788,7 +781,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
@@ -807,8 +800,8 @@ public:
}
protected:
- virtual bool
- DoExecute (const char *command, CommandReturnObject &result)
+ bool
+ DoExecute (const char *command, CommandReturnObject &result) override
{
result.SetStatus (eReturnStatusSuccessFinishNoResult);
@@ -897,14 +890,13 @@ public:
m_arguments.push_back (arg3);
}
- virtual
- ~CommandObjectSettingsInsertAfter () {}
+ ~CommandObjectSettingsInsertAfter () override {}
// Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
- virtual bool
- WantsCompletion() { return true; }
+ bool
+ WantsCompletion() override { return true; }
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -912,7 +904,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
@@ -931,8 +923,8 @@ public:
}
protected:
- virtual bool
- DoExecute (const char *command, CommandReturnObject &result)
+ bool
+ DoExecute (const char *command, CommandReturnObject &result) override
{
result.SetStatus (eReturnStatusSuccessFinishNoResult);
@@ -1011,14 +1003,13 @@ public:
m_arguments.push_back (arg2);
}
- virtual
- ~CommandObjectSettingsAppend () {}
+ ~CommandObjectSettingsAppend () override {}
// Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
- virtual bool
- WantsCompletion() { return true; }
+ bool
+ WantsCompletion() override { return true; }
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -1026,7 +1017,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
@@ -1045,8 +1036,8 @@ public:
}
protected:
- virtual bool
- DoExecute (const char *command, CommandReturnObject &result)
+ bool
+ DoExecute (const char *command, CommandReturnObject &result) override
{
result.SetStatus (eReturnStatusSuccessFinishNoResult);
Args cmd_args(command);
@@ -1117,10 +1108,9 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectSettingsClear () {}
+ ~CommandObjectSettingsClear () override {}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -1128,7 +1118,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
@@ -1147,8 +1137,8 @@ public:
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
result.SetStatus (eReturnStatusSuccessFinishNoResult);
const size_t argc = command.GetArgumentCount ();
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.h
index eca7ade..93ee919 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSettings.h
@@ -31,11 +31,9 @@ public:
CommandObjectMultiwordSettings (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectMultiwordSettings ();
-
+ ~CommandObjectMultiwordSettings() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectSettings_h_
+#endif // liblldb_CommandObjectSettings_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp
index 7c5f127..a9e52d1 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp
@@ -27,6 +27,7 @@
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/StackFrame.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/Options.h"
@@ -34,9 +35,11 @@
using namespace lldb;
using namespace lldb_private;
-//-------------------------------------------------------------------------
-// CommandObjectSourceInfo
-//-------------------------------------------------------------------------
+
+#pragma mark CommandObjectSourceInfo
+//----------------------------------------------------------------------
+// CommandObjectSourceInfo - debug line entries dumping command
+//----------------------------------------------------------------------
class CommandObjectSourceInfo : public CommandObjectParsed
{
@@ -44,50 +47,75 @@ class CommandObjectSourceInfo : public CommandObjectParsed
class CommandOptions : public Options
{
public:
- CommandOptions (CommandInterpreter &interpreter) :
- Options(interpreter)
- {
- }
+ CommandOptions (CommandInterpreter &interpreter) : Options(interpreter) {}
- ~CommandOptions ()
- {
- }
+ ~CommandOptions () override {}
Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = g_option_table[option_idx].short_option;
switch (short_option)
{
- case 'l':
- start_line = StringConvert::ToUInt32 (option_arg, 0);
- if (start_line == 0)
- error.SetErrorStringWithFormat("invalid line number: '%s'", option_arg);
- break;
-
- case 'f':
- file_name = option_arg;
- break;
-
- default:
- error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
+ case 'l':
+ start_line = StringConvert::ToUInt32(option_arg, 0);
+ if (start_line == 0)
+ error.SetErrorStringWithFormat("invalid line number: '%s'", option_arg);
+ break;
+
+ case 'e':
+ end_line = StringConvert::ToUInt32(option_arg, 0);
+ if (end_line == 0)
+ error.SetErrorStringWithFormat("invalid line number: '%s'", option_arg);
+ break;
+
+ case 'c':
+ num_lines = StringConvert::ToUInt32(option_arg, 0);
+ if (num_lines == 0)
+ error.SetErrorStringWithFormat("invalid line count: '%s'", option_arg);
+ break;
+
+ case 'f':
+ file_name = option_arg;
+ break;
+
+ case 'n':
+ symbol_name = option_arg;
+ break;
+
+ case 'a':
+ {
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
+ address = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
+ }
break;
+ case 's':
+ modules.push_back(std::string(option_arg));
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
+ break;
}
return error;
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
file_spec.Clear();
file_name.clear();
+ symbol_name.clear();
+ address = LLDB_INVALID_ADDRESS;
start_line = 0;
+ end_line = 0;
+ num_lines = 0;
+ modules.clear();
}
- const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition *
+ GetDefinitions () override
{
return g_option_table;
}
@@ -96,51 +124,602 @@ class CommandObjectSourceInfo : public CommandObjectParsed
// Instance variables to hold the values for command options.
FileSpec file_spec;
std::string file_name;
+ std::string symbol_name;
+ lldb::addr_t address;
uint32_t start_line;
-
+ uint32_t end_line;
+ uint32_t num_lines;
+ STLStringArray modules;
};
-
-public:
- CommandObjectSourceInfo(CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "source info",
- "Display information about the source lines from the current executable's debug info.",
- "source info [<cmd-options>]"),
- m_options (interpreter)
- {
- }
- ~CommandObjectSourceInfo ()
+public:
+ CommandObjectSourceInfo (CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "source info", "Display source line information (as specified) based "
+ "on the current executable's debug info.",
+ NULL, eCommandRequiresTarget),
+ m_options(interpreter)
{
}
+ ~CommandObjectSourceInfo () override {}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
protected:
+
+ // Dump the line entries in each symbol context.
+ // Return the number of entries found.
+ // If module_list is set, only dump lines contained in one of the modules.
+ // If file_spec is set, only dump lines in the file.
+ // If the start_line option was specified, don't print lines less than start_line.
+ // If the end_line option was specified, don't print lines greater than end_line.
+ // If the num_lines option was specified, dont print more than num_lines entries.
+ uint32_t
+ DumpLinesInSymbolContexts (Stream &strm, const SymbolContextList &sc_list,
+ const ModuleList &module_list, const FileSpec &file_spec)
+ {
+ uint32_t start_line = m_options.start_line;
+ uint32_t end_line = m_options.end_line;
+ uint32_t num_lines = m_options.num_lines;
+ Target *target = m_exe_ctx.GetTargetPtr();
+
+ uint32_t num_matches = 0;
+ bool has_path = false;
+ if (file_spec)
+ {
+ assert(file_spec.GetFilename().AsCString());
+ has_path = (file_spec.GetDirectory().AsCString() != 0);
+ }
+
+ // Dump all the line entries for the file in the list.
+ ConstString last_module_file_name;
+ uint32_t num_scs = sc_list.GetSize();
+ for (uint32_t i = 0; i < num_scs; ++i)
+ {
+ SymbolContext sc;
+ sc_list.GetContextAtIndex(i, sc);
+ if (sc.comp_unit)
+ {
+ Module *module = sc.module_sp.get();
+ CompileUnit *cu = sc.comp_unit;
+ const LineEntry &line_entry = sc.line_entry;
+ assert(module && cu);
+
+ // Are we looking for specific modules, files or lines?
+ if (module_list.GetSize() && module_list.GetIndexForModule(module) == LLDB_INVALID_INDEX32)
+ continue;
+ if (file_spec && !lldb_private::FileSpec::Equal(file_spec, line_entry.file, has_path))
+ continue;
+ if (start_line > 0 && line_entry.line < start_line)
+ continue;
+ if (end_line > 0 && line_entry.line > end_line)
+ continue;
+ if (num_lines > 0 && num_matches > num_lines)
+ continue;
+
+ // Print a new header if the module changed.
+ const ConstString &module_file_name = module->GetFileSpec().GetFilename();
+ assert(module_file_name);
+ if (module_file_name != last_module_file_name)
+ {
+ if (num_matches > 0)
+ strm << "\n\n";
+ strm << "Lines found in module `" << module_file_name << "\n";
+ }
+ // Dump the line entry.
+ line_entry.GetDescription(&strm, lldb::eDescriptionLevelBrief, cu,
+ target, /*show_address_only=*/false);
+ strm << "\n";
+ last_module_file_name = module_file_name;
+ num_matches++;
+ }
+ }
+ return num_matches;
+ }
+
+ // Dump the requested line entries for the file in the compilation unit.
+ // Return the number of entries found.
+ // If module_list is set, only dump lines contained in one of the modules.
+ // If the start_line option was specified, don't print lines less than start_line.
+ // If the end_line option was specified, don't print lines greater than end_line.
+ // If the num_lines option was specified, dont print more than num_lines entries.
+ uint32_t
+ DumpFileLinesInCompUnit (Stream &strm, Module *module, CompileUnit *cu, const FileSpec &file_spec)
+ {
+ uint32_t start_line = m_options.start_line;
+ uint32_t end_line = m_options.end_line;
+ uint32_t num_lines = m_options.num_lines;
+ Target *target = m_exe_ctx.GetTargetPtr();
+
+ uint32_t num_matches = 0;
+ assert(module);
+ if (cu)
+ {
+ assert(file_spec.GetFilename().AsCString());
+ bool has_path = (file_spec.GetDirectory().AsCString() != 0);
+ const FileSpecList &cu_file_list = cu->GetSupportFiles();
+ size_t file_idx = cu_file_list.FindFileIndex(0, file_spec, has_path);
+ if (file_idx != UINT32_MAX)
+ {
+ // Update the file to how it appears in the CU.
+ const FileSpec &cu_file_spec = cu_file_list.GetFileSpecAtIndex(file_idx);
+
+ // Dump all matching lines at or above start_line for the file in the CU.
+ const ConstString &file_spec_name = file_spec.GetFilename();
+ const ConstString &module_file_name = module->GetFileSpec().GetFilename();
+ bool cu_header_printed = false;
+ uint32_t line = start_line;
+ while (true)
+ {
+ LineEntry line_entry;
+
+ // Find the lowest index of a line entry with a line equal to
+ // or higher than 'line'.
+ uint32_t start_idx = 0;
+ start_idx = cu->FindLineEntry(start_idx, line, &cu_file_spec,
+ /*exact=*/false, &line_entry);
+ if (start_idx == UINT32_MAX)
+ // No more line entries for our file in this CU.
+ break;
+
+ if (end_line > 0 && line_entry.line > end_line)
+ break;
+
+ // Loop through to find any other entries for this line, dumping each.
+ line = line_entry.line;
+ do
+ {
+ num_matches++;
+ if (num_lines > 0 && num_matches > num_lines)
+ break;
+ assert(lldb_private::FileSpec::Equal(cu_file_spec, line_entry.file, has_path));
+ if (!cu_header_printed)
+ {
+ if (num_matches > 0)
+ strm << "\n\n";
+ strm << "Lines found for file " << file_spec_name
+ << " in compilation unit " << cu->GetFilename()
+ << " in `" << module_file_name << "\n";
+ cu_header_printed = true;
+ }
+ line_entry.GetDescription(&strm, lldb::eDescriptionLevelBrief, cu,
+ target, /*show_address_only=*/false);
+ strm << "\n";
+
+ // Anymore after this one?
+ start_idx++;
+ start_idx = cu->FindLineEntry(start_idx, line, &cu_file_spec,
+ /*exact=*/true, &line_entry);
+ } while (start_idx != UINT32_MAX);
+
+ // Try the next higher line, starting over at start_idx 0.
+ line++;
+ }
+ }
+ }
+ return num_matches;
+ }
+
+ // Dump the requested line entries for the file in the module.
+ // Return the number of entries found.
+ // If module_list is set, only dump lines contained in one of the modules.
+ // If the start_line option was specified, don't print lines less than start_line.
+ // If the end_line option was specified, don't print lines greater than end_line.
+ // If the num_lines option was specified, dont print more than num_lines entries.
+ uint32_t
+ DumpFileLinesInModule (Stream &strm, Module *module, const FileSpec &file_spec)
+ {
+ uint32_t num_matches = 0;
+ if (module)
+ {
+ // Look through all the compilation units (CUs) in this module for ones that
+ // contain lines of code from this source file.
+ for (size_t i = 0; i < module->GetNumCompileUnits(); i++)
+ {
+ // Look for a matching source file in this CU.
+ CompUnitSP cu_sp(module->GetCompileUnitAtIndex(i));
+ if (cu_sp)
+ {
+ num_matches += DumpFileLinesInCompUnit(strm, module, cu_sp.get(), file_spec);
+ }
+ }
+ }
+ return num_matches;
+ }
+
+ // Given an address and a list of modules, append the symbol contexts of all line entries
+ // containing the address found in the modules and return the count of matches. If none
+ // is found, return an error in 'error_strm'.
+ size_t
+ GetSymbolContextsForAddress (const ModuleList &module_list, lldb::addr_t addr,
+ SymbolContextList &sc_list, StreamString &error_strm)
+ {
+ Address so_addr;
+ size_t num_matches = 0;
+ assert(module_list.GetSize() > 0);
+ Target *target = m_exe_ctx.GetTargetPtr();
+ if (target->GetSectionLoadList().IsEmpty())
+ {
+ // The target isn't loaded yet, we need to lookup the file address in
+ // all modules. Note: the module list option does not apply to addresses.
+ const size_t num_modules = module_list.GetSize();
+ for (size_t i = 0; i < num_modules; ++i)
+ {
+ ModuleSP module_sp(module_list.GetModuleAtIndex(i));
+ if (!module_sp)
+ continue;
+ if (module_sp->ResolveFileAddress(addr, so_addr))
+ {
+ SymbolContext sc;
+ sc.Clear(true);
+ if (module_sp->ResolveSymbolContextForAddress(so_addr, eSymbolContextEverything, sc) &
+ eSymbolContextLineEntry)
+ {
+ sc_list.AppendIfUnique(sc, /*merge_symbol_into_function=*/false);
+ ++num_matches;
+ }
+ }
+ }
+ if (num_matches == 0)
+ error_strm.Printf("Source information for file address 0x%" PRIx64
+ " not found in any modules.\n", addr);
+ }
+ else
+ {
+ // The target has some things loaded, resolve this address to a
+ // compile unit + file + line and display
+ if (target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
+ {
+ ModuleSP module_sp(so_addr.GetModule());
+ // Check to make sure this module is in our list.
+ if (module_sp &&
+ module_list.GetIndexForModule(module_sp.get()) != LLDB_INVALID_INDEX32)
+ {
+ SymbolContext sc;
+ sc.Clear(true);
+ if (module_sp->ResolveSymbolContextForAddress(so_addr, eSymbolContextEverything, sc) &
+ eSymbolContextLineEntry)
+ {
+ sc_list.AppendIfUnique(sc, /*merge_symbol_into_function=*/false);
+ ++num_matches;
+ }
+ else
+ {
+ StreamString addr_strm;
+ so_addr.Dump(&addr_strm, NULL, Address::DumpStyleModuleWithFileAddress);
+ error_strm.Printf("Address 0x%" PRIx64 " resolves to %s, but there is"
+ " no source information available for this address.\n",
+ addr, addr_strm.GetData());
+ }
+ }
+ else
+ {
+ StreamString addr_strm;
+ so_addr.Dump(&addr_strm, NULL, Address::DumpStyleModuleWithFileAddress);
+ error_strm.Printf("Address 0x%" PRIx64 " resolves to %s, but it cannot"
+ " be found in any modules.\n",
+ addr, addr_strm.GetData());
+ }
+ }
+ else
+ error_strm.Printf("Unable to resolve address 0x%" PRIx64 ".\n", addr);
+ }
+ return num_matches;
+ }
+
+ // Dump the line entries found in functions matching the name specified in the option.
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DumpLinesInFunctions (CommandReturnObject &result)
{
- result.AppendError ("Not yet implemented");
- result.SetStatus (eReturnStatusFailed);
- return false;
+ SymbolContextList sc_list_funcs;
+ ConstString name(m_options.symbol_name.c_str());
+ SymbolContextList sc_list_lines;
+ Target *target = m_exe_ctx.GetTargetPtr();
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+
+ // Note: module_list can't be const& because FindFunctionSymbols isn't const.
+ ModuleList module_list = (m_module_list.GetSize() > 0) ?
+ m_module_list : target->GetImages();
+ size_t num_matches = module_list.FindFunctions(name,
+ eFunctionNameTypeAuto,
+ /*include_symbols=*/false,
+ /*include_inlines=*/true,
+ /*append=*/true,
+ sc_list_funcs);
+ if (!num_matches)
+ {
+ // If we didn't find any functions with that name, try searching for
+ // symbols that line up exactly with function addresses.
+ SymbolContextList sc_list_symbols;
+ size_t num_symbol_matches = module_list.FindFunctionSymbols(name,
+ eFunctionNameTypeAuto,
+ sc_list_symbols);
+ for (size_t i = 0; i < num_symbol_matches; i++)
+ {
+ SymbolContext sc;
+ sc_list_symbols.GetContextAtIndex(i, sc);
+ if (sc.symbol && sc.symbol->ValueIsAddress())
+ {
+ const Address &base_address = sc.symbol->GetAddressRef();
+ Function *function = base_address.CalculateSymbolContextFunction();
+ if (function)
+ {
+ sc_list_funcs.Append(SymbolContext(function));
+ num_matches++;
+ }
+ }
+ }
+ }
+ if (num_matches == 0)
+ {
+ result.AppendErrorWithFormat("Could not find function named \'%s\'.\n",
+ m_options.symbol_name.c_str());
+ return false;
+ }
+ for (size_t i = 0; i < num_matches; i++)
+ {
+ SymbolContext sc;
+ sc_list_funcs.GetContextAtIndex(i, sc);
+ bool context_found_for_symbol = false;
+ // Loop through all the ranges in the function.
+ AddressRange range;
+ for (uint32_t r = 0;
+ sc.GetAddressRange(eSymbolContextEverything,
+ r,
+ /*use_inline_block_range=*/true,
+ range);
+ ++r)
+ {
+ // Append the symbol contexts for each address in the range to sc_list_lines.
+ const Address &base_address = range.GetBaseAddress();
+ const addr_t size = range.GetByteSize();
+ lldb::addr_t start_addr = base_address.GetLoadAddress(target);
+ if (start_addr == LLDB_INVALID_ADDRESS)
+ start_addr = base_address.GetFileAddress();
+ lldb::addr_t end_addr = start_addr + size;
+ for (lldb::addr_t addr = start_addr; addr < end_addr; addr += addr_byte_size)
+ {
+ StreamString error_strm;
+ if (!GetSymbolContextsForAddress(module_list, addr, sc_list_lines, error_strm))
+ result.AppendWarningWithFormat("in symbol '%s': %s",
+ sc.GetFunctionName().AsCString(),
+ error_strm.GetData());
+ else
+ context_found_for_symbol = true;
+ }
+ }
+ if (!context_found_for_symbol)
+ result.AppendWarningWithFormat("Unable to find line information"
+ " for matching symbol '%s'.\n",
+ sc.GetFunctionName().AsCString());
+ }
+ if (sc_list_lines.GetSize() == 0)
+ {
+ result.AppendErrorWithFormat("No line information could be found"
+ " for any symbols matching '%s'.\n",
+ name.AsCString());
+ return false;
+ }
+ FileSpec file_spec;
+ if (!DumpLinesInSymbolContexts(result.GetOutputStream(),
+ sc_list_lines, module_list, file_spec))
+ {
+ result.AppendErrorWithFormat("Unable to dump line information for symbol '%s'.\n",
+ name.AsCString());
+ return false;
+ }
+ return true;
+ }
+
+ // Dump the line entries found for the address specified in the option.
+ bool
+ DumpLinesForAddress (CommandReturnObject &result)
+ {
+ Target *target = m_exe_ctx.GetTargetPtr();
+ SymbolContextList sc_list;
+
+ StreamString error_strm;
+ if (!GetSymbolContextsForAddress(target->GetImages(), m_options.address, sc_list, error_strm))
+ {
+ result.AppendErrorWithFormat("%s.\n", error_strm.GetData());
+ return false;
+ }
+ ModuleList module_list;
+ FileSpec file_spec;
+ if (!DumpLinesInSymbolContexts(result.GetOutputStream(),
+ sc_list, module_list, file_spec))
+ {
+ result.AppendErrorWithFormat("No modules contain load address 0x%" PRIx64 ".\n",
+ m_options.address);
+ return false;
+ }
+ return true;
+ }
+
+ // Dump the line entries found in the file specified in the option.
+ bool
+ DumpLinesForFile (CommandReturnObject &result)
+ {
+ FileSpec file_spec(m_options.file_name, false);
+ const char *filename = m_options.file_name.c_str();
+ Target *target = m_exe_ctx.GetTargetPtr();
+ const ModuleList &module_list = (m_module_list.GetSize() > 0) ?
+ m_module_list : target->GetImages();
+
+ bool displayed_something = false;
+ const size_t num_modules = module_list.GetSize();
+ for (uint32_t i = 0; i < num_modules; ++i)
+ {
+ // Dump lines for this module.
+ Module *module = module_list.GetModulePointerAtIndex(i);
+ assert(module);
+ if (DumpFileLinesInModule(result.GetOutputStream(), module, file_spec))
+ displayed_something = true;
+ }
+ if (!displayed_something)
+ {
+ result.AppendErrorWithFormat("No source filenames matched '%s'.\n", filename);
+ return false;
+ }
+ return true;
+ }
+
+ // Dump the line entries for the current frame.
+ bool
+ DumpLinesForFrame (CommandReturnObject &result)
+ {
+ StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
+ if (cur_frame == NULL)
+ {
+ result.AppendError("No selected frame to use to find the default source.");
+ return false;
+ }
+ else if (!cur_frame->HasDebugInformation())
+ {
+ result.AppendError("No debug info for the selected frame.");
+ return false;
+ }
+ else
+ {
+ const SymbolContext &sc = cur_frame->GetSymbolContext(eSymbolContextLineEntry);
+ SymbolContextList sc_list;
+ sc_list.Append(sc);
+ ModuleList module_list;
+ FileSpec file_spec;
+ if (!DumpLinesInSymbolContexts(result.GetOutputStream(), sc_list, module_list, file_spec))
+ {
+ result.AppendError("No source line info available for the selected frame.");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool
+ DoExecute (Args &command, CommandReturnObject &result) override
+ {
+ const size_t argc = command.GetArgumentCount();
+
+ if (argc != 0)
+ {
+ result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n",
+ GetCommandName());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ Target *target = m_exe_ctx.GetTargetPtr();
+ if (target == NULL)
+ {
+ target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ if (target == NULL)
+ {
+ result.AppendError("invalid target, create a debug target using the "
+ "'target create' command.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+ // Collect the list of modules to search.
+ m_module_list.Clear();
+ if (m_options.modules.size() > 0)
+ {
+ for (size_t i = 0, e = m_options.modules.size(); i < e; ++i)
+ {
+ FileSpec module_file_spec(m_options.modules[i].c_str(), false);
+ if (module_file_spec)
+ {
+ ModuleSpec module_spec(module_file_spec);
+ if (target->GetImages().FindModules(module_spec, m_module_list) == 0)
+ result.AppendWarningWithFormat("No module found for '%s'.\n",
+ m_options.modules[i].c_str());
+ }
+ }
+ if (!m_module_list.GetSize())
+ {
+ result.AppendError("No modules match the input.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+ else if (target->GetImages().GetSize() == 0)
+ {
+ result.AppendError("The target has no associated executable images.");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ // Check the arguments to see what lines we should dump.
+ if (!m_options.symbol_name.empty())
+ {
+ // Print lines for symbol.
+ if (DumpLinesInFunctions(result))
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+ }
+ else if (m_options.address != LLDB_INVALID_ADDRESS)
+ {
+ // Print lines for an address.
+ if (DumpLinesForAddress(result))
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+ }
+ else if (!m_options.file_name.empty())
+ {
+ // Dump lines for a file.
+ if (DumpLinesForFile(result))
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+ }
+ else
+ {
+ // Dump the line for the current frame.
+ if (DumpLinesForFrame(result))
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+ }
+ return result.Succeeded();
}
CommandOptions m_options;
+ ModuleList m_module_list;
};
-OptionDefinition
-CommandObjectSourceInfo::CommandOptions::g_option_table[] =
-{
-{ LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum, "The line number at which to start the display source."},
-{ LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."},
-{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+OptionDefinition CommandObjectSourceInfo::CommandOptions::g_option_table[] = {
+ {LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount,
+ "The number of line entries to display."},
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, NULL, NULL,
+ CommandCompletions::eModuleCompletion, eArgTypeShlibName,
+ "Look up the source in the given module or shared library (can be "
+ "specified more than once)."},
+ {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL,
+ CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."},
+ {LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
+ "The line number at which to start the displaying lines."},
+ {LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
+ "The line number at which to stop displaying lines."},
+ {LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL,
+ CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display."},
+ {LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression,
+ "Lookup the address and display the source information for the "
+ "corresponding file and line."},
+ {0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL}
};
+
#pragma mark CommandObjectSourceList
//-------------------------------------------------------------------------
// CommandObjectSourceList
@@ -157,12 +736,12 @@ class CommandObjectSourceList : public CommandObjectParsed
{
}
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = g_option_table[option_idx].short_option;
@@ -213,7 +792,7 @@ class CommandObjectSourceList : public CommandObjectParsed
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
file_spec.Clear();
file_name.clear();
@@ -227,7 +806,7 @@ class CommandObjectSourceList : public CommandObjectParsed
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -256,19 +835,19 @@ public:
{
}
- ~CommandObjectSourceList ()
+ ~CommandObjectSourceList () override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
- virtual const char *
- GetRepeatCommand (Args &current_command_args, uint32_t index)
+ const char *
+ GetRepeatCommand (Args &current_command_args, uint32_t index) override
{
// This is kind of gross, but the command hasn't been parsed yet so we can't look at the option
// values for this invocation... I have to scan the arguments directly.
@@ -507,7 +1086,7 @@ protected:
}
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
@@ -906,7 +1485,6 @@ CommandObjectSourceList::CommandOptions::g_option_table[] =
};
#pragma mark CommandObjectMultiwordSource
-
//-------------------------------------------------------------------------
// CommandObjectMultiwordSource
//-------------------------------------------------------------------------
@@ -917,8 +1495,7 @@ CommandObjectMultiwordSource::CommandObjectMultiwordSource (CommandInterpreter &
"A set of commands for accessing source file information",
"source <subcommand> [<subcommand-options>]")
{
- // "source info" isn't implemented yet...
- //LoadSubCommand ("info", CommandObjectSP (new CommandObjectSourceInfo (interpreter)));
+ LoadSubCommand ("info", CommandObjectSP (new CommandObjectSourceInfo (interpreter)));
LoadSubCommand ("list", CommandObjectSP (new CommandObjectSourceList (interpreter)));
}
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.h
index 0daef13..7ed08cd 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.h
@@ -30,11 +30,9 @@ public:
CommandObjectMultiwordSource (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectMultiwordSource ();
-
+ ~CommandObjectMultiwordSource() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectSource.h_h_
+#endif // liblldb_CommandObjectSource_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.h
index 47bf85f..1a3e4e0 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSyntax.h
@@ -28,17 +28,14 @@ public:
CommandObjectSyntax (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectSyntax ();
+ ~CommandObjectSyntax() override;
protected:
- virtual bool
- DoExecute (Args& command,
- CommandReturnObject &result);
-
-
+ bool
+ DoExecute(Args& command,
+ CommandReturnObject &result) override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectSyntax_h_
+#endif // liblldb_CommandObjectSyntax_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp
index 448da0e..57ec1c9 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp
@@ -79,7 +79,8 @@ DumpTargetInfo (uint32_t target_idx, Target *target, const char *prefix_cstr, bo
uint32_t properties = 0;
if (target_arch.IsValid())
{
- strm.Printf ("%sarch=%s", properties++ > 0 ? ", " : " ( ", target_arch.GetTriple().str().c_str());
+ strm.Printf ("%sarch=", properties++ > 0 ? ", " : " ( ");
+ target_arch.DumpTriple (strm);
properties++;
}
PlatformSP platform_sp (target->GetPlatform());
@@ -187,17 +188,17 @@ public:
m_option_group.Finalize();
}
- ~CommandObjectTargetCreate ()
+ ~CommandObjectTargetCreate () override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_option_group;
}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -205,7 +206,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
@@ -223,7 +224,7 @@ public:
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
FileSpec core_file (m_core_file.GetOptionValue().GetCurrentValue());
@@ -255,7 +256,7 @@ protected:
{
if (!symfile.Readable())
{
- result.AppendErrorWithFormat("symbol file '%s' is not readable", core_file.GetPath().c_str());
+ result.AppendErrorWithFormat("symbol file '%s' is not readable", symfile.GetPath().c_str());
result.SetStatus (eReturnStatusFailed);
return false;
}
@@ -401,7 +402,7 @@ protected:
if (process_sp)
{
- // Seems wierd that we Launch a core file, but that is
+ // Seems weird that we Launch a core file, but that is
// what we do!
error = process_sp->LoadCore();
@@ -477,14 +478,13 @@ public:
{
}
- virtual
- ~CommandObjectTargetList ()
+ ~CommandObjectTargetList () override
{
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
if (args.GetArgumentCount() == 0)
{
@@ -525,14 +525,13 @@ public:
{
}
- virtual
- ~CommandObjectTargetSelect ()
+ ~CommandObjectTargetSelect () override
{
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
if (args.GetArgumentCount() == 1)
{
@@ -622,20 +621,19 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectTargetDelete ()
+ ~CommandObjectTargetDelete () override
{
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_option_group;
}
protected:
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
const size_t argc = args.GetArgumentCount();
std::vector<TargetSP> delete_target_list;
@@ -777,8 +775,7 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectTargetVariable ()
+ ~CommandObjectTargetVariable () override
{
}
@@ -850,7 +847,7 @@ public:
}
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_option_group;
}
@@ -896,8 +893,8 @@ protected:
}
}
- virtual bool
- DoExecute (Args& args, CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
Target *target = m_exe_ctx.GetTargetPtr();
const size_t argc = args.GetArgumentCount();
@@ -1134,14 +1131,13 @@ public:
m_arguments.push_back (arg);
}
- ~CommandObjectTargetModulesSearchPathsAdd ()
+ ~CommandObjectTargetModulesSearchPathsAdd () override
{
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target)
@@ -1161,6 +1157,12 @@ protected:
if (from[0] && to[0])
{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ if (log)
+ {
+ log->Printf ("target modules search path adding ImageSearchPath pair: '%s' -> '%s'",
+ from, to);
+ }
bool last_pair = ((argc - i) == 2);
target->GetImageSearchPathList().Append (ConstString(from),
ConstString(to),
@@ -1201,14 +1203,13 @@ public:
{
}
- ~CommandObjectTargetModulesSearchPathsClear ()
+ ~CommandObjectTargetModulesSearchPathsClear () override
{
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target)
@@ -1271,20 +1272,19 @@ public:
m_arguments.push_back (arg2);
}
- ~CommandObjectTargetModulesSearchPathsInsert ()
+ ~CommandObjectTargetModulesSearchPathsInsert () override
{
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target)
{
size_t argc = command.GetArgumentCount();
- // check for at least 3 arguments and an odd nubmer of parameters
+ // check for at least 3 arguments and an odd number of parameters
if (argc >= 3 && argc & 1)
{
bool success = false;
@@ -1360,14 +1360,13 @@ public:
{
}
- ~CommandObjectTargetModulesSearchPathsList ()
+ ~CommandObjectTargetModulesSearchPathsList () override
{
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target)
@@ -1417,14 +1416,13 @@ public:
m_arguments.push_back (arg);
}
- ~CommandObjectTargetModulesSearchPathsQuery ()
+ ~CommandObjectTargetModulesSearchPathsQuery () override
{
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target)
@@ -1462,15 +1460,18 @@ DumpModuleArchitecture (Stream &strm, Module *module, bool full_triple, uint32_t
{
if (module)
{
- const char *arch_cstr;
+ StreamString arch_strm;
+
if (full_triple)
- arch_cstr = module->GetArchitecture().GetTriple().str().c_str();
+ module->GetArchitecture().DumpTriple(arch_strm);
else
- arch_cstr = module->GetArchitecture().GetArchitectureName();
+ arch_strm.PutCString(module->GetArchitecture().GetArchitectureName());
+ std::string arch_str = arch_strm.GetString();
+
if (width)
- strm.Printf("%-*s", width, arch_cstr);
+ strm.Printf("%-*s", width, arch_str.c_str());
else
- strm.PutCString(arch_cstr);
+ strm.PutCString(arch_str.c_str());
}
}
@@ -1865,7 +1866,7 @@ LookupTypeInModule (CommandInterpreter &interpreter,
{
// Resolve the clang type so that any forward references
// to types that haven't yet been parsed will get parsed.
- type_sp->GetClangFullType ();
+ type_sp->GetFullCompilerType ();
type_sp->GetDescription (&strm, eDescriptionLevelFull, true);
// Print all typedef chains
TypeSP typedef_type_sp (type_sp);
@@ -1874,7 +1875,7 @@ LookupTypeInModule (CommandInterpreter &interpreter,
{
strm.EOL();
strm.Printf(" typedef '%s': ", typedef_type_sp->GetName().GetCString());
- typedefed_type_sp->GetClangFullType ();
+ typedefed_type_sp->GetFullCompilerType ();
typedefed_type_sp->GetDescription (&strm, eDescriptionLevelFull, true);
typedef_type_sp = typedefed_type_sp;
typedefed_type_sp = typedef_type_sp->GetTypedefType();
@@ -1918,7 +1919,7 @@ LookupTypeHere (CommandInterpreter &interpreter,
{
// Resolve the clang type so that any forward references
// to types that haven't yet been parsed will get parsed.
- type_sp->GetClangFullType ();
+ type_sp->GetFullCompilerType ();
type_sp->GetDescription (&strm, eDescriptionLevelFull, true);
// Print all typedef chains
TypeSP typedef_type_sp (type_sp);
@@ -1927,7 +1928,7 @@ LookupTypeHere (CommandInterpreter &interpreter,
{
strm.EOL();
strm.Printf(" typedef '%s': ", typedef_type_sp->GetName().GetCString());
- typedefed_type_sp->GetClangFullType ();
+ typedefed_type_sp->GetFullCompilerType ();
typedefed_type_sp->GetDescription (&strm, eDescriptionLevelFull, true);
typedef_type_sp = typedefed_type_sp;
typedefed_type_sp = typedef_type_sp->GetTypedefType();
@@ -2056,12 +2057,11 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectTargetModulesModuleAutoComplete ()
+ ~CommandObjectTargetModulesModuleAutoComplete () override
{
}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -2069,7 +2069,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
// Arguments are the standard module completer.
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
@@ -2118,12 +2118,11 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectTargetModulesSourceFileAutoComplete ()
+ ~CommandObjectTargetModulesSourceFileAutoComplete () override
{
}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -2131,7 +2130,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
// Arguments are the standard source file completer.
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
@@ -2165,13 +2164,12 @@ public:
{
}
- virtual
- ~CommandObjectTargetModulesDumpSymtab ()
+ ~CommandObjectTargetModulesDumpSymtab () override
{
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -2185,13 +2183,12 @@ public:
{
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -2214,13 +2211,13 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_sort_order = eSortOrderNone;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -2232,9 +2229,8 @@ public:
};
protected:
- virtual bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target == NULL)
@@ -2359,15 +2355,13 @@ public:
{
}
- virtual
- ~CommandObjectTargetModulesDumpSections ()
+ ~CommandObjectTargetModulesDumpSections () override
{
}
protected:
- virtual bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target == NULL)
@@ -2465,15 +2459,13 @@ public:
{
}
- virtual
- ~CommandObjectTargetModulesDumpSymfile ()
+ ~CommandObjectTargetModulesDumpSymfile () override
{
}
protected:
- virtual bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target == NULL)
@@ -2568,15 +2560,13 @@ public:
{
}
- virtual
- ~CommandObjectTargetModulesDumpLineTable ()
+ ~CommandObjectTargetModulesDumpLineTable () override
{
}
protected:
- virtual bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_exe_ctx.GetTargetPtr();
uint32_t total_num_dumped = 0;
@@ -2587,8 +2577,9 @@ protected:
if (command.GetArgumentCount() == 0)
{
- result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
+ result.AppendError ("file option must be specified.");
result.SetStatus (eReturnStatusFailed);
+ return result.Succeeded();
}
else
{
@@ -2657,8 +2648,7 @@ public:
LoadSubCommand ("line-table", CommandObjectSP (new CommandObjectTargetModulesDumpLineTable (interpreter)));
}
- virtual
- ~CommandObjectTargetModulesDump()
+ ~CommandObjectTargetModulesDump() override
{
}
};
@@ -2679,18 +2669,17 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectTargetModulesAdd ()
+ ~CommandObjectTargetModulesAdd () override
{
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_option_group;
}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -2698,7 +2687,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
@@ -2719,9 +2708,8 @@ protected:
OptionGroupUUID m_uuid_option_group;
OptionGroupFile m_symbol_file;
- virtual bool
- DoExecute (Args& args,
- CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target == NULL)
@@ -2882,21 +2870,19 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectTargetModulesLoad ()
+ ~CommandObjectTargetModulesLoad () override
{
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_option_group;
}
protected:
- virtual bool
- DoExecute (Args& args,
- CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target == NULL)
@@ -3139,13 +3125,12 @@ public:
{
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
@@ -3170,7 +3155,7 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_format_array.clear();
m_use_global_module_list = false;
@@ -3178,7 +3163,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -3203,22 +3188,19 @@ public:
{
}
- virtual
- ~CommandObjectTargetModulesList ()
+ ~CommandObjectTargetModulesList () override
{
}
- virtual
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
protected:
- virtual bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
const bool use_global_module_list = m_options.m_use_global_module_list;
@@ -3584,13 +3566,12 @@ public:
{
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
@@ -3625,7 +3606,7 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_type = eLookupTypeInvalid;
m_str.clear();
@@ -3633,7 +3614,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -3662,22 +3643,19 @@ public:
{
}
- virtual
- ~CommandObjectTargetModulesShowUnwind ()
+ ~CommandObjectTargetModulesShowUnwind () override
{
}
- virtual
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
protected:
bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_exe_ctx.GetTargetPtr();
Process *process = m_exe_ctx.GetProcessPtr();
@@ -3813,6 +3791,14 @@ protected:
result.GetOutputStream().Printf("\n");
}
+ UnwindPlanSP arm_unwind_sp = func_unwinders_sp->GetArmUnwindUnwindPlan(*target, 0);
+ if (arm_unwind_sp)
+ {
+ result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
+ arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+ result.GetOutputStream().Printf("\n");
+ }
+
UnwindPlanSP compact_unwind_sp = func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0);
if (compact_unwind_sp)
{
@@ -3891,13 +3877,12 @@ public:
OptionParsingStarting();
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
@@ -3974,7 +3959,7 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_type = eLookupTypeInvalid;
m_str.clear();
@@ -3989,7 +3974,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -4031,13 +4016,12 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectTargetModulesLookup ()
+ ~CommandObjectTargetModulesLookup () override
{
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -4191,9 +4175,8 @@ public:
}
protected:
- virtual bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target == NULL)
@@ -4339,7 +4322,7 @@ public:
LoadSubCommand ("query", CommandObjectSP (new CommandObjectTargetModulesSearchPathsQuery (interpreter)));
}
- ~CommandObjectTargetModulesImageSearchPaths()
+ ~CommandObjectTargetModulesImageSearchPaths() override
{
}
};
@@ -4373,8 +4356,8 @@ public:
LoadSubCommand ("show-unwind", CommandObjectSP (new CommandObjectTargetModulesShowUnwind (interpreter)));
}
- virtual
- ~CommandObjectTargetModules()
+
+ ~CommandObjectTargetModules() override
{
}
@@ -4406,12 +4389,11 @@ public:
m_option_group.Finalize();
}
- virtual
- ~CommandObjectTargetSymbolsAdd ()
+ ~CommandObjectTargetSymbolsAdd () override
{
}
- virtual int
+ int
HandleArgumentCompletion (Args &input,
int &cursor_index,
int &cursor_char_position,
@@ -4419,7 +4401,7 @@ public:
int match_start_point,
int max_return_elements,
bool &word_complete,
- StringList &matches)
+ StringList &matches) override
{
std::string completion_str (input.GetArgumentAtIndex(cursor_index));
completion_str.erase (cursor_char_position);
@@ -4435,8 +4417,8 @@ public:
return matches.GetSize();
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_option_group;
}
@@ -4614,9 +4596,8 @@ protected:
return false;
}
- virtual bool
- DoExecute (Args& args,
- CommandReturnObject &result)
+ bool
+ DoExecute (Args& args, CommandReturnObject &result) override
{
Target *target = m_exe_ctx.GetTargetPtr();
result.SetStatus (eReturnStatusFailed);
@@ -4834,8 +4815,8 @@ public:
LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetSymbolsAdd (interpreter)));
}
- virtual
- ~CommandObjectTargetSymbols()
+
+ ~CommandObjectTargetSymbols() override
{
}
@@ -4874,16 +4855,16 @@ public:
{
}
- ~CommandOptions () {}
+ ~CommandOptions () override {}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -4970,7 +4951,7 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_class_name.clear();
m_function_name.clear();
@@ -5015,7 +4996,7 @@ public:
};
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
@@ -5030,13 +5011,13 @@ public:
{
}
- ~CommandObjectTargetStopHookAdd ()
+ ~CommandObjectTargetStopHookAdd () override
{
}
protected:
- virtual void
- IOHandlerActivated (IOHandler &io_handler)
+ void
+ IOHandlerActivated (IOHandler &io_handler) override
{
StreamFileSP output_sp(io_handler.GetOutputStreamFile());
if (output_sp)
@@ -5046,8 +5027,8 @@ protected:
}
}
- virtual void
- IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+ void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override
{
if (m_stop_hook_sp)
{
@@ -5079,7 +5060,7 @@ protected:
}
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
m_stop_hook_sp.reset();
@@ -5227,13 +5208,13 @@ public:
{
}
- ~CommandObjectTargetStopHookDelete ()
+ ~CommandObjectTargetStopHookDelete () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget();
if (target)
@@ -5303,13 +5284,13 @@ public:
{
}
- ~CommandObjectTargetStopHookEnableDisable ()
+ ~CommandObjectTargetStopHookEnableDisable () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget();
if (target)
@@ -5373,13 +5354,13 @@ public:
{
}
- ~CommandObjectTargetStopHookList ()
+ ~CommandObjectTargetStopHookList () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = GetSelectedOrDummyTarget();
if (!target)
@@ -5439,7 +5420,7 @@ public:
LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetStopHookList (interpreter)));
}
- ~CommandObjectMultiwordTargetStopHooks()
+ ~CommandObjectMultiwordTargetStopHooks() override
{
}
};
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.h
index 7b66378..d99a2b0 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.h
@@ -30,12 +30,9 @@ public:
CommandObjectMultiwordTarget (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectMultiwordTarget ();
-
-
+ ~CommandObjectMultiwordTarget() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectTarget_h_
+#endif // liblldb_CommandObjectTarget_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp
index 5f38ad4..e932c9d 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp
@@ -58,9 +58,10 @@ public:
{
}
- virtual ~CommandObjectIterateOverThreads() {}
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ ~CommandObjectIterateOverThreads() override {}
+
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
result.SetStatus (m_success_return);
@@ -162,13 +163,12 @@ public:
OptionParsingStarting ();
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -211,7 +211,7 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_count = UINT32_MAX;
m_start = 0;
@@ -219,7 +219,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -248,12 +248,12 @@ public:
{
}
- ~CommandObjectThreadBacktrace()
+ ~CommandObjectThreadBacktrace() override
{
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -285,8 +285,8 @@ protected:
}
}
- virtual bool
- HandleOneThread (Thread &thread, CommandReturnObject &result)
+ bool
+ HandleOneThread (Thread &thread, CommandReturnObject &result) override
{
Stream &strm = result.GetOutputStream();
@@ -343,13 +343,12 @@ public:
OptionParsingStarting ();
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -426,7 +425,7 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_step_in_avoid_no_debug = eLazyBoolCalculate;
m_step_out_avoid_no_debug = eLazyBoolCalculate;
@@ -444,7 +443,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -493,21 +492,19 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectThreadStepWithTypeAndScope ()
+ ~CommandObjectThreadStepWithTypeAndScope () override
{
}
- virtual
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Process *process = m_exe_ctx.GetProcessPtr();
bool synchronous_execution = m_interpreter.GetSynchronous();
@@ -589,7 +586,7 @@ protected:
if (frame->HasDebugInformation ())
{
new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
- frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
+ frame->GetSymbolContext(eSymbolContextEverything).line_entry,
frame->GetSymbolContext(eSymbolContextEverything),
m_options.m_step_in_target.c_str(),
stop_other_threads,
@@ -612,7 +609,7 @@ protected:
if (frame->HasDebugInformation())
new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
- frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
+ frame->GetSymbolContext(eSymbolContextEverything).line_entry,
frame->GetSymbolContext(eSymbolContextEverything),
stop_other_threads,
m_options.m_step_out_avoid_no_debug);
@@ -780,13 +777,12 @@ public:
}
- virtual
- ~CommandObjectThreadContinue ()
+ ~CommandObjectThreadContinue () override
{
}
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
bool synchronous_execution = m_interpreter.GetSynchronous ();
@@ -980,13 +976,12 @@ public:
OptionParsingStarting ();
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1042,7 +1037,7 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_thread_idx = LLDB_INVALID_THREAD_ID;
m_frame_idx = 0;
@@ -1051,7 +1046,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1093,21 +1088,19 @@ public:
}
- virtual
- ~CommandObjectThreadUntil ()
+ ~CommandObjectThreadUntil () override
{
}
- virtual
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
bool synchronous_execution = m_interpreter.GetSynchronous ();
@@ -1371,14 +1364,13 @@ public:
}
- virtual
- ~CommandObjectThreadSelect ()
+ ~CommandObjectThreadSelect () override
{
}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Process *process = m_exe_ctx.GetProcessPtr();
if (process == NULL)
@@ -1434,13 +1426,13 @@ public:
{
}
- ~CommandObjectThreadList()
+ ~CommandObjectThreadList() override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Stream &strm = result.GetOutputStream();
result.SetStatus (eReturnStatusSuccessFinishNoResult);
@@ -1492,19 +1484,18 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_json_thread = false;
m_json_stopinfo = false;
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
const int short_option = m_getopt_table[option_idx].val;
Error error;
@@ -1527,7 +1518,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1538,21 +1529,18 @@ public:
static OptionDefinition g_option_table[];
};
- virtual
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
-
- virtual
- ~CommandObjectThreadInfo ()
+ ~CommandObjectThreadInfo () override
{
}
- virtual bool
- HandleOneThread (Thread &thread, CommandReturnObject &result)
+ bool
+ HandleOneThread (Thread &thread, CommandReturnObject &result) override
{
Stream &strm = result.GetOutputStream();
if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo))
@@ -1597,13 +1585,12 @@ public:
OptionParsingStarting ();
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1631,13 +1618,13 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_from_expression = false;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1651,9 +1638,8 @@ public:
// Instance variables to hold the values for command options.
};
- virtual
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
@@ -1686,17 +1672,14 @@ public:
}
- ~CommandObjectThreadReturn()
+ ~CommandObjectThreadReturn() override
{
}
protected:
- bool DoExecute
- (
- const char *command,
- CommandReturnObject &result
- )
+ bool
+ DoExecute (const char *command, CommandReturnObject &result) override
{
// I am going to handle this by hand, because I don't want you to have to say:
// "thread return -- -5".
@@ -1810,7 +1793,7 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_filenames.Clear();
m_line_num = 0;
@@ -1819,13 +1802,12 @@ public:
m_force = false;
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
bool success;
const int short_option = m_getopt_table[option_idx].val;
@@ -1866,7 +1848,7 @@ public:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1880,9 +1862,8 @@ public:
static OptionDefinition g_option_table[];
};
- virtual
Options *
- GetOptions ()
+ GetOptions () override
{
return &m_options;
}
@@ -1900,13 +1881,13 @@ public:
{
}
- ~CommandObjectThreadJump()
+ ~CommandObjectThreadJump() override
{
}
protected:
- bool DoExecute (Args& args, CommandReturnObject &result)
+ bool DoExecute (Args& args, CommandReturnObject &result) override
{
RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
StackFrame *frame = m_exe_ctx.GetFramePtr();
@@ -2017,13 +1998,12 @@ public:
OptionParsingStarting ();
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -2049,14 +2029,14 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_verbose = false;
m_internal = false;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -2085,19 +2065,19 @@ public:
{
}
- ~CommandObjectThreadPlanList ()
+ ~CommandObjectThreadPlanList () override
{
}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
protected:
- virtual bool
- HandleOneThread (Thread &thread, CommandReturnObject &result)
+ bool
+ HandleOneThread (Thread &thread, CommandReturnObject &result) override
{
Stream &strm = result.GetOutputStream();
DescriptionLevel desc_level = eDescriptionLevelFull;
@@ -2148,10 +2128,10 @@ public:
m_arguments.push_back (arg);
}
- virtual ~CommandObjectThreadPlanDiscard () {}
+ ~CommandObjectThreadPlanDiscard () override {}
bool
- DoExecute (Args& args, CommandReturnObject &result)
+ DoExecute (Args& args, CommandReturnObject &result) override
{
Thread *thread = m_exe_ctx.GetThreadPtr();
if (args.GetArgumentCount() != 1)
@@ -2211,7 +2191,7 @@ public:
LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter)));
}
- virtual ~CommandObjectMultiwordThreadPlan () {}
+ ~CommandObjectMultiwordThreadPlan () override {}
};
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.h
index 52902ee..90f8236 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.h
@@ -24,11 +24,9 @@ public:
CommandObjectMultiwordThread (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectMultiwordThread ();
-
+ ~CommandObjectMultiwordThread() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectThread_h_
+#endif // liblldb_CommandObjectThread_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp
index 584e94d..2b803e7 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp
@@ -30,6 +30,10 @@
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
+#include "lldb/Interpreter/OptionValueBoolean.h"
+#include "lldb/Interpreter/OptionValueLanguage.h"
+#include "lldb/Interpreter/OptionValueString.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
@@ -144,17 +148,16 @@ private:
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg);
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override;
void
- OptionParsingStarting ();
+ OptionParsingStarting () override;
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -177,8 +180,8 @@ private:
CommandOptions m_options;
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -200,12 +203,12 @@ public:
CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter);
- ~CommandObjectTypeSummaryAdd ()
+ ~CommandObjectTypeSummaryAdd () override
{
}
- virtual void
- IOHandlerActivated (IOHandler &io_handler)
+ void
+ IOHandlerActivated (IOHandler &io_handler) override
{
static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
"def function (valobj,internal_dict):\n"
@@ -221,8 +224,8 @@ public:
}
- virtual void
- IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+ void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override
{
StreamFileSP error_sp = io_handler.GetErrorStreamFile();
@@ -353,7 +356,7 @@ public:
Error* error = NULL);
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result);
+ DoExecute (Args& command, CommandReturnObject &result) override;
};
@@ -383,11 +386,10 @@ private:
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -428,7 +430,7 @@ private:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_cascade = true;
m_class_name = "";
@@ -441,7 +443,7 @@ private:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -469,8 +471,8 @@ private:
CommandOptions m_options;
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -483,7 +485,7 @@ private:
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
WarnOnPotentialUnquotedUnsignedType(command, result);
@@ -499,8 +501,8 @@ protected:
}
}
- virtual void
- IOHandlerActivated (IOHandler &io_handler)
+ void
+ IOHandlerActivated (IOHandler &io_handler) override
{
StreamFileSP output_sp(io_handler.GetOutputStreamFile());
if (output_sp)
@@ -511,8 +513,8 @@ protected:
}
- virtual void
- IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+ void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override
{
StreamFileSP error_sp = io_handler.GetErrorStreamFile();
@@ -626,7 +628,7 @@ public:
CommandObjectTypeSynthAdd (CommandInterpreter &interpreter);
- ~CommandObjectTypeSynthAdd ()
+ ~CommandObjectTypeSynthAdd () override
{
}
@@ -656,22 +658,21 @@ private:
{
}
- virtual
- ~CommandOptions ()
+ ~CommandOptions () override
{
}
- virtual uint32_t
- GetNumDefinitions ();
+ uint32_t
+ GetNumDefinitions () override;
- virtual const OptionDefinition*
- GetDefinitions ()
+ const OptionDefinition*
+ GetDefinitions () override
{
return g_option_table;
}
- virtual void
- OptionParsingStarting (CommandInterpreter &interpreter)
+ void
+ OptionParsingStarting (CommandInterpreter &interpreter) override
{
m_cascade = true;
m_skip_pointers = false;
@@ -680,10 +681,10 @@ private:
m_category.assign("default");
m_custom_type_name.clear();
}
- virtual Error
+ Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
- const char *option_value)
+ const char *option_value) override
{
Error error;
const int short_option = g_option_table[option_idx].short_option;
@@ -737,8 +738,8 @@ private:
OptionGroupFormat m_format_options;
CommandOptions m_command_options;
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_option_group;
}
@@ -806,13 +807,13 @@ pointers to floats. Nor will it change the default display for Afloat and Bfloa
}
- ~CommandObjectTypeFormatAdd ()
+ ~CommandObjectTypeFormatAdd () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
@@ -906,14 +907,9 @@ CommandObjectTypeFormatAdd::CommandOptions::GetNumDefinitions ()
return sizeof(g_option_table) / sizeof (OptionDefinition);
}
-
-//-------------------------------------------------------------------------
-// CommandObjectTypeFormatDelete
-//-------------------------------------------------------------------------
-
-class CommandObjectTypeFormatDelete : public CommandObjectParsed
+class CommandObjectTypeFormatterDelete : public CommandObjectParsed
{
-private:
+protected:
class CommandOptions : public Options
{
public:
@@ -923,11 +919,10 @@ private:
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -940,6 +935,9 @@ private:
case 'w':
m_category = std::string(option_arg);
break;
+ case 'l':
+ m_language = Language::GetLanguageTypeFromString(option_arg);
+ break;
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
break;
@@ -949,14 +947,15 @@ private:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_delete_all = false;
m_category = "default";
+ m_language = lldb::eLanguageTypeUnknown;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -969,33 +968,29 @@ private:
bool m_delete_all;
std::string m_category;
-
+ lldb::LanguageType m_language;
};
CommandOptions m_options;
+ uint32_t m_formatter_kind_mask;
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
- static bool
- PerCategoryCallback(void* param,
- const lldb::TypeCategoryImplSP& category_sp)
- {
- ConstString *name = (ConstString*)param;
- category_sp->Delete(*name, eFormatCategoryItemValue | eFormatCategoryItemRegexValue);
- return true;
- }
-
public:
- CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "type format delete",
- "Delete an existing formatting style for a type.",
- NULL),
- m_options(interpreter)
+ CommandObjectTypeFormatterDelete (CommandInterpreter &interpreter,
+ uint32_t formatter_kind_mask,
+ const char* name,
+ const char* help) :
+ CommandObjectParsed (interpreter,
+ name,
+ help,
+ NULL),
+ m_options(interpreter),
+ m_formatter_kind_mask(formatter_kind_mask)
{
CommandArgumentEntry type_arg;
CommandArgumentData type_style_arg;
@@ -1009,13 +1004,17 @@ public:
}
- ~CommandObjectTypeFormatDelete ()
+ ~CommandObjectTypeFormatterDelete () override = default;
+
+protected:
+ virtual bool
+ FormatterSpecificDeletion (ConstString typeCS)
{
+ return false;
}
-protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
@@ -1038,25 +1037,42 @@ protected:
if (m_options.m_delete_all)
{
- DataVisualization::Categories::LoopThrough(PerCategoryCallback, &typeCS);
+ DataVisualization::Categories::ForEach( [this, typeCS] (const lldb::TypeCategoryImplSP& category_sp) -> bool {
+ category_sp->Delete(typeCS, m_formatter_kind_mask);
+ return true;
+ });
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
}
- lldb::TypeCategoryImplSP category;
- DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
+ bool delete_category = false;
+ bool extra_deletion = false;
- bool delete_category = category->Delete(typeCS,
- eFormatCategoryItemValue | eFormatCategoryItemRegexValue);
+ if (m_options.m_language != lldb::eLanguageTypeUnknown)
+ {
+ lldb::TypeCategoryImplSP category;
+ DataVisualization::Categories::GetCategory(m_options.m_language, category);
+ if (category)
+ delete_category = category->Delete(typeCS, m_formatter_kind_mask);
+ extra_deletion = FormatterSpecificDeletion(typeCS);
+ }
+ else
+ {
+ lldb::TypeCategoryImplSP category;
+ DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
+ if (category)
+ delete_category = category->Delete(typeCS, m_formatter_kind_mask);
+ extra_deletion = FormatterSpecificDeletion(typeCS);
+ }
- if (delete_category)
+ if (delete_category || extra_deletion)
{
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
}
else
{
- result.AppendErrorWithFormat ("no custom format for %s.\n", typeA);
+ result.AppendErrorWithFormat ("no custom formatter for %s.\n", typeA);
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1066,18 +1082,15 @@ protected:
};
OptionDefinition
-CommandObjectTypeFormatDelete::CommandOptions::g_option_table[] =
+CommandObjectTypeFormatterDelete::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."},
{ LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."},
+ { LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Delete from given language's category."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
-//-------------------------------------------------------------------------
-// CommandObjectTypeFormatClear
-//-------------------------------------------------------------------------
-
-class CommandObjectTypeFormatClear : public CommandObjectParsed
+class CommandObjectTypeFormatterClear : public CommandObjectParsed
{
private:
@@ -1090,11 +1103,10 @@ private:
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1113,13 +1125,13 @@ private:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_delete_all = false;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -1129,50 +1141,52 @@ private:
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
-
bool m_delete_all;
- bool m_delete_named;
};
CommandOptions m_options;
-
- virtual Options *
- GetOptions ()
+ uint32_t m_formatter_kind_mask;
+
+ Options *
+ GetOptions () override
{
return &m_options;
}
- static bool
- PerCategoryCallback(void* param,
- const lldb::TypeCategoryImplSP& cate)
+public:
+ CommandObjectTypeFormatterClear (CommandInterpreter &interpreter,
+ uint32_t formatter_kind_mask,
+ const char* name,
+ const char* help) :
+ CommandObjectParsed (interpreter,
+ name,
+ help,
+ NULL),
+ m_options(interpreter),
+ m_formatter_kind_mask(formatter_kind_mask)
{
- cate->GetTypeFormatsContainer()->Clear();
- cate->GetRegexTypeFormatsContainer()->Clear();
- return true;
-
}
-public:
- CommandObjectTypeFormatClear (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "type format clear",
- "Delete all existing format styles.",
- NULL),
- m_options(interpreter)
+ ~CommandObjectTypeFormatterClear () override
{
}
- ~CommandObjectTypeFormatClear ()
+protected:
+ virtual void
+ FormatterSpecificDeletion ()
{
}
-protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
if (m_options.m_delete_all)
- DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL);
-
+ {
+ DataVisualization::Categories::ForEach( [this] (const TypeCategoryImplSP& category_sp) -> bool {
+ category_sp->Clear(m_formatter_kind_mask);
+ return true;
+ });
+ }
else
{
lldb::TypeCategoryImplSP category;
@@ -1183,10 +1197,14 @@ protected:
DataVisualization::Categories::GetCategory(cat_nameCS, category);
}
else
+ {
DataVisualization::Categories::GetCategory(ConstString(NULL), category);
- category->Clear(eFormatCategoryItemValue | eFormatCategoryItemRegexValue);
+ }
+ category->Clear(m_formatter_kind_mask);
}
+ FormatterSpecificDeletion();
+
result.SetStatus(eReturnStatusSuccessFinishResult);
return result.Succeeded();
}
@@ -1194,46 +1212,68 @@ protected:
};
OptionDefinition
-CommandObjectTypeFormatClear::CommandOptions::g_option_table[] =
+CommandObjectTypeFormatterClear::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
-// CommandObjectTypeFormatList
+// CommandObjectTypeFormatDelete
//-------------------------------------------------------------------------
-bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry);
-bool CommandObjectTypeRXFormatList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeFormatImplSP& entry);
+class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete
+{
+public:
+ CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) :
+ CommandObjectTypeFormatterDelete (interpreter,
+ eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
+ "type format delete",
+ "Delete an existing formatting style for a type.")
+ {
+ }
+
+ ~CommandObjectTypeFormatDelete () override
+ {
+ }
+};
-class CommandObjectTypeFormatList;
+//-------------------------------------------------------------------------
+// CommandObjectTypeFormatClear
+//-------------------------------------------------------------------------
-struct CommandObjectTypeFormatList_LoopCallbackParam {
- CommandObjectTypeFormatList* self;
- CommandReturnObject* result;
- RegularExpression* regex;
- RegularExpression* cate_regex;
- CommandObjectTypeFormatList_LoopCallbackParam(CommandObjectTypeFormatList* S, CommandReturnObject* R,
- RegularExpression* X = NULL, RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
+class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear
+{
+public:
+ CommandObjectTypeFormatClear (CommandInterpreter &interpreter) :
+ CommandObjectTypeFormatterClear (interpreter,
+ eFormatCategoryItemValue | eFormatCategoryItemRegexValue,
+ "type format clear",
+ "Delete all existing format styles.")
+ {
+ }
};
-class CommandObjectTypeFormatList : public CommandObjectParsed
+template <typename FormatterType>
+class CommandObjectTypeFormatterList : public CommandObjectParsed
{
+ typedef typename FormatterType::SharedPointer FormatterSharedPointer;
+
class CommandOptions : public Options
{
public:
CommandOptions (CommandInterpreter &interpreter) :
- Options (interpreter)
+ Options (interpreter),
+ m_category_regex("",""),
+ m_category_language(lldb::eLanguageTypeUnknown, lldb::eLanguageTypeUnknown)
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -1241,7 +1281,10 @@ class CommandObjectTypeFormatList : public CommandObjectParsed
switch (short_option)
{
case 'w':
- m_category_regex = std::string(option_arg);
+ m_category_regex.SetCurrentValue(option_arg);
+ break;
+ case 'l':
+ error = m_category_language.SetValueFromString(option_arg);
break;
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
@@ -1252,14 +1295,22 @@ class CommandObjectTypeFormatList : public CommandObjectParsed
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
- m_category_regex = "";
+ m_category_regex.Clear();
+ m_category_language.Clear();
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
+ static OptionDefinition g_option_table[] =
+ {
+ { LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
+ { LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Only show the category for a specific language."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+ };
+
return g_option_table;
}
@@ -1269,23 +1320,25 @@ class CommandObjectTypeFormatList : public CommandObjectParsed
// Instance variables to hold the values for command options.
- std::string m_category_regex;
-
+ OptionValueString m_category_regex;
+ OptionValueLanguage m_category_language;
};
CommandOptions m_options;
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
public:
- CommandObjectTypeFormatList (CommandInterpreter &interpreter) :
+ CommandObjectTypeFormatterList (CommandInterpreter &interpreter,
+ const char* name,
+ const char* help) :
CommandObjectParsed (interpreter,
- "type format list",
- "Show a list of current formatting styles.",
+ name,
+ help,
NULL),
m_options(interpreter)
{
@@ -1300,117 +1353,150 @@ public:
m_arguments.push_back (type_arg);
}
- ~CommandObjectTypeFormatList ()
+ ~CommandObjectTypeFormatterList () override
{
}
protected:
+ virtual void
+ FormatterSpecificList (CommandReturnObject &result)
+ {
+ }
+
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
- CommandObjectTypeFormatList_LoopCallbackParam *param;
- RegularExpression* cate_regex =
- m_options.m_category_regex.empty() ? NULL :
- new RegularExpression(m_options.m_category_regex.c_str());
+ std::unique_ptr<RegularExpression> category_regex;
+ std::unique_ptr<RegularExpression> formatter_regex;
- if (argc == 1)
+ if (m_options.m_category_regex.OptionWasSet())
{
- RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
- regex->Compile(command.GetArgumentAtIndex(0));
- param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,regex,cate_regex);
+ category_regex.reset(new RegularExpression());
+ if (!category_regex->Compile(m_options.m_category_regex.GetCurrentValue()))
+ {
+ result.AppendErrorWithFormat("syntax error in category regular expression '%s'", m_options.m_category_regex.GetCurrentValue());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
}
- else
- param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,NULL,cate_regex);
-
- DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
- delete param;
-
- if (cate_regex)
- delete cate_regex;
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-
-private:
-
- static bool
- PerCategoryCallback(void* param_vp,
- const lldb::TypeCategoryImplSP& cate)
- {
-
- CommandObjectTypeFormatList_LoopCallbackParam* param =
- (CommandObjectTypeFormatList_LoopCallbackParam*)param_vp;
- CommandReturnObject* result = param->result;
-
- const char* cate_name = cate->GetName();
-
- // if the category is disabled or empty and there is no regex, just skip it
- if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemValue | eFormatCategoryItemRegexValue) == 0) && param->cate_regex == NULL)
- return true;
-
- // if we have a regex and this category does not match it, just skip it
- if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false)
- return true;
-
- result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
- cate_name,
- (cate->IsEnabled() ? "enabled" : "disabled"));
+ if (argc == 1)
+ {
+ const char* arg = command.GetArgumentAtIndex(1);
+ formatter_regex.reset(new RegularExpression());
+ if (!formatter_regex->Compile(arg))
+ {
+ result.AppendErrorWithFormat("syntax error in regular expression '%s'", arg);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
- cate->GetTypeFormatsContainer()->LoopThrough(CommandObjectTypeFormatList_LoopCallback, param_vp);
+ auto category_closure = [&result, &formatter_regex] (const lldb::TypeCategoryImplSP& category) -> void {
+ result.GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", category->GetName());
+ TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach;
+ foreach.SetExact([&result, &formatter_regex] (ConstString name, const FormatterSharedPointer& format_sp) -> bool {
+ if (formatter_regex)
+ {
+ bool escape = true;
+ if (0 == strcmp(name.AsCString(), formatter_regex->GetText()))
+ {
+ escape = false;
+ }
+ else if (formatter_regex->Execute(name.AsCString()))
+ {
+ escape = false;
+ }
+
+ if (escape)
+ return true;
+ }
+
+ result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), format_sp->GetDescription().c_str());
+
+ return true;
+ });
+
+ foreach.SetWithRegex( [&result, &formatter_regex] (RegularExpressionSP regex_sp, const FormatterSharedPointer& format_sp) -> bool {
+ if (formatter_regex)
+ {
+ bool escape = true;
+ if (0 == strcmp(regex_sp->GetText(), formatter_regex->GetText()))
+ {
+ escape = false;
+ }
+ else if (formatter_regex->Execute(regex_sp->GetText()))
+ {
+ escape = false;
+ }
+
+ if (escape)
+ return true;
+ }
+
+ result.GetOutputStream().Printf ("%s: %s\n", regex_sp->GetText(), format_sp->GetDescription().c_str());
+
+ return true;
+ });
+
+ category->ForEach(foreach);
+ };
- if (cate->GetRegexTypeSummariesContainer()->GetCount() > 0)
+ if (m_options.m_category_language.OptionWasSet())
{
- result->GetOutputStream().Printf("Regex-based summaries (slower):\n");
- cate->GetRegexTypeFormatsContainer()->LoopThrough(CommandObjectTypeRXFormatList_LoopCallback, param_vp);
+ lldb::TypeCategoryImplSP category_sp;
+ DataVisualization::Categories::GetCategory(m_options.m_category_language.GetCurrentValue(), category_sp);
+ if (category_sp)
+ category_closure(category_sp);
}
- return true;
- }
-
-
- bool
- LoopCallback (const char* type,
- const lldb::TypeFormatImplSP& entry,
- RegularExpression* regex,
- CommandReturnObject *result)
- {
- if (regex == NULL || strcmp(type,regex->GetText()) == 0 || regex->Execute(type))
- result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
- return true;
+ else
+ {
+ DataVisualization::Categories::ForEach( [this, &command, &result, &category_regex, &formatter_regex, &category_closure] (const lldb::TypeCategoryImplSP& category) -> bool {
+ if (category_regex)
+ {
+ bool escape = true;
+ if (0 == strcmp(category->GetName(), category_regex->GetText()))
+ {
+ escape = false;
+ }
+ else if (category_regex->Execute(category->GetName()))
+ {
+ escape = false;
+ }
+
+ if (escape)
+ return true;
+ }
+
+ category_closure(category);
+
+ return true;
+ });
+
+ FormatterSpecificList(result);
+ }
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return result.Succeeded();
}
-
- friend bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry);
- friend bool CommandObjectTypeRXFormatList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeFormatImplSP& entry);
-
};
-bool
-CommandObjectTypeFormatList_LoopCallback (
- void* pt2self,
- ConstString type,
- const lldb::TypeFormatImplSP& entry)
-{
- CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self;
- return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
-}
-
-bool
-CommandObjectTypeRXFormatList_LoopCallback (
- void* pt2self,
- lldb::RegularExpressionSP regex,
- const lldb::TypeFormatImplSP& entry)
-{
- CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self;
- return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
-}
+//-------------------------------------------------------------------------
+// CommandObjectTypeFormatList
+//-------------------------------------------------------------------------
-OptionDefinition
-CommandObjectTypeFormatList::CommandOptions::g_option_table[] =
+class CommandObjectTypeFormatList : public CommandObjectTypeFormatterList<TypeFormatImpl>
{
- { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
- { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+public:
+
+ CommandObjectTypeFormatList (CommandInterpreter &interpreter) :
+ CommandObjectTypeFormatterList(interpreter,
+ "type format list",
+ "Show a list of current formats.")
+ {
+ }
};
#ifndef LLDB_DISABLE_PYTHON
@@ -1438,6 +1524,9 @@ CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx
case 'e':
m_flags.SetDontShowChildren(false);
break;
+ case 'h':
+ m_flags.SetHideEmptyAggregates(true);
+ break;
case 'v':
m_flags.SetDontShowValue(true);
break;
@@ -1924,6 +2013,7 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type."},
{ LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."},
{ LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines."},
+ { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "hide-empty", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Do not expand aggregate data types with no children."},
{ LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "A name for this summary string."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -1933,194 +2023,113 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] =
// CommandObjectTypeSummaryDelete
//-------------------------------------------------------------------------
-class CommandObjectTypeSummaryDelete : public CommandObjectParsed
+class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete
{
-private:
- class CommandOptions : public Options
+public:
+ CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) :
+ CommandObjectTypeFormatterDelete (interpreter,
+ eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
+ "type summary delete",
+ "Delete an existing summary for a type.")
{
- public:
-
- CommandOptions (CommandInterpreter &interpreter) :
- Options (interpreter)
- {
- }
-
- virtual
- ~CommandOptions (){}
-
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- case 'a':
- m_delete_all = true;
- break;
- case 'w':
- m_category = std::string(option_arg);
- break;
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
- }
-
- return error;
- }
-
- void
- OptionParsingStarting ()
- {
- m_delete_all = false;
- m_category = "default";
- }
-
- const OptionDefinition*
- GetDefinitions ()
- {
- return g_option_table;
- }
-
- // Options table: Required for subclasses of Options.
-
- static OptionDefinition g_option_table[];
-
- // Instance variables to hold the values for command options.
-
- bool m_delete_all;
- std::string m_category;
-
- };
-
- CommandOptions m_options;
+ }
- virtual Options *
- GetOptions ()
+ ~CommandObjectTypeSummaryDelete () override
{
- return &m_options;
}
- static bool
- PerCategoryCallback(void* param,
- const lldb::TypeCategoryImplSP& category_sp)
+protected:
+ bool
+ FormatterSpecificDeletion (ConstString typeCS) override
{
- ConstString *name = (ConstString*)param;
- category_sp->Delete(*name, eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary);
- return true;
+ if (m_options.m_language != lldb::eLanguageTypeUnknown)
+ return false;
+ return DataVisualization::NamedSummaryFormats::Delete(typeCS);
}
+};
+class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear
+{
public:
- CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "type summary delete",
- "Delete an existing summary style for a type.",
- NULL),
- m_options(interpreter)
+ CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) :
+ CommandObjectTypeFormatterClear (interpreter,
+ eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary,
+ "type summary clear",
+ "Delete all existing summaries.")
{
- CommandArgumentEntry type_arg;
- CommandArgumentData type_style_arg;
-
- type_style_arg.arg_type = eArgTypeName;
- type_style_arg.arg_repetition = eArgRepeatPlain;
-
- type_arg.push_back (type_style_arg);
-
- m_arguments.push_back (type_arg);
-
}
- ~CommandObjectTypeSummaryDelete ()
+protected:
+ void
+ FormatterSpecificDeletion () override
+ {
+ DataVisualization::NamedSummaryFormats::Clear();
+ }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeSummaryList
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeSummaryList : public CommandObjectTypeFormatterList<TypeSummaryImpl>
+{
+public:
+
+ CommandObjectTypeSummaryList (CommandInterpreter &interpreter) :
+ CommandObjectTypeFormatterList(interpreter,
+ "type summary list",
+ "Show a list of current summaries.")
{
}
protected:
- bool
- DoExecute (Args& command, CommandReturnObject &result)
+ void
+ FormatterSpecificList (CommandReturnObject &result) override
{
- const size_t argc = command.GetArgumentCount();
-
- if (argc != 1)
- {
- result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- const char* typeA = command.GetArgumentAtIndex(0);
- ConstString typeCS(typeA);
-
- if (!typeCS)
- {
- result.AppendError("empty typenames not allowed");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- if (m_options.m_delete_all)
- {
- DataVisualization::Categories::LoopThrough(PerCategoryCallback, &typeCS);
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
- }
-
- lldb::TypeCategoryImplSP category;
- DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
-
- bool delete_category = category->Delete(typeCS,
- eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary);
- bool delete_named = DataVisualization::NamedSummaryFormats::Delete(typeCS);
-
- if (delete_category || delete_named)
- {
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
- }
- else
+ if (DataVisualization::NamedSummaryFormats::GetCount() > 0)
{
- result.AppendErrorWithFormat ("no custom summary for %s.\n", typeA);
- result.SetStatus(eReturnStatusFailed);
- return false;
+ result.GetOutputStream().Printf("Named summaries:\n");
+ DataVisualization::NamedSummaryFormats::ForEach( [&result] (ConstString name, const TypeSummaryImplSP& summary_sp) -> bool {
+ result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), summary_sp->GetDescription().c_str());
+ return true;
+ });
}
-
}
};
-OptionDefinition
-CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] =
-{
- { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."},
- { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."},
- { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
-};
+//-------------------------------------------------------------------------
+// CommandObjectTypeCategoryDefine
+//-------------------------------------------------------------------------
-class CommandObjectTypeSummaryClear : public CommandObjectParsed
+class CommandObjectTypeCategoryDefine : public CommandObjectParsed
{
-private:
class CommandOptions : public Options
{
public:
CommandOptions (CommandInterpreter &interpreter) :
- Options (interpreter)
+ Options (interpreter),
+ m_define_enabled(false,false),
+ m_cate_language(eLanguageTypeUnknown,eLanguageTypeUnknown)
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
switch (short_option)
{
- case 'a':
- m_delete_all = true;
+ case 'e':
+ m_define_enabled.SetValueFromString("true");
+ break;
+ case 'l':
+ error = m_cate_language.SetValueFromString(option_arg);
break;
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
@@ -2131,13 +2140,14 @@ private:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
- m_delete_all = false;
+ m_define_enabled.Clear();
+ m_cate_language.Clear();
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -2148,66 +2158,69 @@ private:
// Instance variables to hold the values for command options.
- bool m_delete_all;
- bool m_delete_named;
+ OptionValueBoolean m_define_enabled;
+ OptionValueLanguage m_cate_language;
+
+
};
CommandOptions m_options;
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
-
- static bool
- PerCategoryCallback(void* param,
- const lldb::TypeCategoryImplSP& cate)
- {
- cate->GetTypeSummariesContainer()->Clear();
- cate->GetRegexTypeSummariesContainer()->Clear();
- return true;
-
- }
-
+
public:
- CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "type summary clear",
- "Delete all existing summary styles.",
- NULL),
- m_options(interpreter)
+ CommandObjectTypeCategoryDefine (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "type category define",
+ "Define a new category as a source of formatters.",
+ NULL),
+ m_options(interpreter)
{
+ CommandArgumentEntry type_arg;
+ CommandArgumentData type_style_arg;
+
+ type_style_arg.arg_type = eArgTypeName;
+ type_style_arg.arg_repetition = eArgRepeatPlus;
+
+ type_arg.push_back (type_style_arg);
+
+ m_arguments.push_back (type_arg);
+
}
- ~CommandObjectTypeSummaryClear ()
+ ~CommandObjectTypeCategoryDefine () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
+ const size_t argc = command.GetArgumentCount();
- if (m_options.m_delete_all)
- DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL);
+ if (argc < 1)
+ {
+ result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
- else
- {
- lldb::TypeCategoryImplSP category;
- if (command.GetArgumentCount() > 0)
+ for (size_t i = 0; i < argc; i++)
+ {
+ const char* cateName = command.GetArgumentAtIndex(i);
+ TypeCategoryImplSP category_sp;
+ if (DataVisualization::Categories::GetCategory(ConstString(cateName), category_sp) && category_sp)
{
- const char* cat_name = command.GetArgumentAtIndex(0);
- ConstString cat_nameCS(cat_name);
- DataVisualization::Categories::GetCategory(cat_nameCS, category);
+ category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
+ if (m_options.m_define_enabled.GetCurrentValue())
+ DataVisualization::Categories::Enable(category_sp, TypeCategoryMap::Default);
}
- else
- DataVisualization::Categories::GetCategory(ConstString(NULL), category);
- category->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary);
}
- DataVisualization::NamedSummaryFormats::Clear();
-
result.SetStatus(eReturnStatusSuccessFinishResult);
return result.Succeeded();
}
@@ -2215,34 +2228,19 @@ protected:
};
OptionDefinition
-CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] =
+CommandObjectTypeCategoryDefine::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."},
+ { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "If specified, this category will be created enabled."},
+ { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Specify the language that this category is supported for."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------
-// CommandObjectTypeSummaryList
+// CommandObjectTypeCategoryEnable
//-------------------------------------------------------------------------
-bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const StringSummaryFormat::SharedPointer& entry);
-bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry);
-
-class CommandObjectTypeSummaryList;
-
-struct CommandObjectTypeSummaryList_LoopCallbackParam {
- CommandObjectTypeSummaryList* self;
- CommandReturnObject* result;
- RegularExpression* regex;
- RegularExpression* cate_regex;
- CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R,
- RegularExpression* X = NULL,
- RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
-};
-
-class CommandObjectTypeSummaryList : public CommandObjectParsed
+class CommandObjectTypeCategoryEnable : public CommandObjectParsed
{
-
class CommandOptions : public Options
{
public:
@@ -2252,19 +2250,23 @@ class CommandObjectTypeSummaryList : public CommandObjectParsed
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
switch (short_option)
{
- case 'w':
- m_category_regex = std::string(option_arg);
+ case 'l':
+ if (option_arg)
+ {
+ m_language = Language::GetLanguageTypeFromString(option_arg);
+ if (m_language == lldb::eLanguageTypeUnknown)
+ error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg);
+ }
break;
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
@@ -2275,13 +2277,13 @@ class CommandObjectTypeSummaryList : public CommandObjectParsed
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
- m_category_regex = "";
+ m_language = lldb::eLanguageTypeUnknown;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -2292,176 +2294,25 @@ class CommandObjectTypeSummaryList : public CommandObjectParsed
// Instance variables to hold the values for command options.
- std::string m_category_regex;
+ lldb::LanguageType m_language;
};
CommandOptions m_options;
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
public:
- CommandObjectTypeSummaryList (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "type summary list",
- "Show a list of current summary styles.",
- NULL),
- m_options(interpreter)
- {
- CommandArgumentEntry type_arg;
- CommandArgumentData type_style_arg;
-
- type_style_arg.arg_type = eArgTypeName;
- type_style_arg.arg_repetition = eArgRepeatOptional;
-
- type_arg.push_back (type_style_arg);
-
- m_arguments.push_back (type_arg);
- }
-
- ~CommandObjectTypeSummaryList ()
- {
- }
-
-protected:
- bool
- DoExecute (Args& command, CommandReturnObject &result)
- {
- const size_t argc = command.GetArgumentCount();
-
- CommandObjectTypeSummaryList_LoopCallbackParam *param;
- RegularExpression* cate_regex =
- m_options.m_category_regex.empty() ? NULL :
- new RegularExpression(m_options.m_category_regex.c_str());
-
- if (argc == 1)
- {
- RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
- regex->Compile(command.GetArgumentAtIndex(0));
- param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex,cate_regex);
- }
- else
- param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,NULL,cate_regex);
-
- DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
- delete param;
-
- if (DataVisualization::NamedSummaryFormats::GetCount() > 0)
- {
- result.GetOutputStream().Printf("Named summaries:\n");
- if (argc == 1)
- {
- RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
- regex->Compile(command.GetArgumentAtIndex(0));
- param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex);
- }
- else
- param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result);
- DataVisualization::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param);
- delete param;
- }
-
- if (cate_regex)
- delete cate_regex;
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-
-private:
-
- static bool
- PerCategoryCallback(void* param_vp,
- const lldb::TypeCategoryImplSP& cate)
- {
-
- CommandObjectTypeSummaryList_LoopCallbackParam* param =
- (CommandObjectTypeSummaryList_LoopCallbackParam*)param_vp;
- CommandReturnObject* result = param->result;
-
- const char* cate_name = cate->GetName();
-
- // if the category is disabled or empty and there is no regex, just skip it
- if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary) == 0) && param->cate_regex == NULL)
- return true;
-
- // if we have a regex and this category does not match it, just skip it
- if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false)
- return true;
-
- result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
- cate_name,
- (cate->IsEnabled() ? "enabled" : "disabled"));
-
- cate->GetTypeSummariesContainer()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param_vp);
-
- if (cate->GetRegexTypeSummariesContainer()->GetCount() > 0)
- {
- result->GetOutputStream().Printf("Regex-based summaries (slower):\n");
- cate->GetRegexTypeSummariesContainer()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param_vp);
- }
- return true;
- }
-
-
- bool
- LoopCallback (const char* type,
- const lldb::TypeSummaryImplSP& entry,
- RegularExpression* regex,
- CommandReturnObject *result)
- {
- if (regex == NULL || strcmp(type,regex->GetText()) == 0 || regex->Execute(type))
- result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
- return true;
- }
-
- friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeSummaryImplSP& entry);
- friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeSummaryImplSP& entry);
-};
-
-bool
-CommandObjectTypeSummaryList_LoopCallback (
- void* pt2self,
- ConstString type,
- const lldb::TypeSummaryImplSP& entry)
-{
- CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
- return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
-}
-
-bool
-CommandObjectTypeRXSummaryList_LoopCallback (
- void* pt2self,
- lldb::RegularExpressionSP regex,
- const lldb::TypeSummaryImplSP& entry)
-{
- CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self;
- return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
-}
-
-OptionDefinition
-CommandObjectTypeSummaryList::CommandOptions::g_option_table[] =
-{
- { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
- { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
-};
-
-//-------------------------------------------------------------------------
-// CommandObjectTypeCategoryEnable
-//-------------------------------------------------------------------------
-
-class CommandObjectTypeCategoryEnable : public CommandObjectParsed
-{
-public:
CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"type category enable",
"Enable a category as a source of formatters.",
- NULL)
+ NULL),
+ m_options(interpreter)
{
CommandArgumentEntry type_arg;
CommandArgumentData type_style_arg;
@@ -2475,19 +2326,20 @@ public:
}
- ~CommandObjectTypeCategoryEnable ()
+ ~CommandObjectTypeCategoryEnable () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
- if (argc < 1)
+ if (argc < 1 &&
+ m_options.m_language == lldb::eLanguageTypeUnknown)
{
- result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
+ result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -2496,7 +2348,7 @@ protected:
{
DataVisualization::Categories::EnableStar();
}
- else
+ else if (argc > 0)
{
for (int i = argc - 1; i >= 0; i--)
{
@@ -2521,12 +2373,22 @@ protected:
}
}
+ if (m_options.m_language != lldb::eLanguageTypeUnknown)
+ DataVisualization::Categories::Enable(m_options.m_language);
+
result.SetStatus(eReturnStatusSuccessFinishResult);
return result.Succeeded();
}
};
+OptionDefinition
+CommandObjectTypeCategoryEnable::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Enable the category for this language."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
//-------------------------------------------------------------------------
// CommandObjectTypeCategoryDelete
//-------------------------------------------------------------------------
@@ -2552,13 +2414,13 @@ public:
}
- ~CommandObjectTypeCategoryDelete ()
+ ~CommandObjectTypeCategoryDelete () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
@@ -2606,185 +2468,6 @@ protected:
class CommandObjectTypeCategoryDisable : public CommandObjectParsed
{
-public:
- CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "type category disable",
- "Disable a category as a source of formatters.",
- NULL)
- {
- CommandArgumentEntry type_arg;
- CommandArgumentData type_style_arg;
-
- type_style_arg.arg_type = eArgTypeName;
- type_style_arg.arg_repetition = eArgRepeatPlus;
-
- type_arg.push_back (type_style_arg);
-
- m_arguments.push_back (type_arg);
-
- }
-
- ~CommandObjectTypeCategoryDisable ()
- {
- }
-
-protected:
- bool
- DoExecute (Args& command, CommandReturnObject &result)
- {
- const size_t argc = command.GetArgumentCount();
-
- if (argc < 1)
- {
- result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)
- {
- DataVisualization::Categories::DisableStar();
- }
- else
- {
- // the order is not relevant here
- for (int i = argc - 1; i >= 0; i--)
- {
- const char* typeA = command.GetArgumentAtIndex(i);
- ConstString typeCS(typeA);
-
- if (!typeCS)
- {
- result.AppendError("empty category name not allowed");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- DataVisualization::Categories::Disable(typeCS);
- }
- }
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-
-};
-
-//-------------------------------------------------------------------------
-// CommandObjectTypeCategoryList
-//-------------------------------------------------------------------------
-
-class CommandObjectTypeCategoryList : public CommandObjectParsed
-{
-private:
-
- struct CommandObjectTypeCategoryList_CallbackParam
- {
- CommandReturnObject* result;
- RegularExpression* regex;
-
- CommandObjectTypeCategoryList_CallbackParam(CommandReturnObject* res,
- RegularExpression* rex = NULL) :
- result(res),
- regex(rex)
- {
- }
-
- };
-
- static bool
- PerCategoryCallback(void* param_vp,
- const lldb::TypeCategoryImplSP& cate)
- {
- CommandObjectTypeCategoryList_CallbackParam* param =
- (CommandObjectTypeCategoryList_CallbackParam*)param_vp;
- CommandReturnObject* result = param->result;
- RegularExpression* regex = param->regex;
-
- const char* cate_name = cate->GetName();
-
- if (regex == NULL || strcmp(cate_name, regex->GetText()) == 0 || regex->Execute(cate_name))
- result->GetOutputStream().Printf("Category %s is%s enabled\n",
- cate_name,
- (cate->IsEnabled() ? "" : " not"));
- return true;
- }
-public:
- CommandObjectTypeCategoryList (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "type category list",
- "Provide a list of all existing categories.",
- NULL)
- {
- CommandArgumentEntry type_arg;
- CommandArgumentData type_style_arg;
-
- type_style_arg.arg_type = eArgTypeName;
- type_style_arg.arg_repetition = eArgRepeatOptional;
-
- type_arg.push_back (type_style_arg);
-
- m_arguments.push_back (type_arg);
- }
-
- ~CommandObjectTypeCategoryList ()
- {
- }
-
-protected:
- bool
- DoExecute (Args& command, CommandReturnObject &result)
- {
- const size_t argc = command.GetArgumentCount();
- RegularExpression* regex = NULL;
-
- if (argc == 0)
- ;
- else if (argc == 1)
- regex = new RegularExpression(command.GetArgumentAtIndex(0));
- else
- {
- result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- CommandObjectTypeCategoryList_CallbackParam param(&result,
- regex);
-
- DataVisualization::Categories::LoopThrough(PerCategoryCallback, &param);
-
- if (regex)
- delete regex;
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-
-};
-
-//-------------------------------------------------------------------------
-// CommandObjectTypeFilterList
-//-------------------------------------------------------------------------
-
-bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
-bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
-
-class CommandObjectTypeFilterList;
-
-struct CommandObjectTypeFilterList_LoopCallbackParam {
- CommandObjectTypeFilterList* self;
- CommandReturnObject* result;
- RegularExpression* regex;
- RegularExpression* cate_regex;
- CommandObjectTypeFilterList_LoopCallbackParam(CommandObjectTypeFilterList* S, CommandReturnObject* R,
- RegularExpression* X = NULL,
- RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
-};
-
-class CommandObjectTypeFilterList : public CommandObjectParsed
-{
-
class CommandOptions : public Options
{
public:
@@ -2794,19 +2477,23 @@ class CommandObjectTypeFilterList : public CommandObjectParsed
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
switch (short_option)
{
- case 'w':
- m_category_regex = std::string(option_arg);
+ case 'l':
+ if (option_arg)
+ {
+ m_language = Language::GetLanguageTypeFromString(option_arg);
+ if (m_language == lldb::eLanguageTypeUnknown)
+ error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg);
+ }
break;
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
@@ -2817,13 +2504,13 @@ class CommandObjectTypeFilterList : public CommandObjectParsed
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
- m_category_regex = "";
+ m_language = lldb::eLanguageTypeUnknown;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -2834,23 +2521,23 @@ class CommandObjectTypeFilterList : public CommandObjectParsed
// Instance variables to hold the values for command options.
- std::string m_category_regex;
+ lldb::LanguageType m_language;
};
CommandOptions m_options;
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
-
+
public:
- CommandObjectTypeFilterList (CommandInterpreter &interpreter) :
+ CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
- "type filter list",
- "Show a list of current filters.",
+ "type category disable",
+ "Disable a category as a source of formatters.",
NULL),
m_options(interpreter)
{
@@ -2858,216 +2545,82 @@ public:
CommandArgumentData type_style_arg;
type_style_arg.arg_type = eArgTypeName;
- type_style_arg.arg_repetition = eArgRepeatOptional;
+ type_style_arg.arg_repetition = eArgRepeatPlus;
type_arg.push_back (type_style_arg);
m_arguments.push_back (type_arg);
+
}
- ~CommandObjectTypeFilterList ()
+ ~CommandObjectTypeCategoryDisable () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
- CommandObjectTypeFilterList_LoopCallbackParam *param;
- RegularExpression* cate_regex =
- m_options.m_category_regex.empty() ? NULL :
- new RegularExpression(m_options.m_category_regex.c_str());
-
- if (argc == 1)
+ if (argc < 1 &&
+ m_options.m_language == lldb::eLanguageTypeUnknown)
{
- RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
- regex->Compile(command.GetArgumentAtIndex(0));
- param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,regex,cate_regex);
+ result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
- else
- param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,NULL,cate_regex);
-
- DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
- delete param;
-
- if (cate_regex)
- delete cate_regex;
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-
-private:
-
- static bool
- PerCategoryCallback(void* param_vp,
- const lldb::TypeCategoryImplSP& cate)
- {
-
- const char* cate_name = cate->GetName();
- CommandObjectTypeFilterList_LoopCallbackParam* param =
- (CommandObjectTypeFilterList_LoopCallbackParam*)param_vp;
- CommandReturnObject* result = param->result;
-
- // if the category is disabled or empty and there is no regex, just skip it
- if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter) == 0) && param->cate_regex == NULL)
- return true;
-
- // if we have a regex and this category does not match it, just skip it
- if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false)
- return true;
-
- result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
- cate_name,
- (cate->IsEnabled() ? "enabled" : "disabled"));
-
- cate->GetTypeFiltersContainer()->LoopThrough(CommandObjectTypeFilterList_LoopCallback, param_vp);
-
- if (cate->GetRegexTypeFiltersContainer()->GetCount() > 0)
+ if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0)
+ {
+ DataVisualization::Categories::DisableStar();
+ }
+ else if (argc > 0)
{
- result->GetOutputStream().Printf("Regex-based filters (slower):\n");
- cate->GetRegexTypeFiltersContainer()->LoopThrough(CommandObjectTypeFilterRXList_LoopCallback, param_vp);
+ // the order is not relevant here
+ for (int i = argc - 1; i >= 0; i--)
+ {
+ const char* typeA = command.GetArgumentAtIndex(i);
+ ConstString typeCS(typeA);
+
+ if (!typeCS)
+ {
+ result.AppendError("empty category name not allowed");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ DataVisualization::Categories::Disable(typeCS);
+ }
}
- return true;
- }
-
- bool
- LoopCallback (const char* type,
- const SyntheticChildren::SharedPointer& entry,
- RegularExpression* regex,
- CommandReturnObject *result)
- {
- if (regex == NULL || regex->Execute(type))
- result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
- return true;
+ if (m_options.m_language != lldb::eLanguageTypeUnknown)
+ DataVisualization::Categories::Disable(m_options.m_language);
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return result.Succeeded();
}
- friend bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
- friend bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
};
-bool
-CommandObjectTypeFilterList_LoopCallback (void* pt2self,
- ConstString type,
- const SyntheticChildren::SharedPointer& entry)
-{
- CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self;
- return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
-}
-
-bool
-CommandObjectTypeFilterRXList_LoopCallback (void* pt2self,
- lldb::RegularExpressionSP regex,
- const SyntheticChildren::SharedPointer& entry)
-{
- CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self;
- return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
-}
-
-
OptionDefinition
-CommandObjectTypeFilterList::CommandOptions::g_option_table[] =
+CommandObjectTypeCategoryDisable::CommandOptions::g_option_table[] =
{
- { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
+ { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Enable the category for this language."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
-#ifndef LLDB_DISABLE_PYTHON
-
//-------------------------------------------------------------------------
-// CommandObjectTypeSynthList
+// CommandObjectTypeCategoryList
//-------------------------------------------------------------------------
-bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
-bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
-
-class CommandObjectTypeSynthList;
-
-struct CommandObjectTypeSynthList_LoopCallbackParam {
- CommandObjectTypeSynthList* self;
- CommandReturnObject* result;
- RegularExpression* regex;
- RegularExpression* cate_regex;
- CommandObjectTypeSynthList_LoopCallbackParam(CommandObjectTypeSynthList* S, CommandReturnObject* R,
- RegularExpression* X = NULL,
- RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {}
-};
-
-class CommandObjectTypeSynthList : public CommandObjectParsed
+class CommandObjectTypeCategoryList : public CommandObjectParsed
{
-
- class CommandOptions : public Options
- {
- public:
-
- CommandOptions (CommandInterpreter &interpreter) :
- Options (interpreter)
- {
- }
-
- virtual
- ~CommandOptions (){}
-
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- case 'w':
- m_category_regex = std::string(option_arg);
- break;
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
- }
-
- return error;
- }
-
- void
- OptionParsingStarting ()
- {
- m_category_regex = "";
- }
-
- const OptionDefinition*
- GetDefinitions ()
- {
- return g_option_table;
- }
-
- // Options table: Required for subclasses of Options.
-
- static OptionDefinition g_option_table[];
-
- // Instance variables to hold the values for command options.
-
- std::string m_category_regex;
-
- };
-
- CommandOptions m_options;
-
- virtual Options *
- GetOptions ()
- {
- return &m_options;
- }
-
public:
- CommandObjectTypeSynthList (CommandInterpreter &interpreter) :
+ CommandObjectTypeCategoryList (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
- "type synthetic list",
- "Show a list of current synthetic providers.",
- NULL),
- m_options(interpreter)
+ "type category list",
+ "Provide a list of all existing categories.",
+ NULL)
{
CommandArgumentEntry type_arg;
CommandArgumentData type_style_arg;
@@ -3080,115 +2633,96 @@ public:
m_arguments.push_back (type_arg);
}
- ~CommandObjectTypeSynthList ()
+ ~CommandObjectTypeCategoryList () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
-
- CommandObjectTypeSynthList_LoopCallbackParam *param;
- RegularExpression* cate_regex =
- m_options.m_category_regex.empty() ? NULL :
- new RegularExpression(m_options.m_category_regex.c_str());
+
+ std::unique_ptr<RegularExpression> regex;
if (argc == 1)
{
- RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0));
- regex->Compile(command.GetArgumentAtIndex(0));
- param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,regex,cate_regex);
+ regex.reset(new RegularExpression());
+ const char* arg = command.GetArgumentAtIndex(0);
+ if (!regex->Compile(arg))
+ {
+ result.AppendErrorWithFormat("syntax error in category regular expression '%s'", arg);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+ else if (argc != 0)
+ {
+ result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
- else
- param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,NULL,cate_regex);
- DataVisualization::Categories::LoopThrough(PerCategoryCallback,param);
- delete param;
-
- if (cate_regex)
- delete cate_regex;
+ DataVisualization::Categories::ForEach( [&regex, &result] (const lldb::TypeCategoryImplSP& category_sp) -> bool {
+ if (regex)
+ {
+ bool escape = true;
+ if (0 == strcmp(category_sp->GetName(), regex->GetText()))
+ {
+ escape = false;
+ }
+ else if (regex->Execute(category_sp->GetName()))
+ {
+ escape = false;
+ }
+
+ if (escape)
+ return true;
+ }
+
+ result.GetOutputStream().Printf("Category: %s\n", category_sp->GetDescription().c_str());
+
+ return true;
+ });
result.SetStatus(eReturnStatusSuccessFinishResult);
return result.Succeeded();
}
-private:
-
- static bool
- PerCategoryCallback(void* param_vp,
- const lldb::TypeCategoryImplSP& cate)
- {
-
- CommandObjectTypeSynthList_LoopCallbackParam* param =
- (CommandObjectTypeSynthList_LoopCallbackParam*)param_vp;
- CommandReturnObject* result = param->result;
-
- const char* cate_name = cate->GetName();
-
- // if the category is disabled or empty and there is no regex, just skip it
- if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth) == 0) && param->cate_regex == NULL)
- return true;
-
- // if we have a regex and this category does not match it, just skip it
- if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false)
- return true;
-
- result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n",
- cate_name,
- (cate->IsEnabled() ? "enabled" : "disabled"));
-
- cate->GetTypeSyntheticsContainer()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp);
-
- if (cate->GetRegexTypeSyntheticsContainer()->GetCount() > 0)
- {
- result->GetOutputStream().Printf("Regex-based synthetic providers (slower):\n");
- cate->GetRegexTypeSyntheticsContainer()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp);
- }
-
- return true;
- }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectTypeFilterList
+//-------------------------------------------------------------------------
+
+class CommandObjectTypeFilterList : public CommandObjectTypeFormatterList<TypeFilterImpl>
+{
+public:
- bool
- LoopCallback (const char* type,
- const SyntheticChildren::SharedPointer& entry,
- RegularExpression* regex,
- CommandReturnObject *result)
+ CommandObjectTypeFilterList (CommandInterpreter &interpreter) :
+ CommandObjectTypeFormatterList(interpreter,
+ "type filter list",
+ "Show a list of current filters.")
{
- if (regex == NULL || regex->Execute(type))
- result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str());
- return true;
}
-
- friend bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry);
- friend bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry);
};
-bool
-CommandObjectTypeSynthList_LoopCallback (void* pt2self,
- ConstString type,
- const SyntheticChildren::SharedPointer& entry)
-{
- CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
- return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result);
-}
-
-bool
-CommandObjectTypeSynthRXList_LoopCallback (void* pt2self,
- lldb::RegularExpressionSP regex,
- const SyntheticChildren::SharedPointer& entry)
-{
- CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self;
- return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result);
-}
+#ifndef LLDB_DISABLE_PYTHON
+//-------------------------------------------------------------------------
+// CommandObjectTypeSynthList
+//-------------------------------------------------------------------------
-OptionDefinition
-CommandObjectTypeSynthList::CommandOptions::g_option_table[] =
+class CommandObjectTypeSynthList : public CommandObjectTypeFormatterList<SyntheticChildren>
{
- { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."},
- { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+public:
+
+ CommandObjectTypeSynthList (CommandInterpreter &interpreter) :
+ CommandObjectTypeFormatterList(interpreter,
+ "type synthetic list",
+ "Show a list of current synthetic providers.")
+ {
+ }
};
#endif // #ifndef LLDB_DISABLE_PYTHON
@@ -3196,164 +2730,20 @@ CommandObjectTypeSynthList::CommandOptions::g_option_table[] =
// CommandObjectTypeFilterDelete
//-------------------------------------------------------------------------
-class CommandObjectTypeFilterDelete : public CommandObjectParsed
+class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete
{
-private:
- class CommandOptions : public Options
- {
- public:
-
- CommandOptions (CommandInterpreter &interpreter) :
- Options (interpreter)
- {
- }
-
- virtual
- ~CommandOptions (){}
-
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- case 'a':
- m_delete_all = true;
- break;
- case 'w':
- m_category = std::string(option_arg);
- break;
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
- }
-
- return error;
- }
-
- void
- OptionParsingStarting ()
- {
- m_delete_all = false;
- m_category = "default";
- }
-
- const OptionDefinition*
- GetDefinitions ()
- {
- return g_option_table;
- }
-
- // Options table: Required for subclasses of Options.
-
- static OptionDefinition g_option_table[];
-
- // Instance variables to hold the values for command options.
-
- bool m_delete_all;
- std::string m_category;
-
- };
-
- CommandOptions m_options;
-
- virtual Options *
- GetOptions ()
- {
- return &m_options;
- }
-
- static bool
- PerCategoryCallback(void* param,
- const lldb::TypeCategoryImplSP& cate)
- {
- ConstString *name = (ConstString*)param;
- return cate->Delete(*name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter);
- }
-
public:
CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "type filter delete",
- "Delete an existing filter for a type.",
- NULL),
- m_options(interpreter)
+ CommandObjectTypeFormatterDelete (interpreter,
+ eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
+ "type filter delete",
+ "Delete an existing filter for a type.")
{
- CommandArgumentEntry type_arg;
- CommandArgumentData type_style_arg;
-
- type_style_arg.arg_type = eArgTypeName;
- type_style_arg.arg_repetition = eArgRepeatPlain;
-
- type_arg.push_back (type_style_arg);
-
- m_arguments.push_back (type_arg);
-
}
- ~CommandObjectTypeFilterDelete ()
+ ~CommandObjectTypeFilterDelete () override
{
}
-
-protected:
- bool
- DoExecute (Args& command, CommandReturnObject &result)
- {
- const size_t argc = command.GetArgumentCount();
-
- if (argc != 1)
- {
- result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- const char* typeA = command.GetArgumentAtIndex(0);
- ConstString typeCS(typeA);
-
- if (!typeCS)
- {
- result.AppendError("empty typenames not allowed");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- if (m_options.m_delete_all)
- {
- DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS);
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
- }
-
- lldb::TypeCategoryImplSP category;
- DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
-
- bool delete_category = category->GetTypeFiltersContainer()->Delete(typeCS);
- delete_category = category->GetRegexTypeFiltersContainer()->Delete(typeCS) || delete_category;
-
- if (delete_category)
- {
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
- }
- else
- {
- result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA);
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- }
-};
-
-OptionDefinition
-CommandObjectTypeFilterDelete::CommandOptions::g_option_table[] =
-{
- { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."},
- { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."},
- { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#ifndef LLDB_DISABLE_PYTHON
@@ -3362,294 +2752,38 @@ CommandObjectTypeFilterDelete::CommandOptions::g_option_table[] =
// CommandObjectTypeSynthDelete
//-------------------------------------------------------------------------
-class CommandObjectTypeSynthDelete : public CommandObjectParsed
+class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete
{
-private:
- class CommandOptions : public Options
- {
- public:
-
- CommandOptions (CommandInterpreter &interpreter) :
- Options (interpreter)
- {
- }
-
- virtual
- ~CommandOptions (){}
-
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- case 'a':
- m_delete_all = true;
- break;
- case 'w':
- m_category = std::string(option_arg);
- break;
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
- }
-
- return error;
- }
-
- void
- OptionParsingStarting ()
- {
- m_delete_all = false;
- m_category = "default";
- }
-
- const OptionDefinition*
- GetDefinitions ()
- {
- return g_option_table;
- }
-
- // Options table: Required for subclasses of Options.
-
- static OptionDefinition g_option_table[];
-
- // Instance variables to hold the values for command options.
-
- bool m_delete_all;
- std::string m_category;
-
- };
-
- CommandOptions m_options;
-
- virtual Options *
- GetOptions ()
- {
- return &m_options;
- }
-
- static bool
- PerCategoryCallback(void* param,
- const lldb::TypeCategoryImplSP& cate)
- {
- ConstString* name = (ConstString*)param;
- return cate->Delete(*name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth);
- }
-
public:
CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "type synthetic delete",
- "Delete an existing synthetic provider for a type.",
- NULL),
- m_options(interpreter)
- {
- CommandArgumentEntry type_arg;
- CommandArgumentData type_style_arg;
-
- type_style_arg.arg_type = eArgTypeName;
- type_style_arg.arg_repetition = eArgRepeatPlain;
-
- type_arg.push_back (type_style_arg);
-
- m_arguments.push_back (type_arg);
-
- }
-
- ~CommandObjectTypeSynthDelete ()
+ CommandObjectTypeFormatterDelete (interpreter,
+ eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
+ "type synthetic delete",
+ "Delete an existing synthetic provider for a type.")
{
}
-protected:
- bool
- DoExecute (Args& command, CommandReturnObject &result)
+ ~CommandObjectTypeSynthDelete () override
{
- const size_t argc = command.GetArgumentCount();
-
- if (argc != 1)
- {
- result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- const char* typeA = command.GetArgumentAtIndex(0);
- ConstString typeCS(typeA);
-
- if (!typeCS)
- {
- result.AppendError("empty typenames not allowed");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- if (m_options.m_delete_all)
- {
- DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS);
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
- }
-
- lldb::TypeCategoryImplSP category;
- DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category);
-
- bool delete_category = category->GetTypeSyntheticsContainer()->Delete(typeCS);
- delete_category = category->GetRegexTypeSyntheticsContainer()->Delete(typeCS) || delete_category;
-
- if (delete_category)
- {
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
- }
- else
- {
- result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA);
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
}
};
-OptionDefinition
-CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] =
-{
- { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."},
- { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."},
- { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
-};
-
#endif // #ifndef LLDB_DISABLE_PYTHON
//-------------------------------------------------------------------------
// CommandObjectTypeFilterClear
//-------------------------------------------------------------------------
-class CommandObjectTypeFilterClear : public CommandObjectParsed
+class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear
{
-private:
-
- class CommandOptions : public Options
- {
- public:
-
- CommandOptions (CommandInterpreter &interpreter) :
- Options (interpreter)
- {
- }
-
- virtual
- ~CommandOptions (){}
-
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- case 'a':
- m_delete_all = true;
- break;
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
- }
-
- return error;
- }
-
- void
- OptionParsingStarting ()
- {
- m_delete_all = false;
- }
-
- const OptionDefinition*
- GetDefinitions ()
- {
- return g_option_table;
- }
-
- // Options table: Required for subclasses of Options.
-
- static OptionDefinition g_option_table[];
-
- // Instance variables to hold the values for command options.
-
- bool m_delete_all;
- bool m_delete_named;
- };
-
- CommandOptions m_options;
-
- virtual Options *
- GetOptions ()
- {
- return &m_options;
- }
-
- static bool
- PerCategoryCallback(void* param,
- const lldb::TypeCategoryImplSP& cate)
- {
- cate->Clear(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter);
- return true;
-
- }
-
public:
CommandObjectTypeFilterClear (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "type filter clear",
- "Delete all existing filters.",
- NULL),
- m_options(interpreter)
+ CommandObjectTypeFormatterClear (interpreter,
+ eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
+ "type filter clear",
+ "Delete all existing filter.")
{
}
-
- ~CommandObjectTypeFilterClear ()
- {
- }
-
-protected:
- bool
- DoExecute (Args& command, CommandReturnObject &result)
- {
-
- if (m_options.m_delete_all)
- DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL);
-
- else
- {
- lldb::TypeCategoryImplSP category;
- if (command.GetArgumentCount() > 0)
- {
- const char* cat_name = command.GetArgumentAtIndex(0);
- ConstString cat_nameCS(cat_name);
- DataVisualization::Categories::GetCategory(cat_nameCS, category);
- }
- else
- DataVisualization::Categories::GetCategory(ConstString(NULL), category);
- category->GetTypeFiltersContainer()->Clear();
- category->GetRegexTypeFiltersContainer()->Clear();
- }
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-
-};
-
-OptionDefinition
-CommandObjectTypeFilterClear::CommandOptions::g_option_table[] =
-{
- { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."},
- { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
#ifndef LLDB_DISABLE_PYTHON
@@ -3657,131 +2791,18 @@ CommandObjectTypeFilterClear::CommandOptions::g_option_table[] =
// CommandObjectTypeSynthClear
//-------------------------------------------------------------------------
-class CommandObjectTypeSynthClear : public CommandObjectParsed
+class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear
{
-private:
-
- class CommandOptions : public Options
- {
- public:
-
- CommandOptions (CommandInterpreter &interpreter) :
- Options (interpreter)
- {
- }
-
- virtual
- ~CommandOptions (){}
-
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- case 'a':
- m_delete_all = true;
- break;
- default:
- error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
- break;
- }
-
- return error;
- }
-
- void
- OptionParsingStarting ()
- {
- m_delete_all = false;
- }
-
- const OptionDefinition*
- GetDefinitions ()
- {
- return g_option_table;
- }
-
- // Options table: Required for subclasses of Options.
-
- static OptionDefinition g_option_table[];
-
- // Instance variables to hold the values for command options.
-
- bool m_delete_all;
- bool m_delete_named;
- };
-
- CommandOptions m_options;
-
- virtual Options *
- GetOptions ()
- {
- return &m_options;
- }
-
- static bool
- PerCategoryCallback(void* param,
- const lldb::TypeCategoryImplSP& cate)
- {
- cate->Clear(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth);
- return true;
-
- }
-
public:
CommandObjectTypeSynthClear (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "type synthetic clear",
- "Delete all existing synthetic providers.",
- NULL),
- m_options(interpreter)
+ CommandObjectTypeFormatterClear (interpreter,
+ eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
+ "type synthetic clear",
+ "Delete all existing synthetic providers.")
{
}
-
- ~CommandObjectTypeSynthClear ()
- {
- }
-
-protected:
- bool
- DoExecute (Args& command, CommandReturnObject &result)
- {
-
- if (m_options.m_delete_all)
- DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL);
-
- else
- {
- lldb::TypeCategoryImplSP category;
- if (command.GetArgumentCount() > 0)
- {
- const char* cat_name = command.GetArgumentAtIndex(0);
- ConstString cat_nameCS(cat_name);
- DataVisualization::Categories::GetCategory(cat_nameCS, category);
- }
- else
- DataVisualization::Categories::GetCategory(ConstString(NULL), category);
- category->GetTypeSyntheticsContainer()->Clear();
- category->GetRegexTypeSyntheticsContainer()->Clear();
- }
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
-
};
-OptionDefinition
-CommandObjectTypeSynthClear::CommandOptions::g_option_table[] =
-{
- { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."},
- { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
-};
-
-
bool
CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result)
{
@@ -3956,10 +2977,10 @@ CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."},
{ LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."},
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-tNULL, ype objects."},
+ { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."},
{ LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."},
{ LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."},
- { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument,NULL, NULL, 0, eArgTypeNone, "Type Python code to generate a class that NULL, provides synthetic children."},
+ { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."},
{ LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
@@ -3981,11 +3002,10 @@ private:
{
}
- virtual
- ~CommandOptions (){}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -4023,7 +3043,7 @@ private:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_cascade = true;
m_skip_pointers = false;
@@ -4035,7 +3055,7 @@ private:
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -4062,8 +3082,8 @@ private:
CommandOptions m_options;
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -4076,7 +3096,7 @@ private:
bool
AddFilter(ConstString type_name,
- SyntheticChildrenSP entry,
+ TypeFilterImplSP entry,
FilterFormatType type,
std::string category_name,
Error* error)
@@ -4175,13 +3195,13 @@ all children of my_foo as if no filter was defined:" R"(
);
}
- ~CommandObjectTypeFilterAdd ()
+ ~CommandObjectTypeFilterAdd () override
{
}
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result)
+ DoExecute (Args& command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
@@ -4199,19 +3219,15 @@ protected:
return false;
}
- SyntheticChildrenSP entry;
-
- TypeFilterImpl* impl = new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade).
- SetSkipPointers(m_options.m_skip_pointers).
- SetSkipReferences(m_options.m_skip_references));
-
- entry.reset(impl);
+ TypeFilterImplSP entry(new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade).
+ SetSkipPointers(m_options.m_skip_pointers).
+ SetSkipReferences(m_options.m_skip_references)));
// go through the expression paths
CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end();
for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
- impl->AddExpressionPath(*begin);
+ entry->AddExpressionPath(*begin);
// now I have a valid provider, let's add it to every type
@@ -4266,6 +3282,215 @@ CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] =
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
+//----------------------------------------------------------------------
+// "type lookup"
+//----------------------------------------------------------------------
+class CommandObjectTypeLookup : public CommandObjectRaw
+{
+protected:
+
+ class CommandOptions : public OptionGroup
+ {
+ public:
+
+ CommandOptions () :
+ OptionGroup(),
+ m_show_help(false),
+ m_language(eLanguageTypeUnknown)
+ {}
+
+ ~CommandOptions () override {}
+
+ uint32_t
+ GetNumDefinitions () override
+ {
+ return 3;
+ }
+
+ const OptionDefinition*
+ GetDefinitions () override
+ {
+ return g_option_table;
+ }
+
+ Error
+ SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value) override
+ {
+ Error error;
+
+ const int short_option = g_option_table[option_idx].short_option;
+
+ switch (short_option)
+ {
+ case 'h':
+ m_show_help = true;
+ break;
+
+ case 'l':
+ m_language = Language::GetLanguageTypeFromString(option_value);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ OptionParsingStarting (CommandInterpreter &interpreter) override
+ {
+ m_show_help = false;
+ m_language = eLanguageTypeUnknown;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+ bool m_show_help;
+ lldb::LanguageType m_language;
+ };
+
+ OptionGroupOptions m_option_group;
+ CommandOptions m_command_options;
+
+public:
+
+ CommandObjectTypeLookup (CommandInterpreter &interpreter) :
+ CommandObjectRaw (interpreter,
+ "type lookup",
+ "Lookup a type by name in the select target.",
+ "type lookup <typename>",
+ eCommandRequiresTarget),
+ m_option_group(interpreter),
+ m_command_options()
+ {
+ m_option_group.Append(&m_command_options);
+ m_option_group.Finalize();
+ }
+
+ ~CommandObjectTypeLookup () override
+ {
+ }
+
+ Options *
+ GetOptions () override
+ {
+ return &m_option_group;
+ }
+
+ bool
+ DoExecute (const char *raw_command_line, CommandReturnObject &result) override
+ {
+ if (!raw_command_line || !raw_command_line[0])
+ {
+ result.SetError("type lookup cannot be invoked without a type name as argument");
+ return false;
+ }
+
+ m_option_group.NotifyOptionParsingStarting();
+
+ const char * name_of_type = NULL;
+
+ if (raw_command_line[0] == '-')
+ {
+ // We have some options and these options MUST end with --.
+ const char *end_options = NULL;
+ const char *s = raw_command_line;
+ while (s && s[0])
+ {
+ end_options = ::strstr (s, "--");
+ if (end_options)
+ {
+ end_options += 2; // Get past the "--"
+ if (::isspace (end_options[0]))
+ {
+ name_of_type = end_options;
+ while (::isspace (*name_of_type))
+ ++name_of_type;
+ break;
+ }
+ }
+ s = end_options;
+ }
+
+ if (end_options)
+ {
+ Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line));
+ if (!ParseOptions (args, result))
+ return false;
+
+ Error error (m_option_group.NotifyOptionParsingFinished());
+ if (error.Fail())
+ {
+ result.AppendError (error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ }
+ if (nullptr == name_of_type)
+ name_of_type = raw_command_line;
+
+ TargetSP target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());
+ const bool fill_all_in = true;
+ ExecutionContext exe_ctx(target_sp.get(), fill_all_in);
+ ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
+
+ bool any_found = false;
+
+ std::vector<Language*> languages;
+
+ if (m_command_options.m_language == eLanguageTypeUnknown)
+ {
+ // FIXME: hardcoding languages is not good
+ languages.push_back(Language::FindPlugin(eLanguageTypeObjC));
+ languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));
+ }
+ else
+ {
+ languages.push_back(Language::FindPlugin(m_command_options.m_language));
+ }
+
+ for (Language* language : languages)
+ {
+ if (!language)
+ continue;
+
+ if (auto scavenger = language->GetTypeScavenger())
+ {
+ Language::TypeScavenger::ResultSet search_results;
+ if (scavenger->Find(best_scope, name_of_type, search_results) > 0)
+ {
+ for (const auto& search_result : search_results)
+ {
+ if (search_result && search_result->IsValid())
+ {
+ any_found = true;
+ search_result->DumpToStream(result.GetOutputStream(), this->m_command_options.m_show_help);
+ }
+ }
+ }
+ }
+ }
+
+ result.SetStatus (any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+
+};
+
+OptionDefinition
+CommandObjectTypeLookup::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display available help for types"},
+ { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Which language's types should the search scope be"},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
template <typename FormatterType>
class CommandObjectFormatterInfo : public CommandObjectRaw
{
@@ -4293,14 +3518,13 @@ public:
SetSyntax(syntax.GetData());
}
- virtual
- ~CommandObjectFormatterInfo ()
+ ~CommandObjectFormatterInfo () override
{
}
protected:
- virtual bool
- DoExecute (const char *command, CommandReturnObject &result)
+ bool
+ DoExecute (const char *command, CommandReturnObject &result) override
{
auto target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
auto frame_sp = target_sp->GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame();
@@ -4365,7 +3589,7 @@ public:
}
- ~CommandObjectTypeFormat ()
+ ~CommandObjectTypeFormat () override
{
}
};
@@ -4393,7 +3617,7 @@ public:
}
- ~CommandObjectTypeSynth ()
+ ~CommandObjectTypeSynth () override
{
}
};
@@ -4416,7 +3640,7 @@ public:
}
- ~CommandObjectTypeFilter ()
+ ~CommandObjectTypeFilter () override
{
}
};
@@ -4430,6 +3654,7 @@ public:
"A set of commands for operating on categories",
"type category [<sub-command-options>] ")
{
+ LoadSubCommand ("define", CommandObjectSP (new CommandObjectTypeCategoryDefine (interpreter)));
LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter)));
LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter)));
LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter)));
@@ -4437,7 +3662,7 @@ public:
}
- ~CommandObjectTypeCategory ()
+ ~CommandObjectTypeCategory () override
{
}
};
@@ -4463,7 +3688,7 @@ public:
}
- ~CommandObjectTypeSummary ()
+ ~CommandObjectTypeSummary () override
{
}
};
@@ -4485,11 +3710,10 @@ CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) :
#ifndef LLDB_DISABLE_PYTHON
LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter)));
#endif
+ LoadSubCommand ("lookup", CommandObjectSP (new CommandObjectTypeLookup (interpreter)));
}
CommandObjectType::~CommandObjectType ()
{
}
-
-
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.h
index c796902..54f4a33 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.h
@@ -13,7 +13,6 @@
// C Includes
// C++ Includes
-
// Other libraries and framework includes
// Project includes
@@ -28,10 +27,9 @@ class CommandObjectType : public CommandObjectMultiword
public:
CommandObjectType (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectType ();
+ ~CommandObjectType() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectType_h_
+#endif // liblldb_CommandObjectType_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectVersion.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectVersion.h
index 1fdbed6..30ba9d1 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectVersion.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectVersion.h
@@ -28,16 +28,14 @@ public:
CommandObjectVersion (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectVersion ();
+ ~CommandObjectVersion() override;
protected:
- virtual bool
- DoExecute (Args& args,
- CommandReturnObject &result);
-
+ bool
+ DoExecute(Args& args,
+ CommandReturnObject &result) override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectVersion_h_
+#endif // liblldb_CommandObjectVersion_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.cpp
index 414e784..a97f5ad 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.cpp
@@ -104,7 +104,7 @@ CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(Target *target, Args &args
std::pair<llvm::StringRef, llvm::StringRef> Pair;
size_t i;
int32_t idx;
- // Go through the argments and make a canonical form of arg list containing
+ // Go through the arguments and make a canonical form of arg list containing
// only numbers with possible "-" in between.
for (i = 0; i < args.GetArgumentCount(); ++i) {
llvm::StringRef Arg(args.GetArgumentAtIndex(i));
@@ -178,11 +178,10 @@ public:
m_arguments.push_back(arg);
}
- virtual
- ~CommandObjectWatchpointList () {}
+ ~CommandObjectWatchpointList () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -197,11 +196,10 @@ public:
{
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -226,13 +224,13 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_level = lldb::eDescriptionLevelFull;
}
const OptionDefinition *
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -248,8 +246,8 @@ public:
};
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target == NULL)
@@ -361,13 +359,12 @@ public:
m_arguments.push_back(arg);
}
- virtual
- ~CommandObjectWatchpointEnable () {}
+ ~CommandObjectWatchpointEnable () override {}
protected:
- virtual bool
+ bool
DoExecute (Args& command,
- CommandReturnObject &result)
+ CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (!CheckTargetForWatchpointOperations(target, result))
@@ -441,12 +438,11 @@ public:
}
- virtual
- ~CommandObjectWatchpointDisable () {}
+ ~CommandObjectWatchpointDisable () override {}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (!CheckTargetForWatchpointOperations(target, result))
@@ -524,12 +520,11 @@ public:
m_arguments.push_back(arg);
}
- virtual
- ~CommandObjectWatchpointDelete () {}
+ ~CommandObjectWatchpointDelete () override {}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (!CheckTargetForWatchpointOperations(target, result))
@@ -607,11 +602,10 @@ public:
m_arguments.push_back(arg);
}
- virtual
- ~CommandObjectWatchpointIgnore () {}
+ ~CommandObjectWatchpointIgnore () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -626,11 +620,10 @@ public:
{
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -653,13 +646,13 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_ignore_count = 0;
}
const OptionDefinition *
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -675,9 +668,9 @@ public:
};
protected:
- virtual bool
+ bool
DoExecute (Args& command,
- CommandReturnObject &result)
+ CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (!CheckTargetForWatchpointOperations(target, result))
@@ -763,11 +756,10 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectWatchpointModify () {}
+ ~CommandObjectWatchpointModify () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
@@ -783,11 +775,10 @@ public:
{
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -810,14 +801,14 @@ public:
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_condition.clear();
m_condition_passed = false;
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -833,8 +824,8 @@ public:
};
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (!CheckTargetForWatchpointOperations(target, result))
@@ -958,11 +949,10 @@ corresponding to the byte size of the data type."
m_option_group.Finalize();
}
- virtual
- ~CommandObjectWatchpointSetVariable () {}
+ ~CommandObjectWatchpointSetVariable () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_option_group;
}
@@ -983,8 +973,8 @@ protected:
return 0;
}
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
StackFrame *frame = m_exe_ctx.GetFramePtr();
@@ -1048,7 +1038,7 @@ protected:
valobj_sp = valobj_list.GetValueObjectAtIndex(0);
}
- ClangASTType clang_type;
+ CompilerType compiler_type;
if (valobj_sp)
{
@@ -1061,7 +1051,7 @@ protected:
size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize()
: m_option_watchpoint.watch_size;
}
- clang_type = valobj_sp->GetClangType();
+ compiler_type = valobj_sp->GetCompilerType();
}
else
{
@@ -1078,7 +1068,7 @@ protected:
uint32_t watch_type = m_option_watchpoint.watch_type;
error.Clear();
- Watchpoint *wp = target->CreateWatchpoint(addr, size, &clang_type, watch_type, error).get();
+ Watchpoint *wp = target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error).get();
if (wp)
{
wp->SetWatchSpec(command.GetArgumentAtIndex(0));
@@ -1169,22 +1159,21 @@ Examples:
}
- virtual
- ~CommandObjectWatchpointSetExpression () {}
+ ~CommandObjectWatchpointSetExpression () override {}
// Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
- virtual bool
- WantsCompletion() { return true; }
+ bool
+ WantsCompletion() override { return true; }
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_option_group;
}
protected:
- virtual bool
- DoExecute (const char *raw_command, CommandReturnObject &result)
+ bool
+ DoExecute (const char *raw_command, CommandReturnObject &result) override
{
m_option_group.NotifyOptionParsingStarting(); // This is a raw command, so notify the option group
@@ -1295,10 +1284,10 @@ protected:
// Fetch the type from the value object, the type of the watched object is the pointee type
/// of the expression, so convert to that if we found a valid type.
- ClangASTType clang_type(valobj_sp->GetClangType());
+ CompilerType compiler_type(valobj_sp->GetCompilerType());
Error error;
- Watchpoint *wp = target->CreateWatchpoint(addr, size, &clang_type, watch_type, error).get();
+ Watchpoint *wp = target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error).get();
if (wp)
{
Stream &output_stream = result.GetOutputStream();
@@ -1345,8 +1334,7 @@ public:
}
- virtual
- ~CommandObjectWatchpointSet () {}
+ ~CommandObjectWatchpointSet () override {}
};
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.h
index 1b1ebd7..b1926dc 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpoint.h
@@ -30,14 +30,12 @@ class CommandObjectMultiwordWatchpoint : public CommandObjectMultiword
public:
CommandObjectMultiwordWatchpoint (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectMultiwordWatchpoint ();
+ ~CommandObjectMultiwordWatchpoint() override;
static bool
VerifyWatchpointIDs(Target *target, Args &args, std::vector<uint32_t> &wp_ids);
-
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectWatchpoint_h_
+#endif // liblldb_CommandObjectWatchpoint_h_
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
index 84342cc..2fa849f 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -169,17 +169,16 @@ are no syntax errors may indicate that a function was declared but never called.
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectWatchpointCommandAdd () {}
+ ~CommandObjectWatchpointCommandAdd () override {}
- virtual Options *
- GetOptions ()
+ Options *
+ GetOptions () override
{
return &m_options;
}
- virtual void
- IOHandlerActivated (IOHandler &io_handler)
+ void
+ IOHandlerActivated (IOHandler &io_handler) override
{
StreamFileSP output_sp(io_handler.GetOutputStreamFile());
if (output_sp)
@@ -190,8 +189,8 @@ are no syntax errors may indicate that a function was declared but never called.
}
- virtual void
- IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+ void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override
{
io_handler.SetIsDone(true);
@@ -301,11 +300,10 @@ are no syntax errors may indicate that a function was declared but never called.
{
}
- virtual
- ~CommandOptions () {}
+ ~CommandOptions () override {}
- virtual Error
- SetOptionValue (uint32_t option_idx, const char *option_arg)
+ Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg) override
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
@@ -356,7 +354,7 @@ are no syntax errors may indicate that a function was declared but never called.
return error;
}
void
- OptionParsingStarting ()
+ OptionParsingStarting () override
{
m_use_commands = true;
m_use_script_language = false;
@@ -369,7 +367,7 @@ are no syntax errors may indicate that a function was declared but never called.
}
const OptionDefinition*
- GetDefinitions ()
+ GetDefinitions () override
{
return g_option_table;
}
@@ -392,8 +390,8 @@ are no syntax errors may indicate that a function was declared but never called.
};
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
@@ -550,12 +548,11 @@ public:
}
- virtual
- ~CommandObjectWatchpointCommandDelete () {}
+ ~CommandObjectWatchpointCommandDelete () override {}
protected:
- virtual bool
- DoExecute (Args& command, CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
@@ -641,13 +638,11 @@ public:
m_arguments.push_back (arg);
}
- virtual
- ~CommandObjectWatchpointCommandList () {}
+ ~CommandObjectWatchpointCommandList () override {}
protected:
- virtual bool
- DoExecute (Args& command,
- CommandReturnObject &result)
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.h
index 3bc9b35..d77b32a 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.h
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.h
@@ -13,7 +13,6 @@
// C Includes
// C++ Includes
-
// Other libraries and framework includes
// Project includes
@@ -33,11 +32,9 @@ class CommandObjectWatchpointCommand : public CommandObjectMultiword
public:
CommandObjectWatchpointCommand (CommandInterpreter &interpreter);
- virtual
- ~CommandObjectWatchpointCommand ();
-
+ ~CommandObjectWatchpointCommand() override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectWatchpointCommand_h_
+#endif // liblldb_CommandObjectWatchpointCommand_h_
diff --git a/contrib/llvm/tools/lldb/source/Core/Address.cpp b/contrib/llvm/tools/lldb/source/Core/Address.cpp
index 1cd7a74..83100de 100644
--- a/contrib/llvm/tools/lldb/source/Core/Address.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Address.cpp
@@ -179,7 +179,7 @@ ReadCStringFromMemory (ExecutionContextScope *exe_scope, const Address &address,
buf[k_buf_len] = '\0'; // NULL terminate
// Byte order and address size don't matter for C string dumping..
- DataExtractor data (buf, sizeof(buf), lldb::endian::InlHostByteOrder(), 4);
+ DataExtractor data (buf, sizeof(buf), endian::InlHostByteOrder(), 4);
size_t total_len = 0;
size_t bytes_read;
Address curr_address(address);
@@ -367,21 +367,29 @@ Address::SetCallableLoadAddress (lldb::addr_t load_addr, Target *target)
}
addr_t
-Address::GetOpcodeLoadAddress (Target *target) const
+Address::GetOpcodeLoadAddress (Target *target, AddressClass addr_class) const
{
addr_t code_addr = GetLoadAddress (target);
if (code_addr != LLDB_INVALID_ADDRESS)
- code_addr = target->GetOpcodeLoadAddress (code_addr, GetAddressClass());
+ {
+ if (addr_class == eAddressClassInvalid)
+ addr_class = GetAddressClass();
+ code_addr = target->GetOpcodeLoadAddress (code_addr, addr_class);
+ }
return code_addr;
}
bool
-Address::SetOpcodeLoadAddress (lldb::addr_t load_addr, Target *target)
+Address::SetOpcodeLoadAddress (lldb::addr_t load_addr, Target *target, AddressClass addr_class)
{
if (SetLoadAddress (load_addr, target))
{
if (target)
- m_offset = target->GetOpcodeLoadAddress (m_offset, GetAddressClass());
+ {
+ if (addr_class == eAddressClassInvalid)
+ addr_class = GetAddressClass();
+ m_offset = target->GetOpcodeLoadAddress (m_offset, addr_class);
+ }
return true;
}
return false;
@@ -455,6 +463,20 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
case DumpStyleLoadAddress:
{
addr_t load_addr = GetLoadAddress (target);
+
+ /*
+ * MIPS:
+ * Display address in compressed form for MIPS16 or microMIPS
+ * if the address belongs to eAddressClassCodeAlternateISA.
+ */
+ if (target)
+ {
+ const llvm::Triple::ArchType llvm_arch = target->GetArchitecture().GetMachine();
+ if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel
+ || llvm_arch == llvm::Triple::mips64 || llvm_arch == llvm::Triple::mips64el)
+ load_addr = GetCallableLoadAddress (target);
+ }
+
if (load_addr == LLDB_INVALID_ADDRESS)
{
if (fallback_style != DumpStyleInvalid)
diff --git a/contrib/llvm/tools/lldb/source/Core/AddressResolverName.cpp b/contrib/llvm/tools/lldb/source/Core/AddressResolverName.cpp
index 1c6205f..293002a 100644
--- a/contrib/llvm/tools/lldb/source/Core/AddressResolverName.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/AddressResolverName.cpp
@@ -13,7 +13,6 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Symbol.h"
diff --git a/contrib/llvm/tools/lldb/source/Core/ArchSpec.cpp b/contrib/llvm/tools/lldb/source/Core/ArchSpec.cpp
index 2dc001a..ffe717f 100644
--- a/contrib/llvm/tools/lldb/source/Core/ArchSpec.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ArchSpec.cpp
@@ -419,8 +419,8 @@ ArchSpec::ArchSpec() :
m_triple (),
m_core (kCore_invalid),
m_byte_order (eByteOrderInvalid),
- m_distribution_id (),
- m_flags (0)
+ m_flags (0),
+ m_distribution_id ()
{
}
@@ -428,8 +428,8 @@ ArchSpec::ArchSpec (const char *triple_cstr, Platform *platform) :
m_triple (),
m_core (kCore_invalid),
m_byte_order (eByteOrderInvalid),
- m_distribution_id (),
- m_flags (0)
+ m_flags (0),
+ m_distribution_id ()
{
if (triple_cstr)
SetTriple(triple_cstr, platform);
@@ -440,8 +440,8 @@ ArchSpec::ArchSpec (const char *triple_cstr) :
m_triple (),
m_core (kCore_invalid),
m_byte_order (eByteOrderInvalid),
- m_distribution_id (),
- m_flags (0)
+ m_flags (0),
+ m_distribution_id ()
{
if (triple_cstr)
SetTriple(triple_cstr);
@@ -451,8 +451,8 @@ ArchSpec::ArchSpec(const llvm::Triple &triple) :
m_triple (),
m_core (kCore_invalid),
m_byte_order (eByteOrderInvalid),
- m_distribution_id (),
- m_flags (0)
+ m_flags (0),
+ m_distribution_id ()
{
SetTriple(triple);
}
@@ -461,8 +461,8 @@ ArchSpec::ArchSpec (ArchitectureType arch_type, uint32_t cpu, uint32_t subtype)
m_triple (),
m_core (kCore_invalid),
m_byte_order (eByteOrderInvalid),
- m_distribution_id (),
- m_flags (0)
+ m_flags (0),
+ m_distribution_id ()
{
SetArchitecture (arch_type, cpu, subtype);
}
@@ -602,7 +602,15 @@ ArchSpec::GetAddressByteSize() const
{
const CoreDefinition *core_def = FindCoreDefinition (m_core);
if (core_def)
- return core_def->addr_byte_size;
+ {
+ if (core_def->machine == llvm::Triple::mips64 || core_def->machine == llvm::Triple::mips64el)
+ {
+ // For N32/O32 applications Address size is 4 bytes.
+ if (m_flags & (eMIPSABI_N32 | eMIPSABI_O32))
+ return 4;
+ }
+ return core_def->addr_byte_size;
+ }
return 0;
}
@@ -836,14 +844,17 @@ ArchSpec::SetTriple (const char *triple_cstr, Platform *platform)
void
ArchSpec::MergeFrom(const ArchSpec &other)
{
- if (GetTriple().getVendor() == llvm::Triple::UnknownVendor && !TripleVendorWasSpecified())
+ if (TripleVendorIsUnspecifiedUnknown() && !other.TripleVendorIsUnspecifiedUnknown())
GetTriple().setVendor(other.GetTriple().getVendor());
- if (GetTriple().getOS() == llvm::Triple::UnknownOS && !TripleOSWasSpecified())
+ if (TripleOSIsUnspecifiedUnknown() && !other.TripleOSIsUnspecifiedUnknown())
GetTriple().setOS(other.GetTriple().getOS());
if (GetTriple().getArch() == llvm::Triple::UnknownArch)
GetTriple().setArch(other.GetTriple().getArch());
- if (GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment)
- GetTriple().setEnvironment(other.GetTriple().getEnvironment());
+ if (GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && !TripleVendorWasSpecified())
+ {
+ if (other.TripleVendorWasSpecified())
+ GetTriple().setEnvironment(other.GetTriple().getEnvironment());
+ }
}
bool
@@ -868,29 +879,14 @@ ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t su
if (arch_type == eArchTypeMachO)
{
m_triple.setVendor (llvm::Triple::Apple);
- switch (core_def->machine)
- {
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- m_triple.setOS (llvm::Triple::IOS);
- break;
-
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- // Don't set the OS for x86_64 or for x86 as we want to leave it as an "unspecified unknown"
- // which means if we ask for the OS from the llvm::Triple we get back llvm::Triple::UnknownOS, but
- // if we ask for the string value for the OS it will come back empty (unspecified).
- // We do this because we now have iOS and MacOSX as the OS values for x86 and x86_64 for
- // normal desktop and simulator binaries. And if we compare a "x86_64-apple-ios" to a "x86_64-apple-"
- // triple, it will say it is compatible (because the OS is unspecified in the second one and will match
- // anything in the first
- break;
-
- default:
- m_triple.setOS (llvm::Triple::MacOSX);
- break;
- }
+
+ // Don't set the OS. It could be simulator, macosx, ios, watchos, tvos. We could
+ // get close with the cpu type - but we can't get it right all of the time. Better
+ // to leave this unset so other sections of code will set it when they have more
+ // information.
+ // NB: don't call m_triple.setOS (llvm::Triple::UnknownOS). That sets the OSName to
+ // "unknown" and the ArchSpec::TripleVendorWasSpecified() method says that any
+ // OSName setting means it was specified.
}
else if (arch_type == eArchTypeELF)
{
@@ -904,6 +900,11 @@ ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t su
case llvm::ELF::ELFOSABI_SOLARIS: m_triple.setOS (llvm::Triple::OSType::Solaris); break;
}
}
+ else
+ {
+ m_triple.setVendor (llvm::Triple::UnknownVendor);
+ m_triple.setOS (llvm::Triple::UnknownOS);
+ }
// Fall back onto setting the machine type if the arch by name failed...
if (m_triple.getArch () == llvm::Triple::UnknownArch)
m_triple.setArch (core_def->machine);
@@ -966,15 +967,12 @@ ArchSpec::IsEqualTo (const ArchSpec& rhs, bool exact_match) const
const llvm::Triple::VendorType rhs_triple_vendor = rhs_triple.getVendor();
if (lhs_triple_vendor != rhs_triple_vendor)
{
- if (exact_match)
- {
- const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified();
- const bool lhs_vendor_specified = TripleVendorWasSpecified();
- // Both architectures had the vendor specified, so if they aren't
- // equal then we return false
- if (rhs_vendor_specified && lhs_vendor_specified)
- return false;
- }
+ const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified();
+ const bool lhs_vendor_specified = TripleVendorWasSpecified();
+ // Both architectures had the vendor specified, so if they aren't
+ // equal then we return false
+ if (rhs_vendor_specified && lhs_vendor_specified)
+ return false;
// Only fail if both vendor types are not unknown
if (lhs_triple_vendor != llvm::Triple::UnknownVendor &&
@@ -986,15 +984,12 @@ ArchSpec::IsEqualTo (const ArchSpec& rhs, bool exact_match) const
const llvm::Triple::OSType rhs_triple_os = rhs_triple.getOS();
if (lhs_triple_os != rhs_triple_os)
{
- if (exact_match)
- {
- const bool rhs_os_specified = rhs.TripleOSWasSpecified();
- const bool lhs_os_specified = TripleOSWasSpecified();
- // Both architectures had the OS specified, so if they aren't
- // equal then we return false
- if (rhs_os_specified && lhs_os_specified)
- return false;
- }
+ const bool rhs_os_specified = rhs.TripleOSWasSpecified();
+ const bool lhs_os_specified = TripleOSWasSpecified();
+ // Both architectures had the OS specified, so if they aren't
+ // equal then we return false
+ if (rhs_os_specified && lhs_os_specified)
+ return false;
// Only fail if both os types are not unknown
if (lhs_triple_os != llvm::Triple::UnknownOS &&
@@ -1103,6 +1098,10 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
return true;
break;
+ // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
+ // Cortex-M0 - ARMv6-M - armv6m
+ // Cortex-M3 - ARMv7-M - armv7m
+ // Cortex-M4 - ARMv7E-M - armv7em
case ArchSpec::eCore_arm_armv7em:
if (!enforce_exact_match)
{
@@ -1118,6 +1117,10 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
}
break;
+ // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
+ // Cortex-M0 - ARMv6-M - armv6m
+ // Cortex-M3 - ARMv7-M - armv7m
+ // Cortex-M4 - ARMv7E-M - armv7em
case ArchSpec::eCore_arm_armv7m:
if (!enforce_exact_match)
{
@@ -1428,3 +1431,62 @@ ArchSpec::GetStopInfoOverrideCallback () const
return StopInfoOverrideCallbackTypeARM;
return NULL;
}
+
+bool
+ArchSpec::IsFullySpecifiedTriple () const
+{
+ const auto& user_specified_triple = GetTriple();
+
+ bool user_triple_fully_specified = false;
+
+ if ((user_specified_triple.getOS() != llvm::Triple::UnknownOS) || TripleOSWasSpecified())
+ {
+ if ((user_specified_triple.getVendor() != llvm::Triple::UnknownVendor) || TripleVendorWasSpecified())
+ {
+ const unsigned unspecified = 0;
+ if (user_specified_triple.getOSMajorVersion() != unspecified)
+ {
+ user_triple_fully_specified = true;
+ }
+ }
+ }
+
+ return user_triple_fully_specified;
+}
+
+void
+ArchSpec::PiecewiseTripleCompare (const ArchSpec &other,
+ bool &arch_different,
+ bool &vendor_different,
+ bool &os_different,
+ bool &os_version_different,
+ bool &env_different)
+{
+ const llvm::Triple &me(GetTriple());
+ const llvm::Triple &them(other.GetTriple());
+
+ arch_different = (me.getArch() != them.getArch());
+
+ vendor_different = (me.getVendor() != them.getVendor());
+
+ os_different = (me.getOS() != them.getOS());
+
+ os_version_different = (me.getOSMajorVersion() != them.getOSMajorVersion());
+
+ env_different = (me.getEnvironment() != them.getEnvironment());
+}
+
+void
+ArchSpec::DumpTriple(Stream &s) const
+{
+ const llvm::Triple &triple = GetTriple();
+ llvm::StringRef arch_str = triple.getArchName();
+ llvm::StringRef vendor_str = triple.getVendorName();
+ llvm::StringRef os_str = triple.getOSName();
+
+ s.Printf("%s-%s-%s",
+ arch_str.empty() ? "*" : arch_str.str().c_str(),
+ vendor_str.empty() ? "*" : vendor_str.str().c_str(),
+ os_str.empty() ? "*" : os_str.str().c_str()
+ );
+}
diff --git a/contrib/llvm/tools/lldb/source/Core/ConnectionSharedMemory.cpp b/contrib/llvm/tools/lldb/source/Core/ConnectionSharedMemory.cpp
index 77daeb1..e417347 100644
--- a/contrib/llvm/tools/lldb/source/Core/ConnectionSharedMemory.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ConnectionSharedMemory.cpp
@@ -16,10 +16,10 @@
#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
#else
-#include <sys/file.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <fcntl.h>
#endif
// C++ Includes
diff --git a/contrib/llvm/tools/lldb/source/Core/ConstString.cpp b/contrib/llvm/tools/lldb/source/Core/ConstString.cpp
index 85f8d3c..c2e95d8 100644
--- a/contrib/llvm/tools/lldb/source/Core/ConstString.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ConstString.cpp
@@ -8,39 +8,21 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Stream.h"
-#include "lldb/Host/Mutex.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/RWMutex.h"
-#include <mutex> // std::once
+#include <array>
+#include <mutex>
using namespace lldb_private;
-
class Pool
{
public:
typedef const char * StringPoolValueType;
typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool;
typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType;
-
- //------------------------------------------------------------------
- // Default constructor
- //
- // Initialize the member variables and create the empty string.
- //------------------------------------------------------------------
- Pool () :
- m_mutex (Mutex::eMutexTypeRecursive),
- m_string_map ()
- {
- }
-
- //------------------------------------------------------------------
- // Destructor
- //------------------------------------------------------------------
- ~Pool ()
- {
- }
-
static StringPoolEntryType &
GetStringMapEntryFromKeyData (const char *keyData)
@@ -54,7 +36,9 @@ public:
{
if (ccstr)
{
- const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr);
+ const uint8_t h = hash (llvm::StringRef(ccstr));
+ llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex);
+ const StringPoolEntryType& entry = GetStringMapEntryFromKeyData (ccstr);
return entry.getKey().size();
}
return 0;
@@ -64,7 +48,11 @@ public:
GetMangledCounterpart (const char *ccstr) const
{
if (ccstr)
+ {
+ const uint8_t h = hash (llvm::StringRef(ccstr));
+ llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex);
return GetStringMapEntryFromKeyData (ccstr).getValue();
+ }
return 0;
}
@@ -73,8 +61,16 @@ public:
{
if (key_ccstr && value_ccstr)
{
- GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr);
- GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr);
+ {
+ const uint8_t h = hash (llvm::StringRef(key_ccstr));
+ llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
+ GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr);
+ }
+ {
+ const uint8_t h = hash (llvm::StringRef(value_ccstr));
+ llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
+ GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr);
+ }
return true;
}
return false;
@@ -85,20 +81,15 @@ public:
{
if (cstr)
return GetConstCStringWithLength (cstr, strlen (cstr));
- return NULL;
+ return nullptr;
}
const char *
GetConstCStringWithLength (const char *cstr, size_t cstr_len)
{
if (cstr)
- {
- Mutex::Locker locker (m_mutex);
- llvm::StringRef string_ref (cstr, cstr_len);
- StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
- return entry.getKeyData();
- }
- return NULL;
+ return GetConstCStringWithStringRef(llvm::StringRef(cstr, cstr_len));
+ return nullptr;
}
const char *
@@ -106,11 +97,20 @@ public:
{
if (string_ref.data())
{
- Mutex::Locker locker (m_mutex);
- StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first;
+ const uint8_t h = hash (string_ref);
+
+ {
+ llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex);
+ auto it = m_string_pools[h].m_string_map.find (string_ref);
+ if (it != m_string_pools[h].m_string_map.end())
+ return it->getKeyData();
+ }
+
+ llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
+ StringPoolEntryType& entry = *m_string_pools[h].m_string_map.insert (std::make_pair (string_ref, nullptr)).first;
return entry.getKeyData();
}
- return NULL;
+ return nullptr;
}
const char *
@@ -118,19 +118,33 @@ public:
{
if (demangled_cstr)
{
- Mutex::Locker locker (m_mutex);
- // Make string pool entry with the mangled counterpart already set
- StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (llvm::StringRef (demangled_cstr), mangled_ccstr)).first;
-
- // Extract the const version of the demangled_cstr
- const char *demangled_ccstr = entry.getKeyData();
- // Now assign the demangled const string as the counterpart of the
- // mangled const string...
- GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr);
+ const char *demangled_ccstr = nullptr;
+
+ {
+ llvm::StringRef string_ref (demangled_cstr);
+ const uint8_t h = hash (string_ref);
+ llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
+
+ // Make string pool entry with the mangled counterpart already set
+ StringPoolEntryType& entry = *m_string_pools[h].m_string_map.insert (
+ std::make_pair (string_ref, mangled_ccstr)).first;
+
+ // Extract the const version of the demangled_cstr
+ demangled_ccstr = entry.getKeyData();
+ }
+
+ {
+ // Now assign the demangled const string as the counterpart of the
+ // mangled const string...
+ const uint8_t h = hash (llvm::StringRef(mangled_ccstr));
+ llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
+ GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr);
+ }
+
// Return the constant demangled C string
return demangled_ccstr;
}
- return NULL;
+ return nullptr;
}
const char *
@@ -141,7 +155,7 @@ public:
const size_t trimmed_len = std::min<size_t> (strlen (cstr), cstr_len);
return GetConstCStringWithLength (cstr, trimmed_len);
}
- return NULL;
+ return nullptr;
}
//------------------------------------------------------------------
@@ -152,28 +166,31 @@ public:
size_t
MemorySize() const
{
- Mutex::Locker locker (m_mutex);
size_t mem_size = sizeof(Pool);
- const_iterator end = m_string_map.end();
- for (const_iterator pos = m_string_map.begin(); pos != end; ++pos)
+ for (const auto& pool : m_string_pools)
{
- mem_size += sizeof(StringPoolEntryType) + pos->getKey().size();
+ llvm::sys::SmartScopedReader<false> rlock(pool.m_mutex);
+ for (const auto& entry : pool.m_string_map)
+ mem_size += sizeof(StringPoolEntryType) + entry.getKey().size();
}
return mem_size;
}
protected:
- //------------------------------------------------------------------
- // Typedefs
- //------------------------------------------------------------------
- typedef StringPool::iterator iterator;
- typedef StringPool::const_iterator const_iterator;
+ uint8_t
+ hash(const llvm::StringRef &s) const
+ {
+ uint32_t h = llvm::HashString(s);
+ return ((h >> 24) ^ (h >> 16) ^ (h >> 8) ^ h) & 0xff;
+ }
- //------------------------------------------------------------------
- // Member variables
- //------------------------------------------------------------------
- mutable Mutex m_mutex;
- StringPool m_string_map;
+ struct PoolEntry
+ {
+ mutable llvm::sys::SmartRWMutex<false> m_mutex;
+ StringPool m_string_map;
+ };
+
+ std::array<PoolEntry, 256> m_string_pools;
};
//----------------------------------------------------------------------
@@ -191,7 +208,7 @@ static Pool &
StringPool()
{
static std::once_flag g_pool_initialization_flag;
- static Pool *g_string_pool = NULL;
+ static Pool *g_string_pool = nullptr;
std::call_once(g_pool_initialization_flag, [] () {
g_string_pool = new Pool();
@@ -228,8 +245,8 @@ ConstString::operator < (const ConstString& rhs) const
if (lhs_string_ref.data() && rhs_string_ref.data())
return lhs_string_ref < rhs_string_ref;
- // Else one of them was NULL, so if LHS is NULL then it is less than
- return lhs_string_ref.data() == NULL;
+ // Else one of them was nullptr, so if LHS is nullptr then it is less than
+ return lhs_string_ref.data() == nullptr;
}
Stream&
diff --git a/contrib/llvm/tools/lldb/source/Core/CxaDemangle.cpp b/contrib/llvm/tools/lldb/source/Core/CxaDemangle.cpp
index bcc52ff..7d21138 100644
--- a/contrib/llvm/tools/lldb/source/Core/CxaDemangle.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/CxaDemangle.cpp
@@ -13,6 +13,7 @@
// - Included win32.h for snprintf implementation for MSVC
// - Removed constexpr member initialization for MSVC
// - Changed argument to alignas() to a literal for MSVC
+// - Include <cstdio> for fprintf, stderr like entities.
//----------------------------------------------------------------------
#if defined(_MSC_VER)
@@ -40,6 +41,7 @@
#include <cstdlib>
#include <cstring>
#include <cctype>
+#include <cstdio>
namespace lldb_private
{
diff --git a/contrib/llvm/tools/lldb/source/Core/DataEncoder.cpp b/contrib/llvm/tools/lldb/source/Core/DataEncoder.cpp
index d21ca42..040d096 100644
--- a/contrib/llvm/tools/lldb/source/Core/DataEncoder.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/DataEncoder.cpp
@@ -61,7 +61,7 @@ WriteSwappedInt64(unsigned char* ptr, unsigned offset, uint64_t value)
DataEncoder::DataEncoder () :
m_start (NULL),
m_end (NULL),
- m_byte_order(lldb::endian::InlHostByteOrder()),
+ m_byte_order(endian::InlHostByteOrder()),
m_addr_size (sizeof(void*)),
m_data_sp ()
{
@@ -114,7 +114,7 @@ DataEncoder::Clear ()
{
m_start = NULL;
m_end = NULL;
- m_byte_order = lldb::endian::InlHostByteOrder();
+ m_byte_order = endian::InlHostByteOrder();
m_addr_size = sizeof(void*);
m_data_sp.reset();
}
@@ -240,7 +240,7 @@ DataEncoder::PutU16 (uint32_t offset, uint16_t value)
{
if (ValidOffsetForDataOfSize(offset, sizeof(value)))
{
- if (m_byte_order != lldb::endian::InlHostByteOrder())
+ if (m_byte_order != endian::InlHostByteOrder())
WriteSwappedInt16 (m_start, offset, value);
else
WriteInt16 (m_start, offset, value);
@@ -255,7 +255,7 @@ DataEncoder::PutU32 (uint32_t offset, uint32_t value)
{
if (ValidOffsetForDataOfSize(offset, sizeof(value)))
{
- if (m_byte_order != lldb::endian::InlHostByteOrder())
+ if (m_byte_order != endian::InlHostByteOrder())
WriteSwappedInt32 (m_start, offset, value);
else
WriteInt32 (m_start, offset, value);
@@ -270,7 +270,7 @@ DataEncoder::PutU64 (uint32_t offset, uint64_t value)
{
if (ValidOffsetForDataOfSize(offset, sizeof(value)))
{
- if (m_byte_order != lldb::endian::InlHostByteOrder())
+ if (m_byte_order != endian::InlHostByteOrder())
WriteSwappedInt64 (m_start, offset, value);
else
WriteInt64 (m_start, offset, value);
diff --git a/contrib/llvm/tools/lldb/source/Core/DataExtractor.cpp b/contrib/llvm/tools/lldb/source/Core/DataExtractor.cpp
index 861bece..dc7857f 100644
--- a/contrib/llvm/tools/lldb/source/Core/DataExtractor.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/DataExtractor.cpp
@@ -14,6 +14,7 @@
#include <limits>
#include <sstream>
#include <string>
+#include <math.h>
#include "clang/AST/ASTContext.h"
@@ -130,8 +131,8 @@ ReadSwapInt64(const void* ptr)
DataExtractor::DataExtractor () :
m_start (NULL),
m_end (NULL),
- m_byte_order(lldb::endian::InlHostByteOrder()),
- m_addr_size (4),
+ m_byte_order(endian::InlHostByteOrder()),
+ m_addr_size (sizeof(void *)),
m_data_sp (),
m_target_byte_size(1)
{
@@ -142,13 +143,16 @@ DataExtractor::DataExtractor () :
// The data must stay around as long as this object is valid.
//----------------------------------------------------------------------
DataExtractor::DataExtractor (const void* data, offset_t length, ByteOrder endian, uint32_t addr_size, uint32_t target_byte_size/*=1*/) :
- m_start ((uint8_t*)data),
- m_end ((uint8_t*)data + length),
+ m_start (const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data))),
+ m_end (const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data)) + length),
m_byte_order(endian),
m_addr_size (addr_size),
m_data_sp (),
m_target_byte_size(target_byte_size)
{
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert (addr_size == 4 || addr_size == 8);
+#endif
}
//----------------------------------------------------------------------
@@ -166,6 +170,9 @@ DataExtractor::DataExtractor (const DataBufferSP& data_sp, ByteOrder endian, uin
m_data_sp (),
m_target_byte_size(target_byte_size)
{
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert (addr_size == 4 || addr_size == 8);
+#endif
SetData (data_sp);
}
@@ -184,6 +191,9 @@ DataExtractor::DataExtractor (const DataExtractor& data, offset_t offset, offset
m_data_sp(),
m_target_byte_size(target_byte_size)
{
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert (m_addr_size == 4 || m_addr_size == 8);
+#endif
if (data.ValidOffset(offset))
{
offset_t bytes_available = data.GetByteSize() - offset;
@@ -201,6 +211,9 @@ DataExtractor::DataExtractor (const DataExtractor& rhs) :
m_data_sp (rhs.m_data_sp),
m_target_byte_size(rhs.m_target_byte_size)
{
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert (m_addr_size == 4 || m_addr_size == 8);
+#endif
}
//----------------------------------------------------------------------
@@ -237,8 +250,8 @@ DataExtractor::Clear ()
{
m_start = NULL;
m_end = NULL;
- m_byte_order = lldb::endian::InlHostByteOrder();
- m_addr_size = 4;
+ m_byte_order = endian::InlHostByteOrder();
+ m_addr_size = sizeof(void *);
m_data_sp.reset();
}
@@ -287,7 +300,7 @@ DataExtractor::SetData (const void *bytes, offset_t length, ByteOrder endian)
}
else
{
- m_start = (uint8_t *)bytes;
+ m_start = const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(bytes));
m_end = m_start + length;
}
return GetByteSize();
@@ -311,6 +324,9 @@ lldb::offset_t
DataExtractor::SetData (const DataExtractor& data, offset_t data_offset, offset_t data_length)
{
m_addr_size = data.m_addr_size;
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert (m_addr_size == 4 || m_addr_size == 8);
+#endif
// If "data" contains shared pointer to data, then we can use that
if (data.m_data_sp.get())
{
@@ -427,7 +443,7 @@ DataExtractor::GetU16 (offset_t *offset_ptr) const
const uint8_t *data = (const uint8_t *)GetData (offset_ptr, sizeof(val));
if (data)
{
- if (m_byte_order != lldb::endian::InlHostByteOrder())
+ if (m_byte_order != endian::InlHostByteOrder())
val = ReadSwapInt16(data);
else
val = ReadInt16 (data);
@@ -439,7 +455,7 @@ uint16_t
DataExtractor::GetU16_unchecked (offset_t *offset_ptr) const
{
uint16_t val;
- if (m_byte_order == lldb::endian::InlHostByteOrder())
+ if (m_byte_order == endian::InlHostByteOrder())
val = ReadInt16 (m_start, *offset_ptr);
else
val = ReadSwapInt16(m_start, *offset_ptr);
@@ -451,7 +467,7 @@ uint32_t
DataExtractor::GetU32_unchecked (offset_t *offset_ptr) const
{
uint32_t val;
- if (m_byte_order == lldb::endian::InlHostByteOrder())
+ if (m_byte_order == endian::InlHostByteOrder())
val = ReadInt32 (m_start, *offset_ptr);
else
val = ReadSwapInt32 (m_start, *offset_ptr);
@@ -463,7 +479,7 @@ uint64_t
DataExtractor::GetU64_unchecked (offset_t *offset_ptr) const
{
uint64_t val;
- if (m_byte_order == lldb::endian::InlHostByteOrder())
+ if (m_byte_order == endian::InlHostByteOrder())
val = ReadInt64 (m_start, *offset_ptr);
else
val = ReadSwapInt64 (m_start, *offset_ptr);
@@ -488,7 +504,7 @@ DataExtractor::GetU16 (offset_t *offset_ptr, void *void_dst, uint32_t count) con
const uint16_t *src = (const uint16_t *)GetData (offset_ptr, src_size);
if (src)
{
- if (m_byte_order != lldb::endian::InlHostByteOrder())
+ if (m_byte_order != endian::InlHostByteOrder())
{
uint16_t *dst_pos = (uint16_t *)void_dst;
uint16_t *dst_end = dst_pos + count;
@@ -523,7 +539,7 @@ DataExtractor::GetU32 (offset_t *offset_ptr) const
const uint8_t *data = (const uint8_t *)GetData (offset_ptr, sizeof(val));
if (data)
{
- if (m_byte_order != lldb::endian::InlHostByteOrder())
+ if (m_byte_order != endian::InlHostByteOrder())
{
val = ReadSwapInt32 (data);
}
@@ -551,7 +567,7 @@ DataExtractor::GetU32 (offset_t *offset_ptr, void *void_dst, uint32_t count) con
const uint32_t *src = (const uint32_t *)GetData (offset_ptr, src_size);
if (src)
{
- if (m_byte_order != lldb::endian::InlHostByteOrder())
+ if (m_byte_order != endian::InlHostByteOrder())
{
uint32_t *dst_pos = (uint32_t *)void_dst;
uint32_t *dst_end = dst_pos + count;
@@ -586,7 +602,7 @@ DataExtractor::GetU64 (offset_t *offset_ptr) const
const uint8_t *data = (const uint8_t *)GetData (offset_ptr, sizeof(val));
if (data)
{
- if (m_byte_order != lldb::endian::InlHostByteOrder())
+ if (m_byte_order != endian::InlHostByteOrder())
{
val = ReadSwapInt64 (data);
}
@@ -612,7 +628,7 @@ DataExtractor::GetU64 (offset_t *offset_ptr, void *void_dst, uint32_t count) con
const uint64_t *src = (const uint64_t *)GetData (offset_ptr, src_size);
if (src)
{
- if (m_byte_order != lldb::endian::InlHostByteOrder())
+ if (m_byte_order != endian::InlHostByteOrder())
{
uint64_t *dst_pos = (uint64_t *)void_dst;
uint64_t *dst_end = dst_pos + count;
@@ -653,7 +669,7 @@ DataExtractor::GetMaxU32 (offset_t *offset_ptr, size_t byte_size) const
case 2: return GetU16(offset_ptr); break;
case 4: return GetU32(offset_ptr); break;
default:
- assert("GetMaxU32 unhandled case!" == NULL);
+ assert(false && "GetMaxU32 unhandled case!");
break;
}
return 0;
@@ -679,7 +695,7 @@ DataExtractor::GetMaxU64 (offset_t *offset_ptr, size_t size) const
case 4: return GetU32(offset_ptr); break;
case 8: return GetU64(offset_ptr); break;
default:
- assert("GetMax64 unhandled case!" == NULL);
+ assert(false && "GetMax64 unhandled case!");
break;
}
return 0;
@@ -695,7 +711,7 @@ DataExtractor::GetMaxU64_unchecked (offset_t *offset_ptr, size_t size) const
case 4: return GetU32_unchecked (offset_ptr); break;
case 8: return GetU64_unchecked (offset_ptr); break;
default:
- assert("GetMax64 unhandled case!" == NULL);
+ assert(false && "GetMax64 unhandled case!");
break;
}
return 0;
@@ -711,7 +727,7 @@ DataExtractor::GetMaxS64 (offset_t *offset_ptr, size_t size) const
case 4: return (int32_t)GetU32(offset_ptr); break;
case 8: return (int64_t)GetU64(offset_ptr); break;
default:
- assert("GetMax64 unhandled case!" == NULL);
+ assert(false && "GetMax64 unhandled case!");
break;
}
return 0;
@@ -760,7 +776,7 @@ DataExtractor::GetFloat (offset_t *offset_ptr) const
const float_type *src = (const float_type *)GetData (offset_ptr, src_size);
if (src)
{
- if (m_byte_order != lldb::endian::InlHostByteOrder())
+ if (m_byte_order != endian::InlHostByteOrder())
{
const uint8_t *src_data = (const uint8_t *)src;
uint8_t *dst_data = (uint8_t *)&val;
@@ -784,7 +800,7 @@ DataExtractor::GetDouble (offset_t *offset_ptr) const
const float_type *src = (const float_type *)GetData (offset_ptr, src_size);
if (src)
{
- if (m_byte_order != lldb::endian::InlHostByteOrder())
+ if (m_byte_order != endian::InlHostByteOrder())
{
const uint8_t *src_data = (const uint8_t *)src;
uint8_t *dst_data = (uint8_t *)&val;
@@ -805,9 +821,9 @@ DataExtractor::GetLongDouble (offset_t *offset_ptr) const
{
long double val = 0.0;
#if defined (__i386__) || defined (__amd64__) || defined (__x86_64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64)
- *offset_ptr += CopyByteOrderedData (*offset_ptr, 10, &val, sizeof(val), lldb::endian::InlHostByteOrder());
+ *offset_ptr += CopyByteOrderedData (*offset_ptr, 10, &val, sizeof(val), endian::InlHostByteOrder());
#else
- *offset_ptr += CopyByteOrderedData (*offset_ptr, sizeof(val), &val, sizeof(val), lldb::endian::InlHostByteOrder());
+ *offset_ptr += CopyByteOrderedData (*offset_ptr, sizeof(val), &val, sizeof(val), endian::InlHostByteOrder());
#endif
return val;
}
@@ -824,12 +840,18 @@ DataExtractor::GetLongDouble (offset_t *offset_ptr) const
uint64_t
DataExtractor::GetAddress (offset_t *offset_ptr) const
{
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert (m_addr_size == 4 || m_addr_size == 8);
+#endif
return GetMaxU64 (offset_ptr, m_addr_size);
}
uint64_t
DataExtractor::GetAddress_unchecked (offset_t *offset_ptr) const
{
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert (m_addr_size == 4 || m_addr_size == 8);
+#endif
return GetMaxU64_unchecked (offset_ptr, m_addr_size);
}
@@ -844,6 +866,9 @@ DataExtractor::GetAddress_unchecked (offset_t *offset_ptr) const
uint64_t
DataExtractor::GetPointer (offset_t *offset_ptr) const
{
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert (m_addr_size == 4 || m_addr_size == 8);
+#endif
return GetMaxU64 (offset_ptr, m_addr_size);
}
@@ -863,6 +888,9 @@ DataExtractor::GetGNUEHPointer (offset_t *offset_ptr, uint32_t eh_ptr_enc, lldb:
uint64_t baseAddress = 0;
uint64_t addressValue = 0;
const uint32_t addr_size = GetAddressByteSize();
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert (addr_size == 4 || addr_size == 8);
+#endif
bool signExtendValue = false;
// Decode the base part or adjust our offset
@@ -1378,24 +1406,21 @@ DumpAPInt (Stream *s, const DataExtractor &data, lldb::offset_t offset, lldb::of
return offset;
}
-static float half2float (uint16_t half)
+static float
+half2float (uint16_t half)
{
-#ifdef _MSC_VER
- llvm_unreachable("half2float not implemented for MSVC");
-#else
- union{ float f; uint32_t u;}u;
+ union { float f; uint32_t u; } u;
int32_t v = (int16_t) half;
-
- if( 0 == (v & 0x7c00))
+
+ if (0 == (v & 0x7c00))
{
u.u = v & 0x80007FFFU;
return u.f * ldexpf(1, 125);
}
-
+
v <<= 13;
u.u = v | 0x70000000U;
return u.f * ldexpf(1, -112);
-#endif
}
lldb::offset_t
@@ -2012,6 +2037,12 @@ DataExtractor::Dump (Stream *s,
s->PutChar('}');
break;
+ case eFormatVectorOfFloat16:
+ s->PutChar('{');
+ offset = Dump (s, offset, eFormatFloat, 2, item_byte_size / 2, item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0);
+ s->PutChar('}');
+ break;
+
case eFormatVectorOfFloat32:
s->PutChar('{');
offset = Dump (s, offset, eFormatFloat, 4, item_byte_size / 4, item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0);
diff --git a/contrib/llvm/tools/lldb/source/Core/Debugger.cpp b/contrib/llvm/tools/lldb/source/Core/Debugger.cpp
index cd41e5d..d36800e 100644
--- a/contrib/llvm/tools/lldb/source/Core/Debugger.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Debugger.cpp
@@ -11,13 +11,12 @@
#include <map>
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Type.h"
#include "llvm/ADT/StringRef.h"
#include "lldb/lldb-private.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/State.h"
@@ -32,6 +31,7 @@
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Expression/REPL.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Terminal.h"
@@ -40,14 +40,12 @@
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/OptionValueSInt64.h"
#include "lldb/Interpreter/OptionValueString.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/CPPLanguageRuntime.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/TargetList.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
@@ -88,9 +86,10 @@ GetDebuggerList()
OptionEnumValueElement
g_show_disassembly_enum_values[] =
{
- { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."},
- { Debugger::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."},
- { Debugger::eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."},
+ { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."},
+ { Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo", "Show disassembly when there is no debug information."},
+ { Debugger::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."},
+ { Debugger::eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."},
{ 0, NULL, NULL }
};
@@ -105,6 +104,7 @@ g_language_enumerators[] =
#define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}"
#define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}"
+#define IS_OPTIMIZED "{${function.is-optimized} [opt]}"
#define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id%tid}"\
"{, ${frame.pc}}"\
@@ -122,6 +122,7 @@ g_language_enumerators[] =
#define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\
MODULE_WITH_FUNC\
FILE_AND_LINE\
+ IS_OPTIMIZED\
"\\n"
// Three parts to this disassembly format specification:
@@ -150,7 +151,7 @@ g_properties[] =
{ "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." },
{ "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." },
{ "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." },
-{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." },
+{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoDebugInfo, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." },
{ "stop-line-count-after", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come after the current source line when displaying a stopped context." },
{ "stop-line-count-before", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come before the current source line when displaying a stopped context." },
{ "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." },
@@ -158,6 +159,9 @@ g_properties[] =
{ "use-external-editor", OptionValue::eTypeBoolean , true, false, NULL, NULL, "Whether to use an external editor or not." },
{ "use-color", OptionValue::eTypeBoolean , true, true , NULL, NULL, "Whether to use Ansi color codes or not." },
{ "auto-one-line-summaries", OptionValue::eTypeBoolean , true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." },
+{ "auto-indent", OptionValue::eTypeBoolean , true, true , NULL, NULL, "If true, LLDB will auto indent/outdent code. Currently only supported in the REPL (default: true)." },
+{ "print-decls", OptionValue::eTypeBoolean , true, true , NULL, NULL, "If true, LLDB will print the values of variables declared in an expression. Currently only supported in the REPL (default: true)." },
+{ "tab-size", OptionValue::eTypeUInt64 , true, 4 , NULL, NULL, "The tab size to use when indenting code in multi-line input mode (default: 4)." },
{ "escape-non-printables", OptionValue::eTypeBoolean , true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." },
{ NULL, OptionValue::eTypeInvalid , true, 0 , NULL, NULL, NULL }
};
@@ -179,6 +183,9 @@ enum
ePropertyUseExternalEditor,
ePropertyUseColor,
ePropertyAutoOneLineSummaries,
+ ePropertyAutoIndent,
+ ePropertyPrintDecls,
+ ePropertyTabSize,
ePropertyEscapeNonPrintables
};
@@ -394,6 +401,49 @@ Debugger::GetEscapeNonPrintables () const
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);
}
+bool
+Debugger::GetAutoIndent () const
+{
+ const uint32_t idx = ePropertyAutoIndent;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);
+}
+
+bool
+Debugger::SetAutoIndent (bool b)
+{
+ const uint32_t idx = ePropertyAutoIndent;
+ return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
+}
+
+bool
+Debugger::GetPrintDecls () const
+{
+ const uint32_t idx = ePropertyPrintDecls;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);
+}
+
+bool
+Debugger::SetPrintDecls (bool b)
+{
+ const uint32_t idx = ePropertyPrintDecls;
+ return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
+}
+
+uint32_t
+Debugger::GetTabSize () const
+{
+ const uint32_t idx = ePropertyTabSize;
+ return m_collection_sp->GetPropertyAtIndexAsUInt64 (NULL, idx, g_properties[idx].default_uint_value);
+}
+
+bool
+Debugger::SetTabSize (uint32_t tab_size)
+{
+ const uint32_t idx = ePropertyTabSize;
+ return m_collection_sp->SetPropertyAtIndexAsUInt64 (NULL, idx, tab_size);
+}
+
+
#pragma mark Debugger
//const DebuggerPropertiesSP &
@@ -420,7 +470,11 @@ Debugger::Terminate ()
// Clear our master list of debugger objects
Mutex::Locker locker (GetDebuggerListMutex ());
- GetDebuggerList().clear();
+ auto& debuggers = GetDebuggerList();
+ for (const auto& debugger: debuggers)
+ debugger->Clear();
+
+ debuggers.clear();
}
void
@@ -917,6 +971,12 @@ Debugger::IsTopIOHandler (const lldb::IOHandlerSP& reader_sp)
return m_input_reader_stack.IsTop (reader_sp);
}
+bool
+Debugger::CheckTopIOHandlerTypes (IOHandler::Type top_type, IOHandler::Type second_top_type)
+{
+ return m_input_reader_stack.CheckTopIOHandlerTypes (top_type, second_top_type);
+}
+
void
Debugger::PrintAsync (const char *s, size_t len, bool is_stdout)
{
@@ -1682,6 +1742,12 @@ Debugger::IOHandlerThread (lldb::thread_arg_t arg)
}
bool
+Debugger::HasIOHandlerThread()
+{
+ return m_io_handler_thread.IsJoinable();
+}
+
+bool
Debugger::StartIOHandlerThread()
{
if (!m_io_handler_thread.IsJoinable())
@@ -1704,6 +1770,17 @@ Debugger::StopIOHandlerThread()
}
}
+void
+Debugger::JoinIOHandlerThread()
+{
+ if (HasIOHandlerThread())
+ {
+ thread_result_t result;
+ m_io_handler_thread.Join(&result);
+ m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
+ }
+}
+
Target *
Debugger::GetDummyTarget()
{
@@ -1724,3 +1801,52 @@ Debugger::GetSelectedOrDummyTarget(bool prefer_dummy)
return GetDummyTarget();
}
+Error
+Debugger::RunREPL (LanguageType language, const char *repl_options)
+{
+ Error err;
+ FileSpec repl_executable;
+
+ if (language == eLanguageTypeUnknown)
+ {
+ std::set<LanguageType> repl_languages;
+
+ Language::GetLanguagesSupportingREPLs(repl_languages);
+
+ if (repl_languages.size() == 1)
+ {
+ language = *repl_languages.begin();
+ }
+ else if (repl_languages.size() == 0)
+ {
+ err.SetErrorStringWithFormat("LLDB isn't configured with support support for any REPLs.");
+ return err;
+ }
+ else
+ {
+ err.SetErrorStringWithFormat("Multiple possible REPL languages. Please specify a language.");
+ return err;
+ }
+ }
+
+ Target *const target = nullptr; // passing in an empty target means the REPL must create one
+
+ REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));
+
+ if (!err.Success())
+ {
+ return err;
+ }
+
+ if (!repl_sp)
+ {
+ err.SetErrorStringWithFormat("couldn't find a REPL for %s", Language::GetNameForLanguageType(language));
+ return err;
+ }
+
+ repl_sp->SetCompilerOptions(repl_options);
+ repl_sp->RunLoop();
+
+ return err;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Core/Disassembler.cpp b/contrib/llvm/tools/lldb/source/Core/Disassembler.cpp
index f96232f..bb5f106 100644
--- a/contrib/llvm/tools/lldb/source/Core/Disassembler.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Disassembler.cpp
@@ -28,7 +28,6 @@
#include "lldb/Interpreter/OptionValueDictionary.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ExecutionContext.h"
@@ -675,6 +674,13 @@ Instruction::DumpEmulation (const ArchSpec &arch)
return false;
}
+bool
+Instruction::HasDelaySlot ()
+{
+ // Default is false.
+ return false;
+}
+
OptionValueSP
Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type)
{
@@ -1264,7 +1270,7 @@ Disassembler::Disassembler(const ArchSpec& arch, const char *flavor) :
// If this is an arm variant that can only include thumb (T16, T32)
// instructions, force the arch triple to be "thumbv.." instead of
// "armv..."
- if (arch.GetTriple().getArch() == llvm::Triple::arm
+ if ((arch.GetTriple().getArch() == llvm::Triple::arm || arch.GetTriple().getArch() == llvm::Triple::thumb)
&& (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m
|| arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em
|| arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m))
@@ -1319,6 +1325,13 @@ PseudoInstruction::DoesBranch ()
return false;
}
+bool
+PseudoInstruction::HasDelaySlot ()
+{
+ // This is NOT a valid question for a pseudo instruction.
+ return false;
+}
+
size_t
PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler,
const lldb_private::DataExtractor &data,
diff --git a/contrib/llvm/tools/lldb/source/Core/DynamicLoader.cpp b/contrib/llvm/tools/lldb/source/Core/DynamicLoader.cpp
index ffd7425..4d2824c 100644
--- a/contrib/llvm/tools/lldb/source/Core/DynamicLoader.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/DynamicLoader.cpp
@@ -119,16 +119,20 @@ DynamicLoader::GetTargetExecutable()
}
void
-DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
+DynamicLoader::UpdateLoadedSections(ModuleSP module,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
- UpdateLoadedSectionsCommon(module, base_addr);
+ UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
}
void
-DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module, addr_t base_addr)
+DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
bool changed;
- const bool base_addr_is_offset = true;
module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset, changed);
}
@@ -171,7 +175,10 @@ DynamicLoader::GetSectionListFromModule(const ModuleSP module) const
}
ModuleSP
-DynamicLoader::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr)
+DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
Target &target = m_process->GetTarget();
ModuleList &modules = target.GetImages();
@@ -180,27 +187,28 @@ DynamicLoader::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, a
ModuleSpec module_spec (file, target.GetArchitecture());
if ((module_sp = modules.FindFirstModule (module_spec)))
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset);
}
else if ((module_sp = target.GetSharedModule(module_spec)))
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset);
}
else
{
- // Try to fetch the load address of the file from the process. It can be different from the
- // address reported by the linker in case of a file with fixed load address because the
- // linker reports the bias between the load address specified in the file and the actual
- // load address it loaded the file.
- bool is_loaded;
- lldb::addr_t load_addr;
- Error error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
- if (error.Fail() || !is_loaded)
- load_addr = base_addr;
-
- if ((module_sp = m_process->ReadModuleFromMemory(file, load_addr)))
+ if (base_addr_is_offset)
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ // Try to fetch the load address of the file from the process as we need absolute load
+ // address to read the file out of the memory instead of a load bias.
+ bool is_loaded;
+ lldb::addr_t load_addr;
+ Error error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
+ if (error.Success() && is_loaded)
+ base_addr = load_addr;
+ }
+
+ if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr)))
+ {
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
target.GetImages().AppendIfNeeded(module_sp);
}
}
diff --git a/contrib/llvm/tools/lldb/source/Core/EmulateInstruction.cpp b/contrib/llvm/tools/lldb/source/Core/EmulateInstruction.cpp
index 8349f54..9b6beeb 100644
--- a/contrib/llvm/tools/lldb/source/Core/EmulateInstruction.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/EmulateInstruction.cpp
@@ -635,17 +635,17 @@ EmulateInstruction::GetBestRegisterKindAndNumber (const RegisterInfo *reg_info,
return true;
}
- reg_num = reg_info->kinds[eRegisterKindGCC];
+ reg_num = reg_info->kinds[eRegisterKindEHFrame];
if (reg_num != LLDB_INVALID_REGNUM)
{
- reg_kind = eRegisterKindGCC;
+ reg_kind = eRegisterKindEHFrame;
return true;
}
- reg_num = reg_info->kinds[eRegisterKindGDB];
+ reg_num = reg_info->kinds[eRegisterKindProcessPlugin];
if (reg_num != LLDB_INVALID_REGNUM)
{
- reg_kind = eRegisterKindGDB;
+ reg_kind = eRegisterKindProcessPlugin;
return true;
}
return false;
diff --git a/contrib/llvm/tools/lldb/source/Core/Event.cpp b/contrib/llvm/tools/lldb/source/Core/Event.cpp
index bf5ff22..293a322 100644
--- a/contrib/llvm/tools/lldb/source/Core/Event.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Event.cpp
@@ -147,7 +147,7 @@ EventDataBytes::Dump (Stream *s) const
else if (m_bytes.size() > 0)
{
DataExtractor data;
- data.SetData(&m_bytes[0], m_bytes.size(), lldb::endian::InlHostByteOrder());
+ data.SetData(&m_bytes[0], m_bytes.size(), endian::InlHostByteOrder());
data.Dump(s, 0, eFormatBytes, 1, m_bytes.size(), 32, LLDB_INVALID_ADDRESS, 0, 0);
}
}
diff --git a/contrib/llvm/tools/lldb/source/Core/FastDemangle.cpp b/contrib/llvm/tools/lldb/source/Core/FastDemangle.cpp
index 0f12af2..a27a2f1 100644
--- a/contrib/llvm/tools/lldb/source/Core/FastDemangle.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/FastDemangle.cpp
@@ -161,7 +161,7 @@ public:
/// the Itanium C++ ABI mangling specification as implemented by Clang
///
/// @result Newly allocated null-terminated demangled name when demangling
- /// is succesful, and nullptr when demangling fails. The caller is
+ /// is successful, and nullptr when demangling fails. The caller is
/// responsible for freeing the allocated memory.
char *
diff --git a/contrib/llvm/tools/lldb/source/Core/FormatEntity.cpp b/contrib/llvm/tools/lldb/source/Core/FormatEntity.cpp
index e89d6c9..804682f 100644
--- a/contrib/llvm/tools/lldb/source/Core/FormatEntity.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/FormatEntity.cpp
@@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/StringRef.h"
-
#include "lldb/Core/FormatEntity.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+
#include "lldb/Core/Address.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Language.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamString.h"
@@ -21,7 +21,8 @@
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/FormatManager.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
+#include "lldb/DataFormatters/ValueObjectPrinter.h"
+#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/Block.h"
@@ -31,6 +32,7 @@
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
@@ -98,7 +100,8 @@ static FormatEntity::Entry::Definition g_function_child_entries[] =
ENTRY ("line-offset" , FunctionLineOffset , UInt64),
ENTRY ("pc-offset" , FunctionPCOffset , UInt64),
ENTRY ("initial-function" , FunctionInitial , None),
- ENTRY ("changed" , FunctionChanged , None)
+ ENTRY ("changed" , FunctionChanged , None),
+ ENTRY ("is-optimized" , FunctionIsOptimized , None)
};
static FormatEntity::Entry::Definition g_line_child_entries[] =
@@ -343,6 +346,7 @@ FormatEntity::Entry::TypeToCString (Type t)
ENUM_TO_CSTR(FunctionPCOffset);
ENUM_TO_CSTR(FunctionInitial);
ENUM_TO_CSTR(FunctionChanged);
+ ENUM_TO_CSTR(FunctionIsOptimized);
ENUM_TO_CSTR(LineEntryFile);
ENUM_TO_CSTR(LineEntryLineNumber);
ENUM_TO_CSTR(LineEntryStartAddress);
@@ -530,7 +534,7 @@ ScanBracketedRange (llvm::StringRef subpath,
int64_t& index_lower,
int64_t& index_higher)
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
close_bracket_index = llvm::StringRef::npos;
const size_t open_bracket_index = subpath.find('[');
if (open_bracket_index == llvm::StringRef::npos)
@@ -667,7 +671,7 @@ ExpandIndexedExpression (ValueObject* valobj,
StackFrame* frame,
bool deref_pointer)
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
const char* ptr_deref_format = "[%d]";
std::string ptr_deref_buffer(10,0);
::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
@@ -728,7 +732,7 @@ DumpValue (Stream &s,
if (valobj == NULL)
return false;
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
Format custom_format = eFormatInvalid;
ValueObject::ValueObjectRepresentationStyle val_obj_display = entry.string.empty() ? ValueObject::eValueObjectRepresentationStyleValue : ValueObject::eValueObjectRepresentationStyleSummary;
@@ -883,10 +887,10 @@ DumpValue (Stream &s,
}
// TODO use flags for these
- const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL);
+ const uint32_t type_info_flags = target->GetCompilerType().GetTypeInfo(NULL);
bool is_array = (type_info_flags & eTypeIsArray) != 0;
bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
- bool is_aggregate = target->GetClangType().IsAggregateType();
+ bool is_aggregate = target->GetCompilerType().IsAggregateType();
if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions
{
@@ -1302,6 +1306,8 @@ FormatEntity::Format (const Entry &entry,
// Watch for the special "tid" format...
if (entry.printf_format == "tid")
{
+ // TODO(zturner): Rather than hardcoding this to be platform specific, it should be controlled by a
+ // setting and the default value of the setting can be different depending on the platform.
Target &target = thread->GetProcess()->GetTarget();
ArchSpec arch (target.GetArchitecture ());
llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS;
@@ -1432,7 +1438,7 @@ FormatEntity::Format (const Entry &entry,
StopInfoSP stop_info_sp = thread->GetStopInfo ();
if (stop_info_sp && stop_info_sp->IsValid())
{
- ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp);
+ ExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp);
if (expression_var_sp && expression_var_sp->GetValueObject())
{
expression_var_sp->GetValueObject()->Dump(s);
@@ -1524,8 +1530,7 @@ FormatEntity::Format (const Entry &entry,
CompileUnit *cu = sc->comp_unit;
if (cu)
{
- Language lang(cu->GetLanguage());
- const char *lang_name = lang.AsCString();
+ const char *lang_name = Language::GetNameForLanguageType(cu->GetLanguage());
if (lang_name)
{
s.PutCString(lang_name);
@@ -1648,187 +1653,267 @@ FormatEntity::Format (const Entry &entry,
case Entry::Type::FunctionName:
{
- const char *name = NULL;
+ Language *language_plugin = nullptr;
+ bool language_plugin_handled = false;
+ StreamString ss;
if (sc->function)
- name = sc->function->GetName().AsCString (NULL);
+ language_plugin = Language::FindPlugin(sc->function->GetLanguage());
else if (sc->symbol)
- name = sc->symbol->GetName().AsCString (NULL);
- if (name)
+ language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
+ if (language_plugin)
{
- s.PutCString(name);
-
- if (sc->block)
+ language_plugin_handled = language_plugin->GetFunctionDisplayName(sc,
+ exe_ctx,
+ Language::FunctionNameRepresentation::eName,
+ ss);
+ }
+ if (language_plugin_handled)
+ {
+ s.PutCString(ss.GetData());
+ return true;
+ }
+ else
+ {
+ const char *name = NULL;
+ if (sc->function)
+ name = sc->function->GetName().AsCString (NULL);
+ else if (sc->symbol)
+ name = sc->symbol->GetName().AsCString (NULL);
+ if (name)
{
- Block *inline_block = sc->block->GetContainingInlinedBlock ();
- if (inline_block)
+ s.PutCString(name);
+
+ if (sc->block)
{
- const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo();
- if (inline_info)
+ Block *inline_block = sc->block->GetContainingInlinedBlock ();
+ if (inline_block)
{
- s.PutCString(" [inlined] ");
- inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
+ const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo();
+ if (inline_info)
+ {
+ s.PutCString(" [inlined] ");
+ inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
+ }
}
}
+ return true;
}
- return true;
}
}
return false;
case Entry::Type::FunctionNameNoArgs:
{
- ConstString name;
+ Language *language_plugin = nullptr;
+ bool language_plugin_handled = false;
+ StreamString ss;
if (sc->function)
- name = sc->function->GetNameNoArguments();
+ language_plugin = Language::FindPlugin(sc->function->GetLanguage());
else if (sc->symbol)
- name = sc->symbol->GetNameNoArguments();
- if (name)
+ language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
+ if (language_plugin)
+ {
+ language_plugin_handled = language_plugin->GetFunctionDisplayName(sc,
+ exe_ctx,
+ Language::FunctionNameRepresentation::eNameWithNoArgs,
+ ss);
+ }
+ if (language_plugin_handled)
{
- s.PutCString(name.GetCString());
+ s.PutCString(ss.GetData());
return true;
}
+ else
+ {
+ ConstString name;
+ if (sc->function)
+ name = sc->function->GetNameNoArguments();
+ else if (sc->symbol)
+ name = sc->symbol->GetNameNoArguments();
+ if (name)
+ {
+ s.PutCString(name.GetCString());
+ return true;
+ }
+ }
}
return false;
case Entry::Type::FunctionNameWithArgs:
{
- // Print the function name with arguments in it
+ Language *language_plugin = nullptr;
+ bool language_plugin_handled = false;
+ StreamString ss;
if (sc->function)
+ language_plugin = Language::FindPlugin(sc->function->GetLanguage());
+ else if (sc->symbol)
+ language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
+ if (language_plugin)
{
- ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
- const char *cstr = sc->function->GetName().AsCString (NULL);
- if (cstr)
+ language_plugin_handled = language_plugin->GetFunctionDisplayName(sc,
+ exe_ctx,
+ Language::FunctionNameRepresentation::eNameWithArgs,
+ ss);
+ }
+ if (language_plugin_handled)
+ {
+ s.PutCString(ss.GetData());
+ return true;
+ }
+ else
+ {
+ // Print the function name with arguments in it
+ if (sc->function)
{
- const InlineFunctionInfo *inline_info = NULL;
- VariableListSP variable_list_sp;
- bool get_function_vars = true;
- if (sc->block)
- {
- Block *inline_block = sc->block->GetContainingInlinedBlock ();
-
- if (inline_block)
- {
- get_function_vars = false;
- inline_info = sc->block->GetInlinedFunctionInfo();
- if (inline_info)
- variable_list_sp = inline_block->GetBlockVariableList (true);
- }
- }
-
- if (get_function_vars)
- {
- variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true);
- }
-
- if (inline_info)
- {
- s.PutCString (cstr);
- s.PutCString (" [inlined] ");
- cstr = inline_info->GetName(sc->function->GetLanguage()).GetCString();
- }
-
- VariableList args;
- if (variable_list_sp)
- variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args);
- if (args.GetSize() > 0)
+ ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
+ const char *cstr = sc->function->GetName().AsCString (NULL);
+ if (cstr)
{
- const char *open_paren = strchr (cstr, '(');
- const char *close_paren = nullptr;
- const char *generic = strchr(cstr, '<');
- // if before the arguments list begins there is a template sign
- // then scan to the end of the generic args before you try to find
- // the arguments list
- if (generic && open_paren && generic < open_paren)
+ const InlineFunctionInfo *inline_info = NULL;
+ VariableListSP variable_list_sp;
+ bool get_function_vars = true;
+ if (sc->block)
{
- int generic_depth = 1;
- ++generic;
- for (;
- *generic && generic_depth > 0;
- generic++)
+ Block *inline_block = sc->block->GetContainingInlinedBlock ();
+
+ if (inline_block)
{
- if (*generic == '<')
- generic_depth++;
- if (*generic == '>')
- generic_depth--;
+ get_function_vars = false;
+ inline_info = sc->block->GetInlinedFunctionInfo();
+ if (inline_info)
+ variable_list_sp = inline_block->GetBlockVariableList (true);
}
- if (*generic)
- open_paren = strchr(generic, '(');
- else
- open_paren = nullptr;
}
- if (open_paren)
+
+ if (get_function_vars)
{
- if (IsToken (open_paren, "(anonymous namespace)"))
- {
- open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '(');
- if (open_paren)
- close_paren = strchr (open_paren, ')');
- }
- else
- close_paren = strchr (open_paren, ')');
+ variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true);
}
-
- if (open_paren)
- s.Write(cstr, open_paren - cstr + 1);
- else
+
+ if (inline_info)
{
s.PutCString (cstr);
- s.PutChar ('(');
+ s.PutCString (" [inlined] ");
+ cstr = inline_info->GetName(sc->function->GetLanguage()).GetCString();
}
- const size_t num_args = args.GetSize();
- for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx)
+
+ VariableList args;
+ if (variable_list_sp)
+ variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args);
+ if (args.GetSize() > 0)
{
- std::string buffer;
-
- VariableSP var_sp (args.GetVariableAtIndex (arg_idx));
- ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp));
- const char *var_representation = nullptr;
- const char *var_name = var_value_sp->GetName().GetCString();
- if (var_value_sp->GetClangType().IsAggregateType() &&
- DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get()))
+ const char *open_paren = strchr (cstr, '(');
+ const char *close_paren = nullptr;
+ const char *generic = strchr(cstr, '<');
+ // if before the arguments list begins there is a template sign
+ // then scan to the end of the generic args before you try to find
+ // the arguments list
+ if (generic && open_paren && generic < open_paren)
+ {
+ int generic_depth = 1;
+ ++generic;
+ for (;
+ *generic && generic_depth > 0;
+ generic++)
+ {
+ if (*generic == '<')
+ generic_depth++;
+ if (*generic == '>')
+ generic_depth--;
+ }
+ if (*generic)
+ open_paren = strchr(generic, '(');
+ else
+ open_paren = nullptr;
+ }
+ if (open_paren)
{
- static StringSummaryFormat format(TypeSummaryImpl::Flags()
- .SetHideItemNames(false)
- .SetShowMembersOneLiner(true),
- "");
- format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
- var_representation = buffer.c_str();
+ if (IsToken (open_paren, "(anonymous namespace)"))
+ {
+ open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '(');
+ if (open_paren)
+ close_paren = strchr (open_paren, ')');
+ }
+ else
+ close_paren = strchr (open_paren, ')');
}
+
+ if (open_paren)
+ s.Write(cstr, open_paren - cstr + 1);
else
- var_representation = var_value_sp->GetValueAsCString();
- if (arg_idx > 0)
- s.PutCString (", ");
- if (var_value_sp->GetError().Success())
{
- if (var_representation)
- s.Printf ("%s=%s", var_name, var_representation);
+ s.PutCString (cstr);
+ s.PutChar ('(');
+ }
+ const size_t num_args = args.GetSize();
+ for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx)
+ {
+ std::string buffer;
+
+ VariableSP var_sp (args.GetVariableAtIndex (arg_idx));
+ ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp));
+ StreamString ss;
+ const char *var_representation = nullptr;
+ const char *var_name = var_value_sp->GetName().GetCString();
+ if (var_value_sp->GetCompilerType().IsValid())
+ {
+ if (var_value_sp && exe_scope->CalculateTarget())
+ var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(exe_scope->CalculateTarget()->TargetProperties::GetPreferDynamicValue(),
+ exe_scope->CalculateTarget()->TargetProperties::GetEnableSyntheticValue());
+ if (var_value_sp->GetCompilerType().IsAggregateType() &&
+ DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get()))
+ {
+ static StringSummaryFormat format(TypeSummaryImpl::Flags()
+ .SetHideItemNames(false)
+ .SetShowMembersOneLiner(true),
+ "");
+ format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
+ var_representation = buffer.c_str();
+ }
+ else
+ var_value_sp->DumpPrintableRepresentation(ss,
+ ValueObject::ValueObjectRepresentationStyle::eValueObjectRepresentationStyleSummary,
+ eFormatDefault,
+ ValueObject::PrintableRepresentationSpecialCases::ePrintableRepresentationSpecialCasesAllow,
+ false);
+ }
+
+ if (ss.GetData() && ss.GetSize())
+ var_representation = ss.GetData();
+ if (arg_idx > 0)
+ s.PutCString (", ");
+ if (var_value_sp->GetError().Success())
+ {
+ if (var_representation)
+ s.Printf ("%s=%s", var_name, var_representation);
+ else
+ s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString());
+ }
else
- s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString());
+ s.Printf ("%s=<unavailable>", var_name);
}
+
+ if (close_paren)
+ s.PutCString (close_paren);
else
- s.Printf ("%s=<unavailable>", var_name);
+ s.PutChar(')');
+
}
-
- if (close_paren)
- s.PutCString (close_paren);
else
- s.PutChar(')');
-
+ {
+ s.PutCString(cstr);
+ }
+ return true;
}
- else
+ }
+ else if (sc->symbol)
+ {
+ const char *cstr = sc->symbol->GetName().AsCString (NULL);
+ if (cstr)
{
s.PutCString(cstr);
+ return true;
}
- return true;
- }
- }
- else if (sc->symbol)
- {
- const char *cstr = sc->symbol->GetName().AsCString (NULL);
- if (cstr)
- {
- s.PutCString(cstr);
- return true;
}
}
}
@@ -1870,6 +1955,16 @@ FormatEntity::Format (const Entry &entry,
case Entry::Type::FunctionChanged:
return function_changed == true;
+ case Entry::Type::FunctionIsOptimized:
+ {
+ bool is_optimized = false;
+ if (sc->function && sc->function->GetIsOptimized())
+ {
+ is_optimized = true;
+ }
+ return is_optimized;
+ }
+
case Entry::Type::FunctionInitial:
return initial_function == true;
@@ -1976,7 +2071,7 @@ ParseEntry (const llvm::StringRef &format_str,
switch (entry_def->type)
{
case FormatEntity::Entry::Type::ParentString:
- entry.string = std::move(format_str.str());
+ entry.string = format_str.str();
return error; // Success
case FormatEntity::Entry::Type::ParentNumber:
@@ -2026,7 +2121,7 @@ ParseEntry (const llvm::StringRef &format_str,
{
// Any value whose separator is a with a ':' means this value has a string argument
// that needs to be stored in the entry (like "${script.var:modulename.function}")
- entry.string = std::move(value.str());
+ entry.string = value.str();
}
else
{
@@ -2247,7 +2342,7 @@ FormatEntity::ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint3
Entry entry;
if (!variable_format.empty())
{
- entry.printf_format = std::move(variable_format.str());
+ entry.printf_format = variable_format.str();
// If the format contains a '%' we are going to assume this is
// a printf style format. So if you want to format your thread ID
@@ -2396,10 +2491,10 @@ FormatEntity::ExtractVariableInfo (llvm::StringRef &format_str, llvm::StringRef
variable_name = llvm::StringRef();
variable_format = llvm::StringRef();
- const size_t paren_pos = format_str.find_first_of('}');
+ const size_t paren_pos = format_str.find('}');
if (paren_pos != llvm::StringRef::npos)
{
- const size_t percent_pos = format_str.find_first_of('%');
+ const size_t percent_pos = format_str.find('%');
if (percent_pos < paren_pos)
{
if (percent_pos > 0)
@@ -2449,7 +2544,7 @@ MakeMatch (const llvm::StringRef &prefix, const char *suffix)
{
std::string match(prefix.str());
match.append(suffix);
- return std::move(match);
+ return match;
}
static void
@@ -2463,7 +2558,7 @@ AddMatches (const FormatEntity::Entry::Definition *def,
{
for (size_t i=0; i<n; ++i)
{
- std::string match = std::move(prefix.str());
+ std::string match = prefix.str();
if (match_prefix.empty())
matches.AppendString(MakeMatch (prefix, def->children[i].name));
else if (strncmp(def->children[i].name, match_prefix.data(), match_prefix.size()) == 0)
@@ -2488,7 +2583,7 @@ FormatEntity::AutoComplete (const char *s,
// Hitting TAB after $ at the end of the string add a "{"
if (dollar_pos == str.size() - 1)
{
- std::string match = std::move(str.str());
+ std::string match = str.str();
match.append("{");
matches.AppendString(std::move(match));
}
@@ -2521,12 +2616,12 @@ FormatEntity::AutoComplete (const char *s,
if (n > 0)
{
// "${thread.info" <TAB>
- matches.AppendString(std::move(MakeMatch (str, ".")));
+ matches.AppendString(MakeMatch(str, "."));
}
else
{
// "${thread.id" <TAB>
- matches.AppendString(std::move(MakeMatch (str, "}")));
+ matches.AppendString(MakeMatch (str, "}"));
word_complete = true;
}
}
diff --git a/contrib/llvm/tools/lldb/source/Core/IOHandler.cpp b/contrib/llvm/tools/lldb/source/Core/IOHandler.cpp
index 0246778..47d00e9 100644
--- a/contrib/llvm/tools/lldb/source/Core/IOHandler.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/IOHandler.cpp
@@ -7,9 +7,20 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+#ifndef LLDB_DISABLE_CURSES
+#include <curses.h>
+#include <panel.h>
+#endif
+// C++ Includes
+#if defined(__APPLE__)
+#include <deque>
+#endif
#include <string>
+// Other libraries and framework includes
+// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Debugger.h"
@@ -28,10 +39,7 @@
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/ThreadPlan.h"
-#ifndef LLDB_DISABLE_CURSES
-#include <ncurses.h>
-#include <panel.h>
-#endif
+
using namespace lldb;
using namespace lldb_private;
@@ -46,7 +54,6 @@ IOHandler::IOHandler (Debugger &debugger, IOHandler::Type type) :
{
}
-
IOHandler::IOHandler (Debugger &debugger,
IOHandler::Type type,
const lldb::StreamFileSP &input_sp,
@@ -71,10 +78,7 @@ IOHandler::IOHandler (Debugger &debugger,
m_error_sp);
}
-IOHandler::~IOHandler()
-{
-}
-
+IOHandler::~IOHandler() = default;
int
IOHandler::GetInputFD()
@@ -136,7 +140,6 @@ IOHandler::GetOutputStreamFile()
return m_output_sp;
}
-
StreamFileSP &
IOHandler::GetErrorStreamFile()
{
@@ -204,10 +207,7 @@ IOHandlerConfirm::IOHandlerConfirm (Debugger &debugger,
}
-
-IOHandlerConfirm::~IOHandlerConfirm ()
-{
-}
+IOHandlerConfirm::~IOHandlerConfirm() = default;
int
IOHandlerConfirm::IOHandlerComplete (IOHandler &io_handler,
@@ -334,11 +334,9 @@ IOHandlerDelegate::IOHandlerComplete (IOHandler &io_handler,
break;
}
-
return 0;
}
-
IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
IOHandler::Type type,
const char *editline_name, // Used for saving history files
@@ -444,7 +442,6 @@ IOHandlerEditline::Deactivate ()
m_delegate.IOHandlerDeactivated(*this);
}
-
bool
IOHandlerEditline::GetLine (std::string &line, bool &interrupted)
{
@@ -619,7 +616,6 @@ IOHandlerEditline::GetContinuationPrompt ()
return m_continuation_prompt.c_str();
}
-
void
IOHandlerEditline::SetContinuationPrompt (const char *p)
{
@@ -634,7 +630,6 @@ IOHandlerEditline::SetContinuationPrompt (const char *p)
#endif
}
-
void
IOHandlerEditline::SetBaseLineNumber (uint32_t line)
{
@@ -824,6 +819,7 @@ type summary add -s "x=${var.x}, y=${var.y}" curses::Point
type summary add -s "w=${var.width}, h=${var.height}" curses::Size
type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
#endif
+
struct Point
{
int x;
@@ -855,13 +851,13 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
{
printf ("(x=%i, y=%i)\n", x, y);
}
-
};
bool operator == (const Point &lhs, const Point &rhs)
{
return lhs.x == rhs.x && lhs.y == rhs.y;
}
+
bool operator != (const Point &lhs, const Point &rhs)
{
return lhs.x != rhs.x || lhs.y != rhs.y;
@@ -889,13 +885,13 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
{
printf ("(w=%i, h=%i)\n", width, height);
}
-
};
bool operator == (const Size &lhs, const Size &rhs)
{
return lhs.width == rhs.width && lhs.height == rhs.height;
}
+
bool operator != (const Size &lhs, const Size &rhs)
{
return lhs.width != rhs.width || lhs.height != rhs.height;
@@ -942,6 +938,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
size.height -= h*2;
origin.y += h;
}
+
// Return a status bar rectangle which is the last line of
// this rectangle. This rectangle will be modified to not
// include the status bar area.
@@ -1011,7 +1008,6 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
VerticalSplit (left_width, left, right);
}
-
void
VerticalSplit (int left_width, Rect &left, Rect &right) const
{
@@ -1035,6 +1031,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
{
return lhs.origin == rhs.origin && lhs.size == rhs.size;
}
+
bool operator != (const Rect &lhs, const Rect &rhs)
{
return lhs.origin != rhs.origin || lhs.size != rhs.size;
@@ -1064,9 +1061,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
{
public:
virtual
- ~WindowDelegate()
- {
- }
+ ~WindowDelegate() = default;
virtual bool
WindowDelegateDraw (Window &window, bool force)
@@ -1098,9 +1093,9 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
{
public:
HelpDialogDelegate (const char *text, KeyHelp *key_help_array);
-
+
~HelpDialogDelegate() override;
-
+
bool
WindowDelegateDraw (Window &window, bool force) override;
@@ -1124,11 +1119,9 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
int m_first_visible_line;
};
-
class Window
{
public:
-
Window (const char *name) :
m_name (name),
m_window (NULL),
@@ -1726,6 +1719,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
{
return m_name.c_str();
}
+
protected:
std::string m_name;
WINDOW *m_window;
@@ -1747,8 +1741,8 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
class MenuDelegate
{
public:
- virtual ~MenuDelegate() {}
-
+ virtual ~MenuDelegate() = default;
+
virtual MenuActionResult
MenuDelegateAction (Menu &menu) = 0;
};
@@ -1772,10 +1766,8 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
const char *key_name,
int key_value,
uint64_t identifier);
-
- ~Menu () override
- {
- }
+
+ ~Menu() override = default;
const MenuDelegateSP &
GetDelegate () const
@@ -1912,7 +1904,6 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
return m_max_submenu_name_length + m_max_submenu_key_name_length + 8;
}
-
uint64_t
GetIdentifier() const
{
@@ -2223,7 +2214,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
{
// Run the action on this menu in case we need to populate the
// menu with dynamic content and also in case check marks, and
- // any other menu decorations need to be caclulated
+ // any other menu decorations need to be calculated
if (run_menu_sp->Action() == MenuActionResult::Quit)
return eQuitApplication;
@@ -2314,12 +2305,10 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
}
else if (menu_type == Menu::Type::Separator)
{
-
}
return result;
}
-
class Application
{
public:
@@ -2496,7 +2485,6 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
}
debugger.CancelForwardEvents (listener_sp);
-
}
WindowSP &
@@ -2520,11 +2508,9 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
FILE *m_in;
FILE *m_out;
};
-
} // namespace curses
-
using namespace curses;
struct Row
@@ -2661,11 +2647,13 @@ class TreeDelegate
{
public:
TreeDelegate() {}
- virtual ~TreeDelegate() {}
+ virtual ~TreeDelegate() = default;
+
virtual void TreeDelegateDrawTreeItem (TreeItem &item, Window &window) = 0;
virtual void TreeDelegateGenerateChildren (TreeItem &item) = 0;
virtual bool TreeDelegateItemSelected (TreeItem &item) = 0; // Return true if we need to update views
};
+
typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;
class TreeItem
@@ -2751,6 +2739,7 @@ public:
{
m_delegate.TreeDelegateItemSelected(*this);
}
+
void
CalculateRowIndexes (int &row_idx)
{
@@ -2944,7 +2933,6 @@ public:
{
m_identifier = identifier;
}
-
void
SetMightHaveChildren (bool b)
@@ -2961,7 +2949,6 @@ protected:
std::vector<TreeItem> m_children;
bool m_might_have_children;
bool m_is_expanded;
-
};
class TreeWindowDelegate : public WindowDelegate
@@ -3052,8 +3039,7 @@ public:
return true; // Drawing handled
}
-
-
+
const char *
WindowDelegateGetHelpText () override
{
@@ -3125,6 +3111,7 @@ public:
m_selected_item->ItemWasSelected ();
}
return eKeyHandled;
+
case KEY_DOWN:
if (m_selected_row_idx + 1 < m_num_rows)
{
@@ -3191,7 +3178,6 @@ protected:
int m_min_y;
int m_max_x;
int m_max_y;
-
};
class FrameTreeDelegate : public TreeDelegate
@@ -3203,11 +3189,9 @@ public:
FormatEntity::Parse ("frame #${frame.index}: {${function.name}${function.pc-offset}}}",
m_format);
}
-
- ~FrameTreeDelegate() override
- {
- }
-
+
+ ~FrameTreeDelegate() override = default;
+
void
TreeDelegateDrawTreeItem (TreeItem &item, Window &window) override
{
@@ -3229,6 +3213,7 @@ public:
}
}
}
+
void
TreeDelegateGenerateChildren (TreeItem &item) override
{
@@ -3248,6 +3233,7 @@ public:
}
return false;
}
+
protected:
FormatEntity::Entry m_format;
};
@@ -3264,11 +3250,9 @@ public:
FormatEntity::Parse ("thread #${thread.index}: tid = ${thread.id}{, stop reason = ${thread.stop-reason}}",
m_format);
}
-
- ~ThreadTreeDelegate() override
- {
- }
-
+
+ ~ThreadTreeDelegate() override = default;
+
ProcessSP
GetProcess ()
{
@@ -3299,6 +3283,7 @@ public:
}
}
}
+
void
TreeDelegateGenerateChildren (TreeItem &item) override
{
@@ -3369,7 +3354,6 @@ protected:
lldb::user_id_t m_tid;
uint32_t m_stop_id;
FormatEntity::Entry m_format;
-
};
class ThreadsTreeDelegate : public TreeDelegate
@@ -3384,11 +3368,9 @@ public:
FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
m_format);
}
-
- ~ThreadsTreeDelegate() override
- {
- }
-
+
+ ~ThreadsTreeDelegate() override = default;
+
ProcessSP
GetProcess ()
{
@@ -3460,7 +3442,6 @@ protected:
Debugger &m_debugger;
uint32_t m_stop_id;
FormatEntity::Entry m_format;
-
};
class ValueObjectListDelegate : public WindowDelegate
@@ -3490,10 +3471,8 @@ public:
{
SetValues (valobj_list);
}
-
- ~ValueObjectListDelegate() override
- {
- }
+
+ ~ValueObjectListDelegate() override = default;
void
SetValues (ValueObjectList &valobj_list)
@@ -3586,7 +3565,6 @@ public:
return g_source_view_key_help;
}
-
HandleCharResult
WindowDelegateHandleChar (Window &window, int c) override
{
@@ -3646,6 +3624,7 @@ public:
if (m_selected_row_idx > 0)
--m_selected_row_idx;
return eKeyHandled;
+
case KEY_DOWN:
if (m_selected_row_idx + 1 < m_num_rows)
++m_selected_row_idx;
@@ -3784,6 +3763,7 @@ protected:
return true;
}
+
void
DisplayRows (Window &window,
std::vector<Row> &rows,
@@ -3845,6 +3825,7 @@ protected:
}
return row_count;
}
+
static Row *
GetRowForRowIndexImpl (std::vector<Row> &rows, size_t &row_index)
{
@@ -3890,11 +3871,9 @@ public:
m_frame_block (NULL)
{
}
-
- ~FrameVariablesWindowDelegate() override
- {
- }
-
+
+ ~FrameVariablesWindowDelegate() override = default;
+
const char *
WindowDelegateGetHelpText () override
{
@@ -3924,7 +3903,6 @@ public:
}
}
-
ValueObjectList local_values;
if (frame_block)
{
@@ -3964,7 +3942,6 @@ public:
}
return ValueObjectListDelegate::WindowDelegateDraw (window, force);
-
}
protected:
@@ -3972,7 +3949,6 @@ protected:
Block *m_frame_block;
};
-
class RegistersWindowDelegate : public ValueObjectListDelegate
{
public:
@@ -3982,10 +3958,8 @@ public:
{
}
- ~RegistersWindowDelegate()
- {
- }
-
+ ~RegistersWindowDelegate() override = default;
+
const char *
WindowDelegateGetHelpText () override
{
@@ -4133,7 +4107,9 @@ CursesKeyToCString (int ch)
case KEY_UNDO: return "undo key";
case KEY_MOUSE: return "Mouse event has occurred";
case KEY_RESIZE: return "Terminal resize event";
+#ifdef KEY_EVENT
case KEY_EVENT: return "We were interrupted by an event";
+#endif
case KEY_RETURN: return "return";
case ' ': return "space";
case '\t': return "tab";
@@ -4168,9 +4144,7 @@ HelpDialogDelegate::HelpDialogDelegate (const char *text, KeyHelp *key_help_arra
}
}
-HelpDialogDelegate::~HelpDialogDelegate()
-{
-}
+HelpDialogDelegate::~HelpDialogDelegate() = default;
bool
HelpDialogDelegate::WindowDelegateDraw (Window &window, bool force)
@@ -4235,6 +4209,7 @@ HelpDialogDelegate::WindowDelegateHandleChar (Window &window, int key)
m_first_visible_line = 0;
}
break;
+
case KEY_NPAGE:
case '.':
if (m_first_visible_line + num_visible_lines < num_lines)
@@ -4244,6 +4219,7 @@ HelpDialogDelegate::WindowDelegateHandleChar (Window &window, int key)
m_first_visible_line = num_lines - num_visible_lines;
}
break;
+
default:
done = true;
break;
@@ -4298,10 +4274,8 @@ public:
m_debugger (debugger)
{
}
-
- ~ApplicationDelegate ()
- {
- }
+
+ ~ApplicationDelegate() override = default;
bool
WindowDelegateDraw (Window &window, bool force) override
@@ -4330,8 +4304,7 @@ public:
}
return eKeyNotHandled;
}
-
-
+
const char *
WindowDelegateGetHelpText () override
{
@@ -4626,7 +4599,6 @@ protected:
Debugger &m_debugger;
};
-
class StatusBarWindowDelegate : public WindowDelegate
{
public:
@@ -4636,10 +4608,8 @@ public:
FormatEntity::Parse("Thread: ${thread.id%tid}",
m_format);
}
-
- ~StatusBarWindowDelegate ()
- {
- }
+
+ ~StatusBarWindowDelegate() override = default;
bool
WindowDelegateDraw (Window &window, bool force) override
@@ -4713,9 +4683,7 @@ public:
{
}
- ~SourceFileWindowDelegate() override
- {
- }
+ ~SourceFileWindowDelegate() override = default;
void
Update (const SymbolContext &sc)
@@ -5063,7 +5031,6 @@ public:
}
if (highlight_attr)
window.AttributeOff(highlight_attr);
-
}
else
{
@@ -5240,6 +5207,7 @@ public:
return m_file_sp->GetNumLines();
return 0;
}
+
size_t
GetNumDisassemblyLines () const
{
@@ -5404,6 +5372,7 @@ public:
}
}
return eKeyHandled;
+
case 'n': // 'n' == step over
case 'N': // 'N' == step over instruction
{
@@ -5415,6 +5384,7 @@ public:
}
}
return eKeyHandled;
+
case 's': // 's' == step into
case 'S': // 'S' == step into instruction
{
@@ -5460,7 +5430,6 @@ protected:
int m_min_y;
int m_max_x;
int m_max_y;
-
};
DisplayOptions ValueObjectListDelegate::g_options = { true };
@@ -5477,8 +5446,7 @@ IOHandlerCursesGUI::Activate ()
if (!m_app_ap)
{
m_app_ap.reset (new Application (GetInputFILE(), GetOutputFILE()));
-
-
+
// This is both a window and a menu delegate
std::shared_ptr<ApplicationDelegate> app_delegate_sp(new ApplicationDelegate(*m_app_ap, m_debugger));
@@ -5578,7 +5546,6 @@ IOHandlerCursesGUI::Activate ()
init_pair (3, COLOR_MAGENTA , COLOR_WHITE );
init_pair (4, COLOR_MAGENTA , COLOR_BLACK );
init_pair (5, COLOR_RED , COLOR_BLACK );
-
}
}
@@ -5595,11 +5562,7 @@ IOHandlerCursesGUI::Run ()
SetIsDone(true);
}
-
-IOHandlerCursesGUI::~IOHandlerCursesGUI ()
-{
-
-}
+IOHandlerCursesGUI::~IOHandlerCursesGUI() = default;
void
IOHandlerCursesGUI::Cancel ()
@@ -5612,10 +5575,9 @@ IOHandlerCursesGUI::Interrupt ()
return false;
}
-
void
IOHandlerCursesGUI::GotEOF()
{
}
-#endif // #ifndef LLDB_DISABLE_CURSES
+#endif // LLDB_DISABLE_CURSES
diff --git a/contrib/llvm/tools/lldb/source/Core/Language.cpp b/contrib/llvm/tools/lldb/source/Core/Language.cpp
deleted file mode 100644
index 1cc4b8a..0000000
--- a/contrib/llvm/tools/lldb/source/Core/Language.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-//===-- Language.cpp --------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/lldb-private.h"
-#include "lldb/Core/Language.h"
-#include "lldb/Core/Stream.h"
-#include "llvm/ADT/STLExtras.h"
-#include <string.h>
-
-using namespace lldb;
-using namespace lldb_private;
-
-#define ENUM_TO_DCSTREAM(x) case x: s->PutCString(#x); return
-
-struct LanguageStrings
-{
- const char * names[3];
-};
-
-static LanguageStrings
-g_languages[] =
-{
- { { "unknown" , NULL , NULL } },
- { { "c89" , NULL , "ISO C:1989" } },
- { { NULL , NULL , "K&R C" } },
- { { "ada83" , "Ada83" , "ISO Ada:1983" } },
- { { "c++" , "cxx" , "ISO C++:1998" } },
- { { "cobol74" , "Cobol74" , "ISO Cobol:1974" } },
- { { "cobol" , "Cobol85" , "ISO Cobol:1985." } },
- { { "f77" , "Fortran77" , "ISO Fortran 77." } },
- { { "f90" , "Fortran90" , "ISO Fortran 90" } },
- { { "pascal" , "Pascal83" , "ISO Pascal:1983" } },
- { { "modula2" , "Modula2" , "ISO Modula-2:1996" } },
- { { "java" , NULL , "Java" } },
- { { "c" , "C99" , "ISO C:1999" } },
- { { "ada" , "Ada95" , "ISO Ada:1995" } },
- { { "f95" , "Fortran95" , "ISO Fortran 95" } },
- { { "PLI" , NULL , "ANSI PL/I:1976" } },
- { { "objc" , NULL , "Objective-C" } },
- { { "objc++" , NULL , "Objective-C++" } },
- { { "upc" , NULL , "Unified Parallel C" } },
- { { "d" , NULL , "D" } },
- { { "python" , NULL , "Python" } },
- { { "opencl" , "OpenCL" , "OpenCL" } },
- { { "go" , "Go" , "Go" } },
- { { "modula3" , "Modula3" , "Modula 3" } },
- { { "haskell" , "Haskell" , "Haskell" } },
- { { "c++03" , "C_plus_plus_03" , "ISO C++:2003" } },
- { { "c++11" , "C_plus_plus_11" , "ISO C++:2011" } },
- { { "ocaml" , "OCaml" , "OCaml" } },
- { { "rust" , "Rust" , "Rust" } },
- { { "c11" , "C11" , "ISO C:2011" } },
- { { "swift" , "Swift" , "Swift" } },
- { { "julia" , "Julia" , "Julia" } },
- { { "dylan" , "Dylan" , "Dylan" } },
- { { "c++14" , "C_plus_plus_14" , "ISO C++:2014" } },
- { { "f03" , "Fortran03" , "ISO Fortran 2003" } },
- { { "f08" , "Fortran08" , "ISO Fortran 2008" } },
- // Vendor Extensions
- { { "mipsassem" , "Mips_Assembler" , "Mips Assembler" } },
- { { "renderscript" , "RenderScript" , "RenderScript" } }
-};
-
-static const size_t g_num_languages = llvm::array_lengthof(g_languages);
-
-Language::Language(LanguageType language) :
- m_language (language)
-{
-}
-
-Language::~Language()
-{
-}
-
-LanguageType
-Language::GetLanguage() const
-{
- return m_language;
-}
-
-void
-Language::Clear ()
-{
- m_language = eLanguageTypeUnknown;
-}
-
-void
-Language::SetLanguage(LanguageType language)
-{
- m_language = language;
-}
-
-bool
-Language::SetLanguageFromCString(const char *language_cstr)
-{
- size_t i, desc_idx;
- const char *name;
-
- // First check the most common name for the languages
- for (desc_idx=lldb::eDescriptionLevelBrief; desc_idx<kNumDescriptionLevels; ++desc_idx)
- {
- for (i=0; i<g_num_languages; ++i)
- {
- name = g_languages[i].names[desc_idx];
- if (name == NULL)
- continue;
-
- if (::strcasecmp (language_cstr, name) == 0)
- {
- m_language = (LanguageType)i;
- return true;
- }
- }
- }
-
- m_language = eLanguageTypeUnknown;
- return false;
-}
-
-
-const char *
-Language::AsCString (lldb::DescriptionLevel level) const
-{
- if (m_language < g_num_languages && level < kNumDescriptionLevels)
- {
- const char *name = g_languages[m_language].names[level];
- if (name)
- return name;
- else if (level + 1 < kNumDescriptionLevels)
- return AsCString ((lldb::DescriptionLevel)(level + 1));
- else
- return NULL;
- }
- return NULL;
-}
-
-void
-Language::Dump(Stream *s) const
-{
- GetDescription(s, lldb::eDescriptionLevelVerbose);
-}
-
-void
-Language::GetDescription (Stream *s, lldb::DescriptionLevel level) const
-{
- const char *lang_cstr = AsCString(level);
-
- if (lang_cstr)
- s->PutCString(lang_cstr);
- else
- s->Printf("Language(language = 0x%4.4x)", m_language);
-}
-
-
-
-
-Stream&
-lldb_private::operator << (Stream& s, const Language& language)
-{
- language.Dump(&s);
- return s;
-}
-
diff --git a/contrib/llvm/tools/lldb/source/Core/Log.cpp b/contrib/llvm/tools/lldb/source/Core/Log.cpp
index 6acd50e..8d415bd 100644
--- a/contrib/llvm/tools/lldb/source/Core/Log.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Log.cpp
@@ -143,6 +143,7 @@ Log::VAPrintf(const char *format, va_list args)
std::string back_trace;
llvm::raw_string_ostream stream(back_trace);
llvm::sys::PrintStackTrace(stream);
+ stream.flush();
header.PutCString(back_trace.c_str());
}
@@ -449,7 +450,7 @@ Log::DisableAllLogChannels (Stream *feedback_strm)
{
CallbackMap &callback_map = GetCallbackMap ();
CallbackMapIter pos, end = callback_map.end();
- const char *categories[1] = {NULL};
+ const char *categories[] = {"all", nullptr};
for (pos = callback_map.begin(); pos != end; ++pos)
pos->second.disable (categories, feedback_strm);
diff --git a/contrib/llvm/tools/lldb/source/Core/Logging.cpp b/contrib/llvm/tools/lldb/source/Core/Logging.cpp
index 412536a..d08d833 100644
--- a/contrib/llvm/tools/lldb/source/Core/Logging.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Logging.cpp
@@ -148,6 +148,7 @@ lldb_private::DisableLog (const char **categories, Stream *feedback_strm)
else if (0 == ::strcasecmp(arg, "os")) flag_bits &= ~LIBLLDB_LOG_OS;
else if (0 == ::strcasecmp(arg, "jit")) flag_bits &= ~LIBLLDB_LOG_JIT_LOADER;
else if (0 == ::strcasecmp(arg, "language")) flag_bits &= ~LIBLLDB_LOG_LANGUAGE;
+ else if (0 == ::strncasecmp(arg, "formatters", 10)) flag_bits &= ~LIBLLDB_LOG_DATAFORMATTERS;
else
{
feedback_strm->Printf ("error: unrecognized log category '%s'\n", arg);
@@ -224,6 +225,7 @@ lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const ch
else if (0 == ::strncasecmp(arg, "watch", 5)) flag_bits |= LIBLLDB_LOG_WATCHPOINTS;
else if (0 == ::strcasecmp(arg, "jit")) flag_bits |= LIBLLDB_LOG_JIT_LOADER;
else if (0 == ::strcasecmp(arg, "language")) flag_bits |= LIBLLDB_LOG_LANGUAGE;
+ else if (0 == ::strncasecmp(arg, "formatters", 10)) flag_bits |= LIBLLDB_LOG_DATAFORMATTERS;
else
{
feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
@@ -254,6 +256,7 @@ lldb_private::ListLogCategories (Stream *strm)
" dyld - log shared library related activities\n"
" events - log broadcaster, listener and event queue activities\n"
" expr - log expressions\n"
+ " formatters - log data formatters related activities\n"
" host - log host activities\n"
" jit - log JIT events in the target\n"
" language - log language runtime events\n"
diff --git a/contrib/llvm/tools/lldb/source/Core/Mangled.cpp b/contrib/llvm/tools/lldb/source/Core/Mangled.cpp
index a1916fe..bdc710c 100644
--- a/contrib/llvm/tools/lldb/source/Core/Mangled.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Mangled.cpp
@@ -38,7 +38,8 @@
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/Timer.h"
-#include "lldb/Target/CPPLanguageRuntime.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
@@ -94,11 +95,12 @@ get_demangled_name_without_arguments (ConstString mangled, ConstString demangled
mangled_name_cstr[2] != 'G' && // avoid guard variables
mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
{
- CPPLanguageRuntime::MethodName cxx_method (demangled);
- if (!cxx_method.GetBasename().empty() && !cxx_method.GetContext().empty())
+ CPlusPlusLanguage::MethodName cxx_method (demangled);
+ if (!cxx_method.GetBasename().empty())
{
- std::string shortname = cxx_method.GetContext().str();
- shortname += "::";
+ std::string shortname;
+ if (!cxx_method.GetContext().empty())
+ shortname = cxx_method.GetContext().str() + "::";
shortname += cxx_method.GetBasename().str();
ConstString result(shortname.c_str());
g_most_recent_mangled_to_name_sans_args.first = mangled;
@@ -360,6 +362,9 @@ Mangled::NameMatches (const RegularExpression& regex, lldb::LanguageType languag
ConstString
Mangled::GetName (lldb::LanguageType language, Mangled::NamePreference preference) const
{
+ if (preference == ePreferMangled && m_mangled)
+ return m_mangled;
+
ConstString demangled = GetDemangledName(language);
if (preference == ePreferDemangledWithoutArguments)
@@ -374,12 +379,7 @@ Mangled::GetName (lldb::LanguageType language, Mangled::NamePreference preferenc
return demangled;
return m_mangled;
}
- else
- {
- if (m_mangled)
- return m_mangled;
- return demangled;
- }
+ return demangled;
}
//----------------------------------------------------------------------
@@ -425,6 +425,14 @@ Mangled::MemorySize () const
return m_mangled.MemorySize() + m_demangled.MemorySize();
}
+//----------------------------------------------------------------------
+// We "guess" the language because we can't determine a symbol's language
+// from it's name. For example, a Pascal symbol can be mangled using the
+// C++ Itanium scheme, and defined in a compilation unit within the same
+// module as other C++ units. In addition, different targets could have
+// different ways of mangling names from a given language, likewise the
+// compilation units within those targets.
+//----------------------------------------------------------------------
lldb::LanguageType
Mangled::GuessLanguage () const
{
@@ -433,11 +441,14 @@ Mangled::GuessLanguage () const
{
if (GetDemangledName(lldb::eLanguageTypeUnknown))
{
- if (cstring_is_mangled(mangled.GetCString()))
+ const char *mangled_name = mangled.GetCString();
+ if (CPlusPlusLanguage::IsCPPMangledName(mangled_name))
return lldb::eLanguageTypeC_plus_plus;
+ else if (ObjCLanguage::IsPossibleObjCMethodName(mangled_name))
+ return lldb::eLanguageTypeObjC;
}
}
- return lldb::eLanguageTypeUnknown;
+ return lldb::eLanguageTypeUnknown;
}
//----------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/source/Core/Module.cpp b/contrib/llvm/tools/lldb/source/Core/Module.cpp
index eb0359d..833540e 100644
--- a/contrib/llvm/tools/lldb/source/Core/Module.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Module.cpp
@@ -15,6 +15,7 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamString.h"
@@ -23,17 +24,19 @@
#include "lldb/Host/Symbols.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Target/CPPLanguageRuntime.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
-#include "lldb/Symbol/SymbolFile.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+#include "lldb/Symbol/TypeMap.h"
#include "Plugins/ObjectFile/JIT/ObjectFileJIT.h"
@@ -146,13 +149,12 @@ Module::Module (const ModuleSpec &module_spec) :
m_object_mod_time (),
m_objfile_sp (),
m_symfile_ap (),
- m_ast (new ClangASTContext),
+ m_type_system_map(),
m_source_mappings (),
m_sections_ap(),
m_did_load_objfile (false),
m_did_load_symbol_vendor (false),
m_did_parse_uuid (false),
- m_did_init_ast (false),
m_file_has_changed (false),
m_first_file_changed_log (false)
{
@@ -250,13 +252,12 @@ Module::Module(const FileSpec& file_spec,
m_object_mod_time (),
m_objfile_sp (),
m_symfile_ap (),
- m_ast (new ClangASTContext),
+ m_type_system_map(),
m_source_mappings (),
m_sections_ap(),
m_did_load_objfile (false),
m_did_load_symbol_vendor (false),
m_did_parse_uuid (false),
- m_did_init_ast (false),
m_file_has_changed (false),
m_first_file_changed_log (false)
{
@@ -296,13 +297,12 @@ Module::Module () :
m_object_mod_time (),
m_objfile_sp (),
m_symfile_ap (),
- m_ast (new ClangASTContext),
+ m_type_system_map(),
m_source_mappings (),
m_sections_ap(),
m_did_load_objfile (false),
m_did_load_symbol_vendor (false),
m_did_parse_uuid (false),
- m_did_init_ast (false),
m_file_has_changed (false),
m_first_file_changed_log (false)
{
@@ -399,52 +399,27 @@ Module::GetMemoryObjectFile (const lldb::ProcessSP &process_sp, lldb::addr_t hea
const lldb_private::UUID&
Module::GetUUID()
{
- Mutex::Locker locker (m_mutex);
- if (m_did_parse_uuid == false)
+ if (m_did_parse_uuid.load() == false)
{
- ObjectFile * obj_file = GetObjectFile ();
-
- if (obj_file != NULL)
+ Mutex::Locker locker (m_mutex);
+ if (m_did_parse_uuid.load() == false)
{
- obj_file->GetUUID(&m_uuid);
- m_did_parse_uuid = true;
+ ObjectFile * obj_file = GetObjectFile ();
+
+ if (obj_file != NULL)
+ {
+ obj_file->GetUUID(&m_uuid);
+ m_did_parse_uuid = true;
+ }
}
}
return m_uuid;
}
-ClangASTContext &
-Module::GetClangASTContext ()
+TypeSystem *
+Module::GetTypeSystemForLanguage (LanguageType language)
{
- Mutex::Locker locker (m_mutex);
- if (m_did_init_ast == false)
- {
- ObjectFile * objfile = GetObjectFile();
- ArchSpec object_arch;
- if (objfile && objfile->GetArchitecture(object_arch))
- {
- m_did_init_ast = true;
-
- // LLVM wants this to be set to iOS or MacOSX; if we're working on
- // a bare-boards type image, change the triple for llvm's benefit.
- if (object_arch.GetTriple().getVendor() == llvm::Triple::Apple
- && object_arch.GetTriple().getOS() == llvm::Triple::UnknownOS)
- {
- if (object_arch.GetTriple().getArch() == llvm::Triple::arm ||
- object_arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
- object_arch.GetTriple().getArch() == llvm::Triple::thumb)
- {
- object_arch.GetTriple().setOS(llvm::Triple::IOS);
- }
- else
- {
- object_arch.GetTriple().setOS(llvm::Triple::MacOSX);
- }
- }
- m_ast->SetArchitecture (object_arch);
- }
- }
- return *m_ast;
+ return m_type_system_map.GetTypeSystemForLanguage(language, this, true);
}
void
@@ -706,14 +681,14 @@ Module::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t li
size_t
Module::FindGlobalVariables (const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
bool append,
size_t max_matches,
VariableList& variables)
{
SymbolVendor *symbols = GetSymbolVendor ();
if (symbols)
- return symbols->FindGlobalVariables(name, namespace_decl, append, max_matches, variables);
+ return symbols->FindGlobalVariables(name, parent_decl_ctx, append, max_matches, variables);
return 0;
}
@@ -756,7 +731,7 @@ Module::FindCompileUnits (const FileSpec &path,
size_t
Module::FindFunctions (const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
uint32_t name_type_mask,
bool include_symbols,
bool include_inlines,
@@ -778,6 +753,7 @@ Module::FindFunctions (const ConstString &name,
bool match_name_after_lookup = false;
Module::PrepareForFunctionNameLookup (name,
name_type_mask,
+ eLanguageTypeUnknown, // TODO: add support
lookup_name,
lookup_name_type_mask,
match_name_after_lookup);
@@ -785,7 +761,7 @@ Module::FindFunctions (const ConstString &name,
if (symbols)
{
symbols->FindFunctions(lookup_name,
- namespace_decl,
+ parent_decl_ctx,
lookup_name_type_mask,
include_inlines,
append,
@@ -825,7 +801,7 @@ Module::FindFunctions (const ConstString &name,
{
if (symbols)
{
- symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list);
+ symbols->FindFunctions(name, parent_decl_ctx, name_type_mask, include_inlines, append, sc_list);
// Now check our symbol table for symbols that are code symbols if requested
if (include_symbols)
@@ -943,17 +919,17 @@ Module::FindAddressesForLine (const lldb::TargetSP target_sp,
size_t
Module::FindTypes_Impl (const SymbolContext& sc,
const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
bool append,
size_t max_matches,
- TypeList& types)
+ TypeMap& types)
{
Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
if (sc.module_sp.get() == NULL || sc.module_sp.get() == this)
{
SymbolVendor *symbols = GetSymbolVendor ();
if (symbols)
- return symbols->FindTypes(sc, name, namespace_decl, append, max_matches, types);
+ return symbols->FindTypes(sc, name, parent_decl_ctx, append, max_matches, types);
}
return 0;
}
@@ -961,12 +937,16 @@ Module::FindTypes_Impl (const SymbolContext& sc,
size_t
Module::FindTypesInNamespace (const SymbolContext& sc,
const ConstString &type_name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
size_t max_matches,
TypeList& type_list)
{
const bool append = true;
- return FindTypes_Impl(sc, type_name, namespace_decl, append, max_matches, type_list);
+ TypeMap types_map;
+ size_t num_types = FindTypes_Impl(sc, type_name, parent_decl_ctx, append, max_matches, types_map);
+ if (num_types > 0)
+ sc.SortTypeList(types_map, type_list);
+ return num_types;
}
lldb::TypeSP
@@ -995,6 +975,7 @@ Module::FindTypes (const SymbolContext& sc,
std::string type_basename;
const bool append = true;
TypeClass type_class = eTypeClassAny;
+ TypeMap typesmap;
if (Type::GetTypeScopeAndBasename (type_name_cstr, type_scope, type_basename, type_class))
{
// Check if "name" starts with "::" which means the qualified type starts
@@ -1008,10 +989,10 @@ Module::FindTypes (const SymbolContext& sc,
exact_match = true;
}
ConstString type_basename_const_str (type_basename.c_str());
- if (FindTypes_Impl(sc, type_basename_const_str, NULL, append, max_matches, types))
+ if (FindTypes_Impl(sc, type_basename_const_str, NULL, append, max_matches, typesmap))
{
- types.RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match);
- num_matches = types.GetSize();
+ typesmap.RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match);
+ num_matches = typesmap.GetSize();
}
}
else
@@ -1021,32 +1002,35 @@ Module::FindTypes (const SymbolContext& sc,
{
// The "type_name_cstr" will have been modified if we have a valid type class
// prefix (like "struct", "class", "union", "typedef" etc).
- FindTypes_Impl(sc, ConstString(type_name_cstr), NULL, append, max_matches, types);
- types.RemoveMismatchedTypes (type_class);
- num_matches = types.GetSize();
+ FindTypes_Impl(sc, ConstString(type_name_cstr), NULL, append, max_matches, typesmap);
+ typesmap.RemoveMismatchedTypes (type_class);
+ num_matches = typesmap.GetSize();
}
else
{
- num_matches = FindTypes_Impl(sc, name, NULL, append, max_matches, types);
+ num_matches = FindTypes_Impl(sc, name, NULL, append, max_matches, typesmap);
}
}
-
+ if (num_matches > 0)
+ sc.SortTypeList(typesmap, types);
return num_matches;
-
}
SymbolVendor*
Module::GetSymbolVendor (bool can_create, lldb_private::Stream *feedback_strm)
{
- Mutex::Locker locker (m_mutex);
- if (m_did_load_symbol_vendor == false && can_create)
+ if (m_did_load_symbol_vendor.load() == false)
{
- ObjectFile *obj_file = GetObjectFile ();
- if (obj_file != NULL)
+ Mutex::Locker locker (m_mutex);
+ if (m_did_load_symbol_vendor.load() == false && can_create)
{
- Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
- m_symfile_ap.reset(SymbolVendor::FindPlugin(shared_from_this(), feedback_strm));
- m_did_load_symbol_vendor = true;
+ ObjectFile *obj_file = GetObjectFile ();
+ if (obj_file != NULL)
+ {
+ Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+ m_symfile_ap.reset(SymbolVendor::FindPlugin(shared_from_this(), feedback_strm));
+ m_did_load_symbol_vendor = true;
+ }
}
}
return m_symfile_ap.get();
@@ -1287,37 +1271,40 @@ Module::GetObjectName() const
ObjectFile *
Module::GetObjectFile()
{
- Mutex::Locker locker (m_mutex);
- if (m_did_load_objfile == false)
+ if (m_did_load_objfile.load() == false)
{
- Timer scoped_timer(__PRETTY_FUNCTION__,
- "Module::GetObjectFile () module = %s", GetFileSpec().GetFilename().AsCString(""));
- DataBufferSP data_sp;
- lldb::offset_t data_offset = 0;
- const lldb::offset_t file_size = m_file.GetByteSize();
- if (file_size > m_object_offset)
+ Mutex::Locker locker (m_mutex);
+ if (m_did_load_objfile.load() == false)
{
- m_did_load_objfile = true;
- m_objfile_sp = ObjectFile::FindPlugin (shared_from_this(),
- &m_file,
- m_object_offset,
- file_size - m_object_offset,
- data_sp,
- data_offset);
- if (m_objfile_sp)
+ Timer scoped_timer(__PRETTY_FUNCTION__,
+ "Module::GetObjectFile () module = %s", GetFileSpec().GetFilename().AsCString(""));
+ DataBufferSP data_sp;
+ lldb::offset_t data_offset = 0;
+ const lldb::offset_t file_size = m_file.GetByteSize();
+ if (file_size > m_object_offset)
{
- // Once we get the object file, update our module with the object file's
- // architecture since it might differ in vendor/os if some parts were
- // unknown. But since the matching arch might already be more specific
- // than the generic COFF architecture, only merge in those values that
- // overwrite unspecified unknown values.
- ArchSpec new_arch;
- m_objfile_sp->GetArchitecture(new_arch);
- m_arch.MergeFrom(new_arch);
- }
- else
- {
- ReportError ("failed to load objfile for %s", GetFileSpec().GetPath().c_str());
+ m_did_load_objfile = true;
+ m_objfile_sp = ObjectFile::FindPlugin (shared_from_this(),
+ &m_file,
+ m_object_offset,
+ file_size - m_object_offset,
+ data_sp,
+ data_offset);
+ if (m_objfile_sp)
+ {
+ // Once we get the object file, update our module with the object file's
+ // architecture since it might differ in vendor/os if some parts were
+ // unknown. But since the matching arch might already be more specific
+ // than the generic COFF architecture, only merge in those values that
+ // overwrite unspecified unknown values.
+ ArchSpec new_arch;
+ m_objfile_sp->GetArchitecture(new_arch);
+ m_arch.MergeFrom(new_arch);
+ }
+ else
+ {
+ ReportError ("failed to load objfile for %s", GetFileSpec().GetPath().c_str());
+ }
}
}
}
@@ -1487,6 +1474,9 @@ Module::SetSymbolFileFileSpec (const FileSpec &file)
// we don't have to do anything.
return;
}
+
+ // Cleare the current symtab as we are going to replace it with a new one
+ obj_file->ClearSymtab();
// The symbol file might be a directory bundle ("/tmp/a.out.dSYM") instead
// of a full path to the symbol file within the bundle
@@ -1680,7 +1670,8 @@ Module::MatchesModuleSpec (const ModuleSpec &module_ref)
const FileSpec &file_spec = module_ref.GetFileSpec();
if (file_spec)
{
- if (!FileSpec::Equal (file_spec, m_file, (bool)file_spec.GetDirectory()))
+ if (!FileSpec::Equal (file_spec, m_file, (bool)file_spec.GetDirectory()) &&
+ !FileSpec::Equal (file_spec, m_platform_file, (bool)file_spec.GetDirectory()))
return false;
}
@@ -1739,6 +1730,7 @@ Module::GetVersion (uint32_t *versions, uint32_t num_versions)
void
Module::PrepareForFunctionNameLookup (const ConstString &name,
uint32_t name_type_mask,
+ LanguageType language,
ConstString &lookup_name,
uint32_t &lookup_name_type_mask,
bool &match_name_after_lookup)
@@ -1752,20 +1744,28 @@ Module::PrepareForFunctionNameLookup (const ConstString &name,
if (name_type_mask & eFunctionNameTypeAuto)
{
- if (CPPLanguageRuntime::IsCPPMangledName (name_cstr))
+ if (CPlusPlusLanguage::IsCPPMangledName (name_cstr))
lookup_name_type_mask = eFunctionNameTypeFull;
- else if (ObjCLanguageRuntime::IsPossibleObjCMethodName (name_cstr))
+ else if ((language == eLanguageTypeUnknown ||
+ Language::LanguageIsObjC(language)) &&
+ ObjCLanguage::IsPossibleObjCMethodName (name_cstr))
lookup_name_type_mask = eFunctionNameTypeFull;
+ else if (Language::LanguageIsC(language))
+ {
+ lookup_name_type_mask = eFunctionNameTypeFull;
+ }
else
{
- if (ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr))
+ if ((language == eLanguageTypeUnknown ||
+ Language::LanguageIsObjC(language)) &&
+ ObjCLanguage::IsPossibleObjCSelector(name_cstr))
lookup_name_type_mask |= eFunctionNameTypeSelector;
- CPPLanguageRuntime::MethodName cpp_method (name);
+ CPlusPlusLanguage::MethodName cpp_method (name);
basename = cpp_method.GetBasename();
if (basename.empty())
{
- if (CPPLanguageRuntime::ExtractContextAndIdentifier (name_cstr, context, basename))
+ if (CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename))
lookup_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);
else
lookup_name_type_mask |= eFunctionNameTypeFull;
@@ -1783,7 +1783,7 @@ Module::PrepareForFunctionNameLookup (const ConstString &name,
{
// If they've asked for a CPP method or function name and it can't be that, we don't
// even need to search for CPP methods or names.
- CPPLanguageRuntime::MethodName cpp_method (name);
+ CPlusPlusLanguage::MethodName cpp_method (name);
if (cpp_method.IsValid())
{
basename = cpp_method.GetBasename();
@@ -1801,13 +1801,13 @@ Module::PrepareForFunctionNameLookup (const ConstString &name,
{
// If the CPP method parser didn't manage to chop this up, try to fill in the base name if we can.
// If a::b::c is passed in, we need to just look up "c", and then we'll filter the result later.
- CPPLanguageRuntime::ExtractContextAndIdentifier (name_cstr, context, basename);
+ CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename);
}
}
if (lookup_name_type_mask & eFunctionNameTypeSelector)
{
- if (!ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr))
+ if (!ObjCLanguage::IsPossibleObjCSelector(name_cstr))
{
lookup_name_type_mask &= ~(eFunctionNameTypeSelector);
if (lookup_name_type_mask == eFunctionNameTypeNone)
diff --git a/contrib/llvm/tools/lldb/source/Core/ModuleList.cpp b/contrib/llvm/tools/lldb/source/Core/ModuleList.cpp
index 669b3d9..75b2ca1 100644
--- a/contrib/llvm/tools/lldb/source/Core/ModuleList.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ModuleList.cpp
@@ -22,7 +22,6 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/Symbols.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/VariableList.h"
@@ -70,7 +69,7 @@ ModuleList::operator= (const ModuleList& rhs)
// That's probably me nit-picking, but in theoretical situation:
//
// * that two threads A B and
- // * two ModuleList's x y do opposite assignemnts ie.:
+ // * two ModuleList's x y do opposite assignments ie.:
//
// in thread A: | in thread B:
// x = y; | y = x;
@@ -372,6 +371,7 @@ ModuleList::FindFunctions (const ConstString &name,
uint32_t lookup_name_type_mask = 0;
bool match_name_after_lookup = false;
Module::PrepareForFunctionNameLookup (name, name_type_mask,
+ eLanguageTypeUnknown, // TODO: add support
lookup_name,
lookup_name_type_mask,
match_name_after_lookup);
@@ -436,6 +436,7 @@ ModuleList::FindFunctionSymbols (const ConstString &name,
uint32_t lookup_name_type_mask = 0;
bool match_name_after_lookup = false;
Module::PrepareForFunctionNameLookup (name, name_type_mask,
+ eLanguageTypeUnknown, // TODO: add support
lookup_name,
lookup_name_type_mask,
match_name_after_lookup);
@@ -682,7 +683,7 @@ ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool na
{
// Search the module if the module is not equal to the one in the symbol
// context "sc". If "sc" contains a empty module shared pointer, then
- // the comparisong will always be true (valid_module_ptr != NULL).
+ // the comparison will always be true (valid_module_ptr != NULL).
if (sc.module_sp.get() != (*pos).get())
total_matches += (*pos)->FindTypes (world_sc, name, name_is_fully_qualified, max_matches, types);
@@ -988,18 +989,31 @@ ModuleList::GetSharedModule
// If we get in here we got the correct arch, now we just need
// to verify the UUID if one was given
if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
+ {
module_sp.reset();
+ }
else
{
- if (did_create_ptr)
- *did_create_ptr = true;
+ if (module_sp->GetObjectFile() && module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary)
+ {
+ module_sp.reset();
+ }
+ else
+ {
+ if (did_create_ptr)
+ {
+ *did_create_ptr = true;
+ }
- shared_module_list.ReplaceEquivalent(module_sp);
- return error;
+ shared_module_list.ReplaceEquivalent(module_sp);
+ return error;
+ }
}
}
else
+ {
module_sp.reset();
+ }
if (module_search_paths_ptr)
{
@@ -1023,18 +1037,29 @@ ModuleList::GetSharedModule
// If we get in here we got the correct arch, now we just need
// to verify the UUID if one was given
if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
+ {
module_sp.reset();
+ }
else
{
- if (did_create_ptr)
- *did_create_ptr = true;
-
- shared_module_list.ReplaceEquivalent(module_sp);
- return Error();
+ if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary)
+ {
+ module_sp.reset();
+ }
+ else
+ {
+ if (did_create_ptr)
+ *did_create_ptr = true;
+
+ shared_module_list.ReplaceEquivalent(module_sp);
+ return Error();
+ }
}
}
else
+ {
module_sp.reset();
+ }
}
}
@@ -1044,19 +1069,19 @@ ModuleList::GetSharedModule
// Fixup the incoming path in case the path points to a valid file, yet
// the arch or UUID (if one was passed in) don't match.
- FileSpec file_spec = Symbols::LocateExecutableObjectFile (module_spec);
+ ModuleSpec located_binary_modulespec = Symbols::LocateExecutableObjectFile (module_spec);
// Don't look for the file if it appears to be the same one we already
// checked for above...
- if (file_spec != module_file_spec)
+ if (located_binary_modulespec.GetFileSpec() != module_file_spec)
{
- if (!file_spec.Exists())
+ if (!located_binary_modulespec.GetFileSpec().Exists())
{
- file_spec.GetPath(path, sizeof(path));
+ located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
if (path[0] == '\0')
module_file_spec.GetPath(path, sizeof(path));
// How can this check ever be true? This branch it is false, and we haven't modified file_spec.
- if (file_spec.Exists())
+ if (located_binary_modulespec.GetFileSpec().Exists())
{
std::string uuid_str;
if (uuid_ptr && uuid_ptr->IsValid())
@@ -1084,8 +1109,9 @@ ModuleList::GetSharedModule
// function is actively working on it by doing an extra lock on the
// global mutex list.
ModuleSpec platform_module_spec(module_spec);
- platform_module_spec.GetFileSpec() = file_spec;
- platform_module_spec.GetPlatformFileSpec() = file_spec;
+ platform_module_spec.GetFileSpec() = located_binary_modulespec.GetFileSpec();
+ platform_module_spec.GetPlatformFileSpec() = located_binary_modulespec.GetFileSpec();
+ platform_module_spec.GetSymbolFileSpec() = located_binary_modulespec.GetSymbolFileSpec();
ModuleList matching_module_list;
if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0)
{
@@ -1095,7 +1121,7 @@ ModuleList::GetSharedModule
// then we should make sure the modification time hasn't changed!
if (platform_module_spec.GetUUIDPtr() == NULL)
{
- TimeValue file_spec_mod_time(file_spec.GetModificationTime());
+ TimeValue file_spec_mod_time(located_binary_modulespec.GetFileSpec().GetModificationTime());
if (file_spec_mod_time.IsValid())
{
if (file_spec_mod_time != module_sp->GetModificationTime())
@@ -1117,16 +1143,23 @@ ModuleList::GetSharedModule
// By getting the object file we can guarantee that the architecture matches
if (module_sp && module_sp->GetObjectFile())
{
- if (did_create_ptr)
- *did_create_ptr = true;
+ if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary)
+ {
+ module_sp.reset();
+ }
+ else
+ {
+ if (did_create_ptr)
+ *did_create_ptr = true;
- shared_module_list.ReplaceEquivalent(module_sp);
+ shared_module_list.ReplaceEquivalent(module_sp);
+ }
}
else
{
- file_spec.GetPath(path, sizeof(path));
+ located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
- if (file_spec)
+ if (located_binary_modulespec.GetFileSpec())
{
if (arch.IsValid())
error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path);
diff --git a/contrib/llvm/tools/lldb/source/Core/Opcode.cpp b/contrib/llvm/tools/lldb/source/Core/Opcode.cpp
index 73f5f85..89eea26 100644
--- a/contrib/llvm/tools/lldb/source/Core/Opcode.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Opcode.cpp
@@ -82,7 +82,7 @@ Opcode::GetDataByteOrder () const
case Opcode::eType16:
case Opcode::eType16_2:
case Opcode::eType32:
- case Opcode::eType64: return lldb::endian::InlHostByteOrder();
+ case Opcode::eType64: return endian::InlHostByteOrder();
case Opcode::eTypeBytes:
break;
}
diff --git a/contrib/llvm/tools/lldb/source/Core/PluginManager.cpp b/contrib/llvm/tools/lldb/source/Core/PluginManager.cpp
index e34b7fc..a90b576 100644
--- a/contrib/llvm/tools/lldb/source/Core/PluginManager.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/PluginManager.cpp
@@ -771,16 +771,18 @@ PluginManager::GetEmulateInstructionCreateCallbackForPluginName (const ConstStri
struct OperatingSystemInstance
{
- OperatingSystemInstance() :
- name(),
- description(),
- create_callback(NULL)
+ OperatingSystemInstance () :
+ name (),
+ description (),
+ create_callback (nullptr),
+ debugger_init_callback (nullptr)
{
}
ConstString name;
std::string description;
OperatingSystemCreateInstance create_callback;
+ DebuggerInitializeCallback debugger_init_callback;
};
typedef std::vector<OperatingSystemInstance> OperatingSystemInstances;
@@ -800,9 +802,9 @@ GetOperatingSystemInstances ()
}
bool
-PluginManager::RegisterPlugin (const ConstString &name,
- const char *description,
- OperatingSystemCreateInstance create_callback)
+PluginManager::RegisterPlugin(const ConstString &name, const char *description,
+ OperatingSystemCreateInstance create_callback,
+ DebuggerInitializeCallback debugger_init_callback)
{
if (create_callback)
{
@@ -812,6 +814,7 @@ PluginManager::RegisterPlugin (const ConstString &name,
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
+ instance.debugger_init_callback = debugger_init_callback;
Mutex::Locker locker (GetOperatingSystemMutex ());
GetOperatingSystemInstances ().push_back (instance);
}
@@ -868,6 +871,111 @@ PluginManager::GetOperatingSystemCreateCallbackForPluginName (const ConstString
}
+#pragma mark Language
+
+
+struct LanguageInstance
+{
+ LanguageInstance() :
+ name(),
+ description(),
+ create_callback(NULL)
+ {
+ }
+
+ ConstString name;
+ std::string description;
+ LanguageCreateInstance create_callback;
+};
+
+typedef std::vector<LanguageInstance> LanguageInstances;
+
+static Mutex &
+GetLanguageMutex ()
+{
+ static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
+ return g_instances_mutex;
+}
+
+static LanguageInstances &
+GetLanguageInstances ()
+{
+ static LanguageInstances g_instances;
+ return g_instances;
+}
+
+bool
+PluginManager::RegisterPlugin
+(
+ const ConstString &name,
+ const char *description,
+ LanguageCreateInstance create_callback
+ )
+{
+ if (create_callback)
+ {
+ LanguageInstance instance;
+ assert ((bool)name);
+ instance.name = name;
+ if (description && description[0])
+ instance.description = description;
+ instance.create_callback = create_callback;
+ Mutex::Locker locker (GetLanguageMutex ());
+ GetLanguageInstances ().push_back (instance);
+ }
+ return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (LanguageCreateInstance create_callback)
+{
+ if (create_callback)
+ {
+ Mutex::Locker locker (GetLanguageMutex ());
+ LanguageInstances &instances = GetLanguageInstances ();
+
+ LanguageInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (pos->create_callback == create_callback)
+ {
+ instances.erase(pos);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+LanguageCreateInstance
+PluginManager::GetLanguageCreateCallbackAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (GetLanguageMutex ());
+ LanguageInstances &instances = GetLanguageInstances ();
+ if (idx < instances.size())
+ return instances[idx].create_callback;
+ return NULL;
+}
+
+LanguageCreateInstance
+PluginManager::GetLanguageCreateCallbackForPluginName (const ConstString &name)
+{
+ if (name)
+ {
+ Mutex::Locker locker (GetLanguageMutex ());
+ LanguageInstances &instances = GetLanguageInstances ();
+
+ LanguageInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (name == pos->name)
+ return pos->create_callback;
+ }
+ }
+ return NULL;
+}
+
+
#pragma mark LanguageRuntime
@@ -1764,6 +1872,110 @@ PluginManager::GetProcessCreateCallbackForPluginName (const ConstString &name)
return NULL;
}
+#pragma mark ScriptInterpreter
+
+struct ScriptInterpreterInstance
+{
+ ScriptInterpreterInstance()
+ : name()
+ , language(lldb::eScriptLanguageNone)
+ , description()
+ , create_callback(NULL)
+ {
+ }
+
+ ConstString name;
+ lldb::ScriptLanguage language;
+ std::string description;
+ ScriptInterpreterCreateInstance create_callback;
+};
+
+typedef std::vector<ScriptInterpreterInstance> ScriptInterpreterInstances;
+
+static Mutex &
+GetScriptInterpreterMutex()
+{
+ static Mutex g_instances_mutex(Mutex::eMutexTypeRecursive);
+ return g_instances_mutex;
+}
+
+static ScriptInterpreterInstances &
+GetScriptInterpreterInstances()
+{
+ static ScriptInterpreterInstances g_instances;
+ return g_instances;
+}
+
+bool
+PluginManager::RegisterPlugin(const ConstString &name, const char *description, lldb::ScriptLanguage script_language,
+ ScriptInterpreterCreateInstance create_callback)
+{
+ if (!create_callback)
+ return false;
+ ScriptInterpreterInstance instance;
+ assert((bool)name);
+ instance.name = name;
+ if (description && description[0])
+ instance.description = description;
+ instance.create_callback = create_callback;
+ instance.language = script_language;
+ Mutex::Locker locker(GetScriptInterpreterMutex());
+ GetScriptInterpreterInstances().push_back(instance);
+ return false;
+}
+
+bool
+PluginManager::UnregisterPlugin(ScriptInterpreterCreateInstance create_callback)
+{
+ if (!create_callback)
+ return false;
+ Mutex::Locker locker(GetScriptInterpreterMutex());
+ ScriptInterpreterInstances &instances = GetScriptInterpreterInstances();
+
+ ScriptInterpreterInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++pos)
+ {
+ if (pos->create_callback != create_callback)
+ continue;
+
+ instances.erase(pos);
+ return true;
+ }
+ return false;
+}
+
+ScriptInterpreterCreateInstance
+PluginManager::GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx)
+{
+ Mutex::Locker locker(GetScriptInterpreterMutex());
+ ScriptInterpreterInstances &instances = GetScriptInterpreterInstances();
+ if (idx < instances.size())
+ return instances[idx].create_callback;
+ return nullptr;
+}
+
+lldb::ScriptInterpreterSP
+PluginManager::GetScriptInterpreterForLanguage(lldb::ScriptLanguage script_lang, CommandInterpreter &interpreter)
+{
+ Mutex::Locker locker(GetScriptInterpreterMutex());
+ ScriptInterpreterInstances &instances = GetScriptInterpreterInstances();
+
+ ScriptInterpreterInstances::iterator pos, end = instances.end();
+ ScriptInterpreterCreateInstance none_instance = nullptr;
+ for (pos = instances.begin(); pos != end; ++pos)
+ {
+ if (pos->language == lldb::eScriptLanguageNone)
+ none_instance = pos->create_callback;
+
+ if (script_lang == pos->language)
+ return pos->create_callback(interpreter);
+ }
+
+ // If we didn't find one, return the ScriptInterpreter for the null language.
+ assert(none_instance != nullptr);
+ return none_instance(interpreter);
+}
+
#pragma mark SymbolFile
struct SymbolFileInstance
@@ -1771,13 +1983,15 @@ struct SymbolFileInstance
SymbolFileInstance() :
name(),
description(),
- create_callback(NULL)
+ create_callback(nullptr),
+ debugger_init_callback(nullptr)
{
}
ConstString name;
std::string description;
SymbolFileCreateInstance create_callback;
+ DebuggerInitializeCallback debugger_init_callback;
};
typedef std::vector<SymbolFileInstance> SymbolFileInstances;
@@ -1802,7 +2016,8 @@ PluginManager::RegisterPlugin
(
const ConstString &name,
const char *description,
- SymbolFileCreateInstance create_callback
+ SymbolFileCreateInstance create_callback,
+ DebuggerInitializeCallback debugger_init_callback
)
{
if (create_callback)
@@ -1813,6 +2028,7 @@ PluginManager::RegisterPlugin
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
+ instance.debugger_init_callback = debugger_init_callback;
Mutex::Locker locker (GetSymbolFileMutex ());
GetSymbolFileInstances ().push_back (instance);
}
@@ -2300,6 +2516,270 @@ PluginManager::GetInstrumentationRuntimeCreateCallbackForPluginName (const Const
return NULL;
}
+#pragma mark TypeSystem
+
+
+struct TypeSystemInstance
+{
+ TypeSystemInstance() :
+ name(),
+ description(),
+ create_callback(NULL)
+ {
+ }
+
+ ConstString name;
+ std::string description;
+ TypeSystemCreateInstance create_callback;
+ TypeSystemEnumerateSupportedLanguages enumerate_callback;
+};
+
+typedef std::vector<TypeSystemInstance> TypeSystemInstances;
+
+static Mutex &
+GetTypeSystemMutex ()
+{
+ static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
+ return g_instances_mutex;
+}
+
+static TypeSystemInstances &
+GetTypeSystemInstances ()
+{
+ static TypeSystemInstances g_instances;
+ return g_instances;
+}
+
+bool
+PluginManager::RegisterPlugin (const ConstString &name,
+ const char *description,
+ TypeSystemCreateInstance create_callback,
+ TypeSystemEnumerateSupportedLanguages enumerate_supported_languages_callback)
+{
+ if (create_callback)
+ {
+ TypeSystemInstance instance;
+ assert ((bool)name);
+ instance.name = name;
+ if (description && description[0])
+ instance.description = description;
+ instance.create_callback = create_callback;
+ instance.enumerate_callback = enumerate_supported_languages_callback;
+ Mutex::Locker locker (GetTypeSystemMutex ());
+ GetTypeSystemInstances ().push_back (instance);
+ }
+ return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (TypeSystemCreateInstance create_callback)
+{
+ if (create_callback)
+ {
+ Mutex::Locker locker (GetTypeSystemMutex ());
+ TypeSystemInstances &instances = GetTypeSystemInstances ();
+
+ TypeSystemInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (pos->create_callback == create_callback)
+ {
+ instances.erase(pos);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+TypeSystemCreateInstance
+PluginManager::GetTypeSystemCreateCallbackAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (GetTypeSystemMutex ());
+ TypeSystemInstances &instances = GetTypeSystemInstances ();
+ if (idx < instances.size())
+ return instances[idx].create_callback;
+ return NULL;
+}
+
+TypeSystemCreateInstance
+PluginManager::GetTypeSystemCreateCallbackForPluginName (const ConstString &name)
+{
+ if (name)
+ {
+ Mutex::Locker locker (GetTypeSystemMutex ());
+ TypeSystemInstances &instances = GetTypeSystemInstances ();
+
+ TypeSystemInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (name == pos->name)
+ return pos->create_callback;
+ }
+ }
+ return NULL;
+}
+
+TypeSystemEnumerateSupportedLanguages
+PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (GetTypeSystemMutex ());
+ TypeSystemInstances &instances = GetTypeSystemInstances ();
+ if (idx < instances.size())
+ return instances[idx].enumerate_callback;
+ return NULL;
+}
+
+TypeSystemEnumerateSupportedLanguages
+PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name)
+{
+ if (name)
+ {
+ Mutex::Locker locker (GetTypeSystemMutex ());
+ TypeSystemInstances &instances = GetTypeSystemInstances ();
+
+ TypeSystemInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (name == pos->name)
+ return pos->enumerate_callback;
+ }
+ }
+ return NULL;
+}
+
+#pragma mark REPL
+
+struct REPLInstance
+{
+ REPLInstance() :
+ name(),
+ description(),
+ create_callback(NULL)
+ {
+ }
+
+ ConstString name;
+ std::string description;
+ REPLCreateInstance create_callback;
+ REPLEnumerateSupportedLanguages enumerate_languages_callback;
+};
+
+typedef std::vector<REPLInstance> REPLInstances;
+
+static Mutex &
+GetREPLMutex ()
+{
+ static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
+ return g_instances_mutex;
+}
+
+static REPLInstances &
+GetREPLInstances ()
+{
+ static REPLInstances g_instances;
+ return g_instances;
+}
+
+bool
+PluginManager::RegisterPlugin (const ConstString &name,
+ const char *description,
+ REPLCreateInstance create_callback,
+ REPLEnumerateSupportedLanguages enumerate_languages_callback)
+{
+ if (create_callback)
+ {
+ REPLInstance instance;
+ assert ((bool)name);
+ instance.name = name;
+ if (description && description[0])
+ instance.description = description;
+ instance.create_callback = create_callback;
+ instance.enumerate_languages_callback = enumerate_languages_callback;
+ Mutex::Locker locker (GetREPLMutex ());
+ GetREPLInstances ().push_back (instance);
+ }
+ return false;
+}
+
+bool
+PluginManager::UnregisterPlugin (REPLCreateInstance create_callback)
+{
+ if (create_callback)
+ {
+ Mutex::Locker locker (GetREPLMutex ());
+ REPLInstances &instances = GetREPLInstances ();
+
+ REPLInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (pos->create_callback == create_callback)
+ {
+ instances.erase(pos);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+REPLCreateInstance
+PluginManager::GetREPLCreateCallbackAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (GetREPLMutex ());
+ REPLInstances &instances = GetREPLInstances ();
+ if (idx < instances.size())
+ return instances[idx].create_callback;
+ return NULL;
+}
+
+REPLCreateInstance
+PluginManager::GetREPLCreateCallbackForPluginName (const ConstString &name)
+{
+ if (name)
+ {
+ Mutex::Locker locker (GetREPLMutex ());
+ REPLInstances &instances = GetREPLInstances ();
+
+ REPLInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (name == pos->name)
+ return pos->create_callback;
+ }
+ }
+ return NULL;
+}
+
+REPLEnumerateSupportedLanguages
+PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx)
+{
+ Mutex::Locker locker (GetREPLMutex ());
+ REPLInstances &instances = GetREPLInstances ();
+ if (idx < instances.size())
+ return instances[idx].enumerate_languages_callback;
+ return NULL;
+}
+
+
+REPLEnumerateSupportedLanguages
+PluginManager::GetREPLSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name)
+{
+ if (name)
+ {
+ Mutex::Locker locker (GetREPLMutex ());
+ REPLInstances &instances = GetREPLInstances ();
+
+ REPLInstances::iterator pos, end = instances.end();
+ for (pos = instances.begin(); pos != end; ++ pos)
+ {
+ if (name == pos->name)
+ return pos->enumerate_languages_callback;
+ }
+ }
+ return NULL;
+}
+
#pragma mark PluginManager
void
@@ -2343,7 +2823,7 @@ PluginManager::DebuggerInitialize (Debugger &debugger)
pos->debugger_init_callback (debugger);
}
}
-
+
// Initialize the Process plugins
{
Mutex::Locker locker (GetProcessMutex());
@@ -2357,6 +2837,25 @@ PluginManager::DebuggerInitialize (Debugger &debugger)
}
}
+ // Initialize the SymbolFile plugins
+ {
+ Mutex::Locker locker (GetSymbolFileMutex());
+ for (auto& sym_file: GetSymbolFileInstances())
+ {
+ if (sym_file.debugger_init_callback)
+ sym_file.debugger_init_callback (debugger);
+ }
+ }
+
+ // Initialize the OperatingSystem plugins
+ {
+ Mutex::Locker locker(GetOperatingSystemMutex());
+ for (auto &os : GetOperatingSystemInstances())
+ {
+ if (os.debugger_init_callback)
+ os.debugger_init_callback(debugger);
+ }
+ }
}
// This is the preferred new way to register plugin specific settings. e.g.
@@ -2439,32 +2938,40 @@ GetDebuggerPropertyForPluginsOldStyle (Debugger &debugger,
return lldb::OptionValuePropertiesSP();
}
+namespace {
+
+typedef lldb::OptionValuePropertiesSP
+GetDebuggerPropertyForPluginsPtr (Debugger&, const ConstString&, const ConstString&, bool can_create);
lldb::OptionValuePropertiesSP
-PluginManager::GetSettingForDynamicLoaderPlugin (Debugger &debugger, const ConstString &setting_name)
+GetSettingForPlugin (Debugger &debugger,
+ const ConstString &setting_name,
+ const ConstString &plugin_type_name,
+ GetDebuggerPropertyForPluginsPtr get_debugger_property= GetDebuggerPropertyForPlugins)
{
lldb::OptionValuePropertiesSP properties_sp;
- lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
- ConstString("dynamic-loader"),
- ConstString(), // not creating to so we don't need the description
- false));
+ lldb::OptionValuePropertiesSP plugin_type_properties_sp (get_debugger_property (debugger,
+ plugin_type_name,
+ ConstString(), // not creating to so we don't need the description
+ false));
if (plugin_type_properties_sp)
- properties_sp = plugin_type_properties_sp->GetSubProperty (NULL, setting_name);
+ properties_sp = plugin_type_properties_sp->GetSubProperty (nullptr, setting_name);
return properties_sp;
}
bool
-PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger,
- const lldb::OptionValuePropertiesSP &properties_sp,
- const ConstString &description,
- bool is_global_property)
+CreateSettingForPlugin (Debugger &debugger,
+ const ConstString &plugin_type_name,
+ const ConstString &plugin_type_desc,
+ const lldb::OptionValuePropertiesSP &properties_sp,
+ const ConstString &description,
+ bool is_global_property,
+ GetDebuggerPropertyForPluginsPtr get_debugger_property = GetDebuggerPropertyForPlugins)
{
if (properties_sp)
{
- lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
- ConstString("dynamic-loader"),
- ConstString("Settings for dynamic loader plug-ins"),
- true));
+ lldb::OptionValuePropertiesSP plugin_type_properties_sp (get_debugger_property (
+ debugger, plugin_type_name, plugin_type_desc, true));
if (plugin_type_properties_sp)
{
plugin_type_properties_sp->AppendProperty (properties_sp->GetName(),
@@ -2477,56 +2984,65 @@ PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger,
return false;
}
+const char* kDynamicLoaderPluginName("dynamic-loader");
+const char* kPlatformPluginName("platform");
+const char* kProcessPluginName("process");
+const char* kSymbolFilePluginName("symbol-file");
+const char* kJITLoaderPluginName("jit-loader");
+
+}
lldb::OptionValuePropertiesSP
-PluginManager::GetSettingForPlatformPlugin (Debugger &debugger, const ConstString &setting_name)
+PluginManager::GetSettingForDynamicLoaderPlugin (Debugger &debugger,
+ const ConstString &setting_name)
{
- lldb::OptionValuePropertiesSP properties_sp;
- lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPluginsOldStyle (debugger,
- ConstString("platform"),
- ConstString(), // not creating to so we don't need the description
- false));
- if (plugin_type_properties_sp)
- properties_sp = plugin_type_properties_sp->GetSubProperty (NULL, setting_name);
- return properties_sp;
+ return GetSettingForPlugin(debugger, setting_name, ConstString(kDynamicLoaderPluginName));
}
bool
-PluginManager::CreateSettingForPlatformPlugin (Debugger &debugger,
+PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger,
const lldb::OptionValuePropertiesSP &properties_sp,
const ConstString &description,
bool is_global_property)
{
- if (properties_sp)
- {
- lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPluginsOldStyle (debugger,
- ConstString("platform"),
- ConstString("Settings for platform plug-ins"),
- true));
- if (plugin_type_properties_sp)
- {
- plugin_type_properties_sp->AppendProperty (properties_sp->GetName(),
- description,
- is_global_property,
- properties_sp);
- return true;
- }
- }
- return false;
+ return CreateSettingForPlugin(debugger,
+ ConstString(kDynamicLoaderPluginName),
+ ConstString("Settings for dynamic loader plug-ins"),
+ properties_sp,
+ description,
+ is_global_property);
+}
+
+
+lldb::OptionValuePropertiesSP
+PluginManager::GetSettingForPlatformPlugin (Debugger &debugger, const ConstString &setting_name)
+{
+ return GetSettingForPlugin(debugger,
+ setting_name,
+ ConstString(kPlatformPluginName),
+ GetDebuggerPropertyForPluginsOldStyle);
+}
+
+bool
+PluginManager::CreateSettingForPlatformPlugin (Debugger &debugger,
+ const lldb::OptionValuePropertiesSP &properties_sp,
+ const ConstString &description,
+ bool is_global_property)
+{
+ return CreateSettingForPlugin(debugger,
+ ConstString(kPlatformPluginName),
+ ConstString("Settings for platform plug-ins"),
+ properties_sp,
+ description,
+ is_global_property,
+ GetDebuggerPropertyForPluginsOldStyle);
}
lldb::OptionValuePropertiesSP
PluginManager::GetSettingForProcessPlugin (Debugger &debugger, const ConstString &setting_name)
{
- lldb::OptionValuePropertiesSP properties_sp;
- lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
- ConstString("process"),
- ConstString(), // not creating to so we don't need the description
- false));
- if (plugin_type_properties_sp)
- properties_sp = plugin_type_properties_sp->GetSubProperty (NULL, setting_name);
- return properties_sp;
+ return GetSettingForPlugin(debugger, setting_name, ConstString(kProcessPluginName));
}
bool
@@ -2535,21 +3051,87 @@ PluginManager::CreateSettingForProcessPlugin (Debugger &debugger,
const ConstString &description,
bool is_global_property)
{
+ return CreateSettingForPlugin(debugger,
+ ConstString(kProcessPluginName),
+ ConstString("Settings for process plug-ins"),
+ properties_sp,
+ description,
+ is_global_property);
+}
+
+lldb::OptionValuePropertiesSP
+PluginManager::GetSettingForSymbolFilePlugin (Debugger &debugger,
+ const ConstString &setting_name)
+{
+ return GetSettingForPlugin(debugger, setting_name, ConstString(kSymbolFilePluginName));
+}
+
+bool
+PluginManager::CreateSettingForSymbolFilePlugin (Debugger &debugger,
+ const lldb::OptionValuePropertiesSP &properties_sp,
+ const ConstString &description,
+ bool is_global_property)
+{
+ return CreateSettingForPlugin(debugger,
+ ConstString(kSymbolFilePluginName),
+ ConstString("Settings for symbol file plug-ins"),
+ properties_sp,
+ description,
+ is_global_property);
+}
+
+lldb::OptionValuePropertiesSP
+PluginManager::GetSettingForJITLoaderPlugin (Debugger &debugger,
+ const ConstString &setting_name)
+{
+ return GetSettingForPlugin(debugger, setting_name, ConstString(kJITLoaderPluginName));
+}
+
+bool
+PluginManager::CreateSettingForJITLoaderPlugin (Debugger &debugger,
+ const lldb::OptionValuePropertiesSP &properties_sp,
+ const ConstString &description,
+ bool is_global_property)
+{
+ return CreateSettingForPlugin(debugger,
+ ConstString(kJITLoaderPluginName),
+ ConstString("Settings for JIT loader plug-ins"),
+ properties_sp,
+ description,
+ is_global_property);
+}
+
+static const char *kOperatingSystemPluginName("os");
+
+lldb::OptionValuePropertiesSP
+PluginManager::GetSettingForOperatingSystemPlugin(Debugger &debugger, const ConstString &setting_name)
+{
+ lldb::OptionValuePropertiesSP properties_sp;
+ lldb::OptionValuePropertiesSP plugin_type_properties_sp(
+ GetDebuggerPropertyForPlugins(debugger, ConstString(kOperatingSystemPluginName),
+ ConstString(), // not creating to so we don't need the description
+ false));
+ if (plugin_type_properties_sp)
+ properties_sp = plugin_type_properties_sp->GetSubProperty(nullptr, setting_name);
+ return properties_sp;
+}
+
+bool
+PluginManager::CreateSettingForOperatingSystemPlugin(Debugger &debugger,
+ const lldb::OptionValuePropertiesSP &properties_sp,
+ const ConstString &description, bool is_global_property)
+{
if (properties_sp)
{
- lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger,
- ConstString("process"),
- ConstString("Settings for process plug-ins"),
- true));
+ lldb::OptionValuePropertiesSP plugin_type_properties_sp(
+ GetDebuggerPropertyForPlugins(debugger, ConstString(kOperatingSystemPluginName),
+ ConstString("Settings for operating system plug-ins"), true));
if (plugin_type_properties_sp)
{
- plugin_type_properties_sp->AppendProperty (properties_sp->GetName(),
- description,
- is_global_property,
- properties_sp);
+ plugin_type_properties_sp->AppendProperty(properties_sp->GetName(), description, is_global_property,
+ properties_sp);
return true;
}
}
return false;
}
-
diff --git a/contrib/llvm/tools/lldb/source/Core/RegisterValue.cpp b/contrib/llvm/tools/lldb/source/Core/RegisterValue.cpp
index 272c1ee..d4ba998 100644
--- a/contrib/llvm/tools/lldb/source/Core/RegisterValue.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/RegisterValue.cpp
@@ -119,7 +119,7 @@ RegisterValue::GetAsMemoryData (const RegisterInfo *reg_info,
return 0;
}
- // ReadRegister should have already been called on tgus object prior to
+ // ReadRegister should have already been called on this object prior to
// calling this.
if (GetType() == eTypeInvalid)
{
@@ -215,10 +215,10 @@ RegisterValue::SetFromMemoryData (const RegisterInfo *reg_info,
}
else if (value_type == eTypeBytes)
{
- m_data.buffer.byte_order = src_byte_order;
+ buffer.byte_order = src_byte_order;
// Make sure to set the buffer length of the destination buffer to avoid
- // problems due to uninitalized variables.
- m_data.buffer.length = src_len;
+ // problems due to uninitialized variables.
+ buffer.length = src_len;
}
const uint32_t bytes_copied = src_data.CopyByteOrderedData (0, // src offset
@@ -240,25 +240,23 @@ RegisterValue::GetScalarValue (Scalar &scalar) const
case eTypeInvalid: break;
case eTypeBytes:
{
- switch (m_data.buffer.length)
+ switch (buffer.length)
{
default: break;
- case 1: scalar = m_data.uint8; return true;
- case 2: scalar = m_data.uint16; return true;
- case 4: scalar = m_data.uint32; return true;
- case 8: scalar = m_data.uint64; return true;
+ case 1: scalar = *(const uint8_t *)buffer.bytes; return true;
+ case 2: scalar = *(const uint16_t *)buffer.bytes; return true;
+ case 4: scalar = *(const uint32_t *)buffer.bytes; return true;
+ case 8: scalar = *(const uint64_t *)buffer.bytes; return true;
}
}
- case eTypeUInt8: scalar = m_data.uint8; return true;
- case eTypeUInt16: scalar = m_data.uint16; return true;
- case eTypeUInt32: scalar = m_data.uint32; return true;
- case eTypeUInt64: scalar = m_data.uint64; return true;
-#if defined (ENABLE_128_BIT_SUPPORT)
- case eTypeUInt128: break;
-#endif
- case eTypeFloat: scalar = m_data.ieee_float; return true;
- case eTypeDouble: scalar = m_data.ieee_double; return true;
- case eTypeLongDouble: scalar = m_data.ieee_long_double; return true;
+ case eTypeUInt8:
+ case eTypeUInt16:
+ case eTypeUInt32:
+ case eTypeUInt64:
+ case eTypeUInt128:
+ case eTypeFloat:
+ case eTypeDouble:
+ case eTypeLongDouble: scalar = m_scalar; return true;
}
return false;
}
@@ -289,10 +287,8 @@ RegisterValue::SetType (const RegisterInfo *reg_info)
m_type = eTypeUInt32;
else if (byte_size <= 8)
m_type = eTypeUInt64;
-#if defined (ENABLE_128_BIT_SUPPORT)
else if (byte_size <= 16)
m_type = eTypeUInt128;
-#endif
break;
case eEncodingIEEE754:
@@ -308,6 +304,7 @@ RegisterValue::SetType (const RegisterInfo *reg_info)
m_type = eTypeBytes;
break;
}
+ m_scalar.SetType(reg_info);
return m_type;
}
@@ -342,8 +339,9 @@ RegisterValue::SetValueFromData (const RegisterInfo *reg_info, DataExtractor &sr
src_len = reg_info->byte_size;
// Zero out the value in case we get partial data...
- memset (m_data.buffer.bytes, 0, sizeof (m_data.buffer.bytes));
-
+ memset (buffer.bytes, 0, sizeof (buffer.bytes));
+
+ type128 int128;
switch (SetType (reg_info))
{
case eTypeInvalid:
@@ -353,33 +351,38 @@ RegisterValue::SetValueFromData (const RegisterInfo *reg_info, DataExtractor &sr
case eTypeUInt16: SetUInt16 (src.GetMaxU32 (&src_offset, src_len)); break;
case eTypeUInt32: SetUInt32 (src.GetMaxU32 (&src_offset, src_len)); break;
case eTypeUInt64: SetUInt64 (src.GetMaxU64 (&src_offset, src_len)); break;
-#if defined (ENABLE_128_BIT_SUPPORT)
case eTypeUInt128:
{
- __uint128_t data1 = src.GetU64 (&src_offset);
- __uint128_t data2 = src.GetU64 (&src_offset);
+ uint64_t data1 = src.GetU64 (&src_offset);
+ uint64_t data2 = src.GetU64 (&src_offset);
if (src.GetByteSize() == eByteOrderBig)
- SetUInt128 (data1 << 64 + data2);
+ {
+ int128.x[0] = data1;
+ int128.x[1] = data2;
+ }
else
- SetUInt128 (data2 << 64 + data1);
+ {
+ int128.x[0] = data2;
+ int128.x[1] = data1;
+ }
+ SetUInt128 (llvm::APInt(128, 2, int128.x));
}
break;
-#endif
case eTypeFloat: SetFloat (src.GetFloat (&src_offset)); break;
case eTypeDouble: SetDouble(src.GetDouble (&src_offset)); break;
case eTypeLongDouble: SetFloat (src.GetLongDouble (&src_offset)); break;
case eTypeBytes:
{
- m_data.buffer.length = reg_info->byte_size;
- m_data.buffer.byte_order = src.GetByteOrder();
- assert (m_data.buffer.length <= kMaxRegisterByteSize);
- if (m_data.buffer.length > kMaxRegisterByteSize)
- m_data.buffer.length = kMaxRegisterByteSize;
+ buffer.length = reg_info->byte_size;
+ buffer.byte_order = src.GetByteOrder();
+ assert (buffer.length <= kMaxRegisterByteSize);
+ if (buffer.length > kMaxRegisterByteSize)
+ buffer.length = kMaxRegisterByteSize;
if (src.CopyByteOrderedData (src_offset, // offset within "src" to start extracting data
src_len, // src length
- m_data.buffer.bytes, // dst buffer
- m_data.buffer.length, // dst length
- m_data.buffer.byte_order) == 0)// dst byte order
+ buffer.bytes, // dst buffer
+ buffer.length, // dst length
+ buffer.byte_order) == 0)// dst byte order
{
error.SetErrorString ("data copy failed data.");
return error;
@@ -459,6 +462,9 @@ RegisterValue::SetValueFromCString (const RegisterInfo *reg_info, const char *va
}
bool success = false;
const uint32_t byte_size = reg_info->byte_size;
+ static float flt_val;
+ static double dbl_val;
+ static long double ldbl_val;
switch (reg_info->encoding)
{
case eEncodingInvalid:
@@ -510,22 +516,31 @@ RegisterValue::SetValueFromCString (const RegisterInfo *reg_info, const char *va
case eEncodingIEEE754:
if (byte_size == sizeof (float))
{
- if (::sscanf (value_str, "%f", &m_data.ieee_float) == 1)
+ if (::sscanf (value_str, "%f", &flt_val) == 1)
+ {
+ m_scalar = flt_val;
m_type = eTypeFloat;
+ }
else
error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str);
}
else if (byte_size == sizeof (double))
{
- if (::sscanf (value_str, "%lf", &m_data.ieee_double) == 1)
+ if (::sscanf (value_str, "%lf", &dbl_val) == 1)
+ {
+ m_scalar = dbl_val;
m_type = eTypeDouble;
+ }
else
error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str);
}
else if (byte_size == sizeof (long double))
{
- if (::sscanf (value_str, "%Lf", &m_data.ieee_long_double) == 1)
+ if (::sscanf (value_str, "%Lf", &ldbl_val) == 1)
+ {
+ m_scalar = ldbl_val;
m_type = eTypeLongDouble;
+ }
else
error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str);
}
@@ -557,81 +572,11 @@ RegisterValue::SignExtend (uint32_t sign_bitpos)
break;
case eTypeUInt8:
- if (sign_bitpos == (8-1))
- return true;
- else if (sign_bitpos < (8-1))
- {
- uint8_t sign_bit = 1u << sign_bitpos;
- if (m_data.uint8 & sign_bit)
- {
- const uint8_t mask = ~(sign_bit) + 1u;
- m_data.uint8 |= mask;
- }
- return true;
- }
- break;
-
case eTypeUInt16:
- if (sign_bitpos == (16-1))
- return true;
- else if (sign_bitpos < (16-1))
- {
- uint16_t sign_bit = 1u << sign_bitpos;
- if (m_data.uint16 & sign_bit)
- {
- const uint16_t mask = ~(sign_bit) + 1u;
- m_data.uint16 |= mask;
- }
- return true;
- }
- break;
-
case eTypeUInt32:
- if (sign_bitpos == (32-1))
- return true;
- else if (sign_bitpos < (32-1))
- {
- uint32_t sign_bit = 1u << sign_bitpos;
- if (m_data.uint32 & sign_bit)
- {
- const uint32_t mask = ~(sign_bit) + 1u;
- m_data.uint32 |= mask;
- }
- return true;
- }
- break;
-
case eTypeUInt64:
- if (sign_bitpos == (64-1))
- return true;
- else if (sign_bitpos < (64-1))
- {
- uint64_t sign_bit = 1ull << sign_bitpos;
- if (m_data.uint64 & sign_bit)
- {
- const uint64_t mask = ~(sign_bit) + 1ull;
- m_data.uint64 |= mask;
- }
- return true;
- }
- break;
-
-#if defined (ENABLE_128_BIT_SUPPORT)
case eTypeUInt128:
- if (sign_bitpos == (128-1))
- return true;
- else if (sign_bitpos < (128-1))
- {
- __uint128_t sign_bit = (__uint128_t)1u << sign_bitpos;
- if (m_data.uint128 & sign_bit)
- {
- const uint128_t mask = ~(sign_bit) + 1u;
- m_data.uint128 |= mask;
- }
- return true;
- }
- break;
-#endif
+ return m_scalar.SignExtend(sign_bitpos);
case eTypeFloat:
case eTypeDouble:
case eTypeLongDouble:
@@ -649,21 +594,19 @@ RegisterValue::CopyValue (const RegisterValue &rhs)
{
case eTypeInvalid:
return false;
- case eTypeUInt8: m_data.uint8 = rhs.m_data.uint8; break;
- case eTypeUInt16: m_data.uint16 = rhs.m_data.uint16; break;
- case eTypeUInt32: m_data.uint32 = rhs.m_data.uint32; break;
- case eTypeUInt64: m_data.uint64 = rhs.m_data.uint64; break;
-#if defined (ENABLE_128_BIT_SUPPORT)
- case eTypeUInt128: m_data.uint128 = rhs.m_data.uint128; break;
-#endif
- case eTypeFloat: m_data.ieee_float = rhs.m_data.ieee_float; break;
- case eTypeDouble: m_data.ieee_double = rhs.m_data.ieee_double; break;
- case eTypeLongDouble: m_data.ieee_long_double = rhs.m_data.ieee_long_double; break;
+ case eTypeUInt8:
+ case eTypeUInt16:
+ case eTypeUInt32:
+ case eTypeUInt64:
+ case eTypeUInt128:
+ case eTypeFloat:
+ case eTypeDouble:
+ case eTypeLongDouble: m_scalar = rhs.m_scalar; break;
case eTypeBytes:
- assert (rhs.m_data.buffer.length <= kMaxRegisterByteSize);
- ::memcpy (m_data.buffer.bytes, rhs.m_data.buffer.bytes, kMaxRegisterByteSize);
- m_data.buffer.length = rhs.m_data.buffer.length;
- m_data.buffer.byte_order = rhs.m_data.buffer.byte_order;
+ assert (rhs.buffer.length <= kMaxRegisterByteSize);
+ ::memcpy (buffer.bytes, rhs.buffer.bytes, kMaxRegisterByteSize);
+ buffer.length = rhs.buffer.length;
+ buffer.byte_order = rhs.buffer.byte_order;
break;
}
return true;
@@ -678,15 +621,15 @@ RegisterValue::GetAsUInt16 (uint16_t fail_value, bool *success_ptr) const
switch (m_type)
{
default: break;
- case eTypeUInt8: return m_data.uint8;
- case eTypeUInt16: return m_data.uint16;
+ case eTypeUInt8:
+ case eTypeUInt16: return m_scalar.UShort(fail_value);
case eTypeBytes:
{
- switch (m_data.buffer.length)
+ switch (buffer.length)
{
default: break;
- case 1: return m_data.uint8;
- case 2: return m_data.uint16;
+ case 1:
+ case 2: return *(const uint16_t *)buffer.bytes;
}
}
break;
@@ -704,29 +647,20 @@ RegisterValue::GetAsUInt32 (uint32_t fail_value, bool *success_ptr) const
switch (m_type)
{
default: break;
- case eTypeUInt8: return m_data.uint8;
- case eTypeUInt16: return m_data.uint16;
- case eTypeUInt32: return m_data.uint32;
+ case eTypeUInt8:
+ case eTypeUInt16:
+ case eTypeUInt32:
case eTypeFloat:
- if (sizeof(float) == sizeof(uint32_t))
- return m_data.uint32;
- break;
case eTypeDouble:
- if (sizeof(double) == sizeof(uint32_t))
- return m_data.uint32;
- break;
- case eTypeLongDouble:
- if (sizeof(long double) == sizeof(uint32_t))
- return m_data.uint32;
- break;
+ case eTypeLongDouble: return m_scalar.UInt(fail_value);
case eTypeBytes:
{
- switch (m_data.buffer.length)
+ switch (buffer.length)
{
default: break;
- case 1: return m_data.uint8;
- case 2: return m_data.uint16;
- case 4: return m_data.uint32;
+ case 1:
+ case 2:
+ case 4: return *(const uint32_t *)buffer.bytes;
}
}
break;
@@ -744,31 +678,22 @@ RegisterValue::GetAsUInt64 (uint64_t fail_value, bool *success_ptr) const
switch (m_type)
{
default: break;
- case eTypeUInt8: return m_data.uint8;
- case eTypeUInt16: return m_data.uint16;
- case eTypeUInt32: return m_data.uint32;
- case eTypeUInt64: return m_data.uint64;
+ case eTypeUInt8:
+ case eTypeUInt16:
+ case eTypeUInt32:
+ case eTypeUInt64:
case eTypeFloat:
- if (sizeof(float) == sizeof(uint64_t))
- return m_data.uint64;
- break;
case eTypeDouble:
- if (sizeof(double) == sizeof(uint64_t))
- return m_data.uint64;
- break;
- case eTypeLongDouble:
- if (sizeof(long double) == sizeof(uint64_t))
- return m_data.uint64;
- break;
+ case eTypeLongDouble: return m_scalar.ULongLong(fail_value);
case eTypeBytes:
{
- switch (m_data.buffer.length)
+ switch (buffer.length)
{
default: break;
- case 1: return m_data.uint8;
- case 2: return m_data.uint16;
- case 4: return m_data.uint32;
- case 8: return m_data.uint64;
+ case 1:
+ case 2:
+ case 4:
+ case 8: return *(const uint64_t *)buffer.bytes;
}
}
break;
@@ -778,43 +703,36 @@ RegisterValue::GetAsUInt64 (uint64_t fail_value, bool *success_ptr) const
return fail_value;
}
-#if defined (ENABLE_128_BIT_SUPPORT)
-__uint128_t
-RegisterValue::GetAsUInt128 (__uint128_t fail_value, bool *success_ptr) const
+llvm::APInt
+RegisterValue::GetAsUInt128 (const llvm::APInt& fail_value, bool *success_ptr) const
{
if (success_ptr)
*success_ptr = true;
switch (m_type)
{
default: break;
- case eTypeUInt8: return m_data.uint8;
- case eTypeUInt16: return m_data.uint16;
- case eTypeUInt32: return m_data.uint32;
- case eTypeUInt64: return m_data.uint64;
- case eTypeUInt128: return m_data.uint128;
+ case eTypeUInt8:
+ case eTypeUInt16:
+ case eTypeUInt32:
+ case eTypeUInt64:
+ case eTypeUInt128:
case eTypeFloat:
- if (sizeof(float) == sizeof(__uint128_t))
- return m_data.uint128;
- break;
case eTypeDouble:
- if (sizeof(double) == sizeof(__uint128_t))
- return m_data.uint128;
- break;
- case eTypeLongDouble:
- if (sizeof(long double) == sizeof(__uint128_t))
- return m_data.uint128;
- break;
+ case eTypeLongDouble: return m_scalar.UInt128(fail_value);
case eTypeBytes:
{
- switch (m_data.buffer.length)
+ switch (buffer.length)
{
- default:
- break;
- case 1: return m_data.uint8;
- case 2: return m_data.uint16;
- case 4: return m_data.uint32;
- case 8: return m_data.uint64;
- case 16: return m_data.uint128;
+ default:
+ break;
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ {
+ return llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)buffer.bytes)->x);
+ }
}
}
break;
@@ -823,7 +741,7 @@ RegisterValue::GetAsUInt128 (__uint128_t fail_value, bool *success_ptr) const
*success_ptr = false;
return fail_value;
}
-#endif
+
float
RegisterValue::GetAsFloat (float fail_value, bool *success_ptr) const
{
@@ -833,28 +751,12 @@ RegisterValue::GetAsFloat (float fail_value, bool *success_ptr) const
{
default: break;
case eTypeUInt32:
- if (sizeof(float) == sizeof(m_data.uint32))
- return m_data.ieee_float;
- break;
case eTypeUInt64:
- if (sizeof(float) == sizeof(m_data.uint64))
- return m_data.ieee_float;
- break;
-#if defined (ENABLE_128_BIT_SUPPORT)
case eTypeUInt128:
- if (sizeof(float) == sizeof(m_data.uint128))
- return m_data.ieee_float;
- break;
-#endif
- case eTypeFloat: return m_data.ieee_float;
+ case eTypeFloat:
case eTypeDouble:
- if (sizeof(float) == sizeof(double))
- return m_data.ieee_float;
- break;
case eTypeLongDouble:
- if (sizeof(float) == sizeof(long double))
- return m_data.ieee_float;
- break;
+ return m_scalar.Float(fail_value);
}
if (success_ptr)
*success_ptr = false;
@@ -872,27 +774,12 @@ RegisterValue::GetAsDouble (double fail_value, bool *success_ptr) const
break;
case eTypeUInt32:
- if (sizeof(double) == sizeof(m_data.uint32))
- return m_data.ieee_double;
- break;
-
case eTypeUInt64:
- if (sizeof(double) == sizeof(m_data.uint64))
- return m_data.ieee_double;
- break;
-
-#if defined (ENABLE_128_BIT_SUPPORT)
case eTypeUInt128:
- if (sizeof(double) == sizeof(m_data.uint128))
- return m_data.ieee_double;
-#endif
- case eTypeFloat: return m_data.ieee_float;
- case eTypeDouble: return m_data.ieee_double;
-
+ case eTypeFloat:
+ case eTypeDouble:
case eTypeLongDouble:
- if (sizeof(double) == sizeof(long double))
- return m_data.ieee_double;
- break;
+ return m_scalar.Double(fail_value);
}
if (success_ptr)
*success_ptr = false;
@@ -910,24 +797,12 @@ RegisterValue::GetAsLongDouble (long double fail_value, bool *success_ptr) const
break;
case eTypeUInt32:
- if (sizeof(long double) == sizeof(m_data.uint32))
- return m_data.ieee_long_double;
- break;
-
case eTypeUInt64:
- if (sizeof(long double) == sizeof(m_data.uint64))
- return m_data.ieee_long_double;
- break;
-
-#if defined (ENABLE_128_BIT_SUPPORT)
case eTypeUInt128:
- if (sizeof(long double) == sizeof(m_data.uint128))
- return m_data.ieee_long_double;
-#endif
- case eTypeFloat: return m_data.ieee_float;
- case eTypeDouble: return m_data.ieee_double;
- case eTypeLongDouble: return m_data.ieee_long_double;
- break;
+ case eTypeFloat:
+ case eTypeDouble:
+ case eTypeLongDouble:
+ return m_scalar.LongDouble();
}
if (success_ptr)
*success_ptr = false;
@@ -940,17 +815,15 @@ RegisterValue::GetBytes () const
switch (m_type)
{
case eTypeInvalid: break;
- case eTypeUInt8: return &m_data.uint8;
- case eTypeUInt16: return &m_data.uint16;
- case eTypeUInt32: return &m_data.uint32;
- case eTypeUInt64: return &m_data.uint64;
-#if defined (ENABLE_128_BIT_SUPPORT)
- case eTypeUInt128: return &m_data.uint128;
-#endif
- case eTypeFloat: return &m_data.ieee_float;
- case eTypeDouble: return &m_data.ieee_double;
- case eTypeLongDouble: return &m_data.ieee_long_double;
- case eTypeBytes: return m_data.buffer.bytes;
+ case eTypeUInt8:
+ case eTypeUInt16:
+ case eTypeUInt32:
+ case eTypeUInt64:
+ case eTypeUInt128:
+ case eTypeFloat:
+ case eTypeDouble:
+ case eTypeLongDouble: return m_scalar.GetBytes();
+ case eTypeBytes: return buffer.bytes;
}
return NULL;
}
@@ -961,17 +834,15 @@ RegisterValue::GetBytes ()
switch (m_type)
{
case eTypeInvalid: break;
- case eTypeUInt8: return &m_data.uint8;
- case eTypeUInt16: return &m_data.uint16;
- case eTypeUInt32: return &m_data.uint32;
- case eTypeUInt64: return &m_data.uint64;
-#if defined (ENABLE_128_BIT_SUPPORT)
- case eTypeUInt128: return &m_data.uint128;
-#endif
- case eTypeFloat: return &m_data.ieee_float;
- case eTypeDouble: return &m_data.ieee_double;
- case eTypeLongDouble: return &m_data.ieee_long_double;
- case eTypeBytes: return m_data.buffer.bytes;
+ case eTypeUInt8:
+ case eTypeUInt16:
+ case eTypeUInt32:
+ case eTypeUInt64:
+ case eTypeUInt128:
+ case eTypeFloat:
+ case eTypeDouble:
+ case eTypeLongDouble: return m_scalar.GetBytes();
+ case eTypeBytes: return buffer.bytes;
}
return NULL;
}
@@ -982,17 +853,15 @@ RegisterValue::GetByteSize () const
switch (m_type)
{
case eTypeInvalid: break;
- case eTypeUInt8: return sizeof(m_data.uint8);
- case eTypeUInt16: return sizeof(m_data.uint16);
- case eTypeUInt32: return sizeof(m_data.uint32);
- case eTypeUInt64: return sizeof(m_data.uint64);
-#if defined (ENABLE_128_BIT_SUPPORT)
- case eTypeUInt128: return sizeof(m_data.uint128);
-#endif
- case eTypeFloat: return sizeof(m_data.ieee_float);
- case eTypeDouble: return sizeof(m_data.ieee_double);
- case eTypeLongDouble: return sizeof(m_data.ieee_long_double);
- case eTypeBytes: return m_data.buffer.length;
+ case eTypeUInt8: return 1;
+ case eTypeUInt16: return 2;
+ case eTypeUInt32:
+ case eTypeUInt64:
+ case eTypeUInt128:
+ case eTypeFloat:
+ case eTypeDouble:
+ case eTypeLongDouble: return m_scalar.GetByteSize();
+ case eTypeBytes: return buffer.length;
}
return 0;
}
@@ -1021,12 +890,10 @@ RegisterValue::SetUInt (uint64_t uint, uint32_t byte_size)
{
SetUInt64 (uint);
}
-#if defined (ENABLE_128_BIT_SUPPORT)
else if (byte_size <= 16)
{
- SetUInt128 (uint);
+ SetUInt128 (llvm::APInt(128, uint));
}
-#endif
else
return false;
return true;
@@ -1036,21 +903,21 @@ void
RegisterValue::SetBytes (const void *bytes, size_t length, lldb::ByteOrder byte_order)
{
// If this assertion fires off we need to increase the size of
- // m_data.buffer.bytes, or make it something that is allocated on
+ // buffer.bytes, or make it something that is allocated on
// the heap. Since the data buffer is in a union, we can't make it
// a collection class like SmallVector...
if (bytes && length > 0)
{
- assert (length <= sizeof (m_data.buffer.bytes) && "Storing too many bytes in a RegisterValue.");
+ assert (length <= sizeof (buffer.bytes) && "Storing too many bytes in a RegisterValue.");
m_type = eTypeBytes;
- m_data.buffer.length = length;
- memcpy (m_data.buffer.bytes, bytes, length);
- m_data.buffer.byte_order = byte_order;
+ buffer.length = length;
+ memcpy (buffer.bytes, bytes, length);
+ buffer.byte_order = byte_order;
}
else
{
m_type = eTypeInvalid;
- m_data.buffer.length = 0;
+ buffer.length = 0;
}
}
@@ -1063,25 +930,23 @@ RegisterValue::operator == (const RegisterValue &rhs) const
switch (m_type)
{
case eTypeInvalid: return true;
- case eTypeUInt8: return m_data.uint8 == rhs.m_data.uint8;
- case eTypeUInt16: return m_data.uint16 == rhs.m_data.uint16;
- case eTypeUInt32: return m_data.uint32 == rhs.m_data.uint32;
- case eTypeUInt64: return m_data.uint64 == rhs.m_data.uint64;
-#if defined (ENABLE_128_BIT_SUPPORT)
- case eTypeUInt128: return m_data.uint128 == rhs.m_data.uint128;
-#endif
- case eTypeFloat: return m_data.ieee_float == rhs.m_data.ieee_float;
- case eTypeDouble: return m_data.ieee_double == rhs.m_data.ieee_double;
- case eTypeLongDouble: return m_data.ieee_long_double == rhs.m_data.ieee_long_double;
+ case eTypeUInt8:
+ case eTypeUInt16:
+ case eTypeUInt32:
+ case eTypeUInt64:
+ case eTypeUInt128:
+ case eTypeFloat:
+ case eTypeDouble:
+ case eTypeLongDouble: return m_scalar == rhs.m_scalar;
case eTypeBytes:
- if (m_data.buffer.length != rhs.m_data.buffer.length)
+ if (buffer.length != rhs.buffer.length)
return false;
else
{
- uint8_t length = m_data.buffer.length;
+ uint8_t length = buffer.length;
if (length > kMaxRegisterByteSize)
length = kMaxRegisterByteSize;
- return memcmp (m_data.buffer.bytes, rhs.m_data.buffer.bytes, length) == 0;
+ return memcmp (buffer.bytes, rhs.buffer.bytes, length) == 0;
}
break;
}
@@ -1097,27 +962,25 @@ RegisterValue::operator != (const RegisterValue &rhs) const
switch (m_type)
{
case eTypeInvalid: return false;
- case eTypeUInt8: return m_data.uint8 != rhs.m_data.uint8;
- case eTypeUInt16: return m_data.uint16 != rhs.m_data.uint16;
- case eTypeUInt32: return m_data.uint32 != rhs.m_data.uint32;
- case eTypeUInt64: return m_data.uint64 != rhs.m_data.uint64;
-#if defined (ENABLE_128_BIT_SUPPORT)
- case eTypeUInt128: return m_data.uint128 != rhs.m_data.uint128;
-#endif
- case eTypeFloat: return m_data.ieee_float != rhs.m_data.ieee_float;
- case eTypeDouble: return m_data.ieee_double != rhs.m_data.ieee_double;
- case eTypeLongDouble: return m_data.ieee_long_double != rhs.m_data.ieee_long_double;
+ case eTypeUInt8:
+ case eTypeUInt16:
+ case eTypeUInt32:
+ case eTypeUInt64:
+ case eTypeUInt128:
+ case eTypeFloat:
+ case eTypeDouble:
+ case eTypeLongDouble: return m_scalar != rhs.m_scalar;
case eTypeBytes:
- if (m_data.buffer.length != rhs.m_data.buffer.length)
+ if (buffer.length != rhs.buffer.length)
{
return true;
}
else
{
- uint8_t length = m_data.buffer.length;
+ uint8_t length = buffer.length;
if (length > kMaxRegisterByteSize)
length = kMaxRegisterByteSize;
- return memcmp (m_data.buffer.bytes, rhs.m_data.buffer.bytes, length) != 0;
+ return memcmp (buffer.bytes, rhs.buffer.bytes, length) != 0;
}
break;
}
@@ -1132,63 +995,35 @@ RegisterValue::ClearBit (uint32_t bit)
case eTypeInvalid:
break;
- case eTypeUInt8:
- if (bit < 8)
- {
- m_data.uint8 &= ~(1u << bit);
- return true;
- }
- break;
-
+ case eTypeUInt8:
case eTypeUInt16:
- if (bit < 16)
- {
- m_data.uint16 &= ~(1u << bit);
- return true;
- }
- break;
-
case eTypeUInt32:
- if (bit < 32)
- {
- m_data.uint32 &= ~(1u << bit);
- return true;
- }
- break;
-
case eTypeUInt64:
- if (bit < 64)
- {
- m_data.uint64 &= ~(1ull << (uint64_t)bit);
- return true;
- }
- break;
-#if defined (ENABLE_128_BIT_SUPPORT)
case eTypeUInt128:
- if (bit < 64)
+ if (bit < (GetByteSize() * 8))
{
- m_data.uint128 &= ~((__uint128_t)1ull << (__uint128_t)bit);
- return true;
+ return m_scalar.ClearBit(bit);
}
-#endif
+ break;
+
case eTypeFloat:
case eTypeDouble:
case eTypeLongDouble:
break;
case eTypeBytes:
- if (m_data.buffer.byte_order == eByteOrderBig || m_data.buffer.byte_order == eByteOrderLittle)
+ if (buffer.byte_order == eByteOrderBig || buffer.byte_order == eByteOrderLittle)
{
uint32_t byte_idx;
- if (m_data.buffer.byte_order == eByteOrderBig)
- byte_idx = m_data.buffer.length - (bit / 8) - 1;
+ if (buffer.byte_order == eByteOrderBig)
+ byte_idx = buffer.length - (bit / 8) - 1;
else
byte_idx = bit / 8;
const uint32_t byte_bit = bit % 8;
- if (byte_idx < m_data.buffer.length)
+ if (byte_idx < buffer.length)
{
- m_data.buffer.bytes[byte_idx] &= ~(1u << byte_bit);
+ buffer.bytes[byte_idx] &= ~(1u << byte_bit);
return true;
}
}
@@ -1207,62 +1042,34 @@ RegisterValue::SetBit (uint32_t bit)
break;
case eTypeUInt8:
- if (bit < 8)
- {
- m_data.uint8 |= (1u << bit);
- return true;
- }
- break;
-
case eTypeUInt16:
- if (bit < 16)
- {
- m_data.uint16 |= (1u << bit);
- return true;
- }
- break;
-
case eTypeUInt32:
- if (bit < 32)
- {
- m_data.uint32 |= (1u << bit);
- return true;
- }
- break;
-
case eTypeUInt64:
- if (bit < 64)
- {
- m_data.uint64 |= (1ull << (uint64_t)bit);
- return true;
- }
- break;
-#if defined (ENABLE_128_BIT_SUPPORT)
case eTypeUInt128:
- if (bit < 64)
+ if (bit < (GetByteSize() * 8))
{
- m_data.uint128 |= ((__uint128_t)1ull << (__uint128_t)bit);
- return true;
+ return m_scalar.SetBit(bit);
}
-#endif
+ break;
+
case eTypeFloat:
case eTypeDouble:
case eTypeLongDouble:
break;
case eTypeBytes:
- if (m_data.buffer.byte_order == eByteOrderBig || m_data.buffer.byte_order == eByteOrderLittle)
+ if (buffer.byte_order == eByteOrderBig || buffer.byte_order == eByteOrderLittle)
{
uint32_t byte_idx;
- if (m_data.buffer.byte_order == eByteOrderBig)
- byte_idx = m_data.buffer.length - (bit / 8) - 1;
+ if (buffer.byte_order == eByteOrderBig)
+ byte_idx = buffer.length - (bit / 8) - 1;
else
byte_idx = bit / 8;
const uint32_t byte_bit = bit % 8;
- if (byte_idx < m_data.buffer.length)
+ if (byte_idx < buffer.length)
{
- m_data.buffer.bytes[byte_idx] |= (1u << byte_bit);
+ buffer.bytes[byte_idx] |= (1u << byte_bit);
return true;
}
}
diff --git a/contrib/llvm/tools/lldb/source/Core/RegularExpression.cpp b/contrib/llvm/tools/lldb/source/Core/RegularExpression.cpp
index 3f712e1..7675215 100644
--- a/contrib/llvm/tools/lldb/source/Core/RegularExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/RegularExpression.cpp
@@ -153,7 +153,7 @@ RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, std::str
llvm::StringRef match_str_ref;
if (GetMatchAtIndex(s, idx, match_str_ref))
{
- match_str = std::move(match_str_ref.str());
+ match_str = match_str_ref.str();
return true;
}
return false;
@@ -258,4 +258,3 @@ RegularExpression::operator < (const RegularExpression& rhs) const
{
return (m_re < rhs.m_re);
}
-
diff --git a/contrib/llvm/tools/lldb/source/Core/Scalar.cpp b/contrib/llvm/tools/lldb/source/Core/Scalar.cpp
index 0022c34..586969b 100644
--- a/contrib/llvm/tools/lldb/source/Core/Scalar.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Scalar.cpp
@@ -11,6 +11,7 @@
#include <math.h>
#include <inttypes.h>
+#include <stdio.h>
#include "lldb/Interpreter/Args.h"
#include "lldb/Core/Error.h"
@@ -77,7 +78,7 @@ PromoteToMaxType
//----------------------------------------------------------------------
Scalar::Scalar() :
m_type(e_void),
- m_data()
+ m_float((float)0)
{
}
@@ -86,7 +87,8 @@ Scalar::Scalar() :
//----------------------------------------------------------------------
Scalar::Scalar(const Scalar& rhs) :
m_type(rhs.m_type),
- m_data(rhs.m_data) // TODO: verify that for C++ this will correctly copy the union??
+ m_integer(rhs.m_integer),
+ m_float(rhs.m_float)
{
}
@@ -135,29 +137,109 @@ bool
Scalar::GetData (DataExtractor &data, size_t limit_byte_size) const
{
size_t byte_size = GetByteSize();
+ static float f_val;
+ static double d_val;
if (byte_size > 0)
{
if (limit_byte_size < byte_size)
{
- if (lldb::endian::InlHostByteOrder() == eByteOrderLittle)
+ if (endian::InlHostByteOrder() == eByteOrderLittle)
{
// On little endian systems if we want fewer bytes from the
// current type we just specify fewer bytes since the LSByte
// is first...
- data.SetData((uint8_t*)&m_data, limit_byte_size, lldb::endian::InlHostByteOrder());
+ switch(m_type)
+ {
+ case e_void:
+ break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ data.SetData((const uint8_t *)m_integer.getRawData(), limit_byte_size, endian::InlHostByteOrder());
+ return true;
+ case e_float:
+ f_val = m_float.convertToFloat();
+ data.SetData((uint8_t *)&f_val, limit_byte_size, endian::InlHostByteOrder());
+ return true;
+ case e_double:
+ d_val = m_float.convertToDouble();
+ data.SetData((uint8_t *)&d_val, limit_byte_size, endian::InlHostByteOrder());
+ return true;
+ case e_long_double:
+ static llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ data.SetData((const uint8_t *)ldbl_val.getRawData(), limit_byte_size, endian::InlHostByteOrder());
+ return true;
+ }
}
- else if (lldb::endian::InlHostByteOrder() == eByteOrderBig)
+ else if (endian::InlHostByteOrder() == eByteOrderBig)
{
// On big endian systems if we want fewer bytes from the
// current type have to advance our initial byte pointer and
// trim down the number of bytes since the MSByte is first
- data.SetData(((uint8_t*)&m_data) + byte_size - limit_byte_size, limit_byte_size, lldb::endian::InlHostByteOrder());
+ switch(m_type)
+ {
+ case e_void:
+ break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ data.SetData((const uint8_t *)m_integer.getRawData() + byte_size - limit_byte_size, limit_byte_size, endian::InlHostByteOrder());
+ return true;
+ case e_float:
+ f_val = m_float.convertToFloat();
+ data.SetData((uint8_t *)&f_val + byte_size - limit_byte_size, limit_byte_size, endian::InlHostByteOrder());
+ return true;
+ case e_double:
+ d_val = m_float.convertToDouble();
+ data.SetData((uint8_t *)&d_val + byte_size - limit_byte_size, limit_byte_size, endian::InlHostByteOrder());
+ return true;
+ case e_long_double:
+ static llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ data.SetData((const uint8_t *)ldbl_val.getRawData() + byte_size - limit_byte_size, limit_byte_size, endian::InlHostByteOrder());
+ return true;
+ }
}
}
else
{
// We want all of the data
- data.SetData((uint8_t*)&m_data, byte_size, lldb::endian::InlHostByteOrder());
+ switch(m_type)
+ {
+ case e_void:
+ break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ data.SetData((const uint8_t *)m_integer.getRawData(), byte_size, endian::InlHostByteOrder());
+ return true;
+ case e_float:
+ f_val = m_float.convertToFloat();
+ data.SetData((uint8_t *)&f_val, byte_size, endian::InlHostByteOrder());
+ return true;
+ case e_double:
+ d_val = m_float.convertToDouble();
+ data.SetData((uint8_t *)&d_val, byte_size, endian::InlHostByteOrder());
+ return true;
+ case e_long_double:
+ static llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ data.SetData((const uint8_t *)ldbl_val.getRawData(), byte_size, endian::InlHostByteOrder());
+ return true;
+ }
}
return true;
}
@@ -165,6 +247,37 @@ Scalar::GetData (DataExtractor &data, size_t limit_byte_size) const
return false;
}
+void *
+Scalar::GetBytes() const
+{
+ static float_t flt_val;
+ static double_t dbl_val;
+ switch (m_type)
+ {
+ case e_void:
+ break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return const_cast<void *>(reinterpret_cast<const void *>(m_integer.getRawData()));
+ case e_float:
+ flt_val = m_float.convertToFloat();
+ return (void *)&flt_val;
+ case e_double:
+ dbl_val = m_float.convertToDouble();
+ return (void *)&dbl_val;
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return const_cast<void *>(reinterpret_cast<const void *>(ldbl_val.getRawData()));
+ }
+ return NULL;
+}
+
size_t
Scalar::GetByteSize() const
{
@@ -172,15 +285,17 @@ Scalar::GetByteSize() const
{
case e_void:
break;
- case e_sint: return sizeof(m_data.sint);
- case e_uint: return sizeof(m_data.uint);
- case e_slong: return sizeof(m_data.slong);
- case e_ulong: return sizeof(m_data.ulong);
- case e_slonglong: return sizeof(m_data.slonglong);
- case e_ulonglong: return sizeof(m_data.ulonglong);
- case e_float: return sizeof(m_data.flt);
- case e_double: return sizeof(m_data.dbl);
- case e_long_double: return sizeof(m_data.ldbl);
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128: return (m_integer.getBitWidth() / 8);
+ case e_float: return sizeof(float_t);
+ case e_double: return sizeof(double_t);
+ case e_long_double: return sizeof(long_double_t);
}
return 0;
}
@@ -188,19 +303,24 @@ Scalar::GetByteSize() const
bool
Scalar::IsZero() const
{
+ llvm::APInt zero_int = llvm::APInt::getNullValue(m_integer.getBitWidth() / 8);
switch (m_type)
{
case e_void:
break;
- case e_sint: return m_data.sint == 0;
- case e_uint: return m_data.uint == 0;
- case e_slong: return m_data.slong == 0;
- case e_ulong: return m_data.ulong == 0;
- case e_slonglong: return m_data.slonglong == 0;
- case e_ulonglong: return m_data.ulonglong == 0;
- case e_float: return m_data.flt == 0.0f;
- case e_double: return m_data.dbl == 0.0;
- case e_long_double: return m_data.ldbl == 0.0;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return llvm::APInt::isSameValue(zero_int, m_integer);
+ case e_float:
+ case e_double:
+ case e_long_double:
+ return m_float.isZero();
}
return false;
}
@@ -208,6 +328,7 @@ Scalar::IsZero() const
void
Scalar::GetValue (Stream *s, bool show_type) const
{
+ const uint64_t *src;
if (show_type)
s->Printf("(%s) ", GetTypeAsCString());
@@ -215,15 +336,26 @@ Scalar::GetValue (Stream *s, bool show_type) const
{
case e_void:
break;
- case e_sint: s->Printf("%i", m_data.sint); break;
- case e_uint: s->Printf("0x%8.8x", m_data.uint); break;
- case e_slong: s->Printf("%li", m_data.slong); break;
- case e_ulong: s->Printf("0x%8.8lx", m_data.ulong); break;
- case e_slonglong: s->Printf("%lli", m_data.slonglong); break;
- case e_ulonglong: s->Printf("0x%16.16llx", m_data.ulonglong); break;
- case e_float: s->Printf("%f", m_data.flt); break;
- case e_double: s->Printf("%g", m_data.dbl); break;
- case e_long_double: s->Printf("%Lg", m_data.ldbl); break;
+ case e_sint: s->Printf("%i", *(const sint_t *) m_integer.getRawData()); break;
+ case e_uint: s->Printf("0x%8.8x", *(const uint_t *) m_integer.getRawData()); break;
+ case e_slong: s->Printf("%li", *(const slong_t *) m_integer.getRawData()); break;
+ case e_ulong: s->Printf("0x%8.8lx", *(const ulong_t *) m_integer.getRawData()); break;
+ case e_slonglong: s->Printf("%lli", *(const slonglong_t *) m_integer.getRawData()); break;
+ case e_ulonglong: s->Printf("0x%16.16llx", *(const ulonglong_t *) m_integer.getRawData()); break;
+ case e_sint128:
+ src = m_integer.getRawData();
+ s->Printf("%lli%lli", *(const slonglong_t *)src, *(const slonglong_t *)(src + 1));
+ break;
+ case e_uint128:
+ src = m_integer.getRawData();
+ s->Printf("0x%16.16llx%16.16llx", *(const ulonglong_t *)src, *(const ulonglong_t *)(src + 1));
+ break;
+ case e_float: s->Printf("%f", m_float.convertToFloat()); break;
+ case e_double: s->Printf("%g", m_float.convertToDouble()); break;
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ s->Printf("%Lg", *(const long_double_t *)ldbl_val.getRawData());
+ break;
}
}
@@ -239,6 +371,8 @@ Scalar::GetTypeAsCString() const
case e_ulong: return "unsigned long";
case e_slonglong: return "long long";
case e_ulonglong: return "unsigned long long";
+ case e_sint128: return "int128_t";
+ case e_uint128: return "unsigned int128_t";
case e_float: return "float";
case e_double: return "double";
case e_long_double: return "long double";
@@ -257,7 +391,8 @@ Scalar::operator=(const Scalar& rhs)
if (this != &rhs)
{
m_type = rhs.m_type;
- ::memcpy (&m_data, &rhs.m_data, sizeof(m_data));
+ m_integer = llvm::APInt(rhs.m_integer);
+ m_float = rhs.m_float;
}
return *this;
}
@@ -266,7 +401,7 @@ Scalar&
Scalar::operator= (const int v)
{
m_type = e_sint;
- m_data.sint = v;
+ m_integer = llvm::APInt(sizeof(int) * 8, v, true);
return *this;
}
@@ -275,7 +410,7 @@ Scalar&
Scalar::operator= (unsigned int v)
{
m_type = e_uint;
- m_data.uint = v;
+ m_integer = llvm::APInt(sizeof(int) * 8, v);
return *this;
}
@@ -283,7 +418,7 @@ Scalar&
Scalar::operator= (long v)
{
m_type = e_slong;
- m_data.slong = v;
+ m_integer = llvm::APInt(sizeof(long) * 8, v, true);
return *this;
}
@@ -291,7 +426,7 @@ Scalar&
Scalar::operator= (unsigned long v)
{
m_type = e_ulong;
- m_data.ulong = v;
+ m_integer = llvm::APInt(sizeof(long) * 8, v);
return *this;
}
@@ -299,7 +434,7 @@ Scalar&
Scalar::operator= (long long v)
{
m_type = e_slonglong;
- m_data.slonglong = v;
+ m_integer = llvm::APInt(sizeof(long) * 8, v, true);
return *this;
}
@@ -307,7 +442,7 @@ Scalar&
Scalar::operator= (unsigned long long v)
{
m_type = e_ulonglong;
- m_data.ulonglong = v;
+ m_integer = llvm::APInt(sizeof(long long) * 8, v);
return *this;
}
@@ -315,7 +450,7 @@ Scalar&
Scalar::operator= (float v)
{
m_type = e_float;
- m_data.flt = v;
+ m_float = llvm::APFloat(v);
return *this;
}
@@ -323,7 +458,7 @@ Scalar&
Scalar::operator= (double v)
{
m_type = e_double;
- m_data.dbl = v;
+ m_float = llvm::APFloat(v);
return *this;
}
@@ -331,7 +466,40 @@ Scalar&
Scalar::operator= (long double v)
{
m_type = e_long_double;
- m_data.ldbl = v;
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x));
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x));
+ return *this;
+}
+
+Scalar&
+Scalar::operator= (llvm::APInt rhs)
+{
+ m_integer = llvm::APInt(rhs);
+ switch(m_integer.getBitWidth())
+ {
+ case 8:
+ case 16:
+ case 32:
+ if(m_integer.isSignedIntN(sizeof(sint_t) * 8))
+ m_type = e_sint;
+ else
+ m_type = e_uint;
+ break;
+ case 64:
+ if(m_integer.isSignedIntN(sizeof(slonglong_t) * 8))
+ m_type = e_slonglong;
+ else
+ m_type = e_ulonglong;
+ break;
+ case 128:
+ if(m_integer.isSignedIntN(BITWIDTH_INT128))
+ m_type = e_sint128;
+ else
+ m_type = e_uint128;
+ break;
+ }
return *this;
}
@@ -354,128 +522,455 @@ Scalar::Promote(Scalar::Type type)
case e_sint:
switch (type)
{
- case e_void: break;
- case e_sint: success = true; break;
- case e_uint: m_data.uint = m_data.sint; success = true; break;
- case e_slong: m_data.slong = m_data.sint; success = true; break;
- case e_ulong: m_data.ulong = m_data.sint; success = true; break;
- case e_slonglong: m_data.slonglong = m_data.sint; success = true; break;
- case e_ulonglong: m_data.ulonglong = m_data.sint; success = true; break;
- case e_float: m_data.flt = m_data.sint; success = true; break;
- case e_double: m_data.dbl = m_data.sint; success = true; break;
- case e_long_double: m_data.ldbl = m_data.sint; success = true; break;
+ case e_void: break;
+ case e_sint: success = true; break;
+ case e_uint:
+ {
+ m_integer = llvm::APInt(sizeof(uint_t) * 8, *(const uint64_t *)m_integer.getRawData(), false);
+ success = true;
+ break;
+ }
+ case e_slong:
+ {
+ m_integer = llvm::APInt(sizeof(slong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true);
+ success = true;
+ break;
+ }
+ case e_ulong:
+ {
+ m_integer = llvm::APInt(sizeof(ulong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false);
+ success = true;
+ break;
+ }
+ case e_slonglong:
+ {
+ m_integer = llvm::APInt(sizeof(slonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true);
+ success = true;
+ break;
+ }
+ case e_ulonglong:
+ {
+ m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false);
+ success = true;
+ break;
+ }
+ case e_sint128:
+ case e_uint128:
+ {
+ m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData()));
+ success = true;
+ break;
+ }
+ case e_float:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToFloat());
+ success = true;
+ break;
+ }
+ case e_double:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToDouble());
+ success = true;
+ break;
+ }
+ case e_long_double:
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer);
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer);
+ success = true;
+ break;
+ }
}
break;
case e_uint:
switch (type)
{
- case e_void:
- case e_sint: break;
- case e_uint: success = true; break;
- case e_slong: m_data.slong = m_data.uint; success = true; break;
- case e_ulong: m_data.ulong = m_data.uint; success = true; break;
- case e_slonglong: m_data.slonglong = m_data.uint; success = true; break;
- case e_ulonglong: m_data.ulonglong = m_data.uint; success = true; break;
- case e_float: m_data.flt = m_data.uint; success = true; break;
- case e_double: m_data.dbl = m_data.uint; success = true; break;
- case e_long_double: m_data.ldbl = m_data.uint; success = true; break;
+ case e_void:
+ case e_sint: break;
+ case e_uint: success = true; break;
+ case e_slong:
+ {
+ m_integer = llvm::APInt(sizeof(slong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true);
+ success = true;
+ break;
+ }
+ case e_ulong:
+ {
+ m_integer = llvm::APInt(sizeof(ulong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false);
+ success = true;
+ break;
+ }
+ case e_slonglong:
+ {
+ m_integer = llvm::APInt(sizeof(slonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true);
+ success = true;
+ break;
+ }
+ case e_ulonglong:
+ {
+ m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false);
+ success = true;
+ break;
+ }
+ case e_sint128:
+ case e_uint128:
+ {
+ m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData()));
+ success = true;
+ break;
+ }
+ case e_float:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToFloat());
+ success = true;
+ break;
+ }
+ case e_double:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToDouble());
+ success = true;
+ break;
+ }
+ case e_long_double:
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer);
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer);
+ success = true;
+ break;
+ }
}
break;
case e_slong:
switch (type)
{
- case e_void:
- case e_sint:
- case e_uint: break;
- case e_slong: success = true; break;
- case e_ulong: m_data.ulong = m_data.slong; success = true; break;
- case e_slonglong: m_data.slonglong = m_data.slong; success = true; break;
- case e_ulonglong: m_data.ulonglong = m_data.slong; success = true; break;
- case e_float: m_data.flt = m_data.slong; success = true; break;
- case e_double: m_data.dbl = m_data.slong; success = true; break;
- case e_long_double: m_data.ldbl = m_data.slong; success = true; break;
+ case e_void:
+ case e_sint:
+ case e_uint: break;
+ case e_slong: success = true; break;
+ case e_ulong:
+ {
+ m_integer = llvm::APInt(sizeof(ulong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false);
+ success = true;
+ break;
+ }
+ case e_slonglong:
+ {
+ m_integer = llvm::APInt(sizeof(slonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true);
+ success = true;
+ break;
+ }
+ case e_ulonglong:
+ {
+ m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false);
+ success = true;
+ break;
+ }
+ case e_sint128:
+ case e_uint128:
+ {
+ m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData()));
+ success = true;
+ break;
+ }
+ case e_float:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToFloat());
+ success = true;
+ break;
+ }
+ case e_double:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToDouble());
+ success = true;
+ break;
+ }
+ case e_long_double:
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer);
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer);
+ success = true;
+ break;
+ }
}
break;
case e_ulong:
switch (type)
{
- case e_void:
- case e_sint:
- case e_uint:
- case e_slong: break;
- case e_ulong: success = true; break;
- case e_slonglong: m_data.slonglong = m_data.ulong; success = true; break;
- case e_ulonglong: m_data.ulonglong = m_data.ulong; success = true; break;
- case e_float: m_data.flt = m_data.ulong; success = true; break;
- case e_double: m_data.dbl = m_data.ulong; success = true; break;
- case e_long_double: m_data.ldbl = m_data.ulong; success = true; break;
+ case e_void:
+ case e_sint:
+ case e_uint:
+ case e_slong: break;
+ case e_ulong: success = true; break;
+ case e_slonglong:
+ {
+ m_integer = llvm::APInt(sizeof(slonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true);
+ success = true;
+ break;
+ }
+ case e_ulonglong:
+ {
+ m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false);
+ success = true;
+ break;
+ }
+ case e_sint128:
+ case e_uint128:
+ {
+ m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData()));
+ success = true;
+ break;
+ }
+ case e_float:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToFloat());
+ success = true;
+ break;
+ }
+ case e_double:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToDouble());
+ success = true;
+ break;
+ }
+ case e_long_double:
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer);
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer);
+ success = true;
+ break;
+ }
}
break;
case e_slonglong:
switch (type)
{
- case e_void:
- case e_sint:
- case e_uint:
- case e_slong:
- case e_ulong: break;
- case e_slonglong: success = true; break;
- case e_ulonglong: m_data.ulonglong = m_data.slonglong; success = true; break;
- case e_float: m_data.flt = m_data.slonglong; success = true; break;
- case e_double: m_data.dbl = m_data.slonglong; success = true; break;
- case e_long_double: m_data.ldbl = m_data.slonglong; success = true; break;
+ case e_void:
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong: break;
+ case e_slonglong: success = true; break;
+ case e_ulonglong:
+ {
+ m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false);
+ success = true;
+ break;
+ }
+ case e_sint128:
+ case e_uint128:
+ {
+ m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData()));
+ success = true;
+ break;
+ }
+ case e_float:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToFloat());
+ success = true;
+ break;
+ }
+ case e_double:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToDouble());
+ success = true;
+ break;
+ }
+ case e_long_double:
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer);
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer);
+ success = true;
+ break;
+ }
}
break;
case e_ulonglong:
switch (type)
{
- case e_void:
- case e_sint:
- case e_uint:
- case e_slong:
- case e_ulong:
- case e_slonglong: break;
- case e_ulonglong: success = true; break;
- case e_float: m_data.flt = m_data.ulonglong; success = true; break;
- case e_double: m_data.dbl = m_data.ulonglong; success = true; break;
- case e_long_double: m_data.ldbl = m_data.ulonglong; success = true; break;
+ case e_void:
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong: break;
+ case e_ulonglong: success = true; break;
+ case e_sint128:
+ case e_uint128:
+ {
+ m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData()));
+ success = true;
+ break;
+ }
+ case e_float:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToFloat());
+ success = true;
+ break;
+ }
+ case e_double:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToDouble());
+ success = true;
+ break;
+ }
+ case e_long_double:
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer);
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer);
+ success = true;
+ break;
+ }
+ }
+ break;
+
+ case e_sint128:
+ switch (type)
+ {
+ case e_void:
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong: break;
+ case e_sint128: success = true; break;
+ case e_uint128:
+ {
+ m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData()));
+ success = true;
+ break;
+ }
+ case e_float:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToFloat());
+ success = true;
+ break;
+ }
+ case e_double:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToDouble());
+ success = true;
+ break;
+ }
+ case e_long_double:
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer);
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer);
+ success = true;
+ break;
+ }
+ }
+ break;
+
+ case e_uint128:
+ switch (type)
+ {
+ case e_void:
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128: break;
+ case e_uint128: success = true; break;
+ case e_float:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToFloat());
+ success = true;
+ break;
+ }
+ case e_double:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToDouble());
+ success = true;
+ break;
+ }
+ case e_long_double:
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer);
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer);
+ success = true;
+ break;
+ }
}
break;
case e_float:
switch (type)
{
- case e_void:
- case e_sint:
- case e_uint:
- case e_slong:
- case e_ulong:
- case e_slonglong:
- case e_ulonglong: break;
- case e_float: success = true; break;
- case e_double: m_data.dbl = m_data.flt; success = true; break;
- case e_long_double: m_data.ldbl = m_data.ulonglong; success = true; break;
+ case e_void:
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128: break;
+ case e_float: success = true; break;
+ case e_double:
+ {
+ m_float = llvm::APFloat((float_t)m_float.convertToFloat());
+ success = true;
+ break;
+ }
+ case e_long_double:
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt());
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt());
+ success = true;
+ break;
+ }
}
break;
case e_double:
switch (type)
{
- case e_void:
- case e_sint:
- case e_uint:
- case e_slong:
- case e_ulong:
- case e_slonglong:
- case e_ulonglong:
- case e_float: break;
- case e_double: success = true; break;
- case e_long_double: m_data.ldbl = m_data.dbl; success = true; break;
+ case e_void:
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ case e_float: break;
+ case e_double: success = true; break;
+ case e_long_double:
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt());
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt());
+ success = true;
+ break;
+ }
}
break;
@@ -489,6 +984,8 @@ Scalar::Promote(Scalar::Type type)
case e_ulong:
case e_slonglong:
case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
case e_float:
case e_double: break;
case e_long_double: success = true; break;
@@ -516,6 +1013,8 @@ Scalar::GetValueTypeAsCString (Scalar::Type type)
case e_float: return "float";
case e_double: return "double";
case e_long_double: return "long double";
+ case e_sint128: return "int128_t";
+ case e_uint128: return "uint128_t";
}
return "???";
}
@@ -567,145 +1066,198 @@ Scalar::Cast(Scalar::Type type)
break;
case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
switch (type)
{
- case e_void: break;
- case e_sint: success = true; break;
- case e_uint: m_data.uint = m_data.sint; success = true; break;
- case e_slong: m_data.slong = m_data.sint; success = true; break;
- case e_ulong: m_data.ulong = m_data.sint; success = true; break;
- case e_slonglong: m_data.slonglong = m_data.sint; success = true; break;
- case e_ulonglong: m_data.ulonglong = m_data.sint; success = true; break;
- case e_float: m_data.flt = m_data.sint; success = true; break;
- case e_double: m_data.dbl = m_data.sint; success = true; break;
- case e_long_double: m_data.ldbl = m_data.sint; success = true; break;
+ case e_void: break;
+ case e_sint:
+ {
+ m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8);
+ success = true;
+ break;
+ }
+ case e_uint:
+ {
+ m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8);
+ success = true;
+ break;
+ }
+ case e_slong:
+ {
+ m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8);
+ success = true;
+ break;
+ }
+ case e_ulong:
+ {
+ m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8);
+ success = true;
+ break;
+ }
+ case e_slonglong:
+ {
+ m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8);
+ success = true;
+ break;
+ }
+ case e_ulonglong:
+ {
+ m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8);
+ success = true;
+ break;
+ }
+ case e_sint128:
+ {
+ m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128);
+ success = true;
+ break;
+ }
+ case e_uint128:
+ {
+ m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128);
+ success = true;
+ break;
+ }
+ case e_float:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToFloat());
+ success = true;
+ break;
+ }
+ case e_double:
+ {
+ m_float = llvm::APFloat(m_integer.bitsToDouble());
+ success = true;
+ break;
+ }
+ case e_long_double:
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer);
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer);
+ success = true;
+ break;
+ }
}
break;
- case e_uint:
+ case e_float:
switch (type)
{
- case e_void:
- case e_sint: m_data.sint = m_data.uint; success = true; break;
- case e_uint: success = true; break;
- case e_slong: m_data.slong = m_data.uint; success = true; break;
- case e_ulong: m_data.ulong = m_data.uint; success = true; break;
- case e_slonglong: m_data.slonglong = m_data.uint; success = true; break;
- case e_ulonglong: m_data.ulonglong = m_data.uint; success = true; break;
- case e_float: m_data.flt = m_data.uint; success = true; break;
- case e_double: m_data.dbl = m_data.uint; success = true; break;
- case e_long_double: m_data.ldbl = m_data.uint; success = true; break;
+ case e_void: break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128: m_integer = m_float.bitcastToAPInt(); success = true; break;
+ case e_float: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break;
+ case e_double: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break;
+ case e_long_double:
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt());
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt());
+ success = true;
+ break;
}
break;
- case e_slong:
+ case e_double:
switch (type)
{
- case e_void:
- case e_sint: m_data.sint = (sint_t)m_data.slong; success = true; break;
- case e_uint: m_data.uint = (uint_t)m_data.slong; success = true; break;
- case e_slong: success = true; break;
- case e_ulong: m_data.ulong = m_data.slong; success = true; break;
- case e_slonglong: m_data.slonglong = m_data.slong; success = true; break;
- case e_ulonglong: m_data.ulonglong = m_data.slong; success = true; break;
- case e_float: m_data.flt = m_data.slong; success = true; break;
- case e_double: m_data.dbl = m_data.slong; success = true; break;
- case e_long_double: m_data.ldbl = m_data.slong; success = true; break;
+ case e_void: break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128: m_integer = m_float.bitcastToAPInt(); success = true; break;
+ case e_float: m_float = llvm::APFloat(m_float.convertToDouble()); success = true; break;
+ case e_double: m_float = llvm::APFloat(m_float.convertToDouble()); success = true; break;
+ case e_long_double:
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt());
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt());
+ success = true;
+ break;
}
break;
- case e_ulong:
+ case e_long_double:
switch (type)
{
- case e_void:
- case e_sint: m_data.sint = (sint_t)m_data.ulong; success = true; break;
- case e_uint: m_data.uint = (uint_t)m_data.ulong; success = true; break;
- case e_slong: m_data.slong = m_data.ulong; success = true; break;
- case e_ulong: success = true; break;
- case e_slonglong: m_data.slonglong = m_data.ulong; success = true; break;
- case e_ulonglong: m_data.ulonglong = m_data.ulong; success = true; break;
- case e_float: m_data.flt = m_data.ulong; success = true; break;
- case e_double: m_data.dbl = m_data.ulong; success = true; break;
- case e_long_double: m_data.ldbl = m_data.ulong; success = true; break;
+ case e_void: break;
+ case e_sint:
+ {
+ m_integer = m_float.bitcastToAPInt();
+ m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8);
+ success = true;
+ break;
}
- break;
-
- case e_slonglong:
- switch (type)
+ case e_uint:
{
- case e_void:
- case e_sint: m_data.sint = (sint_t)m_data.slonglong; success = true; break;
- case e_uint: m_data.uint = (uint_t)m_data.slonglong; success = true; break;
- case e_slong: m_data.slong = m_data.slonglong; success = true; break;
- case e_ulong: m_data.ulong = m_data.slonglong; success = true; break;
- case e_slonglong: success = true; break;
- case e_ulonglong: m_data.ulonglong = m_data.slonglong; success = true; break;
- case e_float: m_data.flt = m_data.slonglong; success = true; break;
- case e_double: m_data.dbl = m_data.slonglong; success = true; break;
- case e_long_double: m_data.ldbl = m_data.slonglong; success = true; break;
+ m_integer = m_float.bitcastToAPInt();
+ m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8);
+ success = true;
+ break;
}
- break;
-
- case e_ulonglong:
- switch (type)
+ case e_slong:
{
- case e_void:
- case e_sint: m_data.sint = (sint_t)m_data.ulonglong; success = true; break;
- case e_uint: m_data.uint = (uint_t)m_data.ulonglong; success = true; break;
- case e_slong: m_data.slong = m_data.ulonglong; success = true; break;
- case e_ulong: m_data.ulong = m_data.ulonglong; success = true; break;
- case e_slonglong: m_data.slonglong = m_data.ulonglong; success = true; break;
- case e_ulonglong: success = true; break;
- case e_float: m_data.flt = m_data.ulonglong; success = true; break;
- case e_double: m_data.dbl = m_data.ulonglong; success = true; break;
- case e_long_double: m_data.ldbl = m_data.ulonglong; success = true; break;
+ m_integer = m_float.bitcastToAPInt();
+ m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8);
+ success = true;
+ break;
}
- break;
-
- case e_float:
- switch (type)
+ case e_ulong:
{
- case e_void:
- case e_sint: m_data.sint = (sint_t)m_data.flt; success = true; break;
- case e_uint: m_data.uint = (uint_t)m_data.flt; success = true; break;
- case e_slong: m_data.slong = (slong_t)m_data.flt; success = true; break;
- case e_ulong: m_data.ulong = (ulong_t)m_data.flt; success = true; break;
- case e_slonglong: m_data.slonglong = (slonglong_t)m_data.flt; success = true; break;
- case e_ulonglong: m_data.ulonglong = (ulonglong_t)m_data.flt; success = true; break;
- case e_float: success = true; break;
- case e_double: m_data.dbl = m_data.flt; success = true; break;
- case e_long_double: m_data.ldbl = m_data.flt; success = true; break;
+ m_integer = m_float.bitcastToAPInt();
+ m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8);
+ success = true;
+ break;
}
- break;
-
- case e_double:
- switch (type)
+ case e_slonglong:
{
- case e_void:
- case e_sint: m_data.sint = (sint_t)m_data.dbl; success = true; break;
- case e_uint: m_data.uint = (uint_t)m_data.dbl; success = true; break;
- case e_slong: m_data.slong = (slong_t)m_data.dbl; success = true; break;
- case e_ulong: m_data.ulong = (ulong_t)m_data.dbl; success = true; break;
- case e_slonglong: m_data.slonglong = (slonglong_t)m_data.dbl; success = true; break;
- case e_ulonglong: m_data.ulonglong = (ulonglong_t)m_data.dbl; success = true; break;
- case e_float: m_data.flt = (float_t)m_data.dbl; success = true; break;
- case e_double: success = true; break;
- case e_long_double: m_data.ldbl = m_data.dbl; success = true; break;
+ m_integer = m_float.bitcastToAPInt();
+ m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8);
+ success = true;
+ break;
}
- break;
-
- case e_long_double:
- switch (type)
+ case e_ulonglong:
{
- case e_void:
- case e_sint: m_data.sint = (sint_t)m_data.ldbl; success = true; break;
- case e_uint: m_data.uint = (uint_t)m_data.ldbl; success = true; break;
- case e_slong: m_data.slong = (slong_t)m_data.ldbl; success = true; break;
- case e_ulong: m_data.ulong = (ulong_t)m_data.ldbl; success = true; break;
- case e_slonglong: m_data.slonglong = (slonglong_t)m_data.ldbl; success = true; break;
- case e_ulonglong: m_data.ulonglong = (ulonglong_t)m_data.ldbl; success = true; break;
- case e_float: m_data.flt = (float_t)m_data.ldbl; success = true; break;
- case e_double: m_data.dbl = (double_t)m_data.ldbl; success = true; break;
+ m_integer = m_float.bitcastToAPInt();
+ m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8);
+ success = true;
+ break;
+ }
+ case e_sint128:
+ {
+ m_integer = m_float.bitcastToAPInt();
+ m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128);
+ success = true;
+ break;
+ }
+ case e_uint128:
+ {
+ m_integer = m_float.bitcastToAPInt();
+ m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128);
+ success = true;
+ break;
+ }
+ case e_float: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break;
+ case e_double: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break;
case e_long_double: success = true; break;
}
break;
@@ -730,6 +1282,8 @@ Scalar::MakeSigned ()
case e_ulong: m_type = e_slong; success = true; break;
case e_slonglong: success = true; break;
case e_ulonglong: m_type = e_slonglong; success = true; break;
+ case e_sint128: success = true; break;
+ case e_uint128: m_type = e_sint; success = true; break;
case e_float: success = true; break;
case e_double: success = true; break;
case e_long_double: success = true; break;
@@ -738,21 +1292,132 @@ Scalar::MakeSigned ()
return success;
}
+char
+Scalar::SChar(char fail_value) const
+{
+ switch (m_type)
+ {
+ case e_void: break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return *(const schar_t *)(m_integer.sextOrTrunc(sizeof(schar_t) * 8)).getRawData();
+ case e_float:
+ return (schar_t)m_float.convertToFloat();
+ case e_double:
+ return (schar_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return (schar_t)*ldbl_val.getRawData();
+ }
+ return fail_value;
+}
+
+unsigned char
+Scalar::UChar(unsigned char fail_value) const
+{
+ switch (m_type)
+ {
+ case e_void: break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return *(const uchar_t *)m_integer.getRawData();
+ case e_float:
+ return (uchar_t)m_float.convertToFloat();
+ case e_double:
+ return (uchar_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return (uchar_t)*ldbl_val.getRawData();
+ }
+ return fail_value;
+}
+
+short
+Scalar::SShort(short fail_value) const
+{
+ switch (m_type)
+ {
+ case e_void: break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return *(const sshort_t *)(m_integer.sextOrTrunc(sizeof(sshort_t) * 8)).getRawData();
+ case e_float:
+ return (sshort_t)m_float.convertToFloat();
+ case e_double:
+ return (sshort_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return *(const sshort_t *)ldbl_val.getRawData();
+ }
+ return fail_value;
+}
+
+unsigned short
+Scalar::UShort(unsigned short fail_value) const
+{
+ switch (m_type)
+ {
+ case e_void: break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return *(const ushort_t *)m_integer.getRawData();
+ case e_float:
+ return (ushort_t)m_float.convertToFloat();
+ case e_double:
+ return (ushort_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return *(const ushort_t *)ldbl_val.getRawData();;
+ }
+ return fail_value;
+}
+
int
Scalar::SInt(int fail_value) const
{
switch (m_type)
{
case e_void: break;
- case e_sint: return m_data.sint;
- case e_uint: return (int)m_data.uint;
- case e_slong: return (int)m_data.slong;
- case e_ulong: return (int)m_data.ulong;
- case e_slonglong: return (int)m_data.slonglong;
- case e_ulonglong: return (int)m_data.ulonglong;
- case e_float: return (int)m_data.flt;
- case e_double: return (int)m_data.dbl;
- case e_long_double: return (int)m_data.ldbl;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return *(const sint_t *)(m_integer.sextOrTrunc(sizeof(sint_t) * 8)).getRawData();
+ case e_float:
+ return (sint_t)m_float.convertToFloat();
+ case e_double:
+ return (sint_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return *(const sint_t *)ldbl_val.getRawData();
}
return fail_value;
}
@@ -763,15 +1428,22 @@ Scalar::UInt(unsigned int fail_value) const
switch (m_type)
{
case e_void: break;
- case e_sint: return (unsigned int)m_data.sint;
- case e_uint: return (unsigned int)m_data.uint;
- case e_slong: return (unsigned int)m_data.slong;
- case e_ulong: return (unsigned int)m_data.ulong;
- case e_slonglong: return (unsigned int)m_data.slonglong;
- case e_ulonglong: return (unsigned int)m_data.ulonglong;
- case e_float: return (unsigned int)m_data.flt;
- case e_double: return (unsigned int)m_data.dbl;
- case e_long_double: return (unsigned int)m_data.ldbl;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return *(const uint_t *)m_integer.getRawData();
+ case e_float:
+ return (uint_t)m_float.convertToFloat();
+ case e_double:
+ return (uint_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return *(const uint_t *)ldbl_val.getRawData();
}
return fail_value;
}
@@ -783,15 +1455,22 @@ Scalar::SLong(long fail_value) const
switch (m_type)
{
case e_void: break;
- case e_sint: return (long)m_data.sint;
- case e_uint: return (long)m_data.uint;
- case e_slong: return (long)m_data.slong;
- case e_ulong: return (long)m_data.ulong;
- case e_slonglong: return (long)m_data.slonglong;
- case e_ulonglong: return (long)m_data.ulonglong;
- case e_float: return (long)m_data.flt;
- case e_double: return (long)m_data.dbl;
- case e_long_double: return (long)m_data.ldbl;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return *(const slong_t *)(m_integer.sextOrTrunc(sizeof(slong_t) * 8)).getRawData();
+ case e_float:
+ return (slong_t)m_float.convertToFloat();
+ case e_double:
+ return (slong_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return *(const slong_t *)ldbl_val.getRawData();
}
return fail_value;
}
@@ -804,15 +1483,22 @@ Scalar::ULong(unsigned long fail_value) const
switch (m_type)
{
case e_void: break;
- case e_sint: return (unsigned long)m_data.sint;
- case e_uint: return (unsigned long)m_data.uint;
- case e_slong: return (unsigned long)m_data.slong;
- case e_ulong: return (unsigned long)m_data.ulong;
- case e_slonglong: return (unsigned long)m_data.slonglong;
- case e_ulonglong: return (unsigned long)m_data.ulonglong;
- case e_float: return (unsigned long)m_data.flt;
- case e_double: return (unsigned long)m_data.dbl;
- case e_long_double: return (unsigned long)m_data.ldbl;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return *(const ulong_t *)m_integer.getRawData();
+ case e_float:
+ return (ulong_t)m_float.convertToFloat();
+ case e_double:
+ return (ulong_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return *(const ulong_t *)ldbl_val.getRawData();
}
return fail_value;
}
@@ -827,42 +1513,20 @@ Scalar::GetRawBits64(uint64_t fail_value) const
case e_sint:
case e_uint:
- return m_data.uint;
-
case e_slong:
case e_ulong:
- return m_data.ulong;
-
case e_slonglong:
case e_ulonglong:
- return m_data.ulonglong;
-
+ case e_sint128:
+ case e_uint128:
+ return *m_integer.getRawData();
case e_float:
- if (sizeof(m_data.flt) == sizeof(m_data.uint))
- return m_data.uint;
- else if (sizeof(m_data.flt) == sizeof(m_data.ulong))
- return m_data.ulong;
- else if (sizeof(m_data.flt) == sizeof(m_data.ulonglong))
- return m_data.ulonglong;
- break;
-
+ return (uint64_t)m_float.convertToFloat();
case e_double:
- if (sizeof(m_data.dbl) == sizeof(m_data.uint))
- return m_data.uint;
- else if (sizeof(m_data.dbl) == sizeof(m_data.ulong))
- return m_data.ulong;
- else if (sizeof(m_data.dbl) == sizeof(m_data.ulonglong))
- return m_data.ulonglong;
- break;
-
+ return (uint64_t)m_float.convertToDouble();
case e_long_double:
- if (sizeof(m_data.ldbl) == sizeof(m_data.uint))
- return m_data.uint;
- else if (sizeof(m_data.ldbl) == sizeof(m_data.ulong))
- return m_data.ulong;
- else if (sizeof(m_data.ldbl) == sizeof(m_data.ulonglong))
- return m_data.ulonglong;
- break;
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return *ldbl_val.getRawData();
}
return fail_value;
}
@@ -875,15 +1539,22 @@ Scalar::SLongLong(long long fail_value) const
switch (m_type)
{
case e_void: break;
- case e_sint: return (long long)m_data.sint;
- case e_uint: return (long long)m_data.uint;
- case e_slong: return (long long)m_data.slong;
- case e_ulong: return (long long)m_data.ulong;
- case e_slonglong: return (long long)m_data.slonglong;
- case e_ulonglong: return (long long)m_data.ulonglong;
- case e_float: return (long long)m_data.flt;
- case e_double: return (long long)m_data.dbl;
- case e_long_double: return (long long)m_data.ldbl;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return *(const slonglong_t *)(m_integer.sextOrTrunc(sizeof(slonglong_t) * 8)).getRawData();
+ case e_float:
+ return (slonglong_t)m_float.convertToFloat();
+ case e_double:
+ return (slonglong_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return *(const slonglong_t *)ldbl_val.getRawData();
}
return fail_value;
}
@@ -895,19 +1566,71 @@ Scalar::ULongLong(unsigned long long fail_value) const
switch (m_type)
{
case e_void: break;
- case e_sint: return (unsigned long long)m_data.sint;
- case e_uint: return (unsigned long long)m_data.uint;
- case e_slong: return (unsigned long long)m_data.slong;
- case e_ulong: return (unsigned long long)m_data.ulong;
- case e_slonglong: return (unsigned long long)m_data.slonglong;
- case e_ulonglong: return (unsigned long long)m_data.ulonglong;
- case e_float: return (unsigned long long)m_data.flt;
- case e_double: return (unsigned long long)m_data.dbl;
- case e_long_double: return (unsigned long long)m_data.ldbl;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return *(const ulonglong_t *)m_integer.getRawData();
+ case e_float:
+ return (ulonglong_t)m_float.convertToFloat();
+ case e_double:
+ return (ulonglong_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return *(const ulonglong_t *)ldbl_val.getRawData();
}
return fail_value;
}
+llvm::APInt
+Scalar::UInt128(const llvm::APInt& fail_value) const
+{
+ switch (m_type)
+ {
+ case e_void: break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return m_integer;
+ case e_float:
+ case e_double:
+ case e_long_double:
+ return m_float.bitcastToAPInt();
+ }
+ return fail_value;
+}
+
+llvm::APInt
+Scalar::SInt128(llvm::APInt& fail_value) const
+{
+ switch (m_type)
+ {
+ case e_void: break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return m_integer;
+ case e_float:
+ case e_double:
+ case e_long_double:
+ return m_float.bitcastToAPInt();
+ }
+ return fail_value;
+}
float
Scalar::Float(float fail_value) const
@@ -915,15 +1638,22 @@ Scalar::Float(float fail_value) const
switch (m_type)
{
case e_void: break;
- case e_sint: return (float)m_data.sint;
- case e_uint: return (float)m_data.uint;
- case e_slong: return (float)m_data.slong;
- case e_ulong: return (float)m_data.ulong;
- case e_slonglong: return (float)m_data.slonglong;
- case e_ulonglong: return (float)m_data.ulonglong;
- case e_float: return (float)m_data.flt;
- case e_double: return (float)m_data.dbl;
- case e_long_double: return (float)m_data.ldbl;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return m_integer.bitsToFloat();
+ case e_float:
+ return m_float.convertToFloat();
+ case e_double:
+ return (float_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return ldbl_val.bitsToFloat();
}
return fail_value;
}
@@ -935,15 +1665,22 @@ Scalar::Double(double fail_value) const
switch (m_type)
{
case e_void: break;
- case e_sint: return (double)m_data.sint;
- case e_uint: return (double)m_data.uint;
- case e_slong: return (double)m_data.slong;
- case e_ulong: return (double)m_data.ulong;
- case e_slonglong: return (double)m_data.slonglong;
- case e_ulonglong: return (double)m_data.ulonglong;
- case e_float: return (double)m_data.flt;
- case e_double: return (double)m_data.dbl;
- case e_long_double: return (double)m_data.ldbl;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return m_integer.bitsToDouble();
+ case e_float:
+ return (double_t)m_float.convertToFloat();
+ case e_double:
+ return m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return ldbl_val.bitsToFloat();
}
return fail_value;
}
@@ -955,15 +1692,22 @@ Scalar::LongDouble(long double fail_value) const
switch (m_type)
{
case e_void: break;
- case e_sint: return (long double)m_data.sint;
- case e_uint: return (long double)m_data.uint;
- case e_slong: return (long double)m_data.slong;
- case e_ulong: return (long double)m_data.ulong;
- case e_slonglong: return (long double)m_data.slonglong;
- case e_ulonglong: return (long double)m_data.ulonglong;
- case e_float: return (long double)m_data.flt;
- case e_double: return (long double)m_data.dbl;
- case e_long_double: return (long double)m_data.ldbl;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ return (long_double_t)m_integer.bitsToDouble();
+ case e_float:
+ return (long_double_t)m_float.convertToFloat();
+ case e_double:
+ return (long_double_t)m_float.convertToDouble();
+ case e_long_double:
+ llvm::APInt ldbl_val = m_float.bitcastToAPInt();
+ return (long_double_t)ldbl_val.bitsToDouble();
}
return fail_value;
}
@@ -978,17 +1722,27 @@ Scalar::operator+= (const Scalar& rhs)
if ((m_type = PromoteToMaxType(*this, rhs, temp_value, a, b)) != Scalar::e_void)
{
switch (m_type)
- {
- case e_void: break;
- case e_sint: m_data.sint = a->m_data.sint + b->m_data.sint; break;
- case e_uint: m_data.uint = a->m_data.uint + b->m_data.uint; break;
- case e_slong: m_data.slong = a->m_data.slong + b->m_data.slong; break;
- case e_ulong: m_data.ulong = a->m_data.ulong + b->m_data.ulong; break;
- case e_slonglong: m_data.slonglong = a->m_data.slonglong + b->m_data.slonglong; break;
- case e_ulonglong: m_data.ulonglong = a->m_data.ulonglong + b->m_data.ulonglong; break;
- case e_float: m_data.flt = a->m_data.flt + b->m_data.flt; break;
- case e_double: m_data.dbl = a->m_data.dbl + b->m_data.dbl; break;
- case e_long_double: m_data.ldbl = a->m_data.ldbl + b->m_data.ldbl; break;
+ {
+ case e_void: break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ {
+ m_integer = a->m_integer + b->m_integer;
+ break;
+ }
+ case e_float:
+ case e_double:
+ case e_long_double:
+ {
+ m_float = a->m_float + b->m_float;
+ break;
+ }
}
}
return *this;
@@ -1007,109 +1761,33 @@ Scalar::operator<<= (const Scalar& rhs)
break;
case e_sint:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.sint <<= rhs.m_data.sint; break;
- case e_uint: m_data.sint <<= rhs.m_data.uint; break;
- case e_slong: m_data.sint <<= rhs.m_data.slong; break;
- case e_ulong: m_data.sint <<= rhs.m_data.ulong; break;
- case e_slonglong: m_data.sint <<= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.sint <<= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_uint:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.uint <<= rhs.m_data.sint; break;
- case e_uint: m_data.uint <<= rhs.m_data.uint; break;
- case e_slong: m_data.uint <<= rhs.m_data.slong; break;
- case e_ulong: m_data.uint <<= rhs.m_data.ulong; break;
- case e_slonglong: m_data.uint <<= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.uint <<= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_slong:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.slong <<= rhs.m_data.sint; break;
- case e_uint: m_data.slong <<= rhs.m_data.uint; break;
- case e_slong: m_data.slong <<= rhs.m_data.slong; break;
- case e_ulong: m_data.slong <<= rhs.m_data.ulong; break;
- case e_slonglong: m_data.slong <<= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.slong <<= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_ulong:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.ulong <<= rhs.m_data.sint; break;
- case e_uint: m_data.ulong <<= rhs.m_data.uint; break;
- case e_slong: m_data.ulong <<= rhs.m_data.slong; break;
- case e_ulong: m_data.ulong <<= rhs.m_data.ulong; break;
- case e_slonglong: m_data.ulong <<= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.ulong <<= rhs.m_data.ulonglong; break;
- }
- break;
case e_slonglong:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.slonglong <<= rhs.m_data.sint; break;
- case e_uint: m_data.slonglong <<= rhs.m_data.uint; break;
- case e_slong: m_data.slonglong <<= rhs.m_data.slong; break;
- case e_ulong: m_data.slonglong <<= rhs.m_data.ulong; break;
- case e_slonglong: m_data.slonglong <<= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.slonglong <<= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
switch (rhs.m_type)
{
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.ulonglong <<= rhs.m_data.sint; break;
- case e_uint: m_data.ulonglong <<= rhs.m_data.uint; break;
- case e_slong: m_data.ulonglong <<= rhs.m_data.slong; break;
- case e_ulong: m_data.ulonglong <<= rhs.m_data.ulong; break;
- case e_slonglong: m_data.ulonglong <<= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.ulonglong <<= rhs.m_data.ulonglong; break;
+ case e_void:
+ case e_float:
+ case e_double:
+ case e_long_double:
+ m_type = e_void;
+ break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ {
+ m_integer <<= *rhs.m_integer.getRawData();
+ break;
+ }
}
break;
}
@@ -1130,44 +1808,12 @@ Scalar::ShiftRightLogical(const Scalar& rhs)
case e_sint:
case e_uint:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.uint >>= rhs.m_data.sint; break;
- case e_uint: m_data.uint >>= rhs.m_data.uint; break;
- case e_slong: m_data.uint >>= rhs.m_data.slong; break;
- case e_ulong: m_data.uint >>= rhs.m_data.ulong; break;
- case e_slonglong: m_data.uint >>= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.uint >>= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_slong:
case e_ulong:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.ulong >>= rhs.m_data.sint; break;
- case e_uint: m_data.ulong >>= rhs.m_data.uint; break;
- case e_slong: m_data.ulong >>= rhs.m_data.slong; break;
- case e_ulong: m_data.ulong >>= rhs.m_data.ulong; break;
- case e_slonglong: m_data.ulong >>= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.ulong >>= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_slonglong:
case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
switch (rhs.m_type)
{
case e_void:
@@ -1176,12 +1822,15 @@ Scalar::ShiftRightLogical(const Scalar& rhs)
case e_long_double:
m_type = e_void;
break;
- case e_sint: m_data.ulonglong >>= rhs.m_data.sint; break;
- case e_uint: m_data.ulonglong >>= rhs.m_data.uint; break;
- case e_slong: m_data.ulonglong >>= rhs.m_data.slong; break;
- case e_ulong: m_data.ulonglong >>= rhs.m_data.ulong; break;
- case e_slonglong: m_data.ulonglong >>= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.ulonglong >>= rhs.m_data.ulonglong; break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ m_integer = m_integer.lshr(*(const uint_t *) rhs.m_integer.getRawData()); break;
}
break;
}
@@ -1202,95 +1851,13 @@ Scalar::operator>>= (const Scalar& rhs)
break;
case e_sint:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.sint >>= rhs.m_data.sint; break;
- case e_uint: m_data.sint >>= rhs.m_data.uint; break;
- case e_slong: m_data.sint >>= rhs.m_data.slong; break;
- case e_ulong: m_data.sint >>= rhs.m_data.ulong; break;
- case e_slonglong: m_data.sint >>= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.sint >>= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_uint:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.uint >>= rhs.m_data.sint; break;
- case e_uint: m_data.uint >>= rhs.m_data.uint; break;
- case e_slong: m_data.uint >>= rhs.m_data.slong; break;
- case e_ulong: m_data.uint >>= rhs.m_data.ulong; break;
- case e_slonglong: m_data.uint >>= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.uint >>= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_slong:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.slong >>= rhs.m_data.sint; break;
- case e_uint: m_data.slong >>= rhs.m_data.uint; break;
- case e_slong: m_data.slong >>= rhs.m_data.slong; break;
- case e_ulong: m_data.slong >>= rhs.m_data.ulong; break;
- case e_slonglong: m_data.slong >>= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.slong >>= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_ulong:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.ulong >>= rhs.m_data.sint; break;
- case e_uint: m_data.ulong >>= rhs.m_data.uint; break;
- case e_slong: m_data.ulong >>= rhs.m_data.slong; break;
- case e_ulong: m_data.ulong >>= rhs.m_data.ulong; break;
- case e_slonglong: m_data.ulong >>= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.ulong >>= rhs.m_data.ulonglong; break;
- }
- break;
case e_slonglong:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.slonglong >>= rhs.m_data.sint; break;
- case e_uint: m_data.slonglong >>= rhs.m_data.uint; break;
- case e_slong: m_data.slonglong >>= rhs.m_data.slong; break;
- case e_ulong: m_data.slonglong >>= rhs.m_data.ulong; break;
- case e_slonglong: m_data.slonglong >>= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.slonglong >>= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
switch (rhs.m_type)
{
case e_void:
@@ -1299,12 +1866,18 @@ Scalar::operator>>= (const Scalar& rhs)
case e_long_double:
m_type = e_void;
break;
- case e_sint: m_data.ulonglong >>= rhs.m_data.sint; break;
- case e_uint: m_data.ulonglong >>= rhs.m_data.uint; break;
- case e_slong: m_data.ulonglong >>= rhs.m_data.slong; break;
- case e_ulong: m_data.ulonglong >>= rhs.m_data.ulong; break;
- case e_slonglong: m_data.ulonglong >>= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.ulonglong >>= rhs.m_data.ulonglong; break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ {
+ m_integer >> *rhs.m_integer.getRawData();
+ break;
+ }
}
break;
}
@@ -1325,95 +1898,13 @@ Scalar::operator&= (const Scalar& rhs)
break;
case e_sint:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.sint &= rhs.m_data.sint; break;
- case e_uint: m_data.sint &= rhs.m_data.uint; break;
- case e_slong: m_data.sint &= rhs.m_data.slong; break;
- case e_ulong: m_data.sint &= rhs.m_data.ulong; break;
- case e_slonglong: m_data.sint &= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.sint &= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_uint:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.uint &= rhs.m_data.sint; break;
- case e_uint: m_data.uint &= rhs.m_data.uint; break;
- case e_slong: m_data.uint &= rhs.m_data.slong; break;
- case e_ulong: m_data.uint &= rhs.m_data.ulong; break;
- case e_slonglong: m_data.uint &= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.uint &= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_slong:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.slong &= rhs.m_data.sint; break;
- case e_uint: m_data.slong &= rhs.m_data.uint; break;
- case e_slong: m_data.slong &= rhs.m_data.slong; break;
- case e_ulong: m_data.slong &= rhs.m_data.ulong; break;
- case e_slonglong: m_data.slong &= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.slong &= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_ulong:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.ulong &= rhs.m_data.sint; break;
- case e_uint: m_data.ulong &= rhs.m_data.uint; break;
- case e_slong: m_data.ulong &= rhs.m_data.slong; break;
- case e_ulong: m_data.ulong &= rhs.m_data.ulong; break;
- case e_slonglong: m_data.ulong &= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.ulong &= rhs.m_data.ulonglong; break;
- }
- break;
case e_slonglong:
- switch (rhs.m_type)
- {
- case e_void:
- case e_float:
- case e_double:
- case e_long_double:
- m_type = e_void;
- break;
- case e_sint: m_data.slonglong &= rhs.m_data.sint; break;
- case e_uint: m_data.slonglong &= rhs.m_data.uint; break;
- case e_slong: m_data.slonglong &= rhs.m_data.slong; break;
- case e_ulong: m_data.slonglong &= rhs.m_data.ulong; break;
- case e_slonglong: m_data.slonglong &= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.slonglong &= rhs.m_data.ulonglong; break;
- }
- break;
-
case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
switch (rhs.m_type)
{
case e_void:
@@ -1422,12 +1913,18 @@ Scalar::operator&= (const Scalar& rhs)
case e_long_double:
m_type = e_void;
break;
- case e_sint: m_data.ulonglong &= rhs.m_data.sint; break;
- case e_uint: m_data.ulonglong &= rhs.m_data.uint; break;
- case e_slong: m_data.ulonglong &= rhs.m_data.slong; break;
- case e_ulong: m_data.ulonglong &= rhs.m_data.ulong; break;
- case e_slonglong: m_data.ulonglong &= rhs.m_data.slonglong; break;
- case e_ulonglong: m_data.ulonglong &= rhs.m_data.ulonglong; break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ {
+ m_integer &= rhs.m_integer;
+ break;
+ }
}
break;
}
@@ -1445,26 +1942,22 @@ Scalar::AbsoluteValue()
break;
case e_sint:
- if (m_data.sint < 0)
- m_data.sint = -m_data.sint;
- return true;
-
case e_slong:
- if (m_data.slong < 0)
- m_data.slong = -m_data.slong;
- return true;
-
case e_slonglong:
- if (m_data.slonglong < 0)
- m_data.slonglong = -m_data.slonglong;
+ case e_sint128:
+ if (m_integer.isNegative())
+ m_integer = -m_integer;
return true;
case e_uint:
case e_ulong:
case e_ulonglong: return true;
- case e_float: m_data.flt = fabsf(m_data.flt); return true;
- case e_double: m_data.dbl = fabs(m_data.dbl); return true;
- case e_long_double: m_data.ldbl = fabsl(m_data.ldbl); return true;
+ case e_uint128:
+ case e_float:
+ case e_double:
+ case e_long_double:
+ m_float.clearSign();
+ return true;
}
return false;
}
@@ -1476,15 +1969,19 @@ Scalar::UnaryNegate()
switch (m_type)
{
case e_void: break;
- case e_sint: m_data.sint = -m_data.sint; return true;
- case e_uint: m_data.uint = -m_data.uint; return true;
- case e_slong: m_data.slong = -m_data.slong; return true;
- case e_ulong: m_data.ulong = -m_data.ulong; return true;
- case e_slonglong: m_data.slonglong = -m_data.slonglong; return true;
- case e_ulonglong: m_data.ulonglong = -m_data.ulonglong; return true;
- case e_float: m_data.flt = -m_data.flt; return true;
- case e_double: m_data.dbl = -m_data.dbl; return true;
- case e_long_double: m_data.ldbl = -m_data.ldbl; return true;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ m_integer = -m_integer; return true;
+ case e_float:
+ case e_double:
+ case e_long_double:
+ m_float.changeSign(); return true;
}
return false;
}
@@ -1494,12 +1991,15 @@ Scalar::OnesComplement()
{
switch (m_type)
{
- case e_sint: m_data.sint = ~m_data.sint; return true;
- case e_uint: m_data.uint = ~m_data.uint; return true;
- case e_slong: m_data.slong = ~m_data.slong; return true;
- case e_ulong: m_data.ulong = ~m_data.ulong; return true;
- case e_slonglong: m_data.slonglong = ~m_data.slonglong; return true;
- case e_ulonglong: m_data.ulonglong = ~m_data.ulonglong; return true;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128:
+ m_integer = ~m_integer; return true;
case e_void:
case e_float:
@@ -1523,15 +2023,19 @@ lldb_private::operator+ (const Scalar& lhs, const Scalar& rhs)
switch (result.m_type)
{
case Scalar::e_void: break;
- case Scalar::e_sint: result.m_data.sint = a->m_data.sint + b->m_data.sint; break;
- case Scalar::e_uint: result.m_data.uint = a->m_data.uint + b->m_data.uint; break;
- case Scalar::e_slong: result.m_data.slong = a->m_data.slong + b->m_data.slong; break;
- case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong + b->m_data.ulong; break;
- case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong + b->m_data.slonglong; break;
- case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong + b->m_data.ulonglong; break;
- case Scalar::e_float: result.m_data.flt = a->m_data.flt + b->m_data.flt; break;
- case Scalar::e_double: result.m_data.dbl = a->m_data.dbl + b->m_data.dbl; break;
- case Scalar::e_long_double: result.m_data.ldbl = a->m_data.ldbl + b->m_data.ldbl; break;
+ case Scalar::e_sint:
+ case Scalar::e_uint:
+ case Scalar::e_slong:
+ case Scalar::e_ulong:
+ case Scalar::e_slonglong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_sint128:
+ case Scalar::e_uint128:
+ result.m_integer = a->m_integer + b->m_integer; break;
+ case Scalar::e_float:
+ case Scalar::e_double:
+ case Scalar::e_long_double:
+ result.m_float = a->m_float + b->m_float; break;
}
}
return result;
@@ -1550,15 +2054,19 @@ lldb_private::operator- (const Scalar& lhs, const Scalar& rhs)
switch (result.m_type)
{
case Scalar::e_void: break;
- case Scalar::e_sint: result.m_data.sint = a->m_data.sint - b->m_data.sint; break;
- case Scalar::e_uint: result.m_data.uint = a->m_data.uint - b->m_data.uint; break;
- case Scalar::e_slong: result.m_data.slong = a->m_data.slong - b->m_data.slong; break;
- case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong - b->m_data.ulong; break;
- case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong - b->m_data.slonglong; break;
- case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong - b->m_data.ulonglong; break;
- case Scalar::e_float: result.m_data.flt = a->m_data.flt - b->m_data.flt; break;
- case Scalar::e_double: result.m_data.dbl = a->m_data.dbl - b->m_data.dbl; break;
- case Scalar::e_long_double: result.m_data.ldbl = a->m_data.ldbl - b->m_data.ldbl; break;
+ case Scalar::e_sint:
+ case Scalar::e_uint:
+ case Scalar::e_slong:
+ case Scalar::e_ulong:
+ case Scalar::e_slonglong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_sint128:
+ case Scalar::e_uint128:
+ result.m_integer = a->m_integer - b->m_integer; break;
+ case Scalar::e_float:
+ case Scalar::e_double:
+ case Scalar::e_long_double:
+ result.m_float = a->m_float - b->m_float; break;
}
}
return result;
@@ -1576,16 +2084,31 @@ lldb_private::operator/ (const Scalar& lhs, const Scalar& rhs)
switch (result.m_type)
{
case Scalar::e_void: break;
-
- case Scalar::e_sint: if (b->m_data.sint != 0) { result.m_data.sint = a->m_data.sint/ b->m_data.sint; return result; } break;
- case Scalar::e_uint: if (b->m_data.uint != 0) { result.m_data.uint = a->m_data.uint / b->m_data.uint; return result; } break;
- case Scalar::e_slong: if (b->m_data.slong != 0) { result.m_data.slong = a->m_data.slong / b->m_data.slong; return result; } break;
- case Scalar::e_ulong: if (b->m_data.ulong != 0) { result.m_data.ulong = a->m_data.ulong / b->m_data.ulong; return result; } break;
- case Scalar::e_slonglong: if (b->m_data.slonglong != 0) { result.m_data.slonglong = a->m_data.slonglong / b->m_data.slonglong; return result; } break;
- case Scalar::e_ulonglong: if (b->m_data.ulonglong != 0) { result.m_data.ulonglong = a->m_data.ulonglong / b->m_data.ulonglong; return result; } break;
- case Scalar::e_float: if (b->m_data.flt != 0.0f) { result.m_data.flt = a->m_data.flt / b->m_data.flt; return result; } break;
- case Scalar::e_double: if (b->m_data.dbl != 0.0) { result.m_data.dbl = a->m_data.dbl / b->m_data.dbl; return result; } break;
- case Scalar::e_long_double: if (b->m_data.ldbl != 0.0) { result.m_data.ldbl = a->m_data.ldbl / b->m_data.ldbl; return result; } break;
+ case Scalar::e_sint:
+ case Scalar::e_uint:
+ case Scalar::e_slong:
+ case Scalar::e_ulong:
+ case Scalar::e_slonglong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_sint128:
+ case Scalar::e_uint128:
+ {
+ if (b->m_integer != 0)
+ {
+ result.m_integer = *a->m_integer.getRawData() / *b->m_integer.getRawData();
+ return result;
+ }
+ break;
+ }
+ case Scalar::e_float:
+ case Scalar::e_double:
+ case Scalar::e_long_double:
+ if (b->m_float.isZero())
+ {
+ result.m_float = a->m_float / b->m_float;
+ return result;
+ }
+ break;
}
}
// For division only, the only way it should make it here is if a promotion failed,
@@ -1606,15 +2129,19 @@ lldb_private::operator* (const Scalar& lhs, const Scalar& rhs)
switch (result.m_type)
{
case Scalar::e_void: break;
- case Scalar::e_sint: result.m_data.sint = a->m_data.sint * b->m_data.sint; break;
- case Scalar::e_uint: result.m_data.uint = a->m_data.uint * b->m_data.uint; break;
- case Scalar::e_slong: result.m_data.slong = a->m_data.slong * b->m_data.slong; break;
- case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong * b->m_data.ulong; break;
- case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong * b->m_data.slonglong; break;
- case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong * b->m_data.ulonglong; break;
- case Scalar::e_float: result.m_data.flt = a->m_data.flt * b->m_data.flt; break;
- case Scalar::e_double: result.m_data.dbl = a->m_data.dbl * b->m_data.dbl; break;
- case Scalar::e_long_double: result.m_data.ldbl = a->m_data.ldbl * b->m_data.ldbl; break;
+ case Scalar::e_sint:
+ case Scalar::e_uint:
+ case Scalar::e_slong:
+ case Scalar::e_ulong:
+ case Scalar::e_slonglong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_sint128:
+ case Scalar::e_uint128:
+ result.m_integer = a->m_integer * b->m_integer; break;
+ case Scalar::e_float:
+ case Scalar::e_double:
+ case Scalar::e_long_double:
+ result.m_float = a->m_float * b->m_float; break;
}
}
return result;
@@ -1631,13 +2158,15 @@ lldb_private::operator& (const Scalar& lhs, const Scalar& rhs)
{
switch (result.m_type)
{
- case Scalar::e_sint: result.m_data.sint = a->m_data.sint & b->m_data.sint; break;
- case Scalar::e_uint: result.m_data.uint = a->m_data.uint & b->m_data.uint; break;
- case Scalar::e_slong: result.m_data.slong = a->m_data.slong & b->m_data.slong; break;
- case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong & b->m_data.ulong; break;
- case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong & b->m_data.slonglong; break;
- case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong & b->m_data.ulonglong; break;
-
+ case Scalar::e_sint:
+ case Scalar::e_uint:
+ case Scalar::e_slong:
+ case Scalar::e_ulong:
+ case Scalar::e_slonglong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_sint128:
+ case Scalar::e_uint128:
+ result.m_integer = a->m_integer & b->m_integer; break;
case Scalar::e_void:
case Scalar::e_float:
case Scalar::e_double:
@@ -1661,12 +2190,15 @@ lldb_private::operator| (const Scalar& lhs, const Scalar& rhs)
{
switch (result.m_type)
{
- case Scalar::e_sint: result.m_data.sint = a->m_data.sint | b->m_data.sint; break;
- case Scalar::e_uint: result.m_data.uint = a->m_data.uint | b->m_data.uint; break;
- case Scalar::e_slong: result.m_data.slong = a->m_data.slong | b->m_data.slong; break;
- case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong | b->m_data.ulong; break;
- case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong | b->m_data.slonglong; break;
- case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong | b->m_data.ulonglong; break;
+ case Scalar::e_sint:
+ case Scalar::e_uint:
+ case Scalar::e_slong:
+ case Scalar::e_ulong:
+ case Scalar::e_slonglong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_sint128:
+ case Scalar::e_uint128:
+ result.m_integer = a->m_integer | b->m_integer; break;
case Scalar::e_void:
case Scalar::e_float:
@@ -1692,12 +2224,23 @@ lldb_private::operator% (const Scalar& lhs, const Scalar& rhs)
switch (result.m_type)
{
default: break;
- case Scalar::e_sint: if (b->m_data.sint != 0) { result.m_data.sint = a->m_data.sint % b->m_data.sint; return result; } break;
- case Scalar::e_uint: if (b->m_data.uint != 0) { result.m_data.uint = a->m_data.uint % b->m_data.uint; return result; } break;
- case Scalar::e_slong: if (b->m_data.slong != 0) { result.m_data.slong = a->m_data.slong % b->m_data.slong; return result; } break;
- case Scalar::e_ulong: if (b->m_data.ulong != 0) { result.m_data.ulong = a->m_data.ulong % b->m_data.ulong; return result; } break;
- case Scalar::e_slonglong: if (b->m_data.slonglong != 0) { result.m_data.slonglong = a->m_data.slonglong % b->m_data.slonglong; return result; } break;
- case Scalar::e_ulonglong: if (b->m_data.ulonglong != 0) { result.m_data.ulonglong = a->m_data.ulonglong % b->m_data.ulonglong; return result; } break;
+ case Scalar::e_void: break;
+ case Scalar::e_sint:
+ case Scalar::e_uint:
+ case Scalar::e_slong:
+ case Scalar::e_ulong:
+ case Scalar::e_slonglong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_sint128:
+ case Scalar::e_uint128:
+ {
+ if (b->m_integer != 0)
+ {
+ result.m_integer = *a->m_integer.getRawData() % *b->m_integer.getRawData();
+ return result;
+ }
+ break;
+ }
}
}
result.m_type = Scalar::e_void;
@@ -1715,12 +2258,15 @@ lldb_private::operator^ (const Scalar& lhs, const Scalar& rhs)
{
switch (result.m_type)
{
- case Scalar::e_sint: result.m_data.sint = a->m_data.sint ^ b->m_data.sint; break;
- case Scalar::e_uint: result.m_data.uint = a->m_data.uint ^ b->m_data.uint; break;
- case Scalar::e_slong: result.m_data.slong = a->m_data.slong ^ b->m_data.slong; break;
- case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong ^ b->m_data.ulong; break;
- case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong ^ b->m_data.slonglong; break;
- case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong ^ b->m_data.ulonglong; break;
+ case Scalar::e_sint:
+ case Scalar::e_uint:
+ case Scalar::e_slong:
+ case Scalar::e_ulong:
+ case Scalar::e_slonglong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_sint128:
+ case Scalar::e_uint128:
+ result.m_integer = a->m_integer ^ b->m_integer; break;
case Scalar::e_void:
case Scalar::e_float:
@@ -1754,21 +2300,21 @@ lldb_private::operator>> (const Scalar& lhs, const Scalar &rhs)
unsigned int
Scalar::RawUInt () const
{
- return m_data.uint;
+ return *(const uint_t *) m_integer.getRawData();
}
// Return the raw unsigned long without any casting or conversion
unsigned long
Scalar::RawULong () const
{
- return m_data.ulong;
+ return *(const ulong_t *) m_integer.getRawData();
}
// Return the raw unsigned long long without any casting or conversion
unsigned long long
Scalar::RawULongLong () const
{
- return m_data.ulonglong;
+ return *(const ulonglong_t *) m_integer.getRawData();
}
@@ -1801,9 +2347,9 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by
m_type = Scalar::GetValueTypeForUnsignedIntegerWithByteSize (byte_size);
switch (m_type)
{
- case e_uint: m_data.uint = (uint_t)uval64; break;
- case e_ulong: m_data.ulong = (ulong_t)uval64; break;
- case e_ulonglong: m_data.ulonglong = (ulonglong_t)uval64; break;
+ case e_uint: m_integer = llvm::APInt(sizeof(uint_t) * 8, uval64, false); break;
+ case e_ulong: m_integer = llvm::APInt(sizeof(ulong_t) * 8, uval64, false); break;
+ case e_ulonglong: m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, uval64, false); break;
default:
error.SetErrorStringWithFormat("unsupported unsigned integer byte size: %" PRIu64 "", (uint64_t)byte_size);
break;
@@ -1830,9 +2376,9 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by
m_type = Scalar::GetValueTypeForSignedIntegerWithByteSize (byte_size);
switch (m_type)
{
- case e_sint: m_data.sint = (sint_t)sval64; break;
- case e_slong: m_data.slong = (slong_t)sval64; break;
- case e_slonglong: m_data.slonglong = (slonglong_t)sval64; break;
+ case e_sint: m_integer = llvm::APInt(sizeof(sint_t) * 8, sval64, true); break;
+ case e_slong: m_integer = llvm::APInt(sizeof(slong_t) * 8, sval64, true); break;
+ case e_slonglong: m_integer = llvm::APInt(sizeof(slonglong_t) * 8, sval64, true); break;
default:
error.SetErrorStringWithFormat("unsupported signed integer byte size: %" PRIu64 "", (uint64_t)byte_size);
break;
@@ -1847,24 +2393,36 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by
break;
case eEncodingIEEE754:
+ static float f_val;
+ static double d_val;
+ static long double l_val;
if (byte_size == sizeof (float))
{
- if (::sscanf (value_str, "%f", &m_data.flt) == 1)
+ if (::sscanf (value_str, "%f", &f_val) == 1)
+ {
+ m_float = llvm::APFloat(f_val);
m_type = e_float;
+ }
else
error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str);
}
else if (byte_size == sizeof (double))
{
- if (::sscanf (value_str, "%lf", &m_data.dbl) == 1)
+ if (::sscanf (value_str, "%lf", &d_val) == 1)
+ {
+ m_float = llvm::APFloat(d_val);
m_type = e_double;
+ }
else
error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str);
}
else if (byte_size == sizeof (long double))
{
- if (::sscanf (value_str, "%Lf", &m_data.ldbl) == 1)
+ if (::sscanf (value_str, "%Lf", &l_val) == 1)
+ {
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&l_val)->x));
m_type = e_long_double;
+ }
else
error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str);
}
@@ -1890,6 +2448,7 @@ Scalar::SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t b
{
Error error;
+ type128 int128;
switch (encoding)
{
case lldb::eEncodingInvalid:
@@ -1904,10 +2463,25 @@ Scalar::SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t b
switch (byte_size)
{
- case 1: operator=((uint8_t)data.GetU8(&offset)); break;
- case 2: operator=((uint16_t)data.GetU16(&offset)); break;
- case 4: operator=((uint32_t)data.GetU32(&offset)); break;
- case 8: operator=((uint64_t)data.GetU64(&offset)); break;
+ case 1: operator=((uint8_t)data.GetU8(&offset)); break;
+ case 2: operator=((uint16_t)data.GetU16(&offset)); break;
+ case 4: operator=((uint32_t)data.GetU32(&offset)); break;
+ case 8: operator=((uint64_t)data.GetU64(&offset)); break;
+ case 16:
+ {
+ if (data.GetByteOrder() == eByteOrderBig)
+ {
+ int128.x[1] = (uint64_t)data.GetU64 (&offset);
+ int128.x[0] = (uint64_t)data.GetU64 (&offset + 1);
+ }
+ else
+ {
+ int128.x[0] = (uint64_t)data.GetU64 (&offset);
+ int128.x[1] = (uint64_t)data.GetU64 (&offset + 1);
+ }
+ operator=(llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, int128.x));
+ break;
+ }
default:
error.SetErrorStringWithFormat("unsupported unsigned integer byte size: %" PRIu64 "", (uint64_t)byte_size);
break;
@@ -1924,6 +2498,21 @@ Scalar::SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t b
case 2: operator=((int16_t)data.GetU16(&offset)); break;
case 4: operator=((int32_t)data.GetU32(&offset)); break;
case 8: operator=((int64_t)data.GetU64(&offset)); break;
+ case 16:
+ {
+ if (data.GetByteOrder() == eByteOrderBig)
+ {
+ int128.x[1] = (uint64_t)data.GetU64 (&offset);
+ int128.x[0] = (uint64_t)data.GetU64 (&offset + 1);
+ }
+ else
+ {
+ int128.x[0] = (uint64_t)data.GetU64 (&offset);
+ int128.x[1] = (uint64_t)data.GetU64 (&offset + 1);
+ }
+ operator=(llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, int128.x));
+ break;
+ }
default:
error.SetErrorStringWithFormat("unsupported signed integer byte size: %" PRIu64 "", (uint64_t)byte_size);
break;
@@ -1966,47 +2555,22 @@ Scalar::SignExtend (uint32_t sign_bit_pos)
case Scalar::e_sint:
case Scalar::e_uint:
- if (max_bit_pos == sign_bit_pos)
- return true;
- else if (sign_bit_pos < (max_bit_pos-1))
- {
- unsigned int sign_bit = 1u << sign_bit_pos;
- if (m_data.uint & sign_bit)
- {
- const unsigned int mask = ~(sign_bit) + 1u;
- m_data.uint |= mask;
- }
- return true;
- }
- break;
-
case Scalar::e_slong:
case Scalar::e_ulong:
- if (max_bit_pos == sign_bit_pos)
- return true;
- else if (sign_bit_pos < (max_bit_pos-1))
- {
- unsigned long sign_bit = 1ul << sign_bit_pos;
- if (m_data.ulong & sign_bit)
- {
- const unsigned long mask = ~(sign_bit) + 1ul;
- m_data.ulong |= mask;
- }
- return true;
- }
- break;
-
case Scalar::e_slonglong:
case Scalar::e_ulonglong:
+ case Scalar::e_sint128:
+ case Scalar::e_uint128:
if (max_bit_pos == sign_bit_pos)
return true;
else if (sign_bit_pos < (max_bit_pos-1))
{
- unsigned long long sign_bit = 1ull << sign_bit_pos;
- if (m_data.ulonglong & sign_bit)
+ llvm::APInt sign_bit = llvm::APInt::getSignBit(sign_bit_pos + 1);
+ llvm::APInt bitwize_and = m_integer & sign_bit;
+ if (bitwize_and.getBoolValue())
{
- const unsigned long long mask = ~(sign_bit) + 1ull;
- m_data.ulonglong |= mask;
+ const llvm::APInt mask = ~(sign_bit) + llvm::APInt(m_integer.getBitWidth(), 1);
+ m_integer |= mask;
}
return true;
}
@@ -2053,66 +2617,40 @@ Scalar::ExtractBitfield (uint32_t bit_size,
uint32_t msbit = bit_offset + bit_size - 1;
uint32_t lsbit = bit_offset;
+ uint64_t result;
switch (m_type)
{
case Scalar::e_void:
break;
case e_float:
- if (sizeof(m_data.flt) == sizeof(sint_t))
- m_data.sint = (sint_t)SignedBits (m_data.sint, msbit, lsbit);
- else if (sizeof(m_data.flt) == sizeof(ulong_t))
- m_data.slong = (slong_t)SignedBits (m_data.slong, msbit, lsbit);
- else if (sizeof(m_data.flt) == sizeof(ulonglong_t))
- m_data.slonglong = (slonglong_t)SignedBits (m_data.slonglong, msbit, lsbit);
- else
- return false;
+ result = SignedBits ((uint64_t )m_float.convertToFloat(), msbit, lsbit);
+ m_float = llvm::APFloat((float_t)result);
return true;
-
case e_double:
- if (sizeof(m_data.dbl) == sizeof(sint_t))
- m_data.sint = SignedBits (m_data.sint, msbit, lsbit);
- else if (sizeof(m_data.dbl) == sizeof(ulong_t))
- m_data.slong = SignedBits (m_data.slong, msbit, lsbit);
- else if (sizeof(m_data.dbl) == sizeof(ulonglong_t))
- m_data.slonglong = SignedBits (m_data.slonglong, msbit, lsbit);
- else
- return false;
- return true;
-
+ result = SignedBits ((uint64_t )m_float.convertToDouble(), msbit, lsbit);
+ m_float = llvm::APFloat((double_t)result);
case e_long_double:
- if (sizeof(m_data.ldbl) == sizeof(sint_t))
- m_data.sint = SignedBits (m_data.sint, msbit, lsbit);
- else if (sizeof(m_data.ldbl) == sizeof(ulong_t))
- m_data.slong = SignedBits (m_data.slong, msbit, lsbit);
- else if (sizeof(m_data.ldbl) == sizeof(ulonglong_t))
- m_data.slonglong = SignedBits (m_data.slonglong, msbit, lsbit);
+ m_integer = m_float.bitcastToAPInt();
+ result = SignedBits (*m_integer.getRawData(), msbit, lsbit);
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&result)->x));
else
- return false;
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&result)->x));
return true;
case Scalar::e_sint:
- m_data.sint = (sint_t)SignedBits (m_data.sint, msbit, lsbit);
- return true;
-
- case Scalar::e_uint:
- m_data.uint = (uint_t)UnsignedBits (m_data.uint, msbit, lsbit);
- return true;
-
case Scalar::e_slong:
- m_data.slong = (slong_t)SignedBits (m_data.slong, msbit, lsbit);
- return true;
-
- case Scalar::e_ulong:
- m_data.ulong = (ulong_t)UnsignedBits (m_data.ulong, msbit, lsbit);
- return true;
-
case Scalar::e_slonglong:
- m_data.slonglong = (slonglong_t)SignedBits (m_data.slonglong, msbit, lsbit);
+ case Scalar::e_sint128:
+ m_integer = SignedBits (*m_integer.getRawData(), msbit, lsbit);
return true;
+ case Scalar::e_uint:
+ case Scalar::e_ulong:
case Scalar::e_ulonglong:
- m_data.ulonglong = (ulonglong_t)UnsignedBits (m_data.ulonglong, msbit, lsbit);
+ case Scalar::e_uint128:
+ m_integer = UnsignedBits (*m_integer.getRawData(), msbit, lsbit);
return true;
}
return false;
@@ -2132,18 +2670,25 @@ lldb_private::operator== (const Scalar& lhs, const Scalar& rhs)
Scalar temp_value;
const Scalar* a;
const Scalar* b;
+ llvm::APFloat::cmpResult result;
switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
{
case Scalar::e_void: break;
- case Scalar::e_sint: return a->m_data.sint == b->m_data.sint;
- case Scalar::e_uint: return a->m_data.uint == b->m_data.uint;
- case Scalar::e_slong: return a->m_data.slong == b->m_data.slong;
- case Scalar::e_ulong: return a->m_data.ulong == b->m_data.ulong;
- case Scalar::e_slonglong: return a->m_data.slonglong == b->m_data.slonglong;
- case Scalar::e_ulonglong: return a->m_data.ulonglong == b->m_data.ulonglong;
- case Scalar::e_float: return a->m_data.flt == b->m_data.flt;
- case Scalar::e_double: return a->m_data.dbl == b->m_data.dbl;
- case Scalar::e_long_double: return a->m_data.ldbl == b->m_data.ldbl;
+ case Scalar::e_sint:
+ case Scalar::e_uint:
+ case Scalar::e_slong:
+ case Scalar::e_ulong:
+ case Scalar::e_slonglong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_sint128:
+ case Scalar::e_uint128:
+ return a->m_integer == b->m_integer;
+ case Scalar::e_float:
+ case Scalar::e_double:
+ case Scalar::e_long_double:
+ result = a->m_float.compare(b->m_float);
+ if(result == llvm::APFloat::cmpEqual)
+ return true;
}
return false;
}
@@ -2158,18 +2703,25 @@ lldb_private::operator!= (const Scalar& lhs, const Scalar& rhs)
Scalar temp_value; // A temp value that might get a copy of either promoted value
const Scalar* a;
const Scalar* b;
+ llvm::APFloat::cmpResult result;
switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
{
case Scalar::e_void: break;
- case Scalar::e_sint: return a->m_data.sint != b->m_data.sint;
- case Scalar::e_uint: return a->m_data.uint != b->m_data.uint;
- case Scalar::e_slong: return a->m_data.slong != b->m_data.slong;
- case Scalar::e_ulong: return a->m_data.ulong != b->m_data.ulong;
- case Scalar::e_slonglong: return a->m_data.slonglong != b->m_data.slonglong;
- case Scalar::e_ulonglong: return a->m_data.ulonglong != b->m_data.ulonglong;
- case Scalar::e_float: return a->m_data.flt != b->m_data.flt;
- case Scalar::e_double: return a->m_data.dbl != b->m_data.dbl;
- case Scalar::e_long_double: return a->m_data.ldbl != b->m_data.ldbl;
+ case Scalar::e_sint:
+ case Scalar::e_uint:
+ case Scalar::e_slong:
+ case Scalar::e_ulong:
+ case Scalar::e_slonglong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_sint128:
+ case Scalar::e_uint128:
+ return a->m_integer != b->m_integer;
+ case Scalar::e_float:
+ case Scalar::e_double:
+ case Scalar::e_long_double:
+ result = a->m_float.compare(b->m_float);
+ if(result != llvm::APFloat::cmpEqual)
+ return true;
}
return true;
}
@@ -2183,18 +2735,26 @@ lldb_private::operator< (const Scalar& lhs, const Scalar& rhs)
Scalar temp_value;
const Scalar* a;
const Scalar* b;
+ llvm::APFloat::cmpResult result;
switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
{
case Scalar::e_void: break;
- case Scalar::e_sint: return a->m_data.sint < b->m_data.sint;
- case Scalar::e_uint: return a->m_data.uint < b->m_data.uint;
- case Scalar::e_slong: return a->m_data.slong < b->m_data.slong;
- case Scalar::e_ulong: return a->m_data.ulong < b->m_data.ulong;
- case Scalar::e_slonglong: return a->m_data.slonglong < b->m_data.slonglong;
- case Scalar::e_ulonglong: return a->m_data.ulonglong < b->m_data.ulonglong;
- case Scalar::e_float: return a->m_data.flt < b->m_data.flt;
- case Scalar::e_double: return a->m_data.dbl < b->m_data.dbl;
- case Scalar::e_long_double: return a->m_data.ldbl < b->m_data.ldbl;
+ case Scalar::e_sint:
+ case Scalar::e_slong:
+ case Scalar::e_slonglong:
+ case Scalar::e_sint128:
+ return a->m_integer.slt(b->m_integer);
+ case Scalar::e_uint:
+ case Scalar::e_ulong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_uint128:
+ return a->m_integer.ult(b->m_integer);
+ case Scalar::e_float:
+ case Scalar::e_double:
+ case Scalar::e_long_double:
+ result = a->m_float.compare(b->m_float);
+ if(result == llvm::APFloat::cmpLessThan)
+ return true;
}
return false;
}
@@ -2208,18 +2768,26 @@ lldb_private::operator<= (const Scalar& lhs, const Scalar& rhs)
Scalar temp_value;
const Scalar* a;
const Scalar* b;
+ llvm::APFloat::cmpResult result;
switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
{
case Scalar::e_void: break;
- case Scalar::e_sint: return a->m_data.sint <= b->m_data.sint;
- case Scalar::e_uint: return a->m_data.uint <= b->m_data.uint;
- case Scalar::e_slong: return a->m_data.slong <= b->m_data.slong;
- case Scalar::e_ulong: return a->m_data.ulong <= b->m_data.ulong;
- case Scalar::e_slonglong: return a->m_data.slonglong <= b->m_data.slonglong;
- case Scalar::e_ulonglong: return a->m_data.ulonglong <= b->m_data.ulonglong;
- case Scalar::e_float: return a->m_data.flt <= b->m_data.flt;
- case Scalar::e_double: return a->m_data.dbl <= b->m_data.dbl;
- case Scalar::e_long_double: return a->m_data.ldbl <= b->m_data.ldbl;
+ case Scalar::e_sint:
+ case Scalar::e_slong:
+ case Scalar::e_slonglong:
+ case Scalar::e_sint128:
+ return a->m_integer.sle(b->m_integer);
+ case Scalar::e_uint:
+ case Scalar::e_ulong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_uint128:
+ return a->m_integer.ule(b->m_integer);
+ case Scalar::e_float:
+ case Scalar::e_double:
+ case Scalar::e_long_double:
+ result = a->m_float.compare(b->m_float);
+ if(result == llvm::APFloat::cmpLessThan || result == llvm::APFloat::cmpEqual)
+ return true;
}
return false;
}
@@ -2234,18 +2802,26 @@ lldb_private::operator> (const Scalar& lhs, const Scalar& rhs)
Scalar temp_value;
const Scalar* a;
const Scalar* b;
+ llvm::APFloat::cmpResult result;
switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
{
- case Scalar::e_void: break;
- case Scalar::e_sint: return a->m_data.sint > b->m_data.sint;
- case Scalar::e_uint: return a->m_data.uint > b->m_data.uint;
- case Scalar::e_slong: return a->m_data.slong > b->m_data.slong;
- case Scalar::e_ulong: return a->m_data.ulong > b->m_data.ulong;
- case Scalar::e_slonglong: return a->m_data.slonglong > b->m_data.slonglong;
- case Scalar::e_ulonglong: return a->m_data.ulonglong > b->m_data.ulonglong;
- case Scalar::e_float: return a->m_data.flt > b->m_data.flt;
- case Scalar::e_double: return a->m_data.dbl > b->m_data.dbl;
- case Scalar::e_long_double: return a->m_data.ldbl > b->m_data.ldbl;
+ case Scalar::e_void: break;
+ case Scalar::e_sint:
+ case Scalar::e_slong:
+ case Scalar::e_slonglong:
+ case Scalar::e_sint128:
+ return a->m_integer.sgt(b->m_integer);
+ case Scalar::e_uint:
+ case Scalar::e_ulong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_uint128:
+ return a->m_integer.ugt(b->m_integer);
+ case Scalar::e_float:
+ case Scalar::e_double:
+ case Scalar::e_long_double:
+ result = a->m_float.compare(b->m_float);
+ if(result == llvm::APFloat::cmpGreaterThan)
+ return true;
}
return false;
}
@@ -2259,22 +2835,140 @@ lldb_private::operator>= (const Scalar& lhs, const Scalar& rhs)
Scalar temp_value;
const Scalar* a;
const Scalar* b;
+ llvm::APFloat::cmpResult result;
switch (PromoteToMaxType(lhs, rhs, temp_value, a, b))
{
- case Scalar::e_void: break;
- case Scalar::e_sint: return a->m_data.sint >= b->m_data.sint;
- case Scalar::e_uint: return a->m_data.uint >= b->m_data.uint;
- case Scalar::e_slong: return a->m_data.slong >= b->m_data.slong;
- case Scalar::e_ulong: return a->m_data.ulong >= b->m_data.ulong;
- case Scalar::e_slonglong: return a->m_data.slonglong >= b->m_data.slonglong;
- case Scalar::e_ulonglong: return a->m_data.ulonglong >= b->m_data.ulonglong;
- case Scalar::e_float: return a->m_data.flt >= b->m_data.flt;
- case Scalar::e_double: return a->m_data.dbl >= b->m_data.dbl;
- case Scalar::e_long_double: return a->m_data.ldbl >= b->m_data.ldbl;
+ case Scalar::e_void: break;
+ case Scalar::e_sint:
+ case Scalar::e_slong:
+ case Scalar::e_slonglong:
+ case Scalar::e_sint128:
+ return a->m_integer.sge(b->m_integer);
+ case Scalar::e_uint:
+ case Scalar::e_ulong:
+ case Scalar::e_ulonglong:
+ case Scalar::e_uint128:
+ return a->m_integer.uge(b->m_integer);
+ case Scalar::e_float:
+ case Scalar::e_double:
+ case Scalar::e_long_double:
+ result = a->m_float.compare(b->m_float);
+ if(result == llvm::APFloat::cmpGreaterThan || result == llvm::APFloat::cmpEqual)
+ return true;
}
return false;
}
+bool
+Scalar::ClearBit (uint32_t bit)
+{
+ switch (m_type)
+ {
+ case e_void:
+ break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128: m_integer.clearBit(bit); return true;
+ case e_float:
+ case e_double:
+ case e_long_double: break;
+ }
+ return false;
+}
+bool
+Scalar::SetBit (uint32_t bit)
+{
+ switch (m_type)
+ {
+ case e_void:
+ break;
+ case e_sint:
+ case e_uint:
+ case e_slong:
+ case e_ulong:
+ case e_slonglong:
+ case e_ulonglong:
+ case e_sint128:
+ case e_uint128: m_integer.setBit(bit); return true;
+ case e_float:
+ case e_double:
+ case e_long_double: break;
+ }
+ return false;
+}
-
+void
+Scalar::SetType (const RegisterInfo *reg_info)
+{
+ const uint32_t byte_size = reg_info->byte_size;
+ switch (reg_info->encoding)
+ {
+ case eEncodingInvalid:
+ break;
+ case eEncodingUint:
+ if (byte_size == 1 || byte_size == 2 || byte_size == 4)
+ {
+ m_integer = llvm::APInt(sizeof(uint_t) * 8, *(const uint64_t *)m_integer.getRawData(), false);
+ m_type = e_uint;
+ }
+ if (byte_size == 8)
+ {
+ m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false);
+ m_type = e_ulonglong;
+ }
+ if (byte_size == 16)
+ {
+ m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData())->x);
+ m_type = e_uint128;
+ }
+ break;
+ case eEncodingSint:
+ if (byte_size == 1 || byte_size == 2 || byte_size == 4)
+ {
+ m_integer = llvm::APInt(sizeof(sint_t) * 8, *(const uint64_t *)m_integer.getRawData(), true);
+ m_type = e_sint;
+ }
+ if (byte_size == 8)
+ {
+ m_integer = llvm::APInt(sizeof(slonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true);
+ m_type = e_slonglong;
+ }
+ if (byte_size == 16)
+ {
+ m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData())->x);
+ m_type = e_sint128;
+ }
+ break;
+ case eEncodingIEEE754:
+ if (byte_size == sizeof(float))
+ {
+ bool losesInfo = false;
+ m_float.convert(llvm::APFloat::IEEEsingle, llvm::APFloat::rmTowardZero, &losesInfo);
+ m_type = e_float;
+ }
+ else if (byte_size == sizeof(double))
+ {
+ bool losesInfo = false;
+ m_float.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmTowardZero, &losesInfo);
+ m_type = e_double;
+ }
+ else if (byte_size == sizeof(long double))
+ {
+ if(m_ieee_quad)
+ m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt());
+ else
+ m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt());
+ m_type = e_long_double;
+ }
+ break;
+ case eEncodingVector:
+ m_type = e_void;
+ break;
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Core/Section.cpp b/contrib/llvm/tools/lldb/source/Core/Section.cpp
index 9a3f220..cf1cbac 100644
--- a/contrib/llvm/tools/lldb/source/Core/Section.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Section.cpp
@@ -319,6 +319,25 @@ Section::Slide (addr_t slide_amount, bool slide_children)
return false;
}
+lldb::offset_t
+Section::GetSectionData (void *dst, lldb::offset_t dst_len, lldb::offset_t offset)
+{
+ if (m_obj_file)
+ return m_obj_file->ReadSectionData (this,
+ offset,
+ dst,
+ dst_len);
+ return 0;
+}
+
+lldb::offset_t
+Section::GetSectionData (DataExtractor& section_data) const
+{
+ if (m_obj_file)
+ return m_obj_file->ReadSectionData (this, section_data);
+ return 0;
+}
+
#pragma mark SectionList
SectionList::SectionList () :
diff --git a/contrib/llvm/tools/lldb/source/Core/SourceManager.cpp b/contrib/llvm/tools/lldb/source/Core/SourceManager.cpp
index 324ed34b..a69e75f 100644
--- a/contrib/llvm/tools/lldb/source/Core/SourceManager.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/SourceManager.cpp
@@ -18,7 +18,6 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Stream.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -83,6 +82,10 @@ SourceManager::GetFile (const FileSpec &file_spec)
if (target_sp && file_sp && file_sp->GetSourceMapModificationID() != target_sp->GetSourcePathMap().GetModificationID())
file_sp.reset();
+ // Update the file contents if needed if we found a file
+ if (file_sp)
+ file_sp->UpdateIfNeeded();
+
// If file_sp is no good or it points to a non-existent file, reset it.
if (!file_sp || !file_sp->GetFileSpec().Exists())
{
@@ -492,8 +495,8 @@ SourceManager::File::LineIsValid (uint32_t line)
return false;
}
-size_t
-SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s)
+void
+SourceManager::File::UpdateIfNeeded ()
{
// TODO: use host API to sign up for file modifications to anything in our
// source cache and only update when we determine a file has been updated.
@@ -506,7 +509,11 @@ SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before,
m_data_sp = m_file_spec.ReadFileContents ();
m_offsets.clear();
}
+}
+size_t
+SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s)
+{
// Sanity check m_data_sp before proceeding.
if (!m_data_sp)
return 0;
@@ -538,14 +545,6 @@ SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before,
void
SourceManager::File::FindLinesMatchingRegex (RegularExpression& regex, uint32_t start_line, uint32_t end_line, std::vector<uint32_t> &match_lines)
{
- TimeValue curr_mod_time (m_file_spec.GetModificationTime());
- if (m_mod_time != curr_mod_time)
- {
- m_mod_time = curr_mod_time;
- m_data_sp = m_file_spec.ReadFileContents ();
- m_offsets.clear();
- }
-
match_lines.clear();
if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line)))
@@ -645,14 +644,14 @@ SourceManager::File::CalculateLineOffsets (uint32_t line)
else
{
// Some lines have been populated, start where we last left off
- assert("Not implemented yet" == NULL);
+ assert("Not implemented yet" && false);
}
}
else
{
// Calculate all line offsets up to "line"
- assert("Not implemented yet" == NULL);
+ assert("Not implemented yet" && false);
}
return false;
}
diff --git a/contrib/llvm/tools/lldb/source/Core/Stream.cpp b/contrib/llvm/tools/lldb/source/Core/Stream.cpp
index 29bebb3..15876d5 100644
--- a/contrib/llvm/tools/lldb/source/Core/Stream.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Stream.cpp
@@ -30,7 +30,7 @@ Stream::Stream (uint32_t flags, uint32_t addr_size, ByteOrder byte_order) :
Stream::Stream () :
m_flags (0),
m_addr_size (4),
- m_byte_order (lldb::endian::InlHostByteOrder()),
+ m_byte_order (endian::InlHostByteOrder()),
m_indent_level(0)
{
}
@@ -284,9 +284,9 @@ Stream::operator<< (const char *s)
// Stream the pointer value out to this stream.
//------------------------------------------------------------------
Stream&
-Stream::operator<< (void *p)
+Stream::operator<< (const void *p)
{
- Printf ("0x%.*tx", (int)sizeof(void*) * 2, (ptrdiff_t)p);
+ Printf ("0x%.*tx", (int)sizeof(const void*) * 2, (ptrdiff_t)p);
return *this;
}
@@ -632,7 +632,7 @@ Stream::PutMaxHex64
size_t
Stream::PutPointer (void *ptr)
{
- return PutRawBytes (&ptr, sizeof(ptr), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
+ return PutRawBytes (&ptr, sizeof(ptr), endian::InlHostByteOrder(), endian::InlHostByteOrder());
}
size_t
@@ -641,7 +641,7 @@ Stream::PutFloat(float f, ByteOrder byte_order)
if (byte_order == eByteOrderInvalid)
byte_order = m_byte_order;
- return PutRawBytes (&f, sizeof(f), lldb::endian::InlHostByteOrder(), byte_order);
+ return PutRawBytes (&f, sizeof(f), endian::InlHostByteOrder(), byte_order);
}
size_t
@@ -650,7 +650,7 @@ Stream::PutDouble(double d, ByteOrder byte_order)
if (byte_order == eByteOrderInvalid)
byte_order = m_byte_order;
- return PutRawBytes (&d, sizeof(d), lldb::endian::InlHostByteOrder(), byte_order);
+ return PutRawBytes (&d, sizeof(d), endian::InlHostByteOrder(), byte_order);
}
size_t
@@ -659,7 +659,7 @@ Stream::PutLongDouble(long double ld, ByteOrder byte_order)
if (byte_order == eByteOrderInvalid)
byte_order = m_byte_order;
- return PutRawBytes (&ld, sizeof(ld), lldb::endian::InlHostByteOrder(), byte_order);
+ return PutRawBytes (&ld, sizeof(ld), endian::InlHostByteOrder(), byte_order);
}
size_t
@@ -743,21 +743,21 @@ Stream::UnitTest(Stream *s)
s->PutHex8(0x12);
s->PutChar(' ');
- s->PutHex16(0x3456, lldb::endian::InlHostByteOrder());
+ s->PutHex16(0x3456, endian::InlHostByteOrder());
s->PutChar(' ');
s->PutHex16(0x3456, eByteOrderBig);
s->PutChar(' ');
s->PutHex16(0x3456, eByteOrderLittle);
s->PutChar(' ');
- s->PutHex32(0x789abcde, lldb::endian::InlHostByteOrder());
+ s->PutHex32(0x789abcde, endian::InlHostByteOrder());
s->PutChar(' ');
s->PutHex32(0x789abcde, eByteOrderBig);
s->PutChar(' ');
s->PutHex32(0x789abcde, eByteOrderLittle);
s->PutChar(' ');
- s->PutHex64(0x1122334455667788ull, lldb::endian::InlHostByteOrder());
+ s->PutHex64(0x1122334455667788ull, endian::InlHostByteOrder());
s->PutChar(' ');
s->PutHex64(0x1122334455667788ull, eByteOrderBig);
s->PutChar(' ');
diff --git a/contrib/llvm/tools/lldb/source/Core/StreamAsynchronousIO.cpp b/contrib/llvm/tools/lldb/source/Core/StreamAsynchronousIO.cpp
index ccfde0c..6f8fcce 100644
--- a/contrib/llvm/tools/lldb/source/Core/StreamAsynchronousIO.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/StreamAsynchronousIO.cpp
@@ -36,7 +36,7 @@ StreamAsynchronousIO::Flush ()
if (!m_data.empty())
{
m_debugger.PrintAsync (m_data.data(), m_data.size(), m_for_stdout);
- m_data = std::move(std::string());
+ m_data = std::string();
}
}
diff --git a/contrib/llvm/tools/lldb/source/Core/StreamString.cpp b/contrib/llvm/tools/lldb/source/Core/StreamString.cpp
index ef2b705..36e086b 100644
--- a/contrib/llvm/tools/lldb/source/Core/StreamString.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/StreamString.cpp
@@ -37,7 +37,7 @@ StreamString::Flush ()
size_t
StreamString::Write (const void *s, size_t length)
{
- m_packet.append ((char *)s, length);
+ m_packet.append (reinterpret_cast<const char *>(s), length);
return length;
}
diff --git a/contrib/llvm/tools/lldb/source/Core/StringList.cpp b/contrib/llvm/tools/lldb/source/Core/StringList.cpp
index 4e07ba4..98a0790 100644
--- a/contrib/llvm/tools/lldb/source/Core/StringList.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/StringList.cpp
@@ -11,6 +11,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
+#include "lldb/Core/Log.h"
#include <string>
@@ -305,12 +306,29 @@ StringList::operator << (const char* str)
}
StringList&
+StringList::operator << (const std::string& str)
+{
+ AppendString(str);
+ return *this;
+}
+
+StringList&
StringList::operator << (StringList strings)
{
AppendList(strings);
return *this;
}
+StringList&
+StringList::operator = (const std::vector<std::string> &rhs)
+{
+ Clear();
+ for (const auto &s : rhs)
+ m_strings.push_back(s);
+
+ return *this;
+}
+
size_t
StringList::AutoComplete (const char *s, StringList &matches, size_t &exact_idx) const
{
@@ -339,3 +357,21 @@ StringList::AutoComplete (const char *s, StringList &matches, size_t &exact_idx)
return matches.GetSize();
}
+void
+StringList::LogDump(Log *log, const char *name)
+{
+ if (!log)
+ return;
+
+ StreamString strm;
+ if (name)
+ strm.Printf("Begin %s:\n", name);
+ for (const auto &s : m_strings) {
+ strm.Indent();
+ strm.Printf("%s\n", s.c_str());
+ }
+ if (name)
+ strm.Printf("End %s.\n", name);
+
+ log->Debug("%s", strm.GetData());
+}
diff --git a/contrib/llvm/tools/lldb/source/Core/Timer.cpp b/contrib/llvm/tools/lldb/source/Core/Timer.cpp
index bbd9900..e53ce2e 100644
--- a/contrib/llvm/tools/lldb/source/Core/Timer.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Timer.cpp
@@ -21,12 +21,27 @@
using namespace lldb_private;
#define TIMER_INDENT_AMOUNT 2
-static bool g_quiet = true;
-uint32_t Timer::g_depth = 0;
-uint32_t Timer::g_display_depth = 0;
-FILE * Timer::g_file = NULL;
-typedef std::vector<Timer *> TimerStack;
-typedef std::map<const char *, uint64_t> TimerCategoryMap;
+
+namespace
+{
+ typedef std::map<const char*, uint64_t> TimerCategoryMap;
+
+ struct TimerStack
+ {
+ TimerStack() :
+ m_depth(0)
+ {}
+
+ uint32_t m_depth;
+ std::vector<Timer*> m_stack;
+ };
+} // end of anonymous namespace
+
+std::atomic<bool> Timer::g_quiet(true);
+std::atomic<unsigned> Timer::g_display_depth(0);
+std::mutex Timer::g_file_mutex;
+FILE* Timer::g_file = nullptr;
+
static lldb::thread_key_t g_key;
static Mutex &
@@ -82,12 +97,18 @@ Timer::Timer (const char *category, const char *format, ...) :
m_total_ticks (0),
m_timer_ticks (0)
{
- if (g_depth++ < g_display_depth)
+ TimerStack *stack = GetTimerStackForCurrentThread ();
+ if (!stack)
+ return;
+
+ if (stack->m_depth++ < g_display_depth)
{
if (g_quiet == false)
{
+ std::lock_guard<std::mutex> lock(g_file_mutex);
+
// Indent
- ::fprintf (g_file, "%*s", g_depth * TIMER_INDENT_AMOUNT, "");
+ ::fprintf (g_file, "%*s", stack->m_depth * TIMER_INDENT_AMOUNT, "");
// Print formatted string
va_list args;
va_start (args, format);
@@ -100,19 +121,19 @@ Timer::Timer (const char *category, const char *format, ...) :
TimeValue start_time(TimeValue::Now());
m_total_start = start_time;
m_timer_start = start_time;
- TimerStack *stack = GetTimerStackForCurrentThread ();
- if (stack)
- {
- if (stack->empty() == false)
- stack->back()->ChildStarted (start_time);
- stack->push_back(this);
- }
+
+ if (!stack->m_stack.empty())
+ stack->m_stack.back()->ChildStarted (start_time);
+ stack->m_stack.push_back(this);
}
}
-
Timer::~Timer()
{
+ TimerStack *stack = GetTimerStackForCurrentThread ();
+ if (!stack)
+ return;
+
if (m_total_start.IsValid())
{
TimeValue stop_time = TimeValue::Now();
@@ -127,14 +148,10 @@ Timer::~Timer()
m_timer_start.Clear();
}
- TimerStack *stack = GetTimerStackForCurrentThread ();
- if (stack)
- {
- assert (stack->back() == this);
- stack->pop_back();
- if (stack->empty() == false)
- stack->back()->ChildStopped(stop_time);
- }
+ assert (stack->m_stack.back() == this);
+ stack->m_stack.pop_back();
+ if (stack->m_stack.empty() == false)
+ stack->m_stack.back()->ChildStopped(stop_time);
const uint64_t total_nsec_uint = GetTotalElapsedNanoSeconds();
const uint64_t timer_nsec_uint = GetTimerElapsedNanoSeconds();
@@ -143,10 +160,10 @@ Timer::~Timer()
if (g_quiet == false)
{
-
+ std::lock_guard<std::mutex> lock(g_file_mutex);
::fprintf (g_file,
"%*s%.9f sec (%.9f sec)\n",
- (g_depth - 1) *TIMER_INDENT_AMOUNT, "",
+ (stack->m_depth - 1) *TIMER_INDENT_AMOUNT, "",
total_nsec / 1000000000.0,
timer_nsec / 1000000000.0);
}
@@ -156,8 +173,8 @@ Timer::~Timer()
TimerCategoryMap &category_map = GetCategoryMap();
category_map[m_category] += timer_nsec_uint;
}
- if (g_depth > 0)
- --g_depth;
+ if (stack->m_depth > 0)
+ --stack->m_depth;
}
uint64_t
diff --git a/contrib/llvm/tools/lldb/source/Core/Value.cpp b/contrib/llvm/tools/lldb/source/Core/Value.cpp
index a416d07..a5c48e8 100644
--- a/contrib/llvm/tools/lldb/source/Core/Value.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/Value.cpp
@@ -18,7 +18,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -35,7 +35,7 @@ using namespace lldb_private;
Value::Value() :
m_value (),
m_vector (),
- m_clang_type (),
+ m_compiler_type (),
m_context (NULL),
m_value_type (eValueTypeScalar),
m_context_type (eContextTypeInvalid),
@@ -46,7 +46,7 @@ Value::Value() :
Value::Value(const Scalar& scalar) :
m_value (scalar),
m_vector (),
- m_clang_type (),
+ m_compiler_type (),
m_context (NULL),
m_value_type (eValueTypeScalar),
m_context_type (eContextTypeInvalid),
@@ -58,7 +58,7 @@ Value::Value(const Scalar& scalar) :
Value::Value(const void *bytes, int len) :
m_value (),
m_vector (),
- m_clang_type (),
+ m_compiler_type (),
m_context (NULL),
m_value_type (eValueTypeHostAddress),
m_context_type (eContextTypeInvalid),
@@ -70,7 +70,7 @@ Value::Value(const void *bytes, int len) :
Value::Value(const Value &v) :
m_value (v.m_value),
m_vector (v.m_vector),
- m_clang_type (v.m_clang_type),
+ m_compiler_type (v.m_compiler_type),
m_context (v.m_context),
m_value_type (v.m_value_type),
m_context_type (v.m_context_type),
@@ -93,7 +93,7 @@ Value::operator=(const Value &rhs)
{
m_value = rhs.m_value;
m_vector = rhs.m_vector;
- m_clang_type = rhs.m_clang_type;
+ m_compiler_type = rhs.m_compiler_type;
m_context = rhs.m_context;
m_value_type = rhs.m_value_type;
m_context_type = rhs.m_context_type;
@@ -189,7 +189,7 @@ Value::AppendDataToHostBuffer (const Value &rhs)
{
rhs.m_value.GetAsMemoryData (m_data_buffer.GetBytes() + curr_size,
scalar_size,
- lldb::endian::InlHostByteOrder(),
+ endian::InlHostByteOrder(),
error);
return scalar_size;
}
@@ -260,7 +260,7 @@ Value::ValueOf(ExecutionContext *exe_ctx)
}
uint64_t
-Value::GetValueByteSize (Error *error_ptr)
+Value::GetValueByteSize (Error *error_ptr, ExecutionContext *exe_ctx)
{
uint64_t byte_size = 0;
@@ -275,9 +275,9 @@ Value::GetValueByteSize (Error *error_ptr)
case eContextTypeLLDBType: // Type *
case eContextTypeVariable: // Variable *
{
- const ClangASTType &ast_type = GetClangType();
+ const CompilerType &ast_type = GetCompilerType();
if (ast_type.IsValid())
- byte_size = ast_type.GetByteSize(nullptr);
+ byte_size = ast_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
}
break;
}
@@ -297,10 +297,10 @@ Value::GetValueByteSize (Error *error_ptr)
return byte_size;
}
-const ClangASTType &
-Value::GetClangType ()
+const CompilerType &
+Value::GetCompilerType ()
{
- if (!m_clang_type.IsValid())
+ if (!m_compiler_type.IsValid())
{
switch (m_context_type)
{
@@ -308,13 +308,13 @@ Value::GetClangType ()
break;
case eContextTypeRegisterInfo:
- break; // TODO: Eventually convert into a clang type?
+ break; // TODO: Eventually convert into a compiler type?
case eContextTypeLLDBType:
{
Type *lldb_type = GetType();
if (lldb_type)
- m_clang_type = lldb_type->GetClangForwardType();
+ m_compiler_type = lldb_type->GetForwardCompilerType ();
}
break;
@@ -325,20 +325,20 @@ Value::GetClangType ()
{
Type *variable_type = variable->GetType();
if (variable_type)
- m_clang_type = variable_type->GetClangForwardType();
+ m_compiler_type = variable_type->GetForwardCompilerType ();
}
}
break;
}
}
- return m_clang_type;
+ return m_compiler_type;
}
void
-Value::SetClangType (const ClangASTType &clang_type)
+Value::SetCompilerType (const CompilerType &compiler_type)
{
- m_clang_type = clang_type;
+ m_compiler_type = compiler_type;
}
lldb::Format
@@ -355,7 +355,7 @@ Value::GetValueDefaultFormat ()
case eContextTypeLLDBType:
case eContextTypeVariable:
{
- const ClangASTType &ast_type = GetClangType();
+ const CompilerType &ast_type = GetCompilerType();
if (ast_type.IsValid())
return ast_type.GetFormat();
}
@@ -407,7 +407,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx,
lldb::addr_t address = LLDB_INVALID_ADDRESS;
AddressType address_type = eAddressTypeFile;
Address file_so_addr;
- const ClangASTType &ast_type = GetClangType();
+ const CompilerType &ast_type = GetCompilerType();
switch (m_value_type)
{
case eValueTypeVector:
@@ -420,7 +420,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx,
case eValueTypeScalar:
{
- data.SetByteOrder (lldb::endian::InlHostByteOrder());
+ data.SetByteOrder (endian::InlHostByteOrder());
if (ast_type.IsValid())
data.SetAddressByteSize (ast_type.GetPointerByteSize());
else
@@ -434,7 +434,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx,
lldb::Encoding type_encoding = ast_type.GetEncoding(type_encoding_count);
if (type_encoding == eEncodingUint || type_encoding == eEncodingSint)
- limit_byte_size = ast_type.GetByteSize(nullptr);
+ limit_byte_size = ast_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
}
if (m_value.GetData (data, limit_byte_size))
@@ -623,7 +623,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx,
}
}
// fallback to host settings
- data.SetByteOrder(lldb::endian::InlHostByteOrder());
+ data.SetByteOrder(endian::InlHostByteOrder());
data.SetAddressByteSize(sizeof(void *));
break;
}
@@ -639,7 +639,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx,
}
// If we got here, we need to read the value from memory
- size_t byte_size = GetValueByteSize (&error);
+ size_t byte_size = GetValueByteSize (&error, exe_ctx);
// Bail if we encountered any errors getting the byte size
if (error.Fail())
@@ -721,8 +721,8 @@ Value::GetValueAsData (ExecutionContext *exe_ctx,
Scalar &
Value::ResolveValue(ExecutionContext *exe_ctx)
{
- const ClangASTType &clang_type = GetClangType();
- if (clang_type.IsValid())
+ const CompilerType &compiler_type = GetCompilerType();
+ if (compiler_type.IsValid())
{
switch (m_value_type)
{
@@ -740,7 +740,7 @@ Value::ResolveValue(ExecutionContext *exe_ctx)
if (error.Success())
{
Scalar scalar;
- if (clang_type.GetValueAsScalar (data, 0, data.GetByteSize(), scalar))
+ if (compiler_type.GetValueAsScalar (data, 0, data.GetByteSize(), scalar))
{
m_value = scalar;
m_value_type = eValueTypeScalar;
@@ -782,7 +782,7 @@ Value::Clear()
{
m_value.Clear();
m_vector.Clear();
- m_clang_type.Clear();
+ m_compiler_type.Clear();
m_value_type = eValueTypeScalar;
m_context = NULL;
m_context_type = eContextTypeInvalid;
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObject.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObject.cpp
index 8718b37..6b1a6c5 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObject.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObject.cpp
@@ -15,7 +15,6 @@
// C++ Includes
// Other libraries and framework includes
#include "llvm/Support/raw_ostream.h"
-#include "clang/AST/Type.h"
// Project includes
#include "lldb/Core/DataBufferHeap.h"
@@ -35,19 +34,20 @@
#include "lldb/DataFormatters/StringPrinter.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
+#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Host/Endian.h"
#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
@@ -97,6 +97,7 @@ ValueObject::ValueObject (ValueObject &parent) :
m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid),
m_value_checksum(),
m_preferred_display_language(lldb::eLanguageTypeUnknown),
+ m_language_flags(0),
m_value_is_valid (false),
m_value_did_change (false),
m_children_count_valid (false),
@@ -148,6 +149,7 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope,
m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
m_value_checksum(),
m_preferred_display_language(lldb::eLanguageTypeUnknown),
+ m_language_flags(0),
m_value_is_valid (false),
m_value_did_change (false),
m_children_count_valid (false),
@@ -276,7 +278,7 @@ ValueObject::UpdateValueIfNeeded (bool update_format)
bool
ValueObject::UpdateFormatsIfNeeded()
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
if (log)
log->Printf("[%s %p] checking for FormatManager revisions. ValueObject rev: %d - Global rev: %d",
GetName().GetCString(), static_cast<void*>(this),
@@ -316,39 +318,39 @@ ValueObject::ClearDynamicTypeInformation ()
m_children_count_valid = false;
m_did_calculate_complete_objc_class_type = false;
m_last_format_mgr_revision = 0;
- m_override_type = ClangASTType();
+ m_override_type = CompilerType();
SetValueFormat(lldb::TypeFormatImplSP());
SetSummaryFormat(lldb::TypeSummaryImplSP());
SetSyntheticChildren(lldb::SyntheticChildrenSP());
}
-ClangASTType
+CompilerType
ValueObject::MaybeCalculateCompleteType ()
{
- ClangASTType clang_type(GetClangTypeImpl());
+ CompilerType compiler_type(GetCompilerTypeImpl());
if (m_did_calculate_complete_objc_class_type)
{
if (m_override_type.IsValid())
return m_override_type;
else
- return clang_type;
+ return compiler_type;
}
- ClangASTType class_type;
+ CompilerType class_type;
bool is_pointer_type = false;
- if (clang_type.IsObjCObjectPointerType(&class_type))
+ if (ClangASTContext::IsObjCObjectPointerType(compiler_type, &class_type))
{
is_pointer_type = true;
}
- else if (clang_type.IsObjCObjectOrInterfaceType())
+ else if (ClangASTContext::IsObjCObjectOrInterfaceType(compiler_type))
{
- class_type = clang_type;
+ class_type = compiler_type;
}
else
{
- return clang_type;
+ return compiler_type;
}
m_did_calculate_complete_objc_class_type = true;
@@ -371,7 +373,7 @@ ValueObject::MaybeCalculateCompleteType ()
if (complete_objc_class_type_sp)
{
- ClangASTType complete_class(complete_objc_class_type_sp->GetClangFullType());
+ CompilerType complete_class(complete_objc_class_type_sp->GetFullCompilerType ());
if (complete_class.GetCompleteType())
{
@@ -392,11 +394,11 @@ ValueObject::MaybeCalculateCompleteType ()
}
}
}
- return clang_type;
+ return compiler_type;
}
-ClangASTType
-ValueObject::GetClangType ()
+CompilerType
+ValueObject::GetCompilerType ()
{
return MaybeCalculateCompleteType();
}
@@ -404,7 +406,7 @@ ValueObject::GetClangType ()
TypeImpl
ValueObject::GetTypeImpl ()
{
- return TypeImpl(GetClangType());
+ return TypeImpl(GetCompilerType());
}
DataExtractor &
@@ -514,6 +516,39 @@ ValueObject::ResolveValue (Scalar &scalar)
}
bool
+ValueObject::IsLogicalTrue (Error& error)
+{
+ if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage()))
+ {
+ LazyBool is_logical_true = language->IsLogicalTrue(*this, error);
+ switch (is_logical_true)
+ {
+ case eLazyBoolYes:
+ case eLazyBoolNo:
+ return (is_logical_true == true);
+ case eLazyBoolCalculate:
+ break;
+ }
+ }
+
+ Scalar scalar_value;
+
+ if (!ResolveValue (scalar_value))
+ {
+ error.SetErrorString("failed to get a scalar result");
+ return false;
+ }
+
+ bool ret;
+ if (scalar_value.ULongLong(1) == 0)
+ ret = false;
+ else
+ ret = true;
+ error.Clear();
+ return ret;
+}
+
+bool
ValueObject::GetValueIsValid () const
{
return m_value_is_valid;
@@ -566,40 +601,16 @@ ValueObjectSP
ValueObject::GetChildAtIndexPath (const std::initializer_list<size_t>& idxs,
size_t* index_of_error)
{
- if (idxs.size() == 0)
- return GetSP();
- ValueObjectSP root(GetSP());
- for (size_t idx : idxs)
- {
- root = root->GetChildAtIndex(idx, true);
- if (!root)
- {
- if (index_of_error)
- *index_of_error = idx;
- return root;
- }
- }
- return root;
+ return GetChildAtIndexPath( std::vector<size_t>(idxs),
+ index_of_error );
}
ValueObjectSP
ValueObject::GetChildAtIndexPath (const std::initializer_list< std::pair<size_t, bool> >& idxs,
size_t* index_of_error)
{
- if (idxs.size() == 0)
- return GetSP();
- ValueObjectSP root(GetSP());
- for (std::pair<size_t, bool> idx : idxs)
- {
- root = root->GetChildAtIndex(idx.first, idx.second);
- if (!root)
- {
- if (index_of_error)
- *index_of_error = idx.first;
- return root;
- }
- }
- return root;
+ return GetChildAtIndexPath( std::vector<std::pair<size_t,bool>>(idxs),
+ index_of_error );
}
lldb::ValueObjectSP
@@ -646,20 +657,16 @@ lldb::ValueObjectSP
ValueObject::GetChildAtNamePath (const std::initializer_list<ConstString> &names,
ConstString* name_of_error)
{
- if (names.size() == 0)
- return GetSP();
- ValueObjectSP root(GetSP());
- for (ConstString name : names)
- {
- root = root->GetChildMemberWithName(name, true);
- if (!root)
- {
- if (name_of_error)
- *name_of_error = name;
- return root;
- }
- }
- return root;
+ return GetChildAtNamePath( std::vector<ConstString>(names),
+ name_of_error );
+}
+
+lldb::ValueObjectSP
+ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names,
+ ConstString* name_of_error)
+{
+ return GetChildAtNamePath( std::vector<std::pair<ConstString,bool>>(names),
+ name_of_error );
}
lldb::ValueObjectSP
@@ -683,7 +690,7 @@ ValueObject::GetChildAtNamePath (const std::vector<ConstString> &names,
}
lldb::ValueObjectSP
-ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names,
+ValueObject::GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names,
ConstString* name_of_error)
{
if (names.size() == 0)
@@ -696,37 +703,17 @@ ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair<ConstStr
{
if (name_of_error)
*name_of_error = name.first;
- return root;
+ return root;
}
}
return root;
}
-lldb::ValueObjectSP
-ValueObject::GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names,
- ConstString* name_of_error)
-{
- if (names.size() == 0)
- return GetSP();
- ValueObjectSP root(GetSP());
- for (std::pair<ConstString, bool> name : names)
- {
- root = root->GetChildMemberWithName(name.first, name.second);
- if (!root)
- {
- if (name_of_error)
- *name_of_error = name.first;
- return root;
- }
- }
- return root;
-}
-
size_t
ValueObject::GetIndexOfChildWithName (const ConstString &name)
{
bool omit_empty_base_classes = true;
- return GetClangType().GetIndexOfChildWithName (name.GetCString(), omit_empty_base_classes);
+ return GetCompilerType().GetIndexOfChildWithName (name.GetCString(), omit_empty_base_classes);
}
ValueObjectSP
@@ -743,7 +730,7 @@ ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create)
std::vector<uint32_t> child_indexes;
bool omit_empty_base_classes = true;
- const size_t num_child_indexes = GetClangType().GetIndexOfChildMemberWithName (name.GetCString(),
+ const size_t num_child_indexes = GetCompilerType().GetIndexOfChildMemberWithName (name.GetCString(),
omit_empty_base_classes,
child_indexes);
if (num_child_indexes > 0)
@@ -771,9 +758,21 @@ ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create)
size_t
-ValueObject::GetNumChildren ()
+ValueObject::GetNumChildren (uint32_t max)
{
UpdateValueIfNeeded();
+
+ if (max < UINT32_MAX)
+ {
+ if (m_children_count_valid)
+ {
+ size_t children_count = m_children.GetChildrenCount();
+ return children_count <= max ? children_count : max;
+ }
+ else
+ return CalculateNumChildren(max);
+ }
+
if (!m_children_count_valid)
{
SetNumChildren (CalculateNumChildren());
@@ -828,26 +827,28 @@ ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_
uint32_t child_bitfield_bit_offset = 0;
bool child_is_base_class = false;
bool child_is_deref_of_parent = false;
+ uint64_t language_flags = 0;
const bool transparent_pointers = synthetic_array_member == false;
- ClangASTType child_clang_type;
+ CompilerType child_compiler_type;
ExecutionContext exe_ctx (GetExecutionContextRef());
- child_clang_type = GetClangType().GetChildClangTypeAtIndex (&exe_ctx,
- idx,
- transparent_pointers,
- omit_empty_base_classes,
- ignore_array_bounds,
- child_name_str,
- child_byte_size,
- child_byte_offset,
- child_bitfield_bit_size,
- child_bitfield_bit_offset,
- child_is_base_class,
- child_is_deref_of_parent,
- this);
- if (child_clang_type)
+ child_compiler_type = GetCompilerType().GetChildCompilerTypeAtIndex (&exe_ctx,
+ idx,
+ transparent_pointers,
+ omit_empty_base_classes,
+ ignore_array_bounds,
+ child_name_str,
+ child_byte_size,
+ child_byte_offset,
+ child_bitfield_bit_size,
+ child_bitfield_bit_offset,
+ child_is_base_class,
+ child_is_deref_of_parent,
+ this,
+ language_flags);
+ if (child_compiler_type)
{
if (synthetic_index)
child_byte_offset += child_byte_size * synthetic_index;
@@ -857,7 +858,7 @@ ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_
child_name.SetCString (child_name_str.c_str());
valobj = new ValueObjectChild (*this,
- child_clang_type,
+ child_compiler_type,
child_name,
child_byte_size,
child_byte_offset,
@@ -865,7 +866,8 @@ ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_
child_bitfield_bit_offset,
child_is_base_class,
child_is_deref_of_parent,
- eAddressTypeInvalid);
+ eAddressTypeInvalid,
+ language_flags);
//if (valobj)
// valobj->SetAddressTypeOfChildren(eAddressTypeInvalid);
}
@@ -875,9 +877,10 @@ ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_
bool
ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr,
- std::string& destination)
+ std::string& destination,
+ lldb::LanguageType lang)
{
- return GetSummaryAsCString(summary_ptr, destination, TypeSummaryOptions());
+ return GetSummaryAsCString(summary_ptr, destination, TypeSummaryOptions().SetLanguage(lang));
}
bool
@@ -886,7 +889,7 @@ ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr,
const TypeSummaryOptions& options)
{
destination.clear();
-
+
// ideally we would like to bail out if passing NULL, but if we do so
// we end up not providing the summary for function pointers anymore
if (/*summary_ptr == NULL ||*/ m_is_getting_summary)
@@ -894,31 +897,38 @@ ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr,
m_is_getting_summary = true;
+ TypeSummaryOptions actual_options(options);
+
+ if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)
+ actual_options.SetLanguage(GetPreferredDisplayLanguage());
+
// this is a hot path in code and we prefer to avoid setting this string all too often also clearing out other
// information that we might care to see in a crash log. might be useful in very specific situations though.
/*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s. Summary provider's description is %s",
- GetTypeName().GetCString(),
- GetName().GetCString(),
- summary_ptr->GetDescription().c_str());*/
+ GetTypeName().GetCString(),
+ GetName().GetCString(),
+ summary_ptr->GetDescription().c_str());*/
if (UpdateValueIfNeeded (false) && summary_ptr)
{
if (HasSyntheticValue())
m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on the synthetic children being up-to-date (e.g. ${svar%#})
- summary_ptr->FormatObject(this, destination, options);
+ summary_ptr->FormatObject(this, destination, actual_options);
}
m_is_getting_summary = false;
return !destination.empty();
}
const char *
-ValueObject::GetSummaryAsCString ()
+ValueObject::GetSummaryAsCString (lldb::LanguageType lang)
{
if (UpdateValueIfNeeded(true) && m_summary_str.empty())
{
+ TypeSummaryOptions summary_options;
+ summary_options.SetLanguage(lang);
GetSummaryAsCString(GetSummaryFormat().get(),
m_summary_str,
- TypeSummaryOptions());
+ summary_options);
}
if (m_summary_str.empty())
return NULL;
@@ -930,17 +940,17 @@ ValueObject::GetSummaryAsCString (std::string& destination,
const TypeSummaryOptions& options)
{
return GetSummaryAsCString(GetSummaryFormat().get(),
- destination,
- options);
+ destination,
+ options);
}
bool
ValueObject::IsCStringContainer(bool check_pointer)
{
- ClangASTType pointee_or_element_clang_type;
- const Flags type_flags (GetTypeInfo (&pointee_or_element_clang_type));
+ CompilerType pointee_or_element_compiler_type;
+ const Flags type_flags (GetTypeInfo (&pointee_or_element_compiler_type));
bool is_char_arr_ptr (type_flags.AnySet (eTypeIsArray | eTypeIsPointer) &&
- pointee_or_element_clang_type.IsCharType ());
+ pointee_or_element_compiler_type.IsCharType ());
if (!is_char_arr_ptr)
return false;
if (!check_pointer)
@@ -958,8 +968,8 @@ ValueObject::GetPointeeData (DataExtractor& data,
uint32_t item_idx,
uint32_t item_count)
{
- ClangASTType pointee_or_element_clang_type;
- const uint32_t type_info = GetTypeInfo (&pointee_or_element_clang_type);
+ CompilerType pointee_or_element_compiler_type;
+ const uint32_t type_info = GetTypeInfo (&pointee_or_element_compiler_type);
const bool is_pointer_type = type_info & eTypeIsPointer;
const bool is_array_type = type_info & eTypeIsArray;
if (!(is_pointer_type || is_array_type))
@@ -970,7 +980,7 @@ ValueObject::GetPointeeData (DataExtractor& data,
ExecutionContext exe_ctx (GetExecutionContextRef());
- const uint64_t item_type_size = pointee_or_element_clang_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
+ const uint64_t item_type_size = pointee_or_element_compiler_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
const uint64_t bytes = item_count * item_type_size;
const uint64_t offset = item_idx * item_type_size;
@@ -1046,12 +1056,12 @@ ValueObject::GetPointeeData (DataExtractor& data,
break;
case eAddressTypeHost:
{
- const uint64_t max_bytes = GetClangType().GetByteSize(exe_ctx.GetBestExecutionContextScope());
+ const uint64_t max_bytes = GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());
if (max_bytes > offset)
{
size_t bytes_read = std::min<uint64_t>(max_bytes - offset, bytes);
addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
- if (addr == LLDB_INVALID_ADDRESS)
+ if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
break;
heap_buf_ptr->CopyData((uint8_t*)(addr + offset), bytes_read);
data.SetData(data_sp);
@@ -1077,6 +1087,7 @@ ValueObject::GetData (DataExtractor& data, Error &error)
if (m_data.GetByteSize())
{
data = m_data;
+ error.Clear();
return data.GetByteSize();
}
else
@@ -1102,7 +1113,7 @@ ValueObject::SetData (DataExtractor &data, Error &error)
}
uint64_t count = 0;
- const Encoding encoding = GetClangType().GetEncoding(count);
+ const Encoding encoding = GetCompilerType().GetEncoding(count);
const size_t byte_size = GetByteSize();
@@ -1167,31 +1178,6 @@ ValueObject::SetData (DataExtractor &data, Error &error)
return true;
}
-// will compute strlen(str), but without consuming more than
-// maxlen bytes out of str (this serves the purpose of reading
-// chunks of a string without having to worry about
-// missing NULL terminators in the chunk)
-// of course, if strlen(str) > maxlen, the function will return
-// maxlen_value (which should be != maxlen, because that allows you
-// to know whether strlen(str) == maxlen or strlen(str) > maxlen)
-static uint32_t
-strlen_or_inf (const char* str,
- uint32_t maxlen,
- uint32_t maxlen_value)
-{
- uint32_t len = 0;
- if (str)
- {
- while(*str)
- {
- len++;str++;
- if (len >= maxlen)
- return maxlen_value;
- }
- }
- return len;
-}
-
static bool
CopyStringDataToBufferSP(const StreamString& source,
lldb::DataBufferSP& destination)
@@ -1201,13 +1187,14 @@ CopyStringDataToBufferSP(const StreamString& source,
return true;
}
-size_t
+std::pair<size_t,bool>
ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp,
Error& error,
uint32_t max_length,
bool honor_array,
Format item_format)
{
+ bool was_capped = false;
StreamString s;
ExecutionContext exe_ctx (GetExecutionContextRef());
Target* target = exe_ctx.GetTargetPtr();
@@ -1217,7 +1204,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp,
s << "<no target to read from>";
error.SetErrorString("no target to read from");
CopyStringDataToBufferSP(s, buffer_sp);
- return 0;
+ return {0,was_capped};
}
if (max_length == 0)
@@ -1226,11 +1213,11 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp,
size_t bytes_read = 0;
size_t total_bytes_read = 0;
- ClangASTType clang_type = GetClangType();
- ClangASTType elem_or_pointee_clang_type;
- const Flags type_flags (GetTypeInfo (&elem_or_pointee_clang_type));
+ CompilerType compiler_type = GetCompilerType();
+ CompilerType elem_or_pointee_compiler_type;
+ const Flags type_flags (GetTypeInfo (&elem_or_pointee_compiler_type));
if (type_flags.AnySet (eTypeIsArray | eTypeIsPointer) &&
- elem_or_pointee_clang_type.IsCharType ())
+ elem_or_pointee_compiler_type.IsCharType ())
{
addr_t cstr_address = LLDB_INVALID_ADDRESS;
AddressType cstr_address_type = eAddressTypeInvalid;
@@ -1241,7 +1228,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp,
{
// We have an array
uint64_t array_size = 0;
- if (clang_type.IsArrayType(NULL, &array_size, NULL))
+ if (compiler_type.IsArrayType(NULL, &array_size, NULL))
{
cstr_len = array_size;
if (cstr_len > max_length)
@@ -1263,7 +1250,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp,
s << "<invalid address>";
error.SetErrorString("invalid address");
CopyStringDataToBufferSP(s, buffer_sp);
- return 0;
+ return {0,was_capped};
}
Address cstr_so_addr (cstr_address);
@@ -1280,7 +1267,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp,
for (size_t offset = 0; offset < bytes_read; offset++)
s.Printf("%c", *data.PeekData(offset, 1));
if (capped_data)
- s << "...";
+ was_capped = true;
}
}
else
@@ -1298,10 +1285,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp,
{
total_bytes_read += bytes_read;
const char *cstr = data.PeekCStr(0);
- size_t len = strlen_or_inf (cstr, k_max_buf_size, k_max_buf_size+1);
- if (len > k_max_buf_size)
- len = k_max_buf_size;
-
+ size_t len = strnlen (cstr, k_max_buf_size);
if (cstr_len_displayed < 0)
cstr_len_displayed = len;
@@ -1332,7 +1316,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp,
if (cstr_len_displayed >= 0)
{
if (capped_cstr)
- s << "...";
+ was_capped = true;
}
}
}
@@ -1342,7 +1326,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp,
s << "<not a string object>";
}
CopyStringDataToBufferSP(s, buffer_sp);
- return total_bytes_read;
+ return {total_bytes_read,was_capped};
}
std::pair<TypeValidatorResult, std::string>
@@ -1385,11 +1369,11 @@ ValueObject::GetObjectDescription ()
if (runtime == NULL)
{
// Aw, hell, if the things a pointer, or even just an integer, let's try ObjC anyway...
- ClangASTType clang_type = GetClangType();
- if (clang_type)
+ CompilerType compiler_type = GetCompilerType();
+ if (compiler_type)
{
bool is_signed;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType ())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType ())
{
runtime = process->GetLanguageRuntime(eLanguageTypeObjC);
}
@@ -1449,7 +1433,7 @@ ValueObject::GetValueAsCString ()
}
else
{
- my_format = GetValue().GetClangType().GetFormat();
+ my_format = GetValue().GetCompilerType().GetFormat();
}
}
}
@@ -1590,18 +1574,19 @@ ValueObject::DumpPrintableRepresentation(Stream& s,
{
Error error;
lldb::DataBufferSP buffer_sp;
- ReadPointedString(buffer_sp,
- error,
- 0,
- (custom_format == eFormatVectorOfChar) ||
- (custom_format == eFormatCharArray));
- lldb_private::formatters::ReadBufferAndDumpToStreamOptions options(*this);
+ std::pair<size_t, bool> read_string = ReadPointedString(buffer_sp,
+ error,
+ 0,
+ (custom_format == eFormatVectorOfChar) ||
+ (custom_format == eFormatCharArray));
+ lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions options(*this);
options.SetData(DataExtractor(buffer_sp, lldb::eByteOrderInvalid, 8)); // none of this matters for a string - pass some defaults
options.SetStream(&s);
options.SetPrefixToken(0);
options.SetQuote('"');
options.SetSourceSize(buffer_sp->GetByteSize());
- lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::ASCII>(options);
+ options.SetIsTruncated(read_string.second);
+ formatters::StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::ASCII>(options);
return !error.Fail();
}
@@ -1886,7 +1871,7 @@ ValueObject::SetValueFromCString (const char *value_str, Error& error)
}
uint64_t count = 0;
- const Encoding encoding = GetClangType().GetEncoding (count);
+ const Encoding encoding = GetCompilerType().GetEncoding (count);
const size_t byte_size = GetByteSize();
@@ -1897,7 +1882,7 @@ ValueObject::SetValueFromCString (const char *value_str, Error& error)
// If the value is already a scalar, then let the scalar change itself:
m_value.GetScalar().SetValueFromCString (value_str, encoding, byte_size);
}
- else if (byte_size <= Scalar::GetMaxByteSize())
+ else if (byte_size <= 16)
{
// If the value fits in a scalar, then make a new scalar and again let the
// scalar code do the conversion, then figure out where to put the new value.
@@ -1984,7 +1969,7 @@ ValueObject::GetDeclaration (Declaration &decl)
ConstString
ValueObject::GetTypeName()
{
- return GetClangType().GetConstTypeName();
+ return GetCompilerType().GetConstTypeName();
}
ConstString
@@ -1996,14 +1981,14 @@ ValueObject::GetDisplayTypeName()
ConstString
ValueObject::GetQualifiedTypeName()
{
- return GetClangType().GetConstQualifiedTypeName();
+ return GetCompilerType().GetConstQualifiedTypeName();
}
LanguageType
ValueObject::GetObjectRuntimeLanguage ()
{
- return GetClangType().GetMinimumLanguage ();
+ return GetCompilerType().GetMinimumLanguage ();
}
void
@@ -2023,39 +2008,39 @@ ValueObject::GetSyntheticChild (const ConstString &key) const
}
uint32_t
-ValueObject::GetTypeInfo (ClangASTType *pointee_or_element_clang_type)
+ValueObject::GetTypeInfo (CompilerType *pointee_or_element_compiler_type)
{
- return GetClangType().GetTypeInfo (pointee_or_element_clang_type);
+ return GetCompilerType().GetTypeInfo (pointee_or_element_compiler_type);
}
bool
ValueObject::IsPointerType ()
{
- return GetClangType().IsPointerType();
+ return GetCompilerType().IsPointerType();
}
bool
ValueObject::IsArrayType ()
{
- return GetClangType().IsArrayType (NULL, NULL, NULL);
+ return GetCompilerType().IsArrayType (NULL, NULL, NULL);
}
bool
ValueObject::IsScalarType ()
{
- return GetClangType().IsScalarType ();
+ return GetCompilerType().IsScalarType ();
}
bool
ValueObject::IsIntegerType (bool &is_signed)
{
- return GetClangType().IsIntegerType (is_signed);
+ return GetCompilerType().IsIntegerType (is_signed);
}
bool
ValueObject::IsPointerOrReferenceType ()
{
- return GetClangType().IsPointerOrReferenceType ();
+ return GetCompilerType().IsPointerOrReferenceType ();
}
bool
@@ -2066,7 +2051,7 @@ ValueObject::IsPossibleDynamicType ()
if (process)
return process->IsPossibleDynamicValue(*this);
else
- return GetClangType().IsPossibleDynamicType (NULL, true, true);
+ return GetCompilerType().IsPossibleDynamicType (NULL, true, true);
}
bool
@@ -2085,15 +2070,23 @@ ValueObject::IsRuntimeSupportValue ()
}
bool
-ValueObject::IsObjCNil ()
+ValueObject::IsNilReference ()
{
- const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
- bool isObjCpointer = (((GetClangType().GetTypeInfo(NULL)) & mask) == mask);
- if (!isObjCpointer)
- return false;
- bool canReadValue = true;
- bool isZero = GetValueAsUnsigned(0,&canReadValue) == 0;
- return canReadValue && isZero;
+ if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage()))
+ {
+ return language->IsNilReference(*this);
+ }
+ return false;
+}
+
+bool
+ValueObject::IsUninitializedReference ()
+{
+ if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage()))
+ {
+ return language->IsUninitializedReference(*this);
+ }
+ return false;
}
// This allows you to create an array member using and index
@@ -2156,7 +2149,7 @@ ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_cre
// We haven't made a synthetic array member for INDEX yet, so
// lets make one and cache it for any future reference.
ValueObjectChild *synthetic_child = new ValueObjectChild (*this,
- GetClangType(),
+ GetCompilerType(),
index_const_str,
GetByteSize(),
0,
@@ -2164,7 +2157,8 @@ ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_cre
from,
false,
false,
- eAddressTypeInvalid);
+ eAddressTypeInvalid,
+ 0);
// Cache the value if we got one back...
if (synthetic_child)
@@ -2180,7 +2174,7 @@ ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_cre
}
ValueObjectSP
-ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create)
+ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create)
{
ValueObjectSP synthetic_child_sp;
@@ -2210,7 +2204,8 @@ ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type
0,
false,
false,
- eAddressTypeInvalid);
+ eAddressTypeInvalid,
+ 0);
if (synthetic_child)
{
AddSyntheticChild(name_const_str, synthetic_child);
@@ -2222,7 +2217,7 @@ ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type
}
ValueObjectSP
-ValueObject::GetSyntheticBase (uint32_t offset, const ClangASTType& type, bool can_create)
+ValueObject::GetSyntheticBase (uint32_t offset, const CompilerType& type, bool can_create)
{
ValueObjectSP synthetic_child_sp;
@@ -2253,7 +2248,8 @@ ValueObject::GetSyntheticBase (uint32_t offset, const ClangASTType& type, bool c
0,
is_base_class,
false,
- eAddressTypeInvalid);
+ eAddressTypeInvalid,
+ 0);
if (synthetic_child)
{
AddSyntheticChild(name_const_str, synthetic_child);
@@ -2417,9 +2413,9 @@ ValueObject::GetBaseClassPath (Stream &s)
if (IsBaseClass())
{
bool parent_had_base_class = GetParent() && GetParent()->GetBaseClassPath (s);
- ClangASTType clang_type = GetClangType();
+ CompilerType compiler_type = GetCompilerType();
std::string cxx_class_name;
- bool this_had_base_class = clang_type.GetCXXClassName (cxx_class_name);
+ bool this_had_base_class = ClangASTContext::GetCXXClassName (compiler_type, cxx_class_name);
if (this_had_base_class)
{
if (parent_had_base_class)
@@ -2536,8 +2532,8 @@ ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExp
ValueObject *non_base_class_parent = GetNonBaseClassParent();
if (non_base_class_parent)
{
- ClangASTType non_base_class_parent_clang_type = non_base_class_parent->GetClangType();
- if (non_base_class_parent_clang_type)
+ CompilerType non_base_class_parent_compiler_type = non_base_class_parent->GetCompilerType();
+ if (non_base_class_parent_compiler_type)
{
if (parent && parent->IsDereferenceOfParent() && epformat == eGetExpressionPathFormatHonorPointers)
{
@@ -2545,7 +2541,7 @@ ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExp
}
else
{
- const uint32_t non_base_class_parent_type_info = non_base_class_parent_clang_type.GetTypeInfo();
+ const uint32_t non_base_class_parent_type_info = non_base_class_parent_compiler_type.GetTypeInfo();
if (non_base_class_parent_type_info & eTypeIsPointer)
{
@@ -2757,13 +2753,13 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr
- ClangASTType root_clang_type = root->GetClangType();
- ClangASTType pointee_clang_type;
- Flags pointee_clang_type_info;
+ CompilerType root_compiler_type = root->GetCompilerType();
+ CompilerType pointee_compiler_type;
+ Flags pointee_compiler_type_info;
- Flags root_clang_type_info(root_clang_type.GetTypeInfo(&pointee_clang_type));
- if (pointee_clang_type)
- pointee_clang_type_info.Reset(pointee_clang_type.GetTypeInfo());
+ Flags root_compiler_type_info(root_compiler_type.GetTypeInfo(&pointee_compiler_type));
+ if (pointee_compiler_type)
+ pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());
if (!expression_cstr || *expression_cstr == '\0')
{
@@ -2776,15 +2772,15 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
case '-':
{
if (options.m_check_dot_vs_arrow_syntax &&
- root_clang_type_info.Test(eTypeIsPointer) ) // if you are trying to use -> on a non-pointer and I must catch the error
+ root_compiler_type_info.Test(eTypeIsPointer) ) // if you are trying to use -> on a non-pointer and I must catch the error
{
*first_unparsed = expression_cstr;
*reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;
*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
return ValueObjectSP();
}
- if (root_clang_type_info.Test(eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden
- root_clang_type_info.Test(eTypeIsPointer) &&
+ if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden
+ root_compiler_type_info.Test(eTypeIsPointer) &&
options.m_no_fragile_ivar)
{
*first_unparsed = expression_cstr;
@@ -2804,7 +2800,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
case '.': // or fallthrough from ->
{
if (options.m_check_dot_vs_arrow_syntax && *expression_cstr == '.' &&
- root_clang_type_info.Test(eTypeIsPointer)) // if you are trying to use . on a pointer and I must catch the error
+ root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to use . on a pointer and I must catch the error
{
*first_unparsed = expression_cstr;
*reason_to_stop = ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;
@@ -2953,9 +2949,9 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
}
case '[':
{
- if (!root_clang_type_info.Test(eTypeIsArray) && !root_clang_type_info.Test(eTypeIsPointer) && !root_clang_type_info.Test(eTypeIsVector)) // if this is not a T[] nor a T*
+ if (!root_compiler_type_info.Test(eTypeIsArray) && !root_compiler_type_info.Test(eTypeIsPointer) && !root_compiler_type_info.Test(eTypeIsVector)) // if this is not a T[] nor a T*
{
- if (!root_clang_type_info.Test(eTypeIsScalar)) // if this is not even a scalar...
+ if (!root_compiler_type_info.Test(eTypeIsScalar)) // if this is not even a scalar...
{
if (options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None) // ...only chance left is synthetic
{
@@ -2975,7 +2971,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
}
if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays
{
- if (!root_clang_type_info.Test(eTypeIsArray))
+ if (!root_compiler_type_info.Test(eTypeIsArray))
{
*first_unparsed = expression_cstr;
*reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
@@ -3012,7 +3008,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
}
if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays
{
- if (root_clang_type_info.Test(eTypeIsArray))
+ if (root_compiler_type_info.Test(eTypeIsArray))
{
*first_unparsed = expression_cstr+2;
*reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
@@ -3028,7 +3024,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
}
}
// from here on we do have a valid index
- if (root_clang_type_info.Test(eTypeIsArray))
+ if (root_compiler_type_info.Test(eTypeIsArray))
{
ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true);
if (!child_valobj_sp)
@@ -3051,10 +3047,10 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
return ValueObjectSP();
}
}
- else if (root_clang_type_info.Test(eTypeIsPointer))
+ else if (root_compiler_type_info.Test(eTypeIsPointer))
{
if (*what_next == ValueObject::eExpressionPathAftermathDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
- pointee_clang_type_info.Test(eTypeIsScalar))
+ pointee_compiler_type_info.Test(eTypeIsScalar))
{
Error error;
root = root->Dereference(error);
@@ -3073,8 +3069,8 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
}
else
{
- if (root->GetClangType().GetMinimumLanguage() == eLanguageTypeObjC
- && pointee_clang_type_info.AllClear(eTypeIsPointer)
+ if (root->GetCompilerType().GetMinimumLanguage() == eLanguageTypeObjC
+ && pointee_compiler_type_info.AllClear(eTypeIsPointer)
&& root->HasSyntheticValue()
&& (options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::ToSynthetic ||
options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both))
@@ -3098,7 +3094,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
}
}
}
- else if (root_clang_type_info.Test(eTypeIsScalar))
+ else if (root_compiler_type_info.Test(eTypeIsScalar))
{
root = root->GetSyntheticBitFieldChild(index, index, true);
if (!root.get())
@@ -3116,7 +3112,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
return root;
}
}
- else if (root_clang_type_info.Test(eTypeIsVector))
+ else if (root_compiler_type_info.Test(eTypeIsVector))
{
root = root->GetChildAtIndex(index, true);
if (!root.get())
@@ -3202,7 +3198,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
index_lower = index_higher;
index_higher = temp;
}
- if (root_clang_type_info.Test(eTypeIsScalar)) // expansion only works for scalars
+ if (root_compiler_type_info.Test(eTypeIsScalar)) // expansion only works for scalars
{
root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true);
if (!root.get())
@@ -3220,9 +3216,9 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
return root;
}
}
- else if (root_clang_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
+ else if (root_compiler_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
*what_next == ValueObject::eExpressionPathAftermathDereference &&
- pointee_clang_type_info.Test(eTypeIsScalar))
+ pointee_compiler_type_info.Test(eTypeIsScalar))
{
Error error;
root = root->Dereference(error);
@@ -3281,12 +3277,12 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr,
const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr
- ClangASTType root_clang_type = root->GetClangType();
- ClangASTType pointee_clang_type;
- Flags pointee_clang_type_info;
- Flags root_clang_type_info(root_clang_type.GetTypeInfo(&pointee_clang_type));
- if (pointee_clang_type)
- pointee_clang_type_info.Reset(pointee_clang_type.GetTypeInfo());
+ CompilerType root_compiler_type = root->GetCompilerType();
+ CompilerType pointee_compiler_type;
+ Flags pointee_compiler_type_info;
+ Flags root_compiler_type_info(root_compiler_type.GetTypeInfo(&pointee_compiler_type));
+ if (pointee_compiler_type)
+ pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());
if (!expression_cstr || *expression_cstr == '\0')
{
@@ -3299,9 +3295,9 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr,
{
case '[':
{
- if (!root_clang_type_info.Test(eTypeIsArray) && !root_clang_type_info.Test(eTypeIsPointer)) // if this is not a T[] nor a T*
+ if (!root_compiler_type_info.Test(eTypeIsArray) && !root_compiler_type_info.Test(eTypeIsPointer)) // if this is not a T[] nor a T*
{
- if (!root_clang_type_info.Test(eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong!
+ if (!root_compiler_type_info.Test(eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong!
{
*first_unparsed = expression_cstr;
*reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;
@@ -3318,7 +3314,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr,
}
if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays
{
- if (!root_clang_type_info.Test(eTypeIsArray))
+ if (!root_compiler_type_info.Test(eTypeIsArray))
{
*first_unparsed = expression_cstr;
*reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
@@ -3362,7 +3358,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr,
}
if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays
{
- if (root_clang_type_info.Test(eTypeIsArray))
+ if (root_compiler_type_info.Test(eTypeIsArray))
{
const size_t max_index = root->GetNumChildren() - 1;
for (size_t index = 0; index < max_index; index++)
@@ -3385,7 +3381,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr,
}
}
// from here on we do have a valid index
- if (root_clang_type_info.Test(eTypeIsArray))
+ if (root_compiler_type_info.Test(eTypeIsArray))
{
root = root->GetChildAtIndex(index, true);
if (!root.get())
@@ -3404,10 +3400,10 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr,
return 1;
}
}
- else if (root_clang_type_info.Test(eTypeIsPointer))
+ else if (root_compiler_type_info.Test(eTypeIsPointer))
{
if (*what_next == ValueObject::eExpressionPathAftermathDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
- pointee_clang_type_info.Test(eTypeIsScalar))
+ pointee_compiler_type_info.Test(eTypeIsScalar))
{
Error error;
root = root->Dereference(error);
@@ -3444,7 +3440,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr,
}
}
}
- else /*if (ClangASTContext::IsScalarType(root_clang_type))*/
+ else /*if (ClangASTContext::IsScalarType(root_compiler_type))*/
{
root = root->GetSyntheticBitFieldChild(index, index, true);
if (!root.get())
@@ -3489,7 +3485,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr,
index_lower = index_higher;
index_higher = temp;
}
- if (root_clang_type_info.Test(eTypeIsScalar)) // expansion only works for scalars
+ if (root_compiler_type_info.Test(eTypeIsScalar)) // expansion only works for scalars
{
root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true);
if (!root.get())
@@ -3508,9 +3504,9 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr,
return 1;
}
}
- else if (root_clang_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
+ else if (root_compiler_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
*what_next == ValueObject::eExpressionPathAftermathDereference &&
- pointee_clang_type_info.Test(eTypeIsScalar))
+ pointee_compiler_type_info.Test(eTypeIsScalar))
{
Error error;
root = root->Dereference(error);
@@ -3611,7 +3607,7 @@ ValueObject::CreateConstantValue (const ConstString &name)
m_error = m_value.GetValueAsData (&exe_ctx, data, 0, GetModule().get());
valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
- GetClangType(),
+ GetCompilerType(),
name,
data,
GetAddressOf());
@@ -3677,8 +3673,8 @@ ValueObject::GetQualifiedRepresentationIfAvailable (lldb::DynamicValueType dynVa
lldb::addr_t
ValueObject::GetCPPVTableAddress (AddressType &address_type)
{
- ClangASTType pointee_type;
- ClangASTType this_type(GetClangType());
+ CompilerType pointee_type;
+ CompilerType this_type(GetCompilerType());
uint32_t type_info = this_type.GetTypeInfo(&pointee_type);
if (type_info)
{
@@ -3711,9 +3707,9 @@ ValueObject::Dereference (Error &error)
{
if (m_deref_valobj)
return m_deref_valobj->GetSP();
-
- const bool is_pointer_type = IsPointerType();
- if (is_pointer_type)
+
+ const bool is_pointer_or_reference_type = IsPointerOrReferenceType();
+ if (is_pointer_or_reference_type)
{
bool omit_empty_base_classes = true;
bool ignore_array_bounds = false;
@@ -3726,32 +3722,34 @@ ValueObject::Dereference (Error &error)
bool child_is_base_class = false;
bool child_is_deref_of_parent = false;
const bool transparent_pointers = false;
- ClangASTType clang_type = GetClangType();
- ClangASTType child_clang_type;
+ CompilerType compiler_type = GetCompilerType();
+ CompilerType child_compiler_type;
+ uint64_t language_flags;
ExecutionContext exe_ctx (GetExecutionContextRef());
-
- child_clang_type = clang_type.GetChildClangTypeAtIndex (&exe_ctx,
- 0,
- transparent_pointers,
- omit_empty_base_classes,
- ignore_array_bounds,
- child_name_str,
- child_byte_size,
- child_byte_offset,
- child_bitfield_bit_size,
- child_bitfield_bit_offset,
- child_is_base_class,
- child_is_deref_of_parent,
- this);
- if (child_clang_type && child_byte_size)
+
+ child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex (&exe_ctx,
+ 0,
+ transparent_pointers,
+ omit_empty_base_classes,
+ ignore_array_bounds,
+ child_name_str,
+ child_byte_size,
+ child_byte_offset,
+ child_bitfield_bit_size,
+ child_bitfield_bit_offset,
+ child_is_base_class,
+ child_is_deref_of_parent,
+ this,
+ language_flags);
+ if (child_compiler_type && child_byte_size)
{
ConstString child_name;
if (!child_name_str.empty())
child_name.SetCString (child_name_str.c_str());
m_deref_valobj = new ValueObjectChild (*this,
- child_clang_type,
+ child_compiler_type,
child_name,
child_byte_size,
child_byte_offset,
@@ -3759,7 +3757,8 @@ ValueObject::Dereference (Error &error)
child_bitfield_bit_offset,
child_is_base_class,
child_is_deref_of_parent,
- eAddressTypeInvalid);
+ eAddressTypeInvalid,
+ language_flags);
}
}
@@ -3773,10 +3772,10 @@ ValueObject::Dereference (Error &error)
StreamString strm;
GetExpressionPath(strm, true);
- if (is_pointer_type)
+ if (is_pointer_or_reference_type)
error.SetErrorStringWithFormat("dereference failed: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
else
- error.SetErrorStringWithFormat("not a pointer type: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
+ error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
return ValueObjectSP();
}
}
@@ -3806,14 +3805,14 @@ ValueObject::AddressOf (Error &error)
case eAddressTypeFile:
case eAddressTypeLoad:
{
- ClangASTType clang_type = GetClangType();
- if (clang_type)
+ CompilerType compiler_type = GetCompilerType();
+ if (compiler_type)
{
std::string name (1, '&');
name.append (m_name.AsCString(""));
ExecutionContext exe_ctx (GetExecutionContextRef());
m_addr_of_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
- clang_type.GetPointerType(),
+ compiler_type.GetPointerType(),
ConstString (name.c_str()),
addr,
eAddressTypeInvalid,
@@ -3836,13 +3835,13 @@ ValueObject::AddressOf (Error &error)
}
ValueObjectSP
-ValueObject::Cast (const ClangASTType &clang_ast_type)
+ValueObject::Cast (const CompilerType &compiler_type)
{
- return ValueObjectCast::Create (*this, GetName(), clang_ast_type);
+ return ValueObjectCast::Create (*this, GetName(), compiler_type);
}
ValueObjectSP
-ValueObject::CastPointerType (const char *name, ClangASTType &clang_ast_type)
+ValueObject::CastPointerType (const char *name, CompilerType &compiler_type)
{
ValueObjectSP valobj_sp;
AddressType address_type;
@@ -3855,7 +3854,7 @@ ValueObject::CastPointerType (const char *name, ClangASTType &clang_ast_type)
valobj_sp = ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(),
name,
ptr_addr,
- clang_ast_type);
+ compiler_type);
}
return valobj_sp;
}
@@ -4104,11 +4103,11 @@ lldb::ValueObjectSP
ValueObject::CreateValueObjectFromAddress (const char* name,
uint64_t address,
const ExecutionContext& exe_ctx,
- ClangASTType type)
+ CompilerType type)
{
if (type)
{
- ClangASTType pointer_type(type.GetPointerType());
+ CompilerType pointer_type(type.GetPointerType());
if (pointer_type)
{
lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t)));
@@ -4136,7 +4135,7 @@ lldb::ValueObjectSP
ValueObject::CreateValueObjectFromData (const char* name,
const DataExtractor& data,
const ExecutionContext& exe_ctx,
- ClangASTType type)
+ CompilerType type)
{
lldb::ValueObjectSP new_value_sp;
new_value_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
@@ -4252,13 +4251,20 @@ ValueObject::SetPreferredDisplayLanguage (lldb::LanguageType lt)
m_preferred_display_language = lt;
}
+void
+ValueObject::SetPreferredDisplayLanguageIfNeeded (lldb::LanguageType lt)
+{
+ if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
+ SetPreferredDisplayLanguage(lt);
+}
+
bool
ValueObject::CanProvideValue ()
{
// we need to support invalid types as providers of values because some bare-board
// debugging scenarios have no notion of types, but still manage to have raw numeric
// values for things like registers. sigh.
- const ClangASTType &type(GetClangType());
+ const CompilerType &type(GetCompilerType());
return (false == type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
}
@@ -4278,15 +4284,18 @@ ValueObject::Persist ()
if (!target_sp)
return nullptr;
- ConstString name(target_sp->GetPersistentVariables().GetNextPersistentVariableName());
+ PersistentExpressionState *persistent_state = target_sp->GetPersistentExpressionStateForLanguage(GetPreferredDisplayLanguage());
- ClangExpressionVariableSP clang_var_sp(new ClangExpressionVariable(target_sp.get(), GetValue(), name));
- if (clang_var_sp)
- {
- clang_var_sp->m_live_sp = clang_var_sp->m_frozen_sp;
- clang_var_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
- target_sp->GetPersistentVariables().AddVariable(clang_var_sp);
- }
+ if (!persistent_state)
+ return nullptr;
+
+ ConstString name(persistent_state->GetNextPersistentVariableName());
+
+ ValueObjectSP const_result_sp = ValueObjectConstResult::Create (target_sp.get(), GetValue(), name);
+
+ ExpressionVariableSP clang_var_sp = persistent_state->CreatePersistentVariable(const_result_sp);
+ clang_var_sp->m_live_sp = clang_var_sp->m_frozen_sp;
+ clang_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;
return clang_var_sp->GetValueObject();
}
@@ -4302,3 +4311,15 @@ ValueObject::SetSyntheticChildrenGenerated (bool b)
{
m_is_synthetic_children_generated = b;
}
+
+uint64_t
+ValueObject::GetLanguageFlags ()
+{
+ return m_language_flags;
+}
+
+void
+ValueObject::SetLanguageFlags (uint64_t flags)
+{
+ m_language_flags = flags;
+}
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectCast.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectCast.cpp
index b20371b..1c5838b 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectCast.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectCast.cpp
@@ -20,14 +20,13 @@
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
@@ -38,7 +37,7 @@ using namespace lldb_private;
lldb::ValueObjectSP
ValueObjectCast::Create (ValueObject &parent,
const ConstString &name,
- const ClangASTType &cast_type)
+ const CompilerType &cast_type)
{
ValueObjectCast *cast_valobj_ptr = new ValueObjectCast (parent, name, cast_type);
return cast_valobj_ptr->GetSP();
@@ -48,36 +47,38 @@ ValueObjectCast::ValueObjectCast
(
ValueObject &parent,
const ConstString &name,
- const ClangASTType &cast_type
+ const CompilerType &cast_type
) :
ValueObject(parent),
m_cast_type (cast_type)
{
SetName (name);
//m_value.SetContext (Value::eContextTypeClangType, cast_type.GetOpaqueQualType());
- m_value.SetClangType (cast_type);
+ m_value.SetCompilerType (cast_type);
}
ValueObjectCast::~ValueObjectCast()
{
}
-ClangASTType
-ValueObjectCast::GetClangTypeImpl ()
+CompilerType
+ValueObjectCast::GetCompilerTypeImpl ()
{
return m_cast_type;
}
size_t
-ValueObjectCast::CalculateNumChildren()
+ValueObjectCast::CalculateNumChildren(uint32_t max)
{
- return GetClangType().GetNumChildren (true);
+ auto children_count = GetCompilerType().GetNumChildren (true);
+ return children_count <= max ? children_count : max;
}
uint64_t
ValueObjectCast::GetByteSize()
{
- return m_value.GetValueByteSize(NULL);
+ ExecutionContext exe_ctx (GetExecutionContextRef());
+ return m_value.GetValueByteSize(nullptr, &exe_ctx);
}
lldb::ValueType
@@ -98,9 +99,9 @@ ValueObjectCast::UpdateValue ()
Value old_value(m_value);
m_update_point.SetUpdated();
m_value = m_parent->GetValue();
- ClangASTType clang_type (GetClangType());
- //m_value.SetContext (Value::eContextTypeClangType, clang_type);
- m_value.SetClangType (clang_type);
+ CompilerType compiler_type (GetCompilerType());
+ //m_value.SetContext (Value::eContextTypeClangType, compiler_type);
+ m_value.SetCompilerType (compiler_type);
SetAddressTypeOfChildren(m_parent->GetAddressTypeOfChildren());
if (!CanProvideValue())
{
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp
index c1e45e1..6ecc749 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp
@@ -12,7 +12,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ValueObjectList.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
@@ -27,7 +27,7 @@ using namespace lldb_private;
ValueObjectChild::ValueObjectChild
(
ValueObject &parent,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
uint64_t byte_size,
int32_t byte_offset,
@@ -35,19 +35,22 @@ ValueObjectChild::ValueObjectChild
uint32_t bitfield_bit_offset,
bool is_base_class,
bool is_deref_of_parent,
- AddressType child_ptr_or_ref_addr_type
+ AddressType child_ptr_or_ref_addr_type,
+ uint64_t language_flags
) :
ValueObject (parent),
- m_clang_type (clang_type),
+ m_compiler_type (compiler_type),
m_byte_size (byte_size),
m_byte_offset (byte_offset),
m_bitfield_bit_size (bitfield_bit_size),
m_bitfield_bit_offset (bitfield_bit_offset),
m_is_base_class (is_base_class),
- m_is_deref_of_parent (is_deref_of_parent)
+ m_is_deref_of_parent (is_deref_of_parent),
+ m_can_update_with_invalid_exe_ctx()
{
m_name = name;
SetAddressTypeOfChildren(child_ptr_or_ref_addr_type);
+ SetLanguageFlags(language_flags);
}
ValueObjectChild::~ValueObjectChild()
@@ -61,9 +64,10 @@ ValueObjectChild::GetValueType() const
}
size_t
-ValueObjectChild::CalculateNumChildren()
+ValueObjectChild::CalculateNumChildren(uint32_t max)
{
- return GetClangType().GetNumChildren (true);
+ auto children_count = GetCompilerType().GetNumChildren (true);
+ return children_count <= max ? children_count : max;
}
static void
@@ -72,11 +76,11 @@ AdjustForBitfieldness(ConstString& name,
{
if (name && bitfield_bit_size)
{
- const char *clang_type_name = name.AsCString();
- if (clang_type_name)
+ const char *compiler_type_name = name.AsCString();
+ if (compiler_type_name)
{
- std::vector<char> bitfield_type_name (strlen(clang_type_name) + 32, 0);
- ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, bitfield_bit_size);
+ std::vector<char> bitfield_type_name (strlen(compiler_type_name) + 32, 0);
+ ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", compiler_type_name, bitfield_bit_size);
name.SetCString(&bitfield_type_name.front());
}
}
@@ -87,7 +91,7 @@ ValueObjectChild::GetTypeName()
{
if (m_type_name.IsEmpty())
{
- m_type_name = GetClangType().GetConstTypeName ();
+ m_type_name = GetCompilerType().GetConstTypeName ();
AdjustForBitfieldness(m_type_name, m_bitfield_bit_size);
}
return m_type_name;
@@ -96,7 +100,7 @@ ValueObjectChild::GetTypeName()
ConstString
ValueObjectChild::GetQualifiedTypeName()
{
- ConstString qualified_name = GetClangType().GetConstTypeName();
+ ConstString qualified_name = GetCompilerType().GetConstTypeName();
AdjustForBitfieldness(qualified_name, m_bitfield_bit_size);
return qualified_name;
}
@@ -104,17 +108,25 @@ ValueObjectChild::GetQualifiedTypeName()
ConstString
ValueObjectChild::GetDisplayTypeName()
{
- ConstString display_name = GetClangType().GetDisplayTypeName();
+ ConstString display_name = GetCompilerType().GetDisplayTypeName();
AdjustForBitfieldness(display_name, m_bitfield_bit_size);
return display_name;
}
-bool
+LazyBool
ValueObjectChild::CanUpdateWithInvalidExecutionContext ()
{
+ if (m_can_update_with_invalid_exe_ctx.hasValue())
+ return m_can_update_with_invalid_exe_ctx.getValue();
if (m_parent)
- return m_parent->CanUpdateWithInvalidExecutionContext();
- return this->ValueObject::CanUpdateWithInvalidExecutionContext();
+ {
+ ValueObject *opinionated_parent = m_parent->FollowParentChain([] (ValueObject* valobj) -> bool {
+ return (valobj->CanUpdateWithInvalidExecutionContext() == eLazyBoolCalculate);
+ });
+ if (opinionated_parent)
+ return (m_can_update_with_invalid_exe_ctx = opinionated_parent->CanUpdateWithInvalidExecutionContext()).getValue();
+ }
+ return (m_can_update_with_invalid_exe_ctx = this->ValueObject::CanUpdateWithInvalidExecutionContext()).getValue();
}
bool
@@ -127,18 +139,22 @@ ValueObjectChild::UpdateValue ()
{
if (parent->UpdateValueIfNeeded(false))
{
- m_value.SetClangType(GetClangType());
-
+ m_value.SetCompilerType(GetCompilerType());
+
+ CompilerType parent_type(parent->GetCompilerType());
// Copy the parent scalar value and the scalar value type
m_value.GetScalar() = parent->GetValue().GetScalar();
Value::ValueType value_type = parent->GetValue().GetValueType();
m_value.SetValueType (value_type);
+
+ Flags parent_type_flags(parent_type.GetTypeInfo());
+ const bool is_instance_ptr_base = ((m_is_base_class == true) && (parent_type_flags.AnySet(lldb::eTypeInstanceIsPointer)));
- if (parent->GetClangType().IsPointerOrReferenceType ())
+ if (parent->GetCompilerType().ShouldTreatScalarValueAsAddress())
{
lldb::addr_t addr = parent->GetPointerValue ();
m_value.GetScalar() = addr;
-
+
if (addr == LLDB_INVALID_ADDRESS)
{
m_error.SetErrorString ("parent address is invalid.");
@@ -155,16 +171,16 @@ ValueObjectChild::UpdateValue ()
switch (addr_type)
{
case eAddressTypeFile:
- {
- lldb::ProcessSP process_sp (GetProcessSP());
- if (process_sp && process_sp->IsAlive() == true)
- m_value.SetValueType (Value::eValueTypeLoadAddress);
- else
- m_value.SetValueType(Value::eValueTypeFileAddress);
- }
+ {
+ lldb::ProcessSP process_sp (GetProcessSP());
+ if (process_sp && process_sp->IsAlive() == true)
+ m_value.SetValueType (Value::eValueTypeLoadAddress);
+ else
+ m_value.SetValueType(Value::eValueTypeFileAddress);
+ }
break;
case eAddressTypeLoad:
- m_value.SetValueType (Value::eValueTypeLoadAddress);
+ m_value.SetValueType (is_instance_ptr_base ? Value::eValueTypeScalar: Value::eValueTypeLoadAddress);
break;
case eAddressTypeHost:
m_value.SetValueType(Value::eValueTypeHostAddress);
@@ -180,9 +196,9 @@ ValueObjectChild::UpdateValue ()
{
switch (value_type)
{
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeHostAddress:
+ case Value::eValueTypeLoadAddress:
+ case Value::eValueTypeFileAddress:
+ case Value::eValueTypeHostAddress:
{
lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
if (addr == LLDB_INVALID_ADDRESS)
@@ -200,27 +216,42 @@ ValueObjectChild::UpdateValue ()
m_value.GetScalar() += GetByteOffset();
}
}
- break;
-
- case Value::eValueTypeScalar:
- // TODO: What if this is a register value? Do we try and
- // extract the child value from within the parent data?
- // Probably...
- default:
- m_error.SetErrorString ("parent has invalid value.");
- break;
+ break;
+
+ case Value::eValueTypeScalar:
+ // try to extract the child value from the parent's scalar value
+ {
+ Scalar scalar(m_value.GetScalar());
+ if (m_bitfield_bit_size)
+ scalar.ExtractBitfield(m_bitfield_bit_size, m_bitfield_bit_offset);
+ else
+ scalar.ExtractBitfield(8*m_byte_size, 8*m_byte_offset);
+ m_value.GetScalar() = scalar;
+ }
+ break;
+ default:
+ m_error.SetErrorString ("parent has invalid value.");
+ break;
}
}
-
+
if (m_error.Success())
{
const bool thread_and_frame_only_if_stopped = true;
ExecutionContext exe_ctx (GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped));
- if (GetClangType().GetTypeInfo() & lldb::eTypeHasValue)
- m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
+ if (GetCompilerType().GetTypeInfo() & lldb::eTypeHasValue)
+ {
+ if (!is_instance_ptr_base)
+ m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
+ else
+ m_error = m_parent->GetValue().GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
+ }
else
+ {
m_error.Clear(); // No value so nothing to read...
+ }
}
+
}
else
{
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResult.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResult.cpp
index b4e6303..a0f1737 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResult.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResult.cpp
@@ -16,7 +16,7 @@
#include "lldb/Core/ValueObjectDynamicValue.h"
#include "lldb/Core/ValueObjectList.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
@@ -61,21 +61,21 @@ ValueObjectSP
ValueObjectConstResult::Create
(
ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
const DataExtractor &data,
lldb::addr_t address
)
{
return (new ValueObjectConstResult (exe_scope,
- clang_type,
+ compiler_type,
name,
data,
address))->GetSP();
}
ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
const DataExtractor &data,
lldb::addr_t address) :
@@ -94,7 +94,7 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope
m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
m_value.SetValueType(Value::eValueTypeHostAddress);
- m_value.SetClangType(clang_type);
+ m_value.SetCompilerType(compiler_type);
m_name = name;
SetIsConstant ();
SetValueIsValid(true);
@@ -103,7 +103,7 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope
ValueObjectSP
ValueObjectConstResult::Create (ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
const lldb::DataBufferSP &data_sp,
lldb::ByteOrder data_byte_order,
@@ -111,7 +111,7 @@ ValueObjectConstResult::Create (ExecutionContextScope *exe_scope,
lldb::addr_t address)
{
return (new ValueObjectConstResult (exe_scope,
- clang_type,
+ compiler_type,
name,
data_sp,
data_byte_order,
@@ -129,7 +129,7 @@ ValueObjectConstResult::Create (ExecutionContextScope *exe_scope,
}
ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
const lldb::DataBufferSP &data_sp,
lldb::ByteOrder data_byte_order,
@@ -145,8 +145,8 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope
m_data.SetData(data_sp);
m_value.GetScalar() = (uintptr_t)data_sp->GetBytes();
m_value.SetValueType(Value::eValueTypeHostAddress);
- //m_value.SetContext(Value::eContextTypeClangType, clang_type);
- m_value.SetClangType (clang_type);
+ //m_value.SetContext(Value::eContextTypeClangType, compiler_type);
+ m_value.SetCompilerType (compiler_type);
m_name = name;
SetIsConstant ();
SetValueIsValid(true);
@@ -155,14 +155,14 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope
ValueObjectSP
ValueObjectConstResult::Create (ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
lldb::addr_t address,
AddressType address_type,
uint32_t addr_byte_size)
{
return (new ValueObjectConstResult (exe_scope,
- clang_type,
+ compiler_type,
name,
address,
address_type,
@@ -170,7 +170,7 @@ ValueObjectConstResult::Create (ExecutionContextScope *exe_scope,
}
ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
lldb::addr_t address,
AddressType address_type,
@@ -191,8 +191,8 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope
case eAddressTypeLoad: m_value.SetValueType(Value::eValueTypeLoadAddress); break;
case eAddressTypeHost: m_value.SetValueType(Value::eValueTypeHostAddress); break;
}
-// m_value.SetContext(Value::eContextTypeClangType, clang_type);
- m_value.SetClangType (clang_type);
+// m_value.SetContext(Value::eContextTypeClangType, compiler_type);
+ m_value.SetCompilerType (compiler_type);
m_name = name;
SetIsConstant ();
SetValueIsValid(true);
@@ -241,10 +241,10 @@ ValueObjectConstResult::~ValueObjectConstResult()
{
}
-ClangASTType
-ValueObjectConstResult::GetClangTypeImpl()
+CompilerType
+ValueObjectConstResult::GetCompilerTypeImpl()
{
- return m_value.GetClangType();
+ return m_value.GetCompilerType();
}
lldb::ValueType
@@ -259,7 +259,7 @@ ValueObjectConstResult::GetByteSize()
ExecutionContext exe_ctx(GetExecutionContextRef());
if (m_byte_size == 0)
- SetByteSize(GetClangType().GetByteSize(exe_ctx.GetBestExecutionContextScope()));
+ SetByteSize(GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope()));
return m_byte_size;
}
@@ -270,23 +270,24 @@ ValueObjectConstResult::SetByteSize (size_t size)
}
size_t
-ValueObjectConstResult::CalculateNumChildren()
+ValueObjectConstResult::CalculateNumChildren(uint32_t max)
{
- return GetClangType().GetNumChildren (true);
+ auto children_count = GetCompilerType().GetNumChildren (true);
+ return children_count <= max ? children_count : max;
}
ConstString
ValueObjectConstResult::GetTypeName()
{
if (m_type_name.IsEmpty())
- m_type_name = GetClangType().GetConstTypeName ();
+ m_type_name = GetCompilerType().GetConstTypeName ();
return m_type_name;
}
ConstString
ValueObjectConstResult::GetDisplayTypeName()
{
- return GetClangType().GetDisplayTypeName();
+ return GetCompilerType().GetDisplayTypeName();
}
bool
@@ -313,7 +314,7 @@ ValueObjectConstResult::Dereference (Error &error)
}
lldb::ValueObjectSP
-ValueObjectConstResult::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create)
+ValueObjectConstResult::GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create)
{
return m_impl.GetSyntheticChildAtOffset(offset, type, can_create);
}
@@ -365,8 +366,16 @@ ValueObjectConstResult::GetDynamicValue (lldb::DynamicValueType use_dynamic)
return ValueObjectSP();
}
+lldb::ValueObjectSP
+ValueObjectConstResult::Cast (const CompilerType &compiler_type)
+{
+ return m_impl.Cast(compiler_type);
+}
+
lldb::LanguageType
ValueObjectConstResult::GetPreferredDisplayLanguage ()
{
- return lldb::eLanguageTypeUnknown;
+ if (m_preferred_display_language != lldb::eLanguageTypeUnknown)
+ return m_preferred_display_language;
+ return GetCompilerTypeImpl().GetMinimumLanguage();
}
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultCast.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultCast.cpp
new file mode 100644
index 0000000..8f0c0f1
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultCast.cpp
@@ -0,0 +1,75 @@
+//===-- ValueObjectConstResultCast.cpp --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/ValueObjectConstResultCast.h"
+
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectList.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+
+using namespace lldb_private;
+
+ValueObjectConstResultCast::ValueObjectConstResultCast(
+ ValueObject &parent,
+ const ConstString &name,
+ const CompilerType &cast_type,
+ lldb::addr_t live_address) :
+ ValueObjectCast (parent, name, cast_type),
+ m_impl(this, live_address)
+{
+ m_name = name;
+}
+
+ValueObjectConstResultCast::~ValueObjectConstResultCast()
+{
+}
+
+lldb::ValueObjectSP
+ValueObjectConstResultCast::Dereference (Error &error)
+{
+ return m_impl.Dereference(error);
+}
+
+lldb::ValueObjectSP
+ValueObjectConstResultCast::GetSyntheticChildAtOffset(uint32_t offset,
+ const CompilerType& type,
+ bool can_create)
+{
+ return m_impl.GetSyntheticChildAtOffset(offset, type, can_create);
+}
+
+lldb::ValueObjectSP
+ValueObjectConstResultCast::AddressOf (Error &error)
+{
+ return m_impl.AddressOf(error);
+}
+
+ValueObject *
+ValueObjectConstResultCast::CreateChildAtIndex (size_t idx,
+ bool synthetic_array_member,
+ int32_t synthetic_index)
+{
+ return m_impl.CreateChildAtIndex(
+ idx, synthetic_array_member, synthetic_index);
+}
+
+size_t
+ValueObjectConstResultCast::GetPointeeData (DataExtractor& data,
+ uint32_t item_idx,
+ uint32_t item_count)
+{
+ return m_impl.GetPointeeData(data, item_idx, item_count);
+}
+
+lldb::ValueObjectSP
+ValueObjectConstResultCast::Cast (const CompilerType &compiler_type)
+{
+ return m_impl.Cast(compiler_type);
+}
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultChild.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultChild.cpp
index 64425ea..c93aedc 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultChild.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultChild.cpp
@@ -19,17 +19,19 @@ using namespace lldb_private;
ValueObjectConstResultChild::ValueObjectConstResultChild
(
ValueObject &parent,
- const ClangASTType &clang_type,
+ const CompilerType &compiler_type,
const ConstString &name,
uint32_t byte_size,
int32_t byte_offset,
uint32_t bitfield_bit_size,
uint32_t bitfield_bit_offset,
bool is_base_class,
- bool is_deref_of_parent
+ bool is_deref_of_parent,
+ lldb::addr_t live_address,
+ uint64_t language_flags
) :
ValueObjectChild (parent,
- clang_type,
+ compiler_type,
name,
byte_size,
byte_offset,
@@ -37,8 +39,9 @@ ValueObjectConstResultChild::ValueObjectConstResultChild
bitfield_bit_offset,
is_base_class,
is_deref_of_parent,
- eAddressTypeLoad),
- m_impl(this)
+ eAddressTypeLoad,
+ language_flags),
+ m_impl(this, live_address)
{
m_name = name;
}
@@ -54,7 +57,7 @@ ValueObjectConstResultChild::Dereference (Error &error)
}
lldb::ValueObjectSP
-ValueObjectConstResultChild::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create)
+ValueObjectConstResultChild::GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create)
{
return m_impl.GetSyntheticChildAtOffset(offset, type, can_create);
}
@@ -78,3 +81,9 @@ ValueObjectConstResultChild::GetPointeeData (DataExtractor& data,
{
return m_impl.GetPointeeData(data, item_idx, item_count);
}
+
+lldb::ValueObjectSP
+ValueObjectConstResultChild::Cast (const CompilerType &compiler_type)
+{
+ return m_impl.Cast(compiler_type);
+}
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultImpl.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultImpl.cpp
index 733d767..85ac3f2 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultImpl.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectConstResultImpl.cpp
@@ -11,13 +11,14 @@
#include "lldb/Core/ValueObjectChild.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectConstResultCast.h"
#include "lldb/Core/ValueObjectConstResultChild.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ValueObjectList.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
@@ -68,27 +69,29 @@ ValueObjectConstResultImpl::CreateChildAtIndex (size_t idx, bool synthetic_array
uint32_t child_bitfield_bit_offset = 0;
bool child_is_base_class = false;
bool child_is_deref_of_parent = false;
+ uint64_t language_flags;
const bool transparent_pointers = synthetic_array_member == false;
- ClangASTType clang_type = m_impl_backend->GetClangType();
- ClangASTType child_clang_type;
+ CompilerType compiler_type = m_impl_backend->GetCompilerType();
+ CompilerType child_compiler_type;
ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
- child_clang_type = clang_type.GetChildClangTypeAtIndex (&exe_ctx,
- idx,
- transparent_pointers,
- omit_empty_base_classes,
- ignore_array_bounds,
- child_name_str,
- child_byte_size,
- child_byte_offset,
- child_bitfield_bit_size,
- child_bitfield_bit_offset,
- child_is_base_class,
- child_is_deref_of_parent,
- m_impl_backend);
- if (child_clang_type && child_byte_size)
+ child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex (&exe_ctx,
+ idx,
+ transparent_pointers,
+ omit_empty_base_classes,
+ ignore_array_bounds,
+ child_name_str,
+ child_byte_size,
+ child_byte_offset,
+ child_bitfield_bit_size,
+ child_bitfield_bit_offset,
+ child_is_base_class,
+ child_is_deref_of_parent,
+ m_impl_backend,
+ language_flags);
+ if (child_compiler_type && child_byte_size)
{
if (synthetic_index)
child_byte_offset += child_byte_size * synthetic_index;
@@ -96,25 +99,25 @@ ValueObjectConstResultImpl::CreateChildAtIndex (size_t idx, bool synthetic_array
ConstString child_name;
if (!child_name_str.empty())
child_name.SetCString (child_name_str.c_str());
-
+
valobj = new ValueObjectConstResultChild (*m_impl_backend,
- child_clang_type,
+ child_compiler_type,
child_name,
child_byte_size,
child_byte_offset,
child_bitfield_bit_size,
child_bitfield_bit_offset,
child_is_base_class,
- child_is_deref_of_parent);
- if (m_live_address != LLDB_INVALID_ADDRESS)
- valobj->m_impl.SetLiveAddress(m_live_address+child_byte_offset);
+ child_is_deref_of_parent,
+ m_live_address == LLDB_INVALID_ADDRESS ? m_live_address : m_live_address+child_byte_offset,
+ language_flags);
}
return valobj;
}
lldb::ValueObjectSP
-ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create)
+ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, const CompilerType& type, bool can_create)
{
if (m_impl_backend == NULL)
return lldb::ValueObjectSP();
@@ -132,7 +135,7 @@ ValueObjectConstResultImpl::AddressOf (Error &error)
return lldb::ValueObjectSP();
if (m_live_address != LLDB_INVALID_ADDRESS)
{
- ClangASTType clang_type(m_impl_backend->GetClangType());
+ CompilerType compiler_type(m_impl_backend->GetCompilerType());
lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&m_live_address,sizeof(lldb::addr_t)));
@@ -140,10 +143,10 @@ ValueObjectConstResultImpl::AddressOf (Error &error)
new_name.append(m_impl_backend->GetName().AsCString(""));
ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
m_address_of_backend = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
- clang_type.GetPointerType(),
+ compiler_type.GetPointerType(),
ConstString(new_name.c_str()),
buffer,
- lldb::endian::InlHostByteOrder(),
+ endian::InlHostByteOrder(),
exe_ctx.GetAddressByteSize());
m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar);
@@ -155,6 +158,17 @@ ValueObjectConstResultImpl::AddressOf (Error &error)
return m_impl_backend->ValueObject::AddressOf(error);
}
+lldb::ValueObjectSP
+ValueObjectConstResultImpl::Cast (const CompilerType &compiler_type)
+{
+ if (m_impl_backend == NULL)
+ return lldb::ValueObjectSP();
+
+ ValueObjectConstResultCast *result_cast = new ValueObjectConstResultCast(
+ *m_impl_backend, m_impl_backend->GetName(), compiler_type, m_live_address);
+ return result_cast->GetSP();
+}
+
lldb::addr_t
ValueObjectConstResultImpl::GetAddressOf (bool scalar_is_load_address,
AddressType *address_type)
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectDynamicValue.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectDynamicValue.cpp
index 89b98a1..0ac86a6 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectDynamicValue.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectDynamicValue.cpp
@@ -20,7 +20,7 @@
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
@@ -49,18 +49,18 @@ ValueObjectDynamicValue::~ValueObjectDynamicValue()
m_owning_valobj_sp.reset();
}
-ClangASTType
-ValueObjectDynamicValue::GetClangTypeImpl ()
+CompilerType
+ValueObjectDynamicValue::GetCompilerTypeImpl ()
{
const bool success = UpdateValueIfNeeded(false);
if (success)
{
if (m_dynamic_type_info.HasType())
- return m_value.GetClangType();
+ return m_value.GetCompilerType();
else
- return m_parent->GetClangType();
+ return m_parent->GetCompilerType();
}
- return m_parent->GetClangType();
+ return m_parent->GetCompilerType();
}
ConstString
@@ -105,7 +105,7 @@ ValueObjectDynamicValue::GetDisplayTypeName()
if (success)
{
if (m_dynamic_type_info.HasType())
- return GetClangType().GetDisplayTypeName();
+ return GetCompilerType().GetDisplayTypeName();
if (m_dynamic_type_info.HasName())
return m_dynamic_type_info.GetName();
}
@@ -113,13 +113,16 @@ ValueObjectDynamicValue::GetDisplayTypeName()
}
size_t
-ValueObjectDynamicValue::CalculateNumChildren()
+ValueObjectDynamicValue::CalculateNumChildren(uint32_t max)
{
const bool success = UpdateValueIfNeeded(false);
if (success && m_dynamic_type_info.HasType())
- return GetClangType().GetNumChildren (true);
+ {
+ auto children_count = GetCompilerType().GetNumChildren (true);
+ return children_count <= max ? children_count : max;
+ }
else
- return m_parent->GetNumChildren();
+ return m_parent->GetNumChildren(max);
}
uint64_t
@@ -127,7 +130,10 @@ ValueObjectDynamicValue::GetByteSize()
{
const bool success = UpdateValueIfNeeded(false);
if (success && m_dynamic_type_info.HasType())
- return m_value.GetValueByteSize(nullptr);
+ {
+ ExecutionContext exe_ctx (GetExecutionContextRef());
+ return m_value.GetValueByteSize(nullptr, &exe_ctx);
+ }
else
return m_parent->GetByteSize();
}
@@ -138,40 +144,6 @@ ValueObjectDynamicValue::GetValueType() const
return m_parent->GetValueType();
}
-
-static TypeAndOrName
-FixupTypeAndOrName (const TypeAndOrName& type_andor_name,
- ValueObject& parent)
-{
- TypeAndOrName ret(type_andor_name);
- if (type_andor_name.HasType())
- {
- // The type will always be the type of the dynamic object. If our parent's type was a pointer,
- // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type
- // should be okay...
- ClangASTType orig_type = type_andor_name.GetClangASTType();
- ClangASTType corrected_type = orig_type;
- if (parent.IsPointerType())
- corrected_type = orig_type.GetPointerType ();
- else if (parent.IsPointerOrReferenceType())
- corrected_type = orig_type.GetLValueReferenceType ();
- ret.SetClangASTType(corrected_type);
- }
- else /*if (m_dynamic_type_info.HasName())*/
- {
- // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
- std::string corrected_name (type_andor_name.GetName().GetCString());
- if (parent.IsPointerType())
- corrected_name.append(" *");
- else if (parent.IsPointerOrReferenceType())
- corrected_name.append(" &");
- // the parent type should be a correctly pointer'ed or referenc'ed type
- ret.SetClangASTType(parent.GetClangType());
- ret.SetName(corrected_name.c_str());
- }
- return ret;
-}
-
bool
ValueObjectDynamicValue::UpdateValue ()
{
@@ -210,25 +182,28 @@ ValueObjectDynamicValue::UpdateValue ()
TypeAndOrName class_type_or_name;
Address dynamic_address;
bool found_dynamic_type = false;
+ Value::ValueType value_type;
+
+ LanguageRuntime *runtime = nullptr;
lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC)
{
- LanguageRuntime *runtime = process->GetLanguageRuntime (known_type);
+ runtime = process->GetLanguageRuntime (known_type);
if (runtime)
- found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
+ found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type);
}
else
{
- LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus);
- if (cpp_runtime)
- found_dynamic_type = cpp_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
+ runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus);
+ if (runtime)
+ found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type);
if (!found_dynamic_type)
{
- LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
- if (objc_runtime)
- found_dynamic_type = objc_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
+ runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
+ if (runtime)
+ found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type);
}
}
@@ -237,11 +212,12 @@ ValueObjectDynamicValue::UpdateValue ()
m_update_point.SetUpdated();
- if (found_dynamic_type)
+ if (runtime && found_dynamic_type)
{
if (class_type_or_name.HasType())
{
- m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType());
+ m_type_impl = TypeImpl(m_parent->GetCompilerType(),
+ runtime->FixUpDynamicType(class_type_or_name, *m_parent).GetCompilerType());
}
else
{
@@ -300,14 +276,13 @@ ValueObjectDynamicValue::UpdateValue ()
m_value.GetScalar() = load_address;
}
- m_dynamic_type_info = FixupTypeAndOrName(m_dynamic_type_info, *m_parent);
+ if (runtime)
+ m_dynamic_type_info = runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
//m_value.SetContext (Value::eContextTypeClangType, corrected_type);
- m_value.SetClangType (m_dynamic_type_info.GetClangASTType());
+ m_value.SetCompilerType (m_dynamic_type_info.GetCompilerType());
- // Our address is the location of the dynamic type stored in memory. It isn't a load address,
- // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us...
- m_value.SetValueType(Value::eValueTypeScalar);
+ m_value.SetValueType(value_type);
if (has_changed_type && log)
log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(),
@@ -421,3 +396,50 @@ ValueObjectDynamicValue::SetData (DataExtractor &data, Error &error)
SetNeedsUpdate();
return ret_val;
}
+
+void
+ValueObjectDynamicValue::SetPreferredDisplayLanguage (lldb::LanguageType lang)
+{
+ this->ValueObject::SetPreferredDisplayLanguage(lang);
+ if (m_parent)
+ m_parent->SetPreferredDisplayLanguage(lang);
+}
+
+lldb::LanguageType
+ValueObjectDynamicValue::GetPreferredDisplayLanguage ()
+{
+ if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
+ {
+ if (m_parent)
+ return m_parent->GetPreferredDisplayLanguage();
+ return lldb::eLanguageTypeUnknown;
+ }
+ else
+ return m_preferred_display_language;
+}
+
+bool
+ValueObjectDynamicValue::GetDeclaration (Declaration &decl)
+{
+ if (m_parent)
+ return m_parent->GetDeclaration(decl);
+
+ return ValueObject::GetDeclaration(decl);
+}
+
+uint64_t
+ValueObjectDynamicValue::GetLanguageFlags ()
+{
+ if (m_parent)
+ return m_parent->GetLanguageFlags();
+ return this->ValueObject::GetLanguageFlags();
+}
+
+void
+ValueObjectDynamicValue::SetLanguageFlags (uint64_t flags)
+{
+ if (m_parent)
+ m_parent->SetLanguageFlags(flags);
+ else
+ this->ValueObject::SetLanguageFlags(flags);
+}
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectMemory.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectMemory.cpp
index 9f19531..b989710 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectMemory.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectMemory.cpp
@@ -46,7 +46,7 @@ ValueObjectSP
ValueObjectMemory::Create (ExecutionContextScope *exe_scope,
const char *name,
const Address &address,
- const ClangASTType &ast_type)
+ const CompilerType &ast_type)
{
return (new ValueObjectMemory (exe_scope, name, address, ast_type))->GetSP();
}
@@ -58,7 +58,7 @@ ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope,
ValueObject(exe_scope),
m_address (address),
m_type_sp(type_sp),
- m_clang_type()
+ m_compiler_type()
{
// Do not attempt to construct one of these objects with no variable!
assert (m_type_sp.get() != NULL);
@@ -90,21 +90,21 @@ ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope,
ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope,
const char *name,
const Address &address,
- const ClangASTType &ast_type) :
+ const CompilerType &ast_type) :
ValueObject(exe_scope),
m_address (address),
m_type_sp(),
- m_clang_type(ast_type)
+ m_compiler_type(ast_type)
{
// Do not attempt to construct one of these objects with no variable!
- assert (m_clang_type.GetASTContext());
- assert (m_clang_type.GetOpaqueQualType());
+ assert (m_compiler_type.GetTypeSystem());
+ assert (m_compiler_type.GetOpaqueQualType());
TargetSP target_sp (GetTargetSP());
SetName (ConstString(name));
-// m_value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType());
- m_value.SetClangType(m_clang_type);
+// m_value.SetContext(Value::eContextTypeClangType, m_compiler_type.GetOpaqueQualType());
+ m_value.SetCompilerType(m_compiler_type);
lldb::addr_t load_address = m_address.GetLoadAddress (target_sp.get());
if (load_address != LLDB_INVALID_ADDRESS)
{
@@ -131,12 +131,12 @@ ValueObjectMemory::~ValueObjectMemory()
{
}
-ClangASTType
-ValueObjectMemory::GetClangTypeImpl ()
+CompilerType
+ValueObjectMemory::GetCompilerTypeImpl ()
{
if (m_type_sp)
- return m_type_sp->GetClangForwardType();
- return m_clang_type;
+ return m_type_sp->GetForwardCompilerType ();
+ return m_compiler_type;
}
ConstString
@@ -144,24 +144,29 @@ ValueObjectMemory::GetTypeName()
{
if (m_type_sp)
return m_type_sp->GetName();
- return m_clang_type.GetConstTypeName();
+ return m_compiler_type.GetConstTypeName();
}
ConstString
ValueObjectMemory::GetDisplayTypeName()
{
if (m_type_sp)
- return m_type_sp->GetClangForwardType().GetDisplayTypeName();
- return m_clang_type.GetDisplayTypeName();
+ return m_type_sp->GetForwardCompilerType ().GetDisplayTypeName();
+ return m_compiler_type.GetDisplayTypeName();
}
size_t
-ValueObjectMemory::CalculateNumChildren()
+ValueObjectMemory::CalculateNumChildren(uint32_t max)
{
if (m_type_sp)
- return m_type_sp->GetNumChildren(true);
+ {
+ auto child_count = m_type_sp->GetNumChildren(true);
+ return child_count <= max ? child_count : max;
+ }
+
const bool omit_empty_base_classes = true;
- return m_clang_type.GetNumChildren (omit_empty_base_classes);
+ auto child_count = m_compiler_type.GetNumChildren (omit_empty_base_classes);
+ return child_count <= max ? child_count : max;
}
uint64_t
@@ -169,7 +174,7 @@ ValueObjectMemory::GetByteSize()
{
if (m_type_sp)
return m_type_sp->GetByteSize();
- return m_clang_type.GetByteSize (nullptr);
+ return m_compiler_type.GetByteSize (nullptr);
}
lldb::ValueType
@@ -249,8 +254,8 @@ ValueObjectMemory::UpdateValue ()
value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
else
{
- //value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType());
- value.SetClangType(m_clang_type);
+ //value.SetContext(Value::eContextTypeClangType, m_compiler_type.GetOpaqueQualType());
+ value.SetCompilerType(m_compiler_type);
}
m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectRegister.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectRegister.cpp
index 0db1f0c..c7845cd 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectRegister.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectRegister.cpp
@@ -15,7 +15,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Module.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/ExecutionContext.h"
@@ -42,10 +42,10 @@ ValueObjectRegisterContext::~ValueObjectRegisterContext()
{
}
-ClangASTType
-ValueObjectRegisterContext::GetClangTypeImpl ()
+CompilerType
+ValueObjectRegisterContext::GetCompilerTypeImpl ()
{
- return ClangASTType();
+ return CompilerType();
}
ConstString
@@ -67,9 +67,10 @@ ValueObjectRegisterContext::GetQualifiedTypeName()
}
size_t
-ValueObjectRegisterContext::CalculateNumChildren()
+ValueObjectRegisterContext::CalculateNumChildren(uint32_t max)
{
- return m_reg_ctx_sp->GetRegisterSetCount();
+ auto reg_set_count = m_reg_ctx_sp->GetRegisterSetCount();
+ return reg_set_count <= max ? reg_set_count : max;
}
uint64_t
@@ -144,10 +145,10 @@ ValueObjectRegisterSet::~ValueObjectRegisterSet()
{
}
-ClangASTType
-ValueObjectRegisterSet::GetClangTypeImpl ()
+CompilerType
+ValueObjectRegisterSet::GetCompilerTypeImpl ()
{
- return ClangASTType();
+ return CompilerType();
}
ConstString
@@ -163,11 +164,14 @@ ValueObjectRegisterSet::GetQualifiedTypeName()
}
size_t
-ValueObjectRegisterSet::CalculateNumChildren()
+ValueObjectRegisterSet::CalculateNumChildren(uint32_t max)
{
const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
if (reg_set)
- return reg_set->num_registers;
+ {
+ auto reg_count = reg_set->num_registers;
+ return reg_count <= max ? reg_count : max;
+ }
return 0;
}
@@ -279,7 +283,7 @@ ValueObjectRegister::ValueObjectRegister (ValueObject &parent, lldb::RegisterCon
m_reg_info (),
m_reg_value (),
m_type_name (),
- m_clang_type ()
+ m_compiler_type ()
{
assert (reg_ctx_sp.get());
ConstructObject(reg_num);
@@ -297,7 +301,7 @@ ValueObjectRegister::ValueObjectRegister (ExecutionContextScope *exe_scope, lldb
m_reg_info (),
m_reg_value (),
m_type_name (),
- m_clang_type ()
+ m_compiler_type ()
{
assert (reg_ctx);
ConstructObject(reg_num);
@@ -307,10 +311,10 @@ ValueObjectRegister::~ValueObjectRegister()
{
}
-ClangASTType
-ValueObjectRegister::GetClangTypeImpl ()
+CompilerType
+ValueObjectRegister::GetCompilerTypeImpl ()
{
- if (!m_clang_type.IsValid())
+ if (!m_compiler_type.IsValid())
{
ExecutionContext exe_ctx (GetExecutionContextRef());
Target *target = exe_ctx.GetTargetPtr();
@@ -319,26 +323,29 @@ ValueObjectRegister::GetClangTypeImpl ()
Module *exe_module = target->GetExecutableModulePointer();
if (exe_module)
{
- m_clang_type = exe_module->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize (m_reg_info.encoding,
- m_reg_info.byte_size * 8);
+ TypeSystem *type_system = exe_module->GetTypeSystemForLanguage (eLanguageTypeC);
+ if (type_system)
+ m_compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize (m_reg_info.encoding,
+ m_reg_info.byte_size * 8);
}
}
}
- return m_clang_type;
+ return m_compiler_type;
}
ConstString
ValueObjectRegister::GetTypeName()
{
if (m_type_name.IsEmpty())
- m_type_name = GetClangType().GetConstTypeName ();
+ m_type_name = GetCompilerType().GetConstTypeName ();
return m_type_name;
}
size_t
-ValueObjectRegister::CalculateNumChildren()
+ValueObjectRegister::CalculateNumChildren(uint32_t max)
{
- return GetClangType().GetNumChildren(true);
+ auto children_count = GetCompilerType().GetNumChildren (true);
+ return children_count <= max ? children_count : max;
}
uint64_t
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectSyntheticFilter.cpp
index 867b520..0ccc438 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectSyntheticFilter.cpp
@@ -1,4 +1,4 @@
-//===-- ValueObjectSyntheticFilter.cpp -----------------------------*- C++ -*-===//
+//===-- ValueObjectSyntheticFilter.cpp --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/ValueObjectSyntheticFilter.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Core/ValueObjectSyntheticFilter.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
@@ -26,35 +25,34 @@ public:
{}
size_t
- CalculateNumChildren()
+ CalculateNumChildren() override
{
return m_backend.GetNumChildren();
}
lldb::ValueObjectSP
- GetChildAtIndex (size_t idx)
+ GetChildAtIndex(size_t idx) override
{
return m_backend.GetChildAtIndex(idx, true);
}
-
+
size_t
- GetIndexOfChildWithName (const ConstString &name)
+ GetIndexOfChildWithName(const ConstString &name) override
{
return m_backend.GetIndexOfChildWithName(name);
}
bool
- MightHaveChildren ()
+ MightHaveChildren() override
{
return true;
}
bool
- Update()
+ Update() override
{
return false;
}
-
};
ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) :
@@ -78,14 +76,12 @@ ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::Synthetic
CreateSynthFilter();
}
-ValueObjectSynthetic::~ValueObjectSynthetic()
-{
-}
+ValueObjectSynthetic::~ValueObjectSynthetic() = default;
-ClangASTType
-ValueObjectSynthetic::GetClangTypeImpl ()
+CompilerType
+ValueObjectSynthetic::GetCompilerTypeImpl ()
{
- return m_parent->GetClangType();
+ return m_parent->GetCompilerType();
}
ConstString
@@ -107,12 +103,16 @@ ValueObjectSynthetic::GetDisplayTypeName()
}
size_t
-ValueObjectSynthetic::CalculateNumChildren()
+ValueObjectSynthetic::CalculateNumChildren(uint32_t max)
{
UpdateValueIfNeeded();
if (m_synthetic_children_count < UINT32_MAX)
- return m_synthetic_children_count;
- return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren());
+ return m_synthetic_children_count <= max ? m_synthetic_children_count : max;
+
+ if (max < UINT32_MAX)
+ return m_synth_filter_ap->CalculateNumChildren(max);
+ else
+ return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren(max));
}
lldb::ValueObjectSP
@@ -217,12 +217,13 @@ ValueObjectSynthetic::GetChildAtIndex (size_t idx, bool can_create)
ValueObject *valobj;
if (m_children_byindex.GetValueForKey(idx, valobj) == false)
{
- if (can_create && m_synth_filter_ap.get() != NULL)
+ if (can_create && m_synth_filter_ap.get() != nullptr)
{
lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx);
if (!synth_guy)
return synth_guy;
m_children_byindex.SetValueForKey(idx, synth_guy.get());
+ synth_guy->SetPreferredDisplayLanguageIfNeeded(GetPreferredDisplayLanguage());
return synth_guy;
}
else
@@ -253,7 +254,7 @@ ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name)
uint32_t found_index = UINT32_MAX;
bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index);
- if (!did_find && m_synth_filter_ap.get() != NULL)
+ if (!did_find && m_synth_filter_ap.get() != nullptr)
{
uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name);
if (index == UINT32_MAX)
@@ -261,7 +262,7 @@ ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name)
m_name_toindex.SetValueForKey(name.GetCString(), index);
return index;
}
- else if (!did_find && m_synth_filter_ap.get() == NULL)
+ else if (!did_find && m_synth_filter_ap.get() == nullptr)
return UINT32_MAX;
else /*if (iter != m_name_toindex.end())*/
return found_index;
@@ -314,3 +315,50 @@ ValueObjectSynthetic::SetFormat (lldb::Format format)
this->ValueObject::SetFormat(format);
this->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
}
+
+void
+ValueObjectSynthetic::SetPreferredDisplayLanguage (lldb::LanguageType lang)
+{
+ this->ValueObject::SetPreferredDisplayLanguage(lang);
+ if (m_parent)
+ m_parent->SetPreferredDisplayLanguage(lang);
+}
+
+lldb::LanguageType
+ValueObjectSynthetic::GetPreferredDisplayLanguage ()
+{
+ if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
+ {
+ if (m_parent)
+ return m_parent->GetPreferredDisplayLanguage();
+ return lldb::eLanguageTypeUnknown;
+ }
+ else
+ return m_preferred_display_language;
+}
+
+bool
+ValueObjectSynthetic::GetDeclaration (Declaration &decl)
+{
+ if (m_parent)
+ return m_parent->GetDeclaration(decl);
+
+ return ValueObject::GetDeclaration(decl);
+}
+
+uint64_t
+ValueObjectSynthetic::GetLanguageFlags ()
+{
+ if (m_parent)
+ return m_parent->GetLanguageFlags();
+ return this->ValueObject::GetLanguageFlags();
+}
+
+void
+ValueObjectSynthetic::SetLanguageFlags (uint64_t flags)
+{
+ if (m_parent)
+ m_parent->SetLanguageFlags(flags);
+ else
+ this->ValueObject::SetLanguageFlags(flags);
+}
diff --git a/contrib/llvm/tools/lldb/source/Core/ValueObjectVariable.cpp b/contrib/llvm/tools/lldb/source/Core/ValueObjectVariable.cpp
index c86bece..389b7c5 100644
--- a/contrib/llvm/tools/lldb/source/Core/ValueObjectVariable.cpp
+++ b/contrib/llvm/tools/lldb/source/Core/ValueObjectVariable.cpp
@@ -54,13 +54,13 @@ ValueObjectVariable::~ValueObjectVariable()
{
}
-ClangASTType
-ValueObjectVariable::GetClangTypeImpl ()
+CompilerType
+ValueObjectVariable::GetCompilerTypeImpl ()
{
Type *var_type = m_variable_sp->GetType();
if (var_type)
- return var_type->GetClangForwardType();
- return ClangASTType();
+ return var_type->GetForwardCompilerType ();
+ return CompilerType();
}
ConstString
@@ -77,7 +77,7 @@ ValueObjectVariable::GetDisplayTypeName()
{
Type * var_type = m_variable_sp->GetType();
if (var_type)
- return var_type->GetClangForwardType().GetDisplayTypeName();
+ return var_type->GetForwardCompilerType ().GetDisplayTypeName();
return ConstString();
}
@@ -91,15 +91,16 @@ ValueObjectVariable::GetQualifiedTypeName()
}
size_t
-ValueObjectVariable::CalculateNumChildren()
+ValueObjectVariable::CalculateNumChildren(uint32_t max)
{
- ClangASTType type(GetClangType());
+ CompilerType type(GetCompilerType());
if (!type.IsValid())
return 0;
const bool omit_empty_base_classes = true;
- return type.GetNumChildren(omit_empty_base_classes);
+ auto child_count = type.GetNumChildren(omit_empty_base_classes);
+ return child_count <= max ? child_count : max;
}
uint64_t
@@ -107,7 +108,7 @@ ValueObjectVariable::GetByteSize()
{
ExecutionContext exe_ctx(GetExecutionContextRef());
- ClangASTType type(GetClangType());
+ CompilerType type(GetCompilerType());
if (!type.IsValid())
return 0;
@@ -168,15 +169,15 @@ ValueObjectVariable::UpdateValue ()
m_resolved_value = m_value;
m_value.SetContext(Value::eContextTypeVariable, variable);
- ClangASTType clang_type = GetClangType();
- if (clang_type.IsValid())
- m_value.SetClangType(clang_type);
+ CompilerType compiler_type = GetCompilerType();
+ if (compiler_type.IsValid())
+ m_value.SetCompilerType(compiler_type);
Value::ValueType value_type = m_value.GetValueType();
Process *process = exe_ctx.GetProcessPtr();
const bool process_is_alive = process && process->IsAlive();
- const uint32_t type_info = clang_type.GetTypeInfo();
+ const uint32_t type_info = compiler_type.GetTypeInfo();
const bool is_pointer_or_ref = (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0;
switch (value_type)
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/CXXFormatterFunctions.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/CXXFormatterFunctions.cpp
deleted file mode 100644
index 49eacee..0000000
--- a/contrib/llvm/tools/lldb/source/DataFormatters/CXXFormatterFunctions.cpp
+++ /dev/null
@@ -1,1228 +0,0 @@
-//===-- CXXFormatterFunctions.cpp---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
-#include "lldb/DataFormatters/StringPrinter.h"
-#include "lldb/DataFormatters/TypeSummary.h"
-
-#include "llvm/Support/ConvertUTF.h"
-
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Host/Endian.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Target/SectionLoadList.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-
-#include "lldb/Utility/ProcessStructReader.h"
-
-#include <algorithm>
-
-#if __ANDROID_NDK__
-#include <sys/types.h>
-#endif
-
-#include "lldb/Host/Time.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace lldb_private::formatters;
-
-StackFrame*
-lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx)
-{
- StackFrame* frame = exe_ctx.GetFramePtr();
- if (frame)
- return frame;
-
- Process* process = exe_ctx.GetProcessPtr();
- if (!process)
- return nullptr;
-
- ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
- if (thread_sp)
- return thread_sp->GetSelectedFrame().get();
- return nullptr;
-}
-
-bool
-lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
- const char* target_type,
- const char* selector,
- uint64_t &value)
-{
- if (!target_type || !*target_type)
- return false;
- if (!selector || !*selector)
- return false;
- StreamString expr;
- expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
- ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
- lldb::ValueObjectSP result_sp;
- Target* target = exe_ctx.GetTargetPtr();
- StackFrame* stack_frame = GetViableFrame(exe_ctx);
- if (!target || !stack_frame)
- return false;
-
- EvaluateExpressionOptions options;
- options.SetCoerceToId(false);
- options.SetUnwindOnError(true);
- options.SetKeepInMemory(true);
-
- target->EvaluateExpression(expr.GetData(),
- stack_frame,
- result_sp,
- options);
- if (!result_sp)
- return false;
- value = result_sp->GetValueAsUnsigned(0);
- return true;
-}
-
-bool
-lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
- const char* target_type,
- const char* selector,
- Stream &stream)
-{
- if (!target_type || !*target_type)
- return false;
- if (!selector || !*selector)
- return false;
- StreamString expr;
- expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
- ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
- lldb::ValueObjectSP result_sp;
- Target* target = exe_ctx.GetTargetPtr();
- StackFrame* stack_frame = GetViableFrame(exe_ctx);
- if (!target || !stack_frame)
- return false;
-
- EvaluateExpressionOptions options;
- options.SetCoerceToId(false);
- options.SetUnwindOnError(true);
- options.SetKeepInMemory(true);
- options.SetUseDynamic(lldb::eDynamicCanRunTarget);
-
- target->EvaluateExpression(expr.GetData(),
- stack_frame,
- result_sp,
- options);
- if (!result_sp)
- return false;
- stream.Printf("%s",result_sp->GetSummaryAsCString());
- return true;
-}
-
-lldb::ValueObjectSP
-lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
- const char* return_type,
- const char* selector,
- uint64_t index)
-{
- lldb::ValueObjectSP valobj_sp;
- if (!return_type || !*return_type)
- return valobj_sp;
- if (!selector || !*selector)
- return valobj_sp;
- StreamString expr_path_stream;
- valobj.GetExpressionPath(expr_path_stream, false);
- StreamString expr;
- expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
- ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
- lldb::ValueObjectSP result_sp;
- Target* target = exe_ctx.GetTargetPtr();
- StackFrame* stack_frame = GetViableFrame(exe_ctx);
- if (!target || !stack_frame)
- return valobj_sp;
-
- EvaluateExpressionOptions options;
- options.SetCoerceToId(false);
- options.SetUnwindOnError(true);
- options.SetKeepInMemory(true);
- options.SetUseDynamic(lldb::eDynamicCanRunTarget);
-
- target->EvaluateExpression(expr.GetData(),
- stack_frame,
- valobj_sp,
- options);
- return valobj_sp;
-}
-
-lldb::ValueObjectSP
-lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
- const char* return_type,
- const char* selector,
- const char* key)
-{
- lldb::ValueObjectSP valobj_sp;
- if (!return_type || !*return_type)
- return valobj_sp;
- if (!selector || !*selector)
- return valobj_sp;
- if (!key || !*key)
- return valobj_sp;
- StreamString expr_path_stream;
- valobj.GetExpressionPath(expr_path_stream, false);
- StreamString expr;
- expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
- ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
- lldb::ValueObjectSP result_sp;
- Target* target = exe_ctx.GetTargetPtr();
- StackFrame* stack_frame = GetViableFrame(exe_ctx);
- if (!target || !stack_frame)
- return valobj_sp;
-
- EvaluateExpressionOptions options;
- options.SetCoerceToId(false);
- options.SetUnwindOnError(true);
- options.SetKeepInMemory(true);
- options.SetUseDynamic(lldb::eDynamicCanRunTarget);
-
- target->EvaluateExpression(expr.GetData(),
- stack_frame,
- valobj_sp,
- options);
- return valobj_sp;
-}
-
-bool
-lldb_private::formatters::FunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
-{
- std::string destination;
- StreamString sstr;
- AddressType func_ptr_address_type = eAddressTypeInvalid;
- addr_t func_ptr_address = valobj.GetPointerValue (&func_ptr_address_type);
- if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS)
- {
- switch (func_ptr_address_type)
- {
- case eAddressTypeInvalid:
- case eAddressTypeFile:
- case eAddressTypeHost:
- break;
-
- case eAddressTypeLoad:
- {
- ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
-
- Address so_addr;
- Target *target = exe_ctx.GetTargetPtr();
- if (target && target->GetSectionLoadList().IsEmpty() == false)
- {
- if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr))
- {
- so_addr.Dump (&sstr,
- exe_ctx.GetBestExecutionContextScope(),
- Address::DumpStyleResolvedDescription,
- Address::DumpStyleSectionNameOffset);
- }
- }
- }
- break;
- }
- }
- if (sstr.GetSize() > 0)
- {
- stream.Printf("(%s)", sstr.GetData());
- return true;
- }
- else
- return false;
-}
-
-bool
-lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
-{
- ProcessSP process_sp = valobj.GetProcessSP();
- if (!process_sp)
- return false;
-
- lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
-
- if (!valobj_addr)
- return false;
-
- ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(valobj_addr);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetPrefixToken('u');
-
- if (!ReadStringAndDumpToStream<StringElementType::UTF16>(options))
- {
- stream.Printf("Summary Unavailable");
- return true;
- }
-
- return true;
-}
-
-bool
-lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
-{
- ProcessSP process_sp = valobj.GetProcessSP();
- if (!process_sp)
- return false;
-
- lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
-
- if (!valobj_addr)
- return false;
-
- ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(valobj_addr);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetPrefixToken('U');
-
- if (!ReadStringAndDumpToStream<StringElementType::UTF32>(options))
- {
- stream.Printf("Summary Unavailable");
- return true;
- }
-
- return true;
-}
-
-bool
-lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
-{
- ProcessSP process_sp = valobj.GetProcessSP();
- if (!process_sp)
- return false;
-
- lldb::addr_t data_addr = 0;
-
- if (valobj.IsPointerType())
- data_addr = valobj.GetValueAsUnsigned(0);
- else if (valobj.IsArrayType())
- data_addr = valobj.GetAddressOf();
-
- if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
- return false;
-
- clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
-
- if (!ast)
- return false;
-
- ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
- const uint32_t wchar_size = wchar_clang_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here
-
- ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(data_addr);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetPrefixToken('L');
-
- switch (wchar_size)
- {
- case 8:
- return ReadStringAndDumpToStream<StringElementType::UTF8>(options);
- case 16:
- return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
- case 32:
- return ReadStringAndDumpToStream<StringElementType::UTF32>(options);
- default:
- stream.Printf("size for wchar_t is not valid");
- return true;
- }
- return true;
-}
-
-bool
-lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
-{
- DataExtractor data;
- Error error;
- valobj.GetData(data, error);
-
- if (error.Fail())
- return false;
-
- std::string value;
- valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
- if (!value.empty())
- stream.Printf("%s ", value.c_str());
-
- ReadBufferAndDumpToStreamOptions options(valobj);
- options.SetData(data);
- options.SetStream(&stream);
- options.SetPrefixToken('u');
- options.SetQuote('\'');
- options.SetSourceSize(1);
-
- return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
-}
-
-bool
-lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
-{
- DataExtractor data;
- Error error;
- valobj.GetData(data, error);
-
- if (error.Fail())
- return false;
-
- std::string value;
- valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
- if (!value.empty())
- stream.Printf("%s ", value.c_str());
-
- ReadBufferAndDumpToStreamOptions options(valobj);
- options.SetData(data);
- options.SetStream(&stream);
- options.SetPrefixToken('U');
- options.SetQuote('\'');
- options.SetSourceSize(1);
-
- return ReadBufferAndDumpToStream<StringElementType::UTF32>(options);
-}
-
-bool
-lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
-{
- DataExtractor data;
- Error error;
- valobj.GetData(data, error);
-
- if (error.Fail())
- return false;
-
- ReadBufferAndDumpToStreamOptions options(valobj);
- options.SetData(data);
- options.SetStream(&stream);
- options.SetPrefixToken('L');
- options.SetQuote('\'');
- options.SetSourceSize(1);
-
- return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
-}
-
-// the field layout in a libc++ string (cap, side, data or data, size, cap)
-enum LibcxxStringLayoutMode
-{
- eLibcxxStringLayoutModeCSD = 0,
- eLibcxxStringLayoutModeDSC = 1,
- eLibcxxStringLayoutModeInvalid = 0xffff
-};
-
-// this function abstracts away the layout and mode details of a libc++ string
-// and returns the address of the data and the size ready for callers to consume
-static bool
-ExtractLibcxxStringInfo (ValueObject& valobj,
- ValueObjectSP &location_sp,
- uint64_t& size)
-{
- ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
- if (!D)
- return false;
-
- ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
-
- // this child should exist
- if (!layout_decider)
- return false;
-
- ConstString g_data_name("__data_");
- ConstString g_size_name("__size_");
- bool short_mode = false; // this means the string is in short-mode and the data is stored inline
- LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
- uint64_t size_mode_value = 0;
-
- if (layout == eLibcxxStringLayoutModeDSC)
- {
- ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
- if (!size_mode)
- return false;
-
- if (size_mode->GetName() != g_size_name)
- {
- // we are hitting the padding structure, move along
- size_mode = D->GetChildAtIndexPath({1,1,1});
- if (!size_mode)
- return false;
- }
-
- size_mode_value = (size_mode->GetValueAsUnsigned(0));
- short_mode = ((size_mode_value & 0x80) == 0);
- }
- else
- {
- ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
- if (!size_mode)
- return false;
-
- size_mode_value = (size_mode->GetValueAsUnsigned(0));
- short_mode = ((size_mode_value & 1) == 0);
- }
-
- if (short_mode)
- {
- ValueObjectSP s(D->GetChildAtIndex(1, true));
- if (!s)
- return false;
- location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
- size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
- return (location_sp.get() != nullptr);
- }
- else
- {
- ValueObjectSP l(D->GetChildAtIndex(0, true));
- if (!l)
- return false;
- // we can use the layout_decider object as the data pointer
- location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
- ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
- if (!size_vo || !location_sp)
- return false;
- size = size_vo->GetValueAsUnsigned(0);
- return true;
- }
-}
-
-bool
-lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
-{
- uint64_t size = 0;
- ValueObjectSP location_sp((ValueObject*)nullptr);
- if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
- return false;
- if (size == 0)
- {
- stream.Printf("L\"\"");
- return true;
- }
- if (!location_sp)
- return false;
- return WCharStringSummaryProvider(*location_sp.get(), stream, options);
-}
-
-bool
-lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
-{
- uint64_t size = 0;
- ValueObjectSP location_sp((ValueObject*)nullptr);
-
- if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
- return false;
-
- if (size == 0)
- {
- stream.Printf("\"\"");
- return true;
- }
-
- if (!location_sp)
- return false;
-
- DataExtractor extractor;
- if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
- size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
- location_sp->GetPointeeData(extractor, 0, size);
-
- ReadBufferAndDumpToStreamOptions options(valobj);
- options.SetData(extractor); // none of this matters for a string - pass some defaults
- options.SetStream(&stream);
- options.SetPrefixToken(0);
- options.SetQuote('"');
- options.SetSourceSize(size);
- lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::ASCII>(options);
-
- return true;
-}
-
-bool
-lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
-{
- ProcessSP process_sp = valobj.GetProcessSP();
- if (!process_sp)
- return false;
-
- ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
-
- if (!runtime)
- return false;
-
- ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
-
- if (!descriptor.get() || !descriptor->IsValid())
- return false;
-
- const char* class_name = descriptor->GetClassName().GetCString();
-
- if (!class_name || !*class_name)
- return false;
-
- stream.Printf("%s",class_name);
- return true;
-}
-
-class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
-{
-public:
- ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
- SyntheticChildrenFrontEnd(*valobj_sp.get())
- {
- }
-
- virtual size_t
- CalculateNumChildren ()
- {
- return 0;
- }
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx)
- {
- return lldb::ValueObjectSP();
- }
-
- virtual bool
- Update()
- {
- return false;
- }
-
- virtual bool
- MightHaveChildren ()
- {
- return false;
- }
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name)
- {
- return UINT32_MAX;
- }
-
- virtual
- ~ObjCClassSyntheticChildrenFrontEnd ()
- {
- }
-};
-
-SyntheticChildrenFrontEnd*
-lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
-{
- return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
-}
-
-template<bool needs_at>
-bool
-lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
-{
- ProcessSP process_sp = valobj.GetProcessSP();
- if (!process_sp)
- return false;
-
- ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
-
- if (!runtime)
- return false;
-
- ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
-
- if (!descriptor.get() || !descriptor->IsValid())
- return false;
-
- bool is_64bit = (process_sp->GetAddressByteSize() == 8);
- lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
-
- if (!valobj_addr)
- return false;
-
- uint64_t value = 0;
-
- const char* class_name = descriptor->GetClassName().GetCString();
-
- if (!class_name || !*class_name)
- return false;
-
- if (!strcmp(class_name,"NSConcreteData") ||
- !strcmp(class_name,"NSConcreteMutableData") ||
- !strcmp(class_name,"__NSCFData"))
- {
- uint32_t offset = (is_64bit ? 16 : 8);
- Error error;
- value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
- if (error.Fail())
- return false;
- }
- else
- {
- if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
- return false;
- }
-
- stream.Printf("%s%" PRIu64 " byte%s%s",
- (needs_at ? "@\"" : ""),
- value,
- (value != 1 ? "s" : ""),
- (needs_at ? "\"" : ""));
-
- return true;
-}
-
-static bool
-ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
- lldb::ProcessSP& process_sp,
- Stream& dest,
- uint32_t size = 0,
- Error* error = NULL,
- size_t *data_read = NULL,
- char prefix_token = '@',
- char quote = '"')
-{
- Error my_error;
- size_t my_data_read;
- if (!process_sp || location == 0)
- return false;
-
- if (!size)
- size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
- else
- size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
-
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
-
- my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
-
- if (error)
- *error = my_error;
- if (data_read)
- *data_read = my_data_read;
-
- if (my_error.Fail())
- return false;
-
- dest.Printf("%c%c",prefix_token,quote);
-
- if (my_data_read)
- dest.Printf("%s",(char*)buffer_sp->GetBytes());
-
- dest.Printf("%c",quote);
-
- return true;
-}
-
-bool
-lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream)
-{
- if (!descriptor)
- return false;
- uint64_t len_bits = 0, data_bits = 0;
- if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
- return false;
-
- static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
- static const int g_SixbitMaxLen = 9;
- static const int g_fiveBitMaxLen = 11;
-
- static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
-
- if (len_bits > g_fiveBitMaxLen)
- return false;
-
- // this is a fairly ugly trick - pretend that the numeric value is actually a char*
- // this works under a few assumptions:
- // little endian architecture
- // sizeof(uint64_t) > g_MaxNonBitmaskedLen
- if (len_bits <= g_MaxNonBitmaskedLen)
- {
- stream.Printf("@\"%s\"",(const char*)&data_bits);
- return true;
- }
-
- // if the data is bitmasked, we need to actually process the bytes
- uint8_t bitmask = 0;
- uint8_t shift_offset = 0;
-
- if (len_bits <= g_SixbitMaxLen)
- {
- bitmask = 0x03f;
- shift_offset = 6;
- }
- else
- {
- bitmask = 0x01f;
- shift_offset = 5;
- }
-
- std::vector<uint8_t> bytes;
- bytes.resize(len_bits);
- for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
- {
- uint8_t packed = data_bits & bitmask;
- bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
- }
-
- stream.Printf("@\"%s\"",&bytes[0]);
- return true;
-}
-
-static ClangASTType
-GetNSPathStore2Type (Target &target)
-{
- static ConstString g_type_name("__lldb_autogen_nspathstore2");
-
- ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
-
- if (!ast_ctx)
- return ClangASTType();
-
- ClangASTType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
- ClangASTType uint32 = ast_ctx->GetIntTypeFromBitSize(32, false);
-
- return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, {
- {"isa",voidstar},
- {"lengthAndRef",uint32},
- {"buffer",voidstar}
- });
-}
-
-bool
-lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
-{
- ProcessSP process_sp = valobj.GetProcessSP();
- if (!process_sp)
- return false;
-
- ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
-
- if (!runtime)
- return false;
-
- ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
-
- if (!descriptor.get() || !descriptor->IsValid())
- return false;
-
- uint32_t ptr_size = process_sp->GetAddressByteSize();
-
- lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
-
- if (!valobj_addr)
- return false;
-
- const char* class_name = descriptor->GetClassName().GetCString();
-
- if (!class_name || !*class_name)
- return false;
-
- bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
- // for a tagged pointer, the descriptor has everything we need
- if (is_tagged_ptr)
- return NSTaggedString_SummaryProvider(descriptor, stream);
-
- // if not a tagged pointer that we know about, try the normal route
- uint64_t info_bits_location = valobj_addr + ptr_size;
- if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
- info_bits_location += 3;
-
- Error error;
-
- uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
- if (error.Fail())
- return false;
-
- bool is_mutable = (info_bits & 1) == 1;
- bool is_inline = (info_bits & 0x60) == 0;
- bool has_explicit_length = (info_bits & (1 | 4)) != 4;
- bool is_unicode = (info_bits & 0x10) == 0x10;
- bool is_special = strcmp(class_name,"NSPathStore2") == 0;
- bool has_null = (info_bits & 8) == 8;
-
- size_t explicit_length = 0;
- if (!has_null && has_explicit_length && !is_special)
- {
- lldb::addr_t explicit_length_offset = 2*ptr_size;
- if (is_mutable && !is_inline)
- explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
- else if (is_inline)
- explicit_length = explicit_length + 0; // inline1.length;
- else if (!is_inline && !is_mutable)
- explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
- else
- explicit_length_offset = 0;
-
- if (explicit_length_offset)
- {
- explicit_length_offset = valobj_addr + explicit_length_offset;
- explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
- }
- }
-
- if (strcmp(class_name,"NSString") &&
- strcmp(class_name,"CFStringRef") &&
- strcmp(class_name,"CFMutableStringRef") &&
- strcmp(class_name,"__NSCFConstantString") &&
- strcmp(class_name,"__NSCFString") &&
- strcmp(class_name,"NSCFConstantString") &&
- strcmp(class_name,"NSCFString") &&
- strcmp(class_name,"NSPathStore2"))
- {
- // not one of us - but tell me class name
- stream.Printf("class name = %s",class_name);
- return true;
- }
-
- if (is_mutable)
- {
- uint64_t location = 2 * ptr_size + valobj_addr;
- location = process_sp->ReadPointerFromMemory(location, error);
- if (error.Fail())
- return false;
- if (has_explicit_length && is_unicode)
- {
- ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(location);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetPrefixToken('@');
- options.SetQuote('"');
- options.SetSourceSize(explicit_length);
- options.SetNeedsZeroTermination(false);
- options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
- return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
- }
- else
- {
- ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(location+1);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetPrefixToken('@');
- options.SetSourceSize(explicit_length);
- options.SetNeedsZeroTermination(false);
- options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
- return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
- }
- }
- else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
- {
- uint64_t location = 3 * ptr_size + valobj_addr;
- return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
- }
- else if (is_unicode)
- {
- uint64_t location = valobj_addr + 2*ptr_size;
- if (is_inline)
- {
- if (!has_explicit_length)
- {
- stream.Printf("found new combo");
- return true;
- }
- else
- location += ptr_size;
- }
- else
- {
- location = process_sp->ReadPointerFromMemory(location, error);
- if (error.Fail())
- return false;
- }
- ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(location);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetPrefixToken('@');
- options.SetQuote('"');
- options.SetSourceSize(explicit_length);
- options.SetNeedsZeroTermination(has_explicit_length == false);
- options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
- return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
- }
- else if (is_special)
- {
- ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP()));
- explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20;
- lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4;
-
- ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(location);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetPrefixToken('@');
- options.SetQuote('"');
- options.SetSourceSize(explicit_length);
- options.SetNeedsZeroTermination(has_explicit_length == false);
- options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
- return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
- }
- else if (is_inline)
- {
- uint64_t location = valobj_addr + 2*ptr_size;
- if (!has_explicit_length)
- location++;
- ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(location);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetPrefixToken('@');
- options.SetSourceSize(explicit_length);
- options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
- return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
- }
- else
- {
- uint64_t location = valobj_addr + 2*ptr_size;
- location = process_sp->ReadPointerFromMemory(location, error);
- if (error.Fail())
- return false;
- if (has_explicit_length && !has_null)
- explicit_length++; // account for the fact that there is no NULL and we need to have one added
- ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(location);
- options.SetProcessSP(process_sp);
- options.SetPrefixToken('@');
- options.SetStream(&stream);
- options.SetSourceSize(explicit_length);
- options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
- return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
- }
-}
-
-bool
-lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
-{
- TargetSP target_sp(valobj.GetTargetSP());
- if (!target_sp)
- return false;
- uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
- uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
- if (!pointer_value)
- return false;
- pointer_value += addr_size;
- ClangASTType type(valobj.GetClangType());
- ExecutionContext exe_ctx(target_sp,false);
- ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
- if (!child_ptr_sp)
- return false;
- DataExtractor data;
- Error error;
- child_ptr_sp->GetData(data, error);
- if (error.Fail())
- return false;
- ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
- child_sp->GetValueAsUnsigned(0);
- if (child_sp)
- return NSStringSummaryProvider(*child_sp, stream, options);
- return false;
-}
-
-bool
-lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
-{
- return NSAttributedStringSummaryProvider(valobj, stream, options);
-}
-
-bool
-lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
-{
- stream.Printf("%s",valobj.GetObjectDescription());
- return true;
-}
-
-bool
-lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
-{
- const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
-
- ValueObjectSP real_guy_sp = valobj.GetSP();
-
- if (type_info & eTypeIsPointer)
- {
- Error err;
- real_guy_sp = valobj.Dereference(err);
- if (err.Fail() || !real_guy_sp)
- return false;
- }
- else if (type_info & eTypeIsReference)
- {
- real_guy_sp = valobj.GetChildAtIndex(0, true);
- if (!real_guy_sp)
- return false;
- }
- uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
- if (value == 0)
- {
- stream.Printf("NO");
- return true;
- }
- stream.Printf("YES");
- return true;
-}
-
-template <bool is_sel_ptr>
-bool
-lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
-{
- lldb::ValueObjectSP valobj_sp;
-
- ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
-
- if (!charstar)
- return false;
-
- ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
-
- if (is_sel_ptr)
- {
- lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
- if (data_address == LLDB_INVALID_ADDRESS)
- return false;
- valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
- }
- else
- {
- DataExtractor data;
- Error error;
- valobj.GetData(data, error);
- if (error.Fail())
- return false;
- valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
- }
-
- if (!valobj_sp)
- return false;
-
- stream.Printf("%s",valobj_sp->GetSummaryAsCString());
- return true;
-}
-
-// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
-// this call gives the POSIX equivalent of the Cocoa epoch
-time_t
-lldb_private::formatters::GetOSXEpoch ()
-{
- static time_t epoch = 0;
- if (!epoch)
- {
-#ifndef _WIN32
- tzset();
- tm tm_epoch;
- tm_epoch.tm_sec = 0;
- tm_epoch.tm_hour = 0;
- tm_epoch.tm_min = 0;
- tm_epoch.tm_mon = 0;
- tm_epoch.tm_mday = 1;
- tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
- tm_epoch.tm_isdst = -1;
- tm_epoch.tm_gmtoff = 0;
- tm_epoch.tm_zone = NULL;
- epoch = timegm(&tm_epoch);
-#endif
- }
- return epoch;
-}
-
-size_t
-lldb_private::formatters::ExtractIndexFromString (const char* item_name)
-{
- if (!item_name || !*item_name)
- return UINT32_MAX;
- if (*item_name != '[')
- return UINT32_MAX;
- item_name++;
- char* endptr = NULL;
- unsigned long int idx = ::strtoul(item_name, &endptr, 0);
- if (idx == 0 && endptr == item_name)
- return UINT32_MAX;
- if (idx == ULONG_MAX)
- return UINT32_MAX;
- return idx;
-}
-
-lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
- ConstString item_name) :
-SyntheticChildrenFrontEnd(*valobj_sp.get()),
-m_exe_ctx_ref(),
-m_item_name(item_name),
-m_item_sp()
-{
- if (valobj_sp)
- Update();
-}
-
-bool
-lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
-{
- m_item_sp.reset();
-
- ValueObjectSP valobj_sp = m_backend.GetSP();
- if (!valobj_sp)
- return false;
-
- if (!valobj_sp)
- return false;
-
- ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
- if (!item_ptr)
- return false;
- if (item_ptr->GetValueAsUnsigned(0) == 0)
- return false;
- Error err;
- m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
- m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
- if (err.Fail())
- m_item_sp.reset();
- return false;
-}
-
-size_t
-lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
-{
- return 1;
-}
-
-lldb::ValueObjectSP
-lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
-{
- if (idx == 0)
- return m_item_sp;
- return lldb::ValueObjectSP();
-}
-
-bool
-lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
-{
- return true;
-}
-
-size_t
-lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
-{
- if (name == ConstString("item"))
- return 0;
- return UINT32_MAX;
-}
-
-lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
-{
-}
-
-template bool
-lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
-
-template bool
-lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
-
-template bool
-lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
-
-template bool
-lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/CXXFunctionPointer.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/CXXFunctionPointer.cpp
new file mode 100644
index 0000000..c9e0ccb
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/CXXFunctionPointer.cpp
@@ -0,0 +1,66 @@
+//===-- CXXFormatterFunctions.cpp---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/DataFormatters/CXXFunctionPointer.h"
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/Target.h"
+
+#include <string>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::CXXFunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ std::string destination;
+ StreamString sstr;
+ AddressType func_ptr_address_type = eAddressTypeInvalid;
+ addr_t func_ptr_address = valobj.GetPointerValue (&func_ptr_address_type);
+ if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS)
+ {
+ switch (func_ptr_address_type)
+ {
+ case eAddressTypeInvalid:
+ case eAddressTypeFile:
+ case eAddressTypeHost:
+ break;
+
+ case eAddressTypeLoad:
+ {
+ ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+
+ Address so_addr;
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target && target->GetSectionLoadList().IsEmpty() == false)
+ {
+ if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr))
+ {
+ so_addr.Dump (&sstr,
+ exe_ctx.GetBestExecutionContextScope(),
+ Address::DumpStyleResolvedDescription,
+ Address::DumpStyleSectionNameOffset);
+ }
+ }
+ }
+ break;
+ }
+ }
+ if (sstr.GetSize() > 0)
+ {
+ stream.Printf("(%s)", sstr.GetData());
+ return true;
+ }
+ else
+ return false;
+}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/DataVisualization.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/DataVisualization.cpp
index 3612541..14cf13d 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/DataVisualization.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/DataVisualization.cpp
@@ -14,8 +14,6 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/Core/Debugger.h"
-
using namespace lldb;
using namespace lldb_private;
@@ -133,6 +131,14 @@ DataVisualization::Categories::GetCategory (const ConstString &category, lldb::T
return (entry.get() != NULL);
}
+bool
+DataVisualization::Categories::GetCategory (lldb::LanguageType language, lldb::TypeCategoryImplSP &entry)
+{
+ if (LanguageCategory *lang_category = GetFormatManager().GetCategoryForLanguage(language))
+ entry = lang_category->GetCategory();
+ return (entry.get() != nullptr);
+}
+
void
DataVisualization::Categories::Add (const ConstString &category)
{
@@ -164,7 +170,14 @@ DataVisualization::Categories::Enable (const ConstString& category,
{
if (GetFormatManager().GetCategory(category)->IsEnabled())
GetFormatManager().DisableCategory(category);
- GetFormatManager().EnableCategory(category, pos);
+ GetFormatManager().EnableCategory(category, pos, std::initializer_list<lldb::LanguageType>());
+}
+
+void
+DataVisualization::Categories::Enable (lldb::LanguageType lang_type)
+{
+ if (LanguageCategory* lang_category = GetFormatManager().GetCategoryForLanguage(lang_type))
+ lang_category->Enable();
}
void
@@ -175,6 +188,13 @@ DataVisualization::Categories::Disable (const ConstString& category)
}
void
+DataVisualization::Categories::Disable (lldb::LanguageType lang_type)
+{
+ if (LanguageCategory* lang_category = GetFormatManager().GetCategoryForLanguage(lang_type))
+ lang_category->Disable();
+}
+
+void
DataVisualization::Categories::Enable (const lldb::TypeCategoryImplSP& category,
TypeCategoryMap::Position pos)
{
@@ -206,9 +226,9 @@ DataVisualization::Categories::DisableStar ()
}
void
-DataVisualization::Categories::LoopThrough (FormatManager::CategoryCallback callback, void* callback_baton)
+DataVisualization::Categories::ForEach (TypeCategoryMap::ForEachCallback callback)
{
- GetFormatManager().LoopThroughCategories(callback, callback_baton);
+ GetFormatManager().ForEachCategory(callback);
}
uint32_t
@@ -248,9 +268,9 @@ DataVisualization::NamedSummaryFormats::Clear ()
}
void
-DataVisualization::NamedSummaryFormats::LoopThrough (TypeSummaryImpl::SummaryCallback callback, void* callback_baton)
+DataVisualization::NamedSummaryFormats::ForEach (std::function<bool(ConstString, const lldb::TypeSummaryImplSP&)> callback)
{
- GetFormatManager().GetNamedSummaryContainer().LoopThrough(callback, callback_baton);
+ GetFormatManager().GetNamedSummaryContainer().ForEach(callback);
}
uint32_t
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/DumpValueObjectOptions.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/DumpValueObjectOptions.cpp
new file mode 100644
index 0000000..f3de125
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/DumpValueObjectOptions.cpp
@@ -0,0 +1,245 @@
+//===-- DumpValueObjectOptions.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/DataFormatters/DumpValueObjectOptions.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ValueObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+DumpValueObjectOptions::DumpValueObjectOptions() :
+ m_summary_sp(),
+ m_root_valobj_name(),
+ m_max_ptr_depth(PointerDepth{PointerDepth::Mode::Default,0}),
+ m_decl_printing_helper(),
+ m_use_synthetic(true),
+ m_scope_already_checked(false),
+ m_flat_output(false),
+ m_ignore_cap(false),
+ m_show_types(false),
+ m_show_location(false),
+ m_use_objc(false),
+ m_hide_root_type(false),
+ m_hide_name(false),
+ m_hide_value(false),
+ m_run_validator(false),
+ m_use_type_display_name(true),
+ m_allow_oneliner_mode(true),
+ m_hide_pointer_value(false),
+ m_reveal_empty_aggregates(true)
+{}
+
+
+DumpValueObjectOptions::DumpValueObjectOptions (ValueObject& valobj) :
+ DumpValueObjectOptions()
+{
+ m_use_dynamic = valobj.GetDynamicValueType();
+ m_use_synthetic = valobj.IsSynthetic();
+ m_varformat_language = valobj.GetPreferredDisplayLanguage();
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetMaximumPointerDepth(PointerDepth depth)
+{
+ m_max_ptr_depth = depth;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetMaximumDepth(uint32_t depth)
+{
+ m_max_depth = depth;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetDeclPrintingHelper(DeclPrintingHelper helper)
+{
+ m_decl_printing_helper = helper;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetShowTypes(bool show)
+{
+ m_show_types = show;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetShowLocation(bool show)
+{
+ m_show_location = show;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetUseObjectiveC(bool use)
+{
+ m_use_objc = use;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetShowSummary(bool show)
+{
+ if (show == false)
+ SetOmitSummaryDepth(UINT32_MAX);
+ else
+ SetOmitSummaryDepth(0);
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetUseDynamicType(lldb::DynamicValueType dyn)
+{
+ m_use_dynamic = dyn;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetUseSyntheticValue(bool use_synthetic)
+{
+ m_use_synthetic = use_synthetic;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetScopeChecked(bool check)
+{
+ m_scope_already_checked = check;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetFlatOutput(bool flat)
+{
+ m_flat_output = flat;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetOmitSummaryDepth(uint32_t depth)
+{
+ m_omit_summary_depth = depth;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetIgnoreCap(bool ignore)
+{
+ m_ignore_cap = ignore;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetRawDisplay()
+{
+ SetUseSyntheticValue(false);
+ SetOmitSummaryDepth(UINT32_MAX);
+ SetIgnoreCap(true);
+ SetHideName(false);
+ SetHideValue(false);
+ SetUseTypeDisplayName(false);
+ SetAllowOnelinerMode(false);
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetFormat (lldb::Format format)
+{
+ m_format = format;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetSummary (lldb::TypeSummaryImplSP summary)
+{
+ m_summary_sp = summary;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetRootValueObjectName (const char* name)
+{
+ if (name)
+ m_root_valobj_name.assign(name);
+ else
+ m_root_valobj_name.clear();
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetHideRootType (bool hide_root_type)
+{
+ m_hide_root_type = hide_root_type;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetHideName (bool hide_name)
+{
+ m_hide_name = hide_name;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetHideValue (bool hide_value)
+{
+ m_hide_value = hide_value;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetHidePointerValue (bool hide)
+{
+ m_hide_pointer_value = hide;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetVariableFormatDisplayLanguage (lldb::LanguageType lang)
+{
+ m_varformat_language = lang;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetRunValidator (bool run)
+{
+ m_run_validator = run;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetUseTypeDisplayName (bool dis)
+{
+ m_use_type_display_name = dis;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetAllowOnelinerMode (bool oneliner)
+{
+ m_allow_oneliner_mode = oneliner;
+ return *this;
+}
+
+DumpValueObjectOptions&
+DumpValueObjectOptions::SetRevealEmptyAggregates (bool reveal)
+{
+ m_reveal_empty_aggregates = reveal;
+ return *this;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/FormatClasses.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/FormatClasses.cpp
index f27b45b..2e4acd1 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/FormatClasses.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/FormatClasses.cpp
@@ -9,6 +9,8 @@
#include "lldb/DataFormatters/FormatClasses.h"
+#include "lldb/DataFormatters/FormatManager.h"
+
// C Includes
// C++ Includes
@@ -20,3 +22,48 @@
using namespace lldb;
using namespace lldb_private;
+FormattersMatchData::FormattersMatchData (ValueObject& valobj, lldb::DynamicValueType use_dynamic) :
+ m_valobj(valobj),
+ m_dynamic_value_type(use_dynamic),
+ m_formatters_match_vector({},false),
+ m_type_for_cache(),
+ m_candidate_languages()
+{
+ m_type_for_cache = FormatManager::GetTypeForCache(valobj, use_dynamic);
+ m_candidate_languages = FormatManager::GetCandidateLanguages(valobj);
+}
+
+FormattersMatchVector
+FormattersMatchData::GetMatchesVector ()
+{
+ if (!m_formatters_match_vector.second)
+ {
+ m_formatters_match_vector.second = true;
+ m_formatters_match_vector.first = FormatManager::GetPossibleMatches(m_valobj, m_dynamic_value_type);
+ }
+ return m_formatters_match_vector.first;
+}
+
+ConstString
+FormattersMatchData::GetTypeForCache ()
+{
+ return m_type_for_cache;
+}
+
+CandidateLanguagesVector
+FormattersMatchData::GetCandidateLanguages ()
+{
+ return m_candidate_languages;
+}
+
+ValueObject&
+FormattersMatchData::GetValueObject ()
+{
+ return m_valobj;
+}
+
+lldb::DynamicValueType
+FormattersMatchData::GetDynamicValueType ()
+{
+ return m_dynamic_value_type;
+}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/FormatManager.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/FormatManager.cpp
index 4e0fffb..35a0468 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/FormatManager.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/FormatManager.cpp
@@ -9,20 +9,23 @@
#include "lldb/DataFormatters/FormatManager.h"
+#include "llvm/ADT/STLExtras.h"
+
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Debugger.h"
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+#include "lldb/Core/Log.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/LanguageCategory.h"
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Platform.h"
-#include "llvm/ADT/STLExtras.h"
+#include "lldb/Target/Language.h"
using namespace lldb;
using namespace lldb_private;
-
+using namespace lldb_private::formatters;
struct FormatInfo
{
@@ -63,6 +66,7 @@ g_format_infos[] =
{ eFormatVectorOfUInt32 , '\0' , "uint32_t[]" },
{ eFormatVectorOfSInt64 , '\0' , "int64_t[]" },
{ eFormatVectorOfUInt64 , '\0' , "uint64_t[]" },
+ { eFormatVectorOfFloat16, '\0' , "float16[]" },
{ eFormatVectorOfFloat32, '\0' , "float32[]" },
{ eFormatVectorOfFloat64, '\0' , "float64[]" },
{ eFormatVectorOfUInt128, '\0' , "uint128_t[]" },
@@ -119,6 +123,19 @@ GetFormatFromFormatName (const char *format_name, bool partial_match_ok, Format
return false;
}
+void
+FormatManager::Changed ()
+{
+ ++m_last_revision;
+ m_format_cache.Clear ();
+ Mutex::Locker lang_locker(m_language_categories_mutex);
+ for (auto& iter : m_language_categories_map)
+ {
+ if (iter.second)
+ iter.second->GetFormatCache().Clear();
+ }
+}
+
bool
FormatManager::GetFormatFromCString (const char *format_cstr,
bool partial_match_ok,
@@ -161,8 +178,32 @@ FormatManager::GetFormatAsCString (Format format)
}
void
+FormatManager::EnableAllCategories ()
+{
+ m_categories_map.EnableAllCategories ();
+ Mutex::Locker lang_locker(m_language_categories_mutex);
+ for (auto& iter : m_language_categories_map)
+ {
+ if (iter.second)
+ iter.second->Enable();
+ }
+}
+
+void
+FormatManager::DisableAllCategories ()
+{
+ m_categories_map.DisableAllCategories ();
+ Mutex::Locker lang_locker(m_language_categories_mutex);
+ for (auto& iter : m_language_categories_map)
+ {
+ if (iter.second)
+ iter.second->Disable();
+ }
+}
+
+void
FormatManager::GetPossibleMatches (ValueObject& valobj,
- ClangASTType clang_type,
+ CompilerType compiler_type,
uint32_t reason,
lldb::DynamicValueType use_dynamic,
FormattersMatchVector& entries,
@@ -171,8 +212,8 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
bool did_strip_typedef,
bool root_level)
{
- clang_type = clang_type.RemoveFastQualifiers();
- ConstString type_name(clang_type.GetConstTypeName());
+ compiler_type = compiler_type.GetTypeForFormatters();
+ ConstString type_name(compiler_type.GetConstTypeName());
if (valobj.GetBitfieldBitSize() > 0)
{
StreamString sstring;
@@ -181,15 +222,19 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
entries.push_back({bitfieldname,0,did_strip_ptr,did_strip_ref,did_strip_typedef});
reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
}
- entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
- ConstString display_type_name(clang_type.GetDisplayTypeName());
- if (display_type_name != type_name)
- entries.push_back({display_type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
+ if (!compiler_type.IsMeaninglessWithoutDynamicResolution())
+ {
+ entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
+
+ ConstString display_type_name(compiler_type.GetDisplayTypeName());
+ if (display_type_name != type_name)
+ entries.push_back({display_type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
+ }
- for (bool is_rvalue_ref = true, j = true; j && clang_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false)
+ for (bool is_rvalue_ref = true, j = true; j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false)
{
- ClangASTType non_ref_type = clang_type.GetNonReferenceType();
+ CompilerType non_ref_type = compiler_type.GetNonReferenceType();
GetPossibleMatches(valobj,
non_ref_type,
reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
@@ -200,7 +245,7 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
did_strip_typedef);
if (non_ref_type.IsTypedefType())
{
- ClangASTType deffed_referenced_type = non_ref_type.GetTypedefedType();
+ CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType();
deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType();
GetPossibleMatches(valobj,
deffed_referenced_type,
@@ -213,9 +258,9 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
}
}
- if (clang_type.IsPointerType())
+ if (compiler_type.IsPointerType())
{
- ClangASTType non_ptr_type = clang_type.GetPointeeType();
+ CompilerType non_ptr_type = compiler_type.GetPointeeType();
GetPossibleMatches(valobj,
non_ptr_type,
reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
@@ -226,7 +271,7 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
did_strip_typedef);
if (non_ptr_type.IsTypedefType())
{
- ClangASTType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType();
+ CompilerType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType();
GetPossibleMatches(valobj,
deffed_pointed_type,
reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
@@ -237,45 +282,26 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
true); // this is not exactly the usual meaning of stripping typedefs
}
}
- bool canBeObjCDynamic = clang_type.IsPossibleDynamicType (NULL,
- false, // no C
- true); // yes ObjC
- if (canBeObjCDynamic)
+ for (lldb::LanguageType language_type : GetCandidateLanguages(valobj))
{
- if (use_dynamic != lldb::eNoDynamicValues)
+ if (Language* language = Language::FindPlugin(language_type))
{
- do
+ for (ConstString candidate : language->GetPossibleFormattersMatches(valobj, use_dynamic))
{
- lldb::ProcessSP process_sp = valobj.GetProcessSP();
- if (!process_sp)
- break;
- ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
- if (runtime == nullptr)
- break;
- ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
- if (!objc_class_sp)
- break;
- ConstString name (objc_class_sp->GetClassName());
- entries.push_back({name,reason | lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery,did_strip_ptr,did_strip_ref,did_strip_typedef});
- } while (false);
+ entries.push_back({candidate,
+ reason | lldb_private::eFormatterChoiceCriterionLanguagePlugin,
+ did_strip_ptr,
+ did_strip_ref,
+ did_strip_typedef});
+ }
}
-
- ClangASTType non_ptr_type = clang_type.GetPointeeType();
- GetPossibleMatches(valobj,
- non_ptr_type,
- reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
- use_dynamic,
- entries,
- true,
- did_strip_ref,
- did_strip_typedef);
}
-
+
// try to strip typedef chains
- if (clang_type.IsTypedefType())
+ if (compiler_type.IsTypedefType())
{
- ClangASTType deffed_type = clang_type.GetTypedefedType();
+ CompilerType deffed_type = compiler_type.GetTypedefedType();
GetPossibleMatches(valobj,
deffed_type,
reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
@@ -289,15 +315,15 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
if (root_level)
{
do {
- if (!clang_type.IsValid())
+ if (!compiler_type.IsValid())
break;
- ClangASTType unqual_clang_ast_type = clang_type.GetFullyUnqualifiedType();
- if (!unqual_clang_ast_type.IsValid())
+ CompilerType unqual_compiler_ast_type = compiler_type.GetFullyUnqualifiedType();
+ if (!unqual_compiler_ast_type.IsValid())
break;
- if (unqual_clang_ast_type.GetOpaqueQualType() != clang_type.GetOpaqueQualType())
+ if (unqual_compiler_ast_type.GetOpaqueQualType() != compiler_type.GetOpaqueQualType())
GetPossibleMatches (valobj,
- unqual_clang_ast_type,
+ unqual_compiler_ast_type,
reason,
use_dynamic,
entries,
@@ -313,7 +339,7 @@ FormatManager::GetPossibleMatches (ValueObject& valobj,
lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
if (static_value_sp)
GetPossibleMatches(*static_value_sp.get(),
- static_value_sp->GetClangType(),
+ static_value_sp->GetCompilerType(),
reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue,
use_dynamic,
entries,
@@ -472,6 +498,21 @@ FormatManager::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp)
return validator_chosen_sp;
}
+void
+FormatManager::ForEachCategory(TypeCategoryMap::ForEachCallback callback)
+{
+ m_categories_map.ForEach(callback);
+ Mutex::Locker locker(m_language_categories_mutex);
+ for (const auto& entry : m_language_categories_map)
+ {
+ if (auto category_sp = entry.second->GetCategory())
+ {
+ if (!callback(category_sp))
+ break;
+ }
+ }
+}
+
lldb::TypeCategoryImplSP
FormatManager::GetCategory (const ConstString& category_name,
bool can_create)
@@ -510,6 +551,7 @@ FormatManager::GetSingleItemFormat(lldb::Format vector_format)
case eFormatVectorOfUInt128:
return eFormatHex;
+ case eFormatVectorOfFloat16:
case eFormatVectorOfFloat32:
case eFormatVectorOfFloat64:
return eFormatFloat;
@@ -534,6 +576,22 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj)
if (valobj.GetNumChildren() == 0)
return false;
+ // ask the type if it has any opinion about this
+ // eLazyBoolCalculate == no opinion; other values should be self explanatory
+ CompilerType compiler_type(valobj.GetCompilerType());
+ if (compiler_type.IsValid())
+ {
+ switch (compiler_type.ShouldPrintAsOneLiner(&valobj))
+ {
+ case eLazyBoolNo:
+ return false;
+ case eLazyBoolYes:
+ return true;
+ case eLazyBoolCalculate:
+ break;
+ }
+ }
+
size_t total_children_name_len = 0;
for (size_t idx = 0;
@@ -545,6 +603,23 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj)
// something is wrong here - bail out
if (!child_sp)
return false;
+
+ // also ask the child's type if it has any opinion
+ CompilerType child_compiler_type(child_sp->GetCompilerType());
+ if (child_compiler_type.IsValid())
+ {
+ switch (child_compiler_type.ShouldPrintAsOneLiner(child_sp.get()))
+ {
+ case eLazyBoolYes:
+ // an opinion of yes is only binding for the child, so keep going
+ case eLazyBoolCalculate:
+ break;
+ case eLazyBoolNo:
+ // but if the child says no, then it's a veto on the whole thing
+ return false;
+ }
+ }
+
// if we decided to define synthetic children for a type, we probably care enough
// to show them, but avoid nesting children in children
if (child_sp->GetSyntheticChildren().get() != nullptr)
@@ -596,53 +671,86 @@ FormatManager::GetValidTypeName (const ConstString& type)
}
ConstString
-GetTypeForCache (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+FormatManager::GetTypeForCache (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
{
- if (use_dynamic == lldb::eNoDynamicValues)
+ ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable(use_dynamic, valobj.IsSynthetic());
+ if (valobj_sp && valobj_sp->GetCompilerType().IsValid())
{
- if (valobj.IsDynamic())
- {
- if (valobj.GetStaticValue())
- return valobj.GetStaticValue()->GetQualifiedTypeName();
- else
- return ConstString();
- }
- else
- return valobj.GetQualifiedTypeName();
+ if (!valobj_sp->GetCompilerType().IsMeaninglessWithoutDynamicResolution())
+ return valobj_sp->GetQualifiedTypeName();
}
- if (valobj.IsDynamic())
- return valobj.GetQualifiedTypeName();
- if (valobj.GetDynamicValue(use_dynamic))
- return valobj.GetDynamicValue(use_dynamic)->GetQualifiedTypeName();
return ConstString();
}
+std::vector<lldb::LanguageType>
+FormatManager::GetCandidateLanguages (ValueObject& valobj)
+{
+ lldb::LanguageType lang_type = valobj.GetObjectRuntimeLanguage();
+ return GetCandidateLanguages(lang_type);
+}
+
+std::vector<lldb::LanguageType>
+FormatManager::GetCandidateLanguages (lldb::LanguageType lang_type)
+{
+ switch (lang_type)
+ {
+ case lldb::eLanguageTypeC:
+ case lldb::eLanguageTypeC89:
+ case lldb::eLanguageTypeC99:
+ case lldb::eLanguageTypeC11:
+ case lldb::eLanguageTypeC_plus_plus:
+ case lldb::eLanguageTypeC_plus_plus_03:
+ case lldb::eLanguageTypeC_plus_plus_11:
+ case lldb::eLanguageTypeC_plus_plus_14:
+ return {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC};
+ default:
+ return {lang_type};
+ }
+}
+
+LanguageCategory*
+FormatManager::GetCategoryForLanguage (lldb::LanguageType lang_type)
+{
+ Mutex::Locker locker(m_language_categories_mutex);
+ auto iter = m_language_categories_map.find(lang_type), end = m_language_categories_map.end();
+ if (iter != end)
+ return iter->second.get();
+ LanguageCategory* lang_category = new LanguageCategory(lang_type);
+ m_language_categories_map[lang_type] = LanguageCategory::UniquePointer(lang_category);
+ return lang_category;
+}
+
lldb::TypeFormatImplSP
-FormatManager::GetHardcodedFormat (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+FormatManager::GetHardcodedFormat (FormattersMatchData& match_data)
{
- for (const auto& candidate: m_hardcoded_formats)
+ TypeFormatImplSP retval_sp;
+
+ for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
{
- auto result = candidate(valobj,use_dynamic,*this);
- if (result)
- return result;
+ if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
+ {
+ if (lang_category->GetHardcoded(*this, match_data, retval_sp))
+ break;
+ }
}
- return nullptr;
+
+ return retval_sp;
}
lldb::TypeFormatImplSP
FormatManager::GetFormat (ValueObject& valobj,
lldb::DynamicValueType use_dynamic)
{
+ FormattersMatchData match_data(valobj, use_dynamic);
+
TypeFormatImplSP retval;
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
- ConstString valobj_type(GetTypeForCache(valobj, use_dynamic));
- if (valobj_type)
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
+ if (match_data.GetTypeForCache())
{
if (log)
- log->Printf("\n\n[FormatManager::GetFormat] Looking into cache for type %s", valobj_type.AsCString("<invalid>"));
- if (m_format_cache.GetFormat(valobj_type,retval))
+ log->Printf("\n\n[FormatManager::GetFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
+ if (m_format_cache.GetFormat(match_data.GetTypeForCache(),retval))
{
if (log)
{
@@ -655,21 +763,41 @@ FormatManager::GetFormat (ValueObject& valobj,
if (log)
log->Printf("[FormatManager::GetFormat] Cache search failed. Going normal route");
}
- retval = m_categories_map.GetFormat(valobj, use_dynamic);
+
+ retval = m_categories_map.GetFormat(match_data);
+ if (!retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetFormat] Search failed. Giving language a chance.");
+ for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
+ {
+ if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
+ {
+ if (lang_category->Get(match_data, retval))
+ break;
+ }
+ }
+ if (retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetFormat] Language search success. Returning.");
+ return retval;
+ }
+ }
if (!retval)
{
if (log)
log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded a chance.");
- retval = GetHardcodedFormat(valobj, use_dynamic);
+ retval = GetHardcodedFormat(match_data);
}
- if (valobj_type && (!retval || !retval->NonCacheable()))
+ if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
{
if (log)
log->Printf("[FormatManager::GetFormat] Caching %p for type %s",
static_cast<void*>(retval.get()),
- valobj_type.AsCString("<invalid>"));
- m_format_cache.SetFormat(valobj_type,retval);
+ match_data.GetTypeForCache().AsCString("<invalid>"));
+ m_format_cache.SetFormat(match_data.GetTypeForCache(),retval);
}
if (log && log->GetDebug())
log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
@@ -677,30 +805,35 @@ FormatManager::GetFormat (ValueObject& valobj,
}
lldb::TypeSummaryImplSP
-FormatManager::GetHardcodedSummaryFormat (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+FormatManager::GetHardcodedSummaryFormat (FormattersMatchData& match_data)
{
- for (const auto& candidate: m_hardcoded_summaries)
+ TypeSummaryImplSP retval_sp;
+
+ for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
{
- auto result = candidate(valobj,use_dynamic,*this);
- if (result)
- return result;
+ if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
+ {
+ if (lang_category->GetHardcoded(*this, match_data, retval_sp))
+ break;
+ }
}
- return nullptr;
+
+ return retval_sp;
}
lldb::TypeSummaryImplSP
FormatManager::GetSummaryFormat (ValueObject& valobj,
lldb::DynamicValueType use_dynamic)
{
+ FormattersMatchData match_data(valobj, use_dynamic);
+
TypeSummaryImplSP retval;
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
- ConstString valobj_type(GetTypeForCache(valobj, use_dynamic));
- if (valobj_type)
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
+ if (match_data.GetTypeForCache())
{
if (log)
- log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache for type %s", valobj_type.AsCString("<invalid>"));
- if (m_format_cache.GetSummary(valobj_type,retval))
+ log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
+ if (m_format_cache.GetSummary(match_data.GetTypeForCache(),retval))
{
if (log)
{
@@ -713,21 +846,41 @@ FormatManager::GetSummaryFormat (ValueObject& valobj,
if (log)
log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. Going normal route");
}
- retval = m_categories_map.GetSummaryFormat(valobj, use_dynamic);
+
+ retval = m_categories_map.GetSummaryFormat(match_data);
+ if (!retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving language a chance.");
+ for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
+ {
+ if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
+ {
+ if (lang_category->Get(match_data, retval))
+ break;
+ }
+ }
+ if (retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetSummaryFormat] Language search success. Returning.");
+ return retval;
+ }
+ }
if (!retval)
{
if (log)
log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving hardcoded a chance.");
- retval = GetHardcodedSummaryFormat(valobj, use_dynamic);
+ retval = GetHardcodedSummaryFormat(match_data);
}
- if (valobj_type && (!retval || !retval->NonCacheable()))
+ if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
{
if (log)
log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s",
static_cast<void*>(retval.get()),
- valobj_type.AsCString("<invalid>"));
- m_format_cache.SetSummary(valobj_type,retval);
+ match_data.GetTypeForCache().AsCString("<invalid>"));
+ m_format_cache.SetSummary(match_data.GetTypeForCache(),retval);
}
if (log && log->GetDebug())
log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
@@ -736,30 +889,35 @@ FormatManager::GetSummaryFormat (ValueObject& valobj,
#ifndef LLDB_DISABLE_PYTHON
lldb::SyntheticChildrenSP
-FormatManager::GetHardcodedSyntheticChildren (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+FormatManager::GetHardcodedSyntheticChildren (FormattersMatchData& match_data)
{
- for (const auto& candidate: m_hardcoded_synthetics)
+ SyntheticChildrenSP retval_sp;
+
+ for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
{
- auto result = candidate(valobj,use_dynamic,*this);
- if (result)
- return result;
+ if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
+ {
+ if (lang_category->GetHardcoded(*this, match_data, retval_sp))
+ break;
+ }
}
- return nullptr;
+
+ return retval_sp;
}
lldb::SyntheticChildrenSP
FormatManager::GetSyntheticChildren (ValueObject& valobj,
lldb::DynamicValueType use_dynamic)
{
+ FormattersMatchData match_data(valobj, use_dynamic);
+
SyntheticChildrenSP retval;
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
- ConstString valobj_type(GetTypeForCache(valobj, use_dynamic));
- if (valobj_type)
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
+ if (match_data.GetTypeForCache())
{
if (log)
- log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into cache for type %s", valobj_type.AsCString("<invalid>"));
- if (m_format_cache.GetSynthetic(valobj_type,retval))
+ log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
+ if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(),retval))
{
if (log)
{
@@ -772,21 +930,41 @@ FormatManager::GetSyntheticChildren (ValueObject& valobj,
if (log)
log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. Going normal route");
}
- retval = m_categories_map.GetSyntheticChildren(valobj, use_dynamic);
+
+ retval = m_categories_map.GetSyntheticChildren(match_data);
+ if (!retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving language a chance.");
+ for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
+ {
+ if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
+ {
+ if (lang_category->Get(match_data, retval))
+ break;
+ }
+ }
+ if (retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetSyntheticChildren] Language search success. Returning.");
+ return retval;
+ }
+ }
if (!retval)
{
if (log)
log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving hardcoded a chance.");
- retval = GetHardcodedSyntheticChildren(valobj, use_dynamic);
+ retval = GetHardcodedSyntheticChildren(match_data);
}
- if (valobj_type && (!retval || !retval->NonCacheable()))
+ if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
{
if (log)
log->Printf("[FormatManager::GetSyntheticChildren] Caching %p for type %s",
static_cast<void*>(retval.get()),
- valobj_type.AsCString("<invalid>"));
- m_format_cache.SetSynthetic(valobj_type,retval);
+ match_data.GetTypeForCache().AsCString("<invalid>"));
+ m_format_cache.SetSynthetic(match_data.GetTypeForCache(),retval);
}
if (log && log->GetDebug())
log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
@@ -798,14 +976,15 @@ lldb::TypeValidatorImplSP
FormatManager::GetValidator (ValueObject& valobj,
lldb::DynamicValueType use_dynamic)
{
+ FormattersMatchData match_data(valobj, use_dynamic);
+
TypeValidatorImplSP retval;
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
- ConstString valobj_type(GetTypeForCache(valobj, use_dynamic));
- if (valobj_type)
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
+ if (match_data.GetTypeForCache())
{
if (log)
- log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", valobj_type.AsCString("<invalid>"));
- if (m_format_cache.GetValidator(valobj_type,retval))
+ log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("<invalid>"));
+ if (m_format_cache.GetValidator(match_data.GetTypeForCache(),retval))
{
if (log)
{
@@ -818,21 +997,41 @@ FormatManager::GetValidator (ValueObject& valobj,
if (log)
log->Printf("[FormatManager::GetValidator] Cache search failed. Going normal route");
}
- retval = m_categories_map.GetValidator(valobj, use_dynamic);
+
+ retval = m_categories_map.GetValidator(match_data);
+ if (!retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetValidator] Search failed. Giving language a chance.");
+ for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
+ {
+ if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
+ {
+ if (lang_category->Get(match_data, retval))
+ break;
+ }
+ }
+ if (retval)
+ {
+ if (log)
+ log->Printf("[FormatManager::GetValidator] Language search success. Returning.");
+ return retval;
+ }
+ }
if (!retval)
{
if (log)
log->Printf("[FormatManager::GetValidator] Search failed. Giving hardcoded a chance.");
- retval = GetHardcodedValidator(valobj, use_dynamic);
+ retval = GetHardcodedValidator(match_data);
}
- if (valobj_type && (!retval || !retval->NonCacheable()))
+ if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable()))
{
if (log)
log->Printf("[FormatManager::GetValidator] Caching %p for type %s",
static_cast<void*>(retval.get()),
- valobj_type.AsCString("<invalid>"));
- m_format_cache.SetValidator(valobj_type,retval);
+ match_data.GetTypeForCache().AsCString("<invalid>"));
+ m_format_cache.SetValidator(match_data.GetTypeForCache(),retval);
}
if (log && log->GetDebug())
log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses());
@@ -840,313 +1039,43 @@ FormatManager::GetValidator (ValueObject& valobj,
}
lldb::TypeValidatorImplSP
-FormatManager::GetHardcodedValidator (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+FormatManager::GetHardcodedValidator (FormattersMatchData& match_data)
{
- for (const auto& candidate: m_hardcoded_validators)
+ TypeValidatorImplSP retval_sp;
+
+ for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages())
{
- auto result = candidate(valobj,use_dynamic,*this);
- if (result)
- return result;
+ if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type))
+ {
+ if (lang_category->GetHardcoded(*this, match_data, retval_sp))
+ break;
+ }
}
- return nullptr;
+
+ return retval_sp;
}
FormatManager::FormatManager() :
+ m_last_revision(0),
m_format_cache(),
+ m_language_categories_mutex(Mutex::eMutexTypeRecursive),
+ m_language_categories_map(),
m_named_summaries_map(this),
- m_last_revision(0),
m_categories_map(this),
m_default_category_name(ConstString("default")),
m_system_category_name(ConstString("system")),
- m_gnu_cpp_category_name(ConstString("gnu-libstdc++")),
- m_libcxx_category_name(ConstString("libcxx")),
- m_objc_category_name(ConstString("objc")),
- m_corefoundation_category_name(ConstString("CoreFoundation")),
- m_coregraphics_category_name(ConstString("CoreGraphics")),
- m_coreservices_category_name(ConstString("CoreServices")),
- m_vectortypes_category_name(ConstString("VectorTypes")),
- m_appkit_category_name(ConstString("AppKit")),
- m_coremedia_category_name(ConstString("CoreMedia")),
- m_hardcoded_formats(),
- m_hardcoded_summaries(),
- m_hardcoded_synthetics(),
- m_hardcoded_validators()
-
+ m_vectortypes_category_name(ConstString("VectorTypes"))
{
LoadSystemFormatters();
- LoadLibStdcppFormatters();
- LoadLibcxxFormatters();
- LoadObjCFormatters();
- LoadCoreMediaFormatters();
- LoadHardcodedFormatters();
-
- EnableCategory(m_objc_category_name,TypeCategoryMap::Last);
- EnableCategory(m_corefoundation_category_name,TypeCategoryMap::Last);
- EnableCategory(m_appkit_category_name,TypeCategoryMap::Last);
- EnableCategory(m_coreservices_category_name,TypeCategoryMap::Last);
- EnableCategory(m_coregraphics_category_name,TypeCategoryMap::Last);
- EnableCategory(m_coremedia_category_name,TypeCategoryMap::Last);
- EnableCategory(m_gnu_cpp_category_name,TypeCategoryMap::Last);
- EnableCategory(m_libcxx_category_name,TypeCategoryMap::Last);
- EnableCategory(m_vectortypes_category_name,TypeCategoryMap::Last);
- EnableCategory(m_system_category_name,TypeCategoryMap::Last);
-}
-
-static void
-AddFormat (TypeCategoryImpl::SharedPointer category_sp,
- lldb::Format format,
- ConstString type_name,
- TypeFormatImpl::Flags flags,
- bool regex = false)
-{
- lldb::TypeFormatImplSP format_sp(new TypeFormatImpl_Format(format, flags));
-
- if (regex)
- category_sp->GetRegexTypeFormatsContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),format_sp);
- else
- category_sp->GetTypeFormatsContainer()->Add(type_name, format_sp);
-}
-
-
-static void
-AddStringSummary(TypeCategoryImpl::SharedPointer category_sp,
- const char* string,
- ConstString type_name,
- TypeSummaryImpl::Flags flags,
- bool regex = false)
-{
- lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags,
- string));
-
- if (regex)
- category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
- else
- category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
-}
-
-static void
-AddOneLineSummary (TypeCategoryImpl::SharedPointer category_sp,
- ConstString type_name,
- TypeSummaryImpl::Flags flags,
- bool regex = false)
-{
- flags.SetShowMembersOneLiner(true);
- lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, ""));
-
- if (regex)
- category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
- else
- category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
-}
-
-#ifndef LLDB_DISABLE_PYTHON
-static void
-AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp,
- CXXFunctionSummaryFormat::Callback funct,
- const char* description,
- ConstString type_name,
- TypeSummaryImpl::Flags flags,
- bool regex = false)
-{
- lldb::TypeSummaryImplSP summary_sp(new CXXFunctionSummaryFormat(flags,funct,description));
- if (regex)
- category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
- else
- category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
-}
-#endif
-
-#ifndef LLDB_DISABLE_PYTHON
-static void AddCXXSynthetic (TypeCategoryImpl::SharedPointer category_sp,
- CXXSyntheticChildren::CreateFrontEndCallback generator,
- const char* description,
- ConstString type_name,
- ScriptedSyntheticChildren::Flags flags,
- bool regex = false)
-{
- lldb::SyntheticChildrenSP synth_sp(new CXXSyntheticChildren(flags,description,generator));
- if (regex)
- category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), synth_sp);
- else
- category_sp->GetTypeSyntheticsContainer()->Add(type_name,synth_sp);
-}
-#endif
-
-#ifndef LLDB_DISABLE_PYTHON
-static void AddFilter (TypeCategoryImpl::SharedPointer category_sp,
- std::vector<std::string> children,
- const char* description,
- ConstString type_name,
- ScriptedSyntheticChildren::Flags flags,
- bool regex = false)
-{
- TypeFilterImplSP filter_sp(new TypeFilterImpl(flags));
- for (auto child : children)
- filter_sp->AddExpressionPath(child);
- if (regex)
- category_sp->GetRegexTypeFiltersContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), filter_sp);
- else
- category_sp->GetTypeFiltersContainer()->Add(type_name,filter_sp);
-}
-#endif
-
-void
-FormatManager::LoadLibStdcppFormatters()
-{
- TypeSummaryImpl::Flags stl_summary_flags;
- stl_summary_flags.SetCascades(true)
- .SetSkipPointers(false)
- .SetSkipReferences(false)
- .SetDontShowChildren(true)
- .SetDontShowValue(true)
- .SetShowMembersOneLiner(false)
- .SetHideItemNames(false);
-
- lldb::TypeSummaryImplSP std_string_summary_sp(new StringSummaryFormat(stl_summary_flags,
- "${var._M_dataplus._M_p}"));
-
- TypeCategoryImpl::SharedPointer gnu_category_sp = GetCategory(m_gnu_cpp_category_name);
-
- gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
- std_string_summary_sp);
- gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char>"),
- std_string_summary_sp);
- gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"),
- std_string_summary_sp);
- gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
- std_string_summary_sp);
-
- // making sure we force-pick the summary for printing wstring (_M_p is a wchar_t*)
- lldb::TypeSummaryImplSP std_wstring_summary_sp(new StringSummaryFormat(stl_summary_flags,
- "${var._M_dataplus._M_p%S}"));
-
- gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"),
- std_wstring_summary_sp);
- gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t>"),
- std_wstring_summary_sp);
- gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >"),
- std_wstring_summary_sp);
- gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
- std_wstring_summary_sp);
+ LoadVectorFormatters();
-
-#ifndef LLDB_DISABLE_PYTHON
-
- SyntheticChildren::Flags stl_synth_flags;
- stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
-
- gnu_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
- SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
- "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
- gnu_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
- SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
- "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
- gnu_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
- SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
- "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
-
- stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(true);
- gnu_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
- TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
- "size=${svar%#}")));
- gnu_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
- TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
- "size=${svar%#}")));
- gnu_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
- TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
- "size=${svar%#}")));
-
- AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
-
- AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
-#endif
-}
-
-void
-FormatManager::LoadLibcxxFormatters()
-{
- TypeSummaryImpl::Flags stl_summary_flags;
- stl_summary_flags.SetCascades(true)
- .SetSkipPointers(false)
- .SetSkipReferences(false)
- .SetDontShowChildren(true)
- .SetDontShowValue(true)
- .SetShowMembersOneLiner(false)
- .SetHideItemNames(false);
-
-#ifndef LLDB_DISABLE_PYTHON
- //std::string code(" lldb.formatters.cpp.libcxx.stdstring_SummaryProvider(valobj,internal_dict)");
- //lldb::TypeSummaryImplSP std_string_summary_sp(new ScriptSummaryFormat(stl_summary_flags, "lldb.formatters.cpp.libcxx.stdstring_SummaryProvider",code.c_str()));
-
- lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider, "std::string summary provider"));
- lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider, "std::wstring summary provider"));
-
- TypeCategoryImpl::SharedPointer libcxx_category_sp = GetCategory(m_libcxx_category_name);
-
- libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::string"),
- std_string_summary_sp);
- libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >"),
- std_string_summary_sp);
-
- libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::wstring"),
- std_wstring_summary_sp);
- libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >"),
- std_wstring_summary_sp);
-
- SyntheticChildren::Flags stl_synth_flags;
- stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
-
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_synth_flags, true);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_synth_flags, true);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::map synthetic children", ConstString("^std::__1::map<.+> >(( )?&)?$"), stl_synth_flags, true);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_synth_flags);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::set synthetic children", ConstString("^std::__1::set<.+> >(( )?&)?$"), stl_synth_flags, true);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator, "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true);
-
- libcxx_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")),
- SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
- "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
-
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "shared_ptr synthetic children", ConstString("^(std::__1::)shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "weak_ptr synthetic children", ConstString("^(std::__1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
-
- stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(false);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
-
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_summary_flags, true);
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_summary_flags, true);
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", ConstString("^std::__1::map<.+>(( )?&)?$"), stl_summary_flags, true);
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::deque summary provider", ConstString("^std::__1::deque<.+>(( )?&)?$"), stl_summary_flags, true);
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_summary_flags);
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__1::set<.+>(( )?&)?$"), stl_summary_flags, true);
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multiset summary provider", ConstString("^std::__1::multiset<.+>(( )?&)?$"), stl_summary_flags, true);
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multimap summary provider", ConstString("^std::__1::multimap<.+>(( )?&)?$"), stl_summary_flags, true);
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::unordered containers summary provider", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true);
-
- stl_summary_flags.SetSkipPointers(true);
-
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::shared_ptr summary provider", ConstString("^std::__1::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::weak_ptr summary provider", ConstString("^std::__1::weak_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
-
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^std::__1::__wrap_iter<.+>$"), stl_synth_flags, true);
-
- AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
- AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::__1::__map_iterator<.+>$"), stl_synth_flags, true);
-
- AddFilter(libcxx_category_sp, {"__a_"}, "libc++ std::atomic filter", ConstString("^std::__1::atomic<.*>$"), stl_synth_flags, true);
-#endif
+ EnableCategory(m_vectortypes_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus);
+ EnableCategory(m_system_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus);
}
void
FormatManager::LoadSystemFormatters()
{
-
TypeSummaryImpl::Flags string_flags;
string_flags.SetCascades(true)
.SetSkipPointers(true)
@@ -1157,7 +1086,7 @@ FormatManager::LoadSystemFormatters()
.SetHideItemNames(false);
TypeSummaryImpl::Flags string_array_flags;
- string_array_flags.SetCascades(false)
+ string_array_flags.SetCascades(true)
.SetSkipPointers(true)
.SetSkipReferences(false)
.SetDontShowChildren(true)
@@ -1192,31 +1121,6 @@ FormatManager::LoadSystemFormatters()
sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"), ostype_summary);
#ifndef LLDB_DISABLE_PYTHON
- // FIXME because of a bug in the FormattersContainer we need to add a summary for both X* and const X* (<rdar://problem/12717717>)
- AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags);
-
- AddCXXSummary(sys_category_sp, lldb_private::formatters::Char32StringSummaryProvider, "char32_t * summary provider", ConstString("char32_t *"), string_flags);
-
- AddCXXSummary(sys_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
- AddCXXSummary(sys_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
-
- AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "unichar * summary provider", ConstString("unichar *"), string_flags);
-
- TypeSummaryImpl::Flags widechar_flags;
- widechar_flags.SetDontShowValue(true)
- .SetSkipPointers(true)
- .SetSkipReferences(false)
- .SetCascades(true)
- .SetDontShowChildren(true)
- .SetHideItemNames(true)
- .SetShowMembersOneLiner(false);
-
- AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags);
- AddCXXSummary(sys_category_sp, lldb_private::formatters::Char32SummaryProvider, "char32_t summary provider", ConstString("char32_t"), widechar_flags);
- AddCXXSummary(sys_category_sp, lldb_private::formatters::WCharSummaryProvider, "wchar_t summary provider", ConstString("wchar_t"), widechar_flags);
-
- AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16SummaryProvider, "unichar summary provider", ConstString("unichar"), widechar_flags);
-
TypeFormatImpl::Flags fourchar_flags;
fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(true);
@@ -1225,283 +1129,10 @@ FormatManager::LoadSystemFormatters()
}
void
-FormatManager::LoadObjCFormatters()
+FormatManager::LoadVectorFormatters()
{
- TypeSummaryImpl::Flags objc_flags;
- objc_flags.SetCascades(false)
- .SetSkipPointers(true)
- .SetSkipReferences(true)
- .SetDontShowChildren(true)
- .SetDontShowValue(true)
- .SetShowMembersOneLiner(false)
- .SetHideItemNames(false);
-
- TypeCategoryImpl::SharedPointer objc_category_sp = GetCategory(m_objc_category_name);
- TypeCategoryImpl::SharedPointer appkit_category_sp = GetCategory(m_appkit_category_name);
- TypeCategoryImpl::SharedPointer corefoundation_category_sp = GetCategory(m_corefoundation_category_name);
- TypeCategoryImpl::SharedPointer coregraphics_category_sp = GetCategory(m_coregraphics_category_name);
- TypeCategoryImpl::SharedPointer coreservices_category_sp = GetCategory(m_coreservices_category_name);
-
- lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider,""));
- objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"),
- ObjC_BOOL_summary);
- objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"),
- ObjC_BOOL_summary);
- objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"),
- ObjC_BOOL_summary);
-
-#ifndef LLDB_DISABLE_PYTHON
- // we need to skip pointers here since we are special casing a SEL* when retrieving its value
- objc_flags.SetSkipPointers(true);
- AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("SEL"), objc_flags);
- AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("struct objc_selector"), objc_flags);
- AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("objc_selector"), objc_flags);
- AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, "SEL summary provider", ConstString("objc_selector *"), objc_flags);
- AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, "SEL summary provider", ConstString("SEL *"), objc_flags);
-
- AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCClassSummaryProvider, "Class summary provider", ConstString("Class"), objc_flags);
-
- SyntheticChildren::Flags class_synth_flags;
- class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
-
- AddCXXSynthetic(objc_category_sp, lldb_private::formatters::ObjCClassSyntheticFrontEndCreator, "Class synthetic children", ConstString("Class"), class_synth_flags);
-#endif // LLDB_DISABLE_PYTHON
-
- objc_flags.SetSkipPointers(false);
- objc_flags.SetCascades(true);
- objc_flags.SetSkipReferences(false);
-
- AddStringSummary (objc_category_sp,
- "${var.__FuncPtr%A}",
- ConstString("__block_literal_generic"),
- objc_flags);
-
- AddStringSummary(corefoundation_category_sp,
- "${var.years} years, ${var.months} months, ${var.days} days, ${var.hours} hours, ${var.minutes} minutes ${var.seconds} seconds",
- ConstString("CFGregorianUnits"),
- objc_flags);
- AddStringSummary(corefoundation_category_sp,
- "location=${var.location} length=${var.length}",
- ConstString("CFRange"),
- objc_flags);
-
- AddStringSummary(appkit_category_sp,
- "location=${var.location}, length=${var.length}",
- ConstString("NSRange"),
- objc_flags);
- AddStringSummary(appkit_category_sp,
- "(${var.origin}, ${var.size}), ...",
- ConstString("NSRectArray"),
- objc_flags);
-
- AddOneLineSummary (appkit_category_sp,
- ConstString("NSPoint"),
- objc_flags);
- AddOneLineSummary (appkit_category_sp,
- ConstString("NSSize"),
- objc_flags);
- AddOneLineSummary (appkit_category_sp,
- ConstString("NSRect"),
- objc_flags);
-
- AddOneLineSummary (coregraphics_category_sp,
- ConstString("CGSize"),
- objc_flags);
- AddOneLineSummary (coregraphics_category_sp,
- ConstString("CGPoint"),
- objc_flags);
- AddOneLineSummary (coregraphics_category_sp,
- ConstString("CGRect"),
- objc_flags);
-
- AddStringSummary(coreservices_category_sp,
- "red=${var.red} green=${var.green} blue=${var.blue}",
- ConstString("RGBColor"),
- objc_flags);
- AddStringSummary(coreservices_category_sp,
- "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})",
- ConstString("Rect"),
- objc_flags);
- AddStringSummary(coreservices_category_sp,
- "(v=${var.v}, h=${var.h})",
- ConstString("Point"),
- objc_flags);
- AddStringSummary(coreservices_category_sp,
- "${var.month}/${var.day}/${var.year} ${var.hour} :${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}",
- ConstString("DateTimeRect *"),
- objc_flags);
- AddStringSummary(coreservices_category_sp,
- "${var.ld.month}/${var.ld.day}/${var.ld.year} ${var.ld.hour} :${var.ld.minute} :${var.ld.second} dayOfWeek:${var.ld.dayOfWeek}",
- ConstString("LongDateRect"),
- objc_flags);
- AddStringSummary(coreservices_category_sp,
- "(x=${var.x}, y=${var.y})",
- ConstString("HIPoint"),
- objc_flags);
- AddStringSummary(coreservices_category_sp,
- "origin=${var.origin} size=${var.size}",
- ConstString("HIRect"),
- objc_flags);
-
- TypeSummaryImpl::Flags appkit_flags;
- appkit_flags.SetCascades(true)
- .SetSkipPointers(false)
- .SetSkipReferences(false)
- .SetDontShowChildren(true)
- .SetDontShowValue(false)
- .SetShowMembersOneLiner(false)
- .SetHideItemNames(false);
-
- appkit_flags.SetDontShowChildren(false);
-
-
-#ifndef LLDB_DISABLE_PYTHON
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSArray"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFMutableArrayRef"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSDictionary"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSMutableDictionary"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSCFDictionary"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryI"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryM"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSSet summary", ConstString("NSSet"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFSetRef summary", ConstString("CFSetRef"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetI summary", ConstString("__NSSetI"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetM summary", ConstString("__NSSetM"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags);
-
- // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}", ConstString("$_lldb_typegen_nspair"), appkit_flags);
-
- appkit_flags.SetDontShowChildren(true);
-
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayM"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayI"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSArray"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSMutableArray"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSCFArray"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFMutableArrayRef"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFArrayRef"), ScriptedSyntheticChildren::Flags());
-
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryM"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryI"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSCFDictionary"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSDictionary"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSMutableDictionary"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFDictionaryRef"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"), ScriptedSyntheticChildren::Flags());
-
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSSet synthetic children", ConstString("NSSet"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetI synthetic children", ConstString("__NSSetI"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetM synthetic children", ConstString("__NSSetM"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSMutableSet synthetic children", ConstString("NSMutableSet"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSOrderedSet synthetic children", ConstString("NSOrderedSet"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags());
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags());
-
- AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, "NSIndexPath synthetic children", ConstString("NSIndexPath"), ScriptedSyntheticChildren::Flags());
-
- AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("const struct __CFBag"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags);
-
- AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSString"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFStringRef"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__CFString"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFMutableStringRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSMutableString"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFConstantString"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFString"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFConstantString"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFString"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSPathStore2"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSAttributedStringSummaryProvider, "NSAttributedString summary provider", ConstString("NSAttributedString"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSMutableAttributedString"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSConcreteMutableAttributedString"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSBundleSummaryProvider, "NSBundle summary provider", ConstString("NSBundle"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSData"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteData"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteMutableData"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSMutableData"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("__NSCFData"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFDataRef"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSMachPortSummaryProvider, "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSNotification"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSConcreteNotification"), appkit_flags);
-
- AddStringSummary(appkit_category_sp, "domain: ${var._domain} - code: ${var._code}", ConstString("NSError"), appkit_flags);
- AddStringSummary(appkit_category_sp,"name:${var.name%S} reason:${var.reason%S}",ConstString("NSException"),appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSNumber"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSDecimalNumber summary provider", ConstString("NSDecimalNumber"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSHost summary provider", ConstString("NSHost"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSTask summary provider", ConstString("NSTask"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSValue summary provider", ConstString("NSValue"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("NSURL"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("CFURLRef"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSDate"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSDate"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("CFTimeZoneRef"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags);
-
- // CFAbsoluteTime is actually a double rather than a pointer to an object
- // we do not care about the numeric value, since it is probably meaningless to users
- appkit_flags.SetDontShowValue(true);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFAbsoluteTimeSummaryProvider, "CFAbsoluteTime summary provider", ConstString("CFAbsoluteTime"), appkit_flags);
- appkit_flags.SetDontShowValue(false);
-
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags);
- AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSMutableIndexSet"), appkit_flags);
-
- AddStringSummary(corefoundation_category_sp,
- "@\"${var.month%d}/${var.day%d}/${var.year%d} ${var.hour%d}:${var.minute%d}:${var.second}\"",
- ConstString("CFGregorianDate"),
- appkit_flags);
-
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFBitVectorRef"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFMutableBitVectorRef"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFBitVector"), appkit_flags);
- AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFMutableBitVector"), appkit_flags);
-#endif // LLDB_DISABLE_PYTHON
-
TypeCategoryImpl::SharedPointer vectors_category_sp = GetCategory(m_vectortypes_category_name);
-
+
TypeSummaryImpl::Flags vector_flags;
vector_flags.SetCascades(true)
.SetSkipPointers(true)
@@ -1514,8 +1145,8 @@ FormatManager::LoadObjCFormatters()
AddStringSummary(vectors_category_sp,
"${var.uint128}",
ConstString("builtin_type_vec128"),
- objc_flags);
-
+ vector_flags);
+
AddStringSummary(vectors_category_sp,
"",
ConstString("float [4]"),
@@ -1569,84 +1200,3 @@ FormatManager::LoadObjCFormatters()
ConstString("vBool32"),
vector_flags);
}
-
-void
-FormatManager::LoadCoreMediaFormatters()
-{
- TypeSummaryImpl::Flags cm_flags;
- cm_flags.SetCascades(true)
- .SetDontShowChildren(false)
- .SetDontShowValue(false)
- .SetHideItemNames(false)
- .SetShowMembersOneLiner(false)
- .SetSkipPointers(false)
- .SetSkipReferences(false);
-
- TypeCategoryImpl::SharedPointer cm_category_sp = GetCategory(m_coremedia_category_name);
-
-#ifndef LLDB_DISABLE_PYTHON
- AddCXXSummary(cm_category_sp, lldb_private::formatters::CMTimeSummaryProvider, "CMTime summary provider", ConstString("CMTime"), cm_flags);
-#endif // LLDB_DISABLE_PYTHON
-}
-
-void
-FormatManager::LoadHardcodedFormatters()
-{
- {
- // insert code to load formats here
- }
- {
- // insert code to load summaries here
- m_hardcoded_summaries.push_back(
- [](lldb_private::ValueObject& valobj,
- lldb::DynamicValueType,
- FormatManager&) -> TypeSummaryImpl::SharedPointer {
- static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags(), lldb_private::formatters::FunctionPointerSummaryProvider, "Function pointer summary provider"));
- if (valobj.GetClangType().IsFunctionPointerType())
- {
- return formatter_sp;
- }
- return nullptr;
- });
- m_hardcoded_summaries.push_back(
- [](lldb_private::ValueObject& valobj,
- lldb::DynamicValueType,
- FormatManager& fmt_mgr) -> TypeSummaryImpl::SharedPointer {
- static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags()
- .SetCascades(true)
- .SetDontShowChildren(true)
- .SetHideItemNames(true)
- .SetShowMembersOneLiner(true)
- .SetSkipPointers(true)
- .SetSkipReferences(false),
- lldb_private::formatters::VectorTypeSummaryProvider,
- "vector_type pointer summary provider"));
- if (valobj.GetClangType().IsVectorType(nullptr, nullptr))
- {
- if (fmt_mgr.GetCategory(fmt_mgr.m_vectortypes_category_name)->IsEnabled())
- return formatter_sp;
- }
- return nullptr;
- });
- }
- {
- // insert code to load synthetics here
- m_hardcoded_synthetics.push_back(
- [](lldb_private::ValueObject& valobj,
- lldb::DynamicValueType,
- FormatManager& fmt_mgr) -> SyntheticChildren::SharedPointer {
- static CXXSyntheticChildren::SharedPointer formatter_sp(new CXXSyntheticChildren(SyntheticChildren::Flags().SetCascades(true).SetSkipPointers(true).SetSkipReferences(true).SetNonCacheable(true),
- "vector_type synthetic children",
- lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
- if (valobj.GetClangType().IsVectorType(nullptr, nullptr))
- {
- if (fmt_mgr.GetCategory(fmt_mgr.m_vectortypes_category_name)->IsEnabled())
- return formatter_sp;
- }
- return nullptr;
- });
- }
- {
- // insert code to load validators here
- }
-}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/FormattersHelpers.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/FormattersHelpers.cpp
new file mode 100644
index 0000000..4b0e82e
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/FormattersHelpers.cpp
@@ -0,0 +1,336 @@
+//===-- FormattersHelpers.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+
+// C++ Includes
+
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+void
+lldb_private::formatters::AddFormat (TypeCategoryImpl::SharedPointer category_sp,
+ lldb::Format format,
+ ConstString type_name,
+ TypeFormatImpl::Flags flags,
+ bool regex)
+{
+ lldb::TypeFormatImplSP format_sp(new TypeFormatImpl_Format(format, flags));
+
+ if (regex)
+ category_sp->GetRegexTypeFormatsContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),format_sp);
+ else
+ category_sp->GetTypeFormatsContainer()->Add(type_name, format_sp);
+}
+
+void
+lldb_private::formatters::AddSummary(TypeCategoryImpl::SharedPointer category_sp,
+ TypeSummaryImplSP summary_sp,
+ ConstString type_name,
+ bool regex)
+{
+ if (regex)
+ category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
+ else
+ category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
+}
+
+void
+lldb_private::formatters::AddStringSummary(TypeCategoryImpl::SharedPointer category_sp,
+ const char* string,
+ ConstString type_name,
+ TypeSummaryImpl::Flags flags,
+ bool regex)
+{
+ lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags,
+ string));
+
+ if (regex)
+ category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
+ else
+ category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
+}
+
+void
+lldb_private::formatters::AddOneLineSummary (TypeCategoryImpl::SharedPointer category_sp,
+ ConstString type_name,
+ TypeSummaryImpl::Flags flags,
+ bool regex)
+{
+ flags.SetShowMembersOneLiner(true);
+ lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, ""));
+
+ if (regex)
+ category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
+ else
+ category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
+}
+
+#ifndef LLDB_DISABLE_PYTHON
+void
+lldb_private::formatters::AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp,
+ CXXFunctionSummaryFormat::Callback funct,
+ const char* description,
+ ConstString type_name,
+ TypeSummaryImpl::Flags flags,
+ bool regex)
+{
+ lldb::TypeSummaryImplSP summary_sp(new CXXFunctionSummaryFormat(flags,funct,description));
+ if (regex)
+ category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp);
+ else
+ category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp);
+}
+
+void
+lldb_private::formatters::AddCXXSynthetic (TypeCategoryImpl::SharedPointer category_sp,
+ CXXSyntheticChildren::CreateFrontEndCallback generator,
+ const char* description,
+ ConstString type_name,
+ ScriptedSyntheticChildren::Flags flags,
+ bool regex)
+{
+ lldb::SyntheticChildrenSP synth_sp(new CXXSyntheticChildren(flags,description,generator));
+ if (regex)
+ category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), synth_sp);
+ else
+ category_sp->GetTypeSyntheticsContainer()->Add(type_name,synth_sp);
+}
+
+void
+lldb_private::formatters::AddFilter (TypeCategoryImpl::SharedPointer category_sp,
+ std::vector<std::string> children,
+ const char* description,
+ ConstString type_name,
+ ScriptedSyntheticChildren::Flags flags,
+ bool regex)
+{
+ TypeFilterImplSP filter_sp(new TypeFilterImpl(flags));
+ for (auto child : children)
+ filter_sp->AddExpressionPath(child);
+ if (regex)
+ category_sp->GetRegexTypeFiltersContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), filter_sp);
+ else
+ category_sp->GetTypeFiltersContainer()->Add(type_name,filter_sp);
+}
+#endif
+
+StackFrame*
+lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx)
+{
+ StackFrame* frame = exe_ctx.GetFramePtr();
+ if (frame)
+ return frame;
+
+ Process* process = exe_ctx.GetProcessPtr();
+ if (!process)
+ return nullptr;
+
+ ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
+ if (thread_sp)
+ return thread_sp->GetSelectedFrame().get();
+ return nullptr;
+}
+
+bool
+lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
+ const char* target_type,
+ const char* selector,
+ uint64_t &value)
+{
+ if (!target_type || !*target_type)
+ return false;
+ if (!selector || !*selector)
+ return false;
+ StreamString expr;
+ expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
+ ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+ lldb::ValueObjectSP result_sp;
+ Target* target = exe_ctx.GetTargetPtr();
+ StackFrame* stack_frame = GetViableFrame(exe_ctx);
+ if (!target || !stack_frame)
+ return false;
+
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(true);
+ options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus);
+ options.SetResultIsInternal(true);
+ options.SetUseDynamic(lldb::eDynamicCanRunTarget);
+
+ target->EvaluateExpression(expr.GetData(),
+ stack_frame,
+ result_sp,
+ options);
+ if (!result_sp)
+ return false;
+ value = result_sp->GetValueAsUnsigned(0);
+ return true;
+}
+
+bool
+lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
+ const char* target_type,
+ const char* selector,
+ Stream &stream,
+ lldb::LanguageType lang_type)
+{
+ if (!target_type || !*target_type)
+ return false;
+ if (!selector || !*selector)
+ return false;
+ StreamString expr;
+ expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
+ ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+ lldb::ValueObjectSP result_sp;
+ Target* target = exe_ctx.GetTargetPtr();
+ StackFrame* stack_frame = GetViableFrame(exe_ctx);
+ if (!target || !stack_frame)
+ return false;
+
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(true);
+ options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus);
+ options.SetResultIsInternal(true);
+ options.SetUseDynamic(lldb::eDynamicCanRunTarget);
+
+ target->EvaluateExpression(expr.GetData(),
+ stack_frame,
+ result_sp,
+ options);
+ if (!result_sp)
+ return false;
+ stream.Printf("%s",result_sp->GetSummaryAsCString(lang_type));
+ return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
+ const char* return_type,
+ const char* selector,
+ uint64_t index)
+{
+ lldb::ValueObjectSP valobj_sp;
+ if (!return_type || !*return_type)
+ return valobj_sp;
+ if (!selector || !*selector)
+ return valobj_sp;
+ StreamString expr;
+ const char *colon = "";
+ llvm::StringRef selector_sr(selector);
+ if (selector_sr.back() != ':')
+ colon = ":";
+ expr.Printf("(%s)[(id)0x%" PRIx64 " %s%s%" PRId64 "]",return_type,valobj.GetPointerValue(),selector,colon,index);
+ ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+ lldb::ValueObjectSP result_sp;
+ Target* target = exe_ctx.GetTargetPtr();
+ StackFrame* stack_frame = GetViableFrame(exe_ctx);
+ if (!target || !stack_frame)
+ return valobj_sp;
+
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(true);
+ options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus);
+ options.SetResultIsInternal(true);
+ options.SetUseDynamic(lldb::eDynamicCanRunTarget);
+
+ target->EvaluateExpression(expr.GetData(),
+ stack_frame,
+ valobj_sp,
+ options);
+ return valobj_sp;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
+ const char* return_type,
+ const char* selector,
+ const char* key)
+{
+ lldb::ValueObjectSP valobj_sp;
+ if (!return_type || !*return_type)
+ return valobj_sp;
+ if (!selector || !*selector)
+ return valobj_sp;
+ if (!key || !*key)
+ return valobj_sp;
+ StreamString expr;
+ const char *colon = "";
+ llvm::StringRef selector_sr(selector);
+ if (selector_sr.back() != ':')
+ colon = ":";
+ expr.Printf("(%s)[(id)0x%" PRIx64 " %s%s%s]",return_type,valobj.GetPointerValue(),selector,colon,key);
+ ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+ lldb::ValueObjectSP result_sp;
+ Target* target = exe_ctx.GetTargetPtr();
+ StackFrame* stack_frame = GetViableFrame(exe_ctx);
+ if (!target || !stack_frame)
+ return valobj_sp;
+
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(true);
+ options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus);
+ options.SetResultIsInternal(true);
+ options.SetUseDynamic(lldb::eDynamicCanRunTarget);
+
+ target->EvaluateExpression(expr.GetData(),
+ stack_frame,
+ valobj_sp,
+ options);
+ return valobj_sp;
+}
+
+size_t
+lldb_private::formatters::ExtractIndexFromString (const char* item_name)
+{
+ if (!item_name || !*item_name)
+ return UINT32_MAX;
+ if (*item_name != '[')
+ return UINT32_MAX;
+ item_name++;
+ char* endptr = NULL;
+ unsigned long int idx = ::strtoul(item_name, &endptr, 0);
+ if (idx == 0 && endptr == item_name)
+ return UINT32_MAX;
+ if (idx == ULONG_MAX)
+ return UINT32_MAX;
+ return idx;
+}
+
+lldb::addr_t
+lldb_private::formatters::GetArrayAddressOrPointerValue (ValueObject& valobj)
+{
+ lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
+
+ if (valobj.IsPointerType())
+ data_addr = valobj.GetValueAsUnsigned(0);
+ else if (valobj.IsArrayType())
+ data_addr = valobj.GetAddressOf();
+
+ return data_addr;
+}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/LanguageCategory.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/LanguageCategory.cpp
new file mode 100644
index 0000000..261c3e6
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/LanguageCategory.cpp
@@ -0,0 +1,271 @@
+//===-- LanguageCategory.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/DataFormatters/LanguageCategory.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/DataFormatters/TypeCategory.h"
+#include "lldb/DataFormatters/TypeFormat.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/DataFormatters/TypeValidator.h"
+#include "lldb/Target/Language.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+LanguageCategory::LanguageCategory (lldb::LanguageType lang_type) :
+ m_category_sp(),
+ m_hardcoded_formats(),
+ m_hardcoded_summaries(),
+ m_hardcoded_synthetics(),
+ m_hardcoded_validators(),
+ m_format_cache(),
+ m_enabled(false)
+{
+ if (Language* language_plugin = Language::FindPlugin(lang_type))
+ {
+ m_category_sp = language_plugin->GetFormatters();
+ m_hardcoded_formats = language_plugin->GetHardcodedFormats();
+ m_hardcoded_summaries = language_plugin->GetHardcodedSummaries();
+ m_hardcoded_synthetics = language_plugin->GetHardcodedSynthetics();
+ m_hardcoded_validators = language_plugin->GetHardcodedValidators();
+ }
+ Enable();
+}
+
+bool
+LanguageCategory::Get (FormattersMatchData& match_data,
+ lldb::TypeFormatImplSP& format_sp)
+{
+ if (!m_category_sp)
+ return false;
+
+ if (!IsEnabled())
+ return false;
+
+ if (match_data.GetTypeForCache())
+ {
+ if (m_format_cache.GetFormat(match_data.GetTypeForCache(), format_sp))
+ return format_sp.get() != nullptr;
+ }
+
+ ValueObject& valobj(match_data.GetValueObject());
+ bool result = m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp);
+ if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable()))
+ {
+ m_format_cache.SetFormat(match_data.GetTypeForCache(), format_sp);
+ }
+ return result;
+}
+
+bool
+LanguageCategory::Get (FormattersMatchData& match_data,
+ lldb::TypeSummaryImplSP& format_sp)
+{
+ if (!m_category_sp)
+ return false;
+
+ if (!IsEnabled())
+ return false;
+
+ if (match_data.GetTypeForCache())
+ {
+ if (m_format_cache.GetSummary(match_data.GetTypeForCache(), format_sp))
+ return format_sp.get() != nullptr;
+ }
+
+ ValueObject& valobj(match_data.GetValueObject());
+ bool result = m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp);
+ if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable()))
+ {
+ m_format_cache.SetSummary(match_data.GetTypeForCache(), format_sp);
+ }
+ return result;
+}
+
+bool
+LanguageCategory::Get (FormattersMatchData& match_data,
+ lldb::SyntheticChildrenSP& format_sp)
+{
+ if (!m_category_sp)
+ return false;
+
+ if (!IsEnabled())
+ return false;
+
+ if (match_data.GetTypeForCache())
+ {
+ if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(), format_sp))
+ return format_sp.get() != nullptr;
+ }
+
+ ValueObject& valobj(match_data.GetValueObject());
+ bool result = m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp);
+ if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable()))
+ {
+ m_format_cache.SetSynthetic(match_data.GetTypeForCache(), format_sp);
+ }
+ return result;
+}
+
+bool
+LanguageCategory::Get (FormattersMatchData& match_data,
+ lldb::TypeValidatorImplSP& format_sp)
+{
+ if (!m_category_sp)
+ return false;
+
+ if (!IsEnabled())
+ return false;
+
+ if (match_data.GetTypeForCache())
+ {
+ if (m_format_cache.GetValidator(match_data.GetTypeForCache(), format_sp))
+ return format_sp.get() != nullptr;
+ }
+
+ ValueObject& valobj(match_data.GetValueObject());
+ bool result = m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp);
+ if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable()))
+ {
+ m_format_cache.SetValidator(match_data.GetTypeForCache(), format_sp);
+ }
+ return result;
+}
+
+bool
+LanguageCategory::GetHardcoded (FormatManager& fmt_mgr,
+ FormattersMatchData& match_data,
+ lldb::TypeFormatImplSP& format_sp)
+{
+ if (!IsEnabled())
+ return false;
+
+ ValueObject& valobj(match_data.GetValueObject());
+ lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType());
+
+ for (auto& candidate : m_hardcoded_formats)
+ {
+ if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr)))
+ break;
+ }
+ if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable()))
+ {
+ m_format_cache.SetFormat(match_data.GetTypeForCache(), format_sp);
+ }
+ return format_sp.get() != nullptr;
+}
+
+bool
+LanguageCategory::GetHardcoded (FormatManager& fmt_mgr,
+ FormattersMatchData& match_data,
+ lldb::TypeSummaryImplSP& format_sp)
+{
+ if (!IsEnabled())
+ return false;
+
+ ValueObject& valobj(match_data.GetValueObject());
+ lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType());
+
+ for (auto& candidate : m_hardcoded_summaries)
+ {
+ if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr)))
+ break;
+ }
+ if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable()))
+ {
+ m_format_cache.SetSummary(match_data.GetTypeForCache(), format_sp);
+ }
+ return format_sp.get() != nullptr;
+}
+
+bool
+LanguageCategory::GetHardcoded (FormatManager& fmt_mgr,
+ FormattersMatchData& match_data,
+ lldb::SyntheticChildrenSP& format_sp)
+{
+ if (!IsEnabled())
+ return false;
+
+ ValueObject& valobj(match_data.GetValueObject());
+ lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType());
+
+ for (auto& candidate : m_hardcoded_synthetics)
+ {
+ if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr)))
+ break;
+ }
+ if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable()))
+ {
+ m_format_cache.SetSynthetic(match_data.GetTypeForCache(), format_sp);
+ }
+ return format_sp.get() != nullptr;
+}
+
+bool
+LanguageCategory::GetHardcoded (FormatManager& fmt_mgr,
+ FormattersMatchData& match_data,
+ lldb::TypeValidatorImplSP& format_sp)
+{
+ if (!IsEnabled())
+ return false;
+
+ ValueObject& valobj(match_data.GetValueObject());
+ lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType());
+
+ for (auto& candidate : m_hardcoded_validators)
+ {
+ if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr)))
+ break;
+ }
+ if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable()))
+ {
+ m_format_cache.SetValidator(match_data.GetTypeForCache(), format_sp);
+ }
+ return format_sp.get() != nullptr;
+}
+
+lldb::TypeCategoryImplSP
+LanguageCategory::GetCategory () const
+{
+ return m_category_sp;
+}
+
+FormatCache&
+LanguageCategory::GetFormatCache ()
+{
+ return m_format_cache;
+}
+
+void
+LanguageCategory::Enable ()
+{
+ if (m_category_sp)
+ m_category_sp->Enable(true, TypeCategoryMap::Default);
+ m_enabled = true;
+}
+
+void
+LanguageCategory::Disable ()
+{
+ if (m_category_sp)
+ m_category_sp->Disable();
+ m_enabled = false;
+}
+
+bool
+LanguageCategory::IsEnabled ()
+{
+ return m_enabled;
+}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/LibStdcpp.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/LibStdcpp.cpp
deleted file mode 100644
index 2b3bcb5..0000000
--- a/contrib/llvm/tools/lldb/source/DataFormatters/LibStdcpp.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-//===-- LibStdcpp.cpp ---------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
-
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Host/Endian.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/Target.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace lldb_private::formatters;
-
-/*
- (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) ibeg = {
- (_Base_ptr) _M_node = 0x0000000100103910 {
- (std::_Rb_tree_color) _M_color = _S_black
- (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0
- (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000
- (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000
- }
- }
- */
-
-lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
- SyntheticChildrenFrontEnd(*valobj_sp.get()),
- m_exe_ctx_ref(),
- m_pair_address(0),
- m_pair_type(),
- m_options(),
- m_pair_sp()
-{
- if (valobj_sp)
- Update();
- m_options.SetCoerceToId(false);
- m_options.SetUnwindOnError(true);
- m_options.SetKeepInMemory(true);
- m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
-}
-
-bool
-lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::Update()
-{
- ValueObjectSP valobj_sp = m_backend.GetSP();
- if (!valobj_sp)
- return false;
-
- TargetSP target_sp(valobj_sp->GetTargetSP());
-
- if (!target_sp)
- return false;
-
- bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8);
-
- if (!valobj_sp)
- return false;
- m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
-
- ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true));
- if (!_M_node_sp)
- return false;
-
- m_pair_address = _M_node_sp->GetValueAsUnsigned(0);
- if (m_pair_address == 0)
- return false;
-
- m_pair_address += (is_64bit ? 32 : 16);
-
- ClangASTType my_type(valobj_sp->GetClangType());
- if (my_type.GetNumTemplateArguments() >= 1)
- {
- TemplateArgumentKind kind;
- ClangASTType pair_type = my_type.GetTemplateArgument(0, kind);
- if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion)
- return false;
- m_pair_type = pair_type;
- }
- else
- return false;
-
- return true;
-}
-
-size_t
-lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
-{
- return 2;
-}
-
-lldb::ValueObjectSP
-lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
-{
- if (m_pair_address != 0 && m_pair_type)
- {
- if (!m_pair_sp)
- m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type);
- if (m_pair_sp)
- return m_pair_sp->GetChildAtIndex(idx, true);
- }
- return lldb::ValueObjectSP();
-}
-
-bool
-lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren ()
-{
- return true;
-}
-
-size_t
-lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
-{
- if (name == ConstString("first"))
- return 0;
- if (name == ConstString("second"))
- return 1;
- return UINT32_MAX;
-}
-
-lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::~LibstdcppMapIteratorSyntheticFrontEnd ()
-{}
-
-SyntheticChildrenFrontEnd*
-lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
-{
- if (!valobj_sp)
- return NULL;
- return (new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp));
-}
-
-/*
- (lldb) fr var ibeg --ptr-depth 1
- (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >) ibeg = {
- _M_current = 0x00000001001037a0 {
- *_M_current = 1
- }
- }
- */
-
-SyntheticChildrenFrontEnd*
-lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
-{
- static ConstString g_item_name;
- if (!g_item_name)
- g_item_name.SetCString("_M_current");
- if (!valobj_sp)
- return NULL;
- return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
-}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/StringPrinter.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/StringPrinter.cpp
index a011cd5..b114add 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/StringPrinter.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/StringPrinter.cpp
@@ -9,109 +9,26 @@
#include "lldb/DataFormatters/StringPrinter.h"
-#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/ValueObject.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "llvm/Support/ConvertUTF.h"
#include <ctype.h>
-#include <functional>
#include <locale>
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
-// I can't use a std::unique_ptr for this because the Deleter is a template argument there
-// and I want the same type to represent both pointers I want to free and pointers I don't need
-// to free - which is what this class essentially is
-// It's very specialized to the needs of this file, and not suggested for general use
-template <typename T = uint8_t, typename U = char, typename S = size_t>
-struct StringPrinterBufferPointer
-{
-public:
-
- typedef std::function<void(const T*)> Deleter;
-
- StringPrinterBufferPointer (std::nullptr_t ptr) :
- m_data(nullptr),
- m_size(0),
- m_deleter()
- {}
-
- StringPrinterBufferPointer(const T* bytes, S size, Deleter deleter = nullptr) :
- m_data(bytes),
- m_size(size),
- m_deleter(deleter)
- {}
-
- StringPrinterBufferPointer(const U* bytes, S size, Deleter deleter = nullptr) :
- m_data((T*)bytes),
- m_size(size),
- m_deleter(deleter)
- {}
-
- StringPrinterBufferPointer(StringPrinterBufferPointer&& rhs) :
- m_data(rhs.m_data),
- m_size(rhs.m_size),
- m_deleter(rhs.m_deleter)
- {
- rhs.m_data = nullptr;
- }
-
- StringPrinterBufferPointer(const StringPrinterBufferPointer& rhs) :
- m_data(rhs.m_data),
- m_size(rhs.m_size),
- m_deleter(rhs.m_deleter)
- {
- rhs.m_data = nullptr; // this is why m_data has to be mutable
- }
-
- const T*
- GetBytes () const
- {
- return m_data;
- }
-
- const S
- GetSize () const
- {
- return m_size;
- }
-
- ~StringPrinterBufferPointer ()
- {
- if (m_data && m_deleter)
- m_deleter(m_data);
- m_data = nullptr;
- }
-
- StringPrinterBufferPointer&
- operator = (const StringPrinterBufferPointer& rhs)
- {
- if (m_data && m_deleter)
- m_deleter(m_data);
- m_data = rhs.m_data;
- m_size = rhs.m_size;
- m_deleter = rhs.m_deleter;
- rhs.m_data = nullptr;
- return *this;
- }
-
-private:
- mutable const T* m_data;
- size_t m_size;
- Deleter m_deleter;
-};
-
// we define this for all values of type but only implement it for those we care about
// that's good because we get linker errors for any unsupported type
-template <StringElementType type>
-static StringPrinterBufferPointer<>
+template <lldb_private::formatters::StringPrinter::StringElementType type>
+static StringPrinter::StringPrinterBufferPointer<>
GetPrintableImpl(uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next);
// mimic isprint() for Unicode codepoints
@@ -142,10 +59,10 @@ isprint(char32_t codepoint)
}
template <>
-StringPrinterBufferPointer<>
-GetPrintableImpl<StringElementType::ASCII> (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
+StringPrinter::StringPrinterBufferPointer<>
+GetPrintableImpl<StringPrinter::StringElementType::ASCII> (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
{
- StringPrinterBufferPointer<> retval = {nullptr};
+ StringPrinter::StringPrinterBufferPointer<> retval = {nullptr};
switch (*buffer)
{
@@ -212,10 +129,10 @@ ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1, unsigned char c2, un
}
template <>
-StringPrinterBufferPointer<>
-GetPrintableImpl<StringElementType::UTF8> (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
+StringPrinter::StringPrinterBufferPointer<>
+GetPrintableImpl<StringPrinter::StringElementType::UTF8> (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
{
- StringPrinterBufferPointer<> retval {nullptr};
+ StringPrinter::StringPrinterBufferPointer<> retval {nullptr};
unsigned utf8_encoded_len = getNumBytesForUTF8(*buffer);
@@ -232,7 +149,7 @@ GetPrintableImpl<StringElementType::UTF8> (uint8_t* buffer, uint8_t* buffer_end,
{
case 1:
// this is just an ASCII byte - ask ASCII
- return GetPrintableImpl<StringElementType::ASCII>(buffer, buffer_end, next);
+ return GetPrintableImpl<StringPrinter::StringElementType::ASCII>(buffer, buffer_end, next);
case 2:
codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1));
break;
@@ -309,23 +226,40 @@ GetPrintableImpl<StringElementType::UTF8> (uint8_t* buffer, uint8_t* buffer_end,
// Given a sequence of bytes, this function returns:
// a sequence of bytes to actually print out + a length
// the following unscanned position of the buffer is in next
-static StringPrinterBufferPointer<>
-GetPrintable(StringElementType type, uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
+static StringPrinter::StringPrinterBufferPointer<>
+GetPrintable(StringPrinter::StringElementType type, uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
{
if (!buffer)
return {nullptr};
switch (type)
{
- case StringElementType::ASCII:
- return GetPrintableImpl<StringElementType::ASCII>(buffer, buffer_end, next);
- case StringElementType::UTF8:
- return GetPrintableImpl<StringElementType::UTF8>(buffer, buffer_end, next);
+ case StringPrinter::StringElementType::ASCII:
+ return GetPrintableImpl<StringPrinter::StringElementType::ASCII>(buffer, buffer_end, next);
+ case StringPrinter::StringElementType::UTF8:
+ return GetPrintableImpl<StringPrinter::StringElementType::UTF8>(buffer, buffer_end, next);
default:
return {nullptr};
}
}
+StringPrinter::EscapingHelper
+StringPrinter::GetDefaultEscapingHelper (GetPrintableElementType elem_type)
+{
+ switch (elem_type)
+ {
+ case GetPrintableElementType::UTF8:
+ return [] (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) -> StringPrinter::StringPrinterBufferPointer<> {
+ return GetPrintable(StringPrinter::StringElementType::UTF8, buffer, buffer_end, next);
+ };
+ case GetPrintableElementType::ASCII:
+ return [] (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) -> StringPrinter::StringPrinterBufferPointer<> {
+ return GetPrintable(StringPrinter::StringElementType::ASCII, buffer, buffer_end, next);
+ };
+ }
+ llvm_unreachable("bad element type");
+}
+
// use this call if you already have an LLDB-side buffer for the data
template<typename SourceDataType>
static bool
@@ -334,41 +268,44 @@ DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType
UTF8**,
UTF8*,
ConversionFlags),
- const DataExtractor& data,
- Stream& stream,
- char prefix_token,
- char quote,
- uint32_t sourceSize,
- bool escapeNonPrintables)
+ const StringPrinter::ReadBufferAndDumpToStreamOptions& dump_options)
{
- if (prefix_token != 0)
- stream.Printf("%c",prefix_token);
- if (quote != 0)
- stream.Printf("%c",quote);
+ Stream &stream(*dump_options.GetStream());
+ if (dump_options.GetPrefixToken() != 0)
+ stream.Printf("%s",dump_options.GetPrefixToken());
+ if (dump_options.GetQuote() != 0)
+ stream.Printf("%c",dump_options.GetQuote());
+ auto data(dump_options.GetData());
+ auto source_size(dump_options.GetSourceSize());
if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
{
const int bufferSPSize = data.GetByteSize();
- if (sourceSize == 0)
+ if (dump_options.GetSourceSize() == 0)
{
const int origin_encoding = 8*sizeof(SourceDataType);
- sourceSize = bufferSPSize/(origin_encoding / 4);
+ source_size = bufferSPSize/(origin_encoding / 4);
}
const SourceDataType *data_ptr = (const SourceDataType*)data.GetDataStart();
- const SourceDataType *data_end_ptr = data_ptr + sourceSize;
+ const SourceDataType *data_end_ptr = data_ptr + source_size;
- while (data_ptr < data_end_ptr)
+ const bool zero_is_terminator = dump_options.GetBinaryZeroIsTerminator();
+
+ if (zero_is_terminator)
{
- if (!*data_ptr)
+ while (data_ptr < data_end_ptr)
{
- data_end_ptr = data_ptr;
- break;
+ if (!*data_ptr)
+ {
+ data_end_ptr = data_ptr;
+ break;
+ }
+ data_ptr++;
}
- data_ptr++;
+
+ data_ptr = (const SourceDataType*)data.GetDataStart();
}
- data_ptr = (const SourceDataType*)data.GetDataStart();
-
lldb::DataBufferSP utf8_data_buffer_sp;
UTF8* utf8_data_ptr = nullptr;
UTF8* utf8_data_end_ptr = nullptr;
@@ -379,14 +316,26 @@ DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType
utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
ConvertFunction ( &data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
+ if (false == zero_is_terminator)
+ utf8_data_end_ptr = utf8_data_ptr;
utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
}
else
{
// just copy the pointers - the cast is necessary to make the compiler happy
// but this should only happen if we are reading UTF8 data
- utf8_data_ptr = (UTF8*)data_ptr;
- utf8_data_end_ptr = (UTF8*)data_end_ptr;
+ utf8_data_ptr = const_cast<UTF8 *>(reinterpret_cast<const UTF8*>(data_ptr));
+ utf8_data_end_ptr = const_cast<UTF8 *>(reinterpret_cast<const UTF8*>(data_end_ptr));
+ }
+
+ const bool escape_non_printables = dump_options.GetEscapeNonPrintables();
+ lldb_private::formatters::StringPrinter::EscapingHelper escaping_callback;
+ if (escape_non_printables)
+ {
+ if (Language *language = Language::FindPlugin(dump_options.GetLanguage()))
+ escaping_callback = language->GetStringPrinterEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::UTF8);
+ else
+ escaping_callback = lldb_private::formatters::StringPrinter::GetDefaultEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::UTF8);
}
// since we tend to accept partial data (and even partially malformed data)
@@ -394,13 +343,13 @@ DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType
// hence we need to take a slower route and ensure we stay within boundaries
for (;utf8_data_ptr < utf8_data_end_ptr;)
{
- if (!*utf8_data_ptr)
+ if (zero_is_terminator && !*utf8_data_ptr)
break;
- if (escapeNonPrintables)
+ if (escape_non_printables)
{
uint8_t* next_data = nullptr;
- auto printable = GetPrintable(StringElementType::UTF8, utf8_data_ptr, utf8_data_end_ptr, next_data);
+ auto printable = escaping_callback(utf8_data_ptr, utf8_data_end_ptr, next_data);
auto printable_bytes = printable.GetBytes();
auto printable_size = printable.GetSize();
if (!printable_bytes || !next_data)
@@ -421,23 +370,39 @@ DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType
}
}
}
- if (quote != 0)
- stream.Printf("%c",quote);
+ if (dump_options.GetQuote() != 0)
+ stream.Printf("%c",dump_options.GetQuote());
+ if (dump_options.GetSuffixToken() != 0)
+ stream.Printf("%s",dump_options.GetSuffixToken());
+ if (dump_options.GetIsTruncated())
+ stream.Printf("...");
return true;
}
-lldb_private::formatters::ReadStringAndDumpToStreamOptions::ReadStringAndDumpToStreamOptions (ValueObject& valobj) :
+lldb_private::formatters::StringPrinter::ReadStringAndDumpToStreamOptions::ReadStringAndDumpToStreamOptions (ValueObject& valobj) :
ReadStringAndDumpToStreamOptions()
{
SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables());
}
-lldb_private::formatters::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (ValueObject& valobj) :
+lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (ValueObject& valobj) :
ReadBufferAndDumpToStreamOptions()
{
SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables());
}
+lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (const ReadStringAndDumpToStreamOptions& options) :
+ ReadBufferAndDumpToStreamOptions()
+{
+ SetStream(options.GetStream());
+ SetPrefixToken(options.GetPrefixToken());
+ SetSuffixToken(options.GetSuffixToken());
+ SetQuote(options.GetQuote());
+ SetEscapeNonPrintables(options.GetEscapeNonPrintables());
+ SetBinaryZeroIsTerminator(options.GetBinaryZeroIsTerminator());
+ SetLanguage(options.GetLanguage());
+}
+
namespace lldb_private
{
@@ -447,7 +412,7 @@ namespace formatters
template <>
bool
-ReadStringAndDumpToStream<StringElementType::ASCII> (ReadStringAndDumpToStreamOptions options)
+StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII> (const ReadStringAndDumpToStreamOptions& options)
{
assert(options.GetStream() && "need a Stream to print the string to");
Error my_error;
@@ -458,11 +423,20 @@ ReadStringAndDumpToStream<StringElementType::ASCII> (ReadStringAndDumpToStreamOp
return false;
size_t size;
+ const auto max_size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
+ bool is_truncated = false;
if (options.GetSourceSize() == 0)
- size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
+ size = max_size;
else if (!options.GetIgnoreMaxLength())
- size = std::min(options.GetSourceSize(),process_sp->GetTarget().GetMaximumSizeOfStringSummary());
+ {
+ size = options.GetSourceSize();
+ if (size > max_size)
+ {
+ size = max_size;
+ is_truncated = true;
+ }
+ }
else
size = options.GetSourceSize();
@@ -473,25 +447,35 @@ ReadStringAndDumpToStream<StringElementType::ASCII> (ReadStringAndDumpToStreamOp
if (my_error.Fail())
return false;
- char prefix_token = options.GetPrefixToken();
+ const char* prefix_token = options.GetPrefixToken();
char quote = options.GetQuote();
if (prefix_token != 0)
- options.GetStream()->Printf("%c%c",prefix_token,quote);
+ options.GetStream()->Printf("%s%c",prefix_token,quote);
else if (quote != 0)
options.GetStream()->Printf("%c",quote);
uint8_t* data_end = buffer_sp->GetBytes()+buffer_sp->GetByteSize();
+ const bool escape_non_printables = options.GetEscapeNonPrintables();
+ lldb_private::formatters::StringPrinter::EscapingHelper escaping_callback;
+ if (escape_non_printables)
+ {
+ if (Language *language = Language::FindPlugin(options.GetLanguage()))
+ escaping_callback = language->GetStringPrinterEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::ASCII);
+ else
+ escaping_callback = lldb_private::formatters::StringPrinter::GetDefaultEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::ASCII);
+ }
+
// since we tend to accept partial data (and even partially malformed data)
// we might end up with no NULL terminator before the end_ptr
// hence we need to take a slower route and ensure we stay within boundaries
for (uint8_t* data = buffer_sp->GetBytes(); *data && (data < data_end);)
{
- if (options.GetEscapeNonPrintables())
+ if (escape_non_printables)
{
uint8_t* next_data = nullptr;
- auto printable = GetPrintable(StringElementType::ASCII, data, data_end, next_data);
+ auto printable = escaping_callback(data, data_end, next_data);
auto printable_bytes = printable.GetBytes();
auto printable_size = printable.GetSize();
if (!printable_bytes || !next_data)
@@ -511,16 +495,23 @@ ReadStringAndDumpToStream<StringElementType::ASCII> (ReadStringAndDumpToStreamOp
data++;
}
}
-
- if (quote != 0)
+
+ const char* suffix_token = options.GetSuffixToken();
+
+ if (suffix_token != 0)
+ options.GetStream()->Printf("%c%s",quote, suffix_token);
+ else if (quote != 0)
options.GetStream()->Printf("%c",quote);
+ if (is_truncated)
+ options.GetStream()->Printf("...");
+
return true;
}
template<typename SourceDataType>
static bool
-ReadUTFBufferAndDumpToStream (const ReadStringAndDumpToStreamOptions& options,
+ReadUTFBufferAndDumpToStream (const StringPrinter::ReadStringAndDumpToStreamOptions& options,
ConversionResult (*ConvertFunction) (const SourceDataType**,
const SourceDataType*,
UTF8**,
@@ -550,14 +541,23 @@ ReadUTFBufferAndDumpToStream (const ReadStringAndDumpToStreamOptions& options,
uint32_t sourceSize = options.GetSourceSize();
bool needs_zero_terminator = options.GetNeedsZeroTermination();
+
+ bool is_truncated = false;
+ const auto max_size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
if (!sourceSize)
{
- sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
+ sourceSize = max_size;
needs_zero_terminator = true;
}
else if (!options.GetIgnoreMaxLength())
- sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
+ {
+ if (sourceSize > max_size)
+ {
+ sourceSize = max_size;
+ is_truncated = true;
+ }
+ }
const int bufferSPSize = sourceSize * type_width;
@@ -581,13 +581,18 @@ ReadUTFBufferAndDumpToStream (const ReadStringAndDumpToStreamOptions& options,
}
DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
+
+ StringPrinter::ReadBufferAndDumpToStreamOptions dump_options(options);
+ dump_options.SetData(data);
+ dump_options.SetSourceSize(sourceSize);
+ dump_options.SetIsTruncated(is_truncated);
- return DumpUTFBufferToStream(ConvertFunction, data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize, options.GetEscapeNonPrintables());
+ return DumpUTFBufferToStream(ConvertFunction, dump_options);
}
template <>
bool
-ReadStringAndDumpToStream<StringElementType::UTF8> (ReadStringAndDumpToStreamOptions options)
+StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8> (const ReadStringAndDumpToStreamOptions& options)
{
return ReadUTFBufferAndDumpToStream<UTF8>(options,
nullptr);
@@ -595,7 +600,7 @@ ReadStringAndDumpToStream<StringElementType::UTF8> (ReadStringAndDumpToStreamOpt
template <>
bool
-ReadStringAndDumpToStream<StringElementType::UTF16> (ReadStringAndDumpToStreamOptions options)
+StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16> (const ReadStringAndDumpToStreamOptions& options)
{
return ReadUTFBufferAndDumpToStream<UTF16>(options,
ConvertUTF16toUTF8);
@@ -603,7 +608,7 @@ ReadStringAndDumpToStream<StringElementType::UTF16> (ReadStringAndDumpToStreamOp
template <>
bool
-ReadStringAndDumpToStream<StringElementType::UTF32> (ReadStringAndDumpToStreamOptions options)
+StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32> (const ReadStringAndDumpToStreamOptions& options)
{
return ReadUTFBufferAndDumpToStream<UTF32>(options,
ConvertUTF32toUTF8);
@@ -611,16 +616,16 @@ ReadStringAndDumpToStream<StringElementType::UTF32> (ReadStringAndDumpToStreamOp
template <>
bool
-ReadBufferAndDumpToStream<StringElementType::UTF8> (ReadBufferAndDumpToStreamOptions options)
+StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF8> (const ReadBufferAndDumpToStreamOptions& options)
{
assert(options.GetStream() && "need a Stream to print the string to");
- return DumpUTFBufferToStream<UTF8>(nullptr, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables());
+ return DumpUTFBufferToStream<UTF8>(nullptr, options);
}
template <>
bool
-ReadBufferAndDumpToStream<StringElementType::ASCII> (ReadBufferAndDumpToStreamOptions options)
+StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::ASCII> (const ReadBufferAndDumpToStreamOptions& options)
{
// treat ASCII the same as UTF8
// FIXME: can we optimize ASCII some more?
@@ -629,20 +634,20 @@ ReadBufferAndDumpToStream<StringElementType::ASCII> (ReadBufferAndDumpToStreamOp
template <>
bool
-ReadBufferAndDumpToStream<StringElementType::UTF16> (ReadBufferAndDumpToStreamOptions options)
+StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF16> (const ReadBufferAndDumpToStreamOptions& options)
{
assert(options.GetStream() && "need a Stream to print the string to");
- return DumpUTFBufferToStream(ConvertUTF16toUTF8, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables());
+ return DumpUTFBufferToStream(ConvertUTF16toUTF8, options);
}
template <>
bool
-ReadBufferAndDumpToStream<StringElementType::UTF32> (ReadBufferAndDumpToStreamOptions options)
+StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF32> (const ReadBufferAndDumpToStreamOptions& options)
{
assert(options.GetStream() && "need a Stream to print the string to");
- return DumpUTFBufferToStream(ConvertUTF32toUTF8, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables());
+ return DumpUTFBufferToStream(ConvertUTF32toUTF8, options);
}
} // namespace formatters
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/TypeCategory.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/TypeCategory.cpp
index b05cea5..636d935 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/TypeCategory.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/TypeCategory.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/DataFormatters/TypeCategory.h"
+#include "lldb/Target/Language.h"
// C Includes
// C++ Includes
@@ -18,7 +19,8 @@ using namespace lldb;
using namespace lldb_private;
TypeCategoryImpl::TypeCategoryImpl(IFormatChangeListener* clist,
- ConstString name) :
+ ConstString name,
+ std::initializer_list<lldb::LanguageType> langs) :
m_format_cont("format","regex-format",clist),
m_summary_cont("summary","regex-summary",clist),
m_filter_cont("filter","regex-filter",clist),
@@ -29,8 +31,118 @@ m_validator_cont("validator","regex-validator",clist),
m_enabled(false),
m_change_listener(clist),
m_mutex(Mutex::eMutexTypeRecursive),
-m_name(name)
-{}
+m_name(name),
+m_languages()
+{
+ for (const lldb::LanguageType lang : langs)
+ AddLanguage(lang);
+}
+
+static bool
+IsApplicable(lldb::LanguageType category_lang,
+ lldb::LanguageType valobj_lang)
+{
+ switch (category_lang)
+ {
+ // these are not languages that LLDB would ordinarily deal with
+ // only allow an exact equality here, since we really don't know
+ // any better
+ case eLanguageTypeAda83:
+ case eLanguageTypeCobol74:
+ case eLanguageTypeCobol85:
+ case eLanguageTypeFortran77:
+ case eLanguageTypeFortran90:
+ case eLanguageTypePascal83:
+ case eLanguageTypeModula2:
+ case eLanguageTypeJava:
+ case eLanguageTypeAda95:
+ case eLanguageTypeFortran95:
+ case eLanguageTypePLI:
+ case eLanguageTypeUPC:
+ case eLanguageTypeD:
+ case eLanguageTypePython:
+ return category_lang == valobj_lang;
+
+ // the C family, we consider it as one
+ case eLanguageTypeC89:
+ case eLanguageTypeC:
+ case eLanguageTypeC99:
+ return valobj_lang == eLanguageTypeC89 ||
+ valobj_lang == eLanguageTypeC ||
+ valobj_lang == eLanguageTypeC99;
+
+ // ObjC knows about C and itself
+ case eLanguageTypeObjC:
+ return valobj_lang == eLanguageTypeC89 ||
+ valobj_lang == eLanguageTypeC ||
+ valobj_lang == eLanguageTypeC99 ||
+ valobj_lang == eLanguageTypeObjC;
+
+ // C++ knows about C and C++
+ case eLanguageTypeC_plus_plus:
+ return valobj_lang == eLanguageTypeC89 ||
+ valobj_lang == eLanguageTypeC ||
+ valobj_lang == eLanguageTypeC99 ||
+ valobj_lang == eLanguageTypeC_plus_plus;
+
+ // ObjC++ knows about C,C++,ObjC and ObjC++
+ case eLanguageTypeObjC_plus_plus:
+ return valobj_lang == eLanguageTypeC89 ||
+ valobj_lang == eLanguageTypeC ||
+ valobj_lang == eLanguageTypeC99 ||
+ valobj_lang == eLanguageTypeC_plus_plus ||
+ valobj_lang == eLanguageTypeObjC;
+
+ default:
+ case eLanguageTypeUnknown:
+ return true;
+ }
+}
+
+bool
+TypeCategoryImpl::IsApplicable (ValueObject& valobj)
+{
+ lldb::LanguageType valobj_lang = valobj.GetObjectRuntimeLanguage();
+ for (size_t idx = 0;
+ idx < GetNumLanguages();
+ idx++)
+ {
+ const lldb::LanguageType category_lang = GetLanguageAtIndex(idx);
+ if (::IsApplicable(category_lang,valobj_lang))
+ return true;
+ }
+ return false;
+}
+
+size_t
+TypeCategoryImpl::GetNumLanguages ()
+{
+ if (m_languages.empty())
+ return 1;
+ return m_languages.size();
+}
+
+lldb::LanguageType
+TypeCategoryImpl::GetLanguageAtIndex (size_t idx)
+{
+ if (m_languages.empty())
+ return lldb::eLanguageTypeUnknown;
+ return m_languages[idx];
+}
+
+void
+TypeCategoryImpl::AddLanguage (lldb::LanguageType lang)
+{
+ m_languages.push_back(lang);
+}
+
+bool
+TypeCategoryImpl::HasLanguage (lldb::LanguageType lang)
+{
+ const auto iter = std::find(m_languages.begin(), m_languages.end(), lang),
+ end = m_languages.end();
+ return (iter != end);
+}
bool
TypeCategoryImpl::Get (ValueObject& valobj,
@@ -38,7 +150,7 @@ TypeCategoryImpl::Get (ValueObject& valobj,
lldb::TypeFormatImplSP& entry,
uint32_t* reason)
{
- if (!IsEnabled())
+ if (!IsEnabled() || !IsApplicable(valobj))
return false;
if (GetTypeFormatsContainer()->Get(candidates, entry, reason))
return true;
@@ -54,7 +166,7 @@ TypeCategoryImpl::Get (ValueObject& valobj,
lldb::TypeSummaryImplSP& entry,
uint32_t* reason)
{
- if (!IsEnabled())
+ if (!IsEnabled() || !IsApplicable(valobj))
return false;
if (GetTypeSummariesContainer()->Get(candidates, entry, reason))
return true;
@@ -70,7 +182,7 @@ TypeCategoryImpl::Get (ValueObject& valobj,
lldb::SyntheticChildrenSP& entry,
uint32_t* reason)
{
- if (!IsEnabled())
+ if (!IsEnabled() || !IsApplicable(valobj))
return false;
TypeFilterImpl::SharedPointer filter_sp;
uint32_t reason_filter = 0;
@@ -567,3 +679,30 @@ TypeCategoryImpl::Enable (bool value, uint32_t position)
if (m_change_listener)
m_change_listener->Changed();
}
+
+std::string
+TypeCategoryImpl::GetDescription ()
+{
+ StreamString stream;
+ stream.Printf("%s (%s",
+ GetName(),
+ (IsEnabled() ? "enabled" : "disabled"));
+ StreamString lang_stream;
+ lang_stream.Printf(", applicable for language(s): ");
+ bool print_lang = false;
+ for (size_t idx = 0;
+ idx < GetNumLanguages();
+ idx++)
+ {
+ const lldb::LanguageType lang = GetLanguageAtIndex(idx);
+ if (lang != lldb::eLanguageTypeUnknown)
+ print_lang = true;
+ lang_stream.Printf("%s%s",
+ Language::GetNameForLanguageType(lang),
+ idx+1<GetNumLanguages() ? ", " : "");
+ }
+ if (print_lang)
+ stream.Printf("%s",lang_stream.GetData());
+ stream.PutChar(')');
+ return stream.GetData();
+}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/TypeCategoryMap.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/TypeCategoryMap.cpp
index 96b9e6d..58e4e21 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/TypeCategoryMap.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/TypeCategoryMap.cpp
@@ -9,8 +9,8 @@
#include "lldb/DataFormatters/TypeCategoryMap.h"
+#include "lldb/Core/Log.h"
#include "lldb/DataFormatters/FormatClasses.h"
-#include "lldb/DataFormatters/FormatManager.h"
// C Includes
// C++ Includes
@@ -218,25 +218,35 @@ TypeCategoryMap::AnyMatches (ConstString type_name,
}
lldb::TypeFormatImplSP
-TypeCategoryMap::GetFormat (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+TypeCategoryMap::GetFormat (FormattersMatchData& match_data)
{
Mutex::Locker locker(m_map_mutex);
uint32_t reason_why;
ActiveCategoriesIterator begin, end = m_active_categories.end();
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
-
- FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
+ if (log)
+ {
+ for (auto match : match_data.GetMatchesVector())
+ {
+ log->Printf("[CategoryMap::GetSummaryFormat] candidate match = %s %s %s %s reason = %" PRIu32,
+ match.GetTypeName().GetCString(),
+ match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
+ match.DidStripReference() ? "strip-reference" : "no-strip-reference",
+ match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
+ match.GetReason());
+ }
+ }
+
for (begin = m_active_categories.begin(); begin != end; begin++)
{
lldb::TypeCategoryImplSP category_sp = *begin;
lldb::TypeFormatImplSP current_format;
if (log)
- log->Printf("\n[TypeCategoryMap::GetFormat] Trying to use category %s", category_sp->GetName());
- if (!category_sp->Get(valobj, matches, current_format, &reason_why))
+ log->Printf("[TypeCategoryMap::GetFormat] Trying to use category %s", category_sp->GetName());
+ if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why))
continue;
return current_format;
}
@@ -246,25 +256,35 @@ TypeCategoryMap::GetFormat (ValueObject& valobj,
}
lldb::TypeSummaryImplSP
-TypeCategoryMap::GetSummaryFormat (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+TypeCategoryMap::GetSummaryFormat (FormattersMatchData& match_data)
{
Mutex::Locker locker(m_map_mutex);
uint32_t reason_why;
ActiveCategoriesIterator begin, end = m_active_categories.end();
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
-
- FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
+ if (log)
+ {
+ for (auto match : match_data.GetMatchesVector())
+ {
+ log->Printf("[CategoryMap::GetSummaryFormat] candidate match = %s %s %s %s reason = %" PRIu32,
+ match.GetTypeName().GetCString(),
+ match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
+ match.DidStripReference() ? "strip-reference" : "no-strip-reference",
+ match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
+ match.GetReason());
+ }
+ }
+
for (begin = m_active_categories.begin(); begin != end; begin++)
{
lldb::TypeCategoryImplSP category_sp = *begin;
lldb::TypeSummaryImplSP current_format;
if (log)
- log->Printf("\n[CategoryMap::GetSummaryFormat] Trying to use category %s", category_sp->GetName());
- if (!category_sp->Get(valobj, matches, current_format, &reason_why))
+ log->Printf("[CategoryMap::GetSummaryFormat] Trying to use category %s", category_sp->GetName());
+ if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why))
continue;
return current_format;
}
@@ -275,8 +295,7 @@ TypeCategoryMap::GetSummaryFormat (ValueObject& valobj,
#ifndef LLDB_DISABLE_PYTHON
lldb::SyntheticChildrenSP
-TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+TypeCategoryMap::GetSyntheticChildren (FormattersMatchData& match_data)
{
Mutex::Locker locker(m_map_mutex);
@@ -284,17 +303,28 @@ TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj,
ActiveCategoriesIterator begin, end = m_active_categories.end();
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
-
- FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
+ if (log)
+ {
+ for (auto match : match_data.GetMatchesVector())
+ {
+ log->Printf("[CategoryMap::GetSummaryFormat] candidate match = %s %s %s %s reason = %" PRIu32,
+ match.GetTypeName().GetCString(),
+ match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
+ match.DidStripReference() ? "strip-reference" : "no-strip-reference",
+ match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
+ match.GetReason());
+ }
+ }
+
for (begin = m_active_categories.begin(); begin != end; begin++)
{
lldb::TypeCategoryImplSP category_sp = *begin;
lldb::SyntheticChildrenSP current_format;
if (log)
- log->Printf("\n[CategoryMap::GetSyntheticChildren] Trying to use category %s", category_sp->GetName());
- if (!category_sp->Get(valobj, matches, current_format, &reason_why))
+ log->Printf("[CategoryMap::GetSyntheticChildren] Trying to use category %s", category_sp->GetName());
+ if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why))
continue;
return current_format;
}
@@ -305,25 +335,35 @@ TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj,
#endif
lldb::TypeValidatorImplSP
-TypeCategoryMap::GetValidator (ValueObject& valobj,
- lldb::DynamicValueType use_dynamic)
+TypeCategoryMap::GetValidator (FormattersMatchData& match_data)
{
Mutex::Locker locker(m_map_mutex);
uint32_t reason_why;
ActiveCategoriesIterator begin, end = m_active_categories.end();
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
-
- FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
+ if (log)
+ {
+ for (auto match : match_data.GetMatchesVector())
+ {
+ log->Printf("[CategoryMap::GetValidator] candidate match = %s %s %s %s reason = %" PRIu32,
+ match.GetTypeName().GetCString(),
+ match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
+ match.DidStripReference() ? "strip-reference" : "no-strip-reference",
+ match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
+ match.GetReason());
+ }
+ }
+
for (begin = m_active_categories.begin(); begin != end; begin++)
{
lldb::TypeCategoryImplSP category_sp = *begin;
lldb::TypeValidatorImplSP current_format;
if (log)
- log->Printf("\n[CategoryMap::GetValidator] Trying to use category %s", category_sp->GetName());
- if (!category_sp->Get(valobj, matches, current_format, &reason_why))
+ log->Printf("[CategoryMap::GetValidator] Trying to use category %s", category_sp->GetName());
+ if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why))
continue;
return current_format;
}
@@ -333,7 +373,7 @@ TypeCategoryMap::GetValidator (ValueObject& valobj,
}
void
-TypeCategoryMap::LoopThrough(CallbackType callback, void* param)
+TypeCategoryMap::ForEach(ForEachCallback callback)
{
if (callback)
{
@@ -345,8 +385,7 @@ TypeCategoryMap::LoopThrough(CallbackType callback, void* param)
for (begin = m_active_categories.begin(); begin != end; begin++)
{
lldb::TypeCategoryImplSP category = *begin;
- ConstString type = ConstString(category->GetName());
- if (!callback(param, category))
+ if (!callback(category))
break;
}
}
@@ -359,7 +398,7 @@ TypeCategoryMap::LoopThrough(CallbackType callback, void* param)
if (pos->second->IsEnabled())
continue;
KeyType type = pos->first;
- if (!callback(param, pos->second))
+ if (!callback(pos->second))
break;
}
}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/TypeFormat.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/TypeFormat.cpp
index c4a65fe..6ab8d29 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/TypeFormat.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/TypeFormat.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/DataFormatters/TypeFormat.h"
+
// C Includes
// C++ Includes
@@ -17,15 +19,11 @@
#include "lldb/lldb-public.h"
#include "lldb/lldb-enumerations.h"
-#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Core/Timer.h"
#include "lldb/DataFormatters/FormatManager.h"
-#include "lldb/DataFormatters/TypeFormat.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/TypeList.h"
-#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
using namespace lldb;
@@ -91,13 +89,13 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
}
else
{
- ClangASTType clang_type = value.GetClangType ();
- if (clang_type)
+ CompilerType compiler_type = value.GetCompilerType ();
+ if (compiler_type)
{
// put custom bytes to display in the DataExtractor to override the default value logic
if (GetFormat() == eFormatCString)
{
- lldb_private::Flags type_flags(clang_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags
+ lldb_private::Flags type_flags(compiler_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags
if (type_flags.Test(eTypeIsPointer) && !type_flags.Test(eTypeIsObjC))
{
// if we are dumping a pointer as a c-string, get the pointee data as a string
@@ -122,7 +120,7 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
}
StreamString sstr;
- clang_type.DumpTypeValue (&sstr, // The stream to use for display
+ compiler_type.DumpTypeValue (&sstr, // The stream to use for display
GetFormat(), // Format to display this type with
data, // Data to extract from
0, // Byte offset into "m_data"
@@ -134,7 +132,7 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
// for a formatting error (or else we wouldn't be able to reformat
// until a next update), an empty string is treated as a "false"
// return from here, but that's about as severe as we get
- // ClangASTType::DumpTypeValue() should always return
+ // CompilerType::DumpTypeValue() should always return
// something, even if that something is an error message
if (sstr.GetString().empty())
dest.clear();
@@ -192,7 +190,7 @@ TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj,
return false;
auto iter = m_types.find(valobj_key),
end = m_types.end();
- ClangASTType valobj_enum_type;
+ CompilerType valobj_enum_type;
if (iter == end)
{
// probably a redundant check
@@ -208,9 +206,9 @@ TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj,
{
if (!type_sp)
continue;
- if ( (type_sp->GetClangForwardType().GetTypeInfo() & eTypeIsEnumeration) == eTypeIsEnumeration)
+ if ( (type_sp->GetForwardCompilerType().GetTypeInfo() & eTypeIsEnumeration) == eTypeIsEnumeration)
{
- valobj_enum_type = type_sp->GetClangFullType();
+ valobj_enum_type = type_sp->GetFullCompilerType ();
m_types.emplace(valobj_key,valobj_enum_type);
break;
}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/TypeSummary.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/TypeSummary.cpp
index fa06f29..2806ba2 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/TypeSummary.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/TypeSummary.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/DataFormatters/TypeSummary.h"
+
// C Includes
// C++ Includes
@@ -19,16 +21,13 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Core/Timer.h"
-#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
-#include "lldb/Host/Host.h"
-
using namespace lldb;
using namespace lldb_private;
@@ -76,15 +75,17 @@ TypeSummaryOptions::SetCapping (lldb::TypeSummaryCapping cap)
return *this;
}
-TypeSummaryImpl::TypeSummaryImpl (const TypeSummaryImpl::Flags& flags) :
-m_flags(flags)
+TypeSummaryImpl::TypeSummaryImpl (Kind kind,
+ const TypeSummaryImpl::Flags& flags) :
+ m_flags(flags),
+ m_kind(kind)
{
}
StringSummaryFormat::StringSummaryFormat (const TypeSummaryImpl::Flags& flags,
const char *format_cstr) :
- TypeSummaryImpl(flags),
+ TypeSummaryImpl(Kind::eSummaryString,flags),
m_format_str()
{
SetSummaryString (format_cstr);
@@ -170,7 +171,7 @@ StringSummaryFormat::GetDescription ()
CXXFunctionSummaryFormat::CXXFunctionSummaryFormat (const TypeSummaryImpl::Flags& flags,
Callback impl,
const char* description) :
-TypeSummaryImpl(flags),
+ TypeSummaryImpl(Kind::eCallback,flags),
m_impl(impl),
m_description(description ? description : "")
{
@@ -193,28 +194,25 @@ std::string
CXXFunctionSummaryFormat::GetDescription ()
{
StreamString sstr;
- sstr.Printf ("`%s (%p) `%s%s%s%s%s%s%s", m_description.c_str(),
- static_cast<void*>(&m_impl),
+ sstr.Printf ("%s%s%s%s%s%s%s %s",
Cascades() ? "" : " (not cascading)",
!DoesPrintChildren(nullptr) ? "" : " (show children)",
!DoesPrintValue(nullptr) ? " (hide value)" : "",
IsOneLiner() ? " (one-line printout)" : "",
SkipsPointers() ? " (skip pointers)" : "",
SkipsReferences() ? " (skip references)" : "",
- HideNames(nullptr) ? " (hide member names)" : "");
+ HideNames(nullptr) ? " (hide member names)" : "",
+ m_description.c_str());
return sstr.GetString();
}
-#ifndef LLDB_DISABLE_PYTHON
-
-
ScriptSummaryFormat::ScriptSummaryFormat (const TypeSummaryImpl::Flags& flags,
const char * function_name,
const char * python_script) :
-TypeSummaryImpl(flags),
-m_function_name(),
-m_python_script(),
-m_script_function_sp()
+ TypeSummaryImpl(Kind::eScript,flags),
+ m_function_name(),
+ m_python_script(),
+ m_script_function_sp()
{
if (function_name)
m_function_name.assign(function_name);
@@ -227,15 +225,9 @@ ScriptSummaryFormat::FormatObject (ValueObject *valobj,
std::string& retval,
const TypeSummaryOptions& options)
{
- Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
-
if (!valobj)
return false;
- Host::SetCrashDescriptionWithFormat("[Python summary] Name: %s - Function: %s",
- valobj->GetName().AsCString("unknown"),
- m_function_name.c_str());
-
TargetSP target_sp(valobj->GetTargetSP());
if (!target_sp)
@@ -275,5 +267,3 @@ ScriptSummaryFormat::GetDescription ()
return sstr.GetString();
}
-
-#endif // #ifndef LLDB_DISABLE_PYTHON
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/TypeSynthetic.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/TypeSynthetic.cpp
index 5bd8d30..e49cd99 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/TypeSynthetic.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/TypeSynthetic.cpp
@@ -22,8 +22,7 @@
#include "lldb/DataFormatters/TypeSynthetic.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Symbol/ClangASTType.h"
-#include "lldb/Target/StackFrame.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Target.h"
using namespace lldb;
@@ -111,11 +110,10 @@ std::string
CXXSyntheticChildren::GetDescription()
{
StreamString sstr;
- sstr.Printf("%s%s%s Generator at %p - %s",
+ sstr.Printf("%s%s%s %s",
Cascades() ? "" : " (not cascading)",
SkipsPointers() ? " (skip pointers)" : "",
SkipsReferences() ? " (skip references)" : "",
- reinterpret_cast<void*>(reinterpret_cast<intptr_t>(m_create_callback)),
m_description.c_str());
return sstr.GetString();
@@ -136,7 +134,7 @@ lldb::ValueObjectSP
SyntheticChildrenFrontEnd::CreateValueObjectFromAddress (const char* name,
uint64_t address,
const ExecutionContext& exe_ctx,
- ClangASTType type)
+ CompilerType type)
{
ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, type));
if (valobj_sp)
@@ -148,7 +146,7 @@ lldb::ValueObjectSP
SyntheticChildrenFrontEnd::CreateValueObjectFromData (const char* name,
const DataExtractor& data,
const ExecutionContext& exe_ctx,
- ClangASTType type)
+ CompilerType type)
{
ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromData(name, data, exe_ctx, type));
if (valobj_sp)
@@ -202,7 +200,15 @@ ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren ()
{
if (!m_wrapper_sp || m_interpreter == NULL)
return 0;
- return m_interpreter->CalculateNumChildren(m_wrapper_sp);
+ return m_interpreter->CalculateNumChildren(m_wrapper_sp, UINT32_MAX);
+}
+
+size_t
+ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren (uint32_t max)
+{
+ if (!m_wrapper_sp || m_interpreter == NULL)
+ return 0;
+ return m_interpreter->CalculateNumChildren(m_wrapper_sp, max);
}
bool
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index 7c794ee..04c2912 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -13,33 +13,28 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
-DumpValueObjectOptions::DumpValueObjectOptions (ValueObject& valobj) :
-DumpValueObjectOptions()
-{
- m_use_dynamic = valobj.GetDynamicValueType();
- m_use_synthetic = valobj.IsSynthetic();
-}
-
ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
Stream* s)
{
if (valobj)
{
DumpValueObjectOptions options(*valobj);
- Init (valobj,s,options,options.m_max_ptr_depth,0);
+ Init (valobj,s,options,m_options.m_max_ptr_depth,0, nullptr);
}
else
{
DumpValueObjectOptions options;
- Init (valobj,s,options,options.m_max_ptr_depth,0);
+ Init (valobj,s,options,m_options.m_max_ptr_depth,0, nullptr);
}
}
@@ -47,42 +42,48 @@ ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
Stream* s,
const DumpValueObjectOptions& options)
{
- Init(valobj,s,options,options.m_max_ptr_depth,0);
+ Init(valobj,s,options,m_options.m_max_ptr_depth,0, nullptr);
}
ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
Stream* s,
const DumpValueObjectOptions& options,
- uint32_t ptr_depth,
- uint32_t curr_depth)
+ const DumpValueObjectOptions::PointerDepth& ptr_depth,
+ uint32_t curr_depth,
+ InstancePointersSetSP printed_instance_pointers)
{
- Init(valobj,s,options,ptr_depth,curr_depth);
+ Init(valobj,s,options,ptr_depth,curr_depth, printed_instance_pointers);
}
void
ValueObjectPrinter::Init (ValueObject* valobj,
Stream* s,
const DumpValueObjectOptions& options,
- uint32_t ptr_depth,
- uint32_t curr_depth)
+ const DumpValueObjectOptions::PointerDepth& ptr_depth,
+ uint32_t curr_depth,
+ InstancePointersSetSP printed_instance_pointers)
{
m_orig_valobj = valobj;
m_valobj = nullptr;
m_stream = s;
- this->options = options;
+ m_options = options;
m_ptr_depth = ptr_depth;
m_curr_depth = curr_depth;
assert (m_orig_valobj && "cannot print a NULL ValueObject");
assert (m_stream && "cannot print to a NULL Stream");
m_should_print = eLazyBoolCalculate;
m_is_nil = eLazyBoolCalculate;
+ m_is_uninit = eLazyBoolCalculate;
m_is_ptr = eLazyBoolCalculate;
m_is_ref = eLazyBoolCalculate;
m_is_aggregate = eLazyBoolCalculate;
+ m_is_instance_ptr = eLazyBoolCalculate;
m_summary_formatter = {nullptr,false};
m_value.assign("");
m_summary.assign("");
m_error.assign("");
+ m_val_summary_ok = false;
+ m_printed_instance_pointers = printed_instance_pointers ? printed_instance_pointers : InstancePointersSetSP(new InstancePointersSet());
}
bool
@@ -98,17 +99,15 @@ ValueObjectPrinter::PrintValueObject ()
PrintLocationIfNeeded();
m_stream->Indent();
- bool show_type = PrintTypeIfNeeded();
-
- PrintNameIfNeeded(show_type);
+ PrintDecl();
}
bool value_printed = false;
bool summary_printed = false;
- bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed);
+ m_val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed);
- if (val_summary_ok)
+ if (m_val_summary_ok)
PrintChildrenIfNeeded (value_printed, summary_printed);
else
m_stream->EOL();
@@ -132,7 +131,7 @@ ValueObjectPrinter::GetMostSpecializedValue ()
{
if (m_orig_valobj->IsDynamic())
{
- if (options.m_use_dynamic == eNoDynamicValues)
+ if (m_options.m_use_dynamic == eNoDynamicValues)
{
ValueObject *static_value = m_orig_valobj->GetStaticValue().get();
if (static_value)
@@ -145,9 +144,9 @@ ValueObjectPrinter::GetMostSpecializedValue ()
}
else
{
- if (options.m_use_dynamic != eNoDynamicValues)
+ if (m_options.m_use_dynamic != eNoDynamicValues)
{
- ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(options.m_use_dynamic).get();
+ ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(m_options.m_use_dynamic).get();
if (dynamic_value)
m_valobj = dynamic_value;
else
@@ -159,7 +158,7 @@ ValueObjectPrinter::GetMostSpecializedValue ()
if (m_valobj->IsSynthetic())
{
- if (options.m_use_synthetic == false)
+ if (m_options.m_use_synthetic == false)
{
ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get();
if (non_synthetic)
@@ -168,7 +167,7 @@ ValueObjectPrinter::GetMostSpecializedValue ()
}
else
{
- if (options.m_use_synthetic == true)
+ if (m_options.m_use_synthetic == true)
{
ValueObject *synthetic = m_valobj->GetSyntheticValue().get();
if (synthetic)
@@ -176,8 +175,8 @@ ValueObjectPrinter::GetMostSpecializedValue ()
}
}
}
- m_clang_type = m_valobj->GetClangType();
- m_type_flags = m_clang_type.GetTypeInfo ();
+ m_compiler_type = m_valobj->GetCompilerType();
+ m_type_flags = m_compiler_type.GetTypeInfo ();
return true;
}
@@ -195,9 +194,9 @@ ValueObjectPrinter::GetDescriptionForDisplay ()
const char*
ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail)
{
- const char *root_valobj_name = options.m_root_valobj_name.empty() ?
+ const char *root_valobj_name = m_options.m_root_valobj_name.empty() ?
m_valobj->GetName().AsCString() :
- options.m_root_valobj_name.c_str();
+ m_options.m_root_valobj_name.c_str();
return root_valobj_name ? root_valobj_name : if_fail;
}
@@ -205,7 +204,7 @@ bool
ValueObjectPrinter::ShouldPrintValueObject ()
{
if (m_should_print == eLazyBoolCalculate)
- m_should_print = (options.m_flat_output == false || m_type_flags.Test (eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo;
+ m_should_print = (m_options.m_flat_output == false || m_type_flags.Test (eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo;
return m_should_print == eLazyBoolYes;
}
@@ -213,11 +212,19 @@ bool
ValueObjectPrinter::IsNil ()
{
if (m_is_nil == eLazyBoolCalculate)
- m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo;
+ m_is_nil = m_valobj->IsNilReference() ? eLazyBoolYes : eLazyBoolNo;
return m_is_nil == eLazyBoolYes;
}
bool
+ValueObjectPrinter::IsUninitialized ()
+{
+ if (m_is_uninit == eLazyBoolCalculate)
+ m_is_uninit = m_valobj->IsUninitializedReference() ? eLazyBoolYes : eLazyBoolNo;
+ return m_is_uninit == eLazyBoolYes;
+}
+
+bool
ValueObjectPrinter::IsPtr ()
{
if (m_is_ptr == eLazyBoolCalculate)
@@ -242,9 +249,20 @@ ValueObjectPrinter::IsAggregate ()
}
bool
+ValueObjectPrinter::IsInstancePointer ()
+{
+ // you need to do this check on the value's clang type
+ if (m_is_instance_ptr == eLazyBoolCalculate)
+ m_is_instance_ptr = (m_valobj->GetValue().GetCompilerType().GetTypeInfo() & eTypeInstanceIsPointer) != 0 ? eLazyBoolYes : eLazyBoolNo;
+ if ((eLazyBoolYes == m_is_instance_ptr) && m_valobj->IsBaseClass())
+ m_is_instance_ptr = eLazyBoolNo;
+ return m_is_instance_ptr == eLazyBoolYes;
+}
+
+bool
ValueObjectPrinter::PrintLocationIfNeeded ()
{
- if (options.m_show_location)
+ if (m_options.m_show_location)
{
m_stream->Printf("%s: ", m_valobj->GetLocationAsCString());
return true;
@@ -252,88 +270,155 @@ ValueObjectPrinter::PrintLocationIfNeeded ()
return false;
}
-bool
-ValueObjectPrinter::PrintTypeIfNeeded ()
+void
+ValueObjectPrinter::PrintDecl ()
{
bool show_type = true;
// if we are at the root-level and been asked to hide the root's type, then hide it
- if (m_curr_depth == 0 && options.m_hide_root_type)
+ if (m_curr_depth == 0 && m_options.m_hide_root_type)
show_type = false;
else
// otherwise decide according to the usual rules (asked to show types - always at the root level)
- show_type = options.m_show_types || (m_curr_depth == 0 && !options.m_flat_output);
+ show_type = m_options.m_show_types || (m_curr_depth == 0 && !m_options.m_flat_output);
+
+ StreamString typeName;
+ // always show the type at the root level if it is invalid
if (show_type)
{
// Some ValueObjects don't have types (like registers sets). Only print
// the type if there is one to print
ConstString type_name;
- if (options.m_use_type_display_name)
- type_name = m_valobj->GetDisplayTypeName();
+ if (m_compiler_type.IsValid())
+ {
+ if (m_options.m_use_type_display_name)
+ type_name = m_valobj->GetDisplayTypeName();
+ else
+ type_name = m_valobj->GetQualifiedTypeName();
+ }
else
- type_name = m_valobj->GetQualifiedTypeName();
+ {
+ // only show an invalid type name if the user explicitly triggered show_type
+ if (m_options.m_show_types)
+ type_name = ConstString("<invalid type>");
+ else
+ type_name.Clear();
+ }
+
if (type_name)
- m_stream->Printf("(%s) ", type_name.GetCString());
- else
- show_type = false;
+ {
+ std::string type_name_str(type_name.GetCString());
+ if (m_options.m_hide_pointer_value)
+ {
+ for(auto iter = type_name_str.find(" *");
+ iter != std::string::npos;
+ iter = type_name_str.find(" *"))
+ {
+ type_name_str.erase(iter, 2);
+ }
+ }
+ typeName.Printf("%s", type_name_str.c_str());
+ }
}
- return show_type;
-}
-
-bool
-ValueObjectPrinter::PrintNameIfNeeded (bool show_type)
-{
- if (options.m_flat_output)
+
+ StreamString varName;
+
+ if (m_options.m_flat_output)
{
// If we are showing types, also qualify the C++ base classes
const bool qualify_cxx_base_classes = show_type;
- if (!options.m_hide_name)
+ if (!m_options.m_hide_name)
{
- m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes);
- m_stream->PutCString(" =");
- return true;
+ m_valobj->GetExpressionPath(varName, qualify_cxx_base_classes);
}
}
- else if (!options.m_hide_name)
+ else if (!m_options.m_hide_name)
{
const char *name_cstr = GetRootNameForDisplay("");
- m_stream->Printf ("%s =", name_cstr);
- return true;
+ varName.Printf ("%s", name_cstr);
+ }
+
+ bool decl_printed = false;
+ if (!m_options.m_decl_printing_helper)
+ {
+ // if the user didn't give us a custom helper, pick one based upon the language, either the one that this printer is bound to, or the preferred one for the ValueObject
+ lldb::LanguageType lang_type = (m_options.m_varformat_language == lldb::eLanguageTypeUnknown) ? m_valobj->GetPreferredDisplayLanguage() : m_options.m_varformat_language;
+ if (Language *lang_plugin = Language::FindPlugin(lang_type))
+ {
+ m_options.m_decl_printing_helper = lang_plugin->GetDeclPrintingHelper();
+ }
+ }
+
+ if (m_options.m_decl_printing_helper)
+ {
+ ConstString type_name_cstr(typeName.GetData());
+ ConstString var_name_cstr(varName.GetData());
+
+ StreamString dest_stream;
+ if (m_options.m_decl_printing_helper (type_name_cstr,
+ var_name_cstr,
+ m_options,
+ dest_stream))
+ {
+ decl_printed = true;
+ m_stream->Printf("%s", dest_stream.GetData());
+ }
+ }
+
+ // if the helper failed, or there is none, do a default thing
+ if (!decl_printed)
+ {
+ if (typeName.GetSize())
+ m_stream->Printf("(%s) ", typeName.GetData());
+ if (varName.GetSize())
+ m_stream->Printf("%s =", varName.GetData());
+ else if (!m_options.m_hide_name)
+ m_stream->Printf(" =");
}
- return false;
}
bool
ValueObjectPrinter::CheckScopeIfNeeded ()
{
- if (options.m_scope_already_checked)
+ if (m_options.m_scope_already_checked)
return true;
return m_valobj->IsInScope();
}
TypeSummaryImpl*
-ValueObjectPrinter::GetSummaryFormatter ()
+ValueObjectPrinter::GetSummaryFormatter (bool null_if_omitted)
{
if (m_summary_formatter.second == false)
{
- TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get();
+ TypeSummaryImpl* entry = m_options.m_summary_sp ? m_options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get();
- if (options.m_omit_summary_depth > 0)
+ if (m_options.m_omit_summary_depth > 0)
entry = NULL;
m_summary_formatter.first = entry;
m_summary_formatter.second = true;
}
+ if (m_options.m_omit_summary_depth > 0 && null_if_omitted)
+ return nullptr;
return m_summary_formatter.first;
}
+static bool
+IsPointerValue (const CompilerType &type)
+{
+ Flags type_flags(type.GetTypeInfo());
+ if (type_flags.AnySet(eTypeInstanceIsPointer | eTypeIsPointer))
+ return type_flags.AllClear(eTypeIsBuiltIn);
+ return false;
+}
+
void
ValueObjectPrinter::GetValueSummaryError (std::string& value,
std::string& summary,
std::string& error)
{
- if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat())
+ if (m_options.m_format != eFormatDefault && m_options.m_format != m_valobj->GetFormat())
{
- m_valobj->GetValueAsCString(options.m_format,
+ m_valobj->GetValueAsCString(m_options.m_format,
value);
}
else
@@ -350,14 +435,16 @@ ValueObjectPrinter::GetValueSummaryError (std::string& value,
{
if (IsNil())
summary.assign("nil");
- else if (options.m_omit_summary_depth == 0)
+ else if (IsUninitialized())
+ summary.assign("<uninitialized>");
+ else if (m_options.m_omit_summary_depth == 0)
{
TypeSummaryImpl* entry = GetSummaryFormatter();
if (entry)
- m_valobj->GetSummaryAsCString(entry, summary);
+ m_valobj->GetSummaryAsCString(entry, summary, m_options.m_varformat_language);
else
{
- const char* sum_cstr = m_valobj->GetSummaryAsCString();
+ const char* sum_cstr = m_valobj->GetSummaryAsCString(m_options.m_varformat_language);
if (sum_cstr)
summary.assign(sum_cstr);
}
@@ -380,6 +467,16 @@ ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed,
}
if (m_error.size())
{
+ // we need to support scenarios in which it is actually fine for a value to have no type
+ // but - on the other hand - if we get an error *AND* have no type, we try to get out
+ // gracefully, since most often that combination means "could not resolve a type"
+ // and the default failure mode is quite ugly
+ if (!m_compiler_type.IsValid())
+ {
+ m_stream->Printf(" <could not resolve type>");
+ return false;
+ }
+
error_printed = true;
m_stream->Printf (" <%s>\n", m_error.c_str());
}
@@ -390,10 +487,14 @@ ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed,
// the value if this thing is nil
// (but show the value if the user passes a format explicitly)
TypeSummaryImpl* entry = GetSummaryFormatter();
- if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value)
+ if (!IsNil() && !IsUninitialized() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || m_options.m_format != eFormatDefault) || m_summary.empty()) && !m_options.m_hide_value)
{
- m_stream->Printf(" %s", m_value.c_str());
- value_printed = true;
+ if (m_options.m_hide_pointer_value && IsPointerValue(m_valobj->GetCompilerType())) {}
+ else
+ {
+ m_stream->Printf(" %s", m_value.c_str());
+ value_printed = true;
+ }
}
if (m_summary.size())
@@ -413,9 +514,9 @@ ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed,
if (ShouldPrintValueObject())
{
// let's avoid the overly verbose no description error for a nil thing
- if (options.m_use_objc && !IsNil())
+ if (m_options.m_use_objc && !IsNil() && !IsUninitialized())
{
- if (!options.m_hide_value || !options.m_hide_name)
+ if (!m_options.m_hide_value || !m_options.m_hide_name)
m_stream->Printf(" ");
const char *object_desc = nullptr;
if (value_printed || summary_printed)
@@ -437,13 +538,61 @@ ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed,
}
bool
+DumpValueObjectOptions::PointerDepth::CanAllowExpansion (bool is_root,
+ TypeSummaryImpl* entry,
+ ValueObject *valobj,
+ const std::string& summary)
+{
+ switch (m_mode)
+ {
+ case Mode::Always:
+ return (m_count > 0);
+ case Mode::Never:
+ return false;
+ case Mode::Default:
+ if (is_root)
+ m_count = std::min<decltype(m_count)>(m_count,1);
+ return m_count > 0;
+ case Mode::Formatters:
+ if (!entry || entry->DoesPrintChildren(valobj) || summary.empty())
+ return m_count > 0;
+ return false;
+ }
+ return false;
+}
+
+bool
+DumpValueObjectOptions::PointerDepth::CanAllowExpansion () const
+{
+ switch (m_mode)
+ {
+ case Mode::Always:
+ case Mode::Default:
+ case Mode::Formatters:
+ return (m_count > 0);
+ case Mode::Never:
+ return false;
+ }
+ return false;
+}
+
+bool
ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
- uint32_t& curr_ptr_depth)
+ DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
{
const bool is_ref = IsRef ();
const bool is_ptr = IsPtr ();
-
- if (is_failed_description || m_curr_depth < options.m_max_depth)
+ const bool is_uninit = IsUninitialized();
+
+ if (is_uninit)
+ return false;
+
+ TypeSummaryImpl* entry = GetSummaryFormatter();
+
+ if (m_options.m_use_objc)
+ return false;
+
+ if (is_failed_description || m_curr_depth < m_options.m_max_depth)
{
// We will show children for all concrete types. We won't show
// pointer contents unless a pointer depth has been specified.
@@ -461,25 +610,37 @@ ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
if (m_valobj->GetPointerValue (&ptr_address_type) == 0)
return false;
- else if (is_ref && m_curr_depth == 0 && curr_ptr_depth == 0)
+ const bool is_root_level = m_curr_depth == 0;
+
+ if (is_ref &&
+ is_root_level)
{
// If this is the root object (depth is zero) that we are showing
// and it is a reference, and no pointer depth has been supplied
// print out what it references. Don't do this at deeper depths
// otherwise we can end up with infinite recursion...
- curr_ptr_depth = 1;
+ return true;
}
- return (curr_ptr_depth > 0);
+ return curr_ptr_depth.CanAllowExpansion(false, entry, m_valobj, m_summary);
}
- TypeSummaryImpl* entry = GetSummaryFormatter();
-
return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty());
}
return false;
}
+bool
+ValueObjectPrinter::ShouldExpandEmptyAggregates ()
+{
+ TypeSummaryImpl* entry = GetSummaryFormatter();
+
+ if (!entry)
+ return true;
+
+ return entry->DoesPrintEmptyAggregates();
+}
+
ValueObject*
ValueObjectPrinter::GetValueObjectForChildrenGeneration ()
{
@@ -489,7 +650,7 @@ ValueObjectPrinter::GetValueObjectForChildrenGeneration ()
void
ValueObjectPrinter::PrintChildrenPreamble ()
{
- if (options.m_flat_output)
+ if (m_options.m_flat_output)
{
if (ShouldPrintValueObject())
m_stream->EOL();
@@ -504,22 +665,23 @@ ValueObjectPrinter::PrintChildrenPreamble ()
void
ValueObjectPrinter::PrintChild (ValueObjectSP child_sp,
- uint32_t curr_ptr_depth)
+ const DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
{
- DumpValueObjectOptions child_options(options);
- child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName();
- child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value)
+ DumpValueObjectOptions child_options(m_options);
+ child_options.SetFormat(m_options.m_format).SetSummary().SetRootValueObjectName();
+ child_options.SetScopeChecked(true).SetHideName(m_options.m_hide_name).SetHideValue(m_options.m_hide_value)
.SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0);
+
if (child_sp.get())
{
ValueObjectPrinter child_printer(child_sp.get(),
m_stream,
child_options,
- (IsPtr() || IsRef()) && curr_ptr_depth >= 1 ? curr_ptr_depth - 1 : curr_ptr_depth,
- m_curr_depth + 1);
+ (IsPtr() || IsRef()) ? --curr_ptr_depth : curr_ptr_depth,
+ m_curr_depth + 1,
+ m_printed_instance_pointers);
child_printer.PrintValueObject();
}
-
}
uint32_t
@@ -533,7 +695,7 @@ ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot)
{
const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
- if (num_children > max_num_children && !options.m_ignore_cap)
+ if (num_children > max_num_children && !m_options.m_ignore_cap)
{
print_dotdotdot = true;
return max_num_children;
@@ -545,7 +707,7 @@ ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot)
void
ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot)
{
- if (!options.m_flat_output)
+ if (!m_options.m_flat_output)
{
if (print_dotdotdot)
{
@@ -557,8 +719,34 @@ ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot)
}
}
+bool
+ValueObjectPrinter::ShouldPrintEmptyBrackets (bool value_printed,
+ bool summary_printed)
+{
+ ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
+
+ if (!IsAggregate())
+ return false;
+
+ if (m_options.m_reveal_empty_aggregates == false)
+ {
+ if (value_printed || summary_printed)
+ return false;
+ }
+
+ if (synth_m_valobj->MightHaveChildren())
+ return true;
+
+ if (m_val_summary_ok)
+ return false;
+
+ return true;
+}
+
void
-ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth)
+ValueObjectPrinter::PrintChildren (bool value_printed,
+ bool summary_printed,
+ const DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
{
ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
@@ -566,23 +754,44 @@ ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth)
size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
if (num_children)
{
- PrintChildrenPreamble ();
+ bool any_children_printed = false;
for (size_t idx=0; idx<num_children; ++idx)
{
ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
- PrintChild (child_sp, curr_ptr_depth);
+ if (child_sp)
+ {
+ if (!any_children_printed)
+ {
+ PrintChildrenPreamble ();
+ any_children_printed = true;
+ }
+ PrintChild (child_sp, curr_ptr_depth);
+ }
}
- PrintChildrenPostamble (print_dotdotdot);
+ if (any_children_printed)
+ PrintChildrenPostamble (print_dotdotdot);
+ else
+ {
+ if (ShouldPrintEmptyBrackets(value_printed, summary_printed))
+ {
+ if (ShouldPrintValueObject())
+ m_stream->PutCString(" {}\n");
+ else
+ m_stream->EOL();
+ }
+ else
+ m_stream->EOL();
+ }
}
- else if (IsAggregate())
+ else if (ShouldPrintEmptyBrackets(value_printed, summary_printed))
{
// Aggregate, no children...
if (ShouldPrintValueObject())
{
// if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value
- if (m_valobj->DoesProvideSyntheticValue())
+ if (m_valobj->DoesProvideSyntheticValue() || !ShouldExpandEmptyAggregates())
m_stream->PutCString( "\n");
else
m_stream->PutCString(" {}\n");
@@ -614,7 +823,7 @@ ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names)
{
lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
if (child_sp)
- child_sp = child_sp->GetQualifiedRepresentationIfAvailable(options.m_use_dynamic, options.m_use_synthetic);
+ child_sp = child_sp->GetQualifiedRepresentationIfAvailable(m_options.m_use_dynamic, m_options.m_use_synthetic);
if (child_sp)
{
if (idx)
@@ -630,7 +839,7 @@ ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names)
}
child_sp->DumpPrintableRepresentation(*m_stream,
ValueObject::eValueObjectRepresentationStyleSummary,
- lldb::eFormatInvalid,
+ m_options.m_format,
ValueObject::ePrintableRepresentationSpecialCasesDisable);
}
}
@@ -651,13 +860,30 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
// if that happens, we want to display the children, if any
bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
- uint32_t curr_ptr_depth = m_ptr_depth;
+ auto curr_ptr_depth = m_ptr_depth;
bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth);
- bool print_oneline = (curr_ptr_depth > 0 ||
- options.m_show_types ||
- !options.m_allow_oneliner_mode ||
- options.m_flat_output ||
- options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
+ bool print_oneline = (curr_ptr_depth.CanAllowExpansion() ||
+ m_options.m_show_types ||
+ !m_options.m_allow_oneliner_mode ||
+ m_options.m_flat_output ||
+ m_options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
+ bool is_instance_ptr = IsInstancePointer();
+ uint64_t instance_ptr_value = LLDB_INVALID_ADDRESS;
+
+ if (print_children && is_instance_ptr)
+ {
+ instance_ptr_value = m_valobj->GetValueAsUnsigned(0);
+ if (m_printed_instance_pointers->count(instance_ptr_value))
+ {
+ // we already printed this instance-is-pointer thing, so don't expand it
+ m_stream->PutCString(" {...}\n");
+
+ // we're done here - get out fast
+ return;
+ }
+ else
+ m_printed_instance_pointers->emplace(instance_ptr_value); // remember this guy for future reference
+ }
if (print_children)
{
@@ -668,11 +894,11 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
m_stream->EOL();
}
else
- PrintChildren (curr_ptr_depth);
+ PrintChildren (value_printed, summary_printed, curr_ptr_depth);
}
- else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject())
+ else if (m_curr_depth >= m_options.m_max_depth && IsAggregate() && ShouldPrintValueObject())
{
- m_stream->PutCString("{...}\n");
+ m_stream->PutCString("{...}\n");
}
else
m_stream->EOL();
@@ -681,7 +907,7 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
bool
ValueObjectPrinter::ShouldPrintValidation ()
{
- return options.m_run_validator;
+ return m_options.m_run_validator;
}
bool
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/VectorType.cpp b/contrib/llvm/tools/lldb/source/DataFormatters/VectorType.cpp
index 316d7b5..347afa5 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/VectorType.cpp
+++ b/contrib/llvm/tools/lldb/source/DataFormatters/VectorType.cpp
@@ -1,4 +1,4 @@
-//===-- VectorType.cpp ---------------------------------------------*- C++ -*-===//
+//===-- VectorType.cpp ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,17 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/DataFormatters/VectorType.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBAssert.h"
@@ -20,87 +25,87 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
-static ClangASTType
-GetClangTypeForFormat (lldb::Format format,
- ClangASTType element_type,
- ClangASTContext *ast_ctx)
+static CompilerType
+GetCompilerTypeForFormat (lldb::Format format,
+ CompilerType element_type,
+ TypeSystem *type_system)
{
- lldbassert(ast_ctx && "ast_ctx needs to be not NULL");
+ lldbassert(type_system && "type_system needs to be not NULL");
switch (format)
{
case lldb::eFormatAddressInfo:
case lldb::eFormatPointer:
- return ast_ctx->GetPointerSizedIntType(false);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 8*type_system->GetPointerByteSize());
case lldb::eFormatBoolean:
- return ast_ctx->GetBasicType(lldb::eBasicTypeBool);
+ return type_system->GetBasicTypeFromAST(lldb::eBasicTypeBool);
case lldb::eFormatBytes:
case lldb::eFormatBytesWithASCII:
case lldb::eFormatChar:
case lldb::eFormatCharArray:
case lldb::eFormatCharPrintable:
- return ast_ctx->GetBasicType(lldb::eBasicTypeChar);
+ return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar);
case lldb::eFormatComplex /* lldb::eFormatComplexFloat */:
- return ast_ctx->GetBasicType(lldb::eBasicTypeFloatComplex);
+ return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloatComplex);
case lldb::eFormatCString:
- return ast_ctx->GetBasicType(lldb::eBasicTypeChar).GetPointerType();
+ return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar).GetPointerType();
case lldb::eFormatFloat:
- return ast_ctx->GetBasicType(lldb::eBasicTypeFloat);
+ return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat);
case lldb::eFormatHex:
case lldb::eFormatHexUppercase:
case lldb::eFormatOctal:
- return ast_ctx->GetBasicType(lldb::eBasicTypeInt);
+ return type_system->GetBasicTypeFromAST(lldb::eBasicTypeInt);
case lldb::eFormatHexFloat:
- return ast_ctx->GetBasicType(lldb::eBasicTypeFloat);
+ return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat);
case lldb::eFormatUnicode16:
case lldb::eFormatUnicode32:
case lldb::eFormatUnsigned:
- return ast_ctx->GetBasicType(lldb::eBasicTypeUnsignedInt);
+ return type_system->GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt);
case lldb::eFormatVectorOfChar:
- return ast_ctx->GetBasicType(lldb::eBasicTypeChar);
+ return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar);
case lldb::eFormatVectorOfFloat32:
- return ast_ctx->GetFloatTypeFromBitSize(32);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754, 32);
case lldb::eFormatVectorOfFloat64:
- return ast_ctx->GetFloatTypeFromBitSize(64);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754, 64);
case lldb::eFormatVectorOfSInt16:
- return ast_ctx->GetIntTypeFromBitSize(16, true);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingSint, 16);
case lldb::eFormatVectorOfSInt32:
- return ast_ctx->GetIntTypeFromBitSize(32, true);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingSint, 32);
case lldb::eFormatVectorOfSInt64:
- return ast_ctx->GetIntTypeFromBitSize(64, true);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingSint, 64);
case lldb::eFormatVectorOfSInt8:
- return ast_ctx->GetIntTypeFromBitSize(8, true);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingSint, 8);
case lldb::eFormatVectorOfUInt128:
- return ast_ctx->GetIntTypeFromBitSize(128, false);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 128);
case lldb::eFormatVectorOfUInt16:
- return ast_ctx->GetIntTypeFromBitSize(16, false);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 16);
case lldb::eFormatVectorOfUInt32:
- return ast_ctx->GetIntTypeFromBitSize(32, false);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 32);
case lldb::eFormatVectorOfUInt64:
- return ast_ctx->GetIntTypeFromBitSize(64, false);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 64);
case lldb::eFormatVectorOfUInt8:
- return ast_ctx->GetIntTypeFromBitSize(8, false);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 8);
case lldb::eFormatDefault:
return element_type;
@@ -113,13 +118,13 @@ GetClangTypeForFormat (lldb::Format format,
case lldb::eFormatOSType:
case lldb::eFormatVoid:
default:
- return ast_ctx->GetIntTypeFromBitSize(8, false);
+ return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 8);
}
}
static lldb::Format
GetItemFormatForFormat (lldb::Format format,
- ClangASTType element_type)
+ CompilerType element_type)
{
switch (format)
{
@@ -169,8 +174,8 @@ GetItemFormatForFormat (lldb::Format format,
}
static size_t
-CalculateNumChildren (ClangASTType container_type,
- ClangASTType element_type,
+CalculateNumChildren (CompilerType container_type,
+ CompilerType element_type,
lldb_private::ExecutionContextScope *exe_scope = nullptr // does not matter here because all we trade in are basic types
)
{
@@ -199,15 +204,17 @@ namespace lldb_private {
m_child_type(),
m_num_children(0)
{}
-
- virtual size_t
- CalculateNumChildren ()
+
+ ~VectorTypeSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override
{
return m_num_children;
}
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx)
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
{
if (idx >= CalculateNumChildren())
return lldb::ValueObjectSP();
@@ -225,29 +232,32 @@ namespace lldb_private {
return child_sp;
}
- virtual bool
- Update()
+ bool
+ Update() override
{
m_parent_format = m_backend.GetFormat();
- ClangASTType parent_type(m_backend.GetClangType());
- ClangASTType element_type;
+ CompilerType parent_type(m_backend.GetCompilerType());
+ CompilerType element_type;
parent_type.IsVectorType(&element_type, nullptr);
- m_child_type = ::GetClangTypeForFormat(m_parent_format, element_type, ClangASTContext::GetASTContext(parent_type.GetASTContext()));
+ TargetSP target_sp(m_backend.GetTargetSP());
+ m_child_type = ::GetCompilerTypeForFormat(m_parent_format,
+ element_type,
+ target_sp ? target_sp->GetScratchTypeSystemForLanguage(nullptr, lldb::eLanguageTypeC) : nullptr);
m_num_children = ::CalculateNumChildren(parent_type,
m_child_type);
m_item_format = GetItemFormatForFormat(m_parent_format,
m_child_type);
return false;
}
-
- virtual bool
- MightHaveChildren ()
+
+ bool
+ MightHaveChildren() override
{
return true;
}
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name)
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override
{
const char* item_name = name.GetCString();
uint32_t idx = ExtractIndexFromString(item_name);
@@ -255,18 +265,16 @@ namespace lldb_private {
return UINT32_MAX;
return idx;
}
-
- virtual
- ~VectorTypeSyntheticFrontEnd () {}
-
+
private:
lldb::Format m_parent_format;
lldb::Format m_item_format;
- ClangASTType m_child_type;
+ CompilerType m_child_type;
size_t m_num_children;
};
- }
-}
+
+ } // namespace formatters
+} // namespace lldb_private
bool
lldb_private::formatters::VectorTypeSummaryProvider (ValueObject& valobj,
@@ -317,6 +325,6 @@ lldb_private::SyntheticChildrenFrontEnd*
lldb_private::formatters::VectorTypeSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
if (!valobj_sp)
- return NULL;
- return (new VectorTypeSyntheticFrontEnd(valobj_sp));
+ return nullptr;
+ return new VectorTypeSyntheticFrontEnd(valobj_sp);
}
diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangExpressionVariable.cpp b/contrib/llvm/tools/lldb/source/Expression/ClangExpressionVariable.cpp
deleted file mode 100644
index e86016e..0000000
--- a/contrib/llvm/tools/lldb/source/Expression/ClangExpressionVariable.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-//===-- ClangExpressionVariable.cpp -----------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Expression/ClangExpressionVariable.h"
-#include "clang/AST/ASTContext.h"
-#include "lldb/Core/ConstString.h"
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Core/Value.h"
-#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
-
-using namespace lldb_private;
-using namespace clang;
-
-ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size) :
- m_parser_vars(),
- m_jit_vars (),
- m_flags (EVNone),
- m_frozen_sp (ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size))
-{
-}
-
-ClangExpressionVariable::ClangExpressionVariable (ExecutionContextScope *exe_scope,
- Value &value,
- const ConstString &name,
- uint16_t flags) :
- m_parser_vars(),
- m_jit_vars (),
- m_flags (flags),
- m_frozen_sp (ValueObjectConstResult::Create (exe_scope, value, name))
-{
-}
-
-ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) :
- m_parser_vars(),
- m_jit_vars (),
- m_flags (EVNone),
- m_frozen_sp (valobj_sp)
-{
-}
-
-//----------------------------------------------------------------------
-/// Return the variable's size in bytes
-//----------------------------------------------------------------------
-size_t
-ClangExpressionVariable::GetByteSize ()
-{
- return m_frozen_sp->GetByteSize();
-}
-
-const ConstString &
-ClangExpressionVariable::GetName ()
-{
- return m_frozen_sp->GetName();
-}
-
-lldb::ValueObjectSP
-ClangExpressionVariable::GetValueObject()
-{
- return m_frozen_sp;
-}
-
-RegisterInfo *
-ClangExpressionVariable::GetRegisterInfo()
-{
- return m_frozen_sp->GetValue().GetRegisterInfo();
-}
-
-void
-ClangExpressionVariable::SetRegisterInfo (const RegisterInfo *reg_info)
-{
- return m_frozen_sp->GetValue().SetContext (Value::eContextTypeRegisterInfo, const_cast<RegisterInfo *>(reg_info));
-}
-
-ClangASTType
-ClangExpressionVariable::GetClangType()
-{
- return m_frozen_sp->GetClangType();
-}
-
-void
-ClangExpressionVariable::SetClangType(const ClangASTType &clang_type)
-{
- m_frozen_sp->GetValue().SetClangType(clang_type);
-}
-
-
-TypeFromUser
-ClangExpressionVariable::GetTypeFromUser()
-{
- TypeFromUser tfu (m_frozen_sp->GetClangType());
- return tfu;
-}
-
-uint8_t *
-ClangExpressionVariable::GetValueBytes()
-{
- const size_t byte_size = m_frozen_sp->GetByteSize();
- if (byte_size > 0)
- {
- if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size)
- {
- m_frozen_sp->GetValue().ResizeData(byte_size);
- m_frozen_sp->GetValue().GetData (m_frozen_sp->GetDataExtractor());
- }
- return const_cast<uint8_t *>(m_frozen_sp->GetDataExtractor().GetDataStart());
- }
- return NULL;
-}
-
-void
-ClangExpressionVariable::SetName (const ConstString &name)
-{
- m_frozen_sp->SetName (name);
-}
-
-void
-ClangExpressionVariable::ValueUpdated ()
-{
- m_frozen_sp->ValueUpdated ();
-}
-
-void
-ClangExpressionVariable::TransferAddress (bool force)
-{
- if (m_live_sp.get() == NULL)
- return;
-
- if (m_frozen_sp.get() == NULL)
- return;
-
- if (force || (m_frozen_sp->GetLiveAddress() == LLDB_INVALID_ADDRESS))
- m_frozen_sp->SetLiveAddress(m_live_sp->GetLiveAddress());
-}
diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp b/contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp
deleted file mode 100644
index 0da70e2..0000000
--- a/contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp
+++ /dev/null
@@ -1,1172 +0,0 @@
-//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#include <cstdlib>
-#include <string>
-#include <map>
-
-#include "lldb/Core/ConstString.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Expression/ASTResultSynthesizer.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "lldb/Expression/ClangExpressionParser.h"
-#include "lldb/Expression/ClangFunction.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Expression/ClangUserExpression.h"
-#include "lldb/Expression/ExpressionSourceCode.h"
-#include "lldb/Expression/IRExecutionUnit.h"
-#include "lldb/Expression/IRInterpreter.h"
-#include "lldb/Expression/Materializer.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/Block.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
-#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadPlan.h"
-#include "lldb/Target/ThreadPlanCallUserExpression.h"
-
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-
-using namespace lldb_private;
-
-ClangUserExpression::ClangUserExpression (const char *expr,
- const char *expr_prefix,
- lldb::LanguageType language,
- ResultType desired_type) :
- ClangExpression (),
- m_stack_frame_bottom (LLDB_INVALID_ADDRESS),
- m_stack_frame_top (LLDB_INVALID_ADDRESS),
- m_expr_text (expr),
- m_expr_prefix (expr_prefix ? expr_prefix : ""),
- m_language (language),
- m_transformed_text (),
- m_desired_type (desired_type),
- m_expr_decl_map(),
- m_execution_unit_sp(),
- m_materializer_ap(),
- m_result_synthesizer(),
- m_jit_module_wp(),
- m_enforce_valid_object (true),
- m_in_cplusplus_method (false),
- m_in_objectivec_method (false),
- m_in_static_method(false),
- m_needs_object_ptr (false),
- m_const_object (false),
- m_target (NULL),
- m_can_interpret (false),
- m_materialized_address (LLDB_INVALID_ADDRESS)
-{
- switch (m_language)
- {
- case lldb::eLanguageTypeC_plus_plus:
- m_allow_cxx = true;
- break;
- case lldb::eLanguageTypeObjC:
- m_allow_objc = true;
- break;
- case lldb::eLanguageTypeObjC_plus_plus:
- default:
- m_allow_cxx = true;
- m_allow_objc = true;
- break;
- }
-}
-
-ClangUserExpression::~ClangUserExpression ()
-{
- if (m_target)
- {
- lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
- if (jit_module_sp)
- m_target->GetImages().Remove(jit_module_sp);
- }
-}
-
-clang::ASTConsumer *
-ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
-{
- m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough,
- *m_target));
-
- return m_result_synthesizer.get();
-}
-
-void
-ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("ClangUserExpression::ScanContext()");
-
- m_target = exe_ctx.GetTargetPtr();
-
- if (!(m_allow_cxx || m_allow_objc))
- {
- if (log)
- log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C");
- return;
- }
-
- StackFrame *frame = exe_ctx.GetFramePtr();
- if (frame == NULL)
- {
- if (log)
- log->Printf(" [CUE::SC] Null stack frame");
- return;
- }
-
- SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
-
- if (!sym_ctx.function)
- {
- if (log)
- log->Printf(" [CUE::SC] Null function");
- return;
- }
-
- // Find the block that defines the function represented by "sym_ctx"
- Block *function_block = sym_ctx.GetFunctionBlock();
-
- if (!function_block)
- {
- if (log)
- log->Printf(" [CUE::SC] Null function block");
- return;
- }
-
- clang::DeclContext *decl_context = function_block->GetClangDeclContext();
-
- if (!decl_context)
- {
- if (log)
- log->Printf(" [CUE::SC] Null decl context");
- return;
- }
-
- if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context))
- {
- if (m_allow_cxx && method_decl->isInstance())
- {
- if (m_enforce_valid_object)
- {
- lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
- const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context";
-
- if (!variable_list_sp)
- {
- err.SetErrorString(thisErrorString);
- return;
- }
-
- lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
-
- if (!this_var_sp ||
- !this_var_sp->IsInScope(frame) ||
- !this_var_sp->LocationIsValidForFrame (frame))
- {
- err.SetErrorString(thisErrorString);
- return;
- }
- }
-
- m_in_cplusplus_method = true;
- m_needs_object_ptr = true;
- }
- }
- else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context))
- {
- if (m_allow_objc)
- {
- if (m_enforce_valid_object)
- {
- lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
- const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context";
-
- if (!variable_list_sp)
- {
- err.SetErrorString(selfErrorString);
- return;
- }
-
- lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
-
- if (!self_variable_sp ||
- !self_variable_sp->IsInScope(frame) ||
- !self_variable_sp->LocationIsValidForFrame (frame))
- {
- err.SetErrorString(selfErrorString);
- return;
- }
- }
-
- m_in_objectivec_method = true;
- m_needs_object_ptr = true;
-
- if (!method_decl->isInstanceMethod())
- m_in_static_method = true;
- }
- }
- else if (clang::FunctionDecl *function_decl = llvm::dyn_cast<clang::FunctionDecl>(decl_context))
- {
- // We might also have a function that said in the debug information that it captured an
- // object pointer. The best way to deal with getting to the ivars at present is by pretending
- // that this is a method of a class in whatever runtime the debug info says the object pointer
- // belongs to. Do that here.
-
- ClangASTMetadata *metadata = ClangASTContext::GetMetadata (&decl_context->getParentASTContext(), function_decl);
- if (metadata && metadata->HasObjectPtr())
- {
- lldb::LanguageType language = metadata->GetObjectPtrLanguage();
- if (language == lldb::eLanguageTypeC_plus_plus)
- {
- if (m_enforce_valid_object)
- {
- lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
- const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context";
-
- if (!variable_list_sp)
- {
- err.SetErrorString(thisErrorString);
- return;
- }
-
- lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
-
- if (!this_var_sp ||
- !this_var_sp->IsInScope(frame) ||
- !this_var_sp->LocationIsValidForFrame (frame))
- {
- err.SetErrorString(thisErrorString);
- return;
- }
- }
-
- m_in_cplusplus_method = true;
- m_needs_object_ptr = true;
- }
- else if (language == lldb::eLanguageTypeObjC)
- {
- if (m_enforce_valid_object)
- {
- lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
-
- const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context";
-
- if (!variable_list_sp)
- {
- err.SetErrorString(selfErrorString);
- return;
- }
-
- lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
-
- if (!self_variable_sp ||
- !self_variable_sp->IsInScope(frame) ||
- !self_variable_sp->LocationIsValidForFrame (frame))
- {
- err.SetErrorString(selfErrorString);
- return;
- }
-
- Type *self_type = self_variable_sp->GetType();
-
- if (!self_type)
- {
- err.SetErrorString(selfErrorString);
- return;
- }
-
- ClangASTType self_clang_type = self_type->GetClangForwardType();
-
- if (!self_clang_type)
- {
- err.SetErrorString(selfErrorString);
- return;
- }
-
- if (self_clang_type.IsObjCClassType())
- {
- return;
- }
- else if (self_clang_type.IsObjCObjectPointerType())
- {
- m_in_objectivec_method = true;
- m_needs_object_ptr = true;
- }
- else
- {
- err.SetErrorString(selfErrorString);
- return;
- }
- }
- else
- {
- m_in_objectivec_method = true;
- m_needs_object_ptr = true;
- }
- }
- }
- }
-}
-
-void
-ClangUserExpression::InstallContext (ExecutionContext &exe_ctx)
-{
- m_process_wp = exe_ctx.GetProcessSP();
-
- lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
-
- if (frame_sp)
- m_address = frame_sp->GetFrameCodeAddress();
-}
-
-bool
-ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx,
- lldb::TargetSP &target_sp,
- lldb::ProcessSP &process_sp,
- lldb::StackFrameSP &frame_sp)
-{
- lldb::ProcessSP expected_process_sp = m_process_wp.lock();
- process_sp = exe_ctx.GetProcessSP();
-
- if (process_sp != expected_process_sp)
- return false;
-
- process_sp = exe_ctx.GetProcessSP();
- target_sp = exe_ctx.GetTargetSP();
- frame_sp = exe_ctx.GetFrameSP();
-
- if (m_address.IsValid())
- {
- if (!frame_sp)
- return false;
- else
- return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get()));
- }
-
- return true;
-}
-
-bool
-ClangUserExpression::MatchesContext (ExecutionContext &exe_ctx)
-{
- lldb::TargetSP target_sp;
- lldb::ProcessSP process_sp;
- lldb::StackFrameSP frame_sp;
-
- return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
-}
-
-// This is a really nasty hack, meant to fix Objective-C expressions of the form
-// (int)[myArray count]. Right now, because the type information for count is
-// not available, [myArray count] returns id, which can't be directly cast to
-// int without causing a clang error.
-static void
-ApplyObjcCastHack(std::string &expr)
-{
-#define OBJC_CAST_HACK_FROM "(int)["
-#define OBJC_CAST_HACK_TO "(int)(long long)["
-
- size_t from_offset;
-
- while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
- expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
-
-#undef OBJC_CAST_HACK_TO
-#undef OBJC_CAST_HACK_FROM
-}
-
-// Another hack, meant to allow use of unichar despite it not being available in
-// the type information. Although we could special-case it in type lookup,
-// hopefully we'll figure out a way to #include the same environment as is
-// present in the original source file rather than try to hack specific type
-// definitions in as needed.
-//static void
-//ApplyUnicharHack(std::string &expr)
-//{
-//#define UNICHAR_HACK_FROM "unichar"
-//#define UNICHAR_HACK_TO "unsigned short"
-//
-// size_t from_offset;
-//
-// while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
-// expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
-//
-//#undef UNICHAR_HACK_TO
-//#undef UNICHAR_HACK_FROM
-//}
-
-bool
-ClangUserExpression::Parse (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb_private::ExecutionPolicy execution_policy,
- bool keep_result_in_memory,
- bool generate_debug_info)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- Error err;
-
- InstallContext(exe_ctx);
-
- ScanContext(exe_ctx, err);
-
- if (!err.Success())
- {
- error_stream.Printf("warning: %s\n", err.AsCString());
- }
-
- StreamString m_transformed_stream;
-
- ////////////////////////////////////
- // Generate the expression
- //
-
- ApplyObjcCastHack(m_expr_text);
- //ApplyUnicharHack(m_expr_text);
-
- std::string prefix = m_expr_prefix;
-
- if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor())
- {
- const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = m_target->GetPersistentVariables().GetHandLoadedClangModules();
- ClangModulesDeclVendor::ModuleVector modules_for_macros;
-
- for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
- {
- modules_for_macros.push_back(module);
- }
-
- if (m_target->GetEnableAutoImportClangModules())
- {
- if (StackFrame *frame = exe_ctx.GetFramePtr())
- {
- if (Block *block = frame->GetFrameBlock())
- {
- SymbolContext sc;
-
- block->CalculateSymbolContext(&sc);
-
- if (sc.comp_unit)
- {
- StreamString error_stream;
-
- decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream);
- }
- }
- }
- }
- }
-
- std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str()));
-
- lldb::LanguageType lang_type;
-
- if (m_in_cplusplus_method)
- lang_type = lldb::eLanguageTypeC_plus_plus;
- else if (m_in_objectivec_method)
- lang_type = lldb::eLanguageTypeObjC;
- else
- lang_type = lldb::eLanguageTypeC;
-
- if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx))
- {
- error_stream.PutCString ("error: couldn't construct expression body");
- return false;
- }
-
- if (log)
- log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
-
- ////////////////////////////////////
- // Set up the target and compiler
- //
-
- Target *target = exe_ctx.GetTargetPtr();
-
- if (!target)
- {
- error_stream.PutCString ("error: invalid target\n");
- return false;
- }
-
- //////////////////////////
- // Parse the expression
- //
-
- m_materializer_ap.reset(new Materializer());
-
- m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
-
- class OnExit
- {
- public:
- typedef std::function <void (void)> Callback;
-
- OnExit (Callback const &callback) :
- m_callback(callback)
- {
- }
-
- ~OnExit ()
- {
- m_callback();
- }
- private:
- Callback m_callback;
- };
-
- OnExit on_exit([this]() { m_expr_decl_map.reset(); });
-
- if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get()))
- {
- error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
-
- m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.
-
- return false;
- }
-
- Process *process = exe_ctx.GetProcessPtr();
- ExecutionContextScope *exe_scope = process;
-
- if (!exe_scope)
- exe_scope = exe_ctx.GetTargetPtr();
-
- ClangExpressionParser parser(exe_scope, *this, generate_debug_info);
-
- unsigned num_errors = parser.Parse (error_stream);
-
- if (num_errors)
- {
- error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
-
- m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.
-
- return false;
- }
-
- //////////////////////////////////////////////////////////////////////////////////////////
- // Prepare the output of the parser for execution, evaluating it statically if possible
- //
-
- Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
- m_jit_end_addr,
- m_execution_unit_sp,
- exe_ctx,
- m_can_interpret,
- execution_policy);
-
- if (generate_debug_info)
- {
- lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
-
- if (jit_module_sp)
- {
- ConstString const_func_name(FunctionName());
- FileSpec jit_file;
- jit_file.GetFilename() = const_func_name;
- jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
- m_jit_module_wp = jit_module_sp;
- target->GetImages().Append(jit_module_sp);
- }
-// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
-// StreamFile strm (stdout, false);
-// if (jit_obj_file)
-// {
-// jit_obj_file->GetSectionList();
-// jit_obj_file->GetSymtab();
-// jit_obj_file->Dump(&strm);
-// }
-// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
-// if (jit_sym_vendor)
-// {
-// lldb_private::SymbolContextList sc_list;
-// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
-// sc_list.Dump(&strm, target);
-// jit_sym_vendor->Dump(&strm);
-// }
- }
-
- m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions.
-
- if (jit_error.Success())
- {
- if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
- m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
- return true;
- }
- else
- {
- const char *error_cstr = jit_error.AsCString();
- if (error_cstr && error_cstr[0])
- error_stream.Printf ("error: %s\n", error_cstr);
- else
- error_stream.Printf ("error: expression can't be interpreted or run\n");
- return false;
- }
-}
-
-static lldb::addr_t
-GetObjectPointer (lldb::StackFrameSP frame_sp,
- ConstString &object_name,
- Error &err)
-{
- err.Clear();
-
- if (!frame_sp)
- {
- err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
- return LLDB_INVALID_ADDRESS;
- }
-
- lldb::VariableSP var_sp;
- lldb::ValueObjectSP valobj_sp;
-
- valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
- lldb::eNoDynamicValues,
- StackFrame::eExpressionPathOptionCheckPtrVsMember |
- StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
- StackFrame::eExpressionPathOptionsNoSyntheticChildren |
- StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
- var_sp,
- err);
-
- if (!err.Success() || !valobj_sp.get())
- return LLDB_INVALID_ADDRESS;
-
- lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
-
- if (ret == LLDB_INVALID_ADDRESS)
- {
- err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
- return LLDB_INVALID_ADDRESS;
- }
-
- return ret;
-}
-
-bool
-ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb::addr_t &struct_address,
- lldb::addr_t &object_ptr,
- lldb::addr_t &cmd_ptr)
-{
- lldb::TargetSP target;
- lldb::ProcessSP process;
- lldb::StackFrameSP frame;
-
- if (!LockAndCheckContext(exe_ctx,
- target,
- process,
- frame))
- {
- error_stream.Printf("The context has changed before we could JIT the expression!\n");
- return false;
- }
-
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
- {
- if (m_needs_object_ptr)
- {
- ConstString object_name;
-
- if (m_in_cplusplus_method)
- {
- object_name.SetCString("this");
- }
- else if (m_in_objectivec_method)
- {
- object_name.SetCString("self");
- }
- else
- {
- error_stream.Printf("Need object pointer but don't know the language\n");
- return false;
- }
-
- Error object_ptr_error;
-
- object_ptr = GetObjectPointer(frame, object_name, object_ptr_error);
-
- if (!object_ptr_error.Success())
- {
- error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
- object_ptr = 0;
- }
-
- if (m_in_objectivec_method)
- {
- ConstString cmd_name("_cmd");
-
- cmd_ptr = GetObjectPointer(frame, cmd_name, object_ptr_error);
-
- if (!object_ptr_error.Success())
- {
- error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
- cmd_ptr = 0;
- }
- }
- }
-
- if (m_materialized_address == LLDB_INVALID_ADDRESS)
- {
- Error alloc_error;
-
- IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
-
- m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(),
- m_materializer_ap->GetStructAlignment(),
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- policy,
- alloc_error);
-
- if (!alloc_error.Success())
- {
- error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
- return false;
- }
- }
-
- struct_address = m_materialized_address;
-
- if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
- {
- Error alloc_error;
-
- const size_t stack_frame_size = 512 * 1024;
-
- m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size,
- 8,
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- IRMemoryMap::eAllocationPolicyHostOnly,
- alloc_error);
-
- m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
-
- if (!alloc_error.Success())
- {
- error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
- return false;
- }
- }
-
- Error materialize_error;
-
- m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
-
- if (!materialize_error.Success())
- {
- error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString());
- return false;
- }
- }
- return true;
-}
-
-bool
-ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb::ClangExpressionVariableSP &result,
- lldb::addr_t function_stack_bottom,
- lldb::addr_t function_stack_top)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
-
- if (!m_dematerializer_sp)
- {
- error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present");
- return false;
- }
-
- Error dematerialize_error;
-
- m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_bottom, function_stack_top);
-
- if (!dematerialize_error.Success())
- {
- error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error"));
- return false;
- }
-
- if (result)
- result->TransferAddress();
-
- m_dematerializer_sp.reset();
-
- return true;
-}
-
-lldb::ExpressionResults
-ClangUserExpression::Execute (Stream &error_stream,
- ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions& options,
- lldb::ClangUserExpressionSP &shared_ptr_to_me,
- lldb::ClangExpressionVariableSP &result)
-{
- // The expression log is quite verbose, and if you're just tracking the execution of the
- // expression, it's quite convenient to have these logs come out with the STEP log as well.
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
-
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
- {
- lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
-
- lldb::addr_t object_ptr = 0;
- lldb::addr_t cmd_ptr = 0;
-
- if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
- {
- error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
- return lldb::eExpressionSetupError;
- }
-
- lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
- lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
-
- if (m_can_interpret)
- {
- llvm::Module *module = m_execution_unit_sp->GetModule();
- llvm::Function *function = m_execution_unit_sp->GetFunction();
-
- if (!module || !function)
- {
- error_stream.Printf("Supposed to interpret, but nothing is there");
- return lldb::eExpressionSetupError;
- }
-
- Error interpreter_error;
-
- llvm::SmallVector <lldb::addr_t, 3> args;
-
- if (m_needs_object_ptr)
- {
- args.push_back(object_ptr);
-
- if (m_in_objectivec_method)
- args.push_back(cmd_ptr);
- }
-
- args.push_back(struct_address);
-
- function_stack_bottom = m_stack_frame_bottom;
- function_stack_top = m_stack_frame_top;
-
- IRInterpreter::Interpret (*module,
- *function,
- args,
- *m_execution_unit_sp.get(),
- interpreter_error,
- function_stack_bottom,
- function_stack_top,
- exe_ctx);
-
- if (!interpreter_error.Success())
- {
- error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
- return lldb::eExpressionDiscarded;
- }
- }
- else
- {
- if (!exe_ctx.HasThreadScope())
- {
- error_stream.Printf("ClangUserExpression::Execute called with no thread selected.");
- return lldb::eExpressionSetupError;
- }
-
- Address wrapper_address (m_jit_start_addr);
-
- llvm::SmallVector <lldb::addr_t, 3> args;
-
- if (m_needs_object_ptr) {
- args.push_back(object_ptr);
- if (m_in_objectivec_method)
- args.push_back(cmd_ptr);
- }
-
- args.push_back(struct_address);
-
- lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
- wrapper_address,
- args,
- options,
- shared_ptr_to_me));
-
- if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
- return lldb::eExpressionSetupError;
-
- ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
-
- lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
-
- function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
- function_stack_top = function_stack_pointer;
-
- if (log)
- log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
-
- lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
- call_plan_sp,
- options,
- error_stream);
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
-
- if (log)
- log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
-
- if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
- {
- const char *error_desc = NULL;
-
- if (call_plan_sp)
- {
- lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
- if (real_stop_info_sp)
- error_desc = real_stop_info_sp->GetDescription();
- }
- if (error_desc)
- error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
- else
- error_stream.PutCString ("Execution was interrupted.");
-
- if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError())
- || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
- error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
- else
- {
- if (execution_result == lldb::eExpressionHitBreakpoint)
- user_expression_plan->TransferExpressionOwnership();
- error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, "
- "use \"thread return -x\" to return to the state before expression evaluation.");
- }
-
- return execution_result;
- }
- else if (execution_result == lldb::eExpressionStoppedForDebug)
- {
- error_stream.PutCString ("Execution was halted at the first instruction of the expression "
- "function because \"debug\" was requested.\n"
- "Use \"thread return -x\" to return to the state before expression evaluation.");
- return execution_result;
- }
- else if (execution_result != lldb::eExpressionCompleted)
- {
- error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
- return execution_result;
- }
- }
-
- if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
- {
- return lldb::eExpressionCompleted;
- }
- else
- {
- return lldb::eExpressionResultUnavailable;
- }
- }
- else
- {
- error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
- return lldb::eExpressionSetupError;
- }
-}
-
-lldb::ExpressionResults
-ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions& options,
- const char *expr_cstr,
- const char *expr_prefix,
- lldb::ValueObjectSP &result_valobj_sp,
- Error &error)
-{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
-
- lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
- const lldb::LanguageType language = options.GetLanguage();
- const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny;
- lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
-
- Process *process = exe_ctx.GetProcessPtr();
-
- if (process == NULL || process->GetState() != lldb::eStateStopped)
- {
- if (execution_policy == eExecutionPolicyAlways)
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
-
- error.SetErrorString ("expression needed to run but couldn't");
-
- return execution_results;
- }
- }
-
- if (process == NULL || !process->CanJIT())
- execution_policy = eExecutionPolicyNever;
-
- const char *full_prefix = NULL;
- const char *option_prefix = options.GetPrefix();
- std::string full_prefix_storage;
- if (expr_prefix && option_prefix)
- {
- full_prefix_storage.assign(expr_prefix);
- full_prefix_storage.append(option_prefix);
- if (!full_prefix_storage.empty())
- full_prefix = full_prefix_storage.c_str();
- }
- else if (expr_prefix)
- full_prefix = expr_prefix;
- else
- full_prefix = option_prefix;
-
- lldb::ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, full_prefix, language, desired_type));
-
- StreamString error_stream;
-
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
-
- const bool keep_expression_in_memory = true;
- const bool generate_debug_info = options.GetGenerateDebugInfo();
-
- if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
- {
- error.SetErrorString ("expression interrupted by callback before parse");
- result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
- return lldb::eExpressionInterrupted;
- }
-
- if (!user_expression_sp->Parse (error_stream,
- exe_ctx,
- execution_policy,
- keep_expression_in_memory,
- generate_debug_info))
- {
- execution_results = lldb::eExpressionParseError;
- if (error_stream.GetString().empty())
- error.SetExpressionError (execution_results, "expression failed to parse, unknown error");
- else
- error.SetExpressionError (execution_results, error_stream.GetString().c_str());
- }
- else
- {
- lldb::ClangExpressionVariableSP expr_result;
-
- if (execution_policy == eExecutionPolicyNever &&
- !user_expression_sp->CanInterpret())
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
-
- if (error_stream.GetString().empty())
- error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
- }
- else
- {
- if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
- {
- error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
- result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
- return lldb::eExpressionInterrupted;
- }
-
- error_stream.GetString().clear();
-
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
-
- execution_results = user_expression_sp->Execute (error_stream,
- exe_ctx,
- options,
- user_expression_sp,
- expr_result);
-
- if (options.GetResultIsInternal() && expr_result && process)
- {
- process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result);
- }
-
- if (execution_results != lldb::eExpressionCompleted)
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
-
- if (error_stream.GetString().empty())
- error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
- else
- error.SetExpressionError (execution_results, error_stream.GetString().c_str());
- }
- else
- {
- if (expr_result)
- {
- result_valobj_sp = expr_result->GetValueObject();
-
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==",
- result_valobj_sp->GetValueAsCString());
- }
- else
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
-
- error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
- }
- }
- }
- }
-
- if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
- {
- error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
- return lldb::eExpressionInterrupted;
- }
-
- if (result_valobj_sp.get() == NULL)
- {
- result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
- }
-
- return execution_results;
-}
diff --git a/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp b/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp
index 9307c84..ebcc284 100644
--- a/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/DWARFExpression.cpp
@@ -24,8 +24,8 @@
#include "lldb/Core/Value.h"
#include "lldb/Core/VMRange.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
+#include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h"
+#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/Host.h"
@@ -38,190 +38,27 @@
#include "lldb/Target/StackID.h"
#include "lldb/Target/Thread.h"
+#include "Plugins/SymbolFile/DWARF/DWARFCompileUnit.h"
+
using namespace lldb;
using namespace lldb_private;
-// TODO- why is this also defined (in a better way) in DWARFDefines.cpp?
-const char *
-DW_OP_value_to_name (uint32_t val)
+static lldb::addr_t
+ReadAddressFromDebugAddrSection(const DWARFCompileUnit* dwarf_cu, uint32_t index)
{
- static char invalid[100];
- switch (val) {
- case 0x03: return "DW_OP_addr";
- case 0x06: return "DW_OP_deref";
- case 0x08: return "DW_OP_const1u";
- case 0x09: return "DW_OP_const1s";
- case 0x0a: return "DW_OP_const2u";
- case 0x0b: return "DW_OP_const2s";
- case 0x0c: return "DW_OP_const4u";
- case 0x0d: return "DW_OP_const4s";
- case 0x0e: return "DW_OP_const8u";
- case 0x0f: return "DW_OP_const8s";
- case 0x10: return "DW_OP_constu";
- case 0x11: return "DW_OP_consts";
- case 0x12: return "DW_OP_dup";
- case 0x13: return "DW_OP_drop";
- case 0x14: return "DW_OP_over";
- case 0x15: return "DW_OP_pick";
- case 0x16: return "DW_OP_swap";
- case 0x17: return "DW_OP_rot";
- case 0x18: return "DW_OP_xderef";
- case 0x19: return "DW_OP_abs";
- case 0x1a: return "DW_OP_and";
- case 0x1b: return "DW_OP_div";
- case 0x1c: return "DW_OP_minus";
- case 0x1d: return "DW_OP_mod";
- case 0x1e: return "DW_OP_mul";
- case 0x1f: return "DW_OP_neg";
- case 0x20: return "DW_OP_not";
- case 0x21: return "DW_OP_or";
- case 0x22: return "DW_OP_plus";
- case 0x23: return "DW_OP_plus_uconst";
- case 0x24: return "DW_OP_shl";
- case 0x25: return "DW_OP_shr";
- case 0x26: return "DW_OP_shra";
- case 0x27: return "DW_OP_xor";
- case 0x2f: return "DW_OP_skip";
- case 0x28: return "DW_OP_bra";
- case 0x29: return "DW_OP_eq";
- case 0x2a: return "DW_OP_ge";
- case 0x2b: return "DW_OP_gt";
- case 0x2c: return "DW_OP_le";
- case 0x2d: return "DW_OP_lt";
- case 0x2e: return "DW_OP_ne";
- case 0x30: return "DW_OP_lit0";
- case 0x31: return "DW_OP_lit1";
- case 0x32: return "DW_OP_lit2";
- case 0x33: return "DW_OP_lit3";
- case 0x34: return "DW_OP_lit4";
- case 0x35: return "DW_OP_lit5";
- case 0x36: return "DW_OP_lit6";
- case 0x37: return "DW_OP_lit7";
- case 0x38: return "DW_OP_lit8";
- case 0x39: return "DW_OP_lit9";
- case 0x3a: return "DW_OP_lit10";
- case 0x3b: return "DW_OP_lit11";
- case 0x3c: return "DW_OP_lit12";
- case 0x3d: return "DW_OP_lit13";
- case 0x3e: return "DW_OP_lit14";
- case 0x3f: return "DW_OP_lit15";
- case 0x40: return "DW_OP_lit16";
- case 0x41: return "DW_OP_lit17";
- case 0x42: return "DW_OP_lit18";
- case 0x43: return "DW_OP_lit19";
- case 0x44: return "DW_OP_lit20";
- case 0x45: return "DW_OP_lit21";
- case 0x46: return "DW_OP_lit22";
- case 0x47: return "DW_OP_lit23";
- case 0x48: return "DW_OP_lit24";
- case 0x49: return "DW_OP_lit25";
- case 0x4a: return "DW_OP_lit26";
- case 0x4b: return "DW_OP_lit27";
- case 0x4c: return "DW_OP_lit28";
- case 0x4d: return "DW_OP_lit29";
- case 0x4e: return "DW_OP_lit30";
- case 0x4f: return "DW_OP_lit31";
- case 0x50: return "DW_OP_reg0";
- case 0x51: return "DW_OP_reg1";
- case 0x52: return "DW_OP_reg2";
- case 0x53: return "DW_OP_reg3";
- case 0x54: return "DW_OP_reg4";
- case 0x55: return "DW_OP_reg5";
- case 0x56: return "DW_OP_reg6";
- case 0x57: return "DW_OP_reg7";
- case 0x58: return "DW_OP_reg8";
- case 0x59: return "DW_OP_reg9";
- case 0x5a: return "DW_OP_reg10";
- case 0x5b: return "DW_OP_reg11";
- case 0x5c: return "DW_OP_reg12";
- case 0x5d: return "DW_OP_reg13";
- case 0x5e: return "DW_OP_reg14";
- case 0x5f: return "DW_OP_reg15";
- case 0x60: return "DW_OP_reg16";
- case 0x61: return "DW_OP_reg17";
- case 0x62: return "DW_OP_reg18";
- case 0x63: return "DW_OP_reg19";
- case 0x64: return "DW_OP_reg20";
- case 0x65: return "DW_OP_reg21";
- case 0x66: return "DW_OP_reg22";
- case 0x67: return "DW_OP_reg23";
- case 0x68: return "DW_OP_reg24";
- case 0x69: return "DW_OP_reg25";
- case 0x6a: return "DW_OP_reg26";
- case 0x6b: return "DW_OP_reg27";
- case 0x6c: return "DW_OP_reg28";
- case 0x6d: return "DW_OP_reg29";
- case 0x6e: return "DW_OP_reg30";
- case 0x6f: return "DW_OP_reg31";
- case 0x70: return "DW_OP_breg0";
- case 0x71: return "DW_OP_breg1";
- case 0x72: return "DW_OP_breg2";
- case 0x73: return "DW_OP_breg3";
- case 0x74: return "DW_OP_breg4";
- case 0x75: return "DW_OP_breg5";
- case 0x76: return "DW_OP_breg6";
- case 0x77: return "DW_OP_breg7";
- case 0x78: return "DW_OP_breg8";
- case 0x79: return "DW_OP_breg9";
- case 0x7a: return "DW_OP_breg10";
- case 0x7b: return "DW_OP_breg11";
- case 0x7c: return "DW_OP_breg12";
- case 0x7d: return "DW_OP_breg13";
- case 0x7e: return "DW_OP_breg14";
- case 0x7f: return "DW_OP_breg15";
- case 0x80: return "DW_OP_breg16";
- case 0x81: return "DW_OP_breg17";
- case 0x82: return "DW_OP_breg18";
- case 0x83: return "DW_OP_breg19";
- case 0x84: return "DW_OP_breg20";
- case 0x85: return "DW_OP_breg21";
- case 0x86: return "DW_OP_breg22";
- case 0x87: return "DW_OP_breg23";
- case 0x88: return "DW_OP_breg24";
- case 0x89: return "DW_OP_breg25";
- case 0x8a: return "DW_OP_breg26";
- case 0x8b: return "DW_OP_breg27";
- case 0x8c: return "DW_OP_breg28";
- case 0x8d: return "DW_OP_breg29";
- case 0x8e: return "DW_OP_breg30";
- case 0x8f: return "DW_OP_breg31";
- case 0x90: return "DW_OP_regx";
- case 0x91: return "DW_OP_fbreg";
- case 0x92: return "DW_OP_bregx";
- case 0x93: return "DW_OP_piece";
- case 0x94: return "DW_OP_deref_size";
- case 0x95: return "DW_OP_xderef_size";
- case 0x96: return "DW_OP_nop";
- case 0x97: return "DW_OP_push_object_address";
- case 0x98: return "DW_OP_call2";
- case 0x99: return "DW_OP_call4";
- case 0x9a: return "DW_OP_call_ref";
-// case DW_OP_APPLE_array_ref: return "DW_OP_APPLE_array_ref";
-// case DW_OP_APPLE_extern: return "DW_OP_APPLE_extern";
- case DW_OP_APPLE_uninit: return "DW_OP_APPLE_uninit";
-// case DW_OP_APPLE_assign: return "DW_OP_APPLE_assign";
-// case DW_OP_APPLE_address_of: return "DW_OP_APPLE_address_of";
-// case DW_OP_APPLE_value_of: return "DW_OP_APPLE_value_of";
-// case DW_OP_APPLE_deref_type: return "DW_OP_APPLE_deref_type";
-// case DW_OP_APPLE_expr_local: return "DW_OP_APPLE_expr_local";
-// case DW_OP_APPLE_constf: return "DW_OP_APPLE_constf";
-// case DW_OP_APPLE_scalar_cast: return "DW_OP_APPLE_scalar_cast";
-// case DW_OP_APPLE_clang_cast: return "DW_OP_APPLE_clang_cast";
-// case DW_OP_APPLE_clear: return "DW_OP_APPLE_clear";
-// case DW_OP_APPLE_error: return "DW_OP_APPLE_error";
- default:
- snprintf (invalid, sizeof(invalid), "Unknown DW_OP constant: 0x%x", val);
- return invalid;
- }
+ uint32_t index_size = dwarf_cu->GetAddressByteSize();
+ dw_offset_t addr_base = dwarf_cu->GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ return dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset, index_size);
}
-
//----------------------------------------------------------------------
// DWARFExpression constructor
//----------------------------------------------------------------------
-DWARFExpression::DWARFExpression() :
+DWARFExpression::DWARFExpression(DWARFCompileUnit* dwarf_cu) :
m_module_wp(),
m_data(),
+ m_dwarf_cu(dwarf_cu),
m_reg_kind (eRegisterKindDWARF),
m_loclist_slide (LLDB_INVALID_ADDRESS)
{
@@ -230,15 +67,21 @@ DWARFExpression::DWARFExpression() :
DWARFExpression::DWARFExpression(const DWARFExpression& rhs) :
m_module_wp(rhs.m_module_wp),
m_data(rhs.m_data),
+ m_dwarf_cu(rhs.m_dwarf_cu),
m_reg_kind (rhs.m_reg_kind),
m_loclist_slide(rhs.m_loclist_slide)
{
}
-DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length) :
+DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp,
+ const DataExtractor& data,
+ DWARFCompileUnit* dwarf_cu,
+ lldb::offset_t data_offset,
+ lldb::offset_t data_length) :
m_module_wp(),
m_data(data, data_offset, data_length),
+ m_dwarf_cu(dwarf_cu),
m_reg_kind (eRegisterKindDWARF),
m_loclist_slide(LLDB_INVALID_ADDRESS)
{
@@ -624,6 +467,12 @@ DWARFExpression::DumpLocation (Stream *s, lldb::offset_t offset, lldb::offset_t
case DW_OP_form_tls_address:
s->PutCString("DW_OP_form_tls_address"); // 0x9b
break;
+ case DW_OP_GNU_addr_index: // 0xfb
+ s->Printf("DW_OP_GNU_addr_index(0x%" PRIx64 ")", m_data.GetULEB128(&offset));
+ break;
+ case DW_OP_GNU_const_index: // 0xfc
+ s->Printf("DW_OP_GNU_const_index(0x%" PRIx64 ")", m_data.GetULEB128(&offset));
+ break;
case DW_OP_GNU_push_tls_address:
s->PutCString("DW_OP_GNU_push_tls_address"); // 0xe0
break;
@@ -709,8 +558,14 @@ DWARFExpression::GetDescription (Stream *s, lldb::DescriptionLevel level, addr_t
addr_t curr_base_addr = location_list_base_addr;
while (m_data.ValidOffset(offset))
{
- lldb::addr_t begin_addr_offset = m_data.GetAddress(&offset);
- lldb::addr_t end_addr_offset = m_data.GetAddress(&offset);
+ addr_t begin_addr_offset = LLDB_INVALID_ADDRESS;
+ addr_t end_addr_offset = LLDB_INVALID_ADDRESS;
+ if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, begin_addr_offset, end_addr_offset))
+ break;
+
+ if (begin_addr_offset == 0 && end_addr_offset == 0)
+ break;
+
if (begin_addr_offset < end_addr_offset)
{
if (count > 0)
@@ -723,11 +578,6 @@ DWARFExpression::GetDescription (Stream *s, lldb::DescriptionLevel level, addr_t
s->PutChar('}');
offset += location_length;
}
- else if (begin_addr_offset == 0 && end_addr_offset == 0)
- {
- // The end of the location list is marked by both the start and end offset being zero
- break;
- }
else
{
if ((m_data.GetAddressByteSize() == 4 && (begin_addr_offset == UINT32_MAX)) ||
@@ -1027,8 +877,10 @@ GetOpcodeDataSize (const DataExtractor &data, const lldb::offset_t data_offset,
case DW_OP_regx: // 0x90 1 ULEB128 register
case DW_OP_fbreg: // 0x91 1 SLEB128 offset
case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed
+ case DW_OP_GNU_addr_index: // 0xfb 1 ULEB128 index
+ case DW_OP_GNU_const_index: // 0xfc 1 ULEB128 index
data.Skip_LEB128(&offset);
- return offset - data_offset;
+ return offset - data_offset;
// All opcodes that have a 2 ULEB (signed or unsigned) arguments
case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset
@@ -1070,6 +922,22 @@ DWARFExpression::GetLocation_DW_OP_addr (uint32_t op_addr_idx, bool &error) cons
else
++curr_op_addr_idx;
}
+ else if (op == DW_OP_GNU_addr_index)
+ {
+ uint64_t index = m_data.GetULEB128(&offset);
+ if (curr_op_addr_idx == op_addr_idx)
+ {
+ if (!m_dwarf_cu)
+ {
+ error = true;
+ break;
+ }
+
+ return ReadAddressFromDebugAddrSection(m_dwarf_cu, index);
+ }
+ else
+ ++curr_op_addr_idx;
+ }
else
{
const offset_t op_arg_size = GetOpcodeDataSize (m_data, offset, op);
@@ -1104,7 +972,7 @@ DWARFExpression::Update_DW_OP_addr (lldb::addr_t file_addr)
// So first we copy the data into a heap buffer
std::unique_ptr<DataBufferHeap> head_data_ap (new DataBufferHeap (m_data.GetDataStart(),
- m_data.GetByteSize()));
+ m_data.GetByteSize()));
// Make en encoder so we can write the address into the buffer using
// the correct byte order (endianness)
@@ -1150,20 +1018,21 @@ DWARFExpression::LocationListContainsAddress (lldb::addr_t loclist_base_addr, ll
while (m_data.ValidOffset(offset))
{
// We need to figure out what the value is for the location.
- addr_t lo_pc = m_data.GetAddress(&offset);
- addr_t hi_pc = m_data.GetAddress(&offset);
+ addr_t lo_pc = LLDB_INVALID_ADDRESS;
+ addr_t hi_pc = LLDB_INVALID_ADDRESS;
+ if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc))
+ break;
+
if (lo_pc == 0 && hi_pc == 0)
break;
- else
- {
- lo_pc += loclist_base_addr - m_loclist_slide;
- hi_pc += loclist_base_addr - m_loclist_slide;
- if (lo_pc <= addr && addr < hi_pc)
- return true;
+ lo_pc += loclist_base_addr - m_loclist_slide;
+ hi_pc += loclist_base_addr - m_loclist_slide;
- offset += m_data.GetU16(&offset);
- }
+ if (lo_pc <= addr && addr < hi_pc)
+ return true;
+
+ offset += m_data.GetU16(&offset);
}
}
return false;
@@ -1186,24 +1055,23 @@ DWARFExpression::GetLocation (addr_t base_addr, addr_t pc, lldb::offset_t &offse
while (m_data.ValidOffset(offset))
{
// We need to figure out what the value is for the location.
- addr_t lo_pc = m_data.GetAddress(&offset);
- addr_t hi_pc = m_data.GetAddress(&offset);
+ addr_t lo_pc = LLDB_INVALID_ADDRESS;
+ addr_t hi_pc = LLDB_INVALID_ADDRESS;
+ if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc))
+ break;
+
if (lo_pc == 0 && hi_pc == 0)
- {
break;
- }
- else
- {
- lo_pc += curr_base_addr - m_loclist_slide;
- hi_pc += curr_base_addr - m_loclist_slide;
-
- length = m_data.GetU16(&offset);
-
- if (length > 0 && lo_pc <= pc && pc < hi_pc)
- return true;
- offset += length;
- }
+ lo_pc += curr_base_addr - m_loclist_slide;
+ hi_pc += curr_base_addr - m_loclist_slide;
+
+ length = m_data.GetU16(&offset);
+
+ if (length > 0 && lo_pc <= pc && pc < hi_pc)
+ return true;
+
+ offset += length;
}
}
offset = LLDB_INVALID_OFFSET;
@@ -1295,25 +1163,36 @@ DWARFExpression::Evaluate
while (m_data.ValidOffset(offset))
{
// We need to figure out what the value is for the location.
- addr_t lo_pc = m_data.GetAddress(&offset);
- addr_t hi_pc = m_data.GetAddress(&offset);
+ addr_t lo_pc = LLDB_INVALID_ADDRESS;
+ addr_t hi_pc = LLDB_INVALID_ADDRESS;
+ if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc))
+ break;
+
if (lo_pc == 0 && hi_pc == 0)
- {
break;
- }
- else
- {
- lo_pc += curr_loclist_base_load_addr - m_loclist_slide;
- hi_pc += curr_loclist_base_load_addr - m_loclist_slide;
- uint16_t length = m_data.GetU16(&offset);
+ lo_pc += curr_loclist_base_load_addr - m_loclist_slide;
+ hi_pc += curr_loclist_base_load_addr - m_loclist_slide;
- if (length > 0 && lo_pc <= pc && pc < hi_pc)
- {
- return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr);
- }
- offset += length;
+ uint16_t length = m_data.GetU16(&offset);
+
+ if (length > 0 && lo_pc <= pc && pc < hi_pc)
+ {
+ return DWARFExpression::Evaluate (exe_ctx,
+ expr_locals,
+ decl_map,
+ reg_ctx,
+ module_sp,
+ m_data,
+ m_dwarf_cu,
+ offset,
+ length,
+ m_reg_kind,
+ initial_value_ptr,
+ result,
+ error_ptr);
}
+ offset += length;
}
}
if (error_ptr)
@@ -1322,7 +1201,19 @@ DWARFExpression::Evaluate
}
// Not a location list, just a single expression.
- return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr);
+ return DWARFExpression::Evaluate (exe_ctx,
+ expr_locals,
+ decl_map,
+ reg_ctx,
+ module_sp,
+ m_data,
+ m_dwarf_cu,
+ 0,
+ m_data.GetByteSize(),
+ m_reg_kind,
+ initial_value_ptr,
+ result,
+ error_ptr);
}
@@ -1336,6 +1227,7 @@ DWARFExpression::Evaluate
RegisterContext *reg_ctx,
lldb::ModuleSP module_sp,
const DataExtractor& opcodes,
+ DWARFCompileUnit* dwarf_cu,
const lldb::offset_t opcodes_offset,
const lldb::offset_t opcodes_length,
const lldb::RegisterKind reg_kind,
@@ -2711,7 +2603,7 @@ DWARFExpression::Evaluate
return false;
}
}
- else if (!stack.empty())
+ else
{
// If this is the second or later piece there should be a value on the stack
if (pieces.GetBuffer().GetByteSize() != op_piece_offset)
@@ -2950,6 +2842,69 @@ DWARFExpression::Evaluate
}
break;
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_GNU_addr_index
+ // OPERANDS: 1
+ // ULEB128: index to the .debug_addr section
+ // DESCRIPTION: Pushes an address to the stack from the .debug_addr
+ // section with the base address specified by the DW_AT_addr_base
+ // attribute and the 0 based index is the ULEB128 encoded index.
+ //----------------------------------------------------------------------
+ case DW_OP_GNU_addr_index:
+ {
+ if (!dwarf_cu)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString ("DW_OP_GNU_addr_index found without a compile unit being specified");
+ return false;
+ }
+ uint64_t index = opcodes.GetULEB128(&offset);
+ uint32_t index_size = dwarf_cu->GetAddressByteSize();
+ dw_offset_t addr_base = dwarf_cu->GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ uint64_t value = dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset, index_size);
+ stack.push_back(Scalar(value));
+ stack.back().SetValueType(Value::eValueTypeFileAddress);
+ }
+ break;
+
+ //----------------------------------------------------------------------
+ // OPCODE: DW_OP_GNU_const_index
+ // OPERANDS: 1
+ // ULEB128: index to the .debug_addr section
+ // DESCRIPTION: Pushes an constant with the size of a machine address to
+ // the stack from the .debug_addr section with the base address specified
+ // by the DW_AT_addr_base attribute and the 0 based index is the ULEB128
+ // encoded index.
+ //----------------------------------------------------------------------
+ case DW_OP_GNU_const_index:
+ {
+ if (!dwarf_cu)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString ("DW_OP_GNU_const_index found without a compile unit being specified");
+ return false;
+ }
+ uint64_t index = opcodes.GetULEB128(&offset);
+ uint32_t index_size = dwarf_cu->GetAddressByteSize();
+ dw_offset_t addr_base = dwarf_cu->GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ const DWARFDataExtractor& debug_addr = dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data();
+ switch (index_size)
+ {
+ case 4:
+ stack.push_back(Scalar(debug_addr.GetU32(&offset)));
+ break;
+ case 8:
+ stack.push_back(Scalar(debug_addr.GetU64(&offset)));
+ break;
+ default:
+ assert(false && "Unhandled index size");
+ return false;
+ }
+ }
+ break;
+
default:
if (log)
log->Printf("Unhandled opcode %s in DWARFExpression.", DW_OP_value_to_name(op));
@@ -2990,3 +2945,255 @@ DWARFExpression::Evaluate
return true; // Return true on success
}
+size_t
+DWARFExpression::LocationListSize(const DWARFCompileUnit* dwarf_cu,
+ const DataExtractor& debug_loc_data,
+ lldb::offset_t offset)
+{
+ const lldb::offset_t debug_loc_offset = offset;
+ while (debug_loc_data.ValidOffset(offset))
+ {
+ lldb::addr_t start_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t end_addr = LLDB_INVALID_ADDRESS;
+ if (!AddressRangeForLocationListEntry(dwarf_cu, debug_loc_data, &offset, start_addr, end_addr))
+ break;
+
+ if (start_addr == 0 && end_addr == 0)
+ break;
+
+ uint16_t loc_length = debug_loc_data.GetU16(&offset);
+ offset += loc_length;
+ }
+
+ if (offset > debug_loc_offset)
+ return offset - debug_loc_offset;
+ return 0;
+}
+
+bool
+DWARFExpression::AddressRangeForLocationListEntry(const DWARFCompileUnit* dwarf_cu,
+ const DataExtractor& debug_loc_data,
+ lldb::offset_t* offset_ptr,
+ lldb::addr_t& low_pc,
+ lldb::addr_t& high_pc)
+{
+ if (!debug_loc_data.ValidOffset(*offset_ptr))
+ return false;
+
+ switch (dwarf_cu->GetSymbolFileDWARF()->GetLocationListFormat())
+ {
+ case NonLocationList:
+ return false;
+ case RegularLocationList:
+ low_pc = debug_loc_data.GetAddress(offset_ptr);
+ high_pc = debug_loc_data.GetAddress(offset_ptr);
+ return true;
+ case SplitDwarfLocationList:
+ switch (debug_loc_data.GetU8(offset_ptr))
+ {
+ case DW_LLE_end_of_list_entry:
+ return false;
+ case DW_LLE_start_end_entry:
+ {
+ uint64_t index = debug_loc_data.GetULEB128(offset_ptr);
+ low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index);
+ index = debug_loc_data.GetULEB128(offset_ptr);
+ high_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index);
+ return true;
+ }
+ case DW_LLE_start_length_entry:
+ {
+ uint64_t index = debug_loc_data.GetULEB128(offset_ptr);
+ low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index);
+ uint32_t length = debug_loc_data.GetU32(offset_ptr);
+ high_pc = low_pc + length;
+ return true;
+ }
+ default:
+ // Not supported entry type
+ return false;
+ }
+ }
+ assert (false && "Not supported location list type");
+ return false;
+}
+
+static bool
+print_dwarf_exp_op (Stream &s,
+ const DataExtractor& data,
+ lldb::offset_t *offset_ptr,
+ int address_size,
+ int dwarf_ref_size)
+{
+ uint8_t opcode = data.GetU8(offset_ptr);
+ DRC_class opcode_class;
+ uint64_t uint;
+ int64_t sint;
+
+ int size;
+
+ opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3);
+
+ s.Printf("%s ", DW_OP_value_to_name (opcode));
+
+ /* Does this take zero parameters? If so we can shortcut this function. */
+ if (opcode_class == DRC_ZEROOPERANDS)
+ return true;
+
+ if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx)
+ {
+ uint = data.GetULEB128(offset_ptr);
+ sint = data.GetSLEB128(offset_ptr);
+ s.Printf("%" PRIu64 " %" PRIi64, uint, sint);
+ return true;
+ }
+ if (opcode_class != DRC_ONEOPERAND)
+ {
+ s.Printf("UNKNOWN OP %u", opcode);
+ return false;
+ }
+
+ switch (opcode)
+ {
+ case DW_OP_addr: size = address_size; break;
+ case DW_OP_const1u: size = 1; break;
+ case DW_OP_const1s: size = -1; break;
+ case DW_OP_const2u: size = 2; break;
+ case DW_OP_const2s: size = -2; break;
+ case DW_OP_const4u: size = 4; break;
+ case DW_OP_const4s: size = -4; break;
+ case DW_OP_const8u: size = 8; break;
+ case DW_OP_const8s: size = -8; break;
+ case DW_OP_constu: size = 128; break;
+ case DW_OP_consts: size = -128; break;
+ case DW_OP_fbreg: size = -128; break;
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31:
+ size = -128; break;
+ case DW_OP_pick:
+ case DW_OP_deref_size:
+ case DW_OP_xderef_size:
+ size = 1; break;
+ case DW_OP_skip:
+ case DW_OP_bra:
+ size = -2; break;
+ case DW_OP_call2:
+ size = 2; break;
+ case DW_OP_call4:
+ size = 4; break;
+ case DW_OP_call_ref:
+ size = dwarf_ref_size; break;
+ case DW_OP_piece:
+ case DW_OP_plus_uconst:
+ case DW_OP_regx:
+ case DW_OP_GNU_addr_index:
+ case DW_OP_GNU_const_index:
+ size = 128; break;
+ default:
+ s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
+ return true;
+ }
+
+ switch (size)
+ {
+ case -1: sint = (int8_t) data.GetU8(offset_ptr); s.Printf("%+" PRIi64, sint); break;
+ case -2: sint = (int16_t) data.GetU16(offset_ptr); s.Printf("%+" PRIi64, sint); break;
+ case -4: sint = (int32_t) data.GetU32(offset_ptr); s.Printf("%+" PRIi64, sint); break;
+ case -8: sint = (int64_t) data.GetU64(offset_ptr); s.Printf("%+" PRIi64, sint); break;
+ case -128: sint = data.GetSLEB128(offset_ptr); s.Printf("%+" PRIi64, sint); break;
+ case 1: uint = data.GetU8(offset_ptr); s.Printf("0x%2.2" PRIx64, uint); break;
+ case 2: uint = data.GetU16(offset_ptr); s.Printf("0x%4.4" PRIx64, uint); break;
+ case 4: uint = data.GetU32(offset_ptr); s.Printf("0x%8.8" PRIx64, uint); break;
+ case 8: uint = data.GetU64(offset_ptr); s.Printf("0x%16.16" PRIx64, uint); break;
+ case 128: uint = data.GetULEB128(offset_ptr); s.Printf("0x%" PRIx64, uint); break;
+ }
+
+ return false;
+}
+
+bool
+DWARFExpression::PrintDWARFExpression(Stream &s,
+ const DataExtractor& data,
+ int address_size,
+ int dwarf_ref_size,
+ bool location_expression)
+{
+ int op_count = 0;
+ lldb::offset_t offset = 0;
+ while (data.ValidOffset(offset))
+ {
+ if (location_expression && op_count > 0)
+ return false;
+ if (op_count > 0)
+ s.PutCString(", ");
+ if (!print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size))
+ return false;
+ op_count++;
+ }
+
+ return true;
+}
+
+void
+DWARFExpression::PrintDWARFLocationList(Stream &s,
+ const DWARFCompileUnit* cu,
+ const DataExtractor& debug_loc_data,
+ lldb::offset_t offset)
+{
+ uint64_t start_addr, end_addr;
+ uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu);
+ s.SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu));
+ dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
+ while (debug_loc_data.ValidOffset(offset))
+ {
+ start_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
+ end_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
+
+ if (start_addr == 0 && end_addr == 0)
+ break;
+
+ s.PutCString("\n ");
+ s.Indent();
+ if (cu)
+ s.AddressRange (start_addr + base_addr,
+ end_addr + base_addr,
+ cu->GetAddressByteSize(),
+ NULL,
+ ": ");
+ uint32_t loc_length = debug_loc_data.GetU16(&offset);
+
+ DataExtractor locationData(debug_loc_data, offset, loc_length);
+ PrintDWARFExpression (s, locationData, addr_size, 4, false);
+ offset += loc_length;
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Expression/Expression.cpp b/contrib/llvm/tools/lldb/source/Expression/Expression.cpp
new file mode 100644
index 0000000..e5dd9c0
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Expression/Expression.cpp
@@ -0,0 +1,32 @@
+//===-- Expression.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/Expression.h"
+#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb_private;
+
+Expression::Expression (Target &target) :
+ m_target_wp (target.shared_from_this()),
+ m_jit_start_addr (LLDB_INVALID_ADDRESS),
+ m_jit_end_addr (LLDB_INVALID_ADDRESS)
+{
+ // Can't make any kind of expression without a target.
+ assert (m_target_wp.lock());
+}
+
+Expression::Expression (ExecutionContextScope &exe_scope) :
+ m_target_wp (exe_scope.CalculateTarget()),
+ m_jit_start_addr (LLDB_INVALID_ADDRESS),
+ m_jit_end_addr (LLDB_INVALID_ADDRESS)
+{
+ assert (m_target_wp.lock());
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp b/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp
index 9a42510..c4ab7a9 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/ExpressionSourceCode.cpp
@@ -10,9 +10,12 @@
#include "lldb/Expression/ExpressionSourceCode.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
+#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/StackFrame.h"
@@ -56,6 +59,121 @@ extern "C"
}
)";
+namespace {
+
+class AddMacroState
+{
+ enum State
+ {
+ CURRENT_FILE_NOT_YET_PUSHED,
+ CURRENT_FILE_PUSHED,
+ CURRENT_FILE_POPPED
+ };
+
+public:
+ AddMacroState(const FileSpec &current_file, const uint32_t current_file_line)
+ : m_state(CURRENT_FILE_NOT_YET_PUSHED),
+ m_current_file(current_file),
+ m_current_file_line(current_file_line)
+ { }
+
+ void
+ StartFile(const FileSpec &file)
+ {
+ m_file_stack.push_back(file);
+ if (file == m_current_file)
+ m_state = CURRENT_FILE_PUSHED;
+ }
+
+ void
+ EndFile()
+ {
+ if (m_file_stack.size() == 0)
+ return;
+
+ FileSpec old_top = m_file_stack.back();
+ m_file_stack.pop_back();
+ if (old_top == m_current_file)
+ m_state = CURRENT_FILE_POPPED;
+ }
+
+ // An entry is valid if it occurs before the current line in
+ // the current file.
+ bool
+ IsValidEntry(uint32_t line)
+ {
+ switch (m_state)
+ {
+ case CURRENT_FILE_NOT_YET_PUSHED:
+ return true;
+ case CURRENT_FILE_POPPED:
+ return false;
+ case CURRENT_FILE_PUSHED:
+ // If we are in file included in the current file,
+ // the entry should be added.
+ if (m_file_stack.back() != m_current_file)
+ return true;
+
+ if (line >= m_current_file_line)
+ return false;
+ else
+ return true;
+ }
+ }
+
+private:
+ std::vector<FileSpec> m_file_stack;
+ State m_state;
+ FileSpec m_current_file;
+ uint32_t m_current_file_line;
+};
+
+} // anonymous namespace
+
+static void
+AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream)
+{
+ if (dm == nullptr)
+ return;
+
+ for (size_t i = 0; i < dm->GetNumMacroEntries(); i++)
+ {
+ const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i);
+ uint32_t line;
+
+ switch (entry.GetType())
+ {
+ case DebugMacroEntry::DEFINE:
+ if (state.IsValidEntry(entry.GetLineNumber()))
+ stream.Printf("#define %s\n", entry.GetMacroString().AsCString());
+ else
+ return;
+ break;
+ case DebugMacroEntry::UNDEF:
+ if (state.IsValidEntry(entry.GetLineNumber()))
+ stream.Printf("#undef %s\n", entry.GetMacroString().AsCString());
+ else
+ return;
+ break;
+ case DebugMacroEntry::START_FILE:
+ line = entry.GetLineNumber();
+ if (state.IsValidEntry(line))
+ state.StartFile(entry.GetFileSpec(comp_unit));
+ else
+ return;
+ break;
+ case DebugMacroEntry::END_FILE:
+ state.EndFile();
+ break;
+ case DebugMacroEntry::INDIRECT:
+ AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream);
+ break;
+ default:
+ // This is an unknown/invalid entry. Ignore.
+ break;
+ }
+ }
+}
bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const
{
@@ -82,7 +200,8 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor())
{
- const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = target->GetPersistentVariables().GetHandLoadedClangModules();
+ ClangPersistentVariables *persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
+ const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules();
ClangModulesDeclVendor::ModuleVector modules_for_macros;
for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
@@ -118,6 +237,23 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
}
}
+
+ StreamString debug_macros_stream;
+ if (StackFrame *frame = exe_ctx.GetFramePtr())
+ {
+ const SymbolContext &sc = frame->GetSymbolContext(
+ lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry);
+
+ if (sc.comp_unit && sc.line_entry.IsValid())
+ {
+ DebugMacros *dm = sc.comp_unit->GetDebugMacros();
+ if (dm)
+ {
+ AddMacroState state(sc.line_entry.file, sc.line_entry.line);
+ AddMacros(dm, sc.comp_unit, state, debug_macros_stream);
+ }
+ }
+ }
if (m_wrap)
{
@@ -133,8 +269,9 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi
StreamString wrap_stream;
- wrap_stream.Printf("%s\n%s\n%s\n%s\n",
+ wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n",
module_macros.c_str(),
+ debug_macros_stream.GetData(),
g_expression_prefix,
target_specific_defines,
m_prefix.c_str());
diff --git a/contrib/llvm/tools/lldb/source/Expression/ExpressionVariable.cpp b/contrib/llvm/tools/lldb/source/Expression/ExpressionVariable.cpp
new file mode 100644
index 0000000..8bef60f
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Expression/ExpressionVariable.cpp
@@ -0,0 +1,36 @@
+//===-- ExpressionVariable.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/ExpressionVariable.h"
+
+using namespace lldb_private;
+
+ExpressionVariable::~ExpressionVariable()
+{
+}
+
+uint8_t *
+ExpressionVariable::GetValueBytes()
+{
+ const size_t byte_size = m_frozen_sp->GetByteSize();
+ if (byte_size > 0)
+ {
+ if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size)
+ {
+ m_frozen_sp->GetValue().ResizeData(byte_size);
+ m_frozen_sp->GetValue().GetData (m_frozen_sp->GetDataExtractor());
+ }
+ return const_cast<uint8_t *>(m_frozen_sp->GetDataExtractor().GetDataStart());
+ }
+ return NULL;
+}
+
+PersistentExpressionState::~PersistentExpressionState ()
+{
+}
diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangFunction.cpp b/contrib/llvm/tools/lldb/source/Expression/FunctionCaller.cpp
index b438dac..ddc378d 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ClangFunction.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/FunctionCaller.cpp
@@ -1,4 +1,4 @@
-//===-- ClangFunction.cpp ---------------------------------------*- C++ -*-===//
+//===-- FunctionCaller.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,15 +11,6 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/CodeGen/CodeGenAction.h"
-#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/IR/Module.h"
// Project includes
#include "lldb/Core/DataExtractor.h"
@@ -28,12 +19,9 @@
#include "lldb/Core/State.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectList.h"
-#include "lldb/Expression/ASTStructExtractor.h"
-#include "lldb/Expression/ClangExpressionParser.h"
-#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/ExecutionContext.h"
@@ -47,16 +35,17 @@
using namespace lldb_private;
//----------------------------------------------------------------------
-// ClangFunction constructor
+// FunctionCaller constructor
//----------------------------------------------------------------------
-ClangFunction::ClangFunction
+FunctionCaller::FunctionCaller
(
ExecutionContextScope &exe_scope,
- const ClangASTType &return_type,
+ const CompilerType &return_type,
const Address& functionAddress,
const ValueList &arg_value_list,
const char *name
) :
+ Expression (exe_scope),
m_execution_unit_sp(),
m_parser(),
m_jit_module_wp(),
@@ -72,41 +61,14 @@ ClangFunction::ClangFunction
m_JITted (false)
{
m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
- // Can't make a ClangFunction without a process.
+ // Can't make a FunctionCaller without a process.
assert (m_jit_process_wp.lock());
}
-ClangFunction::ClangFunction
-(
- ExecutionContextScope &exe_scope,
- Function &function,
- ClangASTContext *ast_context,
- const ValueList &arg_value_list,
- const char *name
-) :
- m_name (name ? name : "<unknown>"),
- m_function_ptr (&function),
- m_function_addr (),
- m_function_return_type (),
- m_wrapper_function_name ("__lldb_function_caller"),
- m_wrapper_struct_name ("__lldb_caller_struct"),
- m_wrapper_args_addrs (),
- m_arg_values (arg_value_list),
- m_compiled (false),
- m_JITted (false)
-{
- m_jit_process_wp = exe_scope.CalculateProcess();
- // Can't make a ClangFunction without a process.
- assert (m_jit_process_wp.lock());
-
- m_function_addr = m_function_ptr->GetAddressRange().GetBaseAddress();
- m_function_return_type = m_function_ptr->GetClangType().GetFunctionReturnType();
-}
-
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-ClangFunction::~ClangFunction()
+FunctionCaller::~FunctionCaller()
{
lldb::ProcessSP process_sp (m_jit_process_wp.lock());
if (process_sp)
@@ -117,147 +79,8 @@ ClangFunction::~ClangFunction()
}
}
-unsigned
-ClangFunction::CompileFunction (Stream &errors)
-{
- if (m_compiled)
- return 0;
-
- // FIXME: How does clang tell us there's no return value? We need to handle that case.
- unsigned num_errors = 0;
-
- std::string return_type_str (m_function_return_type.GetTypeName().AsCString(""));
-
- // Cons up the function we're going to wrap our call in, then compile it...
- // We declare the function "extern "C"" because the compiler might be in C++
- // mode which would mangle the name and then we couldn't find it again...
- m_wrapper_function_text.clear();
- m_wrapper_function_text.append ("extern \"C\" void ");
- m_wrapper_function_text.append (m_wrapper_function_name);
- m_wrapper_function_text.append (" (void *input)\n{\n struct ");
- m_wrapper_function_text.append (m_wrapper_struct_name);
- m_wrapper_function_text.append (" \n {\n");
- m_wrapper_function_text.append (" ");
- m_wrapper_function_text.append (return_type_str);
- m_wrapper_function_text.append (" (*fn_ptr) (");
-
- // Get the number of arguments. If we have a function type and it is prototyped,
- // trust that, otherwise use the values we were given.
-
- // FIXME: This will need to be extended to handle Variadic functions. We'll need
- // to pull the defined arguments out of the function, then add the types from the
- // arguments list for the variable arguments.
-
- uint32_t num_args = UINT32_MAX;
- bool trust_function = false;
- // GetArgumentCount returns -1 for an unprototyped function.
- ClangASTType function_clang_type;
- if (m_function_ptr)
- {
- function_clang_type = m_function_ptr->GetClangType();
- if (function_clang_type)
- {
- int num_func_args = function_clang_type.GetFunctionArgumentCount();
- if (num_func_args >= 0)
- {
- trust_function = true;
- num_args = num_func_args;
- }
- }
- }
-
- if (num_args == UINT32_MAX)
- num_args = m_arg_values.GetSize();
-
- std::string args_buffer; // This one stores the definition of all the args in "struct caller".
- std::string args_list_buffer; // This one stores the argument list called from the structure.
- for (size_t i = 0; i < num_args; i++)
- {
- std::string type_name;
-
- if (trust_function)
- {
- type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString("");
- }
- else
- {
- ClangASTType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetClangType ();
- if (clang_qual_type)
- {
- type_name = clang_qual_type.GetTypeName().AsCString("");
- }
- else
- {
- errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i);
- return 1;
- }
- }
-
- m_wrapper_function_text.append (type_name);
- if (i < num_args - 1)
- m_wrapper_function_text.append (", ");
-
- char arg_buf[32];
- args_buffer.append (" ");
- args_buffer.append (type_name);
- snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i);
- args_buffer.push_back (' ');
- args_buffer.append (arg_buf);
- args_buffer.append (";\n");
-
- args_list_buffer.append ("__lldb_fn_data->");
- args_list_buffer.append (arg_buf);
- if (i < num_args - 1)
- args_list_buffer.append (", ");
-
- }
- m_wrapper_function_text.append (");\n"); // Close off the function calling prototype.
-
- m_wrapper_function_text.append (args_buffer);
-
- m_wrapper_function_text.append (" ");
- m_wrapper_function_text.append (return_type_str);
- m_wrapper_function_text.append (" return_value;");
- m_wrapper_function_text.append ("\n };\n struct ");
- m_wrapper_function_text.append (m_wrapper_struct_name);
- m_wrapper_function_text.append ("* __lldb_fn_data = (struct ");
- m_wrapper_function_text.append (m_wrapper_struct_name);
- m_wrapper_function_text.append (" *) input;\n");
-
- m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
- m_wrapper_function_text.append (args_list_buffer);
- m_wrapper_function_text.append (");\n}\n");
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- if (log)
- log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str());
-
- // Okay, now compile this expression
-
- lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
- if (jit_process_sp)
- {
- const bool generate_debug_info = true;
- m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info));
-
- num_errors = m_parser->Parse (errors);
- }
- else
- {
- errors.Printf("no process - unable to inject function");
- num_errors = 1;
- }
-
- m_compiled = (num_errors == 0);
-
- if (!m_compiled)
- return num_errors;
-
- return num_errors;
-}
-
bool
-ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
+FunctionCaller::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
{
Process *process = exe_ctx.GetProcessPtr();
@@ -310,18 +133,17 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
}
bool
-ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
+FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
{
- return WriteFunctionArguments(exe_ctx, args_addr_ref, m_function_addr, m_arg_values, errors);
+ return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, errors);
}
// FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function.
bool
-ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
+FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx,
lldb::addr_t &args_addr_ref,
- Address function_address,
- ValueList &arg_values,
+ ValueList &arg_values,
Stream &errors)
{
// All the information to reconstruct the struct is provided by the
@@ -333,7 +155,6 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
}
Error error;
- using namespace clang;
lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
Process *process = exe_ctx.GetProcessPtr();
@@ -363,7 +184,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
}
// TODO: verify fun_addr needs to be a callable address
- Scalar fun_addr (function_address.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
+ Scalar fun_addr (m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
uint64_t first_offset = m_member_offsets[0];
process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error);
@@ -391,7 +212,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
if (arg_value->GetValueType() == Value::eValueTypeHostAddress &&
arg_value->GetContextType() == Value::eContextTypeInvalid &&
- arg_value->GetClangType().IsPointerType())
+ arg_value->GetCompilerType().IsPointerType())
continue;
const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx);
@@ -404,10 +225,8 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
}
bool
-ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
+FunctionCaller::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
{
- using namespace clang;
-
if (CompileFunction(errors) != 0)
return false;
if (!WriteFunctionWrapper(exe_ctx, errors))
@@ -423,7 +242,7 @@ ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_add
}
lldb::ThreadPlanSP
-ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
+FunctionCaller::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::addr_t args_addr,
const EvaluateExpressionOptions &options,
Stream &errors)
@@ -431,7 +250,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("-- [ClangFunction::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str());
+ log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str());
// FIXME: Use the errors Stream for better error reporting.
Thread *thread = exe_ctx.GetThreadPtr();
@@ -449,7 +268,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::ThreadPlanSP new_plan_sp (new ThreadPlanCallFunction (*thread,
wrapper_address,
- ClangASTType(),
+ CompilerType(),
args,
options));
new_plan_sp->SetIsMasterPlan(true);
@@ -458,17 +277,17 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
}
bool
-ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value)
+FunctionCaller::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value)
{
// Read the return value - it is the last field in the struct:
// FIXME: How does clang tell us there's no return value? We need to handle that case.
- // FIXME: Create our ThreadPlanCallFunction with the return ClangASTType, and then use GetReturnValueObject
+ // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and then use GetReturnValueObject
// to fetch the value. That way we can fetch any values we need.
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("-- [ClangFunction::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str());
+ log->Printf("-- [FunctionCaller::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str());
Process *process = exe_ctx.GetProcessPtr();
@@ -486,13 +305,13 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t arg
if (error.Fail())
return false;
- ret_value.SetClangType(m_function_return_type);
+ ret_value.SetCompilerType(m_function_return_type);
ret_value.SetValueType(Value::eValueTypeScalar);
return true;
}
void
-ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr)
+FunctionCaller::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr)
{
std::list<lldb::addr_t>::iterator pos;
pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr);
@@ -503,17 +322,16 @@ ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_
}
lldb::ExpressionResults
-ClangFunction::ExecuteFunction(
+FunctionCaller::ExecuteFunction(
ExecutionContext &exe_ctx,
lldb::addr_t *args_addr_ptr,
const EvaluateExpressionOptions &options,
Stream &errors,
Value &results)
{
- using namespace clang;
lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
- // ClangFunction::ExecuteFunction execution is always just to get the result. Do make sure we ignore
+ // FunctionCaller::ExecuteFunction execution is always just to get the result. Do make sure we ignore
// breakpoints, unwind on error, and don't try to debug it.
EvaluateExpressionOptions real_options = options;
real_options.SetDebug(false);
@@ -539,7 +357,7 @@ ClangFunction::ExecuteFunction(
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
+ log->Printf("== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx,
args_addr,
@@ -562,11 +380,11 @@ ClangFunction::ExecuteFunction(
{
if (return_value != lldb::eExpressionCompleted)
{
- log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str());
+ log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str());
}
else
{
- log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str());
+ log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str());
}
}
@@ -586,11 +404,3 @@ ClangFunction::ExecuteFunction(
return lldb::eExpressionCompleted;
}
-
-clang::ASTConsumer *
-ClangFunction::ASTTransformer (clang::ASTConsumer *passthrough)
-{
- m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_wrapper_struct_name.c_str(), *this));
-
- return m_struct_extractor.get();
-}
diff --git a/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp b/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp
index aa5d28b..30d7f63 100644
--- a/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/IRDynamicChecks.cpp
@@ -1,4 +1,4 @@
-//===-- IRDynamicChecks.cpp -------------------------------------------*- C++ -*-===//
+//===-- IRDynamicChecks.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,23 +7,28 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Value.h"
+
+// Project includes
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
-
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/Module.h"
-#include "llvm/IR/Value.h"
+#include "lldb/Target/Target.h"
using namespace llvm;
using namespace lldb_private;
@@ -40,20 +45,22 @@ static const char g_valid_pointer_check_text[] =
" unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n"
"}";
-DynamicCheckerFunctions::DynamicCheckerFunctions ()
-{
-}
+DynamicCheckerFunctions::DynamicCheckerFunctions() = default;
-DynamicCheckerFunctions::~DynamicCheckerFunctions ()
-{
-}
+DynamicCheckerFunctions::~DynamicCheckerFunctions() = default;
bool
DynamicCheckerFunctions::Install(Stream &error_stream,
ExecutionContext &exe_ctx)
{
- m_valid_pointer_check.reset(new ClangUtilityFunction(g_valid_pointer_check_text,
- VALID_POINTER_CHECK_NAME));
+ Error error;
+ m_valid_pointer_check.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_valid_pointer_check_text,
+ lldb::eLanguageTypeC,
+ VALID_POINTER_CHECK_NAME,
+ error));
+ if (error.Fail())
+ return false;
+
if (!m_valid_pointer_check->Install(error_stream, exe_ctx))
return false;
@@ -80,12 +87,12 @@ DynamicCheckerFunctions::DoCheckersExplainStop (lldb::addr_t addr, Stream &messa
{
// FIXME: We have to get the checkers to know why they scotched the call in more detail,
// so we can print a better message here.
- if (m_valid_pointer_check.get() != NULL && m_valid_pointer_check->ContainsAddress(addr))
+ if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr))
{
message.Printf ("Attempted to dereference an invalid pointer.");
return true;
}
- else if (m_objc_object_check.get() != NULL && m_objc_object_check->ContainsAddress(addr))
+ else if (m_objc_object_check && m_objc_object_check->ContainsAddress(addr))
{
message.Printf ("Attempted to dereference an invalid ObjC Object or send it an unrecognized selector");
return true;
@@ -93,7 +100,6 @@ DynamicCheckerFunctions::DoCheckersExplainStop (lldb::addr_t addr, Stream &messa
return false;
}
-
static std::string
PrintValue(llvm::Value *V, bool truncate = false)
{
@@ -146,14 +152,12 @@ public:
DynamicCheckerFunctions &checker_functions) :
m_module(module),
m_checker_functions(checker_functions),
- m_i8ptr_ty(NULL),
- m_intptr_ty(NULL)
+ m_i8ptr_ty(nullptr),
+ m_intptr_ty(nullptr)
{
}
- virtual~Instrumenter ()
- {
- }
+ virtual ~Instrumenter() = default;
//------------------------------------------------------------------
/// Inspect a function to find instructions to instrument
@@ -187,6 +191,7 @@ public:
return true;
}
+
protected:
//------------------------------------------------------------------
/// Add instrumentation to a single instruction
@@ -344,6 +349,7 @@ protected:
InstVector m_to_instrument; ///< List of instructions the inspector found
llvm::Module &m_module; ///< The module which is being instrumented
DynamicCheckerFunctions &m_checker_functions; ///< The dynamic checker functions for the process
+
private:
PointerType *m_i8ptr_ty;
IntegerType *m_intptr_ty;
@@ -355,15 +361,14 @@ public:
ValidPointerChecker (llvm::Module &module,
DynamicCheckerFunctions &checker_functions) :
Instrumenter(module, checker_functions),
- m_valid_pointer_check_func(NULL)
+ m_valid_pointer_check_func(nullptr)
{
}
- virtual ~ValidPointerChecker ()
- {
- }
-private:
- bool InstrumentInstruction(llvm::Instruction *inst)
+ ~ValidPointerChecker() override = default;
+
+protected:
+ bool InstrumentInstruction(llvm::Instruction *inst) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -374,7 +379,7 @@ private:
if (!m_valid_pointer_check_func)
m_valid_pointer_check_func = BuildPointerValidatorFunc(m_checker_functions.m_valid_pointer_check->StartAddress());
- llvm::Value *dereferenced_ptr = NULL;
+ llvm::Value *dereferenced_ptr = nullptr;
if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst> (inst))
dereferenced_ptr = li->getPointerOperand();
@@ -406,7 +411,7 @@ private:
return true;
}
- bool InspectInstruction(llvm::Instruction &i)
+ bool InspectInstruction(llvm::Instruction &i) override
{
if (dyn_cast<llvm::LoadInst> (&i) ||
dyn_cast<llvm::StoreInst> (&i))
@@ -415,6 +420,7 @@ private:
return true;
}
+private:
llvm::Value *m_valid_pointer_check_func;
};
@@ -424,14 +430,11 @@ public:
ObjcObjectChecker(llvm::Module &module,
DynamicCheckerFunctions &checker_functions) :
Instrumenter(module, checker_functions),
- m_objc_object_check_func(NULL)
+ m_objc_object_check_func(nullptr)
{
}
- virtual
- ~ObjcObjectChecker ()
- {
- }
+ ~ObjcObjectChecker() override = default;
enum msgSend_type
{
@@ -444,13 +447,13 @@ public:
std::map <llvm::Instruction *, msgSend_type> msgSend_types;
-private:
- bool InstrumentInstruction(llvm::Instruction *inst)
+protected:
+ bool InstrumentInstruction(llvm::Instruction *inst) override
{
CallInst *call_inst = dyn_cast<CallInst>(inst);
if (!call_inst)
- return false; // call_inst really shouldn't be NULL, because otherwise InspectInstruction wouldn't have registered it
+ return false; // call_inst really shouldn't be nullptr, because otherwise InspectInstruction wouldn't have registered it
if (!m_objc_object_check_func)
m_objc_object_check_func = BuildObjectCheckerFunc(m_checker_functions.m_objc_object_check->StartAddress());
@@ -504,7 +507,7 @@ private:
return true;
}
- bool InspectInstruction(llvm::Instruction &i)
+ bool InspectInstruction(llvm::Instruction &i) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -593,6 +596,7 @@ private:
return true;
}
+private:
llvm::Value *m_objc_object_check_func;
};
@@ -604,9 +608,7 @@ IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
{
}
-IRDynamicChecks::~IRDynamicChecks()
-{
-}
+IRDynamicChecks::~IRDynamicChecks() = default;
bool
IRDynamicChecks::runOnModule(llvm::Module &M)
@@ -623,7 +625,7 @@ IRDynamicChecks::runOnModule(llvm::Module &M)
return false;
}
- if (m_checker_functions.m_valid_pointer_check.get())
+ if (m_checker_functions.m_valid_pointer_check)
{
ValidPointerChecker vpc(M, m_checker_functions);
@@ -634,7 +636,7 @@ IRDynamicChecks::runOnModule(llvm::Module &M)
return false;
}
- if (m_checker_functions.m_objc_object_check.get())
+ if (m_checker_functions.m_objc_object_check)
{
ObjcObjectChecker ooc(M, m_checker_functions);
@@ -650,7 +652,7 @@ IRDynamicChecks::runOnModule(llvm::Module &M)
std::string s;
raw_string_ostream oss(s);
- M.print(oss, NULL);
+ M.print(oss, nullptr);
oss.flush();
diff --git a/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp b/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp
index 59c7fb6..3f19c50 100644
--- a/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp
@@ -50,10 +50,12 @@ IRExecutionUnit::WriteNow (const uint8_t *bytes,
size_t size,
Error &error)
{
+ const bool zero_memory = false;
lldb::addr_t allocation_process_addr = Malloc (size,
8,
lldb::ePermissionsWritable | lldb::ePermissionsReadable,
eAllocationPolicyMirror,
+ zero_memory,
error);
if (!error.Success())
@@ -432,6 +434,13 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), record.m_process_address, 16, DataExtractor::TypeUInt8);
}
}
+ else
+ {
+ record.dump(log);
+
+ DataExtractor my_extractor ((const void*)record.m_host_address, record.m_size, lldb::eByteOrderBig, 8);
+ my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16, DataExtractor::TypeUInt8);
+ }
}
}
@@ -488,6 +497,8 @@ IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRE
sect_type = lldb::eSectionTypeDWARFDebugAbbrev;
else if (dwarf_name.equals("aranges"))
sect_type = lldb::eSectionTypeDWARFDebugAranges;
+ else if (dwarf_name.equals("addr"))
+ sect_type = lldb::eSectionTypeDWARFDebugAddr;
break;
case 'f':
@@ -522,6 +533,8 @@ IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRE
case 's':
if (dwarf_name.equals("str"))
sect_type = lldb::eSectionTypeDWARFDebugStr;
+ else if (dwarf_name.equals("str_offsets"))
+ sect_type = lldb::eSectionTypeDWARFDebugStrOffsets;
break;
case 'r':
@@ -789,6 +802,7 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
{
case lldb::eSectionTypeInvalid:
case lldb::eSectionTypeDWARFDebugAbbrev:
+ case lldb::eSectionTypeDWARFDebugAddr:
case lldb::eSectionTypeDWARFDebugAranges:
case lldb::eSectionTypeDWARFDebugFrame:
case lldb::eSectionTypeDWARFDebugInfo:
@@ -799,6 +813,7 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
case lldb::eSectionTypeDWARFDebugPubTypes:
case lldb::eSectionTypeDWARFDebugRanges:
case lldb::eSectionTypeDWARFDebugStr:
+ case lldb::eSectionTypeDWARFDebugStrOffsets:
case lldb::eSectionTypeDWARFAppleNames:
case lldb::eSectionTypeDWARFAppleTypes:
case lldb::eSectionTypeDWARFAppleNamespaces:
@@ -806,10 +821,12 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
err.Clear();
break;
default:
+ const bool zero_memory = false;
record.m_process_address = Malloc (record.m_size,
record.m_alignment,
record.m_permissions,
eAllocationPolicyProcessOnly,
+ zero_memory,
err);
break;
}
@@ -877,12 +894,13 @@ IRExecutionUnit::AllocationRecord::dump (Log *log)
if (!log)
return;
- log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)",
+ log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)",
(unsigned long long)m_host_address,
(unsigned long long)m_size,
(unsigned long long)m_process_address,
(unsigned)m_alignment,
- (unsigned)m_section_id);
+ (unsigned)m_section_id,
+ m_name.c_str());
}
diff --git a/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp b/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp
index 926d1f2..a2b0c5b 100644
--- a/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/IRInterpreter.cpp
@@ -365,7 +365,7 @@ public:
const uint64_t *raw_data = resolved_value.getRawData();
- buffer.PutRawBytes(raw_data, constant_size, lldb::endian::InlHostByteOrder());
+ buffer.PutRawBytes(raw_data, constant_size, lldb_private::endian::InlHostByteOrder());
lldb_private::Error write_error;
@@ -498,7 +498,7 @@ IRInterpreter::CanInterpret (llvm::Module &module,
default:
{
if (log)
- log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str());
+ log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str());
error.SetErrorToGenericError();
error.SetErrorString(unsupported_opcode_error);
return false;
@@ -522,7 +522,7 @@ IRInterpreter::CanInterpret (llvm::Module &module,
if (!CanIgnoreCall(call_inst) && !support_function_calls)
{
if (log)
- log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str());
+ log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str());
error.SetErrorToGenericError();
error.SetErrorString(unsupported_opcode_error);
return false;
@@ -547,7 +547,7 @@ IRInterpreter::CanInterpret (llvm::Module &module,
default:
{
if (log)
- log->Printf("Unsupported ICmp predicate: %s", PrintValue(ii).c_str());
+ log->Printf("Unsupported ICmp predicate: %s", PrintValue(&*ii).c_str());
error.SetErrorToGenericError();
error.SetErrorString(unsupported_opcode_error);
@@ -655,7 +655,7 @@ IRInterpreter::Interpret (llvm::Module &module,
ai != ae;
++ai, ++arg_index)
{
- if (args.size() < static_cast<size_t>(arg_index))
+ if (args.size() <= static_cast<size_t>(arg_index))
{
error.SetErrorString ("Not enough arguments passed in to function");
return false;
@@ -663,16 +663,16 @@ IRInterpreter::Interpret (llvm::Module &module,
lldb::addr_t ptr = args[arg_index];
- frame.MakeArgument(ai, ptr);
+ frame.MakeArgument(&*ai, ptr);
}
uint32_t num_insts = 0;
- frame.Jump(function.begin());
+ frame.Jump(&function.front());
while (frame.m_ii != frame.m_ie && (++num_insts < 4096))
{
- const Instruction *inst = frame.m_ii;
+ const Instruction *inst = &*frame.m_ii;
if (log)
log->Printf("Interpreting %s", PrintValue(inst).c_str());
diff --git a/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp b/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp
index 4733b16..e96bddd 100644
--- a/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/IRMemoryMap.cpp
@@ -47,7 +47,7 @@ IRMemoryMap::~IRMemoryMap ()
}
lldb::addr_t
-IRMemoryMap::FindSpace (size_t size)
+IRMemoryMap::FindSpace (size_t size, bool zero_memory)
{
lldb::TargetSP target_sp = m_target_wp.lock();
lldb::ProcessSP process_sp = m_process_wp.lock();
@@ -60,7 +60,10 @@ IRMemoryMap::FindSpace (size_t size)
{
Error alloc_error;
- ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
+ if (!zero_memory)
+ ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
+ else
+ ret = process_sp->CallocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
if (!alloc_error.Success())
return LLDB_INVALID_ADDRESS;
@@ -225,7 +228,7 @@ IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
}
lldb::addr_t
-IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
+IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, Error &error)
{
lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
error.Clear();
@@ -263,7 +266,11 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
log->Printf ("IRMemoryMap::%s process_sp=0x%" PRIx64 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", __FUNCTION__, (lldb::addr_t) process_sp.get (), process_sp && process_sp->CanJIT () ? "true" : "false", process_sp && process_sp->IsAlive () ? "true" : "false");
if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
{
- allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+ if (!zero_memory)
+ allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+ else
+ allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error);
+
if (!error.Success())
return LLDB_INVALID_ADDRESS;
}
@@ -287,7 +294,11 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
{
if (process_sp->CanJIT() && process_sp->IsAlive())
{
- allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+ if (!zero_memory)
+ allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+ else
+ allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error);
+
if (!error.Success())
return LLDB_INVALID_ADDRESS;
}
diff --git a/contrib/llvm/tools/lldb/source/Expression/LLVMUserExpression.cpp b/contrib/llvm/tools/lldb/source/Expression/LLVMUserExpression.cpp
new file mode 100644
index 0000000..eff0a2d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Expression/LLVMUserExpression.cpp
@@ -0,0 +1,363 @@
+//===-- LLVMUserExpression.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+
+// Project includes
+#include "lldb/Expression/LLVMUserExpression.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+
+using namespace lldb_private;
+
+LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type,
+ const EvaluateExpressionOptions &options)
+ : UserExpression(exe_scope, expr, expr_prefix, language, desired_type, options),
+ m_stack_frame_bottom(LLDB_INVALID_ADDRESS),
+ m_stack_frame_top(LLDB_INVALID_ADDRESS),
+ m_transformed_text(),
+ m_execution_unit_sp(),
+ m_materializer_ap(),
+ m_jit_module_wp(),
+ m_enforce_valid_object(true),
+ m_in_cplusplus_method(false),
+ m_in_objectivec_method(false),
+ m_in_static_method(false),
+ m_needs_object_ptr(false),
+ m_const_object(false),
+ m_target(NULL),
+ m_can_interpret(false),
+ m_materialized_address(LLDB_INVALID_ADDRESS)
+{
+}
+
+LLVMUserExpression::~LLVMUserExpression()
+{
+ if (m_target)
+ {
+ lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
+ if (jit_module_sp)
+ m_target->GetImages().Remove(jit_module_sp);
+ }
+}
+
+lldb::ExpressionResults
+LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options,
+ lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result)
+{
+ // The expression log is quite verbose, and if you're just tracking the execution of the
+ // expression, it's quite convenient to have these logs come out with the STEP log as well.
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
+ {
+ lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
+
+ if (!PrepareToExecuteJITExpression(error_stream, exe_ctx, struct_address))
+ {
+ error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
+ lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
+
+ if (m_can_interpret)
+ {
+ llvm::Module *module = m_execution_unit_sp->GetModule();
+ llvm::Function *function = m_execution_unit_sp->GetFunction();
+
+ if (!module || !function)
+ {
+ error_stream.Printf("Supposed to interpret, but nothing is there");
+ return lldb::eExpressionSetupError;
+ }
+
+ Error interpreter_error;
+
+ std::vector<lldb::addr_t> args;
+
+ if (!AddArguments(exe_ctx, args, struct_address, error_stream))
+ {
+ error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ function_stack_bottom = m_stack_frame_bottom;
+ function_stack_top = m_stack_frame_top;
+
+ IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp.get(), interpreter_error,
+ function_stack_bottom, function_stack_top, exe_ctx);
+
+ if (!interpreter_error.Success())
+ {
+ error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
+ return lldb::eExpressionDiscarded;
+ }
+ }
+ else
+ {
+ if (!exe_ctx.HasThreadScope())
+ {
+ error_stream.Printf("UserExpression::Execute called with no thread selected.");
+ return lldb::eExpressionSetupError;
+ }
+
+ Address wrapper_address(m_jit_start_addr);
+
+ std::vector<lldb::addr_t> args;
+
+ if (!AddArguments(exe_ctx, args, struct_address, error_stream))
+ {
+ error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(exe_ctx.GetThreadRef(), wrapper_address,
+ args, options, shared_ptr_to_me));
+
+ if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream))
+ return lldb::eExpressionSetupError;
+
+ ThreadPlanCallUserExpression *user_expression_plan =
+ static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
+
+ lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
+
+ function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
+ function_stack_top = function_stack_pointer;
+
+ if (log)
+ log->Printf("-- [UserExpression::Execute] Execution of expression begins --");
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+
+ lldb::ExpressionResults execution_result =
+ exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream);
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
+
+ if (log)
+ log->Printf("-- [UserExpression::Execute] Execution of expression completed --");
+
+ if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
+ {
+ const char *error_desc = NULL;
+
+ if (call_plan_sp)
+ {
+ lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
+ if (real_stop_info_sp)
+ error_desc = real_stop_info_sp->GetDescription();
+ }
+ if (error_desc)
+ error_stream.Printf("Execution was interrupted, reason: %s.", error_desc);
+ else
+ error_stream.PutCString("Execution was interrupted.");
+
+ if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) ||
+ (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
+ error_stream.PutCString(
+ "\nThe process has been returned to the state before expression evaluation.");
+ else
+ {
+ if (execution_result == lldb::eExpressionHitBreakpoint)
+ user_expression_plan->TransferExpressionOwnership();
+ error_stream.PutCString(
+ "\nThe process has been left at the point where it was interrupted, "
+ "use \"thread return -x\" to return to the state before expression evaluation.");
+ }
+
+ return execution_result;
+ }
+ else if (execution_result == lldb::eExpressionStoppedForDebug)
+ {
+ error_stream.PutCString(
+ "Execution was halted at the first instruction of the expression "
+ "function because \"debug\" was requested.\n"
+ "Use \"thread return -x\" to return to the state before expression evaluation.");
+ return execution_result;
+ }
+ else if (execution_result != lldb::eExpressionCompleted)
+ {
+ error_stream.Printf("Couldn't execute function; result was %s\n",
+ Process::ExecutionResultAsCString(execution_result));
+ return execution_result;
+ }
+ }
+
+ if (FinalizeJITExecution(error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
+ {
+ return lldb::eExpressionCompleted;
+ }
+ else
+ {
+ return lldb::eExpressionResultUnavailable;
+ }
+ }
+ else
+ {
+ error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
+ return lldb::eExpressionSetupError;
+ }
+}
+
+bool
+LLVMUserExpression::FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx,
+ lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom,
+ lldb::addr_t function_stack_top)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing after execution --");
+
+ if (!m_dematerializer_sp)
+ {
+ error_stream.Printf("Couldn't apply expression side effects : no dematerializer is present");
+ return false;
+ }
+
+ Error dematerialize_error;
+
+ m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom, function_stack_top);
+
+ if (!dematerialize_error.Success())
+ {
+ error_stream.Printf("Couldn't apply expression side effects : %s\n",
+ dematerialize_error.AsCString("unknown error"));
+ return false;
+ }
+
+ result = GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope());
+
+ if (result)
+ result->TransferAddress();
+
+ m_dematerializer_sp.reset();
+
+ return true;
+}
+
+bool
+LLVMUserExpression::PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx,
+ lldb::addr_t &struct_address)
+{
+ lldb::TargetSP target;
+ lldb::ProcessSP process;
+ lldb::StackFrameSP frame;
+
+ if (!LockAndCheckContext(exe_ctx, target, process, frame))
+ {
+ error_stream.Printf("The context has changed before we could JIT the expression!\n");
+ return false;
+ }
+
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
+ {
+ if (m_materialized_address == LLDB_INVALID_ADDRESS)
+ {
+ Error alloc_error;
+
+ IRMemoryMap::AllocationPolicy policy =
+ m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
+
+ const bool zero_memory = false;
+
+ m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(),
+ m_materializer_ap->GetStructAlignment(),
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ policy,
+ zero_memory,
+ alloc_error);
+
+ if (!alloc_error.Success())
+ {
+ error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
+ return false;
+ }
+ }
+
+ struct_address = m_materialized_address;
+
+ if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
+ {
+ Error alloc_error;
+
+ const size_t stack_frame_size = 512 * 1024;
+
+ const bool zero_memory = false;
+
+ m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size,
+ 8,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyHostOnly,
+ zero_memory,
+ alloc_error);
+
+ m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
+
+ if (!alloc_error.Success())
+ {
+ error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
+ return false;
+ }
+ }
+
+ Error materialize_error;
+
+ m_dematerializer_sp =
+ m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
+
+ if (!materialize_error.Success())
+ {
+ error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString());
+ return false;
+ }
+ }
+ return true;
+}
+
+lldb::ModuleSP
+LLVMUserExpression::GetJITModule()
+{
+ if (m_execution_unit_sp)
+ return m_execution_unit_sp->GetJITModule();
+ return lldb::ModuleSP();
+}
diff --git a/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp b/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp
index ef01fee..8d68b4f 100644
--- a/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp
+++ b/contrib/llvm/tools/lldb/source/Expression/Materializer.cpp
@@ -7,12 +7,15 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectVariable.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
+#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Symbol.h"
@@ -48,7 +51,7 @@ Materializer::AddStructMember (Entity &entity)
}
void
-Materializer::Entity::SetSizeAndAlignmentFromType (ClangASTType &type)
+Materializer::Entity::SetSizeAndAlignmentFromType (CompilerType &type)
{
m_size = type.GetByteSize(nullptr);
@@ -66,9 +69,11 @@ Materializer::Entity::SetSizeAndAlignmentFromType (ClangASTType &type)
class EntityPersistentVariable : public Materializer::Entity
{
public:
- EntityPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp) :
+ EntityPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp,
+ Materializer::PersistentVariableDelegate *delegate) :
Entity(),
- m_persistent_variable_sp(persistent_variable_sp)
+ m_persistent_variable_sp(persistent_variable_sp),
+ m_delegate(delegate)
{
// Hard-coding to maximum size of a pointer since persistent variables are materialized by reference
m_size = 8;
@@ -82,11 +87,13 @@ public:
// Allocate a spare memory area to store the persistent variable's contents.
Error allocate_error;
+ const bool zero_memory = false;
lldb::addr_t mem = map.Malloc(m_persistent_variable_sp->GetByteSize(),
8,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
IRMemoryMap::eAllocationPolicyMirror,
+ zero_memory,
allocate_error);
if (!allocate_error.Success())
@@ -99,21 +106,21 @@ public:
log->Printf("Allocated %s (0x%" PRIx64 ") successfully", m_persistent_variable_sp->GetName().GetCString(), mem);
// Put the location of the spare memory into the live data of the ValueObject.
-
+
m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope(),
- m_persistent_variable_sp->GetTypeFromUser(),
+ m_persistent_variable_sp->GetCompilerType(),
m_persistent_variable_sp->GetName(),
mem,
eAddressTypeLoad,
- m_persistent_variable_sp->GetByteSize());
+ map.GetAddressByteSize());
// Clear the flag if the variable will never be deallocated.
- if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
+ if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget)
{
Error leak_error;
map.Leak(mem, leak_error);
- m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation;
+ m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsAllocation;
}
// Write the contents of the variable to the area.
@@ -147,7 +154,10 @@ public:
}
}
- void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
+ void Materialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -161,17 +171,17 @@ public:
m_persistent_variable_sp->m_flags);
}
- if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation)
+ if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsAllocation)
{
MakeAllocation(map, err);
- m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
+ m_persistent_variable_sp->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
if (!err.Success())
return;
}
- if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) ||
- m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated)
+ if ((m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) ||
+ m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsLLDBAllocated)
{
Error write_error;
@@ -192,12 +202,12 @@ public:
}
}
- void Dematerialize (lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
+ void Dematerialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -211,10 +221,15 @@ public:
m_persistent_variable_sp->m_flags);
}
- if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) ||
- (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference))
+ if (m_delegate)
+ {
+ m_delegate->DidDematerialize(m_persistent_variable_sp);
+ }
+
+ if ((m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsLLDBAllocated) ||
+ (m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference))
{
- if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference &&
+ if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference &&
!m_persistent_variable_sp->m_live_sp)
{
// If the reference comes from the program, then the ClangExpressionVariable's
@@ -230,9 +245,9 @@ public:
err.SetErrorStringWithFormat("couldn't read the address of program-allocated variable %s: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
return;
}
-
+
m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope (),
- m_persistent_variable_sp->GetTypeFromUser(),
+ m_persistent_variable_sp.get()->GetCompilerType(),
m_persistent_variable_sp->GetName(),
location,
eAddressTypeLoad,
@@ -246,10 +261,10 @@ public:
// If the variable is resident in the stack frame created by the expression,
// then it cannot be relied upon to stay around. We treat it as needing
// reallocation.
- m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
- m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
- m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
- m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVIsProgramReference;
+ m_persistent_variable_sp->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
+ m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation;
+ m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsFreezeDry;
+ m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVIsProgramReference;
}
}
@@ -267,8 +282,8 @@ public:
return;
}
- if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry ||
- m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
+ if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsFreezeDry ||
+ m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget)
{
if (log)
log->Printf("Dematerializing %s from 0x%" PRIx64 " (size = %llu)", m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, (unsigned long long)m_persistent_variable_sp->GetByteSize());
@@ -290,7 +305,7 @@ public:
return;
}
- m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry;
+ m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsFreezeDry;
}
}
else
@@ -305,14 +320,14 @@ public:
{
// Allocations are not persistent so persistent variables cannot stay materialized.
- m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
+ m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation;
DestroyAllocation(map, err);
if (!err.Success())
return;
}
- else if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation &&
- !(m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget))
+ else if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsAllocation &&
+ !(m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget))
{
DestroyAllocation(map, err);
if (!err.Success())
@@ -320,7 +335,7 @@ public:
}
}
- void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
{
StreamString dump_stream;
@@ -386,18 +401,22 @@ public:
log->PutCString(dump_stream.GetData());
}
- void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
{
}
+
private:
- lldb::ClangExpressionVariableSP m_persistent_variable_sp;
+ lldb::ExpressionVariableSP m_persistent_variable_sp;
+ Materializer::PersistentVariableDelegate *m_delegate;
};
uint32_t
-Materializer::AddPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp, Error &err)
+Materializer::AddPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp,
+ PersistentVariableDelegate *delegate,
+ Error &err)
{
EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
- iter->reset (new EntityPersistentVariable (persistent_variable_sp));
+ iter->reset (new EntityPersistentVariable (persistent_variable_sp, delegate));
uint32_t ret = AddStructMember(**iter);
(*iter)->SetOffset(ret);
return ret;
@@ -416,10 +435,13 @@ public:
// Hard-coding to maximum size of a pointer since all variables are materialized by reference
m_size = 8;
m_alignment = 8;
- m_is_reference = m_variable_sp->GetType()->GetClangForwardType().IsReferenceType();
+ m_is_reference = m_variable_sp->GetType()->GetForwardCompilerType ().IsReferenceType();
}
- void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
+ void Materialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -525,15 +547,22 @@ public:
return;
}
- size_t bit_align = m_variable_sp->GetType()->GetClangLayoutType().GetTypeBitAlign();
+ size_t bit_align = m_variable_sp->GetType()->GetLayoutCompilerType ().GetTypeBitAlign();
size_t byte_align = (bit_align + 7) / 8;
if (!byte_align)
byte_align = 1;
Error alloc_error;
+ const bool zero_memory = false;
+
+ m_temporary_allocation = map.Malloc(data.GetByteSize(),
+ byte_align,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyMirror,
+ zero_memory,
+ alloc_error);
- m_temporary_allocation = map.Malloc(data.GetByteSize(), byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
m_temporary_allocation_size = data.GetByteSize();
m_original_data.reset(new DataBufferHeap(data.GetDataStart(), data.GetByteSize()));
@@ -566,12 +595,12 @@ public:
}
}
- void Dematerialize (lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
+ void Dematerialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -650,7 +679,7 @@ public:
}
}
- void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
{
StreamString dump_stream;
@@ -722,7 +751,7 @@ public:
log->PutCString(dump_stream.GetData());
}
- void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
{
if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
{
@@ -735,6 +764,7 @@ public:
}
}
+
private:
lldb::VariableSP m_variable_sp;
bool m_is_reference;
@@ -756,20 +786,27 @@ Materializer::AddVariable (lldb::VariableSP &variable_sp, Error &err)
class EntityResultVariable : public Materializer::Entity
{
public:
- EntityResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory) :
+ EntityResultVariable (const CompilerType &type,
+ bool is_program_reference,
+ bool keep_in_memory,
+ Materializer::PersistentVariableDelegate *delegate) :
Entity(),
m_type(type),
m_is_program_reference(is_program_reference),
m_keep_in_memory(keep_in_memory),
m_temporary_allocation(LLDB_INVALID_ADDRESS),
- m_temporary_allocation_size(0)
+ m_temporary_allocation_size(0),
+ m_delegate(delegate)
{
// Hard-coding to maximum size of a pointer since all results are materialized by reference
m_size = 8;
m_alignment = 8;
}
- void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
+ void Materialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ Error &err) override
{
if (!m_is_program_reference)
{
@@ -789,8 +826,14 @@ public:
byte_align = 1;
Error alloc_error;
-
- m_temporary_allocation = map.Malloc(byte_size, byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error);
+ const bool zero_memory = true;
+
+ m_temporary_allocation = map.Malloc(byte_size,
+ byte_align,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyMirror,
+ zero_memory,
+ alloc_error);
m_temporary_allocation_size = byte_size;
if (!alloc_error.Success())
@@ -810,23 +853,12 @@ public:
}
}
- void Dematerialize (lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
- {
- err.SetErrorString("Tried to detmaterialize a result variable with the normal Dematerialize method");
- }
-
- void Dematerialize (lldb::ClangExpressionVariableSP &result_variable_sp,
- lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
+ void Dematerialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom,
+ Error &err) override
{
err.Clear();
@@ -858,15 +890,30 @@ public:
return;
}
- ConstString name = target_sp->GetPersistentVariables().GetNextPersistentVariableName();
+ Error type_system_error;
+ TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(&type_system_error, m_type.GetMinimumLanguage());
+
+ if (!type_system)
+ {
+ err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: couldn't get the corresponding type system: %s", type_system_error.AsCString());
+ return;
+ }
+
+ PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState();
+
+ if (!persistent_state)
+ {
+ err.SetErrorString("Couldn't dematerialize a result variable: corresponding type system doesn't handle persistent variables");
+ return;
+ }
- lldb::ClangExpressionVariableSP ret;
+ ConstString name = m_delegate ? m_delegate->GetName() : persistent_state->GetNextPersistentVariableName();
- ret = target_sp->GetPersistentVariables().CreateVariable(exe_scope,
- name,
- m_type,
- map.GetByteOrder(),
- map.GetAddressByteSize());
+ lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(exe_scope,
+ name,
+ m_type,
+ map.GetByteOrder(),
+ map.GetAddressByteSize());
if (!ret)
{
@@ -876,6 +923,11 @@ public:
lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess();
+ if (m_delegate)
+ {
+ m_delegate->DidDematerialize(ret);
+ }
+
bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top));
if (can_persist && m_keep_in_memory)
@@ -900,12 +952,10 @@ public:
err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory");
return;
}
-
- result_variable_sp = ret;
if (!can_persist || !m_keep_in_memory)
{
- ret->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
+ ret->m_flags |= ExpressionVariable::EVNeedsAllocation;
if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
{
@@ -915,14 +965,14 @@ public:
}
else
{
- ret->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
+ ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated;
}
m_temporary_allocation = LLDB_INVALID_ADDRESS;
m_temporary_allocation_size = 0;
}
- void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
{
StreamString dump_stream;
@@ -995,7 +1045,7 @@ public:
log->PutCString(dump_stream.GetData());
}
- void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
{
if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS)
{
@@ -1007,23 +1057,28 @@ public:
m_temporary_allocation = LLDB_INVALID_ADDRESS;
m_temporary_allocation_size = 0;
}
+
private:
- TypeFromUser m_type;
+ CompilerType m_type;
bool m_is_program_reference;
bool m_keep_in_memory;
lldb::addr_t m_temporary_allocation;
size_t m_temporary_allocation_size;
+ Materializer::PersistentVariableDelegate *m_delegate;
};
uint32_t
-Materializer::AddResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory, Error &err)
+Materializer::AddResultVariable (const CompilerType &type,
+ bool is_program_reference,
+ bool keep_in_memory,
+ PersistentVariableDelegate *delegate,
+ Error &err)
{
EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
- iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory));
+ iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory, delegate));
uint32_t ret = AddStructMember(**iter);
(*iter)->SetOffset(ret);
- m_result_entity = iter->get();
return ret;
}
@@ -1039,7 +1094,10 @@ public:
m_alignment = 8;
}
- void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
+ void Materialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1083,12 +1141,12 @@ public:
}
}
- void Dematerialize (lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
+ void Dematerialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1104,7 +1162,7 @@ public:
// no work needs to be done
}
- void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
{
StreamString dump_stream;
@@ -1138,9 +1196,10 @@ public:
log->PutCString(dump_stream.GetData());
}
- void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
{
}
+
private:
Symbol m_symbol;
};
@@ -1167,7 +1226,10 @@ public:
m_alignment = m_register_info.byte_size;
}
- void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
+ void Materialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1223,12 +1285,12 @@ public:
}
}
- void Dematerialize (lldb::StackFrameSP &frame_sp,
- IRMemoryMap &map,
- lldb::addr_t process_address,
- lldb::addr_t frame_top,
- lldb::addr_t frame_bottom,
- Error &err)
+ void Dematerialize(lldb::StackFrameSP &frame_sp,
+ IRMemoryMap &map,
+ lldb::addr_t process_address,
+ lldb::addr_t frame_top,
+ lldb::addr_t frame_bottom,
+ Error &err) override
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -1280,7 +1342,7 @@ public:
}
}
- void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log)
+ void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
{
StreamString dump_stream;
@@ -1315,9 +1377,10 @@ public:
log->PutCString(dump_stream.GetData());
}
- void Wipe (IRMemoryMap &map, lldb::addr_t process_address)
+ void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
{
}
+
private:
RegisterInfo m_register_info;
lldb::DataBufferSP m_register_contents;
@@ -1335,7 +1398,6 @@ Materializer::AddRegister (const RegisterInfo &register_info, Error &err)
Materializer::Materializer () :
m_dematerializer_wp(),
- m_result_entity(NULL),
m_current_offset(0),
m_struct_alignment(8)
{
@@ -1395,7 +1457,9 @@ Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb:
}
void
-Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_bottom, lldb::addr_t frame_top)
+Materializer::Dematerializer::Dematerialize (Error &error,
+ lldb::addr_t frame_bottom,
+ lldb::addr_t frame_top)
{
lldb::StackFrameSP frame_sp;
@@ -1428,14 +1492,7 @@ Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpression
for (EntityUP &entity_up : m_materializer->m_entities)
{
- if (entity_up.get() == m_materializer->m_result_entity)
- {
- static_cast<EntityResultVariable*>(m_materializer->m_result_entity)->Dematerialize (result_sp, frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
- }
- else
- {
- entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
- }
+ entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error);
if (!error.Success())
break;
@@ -1456,7 +1513,9 @@ Materializer::Dematerializer::Wipe ()
entity_up->Wipe (*m_map, m_process_address);
}
- m_materializer = NULL;
- m_map = NULL;
+ m_materializer = nullptr;
+ m_map = nullptr;
m_process_address = LLDB_INVALID_ADDRESS;
}
+
+Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() = default;
diff --git a/contrib/llvm/tools/lldb/source/Expression/REPL.cpp b/contrib/llvm/tools/lldb/source/Expression/REPL.cpp
new file mode 100644
index 0000000..1727a13
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Expression/REPL.cpp
@@ -0,0 +1,649 @@
+//===-- REPL.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Expression/REPL.h"
+#include "lldb/Expression/UserExpression.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/AnsiTerminal.h"
+
+using namespace lldb_private;
+
+REPL::REPL(LLVMCastKind kind, Target &target) :
+ m_target(target),
+ m_kind(kind)
+{
+ // Make sure all option values have sane defaults
+ Debugger &debugger = m_target.GetDebugger();
+ CommandInterpreter &ci = debugger.GetCommandInterpreter();
+ m_format_options.OptionParsingStarting(ci);
+ m_varobj_options.OptionParsingStarting(ci);
+ m_command_options.OptionParsingStarting(ci);
+
+ // Default certain settings for REPL regardless of the global settings.
+ m_command_options.unwind_on_error = false;
+ m_command_options.ignore_breakpoints = false;
+ m_command_options.debug = false;
+}
+
+REPL::~REPL() = default;
+
+lldb::REPLSP
+REPL::Create(Error &err, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options)
+{
+ uint32_t idx = 0;
+ lldb::REPLSP ret;
+
+ while (REPLCreateInstance create_instance = PluginManager::GetREPLCreateCallbackAtIndex(idx++))
+ {
+ ret = (*create_instance)(err, language, debugger, target, repl_options);
+ if (ret)
+ {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+std::string
+REPL::GetSourcePath()
+{
+ ConstString file_basename = GetSourceFileBasename();
+
+ FileSpec tmpdir_file_spec;
+ if (HostInfo::GetLLDBPath (lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
+ {
+ tmpdir_file_spec.GetFilename().SetCString(file_basename.AsCString());
+ m_repl_source_path = tmpdir_file_spec.GetPath();
+ }
+ else
+ {
+ tmpdir_file_spec = FileSpec("/tmp", false);
+ tmpdir_file_spec.AppendPathComponent(file_basename.AsCString());
+ }
+
+ return tmpdir_file_spec.GetPath();
+}
+
+lldb::IOHandlerSP
+REPL::GetIOHandler()
+{
+ if (!m_io_handler_sp)
+ {
+ Debugger &debugger = m_target.GetDebugger();
+ m_io_handler_sp.reset (new IOHandlerEditline (debugger,
+ IOHandler::Type::REPL,
+ "lldb-repl", // Name of input reader for history
+ "> ", // prompt
+ ". ", // Continuation prompt
+ true, // Multi-line
+ true, // The REPL prompt is always colored
+ 1, // Line number
+ *this));
+
+ // Don't exit if CTRL+C is pressed
+ static_cast<IOHandlerEditline *>(m_io_handler_sp.get())->SetInterruptExits(false);
+
+ if (m_io_handler_sp->GetIsInteractive() && m_io_handler_sp->GetIsRealTerminal())
+ {
+ m_indent_str.assign (debugger.GetTabSize(), ' ');
+ m_enable_auto_indent = debugger.GetAutoIndent();
+ }
+ else
+ {
+ m_indent_str.clear();
+ m_enable_auto_indent = false;
+ }
+
+ }
+ return m_io_handler_sp;
+}
+
+void
+REPL::IOHandlerActivated (IOHandler &io_handler)
+{
+ lldb::ProcessSP process_sp = m_target.GetProcessSP();
+ if (process_sp && process_sp->IsAlive())
+ return;
+ lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+ error_sp->Printf("REPL requires a running target process.\n");
+ io_handler.SetIsDone(true);
+}
+
+bool
+REPL::IOHandlerInterrupt (IOHandler &io_handler)
+{
+ return false;
+}
+
+void
+REPL::IOHandlerInputInterrupted (IOHandler &io_handler,
+ std::string &line)
+{
+}
+
+const char *
+REPL::IOHandlerGetFixIndentationCharacters()
+{
+ return (m_enable_auto_indent ? GetAutoIndentCharacters() : nullptr);
+}
+
+ConstString
+REPL::IOHandlerGetControlSequence (char ch)
+{
+ if (ch == 'd')
+ return ConstString(":quit\n");
+ return ConstString();
+}
+
+const char *
+REPL::IOHandlerGetCommandPrefix ()
+{
+ return ":";
+}
+
+const char *
+REPL::IOHandlerGetHelpPrologue ()
+{
+ return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter. "
+ "Valid statements, expressions, and declarations are immediately compiled and executed.\n\n"
+ "The complete set of LLDB debugging commands are also available as described below. Commands "
+ "must be prefixed with a colon at the REPL prompt (:quit for example.) Typing just a colon "
+ "followed by return will switch to the LLDB prompt.\n\n";
+}
+
+bool
+REPL::IOHandlerIsInputComplete (IOHandler &io_handler,
+ StringList &lines)
+{
+ // Check for meta command
+ const size_t num_lines = lines.GetSize();
+ if (num_lines == 1)
+ {
+ const char *first_line = lines.GetStringAtIndex(0);
+ if (first_line[0] == ':')
+ return true; // Meta command is a single line where that starts with ':'
+ }
+
+ // Check if REPL input is done
+ std::string source_string (lines.CopyList());
+ return SourceIsComplete(source_string);
+}
+
+int
+REPL::CalculateActualIndentation (const StringList &lines)
+{
+ std::string last_line = lines[lines.GetSize() - 1];
+
+ int actual_indent = 0;
+ for (char &ch : last_line)
+ {
+ if (ch != ' ') break;
+ ++actual_indent;
+ }
+
+ return actual_indent;
+}
+
+int
+REPL::IOHandlerFixIndentation (IOHandler &io_handler,
+ const StringList &lines,
+ int cursor_position)
+{
+ if (!m_enable_auto_indent) return 0;
+
+ if (!lines.GetSize())
+ {
+ return 0;
+ }
+
+ int tab_size = io_handler.GetDebugger().GetTabSize();
+
+ lldb::offset_t desired_indent = GetDesiredIndentation(lines,
+ cursor_position,
+ tab_size);
+
+ int actual_indent = REPL::CalculateActualIndentation(lines);
+
+ if (desired_indent == LLDB_INVALID_OFFSET)
+ return 0;
+
+ return (int)desired_indent - actual_indent;
+}
+
+void
+REPL::IOHandlerInputComplete (IOHandler &io_handler, std::string &code)
+{
+ lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+ bool extra_line = false;
+ bool did_quit = false;
+
+ if (code.empty())
+ {
+ m_code.AppendString("");
+ static_cast<IOHandlerEditline &>(io_handler).SetBaseLineNumber(m_code.GetSize()+1);
+ }
+ else
+ {
+ Debugger &debugger = m_target.GetDebugger();
+ CommandInterpreter &ci = debugger.GetCommandInterpreter();
+ extra_line = ci.GetSpaceReplPrompts();
+
+ ExecutionContext exe_ctx (m_target.GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame().get());
+
+ lldb::ProcessSP process_sp(exe_ctx.GetProcessSP());
+
+ if (code[0] == ':')
+ {
+ // Meta command
+ // Strip the ':'
+ code.erase(0, 1);
+ if (Args::StripSpaces (code))
+ {
+ // "lldb" was followed by arguments, so just execute the command dump the results
+
+ // Turn off prompt on quit in case the user types ":quit"
+ const bool saved_prompt_on_quit = ci.GetPromptOnQuit();
+ if (saved_prompt_on_quit)
+ ci.SetPromptOnQuit(false);
+
+ // Execute the command
+ CommandReturnObject result;
+ result.SetImmediateOutputStream(output_sp);
+ result.SetImmediateErrorStream(error_sp);
+ ci.HandleCommand(code.c_str(), eLazyBoolNo, result);
+
+ if (saved_prompt_on_quit)
+ ci.SetPromptOnQuit(true);
+
+ if (result.GetStatus() == lldb::eReturnStatusQuit)
+ {
+ did_quit = true;
+ io_handler.SetIsDone(true);
+ if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter))
+ {
+ // We typed "quit" or an alias to quit so we need to check if the
+ // command interpreter is above us and tell it that it is done as well
+ // so we don't drop back into the command interpreter if we have already
+ // quit
+ lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());
+ if (io_handler_sp)
+ io_handler_sp->SetIsDone(true);
+ }
+ }
+ }
+ else
+ {
+ // ":" was followed by no arguments, so push the LLDB command prompt
+ if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter))
+ {
+ // If the user wants to get back to the command interpreter and the
+ // command interpreter is what launched the REPL, then just let the
+ // REPL exit and fall back to the command interpreter.
+ io_handler.SetIsDone(true);
+ }
+ else
+ {
+ // The REPL wasn't launched the by the command interpreter, it is the
+ // base IOHandler, so we need to get the command interpreter and
+ lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());
+ if (io_handler_sp)
+ {
+ io_handler_sp->SetIsDone(false);
+ debugger.PushIOHandler(ci.GetIOHandler());
+ }
+ }
+ }
+ }
+ else
+ {
+ // Unwind any expression we might have been running in case our REPL
+ // expression crashed and the user was looking around
+ if (m_dedicated_repl_mode)
+ {
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (thread && thread->UnwindInnermostExpression().Success())
+ {
+ thread->SetSelectedFrameByIndex(0, false);
+ exe_ctx.SetFrameSP(thread->GetSelectedFrame());
+ }
+ }
+
+ const bool colorize_err = error_sp->GetFile().GetIsTerminalWithColors();
+
+ EvaluateExpressionOptions expr_options;
+ expr_options.SetCoerceToId(m_varobj_options.use_objc);
+ expr_options.SetUnwindOnError(m_command_options.unwind_on_error);
+ expr_options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);
+ expr_options.SetKeepInMemory(true);
+ expr_options.SetUseDynamic(m_varobj_options.use_dynamic);
+ expr_options.SetTryAllThreads(m_command_options.try_all_threads);
+ expr_options.SetGenerateDebugInfo(true);
+ expr_options.SetREPLEnabled (true);
+ expr_options.SetColorizeErrors(colorize_err);
+ expr_options.SetPoundLine(m_repl_source_path.c_str(), m_code.GetSize() + 1);
+ if (m_command_options.timeout > 0)
+ expr_options.SetTimeoutUsec(m_command_options.timeout);
+ else
+ expr_options.SetTimeoutUsec(0);
+
+ expr_options.SetLanguage(GetLanguage());
+
+ PersistentExpressionState *persistent_state = m_target.GetPersistentExpressionStateForLanguage(GetLanguage());
+
+ const size_t var_count_before = persistent_state->GetSize();
+
+ const char *expr_prefix = nullptr;
+ lldb::ValueObjectSP result_valobj_sp;
+ Error error;
+ lldb::ModuleSP jit_module_sp;
+ lldb::ExpressionResults execution_results = UserExpression::Evaluate (exe_ctx,
+ expr_options,
+ code.c_str(),
+ expr_prefix,
+ result_valobj_sp,
+ error,
+ 0, // Line offset
+ &jit_module_sp);
+
+ //CommandInterpreter &ci = debugger.GetCommandInterpreter();
+
+ if (process_sp && process_sp->IsAlive())
+ {
+ bool add_to_code = true;
+ bool handled = false;
+ if (result_valobj_sp)
+ {
+ lldb::Format format = m_format_options.GetFormat();
+
+ if (result_valobj_sp->GetError().Success())
+ {
+ handled |= PrintOneVariable(debugger, output_sp, result_valobj_sp);
+ }
+ else if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult)
+ {
+ if (format != lldb::eFormatVoid && debugger.GetNotifyVoid())
+ {
+ error_sp->PutCString("(void)\n");
+ handled = true;
+ }
+ }
+ }
+
+ if (debugger.GetPrintDecls())
+ {
+ for (size_t vi = var_count_before, ve = persistent_state->GetSize();
+ vi != ve;
+ ++vi)
+ {
+ lldb::ExpressionVariableSP persistent_var_sp = persistent_state->GetVariableAtIndex(vi);
+ lldb::ValueObjectSP valobj_sp = persistent_var_sp->GetValueObject();
+
+ PrintOneVariable(debugger, output_sp, valobj_sp, persistent_var_sp.get());
+ }
+ }
+
+ if (!handled)
+ {
+ bool useColors = error_sp->GetFile().GetIsTerminalWithColors();
+ switch (execution_results)
+ {
+ case lldb::eExpressionSetupError:
+ case lldb::eExpressionParseError:
+ add_to_code = false;
+ // Fall through
+ case lldb::eExpressionDiscarded:
+ error_sp->Printf("%s\n", error.AsCString());
+ break;
+
+ case lldb::eExpressionCompleted:
+ break;
+ case lldb::eExpressionInterrupted:
+ if (useColors) {
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));
+ }
+ error_sp->Printf("Execution interrupted. ");
+ if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));
+ error_sp->Printf("Enter code to recover and continue.\nEnter LLDB commands to investigate (type :help for assistance.)\n");
+ break;
+
+ case lldb::eExpressionHitBreakpoint:
+ // Breakpoint was hit, drop into LLDB command interpreter
+ if (useColors) {
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));
+ error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));
+ }
+ output_sp->Printf("Execution stopped at breakpoint. ");
+ if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));
+ output_sp->Printf("Enter LLDB commands to investigate (type help for assistance.)\n");
+ {
+ lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler());
+ if (io_handler_sp)
+ {
+ io_handler_sp->SetIsDone(false);
+ debugger.PushIOHandler(ci.GetIOHandler());
+ }
+ }
+ break;
+
+ case lldb::eExpressionTimedOut:
+ error_sp->Printf("error: timeout\n");
+ if (error.AsCString())
+ error_sp->Printf("error: %s\n", error.AsCString());
+ break;
+ case lldb::eExpressionResultUnavailable:
+ // Shoulnd't happen???
+ error_sp->Printf("error: could not fetch result -- %s\n", error.AsCString());
+ break;
+ case lldb::eExpressionStoppedForDebug:
+ // Shoulnd't happen???
+ error_sp->Printf("error: stopped for debug -- %s\n", error.AsCString());
+ break;
+ }
+ }
+
+ if (add_to_code)
+ {
+ const uint32_t new_default_line = m_code.GetSize() + 1;
+
+ m_code.SplitIntoLines(code);
+
+ // Update our code on disk
+ if (!m_repl_source_path.empty())
+ {
+ lldb_private::File file (m_repl_source_path.c_str(),
+ File::eOpenOptionWrite | File::eOpenOptionTruncate | File::eOpenOptionCanCreate,
+ lldb::eFilePermissionsFileDefault);
+ std::string code (m_code.CopyList());
+ code.append(1, '\n');
+ size_t bytes_written = code.size();
+ file.Write(code.c_str(), bytes_written);
+ file.Close();
+
+ // Now set the default file and line to the REPL source file
+ m_target.GetSourceManager().SetDefaultFileAndLine(FileSpec(m_repl_source_path.c_str(), false), new_default_line);
+ }
+ static_cast<IOHandlerEditline &>(io_handler).SetBaseLineNumber(m_code.GetSize()+1);
+ }
+ if (extra_line)
+ {
+ fprintf(output_sp->GetFile().GetStream(), "\n");
+ }
+ }
+ }
+
+ // Don't complain about the REPL process going away if we are in the process of quitting.
+ if (!did_quit && (!process_sp || !process_sp->IsAlive()))
+ {
+ error_sp->Printf("error: REPL process is no longer alive, exiting REPL\n");
+ io_handler.SetIsDone(true);
+ }
+ }
+}
+
+int
+REPL::IOHandlerComplete (IOHandler &io_handler,
+ const char *current_line,
+ const char *cursor,
+ const char *last_char,
+ int skip_first_n_matches,
+ int max_matches,
+ StringList &matches)
+{
+ matches.Clear();
+
+ llvm::StringRef line (current_line, cursor - current_line);
+
+ // Complete an LLDB command if the first character is a colon...
+ if (!line.empty() && line[0] == ':')
+ {
+ Debugger &debugger = m_target.GetDebugger();
+
+ // auto complete LLDB commands
+ const char *lldb_current_line = line.substr(1).data();
+ return debugger.GetCommandInterpreter().HandleCompletion (lldb_current_line,
+ cursor,
+ last_char,
+ skip_first_n_matches,
+ max_matches,
+ matches);
+ }
+
+ // Strip spaces from the line and see if we had only spaces
+ line = line.ltrim();
+ if (line.empty())
+ {
+ // Only spaces on this line, so just indent
+ matches.AppendString(m_indent_str);
+ return 1;
+ }
+
+ std::string current_code;
+ current_code.append(m_code.CopyList());
+
+ IOHandlerEditline &editline = static_cast<IOHandlerEditline &>(io_handler);
+ const StringList *current_lines = editline.GetCurrentLines();
+ if (current_lines)
+ {
+ const uint32_t current_line_idx = editline.GetCurrentLineIndex();
+
+ if (current_line_idx < current_lines->GetSize())
+ {
+ for (uint32_t i=0; i<current_line_idx; ++i)
+ {
+ const char *line_cstr = current_lines->GetStringAtIndex(i);
+ if (line_cstr)
+ {
+ current_code.append("\n");
+ current_code.append (line_cstr);
+ }
+ }
+ }
+ }
+
+ if (cursor > current_line)
+ {
+ current_code.append("\n");
+ current_code.append(current_line, cursor - current_line);
+ }
+
+ return CompleteCode(current_code, matches);
+}
+
+bool
+QuitCommandOverrideCallback(void *baton, const char **argv)
+{
+ Target *target = (Target *)baton;
+ lldb::ProcessSP process_sp (target->GetProcessSP());
+ if (process_sp)
+ {
+ process_sp->Destroy(false);
+ process_sp->GetTarget().GetDebugger().ClearIOHandlers();
+ }
+ return false;
+}
+
+Error
+REPL::RunLoop ()
+{
+ Error error;
+
+ error = DoInitialization();
+ m_repl_source_path = GetSourcePath();
+
+ if (!error.Success())
+ return error;
+
+ Debugger &debugger = m_target.GetDebugger();
+
+ lldb::IOHandlerSP io_handler_sp (GetIOHandler());
+
+ FileSpec save_default_file;
+ uint32_t save_default_line = 0;
+
+ if (!m_repl_source_path.empty())
+ {
+ // Save the current default file and line
+ m_target.GetSourceManager().GetDefaultFileAndLine(save_default_file, save_default_line);
+ }
+
+ debugger.PushIOHandler(io_handler_sp);
+
+ // Check if we are in dedicated REPL mode where LLDB was start with the "--repl" option
+ // from the command line. Currently we know this by checking if the debugger already
+ // has a IOHandler thread.
+ if (!debugger.HasIOHandlerThread())
+ {
+ // The debugger doesn't have an existing IOHandler thread, so this must be
+ // dedicated REPL mode...
+ m_dedicated_repl_mode = true;
+ debugger.StartIOHandlerThread();
+ std::string command_name_str ("quit");
+ CommandObject *cmd_obj = debugger.GetCommandInterpreter().GetCommandObjectForCommand(command_name_str);
+ if (cmd_obj)
+ {
+ assert(command_name_str.empty());
+ cmd_obj->SetOverrideCallback (QuitCommandOverrideCallback, &m_target);
+ }
+ }
+
+ // Wait for the REPL command interpreter to get popped
+ io_handler_sp->WaitForPop();
+
+ if (m_dedicated_repl_mode)
+ {
+ // If we were in dedicated REPL mode we would have started the
+ // IOHandler thread, and we should kill our process
+ lldb::ProcessSP process_sp = m_target.GetProcessSP();
+ if (process_sp && process_sp->IsAlive())
+ process_sp->Destroy(false);
+
+ // Wait for the IO handler thread to exit (TODO: don't do this if the IO handler thread already exists...)
+ debugger.JoinIOHandlerThread();
+ }
+
+ // Restore the default file and line
+ if (save_default_file && save_default_line != 0)
+ m_target.GetSourceManager().SetDefaultFileAndLine(save_default_file, save_default_line);
+ return error;
+}
diff --git a/contrib/llvm/tools/lldb/source/Expression/UserExpression.cpp b/contrib/llvm/tools/lldb/source/Expression/UserExpression.cpp
new file mode 100644
index 0000000..70f004b
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Expression/UserExpression.cpp
@@ -0,0 +1,348 @@
+//===-- UserExpression.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <cstdlib>
+#include <string>
+#include <map>
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Expression/UserExpression.h"
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+
+using namespace lldb_private;
+
+UserExpression::UserExpression (ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type,
+ const EvaluateExpressionOptions &options) :
+ Expression(exe_scope),
+ m_expr_text(expr),
+ m_expr_prefix(expr_prefix ? expr_prefix : ""),
+ m_language(language),
+ m_desired_type(desired_type),
+ m_options (options)
+{
+}
+
+UserExpression::~UserExpression ()
+{
+}
+
+void
+UserExpression::InstallContext (ExecutionContext &exe_ctx)
+{
+ m_jit_process_wp = exe_ctx.GetProcessSP();
+
+ lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
+
+ if (frame_sp)
+ m_address = frame_sp->GetFrameCodeAddress();
+}
+
+bool
+UserExpression::LockAndCheckContext (ExecutionContext &exe_ctx,
+ lldb::TargetSP &target_sp,
+ lldb::ProcessSP &process_sp,
+ lldb::StackFrameSP &frame_sp)
+{
+ lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
+ process_sp = exe_ctx.GetProcessSP();
+
+ if (process_sp != expected_process_sp)
+ return false;
+
+ process_sp = exe_ctx.GetProcessSP();
+ target_sp = exe_ctx.GetTargetSP();
+ frame_sp = exe_ctx.GetFrameSP();
+
+ if (m_address.IsValid())
+ {
+ if (!frame_sp)
+ return false;
+ else
+ return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get()));
+ }
+
+ return true;
+}
+
+bool
+UserExpression::MatchesContext (ExecutionContext &exe_ctx)
+{
+ lldb::TargetSP target_sp;
+ lldb::ProcessSP process_sp;
+ lldb::StackFrameSP frame_sp;
+
+ return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
+}
+
+lldb::addr_t
+UserExpression::GetObjectPointer (lldb::StackFrameSP frame_sp,
+ ConstString &object_name,
+ Error &err)
+{
+ err.Clear();
+
+ if (!frame_sp)
+ {
+ err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ lldb::VariableSP var_sp;
+ lldb::ValueObjectSP valobj_sp;
+
+ valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
+ lldb::eNoDynamicValues,
+ StackFrame::eExpressionPathOptionCheckPtrVsMember |
+ StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
+ StackFrame::eExpressionPathOptionsNoSyntheticChildren |
+ StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
+ var_sp,
+ err);
+
+ if (!err.Success() || !valobj_sp.get())
+ return LLDB_INVALID_ADDRESS;
+
+ lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (ret == LLDB_INVALID_ADDRESS)
+ {
+ err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ return ret;
+}
+
+lldb::ExpressionResults
+UserExpression::Evaluate (ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions& options,
+ const char *expr_cstr,
+ const char *expr_prefix,
+ lldb::ValueObjectSP &result_valobj_sp,
+ Error &error,
+ uint32_t line_offset,
+ lldb::ModuleSP *jit_module_sp_ptr)
+{
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+
+ lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
+ lldb::LanguageType language = options.GetLanguage();
+ const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
+ lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
+
+ Target *target = exe_ctx.GetTargetPtr();
+ if (!target)
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
+ return lldb::eExpressionSetupError;
+ }
+
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process == NULL || process->GetState() != lldb::eStateStopped)
+ {
+ if (execution_policy == eExecutionPolicyAlways)
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
+
+ error.SetErrorString ("expression needed to run but couldn't");
+
+ return execution_results;
+ }
+ }
+
+ if (process == NULL || !process->CanJIT())
+ execution_policy = eExecutionPolicyNever;
+
+ const char *full_prefix = NULL;
+ const char *option_prefix = options.GetPrefix();
+ std::string full_prefix_storage;
+ if (expr_prefix && option_prefix)
+ {
+ full_prefix_storage.assign(expr_prefix);
+ full_prefix_storage.append(option_prefix);
+ if (!full_prefix_storage.empty())
+ full_prefix = full_prefix_storage.c_str();
+ }
+ else if (expr_prefix)
+ full_prefix = expr_prefix;
+ else
+ full_prefix = option_prefix;
+
+ // If the language was not specified in the expression command,
+ // set it to the language in the target's properties if
+ // specified, else default to the langage for the frame.
+ if (language == lldb::eLanguageTypeUnknown)
+ {
+ if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
+ language = target->GetLanguage();
+ else if (StackFrame *frame = exe_ctx.GetFramePtr())
+ language = frame->GetLanguage();
+ }
+
+ lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
+ full_prefix,
+ language,
+ desired_type,
+ options,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
+ return lldb::eExpressionSetupError;
+ }
+
+ StreamString error_stream;
+
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
+
+ const bool keep_expression_in_memory = true;
+ const bool generate_debug_info = options.GetGenerateDebugInfo();
+
+ if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
+ {
+ error.SetErrorString ("expression interrupted by callback before parse");
+ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
+ return lldb::eExpressionInterrupted;
+ }
+
+ if (!user_expression_sp->Parse (error_stream,
+ exe_ctx,
+ execution_policy,
+ keep_expression_in_memory,
+ generate_debug_info))
+ {
+ execution_results = lldb::eExpressionParseError;
+ if (error_stream.GetString().empty())
+ error.SetExpressionError (execution_results, "expression failed to parse, unknown error");
+ else
+ error.SetExpressionError (execution_results, error_stream.GetString().c_str());
+ }
+ else
+ {
+ // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
+ if (jit_module_sp_ptr)
+ *jit_module_sp_ptr = user_expression_sp->GetJITModule();
+
+ lldb::ExpressionVariableSP expr_result;
+
+ if (execution_policy == eExecutionPolicyNever &&
+ !user_expression_sp->CanInterpret())
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
+
+ if (error_stream.GetString().empty())
+ error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
+ }
+ else
+ {
+ if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
+ {
+ error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
+ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
+ return lldb::eExpressionInterrupted;
+ }
+
+ error_stream.GetString().clear();
+
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Executing expression ==");
+
+ execution_results = user_expression_sp->Execute (error_stream,
+ exe_ctx,
+ options,
+ user_expression_sp,
+ expr_result);
+
+ if (options.GetResultIsInternal() && expr_result && process)
+ {
+ process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result);
+ }
+
+ if (execution_results != lldb::eExpressionCompleted)
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");
+
+ if (error_stream.GetString().empty())
+ error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
+ else
+ error.SetExpressionError (execution_results, error_stream.GetString().c_str());
+ }
+ else
+ {
+ if (expr_result)
+ {
+ result_valobj_sp = expr_result->GetValueObject();
+
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
+ result_valobj_sp->GetValueAsCString());
+ }
+ else
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");
+
+ error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
+ }
+ }
+ }
+ }
+
+ if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
+ {
+ error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
+ return lldb::eExpressionInterrupted;
+ }
+
+ if (result_valobj_sp.get() == NULL)
+ {
+ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
+ }
+
+ return execution_results;
+}
diff --git a/contrib/llvm/tools/lldb/source/Expression/UtilityFunction.cpp b/contrib/llvm/tools/lldb/source/Expression/UtilityFunction.cpp
new file mode 100644
index 0000000..f93e358
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Expression/UtilityFunction.cpp
@@ -0,0 +1,124 @@
+//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+// C++ Includes
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+//------------------------------------------------------------------
+/// Constructor
+///
+/// @param[in] text
+/// The text of the function. Must be a full translation unit.
+///
+/// @param[in] name
+/// The name of the function, as used in the text.
+//------------------------------------------------------------------
+UtilityFunction::UtilityFunction (ExecutionContextScope &exe_scope,
+ const char *text,
+ const char *name) :
+ Expression (exe_scope),
+ m_execution_unit_sp (),
+ m_jit_module_wp (),
+ m_function_text (ExpressionSourceCode::g_expression_prefix),
+ m_function_name (name)
+{
+ if (text && text[0])
+ m_function_text.append (text);
+}
+
+UtilityFunction::~UtilityFunction ()
+{
+ lldb::ProcessSP process_sp (m_jit_process_wp.lock());
+ if (process_sp)
+ {
+ lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
+ if (jit_module_sp)
+ process_sp->GetTarget().GetImages().Remove(jit_module_sp);
+ }
+
+}
+
+// FIXME: We should check that every time this is called it is called with the same return type & arguments...
+
+FunctionCaller *
+UtilityFunction::MakeFunctionCaller (const CompilerType &return_type, const ValueList &arg_value_list, Error &error)
+{
+ if (m_caller_up)
+ return m_caller_up.get();
+
+ ProcessSP process_sp = m_jit_process_wp.lock();
+ if (!process_sp)
+ return nullptr;
+
+ Address impl_code_address;
+ impl_code_address.SetOffset(StartAddress());
+ std::string name(m_function_name);
+ name.append("-caller");
+
+ m_caller_up.reset (process_sp->GetTarget().GetFunctionCallerForLanguage (Language(),
+ return_type,
+ impl_code_address,
+ arg_value_list,
+ name.c_str(),
+ error));
+ if (error.Fail())
+ {
+
+ return nullptr;
+ }
+ if (m_caller_up)
+ {
+ StreamString errors;
+ errors.Clear();
+ unsigned num_errors = m_caller_up->CompileFunction(errors);
+ if (num_errors)
+ {
+ error.SetErrorStringWithFormat ("Error compiling %s caller function: \"%s\".",
+ m_function_name.c_str(),
+ errors.GetData());
+ m_caller_up.reset();
+ return nullptr;
+ }
+
+ errors.Clear();
+ ExecutionContext exe_ctx(process_sp);
+
+ if (!m_caller_up->WriteFunctionWrapper(exe_ctx, errors))
+ {
+ error.SetErrorStringWithFormat ("Error inserting caller function for %s: \"%s\".",
+ m_function_name.c_str(),
+ errors.GetData());
+ m_caller_up.reset();
+ return nullptr;
+ }
+ }
+ return m_caller_up.get();
+}
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp b/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp
index ed67d0c..4640154 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/Editline.cpp
@@ -203,7 +203,7 @@ namespace lldb_private
{
snprintf (history_path, sizeof (history_path), "~/%s-widehistory", m_prefix.c_str());
}
- m_path = std::move (FileSpec (history_path, true).GetPath());
+ m_path = FileSpec (history_path, true).GetPath();
}
if (m_path.empty())
return NULL;
@@ -863,34 +863,50 @@ Editline::NextLineCommand (int ch)
unsigned char
Editline::FixIndentationCommand (int ch)
{
- if (!m_fix_indentation_callback)
+ if (!m_fix_indentation_callback)
return CC_NORM;
-
- // Insert the character by hand prior to correction
+
+ // Insert the character typed before proceeding
EditLineCharType inserted[] = { (EditLineCharType)ch, 0 };
el_winsertstr (m_editline, inserted);
- SaveEditedLine();
- StringList lines = GetInputAsStringList (m_current_line_index + 1);
-
- // Determine the cursor position
LineInfoW * info = const_cast<LineInfoW *>(el_wline (m_editline));
int cursor_position = info->cursor - info->buffer;
-
+
+ // Save the edits and determine the correct indentation level
+ SaveEditedLine();
+ StringList lines = GetInputAsStringList (m_current_line_index + 1);
int indent_correction = m_fix_indentation_callback (this, lines, cursor_position, m_fix_indentation_callback_baton);
-
- // Adjust the input buffer to correct indentation
+
+ // If it is already correct no special work is needed
+ if (indent_correction == 0)
+ return CC_REFRESH;
+
+ // Change the indentation level of the line
+ std::string currentLine = lines.GetStringAtIndex (m_current_line_index);
if (indent_correction > 0)
{
- info->cursor = info->buffer;
- el_winsertstr (m_editline, EditLineStringType (indent_correction, EditLineCharType(' ')).c_str());
+ currentLine = currentLine.insert (0, indent_correction, ' ');
}
- else if (indent_correction < 0)
+ else
{
- info->cursor = info->buffer - indent_correction;
- el_wdeletestr (m_editline, -indent_correction);
+ currentLine = currentLine.erase (0, -indent_correction);
}
- info->cursor = info->buffer + cursor_position + indent_correction;
- return CC_REFRESH;
+#if LLDB_EDITLINE_USE_WCHAR
+ m_input_lines[m_current_line_index] = m_utf8conv.from_bytes (currentLine);
+#else
+ m_input_lines[m_current_line_index] = currentLine;
+#endif
+
+ // Update the display to reflect the change
+ MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
+ DisplayInput (m_current_line_index);
+
+ // Reposition the cursor back on the original line and prepare to restart editing
+ // with a new cursor position
+ SetCurrentLine (m_current_line_index);
+ MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
+ m_revert_cursor_index = cursor_position + indent_correction;
+ return CC_NEWLINE;
}
unsigned char
diff --git a/contrib/llvm/tools/lldb/source/Host/common/File.cpp b/contrib/llvm/tools/lldb/source/Host/common/File.cpp
index a3420bf..71a6149 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/File.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/File.cpp
@@ -22,6 +22,8 @@
#include <sys/ioctl.h>
#endif
+#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors()
+
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
@@ -143,7 +145,13 @@ File::GetDescriptor() const
// Don't open the file descriptor if we don't need to, just get it from the
// stream if we have one.
if (StreamIsValid())
- return fileno (m_stream);
+ {
+#if defined(LLVM_ON_WIN32)
+ return _fileno(m_stream);
+#else
+ return fileno(m_stream);
+#endif
+ }
// Invalid descriptor and invalid stream, return invalid descriptor.
return kInvalidDescriptor;
@@ -1045,7 +1053,11 @@ File::CalculateInteractiveAndTerminal ()
if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0)
{
if (window_size.ws_col > 0)
+ {
m_is_real_terminal = eLazyBoolYes;
+ if (llvm::sys::Process::FileDescriptorHasColors(fd))
+ m_supports_colors = eLazyBoolYes;
+ }
}
}
#endif
@@ -1068,3 +1080,11 @@ File::GetIsRealTerminal ()
return m_is_real_terminal == eLazyBoolYes;
}
+bool
+File::GetIsTerminalWithColors ()
+{
+ if (m_supports_colors == eLazyBoolCalculate)
+ CalculateInteractiveAndTerminal();
+ return m_supports_colors == eLazyBoolYes;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Host/common/FileSpec.cpp b/contrib/llvm/tools/lldb/source/Host/common/FileSpec.cpp
index ceb094b..8885a79 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/FileSpec.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/FileSpec.cpp
@@ -107,7 +107,7 @@ FileSpec::ResolveUsername (llvm::SmallVectorImpl<char> &path)
return;
llvm::StringRef path_str(path.data(), path.size());
- size_t slash_pos = path_str.find_first_of("/", 1);
+ size_t slash_pos = path_str.find('/', 1);
if (slash_pos == 1 || path.size() == 1)
{
// A path of ~/ resolves to the current user's home dir
@@ -789,6 +789,28 @@ FileSpec::GetFileType () const
return eFileTypeInvalid;
}
+bool
+FileSpec::IsSymbolicLink () const
+{
+ char resolved_path[PATH_MAX];
+ if (!GetPath (resolved_path, sizeof (resolved_path)))
+ return false;
+
+#ifdef _WIN32
+ auto attrs = ::GetFileAttributes (resolved_path);
+ if (attrs == INVALID_FILE_ATTRIBUTES)
+ return false;
+
+ return (attrs & FILE_ATTRIBUTE_REPARSE_POINT);
+#else
+ struct stat file_stats;
+ if (::lstat (resolved_path, &file_stats) != 0)
+ return false;
+
+ return (file_stats.st_mode & S_IFMT) == S_IFLNK;
+#endif
+}
+
uint32_t
FileSpec::GetPermissions () const
{
@@ -1409,7 +1431,7 @@ FileSpec::AppendPathComponent(const char *new_path)
return;
}
StreamString stream;
- if (m_filename.IsEmpty())
+ if (m_filename.IsEmpty() || (m_filename.GetLength() == 1 && m_filename.GetCString()[0] == '.'))
stream.Printf("%s/%s", m_directory.GetCString(), new_path);
else if (m_directory.IsEmpty())
stream.Printf("%s/%s", m_filename.GetCString(), new_path);
diff --git a/contrib/llvm/tools/lldb/source/Host/common/GetOptInc.cpp b/contrib/llvm/tools/lldb/source/Host/common/GetOptInc.cpp
new file mode 100644
index 0000000..7689f36
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Host/common/GetOptInc.cpp
@@ -0,0 +1,473 @@
+#include "lldb/Host/common/GetOptInc.h"
+
+#if defined(REPLACE_GETOPT) || defined(REPLACE_GETOPT_LONG) || defined(REPLACE_GETOPT_LONG_ONLY)
+
+// getopt.cpp
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(REPLACE_GETOPT)
+int opterr = 1; /* if error message should be printed */
+int optind = 1; /* index into parent argv vector */
+int optopt = '?'; /* character checked for validity */
+int optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+#endif
+
+#define PRINT_ERROR ((opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
+#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
+#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
+
+/* return values */
+#define BADCH (int)'?'
+#define BADARG ((*options == ':') ? (int)':' : (int)'?')
+#define INORDER (int)1
+
+#define EMSG ""
+
+static int getopt_internal(int, char * const *, const char *,
+ const struct option *, int *, int);
+static int parse_long_options(char * const *, const char *,
+ const struct option *, int *, int);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static const char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1; /* first option after non options (for permute) */
+
+/*
+* Compute the greatest common divisor of a and b.
+*/
+static int
+gcd(int a, int b)
+{
+ int c;
+
+ c = a % b;
+ while (c != 0) {
+ a = b;
+ b = c;
+ c = a % b;
+ }
+
+ return (b);
+}
+
+static void pass() {}
+#define warnx(a, ...) pass();
+
+/*
+* Exchange the block from nonopt_start to nonopt_end with the block
+* from nonopt_end to opt_end (keeping the same order of arguments
+* in each block).
+*/
+static void
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
+char * const *nargv)
+{
+ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+ char *swap;
+
+ /*
+ * compute lengths of blocks and number and size of cycles
+ */
+ nnonopts = panonopt_end - panonopt_start;
+ nopts = opt_end - panonopt_end;
+ ncycle = gcd(nnonopts, nopts);
+ cyclelen = (opt_end - panonopt_start) / ncycle;
+
+ for (i = 0; i < ncycle; i++) {
+ cstart = panonopt_end + i;
+ pos = cstart;
+ for (j = 0; j < cyclelen; j++) {
+ if (pos >= panonopt_end)
+ pos -= nnonopts;
+ else
+ pos += nopts;
+ swap = nargv[pos];
+ /* LINTED const cast */
+ ((char **)nargv)[pos] = nargv[cstart];
+ /* LINTED const cast */
+ ((char **)nargv)[cstart] = swap;
+ }
+ }
+}
+
+/*
+* parse_long_options --
+* Parse long options in argc/argv argument vector.
+* Returns -1 if short_too is set and the option does not match long_options.
+*/
+static int
+parse_long_options(char * const *nargv, const char *options,
+const struct option *long_options, int *idx, int short_too)
+{
+ char *current_argv, *has_equal;
+ size_t current_argv_len;
+ int i, match;
+
+ current_argv = const_cast<char*>(place);
+ match = -1;
+
+ optind++;
+
+ if ((has_equal = strchr(current_argv, '=')) != NULL) {
+ /* argument found (--option=arg) */
+ current_argv_len = has_equal - current_argv;
+ has_equal++;
+ }
+ else
+ current_argv_len = strlen(current_argv);
+
+ for (i = 0; long_options[i].name; i++) {
+ /* find matching long option */
+ if (strncmp(current_argv, long_options[i].name,
+ current_argv_len))
+ continue;
+
+ if (strlen(long_options[i].name) == current_argv_len) {
+ /* exact match */
+ match = i;
+ break;
+ }
+ /*
+ * If this is a known short option, don't allow
+ * a partial match of a single character.
+ */
+ if (short_too && current_argv_len == 1)
+ continue;
+
+ if (match == -1) /* partial match */
+ match = i;
+ else {
+ /* ambiguous abbreviation */
+ if (PRINT_ERROR)
+ warnx(ambig, (int)current_argv_len,
+ current_argv);
+ optopt = 0;
+ return (BADCH);
+ }
+ }
+ if (match != -1) { /* option found */
+ if (long_options[match].has_arg == no_argument
+ && has_equal) {
+ if (PRINT_ERROR)
+ warnx(noarg, (int)current_argv_len,
+ current_argv);
+ /*
+ * XXX: GNU sets optopt to val regardless of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ return (BADARG);
+ }
+ if (long_options[match].has_arg == required_argument ||
+ long_options[match].has_arg == optional_argument) {
+ if (has_equal)
+ optarg = has_equal;
+ else if (long_options[match].has_arg ==
+ required_argument) {
+ /*
+ * optional argument doesn't use next nargv
+ */
+ optarg = nargv[optind++];
+ }
+ }
+ if ((long_options[match].has_arg == required_argument)
+ && (optarg == NULL)) {
+ /*
+ * Missing argument; leading ':' indicates no error
+ * should be generated.
+ */
+ if (PRINT_ERROR)
+ warnx(recargstring,
+ current_argv);
+ /*
+ * XXX: GNU sets optopt to val regardless of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ --optind;
+ return (BADARG);
+ }
+ }
+ else { /* unknown option */
+ if (short_too) {
+ --optind;
+ return (-1);
+ }
+ if (PRINT_ERROR)
+ warnx(illoptstring, current_argv);
+ optopt = 0;
+ return (BADCH);
+ }
+ if (idx)
+ *idx = match;
+ if (long_options[match].flag) {
+ *long_options[match].flag = long_options[match].val;
+ return (0);
+ }
+ else
+ return (long_options[match].val);
+}
+
+/*
+* getopt_internal --
+* Parse argc/argv argument vector. Called by user level routines.
+*/
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options,
+const struct option *long_options, int *idx, int flags)
+{
+ const char *oli; /* option letter list index */
+ int optchar, short_too;
+ static int posixly_correct = -1;
+
+ if (options == NULL)
+ return (-1);
+
+ /*
+ * XXX Some GNU programs (like cvs) set optind to 0 instead of
+ * XXX using optreset. Work around this braindamage.
+ */
+ if (optind == 0)
+ optind = optreset = 1;
+
+ /*
+ * Disable GNU extensions if POSIXLY_CORRECT is set or options
+ * string begins with a '+'.
+ */
+ if (posixly_correct == -1 || optreset)
+ posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+ if (*options == '-')
+ flags |= FLAG_ALLARGS;
+ else if (posixly_correct || *options == '+')
+ flags &= ~FLAG_PERMUTE;
+ if (*options == '+' || *options == '-')
+ options++;
+
+ optarg = NULL;
+ if (optreset)
+ nonopt_start = nonopt_end = -1;
+start:
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc) { /* end of argument vector */
+ place = EMSG;
+ if (nonopt_end != -1) {
+ /* do permutation, if we have to */
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ else if (nonopt_start != -1) {
+ /*
+ * If we skipped non-options, set optind
+ * to the first of them.
+ */
+ optind = nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return (-1);
+ }
+ if (*(place = nargv[optind]) != '-' ||
+ (place[1] == '\0' && strchr(options, '-') == NULL)) {
+ place = EMSG; /* found non-option */
+ if (flags & FLAG_ALLARGS) {
+ /*
+ * GNU extension:
+ * return non-option as argument to option 1
+ */
+ optarg = nargv[optind++];
+ return (INORDER);
+ }
+ if (!(flags & FLAG_PERMUTE)) {
+ /*
+ * If no permutation wanted, stop parsing
+ * at first non-option.
+ */
+ return (-1);
+ }
+ /* do permutation */
+ if (nonopt_start == -1)
+ nonopt_start = optind;
+ else if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ nonopt_start = optind -
+ (nonopt_end - nonopt_start);
+ nonopt_end = -1;
+ }
+ optind++;
+ /* process next argument */
+ goto start;
+ }
+ if (nonopt_start != -1 && nonopt_end == -1)
+ nonopt_end = optind;
+
+ /*
+ * If we have "-" do nothing, if "--" we are done.
+ */
+ if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+ optind++;
+ place = EMSG;
+ /*
+ * We found an option (--), so if we skipped
+ * non-options, we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return (-1);
+ }
+ }
+
+ /*
+ * Check long options if:
+ * 1) we were passed some
+ * 2) the arg is not just "-"
+ * 3) either the arg starts with -- we are getopt_long_only()
+ */
+ if (long_options != NULL && place != nargv[optind] &&
+ (*place == '-' || (flags & FLAG_LONGONLY))) {
+ short_too = 0;
+ if (*place == '-')
+ place++; /* --foo long option */
+ else if (*place != ':' && strchr(options, *place) != NULL)
+ short_too = 1; /* could be short option too */
+
+ optchar = parse_long_options(nargv, options, long_options,
+ idx, short_too);
+ if (optchar != -1) {
+ place = EMSG;
+ return (optchar);
+ }
+ }
+
+ if ((optchar = (int)*place++) == (int)':' ||
+ (optchar == (int)'-' && *place != '\0') ||
+ (oli = strchr(options, optchar)) == NULL) {
+ /*
+ * If the user specified "-" and '-' isn't listed in
+ * options, return -1 (non-option) as per POSIX.
+ * Otherwise, it is an unknown option character (or ':').
+ */
+ if (optchar == (int)'-' && *place == '\0')
+ return (-1);
+ if (!*place)
+ ++optind;
+ if (PRINT_ERROR)
+ warnx(illoptchar, optchar);
+ optopt = optchar;
+ return (BADCH);
+ }
+ if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+ /* -W long-option */
+ if (*place) /* no space */
+ /* NOTHING */;
+ else if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+ optopt = optchar;
+ return (BADARG);
+ }
+ else /* white space */
+ place = nargv[optind];
+ optchar = parse_long_options(nargv, options, long_options,
+ idx, 0);
+ place = EMSG;
+ return (optchar);
+ }
+ if (*++oli != ':') { /* doesn't take argument */
+ if (!*place)
+ ++optind;
+ }
+ else { /* takes (optional) argument */
+ optarg = NULL;
+ if (*place) /* no white space */
+ optarg = const_cast<char*>(place);
+ else if (oli[1] != ':') { /* arg not optional */
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+ optopt = optchar;
+ return (BADARG);
+ }
+ else
+ optarg = nargv[optind];
+ }
+ place = EMSG;
+ ++optind;
+ }
+ /* dump back option letter */
+ return (optchar);
+}
+
+/*
+* getopt --
+* Parse argc/argv argument vector.
+*
+* [eventually this will replace the BSD getopt]
+*/
+#if defined(REPLACE_GETOPT)
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+
+ /*
+ * We don't pass FLAG_PERMUTE to getopt_internal() since
+ * the BSD getopt(3) (unlike GNU) has never done this.
+ *
+ * Furthermore, since many privileged programs call getopt()
+ * before dropping privileges it makes sense to keep things
+ * as simple (and bug-free) as possible.
+ */
+ return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
+}
+#endif
+
+/*
+* getopt_long --
+* Parse argc/argv argument vector.
+*/
+#if defined(REPLACE_GETOPT_LONG)
+int
+getopt_long(int nargc, char * const *nargv, const char *options,
+const struct option *long_options, int *idx)
+{
+ return (getopt_internal(nargc, nargv, options, long_options, idx,
+ FLAG_PERMUTE));
+}
+#endif
+
+/*
+* getopt_long_only --
+* Parse argc/argv argument vector.
+*/
+#if defined(REPLACE_GETOPT_LONG_ONLY)
+int
+getopt_long_only(int nargc, char * const *nargv, const char *options,
+const struct option *long_options, int *idx)
+{
+
+ return (getopt_internal(nargc, nargv, options, long_options, idx,
+ FLAG_PERMUTE | FLAG_LONGONLY));
+}
+#endif
+
+#endif
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Host.cpp b/contrib/llvm/tools/lldb/source/Host/common/Host.cpp
index 94c78a0..e89f4de 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/Host.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/Host.cpp
@@ -143,7 +143,11 @@ private:
#endif // __linux__
#ifdef __linux__
+#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
+static __thread volatile sig_atomic_t g_usr1_called;
+#else
static thread_local volatile sig_atomic_t g_usr1_called;
+#endif
static void
SigUsr1Handler (int)
@@ -816,8 +820,8 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau
#endif
const char *tmp_argv[2];
- char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector();
- char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector();
+ char * const *argv = const_cast<char * const*>(launch_info.GetArguments().GetConstArgumentVector());
+ char * const *envp = const_cast<char * const*>(launch_info.GetEnvironmentEntries().GetConstArgumentVector());
if (argv == NULL)
{
// posix_spawn gets very unhappy if it doesn't have at least the program
@@ -825,7 +829,7 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau
// variables don't make it into the child process if "argv == NULL"!!!
tmp_argv[0] = exe_path;
tmp_argv[1] = NULL;
- argv = (char * const*)tmp_argv;
+ argv = const_cast<char * const*>(tmp_argv);
}
#if !defined (__APPLE__)
diff --git a/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp b/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp
index e969e33..f7ba755 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/HostInfoBase.cpp
@@ -20,6 +20,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <thread>
@@ -102,7 +103,7 @@ HostInfoBase::GetVendorString()
{
static std::once_flag g_once_flag;
std::call_once(g_once_flag, []() {
- g_fields->m_vendor_string = std::move(HostInfo::GetArchitecture().GetTriple().getVendorName().str());
+ g_fields->m_vendor_string = HostInfo::GetArchitecture().GetTriple().getVendorName().str();
});
return g_fields->m_vendor_string;
}
@@ -306,7 +307,10 @@ HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
FileSpec lldb_file_spec(
Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));
-
+
+ // This is necessary because when running the testsuite the shlib might be a symbolic link inside the Python resource dir.
+ FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec);
+
// Remove the filename so that this FileSpec only represents the directory.
file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
@@ -341,19 +345,9 @@ HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec)
bool
HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec)
{
- file_spec.Clear();
-
- const char *tmpdir_cstr = getenv("TMPDIR");
- if (tmpdir_cstr == nullptr)
- {
- tmpdir_cstr = getenv("TMP");
- if (tmpdir_cstr == nullptr)
- tmpdir_cstr = getenv("TEMP");
- }
- if (!tmpdir_cstr)
- return false;
-
- file_spec = FileSpec(tmpdir_cstr, false);
+ llvm::SmallVector<char, 16> tmpdir;
+ llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);
+ file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true);
return true;
}
@@ -415,13 +409,13 @@ HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_6
arch_32.SetTriple(triple);
break;
+ case llvm::Triple::aarch64:
case llvm::Triple::ppc64:
case llvm::Triple::x86_64:
arch_64.SetTriple(triple);
arch_32.SetTriple(triple.get32BitArchVariant());
break;
- case llvm::Triple::aarch64:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
case llvm::Triple::sparcv9:
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Mutex.cpp b/contrib/llvm/tools/lldb/source/Host/common/Mutex.cpp
index c26467f..98f5321 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/Mutex.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/Mutex.cpp
@@ -27,7 +27,7 @@
#endif
// Enable extra mutex error checking
-#ifdef LLDB_CONFIGURATION_DEBUG
+#if 0 // LLDB_CONFIGURATION_DEBUG
#define ENABLE_MUTEX_ERROR_CHECKING 1
#include <inttypes.h>
#endif
diff --git a/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp b/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp
index 818d69b..7d2f401 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/NativeProcessProtocol.cpp
@@ -436,12 +436,6 @@ NativeProcessProtocol::DoStopIDBumped (uint32_t /* newBumpId */)
// Default implementation does nothing.
}
-void
-NativeProcessProtocol::Terminate ()
-{
- // Default implementation does nothing.
-}
-
#ifndef __linux__
// These need to be implemented to support lldb-gdb-server on a given platform. Stubs are
// provided to make the rest of the code link on non-supported platforms.
@@ -449,6 +443,7 @@ NativeProcessProtocol::Terminate ()
Error
NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info,
NativeDelegate &native_delegate,
+ MainLoop &mainloop,
NativeProcessProtocolSP &process_sp)
{
llvm_unreachable("Platform has no NativeProcessProtocol support");
@@ -457,6 +452,7 @@ NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info,
Error
NativeProcessProtocol::Attach (lldb::pid_t pid,
NativeDelegate &native_delegate,
+ MainLoop &mainloop,
NativeProcessProtocolSP &process_sp)
{
llvm_unreachable("Platform has no NativeProcessProtocol support");
diff --git a/contrib/llvm/tools/lldb/source/Host/common/OptionParser.cpp b/contrib/llvm/tools/lldb/source/Host/common/OptionParser.cpp
index a91e764..a978459 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/OptionParser.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/OptionParser.cpp
@@ -16,8 +16,10 @@
using namespace lldb_private;
void
-OptionParser::Prepare()
+OptionParser::Prepare(Mutex::Locker &locker)
{
+ static Mutex g_mutex(Mutex::eMutexTypeNormal);
+ locker.Lock(g_mutex);
#ifdef __GLIBC__
optind = 0;
#else
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp b/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp
index f7e93c6..91a5e37 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/Socket.cpp
@@ -12,21 +12,16 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Host/Config.h"
-#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/SocketAddress.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/TimeValue.h"
-
-#ifdef __ANDROID_NDK__
-#include <linux/tcp.h>
-#include <bits/error_constants.h>
-#include <asm-generic/errno-base.h>
-#include <errno.h>
-#include <arpa/inet.h>
-#endif
+#include "lldb/Host/common/TCPSocket.h"
+#include "lldb/Host/common/UDPSocket.h"
#ifndef LLDB_DISABLE_POSIX
+#include "lldb/Host/posix/DomainSocket.h"
+
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
@@ -35,6 +30,23 @@
#include <sys/un.h>
#endif
+#ifdef __linux__
+#include "lldb/Host/linux/AbstractSocket.h"
+#endif
+
+#ifdef __ANDROID_NDK__
+#include <linux/tcp.h>
+#include <bits/error_constants.h>
+#include <asm-generic/errno-base.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#if defined(ANDROID_ARM_BUILD_STATIC) || defined(ANDROID_MIPS_BUILD_STATIC)
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <fcntl.h>
+#endif // ANDROID_ARM_BUILD_STATIC || ANDROID_MIPS_BUILD_STATIC
+#endif // __ANDROID_NDK__
+
using namespace lldb;
using namespace lldb_private;
@@ -48,48 +60,8 @@ typedef void * get_socket_option_arg_type;
const NativeSocket Socket::kInvalidSocketValue = -1;
#endif // #if defined(_WIN32)
-#ifdef __ANDROID__
-// Android does not have SUN_LEN
-#ifndef SUN_LEN
-#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path))
-#endif
-#endif // #ifdef __ANDROID__
-
namespace {
-NativeSocket CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit)
-{
- auto socketType = type;
-#ifdef SOCK_CLOEXEC
- if (!child_processes_inherit) {
- socketType |= SOCK_CLOEXEC;
- }
-#endif
- return ::socket (domain, socketType, protocol);
-}
-
-NativeSocket Accept(NativeSocket sockfd, struct sockaddr *addr, socklen_t *addrlen, bool child_processes_inherit)
-{
-#ifdef SOCK_CLOEXEC
- int flags = 0;
- if (!child_processes_inherit) {
- flags |= SOCK_CLOEXEC;
- }
- return ::accept4 (sockfd, addr, addrlen, flags);
-#else
- return ::accept (sockfd, addr, addrlen);
-#endif
-}
-
-void SetLastError(Error &error)
-{
-#if defined(_WIN32)
- error.SetError(::WSAGetLastError(), lldb::eErrorTypeWin32);
-#else
- error.SetErrorToErrno();
-#endif
-}
-
bool IsInterrupted()
{
#if defined(_WIN32)
@@ -114,128 +86,84 @@ Socket::~Socket()
Close();
}
-Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket)
+std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, bool child_processes_inherit, Error &error)
{
- // Store the result in a unique_ptr in case we error out, the memory will get correctly freed.
- std::unique_ptr<Socket> final_socket;
- NativeSocket sock = kInvalidSocketValue;
- Error error;
-
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
- if (log)
- log->Printf ("Socket::TcpConnect (host/port = %s)", host_and_port.data());
-
- std::string host_str;
- std::string port_str;
- int32_t port = INT32_MIN;
- if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
- return error;
-
- // Create the socket
- sock = CreateSocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, child_processes_inherit);
- if (sock == kInvalidSocketValue)
- {
- SetLastError (error);
- return error;
- }
-
- // Since they both refer to the same socket descriptor, arbitrarily choose the send socket to
- // be the owner.
- final_socket.reset(new Socket(sock, ProtocolTcp, true));
-
- // Enable local address reuse
- final_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
-
- struct sockaddr_in sa;
- ::memset (&sa, 0, sizeof (sa));
- sa.sin_family = AF_INET;
- sa.sin_port = htons (port);
-
- int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
+ error.Clear();
- if (inet_pton_result <= 0)
+ std::unique_ptr<Socket> socket_up;
+ switch (protocol)
{
- struct hostent *host_entry = gethostbyname (host_str.c_str());
- if (host_entry)
- host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
- inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
- if (inet_pton_result <= 0)
- {
- if (inet_pton_result == -1)
- SetLastError(error);
- else
- error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
-
- return error;
- }
+ case ProtocolTcp:
+ socket_up.reset(new TCPSocket(child_processes_inherit, error));
+ break;
+ case ProtocolUdp:
+ socket_up.reset(new UDPSocket(child_processes_inherit, error));
+ break;
+ case ProtocolUnixDomain:
+#ifndef LLDB_DISABLE_POSIX
+ socket_up.reset(new DomainSocket(child_processes_inherit, error));
+#else
+ error.SetErrorString("Unix domain sockets are not supported on this platform.");
+#endif
+ break;
+ case ProtocolUnixAbstract:
+#ifdef __linux__
+ socket_up.reset(new AbstractSocket(child_processes_inherit, error));
+#else
+ error.SetErrorString("Abstract domain sockets are not supported on this platform.");
+#endif
+ break;
}
- if (-1 == ::connect (sock, (const struct sockaddr *)&sa, sizeof(sa)))
- {
- SetLastError (error);
- return error;
- }
+ if (error.Fail())
+ socket_up.reset();
- // Keep our TCP packets coming without any delays.
- final_socket->SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
- error.Clear();
- socket = final_socket.release();
- return error;
+ return socket_up;
}
-Error Socket::TcpListen(
- llvm::StringRef host_and_port,
- bool child_processes_inherit,
- Socket *&socket,
- Predicate<uint16_t>* predicate,
- int backlog)
+Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket)
{
- std::unique_ptr<Socket> listen_socket;
- NativeSocket listen_sock = kInvalidSocketValue;
- Error error;
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
+ if (log)
+ log->Printf ("Socket::%s (host/port = %s)", __FUNCTION__, host_and_port.data());
- const sa_family_t family = AF_INET;
- const int socktype = SOCK_STREAM;
- const int protocol = IPPROTO_TCP;
- listen_sock = ::CreateSocket (family, socktype, protocol, child_processes_inherit);
- if (listen_sock == kInvalidSocketValue)
- {
- SetLastError (error);
+ Error error;
+ std::unique_ptr<Socket> connect_socket(Create(ProtocolTcp, child_processes_inherit, error));
+ if (error.Fail())
return error;
- }
- listen_socket.reset(new Socket(listen_sock, ProtocolTcp, true));
+ error = connect_socket->Connect(host_and_port);
+ if (error.Success())
+ socket = connect_socket.release();
- // enable local address reuse
- listen_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
+ return error;
+}
+Error
+Socket::TcpListen (llvm::StringRef host_and_port,
+ bool child_processes_inherit,
+ Socket *&socket,
+ Predicate<uint16_t>* predicate,
+ int backlog)
+{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
if (log)
- log->Printf ("Socket::TcpListen (%s)", host_and_port.data());
+ log->Printf ("Socket::%s (%s)", __FUNCTION__, host_and_port.data());
+ Error error;
std::string host_str;
std::string port_str;
int32_t port = INT32_MIN;
if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
return error;
- SocketAddress anyaddr;
- if (anyaddr.SetToAnyAddress (family, port))
- {
- int err = ::bind (listen_sock, anyaddr, anyaddr.GetLength());
- if (err == -1)
- {
- SetLastError (error);
- return error;
- }
-
- err = ::listen (listen_sock, backlog);
- if (err == -1)
- {
- SetLastError (error);
- return error;
- }
+ std::unique_ptr<TCPSocket> listen_socket(new TCPSocket(child_processes_inherit, error));
+ if (error.Fail())
+ return error;
+ error = listen_socket->Listen(host_and_port, backlog);
+ if (error.Success())
+ {
// We were asked to listen on port zero which means we
// must now read the actual port that was given to us
// as port zero is a special code for "find an open port
@@ -250,287 +178,77 @@ Error Socket::TcpListen(
// another thread in an efficient manor.
if (predicate)
predicate->SetValue (port, eBroadcastAlways);
-
socket = listen_socket.release();
}
return error;
}
-Error Socket::BlockingAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket)
-{
- Error error;
- std::string host_str;
- std::string port_str;
- int32_t port;
- if (!DecodeHostAndPort(host_and_port, host_str, port_str, port, &error))
- return error;
-
- const sa_family_t family = AF_INET;
- const int socktype = SOCK_STREAM;
- const int protocol = IPPROTO_TCP;
- SocketAddress listen_addr;
- if (host_str.empty())
- listen_addr.SetToLocalhost(family, port);
- else if (host_str.compare("*") == 0)
- listen_addr.SetToAnyAddress(family, port);
- else
- {
- if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol))
- {
- error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str());
- return error;
- }
- }
-
- bool accept_connection = false;
- std::unique_ptr<Socket> accepted_socket;
-
- // Loop until we are happy with our connection
- while (!accept_connection)
- {
- struct sockaddr_in accept_addr;
- ::memset (&accept_addr, 0, sizeof accept_addr);
-#if !(defined (__linux__) || defined(_WIN32))
- accept_addr.sin_len = sizeof accept_addr;
-#endif
- socklen_t accept_addr_len = sizeof accept_addr;
-
- int sock = Accept (this->GetNativeSocket(),
- (struct sockaddr *)&accept_addr,
- &accept_addr_len,
- child_processes_inherit);
-
- if (sock == kInvalidSocketValue)
- {
- SetLastError (error);
- break;
- }
-
- bool is_same_addr = true;
-#if !(defined(__linux__) || (defined(_WIN32)))
- is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
-#endif
- if (is_same_addr)
- is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr);
-
- if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY))
- {
- accept_connection = true;
- // Since both sockets have the same descriptor, arbitrarily choose the send
- // socket to be the owner.
- accepted_socket.reset(new Socket(sock, ProtocolTcp, true));
- }
- else
- {
- const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
- const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
- ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
- accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
- listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
- accepted_socket.reset();
- }
- }
-
- if (!accepted_socket)
- return error;
-
- // Keep our TCP packets coming without any delays.
- accepted_socket->SetOption (IPPROTO_TCP, TCP_NODELAY, 1);
- error.Clear();
- socket = accepted_socket.release();
- return error;
-
-}
-
Error Socket::UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket)
{
- std::unique_ptr<Socket> final_send_socket;
- std::unique_ptr<Socket> final_recv_socket;
- NativeSocket final_send_fd = kInvalidSocketValue;
- NativeSocket final_recv_fd = kInvalidSocketValue;
-
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
if (log)
- log->Printf ("Socket::UdpConnect (host/port = %s)", host_and_port.data());
+ log->Printf ("Socket::%s (host/port = %s)", __FUNCTION__, host_and_port.data());
+ return UDPSocket::Connect(host_and_port, child_processes_inherit, send_socket, recv_socket);
+}
+
+Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
+{
Error error;
- std::string host_str;
- std::string port_str;
- int32_t port = INT32_MIN;
- if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
+ std::unique_ptr<Socket> connect_socket(Create(ProtocolUnixDomain, child_processes_inherit, error));
+ if (error.Fail())
return error;
- // Setup the receiving end of the UDP connection on this localhost
- // on port zero. After we bind to port zero we can read the port.
- final_recv_fd = ::CreateSocket (AF_INET, SOCK_DGRAM, 0, child_processes_inherit);
- if (final_recv_fd == kInvalidSocketValue)
- {
- // Socket creation failed...
- SetLastError (error);
- }
- else
- {
- final_recv_socket.reset(new Socket(final_recv_fd, ProtocolUdp, true));
-
- // Socket was created, now lets bind to the requested port
- SocketAddress addr;
- addr.SetToAnyAddress (AF_INET, 0);
+ error = connect_socket->Connect(name);
+ if (error.Success())
+ socket = connect_socket.release();
- if (::bind (final_recv_fd, addr, addr.GetLength()) == -1)
- {
- // Bind failed...
- SetLastError (error);
- }
- }
+ return error;
+}
- assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid()));
+Error Socket::UnixDomainAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
+{
+ Error error;
+ std::unique_ptr<Socket> listen_socket(Create(ProtocolUnixDomain, child_processes_inherit, error));
if (error.Fail())
return error;
- // At this point we have setup the receive port, now we need to
- // setup the UDP send socket
-
- struct addrinfo hints;
- struct addrinfo *service_info_list = NULL;
-
- ::memset (&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM;
- int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list);
- if (err != 0)
- {
- error.SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)",
- host_str.c_str(),
- port_str.c_str(),
- err,
- gai_strerror(err));
- return error;
- }
-
- for (struct addrinfo *service_info_ptr = service_info_list;
- service_info_ptr != NULL;
- service_info_ptr = service_info_ptr->ai_next)
- {
- final_send_fd = ::CreateSocket (service_info_ptr->ai_family,
- service_info_ptr->ai_socktype,
- service_info_ptr->ai_protocol,
- child_processes_inherit);
-
- if (final_send_fd != kInvalidSocketValue)
- {
- final_send_socket.reset(new Socket(final_send_fd, ProtocolUdp, true));
- final_send_socket->m_udp_send_sockaddr = service_info_ptr;
- break;
- }
- else
- continue;
- }
-
- :: freeaddrinfo (service_info_list);
-
- if (final_send_fd == kInvalidSocketValue)
- {
- SetLastError (error);
+ error = listen_socket->Listen(name, 5);
+ if (error.Fail())
return error;
- }
- send_socket = final_send_socket.release();
- recv_socket = final_recv_socket.release();
- error.Clear();
+ error = listen_socket->Accept(name, child_processes_inherit, socket);
return error;
}
-Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
+Error
+Socket::UnixAbstractConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
{
Error error;
-#ifndef LLDB_DISABLE_POSIX
- std::unique_ptr<Socket> final_socket;
-
- // Open the socket that was passed in as an option
- struct sockaddr_un saddr_un;
- int fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit);
- if (fd == kInvalidSocketValue)
- {
- SetLastError (error);
- return error;
- }
-
- final_socket.reset(new Socket(fd, ProtocolUnixDomain, true));
-
- saddr_un.sun_family = AF_UNIX;
- ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1);
- saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
- saddr_un.sun_len = SUN_LEN (&saddr_un);
-#endif
-
- if (::connect (fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
- {
- SetLastError (error);
+ std::unique_ptr<Socket> connect_socket(Create(ProtocolUnixAbstract, child_processes_inherit, error));
+ if (error.Fail())
return error;
- }
- socket = final_socket.release();
-#else
- error.SetErrorString("Unix domain sockets are not supported on this platform.");
-#endif
+ error = connect_socket->Connect(name);
+ if (error.Success())
+ socket = connect_socket.release();
return error;
}
-Error Socket::UnixDomainAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
+Error
+Socket::UnixAbstractAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
{
Error error;
-#ifndef LLDB_DISABLE_POSIX
- struct sockaddr_un saddr_un;
- std::unique_ptr<Socket> listen_socket;
- std::unique_ptr<Socket> final_socket;
- NativeSocket listen_fd = kInvalidSocketValue;
- NativeSocket socket_fd = kInvalidSocketValue;
-
- listen_fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit);
- if (listen_fd == kInvalidSocketValue)
- {
- SetLastError (error);
+ std::unique_ptr<Socket> listen_socket(Create(ProtocolUnixAbstract,child_processes_inherit, error));
+ if (error.Fail())
return error;
- }
-
- listen_socket.reset(new Socket(listen_fd, ProtocolUnixDomain, true));
-
- saddr_un.sun_family = AF_UNIX;
- ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1);
- saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
- saddr_un.sun_len = SUN_LEN (&saddr_un);
-#endif
- FileSystem::Unlink(FileSpec{name, true});
- bool success = false;
- if (::bind (listen_fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0)
- {
- if (::listen (listen_fd, 5) == 0)
- {
- socket_fd = Accept (listen_fd, NULL, 0, child_processes_inherit);
- if (socket_fd > 0)
- {
- final_socket.reset(new Socket(socket_fd, ProtocolUnixDomain, true));
- success = true;
- }
- }
- }
-
- if (!success)
- {
- SetLastError (error);
+ error = listen_socket->Listen(name, 5);
+ if (error.Fail())
return error;
- }
- // We are done with the listen port
- listen_socket.reset();
- socket = final_socket.release();
-#else
- error.SetErrorString("Unix domain sockets are not supported on this platform.");
-#endif
+ error = listen_socket->Accept(name, child_processes_inherit, socket);
return error;
}
@@ -605,7 +323,7 @@ Error Socket::Read (void *buf, size_t &num_bytes)
else
num_bytes = bytes_received;
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_COMMUNICATION));
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
if (log)
{
log->Printf ("%p Socket::Read() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
@@ -626,17 +344,7 @@ Error Socket::Write (const void *buf, size_t &num_bytes)
int bytes_sent = 0;
do
{
- if (m_protocol == ProtocolUdp)
- {
- bytes_sent = ::sendto (m_socket,
- static_cast<const char*>(buf),
- num_bytes,
- 0,
- m_udp_send_sockaddr,
- m_udp_send_sockaddr.GetLength());
- }
- else
- bytes_sent = ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0);
+ bytes_sent = Send(buf, num_bytes);
} while (bytes_sent < 0 && IsInterrupted ());
if (bytes_sent < 0)
@@ -647,7 +355,7 @@ Error Socket::Write (const void *buf, size_t &num_bytes)
else
num_bytes = bytes_sent;
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
if (log)
{
log->Printf ("%p Socket::Write() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
@@ -698,70 +406,84 @@ int Socket::GetOption(int level, int option_name, int &option_value)
{
get_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
socklen_t option_value_size = sizeof(int);
- return ::getsockopt(m_socket, level, option_name, option_value_p, &option_value_size);
+ return ::getsockopt(m_socket, level, option_name, option_value_p, &option_value_size);
}
int Socket::SetOption(int level, int option_name, int option_value)
{
set_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
- return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value));
+ return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value));
}
-uint16_t Socket::GetLocalPortNumber(const NativeSocket& socket)
+size_t Socket::Send(const void *buf, const size_t num_bytes)
{
- // We bound to port zero, so we need to figure out which port we actually bound to
- if (socket != kInvalidSocketValue)
- {
- SocketAddress sock_addr;
- socklen_t sock_addr_len = sock_addr.GetMaxLength ();
- if (::getsockname (socket, sock_addr, &sock_addr_len) == 0)
- return sock_addr.GetPort ();
- }
- return 0;
+ return ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0);
}
-// Return the port number that is being used by the socket.
-uint16_t Socket::GetLocalPortNumber() const
+void Socket::SetLastError(Error &error)
{
- return GetLocalPortNumber (m_socket);
+#if defined(_WIN32)
+ error.SetError(::WSAGetLastError(), lldb::eErrorTypeWin32);
+#else
+ error.SetErrorToErrno();
+#endif
}
-std::string Socket::GetLocalIPAddress () const
+NativeSocket
+Socket::CreateSocket(const int domain,
+ const int type,
+ const int protocol,
+ bool child_processes_inherit,
+ Error& error)
{
- // We bound to port zero, so we need to figure out which port we actually bound to
- if (m_socket != kInvalidSocketValue)
- {
- SocketAddress sock_addr;
- socklen_t sock_addr_len = sock_addr.GetMaxLength ();
- if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0)
- return sock_addr.GetIPAddress ();
- }
- return "";
-}
+ error.Clear();
+ auto socketType = type;
+#ifdef SOCK_CLOEXEC
+ if (!child_processes_inherit)
+ socketType |= SOCK_CLOEXEC;
+#endif
+ auto sock = ::socket (domain, socketType, protocol);
+ if (sock == kInvalidSocketValue)
+ SetLastError(error);
-uint16_t Socket::GetRemotePortNumber () const
-{
- if (m_socket != kInvalidSocketValue)
- {
- SocketAddress sock_addr;
- socklen_t sock_addr_len = sock_addr.GetMaxLength ();
- if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
- return sock_addr.GetPort ();
- }
- return 0;
+ return sock;
}
-std::string Socket::GetRemoteIPAddress () const
+NativeSocket
+Socket::AcceptSocket(NativeSocket sockfd,
+ struct sockaddr *addr,
+ socklen_t *addrlen,
+ bool child_processes_inherit,
+ Error& error)
{
- // We bound to port zero, so we need to figure out which port we actually bound to
- if (m_socket != kInvalidSocketValue)
+ error.Clear();
+#if defined(ANDROID_ARM_BUILD_STATIC) || defined(ANDROID_MIPS_BUILD_STATIC)
+ // Temporary workaround for statically linking Android lldb-server with the
+ // latest API.
+ int fd = syscall(__NR_accept, sockfd, addr, addrlen);
+ if (fd >= 0 && !child_processes_inherit)
{
- SocketAddress sock_addr;
- socklen_t sock_addr_len = sock_addr.GetMaxLength ();
- if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
- return sock_addr.GetIPAddress ();
+ int flags = ::fcntl(fd, F_GETFD);
+ if (flags != -1 && ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1)
+ return fd;
+ SetLastError(error);
+ close(fd);
+ }
+ return fd;
+#elif defined(SOCK_CLOEXEC)
+ int flags = 0;
+ if (!child_processes_inherit) {
+ flags |= SOCK_CLOEXEC;
}
- return "";
+#if defined(__NetBSD__)
+ NativeSocket fd = ::paccept (sockfd, addr, addrlen, nullptr, flags);
+#else
+ NativeSocket fd = ::accept4 (sockfd, addr, addrlen, flags);
+#endif
+#else
+ NativeSocket fd = ::accept (sockfd, addr, addrlen);
+#endif
+ if (fd == kInvalidSocketValue)
+ SetLastError(error);
+ return fd;
}
-
-
diff --git a/contrib/llvm/tools/lldb/source/Host/common/SocketAddress.cpp b/contrib/llvm/tools/lldb/source/Host/common/SocketAddress.cpp
index 3ab6cfe..c8b1687 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/SocketAddress.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/SocketAddress.cpp
@@ -304,8 +304,10 @@ SocketAddress::getaddrinfo (const char *host,
*this = service_info_list;
result = IsValid ();
}
-
- :: freeaddrinfo (service_info_list);
+
+ if (service_info_list)
+ ::freeaddrinfo(service_info_list);
+
return result;
}
diff --git a/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp b/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp
index 2b63f46..60e1dc6 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/Symbols.cpp
@@ -11,6 +11,7 @@
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/StreamString.h"
@@ -37,8 +38,7 @@ int
LocateMacOSXFilesUsingDebugSymbols
(
const ModuleSpec &module_spec,
- FileSpec *out_exec_fspec, // If non-NULL, try and find the executable
- FileSpec *out_dsym_fspec // If non-NULL try and find the debug symbol file
+ ModuleSpec &return_module_spec
);
#else
@@ -47,8 +47,7 @@ int
LocateMacOSXFilesUsingDebugSymbols
(
const ModuleSpec &module_spec,
- FileSpec *out_exec_fspec, // If non-NULL, try and find the executable
- FileSpec *out_dsym_fspec // If non-NULL try and find the debug symbol file
+ ModuleSpec &return_module_spec
) {
// Cannot find MacOSX files using debug symbols on non MacOSX.
return 0;
@@ -79,6 +78,7 @@ FileAtPathContainsArchAndUUID (const FileSpec &file_fspec, const ArchSpec *arch,
static bool
LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym_fspec)
{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
if (exec_fspec)
{
@@ -88,6 +88,17 @@ LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym
// Make sure the module isn't already just a dSYM file...
if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL)
{
+ if (log)
+ {
+ if (module_spec.GetUUIDPtr() && module_spec.GetUUIDPtr()->IsValid())
+ {
+ log->Printf ("Searching for dSYM bundle next to executable %s, UUID %s", path, module_spec.GetUUIDPtr()->GetAsString().c_str());
+ }
+ else
+ {
+ log->Printf ("Searching for dSYM bundle next to executable %s", path);
+ }
+ }
size_t obj_file_path_length = strlen(path);
::strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path) - strlen(path) - 1);
::strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path) - strlen(path) - 1);
@@ -99,6 +110,10 @@ LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym
if (dsym_fspec.Exists() &&
FileAtPathContainsArchAndUUID(dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr()))
{
+ if (log)
+ {
+ log->Printf ("dSYM with matching UUID & arch found at %s", path);
+ }
return true;
}
else
@@ -118,6 +133,10 @@ LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym
if (dsym_fspec.Exists() &&
FileAtPathContainsArchAndUUID(dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr()))
{
+ if (log)
+ {
+ log->Printf ("dSYM with matching UUID & arch found at %s", path);
+ }
return true;
}
else
@@ -154,22 +173,28 @@ LocateExecutableSymbolFileDsym (const ModuleSpec &module_spec)
"LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)",
exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
arch ? arch->GetArchitectureName() : "<NULL>",
- (void*)uuid);
+ (const void*)uuid);
FileSpec symbol_fspec;
+ ModuleSpec dsym_module_spec;
// First try and find the dSYM in the same directory as the executable or in
// an appropriate parent directory
if (LocateDSYMInVincinityOfExecutable (module_spec, symbol_fspec) == false)
{
// We failed to easily find the dSYM above, so use DebugSymbols
- LocateMacOSXFilesUsingDebugSymbols (module_spec, NULL, &symbol_fspec);
+ LocateMacOSXFilesUsingDebugSymbols (module_spec, dsym_module_spec);
}
- return symbol_fspec;
+ else
+ {
+ dsym_module_spec.GetSymbolFileSpec() = symbol_fspec;
+ }
+ return dsym_module_spec.GetSymbolFileSpec();
}
-FileSpec
+ModuleSpec
Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec)
{
+ ModuleSpec result;
const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
const ArchSpec *arch = module_spec.GetArchitecturePtr();
const UUID *uuid = module_spec.GetUUIDPtr();
@@ -177,28 +202,31 @@ Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec)
"LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
arch ? arch->GetArchitectureName() : "<NULL>",
- (void*)uuid);
+ (const void*)uuid);
- FileSpec objfile_fspec;
ModuleSpecList module_specs;
ModuleSpec matched_module_spec;
if (exec_fspec &&
ObjectFile::GetModuleSpecifications(*exec_fspec, 0, 0, module_specs) &&
module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
{
- objfile_fspec = exec_fspec;
+ result.GetFileSpec() = exec_fspec;
}
else
{
- LocateMacOSXFilesUsingDebugSymbols (module_spec, &objfile_fspec, NULL);
+ LocateMacOSXFilesUsingDebugSymbols (module_spec, result);
}
- return objfile_fspec;
+ return result;
}
FileSpec
Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
{
- const char *symbol_filename = module_spec.GetSymbolFileSpec().GetFilename().AsCString();
+ FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec();
+ if (symbol_file_spec.IsAbsolute() && symbol_file_spec.Exists())
+ return symbol_file_spec;
+
+ const char *symbol_filename = symbol_file_spec.GetFilename().AsCString();
if (symbol_filename && symbol_filename[0])
{
FileSpecList debug_file_search_paths (Target::GetDefaultDebugFileSearchPaths());
@@ -210,8 +238,10 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
// Add current working directory.
debug_file_search_paths.AppendIfUnique (FileSpec(".", true));
+#ifndef LLVM_ON_WIN32
// Add /usr/lib/debug directory.
debug_file_search_paths.AppendIfUnique (FileSpec("/usr/lib/debug", true));
+#endif // LLVM_ON_WIN32
std::string uuid_str;
const UUID &module_uuid = module_spec.GetUUID();
@@ -224,10 +254,6 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
uuid_str = uuid_str + ".debug";
}
- // Get directory of our module. Needed to check debug files like this:
- // /usr/lib/debug/usr/lib/library.so.debug
- std::string module_directory = module_spec.GetFileSpec().GetDirectory().AsCString();
-
size_t num_directories = debug_file_search_paths.GetSize();
for (size_t idx = 0; idx < num_directories; ++idx)
{
@@ -242,7 +268,11 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
files.push_back (dirname + "/" + symbol_filename);
files.push_back (dirname + "/.debug/" + symbol_filename);
files.push_back (dirname + "/.build-id/" + uuid_str);
- files.push_back (dirname + module_directory + "/" + symbol_filename);
+
+ // Some debug files may stored in the module directory like this:
+ // /usr/lib/debug/usr/lib/library.so.debug
+ if (!file_dir.IsEmpty())
+ files.push_back (dirname + file_dir.AsCString() + "/" + symbol_filename);
const uint32_t num_files = files.size();
for (size_t idx_file = 0; idx_file < num_files; ++idx_file)
diff --git a/contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp b/contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp
new file mode 100644
index 0000000..b23055e
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Host/common/TCPSocket.cpp
@@ -0,0 +1,288 @@
+//===-- TcpSocket.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/common/TCPSocket.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Host/Config.h"
+
+#ifndef LLDB_DISABLE_POSIX
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#include <sys/socket.h>
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+const int kDomain = AF_INET;
+const int kType = SOCK_STREAM;
+
+}
+
+TCPSocket::TCPSocket(NativeSocket socket, bool should_close)
+ : Socket(socket, ProtocolTcp, should_close)
+{
+
+}
+
+TCPSocket::TCPSocket(bool child_processes_inherit, Error &error)
+ : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP, child_processes_inherit, error), true)
+{
+}
+
+
+// Return the port number that is being used by the socket.
+uint16_t
+TCPSocket::GetLocalPortNumber() const
+{
+ if (m_socket != kInvalidSocketValue)
+ {
+ SocketAddress sock_addr;
+ socklen_t sock_addr_len = sock_addr.GetMaxLength ();
+ if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0)
+ return sock_addr.GetPort ();
+ }
+ return 0;
+}
+
+std::string
+TCPSocket::GetLocalIPAddress() const
+{
+ // We bound to port zero, so we need to figure out which port we actually bound to
+ if (m_socket != kInvalidSocketValue)
+ {
+ SocketAddress sock_addr;
+ socklen_t sock_addr_len = sock_addr.GetMaxLength ();
+ if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0)
+ return sock_addr.GetIPAddress ();
+ }
+ return "";
+}
+
+uint16_t
+TCPSocket::GetRemotePortNumber() const
+{
+ if (m_socket != kInvalidSocketValue)
+ {
+ SocketAddress sock_addr;
+ socklen_t sock_addr_len = sock_addr.GetMaxLength ();
+ if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
+ return sock_addr.GetPort ();
+ }
+ return 0;
+}
+
+std::string
+TCPSocket::GetRemoteIPAddress () const
+{
+ // We bound to port zero, so we need to figure out which port we actually bound to
+ if (m_socket != kInvalidSocketValue)
+ {
+ SocketAddress sock_addr;
+ socklen_t sock_addr_len = sock_addr.GetMaxLength ();
+ if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
+ return sock_addr.GetIPAddress ();
+ }
+ return "";
+}
+
+Error
+TCPSocket::Connect(llvm::StringRef name)
+{
+ if (m_socket == kInvalidSocketValue)
+ return Error("Invalid socket");
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
+ if (log)
+ log->Printf ("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
+
+ Error error;
+ std::string host_str;
+ std::string port_str;
+ int32_t port = INT32_MIN;
+ if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
+ return error;
+
+ // Enable local address reuse
+ SetOptionReuseAddress();
+
+ struct sockaddr_in sa;
+ ::memset (&sa, 0, sizeof (sa));
+ sa.sin_family = kDomain;
+ sa.sin_port = htons (port);
+
+ int inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr);
+
+ if (inet_pton_result <= 0)
+ {
+ struct hostent *host_entry = gethostbyname (host_str.c_str());
+ if (host_entry)
+ host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
+ inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr);
+ if (inet_pton_result <= 0)
+ {
+ if (inet_pton_result == -1)
+ SetLastError(error);
+ else
+ error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
+
+ return error;
+ }
+ }
+
+ if (-1 == ::connect (GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa)))
+ {
+ SetLastError (error);
+ return error;
+ }
+
+ // Keep our TCP packets coming without any delays.
+ SetOptionNoDelay();
+ error.Clear();
+ return error;
+}
+
+Error
+TCPSocket::Listen(llvm::StringRef name, int backlog)
+{
+ Error error;
+
+ // enable local address reuse
+ SetOptionReuseAddress();
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("TCPSocket::%s (%s)", __FUNCTION__, name.data());
+
+ std::string host_str;
+ std::string port_str;
+ int32_t port = INT32_MIN;
+ if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
+ return error;
+
+ SocketAddress bind_addr;
+
+ // Only bind to the loopback address if we are expecting a connection from
+ // localhost to avoid any firewall issues.
+ const bool bind_addr_success = (host_str == "127.0.0.1") ?
+ bind_addr.SetToLocalhost (kDomain, port) :
+ bind_addr.SetToAnyAddress (kDomain, port);
+
+ if (!bind_addr_success)
+ {
+ error.SetErrorString("Failed to bind port");
+ return error;
+ }
+
+ int err = ::bind (GetNativeSocket(), bind_addr, bind_addr.GetLength());
+ if (err != -1)
+ err = ::listen (GetNativeSocket(), backlog);
+
+ if (err == -1)
+ SetLastError (error);
+
+ return error;
+}
+
+Error
+TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&conn_socket)
+{
+ Error error;
+ std::string host_str;
+ std::string port_str;
+ int32_t port;
+ if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
+ return error;
+
+ const sa_family_t family = kDomain;
+ const int socktype = kType;
+ const int protocol = IPPROTO_TCP;
+ SocketAddress listen_addr;
+ if (host_str.empty())
+ listen_addr.SetToLocalhost(family, port);
+ else if (host_str.compare("*") == 0)
+ listen_addr.SetToAnyAddress(family, port);
+ else
+ {
+ if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol))
+ {
+ error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str());
+ return error;
+ }
+ }
+
+ bool accept_connection = false;
+ std::unique_ptr<TCPSocket> accepted_socket;
+
+ // Loop until we are happy with our connection
+ while (!accept_connection)
+ {
+ struct sockaddr_in accept_addr;
+ ::memset (&accept_addr, 0, sizeof accept_addr);
+#if !(defined (__linux__) || defined(_WIN32))
+ accept_addr.sin_len = sizeof accept_addr;
+#endif
+ socklen_t accept_addr_len = sizeof accept_addr;
+
+ int sock = AcceptSocket (GetNativeSocket(),
+ (struct sockaddr *)&accept_addr,
+ &accept_addr_len,
+ child_processes_inherit,
+ error);
+
+ if (error.Fail())
+ break;
+
+ bool is_same_addr = true;
+#if !(defined(__linux__) || (defined(_WIN32)))
+ is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
+#endif
+ if (is_same_addr)
+ is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr);
+
+ if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY))
+ {
+ accept_connection = true;
+ accepted_socket.reset(new TCPSocket(sock, true));
+ }
+ else
+ {
+ const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
+ const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
+ ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
+ accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
+ listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
+ accepted_socket.reset();
+ }
+ }
+
+ if (!accepted_socket)
+ return error;
+
+ // Keep our TCP packets coming without any delays.
+ accepted_socket->SetOptionNoDelay();
+ error.Clear();
+ conn_socket = accepted_socket.release();
+ return error;
+}
+
+int
+TCPSocket::SetOptionNoDelay()
+{
+ return SetOption (IPPROTO_TCP, TCP_NODELAY, 1);
+}
+
+int
+TCPSocket::SetOptionReuseAddress()
+{
+ return SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
+}
diff --git a/contrib/llvm/tools/lldb/source/Host/common/ThisThread.cpp b/contrib/llvm/tools/lldb/source/Host/common/ThisThread.cpp
index 289ec78..7637014 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/ThisThread.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/ThisThread.cpp
@@ -37,7 +37,7 @@ ThisThread::SetName(llvm::StringRef name, int max_length)
{
// We're still too long. Since this is a dotted component, use everything after the last
// dot, up to a maximum of |length| characters.
- std::string::size_type last_dot = truncated_name.find_last_of(".");
+ std::string::size_type last_dot = truncated_name.rfind('.');
if (last_dot != std::string::npos)
begin = last_dot + 1;
diff --git a/contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp b/contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp
new file mode 100644
index 0000000..8297232
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Host/common/UDPSocket.cpp
@@ -0,0 +1,158 @@
+//===-- UdpSocket.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/common/UDPSocket.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Host/Config.h"
+
+#ifndef LLDB_DISABLE_POSIX
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#endif
+
+#include <memory>
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+const int kDomain = AF_INET;
+const int kType = SOCK_DGRAM;
+
+const Error kNotSupported("Not supported");
+
+}
+
+UDPSocket::UDPSocket(NativeSocket socket)
+ : Socket(socket, ProtocolUdp, true)
+{
+}
+
+UDPSocket::UDPSocket(bool child_processes_inherit, Error &error)
+ : UDPSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error))
+{
+}
+
+size_t
+UDPSocket::Send(const void *buf, const size_t num_bytes)
+{
+ return ::sendto (m_socket,
+ static_cast<const char*>(buf),
+ num_bytes,
+ 0,
+ m_send_sockaddr,
+ m_send_sockaddr.GetLength());
+}
+
+Error
+UDPSocket::Connect(llvm::StringRef name)
+{
+ return kNotSupported;
+}
+
+Error
+UDPSocket::Listen(llvm::StringRef name, int backlog)
+{
+ return kNotSupported;
+}
+
+Error
+UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
+{
+ return kNotSupported;
+}
+
+Error
+UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket)
+{
+ std::unique_ptr<UDPSocket> final_send_socket;
+ std::unique_ptr<UDPSocket> final_recv_socket;
+
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
+ if (log)
+ log->Printf ("UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
+
+ Error error;
+ std::string host_str;
+ std::string port_str;
+ int32_t port = INT32_MIN;
+ if (!DecodeHostAndPort (name, host_str, port_str, port, &error))
+ return error;
+
+ // Setup the receiving end of the UDP connection on this localhost
+ // on port zero. After we bind to port zero we can read the port.
+ final_recv_socket.reset(new UDPSocket(child_processes_inherit, error));
+ if (error.Success())
+ {
+ // Socket was created, now lets bind to the requested port
+ SocketAddress addr;
+ addr.SetToAnyAddress (AF_INET, 0);
+
+ if (::bind (final_recv_socket->GetNativeSocket(), addr, addr.GetLength()) == -1)
+ {
+ // Bind failed...
+ SetLastError (error);
+ }
+ }
+
+ assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid()));
+ if (error.Fail())
+ return error;
+
+ // At this point we have setup the receive port, now we need to
+ // setup the UDP send socket
+
+ struct addrinfo hints;
+ struct addrinfo *service_info_list = nullptr;
+
+ ::memset (&hints, 0, sizeof(hints));
+ hints.ai_family = kDomain;
+ hints.ai_socktype = kType;
+ int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list);
+ if (err != 0)
+ {
+ error.SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)",
+ host_str.c_str(),
+ port_str.c_str(),
+ err,
+ gai_strerror(err));
+ return error;
+ }
+
+ for (struct addrinfo *service_info_ptr = service_info_list;
+ service_info_ptr != nullptr;
+ service_info_ptr = service_info_ptr->ai_next)
+ {
+ auto send_fd = CreateSocket (service_info_ptr->ai_family,
+ service_info_ptr->ai_socktype,
+ service_info_ptr->ai_protocol,
+ child_processes_inherit,
+ error);
+ if (error.Success())
+ {
+ final_send_socket.reset(new UDPSocket(send_fd));
+ final_send_socket->m_send_sockaddr = service_info_ptr;
+ break;
+ }
+ else
+ continue;
+ }
+
+ :: freeaddrinfo (service_info_list);
+
+ if (!final_send_socket)
+ return error;
+
+ send_socket = final_send_socket.release();
+ recv_socket = final_recv_socket.release();
+ error.Clear();
+ return error;
+}
diff --git a/contrib/llvm/tools/lldb/source/Host/common/XML.cpp b/contrib/llvm/tools/lldb/source/Host/common/XML.cpp
index 14e786a..dc9cb0b 100644
--- a/contrib/llvm/tools/lldb/source/Host/common/XML.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/common/XML.cpp
@@ -329,7 +329,7 @@ XMLNode::ForEachSiblingElementWithName (const char *name, NodeCallback const &ca
else
{
if (node->name)
- continue; // nullptr name specified and this elemnt has a name, ignore this one
+ continue; // nullptr name specified and this element has a name, ignore this one
}
if (callback(XMLNode(node)) == false)
@@ -592,7 +592,7 @@ ApplePropertyList::ExtractStringFromValueNode (const XMLNode &node, std::string
if (element_name == "true" || element_name == "false")
{
// The text value _is_ the element name itself...
- value = std::move(element_name.str());
+ value = element_name.str();
return true;
}
else if (element_name == "dict" || element_name == "array")
@@ -689,5 +689,3 @@ ApplePropertyList::GetStructuredData()
#endif
return root_sp;
}
-
-
diff --git a/contrib/llvm/tools/lldb/source/Host/freebsd/Host.cpp b/contrib/llvm/tools/lldb/source/Host/freebsd/Host.cpp
index 7f8d7ae..cf53cda 100644
--- a/contrib/llvm/tools/lldb/source/Host/freebsd/Host.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/freebsd/Host.cpp
@@ -76,7 +76,7 @@ GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
size_t arg_data_size = sizeof(arg_data);
if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0)
{
- DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
+ DataExtractor data (arg_data, arg_data_size, endian::InlHostByteOrder(), sizeof(void *));
lldb::offset_t offset = 0;
const char *cstr;
diff --git a/contrib/llvm/tools/lldb/source/Host/netbsd/Host.cpp b/contrib/llvm/tools/lldb/source/Host/netbsd/Host.cpp
new file mode 100644
index 0000000..8742850
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Host/netbsd/Host.cpp
@@ -0,0 +1,287 @@
+//===-- source/Host/netbsd/Host.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <stdio.h>
+#include <dlfcn.h>
+#include <execinfo.h>
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+
+#include <limits.h>
+
+#include <sys/ptrace.h>
+#include <sys/exec.h>
+#include <elf.h>
+#include <kvm.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Error.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Platform.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Utility/CleanUp.h"
+#include "lldb/Utility/NameMatches.h"
+
+#include "llvm/Support/Host.h"
+
+extern "C" {
+ extern char **environ;
+}
+
+using namespace lldb;
+using namespace lldb_private;
+
+size_t
+Host::GetEnvironment (StringList &env)
+{
+ char *v;
+ char **var = environ;
+ for (; var != NULL && *var != NULL; ++var)
+ {
+ v = ::strchr(*var, (int)'-');
+ if (v == NULL)
+ continue;
+ env.AppendString(v);
+ }
+ return env.GetSize();
+}
+
+static bool
+GetNetBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
+ ProcessInstanceInfo &process_info)
+{
+ if (!process_info.ProcessIDIsValid())
+ return false;
+
+ int pid = process_info.GetProcessID();
+
+ int mib[4] = { CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV };
+
+ char arg_data[8192];
+ size_t arg_data_size = sizeof(arg_data);
+ if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) != 0)
+ return false;
+
+ DataExtractor data (arg_data, arg_data_size, endian::InlHostByteOrder(), sizeof(void *));
+ lldb::offset_t offset = 0;
+ const char *cstr;
+
+ cstr = data.GetCStr (&offset);
+ if (!cstr)
+ return false;
+
+ process_info.GetExecutableFile().SetFile(cstr, false);
+
+ if (!(match_info_ptr == NULL ||
+ NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(),
+ match_info_ptr->GetNameMatchType(),
+ match_info_ptr->GetProcessInfo().GetName())))
+ return false;
+
+ Args &proc_args = process_info.GetArguments();
+ while (1)
+ {
+ const uint8_t *p = data.PeekData(offset, 1);
+ while ((p != NULL) && (*p == '\0') && offset < arg_data_size)
+ {
+ ++offset;
+ p = data.PeekData(offset, 1);
+ }
+ if (p == NULL || offset >= arg_data_size)
+ break;
+
+ cstr = data.GetCStr(&offset);
+ if (!cstr)
+ break;
+
+ proc_args.AppendArgument(cstr);
+ }
+
+ return true;
+}
+
+static bool
+GetNetBSDProcessCPUType (ProcessInstanceInfo &process_info)
+{
+ if (process_info.ProcessIDIsValid())
+ {
+ process_info.GetArchitecture() = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
+ return true;
+ }
+ process_info.GetArchitecture().Clear();
+ return false;
+}
+
+static bool
+GetNetBSDProcessUserAndGroup(ProcessInstanceInfo &process_info)
+{
+ ::kvm_t *kdp;
+ char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */
+
+ struct ::kinfo_proc2 *proc_kinfo;
+ const int pid = process_info.GetProcessID();
+ int nproc;
+
+ if (!process_info.ProcessIDIsValid())
+ goto error;
+
+ if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL)
+ goto error;
+
+ if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_PID, pid,
+ sizeof(struct ::kinfo_proc2),
+ &nproc)) == NULL) {
+ ::kvm_close(kdp);
+ goto error;
+ }
+
+ if (nproc < 1) {
+ ::kvm_close(kdp); /* XXX: we don't check for error here */
+ goto error;
+ }
+
+ process_info.SetParentProcessID (proc_kinfo->p_ppid);
+ process_info.SetUserID (proc_kinfo->p_ruid);
+ process_info.SetGroupID (proc_kinfo->p_rgid);
+ process_info.SetEffectiveUserID (proc_kinfo->p_uid);
+ process_info.SetEffectiveGroupID (proc_kinfo->p_gid);
+
+ ::kvm_close(kdp); /* XXX: we don't check for error here */
+
+ return true;
+
+error:
+ process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID);
+ process_info.SetUserID (UINT32_MAX);
+ process_info.SetGroupID (UINT32_MAX);
+ process_info.SetEffectiveUserID (UINT32_MAX);
+ process_info.SetEffectiveGroupID (UINT32_MAX);
+ return false;
+}
+
+uint32_t
+Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
+{
+ const ::pid_t our_pid = ::getpid();
+ const ::uid_t our_uid = ::getuid();
+
+ const bool all_users = match_info.GetMatchAllUsers() ||
+ // Special case, if lldb is being run as root we can attach to anything
+ (our_uid == 0);
+
+ kvm_t *kdp;
+ char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */
+ if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL)
+ return 0;
+
+ struct ::kinfo_proc2 *proc_kinfo;
+ int nproc;
+ if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_ALL, 0,
+ sizeof(struct ::kinfo_proc2),
+ &nproc)) == NULL) {
+ ::kvm_close(kdp);
+ return 0;
+ }
+
+ for (int i = 0; i < nproc; i++) {
+ if (proc_kinfo[i].p_pid < 1)
+ continue; /* not valid */
+ /* Make sure the user is acceptable */
+ if (!all_users && proc_kinfo[i].p_ruid != our_uid)
+ continue;
+
+ if (proc_kinfo[i].p_pid == our_pid || // Skip this process
+ proc_kinfo[i].p_pid == 0 || // Skip kernel (kernel pid is 0)
+ proc_kinfo[i].p_stat == LSZOMB || // Zombies are bad
+ proc_kinfo[i].p_flag & P_TRACED || // Being debugged?
+ proc_kinfo[i].p_flag & P_WEXIT) // Working on exiting
+ continue;
+
+
+ // Every thread is a process in NetBSD, but all the threads of a single
+ // process have the same pid. Do not store the process info in the
+ // result list if a process with given identifier is already registered
+ // there.
+ if (proc_kinfo[i].p_nlwps > 1) {
+ bool already_registered = false;
+ for (size_t pi = 0; pi < process_infos.GetSize(); pi++) {
+ if (process_infos.GetProcessIDAtIndex(pi) ==
+ proc_kinfo[i].p_pid) {
+ already_registered = true;
+ break;
+ }
+ }
+
+ if (already_registered)
+ continue;
+ }
+ ProcessInstanceInfo process_info;
+ process_info.SetProcessID (proc_kinfo[i].p_pid);
+ process_info.SetParentProcessID (proc_kinfo[i].p_ppid);
+ process_info.SetUserID (proc_kinfo[i].p_ruid);
+ process_info.SetGroupID (proc_kinfo[i].p_rgid);
+ process_info.SetEffectiveUserID (proc_kinfo[i].p_uid);
+ process_info.SetEffectiveGroupID (proc_kinfo[i].p_gid);
+ // Make sure our info matches before we go fetch the name and cpu type
+ if (match_info.Matches (process_info) &&
+ GetNetBSDProcessArgs (&match_info, process_info))
+ {
+ GetNetBSDProcessCPUType (process_info);
+ if (match_info.Matches (process_info))
+ process_infos.Append (process_info);
+ }
+ }
+
+ kvm_close(kdp); /* XXX: we don't check for error here */
+
+ return process_infos.GetSize();
+}
+
+bool
+Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+ process_info.SetProcessID(pid);
+
+ if (GetNetBSDProcessArgs(NULL, process_info))
+ {
+ GetNetBSDProcessCPUType(process_info);
+ GetNetBSDProcessUserAndGroup(process_info);
+ return true;
+ }
+
+ process_info.Clear();
+ return false;
+}
+
+lldb::DataBufferSP
+Host::GetAuxvData(lldb_private::Process *process)
+{
+ return lldb::DataBufferSP();
+}
+
+Error
+Host::ShellExpandArguments (ProcessLaunchInfo &launch_info)
+{
+ return Error("unimplemented");
+}
diff --git a/contrib/llvm/tools/lldb/source/Host/netbsd/HostInfoNetBSD.cpp b/contrib/llvm/tools/lldb/source/Host/netbsd/HostInfoNetBSD.cpp
new file mode 100644
index 0000000..aadda76
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Host/netbsd/HostInfoNetBSD.cpp
@@ -0,0 +1,112 @@
+//===-- HostInfoNetBSD.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/netbsd/HostInfoNetBSD.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <inttypes.h>
+
+
+using namespace lldb_private;
+
+uint32_t
+HostInfoNetBSD::GetMaxThreadNameLength()
+{
+ return PTHREAD_MAX_NAMELEN_NP;
+}
+
+bool
+HostInfoNetBSD::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update)
+{
+ struct utsname un;
+
+ ::memset(&un, 0, sizeof(un));
+ if (::uname(&un) < 0)
+ return false;
+
+ /* Accept versions like 7.99.21 and 6.1_STABLE */
+ int status = ::sscanf(un.release, "%" PRIu32 ".%" PRIu32 ".%" PRIu32, &major, &minor, &update);
+ switch(status) {
+ case 0:
+ return false;
+ case 1:
+ minor = 0;
+ /* FALLTHROUGH */
+ case 2:
+ update = 0;
+ /* FALLTHROUGH */
+ case 3:
+ default:
+ return true;
+ }
+}
+
+bool
+HostInfoNetBSD::GetOSBuildString(std::string &s)
+{
+ int mib[2] = {CTL_KERN, KERN_OSREV};
+ char osrev_str[12];
+ int osrev = 0;
+ size_t osrev_len = sizeof(osrev);
+
+ if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0)
+ {
+ ::snprintf(osrev_str, sizeof(osrev_str), "%-10.10d", osrev);
+ s.assign(osrev_str);
+ return true;
+ }
+
+ s.clear();
+ return false;
+}
+
+bool
+HostInfoNetBSD::GetOSKernelDescription(std::string &s)
+{
+ struct utsname un;
+
+ ::memset(&un, 0, sizeof(un));
+ s.clear();
+
+ if (::uname(&un) < 0)
+ return false;
+
+ s.assign(un.version);
+
+ return true;
+}
+
+FileSpec
+HostInfoNetBSD::GetProgramFileSpec()
+{
+ static FileSpec g_program_filespec;
+
+ if (!g_program_filespec)
+ {
+ ssize_t len;
+ static char buf[PATH_MAX];
+ char name[PATH_MAX];
+
+ ::snprintf(name, PATH_MAX, "/proc/%d/exe", ::getpid());
+ len = ::readlink(name, buf, PATH_MAX - 1);
+ if (len != -1)
+ {
+ buf[len] = '\0';
+ g_program_filespec.SetFile(buf, false);
+ }
+ }
+ return g_program_filespec;
+}
diff --git a/contrib/llvm/tools/lldb/source/Host/netbsd/HostThreadNetBSD.cpp b/contrib/llvm/tools/lldb/source/Host/netbsd/HostThreadNetBSD.cpp
new file mode 100644
index 0000000..06bc502
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Host/netbsd/HostThreadNetBSD.cpp
@@ -0,0 +1,50 @@
+//===-- HostThreadNetBSD.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// lldb Includes
+#include "lldb/Host/netbsd/HostThreadNetBSD.h"
+#include "lldb/Host/Host.h"
+
+// C includes
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+// C++ includes
+#include <string>
+
+using namespace lldb_private;
+
+HostThreadNetBSD::HostThreadNetBSD()
+{
+}
+
+HostThreadNetBSD::HostThreadNetBSD(lldb::thread_t thread)
+ : HostThreadPosix(thread)
+{
+}
+
+void
+HostThreadNetBSD::SetName(lldb::thread_t thread, llvm::StringRef &name)
+{
+ ::pthread_setname_np(thread, "%s", const_cast<char*>(name.data()));
+}
+
+void
+HostThreadNetBSD::GetName(lldb::thread_t thread, llvm::SmallVectorImpl<char> &name)
+{
+ char buf[PTHREAD_MAX_NAMELEN_NP];
+ ::pthread_getname_np(thread, buf, PTHREAD_MAX_NAMELEN_NP);
+
+ name.clear();
+ name.append(buf, buf + strlen(buf));
+}
diff --git a/contrib/llvm/tools/lldb/source/Host/netbsd/ThisThread.cpp b/contrib/llvm/tools/lldb/source/Host/netbsd/ThisThread.cpp
new file mode 100644
index 0000000..dff5d9e
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Host/netbsd/ThisThread.cpp
@@ -0,0 +1,30 @@
+//===-- ThisThread.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/HostNativeThread.h"
+#include "lldb/Host/ThisThread.h"
+
+#include "llvm/ADT/SmallVector.h"
+
+#include <pthread.h>
+#include <string.h>
+
+using namespace lldb_private;
+
+void
+ThisThread::SetName(llvm::StringRef name)
+{
+ HostNativeThread::SetName(::pthread_self(), name);
+}
+
+void
+ThisThread::GetName(llvm::SmallVectorImpl<char> &name)
+{
+ HostNativeThread::GetName(::pthread_self(), name);
+}
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/contrib/llvm/tools/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
index f12f98c..dbbd5a1 100644
--- a/contrib/llvm/tools/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -33,6 +33,8 @@
#endif
// C++ Includes
+#include <sstream>
+
// Other libraries and framework includes
#include "llvm/Support/ErrorHandling.h"
#if defined(__APPLE__)
@@ -45,11 +47,37 @@
#include "lldb/Core/Timer.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/Socket.h"
+#include "lldb/Host/common/TCPSocket.h"
#include "lldb/Interpreter/Args.h"
using namespace lldb;
using namespace lldb_private;
+const char* ConnectionFileDescriptor::LISTEN_SCHEME = "listen";
+const char* ConnectionFileDescriptor::ACCEPT_SCHEME = "accept";
+const char* ConnectionFileDescriptor::UNIX_ACCEPT_SCHEME = "unix-accept";
+const char* ConnectionFileDescriptor::CONNECT_SCHEME = "connect";
+const char* ConnectionFileDescriptor::TCP_CONNECT_SCHEME = "tcp-connect";
+const char* ConnectionFileDescriptor::UDP_SCHEME = "udp";
+const char* ConnectionFileDescriptor::UNIX_CONNECT_SCHEME = "unix-connect";
+const char* ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME = "unix-abstract-connect";
+const char* ConnectionFileDescriptor::FD_SCHEME = "fd";
+const char* ConnectionFileDescriptor::FILE_SCHEME = "file";
+
+namespace {
+
+const char*
+GetURLAddress(const char *url, const char *scheme)
+{
+ const auto prefix = std::string(scheme) + "://";
+ if (strstr(url, prefix.c_str()) != url)
+ return nullptr;
+
+ return url + prefix.size();
+}
+
+}
+
ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit)
: Connection()
, m_pipe()
@@ -151,49 +179,51 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr)
if (s && s[0])
{
- if (strstr(s, "listen://") == s)
+ const char *addr = nullptr;
+ if ((addr = GetURLAddress(s, LISTEN_SCHEME)))
{
// listen://HOST:PORT
- return SocketListenAndAccept(s + strlen("listen://"), error_ptr);
+ return SocketListenAndAccept(addr, error_ptr);
}
- else if (strstr(s, "accept://") == s)
+ else if ((addr = GetURLAddress(s, ACCEPT_SCHEME)))
{
// unix://SOCKNAME
- return NamedSocketAccept(s + strlen("accept://"), error_ptr);
+ return NamedSocketAccept(addr, error_ptr);
}
- else if (strstr(s, "unix-accept://") == s)
+ else if ((addr = GetURLAddress(s, UNIX_ACCEPT_SCHEME)))
{
// unix://SOCKNAME
- return NamedSocketAccept(s + strlen("unix-accept://"), error_ptr);
+ return NamedSocketAccept(addr, error_ptr);
+ }
+ else if ((addr = GetURLAddress(s, CONNECT_SCHEME)))
+ {
+ return ConnectTCP(addr, error_ptr);
}
- else if (strstr(s, "adb://") == s)
+ else if ((addr = GetURLAddress(s, TCP_CONNECT_SCHEME)))
{
- int port = -1;
- sscanf(s, "adb://%*[^:]:%d", &port);
- char host_and_port[sizeof("localhost:65535")];
- snprintf(host_and_port, sizeof(host_and_port), "localhost:%d", port);
- return ConnectTCP(host_and_port, error_ptr);
+ return ConnectTCP(addr, error_ptr);
}
- else if (strstr(s, "connect://") == s)
+ else if ((addr = GetURLAddress(s, UDP_SCHEME)))
{
- return ConnectTCP(s + strlen("connect://"), error_ptr);
+ return ConnectUDP(addr, error_ptr);
}
- else if (strstr(s, "tcp-connect://") == s)
+ else if ((addr = GetURLAddress(s, UNIX_CONNECT_SCHEME)))
{
- return ConnectTCP(s + strlen("tcp-connect://"), error_ptr);
+ // unix-connect://SOCKNAME
+ return NamedSocketConnect(addr, error_ptr);
}
- else if (strstr(s, "udp://") == s)
+ else if ((addr = GetURLAddress(s, UNIX_ABSTRACT_CONNECT_SCHEME)))
{
- return ConnectUDP(s + strlen("udp://"), error_ptr);
+ // unix-abstract-connect://SOCKNAME
+ return UnixAbstractSocketConnect(addr, error_ptr);
}
#ifndef LLDB_DISABLE_POSIX
- else if (strstr(s, "fd://") == s)
+ else if ((addr = GetURLAddress(s, FD_SCHEME)))
{
// Just passing a native file descriptor within this current process
// that is already opened (possibly from a service or other source).
- s += strlen("fd://");
bool success = false;
- int fd = StringConvert::ToSInt32(s, -1, 0, &success);
+ int fd = StringConvert::ToSInt32(addr, -1, 0, &success);
if (success)
{
@@ -223,8 +253,8 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr)
// allow us to specify this. For now, we assume we must
// assume we don't own it.
- std::unique_ptr<Socket> tcp_socket;
- tcp_socket.reset(new Socket(fd, Socket::ProtocolTcp, false));
+ std::unique_ptr<TCPSocket> tcp_socket;
+ tcp_socket.reset(new TCPSocket(fd, false));
// Try and get a socket option from this file descriptor to
// see if this is a socket and set m_is_socket accordingly.
int resuse;
@@ -239,21 +269,21 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr)
m_read_sp.reset(new File(fd, false));
m_write_sp.reset(new File(fd, false));
}
- m_uri.assign(s);
+ m_uri.assign(addr);
return eConnectionStatusSuccess;
}
}
if (error_ptr)
- error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"fd://%s\"", s);
+ error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"", s);
m_read_sp.reset();
m_write_sp.reset();
return eConnectionStatusError;
}
- else if (strstr(s, "file://") == s)
+ else if ((addr = GetURLAddress(s, FILE_SCHEME)))
{
// file:///PATH
- const char *path = s + strlen("file://");
+ const char *path = addr;
int fd = -1;
do
{
@@ -763,6 +793,23 @@ ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, Error *err
return eConnectionStatusSuccess;
}
+lldb::ConnectionStatus
+ConnectionFileDescriptor::UnixAbstractSocketConnect(const char *socket_name, Error *error_ptr)
+{
+ Socket *socket = nullptr;
+ Error error = Socket::UnixAbstractConnect(socket_name, m_child_processes_inherit, socket);
+ if (error_ptr)
+ *error_ptr = error;
+ m_write_sp.reset(socket);
+ m_read_sp = m_write_sp;
+ if (error.Fail())
+ {
+ return eConnectionStatusError;
+ }
+ m_uri.assign(socket_name);
+ return eConnectionStatusSuccess;
+}
+
ConnectionStatus
ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr)
{
@@ -780,7 +827,7 @@ ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr)
listening_socket_up.reset(socket);
socket = nullptr;
- error = listening_socket_up->BlockingAccept(s, m_child_processes_inherit, socket);
+ error = listening_socket_up->Accept(s, m_child_processes_inherit, socket);
listening_socket_up.reset();
if (error_ptr)
*error_ptr = error;
@@ -856,9 +903,12 @@ ConnectionFileDescriptor::SetChildProcessesInherit(bool child_processes_inherit)
void
ConnectionFileDescriptor::InitializeSocket(Socket* socket)
{
+ assert(socket->GetSocketProtocol() == Socket::ProtocolTcp);
+ TCPSocket* tcp_socket = static_cast<TCPSocket*>(socket);
+
m_write_sp.reset(socket);
m_read_sp = m_write_sp;
StreamString strm;
- strm.Printf("connect://%s:%u",socket->GetRemoteIPAddress().c_str(), socket->GetRemotePortNumber());
+ strm.Printf("connect://%s:%u",tcp_socket->GetRemoteIPAddress().c_str(), tcp_socket->GetRemotePortNumber());
m_uri.swap(strm.GetString());
}
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/DomainSocket.cpp b/contrib/llvm/tools/lldb/source/Host/posix/DomainSocket.cpp
new file mode 100644
index 0000000..b4427e3
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Host/posix/DomainSocket.cpp
@@ -0,0 +1,133 @@
+//===-- DomainSocket.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/posix/DomainSocket.h"
+
+#include "lldb/Host/FileSystem.h"
+
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+#ifdef __ANDROID__
+// Android does not have SUN_LEN
+#ifndef SUN_LEN
+#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path))
+#endif
+#endif // #ifdef __ANDROID__
+
+namespace {
+
+const int kDomain = AF_UNIX;
+const int kType = SOCK_STREAM;
+
+bool SetSockAddr(llvm::StringRef name,
+ const size_t name_offset,
+ sockaddr_un* saddr_un,
+ socklen_t& saddr_un_len)
+{
+ if (name.size() + name_offset > sizeof(saddr_un->sun_path))
+ return false;
+
+ memset(saddr_un, 0, sizeof(*saddr_un));
+ saddr_un->sun_family = kDomain;
+
+ memcpy(saddr_un->sun_path + name_offset, name.data(), name.size());
+
+ // For domain sockets we can use SUN_LEN in order to calculate size of
+ // sockaddr_un, but for abstract sockets we have to calculate size manually
+ // because of leading null symbol.
+ if (name_offset == 0)
+ saddr_un_len = SUN_LEN(saddr_un);
+ else
+ saddr_un_len = offsetof(struct sockaddr_un, sun_path) + name_offset + name.size();
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
+ saddr_un->sun_len = saddr_un_len;
+#endif
+
+ return true;
+}
+
+}
+
+DomainSocket::DomainSocket(NativeSocket socket)
+ : Socket(socket, ProtocolUnixDomain, true)
+{
+}
+
+DomainSocket::DomainSocket(bool child_processes_inherit, Error &error)
+ : DomainSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error))
+{
+}
+
+DomainSocket::DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error)
+ : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), protocol, true)
+{
+}
+
+Error
+DomainSocket::Connect(llvm::StringRef name)
+{
+ sockaddr_un saddr_un;
+ socklen_t saddr_un_len;
+ if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
+ return Error("Failed to set socket address");
+
+ Error error;
+ if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) < 0)
+ SetLastError (error);
+
+ return error;
+}
+
+Error
+DomainSocket::Listen(llvm::StringRef name, int backlog)
+{
+ sockaddr_un saddr_un;
+ socklen_t saddr_un_len;
+ if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len))
+ return Error("Failed to set socket address");
+
+ DeleteSocketFile(name);
+
+ Error error;
+ if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) == 0)
+ if (::listen(GetNativeSocket(), backlog) == 0)
+ return error;
+
+ SetLastError(error);
+ return error;
+}
+
+Error
+DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
+{
+ Error error;
+ auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, child_processes_inherit, error);
+ if (error.Success())
+ socket = new DomainSocket(conn_fd);
+
+ return error;
+}
+
+size_t
+DomainSocket::GetNameOffset() const
+{
+ return 0;
+}
+
+void
+DomainSocket::DeleteSocketFile(llvm::StringRef name)
+{
+ FileSystem::Unlink(FileSpec{name, true});
+}
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/FileSystem.cpp b/contrib/llvm/tools/lldb/source/Host/posix/FileSystem.cpp
index 5269803..1f2e7db 100644
--- a/contrib/llvm/tools/lldb/source/Host/posix/FileSystem.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/posix/FileSystem.cpp
@@ -20,6 +20,9 @@
#include <sys/mount.h>
#include <linux/magic.h>
#endif
+#if defined(__NetBSD__)
+#include <sys/statvfs.h>
+#endif
// lldb Includes
#include "lldb/Core/Error.h"
@@ -29,6 +32,9 @@
using namespace lldb;
using namespace lldb_private;
+const char *
+FileSystem::DEV_NULL = "/dev/null";
+
FileSpec::PathSyntax
FileSystem::GetNativePathSyntax()
{
@@ -179,6 +185,16 @@ FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)
return error;
}
+int
+FileSystem::GetHardlinkCount(const FileSpec &file_spec)
+{
+ struct stat file_stat;
+ if (::stat(file_spec.GetCString(), &file_stat) == 0)
+ return file_stat.st_nlink;
+
+ return -1;
+}
+
Error
FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)
{
@@ -213,6 +229,34 @@ FileSystem::Readlink(const FileSpec &src, FileSpec &dst)
return error;
}
+Error
+FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst)
+{
+ char resolved_path[PATH_MAX];
+ if (!src.GetPath (resolved_path, sizeof (resolved_path)))
+ {
+ return Error("Couldn't get the canonical path for %s", src.GetCString());
+ }
+
+ char real_path[PATH_MAX + 1];
+ if (realpath(resolved_path, real_path) == nullptr)
+ {
+ Error err;
+ err.SetErrorToErrno();
+ return err;
+ }
+
+ dst = FileSpec(real_path, false);
+
+ return Error();
+}
+
+#if defined(__NetBSD__)
+static bool IsLocal(const struct statvfs& info)
+{
+ return (info.f_flag & MNT_LOCAL) != 0;
+}
+#else
static bool IsLocal(const struct statfs& info)
{
#ifdef __linux__
@@ -230,7 +274,19 @@ static bool IsLocal(const struct statfs& info)
return (info.f_flags & MNT_LOCAL) != 0;
#endif
}
+#endif
+#if defined(__NetBSD__)
+bool
+FileSystem::IsLocal(const FileSpec &spec)
+{
+ struct statvfs statfs_info;
+ std::string path (spec.GetPath());
+ if (statvfs(path.c_str(), &statfs_info) == 0)
+ return ::IsLocal(statfs_info);
+ return false;
+}
+#else
bool
FileSystem::IsLocal(const FileSpec &spec)
{
@@ -240,3 +296,4 @@ FileSystem::IsLocal(const FileSpec &spec)
return ::IsLocal(statfs_info);
return false;
}
+#endif
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/HostInfoPosix.cpp b/contrib/llvm/tools/lldb/source/Host/posix/HostInfoPosix.cpp
index c04db71..cfdbf56 100644
--- a/contrib/llvm/tools/lldb/source/Host/posix/HostInfoPosix.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/posix/HostInfoPosix.cpp
@@ -7,7 +7,10 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/lldb-python.h"
+#if !defined(LLDB_DISABLE_PYTHON)
+#include "Plugins/ScriptInterpreter/Python/lldb-python.h"
+#endif
+
#include "lldb/Core/Log.h"
#include "lldb/Host/posix/HostInfoPosix.h"
@@ -19,6 +22,7 @@
#include <mutex>
#include <netdb.h>
#include <pwd.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
@@ -211,16 +215,29 @@ HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec)
char raw_path[PATH_MAX];
lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
+#if defined(LLDB_PYTHON_RELATIVE_LIBDIR)
+ // Build the path by backing out of the lib dir, then building
+ // with whatever the real python interpreter uses. (e.g. lib
+ // for most, lib64 on RHEL x86_64).
+ char python_path[PATH_MAX];
+ ::snprintf(python_path, sizeof(python_path), "%s/../%s", raw_path, LLDB_PYTHON_RELATIVE_LIBDIR);
+
+ char final_path[PATH_MAX];
+ realpath(python_path, final_path);
+ file_spec.GetDirectory().SetCString(final_path);
+
+ return true;
+#else
llvm::SmallString<256> python_version_dir;
llvm::raw_svector_ostream os(python_version_dir);
os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages";
- os.flush();
// We may get our string truncated. Should we protect this with an assert?
::strncat(raw_path, python_version_dir.c_str(), sizeof(raw_path) - strlen(raw_path) - 1);
file_spec.GetDirectory().SetCString(raw_path);
return true;
+#endif
#else
return false;
#endif
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/MainLoopPosix.cpp b/contrib/llvm/tools/lldb/source/Host/posix/MainLoopPosix.cpp
index cb213b9..897f2d1 100644
--- a/contrib/llvm/tools/lldb/source/Host/posix/MainLoopPosix.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/posix/MainLoopPosix.cpp
@@ -94,10 +94,10 @@ MainLoopPosix::RegisterSignal(int signo, const Callback &callback, Error &error)
}
void
-MainLoopPosix::UnregisterReadObject(const lldb::IOObjectSP &object_sp)
+MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle)
{
- bool erased = m_read_fds.erase(object_sp->GetWaitableHandle());
- (void) erased;
+ bool erased = m_read_fds.erase(handle);
+ UNUSED_IF_ASSERT_DISABLED(erased);
assert(erased);
}
diff --git a/contrib/llvm/tools/lldb/source/Host/posix/PipePosix.cpp b/contrib/llvm/tools/lldb/source/Host/posix/PipePosix.cpp
index 0ed319f..353faae 100644
--- a/contrib/llvm/tools/lldb/source/Host/posix/PipePosix.cpp
+++ b/contrib/llvm/tools/lldb/source/Host/posix/PipePosix.cpp
@@ -13,6 +13,12 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
+#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
+#ifndef _GLIBCXX_USE_NANOSLEEP
+#define _GLIBCXX_USE_NANOSLEEP
+#endif
+#endif
+
#include <functional>
#include <thread>
@@ -30,9 +36,9 @@ int PipePosix::kInvalidDescriptor = -1;
enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE
-// pipe2 is supported by Linux, FreeBSD v10 and higher.
+// pipe2 is supported by a limited set of platforms
// TODO: Add more platforms that support pipe2.
-#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10)
+#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
#define PIPE2_SUPPORTED 1
#else
#define PIPE2_SUPPORTED 0
diff --git a/contrib/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp b/contrib/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp
index ad75c4a..1688813 100644
--- a/contrib/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp
+++ b/contrib/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp
@@ -13,8 +13,8 @@
#include "lldb/Host/HostInfo.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Timer.h"
-#include "lldb/Interpreter/ScriptInterpreterPython.h"
-
+#include "lldb/Symbol/GoASTContext.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
#include "Plugins/Instruction/MIPS/EmulateInstructionMIPS.h"
@@ -23,9 +23,11 @@
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/OperatingSystem/Python/OperatingSystemPython.h"
#include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h"
+#include "Plugins/Platform/NetBSD/PlatformNetBSD.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
#if defined(__APPLE__)
+#include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h"
#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
#include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h"
@@ -37,7 +39,7 @@
#if defined(_MSC_VER)
#include "lldb/Host/windows/windows.h"
-#include "Plugins/Process/Windows/ProcessWindowsLog.h"
+#include "Plugins/Process/Windows/Common/ProcessWindowsLog.h"
#endif
#include "llvm/Support/TargetSelect.h"
@@ -92,6 +94,9 @@ SystemInitializerCommon::Initialize()
process_gdb_remote::ProcessGDBRemoteLog::Initialize();
// Initialize plug-ins
+ ClangASTContext::Initialize();
+ GoASTContext::Initialize();
+
ObjectContainerBSDArchive::Initialize();
ObjectFileELF::Initialize();
DynamicLoaderPOSIXDYLD::Initialize();
@@ -106,6 +111,7 @@ SystemInitializerCommon::Initialize()
//----------------------------------------------------------------------
#if defined(__APPLE__)
+ PlatformiOSSimulator::Initialize();
DynamicLoaderDarwinKernel::Initialize();
PlatformDarwinKernel::Initialize();
ObjectFileMachO::Initialize();
@@ -118,7 +124,6 @@ SystemInitializerCommon::Initialize()
ProcessWindowsLog::Initialize();
#endif
#ifndef LLDB_DISABLE_PYTHON
- ScriptInterpreterPython::InitializePrivate();
OperatingSystemPython::Initialize();
#endif
}
@@ -132,17 +137,21 @@ SystemInitializerCommon::Terminate()
DynamicLoaderPOSIXDYLD::Terminate();
platform_freebsd::PlatformFreeBSD::Terminate();
+ ClangASTContext::Terminate();
+ GoASTContext::Terminate();
+
EmulateInstructionARM::Terminate();
EmulateInstructionMIPS::Terminate();
EmulateInstructionMIPS64::Terminate();
#if defined(__APPLE__)
+ PlatformiOSSimulator::Terminate();
DynamicLoaderDarwinKernel::Terminate();
ObjectFileMachO::Terminate();
PlatformDarwinKernel::Terminate();
#endif
-#if defined(__WIN32__)
+#if defined(_MSC_VER)
ProcessWindowsLog::Terminate();
#endif
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp b/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp
index 2258c26..81e6b0a 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp
@@ -371,7 +371,7 @@ char **
Args::GetArgumentVector()
{
if (!m_argv.empty())
- return (char **)&m_argv[0];
+ return const_cast<char **>(&m_argv[0]);
return nullptr;
}
@@ -379,7 +379,7 @@ const char **
Args::GetConstArgumentVector() const
{
if (!m_argv.empty())
- return (const char **)&m_argv[0];
+ return const_cast<const char **>(&m_argv[0]);
return nullptr;
}
@@ -575,7 +575,8 @@ Args::ParseOptions (Options &options)
}
}
}
- OptionParser::Prepare();
+ Mutex::Locker options_locker(NULL);
+ OptionParser::Prepare(options_locker);
int val;
while (1)
{
@@ -719,7 +720,7 @@ Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::add
else
{
// Since the compiler can't handle things like "main + 12" we should
- // try to do this for now. The compliler doesn't like adding offsets
+ // try to do this for now. The compiler doesn't like adding offsets
// to function pointer types.
static RegularExpression g_symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
RegularExpression::Match regex_match(3);
@@ -1189,7 +1190,8 @@ Args::ParseAliasOptions (Options &options,
}
}
- OptionParser::Prepare();
+ Mutex::Locker options_locker(NULL);
+ OptionParser::Prepare(options_locker);
int val;
while (1)
{
@@ -1366,7 +1368,8 @@ Args::ParseArgsForCompletion
}
}
- OptionParser::Prepare();
+ Mutex::Locker options_locker(NULL);
+ OptionParser::Prepare(options_locker);
OptionParser::EnableError(false);
int val;
@@ -1387,7 +1390,7 @@ Args::ParseArgsForCompletion
int long_options_index = -1;
val = OptionParser::Parse (dummy_vec.size() - 1,
- (char *const *) &dummy_vec.front(),
+ const_cast<char *const *>(&dummy_vec.front()),
sstr.GetData(),
long_options,
&long_options_index);
@@ -1668,3 +1671,33 @@ Args::ExpandEscapedCharacters (const char *src, std::string &dst)
}
}
+std::string
+Args::EscapeLLDBCommandArgument (const std::string& arg, char quote_char)
+{
+ const char* chars_to_escape = nullptr;
+ switch (quote_char)
+ {
+ case '\0':
+ chars_to_escape = " \t\\'\"`";
+ break;
+ case '\'':
+ chars_to_escape = "";
+ break;
+ case '"':
+ chars_to_escape = "$\"`\\";
+ break;
+ default:
+ assert(false && "Unhandled quote character");
+ }
+
+ std::string res;
+ res.reserve(arg.size());
+ for (char c : arg)
+ {
+ if (::strchr(chars_to_escape, c))
+ res.push_back('\\');
+ res.push_back(c);
+ }
+ return res;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandHistory.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandHistory.cpp
index bbe64b4..9d3c814 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandHistory.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandHistory.cpp
@@ -130,9 +130,9 @@ CommandHistory::Dump (Stream& stream,
size_t stop_idx) const
{
Mutex::Locker locker(m_mutex);
- stop_idx = std::min(stop_idx, m_history.size() - 1);
+ stop_idx = std::min(stop_idx + 1, m_history.size());
for (size_t counter = start_idx;
- counter <= stop_idx;
+ counter < stop_idx;
counter++)
{
const std::string hist_item = m_history[counter];
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp
index 1da541b..fd88f0d 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -41,9 +41,9 @@
#include "../Commands/CommandObjectWatchpoint.h"
#include "../Commands/CommandObjectLanguage.h"
-
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
@@ -62,8 +62,6 @@
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Property.h"
-#include "lldb/Interpreter/ScriptInterpreterNone.h"
-#include "lldb/Interpreter/ScriptInterpreterPython.h"
#include "lldb/Target/Process.h"
@@ -87,6 +85,7 @@ g_properties[] =
{ "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." },
{ "prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." },
{ "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will stop running a 'command source' script upon encountering an error." },
+ { "space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, blank lines will be printed between between REPL submissions." },
{ nullptr , OptionValue::eTypeInvalid, true, 0 , nullptr, nullptr, nullptr }
};
@@ -94,7 +93,8 @@ enum
{
ePropertyExpandRegexAliases = 0,
ePropertyPromptOnQuit = 1,
- ePropertyStopCmdSourceOnError = 2
+ ePropertyStopCmdSourceOnError = 2,
+ eSpaceReplPrompts = 3
};
ConstString &
@@ -104,29 +104,23 @@ CommandInterpreter::GetStaticBroadcasterClass ()
return class_name;
}
-CommandInterpreter::CommandInterpreter
-(
- Debugger &debugger,
- ScriptLanguage script_language,
- bool synchronous_execution
-) :
- Broadcaster (&debugger, CommandInterpreter::GetStaticBroadcasterClass().AsCString()),
- Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
- IOHandlerDelegate (IOHandlerDelegate::Completion::LLDBCommand),
- m_debugger (debugger),
- m_synchronous_execution (synchronous_execution),
- m_skip_lldbinit_files (false),
- m_skip_app_init_files (false),
- m_script_interpreter_ap (),
- m_command_io_handler_sp (),
- m_comment_char ('#'),
- m_batch_command_mode (false),
- m_truncation_warning(eNoTruncation),
- m_command_source_depth (0),
- m_num_errors(0),
- m_quit_requested(false),
- m_stopped_for_crash(false)
-
+CommandInterpreter::CommandInterpreter(Debugger &debugger, ScriptLanguage script_language, bool synchronous_execution)
+ : Broadcaster(&debugger, CommandInterpreter::GetStaticBroadcasterClass().AsCString()),
+ Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
+ IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand),
+ m_debugger(debugger),
+ m_synchronous_execution(synchronous_execution),
+ m_skip_lldbinit_files(false),
+ m_skip_app_init_files(false),
+ m_script_interpreter_sp(),
+ m_command_io_handler_sp(),
+ m_comment_char('#'),
+ m_batch_command_mode(false),
+ m_truncation_warning(eNoTruncation),
+ m_command_source_depth(0),
+ m_num_errors(0),
+ m_quit_requested(false),
+ m_stopped_for_crash(false)
{
debugger.SetScriptLanguage (script_language);
SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
@@ -175,6 +169,13 @@ CommandInterpreter::GetStopCmdSourceOnError () const
return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
}
+bool
+CommandInterpreter::GetSpaceReplPrompts () const
+{
+ const uint32_t idx = eSpaceReplPrompts;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
void
CommandInterpreter::Initialize ()
{
@@ -360,11 +361,19 @@ CommandInterpreter::Initialize ()
#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
#else
+ #if defined(__APPLE__)
+ std::string shell_option;
+ shell_option.append("--shell-expand-args");
+ shell_option.append(" true");
+ shell_option.append(" --");
+ ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp);
+ #else
std::string shell_option;
shell_option.append("--shell=");
shell_option.append(HostInfo::GetDefaultShell().GetPath());
shell_option.append(" --");
ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp);
+ #endif
#endif
AddAlias ("r", cmd_obj_sp);
AddAlias ("run", cmd_obj_sp);
@@ -392,9 +401,9 @@ void
CommandInterpreter::Clear()
{
m_command_io_handler_sp.reset();
-
- if (m_script_interpreter_ap)
- m_script_interpreter_ap->Clear();
+
+ if (m_script_interpreter_sp)
+ m_script_interpreter_sp->Clear();
}
const char *
@@ -511,8 +520,7 @@ CommandInterpreter::LoadCommandDictionary ()
char buffer[1024];
int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
assert (num_printed < 1024);
- // Quiet unused variable warning for release builds.
- (void) num_printed;
+ UNUSED_IF_ASSERT_DISABLED(num_printed);
success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer);
if (!success)
break;
@@ -2011,7 +2019,7 @@ CommandInterpreter::HandleCompletion (const char *current_line,
matches);
if (num_command_matches <= 0)
- return num_command_matches;
+ return num_command_matches;
if (num_args == 0)
{
@@ -2030,18 +2038,18 @@ CommandInterpreter::HandleCompletion (const char *current_line,
std::string common_prefix;
matches.LongestCommonPrefix (common_prefix);
const size_t partial_name_len = command_partial_str.size();
+ common_prefix.erase (0, partial_name_len);
// If we matched a unique single command, add a space...
// Only do this if the completer told us this was a complete word, however...
if (num_command_matches == 1 && word_complete)
{
char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
+ common_prefix = Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
if (quote_char != '\0')
common_prefix.push_back(quote_char);
-
common_prefix.push_back(' ');
}
- common_prefix.erase (0, partial_name_len);
matches.InsertStringAtIndex(0, common_prefix.c_str());
}
return num_command_matches;
@@ -2709,48 +2717,19 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
}
ScriptInterpreter *
-CommandInterpreter::GetScriptInterpreter (bool can_create)
+CommandInterpreter::GetScriptInterpreter(bool can_create)
{
- if (m_script_interpreter_ap.get() != nullptr)
- return m_script_interpreter_ap.get();
-
+ if (m_script_interpreter_sp)
+ return m_script_interpreter_sp.get();
+
if (!can_create)
return nullptr;
-
- // <rdar://problem/11751427>
- // we need to protect the initialization of the script interpreter
- // otherwise we could end up with two threads both trying to create
- // their instance of it, and for some languages (e.g. Python)
- // this is a bulletproof recipe for disaster!
- // this needs to be a function-level static because multiple Debugger instances living in the same process
- // still need to be isolated and not try to initialize Python concurrently
- static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
- Mutex::Locker interpreter_lock(g_interpreter_mutex);
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
- if (log)
- log->Printf("Initializing the ScriptInterpreter now\n");
-
+
lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
- switch (script_lang)
- {
- case eScriptLanguagePython:
-#ifndef LLDB_DISABLE_PYTHON
- m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
- break;
-#else
- // Fall through to the None case when python is disabled
-#endif
- case eScriptLanguageNone:
- m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
- break;
- };
-
- return m_script_interpreter_ap.get();
+ m_script_interpreter_sp = PluginManager::GetScriptInterpreterForLanguage(script_lang, *this);
+ return m_script_interpreter_sp.get();
}
-
-
bool
CommandInterpreter::GetSynchronous ()
{
@@ -3059,7 +3038,10 @@ CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &
for (ThreadSP thread_sp : process_sp->GetThreadList().Threads())
{
StopReason reason = thread_sp->GetStopReason();
- if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation)
+ if ((reason == eStopReasonSignal
+ || reason == eStopReasonException
+ || reason == eStopReasonInstrumentation)
+ && !result.GetAbnormalStopWasExpected())
{
should_stop = true;
break;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp
index c0efd9e..616d3e3 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp
@@ -28,6 +28,8 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Target/Language.h"
+
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -395,7 +397,7 @@ CommandObject::HandleCompletion
StringList &matches
)
{
- // Default implmentation of WantsCompletion() is !WantsRawCommandString().
+ // Default implementation of WantsCompletion() is !WantsRawCommandString().
// Subclasses who want raw command string but desire, for example,
// argument completion should override WantsCompletion() to return true,
// instead.
@@ -848,7 +850,7 @@ LanguageTypeHelpTextCallback ()
StreamString sstr;
sstr << "One of the following languages:\n";
- LanguageRuntime::PrintAllLanguages(sstr, " ", "\n");
+ Language::PrintAllLanguages(sstr, " ", "\n");
sstr.Flush();
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h
index fd55fc4..5365aaa 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h
@@ -25,18 +25,16 @@ namespace lldb_private {
class CommandObjectScript : public CommandObjectRaw
{
public:
+ CommandObjectScript(CommandInterpreter &interpreter,
+ lldb::ScriptLanguage script_lang);
- CommandObjectScript (CommandInterpreter &interpreter,
- lldb::ScriptLanguage script_lang);
-
- virtual
- ~CommandObjectScript ();
+ ~CommandObjectScript() override;
protected:
- virtual bool
- DoExecute (const char *command, CommandReturnObject &result);
+ bool
+ DoExecute(const char *command, CommandReturnObject &result) override;
};
} // namespace lldb_private
-#endif // liblldb_CommandObjectScript_h_
+#endif // liblldb_CommandObjectScript_h_
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp
index 1b54187..b083c7f 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp
@@ -47,7 +47,8 @@ CommandReturnObject::CommandReturnObject () :
m_err_stream (),
m_status (eReturnStatusStarted),
m_did_change_process_state (false),
- m_interactive (true)
+ m_interactive (true),
+ m_abnormal_stop_was_expected(false)
{
}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
index e5a5c00..bbd9668 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -162,7 +162,7 @@ OptionGroupValueObjectDisplay::GetAsDumpOptions (LanguageRuntimeDescriptionDispl
lldb::TypeSummaryImplSP summary_sp)
{
DumpValueObjectOptions options;
- options.SetMaximumPointerDepth(ptr_depth);
+ options.SetMaximumPointerDepth( {DumpValueObjectOptions::PointerDepth::Mode::Always,ptr_depth} );
if (use_objc)
options.SetShowSummary(false);
else
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueLanguage.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueLanguage.cpp
index fd46553..dd7173c 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueLanguage.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueLanguage.cpp
@@ -16,7 +16,7 @@
#include "lldb/Core/Stream.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Interpreter/Args.h"
-#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/Language.h"
using namespace lldb;
using namespace lldb_private;
@@ -30,7 +30,7 @@ OptionValueLanguage::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, u
{
if (dump_mask & eDumpOptionType)
strm.PutCString (" = ");
- strm.PutCString (LanguageRuntime::GetNameForLanguageType(m_current_value));
+ strm.PutCString (Language::GetNameForLanguageType(m_current_value));
}
}
@@ -47,9 +47,28 @@ OptionValueLanguage::SetValueFromString (llvm::StringRef value, VarSetOperationT
case eVarSetOperationReplace:
case eVarSetOperationAssign:
{
- LanguageType new_type = LanguageRuntime::GetLanguageTypeFromString(value.data());
- m_value_was_set = true;
- m_current_value = new_type;
+ ConstString lang_name(value.trim());
+ std::set<lldb::LanguageType> languages_for_types;
+ std::set<lldb::LanguageType> languages_for_expressions;
+ Language::GetLanguagesSupportingTypeSystems(languages_for_types, languages_for_expressions);
+
+ LanguageType new_type = Language::GetLanguageTypeFromString(lang_name.GetCString());
+ if (new_type && languages_for_types.count(new_type))
+ {
+ m_value_was_set = true;
+ m_current_value = new_type;
+ }
+ else
+ {
+ StreamString error_strm;
+ error_strm.Printf("invalid language type '%s', ", value.str().c_str());
+ error_strm.Printf("valid values are:\n");
+ for (lldb::LanguageType language : languages_for_types)
+ {
+ error_strm.Printf("%s%s%s", " ", Language::GetNameForLanguageType(language), "\n");
+ }
+ error.SetErrorString(error_strm.GetData());
+ }
}
break;
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp
index e8d870a..a3c28f7 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp
@@ -311,6 +311,15 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValueArch (const ExecutionConte
return nullptr;
}
+OptionValueLanguage *
+OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage (const ExecutionContext *exe_ctx, uint32_t idx) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ return property->GetValue()->GetAsLanguage();
+ return nullptr;
+}
+
bool
OptionValueProperties::GetPropertyAtIndexAsArgs (const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const
{
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp b/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp
index 077fcbc..b9fe286 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp
+++ b/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp
@@ -17,7 +17,7 @@
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionValues.h"
-#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/Language.h"
using namespace lldb;
using namespace lldb_private;
@@ -129,7 +129,7 @@ Property::Property (const PropertyDefinition &definition) :
{
LanguageType new_lang = eLanguageTypeUnknown;
if (definition.default_cstr_value)
- LanguageRuntime::GetLanguageTypeFromString(definition.default_cstr_value);
+ Language::GetLanguageTypeFromString(definition.default_cstr_value);
else
new_lang = (LanguageType)definition.default_uint_value;
m_value_sp.reset (new OptionValueLanguage(new_lang));
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp b/contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp
deleted file mode 100644
index a581a0b..0000000
--- a/contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp
+++ /dev/null
@@ -1,524 +0,0 @@
-//===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// In order to guarantee correct working with Python, Python.h *MUST* be
-// the *FIRST* header file included here.
-#ifdef LLDB_DISABLE_PYTHON
-
-// Python is disabled in this build
-
-#else
-
-#include "lldb/lldb-python.h"
-
-#include <stdio.h>
-
-#include "lldb/Core/Stream.h"
-#include "lldb/Host/File.h"
-#include "lldb/Interpreter/PythonDataObjects.h"
-#include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Interpreter/ScriptInterpreterPython.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-void
-StructuredPythonObject::Dump(Stream &s) const
-{
- s << "Python Obj: 0x" << GetValue();
-}
-
-//----------------------------------------------------------------------
-// PythonObject
-//----------------------------------------------------------------------
-
-void
-PythonObject::Dump (Stream &strm) const
-{
- if (m_py_obj)
- {
- FILE *file = ::tmpfile();
- if (file)
- {
- ::PyObject_Print (m_py_obj, file, 0);
- const long length = ftell (file);
- if (length)
- {
- ::rewind(file);
- std::vector<char> file_contents (length,'\0');
- const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
- if (length_read > 0)
- strm.Write (file_contents.data(), length_read);
- }
- ::fclose (file);
- }
- }
- else
- strm.PutCString ("NULL");
-}
-
-PyObjectType
-PythonObject::GetObjectType() const
-{
- if (IsNULLOrNone())
- return PyObjectType::None;
-
- if (PyList_Check(m_py_obj))
- return PyObjectType::List;
- if (PyDict_Check(m_py_obj))
- return PyObjectType::Dictionary;
- if (PyString_Check(m_py_obj))
- return PyObjectType::String;
- if (PyInt_Check(m_py_obj) || PyLong_Check(m_py_obj))
- return PyObjectType::Integer;
- return PyObjectType::Unknown;
-}
-
-PythonString
-PythonObject::Repr ()
-{
- if (!m_py_obj)
- return PythonString ();
- PyObject *repr = PyObject_Repr(m_py_obj);
- if (!repr)
- return PythonString ();
- return PythonString(repr);
-}
-
-PythonString
-PythonObject::Str ()
-{
- if (!m_py_obj)
- return PythonString ();
- PyObject *str = PyObject_Str(m_py_obj);
- if (!str)
- return PythonString ();
- return PythonString(str);
-}
-
-bool
-PythonObject::IsNULLOrNone () const
-{
- return ((m_py_obj == nullptr) || (m_py_obj == Py_None));
-}
-
-StructuredData::ObjectSP
-PythonObject::CreateStructuredObject() const
-{
- switch (GetObjectType())
- {
- case PyObjectType::Dictionary:
- return PythonDictionary(m_py_obj).CreateStructuredDictionary();
- case PyObjectType::Integer:
- return PythonInteger(m_py_obj).CreateStructuredInteger();
- case PyObjectType::List:
- return PythonList(m_py_obj).CreateStructuredArray();
- case PyObjectType::String:
- return PythonString(m_py_obj).CreateStructuredString();
- case PyObjectType::None:
- return StructuredData::ObjectSP();
- default:
- return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
- }
-}
-
-//----------------------------------------------------------------------
-// PythonString
-//----------------------------------------------------------------------
-
-PythonString::PythonString (PyObject *py_obj) :
- PythonObject()
-{
- Reset(py_obj); // Use "Reset()" to ensure that py_obj is a string
-}
-
-PythonString::PythonString (const PythonObject &object) :
- PythonObject()
-{
- Reset(object.get()); // Use "Reset()" to ensure that py_obj is a string
-}
-
-PythonString::PythonString (llvm::StringRef string) :
- PythonObject(PyString_FromStringAndSize(string.data(), string.size()))
-{
-}
-
-PythonString::PythonString(const char *string) :
- PythonObject(PyString_FromString(string))
-{
-}
-
-PythonString::PythonString () :
- PythonObject()
-{
-}
-
-PythonString::~PythonString ()
-{
-}
-
-bool
-PythonString::Reset (PyObject *py_obj)
-{
- if (py_obj && PyString_Check(py_obj))
- return PythonObject::Reset(py_obj);
-
- PythonObject::Reset(nullptr);
- return py_obj == nullptr;
-}
-
-llvm::StringRef
-PythonString::GetString() const
-{
- if (m_py_obj)
- return llvm::StringRef(PyString_AsString(m_py_obj), GetSize());
- return llvm::StringRef();
-}
-
-size_t
-PythonString::GetSize() const
-{
- if (m_py_obj)
- return PyString_Size(m_py_obj);
- return 0;
-}
-
-void
-PythonString::SetString (llvm::StringRef string)
-{
- PythonObject::Reset(PyString_FromStringAndSize(string.data(), string.size()));
-}
-
-StructuredData::StringSP
-PythonString::CreateStructuredString() const
-{
- StructuredData::StringSP result(new StructuredData::String);
- result->SetValue(GetString());
- return result;
-}
-
-//----------------------------------------------------------------------
-// PythonInteger
-//----------------------------------------------------------------------
-
-PythonInteger::PythonInteger (PyObject *py_obj) :
- PythonObject()
-{
- Reset(py_obj); // Use "Reset()" to ensure that py_obj is a integer type
-}
-
-PythonInteger::PythonInteger (const PythonObject &object) :
- PythonObject()
-{
- Reset(object.get()); // Use "Reset()" to ensure that py_obj is a integer type
-}
-
-PythonInteger::PythonInteger (int64_t value) :
- PythonObject()
-{
- SetInteger (value);
-}
-
-
-PythonInteger::~PythonInteger ()
-{
-}
-
-bool
-PythonInteger::Reset (PyObject *py_obj)
-{
- if (py_obj)
- {
- if (PyInt_Check (py_obj) || PyLong_Check(py_obj))
- return PythonObject::Reset(py_obj);
- }
-
- PythonObject::Reset(nullptr);
- return py_obj == nullptr;
-}
-
-int64_t
-PythonInteger::GetInteger() const
-{
- if (m_py_obj)
- {
- if (PyInt_Check(m_py_obj))
- return PyInt_AsLong(m_py_obj);
- else if (PyLong_Check(m_py_obj))
- return PyLong_AsLongLong(m_py_obj);
- }
- return UINT64_MAX;
-}
-
-void
-PythonInteger::SetInteger (int64_t value)
-{
- PythonObject::Reset(PyLong_FromLongLong(value));
-}
-
-StructuredData::IntegerSP
-PythonInteger::CreateStructuredInteger() const
-{
- StructuredData::IntegerSP result(new StructuredData::Integer);
- result->SetValue(GetInteger());
- return result;
-}
-
-//----------------------------------------------------------------------
-// PythonList
-//----------------------------------------------------------------------
-
-PythonList::PythonList (bool create_empty) :
- PythonObject(create_empty ? PyList_New(0) : nullptr)
-{
-}
-
-PythonList::PythonList (uint32_t count) :
- PythonObject(PyList_New(count))
-{
-}
-
-PythonList::PythonList (PyObject *py_obj) :
- PythonObject()
-{
- Reset(py_obj); // Use "Reset()" to ensure that py_obj is a list
-}
-
-
-PythonList::PythonList (const PythonObject &object) :
- PythonObject()
-{
- Reset(object.get()); // Use "Reset()" to ensure that py_obj is a list
-}
-
-PythonList::~PythonList ()
-{
-}
-
-bool
-PythonList::Reset (PyObject *py_obj)
-{
- if (py_obj && PyList_Check(py_obj))
- return PythonObject::Reset(py_obj);
-
- PythonObject::Reset(nullptr);
- return py_obj == nullptr;
-}
-
-uint32_t
-PythonList::GetSize() const
-{
- if (m_py_obj)
- return PyList_GET_SIZE(m_py_obj);
- return 0;
-}
-
-PythonObject
-PythonList::GetItemAtIndex(uint32_t index) const
-{
- if (m_py_obj)
- return PythonObject(PyList_GetItem(m_py_obj, index));
- return PythonObject();
-}
-
-void
-PythonList::SetItemAtIndex (uint32_t index, const PythonObject & object)
-{
- if (m_py_obj && object)
- PyList_SetItem(m_py_obj, index, object.get());
-}
-
-void
-PythonList::AppendItem (const PythonObject &object)
-{
- if (m_py_obj && object)
- PyList_Append(m_py_obj, object.get());
-}
-
-StructuredData::ArraySP
-PythonList::CreateStructuredArray() const
-{
- StructuredData::ArraySP result(new StructuredData::Array);
- uint32_t count = GetSize();
- for (uint32_t i = 0; i < count; ++i)
- {
- PythonObject obj = GetItemAtIndex(i);
- result->AddItem(obj.CreateStructuredObject());
- }
- return result;
-}
-
-//----------------------------------------------------------------------
-// PythonDictionary
-//----------------------------------------------------------------------
-
-PythonDictionary::PythonDictionary (bool create_empty) :
-PythonObject(create_empty ? PyDict_New() : nullptr)
-{
-}
-
-PythonDictionary::PythonDictionary (PyObject *py_obj) :
- PythonObject(py_obj)
-{
- Reset(py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
-}
-
-
-PythonDictionary::PythonDictionary (const PythonObject &object) :
- PythonObject()
-{
- Reset(object.get()); // Use "Reset()" to ensure that py_obj is a dictionary
-}
-
-PythonDictionary::~PythonDictionary ()
-{
-}
-
-bool
-PythonDictionary::Reset (PyObject *py_obj)
-{
- if (py_obj && PyDict_Check(py_obj))
- return PythonObject::Reset(py_obj);
-
- PythonObject::Reset(nullptr);
- return py_obj == nullptr;
-}
-
-uint32_t
-PythonDictionary::GetSize() const
-{
- if (m_py_obj)
- return PyDict_Size(m_py_obj);
- return 0;
-}
-
-PythonObject
-PythonDictionary::GetItemForKey (const char *key) const
-{
- if (key && key[0])
- {
- PythonString python_key(key);
- return GetItemForKey(python_key);
- }
- return PythonObject();
-}
-
-
-PythonObject
-PythonDictionary::GetItemForKey (const PythonString &key) const
-{
- if (m_py_obj && key)
- return PythonObject(PyDict_GetItem(m_py_obj, key.get()));
- return PythonObject();
-}
-
-
-const char *
-PythonDictionary::GetItemForKeyAsString (const PythonString &key, const char *fail_value) const
-{
- if (m_py_obj && key)
- {
- PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get());
- if (py_obj && PyString_Check(py_obj))
- return PyString_AsString(py_obj);
- }
- return fail_value;
-}
-
-int64_t
-PythonDictionary::GetItemForKeyAsInteger (const PythonString &key, int64_t fail_value) const
-{
- if (m_py_obj && key)
- {
- PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get());
- if (py_obj)
- {
- if (PyInt_Check(py_obj))
- return PyInt_AsLong(py_obj);
-
- if (PyLong_Check(py_obj))
- return PyLong_AsLong(py_obj);
- }
- }
- return fail_value;
-}
-
-PythonList
-PythonDictionary::GetKeys () const
-{
- if (m_py_obj)
- return PythonList(PyDict_Keys(m_py_obj));
- return PythonList(true);
-}
-
-PythonString
-PythonDictionary::GetKeyAtPosition (uint32_t pos) const
-{
- PyObject *key, *value;
- Py_ssize_t pos_iter = 0;
-
- if (m_py_obj)
- {
- while (PyDict_Next(m_py_obj, &pos_iter, &key, &value))
- {
- if (pos-- == 0)
- return PythonString(key);
- }
- }
- return PythonString();
-}
-
-PythonObject
-PythonDictionary::GetValueAtPosition (uint32_t pos) const
-{
- PyObject *key, *value;
- Py_ssize_t pos_iter = 0;
-
- if (!m_py_obj)
- return PythonObject();
-
- while (PyDict_Next(m_py_obj, &pos_iter, &key, &value)) {
- if (pos-- == 0)
- return PythonObject(value);
- }
- return PythonObject();
-}
-
-void
-PythonDictionary::SetItemForKey (const PythonString &key, PyObject *value)
-{
- if (m_py_obj && key && value)
- PyDict_SetItem(m_py_obj, key.get(), value);
-}
-
-void
-PythonDictionary::SetItemForKey (const PythonString &key, const PythonObject &value)
-{
- if (m_py_obj && key && value)
- PyDict_SetItem(m_py_obj, key.get(), value.get());
-}
-
-StructuredData::DictionarySP
-PythonDictionary::CreateStructuredDictionary() const
-{
- StructuredData::DictionarySP result(new StructuredData::Dictionary);
- PythonList keys(GetKeys());
- uint32_t num_keys = keys.GetSize();
- for (uint32_t i = 0; i < num_keys; ++i)
- {
- PythonObject key = keys.GetItemAtIndex(i);
- PythonString key_str = key.Str();
- PythonObject value = GetItemForKey(key);
- StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
- result->AddItem(key_str.GetString(), structured_value);
- }
- return result;
-}
-
-#endif
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp
deleted file mode 100644
index 909a116..0000000
--- a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//===-- ScriptInterpreterNone.cpp -------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Interpreter/ScriptInterpreterNone.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/StringList.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-ScriptInterpreterNone::ScriptInterpreterNone (CommandInterpreter &interpreter) :
- ScriptInterpreter (interpreter, eScriptLanguageNone)
-{
-}
-
-ScriptInterpreterNone::~ScriptInterpreterNone ()
-{
-}
-
-bool
-ScriptInterpreterNone::ExecuteOneLine (const char *command, CommandReturnObject *, const ExecuteScriptOptions&)
-{
- m_interpreter.GetDebugger().GetErrorFile()->PutCString ("error: there is no embedded script interpreter in this mode.\n");
- return false;
-}
-
-void
-ScriptInterpreterNone::ExecuteInterpreterLoop ()
-{
- m_interpreter.GetDebugger().GetErrorFile()->PutCString ("error: there is no embedded script interpreter in this mode.\n");
-}
-
-
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py b/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py
index 10186f5..8ba539a 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py
+++ b/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py
@@ -1,7 +1,10 @@
-import __builtin__
+import sys
+if sys.version_info[0] < 3:
+ import __builtin__ as builtins
+else:
+ import builtins
import code
import lldb
-import sys
import traceback
try:
@@ -42,8 +45,8 @@ def setquit():
# "sys.exit(123)"
global g_builtin_override_called
g_builtin_override_called = False
- __builtin__.quit = LLDBQuitter('quit')
- __builtin__.exit = LLDBQuitter('exit')
+ builtins.quit = LLDBQuitter('quit')
+ builtins.exit = LLDBQuitter('exit')
# When running one line, we might place the string to run in this string
# in case it would be hard to correctly escape a string's contents
@@ -94,7 +97,7 @@ def run_python_interpreter (local_dict):
except SystemExit as e:
global g_builtin_override_called
if not g_builtin_override_called:
- print 'Script exited with %s' %(e)
+ print('Script exited with %s' %(e))
def run_one_line (local_dict, input_string):
global g_run_one_line_str
@@ -109,4 +112,4 @@ def run_one_line (local_dict, input_string):
except SystemExit as e:
global g_builtin_override_called
if not g_builtin_override_called:
- print 'Script exited with %s' %(e)
+ print('Script exited with %s' %(e))
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index 700d223..3b9b0f3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -17,7 +17,6 @@
#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -28,7 +27,7 @@
#include "llvm/ADT/Triple.h"
#include "Utility/ARM_DWARF_Registers.h"
-#include "Utility/ARM_GCC_Registers.h"
+#include "Utility/ARM_ehframe_Registers.h"
#include "Plugins/Process/Utility/ARMDefines.h"
#include <vector>
@@ -38,90 +37,90 @@ using namespace lldb_private;
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== ===============
- { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, gdb_arm_d0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, gdb_arm_d1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, gdb_arm_d2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, gdb_arm_d3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, gdb_arm_d4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, gdb_arm_d5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, gdb_arm_d6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, gdb_arm_d7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, gdb_arm_d8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, gdb_arm_d9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, gdb_arm_d10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, gdb_arm_d11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, gdb_arm_d12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, gdb_arm_d13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, gdb_arm_d14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, gdb_arm_d15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, gdb_arm_d16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, gdb_arm_d17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, gdb_arm_d18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, gdb_arm_d19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, gdb_arm_d20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, gdb_arm_d21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, gdb_arm_d22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, gdb_arm_d23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, gdb_arm_d24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, gdb_arm_d25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, gdb_arm_d26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, gdb_arm_d27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, gdb_arm_d28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, gdb_arm_d29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, gdb_arm_d30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, gdb_arm_d31, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r8_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r9_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r10_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
@@ -239,8 +238,8 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread,
size_t num_stack_regs = ae - ai;
sp -= (num_stack_regs * 4);
- // Keep the stack 8 byte aligned, not that we need to
- sp &= ~(8ull-1ull);
+ // Keep the stack 16 byte aligned
+ sp &= ~(16ull-1ull);
// just using arg1 to get the right size
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
@@ -333,18 +332,18 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread,
if (!value)
return false;
- ClangASTType clang_type = value->GetClangType();
- if (clang_type)
+ CompilerType compiler_type = value->GetCompilerType();
+ if (compiler_type)
{
bool is_signed = false;
size_t bit_width = 0;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
- bit_width = clang_type.GetBitSize(&thread);
+ bit_width = compiler_type.GetBitSize(&thread);
}
- else if (clang_type.IsPointerOrReferenceType ())
+ else if (compiler_type.IsPointerOrReferenceType ())
{
- bit_width = clang_type.GetBitSize(&thread);
+ bit_width = compiler_type.GetBitSize(&thread);
}
else
{
@@ -414,22 +413,37 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread,
return true;
}
+bool
+ABIMacOSX_arm::IsArmv7kProcess (Thread *thread) const
+{
+ bool is_armv7k = false;
+ if (thread)
+ {
+ ProcessSP process_sp (thread->GetProcess());
+ if (process_sp)
+ {
+ const ArchSpec &arch (process_sp->GetTarget().GetArchitecture());
+ const ArchSpec::Core system_core = arch.GetCore();
+ if (system_core == ArchSpec::eCore_arm_armv7k)
+ {
+ is_armv7k = true;
+ }
+ }
+ }
+ return is_armv7k;
+}
+
ValueObjectSP
ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
- lldb_private::ClangASTType &clang_type) const
+ lldb_private::CompilerType &compiler_type) const
{
Value value;
ValueObjectSP return_valobj_sp;
- if (!clang_type)
- return return_valobj_sp;
-
- clang::ASTContext *ast_context = clang_type.GetASTContext();
- if (!ast_context)
+ if (!compiler_type)
return return_valobj_sp;
- //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType());
- value.SetClangType (clang_type);
+ value.SetCompilerType (compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
@@ -441,14 +455,68 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
// when reading data
const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0);
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
- size_t bit_width = clang_type.GetBitSize(&thread);
+ size_t bit_width = compiler_type.GetBitSize(&thread);
switch (bit_width)
{
default:
return return_valobj_sp;
+ case 128:
+ if (IsArmv7kProcess (&thread))
+ {
+ // "A composite type not larger than 16 bytes is returned in r0-r3. The format is
+ // as if the result had been stored in memory at a word-aligned address and then
+ // loaded into r0-r3 with an ldm instruction"
+ {
+ const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0);
+ const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+ const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
+ if (r1_reg_info && r2_reg_info && r3_reg_info)
+ {
+ const size_t byte_size = compiler_type.GetByteSize(&thread);
+ ProcessSP process_sp (thread.GetProcess());
+ if (byte_size <= r0_reg_info->byte_size + r1_reg_info->byte_size + r2_reg_info->byte_size + r3_reg_info->byte_size
+ && process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue r0_reg_value;
+ RegisterValue r1_reg_value;
+ RegisterValue r2_reg_value;
+ RegisterValue r3_reg_value;
+ if (reg_ctx->ReadRegister(r0_reg_info, r0_reg_value)
+ && reg_ctx->ReadRegister(r1_reg_info, r1_reg_value)
+ && reg_ctx->ReadRegister(r2_reg_info, r2_reg_value)
+ && reg_ctx->ReadRegister(r3_reg_info, r3_reg_value))
+ {
+ Error error;
+ if (r0_reg_value.GetAsMemoryData (r0_reg_info, heap_data_ap->GetBytes()+0, 4, byte_order, error)
+ && r1_reg_value.GetAsMemoryData (r1_reg_info, heap_data_ap->GetBytes()+4, 4, byte_order, error)
+ && r2_reg_value.GetAsMemoryData (r2_reg_info, heap_data_ap->GetBytes()+8, 4, byte_order, error)
+ && r3_reg_value.GetAsMemoryData (r3_reg_info, heap_data_ap->GetBytes()+12, 4, byte_order, error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetAddressByteSize());
+
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ compiler_type,
+ ConstString(""),
+ data);
+ return return_valobj_sp;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ return return_valobj_sp;
+ }
+ break;
case 64:
{
const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0);
@@ -481,7 +549,7 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
break;
}
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
value.GetScalar() = ptr;
@@ -510,8 +578,8 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -526,7 +594,7 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
DataExtractor data;
Error data_error;
@@ -561,12 +629,45 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
}
}
}
+ else if (num_bytes <= 16 && IsArmv7kProcess (frame_sp->GetThread().get()))
+ {
+ // "A composite type not larger than 16 bytes is returned in r0-r3. The format is
+ // as if the result had been stored in memory at a word-aligned address and then
+ // loaded into r0-r3 with an ldm instruction"
+
+ const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0);
+ const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0);
+ const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+ const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
+ lldb::offset_t offset = 0;
+ uint32_t bytes_written = 4;
+ uint32_t raw_value = data.GetMaxU64(&offset, 4);
+ if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value) && bytes_written <= num_bytes)
+ {
+ bytes_written += 4;
+ raw_value = data.GetMaxU64(&offset, 4);
+ if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value))
+ {
+ bytes_written += 4;
+ raw_value = data.GetMaxU64(&offset, 4);
+ if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
+ {
+ bytes_written += 4;
+ raw_value = data.GetMaxU64(&offset, 4);
+ if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r3_info, raw_value))
+ {
+ set_it_simple = true;
+ }
+ }
+ }
+ }
+ }
else
{
error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
index eee4394..a4e9dea 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
@@ -20,42 +20,36 @@
class ABIMacOSX_arm : public lldb_private::ABI
{
public:
- ~ABIMacOSX_arm() { }
+ ~ABIMacOSX_arm() override = default;
- virtual size_t
- GetRedZoneSize () const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t func_addr,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t func_addr,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are are 4 byte aligned
if (cfa & (4ull - 1ull))
@@ -65,8 +59,8 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// Just make sure the address is a valid 32 bit address. Bit zero
// might be set due to Thumb function calls, so don't enforce 2 byte
@@ -74,20 +68,24 @@ public:
return pc <= UINT32_MAX;
}
- virtual lldb::addr_t
- FixCodeAddress (lldb::addr_t pc)
+ lldb::addr_t
+ FixCodeAddress(lldb::addr_t pc) override
{
// ARM uses bit zero to signify a code address is thumb, so we must
// strip bit zero in any code addresses.
return pc & ~(lldb::addr_t)1;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
+
+ bool
+ IsArmv7kProcess (lldb_private::Thread *thread) const;
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -103,13 +101,18 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const override;
+
private:
ABIMacOSX_arm() :
lldb_private::ABI()
@@ -118,4 +121,4 @@ private:
}
};
-#endif // liblldb_ABIMacOSX_arm_h_
+#endif // liblldb_ABIMacOSX_arm_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
index 04b9618..0e6f9d6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
@@ -19,7 +19,6 @@
#include "lldb/Core/Value.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -37,12 +36,11 @@ using namespace lldb;
using namespace lldb_private;
static const char *pluginDesc = "Mac OS X ABI for arm64 targets";
-static const char *pluginShort = "abi.macosx-arm64";
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE
// ========== ======= == === ============= =================== =================== ====================== =========================== ======================= ======================
{ "x0", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "x1", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
@@ -77,7 +75,7 @@ static RegisterInfo g_register_infos[] =
{ "lr", "x30", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "sp", "x31", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "pc", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "v0", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "v1", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
@@ -115,71 +113,71 @@ static RegisterInfo g_register_infos[] =
{ "fpsr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "fpcr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
-
- { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
+ { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+
+ { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -322,7 +320,7 @@ ABIMacOSX_arm64::GetArgumentValues (Thread &thread, ValueList &values) const
if (!value)
return false;
- ClangASTType value_type = value->GetClangType();
+ CompilerType value_type = value->GetCompilerType();
if (value_type)
{
bool is_signed = false;
@@ -424,7 +422,7 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO
return error;
}
- ClangASTType return_value_type = new_value_sp->GetClangType();
+ CompilerType return_value_type = new_value_sp->GetCompilerType();
if (!return_value_type)
{
error.SetErrorString ("Null clang type for return value.");
@@ -709,7 +707,7 @@ ABIMacOSX_arm64::RegisterIsVolatile (const RegisterInfo *reg_info)
static bool
LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
RegisterContext *reg_ctx,
- const ClangASTType &value_type,
+ const CompilerType &value_type,
bool is_return_value, // false => parameter, true => return value
uint32_t &NGRN, // NGRN (see ABI documentation)
uint32_t &NSRN, // NSRN (see ABI documentation)
@@ -724,18 +722,16 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
Error error;
- ClangASTType base_type;
+ CompilerType base_type;
const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type);
if (homogeneous_count > 0 && homogeneous_count <= 8)
{
- printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count);
// Make sure we have enough registers
if (NSRN < 8 && (8-NSRN) >= homogeneous_count)
{
if (!base_type)
return false;
const size_t base_byte_size = base_type.GetByteSize(nullptr);
- printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size);
uint32_t data_offset = 0;
for (uint32_t i=0; i<homogeneous_count; ++i)
@@ -861,7 +857,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
}
ValueObjectSP
-ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
@@ -870,16 +866,16 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
return return_valobj_sp;
- //value.SetContext (Value::eContextTypeClangType, return_clang_type);
- value.SetClangType(return_clang_type);
+ //value.SetContext (Value::eContextTypeClangType, return_compiler_type);
+ value.SetCompilerType(return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL);
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL);
if (type_flags & eTypeIsScalar ||
type_flags & eTypeIsPointer)
{
@@ -926,7 +922,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
exe_ctx.GetProcessRef().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
return return_valobj_sp;
@@ -1043,7 +1039,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
byte_order,
exe_ctx.GetProcessRef().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
@@ -1060,10 +1056,10 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
uint32_t NGRN = 0; // Search ABI docs for NGRN
uint32_t NSRN = 0; // Search ABI docs for NSRN
const bool is_return_value = true;
- if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_clang_type, is_return_value, NGRN, NSRN, data))
+ if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_compiler_type, is_return_value, NGRN, NSRN, data))
{
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
@@ -1095,12 +1091,6 @@ ABIMacOSX_arm64::GetPluginNameStatic()
return g_plugin_name;
}
-const char *
-ABIMacOSX_arm64::GetShortPluginName()
-{
- return pluginShort;
-}
-
uint32_t
ABIMacOSX_arm64::GetPluginVersion()
{
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
index 6cce6a6..1bc94f6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
@@ -22,30 +22,30 @@ class ABIMacOSX_arm64 :
public lldb_private::ABI
{
public:
- ~ABIMacOSX_arm64() { }
+ ~ABIMacOSX_arm64() override = default;
- virtual size_t
- GetRedZoneSize () const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The arm64 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -57,9 +57,8 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
-
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -69,8 +68,8 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
if (pc & (4ull - 1ull))
return false; // Not 4 byte aligned
@@ -79,12 +78,13 @@ public:
return true;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -97,28 +97,26 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
+
static lldb_private::ConstString
GetPluginNameStatic();
- virtual lldb_private::ConstString
- GetPluginName()
+ lldb_private::ConstString
+ GetPluginName() override
{
return GetPluginNameStatic();
}
- virtual const char *
- GetShortPluginName();
-
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
protected:
- virtual lldb::ValueObjectSP
+ lldb::ValueObjectSP
GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
+ lldb_private::CompilerType &ast_type) const override;
private:
ABIMacOSX_arm64() :
@@ -128,4 +126,4 @@ private:
}
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABIMacOSX_arm64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index 4204d18..75e5fb1 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -16,13 +16,13 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include <vector>
@@ -32,16 +32,16 @@ using namespace lldb_private;
enum
{
- gcc_eax = 0,
- gcc_ecx,
- gcc_edx,
- gcc_ebx,
- gcc_ebp,
- gcc_esp,
- gcc_esi,
- gcc_edi,
- gcc_eip,
- gcc_eflags
+ ehframe_eax = 0,
+ ehframe_ecx,
+ ehframe_edx,
+ ehframe_ebx,
+ ehframe_ebp, // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin
+ ehframe_esp, // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin
+ ehframe_esi,
+ ehframe_edi,
+ ehframe_eip,
+ ehframe_eflags
};
enum
@@ -82,121 +82,60 @@ enum
dwarf_ymm7 = dwarf_xmm7
};
-enum
-{
- gdb_eax = 0,
- gdb_ecx = 1,
- gdb_edx = 2,
- gdb_ebx = 3,
- gdb_esp = 4,
- gdb_ebp = 5,
- gdb_esi = 6,
- gdb_edi = 7,
- gdb_eip = 8,
- gdb_eflags = 9,
- gdb_cs = 10,
- gdb_ss = 11,
- gdb_ds = 12,
- gdb_es = 13,
- gdb_fs = 14,
- gdb_gs = 15,
- gdb_stmm0 = 16,
- gdb_stmm1 = 17,
- gdb_stmm2 = 18,
- gdb_stmm3 = 19,
- gdb_stmm4 = 20,
- gdb_stmm5 = 21,
- gdb_stmm6 = 22,
- gdb_stmm7 = 23,
- gdb_fctrl = 24, gdb_fcw = gdb_fctrl,
- gdb_fstat = 25, gdb_fsw = gdb_fstat,
- gdb_ftag = 26, gdb_ftw = gdb_ftag,
- gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg,
- gdb_fioff = 28, gdb_ip = gdb_fioff,
- gdb_foseg = 29, gdb_fpu_ds = gdb_foseg,
- gdb_fooff = 30, gdb_dp = gdb_fooff,
- gdb_fop = 31,
- gdb_xmm0 = 32,
- gdb_xmm1 = 33,
- gdb_xmm2 = 34,
- gdb_xmm3 = 35,
- gdb_xmm4 = 36,
- gdb_xmm5 = 37,
- gdb_xmm6 = 38,
- gdb_xmm7 = 39,
- gdb_mxcsr = 40,
- gdb_mm0 = 41,
- gdb_mm1 = 42,
- gdb_mm2 = 43,
- gdb_mm3 = 44,
- gdb_mm4 = 45,
- gdb_mm5 = 46,
- gdb_mm6 = 47,
- gdb_mm7 = 48,
- gdb_ymm0 = gdb_xmm0,
- gdb_ymm1 = gdb_xmm1,
- gdb_ymm2 = gdb_xmm2,
- gdb_ymm3 = gdb_xmm3,
- gdb_ymm4 = gdb_xmm4,
- gdb_ymm5 = gdb_xmm5,
- gdb_ymm6 = gdb_xmm6,
- gdb_ymm7 = gdb_xmm7
-};
-
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== ===============
- { "eax", NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_eax , dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ebx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ecx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , gdb_ecx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "edx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , gdb_edx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "esi" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , gdb_esi , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "edi" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , gdb_edi , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { gcc_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { gcc_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { gcc_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "eflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0 , LLDB_INVALID_REGNUM , gdb_stmm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1 , LLDB_INVALID_REGNUM , gdb_stmm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2 , LLDB_INVALID_REGNUM , gdb_stmm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3 , LLDB_INVALID_REGNUM , gdb_stmm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4 , LLDB_INVALID_REGNUM , gdb_stmm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5 , LLDB_INVALID_REGNUM , gdb_stmm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6 , LLDB_INVALID_REGNUM , gdb_stmm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7 , LLDB_INVALID_REGNUM , gdb_stmm7 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, NULL, NULL}
+ { "eax", NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ebx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ecx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "edx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "esi" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "edi" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { ehframe_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { ehframe_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { ehframe_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "eflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -237,7 +176,7 @@ ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)
{
static ABISP g_abi_sp;
if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
- (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS()))
+ (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() || arch.GetTriple().isWatchOS()))
{
if (!g_abi_sp)
g_abi_sp.reset (new ABIMacOSX_i386);
@@ -316,184 +255,6 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,
return true;
}
-bool
-ABIMacOSX_i386::PrepareNormalCall (Thread &thread,
- addr_t sp,
- addr_t func_addr,
- addr_t return_addr,
- ValueList &args) const
-{
- ExecutionContext exe_ctx (thread.shared_from_this());
- RegisterContext *reg_ctx = thread.GetRegisterContext().get();
- if (!reg_ctx)
- return false;
-
- Process *process = exe_ctx.GetProcessPtr();
- Error error;
- uint32_t fp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
- uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
-
- // Do the argument layout
-
- std::vector <uint32_t> argLayout; // 4-byte chunks, as discussed in the ABI Function Call Guide
-
- size_t numArgs = args.GetSize();
- size_t index;
-
- for (index = 0; index < numArgs; ++index)
- {
- Value *val = args.GetValueAtIndex(index);
-
- if (!val)
- return false;
-
- switch (val->GetValueType())
- {
- case Value::eValueTypeScalar:
- {
- Scalar &scalar = val->GetScalar();
- switch (scalar.GetType())
- {
- case Scalar::e_void:
- return false;
- case Scalar::e_sint:
- case Scalar::e_uint:
- case Scalar::e_slong:
- case Scalar::e_ulong:
- case Scalar::e_slonglong:
- case Scalar::e_ulonglong:
- {
- uint64_t data = scalar.ULongLong();
-
- switch (scalar.GetByteSize())
- {
- default:
- return false;
- case 1:
- argLayout.push_back((uint32_t)(data & 0xffull));
- break;
- case 2:
- argLayout.push_back((uint32_t)(data & 0xffffull));
- break;
- case 4:
- argLayout.push_back((uint32_t)(data & 0xffffffffull));
- break;
- case 8:
- argLayout.push_back((uint32_t)(data & 0xffffffffull));
- argLayout.push_back((uint32_t)(data >> 32));
- break;
- }
- }
- break;
- case Scalar::e_float:
- {
- float data = scalar.Float();
- uint32_t dataRaw = *((uint32_t*)(&data));
- argLayout.push_back(dataRaw);
- }
- break;
- case Scalar::e_double:
- {
- double data = scalar.Double();
- uint32_t *dataRaw = ((uint32_t*)(&data));
- argLayout.push_back(dataRaw[0]);
- argLayout.push_back(dataRaw[1]);
- }
- break;
- case Scalar::e_long_double:
- {
- long double data = scalar.Double();
- uint32_t *dataRaw = ((uint32_t*)(&data));
- while ((argLayout.size() * 4) & 0xf)
- argLayout.push_back(0);
- argLayout.push_back(dataRaw[0]);
- argLayout.push_back(dataRaw[1]);
- argLayout.push_back(dataRaw[2]);
- argLayout.push_back(dataRaw[3]);
- }
- break;
- }
- }
- break;
- case Value::eValueTypeHostAddress:
- {
- ClangASTType clang_type (val->GetClangType());
- if (clang_type)
- {
- uint32_t cstr_length = 0;
- if (clang_type.IsCStringType (cstr_length))
- {
- const char *cstr = (const char*)val->GetScalar().ULongLong();
- cstr_length = strlen(cstr);
-
- // Push the string onto the stack immediately.
-
- sp -= (cstr_length + 1);
-
- if (process->WriteMemory(sp, cstr, cstr_length + 1, error) != (cstr_length + 1))
- return false;
-
- // Put the address of the string into the argument array.
-
- argLayout.push_back((uint32_t)(sp & 0xffffffff));
- }
- else
- {
- return false;
- }
- }
- break;
- }
- break;
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeLoadAddress:
- default:
- return false;
- }
- }
-
- // Make room for the arguments on the stack
-
- sp -= 4 * argLayout.size();
-
- // Align the SP
-
- sp &= ~(16ull-1ull); // 16-byte alignment
-
- // Write the arguments on the stack
-
- size_t numChunks = argLayout.size();
-
- for (index = 0; index < numChunks; ++index)
- if (process->WriteMemory(sp + (index * 4), &argLayout[index], sizeof(uint32_t), error) != sizeof(uint32_t))
- return false;
-
- // The return address is pushed onto the stack.
-
- sp -= 4;
- uint32_t returnAddressU32 = return_addr;
- if (process->WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32))
- return false;
-
- // %esp is set to the actual stack value.
-
- if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
- return false;
-
- // %ebp is set to a fake value, in our case 0x0x00000000
-
- if (!reg_ctx->WriteRegisterFromUnsigned(fp_reg_num, 0x00000000))
- return false;
-
- // %eip is set to the address of the called function.
-
- if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
- return false;
-
- return true;
-}
-
static bool
ReadIntegerArgument (Scalar &scalar,
unsigned int bit_width,
@@ -545,23 +306,23 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread,
// We currently only support extracting values with Clang QualTypes.
// Do we care about others?
- ClangASTType clang_type (value->GetClangType());
- if (clang_type)
+ CompilerType compiler_type (value->GetCompilerType());
+ if (compiler_type)
{
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
is_signed,
thread.GetProcess().get(),
current_stack_argument);
}
- else if (clang_type.IsPointerType())
+ else if (compiler_type.IsPointerType())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
false,
thread.GetProcess().get(),
current_stack_argument);
@@ -582,8 +343,8 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -598,7 +359,7 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
DataExtractor data;
Error data_error;
@@ -638,7 +399,7 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
@@ -654,16 +415,16 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
ValueObjectSP
ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
- ClangASTType &clang_type) const
+ CompilerType &compiler_type) const
{
Value value;
ValueObjectSP return_valobj_sp;
- if (!clang_type)
+ if (!compiler_type)
return return_valobj_sp;
- //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType());
- value.SetClangType (clang_type);
+ //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType());
+ value.SetCompilerType (compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
@@ -671,9 +432,9 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
- size_t bit_width = clang_type.GetBitSize(&thread);
+ size_t bit_width = compiler_type.GetBitSize(&thread);
unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
@@ -713,7 +474,7 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
break;
}
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
index d81b7a7..6a82fce 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
@@ -22,48 +22,33 @@ class ABIMacOSX_i386 :
public lldb_private::ABI
{
public:
-
- ~ABIMacOSX_i386() { }
-
- virtual size_t
- GetRedZoneSize () const;
+ ~ABIMacOSX_i386() override = default;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t func_addr,
- lldb::addr_t return_addr,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareNormalCall (lldb_private::Thread &thread,
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
lldb::addr_t sp,
lldb::addr_t func_addr,
lldb::addr_t return_addr,
- lldb_private::ValueList &args) const;
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
-
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The Darwin i386 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -78,8 +63,8 @@ public:
//
// If we were to enforce 16-byte alignment, we also need to relax to 4-byte
// alignment for non-darwin i386 targets.
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are are 4 byte aligned
if (cfa & (4ull - 1ull))
@@ -89,19 +74,20 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// Just make sure the address is a valid 32 bit address.
return pc <= UINT32_MAX;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -114,22 +100,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
+
static lldb_private::ConstString
GetPluginNameStatic ();
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const override;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABIMacOSX_i386() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABIMacOSX_i386_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
index 50a9863..ef625de 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
@@ -17,7 +17,6 @@
#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -28,7 +27,7 @@
#include "llvm/ADT/Triple.h"
#include "Utility/ARM_DWARF_Registers.h"
-#include "Utility/ARM_GCC_Registers.h"
+#include "Utility/ARM_ehframe_Registers.h"
#include "Plugins/Process/Utility/ARMDefines.h"
#include <vector>
@@ -38,90 +37,90 @@ using namespace lldb_private;
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== ===============
- { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, gdb_arm_d0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, gdb_arm_d1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, gdb_arm_d2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, gdb_arm_d3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, gdb_arm_d4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, gdb_arm_d5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, gdb_arm_d6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, gdb_arm_d7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, gdb_arm_d8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, gdb_arm_d9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, gdb_arm_d10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, gdb_arm_d11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, gdb_arm_d12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, gdb_arm_d13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, gdb_arm_d14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, gdb_arm_d15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, gdb_arm_d16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, gdb_arm_d17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, gdb_arm_d18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, gdb_arm_d19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, gdb_arm_d20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, gdb_arm_d21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, gdb_arm_d22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, gdb_arm_d23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, gdb_arm_d24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, gdb_arm_d25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, gdb_arm_d26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, gdb_arm_d27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, gdb_arm_d28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, gdb_arm_d29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, gdb_arm_d30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, gdb_arm_d31, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r8_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r9_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r10_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
@@ -333,18 +332,18 @@ ABISysV_arm::GetArgumentValues (Thread &thread,
if (!value)
return false;
- ClangASTType clang_type = value->GetClangType();
- if (clang_type)
+ CompilerType compiler_type = value->GetCompilerType();
+ if (compiler_type)
{
bool is_signed = false;
size_t bit_width = 0;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
- bit_width = clang_type.GetBitSize(&thread);
+ bit_width = compiler_type.GetBitSize(&thread);
}
- else if (clang_type.IsPointerOrReferenceType ())
+ else if (compiler_type.IsPointerOrReferenceType ())
{
- bit_width = clang_type.GetBitSize(&thread);
+ bit_width = compiler_type.GetBitSize(&thread);
}
else
{
@@ -398,22 +397,35 @@ ABISysV_arm::GetArgumentValues (Thread &thread,
return true;
}
+static bool
+GetReturnValuePassedInMemory(Thread &thread, RegisterContext* reg_ctx, size_t byte_size, Value& value)
+{
+ Error error;
+ DataBufferHeap buffer(byte_size, 0);
+
+ const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+ uint32_t address = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+ thread.GetProcess()->ReadMemory(address, buffer.GetBytes(), buffer.GetByteSize(), error);
+
+ if (error.Fail())
+ return false;
+
+ value.SetBytes(buffer.GetBytes(), buffer.GetByteSize());
+ return true;
+}
+
ValueObjectSP
ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
- lldb_private::ClangASTType &clang_type) const
+ lldb_private::CompilerType &compiler_type) const
{
Value value;
ValueObjectSP return_valobj_sp;
- if (!clang_type)
+ if (!compiler_type)
return return_valobj_sp;
- clang::ASTContext *ast_context = clang_type.GetASTContext();
- if (!ast_context)
- return return_valobj_sp;
-
- //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType());
- value.SetClangType (clang_type);
+ //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType());
+ value.SetCompilerType (compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
@@ -427,9 +439,9 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
// when reading data
const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
- size_t bit_width = clang_type.GetBitSize(&thread);
+ size_t bit_width = compiler_type.GetBitSize(&thread);
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
switch (bit_width)
{
@@ -467,12 +479,33 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
break;
}
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
value.GetScalar() = ptr;
}
- else if (clang_type.IsFloatingPointType(float_count, is_complex))
+ else if (compiler_type.IsVectorType(nullptr, nullptr))
+ {
+ size_t byte_size = compiler_type.GetByteSize(&thread);
+ if (byte_size <= 16)
+ {
+ DataBufferHeap buffer(16, 0);
+ uint32_t* buffer_ptr = (uint32_t*)buffer.GetBytes();
+
+ for (uint32_t i = 0; 4*i < byte_size; ++i)
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
+ buffer_ptr[i] = reg_ctx->ReadRegisterAsUnsigned(reg_info, 0) & UINT32_MAX;
+ }
+ value.SetBytes(buffer.GetBytes(), byte_size);
+ }
+ else
+ {
+ if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value))
+ return return_valobj_sp;
+ }
+ }
+ else if (compiler_type.IsFloatingPointType(float_count, is_complex))
{
if (float_count == 1 && !is_complex)
{
@@ -506,9 +539,9 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
return return_valobj_sp;
}
}
- else if (clang_type.IsAggregateType())
+ else if (compiler_type.IsAggregateType())
{
- size_t byte_size = clang_type.GetByteSize(&thread);
+ size_t byte_size = compiler_type.GetByteSize(&thread);
if (byte_size <= 4)
{
RegisterValue r0_reg_value;
@@ -517,16 +550,7 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
}
else
{
- RegisterValue r0_reg_value;
- uint32_t address = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
-
- Error error;
- DataBufferHeap buffer(byte_size, 0);
- thread.GetProcess()->ReadMemory(address, buffer.GetBytes(), buffer.GetByteSize(), error);
-
- if (error.Success())
- value.SetBytes(buffer.GetBytes(), buffer.GetByteSize());
- else
+ if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value))
return return_valobj_sp;
}
}
@@ -554,8 +578,8 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -570,7 +594,7 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
DataExtractor data;
Error data_error;
@@ -610,7 +634,7 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.h
index 69becd6..e3b2802 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.h
@@ -20,7 +20,7 @@
class ABISysV_arm : public lldb_private::ABI
{
public:
- ~ABISysV_arm() { }
+ ~ABISysV_arm() override = default;
size_t
GetRedZoneSize () const override;
@@ -39,12 +39,6 @@ public:
lldb_private::Error
SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
- lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const override;
-
-public:
bool
CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
@@ -88,6 +82,7 @@ public:
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -103,6 +98,7 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
+
lldb_private::ConstString
GetPluginName() override;
@@ -110,6 +106,10 @@ public:
GetPluginVersion() override;
protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const override;
+
private:
ABISysV_arm() :
lldb_private::ABI()
@@ -118,4 +118,4 @@ private:
}
};
-#endif // liblldb_ABISysV_arm_h_
+#endif // liblldb_ABISysV_arm_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
index ed058ff..bc6df23 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
@@ -18,7 +18,6 @@
#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -37,7 +36,7 @@ using namespace lldb_private;
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE
// ========== ======= == === ============= =================== =================== ====================== =========================== ======================= ======================
{ "x0", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "x1", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
@@ -313,7 +312,7 @@ ABISysV_arm64::GetArgumentValues (Thread &thread, ValueList &values) const
if (!value)
return false;
- ClangASTType value_type = value->GetClangType();
+ CompilerType value_type = value->GetCompilerType();
if (value_type)
{
bool is_signed = false;
@@ -397,7 +396,7 @@ ABISysV_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
return error;
}
- ClangASTType return_value_type = new_value_sp->GetClangType();
+ CompilerType return_value_type = new_value_sp->GetCompilerType();
if (!return_value_type)
{
error.SetErrorString ("Null clang type for return value.");
@@ -686,7 +685,7 @@ ABISysV_arm64::RegisterIsVolatile (const RegisterInfo *reg_info)
static bool
LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
RegisterContext *reg_ctx,
- const ClangASTType &value_type,
+ const CompilerType &value_type,
bool is_return_value, // false => parameter, true => return value
uint32_t &NGRN, // NGRN (see ABI documentation)
uint32_t &NSRN, // NSRN (see ABI documentation)
@@ -701,18 +700,16 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
Error error;
- ClangASTType base_type;
+ CompilerType base_type;
const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type);
if (homogeneous_count > 0 && homogeneous_count <= 8)
{
- printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count);
// Make sure we have enough registers
if (NSRN < 8 && (8-NSRN) >= homogeneous_count)
{
if (!base_type)
return false;
const size_t base_byte_size = base_type.GetByteSize(nullptr);
- printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size);
uint32_t data_offset = 0;
for (uint32_t i=0; i<homogeneous_count; ++i)
@@ -831,7 +828,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
}
ValueObjectSP
-ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
@@ -840,16 +837,16 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
return return_valobj_sp;
- //value.SetContext (Value::eContextTypeClangType, return_clang_type);
- value.SetClangType(return_clang_type);
+ //value.SetContext (Value::eContextTypeClangType, return_compiler_type);
+ value.SetCompilerType(return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL);
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL);
if (type_flags & eTypeIsScalar ||
type_flags & eTypeIsPointer)
{
@@ -898,7 +895,7 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
exe_ctx.GetProcessRef().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
return return_valobj_sp;
@@ -1015,7 +1012,7 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
byte_order,
exe_ctx.GetProcessRef().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
@@ -1032,10 +1029,10 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
uint32_t NGRN = 0; // Search ABI docs for NGRN
uint32_t NSRN = 0; // Search ABI docs for NSRN
const bool is_return_value = true;
- if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_clang_type, is_return_value, NGRN, NSRN, data))
+ if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_compiler_type, is_return_value, NGRN, NSRN, data))
{
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h
index 08c8682..e36f87e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h
@@ -20,7 +20,7 @@
class ABISysV_arm64 : public lldb_private::ABI
{
public:
- ~ABISysV_arm64() { }
+ ~ABISysV_arm64() override = default;
size_t
GetRedZoneSize () const override;
@@ -39,12 +39,6 @@ public:
lldb_private::Error
SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
- lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const override;
-
-public:
bool
CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
@@ -64,7 +58,6 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
-
bool
CallFrameAddressIsValid (lldb::addr_t cfa) override
{
@@ -92,6 +85,7 @@ public:
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -107,6 +101,7 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
+
lldb_private::ConstString
GetPluginName() override;
@@ -114,6 +109,10 @@ public:
GetPluginVersion() override;
protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const override;
+
private:
ABISysV_arm64() :
lldb_private::ABI()
@@ -122,4 +121,4 @@ private:
}
};
-#endif // liblldb_ABISysV_arm64_h_
+#endif // liblldb_ABISysV_arm64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
index 69129df..e0299b6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -30,7 +29,7 @@
#include "llvm/ADT/Triple.h"
-#include "llvm/IR/Type.h"
+#include "llvm/IR/DerivedTypes.h"
using namespace lldb;
using namespace lldb_private;
@@ -227,7 +226,7 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
// . handle 64bit values and their register / stack requirements
*/
-#define HEX_ABI_DEBUG 1
+#define HEX_ABI_DEBUG 0
bool
ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
lldb::addr_t sp ,
@@ -243,6 +242,23 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
// grab the process so we have access to the memory for spilling
lldb::ProcessSP proc = thread.GetProcess( );
+ // get the register context for modifying all of the registers
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ if (pc_reg == LLDB_INVALID_REGNUM)
+ return false;
+
+ uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+ if (ra_reg == LLDB_INVALID_REGNUM)
+ return false;
+
+ uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ if (sp_reg == LLDB_INVALID_REGNUM)
+ return false;
+
// push host data onto target
for ( size_t i = 0; i < args.size( ); i++ )
{
@@ -277,11 +293,6 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
// check if this is a variable argument function
bool isVArg = prototype.isFunctionVarArg();
- // get the register context for modifying all of the registers
- RegisterContext *reg_ctx = thread.GetRegisterContext().get();
- if (!reg_ctx)
- return false;
-
// number of arguments passed by register
int nRegArgs = nVArgRegParams;
if (! isVArg )
@@ -324,10 +335,9 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
}
// update registers with current function call state
- reg_ctx->WriteRegisterFromUnsigned ( 41, pc );
- reg_ctx->WriteRegisterFromUnsigned ( 31, ra );
- reg_ctx->WriteRegisterFromUnsigned ( 29, sp );
-// reg_ctx->WriteRegisterFromUnsigned ( FP ??? );
+ reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc);
+ reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra);
+ reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp);
#if HEX_ABI_DEBUG
// quick and dirty stack dumper for debugging
@@ -359,14 +369,14 @@ ABISysV_hexagon::SetReturnValueObject ( lldb::StackFrameSP &frame_sp, lldb::Valu
}
ValueObjectSP
-ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, ClangASTType &return_clang_type ) const
+ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, CompilerType &return_compiler_type ) const
{
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
}
ValueObjectSP
-ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, ClangASTType &return_clang_type ) const
+ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, CompilerType &return_compiler_type ) const
{
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
index 1550a38..337e3fd 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
@@ -21,63 +21,54 @@ class ABISysV_hexagon :
public lldb_private::ABI
{
public:
+ ~ABISysV_hexagon() override = default;
- ~ABISysV_hexagon( void )
- {
- }
-
- virtual size_t
- GetRedZoneSize ( void ) const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall ( lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args ) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
// special thread plan for GDB style non-jit function calls
- virtual bool
- PrepareTrivialCall ( lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::Type &prototype,
- llvm::ArrayRef<ABI::CallArgument> args ) const;
-
- virtual bool
- GetArgumentValues ( lldb_private::Thread &thread,
- lldb_private::ValueList &values ) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::Type &prototype,
+ llvm::ArrayRef<ABI::CallArgument> args) const override;
+
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject ( lldb::StackFrameSP &frame_sp,
- lldb::ValueObjectSP &new_value );
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp,
+ lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple ( lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type ) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl ( lldb_private::Thread &thread,
- lldb_private::ClangASTType &type ) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
// specialized to work with llvm IR types
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl ( lldb_private::Thread &thread, llvm::Type &type ) const;
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl(lldb_private::Thread &thread, llvm::Type &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan ( lldb_private::UnwindPlan &unwind_plan );
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan ( lldb_private::UnwindPlan &unwind_plan );
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile ( const lldb_private::RegisterInfo *reg_info );
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
- virtual bool
- CallFrameAddressIsValid ( lldb::addr_t cfa )
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & 0x07)
@@ -87,50 +78,60 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid ( lldb::addr_t pc )
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// We have a 64 bit address space, so anything is valid as opcodes
// aren't fixed width...
return true;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray ( uint32_t &count );
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
- Initialize ( void );
+ Initialize();
static void
- Terminate ( void );
+ Terminate();
static lldb::ABISP
CreateInstance ( const lldb_private::ArchSpec &arch );
static lldb_private::ConstString
- GetPluginNameStatic ( void );
+ GetPluginNameStatic();
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName ( void );
- virtual uint32_t
- GetPluginVersion ( void );
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
- CreateRegisterMapIfNeeded ( void );
+ CreateRegisterMapIfNeeded();
+
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_hexagon ( void ) : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_hexagon() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABISysV_hexagon_h_
+#endif // liblldb_ABISysV_hexagon_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
index 26da9ae..0a3779a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
@@ -19,7 +19,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -59,171 +58,109 @@ using namespace lldb_private;
// Comment: Table 2.14 is followed till 'mm' entries.
// After that, all entries are ignored here.
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_eax = 0,
- gcc_dwarf_ecx,
- gcc_dwarf_edx,
- gcc_dwarf_ebx,
- gcc_dwarf_esp,
- gcc_dwarf_ebp,
- gcc_dwarf_esi,
- gcc_dwarf_edi,
- gcc_dwarf_eip,
- gcc_dwarf_eflags,
-
- gcc_dwarf_st0 = 11,
- gcc_dwarf_st1,
- gcc_dwarf_st2,
- gcc_dwarf_st3,
- gcc_dwarf_st4,
- gcc_dwarf_st5,
- gcc_dwarf_st6,
- gcc_dwarf_st7,
-
- gcc_dwarf_xmm0 = 21,
- gcc_dwarf_xmm1,
- gcc_dwarf_xmm2,
- gcc_dwarf_xmm3,
- gcc_dwarf_xmm4,
- gcc_dwarf_xmm5,
- gcc_dwarf_xmm6,
- gcc_dwarf_xmm7,
- gcc_dwarf_ymm0 = gcc_dwarf_xmm0,
- gcc_dwarf_ymm1 = gcc_dwarf_xmm1,
- gcc_dwarf_ymm2 = gcc_dwarf_xmm2,
- gcc_dwarf_ymm3 = gcc_dwarf_xmm3,
- gcc_dwarf_ymm4 = gcc_dwarf_xmm4,
- gcc_dwarf_ymm5 = gcc_dwarf_xmm5,
- gcc_dwarf_ymm6 = gcc_dwarf_xmm6,
- gcc_dwarf_ymm7 = gcc_dwarf_xmm7,
-
- gcc_dwarf_mm0 = 29,
- gcc_dwarf_mm1,
- gcc_dwarf_mm2,
- gcc_dwarf_mm3,
- gcc_dwarf_mm4,
- gcc_dwarf_mm5,
- gcc_dwarf_mm6,
- gcc_dwarf_mm7
-};
-
-
-enum gdb_regnums
-{
- gdb_eax = 0,
- gdb_ecx = 1,
- gdb_edx = 2,
- gdb_ebx = 3,
- gdb_esp = 4,
- gdb_ebp = 5,
- gdb_esi = 6,
- gdb_edi = 7,
- gdb_eip = 8,
- gdb_eflags = 9,
- gdb_cs = 10,
- gdb_ss = 11,
- gdb_ds = 12,
- gdb_es = 13,
- gdb_fs = 14,
- gdb_gs = 15,
- gdb_st0 = 16,
- gdb_st1 = 17,
- gdb_st2 = 18,
- gdb_st3 = 19,
- gdb_st4 = 20,
- gdb_st5 = 21,
- gdb_st6 = 22,
- gdb_st7 = 23,
- gdb_fctrl = 24, gdb_fcw = gdb_fctrl,
- gdb_fstat = 25, gdb_fsw = gdb_fstat,
- gdb_ftag = 26, gdb_ftw = gdb_ftag,
- gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg,
- gdb_fioff = 28, gdb_ip = gdb_fioff,
- gdb_foseg = 29, gdb_fpu_ds = gdb_foseg,
- gdb_fooff = 30, gdb_dp = gdb_fooff,
- gdb_fop = 31,
- gdb_xmm0 = 32,
- gdb_xmm1 = 33,
- gdb_xmm2 = 34,
- gdb_xmm3 = 35,
- gdb_xmm4 = 36,
- gdb_xmm5 = 37,
- gdb_xmm6 = 38,
- gdb_xmm7 = 39,
- gdb_mxcsr = 40,
- gdb_mm0 = 41,
- gdb_mm1 = 42,
- gdb_mm2 = 43,
- gdb_mm3 = 44,
- gdb_mm4 = 45,
- gdb_mm5 = 46,
- gdb_mm6 = 47,
- gdb_mm7 = 48,
- gdb_ymm0 = gdb_xmm0,
- gdb_ymm1 = gdb_xmm1,
- gdb_ymm2 = gdb_xmm2,
- gdb_ymm3 = gdb_xmm3,
- gdb_ymm4 = gdb_xmm4,
- gdb_ymm5 = gdb_xmm5,
- gdb_ymm6 = gdb_xmm6,
- gdb_ymm7 = gdb_xmm7
+ dwarf_eax = 0,
+ dwarf_ecx,
+ dwarf_edx,
+ dwarf_ebx,
+ dwarf_esp,
+ dwarf_ebp,
+ dwarf_esi,
+ dwarf_edi,
+ dwarf_eip,
+ dwarf_eflags,
+
+ dwarf_st0 = 11,
+ dwarf_st1,
+ dwarf_st2,
+ dwarf_st3,
+ dwarf_st4,
+ dwarf_st5,
+ dwarf_st6,
+ dwarf_st7,
+
+ dwarf_xmm0 = 21,
+ dwarf_xmm1,
+ dwarf_xmm2,
+ dwarf_xmm3,
+ dwarf_xmm4,
+ dwarf_xmm5,
+ dwarf_xmm6,
+ dwarf_xmm7,
+ dwarf_ymm0 = dwarf_xmm0,
+ dwarf_ymm1 = dwarf_xmm1,
+ dwarf_ymm2 = dwarf_xmm2,
+ dwarf_ymm3 = dwarf_xmm3,
+ dwarf_ymm4 = dwarf_xmm4,
+ dwarf_ymm5 = dwarf_xmm5,
+ dwarf_ymm6 = dwarf_xmm6,
+ dwarf_ymm7 = dwarf_xmm7,
+
+ dwarf_mm0 = 29,
+ dwarf_mm1,
+ dwarf_mm2,
+ dwarf_mm3,
+ dwarf_mm4,
+ dwarf_mm5,
+ dwarf_mm6,
+ dwarf_mm7
};
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== ===============
- { "eax", nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_eax , gcc_dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ebx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ebx , gcc_dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ecx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ecx , gcc_dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , gdb_ecx , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "edx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_edx , gcc_dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , gdb_edx , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "esi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_esi , gcc_dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , gdb_esi , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "edi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_edi , gcc_dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , gdb_edi , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ebp , gcc_dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_esp , gcc_dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_eip , gcc_dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "eflags", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "cs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ss" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ds" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "es" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "gs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st0" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st0 , LLDB_INVALID_REGNUM , gdb_st0 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st1" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st1 , LLDB_INVALID_REGNUM , gdb_st1 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st2" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st2 , LLDB_INVALID_REGNUM , gdb_st2 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st3" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st3 , LLDB_INVALID_REGNUM , gdb_st3 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st4" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st4 , LLDB_INVALID_REGNUM , gdb_st4 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st5" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st5 , LLDB_INVALID_REGNUM , gdb_st5 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st6" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st6 , LLDB_INVALID_REGNUM , gdb_st6 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st7" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st7 , LLDB_INVALID_REGNUM , gdb_st7 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fctrl" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fstat" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ftag" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fiseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fioff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "foseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fooff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fop" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm0" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm1" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm2" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm3" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm4" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm5" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm6" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm7" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "mxcsr" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm0" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm1" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm2" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm3" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm4" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm5" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm6" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm7" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, nullptr, nullptr}
+ { "eax", nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ebx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ecx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "edx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "esi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "edi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { dwarf_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { dwarf_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { dwarf_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "eflags", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "cs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ss" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ds" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "es" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "gs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st0" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st1" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st2" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st3" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st4" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st5" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st6" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st7" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fctrl" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fstat" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ftag" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fiseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fioff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "foseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fooff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fop" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm0" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm1" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm2" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm3" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm4" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm5" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm6" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm7" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "mxcsr" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm0" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm1" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm2" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm3" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm4" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm5" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm6" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm7" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -387,22 +324,22 @@ ABISysV_i386::GetArgumentValues (Thread &thread,
return false;
// Currently: Support for extracting values with Clang QualTypes only.
- ClangASTType clang_type (value->GetClangType());
- if (clang_type)
+ CompilerType compiler_type (value->GetCompilerType());
+ if (compiler_type)
{
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
is_signed,
thread.GetProcess().get(),
current_stack_argument);
}
- else if (clang_type.IsPointerType())
+ else if (compiler_type.IsPointerType())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
false,
thread.GetProcess().get(),
current_stack_argument);
@@ -418,29 +355,170 @@ Error
ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
{
Error error;
- //ToDo: Yet to be implemented
- error.SetErrorString("ABISysV_i386::SetReturnValueObject(): Not implemented yet");
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ const uint32_t type_flags = compiler_type.GetTypeInfo ();
+ Thread *thread = frame_sp->GetThread().get();
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ bool register_write_successful = true;
+
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+
+ // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
+ // The terminology 'Fundamental Data Types' used here is adopted from
+ // Table 2.1 of the reference document (specified on top of this file)
+
+ if (type_flags & eTypeIsPointer) // 'Pointer'
+ {
+ if(num_bytes != sizeof(uint32_t))
+ {
+ error.SetErrorString("Pointer to be returned is not 4 bytes wide");
+ return error;
+ }
+ lldb::offset_t offset = 0;
+ const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+ register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
+ }
+ else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
+ {
+ lldb::offset_t offset = 0;
+ const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
+
+ if (type_flags & eTypeIsInteger) // 'Integral' except enum
+ {
+ switch (num_bytes)
+ {
+ default:
+ break;
+ case 16:
+ // For clang::BuiltinType::UInt128 & Int128
+ // ToDo: Need to decide how to handle it
+ break;
+ case 8:
+ {
+ uint32_t raw_value_low = data.GetMaxU32(&offset, 4);
+ const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
+ uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset);
+ register_write_successful = (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value_low) &&
+ reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value_high));
+ break;
+ }
+ case 4:
+ case 2:
+ case 1:
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+ register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
+ break;
+ }
+ }
+ }
+ else if (type_flags & eTypeIsEnumeration) // handles enum
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+ register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
+ }
+ else if (type_flags & eTypeIsFloat) // 'Floating Point'
+ {
+ RegisterValue st0_value, fstat_value, ftag_value;
+ const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
+ const RegisterInfo *fstat_info = reg_ctx->GetRegisterInfoByName("fstat", 0);
+ const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0);
+
+ /* According to Page 3-12 of document
+ System V Application Binary Interface, Intel386 Architecture Processor Supplement, Fourth Edition
+ To return Floating Point values, all st% registers except st0 should be empty after exiting from
+ a function. This requires setting fstat and ftag registers to specific values.
+ fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't specify the specific
+ value of TOP in case of function return. Hence, we set the TOP field to 7 by our choice. */
+ uint32_t value_fstat_u32 = 0x00003800;
+
+ /* ftag: Implication of setting TOP to 7 and indicating all st% registers empty except st0 is to set
+ 7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to 0. This is in accordance
+ with the document Intel 64 and IA-32 Architectures Software Developer's Manual, January 2015 */
+ uint32_t value_ftag_u32 = 0x00000080;
+
+ if (num_bytes <= 12) // handles float, double, long double, __float80
+ {
+ long double value_long_dbl = 0.0;
+ if (num_bytes == 4)
+ value_long_dbl = data.GetFloat(&offset);
+ else if (num_bytes == 8)
+ value_long_dbl = data.GetDouble(&offset);
+ else if (num_bytes == 12)
+ value_long_dbl = data.GetLongDouble(&offset);
+ else
+ {
+ error.SetErrorString ("Invalid number of bytes for this return type");
+ return error;
+ }
+ st0_value.SetLongDouble(value_long_dbl);
+ fstat_value.SetUInt32(value_fstat_u32);
+ ftag_value.SetUInt32(value_ftag_u32);
+ register_write_successful = reg_ctx->WriteRegister(st0_info, st0_value) &&
+ reg_ctx->WriteRegister(fstat_info, fstat_value) &&
+ reg_ctx->WriteRegister(ftag_info, ftag_value);
+ }
+ else if(num_bytes == 16) // handles __float128
+ {
+ error.SetErrorString ("Implementation is missing for this clang type.");
+ }
+ }
+ else
+ {
+ // Neither 'Integral' nor 'Floating Point'. If flow reaches here
+ // then check type_flags. This type_flags is not a valid type.
+ error.SetErrorString ("Invalid clang type");
+ }
+ }
+ else
+ {
+ /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and 'Aggregate' data types
+ are yet to be implemented */
+ error.SetErrorString ("Currently only Integral and Floating Point clang types are supported.");
+ }
+ if(!register_write_successful)
+ error.SetErrorString ("Register writing failed");
return error;
}
ValueObjectSP
ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
- ClangASTType &return_clang_type) const
+ CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
- value.SetClangType (return_clang_type);
+ value.SetCompilerType (return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo ();
unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
@@ -463,7 +541,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
{
value.SetValueType(Value::eValueTypeScalar);
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
bool success = false;
if (type_flags & eTypeIsInteger) // 'Integral' except enum
@@ -579,7 +657,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
return_valobj_sp = ValueObjectMemory::Create (&thread,
"",
Address (storage_addr, nullptr),
- return_clang_type);
+ return_compiler_type);
}
}
@@ -597,16 +675,12 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
else if (type_flags & eTypeIsVector) // 'Packed'
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size > 0)
{
- const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0);
+ const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
if (vec_reg == nullptr)
- {
- vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
- if (vec_reg == nullptr)
- vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
- }
+ vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
if (vec_reg)
{
@@ -631,13 +705,52 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
byte_order,
process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
}
}
}
+ else if (byte_size <= vec_reg->byte_size*2)
+ {
+ const RegisterInfo *vec_reg2 = reg_ctx->GetRegisterInfoByName("xmm1", 0);
+ if (vec_reg2)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue reg_value;
+ RegisterValue reg_value2;
+ if (reg_ctx->ReadRegister(vec_reg, reg_value) && reg_ctx->ReadRegister(vec_reg2, reg_value2))
+ {
+
+ Error error;
+ if (reg_value.GetAsMemoryData (vec_reg,
+ heap_data_ap->GetBytes(),
+ vec_reg->byte_size,
+ byte_order,
+ error) &&
+ reg_value2.GetAsMemoryData (vec_reg2,
+ heap_data_ap->GetBytes() + vec_reg->byte_size,
+ heap_data_ap->GetByteSize() - vec_reg->byte_size,
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_compiler_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
}
}
}
@@ -651,15 +764,15 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
ValueObjectSP
-ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
ExecutionContext exe_ctx (thread.shared_from_this());
- return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
if (return_valobj_sp)
return return_valobj_sp;
@@ -667,14 +780,14 @@ ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cla
if (!reg_ctx_sp)
return return_valobj_sp;
- if (return_clang_type.IsAggregateType())
+ if (return_compiler_type.IsAggregateType())
{
unsigned eax_id = reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
lldb::addr_t storage_addr = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
return_valobj_sp = ValueObjectMemory::Create (&thread,
"",
Address (storage_addr, nullptr),
- return_clang_type);
+ return_compiler_type);
}
return return_valobj_sp;
@@ -690,8 +803,8 @@ ABISysV_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t sp_reg_num = gcc_dwarf_esp;
- uint32_t pc_reg_num = gcc_dwarf_eip;
+ uint32_t sp_reg_num = dwarf_esp;
+ uint32_t pc_reg_num = dwarf_eip;
UnwindPlan::RowSP row(new UnwindPlan::Row);
row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
@@ -714,9 +827,9 @@ ABISysV_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t fp_reg_num = gcc_dwarf_ebp;
- uint32_t sp_reg_num = gcc_dwarf_esp;
- uint32_t pc_reg_num = gcc_dwarf_eip;
+ uint32_t fp_reg_num = dwarf_ebp;
+ uint32_t sp_reg_num = dwarf_esp;
+ uint32_t pc_reg_num = dwarf_eip;
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 4;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.h
index 9612f90..2d0f097 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-i386/ABISysV_i386.h
@@ -21,10 +21,7 @@ class ABISysV_i386 :
public lldb_private::ABI
{
public:
-
- ~ABISysV_i386()
- {
- }
+ ~ABISysV_i386() override = default;
size_t
GetRedZoneSize () const override
@@ -46,18 +43,9 @@ public:
lldb_private::Error
SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
- lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
- bool
- RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
-
-public:
lldb::ValueObjectSP
GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const override;
+ lldb_private::CompilerType &type) const override;
bool
CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
@@ -104,9 +92,11 @@ public:
const lldb_private::RegisterInfo *
GetRegisterInfoArray (uint32_t &count) override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -119,6 +109,7 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
+
static lldb_private::ConstString
GetPluginNameStatic();
@@ -126,13 +117,25 @@ public:
GetPluginName() override;
uint32_t
- GetPluginVersion() override
+ GetPluginVersion() override
{
return 1;
}
+protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
+ bool
+ RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info);
+
private:
- ABISysV_i386() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_i386() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h
+#endif // liblldb_ABISysV_i386_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
index e1fc13a..3c7e949 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -34,133 +33,91 @@
using namespace lldb;
using namespace lldb_private;
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_r0 = 0,
- gcc_dwarf_r1,
- gcc_dwarf_r2,
- gcc_dwarf_r3,
- gcc_dwarf_r4,
- gcc_dwarf_r5,
- gcc_dwarf_r6,
- gcc_dwarf_r7,
- gcc_dwarf_r8,
- gcc_dwarf_r9,
- gcc_dwarf_r10,
- gcc_dwarf_r11,
- gcc_dwarf_r12,
- gcc_dwarf_r13,
- gcc_dwarf_r14,
- gcc_dwarf_r15,
- gcc_dwarf_r16,
- gcc_dwarf_r17,
- gcc_dwarf_r18,
- gcc_dwarf_r19,
- gcc_dwarf_r20,
- gcc_dwarf_r21,
- gcc_dwarf_r22,
- gcc_dwarf_r23,
- gcc_dwarf_r24,
- gcc_dwarf_r25,
- gcc_dwarf_r26,
- gcc_dwarf_r27,
- gcc_dwarf_r28,
- gcc_dwarf_r29,
- gcc_dwarf_r30,
- gcc_dwarf_r31,
- gcc_dwarf_sr,
- gcc_dwarf_lo,
- gcc_dwarf_hi,
- gcc_dwarf_bad,
- gcc_dwarf_cause,
- gcc_dwarf_pc
-};
-
-enum gdb_regnums
-{
- gdb_r0 = 0,
- gdb_r1,
- gdb_r2,
- gdb_r3,
- gdb_r4,
- gdb_r5,
- gdb_r6,
- gdb_r7,
- gdb_r8,
- gdb_r9,
- gdb_r10,
- gdb_r11,
- gdb_r12,
- gdb_r13,
- gdb_r14,
- gdb_r15,
- gdb_r16,
- gdb_r17,
- gdb_r18,
- gdb_r19,
- gdb_r20,
- gdb_r21,
- gdb_r22,
- gdb_r23,
- gdb_r24,
- gdb_r25,
- gdb_r26,
- gdb_r27,
- gdb_r28,
- gdb_r29,
- gdb_r30,
- gdb_r31,
- gdb_sr,
- gdb_lo,
- gdb_hi,
- gdb_bad,
- gdb_cause,
- gdb_pc
+ dwarf_r0 = 0,
+ dwarf_r1,
+ dwarf_r2,
+ dwarf_r3,
+ dwarf_r4,
+ dwarf_r5,
+ dwarf_r6,
+ dwarf_r7,
+ dwarf_r8,
+ dwarf_r9,
+ dwarf_r10,
+ dwarf_r11,
+ dwarf_r12,
+ dwarf_r13,
+ dwarf_r14,
+ dwarf_r15,
+ dwarf_r16,
+ dwarf_r17,
+ dwarf_r18,
+ dwarf_r19,
+ dwarf_r20,
+ dwarf_r21,
+ dwarf_r22,
+ dwarf_r23,
+ dwarf_r24,
+ dwarf_r25,
+ dwarf_r26,
+ dwarf_r27,
+ dwarf_r28,
+ dwarf_r29,
+ dwarf_r30,
+ dwarf_r31,
+ dwarf_sr,
+ dwarf_lo,
+ dwarf_hi,
+ dwarf_bad,
+ dwarf_cause,
+ dwarf_pc
};
static const RegisterInfo
g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
- // ======== ====== == === ============= =================== ============ ===================== ==================== ================= ====================== ========== ===============
- { "r0" , "zero", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r1" , "AT", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r1, gcc_dwarf_r1, LLDB_INVALID_REGNUM, gdb_r1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r2" , "v0", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r3" , "v1", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r3, gcc_dwarf_r3, LLDB_INVALID_REGNUM, gdb_r3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r4" , "arg1", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, gdb_r4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r5" , "arg2", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, gdb_r5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r6" , "arg3", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, gdb_r6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r7" , "arg4", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, gdb_r7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r8" , "arg5", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r8, gcc_dwarf_r8, LLDB_INVALID_REGNUM, gdb_r8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r9" , "arg6", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r9, gcc_dwarf_r9, LLDB_INVALID_REGNUM, gdb_r9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r10" , "arg7", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r10, gcc_dwarf_r10, LLDB_INVALID_REGNUM, gdb_r10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r11" , "arg8", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r12" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r13" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r14" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r15" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r16" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r17" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r18" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r19" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r20" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r21" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r22" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r23" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r24" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r25" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r26" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r27" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r28" , "gp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r29" , "sp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r29, gcc_dwarf_r29, LLDB_REGNUM_GENERIC_SP, gdb_r29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r30" , "fp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r30, gcc_dwarf_r30, LLDB_REGNUM_GENERIC_FP, gdb_r30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r31" , "ra", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r31, gcc_dwarf_r31, LLDB_REGNUM_GENERIC_RA, gdb_r31, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_sr, gcc_dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, gdb_sr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "lo" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_lo, gcc_dwarf_lo, LLDB_INVALID_REGNUM, gdb_lo, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "hi" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_hi, gcc_dwarf_hi, LLDB_INVALID_REGNUM, gdb_hi, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "bad" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_bad, gcc_dwarf_bad, LLDB_INVALID_REGNUM, gdb_bad, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cause" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cause, gcc_dwarf_cause, LLDB_INVALID_REGNUM, gdb_cause, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "pc" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_pc, LLDB_INVALID_REGNUM }, NULL, NULL},
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGINS LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // ======== ====== == === ============= =========== ============ ============== ============ ================= =================== ========== =================
+ { "r0" , "zero", 4, 0, eEncodingUint, eFormatHex, { dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r1" , "AT", 4, 0, eEncodingUint, eFormatHex, { dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r2" , "v0", 4, 0, eEncodingUint, eFormatHex, { dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r3" , "v1", 4, 0, eEncodingUint, eFormatHex, { dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r4" , "arg1", 4, 0, eEncodingUint, eFormatHex, { dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r5" , "arg2", 4, 0, eEncodingUint, eFormatHex, { dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r6" , "arg3", 4, 0, eEncodingUint, eFormatHex, { dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r7" , "arg4", 4, 0, eEncodingUint, eFormatHex, { dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8" , "arg5", 4, 0, eEncodingUint, eFormatHex, { dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9" , "arg6", 4, 0, eEncodingUint, eFormatHex, { dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10" , "arg7", 4, 0, eEncodingUint, eFormatHex, { dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11" , "arg8", 4, 0, eEncodingUint, eFormatHex, { dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r15" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r16" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r17" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r18" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r19" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r20" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r21" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r22" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r23" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r24" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r25" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r26" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r27" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r28" , "gp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r29" , "sp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r30" , "fp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r31" , "ra", 4, 0, eEncodingUint, eFormatHex, { dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "lo" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "hi" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "bad" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cause" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "pc" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -284,6 +241,7 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread,
const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+ const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
if (log)
log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
@@ -305,7 +263,14 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread,
// Set pc to the address of the called function.
if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
return false;
-
+
+ if (log)
+ log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
+
+ // All callers of position independent functions must place the address of the called function in t9 (r25)
+ if (!reg_ctx->WriteRegisterFromUnsigned (r25_info, func_addr))
+ return false;
+
return true;
}
@@ -325,8 +290,8 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -341,7 +306,7 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
DataExtractor data;
Error data_error;
@@ -382,7 +347,7 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje
error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
@@ -398,40 +363,41 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje
ValueObjectSP
-ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
}
ValueObjectSP
-ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
ExecutionContext exe_ctx (thread.shared_from_this());
if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
return return_valobj_sp;
- value.SetClangType(return_clang_type);
+ value.SetCompilerType(return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- bool is_signed;
+ bool is_signed = false;
+ bool is_complex = false;
+ uint32_t count = 0;
// In MIPS register "r2" (v0) holds the integer function return values
const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+ size_t bit_width = return_compiler_type.GetBitSize(&thread);
- if (return_clang_type.IsIntegerType (is_signed))
+ if (return_compiler_type.IsIntegerType (is_signed))
{
- size_t bit_width = return_clang_type.GetBitSize(&thread);
-
switch (bit_width)
{
default:
@@ -468,11 +434,57 @@ ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cla
break;
}
}
- else if (return_clang_type.IsPointerType ())
+ else if (return_compiler_type.IsPointerType ())
{
uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
value.GetScalar() = ptr;
}
+ else if (return_compiler_type.IsAggregateType ())
+ {
+ // Structure/Vector is always passed in memory and pointer to that memory is passed in r2.
+ uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
+ // We have got the address. Create a memory object out of it
+ return_valobj_sp = ValueObjectMemory::Create (&thread,
+ "",
+ Address (mem_address, NULL),
+ return_compiler_type);
+ return return_valobj_sp;
+ }
+ else if (return_compiler_type.IsFloatingPointType (count, is_complex))
+ {
+ const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
+ const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
+
+ if (count == 1 && !is_complex)
+ {
+ switch (bit_width)
+ {
+ default:
+ return return_valobj_sp;
+ case 64:
+ {
+ static_assert(sizeof(double) == sizeof(uint64_t), "");
+ uint64_t raw_value;
+ raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX;
+ raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(f1_info, 0) & UINT32_MAX)) << 32;
+ value.GetScalar() = *reinterpret_cast<double*>(&raw_value);
+ break;
+ }
+ case 32:
+ {
+ static_assert(sizeof(float) == sizeof(uint32_t), "");
+ uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX;
+ value.GetScalar() = *reinterpret_cast<float*>(&raw_value);
+ break;
+ }
+ }
+ }
+ else
+ {
+ // not handled yet
+ return return_valobj_sp;
+ }
+ }
else
{
// not handled yet
@@ -496,17 +508,17 @@ ABISysV_mips::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
// The previous PC is in the RA
- row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+ row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
unwind_plan.AppendRow (row);
// All other registers are the same.
unwind_plan.SetSourceName ("mips at-func-entry default");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
- unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31);
+ unwind_plan.SetReturnAddressRegister(dwarf_r31);
return true;
}
@@ -518,9 +530,9 @@ ABISysV_mips::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
- row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+ row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("mips default unwind plan");
@@ -542,13 +554,36 @@ ABISysV_mips::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
{
// Preserved registers are :
// r16-r23, r28, r29, r30, r31
+ const char *name = reg_info->name;
- int reg = ((reg_info->byte_offset) / 4);
-
- bool save = (reg >= 16) && (reg <= 23);
- save |= (reg >= 28) && (reg <= 31);
+ if (name[0] == 'r')
+ {
+ switch (name[1])
+ {
+ case '1':
+ if (name[2] == '6' || name[2] == '7' || name[2] == '8' || name[2] == '9') // r16-r19
+ return name[3] == '\0';
+ break;
+ case '2':
+ if (name[2] == '0' || name[2] == '1' || name[2] == '2' || name[2] == '3' // r20-r23
+ || name[2] == '8' || name[2] == '9') // r28 and r29
+ return name[3] == '\0';
+ break;
+ case '3':
+ if (name[2] == '0' || name[2] == '1') // r30 and r31
+ return name[3] == '\0';
+ break;
+ }
- return save;
+ if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
+ return true;
+ if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
+ return true;
+ if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
+ return true;
+ if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
+ return true;
+ }
}
return false;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.h
index ad47ac2..709c3bf 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips/ABISysV_mips.h
@@ -21,49 +21,40 @@ class ABISysV_mips :
public lldb_private::ABI
{
public:
+ ~ABISysV_mips() override = default;
- ~ABISysV_mips()
- {
- }
-
- virtual size_t
- GetRedZoneSize () const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -73,21 +64,21 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)//must- check
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
- if (pc & (4ull - 1ull))
- return false; // Not 4 byte aligned
-
- // Anything else if fair game..
- return true;
+ // Just make sure the address is a valid 32 bit address. Bit zero
+ // might be set due to MicroMIPS function calls, so don't enforce alignment.
+ return (pc <= UINT32_MAX);
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -103,21 +94,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
CreateRegisterMapIfNeeded ();
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_mips() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_mips() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABISysV_mips_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
index c790fa7..e3da363 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -34,133 +33,91 @@
using namespace lldb;
using namespace lldb_private;
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_r0 = 0,
- gcc_dwarf_r1,
- gcc_dwarf_r2,
- gcc_dwarf_r3,
- gcc_dwarf_r4,
- gcc_dwarf_r5,
- gcc_dwarf_r6,
- gcc_dwarf_r7,
- gcc_dwarf_r8,
- gcc_dwarf_r9,
- gcc_dwarf_r10,
- gcc_dwarf_r11,
- gcc_dwarf_r12,
- gcc_dwarf_r13,
- gcc_dwarf_r14,
- gcc_dwarf_r15,
- gcc_dwarf_r16,
- gcc_dwarf_r17,
- gcc_dwarf_r18,
- gcc_dwarf_r19,
- gcc_dwarf_r20,
- gcc_dwarf_r21,
- gcc_dwarf_r22,
- gcc_dwarf_r23,
- gcc_dwarf_r24,
- gcc_dwarf_r25,
- gcc_dwarf_r26,
- gcc_dwarf_r27,
- gcc_dwarf_r28,
- gcc_dwarf_r29,
- gcc_dwarf_r30,
- gcc_dwarf_r31,
- gcc_dwarf_sr,
- gcc_dwarf_lo,
- gcc_dwarf_hi,
- gcc_dwarf_bad,
- gcc_dwarf_cause,
- gcc_dwarf_pc
-};
-
-enum gdb_regnums
-{
- gdb_r0 = 0,
- gdb_r1,
- gdb_r2,
- gdb_r3,
- gdb_r4,
- gdb_r5,
- gdb_r6,
- gdb_r7,
- gdb_r8,
- gdb_r9,
- gdb_r10,
- gdb_r11,
- gdb_r12,
- gdb_r13,
- gdb_r14,
- gdb_r15,
- gdb_r16,
- gdb_r17,
- gdb_r18,
- gdb_r19,
- gdb_r20,
- gdb_r21,
- gdb_r22,
- gdb_r23,
- gdb_r24,
- gdb_r25,
- gdb_r26,
- gdb_r27,
- gdb_r28,
- gdb_r29,
- gdb_r30,
- gdb_r31,
- gdb_sr,
- gdb_lo,
- gdb_hi,
- gdb_bad,
- gdb_cause,
- gdb_pc
+ dwarf_r0 = 0,
+ dwarf_r1,
+ dwarf_r2,
+ dwarf_r3,
+ dwarf_r4,
+ dwarf_r5,
+ dwarf_r6,
+ dwarf_r7,
+ dwarf_r8,
+ dwarf_r9,
+ dwarf_r10,
+ dwarf_r11,
+ dwarf_r12,
+ dwarf_r13,
+ dwarf_r14,
+ dwarf_r15,
+ dwarf_r16,
+ dwarf_r17,
+ dwarf_r18,
+ dwarf_r19,
+ dwarf_r20,
+ dwarf_r21,
+ dwarf_r22,
+ dwarf_r23,
+ dwarf_r24,
+ dwarf_r25,
+ dwarf_r26,
+ dwarf_r27,
+ dwarf_r28,
+ dwarf_r29,
+ dwarf_r30,
+ dwarf_r31,
+ dwarf_sr,
+ dwarf_lo,
+ dwarf_hi,
+ dwarf_bad,
+ dwarf_cause,
+ dwarf_pc
};
static const RegisterInfo
g_register_infos_mips64[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
- // ======== ====== == === ============= =================== ============ ===================== ==================== ================= ====================== ========== ===============
- { "r0" , "zero", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r1" , "AT", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r1, gcc_dwarf_r1, LLDB_INVALID_REGNUM, gdb_r1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r2" , "v0", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r3" , "v1", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r3, gcc_dwarf_r3, LLDB_INVALID_REGNUM, gdb_r3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r4" , "arg1", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, gdb_r4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r5" , "arg2", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, gdb_r5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r6" , "arg3", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, gdb_r6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r7" , "arg4", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, gdb_r7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r8" , "arg5", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, gdb_r8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r9" , "arg6", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, gdb_r9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r10" , "arg7", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, gdb_r10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r11" , "arg8", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r11, gcc_dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, gdb_r11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r12" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r13" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r14" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r15" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r16" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r17" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r18" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r19" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r20" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r21" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r22" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r23" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r24" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r25" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r26" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r27" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r28" , "gp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r29" , "sp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r29, gcc_dwarf_r29, LLDB_REGNUM_GENERIC_SP, gdb_r29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r30" , "fp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r30, gcc_dwarf_r30, LLDB_REGNUM_GENERIC_FP, gdb_r30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r31" , "ra", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r31, gcc_dwarf_r31, LLDB_REGNUM_GENERIC_RA, gdb_r31, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_sr, gcc_dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, gdb_sr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "lo" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_lo, gcc_dwarf_lo, LLDB_INVALID_REGNUM, gdb_lo, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "hi" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_hi, gcc_dwarf_hi, LLDB_INVALID_REGNUM, gdb_hi, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "bad" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_bad, gcc_dwarf_bad, LLDB_INVALID_REGNUM, gdb_bad, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cause" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cause, gcc_dwarf_cause, LLDB_INVALID_REGNUM, gdb_cause, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "pc" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_pc, LLDB_INVALID_REGNUM }, NULL, NULL},
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // ======== ====== == === ============= ========== ============= ================= ==================== ================= ==================== ========== ===============
+ { "r0" , "zero", 8, 0, eEncodingUint, eFormatHex, { dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r1" , "AT", 8, 0, eEncodingUint, eFormatHex, { dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r2" , "v0", 8, 0, eEncodingUint, eFormatHex, { dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r3" , "v1", 8, 0, eEncodingUint, eFormatHex, { dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r4" , "arg1", 8, 0, eEncodingUint, eFormatHex, { dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r5" , "arg2", 8, 0, eEncodingUint, eFormatHex, { dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r6" , "arg3", 8, 0, eEncodingUint, eFormatHex, { dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r7" , "arg4", 8, 0, eEncodingUint, eFormatHex, { dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8" , "arg5", 8, 0, eEncodingUint, eFormatHex, { dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9" , "arg6", 8, 0, eEncodingUint, eFormatHex, { dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10" , "arg7", 8, 0, eEncodingUint, eFormatHex, { dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11" , "arg8", 8, 0, eEncodingUint, eFormatHex, { dwarf_r11, dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r15" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r16" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r17" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r18" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r19" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r20" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r21" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r22" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r23" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r24" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r25" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r26" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r27" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r28" , "gp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r29" , "sp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r30" , "fp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r31" , "ra", 8, 0, eEncodingUint, eFormatHex, { dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "lo" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "hi" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "bad" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cause" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "pc" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos_mips64);
@@ -249,6 +206,7 @@ ABISysV_mips64::PrepareTrivialCall (Thread &thread,
const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+ const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
if (log)
log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
@@ -271,6 +229,13 @@ ABISysV_mips64::PrepareTrivialCall (Thread &thread,
if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
return false;
+ if (log)
+ log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
+
+ // All callers of position independent functions must place the address of the called function in t9 (r25)
+ if (!reg_ctx->WriteRegisterFromUnsigned (r25_info, func_addr))
+ return false;
+
return true;
}
@@ -290,8 +255,8 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -313,7 +278,7 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
return error;
}
- const uint32_t type_flags = clang_type.GetTypeInfo (NULL);
+ const uint32_t type_flags = compiler_type.GetTypeInfo (NULL);
if (type_flags & eTypeIsScalar ||
type_flags & eTypeIsPointer)
@@ -368,42 +333,50 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
ValueObjectSP
-ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
}
ValueObjectSP
-ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
-
+ Error error;
+
ExecutionContext exe_ctx (thread.shared_from_this());
if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
return return_valobj_sp;
- value.SetClangType(return_clang_type);
+ value.SetCompilerType(return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
- const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL);
+ Target *target = exe_ctx.GetTargetPtr();
+ ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL);
+
+ const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+ const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
- if (type_flags & eTypeIsScalar)
+ if (type_flags & eTypeIsScalar ||
+ type_flags & eTypeIsPointer)
{
value.SetValueType(Value::eValueTypeScalar);
bool success = false;
- if (type_flags & eTypeIsInteger)
+ if (type_flags & eTypeIsInteger ||
+ type_flags & eTypeIsPointer)
{
// Extract the register context so we can read arguments from registers
// In MIPS register "r2" (v0) holds the integer function return values
- uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
+ uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
switch (byte_size)
@@ -444,25 +417,302 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
break;
}
}
+ else if (type_flags & eTypeIsFloat)
+ {
+ if (type_flags & eTypeIsComplex)
+ {
+ // Don't handle complex yet.
+ }
+ else
+ {
+ if (byte_size <= sizeof(long double))
+ {
+ const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
+ const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0);
+ RegisterValue f0_value, f2_value;
+ DataExtractor f0_data, f2_data;
+
+ reg_ctx->ReadRegister (f0_info, f0_value);
+ reg_ctx->ReadRegister (f2_info, f2_value);
+
+ f0_value.GetData(f0_data);
+ f2_value.GetData(f2_data);
+
+ lldb::offset_t offset = 0;
+ if (byte_size == sizeof(float))
+ {
+ value.GetScalar() = (float) f0_data.GetFloat(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(double))
+ {
+ value.GetScalar() = (double) f0_data.GetDouble(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(long double))
+ {
+ DataExtractor *copy_from_extractor = NULL;
+ DataBufferSP data_sp (new DataBufferHeap(16, 0));
+ DataExtractor return_ext (data_sp,
+ target_byte_order,
+ target->GetArchitecture().GetAddressByteSize());
+
+ if (target_byte_order == eByteOrderLittle)
+ {
+ f0_data.Append(f2_data);
+ copy_from_extractor = &f0_data;
+ }
+ else
+ {
+ f2_data.Append(f0_data);
+ copy_from_extractor = &f2_data;
+ }
+
+ copy_from_extractor->CopyByteOrderedData (0,
+ byte_size,
+ data_sp->GetBytes(),
+ byte_size,
+ target_byte_order);
+
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_compiler_type,
+ ConstString(""),
+ return_ext);
+ return return_valobj_sp;
+
+ }
+ }
+ }
+ }
if (success)
return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
value,
ConstString(""));
}
- else if (type_flags & eTypeIsPointer)
+ else if (type_flags & eTypeIsStructUnion ||
+ type_flags & eTypeIsClass ||
+ type_flags & eTypeIsVector)
{
- value.SetValueType(Value::eValueTypeScalar);
- uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
- value.GetScalar() = (uint64_t)(raw_value);
+ // Any structure of up to 16 bytes in size is returned in the registers.
+ if (byte_size <= 16)
+ {
+ DataBufferSP data_sp (new DataBufferHeap(16, 0));
+ DataExtractor return_ext (data_sp,
+ target_byte_order,
+ target->GetArchitecture().GetAddressByteSize());
+
+ RegisterValue r2_value, r3_value, f0_value, f1_value, f2_value;
+
+ uint32_t integer_bytes = 0; // Tracks how much bytes of r2 and r3 registers we've consumed so far
+ bool use_fp_regs = 0; // True if return values are in FP return registers.
+ bool found_non_fp_field = 0; // True if we found any non floating point field in structure.
+ bool use_r2 = 0; // True if return values are in r2 register.
+ bool use_r3 = 0; // True if return values are in r3 register.
+ bool sucess = 0; // True if the result is copied into our data buffer
+ std::string name;
+ bool is_complex;
+ uint32_t count;
+ const uint32_t num_children = return_compiler_type.GetNumFields ();
+
+ // A structure consisting of one or two FP values (and nothing else) will be
+ // returned in the two FP return-value registers i.e fp0 and fp2.
+ if (num_children <= 2)
+ {
+ uint64_t field_bit_offset = 0;
- return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
- value,
- ConstString(""));
- }
- else if (type_flags & eTypeIsVector)
- {
- // TODO: Handle vector types
+ // Check if this structure contains only floating point fields
+ for (uint32_t idx = 0; idx < num_children; idx++)
+ {
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+
+ if (field_compiler_type.IsFloatingPointType (count, is_complex))
+ use_fp_regs = 1;
+ else
+ found_non_fp_field = 1;
+ }
+
+ if (use_fp_regs && !found_non_fp_field)
+ {
+ // We have one or two FP-only values in this structure. Get it from f0/f2 registers.
+ DataExtractor f0_data, f1_data, f2_data;
+ const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
+ const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
+ const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0);
+
+ reg_ctx->ReadRegister (f0_info, f0_value);
+ reg_ctx->ReadRegister (f2_info, f2_value);
+
+ f0_value.GetData(f0_data);
+ f2_value.GetData(f2_data);
+
+ for (uint32_t idx = 0; idx < num_children; idx++)
+ {
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_byte_width = field_compiler_type.GetByteSize(nullptr);
+
+ DataExtractor *copy_from_extractor = NULL;
+
+ if (idx == 0)
+ {
+ if (field_byte_width == 16) // This case is for long double type.
+ {
+ // If structure contains long double type, then it is returned in fp0/fp1 registers.
+ reg_ctx->ReadRegister (f1_info, f1_value);
+ f1_value.GetData(f1_data);
+
+ if (target_byte_order == eByteOrderLittle)
+ {
+ f0_data.Append(f1_data);
+ copy_from_extractor = &f0_data;
+ }
+ else
+ {
+ f1_data.Append(f0_data);
+ copy_from_extractor = &f1_data;
+ }
+ }
+ else
+ copy_from_extractor = &f0_data; // This is in f0, copy from register to our result structure
+ }
+ else
+ copy_from_extractor = &f2_data; // This is in f2, copy from register to our result structure
+
+ // Sanity check to avoid crash
+ if (!copy_from_extractor || field_byte_width > copy_from_extractor->GetByteSize())
+ return return_valobj_sp;
+
+ // copy the register contents into our data buffer
+ copy_from_extractor->CopyByteOrderedData (0,
+ field_byte_width,
+ data_sp->GetBytes() + (field_bit_offset/8),
+ field_byte_width,
+ target_byte_order);
+ }
+
+ // The result is in our data buffer. Create a variable object out of it
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_compiler_type,
+ ConstString(""),
+ return_ext);
+
+ return return_valobj_sp;
+ }
+ }
+
+ // If we reach here, it means this structure either contains more than two fields or
+ // it contains at least one non floating point type.
+ // In that case, all fields are returned in GP return registers.
+ for (uint32_t idx = 0; idx < num_children; idx++)
+ {
+ uint64_t field_bit_offset = 0;
+ bool is_signed;
+ uint32_t padding;
+
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_byte_width = field_compiler_type.GetByteSize(nullptr);
+
+ // if we don't know the size of the field (e.g. invalid type), just bail out
+ if (field_byte_width == 0)
+ break;
+
+ uint32_t field_byte_offset = field_bit_offset/8;
+
+ if (field_compiler_type.IsIntegerType (is_signed)
+ || field_compiler_type.IsPointerType ()
+ || field_compiler_type.IsFloatingPointType (count, is_complex))
+ {
+ padding = field_byte_offset - integer_bytes;
+
+ if (integer_bytes < 8)
+ {
+ // We have not yet consumed r2 completely.
+ if (integer_bytes + field_byte_width + padding <= 8)
+ {
+ // This field fits in r2, copy its value from r2 to our result structure
+ integer_bytes = integer_bytes + field_byte_width + padding; // Increase the consumed bytes.
+ use_r2 = 1;
+ }
+ else
+ {
+ // There isn't enough space left in r2 for this field, so this will be in r3.
+ integer_bytes = integer_bytes + field_byte_width + padding; // Increase the consumed bytes.
+ use_r3 = 1;
+ }
+ }
+ // We already have consumed at-least 8 bytes that means r2 is done, and this field will be in r3.
+ // Check if this field can fit in r3.
+ else if (integer_bytes + field_byte_width + padding <= 16)
+ {
+ integer_bytes = integer_bytes + field_byte_width + padding;
+ use_r3 = 1;
+ }
+ else
+ {
+ // There isn't any space left for this field, this should not happen as we have already checked
+ // the overall size is not greater than 16 bytes. For now, return a NULL return value object.
+ return return_valobj_sp;
+ }
+ }
+ }
+ // Vector types upto 16 bytes are returned in GP return registers
+ if (type_flags & eTypeIsVector)
+ {
+ if (byte_size <= 8)
+ use_r2 = 1;
+ else
+ {
+ use_r2 = 1;
+ use_r3 = 1;
+ }
+ }
+
+ if (use_r2)
+ {
+ reg_ctx->ReadRegister (r2_info, r2_value);
+
+ const size_t bytes_copied = r2_value.GetAsMemoryData (r2_info,
+ data_sp->GetBytes(),
+ r2_info->byte_size,
+ target_byte_order,
+ error);
+ if (bytes_copied != r2_info->byte_size)
+ return return_valobj_sp;
+ sucess = 1;
+ }
+ if (use_r3)
+ {
+ reg_ctx->ReadRegister (r3_info, r3_value);
+ const size_t bytes_copied = r3_value.GetAsMemoryData (r3_info,
+ data_sp->GetBytes() + r2_info->byte_size,
+ r3_info->byte_size,
+ target_byte_order,
+ error);
+
+ if (bytes_copied != r3_info->byte_size)
+ return return_valobj_sp;
+ sucess = 1;
+ }
+ if (sucess)
+ {
+ // The result is in our data buffer. Create a variable object out of it
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_compiler_type,
+ ConstString(""),
+ return_ext);
+ }
+ return return_valobj_sp;
+ }
+
+ // Any structure/vector greater than 16 bytes in size is returned in memory.
+ // The pointer to that memory is returned in r2.
+ uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
+
+ // We have got the address. Create a memory object out of it
+ return_valobj_sp = ValueObjectMemory::Create (&thread,
+ "",
+ Address (mem_address, NULL),
+ return_compiler_type);
}
return return_valobj_sp;
}
@@ -476,17 +726,17 @@ ABISysV_mips64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
// The previous PC is in the RA
- row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+ row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
unwind_plan.AppendRow (row);
// All other registers are the same.
unwind_plan.SetSourceName ("mips64 at-func-entry default");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
- unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31);
+ unwind_plan.SetReturnAddressRegister(dwarf_r31);
return true;
}
@@ -498,9 +748,9 @@ ABISysV_mips64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
- row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+ row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("mips64 default unwind plan");
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h
index c37e717..3290331 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h
@@ -21,46 +21,37 @@ class ABISysV_mips64 :
public lldb_private::ABI
{
public:
+ ~ABISysV_mips64() override = default;
- ~ABISysV_mips64()
- {
- }
-
- virtual size_t
- GetRedZoneSize () const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The SysV mips ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -72,8 +63,8 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -83,8 +74,8 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
if (pc & (4ull - 1ull))
return false; // Not 4 byte aligned
@@ -93,11 +84,13 @@ public:
return true;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -113,21 +106,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
CreateRegisterMapIfNeeded ();
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_mips64() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_mips64() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABISysV_mips64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
index 08416dc..f0da186 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -34,123 +33,81 @@
using namespace lldb;
using namespace lldb_private;
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_r0 = 0,
- gcc_dwarf_r1,
- gcc_dwarf_r2,
- gcc_dwarf_r3,
- gcc_dwarf_r4,
- gcc_dwarf_r5,
- gcc_dwarf_r6,
- gcc_dwarf_r7,
- gcc_dwarf_r8,
- gcc_dwarf_r9,
- gcc_dwarf_r10,
- gcc_dwarf_r11,
- gcc_dwarf_r12,
- gcc_dwarf_r13,
- gcc_dwarf_r14,
- gcc_dwarf_r15,
- gcc_dwarf_r16,
- gcc_dwarf_r17,
- gcc_dwarf_r18,
- gcc_dwarf_r19,
- gcc_dwarf_r20,
- gcc_dwarf_r21,
- gcc_dwarf_r22,
- gcc_dwarf_r23,
- gcc_dwarf_r24,
- gcc_dwarf_r25,
- gcc_dwarf_r26,
- gcc_dwarf_r27,
- gcc_dwarf_r28,
- gcc_dwarf_r29,
- gcc_dwarf_r30,
- gcc_dwarf_r31,
- gcc_dwarf_f0,
- gcc_dwarf_f1,
- gcc_dwarf_f2,
- gcc_dwarf_f3,
- gcc_dwarf_f4,
- gcc_dwarf_f5,
- gcc_dwarf_f6,
- gcc_dwarf_f7,
- gcc_dwarf_f8,
- gcc_dwarf_f9,
- gcc_dwarf_f10,
- gcc_dwarf_f11,
- gcc_dwarf_f12,
- gcc_dwarf_f13,
- gcc_dwarf_f14,
- gcc_dwarf_f15,
- gcc_dwarf_f16,
- gcc_dwarf_f17,
- gcc_dwarf_f18,
- gcc_dwarf_f19,
- gcc_dwarf_f20,
- gcc_dwarf_f21,
- gcc_dwarf_f22,
- gcc_dwarf_f23,
- gcc_dwarf_f24,
- gcc_dwarf_f25,
- gcc_dwarf_f26,
- gcc_dwarf_f27,
- gcc_dwarf_f28,
- gcc_dwarf_f29,
- gcc_dwarf_f30,
- gcc_dwarf_f31,
- gcc_dwarf_cr,
- gcc_dwarf_fpscr,
- gcc_dwarf_xer = 101,
- gcc_dwarf_lr = 108,
- gcc_dwarf_ctr,
- gcc_dwarf_pc,
- gcc_dwarf_cfa,
+ dwarf_r0 = 0,
+ dwarf_r1,
+ dwarf_r2,
+ dwarf_r3,
+ dwarf_r4,
+ dwarf_r5,
+ dwarf_r6,
+ dwarf_r7,
+ dwarf_r8,
+ dwarf_r9,
+ dwarf_r10,
+ dwarf_r11,
+ dwarf_r12,
+ dwarf_r13,
+ dwarf_r14,
+ dwarf_r15,
+ dwarf_r16,
+ dwarf_r17,
+ dwarf_r18,
+ dwarf_r19,
+ dwarf_r20,
+ dwarf_r21,
+ dwarf_r22,
+ dwarf_r23,
+ dwarf_r24,
+ dwarf_r25,
+ dwarf_r26,
+ dwarf_r27,
+ dwarf_r28,
+ dwarf_r29,
+ dwarf_r30,
+ dwarf_r31,
+ dwarf_f0,
+ dwarf_f1,
+ dwarf_f2,
+ dwarf_f3,
+ dwarf_f4,
+ dwarf_f5,
+ dwarf_f6,
+ dwarf_f7,
+ dwarf_f8,
+ dwarf_f9,
+ dwarf_f10,
+ dwarf_f11,
+ dwarf_f12,
+ dwarf_f13,
+ dwarf_f14,
+ dwarf_f15,
+ dwarf_f16,
+ dwarf_f17,
+ dwarf_f18,
+ dwarf_f19,
+ dwarf_f20,
+ dwarf_f21,
+ dwarf_f22,
+ dwarf_f23,
+ dwarf_f24,
+ dwarf_f25,
+ dwarf_f26,
+ dwarf_f27,
+ dwarf_f28,
+ dwarf_f29,
+ dwarf_f30,
+ dwarf_f31,
+ dwarf_cr,
+ dwarf_fpscr,
+ dwarf_xer = 101,
+ dwarf_lr = 108,
+ dwarf_ctr,
+ dwarf_pc,
+ dwarf_cfa,
};
-enum gdb_regnums
-{
- gdb_r0 = 0,
- gdb_r1,
- gdb_r2,
- gdb_r3,
- gdb_r4,
- gdb_r5,
- gdb_r6,
- gdb_r7,
- gdb_r8,
- gdb_r9,
- gdb_r10,
- gdb_r11,
- gdb_r12,
- gdb_r13,
- gdb_r14,
- gdb_r15,
- gdb_r16,
- gdb_r17,
- gdb_r18,
- gdb_r19,
- gdb_r20,
- gdb_r21,
- gdb_r22,
- gdb_r23,
- gdb_r24,
- gdb_r25,
- gdb_r26,
- gdb_r27,
- gdb_r28,
- gdb_r29,
- gdb_r30,
- gdb_r31,
- gdb_lr,
- gdb_cr,
- gdb_xer,
- gdb_ctr,
- gdb_pc,
-};
-
-
// Note that the size and offset will be updated by platform-specific classes.
#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
{ #reg, alt, 8, 0, eEncodingUint, \
@@ -158,45 +115,45 @@ enum gdb_regnums
static const RegisterInfo
g_register_infos[] =
{
- // General purpose registers. GCC, DWARF, Generic, GDB
- DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0),
- DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1),
- DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2),
- DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3),
- DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4),
- DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5),
- DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6),
- DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7),
- DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8),
- DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9),
- DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10),
- DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11),
- DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12),
- DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13),
- DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14),
- DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15),
- DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16),
- DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17),
- DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18),
- DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19),
- DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20),
- DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21),
- DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22),
- DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23),
- DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24),
- DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25),
- DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26),
- DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27),
- DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28),
- DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29),
- DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30),
- DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31),
- DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr),
- DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
- DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
- { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
+ // General purpose registers. eh_frame, DWARF, Generic, Process Plugin
+ DEFINE_GPR(r0, NULL, dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r1, "sp", dwarf_r1, dwarf_r1, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r2, NULL, dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r3, "arg1",dwarf_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r4, "arg2",dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r5, "arg3",dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r6, "arg4",dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r7, "arg5",dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r8, "arg6",dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r9, "arg7",dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r10, "arg8",dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r11, NULL, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r12, NULL, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r13, NULL, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r14, NULL, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r15, NULL, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r16, NULL, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r17, NULL, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r18, NULL, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r19, NULL, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r20, NULL, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r21, NULL, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r22, NULL, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r23, NULL, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r24, NULL, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r25, NULL, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r26, NULL, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r27, NULL, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r28, NULL, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r29, NULL, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r30, NULL, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r31, NULL, dwarf_r31, dwarf_r31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(lr, "lr", dwarf_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cr, "cr", dwarf_cr, dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(xer, "xer", dwarf_xer, dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ctr, "ctr", dwarf_ctr, dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -436,25 +393,25 @@ ABISysV_ppc::GetArgumentValues (Thread &thread,
// We currently only support extracting values with Clang QualTypes.
// Do we care about others?
- ClangASTType clang_type = value->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = value->GetCompilerType();
+ if (!compiler_type)
return false;
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
is_signed,
thread,
argument_register_ids,
current_argument_register,
current_stack_argument);
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
false,
thread,
argument_register_ids,
@@ -476,8 +433,8 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -492,7 +449,7 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
@@ -518,13 +475,13 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
else
{
- size_t bit_width = clang_type.GetBitSize(frame_sp.get());
+ size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
if (bit_width <= 64)
{
DataExtractor data;
@@ -563,22 +520,22 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
ValueObjectSP
ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
- ClangASTType &return_clang_type) const
+ CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
//value.SetContext (Value::eContextTypeClangType, return_value_type);
- value.SetClangType (return_clang_type);
+ value.SetCompilerType (return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo ();
if (type_flags & eTypeIsScalar)
{
value.SetValueType(Value::eValueTypeScalar);
@@ -588,7 +545,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
{
// Extract the register context so we can read arguments from registers
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
switch (byte_size)
@@ -637,7 +594,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
}
else
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size <= sizeof(long double))
{
const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
@@ -681,7 +638,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
}
else if (type_flags & eTypeIsVector)
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size > 0)
{
@@ -709,7 +666,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
byte_order,
process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
@@ -724,15 +681,15 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
}
ValueObjectSP
-ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
ExecutionContext exe_ctx (thread.shared_from_this());
- return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
if (return_valobj_sp)
return return_valobj_sp;
@@ -740,8 +697,8 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
if (!reg_ctx_sp)
return return_valobj_sp;
- const size_t bit_width = return_clang_type.GetBitSize(&thread);
- if (return_clang_type.IsAggregateType())
+ const size_t bit_width = return_compiler_type.GetBitSize(&thread);
+ if (return_compiler_type.IsAggregateType())
{
Target *target = exe_ctx.GetTargetPtr();
bool is_memory = true;
@@ -768,7 +725,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far
uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far
- const uint32_t num_children = return_clang_type.GetNumFields ();
+ const uint32_t num_children = return_compiler_type.GetNumFields ();
// Since we are in the small struct regime, assume we are not in memory.
is_memory = false;
@@ -781,8 +738,8 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
bool is_complex;
uint32_t count;
- ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
- const size_t field_bit_width = field_clang_type.GetBitSize(&thread);
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
// If there are any unaligned fields, this is stored in memory.
if (field_bit_offset % field_bit_width != 0)
@@ -798,7 +755,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
DataExtractor *copy_from_extractor = NULL;
uint32_t copy_from_offset = 0;
- if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
+ if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ())
{
if (integer_bytes < 8)
{
@@ -831,7 +788,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
return return_valobj_sp;
}
}
- else if (field_clang_type.IsFloatingPointType (count, is_complex))
+ else if (field_compiler_type.IsFloatingPointType (count, is_complex))
{
// Structs with long doubles are always passed in memory.
if (field_bit_width == 128)
@@ -858,12 +815,12 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
else
{
uint64_t next_field_bit_offset = 0;
- ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
+ CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1,
name,
&next_field_bit_offset,
NULL,
NULL);
- if (next_field_clang_type.IsIntegerType (is_signed))
+ if (next_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -882,12 +839,12 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
else
{
uint64_t prev_field_bit_offset = 0;
- ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
+ CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1,
name,
&prev_field_bit_offset,
NULL,
NULL);
- if (prev_field_clang_type.IsIntegerType (is_signed))
+ if (prev_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -946,7 +903,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
{
// The result is in our data buffer. Let's make a variable object out of it:
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
return_ext);
}
@@ -965,7 +922,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
return_valobj_sp = ValueObjectMemory::Create (&thread,
"",
Address (storage_addr, NULL),
- return_clang_type);
+ return_compiler_type);
}
}
@@ -978,9 +935,9 @@ ABISysV_ppc::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t lr_reg_num = gcc_dwarf_lr;
- uint32_t sp_reg_num = gcc_dwarf_r1;
- uint32_t pc_reg_num = gcc_dwarf_pc;
+ uint32_t lr_reg_num = dwarf_lr;
+ uint32_t sp_reg_num = dwarf_r1;
+ uint32_t pc_reg_num = dwarf_pc;
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -1005,8 +962,8 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t sp_reg_num = gcc_dwarf_r1;
- uint32_t pc_reg_num = gcc_dwarf_lr;
+ uint32_t sp_reg_num = dwarf_r1;
+ uint32_t pc_reg_num = dwarf_lr;
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -1020,7 +977,7 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.SetSourceName ("ppc default unwind plan");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
- unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr);
+ unwind_plan.SetReturnAddressRegister(dwarf_lr);
return true;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
index a7aad30..99ee755 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
@@ -21,52 +21,37 @@ class ABISysV_ppc :
public lldb_private::ABI
{
public:
+ ~ABISysV_ppc() override = default;
- ~ABISysV_ppc()
- {
- }
+ size_t
+ GetRedZoneSize() const override;
- virtual size_t
- GetRedZoneSize () const;
-
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
-
- virtual bool
- StackUsesFrames ()
- {
- return true;
- }
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The SysV ppc ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -78,8 +63,8 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -89,25 +74,21 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// We have a 64 bit address space, so anything is valid as opcodes
// aren't fixed width...
return true;
}
- virtual bool
- FunctionCallsChangeCFA ()
- {
- return true;
- }
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -123,21 +104,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
CreateRegisterMapIfNeeded ();
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_ppc() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_ppc() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABISysV_ppc_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
index eb0d7c0..96c54ce 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -34,120 +33,79 @@
using namespace lldb;
using namespace lldb_private;
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_r0 = 0,
- gcc_dwarf_r1,
- gcc_dwarf_r2,
- gcc_dwarf_r3,
- gcc_dwarf_r4,
- gcc_dwarf_r5,
- gcc_dwarf_r6,
- gcc_dwarf_r7,
- gcc_dwarf_r8,
- gcc_dwarf_r9,
- gcc_dwarf_r10,
- gcc_dwarf_r11,
- gcc_dwarf_r12,
- gcc_dwarf_r13,
- gcc_dwarf_r14,
- gcc_dwarf_r15,
- gcc_dwarf_r16,
- gcc_dwarf_r17,
- gcc_dwarf_r18,
- gcc_dwarf_r19,
- gcc_dwarf_r20,
- gcc_dwarf_r21,
- gcc_dwarf_r22,
- gcc_dwarf_r23,
- gcc_dwarf_r24,
- gcc_dwarf_r25,
- gcc_dwarf_r26,
- gcc_dwarf_r27,
- gcc_dwarf_r28,
- gcc_dwarf_r29,
- gcc_dwarf_r30,
- gcc_dwarf_r31,
- gcc_dwarf_f0,
- gcc_dwarf_f1,
- gcc_dwarf_f2,
- gcc_dwarf_f3,
- gcc_dwarf_f4,
- gcc_dwarf_f5,
- gcc_dwarf_f6,
- gcc_dwarf_f7,
- gcc_dwarf_f8,
- gcc_dwarf_f9,
- gcc_dwarf_f10,
- gcc_dwarf_f11,
- gcc_dwarf_f12,
- gcc_dwarf_f13,
- gcc_dwarf_f14,
- gcc_dwarf_f15,
- gcc_dwarf_f16,
- gcc_dwarf_f17,
- gcc_dwarf_f18,
- gcc_dwarf_f19,
- gcc_dwarf_f20,
- gcc_dwarf_f21,
- gcc_dwarf_f22,
- gcc_dwarf_f23,
- gcc_dwarf_f24,
- gcc_dwarf_f25,
- gcc_dwarf_f26,
- gcc_dwarf_f27,
- gcc_dwarf_f28,
- gcc_dwarf_f29,
- gcc_dwarf_f30,
- gcc_dwarf_f31,
- gcc_dwarf_cr,
- gcc_dwarf_fpscr,
- gcc_dwarf_xer = 101,
- gcc_dwarf_lr = 108,
- gcc_dwarf_ctr,
- gcc_dwarf_pc,
- gcc_dwarf_cfa,
-};
-
-enum gdb_regnums
-{
- gdb_r0 = 0,
- gdb_r1,
- gdb_r2,
- gdb_r3,
- gdb_r4,
- gdb_r5,
- gdb_r6,
- gdb_r7,
- gdb_r8,
- gdb_r9,
- gdb_r10,
- gdb_r11,
- gdb_r12,
- gdb_r13,
- gdb_r14,
- gdb_r15,
- gdb_r16,
- gdb_r17,
- gdb_r18,
- gdb_r19,
- gdb_r20,
- gdb_r21,
- gdb_r22,
- gdb_r23,
- gdb_r24,
- gdb_r25,
- gdb_r26,
- gdb_r27,
- gdb_r28,
- gdb_r29,
- gdb_r30,
- gdb_r31,
- gdb_lr,
- gdb_cr,
- gdb_xer,
- gdb_ctr,
- gdb_pc,
+ dwarf_r0 = 0,
+ dwarf_r1,
+ dwarf_r2,
+ dwarf_r3,
+ dwarf_r4,
+ dwarf_r5,
+ dwarf_r6,
+ dwarf_r7,
+ dwarf_r8,
+ dwarf_r9,
+ dwarf_r10,
+ dwarf_r11,
+ dwarf_r12,
+ dwarf_r13,
+ dwarf_r14,
+ dwarf_r15,
+ dwarf_r16,
+ dwarf_r17,
+ dwarf_r18,
+ dwarf_r19,
+ dwarf_r20,
+ dwarf_r21,
+ dwarf_r22,
+ dwarf_r23,
+ dwarf_r24,
+ dwarf_r25,
+ dwarf_r26,
+ dwarf_r27,
+ dwarf_r28,
+ dwarf_r29,
+ dwarf_r30,
+ dwarf_r31,
+ dwarf_f0,
+ dwarf_f1,
+ dwarf_f2,
+ dwarf_f3,
+ dwarf_f4,
+ dwarf_f5,
+ dwarf_f6,
+ dwarf_f7,
+ dwarf_f8,
+ dwarf_f9,
+ dwarf_f10,
+ dwarf_f11,
+ dwarf_f12,
+ dwarf_f13,
+ dwarf_f14,
+ dwarf_f15,
+ dwarf_f16,
+ dwarf_f17,
+ dwarf_f18,
+ dwarf_f19,
+ dwarf_f20,
+ dwarf_f21,
+ dwarf_f22,
+ dwarf_f23,
+ dwarf_f24,
+ dwarf_f25,
+ dwarf_f26,
+ dwarf_f27,
+ dwarf_f28,
+ dwarf_f29,
+ dwarf_f30,
+ dwarf_f31,
+ dwarf_cr,
+ dwarf_fpscr,
+ dwarf_xer = 101,
+ dwarf_lr = 108,
+ dwarf_ctr,
+ dwarf_pc,
+ dwarf_cfa,
};
@@ -158,45 +116,45 @@ enum gdb_regnums
static const RegisterInfo
g_register_infos[] =
{
- // General purpose registers. GCC, DWARF, Generic, GDB
- DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0),
- DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1),
- DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2),
- DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3),
- DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4),
- DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5),
- DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6),
- DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7),
- DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8),
- DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9),
- DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10),
- DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11),
- DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12),
- DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13),
- DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14),
- DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15),
- DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16),
- DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17),
- DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18),
- DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19),
- DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20),
- DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21),
- DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22),
- DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23),
- DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24),
- DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25),
- DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26),
- DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27),
- DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28),
- DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29),
- DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30),
- DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31),
- DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr),
- DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
- DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
- { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
+ // General purpose registers. eh_frame, DWARF, Generic, Process Plugin
+ DEFINE_GPR(r0, NULL, dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r1, "sp", dwarf_r1, dwarf_r1, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r2, NULL, dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r3, "arg1",dwarf_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r4, "arg2",dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r5, "arg3",dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r6, "arg4",dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r7, "arg5",dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r8, "arg6",dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r9, "arg7",dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r10, "arg8",dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r11, NULL, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r12, NULL, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r13, NULL, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r14, NULL, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r15, NULL, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r16, NULL, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r17, NULL, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r18, NULL, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r19, NULL, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r20, NULL, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r21, NULL, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r22, NULL, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r23, NULL, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r24, NULL, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r25, NULL, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r26, NULL, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r27, NULL, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r28, NULL, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r29, NULL, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r30, NULL, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r31, NULL, dwarf_r31, dwarf_r31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(lr, "lr", dwarf_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cr, "cr", dwarf_cr, dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(xer, "xer", dwarf_xer, dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ctr, "ctr", dwarf_ctr, dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -436,25 +394,25 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread,
// We currently only support extracting values with Clang QualTypes.
// Do we care about others?
- ClangASTType clang_type = value->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = value->GetCompilerType();
+ if (!compiler_type)
return false;
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
is_signed,
thread,
argument_register_ids,
current_argument_register,
current_stack_argument);
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
false,
thread,
argument_register_ids,
@@ -476,8 +434,8 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -492,7 +450,7 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
@@ -518,13 +476,13 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
else
{
- size_t bit_width = clang_type.GetBitSize(frame_sp.get());
+ size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
if (bit_width <= 64)
{
DataExtractor data;
@@ -563,22 +521,22 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
ValueObjectSP
ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
- ClangASTType &return_clang_type) const
+ CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
//value.SetContext (Value::eContextTypeClangType, return_value_type);
- value.SetClangType (return_clang_type);
+ value.SetCompilerType (return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo ();
if (type_flags & eTypeIsScalar)
{
value.SetValueType(Value::eValueTypeScalar);
@@ -588,7 +546,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
{
// Extract the register context so we can read arguments from registers
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
switch (byte_size)
@@ -637,7 +595,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
}
else
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size <= sizeof(long double))
{
const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
@@ -681,7 +639,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
}
else if (type_flags & eTypeIsVector)
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size > 0)
{
@@ -709,7 +667,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
byte_order,
process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
@@ -724,15 +682,15 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
}
ValueObjectSP
-ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
ExecutionContext exe_ctx (thread.shared_from_this());
- return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
if (return_valobj_sp)
return return_valobj_sp;
@@ -740,8 +698,8 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
if (!reg_ctx_sp)
return return_valobj_sp;
- const size_t bit_width = return_clang_type.GetBitSize(&thread);
- if (return_clang_type.IsAggregateType())
+ const size_t bit_width = return_compiler_type.GetBitSize(&thread);
+ if (return_compiler_type.IsAggregateType())
{
Target *target = exe_ctx.GetTargetPtr();
bool is_memory = true;
@@ -768,7 +726,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far
uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far
- const uint32_t num_children = return_clang_type.GetNumFields ();
+ const uint32_t num_children = return_compiler_type.GetNumFields ();
// Since we are in the small struct regime, assume we are not in memory.
is_memory = false;
@@ -781,8 +739,8 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
bool is_complex;
uint32_t count;
- ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
- const size_t field_bit_width = field_clang_type.GetBitSize(&thread);
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
// If there are any unaligned fields, this is stored in memory.
if (field_bit_offset % field_bit_width != 0)
@@ -798,7 +756,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
DataExtractor *copy_from_extractor = NULL;
uint32_t copy_from_offset = 0;
- if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
+ if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ())
{
if (integer_bytes < 8)
{
@@ -831,7 +789,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
return return_valobj_sp;
}
}
- else if (field_clang_type.IsFloatingPointType (count, is_complex))
+ else if (field_compiler_type.IsFloatingPointType (count, is_complex))
{
// Structs with long doubles are always passed in memory.
if (field_bit_width == 128)
@@ -858,12 +816,12 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
else
{
uint64_t next_field_bit_offset = 0;
- ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
+ CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1,
name,
&next_field_bit_offset,
NULL,
NULL);
- if (next_field_clang_type.IsIntegerType (is_signed))
+ if (next_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -882,12 +840,12 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
else
{
uint64_t prev_field_bit_offset = 0;
- ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
+ CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1,
name,
&prev_field_bit_offset,
NULL,
NULL);
- if (prev_field_clang_type.IsIntegerType (is_signed))
+ if (prev_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -946,7 +904,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
{
// The result is in our data buffer. Let's make a variable object out of it:
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
return_ext);
}
@@ -965,7 +923,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
return_valobj_sp = ValueObjectMemory::Create (&thread,
"",
Address (storage_addr, NULL),
- return_clang_type);
+ return_compiler_type);
}
}
@@ -978,9 +936,9 @@ ABISysV_ppc64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t lr_reg_num = gcc_dwarf_lr;
- uint32_t sp_reg_num = gcc_dwarf_r1;
- uint32_t pc_reg_num = gcc_dwarf_pc;
+ uint32_t lr_reg_num = dwarf_lr;
+ uint32_t sp_reg_num = dwarf_r1;
+ uint32_t pc_reg_num = dwarf_pc;
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -1005,8 +963,8 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t sp_reg_num = gcc_dwarf_r1;
- uint32_t pc_reg_num = gcc_dwarf_lr;
+ uint32_t sp_reg_num = dwarf_r1;
+ uint32_t pc_reg_num = dwarf_lr;
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -1015,13 +973,13 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
- row->SetRegisterLocationToAtCFAPlusOffset(gcc_dwarf_cr, ptr_size, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(dwarf_cr, ptr_size, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("ppc64 default unwind plan");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
- unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr);
+ unwind_plan.SetReturnAddressRegister(dwarf_lr);
return true;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
index d77cb9f..b87f793 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
@@ -21,52 +21,37 @@ class ABISysV_ppc64 :
public lldb_private::ABI
{
public:
+ ~ABISysV_ppc64() override = default;
- ~ABISysV_ppc64()
- {
- }
+ size_t
+ GetRedZoneSize() const override;
- virtual size_t
- GetRedZoneSize () const;
-
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
-
- virtual bool
- StackUsesFrames ()
- {
- return true;
- }
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The SysV ppc64 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -78,8 +63,8 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -89,25 +74,21 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// We have a 64 bit address space, so anything is valid as opcodes
// aren't fixed width...
return true;
}
- virtual bool
- FunctionCallsChangeCFA ()
- {
- return true;
- }
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -123,21 +104,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
CreateRegisterMapIfNeeded ();
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_ppc64() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_ppc64() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABISysV_ppc64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
index 1d63628..11e383d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -34,222 +33,144 @@
using namespace lldb;
using namespace lldb_private;
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_rax = 0,
- gcc_dwarf_rdx,
- gcc_dwarf_rcx,
- gcc_dwarf_rbx,
- gcc_dwarf_rsi,
- gcc_dwarf_rdi,
- gcc_dwarf_rbp,
- gcc_dwarf_rsp,
- gcc_dwarf_r8,
- gcc_dwarf_r9,
- gcc_dwarf_r10,
- gcc_dwarf_r11,
- gcc_dwarf_r12,
- gcc_dwarf_r13,
- gcc_dwarf_r14,
- gcc_dwarf_r15,
- gcc_dwarf_rip,
- gcc_dwarf_xmm0,
- gcc_dwarf_xmm1,
- gcc_dwarf_xmm2,
- gcc_dwarf_xmm3,
- gcc_dwarf_xmm4,
- gcc_dwarf_xmm5,
- gcc_dwarf_xmm6,
- gcc_dwarf_xmm7,
- gcc_dwarf_xmm8,
- gcc_dwarf_xmm9,
- gcc_dwarf_xmm10,
- gcc_dwarf_xmm11,
- gcc_dwarf_xmm12,
- gcc_dwarf_xmm13,
- gcc_dwarf_xmm14,
- gcc_dwarf_xmm15,
- gcc_dwarf_stmm0,
- gcc_dwarf_stmm1,
- gcc_dwarf_stmm2,
- gcc_dwarf_stmm3,
- gcc_dwarf_stmm4,
- gcc_dwarf_stmm5,
- gcc_dwarf_stmm6,
- gcc_dwarf_stmm7,
- gcc_dwarf_ymm0,
- gcc_dwarf_ymm1,
- gcc_dwarf_ymm2,
- gcc_dwarf_ymm3,
- gcc_dwarf_ymm4,
- gcc_dwarf_ymm5,
- gcc_dwarf_ymm6,
- gcc_dwarf_ymm7,
- gcc_dwarf_ymm8,
- gcc_dwarf_ymm9,
- gcc_dwarf_ymm10,
- gcc_dwarf_ymm11,
- gcc_dwarf_ymm12,
- gcc_dwarf_ymm13,
- gcc_dwarf_ymm14,
- gcc_dwarf_ymm15
+ dwarf_rax = 0,
+ dwarf_rdx,
+ dwarf_rcx,
+ dwarf_rbx,
+ dwarf_rsi,
+ dwarf_rdi,
+ dwarf_rbp,
+ dwarf_rsp,
+ dwarf_r8,
+ dwarf_r9,
+ dwarf_r10,
+ dwarf_r11,
+ dwarf_r12,
+ dwarf_r13,
+ dwarf_r14,
+ dwarf_r15,
+ dwarf_rip,
+ dwarf_xmm0,
+ dwarf_xmm1,
+ dwarf_xmm2,
+ dwarf_xmm3,
+ dwarf_xmm4,
+ dwarf_xmm5,
+ dwarf_xmm6,
+ dwarf_xmm7,
+ dwarf_xmm8,
+ dwarf_xmm9,
+ dwarf_xmm10,
+ dwarf_xmm11,
+ dwarf_xmm12,
+ dwarf_xmm13,
+ dwarf_xmm14,
+ dwarf_xmm15,
+ dwarf_stmm0,
+ dwarf_stmm1,
+ dwarf_stmm2,
+ dwarf_stmm3,
+ dwarf_stmm4,
+ dwarf_stmm5,
+ dwarf_stmm6,
+ dwarf_stmm7,
+ dwarf_ymm0,
+ dwarf_ymm1,
+ dwarf_ymm2,
+ dwarf_ymm3,
+ dwarf_ymm4,
+ dwarf_ymm5,
+ dwarf_ymm6,
+ dwarf_ymm7,
+ dwarf_ymm8,
+ dwarf_ymm9,
+ dwarf_ymm10,
+ dwarf_ymm11,
+ dwarf_ymm12,
+ dwarf_ymm13,
+ dwarf_ymm14,
+ dwarf_ymm15
};
-enum gdb_regnums
-{
- gdb_rax = 0,
- gdb_rbx = 1,
- gdb_rcx = 2,
- gdb_rdx = 3,
- gdb_rsi = 4,
- gdb_rdi = 5,
- gdb_rbp = 6,
- gdb_rsp = 7,
- gdb_r8 = 8,
- gdb_r9 = 9,
- gdb_r10 = 10,
- gdb_r11 = 11,
- gdb_r12 = 12,
- gdb_r13 = 13,
- gdb_r14 = 14,
- gdb_r15 = 15,
- gdb_rip = 16,
- gdb_rflags = 17,
- gdb_cs = 18,
- gdb_ss = 19,
- gdb_ds = 20,
- gdb_es = 21,
- gdb_fs = 22,
- gdb_gs = 23,
- gdb_stmm0 = 24,
- gdb_stmm1 = 25,
- gdb_stmm2 = 26,
- gdb_stmm3 = 27,
- gdb_stmm4 = 28,
- gdb_stmm5 = 29,
- gdb_stmm6 = 30,
- gdb_stmm7 = 31,
- gdb_fctrl = 32, gdb_fcw = gdb_fctrl,
- gdb_fstat = 33, gdb_fsw = gdb_fstat,
- gdb_ftag = 34, gdb_ftw = gdb_ftag,
- gdb_fiseg = 35, gdb_fpu_cs = gdb_fiseg,
- gdb_fioff = 36, gdb_ip = gdb_fioff,
- gdb_foseg = 37, gdb_fpu_ds = gdb_foseg,
- gdb_fooff = 38, gdb_dp = gdb_fooff,
- gdb_fop = 39,
- gdb_xmm0 = 40,
- gdb_xmm1 = 41,
- gdb_xmm2 = 42,
- gdb_xmm3 = 43,
- gdb_xmm4 = 44,
- gdb_xmm5 = 45,
- gdb_xmm6 = 46,
- gdb_xmm7 = 47,
- gdb_xmm8 = 48,
- gdb_xmm9 = 49,
- gdb_xmm10 = 50,
- gdb_xmm11 = 51,
- gdb_xmm12 = 52,
- gdb_xmm13 = 53,
- gdb_xmm14 = 54,
- gdb_xmm15 = 55,
- gdb_mxcsr = 56,
- gdb_ymm0 = 57,
- gdb_ymm1 = 58,
- gdb_ymm2 = 59,
- gdb_ymm3 = 60,
- gdb_ymm4 = 61,
- gdb_ymm5 = 62,
- gdb_ymm6 = 63,
- gdb_ymm7 = 64,
- gdb_ymm8 = 65,
- gdb_ymm9 = 66,
- gdb_ymm10 = 67,
- gdb_ymm11 = 68,
- gdb_ymm12 = 69,
- gdb_ymm13 = 70,
- gdb_ymm14 = 71,
- gdb_ymm15 = 72
-};
-
-
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ======== ======= == === ============= =================== ======================= ===================== =========================== ===================== ====================== ========== ===============
- { "rax" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rax , gcc_dwarf_rax , LLDB_INVALID_REGNUM , gdb_rax , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rbx" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rbx , gcc_dwarf_rbx , LLDB_INVALID_REGNUM , gdb_rbx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rcx" , "arg4", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rcx , gcc_dwarf_rcx , LLDB_REGNUM_GENERIC_ARG4 , gdb_rcx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rdx" , "arg3", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rdx , gcc_dwarf_rdx , LLDB_REGNUM_GENERIC_ARG3 , gdb_rdx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rsi" , "arg2", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rsi , gcc_dwarf_rsi , LLDB_REGNUM_GENERIC_ARG2 , gdb_rsi , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rdi" , "arg1", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rdi , gcc_dwarf_rdi , LLDB_REGNUM_GENERIC_ARG1 , gdb_rdi , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rbp" , "fp", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rbp , gcc_dwarf_rbp , LLDB_REGNUM_GENERIC_FP , gdb_rbp , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rsp" , "sp", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rsp , gcc_dwarf_rsp , LLDB_REGNUM_GENERIC_SP , gdb_rsp , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r8" , "arg5", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r8 , gcc_dwarf_r8 , LLDB_REGNUM_GENERIC_ARG5 , gdb_r8 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r9" , "arg6", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r9 , gcc_dwarf_r9 , LLDB_REGNUM_GENERIC_ARG6 , gdb_r9 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r10" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r10 , gcc_dwarf_r10 , LLDB_INVALID_REGNUM , gdb_r10 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r11" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r11 , gcc_dwarf_r11 , LLDB_INVALID_REGNUM , gdb_r11 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r12" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r12 , gcc_dwarf_r12 , LLDB_INVALID_REGNUM , gdb_r12 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r13" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r13 , gcc_dwarf_r13 , LLDB_INVALID_REGNUM , gdb_r13 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r14" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r14 , gcc_dwarf_r14 , LLDB_INVALID_REGNUM , gdb_r14 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r15" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r15 , gcc_dwarf_r15 , LLDB_INVALID_REGNUM , gdb_r15 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rip" , "pc", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rip , gcc_dwarf_rip , LLDB_REGNUM_GENERIC_PC , gdb_rip , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_rflags , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm0 , gcc_dwarf_stmm0 , LLDB_INVALID_REGNUM , gdb_stmm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm1 , gcc_dwarf_stmm1 , LLDB_INVALID_REGNUM , gdb_stmm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm2 , gcc_dwarf_stmm2 , LLDB_INVALID_REGNUM , gdb_stmm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm3 , gcc_dwarf_stmm3 , LLDB_INVALID_REGNUM , gdb_stmm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm4 , gcc_dwarf_stmm4 , LLDB_INVALID_REGNUM , gdb_stmm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm5 , gcc_dwarf_stmm5 , LLDB_INVALID_REGNUM , gdb_stmm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm6 , gcc_dwarf_stmm6 , LLDB_INVALID_REGNUM , gdb_stmm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm7 , gcc_dwarf_stmm7 , LLDB_INVALID_REGNUM , gdb_stmm7 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm0 , gcc_dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm1 , gcc_dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm2 , gcc_dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm3 , gcc_dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm4 , gcc_dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm5 , gcc_dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm6 , gcc_dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm7 , gcc_dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm8" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm8 , gcc_dwarf_xmm8 , LLDB_INVALID_REGNUM , gdb_xmm8 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm9" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm9 , gcc_dwarf_xmm9 , LLDB_INVALID_REGNUM , gdb_xmm9 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm10" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm10 , gcc_dwarf_xmm10 , LLDB_INVALID_REGNUM , gdb_xmm10 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm11" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm11 , gcc_dwarf_xmm11 , LLDB_INVALID_REGNUM , gdb_xmm11 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm12" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm12 , gcc_dwarf_xmm12 , LLDB_INVALID_REGNUM , gdb_xmm12 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm13" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm13 , gcc_dwarf_xmm13 , LLDB_INVALID_REGNUM , gdb_xmm13 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm14" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm14 , gcc_dwarf_xmm14 , LLDB_INVALID_REGNUM , gdb_xmm14 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm15" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm15 , gcc_dwarf_xmm15 , LLDB_INVALID_REGNUM , gdb_xmm15 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm0 , gcc_dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm1 , gcc_dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm2 , gcc_dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm3 , gcc_dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm4 , gcc_dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm5 , gcc_dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm6 , gcc_dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm7 , gcc_dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm8" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm8 , gcc_dwarf_ymm8 , LLDB_INVALID_REGNUM , gdb_ymm8 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm9" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm9 , gcc_dwarf_ymm9 , LLDB_INVALID_REGNUM , gdb_ymm9 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm10" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm10 , gcc_dwarf_ymm10 , LLDB_INVALID_REGNUM , gdb_ymm10 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm11" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm11 , gcc_dwarf_ymm11 , LLDB_INVALID_REGNUM , gdb_ymm11 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm12" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm12 , gcc_dwarf_ymm12 , LLDB_INVALID_REGNUM , gdb_ymm12 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm13" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm13 , gcc_dwarf_ymm13 , LLDB_INVALID_REGNUM , gdb_ymm13 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm14" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm14 , gcc_dwarf_ymm14 , LLDB_INVALID_REGNUM , gdb_ymm14 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm15" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm15 , gcc_dwarf_ymm15 , LLDB_INVALID_REGNUM , gdb_ymm15 , LLDB_INVALID_REGNUM }, NULL, NULL}
+ { "rax" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_rax , dwarf_rax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rbx" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_rbx , dwarf_rbx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rcx" , "arg4", 8, 0, eEncodingUint , eFormatHex , { dwarf_rcx , dwarf_rcx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rdx" , "arg3", 8, 0, eEncodingUint , eFormatHex , { dwarf_rdx , dwarf_rdx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rsi" , "arg2", 8, 0, eEncodingUint , eFormatHex , { dwarf_rsi , dwarf_rsi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rdi" , "arg1", 8, 0, eEncodingUint , eFormatHex , { dwarf_rdi , dwarf_rdi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rbp" , "fp", 8, 0, eEncodingUint , eFormatHex , { dwarf_rbp , dwarf_rbp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rsp" , "sp", 8, 0, eEncodingUint , eFormatHex , { dwarf_rsp , dwarf_rsp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8" , "arg5", 8, 0, eEncodingUint , eFormatHex , { dwarf_r8 , dwarf_r8 , LLDB_REGNUM_GENERIC_ARG5 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9" , "arg6", 8, 0, eEncodingUint , eFormatHex , { dwarf_r9 , dwarf_r9 , LLDB_REGNUM_GENERIC_ARG6 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r10 , dwarf_r10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r11 , dwarf_r11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r12 , dwarf_r12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r13 , dwarf_r13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r14 , dwarf_r14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r15" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r15 , dwarf_r15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rip" , "pc", 8, 0, eEncodingUint , eFormatHex , { dwarf_rip , dwarf_rip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm0 , dwarf_stmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm1 , dwarf_stmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm2 , dwarf_stmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm3 , dwarf_stmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm4 , dwarf_stmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm5 , dwarf_stmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm6 , dwarf_stmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm7 , dwarf_stmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm0 , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm1 , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm2 , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm3 , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm4 , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm5 , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm6 , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm7 , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm8" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm8 , dwarf_xmm8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm9" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm9 , dwarf_xmm9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm10" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm10 , dwarf_xmm10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm11" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm11 , dwarf_xmm11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm12" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm12 , dwarf_xmm12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm13" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm13 , dwarf_xmm13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm14" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm14 , dwarf_xmm14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm15" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm15 , dwarf_xmm15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm0 , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm1 , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm2 , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm3 , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm4 , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm5 , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm6 , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm7 , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm8" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm8 , dwarf_ymm8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm9" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm9 , dwarf_ymm9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm10" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm10 , dwarf_ymm10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm11" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm11 , dwarf_ymm11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm12" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm12 , dwarf_ymm12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm13" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm13 , dwarf_ymm13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm14" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm14 , dwarf_ymm14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm15" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm15 , dwarf_ymm15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -502,25 +423,25 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread,
// We currently only support extracting values with Clang QualTypes.
// Do we care about others?
- ClangASTType clang_type = value->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = value->GetCompilerType();
+ if (!compiler_type)
return false;
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
is_signed,
thread,
argument_register_ids,
current_argument_register,
current_stack_argument);
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
false,
thread,
argument_register_ids,
@@ -542,8 +463,8 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -558,7 +479,7 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0);
@@ -584,13 +505,13 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
else
{
- size_t bit_width = clang_type.GetBitSize(frame_sp.get());
+ size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
if (bit_width <= 64)
{
const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
@@ -633,22 +554,22 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
ValueObjectSP
ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
- ClangASTType &return_clang_type) const
+ CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
//value.SetContext (Value::eContextTypeClangType, return_value_type);
- value.SetClangType (return_clang_type);
+ value.SetCompilerType (return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo ();
if (type_flags & eTypeIsScalar)
{
value.SetValueType(Value::eValueTypeScalar);
@@ -658,7 +579,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
{
// Extract the register context so we can read arguments from registers
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
switch (byte_size)
@@ -707,7 +628,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
}
else
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size <= sizeof(long double))
{
const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
@@ -755,18 +676,13 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
}
else if (type_flags & eTypeIsVector)
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size > 0)
{
+ const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
+ if (altivec_reg == nullptr)
+ altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
- const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0);
- if (altivec_reg == NULL)
- {
- altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
- if (altivec_reg == NULL)
- altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
- }
-
if (altivec_reg)
{
if (byte_size <= altivec_reg->byte_size)
@@ -790,13 +706,52 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
byte_order,
process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
}
}
}
+ else if (byte_size <= altivec_reg->byte_size*2)
+ {
+ const RegisterInfo *altivec_reg2 = reg_ctx->GetRegisterInfoByName("xmm1", 0);
+ if (altivec_reg2)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue reg_value;
+ RegisterValue reg_value2;
+ if (reg_ctx->ReadRegister(altivec_reg, reg_value) && reg_ctx->ReadRegister(altivec_reg2, reg_value2))
+ {
+
+ Error error;
+ if (reg_value.GetAsMemoryData (altivec_reg,
+ heap_data_ap->GetBytes(),
+ altivec_reg->byte_size,
+ byte_order,
+ error) &&
+ reg_value2.GetAsMemoryData (altivec_reg2,
+ heap_data_ap->GetBytes() + altivec_reg->byte_size,
+ heap_data_ap->GetByteSize() - altivec_reg->byte_size,
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_compiler_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
}
}
}
@@ -805,15 +760,15 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
}
ValueObjectSP
-ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
ExecutionContext exe_ctx (thread.shared_from_this());
- return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
if (return_valobj_sp)
return return_valobj_sp;
@@ -821,8 +776,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
if (!reg_ctx_sp)
return return_valobj_sp;
- const size_t bit_width = return_clang_type.GetBitSize(&thread);
- if (return_clang_type.IsAggregateType())
+ const size_t bit_width = return_compiler_type.GetBitSize(&thread);
+ if (return_compiler_type.IsAggregateType())
{
Target *target = exe_ctx.GetTargetPtr();
bool is_memory = true;
@@ -855,7 +810,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far
uint32_t integer_bytes = 0; // Tracks how much of the rax/rds registers we've consumed so far
- const uint32_t num_children = return_clang_type.GetNumFields ();
+ const uint32_t num_children = return_compiler_type.GetNumFields ();
// Since we are in the small struct regime, assume we are not in memory.
is_memory = false;
@@ -868,8 +823,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
bool is_complex;
uint32_t count;
- ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
- const size_t field_bit_width = field_clang_type.GetBitSize(&thread);
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
// if we don't know the size of the field (e.g. invalid type), just bail out
if (field_bit_width == 0)
@@ -889,7 +844,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
DataExtractor *copy_from_extractor = NULL;
uint32_t copy_from_offset = 0;
- if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
+ if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ())
{
if (integer_bytes < 8)
{
@@ -922,7 +877,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
return return_valobj_sp;
}
}
- else if (field_clang_type.IsFloatingPointType (count, is_complex))
+ else if (field_compiler_type.IsFloatingPointType (count, is_complex))
{
// Structs with long doubles are always passed in memory.
if (field_bit_width == 128)
@@ -955,12 +910,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
else
{
uint64_t next_field_bit_offset = 0;
- ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
+ CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1,
name,
&next_field_bit_offset,
NULL,
NULL);
- if (next_field_clang_type.IsIntegerType (is_signed))
+ if (next_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -979,12 +934,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
else
{
uint64_t prev_field_bit_offset = 0;
- ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
+ CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1,
name,
&prev_field_bit_offset,
NULL,
NULL);
- if (prev_field_clang_type.IsIntegerType (is_signed))
+ if (prev_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -1048,7 +1003,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
{
// The result is in our data buffer. Let's make a variable object out of it:
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
return_ext);
}
@@ -1067,7 +1022,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
return_valobj_sp = ValueObjectMemory::Create (&thread,
"",
Address (storage_addr, NULL),
- return_clang_type);
+ return_compiler_type);
}
}
@@ -1084,8 +1039,8 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t sp_reg_num = gcc_dwarf_rsp;
- uint32_t pc_reg_num = gcc_dwarf_rip;
+ uint32_t sp_reg_num = dwarf_rsp;
+ uint32_t pc_reg_num = dwarf_rip;
UnwindPlan::RowSP row(new UnwindPlan::Row);
row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 8);
@@ -1108,14 +1063,14 @@ ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t fp_reg_num = gcc_dwarf_rbp;
- uint32_t sp_reg_num = gcc_dwarf_rsp;
- uint32_t pc_reg_num = gcc_dwarf_rip;
+ uint32_t fp_reg_num = dwarf_rbp;
+ uint32_t sp_reg_num = dwarf_rsp;
+ uint32_t pc_reg_num = dwarf_rip;
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_rbp, 2 * ptr_size);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);
row->SetOffset (0);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
index 6fefcc2..07b57ab 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
@@ -21,46 +21,37 @@ class ABISysV_x86_64 :
public lldb_private::ABI
{
public:
+ ~ABISysV_x86_64() override = default;
- ~ABISysV_x86_64()
- {
- }
-
- virtual size_t
- GetRedZoneSize () const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The SysV x86_64 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -72,8 +63,8 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -83,19 +74,21 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// We have a 64 bit address space, so anything is valid as opcodes
// aren't fixed width...
return true;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -111,21 +104,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
CreateRegisterMapIfNeeded ();
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_x86_64() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_x86_64() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABISysV_x86_64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index d20219f..6d124b6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -7,8 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "DisassemblerLLVMC.h"
-
+// C Includes
+// C++ Includes
+// Project includes
#include "llvm-c/Disassembler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -25,6 +26,8 @@
#include "llvm/Support/TargetSelect.h"
#include "llvm/ADT/SmallString.h"
+// Other libraries and framework includes
+#include "DisassemblerLLVMC.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/DataExtractor.h"
@@ -52,18 +55,16 @@ public:
Instruction (address, addr_class),
m_disasm_sp (disasm.shared_from_this()),
m_does_branch (eLazyBoolCalculate),
+ m_has_delay_slot (eLazyBoolCalculate),
m_is_valid (false),
m_using_file_addr (false)
{
}
- virtual
- ~InstructionLLVMC ()
- {
- }
+ ~InstructionLLVMC() override = default;
- virtual bool
- DoesBranch ()
+ bool
+ DoesBranch() override
{
if (m_does_branch == eLazyBoolCalculate)
{
@@ -99,6 +100,43 @@ public:
return m_does_branch == eLazyBoolYes;
}
+ bool
+ HasDelaySlot() override
+ {
+ if (m_has_delay_slot == eLazyBoolCalculate)
+ {
+ GetDisassemblerLLVMC().Lock(this, NULL);
+ DataExtractor data;
+ if (m_opcode.GetData(data))
+ {
+ bool is_alternate_isa;
+ lldb::addr_t pc = m_address.GetFileAddress();
+
+ DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
+ const uint8_t *opcode_data = data.GetDataStart();
+ const size_t opcode_data_len = data.GetByteSize();
+ llvm::MCInst inst;
+ const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
+ opcode_data_len,
+ pc,
+ inst);
+ // if we didn't understand the instruction, say it doesn't have a delay slot...
+ if (inst_size == 0)
+ m_has_delay_slot = eLazyBoolNo;
+ else
+ {
+ const bool has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst);
+ if (has_delay_slot)
+ m_has_delay_slot = eLazyBoolYes;
+ else
+ m_has_delay_slot = eLazyBoolNo;
+ }
+ }
+ GetDisassemblerLLVMC().Unlock();
+ }
+ return m_has_delay_slot == eLazyBoolYes;
+ }
+
DisassemblerLLVMC::LLVMCDisassembler *
GetDisasmToUse (bool &is_alternate_isa)
{
@@ -117,10 +155,10 @@ public:
return llvm_disasm.m_disasm_ap.get();
}
- virtual size_t
- Decode (const lldb_private::Disassembler &disassembler,
- const lldb_private::DataExtractor &data,
- lldb::offset_t data_offset)
+ size_t
+ Decode(const lldb_private::Disassembler &disassembler,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t data_offset) override
{
// All we have to do is read the opcode which can be easy for some
// architectures
@@ -234,15 +272,16 @@ public:
}
}
- virtual void
- CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx)
+ void
+ CalculateMnemonicOperandsAndComment(const lldb_private::ExecutionContext *exe_ctx) override
{
DataExtractor data;
const AddressClass address_class = GetAddressClass ();
if (m_opcode.GetData(data))
{
- char out_string[512];
+ std::string out_string;
+ std::string comment_string;
DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
@@ -293,7 +332,12 @@ public:
if (inst_size > 0)
{
mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style);
- mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string));
+ mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string);
+
+ if (!comment_string.empty())
+ {
+ AppendComment(comment_string);
+ }
}
llvm_disasm.Unlock();
@@ -375,10 +419,10 @@ public:
RegularExpression::Match matches(3);
- if (s_regex.Execute(out_string, &matches))
+ if (s_regex.Execute(out_string.c_str(), &matches))
{
- matches.GetMatchAtIndex(out_string, 1, m_opcode_name);
- matches.GetMatchAtIndex(out_string, 2, m_mnemonics);
+ matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name);
+ matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics);
}
}
}
@@ -409,12 +453,11 @@ protected:
DisassemblerSP m_disasm_sp; // for ownership
LazyBool m_does_branch;
+ LazyBool m_has_delay_slot;
bool m_is_valid;
bool m_using_file_addr;
};
-
-
DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, const char *cpu, const char *features_str, unsigned flavor, DisassemblerLLVMC &owner):
m_is_valid(true)
{
@@ -482,9 +525,7 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, con
m_is_valid = false;
}
-DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler()
-{
-}
+DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() = default;
uint64_t
DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,
@@ -508,22 +549,25 @@ DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,
return 0;
}
-uint64_t
+void
DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst,
- char *dst,
- size_t dst_len)
+ std::string &inst_string,
+ std::string &comments_string)
{
- llvm::StringRef unused_annotations;
- llvm::SmallString<64> inst_string;
- llvm::raw_svector_ostream inst_stream(inst_string);
- m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations,
- *m_subtarget_info_ap);
- inst_stream.flush();
- const size_t output_size = std::min(dst_len - 1, inst_string.size());
- std::memcpy(dst, inst_string.data(), output_size);
- dst[output_size] = '\0';
-
- return output_size;
+ llvm::raw_string_ostream inst_stream(inst_string);
+ llvm::raw_string_ostream comments_stream(comments_string);
+
+ m_instr_printer_ap->setCommentStream(comments_stream);
+ m_instr_printer_ap->printInst (&mc_inst, inst_stream, llvm::StringRef(), *m_subtarget_info_ap);
+ m_instr_printer_ap->setCommentStream(llvm::nulls());
+ comments_stream.flush();
+
+ static std::string g_newlines("\r\n");
+
+ for (size_t newline_pos = 0; (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) != comments_string.npos; /**/)
+ {
+ comments_string.replace(comments_string.begin() + newline_pos, comments_string.begin() + newline_pos + 1, 1, ' ');
+ }
}
void
@@ -544,35 +588,9 @@ DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst)
}
bool
-DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor)
+DisassemblerLLVMC::LLVMCDisassembler::HasDelaySlot (llvm::MCInst &mc_inst)
{
- llvm::Triple triple = arch.GetTriple();
- if (flavor == NULL || strcmp (flavor, "default") == 0)
- return true;
-
- if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
- {
- if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0)
- return true;
- else
- return false;
- }
- else
- return false;
-}
-
-
-Disassembler *
-DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
-{
- if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch)
- {
- std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor));
-
- if (disasm_ap.get() && disasm_ap->IsValid())
- return disasm_ap.release();
- }
- return NULL;
+ return m_instr_info_ap->get(mc_inst.getOpcode()).hasDelaySlot();
}
DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) :
@@ -586,13 +604,12 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
m_flavor.assign("default");
}
- const char *triple = arch.GetTriple().getTriple().c_str();
unsigned flavor = ~0U;
+ llvm::Triple triple = arch.GetTriple();
// So far the only supported flavor is "intel" on x86. The base class will set this
// correctly coming in.
- if (arch.GetTriple().getArch() == llvm::Triple::x86
- || arch.GetTriple().getArch() == llvm::Triple::x86_64)
+ if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
{
if (m_flavor == "intel")
{
@@ -605,7 +622,7 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
}
ArchSpec thumb_arch(arch);
- if (arch.GetTriple().getArch() == llvm::Triple::arm)
+ if (triple.getArch() == llvm::Triple::arm)
{
std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str());
// Replace "arm" with "thumb" so we get all thumb variants correct
@@ -621,18 +638,29 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str()));
}
+ // If no sub architecture specified then use the most recent arm architecture so the
+ // disassembler will return all instruction. Without it we will see a lot of unknow opcode
+ // in case the code uses instructions which are not available in the oldest arm version
+ // (used when no sub architecture is specified)
+ if (triple.getArch() == llvm::Triple::arm && triple.getSubArch() == llvm::Triple::NoSubArch)
+ triple.setArchName("armv8.1a");
+
+ const char *triple_str = triple.getTriple().c_str();
+
+ // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
+ //
// Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions,
// so hardcode the primary disassembler to thumb mode. Same for Cortex-M4 (armv7em).
//
// Handle the Cortex-M0 (armv6m) the same; the ISA is a subset of the T and T32
// instructions defined in ARMv7-A.
- if (arch.GetTriple().getArch() == llvm::Triple::arm
+ if ((triple.getArch() == llvm::Triple::arm || triple.getArch() == llvm::Triple::thumb)
&& (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m
|| arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em
|| arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m))
{
- triple = thumb_arch.GetTriple().getTriple().c_str();
+ triple_str = thumb_arch.GetTriple().getTriple().c_str();
}
const char *cpu = "";
@@ -674,8 +702,8 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
}
std::string features_str = "";
- if (arch.GetTriple().getArch() == llvm::Triple::mips || arch.GetTriple().getArch() == llvm::Triple::mipsel
- || arch.GetTriple().getArch() == llvm::Triple::mips64 || arch.GetTriple().getArch() == llvm::Triple::mips64el)
+ if (triple.getArch() == llvm::Triple::mips || triple.getArch() == llvm::Triple::mipsel
+ || triple.getArch() == llvm::Triple::mips64 || triple.getArch() == llvm::Triple::mips64el)
{
uint32_t arch_flags = arch.GetFlags ();
if (arch_flags & ArchSpec::eMIPSAse_msa)
@@ -684,13 +712,9 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
features_str += "+dsp,";
if (arch_flags & ArchSpec::eMIPSAse_dspr2)
features_str += "+dspr2,";
- if (arch_flags & ArchSpec::eMIPSAse_mips16)
- features_str += "+mips16,";
- if (arch_flags & ArchSpec::eMIPSAse_micromips)
- features_str += "+micromips,";
}
- m_disasm_ap.reset (new LLVMCDisassembler(triple, cpu, features_str.c_str(), flavor, *this));
+ m_disasm_ap.reset (new LLVMCDisassembler(triple_str, cpu, features_str.c_str(), flavor, *this));
if (!m_disasm_ap->IsValid())
{
// We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason,
@@ -698,8 +722,10 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
m_disasm_ap.reset();
}
+ llvm::Triple::ArchType llvm_arch = triple.getArch();
+
// For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler.
- if (arch.GetTriple().getArch() == llvm::Triple::arm)
+ if (llvm_arch == llvm::Triple::arm)
{
std::string thumb_triple(thumb_arch.GetTriple().getTriple());
m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), "", "", flavor, *this));
@@ -709,10 +735,40 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
m_alternate_disasm_ap.reset();
}
}
+ else if (llvm_arch == llvm::Triple::mips
+ || llvm_arch == llvm::Triple::mipsel
+ || llvm_arch == llvm::Triple::mips64
+ || llvm_arch == llvm::Triple::mips64el)
+ {
+ /* Create alternate disassembler for MIPS16 and microMIPS */
+ uint32_t arch_flags = arch.GetFlags ();
+ if (arch_flags & ArchSpec::eMIPSAse_mips16)
+ features_str += "+mips16,";
+ else if (arch_flags & ArchSpec::eMIPSAse_micromips)
+ features_str += "+micromips,";
+
+ m_alternate_disasm_ap.reset(new LLVMCDisassembler (triple_str, cpu, features_str.c_str(), flavor, *this));
+ if (!m_alternate_disasm_ap->IsValid())
+ {
+ m_disasm_ap.reset();
+ m_alternate_disasm_ap.reset();
+ }
+ }
}
-DisassemblerLLVMC::~DisassemblerLLVMC()
+DisassemblerLLVMC::~DisassemblerLLVMC() = default;
+
+Disassembler *
+DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
{
+ if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch)
+ {
+ std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor));
+
+ if (disasm_ap.get() && disasm_ap->IsValid())
+ return disasm_ap.release();
+ }
+ return NULL;
}
size_t
@@ -817,6 +873,24 @@ const char *DisassemblerLLVMC::SymbolLookupCallback (void *disassembler,
name);
}
+bool
+DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor)
+{
+ llvm::Triple triple = arch.GetTriple();
+ if (flavor == NULL || strcmp (flavor, "default") == 0)
+ return true;
+
+ if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
+ {
+ if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0)
+ return true;
+ else
+ return false;
+ }
+ else
+ return false;
+}
+
int DisassemblerLLVMC::OpInfo (uint64_t PC,
uint64_t Offset,
uint64_t Size,
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
index 56cec03..6359146 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
@@ -10,10 +10,20 @@
#ifndef liblldb_DisassemblerLLVMC_h_
#define liblldb_DisassemblerLLVMC_h_
+// C Includes
+// C++ Includes
+#include <memory>
#include <string>
+// Other libraries and framework includes
#include "llvm-c/Disassembler.h"
+// Project includes
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/Mutex.h"
+
// Opaque references to C++ Objects in LLVM's MC.
namespace llvm
{
@@ -25,12 +35,7 @@ namespace llvm
class MCInstPrinter;
class MCAsmInfo;
class MCSubtargetInfo;
-}
-
-#include "lldb/Core/Address.h"
-#include "lldb/Core/Disassembler.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Host/Mutex.h"
+} // namespace llvm
class InstructionLLVMC;
@@ -46,9 +51,10 @@ class DisassemblerLLVMC : public lldb_private::Disassembler
~LLVMCDisassembler();
uint64_t GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst);
- uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len);
+ void PrintMCInst (llvm::MCInst &mc_inst, std::string &inst_string, std::string &comments_string);
void SetStyle (bool use_hex_immed, HexImmediateStyle hex_style);
bool CanBranch (llvm::MCInst &mc_inst);
+ bool HasDelaySlot (llvm::MCInst &mc_inst);
bool IsValid()
{
return m_is_valid;
@@ -66,6 +72,10 @@ class DisassemblerLLVMC : public lldb_private::Disassembler
};
public:
+ DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */);
+
+ ~DisassemblerLLVMC() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -81,33 +91,28 @@ public:
static lldb_private::Disassembler *
CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor);
- DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */);
-
- virtual
- ~DisassemblerLLVMC();
-
- virtual size_t
- DecodeInstructions (const lldb_private::Address &base_addr,
- const lldb_private::DataExtractor& data,
- lldb::offset_t data_offset,
- size_t num_instructions,
- bool append,
- bool data_from_file);
+ size_t
+ DecodeInstructions(const lldb_private::Address &base_addr,
+ const lldb_private::DataExtractor& data,
+ lldb::offset_t data_offset,
+ size_t num_instructions,
+ bool append,
+ bool data_from_file) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
protected:
friend class InstructionLLVMC;
- virtual bool
- FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor);
+ bool
+ FlavorValidForArchSpec(const lldb_private::ArchSpec &arch, const char *flavor) override;
bool
IsValid()
@@ -163,4 +168,4 @@ protected:
std::unique_ptr<LLVMCDisassembler> m_alternate_disasm_ap;
};
-#endif // liblldb_DisassemblerLLVM_h_
+#endif // liblldb_DisassemblerLLVM_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
index 2308129..2849317 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
@@ -104,11 +104,6 @@ DynamicLoaderHexagonDYLD::GetPluginDescriptionStatic()
"loads/unloads in Hexagon processes.";
}
-void
-DynamicLoaderHexagonDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
-{
-}
-
uint32_t
DynamicLoaderHexagonDYLD::GetPluginVersion()
{
@@ -177,7 +172,7 @@ DynamicLoaderHexagonDYLD::DidAttach()
// Map the loaded sections of this executable
if ( load_offset != LLDB_INVALID_ADDRESS )
- UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);
// AD: confirm this?
// Load into LLDB all of the currently loaded executables in the stub
@@ -248,18 +243,6 @@ DynamicLoaderHexagonDYLD::GetTargetExecutable()
return executable;
}
-Error
-DynamicLoaderHexagonDYLD::ExecutePluginCommand(Args &command, Stream *strm)
-{
- return Error();
-}
-
-Log *
-DynamicLoaderHexagonDYLD::EnablePluginLogging(Stream *strm, Args &command)
-{
- return NULL;
-}
-
//AD: Needs to be updated?
Error
DynamicLoaderHexagonDYLD::CanLoadImage()
@@ -268,7 +251,10 @@ DynamicLoaderHexagonDYLD::CanLoadImage()
}
void
-DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
+DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
Target &target = m_process->GetTarget();
const SectionList *sections = GetSectionListFromModule(module);
@@ -442,7 +428,7 @@ DynamicLoaderHexagonDYLD::RefreshModules()
for (I = m_rendezvous.loaded_begin(); I != E; ++I)
{
FileSpec file(I->path.c_str(), true);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
loaded_modules.AppendIfNeeded( module_sp );
@@ -571,7 +557,7 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules()
{
const char *module_path = I->path.c_str();
FileSpec file(module_path, false);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
module_list.Append(module_sp);
@@ -591,7 +577,10 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules()
/// Helper for the entry breakpoint callback. Resolves the load addresses
/// of all dependent modules.
ModuleSP
-DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr)
+DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
Target &target = m_process->GetTarget();
ModuleList &modules = target.GetImages();
@@ -602,12 +591,12 @@ DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_
// check if module is currently loaded
if ((module_sp = modules.FindFirstModule (module_spec)))
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, true);
}
// try to load this module from disk
else if ((module_sp = target.GetSharedModule(module_spec)))
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, true);
}
return module_sp;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
index aafa385..e10d4ee 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
@@ -7,12 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_DynamicLoaderHexagon_H_
-#define liblldb_DynamicLoaderHexagon_H_
+#ifndef liblldb_DynamicLoaderHexagonDYLD_h_
+#define liblldb_DynamicLoaderHexagonDYLD_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
+// Project includes
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Target/DynamicLoader.h"
@@ -21,6 +22,9 @@
class DynamicLoaderHexagonDYLD : public lldb_private::DynamicLoader
{
public:
+ DynamicLoaderHexagonDYLD(lldb_private::Process *process);
+
+ ~DynamicLoaderHexagonDYLD() override;
static void
Initialize();
@@ -37,48 +41,34 @@ public:
static lldb_private::DynamicLoader *
CreateInstance(lldb_private::Process *process, bool force);
- DynamicLoaderHexagonDYLD(lldb_private::Process *process);
-
- virtual
- ~DynamicLoaderHexagonDYLD();
-
//------------------------------------------------------------------
// DynamicLoader protocol
//------------------------------------------------------------------
- virtual void
- DidAttach();
+ void
+ DidAttach() override;
- virtual void
- DidLaunch();
+ void
+ DidLaunch() override;
- virtual lldb::ThreadPlanSP
+ lldb::ThreadPlanSP
GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
- bool stop_others);
+ bool stop_others) override;
- virtual lldb_private::Error
- CanLoadImage();
+ lldb_private::Error
+ CanLoadImage() override;
- virtual lldb::addr_t
- GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread);
+ lldb::addr_t
+ GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
-
- virtual void
- GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
-
- virtual lldb_private::Error
- ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
-
- virtual lldb_private::Log *
- EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
+ uint32_t
+ GetPluginVersion() override;
protected:
/// Runtime linker rendezvous structure.
@@ -124,18 +114,22 @@ protected:
void
UpdateLoadedSections(lldb::ModuleSP module,
lldb::addr_t link_map_addr,
- lldb::addr_t base_addr);
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset) override;
/// Removes the loaded sections from the target in @p module.
///
/// @param module The module to traverse.
void
- UnloadSections(const lldb::ModuleSP module);
+ UnloadSections(const lldb::ModuleSP module) override;
/// Locates or creates a module given by @p file and updates/loads the
/// resulting module at the virtual base address @p base_addr.
lldb::ModuleSP
- LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr);
+ LoadModuleAtAddress(const lldb_private::FileSpec &file,
+ lldb::addr_t link_map_addr,
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset) override;
/// Callback routine invoked when we hit the breakpoint on process entry.
///
@@ -173,10 +167,10 @@ protected:
FindRendezvousBreakpointAddress( );
private:
- DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD);
-
const lldb_private::SectionList *
GetSectionListFromModule(const lldb::ModuleSP module) const;
+
+ DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD);
};
-#endif // liblldb_DynamicLoaderHexagonDYLD_H_
+#endif // liblldb_DynamicLoaderHexagonDYLD_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index 8b1dd28..443f97e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -17,6 +17,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -106,6 +107,7 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
m_rendezvous_addr(LLDB_INVALID_ADDRESS),
m_current(),
m_previous(),
+ m_loaded_modules(),
m_soentries(),
m_added_soentries(),
m_removed_soentries()
@@ -180,6 +182,9 @@ DYLDRendezvous::Resolve()
m_previous = m_current;
m_current = info;
+ if (UpdateSOEntries (true))
+ return true;
+
return UpdateSOEntries();
}
@@ -190,18 +195,23 @@ DYLDRendezvous::IsValid()
}
bool
-DYLDRendezvous::UpdateSOEntries()
+DYLDRendezvous::UpdateSOEntries(bool fromRemote)
{
SOEntry entry;
+ LoadedModuleInfoList module_list;
- if (m_current.map_addr == 0)
+ // If we can't get the SO info from the remote, return failure.
+ if (fromRemote && m_process->LoadModules (module_list) == 0)
+ return false;
+
+ if (!fromRemote && m_current.map_addr == 0)
return false;
// When the previous and current states are consistent this is the first
// time we have been asked to update. Just take a snapshot of the currently
// loaded modules.
- if (m_previous.state == eConsistent && m_current.state == eConsistent)
- return TakeSnapshot(m_soentries);
+ if (m_previous.state == eConsistent && m_current.state == eConsistent)
+ return fromRemote ? SaveSOEntriesFromRemote(module_list) : TakeSnapshot(m_soentries);
// If we are about to add or remove a shared object clear out the current
// state and take a snapshot of the currently loaded images.
@@ -214,6 +224,9 @@ DYLDRendezvous::UpdateSOEntries()
return false;
m_soentries.clear();
+ if (fromRemote)
+ return SaveSOEntriesFromRemote(module_list);
+
m_added_soentries.clear();
m_removed_soentries.clear();
return TakeSnapshot(m_soentries);
@@ -223,15 +236,133 @@ DYLDRendezvous::UpdateSOEntries()
// Otherwise check the previous state to determine what to expect and update
// accordingly.
if (m_previous.state == eAdd)
- return UpdateSOEntriesForAddition();
+ return fromRemote ? AddSOEntriesFromRemote(module_list) : AddSOEntries();
else if (m_previous.state == eDelete)
- return UpdateSOEntriesForDeletion();
+ return fromRemote ? RemoveSOEntriesFromRemote(module_list) : RemoveSOEntries();
return false;
}
-
+
+bool
+DYLDRendezvous::FillSOEntryFromModuleInfo (LoadedModuleInfoList::LoadedModuleInfo const & modInfo,
+ SOEntry &entry)
+{
+ addr_t link_map_addr;
+ addr_t base_addr;
+ addr_t dyn_addr;
+ std::string name;
+
+ if (!modInfo.get_link_map (link_map_addr) ||
+ !modInfo.get_base (base_addr) ||
+ !modInfo.get_dynamic (dyn_addr) ||
+ !modInfo.get_name (name))
+ return false;
+
+ entry.link_addr = link_map_addr;
+ entry.base_addr = base_addr;
+ entry.dyn_addr = dyn_addr;
+
+ entry.file_spec.SetFile(name, false);
+
+ UpdateBaseAddrIfNecessary(entry, name);
+
+ // not needed if we're using ModuleInfos
+ entry.next = 0;
+ entry.prev = 0;
+ entry.path_addr = 0;
+
+ return true;
+}
+
+bool
+DYLDRendezvous::SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list)
+{
+ for (auto const & modInfo : module_list.m_list)
+ {
+ SOEntry entry;
+ if (!FillSOEntryFromModuleInfo(modInfo, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ if (!SOEntryIsMainExecutable(entry))
+ m_soentries.push_back(entry);
+ }
+
+ m_loaded_modules = module_list;
+ return true;
+
+}
+
+bool
+DYLDRendezvous::AddSOEntriesFromRemote(LoadedModuleInfoList &module_list)
+{
+ for (auto const & modInfo : module_list.m_list)
+ {
+ bool found = false;
+ for (auto const & existing : m_loaded_modules.m_list)
+ {
+ if (modInfo == existing)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ SOEntry entry;
+ if (!FillSOEntryFromModuleInfo(modInfo, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ if (!SOEntryIsMainExecutable(entry))
+ m_soentries.push_back(entry);
+ }
+
+ m_loaded_modules = module_list;
+ return true;
+}
+
bool
-DYLDRendezvous::UpdateSOEntriesForAddition()
+DYLDRendezvous::RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list)
+{
+ for (auto const & existing : m_loaded_modules.m_list)
+ {
+ bool found = false;
+ for (auto const & modInfo : module_list.m_list)
+ {
+ if (modInfo == existing)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ SOEntry entry;
+ if (!FillSOEntryFromModuleInfo(existing, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ if (!SOEntryIsMainExecutable(entry))
+ {
+ auto pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
+ if (pos == m_soentries.end())
+ return false;
+
+ m_soentries.erase(pos);
+ }
+ }
+
+ m_loaded_modules = module_list;
+ return true;
+}
+
+bool
+DYLDRendezvous::AddSOEntries()
{
SOEntry entry;
iterator pos;
@@ -262,7 +393,7 @@ DYLDRendezvous::UpdateSOEntriesForAddition()
}
bool
-DYLDRendezvous::UpdateSOEntriesForDeletion()
+DYLDRendezvous::RemoveSOEntries()
{
SOEntryList entry_list;
iterator pos;
@@ -290,19 +421,14 @@ DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry)
// FreeBSD and on Android it is the full path to the executable.
auto triple = m_process->GetTarget().GetArchitecture().GetTriple();
- auto os_type = triple.getOS();
- auto env_type = triple.getEnvironment();
-
- switch (os_type) {
+ switch (triple.getOS())
+ {
case llvm::Triple::FreeBSD:
return entry.file_spec == m_exe_file_spec;
case llvm::Triple::Linux:
- switch (env_type) {
- case llvm::Triple::Android:
- return entry.file_spec == m_exe_file_spec;
- default:
- return !entry.file_spec;
- }
+ if (triple.isAndroid())
+ return entry.file_spec == m_exe_file_spec;
+ return !entry.file_spec;
default:
return false;
}
@@ -372,6 +498,40 @@ DYLDRendezvous::ReadStringFromMemory(addr_t addr)
return str;
}
+// Returns true if the load bias reported by the linker is incorrect for the given entry. This
+// function is used to handle cases where we want to work around a bug in the system linker.
+static bool
+isLoadBiasIncorrect(Target& target, const std::string& file_path)
+{
+ // On Android L (API 21, 22) the load address of the "/system/bin/linker" isn't filled in
+ // correctly.
+ uint32_t os_major = 0, os_minor = 0, os_update = 0;
+ if (target.GetArchitecture().GetTriple().isAndroid() &&
+ target.GetPlatform()->GetOSVersion(os_major, os_minor, os_update) &&
+ (os_major == 21 || os_major == 22) &&
+ (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64"))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+void
+DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path)
+{
+ // If the load bias reported by the linker is incorrect then fetch the load address of the file
+ // from the proc file system.
+ if (isLoadBiasIncorrect(m_process->GetTarget(), file_path))
+ {
+ lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
+ bool is_loaded = false;
+ Error error = m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
+ if (error.Success() && is_loaded)
+ entry.base_addr = load_addr;
+ }
+}
+
bool
DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
{
@@ -413,18 +573,7 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
std::string file_path = ReadStringFromMemory(entry.path_addr);
entry.file_spec.SetFile(file_path, false);
- // On Android L (5.0, 5.1) the load address of the "/system/bin/linker" isn't filled in
- // correctly. To get the correct load address we fetch the load address of the file from the
- // proc file system.
- if (arch.GetTriple().getEnvironment() == llvm::Triple::Android && entry.base_addr == 0 &&
- (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64"))
- {
- lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
- bool is_loaded = false;
- Error error = m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
- if (error.Success() && is_loaded)
- entry.base_addr = load_addr;
- }
+ UpdateBaseAddrIfNecessary(entry, file_path);
return true;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index ec5af94..8498116 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -20,6 +20,10 @@
#include "lldb/lldb-types.h"
#include "lldb/Host/FileSpec.h"
+#include "lldb/Core/LoadedModuleInfoList.h"
+
+using lldb_private::LoadedModuleInfoList;
+
namespace lldb_private {
class Process;
}
@@ -201,6 +205,9 @@ protected:
Rendezvous m_current;
Rendezvous m_previous;
+ /// List of currently loaded SO modules
+ LoadedModuleInfoList m_loaded_modules;
+
/// List of SOEntry objects corresponding to the current link map state.
SOEntryList m_soentries;
@@ -240,13 +247,29 @@ protected:
/// Updates the current set of SOEntries, the set of added entries, and the
/// set of removed entries.
bool
- UpdateSOEntries();
+ UpdateSOEntries(bool fromRemote = false);
+
+ bool
+ FillSOEntryFromModuleInfo (LoadedModuleInfoList::LoadedModuleInfo const & modInfo,
+ SOEntry &entry);
+
+ bool
+ SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list);
bool
- UpdateSOEntriesForAddition();
+ AddSOEntriesFromRemote(LoadedModuleInfoList &module_list);
bool
- UpdateSOEntriesForDeletion();
+ RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list);
+
+ bool
+ AddSOEntries();
+
+ bool
+ RemoveSOEntries();
+
+ void
+ UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path);
bool
SOEntryIsMainExecutable(const SOEntry &entry);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 8724fc0..6ba7b47 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -62,11 +62,6 @@ DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic()
"loads/unloads in POSIX processes.";
}
-void
-DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
-{
-}
-
uint32_t
DynamicLoaderPOSIXDYLD::GetPluginVersion()
{
@@ -96,7 +91,8 @@ DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process)
m_load_offset(LLDB_INVALID_ADDRESS),
m_entry_point(LLDB_INVALID_ADDRESS),
m_auxv(),
- m_dyld_bid(LLDB_INVALID_BREAK_ID)
+ m_dyld_bid(LLDB_INVALID_BREAK_ID),
+ m_vdso_base(LLDB_INVALID_ADDRESS)
{
}
@@ -131,6 +127,8 @@ DynamicLoaderPOSIXDYLD::DidAttach()
if (log)
log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " executable '%s', load_offset 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp ? executable_sp->GetFileSpec().GetPath().c_str () : "<null executable>", load_offset);
+ EvalVdsoStatus();
+
// if we dont have a load address we cant re-base
bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true;
@@ -165,7 +163,7 @@ DynamicLoaderPOSIXDYLD::DidAttach()
m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID,
executable_sp->GetFileSpec().GetPath().c_str ());
- UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset);
+ UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, true);
// When attaching to a target, there are two possible states:
// (1) We already crossed the entry point and therefore the rendezvous
@@ -218,12 +216,13 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
executable = GetTargetExecutable();
load_offset = ComputeLoadOffset();
+ EvalVdsoStatus();
if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)
{
ModuleList module_list;
module_list.Append(executable);
- UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);
if (log)
log->Printf ("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", __FUNCTION__);
@@ -234,29 +233,19 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
}
Error
-DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm)
-{
- return Error();
-}
-
-Log *
-DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command)
-{
- return NULL;
-}
-
-Error
DynamicLoaderPOSIXDYLD::CanLoadImage()
{
return Error();
}
void
-DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
+DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
m_loaded_modules[module] = link_map_addr;
-
- UpdateLoadedSectionsCommon(module, base_addr);
+ UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
}
void
@@ -414,7 +403,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
E = m_rendezvous.loaded_end();
for (I = m_rendezvous.loaded_begin(); I != E; ++I)
{
- ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
loaded_modules.AppendIfNeeded(module_sp);
@@ -432,8 +421,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
{
ModuleSpec module_spec{I->file_spec};
- ModuleSP module_sp =
- loaded_modules.FindFirstModule (module_spec);
+ ModuleSP module_sp = loaded_modules.FindFirstModule (module_spec);
if (module_sp.get())
{
@@ -519,11 +507,18 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
// that ourselves here.
ModuleSP executable = GetTargetExecutable();
m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
-
-
+ if (m_vdso_base != LLDB_INVALID_ADDRESS)
+ {
+ FileSpec file_spec("[vdso]", false);
+ ModuleSP module_sp = LoadModuleAtAddress(file_spec, LLDB_INVALID_ADDRESS, m_vdso_base, false);
+ if (module_sp.get())
+ {
+ module_list.Append(module_sp);
+ }
+ }
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
{
- ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
module_list.Append(module_sp);
@@ -568,6 +563,16 @@ DynamicLoaderPOSIXDYLD::ComputeLoadOffset()
return m_load_offset;
}
+void
+DynamicLoaderPOSIXDYLD::EvalVdsoStatus()
+{
+ AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_SYSINFO_EHDR);
+
+ if (I != m_auxv->end())
+ m_vdso_base = I->value;
+
+}
+
addr_t
DynamicLoaderPOSIXDYLD::GetEntryPoint()
{
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index 68d3059..cb97bbf 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -1,4 +1,4 @@
-//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===//
+//===-- DynamicLoaderPOSIXDYLD.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_DynamicLoaderPOSIX_H_
-#define liblldb_DynamicLoaderPOSIX_H_
+#ifndef liblldb_DynamicLoaderPOSIXDYLD_h_
+#define liblldb_DynamicLoaderPOSIXDYLD_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
+// Project includes
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Target/DynamicLoader.h"
@@ -23,6 +24,9 @@ class AuxVector;
class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader
{
public:
+ DynamicLoaderPOSIXDYLD(lldb_private::Process *process);
+
+ ~DynamicLoaderPOSIXDYLD() override;
static void
Initialize();
@@ -39,48 +43,34 @@ public:
static lldb_private::DynamicLoader *
CreateInstance(lldb_private::Process *process, bool force);
- DynamicLoaderPOSIXDYLD(lldb_private::Process *process);
-
- virtual
- ~DynamicLoaderPOSIXDYLD();
-
//------------------------------------------------------------------
// DynamicLoader protocol
//------------------------------------------------------------------
- virtual void
- DidAttach();
+ void
+ DidAttach() override;
- virtual void
- DidLaunch();
+ void
+ DidLaunch() override;
- virtual lldb::ThreadPlanSP
+ lldb::ThreadPlanSP
GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
- bool stop_others);
+ bool stop_others) override;
- virtual lldb_private::Error
- CanLoadImage();
+ lldb_private::Error
+ CanLoadImage() override;
- virtual lldb::addr_t
- GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread);
+ lldb::addr_t
+ GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
-
- virtual uint32_t
- GetPluginVersion();
-
- virtual void
- GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual lldb_private::Error
- ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
-
- virtual lldb_private::Log *
- EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
+ uint32_t
+ GetPluginVersion() override;
protected:
/// Runtime linker rendezvous structure.
@@ -98,12 +88,16 @@ protected:
/// Rendezvous breakpoint.
lldb::break_id_t m_dyld_bid;
+ /// Contains AT_SYSINFO_EHDR, which means a vDSO has been
+ /// mapped to the address space
+ lldb::addr_t m_vdso_base;
+
/// Loaded module list. (link map for each module)
std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> m_loaded_modules;
/// Enables a breakpoint on a function called by the runtime
/// linker each time a module is loaded or unloaded.
- void
+ virtual void
SetRendezvousBreakpoint();
/// Callback routine which updates the current list of loaded modules based
@@ -126,16 +120,17 @@ protected:
/// @param link_map_addr The virtual address of the link map for the @p module.
///
/// @param base_addr The virtual base address @p module is loaded at.
- virtual void
+ void
UpdateLoadedSections(lldb::ModuleSP module,
lldb::addr_t link_map_addr,
- lldb::addr_t base_addr);
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset) override;
/// Removes the loaded sections from the target in @p module.
///
/// @param module The module to traverse.
- virtual void
- UnloadSections(const lldb::ModuleSP module);
+ void
+ UnloadSections(const lldb::ModuleSP module) override;
/// Resolves the entry point for the current inferior process and sets a
/// breakpoint at that address.
@@ -155,7 +150,7 @@ protected:
/// Helper for the entry breakpoint callback. Resolves the load addresses
/// of all dependent modules.
- void
+ virtual void
LoadAllCurrentModules();
/// Computes a value for m_load_offset returning the computed address on
@@ -168,6 +163,11 @@ protected:
lldb::addr_t
GetEntryPoint();
+ /// Evaluate if Aux vectors contain vDSO information
+ /// in case they do, read and assign the address to m_vdso_base
+ void
+ EvalVdsoStatus();
+
/// Loads Module from inferior process.
void
ResolveExecutableModule(lldb::ModuleSP &module_sp);
@@ -176,4 +176,4 @@ private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);
};
-#endif // liblldb_DynamicLoaderPOSIXDYLD_H_
+#endif // liblldb_DynamicLoaderPOSIXDYLD_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
index ea33164..a7fdf4d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
@@ -12,12 +12,8 @@
// C Includes
// C++ Includes
-#include <map>
-#include <vector>
-#include <string>
-
// Other libraries and framework includes
-
+// Project includes
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/UUID.h"
@@ -27,6 +23,10 @@
class DynamicLoaderStatic : public lldb_private::DynamicLoader
{
public:
+ DynamicLoaderStatic(lldb_private::Process *process);
+
+ ~DynamicLoaderStatic() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -45,37 +45,33 @@ public:
static lldb_private::DynamicLoader *
CreateInstance (lldb_private::Process *process, bool force);
- DynamicLoaderStatic (lldb_private::Process *process);
-
- virtual
- ~DynamicLoaderStatic ();
//------------------------------------------------------------------
/// Called after attaching a process.
///
/// Allow DynamicLoader plug-ins to execute some code after
/// attaching to a process.
//------------------------------------------------------------------
- virtual void
- DidAttach ();
+ void
+ DidAttach() override;
- virtual void
- DidLaunch ();
+ void
+ DidLaunch() override;
- virtual lldb::ThreadPlanSP
- GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
- bool stop_others);
+ lldb::ThreadPlanSP
+ GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
+ bool stop_others) override;
- virtual lldb_private::Error
- CanLoadImage ();
+ lldb_private::Error
+ CanLoadImage() override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
private:
void
@@ -84,4 +80,4 @@ private:
DISALLOW_COPY_AND_ASSIGN (DynamicLoaderStatic);
};
-#endif // liblldb_DynamicLoaderStatic_h_
+#endif // liblldb_DynamicLoaderStatic_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
index 56b56ab..dd391b4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
@@ -21,40 +21,39 @@ using namespace lldb_private;
DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process)
: DynamicLoader(process)
{
-
}
DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD()
{
-
}
-void DynamicLoaderWindowsDYLD::Initialize()
+void
+DynamicLoaderWindowsDYLD::Initialize()
{
- PluginManager::RegisterPlugin(GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance);
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance);
}
-void DynamicLoaderWindowsDYLD::Terminate()
+void
+DynamicLoaderWindowsDYLD::Terminate()
{
-
}
-ConstString DynamicLoaderWindowsDYLD::GetPluginNameStatic()
+ConstString
+DynamicLoaderWindowsDYLD::GetPluginNameStatic()
{
static ConstString g_plugin_name("windows-dyld");
return g_plugin_name;
}
-const char *DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic()
+const char *
+DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic()
{
return "Dynamic loader plug-in that watches for shared library "
"loads/unloads in Windows processes.";
}
-
-DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force)
+DynamicLoader *
+DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force)
{
bool should_create = force;
if (!should_create)
@@ -65,32 +64,35 @@ DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool f
}
if (should_create)
- return new DynamicLoaderWindowsDYLD (process);
+ return new DynamicLoaderWindowsDYLD(process);
return nullptr;
}
-void DynamicLoaderWindowsDYLD::DidAttach()
+void
+DynamicLoaderWindowsDYLD::DidAttach()
{
-
}
-void DynamicLoaderWindowsDYLD::DidLaunch()
+void
+DynamicLoaderWindowsDYLD::DidLaunch()
{
-
}
-Error DynamicLoaderWindowsDYLD::CanLoadImage()
+Error
+DynamicLoaderWindowsDYLD::CanLoadImage()
{
return Error();
}
-ConstString DynamicLoaderWindowsDYLD::GetPluginName()
+ConstString
+DynamicLoaderWindowsDYLD::GetPluginName()
{
return GetPluginNameStatic();
}
-uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion()
+uint32_t
+DynamicLoaderWindowsDYLD::GetPluginVersion()
{
return 1;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h
index d12b999..8c47981 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h
@@ -1,4 +1,4 @@
-//===-- DynamicLoaderWindowsDYLDh ----------------------------------*- C++ -*-===//
+//===-- DynamicLoaderWindowsDYLD.h ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,9 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_
-#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_
+#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_
+#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-forward.h"
#include "lldb/Target/DynamicLoader.h"
@@ -18,9 +22,10 @@ namespace lldb_private
class DynamicLoaderWindowsDYLD : public DynamicLoader
{
- public:
+public:
DynamicLoaderWindowsDYLD(Process *process);
- virtual ~DynamicLoaderWindowsDYLD();
+
+ ~DynamicLoaderWindowsDYLD() override;
static void Initialize();
static void Terminate();
@@ -29,15 +34,15 @@ class DynamicLoaderWindowsDYLD : public DynamicLoader
static DynamicLoader *CreateInstance(Process *process, bool force);
- void DidAttach () override;
- void DidLaunch () override;
- Error CanLoadImage () override;
+ void DidAttach() override;
+ void DidLaunch() override;
+ Error CanLoadImage() override;
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop) override;
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_
diff --git a/contrib/llvm/tools/lldb/source/Expression/ASTDumper.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp
index 5210d14..9763106 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ASTDumper.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp
@@ -7,9 +7,11 @@
//
//===----------------------------------------------------------------------===//
+#include "ASTDumper.h"
+
#include "lldb/Core/Log.h"
-#include "lldb/Expression/ASTDumper.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompilerType.h"
#include "llvm/Support/raw_ostream.h"
@@ -74,14 +76,14 @@ ASTDumper::ASTDumper (clang::QualType type)
m_dump = type.getAsString();
}
-ASTDumper::ASTDumper (lldb::clang_type_t type)
+ASTDumper::ASTDumper (lldb::opaque_compiler_type_t type)
{
m_dump = clang::QualType::getFromOpaquePtr(type).getAsString();
}
-ASTDumper::ASTDumper (const ClangASTType &clang_type)
+ASTDumper::ASTDumper (const CompilerType &compiler_type)
{
- m_dump = clang_type.GetQualType().getAsString();
+ m_dump = ClangASTContext::GetQualType(compiler_type).getAsString();
}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ASTDumper.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h
index 47f7ea4..c8dc684 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ASTDumper.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h
@@ -11,7 +11,6 @@
#define liblldb_ASTDumper_h_
#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeVisitor.h"
#include "lldb/Core/Stream.h"
@@ -27,8 +26,8 @@ public:
ASTDumper (clang::DeclContext *decl_ctx);
ASTDumper (const clang::Type *type);
ASTDumper (clang::QualType type);
- ASTDumper (lldb::clang_type_t type);
- ASTDumper (const ClangASTType &clang_type);
+ ASTDumper (lldb::opaque_compiler_type_t type);
+ ASTDumper (const CompilerType &compiler_type);
const char *GetCString();
void ToSTDERR();
diff --git a/contrib/llvm/tools/lldb/source/Expression/ASTResultSynthesizer.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
index c3d42cb..02505bd 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ASTResultSynthesizer.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+#include "ASTResultSynthesizer.h"
+
+#include "ClangPersistentVariables.h"
+
#include "stdlib.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -20,8 +24,6 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "lldb/Core/Log.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Expression/ASTResultSynthesizer.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Target/Target.h"
@@ -462,7 +464,7 @@ ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D)
D);
if (TypeDecl *TypeDecl_scratch = dyn_cast<TypeDecl>(D_scratch))
- m_target.GetPersistentVariables().RegisterPersistentType(name_cs, TypeDecl_scratch);
+ llvm::cast<ClangPersistentVariables>(m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->RegisterPersistentType(name_cs, TypeDecl_scratch);
}
void
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ASTResultSynthesizer.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
index 410a862..9f7bbe0 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ASTResultSynthesizer.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
@@ -12,7 +12,7 @@
#include "clang/Sema/SemaConsumer.h"
#include "lldb/Core/ClangForward.h"
-#include "lldb/Symbol/TaggedASTType.h"
+#include "lldb/Target/Target.h"
namespace lldb_private {
@@ -51,7 +51,7 @@ public:
//----------------------------------------------------------------------
/// Destructor
//----------------------------------------------------------------------
- ~ASTResultSynthesizer();
+ ~ASTResultSynthesizer() override;
//----------------------------------------------------------------------
/// Link this consumer with a particular AST context
@@ -60,7 +60,7 @@ public:
/// This AST context will be used for types and identifiers, and also
/// forwarded to the passthrough consumer, if one exists.
//----------------------------------------------------------------------
- void Initialize(clang::ASTContext &Context);
+ void Initialize(clang::ASTContext &Context) override;
//----------------------------------------------------------------------
/// Examine a list of Decls to find the function $__lldb_expr and
@@ -71,32 +71,32 @@ public:
/// which need to be searched recursively. That job falls to
/// TransformTopLevelDecl.
//----------------------------------------------------------------------
- bool HandleTopLevelDecl(clang::DeclGroupRef D);
+ bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
- void HandleTranslationUnit(clang::ASTContext &Ctx);
+ void HandleTranslationUnit(clang::ASTContext &Ctx) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
- void HandleTagDeclDefinition(clang::TagDecl *D);
+ void HandleTagDeclDefinition(clang::TagDecl *D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
- void CompleteTentativeDefinition(clang::VarDecl *D);
+ void CompleteTentativeDefinition(clang::VarDecl *D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
- void HandleVTable(clang::CXXRecordDecl *RD);
+ void HandleVTable(clang::CXXRecordDecl *RD) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
- void PrintStats();
+ void PrintStats() override;
//----------------------------------------------------------------------
/// Set the Sema object to use when performing transforms, and pass it on
@@ -105,12 +105,13 @@ public:
/// The Sema to use. Because Sema isn't externally visible, this class
/// casts it to an Action for actual use.
//----------------------------------------------------------------------
- void InitializeSema(clang::Sema &S);
+ void InitializeSema(clang::Sema &S) override;
//----------------------------------------------------------------------
/// Reset the Sema to NULL now that transformations are done
//----------------------------------------------------------------------
- void ForgetSema();
+ void ForgetSema() override;
+
private:
//----------------------------------------------------------------------
/// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing
@@ -179,6 +180,6 @@ private:
clang::Sema *m_sema; ///< The Sema to use.
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_ASTResultSynthesizer_h_
diff --git a/contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
index 98628db..38a2b6b 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ASTStructExtractor.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "ASTStructExtractor.h"
+
#include "stdlib.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -20,7 +22,6 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "lldb/Core/Log.h"
-#include "lldb/Expression/ASTStructExtractor.h"
using namespace llvm;
using namespace clang;
@@ -28,7 +29,7 @@ using namespace lldb_private;
ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
const char *struct_name,
- ClangFunction &function) :
+ ClangFunctionCaller &function) :
m_ast_context (NULL),
m_passthrough (passthrough),
m_passthrough_sema (NULL),
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ASTStructExtractor.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
index 2519374..2152cff 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ASTStructExtractor.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
@@ -10,10 +10,11 @@
#ifndef liblldb_ASTStructExtractor_h_
#define liblldb_ASTStructExtractor_h_
+#include "ClangExpressionVariable.h"
+#include "ClangFunctionCaller.h"
+
#include "clang/Sema/SemaConsumer.h"
#include "lldb/Core/ClangForward.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangFunction.h"
namespace lldb_private {
@@ -21,9 +22,9 @@ namespace lldb_private {
/// @class ASTStructExtractor ASTStructExtractor.h "lldb/Expression/ASTStructExtractor.h"
/// @brief Extracts and describes the argument structure for a wrapped function.
///
-/// This pass integrates with ClangFunction, which calls functions with custom
+/// This pass integrates with ClangFunctionCaller, which calls functions with custom
/// sets of arguments. To avoid having to implement the full calling convention
-/// for the target's architecture, ClangFunction writes a simple wrapper
+/// for the target's architecture, ClangFunctionCaller writes a simple wrapper
/// function that takes a pointer to an argument structure that contains room
/// for the address of the function to be called, the values of all its
/// arguments, and room for the function's return value.
@@ -49,17 +50,17 @@ public:
///
/// @param[in] function
/// The caller object whose members should be populated with information
- /// about the argument struct. ClangFunction friends ASTStructExtractor
+ /// about the argument struct. ClangFunctionCaller friends ASTStructExtractor
/// for this purpose.
//----------------------------------------------------------------------
ASTStructExtractor(clang::ASTConsumer *passthrough,
const char *struct_name,
- ClangFunction &function);
+ ClangFunctionCaller &function);
//----------------------------------------------------------------------
/// Destructor
//----------------------------------------------------------------------
- virtual ~ASTStructExtractor();
+ ~ASTStructExtractor() override;
//----------------------------------------------------------------------
/// Link this consumer with a particular AST context
@@ -68,7 +69,7 @@ public:
/// This AST context will be used for types and identifiers, and also
/// forwarded to the passthrough consumer, if one exists.
//----------------------------------------------------------------------
- void Initialize(clang::ASTContext &Context);
+ void Initialize(clang::ASTContext &Context) override;
//----------------------------------------------------------------------
/// Examine a list of Decls to find the function $__lldb_expr and
@@ -79,32 +80,32 @@ public:
/// which need to be searched recursively. That job falls to
/// TransformTopLevelDecl.
//----------------------------------------------------------------------
- bool HandleTopLevelDecl(clang::DeclGroupRef D);
+ bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
- void HandleTranslationUnit(clang::ASTContext &Ctx);
+ void HandleTranslationUnit(clang::ASTContext &Ctx) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
- void HandleTagDeclDefinition(clang::TagDecl *D);
+ void HandleTagDeclDefinition(clang::TagDecl *D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
- void CompleteTentativeDefinition(clang::VarDecl *D);
+ void CompleteTentativeDefinition(clang::VarDecl *D) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
- void HandleVTable(clang::CXXRecordDecl *RD);
+ void HandleVTable(clang::CXXRecordDecl *RD) override;
//----------------------------------------------------------------------
/// Passthrough stub
//----------------------------------------------------------------------
- void PrintStats();
+ void PrintStats() override;
//----------------------------------------------------------------------
/// Set the Sema object to use when performing transforms, and pass it on
@@ -113,12 +114,13 @@ public:
/// The Sema to use. Because Sema isn't externally visible, this class
/// casts it to an Action for actual use.
//----------------------------------------------------------------------
- void InitializeSema(clang::Sema &S);
+ void InitializeSema(clang::Sema &S) override;
//----------------------------------------------------------------------
/// Reset the Sema to NULL now that transformations are done
//----------------------------------------------------------------------
- void ForgetSema();
+ void ForgetSema() override;
+
private:
//----------------------------------------------------------------------
/// Hunt the given FunctionDecl for the argument struct and place
@@ -147,10 +149,10 @@ private:
clang::Sema *m_sema; ///< The Sema to use.
clang::Action *m_action; ///< The Sema to use, cast to an Action so it's usable.
- ClangFunction &m_function; ///< The function to populate with information about the argument structure.
+ ClangFunctionCaller &m_function; ///< The function to populate with information about the argument structure.
std::string m_struct_name; ///< The name of the structure to extract.
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_ASTStructExtractor_h_
diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index 3988cd6..d2ea439 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ClangASTSource.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -7,18 +7,18 @@
//
//===----------------------------------------------------------------------===//
+#include "ClangASTSource.h"
+
+#include "ASTDumper.h"
+#include "ClangModulesDeclVendor.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
-#include "lldb/Expression/ASTDumper.h"
-#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/TaggedASTType.h"
@@ -57,7 +57,7 @@ namespace {
ClangASTSource::~ClangASTSource()
{
- m_ast_importer->ForgetDestination(m_ast_context);
+ m_ast_importer_sp->ForgetDestination(m_ast_context);
// We are in the process of destruction, don't create clang ast context on demand
// by passing false to Target::GetScratchClangASTContext(create_on_demand).
@@ -72,7 +72,7 @@ ClangASTSource::~ClangASTSource()
return;
if (m_ast_context != scratch_ast_context)
- m_ast_importer->ForgetSource(scratch_ast_context, m_ast_context);
+ m_ast_importer_sp->ForgetSource(scratch_ast_context, m_ast_context);
}
void
@@ -125,11 +125,10 @@ ClangASTSource::FindExternalVisibleDeclsByName
}
break;
- // Operator names. Not important for now.
+ // Operator names.
case DeclarationName::CXXOperatorName:
case DeclarationName::CXXLiteralOperatorName:
- SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
- return false;
+ break;
// Using directives found in this context.
// Tell Sema we didn't find any or we'll end up getting asked a *lot*.
@@ -222,7 +221,7 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
m_active_lexical_decls.insert(tag_decl);
ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl);
- if (!m_ast_importer->CompleteTagDecl (tag_decl))
+ if (!m_ast_importer_sp->CompleteTagDecl (tag_decl))
{
// We couldn't complete the type. Maybe there's a definition
// somewhere else that can be completed.
@@ -236,7 +235,7 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(decl_ctx))
{
- ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);
+ ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context);
if (log && log->GetVerbose())
log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)",
@@ -253,7 +252,7 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
if (log)
log->Printf(" CTD[%u] Searching namespace %s in module %s",
current_id,
- i->second.GetNamespaceDecl()->getNameAsString().c_str(),
+ i->second.GetName().AsCString(),
i->first->GetFileSpec().GetFilename().GetCString());
TypeList types;
@@ -272,19 +271,19 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
if (!type)
continue;
- ClangASTType clang_type (type->GetClangFullType());
+ CompilerType clang_type (type->GetFullCompilerType ());
if (!clang_type)
continue;
- const TagType *tag_type = clang_type.GetQualType()->getAs<TagType>();
+ const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs<TagType>();
if (!tag_type)
continue;
TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
- if (m_ast_importer->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
+ if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
found = true;
}
}
@@ -295,7 +294,7 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
SymbolContext null_sc;
ConstString name(tag_decl->getName().str().c_str());
- ClangNamespaceDecl namespace_decl;
+ CompilerDeclContext namespace_decl;
const ModuleList &module_list = m_target->GetImages();
@@ -311,19 +310,24 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
if (!type)
continue;
- ClangASTType clang_type (type->GetClangFullType());
+ CompilerType clang_type (type->GetFullCompilerType ());
if (!clang_type)
continue;
- const TagType *tag_type = clang_type.GetQualType()->getAs<TagType>();
+ const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs<TagType>();
if (!tag_type)
continue;
TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
- if (m_ast_importer->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
+ // We have found a type by basename and we need to make sure the decl contexts
+ // are the same before we can try to complete this type with another
+ if (!ClangASTContext::DeclsAreEquivalent (tag_decl, candidate_tag_decl))
+ continue;
+
+ if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
found = true;
}
}
@@ -355,7 +359,7 @@ ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl)
Decl *original_decl = NULL;
ASTContext *original_ctx = NULL;
- if (m_ast_importer->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx))
+ if (m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx))
{
if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl))
{
@@ -363,12 +367,12 @@ ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl)
if (complete_iface_decl && (complete_iface_decl != original_iface_decl))
{
- m_ast_importer->SetDeclOrigin(interface_decl, original_iface_decl);
+ m_ast_importer_sp->SetDeclOrigin(interface_decl, original_iface_decl);
}
}
}
- m_ast_importer->CompleteObjCInterfaceDecl (interface_decl);
+ m_ast_importer_sp->CompleteObjCInterfaceDecl (interface_decl);
if (interface_decl->getSuperClass() &&
interface_decl->getSuperClass() != interface_decl)
@@ -402,8 +406,8 @@ ClangASTSource::GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_de
if (!complete_type_sp)
return NULL;
- TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetClangFullType());
- lldb::clang_type_t complete_opaque_type = complete_type.GetOpaqueQualType();
+ TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetFullCompilerType ());
+ lldb::opaque_compiler_type_t complete_opaque_type = complete_type.GetOpaqueQualType();
if (!complete_opaque_type)
return NULL;
@@ -419,9 +423,9 @@ ClangASTSource::GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_de
return complete_iface_decl;
}
-clang::ExternalLoadResult
+void
ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
- bool (*predicate)(Decl::Kind),
+ llvm::function_ref<bool(Decl::Kind)> predicate,
llvm::SmallVectorImpl<Decl*> &decls)
{
ClangASTMetrics::RegisterLexicalQuery();
@@ -431,11 +435,11 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
const Decl *context_decl = dyn_cast<Decl>(decl_context);
if (!context_decl)
- return ELR_Failure;
+ return;
auto iter = m_active_lexical_decls.find(context_decl);
if (iter != m_active_lexical_decls.end())
- return ELR_Failure;
+ return;
m_active_lexical_decls.insert(context_decl);
ScopedLexicalDeclEraser eraser(m_active_lexical_decls, context_decl);
@@ -445,29 +449,26 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
if (log)
{
if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl))
- log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p with %s predicate",
+ log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p",
current_id, static_cast<void*>(m_ast_context),
context_named_decl->getNameAsString().c_str(),
context_decl->getDeclKindName(),
- static_cast<const void*>(context_decl),
- (predicate ? "non-null" : "null"));
+ static_cast<const void*>(context_decl));
else if(context_decl)
- log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p with %s predicate",
+ log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p",
current_id, static_cast<void*>(m_ast_context),
context_decl->getDeclKindName(),
- static_cast<const void*>(context_decl),
- (predicate ? "non-null" : "null"));
+ static_cast<const void*>(context_decl));
else
- log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context with %s predicate",
- current_id, static_cast<const void*>(m_ast_context),
- (predicate ? "non-null" : "null"));
+ log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context",
+ current_id, static_cast<const void*>(m_ast_context));
}
Decl *original_decl = NULL;
ASTContext *original_ctx = NULL;
- if (!m_ast_importer->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx))
- return ELR_Failure;
+ if (!m_ast_importer_sp->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx))
+ return;
if (log)
{
@@ -486,7 +487,7 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
original_decl = complete_iface_decl;
original_ctx = &complete_iface_decl->getASTContext();
- m_ast_importer->SetDeclOrigin(context_decl, original_iface_decl);
+ m_ast_importer_sp->SetDeclOrigin(context_decl, original_iface_decl);
}
}
@@ -501,7 +502,7 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
const DeclContext *original_decl_context = dyn_cast<DeclContext>(original_decl);
if (!original_decl_context)
- return ELR_Failure;
+ return;
for (TagDecl::decl_iterator iter = original_decl_context->decls_begin();
iter != original_decl_context->decls_end();
@@ -509,7 +510,7 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
{
Decl *decl = *iter;
- if (!predicate || predicate(decl->getKind()))
+ if (predicate(decl->getKind()))
{
if (log)
{
@@ -519,8 +520,8 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
else
log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString());
}
-
- Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, original_ctx, decl);
+
+ Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, original_ctx, decl);
if (!copied_decl)
continue;
@@ -529,11 +530,9 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
{
QualType copied_field_type = copied_field->getType();
- m_ast_importer->RequireCompleteType(copied_field_type);
+ m_ast_importer_sp->RequireCompleteType(copied_field_type);
}
- decls.push_back(copied_decl);
-
DeclContext *decl_context_non_const = const_cast<DeclContext *>(decl_context);
if (copied_decl->getDeclContext() != decl_context)
@@ -548,7 +547,7 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
}
}
- return ELR_AlreadyLoaded;
+ return;
}
void
@@ -587,7 +586,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context)
if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context))
{
- ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);
+ ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context);
if (log && log->GetVerbose())
log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)",
@@ -604,7 +603,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context)
if (log)
log->Printf(" CAS::FEVD[%u] Searching namespace %s in module %s",
current_id,
- i->second.GetNamespaceDecl()->getNameAsString().c_str(),
+ i->second.GetName().AsCString(),
i->first->GetFileSpec().GetFilename().GetCString());
FindExternalVisibleDecls(context,
@@ -624,7 +623,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context)
}
else
{
- ClangNamespaceDecl namespace_decl;
+ CompilerDeclContext namespace_decl;
if (log)
log->Printf(" CAS::FEVD[%u] Searching the root namespace", current_id);
@@ -653,7 +652,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context)
void
ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
lldb::ModuleSP module_sp,
- ClangNamespaceDecl &namespace_decl,
+ CompilerDeclContext &namespace_decl,
unsigned int current_id)
{
assert (m_ast_context);
@@ -681,7 +680,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
if (module_sp && namespace_decl)
{
- ClangNamespaceDecl found_namespace_decl;
+ CompilerDeclContext found_namespace_decl;
SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
@@ -693,7 +692,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
if (found_namespace_decl)
{
- context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(module_sp, found_namespace_decl));
+ context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(module_sp, found_namespace_decl));
if (log)
log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s",
@@ -715,7 +714,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
if (!image)
continue;
- ClangNamespaceDecl found_namespace_decl;
+ CompilerDeclContext found_namespace_decl;
SymbolVendor *symbol_vendor = image->GetSymbolVendor();
@@ -728,7 +727,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
if (found_namespace_decl)
{
- context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(image, found_namespace_decl));
+ context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(image, found_namespace_decl));
if (log)
log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s",
@@ -752,38 +751,42 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
bool found_a_type = false;
- if (types.GetSize())
+ if (size_t num_types = types.GetSize())
{
- lldb::TypeSP type_sp = types.GetTypeAtIndex(0);
-
- if (log)
- {
- const char *name_string = type_sp->GetName().GetCString();
-
- log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s",
- current_id,
- name.GetCString(),
- (name_string ? name_string : "<anonymous>"));
- }
-
- ClangASTType full_type = type_sp->GetClangFullType();
-
- ClangASTType copied_clang_type (GuardedCopyType(full_type));
-
- if (!copied_clang_type)
+ for (size_t ti = 0; ti < num_types; ++ti)
{
+ lldb::TypeSP type_sp = types.GetTypeAtIndex(ti);
+
if (log)
- log->Printf(" CAS::FEVD[%u] - Couldn't export a type",
- current_id);
-
+ {
+ const char *name_string = type_sp->GetName().GetCString();
+
+ log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s",
+ current_id,
+ name.GetCString(),
+ (name_string ? name_string : "<anonymous>"));
+ }
+
+ CompilerType full_type = type_sp->GetFullCompilerType();
+
+ CompilerType copied_clang_type (GuardedCopyType(full_type));
+
+ if (!copied_clang_type)
+ {
+ if (log)
+ log->Printf(" CAS::FEVD[%u] - Couldn't export a type",
+ current_id);
+
+ continue;
+ }
+
+ context.AddTypeDecl(copied_clang_type);
+
+ found_a_type = true;
break;
}
-
- context.AddTypeDecl(copied_clang_type);
-
- found_a_type = true;
}
-
+
if (!found_a_type)
{
// Try the modules next.
@@ -815,7 +818,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
llvm::isa<clang::ObjCContainerDecl>(decl_from_modules) ||
llvm::isa<clang::EnumConstantDecl>(decl_from_modules))
{
- clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
+ clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr;
if (!copied_named_decl)
@@ -873,7 +876,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
name.GetCString());
}
- clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decls[0]->getASTContext(), decls[0]);
+ clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decls[0]->getASTContext(), decls[0]);
clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr;
if (!copied_named_decl)
@@ -1068,7 +1071,7 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
Decl *original_decl = NULL;
ASTContext *original_ctx = NULL;
- m_ast_importer->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx);
+ m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx);
if (!original_decl)
break;
@@ -1079,7 +1082,7 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
context,
original_interface_decl,
m_ast_context,
- m_ast_importer,
+ m_ast_importer_sp.get(),
"at origin"))
return; // found it, no need to look any further
} while (0);
@@ -1210,12 +1213,11 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
if (!sc.function)
continue;
- DeclContext *function_ctx = sc.function->GetClangDeclContext();
-
- if (!function_ctx)
+ CompilerDeclContext function_decl_ctx = sc.function->GetDeclContext();
+ if (!function_decl_ctx)
continue;
- ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(function_ctx);
+ ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx);
if (!method_decl)
continue;
@@ -1227,7 +1229,7 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
if (found_interface_decl->getName() == interface_decl->getName())
{
- Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl);
+ Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl);
if (!copied_decl)
continue;
@@ -1275,7 +1277,7 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
context,
complete_interface_decl,
m_ast_context,
- m_ast_importer,
+ m_ast_importer_sp.get(),
"in debug info");
return;
@@ -1308,7 +1310,7 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
context,
interface_decl_from_modules,
m_ast_context,
- m_ast_importer,
+ m_ast_importer_sp.get(),
"in modules"))
return;
}
@@ -1354,7 +1356,7 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
context,
runtime_interface_decl,
m_ast_context,
- m_ast_importer,
+ m_ast_importer_sp.get(),
"in runtime");
}
while(0);
@@ -1426,7 +1428,7 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
unsigned int current_id = invocation_id++;
DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context));
- DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer));
+ DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer_sp.get()));
ConstString class_name(parser_iface_decl->getNameAsString().c_str());
@@ -1439,7 +1441,7 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
context,
*m_ast_context,
- m_ast_importer,
+ m_ast_importer_sp.get(),
origin_iface_decl))
return;
@@ -1474,7 +1476,7 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
context,
*m_ast_context,
- m_ast_importer,
+ m_ast_importer_sp.get(),
complete_iface_decl);
return;
@@ -1514,7 +1516,7 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
context,
*m_ast_context,
- m_ast_importer,
+ m_ast_importer_sp.get(),
interface_decl_from_modules))
return;
}
@@ -1564,7 +1566,7 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
context,
*m_ast_context,
- m_ast_importer,
+ m_ast_importer_sp.get(),
interface_decl_from_runtime))
return;
}
@@ -1667,7 +1669,7 @@ ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, uint6
record->getNameAsString().c_str());
DeclFromParser <const RecordDecl> parser_record(record);
- DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer));
+ DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer_sp.get()));
if (origin_record.IsInvalid())
return false;
@@ -1678,7 +1680,8 @@ ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, uint6
ClangASTContext::GetCompleteDecl(&origin_record->getASTContext(), const_cast<RecordDecl*>(origin_record.decl));
- if (!origin_record.decl->getDefinition())
+ clang::RecordDecl* definition = origin_record.decl->getDefinition();
+ if (!definition || !definition->isCompleteDefinition())
return false;
const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl));
@@ -1708,9 +1711,9 @@ ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, uint6
return false;
}
- if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer, parser_ast_context) ||
- !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer, parser_ast_context) ||
- !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer, parser_ast_context))
+ if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer_sp.get(), parser_ast_context) ||
+ !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer_sp.get(), parser_ast_context) ||
+ !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer_sp.get(), parser_ast_context))
return false;
size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth();
@@ -1778,7 +1781,7 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac
log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s in namespace %s",
current_id, static_cast<void*>(m_ast_context),
name.GetCString(),
- parent_map->begin()->second.GetNamespaceDecl()->getDeclName().getAsString().c_str());
+ parent_map->begin()->second.GetName().AsCString());
else
log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s",
current_id, static_cast<void*>(m_ast_context),
@@ -1791,10 +1794,10 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac
i != e;
++i)
{
- ClangNamespaceDecl found_namespace_decl;
+ CompilerDeclContext found_namespace_decl;
lldb::ModuleSP module_sp = i->first;
- ClangNamespaceDecl module_parent_namespace_decl = i->second;
+ CompilerDeclContext module_parent_namespace_decl = i->second;
SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
@@ -1808,7 +1811,7 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac
if (!found_namespace_decl)
continue;
- namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(module_sp, found_namespace_decl));
+ namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(module_sp, found_namespace_decl));
if (log)
log->Printf(" CMN[%u] Found namespace %s in module %s",
@@ -1822,7 +1825,7 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac
const ModuleList &target_images = m_target->GetImages();
Mutex::Locker modules_locker(target_images.GetMutex());
- ClangNamespaceDecl null_namespace_decl;
+ CompilerDeclContext null_namespace_decl;
for (size_t i = 0, e = target_images.GetSize(); i < e; ++i)
{
@@ -1831,7 +1834,7 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac
if (!image)
continue;
- ClangNamespaceDecl found_namespace_decl;
+ CompilerDeclContext found_namespace_decl;
SymbolVendor *symbol_vendor = image->GetSymbolVendor();
@@ -1845,7 +1848,7 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac
if (!found_namespace_decl)
continue;
- namespace_map->push_back(std::pair<lldb::ModuleSP, ClangNamespaceDecl>(image, found_namespace_decl));
+ namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(image, found_namespace_decl));
if (log)
log->Printf(" CMN[%u] Found namespace %s in module %s",
@@ -1860,64 +1863,80 @@ NamespaceDecl *
ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::NamespaceMapSP &namespace_decls)
{
if (!namespace_decls)
- return NULL;
+ return nullptr;
- const ClangNamespaceDecl &namespace_decl = namespace_decls->begin()->second;
+ const CompilerDeclContext &namespace_decl = namespace_decls->begin()->second;
- Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, namespace_decl.GetASTContext(), namespace_decl.GetNamespaceDecl());
+ clang::ASTContext *src_ast = ClangASTContext::DeclContextGetClangASTContext(namespace_decl);
+ if (!src_ast)
+ return nullptr;
+ clang::NamespaceDecl *src_namespace_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(namespace_decl);
+
+ if (!src_namespace_decl)
+ return nullptr;
+
+ Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, src_ast, src_namespace_decl);
if (!copied_decl)
- return NULL;
+ return nullptr;
NamespaceDecl *copied_namespace_decl = dyn_cast<NamespaceDecl>(copied_decl);
if (!copied_namespace_decl)
- return NULL;
+ return nullptr;
context.m_decls.push_back(copied_namespace_decl);
- m_ast_importer->RegisterNamespaceMap(copied_namespace_decl, namespace_decls);
+ m_ast_importer_sp->RegisterNamespaceMap(copied_namespace_decl, namespace_decls);
return dyn_cast<NamespaceDecl>(copied_decl);
}
-ClangASTType
-ClangASTSource::GuardedCopyType (const ClangASTType &src_type)
+CompilerType
+ClangASTSource::GuardedCopyType (const CompilerType &src_type)
{
+ ClangASTContext *src_ast = llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem());
+ if (src_ast == nullptr)
+ return CompilerType();
+
ClangASTMetrics::RegisterLLDBImport();
SetImportInProgress(true);
- QualType copied_qual_type = m_ast_importer->CopyType (m_ast_context, src_type.GetASTContext(), src_type.GetQualType());
+ QualType copied_qual_type = m_ast_importer_sp->CopyType (m_ast_context, src_ast->getASTContext(), ClangASTContext::GetQualType(src_type));
SetImportInProgress(false);
if (copied_qual_type.getAsOpaquePtr() && copied_qual_type->getCanonicalTypeInternal().isNull())
// this shouldn't happen, but we're hardening because the AST importer seems to be generating bad types
// on occasion.
- return ClangASTType();
+ return CompilerType();
- return ClangASTType(m_ast_context, copied_qual_type);
+ return CompilerType(m_ast_context, copied_qual_type);
}
clang::NamedDecl *
-NameSearchContext::AddVarDecl(const ClangASTType &type)
+NameSearchContext::AddVarDecl(const CompilerType &type)
{
assert (type && "Type for variable must be valid!");
if (!type.IsValid())
return NULL;
+ ClangASTContext* lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (!lldb_ast)
+ return NULL;
+
IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo();
- clang::ASTContext *ast = type.GetASTContext();
+ clang::ASTContext *ast = lldb_ast->getASTContext();
clang::NamedDecl *Decl = VarDecl::Create(*ast,
const_cast<DeclContext*>(m_decl_context),
SourceLocation(),
SourceLocation(),
ii,
- type.GetQualType(),
+ ClangASTContext::GetQualType(type),
0,
SC_Static);
m_decls.push_back(Decl);
@@ -1926,7 +1945,7 @@ NameSearchContext::AddVarDecl(const ClangASTType &type)
}
clang::NamedDecl *
-NameSearchContext::AddFunDecl (const ClangASTType &type, bool extern_c)
+NameSearchContext::AddFunDecl (const CompilerType &type, bool extern_c)
{
assert (type && "Type for variable must be valid!");
@@ -1935,12 +1954,16 @@ NameSearchContext::AddFunDecl (const ClangASTType &type, bool extern_c)
if (m_function_types.count(type))
return NULL;
+
+ ClangASTContext* lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (!lldb_ast)
+ return NULL;
m_function_types.insert(type);
- QualType qual_type (type.GetQualType());
+ QualType qual_type (ClangASTContext::GetQualType(type));
- clang::ASTContext *ast = type.GetASTContext();
+ clang::ASTContext *ast = lldb_ast->getASTContext();
const bool isInlineSpecified = false;
const bool hasWrittenPrototype = true;
@@ -1957,11 +1980,14 @@ NameSearchContext::AddFunDecl (const ClangASTType &type, bool extern_c)
false);
}
+ // Pass the identifier info for functions the decl_name is needed for operators
+ clang::DeclarationName decl_name = m_decl_name.getNameKind() == DeclarationName::Identifier ? m_decl_name.getAsIdentifierInfo() : m_decl_name;
+
clang::FunctionDecl *func_decl = FunctionDecl::Create (*ast,
context,
SourceLocation(),
SourceLocation(),
- m_decl_name.getAsIdentifierInfo(),
+ decl_name,
qual_type,
NULL,
SC_Extern,
@@ -2023,15 +2049,15 @@ NameSearchContext::AddGenericFunDecl()
ArrayRef<QualType>(), // argument types
proto_info));
- return AddFunDecl(ClangASTType (m_ast_source.m_ast_context, generic_function_type), true);
+ return AddFunDecl(CompilerType (m_ast_source.m_ast_context, generic_function_type), true);
}
clang::NamedDecl *
-NameSearchContext::AddTypeDecl(const ClangASTType &clang_type)
+NameSearchContext::AddTypeDecl(const CompilerType &clang_type)
{
if (clang_type)
{
- QualType qual_type = clang_type.GetQualType();
+ QualType qual_type = ClangASTContext::GetQualType(clang_type);
if (const TypedefType *typedef_type = llvm::dyn_cast<TypedefType>(qual_type))
{
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangASTSource.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
index 46140d2..bb63847 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangASTSource.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
@@ -15,7 +15,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Target.h"
#include "llvm/ADT/SmallSet.h"
@@ -54,13 +54,13 @@ public:
m_active_lexical_decls (),
m_active_lookups ()
{
- m_ast_importer = m_target->GetClangASTImporter();
+ m_ast_importer_sp = m_target->GetClangASTImporter();
}
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- ~ClangASTSource();
+ ~ClangASTSource() override;
//------------------------------------------------------------------
/// Interface stubs.
@@ -77,7 +77,7 @@ public:
void InstallASTContext (clang::ASTContext *ast_context)
{
m_ast_context = ast_context;
- m_ast_importer->InstallMapCompleter(ast_context, *this);
+ m_ast_importer_sp->InstallMapCompleter(ast_context, *this);
}
//
@@ -111,15 +111,15 @@ public:
/// The DeclContext being searched.
///
/// @param[in] isKindWeWant
- /// If non-NULL, a callback function that returns true given the
+ /// A callback function that returns true given the
/// DeclKinds of desired Decls, and false otherwise.
///
/// @param[in] Decls
/// A vector that is filled in with matching Decls.
//------------------------------------------------------------------
- clang::ExternalLoadResult FindExternalLexicalDecls(const clang::DeclContext *DC,
- bool (*isKindWeWant)(clang::Decl::Kind),
- llvm::SmallVectorImpl<clang::Decl *> &Decls) override;
+ void FindExternalLexicalDecls(
+ const clang::DeclContext *DC, llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
+ llvm::SmallVectorImpl<clang::Decl *> &Decls) override;
//------------------------------------------------------------------
/// Specify the layout of the contents of a RecordDecl.
@@ -249,11 +249,12 @@ public:
return m_original.FindExternalVisibleDeclsByName(DC, Name);
}
- clang::ExternalLoadResult
- FindExternalLexicalDecls(const clang::DeclContext *DC, bool (*isKindWeWant)(clang::Decl::Kind),
+ void
+ FindExternalLexicalDecls(const clang::DeclContext *DC,
+ llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
llvm::SmallVectorImpl<clang::Decl *> &Decls) override
{
- return m_original.FindExternalLexicalDecls(DC, isKindWeWant, Decls);
+ return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls);
}
void
@@ -352,7 +353,7 @@ protected:
void
FindExternalVisibleDecls (NameSearchContext &context,
lldb::ModuleSP module,
- ClangNamespaceDecl &namespace_decl,
+ CompilerDeclContext &namespace_decl,
unsigned int current_id);
//------------------------------------------------------------------
@@ -388,14 +389,14 @@ protected:
/// The source AST context, typically the AST context of whatever
/// symbol file the type was found in.
///
- /// @param[in] clang_type
+ /// @param[in] src_type
/// The source type.
///
/// @return
/// The imported type.
//------------------------------------------------------------------
- ClangASTType
- GuardedCopyType (const ClangASTType &src_type);
+ CompilerType
+ GuardedCopyType (const CompilerType &src_type);
friend struct NameSearchContext;
@@ -404,7 +405,7 @@ protected:
const lldb::TargetSP m_target; ///< The target to use in finding variables and types.
clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for.
- ClangASTImporter *m_ast_importer; ///< The target's AST importer.
+ lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer.
std::set<const clang::Decl *> m_active_lexical_decls;
std::set<const char *> m_active_lookups;
};
@@ -423,7 +424,7 @@ struct NameSearchContext {
ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all namespaces found for this request back to their modules
const clang::DeclarationName &m_decl_name; ///< The name being looked for
const clang::DeclContext *m_decl_context; ///< The DeclContext to put declarations into
- llvm::SmallSet <ClangASTType, 5> m_function_types; ///< All the types of functions that have been reported, so we don't report conflicts
+ llvm::SmallSet <CompilerType, 5> m_function_types; ///< All the types of functions that have been reported, so we don't report conflicts
struct {
bool variable : 1;
@@ -468,7 +469,7 @@ struct NameSearchContext {
/// @param[in] type
/// The opaque QualType for the VarDecl being registered.
//------------------------------------------------------------------
- clang::NamedDecl *AddVarDecl(const ClangASTType &type);
+ clang::NamedDecl *AddVarDecl(const CompilerType &type);
//------------------------------------------------------------------
/// Create a FunDecl with the name being searched for and the provided
@@ -480,7 +481,7 @@ struct NameSearchContext {
/// @param[in] extern_c
/// If true, build an extern "C" linkage specification for this.
//------------------------------------------------------------------
- clang::NamedDecl *AddFunDecl(const ClangASTType &type,
+ clang::NamedDecl *AddFunDecl(const CompilerType &type,
bool extern_c = false);
//------------------------------------------------------------------
@@ -494,10 +495,10 @@ struct NameSearchContext {
/// Create a TypeDecl with the name being searched for and the provided
/// type and register it in the right places.
///
- /// @param[in] type
+ /// @param[in] compiler_type
/// The opaque QualType for the TypeDecl being registered.
//------------------------------------------------------------------
- clang::NamedDecl *AddTypeDecl(const ClangASTType &clang_type);
+ clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type);
//------------------------------------------------------------------
@@ -520,6 +521,6 @@ struct NameSearchContext {
void AddNamedDecl (clang::NamedDecl *decl);
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_ClangASTSource_h_
diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangExpressionDeclMap.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 2c66a0a..f4d6b19 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ClangExpressionDeclMap.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -7,7 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "ClangExpressionDeclMap.h"
+
+#include "ASTDumper.h"
+#include "ClangASTSource.h"
+#include "ClangModulesDeclVendor.h"
+#include "ClangPersistentVariables.h"
+
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclarationName.h"
@@ -21,18 +27,16 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectVariable.h"
-#include "lldb/Expression/ASTDumper.h"
-#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/TypeList.h"
@@ -47,15 +51,20 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+
using namespace lldb;
using namespace lldb_private;
using namespace clang;
-ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory, ExecutionContext &exe_ctx) :
+ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory,
+ Materializer::PersistentVariableDelegate *result_delegate,
+ ExecutionContext &exe_ctx) :
ClangASTSource (exe_ctx.GetTargetSP()),
m_found_entities (),
m_struct_members (),
m_keep_result_in_memory (keep_result_in_memory),
+ m_result_delegate (result_delegate),
m_parser_vars (),
m_struct_vars ()
{
@@ -99,7 +108,7 @@ ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx,
if (target)
{
- m_parser_vars->m_persistent_vars = &target->GetPersistentVariables();
+ m_parser_vars->m_persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(eLanguageTypeC));
if (!target->GetScratchClangASTContext())
return false;
@@ -132,18 +141,18 @@ ClangExpressionDeclMap::DidParse()
entity_index < num_entities;
++entity_index)
{
- ClangExpressionVariableSP var_sp(m_found_entities.GetVariableAtIndex(entity_index));
+ ExpressionVariableSP var_sp(m_found_entities.GetVariableAtIndex(entity_index));
if (var_sp)
- var_sp->DisableParserVars(GetParserID());
+ llvm::cast<ClangExpressionVariable>(var_sp.get())->DisableParserVars(GetParserID());
}
for (size_t pvar_index = 0, num_pvars = m_parser_vars->m_persistent_vars->GetSize();
pvar_index < num_pvars;
++pvar_index)
{
- ClangExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index));
- if (pvar_sp)
- pvar_sp->DisableParserVars(GetParserID());
+ ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index));
+ if (ClangExpressionVariable *clang_var = llvm::dyn_cast<ClangExpressionVariable>(pvar_sp.get()))
+ clang_var->DisableParserVars(GetParserID());
}
DisableParserVars();
@@ -192,43 +201,50 @@ ClangExpressionDeclMap::AddPersistentVariable
{
assert (m_parser_vars.get());
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(parser_type.GetTypeSystem());
+ if (ast == nullptr)
+ return false;
+
if (m_parser_vars->m_materializer && is_result)
{
Error err;
ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
Target *target = exe_ctx.GetTargetPtr();
- if (target == NULL)
+ if (target == nullptr)
return false;
- ASTContext *context(target->GetScratchClangASTContext()->getASTContext());
+ ClangASTContext *context(target->GetScratchClangASTContext());
- TypeFromUser user_type(m_ast_importer->DeportType(context,
- parser_type.GetASTContext(),
- parser_type.GetOpaqueQualType()),
+ TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(),
+ ast->getASTContext(),
+ parser_type.GetOpaqueQualType()),
context);
+
+ uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type,
+ is_lvalue,
+ m_keep_result_in_memory,
+ m_result_delegate,
+ err);
+
+ ClangExpressionVariable *var = new ClangExpressionVariable(exe_ctx.GetBestExecutionContextScope(),
+ name,
+ user_type,
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size);
+
+ m_found_entities.AddNewlyConstructedVariable(var);
+
+ var->EnableParserVars(GetParserID());
- uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type, is_lvalue, m_keep_result_in_memory, err);
-
- ClangExpressionVariableSP var_sp = m_found_entities.CreateVariable(exe_ctx.GetBestExecutionContextScope(),
- name,
- user_type,
- m_parser_vars->m_target_info.byte_order,
- m_parser_vars->m_target_info.address_byte_size);
-
- if (!var_sp)
- return false;
-
- var_sp->EnableParserVars(GetParserID());
-
- ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID());
+ ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID());
parser_vars->m_named_decl = decl;
parser_vars->m_parser_type = parser_type;
- var_sp->EnableJITVars(GetParserID());
+ var->EnableJITVars(GetParserID());
- ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID());
+ ClangExpressionVariable::JITVars *jit_vars = var->GetJITVars(GetParserID());
jit_vars->m_offset = offset;
@@ -241,11 +257,11 @@ ClangExpressionDeclMap::AddPersistentVariable
if (target == NULL)
return false;
- ASTContext *context(target->GetScratchClangASTContext()->getASTContext());
+ ClangASTContext *context(target->GetScratchClangASTContext());
- TypeFromUser user_type(m_ast_importer->DeportType(context,
- parser_type.GetASTContext(),
- parser_type.GetOpaqueQualType()),
+ TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(),
+ ast->getASTContext(),
+ parser_type.GetOpaqueQualType()),
context);
if (!user_type.GetOpaqueQualType())
@@ -258,43 +274,43 @@ ClangExpressionDeclMap::AddPersistentVariable
if (!m_parser_vars->m_target_info.IsValid())
return false;
- ClangExpressionVariableSP var_sp = m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx.GetBestExecutionContextScope (),
- name,
- user_type,
- m_parser_vars->m_target_info.byte_order,
- m_parser_vars->m_target_info.address_byte_size);
+ ClangExpressionVariable *var = llvm::cast<ClangExpressionVariable>(m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx.GetBestExecutionContextScope (),
+ name,
+ user_type,
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size).get());
- if (!var_sp)
+ if (!var)
return false;
- var_sp->m_frozen_sp->SetHasCompleteType();
+ var->m_frozen_sp->SetHasCompleteType();
if (is_result)
- var_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
+ var->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
else
- var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist
+ var->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist
if (is_lvalue)
{
- var_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
+ var->m_flags |= ClangExpressionVariable::EVIsProgramReference;
}
else
{
- var_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
- var_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
+ var->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
+ var->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
}
if (m_keep_result_in_memory)
{
- var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget;
+ var->m_flags |= ClangExpressionVariable::EVKeepInTarget;
}
if (log)
- log->Printf("Created persistent variable with flags 0x%hx", var_sp->m_flags);
+ log->Printf("Created persistent variable with flags 0x%hx", var->m_flags);
- var_sp->EnableParserVars(GetParserID());
+ var->EnableParserVars(GetParserID());
- ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID());
+ ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID());
parser_vars->m_named_decl = decl;
parser_vars->m_parser_type = parser_type;
@@ -321,33 +337,33 @@ ClangExpressionDeclMap::AddValueToStruct
m_struct_vars->m_struct_laid_out = false;
- if (m_struct_members.GetVariable(decl, GetParserID()))
+ if (ClangExpressionVariable::FindVariableInList(m_struct_members, decl, GetParserID()))
return true;
- ClangExpressionVariableSP var_sp (m_found_entities.GetVariable(decl, GetParserID()));
+ ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID()));
- if (!var_sp)
+ if (!var)
{
- var_sp = m_parser_vars->m_persistent_vars->GetVariable(decl, GetParserID());
+ var = ClangExpressionVariable::FindVariableInList(*m_parser_vars->m_persistent_vars, decl, GetParserID());
is_persistent_variable = true;
}
- if (!var_sp)
+ if (!var)
return false;
if (log)
log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure",
static_cast<const void*>(decl), name.GetCString(),
- var_sp->GetName().GetCString());
+ var->GetName().GetCString());
// We know entity->m_parser_vars is valid because we used a parser variable
// to find it
- ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID());
+ ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(var)->GetParserVars(GetParserID());
parser_vars->m_llvm_value = value;
- if (ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID()))
+ if (ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID()))
{
// We already laid this out; do not touch
@@ -355,14 +371,14 @@ ClangExpressionDeclMap::AddValueToStruct
log->Printf("Already placed at 0x%llx", (unsigned long long)jit_vars->m_offset);
}
- var_sp->EnableJITVars(GetParserID());
+ llvm::cast<ClangExpressionVariable>(var)->EnableJITVars(GetParserID());
- ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID());
+ ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID());
jit_vars->m_alignment = alignment;
jit_vars->m_size = size;
- m_struct_members.AddVariable(var_sp);
+ m_struct_members.AddVariable(var->shared_from_this());
if (m_parser_vars->m_materializer)
{
@@ -372,13 +388,14 @@ ClangExpressionDeclMap::AddValueToStruct
if (is_persistent_variable)
{
- offset = m_parser_vars->m_materializer->AddPersistentVariable(var_sp, err);
+ ExpressionVariableSP var_sp(var->shared_from_this());
+ offset = m_parser_vars->m_materializer->AddPersistentVariable(var_sp, nullptr, err);
}
else
{
if (const lldb_private::Symbol *sym = parser_vars->m_lldb_sym)
offset = m_parser_vars->m_materializer->AddSymbol(*sym, err);
- else if (const RegisterInfo *reg_info = var_sp->GetRegisterInfo())
+ else if (const RegisterInfo *reg_info = var->GetRegisterInfo())
offset = m_parser_vars->m_materializer->AddRegister(*reg_info, err);
else if (parser_vars->m_lldb_var)
offset = m_parser_vars->m_materializer->AddVariable(parser_vars->m_lldb_var, err);
@@ -450,13 +467,13 @@ ClangExpressionDeclMap::GetStructElement
if (index >= m_struct_members.GetSize())
return false;
- ClangExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index));
+ ExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index));
if (!member_sp)
return false;
- ClangExpressionVariable::ParserVars *parser_vars = member_sp->GetParserVars(GetParserID());
- ClangExpressionVariable::JITVars *jit_vars = member_sp->GetJITVars(GetParserID());
+ ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(member_sp.get())->GetParserVars(GetParserID());
+ ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(member_sp.get())->GetJITVars(GetParserID());
if (!parser_vars ||
!jit_vars ||
@@ -478,15 +495,15 @@ ClangExpressionDeclMap::GetFunctionInfo
uint64_t &ptr
)
{
- ClangExpressionVariableSP entity_sp(m_found_entities.GetVariable(decl, GetParserID()));
+ ClangExpressionVariable *entity(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID()));
- if (!entity_sp)
+ if (!entity)
return false;
// We know m_parser_vars is valid since we searched for the variable by
// its NamedDecl
- ClangExpressionVariable::ParserVars *parser_vars = entity_sp->GetParserVars(GetParserID());
+ ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
ptr = parser_vars->m_lldb_value.GetScalar().ULongLong();
@@ -498,6 +515,7 @@ FindCodeSymbolInContext
(
const ConstString &name,
SymbolContext &sym_ctx,
+ uint32_t name_type_mask,
SymbolContextList &sc_list
)
{
@@ -506,7 +524,7 @@ FindCodeSymbolInContext
if (sym_ctx.module_sp)
sym_ctx.module_sp->FindFunctions(name,
NULL,
- eFunctionNameTypeAuto,
+ name_type_mask,
true, // include_symbols
false, // include_inlines
true, // append
@@ -515,7 +533,7 @@ FindCodeSymbolInContext
{
if (sym_ctx.target_sp)
sym_ctx.target_sp->GetImages().FindFunctions(name,
- eFunctionNameTypeAuto,
+ name_type_mask,
true, // include_symbols
false, // include_inlines
true, // append
@@ -553,6 +571,63 @@ FindCodeSymbolInContext
}
}
+ConstString
+FindBestAlternateMangledName
+(
+ const ConstString &demangled,
+ const LanguageType &lang_type,
+ SymbolContext &sym_ctx
+)
+{
+ CPlusPlusLanguage::MethodName cpp_name(demangled);
+ std::string scope_qualified_name = cpp_name.GetScopeQualifiedName();
+
+ if (!scope_qualified_name.size())
+ return ConstString();
+
+ if (!sym_ctx.module_sp)
+ return ConstString();
+
+ SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor();
+ if (!sym_vendor)
+ return ConstString();
+
+ lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile();
+ if (!sym_file)
+ return ConstString();
+
+ std::vector<ConstString> alternates;
+ sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates);
+
+ std::vector<ConstString> param_and_qual_matches;
+ std::vector<ConstString> param_matches;
+ for (size_t i = 0; i < alternates.size(); i++)
+ {
+ ConstString alternate_mangled_name = alternates[i];
+ Mangled mangled(alternate_mangled_name, true);
+ ConstString demangled = mangled.GetDemangledName(lang_type);
+
+ CPlusPlusLanguage::MethodName alternate_cpp_name(demangled);
+ if (!cpp_name.IsValid())
+ continue;
+
+ if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments())
+ {
+ if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers())
+ param_and_qual_matches.push_back(alternate_mangled_name);
+ else
+ param_matches.push_back(alternate_mangled_name);
+ }
+ }
+
+ if (param_and_qual_matches.size())
+ return param_and_qual_matches[0]; // It is assumed that there will be only one!
+ else if (param_matches.size())
+ return param_matches[0]; // Return one of them as a best match
+ else
+ return ConstString();
+}
+
bool
ClangExpressionDeclMap::GetFunctionAddress
(
@@ -573,10 +648,43 @@ ClangExpressionDeclMap::GetFunctionAddress
SymbolContextList sc_list;
- FindCodeSymbolInContext(name, m_parser_vars->m_sym_ctx, sc_list);
+ FindCodeSymbolInContext(name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list);
uint32_t sc_list_size = sc_list.GetSize();
-
+
+ if (sc_list_size == 0)
+ {
+ SymbolContext &sc = m_parser_vars->m_sym_ctx;
+ if (sc.comp_unit)
+ {
+ LanguageType lang_type = sc.comp_unit->GetLanguage();
+ if (Language::LanguageIsCPlusPlus(lang_type) &&
+ CPlusPlusLanguage::IsCPPMangledName(name.AsCString()))
+ {
+ Mangled mangled(name, true);
+ ConstString demangled = mangled.GetDemangledName(lang_type);
+
+ if (demangled)
+ {
+ ConstString best_alternate_mangled_name = FindBestAlternateMangledName(demangled, lang_type, sc);
+ if (best_alternate_mangled_name)
+ {
+ FindCodeSymbolInContext(
+ best_alternate_mangled_name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list);
+ sc_list_size = sc_list.GetSize();
+ }
+
+ if (sc_list_size == 0)
+ {
+ FindCodeSymbolInContext(
+ demangled, m_parser_vars->m_sym_ctx, eFunctionNameTypeFull, sc_list);
+ sc_list_size = sc_list.GetSize();
+ }
+ }
+ }
+ }
+ }
+
if (sc_list_size == 0)
{
// We occasionally get debug information in which a const function is reported
@@ -592,7 +700,8 @@ ClangExpressionDeclMap::GetFunctionAddress
if (log)
log->Printf("Failed to find symbols given non-const name %s; trying %s", name.GetCString(), fixed_name.GetCString());
- FindCodeSymbolInContext(fixed_name, m_parser_vars->m_sym_ctx, sc_list);
+ FindCodeSymbolInContext(
+ fixed_name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list);
sc_list_size = sc_list.GetSize();
}
}
@@ -863,7 +972,7 @@ ClangExpressionDeclMap::FindGlobalVariable
Target &target,
ModuleSP &module,
const ConstString &name,
- ClangNamespaceDecl *namespace_decl,
+ CompilerDeclContext *namespace_decl,
TypeFromUser *type
)
{
@@ -882,7 +991,7 @@ ClangExpressionDeclMap::FindGlobalVariable
{
VariableSP var_sp = vars.GetVariableAtIndex(i);
- if (ClangASTContext::AreTypesSame(*type, var_sp->GetType()->GetClangFullType()))
+ if (ClangASTContext::AreTypesSame(*type, var_sp->GetType()->GetFullCompilerType ()))
return var_sp;
}
}
@@ -930,7 +1039,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context)
if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context))
{
- ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);
+ ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context);
if (log && log->GetVerbose())
log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)",
@@ -947,7 +1056,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context)
if (log)
log->Printf(" CEDM::FEVD[%u] Searching namespace %s in module %s",
current_id,
- i->second.GetNamespaceDecl()->getNameAsString().c_str(),
+ i->second.GetName().AsCString(),
i->first->GetFileSpec().GetFilename().GetCString());
FindExternalVisibleDecls(context,
@@ -958,7 +1067,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context)
}
else if (isa<TranslationUnitDecl>(context.m_decl_context))
{
- ClangNamespaceDecl namespace_decl;
+ CompilerDeclContext namespace_decl;
if (log)
log->Printf(" CEDM::FEVD[%u] Searching the root namespace", current_id);
@@ -976,7 +1085,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context)
void
ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
lldb::ModuleSP module_sp,
- ClangNamespaceDecl &namespace_decl,
+ CompilerDeclContext &namespace_decl,
unsigned int current_id)
{
assert (m_ast_context);
@@ -1002,6 +1111,9 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
// doesn't start with our phony prefix of '$'
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+ SymbolContext sym_ctx;
+ if (frame != nullptr)
+ sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock);
if (name_unique_cstr[0] == '$' && !namespace_decl)
{
static ConstString g_lldb_class_name ("$__lldb_class");
@@ -1013,23 +1125,19 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (frame == NULL)
return;
- SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction);
-
- if (!sym_ctx.function)
- return;
- // Get the block that defines the function
+ // Find the block that defines the function represented by "sym_ctx"
Block *function_block = sym_ctx.GetFunctionBlock();
if (!function_block)
return;
- clang::DeclContext *decl_context = function_block->GetClangDeclContext();
+ CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
- if (!decl_context)
+ if (!function_decl_ctx)
return;
- clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context);
+ clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx);
if (method_decl)
{
@@ -1038,7 +1146,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
QualType class_qual_type(class_decl->getTypeForDecl(), 0);
TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(),
- &class_decl->getASTContext());
+ ClangASTContext::GetASTContext(&class_decl->getASTContext()));
if (log)
{
@@ -1046,28 +1154,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString());
}
- TypeFromParser class_type = CopyClassType(class_user_type, current_id);
-
- if (!class_type.IsValid())
- return;
-
- TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo(QualType::getFromOpaquePtr(class_type.GetOpaqueQualType()));
-
- if (!type_source_info)
- return;
-
- TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context,
- m_ast_context->getTranslationUnitDecl(),
- SourceLocation(),
- SourceLocation(),
- context.m_decl_name.getAsIdentifierInfo(),
- type_source_info);
-
-
- if (!typedef_decl)
- return;
-
- context.AddNamedDecl(typedef_decl);
+ AddThisType(context, class_user_type, current_id);
if (method_decl->isInstance())
{
@@ -1076,7 +1163,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type);
TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
- &method_decl->getASTContext());
+ ClangASTContext::GetASTContext(&method_decl->getASTContext()));
m_struct_vars->m_object_pointer_type = self_user_type;
}
@@ -1103,21 +1190,18 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (!this_type)
return;
- ClangASTType pointee_type = this_type->GetClangForwardType().GetPointeeType();
+ TypeFromUser pointee_type = this_type->GetForwardCompilerType ().GetPointeeType();
if (pointee_type.IsValid())
{
if (log)
{
- ASTDumper ast_dumper(this_type->GetClangFullType());
- log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
+ ASTDumper ast_dumper(pointee_type);
+ log->Printf(" FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString());
}
-
- TypeFromUser class_user_type(pointee_type);
- AddOneType(context, class_user_type, current_id);
-
-
- TypeFromUser this_user_type(this_type->GetClangFullType());
+
+ AddThisType(context, pointee_type, current_id);
+ TypeFromUser this_user_type(this_type->GetFullCompilerType ());
m_struct_vars->m_object_pointer_type = this_user_type;
return;
}
@@ -1135,23 +1219,20 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (!frame)
return;
- SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction);
+ SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock);
- if (!sym_ctx.function)
- return;
-
- // Get the block that defines the function
+ // Find the block that defines the function represented by "sym_ctx"
Block *function_block = sym_ctx.GetFunctionBlock();
if (!function_block)
return;
- clang::DeclContext *decl_context = function_block->GetClangDeclContext();
+ CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
- if (!decl_context)
+ if (!function_decl_ctx)
return;
- clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context);
+ clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx);
if (method_decl)
{
@@ -1166,7 +1247,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
return; // This is unlikely, but we have seen crashes where this occurred
TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(),
- &method_decl->getASTContext());
+ ClangASTContext::GetASTContext(&method_decl->getASTContext()));
if (log)
{
@@ -1183,7 +1264,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0));
TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
- &method_decl->getASTContext());
+ ClangASTContext::GetASTContext(&method_decl->getASTContext()));
m_struct_vars->m_object_pointer_type = self_user_type;
}
@@ -1193,7 +1274,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
QualType class_type = method_decl->getASTContext().getObjCClassType();
TypeFromUser self_user_type(class_type.getAsOpaquePtr(),
- &method_decl->getASTContext());
+ ClangASTContext::GetASTContext(&method_decl->getASTContext()));
m_struct_vars->m_object_pointer_type = self_user_type;
}
@@ -1220,13 +1301,13 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (!self_type)
return;
- ClangASTType self_clang_type = self_type->GetClangFullType();
+ CompilerType self_clang_type = self_type->GetFullCompilerType ();
- if (self_clang_type.IsObjCClassType())
+ if (ClangASTContext::IsObjCClassType(self_clang_type))
{
return;
}
- else if (self_clang_type.IsObjCObjectPointerType())
+ else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type))
{
self_clang_type = self_clang_type.GetPointeeType();
@@ -1235,7 +1316,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (log)
{
- ASTDumper ast_dumper(self_type->GetClangFullType());
+ ASTDumper ast_dumper(self_type->GetFullCompilerType ());
log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
}
@@ -1243,7 +1324,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
AddOneType(context, class_user_type, current_id);
- TypeFromUser self_user_type(self_type->GetClangFullType());
+ TypeFromUser self_user_type(self_type->GetFullCompilerType ());
m_struct_vars->m_object_pointer_type = self_user_type;
return;
@@ -1278,7 +1359,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (!ptype_type_decl)
break;
- Decl *parser_ptype_decl = m_ast_importer->CopyDecl(m_ast_context, scratch_ast_context, ptype_type_decl);
+ Decl *parser_ptype_decl = m_ast_importer_sp->CopyDecl(m_ast_context, scratch_ast_context, ptype_type_decl);
if (!parser_ptype_decl)
break;
@@ -1294,7 +1375,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
context.AddNamedDecl(parser_ptype_type_decl);
} while (0);
- ClangExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name));
+ ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name));
if (pvar_sp)
{
@@ -1321,28 +1402,37 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
{
ValueObjectSP valobj;
VariableSP var;
- Error err;
if (frame && !namespace_decl)
{
- valobj = frame->GetValueForVariableExpressionPath(name_unique_cstr,
- eNoDynamicValues,
- StackFrame::eExpressionPathOptionCheckPtrVsMember |
- StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
- StackFrame::eExpressionPathOptionsNoSyntheticChildren |
- StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
- var,
- err);
-
- // If we found a variable in scope, no need to pull up function names
- if (err.Success() && var)
+ CompilerDeclContext compiler_decl_context = sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() : CompilerDeclContext();
+
+ if (compiler_decl_context)
{
- AddOneVariable(context, var, valobj, current_id);
- context.m_found.variable = true;
- return;
+ // Make sure that the variables are parsed so that we have the declarations
+ VariableListSP vars = frame->GetInScopeVariableList(true);
+ for (size_t i = 0; i < vars->GetSize(); i++)
+ vars->GetVariableAtIndex(i)->GetDecl();
+
+ // Search for declarations matching the name
+ std::vector<CompilerDecl> found_decls = compiler_decl_context.FindDeclByName(name);
+
+ bool variable_found = false;
+ for (CompilerDecl decl : found_decls)
+ {
+ var = decl.GetAsVariable();
+ if (var)
+ {
+ variable_found = true;
+ valobj = ValueObjectVariable::Create(frame, var);
+ AddOneVariable(context, var, valobj, current_id);
+ context.m_found.variable = true;
+ }
+ }
+ if (variable_found)
+ return;
}
}
-
if (target)
{
var = FindGlobalVariable (*target,
@@ -1402,6 +1492,128 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
sc_list);
}
+ // If we found more than one function, see if we can use the
+ // frame's decl context to remove functions that are shadowed
+ // by other functions which match in type but are nearer in scope.
+ //
+ // AddOneFunction will not add a function whose type has already been
+ // added, so if there's another function in the list with a matching
+ // type, check to see if their decl context is a parent of the current
+ // frame's or was imported via a and using statement, and pick the
+ // best match according to lookup rules.
+ if (sc_list.GetSize() > 1)
+ {
+ // Collect some info about our frame's context.
+ StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+ SymbolContext frame_sym_ctx;
+ if (frame != nullptr)
+ frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock);
+ CompilerDeclContext frame_decl_context = frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext() : CompilerDeclContext();
+
+ // We can't do this without a compiler decl context for our frame.
+ if (frame_decl_context)
+ {
+ clang::DeclContext *frame_decl_ctx = (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext();
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(frame_decl_context.GetTypeSystem());
+
+ // Structure to hold the info needed when comparing function
+ // declarations.
+ struct FuncDeclInfo
+ {
+ ConstString m_name;
+ CompilerType m_copied_type;
+ uint32_t m_decl_lvl;
+ SymbolContext m_sym_ctx;
+ };
+
+ // First, symplify things by looping through the symbol contexts
+ // to remove unwanted functions and separate out the functions we
+ // want to compare and prune into a separate list.
+ // Cache the info needed about the function declarations in a
+ // vector for efficiency.
+ SymbolContextList sc_sym_list;
+ uint32_t num_indices = sc_list.GetSize();
+ std::vector<FuncDeclInfo> fdi_cache;
+ fdi_cache.reserve(num_indices);
+ for (uint32_t index = 0; index < num_indices; ++index)
+ {
+ FuncDeclInfo fdi;
+ SymbolContext sym_ctx;
+ sc_list.GetContextAtIndex(index, sym_ctx);
+
+ // We don't know enough about symbols to compare them,
+ // but we should keep them in the list.
+ Function *function = sym_ctx.function;
+ if (!function)
+ {
+ sc_sym_list.Append(sym_ctx);
+ continue;
+ }
+ // Filter out functions without declaration contexts, as well as
+ // class/instance methods, since they'll be skipped in the
+ // code that follows anyway.
+ CompilerDeclContext func_decl_context = function->GetDeclContext();
+ if (!func_decl_context || func_decl_context.IsClassMethod(nullptr, nullptr, nullptr))
+ continue;
+ // We can only prune functions for which we can copy the type.
+ CompilerType func_clang_type = function->GetType()->GetFullCompilerType();
+ CompilerType copied_func_type = GuardedCopyType(func_clang_type);
+ if (!copied_func_type)
+ {
+ sc_sym_list.Append(sym_ctx);
+ continue;
+ }
+
+ fdi.m_sym_ctx = sym_ctx;
+ fdi.m_name = function->GetName();
+ fdi.m_copied_type = copied_func_type;
+ fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL;
+ if (fdi.m_copied_type && func_decl_context)
+ {
+ // Call CountDeclLevels to get the number of parent scopes we
+ // have to look through before we find the function declaration.
+ // When comparing functions of the same type, the one with a
+ // lower count will be closer to us in the lookup scope and
+ // shadows the other.
+ clang::DeclContext *func_decl_ctx = (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext();
+ fdi.m_decl_lvl = ast->CountDeclLevels(frame_decl_ctx,
+ func_decl_ctx,
+ &fdi.m_name,
+ &fdi.m_copied_type);
+ }
+ fdi_cache.emplace_back(fdi);
+ }
+
+ // Loop through the functions in our cache looking for matching types,
+ // then compare their scope levels to see which is closer.
+ std::multimap<CompilerType, const FuncDeclInfo*> matches;
+ for (const FuncDeclInfo &fdi : fdi_cache)
+ {
+ const CompilerType t = fdi.m_copied_type;
+ auto q = matches.find(t);
+ if (q != matches.end())
+ {
+ if (q->second->m_decl_lvl > fdi.m_decl_lvl)
+ // This function is closer; remove the old set.
+ matches.erase(t);
+ else if (q->second->m_decl_lvl < fdi.m_decl_lvl)
+ // The functions in our set are closer - skip this one.
+ continue;
+ }
+ matches.insert(std::make_pair(t, &fdi));
+ }
+
+ // Loop through our matches and add their symbol contexts to our list.
+ SymbolContextList sc_func_list;
+ for (const auto &q : matches)
+ sc_func_list.Append(q.second->m_sym_ctx);
+
+ // Rejoin the lists with the functions in front.
+ sc_list = sc_func_list;
+ sc_list.Append(sc_sym_list);
+ }
+ }
+
if (sc_list.GetSize())
{
Symbol *extern_symbol = NULL;
@@ -1416,15 +1628,13 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (sym_ctx.function)
{
- clang::DeclContext *decl_ctx = sym_ctx.function->GetClangDeclContext();
+ CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext();
if (!decl_ctx)
continue;
// Filter out class/instance methods.
- if (dyn_cast<clang::ObjCMethodDecl>(decl_ctx))
- continue;
- if (dyn_cast<clang::CXXMethodDecl>(decl_ctx))
+ if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr))
continue;
AddOneFunction(context, sym_ctx.function, NULL, current_id);
@@ -1453,7 +1663,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
{
if (llvm::isa<clang::FunctionDecl>(decl))
{
- clang::NamedDecl *copied_decl = llvm::cast<FunctionDecl>(m_ast_importer->CopyDecl(m_ast_context, &decl->getASTContext(), decl));
+ clang::NamedDecl *copied_decl = llvm::cast<FunctionDecl>(m_ast_importer_sp->CopyDecl(m_ast_context, &decl->getASTContext(), decl));
context.AddNamedDecl(copied_decl);
context.m_found.function_with_type_info = true;
}
@@ -1504,7 +1714,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
name.GetCString());
}
- clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
+ clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl) : nullptr;
if (!copied_function_decl)
@@ -1536,7 +1746,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
name.GetCString());
}
- clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
+ clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) : nullptr;
if (!copied_var_decl)
@@ -1577,11 +1787,11 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
}
}
-//static clang_type_t
+//static opaque_compiler_type_t
//MaybePromoteToBlockPointerType
//(
// ASTContext *ast_context,
-// clang_type_t candidate_type
+// opaque_compiler_type_t candidate_type
//)
//{
// if (!candidate_type)
@@ -1632,7 +1842,7 @@ ClangExpressionDeclMap::GetVariableValue (VariableSP &var,
return false;
}
- ClangASTType var_clang_type = var_type->GetClangFullType();
+ CompilerType var_clang_type = var_type->GetFullCompilerType ();
if (!var_clang_type)
{
@@ -1641,7 +1851,17 @@ ClangExpressionDeclMap::GetVariableValue (VariableSP &var,
return false;
}
- ASTContext *ast = var_type->GetClangASTContext().getASTContext();
+ ClangASTContext *clang_ast = llvm::dyn_cast_or_null<ClangASTContext>(var_type->GetForwardCompilerType().GetTypeSystem());
+
+ if (!clang_ast)
+ {
+ if (log)
+ log->PutCString("Skipped a definition because it has no Clang AST");
+ return false;
+ }
+
+
+ ASTContext *ast = clang_ast->getASTContext();
if (!ast)
{
@@ -1673,7 +1893,7 @@ ClangExpressionDeclMap::GetVariableValue (VariableSP &var,
}
}
- ClangASTType type_to_use = GuardedCopyType(var_clang_type);
+ CompilerType type_to_use = GuardedCopyType(var_clang_type);
if (!type_to_use)
{
@@ -1687,7 +1907,7 @@ ClangExpressionDeclMap::GetVariableValue (VariableSP &var,
*parser_type = TypeFromParser(type_to_use);
if (var_location.GetContextType() == Value::eContextTypeInvalid)
- var_location.SetClangType(type_to_use);
+ var_location.SetCompilerType(type_to_use);
if (var_location.GetValueType() == Value::eValueTypeFileAddress)
{
@@ -1752,9 +1972,10 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v
std::string decl_name(context.m_decl_name.getAsString());
ConstString entity_name(decl_name.c_str());
- ClangExpressionVariableSP entity(m_found_entities.CreateVariable (valobj));
+ ClangExpressionVariable *entity(new ClangExpressionVariable(valobj));
+ m_found_entities.AddNewlyConstructedVariable(entity);
- assert (entity.get());
+ assert (entity);
entity->EnableParserVars(GetParserID());
ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
parser_vars->m_parser_type = pt;
@@ -1776,12 +1997,12 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v
void
ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
- ClangExpressionVariableSP &pvar_sp,
+ ExpressionVariableSP &pvar_sp,
unsigned int current_id)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- TypeFromUser user_type (pvar_sp->GetTypeFromUser());
+ TypeFromUser user_type (llvm::cast<ClangExpressionVariable>(pvar_sp.get())->GetTypeFromUser());
TypeFromParser parser_type (GuardedCopyType(user_type));
@@ -1794,8 +2015,8 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
NamedDecl *var_decl = context.AddVarDecl(parser_type.GetLValueReferenceType());
- pvar_sp->EnableParserVars(GetParserID());
- ClangExpressionVariable::ParserVars *parser_vars = pvar_sp->GetParserVars(GetParserID());
+ llvm::cast<ClangExpressionVariable>(pvar_sp.get())->EnableParserVars(GetParserID());
+ ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(pvar_sp.get())->GetParserVars(GetParserID());
parser_vars->m_parser_type = parser_type;
parser_vars->m_named_decl = var_decl;
parser_vars->m_llvm_value = NULL;
@@ -1830,13 +2051,13 @@ ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
std::string decl_name(context.m_decl_name.getAsString());
ConstString entity_name(decl_name.c_str());
- ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (),
- entity_name,
- user_type,
- m_parser_vars->m_target_info.byte_order,
- m_parser_vars->m_target_info.address_byte_size));
- assert (entity.get());
-
+ ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (),
+ entity_name,
+ user_type,
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size));
+ m_found_entities.AddNewlyConstructedVariable(entity);
+
entity->EnableParserVars(GetParserID());
ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
@@ -1844,7 +2065,7 @@ ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target);
//parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType());
- parser_vars->m_lldb_value.SetClangType(user_type);
+ parser_vars->m_lldb_value.SetCompilerType(user_type);
parser_vars->m_lldb_value.GetScalar() = symbol_load_addr;
parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress);
@@ -1867,15 +2088,15 @@ ClangExpressionDeclMap::ResolveUnknownTypes()
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
- ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext();
+ ClangASTContext *scratch_ast_context = target->GetScratchClangASTContext();
for (size_t index = 0, num_entities = m_found_entities.GetSize();
index < num_entities;
++index)
{
- ClangExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index);
+ ExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index);
- ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
+ ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(entity.get())->GetParserVars(GetParserID());
if (entity->m_flags & ClangExpressionVariable::EVUnknownType)
{
@@ -1896,25 +2117,25 @@ ClangExpressionDeclMap::ResolveUnknownTypes()
}
QualType var_type = var_decl->getType();
- TypeFromParser parser_type(var_type.getAsOpaquePtr(), &var_decl->getASTContext());
+ TypeFromParser parser_type(var_type.getAsOpaquePtr(), ClangASTContext::GetASTContext(&var_decl->getASTContext()));
- lldb::clang_type_t copied_type = m_ast_importer->CopyType(scratch_ast_context, &var_decl->getASTContext(), var_type.getAsOpaquePtr());
+ lldb::opaque_compiler_type_t copied_type = m_ast_importer_sp->CopyType(scratch_ast_context->getASTContext(), &var_decl->getASTContext(), var_type.getAsOpaquePtr());
if (!copied_type)
{
if (log)
log->Printf("ClangExpressionDeclMap::ResolveUnknownType - Couldn't import the type for a variable");
- return (bool) lldb::ClangExpressionVariableSP();
+ return (bool) lldb::ExpressionVariableSP();
}
TypeFromUser user_type(copied_type, scratch_ast_context);
// parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType());
- parser_vars->m_lldb_value.SetClangType(user_type);
+ parser_vars->m_lldb_value.SetCompilerType(user_type);
parser_vars->m_parser_type = parser_type;
- entity->SetClangType(user_type);
+ entity->SetCompilerType(user_type);
entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType);
}
@@ -1930,7 +2151,7 @@ ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context,
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- ClangASTType clang_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (m_ast_context,
+ CompilerType clang_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (m_ast_context,
reg_info->encoding,
reg_info->byte_size * 8);
@@ -1945,10 +2166,10 @@ ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context,
NamedDecl *var_decl = context.AddVarDecl(parser_clang_type);
- ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
- m_parser_vars->m_target_info.byte_order,
- m_parser_vars->m_target_info.address_byte_size));
- assert (entity.get());
+ ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size));
+ m_found_entities.AddNewlyConstructedVariable(entity);
std::string decl_name(context.m_decl_name.getAsString());
entity->SetName (ConstString (decl_name.c_str()));
@@ -1980,7 +2201,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
NamedDecl *function_decl = NULL;
Address fun_address;
- ClangASTType function_clang_type;
+ CompilerType function_clang_type;
bool is_indirect_function = false;
@@ -1995,7 +2216,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
return;
}
- function_clang_type = function_type->GetClangFullType();
+ function_clang_type = function_type->GetFullCompilerType ();
if (!function_clang_type)
{
@@ -2006,7 +2227,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
fun_address = function->GetAddressRange().GetBaseAddress();
- ClangASTType copied_function_type = GuardedCopyType(function_clang_type);
+ CompilerType copied_function_type = GuardedCopyType(function_clang_type);
if (copied_function_type)
{
function_decl = context.AddFunDecl(copied_function_type);
@@ -2053,14 +2274,14 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
lldb::addr_t load_addr = fun_address.GetCallableLoadAddress(target, is_indirect_function);
- ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (),
- m_parser_vars->m_target_info.byte_order,
- m_parser_vars->m_target_info.address_byte_size));
- assert (entity.get());
+ ClangExpressionVariable *entity(new ClangExpressionVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (),
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size));
+ m_found_entities.AddNewlyConstructedVariable(entity);
std::string decl_name(context.m_decl_name.getAsString());
entity->SetName(ConstString(decl_name.c_str()));
- entity->SetClangType (function_clang_type);
+ entity->SetCompilerType (function_clang_type);
entity->EnableParserVars(GetParserID());
ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
@@ -2101,28 +2322,29 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
}
}
-TypeFromParser
-ClangExpressionDeclMap::CopyClassType(TypeFromUser &ut,
- unsigned int current_id)
+void
+ClangExpressionDeclMap::AddThisType(NameSearchContext &context,
+ TypeFromUser &ut,
+ unsigned int current_id)
{
- ClangASTType copied_clang_type = GuardedCopyType(ut);
+ CompilerType copied_clang_type = GuardedCopyType(ut);
if (!copied_clang_type)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
- log->Printf("ClangExpressionDeclMap::CopyClassType - Couldn't import the type");
+ log->Printf("ClangExpressionDeclMap::AddThisType - Couldn't import the type");
- return TypeFromParser();
+ return;
}
if (copied_clang_type.IsAggregateType() && copied_clang_type.GetCompleteType ())
{
- ClangASTType void_clang_type = ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid);
- ClangASTType void_ptr_clang_type = void_clang_type.GetPointerType();
+ CompilerType void_clang_type = ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid);
+ CompilerType void_ptr_clang_type = void_clang_type.GetPointerType();
- ClangASTType method_type = ClangASTContext::CreateFunctionType (m_ast_context,
+ CompilerType method_type = ClangASTContext::CreateFunctionType (m_ast_context,
void_clang_type,
&void_ptr_clang_type,
1,
@@ -2136,18 +2358,44 @@ ClangExpressionDeclMap::CopyClassType(TypeFromUser &ut,
const bool is_attr_used = true;
const bool is_artificial = false;
- copied_clang_type.AddMethodToCXXRecordType ("$__lldb_expr",
- method_type,
- lldb::eAccessPublic,
- is_virtual,
- is_static,
- is_inline,
- is_explicit,
- is_attr_used,
- is_artificial);
+ ClangASTContext::GetASTContext(m_ast_context)->
+ AddMethodToCXXRecordType (copied_clang_type.GetOpaqueQualType(),
+ "$__lldb_expr",
+ method_type,
+ lldb::eAccessPublic,
+ is_virtual,
+ is_static,
+ is_inline,
+ is_explicit,
+ is_attr_used,
+ is_artificial);
}
- return TypeFromParser(copied_clang_type);
+ if (!copied_clang_type.IsValid())
+ return;
+
+ TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo(QualType::getFromOpaquePtr(copied_clang_type.GetOpaqueQualType()));
+
+ if (!type_source_info)
+ return;
+
+ // Construct a typedef type because if "*this" is a templated type we can't just return ClassTemplateSpecializationDecls in response to name queries.
+ // Using a typedef makes this much more robust.
+
+ TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context,
+ m_ast_context->getTranslationUnitDecl(),
+ SourceLocation(),
+ SourceLocation(),
+ context.m_decl_name.getAsIdentifierInfo(),
+ type_source_info);
+
+
+ if (!typedef_decl)
+ return;
+
+ context.AddNamedDecl(typedef_decl);
+
+ return;
}
void
@@ -2155,7 +2403,7 @@ ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
TypeFromUser &ut,
unsigned int current_id)
{
- ClangASTType copied_clang_type = GuardedCopyType(ut);
+ CompilerType copied_clang_type = GuardedCopyType(ut);
if (!copied_clang_type)
{
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpressionDeclMap.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
index f24500a..b3f890c 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpressionDeclMap.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -17,16 +17,16 @@
// C++ Includes
#include <vector>
+#include "ClangExpressionVariable.h"
+#include "ClangASTSource.h"
+
// Other libraries and framework includes
// Project includes
-#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "clang/AST/Decl.h"
#include "lldb/lldb-public.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Symbol/TaggedASTType.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -71,16 +71,21 @@ public:
/// the result persistent variable, and instead marks the variable
/// as persisting.
///
+ /// @param[in] delegate
+ /// If non-NULL, use this delegate to report result values. This
+ /// allows the client ClangUserExpression to report a result.
+ ///
/// @param[in] exe_ctx
/// The execution context to use when parsing.
//------------------------------------------------------------------
ClangExpressionDeclMap (bool keep_result_in_memory,
+ Materializer::PersistentVariableDelegate *result_delegate,
ExecutionContext &exe_ctx);
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- ~ClangExpressionDeclMap ();
+ ~ClangExpressionDeclMap() override;
//------------------------------------------------------------------
/// Enable the state needed for parsing and IR transformation.
@@ -354,7 +359,7 @@ public:
/// True on success; false otherwise.
//------------------------------------------------------------------
void
- FindExternalVisibleDecls (NameSearchContext &context);
+ FindExternalVisibleDecls(NameSearchContext &context) override;
//------------------------------------------------------------------
/// Find all entities matching a given name in a given module/namespace,
@@ -385,12 +390,13 @@ public:
void
FindExternalVisibleDecls (NameSearchContext &context,
lldb::ModuleSP module,
- ClangNamespaceDecl &namespace_decl,
+ CompilerDeclContext &namespace_decl,
unsigned int current_id);
private:
- ClangExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser.
- ClangExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct.
- bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory.
+ ExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser.
+ ExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct.
+ bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory.
+ Materializer::PersistentVariableDelegate *m_result_delegate; ///< If non-NULL, used to report expression results to ClangUserExpression.
//----------------------------------------------------------------------
/// The following values should not live beyond parsing
@@ -546,7 +552,7 @@ private:
FindGlobalVariable (Target &target,
lldb::ModuleSP &module,
const ConstString &name,
- ClangNamespaceDecl *namespace_decl,
+ CompilerDeclContext *namespace_decl,
TypeFromUser *type = NULL);
//------------------------------------------------------------------
@@ -616,7 +622,7 @@ private:
//------------------------------------------------------------------
void
AddOneVariable (NameSearchContext &context,
- lldb::ClangExpressionVariableSP &pvar_sp,
+ lldb::ExpressionVariableSP &pvar_sp,
unsigned int current_id);
//------------------------------------------------------------------
@@ -688,18 +694,21 @@ private:
unsigned int current_id);
//------------------------------------------------------------------
- /// Copy a C++ class type into the parser's AST context and add a
- /// member function declaration to it for the expression.
+ /// Generate a Decl for "*this" and add a member function declaration
+ /// to it for the expression, then report it.
+ ///
+ /// @param[in] context
+ /// The NameSearchContext to use when constructing the Decl.
///
/// @param[in] type
- /// The type that needs to be created.
+ /// The type for *this.
//------------------------------------------------------------------
-
- TypeFromParser
- CopyClassType(TypeFromUser &type,
- unsigned int current_id);
+ void
+ AddThisType(NameSearchContext &context,
+ TypeFromUser &type,
+ unsigned int current_id);
};
} // namespace lldb_private
-#endif // liblldb_ClangExpressionDeclMap_h_
+#endif // liblldb_ClangExpressionDeclMap_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
new file mode 100644
index 0000000..bb620de
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
@@ -0,0 +1,79 @@
+//===-- ClangExpression.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangExpression_h_
+#define liblldb_ClangExpression_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/ExpressionTypeSystemHelper.h"
+
+namespace lldb_private {
+
+class RecordingMemoryManager;
+
+//----------------------------------------------------------------------
+// ClangExpressionHelper
+//----------------------------------------------------------------------
+class ClangExpressionHelper : public ExpressionTypeSystemHelper
+{
+public:
+ static bool classof(const ExpressionTypeSystemHelper *ts)
+ {
+ return ts->getKind() == eKindClangHelper;
+ }
+
+ ClangExpressionHelper () :
+ ExpressionTypeSystemHelper(ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper)
+ {
+ }
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ virtual ~ClangExpressionHelper ()
+ {
+ }
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ virtual ClangExpressionDeclMap *
+ DeclMap () = 0;
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ virtual clang::ASTConsumer *
+ ASTTransformer (clang::ASTConsumer *passthrough) = 0;
+
+
+protected:
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangExpression_h_
diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangExpressionParser.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 2b344b0..72c33fe 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ClangExpressionParser.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -7,36 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Expression/ClangExpressionParser.h"
-
-#include "lldb/Core/ArchSpec.h"
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Disassembler.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Expression/IRExecutionUnit.h"
-#include "lldb/Expression/IRDynamicChecks.h"
-#include "lldb/Expression/IRInterpreter.h"
-#include "lldb/Host/File.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
-
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/CodeGen/CodeGenAction.h"
@@ -69,6 +46,37 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/Signals.h"
+// Project includes
+#include "ClangExpressionParser.h"
+
+#include "ClangASTSource.h"
+#include "ClangExpressionHelper.h"
+#include "ClangExpressionDeclMap.h"
+#include "ClangModulesDeclVendor.h"
+#include "ClangPersistentVariables.h"
+#include "IRForTarget.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRDynamicChecks.h"
+#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Host/File.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
using namespace clang;
using namespace llvm;
using namespace lldb_private;
@@ -99,6 +107,7 @@ class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks
ClangPersistentVariables &m_persistent_vars;
StreamString m_error_stream;
bool m_has_errors = false;
+
public:
LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor,
ClangPersistentVariables &persistent_vars) :
@@ -107,9 +116,10 @@ public:
{
}
- virtual void moduleImport(SourceLocation import_location,
- ModuleIdPath path,
- const clang::Module * /*null*/)
+ void
+ moduleImport(SourceLocation import_location,
+ clang::ModuleIdPath path,
+ const clang::Module * /*null*/) override
{
std::vector<ConstString> string_path;
@@ -149,9 +159,9 @@ public:
//===----------------------------------------------------------------------===//
ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
- ClangExpression &expr,
+ Expression &expr,
bool generate_debug_info) :
- m_expr (expr),
+ ExpressionParser (exe_scope, expr, generate_debug_info),
m_compiler (),
m_code_generator (),
m_pp_callbacks(nullptr)
@@ -210,17 +220,38 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
switch (language)
{
case lldb::eLanguageTypeC:
+ case lldb::eLanguageTypeC89:
+ case lldb::eLanguageTypeC99:
+ case lldb::eLanguageTypeC11:
+ // FIXME: the following language option is a temporary workaround,
+ // to "ask for C, get C++."
+ // For now, the expression parser must use C++ anytime the
+ // language is a C family language, because the expression parser
+ // uses features of C++ to capture values.
+ m_compiler->getLangOpts().CPlusPlus = true;
break;
case lldb::eLanguageTypeObjC:
m_compiler->getLangOpts().ObjC1 = true;
m_compiler->getLangOpts().ObjC2 = true;
+ // FIXME: the following language option is a temporary workaround,
+ // to "ask for ObjC, get ObjC++" (see comment above).
+ m_compiler->getLangOpts().CPlusPlus = true;
break;
case lldb::eLanguageTypeC_plus_plus:
- m_compiler->getLangOpts().CPlusPlus = true;
+ case lldb::eLanguageTypeC_plus_plus_11:
+ case lldb::eLanguageTypeC_plus_plus_14:
m_compiler->getLangOpts().CPlusPlus11 = true;
m_compiler->getHeaderSearchOpts().UseLibcxx = true;
+ // fall thru ...
+ case lldb::eLanguageTypeC_plus_plus_03:
+ m_compiler->getLangOpts().CPlusPlus = true;
+ // FIXME: the following language option is a temporary workaround,
+ // to "ask for C++, get ObjC++". Apple hopes to remove this requirement
+ // on non-Apple platforms, but for now it is needed.
+ m_compiler->getLangOpts().ObjC1 = true;
break;
case lldb::eLanguageTypeObjC_plus_plus:
+ case lldb::eLanguageTypeUnknown:
default:
m_compiler->getLangOpts().ObjC1 = true;
m_compiler->getLangOpts().ObjC2 = true;
@@ -234,7 +265,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
m_compiler->getLangOpts().WChar = true;
m_compiler->getLangOpts().Blocks = true;
m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients
- if (expr.DesiredResultType() == ClangExpression::eResultTypeId)
+ if (expr.DesiredResultType() == Expression::eResultTypeId)
m_compiler->getLangOpts().DebuggerCastResultToId = true;
m_compiler->getLangOpts().CharIsSigned =
@@ -254,7 +285,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
{
if (process_sp->GetObjCLanguageRuntime())
{
- if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == eAppleObjC_V2)
+ if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2)
m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
else
m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7));
@@ -307,7 +338,8 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor())
{
- std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, target_sp->GetPersistentVariables()));
+ ClangPersistentVariables *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(target_sp->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
+ std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars));
m_pp_callbacks = static_cast<LLDBPreprocessorCallbacks*>(pp_callbacks.get());
m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
}
@@ -325,7 +357,8 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
ast_context->InitBuiltinTypes(m_compiler->getTarget());
- ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
+ ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
+ ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap();
if (decl_map)
{
@@ -334,6 +367,8 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
ast_context->setExternalSource(ast_source);
}
+ m_ast_context.reset(new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str()));
+ m_ast_context->setASTContext(ast_context.get());
m_compiler->setASTContext(ast_context.release());
std::string module_name("$__lldb_module");
@@ -372,7 +407,7 @@ ClangExpressionParser::Parse (Stream &stream)
if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
{
tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr");
- temp_source_path = std::move(tmpdir_file_spec.GetPath());
+ temp_source_path = tmpdir_file_spec.GetPath();
llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
}
else
@@ -407,15 +442,23 @@ ClangExpressionParser::Parse (Stream &stream)
diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor());
- ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get());
+ ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
- if (ClangExpressionDeclMap *decl_map = m_expr.DeclMap())
+ ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get());
+
+ if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap())
decl_map->InstallCodeGenerator(m_code_generator.get());
-
+
if (ast_transformer)
+ {
+ ast_transformer->Initialize(m_compiler->getASTContext());
ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext());
+ }
else
+ {
+ m_code_generator->Initialize(m_compiler->getASTContext());
ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext());
+ }
diag_buf->EndSourceFile();
@@ -450,7 +493,7 @@ ClangExpressionParser::Parse (Stream &stream)
if (!num_errors)
{
- if (m_expr.DeclMap() && !m_expr.DeclMap()->ResolveUnknownTypes())
+ if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes())
{
stream.Printf("error: Couldn't infer the type of a variable\n");
num_errors++;
@@ -481,7 +524,7 @@ static bool FindFunctionInModule (ConstString &mangled_name,
Error
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
lldb::addr_t &func_end,
- std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
+ lldb::IRExecutionUnitSP &execution_unit_sp,
ExecutionContext &exe_ctx,
bool &can_interpret,
ExecutionPolicy execution_policy)
@@ -523,7 +566,8 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
exe_ctx.GetTargetSP(),
m_compiler->getTargetOpts().Features));
- ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
+ ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
+ ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL
if (decl_map)
{
@@ -611,11 +655,3 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
return err;
}
-
-bool
-ClangExpressionParser::GetGenerateDebugInfo () const
-{
- if (m_compiler)
- return m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo;
- return false;
-}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpressionParser.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
index 21a27a4..3c05538 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpressionParser.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
@@ -14,7 +14,7 @@
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/Error.h"
-#include "lldb/Expression/IRForTarget.h"
+#include "lldb/Expression/ExpressionParser.h"
#include <string>
#include <vector>
@@ -34,7 +34,7 @@ class IRExecutionUnit;
/// conversion to formats (DWARF bytecode, or JIT compiled machine code)
/// that can be executed.
//----------------------------------------------------------------------
-class ClangExpressionParser
+class ClangExpressionParser : public ExpressionParser
{
public:
//------------------------------------------------------------------
@@ -51,13 +51,13 @@ public:
/// The expression to be parsed.
//------------------------------------------------------------------
ClangExpressionParser (ExecutionContextScope *exe_scope,
- ClangExpression &expr,
+ Expression &expr,
bool generate_debug_info);
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- ~ClangExpressionParser ();
+ ~ClangExpressionParser () override;
//------------------------------------------------------------------
/// Parse a single expression and convert it to IR using Clang. Don't
@@ -71,7 +71,7 @@ public:
/// success.
//------------------------------------------------------------------
unsigned
- Parse (Stream &stream);
+ Parse (Stream &stream) override;
//------------------------------------------------------------------
/// Ready an already-parsed expression for execution, possibly
@@ -113,33 +113,12 @@ public:
Error
PrepareForExecution (lldb::addr_t &func_addr,
lldb::addr_t &func_end,
- std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
+ lldb::IRExecutionUnitSP &execution_unit_sp,
ExecutionContext &exe_ctx,
bool &can_interpret,
- lldb_private::ExecutionPolicy execution_policy);
+ lldb_private::ExecutionPolicy execution_policy) override;
- //------------------------------------------------------------------
- /// Disassemble the machine code for a JITted function from the target
- /// process's memory and print the result to a stream.
- ///
- /// @param[in] stream
- /// The stream to print disassembly to.
- ///
- /// @param[in] exc_context
- /// The execution context to get the machine code from.
- ///
- /// @return
- /// The error generated. If .Success() is true, disassembly succeeded.
- //------------------------------------------------------------------
- Error
- DisassembleFunction (Stream &stream,
- ExecutionContext &exe_ctx);
-
- bool
- GetGenerateDebugInfo () const;
-
private:
- ClangExpression & m_expr; ///< The expression to be parsed
std::unique_ptr<llvm::LLVMContext> m_llvm_context; ///< The LLVM context to generate IR into
std::unique_ptr<clang::FileManager> m_file_manager; ///< The Clang file manager object used by the compiler
std::unique_ptr<clang::CompilerInstance> m_compiler; ///< The Clang compiler used to parse expressions into IR
@@ -149,6 +128,7 @@ private:
class LLDBPreprocessorCallbacks;
LLDBPreprocessorCallbacks *m_pp_callbacks; ///< Called when the preprocessor encounters module imports
+ std::unique_ptr<ClangASTContext> m_ast_context;
};
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp
new file mode 100644
index 0000000..908546b
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp
@@ -0,0 +1,76 @@
+//===-- ClangExpressionVariable.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangExpressionVariable.h"
+
+#include "clang/AST/ASTContext.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb_private;
+using namespace clang;
+
+const char *g_clang_expression_variable_kind_name = "ClangExpressionVariable";
+
+ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size) :
+ ExpressionVariable(LLVMCastKind::eKindClang),
+ m_parser_vars(),
+ m_jit_vars ()
+{
+ m_flags = EVNone;
+ m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size);
+}
+
+ClangExpressionVariable::ClangExpressionVariable (ExecutionContextScope *exe_scope,
+ Value &value,
+ const ConstString &name,
+ uint16_t flags) :
+ ExpressionVariable(LLVMCastKind::eKindClang),
+ m_parser_vars(),
+ m_jit_vars ()
+{
+ m_flags = flags;
+ m_frozen_sp = ValueObjectConstResult::Create (exe_scope, value, name);
+}
+
+ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) :
+ ExpressionVariable(LLVMCastKind::eKindClang),
+ m_parser_vars(),
+ m_jit_vars ()
+{
+ m_flags = EVNone;
+ m_frozen_sp = valobj_sp;
+}
+
+ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope,
+ const ConstString &name,
+ const TypeFromUser& user_type,
+ lldb::ByteOrder byte_order,
+ uint32_t addr_byte_size) :
+ ExpressionVariable(LLVMCastKind::eKindClang),
+ m_parser_vars(),
+ m_jit_vars()
+{
+ m_flags = EVNone;
+ m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size);
+ SetName (name);
+ SetCompilerType (user_type);
+}
+
+TypeFromUser
+ClangExpressionVariable::GetTypeFromUser()
+{
+ TypeFromUser tfu (m_frozen_sp->GetCompilerType());
+ return tfu;
+}
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpressionVariable.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
index 6c21010..a459614 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangExpressionVariable.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
@@ -21,11 +21,14 @@
#include <vector>
// Other libraries and framework includes
+#include "llvm/Support/Casting.h"
+
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Value.h"
+#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Symbol/TaggedASTType.h"
namespace llvm {
@@ -34,7 +37,6 @@ namespace llvm {
namespace lldb_private {
-class ClangExpressionVariableList;
class ValueObjectConstResult;
//----------------------------------------------------------------------
@@ -60,7 +62,7 @@ class ValueObjectConstResult;
/// polymorphism, and provides necessary support methods. Its interface
/// is RTTI-neutral.
//----------------------------------------------------------------------
-class ClangExpressionVariable
+class ClangExpressionVariable : public ExpressionVariable
{
public:
ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size);
@@ -71,6 +73,44 @@ public:
uint16_t flags = EVNone);
ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp);
+
+ ClangExpressionVariable(ExecutionContextScope *exe_scope,
+ const ConstString &name,
+ const TypeFromUser& user_type,
+ lldb::ByteOrder byte_order,
+ uint32_t addr_byte_size);
+
+ //----------------------------------------------------------------------
+ /// Utility functions for dealing with ExpressionVariableLists in Clang-specific ways
+ //----------------------------------------------------------------------
+
+ //----------------------------------------------------------------------
+ /// Finds a variable by NamedDecl in the list.
+ ///
+ /// @param[in] name
+ /// The name of the requested variable.
+ ///
+ /// @return
+ /// The variable requested, or NULL if that variable is not in the list.
+ //----------------------------------------------------------------------
+ static ClangExpressionVariable *
+ FindVariableInList (ExpressionVariableList &list, const clang::NamedDecl *decl, uint64_t parser_id)
+ {
+ lldb::ExpressionVariableSP var_sp;
+ for (size_t index = 0, size = list.GetSize(); index < size; ++index)
+ {
+ var_sp = list.GetVariableAtIndex(index);
+
+ if (ClangExpressionVariable *clang_var = llvm::dyn_cast<ClangExpressionVariable>(var_sp.get()))
+ {
+ ClangExpressionVariable::ParserVars *parser_vars = clang_var->GetParserVars(parser_id);
+
+ if (parser_vars && parser_vars->m_named_decl == decl)
+ return clang_var;
+ }
+ }
+ return nullptr;
+ }
//----------------------------------------------------------------------
/// If the variable contains its own data, make a Value point at it.
@@ -90,9 +130,6 @@ public:
bool
PointValueAtData(Value &value, ExecutionContext *exe_ctx);
- lldb::ValueObjectSP
- GetValueObject();
-
//----------------------------------------------------------------------
/// The following values should not live beyond parsing
//----------------------------------------------------------------------
@@ -205,252 +242,24 @@ public:
else
return &i->second;
}
-
- //----------------------------------------------------------------------
- /// Return the variable's size in bytes
- //----------------------------------------------------------------------
- size_t
- GetByteSize ();
-
- const ConstString &
- GetName();
-
- RegisterInfo *
- GetRegisterInfo();
-
- void
- SetRegisterInfo (const RegisterInfo *reg_info);
-
- ClangASTType
- GetClangType ();
- void
- SetClangType (const ClangASTType &clang_type);
-
TypeFromUser
GetTypeFromUser ();
-
- uint8_t *
- GetValueBytes ();
- void
- SetName (const ConstString &name);
-
- void
- ValueUpdated ();
-
- // this function is used to copy the address-of m_live_sp into m_frozen_sp
- // this is necessary because the results of certain cast and pointer-arithmetic
- // operations (such as those described in bugzilla issues 11588 and 11618) generate
- // frozen objects that do not have a valid address-of, which can be troublesome when
- // using synthetic children providers. Transferring the address-of the live object
- // solves these issues and provides the expected user-level behavior
- void
- TransferAddress (bool force = false);
-
- typedef std::shared_ptr<ValueObjectConstResult> ValueObjectConstResultSP;
-
- //----------------------------------------------------------------------
- /// Members
- //----------------------------------------------------------------------
- enum Flags
- {
- EVNone = 0,
- EVIsLLDBAllocated = 1 << 0, ///< This variable is resident in a location specifically allocated for it by LLDB in the target process
- EVIsProgramReference = 1 << 1, ///< This variable is a reference to a (possibly invalid) area managed by the target program
- EVNeedsAllocation = 1 << 2, ///< Space for this variable has yet to be allocated in the target process
- EVIsFreezeDried = 1 << 3, ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results)
- EVNeedsFreezeDry = 1 << 4, ///< Copy from m_live_sp to m_frozen_sp during dematerialization
- EVKeepInTarget = 1 << 5, ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it
- EVTypeIsReference = 1 << 6, ///< The original type of this variable is a reference, so materialize the value rather than the location
- EVUnknownType = 1 << 7, ///< This is a symbol of unknown type, and the type must be resolved after parsing is complete
- EVBareRegister = 1 << 8 ///< This variable is a direct reference to $pc or some other entity.
- };
-
- typedef uint16_t FlagType;
-
- FlagType m_flags; // takes elements of Flags
-
- lldb::ValueObjectSP m_frozen_sp;
- lldb::ValueObjectSP m_live_sp;
-
- DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable);
-};
-
-//----------------------------------------------------------------------
-/// @class ClangExpressionVariableListBase ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h"
-/// @brief A list of variable references.
-///
-/// This class stores variables internally, acting as the permanent store.
-//----------------------------------------------------------------------
-class ClangExpressionVariableList
-{
-public:
- //----------------------------------------------------------------------
- /// Implementation of methods in ClangExpressionVariableListBase
- //----------------------------------------------------------------------
- size_t
- GetSize()
- {
- return m_variables.size();
- }
-
- lldb::ClangExpressionVariableSP
- GetVariableAtIndex(size_t index)
- {
- lldb::ClangExpressionVariableSP var_sp;
- if (index < m_variables.size())
- var_sp = m_variables[index];
- return var_sp;
- }
-
- size_t
- AddVariable (const lldb::ClangExpressionVariableSP &var_sp)
- {
- m_variables.push_back(var_sp);
- return m_variables.size() - 1;
- }
-
- bool
- ContainsVariable (const lldb::ClangExpressionVariableSP &var_sp)
- {
- const size_t size = m_variables.size();
- for (size_t index = 0; index < size; ++index)
- {
- if (m_variables[index].get() == var_sp.get())
- return true;
- }
- return false;
- }
-
- //----------------------------------------------------------------------
- /// Finds a variable by name in the list.
- ///
- /// @param[in] name
- /// The name of the requested variable.
- ///
- /// @return
- /// The variable requested, or NULL if that variable is not in the list.
- //----------------------------------------------------------------------
- lldb::ClangExpressionVariableSP
- GetVariable (const ConstString &name)
- {
- lldb::ClangExpressionVariableSP var_sp;
- for (size_t index = 0, size = GetSize(); index < size; ++index)
- {
- var_sp = GetVariableAtIndex(index);
- if (var_sp->GetName() == name)
- return var_sp;
- }
- var_sp.reset();
- return var_sp;
- }
-
- lldb::ClangExpressionVariableSP
- GetVariable (const char *name)
+ //------------------------------------------------------------------
+ // llvm casting support
+ //------------------------------------------------------------------
+ static bool classof(const ExpressionVariable *ev)
{
- lldb::ClangExpressionVariableSP var_sp;
- if (name && name[0])
- {
- for (size_t index = 0, size = GetSize(); index < size; ++index)
- {
- var_sp = GetVariableAtIndex(index);
- const char *var_name_cstr = var_sp->GetName().GetCString();
- if (!var_name_cstr || !name)
- continue;
- if (::strcmp (var_name_cstr, name) == 0)
- return var_sp;
- }
- var_sp.reset();
- }
- return var_sp;
+ return ev->getKind() == ExpressionVariable::eKindClang;
}
//----------------------------------------------------------------------
- /// Finds a variable by NamedDecl in the list.
- ///
- /// @param[in] name
- /// The name of the requested variable.
- ///
- /// @return
- /// The variable requested, or NULL if that variable is not in the list.
- //----------------------------------------------------------------------
- lldb::ClangExpressionVariableSP
- GetVariable (const clang::NamedDecl *decl, uint64_t parser_id)
- {
- lldb::ClangExpressionVariableSP var_sp;
- for (size_t index = 0, size = GetSize(); index < size; ++index)
- {
- var_sp = GetVariableAtIndex(index);
-
- ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(parser_id);
-
- if (parser_vars && parser_vars->m_named_decl == decl)
- return var_sp;
- }
- var_sp.reset();
- return var_sp;
- }
-
- //----------------------------------------------------------------------
- /// Create a new variable in the list and return its index
- //----------------------------------------------------------------------
- lldb::ClangExpressionVariableSP
- CreateVariable (ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size)
- {
- lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size));
- m_variables.push_back(var_sp);
- return var_sp;
- }
-
- lldb::ClangExpressionVariableSP
- CreateVariable(const lldb::ValueObjectSP &valobj_sp)
- {
- lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(valobj_sp));
- m_variables.push_back(var_sp);
- return var_sp;
- }
-
- lldb::ClangExpressionVariableSP
- CreateVariable (ExecutionContextScope *exe_scope,
- const ConstString &name,
- const TypeFromUser& user_type,
- lldb::ByteOrder byte_order,
- uint32_t addr_byte_size)
- {
- lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size));
- var_sp->SetName (name);
- var_sp->SetClangType (user_type);
- m_variables.push_back(var_sp);
- return var_sp;
- }
-
- void
- RemoveVariable (lldb::ClangExpressionVariableSP var_sp)
- {
- for (std::vector<lldb::ClangExpressionVariableSP>::iterator vi = m_variables.begin(), ve = m_variables.end();
- vi != ve;
- ++vi)
- {
- if (vi->get() == var_sp.get())
- {
- m_variables.erase(vi);
- return;
- }
- }
- }
-
- void
- Clear()
- {
- m_variables.clear();
- }
-
-private:
- std::vector <lldb::ClangExpressionVariableSP> m_variables;
+ /// Members
+ //----------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable);
};
-
} // namespace lldb_private
#endif // liblldb_ClangExpressionVariable_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
new file mode 100644
index 0000000..0d0d747
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
@@ -0,0 +1,221 @@
+//===-- ClangFunctionCallerCaller.cpp ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangFunctionCaller.h"
+
+#include "ASTStructExtractor.h"
+#include "ClangExpressionParser.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/IR/Module.h"
+
+// Project includes
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallFunction.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ClangFunctionCaller constructor
+//----------------------------------------------------------------------
+ClangFunctionCaller::ClangFunctionCaller
+(
+ ExecutionContextScope &exe_scope,
+ const CompilerType &return_type,
+ const Address& functionAddress,
+ const ValueList &arg_value_list,
+ const char *name
+) :
+ FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list, name),
+ m_type_system_helper (*this)
+{
+ m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
+ // Can't make a ClangFunctionCaller without a process.
+ assert (m_jit_process_wp.lock());
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ClangFunctionCaller::~ClangFunctionCaller()
+{
+}
+
+unsigned
+ClangFunctionCaller::CompileFunction (Stream &errors)
+{
+ if (m_compiled)
+ return 0;
+
+ // FIXME: How does clang tell us there's no return value? We need to handle that case.
+ unsigned num_errors = 0;
+
+ std::string return_type_str (m_function_return_type.GetTypeName().AsCString(""));
+
+ // Cons up the function we're going to wrap our call in, then compile it...
+ // We declare the function "extern "C"" because the compiler might be in C++
+ // mode which would mangle the name and then we couldn't find it again...
+ m_wrapper_function_text.clear();
+ m_wrapper_function_text.append ("extern \"C\" void ");
+ m_wrapper_function_text.append (m_wrapper_function_name);
+ m_wrapper_function_text.append (" (void *input)\n{\n struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append (" \n {\n");
+ m_wrapper_function_text.append (" ");
+ m_wrapper_function_text.append (return_type_str);
+ m_wrapper_function_text.append (" (*fn_ptr) (");
+
+ // Get the number of arguments. If we have a function type and it is prototyped,
+ // trust that, otherwise use the values we were given.
+
+ // FIXME: This will need to be extended to handle Variadic functions. We'll need
+ // to pull the defined arguments out of the function, then add the types from the
+ // arguments list for the variable arguments.
+
+ uint32_t num_args = UINT32_MAX;
+ bool trust_function = false;
+ // GetArgumentCount returns -1 for an unprototyped function.
+ CompilerType function_clang_type;
+ if (m_function_ptr)
+ {
+ function_clang_type = m_function_ptr->GetCompilerType();
+ if (function_clang_type)
+ {
+ int num_func_args = function_clang_type.GetFunctionArgumentCount();
+ if (num_func_args >= 0)
+ {
+ trust_function = true;
+ num_args = num_func_args;
+ }
+ }
+ }
+
+ if (num_args == UINT32_MAX)
+ num_args = m_arg_values.GetSize();
+
+ std::string args_buffer; // This one stores the definition of all the args in "struct caller".
+ std::string args_list_buffer; // This one stores the argument list called from the structure.
+ for (size_t i = 0; i < num_args; i++)
+ {
+ std::string type_name;
+
+ if (trust_function)
+ {
+ type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString("");
+ }
+ else
+ {
+ CompilerType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetCompilerType ();
+ if (clang_qual_type)
+ {
+ type_name = clang_qual_type.GetTypeName().AsCString("");
+ }
+ else
+ {
+ errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i);
+ return 1;
+ }
+ }
+
+ m_wrapper_function_text.append (type_name);
+ if (i < num_args - 1)
+ m_wrapper_function_text.append (", ");
+
+ char arg_buf[32];
+ args_buffer.append (" ");
+ args_buffer.append (type_name);
+ snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i);
+ args_buffer.push_back (' ');
+ args_buffer.append (arg_buf);
+ args_buffer.append (";\n");
+
+ args_list_buffer.append ("__lldb_fn_data->");
+ args_list_buffer.append (arg_buf);
+ if (i < num_args - 1)
+ args_list_buffer.append (", ");
+
+ }
+ m_wrapper_function_text.append (");\n"); // Close off the function calling prototype.
+
+ m_wrapper_function_text.append (args_buffer);
+
+ m_wrapper_function_text.append (" ");
+ m_wrapper_function_text.append (return_type_str);
+ m_wrapper_function_text.append (" return_value;");
+ m_wrapper_function_text.append ("\n };\n struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append ("* __lldb_fn_data = (struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append (" *) input;\n");
+
+ m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
+ m_wrapper_function_text.append (args_list_buffer);
+ m_wrapper_function_text.append (");\n}\n");
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ if (log)
+ log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str());
+
+ // Okay, now compile this expression
+
+ lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
+ if (jit_process_sp)
+ {
+ const bool generate_debug_info = true;
+ m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info));
+
+ num_errors = m_parser->Parse (errors);
+ }
+ else
+ {
+ errors.Printf("no process - unable to inject function");
+ num_errors = 1;
+ }
+
+ m_compiled = (num_errors == 0);
+
+ if (!m_compiled)
+ return num_errors;
+
+ return num_errors;
+}
+
+clang::ASTConsumer *
+ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer (clang::ASTConsumer *passthrough)
+{
+ m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_owner.GetWrapperStructName(), m_owner));
+
+ return m_struct_extractor.get();
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
new file mode 100644
index 0000000..3e30f81
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
@@ -0,0 +1,173 @@
+//===-- ClangFunctionCaller.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangFunctionCaller_h_
+#define liblldb_ClangFunctionCaller_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "ClangExpressionHelper.h"
+
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Target/Process.h"
+
+namespace lldb_private
+{
+
+class ASTStructExtractor;
+class ClangExpressionParser;
+
+//----------------------------------------------------------------------
+/// @class ClangFunctionCaller ClangFunctionCaller.h "lldb/Expression/ClangFunctionCaller.h"
+/// @brief Encapsulates a function that can be called.
+///
+/// A given ClangFunctionCaller object can handle a single function signature.
+/// Once constructed, it can set up any number of concurrent calls to
+/// functions with that signature.
+///
+/// It performs the call by synthesizing a structure that contains the pointer
+/// to the function and the arguments that should be passed to that function,
+/// and producing a special-purpose JIT-compiled function that accepts a void*
+/// pointing to this struct as its only argument and calls the function in the
+/// struct with the written arguments. This method lets Clang handle the
+/// vagaries of function calling conventions.
+///
+/// The simplest use of the ClangFunctionCaller is to construct it with a
+/// function representative of the signature you want to use, then call
+/// ExecuteFunction(ExecutionContext &, Stream &, Value &).
+///
+/// If you need to reuse the arguments for several calls, you can call
+/// InsertFunction() followed by WriteFunctionArguments(), which will return
+/// the location of the args struct for the wrapper function in args_addr_ref.
+///
+/// If you need to call the function on the thread plan stack, you can also
+/// call InsertFunction() followed by GetThreadPlanToCallFunction().
+///
+/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed
+/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated
+/// and its address returned in that variable.
+///
+/// Any of the methods that take arg_addr_ptr can be passed NULL, and the
+/// argument space will be managed for you.
+//----------------------------------------------------------------------
+class ClangFunctionCaller : public FunctionCaller
+{
+ friend class ASTStructExtractor;
+
+ class ClangFunctionCallerHelper : public ClangExpressionHelper
+ {
+ public:
+ ClangFunctionCallerHelper (ClangFunctionCaller &owner) :
+ m_owner(owner)
+ {
+ }
+
+ ~ClangFunctionCallerHelper() override = default;
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ ClangExpressionDeclMap *
+ DeclMap() override
+ {
+ return NULL;
+ }
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ clang::ASTConsumer *
+ ASTTransformer(clang::ASTConsumer *passthrough) override;
+
+ private:
+ ClangFunctionCaller &m_owner;
+ std::unique_ptr<ASTStructExtractor> m_struct_extractor; ///< The class that generates the argument struct layout.
+ };
+
+public:
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] exe_scope
+ /// An execution context scope that gets us at least a target and
+ /// process.
+ ///
+ /// @param[in] ast_context
+ /// The AST context to evaluate argument types in.
+ ///
+ /// @param[in] return_qualtype
+ /// An opaque Clang QualType for the function result. Should be
+ /// defined in ast_context.
+ ///
+ /// @param[in] function_address
+ /// The address of the function to call.
+ ///
+ /// @param[in] arg_value_list
+ /// The default values to use when calling this function. Can
+ /// be overridden using WriteFunctionArguments().
+ //------------------------------------------------------------------
+ ClangFunctionCaller (ExecutionContextScope &exe_scope,
+ const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name);
+
+ ~ClangFunctionCaller() override;
+
+ //------------------------------------------------------------------
+ /// Compile the wrapper function
+ ///
+ /// @param[in] errors
+ /// The stream to print parser errors to.
+ ///
+ /// @return
+ /// The number of errors.
+ //------------------------------------------------------------------
+ unsigned
+ CompileFunction (Stream &errors) override;
+
+ ExpressionTypeSystemHelper *
+ GetTypeSystemHelper () override
+ {
+ return &m_type_system_helper;
+ }
+
+protected:
+ const char *GetWrapperStructName()
+ {
+ return m_wrapper_struct_name.c_str();
+ }
+
+private:
+ //------------------------------------------------------------------
+ // For ClangFunctionCaller only
+ //------------------------------------------------------------------
+
+ // Note: the parser needs to be destructed before the execution unit, so
+ // declare the execution unit first.
+ ClangFunctionCallerHelper m_type_system_helper;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangFunctionCaller_h_
diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangModulesDeclVendor.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
index e825363..05d8a320 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ClangModulesDeclVendor.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -7,9 +7,21 @@
//
//===----------------------------------------------------------------------===//
-#include <mutex> // std::once
+// C Includes
+// C++ Includes
+#include <mutex>
-#include "lldb/Expression/ClangModulesDeclVendor.h"
+// Other libraries and framework includes
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Serialization/ASTReader.h"
+
+// Project includes
+#include "ClangModulesDeclVendor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
@@ -20,15 +32,6 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBAssert.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendActions.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/Parser.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Serialization/ASTReader.h"
-
-
using namespace lldb_private;
namespace {
@@ -38,14 +41,17 @@ namespace {
{
public:
StoringDiagnosticConsumer ();
+
void
- HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info);
+ HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
+ const clang::Diagnostic &info) override;
void
ClearDiagnostics ();
void
DumpDiagnostics (Stream &error_stream);
+
private:
typedef std::pair<clang::DiagnosticsEngine::Level, std::string> IDAndDiagnostic;
std::vector<IDAndDiagnostic> m_diagnostics;
@@ -61,29 +67,29 @@ namespace {
llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation,
std::unique_ptr<clang::CompilerInstance> &&compiler_instance,
std::unique_ptr<clang::Parser> &&parser);
-
- virtual bool
+
+ ~ClangModulesDeclVendorImpl() override = default;
+
+ bool
AddModule(ModulePath &path,
ModuleVector *exported_modules,
Stream &error_stream) override;
-
- virtual bool
+
+ bool
AddModulesForCompileUnit(CompileUnit &cu,
ModuleVector &exported_modules,
Stream &error_stream) override;
+
+ uint32_t
+ FindDecls(const ConstString &name,
+ bool append,
+ uint32_t max_matches,
+ std::vector <clang::NamedDecl*> &decls) override;
- virtual uint32_t
- FindDecls (const ConstString &name,
- bool append,
- uint32_t max_matches,
- std::vector <clang::NamedDecl*> &decls) override;
-
- virtual void
+ void
ForEachMacro(const ModuleVector &modules,
std::function<bool (const std::string &)> handler) override;
- ~ClangModulesDeclVendorImpl();
-
private:
void
ReportModuleExportsHelper (std::set<ClangModulesDeclVendor::ModuleID> &exports,
@@ -110,7 +116,7 @@ namespace {
ImportedModuleMap m_imported_modules;
ImportedModuleSet m_user_imported_modules;
};
-}
+} // anonymous namespace
StoringDiagnosticConsumer::StoringDiagnosticConsumer ()
{
@@ -164,7 +170,6 @@ GetResourceDir ()
return g_cached_resource_dir;
}
-
ClangModulesDeclVendor::ClangModulesDeclVendor()
{
}
@@ -318,7 +323,6 @@ ClangModulesDeclVendorImpl::AddModule(ModulePath &path,
return false;
}
-
bool
ClangModulesDeclVendor::LanguageSupportsClangModules (lldb::LanguageType language)
{
@@ -597,10 +601,6 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec
}
}
-ClangModulesDeclVendorImpl::~ClangModulesDeclVendorImpl()
-{
-}
-
clang::ModuleLoadResult
ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
bool make_visible)
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangModulesDeclVendor.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h
index a8297c8..df3b205 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangModulesDeclVendor.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef _liblldb_ClangModulesDeclVendor_
-#define _liblldb_ClangModulesDeclVendor_
+#ifndef liblldb_ClangModulesDeclVendor_h
+#define liblldb_ClangModulesDeclVendor_h
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/ClangForward.h"
@@ -29,8 +29,7 @@ public:
//------------------------------------------------------------------
ClangModulesDeclVendor();
- virtual
- ~ClangModulesDeclVendor();
+ ~ClangModulesDeclVendor() override;
static ClangModulesDeclVendor *
Create(Target &target);
@@ -122,8 +121,8 @@ public:
//------------------------------------------------------------------
static bool
LanguageSupportsClangModules (lldb::LanguageType language);
-
};
-}
-#endif /* defined(_lldb_ClangModulesDeclVendor_) */
+} // namespace lldb_private
+
+#endif // liblldb_ClangModulesDeclVendor_h
diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangPersistentVariables.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
index db062d2..9bf9d43 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ClangPersistentVariables.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
@@ -7,7 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Expression/ClangPersistentVariables.h"
+#include "ClangPersistentVariables.h"
+
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
@@ -19,35 +20,29 @@ using namespace lldb;
using namespace lldb_private;
ClangPersistentVariables::ClangPersistentVariables () :
- ClangExpressionVariableList(),
+ lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang),
m_next_persistent_variable_id (0)
{
}
-ClangExpressionVariableSP
+ExpressionVariableSP
ClangPersistentVariables::CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp)
{
- ClangExpressionVariableSP var_sp (CreateVariable(valobj_sp));
- return var_sp;
+ return AddNewlyConstructedVariable(new ClangExpressionVariable(valobj_sp));
}
-ClangExpressionVariableSP
+ExpressionVariableSP
ClangPersistentVariables::CreatePersistentVariable (ExecutionContextScope *exe_scope,
const ConstString &name,
- const TypeFromUser& user_type,
+ const CompilerType& compiler_type,
lldb::ByteOrder byte_order,
uint32_t addr_byte_size)
{
- ClangExpressionVariableSP var_sp (GetVariable(name));
-
- if (!var_sp)
- var_sp = CreateVariable(exe_scope, name, user_type, byte_order, addr_byte_size);
-
- return var_sp;
+ return AddNewlyConstructedVariable(new ClangExpressionVariable(exe_scope, name, compiler_type, byte_order, addr_byte_size));
}
void
-ClangPersistentVariables::RemovePersistentVariable (lldb::ClangExpressionVariableSP variable)
+ClangPersistentVariables::RemovePersistentVariable (lldb::ExpressionVariableSP variable)
{
RemoveVariable(variable);
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangPersistentVariables.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
index 247f87f..0e03d01 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/ClangPersistentVariables.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
@@ -10,11 +10,17 @@
#ifndef liblldb_ClangPersistentVariables_h_
#define liblldb_ClangPersistentVariables_h_
-#include "lldb/Expression/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
-
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
#include "llvm/ADT/DenseMap.h"
+// Project includes
+#include "ClangExpressionVariable.h"
+#include "ClangModulesDeclVendor.h"
+
+#include "lldb/Expression/ExpressionVariable.h"
+
namespace lldb_private
{
@@ -26,24 +32,30 @@ namespace lldb_private
/// ClangPersistentVariable for more discussion. Also provides an increasing,
/// 0-based counter for naming result variables.
//----------------------------------------------------------------------
-class ClangPersistentVariables : public ClangExpressionVariableList
+class ClangPersistentVariables : public PersistentExpressionState
{
public:
-
- //----------------------------------------------------------------------
- /// Constructor
- //----------------------------------------------------------------------
- ClangPersistentVariables ();
+ ClangPersistentVariables();
- lldb::ClangExpressionVariableSP
- CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp);
+ ~ClangPersistentVariables() override = default;
- lldb::ClangExpressionVariableSP
+ //------------------------------------------------------------------
+ // llvm casting support
+ //------------------------------------------------------------------
+ static bool classof(const PersistentExpressionState *pv)
+ {
+ return pv->getKind() == PersistentExpressionState::eKindClang;
+ }
+
+ lldb::ExpressionVariableSP
+ CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) override;
+
+ lldb::ExpressionVariableSP
CreatePersistentVariable (ExecutionContextScope *exe_scope,
const ConstString &name,
- const TypeFromUser& user_type,
+ const CompilerType& compiler_type,
lldb::ByteOrder byte_order,
- uint32_t addr_byte_size);
+ uint32_t addr_byte_size) override;
//----------------------------------------------------------------------
/// Return the next entry in the sequence of strings "$0", "$1", ... for
@@ -53,10 +65,13 @@ public:
/// A string that contains the next persistent variable name.
//----------------------------------------------------------------------
ConstString
- GetNextPersistentVariableName ();
+ GetNextPersistentVariableName () override;
void
- RemovePersistentVariable (lldb::ClangExpressionVariableSP variable);
+ RemovePersistentVariable (lldb::ExpressionVariableSP variable) override;
+
+ lldb::addr_t
+ LookupSymbol (const ConstString &name) override { return LLDB_INVALID_ADDRESS; }
void
RegisterPersistentType (const ConstString &name,
@@ -86,6 +101,6 @@ private:
///< priority source for macros.
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_ClangPersistentVariables_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
new file mode 100644
index 0000000..11f7f84
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -0,0 +1,673 @@
+//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <cstdlib>
+#include <string>
+#include <map>
+
+#include "ClangUserExpression.h"
+
+#include "ASTResultSynthesizer.h"
+#include "ClangExpressionDeclMap.h"
+#include "ClangExpressionParser.h"
+#include "ClangModulesDeclVendor.h"
+#include "ClangPersistentVariables.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+
+using namespace lldb_private;
+
+ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type,
+ const EvaluateExpressionOptions &options) :
+ LLVMUserExpression (exe_scope, expr, expr_prefix, language, desired_type, options),
+ m_type_system_helper(*m_target_wp.lock().get())
+{
+ switch (m_language)
+ {
+ case lldb::eLanguageTypeC_plus_plus:
+ m_allow_cxx = true;
+ break;
+ case lldb::eLanguageTypeObjC:
+ m_allow_objc = true;
+ break;
+ case lldb::eLanguageTypeObjC_plus_plus:
+ default:
+ m_allow_cxx = true;
+ m_allow_objc = true;
+ break;
+ }
+}
+
+ClangUserExpression::~ClangUserExpression ()
+{
+}
+
+void
+ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("ClangUserExpression::ScanContext()");
+
+ m_target = exe_ctx.GetTargetPtr();
+
+ if (!(m_allow_cxx || m_allow_objc))
+ {
+ if (log)
+ log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C");
+ return;
+ }
+
+ StackFrame *frame = exe_ctx.GetFramePtr();
+ if (frame == NULL)
+ {
+ if (log)
+ log->Printf(" [CUE::SC] Null stack frame");
+ return;
+ }
+
+ SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
+
+ if (!sym_ctx.function)
+ {
+ if (log)
+ log->Printf(" [CUE::SC] Null function");
+ return;
+ }
+
+ // Find the block that defines the function represented by "sym_ctx"
+ Block *function_block = sym_ctx.GetFunctionBlock();
+
+ if (!function_block)
+ {
+ if (log)
+ log->Printf(" [CUE::SC] Null function block");
+ return;
+ }
+
+ CompilerDeclContext decl_context = function_block->GetDeclContext();
+
+ if (!decl_context)
+ {
+ if (log)
+ log->Printf(" [CUE::SC] Null decl context");
+ return;
+ }
+
+ if (clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(decl_context))
+ {
+ if (m_allow_cxx && method_decl->isInstance())
+ {
+ if (m_enforce_valid_object)
+ {
+ lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
+
+ const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context";
+
+ if (!variable_list_sp)
+ {
+ err.SetErrorString(thisErrorString);
+ return;
+ }
+
+ lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
+
+ if (!this_var_sp ||
+ !this_var_sp->IsInScope(frame) ||
+ !this_var_sp->LocationIsValidForFrame (frame))
+ {
+ err.SetErrorString(thisErrorString);
+ return;
+ }
+ }
+
+ m_in_cplusplus_method = true;
+ m_needs_object_ptr = true;
+ }
+ }
+ else if (clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(decl_context))
+ {
+ if (m_allow_objc)
+ {
+ if (m_enforce_valid_object)
+ {
+ lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
+
+ const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context";
+
+ if (!variable_list_sp)
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
+
+ if (!self_variable_sp ||
+ !self_variable_sp->IsInScope(frame) ||
+ !self_variable_sp->LocationIsValidForFrame (frame))
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+ }
+
+ m_in_objectivec_method = true;
+ m_needs_object_ptr = true;
+
+ if (!method_decl->isInstanceMethod())
+ m_in_static_method = true;
+ }
+ }
+ else if (clang::FunctionDecl *function_decl = ClangASTContext::DeclContextGetAsFunctionDecl(decl_context))
+ {
+ // We might also have a function that said in the debug information that it captured an
+ // object pointer. The best way to deal with getting to the ivars at present is by pretending
+ // that this is a method of a class in whatever runtime the debug info says the object pointer
+ // belongs to. Do that here.
+
+ ClangASTMetadata *metadata = ClangASTContext::DeclContextGetMetaData (decl_context, function_decl);
+ if (metadata && metadata->HasObjectPtr())
+ {
+ lldb::LanguageType language = metadata->GetObjectPtrLanguage();
+ if (language == lldb::eLanguageTypeC_plus_plus)
+ {
+ if (m_enforce_valid_object)
+ {
+ lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
+
+ const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context";
+
+ if (!variable_list_sp)
+ {
+ err.SetErrorString(thisErrorString);
+ return;
+ }
+
+ lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
+
+ if (!this_var_sp ||
+ !this_var_sp->IsInScope(frame) ||
+ !this_var_sp->LocationIsValidForFrame (frame))
+ {
+ err.SetErrorString(thisErrorString);
+ return;
+ }
+ }
+
+ m_in_cplusplus_method = true;
+ m_needs_object_ptr = true;
+ }
+ else if (language == lldb::eLanguageTypeObjC)
+ {
+ if (m_enforce_valid_object)
+ {
+ lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
+
+ const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context";
+
+ if (!variable_list_sp)
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
+
+ if (!self_variable_sp ||
+ !self_variable_sp->IsInScope(frame) ||
+ !self_variable_sp->LocationIsValidForFrame (frame))
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ Type *self_type = self_variable_sp->GetType();
+
+ if (!self_type)
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ CompilerType self_clang_type = self_type->GetForwardCompilerType ();
+
+ if (!self_clang_type)
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ if (ClangASTContext::IsObjCClassType(self_clang_type))
+ {
+ return;
+ }
+ else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type))
+ {
+ m_in_objectivec_method = true;
+ m_needs_object_ptr = true;
+ }
+ else
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+ }
+ else
+ {
+ m_in_objectivec_method = true;
+ m_needs_object_ptr = true;
+ }
+ }
+ }
+ }
+}
+
+// This is a really nasty hack, meant to fix Objective-C expressions of the form
+// (int)[myArray count]. Right now, because the type information for count is
+// not available, [myArray count] returns id, which can't be directly cast to
+// int without causing a clang error.
+static void
+ApplyObjcCastHack(std::string &expr)
+{
+#define OBJC_CAST_HACK_FROM "(int)["
+#define OBJC_CAST_HACK_TO "(int)(long long)["
+
+ size_t from_offset;
+
+ while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
+ expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
+
+#undef OBJC_CAST_HACK_TO
+#undef OBJC_CAST_HACK_FROM
+}
+
+bool
+ClangUserExpression::Parse (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy,
+ bool keep_result_in_memory,
+ bool generate_debug_info)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ Error err;
+
+ InstallContext(exe_ctx);
+
+ if (Target *target = exe_ctx.GetTargetPtr())
+ {
+ if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))
+ {
+ m_result_delegate.RegisterPersistentState(persistent_state);
+ }
+ else
+ {
+ error_stream.PutCString ("error: couldn't start parsing (no persistent data)");
+ return false;
+ }
+ }
+ else
+ {
+ error_stream.PutCString ("error: couldn't start parsing (no target)");
+ return false;
+ }
+
+ ScanContext(exe_ctx, err);
+
+ if (!err.Success())
+ {
+ error_stream.Printf("warning: %s\n", err.AsCString());
+ }
+
+ StreamString m_transformed_stream;
+
+ ////////////////////////////////////
+ // Generate the expression
+ //
+
+ ApplyObjcCastHack(m_expr_text);
+ //ApplyUnicharHack(m_expr_text);
+
+ std::string prefix = m_expr_prefix;
+
+ if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor())
+ {
+ const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast<ClangPersistentVariables>(m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->GetHandLoadedClangModules();
+ ClangModulesDeclVendor::ModuleVector modules_for_macros;
+
+ for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
+ {
+ modules_for_macros.push_back(module);
+ }
+
+ if (m_target->GetEnableAutoImportClangModules())
+ {
+ if (StackFrame *frame = exe_ctx.GetFramePtr())
+ {
+ if (Block *block = frame->GetFrameBlock())
+ {
+ SymbolContext sc;
+
+ block->CalculateSymbolContext(&sc);
+
+ if (sc.comp_unit)
+ {
+ StreamString error_stream;
+
+ decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream);
+ }
+ }
+ }
+ }
+ }
+
+ std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str()));
+
+ lldb::LanguageType lang_type;
+
+ if (m_in_cplusplus_method)
+ lang_type = lldb::eLanguageTypeC_plus_plus;
+ else if (m_in_objectivec_method)
+ lang_type = lldb::eLanguageTypeObjC;
+ else
+ lang_type = lldb::eLanguageTypeC;
+
+ if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx))
+ {
+ error_stream.PutCString ("error: couldn't construct expression body");
+ return false;
+ }
+
+ if (log)
+ log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
+
+ ////////////////////////////////////
+ // Set up the target and compiler
+ //
+
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (!target)
+ {
+ error_stream.PutCString ("error: invalid target\n");
+ return false;
+ }
+
+ //////////////////////////
+ // Parse the expression
+ //
+
+ m_materializer_ap.reset(new Materializer());
+
+ ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
+
+ class OnExit
+ {
+ public:
+ typedef std::function <void (void)> Callback;
+
+ OnExit (Callback const &callback) :
+ m_callback(callback)
+ {
+ }
+
+ ~OnExit ()
+ {
+ m_callback();
+ }
+ private:
+ Callback m_callback;
+ };
+
+ OnExit on_exit([this]() { ResetDeclMap(); });
+
+ if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get()))
+ {
+ error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
+
+ ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
+
+ return false;
+ }
+
+ Process *process = exe_ctx.GetProcessPtr();
+ ExecutionContextScope *exe_scope = process;
+
+ if (!exe_scope)
+ exe_scope = exe_ctx.GetTargetPtr();
+
+ ClangExpressionParser parser(exe_scope, *this, generate_debug_info);
+
+ unsigned num_errors = parser.Parse (error_stream);
+
+ if (num_errors)
+ {
+ error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
+
+ ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
+
+ return false;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ // Prepare the output of the parser for execution, evaluating it statically if possible
+ //
+
+ Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
+ m_jit_end_addr,
+ m_execution_unit_sp,
+ exe_ctx,
+ m_can_interpret,
+ execution_policy);
+
+ if (generate_debug_info)
+ {
+ lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
+
+ if (jit_module_sp)
+ {
+ ConstString const_func_name(FunctionName());
+ FileSpec jit_file;
+ jit_file.GetFilename() = const_func_name;
+ jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
+ m_jit_module_wp = jit_module_sp;
+ target->GetImages().Append(jit_module_sp);
+ }
+// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
+// StreamFile strm (stdout, false);
+// if (jit_obj_file)
+// {
+// jit_obj_file->GetSectionList();
+// jit_obj_file->GetSymtab();
+// jit_obj_file->Dump(&strm);
+// }
+// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
+// if (jit_sym_vendor)
+// {
+// lldb_private::SymbolContextList sc_list;
+// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
+// sc_list.Dump(&strm, target);
+// jit_sym_vendor->Dump(&strm);
+// }
+ }
+
+ ResetDeclMap(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions.
+
+ if (jit_error.Success())
+ {
+ if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
+ m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
+ return true;
+ }
+ else
+ {
+ const char *error_cstr = jit_error.AsCString();
+ if (error_cstr && error_cstr[0])
+ error_stream.Printf ("error: %s\n", error_cstr);
+ else
+ error_stream.Printf ("error: expression can't be interpreted or run\n");
+ return false;
+ }
+}
+
+bool
+ClangUserExpression::AddArguments (ExecutionContext &exe_ctx,
+ std::vector<lldb::addr_t> &args,
+ lldb::addr_t struct_address,
+ Stream &error_stream)
+{
+ lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;
+
+ if (m_needs_object_ptr)
+ {
+ lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
+ if (!frame_sp)
+ return true;
+
+ ConstString object_name;
+
+ if (m_in_cplusplus_method)
+ {
+ object_name.SetCString("this");
+ }
+ else if (m_in_objectivec_method)
+ {
+ object_name.SetCString("self");
+ }
+ else
+ {
+ error_stream.Printf("Need object pointer but don't know the language\n");
+ return false;
+ }
+
+ Error object_ptr_error;
+
+ object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);
+
+ if (!object_ptr_error.Success())
+ {
+ error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
+ object_ptr = 0;
+ }
+
+ if (m_in_objectivec_method)
+ {
+ ConstString cmd_name("_cmd");
+
+ cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error);
+
+ if (!object_ptr_error.Success())
+ {
+ error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
+ cmd_ptr = 0;
+ }
+ }
+ if (object_ptr)
+ args.push_back(object_ptr);
+
+ if (m_in_objectivec_method)
+ args.push_back(cmd_ptr);
+
+ args.push_back(struct_address);
+ }
+ else
+ {
+ args.push_back(struct_address);
+ }
+ return true;
+}
+
+lldb::ExpressionVariableSP
+ClangUserExpression::GetResultAfterDematerialization(ExecutionContextScope *exe_scope)
+{
+ return m_result_delegate.GetVariable();
+}
+
+void
+ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &delegate, bool keep_result_in_memory)
+{
+ m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx));
+}
+
+clang::ASTConsumer *
+ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough)
+{
+ m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough,
+ m_target));
+
+ return m_result_synthesizer_up.get();
+}
+
+ClangUserExpression::ResultDelegate::ResultDelegate()
+{
+}
+
+ConstString
+ClangUserExpression::ResultDelegate::GetName()
+{
+ return m_persistent_state->GetNextPersistentVariableName();
+}
+
+void
+ClangUserExpression::ResultDelegate::DidDematerialize(lldb::ExpressionVariableSP &variable)
+{
+ m_variable = variable;
+}
+
+void
+ClangUserExpression::ResultDelegate::RegisterPersistentState(PersistentExpressionState *persistent_state)
+{
+ m_persistent_state = persistent_state;
+}
+
+lldb::ExpressionVariableSP &
+ClangUserExpression::ResultDelegate::GetVariable()
+{
+ return m_variable;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
new file mode 100644
index 0000000..f2bfe31
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
@@ -0,0 +1,218 @@
+//===-- ClangUserExpression.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangUserExpression_h_
+#define liblldb_ClangUserExpression_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "ASTStructExtractor.h"
+#include "ASTResultSynthesizer.h"
+#include "ClangExpressionDeclMap.h"
+#include "ClangExpressionHelper.h"
+#include "ClangExpressionVariable.h"
+#include "IRForTarget.h"
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/LLVMUserExpression.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Target/ExecutionContext.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class ClangUserExpression ClangUserExpression.h "lldb/Expression/ClangUserExpression.h"
+/// @brief Encapsulates a single expression for use with Clang
+///
+/// LLDB uses expressions for various purposes, notably to call functions
+/// and as a backend for the expr command. ClangUserExpression encapsulates
+/// the objects needed to parse and interpret or JIT an expression. It
+/// uses the Clang parser to produce LLVM IR from the expression.
+//----------------------------------------------------------------------
+class ClangUserExpression : public LLVMUserExpression
+{
+public:
+ enum { kDefaultTimeout = 500000u };
+
+ class ClangUserExpressionHelper : public ClangExpressionHelper
+ {
+ public:
+ ClangUserExpressionHelper (Target &target) :
+ m_target(target)
+ {
+ }
+
+ ~ClangUserExpressionHelper() override = default;
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ ClangExpressionDeclMap *
+ DeclMap() override
+ {
+ return m_expr_decl_map_up.get();
+ }
+
+ void
+ ResetDeclMap()
+ {
+ m_expr_decl_map_up.reset();
+ }
+
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory);
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ clang::ASTConsumer *
+ ASTTransformer(clang::ASTConsumer *passthrough) override;
+
+ private:
+ Target &m_target;
+ std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up;
+ std::unique_ptr<ASTStructExtractor> m_struct_extractor_up; ///< The class that generates the argument struct layout.
+ std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer_up;
+ };
+
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] expr
+ /// The expression to parse.
+ ///
+ /// @param[in] expr_prefix
+ /// If non-NULL, a C string containing translation-unit level
+ /// definitions to be included when the expression is parsed.
+ ///
+ /// @param[in] language
+ /// If not eLanguageTypeUnknown, a language to use when parsing
+ /// the expression. Currently restricted to those languages
+ /// supported by Clang.
+ ///
+ /// @param[in] desired_type
+ /// If not eResultTypeAny, the type to use for the expression
+ /// result.
+ //------------------------------------------------------------------
+ ClangUserExpression (ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type,
+ const EvaluateExpressionOptions &options);
+
+ ~ClangUserExpression() override;
+
+ //------------------------------------------------------------------
+ /// Parse the expression
+ ///
+ /// @param[in] error_stream
+ /// A stream to print parse errors and warnings to.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to use when looking up entities that
+ /// are needed for parsing (locations of functions, types of
+ /// variables, persistent variables, etc.)
+ ///
+ /// @param[in] execution_policy
+ /// Determines whether interpretation is possible or mandatory.
+ ///
+ /// @param[in] keep_result_in_memory
+ /// True if the resulting persistent variable should reside in
+ /// target memory, if applicable.
+ ///
+ /// @return
+ /// True on success (no errors); false otherwise.
+ //------------------------------------------------------------------
+ bool
+ Parse (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy,
+ bool keep_result_in_memory,
+ bool generate_debug_info) override;
+
+ ExpressionTypeSystemHelper *
+ GetTypeSystemHelper () override
+ {
+ return &m_type_system_helper;
+ }
+
+ ClangExpressionDeclMap *
+ DeclMap ()
+ {
+ return m_type_system_helper.DeclMap();
+ }
+
+ void
+ ResetDeclMap ()
+ {
+ m_type_system_helper.ResetDeclMap();
+ }
+
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory)
+ {
+ m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, keep_result_in_memory);
+ }
+
+ lldb::ExpressionVariableSP
+ GetResultAfterDematerialization(ExecutionContextScope *exe_scope) override;
+
+private:
+ //------------------------------------------------------------------
+ /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment.
+ //------------------------------------------------------------------
+
+ void
+ ScanContext (ExecutionContext &exe_ctx,
+ lldb_private::Error &err) override;
+
+ bool
+ AddArguments (ExecutionContext &exe_ctx,
+ std::vector<lldb::addr_t> &args,
+ lldb::addr_t struct_address,
+ Stream &error_stream) override;
+
+ ClangUserExpressionHelper m_type_system_helper;
+
+ class ResultDelegate : public Materializer::PersistentVariableDelegate
+ {
+ public:
+ ResultDelegate();
+ ConstString GetName() override;
+ void DidDematerialize(lldb::ExpressionVariableSP &variable) override;
+
+ void RegisterPersistentState(PersistentExpressionState *persistent_state);
+ lldb::ExpressionVariableSP &GetVariable();
+
+ private:
+ PersistentExpressionState *m_persistent_state;
+ lldb::ExpressionVariableSP m_variable;
+ };
+
+ ResultDelegate m_result_delegate;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangUserExpression_h_
diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangUtilityFunction.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
index de5b0c1..fe044c1 100644
--- a/contrib/llvm/tools/lldb/source/Expression/ClangUtilityFunction.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+#include "ClangExpressionDeclMap.h"
+#include "ClangExpressionParser.h"
+#include "ClangUtilityFunction.h"
+
// C Includes
#include <stdio.h>
#if HAVE_SYS_TYPES_H
@@ -20,9 +24,6 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "lldb/Expression/ClangExpressionParser.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
#include "lldb/Expression/ExpressionSourceCode.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Host/Host.h"
@@ -40,29 +41,15 @@ using namespace lldb_private;
/// @param[in] name
/// The name of the function, as used in the text.
//------------------------------------------------------------------
-ClangUtilityFunction::ClangUtilityFunction (const char *text,
+ClangUtilityFunction::ClangUtilityFunction (ExecutionContextScope &exe_scope,
+ const char *text,
const char *name) :
- ClangExpression (),
- m_expr_decl_map (),
- m_execution_unit_sp (),
- m_jit_module_wp (),
- m_function_text (ExpressionSourceCode::g_expression_prefix),
- m_function_name (name)
+ UtilityFunction (exe_scope, text, name)
{
- if (text && text[0])
- m_function_text.append (text);
}
ClangUtilityFunction::~ClangUtilityFunction ()
{
- lldb::ProcessSP process_sp (m_jit_process_wp.lock());
- if (process_sp)
- {
- lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
- if (jit_module_sp)
- process_sp->GetTarget().GetImages().Remove(jit_module_sp);
- }
-
}
//------------------------------------------------------------------
@@ -113,9 +100,9 @@ ClangUtilityFunction::Install (Stream &error_stream,
bool keep_result_in_memory = false;
- m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
+ ResetDeclMap(exe_ctx, keep_result_in_memory);
- if (!m_expr_decl_map->WillParse(exe_ctx, NULL))
+ if (!DeclMap()->WillParse(exe_ctx, NULL))
{
error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
return false;
@@ -130,7 +117,7 @@ ClangUtilityFunction::Install (Stream &error_stream,
{
error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
- m_expr_decl_map.reset();
+ ResetDeclMap();
return false;
}
@@ -176,9 +163,9 @@ ClangUtilityFunction::Install (Stream &error_stream,
m_function_text.c_str());
#endif
- m_expr_decl_map->DidParse();
+ DeclMap()->DidParse();
- m_expr_decl_map.reset();
+ ResetDeclMap();
if (jit_error.Success())
{
@@ -195,4 +182,8 @@ ClangUtilityFunction::Install (Stream &error_stream,
}
}
-
+void
+ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory)
+{
+ m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx));
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
new file mode 100644
index 0000000..7483971
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
@@ -0,0 +1,137 @@
+//===-- ClangUtilityFunction.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangUtilityFunction_h_
+#define liblldb_ClangUtilityFunction_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "ClangExpressionHelper.h"
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/UtilityFunction.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class ClangUtilityFunction ClangUtilityFunction.h "lldb/Expression/ClangUtilityFunction.h"
+/// @brief Encapsulates a single expression for use with Clang
+///
+/// LLDB uses expressions for various purposes, notably to call functions
+/// and as a backend for the expr command. ClangUtilityFunction encapsulates
+/// a self-contained function meant to be used from other code. Utility
+/// functions can perform error-checking for ClangUserExpressions, or can
+/// simply provide a way to push a function into the target for the debugger to
+/// call later on.
+//----------------------------------------------------------------------
+class ClangUtilityFunction : public UtilityFunction
+{
+public:
+ class ClangUtilityFunctionHelper : public ClangExpressionHelper
+ {
+ public:
+ ClangUtilityFunctionHelper ()
+ {
+ }
+
+ ~ClangUtilityFunctionHelper() override {}
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ ClangExpressionDeclMap *
+ DeclMap() override
+ {
+ return m_expr_decl_map_up.get();
+ }
+
+ void
+ ResetDeclMap()
+ {
+ m_expr_decl_map_up.reset();
+ }
+
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory);
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ clang::ASTConsumer *
+ ASTTransformer(clang::ASTConsumer *passthrough) override
+ {
+ return nullptr;
+ }
+ private:
+ std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up;
+ };
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] text
+ /// The text of the function. Must be a full translation unit.
+ ///
+ /// @param[in] name
+ /// The name of the function, as used in the text.
+ //------------------------------------------------------------------
+ ClangUtilityFunction (ExecutionContextScope &exe_scope,
+ const char *text,
+ const char *name);
+
+ ~ClangUtilityFunction() override;
+
+ ExpressionTypeSystemHelper *
+ GetTypeSystemHelper () override
+ {
+ return &m_type_system_helper;
+ }
+
+ ClangExpressionDeclMap *
+ DeclMap()
+ {
+ return m_type_system_helper.DeclMap();
+ }
+
+ void
+ ResetDeclMap ()
+ {
+ m_type_system_helper.ResetDeclMap();
+ }
+
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory)
+ {
+ m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory);
+ }
+
+ bool
+ Install (Stream &error_stream, ExecutionContext &exe_ctx) override;
+
+private:
+ ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression.
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangUtilityFunction_h_
diff --git a/contrib/llvm/tools/lldb/source/Expression/IRForTarget.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
index cf2a93b..509c594 100644
--- a/contrib/llvm/tools/lldb/source/Expression/IRForTarget.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
@@ -7,7 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Expression/IRForTarget.h"
+#include "IRForTarget.h"
+
+#include "ClangExpressionDeclMap.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Constants.h"
@@ -29,13 +31,11 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangASTType.h"
-#include "lldb/Target/CPPLanguageRuntime.h"
+#include "lldb/Symbol/CompilerType.h"
#include <map>
@@ -229,36 +229,6 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
{
std::vector<lldb_private::ConstString> alternates;
bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr);
- if (!found_it)
- {
- if (log)
- log->Printf("Address of function \"%s\" not found.\n", name.GetCString());
- // Check for an alternate mangling for names from the standard library.
- // For example, "std::basic_string<...>" has an alternate mangling scheme per
- // the Itanium C++ ABI.
- lldb::ProcessSP process_sp = m_data_allocator.GetTarget()->GetProcessSP();
- if (process_sp)
- {
- lldb_private::CPPLanguageRuntime *cpp_runtime = process_sp->GetCPPLanguageRuntime();
- if (cpp_runtime && cpp_runtime->GetAlternateManglings(name, alternates))
- {
- for (size_t i = 0; i < alternates.size(); ++i)
- {
- const lldb_private::ConstString &alternate_name = alternates[i];
- if (log)
- log->Printf("Looking up address of function \"%s\" with alternate name \"%s\"",
- name.GetCString(), alternate_name.GetCString());
- if ((found_it = m_decl_map->GetFunctionAddress (alternate_name, fun_addr)))
- {
- if (log)
- log->Printf("Found address of function \"%s\" with alternate name \"%s\"",
- name.GetCString(), alternate_name.GetCString());
- break;
- }
- }
- }
- }
- }
if (!found_it)
{
@@ -337,7 +307,7 @@ IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module)
fi != llvm_module.end();
++fi)
{
- Function *fun = fi;
+ Function *fun = &*fi;
bool is_decl = fun->isDeclaration();
@@ -575,14 +545,14 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
- &result_decl->getASTContext());
+ lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext()));
}
else if (pointer_objcobjpointertype)
{
clang::QualType element_qual_type = clang::QualType(pointer_objcobjpointertype->getObjectType(), 0);
m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
- &result_decl->getASTContext());
+ lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext()));
}
else
{
@@ -598,7 +568,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
else
{
m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
- &result_decl->getASTContext());
+ lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext()));
}
@@ -1241,7 +1211,7 @@ IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc)
clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr);
lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(),
- &decl->getASTContext());
+ lldb_private::ClangASTContext::GetASTContext(&decl->getASTContext()));
StringRef decl_name (decl->getName());
lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size());
@@ -1509,7 +1479,7 @@ IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr)
if (value_decl == NULL)
return false;
- lldb_private::ClangASTType clang_type(&value_decl->getASTContext(), value_decl->getType());
+ lldb_private::CompilerType compiler_type(&value_decl->getASTContext(), value_decl->getType());
const Type *value_type = NULL;
@@ -1524,7 +1494,7 @@ IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr)
// to the type of $__lldb_expr_result, not the type itself.
//
// We also do this for any user-declared persistent variables.
- clang_type = clang_type.GetPointerType();
+ compiler_type = compiler_type.GetPointerType();
value_type = PointerType::get(global_variable->getType(), 0);
}
else
@@ -1532,14 +1502,14 @@ IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr)
value_type = global_variable->getType();
}
- const uint64_t value_size = clang_type.GetByteSize(nullptr);
- lldb::offset_t value_alignment = (clang_type.GetTypeBitAlign() + 7ull) / 8ull;
+ const uint64_t value_size = compiler_type.GetByteSize(nullptr);
+ lldb::offset_t value_alignment = (compiler_type.GetTypeBitAlign() + 7ull) / 8ull;
if (log)
{
log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRIu64 "]",
name.c_str(),
- clang_type.GetQualType().getAsString().c_str(),
+ lldb_private::ClangASTContext::GetQualType(compiler_type).getAsString().c_str(),
PrintType(value_type).c_str(),
value_size,
value_alignment);
@@ -1954,7 +1924,7 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
if (operand_constant_fp/* && operand_constant_fp->getType()->isX86_FP80Ty()*/)
{
static_constants.push_back(operand_val);
- static_users.push_back(ii);
+ static_users.push_back(&*ii);
}
}
}
@@ -1999,7 +1969,7 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
lldb_private::DataBufferHeap data(operand_data_size, 0);
- if (lldb::endian::InlHostByteOrder() != m_data_allocator.GetStream().GetByteOrder())
+ if (lldb_private::endian::InlHostByteOrder() != m_data_allocator.GetStream().GetByteOrder())
{
uint8_t *data_bytes = data.GetBytes();
@@ -2279,7 +2249,7 @@ IRForTarget::ReplaceVariables (Function &llvm_function)
return false;
}
- Argument *argument = iter;
+ Argument *argument = &*iter;
if (argument->getName().equals("this"))
{
@@ -2293,7 +2263,7 @@ IRForTarget::ReplaceVariables (Function &llvm_function)
return false;
}
- argument = iter;
+ argument = &*iter;
}
else if (argument->getName().equals("self"))
{
@@ -2325,7 +2295,7 @@ IRForTarget::ReplaceVariables (Function &llvm_function)
return false;
}
- argument = iter;
+ argument = &*iter;
}
if (!argument->getName().equals("$__lldb_arg"))
@@ -2623,7 +2593,7 @@ IRForTarget::runOnModule (Module &llvm_module)
fi != fe;
++fi)
{
- llvm::Function *function = fi;
+ llvm::Function *function = &*fi;
if (function->begin() == function->end())
continue;
@@ -2698,7 +2668,7 @@ IRForTarget::runOnModule (Module &llvm_module)
fi != fe;
++fi)
{
- llvm::Function *function = fi;
+ llvm::Function *function = &*fi;
for (llvm::Function::iterator bbi = function->begin(), bbe = function->end();
bbi != bbe;
@@ -2720,7 +2690,7 @@ IRForTarget::runOnModule (Module &llvm_module)
fi != fe;
++fi)
{
- llvm::Function *function = fi;
+ llvm::Function *function = &*fi;
for (llvm::Function::iterator bbi = function->begin(), bbe = function->end();
bbi != bbe;
diff --git a/contrib/llvm/tools/lldb/include/lldb/Expression/IRForTarget.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
index b81fab7..fb4abcc 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Expression/IRForTarget.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
@@ -107,7 +107,7 @@ public:
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- virtual ~IRForTarget();
+ ~IRForTarget() override;
//------------------------------------------------------------------
/// Run this IR transformer on a single module
@@ -126,8 +126,8 @@ public:
/// @return
/// True on success; false otherwise
//------------------------------------------------------------------
- virtual bool
- runOnModule (llvm::Module &llvm_module);
+ bool
+ runOnModule(llvm::Module &llvm_module) override;
//------------------------------------------------------------------
/// Interface stub
@@ -135,9 +135,9 @@ public:
/// Implementation of the llvm::ModulePass::assignPassManager()
/// function.
//------------------------------------------------------------------
- virtual void
- assignPassManager (llvm::PMStack &pass_mgr_stack,
- llvm::PassManagerType pass_mgr_type = llvm::PMT_ModulePassManager);
+ void
+ assignPassManager(llvm::PMStack &pass_mgr_stack,
+ llvm::PassManagerType pass_mgr_type = llvm::PMT_ModulePassManager) override;
//------------------------------------------------------------------
/// Returns PMT_ModulePassManager
@@ -145,8 +145,8 @@ public:
/// Implementation of the llvm::ModulePass::getPotentialPassManagerType()
/// function.
//------------------------------------------------------------------
- virtual llvm::PassManagerType
- getPotentialPassManagerType() const;
+ llvm::PassManagerType
+ getPotentialPassManagerType() const override;
private:
//------------------------------------------------------------------
@@ -742,4 +742,4 @@ private:
};
-#endif
+#endif // liblldb_IRForTarget_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoAST.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoAST.h
new file mode 100644
index 0000000..6d51240
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoAST.h
@@ -0,0 +1,3225 @@
+//===-- GoAST.h -------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// DO NOT EDIT.
+// Generated by gen_go_ast.py
+
+#ifndef liblldb_GoAST_h
+#define liblldb_GoAST_h
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "llvm/Support/Casting.h"
+#include "Plugins/ExpressionParser/Go/GoLexer.h"
+
+namespace lldb_private
+{
+
+class GoASTNode
+{
+ public:
+ typedef GoLexer::TokenType TokenType;
+ typedef GoLexer::Token Token;
+ enum ChanDir
+ {
+ eChanBidir,
+ eChanSend,
+ eChanRecv,
+ };
+ enum NodeKind
+ {
+ eBadDecl,
+ eFuncDecl,
+ eGenDecl,
+ eArrayType,
+ eBadExpr,
+ eBasicLit,
+ eBinaryExpr,
+ eIdent,
+ eCallExpr,
+ eChanType,
+ eCompositeLit,
+ eEllipsis,
+ eFuncType,
+ eFuncLit,
+ eIndexExpr,
+ eInterfaceType,
+ eKeyValueExpr,
+ eMapType,
+ eParenExpr,
+ eSelectorExpr,
+ eSliceExpr,
+ eStarExpr,
+ eStructType,
+ eTypeAssertExpr,
+ eUnaryExpr,
+ eImportSpec,
+ eTypeSpec,
+ eValueSpec,
+ eAssignStmt,
+ eBadStmt,
+ eBlockStmt,
+ eBranchStmt,
+ eCaseClause,
+ eCommClause,
+ eDeclStmt,
+ eDeferStmt,
+ eEmptyStmt,
+ eExprStmt,
+ eForStmt,
+ eGoStmt,
+ eIfStmt,
+ eIncDecStmt,
+ eLabeledStmt,
+ eRangeStmt,
+ eReturnStmt,
+ eSelectStmt,
+ eSendStmt,
+ eSwitchStmt,
+ eTypeSwitchStmt,
+ eField,
+ eFieldList,
+ };
+
+ virtual ~GoASTNode() = default;
+
+ NodeKind
+ GetKind() const
+ {
+ return m_kind;
+ }
+
+ virtual const char *GetKindName() const = 0;
+
+ template <typename V> void WalkChildren(V &v);
+
+ protected:
+ explicit GoASTNode(NodeKind kind) : m_kind(kind) { }
+
+ private:
+ const NodeKind m_kind;
+
+ GoASTNode(const GoASTNode &) = delete;
+ const GoASTNode &operator=(const GoASTNode &) = delete;
+};
+
+
+class GoASTDecl : public GoASTNode
+{
+ public:
+ template <typename R, typename V> R Visit(V *v) const;
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() >= eBadDecl && n->GetKind() <= eGenDecl;
+ }
+
+ protected:
+ explicit GoASTDecl(NodeKind kind) : GoASTNode(kind) { }
+ private:
+
+ GoASTDecl(const GoASTDecl &) = delete;
+ const GoASTDecl &operator=(const GoASTDecl &) = delete;
+};
+
+class GoASTExpr : public GoASTNode
+{
+ public:
+ template <typename R, typename V> R Visit(V *v) const;
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() >= eArrayType && n->GetKind() <= eUnaryExpr;
+ }
+
+ protected:
+ explicit GoASTExpr(NodeKind kind) : GoASTNode(kind) { }
+ private:
+
+ GoASTExpr(const GoASTExpr &) = delete;
+ const GoASTExpr &operator=(const GoASTExpr &) = delete;
+};
+
+class GoASTSpec : public GoASTNode
+{
+ public:
+ template <typename R, typename V> R Visit(V *v) const;
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() >= eImportSpec && n->GetKind() <= eValueSpec;
+ }
+
+ protected:
+ explicit GoASTSpec(NodeKind kind) : GoASTNode(kind) { }
+ private:
+
+ GoASTSpec(const GoASTSpec &) = delete;
+ const GoASTSpec &operator=(const GoASTSpec &) = delete;
+};
+
+class GoASTStmt : public GoASTNode
+{
+ public:
+ template <typename R, typename V> R Visit(V *v) const;
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() >= eAssignStmt && n->GetKind() <= eTypeSwitchStmt;
+ }
+
+ protected:
+ explicit GoASTStmt(NodeKind kind) : GoASTNode(kind) { }
+ private:
+
+ GoASTStmt(const GoASTStmt &) = delete;
+ const GoASTStmt &operator=(const GoASTStmt &) = delete;
+};
+
+
+class GoASTArrayType : public GoASTExpr
+{
+ public:
+ GoASTArrayType(GoASTExpr *len, GoASTExpr *elt) : GoASTExpr(eArrayType), m_len_up(len), m_elt_up(elt) {}
+ ~GoASTArrayType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ArrayType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eArrayType;
+ }
+
+ const GoASTExpr *
+ GetLen() const
+ {
+ return m_len_up.get();
+ }
+ void
+ SetLen(GoASTExpr *len)
+ {
+ m_len_up.reset(len);
+ }
+
+ const GoASTExpr *
+ GetElt() const
+ {
+ return m_elt_up.get();
+ }
+ void
+ SetElt(GoASTExpr *elt)
+ {
+ m_elt_up.reset(elt);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_len_up;
+ std::unique_ptr<GoASTExpr> m_elt_up;
+
+ GoASTArrayType(const GoASTArrayType &) = delete;
+ const GoASTArrayType &operator=(const GoASTArrayType &) = delete;
+};
+
+class GoASTAssignStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTAssignStmt(bool define) : GoASTStmt(eAssignStmt), m_define(define) {}
+ ~GoASTAssignStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "AssignStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eAssignStmt;
+ }
+
+ size_t
+ NumLhs() const
+ {
+ return m_lhs.size();
+ }
+ const GoASTExpr *
+ GetLhs(int i) const
+ {
+ return m_lhs[i].get();
+ }
+ void
+ AddLhs(GoASTExpr *lhs)
+ {
+ m_lhs.push_back(std::unique_ptr<GoASTExpr>(lhs));
+ }
+
+ size_t
+ NumRhs() const
+ {
+ return m_rhs.size();
+ }
+ const GoASTExpr *
+ GetRhs(int i) const
+ {
+ return m_rhs[i].get();
+ }
+ void
+ AddRhs(GoASTExpr *rhs)
+ {
+ m_rhs.push_back(std::unique_ptr<GoASTExpr>(rhs));
+ }
+
+ bool
+ GetDefine() const
+ {
+ return m_define;
+ }
+ void
+ SetDefine(bool define)
+ {
+ m_define = define;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTExpr> > m_lhs;
+ std::vector<std::unique_ptr<GoASTExpr> > m_rhs;
+ bool m_define;
+
+ GoASTAssignStmt(const GoASTAssignStmt &) = delete;
+ const GoASTAssignStmt &operator=(const GoASTAssignStmt &) = delete;
+};
+
+class GoASTBadDecl : public GoASTDecl
+{
+ public:
+ GoASTBadDecl() : GoASTDecl(eBadDecl) {}
+ ~GoASTBadDecl() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BadDecl";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBadDecl;
+ }
+
+ GoASTBadDecl(const GoASTBadDecl &) = delete;
+ const GoASTBadDecl &operator=(const GoASTBadDecl &) = delete;
+};
+
+class GoASTBadExpr : public GoASTExpr
+{
+ public:
+ GoASTBadExpr() : GoASTExpr(eBadExpr) {}
+ ~GoASTBadExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BadExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBadExpr;
+ }
+
+ GoASTBadExpr(const GoASTBadExpr &) = delete;
+ const GoASTBadExpr &operator=(const GoASTBadExpr &) = delete;
+};
+
+class GoASTBadStmt : public GoASTStmt
+{
+ public:
+ GoASTBadStmt() : GoASTStmt(eBadStmt) {}
+ ~GoASTBadStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BadStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBadStmt;
+ }
+
+ GoASTBadStmt(const GoASTBadStmt &) = delete;
+ const GoASTBadStmt &operator=(const GoASTBadStmt &) = delete;
+};
+
+class GoASTBasicLit : public GoASTExpr
+{
+ public:
+ explicit GoASTBasicLit(Token value) : GoASTExpr(eBasicLit), m_value(value) {}
+ ~GoASTBasicLit() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BasicLit";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBasicLit;
+ }
+
+ Token
+ GetValue() const
+ {
+ return m_value;
+ }
+ void
+ SetValue(Token value)
+ {
+ m_value = value;
+ }
+
+ private:
+ friend class GoASTNode;
+ Token m_value;
+
+ GoASTBasicLit(const GoASTBasicLit &) = delete;
+ const GoASTBasicLit &operator=(const GoASTBasicLit &) = delete;
+};
+
+class GoASTBinaryExpr : public GoASTExpr
+{
+ public:
+ GoASTBinaryExpr(GoASTExpr *x, GoASTExpr *y, TokenType op) : GoASTExpr(eBinaryExpr), m_x_up(x), m_y_up(y), m_op(op) {}
+ ~GoASTBinaryExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BinaryExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBinaryExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTExpr *
+ GetY() const
+ {
+ return m_y_up.get();
+ }
+ void
+ SetY(GoASTExpr *y)
+ {
+ m_y_up.reset(y);
+ }
+
+ TokenType
+ GetOp() const
+ {
+ return m_op;
+ }
+ void
+ SetOp(TokenType op)
+ {
+ m_op = op;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTExpr> m_y_up;
+ TokenType m_op;
+
+ GoASTBinaryExpr(const GoASTBinaryExpr &) = delete;
+ const GoASTBinaryExpr &operator=(const GoASTBinaryExpr &) = delete;
+};
+
+class GoASTBlockStmt : public GoASTStmt
+{
+ public:
+ GoASTBlockStmt() : GoASTStmt(eBlockStmt) {}
+ ~GoASTBlockStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BlockStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBlockStmt;
+ }
+
+ size_t
+ NumList() const
+ {
+ return m_list.size();
+ }
+ const GoASTStmt *
+ GetList(int i) const
+ {
+ return m_list[i].get();
+ }
+ void
+ AddList(GoASTStmt *list)
+ {
+ m_list.push_back(std::unique_ptr<GoASTStmt>(list));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTStmt> > m_list;
+
+ GoASTBlockStmt(const GoASTBlockStmt &) = delete;
+ const GoASTBlockStmt &operator=(const GoASTBlockStmt &) = delete;
+};
+
+class GoASTIdent : public GoASTExpr
+{
+ public:
+ explicit GoASTIdent(Token name) : GoASTExpr(eIdent), m_name(name) {}
+ ~GoASTIdent() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "Ident";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eIdent;
+ }
+
+ Token
+ GetName() const
+ {
+ return m_name;
+ }
+ void
+ SetName(Token name)
+ {
+ m_name = name;
+ }
+
+ private:
+ friend class GoASTNode;
+ Token m_name;
+
+ GoASTIdent(const GoASTIdent &) = delete;
+ const GoASTIdent &operator=(const GoASTIdent &) = delete;
+};
+
+class GoASTBranchStmt : public GoASTStmt
+{
+ public:
+ GoASTBranchStmt(GoASTIdent *label, TokenType tok) : GoASTStmt(eBranchStmt), m_label_up(label), m_tok(tok) {}
+ ~GoASTBranchStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BranchStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBranchStmt;
+ }
+
+ const GoASTIdent *
+ GetLabel() const
+ {
+ return m_label_up.get();
+ }
+ void
+ SetLabel(GoASTIdent *label)
+ {
+ m_label_up.reset(label);
+ }
+
+ TokenType
+ GetTok() const
+ {
+ return m_tok;
+ }
+ void
+ SetTok(TokenType tok)
+ {
+ m_tok = tok;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTIdent> m_label_up;
+ TokenType m_tok;
+
+ GoASTBranchStmt(const GoASTBranchStmt &) = delete;
+ const GoASTBranchStmt &operator=(const GoASTBranchStmt &) = delete;
+};
+
+class GoASTCallExpr : public GoASTExpr
+{
+ public:
+ explicit GoASTCallExpr(bool ellipsis) : GoASTExpr(eCallExpr), m_ellipsis(ellipsis) {}
+ ~GoASTCallExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "CallExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eCallExpr;
+ }
+
+ const GoASTExpr *
+ GetFun() const
+ {
+ return m_fun_up.get();
+ }
+ void
+ SetFun(GoASTExpr *fun)
+ {
+ m_fun_up.reset(fun);
+ }
+
+ size_t
+ NumArgs() const
+ {
+ return m_args.size();
+ }
+ const GoASTExpr *
+ GetArgs(int i) const
+ {
+ return m_args[i].get();
+ }
+ void
+ AddArgs(GoASTExpr *args)
+ {
+ m_args.push_back(std::unique_ptr<GoASTExpr>(args));
+ }
+
+ bool
+ GetEllipsis() const
+ {
+ return m_ellipsis;
+ }
+ void
+ SetEllipsis(bool ellipsis)
+ {
+ m_ellipsis = ellipsis;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_fun_up;
+ std::vector<std::unique_ptr<GoASTExpr> > m_args;
+ bool m_ellipsis;
+
+ GoASTCallExpr(const GoASTCallExpr &) = delete;
+ const GoASTCallExpr &operator=(const GoASTCallExpr &) = delete;
+};
+
+class GoASTCaseClause : public GoASTStmt
+{
+ public:
+ GoASTCaseClause() : GoASTStmt(eCaseClause) {}
+ ~GoASTCaseClause() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "CaseClause";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eCaseClause;
+ }
+
+ size_t
+ NumList() const
+ {
+ return m_list.size();
+ }
+ const GoASTExpr *
+ GetList(int i) const
+ {
+ return m_list[i].get();
+ }
+ void
+ AddList(GoASTExpr *list)
+ {
+ m_list.push_back(std::unique_ptr<GoASTExpr>(list));
+ }
+
+ size_t
+ NumBody() const
+ {
+ return m_body.size();
+ }
+ const GoASTStmt *
+ GetBody(int i) const
+ {
+ return m_body[i].get();
+ }
+ void
+ AddBody(GoASTStmt *body)
+ {
+ m_body.push_back(std::unique_ptr<GoASTStmt>(body));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTExpr> > m_list;
+ std::vector<std::unique_ptr<GoASTStmt> > m_body;
+
+ GoASTCaseClause(const GoASTCaseClause &) = delete;
+ const GoASTCaseClause &operator=(const GoASTCaseClause &) = delete;
+};
+
+class GoASTChanType : public GoASTExpr
+{
+ public:
+ GoASTChanType(ChanDir dir, GoASTExpr *value) : GoASTExpr(eChanType), m_dir(dir), m_value_up(value) {}
+ ~GoASTChanType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ChanType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eChanType;
+ }
+
+ ChanDir
+ GetDir() const
+ {
+ return m_dir;
+ }
+ void
+ SetDir(ChanDir dir)
+ {
+ m_dir = dir;
+ }
+
+ const GoASTExpr *
+ GetValue() const
+ {
+ return m_value_up.get();
+ }
+ void
+ SetValue(GoASTExpr *value)
+ {
+ m_value_up.reset(value);
+ }
+
+ private:
+ friend class GoASTNode;
+ ChanDir m_dir;
+ std::unique_ptr<GoASTExpr> m_value_up;
+
+ GoASTChanType(const GoASTChanType &) = delete;
+ const GoASTChanType &operator=(const GoASTChanType &) = delete;
+};
+
+class GoASTCommClause : public GoASTStmt
+{
+ public:
+ GoASTCommClause() : GoASTStmt(eCommClause) {}
+ ~GoASTCommClause() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "CommClause";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eCommClause;
+ }
+
+ const GoASTStmt *
+ GetComm() const
+ {
+ return m_comm_up.get();
+ }
+ void
+ SetComm(GoASTStmt *comm)
+ {
+ m_comm_up.reset(comm);
+ }
+
+ size_t
+ NumBody() const
+ {
+ return m_body.size();
+ }
+ const GoASTStmt *
+ GetBody(int i) const
+ {
+ return m_body[i].get();
+ }
+ void
+ AddBody(GoASTStmt *body)
+ {
+ m_body.push_back(std::unique_ptr<GoASTStmt>(body));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTStmt> m_comm_up;
+ std::vector<std::unique_ptr<GoASTStmt> > m_body;
+
+ GoASTCommClause(const GoASTCommClause &) = delete;
+ const GoASTCommClause &operator=(const GoASTCommClause &) = delete;
+};
+
+class GoASTCompositeLit : public GoASTExpr
+{
+ public:
+ GoASTCompositeLit() : GoASTExpr(eCompositeLit) {}
+ ~GoASTCompositeLit() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "CompositeLit";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eCompositeLit;
+ }
+
+ const GoASTExpr *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTExpr *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ size_t
+ NumElts() const
+ {
+ return m_elts.size();
+ }
+ const GoASTExpr *
+ GetElts(int i) const
+ {
+ return m_elts[i].get();
+ }
+ void
+ AddElts(GoASTExpr *elts)
+ {
+ m_elts.push_back(std::unique_ptr<GoASTExpr>(elts));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_type_up;
+ std::vector<std::unique_ptr<GoASTExpr> > m_elts;
+
+ GoASTCompositeLit(const GoASTCompositeLit &) = delete;
+ const GoASTCompositeLit &operator=(const GoASTCompositeLit &) = delete;
+};
+
+class GoASTDeclStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTDeclStmt(GoASTDecl *decl) : GoASTStmt(eDeclStmt), m_decl_up(decl) {}
+ ~GoASTDeclStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "DeclStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eDeclStmt;
+ }
+
+ const GoASTDecl *
+ GetDecl() const
+ {
+ return m_decl_up.get();
+ }
+ void
+ SetDecl(GoASTDecl *decl)
+ {
+ m_decl_up.reset(decl);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTDecl> m_decl_up;
+
+ GoASTDeclStmt(const GoASTDeclStmt &) = delete;
+ const GoASTDeclStmt &operator=(const GoASTDeclStmt &) = delete;
+};
+
+class GoASTDeferStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTDeferStmt(GoASTCallExpr *call) : GoASTStmt(eDeferStmt), m_call_up(call) {}
+ ~GoASTDeferStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "DeferStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eDeferStmt;
+ }
+
+ const GoASTCallExpr *
+ GetCall() const
+ {
+ return m_call_up.get();
+ }
+ void
+ SetCall(GoASTCallExpr *call)
+ {
+ m_call_up.reset(call);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTCallExpr> m_call_up;
+
+ GoASTDeferStmt(const GoASTDeferStmt &) = delete;
+ const GoASTDeferStmt &operator=(const GoASTDeferStmt &) = delete;
+};
+
+class GoASTEllipsis : public GoASTExpr
+{
+ public:
+ explicit GoASTEllipsis(GoASTExpr *elt) : GoASTExpr(eEllipsis), m_elt_up(elt) {}
+ ~GoASTEllipsis() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "Ellipsis";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eEllipsis;
+ }
+
+ const GoASTExpr *
+ GetElt() const
+ {
+ return m_elt_up.get();
+ }
+ void
+ SetElt(GoASTExpr *elt)
+ {
+ m_elt_up.reset(elt);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_elt_up;
+
+ GoASTEllipsis(const GoASTEllipsis &) = delete;
+ const GoASTEllipsis &operator=(const GoASTEllipsis &) = delete;
+};
+
+class GoASTEmptyStmt : public GoASTStmt
+{
+ public:
+ GoASTEmptyStmt() : GoASTStmt(eEmptyStmt) {}
+ ~GoASTEmptyStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "EmptyStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eEmptyStmt;
+ }
+
+ GoASTEmptyStmt(const GoASTEmptyStmt &) = delete;
+ const GoASTEmptyStmt &operator=(const GoASTEmptyStmt &) = delete;
+};
+
+class GoASTExprStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTExprStmt(GoASTExpr *x) : GoASTStmt(eExprStmt), m_x_up(x) {}
+ ~GoASTExprStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ExprStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eExprStmt;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+
+ GoASTExprStmt(const GoASTExprStmt &) = delete;
+ const GoASTExprStmt &operator=(const GoASTExprStmt &) = delete;
+};
+
+class GoASTField : public GoASTNode
+{
+ public:
+ GoASTField() : GoASTNode(eField) {}
+ ~GoASTField() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "Field";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eField;
+ }
+
+ size_t
+ NumNames() const
+ {
+ return m_names.size();
+ }
+ const GoASTIdent *
+ GetNames(int i) const
+ {
+ return m_names[i].get();
+ }
+ void
+ AddNames(GoASTIdent *names)
+ {
+ m_names.push_back(std::unique_ptr<GoASTIdent>(names));
+ }
+
+ const GoASTExpr *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTExpr *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ const GoASTBasicLit *
+ GetTag() const
+ {
+ return m_tag_up.get();
+ }
+ void
+ SetTag(GoASTBasicLit *tag)
+ {
+ m_tag_up.reset(tag);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTIdent> > m_names;
+ std::unique_ptr<GoASTExpr> m_type_up;
+ std::unique_ptr<GoASTBasicLit> m_tag_up;
+
+ GoASTField(const GoASTField &) = delete;
+ const GoASTField &operator=(const GoASTField &) = delete;
+};
+
+class GoASTFieldList : public GoASTNode
+{
+ public:
+ GoASTFieldList() : GoASTNode(eFieldList) {}
+ ~GoASTFieldList() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "FieldList";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eFieldList;
+ }
+
+ size_t
+ NumList() const
+ {
+ return m_list.size();
+ }
+ const GoASTField *
+ GetList(int i) const
+ {
+ return m_list[i].get();
+ }
+ void
+ AddList(GoASTField *list)
+ {
+ m_list.push_back(std::unique_ptr<GoASTField>(list));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTField> > m_list;
+
+ GoASTFieldList(const GoASTFieldList &) = delete;
+ const GoASTFieldList &operator=(const GoASTFieldList &) = delete;
+};
+
+class GoASTForStmt : public GoASTStmt
+{
+ public:
+ GoASTForStmt(GoASTStmt *init, GoASTExpr *cond, GoASTStmt *post, GoASTBlockStmt *body) : GoASTStmt(eForStmt), m_init_up(init), m_cond_up(cond), m_post_up(post), m_body_up(body) {}
+ ~GoASTForStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ForStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eForStmt;
+ }
+
+ const GoASTStmt *
+ GetInit() const
+ {
+ return m_init_up.get();
+ }
+ void
+ SetInit(GoASTStmt *init)
+ {
+ m_init_up.reset(init);
+ }
+
+ const GoASTExpr *
+ GetCond() const
+ {
+ return m_cond_up.get();
+ }
+ void
+ SetCond(GoASTExpr *cond)
+ {
+ m_cond_up.reset(cond);
+ }
+
+ const GoASTStmt *
+ GetPost() const
+ {
+ return m_post_up.get();
+ }
+ void
+ SetPost(GoASTStmt *post)
+ {
+ m_post_up.reset(post);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTStmt> m_init_up;
+ std::unique_ptr<GoASTExpr> m_cond_up;
+ std::unique_ptr<GoASTStmt> m_post_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTForStmt(const GoASTForStmt &) = delete;
+ const GoASTForStmt &operator=(const GoASTForStmt &) = delete;
+};
+
+class GoASTFuncType : public GoASTExpr
+{
+ public:
+ GoASTFuncType(GoASTFieldList *params, GoASTFieldList *results) : GoASTExpr(eFuncType), m_params_up(params), m_results_up(results) {}
+ ~GoASTFuncType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "FuncType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eFuncType;
+ }
+
+ const GoASTFieldList *
+ GetParams() const
+ {
+ return m_params_up.get();
+ }
+ void
+ SetParams(GoASTFieldList *params)
+ {
+ m_params_up.reset(params);
+ }
+
+ const GoASTFieldList *
+ GetResults() const
+ {
+ return m_results_up.get();
+ }
+ void
+ SetResults(GoASTFieldList *results)
+ {
+ m_results_up.reset(results);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTFieldList> m_params_up;
+ std::unique_ptr<GoASTFieldList> m_results_up;
+
+ GoASTFuncType(const GoASTFuncType &) = delete;
+ const GoASTFuncType &operator=(const GoASTFuncType &) = delete;
+};
+
+class GoASTFuncDecl : public GoASTDecl
+{
+ public:
+ GoASTFuncDecl(GoASTFieldList *recv, GoASTIdent *name, GoASTFuncType *type, GoASTBlockStmt *body) : GoASTDecl(eFuncDecl), m_recv_up(recv), m_name_up(name), m_type_up(type), m_body_up(body) {}
+ ~GoASTFuncDecl() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "FuncDecl";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eFuncDecl;
+ }
+
+ const GoASTFieldList *
+ GetRecv() const
+ {
+ return m_recv_up.get();
+ }
+ void
+ SetRecv(GoASTFieldList *recv)
+ {
+ m_recv_up.reset(recv);
+ }
+
+ const GoASTIdent *
+ GetName() const
+ {
+ return m_name_up.get();
+ }
+ void
+ SetName(GoASTIdent *name)
+ {
+ m_name_up.reset(name);
+ }
+
+ const GoASTFuncType *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTFuncType *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTFieldList> m_recv_up;
+ std::unique_ptr<GoASTIdent> m_name_up;
+ std::unique_ptr<GoASTFuncType> m_type_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTFuncDecl(const GoASTFuncDecl &) = delete;
+ const GoASTFuncDecl &operator=(const GoASTFuncDecl &) = delete;
+};
+
+class GoASTFuncLit : public GoASTExpr
+{
+ public:
+ GoASTFuncLit(GoASTFuncType *type, GoASTBlockStmt *body) : GoASTExpr(eFuncLit), m_type_up(type), m_body_up(body) {}
+ ~GoASTFuncLit() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "FuncLit";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eFuncLit;
+ }
+
+ const GoASTFuncType *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTFuncType *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTFuncType> m_type_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTFuncLit(const GoASTFuncLit &) = delete;
+ const GoASTFuncLit &operator=(const GoASTFuncLit &) = delete;
+};
+
+class GoASTGenDecl : public GoASTDecl
+{
+ public:
+ explicit GoASTGenDecl(TokenType tok) : GoASTDecl(eGenDecl), m_tok(tok) {}
+ ~GoASTGenDecl() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "GenDecl";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eGenDecl;
+ }
+
+ TokenType
+ GetTok() const
+ {
+ return m_tok;
+ }
+ void
+ SetTok(TokenType tok)
+ {
+ m_tok = tok;
+ }
+
+ size_t
+ NumSpecs() const
+ {
+ return m_specs.size();
+ }
+ const GoASTSpec *
+ GetSpecs(int i) const
+ {
+ return m_specs[i].get();
+ }
+ void
+ AddSpecs(GoASTSpec *specs)
+ {
+ m_specs.push_back(std::unique_ptr<GoASTSpec>(specs));
+ }
+
+ private:
+ friend class GoASTNode;
+ TokenType m_tok;
+ std::vector<std::unique_ptr<GoASTSpec> > m_specs;
+
+ GoASTGenDecl(const GoASTGenDecl &) = delete;
+ const GoASTGenDecl &operator=(const GoASTGenDecl &) = delete;
+};
+
+class GoASTGoStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTGoStmt(GoASTCallExpr *call) : GoASTStmt(eGoStmt), m_call_up(call) {}
+ ~GoASTGoStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "GoStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eGoStmt;
+ }
+
+ const GoASTCallExpr *
+ GetCall() const
+ {
+ return m_call_up.get();
+ }
+ void
+ SetCall(GoASTCallExpr *call)
+ {
+ m_call_up.reset(call);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTCallExpr> m_call_up;
+
+ GoASTGoStmt(const GoASTGoStmt &) = delete;
+ const GoASTGoStmt &operator=(const GoASTGoStmt &) = delete;
+};
+
+class GoASTIfStmt : public GoASTStmt
+{
+ public:
+ GoASTIfStmt(GoASTStmt *init, GoASTExpr *cond, GoASTBlockStmt *body, GoASTStmt *els) : GoASTStmt(eIfStmt), m_init_up(init), m_cond_up(cond), m_body_up(body), m_els_up(els) {}
+ ~GoASTIfStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "IfStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eIfStmt;
+ }
+
+ const GoASTStmt *
+ GetInit() const
+ {
+ return m_init_up.get();
+ }
+ void
+ SetInit(GoASTStmt *init)
+ {
+ m_init_up.reset(init);
+ }
+
+ const GoASTExpr *
+ GetCond() const
+ {
+ return m_cond_up.get();
+ }
+ void
+ SetCond(GoASTExpr *cond)
+ {
+ m_cond_up.reset(cond);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ const GoASTStmt *
+ GetEls() const
+ {
+ return m_els_up.get();
+ }
+ void
+ SetEls(GoASTStmt *els)
+ {
+ m_els_up.reset(els);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTStmt> m_init_up;
+ std::unique_ptr<GoASTExpr> m_cond_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+ std::unique_ptr<GoASTStmt> m_els_up;
+
+ GoASTIfStmt(const GoASTIfStmt &) = delete;
+ const GoASTIfStmt &operator=(const GoASTIfStmt &) = delete;
+};
+
+class GoASTImportSpec : public GoASTSpec
+{
+ public:
+ GoASTImportSpec(GoASTIdent *name, GoASTBasicLit *path) : GoASTSpec(eImportSpec), m_name_up(name), m_path_up(path) {}
+ ~GoASTImportSpec() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ImportSpec";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eImportSpec;
+ }
+
+ const GoASTIdent *
+ GetName() const
+ {
+ return m_name_up.get();
+ }
+ void
+ SetName(GoASTIdent *name)
+ {
+ m_name_up.reset(name);
+ }
+
+ const GoASTBasicLit *
+ GetPath() const
+ {
+ return m_path_up.get();
+ }
+ void
+ SetPath(GoASTBasicLit *path)
+ {
+ m_path_up.reset(path);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTIdent> m_name_up;
+ std::unique_ptr<GoASTBasicLit> m_path_up;
+
+ GoASTImportSpec(const GoASTImportSpec &) = delete;
+ const GoASTImportSpec &operator=(const GoASTImportSpec &) = delete;
+};
+
+class GoASTIncDecStmt : public GoASTStmt
+{
+ public:
+ GoASTIncDecStmt(GoASTExpr *x, TokenType tok) : GoASTStmt(eIncDecStmt), m_x_up(x), m_tok(tok) {}
+ ~GoASTIncDecStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "IncDecStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eIncDecStmt;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ TokenType
+ GetTok() const
+ {
+ return m_tok;
+ }
+ void
+ SetTok(TokenType tok)
+ {
+ m_tok = tok;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ TokenType m_tok;
+
+ GoASTIncDecStmt(const GoASTIncDecStmt &) = delete;
+ const GoASTIncDecStmt &operator=(const GoASTIncDecStmt &) = delete;
+};
+
+class GoASTIndexExpr : public GoASTExpr
+{
+ public:
+ GoASTIndexExpr(GoASTExpr *x, GoASTExpr *index) : GoASTExpr(eIndexExpr), m_x_up(x), m_index_up(index) {}
+ ~GoASTIndexExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "IndexExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eIndexExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTExpr *
+ GetIndex() const
+ {
+ return m_index_up.get();
+ }
+ void
+ SetIndex(GoASTExpr *index)
+ {
+ m_index_up.reset(index);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTExpr> m_index_up;
+
+ GoASTIndexExpr(const GoASTIndexExpr &) = delete;
+ const GoASTIndexExpr &operator=(const GoASTIndexExpr &) = delete;
+};
+
+class GoASTInterfaceType : public GoASTExpr
+{
+ public:
+ explicit GoASTInterfaceType(GoASTFieldList *methods) : GoASTExpr(eInterfaceType), m_methods_up(methods) {}
+ ~GoASTInterfaceType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "InterfaceType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eInterfaceType;
+ }
+
+ const GoASTFieldList *
+ GetMethods() const
+ {
+ return m_methods_up.get();
+ }
+ void
+ SetMethods(GoASTFieldList *methods)
+ {
+ m_methods_up.reset(methods);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTFieldList> m_methods_up;
+
+ GoASTInterfaceType(const GoASTInterfaceType &) = delete;
+ const GoASTInterfaceType &operator=(const GoASTInterfaceType &) = delete;
+};
+
+class GoASTKeyValueExpr : public GoASTExpr
+{
+ public:
+ GoASTKeyValueExpr(GoASTExpr *key, GoASTExpr *value) : GoASTExpr(eKeyValueExpr), m_key_up(key), m_value_up(value) {}
+ ~GoASTKeyValueExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "KeyValueExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eKeyValueExpr;
+ }
+
+ const GoASTExpr *
+ GetKey() const
+ {
+ return m_key_up.get();
+ }
+ void
+ SetKey(GoASTExpr *key)
+ {
+ m_key_up.reset(key);
+ }
+
+ const GoASTExpr *
+ GetValue() const
+ {
+ return m_value_up.get();
+ }
+ void
+ SetValue(GoASTExpr *value)
+ {
+ m_value_up.reset(value);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_key_up;
+ std::unique_ptr<GoASTExpr> m_value_up;
+
+ GoASTKeyValueExpr(const GoASTKeyValueExpr &) = delete;
+ const GoASTKeyValueExpr &operator=(const GoASTKeyValueExpr &) = delete;
+};
+
+class GoASTLabeledStmt : public GoASTStmt
+{
+ public:
+ GoASTLabeledStmt(GoASTIdent *label, GoASTStmt *stmt) : GoASTStmt(eLabeledStmt), m_label_up(label), m_stmt_up(stmt) {}
+ ~GoASTLabeledStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "LabeledStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eLabeledStmt;
+ }
+
+ const GoASTIdent *
+ GetLabel() const
+ {
+ return m_label_up.get();
+ }
+ void
+ SetLabel(GoASTIdent *label)
+ {
+ m_label_up.reset(label);
+ }
+
+ const GoASTStmt *
+ GetStmt() const
+ {
+ return m_stmt_up.get();
+ }
+ void
+ SetStmt(GoASTStmt *stmt)
+ {
+ m_stmt_up.reset(stmt);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTIdent> m_label_up;
+ std::unique_ptr<GoASTStmt> m_stmt_up;
+
+ GoASTLabeledStmt(const GoASTLabeledStmt &) = delete;
+ const GoASTLabeledStmt &operator=(const GoASTLabeledStmt &) = delete;
+};
+
+class GoASTMapType : public GoASTExpr
+{
+ public:
+ GoASTMapType(GoASTExpr *key, GoASTExpr *value) : GoASTExpr(eMapType), m_key_up(key), m_value_up(value) {}
+ ~GoASTMapType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "MapType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eMapType;
+ }
+
+ const GoASTExpr *
+ GetKey() const
+ {
+ return m_key_up.get();
+ }
+ void
+ SetKey(GoASTExpr *key)
+ {
+ m_key_up.reset(key);
+ }
+
+ const GoASTExpr *
+ GetValue() const
+ {
+ return m_value_up.get();
+ }
+ void
+ SetValue(GoASTExpr *value)
+ {
+ m_value_up.reset(value);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_key_up;
+ std::unique_ptr<GoASTExpr> m_value_up;
+
+ GoASTMapType(const GoASTMapType &) = delete;
+ const GoASTMapType &operator=(const GoASTMapType &) = delete;
+};
+
+class GoASTParenExpr : public GoASTExpr
+{
+ public:
+ explicit GoASTParenExpr(GoASTExpr *x) : GoASTExpr(eParenExpr), m_x_up(x) {}
+ ~GoASTParenExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ParenExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eParenExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+
+ GoASTParenExpr(const GoASTParenExpr &) = delete;
+ const GoASTParenExpr &operator=(const GoASTParenExpr &) = delete;
+};
+
+class GoASTRangeStmt : public GoASTStmt
+{
+ public:
+ GoASTRangeStmt(GoASTExpr *key, GoASTExpr *value, bool define, GoASTExpr *x, GoASTBlockStmt *body) : GoASTStmt(eRangeStmt), m_key_up(key), m_value_up(value), m_define(define), m_x_up(x), m_body_up(body) {}
+ ~GoASTRangeStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "RangeStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eRangeStmt;
+ }
+
+ const GoASTExpr *
+ GetKey() const
+ {
+ return m_key_up.get();
+ }
+ void
+ SetKey(GoASTExpr *key)
+ {
+ m_key_up.reset(key);
+ }
+
+ const GoASTExpr *
+ GetValue() const
+ {
+ return m_value_up.get();
+ }
+ void
+ SetValue(GoASTExpr *value)
+ {
+ m_value_up.reset(value);
+ }
+
+ bool
+ GetDefine() const
+ {
+ return m_define;
+ }
+ void
+ SetDefine(bool define)
+ {
+ m_define = define;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_key_up;
+ std::unique_ptr<GoASTExpr> m_value_up;
+ bool m_define;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTRangeStmt(const GoASTRangeStmt &) = delete;
+ const GoASTRangeStmt &operator=(const GoASTRangeStmt &) = delete;
+};
+
+class GoASTReturnStmt : public GoASTStmt
+{
+ public:
+ GoASTReturnStmt() : GoASTStmt(eReturnStmt) {}
+ ~GoASTReturnStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ReturnStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eReturnStmt;
+ }
+
+ size_t
+ NumResults() const
+ {
+ return m_results.size();
+ }
+ const GoASTExpr *
+ GetResults(int i) const
+ {
+ return m_results[i].get();
+ }
+ void
+ AddResults(GoASTExpr *results)
+ {
+ m_results.push_back(std::unique_ptr<GoASTExpr>(results));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTExpr> > m_results;
+
+ GoASTReturnStmt(const GoASTReturnStmt &) = delete;
+ const GoASTReturnStmt &operator=(const GoASTReturnStmt &) = delete;
+};
+
+class GoASTSelectStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTSelectStmt(GoASTBlockStmt *body) : GoASTStmt(eSelectStmt), m_body_up(body) {}
+ ~GoASTSelectStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "SelectStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eSelectStmt;
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTSelectStmt(const GoASTSelectStmt &) = delete;
+ const GoASTSelectStmt &operator=(const GoASTSelectStmt &) = delete;
+};
+
+class GoASTSelectorExpr : public GoASTExpr
+{
+ public:
+ GoASTSelectorExpr(GoASTExpr *x, GoASTIdent *sel) : GoASTExpr(eSelectorExpr), m_x_up(x), m_sel_up(sel) {}
+ ~GoASTSelectorExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "SelectorExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eSelectorExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTIdent *
+ GetSel() const
+ {
+ return m_sel_up.get();
+ }
+ void
+ SetSel(GoASTIdent *sel)
+ {
+ m_sel_up.reset(sel);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTIdent> m_sel_up;
+
+ GoASTSelectorExpr(const GoASTSelectorExpr &) = delete;
+ const GoASTSelectorExpr &operator=(const GoASTSelectorExpr &) = delete;
+};
+
+class GoASTSendStmt : public GoASTStmt
+{
+ public:
+ GoASTSendStmt(GoASTExpr *chan, GoASTExpr *value) : GoASTStmt(eSendStmt), m_chan_up(chan), m_value_up(value) {}
+ ~GoASTSendStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "SendStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eSendStmt;
+ }
+
+ const GoASTExpr *
+ GetChan() const
+ {
+ return m_chan_up.get();
+ }
+ void
+ SetChan(GoASTExpr *chan)
+ {
+ m_chan_up.reset(chan);
+ }
+
+ const GoASTExpr *
+ GetValue() const
+ {
+ return m_value_up.get();
+ }
+ void
+ SetValue(GoASTExpr *value)
+ {
+ m_value_up.reset(value);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_chan_up;
+ std::unique_ptr<GoASTExpr> m_value_up;
+
+ GoASTSendStmt(const GoASTSendStmt &) = delete;
+ const GoASTSendStmt &operator=(const GoASTSendStmt &) = delete;
+};
+
+class GoASTSliceExpr : public GoASTExpr
+{
+ public:
+ GoASTSliceExpr(GoASTExpr *x, GoASTExpr *low, GoASTExpr *high, GoASTExpr *max, bool slice3) : GoASTExpr(eSliceExpr), m_x_up(x), m_low_up(low), m_high_up(high), m_max_up(max), m_slice3(slice3) {}
+ ~GoASTSliceExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "SliceExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eSliceExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTExpr *
+ GetLow() const
+ {
+ return m_low_up.get();
+ }
+ void
+ SetLow(GoASTExpr *low)
+ {
+ m_low_up.reset(low);
+ }
+
+ const GoASTExpr *
+ GetHigh() const
+ {
+ return m_high_up.get();
+ }
+ void
+ SetHigh(GoASTExpr *high)
+ {
+ m_high_up.reset(high);
+ }
+
+ const GoASTExpr *
+ GetMax() const
+ {
+ return m_max_up.get();
+ }
+ void
+ SetMax(GoASTExpr *max)
+ {
+ m_max_up.reset(max);
+ }
+
+ bool
+ GetSlice3() const
+ {
+ return m_slice3;
+ }
+ void
+ SetSlice3(bool slice3)
+ {
+ m_slice3 = slice3;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTExpr> m_low_up;
+ std::unique_ptr<GoASTExpr> m_high_up;
+ std::unique_ptr<GoASTExpr> m_max_up;
+ bool m_slice3;
+
+ GoASTSliceExpr(const GoASTSliceExpr &) = delete;
+ const GoASTSliceExpr &operator=(const GoASTSliceExpr &) = delete;
+};
+
+class GoASTStarExpr : public GoASTExpr
+{
+ public:
+ explicit GoASTStarExpr(GoASTExpr *x) : GoASTExpr(eStarExpr), m_x_up(x) {}
+ ~GoASTStarExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "StarExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eStarExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+
+ GoASTStarExpr(const GoASTStarExpr &) = delete;
+ const GoASTStarExpr &operator=(const GoASTStarExpr &) = delete;
+};
+
+class GoASTStructType : public GoASTExpr
+{
+ public:
+ explicit GoASTStructType(GoASTFieldList *fields) : GoASTExpr(eStructType), m_fields_up(fields) {}
+ ~GoASTStructType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "StructType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eStructType;
+ }
+
+ const GoASTFieldList *
+ GetFields() const
+ {
+ return m_fields_up.get();
+ }
+ void
+ SetFields(GoASTFieldList *fields)
+ {
+ m_fields_up.reset(fields);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTFieldList> m_fields_up;
+
+ GoASTStructType(const GoASTStructType &) = delete;
+ const GoASTStructType &operator=(const GoASTStructType &) = delete;
+};
+
+class GoASTSwitchStmt : public GoASTStmt
+{
+ public:
+ GoASTSwitchStmt(GoASTStmt *init, GoASTExpr *tag, GoASTBlockStmt *body) : GoASTStmt(eSwitchStmt), m_init_up(init), m_tag_up(tag), m_body_up(body) {}
+ ~GoASTSwitchStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "SwitchStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eSwitchStmt;
+ }
+
+ const GoASTStmt *
+ GetInit() const
+ {
+ return m_init_up.get();
+ }
+ void
+ SetInit(GoASTStmt *init)
+ {
+ m_init_up.reset(init);
+ }
+
+ const GoASTExpr *
+ GetTag() const
+ {
+ return m_tag_up.get();
+ }
+ void
+ SetTag(GoASTExpr *tag)
+ {
+ m_tag_up.reset(tag);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTStmt> m_init_up;
+ std::unique_ptr<GoASTExpr> m_tag_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTSwitchStmt(const GoASTSwitchStmt &) = delete;
+ const GoASTSwitchStmt &operator=(const GoASTSwitchStmt &) = delete;
+};
+
+class GoASTTypeAssertExpr : public GoASTExpr
+{
+ public:
+ GoASTTypeAssertExpr(GoASTExpr *x, GoASTExpr *type) : GoASTExpr(eTypeAssertExpr), m_x_up(x), m_type_up(type) {}
+ ~GoASTTypeAssertExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "TypeAssertExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eTypeAssertExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTExpr *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTExpr *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTExpr> m_type_up;
+
+ GoASTTypeAssertExpr(const GoASTTypeAssertExpr &) = delete;
+ const GoASTTypeAssertExpr &operator=(const GoASTTypeAssertExpr &) = delete;
+};
+
+class GoASTTypeSpec : public GoASTSpec
+{
+ public:
+ GoASTTypeSpec(GoASTIdent *name, GoASTExpr *type) : GoASTSpec(eTypeSpec), m_name_up(name), m_type_up(type) {}
+ ~GoASTTypeSpec() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "TypeSpec";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eTypeSpec;
+ }
+
+ const GoASTIdent *
+ GetName() const
+ {
+ return m_name_up.get();
+ }
+ void
+ SetName(GoASTIdent *name)
+ {
+ m_name_up.reset(name);
+ }
+
+ const GoASTExpr *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTExpr *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTIdent> m_name_up;
+ std::unique_ptr<GoASTExpr> m_type_up;
+
+ GoASTTypeSpec(const GoASTTypeSpec &) = delete;
+ const GoASTTypeSpec &operator=(const GoASTTypeSpec &) = delete;
+};
+
+class GoASTTypeSwitchStmt : public GoASTStmt
+{
+ public:
+ GoASTTypeSwitchStmt(GoASTStmt *init, GoASTStmt *assign, GoASTBlockStmt *body) : GoASTStmt(eTypeSwitchStmt), m_init_up(init), m_assign_up(assign), m_body_up(body) {}
+ ~GoASTTypeSwitchStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "TypeSwitchStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eTypeSwitchStmt;
+ }
+
+ const GoASTStmt *
+ GetInit() const
+ {
+ return m_init_up.get();
+ }
+ void
+ SetInit(GoASTStmt *init)
+ {
+ m_init_up.reset(init);
+ }
+
+ const GoASTStmt *
+ GetAssign() const
+ {
+ return m_assign_up.get();
+ }
+ void
+ SetAssign(GoASTStmt *assign)
+ {
+ m_assign_up.reset(assign);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTStmt> m_init_up;
+ std::unique_ptr<GoASTStmt> m_assign_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTTypeSwitchStmt(const GoASTTypeSwitchStmt &) = delete;
+ const GoASTTypeSwitchStmt &operator=(const GoASTTypeSwitchStmt &) = delete;
+};
+
+class GoASTUnaryExpr : public GoASTExpr
+{
+ public:
+ GoASTUnaryExpr(TokenType op, GoASTExpr *x) : GoASTExpr(eUnaryExpr), m_op(op), m_x_up(x) {}
+ ~GoASTUnaryExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "UnaryExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eUnaryExpr;
+ }
+
+ TokenType
+ GetOp() const
+ {
+ return m_op;
+ }
+ void
+ SetOp(TokenType op)
+ {
+ m_op = op;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ private:
+ friend class GoASTNode;
+ TokenType m_op;
+ std::unique_ptr<GoASTExpr> m_x_up;
+
+ GoASTUnaryExpr(const GoASTUnaryExpr &) = delete;
+ const GoASTUnaryExpr &operator=(const GoASTUnaryExpr &) = delete;
+};
+
+class GoASTValueSpec : public GoASTSpec
+{
+ public:
+ GoASTValueSpec() : GoASTSpec(eValueSpec) {}
+ ~GoASTValueSpec() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ValueSpec";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eValueSpec;
+ }
+
+ size_t
+ NumNames() const
+ {
+ return m_names.size();
+ }
+ const GoASTIdent *
+ GetNames(int i) const
+ {
+ return m_names[i].get();
+ }
+ void
+ AddNames(GoASTIdent *names)
+ {
+ m_names.push_back(std::unique_ptr<GoASTIdent>(names));
+ }
+
+ const GoASTExpr *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTExpr *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ size_t
+ NumValues() const
+ {
+ return m_values.size();
+ }
+ const GoASTExpr *
+ GetValues(int i) const
+ {
+ return m_values[i].get();
+ }
+ void
+ AddValues(GoASTExpr *values)
+ {
+ m_values.push_back(std::unique_ptr<GoASTExpr>(values));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTIdent> > m_names;
+ std::unique_ptr<GoASTExpr> m_type_up;
+ std::vector<std::unique_ptr<GoASTExpr> > m_values;
+
+ GoASTValueSpec(const GoASTValueSpec &) = delete;
+ const GoASTValueSpec &operator=(const GoASTValueSpec &) = delete;
+};
+
+
+template <typename R, typename V>
+R GoASTDecl::Visit(V* v) const
+{
+ switch(GetKind())
+ {
+ case eBadDecl:
+ return v->VisitBadDecl(llvm::cast<const GoASTBadDecl>(this));
+ case eFuncDecl:
+ return v->VisitFuncDecl(llvm::cast<const GoASTFuncDecl>(this));
+ case eGenDecl:
+ return v->VisitGenDecl(llvm::cast<const GoASTGenDecl>(this));
+ default:
+ assert(false && "Invalid kind");
+ }
+}
+
+template <typename R, typename V>
+R GoASTExpr::Visit(V* v) const
+{
+ switch(GetKind())
+ {
+ case eArrayType:
+ return v->VisitArrayType(llvm::cast<const GoASTArrayType>(this));
+ case eBadExpr:
+ return v->VisitBadExpr(llvm::cast<const GoASTBadExpr>(this));
+ case eBasicLit:
+ return v->VisitBasicLit(llvm::cast<const GoASTBasicLit>(this));
+ case eBinaryExpr:
+ return v->VisitBinaryExpr(llvm::cast<const GoASTBinaryExpr>(this));
+ case eIdent:
+ return v->VisitIdent(llvm::cast<const GoASTIdent>(this));
+ case eCallExpr:
+ return v->VisitCallExpr(llvm::cast<const GoASTCallExpr>(this));
+ case eChanType:
+ return v->VisitChanType(llvm::cast<const GoASTChanType>(this));
+ case eCompositeLit:
+ return v->VisitCompositeLit(llvm::cast<const GoASTCompositeLit>(this));
+ case eEllipsis:
+ return v->VisitEllipsis(llvm::cast<const GoASTEllipsis>(this));
+ case eFuncType:
+ return v->VisitFuncType(llvm::cast<const GoASTFuncType>(this));
+ case eFuncLit:
+ return v->VisitFuncLit(llvm::cast<const GoASTFuncLit>(this));
+ case eIndexExpr:
+ return v->VisitIndexExpr(llvm::cast<const GoASTIndexExpr>(this));
+ case eInterfaceType:
+ return v->VisitInterfaceType(llvm::cast<const GoASTInterfaceType>(this));
+ case eKeyValueExpr:
+ return v->VisitKeyValueExpr(llvm::cast<const GoASTKeyValueExpr>(this));
+ case eMapType:
+ return v->VisitMapType(llvm::cast<const GoASTMapType>(this));
+ case eParenExpr:
+ return v->VisitParenExpr(llvm::cast<const GoASTParenExpr>(this));
+ case eSelectorExpr:
+ return v->VisitSelectorExpr(llvm::cast<const GoASTSelectorExpr>(this));
+ case eSliceExpr:
+ return v->VisitSliceExpr(llvm::cast<const GoASTSliceExpr>(this));
+ case eStarExpr:
+ return v->VisitStarExpr(llvm::cast<const GoASTStarExpr>(this));
+ case eStructType:
+ return v->VisitStructType(llvm::cast<const GoASTStructType>(this));
+ case eTypeAssertExpr:
+ return v->VisitTypeAssertExpr(llvm::cast<const GoASTTypeAssertExpr>(this));
+ case eUnaryExpr:
+ return v->VisitUnaryExpr(llvm::cast<const GoASTUnaryExpr>(this));
+ default:
+ assert(false && "Invalid kind");
+ }
+}
+
+template <typename R, typename V>
+R GoASTSpec::Visit(V* v) const
+{
+ switch(GetKind())
+ {
+ case eImportSpec:
+ return v->VisitImportSpec(llvm::cast<const GoASTImportSpec>(this));
+ case eTypeSpec:
+ return v->VisitTypeSpec(llvm::cast<const GoASTTypeSpec>(this));
+ case eValueSpec:
+ return v->VisitValueSpec(llvm::cast<const GoASTValueSpec>(this));
+ default:
+ assert(false && "Invalid kind");
+ }
+}
+
+template <typename R, typename V>
+R GoASTStmt::Visit(V* v) const
+{
+ switch(GetKind())
+ {
+ case eAssignStmt:
+ return v->VisitAssignStmt(llvm::cast<const GoASTAssignStmt>(this));
+ case eBadStmt:
+ return v->VisitBadStmt(llvm::cast<const GoASTBadStmt>(this));
+ case eBlockStmt:
+ return v->VisitBlockStmt(llvm::cast<const GoASTBlockStmt>(this));
+ case eBranchStmt:
+ return v->VisitBranchStmt(llvm::cast<const GoASTBranchStmt>(this));
+ case eCaseClause:
+ return v->VisitCaseClause(llvm::cast<const GoASTCaseClause>(this));
+ case eCommClause:
+ return v->VisitCommClause(llvm::cast<const GoASTCommClause>(this));
+ case eDeclStmt:
+ return v->VisitDeclStmt(llvm::cast<const GoASTDeclStmt>(this));
+ case eDeferStmt:
+ return v->VisitDeferStmt(llvm::cast<const GoASTDeferStmt>(this));
+ case eEmptyStmt:
+ return v->VisitEmptyStmt(llvm::cast<const GoASTEmptyStmt>(this));
+ case eExprStmt:
+ return v->VisitExprStmt(llvm::cast<const GoASTExprStmt>(this));
+ case eForStmt:
+ return v->VisitForStmt(llvm::cast<const GoASTForStmt>(this));
+ case eGoStmt:
+ return v->VisitGoStmt(llvm::cast<const GoASTGoStmt>(this));
+ case eIfStmt:
+ return v->VisitIfStmt(llvm::cast<const GoASTIfStmt>(this));
+ case eIncDecStmt:
+ return v->VisitIncDecStmt(llvm::cast<const GoASTIncDecStmt>(this));
+ case eLabeledStmt:
+ return v->VisitLabeledStmt(llvm::cast<const GoASTLabeledStmt>(this));
+ case eRangeStmt:
+ return v->VisitRangeStmt(llvm::cast<const GoASTRangeStmt>(this));
+ case eReturnStmt:
+ return v->VisitReturnStmt(llvm::cast<const GoASTReturnStmt>(this));
+ case eSelectStmt:
+ return v->VisitSelectStmt(llvm::cast<const GoASTSelectStmt>(this));
+ case eSendStmt:
+ return v->VisitSendStmt(llvm::cast<const GoASTSendStmt>(this));
+ case eSwitchStmt:
+ return v->VisitSwitchStmt(llvm::cast<const GoASTSwitchStmt>(this));
+ case eTypeSwitchStmt:
+ return v->VisitTypeSwitchStmt(llvm::cast<const GoASTTypeSwitchStmt>(this));
+ default:
+ assert(false && "Invalid kind");
+ }
+}
+
+template <typename V>
+void GoASTNode::WalkChildren(V &v)
+{
+ switch (m_kind)
+ {
+
+
+ case eArrayType:
+ {
+ GoASTArrayType *n = llvm::cast<GoASTArrayType>(this);
+ (void)n;
+ v(n->m_len_up.get());
+ v(n->m_elt_up.get());
+ return;
+ }
+ case eAssignStmt:
+ {
+ GoASTAssignStmt *n = llvm::cast<GoASTAssignStmt>(this);
+ (void)n;
+ for (auto& e : n->m_lhs) { v(e.get()); }
+ for (auto& e : n->m_rhs) { v(e.get()); }
+ return;
+ }
+ case eBasicLit:
+ {
+ GoASTBasicLit *n = llvm::cast<GoASTBasicLit>(this);
+ (void)n;
+ return;
+ }
+ case eBinaryExpr:
+ {
+ GoASTBinaryExpr *n = llvm::cast<GoASTBinaryExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ v(n->m_y_up.get());
+ return;
+ }
+ case eBlockStmt:
+ {
+ GoASTBlockStmt *n = llvm::cast<GoASTBlockStmt>(this);
+ (void)n;
+ for (auto& e : n->m_list) { v(e.get()); }
+ return;
+ }
+ case eIdent:
+ {
+ GoASTIdent *n = llvm::cast<GoASTIdent>(this);
+ (void)n;
+ return;
+ }
+ case eBranchStmt:
+ {
+ GoASTBranchStmt *n = llvm::cast<GoASTBranchStmt>(this);
+ (void)n;
+ v(n->m_label_up.get());
+ return;
+ }
+ case eCallExpr:
+ {
+ GoASTCallExpr *n = llvm::cast<GoASTCallExpr>(this);
+ (void)n;
+ v(n->m_fun_up.get());
+ for (auto& e : n->m_args) { v(e.get()); }
+ return;
+ }
+ case eCaseClause:
+ {
+ GoASTCaseClause *n = llvm::cast<GoASTCaseClause>(this);
+ (void)n;
+ for (auto& e : n->m_list) { v(e.get()); }
+ for (auto& e : n->m_body) { v(e.get()); }
+ return;
+ }
+ case eChanType:
+ {
+ GoASTChanType *n = llvm::cast<GoASTChanType>(this);
+ (void)n;
+ v(n->m_value_up.get());
+ return;
+ }
+ case eCommClause:
+ {
+ GoASTCommClause *n = llvm::cast<GoASTCommClause>(this);
+ (void)n;
+ v(n->m_comm_up.get());
+ for (auto& e : n->m_body) { v(e.get()); }
+ return;
+ }
+ case eCompositeLit:
+ {
+ GoASTCompositeLit *n = llvm::cast<GoASTCompositeLit>(this);
+ (void)n;
+ v(n->m_type_up.get());
+ for (auto& e : n->m_elts) { v(e.get()); }
+ return;
+ }
+ case eDeclStmt:
+ {
+ GoASTDeclStmt *n = llvm::cast<GoASTDeclStmt>(this);
+ (void)n;
+ v(n->m_decl_up.get());
+ return;
+ }
+ case eDeferStmt:
+ {
+ GoASTDeferStmt *n = llvm::cast<GoASTDeferStmt>(this);
+ (void)n;
+ v(n->m_call_up.get());
+ return;
+ }
+ case eEllipsis:
+ {
+ GoASTEllipsis *n = llvm::cast<GoASTEllipsis>(this);
+ (void)n;
+ v(n->m_elt_up.get());
+ return;
+ }
+ case eExprStmt:
+ {
+ GoASTExprStmt *n = llvm::cast<GoASTExprStmt>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ return;
+ }
+ case eField:
+ {
+ GoASTField *n = llvm::cast<GoASTField>(this);
+ (void)n;
+ for (auto& e : n->m_names) { v(e.get()); }
+ v(n->m_type_up.get());
+ v(n->m_tag_up.get());
+ return;
+ }
+ case eFieldList:
+ {
+ GoASTFieldList *n = llvm::cast<GoASTFieldList>(this);
+ (void)n;
+ for (auto& e : n->m_list) { v(e.get()); }
+ return;
+ }
+ case eForStmt:
+ {
+ GoASTForStmt *n = llvm::cast<GoASTForStmt>(this);
+ (void)n;
+ v(n->m_init_up.get());
+ v(n->m_cond_up.get());
+ v(n->m_post_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eFuncType:
+ {
+ GoASTFuncType *n = llvm::cast<GoASTFuncType>(this);
+ (void)n;
+ v(n->m_params_up.get());
+ v(n->m_results_up.get());
+ return;
+ }
+ case eFuncDecl:
+ {
+ GoASTFuncDecl *n = llvm::cast<GoASTFuncDecl>(this);
+ (void)n;
+ v(n->m_recv_up.get());
+ v(n->m_name_up.get());
+ v(n->m_type_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eFuncLit:
+ {
+ GoASTFuncLit *n = llvm::cast<GoASTFuncLit>(this);
+ (void)n;
+ v(n->m_type_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eGenDecl:
+ {
+ GoASTGenDecl *n = llvm::cast<GoASTGenDecl>(this);
+ (void)n;
+ for (auto& e : n->m_specs) { v(e.get()); }
+ return;
+ }
+ case eGoStmt:
+ {
+ GoASTGoStmt *n = llvm::cast<GoASTGoStmt>(this);
+ (void)n;
+ v(n->m_call_up.get());
+ return;
+ }
+ case eIfStmt:
+ {
+ GoASTIfStmt *n = llvm::cast<GoASTIfStmt>(this);
+ (void)n;
+ v(n->m_init_up.get());
+ v(n->m_cond_up.get());
+ v(n->m_body_up.get());
+ v(n->m_els_up.get());
+ return;
+ }
+ case eImportSpec:
+ {
+ GoASTImportSpec *n = llvm::cast<GoASTImportSpec>(this);
+ (void)n;
+ v(n->m_name_up.get());
+ v(n->m_path_up.get());
+ return;
+ }
+ case eIncDecStmt:
+ {
+ GoASTIncDecStmt *n = llvm::cast<GoASTIncDecStmt>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ return;
+ }
+ case eIndexExpr:
+ {
+ GoASTIndexExpr *n = llvm::cast<GoASTIndexExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ v(n->m_index_up.get());
+ return;
+ }
+ case eInterfaceType:
+ {
+ GoASTInterfaceType *n = llvm::cast<GoASTInterfaceType>(this);
+ (void)n;
+ v(n->m_methods_up.get());
+ return;
+ }
+ case eKeyValueExpr:
+ {
+ GoASTKeyValueExpr *n = llvm::cast<GoASTKeyValueExpr>(this);
+ (void)n;
+ v(n->m_key_up.get());
+ v(n->m_value_up.get());
+ return;
+ }
+ case eLabeledStmt:
+ {
+ GoASTLabeledStmt *n = llvm::cast<GoASTLabeledStmt>(this);
+ (void)n;
+ v(n->m_label_up.get());
+ v(n->m_stmt_up.get());
+ return;
+ }
+ case eMapType:
+ {
+ GoASTMapType *n = llvm::cast<GoASTMapType>(this);
+ (void)n;
+ v(n->m_key_up.get());
+ v(n->m_value_up.get());
+ return;
+ }
+ case eParenExpr:
+ {
+ GoASTParenExpr *n = llvm::cast<GoASTParenExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ return;
+ }
+ case eRangeStmt:
+ {
+ GoASTRangeStmt *n = llvm::cast<GoASTRangeStmt>(this);
+ (void)n;
+ v(n->m_key_up.get());
+ v(n->m_value_up.get());
+ v(n->m_x_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eReturnStmt:
+ {
+ GoASTReturnStmt *n = llvm::cast<GoASTReturnStmt>(this);
+ (void)n;
+ for (auto& e : n->m_results) { v(e.get()); }
+ return;
+ }
+ case eSelectStmt:
+ {
+ GoASTSelectStmt *n = llvm::cast<GoASTSelectStmt>(this);
+ (void)n;
+ v(n->m_body_up.get());
+ return;
+ }
+ case eSelectorExpr:
+ {
+ GoASTSelectorExpr *n = llvm::cast<GoASTSelectorExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ v(n->m_sel_up.get());
+ return;
+ }
+ case eSendStmt:
+ {
+ GoASTSendStmt *n = llvm::cast<GoASTSendStmt>(this);
+ (void)n;
+ v(n->m_chan_up.get());
+ v(n->m_value_up.get());
+ return;
+ }
+ case eSliceExpr:
+ {
+ GoASTSliceExpr *n = llvm::cast<GoASTSliceExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ v(n->m_low_up.get());
+ v(n->m_high_up.get());
+ v(n->m_max_up.get());
+ return;
+ }
+ case eStarExpr:
+ {
+ GoASTStarExpr *n = llvm::cast<GoASTStarExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ return;
+ }
+ case eStructType:
+ {
+ GoASTStructType *n = llvm::cast<GoASTStructType>(this);
+ (void)n;
+ v(n->m_fields_up.get());
+ return;
+ }
+ case eSwitchStmt:
+ {
+ GoASTSwitchStmt *n = llvm::cast<GoASTSwitchStmt>(this);
+ (void)n;
+ v(n->m_init_up.get());
+ v(n->m_tag_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eTypeAssertExpr:
+ {
+ GoASTTypeAssertExpr *n = llvm::cast<GoASTTypeAssertExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ v(n->m_type_up.get());
+ return;
+ }
+ case eTypeSpec:
+ {
+ GoASTTypeSpec *n = llvm::cast<GoASTTypeSpec>(this);
+ (void)n;
+ v(n->m_name_up.get());
+ v(n->m_type_up.get());
+ return;
+ }
+ case eTypeSwitchStmt:
+ {
+ GoASTTypeSwitchStmt *n = llvm::cast<GoASTTypeSwitchStmt>(this);
+ (void)n;
+ v(n->m_init_up.get());
+ v(n->m_assign_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eUnaryExpr:
+ {
+ GoASTUnaryExpr *n = llvm::cast<GoASTUnaryExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ return;
+ }
+ case eValueSpec:
+ {
+ GoASTValueSpec *n = llvm::cast<GoASTValueSpec>(this);
+ (void)n;
+ for (auto& e : n->m_names) { v(e.get()); }
+ v(n->m_type_up.get());
+ for (auto& e : n->m_values) { v(e.get()); }
+ return;
+ }
+
+ case eEmptyStmt:
+ case eBadDecl:
+ case eBadExpr:
+ case eBadStmt:
+ break;
+ }
+}
+
+} // namespace lldb_private
+
+#endif
+
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoLexer.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoLexer.cpp
new file mode 100644
index 0000000..6de0f56
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoLexer.cpp
@@ -0,0 +1,402 @@
+//===-- GoLexer.cpp ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "GoLexer.h"
+
+using namespace lldb_private;
+
+llvm::StringMap<GoLexer::TokenType> *GoLexer::m_keywords;
+
+GoLexer::GoLexer(const char *src) : m_src(src), m_end(src + strlen(src)), m_last_token(TOK_INVALID, "")
+{
+}
+
+bool
+GoLexer::SkipWhitespace()
+{
+ bool saw_newline = false;
+ for (; m_src < m_end; ++m_src)
+ {
+ if (*m_src == '\n')
+ saw_newline = true;
+ if (*m_src == '/' && !SkipComment())
+ return saw_newline;
+ else if (!IsWhitespace(*m_src))
+ return saw_newline;
+ }
+ return saw_newline;
+}
+
+bool
+GoLexer::SkipComment()
+{
+ if (m_src[0] == '/' && m_src[1] == '/')
+ {
+ for (const char *c = m_src + 2; c < m_end; ++c)
+ {
+ if (*c == '\n')
+ {
+ m_src = c - 1;
+ return true;
+ }
+ }
+ return true;
+ }
+ else if (m_src[0] == '/' && m_src[1] == '*')
+ {
+ for (const char *c = m_src + 2; c < m_end; ++c)
+ {
+ if (c[0] == '*' && c[1] == '/')
+ {
+ m_src = c + 1;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+const GoLexer::Token &
+GoLexer::Lex()
+{
+ bool newline = SkipWhitespace();
+ const char *start = m_src;
+ m_last_token.m_type = InternalLex(newline);
+ m_last_token.m_value = llvm::StringRef(start, m_src - start);
+ return m_last_token;
+}
+
+GoLexer::TokenType
+GoLexer::InternalLex(bool newline)
+{
+ if (m_src >= m_end)
+ {
+ return TOK_EOF;
+ }
+ if (newline)
+ {
+ switch (m_last_token.m_type)
+ {
+ case TOK_IDENTIFIER:
+ case LIT_FLOAT:
+ case LIT_IMAGINARY:
+ case LIT_INTEGER:
+ case LIT_RUNE:
+ case LIT_STRING:
+ case KEYWORD_BREAK:
+ case KEYWORD_CONTINUE:
+ case KEYWORD_FALLTHROUGH:
+ case KEYWORD_RETURN:
+ case OP_PLUS_PLUS:
+ case OP_MINUS_MINUS:
+ case OP_RPAREN:
+ case OP_RBRACK:
+ case OP_RBRACE:
+ return OP_SEMICOLON;
+ default:
+ break;
+ }
+ }
+ char c = *m_src;
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return DoNumber();
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '&':
+ case '|':
+ case '^':
+ case '<':
+ case '>':
+ case '!':
+ case ':':
+ case ';':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ case '{':
+ case '}':
+ case ',':
+ case '=':
+ return DoOperator();
+ case '.':
+ if (IsDecimal(m_src[1]))
+ return DoNumber();
+ return DoOperator();
+ case '$':
+ // For lldb persistent vars.
+ return DoIdent();
+ case '"':
+ case '`':
+ return DoString();
+ case '\'':
+ return DoRune();
+ default:
+ break;
+ }
+ if (IsLetterOrDigit(c))
+ return DoIdent();
+ ++m_src;
+ return TOK_INVALID;
+}
+
+GoLexer::TokenType
+GoLexer::DoOperator()
+{
+ TokenType t = TOK_INVALID;
+ if (m_end - m_src > 2)
+ {
+ t = LookupKeyword(llvm::StringRef(m_src, 3));
+ if (t != TOK_INVALID)
+ m_src += 3;
+ }
+ if (t == TOK_INVALID && m_end - m_src > 1)
+ {
+ t = LookupKeyword(llvm::StringRef(m_src, 2));
+ if (t != TOK_INVALID)
+ m_src += 2;
+ }
+ if (t == TOK_INVALID)
+ {
+ t = LookupKeyword(llvm::StringRef(m_src, 1));
+ ++m_src;
+ }
+ return t;
+}
+
+GoLexer::TokenType
+GoLexer::DoIdent()
+{
+ const char *start = m_src++;
+ while (m_src < m_end && IsLetterOrDigit(*m_src))
+ {
+ ++m_src;
+ }
+ TokenType kw = LookupKeyword(llvm::StringRef(start, m_src - start));
+ if (kw != TOK_INVALID)
+ return kw;
+ return TOK_IDENTIFIER;
+}
+
+GoLexer::TokenType
+GoLexer::DoNumber()
+{
+ if (m_src[0] == '0' && (m_src[1] == 'x' || m_src[1] == 'X'))
+ {
+ m_src += 2;
+ while (IsHexChar(*m_src))
+ ++m_src;
+ return LIT_INTEGER;
+ }
+ bool dot_ok = true;
+ bool e_ok = true;
+ while (true)
+ {
+ while (IsDecimal(*m_src))
+ ++m_src;
+ switch (*m_src)
+ {
+ case 'i':
+ ++m_src;
+ return LIT_IMAGINARY;
+ case '.':
+ if (!dot_ok)
+ return LIT_FLOAT;
+ ++m_src;
+ dot_ok = false;
+ break;
+ case 'e':
+ case 'E':
+ if (!e_ok)
+ return LIT_FLOAT;
+ dot_ok = e_ok = false;
+ ++m_src;
+ if (*m_src == '+' || *m_src == '-')
+ ++m_src;
+ break;
+ default:
+ if (dot_ok)
+ return LIT_INTEGER;
+ return LIT_FLOAT;
+ }
+ }
+}
+
+GoLexer::TokenType
+GoLexer::DoRune()
+{
+ while (++m_src < m_end)
+ {
+ switch (*m_src)
+ {
+ case '\'':
+ ++m_src;
+ return LIT_RUNE;
+ case '\n':
+ return TOK_INVALID;
+ case '\\':
+ if (m_src[1] == '\n')
+ return TOK_INVALID;
+ ++m_src;
+ }
+ }
+ return TOK_INVALID;
+}
+
+GoLexer::TokenType
+GoLexer::DoString()
+{
+ if (*m_src == '`')
+ {
+ while (++m_src < m_end)
+ {
+ if (*m_src == '`')
+ {
+ ++m_src;
+ return LIT_STRING;
+ }
+ }
+ return TOK_INVALID;
+ }
+ while (++m_src < m_end)
+ {
+ switch (*m_src)
+ {
+ case '"':
+ ++m_src;
+ return LIT_STRING;
+ case '\n':
+ return TOK_INVALID;
+ case '\\':
+ if (m_src[1] == '\n')
+ return TOK_INVALID;
+ ++m_src;
+ }
+ }
+ return TOK_INVALID;
+}
+
+GoLexer::TokenType
+GoLexer::LookupKeyword(llvm::StringRef id)
+{
+ if (m_keywords == nullptr)
+ m_keywords = InitKeywords();
+ const auto &it = m_keywords->find(id);
+ if (it == m_keywords->end())
+ return TOK_INVALID;
+ return it->second;
+}
+
+llvm::StringRef
+GoLexer::LookupToken(TokenType t)
+{
+ if (m_keywords == nullptr)
+ m_keywords = InitKeywords();
+ for (const auto &e : *m_keywords)
+ {
+ if (e.getValue() == t)
+ return e.getKey();
+ }
+ return "";
+}
+
+llvm::StringMap<GoLexer::TokenType> *
+GoLexer::InitKeywords()
+{
+ auto &result = *new llvm::StringMap<TokenType>(128);
+ result["break"] = KEYWORD_BREAK;
+ result["default"] = KEYWORD_DEFAULT;
+ result["func"] = KEYWORD_FUNC;
+ result["interface"] = KEYWORD_INTERFACE;
+ result["select"] = KEYWORD_SELECT;
+ result["case"] = KEYWORD_CASE;
+ result["defer"] = KEYWORD_DEFER;
+ result["go"] = KEYWORD_GO;
+ result["map"] = KEYWORD_MAP;
+ result["struct"] = KEYWORD_STRUCT;
+ result["chan"] = KEYWORD_CHAN;
+ result["else"] = KEYWORD_ELSE;
+ result["goto"] = KEYWORD_GOTO;
+ result["package"] = KEYWORD_PACKAGE;
+ result["switch"] = KEYWORD_SWITCH;
+ result["const"] = KEYWORD_CONST;
+ result["fallthrough"] = KEYWORD_FALLTHROUGH;
+ result["if"] = KEYWORD_IF;
+ result["range"] = KEYWORD_RANGE;
+ result["type"] = KEYWORD_TYPE;
+ result["continue"] = KEYWORD_CONTINUE;
+ result["for"] = KEYWORD_FOR;
+ result["import"] = KEYWORD_IMPORT;
+ result["return"] = KEYWORD_RETURN;
+ result["var"] = KEYWORD_VAR;
+ result["+"] = OP_PLUS;
+ result["-"] = OP_MINUS;
+ result["*"] = OP_STAR;
+ result["/"] = OP_SLASH;
+ result["%"] = OP_PERCENT;
+ result["&"] = OP_AMP;
+ result["|"] = OP_PIPE;
+ result["^"] = OP_CARET;
+ result["<<"] = OP_LSHIFT;
+ result[">>"] = OP_RSHIFT;
+ result["&^"] = OP_AMP_CARET;
+ result["+="] = OP_PLUS_EQ;
+ result["-="] = OP_MINUS_EQ;
+ result["*="] = OP_STAR_EQ;
+ result["/="] = OP_SLASH_EQ;
+ result["%="] = OP_PERCENT_EQ;
+ result["&="] = OP_AMP_EQ;
+ result["|="] = OP_PIPE_EQ;
+ result["^="] = OP_CARET_EQ;
+ result["<<="] = OP_LSHIFT_EQ;
+ result[">>="] = OP_RSHIFT_EQ;
+ result["&^="] = OP_AMP_CARET_EQ;
+ result["&&"] = OP_AMP_AMP;
+ result["||"] = OP_PIPE_PIPE;
+ result["<-"] = OP_LT_MINUS;
+ result["++"] = OP_PLUS_PLUS;
+ result["--"] = OP_MINUS_MINUS;
+ result["=="] = OP_EQ_EQ;
+ result["<"] = OP_LT;
+ result[">"] = OP_GT;
+ result["="] = OP_EQ;
+ result["!"] = OP_BANG;
+ result["!="] = OP_BANG_EQ;
+ result["<="] = OP_LT_EQ;
+ result[">="] = OP_GT_EQ;
+ result[":="] = OP_COLON_EQ;
+ result["..."] = OP_DOTS;
+ result["("] = OP_LPAREN;
+ result["["] = OP_LBRACK;
+ result["{"] = OP_LBRACE;
+ result[","] = OP_COMMA;
+ result["."] = OP_DOT;
+ result[")"] = OP_RPAREN;
+ result["]"] = OP_RBRACK;
+ result["}"] = OP_RBRACE;
+ result[";"] = OP_SEMICOLON;
+ result[":"] = OP_COLON;
+ return &result;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoLexer.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoLexer.h
new file mode 100644
index 0000000..e8e1635
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoLexer.h
@@ -0,0 +1,201 @@
+//===-- GoLexer.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoLexer_h
+#define liblldb_GoLexer_h
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace lldb_private
+{
+
+class GoLexer
+{
+ public:
+ explicit GoLexer(const char *src);
+
+ enum TokenType
+ {
+ TOK_EOF,
+ TOK_INVALID,
+ TOK_IDENTIFIER,
+ LIT_INTEGER,
+ LIT_FLOAT,
+ LIT_IMAGINARY,
+ LIT_RUNE,
+ LIT_STRING,
+ KEYWORD_BREAK,
+ KEYWORD_DEFAULT,
+ KEYWORD_FUNC,
+ KEYWORD_INTERFACE,
+ KEYWORD_SELECT,
+ KEYWORD_CASE,
+ KEYWORD_DEFER,
+ KEYWORD_GO,
+ KEYWORD_MAP,
+ KEYWORD_STRUCT,
+ KEYWORD_CHAN,
+ KEYWORD_ELSE,
+ KEYWORD_GOTO,
+ KEYWORD_PACKAGE,
+ KEYWORD_SWITCH,
+ KEYWORD_CONST,
+ KEYWORD_FALLTHROUGH,
+ KEYWORD_IF,
+ KEYWORD_RANGE,
+ KEYWORD_TYPE,
+ KEYWORD_CONTINUE,
+ KEYWORD_FOR,
+ KEYWORD_IMPORT,
+ KEYWORD_RETURN,
+ KEYWORD_VAR,
+ OP_PLUS,
+ OP_MINUS,
+ OP_STAR,
+ OP_SLASH,
+ OP_PERCENT,
+ OP_AMP,
+ OP_PIPE,
+ OP_CARET,
+ OP_LSHIFT,
+ OP_RSHIFT,
+ OP_AMP_CARET,
+ OP_PLUS_EQ,
+ OP_MINUS_EQ,
+ OP_STAR_EQ,
+ OP_SLASH_EQ,
+ OP_PERCENT_EQ,
+ OP_AMP_EQ,
+ OP_PIPE_EQ,
+ OP_CARET_EQ,
+ OP_LSHIFT_EQ,
+ OP_RSHIFT_EQ,
+ OP_AMP_CARET_EQ,
+ OP_AMP_AMP,
+ OP_PIPE_PIPE,
+ OP_LT_MINUS,
+ OP_PLUS_PLUS,
+ OP_MINUS_MINUS,
+ OP_EQ_EQ,
+ OP_LT,
+ OP_GT,
+ OP_EQ,
+ OP_BANG,
+ OP_BANG_EQ,
+ OP_LT_EQ,
+ OP_GT_EQ,
+ OP_COLON_EQ,
+ OP_DOTS,
+ OP_LPAREN,
+ OP_LBRACK,
+ OP_LBRACE,
+ OP_COMMA,
+ OP_DOT,
+ OP_RPAREN,
+ OP_RBRACK,
+ OP_RBRACE,
+ OP_SEMICOLON,
+ OP_COLON,
+ };
+
+ struct Token
+ {
+ explicit Token(TokenType t, llvm::StringRef text) : m_type(t), m_value(text) {}
+ TokenType m_type;
+ llvm::StringRef m_value;
+ };
+
+ const Token &Lex();
+
+ size_t
+ BytesRemaining() const
+ {
+ return m_end - m_src;
+ }
+ llvm::StringRef
+ GetString(int len) const
+ {
+ return llvm::StringRef(m_src, len);
+ }
+
+ static TokenType LookupKeyword(llvm::StringRef id);
+ static llvm::StringRef LookupToken(TokenType t);
+
+ private:
+ bool
+ IsDecimal(char c)
+ {
+ return c >= '0' && c <= '9';
+ }
+ bool
+ IsHexChar(char c)
+ {
+ if (c >= '0' && c <= '9')
+ return true;
+ if (c >= 'A' && c <= 'F')
+ return true;
+ if (c >= 'a' && c <= 'f')
+ return true;
+ return false;
+ }
+ bool
+ IsLetterOrDigit(char c)
+ {
+ if (c >= 'a' && c <= 'z')
+ return true;
+ if (c >= 'A' && c <= 'Z')
+ return true;
+ if (c == '_')
+ return true;
+ if (c >= '0' && c <= '9')
+ return true;
+ // Treat all non-ascii chars as letters for simplicity.
+ return 0 != (c & 0x80);
+ }
+ bool
+ IsWhitespace(char c)
+ {
+ switch (c)
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ return true;
+ }
+ return false;
+ }
+
+ bool SkipWhitespace();
+ bool SkipComment();
+
+ TokenType InternalLex(bool newline);
+
+ TokenType DoOperator();
+
+ TokenType DoIdent();
+
+ TokenType DoNumber();
+
+ TokenType DoRune();
+
+ TokenType DoString();
+
+ static llvm::StringMap<TokenType> *InitKeywords();
+
+ static llvm::StringMap<TokenType> *m_keywords;
+
+ const char *m_src;
+ const char *m_end;
+ Token m_last_token;
+};
+
+} // namespace lldb_private
+
+#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp
new file mode 100644
index 0000000..0f136f7
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.cpp
@@ -0,0 +1,1035 @@
+//===-- GoParser.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "GoParser.h"
+
+#include "lldb/Core/Error.h"
+#include "llvm/ADT/SmallString.h"
+#include "Plugins/ExpressionParser/Go/GoAST.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+namespace
+{
+llvm::StringRef
+DescribeToken(GoLexer::TokenType t)
+{
+ switch (t)
+ {
+ case GoLexer::TOK_EOF:
+ return "<eof>";
+ case GoLexer::TOK_IDENTIFIER:
+ return "identifier";
+ case GoLexer::LIT_FLOAT:
+ return "float";
+ case GoLexer::LIT_IMAGINARY:
+ return "imaginary";
+ case GoLexer::LIT_INTEGER:
+ return "integer";
+ case GoLexer::LIT_RUNE:
+ return "rune";
+ case GoLexer::LIT_STRING:
+ return "string";
+ default:
+ return GoLexer::LookupToken(t);
+ }
+}
+} // namespace
+
+class GoParser::Rule
+{
+ public:
+ Rule(llvm::StringRef name, GoParser *p) : m_name(name), m_parser(p), m_pos(p->m_pos) {}
+
+ std::nullptr_t
+ error()
+ {
+ if (!m_parser->m_failed)
+ {
+ // Set m_error in case this is the top level.
+ if (m_parser->m_last_tok == GoLexer::TOK_INVALID)
+ m_parser->m_error = m_parser->m_last;
+ else
+ m_parser->m_error = DescribeToken(m_parser->m_last_tok);
+ // And set m_last in case it isn't.
+ m_parser->m_last = m_name;
+ m_parser->m_last_tok = GoLexer::TOK_INVALID;
+ m_parser->m_pos = m_pos;
+ }
+ return nullptr;
+ }
+
+ private:
+ llvm::StringRef m_name;
+ GoParser *m_parser;
+ size_t m_pos;
+};
+
+GoParser::GoParser(const char *src) : m_lexer(src), m_pos(0), m_failed(false)
+{
+}
+
+GoASTStmt *
+GoParser::Statement()
+{
+ Rule r("Statement", this);
+ GoLexer::TokenType t = peek();
+ GoASTStmt *ret = nullptr;
+ switch (t)
+ {
+ case GoLexer::TOK_EOF:
+ case GoLexer::OP_SEMICOLON:
+ case GoLexer::OP_RPAREN:
+ case GoLexer::OP_RBRACE:
+ case GoLexer::TOK_INVALID:
+ return EmptyStmt();
+ case GoLexer::OP_LBRACE:
+ return Block();
+
+ /* TODO:
+ case GoLexer::KEYWORD_GO:
+ return GoStmt();
+ case GoLexer::KEYWORD_RETURN:
+ return ReturnStmt();
+ case GoLexer::KEYWORD_BREAK:
+ case GoLexer::KEYWORD_CONTINUE:
+ case GoLexer::KEYWORD_GOTO:
+ case GoLexer::KEYWORD_FALLTHROUGH:
+ return BranchStmt();
+ case GoLexer::KEYWORD_IF:
+ return IfStmt();
+ case GoLexer::KEYWORD_SWITCH:
+ return SwitchStmt();
+ case GoLexer::KEYWORD_SELECT:
+ return SelectStmt();
+ case GoLexer::KEYWORD_FOR:
+ return ForStmt();
+ case GoLexer::KEYWORD_DEFER:
+ return DeferStmt();
+ case GoLexer::KEYWORD_CONST:
+ case GoLexer::KEYWORD_TYPE:
+ case GoLexer::KEYWORD_VAR:
+ return DeclStmt();
+ case GoLexer::TOK_IDENTIFIER:
+ if ((ret = LabeledStmt()) ||
+ (ret = ShortVarDecl()))
+ {
+ return ret;
+ }
+*/
+ default:
+ break;
+ }
+ GoASTExpr *expr = Expression();
+ if (expr == nullptr)
+ return r.error();
+ if (/*(ret = SendStmt(expr)) ||*/
+ (ret = IncDecStmt(expr)) || (ret = Assignment(expr)) || (ret = ExpressionStmt(expr)))
+ {
+ return ret;
+ }
+ delete expr;
+ return r.error();
+}
+
+GoASTStmt *
+GoParser::ExpressionStmt(GoASTExpr *e)
+{
+ if (Semicolon())
+ return new GoASTExprStmt(e);
+ return nullptr;
+}
+
+GoASTStmt *
+GoParser::IncDecStmt(GoASTExpr *e)
+{
+ Rule r("IncDecStmt", this);
+ if (match(GoLexer::OP_PLUS_PLUS))
+ return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_PLUS_PLUS) : r.error();
+ if (match(GoLexer::OP_MINUS_MINUS))
+ return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_MINUS_MINUS) : r.error();
+ return nullptr;
+}
+
+GoASTStmt *
+GoParser::Assignment(lldb_private::GoASTExpr *e)
+{
+ Rule r("Assignment", this);
+ std::vector<std::unique_ptr<GoASTExpr>> lhs;
+ for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList())
+ lhs.push_back(std::unique_ptr<GoASTExpr>(l));
+ switch (peek())
+ {
+ case GoLexer::OP_EQ:
+ case GoLexer::OP_PLUS_EQ:
+ case GoLexer::OP_MINUS_EQ:
+ case GoLexer::OP_PIPE_EQ:
+ case GoLexer::OP_CARET_EQ:
+ case GoLexer::OP_STAR_EQ:
+ case GoLexer::OP_SLASH_EQ:
+ case GoLexer::OP_PERCENT_EQ:
+ case GoLexer::OP_LSHIFT_EQ:
+ case GoLexer::OP_RSHIFT_EQ:
+ case GoLexer::OP_AMP_EQ:
+ case GoLexer::OP_AMP_CARET_EQ:
+ break;
+ default:
+ return r.error();
+ }
+ // We don't want to own e until we know this is an assignment.
+ std::unique_ptr<GoASTAssignStmt> stmt(new GoASTAssignStmt(false));
+ stmt->AddLhs(e);
+ for (auto &l : lhs)
+ stmt->AddLhs(l.release());
+ for (GoASTExpr *r = Expression(); r; r = MoreExpressionList())
+ stmt->AddRhs(r);
+ if (!Semicolon() || stmt->NumRhs() == 0)
+ return new GoASTBadStmt;
+ return stmt.release();
+}
+
+GoASTStmt *
+GoParser::EmptyStmt()
+{
+ if (match(GoLexer::TOK_EOF))
+ return nullptr;
+ if (Semicolon())
+ return new GoASTEmptyStmt;
+ return nullptr;
+}
+
+GoASTStmt *
+GoParser::GoStmt()
+{
+ if (match(GoLexer::KEYWORD_GO))
+ {
+ if (GoASTCallExpr *e = llvm::dyn_cast_or_null<GoASTCallExpr>(Expression()))
+ {
+ return FinishStmt(new GoASTGoStmt(e));
+ }
+ m_last = "call expression";
+ m_failed = true;
+ return new GoASTBadStmt();
+ }
+ return nullptr;
+}
+
+GoASTStmt *
+GoParser::ReturnStmt()
+{
+ if (match(GoLexer::KEYWORD_RETURN))
+ {
+ std::unique_ptr<GoASTReturnStmt> r(new GoASTReturnStmt());
+ for (GoASTExpr *e = Expression(); e; e = MoreExpressionList())
+ r->AddResults(e);
+ return FinishStmt(r.release());
+ }
+ return nullptr;
+}
+
+GoASTStmt *
+GoParser::BranchStmt()
+{
+ GoLexer::Token *tok;
+ if ((tok = match(GoLexer::KEYWORD_BREAK)) || (tok = match(GoLexer::KEYWORD_CONTINUE)) ||
+ (tok = match(GoLexer::KEYWORD_GOTO)))
+ {
+ auto *e = Identifier();
+ if (tok->m_type == GoLexer::KEYWORD_GOTO && !e)
+ return syntaxerror();
+ return FinishStmt(new GoASTBranchStmt(e, tok->m_type));
+ }
+ if ((tok = match(GoLexer::KEYWORD_FALLTHROUGH)))
+ return FinishStmt(new GoASTBranchStmt(nullptr, tok->m_type));
+
+ return nullptr;
+}
+
+GoASTIdent *
+GoParser::Identifier()
+{
+ if (auto *tok = match(GoLexer::TOK_IDENTIFIER))
+ return new GoASTIdent(*tok);
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::MoreExpressionList()
+{
+ if (match(GoLexer::OP_COMMA))
+ {
+ auto *e = Expression();
+ if (!e)
+ return syntaxerror();
+ return e;
+ }
+ return nullptr;
+}
+
+GoASTIdent *
+GoParser::MoreIdentifierList()
+{
+ if (match(GoLexer::OP_COMMA))
+ {
+ auto *i = Identifier();
+ if (!i)
+ return syntaxerror();
+ return i;
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::Expression()
+{
+ Rule r("Expression", this);
+ if (GoASTExpr *ret = OrExpr())
+ return ret;
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::UnaryExpr()
+{
+ switch (peek())
+ {
+ case GoLexer::OP_PLUS:
+ case GoLexer::OP_MINUS:
+ case GoLexer::OP_BANG:
+ case GoLexer::OP_CARET:
+ case GoLexer::OP_STAR:
+ case GoLexer::OP_AMP:
+ case GoLexer::OP_LT_MINUS:
+ {
+ const GoLexer::Token t = next();
+ if (GoASTExpr *e = UnaryExpr())
+ {
+ if (t.m_type == GoLexer::OP_STAR)
+ return new GoASTStarExpr(e);
+ else
+ return new GoASTUnaryExpr(t.m_type, e);
+ }
+ return syntaxerror();
+ }
+ default:
+ return PrimaryExpr();
+ }
+}
+
+GoASTExpr *
+GoParser::OrExpr()
+{
+ std::unique_ptr<GoASTExpr> l(AndExpr());
+ if (l)
+ {
+ while (match(GoLexer::OP_PIPE_PIPE))
+ {
+ GoASTExpr *r = AndExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_PIPE_PIPE));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::AndExpr()
+{
+ std::unique_ptr<GoASTExpr> l(RelExpr());
+ if (l)
+ {
+ while (match(GoLexer::OP_AMP_AMP))
+ {
+ GoASTExpr *r = RelExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_AMP_AMP));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::RelExpr()
+{
+ std::unique_ptr<GoASTExpr> l(AddExpr());
+ if (l)
+ {
+ for (GoLexer::Token *t; (t = match(GoLexer::OP_EQ_EQ)) || (t = match(GoLexer::OP_BANG_EQ)) ||
+ (t = match(GoLexer::OP_LT)) || (t = match(GoLexer::OP_LT_EQ)) ||
+ (t = match(GoLexer::OP_GT)) || (t = match(GoLexer::OP_GT_EQ));)
+ {
+ GoLexer::TokenType op = t->m_type;
+ GoASTExpr *r = AddExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, op));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::AddExpr()
+{
+ std::unique_ptr<GoASTExpr> l(MulExpr());
+ if (l)
+ {
+ for (GoLexer::Token *t; (t = match(GoLexer::OP_PLUS)) || (t = match(GoLexer::OP_MINUS)) ||
+ (t = match(GoLexer::OP_PIPE)) || (t = match(GoLexer::OP_CARET));)
+ {
+ GoLexer::TokenType op = t->m_type;
+ GoASTExpr *r = MulExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, op));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::MulExpr()
+{
+ std::unique_ptr<GoASTExpr> l(UnaryExpr());
+ if (l)
+ {
+ for (GoLexer::Token *t; (t = match(GoLexer::OP_STAR)) || (t = match(GoLexer::OP_SLASH)) ||
+ (t = match(GoLexer::OP_PERCENT)) || (t = match(GoLexer::OP_LSHIFT)) ||
+ (t = match(GoLexer::OP_RSHIFT)) || (t = match(GoLexer::OP_AMP)) ||
+ (t = match(GoLexer::OP_AMP_CARET));)
+ {
+ GoLexer::TokenType op = t->m_type;
+ GoASTExpr *r = UnaryExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, op));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::PrimaryExpr()
+{
+ GoASTExpr *l;
+ GoASTExpr *r;
+ (l = Conversion()) || (l = Operand());
+ if (!l)
+ return nullptr;
+ while ((r = Selector(l)) || (r = IndexOrSlice(l)) || (r = TypeAssertion(l)) || (r = Arguments(l)))
+ {
+ l = r;
+ }
+ return l;
+}
+
+GoASTExpr *
+GoParser::Operand()
+{
+ GoLexer::Token *lit;
+ if ((lit = match(GoLexer::LIT_INTEGER)) || (lit = match(GoLexer::LIT_FLOAT)) ||
+ (lit = match(GoLexer::LIT_IMAGINARY)) || (lit = match(GoLexer::LIT_RUNE)) || (lit = match(GoLexer::LIT_STRING)))
+ return new GoASTBasicLit(*lit);
+ if (match(GoLexer::OP_LPAREN))
+ {
+ GoASTExpr *e;
+ if (!((e = Expression()) && match(GoLexer::OP_RPAREN)))
+ return syntaxerror();
+ return e;
+ }
+ // MethodExpr should be handled by Selector
+ if (GoASTExpr *e = CompositeLit())
+ return e;
+ if (GoASTExpr *n = Name())
+ return n;
+ return FunctionLit();
+}
+
+GoASTExpr *
+GoParser::FunctionLit()
+{
+ if (!match(GoLexer::KEYWORD_FUNC))
+ return nullptr;
+ auto *sig = Signature();
+ if (!sig)
+ return syntaxerror();
+ auto *body = Block();
+ if (!body)
+ {
+ delete sig;
+ return syntaxerror();
+ }
+ return new GoASTFuncLit(sig, body);
+}
+
+GoASTBlockStmt *
+GoParser::Block()
+{
+ if (!match(GoLexer::OP_LBRACE))
+ return nullptr;
+ std::unique_ptr<GoASTBlockStmt> block(new GoASTBlockStmt);
+ for (auto *s = Statement(); s; s = Statement())
+ block->AddList(s);
+ if (!match(GoLexer::OP_RBRACE))
+ return syntaxerror();
+ return block.release();
+}
+
+GoASTExpr *
+GoParser::CompositeLit()
+{
+ Rule r("CompositeLit", this);
+ GoASTExpr *type;
+ (type = StructType()) || (type = ArrayOrSliceType(true)) || (type = MapType()) || (type = Name());
+ if (!type)
+ return r.error();
+ GoASTCompositeLit *lit = LiteralValue();
+ if (!lit)
+ return r.error();
+ lit->SetType(type);
+ return lit;
+}
+
+GoASTCompositeLit *
+GoParser::LiteralValue()
+{
+ if (!match(GoLexer::OP_LBRACE))
+ return nullptr;
+ std::unique_ptr<GoASTCompositeLit> lit(new GoASTCompositeLit);
+ for (GoASTExpr *e = Element(); e; e = Element())
+ {
+ lit->AddElts(e);
+ if (!match(GoLexer::OP_COMMA))
+ break;
+ }
+ if (!mustMatch(GoLexer::OP_RBRACE))
+ return nullptr;
+ return lit.release();
+}
+
+GoASTExpr *
+GoParser::Element()
+{
+ GoASTExpr *key;
+ if (!((key = Expression()) || (key = LiteralValue())))
+ return nullptr;
+ if (!match(GoLexer::OP_COLON))
+ return key;
+ GoASTExpr *value;
+ if ((value = Expression()) || (value = LiteralValue()))
+ return new GoASTKeyValueExpr(key, value);
+ delete key;
+ return syntaxerror();
+}
+
+GoASTExpr *
+GoParser::Selector(GoASTExpr *e)
+{
+ Rule r("Selector", this);
+ if (match(GoLexer::OP_DOT))
+ {
+ if (auto *name = Identifier())
+ return new GoASTSelectorExpr(e, name);
+ }
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::IndexOrSlice(GoASTExpr *e)
+{
+ Rule r("IndexOrSlice", this);
+ if (match(GoLexer::OP_LBRACK))
+ {
+ std::unique_ptr<GoASTExpr> i1(Expression()), i2, i3;
+ bool slice = false;
+ if (match(GoLexer::OP_COLON))
+ {
+ slice = true;
+ i2.reset(Expression());
+ if (i2 && match(GoLexer::OP_COLON))
+ {
+ i3.reset(Expression());
+ if (!i3)
+ return syntaxerror();
+ }
+ }
+ if (!(slice || i1))
+ return syntaxerror();
+ if (!mustMatch(GoLexer::OP_RBRACK))
+ return nullptr;
+ if (slice)
+ {
+ bool slice3 = i3.get();
+ return new GoASTSliceExpr(e, i1.release(), i2.release(), i3.release(), slice3);
+ }
+ return new GoASTIndexExpr(e, i1.release());
+ }
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::TypeAssertion(GoASTExpr *e)
+{
+ Rule r("TypeAssertion", this);
+ if (match(GoLexer::OP_DOT) && match(GoLexer::OP_LPAREN))
+ {
+ if (auto *t = Type())
+ {
+ if (!mustMatch(GoLexer::OP_RPAREN))
+ return nullptr;
+ return new GoASTTypeAssertExpr(e, t);
+ }
+ return syntaxerror();
+ }
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::Arguments(GoASTExpr *e)
+{
+ if (match(GoLexer::OP_LPAREN))
+ {
+ std::unique_ptr<GoASTCallExpr> call(new GoASTCallExpr(false));
+ GoASTExpr *arg;
+ // ( ExpressionList | Type [ "," ExpressionList ] )
+ for ((arg = Expression()) || (arg = Type()); arg; arg = MoreExpressionList())
+ {
+ call->AddArgs(arg);
+ }
+ if (match(GoLexer::OP_DOTS))
+ call->SetEllipsis(true);
+
+ // Eat trailing comma
+ match(GoLexer::OP_COMMA);
+
+ if (!mustMatch(GoLexer::OP_RPAREN))
+ return nullptr;
+ call->SetFun(e);
+ return call.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::Conversion()
+{
+ Rule r("Conversion", this);
+ if (GoASTExpr *t = Type2())
+ {
+ if (match(GoLexer::OP_LPAREN))
+ {
+ GoASTExpr *v = Expression();
+ if (!v)
+ return syntaxerror();
+ match(GoLexer::OP_COMMA);
+ if (!mustMatch(GoLexer::OP_RPAREN))
+ return r.error();
+ GoASTCallExpr *call = new GoASTCallExpr(false);
+ call->SetFun(t);
+ call->AddArgs(v);
+ return call;
+ }
+ }
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::Type2()
+{
+ switch (peek())
+ {
+ case GoLexer::OP_LBRACK:
+ return ArrayOrSliceType(false);
+ case GoLexer::KEYWORD_STRUCT:
+ return StructType();
+ case GoLexer::KEYWORD_FUNC:
+ return FunctionType();
+ case GoLexer::KEYWORD_INTERFACE:
+ return InterfaceType();
+ case GoLexer::KEYWORD_MAP:
+ return MapType();
+ case GoLexer::KEYWORD_CHAN:
+ return ChanType2();
+ default:
+ return nullptr;
+ }
+}
+
+GoASTExpr *
+GoParser::ArrayOrSliceType(bool allowEllipsis)
+{
+ Rule r("ArrayType", this);
+ if (match(GoLexer::OP_LBRACK))
+ {
+ std::unique_ptr<GoASTExpr> len;
+ if (allowEllipsis && match(GoLexer::OP_DOTS))
+ {
+ len.reset(new GoASTEllipsis(nullptr));
+ }
+ else
+ {
+ len.reset(Expression());
+ }
+
+ if (!match(GoLexer::OP_RBRACK))
+ return r.error();
+ GoASTExpr *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTArrayType(len.release(), elem);
+ }
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::StructType()
+{
+ if (!(match(GoLexer::KEYWORD_STRUCT) && mustMatch(GoLexer::OP_LBRACE)))
+ return nullptr;
+ std::unique_ptr<GoASTFieldList> fields(new GoASTFieldList);
+ while (auto *field = FieldDecl())
+ fields->AddList(field);
+ if (!mustMatch(GoLexer::OP_RBRACE))
+ return nullptr;
+ return new GoASTStructType(fields.release());
+}
+
+GoASTField *
+GoParser::FieldDecl()
+{
+ std::unique_ptr<GoASTField> f(new GoASTField);
+ GoASTExpr *t = FieldNamesAndType(f.get());
+ if (!t)
+ t = AnonymousFieldType();
+ if (!t)
+ return nullptr;
+
+ if (auto *tok = match(GoLexer::LIT_STRING))
+ f->SetTag(new GoASTBasicLit(*tok));
+ if (!Semicolon())
+ return syntaxerror();
+ return f.release();
+}
+
+GoASTExpr *
+GoParser::FieldNamesAndType(GoASTField *field)
+{
+ Rule r("FieldNames", this);
+ for (auto *id = Identifier(); id; id = MoreIdentifierList())
+ field->AddNames(id);
+ if (m_failed)
+ return nullptr;
+ GoASTExpr *t = Type();
+ if (t)
+ return t;
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::AnonymousFieldType()
+{
+ bool pointer = match(GoLexer::OP_STAR);
+ GoASTExpr *t = Type();
+ if (!t)
+ return nullptr;
+ if (pointer)
+ return new GoASTStarExpr(t);
+ return t;
+}
+
+GoASTExpr *
+GoParser::FunctionType()
+{
+ if (!match(GoLexer::KEYWORD_FUNC))
+ return nullptr;
+ return Signature();
+}
+
+GoASTFuncType *
+GoParser::Signature()
+{
+ auto *params = Params();
+ if (!params)
+ return syntaxerror();
+ auto *result = Params();
+ if (!result)
+ {
+ if (auto *t = Type())
+ {
+ result = new GoASTFieldList;
+ auto *f = new GoASTField;
+ f->SetType(t);
+ result->AddList(f);
+ }
+ }
+ return new GoASTFuncType(params, result);
+}
+
+GoASTFieldList *
+GoParser::Params()
+{
+ if (!match(GoLexer::OP_LPAREN))
+ return nullptr;
+ std::unique_ptr<GoASTFieldList> l(new GoASTFieldList);
+ while (GoASTField *p = ParamDecl())
+ {
+ l->AddList(p);
+ if (!match(GoLexer::OP_COMMA))
+ break;
+ }
+ if (!mustMatch(GoLexer::OP_RPAREN))
+ return nullptr;
+ return l.release();
+}
+
+GoASTField *
+GoParser::ParamDecl()
+{
+ std::unique_ptr<GoASTField> field(new GoASTField);
+ GoASTIdent *id = Identifier();
+ if (id)
+ {
+ // Try `IdentifierList [ "..." ] Type`.
+ // If that fails, backtrack and try `[ "..." ] Type`.
+ Rule r("NamedParam", this);
+ for (; id; id = MoreIdentifierList())
+ field->AddNames(id);
+ GoASTExpr *t = ParamType();
+ if (t)
+ {
+ field->SetType(t);
+ return field.release();
+ }
+ field.reset(new GoASTField);
+ r.error();
+ }
+ GoASTExpr *t = ParamType();
+ if (t)
+ {
+ field->SetType(t);
+ return field.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::ParamType()
+{
+ bool dots = match(GoLexer::OP_DOTS);
+ GoASTExpr *t = Type();
+ if (!dots)
+ return t;
+ if (!t)
+ return syntaxerror();
+ return new GoASTEllipsis(t);
+}
+
+GoASTExpr *
+GoParser::InterfaceType()
+{
+ if (!match(GoLexer::KEYWORD_INTERFACE) || !mustMatch(GoLexer::OP_LBRACE))
+ return nullptr;
+ std::unique_ptr<GoASTFieldList> methods(new GoASTFieldList);
+ while (true)
+ {
+ Rule r("MethodSpec", this);
+ // ( identifier Signature | TypeName ) ;
+ std::unique_ptr<GoASTIdent> id(Identifier());
+ if (!id)
+ break;
+ GoASTExpr *type = Signature();
+ if (!type)
+ {
+ r.error();
+ id.reset();
+ type = Name();
+ }
+ if (!Semicolon())
+ return syntaxerror();
+ auto *f = new GoASTField;
+ if (id)
+ f->AddNames(id.release());
+ f->SetType(type);
+ methods->AddList(f);
+ }
+ if (!mustMatch(GoLexer::OP_RBRACE))
+ return nullptr;
+ return new GoASTInterfaceType(methods.release());
+}
+
+GoASTExpr *
+GoParser::MapType()
+{
+ if (!(match(GoLexer::KEYWORD_MAP) && mustMatch(GoLexer::OP_LBRACK)))
+ return nullptr;
+ std::unique_ptr<GoASTExpr> key(Type());
+ if (!key)
+ return syntaxerror();
+ if (!mustMatch(GoLexer::OP_RBRACK))
+ return nullptr;
+ auto *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTMapType(key.release(), elem);
+}
+
+GoASTExpr *
+GoParser::ChanType()
+{
+ Rule r("chan", this);
+ if (match(GoLexer::OP_LT_MINUS))
+ {
+ if (match(GoLexer::KEYWORD_CHAN))
+ {
+ auto *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTChanType(GoASTNode::eChanRecv, elem);
+ }
+ return r.error();
+ }
+ return ChanType2();
+}
+
+GoASTExpr *
+GoParser::ChanType2()
+{
+ if (!match(GoLexer::KEYWORD_CHAN))
+ return nullptr;
+ auto dir = GoASTNode::eChanBidir;
+ if (match(GoLexer::OP_LT_MINUS))
+ dir = GoASTNode::eChanSend;
+ auto *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTChanType(dir, elem);
+}
+
+GoASTExpr *
+GoParser::Type()
+{
+ if (GoASTExpr *t = Type2())
+ return t;
+ if (GoASTExpr *t = Name())
+ return t;
+ if (GoASTExpr *t = ChanType())
+ return t;
+ if (match(GoLexer::OP_STAR))
+ {
+ GoASTExpr *t = Type();
+ if (!t)
+ return syntaxerror();
+ return new GoASTStarExpr(t);
+ }
+ if (match(GoLexer::OP_LPAREN))
+ {
+ std::unique_ptr<GoASTExpr> t(Type());
+ if (!t || !match(GoLexer::OP_RPAREN))
+ return syntaxerror();
+ return t.release();
+ }
+ return nullptr;
+}
+
+bool
+GoParser::Semicolon()
+{
+ if (match(GoLexer::OP_SEMICOLON))
+ return true;
+ switch (peek())
+ {
+ case GoLexer::OP_RPAREN:
+ case GoLexer::OP_RBRACE:
+ case GoLexer::TOK_EOF:
+ return true;
+ default:
+ return false;
+ }
+}
+
+GoASTExpr *
+GoParser::Name()
+{
+ if (auto *id = Identifier())
+ {
+ if (GoASTExpr *qual = QualifiedIdent(id))
+ return qual;
+ return id;
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::QualifiedIdent(lldb_private::GoASTIdent *p)
+{
+ Rule r("QualifiedIdent", this);
+ llvm::SmallString<32> path(p->GetName().m_value);
+ GoLexer::Token *next;
+ bool have_slashes = false;
+ // LLDB extension: support full/package/path.name
+ while (match(GoLexer::OP_SLASH) && (next = match(GoLexer::TOK_IDENTIFIER)))
+ {
+ have_slashes = true;
+ path.append("/");
+ path.append(next->m_value);
+ }
+ if (match(GoLexer::OP_DOT))
+ {
+ auto *name = Identifier();
+ if (name)
+ {
+ if (have_slashes)
+ {
+ p->SetName(GoLexer::Token(GoLexer::TOK_IDENTIFIER, CopyString(path)));
+ }
+ return new GoASTSelectorExpr(p, name);
+ }
+ }
+ return r.error();
+}
+
+llvm::StringRef
+GoParser::CopyString(llvm::StringRef s)
+{
+ return m_strings.insert(std::make_pair(s, 'x')).first->getKey();
+}
+
+void
+GoParser::GetError(Error &error)
+{
+ llvm::StringRef want;
+ if (m_failed)
+ want = m_last_tok == GoLexer::TOK_INVALID ? DescribeToken(m_last_tok) : m_last;
+ else
+ want = m_error;
+ size_t len = m_lexer.BytesRemaining();
+ if (len > 10)
+ len = 10;
+ llvm::StringRef got;
+ if (len == 0)
+ got = "<eof>";
+ else
+ got = m_lexer.GetString(len);
+ error.SetErrorStringWithFormat("Syntax error: expected %s before '%s'.", want.str().c_str(), got.str().c_str());
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.h
new file mode 100644
index 0000000..9ceb670
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoParser.h
@@ -0,0 +1,165 @@
+//===-- GoParser.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoParser_h
+#define liblldb_GoParser_h
+
+#include "lldb/lldb-private.h"
+#include "Plugins/ExpressionParser/Go/GoAST.h"
+#include "Plugins/ExpressionParser/Go/GoLexer.h"
+
+namespace lldb_private
+{
+class GoParser
+{
+ public:
+ explicit GoParser(const char *src);
+
+ GoASTStmt *Statement();
+
+ GoASTStmt *GoStmt();
+ GoASTStmt *ReturnStmt();
+ GoASTStmt *BranchStmt();
+ GoASTStmt *EmptyStmt();
+ GoASTStmt *ExpressionStmt(GoASTExpr *e);
+ GoASTStmt *IncDecStmt(GoASTExpr *e);
+ GoASTStmt *Assignment(GoASTExpr *e);
+ GoASTBlockStmt *Block();
+
+ GoASTExpr *MoreExpressionList(); // ["," Expression]
+ GoASTIdent *MoreIdentifierList(); // ["," Identifier]
+
+ GoASTExpr *Expression();
+ GoASTExpr *UnaryExpr();
+ GoASTExpr *OrExpr();
+ GoASTExpr *AndExpr();
+ GoASTExpr *RelExpr();
+ GoASTExpr *AddExpr();
+ GoASTExpr *MulExpr();
+ GoASTExpr *PrimaryExpr();
+ GoASTExpr *Operand();
+ GoASTExpr *Conversion();
+
+ GoASTExpr *Selector(GoASTExpr *e);
+ GoASTExpr *IndexOrSlice(GoASTExpr *e);
+ GoASTExpr *TypeAssertion(GoASTExpr *e);
+ GoASTExpr *Arguments(GoASTExpr *e);
+
+ GoASTExpr *Type();
+ GoASTExpr *Type2();
+ GoASTExpr *ArrayOrSliceType(bool allowEllipsis);
+ GoASTExpr *StructType();
+ GoASTExpr *FunctionType();
+ GoASTExpr *InterfaceType();
+ GoASTExpr *MapType();
+ GoASTExpr *ChanType();
+ GoASTExpr *ChanType2();
+
+ GoASTExpr *Name();
+ GoASTExpr *QualifiedIdent(GoASTIdent *p);
+ GoASTIdent *Identifier();
+
+ GoASTField *FieldDecl();
+ GoASTExpr *AnonymousFieldType();
+ GoASTExpr *FieldNamesAndType(GoASTField *f);
+
+ GoASTFieldList *Params();
+ GoASTField *ParamDecl();
+ GoASTExpr *ParamType();
+ GoASTFuncType *Signature();
+ GoASTExpr *CompositeLit();
+ GoASTExpr *FunctionLit();
+ GoASTExpr *Element();
+ GoASTCompositeLit *LiteralValue();
+
+ bool
+ Failed() const
+ {
+ return m_failed;
+ }
+ bool
+ AtEOF() const
+ {
+ return m_lexer.BytesRemaining() == 0 && m_pos == m_tokens.size();
+ }
+
+ void GetError(Error &error);
+
+ private:
+ class Rule;
+ friend class Rule;
+
+ std::nullptr_t
+ syntaxerror()
+ {
+ m_failed = true;
+ return nullptr;
+ }
+ GoLexer::Token &
+ next()
+ {
+ if (m_pos >= m_tokens.size())
+ {
+ if (m_pos != 0 &&
+ (m_tokens.back().m_type == GoLexer::TOK_EOF || m_tokens.back().m_type == GoLexer::TOK_INVALID))
+ return m_tokens.back();
+ m_pos = m_tokens.size();
+ m_tokens.push_back(m_lexer.Lex());
+ }
+ return m_tokens[m_pos++];
+ }
+ GoLexer::TokenType
+ peek()
+ {
+ GoLexer::Token &tok = next();
+ --m_pos;
+ return tok.m_type;
+ }
+ GoLexer::Token *
+ match(GoLexer::TokenType t)
+ {
+ GoLexer::Token &tok = next();
+ if (tok.m_type == t)
+ return &tok;
+ --m_pos;
+ m_last_tok = t;
+ return nullptr;
+ }
+ GoLexer::Token *
+ mustMatch(GoLexer::TokenType t)
+ {
+ GoLexer::Token *tok = match(t);
+ if (tok)
+ return tok;
+ return syntaxerror();
+ }
+ bool Semicolon();
+
+ GoASTStmt *
+ FinishStmt(GoASTStmt *s)
+ {
+ if (!Semicolon())
+ m_failed = true;
+ return s;
+ }
+
+ llvm::StringRef CopyString(llvm::StringRef s);
+
+ GoLexer m_lexer;
+ std::vector<GoLexer::Token> m_tokens;
+ size_t m_pos;
+ llvm::StringRef m_error;
+ llvm::StringRef m_last;
+ GoLexer::TokenType m_last_tok;
+ llvm::StringMap<uint8_t> m_strings;
+ bool m_failed;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
new file mode 100644
index 0000000..3f12a2b
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
@@ -0,0 +1,756 @@
+//===-- GoUserExpression.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+// C++ Includes
+#include <cstdlib>
+#include <memory>
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+
+// Project includes
+#include "GoUserExpression.h"
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataEncoder.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/GoASTContext.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+
+#include "Plugins/ExpressionParser/Go/GoAST.h"
+#include "Plugins/ExpressionParser/Go/GoParser.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+class GoUserExpression::GoInterpreter
+{
+ public:
+ GoInterpreter(ExecutionContext &exe_ctx, const char *expr)
+ : m_exe_ctx(exe_ctx), m_frame(exe_ctx.GetFrameSP()), m_parser(expr)
+ {
+ if (m_frame)
+ {
+ const SymbolContext &ctx = m_frame->GetSymbolContext(eSymbolContextFunction);
+ ConstString fname = ctx.GetFunctionName();
+ if (fname.GetLength() > 0)
+ {
+ size_t dot = fname.GetStringRef().find('.');
+ if (dot != llvm::StringRef::npos)
+ m_package = llvm::StringRef(fname.AsCString(), dot);
+ }
+ }
+ }
+
+ void
+ set_use_dynamic(DynamicValueType use_dynamic)
+ {
+ m_use_dynamic = use_dynamic;
+ }
+
+ bool Parse();
+ lldb::ValueObjectSP Evaluate(ExecutionContext &exe_ctx);
+ lldb::ValueObjectSP EvaluateStatement(const GoASTStmt *s);
+ lldb::ValueObjectSP EvaluateExpr(const GoASTExpr *e);
+
+ ValueObjectSP
+ VisitBadExpr(const GoASTBadExpr *e)
+ {
+ m_parser.GetError(m_error);
+ return nullptr;
+ }
+
+ ValueObjectSP VisitParenExpr(const GoASTParenExpr *e);
+ ValueObjectSP VisitIdent(const GoASTIdent *e);
+ ValueObjectSP VisitStarExpr(const GoASTStarExpr *e);
+ ValueObjectSP VisitSelectorExpr(const GoASTSelectorExpr *e);
+ ValueObjectSP VisitBasicLit(const GoASTBasicLit *e);
+ ValueObjectSP VisitIndexExpr(const GoASTIndexExpr *e);
+ ValueObjectSP VisitUnaryExpr(const GoASTUnaryExpr *e);
+ ValueObjectSP VisitCallExpr(const GoASTCallExpr *e);
+
+ ValueObjectSP
+ VisitTypeAssertExpr(const GoASTTypeAssertExpr *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitBinaryExpr(const GoASTBinaryExpr *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitArrayType(const GoASTArrayType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitChanType(const GoASTChanType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitCompositeLit(const GoASTCompositeLit *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitEllipsis(const GoASTEllipsis *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitFuncType(const GoASTFuncType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitFuncLit(const GoASTFuncLit *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitInterfaceType(const GoASTInterfaceType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitKeyValueExpr(const GoASTKeyValueExpr *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitMapType(const GoASTMapType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitSliceExpr(const GoASTSliceExpr *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitStructType(const GoASTStructType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ CompilerType EvaluateType(const GoASTExpr *e);
+
+ Error &
+ error()
+ {
+ return m_error;
+ }
+
+ private:
+ std::nullptr_t
+ NotImplemented(const GoASTExpr *e)
+ {
+ m_error.SetErrorStringWithFormat("%s node not implemented", e->GetKindName());
+ return nullptr;
+ }
+
+ ExecutionContext m_exe_ctx;
+ lldb::StackFrameSP m_frame;
+ GoParser m_parser;
+ DynamicValueType m_use_dynamic;
+ Error m_error;
+ llvm::StringRef m_package;
+ std::vector<std::unique_ptr<GoASTStmt>> m_statements;
+};
+
+VariableSP
+FindGlobalVariable(TargetSP target, llvm::Twine name)
+{
+ ConstString fullname(name.str());
+ VariableList variable_list;
+ const bool append = true;
+ if (!target)
+ {
+ return nullptr;
+ }
+ const uint32_t match_count = target->GetImages().FindGlobalVariables(fullname, append, 1, variable_list);
+ if (match_count == 1)
+ {
+ return variable_list.GetVariableAtIndex(0);
+ }
+ return nullptr;
+}
+
+CompilerType
+LookupType(TargetSP target, ConstString name)
+{
+ if (!target)
+ return CompilerType();
+ SymbolContext sc;
+ TypeList type_list;
+ uint32_t num_matches = target->GetImages().FindTypes(sc, name, false, 2, type_list);
+ if (num_matches > 0)
+ {
+ return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
+ }
+ return CompilerType();
+}
+
+GoUserExpression::GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+ lldb::LanguageType language, ResultType desired_type,
+ const EvaluateExpressionOptions &options)
+ : UserExpression(exe_scope, expr, expr_prefix, language, desired_type, options)
+{
+}
+
+bool
+GoUserExpression::Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy,
+ bool keep_result_in_memory, bool generate_debug_info)
+{
+ InstallContext(exe_ctx);
+ m_interpreter.reset(new GoInterpreter(exe_ctx, GetUserText()));
+ if (m_interpreter->Parse())
+ return true;
+ const char *error_cstr = m_interpreter->error().AsCString();
+ if (error_cstr && error_cstr[0])
+ error_stream.Printf("error: %s\n", error_cstr);
+ else
+ error_stream.Printf("error: expression can't be interpreted or run\n");
+ return false;
+}
+
+lldb::ExpressionResults
+GoUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options,
+ lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result)
+{
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+
+ lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
+ lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
+
+ Process *process = exe_ctx.GetProcessPtr();
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (target == nullptr || process == nullptr || process->GetState() != lldb::eStateStopped)
+ {
+ if (execution_policy == eExecutionPolicyAlways)
+ {
+ if (log)
+ log->Printf("== [GoUserExpression::Evaluate] Expression may not run, but is not constant ==");
+
+ error_stream.Printf("expression needed to run but couldn't");
+
+ return execution_results;
+ }
+ }
+
+ m_interpreter->set_use_dynamic(options.GetUseDynamic());
+ ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx);
+ Error err = m_interpreter->error();
+ m_interpreter.reset();
+
+ if (!result_val_sp)
+ {
+ const char *error_cstr = err.AsCString();
+ if (error_cstr && error_cstr[0])
+ error_stream.Printf("error: %s\n", error_cstr);
+ else
+ error_stream.Printf("error: expression can't be interpreted or run\n");
+ return lldb::eExpressionDiscarded;
+ }
+ result.reset(new ExpressionVariable(ExpressionVariable::eKindGo));
+ result->m_live_sp = result->m_frozen_sp = result_val_sp;
+ result->m_flags |= ExpressionVariable::EVIsProgramReference;
+ PersistentExpressionState *pv = target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo);
+ if (pv != nullptr)
+ {
+ result->SetName(pv->GetNextPersistentVariableName());
+ pv->AddVariable(result);
+ }
+ return lldb::eExpressionCompleted;
+}
+
+bool
+GoUserExpression::GoInterpreter::Parse()
+{
+ for (std::unique_ptr<GoASTStmt> stmt(m_parser.Statement()); stmt; stmt.reset(m_parser.Statement()))
+ {
+ if (m_parser.Failed())
+ break;
+ m_statements.emplace_back(std::move(stmt));
+ }
+ if (m_parser.Failed() || !m_parser.AtEOF())
+ m_parser.GetError(m_error);
+
+ return m_error.Success();
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::Evaluate(ExecutionContext &exe_ctx)
+{
+ m_exe_ctx = exe_ctx;
+ ValueObjectSP result;
+ for (const std::unique_ptr<GoASTStmt> &stmt : m_statements)
+ {
+ result = EvaluateStatement(stmt.get());
+ if (m_error.Fail())
+ return nullptr;
+ }
+ return result;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::EvaluateStatement(const lldb_private::GoASTStmt *stmt)
+{
+ ValueObjectSP result;
+ switch (stmt->GetKind())
+ {
+ case GoASTNode::eBlockStmt:
+ {
+ const GoASTBlockStmt *block = llvm::cast<GoASTBlockStmt>(stmt);
+ for (size_t i = 0; i < block->NumList(); ++i)
+ result = EvaluateStatement(block->GetList(i));
+ break;
+ }
+ case GoASTNode::eBadStmt:
+ m_parser.GetError(m_error);
+ break;
+ case GoASTNode::eExprStmt:
+ {
+ const GoASTExprStmt *expr = llvm::cast<GoASTExprStmt>(stmt);
+ return EvaluateExpr(expr->GetX());
+ }
+ default:
+ m_error.SetErrorStringWithFormat("%s node not supported", stmt->GetKindName());
+ }
+ return result;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::EvaluateExpr(const lldb_private::GoASTExpr *e)
+{
+ if (e)
+ return e->Visit<ValueObjectSP>(this);
+ return ValueObjectSP();
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitParenExpr(const lldb_private::GoASTParenExpr *e)
+{
+ return EvaluateExpr(e->GetX());
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e)
+{
+ ValueObjectSP val;
+ if (m_frame)
+ {
+ VariableSP var_sp;
+ std::string varname = e->GetName().m_value.str();
+ if (varname.size() > 1 && varname[0] == '$')
+ {
+ RegisterContextSP reg_ctx_sp = m_frame->GetRegisterContext();
+ const RegisterInfo *reg = reg_ctx_sp->GetRegisterInfoByName(varname.c_str() + 1);
+ if (reg)
+ {
+ std::string type;
+ switch (reg->encoding)
+ {
+ case lldb::eEncodingSint:
+ type.append("int");
+ break;
+ case lldb::eEncodingUint:
+ type.append("uint");
+ break;
+ case lldb::eEncodingIEEE754:
+ type.append("float");
+ break;
+ default:
+ m_error.SetErrorString("Invaild register encoding");
+ return nullptr;
+ }
+ switch (reg->byte_size)
+ {
+ case 8:
+ type.append("64");
+ break;
+ case 4:
+ type.append("32");
+ break;
+ case 2:
+ type.append("16");
+ break;
+ case 1:
+ type.append("8");
+ break;
+ default:
+ m_error.SetErrorString("Invaild register size");
+ return nullptr;
+ }
+ ValueObjectSP regVal =
+ ValueObjectRegister::Create(m_frame.get(), reg_ctx_sp, reg->kinds[eRegisterKindLLDB]);
+ CompilerType goType = LookupType(m_frame->CalculateTarget(), ConstString(type));
+ if (regVal)
+ {
+ regVal = regVal->Cast(goType);
+ return regVal;
+ }
+ }
+ m_error.SetErrorString("Invaild register name");
+ return nullptr;
+ }
+ VariableListSP var_list_sp(m_frame->GetInScopeVariableList(false));
+ if (var_list_sp)
+ {
+ var_sp = var_list_sp->FindVariable(ConstString(varname));
+ if (var_sp)
+ val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
+ else
+ {
+ // When a variable is on the heap instead of the stack, go records a variable
+ // '&x' instead of 'x'.
+ var_sp = var_list_sp->FindVariable(ConstString("&" + varname));
+ if (var_sp)
+ {
+ val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
+ if (val)
+ val = val->Dereference(m_error);
+ if (m_error.Fail())
+ return nullptr;
+ }
+ }
+ }
+ if (!val)
+ {
+ m_error.Clear();
+ TargetSP target = m_frame->CalculateTarget();
+ if (!target)
+ {
+ m_error.SetErrorString("No target");
+ return nullptr;
+ }
+ var_sp = FindGlobalVariable(target, m_package + "." + e->GetName().m_value);
+ if (var_sp)
+ return m_frame->TrackGlobalVariable(var_sp, m_use_dynamic);
+ }
+ }
+ if (!val)
+ m_error.SetErrorStringWithFormat("Unknown variable %s", e->GetName().m_value.str().c_str());
+ return val;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitStarExpr(const GoASTStarExpr *e)
+{
+ ValueObjectSP target = EvaluateExpr(e->GetX());
+ if (!target)
+ return nullptr;
+ return target->Dereference(m_error);
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitSelectorExpr(const lldb_private::GoASTSelectorExpr *e)
+{
+ ValueObjectSP target = EvaluateExpr(e->GetX());
+ if (target)
+ {
+ if (target->GetCompilerType().IsPointerType())
+ {
+ target = target->Dereference(m_error);
+ if (m_error.Fail())
+ return nullptr;
+ }
+ ConstString field(e->GetSel()->GetName().m_value);
+ ValueObjectSP result = target->GetChildMemberWithName(field, true);
+ if (!result)
+ m_error.SetErrorStringWithFormat("Unknown child %s", field.AsCString());
+ return result;
+ }
+ if (const GoASTIdent *package = llvm::dyn_cast<GoASTIdent>(e->GetX()))
+ {
+ if (VariableSP global = FindGlobalVariable(m_exe_ctx.GetTargetSP(),
+ package->GetName().m_value + "." + e->GetSel()->GetName().m_value))
+ {
+ if (m_frame)
+ {
+ m_error.Clear();
+ return m_frame->GetValueObjectForFrameVariable(global, m_use_dynamic);
+ }
+ }
+ }
+ if (const GoASTBasicLit *packageLit = llvm::dyn_cast<GoASTBasicLit>(e->GetX()))
+ {
+ if (packageLit->GetValue().m_type == GoLexer::LIT_STRING)
+ {
+ std::string value = packageLit->GetValue().m_value.str();
+ value = value.substr(1, value.size() - 2);
+ if (VariableSP global =
+ FindGlobalVariable(m_exe_ctx.GetTargetSP(), value + "." + e->GetSel()->GetName().m_value))
+ {
+ if (m_frame)
+ {
+ m_error.Clear();
+ return m_frame->TrackGlobalVariable(global, m_use_dynamic);
+ }
+ }
+ }
+ }
+ // EvaluateExpr should have already set m_error.
+ return target;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitBasicLit(const lldb_private::GoASTBasicLit *e)
+{
+ std::string value = e->GetValue().m_value.str();
+ if (e->GetValue().m_type != GoLexer::LIT_INTEGER)
+ {
+ m_error.SetErrorStringWithFormat("Unsupported literal %s", value.c_str());
+ return nullptr;
+ }
+ errno = 0;
+ int64_t intvalue = strtol(value.c_str(), nullptr, 0);
+ if (errno != 0)
+ {
+ m_error.SetErrorToErrno();
+ return nullptr;
+ }
+ DataBufferSP buf(new DataBufferHeap(sizeof(intvalue), 0));
+ TargetSP target = m_exe_ctx.GetTargetSP();
+ if (!target)
+ {
+ m_error.SetErrorString("No target");
+ return nullptr;
+ }
+ ByteOrder order = target->GetArchitecture().GetByteOrder();
+ uint8_t addr_size = target->GetArchitecture().GetAddressByteSize();
+ DataEncoder enc(buf, order, addr_size);
+ enc.PutU64(0, static_cast<uint64_t>(intvalue));
+ DataExtractor data(buf, order, addr_size);
+
+ CompilerType type = LookupType(target, ConstString("int64"));
+ return ValueObject::CreateValueObjectFromData(nullptr, data, m_exe_ctx, type);
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitIndexExpr(const lldb_private::GoASTIndexExpr *e)
+{
+ ValueObjectSP target = EvaluateExpr(e->GetX());
+ if (!target)
+ return nullptr;
+ ValueObjectSP index = EvaluateExpr(e->GetIndex());
+ if (!index)
+ return nullptr;
+ bool is_signed;
+ if (!index->GetCompilerType().IsIntegerType(is_signed))
+ {
+ m_error.SetErrorString("Unsupported index");
+ return nullptr;
+ }
+ size_t idx;
+ if (is_signed)
+ idx = index->GetValueAsSigned(0);
+ else
+ idx = index->GetValueAsUnsigned(0);
+ if (GoASTContext::IsGoSlice(target->GetCompilerType()))
+ {
+ target = target->GetStaticValue();
+ ValueObjectSP cap = target->GetChildMemberWithName(ConstString("cap"), true);
+ if (cap)
+ {
+ uint64_t capval = cap->GetValueAsUnsigned(0);
+ if (idx >= capval)
+ {
+ m_error.SetErrorStringWithFormat("Invalid index %" PRIu64 " , cap = %" PRIu64, uint64_t(idx), capval);
+ return nullptr;
+ }
+ }
+ target = target->GetChildMemberWithName(ConstString("array"), true);
+ if (target && m_use_dynamic != eNoDynamicValues)
+ {
+ ValueObjectSP dynamic = target->GetDynamicValue(m_use_dynamic);
+ if (dynamic)
+ target = dynamic;
+ }
+ if (!target)
+ return nullptr;
+ return target->GetSyntheticArrayMember(idx, true);
+ }
+ return target->GetChildAtIndex(idx, true);
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitUnaryExpr(const GoASTUnaryExpr *e)
+{
+ ValueObjectSP x = EvaluateExpr(e->GetX());
+ if (!x)
+ return nullptr;
+ switch (e->GetOp())
+ {
+ case GoLexer::OP_AMP:
+ {
+ CompilerType type = x->GetCompilerType().GetPointerType();
+ uint64_t address = x->GetAddressOf();
+ return ValueObject::CreateValueObjectFromAddress(nullptr, address, m_exe_ctx, type);
+ }
+ case GoLexer::OP_PLUS:
+ return x;
+ default:
+ m_error.SetErrorStringWithFormat("Operator %s not supported",
+ GoLexer::LookupToken(e->GetOp()).str().c_str());
+ return nullptr;
+ }
+}
+
+CompilerType
+GoUserExpression::GoInterpreter::EvaluateType(const GoASTExpr *e)
+{
+ TargetSP target = m_exe_ctx.GetTargetSP();
+ if (auto *id = llvm::dyn_cast<GoASTIdent>(e))
+ {
+ CompilerType result = LookupType(target, ConstString(id->GetName().m_value));
+ if (result.IsValid())
+ return result;
+ std::string fullname = (m_package + "." + id->GetName().m_value).str();
+ result = LookupType(target, ConstString(fullname));
+ if (!result)
+ m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
+ return result;
+ }
+ if (auto *sel = llvm::dyn_cast<GoASTSelectorExpr>(e))
+ {
+ std::string package;
+ if (auto *pkg_node = llvm::dyn_cast<GoASTIdent>(sel->GetX()))
+ {
+ package = pkg_node->GetName().m_value.str();
+ }
+ else if (auto *str_node = llvm::dyn_cast<GoASTBasicLit>(sel->GetX()))
+ {
+ if (str_node->GetValue().m_type == GoLexer::LIT_STRING)
+ {
+ package = str_node->GetValue().m_value.substr(1).str();
+ package.resize(package.length() - 1);
+ }
+ }
+ if (package.empty())
+ {
+ m_error.SetErrorStringWithFormat("Invalid %s in type expression", sel->GetX()->GetKindName());
+ return CompilerType();
+ }
+ std::string fullname = (package + "." + sel->GetSel()->GetName().m_value).str();
+ CompilerType result = LookupType(target, ConstString(fullname));
+ if (!result)
+ m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
+ return result;
+ }
+ if (auto *star = llvm::dyn_cast<GoASTStarExpr>(e))
+ {
+ CompilerType elem = EvaluateType(star->GetX());
+ return elem.GetPointerType();
+ }
+ if (auto *paren = llvm::dyn_cast<GoASTParenExpr>(e))
+ return EvaluateType(paren->GetX());
+ if (auto *array = llvm::dyn_cast<GoASTArrayType>(e))
+ {
+ CompilerType elem = EvaluateType(array->GetElt());
+ }
+
+ m_error.SetErrorStringWithFormat("Invalid %s in type expression", e->GetKindName());
+ return CompilerType();
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitCallExpr(const lldb_private::GoASTCallExpr *e)
+{
+ ValueObjectSP x = EvaluateExpr(e->GetFun());
+ if (x || e->NumArgs() != 1)
+ {
+ m_error.SetErrorStringWithFormat("Code execution not supported");
+ return nullptr;
+ }
+ m_error.Clear();
+ CompilerType type = EvaluateType(e->GetFun());
+ if (!type)
+ {
+ return nullptr;
+ }
+ ValueObjectSP value = EvaluateExpr(e->GetArgs(0));
+ if (!value)
+ return nullptr;
+ // TODO: Handle special conversions
+ return value->Cast(type);
+}
+
+GoPersistentExpressionState::GoPersistentExpressionState() : PersistentExpressionState(eKindGo)
+{
+}
+
+ConstString
+GoPersistentExpressionState::GetNextPersistentVariableName()
+{
+ char name_cstr[256];
+ // We can't use the same variable format as clang.
+ ::snprintf(name_cstr, sizeof(name_cstr), "$go%u", m_next_persistent_variable_id++);
+ ConstString name(name_cstr);
+ return name;
+}
+
+void
+GoPersistentExpressionState::RemovePersistentVariable(lldb::ExpressionVariableSP variable)
+{
+ RemoveVariable(variable);
+
+ const char *name = variable->GetName().AsCString();
+
+ if (*(name++) != '$')
+ return;
+ if (*(name++) != 'g')
+ return;
+ if (*(name++) != 'o')
+ return;
+
+ if (strtoul(name, nullptr, 0) == m_next_persistent_variable_id - 1)
+ m_next_persistent_variable_id--;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.h b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.h
new file mode 100644
index 0000000..b429c68
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.h
@@ -0,0 +1,98 @@
+//===-- GoUserExpression.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoUserExpression_h_
+#define liblldb_GoUserExpression_h_
+
+// C Includes
+// C++ Includes
+#include <memory>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Expression/UserExpression.h"
+#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Target/ExecutionContext.h"
+
+namespace lldb_private
+{
+class GoParser;
+
+class GoPersistentExpressionState : public PersistentExpressionState
+{
+ public:
+ GoPersistentExpressionState();
+
+ ConstString GetNextPersistentVariableName() override;
+
+ void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override;
+
+ lldb::addr_t
+ LookupSymbol(const ConstString &name) override
+ {
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ static bool
+ classof(const PersistentExpressionState *pv)
+ {
+ return pv->getKind() == PersistentExpressionState::eKindGo;
+ }
+
+ private:
+ uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName().
+};
+
+//----------------------------------------------------------------------
+/// @class GoUserExpression GoUserExpression.h "lldb/Expression/GoUserExpression.h"
+/// @brief Encapsulates a single expression for use with Go
+///
+/// LLDB uses expressions for various purposes, notably to call functions
+/// and as a backend for the expr command. GoUserExpression encapsulates
+/// the objects needed to parse and interpret an expression.
+//----------------------------------------------------------------------
+class GoUserExpression : public UserExpression
+{
+ public:
+ GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+ lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options);
+
+ bool
+ Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy,
+ bool keep_result_in_memory, bool generate_debug_info) override;
+
+ lldb::ExpressionResults
+ Execute(Stream &error_stream, ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions &options,
+ lldb::UserExpressionSP &shared_ptr_to_me,
+ lldb::ExpressionVariableSP &result) override;
+
+ bool
+ CanInterpret() override
+ {
+ return true;
+ }
+ bool
+ FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result,
+ lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
+ lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override
+ {
+ return true;
+ }
+
+ private:
+ class GoInterpreter;
+ std::unique_ptr<GoInterpreter> m_interpreter;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_GoUserExpression_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/gen_go_ast.py b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/gen_go_ast.py
new file mode 100644
index 0000000..05b589a
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ExpressionParser/Go/gen_go_ast.py
@@ -0,0 +1,356 @@
+import StringIO
+
+def addNodes():
+ addNode("ArrayType", "Expr", "len", "Expr", "elt", "Expr")
+ addNode("AssignStmt", "Stmt", "lhs", "[]Expr", "rhs", "[]Expr", "define", "bool")
+ addNode("BadDecl", "Decl")
+ addNode("BadExpr", "Expr")
+ addNode("BadStmt", "Stmt")
+ addNode("BasicLit", "Expr", "value", "Token")
+ addNode("BinaryExpr", "Expr", "x", "Expr", "y", "Expr", "op", "TokenType")
+ addNode("BlockStmt", "Stmt", "list", "[]Stmt")
+ addNode("Ident", "Expr", "name", "Token")
+ addNode("BranchStmt", "Stmt", "label", "Ident", "tok", "TokenType")
+ addNode("CallExpr", "Expr", "fun", "Expr", "args", "[]Expr", "ellipsis", "bool")
+ addNode("CaseClause", "Stmt", "list", "[]Expr", "body", "[]Stmt")
+ addNode("ChanType", "Expr", "dir", "ChanDir", "value", "Expr")
+ addNode("CommClause", "Stmt", "comm", "Stmt", "body", "[]Stmt")
+ addNode("CompositeLit", "Expr", "type", "Expr", "elts", "[]Expr")
+ addNode("DeclStmt", "Stmt", "decl", "Decl")
+ addNode("DeferStmt", "Stmt", "call", "CallExpr")
+ addNode("Ellipsis", "Expr", "elt", "Expr")
+ addNode("EmptyStmt", "Stmt")
+ addNode("ExprStmt", "Stmt", "x", "Expr")
+ addNode("Field", "Node", "names", "[]Ident", "type", "Expr", "tag", "BasicLit")
+ addNode("FieldList", "Node", "list", "[]Field")
+ addNode("ForStmt", "Stmt", "init", "Stmt", "cond", "Expr", "post", "Stmt", "body", "BlockStmt")
+ addNode("FuncType", "Expr", "params", "FieldList", "results", "FieldList")
+ addNode("FuncDecl", "Decl", "recv", "FieldList", "name", "Ident", "type", "FuncType", "body", "BlockStmt")
+ addNode("FuncLit", "Expr", "type", "FuncType", "body", "BlockStmt")
+ addNode("GenDecl", "Decl", "tok", "TokenType", "specs", "[]Spec")
+ addNode("GoStmt", "Stmt", "call", "CallExpr")
+ addNode("IfStmt", "Stmt", "init", "Stmt", "cond", "Expr", "body", "BlockStmt", "els", "Stmt")
+ addNode("ImportSpec", "Spec", "name", "Ident", "path", "BasicLit")
+ addNode("IncDecStmt", "Stmt", "x", "Expr", "tok", "TokenType")
+ addNode("IndexExpr", "Expr", "x", "Expr", "index", "Expr")
+ addNode("InterfaceType", "Expr", "methods", "FieldList")
+ addNode("KeyValueExpr", "Expr", "key", "Expr", "value", "Expr")
+ addNode("LabeledStmt", "Stmt", "label", "Ident", "stmt", "Stmt")
+ addNode("MapType", "Expr", "key", "Expr", "value", "Expr")
+ addNode("ParenExpr", "Expr", "x", "Expr")
+ addNode("RangeStmt", "Stmt", "key", "Expr", "value", "Expr", "define", "bool", "x", "Expr", "body", "BlockStmt")
+ addNode("ReturnStmt", "Stmt", "results", "[]Expr")
+ addNode("SelectStmt", "Stmt", "body", "BlockStmt")
+ addNode("SelectorExpr", "Expr", "x", "Expr", "sel", "Ident")
+ addNode("SendStmt", "Stmt", "chan", "Expr", "value", "Expr")
+ addNode("SliceExpr", "Expr", "x", "Expr", "low", "Expr", "high", "Expr", "max", "Expr", "slice3", "bool")
+ addNode("StarExpr", "Expr", "x", "Expr")
+ addNode("StructType", "Expr", "fields", "FieldList")
+ addNode("SwitchStmt", "Stmt", "init", "Stmt", "tag", "Expr", "body", "BlockStmt")
+ addNode("TypeAssertExpr", "Expr", "x", "Expr", "type", "Expr")
+ addNode("TypeSpec", "Spec", "name", "Ident", "type", "Expr")
+ addNode("TypeSwitchStmt", "Stmt", "init", "Stmt", "assign", "Stmt", "body", "BlockStmt")
+ addNode("UnaryExpr", "Expr", "op", "TokenType", "x", "Expr")
+ addNode("ValueSpec", "Spec", "names", "[]Ident", "type", "Expr", "values", "[]Expr")
+ addParent("Decl", "Node")
+ addParent("Expr", "Node")
+ addParent("Spec", "Node")
+ addParent("Stmt", "Node")
+
+
+class Member(object):
+ def __init__(self, name, typename):
+ self.title = name.title()
+ self.sname = name
+ self.mname = 'm_' + name
+ self.is_list = typename.startswith("[]")
+ self.is_value = isValueType(typename)
+ if self.is_value:
+ self.argtype = typename
+ self.mtype = typename
+ elif self.is_list:
+ self.argtype = 'GoAST' + typename[2:]
+ self.mtype = 'std::vector<std::unique_ptr<%s> >' % self.argtype
+ else:
+ self.argtype = 'GoAST' + typename
+ self.mtype = 'std::unique_ptr<%s>' % self.argtype
+ self.mname = self.mname + '_up'
+
+
+kinds = {}
+parentClasses = StringIO.StringIO()
+childClasses = StringIO.StringIO()
+walker = StringIO.StringIO()
+
+def startClass(name, parent, out):
+ out.write("""
+class GoAST%s : public GoAST%s
+{
+ public:
+""" % (name, parent))
+
+def endClass(name, out):
+ out.write("""
+ %(name)s(const %(name)s &) = delete;
+ const %(name)s &operator=(const %(name)s &) = delete;
+};
+""" % {'name': 'GoAST' + name})
+
+def addNode(name, parent, *children):
+ startClass(name, parent, childClasses)
+ l = kinds.setdefault(parent, [])
+ l.append(name)
+ children = createMembers(name, children)
+ addConstructor(name, parent, children)
+ childClasses.write("""
+ const char *
+ GetKindName() const override
+ {
+ return "%(name)s";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == e%(name)s;
+ }
+ """ % {'name':name})
+ addChildren(name, children)
+ endClass(name, childClasses)
+
+def isValueType(typename):
+ if typename[0].islower():
+ return True
+ if typename[0].isupper():
+ return typename.startswith('Token') or typename == 'ChanDir'
+ return False
+
+
+def createMembers(name, children):
+ l = len(children)
+ if (l % 2) != 0:
+ raise Exception("Invalid children for %s: %s" % (name, children))
+ return [Member(children[i], children[i + 1]) for i in xrange(0, l, 2)]
+
+
+def addConstructor(name, parent, children):
+ for c in children:
+ if c.is_list:
+ children = [x for x in children if x.is_value]
+ break
+ childClasses.write(' ')
+ if len(children) == 1:
+ childClasses.write('explicit ')
+ childClasses.write('GoAST%s(' % name)
+ for i in xrange(len(children)):
+ if i > 0:
+ childClasses.write(', ')
+
+ c = children[i]
+ if c.is_value:
+ childClasses.write(c.argtype)
+ childClasses.write(' ')
+ else:
+ childClasses.write('%s *' % c.argtype)
+ childClasses.write(c.sname)
+ childClasses.write(') : GoAST%s(e%s)' % (parent, name))
+ for c in children:
+ childClasses.write(', ')
+ childClasses.write('%(mname)s(%(sname)s)' % c.__dict__)
+ childClasses.write(""" {}
+ ~GoAST%s() override = default;
+""" % name)
+
+
+def addChildren(name, children):
+ if len(children) == 0:
+ return
+ walker.write("""
+ case e%(n)s:
+ {
+ GoAST%(n)s *n = llvm::cast<GoAST%(n)s>(this);
+ (void)n;""" % {'n':name})
+ for c in children:
+ if c.is_list:
+ childClasses.write("""
+ size_t
+ Num%(title)s() const
+ {
+ return %(mname)s.size();
+ }
+ const %(argtype)s *
+ Get%(title)s(int i) const
+ {
+ return %(mname)s[i].get();
+ }
+ void
+ Add%(title)s(%(argtype)s *%(sname)s)
+ {
+ %(mname)s.push_back(std::unique_ptr<%(argtype)s>(%(sname)s));
+ }
+""" % c.__dict__)
+ walker.write("""
+ for (auto& e : n->%s) { v(e.get()); }""" % c.mname)
+ else:
+ const = ''
+ get = ''
+ set = ''
+ t = c.argtype
+ if isValueType(t):
+ set = '%(mname)s = %(sname)s' % c.__dict__
+ t = t + ' '
+ else:
+ t = t + ' *'
+ const = 'const '
+ get = '.get()'
+ set = '%(mname)s.reset(%(sname)s)' % c.__dict__
+ walker.write("""
+ v(n->%s.get());""" % c.mname)
+ childClasses.write("""
+ %(const)s%(type)s
+ Get%(title)s() const
+ {
+ return %(mname)s%(get)s;
+ }
+ void
+ Set%(title)s(%(type)s%(sname)s)
+ {
+ %(set)s;
+ }
+""" % {'const':const, 'title': c.title, 'sname': c.sname, 'get': get, 'set': set, 'type': t, 'mname': c.mname})
+ childClasses.write('\n private:\n friend class GoASTNode;\n')
+ walker.write("""
+ return;
+ }""")
+ for c in children:
+ childClasses.write(' %s %s;\n' %(c.mtype, c.mname))
+
+
+def addParent(name, parent):
+ startClass(name, parent, parentClasses)
+ l = kinds[name]
+ minName = l[0]
+ maxName = l[-1]
+ parentClasses.write(""" template <typename R, typename V> R Visit(V *v) const;
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() >= e%s && n->GetKind() <= e%s;
+ }
+
+ protected:
+ explicit GoAST%s(NodeKind kind) : GoASTNode(kind) { }
+ private:
+""" % (minName, maxName, name))
+ endClass(name, parentClasses)
+
+addNodes()
+
+print """//===-- GoAST.h -------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// DO NOT EDIT.
+// Generated by gen_go_ast.py
+
+#ifndef liblldb_GoAST_h
+#define liblldb_GoAST_h
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "llvm/Support/Casting.h"
+#include "Plugins/ExpressionParser/Go/GoLexer.h"
+
+namespace lldb_private
+{
+
+class GoASTNode
+{
+ public:
+ typedef GoLexer::TokenType TokenType;
+ typedef GoLexer::Token Token;
+ enum ChanDir
+ {
+ eChanBidir,
+ eChanSend,
+ eChanRecv,
+ };
+ enum NodeKind
+ {"""
+for l in kinds.itervalues():
+ for x in l:
+ print " e%s," % x
+print """ };
+
+ virtual ~GoASTNode() = default;
+
+ NodeKind
+ GetKind() const
+ {
+ return m_kind;
+ }
+
+ virtual const char *GetKindName() const = 0;
+
+ template <typename V> void WalkChildren(V &v);
+
+ protected:
+ explicit GoASTNode(NodeKind kind) : m_kind(kind) { }
+
+ private:
+ const NodeKind m_kind;
+
+ GoASTNode(const GoASTNode &) = delete;
+ const GoASTNode &operator=(const GoASTNode &) = delete;
+};
+"""
+
+
+print parentClasses.getvalue()
+print childClasses.getvalue()
+
+for k, l in kinds.iteritems():
+ if k == 'Node':
+ continue
+ print """
+template <typename R, typename V>
+R GoAST%s::Visit(V* v) const
+{
+ switch(GetKind())
+ {""" % k
+ for subtype in l:
+ print """ case e%(n)s:
+ return v->Visit%(n)s(llvm::cast<const GoAST%(n)s>(this));""" % {'n':subtype}
+
+ print """ default:
+ assert(false && "Invalid kind");
+ }
+}"""
+
+print """
+template <typename V>
+void GoASTNode::WalkChildren(V &v)
+{
+ switch (m_kind)
+ {
+"""
+print walker.getvalue()
+print"""
+ case eEmptyStmt:
+ case eBadDecl:
+ case eBadExpr:
+ case eBadStmt:
+ break;
+ }
+}
+
+} // namespace lldb_private
+
+#endif
+"""
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 95ae549..d646d4d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -290,9 +290,8 @@ EmulateInstructionARM::GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t re
uint32_t
EmulateInstructionARM::GetFramePointerRegisterNumber () const
{
- if (m_arch.GetTriple().getEnvironment() == llvm::Triple::Android)
+ if (m_arch.GetTriple().isAndroid())
return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
-
bool is_apple = false;
if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
is_apple = true;
@@ -301,6 +300,8 @@ EmulateInstructionARM::GetFramePointerRegisterNumber () const
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
+ case llvm::Triple::TvOS:
+ case llvm::Triple::WatchOS:
is_apple = true;
break;
default:
@@ -387,9 +388,8 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc
}
#endif
- bool conditional = false;
bool success = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
const uint32_t addr_byte_size = GetAddressByteSize();
const addr_t sp = ReadCoreReg (SP_REG, &success);
@@ -442,10 +442,7 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc
uint32_t i;
EmulateInstruction::Context context;
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterStore;
- else
- context.type = EmulateInstruction::eContextPushRegisterOnStack;
+ context.type = EmulateInstruction::eContextPushRegisterOnStack;
RegisterInfo reg_info;
RegisterInfo sp_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
@@ -511,8 +508,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco
bool success = false;
- bool conditional = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
const uint32_t addr_byte_size = GetAddressByteSize();
const addr_t sp = ReadCoreReg (SP_REG, &success);
@@ -574,10 +570,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco
uint32_t i, data;
EmulateInstruction::Context context;
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterLoad;
- else
- context.type = EmulateInstruction::eContextPopRegisterOffStack;
+ context.type = EmulateInstruction::eContextPopRegisterOffStack;
RegisterInfo sp_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
@@ -586,7 +579,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco
{
if (BitIsSet (registers, i))
{
- context.SetRegisterPlusOffset (sp_reg, addr - sp);
+ context.SetAddress(addr);
data = MemARead(context, addr, 4, 0, &success);
if (!success)
return false;
@@ -900,12 +893,12 @@ EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding
break;
case eEncodingA1:
- // d = UInt(Rd); setflags = (S == Ô1Õ); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
+ // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
Rd = Bits32 (opcode, 15, 12);
setflags = BitIsSet (opcode, 20);
imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
- // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
+ // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
if ((Rd == 15) && setflags)
return EmulateSUBSPcLrEtc (opcode, encoding);
@@ -1971,9 +1964,8 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding
}
#endif
- bool conditional = false;
bool success = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
const uint32_t addr_byte_size = GetAddressByteSize();
const addr_t sp = ReadCoreReg (SP_REG, &success);
@@ -2018,10 +2010,7 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding
addr = sp;
EmulateInstruction::Context context;
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterStore;
- else
- context.type = EmulateInstruction::eContextPushRegisterOnStack;
+ context.type = EmulateInstruction::eContextPushRegisterOnStack;
RegisterInfo sp_reg;
RegisterInfo dwarf_reg;
@@ -2082,8 +2071,7 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en
#endif
bool success = false;
- bool conditional = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
const uint32_t addr_byte_size = GetAddressByteSize();
const addr_t sp = ReadCoreReg (SP_REG, &success);
@@ -2125,10 +2113,8 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en
uint32_t i;
EmulateInstruction::Context context;
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterStore;
- else
- context.type = EmulateInstruction::eContextPushRegisterOnStack;
+ context.type = EmulateInstruction::eContextPushRegisterOnStack;
+
RegisterInfo dwarf_reg;
RegisterInfo sp_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
@@ -2178,8 +2164,7 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc
#endif
bool success = false;
- bool conditional = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
const uint32_t addr_byte_size = GetAddressByteSize();
const addr_t sp = ReadCoreReg (SP_REG, &success);
@@ -2222,17 +2207,15 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc
uint64_t data; // uint64_t to accommodate 64-bit registers.
EmulateInstruction::Context context;
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterLoad;
- else
- context.type = EmulateInstruction::eContextPopRegisterOffStack;
+ context.type = EmulateInstruction::eContextPopRegisterOffStack;
+
RegisterInfo dwarf_reg;
RegisterInfo sp_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
for (i=0; i<regs; ++i)
{
GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
- context.SetRegisterPlusOffset (sp_reg, addr - sp);
+ context.SetAddress(addr);
data = MemARead(context, addr, reg_byte_size, 0, &success);
if (!success)
return false;
@@ -3462,8 +3445,7 @@ EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding enco
#endif
bool success = false;
- bool conditional = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
uint32_t n;
uint32_t registers = 0;
@@ -3536,10 +3518,8 @@ EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding enco
context.SetRegisterPlusOffset (dwarf_reg, offset);
if (wback && (n == 13)) // Pop Instruction
{
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterLoad;
- else
- context.type = EmulateInstruction::eContextPopRegisterOffStack;
+ context.type = EmulateInstruction::eContextPopRegisterOffStack;
+ context.SetAddress(base_address + offset);
}
// R[i] = MemA [address, 4]; address = address + 4;
@@ -4459,7 +4439,7 @@ EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding en
break;
case eEncodingA1:
- // if W == '1' && Rn == '1101Õ && BitCount(register_list) >= 2 then SEE PUSH;
+ // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE PUSH;
if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
{
// See Push
@@ -4801,7 +4781,11 @@ EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding
address = base_address;
EmulateInstruction::Context context;
- context.type = eContextRegisterStore;
+ if (n == 13)
+ context.type = eContextPushRegisterOnStack;
+ else
+ context.type = eContextRegisterStore;
+
RegisterInfo base_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
@@ -4829,8 +4813,12 @@ EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding
// if wback then R[n] = offset_addr;
if (wback)
{
- context.type = eContextRegisterLoad;
+ if (n == 13)
+ context.type = eContextAdjustStackPointer;
+ else
+ context.type = eContextAdjustBaseRegister;
context.SetAddress (offset_addr);
+
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
return false;
}
@@ -9579,7 +9567,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding
if ConditionPassed() then
EncodingSpecificOperations();
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
- (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
+ (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
if d == 15 then // Can only occur for ARM encoding
ALUWritePC(result); // setflags is always FALSE here
else
@@ -9604,7 +9592,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding
switch (encoding)
{
case eEncodingT1:
- // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
+ // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
d = Bits32 (opcode, 11, 8);
m = Bits32 (opcode, 3, 0);
setflags = BitIsSet (opcode, 20);
@@ -9622,12 +9610,12 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding
break;
case eEncodingA1:
- // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
+ // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
d = Bits32 (opcode, 15, 12);
m = Bits32 (opcode, 3, 0);
setflags = BitIsSet (opcode, 20);
- // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
+ // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
if (d == 15 && setflags)
EmulateSUBSPcLrEtc (opcode, encoding);
@@ -9648,7 +9636,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding
if (!success)
return false;
- // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
+ // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
uint32_t sp_val = ReadCoreReg (SP_REG, &success);
if (!success)
return false;
@@ -9679,7 +9667,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod
EncodingSpecificOperations();
shift_n = UInt(R[s]<7:0>);
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
- (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
+ (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
R[d] = result;
if setflags then
APSR.N = result<31>;
@@ -9708,7 +9696,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod
m = Bits32 (opcode, 3, 0);
s = Bits32 (opcode, 11, 8);
- // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type);
+ // setflags = (S == '1'); shift_t = DecodeRegShift(type);
setflags = BitIsSet (opcode, 20);
shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
@@ -9737,7 +9725,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod
if (!success)
return false;
- // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
+ // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
uint32_t Rn = ReadCoreReg (n, &success);
if (!success)
return false;
@@ -9776,7 +9764,7 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e
if ConditionPassed() then
EncodingSpecificOperations();
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
- (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
+ (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
if d == 15 then // Can only occur for ARM encoding
ALUWritePC(result); // setflags is always FALSE here
else
@@ -9839,14 +9827,14 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e
break;
case eEncodingA1:
- // if Rn == Ô1101Õ then SEE SUB (SP minus register);
- // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
+ // if Rn == '1101' then SEE SUB (SP minus register);
+ // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
d = Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
m = Bits32 (opcode, 3, 0);
setflags = BitIsSet (opcode, 20);
- // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
+ // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
if ((d == 15) && setflags)
EmulateSUBSPcLrEtc (opcode, encoding);
@@ -9868,7 +9856,7 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e
if (!success)
return false;
- // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
+ // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
uint32_t Rn = ReadCoreReg (n, &success);
if (!success)
return false;
@@ -9929,7 +9917,7 @@ EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding en
switch (encoding)
{
case eEncodingT1:
- // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
d = Bits32 (opcode, 11, 8);
t = Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
@@ -10037,13 +10025,13 @@ EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncodi
switch (encoding)
{
case eEncodingA1:
- // if P == Ô0Õ && W == Ô1Õ then SEE STRBT;
+ // if P == '0' && W == '1' then SEE STRBT;
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
t = Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 11, 0);
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
@@ -10135,14 +10123,14 @@ EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncodin
switch (encoding)
{
case eEncodingA1:
- // if P == Ô0Õ && W == Ô1Õ then SEE STRT;
- // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH;
+ // if P == '0' && W == '1' then SEE STRT;
+ // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH;
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
t = Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 11, 0);
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
@@ -10247,15 +10235,15 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc
switch (encoding)
{
case eEncodingT1:
- //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- //if Rn == Ô1111Õ then SEE LDRD (literal);
- //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ //if P == '0' && W == '0' then SEE 'Related encodings';
+ //if Rn == '1111' then SEE LDRD (literal);
+ //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
t = Bits32 (opcode, 15, 12);
t2 = Bits32 (opcode, 11, 8);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 7, 0) << 2;
- //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
+ //index = (P == '1'); add = (U == '1'); wback = (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
@@ -10271,8 +10259,8 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc
break;
case eEncodingA1:
- //if Rn == Ô1111Õ then SEE LDRD (literal);
- //if Rt<0> == Ô1Õ then UNPREDICTABLE;
+ //if Rn == '1111' then SEE LDRD (literal);
+ //if Rt<0> == '1' then UNPREDICTABLE;
//t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
t = Bits32 (opcode, 15, 12);
if (BitIsSet (t, 0))
@@ -10281,12 +10269,12 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc
n = Bits32 (opcode, 19, 16);
imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
- //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
- //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
+ //if P == '0' && W == '1' then UNPREDICTABLE;
if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
return false;
@@ -10327,8 +10315,11 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc
GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
EmulateInstruction::Context context;
- context.type = eContextRegisterLoad;
- context.SetRegisterPlusOffset (base_reg, address - Rn);
+ if (n == 13)
+ context.type = eContextPopRegisterOffStack;
+ else
+ context.type = eContextRegisterLoad;
+ context.SetAddress(address);
const uint32_t addr_byte_size = GetAddressByteSize();
uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
@@ -10339,8 +10330,7 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc
return false;
//R[t2] = MemA[address+4,4];
-
- context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
+ context.SetAddress(address + 4);
data = MemARead (context, address + 4, addr_byte_size, 0, &success);
if (!success)
return false;
@@ -10392,7 +10382,7 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco
switch (encoding)
{
case eEncodingA1:
- // if Rt<0> == Ô1Õ then UNPREDICTABLE;
+ // if Rt<0> == '1' then UNPREDICTABLE;
// t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
t = Bits32 (opcode, 15, 12);
if (BitIsSet (t, 0))
@@ -10401,12 +10391,12 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco
n = Bits32 (opcode, 19, 16);
m = Bits32 (opcode, 3, 0);
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
- // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
+ // if P == '0' && W == '1' then UNPREDICTABLE;
if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
return false;
@@ -10454,8 +10444,11 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco
address = Rn;
EmulateInstruction::Context context;
- context.type = eContextRegisterLoad;
- context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
+ if (n == 13)
+ context.type = eContextPopRegisterOffStack;
+ else
+ context.type = eContextRegisterLoad;
+ context.SetAddress(address);
// R[t] = MemA[address,4];
const uint32_t addr_byte_size = GetAddressByteSize();
@@ -10519,14 +10512,14 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding
switch (encoding)
{
case eEncodingT1:
- // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // if P == '0' && W == '0' then SEE 'Related encodings';
+ // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
t = Bits32 (opcode, 15, 12);
t2 = Bits32 (opcode, 11, 8);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 7, 0) << 2;
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
@@ -10542,7 +10535,7 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding
break;
case eEncodingA1:
- // if Rt<0> == Ô1Õ then UNPREDICTABLE;
+ // if Rt<0> == '1' then UNPREDICTABLE;
// t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
t = Bits32 (opcode, 15, 12);
if (BitIsSet (t, 0))
@@ -10552,12 +10545,12 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding
n = Bits32 (opcode, 19, 16);
imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
- // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
+ // if P == '0' && W == '1' then UNPREDICTABLE;
if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
return false;
@@ -10605,7 +10598,10 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding
return false;
EmulateInstruction::Context context;
- context.type = eContextRegisterStore;
+ if (n == 13)
+ context.type = eContextPushRegisterOnStack;
+ else
+ context.type = eContextRegisterStore;
context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
const uint32_t addr_byte_size = GetAddressByteSize();
@@ -10627,9 +10623,12 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding
//if wback then R[n] = offset_addr;
if (wback)
{
- context.type = eContextAdjustBaseRegister;
+ if (n == 13)
+ context.type = eContextAdjustStackPointer;
+ else
+ context.type = eContextAdjustBaseRegister;
context.SetAddress (offset_addr);
-
+
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
return false;
}
@@ -10667,7 +10666,7 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding
switch (encoding)
{
case eEncodingA1:
- // if Rt<0> == Ô1Õ then UNPREDICTABLE;
+ // if Rt<0> == '1' then UNPREDICTABLE;
// t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
t = Bits32 (opcode, 15, 12);
if (BitIsSet (t, 0))
@@ -10677,12 +10676,12 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding
n = Bits32 (opcode, 19, 16);
m = Bits32 (opcode, 3, 0);
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
- // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
+ // if P == '0' && W == '1' then UNPREDICTABLE;
if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
return false;
@@ -10737,7 +10736,11 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding
return false;
EmulateInstruction::Context context;
- context.type = eContextRegisterStore;
+ if (t == 13)
+ context.type = eContextPushRegisterOnStack;
+ else
+ context.type = eContextRegisterStore;
+
GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
@@ -10808,25 +10811,25 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc
{
case eEncodingT1:
case eEncodingA1:
- // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
- // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
- // if P == U && W == Ô1Õ then UNDEFINED;
+ // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
+ // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
+ // if P == '1' && W == '0' then SEE VLDR;
+ // if P == U && W == '1' then UNDEFINED;
if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
return false;
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
- // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
+ // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
single_regs = false;
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
- // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 7, 0) << 2;
- // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ.
+ // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
regs = Bits32 (opcode, 7, 0) / 2;
// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
@@ -10841,22 +10844,22 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc
case eEncodingT2:
case eEncodingA2:
- // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
- // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
- // if P == U && W == Ô1Õ then UNDEFINED;
+ // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
+ // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
+ // if P == '1' && W == '0' then SEE VLDR;
+ // if P == U && W == '1' then UNDEFINED;
if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
return false;
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
- // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
+ // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn);
single_regs = true;
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
n = Bits32 (opcode, 19, 16);
- // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
+ // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
imm32 = Bits32 (opcode, 7, 0) << 2;
regs = Bits32 (opcode, 7, 0);
@@ -11000,25 +11003,25 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc
{
case eEncodingT1:
case eEncodingA1:
- // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
- // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
- // if P == U && W == Ô1Õ then UNDEFINED;
+ // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
+ // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
+ // if P == '1' && W == '0' then SEE VSTR;
+ // if P == U && W == '1' then UNDEFINED;
if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
return false;
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
- // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
+ // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
single_regs = false;
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
- // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 7, 0) << 2;
- // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ.
+ // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
regs = Bits32 (opcode, 7, 0) / 2;
// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
@@ -11033,22 +11036,22 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc
case eEncodingT2:
case eEncodingA2:
- // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
- // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
- // if P == U && W == Ô1Õ then UNDEFINED;
+ // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
+ // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
+ // if P == '1' && W == '0' then SEE VSTR;
+ // if P == U && W == '1' then UNDEFINED;
if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
return false;
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
- // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
+ // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn);
single_regs = true;
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
n = Bits32 (opcode, 19, 16);
- // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
+ // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
imm32 = Bits32 (opcode, 7, 0) << 2;
regs = Bits32 (opcode, 7, 0);
@@ -11193,7 +11196,7 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
{
case eEncodingT1:
case eEncodingA1:
- // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
single_reg = false;
add = BitIsSet (opcode, 23);
imm32 = Bits32 (opcode, 7, 0) << 2;
@@ -11206,7 +11209,7 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
case eEncodingT2:
case eEncodingA2:
- // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
single_reg = true;
add = BitIsSet (opcode, 23);
imm32 = Bits32 (opcode, 7, 0) << 2;
@@ -11322,7 +11325,7 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
{
case eEncodingT1:
case eEncodingA1:
- // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
single_reg = false;
add = BitIsSet (opcode, 23);
imm32 = Bits32 (opcode, 7, 0) << 2;
@@ -11339,7 +11342,7 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
case eEncodingT2:
case eEncodingA2:
- // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
single_reg = true;
add = BitIsSet (opcode, 23);
imm32 = Bits32 (opcode, 7, 0) << 2;
@@ -11461,16 +11464,16 @@ EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding e
case eEncodingA1:
{
// case type of
- // when Ô0111Õ
- // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
- // when Ô1010Õ
- // regs = 2; if align == Ô11Õ then UNDEFINED;
- // when Ô0110Õ
- // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
- // when Ô0010Õ
+ // when '0111'
+ // regs = 1; if align<1> == '1' then UNDEFINED;
+ // when '1010'
+ // regs = 2; if align == '11' then UNDEFINED;
+ // when '0110'
+ // regs = 3; if align<1> == '1' then UNDEFINED;
+ // when '0010'
// regs = 4;
// otherwise
- // SEE ÒRelated encodingsÓ;
+ // SEE 'Related encodings';
uint32_t type = Bits32 (opcode, 11, 8);
uint32_t align = Bits32 (opcode, 5, 4);
if (type == 7) // '0111'
@@ -11499,7 +11502,7 @@ EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding e
else
return false;
- // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
+ // alignment = if align == '00' then 1 else 4 << UInt(align);
if (align == 0)
alignment = 1;
else
@@ -11624,13 +11627,13 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi
{
uint32_t size = Bits32 (opcode, 11, 10);
uint32_t index_align = Bits32 (opcode, 7, 4);
- // if size == Ô11Õ then SEE VLD1 (single element to all lanes);
+ // if size == '11' then SEE VLD1 (single element to all lanes);
if (size == 3)
return EmulateVLD1SingleAll (opcode, encoding);
// case size of
if (size == 0) // when '00'
{
- // if index_align<0> != Ô0Õ then UNDEFINED;
+ // if index_align<0> != '0' then UNDEFINED;
if (BitIsClear (index_align, 0))
return false;
@@ -11640,9 +11643,9 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi
index = Bits32 (index_align, 3, 1);
alignment = 1;
}
- else if (size == 1) // when Ô01Õ
+ else if (size == 1) // when '01'
{
- // if index_align<1> != Ô0Õ then UNDEFINED;
+ // if index_align<1> != '0' then UNDEFINED;
if (BitIsClear (index_align, 1))
return false;
@@ -11651,19 +11654,19 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi
esize = 16;
index = Bits32 (index_align, 3, 2);
- // alignment = if index_align<0> == Ô0Õ then 1 else 2;
+ // alignment = if index_align<0> == '0' then 1 else 2;
if (BitIsClear (index_align, 0))
alignment = 1;
else
alignment = 2;
}
- else if (size == 2) // when Ô10Õ
+ else if (size == 2) // when '10'
{
- // if index_align<2> != Ô0Õ then UNDEFINED;
+ // if index_align<2> != '0' then UNDEFINED;
if (BitIsClear (index_align, 2))
return false;
- // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
+ // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED;
if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
return false;
@@ -11672,7 +11675,7 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi
esize = 32;
index = Bit32 (index_align, 3);
- // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
+ // alignment = if index_align<1:0> == '00' then 1 else 4;
if (Bits32 (index_align, 1, 0) == 0)
alignment = 1;
else
@@ -11806,35 +11809,35 @@ EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding e
uint32_t align = Bits32 (opcode, 5, 4);
// case type of
- if (type == 7) // when Ô0111Õ
+ if (type == 7) // when '0111'
{
- // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
+ // regs = 1; if align<1> == '1' then UNDEFINED;
regs = 1;
if (BitIsSet (align, 1))
return false;
}
- else if (type == 10) // when Ô1010Õ
+ else if (type == 10) // when '1010'
{
- // regs = 2; if align == Ô11Õ then UNDEFINED;
+ // regs = 2; if align == '11' then UNDEFINED;
regs = 2;
if (align == 3)
return false;
}
- else if (type == 6) // when Ô0110Õ
+ else if (type == 6) // when '0110'
{
- // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
+ // regs = 3; if align<1> == '1' then UNDEFINED;
regs = 3;
if (BitIsSet (align, 1))
return false;
}
- else if (type == 2) // when Ô0010Õ
+ else if (type == 2) // when '0010'
// regs = 4;
regs = 4;
else // otherwise
- // SEE ÒRelated encodingsÓ;
+ // SEE 'Related encodings';
return false;
- // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
+ // alignment = if align == '00' then 1 else 4 << UInt(align);
if (align == 0)
alignment = 1;
else
@@ -11964,14 +11967,14 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc
uint32_t size = Bits32 (opcode, 11, 10);
uint32_t index_align = Bits32 (opcode, 7, 4);
- // if size == Ô11Õ then UNDEFINED;
+ // if size == '11' then UNDEFINED;
if (size == 3)
return false;
// case size of
- if (size == 0) // when Ô00Õ
+ if (size == 0) // when '00'
{
- // if index_align<0> != Ô0Õ then UNDEFINED;
+ // if index_align<0> != '0' then UNDEFINED;
if (BitIsClear (index_align, 0))
return false;
// ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
@@ -11980,9 +11983,9 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc
index = Bits32 (index_align, 3, 1);
alignment = 1;
}
- else if (size == 1) // when Ô01Õ
+ else if (size == 1) // when '01'
{
- // if index_align<1> != Ô0Õ then UNDEFINED;
+ // if index_align<1> != '0' then UNDEFINED;
if (BitIsClear (index_align, 1))
return false;
@@ -11991,19 +11994,19 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc
esize = 16;
index = Bits32 (index_align, 3, 2);
- // alignment = if index_align<0> == Ô0Õ then 1 else 2;
+ // alignment = if index_align<0> == '0' then 1 else 2;
if (BitIsClear (index_align, 0))
alignment = 1;
else
alignment = 2;
}
- else if (size == 2) // when Ô10Õ
+ else if (size == 2) // when '10'
{
- // if index_align<2> != Ô0Õ then UNDEFINED;
+ // if index_align<2> != '0' then UNDEFINED;
if (BitIsClear (index_align, 2))
return false;
- // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
+ // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED;
if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
return false;
@@ -12012,7 +12015,7 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc
esize = 32;
index = Bit32 (index_align, 3);
- // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
+ // alignment = if index_align<1:0> == '00' then 1 else 4;
if (Bits32 (index_align, 1, 0) == 0)
alignment = 1;
else
@@ -12125,12 +12128,12 @@ EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEnc
case eEncodingT1:
case eEncodingA1:
{
- //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED;
+ //if size == '11' || (size == '00' && a == '1') then UNDEFINED;
uint32_t size = Bits32 (opcode, 7, 6);
if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
return false;
- //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2;
+ //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0' then 1 else 2;
ebytes = 1 << size;
elements = 8 / ebytes;
if (BitIsClear (opcode, 5))
@@ -12138,7 +12141,7 @@ EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEnc
else
regs = 2;
- //alignment = if a == Ô0Õ then 1 else ebytes;
+ //alignment = if a == '0' then 1 else ebytes;
if (BitIsClear (opcode, 4))
alignment = 1;
else
@@ -12235,19 +12238,19 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod
UNPREDICTABLE;
operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
case opcode of
- when Ô0000Õ result = R[n] AND operand2; // AND
- when Ô0001Õ result = R[n] EOR operand2; // EOR
- when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
- when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
- when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
- when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
- when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
- when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
- when Ô1100Õ result = R[n] OR operand2; // ORR
- when Ô1101Õ result = operand2; // MOV
- when Ô1110Õ result = R[n] AND NOT(operand2); // BIC
- when Ô1111Õ result = NOT(operand2); // MVN
- CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
+ when '0000' result = R[n] AND operand2; // AND
+ when '0001' result = R[n] EOR operand2; // EOR
+ when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
+ when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
+ when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
+ when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
+ when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
+ when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
+ when '1100' result = R[n] OR operand2; // ORR
+ when '1101' result = operand2; // MOV
+ when '1110' result = R[n] AND NOT(operand2); // BIC
+ when '1111' result = NOT(operand2); // MVN
+ CPSRWriteByInstr(SPSR[], '1111', TRUE);
BranchWritePC(result);
#endif
@@ -12267,7 +12270,7 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod
{
case eEncodingT1:
// if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
- // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB
+ // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010'; // = SUB
n = 14;
imm32 = Bits32 (opcode, 7, 0);
register_form = false;
@@ -12329,62 +12332,62 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod
// case opcode of
switch (code)
{
- case 0: // when Ô0000Õ
+ case 0: // when '0000'
// result = R[n] AND operand2; // AND
result.result = Rn & operand2;
break;
- case 1: // when Ô0001Õ
+ case 1: // when '0001'
// result = R[n] EOR operand2; // EOR
result.result = Rn ^ operand2;
break;
- case 2: // when Ô0010Õ
- // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
+ case 2: // when '0010'
+ // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
result = AddWithCarry (Rn, ~(operand2), 1);
break;
- case 3: // when Ô0011Õ
- // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
+ case 3: // when '0011'
+ // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
result = AddWithCarry (~(Rn), operand2, 1);
break;
- case 4: // when Ô0100Õ
- // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
+ case 4: // when '0100'
+ // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
result = AddWithCarry (Rn, operand2, 0);
break;
- case 5: // when Ô0101Õ
+ case 5: // when '0101'
// (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
result = AddWithCarry (Rn, operand2, APSR_C);
break;
- case 6: // when Ô0110Õ
+ case 6: // when '0110'
// (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
result = AddWithCarry (Rn, ~(operand2), APSR_C);
break;
- case 7: // when Ô0111Õ
+ case 7: // when '0111'
// (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
result = AddWithCarry (~(Rn), operand2, APSR_C);
break;
- case 10: // when Ô1100Õ
+ case 10: // when '1100'
// result = R[n] OR operand2; // ORR
result.result = Rn | operand2;
break;
- case 11: // when Ô1101Õ
+ case 11: // when '1101'
// result = operand2; // MOV
result.result = operand2;
break;
- case 12: // when Ô1110Õ
+ case 12: // when '1110'
// result = R[n] AND NOT(operand2); // BIC
result.result = Rn & ~(operand2);
break;
- case 15: // when Ô1111Õ
+ case 15: // when '1111'
// result = NOT(operand2); // MVN
result.result = ~(operand2);
break;
@@ -12392,7 +12395,7 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod
default:
return false;
}
- // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
+ // CPSRWriteByInstr(SPSR[], '1111', TRUE);
// For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
// the best.
@@ -13076,7 +13079,7 @@ EmulateInstructionARM::ArchVersion ()
}
bool
-EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional)
+EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
{
// If we are ignoring conditions, then always return true.
// this allows us to iterate over disassembly code and still
@@ -13084,12 +13087,8 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio
// bits set in the CPSR register...
if (m_ignore_conditions)
return true;
-
- if (is_conditional)
- *is_conditional = true;
const uint32_t cond = CurrentCond (opcode);
-
if (cond == UINT32_MAX)
return false;
@@ -13149,8 +13148,6 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio
case 7:
// Always execute (cond == 0b1110, or the special 0b1111 which gives
// opcodes different meanings, but always means execution happens.
- if (is_conditional)
- *is_conditional = false;
return true;
}
@@ -13643,6 +13640,13 @@ EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
}
bool
+EmulateInstructionARM::IsInstructionConditional()
+{
+ const uint32_t cond = CurrentCond (m_opcode.GetOpcode32());
+ return cond != 0xe && cond != 0xf && cond != UINT32_MAX;
+}
+
+bool
EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
{
if (!test_data)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index d107ca6..893f43f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -94,20 +94,20 @@ public:
return false;
}
- virtual lldb_private::ConstString
- GetPluginName()
+ lldb_private::ConstString
+ GetPluginName() override
{
return GetPluginNameStatic();
}
- virtual uint32_t
- GetPluginVersion()
+ uint32_t
+ GetPluginVersion() override
{
return 1;
}
bool
- SetTargetTriple (const ArchSpec &arch);
+ SetTargetTriple (const ArchSpec &arch) override;
enum Mode
{
@@ -148,8 +148,8 @@ public:
// {
// }
- virtual bool
- SupportsEmulatingInstructionsOfType (InstructionType inst_type)
+ bool
+ SupportsEmulatingInstructionsOfType (InstructionType inst_type) override
{
return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
}
@@ -157,32 +157,32 @@ public:
virtual bool
SetArchitecture (const ArchSpec &arch);
- virtual bool
- ReadInstruction ();
+ bool
+ ReadInstruction () override;
- virtual bool
- SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target);
+ bool
+ SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target) override;
- virtual bool
- EvaluateInstruction (uint32_t evaluate_options);
-
- virtual bool
- TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data);
+ bool
+ EvaluateInstruction (uint32_t evaluate_options) override;
- virtual bool
- GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info);
-
+ bool
+ IsInstructionConditional() override;
- virtual bool
- CreateFunctionEntryUnwind (UnwindPlan &unwind_plan);
+ bool
+ TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) override;
+
+ bool
+ GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info) override;
+
+ bool
+ CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) override;
uint32_t
ArchVersion();
bool
- ConditionPassed (const uint32_t opcode,
- bool *is_conditional = NULL); // Filled in with true if the opcode is a conditional opcode
- // Filled in with false if the opcode is always executed
+ ConditionPassed (const uint32_t opcode);
uint32_t
CurrentCond (const uint32_t opcode);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
index 992df1f..372ccf9 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
@@ -231,58 +231,72 @@ EmulateInstructionARM64::GetOpcodeForInstruction (const uint32_t opcode)
//----------------------------------------------------------------------
// push register(s)
- { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" },
- { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS <Xd>, <Xn|SP>, #<imm> {, <shift>}" },
- { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" },
- { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}" },
-
- { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
- { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
- { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
- { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
-
- { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
-
- { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
-
- { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
-
- { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
-
- { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
-
- { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
-
- { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, "B <label>" },
- { 0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond, "B.<cond> <label>" },
- { 0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBZ <Wt>, <label>" },
- { 0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBNZ <Wt>, <label>" },
- { 0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBZ <R><t>, #<imm>, <label>" },
- { 0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBNZ <R><t>, #<imm>, <label>" },
+ { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUB <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUBS <Xd>, <Xn|SP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}" },
+
+ { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
+
+ { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
+
+ { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
+
+ { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffe00c00, 0xb8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "STR <Wt>, [<Xn|SP>], #<simm>" },
+ { 0xffe00c00, 0xf8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "STR <Xt>, [<Xn|SP>], #<simm>" },
+ { 0xffe00c00, 0xb8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "STR <Wt>, [<Xn|SP>, #<simm>]!" },
+ { 0xffe00c00, 0xf8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "STR <Xt>, [<Xn|SP>, #<simm>]!" },
+ { 0xffc00000, 0xb9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "STR <Wt>, [<Xn|SP>{, #<pimm>}]" },
+ { 0xffc00000, 0xf9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "STR <Xt>, [<Xn|SP>{, #<pimm>}]" },
+
+ { 0xffe00c00, 0xb8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "LDR <Wt>, [<Xn|SP>], #<simm>" },
+ { 0xffe00c00, 0xf8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "LDR <Xt>, [<Xn|SP>], #<simm>" },
+ { 0xffe00c00, 0xb8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "LDR <Wt>, [<Xn|SP>, #<simm>]!" },
+ { 0xffe00c00, 0xf8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "LDR <Xt>, [<Xn|SP>, #<simm>]!" },
+ { 0xffc00000, 0xb9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "LDR <Wt>, [<Xn|SP>{, #<pimm>}]" },
+ { 0xffc00000, 0xf9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "LDR <Xt>, [<Xn|SP>{, #<pimm>}]" },
+
+ { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, "B <label>" },
+ { 0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond, "B.<cond> <label>" },
+ { 0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBZ <Wt>, <label>" },
+ { 0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBNZ <Wt>, <label>" },
+ { 0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBZ <R><t>, #<imm>, <label>" },
+ { 0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBNZ <R><t>, #<imm>, <label>" },
};
static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes);
@@ -391,7 +405,7 @@ EmulateInstructionARM64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
uint32_t
EmulateInstructionARM64::GetFramePointerRegisterNumber () const
{
- if (m_arch.GetTriple().getEnvironment() == llvm::Triple::Android)
+ if (m_arch.GetTriple().isAndroid())
return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
return arm64_dwarf::sp;
@@ -462,7 +476,7 @@ EmulateInstructionARM64::BranchTo (const Context &context, uint32_t N, addr_t ta
}
bool
-EmulateInstructionARM64::ConditionHolds (const uint32_t cond, bool *is_conditional)
+EmulateInstructionARM64::ConditionHolds (const uint32_t cond)
{
// If we are ignoring conditions, then always return true.
// this allows us to iterate over disassembly code and still
@@ -470,10 +484,7 @@ EmulateInstructionARM64::ConditionHolds (const uint32_t cond, bool *is_condition
// bits set in the CPSR register...
if (m_ignore_conditions)
return true;
-
- if (is_conditional)
- *is_conditional = true;
-
+
bool result = false;
switch (UnsignedBits(cond, 3, 1))
{
@@ -499,19 +510,18 @@ EmulateInstructionARM64::ConditionHolds (const uint32_t cond, bool *is_condition
result = (m_opcode_pstate.N == m_opcode_pstate.V && m_opcode_pstate.Z == 0);
break;
case 7:
- result = true;
- if (is_conditional)
- *is_conditional = false;
- break;
+ // Always execute (cond == 0b1110, or the special 0b1111 which gives
+ // opcodes different meanings, but always means execution happens.
+ return true;
}
- if (cond & 1 && cond != 15)
+ if (cond & 1)
result = !result;
return result;
}
bool
-EmulateInstructionARM64::Emulate_addsub_imm (const uint32_t opcode)
+EmulateInstructionARM64::EmulateADDSUBImm (const uint32_t opcode)
{
// integer d = UInt(Rd);
// integer n = UInt(Rn);
@@ -628,26 +638,8 @@ EmulateInstructionARM64::Emulate_addsub_imm (const uint32_t opcode)
return false;
}
-bool
-EmulateInstructionARM64::Emulate_ldstpair_off (const uint32_t opcode)
-{
- return Emulate_ldstpair (opcode, AddrMode_OFF);
-}
-
-bool
-EmulateInstructionARM64::Emulate_ldstpair_pre (const uint32_t opcode)
-{
- return Emulate_ldstpair (opcode, AddrMode_PRE);
-}
-
-bool
-EmulateInstructionARM64::Emulate_ldstpair_post (const uint32_t opcode)
-{
- return Emulate_ldstpair (opcode, AddrMode_POST);
-}
-
-bool
-EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode)
+template <EmulateInstructionARM64::AddrMode a_mode> bool
+EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode)
{
uint32_t opc = Bits32(opcode, 31, 30);
uint32_t V = Bit32(opcode, 26);
@@ -776,10 +768,6 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod
Context context_t;
Context context_t2;
- context_t.type = eContextRegisterPlusOffset;
- context_t2.type = eContextRegisterPlusOffset;
- context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0);
- context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size);
uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
Error error;
@@ -792,6 +780,13 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod
context_t.type = eContextPushRegisterOnStack;
context_t2.type = eContextPushRegisterOnStack;
}
+ else
+ {
+ context_t.type = eContextRegisterStore;
+ context_t2.type = eContextRegisterStore;
+ }
+ context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0);
+ context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size);
if (!ReadRegister (&reg_info_Rt, data_Rt))
return false;
@@ -820,6 +815,13 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod
context_t.type = eContextPopRegisterOffStack;
context_t2.type = eContextPopRegisterOffStack;
}
+ else
+ {
+ context_t.type = eContextRegisterLoad;
+ context_t2.type = eContextRegisterLoad;
+ }
+ context_t.SetAddress(address);
+ context_t2.SetAddress(address + size);
if (rt_unknown)
memset (buffer, 'U', reg_info_Rt.byte_size);
@@ -874,6 +876,132 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod
return true;
}
+template <EmulateInstructionARM64::AddrMode a_mode> bool
+EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode)
+{
+ uint32_t size = Bits32(opcode, 31, 30);
+ uint32_t opc = Bits32(opcode, 23, 22);
+ uint32_t n = Bits32(opcode, 9, 5);
+ uint32_t t = Bits32(opcode, 4, 0);
+
+ bool wback;
+ bool postindex;
+ uint64_t offset;
+
+ switch (a_mode)
+ {
+ case AddrMode_POST:
+ wback = true;
+ postindex = true;
+ offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
+ break;
+ case AddrMode_PRE:
+ wback = true;
+ postindex = false;
+ offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
+ break;
+ case AddrMode_OFF:
+ wback = false;
+ postindex = false;
+ offset = LSL(Bits32(opcode, 21, 10), size);
+ break;
+ }
+
+ MemOp memop;
+
+ if (Bit32(opc, 1) == 0)
+ {
+ memop = Bit32(opc, 0) == 1 ? MemOp_LOAD : MemOp_STORE;
+ }
+ else
+ {
+ memop = MemOp_LOAD;
+ if (size == 2 && Bit32(opc, 0) == 1)
+ return false;
+ }
+
+ Error error;
+ bool success = false;
+ uint64_t address;
+ uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
+ RegisterValue data_Rt;
+
+ if (n == 31)
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::sp, 0, &success);
+ else
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success);
+
+ if (!success)
+ return false;
+
+ if (!postindex)
+ address += offset;
+
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base))
+ return false;
+
+ RegisterInfo reg_info_Rt;
+ if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt))
+ return false;
+
+ Context context;
+ switch (memop)
+ {
+ case MemOp_STORE:
+ if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register
+ context.type = eContextPushRegisterOnStack;
+ else
+ context.type = eContextRegisterStore;
+ context.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, postindex ? 0 : offset);
+
+ if (!ReadRegister (&reg_info_Rt, data_Rt))
+ return false;
+
+ if (data_Rt.GetAsMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!WriteMemory(context, address, buffer, reg_info_Rt.byte_size))
+ return false;
+ break;
+
+ case MemOp_LOAD:
+ if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register
+ context.type = eContextPopRegisterOffStack;
+ else
+ context.type = eContextRegisterLoad;
+ context.SetAddress(address);
+
+ if (!ReadMemory (context, address, buffer, reg_info_Rt.byte_size))
+ return false;
+
+ if (data_Rt.SetFromMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!WriteRegister (context, &reg_info_Rt, data_Rt))
+ return false;
+
+ default:
+ return false;
+ }
+
+ if (wback)
+ {
+ if (postindex)
+ address += offset;
+
+ if (n == 31)
+ context.type = eContextAdjustStackPointer;
+ else
+ context.type = eContextAdjustBaseRegister;
+ context.SetImmediateSigned (offset);
+
+ if (!WriteRegisterUnsigned (context, &reg_info_base, address))
+ return false;
+ }
+ return true;
+}
+
bool
EmulateInstructionARM64::EmulateB (const uint32_t opcode)
{
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
index b74edde..d9333c2 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
@@ -1,4 +1,4 @@
-//===-- EmulateInstructionARM64.h ------------------------------------*- C++ -*-===//
+//===-- EmulateInstructionARM64.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,6 +10,10 @@
#ifndef EmulateInstructionARM64_h_
#define EmulateInstructionARM64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/Error.h"
#include "lldb/Interpreter/OptionValue.h"
@@ -18,6 +22,14 @@
class EmulateInstructionARM64 : public lldb_private::EmulateInstruction
{
public:
+ EmulateInstructionARM64 (const lldb_private::ArchSpec &arch) :
+ EmulateInstruction (arch),
+ m_opcode_pstate (),
+ m_emulated_pstate (),
+ m_ignore_conditions (false)
+ {
+ }
+
static void
Initialize ();
@@ -50,61 +62,46 @@ public:
return false;
}
- virtual lldb_private::ConstString
- GetPluginName();
-
- virtual lldb_private::ConstString
- GetShortPluginName()
- {
- return GetPluginNameStatic();
- }
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion()
+ uint32_t
+ GetPluginVersion() override
{
return 1;
}
bool
- SetTargetTriple (const lldb_private::ArchSpec &arch);
+ SetTargetTriple(const lldb_private::ArchSpec &arch) override;
- EmulateInstructionARM64 (const lldb_private::ArchSpec &arch) :
- EmulateInstruction (arch),
- m_opcode_pstate (),
- m_emulated_pstate (),
- m_ignore_conditions (false)
- {
- }
-
- virtual bool
- SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type)
+ bool
+ SupportsEmulatingInstructionsOfType(lldb_private::InstructionType inst_type) override
{
return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
}
- virtual bool
- ReadInstruction ();
+ bool
+ ReadInstruction() override;
- virtual bool
- EvaluateInstruction (uint32_t evaluate_options);
+ bool
+ EvaluateInstruction(uint32_t evaluate_options) override;
- virtual bool
- TestEmulation (lldb_private::Stream *out_stream,
- lldb_private::ArchSpec &arch,
- lldb_private::OptionValueDictionary *test_data)
+ bool
+ TestEmulation(lldb_private::Stream *out_stream,
+ lldb_private::ArchSpec &arch,
+ lldb_private::OptionValueDictionary *test_data) override
{
return false;
}
- virtual bool
- GetRegisterInfo (lldb::RegisterKind reg_kind,
- uint32_t reg_num,
- lldb_private::RegisterInfo &reg_info);
+ bool
+ GetRegisterInfo(lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ lldb_private::RegisterInfo &reg_info) override;
- virtual bool
- CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override;
-
typedef enum
{
AddrMode_OFF,
@@ -141,7 +138,6 @@ public:
BitwiseOp_NOT,
BitwiseOp_RBIT
} BitwiseOp;
-
typedef enum
{
@@ -252,7 +248,6 @@ public:
} ProcState;
protected:
-
typedef struct
{
uint32_t mask;
@@ -272,25 +267,19 @@ protected:
BranchTo (const Context &context, uint32_t N, lldb::addr_t target);
bool
- ConditionHolds (const uint32_t cond, bool *is_conditional = nullptr);
+ ConditionHolds (const uint32_t cond);
bool
UsingAArch32 ();
bool
- Emulate_addsub_imm (const uint32_t opcode);
-
- bool
- Emulate_ldstpair_off (const uint32_t opcode);
+ EmulateADDSUBImm (const uint32_t opcode);
- bool
- Emulate_ldstpair_pre (const uint32_t opcode);
-
- bool
- Emulate_ldstpair_post (const uint32_t opcode);
+ template <AddrMode a_mode> bool
+ EmulateLDPSTP (const uint32_t opcode);
- bool
- Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode);
+ template <AddrMode a_mode> bool
+ EmulateLDRSTRImm (const uint32_t opcode);
bool
EmulateB (const uint32_t opcode);
@@ -309,4 +298,4 @@ protected:
bool m_ignore_conditions;
};
-#endif // EmulateInstructionARM64_h_
+#endif // EmulateInstructionARM64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
index 66866c7..a71fca7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
@@ -29,6 +29,7 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Target.h"
#include "llvm/ADT/STLExtras.h"
@@ -132,10 +133,6 @@ EmulateInstructionMIPS::EmulateInstructionMIPS (const lldb_private::ArchSpec &ar
features += "+dsp,";
if (arch_flags & ArchSpec::eMIPSAse_dspr2)
features += "+dspr2,";
- if (arch_flags & ArchSpec::eMIPSAse_mips16)
- features += "+mips16,";
- if (arch_flags & ArchSpec::eMIPSAse_micromips)
- features += "+micromips,";
m_reg_info.reset (target->createMCRegInfo (triple.getTriple()));
assert (m_reg_info.get());
@@ -152,6 +149,21 @@ EmulateInstructionMIPS::EmulateInstructionMIPS (const lldb_private::ArchSpec &ar
m_disasm.reset (target->createMCDisassembler (*m_subtype_info, *m_context));
assert (m_disasm.get());
+
+ /* Create alternate disassembler for microMIPS */
+ if (arch_flags & ArchSpec::eMIPSAse_mips16)
+ features += "+mips16,";
+ else if (arch_flags & ArchSpec::eMIPSAse_micromips)
+ features += "+micromips,";
+
+ m_alt_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, features));
+ assert (m_alt_subtype_info.get());
+
+ m_alt_disasm.reset (target->createMCDisassembler (*m_alt_subtype_info, *m_context));
+ assert (m_alt_disasm.get());
+
+ m_next_inst_size = 0;
+ m_use_alt_disaasm = false;
}
void
@@ -221,41 +233,76 @@ EmulateInstructionMIPS::GetRegisterName (unsigned reg_num, bool alternate_name)
{
switch (reg_num)
{
- case gcc_dwarf_sp_mips: return "r29";
- case gcc_dwarf_r30_mips: return "r30";
- case gcc_dwarf_ra_mips: return "r31";
- case gcc_dwarf_f0_mips: return "f0";
- case gcc_dwarf_f1_mips: return "f1";
- case gcc_dwarf_f2_mips: return "f2";
- case gcc_dwarf_f3_mips: return "f3";
- case gcc_dwarf_f4_mips: return "f4";
- case gcc_dwarf_f5_mips: return "f5";
- case gcc_dwarf_f6_mips: return "f6";
- case gcc_dwarf_f7_mips: return "f7";
- case gcc_dwarf_f8_mips: return "f8";
- case gcc_dwarf_f9_mips: return "f9";
- case gcc_dwarf_f10_mips: return "f10";
- case gcc_dwarf_f11_mips: return "f11";
- case gcc_dwarf_f12_mips: return "f12";
- case gcc_dwarf_f13_mips: return "f13";
- case gcc_dwarf_f14_mips: return "f14";
- case gcc_dwarf_f15_mips: return "f15";
- case gcc_dwarf_f16_mips: return "f16";
- case gcc_dwarf_f17_mips: return "f17";
- case gcc_dwarf_f18_mips: return "f18";
- case gcc_dwarf_f19_mips: return "f19";
- case gcc_dwarf_f20_mips: return "f20";
- case gcc_dwarf_f21_mips: return "f21";
- case gcc_dwarf_f22_mips: return "f22";
- case gcc_dwarf_f23_mips: return "f23";
- case gcc_dwarf_f24_mips: return "f24";
- case gcc_dwarf_f25_mips: return "f25";
- case gcc_dwarf_f26_mips: return "f26";
- case gcc_dwarf_f27_mips: return "f27";
- case gcc_dwarf_f28_mips: return "f28";
- case gcc_dwarf_f29_mips: return "f29";
- case gcc_dwarf_f30_mips: return "f30";
- case gcc_dwarf_f31_mips: return "f31";
+ case dwarf_sp_mips: return "r29";
+ case dwarf_r30_mips: return "r30";
+ case dwarf_ra_mips: return "r31";
+ case dwarf_f0_mips: return "f0";
+ case dwarf_f1_mips: return "f1";
+ case dwarf_f2_mips: return "f2";
+ case dwarf_f3_mips: return "f3";
+ case dwarf_f4_mips: return "f4";
+ case dwarf_f5_mips: return "f5";
+ case dwarf_f6_mips: return "f6";
+ case dwarf_f7_mips: return "f7";
+ case dwarf_f8_mips: return "f8";
+ case dwarf_f9_mips: return "f9";
+ case dwarf_f10_mips: return "f10";
+ case dwarf_f11_mips: return "f11";
+ case dwarf_f12_mips: return "f12";
+ case dwarf_f13_mips: return "f13";
+ case dwarf_f14_mips: return "f14";
+ case dwarf_f15_mips: return "f15";
+ case dwarf_f16_mips: return "f16";
+ case dwarf_f17_mips: return "f17";
+ case dwarf_f18_mips: return "f18";
+ case dwarf_f19_mips: return "f19";
+ case dwarf_f20_mips: return "f20";
+ case dwarf_f21_mips: return "f21";
+ case dwarf_f22_mips: return "f22";
+ case dwarf_f23_mips: return "f23";
+ case dwarf_f24_mips: return "f24";
+ case dwarf_f25_mips: return "f25";
+ case dwarf_f26_mips: return "f26";
+ case dwarf_f27_mips: return "f27";
+ case dwarf_f28_mips: return "f28";
+ case dwarf_f29_mips: return "f29";
+ case dwarf_f30_mips: return "f30";
+ case dwarf_f31_mips: return "f31";
+ case dwarf_w0_mips: return "w0";
+ case dwarf_w1_mips: return "w1";
+ case dwarf_w2_mips: return "w2";
+ case dwarf_w3_mips: return "w3";
+ case dwarf_w4_mips: return "w4";
+ case dwarf_w5_mips: return "w5";
+ case dwarf_w6_mips: return "w6";
+ case dwarf_w7_mips: return "w7";
+ case dwarf_w8_mips: return "w8";
+ case dwarf_w9_mips: return "w9";
+ case dwarf_w10_mips: return "w10";
+ case dwarf_w11_mips: return "w11";
+ case dwarf_w12_mips: return "w12";
+ case dwarf_w13_mips: return "w13";
+ case dwarf_w14_mips: return "w14";
+ case dwarf_w15_mips: return "w15";
+ case dwarf_w16_mips: return "w16";
+ case dwarf_w17_mips: return "w17";
+ case dwarf_w18_mips: return "w18";
+ case dwarf_w19_mips: return "w19";
+ case dwarf_w20_mips: return "w20";
+ case dwarf_w21_mips: return "w21";
+ case dwarf_w22_mips: return "w22";
+ case dwarf_w23_mips: return "w23";
+ case dwarf_w24_mips: return "w24";
+ case dwarf_w25_mips: return "w25";
+ case dwarf_w26_mips: return "w26";
+ case dwarf_w27_mips: return "w27";
+ case dwarf_w28_mips: return "w28";
+ case dwarf_w29_mips: return "w29";
+ case dwarf_w30_mips: return "w30";
+ case dwarf_w31_mips: return "w31";
+ case dwarf_mir_mips: return "mir";
+ case dwarf_mcsr_mips: return "mcsr";
+ case dwarf_config5_mips: return "config5";
default:
break;
}
@@ -264,78 +311,113 @@ EmulateInstructionMIPS::GetRegisterName (unsigned reg_num, bool alternate_name)
switch (reg_num)
{
- case gcc_dwarf_zero_mips: return "r0";
- case gcc_dwarf_r1_mips: return "r1";
- case gcc_dwarf_r2_mips: return "r2";
- case gcc_dwarf_r3_mips: return "r3";
- case gcc_dwarf_r4_mips: return "r4";
- case gcc_dwarf_r5_mips: return "r5";
- case gcc_dwarf_r6_mips: return "r6";
- case gcc_dwarf_r7_mips: return "r7";
- case gcc_dwarf_r8_mips: return "r8";
- case gcc_dwarf_r9_mips: return "r9";
- case gcc_dwarf_r10_mips: return "r10";
- case gcc_dwarf_r11_mips: return "r11";
- case gcc_dwarf_r12_mips: return "r12";
- case gcc_dwarf_r13_mips: return "r13";
- case gcc_dwarf_r14_mips: return "r14";
- case gcc_dwarf_r15_mips: return "r15";
- case gcc_dwarf_r16_mips: return "r16";
- case gcc_dwarf_r17_mips: return "r17";
- case gcc_dwarf_r18_mips: return "r18";
- case gcc_dwarf_r19_mips: return "r19";
- case gcc_dwarf_r20_mips: return "r20";
- case gcc_dwarf_r21_mips: return "r21";
- case gcc_dwarf_r22_mips: return "r22";
- case gcc_dwarf_r23_mips: return "r23";
- case gcc_dwarf_r24_mips: return "r24";
- case gcc_dwarf_r25_mips: return "r25";
- case gcc_dwarf_r26_mips: return "r26";
- case gcc_dwarf_r27_mips: return "r27";
- case gcc_dwarf_gp_mips: return "gp";
- case gcc_dwarf_sp_mips: return "sp";
- case gcc_dwarf_r30_mips: return "fp";
- case gcc_dwarf_ra_mips: return "ra";
- case gcc_dwarf_sr_mips: return "sr";
- case gcc_dwarf_lo_mips: return "lo";
- case gcc_dwarf_hi_mips: return "hi";
- case gcc_dwarf_bad_mips: return "bad";
- case gcc_dwarf_cause_mips: return "cause";
- case gcc_dwarf_pc_mips: return "pc";
- case gcc_dwarf_f0_mips: return "f0";
- case gcc_dwarf_f1_mips: return "f1";
- case gcc_dwarf_f2_mips: return "f2";
- case gcc_dwarf_f3_mips: return "f3";
- case gcc_dwarf_f4_mips: return "f4";
- case gcc_dwarf_f5_mips: return "f5";
- case gcc_dwarf_f6_mips: return "f6";
- case gcc_dwarf_f7_mips: return "f7";
- case gcc_dwarf_f8_mips: return "f8";
- case gcc_dwarf_f9_mips: return "f9";
- case gcc_dwarf_f10_mips: return "f10";
- case gcc_dwarf_f11_mips: return "f11";
- case gcc_dwarf_f12_mips: return "f12";
- case gcc_dwarf_f13_mips: return "f13";
- case gcc_dwarf_f14_mips: return "f14";
- case gcc_dwarf_f15_mips: return "f15";
- case gcc_dwarf_f16_mips: return "f16";
- case gcc_dwarf_f17_mips: return "f17";
- case gcc_dwarf_f18_mips: return "f18";
- case gcc_dwarf_f19_mips: return "f19";
- case gcc_dwarf_f20_mips: return "f20";
- case gcc_dwarf_f21_mips: return "f21";
- case gcc_dwarf_f22_mips: return "f22";
- case gcc_dwarf_f23_mips: return "f23";
- case gcc_dwarf_f24_mips: return "f24";
- case gcc_dwarf_f25_mips: return "f25";
- case gcc_dwarf_f26_mips: return "f26";
- case gcc_dwarf_f27_mips: return "f27";
- case gcc_dwarf_f28_mips: return "f28";
- case gcc_dwarf_f29_mips: return "f29";
- case gcc_dwarf_f30_mips: return "f30";
- case gcc_dwarf_f31_mips: return "f31";
- case gcc_dwarf_fcsr_mips: return "fcsr";
- case gcc_dwarf_fir_mips: return "fir";
+ case dwarf_zero_mips: return "r0";
+ case dwarf_r1_mips: return "r1";
+ case dwarf_r2_mips: return "r2";
+ case dwarf_r3_mips: return "r3";
+ case dwarf_r4_mips: return "r4";
+ case dwarf_r5_mips: return "r5";
+ case dwarf_r6_mips: return "r6";
+ case dwarf_r7_mips: return "r7";
+ case dwarf_r8_mips: return "r8";
+ case dwarf_r9_mips: return "r9";
+ case dwarf_r10_mips: return "r10";
+ case dwarf_r11_mips: return "r11";
+ case dwarf_r12_mips: return "r12";
+ case dwarf_r13_mips: return "r13";
+ case dwarf_r14_mips: return "r14";
+ case dwarf_r15_mips: return "r15";
+ case dwarf_r16_mips: return "r16";
+ case dwarf_r17_mips: return "r17";
+ case dwarf_r18_mips: return "r18";
+ case dwarf_r19_mips: return "r19";
+ case dwarf_r20_mips: return "r20";
+ case dwarf_r21_mips: return "r21";
+ case dwarf_r22_mips: return "r22";
+ case dwarf_r23_mips: return "r23";
+ case dwarf_r24_mips: return "r24";
+ case dwarf_r25_mips: return "r25";
+ case dwarf_r26_mips: return "r26";
+ case dwarf_r27_mips: return "r27";
+ case dwarf_gp_mips: return "gp";
+ case dwarf_sp_mips: return "sp";
+ case dwarf_r30_mips: return "fp";
+ case dwarf_ra_mips: return "ra";
+ case dwarf_sr_mips: return "sr";
+ case dwarf_lo_mips: return "lo";
+ case dwarf_hi_mips: return "hi";
+ case dwarf_bad_mips: return "bad";
+ case dwarf_cause_mips: return "cause";
+ case dwarf_pc_mips: return "pc";
+ case dwarf_f0_mips: return "f0";
+ case dwarf_f1_mips: return "f1";
+ case dwarf_f2_mips: return "f2";
+ case dwarf_f3_mips: return "f3";
+ case dwarf_f4_mips: return "f4";
+ case dwarf_f5_mips: return "f5";
+ case dwarf_f6_mips: return "f6";
+ case dwarf_f7_mips: return "f7";
+ case dwarf_f8_mips: return "f8";
+ case dwarf_f9_mips: return "f9";
+ case dwarf_f10_mips: return "f10";
+ case dwarf_f11_mips: return "f11";
+ case dwarf_f12_mips: return "f12";
+ case dwarf_f13_mips: return "f13";
+ case dwarf_f14_mips: return "f14";
+ case dwarf_f15_mips: return "f15";
+ case dwarf_f16_mips: return "f16";
+ case dwarf_f17_mips: return "f17";
+ case dwarf_f18_mips: return "f18";
+ case dwarf_f19_mips: return "f19";
+ case dwarf_f20_mips: return "f20";
+ case dwarf_f21_mips: return "f21";
+ case dwarf_f22_mips: return "f22";
+ case dwarf_f23_mips: return "f23";
+ case dwarf_f24_mips: return "f24";
+ case dwarf_f25_mips: return "f25";
+ case dwarf_f26_mips: return "f26";
+ case dwarf_f27_mips: return "f27";
+ case dwarf_f28_mips: return "f28";
+ case dwarf_f29_mips: return "f29";
+ case dwarf_f30_mips: return "f30";
+ case dwarf_f31_mips: return "f31";
+ case dwarf_fcsr_mips: return "fcsr";
+ case dwarf_fir_mips: return "fir";
+ case dwarf_w0_mips: return "w0";
+ case dwarf_w1_mips: return "w1";
+ case dwarf_w2_mips: return "w2";
+ case dwarf_w3_mips: return "w3";
+ case dwarf_w4_mips: return "w4";
+ case dwarf_w5_mips: return "w5";
+ case dwarf_w6_mips: return "w6";
+ case dwarf_w7_mips: return "w7";
+ case dwarf_w8_mips: return "w8";
+ case dwarf_w9_mips: return "w9";
+ case dwarf_w10_mips: return "w10";
+ case dwarf_w11_mips: return "w11";
+ case dwarf_w12_mips: return "w12";
+ case dwarf_w13_mips: return "w13";
+ case dwarf_w14_mips: return "w14";
+ case dwarf_w15_mips: return "w15";
+ case dwarf_w16_mips: return "w16";
+ case dwarf_w17_mips: return "w17";
+ case dwarf_w18_mips: return "w18";
+ case dwarf_w19_mips: return "w19";
+ case dwarf_w20_mips: return "w20";
+ case dwarf_w21_mips: return "w21";
+ case dwarf_w22_mips: return "w22";
+ case dwarf_w23_mips: return "w23";
+ case dwarf_w24_mips: return "w24";
+ case dwarf_w25_mips: return "w25";
+ case dwarf_w26_mips: return "w26";
+ case dwarf_w27_mips: return "w27";
+ case dwarf_w28_mips: return "w28";
+ case dwarf_w29_mips: return "w29";
+ case dwarf_w30_mips: return "w30";
+ case dwarf_w31_mips: return "w31";
+ case dwarf_mcsr_mips: return "mcsr";
+ case dwarf_mir_mips: return "mir";
+ case dwarf_config5_mips: return "config5";
}
return nullptr;
}
@@ -347,11 +429,11 @@ EmulateInstructionMIPS::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num
{
switch (reg_num)
{
- case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_pc_mips; break;
- case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sp_mips; break;
- case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_r30_mips; break;
- case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_ra_mips; break;
- case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sr_mips; break;
+ case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc_mips; break;
+ case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp_mips; break;
+ case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r30_mips; break;
+ case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_ra_mips; break;
+ case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sr_mips; break;
default:
return false;
}
@@ -362,18 +444,24 @@ EmulateInstructionMIPS::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num
::memset (&reg_info, 0, sizeof(RegisterInfo));
::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
- if (reg_num == gcc_dwarf_sr_mips || reg_num == gcc_dwarf_fcsr_mips || reg_num == gcc_dwarf_fir_mips)
+ if (reg_num == dwarf_sr_mips || reg_num == dwarf_fcsr_mips || reg_num == dwarf_fir_mips || reg_num == dwarf_mcsr_mips || reg_num == dwarf_mir_mips || reg_num == dwarf_config5_mips)
{
reg_info.byte_size = 4;
reg_info.format = eFormatHex;
reg_info.encoding = eEncodingUint;
}
- else if ((int)reg_num >= gcc_dwarf_zero_mips && (int)reg_num <= gcc_dwarf_f31_mips)
+ else if ((int)reg_num >= dwarf_zero_mips && (int)reg_num <= dwarf_f31_mips)
{
reg_info.byte_size = 4;
reg_info.format = eFormatHex;
reg_info.encoding = eEncodingUint;
}
+ else if ((int)reg_num >= dwarf_w0_mips && (int)reg_num <= dwarf_w31_mips)
+ {
+ reg_info.byte_size = 16;
+ reg_info.format = eFormatVectorOfUInt8;
+ reg_info.encoding = eEncodingVector;
+ }
else
{
return false;
@@ -385,11 +473,11 @@ EmulateInstructionMIPS::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num
switch (reg_num)
{
- case gcc_dwarf_r30_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
- case gcc_dwarf_ra_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
- case gcc_dwarf_sp_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
- case gcc_dwarf_pc_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
- case gcc_dwarf_sr_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;
+ case dwarf_r30_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
+ case dwarf_ra_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
+ case dwarf_sp_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
+ case dwarf_pc_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
+ case dwarf_sr_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;
default: break;
}
return true;
@@ -409,49 +497,139 @@ EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name)
{ "ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu, "ADDIU rt,rs,immediate" },
{ "SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt,offset(rs)" },
{ "LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt,offset(base)" },
+ //----------------------------------------------------------------------
+ // MicroMIPS Prologue/Epilogue instructions
+ //----------------------------------------------------------------------
+ { "ADDIUSP_MM", &EmulateInstructionMIPS::Emulate_ADDIUSP, "ADDIU immediate" },
+ { "ADDIUS5_MM", &EmulateInstructionMIPS::Emulate_ADDIUS5, "ADDIUS5 rd,immediate" },
+ { "SWSP_MM", &EmulateInstructionMIPS::Emulate_SWSP, "SWSP rt,offset(sp)" },
+ { "SWM16_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, "SWM16 reglist,offset(sp)" },
+ { "SWM32_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, "SWM32 reglist,offset(base)" },
+ { "SWP_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, "SWP rs1,offset(base)" },
+ { "LWSP_MM", &EmulateInstructionMIPS::Emulate_LWSP, "LWSP rt,offset(sp)" },
+ { "LWM16_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, "LWM16 reglist,offset(sp)" },
+ { "LWM32_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, "LWM32 reglist,offset(base)" },
+ { "LWP_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, "LWP rd,offset(base)" },
+ { "JRADDIUSP", &EmulateInstructionMIPS::Emulate_JRADDIUSP, "JRADDIUSP immediate" },
+ //----------------------------------------------------------------------
+
+ // Load/Store instructions
+ //----------------------------------------------------------------------
+ /* Following list of emulated instructions are required by implementation of hardware watchpoint
+ for MIPS in lldb. As we just need the address accessed by instructions, we have generalised
+ all these instructions in 2 functions depending on their addressing modes */
+
+ { "LB", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LB rt, offset(base)" },
+ { "LBE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBE rt, offset(base)" },
+ { "LBU", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBU rt, offset(base)" },
+ { "LBUE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBUE rt, offset(base)" },
+ { "LDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDC1 ft, offset(base)" },
+ { "LD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LD rt, offset(base)" },
+ { "LDL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDL rt, offset(base)" },
+ { "LDR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDR rt, offset(base)" },
+ { "LLD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLD rt, offset(base)" },
+ { "LDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDC2 rt, offset(base)" },
+ { "LDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "LDXC1 fd, index (base)" },
+ { "LH", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LH rt, offset(base)" },
+ { "LHE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHE rt, offset(base)" },
+ { "LHU", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHU rt, offset(base)" },
+ { "LHUE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHUE rt, offset(base)" },
+ { "LL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LL rt, offset(base)" },
+ { "LLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLE rt, offset(base)" },
+ { "LUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "LUXC1 fd, index (base)" },
+ { "LW", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LW rt, offset(base)" },
+ { "LWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWC1 ft, offset(base)" },
+ { "LWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWC2 rt, offset(base)" },
+ { "LWE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWE rt, offset(base)" },
+ { "LWL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWL rt, offset(base)" },
+ { "LWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWLE rt, offset(base)" },
+ { "LWR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWR rt, offset(base)" },
+ { "LWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWRE rt, offset(base)" },
+ { "LWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "LWXC1 fd, index (base)" },
+ { "LLX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLX rt, offset(base)" },
+ { "LLXE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLXE rt, offset(base)" },
+ { "LLDX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLDX rt, offset(base)" },
+
+ { "SB", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SB rt, offset(base)" },
+ { "SBE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SBE rt, offset(base)" },
+ { "SC", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SC rt, offset(base)" },
+ { "SCE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCE rt, offset(base)" },
+ { "SCD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCD rt, offset(base)" },
+ { "SD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SD rt, offset(base)" },
+ { "SDL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDL rt, offset(base)" },
+ { "SDR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDR rt, offset(base)" },
+ { "SDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDC1 ft, offset(base)" },
+ { "SDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDC2 rt, offset(base)" },
+ { "SDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "SDXC1 fs, index(base)" },
+ { "SH", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SH rt, offset(base)" },
+ { "SHE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SHE rt, offset(base)" },
+ { "SUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "SUXC1 fs, index (base)" },
+ { "SWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWC1 ft, offset(base)" },
+ { "SWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWC2 rt, offset(base)" },
+ { "SWE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWE rt, offset(base)" },
+ { "SWL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWL rt, offset(base)" },
+ { "SWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWLE rt, offset(base)" },
+ { "SWR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWR rt, offset(base)" },
+ { "SWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWRE rt, offset(base)" },
+ { "SWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "SWXC1 fs, index (base)" },
+ { "SCX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCX rt, offset(base)" },
+ { "SCXE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCXE rt, offset(base)" },
+ { "SCDX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCDX rt, offset(base)" },
+
+ //----------------------------------------------------------------------
+ // MicroMIPS Load/Store instructions
+ //----------------------------------------------------------------------
+ { "LBU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBU16 rt, decoded_offset(base)" },
+ { "LHU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHU16 rt, left_shifted_offset(base)" },
+ { "LW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LW16 rt, left_shifted_offset(base)" },
+ { "LWGP_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWGP rt, left_shifted_offset(gp)" },
+ { "SH16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SH16 rt, left_shifted_offset(base)" },
+ { "SW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SW16 rt, left_shifted_offset(base)" },
+ { "SW_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWSP rt, left_shifted_offset(base)" },
+ { "SB16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SB16 rt, offset(base)" },
//----------------------------------------------------------------------
// Branch instructions
//----------------------------------------------------------------------
- { "BEQ", &EmulateInstructionMIPS::Emulate_BEQ, "BEQ rs,rt,offset" },
- { "BNE", &EmulateInstructionMIPS::Emulate_BNE, "BNE rs,rt,offset" },
- { "BEQL", &EmulateInstructionMIPS::Emulate_BEQL, "BEQL rs,rt,offset" },
- { "BNEL", &EmulateInstructionMIPS::Emulate_BNEL, "BNEL rs,rt,offset" },
- { "BGEZALL", &EmulateInstructionMIPS::Emulate_BGEZALL, "BGEZALL rt,offset" },
+ { "BEQ", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQ rs,rt,offset" },
+ { "BNE", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNE rs,rt,offset" },
+ { "BEQL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQL rs,rt,offset" },
+ { "BNEL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNEL rs,rt,offset" },
+ { "BGEZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "BGEZALL rt,offset" },
{ "BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset" },
- { "BGEZAL", &EmulateInstructionMIPS::Emulate_BGEZAL, "BGEZAL rs,offset" },
+ { "BGEZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "BGEZAL rs,offset" },
{ "BALC", &EmulateInstructionMIPS::Emulate_BALC, "BALC offset" },
{ "BC", &EmulateInstructionMIPS::Emulate_BC, "BC offset" },
- { "BGEZ", &EmulateInstructionMIPS::Emulate_BGEZ, "BGEZ rs,offset" },
- { "BLEZALC", &EmulateInstructionMIPS::Emulate_BLEZALC, "BLEZALC rs,offset" },
- { "BGEZALC", &EmulateInstructionMIPS::Emulate_BGEZALC, "BGEZALC rs,offset" },
- { "BLTZALC", &EmulateInstructionMIPS::Emulate_BLTZALC, "BLTZALC rs,offset" },
- { "BGTZALC", &EmulateInstructionMIPS::Emulate_BGTZALC, "BGTZALC rs,offset" },
- { "BEQZALC", &EmulateInstructionMIPS::Emulate_BEQZALC, "BEQZALC rs,offset" },
- { "BNEZALC", &EmulateInstructionMIPS::Emulate_BNEZALC, "BNEZALC rs,offset" },
- { "BEQC", &EmulateInstructionMIPS::Emulate_BEQC, "BEQC rs,rt,offset" },
- { "BNEC", &EmulateInstructionMIPS::Emulate_BNEC, "BNEC rs,rt,offset" },
- { "BLTC", &EmulateInstructionMIPS::Emulate_BLTC, "BLTC rs,rt,offset" },
- { "BGEC", &EmulateInstructionMIPS::Emulate_BGEC, "BGEC rs,rt,offset" },
- { "BLTUC", &EmulateInstructionMIPS::Emulate_BLTUC, "BLTUC rs,rt,offset" },
- { "BGEUC", &EmulateInstructionMIPS::Emulate_BGEUC, "BGEUC rs,rt,offset" },
- { "BLTZC", &EmulateInstructionMIPS::Emulate_BLTZC, "BLTZC rt,offset" },
- { "BLEZC", &EmulateInstructionMIPS::Emulate_BLEZC, "BLEZC rt,offset" },
- { "BGEZC", &EmulateInstructionMIPS::Emulate_BGEZC, "BGEZC rt,offset" },
- { "BGTZC", &EmulateInstructionMIPS::Emulate_BGTZC, "BGTZC rt,offset" },
- { "BEQZC", &EmulateInstructionMIPS::Emulate_BEQZC, "BEQZC rt,offset" },
- { "BNEZC", &EmulateInstructionMIPS::Emulate_BNEZC, "BNEZC rt,offset" },
- { "BGEZL", &EmulateInstructionMIPS::Emulate_BGEZL, "BGEZL rt,offset" },
- { "BGTZ", &EmulateInstructionMIPS::Emulate_BGTZ, "BGTZ rt,offset" },
- { "BGTZL", &EmulateInstructionMIPS::Emulate_BGTZL, "BGTZL rt,offset" },
- { "BLEZ", &EmulateInstructionMIPS::Emulate_BLEZ, "BLEZ rt,offset" },
- { "BLEZL", &EmulateInstructionMIPS::Emulate_BLEZL, "BLEZL rt,offset" },
- { "BLTZ", &EmulateInstructionMIPS::Emulate_BLTZ, "BLTZ rt,offset" },
- { "BLTZAL", &EmulateInstructionMIPS::Emulate_BLTZAL, "BLTZAL rt,offset" },
- { "BLTZALL", &EmulateInstructionMIPS::Emulate_BLTZALL, "BLTZALL rt,offset" },
- { "BLTZL", &EmulateInstructionMIPS::Emulate_BLTZL, "BLTZL rt,offset" },
- { "BOVC", &EmulateInstructionMIPS::Emulate_BOVC, "BOVC rs,rt,offset" },
- { "BNVC", &EmulateInstructionMIPS::Emulate_BNVC, "BNVC rs,rt,offset" },
+ { "BGEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZ rs,offset" },
+ { "BLEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BLEZALC rs,offset" },
+ { "BGEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BGEZALC rs,offset" },
+ { "BLTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BLTZALC rs,offset" },
+ { "BGTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BGTZALC rs,offset" },
+ { "BEQZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BEQZALC rs,offset" },
+ { "BNEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BNEZALC rs,offset" },
+ { "BEQC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BEQC rs,rt,offset" },
+ { "BNEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BNEC rs,rt,offset" },
+ { "BLTC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BLTC rs,rt,offset" },
+ { "BGEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BGEC rs,rt,offset" },
+ { "BLTUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BLTUC rs,rt,offset" },
+ { "BGEUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BGEUC rs,rt,offset" },
+ { "BLTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLTZC rt,offset" },
+ { "BLEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLEZC rt,offset" },
+ { "BGEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGEZC rt,offset" },
+ { "BGTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGTZC rt,offset" },
+ { "BEQZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BEQZC rt,offset" },
+ { "BNEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BNEZC rt,offset" },
+ { "BGEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZL rt,offset" },
+ { "BGTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZ rt,offset" },
+ { "BGTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZL rt,offset" },
+ { "BLEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZ rt,offset" },
+ { "BLEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZL rt,offset" },
+ { "BLTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZ rt,offset" },
+ { "BLTZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "BLTZAL rt,offset" },
+ { "BLTZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "BLTZALL rt,offset" },
+ { "BLTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZL rt,offset" },
+ { "BOVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BOVC rs,rt,offset" },
+ { "BNVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BNVC rs,rt,offset" },
{ "J", &EmulateInstructionMIPS::Emulate_J, "J target" },
{ "JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target" },
{ "JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target" },
@@ -461,16 +639,44 @@ EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name)
{ "JIC", &EmulateInstructionMIPS::Emulate_JIC, "JIC rt,offset" },
{ "JR", &EmulateInstructionMIPS::Emulate_JR, "JR target" },
{ "JR_HB", &EmulateInstructionMIPS::Emulate_JR, "JR.HB target" },
- { "BC1F", &EmulateInstructionMIPS::Emulate_BC1F, "BC1F cc, offset" },
- { "BC1T", &EmulateInstructionMIPS::Emulate_BC1T, "BC1T cc, offset" },
- { "BC1FL", &EmulateInstructionMIPS::Emulate_BC1FL, "BC1FL cc, offset" },
- { "BC1TL", &EmulateInstructionMIPS::Emulate_BC1TL, "BC1TL cc, offset" },
+ { "BC1F", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1F cc, offset" },
+ { "BC1T", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1T cc, offset" },
+ { "BC1FL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1FL cc, offset" },
+ { "BC1TL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1TL cc, offset" },
{ "BC1EQZ", &EmulateInstructionMIPS::Emulate_BC1EQZ, "BC1EQZ ft, offset" },
{ "BC1NEZ", &EmulateInstructionMIPS::Emulate_BC1NEZ, "BC1NEZ ft, offset" },
- { "BC1ANY2F", &EmulateInstructionMIPS::Emulate_BC1ANY2F, "BC1ANY2F cc, offset" },
- { "BC1ANY2T", &EmulateInstructionMIPS::Emulate_BC1ANY2T, "BC1ANY2T cc, offset" },
- { "BC1ANY4F", &EmulateInstructionMIPS::Emulate_BC1ANY4F, "BC1ANY4F cc, offset" },
- { "BC1ANY4T", &EmulateInstructionMIPS::Emulate_BC1ANY4T, "BC1ANY4T cc, offset" },
+ { "BC1ANY2F", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY2F cc, offset" },
+ { "BC1ANY2T", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY2T cc, offset" },
+ { "BC1ANY4F", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY4F cc, offset" },
+ { "BC1ANY4T", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY4T cc, offset" },
+ { "BNZ_B", &EmulateInstructionMIPS::Emulate_BNZB, "BNZ.b wt,s16" },
+ { "BNZ_H", &EmulateInstructionMIPS::Emulate_BNZH, "BNZ.h wt,s16" },
+ { "BNZ_W", &EmulateInstructionMIPS::Emulate_BNZW, "BNZ.w wt,s16" },
+ { "BNZ_D", &EmulateInstructionMIPS::Emulate_BNZD, "BNZ.d wt,s16" },
+ { "BZ_B", &EmulateInstructionMIPS::Emulate_BZB, "BZ.b wt,s16" },
+ { "BZ_H", &EmulateInstructionMIPS::Emulate_BZH, "BZ.h wt,s16" },
+ { "BZ_W", &EmulateInstructionMIPS::Emulate_BZW, "BZ.w wt,s16" },
+ { "BZ_D", &EmulateInstructionMIPS::Emulate_BZD, "BZ.d wt,s16" },
+ { "BNZ_V", &EmulateInstructionMIPS::Emulate_BNZV, "BNZ.V wt,s16" },
+ { "BZ_V", &EmulateInstructionMIPS::Emulate_BZV, "BZ.V wt,s16" },
+
+ //----------------------------------------------------------------------
+ // MicroMIPS Branch instructions
+ //----------------------------------------------------------------------
+ { "B16_MM", &EmulateInstructionMIPS::Emulate_B16_MM, "B16 offset" },
+ { "BEQZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BEQZ16 rs, offset" },
+ { "BNEZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BNEZ16 rs, offset" },
+ { "BEQZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BEQZC rs, offset" },
+ { "BNEZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BNEZC rs, offset" },
+ { "BGEZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BGEZALS rs, offset" },
+ { "BLTZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BLTZALS rs, offset" },
+ { "JALR16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALR16 rs" },
+ { "JALRS16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALRS16 rs" },
+ { "JR16_MM", &EmulateInstructionMIPS::Emulate_JR, "JR16 rs rs" },
+ { "JRC16_MM", &EmulateInstructionMIPS::Emulate_JR, "JRC16 rs rs" },
+ { "JALS_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALS target" },
+ { "JALX_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALX target" },
+ { "JALRS_MM", &EmulateInstructionMIPS::Emulate_JALRS, "JALRS rt, rs" },
};
static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes);
@@ -484,6 +690,76 @@ EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name)
return NULL;
}
+uint32_t
+EmulateInstructionMIPS::GetSizeOfInstruction (lldb_private::DataExtractor& data, uint64_t inst_addr)
+{
+ uint64_t next_inst_size = 0;
+ llvm::MCInst mc_insn;
+ llvm::MCDisassembler::DecodeStatus decode_status;
+ llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize());
+
+ if (m_use_alt_disaasm)
+ decode_status = m_alt_disasm->getInstruction (mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls(), llvm::nulls());
+ else
+ decode_status = m_disasm->getInstruction (mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls(), llvm::nulls());
+
+ if (decode_status != llvm::MCDisassembler::Success)
+ return false;
+
+ return m_insn_info->get(mc_insn.getOpcode()).getSize();
+}
+
+bool
+EmulateInstructionMIPS::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
+{
+ m_use_alt_disaasm = false;
+
+ if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
+ {
+ if (inst_addr.GetAddressClass() == eAddressClassCodeAlternateISA)
+ {
+ Error error;
+ lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
+
+ /*
+ * The address belongs to microMIPS function. To find the size of
+ * next instruction use microMIPS disassembler.
+ */
+ m_use_alt_disaasm = true;
+
+ uint32_t current_inst_size = insn_opcode.GetByteSize();
+ uint8_t buf[sizeof(uint32_t)];
+ uint64_t next_inst_addr = (m_addr & (~1ull)) + current_inst_size;
+ Address next_addr (next_inst_addr);
+
+ const size_t bytes_read = target->ReadMemory (next_addr, /* Address of next instruction */
+ true, /* prefer_file_cache */
+ buf,
+ sizeof(uint32_t),
+ error,
+ &load_addr);
+
+ if (bytes_read == 0)
+ return true;
+
+ DataExtractor data (buf, sizeof(uint32_t), GetByteOrder(), GetAddressByteSize());
+ m_next_inst_size = GetSizeOfInstruction (data, next_inst_addr);
+ return true;
+ }
+ else
+ {
+ /*
+ * If the address class is not eAddressClassCodeAlternateISA then
+ * the function is not microMIPS. In this case instruction size is
+ * always 4 bytes.
+ */
+ m_next_inst_size = 4;
+ return true;
+ }
+ }
+ return false;
+}
+
bool
EmulateInstructionMIPS::ReadInstruction ()
{
@@ -514,7 +790,11 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)
{
llvm::MCDisassembler::DecodeStatus decode_status;
llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize());
- decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ if (m_use_alt_disaasm)
+ decode_status = m_alt_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ else
+ decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+
if (decode_status != llvm::MCDisassembler::Success)
return false;
}
@@ -542,7 +822,7 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)
if (auto_advance_pc)
{
- old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
}
@@ -554,7 +834,7 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)
if (auto_advance_pc)
{
- new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
@@ -563,7 +843,7 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)
{
new_pc += 4;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, new_pc))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, new_pc))
return false;
}
}
@@ -581,10 +861,10 @@ EmulateInstructionMIPS::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
const bool can_replace = false;
// Our previous Call Frame Address is the stack pointer
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_sp_mips, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips, 0);
// Our previous PC is in the RA
- row->SetRegisterLocationToRegister(gcc_dwarf_pc_mips, gcc_dwarf_ra_mips, can_replace);
+ row->SetRegisterLocationToRegister(dwarf_pc_mips, dwarf_ra_mips, can_replace);
unwind_plan.AppendRow (row);
@@ -592,6 +872,7 @@ EmulateInstructionMIPS::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
unwind_plan.SetSourceName ("EmulateInstructionMIPS");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+ unwind_plan.SetReturnAddressRegister (dwarf_ra_mips);
return true;
}
@@ -601,18 +882,18 @@ EmulateInstructionMIPS::nonvolatile_reg_p (uint32_t regnum)
{
switch (regnum)
{
- case gcc_dwarf_r16_mips:
- case gcc_dwarf_r17_mips:
- case gcc_dwarf_r18_mips:
- case gcc_dwarf_r19_mips:
- case gcc_dwarf_r20_mips:
- case gcc_dwarf_r21_mips:
- case gcc_dwarf_r22_mips:
- case gcc_dwarf_r23_mips:
- case gcc_dwarf_gp_mips:
- case gcc_dwarf_sp_mips:
- case gcc_dwarf_r30_mips:
- case gcc_dwarf_ra_mips:
+ case dwarf_r16_mips:
+ case dwarf_r17_mips:
+ case dwarf_r18_mips:
+ case dwarf_r19_mips:
+ case dwarf_r20_mips:
+ case dwarf_r21_mips:
+ case dwarf_r22_mips:
+ case dwarf_r23_mips:
+ case dwarf_gp_mips:
+ case dwarf_sp_mips:
+ case dwarf_r30_mips:
+ case dwarf_ra_mips:
return true;
default:
return false;
@@ -633,10 +914,10 @@ EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn)
src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
/* Check if this is addiu sp,<src>,imm16 */
- if (dst == gcc_dwarf_sp_mips)
+ if (dst == dwarf_sp_mips)
{
/* read <src> register */
- uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, 0, &success);
+ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
if (!success)
return false;
@@ -644,13 +925,13 @@ EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn)
Context context;
RegisterInfo reg_info_sp;
- if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips, reg_info_sp))
+ if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp))
context.SetRegisterPlusOffset (reg_info_sp, imm);
/* We are allocating bytes on stack */
context.type = eContextAdjustStackPointer;
- WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips, result);
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result);
}
return true;
@@ -663,29 +944,38 @@ EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn)
uint32_t imm16 = insn.getOperand(2).getImm();
uint32_t imm = SignedBits(imm16, 15, 0);
uint32_t src, base;
+ int32_t address;
+ Context bad_vaddr_context;
+
+ RegisterInfo reg_info_base;
src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
+
+ /* read base register */
+ address = (int32_t)ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + imm;
+
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
+
/* We look for sp based non-volatile register stores */
- if (base == gcc_dwarf_sp_mips && nonvolatile_reg_p (src))
+ if (base == dwarf_sp_mips && nonvolatile_reg_p (src))
{
- uint32_t address;
- RegisterInfo reg_info_base;
- RegisterInfo reg_info_src;
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + base, reg_info_base)
- || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, reg_info_src))
- return false;
+ RegisterInfo reg_info_src;
- /* read SP */
- address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + base, 0, &success);
- if (!success)
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src))
return false;
- /* destination address */
- address = address + imm;
-
Context context;
RegisterValue data_src;
context.type = eContextPushRegisterOnStack;
@@ -712,21 +1002,42 @@ EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn)
bool
EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn)
{
+ bool success =false;
uint32_t src, base;
+ int32_t imm, address;
+ Context bad_vaddr_context;
src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ imm = insn.getOperand(2).getImm();
+
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
- if (base == gcc_dwarf_sp_mips && nonvolatile_reg_p (src))
+ /* read base register */
+ address = (int32_t)ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + imm;
+
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
+
+ if (base == dwarf_sp_mips && nonvolatile_reg_p (src))
{
RegisterValue data_src;
RegisterInfo reg_info_src;
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, reg_info_src))
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src))
return false;
Context context;
- context.type = eContextRegisterLoad;
+ context.type = eContextPopRegisterOffStack;
+ context.SetAddress (address);
if (!WriteRegister (context, &reg_info_src, data_src))
return false;
@@ -738,1591 +1049,1121 @@ EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn)
}
bool
-EmulateInstructionMIPS::Emulate_BEQ (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_ADDIUSP (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs, rt;
- int32_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BEQ rs, rt, offset
- * condition <- (GPR[rs] = GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ const uint32_t imm9 = insn.getOperand(0).getImm();
+ uint64_t result;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ // This instruction operates implicitly on stack pointer, so read <sp> register.
+ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_sp_mips, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val == rt_val)
- target = pc + offset;
- else
- target = pc + 8;
+ result = src_opd_val + imm9;
Context context;
- context.type = eContextRelativeBranchImmediate;
+ RegisterInfo reg_info_sp;
+ if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp))
+ context.SetRegisterPlusOffset (reg_info_sp, imm9);
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ // We are adjusting the stack.
+ context.type = eContextAdjustStackPointer;
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result);
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BNE (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_ADDIUS5 (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs, rt;
- int32_t offset, pc, target, rs_val, rt_val;
+ uint32_t base;
+ const uint32_t imm4 = insn.getOperand(2).getImm();
+ uint64_t result;
- /*
- * BNE rs, rt, offset
- * condition <- (GPR[rs] != GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
+ // The source and destination register is same for this instruction.
+ base = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ // We are looking for stack adjustment only
+ if (base == dwarf_sp_mips)
+ {
+ // Read stack pointer register
+ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
+ result = src_opd_val + imm4;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val != rt_val)
- target = pc + offset;
- else
- target = pc + 8;
+ Context context;
+ RegisterInfo reg_info_sp;
+ if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp))
+ context.SetRegisterPlusOffset (reg_info_sp, imm4);
- Context context;
- context.type = eContextRelativeBranchImmediate;
+ // We are adjusting the stack.
+ context.type = eContextAdjustStackPointer;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result);
+ }
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BEQL (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_SWSP (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs, rt;
- int32_t offset, pc, target, rs_val, rt_val;
+ uint32_t imm5 = insn.getOperand(2).getImm();
+ uint32_t src, base;
+ Context bad_vaddr_context;
+ uint32_t address;
- /*
- * BEQL rs, rt, offset
- * condition <- (GPR[rs] = GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
+ src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ RegisterInfo reg_info_base;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ // read base register
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
if (!success)
return false;
- if (rs_val == rt_val)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BNEL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int32_t offset, pc, target, rs_val, rt_val;
+ // destination address
+ address = address + imm5;
- /*
- * BNEL rs, rt, offset
- * condition <- (GPR[rs] != GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
+ // We use bad_vaddr_context to store base address which is used by H/W watchpoint
+ // Set the bad_vaddr register with base address used in the instruction
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ // We look for sp based non-volatile register stores.
+ if (base == dwarf_sp_mips && nonvolatile_reg_p (src))
+ {
+ RegisterInfo reg_info_src;
+ Context context;
+ RegisterValue data_src;
+ context.type = eContextPushRegisterOnStack;
+ context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0);
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
+ uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
+ Error error;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
- if (!success)
- return false;
+ if (!ReadRegister (&reg_info_base, data_src))
+ return false;
- if (rs_val != rt_val)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
+ if (data_src.GetAsMemoryData (&reg_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0)
+ return false;
- Context context;
- context.type = eContextRelativeBranchImmediate;
+ if (!WriteMemory (context, address, buffer, reg_info_src.byte_size))
+ return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ return true;
+ }
- return true;
+ return false;
}
+/* Emulate SWM16,SWM32 and SWP instruction.
+
+ SWM16 always has stack pointer as a base register (but it is still available in MCInst as an operand).
+ SWM32 and SWP can have base register other than stack pointer.
+*/
bool
-EmulateInstructionMIPS::Emulate_BGEZL (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_SWM16_32 (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
-
- /*
- * BGEZL rs, offset
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
+ uint32_t src, base;
+ uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on no of regs to store.
- Context context;
- context.type = eContextRelativeBranchImmediate;
+ // Base register is second last operand of the instruction.
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ // We are looking for sp based stores so if base is not a stack pointer then don't proceed.
+ if (base != dwarf_sp_mips)
return false;
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BLTZL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
-
- /*
- * BLTZL rs, offset
- * condition <- (GPR[rs] < 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
+ // offset is always the last operand.
+ uint32_t offset = insn.getOperand(num_operands-1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
+ RegisterInfo reg_info_base;
+ RegisterInfo reg_info_src;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ // read SP
+ uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
if (!success)
return false;
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ // Resulting base addrss
+ base_address = base_address + offset;
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BGTZL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
+ // Total no of registers to be stored are num_operands-2.
+ for (uint32_t i = 0; i < num_operands - 2; i++)
+ {
+ // Get the register number to be stored.
+ src = m_reg_info->getEncodingValue (insn.getOperand(i).getReg());
+
+ /*
+ Record only non-volatile stores.
+ This check is required for SWP instruction because source operand could be any register.
+ SWM16 and SWM32 instruction always has saved registers as source operands.
+ */
+ if (!nonvolatile_reg_p (src))
+ return false;
- /*
- * BGTZL rs, offset
- * condition <- (GPR[rs] > 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src))
+ return false;
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ Context context;
+ RegisterValue data_src;
+ context.type = eContextPushRegisterOnStack;
+ context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0);
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
+ uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
+ Error error;
- if (rs_val > 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
+ if (!ReadRegister (&reg_info_base, data_src))
+ return false;
- Context context;
- context.type = eContextRelativeBranchImmediate;
+ if (data_src.GetAsMemoryData (&reg_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0)
+ return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ if (!WriteMemory (context, base_address, buffer, reg_info_src.byte_size))
+ return false;
+ // Stack address for next register
+ base_address = base_address + reg_info_src.byte_size;
+ }
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BLEZL (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_LWSP (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
+ uint32_t src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ uint32_t base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ uint32_t imm5 = insn.getOperand(2).getImm();
+ Context bad_vaddr_context;
- /*
- * BLEZL rs, offset
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ // read base register
+ uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
if (!success)
return false;
- if (rs_val <= 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ base_address = base_address + imm5;
- return true;
-}
+ // We use bad_vaddr_context to store base address which is used by H/W watchpoint
+ // Set the bad_vaddr register with base address used in the instruction
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, base_address);
-bool
-EmulateInstructionMIPS::Emulate_BGTZ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
-
- /*
- * BGTZ rs, offset
- * condition <- (GPR[rs] > 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ if (base == dwarf_sp_mips && nonvolatile_reg_p (src))
+ {
+ RegisterValue data_src;
+ RegisterInfo reg_info_src;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src))
+ return false;
- if (rs_val > 0)
- target = pc + offset;
- else
- target = pc + 8;
+ Context context;
+ context.type = eContextPopRegisterOffStack;
+ context.SetAddress (base_address);
- Context context;
- context.type = eContextRelativeBranchImmediate;
+ if (!WriteRegister (context, &reg_info_src, data_src))
+ return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ return true;
+ }
- return true;
+ return false;
}
+/* Emulate LWM16, LWM32 and LWP instructions.
+
+ LWM16 always has stack pointer as a base register (but it is still available in MCInst as an operand).
+ LWM32 and LWP can have base register other than stack pointer.
+*/
bool
-EmulateInstructionMIPS::Emulate_BLEZ (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_LWM16_32 (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
-
- /*
- * BLEZ rs, offset
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
+ uint32_t dst, base;
+ uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on no of regs to store.
+ uint32_t imm = insn.getOperand(num_operands-1).getImm(); // imm is the last operand in the instruction.
+
+ // Base register is second last operand of the instruction.
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
+ // We are looking for sp based loads so if base is not a stack pointer then don't proceed.
+ if (base != dwarf_sp_mips)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
if (!success)
return false;
- if (rs_val <= 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
+ base_address = base_address + imm;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ RegisterValue data_dst;
+ RegisterInfo reg_info_dst;
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BLTZ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
-
- /*
- * BLTZ rs, offset
- * condition <- (GPR[rs] < 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8;
+ // Total no of registers to be re-stored are num_operands-2.
+ for (uint32_t i = 0; i < num_operands - 2; i++)
+ {
+ // Get the register number to be re-stored.
+ dst = m_reg_info->getEncodingValue (insn.getOperand(i).getReg());
+
+ /*
+ Record only non-volatile loads.
+ This check is required for LWP instruction because destination operand could be any register.
+ LWM16 and LWM32 instruction always has saved registers as destination operands.
+ */
+ if (!nonvolatile_reg_p (dst))
+ return false;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + dst, reg_info_dst))
+ return false;
- Context context;
- context.type = eContextRelativeBranchImmediate;
+ Context context;
+ context.type = eContextPopRegisterOffStack;
+ context.SetAddress (base_address + (i*4));
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ if (!WriteRegister (context, &reg_info_dst, data_dst))
+ return false;
+ }
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BGEZALL (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_JRADDIUSP (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
+ int32_t imm5 = insn.getOperand(0).getImm();
- /*
- * BGEZALL rt, offset
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
+ /* JRADDIUSP immediate
+ * PC <- RA
+ * SP <- SP + zero_extend(Immediate << 2)
*/
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+
+ // This instruction operates implicitly on stack pointer, so read <sp> register.
+ int32_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_sp_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ int32_t ra_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_ra_mips, 0, &success);
if (!success)
return false;
-
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
+
+ int32_t result = src_opd_val + imm5;
Context context;
- context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ // Update the PC
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, ra_val))
return false;
+
+ RegisterInfo reg_info_sp;
+ if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp))
+ context.SetRegisterPlusOffset (reg_info_sp, imm5);
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BAL (llvm::MCInst& insn)
-{
- bool success = false;
- int32_t offset, pc, target;
-
- /*
- * BAL offset
- * offset = sign_ext (offset << 2)
- * RA = PC + 8
- * PC = PC + offset
- */
- offset = insn.getOperand(0).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- target = pc + offset;
-
- Context context;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ // We are adjusting stack
+ context.type = eContextAdjustStackPointer;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ // update SP
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result))
return false;
return true;
}
-bool
-EmulateInstructionMIPS::Emulate_BALC (llvm::MCInst& insn)
+static int
+IsAdd64bitOverflow (int32_t a, int32_t b)
{
- bool success = false;
- int32_t offset, pc, target;
-
- /*
- * BALC offset
- * offset = sign_ext (offset << 2)
- * RA = PC + 4
- * PC = PC + 4 + offset
- */
- offset = insn.getOperand(0).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- target = pc + 4 + offset;
-
- Context context;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
- return false;
-
- return true;
+ int32_t r = (uint32_t) a + (uint32_t) b;
+ return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
}
+/*
+ Emulate below MIPS branch instructions.
+ BEQ, BNE : Branch on condition
+ BEQL, BNEL : Branch likely
+*/
bool
-EmulateInstructionMIPS::Emulate_BGEZAL (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BXX_3ops (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
+ uint32_t rs, rt;
+ int32_t offset, pc, target = 0, rs_val, rt_val;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BGEZAL rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * RA = PC + 8
- * PC = PC + offset
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- Context context;
-
- if ((int32_t) rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BLTZAL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
-
- /*
- * BLTZAL rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] < 0)
- * if condition then
- * RA = PC + 8
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
+ if (!strcasecmp (op_name, "BEQ") ||
+ !strcasecmp (op_name, "BEQL"))
+ {
+ if (rs_val == rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BNE") ||
+ !strcasecmp (op_name, "BNEL"))
+ {
+ if (rs_val != rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
Context context;
+ context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (offset);
- if ((int32_t) rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
- return false;
-
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
+ return false;
+
return true;
}
+/*
+ Emulate below MIPS branch instructions.
+ BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch instructions with no delay slot
+*/
bool
-EmulateInstructionMIPS::Emulate_BLTZALL (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BXX_3ops_C (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
-
- /*
- * BLTZALL rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] < 0)
- * if condition then
- * RA = PC + 8
- * PC = PC + offset
- */
+ uint32_t rs, rt;
+ int32_t offset, pc, target = 0, rs_val, rt_val;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+ uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
+
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- Context context;
-
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
- return false;
-
- return true;
-}
-
-
-bool
-EmulateInstructionMIPS::Emulate_BLEZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
-
- /*
- * BLEZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
+ if (!strcasecmp (op_name, "BEQC"))
+ {
+ if (rs_val == rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNEC"))
+ {
+ if (rs_val != rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLTC"))
+ {
+ if (rs_val < rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEC"))
+ {
+ if (rs_val >= rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLTUC"))
+ {
+ if (rs_val < rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEUC"))
+ {
+ if ((uint32_t)rs_val >= (uint32_t)rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BOVC"))
+ {
+ if (IsAdd64bitOverflow (rs_val, rt_val))
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNVC"))
+ {
+ if (!IsAdd64bitOverflow (rs_val, rt_val))
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
Context context;
+ context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (current_inst_size + offset);
- if (rs_val <= 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
- return false;
-
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
+ return false;
+
return true;
}
+/*
+ Emulate below MIPS conditional branch and link instructions.
+ BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
+*/
bool
-EmulateInstructionMIPS::Emulate_BGEZALC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_Bcond_Link_C (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs;
- int32_t offset, pc, target;
+ int32_t offset, pc, target = 0;
int32_t rs_val;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BGEZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- Context context;
-
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 4;
+ if (!strcasecmp (op_name, "BLEZALC"))
+ {
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEZALC"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLTZALC"))
+ {
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGTZALC"))
+ {
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BEQZALC"))
+ {
+ if (rs_val == 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNEZALC"))
+ {
+ if (rs_val != 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))
return false;
return true;
}
+/*
+ Emulate below MIPS Non-Compact conditional branch and link instructions.
+ BLTZAL, BGEZAL :
+ BLTZALL, BGEZALL : Branch likely
+*/
bool
-EmulateInstructionMIPS::Emulate_BLTZALC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_Bcond_Link (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs;
- int32_t offset, pc, target;
+ int32_t offset, pc, target = 0;
int32_t rs_val;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BLTZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] < 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- Context context;
+ if (!strcasecmp (op_name, "BLTZAL") ||
+ !strcasecmp (op_name, "BLTZALL"))
+ {
+ if ((int32_t) rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BGEZAL") ||
+ !strcasecmp (op_name, "BGEZALL"))
+ {
+ if ((int32_t) rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 4;
+ Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))
return false;
return true;
}
+/*
+ Emulate below MIPS branch instructions.
+ BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
+ BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
+*/
bool
-EmulateInstructionMIPS::Emulate_BGTZALC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BXX_2ops (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs;
- int32_t offset, pc, target;
+ int32_t offset, pc, target = 0;
int32_t rs_val;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BGTZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] > 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- Context context;
-
- if (rs_val > 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BEQZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int32_t offset, pc, target, rs_val;
-
- /*
- * BEQZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] == 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
+ if (!strcasecmp (op_name, "BLTZL") ||
+ !strcasecmp (op_name, "BLTZ"))
+ {
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BGEZL") ||
+ !strcasecmp (op_name, "BGEZ"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BGTZL") ||
+ !strcasecmp (op_name, "BGTZ"))
+ {
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BLEZL") ||
+ !strcasecmp (op_name, "BLEZ"))
+ {
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
Context context;
+ context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (offset);
- if (rs_val == 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
}
+/*
+ Emulate below MIPS branch instructions.
+ BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
+*/
bool
-EmulateInstructionMIPS::Emulate_BNEZALC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BXX_2ops_C (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs;
- int32_t offset, pc, target, rs_val;
+ int32_t offset, pc, target = 0;
+ int32_t rs_val;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+ uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
- /*
- * BNEZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] != 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- Context context;
-
- if (rs_val != 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BGEZ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int32_t offset, pc, target, rs_val;
-
- /*
- * BGEZ rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
+ if (!strcasecmp (op_name, "BLTZC"))
+ {
+ if (rs_val < 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLEZC"))
+ {
+ if (rs_val <= 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEZC"))
+ {
+ if (rs_val >= 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGTZC"))
+ {
+ if (rs_val > 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BEQZC"))
+ {
+ if (rs_val == 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNEZC"))
+ {
+ if (rs_val != 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
Context context;
+ context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (current_inst_size + offset);
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_B16_MM (llvm::MCInst& insn)
{
bool success = false;
int32_t offset, pc, target;
+ uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
- /*
- * BC offset
- * offset = sign_ext (offset << 2)
- * PC = PC + 4 + offset
- */
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- target = pc + 4 + offset;
-
- Context context;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BEQC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int32_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BEQC rs, rt, offset
- * condition <- (GPR[rs] = GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val == rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
+ // unconditional branch
+ target = pc + offset;
Context context;
context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (current_inst_size + offset);
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
}
+/*
+ BEQZC, BNEZC are 32 bit compact instructions without a delay slot.
+ BEQZ16, BNEZ16 are 16 bit instructions with delay slot.
+ BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot.
+*/
bool
-EmulateInstructionMIPS::Emulate_BNEC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_Branch_MM (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs, rt;
- int32_t offset, pc, target, rs_val, rt_val;
+ int32_t target = 0;
+ uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+ bool update_ra = false;
+ uint32_t ra_offset = 0;
/*
- * BNEC rs, rt, offset
- * condition <- (GPR[rs] != GPR[rt])
+ * BEQZ16 rs, offset
+ * condition <- (GPR[rs] = 0)
* if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val != rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BLTC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int32_t offset, pc, target;
- int32_t rs_val, rt_val;
-
- /*
- * BLTC rs, rt, offset
- * condition <- (GPR[rs] < GPR[rt])
+ * PC = PC + sign_ext (offset || 0)
+ *
+ * BNEZ16 rs, offset
+ * condition <- (GPR[rs] != 0)
* if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val < rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BGEC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int32_t offset, pc, target;
- int32_t rs_val, rt_val;
-
- /*
- * BGEC rs, rt, offset
- * condition <- (GPR[rs] > GPR[rt])
+ * PC = PC + sign_ext (offset || 0)
+ *
+ * BEQZC rs, offset (compact instruction: No delay slot)
+ * condition <- (GPR[rs] == 0)
* if condition then
- * PC = PC + sign_ext (offset << 2)
+ * PC = PC + 4 + sign_ext (offset || 0)
*/
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ int32_t offset = insn.getOperand(1).getImm();
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ int32_t rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- if (rs_val > rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
+ if (!strcasecmp (op_name, "BEQZ16_MM"))
+ {
+ if (rs_val == 0)
+ target = pc + offset;
+ else
+ target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction.
+ }
+ else if (!strcasecmp (op_name, "BNEZ16_MM"))
+ {
+ if (rs_val != 0)
+ target = pc + offset;
+ else
+ target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction.
+ }
+ else if (!strcasecmp (op_name, "BEQZC_MM"))
+ {
+ if (rs_val == 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4; // 32 bit instruction and does not have delay slot instruction.
+ }
+ else if (!strcasecmp (op_name, "BNEZC_MM"))
+ {
+ if (rs_val != 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4; // 32 bit instruction and does not have delay slot instruction.
+ }
+ else if (!strcasecmp (op_name, "BGEZALS_MM"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
+
+ update_ra = true;
+ ra_offset = 6;
+ }
+ else if (!strcasecmp (op_name, "BLTZALS_MM"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
+
+ update_ra = true;
+ ra_offset = 6;
+ }
Context context;
context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (current_inst_size + offset);
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
+ if (update_ra)
+ {
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset))
+ return false;
+ }
return true;
}
+/* Emulate micromips jump instructions.
+ JALR16,JALRS16
+*/
bool
-EmulateInstructionMIPS::Emulate_BLTUC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_JALRx16_MM (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs, rt;
- int32_t offset, pc, target;
- uint32_t rs_val, rt_val;
+ uint32_t ra_offset = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BLTUC rs, rt, offset
- * condition <- (GPR[rs] < GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
+ uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ uint32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ uint32_t rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val < rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
+ if (!strcasecmp (op_name, "JALR16_MM"))
+ ra_offset = 6; // 2-byte instruction with 4-byte delay slot.
+ else if (!strcasecmp (op_name, "JALRS16_MM"))
+ ra_offset = 4; // 2-byte instruction with 2-byte delay slot.
Context context;
- context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val))
return false;
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BGEUC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int32_t offset, pc, target;
- uint32_t rs_val, rt_val;
-
- /*
- * BGEUC rs, rt, offset
- * condition <- (GPR[rs] > GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val > rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset))
return false;
return true;
}
+/* Emulate JALS and JALX instructions.
+ JALS 32 bit instruction with short (2-byte) delay slot.
+ JALX 32 bit instruction with 4-byte delay slot.
+*/
bool
-EmulateInstructionMIPS::Emulate_BLTZC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_JALx (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
-
- /*
- * BLTZC rs, offset
- * condition <- (GPR[rs] < 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
+ uint32_t offset=0, target=0, pc=0, ra_offset=0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+
+ /*
+ * JALS target
+ * RA = PC + 6
+ * offset = sign_ext (offset << 1)
+ * PC = PC[31-27] | offset
+ * JALX target
+ * RA = PC + 8
+ * offset = sign_ext (offset << 2)
+ * PC = PC[31-28] | offset
*/
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ offset = insn.getOperand(0).getImm();
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- if (rs_val < 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
+ // These are PC-region branches and not PC-relative.
+ if (!strcasecmp (op_name, "JALS_MM"))
+ {
+ // target address is in the “current†128 MB-aligned region
+ target = (pc & 0xF8000000UL) | offset;
+ ra_offset = 6;
+ }
+ else if (!strcasecmp (op_name, "JALX_MM"))
+ {
+ // target address is in the “current†256 MB-aligned region
+ target = (pc & 0xF0000000UL) | offset;
+ ra_offset = 8;
+ }
Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BLEZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
-
- /*
- * BLEZC rs, offset
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val <= 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset))
return false;
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BGEZC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_JALRS (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- int32_t rs_val;
-
+ uint32_t rs=0, rt=0;
+ int32_t pc=0, rs_val=0;
+
/*
- * BGEZC rs, offset
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
+ JALRS rt, rs
+ GPR[rt] <- PC + 6
+ PC <- GPR[rs]
*/
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
-
- if (rs_val >= 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
+
Context context;
- context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val))
return false;
+ // This is 4-byte instruction with 2-byte delay slot.
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 6))
+ return false;
+
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BGTZC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BAL (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs;
int32_t offset, pc, target;
- int32_t rs_val;
/*
- * BGTZC rs, offset
- * condition <- (GPR[rs] > 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
+ * BAL offset
+ * offset = sign_ext (offset << 2)
+ * RA = PC + 8
+ * PC = PC + offset
*/
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ offset = insn.getOperand(0).getImm();
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- if (rs_val > 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
+ target = pc + offset;
Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BEQZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int32_t offset, pc, target;
- uint32_t rs_val;
-
- /*
- * BEQZC rs, offset
- * condition <- (GPR[rs] = 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val == 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))
return false;
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BNEZC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BALC (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs;
int32_t offset, pc, target;
- uint32_t rs_val;
- /*
- * BNEZC rs, offset
- * condition <- (GPR[rs] != 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
+ /*
+ * BALC offset
+ * offset = sign_ext (offset << 2)
+ * RA = PC + 4
+ * PC = PC + 4 + offset
*/
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ offset = insn.getOperand(0).getImm();
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- if (rs_val != 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
+ target = pc + 4 + offset;
Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
-
- return true;
-}
-
-static int
-IsAdd64bitOverflow (int32_t a, int32_t b)
-{
- int32_t r = (uint32_t) a + (uint32_t) b;
- return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
-}
-
-bool
-EmulateInstructionMIPS::Emulate_BOVC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int32_t offset, pc, target;
- int32_t rs_val, rt_val;
-
- /*
- * BOVC rs, rt, offset
- * condition <- overflow(GPR[rs] + GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
- if (!success)
- return false;
-
- if (IsAdd64bitOverflow (rs_val, rt_val))
- target = pc + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))
return false;
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BNVC (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BC (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs, rt;
int32_t offset, pc, target;
- int32_t rs_val, rt_val;
- /*
- * BNVC rs, rt, offset
- * condition <- overflow(GPR[rs] + GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
+ /*
+ * BC offset
+ * offset = sign_ext (offset << 2)
+ * PC = PC + 4 + offset
*/
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
- if (!success)
- return false;
+ offset = insn.getOperand(0).getImm();
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- if (! IsAdd64bitOverflow (rs_val, rt_val))
- target = pc + offset;
- else
- target = pc + 4;
+ target = pc + 4 + offset;
Context context;
- context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2341,7 +2182,7 @@ EmulateInstructionMIPS::Emulate_J (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
@@ -2350,7 +2191,7 @@ EmulateInstructionMIPS::Emulate_J (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, pc))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, pc))
return false;
return true;
@@ -2369,7 +2210,7 @@ EmulateInstructionMIPS::Emulate_JAL (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
@@ -2378,10 +2219,10 @@ EmulateInstructionMIPS::Emulate_JAL (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))
return false;
return true;
@@ -2402,20 +2243,20 @@ EmulateInstructionMIPS::Emulate_JALR (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, rs_val))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 8))
return false;
return true;
@@ -2437,11 +2278,11 @@ EmulateInstructionMIPS::Emulate_JIALC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -2449,10 +2290,10 @@ EmulateInstructionMIPS::Emulate_JIALC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))
return false;
return true;
@@ -2473,7 +2314,7 @@ EmulateInstructionMIPS::Emulate_JIC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -2481,7 +2322,7 @@ EmulateInstructionMIPS::Emulate_JIC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2500,432 +2341,436 @@ EmulateInstructionMIPS::Emulate_JR (llvm::MCInst& insn)
*/
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, rs_val))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val))
return false;
return true;
}
+/*
+ Emulate Branch on FP True/False
+ BC1F, BC1FL : Branch on FP False (L stands for branch likely)
+ BC1T, BC1TL : Branch on FP True (L stands for branch likely)
+*/
bool
-EmulateInstructionMIPS::Emulate_BC1F (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_FP_branch (llvm::MCInst& insn)
{
bool success = false;
uint32_t cc, fcsr;
- int32_t target, pc, offset;
-
- /*
- * BC1F cc, offset
- * condition <- (FPConditionCode(cc) == 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
+ int32_t pc, offset, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
if (!success)
return false;
/* fcsr[23], fcsr[25-31] are vaild condition bits */
fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- if ((fcsr & (1 << cc)) == 0)
- target = pc + offset;
- else
- target = pc + 8;
-
+
+ if (!strcasecmp (op_name, "BC1F") ||
+ !strcasecmp (op_name, "BC1FL"))
+ {
+ if ((fcsr & (1 << cc)) == 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1T") ||
+ !strcasecmp (op_name, "BC1TL"))
+ {
+ if ((fcsr & (1 << cc)) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BC1T (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BC1EQZ (llvm::MCInst& insn)
{
bool success = false;
- uint32_t cc, fcsr;
+ uint32_t ft;
+ uint32_t ft_val;
int32_t target, pc, offset;
/*
- * BC1T cc, offset
- * condition <- (FPConditionCode(cc) != 0)
+ * BC1EQZ ft, offset
+ * condition <- (FPR[ft].bit0 == 0)
* if condition then
* offset = sign_ext (offset)
- * PC = PC + offset
+ * PC = PC + 4 + offset
*/
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 0, &success);
if (!success)
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- if ((fcsr & (1 << cc)) != 0)
- target = pc + offset;
+ if ((ft_val & 1) == 0)
+ target = pc + 4 + offset;
else
target = pc + 8;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BC1FL (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BC1NEZ (llvm::MCInst& insn)
{
bool success = false;
- uint32_t cc, fcsr;
+ uint32_t ft;
+ uint32_t ft_val;
int32_t target, pc, offset;
/*
- * BC1F cc, offset
- * condition <- (FPConditionCode(cc) == 0)
+ * BC1NEZ ft, offset
+ * condition <- (FPR[ft].bit0 != 0)
* if condition then
* offset = sign_ext (offset)
- * PC = PC + offset
+ * PC = PC + 4 + offset
*/
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 0, &success);
if (!success)
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- if ((fcsr & (1 << cc)) == 0)
- target = pc + offset;
+ if ((ft_val & 1) != 0)
+ target = pc + 4 + offset;
else
- target = pc + 8; /* skip delay slot */
+ target = pc + 8;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
}
+/*
+ Emulate MIPS-3D Branch instructions
+ BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes False/True
+ BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes False/True
+*/
bool
-EmulateInstructionMIPS::Emulate_BC1TL (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_3D_branch (llvm::MCInst& insn)
{
bool success = false;
uint32_t cc, fcsr;
- int32_t target, pc, offset;
-
- /*
- * BC1T cc, offset
- * condition <- (FPConditionCode(cc) != 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
+ int32_t pc, offset, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
if (!success)
return false;
/* fcsr[23], fcsr[25-31] are vaild condition bits */
fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- if ((fcsr & (1 << cc)) != 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
+
+ if (!strcasecmp (op_name, "BC1ANY2F"))
+ {
+ /* if any one bit is 0 */
+ if (((fcsr >> cc) & 3) != 3)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1ANY2T"))
+ {
+ /* if any one bit is 1 */
+ if (((fcsr >> cc) & 3) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1ANY4F"))
+ {
+ /* if any one bit is 0 */
+ if (((fcsr >> cc) & 0xf) != 0xf)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1ANY4T"))
+ {
+ /* if any one bit is 1 */
+ if (((fcsr >> cc) & 0xf) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BC1EQZ (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BNZB (llvm::MCInst& insn)
{
- bool success = false;
- uint32_t ft;
- uint32_t ft_val;
- int32_t target, pc, offset;
-
- /*
- * BC1EQZ ft, offset
- * condition <- (FPR[ft].bit0 == 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + 4 + offset
- */
- ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
-
- ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + ft, 0, &success);
- if (!success)
- return false;
-
- if ((ft_val & 1) == 0)
- target = pc + 4 + offset;
- else
- target = pc + 8;
-
- Context context;
+ return Emulate_MSA_Branch_DF(insn, 1, true);
+}
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+bool
+EmulateInstructionMIPS::Emulate_BNZH (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 2, true);
+}
- return true;
+bool
+EmulateInstructionMIPS::Emulate_BNZW (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 4, true);
}
bool
-EmulateInstructionMIPS::Emulate_BC1NEZ (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BNZD (llvm::MCInst& insn)
{
- bool success = false;
- uint32_t ft;
- uint32_t ft_val;
- int32_t target, pc, offset;
-
- /*
- * BC1NEZ ft, offset
- * condition <- (FPR[ft].bit0 != 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + 4 + offset
- */
- ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ return Emulate_MSA_Branch_DF(insn, 8, true);
+}
- ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + ft, 0, &success);
- if (!success)
- return false;
+bool
+EmulateInstructionMIPS::Emulate_BZB (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 1, false);
+}
- if ((ft_val & 1) != 0)
- target = pc + 4 + offset;
- else
- target = pc + 8;
-
- Context context;
+bool
+EmulateInstructionMIPS::Emulate_BZH (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 2, false);
+}
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+bool
+EmulateInstructionMIPS::Emulate_BZW (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 4, false);
+}
- return true;
+bool
+EmulateInstructionMIPS::Emulate_BZD (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 8, false);
}
bool
-EmulateInstructionMIPS::Emulate_BC1ANY2F (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz)
{
- bool success = false;
- uint32_t cc, fcsr;
- int32_t target, pc, offset;
-
- /*
- * BC1ANY2F cc, offset
- * condition <- (FPConditionCode(cc) == 0
- * || FPConditionCode(cc+1) == 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ bool success = false, branch_hit = true;
+ int32_t target = 0;
+ RegisterValue reg_value;
+ uint8_t * ptr = NULL;
+
+ uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ int32_t offset = insn.getOperand(1).getImm();
+
+ int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
- if (!success)
+ if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
+ ptr = (uint8_t *)reg_value.GetBytes();
+ else
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+ for(int i = 0; i < 16 / element_byte_size; i++)
+ {
+ switch(element_byte_size)
+ {
+ case 1:
+ if((*ptr == 0 && bnz) || (*ptr != 0 && !bnz) )
+ branch_hit = false;
+ break;
+ case 2:
+ if((*(uint16_t *)ptr == 0 && bnz) || (*(uint16_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ case 4:
+ if((*(uint32_t *)ptr == 0 && bnz) || (*(uint32_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ case 8:
+ if((*(uint64_t *)ptr == 0 && bnz) || (*(uint64_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ }
+ if(!branch_hit)
+ break;
+ ptr = ptr + element_byte_size;
+ }
- /* if any one bit is 0 */
- if (((fcsr >> cc) & 3) != 3)
+ if(branch_hit)
target = pc + offset;
else
target = pc + 8;
-
+
Context context;
+ context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BC1ANY2T (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_BNZV (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_V (insn, true);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BZV (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_V (insn, false);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz)
{
bool success = false;
- uint32_t cc, fcsr;
- int32_t target, pc, offset;
-
- /*
- * BC1ANY2T cc, offset
- * condition <- (FPConditionCode(cc) == 1
- * || FPConditionCode(cc+1) == 1)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
- return false;
+ int32_t target = 0;
+ llvm::APInt wr_val = llvm::APInt::getNullValue(128);
+ llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
+ llvm::APInt zero_value = llvm::APInt::getNullValue(128);
+ RegisterValue reg_value;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ int32_t offset = insn.getOperand(1).getImm();
+
+ int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+ if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
+ wr_val = reg_value.GetAsUInt128(fail_value);
+ else
+ return false;
- /* if any one bit is 1 */
- if (((fcsr >> cc) & 3) != 0)
+ if((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
target = pc + offset;
else
target = pc + 8;
-
+
Context context;
+ context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BC1ANY4F (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_LDST_Imm (llvm::MCInst& insn)
{
bool success = false;
- uint32_t cc, fcsr;
- int32_t target, pc, offset;
-
- /*
- * BC1ANY4F cc, offset
- * condition <- (FPConditionCode(cc) == 0
- * || FPConditionCode(cc+1) == 0)
- * || FPConditionCode(cc+2) == 0)
- * || FPConditionCode(cc+3) == 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
+ uint32_t base;
+ int32_t imm, address;
+ Context bad_vaddr_context;
+
+ uint32_t num_operands = insn.getNumOperands();
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
+ imm = insn.getOperand(num_operands-1).getImm();
+
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ /* read base register */
+ address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
if (!success)
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- /* if any one bit is 0 */
- if (((fcsr >> cc) & 0xf) != 0xf)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
+ /* destination address */
+ address = address + imm;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
return true;
}
bool
-EmulateInstructionMIPS::Emulate_BC1ANY4T (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_LDST_Reg (llvm::MCInst& insn)
{
bool success = false;
- uint32_t cc, fcsr;
- int32_t target, pc, offset;
-
- /*
- * BC1ANY4T cc, offset
- * condition <- (FPConditionCode(cc) == 1
- * || FPConditionCode(cc+1) == 1)
- * || FPConditionCode(cc+2) == 1)
- * || FPConditionCode(cc+3) == 1)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
- if (!success)
+ uint32_t base, index;
+ int32_t address, index_address;
+ Context bad_vaddr_context;
+
+ uint32_t num_operands = insn.getNumOperands();
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
+ index = m_reg_info->getEncodingValue (insn.getOperand(num_operands-1).getReg());
+
+ RegisterInfo reg_info_base, reg_info_index;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + index, reg_info_index))
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ /* read base register */
+ address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
if (!success)
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+ /* read index register */
+ index_address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success);
+ if (!success)
+ return false;
- /* if any one bit is 1 */
- if (((fcsr >> cc) & 0xf) != 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
+ /* destination address */
+ address = address + index_address;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
- return false;
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
return true;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h
index 25d8fc8..892de05 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h
@@ -60,53 +60,52 @@ public:
return false;
}
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual lldb_private::ConstString
- GetShortPluginName()
- {
- return GetPluginNameStatic();
- }
-
- virtual uint32_t
- GetPluginVersion()
+ uint32_t
+ GetPluginVersion() override
{
return 1;
}
bool
- SetTargetTriple (const lldb_private::ArchSpec &arch);
+ SetTargetTriple (const lldb_private::ArchSpec &arch) override;
EmulateInstructionMIPS (const lldb_private::ArchSpec &arch);
- virtual bool
- SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type)
+ bool
+ SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type) override
{
return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
}
- virtual bool
- ReadInstruction ();
-
- virtual bool
- EvaluateInstruction (uint32_t evaluate_options);
+ bool
+ ReadInstruction () override;
- virtual bool
+ bool
+ EvaluateInstruction (uint32_t evaluate_options) override;
+
+ bool
+ SetInstruction (const lldb_private::Opcode &insn_opcode,
+ const lldb_private::Address &inst_addr,
+ lldb_private::Target *target) override;
+
+ bool
TestEmulation (lldb_private::Stream *out_stream,
lldb_private::ArchSpec &arch,
- lldb_private::OptionValueDictionary *test_data)
+ lldb_private::OptionValueDictionary *test_data) override
{
return false;
}
- virtual bool
+ bool
GetRegisterInfo (lldb::RegisterKind reg_kind,
uint32_t reg_num,
- lldb_private::RegisterInfo &reg_info);
+ lldb_private::RegisterInfo &reg_info) override;
- virtual bool
- CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan) override;
protected:
@@ -121,6 +120,9 @@ protected:
static MipsOpcode*
GetOpcodeForInstruction (const char *op_name);
+ uint32_t
+ GetSizeOfInstruction (lldb_private::DataExtractor& data, uint64_t inst_addr);
+
bool
Emulate_ADDiu (llvm::MCInst& insn);
@@ -131,169 +133,139 @@ protected:
Emulate_LW (llvm::MCInst& insn);
bool
- Emulate_BEQ (llvm::MCInst& insn);
-
- bool
- Emulate_BNE (llvm::MCInst& insn);
-
- bool
- Emulate_BEQL (llvm::MCInst& insn);
-
- bool
- Emulate_BNEL (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZALL (llvm::MCInst& insn);
-
- bool
- Emulate_BAL (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZAL (llvm::MCInst& insn);
-
- bool
- Emulate_BALC (llvm::MCInst& insn);
-
- bool
- Emulate_BC (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZ (llvm::MCInst& insn);
+ Emulate_ADDIUSP (llvm::MCInst& insn);
bool
- Emulate_BLEZALC (llvm::MCInst& insn);
+ Emulate_ADDIUS5 (llvm::MCInst& insn);
bool
- Emulate_BGEZALC (llvm::MCInst& insn);
+ Emulate_SWSP (llvm::MCInst& insn);
bool
- Emulate_BLTZALC (llvm::MCInst& insn);
+ Emulate_SWM16_32 (llvm::MCInst& insn);
bool
- Emulate_BGTZALC (llvm::MCInst& insn);
+ Emulate_LWSP (llvm::MCInst& insn);
bool
- Emulate_BEQZALC (llvm::MCInst& insn);
+ Emulate_LWM16_32 (llvm::MCInst& insn);
bool
- Emulate_BNEZALC (llvm::MCInst& insn);
+ Emulate_JRADDIUSP (llvm::MCInst& insn);
bool
- Emulate_BEQC (llvm::MCInst& insn);
+ Emulate_LDST_Imm (llvm::MCInst& insn);
bool
- Emulate_BNEC (llvm::MCInst& insn);
+ Emulate_LDST_Reg (llvm::MCInst& insn);
bool
- Emulate_BLTC (llvm::MCInst& insn);
+ Emulate_BXX_3ops (llvm::MCInst& insn);
bool
- Emulate_BGEC (llvm::MCInst& insn);
+ Emulate_BXX_3ops_C (llvm::MCInst& insn);
bool
- Emulate_BLTUC (llvm::MCInst& insn);
+ Emulate_BXX_2ops (llvm::MCInst& insn);
bool
- Emulate_BGEUC (llvm::MCInst& insn);
+ Emulate_BXX_2ops_C (llvm::MCInst& insn);
bool
- Emulate_BLTZC (llvm::MCInst& insn);
+ Emulate_Bcond_Link_C (llvm::MCInst& insn);
bool
- Emulate_BLEZC (llvm::MCInst& insn);
+ Emulate_Bcond_Link (llvm::MCInst& insn);
bool
- Emulate_BGEZC (llvm::MCInst& insn);
+ Emulate_FP_branch (llvm::MCInst& insn);
bool
- Emulate_BGTZC (llvm::MCInst& insn);
+ Emulate_3D_branch (llvm::MCInst& insn);
bool
- Emulate_BEQZC (llvm::MCInst& insn);
-
- bool
- Emulate_BNEZC (llvm::MCInst& insn);
+ Emulate_BAL (llvm::MCInst& insn);
bool
- Emulate_BGEZL (llvm::MCInst& insn);
+ Emulate_BALC (llvm::MCInst& insn);
bool
- Emulate_BGTZ (llvm::MCInst& insn);
+ Emulate_BC (llvm::MCInst& insn);
bool
- Emulate_BGTZL (llvm::MCInst& insn);
+ Emulate_J (llvm::MCInst& insn);
bool
- Emulate_BLEZ (llvm::MCInst& insn);
+ Emulate_JAL (llvm::MCInst& insn);
bool
- Emulate_BLEZL (llvm::MCInst& insn);
+ Emulate_JALR (llvm::MCInst& insn);
bool
- Emulate_BLTZ (llvm::MCInst& insn);
+ Emulate_JIALC (llvm::MCInst& insn);
bool
- Emulate_BLTZAL (llvm::MCInst& insn);
+ Emulate_JIC (llvm::MCInst& insn);
bool
- Emulate_BLTZALL (llvm::MCInst& insn);
+ Emulate_JR (llvm::MCInst& insn);
bool
- Emulate_BLTZL (llvm::MCInst& insn);
+ Emulate_BC1EQZ (llvm::MCInst& insn);
bool
- Emulate_BOVC (llvm::MCInst& insn);
+ Emulate_BC1NEZ (llvm::MCInst& insn);
bool
- Emulate_BNVC (llvm::MCInst& insn);
+ Emulate_BNZB (llvm::MCInst& insn);
bool
- Emulate_J (llvm::MCInst& insn);
+ Emulate_BNZH (llvm::MCInst& insn);
bool
- Emulate_JAL (llvm::MCInst& insn);
+ Emulate_BNZW (llvm::MCInst& insn);
bool
- Emulate_JALR (llvm::MCInst& insn);
+ Emulate_BNZD (llvm::MCInst& insn);
bool
- Emulate_JIALC (llvm::MCInst& insn);
+ Emulate_BZB (llvm::MCInst& insn);
bool
- Emulate_JIC (llvm::MCInst& insn);
+ Emulate_BZH (llvm::MCInst& insn);
bool
- Emulate_JR (llvm::MCInst& insn);
+ Emulate_BZW (llvm::MCInst& insn);
bool
- Emulate_BC1F (llvm::MCInst& insn);
+ Emulate_BZD (llvm::MCInst& insn);
bool
- Emulate_BC1T (llvm::MCInst& insn);
+ Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz);
bool
- Emulate_BC1FL (llvm::MCInst& insn);
+ Emulate_BNZV (llvm::MCInst& insn);
bool
- Emulate_BC1TL (llvm::MCInst& insn);
+ Emulate_BZV (llvm::MCInst& insn);
bool
- Emulate_BC1EQZ (llvm::MCInst& insn);
+ Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz);
bool
- Emulate_BC1NEZ (llvm::MCInst& insn);
+ Emulate_B16_MM (llvm::MCInst& insn);
bool
- Emulate_BC1ANY2F (llvm::MCInst& insn);
+ Emulate_Branch_MM (llvm::MCInst& insn);
bool
- Emulate_BC1ANY2T (llvm::MCInst& insn);
+ Emulate_JALRx16_MM (llvm::MCInst& insn);
bool
- Emulate_BC1ANY4F (llvm::MCInst& insn);
+ Emulate_JALx (llvm::MCInst& insn);
bool
- Emulate_BC1ANY4T (llvm::MCInst& insn);
+ Emulate_JALRS (llvm::MCInst& insn);
bool
nonvolatile_reg_p (uint32_t regnum);
@@ -303,11 +275,15 @@ protected:
private:
std::unique_ptr<llvm::MCDisassembler> m_disasm;
+ std::unique_ptr<llvm::MCDisassembler> m_alt_disasm;
std::unique_ptr<llvm::MCSubtargetInfo> m_subtype_info;
+ std::unique_ptr<llvm::MCSubtargetInfo> m_alt_subtype_info;
std::unique_ptr<llvm::MCRegisterInfo> m_reg_info;
std::unique_ptr<llvm::MCAsmInfo> m_asm_info;
std::unique_ptr<llvm::MCContext> m_context;
std::unique_ptr<llvm::MCInstrInfo> m_insn_info;
+ uint32_t m_next_inst_size;
+ bool m_use_alt_disaasm;
};
#endif // EmulateInstructionMIPS_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
index a574e7d..9c09d38 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
@@ -221,41 +221,76 @@ EmulateInstructionMIPS64::GetRegisterName (unsigned reg_num, bool alternate_name
{
switch (reg_num)
{
- case gcc_dwarf_sp_mips64: return "r29";
- case gcc_dwarf_r30_mips64: return "r30";
- case gcc_dwarf_ra_mips64: return "r31";
- case gcc_dwarf_f0_mips64: return "f0";
- case gcc_dwarf_f1_mips64: return "f1";
- case gcc_dwarf_f2_mips64: return "f2";
- case gcc_dwarf_f3_mips64: return "f3";
- case gcc_dwarf_f4_mips64: return "f4";
- case gcc_dwarf_f5_mips64: return "f5";
- case gcc_dwarf_f6_mips64: return "f6";
- case gcc_dwarf_f7_mips64: return "f7";
- case gcc_dwarf_f8_mips64: return "f8";
- case gcc_dwarf_f9_mips64: return "f9";
- case gcc_dwarf_f10_mips64: return "f10";
- case gcc_dwarf_f11_mips64: return "f11";
- case gcc_dwarf_f12_mips64: return "f12";
- case gcc_dwarf_f13_mips64: return "f13";
- case gcc_dwarf_f14_mips64: return "f14";
- case gcc_dwarf_f15_mips64: return "f15";
- case gcc_dwarf_f16_mips64: return "f16";
- case gcc_dwarf_f17_mips64: return "f17";
- case gcc_dwarf_f18_mips64: return "f18";
- case gcc_dwarf_f19_mips64: return "f19";
- case gcc_dwarf_f20_mips64: return "f20";
- case gcc_dwarf_f21_mips64: return "f21";
- case gcc_dwarf_f22_mips64: return "f22";
- case gcc_dwarf_f23_mips64: return "f23";
- case gcc_dwarf_f24_mips64: return "f24";
- case gcc_dwarf_f25_mips64: return "f25";
- case gcc_dwarf_f26_mips64: return "f26";
- case gcc_dwarf_f27_mips64: return "f27";
- case gcc_dwarf_f28_mips64: return "f28";
- case gcc_dwarf_f29_mips64: return "f29";
- case gcc_dwarf_f30_mips64: return "f30";
- case gcc_dwarf_f31_mips64: return "f31";
+ case dwarf_sp_mips64: return "r29";
+ case dwarf_r30_mips64: return "r30";
+ case dwarf_ra_mips64: return "r31";
+ case dwarf_f0_mips64: return "f0";
+ case dwarf_f1_mips64: return "f1";
+ case dwarf_f2_mips64: return "f2";
+ case dwarf_f3_mips64: return "f3";
+ case dwarf_f4_mips64: return "f4";
+ case dwarf_f5_mips64: return "f5";
+ case dwarf_f6_mips64: return "f6";
+ case dwarf_f7_mips64: return "f7";
+ case dwarf_f8_mips64: return "f8";
+ case dwarf_f9_mips64: return "f9";
+ case dwarf_f10_mips64: return "f10";
+ case dwarf_f11_mips64: return "f11";
+ case dwarf_f12_mips64: return "f12";
+ case dwarf_f13_mips64: return "f13";
+ case dwarf_f14_mips64: return "f14";
+ case dwarf_f15_mips64: return "f15";
+ case dwarf_f16_mips64: return "f16";
+ case dwarf_f17_mips64: return "f17";
+ case dwarf_f18_mips64: return "f18";
+ case dwarf_f19_mips64: return "f19";
+ case dwarf_f20_mips64: return "f20";
+ case dwarf_f21_mips64: return "f21";
+ case dwarf_f22_mips64: return "f22";
+ case dwarf_f23_mips64: return "f23";
+ case dwarf_f24_mips64: return "f24";
+ case dwarf_f25_mips64: return "f25";
+ case dwarf_f26_mips64: return "f26";
+ case dwarf_f27_mips64: return "f27";
+ case dwarf_f28_mips64: return "f28";
+ case dwarf_f29_mips64: return "f29";
+ case dwarf_f30_mips64: return "f30";
+ case dwarf_f31_mips64: return "f31";
+ case dwarf_w0_mips64: return "w0";
+ case dwarf_w1_mips64: return "w1";
+ case dwarf_w2_mips64: return "w2";
+ case dwarf_w3_mips64: return "w3";
+ case dwarf_w4_mips64: return "w4";
+ case dwarf_w5_mips64: return "w5";
+ case dwarf_w6_mips64: return "w6";
+ case dwarf_w7_mips64: return "w7";
+ case dwarf_w8_mips64: return "w8";
+ case dwarf_w9_mips64: return "w9";
+ case dwarf_w10_mips64: return "w10";
+ case dwarf_w11_mips64: return "w11";
+ case dwarf_w12_mips64: return "w12";
+ case dwarf_w13_mips64: return "w13";
+ case dwarf_w14_mips64: return "w14";
+ case dwarf_w15_mips64: return "w15";
+ case dwarf_w16_mips64: return "w16";
+ case dwarf_w17_mips64: return "w17";
+ case dwarf_w18_mips64: return "w18";
+ case dwarf_w19_mips64: return "w19";
+ case dwarf_w20_mips64: return "w20";
+ case dwarf_w21_mips64: return "w21";
+ case dwarf_w22_mips64: return "w22";
+ case dwarf_w23_mips64: return "w23";
+ case dwarf_w24_mips64: return "w24";
+ case dwarf_w25_mips64: return "w25";
+ case dwarf_w26_mips64: return "w26";
+ case dwarf_w27_mips64: return "w27";
+ case dwarf_w28_mips64: return "w28";
+ case dwarf_w29_mips64: return "w29";
+ case dwarf_w30_mips64: return "w30";
+ case dwarf_w31_mips64: return "w31";
+ case dwarf_mir_mips64: return "mir";
+ case dwarf_mcsr_mips64: return "mcsr";
+ case dwarf_config5_mips64: return "config5";
default:
break;
}
@@ -264,78 +299,113 @@ EmulateInstructionMIPS64::GetRegisterName (unsigned reg_num, bool alternate_name
switch (reg_num)
{
- case gcc_dwarf_zero_mips64: return "r0";
- case gcc_dwarf_r1_mips64: return "r1";
- case gcc_dwarf_r2_mips64: return "r2";
- case gcc_dwarf_r3_mips64: return "r3";
- case gcc_dwarf_r4_mips64: return "r4";
- case gcc_dwarf_r5_mips64: return "r5";
- case gcc_dwarf_r6_mips64: return "r6";
- case gcc_dwarf_r7_mips64: return "r7";
- case gcc_dwarf_r8_mips64: return "r8";
- case gcc_dwarf_r9_mips64: return "r9";
- case gcc_dwarf_r10_mips64: return "r10";
- case gcc_dwarf_r11_mips64: return "r11";
- case gcc_dwarf_r12_mips64: return "r12";
- case gcc_dwarf_r13_mips64: return "r13";
- case gcc_dwarf_r14_mips64: return "r14";
- case gcc_dwarf_r15_mips64: return "r15";
- case gcc_dwarf_r16_mips64: return "r16";
- case gcc_dwarf_r17_mips64: return "r17";
- case gcc_dwarf_r18_mips64: return "r18";
- case gcc_dwarf_r19_mips64: return "r19";
- case gcc_dwarf_r20_mips64: return "r20";
- case gcc_dwarf_r21_mips64: return "r21";
- case gcc_dwarf_r22_mips64: return "r22";
- case gcc_dwarf_r23_mips64: return "r23";
- case gcc_dwarf_r24_mips64: return "r24";
- case gcc_dwarf_r25_mips64: return "r25";
- case gcc_dwarf_r26_mips64: return "r26";
- case gcc_dwarf_r27_mips64: return "r27";
- case gcc_dwarf_gp_mips64: return "gp";
- case gcc_dwarf_sp_mips64: return "sp";
- case gcc_dwarf_r30_mips64: return "fp";
- case gcc_dwarf_ra_mips64: return "ra";
- case gcc_dwarf_sr_mips64: return "sr";
- case gcc_dwarf_lo_mips64: return "lo";
- case gcc_dwarf_hi_mips64: return "hi";
- case gcc_dwarf_bad_mips64: return "bad";
- case gcc_dwarf_cause_mips64: return "cause";
- case gcc_dwarf_pc_mips64: return "pc";
- case gcc_dwarf_f0_mips64: return "f0";
- case gcc_dwarf_f1_mips64: return "f1";
- case gcc_dwarf_f2_mips64: return "f2";
- case gcc_dwarf_f3_mips64: return "f3";
- case gcc_dwarf_f4_mips64: return "f4";
- case gcc_dwarf_f5_mips64: return "f5";
- case gcc_dwarf_f6_mips64: return "f6";
- case gcc_dwarf_f7_mips64: return "f7";
- case gcc_dwarf_f8_mips64: return "f8";
- case gcc_dwarf_f9_mips64: return "f9";
- case gcc_dwarf_f10_mips64: return "f10";
- case gcc_dwarf_f11_mips64: return "f11";
- case gcc_dwarf_f12_mips64: return "f12";
- case gcc_dwarf_f13_mips64: return "f13";
- case gcc_dwarf_f14_mips64: return "f14";
- case gcc_dwarf_f15_mips64: return "f15";
- case gcc_dwarf_f16_mips64: return "f16";
- case gcc_dwarf_f17_mips64: return "f17";
- case gcc_dwarf_f18_mips64: return "f18";
- case gcc_dwarf_f19_mips64: return "f19";
- case gcc_dwarf_f20_mips64: return "f20";
- case gcc_dwarf_f21_mips64: return "f21";
- case gcc_dwarf_f22_mips64: return "f22";
- case gcc_dwarf_f23_mips64: return "f23";
- case gcc_dwarf_f24_mips64: return "f24";
- case gcc_dwarf_f25_mips64: return "f25";
- case gcc_dwarf_f26_mips64: return "f26";
- case gcc_dwarf_f27_mips64: return "f27";
- case gcc_dwarf_f28_mips64: return "f28";
- case gcc_dwarf_f29_mips64: return "f29";
- case gcc_dwarf_f30_mips64: return "f30";
- case gcc_dwarf_f31_mips64: return "f31";
- case gcc_dwarf_fcsr_mips64: return "fcsr";
- case gcc_dwarf_fir_mips64: return "fir";
+ case dwarf_zero_mips64: return "r0";
+ case dwarf_r1_mips64: return "r1";
+ case dwarf_r2_mips64: return "r2";
+ case dwarf_r3_mips64: return "r3";
+ case dwarf_r4_mips64: return "r4";
+ case dwarf_r5_mips64: return "r5";
+ case dwarf_r6_mips64: return "r6";
+ case dwarf_r7_mips64: return "r7";
+ case dwarf_r8_mips64: return "r8";
+ case dwarf_r9_mips64: return "r9";
+ case dwarf_r10_mips64: return "r10";
+ case dwarf_r11_mips64: return "r11";
+ case dwarf_r12_mips64: return "r12";
+ case dwarf_r13_mips64: return "r13";
+ case dwarf_r14_mips64: return "r14";
+ case dwarf_r15_mips64: return "r15";
+ case dwarf_r16_mips64: return "r16";
+ case dwarf_r17_mips64: return "r17";
+ case dwarf_r18_mips64: return "r18";
+ case dwarf_r19_mips64: return "r19";
+ case dwarf_r20_mips64: return "r20";
+ case dwarf_r21_mips64: return "r21";
+ case dwarf_r22_mips64: return "r22";
+ case dwarf_r23_mips64: return "r23";
+ case dwarf_r24_mips64: return "r24";
+ case dwarf_r25_mips64: return "r25";
+ case dwarf_r26_mips64: return "r26";
+ case dwarf_r27_mips64: return "r27";
+ case dwarf_gp_mips64: return "gp";
+ case dwarf_sp_mips64: return "sp";
+ case dwarf_r30_mips64: return "fp";
+ case dwarf_ra_mips64: return "ra";
+ case dwarf_sr_mips64: return "sr";
+ case dwarf_lo_mips64: return "lo";
+ case dwarf_hi_mips64: return "hi";
+ case dwarf_bad_mips64: return "bad";
+ case dwarf_cause_mips64: return "cause";
+ case dwarf_pc_mips64: return "pc";
+ case dwarf_f0_mips64: return "f0";
+ case dwarf_f1_mips64: return "f1";
+ case dwarf_f2_mips64: return "f2";
+ case dwarf_f3_mips64: return "f3";
+ case dwarf_f4_mips64: return "f4";
+ case dwarf_f5_mips64: return "f5";
+ case dwarf_f6_mips64: return "f6";
+ case dwarf_f7_mips64: return "f7";
+ case dwarf_f8_mips64: return "f8";
+ case dwarf_f9_mips64: return "f9";
+ case dwarf_f10_mips64: return "f10";
+ case dwarf_f11_mips64: return "f11";
+ case dwarf_f12_mips64: return "f12";
+ case dwarf_f13_mips64: return "f13";
+ case dwarf_f14_mips64: return "f14";
+ case dwarf_f15_mips64: return "f15";
+ case dwarf_f16_mips64: return "f16";
+ case dwarf_f17_mips64: return "f17";
+ case dwarf_f18_mips64: return "f18";
+ case dwarf_f19_mips64: return "f19";
+ case dwarf_f20_mips64: return "f20";
+ case dwarf_f21_mips64: return "f21";
+ case dwarf_f22_mips64: return "f22";
+ case dwarf_f23_mips64: return "f23";
+ case dwarf_f24_mips64: return "f24";
+ case dwarf_f25_mips64: return "f25";
+ case dwarf_f26_mips64: return "f26";
+ case dwarf_f27_mips64: return "f27";
+ case dwarf_f28_mips64: return "f28";
+ case dwarf_f29_mips64: return "f29";
+ case dwarf_f30_mips64: return "f30";
+ case dwarf_f31_mips64: return "f31";
+ case dwarf_fcsr_mips64: return "fcsr";
+ case dwarf_fir_mips64: return "fir";
+ case dwarf_w0_mips64: return "w0";
+ case dwarf_w1_mips64: return "w1";
+ case dwarf_w2_mips64: return "w2";
+ case dwarf_w3_mips64: return "w3";
+ case dwarf_w4_mips64: return "w4";
+ case dwarf_w5_mips64: return "w5";
+ case dwarf_w6_mips64: return "w6";
+ case dwarf_w7_mips64: return "w7";
+ case dwarf_w8_mips64: return "w8";
+ case dwarf_w9_mips64: return "w9";
+ case dwarf_w10_mips64: return "w10";
+ case dwarf_w11_mips64: return "w11";
+ case dwarf_w12_mips64: return "w12";
+ case dwarf_w13_mips64: return "w13";
+ case dwarf_w14_mips64: return "w14";
+ case dwarf_w15_mips64: return "w15";
+ case dwarf_w16_mips64: return "w16";
+ case dwarf_w17_mips64: return "w17";
+ case dwarf_w18_mips64: return "w18";
+ case dwarf_w19_mips64: return "w19";
+ case dwarf_w20_mips64: return "w20";
+ case dwarf_w21_mips64: return "w21";
+ case dwarf_w22_mips64: return "w22";
+ case dwarf_w23_mips64: return "w23";
+ case dwarf_w24_mips64: return "w24";
+ case dwarf_w25_mips64: return "w25";
+ case dwarf_w26_mips64: return "w26";
+ case dwarf_w27_mips64: return "w27";
+ case dwarf_w28_mips64: return "w28";
+ case dwarf_w29_mips64: return "w29";
+ case dwarf_w30_mips64: return "w30";
+ case dwarf_w31_mips64: return "w31";
+ case dwarf_mcsr_mips64: return "mcsr";
+ case dwarf_mir_mips64: return "mir";
+ case dwarf_config5_mips64: return "config5";
}
return nullptr;
}
@@ -347,11 +417,11 @@ EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_n
{
switch (reg_num)
{
- case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_pc_mips64; break;
- case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sp_mips64; break;
- case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_r30_mips64; break;
- case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_ra_mips64; break;
- case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sr_mips64; break;
+ case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc_mips64; break;
+ case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp_mips64; break;
+ case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r30_mips64; break;
+ case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_ra_mips64; break;
+ case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sr_mips64; break;
default:
return false;
}
@@ -362,18 +432,24 @@ EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_n
::memset (&reg_info, 0, sizeof(RegisterInfo));
::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
- if (reg_num == gcc_dwarf_sr_mips64 || reg_num == gcc_dwarf_fcsr_mips64 || reg_num == gcc_dwarf_fir_mips64)
+ if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 || reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 || reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64)
{
reg_info.byte_size = 4;
reg_info.format = eFormatHex;
reg_info.encoding = eEncodingUint;
}
- else if ((int)reg_num >= gcc_dwarf_zero_mips64 && (int)reg_num <= gcc_dwarf_f31_mips64)
+ else if ((int)reg_num >= dwarf_zero_mips64 && (int)reg_num <= dwarf_f31_mips64)
{
reg_info.byte_size = 8;
reg_info.format = eFormatHex;
reg_info.encoding = eEncodingUint;
}
+ else if ((int)reg_num >= dwarf_w0_mips64 && (int)reg_num <= dwarf_w31_mips64)
+ {
+ reg_info.byte_size = 16;
+ reg_info.format = eFormatVectorOfUInt8;
+ reg_info.encoding = eEncodingVector;
+ }
else
{
return false;
@@ -385,11 +461,11 @@ EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_n
switch (reg_num)
{
- case gcc_dwarf_r30_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
- case gcc_dwarf_ra_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
- case gcc_dwarf_sp_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
- case gcc_dwarf_pc_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
- case gcc_dwarf_sr_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;
+ case dwarf_r30_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
+ case dwarf_ra_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
+ case dwarf_sp_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
+ case dwarf_pc_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
+ case dwarf_sr_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;
default: break;
}
return true;
@@ -410,51 +486,108 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name)
{ "SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt,offset(rs)" },
{ "LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt,offset(base)" },
- { "SW", &EmulateInstructionMIPS64::Emulate_SW, "SW rt,offset(rs)" },
- { "LW", &EmulateInstructionMIPS64::Emulate_LW, "LW rt,offset(rs)" },
+
+
+
+ //----------------------------------------------------------------------
+ // Load/Store instructions
+ //----------------------------------------------------------------------
+ /* Following list of emulated instructions are required by implementation of hardware watchpoint
+ for MIPS in lldb. As we just need the address accessed by instructions, we have generalised
+ all these instructions in 2 functions depending on their addressing modes */
+
+ { "LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LB rt, offset(base)" },
+ { "LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBE rt, offset(base)" },
+ { "LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBU rt, offset(base)" },
+ { "LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBUE rt, offset(base)" },
+ { "LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDC1 ft, offset(base)" },
+ { "LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDL rt, offset(base)" },
+ { "LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDR rt, offset(base)" },
+ { "LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LLD rt, offset(base)" },
+ { "LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDC2 rt, offset(base)" },
+ { "LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LDXC1 fd, index (base)" },
+ { "LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LH rt, offset(base)" },
+ { "LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHE rt, offset(base)" },
+ { "LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHU rt, offset(base)" },
+ { "LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHUE rt, offset(base)" },
+ { "LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LL rt, offset(base)" },
+ { "LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LLE rt, offset(base)" },
+ { "LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LUXC1 fd, index (base)" },
+ { "LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LW rt, offset(rs)" },
+ { "LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWC1 ft, offset(base)" },
+ { "LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWC2 rt, offset(base)" },
+ { "LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWE rt, offset(base)" },
+ { "LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWL rt, offset(base)" },
+ { "LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWLE rt, offset(base)" },
+ { "LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWR rt, offset(base)" },
+ { "LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWRE rt, offset(base)" },
+ { "LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LWXC1 fd, index (base)" },
+
+ { "SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SB rt, offset(base)" },
+ { "SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SBE rt, offset(base)" },
+ { "SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SC rt, offset(base)" },
+ { "SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SCE rt, offset(base)" },
+ { "SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SCD rt, offset(base)" },
+ { "SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDL rt, offset(base)" },
+ { "SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDR rt, offset(base)" },
+ { "SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDC1 ft, offset(base)" },
+ { "SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDC2 rt, offset(base)" },
+ { "SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SDXC1 fs, index (base)" },
+ { "SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SH rt, offset(base)" },
+ { "SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SHE rt, offset(base)" },
+ { "SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SUXC1 fs, index (base)" },
+ { "SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SW rt, offset(rs)" },
+ { "SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWC1 ft, offset(base)" },
+ { "SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWC2 rt, offset(base)" },
+ { "SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWE rt, offset(base)" },
+ { "SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWL rt, offset(base)" },
+ { "SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWLE rt, offset(base)" },
+ { "SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWR rt, offset(base)" },
+ { "SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWRE rt, offset(base)" },
+ { "SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SWXC1 fs, index (base)" },
//----------------------------------------------------------------------
// Branch instructions
//----------------------------------------------------------------------
- { "BEQ", &EmulateInstructionMIPS64::Emulate_BEQ, "BEQ rs,rt,offset" },
- { "BNE", &EmulateInstructionMIPS64::Emulate_BNE, "BNE rs,rt,offset" },
- { "BEQL", &EmulateInstructionMIPS64::Emulate_BEQL, "BEQL rs,rt,offset" },
- { "BNEL", &EmulateInstructionMIPS64::Emulate_BNEL, "BNEL rs,rt,offset" },
- { "BGEZALL", &EmulateInstructionMIPS64::Emulate_BGEZALL, "BGEZALL rt,offset" },
+ { "BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset" },
+ { "BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset" },
+ { "BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQL rs,rt,offset" },
+ { "BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNEL rs,rt,offset" },
+ { "BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BGEZALL rt,offset" },
{ "BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset" },
- { "BGEZAL", &EmulateInstructionMIPS64::Emulate_BGEZAL, "BGEZAL rs,offset" },
+ { "BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BGEZAL rs,offset" },
{ "BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset" },
{ "BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset" },
- { "BGEZ", &EmulateInstructionMIPS64::Emulate_BGEZ, "BGEZ rs,offset" },
- { "BLEZALC", &EmulateInstructionMIPS64::Emulate_BLEZALC, "BLEZALC rs,offset" },
- { "BGEZALC", &EmulateInstructionMIPS64::Emulate_BGEZALC, "BGEZALC rs,offset" },
- { "BLTZALC", &EmulateInstructionMIPS64::Emulate_BLTZALC, "BLTZALC rs,offset" },
- { "BGTZALC", &EmulateInstructionMIPS64::Emulate_BGTZALC, "BGTZALC rs,offset" },
- { "BEQZALC", &EmulateInstructionMIPS64::Emulate_BEQZALC, "BEQZALC rs,offset" },
- { "BNEZALC", &EmulateInstructionMIPS64::Emulate_BNEZALC, "BNEZALC rs,offset" },
- { "BEQC", &EmulateInstructionMIPS64::Emulate_BEQC, "BEQC rs,rt,offset" },
- { "BNEC", &EmulateInstructionMIPS64::Emulate_BNEC, "BNEC rs,rt,offset" },
- { "BLTC", &EmulateInstructionMIPS64::Emulate_BLTC, "BLTC rs,rt,offset" },
- { "BGEC", &EmulateInstructionMIPS64::Emulate_BGEC, "BGEC rs,rt,offset" },
- { "BLTUC", &EmulateInstructionMIPS64::Emulate_BLTUC, "BLTUC rs,rt,offset" },
- { "BGEUC", &EmulateInstructionMIPS64::Emulate_BGEUC, "BGEUC rs,rt,offset" },
- { "BLTZC", &EmulateInstructionMIPS64::Emulate_BLTZC, "BLTZC rt,offset" },
- { "BLEZC", &EmulateInstructionMIPS64::Emulate_BLEZC, "BLEZC rt,offset" },
- { "BGEZC", &EmulateInstructionMIPS64::Emulate_BGEZC, "BGEZC rt,offset" },
- { "BGTZC", &EmulateInstructionMIPS64::Emulate_BGTZC, "BGTZC rt,offset" },
- { "BEQZC", &EmulateInstructionMIPS64::Emulate_BEQZC, "BEQZC rt,offset" },
- { "BNEZC", &EmulateInstructionMIPS64::Emulate_BNEZC, "BNEZC rt,offset" },
- { "BGEZL", &EmulateInstructionMIPS64::Emulate_BGEZL, "BGEZL rt,offset" },
- { "BGTZ", &EmulateInstructionMIPS64::Emulate_BGTZ, "BGTZ rt,offset" },
- { "BGTZL", &EmulateInstructionMIPS64::Emulate_BGTZL, "BGTZL rt,offset" },
- { "BLEZ", &EmulateInstructionMIPS64::Emulate_BLEZ, "BLEZ rt,offset" },
- { "BLEZL", &EmulateInstructionMIPS64::Emulate_BLEZL, "BLEZL rt,offset" },
- { "BLTZ", &EmulateInstructionMIPS64::Emulate_BLTZ, "BLTZ rt,offset" },
- { "BLTZAL", &EmulateInstructionMIPS64::Emulate_BLTZAL, "BLTZAL rt,offset" },
- { "BLTZALL", &EmulateInstructionMIPS64::Emulate_BLTZALL, "BLTZALL rt,offset" },
- { "BLTZL", &EmulateInstructionMIPS64::Emulate_BLTZL, "BLTZL rt,offset" },
- { "BOVC", &EmulateInstructionMIPS64::Emulate_BOVC, "BOVC rs,rt,offset" },
- { "BNVC", &EmulateInstructionMIPS64::Emulate_BNVC, "BNVC rs,rt,offset" },
+ { "BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset" },
+ { "BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BLEZALC rs,offset" },
+ { "BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BGEZALC rs,offset" },
+ { "BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BLTZALC rs,offset" },
+ { "BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BGTZALC rs,offset" },
+ { "BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BEQZALC rs,offset" },
+ { "BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BNEZALC rs,offset" },
+ { "BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BEQC rs,rt,offset" },
+ { "BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNEC rs,rt,offset" },
+ { "BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTC rs,rt,offset" },
+ { "BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEC rs,rt,offset" },
+ { "BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTUC rs,rt,offset" },
+ { "BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEUC rs,rt,offset" },
+ { "BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLTZC rt,offset" },
+ { "BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLEZC rt,offset" },
+ { "BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGEZC rt,offset" },
+ { "BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGTZC rt,offset" },
+ { "BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BEQZC rt,offset" },
+ { "BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BNEZC rt,offset" },
+ { "BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset" },
+ { "BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset" },
+ { "BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset" },
+ { "BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset" },
+ { "BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset" },
+ { "BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset" },
+ { "BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZAL rt,offset" },
+ { "BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZALL rt,offset" },
+ { "BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset" },
+ { "BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BOVC rs,rt,offset" },
+ { "BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNVC rs,rt,offset" },
{ "J", &EmulateInstructionMIPS64::Emulate_J, "J target" },
{ "JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target" },
{ "JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target" },
@@ -464,16 +597,26 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name)
{ "JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset" },
{ "JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target" },
{ "JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target" },
- { "BC1F", &EmulateInstructionMIPS64::Emulate_BC1F, "BC1F cc, offset" },
- { "BC1T", &EmulateInstructionMIPS64::Emulate_BC1T, "BC1T cc, offset" },
- { "BC1FL", &EmulateInstructionMIPS64::Emulate_BC1FL, "BC1FL cc, offset" },
- { "BC1TL", &EmulateInstructionMIPS64::Emulate_BC1TL, "BC1TL cc, offset" },
+ { "BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset" },
+ { "BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset" },
+ { "BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1FL cc, offset" },
+ { "BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1TL cc, offset" },
{ "BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ, "BC1EQZ ft, offset" },
{ "BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ, "BC1NEZ ft, offset" },
- { "BC1ANY2F", &EmulateInstructionMIPS64::Emulate_BC1ANY2F, "BC1ANY2F cc, offset" },
- { "BC1ANY2T", &EmulateInstructionMIPS64::Emulate_BC1ANY2T, "BC1ANY2T cc, offset" },
- { "BC1ANY4F", &EmulateInstructionMIPS64::Emulate_BC1ANY4F, "BC1ANY4F cc, offset" },
- { "BC1ANY4T", &EmulateInstructionMIPS64::Emulate_BC1ANY4T, "BC1ANY4T cc, offset" },
+ { "BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY2F cc, offset" },
+ { "BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY2T cc, offset" },
+ { "BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY4F cc, offset" },
+ { "BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY4T cc, offset" },
+ { "BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16" },
+ { "BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16" },
+ { "BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16" },
+ { "BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16" },
+ { "BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16" },
+ { "BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16" },
+ { "BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16" },
+ { "BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16" },
+ { "BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16" },
+ { "BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16" },
};
static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes);
@@ -545,7 +688,7 @@ EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options)
if (auto_advance_pc)
{
- old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
}
@@ -557,7 +700,7 @@ EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options)
if (auto_advance_pc)
{
- new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -566,7 +709,7 @@ EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options)
{
new_pc += 4;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, new_pc))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, new_pc))
return false;
}
}
@@ -584,10 +727,10 @@ EmulateInstructionMIPS64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
const bool can_replace = false;
// Our previous Call Frame Address is the stack pointer
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_sp_mips64, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0);
// Our previous PC is in the RA
- row->SetRegisterLocationToRegister(gcc_dwarf_pc_mips64, gcc_dwarf_ra_mips64, can_replace);
+ row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64, can_replace);
unwind_plan.AppendRow (row);
@@ -595,6 +738,7 @@ EmulateInstructionMIPS64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
unwind_plan.SetSourceName ("EmulateInstructionMIPS64");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+ unwind_plan.SetReturnAddressRegister (dwarf_ra_mips64);
return true;
}
@@ -604,18 +748,18 @@ EmulateInstructionMIPS64::nonvolatile_reg_p (uint64_t regnum)
{
switch (regnum)
{
- case gcc_dwarf_r16_mips64:
- case gcc_dwarf_r17_mips64:
- case gcc_dwarf_r18_mips64:
- case gcc_dwarf_r19_mips64:
- case gcc_dwarf_r20_mips64:
- case gcc_dwarf_r21_mips64:
- case gcc_dwarf_r22_mips64:
- case gcc_dwarf_r23_mips64:
- case gcc_dwarf_gp_mips64:
- case gcc_dwarf_sp_mips64:
- case gcc_dwarf_r30_mips64:
- case gcc_dwarf_ra_mips64:
+ case dwarf_r16_mips64:
+ case dwarf_r17_mips64:
+ case dwarf_r18_mips64:
+ case dwarf_r19_mips64:
+ case dwarf_r20_mips64:
+ case dwarf_r21_mips64:
+ case dwarf_r22_mips64:
+ case dwarf_r23_mips64:
+ case dwarf_gp_mips64:
+ case dwarf_sp_mips64:
+ case dwarf_r30_mips64:
+ case dwarf_ra_mips64:
return true;
default:
return false;
@@ -636,10 +780,10 @@ EmulateInstructionMIPS64::Emulate_DADDiu (llvm::MCInst& insn)
src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
/* Check if this is daddiu sp,<src>,imm16 */
- if (dst == gcc_dwarf_sp_mips64)
+ if (dst == dwarf_sp_mips64)
{
/* read <src> register */
- uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, 0, &success);
+ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
if (!success)
return false;
@@ -647,79 +791,19 @@ EmulateInstructionMIPS64::Emulate_DADDiu (llvm::MCInst& insn)
Context context;
RegisterInfo reg_info_sp;
- if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips64, reg_info_sp))
+ if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp))
context.SetRegisterPlusOffset (reg_info_sp, imm);
/* We are allocating bytes on stack */
context.type = eContextAdjustStackPointer;
- WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips64, result);
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips64, result);
}
return true;
}
bool
-EmulateInstructionMIPS64::Emulate_SW (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t base;
- int64_t imm, address;
- Context bad_vaddr_context;
-
- base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- imm = insn.getOperand(2).getImm();
-
- RegisterInfo reg_info_base;
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base))
- return false;
-
- /* read base register */
- address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
- if (!success)
- return false;
-
- /* destination address */
- address = address + imm;
-
- /* Set the bad_vaddr register with base address used in the instruction */
- bad_vaddr_context.type = eContextInvalid;
- WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address);
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_LW (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t base;
- int64_t imm, address;
- Context bad_vaddr_context;
-
- base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- imm = insn.getOperand(2).getImm();
-
- RegisterInfo reg_info_base;
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base))
- return false;
-
- /* read base register */
- address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
- if (!success)
- return false;
-
- /* destination address */
- address = address + imm;
-
- /* Set the bad_vaddr register with base address used in the instruction */
- bad_vaddr_context.type = eContextInvalid;
- WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address);
-
- return true;
-}
-
-bool
EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
{
uint64_t address;
@@ -734,12 +818,12 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base)
- || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base)
+ || !GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src))
return false;
/* read SP */
- address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success);
if (!success)
return false;
@@ -747,7 +831,7 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
address = address + imm;
/* We look for sp based non-volatile register stores */
- if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
+ if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src))
{
Context context;
RegisterValue data_src;
@@ -769,7 +853,7 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
/* Set the bad_vaddr register with base address used in the instruction */
bad_vaddr_context.type = eContextInvalid;
- WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address);
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address);
return true;
}
@@ -777,17 +861,38 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
bool
EmulateInstructionMIPS64::Emulate_LD (llvm::MCInst& insn)
{
+ bool success =false;
uint32_t src, base;
+ int64_t imm, address;
+ Context bad_vaddr_context;
src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ imm = insn.getOperand(2).getImm();
- if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base))
+ return false;
+
+ /* read base register */
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + imm;
+
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address);
+
+
+ if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src))
{
RegisterValue data_src;
RegisterInfo reg_info_src;
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src))
return false;
Context context;
@@ -802,490 +907,111 @@ EmulateInstructionMIPS64::Emulate_LD (llvm::MCInst& insn)
return false;
}
-bool
-EmulateInstructionMIPS64::Emulate_BEQ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BEQ rs, rt, offset
- * condition <- (GPR[rs] = GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- * else
- * PC = PC + 4
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val == rt_val)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BNE (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BNE rs, rt, offset
- * condition <- (GPR[rs] != GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val != rt_val)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
+/*
+ Emulate below MIPS branch instructions.
+ BEQ, BNE : Branch on condition
+ BEQL, BNEL : Branch likely
+*/
bool
-EmulateInstructionMIPS64::Emulate_BEQL (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BXX_3ops (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
+ int64_t offset, pc, rs_val, rt_val, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BEQL rs, rt, offset
- * condition <- (GPR[rs] = GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val == rt_val)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BNEL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BNEL rs, rt, offset
- * condition <- (GPR[rs] != GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val != rt_val)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEZL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGEZL rs, offset
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTZL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLTZL rs, offset
- * condition <- (GPR[rs] < 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGTZL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGTZL rs, offset
- * condition <- (GPR[rs] > 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val > 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLEZL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLEZL rs, offset
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val <= 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGTZ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGTZ rs, offset
- * condition <- (GPR[rs] > 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val > 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLEZ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLEZ rs, offset
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val <= 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTZ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLTZ rs, offset
- * condition <- (GPR[rs] < 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8;
+ if (!strcasecmp (op_name, "BEQ") ||
+ !strcasecmp (op_name, "BEQL"))
+ {
+ if (rs_val == rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BNE") ||
+ !strcasecmp (op_name, "BNEL"))
+ {
+ if (rs_val != rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
Context context;
context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (offset);
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
}
+/*
+ Emulate below MIPS Non-Compact conditional branch and link instructions.
+ BLTZAL, BGEZAL :
+ BLTZALL, BGEZALL : Branch likely
+*/
bool
-EmulateInstructionMIPS64::Emulate_BGEZALL (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_Bcond_Link (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs;
- int64_t offset, pc, target;
+ int64_t offset, pc, target = 0;
int64_t rs_val;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BGEZALL rt, offset
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
+ if (!strcasecmp (op_name, "BLTZAL") ||
+ !strcasecmp (op_name, "BLTZALL"))
+ {
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BGEZAL") ||
+ !strcasecmp (op_name, "BGEZALL"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
Context context;
- context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
return false;
return true;
@@ -1305,7 +1031,7 @@ EmulateInstructionMIPS64::Emulate_BAL (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -1313,10 +1039,10 @@ EmulateInstructionMIPS64::Emulate_BAL (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
return false;
return true;
@@ -1336,7 +1062,7 @@ EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -1344,434 +1070,154 @@ EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEZAL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGEZAL rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * RA = PC + 8
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if ((int64_t) rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTZAL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLTZAL rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] < 0)
- * if condition then
- * RA = PC + 8
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if ((int64_t) rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
return false;
return true;
}
+/*
+ Emulate below MIPS conditional branch and link instructions.
+ BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
+*/
bool
-EmulateInstructionMIPS64::Emulate_BLTZALL (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_Bcond_Link_C (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
+ int64_t offset, pc, rs_val, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BLTZALL rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] < 0)
- * if condition then
- * RA = PC + 8
- * PC = PC + offset
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- Context context;
-
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
- return false;
-
- return true;
-}
-
-
-bool
-EmulateInstructionMIPS64::Emulate_BLEZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLEZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if (rs_val <= 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGEZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLTZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] < 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGTZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGTZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] > 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if (rs_val > 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BEQZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target, rs_val;
-
- /*
- * BEQZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] == 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
+ if (!strcasecmp (op_name, "BLEZALC"))
+ {
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEZALC"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLTZALC"))
+ {
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGTZALC"))
+ {
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BEQZALC"))
+ {
+ if (rs_val == 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNEZALC"))
+ {
+ if (rs_val != 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
Context context;
- if (rs_val == 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
return false;
return true;
}
+/*
+ Emulate below MIPS branch instructions.
+ BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
+ BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
+*/
bool
-EmulateInstructionMIPS64::Emulate_BNEZALC (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BXX_2ops (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs;
- int64_t offset, pc, target, rs_val;
+ int64_t offset, pc, rs_val, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BNEZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] != 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- Context context;
-
- if (rs_val != 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEZ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target, rs_val;
-
- /*
- * BGEZ rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
+ if (!strcasecmp (op_name, "BLTZL") ||
+ !strcasecmp (op_name, "BLTZ"))
+ {
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BGEZL") ||
+ !strcasecmp (op_name, "BGEZ"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BGTZL") ||
+ !strcasecmp (op_name, "BGTZ"))
+ {
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BLEZL") ||
+ !strcasecmp (op_name, "BLEZ"))
+ {
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
Context context;
+ context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (offset);
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1790,7 +1236,7 @@ EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -1798,503 +1244,7 @@ EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BEQC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BEQC rs, rt, offset
- * condition <- (GPR[rs] = GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val == rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BNEC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BNEC rs, rt, offset
- * condition <- (GPR[rs] != GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val != rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target;
- int64_t rs_val, rt_val;
-
- /*
- * BLTC rs, rt, offset
- * condition <- (GPR[rs] < GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val < rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target;
- int64_t rs_val, rt_val;
-
- /*
- * BGEC rs, rt, offset
- * condition <- (GPR[rs] > GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val > rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTUC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target;
- uint64_t rs_val, rt_val;
-
- /*
- * BLTUC rs, rt, offset
- * condition <- (GPR[rs] < GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val < rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEUC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target;
- uint64_t rs_val, rt_val;
-
- /*
- * BGEUC rs, rt, offset
- * condition <- (GPR[rs] > GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val > rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLTZC rs, offset
- * condition <- (GPR[rs] < 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val < 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLEZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLEZC rs, offset
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val <= 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGEZC rs, offset
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val >= 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGTZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGTZC rs, offset
- * condition <- (GPR[rs] > 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val > 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BEQZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- uint64_t rs_val;
-
- /*
- * BEQZC rs, offset
- * condition <- (GPR[rs] = 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val == 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BNEZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- uint64_t rs_val;
-
- /*
- * BNEZC rs, offset
- * condition <- (GPR[rs] != 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val != 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2307,89 +1257,175 @@ IsAdd64bitOverflow (int64_t a, int64_t b)
return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
}
+/*
+ Emulate below MIPS branch instructions.
+ BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch instructions with no delay slot
+*/
bool
-EmulateInstructionMIPS64::Emulate_BOVC (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BXX_3ops_C (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs, rt;
- int64_t offset, pc, target;
- int64_t rs_val, rt_val;
+ int64_t offset, pc, rs_val, rt_val, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+ uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
- /*
- * BOVC rs, rt, offset
- * condition <- overflow(GPR[rs] + GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
- if (IsAdd64bitOverflow (rs_val, rt_val))
- target = pc + offset;
- else
- target = pc + 4;
+ if (!strcasecmp (op_name, "BEQC"))
+ {
+ if (rs_val == rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNEC"))
+ {
+ if (rs_val != rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLTC"))
+ {
+ if (rs_val < rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEC"))
+ {
+ if (rs_val >= rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLTUC"))
+ {
+ if (rs_val < rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEUC"))
+ {
+ if ((uint32_t)rs_val >= (uint32_t)rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BOVC"))
+ {
+ if (IsAdd64bitOverflow (rs_val, rt_val))
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNVC"))
+ {
+ if (!IsAdd64bitOverflow (rs_val, rt_val))
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
Context context;
context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (current_inst_size + offset);
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
}
+/*
+ Emulate below MIPS branch instructions.
+ BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
+*/
bool
-EmulateInstructionMIPS64::Emulate_BNVC (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BXX_2ops_C (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target;
- int64_t rs_val, rt_val;
+ uint32_t rs;
+ int64_t offset, pc, target = 0;
+ int64_t rs_val;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+ uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
- /*
- * BNVC rs, rt, offset
- * condition <- overflow(GPR[rs] + GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
+ offset = insn.getOperand(1).getImm();
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- if (! IsAdd64bitOverflow (rs_val, rt_val))
- target = pc + offset;
- else
- target = pc + 4;
+ if (!strcasecmp (op_name, "BLTZC"))
+ {
+ if (rs_val < 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLEZC"))
+ {
+ if (rs_val <= 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEZC"))
+ {
+ if (rs_val >= 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGTZC"))
+ {
+ if (rs_val > 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BEQZC"))
+ {
+ if (rs_val == 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNEZC"))
+ {
+ if (rs_val != 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
Context context;
context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (current_inst_size + offset);
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2408,7 +1444,7 @@ EmulateInstructionMIPS64::Emulate_J (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -2417,7 +1453,7 @@ EmulateInstructionMIPS64::Emulate_J (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, pc))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, pc))
return false;
return true;
@@ -2436,7 +1472,7 @@ EmulateInstructionMIPS64::Emulate_JAL (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -2445,10 +1481,10 @@ EmulateInstructionMIPS64::Emulate_JAL (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
return false;
return true;
@@ -2469,20 +1505,20 @@ EmulateInstructionMIPS64::Emulate_JALR (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, rs_val))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + rt, pc + 8))
return false;
return true;
@@ -2504,11 +1540,11 @@ EmulateInstructionMIPS64::Emulate_JIALC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -2516,10 +1552,10 @@ EmulateInstructionMIPS64::Emulate_JIALC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
return false;
return true;
@@ -2540,7 +1576,7 @@ EmulateInstructionMIPS64::Emulate_JIC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -2548,7 +1584,7 @@ EmulateInstructionMIPS64::Emulate_JIC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2567,25 +1603,31 @@ EmulateInstructionMIPS64::Emulate_JR (llvm::MCInst& insn)
*/
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, rs_val))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val))
return false;
return true;
}
+/*
+ Emulate Branch on FP True/False
+ BC1F, BC1FL : Branch on FP False (L stands for branch likely)
+ BC1T, BC1TL : Branch on FP True (L stands for branch likely)
+*/
bool
-EmulateInstructionMIPS64::Emulate_BC1F (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_FP_branch (llvm::MCInst& insn)
{
bool success = false;
uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
+ int64_t pc, offset, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+
/*
* BC1F cc, offset
* condition <- (FPConditionCode(cc) == 0)
@@ -2595,404 +1637,411 @@ EmulateInstructionMIPS64::Emulate_BC1F (llvm::MCInst& insn)
*/
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
if (!success)
return false;
/* fcsr[23], fcsr[25-31] are vaild condition bits */
fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
- if ((fcsr & (1 << cc)) == 0)
- target = pc + offset;
- else
- target = pc + 8;
-
+ if (!strcasecmp (op_name, "BC1F") ||
+ !strcasecmp (op_name, "BC1FL"))
+ {
+ if ((fcsr & (1 << cc)) == 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1T") ||
+ !strcasecmp (op_name, "BC1TL"))
+ {
+ if ((fcsr & (1 << cc)) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
}
bool
-EmulateInstructionMIPS64::Emulate_BC1T (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BC1EQZ (llvm::MCInst& insn)
{
bool success = false;
- uint32_t cc, fcsr;
+ uint32_t ft;
+ uint64_t ft_val;
int64_t target, pc, offset;
/*
- * BC1T cc, offset
- * condition <- (FPConditionCode(cc) != 0)
+ * BC1EQZ ft, offset
+ * condition <- (FPR[ft].bit0 == 0)
* if condition then
* offset = sign_ext (offset)
- * PC = PC + offset
+ * PC = PC + 4 + offset
*/
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success);
if (!success)
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- if ((fcsr & (1 << cc)) != 0)
- target = pc + offset;
+ if ((ft_val & 1) == 0)
+ target = pc + 4 + offset;
else
target = pc + 8;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
}
bool
-EmulateInstructionMIPS64::Emulate_BC1FL (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn)
{
bool success = false;
- uint32_t cc, fcsr;
+ uint32_t ft;
+ uint64_t ft_val;
int64_t target, pc, offset;
/*
- * BC1F cc, offset
- * condition <- (FPConditionCode(cc) == 0)
+ * BC1NEZ ft, offset
+ * condition <- (FPR[ft].bit0 != 0)
* if condition then
* offset = sign_ext (offset)
- * PC = PC + offset
+ * PC = PC + 4 + offset
*/
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success);
if (!success)
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- if ((fcsr & (1 << cc)) == 0)
- target = pc + offset;
+ if ((ft_val & 1) != 0)
+ target = pc + 4 + offset;
else
- target = pc + 8; /* skip delay slot */
+ target = pc + 8;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
}
+/*
+ Emulate MIPS-3D Branch instructions
+ BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes False/True
+ BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes False/True
+*/
bool
-EmulateInstructionMIPS64::Emulate_BC1TL (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_3D_branch (llvm::MCInst& insn)
{
bool success = false;
uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1T cc, offset
- * condition <- (FPConditionCode(cc) != 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
+ int64_t pc, offset, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
if (!success)
return false;
/* fcsr[23], fcsr[25-31] are vaild condition bits */
fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- if ((fcsr & (1 << cc)) != 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
+
+ if (!strcasecmp (op_name, "BC1ANY2F"))
+ {
+ /* if any one bit is 0 */
+ if (((fcsr >> cc) & 3) != 3)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1ANY2T"))
+ {
+ /* if any one bit is 1 */
+ if (((fcsr >> cc) & 3) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1ANY4F"))
+ {
+ /* if any one bit is 0 */
+ if (((fcsr >> cc) & 0xf) != 0xf)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1ANY4T"))
+ {
+ /* if any one bit is 1 */
+ if (((fcsr >> cc) & 0xf) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
}
bool
-EmulateInstructionMIPS64::Emulate_BC1EQZ (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BNZB (llvm::MCInst& insn)
{
- bool success = false;
- uint32_t ft;
- uint64_t ft_val;
- int64_t target, pc, offset;
-
- /*
- * BC1EQZ ft, offset
- * condition <- (FPR[ft].bit0 == 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + 4 + offset
- */
- ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + ft, 0, &success);
- if (!success)
- return false;
-
- if ((ft_val & 1) == 0)
- target = pc + 4 + offset;
- else
- target = pc + 8;
-
- Context context;
+ return Emulate_MSA_Branch_DF(insn, 1, true);
+}
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
+bool
+EmulateInstructionMIPS64::Emulate_BNZH (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 2, true);
+}
- return true;
+bool
+EmulateInstructionMIPS64::Emulate_BNZW (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 4, true);
}
bool
-EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BNZD (llvm::MCInst& insn)
{
- bool success = false;
- uint32_t ft;
- uint64_t ft_val;
- int64_t target, pc, offset;
-
- /*
- * BC1NEZ ft, offset
- * condition <- (FPR[ft].bit0 != 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + 4 + offset
- */
- ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
+ return Emulate_MSA_Branch_DF(insn, 8, true);
+}
- ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + ft, 0, &success);
- if (!success)
- return false;
+bool
+EmulateInstructionMIPS64::Emulate_BZB (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 1, false);
+}
- if ((ft_val & 1) != 0)
- target = pc + 4 + offset;
- else
- target = pc + 8;
-
- Context context;
+bool
+EmulateInstructionMIPS64::Emulate_BZH (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 2, false);
+}
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
+bool
+EmulateInstructionMIPS64::Emulate_BZW (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 4, false);
+}
- return true;
+bool
+EmulateInstructionMIPS64::Emulate_BZD (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 8, false);
}
bool
-EmulateInstructionMIPS64::Emulate_BC1ANY2F (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz)
{
- bool success = false;
- uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1ANY2F cc, offset
- * condition <- (FPConditionCode(cc) == 0
- * || FPConditionCode(cc+1) == 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ bool success = false, branch_hit = true;
+ int64_t target = 0;
+ RegisterValue reg_value;
+ uint8_t * ptr = NULL;
+
+ uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ int64_t offset = insn.getOperand(1).getImm();
+
+ int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
- if (!success)
+ if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
+ ptr = (uint8_t *)reg_value.GetBytes();
+ else
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+ for(int i = 0; i < 16 / element_byte_size; i++)
+ {
+ switch(element_byte_size)
+ {
+ case 1:
+ if((*ptr == 0 && bnz) || (*ptr != 0 && !bnz) )
+ branch_hit = false;
+ break;
+ case 2:
+ if((*(uint16_t *)ptr == 0 && bnz) || (*(uint16_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ case 4:
+ if((*(uint32_t *)ptr == 0 && bnz) || (*(uint32_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ case 8:
+ if((*(uint64_t *)ptr == 0 && bnz) || (*(uint64_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ }
+ if(!branch_hit)
+ break;
+ ptr = ptr + element_byte_size;
+ }
- /* if any one bit is 0 */
- if (((fcsr >> cc) & 3) != 3)
+ if(branch_hit)
target = pc + offset;
else
target = pc + 8;
-
+
Context context;
+ context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
}
bool
-EmulateInstructionMIPS64::Emulate_BC1ANY2T (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BNZV (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_V (insn, true);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BZV (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_V (insn, false);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz)
{
bool success = false;
- uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1ANY2T cc, offset
- * condition <- (FPConditionCode(cc) == 1
- * || FPConditionCode(cc+1) == 1)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
+ int64_t target = 0;
+ llvm::APInt wr_val = llvm::APInt::getNullValue(128);
+ llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
+ llvm::APInt zero_value = llvm::APInt::getNullValue(128);
+ RegisterValue reg_value;
+
+ uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ int64_t offset = insn.getOperand(1).getImm();
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+ if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
+ wr_val = reg_value.GetAsUInt128(fail_value);
+ else
+ return false;
- /* if any one bit is 1 */
- if (((fcsr >> cc) & 3) != 0)
+ if((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
target = pc + offset;
else
target = pc + 8;
-
+
Context context;
+ context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
}
bool
-EmulateInstructionMIPS64::Emulate_BC1ANY4F (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_LDST_Imm (llvm::MCInst& insn)
{
bool success = false;
- uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1ANY4F cc, offset
- * condition <- (FPConditionCode(cc) == 0
- * || FPConditionCode(cc+1) == 0)
- * || FPConditionCode(cc+2) == 0)
- * || FPConditionCode(cc+3) == 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
+ uint32_t base;
+ int64_t imm, address;
+ Context bad_vaddr_context;
+
+ uint32_t num_operands = insn.getNumOperands();
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
+ imm = insn.getOperand(num_operands-1).getImm();
+
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ /* read base register */
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
if (!success)
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- /* if any one bit is 0 */
- if (((fcsr >> cc) & 0xf) != 0xf)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
+ /* destination address */
+ address = address + imm;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
return true;
}
bool
-EmulateInstructionMIPS64::Emulate_BC1ANY4T (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_LDST_Reg (llvm::MCInst& insn)
{
bool success = false;
- uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1ANY4T cc, offset
- * condition <- (FPConditionCode(cc) == 1
- * || FPConditionCode(cc+1) == 1)
- * || FPConditionCode(cc+2) == 1)
- * || FPConditionCode(cc+3) == 1)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
- if (!success)
+ uint32_t base, index;
+ int64_t address, index_address;
+ Context bad_vaddr_context;
+
+ uint32_t num_operands = insn.getNumOperands();
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
+ index = m_reg_info->getEncodingValue (insn.getOperand(num_operands-1).getReg());
+
+ RegisterInfo reg_info_base, reg_info_index;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + index, reg_info_index))
+ return false;
+
+ /* read base register */
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
if (!success)
return false;
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+ /* read index register */
+ index_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success);
+ if (!success)
+ return false;
- /* if any one bit is 1 */
- if (((fcsr >> cc) & 0xf) != 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
+ /* destination address */
+ address = address + index_address;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
- return false;
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
return true;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
index faefd32..4ca274c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
@@ -1,4 +1,4 @@
-//===-- EmulateInstructionMIPS64.h ------------------------------------*- C++ -*-===//
+//===-- EmulateInstructionMIPS64.h ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,6 +10,14 @@
#ifndef EmulateInstructionMIPS64_h_
#define EmulateInstructionMIPS64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Interpreter/OptionValue.h"
+
namespace llvm
{
class MCDisassembler;
@@ -19,15 +27,13 @@ namespace llvm
class MCContext;
class MCInstrInfo;
class MCInst;
-}
-
-#include "lldb/Core/EmulateInstruction.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Interpreter/OptionValue.h"
+} // namespace llvm
class EmulateInstructionMIPS64 : public lldb_private::EmulateInstruction
{
public:
+ EmulateInstructionMIPS64(const lldb_private::ArchSpec &arch);
+
static void
Initialize ();
@@ -60,57 +66,47 @@ public:
return false;
}
- virtual lldb_private::ConstString
- GetPluginName();
-
- virtual lldb_private::ConstString
- GetShortPluginName()
- {
- return GetPluginNameStatic();
- }
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion()
+ uint32_t
+ GetPluginVersion() override
{
return 1;
}
bool
- SetTargetTriple (const lldb_private::ArchSpec &arch);
+ SetTargetTriple(const lldb_private::ArchSpec &arch) override;
- EmulateInstructionMIPS64 (const lldb_private::ArchSpec &arch);
-
- virtual bool
- SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type)
+ bool
+ SupportsEmulatingInstructionsOfType(lldb_private::InstructionType inst_type) override
{
return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
}
- virtual bool
- ReadInstruction ();
+ bool
+ ReadInstruction() override;
- virtual bool
- EvaluateInstruction (uint32_t evaluate_options);
+ bool
+ EvaluateInstruction(uint32_t evaluate_options) override;
- virtual bool
- TestEmulation (lldb_private::Stream *out_stream,
- lldb_private::ArchSpec &arch,
- lldb_private::OptionValueDictionary *test_data)
+ bool
+ TestEmulation(lldb_private::Stream *out_stream,
+ lldb_private::ArchSpec &arch,
+ lldb_private::OptionValueDictionary *test_data) override
{
return false;
}
- virtual bool
- GetRegisterInfo (lldb::RegisterKind reg_kind,
- uint32_t reg_num,
- lldb_private::RegisterInfo &reg_info);
-
- virtual bool
- CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ GetRegisterInfo(lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ lldb_private::RegisterInfo &reg_info) override;
+ bool
+ CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override;
protected:
-
typedef struct
{
const char *op_name;
@@ -128,178 +124,106 @@ protected:
Emulate_SD (llvm::MCInst& insn);
bool
- Emulate_SW (llvm::MCInst& insn);
-
- bool
- Emulate_LW (llvm::MCInst& insn);
-
- bool
Emulate_LD (llvm::MCInst& insn);
bool
- Emulate_BEQ (llvm::MCInst& insn);
-
- bool
- Emulate_BNE (llvm::MCInst& insn);
-
- bool
- Emulate_BEQL (llvm::MCInst& insn);
-
- bool
- Emulate_BNEL (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZALL (llvm::MCInst& insn);
-
- bool
- Emulate_BAL (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZAL (llvm::MCInst& insn);
-
- bool
- Emulate_BALC (llvm::MCInst& insn);
-
- bool
- Emulate_BC (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZ (llvm::MCInst& insn);
+ Emulate_LDST_Imm (llvm::MCInst& insn);
bool
- Emulate_BLEZALC (llvm::MCInst& insn);
+ Emulate_LDST_Reg (llvm::MCInst& insn);
bool
- Emulate_BGEZALC (llvm::MCInst& insn);
+ Emulate_BXX_3ops (llvm::MCInst& insn);
bool
- Emulate_BLTZALC (llvm::MCInst& insn);
+ Emulate_BXX_3ops_C (llvm::MCInst& insn);
bool
- Emulate_BGTZALC (llvm::MCInst& insn);
+ Emulate_BXX_2ops (llvm::MCInst& insn);
bool
- Emulate_BEQZALC (llvm::MCInst& insn);
+ Emulate_BXX_2ops_C (llvm::MCInst& insn);
bool
- Emulate_BNEZALC (llvm::MCInst& insn);
+ Emulate_Bcond_Link_C (llvm::MCInst& insn);
bool
- Emulate_BEQC (llvm::MCInst& insn);
+ Emulate_Bcond_Link (llvm::MCInst& insn);
bool
- Emulate_BNEC (llvm::MCInst& insn);
+ Emulate_FP_branch (llvm::MCInst& insn);
bool
- Emulate_BLTC (llvm::MCInst& insn);
+ Emulate_3D_branch (llvm::MCInst& insn);
bool
- Emulate_BGEC (llvm::MCInst& insn);
-
- bool
- Emulate_BLTUC (llvm::MCInst& insn);
-
- bool
- Emulate_BGEUC (llvm::MCInst& insn);
-
- bool
- Emulate_BLTZC (llvm::MCInst& insn);
-
- bool
- Emulate_BLEZC (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZC (llvm::MCInst& insn);
-
- bool
- Emulate_BGTZC (llvm::MCInst& insn);
-
- bool
- Emulate_BEQZC (llvm::MCInst& insn);
-
- bool
- Emulate_BNEZC (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZL (llvm::MCInst& insn);
-
- bool
- Emulate_BGTZ (llvm::MCInst& insn);
-
- bool
- Emulate_BGTZL (llvm::MCInst& insn);
-
- bool
- Emulate_BLEZ (llvm::MCInst& insn);
-
- bool
- Emulate_BLEZL (llvm::MCInst& insn);
+ Emulate_BAL (llvm::MCInst& insn);
bool
- Emulate_BLTZ (llvm::MCInst& insn);
+ Emulate_BALC (llvm::MCInst& insn);
bool
- Emulate_BLTZAL (llvm::MCInst& insn);
+ Emulate_BC (llvm::MCInst& insn);
bool
- Emulate_BLTZALL (llvm::MCInst& insn);
+ Emulate_J (llvm::MCInst& insn);
bool
- Emulate_BLTZL (llvm::MCInst& insn);
+ Emulate_JAL (llvm::MCInst& insn);
bool
- Emulate_BOVC (llvm::MCInst& insn);
+ Emulate_JALR (llvm::MCInst& insn);
bool
- Emulate_BNVC (llvm::MCInst& insn);
+ Emulate_JIALC (llvm::MCInst& insn);
bool
- Emulate_J (llvm::MCInst& insn);
+ Emulate_JIC (llvm::MCInst& insn);
bool
- Emulate_JAL (llvm::MCInst& insn);
+ Emulate_JR (llvm::MCInst& insn);
bool
- Emulate_JALR (llvm::MCInst& insn);
+ Emulate_BC1EQZ (llvm::MCInst& insn);
bool
- Emulate_JIALC (llvm::MCInst& insn);
+ Emulate_BC1NEZ (llvm::MCInst& insn);
bool
- Emulate_JIC (llvm::MCInst& insn);
+ Emulate_BNZB (llvm::MCInst& insn);
bool
- Emulate_JR (llvm::MCInst& insn);
+ Emulate_BNZH (llvm::MCInst& insn);
bool
- Emulate_BC1F (llvm::MCInst& insn);
+ Emulate_BNZW (llvm::MCInst& insn);
bool
- Emulate_BC1T (llvm::MCInst& insn);
+ Emulate_BNZD (llvm::MCInst& insn);
bool
- Emulate_BC1FL (llvm::MCInst& insn);
+ Emulate_BZB (llvm::MCInst& insn);
bool
- Emulate_BC1TL (llvm::MCInst& insn);
+ Emulate_BZH (llvm::MCInst& insn);
bool
- Emulate_BC1EQZ (llvm::MCInst& insn);
+ Emulate_BZW (llvm::MCInst& insn);
bool
- Emulate_BC1NEZ (llvm::MCInst& insn);
+ Emulate_BZD (llvm::MCInst& insn);
bool
- Emulate_BC1ANY2F (llvm::MCInst& insn);
+ Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz);
bool
- Emulate_BC1ANY2T (llvm::MCInst& insn);
+ Emulate_BNZV (llvm::MCInst& insn);
bool
- Emulate_BC1ANY4F (llvm::MCInst& insn);
+ Emulate_BZV (llvm::MCInst& insn);
bool
- Emulate_BC1ANY4T (llvm::MCInst& insn);
+ Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz);
bool
nonvolatile_reg_p (uint64_t regnum);
@@ -316,4 +240,4 @@ private:
std::unique_ptr<llvm::MCInstrInfo> m_insn_info;
};
-#endif // EmulateInstructionMIPS64_h_
+#endif // EmulateInstructionMIPS64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp b/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
index 9b72ceb..c2f1f2e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
@@ -66,9 +66,11 @@ AddressSanitizerRuntime::GetTypeStatic()
AddressSanitizerRuntime::AddressSanitizerRuntime(const ProcessSP &process_sp) :
m_is_active(false),
m_runtime_module(),
- m_process(process_sp),
+ m_process_wp(),
m_breakpoint_id(0)
{
+ if (process_sp)
+ m_process_wp = process_sp;
}
AddressSanitizerRuntime::~AddressSanitizerRuntime()
@@ -78,14 +80,11 @@ AddressSanitizerRuntime::~AddressSanitizerRuntime()
bool ModuleContainsASanRuntime(Module * module)
{
- SymbolContextList sc_list;
- const bool include_symbols = true;
- const bool append = true;
- const bool include_inlines = true;
-
- size_t num_matches = module->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list);
-
- return num_matches > 0;
+ const Symbol* symbol = module->FindFirstSymbolWithNameAndType(
+ ConstString("__asan_get_alloc_stack"),
+ lldb::eSymbolTypeAny);
+
+ return symbol != nullptr;
}
void
@@ -164,7 +163,11 @@ t
StructuredData::ObjectSP
AddressSanitizerRuntime::RetrieveReportData()
{
- ThreadSP thread_sp = m_process->GetThreadList().GetSelectedThread();
+ ProcessSP process_sp = GetProcessSP();
+ if (!process_sp)
+ return StructuredData::ObjectSP();
+
+ ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();
StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
if (!frame_sp)
@@ -178,7 +181,7 @@ AddressSanitizerRuntime::RetrieveReportData()
options.SetTimeoutUsec(RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC);
ValueObjectSP return_value_sp;
- if (m_process->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
+ if (process_sp->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
return StructuredData::ObjectSP();
int present = return_value_sp->GetValueForExpressionPath(".present")->GetValueAsUnsigned(0);
@@ -196,7 +199,7 @@ AddressSanitizerRuntime::RetrieveReportData()
addr_t description_ptr = return_value_sp->GetValueForExpressionPath(".description")->GetValueAsUnsigned(0);
std::string description;
Error error;
- m_process->ReadCStringFromMemory(description_ptr, description, error);
+ process_sp->ReadCStringFromMemory(description_ptr, description, error);
StructuredData::Dictionary *dict = new StructuredData::Dictionary();
dict->AddStringItem("instrumentation_class", "AddressSanitizer");
@@ -252,27 +255,31 @@ AddressSanitizerRuntime::NotifyBreakpointHit(void *baton, StoppointCallbackConte
assert (baton && "null baton");
if (!baton)
return false;
-
+
AddressSanitizerRuntime *const instance = static_cast<AddressSanitizerRuntime*>(baton);
-
+
StructuredData::ObjectSP report = instance->RetrieveReportData();
std::string description;
if (report) {
description = instance->FormatDescription(report);
}
- ThreadSP thread = context->exe_ctx_ref.GetThreadSP();
- thread->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread, description.c_str(), report));
-
- if (instance->m_process)
+ ProcessSP process_sp = instance->GetProcessSP();
+ // Make sure this is the right process
+ if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP())
{
- StreamFileSP stream_sp (instance->m_process->GetTarget().GetDebugger().GetOutputFile());
+ ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
+ if (thread_sp)
+ thread_sp->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread_sp, description.c_str(), report));
+
+ StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile());
if (stream_sp)
{
stream_sp->Printf ("AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.\n");
}
+ return true; // Return true to stop the target
}
- // Return true to stop the target, false to just let the target run.
- return true;
+ else
+ return false; // Let target run
}
void
@@ -281,6 +288,10 @@ AddressSanitizerRuntime::Activate()
if (m_is_active)
return;
+ ProcessSP process_sp = GetProcessSP();
+ if (!process_sp)
+ return;
+
ConstString symbol_name ("__asan::AsanDie()");
const Symbol *symbol = m_runtime_module->FindFirstSymbolWithNameAndType (symbol_name, eSymbolTypeCode);
@@ -290,7 +301,7 @@ AddressSanitizerRuntime::Activate()
if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())
return;
- Target &target = m_process->GetTarget();
+ Target &target = process_sp->GetTarget();
addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);
if (symbol_address == LLDB_INVALID_ADDRESS)
@@ -298,18 +309,15 @@ AddressSanitizerRuntime::Activate()
bool internal = true;
bool hardware = false;
- Breakpoint *breakpoint = m_process->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get();
+ Breakpoint *breakpoint = process_sp->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get();
breakpoint->SetCallback (AddressSanitizerRuntime::NotifyBreakpointHit, this, true);
breakpoint->SetBreakpointKind ("address-sanitizer-report");
m_breakpoint_id = breakpoint->GetID();
- if (m_process)
+ StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile());
+ if (stream_sp)
{
- StreamFileSP stream_sp (m_process->GetTarget().GetDebugger().GetOutputFile());
- if (stream_sp)
- {
- stream_sp->Printf ("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n");
- }
+ stream_sp->Printf ("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n");
}
m_is_active = true;
@@ -320,8 +328,12 @@ AddressSanitizerRuntime::Deactivate()
{
if (m_breakpoint_id != LLDB_INVALID_BREAK_ID)
{
- m_process->GetTarget().RemoveBreakpointByID(m_breakpoint_id);
- m_breakpoint_id = LLDB_INVALID_BREAK_ID;
+ ProcessSP process_sp = GetProcessSP();
+ if (process_sp)
+ {
+ process_sp->GetTarget().RemoveBreakpointByID(m_breakpoint_id);
+ m_breakpoint_id = LLDB_INVALID_BREAK_ID;
+ }
}
m_is_active = false;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h b/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h
index 69c134c..fe12ab8 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h
@@ -10,6 +10,10 @@
#ifndef liblldb_AddressSanitizerRuntime_h_
#define liblldb_AddressSanitizerRuntime_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/InstrumentationRuntime.h"
@@ -21,7 +25,8 @@ namespace lldb_private {
class AddressSanitizerRuntime : public lldb_private::InstrumentationRuntime
{
public:
-
+ ~AddressSanitizerRuntime() override;
+
static lldb::InstrumentationRuntimeSP
CreateInstance (const lldb::ProcessSP &process_sp);
@@ -36,29 +41,37 @@ public:
static lldb::InstrumentationRuntimeType
GetTypeStatic();
-
- virtual
- ~AddressSanitizerRuntime();
-
- virtual lldb_private::ConstString
- GetPluginName() { return GetPluginNameStatic(); }
+
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic();
+ }
virtual lldb::InstrumentationRuntimeType
GetType() { return GetTypeStatic(); }
- virtual uint32_t
- GetPluginVersion() { return 1; }
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
- virtual void
- ModulesDidLoad(lldb_private::ModuleList &module_list);
+ void
+ ModulesDidLoad(lldb_private::ModuleList &module_list) override;
- virtual bool
- IsActive();
+ bool
+ IsActive() override;
private:
-
AddressSanitizerRuntime(const lldb::ProcessSP &process_sp);
-
+
+ lldb::ProcessSP
+ GetProcessSP ()
+ {
+ return m_process_wp.lock();
+ }
+
void
Activate();
@@ -76,11 +89,10 @@ private:
bool m_is_active;
lldb::ModuleSP m_runtime_module;
- lldb::ProcessSP m_process;
+ lldb::ProcessWP m_process_wp;
lldb::user_id_t m_breakpoint_id;
-
};
} // namespace lldb_private
-#endif // liblldb_InstrumentationRuntime_h_
+#endif // liblldb_AddressSanitizerRuntime_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/contrib/llvm/tools/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
index 8e454e7..143e447 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
@@ -16,6 +16,7 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Process.h"
@@ -27,6 +28,58 @@
using namespace lldb;
using namespace lldb_private;
+namespace {
+
+ PropertyDefinition
+ g_properties[] =
+ {
+ { "enable-jit-breakpoint", OptionValue::eTypeBoolean, true, true , nullptr, nullptr, "Enable breakpoint on __jit_debug_register_code." },
+ { nullptr , OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr }
+ };
+
+ enum
+ {
+ ePropertyEnableJITBreakpoint
+ };
+
+
+ class PluginProperties : public Properties
+ {
+ public:
+ static ConstString
+ GetSettingName()
+ {
+ return JITLoaderGDB::GetPluginNameStatic();
+ }
+
+ PluginProperties()
+ {
+ m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
+ m_collection_sp->Initialize(g_properties);
+ }
+
+ bool
+ GetEnableJITBreakpoint() const
+ {
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr,
+ ePropertyEnableJITBreakpoint,
+ g_properties[ePropertyEnableJITBreakpoint].default_uint_value != 0);
+ }
+
+ };
+
+ typedef std::shared_ptr<PluginProperties> JITLoaderGDBPropertiesSP;
+
+ static const JITLoaderGDBPropertiesSP&
+ GetGlobalPluginProperties()
+ {
+ static const auto g_settings_sp(std::make_shared<PluginProperties>());
+ return g_settings_sp;
+ }
+
+} // anonymous namespace end
+
//------------------------------------------------------------------
// Debug Interface Structures
//------------------------------------------------------------------
@@ -37,7 +90,6 @@ typedef enum
JIT_UNREGISTER_FN
} jit_actions_t;
-#pragma pack(push, 4)
template <typename ptr_t>
struct jit_code_entry
{
@@ -54,7 +106,6 @@ struct jit_descriptor
ptr_t relevant_entry; // pointer
ptr_t first_entry; // pointer
};
-#pragma pack(pop)
JITLoaderGDB::JITLoaderGDB (lldb_private::Process *process) :
JITLoader(process),
@@ -70,6 +121,19 @@ JITLoaderGDB::~JITLoaderGDB ()
m_process->GetTarget().RemoveBreakpointByID (m_jit_break_id);
}
+void
+JITLoaderGDB::DebuggerInitialize(Debugger &debugger)
+{
+ if (!PluginManager::GetSettingForJITLoaderPlugin(debugger, PluginProperties::GetSettingName()))
+ {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForJITLoaderPlugin(debugger,
+ GetGlobalPluginProperties()->GetValueProperties(),
+ ConstString ("Properties for the JIT LoaderGDB plug-in."),
+ is_global_setting);
+ }
+}
+
void JITLoaderGDB::DidAttach()
{
Target &target = m_process->GetTarget();
@@ -88,7 +152,7 @@ void
JITLoaderGDB::ModulesDidLoad(ModuleList &module_list)
{
if (!DidSetJITBreakpoint() && m_process->IsAlive())
- SetJITBreakpoint(module_list);
+ SetJITBreakpoint(module_list);
}
//------------------------------------------------------------------
@@ -97,11 +161,13 @@ JITLoaderGDB::ModulesDidLoad(ModuleList &module_list)
void
JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list)
{
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
+ if (!GetGlobalPluginProperties()->GetEnableJITBreakpoint())
+ return;
if ( DidSetJITBreakpoint() )
return;
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
if (log)
log->Printf("JITLoaderGDB::%s looking for JIT register hook",
__FUNCTION__);
@@ -407,7 +473,8 @@ JITLoaderGDB::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
- CreateInstance);
+ CreateInstance,
+ DebuggerInitialize);
}
void
diff --git a/contrib/llvm/tools/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.h b/contrib/llvm/tools/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
index bfa1721..10bd989 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
@@ -13,15 +13,19 @@
// C Includes
// C++ Includes
#include <map>
-#include <vector>
-#include <string>
+// Other libraries and framework includes
+// Project includes
#include "lldb/Target/JITLoader.h"
#include "lldb/Target/Process.h"
class JITLoaderGDB : public lldb_private::JITLoader
{
public:
+ JITLoaderGDB(lldb_private::Process *process);
+
+ ~JITLoaderGDB() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -40,31 +44,29 @@ public:
static lldb::JITLoaderSP
CreateInstance (lldb_private::Process *process, bool force);
- JITLoaderGDB (lldb_private::Process *process);
-
- virtual
- ~JITLoaderGDB ();
+ static void
+ DebuggerInitialize(lldb_private::Debugger &debugger);
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
//------------------------------------------------------------------
// JITLoader interface
//------------------------------------------------------------------
- virtual void
- DidAttach ();
+ void
+ DidAttach() override;
- virtual void
- DidLaunch ();
+ void
+ DidLaunch() override;
- virtual void
- ModulesDidLoad (lldb_private::ModuleList &module_list);
+ void
+ ModulesDidLoad(lldb_private::ModuleList &module_list) override;
private:
lldb::addr_t
@@ -105,4 +107,4 @@ private:
};
-#endif
+#endif // liblldb_JITLoaderGDB_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
new file mode 100644
index 0000000..09031e2
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -0,0 +1,808 @@
+//===-- CPlusPlusLanguage.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CPlusPlusLanguage.h"
+
+
+#include "llvm/ADT/StringRef.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/DataFormatters/CXXFunctionPointer.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/VectorType.h"
+
+#include "CxxStringTypes.h"
+#include "LibCxx.h"
+#include "LibStdcpp.h"
+
+#include <cstring>
+#include <cctype>
+#include <functional>
+#include <mutex>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+void
+CPlusPlusLanguage::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "C++ Language",
+ CreateInstance);
+}
+
+void
+CPlusPlusLanguage::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+CPlusPlusLanguage::GetPluginNameStatic()
+{
+ static ConstString g_name("cplusplus");
+ return g_name;
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+CPlusPlusLanguage::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+CPlusPlusLanguage::GetPluginVersion()
+{
+ return 1;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+Language *
+CPlusPlusLanguage::CreateInstance (lldb::LanguageType language)
+{
+ if (Language::LanguageIsCPlusPlus(language))
+ return new CPlusPlusLanguage();
+ return nullptr;
+}
+
+void
+CPlusPlusLanguage::MethodName::Clear()
+{
+ m_full.Clear();
+ m_basename = llvm::StringRef();
+ m_context = llvm::StringRef();
+ m_arguments = llvm::StringRef();
+ m_qualifiers = llvm::StringRef();
+ m_type = eTypeInvalid;
+ m_parsed = false;
+ m_parse_error = false;
+}
+
+bool
+ReverseFindMatchingChars (const llvm::StringRef &s,
+ const llvm::StringRef &left_right_chars,
+ size_t &left_pos,
+ size_t &right_pos,
+ size_t pos = llvm::StringRef::npos)
+{
+ assert (left_right_chars.size() == 2);
+ left_pos = llvm::StringRef::npos;
+ const char left_char = left_right_chars[0];
+ const char right_char = left_right_chars[1];
+ pos = s.find_last_of(left_right_chars, pos);
+ if (pos == llvm::StringRef::npos || s[pos] == left_char)
+ return false;
+ right_pos = pos;
+ uint32_t depth = 1;
+ while (pos > 0 && depth > 0)
+ {
+ pos = s.find_last_of(left_right_chars, pos);
+ if (pos == llvm::StringRef::npos)
+ return false;
+ if (s[pos] == left_char)
+ {
+ if (--depth == 0)
+ {
+ left_pos = pos;
+ return left_pos < right_pos;
+ }
+ }
+ else if (s[pos] == right_char)
+ {
+ ++depth;
+ }
+ }
+ return false;
+}
+
+static bool
+IsValidBasename(const llvm::StringRef& basename)
+{
+ // Check that the basename matches with the following regular expression or is an operator name:
+ // "^~?([A-Za-z_][A-Za-z_0-9]*)(<.*>)?$"
+ // We are using a hand written implementation because it is significantly more efficient then
+ // using the general purpose regular expression library.
+ size_t idx = 0;
+ if (basename.size() > 0 && basename[0] == '~')
+ idx = 1;
+
+ if (basename.size() <= idx)
+ return false; // Empty string or "~"
+
+ if (!std::isalpha(basename[idx]) && basename[idx] != '_')
+ return false; // First charater (after removing the possible '~'') isn't in [A-Za-z_]
+
+ // Read all characters matching [A-Za-z_0-9]
+ ++idx;
+ while (idx < basename.size())
+ {
+ if (!std::isalnum(basename[idx]) && basename[idx] != '_')
+ break;
+ ++idx;
+ }
+
+ // We processed all characters. It is a vaild basename.
+ if (idx == basename.size())
+ return true;
+
+ // Check for basename with template arguments
+ // TODO: Improve the quality of the validation with validating the template arguments
+ if (basename[idx] == '<' && basename.back() == '>')
+ return true;
+
+ // Check if the basename is a vaild C++ operator name
+ if (!basename.startswith("operator"))
+ return false;
+
+ static RegularExpression g_operator_regex("^(operator)( ?)([A-Za-z_][A-Za-z_0-9]*|\\(\\)|\\[\\]|[\\^<>=!\\/*+-]+)(<.*>)?(\\[\\])?$");
+ std::string basename_str(basename.str());
+ return g_operator_regex.Execute(basename_str.c_str(), nullptr);
+}
+
+void
+CPlusPlusLanguage::MethodName::Parse()
+{
+ if (!m_parsed && m_full)
+ {
+// ConstString mangled;
+// m_full.GetMangledCounterpart(mangled);
+// printf ("\n parsing = '%s'\n", m_full.GetCString());
+// if (mangled)
+// printf (" mangled = '%s'\n", mangled.GetCString());
+ m_parse_error = false;
+ m_parsed = true;
+ llvm::StringRef full (m_full.GetCString());
+
+ size_t arg_start, arg_end;
+ llvm::StringRef parens("()", 2);
+ if (ReverseFindMatchingChars (full, parens, arg_start, arg_end))
+ {
+ m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
+ if (arg_end + 1 < full.size())
+ m_qualifiers = full.substr(arg_end + 1);
+ if (arg_start > 0)
+ {
+ size_t basename_end = arg_start;
+ size_t context_start = 0;
+ size_t context_end = llvm::StringRef::npos;
+ if (basename_end > 0 && full[basename_end-1] == '>')
+ {
+ // TODO: handle template junk...
+ // Templated function
+ size_t template_start, template_end;
+ llvm::StringRef lt_gt("<>", 2);
+ if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end))
+ {
+ // Check for templated functions that include return type like: 'void foo<Int>()'
+ context_start = full.rfind(' ', template_start);
+ if (context_start == llvm::StringRef::npos)
+ context_start = 0;
+
+ context_end = full.rfind(':', template_start);
+ if (context_end == llvm::StringRef::npos || context_end < context_start)
+ context_end = context_start;
+ }
+ else
+ {
+ context_end = full.rfind(':', basename_end);
+ }
+ }
+ else if (context_end == llvm::StringRef::npos)
+ {
+ context_end = full.rfind(':', basename_end);
+ }
+
+ if (context_end == llvm::StringRef::npos)
+ m_basename = full.substr(0, basename_end);
+ else
+ {
+ if (context_start < context_end)
+ m_context = full.substr(context_start, context_end - 1);
+ const size_t basename_begin = context_end + 1;
+ m_basename = full.substr(basename_begin, basename_end - basename_begin);
+ }
+ m_type = eTypeUnknownMethod;
+ }
+ else
+ {
+ m_parse_error = true;
+ return;
+ }
+
+ if (!IsValidBasename(m_basename))
+ {
+ // The C++ basename doesn't match our regular expressions so this can't
+ // be a valid C++ method, clear everything out and indicate an error
+ m_context = llvm::StringRef();
+ m_basename = llvm::StringRef();
+ m_arguments = llvm::StringRef();
+ m_qualifiers = llvm::StringRef();
+ m_parse_error = true;
+ }
+ }
+ else
+ {
+ m_parse_error = true;
+ }
+ }
+}
+
+llvm::StringRef
+CPlusPlusLanguage::MethodName::GetBasename ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_basename;
+}
+
+llvm::StringRef
+CPlusPlusLanguage::MethodName::GetContext ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_context;
+}
+
+llvm::StringRef
+CPlusPlusLanguage::MethodName::GetArguments ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_arguments;
+}
+
+llvm::StringRef
+CPlusPlusLanguage::MethodName::GetQualifiers ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_qualifiers;
+}
+
+std::string
+CPlusPlusLanguage::MethodName::GetScopeQualifiedName ()
+{
+ if (!m_parsed)
+ Parse();
+ if (m_basename.empty() || m_context.empty())
+ return std::string();
+
+ std::string res;
+ res += m_context;
+ res += "::";
+ res += m_basename;
+
+ return res;
+}
+
+bool
+CPlusPlusLanguage::IsCPPMangledName (const char *name)
+{
+ // FIXME, we should really run through all the known C++ Language plugins and ask each one if
+ // this is a C++ mangled name, but we can put that off till there is actually more than one
+ // we care about.
+
+ if (name && name[0] == '_' && name[1] == 'Z')
+ return true;
+ else
+ return false;
+}
+
+bool
+CPlusPlusLanguage::ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier)
+{
+ static RegularExpression g_basename_regex("^(([A-Za-z_][A-Za-z_0-9]*::)*)([A-Za-z_][A-Za-z_0-9]*)$");
+ RegularExpression::Match match(4);
+ if (g_basename_regex.Execute (name, &match))
+ {
+ match.GetMatchAtIndex(name, 1, context);
+ match.GetMatchAtIndex(name, 3, identifier);
+ return true;
+ }
+ return false;
+}
+
+class CPPRuntimeEquivalents
+{
+public:
+ CPPRuntimeEquivalents ()
+ {
+
+ m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("basic_string<char>"));
+
+ // these two (with a prefixed std::) occur when c++stdlib string class occurs as a template argument in some STL container
+ m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("std::basic_string<char>"));
+
+ m_impl.Sort();
+ }
+
+ void
+ Add (ConstString& type_name,
+ ConstString& type_equivalent)
+ {
+ m_impl.Insert(type_name.AsCString(), type_equivalent);
+ }
+
+ uint32_t
+ FindExactMatches (ConstString& type_name,
+ std::vector<ConstString>& equivalents)
+ {
+
+ uint32_t count = 0;
+
+ for (ImplData match = m_impl.FindFirstValueForName(type_name.AsCString());
+ match != NULL;
+ match = m_impl.FindNextValueForName(match))
+ {
+ equivalents.push_back(match->value);
+ count++;
+ }
+
+ return count;
+ }
+
+ // partial matches can occur when a name with equivalents is a template argument.
+ // e.g. we may have "class Foo" be a match for "struct Bar". if we have a typename
+ // such as "class Templatized<class Foo, Anything>" we want this to be replaced with
+ // "class Templatized<struct Bar, Anything>". Since partial matching is time consuming
+ // once we get a partial match, we add it to the exact matches list for faster retrieval
+ uint32_t
+ FindPartialMatches (ConstString& type_name,
+ std::vector<ConstString>& equivalents)
+ {
+
+ uint32_t count = 0;
+
+ const char* type_name_cstr = type_name.AsCString();
+
+ size_t items_count = m_impl.GetSize();
+
+ for (size_t item = 0; item < items_count; item++)
+ {
+ const char* key_cstr = m_impl.GetCStringAtIndex(item);
+ if ( strstr(type_name_cstr,key_cstr) )
+ {
+ count += AppendReplacements(type_name_cstr,
+ key_cstr,
+ equivalents);
+ }
+ }
+
+ return count;
+
+ }
+
+private:
+
+ std::string& replace (std::string& target,
+ std::string& pattern,
+ std::string& with)
+ {
+ size_t pos;
+ size_t pattern_len = pattern.size();
+
+ while ( (pos = target.find(pattern)) != std::string::npos )
+ target.replace(pos, pattern_len, with);
+
+ return target;
+ }
+
+ uint32_t
+ AppendReplacements (const char* original,
+ const char *matching_key,
+ std::vector<ConstString>& equivalents)
+ {
+
+ std::string matching_key_str(matching_key);
+ ConstString original_const(original);
+
+ uint32_t count = 0;
+
+ for (ImplData match = m_impl.FindFirstValueForName(matching_key);
+ match != NULL;
+ match = m_impl.FindNextValueForName(match))
+ {
+ std::string target(original);
+ std::string equiv_class(match->value.AsCString());
+
+ replace (target, matching_key_str, equiv_class);
+
+ ConstString target_const(target.c_str());
+
+// you will most probably want to leave this off since it might make this map grow indefinitely
+#ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW
+ Add(original_const, target_const);
+#endif
+ equivalents.push_back(target_const);
+
+ count++;
+ }
+
+ return count;
+ }
+
+ typedef UniqueCStringMap<ConstString> Impl;
+ typedef const Impl::Entry* ImplData;
+ Impl m_impl;
+};
+
+static CPPRuntimeEquivalents&
+GetEquivalentsMap ()
+{
+ static CPPRuntimeEquivalents g_equivalents_map;
+ return g_equivalents_map;
+}
+
+
+uint32_t
+CPlusPlusLanguage::FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents)
+{
+ uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents);
+
+ bool might_have_partials=
+ ( count == 0 ) // if we have a full name match just use it
+ && (strchr(type_name.AsCString(), '<') != NULL // we should only have partial matches when templates are involved, check that we have
+ && strchr(type_name.AsCString(), '>') != NULL); // angle brackets in the type_name before trying to scan for partial matches
+
+ if ( might_have_partials )
+ count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents);
+
+ return count;
+}
+
+static void
+LoadLibCxxFormatters (lldb::TypeCategoryImplSP cpp_category_sp)
+{
+ if (!cpp_category_sp)
+ return;
+
+ TypeSummaryImpl::Flags stl_summary_flags;
+ stl_summary_flags.SetCascades(true)
+ .SetSkipPointers(false)
+ .SetSkipReferences(false)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(true)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+#ifndef LLDB_DISABLE_PYTHON
+ lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider, "std::string summary provider"));
+ lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider, "std::wstring summary provider"));
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::string"),
+ std_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >"),
+ std_string_summary_sp);
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::wstring"),
+ std_wstring_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >"),
+ std_wstring_summary_sp);
+
+ SyntheticChildren::Flags stl_synth_flags;
+ stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
+
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::map synthetic children", ConstString("^std::__1::map<.+> >(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_synth_flags);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::set synthetic children", ConstString("^std::__1::set<.+> >(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator, "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true);
+
+ cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")),
+ SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+ "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
+
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "shared_ptr synthetic children", ConstString("^(std::__1::)shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "weak_ptr synthetic children", ConstString("^(std::__1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
+
+ stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(false);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", ConstString("^std::__1::map<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::deque summary provider", ConstString("^std::__1::deque<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_summary_flags);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__1::set<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multiset summary provider", ConstString("^std::__1::multiset<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multimap summary provider", ConstString("^std::__1::multimap<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::unordered containers summary provider", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true);
+
+ stl_summary_flags.SetSkipPointers(true);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::shared_ptr summary provider", ConstString("^std::__1::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::weak_ptr summary provider", ConstString("^std::__1::weak_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
+
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^std::__1::__wrap_iter<.+>$"), stl_synth_flags, true);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::__1::__map_iterator<.+>$"), stl_synth_flags, true);
+
+ AddFilter(cpp_category_sp, {"__a_"}, "libc++ std::atomic filter", ConstString("^std::__1::atomic<.*>$"), stl_synth_flags, true);
+#endif
+}
+
+static void
+LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
+{
+ if (!cpp_category_sp)
+ return;
+
+ TypeSummaryImpl::Flags stl_summary_flags;
+ stl_summary_flags.SetCascades(true)
+ .SetSkipPointers(false)
+ .SetSkipReferences(false)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(true)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+ lldb::TypeSummaryImplSP std_string_summary_sp(new StringSummaryFormat(stl_summary_flags,
+ "${var._M_dataplus._M_p}"));
+
+ lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags,
+ LibStdcppStringSummaryProvider,
+ "libstdc++ c++11 std::string summary provider"));
+ lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags,
+ LibStdcppWStringSummaryProvider,
+ "libstdc++ c++11 std::wstring summary provider"));
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
+ std_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char>"),
+ std_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"),
+ std_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
+ std_string_summary_sp);
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::string"),
+ cxx11_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
+ cxx11_string_summary_sp);
+
+ // making sure we force-pick the summary for printing wstring (_M_p is a wchar_t*)
+ lldb::TypeSummaryImplSP std_wstring_summary_sp(new StringSummaryFormat(stl_summary_flags,
+ "${var._M_dataplus._M_p%S}"));
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"),
+ std_wstring_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t>"),
+ std_wstring_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >"),
+ std_wstring_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
+ std_wstring_summary_sp);
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::wstring"),
+ cxx11_wstring_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
+ cxx11_wstring_summary_sp);
+
+#ifndef LLDB_DISABLE_PYTHON
+
+ SyntheticChildren::Flags stl_synth_flags;
+ stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
+
+ cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
+ SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+ "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
+ cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
+ SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+ "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
+ cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$")),
+ SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+ "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
+ stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(true);
+ cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
+ TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+ "size=${svar%#}")));
+ cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
+ TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+ "size=${svar%#}")));
+ cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$")),
+ TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+ "size=${svar%#}")));
+
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
+
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
+#endif
+}
+
+static void
+LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
+{
+ if (!cpp_category_sp)
+ return;
+
+ TypeSummaryImpl::Flags string_flags;
+ string_flags.SetCascades(true)
+ .SetSkipPointers(true)
+ .SetSkipReferences(false)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(false)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+ TypeSummaryImpl::Flags string_array_flags;
+ string_array_flags.SetCascades(true)
+ .SetSkipPointers(true)
+ .SetSkipReferences(false)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(true)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+#ifndef LLDB_DISABLE_PYTHON
+ // FIXME because of a bug in the FormattersContainer we need to add a summary for both X* and const X* (<rdar://problem/12717717>)
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::Char16StringSummaryProvider,
+ "char16_t [] summary provider",
+ ConstString("char16_t \\[[0-9]+\\]"),
+ string_array_flags,
+ true);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider, "char32_t * summary provider", ConstString("char32_t *"), string_flags);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::Char32StringSummaryProvider,
+ "char32_t [] summary provider",
+ ConstString("char32_t \\[[0-9]+\\]"),
+ string_array_flags,
+ true);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "unichar * summary provider", ConstString("unichar *"), string_flags);
+
+ TypeSummaryImpl::Flags widechar_flags;
+ widechar_flags.SetDontShowValue(true)
+ .SetSkipPointers(true)
+ .SetSkipReferences(false)
+ .SetCascades(true)
+ .SetDontShowChildren(true)
+ .SetHideItemNames(true)
+ .SetShowMembersOneLiner(false);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32SummaryProvider, "char32_t summary provider", ConstString("char32_t"), widechar_flags);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider, "wchar_t summary provider", ConstString("wchar_t"), widechar_flags);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "unichar summary provider", ConstString("unichar"), widechar_flags);
+#endif
+}
+
+lldb::TypeCategoryImplSP
+CPlusPlusLanguage::GetFormatters ()
+{
+ static std::once_flag g_initialize;
+ static TypeCategoryImplSP g_category;
+
+ std::call_once(g_initialize, [this] () -> void {
+ DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
+ if (g_category)
+ {
+ LoadLibCxxFormatters(g_category);
+ LoadLibStdcppFormatters(g_category);
+ LoadSystemFormatters(g_category);
+ }
+ });
+ return g_category;
+}
+
+HardcodedFormatters::HardcodedSummaryFinder
+CPlusPlusLanguage::GetHardcodedSummaries ()
+{
+ static std::once_flag g_initialize;
+ static ConstString g_vectortypes("VectorTypes");
+ static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
+
+ std::call_once(g_initialize, [] () -> void {
+ g_formatters.push_back(
+ [](lldb_private::ValueObject& valobj,
+ lldb::DynamicValueType,
+ FormatManager&) -> TypeSummaryImpl::SharedPointer {
+ static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags(), lldb_private::formatters::CXXFunctionPointerSummaryProvider, "Function pointer summary provider"));
+ if (valobj.GetCompilerType().IsFunctionPointerType())
+ {
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ g_formatters.push_back(
+ [](lldb_private::ValueObject& valobj,
+ lldb::DynamicValueType,
+ FormatManager& fmt_mgr) -> TypeSummaryImpl::SharedPointer {
+ static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags()
+ .SetCascades(true)
+ .SetDontShowChildren(true)
+ .SetHideItemNames(true)
+ .SetShowMembersOneLiner(true)
+ .SetSkipPointers(true)
+ .SetSkipReferences(false),
+ lldb_private::formatters::VectorTypeSummaryProvider,
+ "vector_type pointer summary provider"));
+ if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr))
+ {
+ if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ });
+
+ return g_formatters;
+}
+
+HardcodedFormatters::HardcodedSyntheticFinder
+CPlusPlusLanguage::GetHardcodedSynthetics ()
+{
+ static std::once_flag g_initialize;
+ static ConstString g_vectortypes("VectorTypes");
+ static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
+
+ std::call_once(g_initialize, [] () -> void {
+ g_formatters.push_back(
+ [](lldb_private::ValueObject& valobj,
+ lldb::DynamicValueType,
+ FormatManager& fmt_mgr) -> SyntheticChildren::SharedPointer {
+ static CXXSyntheticChildren::SharedPointer formatter_sp(new CXXSyntheticChildren(SyntheticChildren::Flags().SetCascades(true).SetSkipPointers(true).SetSkipReferences(true).SetNonCacheable(true),
+ "vector_type synthetic children",
+ lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
+ if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr))
+ {
+ if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ });
+
+ return g_formatters;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
new file mode 100644
index 0000000..f0fc07e
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -0,0 +1,189 @@
+//===-- CPlusPlusLanguage.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CPlusPlusLanguage_h_
+#define liblldb_CPlusPlusLanguage_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "llvm/ADT/StringRef.h"
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Target/Language.h"
+
+namespace lldb_private {
+
+class CPlusPlusLanguage :
+ public Language
+{
+public:
+ class MethodName
+ {
+ public:
+ enum Type
+ {
+ eTypeInvalid,
+ eTypeUnknownMethod,
+ eTypeClassMethod,
+ eTypeInstanceMethod
+ };
+
+ MethodName () :
+ m_full(),
+ m_basename(),
+ m_context(),
+ m_arguments(),
+ m_qualifiers(),
+ m_type (eTypeInvalid),
+ m_parsed (false),
+ m_parse_error (false)
+ {
+ }
+
+ MethodName (const ConstString &s) :
+ m_full(s),
+ m_basename(),
+ m_context(),
+ m_arguments(),
+ m_qualifiers(),
+ m_type (eTypeInvalid),
+ m_parsed (false),
+ m_parse_error (false)
+ {
+ }
+
+ void
+ Clear();
+
+ bool
+ IsValid ()
+ {
+ if (!m_parsed)
+ Parse();
+ if (m_parse_error)
+ return false;
+ if (m_type == eTypeInvalid)
+ return false;
+ return (bool)m_full;
+ }
+
+ Type
+ GetType () const
+ {
+ return m_type;
+ }
+
+ const ConstString &
+ GetFullName () const
+ {
+ return m_full;
+ }
+
+ std::string
+ GetScopeQualifiedName ();
+
+ llvm::StringRef
+ GetBasename ();
+
+ llvm::StringRef
+ GetContext ();
+
+ llvm::StringRef
+ GetArguments ();
+
+ llvm::StringRef
+ GetQualifiers ();
+
+ protected:
+ void
+ Parse();
+
+ ConstString m_full; // Full name: "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) const"
+ llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex"
+ llvm::StringRef m_context; // Decl context: "lldb::SBTarget"
+ llvm::StringRef m_arguments; // Arguments: "(unsigned int)"
+ llvm::StringRef m_qualifiers; // Qualifiers: "const"
+ Type m_type;
+ bool m_parsed;
+ bool m_parse_error;
+ };
+
+ CPlusPlusLanguage() = default;
+
+ ~CPlusPlusLanguage() override = default;
+
+ lldb::LanguageType
+ GetLanguageType () const override
+ {
+ return lldb::eLanguageTypeC_plus_plus;
+ }
+
+ lldb::TypeCategoryImplSP
+ GetFormatters () override;
+
+ HardcodedFormatters::HardcodedSummaryFinder
+ GetHardcodedSummaries () override;
+
+ HardcodedFormatters::HardcodedSyntheticFinder
+ GetHardcodedSynthetics () override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::Language *
+ CreateInstance (lldb::LanguageType language);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static bool
+ IsCPPMangledName(const char *name);
+
+ // Extract C++ context and identifier from a string using heuristic matching (as opposed to
+ // CPlusPlusLanguage::MethodName which has to have a fully qualified C++ name with parens and arguments.
+ // If the name is a lone C identifier (e.g. C) or a qualified C identifier (e.g. A::B::C) it will return true,
+ // and identifier will be the identifier (C and C respectively) and the context will be "" and "A::B::" respectively.
+ // If the name fails the heuristic matching for a qualified or unqualified C/C++ identifier, then it will return false
+ // and identifier and context will be unchanged.
+
+ static bool
+ ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier);
+
+ // in some cases, compilers will output different names for one same type. when that happens, it might be impossible
+ // to construct SBType objects for a valid type, because the name that is available is not the same as the name that
+ // can be used as a search key in FindTypes(). the equivalents map here is meant to return possible alternative names
+ // for a type through which a search can be conducted. Currently, this is only enabled for C++ but can be extended
+ // to ObjC or other languages if necessary
+ static uint32_t
+ FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CPlusPlusLanguage_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
new file mode 100644
index 0000000..7e8d958
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
@@ -0,0 +1,204 @@
+//===-- CXXStringTypes.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CxxStringTypes.h"
+
+#include "llvm/Support/ConvertUTF.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/ProcessStructReader.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+#include <algorithm>
+
+#if __ANDROID_NDK__
+#include <sys/types.h>
+#endif
+
+#include "lldb/Host/Time.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj);
+ if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(valobj_addr);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetPrefixToken("u");
+
+ if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options))
+ {
+ stream.Printf("Summary Unavailable");
+ return true;
+ }
+
+ return true;
+}
+
+bool
+lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj);
+ if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(valobj_addr);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetPrefixToken("U");
+
+ if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options))
+ {
+ stream.Printf("Summary Unavailable");
+ return true;
+ }
+
+ return true;
+}
+
+bool
+lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj);
+ if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ // Get a wchar_t basic type from the current type system
+ CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
+
+ if (!wchar_compiler_type)
+ return false;
+
+ const uint32_t wchar_size = wchar_compiler_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(valobj_addr);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetPrefixToken("L");
+
+ switch (wchar_size)
+ {
+ case 8:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options);
+ case 16:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+ case 32:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options);
+ default:
+ stream.Printf("size for wchar_t is not valid");
+ return true;
+ }
+ return true;
+}
+
+bool
+lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ DataExtractor data;
+ Error error;
+ valobj.GetData(data, error);
+
+ if (error.Fail())
+ return false;
+
+ std::string value;
+ valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
+ if (!value.empty())
+ stream.Printf("%s ", value.c_str());
+
+ StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+ options.SetData(data);
+ options.SetStream(&stream);
+ options.SetPrefixToken("u");
+ options.SetQuote('\'');
+ options.SetSourceSize(1);
+ options.SetBinaryZeroIsTerminator(false);
+
+ return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+}
+
+bool
+lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ DataExtractor data;
+ Error error;
+ valobj.GetData(data, error);
+
+ if (error.Fail())
+ return false;
+
+ std::string value;
+ valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
+ if (!value.empty())
+ stream.Printf("%s ", value.c_str());
+
+ StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+ options.SetData(data);
+ options.SetStream(&stream);
+ options.SetPrefixToken("U");
+ options.SetQuote('\'');
+ options.SetSourceSize(1);
+ options.SetBinaryZeroIsTerminator(false);
+
+ return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF32>(options);
+}
+
+bool
+lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ DataExtractor data;
+ Error error;
+ valobj.GetData(data, error);
+
+ if (error.Fail())
+ return false;
+
+ StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+ options.SetData(data);
+ options.SetStream(&stream);
+ options.SetPrefixToken("L");
+ options.SetQuote('\'');
+ options.SetSourceSize(1);
+ options.SetBinaryZeroIsTerminator(false);
+
+ return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h
new file mode 100644
index 0000000..bfb03bd
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h
@@ -0,0 +1,41 @@
+//===-- CxxStringTypes.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CxxStringTypes_h_
+#define liblldb_CxxStringTypes_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ bool
+ Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t* and unichar*
+
+ bool
+ Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t*
+
+ bool
+ WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t*
+
+ bool
+ Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t and unichar
+
+ bool
+ Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t
+
+ bool
+ WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t
+
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CxxStringTypes_h_
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxx.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index a04b4ff..950bd62 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxx.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+#include "LibCxx.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Debugger.h"
@@ -16,9 +16,12 @@
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/VectorIterator.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Target.h"
using namespace lldb;
@@ -81,7 +84,7 @@ m_children()
if (valobj_sp)
{
Update();
- m_bool_type = valobj_sp->GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeBool);
+ m_bool_type = valobj_sp->GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeBool);
}
}
@@ -377,7 +380,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (siz
return lldb::ValueObjectSP();
uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
- m_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetClangType());
+ m_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetCompilerType());
}
return m_count_sp;
}
@@ -390,7 +393,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (siz
return lldb::ValueObjectSP();
uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
- m_weak_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetClangType());
+ m_weak_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetCompilerType());
}
return m_weak_count_sp;
}
@@ -461,3 +464,190 @@ lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, S
}
return FormatEntity::FormatStringRef("size=${svar%#}", stream, NULL, NULL, NULL, &valobj, false, false);
}
+
+// the field layout in a libc++ string (cap, side, data or data, size, cap)
+enum LibcxxStringLayoutMode
+{
+ eLibcxxStringLayoutModeCSD = 0,
+ eLibcxxStringLayoutModeDSC = 1,
+ eLibcxxStringLayoutModeInvalid = 0xffff
+};
+
+// this function abstracts away the layout and mode details of a libc++ string
+// and returns the address of the data and the size ready for callers to consume
+static bool
+ExtractLibcxxStringInfo (ValueObject& valobj,
+ ValueObjectSP &location_sp,
+ uint64_t& size)
+{
+ ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
+ if (!D)
+ return false;
+
+ ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
+
+ // this child should exist
+ if (!layout_decider)
+ return false;
+
+ ConstString g_data_name("__data_");
+ ConstString g_size_name("__size_");
+ bool short_mode = false; // this means the string is in short-mode and the data is stored inline
+ LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
+ uint64_t size_mode_value = 0;
+
+ if (layout == eLibcxxStringLayoutModeDSC)
+ {
+ ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
+ if (!size_mode)
+ return false;
+
+ if (size_mode->GetName() != g_size_name)
+ {
+ // we are hitting the padding structure, move along
+ size_mode = D->GetChildAtIndexPath({1,1,1});
+ if (!size_mode)
+ return false;
+ }
+
+ size_mode_value = (size_mode->GetValueAsUnsigned(0));
+ short_mode = ((size_mode_value & 0x80) == 0);
+ }
+ else
+ {
+ ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
+ if (!size_mode)
+ return false;
+
+ size_mode_value = (size_mode->GetValueAsUnsigned(0));
+ short_mode = ((size_mode_value & 1) == 0);
+ }
+
+ if (short_mode)
+ {
+ ValueObjectSP s(D->GetChildAtIndex(1, true));
+ if (!s)
+ return false;
+ location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
+ size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
+ return (location_sp.get() != nullptr);
+ }
+ else
+ {
+ ValueObjectSP l(D->GetChildAtIndex(0, true));
+ if (!l)
+ return false;
+ // we can use the layout_decider object as the data pointer
+ location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
+ ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
+ if (!size_vo || !location_sp)
+ return false;
+ size = size_vo->GetValueAsUnsigned(0);
+ return true;
+ }
+}
+
+bool
+lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
+{
+ uint64_t size = 0;
+ ValueObjectSP location_sp((ValueObject*)nullptr);
+ if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
+ return false;
+ if (size == 0)
+ {
+ stream.Printf("L\"\"");
+ return true;
+ }
+ if (!location_sp)
+ return false;
+
+ DataExtractor extractor;
+
+ StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+
+ if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
+ {
+ const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
+ if (size > max_size)
+ {
+ size = max_size;
+ options.SetIsTruncated(true);
+ }
+ }
+ location_sp->GetPointeeData(extractor, 0, size);
+
+ // std::wstring::size() is measured in 'characters', not bytes
+ auto wchar_t_size = valobj.GetTargetSP()->GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
+
+ options.SetData(extractor);
+ options.SetStream(&stream);
+ options.SetPrefixToken("L");
+ options.SetQuote('"');
+ options.SetSourceSize(size);
+ options.SetBinaryZeroIsTerminator(false);
+
+ switch (wchar_t_size)
+ {
+ case 1:
+ StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::UTF8>(options);
+ break;
+
+ case 2:
+ lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::UTF16>(options);
+ break;
+
+ case 4:
+ lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::UTF32>(options);
+ break;
+
+ default:
+ stream.Printf("size for wchar_t is not valid");
+ return true;
+ }
+
+ return true;
+}
+
+bool
+lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
+{
+ uint64_t size = 0;
+ ValueObjectSP location_sp((ValueObject*)nullptr);
+
+ if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
+ return false;
+
+ if (size == 0)
+ {
+ stream.Printf("\"\"");
+ return true;
+ }
+
+ if (!location_sp)
+ return false;
+
+ StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+
+ DataExtractor extractor;
+ if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
+ {
+ const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
+ if (size > max_size)
+ {
+ size = max_size;
+ options.SetIsTruncated(true);
+ }
+ }
+ location_sp->GetPointeeData(extractor, 0, size);
+
+ options.SetData(extractor);
+ options.SetStream(&stream);
+ options.SetPrefixToken(0);
+ options.SetQuote('"');
+ options.SetSourceSize(size);
+ options.SetBinaryZeroIsTerminator(false);
+ StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::ASCII>(options);
+
+ return true;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
new file mode 100644
index 0000000..ae00bc0
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -0,0 +1,141 @@
+//===-- LibCxx.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_LibCxx_h_
+#define liblldb_LibCxx_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+
+ bool
+ LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::string
+
+ bool
+ LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::wstring
+
+ bool
+ LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::shared_ptr<> and std::weak_ptr<>
+
+ class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ ~LibcxxVectorBoolSyntheticFrontEnd() override;
+
+ private:
+ CompilerType m_bool_type;
+ ExecutionContextRef m_exe_ctx_ref;
+ uint64_t m_count;
+ lldb::addr_t m_base_data_address;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ };
+
+ SyntheticChildrenFrontEnd* LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ bool
+ LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ ~LibCxxMapIteratorSyntheticFrontEnd() override;
+
+ private:
+ ValueObject *m_pair_ptr;
+ };
+
+ SyntheticChildrenFrontEnd* LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ ~LibcxxSharedPtrSyntheticFrontEnd() override;
+
+ private:
+ ValueObject* m_cntrl;
+ lldb::ValueObjectSP m_count_sp;
+ lldb::ValueObjectSP m_weak_count_sp;
+ uint8_t m_ptr_size;
+ lldb::ByteOrder m_byte_order;
+ };
+
+ SyntheticChildrenFrontEnd* LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_LibCxx_h_
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxxInitializerList.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
index 0dcef98..9970d49 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxxInitializerList.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
@@ -1,4 +1,4 @@
-//===-- LibCxxInitializerList.cpp ----------------------------------*- C++ -*-===//
+//===-- LibCxxInitializerList.cpp -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,10 +7,15 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "LibCxx.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
using namespace lldb;
using namespace lldb_private;
@@ -22,33 +27,33 @@ namespace lldb_private {
{
public:
LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxInitializerListSyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
- virtual bool
- Update();
+ bool
+ Update() override;
- virtual bool
- MightHaveChildren ();
+ bool
+ MightHaveChildren() override;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
- virtual
- ~LibcxxInitializerListSyntheticFrontEnd ();
private:
ValueObject* m_start;
- ClangASTType m_element_type;
+ CompilerType m_element_type;
uint32_t m_element_size;
size_t m_num_elements;
std::map<size_t,lldb::ValueObjectSP> m_children;
};
- }
-}
+ } // namespace formatters
+} // namespace lldb_private
lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
@@ -62,6 +67,12 @@ m_children()
Update();
}
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::~LibcxxInitializerListSyntheticFrontEnd()
+{
+ // this needs to stay around because it's a child object who will follow its parent's life cycle
+ // delete m_start;
+}
+
size_t
lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::CalculateNumChildren ()
{
@@ -101,7 +112,7 @@ lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update()
m_num_elements = 0;
m_children.clear();
lldb::TemplateArgumentKind kind;
- m_element_type = m_backend.GetClangType().GetTemplateArgument(0, kind);
+ m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind);
if (kind != lldb::eTemplateArgumentKindType || false == m_element_type.IsValid())
return false;
@@ -127,12 +138,6 @@ lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetIndexOfChil
return ExtractIndexFromString(name.GetCString());
}
-lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::~LibcxxInitializerListSyntheticFrontEnd ()
-{
- // this needs to stay around because it's a child object who will follow its parent's life cycle
- // delete m_start;
-}
-
lldb_private::SyntheticChildrenFrontEnd*
lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
@@ -140,4 +145,3 @@ lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSynt
return NULL;
return (new LibcxxInitializerListSyntheticFrontEnd(valobj_sp));
}
-
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxxList.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
index f3e07fe..f86f968 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxxList.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
@@ -1,4 +1,4 @@
-//===-- LibCxxList.cpp -------------------------------------------*- C++ -*-===//
+//===-- LibCxxList.cpp ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,184 +7,204 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "LibCxx.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
+namespace {
+
+ class ListEntry
+ {
+ public:
+ ListEntry() = default;
+ ListEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
+ ListEntry (const ListEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {}
+ ListEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
+
+ ListEntry
+ next ()
+ {
+ if (!m_entry_sp)
+ return ListEntry();
+ return ListEntry(m_entry_sp->GetChildAtIndexPath({0,1}));
+ }
+
+ ListEntry
+ prev ()
+ {
+ if (!m_entry_sp)
+ return ListEntry();
+ return ListEntry(m_entry_sp->GetChildAtIndexPath({0,0}));
+ }
+
+ uint64_t
+ value () const
+ {
+ if (!m_entry_sp)
+ return 0;
+ return m_entry_sp->GetValueAsUnsigned(0);
+ }
+
+ bool
+ null()
+ {
+ return (value() == 0);
+ }
+
+ explicit operator bool ()
+ {
+ return GetEntry().get() != nullptr && null() == false;
+ }
+
+ ValueObjectSP
+ GetEntry ()
+ {
+ return m_entry_sp;
+ }
+
+ void
+ SetEntry (ValueObjectSP entry)
+ {
+ m_entry_sp = entry;
+ }
+
+ bool
+ operator == (const ListEntry& rhs) const
+ {
+ return value() == rhs.value();
+ }
+
+ bool
+ operator != (const ListEntry& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ private:
+ ValueObjectSP m_entry_sp;
+ };
+
+ class ListIterator
+ {
+ public:
+ ListIterator() = default;
+ ListIterator (ListEntry entry) : m_entry(entry) {}
+ ListIterator (ValueObjectSP entry) : m_entry(entry) {}
+ ListIterator (const ListIterator& rhs) : m_entry(rhs.m_entry) {}
+ ListIterator (ValueObject* entry) : m_entry(entry) {}
+
+ ValueObjectSP
+ value ()
+ {
+ return m_entry.GetEntry();
+ }
+
+ ValueObjectSP
+ advance (size_t count)
+ {
+ if (count == 0)
+ return m_entry.GetEntry();
+ if (count == 1)
+ {
+ next ();
+ return m_entry.GetEntry();
+ }
+ while (count > 0)
+ {
+ next ();
+ count--;
+ if (m_entry.null())
+ return lldb::ValueObjectSP();
+ }
+ return m_entry.GetEntry();
+ }
+
+ bool
+ operator == (const ListIterator& rhs) const
+ {
+ return (rhs.m_entry == m_entry);
+ }
+
+ protected:
+ void
+ next ()
+ {
+ m_entry = m_entry.next();
+ }
+
+ void
+ prev ()
+ {
+ m_entry = m_entry.prev();
+ }
+
+ private:
+ ListEntry m_entry;
+ };
+
+} // end anonymous namespace
+
namespace lldb_private {
namespace formatters {
class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxStdListSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
- virtual bool
- Update();
+ bool
+ Update() override;
- virtual bool
- MightHaveChildren ();
+ bool
+ MightHaveChildren() override;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
- virtual
- ~LibcxxStdListSyntheticFrontEnd ();
private:
bool
- HasLoop(size_t);
+ HasLoop(size_t count);
size_t m_list_capping_size;
static const bool g_use_loop_detect = true;
- size_t m_loop_detected;
+
+ size_t m_loop_detected; // The number of elements that have had loop detection run over them.
+ ListEntry m_slow_runner; // Used for loop detection
+ ListEntry m_fast_runner; // Used for loop detection
+
lldb::addr_t m_node_address;
ValueObject* m_head;
ValueObject* m_tail;
- ClangASTType m_element_type;
+ CompilerType m_element_type;
size_t m_count;
std::map<size_t,lldb::ValueObjectSP> m_children;
+ std::map<size_t, ListIterator> m_iterators;
};
- }
-}
-
-class ListEntry
-{
-public:
- ListEntry () {}
- ListEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
- ListEntry (const ListEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {}
- ListEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
-
- ListEntry
- next ()
- {
- if (!m_entry_sp)
- return ListEntry();
- return ListEntry(m_entry_sp->GetChildMemberWithName(ConstString("__next_"), true));
- }
-
- ListEntry
- prev ()
- {
- if (!m_entry_sp)
- return ListEntry();
- return ListEntry(m_entry_sp->GetChildMemberWithName(ConstString("__prev_"), true));
- }
-
- uint64_t
- value ()
- {
- if (!m_entry_sp)
- return 0;
- return m_entry_sp->GetValueAsUnsigned(0);
- }
-
- bool
- null()
- {
- return (value() == 0);
- }
-
- explicit operator bool ()
- {
- return GetEntry().get() != nullptr && null() == false;
- }
-
- ValueObjectSP
- GetEntry ()
- {
- return m_entry_sp;
- }
-
- void
- SetEntry (ValueObjectSP entry)
- {
- m_entry_sp = entry;
- }
-
- bool
- operator == (const ListEntry& rhs) const
- {
- return (rhs.m_entry_sp.get() == m_entry_sp.get());
- }
-
-private:
- ValueObjectSP m_entry_sp;
-};
-
-class ListIterator
-{
-public:
- ListIterator () {}
- ListIterator (ListEntry entry) : m_entry(entry) {}
- ListIterator (ValueObjectSP entry) : m_entry(entry) {}
- ListIterator (const ListIterator& rhs) : m_entry(rhs.m_entry) {}
- ListIterator (ValueObject* entry) : m_entry(entry) {}
-
- ValueObjectSP
- value ()
- {
- return m_entry.GetEntry();
- }
-
- ValueObjectSP
- advance (size_t count)
- {
- if (count == 0)
- return m_entry.GetEntry();
- if (count == 1)
- {
- next ();
- return m_entry.GetEntry();
- }
- while (count > 0)
- {
- next ();
- count--;
- if (m_entry.null())
- return lldb::ValueObjectSP();
- }
- return m_entry.GetEntry();
- }
-
- bool
- operator == (const ListIterator& rhs) const
- {
- return (rhs.m_entry == m_entry);
- }
-
-protected:
- void
- next ()
- {
- m_entry = m_entry.next();
- }
-
- void
- prev ()
- {
- m_entry = m_entry.prev();
- }
-private:
- ListEntry m_entry;
-};
+ } // namespace formatters
+} // namespace lldb_private
lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
@@ -195,7 +215,8 @@ m_head(NULL),
m_tail(NULL),
m_element_type(),
m_count(UINT32_MAX),
-m_children()
+m_children(),
+m_iterators()
{
if (valobj_sp)
Update();
@@ -209,25 +230,34 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop(size_t count)
// don't bother checking for a loop if we won't actually need to jump nodes
if (m_count < 2)
return false;
- auto steps_left = std::min(count,m_count);
- auto steps_left_save = steps_left;
- ListEntry slow(m_head);
- ListEntry fast(m_head);
- while (steps_left-- > 0)
+
+ if (m_loop_detected == 0)
{
- slow = slow.next();
- fast = fast.next();
- if (fast.next())
- fast = fast.next().next();
- else
- fast = nullptr;
- if (!slow || !fast)
- return false;
- if (slow == fast)
- return true;
+ // This is the first time we are being run (after the last update). Set up the loop
+ // invariant for the first element.
+ m_slow_runner = ListEntry(m_head).next();
+ m_fast_runner = m_slow_runner.next();
+ m_loop_detected = 1;
}
- m_loop_detected = steps_left_save;
- return false;
+
+ // Loop invariant:
+ // Loop detection has been run over the first m_loop_detected elements. If m_slow_runner ==
+ // m_fast_runner then the loop has been detected after m_loop_detected elements.
+ const size_t steps_to_run = std::min(count,m_count);
+ while (m_loop_detected < steps_to_run
+ && m_slow_runner
+ && m_fast_runner
+ && m_slow_runner != m_fast_runner) {
+
+ m_slow_runner = m_slow_runner.next();
+ m_fast_runner = m_fast_runner.next().next();
+ m_loop_detected++;
+ }
+ if (count <= m_loop_detected)
+ return false; // No loop in the first m_loop_detected elements.
+ if (!m_slow_runner || !m_fast_runner)
+ return false; // Reached the end of the list. Definitely no loops.
+ return m_slow_runner == m_fast_runner;
}
size_t
@@ -286,15 +316,29 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_
if (cached != m_children.end())
return cached->second;
- if (m_loop_detected <= idx)
- if (HasLoop(idx))
- return lldb::ValueObjectSP();
-
+ if (HasLoop(idx+1))
+ return lldb::ValueObjectSP();
+
+ size_t actual_advance = idx;
+
ListIterator current(m_head);
- ValueObjectSP current_sp(current.advance(idx));
+ if (idx > 0)
+ {
+ auto cached_iterator = m_iterators.find(idx-1);
+ if (cached_iterator != m_iterators.end())
+ {
+ current = cached_iterator->second;
+ actual_advance = 1;
+ }
+ }
+
+ ValueObjectSP current_sp(current.advance(actual_advance));
if (!current_sp)
return lldb::ValueObjectSP();
- current_sp = current_sp->GetChildMemberWithName(ConstString("__value_"), true);
+
+ m_iterators[idx] = current;
+
+ current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child
if (!current_sp)
return lldb::ValueObjectSP();
// we need to copy current_sp into a new object otherwise we will end up with all items named __value_
@@ -312,10 +356,15 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_
bool
lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update()
{
+ m_children.clear();
+ m_iterators.clear();
m_head = m_tail = NULL;
m_node_address = 0;
m_count = UINT32_MAX;
- m_loop_detected = false;
+ m_loop_detected = 0;
+ m_slow_runner.SetEntry(nullptr);
+ m_fast_runner.SetEntry(nullptr);
+
Error err;
ValueObjectSP backend_addr(m_backend.AddressOf(err));
m_list_capping_size = 0;
@@ -331,7 +380,7 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update()
ValueObjectSP impl_sp(m_backend.GetChildMemberWithName(ConstString("__end_"),true));
if (!impl_sp)
return false;
- ClangASTType list_type = m_backend.GetClangType();
+ CompilerType list_type = m_backend.GetCompilerType();
if (list_type.IsReferenceType())
list_type = list_type.GetNonReferenceType();
@@ -356,9 +405,6 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetIndexOfChildWithNam
return ExtractIndexFromString(name.GetCString());
}
-lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::~LibcxxStdListSyntheticFrontEnd ()
-{}
-
SyntheticChildrenFrontEnd*
lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
@@ -366,4 +412,3 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChi
return NULL;
return (new LibcxxStdListSyntheticFrontEnd(valobj_sp));
}
-
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxxMap.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
index 2ff6232..aa82557 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxxMap.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
@@ -1,4 +1,4 @@
-//===-- LibCxxList.cpp -------------------------------------------*- C++ -*-===//
+//===-- LibCxxList.cpp ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,67 +7,30 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "LibCxx.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
-namespace lldb_private {
- namespace formatters {
- class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
- {
- public:
- LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
-
- virtual bool
- MightHaveChildren ();
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
-
- virtual
- ~LibcxxStdMapSyntheticFrontEnd ();
- private:
- bool
- GetDataType();
-
- void
- GetValueOffset (const lldb::ValueObjectSP& node);
-
- ValueObject* m_tree;
- ValueObject* m_root_node;
- ClangASTType m_element_type;
- uint32_t m_skip_size;
- size_t m_count;
- std::map<size_t,lldb::ValueObjectSP> m_children;
- };
- }
-}
-
class MapEntry
{
public:
- MapEntry () {}
+ MapEntry() = default;
explicit MapEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
MapEntry (const MapEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {}
explicit MapEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
@@ -146,7 +109,7 @@ private:
class MapIterator
{
public:
- MapIterator () {}
+ MapIterator() = default;
MapIterator (MapEntry entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {}
MapIterator (ValueObjectSP entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {}
MapIterator (const MapIterator& rhs) : m_entry(rhs.m_entry),m_max_depth(rhs.m_max_depth), m_error(false) {}
@@ -176,6 +139,7 @@ public:
}
return m_entry.GetEntry();
}
+
protected:
void
next ()
@@ -206,7 +170,7 @@ protected:
}
m_entry = MapEntry(m_entry.parent());
}
-
+
private:
MapEntry
tree_min (MapEntry&& x)
@@ -230,7 +194,7 @@ private:
}
return x;
}
-
+
bool
is_left_child (const MapEntry& x)
{
@@ -246,6 +210,48 @@ private:
bool m_error;
};
+namespace lldb_private {
+ namespace formatters {
+ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxStdMapSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ bool
+ GetDataType();
+
+ void
+ GetValueOffset (const lldb::ValueObjectSP& node);
+
+ ValueObject* m_tree;
+ ValueObject* m_root_node;
+ CompilerType m_element_type;
+ uint32_t m_skip_size;
+ size_t m_count;
+ std::map<size_t, lldb::ValueObjectSP> m_children;
+ std::map<size_t, MapIterator> m_iterators;
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
m_tree(NULL),
@@ -253,7 +259,8 @@ m_root_node(NULL),
m_element_type(),
m_skip_size(UINT32_MAX),
m_count(UINT32_MAX),
-m_children()
+m_children(),
+m_iterators()
{
if (valobj_sp)
Update();
@@ -262,14 +269,17 @@ m_children()
size_t
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::CalculateNumChildren ()
{
+ static ConstString g___pair3_("__pair3_");
+ static ConstString g___first_("__first_");
+
if (m_count != UINT32_MAX)
return m_count;
if (m_tree == NULL)
return 0;
- ValueObjectSP m_item(m_tree->GetChildMemberWithName(ConstString("__pair3_"), true));
+ ValueObjectSP m_item(m_tree->GetChildMemberWithName(g___pair3_, true));
if (!m_item)
return 0;
- m_item = m_item->GetChildMemberWithName(ConstString("__first_"), true);
+ m_item = m_item->GetChildMemberWithName(g___first_, true);
if (!m_item)
return 0;
m_count = m_item->GetValueAsUnsigned(0);
@@ -279,7 +289,9 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::CalculateNumChildren ()
bool
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType()
{
- if (m_element_type.GetOpaqueQualType() && m_element_type.GetASTContext())
+ static ConstString g___value_("__value_");
+
+ if (m_element_type.GetOpaqueQualType() && m_element_type.GetTypeSystem())
return true;
m_element_type.Clear();
ValueObjectSP deref;
@@ -287,10 +299,10 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType()
deref = m_root_node->Dereference(error);
if (!deref || error.Fail())
return false;
- deref = deref->GetChildMemberWithName(ConstString("__value_"), true);
+ deref = deref->GetChildMemberWithName(g___value_, true);
if (!deref)
return false;
- m_element_type = deref->GetClangType();
+ m_element_type = deref->GetCompilerType();
return true;
}
@@ -301,7 +313,7 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset (const l
return;
if (!node)
return;
- ClangASTType node_type(node->GetClangType());
+ CompilerType node_type(node->GetCompilerType());
uint64_t bit_offset;
if (node_type.GetIndexOfFieldWithName("__value_", NULL, &bit_offset) == UINT32_MAX)
return;
@@ -313,6 +325,7 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t
{
static ConstString g___cc("__cc");
static ConstString g___nc("__nc");
+ static ConstString g___value_("__value_");
if (idx >= CalculateNumChildren())
@@ -323,10 +336,22 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t
auto cached = m_children.find(idx);
if (cached != m_children.end())
return cached->second;
-
- bool need_to_skip = (idx > 0);
+
MapIterator iterator(m_root_node, CalculateNumChildren());
- ValueObjectSP iterated_sp(iterator.advance(idx));
+
+ const bool need_to_skip = (idx > 0);
+ size_t actual_advancde = idx;
+ if (need_to_skip)
+ {
+ auto cached_iterator = m_iterators.find(idx-1);
+ if (cached_iterator != m_iterators.end())
+ {
+ iterator = cached_iterator->second;
+ actual_advancde = 1;
+ }
+ }
+
+ ValueObjectSP iterated_sp(iterator.advance(actual_advancde));
if (iterated_sp.get() == NULL)
{
// this tree is garbage - stop
@@ -345,7 +370,7 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t
return lldb::ValueObjectSP();
}
GetValueOffset(iterated_sp);
- iterated_sp = iterated_sp->GetChildMemberWithName(ConstString("__value_"), true);
+ iterated_sp = iterated_sp->GetChildMemberWithName(g___value_, true);
if (!iterated_sp)
{
m_tree = NULL;
@@ -412,19 +437,23 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t
}
potential_child_sp->SetName(ConstString(name.GetData()));
}
+ m_iterators[idx] = iterator;
return (m_children[idx] = potential_child_sp);
}
bool
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::Update()
{
+ static ConstString g___tree_("__tree_");
+ static ConstString g___begin_node_("__begin_node_");
m_count = UINT32_MAX;
m_tree = m_root_node = NULL;
m_children.clear();
- m_tree = m_backend.GetChildMemberWithName(ConstString("__tree_"), true).get();
+ m_iterators.clear();
+ m_tree = m_backend.GetChildMemberWithName(g___tree_, true).get();
if (!m_tree)
return false;
- m_root_node = m_tree->GetChildMemberWithName(ConstString("__begin_node_"), true).get();
+ m_root_node = m_tree->GetChildMemberWithName(g___begin_node_, true).get();
return false;
}
@@ -440,9 +469,6 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetIndexOfChildWithName
return ExtractIndexFromString(name.GetCString());
}
-lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::~LibcxxStdMapSyntheticFrontEnd ()
-{}
-
SyntheticChildrenFrontEnd*
lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxxUnorderedMap.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
index 4366980..8ad806d 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxxUnorderedMap.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
@@ -1,4 +1,4 @@
-//===-- LibCxxUnorderedMap.cpp -----------------------------------*- C++ -*-===//
+//===-- LibCxxUnorderedMap.cpp ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,16 +7,20 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "LibCxx.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Target.h"
using namespace lldb;
@@ -29,34 +33,33 @@ namespace lldb_private {
{
public:
LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxStdUnorderedMapSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
- virtual bool
- MightHaveChildren ();
+ bool
+ Update() override;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ bool
+ MightHaveChildren() override;
- virtual
- ~LibcxxStdUnorderedMapSyntheticFrontEnd ();
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
private:
-
ValueObject* m_tree;
size_t m_num_elements;
ValueObject* m_next_element;
std::map<size_t,lldb::ValueObjectSP> m_children;
std::vector<std::pair<ValueObject*, uint64_t> > m_elements_cache;
};
- }
-}
+ } // namespace formatters
+} // namespace lldb_private
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
@@ -125,7 +128,7 @@ lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtInde
return val_hash.first->CreateValueObjectFromData(stream.GetData(),
data,
exe_ctx,
- val_hash.first->GetClangType());
+ val_hash.first->GetCompilerType());
}
bool
@@ -160,9 +163,6 @@ lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetIndexOfChil
return ExtractIndexFromString(name.GetCString());
}
-lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::~LibcxxStdUnorderedMapSyntheticFrontEnd ()
-{}
-
SyntheticChildrenFrontEnd*
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxxVector.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
index 6ccb732..9fb4f48 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/LibCxxVector.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
@@ -1,4 +1,4 @@
-//===-- LibCxxVector.cpp -----------------------------------------*- C++ -*-===//
+//===-- LibCxxVector.cpp ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,10 +7,15 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "LibCxx.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
using namespace lldb;
using namespace lldb_private;
@@ -22,33 +27,33 @@ namespace lldb_private {
{
public:
LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxStdVectorSyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
- virtual bool
- MightHaveChildren ();
+ bool
+ Update() override;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ bool
+ MightHaveChildren() override;
- virtual
- ~LibcxxStdVectorSyntheticFrontEnd ();
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
private:
ValueObject* m_start;
ValueObject* m_finish;
- ClangASTType m_element_type;
+ CompilerType m_element_type;
uint32_t m_element_size;
std::map<size_t,lldb::ValueObjectSP> m_children;
};
- }
-}
+ } // namespace formatters
+} // namespace lldb_private
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
@@ -62,6 +67,13 @@ m_children()
Update();
}
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd()
+{
+ // these need to stay around because they are child objects who will follow their parent's life cycle
+ // delete m_start;
+ // delete m_finish;
+}
+
size_t
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren ()
{
@@ -112,7 +124,7 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update()
data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true);
if (!data_type_finder_sp)
return false;
- m_element_type = data_type_finder_sp->GetClangType().GetPointeeType();
+ m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
m_element_size = m_element_type.GetByteSize(nullptr);
if (m_element_size > 0)
@@ -138,13 +150,6 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithN
return ExtractIndexFromString(name.GetCString());
}
-lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd ()
-{
- // these need to stay around because they are child objects who will follow their parent's life cycle
- // delete m_start;
- // delete m_finish;
-}
-
lldb_private::SyntheticChildrenFrontEnd*
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
@@ -152,4 +157,3 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticC
return NULL;
return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp));
}
-
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
new file mode 100644
index 0000000..ed89c5c
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -0,0 +1,373 @@
+//===-- LibStdcpp.cpp ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibStdcpp.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/VectorIterator.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+ LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName (const ConstString &name) override;
+
+ ~LibstdcppMapIteratorSyntheticFrontEnd() override;
+
+private:
+ ExecutionContextRef m_exe_ctx_ref;
+ lldb::addr_t m_pair_address;
+ CompilerType m_pair_type;
+ EvaluateExpressionOptions m_options;
+ lldb::ValueObjectSP m_pair_sp;
+};
+
+/*
+ (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) ibeg = {
+ (_Base_ptr) _M_node = 0x0000000100103910 {
+ (std::_Rb_tree_color) _M_color = _S_black
+ (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0
+ (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000
+ (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000
+ }
+ }
+ */
+
+LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+ SyntheticChildrenFrontEnd(*valobj_sp.get()),
+ m_exe_ctx_ref(),
+ m_pair_address(0),
+ m_pair_type(),
+ m_options(),
+ m_pair_sp()
+{
+ if (valobj_sp)
+ Update();
+ m_options.SetCoerceToId(false);
+ m_options.SetUnwindOnError(true);
+ m_options.SetKeepInMemory(true);
+ m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
+}
+
+bool
+LibstdcppMapIteratorSyntheticFrontEnd::Update()
+{
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return false;
+
+ TargetSP target_sp(valobj_sp->GetTargetSP());
+
+ if (!target_sp)
+ return false;
+
+ bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8);
+
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+
+ ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true));
+ if (!_M_node_sp)
+ return false;
+
+ m_pair_address = _M_node_sp->GetValueAsUnsigned(0);
+ if (m_pair_address == 0)
+ return false;
+
+ m_pair_address += (is_64bit ? 32 : 16);
+
+ CompilerType my_type(valobj_sp->GetCompilerType());
+ if (my_type.GetNumTemplateArguments() >= 1)
+ {
+ TemplateArgumentKind kind;
+ CompilerType pair_type = my_type.GetTemplateArgument(0, kind);
+ if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion)
+ return false;
+ m_pair_type = pair_type;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+size_t
+LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
+{
+ return 2;
+}
+
+lldb::ValueObjectSP
+LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (m_pair_address != 0 && m_pair_type)
+ {
+ if (!m_pair_sp)
+ m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type);
+ if (m_pair_sp)
+ return m_pair_sp->GetChildAtIndex(idx, true);
+ }
+ return lldb::ValueObjectSP();
+}
+
+bool
+LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (name == ConstString("first"))
+ return 0;
+ if (name == ConstString("second"))
+ return 1;
+ return UINT32_MAX;
+}
+
+LibstdcppMapIteratorSyntheticFrontEnd::~LibstdcppMapIteratorSyntheticFrontEnd ()
+{}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp));
+}
+
+/*
+ (lldb) fr var ibeg --ptr-depth 1
+ (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >) ibeg = {
+ _M_current = 0x00000001001037a0 {
+ *_M_current = 1
+ }
+ }
+ */
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ static ConstString g_item_name;
+ if (!g_item_name)
+ g_item_name.SetCString("_M_current");
+ if (!valobj_sp)
+ return NULL;
+ return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
+}
+
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
+ ConstString item_name) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_exe_ctx_ref(),
+m_item_name(item_name),
+m_item_sp()
+{
+ if (valobj_sp)
+ Update();
+}
+
+bool
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
+{
+ m_item_sp.reset();
+
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return false;
+
+ if (!valobj_sp)
+ return false;
+
+ ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
+ if (!item_ptr)
+ return false;
+ if (item_ptr->GetValueAsUnsigned(0) == 0)
+ return false;
+ Error err;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetCompilerType().GetPointeeType());
+ if (err.Fail())
+ m_item_sp.reset();
+ return false;
+}
+
+size_t
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
+{
+ return 1;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (idx == 0)
+ return m_item_sp;
+ return lldb::ValueObjectSP();
+}
+
+bool
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (name == ConstString("item"))
+ return 0;
+ return UINT32_MAX;
+}
+
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
+{
+}
+
+bool
+lldb_private::formatters::LibStdcppStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ const bool scalar_is_load_addr = true;
+ AddressType addr_type;
+ lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
+ if (addr_of_string != LLDB_INVALID_ADDRESS)
+ {
+ switch (addr_type)
+ {
+ case eAddressTypeLoad:
+ {
+ ProcessSP process_sp(valobj.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ Error error;
+ lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error);
+ if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS)
+ return false;
+ options.SetLocation(addr_of_data);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetNeedsZeroTermination(false);
+ options.SetBinaryZeroIsTerminator(true);
+ lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error);
+ if (error.Fail())
+ return false;
+ options.SetSourceSize(size_of_data);
+
+ if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options))
+ {
+ stream.Printf("Summary Unavailable");
+ return true;
+ }
+ else
+ return true;
+ }
+ break;
+ case eAddressTypeHost:
+ break;
+ case eAddressTypeInvalid:
+ case eAddressTypeFile:
+ break;
+ }
+ }
+ return false;
+}
+
+bool
+lldb_private::formatters::LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ const bool scalar_is_load_addr = true;
+ AddressType addr_type;
+ lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
+ if (addr_of_string != LLDB_INVALID_ADDRESS)
+ {
+ switch (addr_type)
+ {
+ case eAddressTypeLoad:
+ {
+ ProcessSP process_sp(valobj.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
+
+ if (!wchar_compiler_type)
+ return false;
+
+ const uint32_t wchar_size = wchar_compiler_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ Error error;
+ lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error);
+ if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS)
+ return false;
+ options.SetLocation(addr_of_data);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetNeedsZeroTermination(false);
+ options.SetBinaryZeroIsTerminator(false);
+ lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error);
+ if (error.Fail())
+ return false;
+ options.SetSourceSize(size_of_data);
+ options.SetPrefixToken("L");
+
+ switch (wchar_size)
+ {
+ case 8:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options);
+ case 16:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+ case 32:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options);
+ default:
+ stream.Printf("size for wchar_t is not valid");
+ return true;
+ }
+ return true;
+ }
+ break;
+ case eAddressTypeHost:
+ break;
+ case eAddressTypeInvalid:
+ case eAddressTypeFile:
+ break;
+ }
+ }
+ return false;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
new file mode 100644
index 0000000..347856a
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
@@ -0,0 +1,33 @@
+//===-- LibStdCpp.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_LibStdCpp_h_
+#define liblldb_LibStdCpp_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ bool
+ LibStdcppStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libcstdc++ c++11 std::string
+
+ bool
+ LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libcstdc++ c++11 std::wstring
+
+ SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_LibStdCpp_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoFormatterFunctions.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoFormatterFunctions.cpp
new file mode 100644
index 0000000..1d7cd76
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoFormatterFunctions.cpp
@@ -0,0 +1,173 @@
+//===-- GoFormatterFunctions.cpp---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include <map>
+
+// Other libraries and framework includes
+// Project includes
+#include "GoFormatterFunctions.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace
+{
+class GoSliceSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+ public:
+ GoSliceSyntheticFrontEnd(ValueObject &valobj)
+ : SyntheticChildrenFrontEnd(valobj)
+ {
+ Update();
+ }
+
+ ~GoSliceSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override
+ {
+ return m_len;
+ }
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
+ {
+ if (idx < m_len)
+ {
+ ValueObjectSP &cached = m_children[idx];
+ if (!cached)
+ {
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ lldb::addr_t object_at_idx = m_base_data_address;
+ object_at_idx += idx * m_type.GetByteSize(nullptr);
+ cached = CreateValueObjectFromAddress(idx_name.GetData(), object_at_idx,
+ m_backend.GetExecutionContextRef(), m_type);
+ }
+ return cached;
+ }
+ return ValueObjectSP();
+ }
+
+ bool
+ Update() override
+ {
+ size_t old_count = m_len;
+
+ ConstString array_const_str("array");
+ ValueObjectSP array_sp = m_backend.GetChildMemberWithName(array_const_str, true);
+ if (!array_sp)
+ {
+ m_children.clear();
+ return old_count == 0;
+ }
+ m_type = array_sp->GetCompilerType().GetPointeeType();
+ m_base_data_address = array_sp->GetPointerValue();
+
+ ConstString len_const_str("len");
+ ValueObjectSP len_sp = m_backend.GetChildMemberWithName(len_const_str, true);
+ if (len_sp)
+ {
+ m_len = len_sp->GetValueAsUnsigned(0);
+ m_children.clear();
+ }
+
+ return old_count == m_len;
+ }
+
+ bool
+ MightHaveChildren() override
+ {
+ return true;
+ }
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override
+ {
+ return ExtractIndexFromString(name.AsCString());
+ }
+
+ private:
+ CompilerType m_type;
+ lldb::addr_t m_base_data_address;
+ size_t m_len;
+ std::map<size_t, lldb::ValueObjectSP> m_children;
+};
+
+} // anonymous namespace
+
+bool
+lldb_private::formatters::GoStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ if (valobj.IsPointerType())
+ {
+ Error err;
+ ValueObjectSP deref = valobj.Dereference(err);
+ if (!err.Success())
+ return false;
+ return GoStringSummaryProvider(*deref, stream, opts);
+ }
+
+ ConstString str_name("str");
+ ConstString len_name("len");
+
+ ValueObjectSP data_sp = valobj.GetChildMemberWithName(str_name, true);
+ ValueObjectSP len_sp = valobj.GetChildMemberWithName(len_name, true);
+ if (!data_sp || !len_sp)
+ return false;
+ bool success;
+ lldb::addr_t valobj_addr = data_sp->GetValueAsUnsigned(0, &success);
+
+ if (!success)
+ return false;
+
+ uint64_t length = len_sp->GetValueAsUnsigned(0);
+ if (length == 0)
+ {
+ stream.Printf("\"\"");
+ return true;
+ }
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(valobj_addr);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetSourceSize(length);
+ options.SetNeedsZeroTermination(false);
+ options.SetLanguage(eLanguageTypeGo);
+
+ if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options))
+ {
+ stream.Printf("Summary Unavailable");
+ return true;
+ }
+
+ return true;
+}
+
+SyntheticChildrenFrontEnd *
+lldb_private::formatters::GoSliceSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return nullptr;
+
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return nullptr;
+ return new GoSliceSyntheticFrontEnd(*valobj_sp);
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoFormatterFunctions.h b/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoFormatterFunctions.h
new file mode 100644
index 0000000..ae1eda0
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoFormatterFunctions.h
@@ -0,0 +1,43 @@
+//===-- GoFormatterFunctions.h-----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoFormatterFunctions_h_
+#define liblldb_GoFormatterFunctions_h_
+
+// C Includes
+#include <stdint.h>
+#include <time.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+
+// Project includes
+#include "lldb/lldb-forward.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/DataFormatters/FormatClasses.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
+
+namespace lldb_private
+{
+namespace formatters
+{
+
+bool GoStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options);
+
+SyntheticChildrenFrontEnd *GoSliceSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP);
+
+} // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_GoFormatterFunctions_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoLanguage.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoLanguage.cpp
new file mode 100644
index 0000000..ed010ff
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoLanguage.cpp
@@ -0,0 +1,146 @@
+//===-- GoLanguage.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <string.h>
+// C++ Includes
+#include <functional>
+#include <mutex>
+
+// Other libraries and framework includes
+#include "llvm/ADT/StringRef.h"
+
+// Project includes
+#include "GoLanguage.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Symbol/GoASTContext.h"
+#include "Plugins/Language/Go/GoFormatterFunctions.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+void
+GoLanguage::Initialize()
+{
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), "Go Language", CreateInstance);
+}
+
+void
+GoLanguage::Terminate()
+{
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+lldb_private::ConstString
+GoLanguage::GetPluginNameStatic()
+{
+ static ConstString g_name("Go");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+GoLanguage::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+GoLanguage::GetPluginVersion()
+{
+ return 1;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+Language *
+GoLanguage::CreateInstance(lldb::LanguageType language)
+{
+ if (language == eLanguageTypeGo)
+ return new GoLanguage();
+ return nullptr;
+}
+
+HardcodedFormatters::HardcodedSummaryFinder
+GoLanguage::GetHardcodedSummaries()
+{
+ static std::once_flag g_initialize;
+ static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
+
+ std::call_once(g_initialize, []() -> void
+ {
+ g_formatters.push_back(
+ [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
+ FormatManager &) -> TypeSummaryImpl::SharedPointer
+ {
+ static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(
+ TypeSummaryImpl::Flags().SetDontShowChildren(true),
+ lldb_private::formatters::GoStringSummaryProvider, "Go string summary provider"));
+ if (GoASTContext::IsGoString(valobj.GetCompilerType()))
+ {
+ return formatter_sp;
+ }
+ if (GoASTContext::IsGoString(valobj.GetCompilerType().GetPointeeType()))
+ {
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ g_formatters.push_back(
+ [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
+ FormatManager &) -> TypeSummaryImpl::SharedPointer
+ {
+ static lldb::TypeSummaryImplSP formatter_sp(
+ new StringSummaryFormat(TypeSummaryImpl::Flags().SetHideItemNames(true),
+ "(len ${var.len}, cap ${var.cap})"));
+ if (GoASTContext::IsGoSlice(valobj.GetCompilerType()))
+ {
+ return formatter_sp;
+ }
+ if (GoASTContext::IsGoSlice(valobj.GetCompilerType().GetPointeeType()))
+ {
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ });
+ return g_formatters;
+}
+
+HardcodedFormatters::HardcodedSyntheticFinder
+GoLanguage::GetHardcodedSynthetics()
+{
+ static std::once_flag g_initialize;
+ static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
+
+ std::call_once(g_initialize, []() -> void
+ {
+ g_formatters.push_back(
+ [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
+ FormatManager &fmt_mgr) -> SyntheticChildren::SharedPointer
+ {
+ static CXXSyntheticChildren::SharedPointer formatter_sp(
+ new CXXSyntheticChildren(SyntheticChildren::Flags(), "slice synthetic children",
+ lldb_private::formatters::GoSliceSyntheticFrontEndCreator));
+ if (GoASTContext::IsGoSlice(valobj.GetCompilerType()))
+ {
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ });
+
+ return g_formatters;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoLanguage.h b/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoLanguage.h
new file mode 100644
index 0000000..67dd04c
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/Go/GoLanguage.h
@@ -0,0 +1,66 @@
+//===-- GoLanguage.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoLanguage_h_
+#define liblldb_GoLanguage_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "llvm/ADT/StringRef.h"
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Target/Language.h"
+
+namespace lldb_private
+{
+
+class GoLanguage : public Language
+{
+ public:
+ GoLanguage() = default;
+
+ ~GoLanguage() override = default;
+
+ lldb::LanguageType
+ GetLanguageType() const override
+ {
+ return lldb::eLanguageTypeGo;
+ }
+
+ HardcodedFormatters::HardcodedSummaryFinder GetHardcodedSummaries() override;
+
+ HardcodedFormatters::HardcodedSyntheticFinder GetHardcodedSynthetics() override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb_private::Language *CreateInstance(lldb::LanguageType language);
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_GoLanguage_h_
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/CF.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CF.cpp
index 6ab9013..614eb29 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/CF.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CF.cpp
@@ -7,16 +7,19 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+#include "CF.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
using namespace lldb;
@@ -41,6 +44,8 @@ lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, St
bool
lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
+ static ConstString g_TypeHint("CFBag");
+
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
return false;
@@ -83,7 +88,9 @@ lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& str
ValueObjectSP count_sp;
StreamString expr;
expr.Printf("(int)CFBagGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
- if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExpressionCompleted)
+ EvaluateExpressionOptions options;
+ options.SetResultIsInternal(true);
+ if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp, options) != eExpressionCompleted)
return false;
if (!count_sp)
return false;
@@ -97,8 +104,21 @@ lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& str
if (error.Fail())
return false;
}
- stream.Printf("@\"%u value%s\"",
- count,(count == 1 ? "" : "s"));
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s\"%u value%s\"%s",
+ prefix.c_str(),
+ count,(count == 1 ? "" : "s"),
+ suffix.c_str());
return true;
}
@@ -235,6 +255,8 @@ lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Strea
bool
lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
+ static ConstString g_TypeHint("CFBinaryHeap");
+
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
return false;
@@ -277,7 +299,9 @@ lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stre
ValueObjectSP count_sp;
StreamString expr;
expr.Printf("(int)CFBinaryHeapGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
- if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExpressionCompleted)
+ EvaluateExpressionOptions options;
+ options.SetResultIsInternal(true);
+ if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp, options) != eExpressionCompleted)
return false;
if (!count_sp)
return false;
@@ -291,7 +315,20 @@ lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stre
if (error.Fail())
return false;
}
- stream.Printf("@\"%u item%s\"",
- count,(count == 1 ? "" : "s"));
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s\"%u item%s\"%s",
+ prefix.c_str(),
+ count,(count == 1 ? "" : "s"),
+ suffix.c_str());
return true;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CF.h b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CF.h
new file mode 100644
index 0000000..4044f09
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CF.h
@@ -0,0 +1,34 @@
+//===-- CF.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CF_h_
+#define liblldb_CF_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ bool
+ CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CF_h_
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/Cocoa.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
index 28f3d4f..aa6e476 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/Cocoa.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -1,4 +1,4 @@
-//===-- Cocoa.cpp -------------------------------------------------*- C++ -*-===//
+//===-- Cocoa.cpp -----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,17 +7,30 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "Cocoa.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
+#include "lldb/Core/Mangled.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/ProcessStructReader.h"
+
+#include "NSString.h"
using namespace lldb;
using namespace lldb_private;
@@ -55,8 +68,8 @@ lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream&
if (!strcmp(class_name,"NSBundle"))
{
uint64_t offset = 5 * ptr_size;
- ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true));
-
+ ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true));
+
StreamString summary_stream;
bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
if (was_nsstring_ok && summary_stream.GetSize() > 0)
@@ -67,7 +80,7 @@ lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream&
}
// this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle]
// which is encoded differently and needs to be handled by running code
- return ExtractSummaryFromObjCExpression(valobj, "NSString*", "bundlePath", stream);
+ return ExtractSummaryFromObjCExpression(valobj, "NSString*", "bundlePath", stream, options.GetLanguage());
}
bool
@@ -102,7 +115,7 @@ lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream
if (!strcmp(class_name,"__NSTimeZone"))
{
uint64_t offset = ptr_size;
- ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType(), true));
+ ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType(), true));
StreamString summary_stream;
bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
if (was_nsstring_ok && summary_stream.GetSize() > 0)
@@ -111,7 +124,7 @@ lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream
return true;
}
}
- return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream);
+ return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream, options.GetLanguage());
}
bool
@@ -146,7 +159,7 @@ lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, St
if (!strcmp(class_name,"NSConcreteNotification"))
{
uint64_t offset = ptr_size;
- ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType(), true));
+ ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType(), true));
StreamString summary_stream;
bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
if (was_nsstring_ok && summary_stream.GetSize() > 0)
@@ -157,7 +170,7 @@ lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, St
}
// this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle]
// which is encoded differently and needs to be handled by running code
- return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream);
+ return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream, options.GetLanguage());
}
bool
@@ -287,6 +300,150 @@ lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream
return true;
}
+static void
+NSNumber_FormatChar (ValueObject& valobj,
+ Stream& stream,
+ char value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:char");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%hhd%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
+static void
+NSNumber_FormatShort (ValueObject& valobj,
+ Stream& stream,
+ short value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:short");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%hd%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
+static void
+NSNumber_FormatInt (ValueObject& valobj,
+ Stream& stream,
+ int value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:int");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%d%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
+static void
+NSNumber_FormatLong (ValueObject& valobj,
+ Stream& stream,
+ uint64_t value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:long");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%" PRId64 "%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
+static void
+NSNumber_FormatFloat (ValueObject& valobj,
+ Stream& stream,
+ float value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:float");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%f%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
+static void
+NSNumber_FormatDouble (ValueObject& valobj,
+ Stream& stream,
+ double value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:double");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%g%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
bool
lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
@@ -325,19 +482,19 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream&
switch (i_bits)
{
case 0:
- stream.Printf("(char)%hhd",(char)value);
+ NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
break;
case 1:
case 4:
- stream.Printf("(short)%hd",(short)value);
+ NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage());
break;
case 2:
case 8:
- stream.Printf("(int)%d",(int)value);
+ NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage());
break;
case 3:
case 12:
- stream.Printf("(long)%" PRId64,value);
+ NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
break;
default:
return false;
@@ -358,19 +515,19 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream&
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, error);
if (error.Fail())
return false;
- stream.Printf("(char)%hhd",(char)value);
+ NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
break;
case 2: // 0B0010
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, error);
if (error.Fail())
return false;
- stream.Printf("(short)%hd",(short)value);
+ NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage());
break;
case 3: // 0B0011
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error);
if (error.Fail())
return false;
- stream.Printf("(int)%d",(int)value);
+ NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage());
break;
case 17: // 0B10001
data_location += 8;
@@ -378,7 +535,7 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream&
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error);
if (error.Fail())
return false;
- stream.Printf("(long)%" PRId64,value);
+ NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
break;
case 5: // 0B0101
{
@@ -386,7 +543,7 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream&
if (error.Fail())
return false;
float flt_value = *((float*)&flt_as_int);
- stream.Printf("(float)%f",flt_value);
+ NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage());
break;
}
case 6: // 0B0110
@@ -395,7 +552,7 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream&
if (error.Fail())
return false;
double dbl_value = *((double*)&dbl_as_lng);
- stream.Printf("(double)%g",dbl_value);
+ NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage());
break;
}
default:
@@ -406,7 +563,7 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream&
}
else
{
- return ExtractSummaryFromObjCExpression(valobj, "NSString*", "stringValue", stream);
+ return ExtractSummaryFromObjCExpression(valobj, "NSString*", "stringValue", stream, options.GetLanguage());
}
}
@@ -443,7 +600,7 @@ lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& str
{
uint64_t offset_text = ptr_size + ptr_size + 8; // ISA + pointer + 8 bytes of data (even on 32bit)
uint64_t offset_base = offset_text + ptr_size;
- ClangASTType type(valobj.GetClangType());
+ CompilerType type(valobj.GetCompilerType());
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset_text, type, true));
ValueObjectSP base(valobj.GetSyntheticChildAtOffset(offset_base, type, true));
if (!text)
@@ -470,7 +627,7 @@ lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& str
}
else
{
- return ExtractSummaryFromObjCExpression(valobj, "NSString*", "description", stream);
+ return ExtractSummaryFromObjCExpression(valobj, "NSString*", "description", stream, options.GetLanguage());
}
return false;
}
@@ -559,3 +716,252 @@ lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& st
stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
return true;
}
+
+bool
+lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ ConstString class_name = descriptor->GetClassName();
+
+ if (class_name.IsEmpty())
+ return false;
+
+ if (ConstString cs = Mangled(class_name).GetDemangledName(lldb::eLanguageTypeUnknown))
+ class_name = cs;
+
+ stream.Printf("%s",class_name.AsCString("<unknown class>"));
+ return true;
+}
+
+class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+ ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
+ SyntheticChildrenFrontEnd(*valobj_sp.get())
+ {
+ }
+
+ ~ObjCClassSyntheticChildrenFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override
+ {
+ return 0;
+ }
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
+ {
+ return lldb::ValueObjectSP();
+ }
+
+ bool
+ Update() override
+ {
+ return false;
+ }
+
+ bool
+ MightHaveChildren() override
+ {
+ return false;
+ }
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override
+ {
+ return UINT32_MAX;
+ }
+};
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
+}
+
+template<bool needs_at>
+bool
+lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ bool is_64bit = (process_sp->GetAddressByteSize() == 8);
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ uint64_t value = 0;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ if (!strcmp(class_name,"NSConcreteData") ||
+ !strcmp(class_name,"NSConcreteMutableData") ||
+ !strcmp(class_name,"__NSCFData"))
+ {
+ uint32_t offset = (is_64bit ? 16 : 8);
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
+ if (error.Fail())
+ return false;
+ }
+ else
+ {
+ if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
+ return false;
+ }
+
+ stream.Printf("%s%" PRIu64 " byte%s%s",
+ (needs_at ? "@\"" : ""),
+ value,
+ (value != 1 ? "s" : ""),
+ (needs_at ? "\"" : ""));
+
+ return true;
+}
+
+bool
+lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ const uint32_t type_info = valobj.GetCompilerType().GetTypeInfo();
+
+ ValueObjectSP real_guy_sp = valobj.GetSP();
+
+ if (type_info & eTypeIsPointer)
+ {
+ Error err;
+ real_guy_sp = valobj.Dereference(err);
+ if (err.Fail() || !real_guy_sp)
+ return false;
+ }
+ else if (type_info & eTypeIsReference)
+ {
+ real_guy_sp = valobj.GetChildAtIndex(0, true);
+ if (!real_guy_sp)
+ return false;
+ }
+ uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
+ if (value == 0)
+ {
+ stream.Printf("NO");
+ return true;
+ }
+ stream.Printf("YES");
+ return true;
+}
+
+template <bool is_sel_ptr>
+bool
+lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ lldb::ValueObjectSP valobj_sp;
+
+ CompilerType charstar (valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
+
+ if (!charstar)
+ return false;
+
+ ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
+
+ if (is_sel_ptr)
+ {
+ lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ if (data_address == LLDB_INVALID_ADDRESS)
+ return false;
+ valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
+ }
+ else
+ {
+ DataExtractor data;
+ Error error;
+ valobj.GetData(data, error);
+ if (error.Fail())
+ return false;
+ valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
+ }
+
+ if (!valobj_sp)
+ return false;
+
+ stream.Printf("%s",valobj_sp->GetSummaryAsCString());
+ return true;
+}
+
+// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
+// this call gives the POSIX equivalent of the Cocoa epoch
+time_t
+lldb_private::formatters::GetOSXEpoch ()
+{
+ static time_t epoch = 0;
+ if (!epoch)
+ {
+#ifndef _WIN32
+ tzset();
+ tm tm_epoch;
+ tm_epoch.tm_sec = 0;
+ tm_epoch.tm_hour = 0;
+ tm_epoch.tm_min = 0;
+ tm_epoch.tm_mon = 0;
+ tm_epoch.tm_mday = 1;
+ tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
+ tm_epoch.tm_isdst = -1;
+ tm_epoch.tm_gmtoff = 0;
+ tm_epoch.tm_zone = NULL;
+ epoch = timegm(&tm_epoch);
+#endif
+ }
+ return epoch;
+}
+
+bool
+lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ if (const char* description = valobj.GetObjectDescription())
+ {
+ stream.Printf("%s", description);
+ return true;
+ }
+ else
+ return false;
+}
+
+template bool
+lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&);
+
+template bool
+lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&);
+
+template bool
+lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&);
+
+template bool
+lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.h b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.h
new file mode 100644
index 0000000..0caacf3
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/Cocoa.h
@@ -0,0 +1,97 @@
+//===-- Cocoa.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Cocoa_h_
+#define liblldb_Cocoa_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ bool
+ NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ template<bool needs_at>
+ bool
+ NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ extern template bool
+ NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+ extern template bool
+ NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+ SyntheticChildrenFrontEnd* NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ bool
+ ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ SyntheticChildrenFrontEnd* ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ bool
+ ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ template <bool is_sel_ptr>
+ bool
+ ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ extern template bool
+ ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&);
+
+ extern template bool
+ ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&);
+
+ bool
+ RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSError_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSException_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ SyntheticChildrenFrontEnd*
+ NSErrorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp);
+
+ SyntheticChildrenFrontEnd*
+ NSExceptionSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp);
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_Cocoa_h_
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/CoreMedia.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
index 5c33c0b..4103067 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/CoreMedia.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
@@ -7,11 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+#include "CoreMedia.h"
#include "lldb/Core/Flags.h"
-#include "lldb/Symbol/ClangASTContext.h"
-
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Target/Target.h"
#include <inttypes.h>
using namespace lldb;
@@ -21,13 +21,17 @@ using namespace lldb_private::formatters;
bool
lldb_private::formatters::CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
- ClangASTContext *ast_ctx = ClangASTContext::GetASTContext(valobj.GetClangType().GetASTContext());
- if (!ast_ctx)
+ CompilerType type = valobj.GetCompilerType();
+ if (!type.IsValid())
+ return false;
+
+ TypeSystem *type_system = valobj.GetExecutionContextRef().GetTargetSP()->GetScratchTypeSystemForLanguage(nullptr, lldb::eLanguageTypeC);
+ if (!type_system)
return false;
// fetch children by offset to compensate for potential lack of debug info
- auto int64_ty = ast_ctx->GetIntTypeFromBitSize(64, true);
- auto int32_ty = ast_ctx->GetIntTypeFromBitSize(32, true);
+ auto int64_ty = type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 64);
+ auto int32_ty = type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 32);
auto value_sp(valobj.GetSyntheticChildAtOffset(0, int64_ty, true));
auto timescale_sp(valobj.GetSyntheticChildAtOffset(8, int32_ty, true));
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CoreMedia.h b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CoreMedia.h
new file mode 100644
index 0000000..2ffabaa
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/CoreMedia.h
@@ -0,0 +1,26 @@
+//===-- CoreMedia.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CoreMedia_h_
+#define liblldb_CoreMedia_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+
+ bool
+ CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CF_h_
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/NSArray.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSArray.cpp
index 0bade8a..ccc82ab 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/NSArray.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSArray.cpp
@@ -7,20 +7,28 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+
+// Project includes
+#include "Cocoa.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
#include "lldb/Target/Target.h"
-#include "clang/AST/ASTContext.h"
-
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
@@ -31,24 +39,23 @@ namespace lldb_private {
{
public:
NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayMSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update() = 0;
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
- virtual bool
- MightHaveChildren ();
+ bool
+ Update() override = 0;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ bool
+ MightHaveChildren() override;
- virtual
- ~NSArrayMSyntheticFrontEnd () {}
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
protected:
virtual lldb::addr_t
@@ -65,12 +72,33 @@ namespace lldb_private {
ExecutionContextRef m_exe_ctx_ref;
uint8_t m_ptr_size;
- ClangASTType m_id_type;
+ CompilerType m_id_type;
std::vector<lldb::ValueObjectSP> m_children;
};
class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd
{
+ public:
+ NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayMSyntheticFrontEnd_109() override;
+
+ bool
+ Update() override;
+
+ protected:
+ lldb::addr_t
+ GetDataAddress() override;
+
+ uint64_t
+ GetUsedCount() override;
+
+ uint64_t
+ GetOffset() override;
+
+ uint64_t
+ GetSize() override;
+
private:
struct DataDescriptor_32
{
@@ -82,6 +110,7 @@ namespace lldb_private {
uint32_t _priv3;
uint32_t _data;
};
+
struct DataDescriptor_64
{
uint64_t _used;
@@ -92,36 +121,35 @@ namespace lldb_private {
uint32_t _priv3;
uint64_t _data;
};
+
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ };
+
+ class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd
+ {
public:
- NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp);
-
- virtual bool
- Update();
-
- virtual
- ~NSArrayMSyntheticFrontEnd_109 ();
+ NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayMSyntheticFrontEnd_1010() override;
+
+ bool
+ Update() override;
protected:
- virtual lldb::addr_t
- GetDataAddress ();
+ lldb::addr_t
+ GetDataAddress() override;
- virtual uint64_t
- GetUsedCount ();
+ uint64_t
+ GetUsedCount() override;
- virtual uint64_t
- GetOffset ();
+ uint64_t
+ GetOffset() override;
- virtual uint64_t
- GetSize ();
+ uint64_t
+ GetSize() override;
private:
- DataDescriptor_32 *m_data_32;
- DataDescriptor_64 *m_data_64;
- };
-
- class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd
- {
- private:
struct DataDescriptor_32
{
uint32_t _used;
@@ -131,6 +159,7 @@ namespace lldb_private {
uint32_t _priv2;
uint32_t _data;
};
+
struct DataDescriptor_64
{
uint64_t _used;
@@ -140,29 +169,7 @@ namespace lldb_private {
uint32_t _priv2;
uint64_t _data;
};
- public:
- NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp);
-
- virtual bool
- Update();
-
- virtual
- ~NSArrayMSyntheticFrontEnd_1010 ();
-
- protected:
- virtual lldb::addr_t
- GetDataAddress ();
-
- virtual uint64_t
- GetUsedCount ();
-
- virtual uint64_t
- GetOffset ();
-
- virtual uint64_t
- GetSize ();
-
- private:
+
DataDescriptor_32 *m_data_32;
DataDescriptor_64 *m_data_64;
};
@@ -171,62 +178,86 @@ namespace lldb_private {
{
public:
NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayISyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
- virtual bool
- MightHaveChildren ();
+ bool
+ Update() override;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ bool
+ MightHaveChildren() override;
- virtual
- ~NSArrayISyntheticFrontEnd ();
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
private:
ExecutionContextRef m_exe_ctx_ref;
uint8_t m_ptr_size;
uint64_t m_items;
lldb::addr_t m_data_ptr;
- ClangASTType m_id_type;
+ CompilerType m_id_type;
std::vector<lldb::ValueObjectSP> m_children;
};
- class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
- NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+ NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArray0SyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
- virtual size_t
- CalculateNumChildren ();
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
+ bool
+ Update() override;
- virtual bool
- Update();
+ bool
+ MightHaveChildren() override;
- virtual bool
- MightHaveChildren ();
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+ };
+
+ class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayCodeRunningSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ bool
+ MightHaveChildren() override;
- virtual
- ~NSArrayCodeRunningSyntheticFrontEnd ();
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
};
- }
-}
+ } // namespace formatters
+} // namespace lldb_private
bool
lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
+ static ConstString g_TypeHint("NSArray");
+
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
return false;
@@ -269,6 +300,10 @@ lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& s
if (error.Fail())
return false;
}
+ else if (!strcmp(class_name,"__NSArray0"))
+ {
+ value = 0;
+ }
else if (!strcmp(class_name,"__NSCFArray"))
{
Error error;
@@ -282,16 +317,29 @@ lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& s
return false;
}
- stream.Printf("@\"%" PRIu64 " object%s\"",
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%" PRIu64 " %s%s%s",
+ prefix.c_str(),
value,
- value == 1 ? "" : "s");
+ "element",
+ value == 1 ? "" : "s",
+ suffix.c_str());
return true;
}
lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp),
- m_exe_ctx_ref(),
- m_ptr_size(8),
+m_exe_ctx_ref(),
+m_ptr_size(8),
m_id_type(),
m_children()
{
@@ -299,7 +347,7 @@ m_children()
{
clang::ASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext()->getASTContext();
if (ast)
- m_id_type = ClangASTType(ast, ast->ObjCBuiltinIdTy);
+ m_id_type = CompilerType(ast, ast->ObjCBuiltinIdTy);
if (valobj_sp->GetProcessSP())
m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
}
@@ -432,6 +480,14 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (co
return idx;
}
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109()
+{
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+}
+
lldb::addr_t
lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress ()
{
@@ -468,7 +524,7 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize ()
m_data_64->_size;
}
-lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109 ()
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010()
{
delete m_data_32;
m_data_32 = NULL;
@@ -512,33 +568,25 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize ()
m_data_64->_size;
}
-lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010 ()
-{
- delete m_data_32;
- m_data_32 = NULL;
- delete m_data_64;
- m_data_64 = NULL;
-}
-
lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
- SyntheticChildrenFrontEnd (*valobj_sp.get()),
- m_exe_ctx_ref (),
- m_ptr_size (8),
- m_items (0),
- m_data_ptr (0)
+SyntheticChildrenFrontEnd (*valobj_sp.get()),
+m_exe_ctx_ref (),
+m_ptr_size (8),
+m_items (0),
+m_data_ptr (0)
{
if (valobj_sp)
{
- clang::ASTContext *ast = valobj_sp->GetClangType().GetASTContext();
- if (ast)
- m_id_type = ClangASTType(ast, ast->ObjCBuiltinIdTy);
+ CompilerType type = valobj_sp->GetCompilerType();
+ if (type)
+ {
+ ClangASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext();
+ if (ast)
+ m_id_type = CompilerType(ast->getASTContext(), ast->getASTContext()->ObjCBuiltinIdTy);
+ }
}
}
-lldb_private::formatters::NSArrayISyntheticFrontEnd::~NSArrayISyntheticFrontEnd ()
-{
-}
-
size_t
lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
{
@@ -609,21 +657,54 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx
return retval_sp;
}
+lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd (*valobj_sp.get())
+{
+}
+
+size_t
+lldb_private::formatters::NSArray0SyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ return UINT32_MAX;
+}
+
+size_t
+lldb_private::formatters::NSArray0SyntheticFrontEnd::CalculateNumChildren ()
+{
+ return 0;
+}
+
+bool
+lldb_private::formatters::NSArray0SyntheticFrontEnd::Update()
+{
+ return false;
+}
+
+bool
+lldb_private::formatters::NSArray0SyntheticFrontEnd::MightHaveChildren ()
+{
+ return false;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ return lldb::ValueObjectSP();
+}
+
SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
- return nullptr; // Avoid need for AppleObjCRuntime on FreeBSD
-#if 0
if (!valobj_sp)
return nullptr;
lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
if (!process_sp)
return NULL;
- AppleObjCRuntime *runtime = (AppleObjCRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+ AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime());
if (!runtime)
return NULL;
- ClangASTType valobj_type(valobj_sp->GetClangType());
+ CompilerType valobj_type(valobj_sp->GetCompilerType());
Flags flags(valobj_type.GetTypeInfo());
if (flags.IsClear(eTypeIsPointer))
@@ -648,6 +729,10 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCre
{
return (new NSArrayISyntheticFrontEnd(valobj_sp));
}
+ else if (!strcmp(class_name,"__NSArray0"))
+ {
+ return (new NSArray0SyntheticFrontEnd(valobj_sp));
+ }
else if (!strcmp(class_name,"__NSArrayM"))
{
if (runtime->GetFoundationVersion() >= 1100)
@@ -659,7 +744,6 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCre
{
return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp));
}
-#endif
}
lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
@@ -682,7 +766,10 @@ lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
if (valobj_sp)
+ {
+ valobj_sp->SetPreferredDisplayLanguage(m_backend.GetPreferredDisplayLanguage());
valobj_sp->SetName(ConstString(idx_name.GetData()));
+ }
return valobj_sp;
}
@@ -703,6 +790,3 @@ lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWi
{
return 0;
}
-
-lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::~NSArrayCodeRunningSyntheticFrontEnd ()
-{}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/NSDictionary.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
index 30bc3ac..e4a7425 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/NSDictionary.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -1,4 +1,4 @@
-//===-- NSDictionary.cpp ------------------------------------------*- C++ -*-===//
+//===-- NSDictionary.cpp ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,110 +7,153 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+// C Includes
+// C++ Includes
+#include <mutex>
+
+// Other libraries and framework includes
+#include "clang/AST/DeclCXX.h"
+
+// Project includes
+#include "NSDictionary.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
-#include "clang/AST/DeclCXX.h"
-
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
-static ClangASTType
-GetLLDBNSPairType (TargetSP target_sp)
+std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+NSDictionary_Additionals::GetAdditionalSummaries ()
{
- ClangASTType clang_type;
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
+ return g_map;
+}
- ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext();
+std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
+NSDictionary_Additionals::GetAdditionalSynthetics ()
+{
+ static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> g_map;
+ return g_map;
+}
+static CompilerType
+GetLLDBNSPairType (TargetSP target_sp)
+{
+ CompilerType compiler_type;
+
+ ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext();
+
if (target_ast_context)
{
ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair");
-
- clang_type = target_ast_context->GetTypeForIdentifier<clang::CXXRecordDecl>(g___lldb_autogen_nspair);
- if (!clang_type)
+ compiler_type = target_ast_context->GetTypeForIdentifier<clang::CXXRecordDecl>(g___lldb_autogen_nspair);
+
+ if (!compiler_type)
{
- clang_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC);
+ compiler_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC);
- if (clang_type)
+ if (compiler_type)
{
- clang_type.StartTagDeclarationDefinition();
- ClangASTType id_clang_type = target_ast_context->GetBasicType (eBasicTypeObjCID);
- clang_type.AddFieldToRecordType("key", id_clang_type, lldb::eAccessPublic, 0);
- clang_type.AddFieldToRecordType("value", id_clang_type, lldb::eAccessPublic, 0);
- clang_type.CompleteTagDeclarationDefinition();
+ ClangASTContext::StartTagDeclarationDefinition(compiler_type);
+ CompilerType id_compiler_type = target_ast_context->GetBasicType (eBasicTypeObjCID);
+ ClangASTContext::AddFieldToRecordType(compiler_type, "key", id_compiler_type, lldb::eAccessPublic, 0);
+ ClangASTContext::AddFieldToRecordType(compiler_type, "value", id_compiler_type, lldb::eAccessPublic, 0);
+ ClangASTContext::CompleteTagDeclarationDefinition(compiler_type);
}
}
}
- return clang_type;
+ return compiler_type;
}
namespace lldb_private {
namespace formatters {
class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
+ public:
+ NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSDictionaryISyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
private:
struct DataDescriptor_32
{
uint32_t _used : 26;
uint32_t _szidx : 6;
};
+
struct DataDescriptor_64
{
uint64_t _used : 58;
uint32_t _szidx : 6;
};
-
+
struct DictionaryItemDescriptor
{
lldb::addr_t key_ptr;
lldb::addr_t val_ptr;
lldb::ValueObjectSP valobj_sp;
};
-
- public:
- NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
-
- virtual bool
- MightHaveChildren ();
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
-
- virtual
- ~NSDictionaryISyntheticFrontEnd ();
- private:
+
ExecutionContextRef m_exe_ctx_ref;
uint8_t m_ptr_size;
lldb::ByteOrder m_order;
DataDescriptor_32 *m_data_32;
DataDescriptor_64 *m_data_64;
lldb::addr_t m_data_ptr;
- ClangASTType m_pair_type;
+ CompilerType m_pair_type;
std::vector<DictionaryItemDescriptor> m_children;
};
class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
+ public:
+ NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSDictionaryMSyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
private:
struct DataDescriptor_32
{
@@ -121,6 +164,7 @@ namespace lldb_private {
uint32_t _objs_addr;
uint32_t _keys_addr;
};
+
struct DataDescriptor_64
{
uint64_t _used : 58;
@@ -130,39 +174,20 @@ namespace lldb_private {
uint64_t _objs_addr;
uint64_t _keys_addr;
};
+
struct DictionaryItemDescriptor
{
lldb::addr_t key_ptr;
lldb::addr_t val_ptr;
lldb::ValueObjectSP valobj_sp;
};
- public:
- NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
-
- virtual bool
- MightHaveChildren ();
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
-
- virtual
- ~NSDictionaryMSyntheticFrontEnd ();
- private:
+
ExecutionContextRef m_exe_ctx_ref;
uint8_t m_ptr_size;
lldb::ByteOrder m_order;
DataDescriptor_32 *m_data_32;
DataDescriptor_64 *m_data_64;
- ClangASTType m_pair_type;
+ CompilerType m_pair_type;
std::vector<DictionaryItemDescriptor> m_children;
};
@@ -170,32 +195,32 @@ namespace lldb_private {
{
public:
NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSDictionaryCodeRunningSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
- virtual bool
- MightHaveChildren ();
+ bool
+ Update() override;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ bool
+ MightHaveChildren() override;
- virtual
- ~NSDictionaryCodeRunningSyntheticFrontEnd ();
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
};
- }
-}
+ } // namespace formatters
+} // namespace lldb_private
template<bool name_entries>
bool
lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
+ static ConstString g_TypeHint("NSDictionary");
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
return false;
@@ -220,7 +245,8 @@ lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stre
uint64_t value = 0;
- const char* class_name = descriptor->GetClassName().GetCString();
+ ConstString class_name_cs = descriptor->GetClassName();
+ const char* class_name = class_name_cs.GetCString();
if (!class_name || !*class_name)
return false;
@@ -242,31 +268,45 @@ lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stre
value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
}
/*else if (!strcmp(class_name,"__NSCFDictionary"))
- {
- Error error;
- value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
- if (error.Fail())
- return false;
- if (is_64bit)
- value &= ~0x0f1f000000000000UL;
- }*/
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
+ if (error.Fail())
+ return false;
+ if (is_64bit)
+ value &= ~0x0f1f000000000000UL;
+ }*/
else
{
+ auto& map(NSDictionary_Additionals::GetAdditionalSummaries());
+ auto iter = map.find(class_name_cs), end = map.end();
+ if (iter != end)
+ return iter->second(valobj, stream, options);
if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
return false;
}
- stream.Printf("%s%" PRIu64 " %s%s",
- (name_entries ? "@\"" : ""),
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%" PRIu64 " %s%s%s",
+ prefix.c_str(),
value,
- (name_entries ? (value == 1 ? "entry" : "entries") : (value == 1 ? "key/value pair" : "key/value pairs")),
- (name_entries ? "\"" : ""));
+ "key/value pair",
+ value == 1 ? "" : "s",
+ suffix.c_str());
return true;
}
-SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp)
{
-
lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
if (!process_sp)
return NULL;
@@ -274,7 +314,10 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontE
if (!runtime)
return NULL;
- if (!valobj_sp->IsPointerType())
+ CompilerType valobj_type(valobj_sp->GetCompilerType());
+ Flags flags(valobj_type.GetTypeInfo());
+
+ if (flags.IsClear(eTypeIsPointer))
{
Error error;
valobj_sp = valobj_sp->AddressOf(error);
@@ -287,7 +330,8 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontE
if (!descriptor.get() || !descriptor->IsValid())
return NULL;
- const char* class_name = descriptor->GetClassName().GetCString();
+ ConstString class_name_cs = descriptor->GetClassName();
+ const char* class_name = class_name_cs.GetCString();
if (!class_name || !*class_name)
return NULL;
@@ -302,6 +346,10 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontE
}
else
{
+ auto& map(NSDictionary_Additionals::GetAdditionalSynthetics());
+ auto iter = map.find(class_name_cs), end = map.end();
+ if (iter != end)
+ return iter->second(synth, valobj_sp);
return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp));
}
}
@@ -333,6 +381,8 @@ lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIn
lldb::ValueObjectSP child_sp;
EvaluateExpressionOptions options;
options.SetKeepInMemory(true);
+ options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus);
+ options.SetResultIsInternal(true);
m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(),
GetViableFrame(m_backend.GetTargetSP().get()),
child_sp,
@@ -360,9 +410,6 @@ lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfCh
return 0;
}
-lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd ()
-{}
-
lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd(*valobj_sp.get()),
m_exe_ctx_ref(),
@@ -696,7 +743,7 @@ lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_
}
template bool
-lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&);
template bool
-lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.h b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.h
new file mode 100644
index 0000000..e96c25a
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSDictionary.h
@@ -0,0 +1,48 @@
+//===-- NSDictionary.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_NSDictionary_h_
+#define liblldb_NSDictionary_h_
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+#include <map>
+
+namespace lldb_private {
+ namespace formatters
+ {
+ template<bool name_entries>
+ bool
+ NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ extern template bool
+ NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+ extern template bool
+ NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+ SyntheticChildrenFrontEnd* NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ class NSDictionary_Additionals
+ {
+ public:
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+ GetAdditionalSummaries ();
+
+ static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
+ GetAdditionalSynthetics ();
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_NSDictionary_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSError.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSError.cpp
new file mode 100644
index 0000000..c627cd0
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSError.cpp
@@ -0,0 +1,218 @@
+//===-- NSError.cpp ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/DeclCXX.h"
+
+// Project includes
+#include "Cocoa.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
+
+#include "lldb/Utility/ProcessStructReader.h"
+
+#include "Plugins/Language/ObjC/NSString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::NSError_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp(valobj.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS;
+
+ CompilerType valobj_type(valobj.GetCompilerType());
+ Flags type_flags(valobj_type.GetTypeInfo());
+ if (type_flags.AllClear(eTypeHasValue))
+ {
+ if (valobj.IsBaseClass() && valobj.GetParent())
+ ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ }
+ else
+ ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (ptr_value == LLDB_INVALID_ADDRESS)
+ return false;
+ size_t ptr_size = process_sp->GetAddressByteSize();
+ lldb::addr_t code_location = ptr_value + 2 * ptr_size;
+ lldb::addr_t domain_location = ptr_value + 3 * ptr_size;
+
+ Error error;
+ uint64_t code = process_sp->ReadUnsignedIntegerFromMemory(code_location, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+
+ lldb::addr_t domain_str_value = process_sp->ReadPointerFromMemory(domain_location, error);
+ if (error.Fail() || domain_str_value == LLDB_INVALID_ADDRESS)
+ return false;
+
+ if (!domain_str_value)
+ {
+ stream.Printf("domain: nil - code: %" PRIu64, code);
+ return true;
+ }
+
+ InferiorSizedWord isw(domain_str_value, *process_sp);
+
+ ValueObjectSP domain_str_sp = ValueObject::CreateValueObjectFromData("domain_str", isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeVoid).GetPointerType());
+
+ if (!domain_str_sp)
+ return false;
+
+ StreamString domain_str_summary;
+ if (NSStringSummaryProvider(*domain_str_sp, domain_str_summary, options) && !domain_str_summary.Empty())
+ {
+ stream.Printf("domain: %s - code: %" PRIu64, domain_str_summary.GetData(), code);
+ return true;
+ }
+ else
+ {
+ stream.Printf("domain: nil - code: %" PRIu64, code);
+ return true;
+ }
+}
+
+class NSErrorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+ NSErrorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+ SyntheticChildrenFrontEnd(*valobj_sp)
+ {}
+
+ ~NSErrorSyntheticFrontEnd() override = default;
+ // no need to delete m_child_ptr - it's kept alive by the cluster manager on our behalf
+
+ size_t
+ CalculateNumChildren() override
+ {
+ if (m_child_ptr)
+ return 1;
+ if (m_child_sp)
+ return 1;
+ return 0;
+ }
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
+ {
+ if (idx != 0)
+ return lldb::ValueObjectSP();
+
+ if (m_child_ptr)
+ return m_child_ptr->GetSP();
+ return m_child_sp;
+ }
+
+ bool
+ Update() override
+ {
+ m_child_ptr = nullptr;
+ m_child_sp.reset();
+
+ ProcessSP process_sp(m_backend.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t userinfo_location = LLDB_INVALID_ADDRESS;
+
+ CompilerType valobj_type(m_backend.GetCompilerType());
+ Flags type_flags(valobj_type.GetTypeInfo());
+ if (type_flags.AllClear(eTypeHasValue))
+ {
+ if (m_backend.IsBaseClass() && m_backend.GetParent())
+ userinfo_location = m_backend.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ }
+ else
+ userinfo_location = m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (userinfo_location == LLDB_INVALID_ADDRESS)
+ return false;
+
+ size_t ptr_size = process_sp->GetAddressByteSize();
+
+ userinfo_location += 4 * ptr_size;
+ Error error;
+ lldb::addr_t userinfo = process_sp->ReadPointerFromMemory(userinfo_location, error);
+ if (userinfo == LLDB_INVALID_ADDRESS || error.Fail())
+ return false;
+ InferiorSizedWord isw(userinfo,*process_sp);
+ m_child_sp = ValueObject::CreateValueObjectFromData("_userInfo",
+ isw.GetAsData(process_sp->GetByteOrder()),
+ m_backend.GetExecutionContextRef(),
+ process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID));
+ return false;
+ }
+
+ bool
+ MightHaveChildren() override
+ {
+ return true;
+ }
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override
+ {
+ static ConstString g___userInfo("_userInfo");
+ if (name == g___userInfo)
+ return 0;
+ return UINT32_MAX;
+ }
+
+private:
+ // the child here can be "real" (i.e. an actual child of the root) or synthetized from raw memory
+ // if the former, I need to store a plain pointer to it - or else a loop of references will cause this entire hierarchy of values to leak
+ // if the latter, then I need to store a SharedPointer to it - so that it only goes away when everyone else in the cluster goes away
+ // oh joy!
+ ValueObject* m_child_ptr;
+ ValueObjectSP m_child_sp;
+};
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::NSErrorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return nullptr;
+ ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+ if (!runtime)
+ return nullptr;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return nullptr;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return nullptr;
+
+ if (!strcmp(class_name,"NSError"))
+ return (new NSErrorSyntheticFrontEnd(valobj_sp));
+ else if (!strcmp(class_name,"__NSCFError"))
+ return (new NSErrorSyntheticFrontEnd(valobj_sp));
+
+ return nullptr;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSException.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSException.cpp
new file mode 100644
index 0000000..e58223a
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSException.cpp
@@ -0,0 +1,219 @@
+//===-- NSException.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/DeclCXX.h"
+
+// Project includes
+#include "Cocoa.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
+
+#include "lldb/Utility/ProcessStructReader.h"
+
+#include "Plugins/Language/ObjC/NSString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::NSException_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp(valobj.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS;
+
+ CompilerType valobj_type(valobj.GetCompilerType());
+ Flags type_flags(valobj_type.GetTypeInfo());
+ if (type_flags.AllClear(eTypeHasValue))
+ {
+ if (valobj.IsBaseClass() && valobj.GetParent())
+ ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ }
+ else
+ ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (ptr_value == LLDB_INVALID_ADDRESS)
+ return false;
+ size_t ptr_size = process_sp->GetAddressByteSize();
+ lldb::addr_t name_location = ptr_value + 1 * ptr_size;
+ lldb::addr_t reason_location = ptr_value + 2 * ptr_size;
+
+ Error error;
+ lldb::addr_t name = process_sp->ReadPointerFromMemory(name_location, error);
+ if (error.Fail() || name == LLDB_INVALID_ADDRESS)
+ return false;
+
+ lldb::addr_t reason = process_sp->ReadPointerFromMemory(reason_location, error);
+ if (error.Fail() || reason == LLDB_INVALID_ADDRESS)
+ return false;
+
+ InferiorSizedWord name_isw(name, *process_sp);
+ InferiorSizedWord reason_isw(reason, *process_sp);
+
+ CompilerType voidstar = process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
+
+ ValueObjectSP name_sp = ValueObject::CreateValueObjectFromData("name_str", name_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar);
+ ValueObjectSP reason_sp = ValueObject::CreateValueObjectFromData("reason_str", reason_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar);
+
+ if (!name_sp || !reason_sp)
+ return false;
+
+ StreamString name_str_summary;
+ StreamString reason_str_summary;
+ if (NSStringSummaryProvider(*name_sp, name_str_summary, options) &&
+ NSStringSummaryProvider(*reason_sp, reason_str_summary, options) &&
+ !name_str_summary.Empty() &&
+ !reason_str_summary.Empty())
+ {
+ stream.Printf("name: %s - reason: %s", name_str_summary.GetData(), reason_str_summary.GetData());
+ return true;
+ }
+ else
+ return false;
+}
+
+class NSExceptionSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+ NSExceptionSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+ SyntheticChildrenFrontEnd(*valobj_sp)
+ {}
+
+ ~NSExceptionSyntheticFrontEnd() override = default;
+ // no need to delete m_child_ptr - it's kept alive by the cluster manager on our behalf
+
+ size_t
+ CalculateNumChildren() override
+ {
+ if (m_child_ptr)
+ return 1;
+ if (m_child_sp)
+ return 1;
+ return 0;
+ }
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
+ {
+ if (idx != 0)
+ return lldb::ValueObjectSP();
+
+ if (m_child_ptr)
+ return m_child_ptr->GetSP();
+ return m_child_sp;
+ }
+
+ bool
+ Update() override
+ {
+ m_child_ptr = nullptr;
+ m_child_sp.reset();
+
+ ProcessSP process_sp(m_backend.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t userinfo_location = LLDB_INVALID_ADDRESS;
+
+ CompilerType valobj_type(m_backend.GetCompilerType());
+ Flags type_flags(valobj_type.GetTypeInfo());
+ if (type_flags.AllClear(eTypeHasValue))
+ {
+ if (m_backend.IsBaseClass() && m_backend.GetParent())
+ userinfo_location = m_backend.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ }
+ else
+ userinfo_location = m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (userinfo_location == LLDB_INVALID_ADDRESS)
+ return false;
+
+ size_t ptr_size = process_sp->GetAddressByteSize();
+
+ userinfo_location += 3 * ptr_size;
+ Error error;
+ lldb::addr_t userinfo = process_sp->ReadPointerFromMemory(userinfo_location, error);
+ if (userinfo == LLDB_INVALID_ADDRESS || error.Fail())
+ return false;
+ InferiorSizedWord isw(userinfo,*process_sp);
+ m_child_sp = ValueObject::CreateValueObjectFromData("userInfo",
+ isw.GetAsData(process_sp->GetByteOrder()),
+ m_backend.GetExecutionContextRef(),
+ process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID));
+ return false;
+ }
+
+ bool
+ MightHaveChildren() override
+ {
+ return true;
+ }
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override
+ {
+ static ConstString g___userInfo("userInfo");
+ if (name == g___userInfo)
+ return 0;
+ return UINT32_MAX;
+ }
+
+private:
+ // the child here can be "real" (i.e. an actual child of the root) or synthetized from raw memory
+ // if the former, I need to store a plain pointer to it - or else a loop of references will cause this entire hierarchy of values to leak
+ // if the latter, then I need to store a SharedPointer to it - so that it only goes away when everyone else in the cluster goes away
+ // oh joy!
+ ValueObject* m_child_ptr;
+ ValueObjectSP m_child_sp;
+};
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::NSExceptionSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return nullptr;
+ ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+ if (!runtime)
+ return nullptr;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return nullptr;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return nullptr;
+
+ if (!strcmp(class_name,"NSException"))
+ return (new NSExceptionSyntheticFrontEnd(valobj_sp));
+ else if (!strcmp(class_name,"NSCFException"))
+ return (new NSExceptionSyntheticFrontEnd(valobj_sp));
+ else if (!strcmp(class_name,"__NSCFException"))
+ return (new NSExceptionSyntheticFrontEnd(valobj_sp));
+
+ return nullptr;
+}
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/NSIndexPath.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
index 363bd5c..245f6da 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/NSIndexPath.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
@@ -1,4 +1,4 @@
-//===-- NSIndexPath.cpp ------------------------------------------*- C++ -*-===//
+//===-- NSIndexPath.cpp -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,14 +7,20 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "Cocoa.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
-#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
@@ -26,34 +32,39 @@ public:
NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
SyntheticChildrenFrontEnd (*valobj_sp.get()),
m_ptr_size(0),
- m_ast_ctx(nullptr),
m_uint_star_type()
{
m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize();
}
-
- virtual size_t
- CalculateNumChildren ()
+
+ ~NSIndexPathSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override
{
return m_impl.GetNumIndexes();
}
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx)
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
{
return m_impl.GetIndexAtIndex(idx, m_uint_star_type);
}
- virtual bool
- Update()
+ bool
+ Update() override
{
m_impl.Clear();
- m_ast_ctx = ClangASTContext::GetASTContext(m_backend.GetClangType().GetASTContext());
- if (!m_ast_ctx)
+ TypeSystem* type_system = m_backend.GetCompilerType().GetTypeSystem();
+ if (!type_system)
return false;
-
- m_uint_star_type = m_ast_ctx->GetPointerSizedIntType(false);
+
+ ClangASTContext *ast = m_backend.GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext();
+ if (!ast)
+ return false;
+
+ m_uint_star_type = ast->GetPointerSizedIntType(false);
static ConstString g__indexes("_indexes");
static ConstString g__length("_length");
@@ -125,16 +136,16 @@ public:
return false;
}
- virtual bool
- MightHaveChildren ()
+ bool
+ MightHaveChildren() override
{
if (m_impl.m_mode == Mode::Invalid)
return false;
return true;
}
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name)
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override
{
const char* item_name = name.GetCString();
uint32_t idx = ExtractIndexFromString(item_name);
@@ -143,12 +154,12 @@ public:
return idx;
}
- virtual lldb::ValueObjectSP
- GetSyntheticValue () { return nullptr; }
-
- virtual
- ~NSIndexPathSyntheticFrontEnd () {}
-
+ lldb::ValueObjectSP
+ GetSyntheticValue() override
+ {
+ return nullptr;
+ }
+
protected:
ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp;
@@ -176,7 +187,7 @@ protected:
}
lldb::ValueObjectSP
- GetIndexAtIndex (size_t idx, const ClangASTType& desired_type)
+ GetIndexAtIndex (size_t idx, const CompilerType& desired_type)
{
if (idx >= GetNumIndexes())
return nullptr;
@@ -206,7 +217,7 @@ protected:
}
lldb::ValueObjectSP
- GetIndexAtIndex (size_t idx, const ClangASTType& desired_type)
+ GetIndexAtIndex (size_t idx, const CompilerType& desired_type)
{
std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx));
if (!value.second)
@@ -224,7 +235,7 @@ protected:
v = Value(scalar);
}
- v.SetClangType(desired_type);
+ v.SetCompilerType(desired_type);
StreamString idx_name;
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
@@ -241,7 +252,7 @@ protected:
m_process = nullptr;
}
- private:
+ private:
uint64_t m_indexes;
size_t m_count;
uint32_t m_ptr_size;
@@ -321,8 +332,7 @@ protected:
} m_impl;
uint32_t m_ptr_size;
- ClangASTContext* m_ast_ctx;
- ClangASTType m_uint_star_type;
+ CompilerType m_uint_star_type;
};
namespace lldb_private {
@@ -334,5 +344,6 @@ namespace lldb_private {
return new NSIndexPathSyntheticFrontEnd(valobj_sp);
return nullptr;
}
- }
-}
+
+ } // namespace formatters
+} // namespace lldb_private
diff --git a/contrib/llvm/tools/lldb/source/DataFormatters/NSSet.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.cpp
index 116904c..9311595 100644
--- a/contrib/llvm/tools/lldb/source/DataFormatters/NSSet.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.cpp
@@ -1,4 +1,4 @@
-//===-- NSSet.cpp ------------------------------------------------*- C++ -*-===//
+//===-- NSSet.cpp -----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,15 +7,21 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/DataFormatters/CXXFormatterFunctions.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "NSSet.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Target.h"
@@ -23,49 +29,63 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
+std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+NSSet_Additionals::GetAdditionalSummaries ()
+{
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
+ return g_map;
+}
+
+std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
+NSSet_Additionals::GetAdditionalSynthetics ()
+{
+ static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> g_map;
+ return g_map;
+}
+
namespace lldb_private {
namespace formatters {
class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
+ public:
+ NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSSetISyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
private:
struct DataDescriptor_32
{
uint32_t _used : 26;
uint32_t _szidx : 6;
};
+
struct DataDescriptor_64
{
uint64_t _used : 58;
uint32_t _szidx : 6;
};
-
+
struct SetItemDescriptor
{
lldb::addr_t item_ptr;
lldb::ValueObjectSP valobj_sp;
};
-
- public:
- NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
-
- virtual bool
- MightHaveChildren ();
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
-
- virtual
- ~NSSetISyntheticFrontEnd ();
- private:
+
ExecutionContextRef m_exe_ctx_ref;
uint8_t m_ptr_size;
DataDescriptor_32 *m_data_32;
@@ -76,28 +96,26 @@ namespace lldb_private {
class NSOrderedSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
- private:
-
public:
NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSOrderedSetSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
- virtual bool
- MightHaveChildren ();
+ bool
+ Update() override;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ bool
+ MightHaveChildren() override;
- virtual
- ~NSOrderedSetSyntheticFrontEnd ();
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
private:
uint32_t m_count;
std::map<uint32_t,lldb::ValueObjectSP> m_children;
@@ -105,6 +123,26 @@ namespace lldb_private {
class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
+ public:
+ NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSSetMSyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
private:
struct DataDescriptor_32
{
@@ -113,6 +151,7 @@ namespace lldb_private {
uint32_t _mutations;
uint32_t _objs_addr;
};
+
struct DataDescriptor_64
{
uint64_t _used : 58;
@@ -120,32 +159,13 @@ namespace lldb_private {
uint64_t _mutations;
uint64_t _objs_addr;
};
+
struct SetItemDescriptor
{
lldb::addr_t item_ptr;
lldb::ValueObjectSP valobj_sp;
};
- public:
- NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
-
- virtual bool
- MightHaveChildren ();
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
-
- virtual
- ~NSSetMSyntheticFrontEnd ();
- private:
+
ExecutionContextRef m_exe_ctx_ref;
uint8_t m_ptr_size;
DataDescriptor_32 *m_data_32;
@@ -157,32 +177,33 @@ namespace lldb_private {
{
public:
NSSetCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSSetCodeRunningSyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
- virtual bool
- MightHaveChildren ();
+ bool
+ Update() override;
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
+ bool
+ MightHaveChildren() override;
- virtual
- ~NSSetCodeRunningSyntheticFrontEnd ();
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
};
- }
-}
+ } // namespace formatters
+} // namespace lldb_private
template<bool cf_style>
bool
lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
+ static ConstString g_TypeHint("NSSet");
+
ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
return false;
@@ -207,7 +228,8 @@ lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& str
uint64_t value = 0;
- const char* class_name = descriptor->GetClassName().GetCString();
+ ConstString class_name_cs = descriptor->GetClassName();
+ const char* class_name = class_name_cs.GetCString();
if (!class_name || !*class_name)
return false;
@@ -229,41 +251,56 @@ lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& str
value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
}
/*else if (!strcmp(class_name,"__NSCFSet"))
- {
- Error error;
- value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
- if (error.Fail())
- return false;
- if (is_64bit)
- value &= ~0x1fff000000000000UL;
- }
- else if (!strcmp(class_name,"NSCountedSet"))
- {
- Error error;
- value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
- if (error.Fail())
- return false;
- value = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 : 12), 4, 0, error);
- if (error.Fail())
- return false;
- if (is_64bit)
- value &= ~0x1fff000000000000UL;
- }*/
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
+ if (error.Fail())
+ return false;
+ if (is_64bit)
+ value &= ~0x1fff000000000000UL;
+ }
+ else if (!strcmp(class_name,"NSCountedSet"))
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ value = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 : 12), 4, 0, error);
+ if (error.Fail())
+ return false;
+ if (is_64bit)
+ value &= ~0x1fff000000000000UL;
+ }*/
else
{
+ auto& map(NSSet_Additionals::GetAdditionalSummaries());
+ auto iter = map.find(class_name_cs), end = map.end();
+ if (iter != end)
+ return iter->second(valobj, stream, options);
if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
return false;
}
- stream.Printf("%s%" PRIu64 " %s%s",
- (cf_style ? "@\"" : ""),
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%" PRIu64 " %s%s%s",
+ prefix.c_str(),
value,
- (cf_style ? (value == 1 ? "value" : "values") : (value == 1 ? "object" : "objects")),
- (cf_style ? "\"" : ""));
+ "element",
+ value == 1 ? "" : "s",
+ suffix.c_str());
return true;
}
-SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp)
{
lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
if (!process_sp)
@@ -272,7 +309,10 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreat
if (!runtime)
return NULL;
- if (!valobj_sp->IsPointerType())
+ CompilerType valobj_type(valobj_sp->GetCompilerType());
+ Flags flags(valobj_type.GetTypeInfo());
+
+ if (flags.IsClear(eTypeIsPointer))
{
Error error;
valobj_sp = valobj_sp->AddressOf(error);
@@ -285,7 +325,8 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreat
if (!descriptor.get() || !descriptor->IsValid())
return NULL;
- const char* class_name = descriptor->GetClassName().GetCString();
+ ConstString class_name_cs = descriptor->GetClassName();
+ const char* class_name = class_name_cs.GetCString();
if (!class_name || !*class_name)
return NULL;
@@ -304,6 +345,10 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreat
}
else
{
+ auto& map(NSSet_Additionals::GetAdditionalSynthetics());
+ auto iter = map.find(class_name_cs), end = map.end();
+ if (iter != end)
+ return iter->second(synth, valobj_sp);
return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL;
}
}
@@ -467,10 +512,10 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
process_sp->GetAddressByteSize());
set_item.valobj_sp =
- CreateValueObjectFromData(idx_name.GetData(),
- data,
- m_exe_ctx_ref,
- m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
+ CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
}
return set_item.valobj_sp;
}
@@ -565,7 +610,7 @@ lldb::ValueObjectSP
lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
{
lldb::addr_t m_objs_addr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
-
+
uint32_t num_children = CalculateNumChildren();
if (idx >= num_children)
@@ -635,10 +680,10 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
process_sp->GetAddressByteSize());
set_item.valobj_sp =
- CreateValueObjectFromData(idx_name.GetData(),
- data,
- m_exe_ctx_ref,
- m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
+ CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
}
return set_item.valobj_sp;
}
@@ -706,10 +751,6 @@ lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetIndexOfChildWithName
return idx;
}
-lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::~NSOrderedSetSyntheticFrontEnd ()
-{
-}
-
template bool
lldb_private::formatters::NSSetSummaryProvider<true> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.h b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.h
new file mode 100644
index 0000000..c862270
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSSet.h
@@ -0,0 +1,40 @@
+//===-- NSSet.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_NSSet_h_
+#define liblldb_NSSet_h_
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ template<bool cf_style>
+ bool
+ NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ SyntheticChildrenFrontEnd* NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ class NSSet_Additionals
+ {
+ public:
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+ GetAdditionalSummaries ();
+
+ static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
+ GetAdditionalSynthetics ();
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_NSSet_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.cpp
new file mode 100644
index 0000000..8089663
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.cpp
@@ -0,0 +1,405 @@
+//===-- NSString.cpp ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NSString.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/ProcessStructReader.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+NSString_Additionals::GetAdditionalSummaries ()
+{
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
+ return g_map;
+}
+
+static CompilerType
+GetNSPathStore2Type (Target &target)
+{
+ static ConstString g_type_name("__lldb_autogen_nspathstore2");
+
+ ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
+
+ if (!ast_ctx)
+ return CompilerType();
+
+ CompilerType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
+ CompilerType uint32 = ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+
+ return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, {
+ {"isa",voidstar},
+ {"lengthAndRef",uint32},
+ {"buffer",voidstar}
+ });
+}
+
+bool
+lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
+{
+ static ConstString g_TypeHint("NSString");
+
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ ConstString class_name_cs = descriptor->GetClassName();
+ const char* class_name = class_name_cs.GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
+ // for a tagged pointer, the descriptor has everything we need
+ if (is_tagged_ptr)
+ return NSTaggedString_SummaryProvider(valobj, descriptor, stream, summary_options);
+
+ auto& additionals_map(NSString_Additionals::GetAdditionalSummaries());
+ auto iter = additionals_map.find(class_name_cs), end = additionals_map.end();
+ if (iter != end)
+ return iter->second(valobj, stream, summary_options);
+
+ // if not a tagged pointer that we know about, try the normal route
+ uint64_t info_bits_location = valobj_addr + ptr_size;
+ if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
+ info_bits_location += 3;
+
+ Error error;
+
+ uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
+ if (error.Fail())
+ return false;
+
+ bool is_mutable = (info_bits & 1) == 1;
+ bool is_inline = (info_bits & 0x60) == 0;
+ bool has_explicit_length = (info_bits & (1 | 4)) != 4;
+ bool is_unicode = (info_bits & 0x10) == 0x10;
+ bool is_path_store = strcmp(class_name,"NSPathStore2") == 0;
+ bool has_null = (info_bits & 8) == 8;
+
+ size_t explicit_length = 0;
+ if (!has_null && has_explicit_length && !is_path_store)
+ {
+ lldb::addr_t explicit_length_offset = 2*ptr_size;
+ if (is_mutable && !is_inline)
+ explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
+ else if (is_inline)
+ explicit_length = explicit_length + 0; // inline1.length;
+ else if (!is_inline && !is_mutable)
+ explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
+ else
+ explicit_length_offset = 0;
+
+ if (explicit_length_offset)
+ {
+ explicit_length_offset = valobj_addr + explicit_length_offset;
+ explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
+ }
+ }
+
+ if (strcmp(class_name,"NSString") &&
+ strcmp(class_name,"CFStringRef") &&
+ strcmp(class_name,"CFMutableStringRef") &&
+ strcmp(class_name,"__NSCFConstantString") &&
+ strcmp(class_name,"__NSCFString") &&
+ strcmp(class_name,"NSCFConstantString") &&
+ strcmp(class_name,"NSCFString") &&
+ strcmp(class_name,"NSPathStore2"))
+ {
+ // not one of us - but tell me class name
+ stream.Printf("class name = %s",class_name);
+ return true;
+ }
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(summary_options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetPrefixToken(prefix);
+ options.SetSuffixToken(suffix);
+
+ if (is_mutable)
+ {
+ uint64_t location = 2 * ptr_size + valobj_addr;
+ location = process_sp->ReadPointerFromMemory(location, error);
+ if (error.Fail())
+ return false;
+ if (has_explicit_length && is_unicode)
+ {
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetQuote('"');
+ options.SetSourceSize(explicit_length);
+ options.SetNeedsZeroTermination(false);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetBinaryZeroIsTerminator(false);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+ }
+ else
+ {
+ options.SetLocation(location+1);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetSourceSize(explicit_length);
+ options.SetNeedsZeroTermination(false);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetBinaryZeroIsTerminator(false);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options);
+ }
+ }
+ else if (is_inline && has_explicit_length && !is_unicode && !is_path_store && !is_mutable)
+ {
+ uint64_t location = 3 * ptr_size + valobj_addr;
+
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetQuote('"');
+ options.SetSourceSize(explicit_length);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII> (options);
+ }
+ else if (is_unicode)
+ {
+ uint64_t location = valobj_addr + 2*ptr_size;
+ if (is_inline)
+ {
+ if (!has_explicit_length)
+ {
+ stream.Printf("found new combo");
+ return true;
+ }
+ else
+ location += ptr_size;
+ }
+ else
+ {
+ location = process_sp->ReadPointerFromMemory(location, error);
+ if (error.Fail())
+ return false;
+ }
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetQuote('"');
+ options.SetSourceSize(explicit_length);
+ options.SetNeedsZeroTermination(has_explicit_length == false);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetBinaryZeroIsTerminator(has_explicit_length == false);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16> (options);
+ }
+ else if (is_path_store)
+ {
+ ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP()));
+ explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20;
+ lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4;
+
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetQuote('"');
+ options.SetSourceSize(explicit_length);
+ options.SetNeedsZeroTermination(has_explicit_length == false);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetBinaryZeroIsTerminator(has_explicit_length == false);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16> (options);
+ }
+ else if (is_inline)
+ {
+ uint64_t location = valobj_addr + 2*ptr_size;
+ if (!has_explicit_length)
+ {
+ // in this kind of string, the byte before the string content is a length byte
+ // so let's try and use it to handle the embedded NUL case
+ Error error;
+ explicit_length = process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0, error);
+ if (error.Fail() || explicit_length == 0)
+ has_explicit_length = false;
+ else
+ has_explicit_length = true;
+ location++;
+ }
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetSourceSize(explicit_length);
+ options.SetNeedsZeroTermination(!has_explicit_length);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetBinaryZeroIsTerminator(!has_explicit_length);
+ options.SetLanguage(summary_options.GetLanguage());
+ if (has_explicit_length)
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options);
+ else
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options);
+ }
+ else
+ {
+ uint64_t location = valobj_addr + 2*ptr_size;
+ location = process_sp->ReadPointerFromMemory(location, error);
+ if (error.Fail())
+ return false;
+ if (has_explicit_length && !has_null)
+ explicit_length++; // account for the fact that there is no NULL and we need to have one added
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetSourceSize(explicit_length);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options);
+ }
+}
+
+bool
+lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ TargetSP target_sp(valobj.GetTargetSP());
+ if (!target_sp)
+ return false;
+ uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
+ uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
+ if (!pointer_value)
+ return false;
+ pointer_value += addr_size;
+ CompilerType type(valobj.GetCompilerType());
+ ExecutionContext exe_ctx(target_sp,false);
+ ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
+ if (!child_ptr_sp)
+ return false;
+ DataExtractor data;
+ Error error;
+ child_ptr_sp->GetData(data, error);
+ if (error.Fail())
+ return false;
+ ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
+ child_sp->GetValueAsUnsigned(0);
+ if (child_sp)
+ return NSStringSummaryProvider(*child_sp, stream, options);
+ return false;
+}
+
+bool
+lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ return NSAttributedStringSummaryProvider(valobj, stream, options);
+}
+
+bool
+lldb_private::formatters::NSTaggedString_SummaryProvider (ValueObject& valobj, ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream, const TypeSummaryOptions& summary_options)
+{
+ static ConstString g_TypeHint("NSString");
+
+ if (!descriptor)
+ return false;
+ uint64_t len_bits = 0, data_bits = 0;
+ if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
+ return false;
+
+ static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
+ static const int g_SixbitMaxLen = 9;
+ static const int g_fiveBitMaxLen = 11;
+
+ static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
+
+ if (len_bits > g_fiveBitMaxLen)
+ return false;
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(summary_options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ // this is a fairly ugly trick - pretend that the numeric value is actually a char*
+ // this works under a few assumptions:
+ // little endian architecture
+ // sizeof(uint64_t) > g_MaxNonBitmaskedLen
+ if (len_bits <= g_MaxNonBitmaskedLen)
+ {
+ stream.Printf("%s",prefix.c_str());
+ stream.Printf("\"%s\"",(const char*)&data_bits);
+ stream.Printf("%s",suffix.c_str());
+ return true;
+ }
+
+ // if the data is bitmasked, we need to actually process the bytes
+ uint8_t bitmask = 0;
+ uint8_t shift_offset = 0;
+
+ if (len_bits <= g_SixbitMaxLen)
+ {
+ bitmask = 0x03f;
+ shift_offset = 6;
+ }
+ else
+ {
+ bitmask = 0x01f;
+ shift_offset = 5;
+ }
+
+ std::vector<uint8_t> bytes;
+ bytes.resize(len_bits);
+ for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
+ {
+ uint8_t packed = data_bits & bitmask;
+ bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
+ }
+
+ stream.Printf("%s",prefix.c_str());
+ stream.Printf("\"%s\"",&bytes[0]);
+ stream.Printf("%s",suffix.c_str());
+ return true;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.h b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.h
new file mode 100644
index 0000000..6a767a5
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/NSString.h
@@ -0,0 +1,42 @@
+//===-- NSString.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_NSString_h_
+#define liblldb_NSString_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ bool
+ NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSTaggedString_SummaryProvider (ValueObject& valobj, ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream, const TypeSummaryOptions& summary_options);
+
+ bool
+ NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ class NSString_Additionals
+ {
+ public:
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+ GetAdditionalSummaries ();
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CF_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
new file mode 100644
index 0000000..91a3a0f
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -0,0 +1,877 @@
+//===-- ObjCLanguage.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include <mutex>
+
+// Other libraries and framework includes
+// Project includes
+#include "ObjCLanguage.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Symbol/ClangASTContext.h"
+
+#include "CF.h"
+#include "Cocoa.h"
+#include "CoreMedia.h"
+#include "NSDictionary.h"
+#include "NSSet.h"
+#include "NSString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+void
+ObjCLanguage::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Objective-C Language",
+ CreateInstance);
+}
+
+void
+ObjCLanguage::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ObjCLanguage::GetPluginNameStatic()
+{
+ static ConstString g_name("objc");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ObjCLanguage::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ObjCLanguage::GetPluginVersion()
+{
+ return 1;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+Language *
+ObjCLanguage::CreateInstance (lldb::LanguageType language)
+{
+ switch (language)
+ {
+ case lldb::eLanguageTypeObjC:
+ return new ObjCLanguage();
+ default:
+ return nullptr;
+ }
+}
+
+void
+ObjCLanguage::MethodName::Clear()
+{
+ m_full.Clear();
+ m_class.Clear();
+ m_category.Clear();
+ m_selector.Clear();
+ m_type = eTypeUnspecified;
+ m_category_is_valid = false;
+}
+
+bool
+ObjCLanguage::MethodName::SetName (const char *name, bool strict)
+{
+ Clear();
+ if (name && name[0])
+ {
+ // If "strict" is true. then the method must be specified with a
+ // '+' or '-' at the beginning. If "strict" is false, then the '+'
+ // or '-' can be omitted
+ bool valid_prefix = false;
+
+ if (name[0] == '+' || name[0] == '-')
+ {
+ valid_prefix = name[1] == '[';
+ if (name[0] == '+')
+ m_type = eTypeClassMethod;
+ else
+ m_type = eTypeInstanceMethod;
+ }
+ else if (!strict)
+ {
+ // "strict" is false, the name just needs to start with '['
+ valid_prefix = name[0] == '[';
+ }
+
+ if (valid_prefix)
+ {
+ int name_len = strlen (name);
+ // Objective C methods must have at least:
+ // "-[" or "+[" prefix
+ // One character for a class name
+ // One character for the space between the class name
+ // One character for the method name
+ // "]" suffix
+ if (name_len >= (5 + (strict ? 1 : 0)) && name[name_len - 1] == ']')
+ {
+ m_full.SetCStringWithLength(name, name_len);
+ }
+ }
+ }
+ return IsValid(strict);
+}
+
+const ConstString &
+ObjCLanguage::MethodName::GetClassName ()
+{
+ if (!m_class)
+ {
+ if (IsValid(false))
+ {
+ const char *full = m_full.GetCString();
+ const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
+ const char *paren_pos = strchr (class_start, '(');
+ if (paren_pos)
+ {
+ m_class.SetCStringWithLength (class_start, paren_pos - class_start);
+ }
+ else
+ {
+ // No '(' was found in the full name, we can definitively say
+ // that our category was valid (and empty).
+ m_category_is_valid = true;
+ const char *space_pos = strchr (full, ' ');
+ if (space_pos)
+ {
+ m_class.SetCStringWithLength (class_start, space_pos - class_start);
+ if (!m_class_category)
+ {
+ // No category in name, so we can also fill in the m_class_category
+ m_class_category = m_class;
+ }
+ }
+ }
+ }
+ }
+ return m_class;
+}
+
+const ConstString &
+ObjCLanguage::MethodName::GetClassNameWithCategory ()
+{
+ if (!m_class_category)
+ {
+ if (IsValid(false))
+ {
+ const char *full = m_full.GetCString();
+ const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
+ const char *space_pos = strchr (full, ' ');
+ if (space_pos)
+ {
+ m_class_category.SetCStringWithLength (class_start, space_pos - class_start);
+ // If m_class hasn't been filled in and the class with category doesn't
+ // contain a '(', then we can also fill in the m_class
+ if (!m_class && strchr (m_class_category.GetCString(), '(') == NULL)
+ {
+ m_class = m_class_category;
+ // No '(' was found in the full name, we can definitively say
+ // that our category was valid (and empty).
+ m_category_is_valid = true;
+
+ }
+ }
+ }
+ }
+ return m_class_category;
+}
+
+const ConstString &
+ObjCLanguage::MethodName::GetSelector ()
+{
+ if (!m_selector)
+ {
+ if (IsValid(false))
+ {
+ const char *full = m_full.GetCString();
+ const char *space_pos = strchr (full, ' ');
+ if (space_pos)
+ {
+ ++space_pos; // skip the space
+ m_selector.SetCStringWithLength (space_pos, m_full.GetLength() - (space_pos - full) - 1);
+ }
+ }
+ }
+ return m_selector;
+}
+
+const ConstString &
+ObjCLanguage::MethodName::GetCategory ()
+{
+ if (!m_category_is_valid && !m_category)
+ {
+ if (IsValid(false))
+ {
+ m_category_is_valid = true;
+ const char *full = m_full.GetCString();
+ const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
+ const char *open_paren_pos = strchr (class_start, '(');
+ if (open_paren_pos)
+ {
+ ++open_paren_pos; // Skip the open paren
+ const char *close_paren_pos = strchr (open_paren_pos, ')');
+ if (close_paren_pos)
+ m_category.SetCStringWithLength (open_paren_pos, close_paren_pos - open_paren_pos);
+ }
+ }
+ }
+ return m_category;
+}
+
+ConstString
+ObjCLanguage::MethodName::GetFullNameWithoutCategory (bool empty_if_no_category)
+{
+ if (IsValid(false))
+ {
+ if (HasCategory())
+ {
+ StreamString strm;
+ if (m_type == eTypeClassMethod)
+ strm.PutChar('+');
+ else if (m_type == eTypeInstanceMethod)
+ strm.PutChar('-');
+ strm.Printf("[%s %s]", GetClassName().GetCString(), GetSelector().GetCString());
+ return ConstString(strm.GetString().c_str());
+ }
+
+ if (!empty_if_no_category)
+ {
+ // Just return the full name since it doesn't have a category
+ return GetFullName();
+ }
+ }
+ return ConstString();
+}
+
+size_t
+ObjCLanguage::MethodName::GetFullNames (std::vector<ConstString> &names, bool append)
+{
+ if (!append)
+ names.clear();
+ if (IsValid(false))
+ {
+ StreamString strm;
+ const bool is_class_method = m_type == eTypeClassMethod;
+ const bool is_instance_method = m_type == eTypeInstanceMethod;
+ const ConstString &category = GetCategory();
+ if (is_class_method || is_instance_method)
+ {
+ names.push_back (m_full);
+ if (category)
+ {
+ strm.Printf("%c[%s %s]",
+ is_class_method ? '+' : '-',
+ GetClassName().GetCString(),
+ GetSelector().GetCString());
+ names.push_back(ConstString(strm.GetString().c_str()));
+ }
+ }
+ else
+ {
+ const ConstString &class_name = GetClassName();
+ const ConstString &selector = GetSelector();
+ strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString());
+ names.push_back(ConstString(strm.GetString().c_str()));
+ strm.Clear();
+ strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString());
+ names.push_back(ConstString(strm.GetString().c_str()));
+ strm.Clear();
+ if (category)
+ {
+ strm.Printf("+[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
+ names.push_back(ConstString(strm.GetString().c_str()));
+ strm.Clear();
+ strm.Printf("-[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
+ names.push_back(ConstString(strm.GetString().c_str()));
+ }
+ }
+ }
+ return names.size();
+}
+
+static void
+LoadObjCFormatters(TypeCategoryImplSP objc_category_sp)
+{
+ if (!objc_category_sp)
+ return;
+
+ TypeSummaryImpl::Flags objc_flags;
+ objc_flags.SetCascades(false)
+ .SetSkipPointers(true)
+ .SetSkipReferences(true)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(true)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+ lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider,""));
+ objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"),
+ ObjC_BOOL_summary);
+ objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"),
+ ObjC_BOOL_summary);
+ objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"),
+ ObjC_BOOL_summary);
+
+#ifndef LLDB_DISABLE_PYTHON
+ // we need to skip pointers here since we are special casing a SEL* when retrieving its value
+ objc_flags.SetSkipPointers(true);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("SEL"), objc_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("struct objc_selector"), objc_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("objc_selector"), objc_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, "SEL summary provider", ConstString("objc_selector *"), objc_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, "SEL summary provider", ConstString("SEL *"), objc_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCClassSummaryProvider, "Class summary provider", ConstString("Class"), objc_flags);
+
+ SyntheticChildren::Flags class_synth_flags;
+ class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::ObjCClassSyntheticFrontEndCreator, "Class synthetic children", ConstString("Class"), class_synth_flags);
+#endif // LLDB_DISABLE_PYTHON
+
+ objc_flags.SetSkipPointers(false);
+ objc_flags.SetCascades(true);
+ objc_flags.SetSkipReferences(false);
+
+ AddStringSummary (objc_category_sp,
+ "${var.__FuncPtr%A}",
+ ConstString("__block_literal_generic"),
+ objc_flags);
+
+ AddStringSummary(objc_category_sp,
+ "${var.years} years, ${var.months} months, ${var.days} days, ${var.hours} hours, ${var.minutes} minutes ${var.seconds} seconds",
+ ConstString("CFGregorianUnits"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "location=${var.location} length=${var.length}",
+ ConstString("CFRange"),
+ objc_flags);
+
+ AddStringSummary(objc_category_sp,
+ "location=${var.location}, length=${var.length}",
+ ConstString("NSRange"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "(${var.origin}, ${var.size}), ...",
+ ConstString("NSRectArray"),
+ objc_flags);
+
+ AddOneLineSummary (objc_category_sp,
+ ConstString("NSPoint"),
+ objc_flags);
+ AddOneLineSummary (objc_category_sp,
+ ConstString("NSSize"),
+ objc_flags);
+ AddOneLineSummary (objc_category_sp,
+ ConstString("NSRect"),
+ objc_flags);
+
+ AddOneLineSummary (objc_category_sp,
+ ConstString("CGSize"),
+ objc_flags);
+ AddOneLineSummary (objc_category_sp,
+ ConstString("CGPoint"),
+ objc_flags);
+ AddOneLineSummary (objc_category_sp,
+ ConstString("CGRect"),
+ objc_flags);
+
+ AddStringSummary(objc_category_sp,
+ "red=${var.red} green=${var.green} blue=${var.blue}",
+ ConstString("RGBColor"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})",
+ ConstString("Rect"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "{(v=${var.v}, h=${var.h})}",
+ ConstString("Point"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "${var.month}/${var.day}/${var.year} ${var.hour} :${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}",
+ ConstString("DateTimeRect *"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "${var.ld.month}/${var.ld.day}/${var.ld.year} ${var.ld.hour} :${var.ld.minute} :${var.ld.second} dayOfWeek:${var.ld.dayOfWeek}",
+ ConstString("LongDateRect"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "(x=${var.x}, y=${var.y})",
+ ConstString("HIPoint"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "origin=${var.origin} size=${var.size}",
+ ConstString("HIRect"),
+ objc_flags);
+
+ TypeSummaryImpl::Flags appkit_flags;
+ appkit_flags.SetCascades(true)
+ .SetSkipPointers(false)
+ .SetSkipReferences(false)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(false)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+ appkit_flags.SetDontShowChildren(false);
+
+#ifndef LLDB_DISABLE_PYTHON
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSArray"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArray0"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFMutableArrayRef"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSDictionary"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSMutableDictionary"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSCFDictionary"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryI"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryM"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSSet summary", ConstString("NSSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFSetRef summary", ConstString("CFSetRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetI summary", ConstString("__NSSetI"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetM summary", ConstString("__NSSetM"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSError_SummaryProvider, "NSError summary provider", ConstString("NSError"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSException_SummaryProvider, "NSException summary provider", ConstString("NSException"), appkit_flags);
+
+ // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}", ConstString("$_lldb_typegen_nspair"), appkit_flags);
+
+ appkit_flags.SetDontShowChildren(true);
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayM"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayI"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArray0"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSArray"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSMutableArray"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSCFArray"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFMutableArrayRef"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFArrayRef"), ScriptedSyntheticChildren::Flags());
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryM"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryI"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSCFDictionary"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSDictionary"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSMutableDictionary"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFDictionaryRef"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"), ScriptedSyntheticChildren::Flags());
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSErrorSyntheticFrontEndCreator, "NSError synthetic children", ConstString("NSError"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSExceptionSyntheticFrontEndCreator, "NSException synthetic children", ConstString("NSException"), ScriptedSyntheticChildren::Flags());
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSSet synthetic children", ConstString("NSSet"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetI synthetic children", ConstString("__NSSetI"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetM synthetic children", ConstString("__NSSetM"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSMutableSet synthetic children", ConstString("NSMutableSet"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSOrderedSet synthetic children", ConstString("NSOrderedSet"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags());
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, "NSIndexPath synthetic children", ConstString("NSIndexPath"), ScriptedSyntheticChildren::Flags());
+
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("const struct __CFBag"), appkit_flags);
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFStringRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__CFString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFMutableStringRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSMutableString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFConstantString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFConstantString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSPathStore2"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSAttributedStringSummaryProvider, "NSAttributedString summary provider", ConstString("NSAttributedString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSMutableAttributedString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSConcreteMutableAttributedString"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSBundleSummaryProvider, "NSBundle summary provider", ConstString("NSBundle"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSData"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteData"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteMutableData"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSMutableData"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("__NSCFData"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFDataRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMachPortSummaryProvider, "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSNotification"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSConcreteNotification"), appkit_flags);
+
+ AddStringSummary(objc_category_sp, "domain: ${var._domain} - code: ${var._code}", ConstString("NSError"), appkit_flags);
+ AddStringSummary(objc_category_sp,"name:${var.name%S} reason:${var.reason%S}",ConstString("NSException"),appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSNumber"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSDecimalNumber summary provider", ConstString("NSDecimalNumber"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSHost summary provider", ConstString("NSHost"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSTask summary provider", ConstString("NSTask"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSValue summary provider", ConstString("NSValue"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("NSURL"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("CFURLRef"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSDate"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSDate"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("CFTimeZoneRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags);
+
+ // CFAbsoluteTime is actually a double rather than a pointer to an object
+ // we do not care about the numeric value, since it is probably meaningless to users
+ appkit_flags.SetDontShowValue(true);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CFAbsoluteTimeSummaryProvider, "CFAbsoluteTime summary provider", ConstString("CFAbsoluteTime"), appkit_flags);
+ appkit_flags.SetDontShowValue(false);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSMutableIndexSet"), appkit_flags);
+
+ AddStringSummary(objc_category_sp,
+ "@\"${var.month%d}/${var.day%d}/${var.year%d} ${var.hour%d}:${var.minute%d}:${var.second}\"",
+ ConstString("CFGregorianDate"),
+ appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFBitVectorRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFMutableBitVectorRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFBitVector"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFMutableBitVector"), appkit_flags);
+#endif // LLDB_DISABLE_PYTHON
+}
+
+static void
+LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp)
+{
+ if (!objc_category_sp)
+ return;
+
+ TypeSummaryImpl::Flags cm_flags;
+ cm_flags.SetCascades(true)
+ .SetDontShowChildren(false)
+ .SetDontShowValue(false)
+ .SetHideItemNames(false)
+ .SetShowMembersOneLiner(false)
+ .SetSkipPointers(false)
+ .SetSkipReferences(false);
+
+#ifndef LLDB_DISABLE_PYTHON
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CMTimeSummaryProvider, "CMTime summary provider", ConstString("CMTime"), cm_flags);
+#endif // LLDB_DISABLE_PYTHON
+}
+
+lldb::TypeCategoryImplSP
+ObjCLanguage::GetFormatters ()
+{
+ static std::once_flag g_initialize;
+ static TypeCategoryImplSP g_category;
+
+ std::call_once(g_initialize, [this] () -> void {
+ DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
+ if (g_category)
+ {
+ LoadCoreMediaFormatters(g_category);
+ LoadObjCFormatters(g_category);
+ }
+ });
+ return g_category;
+}
+
+std::vector<ConstString>
+ObjCLanguage::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
+{
+ std::vector<ConstString> result;
+
+ if (use_dynamic == lldb::eNoDynamicValues)
+ return result;
+
+ CompilerType compiler_type(valobj.GetCompilerType());
+
+ const bool check_cpp = false;
+ const bool check_objc = true;
+ bool canBeObjCDynamic = compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc);
+
+ if (canBeObjCDynamic)
+ {
+ do {
+ lldb::ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ break;
+ ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
+ if (runtime == nullptr)
+ break;
+ ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
+ if (!objc_class_sp)
+ break;
+ if (ConstString name = objc_class_sp->GetClassName())
+ result.push_back(name);
+ } while (false);
+ }
+
+ return result;
+}
+
+std::unique_ptr<Language::TypeScavenger>
+ObjCLanguage::GetTypeScavenger ()
+{
+ class ObjCTypeScavenger : public Language::TypeScavenger
+ {
+ private:
+ class ObjCScavengerResult : public Language::TypeScavenger::Result
+ {
+ public:
+ ObjCScavengerResult (CompilerType type) :
+ Language::TypeScavenger::Result(),
+ m_compiler_type(type)
+ {
+ }
+
+ bool
+ IsValid () override
+ {
+ return m_compiler_type.IsValid();
+ }
+
+ bool
+ DumpToStream (Stream& stream,
+ bool print_help_if_available) override
+ {
+ if (IsValid())
+ {
+ m_compiler_type.DumpTypeDescription(&stream);
+ stream.EOL();
+ return true;
+ }
+ return false;
+ }
+
+ ~ObjCScavengerResult() override = default;
+
+ private:
+ CompilerType m_compiler_type;
+ };
+
+ protected:
+ ObjCTypeScavenger() = default;
+
+ ~ObjCTypeScavenger() override = default;
+
+ bool
+ Find_Impl (ExecutionContextScope *exe_scope,
+ const char *key,
+ ResultSet &results) override
+ {
+ bool result = false;
+
+ Target* target = exe_scope->CalculateTarget().get();
+ if (target)
+ {
+ if (auto clang_modules_decl_vendor = target->GetClangModulesDeclVendor())
+ {
+ std::vector <clang::NamedDecl*> decls;
+ ConstString key_cs(key);
+
+ if (clang_modules_decl_vendor->FindDecls(key_cs, false, UINT32_MAX, decls) > 0 &&
+ decls.size() > 0)
+ {
+ CompilerType module_type = ClangASTContext::GetTypeForDecl(decls.front());
+ result = true;
+ std::unique_ptr<Language::TypeScavenger::Result> result(new ObjCScavengerResult(module_type));
+ results.insert(std::move(result));
+ }
+ }
+ }
+
+ if (!result)
+ {
+ Process* process = exe_scope->CalculateProcess().get();
+ if (process)
+ {
+ const bool create_on_demand = false;
+ auto objc_runtime = process->GetObjCLanguageRuntime(create_on_demand);
+ if (objc_runtime)
+ {
+ auto decl_vendor = objc_runtime->GetDeclVendor();
+ if (decl_vendor)
+ {
+ std::vector<clang::NamedDecl *> decls;
+ ConstString name(key);
+ decl_vendor->FindDecls(name, true, UINT32_MAX, decls);
+ for (auto decl : decls)
+ {
+ if (decl)
+ {
+ if (CompilerType candidate = ClangASTContext::GetTypeForDecl(decl))
+ {
+ result = true;
+ std::unique_ptr<Language::TypeScavenger::Result> result(new ObjCScavengerResult(candidate));
+ results.insert(std::move(result));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ friend class lldb_private::ObjCLanguage;
+ };
+
+ return std::unique_ptr<TypeScavenger>(new ObjCTypeScavenger());
+}
+
+bool
+ObjCLanguage::GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint,
+ std::string& prefix, std::string& suffix)
+{
+ static ConstString g_CFBag("CFBag");
+ static ConstString g_CFBinaryHeap("CFBinaryHeap");
+
+ static ConstString g_NSNumberChar("NSNumber:char");
+ static ConstString g_NSNumberShort("NSNumber:short");
+ static ConstString g_NSNumberInt("NSNumber:int");
+ static ConstString g_NSNumberLong("NSNumber:long");
+ static ConstString g_NSNumberFloat("NSNumber:float");
+ static ConstString g_NSNumberDouble("NSNumber:double");
+
+ static ConstString g_NSData("NSData");
+ static ConstString g_NSArray("NSArray");
+ static ConstString g_NSString("NSString");
+ static ConstString g_NSStringStar("NSString*");
+
+ if (type_hint.IsEmpty())
+ return false;
+
+ prefix.clear();
+ suffix.clear();
+
+ if (type_hint == g_CFBag ||
+ type_hint == g_CFBinaryHeap)
+ {
+ prefix = "@";
+ return true;
+ }
+
+ if (type_hint == g_NSNumberChar)
+ {
+ prefix = "(char)";
+ return true;
+ }
+ if (type_hint == g_NSNumberShort)
+ {
+ prefix = "(short)";
+ return true;
+ }
+ if (type_hint == g_NSNumberInt)
+ {
+ prefix = "(int)";
+ return true;
+ }
+ if (type_hint == g_NSNumberLong)
+ {
+ prefix = "(long)";
+ return true;
+ }
+ if (type_hint == g_NSNumberFloat)
+ {
+ prefix = "(float)";
+ return true;
+ }
+ if (type_hint == g_NSNumberDouble)
+ {
+ prefix = "(double)";
+ return true;
+ }
+
+ if (type_hint == g_NSData ||
+ type_hint == g_NSArray)
+ {
+ prefix = "@\"";
+ suffix = "\"";
+ return true;
+ }
+
+ if (type_hint == g_NSString ||
+ type_hint == g_NSStringStar)
+ {
+ prefix = "@";
+ return true;
+ }
+
+ return false;
+}
+
+bool
+ObjCLanguage::IsNilReference (ValueObject& valobj)
+{
+ const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
+ bool isObjCpointer = (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask);
+ if (!isObjCpointer)
+ return false;
+ bool canReadValue = true;
+ bool isZero = valobj.GetValueAsUnsigned(0,&canReadValue) == 0;
+ return canReadValue && isZero;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
new file mode 100644
index 0000000..e30aa18
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -0,0 +1,210 @@
+//===-- ObjCLanguage.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ObjCLanguage_h_
+#define liblldb_ObjCLanguage_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Target/Language.h"
+
+namespace lldb_private {
+
+class ObjCLanguage :
+ public Language
+{
+public:
+ class MethodName
+ {
+ public:
+ enum Type
+ {
+ eTypeUnspecified,
+ eTypeClassMethod,
+ eTypeInstanceMethod
+ };
+
+ MethodName () :
+ m_full(),
+ m_class(),
+ m_category(),
+ m_selector(),
+ m_type (eTypeUnspecified),
+ m_category_is_valid (false)
+ {
+ }
+
+ MethodName (const char *name, bool strict) :
+ m_full(),
+ m_class(),
+ m_category(),
+ m_selector(),
+ m_type (eTypeUnspecified),
+ m_category_is_valid (false)
+ {
+ SetName (name, strict);
+ }
+
+ void
+ Clear();
+
+ bool
+ IsValid (bool strict) const
+ {
+ // If "strict" is true, the name must have everything specified including
+ // the leading "+" or "-" on the method name
+ if (strict && m_type == eTypeUnspecified)
+ return false;
+ // Other than that, m_full will only be filled in if the objective C
+ // name is valid.
+ return (bool)m_full;
+ }
+
+ bool
+ HasCategory()
+ {
+ return !GetCategory().IsEmpty();
+ }
+
+ Type
+ GetType () const
+ {
+ return m_type;
+ }
+
+ const ConstString &
+ GetFullName () const
+ {
+ return m_full;
+ }
+
+ ConstString
+ GetFullNameWithoutCategory (bool empty_if_no_category);
+
+ bool
+ SetName (const char *name, bool strict);
+
+ const ConstString &
+ GetClassName ();
+
+ const ConstString &
+ GetClassNameWithCategory ();
+
+ const ConstString &
+ GetCategory ();
+
+ const ConstString &
+ GetSelector ();
+
+ // Get all possible names for a method. Examples:
+ // If name is "+[NSString(my_additions) myStringWithCString:]"
+ // names[0] => "+[NSString(my_additions) myStringWithCString:]"
+ // names[1] => "+[NSString myStringWithCString:]"
+ // If name is specified without the leading '+' or '-' like "[NSString(my_additions) myStringWithCString:]"
+ // names[0] => "+[NSString(my_additions) myStringWithCString:]"
+ // names[1] => "-[NSString(my_additions) myStringWithCString:]"
+ // names[2] => "+[NSString myStringWithCString:]"
+ // names[3] => "-[NSString myStringWithCString:]"
+ size_t
+ GetFullNames (std::vector<ConstString> &names, bool append);
+
+ protected:
+ ConstString m_full; // Full name: "+[NSString(my_additions) myStringWithCString:]"
+ ConstString m_class; // Class name: "NSString"
+ ConstString m_class_category; // Class with category: "NSString(my_additions)"
+ ConstString m_category; // Category: "my_additions"
+ ConstString m_selector; // Selector: "myStringWithCString:"
+ Type m_type;
+ bool m_category_is_valid;
+ };
+
+ ObjCLanguage() = default;
+
+ ~ObjCLanguage() override = default;
+
+ lldb::LanguageType
+ GetLanguageType () const override
+ {
+ return lldb::eLanguageTypeObjC;
+ }
+
+ lldb::TypeCategoryImplSP
+ GetFormatters () override;
+
+ std::vector<ConstString>
+ GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic) override;
+
+ std::unique_ptr<TypeScavenger>
+ GetTypeScavenger () override;
+
+ bool
+ GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint,
+ std::string& prefix, std::string& suffix) override;
+
+ bool
+ IsNilReference (ValueObject& valobj) override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::Language *
+ CreateInstance (lldb::LanguageType language);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static bool
+ IsPossibleObjCMethodName (const char *name)
+ {
+ if (!name)
+ return false;
+ bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '[';
+ bool ends_right = (name[strlen(name) - 1] == ']');
+ return (starts_right && ends_right);
+ }
+
+ static bool
+ IsPossibleObjCSelector (const char *name)
+ {
+ if (!name)
+ return false;
+
+ if (strchr(name, ':') == NULL)
+ return true;
+ else if (name[strlen(name) - 1] == ':')
+ return true;
+ else
+ return false;
+ }
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ObjCLanguage_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
new file mode 100644
index 0000000..62ddafe
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
@@ -0,0 +1,68 @@
+//===-- ObjCPlusPlusLanguage.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObjCPlusPlusLanguage.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+ObjCPlusPlusLanguage::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Objective-C++ Language",
+ CreateInstance);
+}
+
+void
+ObjCPlusPlusLanguage::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ObjCPlusPlusLanguage::GetPluginNameStatic()
+{
+ static ConstString g_name("objcplusplus");
+ return g_name;
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ObjCPlusPlusLanguage::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ObjCPlusPlusLanguage::GetPluginVersion()
+{
+ return 1;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+Language *
+ObjCPlusPlusLanguage::CreateInstance (lldb::LanguageType language)
+{
+ switch (language)
+ {
+ case lldb::eLanguageTypeObjC_plus_plus:
+ return new ObjCPlusPlusLanguage();
+ default:
+ return nullptr;
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
new file mode 100644
index 0000000..0e1db66
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
@@ -0,0 +1,63 @@
+//===-- ObjCPlusPlusLanguage.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ObjCPlusPlusLanguage_h_
+#define liblldb_ObjCPlusPlusLanguage_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/Language.h"
+
+namespace lldb_private {
+
+class ObjCPlusPlusLanguage :
+ public Language
+{
+public:
+ ObjCPlusPlusLanguage() = default;
+
+ ~ObjCPlusPlusLanguage() override = default;
+
+ lldb::LanguageType
+ GetLanguageType() const override
+ {
+ return lldb::eLanguageTypeObjC_plus_plus;
+ }
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::Language *
+ CreateInstance (lldb::LanguageType language);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CPlusPlusLanguage_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 3a3878e..8e2cfb5 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -40,14 +40,15 @@ ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
{
const bool check_cxx = true;
const bool check_objc = false;
- return in_value.GetClangType().IsPossibleDynamicType (NULL, check_cxx, check_objc);
+ return in_value.GetCompilerType().IsPossibleDynamicType (NULL, check_cxx, check_objc);
}
bool
ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
lldb::DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name,
- Address &dynamic_address)
+ Address &dynamic_address,
+ Value::ValueType &value_type)
{
// For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
// in the object. That will point to the "address point" within the vtable (not the beginning of the
@@ -58,6 +59,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
//
class_type_or_name.Clear();
+ value_type = Value::ValueType::eValueTypeScalar;
// Only a pointer or reference type can have a different dynamic and static type:
if (CouldHaveDynamicValue (in_value))
@@ -189,7 +191,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
type_sp = class_types.GetTypeAtIndex(i);
if (type_sp)
{
- if (type_sp->GetClangFullType().IsCXXClassType())
+ if (ClangASTContext::IsCXXClassType(type_sp->GetFullCompilerType ()))
{
if (log)
log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
@@ -221,8 +223,8 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
// the value we were handed.
if (type_sp)
{
- if (ClangASTContext::AreTypesSame (in_value.GetClangType(),
- type_sp->GetClangFullType()))
+ if (ClangASTContext::AreTypesSame (in_value.GetCompilerType(),
+ type_sp->GetFullCompilerType ()))
{
// The dynamic type we found was the same type,
// so we don't have a dynamic type here...
@@ -268,6 +270,42 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
return class_type_or_name.IsEmpty() == false;
}
+TypeAndOrName
+ItaniumABILanguageRuntime::FixUpDynamicType(const TypeAndOrName& type_and_or_name,
+ ValueObject& static_value)
+{
+ CompilerType static_type(static_value.GetCompilerType());
+ Flags static_type_flags(static_type.GetTypeInfo());
+
+ TypeAndOrName ret(type_and_or_name);
+ if (type_and_or_name.HasType())
+ {
+ // The type will always be the type of the dynamic object. If our parent's type was a pointer,
+ // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type
+ // should be okay...
+ CompilerType orig_type = type_and_or_name.GetCompilerType();
+ CompilerType corrected_type = orig_type;
+ if (static_type_flags.AllSet(eTypeIsPointer))
+ corrected_type = orig_type.GetPointerType ();
+ else if (static_type_flags.AllSet(eTypeIsReference))
+ corrected_type = orig_type.GetLValueReferenceType();
+ ret.SetCompilerType(corrected_type);
+ }
+ else
+ {
+ // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
+ std::string corrected_name (type_and_or_name.GetName().GetCString());
+ if (static_type_flags.AllSet(eTypeIsPointer))
+ corrected_name.append(" *");
+ else if (static_type_flags.AllSet(eTypeIsReference))
+ corrected_name.append(" &");
+ // the parent type should be a correctly pointer'ed or referenc'ed type
+ ret.SetCompilerType(static_type);
+ ret.SetName(corrected_name.c_str());
+ }
+ return ret;
+}
+
bool
ItaniumABILanguageRuntime::IsVTableName (const char *name)
{
@@ -281,46 +319,6 @@ ItaniumABILanguageRuntime::IsVTableName (const char *name)
return false;
}
-static std::map<ConstString, std::vector<ConstString> >&
-GetAlternateManglingPrefixes()
-{
- static std::map<ConstString, std::vector<ConstString> > g_alternate_mangling_prefixes;
- return g_alternate_mangling_prefixes;
-}
-
-
-size_t
-ItaniumABILanguageRuntime::GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates)
-{
- if (!mangled)
- return static_cast<size_t>(0);
-
- alternates.clear();
- const char *mangled_cstr = mangled.AsCString();
- std::map<ConstString, std::vector<ConstString> >& alternate_mangling_prefixes = GetAlternateManglingPrefixes();
- for (std::map<ConstString, std::vector<ConstString> >::iterator it = alternate_mangling_prefixes.begin();
- it != alternate_mangling_prefixes.end();
- ++it)
- {
- const char *prefix_cstr = it->first.AsCString();
- if (strncmp(mangled_cstr, prefix_cstr, strlen(prefix_cstr)) == 0)
- {
- const std::vector<ConstString> &alternate_prefixes = it->second;
- for (size_t i = 0; i < alternate_prefixes.size(); ++i)
- {
- std::string alternate_mangling(alternate_prefixes[i].AsCString());
- alternate_mangling.append(mangled_cstr + strlen(prefix_cstr));
-
- alternates.push_back(ConstString(alternate_mangling.c_str()));
- }
-
- return alternates.size();
- }
- }
-
- return static_cast<size_t>(0);
-}
-
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -344,17 +342,6 @@ ItaniumABILanguageRuntime::Initialize()
PluginManager::RegisterPlugin (GetPluginNameStatic(),
"Itanium ABI for the C++ language",
CreateInstance);
-
- // Alternate manglings for std::basic_string<...>
- std::vector<ConstString> basic_string_alternates;
- basic_string_alternates.push_back(ConstString("_ZNSs"));
- basic_string_alternates.push_back(ConstString("_ZNKSs"));
- std::map<ConstString, std::vector<ConstString> >& alternate_mangling_prefixes = GetAlternateManglingPrefixes();
-
- alternate_mangling_prefixes[ConstString("_ZNSbIcSt17char_traits<char>St15allocator<char>E")] =
- basic_string_alternates;
- alternate_mangling_prefixes[ConstString("_ZNKSbIcSt17char_traits<char>St15allocator<char>E")] =
- basic_string_alternates;
}
void
@@ -420,6 +407,7 @@ ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch
exception_names.data(),
exception_names.size(),
eFunctionNameTypeBase,
+ eLanguageTypeUnknown,
eLazyBoolNo));
return resolver_sp;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
index bc5d83b..c06b986 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
@@ -1,4 +1,4 @@
-//===-- ItaniumABILanguageRuntime.h ----------------------------------------*- C++ -*-===//
+//===-- ItaniumABILanguageRuntime.h -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <vector>
+
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@@ -20,28 +22,13 @@
#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Core/Value.h"
-#include <map>
-#include <vector>
-
namespace lldb_private {
class ItaniumABILanguageRuntime :
public lldb_private::CPPLanguageRuntime
{
public:
- ~ItaniumABILanguageRuntime() { }
-
- virtual bool
- IsVTableName (const char *name);
-
- virtual bool
- GetDynamicTypeAndAddress (ValueObject &in_value,
- lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address);
-
- virtual bool
- CouldHaveDynamicValue (ValueObject &in_value);
+ ~ItaniumABILanguageRuntime() override = default;
//------------------------------------------------------------------
// Static Functions
@@ -58,38 +45,51 @@ namespace lldb_private {
static lldb_private::ConstString
GetPluginNameStatic();
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ bool
+ IsVTableName(const char *name) override;
+
+ bool
+ GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
+
+ TypeAndOrName
+ FixUpDynamicType(const TypeAndOrName& type_and_or_name,
+ ValueObject& static_value) override;
- virtual uint32_t
- GetPluginVersion();
+ bool
+ CouldHaveDynamicValue(ValueObject &in_value) override;
- virtual void
- SetExceptionBreakpoints ();
+ void
+ SetExceptionBreakpoints() override;
- virtual void
- ClearExceptionBreakpoints ();
+ void
+ ClearExceptionBreakpoints() override;
- virtual bool
- ExceptionBreakpointsAreSet ();
+ bool
+ ExceptionBreakpointsAreSet() override;
- virtual bool
- ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason);
+ bool
+ ExceptionBreakpointsExplainStop(lldb::StopInfoSP stop_reason) override;
- virtual lldb::BreakpointResolverSP
- CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp);
+ lldb::BreakpointResolverSP
+ CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
- virtual lldb::SearchFilterSP
- CreateExceptionSearchFilter ();
+ lldb::SearchFilterSP
+ CreateExceptionSearchFilter() override;
- virtual size_t
- GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates);
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
-
lldb::BreakpointResolverSP
CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions);
@@ -107,4 +107,4 @@ namespace lldb_private {
} // namespace lldb_private
-#endif // liblldb_ItaniumABILanguageRuntime_h_
+#endif // liblldb_ItaniumABILanguageRuntime_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp
new file mode 100644
index 0000000..d59f292
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp
@@ -0,0 +1,238 @@
+//===-- GoLanguageRuntime.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GoLanguageRuntime.h"
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Symbol/GoASTContext.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "llvm/ADT/Twine.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+ValueObjectSP GetChild(ValueObject& obj, const char* name, bool dereference = true) {
+ ConstString name_const_str(name);
+ ValueObjectSP result = obj.GetChildMemberWithName(name_const_str, true);
+ if (dereference && result && result->IsPointerType()) {
+ Error err;
+ result = result->Dereference(err);
+ if (err.Fail())
+ result.reset();
+ }
+ return result;
+}
+
+ConstString ReadString(ValueObject& str, Process* process) {
+ ConstString result;
+ ValueObjectSP data = GetChild(str, "str", false);
+ ValueObjectSP len = GetChild(str, "len");
+ if (len && data)
+ {
+ Error err;
+ lldb::addr_t addr = data->GetPointerValue();
+ if (addr == LLDB_INVALID_ADDRESS)
+ return result;
+ uint64_t byte_size = len->GetValueAsUnsigned(0);
+ char* buf = new char[byte_size + 1];
+ buf[byte_size] = 0;
+ size_t bytes_read = process->ReadMemory (addr,
+ buf,
+ byte_size,
+ err);
+ if (!(err.Fail() || bytes_read != byte_size))
+ result = ConstString(buf, bytes_read);
+ delete[] buf;
+ }
+ return result;
+}
+
+ConstString
+ReadTypeName(ValueObjectSP type, Process* process)
+{
+ if (ValueObjectSP uncommon = GetChild(*type, "x"))
+ {
+ ValueObjectSP name = GetChild(*uncommon, "name");
+ ValueObjectSP package = GetChild(*uncommon, "pkgpath");
+ if (name && name->GetPointerValue() != 0 && package && package->GetPointerValue() != 0)
+ {
+ ConstString package_const_str = ReadString(*package, process);
+ ConstString name_const_str = ReadString(*name, process);
+ if (package_const_str.GetLength() == 0)
+ return name_const_str;
+ return ConstString((package_const_str.GetStringRef() + "." + name_const_str.GetStringRef()).str());
+ }
+ }
+ ValueObjectSP name = GetChild(*type, "_string");
+ if (name)
+ return ReadString(*name, process);
+ return ConstString("");
+}
+
+CompilerType
+LookupRuntimeType(ValueObjectSP type, ExecutionContext* exe_ctx, bool* is_direct)
+{
+ uint8_t kind = GetChild(*type, "kind")->GetValueAsUnsigned(0);
+ *is_direct = GoASTContext::IsDirectIface(kind);
+ if (GoASTContext::IsPointerKind(kind))
+ {
+ CompilerType type_ptr = type->GetCompilerType().GetPointerType();
+ Error err;
+ ValueObjectSP elem = type->CreateValueObjectFromAddress("elem", type->GetAddressOf() + type->GetByteSize(), *exe_ctx, type_ptr)->Dereference(err);
+ if (err.Fail())
+ return CompilerType();
+ bool tmp_direct;
+ return LookupRuntimeType(elem, exe_ctx, &tmp_direct).GetPointerType();
+ }
+ Target *target = exe_ctx->GetTargetPtr();
+ Process *process = exe_ctx->GetProcessPtr();
+
+ ConstString const_typename = ReadTypeName(type, process);
+ if (const_typename.GetLength() == 0)
+ return CompilerType();
+
+ SymbolContext sc;
+ TypeList type_list;
+ uint32_t num_matches = target->GetImages().FindTypes (sc,
+ const_typename,
+ false,
+ 2,
+ type_list);
+ if (num_matches > 0) {
+ return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
+ }
+ return CompilerType();
+}
+
+}
+
+bool
+GoLanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
+{
+ return GoASTContext::IsGoInterface(in_value.GetCompilerType());
+}
+
+bool
+GoLanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &dynamic_address,
+ Value::ValueType &value_type)
+{
+ value_type = Value::eValueTypeScalar;
+ class_type_or_name.Clear();
+ if (CouldHaveDynamicValue (in_value))
+ {
+ Error err;
+ ValueObjectSP iface = in_value.GetStaticValue();
+ ValueObjectSP data_sp = GetChild(*iface, "data", false);
+ if (!data_sp)
+ return false;
+
+ if (ValueObjectSP tab = GetChild(*iface, "tab"))
+ iface = tab;
+ ValueObjectSP type = GetChild(*iface, "_type");
+ if (!type)
+ {
+ return false;
+ }
+
+ bool direct;
+ ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
+ CompilerType final_type = LookupRuntimeType(type, &exe_ctx, &direct);
+ if (!final_type)
+ return false;
+ if (direct)
+ {
+ class_type_or_name.SetCompilerType(final_type);
+ }
+ else
+ {
+ // TODO: implement reference types or fix caller to support dynamic types that aren't pointers
+ // so we don't have to introduce this extra pointer.
+ class_type_or_name.SetCompilerType(final_type.GetPointerType());
+ }
+
+ dynamic_address.SetLoadAddress(data_sp->GetPointerValue(), exe_ctx.GetTargetPtr());
+
+ return true;
+ }
+ return false;
+}
+
+TypeAndOrName
+GoLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value)
+{
+ return type_and_or_name;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+LanguageRuntime *
+GoLanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
+{
+ if (language == eLanguageTypeGo)
+ return new GoLanguageRuntime (process);
+ else
+ return NULL;
+}
+
+void
+GoLanguageRuntime::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Go Language Runtime",
+ CreateInstance);
+}
+
+void
+GoLanguageRuntime::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+GoLanguageRuntime::GetPluginNameStatic()
+{
+ static ConstString g_name("golang");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+GoLanguageRuntime::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+GoLanguageRuntime::GetPluginVersion()
+{
+ return 1;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h
new file mode 100644
index 0000000..596d288
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h
@@ -0,0 +1,93 @@
+//===-- GoLanguageRuntime.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoLanguageRuntime_h_
+#define liblldb_GoLanguageRuntime_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Core/Value.h"
+
+namespace lldb_private {
+
+ class GoLanguageRuntime :
+ public lldb_private::LanguageRuntime
+ {
+ public:
+ ~GoLanguageRuntime() override = default;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::LanguageRuntime *
+ CreateInstance(Process *process, lldb::LanguageType language);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ lldb::LanguageType
+ GetLanguageType() const override
+ {
+ return lldb::eLanguageTypeGo;
+ }
+
+ bool
+ GetObjectDescription(Stream &str, ValueObject &object) override
+ {
+ // TODO(ribrdb): Maybe call String() method?
+ return false;
+ }
+
+ bool
+ GetObjectDescription(Stream &str, Value &value, ExecutionContextScope *exe_scope) override
+ {
+ return false;
+ }
+
+ bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type) override;
+
+ bool CouldHaveDynamicValue(ValueObject &in_value) override;
+
+ lldb::BreakpointResolverSP
+ CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override
+ {
+ return lldb::BreakpointResolverSP();
+ }
+
+ TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+
+ private:
+ GoLanguageRuntime(Process *process) : lldb_private::LanguageRuntime(process) { } // Call CreateInstance instead.
+ };
+
+} // namespace lldb_private
+
+#endif // liblldb_GoLanguageRuntime_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
new file mode 100644
index 0000000..711d324
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -0,0 +1,573 @@
+//===-- AppleObjCClassDescriptorV2.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AppleObjCClassDescriptorV2.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Expression/FunctionCaller.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool
+ClassDescriptorV2::Read_objc_class (Process* process, std::unique_ptr<objc_class_t> &objc_class) const
+{
+ objc_class.reset(new objc_class_t);
+
+ bool ret = objc_class->Read (process, m_objc_class_ptr);
+
+ if (!ret)
+ objc_class.reset();
+
+ return ret;
+}
+
+bool
+ClassDescriptorV2::objc_class_t::Read(Process *process, lldb::addr_t addr)
+{
+ size_t ptr_size = process->GetAddressByteSize();
+
+ size_t objc_class_size = ptr_size // uintptr_t isa;
+ + ptr_size // Class superclass;
+ + ptr_size // void *cache;
+ + ptr_size // IMP *vtable;
+ + ptr_size; // uintptr_t data_NEVER_USE;
+
+ DataBufferHeap objc_class_buf (objc_class_size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, objc_class_buf.GetBytes(), objc_class_size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(objc_class_buf.GetBytes(), objc_class_size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_isa = extractor.GetAddress_unchecked(&cursor); // uintptr_t isa;
+ m_superclass = extractor.GetAddress_unchecked(&cursor); // Class superclass;
+ m_cache_ptr = extractor.GetAddress_unchecked(&cursor); // void *cache;
+ m_vtable_ptr = extractor.GetAddress_unchecked(&cursor); // IMP *vtable;
+ lldb::addr_t data_NEVER_USE = extractor.GetAddress_unchecked(&cursor); // uintptr_t data_NEVER_USE;
+
+ m_flags = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
+ m_data_ptr = data_NEVER_USE & ~(lldb::addr_t)3;
+
+ return true;
+}
+
+bool
+ClassDescriptorV2::class_rw_t::Read(Process *process, lldb::addr_t addr)
+{
+ size_t ptr_size = process->GetAddressByteSize();
+
+ size_t size = sizeof(uint32_t) // uint32_t flags;
+ + sizeof(uint32_t) // uint32_t version;
+ + ptr_size // const class_ro_t *ro;
+ + ptr_size // union { method_list_t **method_lists; method_list_t *method_list; };
+ + ptr_size // struct chained_property_list *properties;
+ + ptr_size // const protocol_list_t **protocols;
+ + ptr_size // Class firstSubclass;
+ + ptr_size; // Class nextSiblingClass;
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_flags = extractor.GetU32_unchecked(&cursor);
+ m_version = extractor.GetU32_unchecked(&cursor);
+ m_ro_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_method_list_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_properties_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_firstSubclass = extractor.GetAddress_unchecked(&cursor);
+ m_nextSiblingClass = extractor.GetAddress_unchecked(&cursor);
+
+ return true;
+}
+
+bool
+ClassDescriptorV2::class_ro_t::Read(Process *process, lldb::addr_t addr)
+{
+ size_t ptr_size = process->GetAddressByteSize();
+
+ size_t size = sizeof(uint32_t) // uint32_t flags;
+ + sizeof(uint32_t) // uint32_t instanceStart;
+ + sizeof(uint32_t) // uint32_t instanceSize;
+ + (ptr_size == 8 ? sizeof(uint32_t) : 0) // uint32_t reserved; // __LP64__ only
+ + ptr_size // const uint8_t *ivarLayout;
+ + ptr_size // const char *name;
+ + ptr_size // const method_list_t *baseMethods;
+ + ptr_size // const protocol_list_t *baseProtocols;
+ + ptr_size // const ivar_list_t *ivars;
+ + ptr_size // const uint8_t *weakIvarLayout;
+ + ptr_size; // const property_list_t *baseProperties;
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_flags = extractor.GetU32_unchecked(&cursor);
+ m_instanceStart = extractor.GetU32_unchecked(&cursor);
+ m_instanceSize = extractor.GetU32_unchecked(&cursor);
+ if (ptr_size == 8)
+ m_reserved = extractor.GetU32_unchecked(&cursor);
+ else
+ m_reserved = 0;
+ m_ivarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_name_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_baseMethods_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_baseProtocols_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_ivars_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
+
+ DataBufferHeap name_buf(1024, '\0');
+
+ process->ReadCStringFromMemory(m_name_ptr, (char*)name_buf.GetBytes(), name_buf.GetByteSize(), error);
+
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ m_name.assign((char*)name_buf.GetBytes());
+
+ return true;
+}
+
+bool
+ClassDescriptorV2::Read_class_row (Process* process, const objc_class_t &objc_class, std::unique_ptr<class_ro_t> &class_ro, std::unique_ptr<class_rw_t> &class_rw) const
+{
+ class_ro.reset();
+ class_rw.reset();
+
+ Error error;
+ uint32_t class_row_t_flags = process->ReadUnsignedIntegerFromMemory(objc_class.m_data_ptr, sizeof(uint32_t), 0, error);
+ if (!error.Success())
+ return false;
+
+ if (class_row_t_flags & RW_REALIZED)
+ {
+ class_rw.reset(new class_rw_t);
+
+ if (!class_rw->Read(process, objc_class.m_data_ptr))
+ {
+ class_rw.reset();
+ return false;
+ }
+
+ class_ro.reset(new class_ro_t);
+
+ if (!class_ro->Read(process, class_rw->m_ro_ptr))
+ {
+ class_rw.reset();
+ class_ro.reset();
+ return false;
+ }
+ }
+ else
+ {
+ class_ro.reset(new class_ro_t);
+
+ if (!class_ro->Read(process, objc_class.m_data_ptr))
+ {
+ class_ro.reset();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+ClassDescriptorV2::method_list_t::Read(Process *process, lldb::addr_t addr)
+{
+ size_t size = sizeof(uint32_t) // uint32_t entsize_NEVER_USE;
+ + sizeof(uint32_t); // uint32_t count;
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_entsize = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3;
+ m_count = extractor.GetU32_unchecked(&cursor);
+ m_first_ptr = addr + cursor;
+
+ return true;
+}
+
+bool
+ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr)
+{
+ size_t size = GetSize(process);
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_name_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_types_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_imp_ptr = extractor.GetAddress_unchecked(&cursor);
+
+ process->ReadCStringFromMemory(m_name_ptr, m_name, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ process->ReadCStringFromMemory(m_types_ptr, m_types, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool
+ClassDescriptorV2::ivar_list_t::Read(Process *process, lldb::addr_t addr)
+{
+ size_t size = sizeof(uint32_t) // uint32_t entsize;
+ + sizeof(uint32_t); // uint32_t count;
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_entsize = extractor.GetU32_unchecked(&cursor);
+ m_count = extractor.GetU32_unchecked(&cursor);
+ m_first_ptr = addr + cursor;
+
+ return true;
+}
+
+bool
+ClassDescriptorV2::ivar_t::Read(Process *process, lldb::addr_t addr)
+{
+ size_t size = GetSize(process);
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_offset_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_name_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_type_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_alignment = extractor.GetU32_unchecked(&cursor);
+ m_size = extractor.GetU32_unchecked(&cursor);
+
+ process->ReadCStringFromMemory(m_name_ptr, m_name, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ process->ReadCStringFromMemory(m_type_ptr, m_type, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool
+ClassDescriptorV2::Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+ std::function <bool (const char *, const char *)> const &instance_method_func,
+ std::function <bool (const char *, const char *)> const &class_method_func,
+ std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) const
+{
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ std::unique_ptr<objc_class_t> objc_class;
+ std::unique_ptr<class_ro_t> class_ro;
+ std::unique_ptr<class_rw_t> class_rw;
+
+ if (!Read_objc_class(process, objc_class))
+ return 0;
+ if (!Read_class_row(process, *objc_class, class_ro, class_rw))
+ return 0;
+
+ static ConstString NSObject_name("NSObject");
+
+ if (m_name != NSObject_name && superclass_func)
+ superclass_func(objc_class->m_superclass);
+
+ if (instance_method_func)
+ {
+ std::unique_ptr<method_list_t> base_method_list;
+
+ base_method_list.reset(new method_list_t);
+ if (!base_method_list->Read(process, class_ro->m_baseMethods_ptr))
+ return false;
+
+ if (base_method_list->m_entsize != method_t::GetSize(process))
+ return false;
+
+ std::unique_ptr<method_t> method;
+ method.reset(new method_t);
+
+ for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i)
+ {
+ method->Read(process, base_method_list->m_first_ptr + (i * base_method_list->m_entsize));
+
+ if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
+ break;
+ }
+ }
+
+ if (class_method_func)
+ {
+ AppleObjCRuntime::ClassDescriptorSP metaclass(GetMetaclass());
+
+ // We don't care about the metaclass's superclass, or its class methods. Its instance methods are
+ // our class methods.
+
+ if (metaclass) {
+ metaclass->Describe(std::function <void (ObjCLanguageRuntime::ObjCISA)> (nullptr),
+ class_method_func,
+ std::function <bool (const char *, const char *)> (nullptr),
+ std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> (nullptr));
+ }
+ }
+
+ if (ivar_func)
+ {
+ if (class_ro->m_ivars_ptr != 0)
+ {
+ ivar_list_t ivar_list;
+ if (!ivar_list.Read(process, class_ro->m_ivars_ptr))
+ return false;
+
+ if (ivar_list.m_entsize != ivar_t::GetSize(process))
+ return false;
+
+ ivar_t ivar;
+
+ for (uint32_t i = 0, e = ivar_list.m_count; i < e; ++i)
+ {
+ ivar.Read(process, ivar_list.m_first_ptr + (i * ivar_list.m_entsize));
+
+ if (ivar_func(ivar.m_name.c_str(), ivar.m_type.c_str(), ivar.m_offset_ptr, ivar.m_size))
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+ConstString
+ClassDescriptorV2::GetClassName ()
+{
+ if (!m_name)
+ {
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ if (process)
+ {
+ std::unique_ptr<objc_class_t> objc_class;
+ std::unique_ptr<class_ro_t> class_ro;
+ std::unique_ptr<class_rw_t> class_rw;
+
+ if (!Read_objc_class(process, objc_class))
+ return m_name;
+ if (!Read_class_row(process, *objc_class, class_ro, class_rw))
+ return m_name;
+
+ m_name = ConstString(class_ro->m_name.c_str());
+ }
+ }
+ return m_name;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+ClassDescriptorV2::GetSuperclass ()
+{
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ if (!process)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ std::unique_ptr<objc_class_t> objc_class;
+
+ if (!Read_objc_class(process, objc_class))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ return m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(objc_class->m_superclass);
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+ClassDescriptorV2::GetMetaclass () const
+{
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ if (!process)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ std::unique_ptr<objc_class_t> objc_class;
+
+ if (!Read_objc_class(process, objc_class))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ lldb::addr_t candidate_isa = m_runtime.GetPointerISA(objc_class->m_isa);
+
+ return ObjCLanguageRuntime::ClassDescriptorSP(new ClassDescriptorV2(m_runtime, candidate_isa, nullptr));
+}
+
+uint64_t
+ClassDescriptorV2::GetInstanceSize ()
+{
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ if (process)
+ {
+ std::unique_ptr<objc_class_t> objc_class;
+ std::unique_ptr<class_ro_t> class_ro;
+ std::unique_ptr<class_rw_t> class_rw;
+
+ if (!Read_objc_class(process, objc_class))
+ return 0;
+ if (!Read_class_row(process, *objc_class, class_ro, class_rw))
+ return 0;
+
+ return class_ro->m_instanceSize;
+ }
+
+ return 0;
+}
+
+ClassDescriptorV2::iVarsStorage::iVarsStorage ():
+m_filled(false),
+m_ivars(),
+m_mutex(Mutex::eMutexTypeRecursive)
+{}
+
+size_t
+ClassDescriptorV2::iVarsStorage::size ()
+{
+ return m_ivars.size();
+}
+
+ClassDescriptorV2::iVarDescriptor&
+ClassDescriptorV2::iVarsStorage::operator[] (size_t idx)
+{
+ return m_ivars[idx];
+}
+
+void
+ClassDescriptorV2::iVarsStorage::fill (AppleObjCRuntimeV2& runtime, ClassDescriptorV2& descriptor)
+{
+ if (m_filled)
+ return;
+ Mutex::Locker lock(m_mutex);
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES | LIBLLDB_LOG_VERBOSE));
+ if (log)
+ log->Printf("[ClassDescriptorV2::iVarsStorage::fill] class_name = %s", descriptor.GetClassName().AsCString("<unknown"));
+ m_filled = true;
+ ObjCLanguageRuntime::EncodingToTypeSP encoding_to_type_sp(runtime.GetEncodingToType());
+ Process* process(runtime.GetProcess());
+ if (!encoding_to_type_sp)
+ return;
+ descriptor.Describe(nullptr,
+ nullptr,
+ nullptr,
+ [this,process,encoding_to_type_sp,log](const char * name, const char * type, lldb::addr_t offset_ptr, uint64_t size) -> bool {
+ const bool for_expression = false;
+ const bool stop_loop = false;
+ if (log)
+ log->Printf("[ClassDescriptorV2::iVarsStorage::fill] name = %s, encoding = %s, offset_ptr = %" PRIx64 ", size = %" PRIu64,
+ name,type,offset_ptr,size);
+ CompilerType ivar_type = encoding_to_type_sp->RealizeType(type, for_expression);
+ if (ivar_type)
+ {
+ if (log)
+ log->Printf("[ClassDescriptorV2::iVarsStorage::fill] name = %s, encoding = %s, offset_ptr = %" PRIx64 ", size = %" PRIu64 " , type_size = %" PRIu64,
+ name,type,offset_ptr,size,ivar_type.GetByteSize(nullptr));
+ Scalar offset_scalar;
+ Error error;
+ const int offset_ptr_size = 4;
+ const bool is_signed = false;
+ size_t read = process->ReadScalarIntegerFromMemory(offset_ptr, offset_ptr_size, is_signed, offset_scalar, error);
+ if (error.Success() && 4 == read)
+ {
+ if (log)
+ log->Printf("[ClassDescriptorV2::iVarsStorage::fill] offset_ptr = %" PRIx64 " --> %" PRIu32,
+ offset_ptr, offset_scalar.SInt());
+ m_ivars.push_back({ ConstString(name), ivar_type, size, offset_scalar.SInt() });
+ }
+ else if (log)
+ log->Printf("[ClassDescriptorV2::iVarsStorage::fill] offset_ptr = %" PRIx64 " --> read fail, read = %zu",
+ offset_ptr, read);
+ }
+ return stop_loop;
+ });
+}
+
+void
+ClassDescriptorV2::GetIVarInformation ()
+{
+ m_ivars_storage.fill(m_runtime, *this);
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
new file mode 100644
index 0000000..18591ec
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
@@ -0,0 +1,411 @@
+//===-- AppleObjCClassDescriptorV2.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AppleObjCClassDescriptorV2_h_
+#define liblldb_AppleObjCClassDescriptorV2_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "AppleObjCRuntimeV2.h"
+
+namespace lldb_private {
+
+class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor
+{
+public:
+ friend class lldb_private::AppleObjCRuntimeV2;
+
+ ~ClassDescriptorV2() override = default;
+
+ ConstString
+ GetClassName() override;
+
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetSuperclass() override;
+
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetMetaclass() const override;
+
+ bool
+ IsValid() override
+ {
+ return true; // any Objective-C v2 runtime class descriptor we vend is valid
+ }
+
+ // a custom descriptor is used for tagged pointers
+ bool
+ GetTaggedPointerInfo(uint64_t* info_bits = nullptr,
+ uint64_t* value_bits = nullptr,
+ uint64_t* payload = nullptr) override
+ {
+ return false;
+ }
+
+ uint64_t
+ GetInstanceSize() override;
+
+ ObjCLanguageRuntime::ObjCISA
+ GetISA() override
+ {
+ return m_objc_class_ptr;
+ }
+
+ bool
+ Describe(std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+ std::function <bool (const char *, const char *)> const &instance_method_func,
+ std::function <bool (const char *, const char *)> const &class_method_func,
+ std::function <bool (const char *, const char *,
+ lldb::addr_t, uint64_t)> const &ivar_func) const override;
+
+ size_t
+ GetNumIVars() override
+ {
+ GetIVarInformation();
+ return m_ivars_storage.size();
+ }
+
+ iVarDescriptor
+ GetIVarAtIndex(size_t idx) override
+ {
+ if (idx >= GetNumIVars())
+ return iVarDescriptor();
+ return m_ivars_storage[idx];
+ }
+
+protected:
+ void
+ GetIVarInformation ();
+
+private:
+ static const uint32_t RW_REALIZED = (1 << 31);
+
+ struct objc_class_t {
+ ObjCLanguageRuntime::ObjCISA m_isa; // The class's metaclass.
+ ObjCLanguageRuntime::ObjCISA m_superclass;
+ lldb::addr_t m_cache_ptr;
+ lldb::addr_t m_vtable_ptr;
+ lldb::addr_t m_data_ptr;
+ uint8_t m_flags;
+
+ objc_class_t () :
+ m_isa (0),
+ m_superclass (0),
+ m_cache_ptr (0),
+ m_vtable_ptr (0),
+ m_data_ptr (0),
+ m_flags (0)
+ {
+ }
+
+ void
+ Clear()
+ {
+ m_isa = 0;
+ m_superclass = 0;
+ m_cache_ptr = 0;
+ m_vtable_ptr = 0;
+ m_data_ptr = 0;
+ m_flags = 0;
+ }
+
+ bool
+ Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct class_ro_t {
+ uint32_t m_flags;
+ uint32_t m_instanceStart;
+ uint32_t m_instanceSize;
+ uint32_t m_reserved;
+
+ lldb::addr_t m_ivarLayout_ptr;
+ lldb::addr_t m_name_ptr;
+ lldb::addr_t m_baseMethods_ptr;
+ lldb::addr_t m_baseProtocols_ptr;
+ lldb::addr_t m_ivars_ptr;
+
+ lldb::addr_t m_weakIvarLayout_ptr;
+ lldb::addr_t m_baseProperties_ptr;
+
+ std::string m_name;
+
+ bool
+ Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct class_rw_t {
+ uint32_t m_flags;
+ uint32_t m_version;
+
+ lldb::addr_t m_ro_ptr;
+ union {
+ lldb::addr_t m_method_list_ptr;
+ lldb::addr_t m_method_lists_ptr;
+ };
+ lldb::addr_t m_properties_ptr;
+ lldb::addr_t m_protocols_ptr;
+
+ ObjCLanguageRuntime::ObjCISA m_firstSubclass;
+ ObjCLanguageRuntime::ObjCISA m_nextSiblingClass;
+
+ bool
+ Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct method_list_t
+ {
+ uint32_t m_entsize;
+ uint32_t m_count;
+ lldb::addr_t m_first_ptr;
+
+ bool
+ Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct method_t
+ {
+ lldb::addr_t m_name_ptr;
+ lldb::addr_t m_types_ptr;
+ lldb::addr_t m_imp_ptr;
+
+ std::string m_name;
+ std::string m_types;
+
+ static size_t GetSize(Process *process)
+ {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ return ptr_size // SEL name;
+ + ptr_size // const char *types;
+ + ptr_size; // IMP imp;
+ }
+
+ bool
+ Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct ivar_list_t
+ {
+ uint32_t m_entsize;
+ uint32_t m_count;
+ lldb::addr_t m_first_ptr;
+
+ bool Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct ivar_t
+ {
+ lldb::addr_t m_offset_ptr;
+ lldb::addr_t m_name_ptr;
+ lldb::addr_t m_type_ptr;
+ uint32_t m_alignment;
+ uint32_t m_size;
+
+ std::string m_name;
+ std::string m_type;
+
+ static size_t GetSize(Process *process)
+ {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ return ptr_size // uintptr_t *offset;
+ + ptr_size // const char *name;
+ + ptr_size // const char *type;
+ + sizeof(uint32_t) // uint32_t alignment;
+ + sizeof(uint32_t); // uint32_t size;
+ }
+
+ bool
+ Read(Process *process, lldb::addr_t addr);
+ };
+
+ class iVarsStorage
+ {
+ public:
+ iVarsStorage ();
+
+ size_t
+ size ();
+
+ iVarDescriptor&
+ operator[] (size_t idx);
+
+ void
+ fill (AppleObjCRuntimeV2& runtime, ClassDescriptorV2& descriptor);
+
+ private:
+ bool m_filled;
+ std::vector<iVarDescriptor> m_ivars;
+ Mutex m_mutex;
+ };
+
+ // The constructor should only be invoked by the runtime as it builds its caches
+ // or populates them. A ClassDescriptorV2 should only ever exist in a cache.
+ ClassDescriptorV2(AppleObjCRuntimeV2 &runtime, ObjCLanguageRuntime::ObjCISA isa, const char *name) :
+ m_runtime (runtime),
+ m_objc_class_ptr (isa),
+ m_name (name),
+ m_ivars_storage()
+ {
+ }
+
+ bool
+ Read_objc_class (Process* process, std::unique_ptr<objc_class_t> &objc_class) const;
+
+ bool
+ Read_class_row (Process* process, const objc_class_t &objc_class, std::unique_ptr<class_ro_t> &class_ro, std::unique_ptr<class_rw_t> &class_rw) const;
+
+ AppleObjCRuntimeV2 &m_runtime; // The runtime, so we can read information lazily.
+ lldb::addr_t m_objc_class_ptr; // The address of the objc_class_t. (I.e., objects of this class type have this as their ISA)
+ ConstString m_name; // May be NULL
+ iVarsStorage m_ivars_storage;
+};
+
+// tagged pointer descriptor
+class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor
+{
+public:
+ ClassDescriptorV2Tagged (ConstString class_name,
+ uint64_t payload)
+ {
+ m_name = class_name;
+ if (!m_name)
+ {
+ m_valid = false;
+ return;
+ }
+ m_valid = true;
+ m_payload = payload;
+ m_info_bits = (m_payload & 0xF0ULL) >> 4;
+ m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
+ }
+
+ ClassDescriptorV2Tagged (ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
+ uint64_t payload)
+ {
+ if (!actual_class_sp)
+ {
+ m_valid = false;
+ return;
+ }
+ m_name = actual_class_sp->GetClassName();
+ if (!m_name)
+ {
+ m_valid = false;
+ return;
+ }
+ m_valid = true;
+ m_payload = payload;
+ m_info_bits = (m_payload & 0x0FULL);
+ m_value_bits = (m_payload & ~0x0FULL) >> 4;
+ }
+
+ ~ClassDescriptorV2Tagged() override = default;
+
+ ConstString
+ GetClassName() override
+ {
+ return m_name;
+ }
+
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetSuperclass() override
+ {
+ // tagged pointers can represent a class that has a superclass, but since that information is not
+ // stored in the object itself, we would have to query the runtime to discover the hierarchy
+ // for the time being, we skip this step in the interest of static discovery
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ }
+
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetMetaclass() const override
+ {
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ }
+
+ bool
+ IsValid() override
+ {
+ return m_valid;
+ }
+
+ bool
+ IsKVO() override
+ {
+ return false; // tagged pointers are not KVO'ed
+ }
+
+ bool
+ IsCFType() override
+ {
+ return false; // tagged pointers are not CF objects
+ }
+
+ bool
+ GetTaggedPointerInfo(uint64_t* info_bits = nullptr,
+ uint64_t* value_bits = nullptr,
+ uint64_t* payload = nullptr) override
+ {
+ if (info_bits)
+ *info_bits = GetInfoBits();
+ if (value_bits)
+ *value_bits = GetValueBits();
+ if (payload)
+ *payload = GetPayload();
+ return true;
+ }
+
+ uint64_t
+ GetInstanceSize() override
+ {
+ return (IsValid() ? m_pointer_size : 0);
+ }
+
+ ObjCLanguageRuntime::ObjCISA
+ GetISA() override
+ {
+ return 0; // tagged pointers have no ISA
+ }
+
+ // these calls are not part of any formal tagged pointers specification
+ virtual uint64_t
+ GetValueBits ()
+ {
+ return (IsValid() ? m_value_bits : 0);
+ }
+
+ virtual uint64_t
+ GetInfoBits ()
+ {
+ return (IsValid() ? m_info_bits : 0);
+ }
+
+ virtual uint64_t
+ GetPayload ()
+ {
+ return (IsValid() ? m_payload : 0);
+ }
+
+private:
+ ConstString m_name;
+ uint8_t m_pointer_size;
+ bool m_valid;
+ uint64_t m_info_bits;
+ uint64_t m_value_bits;
+ uint64_t m_payload;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_AppleObjCClassDescriptorV2_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
new file mode 100644
index 0000000..cd6ece2
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
@@ -0,0 +1,665 @@
+//===-- AppleObjCDeclVendor.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AppleObjCDeclVendor.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "Plugins/ExpressionParser/Clang/ASTDumper.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+
+using namespace lldb_private;
+
+class lldb_private::AppleObjCExternalASTSource : public ClangExternalASTSourceCommon
+{
+public:
+ AppleObjCExternalASTSource (AppleObjCDeclVendor &decl_vendor) :
+ m_decl_vendor(decl_vendor)
+ {
+ }
+
+ bool
+ FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx, clang::DeclarationName name) override
+ {
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
+
+ if (log)
+ {
+ log->Printf("AppleObjCExternalASTSource::FindExternalVisibleDeclsByName[%u] on (ASTContext*)%p Looking for %s in (%sDecl*)%p",
+ current_id,
+ static_cast<void*>(&decl_ctx->getParentASTContext()),
+ name.getAsString().c_str(), decl_ctx->getDeclKindName(),
+ static_cast<const void*>(decl_ctx));
+ }
+
+ do
+ {
+ const clang::ObjCInterfaceDecl *interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
+
+ if (!interface_decl)
+ break;
+
+ clang::ObjCInterfaceDecl *non_const_interface_decl = const_cast<clang::ObjCInterfaceDecl*>(interface_decl);
+
+ if (!m_decl_vendor.FinishDecl(non_const_interface_decl))
+ break;
+
+ clang::DeclContext::lookup_result result = non_const_interface_decl->lookup(name);
+
+ return (result.size() != 0);
+ }
+ while(0);
+
+ SetNoExternalVisibleDeclsForName(decl_ctx, name);
+ return false;
+ }
+
+ void
+ CompleteType(clang::TagDecl *tag_decl) override
+ {
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
+
+ if (log)
+ {
+ log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s",
+ current_id,
+ static_cast<void*>(&tag_decl->getASTContext()),
+ static_cast<void*>(tag_decl),
+ tag_decl->getName().str().c_str());
+
+ log->Printf(" AOEAS::CT[%u] Before:", current_id);
+ ASTDumper dumper((clang::Decl*)tag_decl);
+ dumper.ToLog(log, " [CT] ");
+ }
+
+ if (log)
+ {
+ log->Printf(" AOEAS::CT[%u] After:", current_id);
+ ASTDumper dumper((clang::Decl*)tag_decl);
+ dumper.ToLog(log, " [CT] ");
+ }
+ return;
+ }
+
+ void
+ CompleteType(clang::ObjCInterfaceDecl *interface_decl) override
+ {
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
+
+ if (log)
+ {
+ log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on (ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s",
+ current_id,
+ static_cast<void*>(&interface_decl->getASTContext()),
+ static_cast<void*>(interface_decl),
+ interface_decl->getName().str().c_str());
+
+ log->Printf(" AOEAS::CT[%u] Before:", current_id);
+ ASTDumper dumper((clang::Decl*)interface_decl);
+ dumper.ToLog(log, " [CT] ");
+ }
+
+ m_decl_vendor.FinishDecl(interface_decl);
+
+ if (log)
+ {
+ log->Printf(" [CT] After:");
+ ASTDumper dumper((clang::Decl*)interface_decl);
+ dumper.ToLog(log, " [CT] ");
+ }
+ return;
+ }
+
+ bool
+ layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override
+ {
+ return false;
+ }
+
+ void
+ StartTranslationUnit(clang::ASTConsumer *Consumer) override
+ {
+ clang::TranslationUnitDecl *translation_unit_decl = m_decl_vendor.m_ast_ctx.getASTContext()->getTranslationUnitDecl();
+ translation_unit_decl->setHasExternalVisibleStorage();
+ translation_unit_decl->setHasExternalLexicalStorage();
+ }
+private:
+ AppleObjCDeclVendor &m_decl_vendor;
+};
+
+AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime) :
+ DeclVendor(),
+ m_runtime(runtime),
+ m_ast_ctx(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().getTriple().c_str()),
+ m_type_realizer_sp(m_runtime.GetEncodingToType())
+{
+ m_external_source = new AppleObjCExternalASTSource (*this);
+ llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr (m_external_source);
+ m_ast_ctx.getASTContext()->setExternalSource(external_source_owning_ptr);
+}
+
+clang::ObjCInterfaceDecl*
+AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa)
+{
+ ISAToInterfaceMap::const_iterator iter = m_isa_to_interface.find(isa);
+
+ if (iter != m_isa_to_interface.end())
+ return iter->second;
+
+ clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptorFromISA(isa);
+
+ if (!descriptor)
+ return NULL;
+
+ const ConstString &name(descriptor->GetClassName());
+
+ clang::IdentifierInfo &identifier_info = ast_ctx->Idents.get(name.GetStringRef());
+
+ clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(*ast_ctx,
+ ast_ctx->getTranslationUnitDecl(),
+ clang::SourceLocation(),
+ &identifier_info,
+ nullptr,
+ nullptr);
+
+ ClangASTMetadata meta_data;
+ meta_data.SetISAPtr(isa);
+ m_external_source->SetMetadata(new_iface_decl, meta_data);
+
+ new_iface_decl->setHasExternalVisibleStorage();
+ new_iface_decl->setHasExternalLexicalStorage();
+
+ ast_ctx->getTranslationUnitDecl()->addDecl(new_iface_decl);
+
+ m_isa_to_interface[isa] = new_iface_decl;
+
+ return new_iface_decl;
+}
+
+class ObjCRuntimeMethodType
+{
+public:
+ ObjCRuntimeMethodType (const char *types) : m_is_valid(false)
+ {
+ const char *cursor = types;
+ enum ParserState {
+ Start = 0,
+ InType,
+ InPos
+ } state = Start;
+ const char *type = NULL;
+ int brace_depth = 0;
+
+ uint32_t stepsLeft = 256;
+
+ while (1)
+ {
+ if (--stepsLeft == 0)
+ {
+ m_is_valid = false;
+ return;
+ }
+
+ switch (state)
+ {
+ case Start:
+ {
+ switch (*cursor)
+ {
+ default:
+ state = InType;
+ type = cursor;
+ break;
+ case '\0':
+ m_is_valid = true;
+ return;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ m_is_valid = false;
+ return;
+ }
+ }
+ break;
+ case InType:
+ {
+ switch (*cursor)
+ {
+ default:
+ ++cursor;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (!brace_depth)
+ {
+ state = InPos;
+ if (type)
+ {
+ m_type_vector.push_back(std::string(type, (cursor - type)));
+ }
+ else
+ {
+ m_is_valid = false;
+ return;
+ }
+ type = NULL;
+ }
+ else
+ {
+ ++cursor;
+ }
+ break;
+ case '[': case '{': case '(':
+ ++brace_depth;
+ ++cursor;
+ break;
+ case ']': case '}': case ')':
+ if (!brace_depth)
+ {
+ m_is_valid = false;
+ return;
+ }
+ --brace_depth;
+ ++cursor;
+ break;
+ case '\0':
+ m_is_valid = false;
+ return;
+ }
+ }
+ break;
+ case InPos:
+ {
+ switch (*cursor)
+ {
+ default:
+ state = InType;
+ type = cursor;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ ++cursor;
+ break;
+ case '\0':
+ m_is_valid = true;
+ return;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ clang::ObjCMethodDecl *BuildMethod (clang::ObjCInterfaceDecl *interface_decl, const char *name, bool instance, ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp)
+ {
+ if (!m_is_valid || m_type_vector.size() < 3)
+ return NULL;
+
+ clang::ASTContext &ast_ctx(interface_decl->getASTContext());
+
+ clang::QualType return_qual_type;
+
+ const bool isInstance = instance;
+ const bool isVariadic = false;
+ const bool isSynthesized = false;
+ const bool isImplicitlyDeclared = true;
+ const bool isDefined = false;
+ const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None;
+ const bool HasRelatedResultType = false;
+ const bool for_expression = true;
+
+ std::vector <clang::IdentifierInfo *> selector_components;
+
+ const char *name_cursor = name;
+ bool is_zero_argument = true;
+
+
+ while (*name_cursor != '\0')
+ {
+ const char *colon_loc = strchr(name_cursor, ':');
+ if (!colon_loc)
+ {
+ selector_components.push_back(&ast_ctx.Idents.get(llvm::StringRef(name_cursor)));
+ break;
+ }
+ else
+ {
+ is_zero_argument = false;
+ selector_components.push_back(&ast_ctx.Idents.get(llvm::StringRef(name_cursor, colon_loc - name_cursor)));
+ name_cursor = colon_loc + 1;
+ }
+ }
+
+ clang::Selector sel = ast_ctx.Selectors.getSelector(is_zero_argument ? 0 : selector_components.size(), selector_components.data());
+
+ clang::QualType ret_type = ClangASTContext::GetQualType(type_realizer_sp->RealizeType(interface_decl->getASTContext(), m_type_vector[0].c_str(), for_expression));
+
+ if (ret_type.isNull())
+ return NULL;
+
+ clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create(ast_ctx,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ sel,
+ ret_type,
+ NULL,
+ interface_decl,
+ isInstance,
+ isVariadic,
+ isSynthesized,
+ isImplicitlyDeclared,
+ isDefined,
+ impControl,
+ HasRelatedResultType);
+
+ std::vector <clang::ParmVarDecl*> parm_vars;
+
+ for (size_t ai = 3, ae = m_type_vector.size();
+ ai != ae;
+ ++ai)
+ {
+ const bool for_expression = true;
+ clang::QualType arg_type = ClangASTContext::GetQualType(type_realizer_sp->RealizeType(ast_ctx, m_type_vector[ai].c_str(), for_expression));
+
+ if (arg_type.isNull())
+ return NULL; // well, we just wasted a bunch of time. Wish we could delete the stuff we'd just made!
+
+ parm_vars.push_back(clang::ParmVarDecl::Create(ast_ctx,
+ ret,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ NULL,
+ arg_type,
+ NULL,
+ clang::SC_None,
+ NULL));
+ }
+
+ ret->setMethodParams(ast_ctx, llvm::ArrayRef<clang::ParmVarDecl*>(parm_vars), llvm::ArrayRef<clang::SourceLocation>());
+
+ return ret;
+ }
+private:
+ typedef std::vector <std::string> TypeVector;
+
+ TypeVector m_type_vector;
+ bool m_is_valid;
+};
+
+bool
+AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl)
+{
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
+
+ ClangASTMetadata *metadata = m_external_source->GetMetadata(interface_decl);
+ ObjCLanguageRuntime::ObjCISA objc_isa = 0;
+ if (metadata)
+ objc_isa = metadata->GetISAPtr();
+
+ if (!objc_isa)
+ return false;
+
+ if (!interface_decl->hasExternalVisibleStorage())
+ return true;
+
+ interface_decl->startDefinition();
+
+ interface_decl->setHasExternalVisibleStorage(false);
+ interface_decl->setHasExternalLexicalStorage(false);
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptorFromISA(objc_isa);
+
+ if (!descriptor)
+ return false;
+
+ auto superclass_func = [interface_decl, this](ObjCLanguageRuntime::ObjCISA isa)
+ {
+ clang::ObjCInterfaceDecl *superclass_decl = GetDeclForISA(isa);
+
+ if (!superclass_decl)
+ return;
+
+ FinishDecl(superclass_decl);
+ clang::ASTContext *context = m_ast_ctx.getASTContext();
+ interface_decl->setSuperClass(
+ context->getTrivialTypeSourceInfo(context->getObjCInterfaceType(superclass_decl)));
+ };
+
+ auto instance_method_func = [log, interface_decl, this](const char *name, const char *types) -> bool
+ {
+ if (!name || !types)
+ return false; // skip this one
+
+ ObjCRuntimeMethodType method_type(types);
+
+ clang::ObjCMethodDecl *method_decl = method_type.BuildMethod (interface_decl, name, true, m_type_realizer_sp);
+
+ if (log)
+ log->Printf("[ AOTV::FD] Instance method [%s] [%s]", name, types);
+
+ if (method_decl)
+ interface_decl->addDecl(method_decl);
+
+ return false;
+ };
+
+ auto class_method_func = [log, interface_decl, this](const char *name, const char *types) -> bool
+ {
+ if (!name || !types)
+ return false; // skip this one
+
+ ObjCRuntimeMethodType method_type(types);
+
+ clang::ObjCMethodDecl *method_decl = method_type.BuildMethod (interface_decl, name, false, m_type_realizer_sp);
+
+ if (log)
+ log->Printf("[ AOTV::FD] Class method [%s] [%s]", name, types);
+
+ if (method_decl)
+ interface_decl->addDecl(method_decl);
+
+ return false;
+ };
+
+ auto ivar_func = [log, interface_decl, this](const char *name, const char *type, lldb::addr_t offset_ptr, uint64_t size) -> bool
+ {
+ if (!name || !type)
+ return false;
+
+ const bool for_expression = false;
+
+ if (log)
+ log->Printf("[ AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64, name, type, offset_ptr);
+
+ CompilerType ivar_type = m_runtime.GetEncodingToType()->RealizeType(m_ast_ctx, type, for_expression);
+
+ if (ivar_type.IsValid())
+ {
+ clang::TypeSourceInfo * const type_source_info = nullptr;
+ const bool is_synthesized = false;
+ clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create (*m_ast_ctx.getASTContext(),
+ interface_decl,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ &m_ast_ctx.getASTContext()->Idents.get(name),
+ ClangASTContext::GetQualType(ivar_type),
+ type_source_info, // TypeSourceInfo *
+ clang::ObjCIvarDecl::Public,
+ 0,
+ is_synthesized);
+
+ if (ivar_decl)
+ {
+ interface_decl->addDecl(ivar_decl);
+ }
+ }
+
+ return false;
+ };
+
+ if (log)
+ {
+ ASTDumper method_dumper ((clang::Decl*)interface_decl);
+
+ log->Printf("[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C interface for %s", descriptor->GetClassName().AsCString());
+ }
+
+
+ if (!descriptor->Describe(superclass_func,
+ instance_method_func,
+ class_method_func,
+ ivar_func))
+ return false;
+
+ if (log)
+ {
+ ASTDumper method_dumper ((clang::Decl*)interface_decl);
+
+ log->Printf("[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface");
+
+ method_dumper.ToLog(log, " [AOTV::FD] ");
+ }
+
+ return true;
+}
+
+uint32_t
+AppleObjCDeclVendor::FindDecls (const ConstString &name,
+ bool append,
+ uint32_t max_matches,
+ std::vector <clang::NamedDecl *> &decls)
+{
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
+
+ if (log)
+ log->Printf("AppleObjCDeclVendor::FindTypes [%u] ('%s', %s, %u, )",
+ current_id,
+ (const char*)name.AsCString(),
+ append ? "true" : "false",
+ max_matches);
+
+ if (!append)
+ decls.clear();
+
+ uint32_t ret = 0;
+
+ do
+ {
+ // See if the type is already in our ASTContext.
+
+ clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
+
+ clang::IdentifierInfo &identifier_info = ast_ctx->Idents.get(name.GetStringRef());
+ clang::DeclarationName decl_name = ast_ctx->DeclarationNames.getIdentifier(&identifier_info);
+
+ clang::DeclContext::lookup_result lookup_result = ast_ctx->getTranslationUnitDecl()->lookup(decl_name);
+
+ if (!lookup_result.empty())
+ {
+ if (clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0]))
+ {
+ if (log)
+ {
+ clang::QualType result_iface_type = ast_ctx->getObjCInterfaceType(result_iface_decl);
+ ASTDumper dumper(result_iface_type);
+
+ uint64_t isa_value = LLDB_INVALID_ADDRESS;
+ ClangASTMetadata *metadata = m_external_source->GetMetadata(result_iface_decl);
+ if (metadata)
+ isa_value = metadata->GetISAPtr();
+
+ log->Printf("AOCTV::FT [%u] Found %s (isa 0x%" PRIx64 ") in the ASTContext",
+ current_id,
+ dumper.GetCString(),
+ isa_value);
+ }
+
+ decls.push_back(result_iface_decl);
+ ret++;
+ break;
+ }
+ else
+ {
+ if (log)
+ log->Printf("AOCTV::FT [%u] There's something in the ASTContext, but it's not something we know about",
+ current_id);
+ break;
+ }
+ }
+ else if(log)
+ {
+ log->Printf("AOCTV::FT [%u] Couldn't find %s in the ASTContext",
+ current_id,
+ name.AsCString());
+ }
+
+ // It's not. If it exists, we have to put it into our ASTContext.
+
+ ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name);
+
+ if (!isa)
+ {
+ if (log)
+ log->Printf("AOCTV::FT [%u] Couldn't find the isa",
+ current_id);
+
+ break;
+ }
+
+ clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa);
+
+ if (!iface_decl)
+ {
+ if (log)
+ log->Printf("AOCTV::FT [%u] Couldn't get the Objective-C interface for isa 0x%" PRIx64,
+ current_id,
+ (uint64_t)isa);
+
+ break;
+ }
+
+ if (log)
+ {
+ clang::QualType new_iface_type = ast_ctx->getObjCInterfaceType(iface_decl);
+ ASTDumper dumper(new_iface_type);
+ log->Printf("AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")",
+ current_id,
+ dumper.GetCString(),
+ (uint64_t)isa);
+ }
+
+ decls.push_back(iface_decl);
+ ret++;
+ break;
+ } while (0);
+
+ return ret;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
new file mode 100644
index 0000000..88789c7
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
@@ -0,0 +1,55 @@
+//===-- AppleObjCDeclVendor.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AppleObjCDeclVendor_h_
+#define liblldb_AppleObjCDeclVendor_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/DeclVendor.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+
+namespace lldb_private {
+
+class AppleObjCExternalASTSource;
+
+class AppleObjCDeclVendor : public DeclVendor
+{
+public:
+ AppleObjCDeclVendor(ObjCLanguageRuntime &runtime);
+
+ uint32_t
+ FindDecls(const ConstString &name,
+ bool append,
+ uint32_t max_matches,
+ std::vector <clang::NamedDecl *> &decls) override;
+
+ friend class AppleObjCExternalASTSource;
+
+private:
+ clang::ObjCInterfaceDecl *GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa);
+ bool FinishDecl(clang::ObjCInterfaceDecl *decl);
+
+ ObjCLanguageRuntime &m_runtime;
+ ClangASTContext m_ast_ctx;
+ ObjCLanguageRuntime::EncodingToTypeSP m_type_realizer_sp;
+ AppleObjCExternalASTSource *m_external_source;
+
+ typedef llvm::DenseMap<ObjCLanguageRuntime::ObjCISA, clang::ObjCInterfaceDecl *> ISAToInterfaceMap;
+
+ ISAToInterfaceMap m_isa_to_interface;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_AppleObjCDeclVendor_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
new file mode 100644
index 0000000..2810b24
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -0,0 +1,554 @@
+//===-- AppleObjCRuntime.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AppleObjCRuntime.h"
+#include "AppleObjCTrampolineHandler.h"
+
+#include "clang/AST/Type.h"
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define PO_FUNCTION_TIMEOUT_USEC 15*1000*1000
+
+AppleObjCRuntime::~AppleObjCRuntime()
+{
+}
+
+AppleObjCRuntime::AppleObjCRuntime(Process *process) :
+ ObjCLanguageRuntime (process),
+ m_read_objc_library (false),
+ m_objc_trampoline_handler_ap (),
+ m_Foundation_major()
+{
+ ReadObjCLibraryIfNeeded (process->GetTarget().GetImages());
+}
+
+bool
+AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &valobj)
+{
+ CompilerType compiler_type(valobj.GetCompilerType());
+ bool is_signed;
+ // ObjC objects can only be pointers (or numbers that actually represents pointers
+ // but haven't been typecast, because reasons..)
+ if (!compiler_type.IsIntegerType (is_signed) && !compiler_type.IsPointerType ())
+ return false;
+
+ // Make the argument list: we pass one arg, the address of our pointer, to the print function.
+ Value val;
+
+ if (!valobj.ResolveValue(val.GetScalar()))
+ return false;
+
+ // Value Objects may not have a process in their ExecutionContextRef. But we need to have one
+ // in the ref we pass down to eventually call description. Get it from the target if it isn't
+ // present.
+ ExecutionContext exe_ctx;
+ if (valobj.GetProcessSP())
+ {
+ exe_ctx = ExecutionContext(valobj.GetExecutionContextRef());
+ }
+ else
+ {
+ exe_ctx.SetContext(valobj.GetTargetSP(), true);
+ if (!exe_ctx.HasProcessScope())
+ return false;
+ }
+ return GetObjectDescription(str, val, exe_ctx.GetBestExecutionContextScope());
+
+}
+bool
+AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionContextScope *exe_scope)
+{
+ if (!m_read_objc_library)
+ return false;
+
+ ExecutionContext exe_ctx;
+ exe_scope->CalculateExecutionContext(exe_ctx);
+ Process *process = exe_ctx.GetProcessPtr();
+ if (!process)
+ return false;
+
+ // We need other parts of the exe_ctx, but the processes have to match.
+ assert (m_process == process);
+
+ // Get the function address for the print function.
+ const Address *function_address = GetPrintForDebuggerAddr();
+ if (!function_address)
+ return false;
+
+ Target *target = exe_ctx.GetTargetPtr();
+ CompilerType compiler_type = value.GetCompilerType();
+ if (compiler_type)
+ {
+ if (!ClangASTContext::IsObjCObjectPointerType(compiler_type))
+ {
+ strm.Printf ("Value doesn't point to an ObjC object.\n");
+ return false;
+ }
+ }
+ else
+ {
+ // If it is not a pointer, see if we can make it into a pointer.
+ ClangASTContext *ast_context = target->GetScratchClangASTContext();
+ CompilerType opaque_type = ast_context->GetBasicType(eBasicTypeObjCID);
+ if (!opaque_type)
+ opaque_type = ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ //value.SetContext(Value::eContextTypeClangType, opaque_type_ptr);
+ value.SetCompilerType (opaque_type);
+ }
+
+ ValueList arg_value_list;
+ arg_value_list.PushValue(value);
+
+ // This is the return value:
+ ClangASTContext *ast_context = target->GetScratchClangASTContext();
+
+ CompilerType return_compiler_type = ast_context->GetCStringType(true);
+ Value ret;
+// ret.SetContext(Value::eContextTypeClangType, return_compiler_type);
+ ret.SetCompilerType (return_compiler_type);
+
+ if (exe_ctx.GetFramePtr() == NULL)
+ {
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (thread == NULL)
+ {
+ exe_ctx.SetThreadSP(process->GetThreadList().GetSelectedThread());
+ thread = exe_ctx.GetThreadPtr();
+ }
+ if (thread)
+ {
+ exe_ctx.SetFrameSP(thread->GetSelectedFrame());
+ }
+ }
+
+ // Now we're ready to call the function:
+
+ StreamString error_stream;
+ lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS;
+
+ if (!m_print_object_caller_up)
+ {
+ Error error;
+ m_print_object_caller_up.reset(exe_scope->CalculateTarget()->GetFunctionCallerForLanguage (eLanguageTypeObjC,
+ return_compiler_type,
+ *function_address,
+ arg_value_list,
+ "objc-object-description",
+ error));
+ if (error.Fail())
+ {
+ m_print_object_caller_up.reset();
+ strm.Printf("Could not get function runner to call print for debugger function: %s.", error.AsCString());
+ return false;
+ }
+ m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, error_stream);
+ }
+ else
+ {
+ m_print_object_caller_up->WriteFunctionArguments(exe_ctx,
+ wrapper_struct_addr,
+ arg_value_list,
+ error_stream);
+ }
+
+
+
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(true);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC);
+
+ ExpressionResults results = m_print_object_caller_up->ExecuteFunction (exe_ctx,
+ &wrapper_struct_addr,
+ options,
+ error_stream,
+ ret);
+ if (results != eExpressionCompleted)
+ {
+ strm.Printf("Error evaluating Print Object function: %d.\n", results);
+ return false;
+ }
+
+ addr_t result_ptr = ret.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+
+ char buf[512];
+ size_t cstr_len = 0;
+ size_t full_buffer_len = sizeof (buf) - 1;
+ size_t curr_len = full_buffer_len;
+ while (curr_len == full_buffer_len)
+ {
+ Error error;
+ curr_len = process->ReadCStringFromMemory(result_ptr + cstr_len, buf, sizeof(buf), error);
+ strm.Write (buf, curr_len);
+ cstr_len += curr_len;
+ }
+ return cstr_len > 0;
+}
+
+lldb::ModuleSP
+AppleObjCRuntime::GetObjCModule ()
+{
+ ModuleSP module_sp (m_objc_module_wp.lock());
+ if (module_sp)
+ return module_sp;
+
+ Process *process = GetProcess();
+ if (process)
+ {
+ const ModuleList& modules = process->GetTarget().GetImages();
+ for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
+ {
+ module_sp = modules.GetModuleAtIndex(idx);
+ if (AppleObjCRuntime::AppleIsModuleObjCLibrary(module_sp))
+ {
+ m_objc_module_wp = module_sp;
+ return module_sp;
+ }
+ }
+ }
+ return ModuleSP();
+}
+
+Address *
+AppleObjCRuntime::GetPrintForDebuggerAddr()
+{
+ if (!m_PrintForDebugger_addr.get())
+ {
+ const ModuleList &modules = m_process->GetTarget().GetImages();
+
+ SymbolContextList contexts;
+ SymbolContext context;
+
+ if ((!modules.FindSymbolsWithNameAndType(ConstString ("_NSPrintForDebugger"), eSymbolTypeCode, contexts)) &&
+ (!modules.FindSymbolsWithNameAndType(ConstString ("_CFPrintForDebugger"), eSymbolTypeCode, contexts)))
+ return NULL;
+
+ contexts.GetContextAtIndex(0, context);
+
+ m_PrintForDebugger_addr.reset(new Address(context.symbol->GetAddress()));
+ }
+
+ return m_PrintForDebugger_addr.get();
+}
+
+bool
+AppleObjCRuntime::CouldHaveDynamicValue (ValueObject &in_value)
+{
+ return in_value.GetCompilerType().IsPossibleDynamicType (NULL,
+ false, // do not check C++
+ true); // check ObjC
+}
+
+bool
+AppleObjCRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type)
+{
+ return false;
+}
+
+TypeAndOrName
+AppleObjCRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name,
+ ValueObject& static_value)
+{
+ CompilerType static_type(static_value.GetCompilerType());
+ Flags static_type_flags(static_type.GetTypeInfo());
+
+ TypeAndOrName ret(type_and_or_name);
+ if (type_and_or_name.HasType())
+ {
+ // The type will always be the type of the dynamic object. If our parent's type was a pointer,
+ // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type
+ // should be okay...
+ CompilerType orig_type = type_and_or_name.GetCompilerType();
+ CompilerType corrected_type = orig_type;
+ if (static_type_flags.AllSet(eTypeIsPointer))
+ corrected_type = orig_type.GetPointerType ();
+ ret.SetCompilerType(corrected_type);
+ }
+ else
+ {
+ // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
+ std::string corrected_name (type_and_or_name.GetName().GetCString());
+ if (static_type_flags.AllSet(eTypeIsPointer))
+ corrected_name.append(" *");
+ // the parent type should be a correctly pointer'ed or referenc'ed type
+ ret.SetCompilerType(static_type);
+ ret.SetName(corrected_name.c_str());
+ }
+ return ret;
+}
+
+bool
+AppleObjCRuntime::AppleIsModuleObjCLibrary (const ModuleSP &module_sp)
+{
+ if (module_sp)
+ {
+ const FileSpec &module_file_spec = module_sp->GetFileSpec();
+ static ConstString ObjCName ("libobjc.A.dylib");
+
+ if (module_file_spec)
+ {
+ if (module_file_spec.GetFilename() == ObjCName)
+ return true;
+ }
+ }
+ return false;
+}
+
+// we use the version of Foundation to make assumptions about the ObjC runtime on a target
+uint32_t
+AppleObjCRuntime::GetFoundationVersion ()
+{
+ if (!m_Foundation_major.hasValue())
+ {
+ const ModuleList& modules = m_process->GetTarget().GetImages();
+ uint32_t major = UINT32_MAX;
+ for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
+ {
+ lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
+ if (!module_sp)
+ continue;
+ if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),"Foundation") == 0)
+ {
+ module_sp->GetVersion(&major,1);
+ m_Foundation_major = major;
+ return major;
+ }
+ }
+ return LLDB_INVALID_MODULE_VERSION;
+ }
+ else
+ return m_Foundation_major.getValue();
+}
+
+bool
+AppleObjCRuntime::IsModuleObjCLibrary (const ModuleSP &module_sp)
+{
+ return AppleIsModuleObjCLibrary(module_sp);
+}
+
+bool
+AppleObjCRuntime::ReadObjCLibrary (const ModuleSP &module_sp)
+{
+ // Maybe check here and if we have a handler already, and the UUID of this module is the same as the one in the
+ // current module, then we don't have to reread it?
+ m_objc_trampoline_handler_ap.reset(new AppleObjCTrampolineHandler (m_process->shared_from_this(), module_sp));
+ if (m_objc_trampoline_handler_ap.get() != NULL)
+ {
+ m_read_objc_library = true;
+ return true;
+ }
+ else
+ return false;
+}
+
+ThreadPlanSP
+AppleObjCRuntime::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
+{
+ ThreadPlanSP thread_plan_sp;
+ if (m_objc_trampoline_handler_ap.get())
+ thread_plan_sp = m_objc_trampoline_handler_ap->GetStepThroughDispatchPlan (thread, stop_others);
+ return thread_plan_sp;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ObjCLanguageRuntime::ObjCRuntimeVersions
+AppleObjCRuntime::GetObjCVersion (Process *process, ModuleSP &objc_module_sp)
+{
+ if (!process)
+ return ObjCRuntimeVersions::eObjC_VersionUnknown;
+
+ Target &target = process->GetTarget();
+ if (target.GetArchitecture().GetTriple().getVendor() != llvm::Triple::VendorType::Apple)
+ return ObjCRuntimeVersions::eObjC_VersionUnknown;
+
+ const ModuleList &target_modules = target.GetImages();
+ Mutex::Locker modules_locker(target_modules.GetMutex());
+
+ size_t num_images = target_modules.GetSize();
+ for (size_t i = 0; i < num_images; i++)
+ {
+ ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked(i);
+ // One tricky bit here is that we might get called as part of the initial module loading, but
+ // before all the pre-run libraries get winnowed from the module list. So there might actually
+ // be an old and incorrect ObjC library sitting around in the list, and we don't want to look at that.
+ // That's why we call IsLoadedInTarget.
+
+ if (AppleIsModuleObjCLibrary (module_sp) && module_sp->IsLoadedInTarget(&target))
+ {
+ objc_module_sp = module_sp;
+ ObjectFile *ofile = module_sp->GetObjectFile();
+ if (!ofile)
+ return ObjCRuntimeVersions::eObjC_VersionUnknown;
+
+ SectionList *sections = module_sp->GetSectionList();
+ if (!sections)
+ return ObjCRuntimeVersions::eObjC_VersionUnknown;
+ SectionSP v1_telltale_section_sp = sections->FindSectionByName(ConstString ("__OBJC"));
+ if (v1_telltale_section_sp)
+ {
+ return ObjCRuntimeVersions::eAppleObjC_V1;
+ }
+ return ObjCRuntimeVersions::eAppleObjC_V2;
+ }
+ }
+
+ return ObjCRuntimeVersions::eObjC_VersionUnknown;
+}
+
+void
+AppleObjCRuntime::SetExceptionBreakpoints ()
+{
+ const bool catch_bp = false;
+ const bool throw_bp = true;
+ const bool is_internal = true;
+
+ if (!m_objc_exception_bp_sp)
+ {
+ m_objc_exception_bp_sp = LanguageRuntime::CreateExceptionBreakpoint (m_process->GetTarget(),
+ GetLanguageType(),
+ catch_bp,
+ throw_bp,
+ is_internal);
+ if (m_objc_exception_bp_sp)
+ m_objc_exception_bp_sp->SetBreakpointKind("ObjC exception");
+ }
+ else
+ m_objc_exception_bp_sp->SetEnabled(true);
+}
+
+
+void
+AppleObjCRuntime::ClearExceptionBreakpoints ()
+{
+ if (!m_process)
+ return;
+
+ if (m_objc_exception_bp_sp.get())
+ {
+ m_objc_exception_bp_sp->SetEnabled (false);
+ }
+}
+
+bool
+AppleObjCRuntime::ExceptionBreakpointsAreSet ()
+{
+ return m_objc_exception_bp_sp && m_objc_exception_bp_sp->IsEnabled();
+}
+
+bool
+AppleObjCRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
+{
+ if (!m_process)
+ return false;
+
+ if (!stop_reason ||
+ stop_reason->GetStopReason() != eStopReasonBreakpoint)
+ return false;
+
+ uint64_t break_site_id = stop_reason->GetValue();
+ return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint (break_site_id,
+ m_objc_exception_bp_sp->GetID());
+}
+
+bool
+AppleObjCRuntime::CalculateHasNewLiteralsAndIndexing()
+{
+ if (!m_process)
+ return false;
+
+ Target &target(m_process->GetTarget());
+
+ static ConstString s_method_signature("-[NSDictionary objectForKeyedSubscript:]");
+ static ConstString s_arclite_method_signature("__arclite_objectForKeyedSubscript");
+
+ SymbolContextList sc_list;
+
+ if (target.GetImages().FindSymbolsWithNameAndType(s_method_signature, eSymbolTypeCode, sc_list) ||
+ target.GetImages().FindSymbolsWithNameAndType(s_arclite_method_signature, eSymbolTypeCode, sc_list))
+ return true;
+ else
+ return false;
+}
+
+lldb::SearchFilterSP
+AppleObjCRuntime::CreateExceptionSearchFilter ()
+{
+ Target &target = m_process->GetTarget();
+
+ if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple)
+ {
+ FileSpecList filter_modules;
+ filter_modules.Append(FileSpec("libobjc.A.dylib", false));
+ return target.GetSearchFilterForModuleList(&filter_modules);
+ }
+ else
+ {
+ return LanguageRuntime::CreateExceptionSearchFilter();
+ }
+}
+
+void
+AppleObjCRuntime::ReadObjCLibraryIfNeeded (const ModuleList &module_list)
+{
+ if (!HasReadObjCLibrary ())
+ {
+ Mutex::Locker locker (module_list.GetMutex ());
+
+ size_t num_modules = module_list.GetSize();
+ for (size_t i = 0; i < num_modules; i++)
+ {
+ auto mod = module_list.GetModuleAtIndex (i);
+ if (IsModuleObjCLibrary (mod))
+ {
+ ReadObjCLibrary (mod);
+ break;
+ }
+ }
+ }
+}
+
+void
+AppleObjCRuntime::ModulesDidLoad (const ModuleList &module_list)
+{
+ ReadObjCLibraryIfNeeded (module_list);
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
new file mode 100644
index 0000000..342824e
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
@@ -0,0 +1,148 @@
+//===-- AppleObjCRuntime.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AppleObjCRuntime_h_
+#define liblldb_AppleObjCRuntime_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/ADT/Optional.h"
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "AppleObjCTrampolineHandler.h"
+#include "AppleThreadPlanStepThroughObjCTrampoline.h"
+
+namespace lldb_private {
+
+class AppleObjCRuntime :
+ public lldb_private::ObjCLanguageRuntime
+{
+public:
+ ~AppleObjCRuntime() override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ // Note there is no CreateInstance, Initialize & Terminate functions here, because
+ // you can't make an instance of this generic runtime.
+
+ static bool classof(const ObjCLanguageRuntime* runtime)
+ {
+ switch (runtime->GetRuntimeVersion())
+ {
+ case ObjCRuntimeVersions::eAppleObjC_V1:
+ case ObjCRuntimeVersions::eAppleObjC_V2:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // These are generic runtime functions:
+ bool
+ GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope) override;
+
+ bool
+ GetObjectDescription (Stream &str, ValueObject &object) override;
+
+ bool
+ CouldHaveDynamicValue (ValueObject &in_value) override;
+
+ bool
+ GetDynamicTypeAndAddress (ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
+
+ TypeAndOrName
+ FixUpDynamicType (const TypeAndOrName& type_and_or_name,
+ ValueObject& static_value) override;
+
+ // These are the ObjC specific functions.
+
+ bool
+ IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) override;
+
+ bool
+ ReadObjCLibrary (const lldb::ModuleSP &module_sp) override;
+
+ bool
+ HasReadObjCLibrary () override
+ {
+ return m_read_objc_library;
+ }
+
+ lldb::ThreadPlanSP
+ GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) override;
+
+ // Get the "libobjc.A.dylib" module from the current target if we can find
+ // it, also cache it once it is found to ensure quick lookups.
+ lldb::ModuleSP
+ GetObjCModule ();
+
+ // Sync up with the target
+
+ void
+ ModulesDidLoad (const ModuleList &module_list) override;
+
+ void
+ SetExceptionBreakpoints() override;
+
+ void
+ ClearExceptionBreakpoints() override;
+
+ bool
+ ExceptionBreakpointsAreSet() override;
+
+ bool
+ ExceptionBreakpointsExplainStop(lldb::StopInfoSP stop_reason) override;
+
+ lldb::SearchFilterSP
+ CreateExceptionSearchFilter() override;
+
+ uint32_t
+ GetFoundationVersion();
+
+protected:
+ // Call CreateInstance instead.
+ AppleObjCRuntime(Process *process);
+
+ bool
+ CalculateHasNewLiteralsAndIndexing() override;
+
+ static bool
+ AppleIsModuleObjCLibrary(const lldb::ModuleSP &module_sp);
+
+ static ObjCRuntimeVersions
+ GetObjCVersion(Process *process, lldb::ModuleSP &objc_module_sp);
+
+ void
+ ReadObjCLibraryIfNeeded(const ModuleList &module_list);
+
+ Address *
+ GetPrintForDebuggerAddr();
+
+ std::unique_ptr<Address> m_PrintForDebugger_addr;
+ bool m_read_objc_library;
+ std::unique_ptr<lldb_private::AppleObjCTrampolineHandler> m_objc_trampoline_handler_ap;
+ lldb::BreakpointSP m_objc_exception_bp_sp;
+ lldb::ModuleWP m_objc_module_wp;
+ std::unique_ptr<FunctionCaller> m_print_object_caller_up;
+
+ llvm::Optional<uint32_t> m_Foundation_major;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_AppleObjCRuntime_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
new file mode 100644
index 0000000..59b28b6
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -0,0 +1,459 @@
+//===-- AppleObjCRuntimeV1.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AppleObjCRuntimeV1.h"
+#include "AppleObjCTrampolineHandler.h"
+#include "AppleObjCDeclVendor.h"
+
+#include "clang/AST/Type.h"
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+AppleObjCRuntimeV1::AppleObjCRuntimeV1(Process *process) :
+ AppleObjCRuntime (process),
+ m_hash_signature (),
+ m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS)
+{
+}
+
+// for V1 runtime we just try to return a class name as that is the minimum level of support
+// required for the data formatters to work
+bool
+AppleObjCRuntimeV1::GetDynamicTypeAndAddress (ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type)
+{
+ class_type_or_name.Clear();
+ value_type = Value::ValueType::eValueTypeScalar;
+ if (CouldHaveDynamicValue(in_value))
+ {
+ auto class_descriptor(GetClassDescriptor(in_value));
+ if (class_descriptor && class_descriptor->IsValid() && class_descriptor->GetClassName())
+ {
+ const addr_t object_ptr = in_value.GetPointerValue();
+ address.SetRawAddress(object_ptr);
+ class_type_or_name.SetName(class_descriptor->GetClassName());
+ }
+ }
+ return class_type_or_name.IsEmpty() == false;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+lldb_private::LanguageRuntime *
+AppleObjCRuntimeV1::CreateInstance (Process *process, lldb::LanguageType language)
+{
+ // FIXME: This should be a MacOS or iOS process, and we need to look for the OBJC section to make
+ // sure we aren't using the V1 runtime.
+ if (language == eLanguageTypeObjC)
+ {
+ ModuleSP objc_module_sp;
+
+ if (AppleObjCRuntime::GetObjCVersion (process, objc_module_sp) == ObjCRuntimeVersions::eAppleObjC_V1)
+ return new AppleObjCRuntimeV1 (process);
+ else
+ return NULL;
+ }
+ else
+ return NULL;
+}
+
+
+void
+AppleObjCRuntimeV1::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Apple Objective C Language Runtime - Version 1",
+ CreateInstance);
+}
+
+void
+AppleObjCRuntimeV1::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+AppleObjCRuntimeV1::GetPluginNameStatic()
+{
+ static ConstString g_name("apple-objc-v1");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+ConstString
+AppleObjCRuntimeV1::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+AppleObjCRuntimeV1::GetPluginVersion()
+{
+ return 1;
+}
+
+BreakpointResolverSP
+AppleObjCRuntimeV1::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
+{
+ BreakpointResolverSP resolver_sp;
+
+ if (throw_bp)
+ resolver_sp.reset (new BreakpointResolverName (bkpt,
+ "objc_exception_throw",
+ eFunctionNameTypeBase,
+ eLanguageTypeUnknown,
+ Breakpoint::Exact,
+ eLazyBoolNo));
+ // FIXME: don't do catch yet.
+ return resolver_sp;
+}
+
+struct BufStruct {
+ char contents[2048];
+};
+
+UtilityFunction *
+AppleObjCRuntimeV1::CreateObjectChecker(const char *name)
+{
+ std::unique_ptr<BufStruct> buf(new BufStruct);
+
+ assert(snprintf(&buf->contents[0], sizeof(buf->contents),
+ "struct __objc_class \n"
+ "{ \n"
+ " struct __objc_class *isa; \n"
+ " struct __objc_class *super_class; \n"
+ " const char *name; \n"
+ " // rest of struct elided because unused \n"
+ "}; \n"
+ " \n"
+ "struct __objc_object \n"
+ "{ \n"
+ " struct __objc_class *isa; \n"
+ "}; \n"
+ " \n"
+ "extern \"C\" void \n"
+ "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n"
+ "{ \n"
+ " struct __objc_object *obj = (struct __objc_object*)$__lldb_arg_obj; \n"
+ " (int)strlen(obj->isa->name); \n"
+ "} \n",
+ name) < (int)sizeof(buf->contents));
+
+ Error error;
+ return GetTargetRef().GetUtilityFunctionForLanguage(buf->contents, eLanguageTypeObjC, name, error);
+}
+
+AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ValueObject &isa_pointer)
+{
+ Initialize (isa_pointer.GetValueAsUnsigned(0),
+ isa_pointer.GetProcessSP());
+}
+
+AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ObjCISA isa, lldb::ProcessSP process_sp)
+{
+ Initialize (isa, process_sp);
+}
+
+void
+AppleObjCRuntimeV1::ClassDescriptorV1::Initialize (ObjCISA isa, lldb::ProcessSP process_sp)
+{
+ if (!isa || !process_sp)
+ {
+ m_valid = false;
+ return;
+ }
+
+ m_valid = true;
+
+ Error error;
+
+ m_isa = process_sp->ReadPointerFromMemory(isa, error);
+
+ if (error.Fail())
+ {
+ m_valid = false;
+ return;
+ }
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ if (!IsPointerValid(m_isa,ptr_size))
+ {
+ m_valid = false;
+ return;
+ }
+
+ m_parent_isa = process_sp->ReadPointerFromMemory(m_isa + ptr_size,error);
+
+ if (error.Fail())
+ {
+ m_valid = false;
+ return;
+ }
+
+ if (!IsPointerValid(m_parent_isa,ptr_size,true))
+ {
+ m_valid = false;
+ return;
+ }
+
+ lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory(m_isa + 2 * ptr_size,error);
+
+ if (error.Fail())
+ {
+ m_valid = false;
+ return;
+ }
+
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+
+ size_t count = process_sp->ReadCStringFromMemory(name_ptr, (char*)buffer_sp->GetBytes(), 1024, error);
+
+ if (error.Fail())
+ {
+ m_valid = false;
+ return;
+ }
+
+ if (count)
+ m_name = ConstString((char*)buffer_sp->GetBytes());
+ else
+ m_name = ConstString();
+
+ m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(m_isa + 5 * ptr_size, ptr_size, 0, error);
+
+ if (error.Fail())
+ {
+ m_valid = false;
+ return;
+ }
+
+ m_process_wp = lldb::ProcessWP(process_sp);
+}
+
+AppleObjCRuntime::ClassDescriptorSP
+AppleObjCRuntimeV1::ClassDescriptorV1::GetSuperclass ()
+{
+ if (!m_valid)
+ return AppleObjCRuntime::ClassDescriptorSP();
+ ProcessSP process_sp = m_process_wp.lock();
+ if (!process_sp)
+ return AppleObjCRuntime::ClassDescriptorSP();
+ return ObjCLanguageRuntime::ClassDescriptorSP(new AppleObjCRuntimeV1::ClassDescriptorV1(m_parent_isa,process_sp));
+}
+
+AppleObjCRuntime::ClassDescriptorSP
+AppleObjCRuntimeV1::ClassDescriptorV1::GetMetaclass () const
+{
+ return ClassDescriptorSP();
+}
+
+bool
+AppleObjCRuntimeV1::ClassDescriptorV1::Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+ std::function <bool (const char *, const char *)> const &instance_method_func,
+ std::function <bool (const char *, const char *)> const &class_method_func,
+ std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) const
+{
+ return false;
+}
+
+lldb::addr_t
+AppleObjCRuntimeV1::GetISAHashTablePointer ()
+{
+ if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS)
+ {
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (!objc_module_sp)
+ return LLDB_INVALID_ADDRESS;
+
+ static ConstString g_objc_debug_class_hash("_objc_debug_class_hash");
+
+ const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_objc_debug_class_hash, lldb::eSymbolTypeData);
+ if (symbol && symbol->ValueIsAddress())
+ {
+ Process *process = GetProcess();
+ if (process)
+ {
+
+ lldb::addr_t objc_debug_class_hash_addr = symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
+
+ if (objc_debug_class_hash_addr != LLDB_INVALID_ADDRESS)
+ {
+ Error error;
+ lldb::addr_t objc_debug_class_hash_ptr = process->ReadPointerFromMemory(objc_debug_class_hash_addr, error);
+ if (objc_debug_class_hash_ptr != 0 &&
+ objc_debug_class_hash_ptr != LLDB_INVALID_ADDRESS)
+ {
+ m_isa_hash_table_ptr = objc_debug_class_hash_ptr;
+ }
+ }
+ }
+ }
+ }
+ return m_isa_hash_table_ptr;
+}
+
+void
+AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded()
+{
+ // TODO: implement HashTableSignature...
+ Process *process = GetProcess();
+
+ if (process)
+ {
+ // Update the process stop ID that indicates the last time we updated the
+ // map, whether it was successful or not.
+ m_isa_to_descriptor_stop_id = process->GetStopID();
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ ProcessSP process_sp = process->shared_from_this();
+
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (!objc_module_sp)
+ return;
+
+ uint32_t isa_count = 0;
+
+ lldb::addr_t hash_table_ptr = GetISAHashTablePointer ();
+ if (hash_table_ptr != LLDB_INVALID_ADDRESS)
+ {
+ // Read the NXHashTable struct:
+ //
+ // typedef struct {
+ // const NXHashTablePrototype *prototype;
+ // unsigned count;
+ // unsigned nbBuckets;
+ // void *buckets;
+ // const void *info;
+ // } NXHashTable;
+
+ Error error;
+ DataBufferHeap buffer(1024, 0);
+ if (process->ReadMemory(hash_table_ptr, buffer.GetBytes(), 20, error) == 20)
+ {
+ const uint32_t addr_size = m_process->GetAddressByteSize();
+ const ByteOrder byte_order = m_process->GetByteOrder();
+ DataExtractor data (buffer.GetBytes(), buffer.GetByteSize(), byte_order, addr_size);
+ lldb::offset_t offset = addr_size; // Skip prototype
+ const uint32_t count = data.GetU32(&offset);
+ const uint32_t num_buckets = data.GetU32(&offset);
+ const addr_t buckets_ptr = data.GetPointer(&offset);
+ if (m_hash_signature.NeedsUpdate (count, num_buckets, buckets_ptr))
+ {
+ m_hash_signature.UpdateSignature (count, num_buckets, buckets_ptr);
+
+ const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t);
+ buffer.SetByteSize(data_size);
+
+ if (process->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size, error) == data_size)
+ {
+ data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order);
+ offset = 0;
+ for (uint32_t bucket_idx = 0; bucket_idx < num_buckets; ++bucket_idx)
+ {
+ const uint32_t bucket_isa_count = data.GetU32 (&offset);
+ const lldb::addr_t bucket_data = data.GetU32 (&offset);
+
+
+ if (bucket_isa_count == 0)
+ continue;
+
+ isa_count += bucket_isa_count;
+
+ ObjCISA isa;
+ if (bucket_isa_count == 1)
+ {
+ // When we only have one entry in the bucket, the bucket data is the "isa"
+ isa = bucket_data;
+ if (isa)
+ {
+ if (!ISAIsCached(isa))
+ {
+ ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
+
+ AddClass (isa, descriptor_sp);
+ }
+ }
+ }
+ else
+ {
+ // When we have more than one entry in the bucket, the bucket data is a pointer
+ // to an array of "isa" values
+ addr_t isa_addr = bucket_data;
+ for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count; ++isa_idx, isa_addr += addr_size)
+ {
+ isa = m_process->ReadPointerFromMemory(isa_addr, error);
+
+ if (isa && isa != LLDB_INVALID_ADDRESS)
+ {
+ if (!ISAIsCached(isa))
+ {
+ ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
+
+ AddClass (isa, descriptor_sp);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ m_isa_to_descriptor_stop_id = UINT32_MAX;
+ }
+}
+
+DeclVendor *
+AppleObjCRuntimeV1::GetDeclVendor()
+{
+ if (!m_decl_vendor_ap.get())
+ m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this));
+
+ return m_decl_vendor_ap.get();
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
new file mode 100644
index 0000000..9f9fcc6
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
@@ -0,0 +1,207 @@
+//===-- AppleObjCRuntimeV1.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AppleObjCRuntimeV1_h_
+#define liblldb_AppleObjCRuntimeV1_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "AppleObjCRuntime.h"
+
+namespace lldb_private {
+
+class AppleObjCRuntimeV1 :
+ public AppleObjCRuntime
+{
+public:
+ ~AppleObjCRuntimeV1() override = default;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::LanguageRuntime *
+ CreateInstance(Process *process, lldb::LanguageType language);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static bool classof(const ObjCLanguageRuntime* runtime)
+ {
+ switch (runtime->GetRuntimeVersion())
+ {
+ case ObjCRuntimeVersions::eAppleObjC_V1:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ class ClassDescriptorV1 : public ObjCLanguageRuntime::ClassDescriptor
+ {
+ public:
+ ClassDescriptorV1 (ValueObject &isa_pointer);
+ ClassDescriptorV1 (ObjCISA isa, lldb::ProcessSP process_sp);
+
+ ~ClassDescriptorV1() override = default;
+
+ ConstString
+ GetClassName() override
+ {
+ return m_name;
+ }
+
+ ClassDescriptorSP
+ GetSuperclass() override;
+
+ ClassDescriptorSP
+ GetMetaclass() const override;
+
+ bool
+ IsValid() override
+ {
+ return m_valid;
+ }
+
+ // v1 does not support tagged pointers
+ bool
+ GetTaggedPointerInfo(uint64_t* info_bits = nullptr,
+ uint64_t* value_bits = nullptr,
+ uint64_t* payload = nullptr) override
+ {
+ return false;
+ }
+
+ uint64_t
+ GetInstanceSize() override
+ {
+ return m_instance_size;
+ }
+
+ ObjCISA
+ GetISA() override
+ {
+ return m_isa;
+ }
+
+ bool
+ Describe(std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+ std::function <bool (const char *, const char *)> const &instance_method_func,
+ std::function <bool (const char *, const char *)> const &class_method_func,
+ std::function <bool (const char *, const char *,
+ lldb::addr_t, uint64_t)> const &ivar_func) const override;
+
+ protected:
+ void
+ Initialize (ObjCISA isa, lldb::ProcessSP process_sp);
+
+ private:
+ ConstString m_name;
+ ObjCISA m_isa;
+ ObjCISA m_parent_isa;
+ bool m_valid;
+ lldb::ProcessWP m_process_wp;
+ uint64_t m_instance_size;
+ };
+
+ // These are generic runtime functions:
+ bool
+ GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
+
+ UtilityFunction *
+ CreateObjectChecker(const char *) override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+
+ ObjCRuntimeVersions
+ GetRuntimeVersion() const override
+ {
+ return ObjCRuntimeVersions::eAppleObjC_V1;
+ }
+
+ void
+ UpdateISAToDescriptorMapIfNeeded() override;
+
+ DeclVendor *
+ GetDeclVendor() override;
+
+protected:
+ lldb::BreakpointResolverSP
+ CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
+
+ class HashTableSignature
+ {
+ public:
+ HashTableSignature () :
+ m_count (0),
+ m_num_buckets (0),
+ m_buckets_ptr (LLDB_INVALID_ADDRESS)
+ {
+ }
+
+ bool
+ NeedsUpdate (uint32_t count,
+ uint32_t num_buckets,
+ lldb::addr_t buckets_ptr)
+ {
+ return m_count != count ||
+ m_num_buckets != num_buckets ||
+ m_buckets_ptr != buckets_ptr ;
+ }
+
+ void
+ UpdateSignature (uint32_t count,
+ uint32_t num_buckets,
+ lldb::addr_t buckets_ptr)
+ {
+ m_count = count;
+ m_num_buckets = num_buckets;
+ m_buckets_ptr = buckets_ptr;
+ }
+
+ protected:
+ uint32_t m_count;
+ uint32_t m_num_buckets;
+ lldb::addr_t m_buckets_ptr;
+ };
+
+ lldb::addr_t
+ GetISAHashTablePointer ();
+
+ HashTableSignature m_hash_signature;
+ lldb::addr_t m_isa_hash_table_ptr;
+ std::unique_ptr<DeclVendor> m_decl_vendor_ap;
+
+private:
+ AppleObjCRuntimeV1(Process *process);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_AppleObjCRuntimeV1_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
new file mode 100644
index 0000000..5844494
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -0,0 +1,2224 @@
+//===-- AppleObjCRuntimeV2.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <stdint.h>
+
+// C++ Includes
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
+
+// Project includes
+#include "lldb/lldb-enumerations.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Symbol/CompilerType.h"
+
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
+#include "lldb/Host/StringConvert.h"
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Platform.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "AppleObjCRuntimeV2.h"
+#include "AppleObjCClassDescriptorV2.h"
+#include "AppleObjCTypeEncodingParser.h"
+#include "AppleObjCDeclVendor.h"
+#include "AppleObjCTrampolineHandler.h"
+
+#if defined(__APPLE__)
+#include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h"
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+// 2 second timeout when running utility functions
+#define UTILITY_FUNCTION_TIMEOUT_USEC 2*1000*1000
+
+static const char *g_get_dynamic_class_info_name = "__lldb_apple_objc_v2_get_dynamic_class_info";
+// Testing using the new C++11 raw string literals. If this breaks GCC then we will
+// need to revert to the code above...
+static const char *g_get_dynamic_class_info_body = R"(
+
+extern "C"
+{
+ size_t strlen(const char *);
+ char *strncpy (char * s1, const char * s2, size_t n);
+ int printf(const char * format, ...);
+}
+//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
+#ifdef ENABLE_DEBUG_PRINTF
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+typedef struct _NXMapTable {
+ void *prototype;
+ unsigned num_classes;
+ unsigned num_buckets_minus_one;
+ void *buckets;
+} NXMapTable;
+
+#define NX_MAPNOTAKEY ((void *)(-1))
+
+typedef struct BucketInfo
+{
+ const char *name_ptr;
+ Class isa;
+} BucketInfo;
+
+struct ClassInfo
+{
+ Class isa;
+ uint32_t hash;
+} __attribute__((__packed__));
+
+uint32_t
+__lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr,
+ void *class_infos_ptr,
+ uint32_t class_infos_byte_size)
+{
+ DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr);
+ DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
+ DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
+ const NXMapTable *grc = (const NXMapTable *)gdb_objc_realized_classes_ptr;
+ if (grc)
+ {
+ const unsigned num_classes = grc->num_classes;
+ if (class_infos_ptr)
+ {
+ const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+ ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
+ BucketInfo *buckets = (BucketInfo *)grc->buckets;
+
+ uint32_t idx = 0;
+ for (unsigned i=0; i<=grc->num_buckets_minus_one; ++i)
+ {
+ if (buckets[i].name_ptr != NX_MAPNOTAKEY)
+ {
+ if (idx < max_class_infos)
+ {
+ const char *s = buckets[i].name_ptr;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ h = ((h << 5) + h) + c;
+ class_infos[idx].hash = h;
+ class_infos[idx].isa = buckets[i].isa;
+ }
+ ++idx;
+ }
+ }
+ if (idx < max_class_infos)
+ {
+ class_infos[idx].isa = NULL;
+ class_infos[idx].hash = 0;
+ }
+ }
+ return num_classes;
+ }
+ return 0;
+}
+
+)";
+
+static const char *g_get_shared_cache_class_info_name = "__lldb_apple_objc_v2_get_shared_cache_class_info";
+// Testing using the new C++11 raw string literals. If this breaks GCC then we will
+// need to revert to the code above...
+static const char *g_get_shared_cache_class_info_body = R"(
+
+extern "C"
+{
+ const char *class_getName(void *objc_class);
+ size_t strlen(const char *);
+ char *strncpy (char * s1, const char * s2, size_t n);
+ int printf(const char * format, ...);
+}
+
+// #define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
+#ifdef ENABLE_DEBUG_PRINTF
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+
+struct objc_classheader_t {
+ int32_t clsOffset;
+ int32_t hiOffset;
+};
+
+struct objc_clsopt_t {
+ uint32_t capacity;
+ uint32_t occupied;
+ uint32_t shift;
+ uint32_t mask;
+ uint32_t zero;
+ uint32_t unused;
+ uint64_t salt;
+ uint32_t scramble[256];
+ uint8_t tab[0]; // tab[mask+1]
+ // uint8_t checkbytes[capacity];
+ // int32_t offset[capacity];
+ // objc_classheader_t clsOffsets[capacity];
+ // uint32_t duplicateCount;
+ // objc_classheader_t duplicateOffsets[duplicateCount];
+};
+
+struct objc_opt_t {
+ uint32_t version;
+ int32_t selopt_offset;
+ int32_t headeropt_offset;
+ int32_t clsopt_offset;
+};
+
+struct objc_opt_v14_t {
+ uint32_t version;
+ uint32_t flags;
+ int32_t selopt_offset;
+ int32_t headeropt_offset;
+ int32_t clsopt_offset;
+};
+
+struct ClassInfo
+{
+ Class isa;
+ uint32_t hash;
+} __attribute__((__packed__));
+
+uint32_t
+__lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
+ void *class_infos_ptr,
+ uint32_t class_infos_byte_size)
+{
+ uint32_t idx = 0;
+ DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
+ DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
+ DEBUG_PRINTF ("class_infos_byte_size = %u (%" PRIu64 " class infos)\n", class_infos_byte_size, (size_t)(class_infos_byte_size/sizeof(ClassInfo)));
+ if (objc_opt_ro_ptr)
+ {
+ const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
+ const objc_opt_v14_t* objc_opt_v14 = (objc_opt_v14_t*)objc_opt_ro_ptr;
+ const bool is_v14_format = objc_opt->version >= 14;
+ if (is_v14_format)
+ {
+ DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v14->version);
+ DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v14->flags);
+ DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v14->selopt_offset);
+ DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt_v14->headeropt_offset);
+ DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt_v14->clsopt_offset);
+ }
+ else
+ {
+ DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt->version);
+ DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt->selopt_offset);
+ DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
+ DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
+ }
+ if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14)
+ {
+ const objc_clsopt_t* clsopt = NULL;
+ if (is_v14_format)
+ clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt_v14 + objc_opt_v14->clsopt_offset);
+ else
+ clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset);
+ const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+ ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
+ int32_t invalidEntryOffset = 0;
+ // this is safe to do because the version field order is invariant
+ if (objc_opt->version == 12)
+ invalidEntryOffset = 16;
+ const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
+ const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
+ const objc_classheader_t *classOffsets = (const objc_classheader_t *)(offsets + clsopt->capacity);
+ DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
+ DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
+ DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
+ for (uint32_t i=0; i<clsopt->capacity; ++i)
+ {
+ const int32_t clsOffset = classOffsets[i].clsOffset;
+ if (clsOffset & 1)
+ continue; // duplicate
+ else if (clsOffset == invalidEntryOffset)
+ continue; // invalid offset
+
+ if (class_infos && idx < max_class_infos)
+ {
+ class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
+ const char *name = class_getName (class_infos[idx].isa);
+ DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
+ // Hash the class name so we don't have to read it
+ const char *s = name;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ h = ((h << 5) + h) + c;
+ class_infos[idx].hash = h;
+ }
+ ++idx;
+ }
+
+ const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
+ const uint32_t duplicate_count = *duplicate_count_ptr;
+ const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]);
+ DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
+ DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
+ for (uint32_t i=0; i<duplicate_count; ++i)
+ {
+ const int32_t clsOffset = duplicateClassOffsets[i].clsOffset;
+ if (clsOffset & 1)
+ continue; // duplicate
+ else if (clsOffset == invalidEntryOffset)
+ continue; // invalid offset
+
+ if (class_infos && idx < max_class_infos)
+ {
+ class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
+ const char *name = class_getName (class_infos[idx].isa);
+ DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
+ // Hash the class name so we don't have to read it
+ const char *s = name;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ h = ((h << 5) + h) + c;
+ class_infos[idx].hash = h;
+ }
+ ++idx;
+ }
+ }
+ DEBUG_PRINTF ("%u class_infos\n", idx);
+ DEBUG_PRINTF ("done\n");
+ }
+ return idx;
+}
+
+
+)";
+
+static uint64_t
+ExtractRuntimeGlobalSymbol (Process* process,
+ ConstString name,
+ const ModuleSP &module_sp,
+ Error& error,
+ bool read_value = true,
+ uint8_t byte_size = 0,
+ uint64_t default_value = LLDB_INVALID_ADDRESS,
+ SymbolType sym_type = lldb::eSymbolTypeData)
+{
+ if (!process)
+ {
+ error.SetErrorString("no process");
+ return default_value;
+ }
+ if (!module_sp)
+ {
+ error.SetErrorString("no module");
+ return default_value;
+ }
+ if (!byte_size)
+ byte_size = process->GetAddressByteSize();
+ const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
+ if (symbol && symbol->ValueIsAddress())
+ {
+ lldb::addr_t symbol_load_addr = symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
+ if (symbol_load_addr != LLDB_INVALID_ADDRESS)
+ {
+ if (read_value)
+ return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size, default_value, error);
+ else
+ return symbol_load_addr;
+ }
+ else
+ {
+ error.SetErrorString("symbol address invalid");
+ return default_value;
+ }
+ }
+ else
+ {
+ error.SetErrorString("no symbol");
+ return default_value;
+ }
+}
+
+AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process,
+ const ModuleSP &objc_module_sp) :
+ AppleObjCRuntime (process),
+ m_get_class_info_code(),
+ m_get_class_info_args (LLDB_INVALID_ADDRESS),
+ m_get_class_info_args_mutex (Mutex::eMutexTypeNormal),
+ m_get_shared_cache_class_info_code(),
+ m_get_shared_cache_class_info_args (LLDB_INVALID_ADDRESS),
+ m_get_shared_cache_class_info_args_mutex (Mutex::eMutexTypeNormal),
+ m_decl_vendor_ap (),
+ m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS),
+ m_hash_signature (),
+ m_has_object_getClass (false),
+ m_loaded_objc_opt (false),
+ m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this,objc_module_sp)),
+ m_tagged_pointer_vendor_ap(TaggedPointerVendorV2::CreateInstance(*this,objc_module_sp)),
+ m_encoding_to_type_sp(),
+ m_noclasses_warning_emitted(false)
+{
+ static const ConstString g_gdb_object_getClass("gdb_object_getClass");
+ m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
+}
+
+bool
+AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
+ DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type)
+{
+ // We should never get here with a null process...
+ assert (m_process != NULL);
+
+ // The Runtime is attached to a particular process, you shouldn't pass in a value from another process.
+ // Note, however, the process might be NULL (e.g. if the value was made with SBTarget::EvaluateExpression...)
+ // in which case it is sufficient if the target's match:
+
+ Process *process = in_value.GetProcessSP().get();
+ if (process)
+ assert (process == m_process);
+ else
+ assert (in_value.GetTargetSP().get() == m_process->CalculateTarget().get());
+
+ class_type_or_name.Clear();
+ value_type = Value::ValueType::eValueTypeScalar;
+
+ // Make sure we can have a dynamic value before starting...
+ if (CouldHaveDynamicValue (in_value))
+ {
+ // First job, pull out the address at 0 offset from the object That will be the ISA pointer.
+ ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor (in_value));
+ if (objc_class_sp)
+ {
+ const addr_t object_ptr = in_value.GetPointerValue();
+ address.SetRawAddress(object_ptr);
+
+ ConstString class_name (objc_class_sp->GetClassName());
+ class_type_or_name.SetName(class_name);
+ TypeSP type_sp (objc_class_sp->GetType());
+ if (type_sp)
+ class_type_or_name.SetTypeSP (type_sp);
+ else
+ {
+ type_sp = LookupInCompleteClassCache (class_name);
+ if (type_sp)
+ {
+ objc_class_sp->SetType (type_sp);
+ class_type_or_name.SetTypeSP (type_sp);
+ }
+ else
+ {
+ // try to go for a CompilerType at least
+ DeclVendor* vendor = GetDeclVendor();
+ if (vendor)
+ {
+ std::vector<clang::NamedDecl*> decls;
+ if (vendor->FindDecls(class_name, false, 1, decls) && decls.size())
+ class_type_or_name.SetCompilerType(ClangASTContext::GetTypeForDecl(decls[0]));
+ }
+ }
+ }
+ }
+ }
+ return class_type_or_name.IsEmpty() == false;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+LanguageRuntime *
+AppleObjCRuntimeV2::CreateInstance (Process *process, LanguageType language)
+{
+ // FIXME: This should be a MacOS or iOS process, and we need to look for the OBJC section to make
+ // sure we aren't using the V1 runtime.
+ if (language == eLanguageTypeObjC)
+ {
+ ModuleSP objc_module_sp;
+
+ if (AppleObjCRuntime::GetObjCVersion (process, objc_module_sp) == ObjCRuntimeVersions::eAppleObjC_V2)
+ return new AppleObjCRuntimeV2 (process, objc_module_sp);
+ else
+ return NULL;
+ }
+ else
+ return NULL;
+}
+
+class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed
+{
+public:
+ CommandObjectObjC_ClassTable_Dump (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "dump",
+ "Dump information on Objective-C classes known to the current process.",
+ "language objc class-table dump",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused )
+ {
+ }
+
+ ~CommandObjectObjC_ClassTable_Dump() override = default;
+
+protected:
+ bool
+ DoExecute(Args& command, CommandReturnObject &result) override
+ {
+ Process *process = m_exe_ctx.GetProcessPtr();
+ ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
+ if (objc_runtime)
+ {
+ auto iterators_pair = objc_runtime->GetDescriptorIteratorPair();
+ auto iterator = iterators_pair.first;
+ for(; iterator != iterators_pair.second; iterator++)
+ {
+ result.GetOutputStream().Printf("isa = 0x%" PRIx64, iterator->first);
+ if (iterator->second)
+ {
+ result.GetOutputStream().Printf(" name = %s", iterator->second->GetClassName().AsCString("<unknown>"));
+ result.GetOutputStream().Printf(" instance size = %" PRIu64, iterator->second->GetInstanceSize());
+ result.GetOutputStream().Printf(" num ivars = %" PRIuPTR, (uintptr_t)iterator->second->GetNumIVars());
+ if (auto superclass = iterator->second->GetSuperclass())
+ {
+ result.GetOutputStream().Printf(" superclass = %s", superclass->GetClassName().AsCString("<unknown>"));
+ }
+ result.GetOutputStream().Printf("\n");
+ }
+ else
+ {
+ result.GetOutputStream().Printf(" has no associated class.\n");
+ }
+ }
+ result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ else
+ {
+ result.AppendError("current process has no Objective-C runtime loaded");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
+ }
+ }
+};
+
+class CommandObjectMultiwordObjC_TaggedPointer_Info : public CommandObjectParsed
+{
+public:
+ CommandObjectMultiwordObjC_TaggedPointer_Info (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "info",
+ "Dump information on a tagged pointer.",
+ "language objc tagged-pointer info",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused )
+ {
+ CommandArgumentEntry arg;
+ CommandArgumentData index_arg;
+
+ // Define the first (and only) variant of this arg.
+ index_arg.arg_type = eArgTypeAddress;
+ index_arg.arg_repetition = eArgRepeatPlus;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg.push_back (index_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg);
+ }
+
+ ~CommandObjectMultiwordObjC_TaggedPointer_Info() override = default;
+
+protected:
+ bool
+ DoExecute(Args& command, CommandReturnObject &result) override
+ {
+ if (command.GetArgumentCount() == 0)
+ {
+ result.AppendError("this command requires arguments");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
+ }
+
+ Process *process = m_exe_ctx.GetProcessPtr();
+ ExecutionContext exe_ctx(process);
+ ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
+ if (objc_runtime)
+ {
+ ObjCLanguageRuntime::TaggedPointerVendor *tagged_ptr_vendor = objc_runtime->GetTaggedPointerVendor();
+ if (tagged_ptr_vendor)
+ {
+ for (size_t i = 0;
+ i < command.GetArgumentCount();
+ i++)
+ {
+ const char *arg_str = command.GetArgumentAtIndex(i);
+ if (!arg_str)
+ continue;
+ Error error;
+ lldb::addr_t arg_addr = Args::StringToAddress(&exe_ctx, arg_str, LLDB_INVALID_ADDRESS, &error);
+ if (arg_addr == 0 || arg_addr == LLDB_INVALID_ADDRESS || error.Fail())
+ continue;
+ auto descriptor_sp = tagged_ptr_vendor->GetClassDescriptor(arg_addr);
+ if (!descriptor_sp)
+ continue;
+ uint64_t info_bits = 0;
+ uint64_t value_bits = 0;
+ uint64_t payload = 0;
+ if (descriptor_sp->GetTaggedPointerInfo(&info_bits, &value_bits, &payload))
+ {
+ result.GetOutputStream().Printf("0x%" PRIx64 " is tagged.\n\tpayload = 0x%" PRIx64 "\n\tvalue = 0x%" PRIx64 "\n\tinfo bits = 0x%" PRIx64 "\n\tclass = %s\n",
+ (uint64_t)arg_addr,
+ payload,
+ value_bits,
+ info_bits,
+ descriptor_sp->GetClassName().AsCString("<unknown>"));
+ }
+ else
+ {
+ result.GetOutputStream().Printf("0x%" PRIx64 " is not tagged.\n", (uint64_t)arg_addr);
+ }
+ }
+ }
+ else
+ {
+ result.AppendError("current process has no tagged pointer support");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
+ }
+ result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ else
+ {
+ result.AppendError("current process has no Objective-C runtime loaded");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
+ }
+ }
+};
+
+class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword
+{
+public:
+ CommandObjectMultiwordObjC_ClassTable (CommandInterpreter &interpreter) :
+ CommandObjectMultiword (interpreter,
+ "class-table",
+ "A set of commands for operating on the Objective-C class table.",
+ "class-table <subcommand> [<subcommand-options>]")
+ {
+ LoadSubCommand ("dump", CommandObjectSP (new CommandObjectObjC_ClassTable_Dump (interpreter)));
+ }
+
+ ~CommandObjectMultiwordObjC_ClassTable() override = default;
+};
+
+class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword
+{
+public:
+
+ CommandObjectMultiwordObjC_TaggedPointer (CommandInterpreter &interpreter) :
+ CommandObjectMultiword (interpreter,
+ "tagged-pointer",
+ "A set of commands for operating on Objective-C tagged pointers.",
+ "class-table <subcommand> [<subcommand-options>]")
+ {
+ LoadSubCommand ("info", CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer_Info (interpreter)));
+ }
+
+ ~CommandObjectMultiwordObjC_TaggedPointer() override = default;
+};
+
+class CommandObjectMultiwordObjC : public CommandObjectMultiword
+{
+public:
+ CommandObjectMultiwordObjC (CommandInterpreter &interpreter) :
+ CommandObjectMultiword (interpreter,
+ "objc",
+ "A set of commands for operating on the Objective-C Language Runtime.",
+ "objc <subcommand> [<subcommand-options>]")
+ {
+ LoadSubCommand ("class-table", CommandObjectSP (new CommandObjectMultiwordObjC_ClassTable (interpreter)));
+ LoadSubCommand ("tagged-pointer", CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer (interpreter)));
+ }
+
+ ~CommandObjectMultiwordObjC() override = default;
+};
+
+void
+AppleObjCRuntimeV2::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Apple Objective C Language Runtime - Version 2",
+ CreateInstance,
+ [] (CommandInterpreter& interpreter) -> lldb::CommandObjectSP {
+ return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter));
+ });
+}
+
+void
+AppleObjCRuntimeV2::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+AppleObjCRuntimeV2::GetPluginNameStatic()
+{
+ static ConstString g_name("apple-objc-v2");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+AppleObjCRuntimeV2::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+AppleObjCRuntimeV2::GetPluginVersion()
+{
+ return 1;
+}
+
+BreakpointResolverSP
+AppleObjCRuntimeV2::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
+{
+ BreakpointResolverSP resolver_sp;
+
+ if (throw_bp)
+ resolver_sp.reset (new BreakpointResolverName (bkpt,
+ "objc_exception_throw",
+ eFunctionNameTypeBase,
+ eLanguageTypeUnknown,
+ Breakpoint::Exact,
+ eLazyBoolNo));
+ // FIXME: We don't do catch breakpoints for ObjC yet.
+ // Should there be some way for the runtime to specify what it can do in this regard?
+ return resolver_sp;
+}
+
+UtilityFunction *
+AppleObjCRuntimeV2::CreateObjectChecker(const char *name)
+{
+ char check_function_code[2048];
+
+ int len = 0;
+ if (m_has_object_getClass)
+ {
+ len = ::snprintf (check_function_code,
+ sizeof(check_function_code),
+ "extern \"C\" void *gdb_object_getClass(void *); \n"
+ "extern \"C\" int printf(const char *format, ...); \n"
+ "extern \"C\" void \n"
+ "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n"
+ "{ \n"
+ " if ($__lldb_arg_obj == (void *)0) \n"
+ " return; // nil is ok \n"
+ " if (!gdb_object_getClass($__lldb_arg_obj)) \n"
+ " *((volatile int *)0) = 'ocgc'; \n"
+ " else if ($__lldb_arg_selector != (void *)0) \n"
+ " { \n"
+ " signed char responds = (signed char) [(id) $__lldb_arg_obj \n"
+ " respondsToSelector: \n"
+ " (struct objc_selector *) $__lldb_arg_selector]; \n"
+ " if (responds == (signed char) 0) \n"
+ " *((volatile int *)0) = 'ocgc'; \n"
+ " } \n"
+ "} \n",
+ name);
+ }
+ else
+ {
+ len = ::snprintf (check_function_code,
+ sizeof(check_function_code),
+ "extern \"C\" void *gdb_class_getClass(void *); \n"
+ "extern \"C\" int printf(const char *format, ...); \n"
+ "extern \"C\" void \n"
+ "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n"
+ "{ \n"
+ " if ($__lldb_arg_obj == (void *)0) \n"
+ " return; // nil is ok \n"
+ " void **$isa_ptr = (void **)$__lldb_arg_obj; \n"
+ " if (*$isa_ptr == (void *)0 || !gdb_class_getClass(*$isa_ptr)) \n"
+ " *((volatile int *)0) = 'ocgc'; \n"
+ " else if ($__lldb_arg_selector != (void *)0) \n"
+ " { \n"
+ " signed char responds = (signed char) [(id) $__lldb_arg_obj \n"
+ " respondsToSelector: \n"
+ " (struct objc_selector *) $__lldb_arg_selector]; \n"
+ " if (responds == (signed char) 0) \n"
+ " *((volatile int *)0) = 'ocgc'; \n"
+ " } \n"
+ "} \n",
+ name);
+ }
+
+ assert (len < (int)sizeof(check_function_code));
+
+ Error error;
+ return GetTargetRef().GetUtilityFunctionForLanguage(check_function_code, eLanguageTypeObjC, name, error);
+}
+
+size_t
+AppleObjCRuntimeV2::GetByteOffsetForIvar (CompilerType &parent_ast_type, const char *ivar_name)
+{
+ uint32_t ivar_offset = LLDB_INVALID_IVAR_OFFSET;
+
+ const char *class_name = parent_ast_type.GetConstTypeName().AsCString();
+ if (class_name && class_name[0] && ivar_name && ivar_name[0])
+ {
+ //----------------------------------------------------------------------
+ // Make the objective C V2 mangled name for the ivar offset from the
+ // class name and ivar name
+ //----------------------------------------------------------------------
+ std::string buffer("OBJC_IVAR_$_");
+ buffer.append (class_name);
+ buffer.push_back ('.');
+ buffer.append (ivar_name);
+ ConstString ivar_const_str (buffer.c_str());
+
+ //----------------------------------------------------------------------
+ // Try to get the ivar offset address from the symbol table first using
+ // the name we created above
+ //----------------------------------------------------------------------
+ SymbolContextList sc_list;
+ Target &target = m_process->GetTarget();
+ target.GetImages().FindSymbolsWithNameAndType(ivar_const_str, eSymbolTypeObjCIVar, sc_list);
+
+ addr_t ivar_offset_address = LLDB_INVALID_ADDRESS;
+
+ Error error;
+ SymbolContext ivar_offset_symbol;
+ if (sc_list.GetSize() == 1 && sc_list.GetContextAtIndex(0, ivar_offset_symbol))
+ {
+ if (ivar_offset_symbol.symbol)
+ ivar_offset_address = ivar_offset_symbol.symbol->GetLoadAddress (&target);
+ }
+
+ //----------------------------------------------------------------------
+ // If we didn't get the ivar offset address from the symbol table, fall
+ // back to getting it from the runtime
+ //----------------------------------------------------------------------
+ if (ivar_offset_address == LLDB_INVALID_ADDRESS)
+ ivar_offset_address = LookupRuntimeSymbol(ivar_const_str);
+
+ if (ivar_offset_address != LLDB_INVALID_ADDRESS)
+ ivar_offset = m_process->ReadUnsignedIntegerFromMemory (ivar_offset_address,
+ 4,
+ LLDB_INVALID_IVAR_OFFSET,
+ error);
+ }
+ return ivar_offset;
+}
+
+// tagged pointers are special not-a-real-pointer values that contain both type and value information
+// this routine attempts to check with as little computational effort as possible whether something
+// could possibly be a tagged pointer - false positives are possible but false negatives shouldn't
+bool
+AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr)
+{
+ if (!m_tagged_pointer_vendor_ap)
+ return false;
+ return m_tagged_pointer_vendor_ap->IsPossibleTaggedPointer(ptr);
+}
+
+class RemoteNXMapTable
+{
+public:
+ RemoteNXMapTable () :
+ m_count (0),
+ m_num_buckets_minus_one (0),
+ m_buckets_ptr (LLDB_INVALID_ADDRESS),
+ m_process (NULL),
+ m_end_iterator (*this, -1),
+ m_load_addr (LLDB_INVALID_ADDRESS),
+ m_map_pair_size (0),
+ m_invalid_key (0)
+ {
+ }
+
+ void
+ Dump ()
+ {
+ printf ("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
+ printf ("RemoteNXMapTable.m_count = %u\n", m_count);
+ printf ("RemoteNXMapTable.m_num_buckets_minus_one = %u\n", m_num_buckets_minus_one);
+ printf ("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr);
+ }
+
+ bool
+ ParseHeader (Process* process, lldb::addr_t load_addr)
+ {
+ m_process = process;
+ m_load_addr = load_addr;
+ m_map_pair_size = m_process->GetAddressByteSize() * 2;
+ m_invalid_key = m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX;
+ Error err;
+
+ // This currently holds true for all platforms we support, but we might
+ // need to change this to use get the actually byte size of "unsigned"
+ // from the target AST...
+ const uint32_t unsigned_byte_size = sizeof(uint32_t);
+ // Skip the prototype as we don't need it (const struct +NXMapTablePrototype *prototype)
+
+ bool success = true;
+ if (load_addr == LLDB_INVALID_ADDRESS)
+ success = false;
+ else
+ {
+ lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize();
+
+ // unsigned count;
+ m_count = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
+ if (m_count)
+ {
+ cursor += unsigned_byte_size;
+
+ // unsigned nbBucketsMinusOne;
+ m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
+ cursor += unsigned_byte_size;
+
+ // void *buckets;
+ m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err);
+
+ success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS;
+ }
+ }
+
+ if (!success)
+ {
+ m_count = 0;
+ m_num_buckets_minus_one = 0;
+ m_buckets_ptr = LLDB_INVALID_ADDRESS;
+ }
+ return success;
+ }
+
+ // const_iterator mimics NXMapState and its code comes from NXInitMapState and NXNextMapState.
+ typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
+
+ friend class const_iterator;
+ class const_iterator
+ {
+ public:
+ const_iterator (RemoteNXMapTable &parent, int index) : m_parent(parent), m_index(index)
+ {
+ AdvanceToValidIndex();
+ }
+
+ const_iterator (const const_iterator &rhs) : m_parent(rhs.m_parent), m_index(rhs.m_index)
+ {
+ // AdvanceToValidIndex() has been called by rhs already.
+ }
+
+ const_iterator &operator=(const const_iterator &rhs)
+ {
+ // AdvanceToValidIndex() has been called by rhs already.
+ assert (&m_parent == &rhs.m_parent);
+ m_index = rhs.m_index;
+ return *this;
+ }
+
+ bool operator==(const const_iterator &rhs) const
+ {
+ if (&m_parent != &rhs.m_parent)
+ return false;
+ if (m_index != rhs.m_index)
+ return false;
+
+ return true;
+ }
+
+ bool operator!=(const const_iterator &rhs) const
+ {
+ return !(operator==(rhs));
+ }
+
+ const_iterator &operator++()
+ {
+ AdvanceToValidIndex();
+ return *this;
+ }
+
+ const element operator*() const
+ {
+ if (m_index == -1)
+ {
+ // TODO find a way to make this an error, but not an assert
+ return element();
+ }
+
+ lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
+ size_t map_pair_size = m_parent.m_map_pair_size;
+ lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
+
+ Error err;
+
+ lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
+ if (!err.Success())
+ return element();
+ lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(pair_ptr + m_parent.m_process->GetAddressByteSize(), err);
+ if (!err.Success())
+ return element();
+
+ std::string key_string;
+
+ m_parent.m_process->ReadCStringFromMemory(key, key_string, err);
+ if (!err.Success())
+ return element();
+
+ return element(ConstString(key_string.c_str()), (ObjCLanguageRuntime::ObjCISA)value);
+ }
+
+ private:
+ void AdvanceToValidIndex ()
+ {
+ if (m_index == -1)
+ return;
+
+ const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
+ const size_t map_pair_size = m_parent.m_map_pair_size;
+ const lldb::addr_t invalid_key = m_parent.m_invalid_key;
+ Error err;
+
+ while (m_index--)
+ {
+ lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
+ lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
+
+ if (!err.Success())
+ {
+ m_index = -1;
+ return;
+ }
+
+ if (key != invalid_key)
+ return;
+ }
+ }
+ RemoteNXMapTable &m_parent;
+ int m_index;
+ };
+
+ const_iterator begin ()
+ {
+ return const_iterator(*this, m_num_buckets_minus_one + 1);
+ }
+
+ const_iterator end ()
+ {
+ return m_end_iterator;
+ }
+
+ uint32_t
+ GetCount () const
+ {
+ return m_count;
+ }
+
+ uint32_t
+ GetBucketCount () const
+ {
+ return m_num_buckets_minus_one;
+ }
+
+ lldb::addr_t
+ GetBucketDataPointer () const
+ {
+ return m_buckets_ptr;
+ }
+
+ lldb::addr_t
+ GetTableLoadAddress() const
+ {
+ return m_load_addr;
+ }
+
+private:
+ // contents of _NXMapTable struct
+ uint32_t m_count;
+ uint32_t m_num_buckets_minus_one;
+ lldb::addr_t m_buckets_ptr;
+ lldb_private::Process *m_process;
+ const_iterator m_end_iterator;
+ lldb::addr_t m_load_addr;
+ size_t m_map_pair_size;
+ lldb::addr_t m_invalid_key;
+};
+
+AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() :
+ m_count (0),
+ m_num_buckets (0),
+ m_buckets_ptr (0)
+{
+}
+
+void
+AppleObjCRuntimeV2::HashTableSignature::UpdateSignature (const RemoteNXMapTable &hash_table)
+{
+ m_count = hash_table.GetCount();
+ m_num_buckets = hash_table.GetBucketCount();
+ m_buckets_ptr = hash_table.GetBucketDataPointer();
+}
+
+bool
+AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate (Process *process, AppleObjCRuntimeV2 *runtime, RemoteNXMapTable &hash_table)
+{
+ if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer ()))
+ {
+ return false; // Failed to parse the header, no need to update anything
+ }
+
+ // Check with out current signature and return true if the count,
+ // number of buckets or the hash table address changes.
+ if (m_count == hash_table.GetCount() &&
+ m_num_buckets == hash_table.GetBucketCount() &&
+ m_buckets_ptr == hash_table.GetBucketDataPointer())
+ {
+ // Hash table hasn't changed
+ return false;
+ }
+ // Hash table data has changed, we need to update
+ return true;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::GetClassDescriptorFromISA (ObjCISA isa)
+{
+ ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
+ if (m_non_pointer_isa_cache_ap.get())
+ class_descriptor_sp = m_non_pointer_isa_cache_ap->GetClassDescriptor(isa);
+ if (!class_descriptor_sp)
+ class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
+ return class_descriptor_sp;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
+{
+ ClassDescriptorSP objc_class_sp;
+ if (valobj.IsBaseClass())
+ {
+ ValueObject *parent = valobj.GetParent();
+ // if I am my own parent, bail out of here fast..
+ if (parent && parent != &valobj)
+ {
+ ClassDescriptorSP parent_descriptor_sp = GetClassDescriptor(*parent);
+ if (parent_descriptor_sp)
+ return parent_descriptor_sp->GetSuperclass();
+ }
+ return nullptr;
+ }
+ // if we get an invalid VO (which might still happen when playing around
+ // with pointers returned by the expression parser, don't consider this
+ // a valid ObjC object)
+ if (valobj.GetCompilerType().IsValid())
+ {
+ addr_t isa_pointer = valobj.GetPointerValue();
+
+ // tagged pointer
+ if (IsTaggedPointer(isa_pointer))
+ {
+ return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer);
+ }
+ else
+ {
+ ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process)
+ {
+ Error error;
+ ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
+ if (isa != LLDB_INVALID_ADDRESS)
+ {
+ objc_class_sp = GetClassDescriptorFromISA (isa);
+ if (isa && !objc_class_sp)
+ {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was not in class descriptor cache 0x%" PRIx64,
+ isa_pointer,
+ isa);
+ }
+ }
+ }
+ }
+ }
+ return objc_class_sp;
+}
+
+lldb::addr_t
+AppleObjCRuntimeV2::GetISAHashTablePointer ()
+{
+ if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS)
+ {
+ Process *process = GetProcess();
+
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (!objc_module_sp)
+ return LLDB_INVALID_ADDRESS;
+
+ static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");
+
+ const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_objc_realized_classes, lldb::eSymbolTypeAny);
+ if (symbol)
+ {
+ lldb::addr_t gdb_objc_realized_classes_ptr = symbol->GetLoadAddress(&process->GetTarget());
+
+ if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS)
+ {
+ Error error;
+ m_isa_hash_table_ptr = process->ReadPointerFromMemory(gdb_objc_realized_classes_ptr, error);
+ }
+ }
+ }
+ return m_isa_hash_table_ptr;
+}
+
+bool
+AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table)
+{
+ Process *process = GetProcess();
+
+ if (process == NULL)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ ExecutionContext exe_ctx;
+
+ ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
+
+ if (!thread_sp)
+ return false;
+
+ thread_sp->CalculateExecutionContext(exe_ctx);
+ ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+
+ if (!ast)
+ return false;
+
+ Address function_address;
+
+ StreamString errors;
+
+ const uint32_t addr_size = process->GetAddressByteSize();
+
+ Error err;
+
+ // Read the total number of classes from the hash table
+ const uint32_t num_classes = hash_table.GetCount();
+ if (num_classes == 0)
+ {
+ if (log)
+ log->Printf ("No dynamic classes found in gdb_objc_realized_classes.");
+ return false;
+ }
+
+ // Make some types for our arguments
+ CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+ CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+
+ ValueList arguments;
+ FunctionCaller *get_class_info_function = nullptr;
+
+ if (!m_get_class_info_code.get())
+ {
+ Error error;
+ m_get_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_dynamic_class_info_body,
+ eLanguageTypeObjC,
+ g_get_dynamic_class_info_name,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("Failed to get Utility Function for implementation lookup: %s", error.AsCString());
+ m_get_class_info_code.reset();
+ }
+ else
+ {
+ errors.Clear();
+
+ if (!m_get_class_info_code->Install(errors, exe_ctx))
+ {
+ if (log)
+ log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ m_get_class_info_code.reset();
+ }
+ }
+ if (!m_get_class_info_code.get())
+ return false;
+
+ // Next make the runner function for our implementation utility function.
+ Value value;
+ value.SetValueType (Value::eValueTypeScalar);
+ value.SetCompilerType (clang_void_pointer_type);
+ arguments.PushValue (value);
+ arguments.PushValue (value);
+
+ value.SetValueType (Value::eValueTypeScalar);
+ value.SetCompilerType (clang_uint32_t_type);
+ arguments.PushValue (value);
+
+ get_class_info_function = m_get_class_info_code->MakeFunctionCaller(clang_uint32_t_type,
+ arguments,
+ error);
+
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("Failed to make function caller for implementation lookup: %s.", error.AsCString());
+ return false;
+ }
+ }
+ else
+ {
+ get_class_info_function = m_get_class_info_code->GetFunctionCaller();
+ if (!get_class_info_function)
+ {
+ if (log)
+ log->Printf ("Failed to get implementation lookup function caller: %s.", errors.GetData());
+ return false;
+ }
+ arguments = get_class_info_function->GetArgumentValues();
+ }
+
+ errors.Clear();
+
+ const uint32_t class_info_byte_size = addr_size + 4;
+ const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
+ lldb::addr_t class_infos_addr = process->AllocateMemory(class_infos_byte_size,
+ ePermissionsReadable | ePermissionsWritable,
+ err);
+
+ if (class_infos_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ Mutex::Locker locker(m_get_class_info_args_mutex);
+
+ // Fill in our function argument values
+ arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress();
+ arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
+ arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
+
+ bool success = false;
+
+ errors.Clear();
+
+ // Write our function arguments into the process so we can run our function
+ if (get_class_info_function->WriteFunctionArguments (exe_ctx,
+ m_get_class_info_args,
+ arguments,
+ errors))
+ {
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(false);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeoutUsec(UTILITY_FUNCTION_TIMEOUT_USEC);
+
+ Value return_value;
+ return_value.SetValueType (Value::eValueTypeScalar);
+ //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
+ return_value.SetCompilerType (clang_uint32_t_type);
+ return_value.GetScalar() = 0;
+
+ errors.Clear();
+
+ // Run the function
+ ExpressionResults results = get_class_info_function->ExecuteFunction (exe_ctx,
+ &m_get_class_info_args,
+ options,
+ errors,
+ return_value);
+
+ if (results == eExpressionCompleted)
+ {
+ // The result is the number of ClassInfo structures that were filled in
+ uint32_t num_class_infos = return_value.GetScalar().ULong();
+ if (log)
+ log->Printf("Discovered %u ObjC classes\n",num_class_infos);
+ if (num_class_infos > 0)
+ {
+ // Read the ClassInfo structures
+ DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
+ if (process->ReadMemory(class_infos_addr, buffer.GetBytes(), buffer.GetByteSize(), err) == buffer.GetByteSize())
+ {
+ DataExtractor class_infos_data (buffer.GetBytes(),
+ buffer.GetByteSize(),
+ process->GetByteOrder(),
+ addr_size);
+ ParseClassInfoArray (class_infos_data, num_class_infos);
+ }
+ }
+ success = true;
+ }
+ else
+ {
+ if (log)
+ log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
+ }
+
+ // Deallocate the memory we allocated for the ClassInfo array
+ process->DeallocateMemory(class_infos_addr);
+
+ return success;
+}
+
+uint32_t
+AppleObjCRuntimeV2::ParseClassInfoArray (const DataExtractor &data, uint32_t num_class_infos)
+{
+ // Parses an array of "num_class_infos" packed ClassInfo structures:
+ //
+ // struct ClassInfo
+ // {
+ // Class isa;
+ // uint32_t hash;
+ // } __attribute__((__packed__));
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ uint32_t num_parsed = 0;
+
+ // Iterate through all ClassInfo structures
+ lldb::offset_t offset = 0;
+ for (uint32_t i=0; i<num_class_infos; ++i)
+ {
+ ObjCISA isa = data.GetPointer(&offset);
+
+ if (isa == 0)
+ {
+ if (log)
+ log->Printf("AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
+ continue;
+ }
+ // Check if we already know about this ISA, if we do, the info will
+ // never change, so we can just skip it.
+ if (ISAIsCached(isa))
+ {
+ offset += 4;
+ }
+ else
+ {
+ // Read the 32 bit hash for the class name
+ const uint32_t name_hash = data.GetU32(&offset);
+ ClassDescriptorSP descriptor_sp (new ClassDescriptorV2(*this, isa, NULL));
+ AddClass (isa, descriptor_sp, name_hash);
+ num_parsed++;
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64 ", hash=0x%8.8x, name=%s", isa, name_hash,descriptor_sp->GetClassName().AsCString("<unknown>"));
+ }
+ }
+ return num_parsed;
+}
+
+AppleObjCRuntimeV2::DescriptorMapUpdateResult
+AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
+{
+ Process *process = GetProcess();
+
+ if (process == NULL)
+ return DescriptorMapUpdateResult::Fail();
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ ExecutionContext exe_ctx;
+
+ ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
+
+ if (!thread_sp)
+ return DescriptorMapUpdateResult::Fail();
+
+ thread_sp->CalculateExecutionContext(exe_ctx);
+ ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+
+ if (!ast)
+ return DescriptorMapUpdateResult::Fail();
+
+ Address function_address;
+
+ StreamString errors;
+
+ const uint32_t addr_size = process->GetAddressByteSize();
+
+ Error err;
+
+ const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();
+
+ if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
+ return DescriptorMapUpdateResult::Fail();
+
+ // Read the total number of classes from the hash table
+ const uint32_t num_classes = 128*1024;
+ if (num_classes == 0)
+ {
+ if (log)
+ log->Printf ("No dynamic classes found in gdb_objc_realized_classes_addr.");
+ return DescriptorMapUpdateResult::Fail();
+ }
+
+ // Make some types for our arguments
+ CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+ CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+
+ ValueList arguments;
+ FunctionCaller *get_shared_cache_class_info_function = nullptr;
+
+ if (!m_get_shared_cache_class_info_code.get())
+ {
+ Error error;
+ m_get_shared_cache_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_shared_cache_class_info_body,
+ eLanguageTypeObjC,
+ g_get_shared_cache_class_info_name,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("Failed to get Utility function for implementation lookup: %s.", error.AsCString());
+ m_get_shared_cache_class_info_code.reset();
+ }
+ else
+ {
+ errors.Clear();
+
+ if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx))
+ {
+ if (log)
+ log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ m_get_shared_cache_class_info_code.reset();
+ }
+ }
+
+ if (!m_get_shared_cache_class_info_code.get())
+ return DescriptorMapUpdateResult::Fail();
+
+ // Next make the function caller for our implementation utility function.
+ Value value;
+ value.SetValueType (Value::eValueTypeScalar);
+ //value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
+ value.SetCompilerType (clang_void_pointer_type);
+ arguments.PushValue (value);
+ arguments.PushValue (value);
+
+ value.SetValueType (Value::eValueTypeScalar);
+ //value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
+ value.SetCompilerType (clang_uint32_t_type);
+ arguments.PushValue (value);
+
+ get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->MakeFunctionCaller(clang_uint32_t_type,
+ arguments,
+ error);
+
+ if (get_shared_cache_class_info_function == nullptr)
+ return DescriptorMapUpdateResult::Fail();
+
+ }
+ else
+ {
+ get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->GetFunctionCaller();
+ if (get_shared_cache_class_info_function == nullptr)
+ return DescriptorMapUpdateResult::Fail();
+ arguments = get_shared_cache_class_info_function->GetArgumentValues();
+ }
+
+ errors.Clear();
+
+ const uint32_t class_info_byte_size = addr_size + 4;
+ const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
+ lldb::addr_t class_infos_addr = process->AllocateMemory (class_infos_byte_size,
+ ePermissionsReadable | ePermissionsWritable,
+ err);
+
+ if (class_infos_addr == LLDB_INVALID_ADDRESS)
+ return DescriptorMapUpdateResult::Fail();
+
+ Mutex::Locker locker(m_get_shared_cache_class_info_args_mutex);
+
+ // Fill in our function argument values
+ arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
+ arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
+ arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
+
+ bool success = false;
+ bool any_found = false;
+
+ errors.Clear();
+
+ // Write our function arguments into the process so we can run our function
+ if (get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx,
+ m_get_shared_cache_class_info_args,
+ arguments,
+ errors))
+ {
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(false);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeoutUsec(UTILITY_FUNCTION_TIMEOUT_USEC);
+
+ Value return_value;
+ return_value.SetValueType (Value::eValueTypeScalar);
+ //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
+ return_value.SetCompilerType (clang_uint32_t_type);
+ return_value.GetScalar() = 0;
+
+ errors.Clear();
+
+ // Run the function
+ ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction (exe_ctx,
+ &m_get_shared_cache_class_info_args,
+ options,
+ errors,
+ return_value);
+
+ if (results == eExpressionCompleted)
+ {
+ // The result is the number of ClassInfo structures that were filled in
+ uint32_t num_class_infos = return_value.GetScalar().ULong();
+ if (log)
+ log->Printf("Discovered %u ObjC classes in shared cache\n",num_class_infos);
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert (num_class_infos <= num_classes);
+#endif
+ if (num_class_infos > 0)
+ {
+ if (num_class_infos > num_classes)
+ {
+ num_class_infos = num_classes;
+
+ success = false;
+ }
+ else
+ {
+ success = true;
+ }
+
+ // Read the ClassInfo structures
+ DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
+ if (process->ReadMemory(class_infos_addr,
+ buffer.GetBytes(),
+ buffer.GetByteSize(),
+ err) == buffer.GetByteSize())
+ {
+ DataExtractor class_infos_data (buffer.GetBytes(),
+ buffer.GetByteSize(),
+ process->GetByteOrder(),
+ addr_size);
+
+ any_found = (ParseClassInfoArray (class_infos_data, num_class_infos) > 0);
+ }
+ }
+ else
+ {
+ success = true;
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
+ }
+
+ // Deallocate the memory we allocated for the ClassInfo array
+ process->DeallocateMemory(class_infos_addr);
+
+ return DescriptorMapUpdateResult(success, any_found);
+}
+
+bool
+AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory (RemoteNXMapTable &hash_table)
+{
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ Process *process = GetProcess();
+
+ if (process == NULL)
+ return false;
+
+ uint32_t num_map_table_isas = 0;
+
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (objc_module_sp)
+ {
+ for (RemoteNXMapTable::element elt : hash_table)
+ {
+ ++num_map_table_isas;
+
+ if (ISAIsCached(elt.second))
+ continue;
+
+ ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, elt.second, elt.first.AsCString()));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 " (%s) from dynamic table to isa->descriptor cache", elt.second, elt.first.AsCString());
+
+ AddClass (elt.second, descriptor_sp, elt.first.AsCString());
+ }
+ }
+
+ return num_map_table_isas > 0;
+}
+
+lldb::addr_t
+AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress()
+{
+ Process *process = GetProcess();
+
+ if (process)
+ {
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (objc_module_sp)
+ {
+ ObjectFile *objc_object = objc_module_sp->GetObjectFile();
+
+ if (objc_object)
+ {
+ SectionList *section_list = objc_module_sp->GetSectionList();
+
+ if (section_list)
+ {
+ SectionSP text_segment_sp (section_list->FindSectionByName(ConstString("__TEXT")));
+
+ if (text_segment_sp)
+ {
+ SectionSP objc_opt_section_sp (text_segment_sp->GetChildren().FindSectionByName(ConstString("__objc_opt_ro")));
+
+ if (objc_opt_section_sp)
+ {
+ return objc_opt_section_sp->GetLoadBaseAddress(&process->GetTarget());
+ }
+ }
+ }
+ }
+ }
+ }
+ return LLDB_INVALID_ADDRESS;
+}
+
+void
+AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded()
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ // Else we need to check with our process to see when the map was updated.
+ Process *process = GetProcess();
+
+ if (process)
+ {
+ RemoteNXMapTable hash_table;
+
+ // Update the process stop ID that indicates the last time we updated the
+ // map, whether it was successful or not.
+ m_isa_to_descriptor_stop_id = process->GetStopID();
+
+ if (!m_hash_signature.NeedsUpdate(process, this, hash_table))
+ return;
+
+ m_hash_signature.UpdateSignature (hash_table);
+
+ // Grab the dynamically loaded objc classes from the hash table in memory
+ UpdateISAToDescriptorMapDynamic(hash_table);
+
+ // Now get the objc classes that are baked into the Objective C runtime
+ // in the shared cache, but only once per process as this data never
+ // changes
+ if (!m_loaded_objc_opt)
+ {
+ DescriptorMapUpdateResult shared_cache_update_result = UpdateISAToDescriptorMapSharedCache();
+ if (!shared_cache_update_result.any_found)
+ WarnIfNoClassesCached ();
+ else
+ m_loaded_objc_opt = true;
+ }
+ }
+ else
+ {
+ m_isa_to_descriptor_stop_id = UINT32_MAX;
+ }
+}
+
+void
+AppleObjCRuntimeV2::WarnIfNoClassesCached ()
+{
+ if (m_noclasses_warning_emitted)
+ return;
+
+#if defined(__APPLE__)
+ if (m_process &&
+ m_process->GetTarget().GetPlatform() &&
+ m_process->GetTarget().GetPlatform()->GetPluginName() == PlatformiOSSimulator::GetPluginNameStatic())
+ {
+ // the iOS simulator does not have the objc_opt_ro class table
+ // so don't actually complain to the user
+ m_noclasses_warning_emitted = true;
+ return;
+ }
+#endif
+
+ Debugger &debugger(GetProcess()->GetTarget().GetDebugger());
+
+ if (debugger.GetAsyncOutputStream())
+ {
+ debugger.GetAsyncOutputStream()->PutCString("warning: could not load any Objective-C class information from the dyld shared cache. This will significantly reduce the quality of type information available.\n");
+ m_noclasses_warning_emitted = true;
+ }
+}
+
+// TODO: should we have a transparent_kvo parameter here to say if we
+// want to replace the KVO swizzled class with the actual user-level type?
+ConstString
+AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
+{
+ if (isa == g_objc_Tagged_ISA)
+ {
+ static const ConstString g_objc_tagged_isa_name ("_lldb_Tagged_ObjC_ISA");
+ return g_objc_tagged_isa_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSAtom)
+ {
+ static const ConstString g_objc_tagged_isa_nsatom_name ("NSAtom");
+ return g_objc_tagged_isa_nsatom_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSNumber)
+ {
+ static const ConstString g_objc_tagged_isa_nsnumber_name ("NSNumber");
+ return g_objc_tagged_isa_nsnumber_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSDateTS)
+ {
+ static const ConstString g_objc_tagged_isa_nsdatets_name ("NSDateTS");
+ return g_objc_tagged_isa_nsdatets_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSManagedObject)
+ {
+ static const ConstString g_objc_tagged_isa_nsmanagedobject_name ("NSManagedObject");
+ return g_objc_tagged_isa_nsmanagedobject_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSDate)
+ {
+ static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate");
+ return g_objc_tagged_isa_nsdate_name;
+ }
+ return ObjCLanguageRuntime::GetActualTypeName(isa);
+}
+
+DeclVendor *
+AppleObjCRuntimeV2::GetDeclVendor()
+{
+ if (!m_decl_vendor_ap.get())
+ m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this));
+
+ return m_decl_vendor_ap.get();
+}
+
+lldb::addr_t
+AppleObjCRuntimeV2::LookupRuntimeSymbol (const ConstString &name)
+{
+ lldb::addr_t ret = LLDB_INVALID_ADDRESS;
+
+ const char *name_cstr = name.AsCString();
+
+ if (name_cstr)
+ {
+ llvm::StringRef name_strref(name_cstr);
+
+ static const llvm::StringRef ivar_prefix("OBJC_IVAR_$_");
+ static const llvm::StringRef class_prefix("OBJC_CLASS_$_");
+
+ if (name_strref.startswith(ivar_prefix))
+ {
+ llvm::StringRef ivar_skipped_prefix = name_strref.substr(ivar_prefix.size());
+ std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar = ivar_skipped_prefix.split('.');
+
+ if (class_and_ivar.first.size() && class_and_ivar.second.size())
+ {
+ const ConstString class_name_cs(class_and_ivar.first);
+ ClassDescriptorSP descriptor = ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs);
+
+ if (descriptor)
+ {
+ const ConstString ivar_name_cs(class_and_ivar.second);
+ const char *ivar_name_cstr = ivar_name_cs.AsCString();
+
+ auto ivar_func = [&ret, ivar_name_cstr](const char *name, const char *type, lldb::addr_t offset_addr, uint64_t size) -> lldb::addr_t
+ {
+ if (!strcmp(name, ivar_name_cstr))
+ {
+ ret = offset_addr;
+ return true;
+ }
+ return false;
+ };
+
+ descriptor->Describe(std::function<void (ObjCISA)>(nullptr),
+ std::function<bool (const char *, const char *)>(nullptr),
+ std::function<bool (const char *, const char *)>(nullptr),
+ ivar_func);
+ }
+ }
+ }
+ else if (name_strref.startswith(class_prefix))
+ {
+ llvm::StringRef class_skipped_prefix = name_strref.substr(class_prefix.size());
+ const ConstString class_name_cs(class_skipped_prefix);
+ ClassDescriptorSP descriptor = GetClassDescriptorFromClassName(class_name_cs);
+
+ if (descriptor)
+ ret = descriptor->GetISA();
+ }
+ }
+
+ return ret;
+}
+
+AppleObjCRuntimeV2::NonPointerISACache*
+AppleObjCRuntimeV2::NonPointerISACache::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
+{
+ Process* process(runtime.GetProcess());
+
+ Error error;
+
+ auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_isa_magic_mask"),
+ objc_module_sp,
+ error);
+ if (error.Fail())
+ return NULL;
+
+ auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_isa_magic_value"),
+ objc_module_sp,
+ error);
+ if (error.Fail())
+ return NULL;
+
+ auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_isa_class_mask"),
+ objc_module_sp,
+ error);
+ if (error.Fail())
+ return NULL;
+
+ // we might want to have some rules to outlaw these other values (e.g if the mask is zero but the value is non-zero, ...)
+
+ return new NonPointerISACache(runtime,
+ objc_debug_isa_class_mask,
+ objc_debug_isa_magic_mask,
+ objc_debug_isa_magic_value);
+}
+
+AppleObjCRuntimeV2::TaggedPointerVendorV2*
+AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
+{
+ Process* process(runtime.GetProcess());
+
+ Error error;
+
+ auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_mask"),
+ objc_module_sp,
+ error);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_slot_shift"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_slot_mask"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_payload_lshift"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_payload_rshift"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_classes"),
+ objc_module_sp,
+ error,
+ false);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+
+ // we might want to have some rules to outlaw these values (e.g if the table's address is zero)
+
+ return new TaggedPointerVendorRuntimeAssisted(runtime,
+ objc_debug_taggedpointer_mask,
+ objc_debug_taggedpointer_slot_shift,
+ objc_debug_taggedpointer_slot_mask,
+ objc_debug_taggedpointer_payload_lshift,
+ objc_debug_taggedpointer_payload_rshift,
+ objc_debug_taggedpointer_classes);
+}
+
+bool
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer (lldb::addr_t ptr)
+{
+ return (ptr & 1);
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor (lldb::addr_t ptr)
+{
+ if (!IsPossibleTaggedPointer(ptr))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ uint32_t foundation_version = m_runtime.GetFoundationVersion();
+
+ if (foundation_version == LLDB_INVALID_MODULE_VERSION)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ uint64_t class_bits = (ptr & 0xE) >> 1;
+ ConstString name;
+
+ // TODO: make a table
+ if (foundation_version >= 900)
+ {
+ switch (class_bits)
+ {
+ case 0:
+ name = ConstString("NSAtom");
+ break;
+ case 3:
+ name = ConstString("NSNumber");
+ break;
+ case 4:
+ name = ConstString("NSDateTS");
+ break;
+ case 5:
+ name = ConstString("NSManagedObject");
+ break;
+ case 6:
+ name = ConstString("NSDate");
+ break;
+ default:
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ }
+ }
+ else
+ {
+ switch (class_bits)
+ {
+ case 1:
+ name = ConstString("NSNumber");
+ break;
+ case 5:
+ name = ConstString("NSManagedObject");
+ break;
+ case 6:
+ name = ConstString("NSDate");
+ break;
+ case 7:
+ name = ConstString("NSDateTS");
+ break;
+ default:
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ }
+ }
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(name,ptr));
+}
+
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_taggedpointer_mask,
+ uint32_t objc_debug_taggedpointer_slot_shift,
+ uint32_t objc_debug_taggedpointer_slot_mask,
+ uint32_t objc_debug_taggedpointer_payload_lshift,
+ uint32_t objc_debug_taggedpointer_payload_rshift,
+ lldb::addr_t objc_debug_taggedpointer_classes) :
+TaggedPointerVendorV2(runtime),
+m_cache(),
+m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
+m_objc_debug_taggedpointer_slot_shift(objc_debug_taggedpointer_slot_shift),
+m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
+m_objc_debug_taggedpointer_payload_lshift(objc_debug_taggedpointer_payload_lshift),
+m_objc_debug_taggedpointer_payload_rshift(objc_debug_taggedpointer_payload_rshift),
+m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes)
+{
+}
+
+bool
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::IsPossibleTaggedPointer (lldb::addr_t ptr)
+{
+ return (ptr & m_objc_debug_taggedpointer_mask) != 0;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb::addr_t ptr)
+{
+ ClassDescriptorSP actual_class_descriptor_sp;
+ uint64_t data_payload;
+
+ if (!IsPossibleTaggedPointer(ptr))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) & m_objc_debug_taggedpointer_slot_mask;
+
+ CacheIterator iterator = m_cache.find(slot),
+ end = m_cache.end();
+ if (iterator != end)
+ {
+ actual_class_descriptor_sp = iterator->second;
+ }
+ else
+ {
+ Process* process(m_runtime.GetProcess());
+ uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_classes;
+ Error error;
+ uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
+ if (error.Fail() || slot_data == 0 || slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
+ return nullptr;
+ actual_class_descriptor_sp = m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
+ if (!actual_class_descriptor_sp)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ m_cache[slot] = actual_class_descriptor_sp;
+ }
+
+ data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >> m_objc_debug_taggedpointer_payload_rshift);
+
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload));
+}
+
+AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_isa_class_mask,
+ uint64_t objc_debug_isa_magic_mask,
+ uint64_t objc_debug_isa_magic_value) :
+m_runtime(runtime),
+m_cache(),
+m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
+m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
+m_objc_debug_isa_magic_value(objc_debug_isa_magic_value)
+{
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor (ObjCISA isa)
+{
+ ObjCISA real_isa = 0;
+ if (EvaluateNonPointerISA(isa, real_isa) == false)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ auto cache_iter = m_cache.find(real_isa);
+ if (cache_iter != m_cache.end())
+ return cache_iter->second;
+ auto descriptor_sp = m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
+ if (descriptor_sp) // cache only positive matches since the table might grow
+ m_cache[real_isa] = descriptor_sp;
+ return descriptor_sp;
+}
+
+bool
+AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa)
+{
+ if ( (isa & ~m_objc_debug_isa_class_mask) == 0)
+ return false;
+ if ( (isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value)
+ {
+ ret_isa = isa & m_objc_debug_isa_class_mask;
+ return (ret_isa != 0); // this is a pointer so 0 is not a valid value
+ }
+ return false;
+}
+
+ObjCLanguageRuntime::EncodingToTypeSP
+AppleObjCRuntimeV2::GetEncodingToType ()
+{
+ if (!m_encoding_to_type_sp)
+ m_encoding_to_type_sp.reset(new AppleObjCTypeEncodingParser(*this));
+ return m_encoding_to_type_sp;
+}
+
+lldb_private::AppleObjCRuntime::ObjCISA
+AppleObjCRuntimeV2::GetPointerISA (ObjCISA isa)
+{
+ ObjCISA ret = isa;
+
+ if (m_non_pointer_isa_cache_ap)
+ m_non_pointer_isa_cache_ap->EvaluateNonPointerISA(isa, ret);
+
+ return ret;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
new file mode 100644
index 0000000..96b47e8
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -0,0 +1,336 @@
+//===-- AppleObjCRuntimeV2.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AppleObjCRuntimeV2_h_
+#define liblldb_AppleObjCRuntimeV2_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <memory>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "AppleObjCRuntime.h"
+
+class RemoteNXMapTable;
+
+namespace lldb_private {
+
+class AppleObjCRuntimeV2 :
+ public AppleObjCRuntime
+{
+public:
+ ~AppleObjCRuntimeV2() override = default;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::LanguageRuntime *
+ CreateInstance (Process *process, lldb::LanguageType language);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static bool classof(const ObjCLanguageRuntime* runtime)
+ {
+ switch (runtime->GetRuntimeVersion())
+ {
+ case ObjCRuntimeVersions::eAppleObjC_V2:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // These are generic runtime functions:
+ bool
+ GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
+
+ UtilityFunction *
+ CreateObjectChecker(const char *) override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+
+ ObjCRuntimeVersions
+ GetRuntimeVersion() const override
+ {
+ return ObjCRuntimeVersions::eAppleObjC_V2;
+ }
+
+ size_t
+ GetByteOffsetForIvar(CompilerType &parent_qual_type, const char *ivar_name) override;
+
+ void
+ UpdateISAToDescriptorMapIfNeeded() override;
+
+ ConstString
+ GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) override;
+
+ ClassDescriptorSP
+ GetClassDescriptor(ValueObject& in_value) override;
+
+ ClassDescriptorSP
+ GetClassDescriptorFromISA(ObjCISA isa) override;
+
+ DeclVendor *
+ GetDeclVendor() override;
+
+ lldb::addr_t
+ LookupRuntimeSymbol(const ConstString &name) override;
+
+ EncodingToTypeSP
+ GetEncodingToType() override;
+
+ TaggedPointerVendor*
+ GetTaggedPointerVendor() override
+ {
+ return m_tagged_pointer_vendor_ap.get();
+ }
+
+ // none of these are valid ISAs - we use them to infer the type
+ // of tagged pointers - if we have something meaningful to say
+ // we report an actual type - otherwise, we just say tagged
+ // there is no connection between the values here and the tagged pointers map
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA = 1;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSAtom = 2;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSNumber = 3;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDateTS = 4;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSManagedObject = 5;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDate = 6;
+
+protected:
+ lldb::BreakpointResolverSP
+ CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
+
+private:
+ class HashTableSignature
+ {
+ public:
+ HashTableSignature ();
+
+ bool
+ NeedsUpdate (Process *process,
+ AppleObjCRuntimeV2 *runtime,
+ RemoteNXMapTable &hash_table);
+
+ void
+ UpdateSignature (const RemoteNXMapTable &hash_table);
+
+ protected:
+ uint32_t m_count;
+ uint32_t m_num_buckets;
+ lldb::addr_t m_buckets_ptr;
+ };
+
+ class NonPointerISACache
+ {
+ public:
+ static NonPointerISACache*
+ CreateInstance (AppleObjCRuntimeV2& runtime,
+ const lldb::ModuleSP& objc_module_sp);
+
+
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor (ObjCISA isa);
+
+ private:
+ NonPointerISACache (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_isa_class_mask,
+ uint64_t objc_debug_isa_magic_mask,
+ uint64_t objc_debug_isa_magic_value);
+
+ bool
+ EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa);
+
+ AppleObjCRuntimeV2& m_runtime;
+ std::map<ObjCISA,ObjCLanguageRuntime::ClassDescriptorSP> m_cache;
+ uint64_t m_objc_debug_isa_class_mask;
+ uint64_t m_objc_debug_isa_magic_mask;
+ uint64_t m_objc_debug_isa_magic_value;
+
+ friend class AppleObjCRuntimeV2;
+
+ DISALLOW_COPY_AND_ASSIGN(NonPointerISACache);
+ };
+
+ class TaggedPointerVendorV2 : public ObjCLanguageRuntime::TaggedPointerVendor
+ {
+ public:
+ ~TaggedPointerVendorV2() override = default;
+
+ static TaggedPointerVendorV2*
+ CreateInstance (AppleObjCRuntimeV2& runtime,
+ const lldb::ModuleSP& objc_module_sp);
+
+ protected:
+ AppleObjCRuntimeV2& m_runtime;
+
+ TaggedPointerVendorV2 (AppleObjCRuntimeV2& runtime) :
+ TaggedPointerVendor(),
+ m_runtime(runtime)
+ {
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorV2);
+ };
+
+ class TaggedPointerVendorRuntimeAssisted : public TaggedPointerVendorV2
+ {
+ public:
+ bool
+ IsPossibleTaggedPointer(lldb::addr_t ptr) override;
+
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor(lldb::addr_t ptr) override;
+
+ protected:
+ TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_taggedpointer_mask,
+ uint32_t objc_debug_taggedpointer_slot_shift,
+ uint32_t objc_debug_taggedpointer_slot_mask,
+ uint32_t objc_debug_taggedpointer_payload_lshift,
+ uint32_t objc_debug_taggedpointer_payload_rshift,
+ lldb::addr_t objc_debug_taggedpointer_classes);
+
+ typedef std::map<uint8_t,ObjCLanguageRuntime::ClassDescriptorSP> Cache;
+ typedef Cache::iterator CacheIterator;
+ Cache m_cache;
+ uint64_t m_objc_debug_taggedpointer_mask;
+ uint32_t m_objc_debug_taggedpointer_slot_shift;
+ uint32_t m_objc_debug_taggedpointer_slot_mask;
+ uint32_t m_objc_debug_taggedpointer_payload_lshift;
+ uint32_t m_objc_debug_taggedpointer_payload_rshift;
+ lldb::addr_t m_objc_debug_taggedpointer_classes;
+
+ friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
+
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorRuntimeAssisted);
+ };
+
+ class TaggedPointerVendorLegacy : public TaggedPointerVendorV2
+ {
+ public:
+ bool
+ IsPossibleTaggedPointer(lldb::addr_t ptr) override;
+
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor (lldb::addr_t ptr) override;
+
+ protected:
+ TaggedPointerVendorLegacy (AppleObjCRuntimeV2& runtime) :
+ TaggedPointerVendorV2 (runtime)
+ {
+ }
+
+ friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
+
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorLegacy);
+ };
+
+ struct DescriptorMapUpdateResult
+ {
+ bool update_ran;
+ bool any_found;
+
+ DescriptorMapUpdateResult (bool ran,
+ bool found)
+ {
+ update_ran = ran;
+ any_found = found;
+ }
+
+ static DescriptorMapUpdateResult
+ Fail ()
+ {
+ return {false, false};
+ }
+
+ static DescriptorMapUpdateResult
+ Success ()
+ {
+ return {true, true};
+ }
+ };
+
+ AppleObjCRuntimeV2 (Process *process,
+ const lldb::ModuleSP &objc_module_sp);
+
+ ObjCISA
+ GetPointerISA (ObjCISA isa);
+
+ bool
+ IsTaggedPointer(lldb::addr_t ptr);
+
+ lldb::addr_t
+ GetISAHashTablePointer ();
+
+ bool
+ UpdateISAToDescriptorMapFromMemory (RemoteNXMapTable &hash_table);
+
+ bool
+ UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table);
+
+ uint32_t
+ ParseClassInfoArray (const lldb_private::DataExtractor &data,
+ uint32_t num_class_infos);
+
+ DescriptorMapUpdateResult
+ UpdateISAToDescriptorMapSharedCache ();
+
+ void
+ WarnIfNoClassesCached ();
+
+ lldb::addr_t
+ GetSharedCacheReadOnlyAddress();
+
+ friend class ClassDescriptorV2;
+
+ std::unique_ptr<UtilityFunction> m_get_class_info_code;
+ lldb::addr_t m_get_class_info_args;
+ Mutex m_get_class_info_args_mutex;
+
+ std::unique_ptr<UtilityFunction> m_get_shared_cache_class_info_code;
+ lldb::addr_t m_get_shared_cache_class_info_args;
+ Mutex m_get_shared_cache_class_info_args_mutex;
+
+ std::unique_ptr<DeclVendor> m_decl_vendor_ap;
+ lldb::addr_t m_isa_hash_table_ptr;
+ HashTableSignature m_hash_signature;
+ bool m_has_object_getClass;
+ bool m_loaded_objc_opt;
+ std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_ap;
+ std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_ap;
+ EncodingToTypeSP m_encoding_to_type_sp;
+ bool m_noclasses_warning_emitted;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_AppleObjCRuntimeV2_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
new file mode 100644
index 0000000..d38a076
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -0,0 +1,1144 @@
+//===-- AppleObjCTrampolineHandler.cpp ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AppleObjCTrampolineHandler.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "AppleThreadPlanStepThroughObjCTrampoline.h"
+
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Expression/UserExpression.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+
+#include "llvm/ADT/STLExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name = "__lldb_objc_find_implementation_for_selector";
+const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_code = NULL;
+const char *AppleObjCTrampolineHandler::g_lookup_implementation_with_stret_function_code = " \n\
+extern \"C\" \n\
+{ \n\
+ extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
+ extern void *class_getMethodImplementation_stret(void *objc_class, void *sel); \n\
+ extern void * object_getClass (id object); \n\
+ extern void * sel_getUid(char *name); \n\
+ extern int printf(const char *format, ...); \n\
+} \n\
+extern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object, \n\
+ void *sel, \n\
+ int is_stret, \n\
+ int is_super, \n\
+ int is_super2, \n\
+ int is_fixup, \n\
+ int is_fixed, \n\
+ int debug) \n\
+{ \n\
+ struct __lldb_imp_return_struct \n\
+ { \n\
+ void *class_addr; \n\
+ void *sel_addr; \n\
+ void *impl_addr; \n\
+ }; \n\
+ \n\
+ struct __lldb_objc_class { \n\
+ void *isa; \n\
+ void *super_ptr; \n\
+ }; \n\
+ struct __lldb_objc_super { \n\
+ void *reciever; \n\
+ struct __lldb_objc_class *class_ptr; \n\
+ }; \n\
+ struct __lldb_msg_ref { \n\
+ void *dont_know; \n\
+ void *sel; \n\
+ }; \n\
+ \n\
+ struct __lldb_imp_return_struct return_struct; \n\
+ \n\
+ if (debug) \n\
+ printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \" \n\
+ \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\
+ object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed); \n\
+ if (is_super) \n\
+ { \n\
+ if (is_super2) \n\
+ { \n\
+ return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr; \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr; \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ // This code seems a little funny, but has its reasons... \n\
+ // The call to [object class] is here because if this is a class, and has not been called into \n\
+ // yet, we need to do something to force the class to initialize itself. \n\
+ // Then the call to object_getClass will actually return the correct class, either the class \n\
+ // if object is a class instance, or the meta-class if it is a class pointer. \n\
+ void *class_ptr = (void *) [(id) object class]; \n\
+ return_struct.class_addr = (id) object_getClass((id) object); \n\
+ if (debug) \n\
+ { \n\
+ if (class_ptr == object) \n\
+ { \n\
+ printf (\"Found a class object, need to use the meta class %p -> %p\\n\", \n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ else \n\
+ { \n\
+ printf (\"[object class] returned: %p object_getClass: %p.\\n\", \n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ } \n\
+ } \n\
+ \n\
+ if (is_fixup) \n\
+ { \n\
+ if (is_fixed) \n\
+ { \n\
+ return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\
+ } \n\
+ else \n\
+ { \n\
+ char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\
+ return_struct.sel_addr = sel_getUid (sel_name); \n\
+ if (debug) \n\
+ printf (\"\\n*** Got fixed up selector: %p for name %s.\\n\", \n\
+ return_struct.sel_addr, sel_name); \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.sel_addr = sel; \n\
+ } \n\
+ \n\
+ if (is_stret) \n\
+ { \n\
+ return_struct.impl_addr = class_getMethodImplementation_stret (return_struct.class_addr, \n\
+ return_struct.sel_addr); \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr, \n\
+ return_struct.sel_addr); \n\
+ } \n\
+ if (debug) \n\
+ printf (\"\\n*** Returning implementation: %p.\\n\", return_struct.impl_addr); \n\
+ \n\
+ return return_struct.impl_addr; \n\
+} \n\
+";
+const char *AppleObjCTrampolineHandler::g_lookup_implementation_no_stret_function_code = " \n\
+extern \"C\" \n\
+{ \n\
+ extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
+ extern void * object_getClass (id object); \n\
+ extern void * sel_getUid(char *name); \n\
+ extern int printf(const char *format, ...); \n\
+} \n\
+extern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object, \n\
+ void *sel, \n\
+ int is_stret, \n\
+ int is_super, \n\
+ int is_super2, \n\
+ int is_fixup, \n\
+ int is_fixed, \n\
+ int debug) \n\
+{ \n\
+ struct __lldb_imp_return_struct \n\
+ { \n\
+ void *class_addr; \n\
+ void *sel_addr; \n\
+ void *impl_addr; \n\
+ }; \n\
+ \n\
+ struct __lldb_objc_class { \n\
+ void *isa; \n\
+ void *super_ptr; \n\
+ }; \n\
+ struct __lldb_objc_super { \n\
+ void *reciever; \n\
+ struct __lldb_objc_class *class_ptr; \n\
+ }; \n\
+ struct __lldb_msg_ref { \n\
+ void *dont_know; \n\
+ void *sel; \n\
+ }; \n\
+ \n\
+ struct __lldb_imp_return_struct return_struct; \n\
+ \n\
+ if (debug) \n\
+ printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \" \n\
+ \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\
+ object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed); \n\
+ if (is_super) \n\
+ { \n\
+ if (is_super2) \n\
+ { \n\
+ return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr; \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr; \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ // This code seems a little funny, but has its reasons... \n\
+ // The call to [object class] is here because if this is a class, and has not been called into \n\
+ // yet, we need to do something to force the class to initialize itself. \n\
+ // Then the call to object_getClass will actually return the correct class, either the class \n\
+ // if object is a class instance, or the meta-class if it is a class pointer. \n\
+ void *class_ptr = (void *) [(id) object class]; \n\
+ return_struct.class_addr = (id) object_getClass((id) object); \n\
+ if (debug) \n\
+ { \n\
+ if (class_ptr == object) \n\
+ { \n\
+ printf (\"Found a class object, need to return the meta class %p -> %p\\n\", \n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ else \n\
+ { \n\
+ printf (\"[object class] returned: %p object_getClass: %p.\\n\", \n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ } \n\
+ } \n\
+ \n\
+ if (is_fixup) \n\
+ { \n\
+ if (is_fixed) \n\
+ { \n\
+ return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\
+ } \n\
+ else \n\
+ { \n\
+ char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\
+ return_struct.sel_addr = sel_getUid (sel_name); \n\
+ if (debug) \n\
+ printf (\"\\n*** Got fixed up selector: %p for name %s.\\n\", \n\
+ return_struct.sel_addr, sel_name); \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.sel_addr = sel; \n\
+ } \n\
+ \n\
+ return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr, \n\
+ return_struct.sel_addr); \n\
+ if (debug) \n\
+ printf (\"\\n*** Returning implementation: 0x%p.\\n\", return_struct.impl_addr); \n\
+ \n\
+ return return_struct.impl_addr; \n\
+} \n\
+";
+
+AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr) :
+ m_valid (true),
+ m_owner(owner),
+ m_header_addr (header_addr),
+ m_code_start_addr(0),
+ m_code_end_addr (0),
+ m_next_region (0)
+{
+ SetUpRegion ();
+}
+
+AppleObjCTrampolineHandler::~AppleObjCTrampolineHandler()
+{
+}
+
+void
+AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion()
+{
+ // The header looks like:
+ //
+ // uint16_t headerSize
+ // uint16_t descSize
+ // uint32_t descCount
+ // void * next
+ //
+ // First read in the header:
+
+ char memory_buffer[16];
+ ProcessSP process_sp = m_owner->GetProcessSP();
+ if (!process_sp)
+ return;
+ DataExtractor data(memory_buffer, sizeof(memory_buffer),
+ process_sp->GetByteOrder(),
+ process_sp->GetAddressByteSize());
+ size_t actual_size = 8 + process_sp->GetAddressByteSize();
+ Error error;
+ size_t bytes_read = process_sp->ReadMemory (m_header_addr, memory_buffer, actual_size, error);
+ if (bytes_read != actual_size)
+ {
+ m_valid = false;
+ return;
+ }
+
+ lldb::offset_t offset = 0;
+ const uint16_t header_size = data.GetU16(&offset);
+ const uint16_t descriptor_size = data.GetU16(&offset);
+ const size_t num_descriptors = data.GetU32(&offset);
+
+ m_next_region = data.GetPointer(&offset);
+
+ // If the header size is 0, that means we've come in too early before this data is set up.
+ // Set ourselves as not valid, and continue.
+ if (header_size == 0 || num_descriptors == 0)
+ {
+ m_valid = false;
+ return;
+ }
+
+ // Now read in all the descriptors:
+ // The descriptor looks like:
+ //
+ // uint32_t offset
+ // uint32_t flags
+ //
+ // Where offset is either 0 - in which case it is unused, or
+ // it is the offset of the vtable code from the beginning of the descriptor record.
+ // Below, we'll convert that into an absolute code address, since I don't want to have
+ // to compute it over and over.
+
+ // Ingest the whole descriptor array:
+ const lldb::addr_t desc_ptr = m_header_addr + header_size;
+ const size_t desc_array_size = num_descriptors * descriptor_size;
+ DataBufferSP data_sp(new DataBufferHeap (desc_array_size, '\0'));
+ uint8_t* dst = (uint8_t*)data_sp->GetBytes();
+
+ DataExtractor desc_extractor (dst, desc_array_size,
+ process_sp->GetByteOrder(),
+ process_sp->GetAddressByteSize());
+ bytes_read = process_sp->ReadMemory(desc_ptr, dst, desc_array_size, error);
+ if (bytes_read != desc_array_size)
+ {
+ m_valid = false;
+ return;
+ }
+
+ // The actual code for the vtables will be laid out consecutively, so I also
+ // compute the start and end of the whole code block.
+
+ offset = 0;
+ m_code_start_addr = 0;
+ m_code_end_addr = 0;
+
+ for (size_t i = 0; i < num_descriptors; i++)
+ {
+ lldb::addr_t start_offset = offset;
+ uint32_t voffset = desc_extractor.GetU32 (&offset);
+ uint32_t flags = desc_extractor.GetU32 (&offset);
+ lldb::addr_t code_addr = desc_ptr + start_offset + voffset;
+ m_descriptors.push_back (VTableDescriptor(flags, code_addr));
+
+ if (m_code_start_addr == 0 || code_addr < m_code_start_addr)
+ m_code_start_addr = code_addr;
+ if (code_addr > m_code_end_addr)
+ m_code_end_addr = code_addr;
+
+ offset = start_offset + descriptor_size;
+ }
+ // Finally, a little bird told me that all the vtable code blocks are the same size.
+ // Let's compute the blocks and if they are all the same add the size to the code end address:
+ lldb::addr_t code_size = 0;
+ bool all_the_same = true;
+ for (size_t i = 0; i < num_descriptors - 1; i++)
+ {
+ lldb::addr_t this_size = m_descriptors[i + 1].code_start - m_descriptors[i].code_start;
+ if (code_size == 0)
+ code_size = this_size;
+ else
+ {
+ if (this_size != code_size)
+ all_the_same = false;
+ if (this_size > code_size)
+ code_size = this_size;
+ }
+ }
+ if (all_the_same)
+ m_code_end_addr += code_size;
+}
+
+bool
+AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::AddressInRegion (lldb::addr_t addr, uint32_t &flags)
+{
+ if (!IsValid())
+ return false;
+
+ if (addr < m_code_start_addr || addr > m_code_end_addr)
+ return false;
+
+ std::vector<VTableDescriptor>::iterator pos, end = m_descriptors.end();
+ for (pos = m_descriptors.begin(); pos != end; pos++)
+ {
+ if (addr <= (*pos).code_start)
+ {
+ flags = (*pos).flags;
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::Dump (Stream &s)
+{
+ s.Printf ("Header addr: 0x%" PRIx64 " Code start: 0x%" PRIx64 " Code End: 0x%" PRIx64 " Next: 0x%" PRIx64 "\n",
+ m_header_addr, m_code_start_addr, m_code_end_addr, m_next_region);
+ size_t num_elements = m_descriptors.size();
+ for (size_t i = 0; i < num_elements; i++)
+ {
+ s.Indent();
+ s.Printf ("Code start: 0x%" PRIx64 " Flags: %d\n", m_descriptors[i].code_start, m_descriptors[i].flags);
+ }
+}
+
+AppleObjCTrampolineHandler::AppleObjCVTables::AppleObjCVTables (const ProcessSP &process_sp,
+ const ModuleSP &objc_module_sp) :
+ m_process_wp (),
+ m_trampoline_header (LLDB_INVALID_ADDRESS),
+ m_trampolines_changed_bp_id (LLDB_INVALID_BREAK_ID),
+ m_objc_module_sp (objc_module_sp)
+{
+ if (process_sp)
+ m_process_wp = process_sp;
+}
+
+AppleObjCTrampolineHandler::AppleObjCVTables::~AppleObjCVTables()
+{
+ ProcessSP process_sp = GetProcessSP ();
+ if (process_sp)
+ {
+ if (m_trampolines_changed_bp_id != LLDB_INVALID_BREAK_ID)
+ process_sp->GetTarget().RemoveBreakpointByID (m_trampolines_changed_bp_id);
+ }
+}
+
+bool
+AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols ()
+{
+ if (m_trampoline_header != LLDB_INVALID_ADDRESS)
+ return true;
+
+ ProcessSP process_sp = GetProcessSP ();
+ if (process_sp)
+ {
+ Target &target = process_sp->GetTarget();
+
+ const ModuleList &target_modules = target.GetImages();
+ Mutex::Locker modules_locker(target_modules.GetMutex());
+ size_t num_modules = target_modules.GetSize();
+ if (!m_objc_module_sp)
+ {
+ for (size_t i = 0; i < num_modules; i++)
+ {
+ if (process_sp->GetObjCLanguageRuntime()->IsModuleObjCLibrary (target_modules.GetModuleAtIndexUnlocked(i)))
+ {
+ m_objc_module_sp = target_modules.GetModuleAtIndexUnlocked(i);
+ break;
+ }
+ }
+ }
+
+ if (m_objc_module_sp)
+ {
+ ConstString trampoline_name ("gdb_objc_trampolines");
+ const Symbol *trampoline_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (trampoline_name,
+ eSymbolTypeData);
+ if (trampoline_symbol != NULL)
+ {
+ m_trampoline_header = trampoline_symbol->GetLoadAddress(&target);
+ if (m_trampoline_header == LLDB_INVALID_ADDRESS)
+ return false;
+
+ // Next look up the "changed" symbol and set a breakpoint on that...
+ ConstString changed_name ("gdb_objc_trampolines_changed");
+ const Symbol *changed_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (changed_name,
+ eSymbolTypeCode);
+ if (changed_symbol != NULL)
+ {
+ const Address changed_symbol_addr = changed_symbol->GetAddress();
+ if (!changed_symbol_addr.IsValid())
+ return false;
+
+ lldb::addr_t changed_addr = changed_symbol_addr.GetOpcodeLoadAddress (&target);
+ if (changed_addr != LLDB_INVALID_ADDRESS)
+ {
+ BreakpointSP trampolines_changed_bp_sp = target.CreateBreakpoint (changed_addr, true, false);
+ if (trampolines_changed_bp_sp)
+ {
+ m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID();
+ trampolines_changed_bp_sp->SetCallback (RefreshTrampolines, this, true);
+ trampolines_changed_bp_sp->SetBreakpointKind ("objc-trampolines-changed");
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool
+AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines (void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id)
+{
+ AppleObjCVTables *vtable_handler = (AppleObjCVTables *) baton;
+ if (vtable_handler->InitializeVTableSymbols())
+ {
+ // The Update function is called with the address of an added region. So we grab that address, and
+ // feed it into ReadRegions. Of course, our friend the ABI will get the values for us.
+ ExecutionContext exe_ctx (context->exe_ctx_ref);
+ Process *process = exe_ctx.GetProcessPtr();
+ const ABI *abi = process->GetABI().get();
+
+ ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
+ ValueList argument_values;
+ Value input_value;
+ CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+
+ input_value.SetValueType (Value::eValueTypeScalar);
+ //input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
+ input_value.SetCompilerType (clang_void_ptr_type);
+ argument_values.PushValue(input_value);
+
+ bool success = abi->GetArgumentValues (exe_ctx.GetThreadRef(), argument_values);
+ if (!success)
+ return false;
+
+ // Now get a pointer value from the zeroth argument.
+ Error error;
+ DataExtractor data;
+ error = argument_values.GetValueAtIndex(0)->GetValueAsData (&exe_ctx,
+ data,
+ 0,
+ NULL);
+ lldb::offset_t offset = 0;
+ lldb::addr_t region_addr = data.GetPointer(&offset);
+
+ if (region_addr != 0)
+ vtable_handler->ReadRegions(region_addr);
+ }
+ return false;
+}
+
+bool
+AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions ()
+{
+ // The no argument version reads the start region from the value of the gdb_regions_header, and
+ // gets started from there.
+
+ m_regions.clear();
+ if (!InitializeVTableSymbols())
+ return false;
+ Error error;
+ ProcessSP process_sp = GetProcessSP ();
+ if (process_sp)
+ {
+ lldb::addr_t region_addr = process_sp->ReadPointerFromMemory (m_trampoline_header, error);
+ if (error.Success())
+ return ReadRegions (region_addr);
+ }
+ return false;
+}
+
+bool
+AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions (lldb::addr_t region_addr)
+{
+ ProcessSP process_sp = GetProcessSP ();
+ if (!process_sp)
+ return false;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+
+ // We aren't starting at the trampoline symbol.
+ InitializeVTableSymbols ();
+ lldb::addr_t next_region = region_addr;
+
+ // Read in the sizes of the headers.
+ while (next_region != 0)
+ {
+ m_regions.push_back (VTableRegion(this, next_region));
+ if (!m_regions.back().IsValid())
+ {
+ m_regions.clear();
+ return false;
+ }
+ if (log)
+ {
+ StreamString s;
+ m_regions.back().Dump(s);
+ log->Printf("Read vtable region: \n%s", s.GetData());
+ }
+
+ next_region = m_regions.back().GetNextRegionAddr();
+ }
+
+ return true;
+}
+
+bool
+AppleObjCTrampolineHandler::AppleObjCVTables::IsAddressInVTables (lldb::addr_t addr, uint32_t &flags)
+{
+ region_collection::iterator pos, end = m_regions.end();
+ for (pos = m_regions.begin(); pos != end; pos++)
+ {
+ if ((*pos).AddressInRegion (addr, flags))
+ return true;
+ }
+ return false;
+}
+
+const AppleObjCTrampolineHandler::DispatchFunction
+AppleObjCTrampolineHandler::g_dispatch_functions[] =
+{
+ // NAME STRET SUPER SUPER2 FIXUP TYPE
+ {"objc_msgSend", false, false, false, DispatchFunction::eFixUpNone },
+ {"objc_msgSend_fixup", false, false, false, DispatchFunction::eFixUpToFix },
+ {"objc_msgSend_fixedup", false, false, false, DispatchFunction::eFixUpFixed },
+ {"objc_msgSend_stret", true, false, false, DispatchFunction::eFixUpNone },
+ {"objc_msgSend_stret_fixup", true, false, false, DispatchFunction::eFixUpToFix },
+ {"objc_msgSend_stret_fixedup", true, false, false, DispatchFunction::eFixUpFixed },
+ {"objc_msgSend_fpret", false, false, false, DispatchFunction::eFixUpNone },
+ {"objc_msgSend_fpret_fixup", false, false, false, DispatchFunction::eFixUpToFix },
+ {"objc_msgSend_fpret_fixedup", false, false, false, DispatchFunction::eFixUpFixed },
+ {"objc_msgSend_fp2ret", false, false, true, DispatchFunction::eFixUpNone },
+ {"objc_msgSend_fp2ret_fixup", false, false, true, DispatchFunction::eFixUpToFix },
+ {"objc_msgSend_fp2ret_fixedup", false, false, true, DispatchFunction::eFixUpFixed },
+ {"objc_msgSendSuper", false, true, false, DispatchFunction::eFixUpNone },
+ {"objc_msgSendSuper_stret", true, true, false, DispatchFunction::eFixUpNone },
+ {"objc_msgSendSuper2", false, true, true, DispatchFunction::eFixUpNone },
+ {"objc_msgSendSuper2_fixup", false, true, true, DispatchFunction::eFixUpToFix },
+ {"objc_msgSendSuper2_fixedup", false, true, true, DispatchFunction::eFixUpFixed },
+ {"objc_msgSendSuper2_stret", true, true, true, DispatchFunction::eFixUpNone },
+ {"objc_msgSendSuper2_stret_fixup", true, true, true, DispatchFunction::eFixUpToFix },
+ {"objc_msgSendSuper2_stret_fixedup", true, true, true, DispatchFunction::eFixUpFixed },
+};
+
+AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process_sp,
+ const ModuleSP &objc_module_sp) :
+ m_process_wp (),
+ m_objc_module_sp (objc_module_sp),
+ m_impl_fn_addr (LLDB_INVALID_ADDRESS),
+ m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS),
+ m_msg_forward_addr (LLDB_INVALID_ADDRESS)
+{
+ if (process_sp)
+ m_process_wp = process_sp;
+ // Look up the known resolution functions:
+
+ ConstString get_impl_name("class_getMethodImplementation");
+ ConstString get_impl_stret_name("class_getMethodImplementation_stret");
+ ConstString msg_forward_name("_objc_msgForward");
+ ConstString msg_forward_stret_name("_objc_msgForward_stret");
+
+ Target *target = process_sp ? &process_sp->GetTarget() : NULL;
+ const Symbol *class_getMethodImplementation = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_name, eSymbolTypeCode);
+ const Symbol *class_getMethodImplementation_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_stret_name, eSymbolTypeCode);
+ const Symbol *msg_forward = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_name, eSymbolTypeCode);
+ const Symbol *msg_forward_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_stret_name, eSymbolTypeCode);
+
+ if (class_getMethodImplementation)
+ m_impl_fn_addr = class_getMethodImplementation->GetAddress().GetOpcodeLoadAddress (target);
+ if (class_getMethodImplementation_stret)
+ m_impl_stret_fn_addr = class_getMethodImplementation_stret->GetAddress().GetOpcodeLoadAddress (target);
+ if (msg_forward)
+ m_msg_forward_addr = msg_forward->GetAddress().GetOpcodeLoadAddress(target);
+ if (msg_forward_stret)
+ m_msg_forward_stret_addr = msg_forward_stret->GetAddress().GetOpcodeLoadAddress(target);
+
+ // FIXME: Do some kind of logging here.
+ if (m_impl_fn_addr == LLDB_INVALID_ADDRESS)
+ {
+ // If we can't even find the ordinary get method implementation function, then we aren't going to be able to
+ // step through any method dispatches. Warn to that effect and get out of here.
+ if (process_sp->CanJIT())
+ {
+ process_sp->GetTarget().GetDebugger().GetErrorFile()->Printf ("Could not find implementation lookup function \"%s\""
+ " step in through ObjC method dispatch will not work.\n",
+ get_impl_name.AsCString());
+ }
+ return;
+ }
+ else if (m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS)
+ {
+ // It there is no stret return lookup function, assume that it is the same as the straight lookup:
+ m_impl_stret_fn_addr = m_impl_fn_addr;
+ // Also we will use the version of the lookup code that doesn't rely on the stret version of the function.
+ g_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code;
+ }
+ else
+ {
+ g_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code;
+ }
+
+ // Look up the addresses for the objc dispatch functions and cache them. For now I'm inspecting the symbol
+ // names dynamically to figure out how to dispatch to them. If it becomes more complicated than this we can
+ // turn the g_dispatch_functions char * array into a template table, and populate the DispatchFunction map
+ // from there.
+
+ for (size_t i = 0; i != llvm::array_lengthof(g_dispatch_functions); i++)
+ {
+ ConstString name_const_str(g_dispatch_functions[i].name);
+ const Symbol *msgSend_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (name_const_str, eSymbolTypeCode);
+ if (msgSend_symbol && msgSend_symbol->ValueIsAddress())
+ {
+ // FixMe: Make g_dispatch_functions static table of DispatchFunctions, and have the map be address->index.
+ // Problem is we also need to lookup the dispatch function. For now we could have a side table of stret & non-stret
+ // dispatch functions. If that's as complex as it gets, we're fine.
+
+ lldb::addr_t sym_addr = msgSend_symbol->GetAddressRef().GetOpcodeLoadAddress(target);
+
+ m_msgSend_map.insert(std::pair<lldb::addr_t, int>(sym_addr, i));
+ }
+ }
+
+ // Build our vtable dispatch handler here:
+ m_vtables_ap.reset(new AppleObjCVTables(process_sp, m_objc_module_sp));
+ if (m_vtables_ap.get())
+ m_vtables_ap->ReadRegions();
+}
+
+lldb::addr_t
+AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &dispatch_values)
+{
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ StreamString errors;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
+ FunctionCaller *impl_function_caller = nullptr;
+
+ // Scope for mutex locker:
+ {
+ Mutex::Locker locker(m_impl_function_mutex);
+
+ // First stage is to make the ClangUtility to hold our injected function:
+
+ if (!m_impl_code.get())
+ {
+ if (g_lookup_implementation_function_code != NULL)
+ {
+ Error error;
+ m_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (g_lookup_implementation_function_code,
+ eLanguageTypeObjC,
+ g_lookup_implementation_function_name,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("Failed to get Utility Function for implementation lookup: %s.", error.AsCString());
+ m_impl_code.reset();
+ return args_addr;
+ }
+
+ if (!m_impl_code->Install(errors, exe_ctx))
+ {
+ if (log)
+ log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ m_impl_code.reset();
+ return args_addr;
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf("No method lookup implementation code.");
+ errors.Printf ("No method lookup implementation code found.");
+ return LLDB_INVALID_ADDRESS;
+ }
+
+
+ // Next make the runner function for our implementation utility function.
+ ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext();
+ CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ Error error;
+
+ impl_function_caller = m_impl_code->MakeFunctionCaller(clang_void_ptr_type,
+ dispatch_values,
+ error);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("Error getting function caller for dispatch lookup: \"%s\".", error.AsCString());
+ return args_addr;
+ }
+ }
+ else
+ {
+ impl_function_caller = m_impl_code->GetFunctionCaller();
+ }
+ }
+
+ errors.Clear();
+
+ // Now write down the argument values for this particular call. This looks like it might be a race condition
+ // if other threads were calling into here, but actually it isn't because we allocate a new args structure for
+ // this call by passing args_addr = LLDB_INVALID_ADDRESS...
+
+ if (impl_function_caller->WriteFunctionArguments (exe_ctx, args_addr, dispatch_values, errors))
+ {
+ if (log)
+ log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
+ return args_addr;
+ }
+
+ return args_addr;
+}
+
+ThreadPlanSP
+AppleObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool stop_others)
+{
+ ThreadPlanSP ret_plan_sp;
+ lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
+
+ DispatchFunction this_dispatch;
+ bool found_it = false;
+
+ // First step is to look and see if we are in one of the known ObjC dispatch functions. We've already compiled
+ // a table of same, so consult it.
+
+ MsgsendMap::iterator pos;
+ pos = m_msgSend_map.find (curr_pc);
+ if (pos != m_msgSend_map.end())
+ {
+ this_dispatch = g_dispatch_functions[(*pos).second];
+ found_it = true;
+ }
+
+ // Next check to see if we are in a vtable region:
+
+ if (!found_it)
+ {
+ uint32_t flags;
+ if (m_vtables_ap.get())
+ {
+ found_it = m_vtables_ap->IsAddressInVTables (curr_pc, flags);
+ if (found_it)
+ {
+ this_dispatch.name = "vtable";
+ this_dispatch.stret_return
+ = (flags & AppleObjCVTables::eOBJC_TRAMPOLINE_STRET) == AppleObjCVTables::eOBJC_TRAMPOLINE_STRET;
+ this_dispatch.is_super = false;
+ this_dispatch.is_super2 = false;
+ this_dispatch.fixedup = DispatchFunction::eFixUpFixed;
+ }
+ }
+ }
+
+ if (found_it)
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+
+ // We are decoding a method dispatch.
+ // First job is to pull the arguments out:
+
+ lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0);
+
+ const ABI *abi = NULL;
+ ProcessSP process_sp (thread.CalculateProcess());
+ if (process_sp)
+ abi = process_sp->GetABI().get();
+ if (abi == NULL)
+ return ret_plan_sp;
+
+ TargetSP target_sp (thread.CalculateTarget());
+
+ ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext();
+ ValueList argument_values;
+ Value void_ptr_value;
+ CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ void_ptr_value.SetValueType (Value::eValueTypeScalar);
+ //void_ptr_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
+ void_ptr_value.SetCompilerType (clang_void_ptr_type);
+
+ int obj_index;
+ int sel_index;
+
+ // If this is a struct return dispatch, then the first argument is the
+ // return struct pointer, and the object is the second, and the selector is the third.
+ // Otherwise the object is the first and the selector the second.
+ if (this_dispatch.stret_return)
+ {
+ obj_index = 1;
+ sel_index = 2;
+ argument_values.PushValue(void_ptr_value);
+ argument_values.PushValue(void_ptr_value);
+ argument_values.PushValue(void_ptr_value);
+ }
+ else
+ {
+ obj_index = 0;
+ sel_index = 1;
+ argument_values.PushValue(void_ptr_value);
+ argument_values.PushValue(void_ptr_value);
+ }
+
+
+ bool success = abi->GetArgumentValues (thread, argument_values);
+ if (!success)
+ return ret_plan_sp;
+
+ lldb::addr_t obj_addr = argument_values.GetValueAtIndex(obj_index)->GetScalar().ULongLong();
+ if (obj_addr == 0x0)
+ {
+ if (log)
+ log->Printf("Asked to step to dispatch to nil object, returning empty plan.");
+ return ret_plan_sp;
+ }
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ Process *process = exe_ctx.GetProcessPtr();
+ // isa_addr will store the class pointer that the method is being dispatched to - so either the class
+ // directly or the super class if this is one of the objc_msgSendSuper flavors. That's mostly used to
+ // look up the class/selector pair in our cache.
+
+ lldb::addr_t isa_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t sel_addr = argument_values.GetValueAtIndex(sel_index)->GetScalar().ULongLong();
+
+ // Figure out the class this is being dispatched to and see if we've already cached this method call,
+ // If so we can push a run-to-address plan directly. Otherwise we have to figure out where
+ // the implementation lives.
+
+ if (this_dispatch.is_super)
+ {
+ if (this_dispatch.is_super2)
+ {
+ // In the objc_msgSendSuper2 case, we don't get the object directly, we get a structure containing
+ // the object and the class to which the super message is being sent. So we need to dig the super
+ // out of the class and use that.
+
+ Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
+ super_value.GetScalar() += process->GetAddressByteSize();
+ super_value.ResolveValue (&exe_ctx);
+
+ if (super_value.GetScalar().IsValid())
+ {
+
+ // isa_value now holds the class pointer. The second word of the class pointer is the super-class pointer:
+ super_value.GetScalar() += process->GetAddressByteSize();
+ super_value.ResolveValue (&exe_ctx);
+ if (super_value.GetScalar().IsValid())
+ isa_addr = super_value.GetScalar().ULongLong();
+ else
+ {
+ if (log)
+ log->Printf("Failed to extract the super class value from the class in objc_super.");
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf("Failed to extract the class value from objc_super.");
+ }
+ }
+ else
+ {
+ // In the objc_msgSendSuper case, we don't get the object directly, we get a two element structure containing
+ // the object and the super class to which the super message is being sent. So the class we want is
+ // the second element of this structure.
+
+ Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
+ super_value.GetScalar() += process->GetAddressByteSize();
+ super_value.ResolveValue (&exe_ctx);
+
+ if (super_value.GetScalar().IsValid())
+ {
+ isa_addr = super_value.GetScalar().ULongLong();
+ }
+ else
+ {
+ if (log)
+ log->Printf("Failed to extract the class value from objc_super.");
+ }
+ }
+ }
+ else
+ {
+ // In the direct dispatch case, the object->isa is the class pointer we want.
+
+ // This is a little cheesy, but since object->isa is the first field,
+ // making the object value a load address value and resolving it will get
+ // the pointer sized data pointed to by that value...
+
+ // Note, it isn't a fatal error not to be able to get the address from the object, since this might
+ // be a "tagged pointer" which isn't a real object, but rather some word length encoded dingus.
+
+ Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
+
+ isa_value.SetValueType(Value::eValueTypeLoadAddress);
+ isa_value.ResolveValue(&exe_ctx);
+ if (isa_value.GetScalar().IsValid())
+ {
+ isa_addr = isa_value.GetScalar().ULongLong();
+ }
+ else
+ {
+ if (log)
+ log->Printf("Failed to extract the isa value from object.");
+ }
+
+ }
+
+ // Okay, we've got the address of the class for which we're resolving this, let's see if it's in our cache:
+ lldb::addr_t impl_addr = LLDB_INVALID_ADDRESS;
+
+ if (isa_addr != LLDB_INVALID_ADDRESS)
+ {
+ if (log)
+ {
+ log->Printf("Resolving call for class - 0x%" PRIx64 " and selector - 0x%" PRIx64,
+ isa_addr, sel_addr);
+ }
+ ObjCLanguageRuntime *objc_runtime = thread.GetProcess()->GetObjCLanguageRuntime ();
+ assert(objc_runtime != NULL);
+
+ impl_addr = objc_runtime->LookupInMethodCache (isa_addr, sel_addr);
+ }
+
+ if (impl_addr != LLDB_INVALID_ADDRESS)
+ {
+ // Yup, it was in the cache, so we can run to that address directly.
+
+ if (log)
+ log->Printf ("Found implementation address in cache: 0x%" PRIx64, impl_addr);
+
+ ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others));
+ }
+ else
+ {
+ // We haven't seen this class/selector pair yet. Look it up.
+ StreamString errors;
+ Address impl_code_address;
+
+ ValueList dispatch_values;
+
+ // We've will inject a little function in the target that takes the object, selector and some flags,
+ // and figures out the implementation. Looks like:
+ // void *__lldb_objc_find_implementation_for_selector (void *object,
+ // void *sel,
+ // int is_stret,
+ // int is_super,
+ // int is_super2,
+ // int is_fixup,
+ // int is_fixed,
+ // int debug)
+ // So set up the arguments for that call.
+
+ dispatch_values.PushValue (*(argument_values.GetValueAtIndex(obj_index)));
+ dispatch_values.PushValue (*(argument_values.GetValueAtIndex(sel_index)));
+
+ Value flag_value;
+ CompilerType clang_int_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingSint, 32);
+ flag_value.SetValueType (Value::eValueTypeScalar);
+ //flag_value.SetContext (Value::eContextTypeClangType, clang_int_type);
+ flag_value.SetCompilerType (clang_int_type);
+
+ if (this_dispatch.stret_return)
+ flag_value.GetScalar() = 1;
+ else
+ flag_value.GetScalar() = 0;
+ dispatch_values.PushValue (flag_value);
+
+ if (this_dispatch.is_super)
+ flag_value.GetScalar() = 1;
+ else
+ flag_value.GetScalar() = 0;
+ dispatch_values.PushValue (flag_value);
+
+ if (this_dispatch.is_super2)
+ flag_value.GetScalar() = 1;
+ else
+ flag_value.GetScalar() = 0;
+ dispatch_values.PushValue (flag_value);
+
+ switch (this_dispatch.fixedup)
+ {
+ case DispatchFunction::eFixUpNone:
+ flag_value.GetScalar() = 0;
+ dispatch_values.PushValue (flag_value);
+ dispatch_values.PushValue (flag_value);
+ break;
+ case DispatchFunction::eFixUpFixed:
+ flag_value.GetScalar() = 1;
+ dispatch_values.PushValue (flag_value);
+ flag_value.GetScalar() = 1;
+ dispatch_values.PushValue (flag_value);
+ break;
+ case DispatchFunction::eFixUpToFix:
+ flag_value.GetScalar() = 1;
+ dispatch_values.PushValue (flag_value);
+ flag_value.GetScalar() = 0;
+ dispatch_values.PushValue (flag_value);
+ break;
+ }
+ if (log && log->GetVerbose())
+ flag_value.GetScalar() = 1;
+ else
+ flag_value.GetScalar() = 0; // FIXME - Set to 0 when debugging is done.
+ dispatch_values.PushValue (flag_value);
+
+
+ // The step through code might have to fill in the cache, so it is not safe to run only one thread.
+ // So we override the stop_others value passed in to us here:
+ const bool trampoline_stop_others = false;
+ ret_plan_sp.reset (new AppleThreadPlanStepThroughObjCTrampoline (thread,
+ this,
+ dispatch_values,
+ isa_addr,
+ sel_addr,
+ trampoline_stop_others));
+ if (log)
+ {
+ StreamString s;
+ ret_plan_sp->GetDescription(&s, eDescriptionLevelFull);
+ log->Printf("Using ObjC step plan: %s.\n", s.GetData());
+ }
+ }
+ }
+
+ return ret_plan_sp;
+}
+
+FunctionCaller *
+AppleObjCTrampolineHandler::GetLookupImplementationFunctionCaller ()
+{
+ return m_impl_code->GetFunctionCaller();
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
new file mode 100644
index 0000000..42d3461
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
@@ -0,0 +1,209 @@
+//===-- AppleObjCTrampolineHandler.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_AppleObjCTrampolineHandler_h_
+#define lldb_AppleObjCTrampolineHandler_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Expression/UtilityFunction.h"
+
+namespace lldb_private
+{
+
+class AppleObjCTrampolineHandler {
+public:
+ AppleObjCTrampolineHandler (const lldb::ProcessSP &process_sp,
+ const lldb::ModuleSP &objc_module_sp);
+
+ ~AppleObjCTrampolineHandler();
+
+ lldb::ThreadPlanSP
+ GetStepThroughDispatchPlan (Thread &thread,
+ bool stop_others);
+
+ FunctionCaller *
+ GetLookupImplementationFunctionCaller ();
+
+ bool
+ AddrIsMsgForward (lldb::addr_t addr) const
+ {
+ return (addr == m_msg_forward_addr || addr == m_msg_forward_stret_addr);
+ }
+
+ struct DispatchFunction {
+ public:
+ typedef enum
+ {
+ eFixUpNone,
+ eFixUpFixed,
+ eFixUpToFix
+ } FixUpState;
+
+ const char *name;
+ bool stret_return;
+ bool is_super;
+ bool is_super2;
+ FixUpState fixedup;
+ };
+
+ lldb::addr_t
+ SetupDispatchFunction (Thread &thread, ValueList &dispatch_values);
+
+private:
+ static const char *g_lookup_implementation_function_name;
+ static const char *g_lookup_implementation_function_code;
+ static const char *g_lookup_implementation_with_stret_function_code;
+ static const char *g_lookup_implementation_no_stret_function_code;
+
+ class AppleObjCVTables
+ {
+ public:
+ // These come from objc-gdb.h.
+ enum VTableFlags
+ {
+ eOBJC_TRAMPOLINE_MESSAGE = (1<<0), // trampoline acts like objc_msgSend
+ eOBJC_TRAMPOLINE_STRET = (1<<1), // trampoline is struct-returning
+ eOBJC_TRAMPOLINE_VTABLE = (1<<2) // trampoline is vtable dispatcher
+ };
+
+ private:
+ struct VTableDescriptor
+ {
+ VTableDescriptor(uint32_t in_flags, lldb::addr_t in_code_start) :
+ flags(in_flags),
+ code_start(in_code_start) {}
+
+ uint32_t flags;
+ lldb::addr_t code_start;
+ };
+
+ class VTableRegion
+ {
+ public:
+ VTableRegion() :
+ m_valid (false),
+ m_owner (NULL),
+ m_header_addr (LLDB_INVALID_ADDRESS),
+ m_code_start_addr(0),
+ m_code_end_addr (0),
+ m_next_region (0)
+ {}
+
+ VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr);
+
+ void SetUpRegion();
+
+ lldb::addr_t GetNextRegionAddr ()
+ {
+ return m_next_region;
+ }
+
+ lldb::addr_t
+ GetCodeStart ()
+ {
+ return m_code_start_addr;
+ }
+
+ lldb::addr_t
+ GetCodeEnd ()
+ {
+ return m_code_end_addr;
+ }
+
+ uint32_t
+ GetFlagsForVTableAtAddress (lldb::addr_t address)
+ {
+ return 0;
+ }
+
+ bool
+ IsValid ()
+ {
+ return m_valid;
+ }
+
+ bool
+ AddressInRegion (lldb::addr_t addr, uint32_t &flags);
+
+ void
+ Dump (Stream &s);
+
+ public:
+ bool m_valid;
+ AppleObjCVTables *m_owner;
+ lldb::addr_t m_header_addr;
+ lldb::addr_t m_code_start_addr;
+ lldb::addr_t m_code_end_addr;
+ std::vector<VTableDescriptor> m_descriptors;
+ lldb::addr_t m_next_region;
+ };
+
+ public:
+ AppleObjCVTables(const lldb::ProcessSP &process_sp,
+ const lldb::ModuleSP &objc_module_sp);
+
+ ~AppleObjCVTables();
+
+ bool
+ InitializeVTableSymbols ();
+
+ static bool RefreshTrampolines (void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+ bool
+ ReadRegions ();
+
+ bool
+ ReadRegions (lldb::addr_t region_addr);
+
+ bool
+ IsAddressInVTables (lldb::addr_t addr, uint32_t &flags);
+
+ lldb::ProcessSP
+ GetProcessSP ()
+ {
+ return m_process_wp.lock();
+ }
+
+ private:
+ lldb::ProcessWP m_process_wp;
+ typedef std::vector<VTableRegion> region_collection;
+ lldb::addr_t m_trampoline_header;
+ lldb::break_id_t m_trampolines_changed_bp_id;
+ region_collection m_regions;
+ lldb::ModuleSP m_objc_module_sp;
+ };
+
+ static const DispatchFunction g_dispatch_functions[];
+
+ typedef std::map<lldb::addr_t, int> MsgsendMap; // This table maps an dispatch fn address to the index in g_dispatch_functions
+ MsgsendMap m_msgSend_map;
+ lldb::ProcessWP m_process_wp;
+ lldb::ModuleSP m_objc_module_sp;
+ std::unique_ptr<UtilityFunction> m_impl_code;
+ Mutex m_impl_function_mutex;
+ lldb::addr_t m_impl_fn_addr;
+ lldb::addr_t m_impl_stret_fn_addr;
+ lldb::addr_t m_msg_forward_addr;
+ lldb::addr_t m_msg_forward_stret_addr;
+ std::unique_ptr<AppleObjCVTables> m_vtables_ap;
+};
+
+} // namespace lldb_private
+
+#endif // lldb_AppleObjCTrampolineHandler_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
new file mode 100644
index 0000000..9308c7a
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
@@ -0,0 +1,398 @@
+//===-- AppleObjCTypeEncodingParser.cpp -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AppleObjCTypeEncodingParser.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/StringLexer.h"
+
+#include <vector>
+
+using namespace lldb_private;
+using namespace lldb_utility;
+
+AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser (ObjCLanguageRuntime& runtime) :
+ ObjCLanguageRuntime::EncodingToType(),
+ m_runtime(runtime)
+{
+ if (!m_scratch_ast_ctx_ap)
+ m_scratch_ast_ctx_ap.reset(new ClangASTContext(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().str().c_str()));
+}
+
+std::string
+AppleObjCTypeEncodingParser::ReadStructName(lldb_utility::StringLexer& type)
+{
+ StreamString buffer;
+ while (type.HasAtLeast(1) && type.Peek() != '=')
+ buffer.Printf("%c",type.Next());
+ return buffer.GetString();
+}
+
+std::string
+AppleObjCTypeEncodingParser::ReadQuotedString(lldb_utility::StringLexer& type)
+{
+ StreamString buffer;
+ while (type.HasAtLeast(1) && type.Peek() != '"')
+ buffer.Printf("%c",type.Next());
+ StringLexer::Character next = type.Next();
+ UNUSED_IF_ASSERT_DISABLED(next);
+ assert (next == '"');
+ return buffer.GetString();
+}
+
+uint32_t
+AppleObjCTypeEncodingParser::ReadNumber (lldb_utility::StringLexer& type)
+{
+ uint32_t total = 0;
+ while (type.HasAtLeast(1) && isdigit(type.Peek()))
+ total = 10*total + (type.Next() - '0');
+ return total;
+}
+
+// as an extension to the published grammar recent runtimes emit structs like this:
+// "{CGRect=\"origin\"{CGPoint=\"x\"d\"y\"d}\"size\"{CGSize=\"width\"d\"height\"d}}"
+
+AppleObjCTypeEncodingParser::StructElement::StructElement() :
+name(""),
+type(clang::QualType()),
+bitfield(0)
+{}
+
+AppleObjCTypeEncodingParser::StructElement
+AppleObjCTypeEncodingParser::ReadStructElement (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression)
+{
+ StructElement retval;
+ if (type.NextIf('"'))
+ retval.name = ReadQuotedString(type);
+ if (!type.NextIf('"'))
+ return retval;
+ uint32_t bitfield_size = 0;
+ retval.type = BuildType(ast_ctx, type, for_expression, &bitfield_size);
+ retval.bitfield = bitfield_size;
+ return retval;
+}
+
+clang::QualType
+AppleObjCTypeEncodingParser::BuildStruct (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression)
+{
+ return BuildAggregate(ast_ctx, type, for_expression, '{', '}', clang::TTK_Struct);
+}
+
+clang::QualType
+AppleObjCTypeEncodingParser::BuildUnion (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression)
+{
+ return BuildAggregate(ast_ctx, type, for_expression, '(', ')', clang::TTK_Union);
+}
+
+clang::QualType
+AppleObjCTypeEncodingParser::BuildAggregate (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression, char opener, char closer, uint32_t kind)
+{
+ if (!type.NextIf(opener))
+ return clang::QualType();
+ std::string name(ReadStructName(type));
+
+ // We do not handle templated classes/structs at the moment.
+ // If the name has a < in it, we are going to abandon this.
+ // We're still obliged to parse it, so we just set a flag that
+ // means "Don't actually build anything."
+
+ const bool is_templated = name.find('<') != std::string::npos;
+
+ if (!type.NextIf('='))
+ return clang::QualType();
+ bool in_union = true;
+ std::vector<StructElement> elements;
+ while (in_union && type.HasAtLeast(1))
+ {
+ if (type.NextIf(closer))
+ {
+ in_union = false;
+ break;
+ }
+ else
+ {
+ auto element = ReadStructElement(ast_ctx, type, for_expression);
+ if (element.type.isNull())
+ break;
+ else
+ elements.push_back(element);
+ }
+ }
+ if (in_union)
+ return clang::QualType();
+
+ if (is_templated)
+ return clang::QualType(); // This is where we bail out. Sorry!
+
+ ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
+ if (!lldb_ctx)
+ return clang::QualType();
+ CompilerType union_type(lldb_ctx->CreateRecordType(nullptr, lldb::eAccessPublic, name.c_str(), kind, lldb::eLanguageTypeC));
+ if (union_type)
+ {
+ ClangASTContext::StartTagDeclarationDefinition(union_type);
+
+ unsigned int count = 0;
+ for (auto element: elements)
+ {
+ if (element.name.empty())
+ {
+ StreamString elem_name;
+ elem_name.Printf("__unnamed_%u",count);
+ element.name = std::string(elem_name.GetData());
+ }
+ ClangASTContext::AddFieldToRecordType(union_type, element.name.c_str(), CompilerType(&ast_ctx, element.type), lldb::eAccessPublic, element.bitfield);
+ ++count;
+ }
+ ClangASTContext::CompleteTagDeclarationDefinition(union_type);
+ }
+ return ClangASTContext::GetQualType(union_type);
+}
+
+clang::QualType
+AppleObjCTypeEncodingParser::BuildArray (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression)
+{
+ if (!type.NextIf('['))
+ return clang::QualType();
+ uint32_t size = ReadNumber(type);
+ clang::QualType element_type(BuildType(ast_ctx, type, for_expression));
+ if (!type.NextIf(']'))
+ return clang::QualType();
+ ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
+ if (!lldb_ctx)
+ return clang::QualType();
+ CompilerType array_type(lldb_ctx->CreateArrayType(CompilerType(&ast_ctx, element_type), size, false));
+ return ClangASTContext::GetQualType(array_type);
+}
+
+// the runtime can emit these in the form of @"SomeType", giving more specifics
+// this would be interesting for expression parser interop, but since we actually try
+// to avoid exposing the ivar info to the expression evaluator, consume but ignore the type info
+// and always return an 'id'; if anything, dynamic typing will resolve things for us anyway
+clang::QualType
+AppleObjCTypeEncodingParser::BuildObjCObjectPointerType (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression)
+{
+ if (!type.NextIf('@'))
+ return clang::QualType();
+
+ std::string name;
+
+ if (type.NextIf('"'))
+ {
+ // We have to be careful here. We're used to seeing
+ // @"NSString"
+ // but in records it is possible that the string following an @ is the name of the next field and @ means "id".
+ // This is the case if anything unquoted except for "}", the end of the type, or another name follows the quoted string.
+ //
+ // E.g.
+ // - @"NSString"@ means "id, followed by a field named NSString of type id"
+ // - @"NSString"} means "a pointer to NSString and the end of the struct"
+ // - @"NSString""nextField" means "a pointer to NSString and a field named nextField"
+ // - @"NSString" followed by the end of the string means "a pointer to NSString"
+ //
+ // As a result, the rule is: If we see @ followed by a quoted string, we peek.
+ // - If we see }, ), ], the end of the string, or a quote ("), the quoted string is a class name.
+ // - If we see anything else, the quoted string is a field name and we push it back onto type.
+
+ name = ReadQuotedString(type);
+
+ if (type.HasAtLeast(1))
+ {
+ switch (type.Peek())
+ {
+ default:
+ // roll back
+ type.PutBack(name.length() + 2); // undo our consumption of the string and of the quotes
+ name.clear();
+ break;
+ case '}':
+ case ')':
+ case ']':
+ case '"':
+ // the quoted string is a class name – see the rule
+ break;
+ }
+ }
+ else
+ {
+ // the quoted string is a class name – see the rule
+ }
+ }
+
+ if (for_expression && !name.empty())
+ {
+ size_t less_than_pos = name.find('<');
+
+ if (less_than_pos != std::string::npos)
+ {
+ if (less_than_pos == 0)
+ return ast_ctx.getObjCIdType();
+ else
+ name.erase(less_than_pos);
+ }
+
+ DeclVendor *decl_vendor = m_runtime.GetDeclVendor();
+
+ assert (decl_vendor); // how are we parsing type encodings for expressions if a type vendor isn't in play?
+
+ const bool append = false;
+ const uint32_t max_matches = 1;
+ std::vector<clang::NamedDecl *> decls;
+
+ uint32_t num_types = decl_vendor->FindDecls(ConstString(name),
+ append,
+ max_matches,
+ decls);
+
+ // The user can forward-declare something that has no definition. The runtime doesn't prohibit this at all.
+ // This is a rare and very weird case. We keep this assert in debug builds so we catch other weird cases.
+#ifdef LLDB_CONFIGURATION_DEBUG
+ assert(num_types);
+#else
+ if (!num_types)
+ return ast_ctx.getObjCIdType();
+#endif
+
+ return ClangASTContext::GetQualType(ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType());
+ }
+ else
+ {
+ // We're going to resolve this dynamically anyway, so just smile and wave.
+ return ast_ctx.getObjCIdType();
+ }
+}
+
+clang::QualType
+AppleObjCTypeEncodingParser::BuildType (clang::ASTContext &ast_ctx, StringLexer& type, bool for_expression, uint32_t *bitfield_bit_size)
+{
+ if (!type.HasAtLeast(1))
+ return clang::QualType();
+
+ switch (type.Peek())
+ {
+ default:
+ break;
+ case '{':
+ return BuildStruct(ast_ctx, type, for_expression);
+ case '[':
+ return BuildArray(ast_ctx, type, for_expression);
+ case '(':
+ return BuildUnion(ast_ctx, type, for_expression);
+ case '@':
+ return BuildObjCObjectPointerType(ast_ctx, type, for_expression);
+ }
+
+ switch (type.Next())
+ {
+ default:
+ type.PutBack(1);
+ return clang::QualType();
+ case 'c':
+ return ast_ctx.CharTy;
+ case 'i':
+ return ast_ctx.IntTy;
+ case 's':
+ return ast_ctx.ShortTy;
+ case 'l':
+ return ast_ctx.getIntTypeForBitwidth(32, true);
+ // this used to be done like this:
+ // ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
+ // if (!lldb_ctx)
+ // return clang::QualType();
+ // return lldb_ctx->GetIntTypeFromBitSize(32, true).GetQualType();
+ // which uses one of the constants if one is available, but we don't think all this work is necessary.
+ case 'q':
+ return ast_ctx.LongLongTy;
+ case 'C':
+ return ast_ctx.UnsignedCharTy;
+ case 'I':
+ return ast_ctx.UnsignedIntTy;
+ case 'S':
+ return ast_ctx.UnsignedShortTy;
+ case 'L':
+ return ast_ctx.getIntTypeForBitwidth(32, false);
+ // see note for 'l'
+ case 'Q':
+ return ast_ctx.UnsignedLongLongTy;
+ case 'f':
+ return ast_ctx.FloatTy;
+ case 'd':
+ return ast_ctx.DoubleTy;
+ case 'B':
+ return ast_ctx.BoolTy;
+ case 'v':
+ return ast_ctx.VoidTy;
+ case '*':
+ return ast_ctx.getPointerType(ast_ctx.CharTy);
+ case '#':
+ return ast_ctx.getObjCClassType();
+ case ':':
+ return ast_ctx.getObjCSelType();
+ case 'b':
+ {
+ uint32_t size = ReadNumber(type);
+ if (bitfield_bit_size)
+ {
+ *bitfield_bit_size = size;
+ return ast_ctx.UnsignedIntTy; // FIXME: the spec is fairly vague here.
+ }
+ else
+ return clang::QualType();
+ }
+ case 'r':
+ {
+ clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
+ if (target_type.isNull())
+ return clang::QualType();
+ else if (target_type == ast_ctx.UnknownAnyTy)
+ return ast_ctx.UnknownAnyTy;
+ else
+ return ast_ctx.getConstType(target_type);
+ }
+ case '^':
+ {
+ if (!for_expression && type.NextIf('?'))
+ {
+ // if we are not supporting the concept of unknownAny, but what is being created here is an unknownAny*, then
+ // we can just get away with a void*
+ // this is theoretically wrong (in the same sense as 'theoretically nothing exists') but is way better than outright failure
+ // in many practical cases
+ return ast_ctx.VoidPtrTy;
+ }
+ else
+ {
+ clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
+ if (target_type.isNull())
+ return clang::QualType();
+ else if (target_type == ast_ctx.UnknownAnyTy)
+ return ast_ctx.UnknownAnyTy;
+ else
+ return ast_ctx.getPointerType(target_type);
+ }
+ }
+ case '?':
+ return for_expression ? ast_ctx.UnknownAnyTy : clang::QualType();
+ }
+}
+
+CompilerType
+AppleObjCTypeEncodingParser::RealizeType (clang::ASTContext &ast_ctx, const char* name, bool for_expression)
+{
+ if (name && name[0])
+ {
+ StringLexer lexer(name);
+ clang::QualType qual_type = BuildType(ast_ctx, lexer, for_expression);
+ return CompilerType(&ast_ctx, qual_type);
+ }
+ return CompilerType();
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
new file mode 100644
index 0000000..87c49cb
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
@@ -0,0 +1,81 @@
+//===-- AppleObjCTypeEncodingParser.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AppleObjCTypeEncodingParser_h_
+#define liblldb_AppleObjCTypeEncodingParser_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+
+namespace lldb_utility {
+ class StringLexer;
+}
+
+namespace lldb_private {
+
+ class AppleObjCTypeEncodingParser : public ObjCLanguageRuntime::EncodingToType
+ {
+ public:
+ AppleObjCTypeEncodingParser (ObjCLanguageRuntime& runtime);
+ ~AppleObjCTypeEncodingParser() override = default;
+
+ CompilerType RealizeType(clang::ASTContext &ast_ctx, const char* name, bool for_expression) override;
+
+ private:
+ struct StructElement {
+ std::string name;
+ clang::QualType type;
+ uint32_t bitfield;
+
+ StructElement ();
+ ~StructElement () = default;
+ };
+
+ clang::QualType
+ BuildType (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression, uint32_t *bitfield_bit_size = nullptr);
+
+ clang::QualType
+ BuildStruct (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression);
+
+ clang::QualType
+ BuildAggregate (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression, char opener, char closer, uint32_t kind);
+
+ clang::QualType
+ BuildUnion (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression);
+
+ clang::QualType
+ BuildArray (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression);
+
+ std::string
+ ReadStructName(lldb_utility::StringLexer& type);
+
+ StructElement
+ ReadStructElement (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression);
+
+ clang::QualType
+ BuildObjCObjectPointerType (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression);
+
+ uint32_t
+ ReadNumber (lldb_utility::StringLexer& type);
+
+ std::string
+ ReadQuotedString(lldb_utility::StringLexer& type);
+
+ ObjCLanguageRuntime& m_runtime;
+ };
+
+} // namespace lldb_private
+
+#endif // liblldb_AppleObjCTypeEncodingParser_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
new file mode 100644
index 0000000..285786a
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
@@ -0,0 +1,244 @@
+//===-- AppleThreadPlanStepThroughObjCTrampoline.cpp --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "AppleThreadPlanStepThroughObjCTrampoline.h"
+#include "AppleObjCTrampolineHandler.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+#include "lldb/Target/ThreadPlanStepOut.h"
+#include "lldb/Core/Log.h"
+
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanStepThroughObjCTrampoline constructor
+//----------------------------------------------------------------------
+AppleThreadPlanStepThroughObjCTrampoline::AppleThreadPlanStepThroughObjCTrampoline
+(
+ Thread &thread,
+ AppleObjCTrampolineHandler *trampoline_handler,
+ ValueList &input_values,
+ lldb::addr_t isa_addr,
+ lldb::addr_t sel_addr,
+ bool stop_others
+) :
+ ThreadPlan (ThreadPlan::eKindGeneric,
+ "MacOSX Step through ObjC Trampoline",
+ thread,
+ eVoteNoOpinion,
+ eVoteNoOpinion),
+ m_trampoline_handler (trampoline_handler),
+ m_args_addr (LLDB_INVALID_ADDRESS),
+ m_input_values (input_values),
+ m_isa_addr(isa_addr),
+ m_sel_addr(sel_addr),
+ m_impl_function (NULL),
+ m_stop_others (stop_others)
+{
+
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+AppleThreadPlanStepThroughObjCTrampoline::~AppleThreadPlanStepThroughObjCTrampoline()
+{
+}
+
+void
+AppleThreadPlanStepThroughObjCTrampoline::DidPush ()
+{
+ // Setting up the memory space for the called function text might require allocations,
+ // i.e. a nested function call. This needs to be done as a PreResumeAction.
+ m_thread.GetProcess()->AddPreResumeAction (PreResumeInitializeFunctionCaller, (void *) this);
+}
+
+bool
+AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller ()
+{
+ if (!m_func_sp)
+ {
+ StreamString errors;
+ m_args_addr = m_trampoline_handler->SetupDispatchFunction(m_thread, m_input_values);
+
+ if (m_args_addr == LLDB_INVALID_ADDRESS)
+ {
+ return false;
+ }
+ m_impl_function = m_trampoline_handler->GetLookupImplementationFunctionCaller();
+ ExecutionContext exc_ctx;
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetStopOthers(m_stop_others);
+ m_thread.CalculateExecutionContext(exc_ctx);
+ m_func_sp = m_impl_function->GetThreadPlanToCallFunction (exc_ctx,
+ m_args_addr,
+ options,
+ errors);
+ m_func_sp->SetOkayToDiscard(true);
+ m_thread.QueueThreadPlan (m_func_sp, false);
+ }
+ return true;
+}
+
+bool
+AppleThreadPlanStepThroughObjCTrampoline::PreResumeInitializeFunctionCaller(void *void_myself)
+{
+ AppleThreadPlanStepThroughObjCTrampoline *myself = static_cast<AppleThreadPlanStepThroughObjCTrampoline *>(void_myself);
+ return myself->InitializeFunctionCaller();
+}
+
+void
+AppleThreadPlanStepThroughObjCTrampoline::GetDescription (Stream *s,
+ lldb::DescriptionLevel level)
+{
+ if (level == lldb::eDescriptionLevelBrief)
+ s->Printf("Step through ObjC trampoline");
+ else
+ {
+ s->Printf ("Stepping to implementation of ObjC method - obj: 0x%llx, isa: 0x%" PRIx64 ", sel: 0x%" PRIx64,
+ m_input_values.GetValueAtIndex(0)->GetScalar().ULongLong(), m_isa_addr, m_sel_addr);
+ }
+}
+
+bool
+AppleThreadPlanStepThroughObjCTrampoline::ValidatePlan (Stream *error)
+{
+ return true;
+}
+
+bool
+AppleThreadPlanStepThroughObjCTrampoline::DoPlanExplainsStop (Event *event_ptr)
+{
+ // If we get asked to explain the stop it will be because something went
+ // wrong (like the implementation for selector function crashed... We're going
+ // to figure out what to do about that, so we do explain the stop.
+ return true;
+}
+
+lldb::StateType
+AppleThreadPlanStepThroughObjCTrampoline::GetPlanRunState ()
+{
+ return eStateRunning;
+}
+
+bool
+AppleThreadPlanStepThroughObjCTrampoline::ShouldStop (Event *event_ptr)
+{
+ // First stage: we are still handling the "call a function to get the target of the dispatch"
+ if (m_func_sp)
+ {
+ if (!m_func_sp->IsPlanComplete())
+ {
+ return false;
+ }
+ else
+ {
+ if (!m_func_sp->PlanSucceeded())
+ {
+ SetPlanComplete(false);
+ return true;
+ }
+ m_func_sp.reset();
+ }
+ }
+
+ // Second stage, if all went well with the function calling, then fetch the target address, and
+ // queue up a "run to that address" plan.
+ if (!m_run_to_sp)
+ {
+ Value target_addr_value;
+ ExecutionContext exc_ctx;
+ m_thread.CalculateExecutionContext(exc_ctx);
+ m_impl_function->FetchFunctionResults (exc_ctx, m_args_addr, target_addr_value);
+ m_impl_function->DeallocateFunctionResults(exc_ctx, m_args_addr);
+ lldb::addr_t target_addr = target_addr_value.GetScalar().ULongLong();
+ Address target_so_addr;
+ target_so_addr.SetOpcodeLoadAddress(target_addr, exc_ctx.GetTargetPtr());
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ if (target_addr == 0)
+ {
+ if (log)
+ log->Printf("Got target implementation of 0x0, stopping.");
+ SetPlanComplete();
+ return true;
+ }
+ if (m_trampoline_handler->AddrIsMsgForward(target_addr))
+ {
+ if (log)
+ log->Printf ("Implementation lookup returned msgForward function: 0x%" PRIx64 ", stopping.", target_addr);
+
+ SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext(eSymbolContextEverything);
+ const bool abort_other_plans = false;
+ const bool first_insn = true;
+ const uint32_t frame_idx = 0;
+ m_run_to_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop (abort_other_plans,
+ &sc,
+ first_insn,
+ m_stop_others,
+ eVoteNoOpinion,
+ eVoteNoOpinion,
+ frame_idx);
+ m_run_to_sp->SetPrivate(true);
+ return false;
+ }
+
+ if (log)
+ log->Printf("Running to ObjC method implementation: 0x%" PRIx64, target_addr);
+
+ ObjCLanguageRuntime *objc_runtime = GetThread().GetProcess()->GetObjCLanguageRuntime();
+ assert (objc_runtime != NULL);
+ objc_runtime->AddToMethodCache (m_isa_addr, m_sel_addr, target_addr);
+ if (log)
+ log->Printf("Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64 "} = addr=0x%" PRIx64 " to cache.", m_isa_addr, m_sel_addr, target_addr);
+
+ // Extract the target address from the value:
+
+ m_run_to_sp.reset(new ThreadPlanRunToAddress(m_thread, target_so_addr, m_stop_others));
+ m_thread.QueueThreadPlan(m_run_to_sp, false);
+ m_run_to_sp->SetPrivate(true);
+ return false;
+ }
+ else if (m_thread.IsThreadPlanDone(m_run_to_sp.get()))
+ {
+ // Third stage, work the run to target plan.
+ SetPlanComplete();
+ return true;
+ }
+ return false;
+}
+
+// The base class MischiefManaged does some cleanup - so you have to call it
+// in your MischiefManaged derived class.
+bool
+AppleThreadPlanStepThroughObjCTrampoline::MischiefManaged ()
+{
+ if (IsPlanComplete())
+ return true;
+ else
+ return false;
+}
+
+bool
+AppleThreadPlanStepThroughObjCTrampoline::WillStop()
+{
+ return true;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
new file mode 100644
index 0000000..8db9963
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
@@ -0,0 +1,95 @@
+//===-- AppleThreadPlanStepThroughObjCTrampoline.h --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_AppleThreadPlanStepThroughObjCTrampoline_h_
+#define lldb_AppleThreadPlanStepThroughObjCTrampoline_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-types.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "AppleObjCTrampolineHandler.h"
+
+namespace lldb_private
+{
+
+class AppleThreadPlanStepThroughObjCTrampoline : public ThreadPlan
+{
+public:
+ AppleThreadPlanStepThroughObjCTrampoline(Thread &thread,
+ AppleObjCTrampolineHandler *trampoline_handler,
+ ValueList &values,
+ lldb::addr_t isa_addr,
+ lldb::addr_t sel_addr,
+ bool stop_others);
+
+ ~AppleThreadPlanStepThroughObjCTrampoline() override;
+
+ static bool
+ PreResumeInitializeFunctionCaller(void *myself);
+
+ void
+ GetDescription(Stream *s,
+ lldb::DescriptionLevel level) override;
+
+ bool
+ ValidatePlan(Stream *error) override;
+
+ lldb::StateType
+ GetPlanRunState() override;
+
+ bool
+ ShouldStop(Event *event_ptr) override;
+
+ bool
+ StopOthers() override
+ {
+ return m_stop_others;
+ }
+
+ // The base class MischiefManaged does some cleanup - so you have to call it
+ // in your MischiefManaged derived class.
+ bool
+ MischiefManaged() override;
+
+ void
+ DidPush() override;
+
+ bool
+ WillStop() override;
+
+protected:
+ bool
+ DoPlanExplainsStop(Event *event_ptr) override;
+
+private:
+ bool
+ InitializeFunctionCaller ();
+
+ AppleObjCTrampolineHandler *m_trampoline_handler; // FIXME - ensure this doesn't go away on us? SP maybe?
+ lldb::addr_t m_args_addr; // Stores the address for our step through function result structure.
+ //lldb::addr_t m_object_addr; // This is only for Description.
+ ValueList m_input_values;
+ lldb::addr_t m_isa_addr; // isa_addr and sel_addr are the keys we will use to cache the implementation.
+ lldb::addr_t m_sel_addr;
+ lldb::ThreadPlanSP m_func_sp; // This is the function call plan. We fill it at start, then set it
+ // to NULL when this plan is done. That way we know to go to:
+ lldb::ThreadPlanSP m_run_to_sp; // The plan that runs to the target.
+ FunctionCaller *m_impl_function; // This is a pointer to a impl function that
+ // is owned by the client that pushes this plan.
+ bool m_stop_others;
+};
+
+} // namespace lldb_private
+
+#endif // lldb_AppleThreadPlanStepThroughObjCTrampoline_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index 2490cf3..8e5d31b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "RenderScriptRuntime.h"
#include "lldb/Core/ConstString.h"
@@ -14,10 +18,15 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/DataFormatters/DumpValueObjectOptions.h"
+#include "lldb/Host/StringConvert.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -25,11 +34,361 @@
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Target/RegisterContext.h"
-
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Symbol/VariableList.h"
using namespace lldb;
using namespace lldb_private;
+using namespace lldb_renderscript;
+
+namespace {
+
+// The empirical_type adds a basic level of validation to arbitrary data
+// allowing us to track if data has been discovered and stored or not.
+// An empirical_type will be marked as valid only if it has been explicitly assigned to.
+template <typename type_t>
+class empirical_type
+{
+public:
+ // Ctor. Contents is invalid when constructed.
+ empirical_type()
+ : valid(false)
+ {}
+
+ // Return true and copy contents to out if valid, else return false.
+ bool get(type_t& out) const
+ {
+ if (valid)
+ out = data;
+ return valid;
+ }
+
+ // Return a pointer to the contents or nullptr if it was not valid.
+ const type_t* get() const
+ {
+ return valid ? &data : nullptr;
+ }
+
+ // Assign data explicitly.
+ void set(const type_t in)
+ {
+ data = in;
+ valid = true;
+ }
+
+ // Mark contents as invalid.
+ void invalidate()
+ {
+ valid = false;
+ }
+
+ // Returns true if this type contains valid data.
+ bool isValid() const
+ {
+ return valid;
+ }
+
+ // Assignment operator.
+ empirical_type<type_t>& operator = (const type_t in)
+ {
+ set(in);
+ return *this;
+ }
+
+ // Dereference operator returns contents.
+ // Warning: Will assert if not valid so use only when you know data is valid.
+ const type_t& operator * () const
+ {
+ assert(valid);
+ return data;
+ }
+
+protected:
+ bool valid;
+ type_t data;
+};
+
+} // anonymous namespace
+
+// The ScriptDetails class collects data associated with a single script instance.
+struct RenderScriptRuntime::ScriptDetails
+{
+ ~ScriptDetails() = default;
+
+ enum ScriptType
+ {
+ eScript,
+ eScriptC
+ };
+
+ // The derived type of the script.
+ empirical_type<ScriptType> type;
+ // The name of the original source file.
+ empirical_type<std::string> resName;
+ // Path to script .so file on the device.
+ empirical_type<std::string> scriptDyLib;
+ // Directory where kernel objects are cached on device.
+ empirical_type<std::string> cacheDir;
+ // Pointer to the context which owns this script.
+ empirical_type<lldb::addr_t> context;
+ // Pointer to the script object itself.
+ empirical_type<lldb::addr_t> script;
+};
+
+// This Element class represents the Element object in RS,
+// defining the type associated with an Allocation.
+struct RenderScriptRuntime::Element
+{
+ // Taken from rsDefines.h
+ enum DataKind
+ {
+ RS_KIND_USER,
+ RS_KIND_PIXEL_L = 7,
+ RS_KIND_PIXEL_A,
+ RS_KIND_PIXEL_LA,
+ RS_KIND_PIXEL_RGB,
+ RS_KIND_PIXEL_RGBA,
+ RS_KIND_PIXEL_DEPTH,
+ RS_KIND_PIXEL_YUV,
+ RS_KIND_INVALID = 100
+ };
+
+ // Taken from rsDefines.h
+ enum DataType
+ {
+ RS_TYPE_NONE = 0,
+ RS_TYPE_FLOAT_16,
+ RS_TYPE_FLOAT_32,
+ RS_TYPE_FLOAT_64,
+ RS_TYPE_SIGNED_8,
+ RS_TYPE_SIGNED_16,
+ RS_TYPE_SIGNED_32,
+ RS_TYPE_SIGNED_64,
+ RS_TYPE_UNSIGNED_8,
+ RS_TYPE_UNSIGNED_16,
+ RS_TYPE_UNSIGNED_32,
+ RS_TYPE_UNSIGNED_64,
+ RS_TYPE_BOOLEAN,
+
+ RS_TYPE_UNSIGNED_5_6_5,
+ RS_TYPE_UNSIGNED_5_5_5_1,
+ RS_TYPE_UNSIGNED_4_4_4_4,
+
+ RS_TYPE_MATRIX_4X4,
+ RS_TYPE_MATRIX_3X3,
+ RS_TYPE_MATRIX_2X2,
+
+ RS_TYPE_ELEMENT = 1000,
+ RS_TYPE_TYPE,
+ RS_TYPE_ALLOCATION,
+ RS_TYPE_SAMPLER,
+ RS_TYPE_SCRIPT,
+ RS_TYPE_MESH,
+ RS_TYPE_PROGRAM_FRAGMENT,
+ RS_TYPE_PROGRAM_VERTEX,
+ RS_TYPE_PROGRAM_RASTER,
+ RS_TYPE_PROGRAM_STORE,
+ RS_TYPE_FONT,
+
+ RS_TYPE_INVALID = 10000
+ };
+
+ std::vector<Element> children; // Child Element fields for structs
+ empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS Element of the Type
+ empirical_type<DataType> type; // Type of each data pointer stored by the allocation
+ empirical_type<DataKind> type_kind; // Defines pixel type if Allocation is created from an image
+ empirical_type<uint32_t> type_vec_size; // Vector size of each data point, e.g '4' for uchar4
+ empirical_type<uint32_t> field_count; // Number of Subelements
+ empirical_type<uint32_t> datum_size; // Size of a single Element with padding
+ empirical_type<uint32_t> padding; // Number of padding bytes
+ empirical_type<uint32_t> array_size; // Number of items in array, only needed for strucrs
+ ConstString type_name; // Name of type, only needed for structs
+
+ static const ConstString &GetFallbackStructName(); // Print this as the type name of a struct Element
+ // If we can't resolve the actual struct name
+
+ bool shouldRefresh() const
+ {
+ const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0;
+ const bool valid_type = type.isValid() && type_vec_size.isValid() && type_kind.isValid();
+ return !valid_ptr || !valid_type || !datum_size.isValid();
+ }
+};
+
+// This AllocationDetails class collects data associated with a single
+// allocation instance.
+struct RenderScriptRuntime::AllocationDetails
+{
+ struct Dimension
+ {
+ uint32_t dim_1;
+ uint32_t dim_2;
+ uint32_t dim_3;
+ uint32_t cubeMap;
+
+ Dimension()
+ {
+ dim_1 = 0;
+ dim_2 = 0;
+ dim_3 = 0;
+ cubeMap = 0;
+ }
+ };
+
+ // The FileHeader struct specifies the header we use for writing allocations to a binary file.
+ // Our format begins with the ASCII characters "RSAD", identifying the file as an allocation dump.
+ // Member variables dims and hdr_size are then written consecutively, immediately followed by an instance of
+ // the ElementHeader struct. Because Elements can contain subelements, there may be more than one instance
+ // of the ElementHeader struct. With this first instance being the root element, and the other instances being
+ // the root's descendants. To identify which instances are an ElementHeader's children, each struct
+ // is immediately followed by a sequence of consecutive offsets to the start of its child structs.
+ // These offsets are 4 bytes in size, and the 0 offset signifies no more children.
+ struct FileHeader
+ {
+ uint8_t ident[4]; // ASCII 'RSAD' identifying the file
+ uint32_t dims[3]; // Dimensions
+ uint16_t hdr_size; // Header size in bytes, including all element headers
+ };
+
+ struct ElementHeader
+ {
+ uint16_t type; // DataType enum
+ uint32_t kind; // DataKind enum
+ uint32_t element_size; // Size of a single element, including padding
+ uint16_t vector_size; // Vector width
+ uint32_t array_size; // Number of elements in array
+ };
+
+ // Monotonically increasing from 1
+ static unsigned int ID;
+
+ // Maps Allocation DataType enum and vector size to printable strings
+ // using mapping from RenderScript numerical types summary documentation
+ static const char* RsDataTypeToString[][4];
+
+ // Maps Allocation DataKind enum to printable strings
+ static const char* RsDataKindToString[];
+
+ // Maps allocation types to format sizes for printing.
+ static const unsigned int RSTypeToFormat[][3];
+
+ // Give each allocation an ID as a way
+ // for commands to reference it.
+ const unsigned int id;
+
+ RenderScriptRuntime::Element element; // Allocation Element type
+ empirical_type<Dimension> dimension; // Dimensions of the Allocation
+ empirical_type<lldb::addr_t> address; // Pointer to address of the RS Allocation
+ empirical_type<lldb::addr_t> data_ptr; // Pointer to the data held by the Allocation
+ empirical_type<lldb::addr_t> type_ptr; // Pointer to the RS Type of the Allocation
+ empirical_type<lldb::addr_t> context; // Pointer to the RS Context of the Allocation
+ empirical_type<uint32_t> size; // Size of the allocation
+ empirical_type<uint32_t> stride; // Stride between rows of the allocation
+
+ // Give each allocation an id, so we can reference it in user commands.
+ AllocationDetails(): id(ID++)
+ {
+ }
+
+ bool shouldRefresh() const
+ {
+ bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0;
+ valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0;
+ return !valid_ptrs || !dimension.isValid() || !size.isValid() || element.shouldRefresh();
+ }
+};
+
+const ConstString &
+RenderScriptRuntime::Element::GetFallbackStructName()
+{
+ static const ConstString FallbackStructName("struct");
+ return FallbackStructName;
+}
+
+unsigned int RenderScriptRuntime::AllocationDetails::ID = 1;
+
+const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] =
+{
+ "User",
+ "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7
+ "Undefined", "Undefined", "Undefined",
+ "L Pixel",
+ "A Pixel",
+ "LA Pixel",
+ "RGB Pixel",
+ "RGBA Pixel",
+ "Pixel Depth",
+ "YUV Pixel"
+};
+
+const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] =
+{
+ {"None", "None", "None", "None"},
+ {"half", "half2", "half3", "half4"},
+ {"float", "float2", "float3", "float4"},
+ {"double", "double2", "double3", "double4"},
+ {"char", "char2", "char3", "char4"},
+ {"short", "short2", "short3", "short4"},
+ {"int", "int2", "int3", "int4"},
+ {"long", "long2", "long3", "long4"},
+ {"uchar", "uchar2", "uchar3", "uchar4"},
+ {"ushort", "ushort2", "ushort3", "ushort4"},
+ {"uint", "uint2", "uint3", "uint4"},
+ {"ulong", "ulong2", "ulong3", "ulong4"},
+ {"bool", "bool2", "bool3", "bool4"},
+ {"packed_565", "packed_565", "packed_565", "packed_565"},
+ {"packed_5551", "packed_5551", "packed_5551", "packed_5551"},
+ {"packed_4444", "packed_4444", "packed_4444", "packed_4444"},
+ {"rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4"},
+ {"rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3"},
+ {"rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2"},
+
+ // Handlers
+ {"RS Element", "RS Element", "RS Element", "RS Element"},
+ {"RS Type", "RS Type", "RS Type", "RS Type"},
+ {"RS Allocation", "RS Allocation", "RS Allocation", "RS Allocation"},
+ {"RS Sampler", "RS Sampler", "RS Sampler", "RS Sampler"},
+ {"RS Script", "RS Script", "RS Script", "RS Script"},
+
+ // Deprecated
+ {"RS Mesh", "RS Mesh", "RS Mesh", "RS Mesh"},
+ {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment", "RS Program Fragment"},
+ {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex", "RS Program Vertex"},
+ {"RS Program Raster", "RS Program Raster", "RS Program Raster", "RS Program Raster"},
+ {"RS Program Store", "RS Program Store", "RS Program Store", "RS Program Store"},
+ {"RS Font", "RS Font", "RS Font", "RS Font"}
+};
+
+// Used as an index into the RSTypeToFormat array elements
+enum TypeToFormatIndex {
+ eFormatSingle = 0,
+ eFormatVector,
+ eElementSize
+};
+
+// { format enum of single element, format enum of element vector, size of element}
+const unsigned int RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] =
+{
+ {eFormatHex, eFormatHex, 1}, // RS_TYPE_NONE
+ {eFormatFloat, eFormatVectorOfFloat16, 2}, // RS_TYPE_FLOAT_16
+ {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, // RS_TYPE_FLOAT_32
+ {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, // RS_TYPE_FLOAT_64
+ {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, // RS_TYPE_SIGNED_8
+ {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)}, // RS_TYPE_SIGNED_16
+ {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)}, // RS_TYPE_SIGNED_32
+ {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)}, // RS_TYPE_SIGNED_64
+ {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)}, // RS_TYPE_UNSIGNED_8
+ {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_16
+ {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)}, // RS_TYPE_UNSIGNED_32
+ {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)}, // RS_TYPE_UNSIGNED_64
+ {eFormatBoolean, eFormatBoolean, 1}, // RS_TYPE_BOOL
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_6_5
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_5_5_1
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_4_4_4_4
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 16}, // RS_TYPE_MATRIX_4X4
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9}, // RS_TYPE_MATRIX_3X3
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4} // RS_TYPE_MATRIX_2X2
+};
//------------------------------------------------------------------
// Static Functions
@@ -44,6 +403,47 @@ RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType languag
return NULL;
}
+// Callback with a module to search for matching symbols.
+// We first check that the module contains RS kernels.
+// Then look for a symbol which matches our kernel name.
+// The breakpoint address is finally set using the address of this symbol.
+Searcher::CallbackReturn
+RSBreakpointResolver::SearchCallback(SearchFilter &filter,
+ SymbolContext &context,
+ Address*,
+ bool)
+{
+ ModuleSP module = context.module_sp;
+
+ if (!module)
+ return Searcher::eCallbackReturnContinue;
+
+ // Is this a module containing renderscript kernels?
+ if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData))
+ return Searcher::eCallbackReturnContinue;
+
+ // Attempt to set a breakpoint on the kernel name symbol within the module library.
+ // If it's not found, it's likely debug info is unavailable - try to set a
+ // breakpoint on <name>.expand.
+
+ const Symbol* kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
+ if (!kernel_sym)
+ {
+ std::string kernel_name_expanded(m_kernel_name.AsCString());
+ kernel_name_expanded.append(".expand");
+ kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
+ }
+
+ if (kernel_sym)
+ {
+ Address bp_addr = kernel_sym->GetAddress();
+ if (filter.AddressPasses(bp_addr))
+ m_breakpoint->AddLocation(bp_addr);
+ }
+
+ return Searcher::eCallbackReturnContinue;
+}
+
void
RenderScriptRuntime::Initialize()
{
@@ -63,7 +463,7 @@ RenderScriptRuntime::GetPluginNameStatic()
return g_name;
}
-RenderScriptRuntime::ModuleKind
+RenderScriptRuntime::ModuleKind
RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)
{
if (module_sp)
@@ -88,7 +488,7 @@ RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)
return eModuleKindDriver;
}
- const ConstString rs_cpureflib("libRSCPURef.so");
+ const ConstString rs_cpureflib("libRSCpuRef.so");
if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib)
{
return eModuleKindImpl;
@@ -104,8 +504,7 @@ RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp)
return GetModuleKind(module_sp) != eModuleKindIgnored;
}
-
-void
+void
RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )
{
Mutex::Locker locker (module_list.GetMutex ());
@@ -121,7 +520,6 @@ RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )
}
}
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -145,11 +543,19 @@ RenderScriptRuntime::IsVTableName(const char *name)
bool
RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &address)
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type)
{
return false;
}
+TypeAndOrName
+RenderScriptRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name,
+ ValueObject& static_value)
+{
+ return type_and_or_name;
+}
+
bool
RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)
{
@@ -163,22 +569,78 @@ RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bo
return resolver_sp;
}
-
const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
{
//rsdScript
- {"rsdScriptInit", "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureScriptInit1},
- {"rsdScriptInvokeForEach", "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
- {"rsdScriptInvokeForEachMulti", "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
- {"rsdScriptInvokeFunction", "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
- {"rsdScriptSetGlobalVar", "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1},
+ {
+ "rsdScriptInit", //name
+ "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", // symbol name 32 bit
+ "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj", // symbol name 64 bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ &lldb_private::RenderScriptRuntime::CaptureScriptInit1 // handler
+ },
+ {
+ "rsdScriptInvokeForEach", // name
+ "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", // symbol name 32bit
+ "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvmPK12RsScriptCall", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ nullptr // handler
+ },
+ {
+ "rsdScriptInvokeForEachMulti", // name
+ "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", // symbol name 32bit
+ "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ nullptr // handler
+ },
+ {
+ "rsdScriptInvokeFunction", // name
+ "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", // symbol name 32bit
+ "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvm", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ nullptr // handler
+ },
+ {
+ "rsdScriptSetGlobalVar", // name
+ "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", // symbol name 32bit
+ "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1 // handler
+ },
//rsdAllocation
- {"rsdAllocationInit", "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureAllocationInit1},
- {"rsdAllocationRead2D", "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
+ {
+ "rsdAllocationInit", // name
+ "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 32bit
+ "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ &lldb_private::RenderScriptRuntime::CaptureAllocationInit1 // handler
+ },
+ {
+ "rsdAllocationRead2D", //name
+ "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", // symbol name 32bit
+ "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ nullptr // handler
+ },
+ {
+ "rsdAllocationDestroy", // name
+ "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", // symbol name 32bit
+ "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy // handler
+ },
};
-const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]);
+const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]);
bool
RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
@@ -189,143 +651,375 @@ RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, ll
RenderScriptRuntime *lang_rt = (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
lang_rt->HookCallback(hook_info, context);
-
+
return false;
}
-
-void
+void
RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& context)
{
Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if(log)
+ if (log)
log->Printf ("RenderScriptRuntime::HookCallback - '%s' .", hook_info->defn->name);
- if (hook_info->defn->grabber)
+ if (hook_info->defn->grabber)
{
(this->*(hook_info->defn->grabber))(hook_info, context);
}
}
-
bool
-RenderScriptRuntime::GetArg32Simple(ExecutionContext& context, uint32_t arg, uint32_t *data)
+RenderScriptRuntime::GetArgSimple(ExecutionContext &context, uint32_t arg, uint64_t *data)
{
- Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ // Get a positional integer argument.
+ // Given an ExecutionContext, ``context`` which should be a RenderScript
+ // frame, get the value of the positional argument ``arg`` and save its value
+ // to the address pointed to by ``data``.
+ // returns true on success, false otherwise.
+ // If unsuccessful, the value pointed to by ``data`` is undefined. Otherwise,
+ // ``data`` will be set to the value of the the given ``arg``.
+ // NOTE: only natural width integer arguments for the machine are supported.
+ // Behaviour with non primitive arguments is undefined.
if (!data)
return false;
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
Error error;
RegisterContext* reg_ctx = context.GetRegisterContext();
Process* process = context.GetProcessPtr();
+ bool success = false; // return value
- if (context.GetTargetPtr()->GetArchitecture().GetMachine() == llvm::Triple::ArchType::x86)
+ if (!context.GetTargetPtr())
{
- uint64_t sp = reg_ctx->GetSP();
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - Invalid target");
+
+ return false;
+ }
+
+ switch (context.GetTargetPtr()->GetArchitecture().GetMachine())
+ {
+ case llvm::Triple::ArchType::x86:
{
+ uint64_t sp = reg_ctx->GetSP();
uint32_t offset = (1 + arg) * sizeof(uint32_t);
- process->ReadMemory(sp + offset, data, sizeof(uint32_t), error);
- if(error.Fail())
+ uint32_t result = 0;
+ process->ReadMemory(sp + offset, &result, sizeof(uint32_t), error);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - error reading X86 stack: %s.", error.AsCString());
+ }
+ else
{
- if(log)
- log->Printf ("RenderScriptRuntime:: GetArg32Simple - error reading X86 stack: %s.", error.AsCString());
+ *data = result;
+ success = true;
}
+ break;
}
- }
- else if (context.GetTargetPtr()->GetArchitecture().GetMachine() == llvm::Triple::ArchType::arm)
- {
- if (arg < 4)
+ case llvm::Triple::ArchType::x86_64:
{
- const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
+ // amd64 has 6 integer registers, and 8 XMM registers for parameter passing.
+ // Surplus args are spilled onto the stack.
+ // rdi, rsi, rdx, rcx, r8, r9, (zmm0 - 7 for vectors)
+ // ref: AMD64 ABI Draft 0.99.6 – October 7, 2013 – 10:35; Figure 3.4. Retrieved from
+ // http://www.x86-64.org/documentation/abi.pdf
+ if (arg > 5)
+ {
+ if (log)
+ log->Warning("X86_64 register spill is not supported.");
+ break;
+ }
+ const char * regnames[] = {"rdi", "rsi", "rdx", "rcx", "r8", "r9"};
+ assert((sizeof(regnames) / sizeof(const char *)) > arg);
+ const RegisterInfo *rArg = reg_ctx->GetRegisterInfoByName(regnames[arg]);
RegisterValue rVal;
- reg_ctx->ReadRegister(rArg, rVal);
- (*data) = rVal.GetAsUInt32();
+ success = reg_ctx->ReadRegister(rArg, rVal);
+ if (success)
+ {
+ *data = rVal.GetAsUInt64(0u, &success);
+ }
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - error reading x86_64 register: %d.", arg);
+ }
+ break;
}
- else
+ case llvm::Triple::ArchType::arm:
{
- uint64_t sp = reg_ctx->GetSP();
+ // arm 32 bit
+ // first 4 arguments are passed via registers
+ if (arg < 4)
{
+ const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
+ RegisterValue rVal;
+ success = reg_ctx->ReadRegister(rArg, rVal);
+ if (success)
+ {
+ (*data) = rVal.GetAsUInt32(0u, &success);
+ }
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - error reading ARM register: %d.", arg);
+ }
+ }
+ else
+ {
+ uint64_t sp = reg_ctx->GetSP();
uint32_t offset = (arg-4) * sizeof(uint32_t);
- process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error);
- if(error.Fail())
+ uint32_t value = 0;
+ size_t bytes_read = process->ReadMemory(sp + offset, &value, sizeof(value), error);
+ if (error.Fail() || bytes_read != sizeof(value))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - error reading ARM stack: %s.", error.AsCString());
+ }
+ else
{
- if(log)
- log->Printf ("RenderScriptRuntime:: GetArg32Simple - error reading ARM stack: %s.", error.AsCString());
+ *data = value;
+ success = true;
}
}
- }
+ break;
+ }
+ case llvm::Triple::ArchType::aarch64:
+ {
+ // arm 64 bit
+ // first 8 arguments are in the registers
+ if (arg < 8)
+ {
+ const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
+ RegisterValue rVal;
+ success = reg_ctx->ReadRegister(rArg, rVal);
+ if (success)
+ {
+ *data = rVal.GetAsUInt64(0u, &success);
+ }
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple() - AARCH64 - Error while reading the argument #%d", arg);
+ }
+ }
+ else
+ {
+ // @TODO: need to find the argument in the stack
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - AARCH64 - FOR #ARG >= 8 NOT IMPLEMENTED YET. Argument number: %d", arg);
+ }
+ break;
+ }
+ case llvm::Triple::ArchType::mipsel:
+ {
+ // read from the registers
+ // first 4 arguments are passed in registers
+ if (arg < 4){
+ const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4);
+ RegisterValue rVal;
+ success = reg_ctx->ReadRegister(rArg, rVal);
+ if (success)
+ {
+ *data = rVal.GetAsUInt64(0u, &success);
+ }
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple() - Mips - Error while reading the argument #%d", arg);
+ }
+ }
+ // arguments > 4 are read from the stack
+ else
+ {
+ uint64_t sp = reg_ctx->GetSP();
+ uint32_t offset = arg * sizeof(uint32_t);
+ uint32_t value = 0;
+ size_t bytes_read = process->ReadMemory(sp + offset, &value, sizeof(value), error);
+ if (error.Fail() || bytes_read != sizeof(value))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - error reading Mips stack: %s.", error.AsCString());
+ }
+ else
+ {
+ *data = value;
+ success = true;
+ }
+ }
+ break;
+ }
+ case llvm::Triple::ArchType::mips64el:
+ {
+ // read from the registers
+ if (arg < 8)
+ {
+ const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4);
+ RegisterValue rVal;
+ success = reg_ctx->ReadRegister(rArg, rVal);
+ if (success)
+ {
+ (*data) = rVal.GetAsUInt64(0u, &success);
+ }
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading the argument #%d", arg);
+ }
+ }
+ // arguments > 8 are read from the stack
+ else
+ {
+ uint64_t sp = reg_ctx->GetSP();
+ uint32_t offset = (arg - 8) * sizeof(uint64_t);
+ uint64_t value = 0;
+ size_t bytes_read = process->ReadMemory(sp + offset, &value, sizeof(value), error);
+ if (error.Fail() || bytes_read != sizeof(value))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading Mips64 stack: %s.", error.AsCString());
+ }
+ else
+ {
+ *data = value;
+ success = true;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ // invalid architecture
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported");
+ }
}
- return true;
+
+ if (!success)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - failed to get argument at index %" PRIu32, arg);
+ }
+ return success;
}
-void
+void
RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context)
{
Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
+
//Context, Script, int, data, length
- Error error;
-
- uint32_t rs_context_u32 = 0U;
- uint32_t rs_script_u32 = 0U;
- uint32_t rs_id_u32 = 0U;
- uint32_t rs_data_u32 = 0U;
- uint32_t rs_length_u32 = 0U;
+ uint64_t rs_context_u64 = 0U;
+ uint64_t rs_script_u64 = 0U;
+ uint64_t rs_id_u64 = 0U;
+ uint64_t rs_data_u64 = 0U;
+ uint64_t rs_length_u64 = 0U;
- std::string resname;
- std::string cachedir;
+ bool success =
+ GetArgSimple(context, 0, &rs_context_u64) &&
+ GetArgSimple(context, 1, &rs_script_u64) &&
+ GetArgSimple(context, 2, &rs_id_u64) &&
+ GetArgSimple(context, 3, &rs_data_u64) &&
+ GetArgSimple(context, 4, &rs_length_u64);
+
+ if (!success)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters");
+ return;
+ }
- GetArg32Simple(context, 0, &rs_context_u32);
- GetArg32Simple(context, 1, &rs_script_u32);
- GetArg32Simple(context, 2, &rs_id_u32);
- GetArg32Simple(context, 3, &rs_data_u32);
- GetArg32Simple(context, 4, &rs_length_u32);
-
- if(log)
+ if (log)
{
log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.",
- (uint64_t)rs_context_u32, (uint64_t)rs_script_u32, (uint64_t)rs_id_u32, (uint64_t)rs_data_u32, (uint64_t)rs_length_u32);
+ rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64);
- addr_t script_addr = (addr_t)rs_script_u32;
+ addr_t script_addr = (addr_t)rs_script_u64;
if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end())
{
auto rsm = m_scriptMappings[script_addr];
- if (rs_id_u32 < rsm->m_globals.size())
+ if (rs_id_u64 < rsm->m_globals.size())
{
- auto rsg = rsm->m_globals[rs_id_u32];
- log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(),
+ auto rsg = rsm->m_globals[rs_id_u64];
+ log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(),
rsm->m_module->GetFileSpec().GetFilename().AsCString());
}
}
}
}
-void
+void
RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context)
{
Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
+
//Context, Alloc, bool
- Error error;
-
- uint32_t rs_context_u32 = 0U;
- uint32_t rs_alloc_u32 = 0U;
- uint32_t rs_forceZero_u32 = 0U;
-
- GetArg32Simple(context, 0, &rs_context_u32);
- GetArg32Simple(context, 1, &rs_alloc_u32);
- GetArg32Simple(context, 2, &rs_forceZero_u32);
-
- if(log)
+ uint64_t rs_context_u64 = 0U;
+ uint64_t rs_alloc_u64 = 0U;
+ uint64_t rs_forceZero_u64 = 0U;
+
+ bool success =
+ GetArgSimple(context, 0, &rs_context_u64) &&
+ GetArgSimple(context, 1, &rs_alloc_u64) &&
+ GetArgSimple(context, 2, &rs_forceZero_u64);
+ if (!success) // error case
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters");
+ return; // abort
+ }
+
+ if (log)
log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
- (uint64_t)rs_context_u32, (uint64_t)rs_alloc_u32, (uint64_t)rs_forceZero_u32);
+ rs_context_u64, rs_alloc_u64, rs_forceZero_u64);
+
+ AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true);
+ if (alloc)
+ alloc->context = rs_context_u64;
}
-void
+void
+RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook* hook_info, ExecutionContext& context)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // Context, Alloc
+ uint64_t rs_context_u64 = 0U;
+ uint64_t rs_alloc_u64 = 0U;
+
+ bool success = GetArgSimple(context, 0, &rs_context_u64) && GetArgSimple(context, 1, &rs_alloc_u64);
+ if (!success) // error case
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Error while reading the function parameters");
+ return; // abort
+ }
+
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - 0x%" PRIx64 ", 0x%" PRIx64 ".",
+ rs_context_u64, rs_alloc_u64);
+
+ for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter)
+ {
+ auto& allocation_ap = *iter; // get the unique pointer
+ if (allocation_ap->address.isValid() && *allocation_ap->address.get() == rs_alloc_u64)
+ {
+ m_allocations.erase(iter);
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Deleted allocation entry");
+ return;
+ }
+ }
+
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Couldn't find destroyed allocation");
+}
+
+void
RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context)
{
Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
@@ -334,64 +1028,72 @@ RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext
Error error;
Process* process = context.GetProcessPtr();
- uint32_t rs_context_u32 = 0U;
- uint32_t rs_script_u32 = 0U;
- uint32_t rs_resnameptr_u32 = 0U;
- uint32_t rs_cachedirptr_u32 = 0U;
+ uint64_t rs_context_u64 = 0U;
+ uint64_t rs_script_u64 = 0U;
+ uint64_t rs_resnameptr_u64 = 0U;
+ uint64_t rs_cachedirptr_u64 = 0U;
std::string resname;
std::string cachedir;
- GetArg32Simple(context, 0, &rs_context_u32);
- GetArg32Simple(context, 1, &rs_script_u32);
- GetArg32Simple(context, 2, &rs_resnameptr_u32);
- GetArg32Simple(context, 3, &rs_cachedirptr_u32);
+ // read the function parameters
+ bool success =
+ GetArgSimple(context, 0, &rs_context_u64) &&
+ GetArgSimple(context, 1, &rs_script_u64) &&
+ GetArgSimple(context, 2, &rs_resnameptr_u64) &&
+ GetArgSimple(context, 3, &rs_cachedirptr_u64);
+
+ if (!success)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters");
+ return;
+ }
- process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u32, resname, error);
+ process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error);
if (error.Fail())
{
- if(log)
+ if (log)
log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString());
-
+
}
- process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u32, cachedir, error);
+ process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error);
if (error.Fail())
{
- if(log)
- log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString());
+ if (log)
+ log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString());
}
-
+
if (log)
log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
- (uint64_t)rs_context_u32, (uint64_t)rs_script_u32, resname.c_str(), cachedir.c_str());
+ rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str());
if (resname.size() > 0)
{
StreamString strm;
strm.Printf("librs.%s.so", resname.c_str());
- ScriptDetails script;
- script.cachedir = cachedir;
- script.resname = resname;
- script.scriptDyLib.assign(strm.GetData());
- script.script = rs_script_u32;
- script.context = rs_context_u32;
-
- m_scripts.push_back(script);
+ ScriptDetails* script = LookUpScript(rs_script_u64, true);
+ if (script)
+ {
+ script->type = ScriptDetails::eScriptC;
+ script->cacheDir = cachedir;
+ script->resName = resname;
+ script->scriptDyLib = strm.GetData();
+ script->context = addr_t(rs_context_u64);
+ }
if (log)
log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".",
- strm.GetData(), (uint64_t)rs_context_u32, (uint64_t)rs_script_u32);
- }
+ strm.GetData(), rs_context_u64, rs_script_u64);
+ }
else if (log)
{
log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged");
}
-
}
-
void
RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
{
@@ -402,16 +1104,24 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
return;
}
- if ((GetProcess()->GetTarget().GetArchitecture().GetMachine() != llvm::Triple::ArchType::x86)
- && (GetProcess()->GetTarget().GetArchitecture().GetMachine() != llvm::Triple::ArchType::arm))
+ Target &target = GetProcess()->GetTarget();
+ llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
+
+ if (targetArchType != llvm::Triple::ArchType::x86
+ && targetArchType != llvm::Triple::ArchType::arm
+ && targetArchType != llvm::Triple::ArchType::aarch64
+ && targetArchType != llvm::Triple::ArchType::mipsel
+ && targetArchType != llvm::Triple::ArchType::mips64el
+ && targetArchType != llvm::Triple::ArchType::x86_64
+ )
{
if (log)
- log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM supported currently.");
+ log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM, Mips supported currently.");
return;
}
- Target &target = GetProcess()->GetTarget();
+ uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
for (size_t idx = 0; idx < s_runtimeHookCount; idx++)
{
@@ -420,16 +1130,29 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
continue;
}
- const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(hook_defn->symbol_name), eSymbolTypeCode);
+ const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64;
+
+ const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode);
+ if (!sym){
+ if (log){
+ log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name);
+ }
+ continue;
+ }
addr_t addr = sym->GetLoadAddress(&target);
if (addr == LLDB_INVALID_ADDRESS)
{
- if(log)
- log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.",
- hook_defn->name, hook_defn->symbol_name);
+ if (log)
+ log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.",
+ hook_defn->name, symbol_name);
continue;
}
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr);
+ }
RuntimeHookSP hook(new RuntimeHook());
hook->address = addr;
@@ -439,7 +1162,7 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
m_runtimeHooks[addr] = hook;
if (log)
{
- log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".",
+ log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".",
hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr);
}
}
@@ -455,35 +1178,1193 @@ RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)
const ModuleSP module = rsmodule_sp->m_module;
const FileSpec& file = module->GetPlatformFileSpec();
-
- for (const auto &rs_script : m_scripts)
+
+ // Iterate over all of the scripts that we currently know of.
+ // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
+ for (const auto & rs_script : m_scripts)
{
- if (file.GetFilename() == ConstString(rs_script.scriptDyLib.c_str()))
+ // Extract the expected .so file path for this script.
+ std::string dylib;
+ if (!rs_script->scriptDyLib.get(dylib))
+ continue;
+
+ // Only proceed if the module that has loaded corresponds to this script.
+ if (file.GetFilename() != ConstString(dylib.c_str()))
+ continue;
+
+ // Obtain the script address which we use as a key.
+ lldb::addr_t script;
+ if (!rs_script->script.get(script))
+ continue;
+
+ // If we have a script mapping for the current script.
+ if (m_scriptMappings.find(script) != m_scriptMappings.end())
{
- if (m_scriptMappings.find( rs_script.script ) != m_scriptMappings.end())
+ // if the module we have stored is different to the one we just received.
+ if (m_scriptMappings[script] != rsmodule_sp)
{
- if (m_scriptMappings[rs_script.script] != rsmodule_sp)
+ if (log)
+ log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
+ (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+ // We don't have a script mapping for the current script.
+ else
+ {
+ // Obtain the script resource name.
+ std::string resName;
+ if (rs_script->resName.get(resName))
+ // Set the modules resource name.
+ rsmodule_sp->m_resname = resName;
+ // Add Script/Module pair to map.
+ m_scriptMappings[script] = rsmodule_sp;
+ if (log)
+ log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
+ (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+}
+
+// Uses the Target API to evaluate the expression passed as a parameter to the function
+// The result of that expression is returned an unsigned 64 bit int, via the result* paramter.
+// Function returns true on success, and false on failure
+bool
+RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ if (log)
+ log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression);
+
+ ValueObjectSP expr_result;
+ // Perform the actual expression evaluation
+ GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result);
+
+ if (!expr_result)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't evaluate expression");
+ return false;
+ }
+
+ // The result of the expression is invalid
+ if (!expr_result->GetError().Success())
+ {
+ Error err = expr_result->GetError();
+ if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void");
+
+ result = nullptr;
+ return true;
+ }
+
+ if (log)
+ log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString());
+ return false;
+ }
+
+ bool success = false;
+ *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int.
+
+ if (!success)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't convert expression result to unsigned int");
+ return false;
+ }
+
+ return true;
+}
+
+namespace // anonymous
+{
+ // max length of an expanded expression
+ const int jit_max_expr_size = 768;
+
+ // Format strings containing the expressions we may need to evaluate.
+ const char runtimeExpressions[][256] =
+ {
+ // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
+ "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)",
+
+ // Type* rsaAllocationGetType(Context*, Allocation*)
+ "(void*)rsaAllocationGetType(0x%lx, 0x%lx)",
+
+ // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
+ // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
+ // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
+ // Need to specify 32 or 64 bit for uint_t since this differs between devices
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr
+
+ // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
+ // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]", // Vector Size
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[4]", // Field Count
+
+ // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names,
+ // size_t *arraySizes, uint32_t dataSize)
+ // Needed for Allocations of structs to gather details about fields/Subelements
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); ids[%u]", // Element* of field
+
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); names[%u]", // Name of field
+
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); arr_size[%u]" // Array size of field
+ };
+
+
+ // Temporary workaround for MIPS, until the compiler emits the JAL instruction when invoking directly the function.
+ // At the moment, when evaluating an expression involving a function call, the LLVM codegen for Mips emits a JAL
+ // instruction, which is able to jump in the range +/- 128MB with respect to the current program counter ($pc). If
+ // the requested function happens to reside outside the above region, the function address will be truncated and the
+ // function invocation will fail. This is a problem in the RS plugin as we rely on the RS API to probe the number and
+ // the nature of allocations. A proper solution in the MIPS compiler is currently being investigated. As temporary
+ // work around for this context, we'll invoke the RS API through function pointers, which cause the compiler to emit a
+ // register based JALR instruction.
+ const char runtimeExpressions_mips[][512] =
+ {
+ // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
+ "int* (*f) (void*, int, int, int, int, int) = (int* (*) (void*, int, int, int, int, int)) "
+ "_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace; "
+ "(int*) f((void*) 0x%lx, %u, %u, %u, 0, 0)",
+
+ // Type* rsaAllocationGetType(Context*, Allocation*)
+ "void* (*f) (void*, void*) = (void* (*) (void*, void*)) rsaAllocationGetType; (void*) f((void*) 0x%lx, (void*) 0x%lx)",
+
+ // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
+ // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
+ // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
+ // Need to specify 32 or 64 bit for uint_t since this differs between devices
+ "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) "
+ "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[0]",
+ "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) "
+ "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[1]",
+ "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) "
+ "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[2]",
+ "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) "
+ "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[5]",
+
+ // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
+ // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
+ "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) "
+ "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[0]", // Type
+ "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) "
+ "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[1]", // Kind
+ "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) "
+ "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[3]", // Vector size
+ "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) "
+ "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[4]", // Field count
+
+ // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names,
+ // size_t *arraySizes, uint32_t dataSize)
+ // Needed for Allocations of structs to gather details about fields/Subelements
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = "
+ "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;"
+ "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);"
+ "ids[%u]", // Element* of field
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = "
+ "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;"
+ "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);"
+ "names[%u]", // Name of field
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = "
+ "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;"
+ "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);"
+ "arr_size[%u]" // Array size of field
+ };
+
+} // end of the anonymous namespace
+
+
+// Retrieve the string to JIT for the given expression
+const char*
+RenderScriptRuntime::JITTemplate(ExpressionStrings e)
+{
+ // be nice to your Mips friend when adding new expression strings
+ static_assert(sizeof(runtimeExpressions)/sizeof(runtimeExpressions[0]) ==
+ sizeof(runtimeExpressions_mips)/sizeof(runtimeExpressions_mips[0]),
+ "#runtimeExpressions != #runtimeExpressions_mips");
+
+ assert((e >= eExprGetOffsetPtr && e <= eExprSubelementsArrSize) &&
+ "Expression string out of bounds");
+
+ llvm::Triple::ArchType arch = GetTargetRef().GetArchitecture().GetMachine();
+
+ // mips JAL workaround
+ if(arch == llvm::Triple::ArchType::mips64el || arch == llvm::Triple::ArchType::mipsel)
+ return runtimeExpressions_mips[e];
+ else
+ return runtimeExpressions[e];
+}
+
+
+// JITs the RS runtime for the internal data pointer of an allocation.
+// Is passed x,y,z coordinates for the pointer to a specific element.
+// Then sets the data_ptr member in Allocation with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
+ unsigned int x, unsigned int y, unsigned int z)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!allocation->address.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details");
+ return false;
+ }
+
+ const char* expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
+
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), x, y, z);
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long");
+ return false;
+ }
+
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
+
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ allocation->data_ptr = mem_ptr;
+
+ return true;
+}
+
+// JITs the RS runtime for the internal pointer to the RS Type of an allocation
+// Then sets the type_ptr member in Allocation with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!allocation->address.isValid() || !allocation->context.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details");
+ return false;
+ }
+
+ const char* expr_cstr = JITTemplate(eExprAllocGetType);
+ char buffer[jit_max_expr_size];
+
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get());
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long");
+ return false;
+ }
+
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
+
+ addr_t type_ptr = static_cast<lldb::addr_t>(result);
+ allocation->type_ptr = type_ptr;
+
+ return true;
+}
+
+// JITs the RS runtime for information about the dimensions and type of an allocation
+// Then sets dimension and element_ptr members in Allocation with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!allocation->type_ptr.isValid() || !allocation->context.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details");
+ return false;
+ }
+
+ // Expression is different depending on if device is 32 or 64 bit
+ uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+ const unsigned int bits = archByteSize == 4 ? 32 : 64;
+
+ // We want 4 elements from packed data
+ const unsigned int num_exprs = 4;
+ assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions");
+
+ char buffer[num_exprs][jit_max_expr_size];
+ uint64_t results[num_exprs];
+
+ for (unsigned int i = 0; i < num_exprs; ++i)
+ {
+ const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprTypeDimX + i));
+ int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, bits,
+ *allocation->context.get(), *allocation->type_ptr.get());
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long");
+ return false;
+ }
+
+ // Perform expression evaluation
+ if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
+ return false;
+ }
+
+ // Assign results to allocation members
+ AllocationDetails::Dimension dims;
+ dims.dim_1 = static_cast<uint32_t>(results[0]);
+ dims.dim_2 = static_cast<uint32_t>(results[1]);
+ dims.dim_3 = static_cast<uint32_t>(results[2]);
+ allocation->dimension = dims;
+
+ addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
+ allocation->element.element_ptr = elem_ptr;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64,
+ dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
+
+ return true;
+}
+
+// JITs the RS runtime for information about the Element of an allocation
+// Then sets type, type_vec_size, field_count and type_kind members in Element with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!elem.element_ptr.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details");
+ return false;
+ }
+
+ // We want 4 elements from packed data
+ const unsigned int num_exprs = 4;
+ assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) && "Invalid number of expressions");
+
+ char buffer[num_exprs][jit_max_expr_size];
+ uint64_t results[num_exprs];
+
+ for (unsigned int i = 0; i < num_exprs; i++)
+ {
+ const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprElementType + i));
+ int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, context, *elem.element_ptr.get());
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITElementPacked - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long");
+ return false;
+ }
+
+ // Perform expression evaluation
+ if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
+ return false;
+ }
+
+ // Assign results to allocation members
+ elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]);
+ elem.type_kind = static_cast<RenderScriptRuntime::Element::DataKind>(results[1]);
+ elem.type_vec_size = static_cast<uint32_t>(results[2]);
+ elem.field_count = static_cast<uint32_t>(results[3]);
+
+ if (log)
+ log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u, field count %u",
+ *elem.type.get(), *elem.type_kind.get(), *elem.type_vec_size.get(), *elem.field_count.get());
+
+ // If this Element has subelements then JIT rsaElementGetSubElements() for details about its fields
+ if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr))
+ return false;
+
+ return true;
+}
+
+// JITs the RS runtime for information about the subelements/fields of a struct allocation
+// This is necessary for infering the struct type so we can pretty print the allocation's contents.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!elem.element_ptr.isValid() || !elem.field_count.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITSubelements - Failed to find allocation details");
+ return false;
+ }
+
+ const short num_exprs = 3;
+ assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) && "Invalid number of expressions");
+
+ char expr_buffer[jit_max_expr_size];
+ uint64_t results;
+
+ // Iterate over struct fields.
+ const uint32_t field_count = *elem.field_count.get();
+ for (unsigned int field_index = 0; field_index < field_count; ++field_index)
+ {
+ Element child;
+ for (unsigned int expr_index = 0; expr_index < num_exprs; ++expr_index)
+ {
+ const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprSubelementsId + expr_index));
+ int chars_written = snprintf(expr_buffer, jit_max_expr_size, expr_cstr,
+ field_count, field_count, field_count,
+ context, *elem.element_ptr.get(), field_count, field_index);
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITSubelements - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITSubelements - Expression too long");
+ return false;
+ }
+
+ // Perform expression evaluation
+ if (!EvalRSExpression(expr_buffer, frame_ptr, &results))
+ return false;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::JITSubelements - Expr result 0x%" PRIx64, results);
+
+ switch(expr_index)
+ {
+ case 0: // Element* of child
+ child.element_ptr = static_cast<addr_t>(results);
+ break;
+ case 1: // Name of child
{
- if (log)
+ lldb::addr_t address = static_cast<addr_t>(results);
+ Error err;
+ std::string name;
+ GetProcess()->ReadCStringFromMemory(address, name, err);
+ if (!err.Fail())
+ child.type_name = ConstString(name);
+ else
{
- log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
- (uint64_t)rs_script.script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+ if (log)
+ log->Printf("RenderScriptRuntime::JITSubelements - Warning: Couldn't read field name");
}
+ break;
}
+ case 2: // Array size of child
+ child.array_size = static_cast<uint32_t>(results);
+ break;
}
- else
+ }
+
+ // We need to recursively JIT each Element field of the struct since
+ // structs can be nested inside structs.
+ if (!JITElementPacked(child, context, frame_ptr))
+ return false;
+ elem.children.push_back(child);
+ }
+
+ // Try to infer the name of the struct type so we can pretty print the allocation contents.
+ FindStructTypeName(elem, frame_ptr);
+
+ return true;
+}
+
+// JITs the RS runtime for the address of the last element in the allocation.
+// The `elem_size` paramter represents the size of a single element, including padding.
+// Which is needed as an offset from the last element pointer.
+// Using this offset minus the starting address we can calculate the size of the allocation.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!allocation->address.isValid() || !allocation->dimension.isValid()
+ || !allocation->data_ptr.isValid() || !allocation->element.datum_size.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details");
+ return false;
+ }
+
+ // Find dimensions
+ unsigned int dim_x = allocation->dimension.get()->dim_1;
+ unsigned int dim_y = allocation->dimension.get()->dim_2;
+ unsigned int dim_z = allocation->dimension.get()->dim_3;
+
+ // Our plan of jitting the last element address doesn't seem to work for struct Allocations
+ // Instead try to infer the size ourselves without any inter element padding.
+ if (allocation->element.children.size() > 0)
+ {
+ if (dim_x == 0) dim_x = 1;
+ if (dim_y == 0) dim_y = 1;
+ if (dim_z == 0) dim_z = 1;
+
+ allocation->size = dim_x * dim_y * dim_z * *allocation->element.datum_size.get();
+
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationSize - Infered size of struct allocation %u", *allocation->size.get());
+
+ return true;
+ }
+
+ const char* expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
+
+ // Calculate last element
+ dim_x = dim_x == 0 ? 0 : dim_x - 1;
+ dim_y = dim_y == 0 ? 0 : dim_y - 1;
+ dim_z = dim_z == 0 ? 0 : dim_z - 1;
+
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(),
+ dim_x, dim_y, dim_z);
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationSize - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long");
+ return false;
+ }
+
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
+
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ // Find pointer to last element and add on size of an element
+ allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + *allocation->element.datum_size.get();
+
+ return true;
+}
+
+// JITs the RS runtime for information about the stride between rows in the allocation.
+// This is done to detect padding, since allocated memory is 16-byte aligned.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!allocation->address.isValid() || !allocation->data_ptr.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationStride - Failed to find allocation details");
+ return false;
+ }
+
+ const char* expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
+
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(),
+ 0, 1, 0);
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationStride - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationStride - Expression too long");
+ return false;
+ }
+
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
+
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get());
+
+ return true;
+}
+
+// JIT all the current runtime info regarding an allocation
+bool
+RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ // GetOffsetPointer()
+ if (!JITDataPointer(allocation, frame_ptr))
+ return false;
+
+ // rsaAllocationGetType()
+ if (!JITTypePointer(allocation, frame_ptr))
+ return false;
+
+ // rsaTypeGetNativeData()
+ if (!JITTypePacked(allocation, frame_ptr))
+ return false;
+
+ // rsaElementGetNativeData()
+ if (!JITElementPacked(allocation->element, *allocation->context.get(), frame_ptr))
+ return false;
+
+ // Sets the datum_size member in Element
+ SetElementSize(allocation->element);
+
+ // Use GetOffsetPointer() to infer size of the allocation
+ if (!JITAllocationSize(allocation, frame_ptr))
+ return false;
+
+ return true;
+}
+
+// Function attempts to set the type_name member of the paramaterised Element object.
+// This string should be the name of the struct type the Element represents.
+// We need this string for pretty printing the Element to users.
+void
+RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!elem.type_name.IsEmpty()) // Name already set
+ return;
+ else
+ elem.type_name = Element::GetFallbackStructName(); // Default type name if we don't succeed
+
+ // Find all the global variables from the script rs modules
+ VariableList variable_list;
+ for (auto module_sp : m_rsmodules)
+ module_sp->m_module->FindGlobalVariables(RegularExpression("."), true, UINT32_MAX, variable_list);
+
+ // Iterate over all the global variables looking for one with a matching type to the Element.
+ // We make the assumption a match exists since there needs to be a global variable to reflect the
+ // struct type back into java host code.
+ for (uint32_t var_index = 0; var_index < variable_list.GetSize(); ++var_index)
+ {
+ const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index));
+ if (!var_sp)
+ continue;
+
+ ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp);
+ if (!valobj_sp)
+ continue;
+
+ // Find the number of variable fields.
+ // If it has no fields, or more fields than our Element, then it can't be the struct we're looking for.
+ // Don't check for equality since RS can add extra struct members for padding.
+ size_t num_children = valobj_sp->GetNumChildren();
+ if (num_children > elem.children.size() || num_children == 0)
+ continue;
+
+ // Iterate over children looking for members with matching field names.
+ // If all the field names match, this is likely the struct we want.
+ //
+ // TODO: This could be made more robust by also checking children data sizes, or array size
+ bool found = true;
+ for (size_t child_index = 0; child_index < num_children; ++child_index)
+ {
+ ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index, true);
+ if (!child || (child->GetName() != elem.children[child_index].type_name))
{
- m_scriptMappings[rs_script.script] = rsmodule_sp;
- rsmodule_sp->m_resname = rs_script.resname;
- if (log)
- {
- log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
- (uint64_t)rs_script.script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
- }
+ found = false;
+ break;
}
}
+
+ // RS can add extra struct members for padding in the format '#rs_padding_[0-9]+'
+ if (found && num_children < elem.children.size())
+ {
+ const unsigned int size_diff = elem.children.size() - num_children;
+ if (log)
+ log->Printf("RenderScriptRuntime::FindStructTypeName - %u padding struct entries", size_diff);
+
+ for (unsigned int padding_index = 0; padding_index < size_diff; ++padding_index)
+ {
+ const ConstString& name = elem.children[num_children + padding_index].type_name;
+ if (strcmp(name.AsCString(), "#rs_padding") < 0)
+ found = false;
+ }
+ }
+
+ // We've found a global var with matching type
+ if (found)
+ {
+ // Dereference since our Element type isn't a pointer.
+ if (valobj_sp->IsPointerType())
+ {
+ Error err;
+ ValueObjectSP deref_valobj = valobj_sp->Dereference(err);
+ if (!err.Fail())
+ valobj_sp = deref_valobj;
+ }
+
+ // Save name of variable in Element.
+ elem.type_name = valobj_sp->GetTypeName();
+ if (log)
+ log->Printf("RenderScriptRuntime::FindStructTypeName - Element name set to %s", elem.type_name.AsCString());
+
+ return;
+ }
}
-
+}
+
+// Function sets the datum_size member of Element. Representing the size of a single instance including padding.
+// Assumes the relevant allocation information has already been jitted.
+void
+RenderScriptRuntime::SetElementSize(Element& elem)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ const Element::DataType type = *elem.type.get();
+ assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT
+ && "Invalid allocation type");
+
+ const unsigned int vec_size = *elem.type_vec_size.get();
+ unsigned int data_size = 0;
+ unsigned int padding = 0;
+
+ // Element is of a struct type, calculate size recursively.
+ if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0))
+ {
+ for (Element& child : elem.children)
+ {
+ SetElementSize(child);
+ const unsigned int array_size = child.array_size.isValid() ? *child.array_size.get() : 1;
+ data_size += *child.datum_size.get() * array_size;
+ }
+ }
+ else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 || type == Element::RS_TYPE_UNSIGNED_5_5_5_1 ||
+ type == Element::RS_TYPE_UNSIGNED_4_4_4_4) // These have been packed already
+ {
+ data_size = AllocationDetails::RSTypeToFormat[type][eElementSize];
+ }
+ else if (type < Element::RS_TYPE_ELEMENT)
+ {
+ data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
+ if (vec_size == 3)
+ padding = AllocationDetails::RSTypeToFormat[type][eElementSize];
+ }
+ else
+ data_size = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+
+ elem.padding = padding;
+ elem.datum_size = data_size + padding;
+ if (log)
+ log->Printf("RenderScriptRuntime::SetElementSize - element size set to %u", data_size + padding);
+}
+
+// Given an allocation, this function copies the allocation contents from device into a buffer on the heap.
+// Returning a shared pointer to the buffer containing the data.
+std::shared_ptr<uint8_t>
+RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // JIT all the allocation details
+ if (allocation->shouldRefresh())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetAllocationData - Allocation details not calculated yet, jitting info");
+
+ if (!RefreshAllocation(allocation, frame_ptr))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't JIT allocation details");
+ return nullptr;
+ }
+ }
+
+ assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() && allocation->element.type_vec_size.isValid()
+ && allocation->size.isValid() && "Allocation information not available");
+
+ // Allocate a buffer to copy data into
+ const unsigned int size = *allocation->size.get();
+ std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
+ if (!buffer)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't allocate a %u byte buffer", size);
+ return nullptr;
+ }
+
+ // Read the inferior memory
+ Error error;
+ lldb::addr_t data_ptr = *allocation->data_ptr.get();
+ GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetAllocationData - '%s' Couldn't read %u bytes of allocation data from 0x%" PRIx64,
+ error.AsCString(), size, data_ptr);
+ return nullptr;
+ }
+
+ return buffer;
+}
+
+// Function copies data from a binary file into an allocation.
+// There is a header at the start of the file, FileHeader, before the data content itself.
+// Information from this header is used to display warnings to the user about incompatabilities
+bool
+RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // Find allocation with the given id
+ AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
+ if (!alloc)
+ return false;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
+
+ // JIT all the allocation details
+ if (alloc->shouldRefresh())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info");
+
+ if (!RefreshAllocation(alloc, frame_ptr))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::LoadAllocation - Couldn't JIT allocation details");
+ return false;
+ }
+ }
+
+ assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid()
+ && alloc->size.isValid() && alloc->element.datum_size.isValid() && "Allocation information not available");
+
+ // Check we can read from file
+ FileSpec file(filename, true);
+ if (!file.Exists())
+ {
+ strm.Printf("Error: File %s does not exist", filename);
+ strm.EOL();
+ return false;
+ }
+
+ if (!file.Readable())
+ {
+ strm.Printf("Error: File %s does not have readable permissions", filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Read file into data buffer
+ DataBufferSP data_sp(file.ReadFileContents());
+
+ // Cast start of buffer to FileHeader and use pointer to read metadata
+ void* file_buffer = data_sp->GetBytes();
+ if (file_buffer == NULL || data_sp->GetByteSize() <
+ (sizeof(AllocationDetails::FileHeader) + sizeof(AllocationDetails::ElementHeader)))
+ {
+ strm.Printf("Error: File %s does not contain enough data for header", filename);
+ strm.EOL();
+ return false;
+ }
+ const AllocationDetails::FileHeader* file_header = static_cast<AllocationDetails::FileHeader*>(file_buffer);
+
+ // Check file starts with ascii characters "RSAD"
+ if (file_header->ident[0] != 'R' || file_header->ident[1] != 'S' || file_header->ident[2] != 'A'
+ || file_header->ident[3] != 'D')
+ {
+ strm.Printf("Error: File doesn't contain identifier for an RS allocation dump. Are you sure this is the correct file?");
+ strm.EOL();
+ return false;
+ }
+
+ // Look at the type of the root element in the header
+ AllocationDetails::ElementHeader root_element_header;
+ memcpy(&root_element_header, static_cast<uint8_t*>(file_buffer) + sizeof(AllocationDetails::FileHeader),
+ sizeof(AllocationDetails::ElementHeader));
+
+ if (log)
+ log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u",
+ root_element_header.type, root_element_header.element_size);
+
+ // Check if the target allocation and file both have the same number of bytes for an Element
+ if (*alloc->element.datum_size.get() != root_element_header.element_size)
+ {
+ strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes",
+ root_element_header.element_size, *alloc->element.datum_size.get());
+ strm.EOL();
+ }
+
+ // Check if the target allocation and file both have the same type
+ const unsigned int alloc_type = static_cast<unsigned int>(*alloc->element.type.get());
+ const unsigned int file_type = root_element_header.type;
+
+ if (file_type > Element::RS_TYPE_FONT)
+ {
+ strm.Printf("Warning: File has unknown allocation type");
+ strm.EOL();
+ }
+ else if (alloc_type != file_type)
+ {
+ // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
+ unsigned int printable_target_type_index = alloc_type;
+ unsigned int printable_head_type_index = file_type;
+ if (alloc_type >= Element::RS_TYPE_ELEMENT && alloc_type <= Element::RS_TYPE_FONT)
+ printable_target_type_index = static_cast<Element::DataType>(
+ (alloc_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
+
+ if (file_type >= Element::RS_TYPE_ELEMENT && file_type <= Element::RS_TYPE_FONT)
+ printable_head_type_index = static_cast<Element::DataType>(
+ (file_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
+
+ const char* file_type_cstr = AllocationDetails::RsDataTypeToString[printable_head_type_index][0];
+ const char* target_type_cstr = AllocationDetails::RsDataTypeToString[printable_target_type_index][0];
+
+ strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type",
+ file_type_cstr, target_type_cstr);
+ strm.EOL();
+ }
+
+ // Advance buffer past header
+ file_buffer = static_cast<uint8_t*>(file_buffer) + file_header->hdr_size;
+
+ // Calculate size of allocation data in file
+ size_t length = data_sp->GetByteSize() - file_header->hdr_size;
+
+ // Check if the target allocation and file both have the same total data size.
+ const unsigned int alloc_size = *alloc->size.get();
+ if (alloc_size != length)
+ {
+ strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%x bytes",
+ (uint64_t) length, alloc_size);
+ strm.EOL();
+ length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum
+ }
+
+ // Copy file data from our buffer into the target allocation.
+ lldb::addr_t alloc_data = *alloc->data_ptr.get();
+ Error error;
+ size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error);
+ if (!error.Success() || bytes_written != length)
+ {
+ strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString());
+ strm.EOL();
+ return false;
+ }
+
+ strm.Printf("Contents of file '%s' read into allocation %u", filename, alloc->id);
+ strm.EOL();
+
+ return true;
+}
+
+// Function takes as parameters a byte buffer, which will eventually be written to file as the element header,
+// an offset into that buffer, and an Element that will be saved into the buffer at the parametrised offset.
+// Return value is the new offset after writing the element into the buffer.
+// Elements are saved to the file as the ElementHeader struct followed by offsets to the structs of all the element's children.
+size_t
+RenderScriptRuntime::PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer, size_t offset, const Element& elem)
+{
+ // File struct for an element header with all the relevant details copied from elem.
+ // We assume members are valid already.
+ AllocationDetails::ElementHeader elem_header;
+ elem_header.type = *elem.type.get();
+ elem_header.kind = *elem.type_kind.get();
+ elem_header.element_size = *elem.datum_size.get();
+ elem_header.vector_size = *elem.type_vec_size.get();
+ elem_header.array_size = elem.array_size.isValid() ? *elem.array_size.get() : 0;
+ const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader);
+
+ // Copy struct into buffer and advance offset
+ // We assume that header_buffer has been checked for NULL before this method is called
+ memcpy(header_buffer.get() + offset, &elem_header, elem_header_size);
+ offset += elem_header_size;
+
+ // Starting offset of child ElementHeader struct
+ size_t child_offset = offset + ((elem.children.size() + 1) * sizeof(uint32_t));
+ for (const RenderScriptRuntime::Element& child : elem.children)
+ {
+ // Recursively populate the buffer with the element header structs of children.
+ // Then save the offsets where they were set after the parent element header.
+ memcpy(header_buffer.get() + offset, &child_offset, sizeof(uint32_t));
+ offset += sizeof(uint32_t);
+
+ child_offset = PopulateElementHeaders(header_buffer, child_offset, child);
+ }
+
+ // Zero indicates no more children
+ memset(header_buffer.get() + offset, 0, sizeof(uint32_t));
+
+ return child_offset;
+}
+
+// Given an Element object this function returns the total size needed in the file header to store the element's details.
+// Taking into account the size of the element header struct, plus the offsets to all the element's children.
+// Function is recursive so that the size of all ancestors is taken into account.
+size_t
+RenderScriptRuntime::CalculateElementHeaderSize(const Element& elem)
+{
+ size_t size = (elem.children.size() + 1) * sizeof(uint32_t); // Offsets to children plus zero terminator
+ size += sizeof(AllocationDetails::ElementHeader); // Size of header struct with type details
+
+ // Calculate recursively for all descendants
+ for (const Element& child : elem.children)
+ size += CalculateElementHeaderSize(child);
+
+ return size;
+}
+
+// Function copies allocation contents into a binary file.
+// This file can then be loaded later into a different allocation.
+// There is a header, FileHeader, before the allocation data containing meta-data.
+bool
+RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // Find allocation with the given id
+ AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
+ if (!alloc)
+ return false;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
+
+ // JIT all the allocation details
+ if (alloc->shouldRefresh())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info");
+
+ if (!RefreshAllocation(alloc, frame_ptr))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Couldn't JIT allocation details");
+ return false;
+ }
+ }
+
+ assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() && alloc->element.datum_size.get()
+ && alloc->element.type_kind.isValid() && alloc->dimension.isValid() && "Allocation information not available");
+
+ // Check we can create writable file
+ FileSpec file_spec(filename, true);
+ File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate);
+ if (!file)
+ {
+ strm.Printf("Error: Failed to open '%s' for writing", filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Read allocation into buffer of heap memory
+ const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
+ if (!buffer)
+ {
+ strm.Printf("Error: Couldn't read allocation data into buffer");
+ strm.EOL();
+ return false;
+ }
+
+ // Create the file header
+ AllocationDetails::FileHeader head;
+ head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D';
+ head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
+ head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
+ head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
+
+ const size_t element_header_size = CalculateElementHeaderSize(alloc->element);
+ assert((sizeof(AllocationDetails::FileHeader) + element_header_size) < UINT16_MAX && "Element header too large");
+ head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader) + element_header_size);
+
+ // Write the file header
+ size_t num_bytes = sizeof(AllocationDetails::FileHeader);
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Writing File Header, 0x%zX bytes", num_bytes);
+
+ Error err = file.Write(&head, num_bytes);
+ if (!err.Success())
+ {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Create the headers describing the element type of the allocation.
+ std::shared_ptr<uint8_t> element_header_buffer(new uint8_t[element_header_size]);
+ if (element_header_buffer == nullptr)
+ {
+ strm.Printf("Internal Error: Couldn't allocate %zu bytes on the heap", element_header_size);
+ strm.EOL();
+ return false;
+ }
+
+ PopulateElementHeaders(element_header_buffer, 0, alloc->element);
+
+ // Write headers for allocation element type to file
+ num_bytes = element_header_size;
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Writing Element Headers, 0x%zX bytes", num_bytes);
+
+ err = file.Write(element_header_buffer.get(), num_bytes);
+ if (!err.Success())
+ {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Write allocation data to file
+ num_bytes = static_cast<size_t>(*alloc->size.get());
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Writing 0x%zX bytes", num_bytes);
+
+ err = file.Write(buffer.get(), num_bytes);
+ if (!err.Success())
+ {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
+ strm.EOL();
+ return false;
+ }
+
+ strm.Printf("Allocation written to file '%s'", filename);
+ strm.EOL();
+ return true;
}
bool
@@ -496,7 +2377,14 @@ RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
for (const auto &rs_module : m_rsmodules)
{
if (rs_module->m_module == module_sp)
+ {
+ // Check if the user has enabled automatically breaking on
+ // all RS kernels.
+ if (m_breakAllKernels)
+ BreakOnModuleKernels(rs_module);
+
return false;
+ }
}
bool module_loaded = false;
switch (GetModuleKind(module_sp))
@@ -532,7 +2420,7 @@ RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
}
case eModuleKindLibRS:
{
- if (!m_libRS)
+ if (!m_libRS)
{
m_libRS = module_sp;
static ConstString gDbgPresentStr("gDebuggerPresent");
@@ -567,7 +2455,7 @@ RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
break;
}
if (module_loaded)
- Update();
+ Update();
return module_loaded;
}
return false;
@@ -585,7 +2473,6 @@ RenderScriptRuntime::Update()
}
}
-
// The maximum line length of an .rs.info packet
#define MAXLINE 500
@@ -609,12 +2496,12 @@ RSModuleDescriptor::ParseRSInfo()
std::string info((const char *)buffer->GetBytes());
std::vector<std::string> info_lines;
- size_t lpos = info.find_first_of("\n");
+ size_t lpos = info.find('\n');
while (lpos != std::string::npos)
{
info_lines.push_back(info.substr(0, lpos));
info = info.substr(lpos + 1);
- lpos = info.find_first_of("\n");
+ lpos = info.find('\n');
}
size_t offset = 0;
while (offset < info_lines.size())
@@ -642,7 +2529,7 @@ RSModuleDescriptor::ParseRSInfo()
m_kernels.push_back(RSKernelDescriptor(this, name, slot));
}
}
- }
+ }
else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1)
{
char name[MAXLINE];
@@ -651,7 +2538,7 @@ RSModuleDescriptor::ParseRSInfo()
{
name[0] = '\0';
value[0] = '\0';
- if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0
+ if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0
&& (name[0] != '\0'))
{
m_pragmas[std::string(name)] = value;
@@ -700,7 +2587,7 @@ RenderScriptRuntime::Status(Stream &strm) const
strm.Printf("CPU Reference Implementation discovered.");
strm.EOL();
}
-
+
if (m_runtimeHooks.size())
{
strm.Printf("Runtime functions hooked:");
@@ -710,8 +2597,7 @@ RenderScriptRuntime::Status(Stream &strm) const
strm.Indent(b.second->defn->name);
strm.EOL();
}
- strm.EOL();
- }
+ }
else
{
strm.Printf("Runtime is not hooked.");
@@ -719,7 +2605,7 @@ RenderScriptRuntime::Status(Stream &strm) const
}
}
-void
+void
RenderScriptRuntime::DumpContexts(Stream &strm) const
{
strm.Printf("Inferred RenderScript Contexts:");
@@ -728,15 +2614,21 @@ RenderScriptRuntime::DumpContexts(Stream &strm) const
std::map<addr_t, uint64_t> contextReferences;
- for (const auto &script : m_scripts)
+ // Iterate over all of the currently discovered scripts.
+ // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script.
+ for (const auto & script : m_scripts)
{
- if (contextReferences.find(script.context) != contextReferences.end())
+ if (!script->context.isValid())
+ continue;
+ lldb::addr_t context = *script->context;
+
+ if (contextReferences.find(context) != contextReferences.end())
{
- contextReferences[script.context]++;
+ contextReferences[context]++;
}
else
{
- contextReferences[script.context] = 1;
+ contextReferences[context] = 1;
}
}
@@ -748,7 +2640,7 @@ RenderScriptRuntime::DumpContexts(Stream &strm) const
strm.IndentLess();
}
-void
+void
RenderScriptRuntime::DumpKernels(Stream &strm) const
{
strm.Printf("RenderScript Kernels:");
@@ -767,69 +2659,502 @@ RenderScriptRuntime::DumpKernels(Stream &strm) const
strm.IndentLess();
}
-void
-RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error)
+RenderScriptRuntime::AllocationDetails*
+RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id)
{
- if (!name)
+ AllocationDetails* alloc = nullptr;
+
+ // See if we can find allocation using id as an index;
+ if (alloc_id <= m_allocations.size() && alloc_id != 0
+ && m_allocations[alloc_id-1]->id == alloc_id)
{
- error.SetErrorString("invalid kernel name");
- return;
+ alloc = m_allocations[alloc_id-1].get();
+ return alloc;
}
- bool kernels_found;
- ConstString kernel_name(name);
- for (const auto &module : m_rsmodules)
+ // Fallback to searching
+ for (const auto & a : m_allocations)
{
- for (const auto &kernel : module->m_kernels)
+ if (a->id == alloc_id)
+ {
+ alloc = a.get();
+ break;
+ }
+ }
+
+ if (alloc == nullptr)
+ {
+ strm.Printf("Error: Couldn't find allocation with id matching %u", alloc_id);
+ strm.EOL();
+ }
+
+ return alloc;
+}
+
+// Prints the contents of an allocation to the output stream, which may be a file
+bool
+RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // Check we can find the desired allocation
+ AllocationDetails* alloc = FindAllocByID(strm, id);
+ if (!alloc)
+ return false; // FindAllocByID() will print error message for us here
+
+ if (log)
+ log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
+
+ // Check we have information about the allocation, if not calculate it
+ if (alloc->shouldRefresh())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info");
+
+ // JIT all the allocation information
+ if (!RefreshAllocation(alloc, frame_ptr))
{
- if (kernel.m_name == kernel_name)
- {
- //Attempt to set a breakpoint on this symbol, within the module library
- //If it's not found, it's likely debug info is unavailable - set a
- //breakpoint on <name>.expand and emit a warning.
+ strm.Printf("Error: Couldn't JIT allocation details");
+ strm.EOL();
+ return false;
+ }
+ }
+
+ // Establish format and size of each data element
+ const unsigned int vec_size = *alloc->element.type_vec_size.get();
+ const Element::DataType type = *alloc->element.type.get();
+
+ assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT
+ && "Invalid allocation type");
+
+ lldb::Format format;
+ if (type >= Element::RS_TYPE_ELEMENT)
+ format = eFormatHex;
+ else
+ format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle])
+ : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]);
+
+ const unsigned int data_size = *alloc->element.datum_size.get();
+
+ if (log)
+ log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, including padding", data_size);
+
+ // Allocate a buffer to copy data into
+ std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
+ if (!buffer)
+ {
+ strm.Printf("Error: Couldn't read allocation data");
+ strm.EOL();
+ return false;
+ }
+
+ // Calculate stride between rows as there may be padding at end of rows since
+ // allocated memory is 16-byte aligned
+ if (!alloc->stride.isValid())
+ {
+ if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
+ alloc->stride = 0;
+ else if (!JITAllocationStride(alloc, frame_ptr))
+ {
+ strm.Printf("Error: Couldn't calculate allocation row stride");
+ strm.EOL();
+ return false;
+ }
+ }
+ const unsigned int stride = *alloc->stride.get();
+ const unsigned int size = *alloc->size.get(); // Size of whole allocation
+ const unsigned int padding = alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0;
+ if (log)
+ log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes, padding %u", stride, size, padding);
+
+ // Find dimensions used to index loops, so need to be non-zero
+ unsigned int dim_x = alloc->dimension.get()->dim_1;
+ dim_x = dim_x == 0 ? 1 : dim_x;
+
+ unsigned int dim_y = alloc->dimension.get()->dim_2;
+ dim_y = dim_y == 0 ? 1 : dim_y;
+
+ unsigned int dim_z = alloc->dimension.get()->dim_3;
+ dim_z = dim_z == 0 ? 1 : dim_z;
- const Symbol* kernel_sym = module->m_module->FindFirstSymbolWithNameAndType(kernel_name, eSymbolTypeCode);
+ // Use data extractor to format output
+ const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+ DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize);
- if (!kernel_sym)
+ unsigned int offset = 0; // Offset in buffer to next element to be printed
+ unsigned int prev_row = 0; // Offset to the start of the previous row
+
+ // Iterate over allocation dimensions, printing results to user
+ strm.Printf("Data (X, Y, Z):");
+ for (unsigned int z = 0; z < dim_z; ++z)
+ {
+ for (unsigned int y = 0; y < dim_y; ++y)
+ {
+ // Use stride to index start of next row.
+ if (!(y==0 && z==0))
+ offset = prev_row + stride;
+ prev_row = offset;
+
+ // Print each element in the row individually
+ for (unsigned int x = 0; x < dim_x; ++x)
+ {
+ strm.Printf("\n(%u, %u, %u) = ", x, y, z);
+ if ((type == Element::RS_TYPE_NONE) && (alloc->element.children.size() > 0) &&
+ (alloc->element.type_name != Element::GetFallbackStructName()))
{
- std::string kernel_name_expanded(name);
- kernel_name_expanded.append(".expand");
- kernel_sym = module->m_module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
+ // Here we are dumping an Element of struct type.
+ // This is done using expression evaluation with the name of the struct type and pointer to element.
- if (kernel_sym)
- {
- strm.Printf("Kernel '%s' could not be found, but expansion exists. ", name);
- strm.Printf("Breakpoint placed on expanded kernel. Have you compiled in debug mode?");
- strm.EOL();
- }
- else
+ // Don't print the name of the resulting expression, since this will be '$[0-9]+'
+ DumpValueObjectOptions expr_options;
+ expr_options.SetHideName(true);
+
+ // Setup expression as derefrencing a pointer cast to element address.
+ char expr_char_buffer[jit_max_expr_size];
+ int chars_written = snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64,
+ alloc->element.type_name.AsCString(), *alloc->data_ptr.get() + offset);
+
+ if (chars_written < 0 || chars_written >= jit_max_expr_size)
{
- error.SetErrorStringWithFormat("Could not locate symbols for loaded kernel '%s'.", name);
- return;
+ if (log)
+ log->Printf("RenderScriptRuntime::DumpAllocation- Error in snprintf()");
+ continue;
}
- }
- addr_t bp_addr = kernel_sym->GetLoadAddress(&GetProcess()->GetTarget());
- if (bp_addr == LLDB_INVALID_ADDRESS)
+ // Evaluate expression
+ ValueObjectSP expr_result;
+ GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer, frame_ptr, expr_result);
+
+ // Print the results to our stream.
+ expr_result->Dump(strm, expr_options);
+ }
+ else
{
- error.SetErrorStringWithFormat("Could not locate load address for symbols of kernel '%s'.", name);
- return;
+ alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);
}
+ offset += data_size;
+ }
+ }
+ }
+ strm.EOL();
+
+ return true;
+}
- BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(bp_addr, false, false);
- strm.Printf("Breakpoint %" PRIu64 ": kernel '%s' within script '%s'", (uint64_t)bp->GetID(), name, module->m_resname.c_str());
- strm.EOL();
+// Prints infomation regarding all the currently loaded allocations.
+// These details are gathered by jitting the runtime, which has as latency.
+void
+RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute)
+{
+ strm.Printf("RenderScript Allocations:");
+ strm.EOL();
+ strm.IndentMore();
- kernels_found = true;
+ for (auto &alloc : m_allocations)
+ {
+ // JIT the allocation info if we haven't done it, or the user forces us to.
+ bool do_refresh = alloc->shouldRefresh() || recompute;
+
+ // JIT current allocation information
+ if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr))
+ {
+ strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id);
+ continue;
+ }
+
+ strm.Printf("%u:\n",alloc->id);
+ strm.IndentMore();
+
+ strm.Indent("Context: ");
+ if (!alloc->context.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
+
+ strm.Indent("Address: ");
+ if (!alloc->address.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
+
+ strm.Indent("Data pointer: ");
+ if (!alloc->data_ptr.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
+
+ strm.Indent("Dimensions: ");
+ if (!alloc->dimension.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1,
+ alloc->dimension.get()->dim_2,
+ alloc->dimension.get()->dim_3);
+
+ strm.Indent("Data Type: ");
+ if (!alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid())
+ strm.Printf("unknown\n");
+ else
+ {
+ const int vector_size = *alloc->element.type_vec_size.get();
+ Element::DataType type = *alloc->element.type.get();
+
+ if (!alloc->element.type_name.IsEmpty())
+ strm.Printf("%s\n", alloc->element.type_name.AsCString());
+ else
+ {
+ // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
+ if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
+ type = static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
+
+ if (type >= (sizeof(AllocationDetails::RsDataTypeToString) / sizeof(AllocationDetails::RsDataTypeToString[0]))
+ || vector_size > 4 || vector_size < 1)
+ strm.Printf("invalid type\n");
+ else
+ strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]);
}
}
+
+ strm.Indent("Data Kind: ");
+ if (!alloc->element.type_kind.isValid())
+ strm.Printf("unknown\n");
+ else
+ {
+ const Element::DataKind kind = *alloc->element.type_kind.get();
+ if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV)
+ strm.Printf("invalid kind\n");
+ else
+ strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]);
+ }
+
+ strm.EOL();
+ strm.IndentLess();
+ }
+ strm.IndentLess();
+}
+
+// Set breakpoints on every kernel found in RS module
+void
+RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
+{
+ for (const auto &kernel : rsmodule_sp->m_kernels)
+ {
+ // Don't set breakpoint on 'root' kernel
+ if (strcmp(kernel.m_name.AsCString(), "root") == 0)
+ continue;
+
+ CreateKernelBreakpoint(kernel.m_name);
+ }
+}
+
+// Method is internally called by the 'kernel breakpoint all' command to
+// enable or disable breaking on all kernels.
+//
+// When do_break is true we want to enable this functionality.
+// When do_break is false we want to disable it.
+void
+RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
+{
+ Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
+
+ InitSearchFilter(target);
+
+ // Set breakpoints on all the kernels
+ if (do_break && !m_breakAllKernels)
+ {
+ m_breakAllKernels = true;
+
+ for (const auto &module : m_rsmodules)
+ BreakOnModuleKernels(module);
+
+ if (log)
+ log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)"
+ "- breakpoints set on all currently loaded kernels");
+ }
+ else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
+ {
+ m_breakAllKernels = false;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set");
+ }
+}
+
+// Given the name of a kernel this function creates a breakpoint using our
+// own breakpoint resolver, and returns the Breakpoint shared pointer.
+BreakpointSP
+RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name)
+{
+ Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
+
+ if (!m_filtersp)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set");
+ return nullptr;
+ }
+
+ BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
+ BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
+
+ // Give RS breakpoints a specific name, so the user can manipulate them as a group.
+ Error err;
+ if (!bp->AddName("RenderScriptKernel", err) && log)
+ log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString());
+
+ return bp;
+}
+
+// Given an expression for a variable this function tries to calculate the variable's value.
+// If this is possible it returns true and sets the uint64_t parameter to the variables unsigned value.
+// Otherwise function returns false.
+bool
+RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const char* var_name, uint64_t& val)
+{
+ Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ Error error;
+ VariableSP var_sp;
+
+ // Find variable in stack frame
+ ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(var_name,
+ eNoDynamicValues,
+ StackFrame::eExpressionPathOptionCheckPtrVsMember |
+ StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
+ var_sp,
+ error));
+ if (!error.Success())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't find '%s' in frame", var_name);
+
+ return false;
+ }
+
+ // Find the unsigned int value for the variable
+ bool success = false;
+ val = value_sp->GetValueAsUnsigned(0, &success);
+ if (!success)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't parse '%s' as an unsigned int", var_name);
+
+ return false;
+ }
+
+ return true;
+}
+
+// Callback when a kernel breakpoint hits and we're looking for a specific coordinate.
+// Baton parameter contains a pointer to the target coordinate we want to break on.
+// Function then checks the .expand frame for the current coordinate and breaks to user if it matches.
+// Parameter 'break_id' is the id of the Breakpoint which made the callback.
+// Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit,
+// a single logical breakpoint can have multiple addresses.
+bool
+RenderScriptRuntime::KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx,
+ user_id_t break_id, user_id_t break_loc_id)
+{
+ Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
+
+ assert(baton && "Error: null baton in conditional kernel breakpoint callback");
+
+ // Coordinate we want to stop on
+ const int* target_coord = static_cast<const int*>(baton);
+
+ if (log)
+ log->Printf("RenderScriptRuntime::KernelBreakpointHit - Break ID %" PRIu64 ", target coord (%d, %d, %d)",
+ break_id, target_coord[0], target_coord[1], target_coord[2]);
+
+ // Go up one stack frame to .expand kernel
+ ExecutionContext context(ctx->exe_ctx_ref);
+ ThreadSP thread_sp = context.GetThreadSP();
+ if (!thread_sp->SetSelectedFrameByIndex(1))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't go up stack frame");
+
+ return false;
+ }
+
+ StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+ if (!frame_sp)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't select .expand stack frame");
+
+ return false;
+ }
+
+ // Get values for variables in .expand frame that tell us the current kernel invocation
+ const char* coord_expressions[] = {"rsIndex", "p->current.y", "p->current.z"};
+ uint64_t current_coord[3] = {0, 0, 0};
+
+ for(int i = 0; i < 3; ++i)
+ {
+ if (!GetFrameVarAsUnsigned(frame_sp, coord_expressions[i], current_coord[i]))
+ return false;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::KernelBreakpointHit, %s = %" PRIu64, coord_expressions[i], current_coord[i]);
}
- if (!kernels_found)
+ // Check if the current kernel invocation coordinate matches our target coordinate
+ if (current_coord[0] == static_cast<uint64_t>(target_coord[0]) &&
+ current_coord[1] == static_cast<uint64_t>(target_coord[1]) &&
+ current_coord[2] == static_cast<uint64_t>(target_coord[2]))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::KernelBreakpointHit, BREAKING %" PRIu64 ", %" PRIu64 ", %" PRIu64,
+ current_coord[0], current_coord[1], current_coord[2]);
+
+ BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id);
+ assert(breakpoint_sp != nullptr && "Error: Couldn't find breakpoint matching break id for callback");
+ breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint should only be hit once.
+ return true;
+ }
+
+ // No match on coordinate
+ return false;
+}
+
+// Tries to set a breakpoint on the start of a kernel, resolved using the kernel name.
+// Argument 'coords', represents a three dimensional coordinate which can be used to specify
+// a single kernel instance to break on. If this is set then we add a callback to the breakpoint.
+void
+RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char* name, const std::array<int,3> coords,
+ Error& error, TargetSP target)
+{
+ if (!name)
+ {
+ error.SetErrorString("invalid kernel name");
+ return;
+ }
+
+ InitSearchFilter(target);
+
+ ConstString kernel_name(name);
+ BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
+
+ // We have a conditional breakpoint on a specific coordinate
+ if (coords[0] != -1)
{
- error.SetErrorString("kernel name not found");
+ strm.Printf("Conditional kernel breakpoint on coordinate %d, %d, %d", coords[0], coords[1], coords[2]);
+ strm.EOL();
+
+ // Allocate memory for the baton, and copy over coordinate
+ int* baton = new int[3];
+ baton[0] = coords[0]; baton[1] = coords[1]; baton[2] = coords[2];
+
+ // Create a callback that will be invoked everytime the breakpoint is hit.
+ // The baton object passed to the handler is the target coordinate we want to break on.
+ bp->SetCallback(KernelBreakpointHit, baton, true);
+
+ // Store a shared pointer to the baton, so the memory will eventually be cleaned up after destruction
+ m_conditional_breaks[bp->GetID()] = std::shared_ptr<int>(baton);
}
- return;
+
+ if (bp)
+ bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
}
void
@@ -845,12 +3170,49 @@ RenderScriptRuntime::DumpModules(Stream &strm) const
strm.IndentLess();
}
+RenderScriptRuntime::ScriptDetails*
+RenderScriptRuntime::LookUpScript(addr_t address, bool create)
+{
+ for (const auto & s : m_scripts)
+ {
+ if (s->script.isValid())
+ if (*s->script == address)
+ return s.get();
+ }
+ if (create)
+ {
+ std::unique_ptr<ScriptDetails> s(new ScriptDetails);
+ s->script = address;
+ m_scripts.push_back(std::move(s));
+ return m_scripts.back().get();
+ }
+ return nullptr;
+}
+
+RenderScriptRuntime::AllocationDetails*
+RenderScriptRuntime::LookUpAllocation(addr_t address, bool create)
+{
+ for (const auto & a : m_allocations)
+ {
+ if (a->address.isValid())
+ if (*a->address == address)
+ return a.get();
+ }
+ if (create)
+ {
+ std::unique_ptr<AllocationDetails> a(new AllocationDetails);
+ a->address = address;
+ m_allocations.push_back(std::move(a));
+ return m_allocations.back().get();
+ }
+ return nullptr;
+}
+
void
RSModuleDescriptor::Dump(Stream &strm) const
{
strm.Indent();
m_module->GetFileSpec().Dump(&strm);
- m_module->ParseAllDebugSymbols();
if(m_module->GetNumCompileUnits())
{
strm.Indent("Debug info loaded.");
@@ -931,8 +3293,7 @@ RSKernelDescriptor::Dump(Stream &strm) const
class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript module probe",
"Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
@@ -941,10 +3302,10 @@ class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
{
}
- ~CommandObjectRenderScriptRuntimeModuleProbe() {}
+ ~CommandObjectRenderScriptRuntimeModuleProbe() override = default;
bool
- DoExecute(Args &command, CommandReturnObject &result)
+ DoExecute(Args &command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
if (argc == 0)
@@ -970,8 +3331,7 @@ class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript module dump",
"Dumps renderscript specific information for all modules.", "renderscript module dump",
@@ -979,10 +3339,10 @@ class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
{
}
- ~CommandObjectRenderScriptRuntimeModuleDump() {}
+ ~CommandObjectRenderScriptRuntimeModuleDump() override = default;
bool
- DoExecute(Args &command, CommandReturnObject &result)
+ DoExecute(Args &command, CommandReturnObject &result) override
{
RenderScriptRuntime *runtime =
(RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
@@ -994,8 +3354,7 @@ class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
NULL)
@@ -1004,13 +3363,12 @@ class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
}
- ~CommandObjectRenderScriptRuntimeModule() {}
+ ~CommandObjectRenderScriptRuntimeModule() override = default;
};
class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript kernel list",
"Lists renderscript kernel names and associated script resources.", "renderscript kernel list",
@@ -1018,10 +3376,10 @@ class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
{
}
- ~CommandObjectRenderScriptRuntimeKernelList() {}
+ ~CommandObjectRenderScriptRuntimeKernelList() override = default;
bool
- DoExecute(Args &command, CommandReturnObject &result)
+ DoExecute(Args &command, CommandReturnObject &result) override
{
RenderScriptRuntime *runtime =
(RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
@@ -1031,52 +3389,213 @@ class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
}
};
-class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectParsed
+class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
{
- private:
- public:
- CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript kernel breakpoint",
- "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
+public:
+ CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
+ "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options(interpreter)
{
}
- ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {}
+ ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;
- bool
- DoExecute(Args &command, CommandReturnObject &result)
+ Options*
+ GetOptions() override
{
- const size_t argc = command.GetArgumentCount();
- if (argc == 1)
+ return &m_options;
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+ CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)
{
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+ }
+
+ ~CommandOptions() override = default;
+ Error
+ SetOptionValue(uint32_t option_idx, const char *option_arg) override
+ {
Error error;
- runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0), error);
+ const int short_option = m_getopt_table[option_idx].val;
- if (error.Success())
+ switch (short_option)
{
- result.AppendMessage("Breakpoint(s) created");
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
+ case 'c':
+ if (!ParseCoordinate(option_arg))
+ error.SetErrorStringWithFormat("Couldn't parse coordinate '%s', should be in format 'x,y,z'.", option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
}
+ return error;
+ }
+
+ // -c takes an argument of the form 'num[,num][,num]'.
+ // Where 'id_cstr' is this argument with the whitespace trimmed.
+ // Missing coordinates are defaulted to zero.
+ bool
+ ParseCoordinate(const char* id_cstr)
+ {
+ RegularExpression regex;
+ RegularExpression::Match regex_match(3);
+
+ bool matched = false;
+ if(regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
+ matched = true;
+ else if(regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
+ matched = true;
+ else if(regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
+ matched = true;
+ for(uint32_t i = 0; i < 3; i++)
+ {
+ std::string group;
+ if(regex_match.GetMatchAtIndex(id_cstr, i + 1, group))
+ m_coord[i] = (uint32_t)strtoul(group.c_str(), NULL, 0);
+ else
+ m_coord[i] = 0;
+ }
+ return matched;
+ }
+
+ void
+ OptionParsingStarting() override
+ {
+ // -1 means the -c option hasn't been set
+ m_coord[0] = -1;
+ m_coord[1] = -1;
+ m_coord[2] = -1;
+ }
+
+ const OptionDefinition*
+ GetDefinitions() override
+ {
+ return g_option_table;
+ }
+
+ static OptionDefinition g_option_table[];
+ std::array<int,3> m_coord;
+ };
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc < 1)
+ {
+ result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name, and an optional coordinate.", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
- result.AppendErrorWithFormat("Error: %s", error.AsCString());
return false;
}
- result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name", m_cmd_name.c_str());
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+
+ Error error;
+ runtime->PlaceBreakpointOnKernel(result.GetOutputStream(), command.GetArgumentAtIndex(0), m_options.m_coord,
+ error, m_exe_ctx.GetTargetSP());
+
+ if (error.Success())
+ {
+ result.AppendMessage("Breakpoint(s) created");
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
result.SetStatus(eReturnStatusFailed);
+ result.AppendErrorWithFormat("Error: %s", error.AsCString());
return false;
}
+
+private:
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectRenderScriptRuntimeKernelBreakpointSet::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue,
+ "Set a breakpoint on a single invocation of the kernel with specified coordinate.\n"
+ "Coordinate takes the form 'x[,y][,z] where x,y,z are positive integers representing kernel dimensions. "
+ "Any unset dimensions will be defaulted to zero."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
+{
+public:
+ CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all",
+ "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
+ "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
+ "but does not remove currently set breakpoints.",
+ "renderscript kernel breakpoint all <enable/disable>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 1)
+ {
+ result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime =
+ static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+
+ bool do_break = false;
+ const char* argument = command.GetArgumentAtIndex(0);
+ if (strcmp(argument, "enable") == 0)
+ {
+ do_break = true;
+ result.AppendMessage("Breakpoints will be set on all kernels.");
+ }
+ else if (strcmp(argument, "disable") == 0)
+ {
+ do_break = false;
+ result.AppendMessage("Breakpoints will not be set on any new kernels.");
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
+{
+public:
+ CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.",
+ nullptr)
+ {
+ LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
+ LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;
};
class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",
NULL)
@@ -1085,13 +3604,12 @@ class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
}
- ~CommandObjectRenderScriptRuntimeKernel() {}
+ ~CommandObjectRenderScriptRuntimeKernel() override = default;
};
class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript context dump",
"Dumps renderscript context information.", "renderscript context dump",
@@ -1099,10 +3617,10 @@ class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
{
}
- ~CommandObjectRenderScriptRuntimeContextDump() {}
+ ~CommandObjectRenderScriptRuntimeContextDump() override = default;
bool
- DoExecute(Args &command, CommandReturnObject &result)
+ DoExecute(Args &command, CommandReturnObject &result) override
{
RenderScriptRuntime *runtime =
(RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
@@ -1114,8 +3632,7 @@ class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",
NULL)
@@ -1123,13 +3640,345 @@ class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
}
- ~CommandObjectRenderScriptRuntimeContext() {}
+ ~CommandObjectRenderScriptRuntimeContext() override = default;
+};
+
+class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed
+{
+public:
+ CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation dump",
+ "Displays the contents of a particular allocation", "renderscript allocation dump <ID>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;
+
+ Options*
+ GetOptions() override
+ {
+ return &m_options;
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+ CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)
+ {
+ }
+
+ ~CommandOptions() override = default;
+
+ Error
+ SetOptionValue(uint32_t option_idx, const char *option_arg) override
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'f':
+ m_outfile.SetFile(option_arg, true);
+ if (m_outfile.Exists())
+ {
+ m_outfile.Clear();
+ error.SetErrorStringWithFormat("file already exists: '%s'", option_arg);
+ }
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
+ }
+ return error;
+ }
+
+ void
+ OptionParsingStarting() override
+ {
+ m_outfile.Clear();
+ }
+
+ const OptionDefinition*
+ GetDefinitions() override
+ {
+ return g_option_table;
+ }
+
+ static OptionDefinition g_option_table[];
+ FileSpec m_outfile;
+ };
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc < 1)
+ {
+ result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime =
+ static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+
+ const char* id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete)
+ {
+ result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ Stream* output_strm = nullptr;
+ StreamFile outfile_stream;
+ const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead
+ if (outfile_spec)
+ {
+ // Open output file
+ char path[256];
+ outfile_spec.GetPath(path, sizeof(path));
+ if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
+ {
+ output_strm = &outfile_stream;
+ result.GetOutputStream().Printf("Results written to '%s'", path);
+ result.GetOutputStream().EOL();
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Couldn't open file '%s'", path);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ output_strm = &result.GetOutputStream();
+
+ assert(output_strm != nullptr);
+ bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id);
+
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+
+ return true;
+ }
+
+private:
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename,
+ "Print results to specified file instead of command line."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed
+{
+public:
+ CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation list",
+ "List renderscript allocations and their information.", "renderscript allocation list",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeAllocationList() override = default;
+
+ Options*
+ GetOptions() override
+ {
+ return &m_options;
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+ CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false)
+ {
+ }
+
+ ~CommandOptions() override = default;
+
+ Error
+ SetOptionValue(uint32_t option_idx, const char *option_arg) override
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'r':
+ m_refresh = true;
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
+ }
+ return error;
+ }
+
+ void
+ OptionParsingStarting() override
+ {
+ m_refresh = false;
+ }
+
+ const OptionDefinition*
+ GetDefinitions() override
+ {
+ return g_option_table;
+ }
+
+ static OptionDefinition g_option_table[];
+ bool m_refresh;
+ };
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ RenderScriptRuntime *runtime =
+ static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+ runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+
+private:
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+ "Recompute allocation details."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed
+{
+public:
+ CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation load",
+ "Loads renderscript allocation contents from a file.", "renderscript allocation load <ID> <filename>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default;
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 2)
+ {
+ result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime =
+ static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+
+ const char* id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete)
+ {
+ result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const char* filename = command.GetArgumentAtIndex(1);
+ bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
+
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed
+{
+public:
+ CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation save",
+ "Write renderscript allocation contents to a file.", "renderscript allocation save <ID> <filename>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeAllocationSave() override = default;
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 2)
+ {
+ result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime =
+ static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+
+ const char* id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete)
+ {
+ result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const char* filename = command.GetArgumentAtIndex(1);
+ bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
+
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword
+{
+public:
+ CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.",
+ NULL)
+ {
+ LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
+ LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
+ LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
+ LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntimeAllocation() override = default;
};
class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript status",
"Displays current renderscript runtime status.", "renderscript status",
@@ -1137,10 +3986,10 @@ class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
{
}
- ~CommandObjectRenderScriptRuntimeStatus() {}
+ ~CommandObjectRenderScriptRuntimeStatus() override = default;
bool
- DoExecute(Args &command, CommandReturnObject &result)
+ DoExecute(Args &command, CommandReturnObject &result) override
{
RenderScriptRuntime *runtime =
(RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
@@ -1152,7 +4001,7 @@ class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
{
- public:
+public:
CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
"renderscript <subcommand> [<subcommand-options>]")
@@ -1161,9 +4010,10 @@ class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
+ LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
}
- ~CommandObjectRenderScriptRuntime() {}
+ ~CommandObjectRenderScriptRuntime() override = default;
};
void
@@ -1173,7 +4023,8 @@ RenderScriptRuntime::Initiate()
}
RenderScriptRuntime::RenderScriptRuntime(Process *process)
- : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false)
+ : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false),
+ m_breakAllKernels(false)
{
ModulesDidLoad(process->GetTarget().GetImages());
}
@@ -1189,3 +4040,4 @@ RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpre
return command_object;
}
+RenderScriptRuntime::~RenderScriptRuntime() = default;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
index 2a01e74..2fe4390 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
@@ -12,6 +12,12 @@
// C Includes
// C++ Includes
+#include <array>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@@ -19,8 +25,8 @@
#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Core/Module.h"
-namespace lldb_private
-{
+namespace lldb_private {
+namespace lldb_renderscript {
typedef uint32_t RSSlot;
class RSModuleDescriptor;
@@ -31,11 +37,56 @@ typedef std::shared_ptr<RSModuleDescriptor> RSModuleDescriptorSP;
typedef std::shared_ptr<RSGlobalDescriptor> RSGlobalDescriptorSP;
typedef std::shared_ptr<RSKernelDescriptor> RSKernelDescriptorSP;
+// Breakpoint Resolvers decide where a breakpoint is placed,
+// so having our own allows us to limit the search scope to RS kernel modules.
+// As well as check for .expand kernels as a fallback.
+class RSBreakpointResolver : public BreakpointResolver
+{
+public:
+ RSBreakpointResolver(Breakpoint *bkpt, ConstString name):
+ BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
+ m_kernel_name(name)
+ {
+ }
+
+ void
+ GetDescription(Stream *strm) override
+ {
+ if (strm)
+ strm->Printf("RenderScript kernel breakpoint for '%s'", m_kernel_name.AsCString());
+ }
+
+ void
+ Dump(Stream *s) const override
+ {
+ }
+
+ Searcher::CallbackReturn
+ SearchCallback(SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool containing) override;
+ Searcher::Depth
+ GetDepth() override
+ {
+ return Searcher::eDepthModule;
+ }
+
+ lldb::BreakpointResolverSP
+ CopyForBreakpoint(Breakpoint &breakpoint) override
+ {
+ lldb::BreakpointResolverSP ret_sp(new RSBreakpointResolver(&breakpoint, m_kernel_name));
+ return ret_sp;
+ }
+
+protected:
+ ConstString m_kernel_name;
+};
struct RSKernelDescriptor
{
- public:
+public:
RSKernelDescriptor(const RSModuleDescriptor *module, const char *name, uint32_t slot)
: m_module(module)
, m_name(name)
@@ -52,7 +103,7 @@ struct RSKernelDescriptor
struct RSGlobalDescriptor
{
- public:
+public:
RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name )
: m_module(module)
, m_name(name)
@@ -67,13 +118,13 @@ struct RSGlobalDescriptor
class RSModuleDescriptor
{
- public:
+public:
RSModuleDescriptor(const lldb::ModuleSP &module)
: m_module(module)
{
}
- ~RSModuleDescriptor() {}
+ ~RSModuleDescriptor() = default;
bool ParseRSInfo();
@@ -86,10 +137,11 @@ class RSModuleDescriptor
std::string m_resname;
};
+} // namespace lldb_renderscript
+
class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
{
- public:
-
+public:
enum ModuleKind
{
eModuleKindIgnored,
@@ -99,8 +151,7 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
eModuleKindKernelObj
};
-
- ~RenderScriptRuntime() {}
+ ~RenderScriptRuntime() override;
//------------------------------------------------------------------
// Static Functions
@@ -121,21 +172,19 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
static void ModulesDidLoad(const lldb::ProcessSP& process_sp, const ModuleList &module_list );
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- virtual lldb_private::ConstString GetPluginName();
-
- virtual uint32_t GetPluginVersion();
-
- virtual bool IsVTableName(const char *name);
+ bool IsVTableName(const char *name) override;
- virtual bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &address);
+ bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type) override;
+
+ TypeAndOrName
+ FixUpDynamicType(const TypeAndOrName& type_and_or_name,
+ ValueObject& static_value) override;
- virtual bool CouldHaveDynamicValue(ValueObject &in_value);
+ bool CouldHaveDynamicValue(ValueObject &in_value) override;
- virtual lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp);
+ lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
bool LoadModule(const lldb::ModuleSP &module_sp);
@@ -147,25 +196,56 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
void DumpKernels(Stream &strm) const;
- void AttemptBreakpointAtKernelName(Stream &strm, const char *name, Error &error);
+ bool DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id);
+
+ void ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute);
+
+ void PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array<int,3> coords,
+ Error &error, lldb::TargetSP target);
+
+ void SetBreakAllKernels(bool do_break, lldb::TargetSP target);
void Status(Stream &strm) const;
- virtual size_t GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) {
- return static_cast<size_t>(0);
- }
+ void ModulesDidLoad(const ModuleList &module_list) override;
+
+ bool LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr);
- virtual void ModulesDidLoad(const ModuleList &module_list );
+ bool SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr);
void Update();
void Initiate();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+protected:
+ struct ScriptDetails;
+ struct AllocationDetails;
+ struct Element;
+
+ void InitSearchFilter(lldb::TargetSP target)
+ {
+ if (!m_filtersp)
+ m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target));
+ }
- protected:
-
- void FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp);
+ void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
+
+ bool RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+ bool EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result);
+
+ lldb::BreakpointSP CreateKernelBreakpoint(const ConstString& name);
+
+ void BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
struct RuntimeHook;
typedef void (RenderScriptRuntime::*CaptureStateFn)(RuntimeHook* hook_info, ExecutionContext &context); // Please do this!
@@ -173,7 +253,8 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
struct HookDefn
{
const char * name;
- const char * symbol_name;
+ const char * symbol_name_m32; // mangled name for the 32 bit architectures
+ const char * symbol_name_m64; // mangled name for the 64 bit archs
uint32_t version;
ModuleKind kind;
CaptureStateFn grabber;
@@ -185,46 +266,105 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
const HookDefn *defn;
lldb::BreakpointSP bp_sp;
};
-
- typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
- struct ScriptDetails
- {
- std::string resname;
- std::string scriptDyLib;
- std::string cachedir;
- lldb::addr_t context;
- lldb::addr_t script;
- };
+ typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
lldb::ModuleSP m_libRS;
lldb::ModuleSP m_libRSDriver;
lldb::ModuleSP m_libRSCpuRef;
- std::vector<RSModuleDescriptorSP> m_rsmodules;
- std::vector<ScriptDetails> m_scripts;
+ std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules;
- std::map<lldb::addr_t, RSModuleDescriptorSP> m_scriptMappings;
+ std::vector<std::unique_ptr<ScriptDetails>> m_scripts;
+ std::vector<std::unique_ptr<AllocationDetails>> m_allocations;
+
+ std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP> m_scriptMappings;
std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
+ std::map<lldb::user_id_t, std::shared_ptr<int>> m_conditional_breaks;
+
+ lldb::SearchFilterSP m_filtersp; // Needed to create breakpoints through Target API
bool m_initiated;
bool m_debuggerPresentFlagged;
+ bool m_breakAllKernels;
static const HookDefn s_runtimeHookDefns[];
static const size_t s_runtimeHookCount;
- private:
+private:
+ // Used to index expression format strings
+ enum ExpressionStrings
+ {
+ eExprGetOffsetPtr = 0,
+ eExprAllocGetType,
+ eExprTypeDimX,
+ eExprTypeDimY,
+ eExprTypeDimZ,
+ eExprTypeElemPtr,
+ eExprElementType,
+ eExprElementKind,
+ eExprElementVec,
+ eExprElementFieldCount,
+ eExprSubelementsId,
+ eExprSubelementsName,
+ eExprSubelementsArrSize
+ };
+
RenderScriptRuntime(Process *process); // Call CreateInstance instead.
static bool HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
+ static bool KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
+
void HookCallback(RuntimeHook* hook_info, ExecutionContext& context);
- bool GetArg32Simple(ExecutionContext& context, uint32_t arg, uint32_t *data);
+ bool GetArgSimple(ExecutionContext& context, uint32_t arg, uint64_t* data);
void CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context);
void CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context);
+ void CaptureAllocationDestroy(RuntimeHook* hook_info, ExecutionContext& context);
void CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context);
+ AllocationDetails* FindAllocByID(Stream &strm, const uint32_t alloc_id);
+ std::shared_ptr<uint8_t> GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr);
+ void SetElementSize(Element& elem);
+ static bool GetFrameVarAsUnsigned(const lldb::StackFrameSP, const char* var_name, uint64_t& val);
+ void FindStructTypeName(Element& elem, StackFrame* frame_ptr);
+
+ size_t PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer, size_t offset, const Element& elem);
+ size_t CalculateElementHeaderSize(const Element& elem);
+
+ //
+ // Helper functions for jitting the runtime
+ //
+ const char* JITTemplate(ExpressionStrings e);
+
+ bool JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
+ unsigned int x = 0, unsigned int y = 0, unsigned int z = 0);
+
+ bool JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+ bool JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+ bool JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr);
+
+ bool JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+ bool JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr);
+
+ bool JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+ // Search for a script detail object using a target address.
+ // If a script does not currently exist this function will return nullptr.
+ // If 'create' is true and there is no previous script with this address,
+ // then a new Script detail object will be created for this address and returned.
+ ScriptDetails* LookUpScript(lldb::addr_t address, bool create);
+
+ // Search for a previously saved allocation detail object using a target address.
+ // If an allocation does not exist for this address then nullptr will be returned.
+ // If 'create' is true and there is no previous allocation then a new allocation
+ // detail object will be created for this address and returned.
+ AllocationDetails* LookUpAllocation(lldb::addr_t address, bool create);
};
} // namespace lldb_private
diff --git a/contrib/llvm/tools/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/contrib/llvm/tools/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
index c7c64ed..c575198 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
@@ -30,36 +30,25 @@ MemoryHistoryASan::CreateInstance (const ProcessSP &process_sp)
{
if (!process_sp.get())
return NULL;
-
+
Target & target = process_sp->GetTarget();
-
- bool found_asan_runtime = false;
-
+
const ModuleList &target_modules = target.GetImages();
Mutex::Locker modules_locker(target_modules.GetMutex());
const size_t num_modules = target_modules.GetSize();
for (size_t i = 0; i < num_modules; ++i)
{
Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i);
-
- SymbolContextList sc_list;
- const bool include_symbols = true;
- const bool append = true;
- const bool include_inlines = true;
- size_t num_matches = module_pointer->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list);
-
- if (num_matches)
- {
- found_asan_runtime = true;
- break;
- }
+ const Symbol* symbol = module_pointer->FindFirstSymbolWithNameAndType(
+ ConstString("__asan_get_alloc_stack"),
+ lldb::eSymbolTypeAny);
+
+ if (symbol != nullptr)
+ return MemoryHistorySP(new MemoryHistoryASan(process_sp));
}
-
- if (! found_asan_runtime)
- return MemoryHistorySP();
- return MemoryHistorySP(new MemoryHistoryASan(process_sp));
+ return MemoryHistorySP();
}
void
@@ -86,7 +75,8 @@ MemoryHistoryASan::GetPluginNameStatic()
MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp)
{
- this->m_process_sp = process_sp;
+ if (process_sp)
+ m_process_wp = process_sp;
}
const char *
@@ -112,14 +102,23 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObject
std::string count_path = "." + std::string(type) + "_count";
std::string tid_path = "." + std::string(type) + "_tid";
std::string trace_path = "." + std::string(type) + "_trace";
+
+ ValueObjectSP count_sp = return_value_sp->GetValueForExpressionPath(count_path.c_str());
+ ValueObjectSP tid_sp = return_value_sp->GetValueForExpressionPath(tid_path.c_str());
+
+ if (!count_sp || !tid_sp)
+ return;
- int count = return_value_sp->GetValueForExpressionPath(count_path.c_str())->GetValueAsUnsigned(0);
- tid_t tid = return_value_sp->GetValueForExpressionPath(tid_path.c_str())->GetValueAsUnsigned(0);
+ int count = count_sp->GetValueAsUnsigned(0);
+ tid_t tid = tid_sp->GetValueAsUnsigned(0);
if (count <= 0)
return;
ValueObjectSP trace_sp = return_value_sp->GetValueForExpressionPath(trace_path.c_str());
+
+ if (!trace_sp)
+ return;
std::vector<lldb::addr_t> pcs;
for (int i = 0; i < count; i++)
@@ -144,40 +143,41 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObject
HistoryThreads
MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address)
{
- ProcessSP process_sp = m_process_sp;
- ThreadSP thread_sp = m_process_sp->GetThreadList().GetSelectedThread();
- StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+ HistoryThreads result;
- if (!frame_sp)
+ ProcessSP process_sp = m_process_wp.lock();
+ if (process_sp)
{
- return HistoryThreads();
- }
+ ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();
- ExecutionContext exe_ctx (frame_sp);
- ValueObjectSP return_value_sp;
- StreamString expr;
- expr.Printf(memory_history_asan_command_format, address, address);
-
- EvaluateExpressionOptions options;
- options.SetUnwindOnError(true);
- options.SetTryAllThreads(true);
- options.SetStopOthers(true);
- options.SetIgnoreBreakpoints(true);
- options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC);
-
- if (m_process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
- {
- return HistoryThreads();
- }
- if (!return_value_sp)
- {
- return HistoryThreads();
+ if (thread_sp)
+ {
+ StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+
+ if (frame_sp)
+ {
+ ExecutionContext exe_ctx (frame_sp);
+ ValueObjectSP return_value_sp;
+ StreamString expr;
+ expr.Printf(memory_history_asan_command_format, address, address);
+
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(true);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC);
+
+ if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) == eExpressionCompleted)
+ {
+ if (return_value_sp)
+ {
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated at", result);
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated at", result);
+ }
+ }
+ }
+ }
}
-
- HistoryThreads result;
-
- CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated at", result);
- CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated at", result);
-
return result;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h b/contrib/llvm/tools/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
index 5307e0b..b38f95e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
@@ -1,4 +1,4 @@
-//===-- MemoryHistoryASan.h ----------------------------------------*- C++ -*-===//
+//===-- MemoryHistoryASan.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -24,7 +24,8 @@ namespace lldb_private {
class MemoryHistoryASan : public lldb_private::MemoryHistory
{
public:
-
+ ~MemoryHistoryASan() override = default;
+
static lldb::MemoryHistorySP
CreateInstance (const lldb::ProcessSP &process_sp);
@@ -36,27 +37,28 @@ public:
static lldb_private::ConstString
GetPluginNameStatic();
+
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic();
+ }
- virtual
- ~MemoryHistoryASan () {}
-
- virtual lldb_private::ConstString
- GetPluginName() { return GetPluginNameStatic(); }
-
- virtual uint32_t
- GetPluginVersion() { return 1; }
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
- virtual lldb_private::HistoryThreads
- GetHistoryThreads(lldb::addr_t address);
+ lldb_private::HistoryThreads
+ GetHistoryThreads(lldb::addr_t address) override;
private:
-
MemoryHistoryASan(const lldb::ProcessSP &process_sp);
- lldb::ProcessSP m_process_sp;
-
+ lldb::ProcessWP m_process_wp;
};
} // namespace lldb_private
-#endif // liblldb_MemoryHistoryASan_h_
+#endif // liblldb_MemoryHistoryASan_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index 8209d23..f2a74b0 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -103,9 +103,13 @@ ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, lldb::off
}
else
{
- // Strip off any spaces (if the object file name contains spaces it
- // will use the extended format above).
- str.erase (str.find(' '));
+ // Strip off any trailing spaces.
+ const size_t last_pos = str.find_last_not_of(' ');
+ if (last_pos != std::string::npos)
+ {
+ if (last_pos + 1 < 16)
+ str.erase (last_pos + 1);
+ }
ar_name.SetCString(str.c_str());
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
index 8093c58..cbb3848 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
@@ -10,8 +10,11 @@
#ifndef liblldb_ObjectContainerBSDArchive_h_
#define liblldb_ObjectContainerBSDArchive_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Symbol/ObjectContainer.h"
-
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Host/FileSpec.h"
@@ -22,6 +25,14 @@ class ObjectContainerBSDArchive :
public lldb_private::ObjectContainer
{
public:
+ ObjectContainerBSDArchive(const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ const lldb_private::FileSpec *file,
+ lldb::offset_t offset,
+ lldb::offset_t length);
+
+ ~ObjectContainerBSDArchive() override;
//------------------------------------------------------------------
// Static Functions
@@ -60,43 +71,33 @@ public:
//------------------------------------------------------------------
// Member Functions
//------------------------------------------------------------------
- ObjectContainerBSDArchive (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const lldb_private::FileSpec *file,
- lldb::offset_t offset,
- lldb::offset_t length);
-
- virtual
- ~ObjectContainerBSDArchive();
+ bool
+ ParseHeader() override;
- virtual bool
- ParseHeader ();
-
- virtual size_t
- GetNumObjects () const
+ size_t
+ GetNumObjects() const override
{
if (m_archive_sp)
return m_archive_sp->GetNumObjects();
return 0;
}
- virtual void
- Dump (lldb_private::Stream *s) const;
- virtual lldb::ObjectFileSP
- GetObjectFile (const lldb_private::FileSpec *file);
+ void
+ Dump(lldb_private::Stream *s) const override;
+
+ lldb::ObjectFileSP
+ GetObjectFile(const lldb_private::FileSpec *file) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
protected:
-
struct Object
{
Object();
@@ -127,6 +128,13 @@ protected:
typedef std::shared_ptr<Archive> shared_ptr;
typedef std::multimap<lldb_private::FileSpec, shared_ptr> Map;
+ Archive(const lldb_private::ArchSpec &arch,
+ const lldb_private::TimeValue &mod_time,
+ lldb::offset_t file_offset,
+ lldb_private::DataExtractor &data);
+
+ ~Archive();
+
static Map &
GetArchiveCache ();
@@ -146,13 +154,6 @@ protected:
lldb::offset_t file_offset,
lldb_private::DataExtractor &data);
- Archive (const lldb_private::ArchSpec &arch,
- const lldb_private::TimeValue &mod_time,
- lldb::offset_t file_offset,
- lldb_private::DataExtractor &data);
-
- ~Archive ();
-
size_t
GetNumObjects () const
{
@@ -226,4 +227,4 @@ protected:
Archive::shared_ptr m_archive_sp;
};
-#endif // liblldb_ObjectContainerBSDArchive_h_
+#endif // liblldb_ObjectContainerBSDArchive_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index ff51c2e..4777f09 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -11,6 +11,7 @@
#include <cassert>
#include <algorithm>
+#include <unordered_map>
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataBuffer.h"
@@ -48,6 +49,8 @@ const char *const LLDB_NT_OWNER_GNU = "GNU";
const char *const LLDB_NT_OWNER_NETBSD = "NetBSD";
const char *const LLDB_NT_OWNER_CSR = "csr";
const char *const LLDB_NT_OWNER_ANDROID = "Android";
+const char *const LLDB_NT_OWNER_CORE = "CORE";
+const char *const LLDB_NT_OWNER_LINUX = "LINUX";
// ELF note type definitions
const elf_word LLDB_NT_FREEBSD_ABI_TAG = 0x01;
@@ -66,6 +69,41 @@ const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00;
const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01;
const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
+// LLDB_NT_OWNER_CORE and LLDB_NT_OWNER_LINUX note contants
+#define NT_PRSTATUS 1
+#define NT_PRFPREG 2
+#define NT_PRPSINFO 3
+#define NT_TASKSTRUCT 4
+#define NT_AUXV 6
+#define NT_SIGINFO 0x53494749
+#define NT_FILE 0x46494c45
+#define NT_PRXFPREG 0x46e62b7f
+#define NT_PPC_VMX 0x100
+#define NT_PPC_SPE 0x101
+#define NT_PPC_VSX 0x102
+#define NT_386_TLS 0x200
+#define NT_386_IOPERM 0x201
+#define NT_X86_XSTATE 0x202
+#define NT_S390_HIGH_GPRS 0x300
+#define NT_S390_TIMER 0x301
+#define NT_S390_TODCMP 0x302
+#define NT_S390_TODPREG 0x303
+#define NT_S390_CTRS 0x304
+#define NT_S390_PREFIX 0x305
+#define NT_S390_LAST_BREAK 0x306
+#define NT_S390_SYSTEM_CALL 0x307
+#define NT_S390_TDB 0x308
+#define NT_S390_VXRS_LOW 0x309
+#define NT_S390_VXRS_HIGH 0x30a
+#define NT_ARM_VFP 0x400
+#define NT_ARM_TLS 0x401
+#define NT_ARM_HW_BREAK 0x402
+#define NT_ARM_HW_WATCH 0x403
+#define NT_ARM_SYSTEM_CALL 0x404
+#define NT_METAG_CBUF 0x500
+#define NT_METAG_RPIPE 0x501
+#define NT_METAG_TLS 0x502
+
//===----------------------------------------------------------------------===//
/// @class ELFRelocation
/// @brief Generic wrapper for ELFRel and ELFRela.
@@ -81,7 +119,7 @@ public:
///
/// @param type Either DT_REL or DT_RELA. Any other value is invalid.
ELFRelocation(unsigned type);
-
+
~ELFRelocation();
bool
@@ -118,7 +156,7 @@ private:
};
ELFRelocation::ELFRelocation(unsigned type)
-{
+{
if (type == DT_REL || type == SHT_REL)
reloc = new ELFRel();
else if (type == DT_RELA || type == SHT_RELA)
@@ -134,7 +172,7 @@ ELFRelocation::~ELFRelocation()
if (reloc.is<ELFRel*>())
delete reloc.get<ELFRel*>();
else
- delete reloc.get<ELFRela*>();
+ delete reloc.get<ELFRela*>();
}
bool
@@ -277,7 +315,7 @@ kalimbaVariantFromElfFlags(const elf::elf_word e_flags)
kal_arch_variant = llvm::Triple::KalimbaSubArch_v5;
break;
default:
- break;
+ break;
}
return kal_arch_variant;
}
@@ -290,12 +328,17 @@ mipsVariantFromElfFlags(const elf::elf_word e_flags, uint32_t endian)
switch (mips_arch)
{
+ case llvm::ELF::EF_MIPS_ARCH_1:
+ case llvm::ELF::EF_MIPS_ARCH_2:
case llvm::ELF::EF_MIPS_ARCH_32:
return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32el : ArchSpec::eMIPSSubType_mips32;
case llvm::ELF::EF_MIPS_ARCH_32R2:
return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r2el : ArchSpec::eMIPSSubType_mips32r2;
case llvm::ELF::EF_MIPS_ARCH_32R6:
return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r6el : ArchSpec::eMIPSSubType_mips32r6;
+ case llvm::ELF::EF_MIPS_ARCH_3:
+ case llvm::ELF::EF_MIPS_ARCH_4:
+ case llvm::ELF::EF_MIPS_ARCH_5:
case llvm::ELF::EF_MIPS_ARCH_64:
return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64el : ArchSpec::eMIPSSubType_mips64;
case llvm::ELF::EF_MIPS_ARCH_64R2:
@@ -427,9 +470,9 @@ ObjectFileELF::CreateInstance (const lldb::ModuleSP &module_sp,
ObjectFile*
-ObjectFileELF::CreateMemoryInstance (const lldb::ModuleSP &module_sp,
- DataBufferSP& data_sp,
- const lldb::ProcessSP &process_sp,
+ObjectFileELF::CreateMemoryInstance (const lldb::ModuleSP &module_sp,
+ DataBufferSP& data_sp,
+ const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr)
{
if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT))
@@ -518,7 +561,7 @@ calc_crc32(uint32_t crc, const void *buf, size_t size)
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
- };
+ };
const uint8_t *p = (const uint8_t *)buf;
crc = crc ^ ~0U;
@@ -783,12 +826,12 @@ ObjectFileELF::GetPluginVersion()
// ObjectFile protocol
//------------------------------------------------------------------
-ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
+ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
DataBufferSP& data_sp,
lldb::offset_t data_offset,
- const FileSpec* file,
+ const FileSpec* file,
lldb::offset_t file_offset,
- lldb::offset_t length) :
+ lldb::offset_t length) :
ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
m_header(),
m_uuid(),
@@ -847,40 +890,52 @@ ObjectFileELF::SetLoadAddress (Target &target,
SectionList *section_list = GetSectionList ();
if (section_list)
{
- if (value_is_offset)
+ if (!value_is_offset)
{
- const size_t num_sections = section_list->GetSize();
- size_t sect_idx = 0;
-
- for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
+ bool found_offset = false;
+ for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i)
{
- // Iterate through the object file sections to find all
- // of the sections that have SHF_ALLOC in their flag bits.
- SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
- // if (section_sp && !section_sp->IsThreadSpecific())
- if (section_sp && section_sp->Test(SHF_ALLOC))
- {
- lldb::addr_t load_addr = section_sp->GetFileAddress() + value;
-
- // On 32-bit systems the load address have to fit into 4 bytes. The rest of
- // the bytes are the overflow from the addition.
- if (GetAddressByteSize() == 4)
- load_addr &= 0xFFFFFFFF;
-
- if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr))
- ++num_loaded_sections;
- }
+ const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i);
+ if (header == nullptr)
+ continue;
+
+ if (header->p_type != PT_LOAD || header->p_offset != 0)
+ continue;
+
+ value = value - header->p_vaddr;
+ found_offset = true;
+ break;
}
- return num_loaded_sections > 0;
+ if (!found_offset)
+ return false;
}
- else
+
+ const size_t num_sections = section_list->GetSize();
+ size_t sect_idx = 0;
+
+ for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
{
- // Not sure how to slide an ELF file given the base address
- // of the ELF file in memory
+ // Iterate through the object file sections to find all
+ // of the sections that have SHF_ALLOC in their flag bits.
+ SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
+ // if (section_sp && !section_sp->IsThreadSpecific())
+ if (section_sp && section_sp->Test(SHF_ALLOC))
+ {
+ lldb::addr_t load_addr = section_sp->GetFileAddress() + value;
+
+ // On 32-bit systems the load address have to fit into 4 bytes. The rest of
+ // the bytes are the overflow from the addition.
+ if (GetAddressByteSize() == 4)
+ load_addr &= 0xFFFFFFFF;
+
+ if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr))
+ ++num_loaded_sections;
+ }
}
+ return num_loaded_sections > 0;
}
}
- return false; // If it changed
+ return false;
}
ByteOrder
@@ -899,14 +954,20 @@ ObjectFileELF::GetAddressByteSize() const
return m_data.GetAddressByteSize();
}
-// Top 16 bits of the `Symbol` flags are available.
-#define ARM_ELF_SYM_IS_THUMB (1 << 16)
-
AddressClass
ObjectFileELF::GetAddressClass (addr_t file_addr)
{
- auto res = ObjectFile::GetAddressClass (file_addr);
+ Symtab* symtab = GetSymtab();
+ if (!symtab)
+ return eAddressClassUnknown;
+
+ // The address class is determined based on the symtab. Ask it from the object file what
+ // contains the symtab information.
+ ObjectFile* symtab_objfile = symtab->GetObjectFile();
+ if (symtab_objfile != nullptr && symtab_objfile != this)
+ return symtab_objfile->GetAddressClass(file_addr);
+ auto res = ObjectFile::GetAddressClass (file_addr);
if (res != eAddressClassCode)
return res;
@@ -1076,16 +1137,35 @@ ObjectFileELF::GetImageInfoAddress(Target *target)
addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
return Address(dynsym_section_sp, offset);
}
- else if (symbol.d_tag == DT_MIPS_RLD_MAP && target)
+ // MIPS executables uses DT_MIPS_RLD_MAP_REL to support PIE. DT_MIPS_RLD_MAP exists in non-PIE.
+ else if ((symbol.d_tag == DT_MIPS_RLD_MAP || symbol.d_tag == DT_MIPS_RLD_MAP_REL) && target)
{
addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
addr_t dyn_base = dynsym_section_sp->GetLoadBaseAddress(target);
if (dyn_base == LLDB_INVALID_ADDRESS)
return Address();
- Address addr;
+
Error error;
- if (target->ReadPointerFromMemory(dyn_base + offset, false, error, addr))
- return addr;
+ if (symbol.d_tag == DT_MIPS_RLD_MAP)
+ {
+ // DT_MIPS_RLD_MAP tag stores an absolute address of the debug pointer.
+ Address addr;
+ if (target->ReadPointerFromMemory(dyn_base + offset, false, error, addr))
+ return addr;
+ }
+ if (symbol.d_tag == DT_MIPS_RLD_MAP_REL)
+ {
+ // DT_MIPS_RLD_MAP_REL tag stores the offset to the debug pointer, relative to the address of the tag.
+ uint64_t rel_offset;
+ rel_offset = target->ReadUnsignedIntegerFromMemory(dyn_base + offset, false, GetAddressByteSize(), UINT64_MAX, error);
+ if (error.Success() && rel_offset != UINT64_MAX)
+ {
+ Address addr;
+ addr_t debug_ptr_address = dyn_base + (offset - GetAddressByteSize()) + rel_offset;
+ addr.SetOffset (debug_ptr_address);
+ return addr;
+ }
+ }
}
}
@@ -1093,7 +1173,7 @@ ObjectFileELF::GetImageInfoAddress(Target *target)
}
lldb_private::Address
-ObjectFileELF::GetEntryPointAddress ()
+ObjectFileELF::GetEntryPointAddress ()
{
if (m_entry_point_address.IsValid())
return m_entry_point_address;
@@ -1104,7 +1184,7 @@ ObjectFileELF::GetEntryPointAddress ()
SectionList *section_list = GetSectionList();
addr_t offset = m_header.e_entry;
- if (!section_list)
+ if (!section_list)
m_entry_point_address.SetOffset(offset);
else
m_entry_point_address.ResolveAddressUsingFileSections(offset, section_list);
@@ -1232,6 +1312,7 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
while (true)
{
// Parse the note header. If this fails, bail out.
+ const lldb::offset_t note_offset = offset;
ELFNote note = ELFNote();
if (!note.Parse(data, &offset))
{
@@ -1239,11 +1320,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
return error;
}
- // If a tag processor handles the tag, it should set processed to true, and
- // the loop will assume the tag processing has moved entirely past the note's payload.
- // Otherwise, leave it false and the end of the loop will handle the offset properly.
- bool processed = false;
-
if (log)
log->Printf ("ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, __FUNCTION__, note.n_name.c_str (), note.n_type);
@@ -1252,9 +1328,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
(note.n_type == LLDB_NT_FREEBSD_ABI_TAG) &&
(note.n_descsz == LLDB_NT_FREEBSD_ABI_SIZE))
{
- // We'll consume the payload below.
- processed = true;
-
// Pull out the min version info.
uint32_t version_info;
if (data.GetU32 (&offset, &version_info, 1) == nullptr)
@@ -1285,9 +1358,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
case LLDB_NT_GNU_ABI_TAG:
if (note.n_descsz == LLDB_NT_GNU_ABI_SIZE)
{
- // We'll consume the payload below.
- processed = true;
-
// Pull out the min OS version supporting the ABI.
uint32_t version_info[4];
if (data.GetU32 (&offset, &version_info[0], note.n_descsz / 4) == nullptr)
@@ -1330,9 +1400,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
// Only bother processing this if we don't already have the uuid set.
if (!uuid.IsValid())
{
- // We'll consume the payload below.
- processed = true;
-
// 16 bytes is UUID|MD5, 20 bytes is SHA1
if ((note.n_descsz == 16 || note.n_descsz == 20))
{
@@ -1355,10 +1422,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
(note.n_type == LLDB_NT_NETBSD_ABI_TAG) &&
(note.n_descsz == LLDB_NT_NETBSD_ABI_SIZE))
{
-
- // We'll consume the payload below.
- processed = true;
-
// Pull out the min version info.
uint32_t version_info;
if (data.GetU32 (&offset, &version_info, 1) == nullptr)
@@ -1378,8 +1441,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
else if ((note.n_type == LLDB_NT_GNU_ABI_TAG) &&
(note.n_name == LLDB_NT_OWNER_CSR))
{
- // We'll consume the payload below.
- processed = true;
arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);
arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR);
@@ -1397,9 +1458,48 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
arch_spec.GetTriple().setEnvironment(llvm::Triple::EnvironmentType::Android);
}
+ else if (note.n_name == LLDB_NT_OWNER_LINUX)
+ {
+ // This is sometimes found in core files and usually contains extended register info
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
+ }
+ else if (note.n_name == LLDB_NT_OWNER_CORE)
+ {
+ // Parse the NT_FILE to look for stuff in paths to shared libraries
+ // As the contents look like:
+ // count = 0x000000000000000a (10)
+ // page_size = 0x0000000000001000 (4096)
+ // Index start end file_ofs path
+ // ===== ------------------ ------------------ ------------------ -------------------------------------
+ // [ 0] 0x0000000000400000 0x0000000000401000 0x0000000000000000 /tmp/a.out
+ // [ 1] 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out
+ // [ 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
+ // [ 3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000 /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so
+ // [ 8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64-linux-gnu/ld-2.19.so
+ // [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so
+ if (note.n_type == NT_FILE)
+ {
+ uint64_t count = data.GetU64(&offset);
+ offset += 8 + 3*8*count; // Skip page size and all start/end/file_ofs
+ for (size_t i=0; i<count; ++i)
+ {
+ llvm::StringRef path(data.GetCStr(&offset));
+ if (path.startswith("/lib/x86_64-linux-gnu"))
+ {
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
+ break;
+ }
+ }
+ }
+ }
- if (!processed)
- offset += llvm::RoundUpToAlignment(note.n_descsz, 4);
+ // Calculate the offset of the next note just in case "offset" has been used
+ // to poke at the contents of the note data
+ offset = note_offset + note.GetByteSize();
}
return error;
@@ -1442,16 +1542,16 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
{
switch (header.e_flags & llvm::ELF::EF_MIPS_ARCH_ASE)
{
- case llvm::ELF::EF_MIPS_MICROMIPS:
- arch_spec.SetFlags (ArchSpec::eMIPSAse_micromips);
+ case llvm::ELF::EF_MIPS_MICROMIPS:
+ arch_spec.SetFlags (ArchSpec::eMIPSAse_micromips);
break;
- case llvm::ELF::EF_MIPS_ARCH_ASE_M16:
- arch_spec.SetFlags (ArchSpec::eMIPSAse_mips16);
+ case llvm::ELF::EF_MIPS_ARCH_ASE_M16:
+ arch_spec.SetFlags (ArchSpec::eMIPSAse_mips16);
break;
- case llvm::ELF::EF_MIPS_ARCH_ASE_MDMX:
- arch_spec.SetFlags (ArchSpec::eMIPSAse_mdmx);
+ case llvm::ELF::EF_MIPS_ARCH_ASE_MDMX:
+ arch_spec.SetFlags (ArchSpec::eMIPSAse_mdmx);
break;
- default:
+ default:
break;
}
}
@@ -1501,8 +1601,8 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
I != section_headers.end(); ++I)
{
static ConstString g_sect_name_gnu_debuglink (".gnu_debuglink");
- const ELFSectionHeaderInfo &header = *I;
- const uint64_t section_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
+ const ELFSectionHeaderInfo &sheader = *I;
+ const uint64_t section_size = sheader.sh_type == SHT_NOBITS ? 0 : sheader.sh_size;
ConstString name(shstr_data.PeekCStr(I->sh_name));
I->section_name = name;
@@ -1510,23 +1610,33 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
if (arch_spec.GetMachine() == llvm::Triple::mips || arch_spec.GetMachine() == llvm::Triple::mipsel
|| arch_spec.GetMachine() == llvm::Triple::mips64 || arch_spec.GetMachine() == llvm::Triple::mips64el)
{
- if (header.sh_type == SHT_MIPS_ABIFLAGS)
+ uint32_t arch_flags = arch_spec.GetFlags ();
+ DataExtractor data;
+ if (sheader.sh_type == SHT_MIPS_ABIFLAGS)
{
- DataExtractor data;
- if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size))
+
+ if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))
{
lldb::offset_t ase_offset = 12; // MIPS ABI Flags Version: 0
- uint32_t arch_flags = arch_spec.GetFlags ();
arch_flags |= data.GetU32 (&ase_offset);
- arch_spec.SetFlags (arch_flags);
}
}
+ // Settings appropriate ArchSpec ABI Flags
+ if (header.e_flags & llvm::ELF::EF_MIPS_ABI2)
+ {
+ arch_flags |= lldb_private::ArchSpec::eMIPSABI_N32;
+ }
+ else if (header.e_flags & llvm::ELF::EF_MIPS_ABI_O32)
+ {
+ arch_flags |= lldb_private::ArchSpec::eMIPSABI_O32;
+ }
+ arch_spec.SetFlags (arch_flags);
}
if (name == g_sect_name_gnu_debuglink)
{
DataExtractor data;
- if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size))
+ if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))
{
lldb::offset_t gnu_debuglink_offset = 0;
gnu_debuglink_file = data.GetCStr (&gnu_debuglink_offset);
@@ -1536,7 +1646,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
}
// Process ELF note section entries.
- bool is_note_header = (header.sh_type == SHT_NOTE);
+ bool is_note_header = (sheader.sh_type == SHT_NOTE);
// The section header ".note.android.ident" is stored as a
// PROGBITS type header but it is actually a note header.
@@ -1548,7 +1658,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
{
// Allow notes to refine module info.
DataExtractor data;
- if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size))
+ if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))
{
Error error = RefineModuleDetailsFromNote (data, arch_spec, uuid);
if (error.Fail ())
@@ -1560,6 +1670,12 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
}
}
+ // Make any unknown triple components to be unspecified unknowns.
+ if (arch_spec.GetTriple().getVendor() == llvm::Triple::UnknownVendor)
+ arch_spec.GetTriple().setVendorName (llvm::StringRef());
+ if (arch_spec.GetTriple().getOS() == llvm::Triple::UnknownOS)
+ arch_spec.GetTriple().setOSName (llvm::StringRef());
+
return section_headers.size();
}
}
@@ -1586,7 +1702,7 @@ ObjectFileELF::GetProgramHeaderByIndex(lldb::user_id_t id)
return NULL;
}
-DataExtractor
+DataExtractor
ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id)
{
const elf::ELFProgramHeader *segment_header = GetProgramHeaderByIndex(id);
@@ -1656,17 +1772,30 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
static ConstString g_sect_name_tdata (".tdata");
static ConstString g_sect_name_tbss (".tbss");
static ConstString g_sect_name_dwarf_debug_abbrev (".debug_abbrev");
+ static ConstString g_sect_name_dwarf_debug_addr (".debug_addr");
static ConstString g_sect_name_dwarf_debug_aranges (".debug_aranges");
static ConstString g_sect_name_dwarf_debug_frame (".debug_frame");
static ConstString g_sect_name_dwarf_debug_info (".debug_info");
static ConstString g_sect_name_dwarf_debug_line (".debug_line");
static ConstString g_sect_name_dwarf_debug_loc (".debug_loc");
static ConstString g_sect_name_dwarf_debug_macinfo (".debug_macinfo");
+ static ConstString g_sect_name_dwarf_debug_macro (".debug_macro");
static ConstString g_sect_name_dwarf_debug_pubnames (".debug_pubnames");
static ConstString g_sect_name_dwarf_debug_pubtypes (".debug_pubtypes");
static ConstString g_sect_name_dwarf_debug_ranges (".debug_ranges");
static ConstString g_sect_name_dwarf_debug_str (".debug_str");
+ static ConstString g_sect_name_dwarf_debug_str_offsets (".debug_str_offsets");
+ static ConstString g_sect_name_dwarf_debug_abbrev_dwo (".debug_abbrev.dwo");
+ static ConstString g_sect_name_dwarf_debug_info_dwo (".debug_info.dwo");
+ static ConstString g_sect_name_dwarf_debug_line_dwo (".debug_line.dwo");
+ static ConstString g_sect_name_dwarf_debug_macro_dwo (".debug_macro.dwo");
+ static ConstString g_sect_name_dwarf_debug_loc_dwo (".debug_loc.dwo");
+ static ConstString g_sect_name_dwarf_debug_str_dwo (".debug_str.dwo");
+ static ConstString g_sect_name_dwarf_debug_str_offsets_dwo (".debug_str_offsets.dwo");
static ConstString g_sect_name_eh_frame (".eh_frame");
+ static ConstString g_sect_name_arm_exidx (".ARM.exidx");
+ static ConstString g_sect_name_arm_extab (".ARM.extab");
+ static ConstString g_sect_name_go_symtab (".gosymtab");
SectionType sect_type = eSectionTypeOther;
@@ -1678,12 +1807,12 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
else if (name == g_sect_name_tdata)
{
sect_type = eSectionTypeData;
- is_thread_specific = true;
+ is_thread_specific = true;
}
else if (name == g_sect_name_tbss)
{
- sect_type = eSectionTypeZeroFill;
- is_thread_specific = true;
+ sect_type = eSectionTypeZeroFill;
+ is_thread_specific = true;
}
// .debug_abbrev – Abbreviations used in the .debug_info section
// .debug_aranges – Lookup table for mapping addresses to compilation units
@@ -1699,18 +1828,31 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
// MISSING? .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section, http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
// MISSING? .debug-index - http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644
// MISSING? .debug_types - Type descriptions from DWARF 4? See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
- else if (name == g_sect_name_dwarf_debug_abbrev) sect_type = eSectionTypeDWARFDebugAbbrev;
- else if (name == g_sect_name_dwarf_debug_aranges) sect_type = eSectionTypeDWARFDebugAranges;
- else if (name == g_sect_name_dwarf_debug_frame) sect_type = eSectionTypeDWARFDebugFrame;
- else if (name == g_sect_name_dwarf_debug_info) sect_type = eSectionTypeDWARFDebugInfo;
- else if (name == g_sect_name_dwarf_debug_line) sect_type = eSectionTypeDWARFDebugLine;
- else if (name == g_sect_name_dwarf_debug_loc) sect_type = eSectionTypeDWARFDebugLoc;
- else if (name == g_sect_name_dwarf_debug_macinfo) sect_type = eSectionTypeDWARFDebugMacInfo;
- else if (name == g_sect_name_dwarf_debug_pubnames) sect_type = eSectionTypeDWARFDebugPubNames;
- else if (name == g_sect_name_dwarf_debug_pubtypes) sect_type = eSectionTypeDWARFDebugPubTypes;
- else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges;
- else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr;
- else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame;
+ else if (name == g_sect_name_dwarf_debug_abbrev) sect_type = eSectionTypeDWARFDebugAbbrev;
+ else if (name == g_sect_name_dwarf_debug_addr) sect_type = eSectionTypeDWARFDebugAddr;
+ else if (name == g_sect_name_dwarf_debug_aranges) sect_type = eSectionTypeDWARFDebugAranges;
+ else if (name == g_sect_name_dwarf_debug_frame) sect_type = eSectionTypeDWARFDebugFrame;
+ else if (name == g_sect_name_dwarf_debug_info) sect_type = eSectionTypeDWARFDebugInfo;
+ else if (name == g_sect_name_dwarf_debug_line) sect_type = eSectionTypeDWARFDebugLine;
+ else if (name == g_sect_name_dwarf_debug_loc) sect_type = eSectionTypeDWARFDebugLoc;
+ else if (name == g_sect_name_dwarf_debug_macinfo) sect_type = eSectionTypeDWARFDebugMacInfo;
+ else if (name == g_sect_name_dwarf_debug_macro) sect_type = eSectionTypeDWARFDebugMacro;
+ else if (name == g_sect_name_dwarf_debug_pubnames) sect_type = eSectionTypeDWARFDebugPubNames;
+ else if (name == g_sect_name_dwarf_debug_pubtypes) sect_type = eSectionTypeDWARFDebugPubTypes;
+ else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges;
+ else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr;
+ else if (name == g_sect_name_dwarf_debug_str_offsets) sect_type = eSectionTypeDWARFDebugStrOffsets;
+ else if (name == g_sect_name_dwarf_debug_abbrev_dwo) sect_type = eSectionTypeDWARFDebugAbbrev;
+ else if (name == g_sect_name_dwarf_debug_info_dwo) sect_type = eSectionTypeDWARFDebugInfo;
+ else if (name == g_sect_name_dwarf_debug_line_dwo) sect_type = eSectionTypeDWARFDebugLine;
+ else if (name == g_sect_name_dwarf_debug_macro_dwo) sect_type = eSectionTypeDWARFDebugMacro;
+ else if (name == g_sect_name_dwarf_debug_loc_dwo) sect_type = eSectionTypeDWARFDebugLoc;
+ else if (name == g_sect_name_dwarf_debug_str_dwo) sect_type = eSectionTypeDWARFDebugStr;
+ else if (name == g_sect_name_dwarf_debug_str_offsets_dwo) sect_type = eSectionTypeDWARFDebugStrOffsets;
+ else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame;
+ else if (name == g_sect_name_arm_exidx) sect_type = eSectionTypeARMexidx;
+ else if (name == g_sect_name_arm_extab) sect_type = eSectionTypeARMextab;
+ else if (name == g_sect_name_go_symtab) sect_type = eSectionTypeGoSymtab;
switch (header.sh_type)
{
@@ -1736,13 +1878,13 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
if (eSectionTypeOther == sect_type)
{
// the kalimba toolchain assumes that ELF section names are free-form. It does
- // supports linkscripts which (can) give rise to various arbitarily named
- // sections being "Code" or "Data".
+ // support linkscripts which (can) give rise to various arbitrarily named
+ // sections being "Code" or "Data".
sect_type = kalimbaSectionType(m_header, header);
}
const uint32_t target_bytes_size =
- (eSectionTypeData == sect_type || eSectionTypeZeroFill == sect_type) ?
+ (eSectionTypeData == sect_type || eSectionTypeZeroFill == sect_type) ?
m_arch_spec.GetDataByteSize() :
eSectionTypeCode == sect_type ?
m_arch_spec.GetCodeByteSize() : 1;
@@ -1775,17 +1917,19 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
{
static const SectionType g_sections[] =
{
- eSectionTypeDWARFDebugAranges,
- eSectionTypeDWARFDebugInfo,
eSectionTypeDWARFDebugAbbrev,
+ eSectionTypeDWARFDebugAddr,
+ eSectionTypeDWARFDebugAranges,
eSectionTypeDWARFDebugFrame,
+ eSectionTypeDWARFDebugInfo,
eSectionTypeDWARFDebugLine,
- eSectionTypeDWARFDebugStr,
eSectionTypeDWARFDebugLoc,
eSectionTypeDWARFDebugMacInfo,
eSectionTypeDWARFDebugPubNames,
eSectionTypeDWARFDebugPubTypes,
eSectionTypeDWARFDebugRanges,
+ eSectionTypeDWARFDebugStr,
+ eSectionTypeDWARFDebugStrOffsets,
eSectionTypeELFSymbolTable,
};
SectionList *elf_section_list = m_sections_ap.get();
@@ -1810,6 +1954,29 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
}
}
+// Find the arm/aarch64 mapping symbol character in the given symbol name. Mapping symbols have the
+// form of "$<char>[.<any>]*". Additionally we recognize cases when the mapping symbol prefixed by
+// an arbitrary string because if a symbol prefix added to each symbol in the object file with
+// objcopy then the mapping symbols are also prefixed.
+static char
+FindArmAarch64MappingSymbol(const char* symbol_name)
+{
+ if (!symbol_name)
+ return '\0';
+
+ const char* dollar_pos = ::strchr(symbol_name, '$');
+ if (!dollar_pos || dollar_pos[1] == '\0')
+ return '\0';
+
+ if (dollar_pos[2] == '\0' || dollar_pos[2] == '.')
+ return dollar_pos[1];
+ return '\0';
+}
+
+#define STO_MIPS_ISA (3 << 6)
+#define STO_MICROMIPS (2 << 6)
+#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER) & STO_MIPS_ISA) == STO_MICROMIPS)
+
// private
unsigned
ObjectFileELF::ParseSymbols (Symtab *symtab,
@@ -1845,12 +2012,19 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
// makes it highly unlikely that this will collide with anything else.
bool skip_oatdata_oatexec = m_file.GetFilename() == ConstString("system@framework@boot.oat");
+ ArchSpec arch;
+ GetArchitecture(arch);
+
+ // Local cache to avoid doing a FindSectionByName for each symbol. The "const char*" key must
+ // came from a ConstString object so they can be compared by pointer
+ std::unordered_map<const char*, lldb::SectionSP> section_name_to_section;
+
unsigned i;
for (i = 0; i < num_symbols; ++i)
{
if (symbol.Parse(symtab_data, &offset) == false)
break;
-
+
const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
// No need to add non-section symbols that have no names
@@ -1950,64 +2124,58 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
int64_t symbol_value_offset = 0;
uint32_t additional_flags = 0;
- ArchSpec arch;
- if (GetArchitecture(arch))
+ if (arch.IsValid())
{
if (arch.GetMachine() == llvm::Triple::arm)
{
- if (symbol.getBinding() == STB_LOCAL && symbol_name && symbol_name[0] == '$')
+ if (symbol.getBinding() == STB_LOCAL)
{
- // These are reserved for the specification (e.g.: mapping
- // symbols). We don't want to add them to the symbol table.
-
+ char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);
if (symbol_type == eSymbolTypeCode)
{
- llvm::StringRef symbol_name_ref(symbol_name);
- if (symbol_name_ref == "$a" || symbol_name_ref.startswith("$a."))
+ switch (mapping_symbol)
{
- // $a[.<any>]* - marks an ARM instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCode;
- }
- else if (symbol_name_ref == "$b" || symbol_name_ref.startswith("$b.") ||
- symbol_name_ref == "$t" || symbol_name_ref.startswith("$t."))
- {
- // $b[.<any>]* - marks a THUMB BL instruction sequence
- // $t[.<any>]* - marks a THUMB instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
- }
- else if (symbol_name_ref == "$d" || symbol_name_ref.startswith("$d."))
- {
- // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ case 'a':
+ // $a[.<any>]* - marks an ARM instruction sequence
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
+ break;
+ case 'b':
+ case 't':
+ // $b[.<any>]* - marks a THUMB BL instruction sequence
+ // $t[.<any>]* - marks a THUMB instruction sequence
+ m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ break;
+ case 'd':
+ // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
+ m_address_class_map[symbol.st_value] = eAddressClassData;
+ break;
}
}
-
- continue;
+ if (mapping_symbol)
+ continue;
}
}
else if (arch.GetMachine() == llvm::Triple::aarch64)
{
- if (symbol.getBinding() == STB_LOCAL && symbol_name && symbol_name[0] == '$')
+ if (symbol.getBinding() == STB_LOCAL)
{
- // These are reserved for the specification (e.g.: mapping
- // symbols). We don't want to add them to the symbol table.
-
+ char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);
if (symbol_type == eSymbolTypeCode)
{
- llvm::StringRef symbol_name_ref(symbol_name);
- if (symbol_name_ref == "$x" || symbol_name_ref.startswith("$x."))
- {
- // $x[.<any>]* - marks an A64 instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCode;
- }
- else if (symbol_name_ref == "$d" || symbol_name_ref.startswith("$d."))
+ switch (mapping_symbol)
{
- // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ case 'x':
+ // $x[.<any>]* - marks an A64 instruction sequence
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
+ break;
+ case 'd':
+ // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
+ m_address_class_map[symbol.st_value] = eAddressClassData;
+ break;
}
}
-
- continue;
+ if (mapping_symbol)
+ continue;
}
}
@@ -2024,7 +2192,6 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
// symbol.st_value to produce the final symbol_value
// that we store in the symtab.
symbol_value_offset = -1;
- additional_flags = ARM_ELF_SYM_IS_THUMB;
m_address_class_map[symbol.st_value^1] = eAddressClassCodeAlternateISA;
}
else
@@ -2034,11 +2201,46 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
}
}
}
+
+ /*
+ * MIPS:
+ * The bit #0 of an address is used for ISA mode (1 for microMIPS, 0 for MIPS).
+ * This allows processer to switch between microMIPS and MIPS without any need
+ * for special mode-control register. However, apart from .debug_line, none of
+ * the ELF/DWARF sections set the ISA bit (for symbol or section). Use st_other
+ * flag to check whether the symbol is microMIPS and then set the address class
+ * accordingly.
+ */
+ const llvm::Triple::ArchType llvm_arch = arch.GetMachine();
+ if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel
+ || llvm_arch == llvm::Triple::mips64 || llvm_arch == llvm::Triple::mips64el)
+ {
+ if (IS_MICROMIPS(symbol.st_other))
+ m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode))
+ {
+ symbol.st_value = symbol.st_value & (~1ull);
+ m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ }
+ else
+ {
+ if (symbol_type == eSymbolTypeCode)
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
+ else if (symbol_type == eSymbolTypeData)
+ m_address_class_map[symbol.st_value] = eAddressClassData;
+ else
+ m_address_class_map[symbol.st_value] = eAddressClassUnknown;
+ }
+ }
}
- // If the symbol section we've found has no data (SHT_NOBITS), then check the module section
- // list. This can happen if we're parsing the debug file and it has no .text section, for example.
- if (symbol_section_sp && (symbol_section_sp->GetFileSize() == 0))
+ // symbol_value_offset may contain 0 for ARM symbols or -1 for
+ // THUMB symbols. See above for more details.
+ uint64_t symbol_value = symbol.st_value + symbol_value_offset;
+ if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile)
+ symbol_value -= symbol_section_sp->GetFileAddress();
+
+ if (symbol_section_sp)
{
ModuleSP module_sp(GetModule());
if (module_sp)
@@ -2047,20 +2249,17 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
if (module_section_list && module_section_list != section_list)
{
const ConstString &sect_name = symbol_section_sp->GetName();
- lldb::SectionSP section_sp (module_section_list->FindSectionByName (sect_name));
- if (section_sp && section_sp->GetFileSize())
- {
- symbol_section_sp = section_sp;
- }
+ auto section_it = section_name_to_section.find(sect_name.GetCString());
+ if (section_it == section_name_to_section.end())
+ section_it = section_name_to_section.emplace(
+ sect_name.GetCString(),
+ module_section_list->FindSectionByName (sect_name)).first;
+ if (section_it->second && section_it->second->GetFileSize())
+ symbol_section_sp = section_it->second;
}
}
}
- // symbol_value_offset may contain 0 for ARM symbols or -1 for
- // THUMB symbols. See above for more details.
- uint64_t symbol_value = symbol.st_value + symbol_value_offset;
- if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile)
- symbol_value -= symbol_section_sp->GetFileAddress();
bool is_global = symbol.getBinding() == STB_GLOBAL;
uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags;
bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false;
@@ -2074,7 +2273,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
Mangled mangled(ConstString(symbol_bare), is_mangled);
// Now append the suffix back to mangled and unmangled names. Only do it if the
- // demangling was sucessful (string is not empty).
+ // demangling was successful (string is not empty).
if (has_suffix)
{
llvm::StringRef suffix = symbol_ref.substr(version_pos);
@@ -2127,7 +2326,7 @@ ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id, lldb_p
user_id_t symtab_id = symtab->GetID();
const ELFSectionHeaderInfo *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
- assert(symtab_hdr->sh_type == SHT_SYMTAB ||
+ assert(symtab_hdr->sh_type == SHT_SYMTAB ||
symtab_hdr->sh_type == SHT_DYNSYM);
// sh_link: section header index of associated string table.
@@ -2226,7 +2425,7 @@ ObjectFileELF::PLTRelocationType()
}
// Returns the size of the normal plt entries and the offset of the first normal plt entry. The
-// 0th entry in the plt table is ususally a resolution entry which have different size in some
+// 0th entry in the plt table is usually a resolution entry which have different size in some
// architectures then the rest of the plt entries.
static std::pair<uint64_t, uint64_t>
GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader* plt_hdr)
@@ -2242,8 +2441,8 @@ GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader
{
// The linker haven't set the plt_hdr->sh_entsize field. Try to guess the size of the plt
// entries based on the number of entries and the size of the plt section with the
- // asumption that the size of the 0th entry is at least as big as the size of the normal
- // entries and it isn't mutch bigger then that.
+ // assumption that the size of the 0th entry is at least as big as the size of the normal
+ // entries and it isn't much bigger then that.
if (plt_hdr->sh_addralign)
plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign / (num_relocations + 1) * plt_hdr->sh_addralign;
else
@@ -2403,16 +2602,16 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
if (!rel_type)
return 0;
- return ParsePLTRelocations (symbol_table,
- start_id,
+ return ParsePLTRelocations (symbol_table,
+ start_id,
rel_type,
- &m_header,
- rel_hdr,
- plt_hdr,
+ &m_header,
+ rel_hdr,
+ plt_hdr,
sym_hdr,
- plt_section_sp,
- rel_data,
- symtab_data,
+ plt_section_sp,
+ rel_data,
+ symtab_data,
strtab_data);
}
@@ -2568,8 +2767,6 @@ ObjectFileELF::GetSymtab()
uint64_t symbol_id = 0;
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
- m_symtab_ap.reset(new Symtab(this));
-
// Sharable objects and dynamic executables usually have 2 distinct symbol
// tables, one named ".symtab", and the other ".dynsym". The dynsym is a smaller
// version of the symtab that only contains global symbols. The information found
@@ -2583,7 +2780,10 @@ ObjectFileELF::GetSymtab()
symtab = section_list->FindSectionByType (eSectionTypeELFDynamicSymbols, true).get();
}
if (symtab)
+ {
+ m_symtab_ap.reset(new Symtab(symtab->GetObjectFile()));
symbol_id += ParseSymbolTable (m_symtab_ap.get(), symbol_id, symtab);
+ }
// DT_JMPREL
// If present, this entry's d_ptr member holds the address of relocation
@@ -2598,15 +2798,24 @@ ObjectFileELF::GetSymtab()
// Synthesize trampoline symbols to help navigate the PLT.
addr_t addr = symbol->d_ptr;
Section *reloc_section = section_list->FindSectionContainingFileAddress(addr).get();
- if (reloc_section)
+ if (reloc_section)
{
user_id_t reloc_id = reloc_section->GetID();
const ELFSectionHeaderInfo *reloc_header = GetSectionHeaderByIndex(reloc_id);
assert(reloc_header);
+ if (m_symtab_ap == nullptr)
+ m_symtab_ap.reset(new Symtab(reloc_section->GetObjectFile()));
+
ParseTrampolineSymbols (m_symtab_ap.get(), symbol_id, reloc_header, reloc_id);
}
}
+
+ // If we still don't have any symtab then create an empty instance to avoid do the section
+ // lookup next time.
+ if (m_symtab_ap == nullptr)
+ m_symtab_ap.reset(new Symtab(this));
+
m_symtab_ap->CalculateSymbolSizes();
}
@@ -3005,6 +3214,27 @@ ObjectFileELF::GetArchitecture (ArchSpec &arch)
ParseSectionHeaders();
}
+ if (CalculateType() == eTypeCoreFile && m_arch_spec.TripleOSIsUnspecifiedUnknown())
+ {
+ // Core files don't have section headers yet they have PT_NOTE program headers
+ // that might shed more light on the architecture
+ if (ParseProgramHeaders())
+ {
+ for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i)
+ {
+ const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i);
+ if (header && header->p_type == PT_NOTE && header->p_offset != 0 && header->p_filesz > 0)
+ {
+ DataExtractor data;
+ if (data.SetData (m_data, header->p_offset, header->p_filesz) == header->p_filesz)
+ {
+ lldb_private::UUID uuid;
+ RefineModuleDetailsFromNote (data, m_arch_spec, uuid);
+ }
+ }
+ }
+ }
+ }
arch = m_arch_spec;
return true;
}
@@ -3045,7 +3275,7 @@ ObjectFileELF::CalculateStrata()
{
switch (m_header.e_type)
{
- case llvm::ELF::ET_NONE:
+ case llvm::ELF::ET_NONE:
// 0 - No file type
return eStrataUnknown;
@@ -3056,21 +3286,21 @@ ObjectFileELF::CalculateStrata()
case llvm::ELF::ET_EXEC:
// 2 - Executable file
// TODO: is there any way to detect that an executable is a kernel
- // related executable by inspecting the program headers, section
+ // related executable by inspecting the program headers, section
// headers, symbols, or any other flag bits???
return eStrataUser;
case llvm::ELF::ET_DYN:
// 3 - Shared object file
// TODO: is there any way to detect that an shared library is a kernel
- // related executable by inspecting the program headers, section
+ // related executable by inspecting the program headers, section
// headers, symbols, or any other flag bits???
return eStrataUnknown;
case ET_CORE:
// 4 - Core file
// TODO: is there any way to detect that an core file is a kernel
- // related executable by inspecting the program headers, section
+ // related executable by inspecting the program headers, section
// headers, symbols, or any other flag bits???
return eStrataUnknown;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 99088d1..4b97f92 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -10,9 +10,14 @@
#ifndef liblldb_ObjectFileELF_h_
#define liblldb_ObjectFileELF_h_
+// C Includes
#include <stdint.h>
+
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -47,6 +52,12 @@ struct ELFNote
/// True if the ELFRel entry was successfully read and false otherwise.
bool
Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+ size_t
+ GetByteSize() const
+ {
+ return 12 + llvm::RoundUpToAlignment (n_namesz, 4) + llvm::RoundUpToAlignment (n_descsz, 4);
+ }
};
//------------------------------------------------------------------------------
@@ -59,6 +70,8 @@ class ObjectFileELF :
public lldb_private::ObjectFile
{
public:
+ ~ObjectFileELF() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -113,9 +126,6 @@ public:
//------------------------------------------------------------------
// ObjectFile Protocol.
//------------------------------------------------------------------
- virtual
- ~ObjectFileELF();
-
bool
ParseHeader() override;
@@ -211,6 +221,7 @@ private:
{
lldb_private::ConstString section_name;
};
+
typedef std::vector<ELFSectionHeaderInfo> SectionHeaderColl;
typedef SectionHeaderColl::iterator SectionHeaderCollIter;
typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;
@@ -428,4 +439,4 @@ private:
RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch_spec, lldb_private::UUID &uuid);
};
-#endif // #ifndef liblldb_ObjectFileELF_h_
+#endif // liblldb_ObjectFileELF_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
index 47140f5..39dbb3f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
@@ -10,10 +10,13 @@
#ifndef liblldb_ObjectFileJIT_h_
#define liblldb_ObjectFileJIT_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Symbol/ObjectFile.h"
-
//----------------------------------------------------------------------
// This class needs to be hidden as eventually belongs in a plugin that
// will export the ObjectFile protocol
@@ -22,6 +25,11 @@ class ObjectFileJIT :
public lldb_private::ObjectFile
{
public:
+ ObjectFileJIT(const lldb::ModuleSP &module_sp,
+ const lldb::ObjectFileJITDelegateSP &delegate_sp);
+
+ ~ObjectFileJIT() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -62,81 +70,77 @@ public:
//------------------------------------------------------------------
// Member Functions
//------------------------------------------------------------------
- ObjectFileJIT (const lldb::ModuleSP &module_sp,
- const lldb::ObjectFileJITDelegateSP &delegate_sp);
-
- virtual
- ~ObjectFileJIT();
-
- virtual bool
- ParseHeader ();
+ bool
+ ParseHeader() override;
- virtual bool
+ bool
SetLoadAddress(lldb_private::Target &target,
lldb::addr_t value,
- bool value_is_offset);
+ bool value_is_offset) override;
- virtual lldb::ByteOrder
- GetByteOrder () const;
+ lldb::ByteOrder
+ GetByteOrder() const override;
- virtual bool
- IsExecutable () const;
+ bool
+ IsExecutable() const override;
- virtual uint32_t
- GetAddressByteSize () const;
+ uint32_t
+ GetAddressByteSize() const override;
- virtual lldb_private::Symtab *
- GetSymtab();
+ lldb_private::Symtab *
+ GetSymtab() override;
- virtual bool
- IsStripped ();
+ bool
+ IsStripped() override;
- virtual void
- CreateSections (lldb_private::SectionList &unified_section_list);
+ void
+ CreateSections(lldb_private::SectionList &unified_section_list) override;
- virtual void
- Dump (lldb_private::Stream *s);
+ void
+ Dump(lldb_private::Stream *s) override;
- virtual bool
- GetArchitecture (lldb_private::ArchSpec &arch);
+ bool
+ GetArchitecture(lldb_private::ArchSpec &arch) override;
- virtual bool
- GetUUID (lldb_private::UUID* uuid);
+ bool
+ GetUUID(lldb_private::UUID* uuid) override;
- virtual uint32_t
- GetDependentModules (lldb_private::FileSpecList& files);
+ uint32_t
+ GetDependentModules(lldb_private::FileSpecList& files) override;
+
+ size_t
+ ReadSectionData(const lldb_private::Section *section,
+ lldb::offset_t section_offset,
+ void *dst,
+ size_t dst_len) const override;
+
+ size_t
+ ReadSectionData(const lldb_private::Section *section,
+ lldb_private::DataExtractor& section_data) const override;
- virtual size_t
- ReadSectionData (const lldb_private::Section *section,
- lldb::offset_t section_offset,
- void *dst,
- size_t dst_len) const;
- virtual size_t
- ReadSectionData (const lldb_private::Section *section,
- lldb_private::DataExtractor& section_data) const;
+ lldb_private::Address
+ GetEntryPointAddress() override;
+ lldb_private::Address
+ GetHeaderAddress() override;
+
+ ObjectFile::Type
+ CalculateType() override;
+
+ ObjectFile::Strata
+ CalculateStrata() override;
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
- virtual lldb_private::Address
- GetEntryPointAddress ();
-
- virtual lldb_private::Address
- GetHeaderAddress ();
-
- virtual ObjectFile::Type
- CalculateType();
-
- virtual ObjectFile::Strata
- CalculateStrata();
protected:
lldb::ObjectFileJITDelegateWP m_delegate_wp;
};
-#endif // liblldb_ObjectFileJIT_h_
+#endif // liblldb_ObjectFileJIT_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
new file mode 100644
index 0000000..86c574f
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
@@ -0,0 +1,559 @@
+//===-- OperatingSystemGo.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include <unordered_map>
+
+// Other libraries and framework includes
+// Project includes
+#include "OperatingSystemGo.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Interpreter/Options.h"
+#include "lldb/Interpreter/OptionGroupBoolean.h"
+#include "lldb/Interpreter/OptionGroupUInt64.h"
+#include "lldb/Interpreter/Property.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadList.h"
+#include "lldb/Target/Thread.h"
+#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
+#include "Plugins/Process/Utility/RegisterContextMemory.h"
+#include "Plugins/Process/Utility/ThreadMemory.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace
+{
+
+static PropertyDefinition g_properties[] = {{"enable", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
+ "Specify whether goroutines should be treated as threads."},
+ {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};
+
+enum
+{
+ ePropertyEnableGoroutines,
+};
+
+class PluginProperties : public Properties
+{
+public:
+ PluginProperties()
+ : Properties()
+ {
+ m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
+ m_collection_sp->Initialize(g_properties);
+ }
+
+ ~PluginProperties() override = default;
+
+ static ConstString
+ GetSettingName()
+ {
+ return OperatingSystemGo::GetPluginNameStatic();
+ }
+
+ bool
+ GetEnableGoroutines()
+ {
+ const uint32_t idx = ePropertyEnableGoroutines;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value);
+ }
+
+ bool
+ SetEnableGoroutines(bool enable)
+ {
+ const uint32_t idx = ePropertyEnableGoroutines;
+ return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, enable);
+ }
+};
+
+typedef std::shared_ptr<PluginProperties> OperatingSystemGoPropertiesSP;
+
+static const OperatingSystemGoPropertiesSP &
+GetGlobalPluginProperties()
+{
+ static OperatingSystemGoPropertiesSP g_settings_sp;
+ if (!g_settings_sp)
+ g_settings_sp.reset(new PluginProperties());
+ return g_settings_sp;
+}
+
+class RegisterContextGo : public RegisterContextMemory
+{
+public:
+ RegisterContextGo(lldb_private::Thread &thread, uint32_t concrete_frame_idx, DynamicRegisterInfo &reg_info,
+ lldb::addr_t reg_data_addr)
+ : RegisterContextMemory(thread, concrete_frame_idx, reg_info, reg_data_addr)
+ {
+ const RegisterInfo *sp = reg_info.GetRegisterInfoAtIndex(
+ reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP));
+ const RegisterInfo *pc = reg_info.GetRegisterInfoAtIndex(
+ reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC));
+ size_t byte_size = std::max(sp->byte_offset + sp->byte_size, pc->byte_offset + pc->byte_size);
+
+ DataBufferSP reg_data_sp(new DataBufferHeap(byte_size, 0));
+ m_reg_data.SetData(reg_data_sp);
+ }
+
+ ~RegisterContextGo() override = default;
+
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &reg_value) override
+ {
+ switch (reg_info->kinds[eRegisterKindGeneric])
+ {
+ case LLDB_REGNUM_GENERIC_SP:
+ case LLDB_REGNUM_GENERIC_PC:
+ return RegisterContextMemory::ReadRegister(reg_info, reg_value);
+ default:
+ reg_value.SetValueToInvalid();
+ return true;
+ }
+ }
+
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &reg_value) override
+ {
+ switch (reg_info->kinds[eRegisterKindGeneric])
+ {
+ case LLDB_REGNUM_GENERIC_SP:
+ case LLDB_REGNUM_GENERIC_PC:
+ return RegisterContextMemory::WriteRegister(reg_info, reg_value);
+ default:
+ return false;
+ }
+ }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(RegisterContextGo);
+};
+
+} // anonymous namespace
+
+struct OperatingSystemGo::Goroutine
+{
+ uint64_t m_lostack;
+ uint64_t m_histack;
+ uint64_t m_goid;
+ addr_t m_gobuf;
+ uint32_t m_status;
+};
+
+void
+OperatingSystemGo::Initialize()
+{
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
+ DebuggerInitialize);
+}
+
+void
+OperatingSystemGo::DebuggerInitialize(Debugger &debugger)
+{
+ if (!PluginManager::GetSettingForOperatingSystemPlugin(debugger, PluginProperties::GetSettingName()))
+ {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForOperatingSystemPlugin(
+ debugger, GetGlobalPluginProperties()->GetValueProperties(),
+ ConstString("Properties for the goroutine thread plug-in."), is_global_setting);
+ }
+}
+
+void
+OperatingSystemGo::Terminate()
+{
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+OperatingSystem *
+OperatingSystemGo::CreateInstance(Process *process, bool force)
+{
+ if (!force)
+ {
+ TargetSP target_sp = process->CalculateTarget();
+ if (!target_sp)
+ return nullptr;
+ ModuleList &module_list = target_sp->GetImages();
+ Mutex::Locker modules_locker(module_list.GetMutex());
+ const size_t num_modules = module_list.GetSize();
+ bool found_go_runtime = false;
+ for (size_t i = 0; i < num_modules; ++i)
+ {
+ Module *module = module_list.GetModulePointerAtIndexUnlocked(i);
+ const SectionList *section_list = module->GetSectionList();
+ if (section_list)
+ {
+ SectionSP section_sp(section_list->FindSectionByType(eSectionTypeGoSymtab, true));
+ if (section_sp)
+ {
+ found_go_runtime = true;
+ break;
+ }
+ }
+ }
+ if (!found_go_runtime)
+ return nullptr;
+ }
+ return new OperatingSystemGo(process);
+}
+
+OperatingSystemGo::OperatingSystemGo(lldb_private::Process *process)
+ : OperatingSystem(process)
+ , m_reginfo(new DynamicRegisterInfo)
+{
+}
+
+OperatingSystemGo::~OperatingSystemGo() = default;
+
+ConstString
+OperatingSystemGo::GetPluginNameStatic()
+{
+ static ConstString g_name("goroutines");
+ return g_name;
+}
+
+const char *
+OperatingSystemGo::GetPluginDescriptionStatic()
+{
+ return "Operating system plug-in that reads runtime data-structures for goroutines.";
+}
+
+bool
+OperatingSystemGo::Init(ThreadList &threads)
+{
+ if (threads.GetSize(false) < 1)
+ return false;
+ TargetSP target_sp = m_process->CalculateTarget();
+ if (!target_sp)
+ return false;
+ m_allg_sp = FindGlobal(target_sp, "runtime.allg");
+ m_allglen_sp = FindGlobal(target_sp, "runtime.allglen");
+
+ if (m_allg_sp && !m_allglen_sp)
+ {
+ StreamSP error_sp = target_sp->GetDebugger().GetAsyncErrorStream();
+ error_sp->Printf("Unsupported Go runtime version detected.");
+ return false;
+ }
+
+ if (!m_allg_sp)
+ return false;
+
+ RegisterContextSP real_registers_sp = threads.GetThreadAtIndex(0, false)->GetRegisterContext();
+
+ std::unordered_map<size_t, ConstString> register_sets;
+ for (size_t set_idx = 0; set_idx < real_registers_sp->GetRegisterSetCount(); ++set_idx)
+ {
+ const RegisterSet *set = real_registers_sp->GetRegisterSet(set_idx);
+ ConstString name(set->name);
+ for (size_t reg_idx = 0; reg_idx < set->num_registers; ++reg_idx)
+ {
+ register_sets[reg_idx] = name;
+ }
+ }
+ TypeSP gobuf_sp = FindType(target_sp, "runtime.gobuf");
+ if (!gobuf_sp)
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
+
+ if (log)
+ log->Printf("OperatingSystemGo unable to find struct Gobuf");
+ return false;
+ }
+ CompilerType gobuf_type(gobuf_sp->GetLayoutCompilerType());
+ for (size_t idx = 0; idx < real_registers_sp->GetRegisterCount(); ++idx)
+ {
+ RegisterInfo reg = *real_registers_sp->GetRegisterInfoAtIndex(idx);
+ int field_index = -1;
+ if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_SP)
+ {
+ field_index = 0;
+ }
+ else if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC)
+ {
+ field_index = 1;
+ }
+ if (field_index == -1)
+ {
+ reg.byte_offset = ~0;
+ }
+ else
+ {
+ std::string field_name;
+ uint64_t bit_offset = 0;
+ CompilerType field_type =
+ gobuf_type.GetFieldAtIndex(field_index, field_name, &bit_offset, nullptr, nullptr);
+ reg.byte_size = field_type.GetByteSize(nullptr);
+ reg.byte_offset = bit_offset / 8;
+ }
+ ConstString name(reg.name);
+ ConstString alt_name(reg.alt_name);
+ m_reginfo->AddRegister(reg, name, alt_name, register_sets[idx]);
+ }
+ return true;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+ConstString
+OperatingSystemGo::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+OperatingSystemGo::GetPluginVersion()
+{
+ return 1;
+}
+
+bool
+OperatingSystemGo::UpdateThreadList(ThreadList &old_thread_list, ThreadList &real_thread_list,
+ ThreadList &new_thread_list)
+{
+ new_thread_list = real_thread_list;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
+
+ if (!(m_allg_sp || Init(real_thread_list)) || (m_allg_sp && !m_allglen_sp) ||
+ !GetGlobalPluginProperties()->GetEnableGoroutines())
+ {
+ return new_thread_list.GetSize(false) > 0;
+ }
+
+ if (log)
+ log->Printf("OperatingSystemGo::UpdateThreadList(%d, %d, %d) fetching thread data from Go for pid %" PRIu64,
+ old_thread_list.GetSize(false), real_thread_list.GetSize(false), new_thread_list.GetSize(0),
+ m_process->GetID());
+ uint64_t allglen = m_allglen_sp->GetValueAsUnsigned(0);
+ if (allglen == 0)
+ {
+ return new_thread_list.GetSize(false) > 0;
+ }
+ std::vector<Goroutine> goroutines;
+ // The threads that are in "new_thread_list" upon entry are the threads from the
+ // lldb_private::Process subclass, no memory threads will be in this list.
+
+ Error err;
+ for (uint64_t i = 0; i < allglen; ++i)
+ {
+ goroutines.push_back(CreateGoroutineAtIndex(i, err));
+ if (err.Fail())
+ {
+ err.PutToLog(log, "OperatingSystemGo::UpdateThreadList");
+ return new_thread_list.GetSize(false) > 0;
+ }
+ }
+ // Make a map so we can match goroutines with backing threads.
+ std::map<uint64_t, ThreadSP> stack_map;
+ for (uint32_t i = 0; i < real_thread_list.GetSize(false); ++i)
+ {
+ ThreadSP thread = real_thread_list.GetThreadAtIndex(i, false);
+ stack_map[thread->GetRegisterContext()->GetSP()] = thread;
+ }
+ for (const Goroutine &goroutine : goroutines)
+ {
+ if (0 /* Gidle */ == goroutine.m_status || 6 /* Gdead */ == goroutine.m_status)
+ {
+ continue;
+ }
+ ThreadSP memory_thread = old_thread_list.FindThreadByID(goroutine.m_goid, false);
+ if (memory_thread && IsOperatingSystemPluginThread(memory_thread) && memory_thread->IsValid())
+ {
+ memory_thread->ClearBackingThread();
+ }
+ else
+ {
+ memory_thread.reset(new ThreadMemory(*m_process, goroutine.m_goid, nullptr, nullptr, goroutine.m_gobuf));
+ }
+ // Search for the backing thread if the goroutine is running.
+ if (2 == (goroutine.m_status & 0xfff))
+ {
+ auto backing_it = stack_map.lower_bound(goroutine.m_lostack);
+ if (backing_it != stack_map.end())
+ {
+ if (goroutine.m_histack >= backing_it->first)
+ {
+ if (log)
+ log->Printf("OperatingSystemGo::UpdateThreadList found backing thread %" PRIx64 " (%" PRIx64
+ ") for thread %" PRIx64 "",
+ backing_it->second->GetID(), backing_it->second->GetProtocolID(),
+ memory_thread->GetID());
+ memory_thread->SetBackingThread(backing_it->second);
+ new_thread_list.RemoveThreadByID(backing_it->second->GetID(), false);
+ }
+ }
+ }
+ new_thread_list.AddThread(memory_thread);
+ }
+
+ return new_thread_list.GetSize(false) > 0;
+}
+
+void
+OperatingSystemGo::ThreadWasSelected(Thread *thread)
+{
+}
+
+RegisterContextSP
+OperatingSystemGo::CreateRegisterContextForThread(Thread *thread, addr_t reg_data_addr)
+{
+ RegisterContextSP reg_ctx_sp;
+ if (!thread)
+ return reg_ctx_sp;
+
+ if (!IsOperatingSystemPluginThread(thread->shared_from_this()))
+ return reg_ctx_sp;
+
+ reg_ctx_sp.reset(new RegisterContextGo(*thread, 0, *m_reginfo, reg_data_addr));
+ return reg_ctx_sp;
+}
+
+StopInfoSP
+OperatingSystemGo::CreateThreadStopReason(lldb_private::Thread *thread)
+{
+ StopInfoSP stop_info_sp;
+ return stop_info_sp;
+}
+
+lldb::ThreadSP
+OperatingSystemGo::CreateThread(lldb::tid_t tid, addr_t context)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
+
+ if (log)
+ log->Printf("OperatingSystemGo::CreateThread (tid = 0x%" PRIx64 ", context = 0x%" PRIx64 ") not implemented",
+ tid, context);
+
+ return ThreadSP();
+}
+
+ValueObjectSP
+OperatingSystemGo::FindGlobal(TargetSP target, const char *name)
+{
+ VariableList variable_list;
+ const bool append = true;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
+
+ if (log)
+ {
+ log->Printf("exe: %s", target->GetExecutableModule()->GetSpecificationDescription().c_str());
+ log->Printf("modules: %zu", target->GetImages().GetSize());
+ }
+
+ uint32_t match_count = target->GetImages().FindGlobalVariables(ConstString(name), append, 1, variable_list);
+ if (match_count > 0)
+ {
+ ExecutionContextScope *exe_scope = target->GetProcessSP().get();
+ if (exe_scope == NULL)
+ exe_scope = target.get();
+ return ValueObjectVariable::Create(exe_scope, variable_list.GetVariableAtIndex(0));
+ }
+ return ValueObjectSP();
+}
+
+TypeSP
+OperatingSystemGo::FindType(TargetSP target_sp, const char *name)
+{
+ ConstString const_typename(name);
+ SymbolContext sc;
+ const bool exact_match = false;
+
+ const ModuleList &module_list = target_sp->GetImages();
+ size_t count = module_list.GetSize();
+ for (size_t idx = 0; idx < count; idx++)
+ {
+ ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
+ if (module_sp)
+ {
+ TypeSP type_sp(module_sp->FindFirstType(sc, const_typename, exact_match));
+ if (type_sp)
+ return type_sp;
+ }
+ }
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
+
+ if (log)
+ log->Printf("OperatingSystemGo::FindType(%s): not found", name);
+ return TypeSP();
+}
+
+OperatingSystemGo::Goroutine
+OperatingSystemGo::CreateGoroutineAtIndex(uint64_t idx, Error &err)
+{
+ err.Clear();
+ Goroutine result;
+ ValueObjectSP g = m_allg_sp->GetSyntheticArrayMember(idx, true)->Dereference(err);
+ if (err.Fail())
+ {
+ return result;
+ }
+
+ ConstString name("goid");
+ ValueObjectSP val = g->GetChildMemberWithName(name, true);
+ bool success = false;
+ result.m_goid = val->GetValueAsUnsigned(0, &success);
+ if (!success)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("unable to read goid");
+ return result;
+ }
+ name.SetCString("atomicstatus");
+ val = g->GetChildMemberWithName(name, true);
+ result.m_status = (uint32_t)val->GetValueAsUnsigned(0, &success);
+ if (!success)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("unable to read atomicstatus");
+ return result;
+ }
+ name.SetCString("sched");
+ val = g->GetChildMemberWithName(name, true);
+ result.m_gobuf = val->GetAddressOf(false);
+ name.SetCString("stack");
+ val = g->GetChildMemberWithName(name, true);
+ name.SetCString("lo");
+ ValueObjectSP child = val->GetChildMemberWithName(name, true);
+ result.m_lostack = child->GetValueAsUnsigned(0, &success);
+ if (!success)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("unable to read stack.lo");
+ return result;
+ }
+ name.SetCString("hi");
+ child = val->GetChildMemberWithName(name, true);
+ result.m_histack = child->GetValueAsUnsigned(0, &success);
+ if (!success)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("unable to read stack.hi");
+ return result;
+ }
+ return result;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h
new file mode 100644
index 0000000..d3391d9
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h
@@ -0,0 +1,87 @@
+//===-- OperatingSystemGo.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _liblldb_OperatingSystemGo_h_
+#define _liblldb_OperatingSystemGo_h_
+
+// C Includes
+// C++ Includes
+#include <memory>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/OperatingSystem.h"
+
+class DynamicRegisterInfo;
+
+class OperatingSystemGo : public lldb_private::OperatingSystem
+{
+public:
+ OperatingSystemGo(lldb_private::Process *process);
+
+ ~OperatingSystemGo() override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static lldb_private::OperatingSystem *CreateInstance(lldb_private::Process *process, bool force);
+
+ static void Initialize();
+
+ static void DebuggerInitialize(lldb_private::Debugger &debugger);
+
+ static void Terminate();
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ //------------------------------------------------------------------
+ // lldb_private::PluginInterface Methods
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ //------------------------------------------------------------------
+ // lldb_private::OperatingSystem Methods
+ //------------------------------------------------------------------
+ bool UpdateThreadList(lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &real_thread_list,
+ lldb_private::ThreadList &new_thread_list) override;
+
+ void ThreadWasSelected(lldb_private::Thread *thread) override;
+
+ lldb::RegisterContextSP CreateRegisterContextForThread(lldb_private::Thread *thread,
+ lldb::addr_t reg_data_addr) override;
+
+ lldb::StopInfoSP CreateThreadStopReason(lldb_private::Thread *thread) override;
+
+ //------------------------------------------------------------------
+ // Method for lazy creation of threads on demand
+ //------------------------------------------------------------------
+ lldb::ThreadSP CreateThread(lldb::tid_t tid, lldb::addr_t context) override;
+
+private:
+ struct Goroutine;
+
+ static lldb::ValueObjectSP FindGlobal(lldb::TargetSP target, const char *name);
+
+ static lldb::TypeSP FindType(lldb::TargetSP target_sp, const char *name);
+
+ bool Init(lldb_private::ThreadList &threads);
+
+ Goroutine CreateGoroutineAtIndex(uint64_t idx, lldb_private::Error &err);
+
+ std::unique_ptr<DynamicRegisterInfo> m_reginfo;
+ lldb::ValueObjectSP m_allg_sp;
+ lldb::ValueObjectSP m_allglen_sp;
+};
+
+#endif // liblldb_OperatingSystemGo_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index e744d13..a556b0e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -24,7 +24,6 @@
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
@@ -43,9 +42,7 @@ using namespace lldb_private;
void
OperatingSystemPython::Initialize()
{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance);
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, nullptr);
}
void
diff --git a/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
index e29bf80..1b33c42 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
@@ -1,4 +1,4 @@
-//===-- OperatingSystemPython.h ---------------------------*- C++ -*-===//
+//===-- OperatingSystemPython.h ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,14 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef LLDB_DISABLE_PYTHON
#ifndef liblldb_OperatingSystemPython_h_
#define liblldb_OperatingSystemPython_h_
+#ifndef LLDB_DISABLE_PYTHON
+
// C Includes
// C++ Includes
// Other libraries and framework includes
+// Project includes
#include "lldb/Core/StructuredData.h"
#include "lldb/Target/OperatingSystem.h"
@@ -27,6 +29,11 @@ class ScriptInterpreter;
class OperatingSystemPython : public lldb_private::OperatingSystem
{
public:
+ OperatingSystemPython(lldb_private::Process *process,
+ const lldb_private::FileSpec &python_module_path);
+
+ ~OperatingSystemPython() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -46,49 +53,39 @@ public:
GetPluginDescriptionStatic();
//------------------------------------------------------------------
- // Class Methods
- //------------------------------------------------------------------
- OperatingSystemPython (lldb_private::Process *process,
- const lldb_private::FileSpec &python_module_path);
-
- virtual
- ~OperatingSystemPython ();
-
- //------------------------------------------------------------------
// lldb_private::PluginInterface Methods
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
//------------------------------------------------------------------
// lldb_private::OperatingSystem Methods
//------------------------------------------------------------------
- virtual bool
- UpdateThreadList (lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &real_thread_list,
- lldb_private::ThreadList &new_thread_list);
+ bool
+ UpdateThreadList(lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &real_thread_list,
+ lldb_private::ThreadList &new_thread_list) override;
- virtual void
- ThreadWasSelected (lldb_private::Thread *thread);
+ void
+ ThreadWasSelected(lldb_private::Thread *thread) override;
- virtual lldb::RegisterContextSP
- CreateRegisterContextForThread (lldb_private::Thread *thread,
- lldb::addr_t reg_data_addr);
+ lldb::RegisterContextSP
+ CreateRegisterContextForThread(lldb_private::Thread *thread,
+ lldb::addr_t reg_data_addr) override;
- virtual lldb::StopInfoSP
- CreateThreadStopReason (lldb_private::Thread *thread);
+ lldb::StopInfoSP
+ CreateThreadStopReason(lldb_private::Thread *thread) override;
//------------------------------------------------------------------
// Method for lazy creation of threads on demand
//------------------------------------------------------------------
- virtual lldb::ThreadSP
- CreateThread (lldb::tid_t tid, lldb::addr_t context);
+ lldb::ThreadSP
+ CreateThread(lldb::tid_t tid, lldb::addr_t context) override;
protected:
-
bool IsValid() const
{
return m_python_object_sp && m_python_object_sp->IsValid();
@@ -107,5 +104,6 @@ protected:
lldb_private::StructuredData::ObjectSP m_python_object_sp;
};
-#endif // #ifndef liblldb_OperatingSystemPython_h_
-#endif // #ifndef LLDB_DISABLE_PYTHON
+#endif // LLDB_DISABLE_PYTHON
+
+#endif // liblldb_OperatingSystemPython_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/contrib/llvm/tools/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
index 67156e6..d1bfc43 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
@@ -22,6 +22,9 @@ namespace platform_freebsd {
class PlatformFreeBSD : public Platform
{
public:
+ PlatformFreeBSD(bool is_host);
+
+ ~PlatformFreeBSD() override;
//------------------------------------------------------------
// Class functions
@@ -42,14 +45,6 @@ namespace platform_freebsd {
GetDescriptionStatic (bool is_host);
//------------------------------------------------------------
- // Class Methods
- //------------------------------------------------------------
- PlatformFreeBSD (bool is_host);
-
- virtual
- ~PlatformFreeBSD();
-
- //------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
ConstString
@@ -179,4 +174,4 @@ namespace platform_freebsd {
} // namespace platform_freebsd
} // namespace lldb_private
-#endif // liblldb_PlatformFreeBSD_h_
+#endif // liblldb_PlatformFreeBSD_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
new file mode 100644
index 0000000..2979d1e
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
@@ -0,0 +1,685 @@
+//===-- PlatformNetBSD.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformNetBSD.h"
+#include "lldb/Host/Config.h"
+
+// C Includes
+#include <stdio.h>
+#ifndef LLDB_DISABLE_POSIX
+#include <sys/utsname.h>
+#endif
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointSite.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::platform_netbsd;
+
+PlatformSP
+PlatformNetBSD::CreateInstance(bool force, const ArchSpec *arch)
+{
+ // The only time we create an instance is when we are creating a remote
+ // netbsd platform
+ const bool is_host = false;
+
+ bool create = force;
+ if (create == false && arch && arch->IsValid())
+ {
+ const llvm::Triple &triple = arch->GetTriple();
+ switch (triple.getOS())
+ {
+ case llvm::Triple::NetBSD:
+ create = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (create)
+ return PlatformSP(new PlatformNetBSD (is_host));
+ return PlatformSP();
+
+}
+
+ConstString
+PlatformNetBSD::GetPluginNameStatic(bool is_host)
+{
+ if (is_host)
+ {
+ static ConstString g_host_name(Platform::GetHostPlatformName ());
+ return g_host_name;
+ }
+ else
+ {
+ static ConstString g_remote_name("remote-netbsd");
+ return g_remote_name;
+ }
+}
+
+const char *
+PlatformNetBSD::GetDescriptionStatic (bool is_host)
+{
+ if (is_host)
+ return "Local NetBSD user platform plug-in.";
+ else
+ return "Remote NetBSD user platform plug-in.";
+}
+
+static uint32_t g_initialize_count = 0;
+
+void
+PlatformNetBSD::Initialize ()
+{
+ Platform::Initialize ();
+
+ if (g_initialize_count++ == 0)
+ {
+#if defined(__NetBSD__)
+ // Force a host flag to true for the default platform object.
+ PlatformSP default_platform_sp (new PlatformNetBSD(true));
+ default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
+ Platform::SetHostPlatform (default_platform_sp);
+#endif
+ PluginManager::RegisterPlugin(PlatformNetBSD::GetPluginNameStatic(false),
+ PlatformNetBSD::GetDescriptionStatic(false),
+ PlatformNetBSD::CreateInstance);
+ }
+}
+
+void
+PlatformNetBSD::Terminate ()
+{
+ if (g_initialize_count > 0 && --g_initialize_count == 0)
+ PluginManager::UnregisterPlugin (PlatformNetBSD::CreateInstance);
+
+ Platform::Terminate ();
+}
+
+bool
+PlatformNetBSD::GetModuleSpec (const FileSpec& module_file_spec,
+ const ArchSpec& arch,
+ ModuleSpec &module_spec)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetModuleSpec (module_file_spec, arch, module_spec);
+
+ return Platform::GetModuleSpec (module_file_spec, arch, module_spec);
+}
+
+Error
+PlatformNetBSD::RunShellCommand(const char *command,
+ const FileSpec &working_dir,
+ int *status_ptr,
+ int *signo_ptr,
+ std::string *command_output,
+ uint32_t timeout_sec)
+{
+ if (IsHost())
+ return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ return Error("unable to run a remote command without a platform");
+ }
+}
+
+Error
+PlatformNetBSD::ResolveExecutable (const ModuleSpec &module_spec,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ char exe_path[PATH_MAX];
+ ModuleSpec resolved_module_spec(module_spec);
+
+ if (IsHost())
+ {
+ // If we have "ls" as the module_spec's file, resolve the executable location based on
+ // the current path variables
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ {
+ module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
+ resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
+ }
+
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ error.Clear();
+ else
+ {
+ error.SetErrorStringWithFormat("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ {
+ error = GetCachedExecutable (resolved_module_spec, exe_module_sp, module_search_paths_ptr, *m_remote_platform_sp);
+ }
+ else
+ {
+ // We may connect to a process and use the provided executable (Don't use local $PATH).
+
+ // Resolve any executable within a bundle on MacOSX
+ Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ {
+ error.Clear();
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+
+ if (error.Success())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ module_search_paths_ptr,
+ NULL,
+ NULL);
+
+ if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
+ {
+ exe_module_sp.reset();
+ error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+ }
+ else
+ {
+ // No valid architecture was specified, ask the platform for
+ // the architectures that we should be using (in the correct order)
+ // and see if we can find a match that way
+ StreamString arch_names;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ module_search_paths_ptr,
+ NULL,
+ NULL);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ }
+
+ return error;
+}
+
+// From PlatformMacOSX only
+Error
+PlatformNetBSD::GetFileWithUUID (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
+{
+ if (IsRemote())
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file);
+ }
+
+ // Default to the local case
+ local_file = platform_file;
+ return Error();
+}
+
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformNetBSD::PlatformNetBSD (bool is_host) :
+ Platform(is_host),
+ m_remote_platform_sp()
+{
+}
+
+bool
+PlatformNetBSD::GetRemoteOSVersion ()
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetOSVersion (m_major_os_version,
+ m_minor_os_version,
+ m_update_os_version);
+ return false;
+}
+
+bool
+PlatformNetBSD::GetRemoteOSBuildString (std::string &s)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteOSBuildString (s);
+ s.clear();
+ return false;
+}
+
+bool
+PlatformNetBSD::GetRemoteOSKernelDescription (std::string &s)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
+ s.clear();
+ return false;
+}
+
+// Remote Platform subclasses need to override this function
+ArchSpec
+PlatformNetBSD::GetRemoteSystemArchitecture ()
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteSystemArchitecture ();
+ return ArchSpec();
+}
+
+
+const char *
+PlatformNetBSD::GetHostname ()
+{
+ if (IsHost())
+ return Platform::GetHostname();
+
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetHostname ();
+ return NULL;
+}
+
+bool
+PlatformNetBSD::IsConnected () const
+{
+ if (IsHost())
+ return true;
+ else if (m_remote_platform_sp)
+ return m_remote_platform_sp->IsConnected();
+ return false;
+}
+
+Error
+PlatformNetBSD::ConnectRemote (Args& args)
+{
+ Error error;
+ if (IsHost())
+ {
+ error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
+ }
+ else
+ {
+ if (!m_remote_platform_sp)
+ m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error);
+
+ if (m_remote_platform_sp)
+ {
+ if (error.Success())
+ {
+ if (m_remote_platform_sp)
+ {
+ error = m_remote_platform_sp->ConnectRemote (args);
+ }
+ else
+ {
+ error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
+ }
+ }
+ }
+ else
+ error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
+
+ if (error.Fail())
+ m_remote_platform_sp.reset();
+ }
+
+ return error;
+}
+
+Error
+PlatformNetBSD::DisconnectRemote ()
+{
+ Error error;
+
+ if (IsHost())
+ {
+ error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ error = m_remote_platform_sp->DisconnectRemote ();
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return error;
+}
+
+bool
+PlatformNetBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+ bool success = false;
+ if (IsHost())
+ {
+ success = Platform::GetProcessInfo (pid, process_info);
+ }
+ else if (m_remote_platform_sp)
+ {
+ success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
+ }
+ return success;
+}
+
+uint32_t
+PlatformNetBSD::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
+{
+ uint32_t match_count = 0;
+ if (IsHost())
+ {
+ // Let the base class figure out the host details
+ match_count = Platform::FindProcesses (match_info, process_infos);
+ }
+ else
+ {
+ // If we are remote, we can only return results if we are connected
+ if (m_remote_platform_sp)
+ match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
+ }
+ return match_count;
+}
+
+const char *
+PlatformNetBSD::GetUserName (uint32_t uid)
+{
+ // Check the cache in Platform in case we have already looked this uid up
+ const char *user_name = Platform::GetUserName(uid);
+ if (user_name)
+ return user_name;
+
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetUserName(uid);
+ return NULL;
+}
+
+const char *
+PlatformNetBSD::GetGroupName (uint32_t gid)
+{
+ const char *group_name = Platform::GetGroupName(gid);
+ if (group_name)
+ return group_name;
+
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetGroupName(gid);
+ return NULL;
+}
+
+
+Error
+PlatformNetBSD::GetSharedModule (const ModuleSpec &module_spec,
+ Process* process,
+ ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ Error error;
+ module_sp.reset();
+
+ if (IsRemote())
+ {
+ // If we have a remote platform always, let it try and locate
+ // the shared module first.
+ if (m_remote_platform_sp)
+ {
+ error = m_remote_platform_sp->GetSharedModule (module_spec,
+ process,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr);
+ }
+ }
+
+ if (!module_sp)
+ {
+ // Fall back to the local platform and find the file locally
+ error = Platform::GetSharedModule (module_spec,
+ process,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr);
+ }
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
+ return error;
+}
+
+
+bool
+PlatformNetBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+ if (IsHost())
+ {
+ ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
+ if (hostArch.GetTriple().isOSNetBSD())
+ {
+ if (idx == 0)
+ {
+ arch = hostArch;
+ return arch.IsValid();
+ }
+ else if (idx == 1)
+ {
+ // If the default host architecture is 64-bit, look for a 32-bit variant
+ if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit())
+ {
+ arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
+ return arch.IsValid();
+ }
+ }
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);
+
+ llvm::Triple triple;
+ // Set the OS to NetBSD
+ triple.setOS(llvm::Triple::NetBSD);
+ // Set the architecture
+ switch (idx)
+ {
+ case 0: triple.setArchName("x86_64"); break;
+ case 1: triple.setArchName("i386"); break;
+ default: return false;
+ }
+ // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the vendor by
+ // calling triple.SetVendorName("unknown") so that it is a "unspecified unknown".
+ // This means when someone calls triple.GetVendorName() it will return an empty string
+ // which indicates that the vendor can be set when two architectures are merged
+
+ // Now set the triple into "arch" and return true
+ arch.SetTriple(triple);
+ return true;
+ }
+ return false;
+}
+
+void
+PlatformNetBSD::GetStatus (Stream &strm)
+{
+#ifndef LLDB_DISABLE_POSIX
+ struct ::utsname un;
+
+ strm << " Host: ";
+
+ ::memset(&un, 0, sizeof(utsname));
+ if (::uname(&un) == -1) {
+ strm << "NetBSD" << '\n';
+ } else {
+ strm << un.sysname << ' ' << un.release;
+ if (un.nodename[0] != '\0')
+ strm << " (" << un.nodename << ')';
+ strm << '\n';
+
+ // Dump a common information about the platform status.
+ strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
+ }
+#endif
+
+ Platform::GetStatus(strm);
+}
+
+size_t
+PlatformNetBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
+{
+ ArchSpec arch = target.GetArchitecture();
+ const uint8_t *trap_opcode = NULL;
+ size_t trap_opcode_size = 0;
+
+ switch (arch.GetMachine())
+ {
+ default:
+ assert(false && "Unhandled architecture in PlatformNetBSD::GetSoftwareBreakpointTrapOpcode()");
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ {
+ static const uint8_t g_i386_opcode[] = { 0xCC };
+ trap_opcode = g_i386_opcode;
+ trap_opcode_size = sizeof(g_i386_opcode);
+ }
+ break;
+ }
+
+ if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
+ return trap_opcode_size;
+ return 0;
+}
+
+
+void
+PlatformNetBSD::CalculateTrapHandlerSymbolNames ()
+{
+ m_trap_handlers.push_back (ConstString ("_sigtramp"));
+}
+
+Error
+PlatformNetBSD::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ if (IsHost())
+ {
+ error = Platform::LaunchProcess (launch_info);
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ error = m_remote_platform_sp->LaunchProcess (launch_info);
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return error;
+}
+
+lldb::ProcessSP
+PlatformNetBSD::Attach(ProcessAttachInfo &attach_info,
+ Debugger &debugger,
+ Target *target,
+ Error &error)
+{
+ lldb::ProcessSP process_sp;
+ if (IsHost())
+ {
+ if (target == NULL)
+ {
+ TargetSP new_target_sp;
+ ArchSpec emptyArchSpec;
+
+ error = debugger.GetTargetList().CreateTarget (debugger,
+ NULL,
+ emptyArchSpec,
+ false,
+ m_remote_platform_sp,
+ new_target_sp);
+ target = new_target_sp.get();
+ }
+ else
+ error.Clear();
+
+ if (target && error.Success())
+ {
+ debugger.GetTargetList().SetSelectedTarget(target);
+ // The netbsd always currently uses the GDB remote debugger plug-in
+ // so even when debugging locally we are debugging remotely!
+ // Just like the darwin plugin.
+ process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
+
+ if (process_sp)
+ error = process_sp->Attach (attach_info);
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error);
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return process_sp;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h b/contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h
new file mode 100644
index 0000000..b0187be
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.h
@@ -0,0 +1,177 @@
+//===-- PlatformNetBSD.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_PlatformNetBSD_h_
+#define liblldb_PlatformNetBSD_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Platform.h"
+
+namespace lldb_private {
+namespace platform_netbsd {
+
+ class PlatformNetBSD : public Platform
+ {
+ public:
+ PlatformNetBSD (bool is_host);
+
+ ~PlatformNetBSD() override = default;
+
+ //------------------------------------------------------------
+ // Class functions
+ //------------------------------------------------------------
+ static lldb::PlatformSP
+ CreateInstance(bool force, const ArchSpec *arch);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static ConstString
+ GetPluginNameStatic (bool is_host);
+
+ static const char *
+ GetDescriptionStatic (bool is_host);
+
+ //------------------------------------------------------------
+ // lldb_private::PluginInterface functions
+ //------------------------------------------------------------
+ ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic (IsHost());
+ }
+
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
+
+ const char *
+ GetDescription () override
+ {
+ return GetDescriptionStatic(IsHost());
+ }
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ bool
+ GetModuleSpec(const FileSpec& module_file_spec,
+ const ArchSpec& arch,
+ ModuleSpec &module_spec) override;
+
+ Error
+ RunShellCommand(const char *command,
+ const FileSpec &working_dir,
+ int *status_ptr,
+ int *signo_ptr,
+ std::string *command_output,
+ uint32_t timeout_sec) override;
+
+ Error
+ ResolveExecutable(const ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr) override;
+
+ size_t
+ GetSoftwareBreakpointTrapOpcode(Target &target,
+ BreakpointSite *bp_site) override;
+
+ bool
+ GetRemoteOSVersion () override;
+
+ bool
+ GetRemoteOSBuildString (std::string &s) override;
+
+ bool
+ GetRemoteOSKernelDescription (std::string &s) override;
+
+ // Remote Platform subclasses need to override this function
+ ArchSpec
+ GetRemoteSystemArchitecture() override;
+
+ bool
+ IsConnected () const override;
+
+ Error
+ ConnectRemote(Args& args) override;
+
+ Error
+ DisconnectRemote() override;
+
+ const char *
+ GetHostname () override;
+
+ const char *
+ GetUserName (uint32_t uid) override;
+
+ const char *
+ GetGroupName (uint32_t gid) override;
+
+ bool
+ GetProcessInfo(lldb::pid_t pid,
+ ProcessInstanceInfo &proc_info) override;
+
+ uint32_t
+ FindProcesses(const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos) override;
+
+ Error
+ LaunchProcess(ProcessLaunchInfo &launch_info) override;
+
+ lldb::ProcessSP
+ Attach(ProcessAttachInfo &attach_info,
+ Debugger &debugger,
+ Target *target,
+ Error &error) override;
+
+ // NetBSD processes can not be launched by spawning and attaching.
+ bool
+ CanDebugProcess () override { return false; }
+
+ // Only on PlatformMacOSX:
+ Error
+ GetFileWithUUID(const FileSpec &platform_file,
+ const UUID* uuid, FileSpec &local_file) override;
+
+ Error
+ GetSharedModule(const ModuleSpec &module_spec,
+ Process* process,
+ lldb::ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ bool
+ GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override;
+
+ void
+ GetStatus(Stream &strm) override;
+
+ void
+ CalculateTrapHandlerSymbolNames () override;
+
+ protected:
+ lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote netbsd OS
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformNetBSD);
+ };
+
+} // namespace platform_netbsd
+} // namespace lldb_private
+
+#endif // liblldb_PlatformNetBSD_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index b4f841a..c756465 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -19,13 +19,18 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileCache.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/ProcessLaunchInfo.h"
+#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
@@ -673,9 +678,12 @@ PlatformPOSIX::ConnectRemote (Args& args)
if (m_options.get())
{
OptionGroupOptions* options = m_options.get();
- const OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r');
- const OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s');
- const OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c');
+ const OptionGroupPlatformRSync *m_rsync_options =
+ static_cast<const OptionGroupPlatformRSync *>(options->GetGroupWithOption('r'));
+ const OptionGroupPlatformSSH *m_ssh_options =
+ static_cast<const OptionGroupPlatformSSH *>(options->GetGroupWithOption('s'));
+ const OptionGroupPlatformCaching *m_cache_options =
+ static_cast<const OptionGroupPlatformCaching *>(options->GetGroupWithOption('c'));
if (m_rsync_options->m_rsync)
{
@@ -843,6 +851,175 @@ PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info,
void
PlatformPOSIX::CalculateTrapHandlerSymbolNames ()
-{
+{
m_trap_handlers.push_back (ConstString ("_sigtramp"));
+}
+
+Error
+PlatformPOSIX::EvaluateLibdlExpression(lldb_private::Process* process,
+ const char* expr_cstr,
+ const char* expr_prefix,
+ lldb::ValueObjectSP& result_valobj_sp)
+{
+ DynamicLoader *loader = process->GetDynamicLoader();
+ if (loader)
+ {
+ Error error = loader->CanLoadImage();
+ if (error.Fail())
+ return error;
+ }
+
+ ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
+ if (!thread_sp)
+ return Error("Selected thread isn't valid");
+
+ StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
+ if (!frame_sp)
+ return Error("Frame 0 isn't valid");
+
+ ExecutionContext exe_ctx;
+ frame_sp->CalculateExecutionContext(exe_ctx);
+ EvaluateExpressionOptions expr_options;
+ expr_options.SetUnwindOnError(true);
+ expr_options.SetIgnoreBreakpoints(true);
+ expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
+ expr_options.SetLanguage(eLanguageTypeC_plus_plus);
+
+ Error expr_error;
+ UserExpression::Evaluate(exe_ctx,
+ expr_options,
+ expr_cstr,
+ expr_prefix,
+ result_valobj_sp,
+ expr_error);
+ if (result_valobj_sp->GetError().Fail())
+ return result_valobj_sp->GetError();
+ return Error();
+}
+
+uint32_t
+PlatformPOSIX::DoLoadImage(lldb_private::Process* process,
+ const lldb_private::FileSpec& remote_file,
+ lldb_private::Error& error)
+{
+ char path[PATH_MAX];
+ remote_file.GetPath(path, sizeof(path));
+
+ StreamString expr;
+ expr.Printf(R"(
+ struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result;
+ the_result.image_ptr = dlopen ("%s", 2);
+ if (the_result.image_ptr == (void *) 0x0)
+ {
+ the_result.error_str = dlerror();
+ }
+ else
+ {
+ the_result.error_str = (const char *) 0x0;
+ }
+ the_result;
+ )",
+ path);
+ const char *prefix = GetLibdlFunctionDeclarations();
+ lldb::ValueObjectSP result_valobj_sp;
+ error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp);
+ if (error.Fail())
+ return LLDB_INVALID_IMAGE_TOKEN;
+
+ error = result_valobj_sp->GetError();
+ if (error.Fail())
+ return LLDB_INVALID_IMAGE_TOKEN;
+
+ Scalar scalar;
+ ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true);
+ if (!image_ptr_sp || !image_ptr_sp->ResolveValue(scalar))
+ {
+ error.SetErrorStringWithFormat("unable to load '%s'", path);
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
+ if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS)
+ return process->AddImageToken(image_ptr);
+
+ if (image_ptr == 0)
+ {
+ ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true);
+ if (error_str_sp && error_str_sp->IsCStringContainer(true))
+ {
+ DataBufferSP buffer_sp(new DataBufferHeap(10240,0));
+ size_t num_chars = error_str_sp->ReadPointedString (buffer_sp, error, 10240).first;
+ if (error.Success() && num_chars > 0)
+ error.SetErrorStringWithFormat("dlopen error: %s", buffer_sp->GetBytes());
+ else
+ error.SetErrorStringWithFormat("dlopen failed for unknown reasons.");
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+ }
+ error.SetErrorStringWithFormat("unable to load '%s'", path);
+ return LLDB_INVALID_IMAGE_TOKEN;
+}
+
+Error
+PlatformPOSIX::UnloadImage (lldb_private::Process* process, uint32_t image_token)
+{
+ const addr_t image_addr = process->GetImagePtrFromToken(image_token);
+ if (image_addr == LLDB_INVALID_ADDRESS)
+ return Error("Invalid image token");
+
+ StreamString expr;
+ expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr);
+ const char *prefix = GetLibdlFunctionDeclarations();
+ lldb::ValueObjectSP result_valobj_sp;
+ Error error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp);
+ if (error.Fail())
+ return error;
+
+ if (result_valobj_sp->GetError().Fail())
+ return result_valobj_sp->GetError();
+
+ Scalar scalar;
+ if (result_valobj_sp->ResolveValue(scalar))
+ {
+ if (scalar.UInt(1))
+ return Error("expression failed: \"%s\"", expr.GetData());
+ process->ResetImageToken(image_token);
+ }
+ return Error();
}
+
+lldb::ProcessSP
+PlatformPOSIX::ConnectProcess (const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->ConnectProcess(connect_url,
+ plugin_name,
+ debugger,
+ target,
+ error);
+
+ return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, error);
+}
+
+const char*
+PlatformPOSIX::GetLibdlFunctionDeclarations() const
+{
+ return R"(
+ extern "C" void* dlopen(const char*, int);
+ extern "C" void* dlsym(void*, const char*);
+ extern "C" int dlclose(void*);
+ extern "C" char* dlerror(void);
+ )";
+}
+
+size_t
+PlatformPOSIX::ConnectToWaitingProcesses(Debugger& debugger, Error& error)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error);
+ return Platform::ConnectToWaitingProcesses(debugger, error);
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 82686dc..60f6207 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -12,7 +12,6 @@
// C Includes
// C++ Includes
-
#include <memory>
// Other libraries and framework includes
@@ -23,11 +22,10 @@
class PlatformPOSIX : public lldb_private::Platform
{
public:
- PlatformPOSIX (bool is_host);
-
- virtual
- ~PlatformPOSIX();
-
+ PlatformPOSIX(bool is_host);
+
+ ~PlatformPOSIX() override;
+
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
@@ -37,9 +35,8 @@ public:
const lldb_private::ArchSpec& arch,
lldb_private::ModuleSpec &module_spec) override;
- lldb_private::OptionGroupOptions
- *GetConnectionOptions(
- lldb_private::CommandInterpreter &interpreter) override;
+ lldb_private::OptionGroupOptions*
+ GetConnectionOptions(lldb_private::CommandInterpreter &interpreter) override;
const char *
GetHostname () override;
@@ -119,11 +116,11 @@ public:
IsConnected () const override;
lldb_private::Error
- RunShellCommand(const char *command, // Shouldn't be NULL
+ RunShellCommand(const char *command, // Shouldn't be nullptr
const lldb_private::FileSpec &working_dir, // Pass empty FileSpec to use the current working directory
- int *status_ptr, // Pass NULL if you don't want the process exit status
- int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
- std::string *command_output, // Pass NULL if you don't want the command output
+ int *status_ptr, // Pass nullptr if you don't want the process exit status
+ int *signo_ptr, // Pass nullptr if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass nullptr if you don't want the command output
uint32_t timeout_sec) override; // Timeout in seconds to wait for shell program to finish
lldb_private::Error
@@ -150,13 +147,13 @@ public:
lldb::ProcessSP
Attach (lldb_private::ProcessAttachInfo &attach_info,
lldb_private::Debugger &debugger,
- lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ lldb_private::Target *target, // Can be nullptr, if nullptr create a new target, else use existing one
lldb_private::Error &error) override;
lldb::ProcessSP
DebugProcess (lldb_private::ProcessLaunchInfo &launch_info,
lldb_private::Debugger &debugger,
- lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ lldb_private::Target *target, // Can be nullptr, if nullptr create a new target, else use existing one
lldb_private::Error &error) override;
std::string
@@ -176,14 +173,39 @@ public:
lldb_private::Error
DisconnectRemote () override;
+ uint32_t
+ DoLoadImage (lldb_private::Process* process,
+ const lldb_private::FileSpec& remote_file,
+ lldb_private::Error& error) override;
+
+ lldb_private::Error
+ UnloadImage (lldb_private::Process* process, uint32_t image_token) override;
+
+ lldb::ProcessSP
+ ConnectProcess (const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error) override;
+
+ size_t
+ ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& error) override;
+
protected:
std::unique_ptr<lldb_private::OptionGroupOptions> m_options;
-
lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote POSIX-compliant OS
-
+
+ lldb_private::Error
+ EvaluateLibdlExpression(lldb_private::Process* process,
+ const char *expr_cstr,
+ const char *expr_prefix,
+ lldb::ValueObjectSP& result_valobj_sp);
+
+ virtual const char*
+ GetLibdlFunctionDeclarations() const;
+
private:
DISALLOW_COPY_AND_ASSIGN (PlatformPOSIX);
-
};
-#endif // liblldb_PlatformPOSIX_h_
+#endif // liblldb_PlatformPOSIX_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index b0e75d4..f16ea01 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -21,6 +21,7 @@
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSpec.h"
@@ -40,23 +41,6 @@ using namespace lldb_private::platform_gdb_server;
static bool g_initialized = false;
-static std::string MakeGdbServerUrl(
- const std::string &platform_scheme,
- const std::string &platform_hostname,
- uint16_t port)
-{
- const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
- const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
- const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
- int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
- StreamString result;
- result.Printf("%s://%s:%u",
- override_scheme ? override_scheme : platform_scheme.c_str(),
- override_hostname ? override_hostname : platform_hostname.c_str(),
- port + port_offset);
- return result.GetString();
-}
-
void
PlatformRemoteGDBServer::Initialize ()
{
@@ -590,9 +574,8 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,
if (IsConnected())
{
lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
- uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid);
-
- if (port == 0)
+ std::string connect_url;
+ if (!LaunchGDBServer(debugserver_pid, connect_url))
{
error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
}
@@ -623,8 +606,6 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,
if (process_sp)
{
- std::string connect_url =
- MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port);
error = process_sp->ConnectRemote (nullptr, connect_url.c_str());
// Retry the connect remote one time...
if (error.Fail())
@@ -649,23 +630,36 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,
}
-uint16_t
-PlatformRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
+bool
+PlatformRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url)
{
ArchSpec remote_arch = GetRemoteSystemArchitecture ();
llvm::Triple &remote_triple = remote_arch.GetTriple ();
+
+ uint16_t port = 0;
+ std::string socket_name;
+ bool launch_result = false;
if (remote_triple.getVendor () == llvm::Triple::Apple && remote_triple.getOS () == llvm::Triple::IOS)
{
// When remote debugging to iOS, we use a USB mux that always talks
// to localhost, so we will need the remote debugserver to accept connections
// only from localhost, no matter what our current hostname is
- return m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1");
+ launch_result = m_gdb_client.LaunchGDBServer ("127.0.0.1", pid, port, socket_name);
}
else
{
// All other hosts should use their actual hostname
- return m_gdb_client.LaunchGDBserverAndGetPort (pid, NULL);
+ launch_result = m_gdb_client.LaunchGDBServer (nullptr, pid, port, socket_name);
}
+
+ if (!launch_result)
+ return false;
+
+ connect_url = MakeGdbServerUrl(m_platform_scheme,
+ m_platform_hostname,
+ port,
+ (socket_name.empty()) ? nullptr : socket_name.c_str());
+ return true;
}
bool
@@ -686,9 +680,8 @@ PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info,
if (IsConnected())
{
lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
- uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid);
-
- if (port == 0)
+ std::string connect_url;
+ if (!LaunchGDBServer(debugserver_pid, connect_url))
{
error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
}
@@ -716,11 +709,8 @@ PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info,
// The darwin always currently uses the GDB remote debugger plug-in
// so even when debugging locally we are debugging remotely!
process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
-
if (process_sp)
{
- std::string connect_url =
- MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port);
error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
if (error.Success())
{
@@ -931,13 +921,8 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals()
return false;
// We can live without short_name, description, etc.
- std::string short_name{""};
- auto object_sp = dict->GetValueForKey("short_name");
- if (object_sp && object_sp->IsValid())
- short_name = object_sp->GetStringValue();
-
bool suppress{false};
- object_sp = dict->GetValueForKey("suppress");
+ auto object_sp = dict->GetValueForKey("suppress");
if (object_sp && object_sp->IsValid())
suppress = object_sp->GetBooleanValue();
@@ -958,7 +943,6 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals()
remote_signals_sp->AddSignal(signo,
name.c_str(),
- short_name.c_str(),
suppress, stop, notify,
description.c_str());
return true;
@@ -969,3 +953,66 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals()
return m_remote_signals_sp;
}
+
+std::string
+PlatformRemoteGDBServer::MakeGdbServerUrl(const std::string &platform_scheme,
+ const std::string &platform_hostname,
+ uint16_t port,
+ const char* socket_name)
+{
+ const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
+ const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
+ const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
+ int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
+
+ return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(),
+ override_hostname ? override_hostname : platform_hostname.c_str(),
+ port + port_offset,
+ socket_name);
+}
+
+std::string
+PlatformRemoteGDBServer::MakeUrl(const char* scheme,
+ const char* hostname,
+ uint16_t port,
+ const char* path)
+{
+ StreamString result;
+ result.Printf("%s://%s", scheme, hostname);
+ if (port != 0)
+ result.Printf(":%u", port);
+ if (path)
+ result.Write(path, strlen(path));
+ return result.GetString();
+}
+
+lldb::ProcessSP
+PlatformRemoteGDBServer::ConnectProcess(const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error)
+{
+ if (!IsRemote() || !IsConnected())
+ {
+ error.SetErrorString("Not connected to remote gdb server");
+ return nullptr;
+ }
+ return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, error);
+}
+
+size_t
+PlatformRemoteGDBServer::GetPendingGdbServerList(std::vector<std::string>& connection_urls)
+{
+ std::vector<std::pair<uint16_t, std::string>> remote_servers;
+ m_gdb_client.QueryGDBServer(remote_servers);
+ for (const auto& gdbserver : remote_servers)
+ {
+ const char* socket_name_cstr = gdbserver.second.empty() ? nullptr : gdbserver.second.c_str();
+ connection_urls.emplace_back(MakeGdbServerUrl(m_platform_scheme,
+ m_platform_hostname,
+ gdbserver.first,
+ socket_name_cstr));
+ }
+ return connection_urls.size();
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index 0bf013f..61136f1 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -217,6 +217,16 @@ public:
const lldb::UnixSignalsSP &
GetRemoteUnixSignals() override;
+ lldb::ProcessSP
+ ConnectProcess (const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error) override;
+
+ virtual size_t
+ GetPendingGdbServerList(std::vector<std::string>& connection_urls);
+
protected:
process_gdb_remote::GDBRemoteCommunicationClient m_gdb_client;
std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to
@@ -225,16 +235,29 @@ protected:
lldb::UnixSignalsSP m_remote_signals_sp;
- // Launch the lldb-gdbserver on the remote host and return the port it is listening on or 0 on
- // failure. Subclasses should override this method if they want to do extra actions before or
- // after launching the lldb-gdbserver.
- virtual uint16_t
- LaunchGDBserverAndGetPort (lldb::pid_t &pid);
+ // Launch the debug server on the remote host - caller connects to launched
+ // debug server using connect_url.
+ // Subclasses should override this method if they want to do extra actions before or
+ // after launching the debug server.
+ virtual bool
+ LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url);
virtual bool
KillSpawnedProcess (lldb::pid_t pid);
+ virtual std::string
+ MakeUrl(const char* scheme,
+ const char* hostname,
+ uint16_t port,
+ const char* path);
+
private:
+ std::string
+ MakeGdbServerUrl(const std::string &platform_scheme,
+ const std::string &platform_hostname,
+ uint16_t port,
+ const char* socket_name);
+
DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer);
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
index 5e46c83..2b29244 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
@@ -8,33 +8,288 @@
//===----------------------------------------------------------------------===//
// C Includes
+#include <errno.h>
+
// C++ Includes
// Other libraries and framework includes
#include "lldb/Core/State.h"
#include "lldb/Target/UnixSignals.h"
// Project includes
+#include "lldb/Breakpoint/Watchpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/State.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostNativeThread.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadSpec.h"
+#include "llvm/ADT/SmallString.h"
+#include "POSIXStopInfo.h"
#include "FreeBSDThread.h"
#include "ProcessFreeBSD.h"
#include "ProcessPOSIXLog.h"
+#include "ProcessMonitor.h"
+#include "RegisterContextPOSIXProcessMonitor_arm.h"
+#include "RegisterContextPOSIXProcessMonitor_arm64.h"
+#include "RegisterContextPOSIXProcessMonitor_mips64.h"
+#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
+#include "RegisterContextPOSIXProcessMonitor_x86.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
+#include "Plugins/Process/Utility/UnwindLLDB.h"
using namespace lldb;
using namespace lldb_private;
-//------------------------------------------------------------------------------
-// Constructors and destructors.
-
FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid)
- : POSIXThread(process, tid)
+ : Thread(process, tid),
+ m_frame_ap (),
+ m_breakpoint (),
+ m_thread_name_valid (false),
+ m_thread_name (),
+ m_posix_thread(NULL)
{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("FreeBSDThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid);
+
+ // Set the current watchpoints for this thread.
+ Target &target = GetProcess()->GetTarget();
+ const WatchpointList &wp_list = target.GetWatchpointList();
+ size_t wp_size = wp_list.GetSize();
+
+ for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++)
+ {
+ lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
+ if (wp.get() && wp->IsEnabled())
+ {
+ // This watchpoint as been enabled; obviously this "new" thread
+ // has been created since that watchpoint was enabled. Since
+ // the POSIXBreakpointProtocol has yet to be initialized, its
+ // m_watchpoints_initialized member will be FALSE. Attempting to
+ // read the debug status register to determine if a watchpoint
+ // has been hit would result in the zeroing of that register.
+ // Since the active debug registers would have been cloned when
+ // this thread was created, simply force the m_watchpoints_initized
+ // member to TRUE and avoid resetting dr6 and dr7.
+ GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized();
+ }
+ }
}
FreeBSDThread::~FreeBSDThread()
{
+ DestroyThread();
+}
+
+ProcessMonitor &
+FreeBSDThread::GetMonitor()
+{
+ ProcessSP base = GetProcess();
+ ProcessFreeBSD &process = static_cast<ProcessFreeBSD&>(*base);
+ return process.GetMonitor();
+}
+
+void
+FreeBSDThread::RefreshStateAfterStop()
+{
+ // Invalidate all registers in our register context. We don't set "force" to
+ // true because the stop reply packet might have had some register values
+ // that were expedited and these will already be copied into the register
+ // context by the time this function gets called. The KDPRegisterContext
+ // class has been made smart enough to detect when it needs to invalidate
+ // which registers are valid by putting hooks in the register read and
+ // register supply functions where they check the process stop ID and do
+ // the right thing.
+ //if (StateIsStoppedState(GetState())
+ {
+ const bool force = false;
+ GetRegisterContext()->InvalidateIfNeeded (force);
+ }
}
-//------------------------------------------------------------------------------
-// ProcessInterface protocol.
+const char *
+FreeBSDThread::GetInfo()
+{
+ return NULL;
+}
+
+void
+FreeBSDThread::SetName (const char *name)
+{
+ m_thread_name_valid = (name && name[0]);
+ if (m_thread_name_valid)
+ m_thread_name.assign (name);
+ else
+ m_thread_name.clear();
+}
+
+const char *
+FreeBSDThread::GetName ()
+{
+ if (!m_thread_name_valid)
+ {
+ llvm::SmallString<32> thread_name;
+ HostNativeThread::GetName(GetID(), thread_name);
+ m_thread_name = thread_name.c_str();
+ m_thread_name_valid = true;
+ }
+
+ if (m_thread_name.empty())
+ return NULL;
+ return m_thread_name.c_str();
+}
+
+lldb::RegisterContextSP
+FreeBSDThread::GetRegisterContext()
+{
+ if (!m_reg_context_sp)
+ {
+ m_posix_thread = NULL;
+
+ RegisterInfoInterface *reg_interface = NULL;
+ const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
+
+ assert(target_arch.GetTriple().getOS() == llvm::Triple::FreeBSD);
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::aarch64:
+ reg_interface = new RegisterContextFreeBSD_arm64(target_arch);
+ break;
+ case llvm::Triple::arm:
+ reg_interface = new RegisterContextFreeBSD_arm(target_arch);
+ break;
+ case llvm::Triple::ppc:
+#ifndef __powerpc64__
+ reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch);
+ break;
+#endif
+ case llvm::Triple::ppc64:
+ reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch);
+ break;
+ case llvm::Triple::mips64:
+ reg_interface = new RegisterContextFreeBSD_mips64(target_arch);
+ break;
+ case llvm::Triple::x86:
+ reg_interface = new RegisterContextFreeBSD_i386(target_arch);
+ break;
+ case llvm::Triple::x86_64:
+ reg_interface = new RegisterContextFreeBSD_x86_64(target_arch);
+ break;
+ default:
+ llvm_unreachable("CPU not supported");
+ }
+
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::aarch64:
+ {
+ RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ case llvm::Triple::arm:
+ {
+ RegisterContextPOSIXProcessMonitor_arm *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ case llvm::Triple::mips64:
+ {
+ RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ {
+ RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ {
+ RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return m_reg_context_sp;
+}
+
+lldb::RegisterContextSP
+FreeBSDThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
+{
+ lldb::RegisterContextSP reg_ctx_sp;
+ uint32_t concrete_frame_idx = 0;
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("FreeBSDThread::%s ()", __FUNCTION__);
+
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex();
+
+ if (concrete_frame_idx == 0)
+ reg_ctx_sp = GetRegisterContext();
+ else
+ {
+ assert(GetUnwinder());
+ reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
+ }
+
+ return reg_ctx_sp;
+}
+
+lldb::addr_t
+FreeBSDThread::GetThreadPointer ()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ addr_t addr;
+ if (monitor.ReadThreadPointer (GetID(), addr))
+ return addr;
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
+bool
+FreeBSDThread::CalculateStopInfo()
+{
+ SetStopInfo (m_stop_info_sp);
+ return true;
+}
+
+Unwind *
+FreeBSDThread::GetUnwinder()
+{
+ if (m_unwinder_ap.get() == NULL)
+ m_unwinder_ap.reset(new UnwindLLDB(*this));
+
+ return m_unwinder_ap.get();
+}
+
+void
+FreeBSDThread::DidStop()
+{
+ // Don't set the thread state to stopped unless we really stopped.
+}
void
FreeBSDThread::WillResume(lldb::StateType resume_state)
@@ -68,3 +323,359 @@ FreeBSDThread::WillResume(lldb::StateType resume_state)
break;
}
}
+
+bool
+FreeBSDThread::Resume()
+{
+ lldb::StateType resume_state = GetResumeState();
+ ProcessMonitor &monitor = GetMonitor();
+ bool status;
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf ("FreeBSDThread::%s (), resume_state = %s", __FUNCTION__,
+ StateAsCString(resume_state));
+
+ switch (resume_state)
+ {
+ default:
+ assert(false && "Unexpected state for resume!");
+ status = false;
+ break;
+
+ case lldb::eStateRunning:
+ SetState(resume_state);
+ status = monitor.Resume(GetID(), GetResumeSignal());
+ break;
+
+ case lldb::eStateStepping:
+ SetState(resume_state);
+ status = monitor.SingleStep(GetID(), GetResumeSignal());
+ break;
+ case lldb::eStateStopped:
+ case lldb::eStateSuspended:
+ status = true;
+ break;
+ }
+
+ return status;
+}
+
+void
+FreeBSDThread::Notify(const ProcessMessage &message)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf ("FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64,
+ __FUNCTION__, message.PrintKind(), GetID());
+
+ switch (message.GetKind())
+ {
+ default:
+ assert(false && "Unexpected message kind!");
+ break;
+
+ case ProcessMessage::eExitMessage:
+ // Nothing to be done.
+ break;
+
+ case ProcessMessage::eLimboMessage:
+ LimboNotify(message);
+ break;
+
+ case ProcessMessage::eSignalMessage:
+ SignalNotify(message);
+ break;
+
+ case ProcessMessage::eSignalDeliveredMessage:
+ SignalDeliveredNotify(message);
+ break;
+
+ case ProcessMessage::eTraceMessage:
+ TraceNotify(message);
+ break;
+
+ case ProcessMessage::eBreakpointMessage:
+ BreakNotify(message);
+ break;
+
+ case ProcessMessage::eWatchpointMessage:
+ WatchNotify(message);
+ break;
+
+ case ProcessMessage::eCrashMessage:
+ CrashNotify(message);
+ break;
+
+ case ProcessMessage::eExecMessage:
+ ExecNotify(message);
+ break;
+ }
+}
+
+bool
+FreeBSDThread::EnableHardwareWatchpoint(Watchpoint *wp)
+{
+ bool wp_set = false;
+ if (wp)
+ {
+ addr_t wp_addr = wp->GetLoadAddress();
+ size_t wp_size = wp->GetByteSize();
+ bool wp_read = wp->WatchpointRead();
+ bool wp_write = wp->WatchpointWrite();
+ uint32_t wp_hw_index = wp->GetHardwareIndex();
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ if (reg_ctx)
+ wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size,
+ wp_read, wp_write,
+ wp_hw_index);
+ }
+ return wp_set;
+}
+
+bool
+FreeBSDThread::DisableHardwareWatchpoint(Watchpoint *wp)
+{
+ bool result = false;
+ if (wp)
+ {
+ lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+ if (reg_ctx_sp.get())
+ result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
+ }
+ return result;
+}
+
+uint32_t
+FreeBSDThread::NumSupportedHardwareWatchpoints()
+{
+ lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+ if (reg_ctx_sp.get())
+ return reg_ctx_sp->NumSupportedHardwareWatchpoints();
+ return 0;
+}
+
+uint32_t
+FreeBSDThread::FindVacantWatchpointIndex()
+{
+ uint32_t hw_index = LLDB_INVALID_INDEX32;
+ uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
+ uint32_t wp_idx;
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ if (reg_ctx)
+ {
+ for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+ {
+ if (reg_ctx->IsWatchpointVacant(wp_idx))
+ {
+ hw_index = wp_idx;
+ break;
+ }
+ }
+ }
+ return hw_index;
+}
+
+void
+FreeBSDThread::BreakNotify(const ProcessMessage &message)
+{
+ bool status;
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+
+ assert(GetRegisterContext());
+ status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint();
+ assert(status && "Breakpoint update failed!");
+
+ // With our register state restored, resolve the breakpoint object
+ // corresponding to our current PC.
+ assert(GetRegisterContext());
+ lldb::addr_t pc = GetRegisterContext()->GetPC();
+ if (log)
+ log->Printf ("FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
+ lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
+
+ // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
+ // we create a stop reason with should_stop=false. If there is no breakpoint location, then report
+ // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will
+ // be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+ if (bp_site)
+ {
+ lldb::break_id_t bp_id = bp_site->GetID();
+ // If we have an operating system plug-in, we might have set a thread specific breakpoint using the
+ // operating system thread ID, so we can't make any assumptions about the thread ID so we must always
+ // report the breakpoint regardless of the thread.
+ if (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL)
+ SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
+ else
+ {
+ const bool should_stop = false;
+ SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop));
+ }
+ }
+ else
+ SetStopInfo(StopInfoSP());
+}
+
+void
+FreeBSDThread::WatchNotify(const ProcessMessage &message)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+
+ lldb::addr_t halt_addr = message.GetHWAddress();
+ if (log)
+ log->Printf ("FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8"
+ PRIx64, __FUNCTION__, halt_addr);
+
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ if (reg_ctx)
+ {
+ uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
+ uint32_t wp_idx;
+ for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+ {
+ if (reg_ctx->IsWatchpointHit(wp_idx))
+ {
+ // Clear the watchpoint hit here
+ reg_ctx->ClearWatchpointHits();
+ break;
+ }
+ }
+
+ if (wp_idx == num_hw_wps)
+ return;
+
+ Target &target = GetProcess()->GetTarget();
+ lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx);
+ const WatchpointList &wp_list = target.GetWatchpointList();
+ lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr);
+
+ assert(wp_sp.get() && "No watchpoint found");
+ SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this,
+ wp_sp->GetID()));
+ }
+}
+
+void
+FreeBSDThread::TraceNotify(const ProcessMessage &message)
+{
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ if (reg_ctx)
+ {
+ uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
+ uint32_t wp_idx;
+ for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+ {
+ if (reg_ctx->IsWatchpointHit(wp_idx))
+ {
+ WatchNotify(message);
+ return;
+ }
+ }
+ }
+
+ SetStopInfo (StopInfo::CreateStopReasonToTrace(*this));
+}
+
+void
+FreeBSDThread::LimboNotify(const ProcessMessage &message)
+{
+ SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this)));
+}
+
+void
+FreeBSDThread::SignalNotify(const ProcessMessage &message)
+{
+ int signo = message.GetSignal();
+ SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
+}
+
+void
+FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message)
+{
+ int signo = message.GetSignal();
+ SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
+}
+
+void
+FreeBSDThread::CrashNotify(const ProcessMessage &message)
+{
+ // FIXME: Update stop reason as per bugzilla 14598
+ int signo = message.GetSignal();
+
+ assert(message.GetKind() == ProcessMessage::eCrashMessage);
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf ("FreeBSDThread::%s () signo = %i, reason = '%s'",
+ __FUNCTION__, signo, message.PrintCrashReason());
+
+ SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo,
+ message.GetCrashReason(),
+ message.GetFaultAddress())));
+}
+
+unsigned
+FreeBSDThread::GetRegisterIndexFromOffset(unsigned offset)
+{
+ unsigned reg = LLDB_INVALID_REGNUM;
+ ArchSpec arch = HostInfo::GetArchitecture();
+
+ switch (arch.GetMachine())
+ {
+ default:
+ llvm_unreachable("CPU type not supported!");
+ break;
+
+ case llvm::Triple::aarch64:
+ case llvm::Triple::arm:
+ case llvm::Triple::mips64:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ {
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ reg = reg_ctx->GetRegisterIndexFromOffset(offset);
+ }
+ break;
+ }
+ return reg;
+}
+
+void
+FreeBSDThread::ExecNotify(const ProcessMessage &message)
+{
+ SetStopInfo (StopInfo::CreateStopReasonWithExec(*this));
+}
+
+const char *
+FreeBSDThread::GetRegisterName(unsigned reg)
+{
+ const char * name = nullptr;
+ ArchSpec arch = HostInfo::GetArchitecture();
+
+ switch (arch.GetMachine())
+ {
+ default:
+ assert(false && "CPU type not supported!");
+ break;
+
+ case llvm::Triple::aarch64:
+ case llvm::Triple::arm:
+ case llvm::Triple::mips64:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ name = GetRegisterContext()->GetRegisterName(reg);
+ break;
+ }
+ return name;
+}
+
+const char *
+FreeBSDThread::GetRegisterNameFromOffset(unsigned offset)
+{
+ return GetRegisterName(GetRegisterIndexFromOffset(offset));
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h
index 8741075..90c11db 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h
@@ -10,14 +10,23 @@
#ifndef liblldb_FreeBSDThread_H_
#define liblldb_FreeBSDThread_H_
+// C++ Includes
+#include <memory>
+#include <string>
+
// Other libraries and framework includes
-#include "POSIXThread.h"
+#include "lldb/Target/Thread.h"
+#include "RegisterContextPOSIX.h"
+
+class ProcessMessage;
+class ProcessMonitor;
+class POSIXBreakpointProtocol;
//------------------------------------------------------------------------------
// @class FreeBSDThread
// @brief Abstraction of a FreeBSD thread.
class FreeBSDThread
- : public POSIXThread
+ : public lldb_private::Thread
{
public:
@@ -28,12 +37,106 @@ public:
virtual ~FreeBSDThread();
+ // POSIXThread
+ void
+ RefreshStateAfterStop() override;
+
+ // This notifies the thread when a private stop occurs.
+ void
+ DidStop () override;
+
+ const char *
+ GetInfo() override;
+
+ void
+ SetName (const char *name) override;
+
+ const char *
+ GetName () override;
+
+ lldb::RegisterContextSP
+ GetRegisterContext() override;
+
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame (lldb_private::StackFrame *frame) override;
+
+ lldb::addr_t
+ GetThreadPointer () override;
+
+ //--------------------------------------------------------------------------
+ // These functions provide a mapping from the register offset
+ // back to the register index or name for use in debugging or log
+ // output.
+
+ unsigned
+ GetRegisterIndexFromOffset(unsigned offset);
+
+ const char *
+ GetRegisterName(unsigned reg);
+
+ const char *
+ GetRegisterNameFromOffset(unsigned offset);
+
+ //--------------------------------------------------------------------------
+ // These methods form a specialized interface to POSIX threads.
+ //
+ bool Resume();
+
+ void Notify(const ProcessMessage &message);
+
+ //--------------------------------------------------------------------------
+ // These methods provide an interface to watchpoints
+ //
+ bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp);
+
+ bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp);
+
+ uint32_t NumSupportedHardwareWatchpoints();
+
+ uint32_t FindVacantWatchpointIndex();
+
+protected:
+ POSIXBreakpointProtocol *
+ GetPOSIXBreakpointProtocol ()
+ {
+ if (!m_reg_context_sp)
+ m_reg_context_sp = GetRegisterContext();
+ return m_posix_thread;
+ }
+
+ std::unique_ptr<lldb_private::StackFrame> m_frame_ap;
+
+ lldb::BreakpointSiteSP m_breakpoint;
+
+ bool m_thread_name_valid;
+ std::string m_thread_name;
+ POSIXBreakpointProtocol *m_posix_thread;
+
+ ProcessMonitor &
+ GetMonitor();
+
+ bool
+ CalculateStopInfo() override;
+
+ void BreakNotify(const ProcessMessage &message);
+ void WatchNotify(const ProcessMessage &message);
+ virtual void TraceNotify(const ProcessMessage &message);
+ void LimboNotify(const ProcessMessage &message);
+ void SignalNotify(const ProcessMessage &message);
+ void SignalDeliveredNotify(const ProcessMessage &message);
+ void CrashNotify(const ProcessMessage &message);
+ void ExitNotify(const ProcessMessage &message);
+ void ExecNotify(const ProcessMessage &message);
+
+ lldb_private::Unwind *
+ GetUnwinder() override;
+
//--------------------------------------------------------------------------
// FreeBSDThread internal API.
// POSIXThread override
virtual void
- WillResume(lldb::StateType resume_state);
+ WillResume(lldb::StateType resume_state) override;
};
#endif // #ifndef liblldb_FreeBSDThread_H_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp
index 3b8cea7..409cf8c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp
@@ -45,7 +45,7 @@ POSIXLimboStopInfo::ShouldNotify(Event *event_ptr)
//===----------------------------------------------------------------------===//
// POSIXCrashStopInfo
-POSIXCrashStopInfo::POSIXCrashStopInfo(POSIXThread &thread,
+POSIXCrashStopInfo::POSIXCrashStopInfo(FreeBSDThread &thread,
uint32_t status,
CrashReason reason,
lldb::addr_t fault_addr)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
index a1ee2ea..ace6c98 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
@@ -17,7 +17,7 @@
#include "lldb/Target/StopInfo.h"
#include "CrashReason.h"
-#include "POSIXThread.h"
+#include "FreeBSDThread.h"
#include <string>
@@ -42,7 +42,7 @@ class POSIXLimboStopInfo
: public POSIXStopInfo
{
public:
- POSIXLimboStopInfo(POSIXThread &thread)
+ POSIXLimboStopInfo(FreeBSDThread &thread)
: POSIXStopInfo(thread, 0)
{ }
@@ -70,7 +70,7 @@ class POSIXCrashStopInfo
: public POSIXStopInfo
{
public:
- POSIXCrashStopInfo(POSIXThread &thread, uint32_t status,
+ POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status,
CrashReason reason,
lldb::addr_t fault_addr);
~POSIXCrashStopInfo();
@@ -88,7 +88,7 @@ class POSIXNewThreadStopInfo
: public POSIXStopInfo
{
public:
- POSIXNewThreadStopInfo (POSIXThread &thread)
+ POSIXNewThreadStopInfo (FreeBSDThread &thread)
: POSIXStopInfo (thread, 0)
{ }
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXThread.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXThread.cpp
deleted file mode 100644
index 7d95e96..0000000
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXThread.cpp
+++ /dev/null
@@ -1,665 +0,0 @@
-//===-- POSIXThread.cpp -----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <errno.h>
-
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/State.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/HostNativeThread.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/StopInfo.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadSpec.h"
-#include "llvm/ADT/SmallString.h"
-#include "POSIXStopInfo.h"
-#include "POSIXThread.h"
-#include "ProcessPOSIX.h"
-#include "ProcessPOSIXLog.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_arm.h"
-#include "RegisterContextPOSIXProcessMonitor_arm64.h"
-#include "RegisterContextPOSIXProcessMonitor_mips64.h"
-#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
-#include "RegisterContextPOSIXProcessMonitor_x86.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
-#include "Plugins/Process/Utility/UnwindLLDB.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-
-POSIXThread::POSIXThread(Process &process, lldb::tid_t tid)
- : Thread(process, tid),
- m_frame_ap (),
- m_breakpoint (),
- m_thread_name_valid (false),
- m_thread_name (),
- m_posix_thread(NULL)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("POSIXThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid);
-
- // Set the current watchpoints for this thread.
- Target &target = GetProcess()->GetTarget();
- const WatchpointList &wp_list = target.GetWatchpointList();
- size_t wp_size = wp_list.GetSize();
-
- for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++)
- {
- lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
- if (wp.get() && wp->IsEnabled())
- {
- // This watchpoint as been enabled; obviously this "new" thread
- // has been created since that watchpoint was enabled. Since
- // the POSIXBreakpointProtocol has yet to be initialized, its
- // m_watchpoints_initialized member will be FALSE. Attempting to
- // read the debug status register to determine if a watchpoint
- // has been hit would result in the zeroing of that register.
- // Since the active debug registers would have been cloned when
- // this thread was created, simply force the m_watchpoints_initized
- // member to TRUE and avoid resetting dr6 and dr7.
- GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized();
- }
- }
-}
-
-POSIXThread::~POSIXThread()
-{
- DestroyThread();
-}
-
-ProcessMonitor &
-POSIXThread::GetMonitor()
-{
- ProcessSP base = GetProcess();
- ProcessPOSIX &process = static_cast<ProcessPOSIX&>(*base);
- return process.GetMonitor();
-}
-
-void
-POSIXThread::RefreshStateAfterStop()
-{
- // Invalidate all registers in our register context. We don't set "force" to
- // true because the stop reply packet might have had some register values
- // that were expedited and these will already be copied into the register
- // context by the time this function gets called. The KDPRegisterContext
- // class has been made smart enough to detect when it needs to invalidate
- // which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
- //if (StateIsStoppedState(GetState())
- {
- const bool force = false;
- GetRegisterContext()->InvalidateIfNeeded (force);
- }
-}
-
-const char *
-POSIXThread::GetInfo()
-{
- return NULL;
-}
-
-void
-POSIXThread::SetName (const char *name)
-{
- m_thread_name_valid = (name && name[0]);
- if (m_thread_name_valid)
- m_thread_name.assign (name);
- else
- m_thread_name.clear();
-}
-
-const char *
-POSIXThread::GetName ()
-{
- if (!m_thread_name_valid)
- {
- llvm::SmallString<32> thread_name;
- HostNativeThread::GetName(GetID(), thread_name);
- m_thread_name = thread_name.c_str();
- m_thread_name_valid = true;
- }
-
- if (m_thread_name.empty())
- return NULL;
- return m_thread_name.c_str();
-}
-
-lldb::RegisterContextSP
-POSIXThread::GetRegisterContext()
-{
- if (!m_reg_context_sp)
- {
- m_posix_thread = NULL;
-
- RegisterInfoInterface *reg_interface = NULL;
- const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
-
- switch (target_arch.GetTriple().getOS())
- {
- case llvm::Triple::FreeBSD:
- switch (target_arch.GetMachine())
- {
- case llvm::Triple::aarch64:
- reg_interface = new RegisterContextFreeBSD_arm64(target_arch);
- break;
- case llvm::Triple::arm:
- reg_interface = new RegisterContextFreeBSD_arm(target_arch);
- break;
- case llvm::Triple::ppc:
-#ifndef __powerpc64__
- reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch);
- break;
-#endif
- case llvm::Triple::ppc64:
- reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch);
- break;
- case llvm::Triple::mips64:
- reg_interface = new RegisterContextFreeBSD_mips64(target_arch);
- break;
- case llvm::Triple::x86:
- reg_interface = new RegisterContextFreeBSD_i386(target_arch);
- break;
- case llvm::Triple::x86_64:
- reg_interface = new RegisterContextFreeBSD_x86_64(target_arch);
- break;
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- assert(reg_interface && "OS or CPU not supported!");
-
- switch (target_arch.GetMachine())
- {
- case llvm::Triple::aarch64:
- {
- RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::arm:
- {
- RegisterContextPOSIXProcessMonitor_arm *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::mips64:
- {
- RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- {
- RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- {
- RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- default:
- break;
- }
- }
- return m_reg_context_sp;
-}
-
-lldb::RegisterContextSP
-POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
-{
- lldb::RegisterContextSP reg_ctx_sp;
- uint32_t concrete_frame_idx = 0;
-
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("POSIXThread::%s ()", __FUNCTION__);
-
- if (frame)
- concrete_frame_idx = frame->GetConcreteFrameIndex();
-
- if (concrete_frame_idx == 0)
- reg_ctx_sp = GetRegisterContext();
- else
- {
- assert(GetUnwinder());
- reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
- }
-
- return reg_ctx_sp;
-}
-
-lldb::addr_t
-POSIXThread::GetThreadPointer ()
-{
- ProcessMonitor &monitor = GetMonitor();
- addr_t addr;
- if (monitor.ReadThreadPointer (GetID(), addr))
- return addr;
- else
- return LLDB_INVALID_ADDRESS;
-}
-
-bool
-POSIXThread::CalculateStopInfo()
-{
- SetStopInfo (m_stop_info_sp);
- return true;
-}
-
-Unwind *
-POSIXThread::GetUnwinder()
-{
- if (m_unwinder_ap.get() == NULL)
- m_unwinder_ap.reset(new UnwindLLDB(*this));
-
- return m_unwinder_ap.get();
-}
-
-void
-POSIXThread::DidStop()
-{
- // Don't set the thread state to stopped unless we really stopped.
-}
-
-bool
-POSIXThread::Resume()
-{
- lldb::StateType resume_state = GetResumeState();
- ProcessMonitor &monitor = GetMonitor();
- bool status;
-
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log)
- log->Printf ("POSIXThread::%s (), resume_state = %s", __FUNCTION__,
- StateAsCString(resume_state));
-
- switch (resume_state)
- {
- default:
- assert(false && "Unexpected state for resume!");
- status = false;
- break;
-
- case lldb::eStateRunning:
- SetState(resume_state);
- status = monitor.Resume(GetID(), GetResumeSignal());
- break;
-
- case lldb::eStateStepping:
- SetState(resume_state);
- status = monitor.SingleStep(GetID(), GetResumeSignal());
- break;
- case lldb::eStateStopped:
- case lldb::eStateSuspended:
- status = true;
- break;
- }
-
- return status;
-}
-
-void
-POSIXThread::Notify(const ProcessMessage &message)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log)
- log->Printf ("POSIXThread::%s () message kind = '%s' for tid %" PRIu64,
- __FUNCTION__, message.PrintKind(), GetID());
-
- switch (message.GetKind())
- {
- default:
- assert(false && "Unexpected message kind!");
- break;
-
- case ProcessMessage::eExitMessage:
- // Nothing to be done.
- break;
-
- case ProcessMessage::eLimboMessage:
- LimboNotify(message);
- break;
-
- case ProcessMessage::eSignalMessage:
- SignalNotify(message);
- break;
-
- case ProcessMessage::eSignalDeliveredMessage:
- SignalDeliveredNotify(message);
- break;
-
- case ProcessMessage::eTraceMessage:
- TraceNotify(message);
- break;
-
- case ProcessMessage::eBreakpointMessage:
- BreakNotify(message);
- break;
-
- case ProcessMessage::eWatchpointMessage:
- WatchNotify(message);
- break;
-
- case ProcessMessage::eCrashMessage:
- CrashNotify(message);
- break;
-
- case ProcessMessage::eNewThreadMessage:
- ThreadNotify(message);
- break;
-
- case ProcessMessage::eExecMessage:
- ExecNotify(message);
- break;
- }
-}
-
-bool
-POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp)
-{
- bool wp_set = false;
- if (wp)
- {
- addr_t wp_addr = wp->GetLoadAddress();
- size_t wp_size = wp->GetByteSize();
- bool wp_read = wp->WatchpointRead();
- bool wp_write = wp->WatchpointWrite();
- uint32_t wp_hw_index = wp->GetHardwareIndex();
- POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx)
- wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size,
- wp_read, wp_write,
- wp_hw_index);
- }
- return wp_set;
-}
-
-bool
-POSIXThread::DisableHardwareWatchpoint(Watchpoint *wp)
-{
- bool result = false;
- if (wp)
- {
- lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
- if (reg_ctx_sp.get())
- result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
- }
- return result;
-}
-
-uint32_t
-POSIXThread::NumSupportedHardwareWatchpoints()
-{
- lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
- if (reg_ctx_sp.get())
- return reg_ctx_sp->NumSupportedHardwareWatchpoints();
- return 0;
-}
-
-uint32_t
-POSIXThread::FindVacantWatchpointIndex()
-{
- uint32_t hw_index = LLDB_INVALID_INDEX32;
- uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx)
- {
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
- {
- if (reg_ctx->IsWatchpointVacant(wp_idx))
- {
- hw_index = wp_idx;
- break;
- }
- }
- }
- return hw_index;
-}
-
-void
-POSIXThread::BreakNotify(const ProcessMessage &message)
-{
- bool status;
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
-
- assert(GetRegisterContext());
- status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint();
- assert(status && "Breakpoint update failed!");
-
- // With our register state restored, resolve the breakpoint object
- // corresponding to our current PC.
- assert(GetRegisterContext());
- lldb::addr_t pc = GetRegisterContext()->GetPC();
- if (log)
- log->Printf ("POSIXThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
- lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
-
- // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
- // we create a stop reason with should_stop=false. If there is no breakpoint location, then report
- // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will
- // be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
- if (bp_site)
- {
- lldb::break_id_t bp_id = bp_site->GetID();
- // If we have an operating system plug-in, we might have set a thread specific breakpoint using the
- // operating system thread ID, so we can't make any assumptions about the thread ID so we must always
- // report the breakpoint regardless of the thread.
- if (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL)
- SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
- else
- {
- const bool should_stop = false;
- SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop));
- }
- }
- else
- SetStopInfo(StopInfoSP());
-}
-
-void
-POSIXThread::WatchNotify(const ProcessMessage &message)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
-
- lldb::addr_t halt_addr = message.GetHWAddress();
- if (log)
- log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8"
- PRIx64, __FUNCTION__, halt_addr);
-
- POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx)
- {
- uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
- {
- if (reg_ctx->IsWatchpointHit(wp_idx))
- {
- // Clear the watchpoint hit here
- reg_ctx->ClearWatchpointHits();
- break;
- }
- }
-
- if (wp_idx == num_hw_wps)
- return;
-
- Target &target = GetProcess()->GetTarget();
- lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx);
- const WatchpointList &wp_list = target.GetWatchpointList();
- lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr);
-
- assert(wp_sp.get() && "No watchpoint found");
- SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this,
- wp_sp->GetID()));
- }
-}
-
-void
-POSIXThread::TraceNotify(const ProcessMessage &message)
-{
- POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx)
- {
- uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
- {
- if (reg_ctx->IsWatchpointHit(wp_idx))
- {
- WatchNotify(message);
- return;
- }
- }
- }
-
- SetStopInfo (StopInfo::CreateStopReasonToTrace(*this));
-}
-
-void
-POSIXThread::LimboNotify(const ProcessMessage &message)
-{
- SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this)));
-}
-
-void
-POSIXThread::SignalNotify(const ProcessMessage &message)
-{
- int signo = message.GetSignal();
- SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
-}
-
-void
-POSIXThread::SignalDeliveredNotify(const ProcessMessage &message)
-{
- int signo = message.GetSignal();
- SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
-}
-
-void
-POSIXThread::CrashNotify(const ProcessMessage &message)
-{
- // FIXME: Update stop reason as per bugzilla 14598
- int signo = message.GetSignal();
-
- assert(message.GetKind() == ProcessMessage::eCrashMessage);
-
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log)
- log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'",
- __FUNCTION__, signo, message.PrintCrashReason());
-
- SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo,
- message.GetCrashReason(),
- message.GetFaultAddress())));
-}
-
-void
-POSIXThread::ThreadNotify(const ProcessMessage &message)
-{
- SetStopInfo (lldb::StopInfoSP(new POSIXNewThreadStopInfo(*this)));
-}
-
-unsigned
-POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
-{
- unsigned reg = LLDB_INVALID_REGNUM;
- ArchSpec arch = HostInfo::GetArchitecture();
-
- switch (arch.GetMachine())
- {
- default:
- llvm_unreachable("CPU type not supported!");
- break;
-
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- case llvm::Triple::mips64:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- {
- POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
- reg = reg_ctx->GetRegisterIndexFromOffset(offset);
- }
- break;
- }
- return reg;
-}
-
-void
-POSIXThread::ExecNotify(const ProcessMessage &message)
-{
- SetStopInfo (StopInfo::CreateStopReasonWithExec(*this));
-}
-
-const char *
-POSIXThread::GetRegisterName(unsigned reg)
-{
- const char * name = nullptr;
- ArchSpec arch = HostInfo::GetArchitecture();
-
- switch (arch.GetMachine())
- {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- case llvm::Triple::mips64:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- name = GetRegisterContext()->GetRegisterName(reg);
- break;
- }
- return name;
-}
-
-const char *
-POSIXThread::GetRegisterNameFromOffset(unsigned offset)
-{
- return GetRegisterName(GetRegisterIndexFromOffset(offset));
-}
-
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXThread.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXThread.h
deleted file mode 100644
index c38d194..0000000
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/POSIXThread.h
+++ /dev/null
@@ -1,132 +0,0 @@
-//===-- POSIXThread.h -------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_POSIXThread_H_
-#define liblldb_POSIXThread_H_
-
-// C Includes
-// C++ Includes
-#include <memory>
-#include <string>
-
-// Other libraries and framework includes
-#include "lldb/Target/Thread.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
-
-class ProcessMessage;
-class ProcessMonitor;
-class POSIXBreakpointProtocol;
-
-//------------------------------------------------------------------------------
-// @class POSIXThread
-// @brief Abstraction of a POSIX thread.
-class POSIXThread
- : public lldb_private::Thread
-{
-public:
- POSIXThread(lldb_private::Process &process, lldb::tid_t tid);
-
- virtual ~POSIXThread();
-
- void
- RefreshStateAfterStop() override;
-
- // This notifies the thread when a private stop occurs.
- void
- DidStop () override;
-
- const char *
- GetInfo() override;
-
- void
- SetName (const char *name) override;
-
- const char *
- GetName () override;
-
- lldb::RegisterContextSP
- GetRegisterContext() override;
-
- lldb::RegisterContextSP
- CreateRegisterContextForFrame (lldb_private::StackFrame *frame) override;
-
- lldb::addr_t
- GetThreadPointer () override;
-
- //--------------------------------------------------------------------------
- // These functions provide a mapping from the register offset
- // back to the register index or name for use in debugging or log
- // output.
-
- unsigned
- GetRegisterIndexFromOffset(unsigned offset);
-
- const char *
- GetRegisterName(unsigned reg);
-
- const char *
- GetRegisterNameFromOffset(unsigned offset);
-
- //--------------------------------------------------------------------------
- // These methods form a specialized interface to POSIX threads.
- //
- bool Resume();
-
- void Notify(const ProcessMessage &message);
-
- //--------------------------------------------------------------------------
- // These methods provide an interface to watchpoints
- //
- bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp);
-
- bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp);
-
- uint32_t NumSupportedHardwareWatchpoints();
-
- uint32_t FindVacantWatchpointIndex();
-
-protected:
- POSIXBreakpointProtocol *
- GetPOSIXBreakpointProtocol ()
- {
- if (!m_reg_context_sp)
- m_reg_context_sp = GetRegisterContext();
- return m_posix_thread;
- }
-
- std::unique_ptr<lldb_private::StackFrame> m_frame_ap;
-
- lldb::BreakpointSiteSP m_breakpoint;
-
- bool m_thread_name_valid;
- std::string m_thread_name;
- POSIXBreakpointProtocol *m_posix_thread;
-
- ProcessMonitor &
- GetMonitor();
-
- bool
- CalculateStopInfo() override;
-
- void BreakNotify(const ProcessMessage &message);
- void WatchNotify(const ProcessMessage &message);
- virtual void TraceNotify(const ProcessMessage &message);
- void LimboNotify(const ProcessMessage &message);
- void SignalNotify(const ProcessMessage &message);
- void SignalDeliveredNotify(const ProcessMessage &message);
- void CrashNotify(const ProcessMessage &message);
- void ThreadNotify(const ProcessMessage &message);
- void ExitNotify(const ProcessMessage &message);
- void ExecNotify(const ProcessMessage &message);
-
- lldb_private::Unwind *
- GetUnwinder() override;
-};
-
-#endif // #ifndef liblldb_POSIXThread_H_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
index a0458f1..769ccd7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -28,6 +28,23 @@
#include "ProcessMonitor.h"
#include "FreeBSDThread.h"
+// Other libraries and framework includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/Watchpoint.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Platform.h"
+#include "lldb/Target/Target.h"
+
+#include "lldb/Host/posix/Fcntl.h"
+
+
using namespace lldb;
using namespace lldb_private;
@@ -45,13 +62,13 @@ namespace
// Static functions.
lldb::ProcessSP
-ProcessFreeBSD::CreateInstance(Target& target,
+ProcessFreeBSD::CreateInstance(lldb::TargetSP target_sp,
Listener &listener,
const FileSpec *crash_file_path)
{
lldb::ProcessSP process_sp;
if (crash_file_path == NULL)
- process_sp.reset(new ProcessFreeBSD (target, listener));
+ process_sp.reset(new ProcessFreeBSD (target_sp, listener, GetFreeBSDSignals()));
return process_sp;
}
@@ -97,32 +114,6 @@ ProcessFreeBSD::GetPluginVersion()
}
void
-ProcessFreeBSD::GetPluginCommandHelp(const char *command, Stream *strm)
-{
-}
-
-Error
-ProcessFreeBSD::ExecutePluginCommand(Args &command, Stream *strm)
-{
- return Error(1, eErrorTypeGeneric);
-}
-
-Log *
-ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command)
-{
- return NULL;
-}
-
-//------------------------------------------------------------------------------
-// Constructors and destructors.
-
-ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener)
- : ProcessPOSIX(target, listener, GetFreeBSDSignals ()),
- m_resume_signo(0)
-{
-}
-
-void
ProcessFreeBSD::Terminate()
{
}
@@ -232,7 +223,7 @@ ProcessFreeBSD::WillResume()
m_suspend_tids.clear();
m_run_tids.clear();
m_step_tids.clear();
- return ProcessPOSIX::WillResume();
+ return Process::WillResume();
}
void
@@ -264,7 +255,7 @@ ProcessFreeBSD::SendMessage(const ProcessMessage &message)
break;
case ProcessMessage::eNewThreadMessage:
- assert(0 && "eNewThreadMessage unexpected on FreeBSD");
+ llvm_unreachable("eNewThreadMessage unexpected on FreeBSD");
break;
case ProcessMessage::eExecMessage:
@@ -274,3 +265,781 @@ ProcessFreeBSD::SendMessage(const ProcessMessage &message)
m_message_queue.push(message);
}
+
+//------------------------------------------------------------------------------
+// Constructors and destructors.
+
+ProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp, Listener &listener, UnixSignalsSP &unix_signals_sp)
+ : Process(target_sp, listener, unix_signals_sp),
+ m_byte_order(endian::InlHostByteOrder()),
+ m_monitor(NULL),
+ m_module(NULL),
+ m_message_mutex (Mutex::eMutexTypeRecursive),
+ m_exit_now(false),
+ m_seen_initial_stop(),
+ m_resume_signo(0)
+{
+ // FIXME: Putting this code in the ctor and saving the byte order in a
+ // member variable is a hack to avoid const qual issues in GetByteOrder.
+ lldb::ModuleSP module = GetTarget().GetExecutableModule();
+ if (module && module->GetObjectFile())
+ m_byte_order = module->GetObjectFile()->GetByteOrder();
+}
+
+ProcessFreeBSD::~ProcessFreeBSD()
+{
+ delete m_monitor;
+}
+
+//------------------------------------------------------------------------------
+// Process protocol.
+void
+ProcessFreeBSD::Finalize()
+{
+ Process::Finalize();
+
+ if (m_monitor)
+ m_monitor->StopMonitor();
+}
+
+bool
+ProcessFreeBSD::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name)
+{
+ // For now we are just making sure the file exists for a given module
+ ModuleSP exe_module_sp(target_sp->GetExecutableModule());
+ if (exe_module_sp.get())
+ return exe_module_sp->GetFileSpec().Exists();
+ // If there is no executable module, we return true since we might be preparing to attach.
+ return true;
+}
+
+Error
+ProcessFreeBSD::DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info)
+{
+ Error error;
+ assert(m_monitor == NULL);
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID());
+
+ m_monitor = new ProcessMonitor(this, pid, error);
+
+ if (!error.Success())
+ return error;
+
+ PlatformSP platform_sp (GetTarget().GetPlatform ());
+ assert (platform_sp.get());
+ if (!platform_sp)
+ return error; // FIXME: Detatch?
+
+ // Find out what we can about this process
+ ProcessInstanceInfo process_info;
+ platform_sp->GetProcessInfo (pid, process_info);
+
+ // Resolve the executable module
+ ModuleSP exe_module_sp;
+ FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
+ ModuleSpec exe_module_spec(process_info.GetExecutableFile(), GetTarget().GetArchitecture());
+ error = platform_sp->ResolveExecutable(exe_module_spec,
+ exe_module_sp,
+ executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+ if (!error.Success())
+ return error;
+
+ // Fix the target architecture if necessary
+ const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
+ if (module_arch.IsValid() && !GetTarget().GetArchitecture().IsExactMatch(module_arch))
+ GetTarget().SetArchitecture(module_arch);
+
+ // Initialize the target module list
+ GetTarget().SetExecutableModule (exe_module_sp, true);
+
+ SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
+
+ SetID(pid);
+
+ return error;
+}
+
+Error
+ProcessFreeBSD::WillLaunch(Module* module)
+{
+ Error error;
+ return error;
+}
+
+FileSpec
+ProcessFreeBSD::GetFileSpec(const lldb_private::FileAction *file_action,
+ const FileSpec &default_file_spec,
+ const FileSpec &dbg_pts_file_spec)
+{
+ FileSpec file_spec{};
+
+ if (file_action && file_action->GetAction() == FileAction::eFileActionOpen)
+ {
+ file_spec = file_action->GetFileSpec();
+ // By default the stdio paths passed in will be pseudo-terminal
+ // (/dev/pts). If so, convert to using a different default path
+ // instead to redirect I/O to the debugger console. This should
+ // also handle user overrides to /dev/null or a different file.
+ if (!file_spec || file_spec == dbg_pts_file_spec)
+ file_spec = default_file_spec;
+ }
+ return file_spec;
+}
+
+Error
+ProcessFreeBSD::DoLaunch (Module *module,
+ ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ assert(m_monitor == NULL);
+
+ FileSpec working_dir = launch_info.GetWorkingDirectory();
+ if (working_dir &&
+ (!working_dir.ResolvePath() ||
+ working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
+ {
+ error.SetErrorStringWithFormat("No such file or directory: %s",
+ working_dir.GetCString());
+ return error;
+ }
+
+ SetPrivateState(eStateLaunching);
+
+ const lldb_private::FileAction *file_action;
+
+ // Default of empty will mean to use existing open file descriptors
+ FileSpec stdin_file_spec{};
+ FileSpec stdout_file_spec{};
+ FileSpec stderr_file_spec{};
+
+ const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL,0), false};
+
+ file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
+ stdin_file_spec = GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec);
+
+ file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
+ stdout_file_spec = GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec);
+
+ file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
+ stderr_file_spec = GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec);
+
+ m_monitor = new ProcessMonitor(this,
+ module,
+ launch_info.GetArguments().GetConstArgumentVector(),
+ launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
+ stdin_file_spec,
+ stdout_file_spec,
+ stderr_file_spec,
+ working_dir,
+ launch_info,
+ error);
+
+ m_module = module;
+
+ if (!error.Success())
+ return error;
+
+ int terminal = m_monitor->GetTerminalFD();
+ if (terminal >= 0) {
+ // The reader thread will close the file descriptor when done, so we pass it a copy.
+#ifdef F_DUPFD_CLOEXEC
+ int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0);
+ if (stdio == -1) {
+ error.SetErrorToErrno();
+ return error;
+ }
+#else
+ // Special case when F_DUPFD_CLOEXEC does not exist (Debian kFreeBSD)
+ int stdio = fcntl(terminal, F_DUPFD, 0);
+ if (stdio == -1) {
+ error.SetErrorToErrno();
+ return error;
+ }
+ stdio = fcntl(terminal, F_SETFD, FD_CLOEXEC);
+ if (stdio == -1) {
+ error.SetErrorToErrno();
+ return error;
+ }
+#endif
+ SetSTDIOFileDescriptor(stdio);
+ }
+
+ SetID(m_monitor->GetPID());
+ return error;
+}
+
+void
+ProcessFreeBSD::DidLaunch()
+{
+}
+
+addr_t
+ProcessFreeBSD::GetImageInfoAddress()
+{
+ Target *target = &GetTarget();
+ ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
+ Address addr = obj_file->GetImageInfoAddress(target);
+
+ if (addr.IsValid())
+ return addr.GetLoadAddress(target);
+ return LLDB_INVALID_ADDRESS;
+}
+
+Error
+ProcessFreeBSD::DoHalt(bool &caused_stop)
+{
+ Error error;
+
+ if (IsStopped())
+ {
+ caused_stop = false;
+ }
+ else if (kill(GetID(), SIGSTOP))
+ {
+ caused_stop = false;
+ error.SetErrorToErrno();
+ }
+ else
+ {
+ caused_stop = true;
+ }
+ return error;
+}
+
+Error
+ProcessFreeBSD::DoSignal(int signal)
+{
+ Error error;
+
+ if (kill(GetID(), signal))
+ error.SetErrorToErrno();
+
+ return error;
+}
+
+Error
+ProcessFreeBSD::DoDestroy()
+{
+ Error error;
+
+ if (!HasExited())
+ {
+ assert(m_monitor);
+ m_exit_now = true;
+ if (GetID() == LLDB_INVALID_PROCESS_ID)
+ {
+ error.SetErrorString("invalid process id");
+ return error;
+ }
+ if (!m_monitor->Kill())
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ SetPrivateState(eStateExited);
+ }
+
+ return error;
+}
+
+void
+ProcessFreeBSD::DoDidExec()
+{
+ Target *target = &GetTarget();
+ if (target)
+ {
+ PlatformSP platform_sp (target->GetPlatform());
+ assert (platform_sp.get());
+ if (platform_sp)
+ {
+ ProcessInstanceInfo process_info;
+ platform_sp->GetProcessInfo(GetID(), process_info);
+ ModuleSP exe_module_sp;
+ ModuleSpec exe_module_spec(process_info.GetExecutableFile(), target->GetArchitecture());
+ FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
+ Error error = platform_sp->ResolveExecutable(exe_module_spec,
+ exe_module_sp,
+ executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+ if (!error.Success())
+ return;
+ target->SetExecutableModule(exe_module_sp, true);
+ }
+ }
+}
+
+bool
+ProcessFreeBSD::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid)
+{
+ bool added_to_set = false;
+ ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid);
+ if (it == m_seen_initial_stop.end())
+ {
+ m_seen_initial_stop.insert(stop_tid);
+ added_to_set = true;
+ }
+ return added_to_set;
+}
+
+bool
+ProcessFreeBSD::WaitingForInitialStop(lldb::tid_t stop_tid)
+{
+ return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
+}
+
+FreeBSDThread *
+ProcessFreeBSD::CreateNewFreeBSDThread(lldb_private::Process &process, lldb::tid_t tid)
+{
+ return new FreeBSDThread(process, tid);
+}
+
+void
+ProcessFreeBSD::RefreshStateAfterStop()
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());
+
+ Mutex::Locker lock(m_message_mutex);
+
+ // This method used to only handle one message. Changing it to loop allows
+ // it to handle the case where we hit a breakpoint while handling a different
+ // breakpoint.
+ while (!m_message_queue.empty())
+ {
+ ProcessMessage &message = m_message_queue.front();
+
+ // Resolve the thread this message corresponds to and pass it along.
+ lldb::tid_t tid = message.GetTID();
+ if (log)
+ log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
+
+ m_thread_list.RefreshStateAfterStop();
+
+ FreeBSDThread *thread = static_cast<FreeBSDThread*>(
+ GetThreadList().FindThreadByID(tid, false).get());
+ if (thread)
+ thread->Notify(message);
+
+ if (message.GetKind() == ProcessMessage::eExitMessage)
+ {
+ // FIXME: We should tell the user about this, but the limbo message is probably better for that.
+ if (log)
+ log->Printf ("ProcessFreeBSD::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);
+
+ Mutex::Locker lock(m_thread_list.GetMutex());
+
+ ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
+ thread_sp.reset();
+ m_seen_initial_stop.erase(tid);
+ }
+
+ m_message_queue.pop();
+ }
+}
+
+bool
+ProcessFreeBSD::IsAlive()
+{
+ StateType state = GetPrivateState();
+ return state != eStateDetached
+ && state != eStateExited
+ && state != eStateInvalid
+ && state != eStateUnloaded;
+}
+
+size_t
+ProcessFreeBSD::DoReadMemory(addr_t vm_addr,
+ void *buf, size_t size, Error &error)
+{
+ assert(m_monitor);
+ return m_monitor->ReadMemory(vm_addr, buf, size, error);
+}
+
+size_t
+ProcessFreeBSD::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
+ Error &error)
+{
+ assert(m_monitor);
+ return m_monitor->WriteMemory(vm_addr, buf, size, error);
+}
+
+addr_t
+ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions,
+ Error &error)
+{
+ addr_t allocated_addr = LLDB_INVALID_ADDRESS;
+
+ unsigned prot = 0;
+ if (permissions & lldb::ePermissionsReadable)
+ prot |= eMmapProtRead;
+ if (permissions & lldb::ePermissionsWritable)
+ prot |= eMmapProtWrite;
+ if (permissions & lldb::ePermissionsExecutable)
+ prot |= eMmapProtExec;
+
+ if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
+ eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
+ m_addr_to_mmap_size[allocated_addr] = size;
+ error.Clear();
+ } else {
+ allocated_addr = LLDB_INVALID_ADDRESS;
+ error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
+ }
+
+ return allocated_addr;
+}
+
+Error
+ProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr)
+{
+ Error error;
+ MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
+ if (pos != m_addr_to_mmap_size.end() &&
+ InferiorCallMunmap(this, addr, pos->second))
+ m_addr_to_mmap_size.erase (pos);
+ else
+ error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
+
+ return error;
+}
+
+size_t
+ProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
+{
+ static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xD4 };
+ static const uint8_t g_i386_opcode[] = { 0xCC };
+
+ ArchSpec arch = GetTarget().GetArchitecture();
+ const uint8_t *opcode = NULL;
+ size_t opcode_size = 0;
+
+ switch (arch.GetMachine())
+ {
+ default:
+ assert(false && "CPU type not supported!");
+ break;
+
+ case llvm::Triple::arm:
+ {
+ // The ARM reference recommends the use of 0xe7fddefe and 0xdefe
+ // but the linux kernel does otherwise.
+ static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 };
+ static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };
+
+ lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
+ AddressClass addr_class = eAddressClassUnknown;
+
+ if (bp_loc_sp)
+ addr_class = bp_loc_sp->GetAddress ().GetAddressClass ();
+
+ if (addr_class == eAddressClassCodeAlternateISA
+ || (addr_class == eAddressClassUnknown
+ && bp_loc_sp->GetAddress().GetOffset() & 1))
+ {
+ opcode = g_thumb_breakpoint_opcode;
+ opcode_size = sizeof(g_thumb_breakpoint_opcode);
+ }
+ else
+ {
+ opcode = g_arm_breakpoint_opcode;
+ opcode_size = sizeof(g_arm_breakpoint_opcode);
+ }
+ }
+ break;
+ case llvm::Triple::aarch64:
+ opcode = g_aarch64_opcode;
+ opcode_size = sizeof(g_aarch64_opcode);
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ opcode = g_i386_opcode;
+ opcode_size = sizeof(g_i386_opcode);
+ break;
+ }
+
+ bp_site->SetTrapOpcode(opcode, opcode_size);
+ return opcode_size;
+}
+
+Error
+ProcessFreeBSD::EnableBreakpointSite(BreakpointSite *bp_site)
+{
+ return EnableSoftwareBreakpoint(bp_site);
+}
+
+Error
+ProcessFreeBSD::DisableBreakpointSite(BreakpointSite *bp_site)
+{
+ return DisableSoftwareBreakpoint(bp_site);
+}
+
+Error
+ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify)
+{
+ Error error;
+ if (wp)
+ {
+ user_id_t watchID = wp->GetID();
+ addr_t addr = wp->GetLoadAddress();
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf ("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")",
+ watchID);
+ if (wp->IsEnabled())
+ {
+ if (log)
+ log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
+ watchID, (uint64_t)addr);
+ return error;
+ }
+
+ // Try to find a vacant watchpoint slot in the inferiors' main thread
+ uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ FreeBSDThread *thread = static_cast<FreeBSDThread*>(
+ m_thread_list.GetThreadAtIndex(0, false).get());
+
+ if (thread)
+ wp_hw_index = thread->FindVacantWatchpointIndex();
+
+ if (wp_hw_index == LLDB_INVALID_INDEX32)
+ {
+ error.SetErrorString("Setting hardware watchpoint failed.");
+ }
+ else
+ {
+ wp->SetHardwareIndex(wp_hw_index);
+ bool wp_enabled = true;
+ uint32_t thread_count = m_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < thread_count; ++i)
+ {
+ thread = static_cast<FreeBSDThread*>(
+ m_thread_list.GetThreadAtIndex(i, false).get());
+ if (thread)
+ wp_enabled &= thread->EnableHardwareWatchpoint(wp);
+ else
+ wp_enabled = false;
+ }
+ if (wp_enabled)
+ {
+ wp->SetEnabled(true, notify);
+ return error;
+ }
+ else
+ {
+ // Watchpoint enabling failed on at least one
+ // of the threads so roll back all of them
+ DisableWatchpoint(wp, false);
+ error.SetErrorString("Setting hardware watchpoint failed");
+ }
+ }
+ }
+ else
+ error.SetErrorString("Watchpoint argument was NULL.");
+ return error;
+}
+
+Error
+ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify)
+{
+ Error error;
+ if (wp)
+ {
+ user_id_t watchID = wp->GetID();
+ addr_t addr = wp->GetLoadAddress();
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")",
+ watchID);
+ if (!wp->IsEnabled())
+ {
+ if (log)
+ log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
+ watchID, (uint64_t)addr);
+ // This is needed (for now) to keep watchpoints disabled correctly
+ wp->SetEnabled(false, notify);
+ return error;
+ }
+
+ if (wp->IsHardware())
+ {
+ bool wp_disabled = true;
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ uint32_t thread_count = m_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < thread_count; ++i)
+ {
+ FreeBSDThread *thread = static_cast<FreeBSDThread*>(
+ m_thread_list.GetThreadAtIndex(i, false).get());
+ if (thread)
+ wp_disabled &= thread->DisableHardwareWatchpoint(wp);
+ else
+ wp_disabled = false;
+ }
+ if (wp_disabled)
+ {
+ wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
+ wp->SetEnabled(false, notify);
+ return error;
+ }
+ else
+ error.SetErrorString("Disabling hardware watchpoint failed");
+ }
+ }
+ else
+ error.SetErrorString("Watchpoint argument was NULL.");
+ return error;
+}
+
+Error
+ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num)
+{
+ Error error;
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ FreeBSDThread *thread = static_cast<FreeBSDThread*>(
+ m_thread_list.GetThreadAtIndex(0, false).get());
+ if (thread)
+ num = thread->NumSupportedHardwareWatchpoints();
+ else
+ error.SetErrorString("Process does not exist.");
+ return error;
+}
+
+Error
+ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after)
+{
+ Error error = GetWatchpointSupportInfo(num);
+ // Watchpoints trigger and halt the inferior after
+ // the corresponding instruction has been executed.
+ after = true;
+ return error;
+}
+
+uint32_t
+ProcessFreeBSD::UpdateThreadListIfNeeded()
+{
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ // Do not allow recursive updates.
+ return m_thread_list.GetSize(false);
+}
+
+#if 0
+bool
+ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());
+
+ bool has_updated = false;
+ // Update the process thread list with this new thread.
+ // FIXME: We should be using tid, not pid.
+ assert(m_monitor);
+ ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
+ if (!thread_sp) {
+ thread_sp.reset(CreateNewFreeBSDThread(*this, GetID()));
+ has_updated = true;
+ }
+
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
+ new_thread_list.AddThread(thread_sp);
+
+ return has_updated; // the list has been updated
+}
+#endif
+
+ByteOrder
+ProcessFreeBSD::GetByteOrder() const
+{
+ // FIXME: We should be able to extract this value directly. See comment in
+ // ProcessFreeBSD().
+ return m_byte_order;
+}
+
+size_t
+ProcessFreeBSD::PutSTDIN(const char *buf, size_t len, Error &error)
+{
+ ssize_t status;
+ if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)
+ {
+ error.SetErrorToErrno();
+ return 0;
+ }
+ return status;
+}
+
+//------------------------------------------------------------------------------
+// Utility functions.
+
+bool
+ProcessFreeBSD::HasExited()
+{
+ switch (GetPrivateState())
+ {
+ default:
+ break;
+
+ case eStateDetached:
+ case eStateExited:
+ return true;
+ }
+
+ return false;
+}
+
+bool
+ProcessFreeBSD::IsStopped()
+{
+ switch (GetPrivateState())
+ {
+ default:
+ break;
+
+ case eStateStopped:
+ case eStateCrashed:
+ case eStateSuspended:
+ return true;
+ }
+
+ return false;
+}
+
+bool
+ProcessFreeBSD::IsAThreadRunning()
+{
+ bool is_running = false;
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ uint32_t thread_count = m_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < thread_count; ++i)
+ {
+ FreeBSDThread *thread = static_cast<FreeBSDThread*>(
+ m_thread_list.GetThreadAtIndex(i, false).get());
+ StateType thread_state = thread->GetState();
+ if (thread_state == eStateRunning || thread_state == eStateStepping)
+ {
+ is_running = true;
+ break;
+ }
+ }
+ return is_running;
+}
+
+const DataBufferSP
+ProcessFreeBSD::GetAuxvData ()
+{
+ // If we're the local platform, we can ask the host for auxv data.
+ PlatformSP platform_sp = GetTarget().GetPlatform ();
+ if (platform_sp && platform_sp->IsHost ())
+ return lldb_private::Host::GetAuxvData(this);
+
+ // Somewhat unexpected - the process is not running locally or we don't have a platform.
+ assert (false && "no platform or not the host - how did we get here with ProcessFreeBSD?");
+ return DataBufferSP ();
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
index 2a5e245..44eefab 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
@@ -13,18 +13,20 @@
// C Includes
// C++ Includes
+#include <set>
#include <queue>
// Other libraries and framework includes
#include "lldb/Target/Process.h"
#include "lldb/Target/ThreadList.h"
#include "Plugins/Process/POSIX/ProcessMessage.h"
-#include "ProcessPOSIX.h"
+#include "ProcessFreeBSD.h"
class ProcessMonitor;
+class FreeBSDThread;
class ProcessFreeBSD :
- public ProcessPOSIX
+ public lldb_private::Process
{
public:
@@ -32,7 +34,7 @@ public:
// Static functions.
//------------------------------------------------------------------
static lldb::ProcessSP
- CreateInstance(lldb_private::Target& target,
+ CreateInstance(lldb::TargetSP target_sp,
lldb_private::Listener &listener,
const lldb_private::FileSpec *crash_file_path);
@@ -51,45 +53,188 @@ public:
//------------------------------------------------------------------
// Constructors and destructors
//------------------------------------------------------------------
- ProcessFreeBSD(lldb_private::Target& target,
- lldb_private::Listener &listener);
-
- virtual lldb_private::Error
- DoDetach(bool keep_stopped);
-
- virtual bool
- UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list);
+ ProcessFreeBSD(lldb::TargetSP target_sp,
+ lldb_private::Listener &listener,
+ lldb::UnixSignalsSP &unix_signals_sp);
- virtual lldb_private::Error
- DoResume();
+ ~ProcessFreeBSD();
virtual lldb_private::Error
- WillResume();
-
- virtual void
- SendMessage(const ProcessMessage &message);
+ WillResume() override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
virtual lldb_private::ConstString
- GetPluginName();
+ GetPluginName() override;
virtual uint32_t
- GetPluginVersion();
+ GetPluginVersion() override;
+
+public:
+ //------------------------------------------------------------------
+ // Process protocol.
+ //------------------------------------------------------------------
+ void
+ Finalize() override;
+
+ bool
+ CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override;
+
+ lldb_private::Error
+ WillLaunch(lldb_private::Module *module) override;
+
+ lldb_private::Error
+ DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override;
+
+ lldb_private::Error
+ DoLaunch (lldb_private::Module *exe_module,
+ lldb_private::ProcessLaunchInfo &launch_info) override;
+
+ void
+ DidLaunch() override;
+
+ lldb_private::Error
+ DoResume() override;
+
+ lldb_private::Error
+ DoHalt(bool &caused_stop) override;
+
+ lldb_private::Error
+ DoDetach(bool keep_stopped) override;
+
+ lldb_private::Error
+ DoSignal(int signal) override;
+
+ lldb_private::Error
+ DoDestroy() override;
+
+ void
+ DoDidExec() override;
+
+ void
+ RefreshStateAfterStop() override;
+
+ bool
+ IsAlive() override;
+
+ size_t
+ DoReadMemory(lldb::addr_t vm_addr,
+ void *buf,
+ size_t size,
+ lldb_private::Error &error) override;
+
+ size_t
+ DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
+ lldb_private::Error &error) override;
+
+ lldb::addr_t
+ DoAllocateMemory(size_t size, uint32_t permissions,
+ lldb_private::Error &error) override;
+
+ lldb_private::Error
+ DoDeallocateMemory(lldb::addr_t ptr) override;
+
+ virtual size_t
+ GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
+ lldb_private::Error
+ EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
+
+ lldb_private::Error
+ DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
+
+ lldb_private::Error
+ EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
+
+ lldb_private::Error
+ DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
+
+ lldb_private::Error
+ GetWatchpointSupportInfo(uint32_t &num) override;
+
+ lldb_private::Error
+ GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
+
+ virtual uint32_t
+ UpdateThreadListIfNeeded();
+
+ bool
+ UpdateThreadList(lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &new_thread_list) override;
+
+ virtual lldb::ByteOrder
+ GetByteOrder() const;
+
+ lldb::addr_t
+ GetImageInfoAddress() override;
+
+ size_t
+ PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override;
+
+ const lldb::DataBufferSP
+ GetAuxvData () override;
+
+ //--------------------------------------------------------------------------
+ // ProcessFreeBSD internal API.
+
+ /// Registers the given message with this process.
virtual void
- GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+ SendMessage(const ProcessMessage &message);
- virtual lldb_private::Error
- ExecutePluginCommand(lldb_private::Args &command,
- lldb_private::Stream *strm);
+ ProcessMonitor &
+ GetMonitor() { assert(m_monitor); return *m_monitor; }
+
+ lldb_private::FileSpec
+ GetFileSpec(const lldb_private::FileAction *file_action,
+ const lldb_private::FileSpec &default_file_spec,
+ const lldb_private::FileSpec &dbg_pts_file_spec);
+
+ /// Adds the thread to the list of threads for which we have received the initial stopping signal.
+ /// The \p stop_tid parameter indicates the thread which the stop happened for.
+ bool
+ AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
+
+ bool
+ WaitingForInitialStop(lldb::tid_t stop_tid);
- virtual lldb_private::Log *
- EnablePluginLogging(lldb_private::Stream *strm,
- lldb_private::Args &command);
+ virtual FreeBSDThread *
+ CreateNewFreeBSDThread(lldb_private::Process &process, lldb::tid_t tid);
protected:
+ /// Target byte order.
+ lldb::ByteOrder m_byte_order;
+
+ /// Process monitor;
+ ProcessMonitor *m_monitor;
+
+ /// The module we are executing.
+ lldb_private::Module *m_module;
+
+ /// Message queue notifying this instance of inferior process state changes.
+ lldb_private::Mutex m_message_mutex;
+ std::queue<ProcessMessage> m_message_queue;
+
+ /// Drive any exit events to completion.
+ bool m_exit_now;
+
+ /// Returns true if the process has exited.
+ bool HasExited();
+
+ /// Returns true if the process is stopped.
+ bool IsStopped();
+
+ /// Returns true if at least one running is currently running
+ bool IsAThreadRunning();
+
+ typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
+ MMapMap m_addr_to_mmap_size;
+
+ typedef std::set<lldb::tid_t> ThreadStopSet;
+ /// Every thread begins with a stop signal. This keeps track
+ /// of the threads for which we have received the stop signal.
+ ThreadStopSet m_seen_initial_stop;
+
friend class FreeBSDThread;
typedef std::vector<lldb::tid_t> tid_collection;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 427c66c..cd016fb 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -32,7 +32,7 @@
#include "lldb/Utility/PseudoTerminal.h"
#include "Plugins/Process/POSIX/CrashReason.h"
-#include "POSIXThread.h"
+#include "FreeBSDThread.h"
#include "ProcessFreeBSD.h"
#include "ProcessPOSIXLog.h"
#include "ProcessMonitor.h"
@@ -317,7 +317,7 @@ ReadRegOperation::Execute(ProcessMonitor *monitor)
else if (m_size == sizeof(uint64_t))
m_value = *(uint64_t *)(((caddr_t)&regs) + m_offset);
else
- memcpy(&m_value, (((caddr_t)&regs) + m_offset), m_size);
+ memcpy((void *)&m_value, (((caddr_t)&regs) + m_offset), m_size);
m_result = true;
}
}
@@ -393,7 +393,7 @@ ReadDebugRegOperation::Execute(ProcessMonitor *monitor)
if (m_size == sizeof(uintptr_t))
m_value = *(uintptr_t *)(((caddr_t)&regs) + m_offset);
else
- memcpy(&m_value, (((caddr_t)&regs) + m_offset), m_size);
+ memcpy((void *)&m_value, (((caddr_t)&regs) + m_offset), m_size);
m_result = true;
}
}
@@ -804,7 +804,7 @@ ProcessMonitor::AttachArgs::~AttachArgs()
/// launching or attaching to the inferior process, and then 2) servicing
/// operations such as register reads/writes, stepping, etc. See the comments
/// on the Operation class for more info as to why this is needed.
-ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
+ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process,
Module *module,
const char *argv[],
const char *envp[],
@@ -865,7 +865,7 @@ WAIT_AGAIN:
}
}
-ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
+ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process,
lldb::pid_t pid,
lldb_private::Error &error)
: m_process(static_cast<ProcessFreeBSD *>(process)),
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index 20ce582..07fa6b7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -49,7 +49,7 @@ public:
/// Launches an inferior process ready for debugging. Forms the
/// implementation of Process::DoLaunch.
- ProcessMonitor(ProcessPOSIX *process,
+ ProcessMonitor(ProcessFreeBSD *process,
lldb_private::Module *module,
char const *argv[],
char const *envp[],
@@ -60,7 +60,7 @@ public:
const lldb_private::ProcessLaunchInfo &launch_info,
lldb_private::Error &error);
- ProcessMonitor(ProcessPOSIX *process,
+ ProcessMonitor(ProcessFreeBSD *process,
lldb::pid_t pid,
lldb_private::Error &error);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp
deleted file mode 100644
index 360382e..0000000
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp
+++ /dev/null
@@ -1,939 +0,0 @@
-//===-- ProcessPOSIX.cpp ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <errno.h>
-
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
-#include "lldb/Host/FileSpec.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Target/DynamicLoader.h"
-#include "lldb/Target/Platform.h"
-#include "lldb/Target/Target.h"
-
-#include "ProcessPOSIX.h"
-#include "ProcessPOSIXLog.h"
-#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
-#include "POSIXThread.h"
-#include "ProcessMonitor.h"
-
-#include "lldb/Host/posix/Fcntl.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-//------------------------------------------------------------------------------
-// Constructors and destructors.
-
-ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener, UnixSignalsSP &unix_signals_sp)
- : Process(target, listener, unix_signals_sp),
- m_byte_order(lldb::endian::InlHostByteOrder()),
- m_monitor(NULL),
- m_module(NULL),
- m_message_mutex (Mutex::eMutexTypeRecursive),
- m_exit_now(false),
- m_seen_initial_stop()
-{
- // FIXME: Putting this code in the ctor and saving the byte order in a
- // member variable is a hack to avoid const qual issues in GetByteOrder.
- lldb::ModuleSP module = GetTarget().GetExecutableModule();
- if (module && module->GetObjectFile())
- m_byte_order = module->GetObjectFile()->GetByteOrder();
-}
-
-ProcessPOSIX::~ProcessPOSIX()
-{
- delete m_monitor;
-}
-
-//------------------------------------------------------------------------------
-// Process protocol.
-void
-ProcessPOSIX::Finalize()
-{
- Process::Finalize();
-
- if (m_monitor)
- m_monitor->StopMonitor();
-}
-
-bool
-ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name)
-{
- // For now we are just making sure the file exists for a given module
- ModuleSP exe_module_sp(target.GetExecutableModule());
- if (exe_module_sp.get())
- return exe_module_sp->GetFileSpec().Exists();
- // If there is no executable module, we return true since we might be preparing to attach.
- return true;
-}
-
-Error
-ProcessPOSIX::DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info)
-{
- Error error;
- assert(m_monitor == NULL);
-
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID());
-
- m_monitor = new ProcessMonitor(this, pid, error);
-
- if (!error.Success())
- return error;
-
- PlatformSP platform_sp (m_target.GetPlatform ());
- assert (platform_sp.get());
- if (!platform_sp)
- return error; // FIXME: Detatch?
-
- // Find out what we can about this process
- ProcessInstanceInfo process_info;
- platform_sp->GetProcessInfo (pid, process_info);
-
- // Resolve the executable module
- ModuleSP exe_module_sp;
- FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
- ModuleSpec exe_module_spec(process_info.GetExecutableFile(), m_target.GetArchitecture());
- error = platform_sp->ResolveExecutable(exe_module_spec,
- exe_module_sp,
- executable_search_paths.GetSize() ? &executable_search_paths : NULL);
- if (!error.Success())
- return error;
-
- // Fix the target architecture if necessary
- const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
- if (module_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(module_arch))
- m_target.SetArchitecture(module_arch);
-
- // Initialize the target module list
- m_target.SetExecutableModule (exe_module_sp, true);
-
- SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
-
- SetID(pid);
-
- return error;
-}
-
-Error
-ProcessPOSIX::WillLaunch(Module* module)
-{
- Error error;
- return error;
-}
-
-FileSpec
-ProcessPOSIX::GetFileSpec(const lldb_private::FileAction *file_action,
- const FileSpec &default_file_spec,
- const FileSpec &dbg_pts_file_spec)
-{
- FileSpec file_spec{};
-
- if (file_action && file_action->GetAction() == FileAction::eFileActionOpen)
- {
- file_spec = file_action->GetFileSpec();
- // By default the stdio paths passed in will be pseudo-terminal
- // (/dev/pts). If so, convert to using a different default path
- // instead to redirect I/O to the debugger console. This should
- // also handle user overrides to /dev/null or a different file.
- if (!file_spec || file_spec == dbg_pts_file_spec)
- file_spec = default_file_spec;
- }
- return file_spec;
-}
-
-Error
-ProcessPOSIX::DoLaunch (Module *module,
- ProcessLaunchInfo &launch_info)
-{
- Error error;
- assert(m_monitor == NULL);
-
- FileSpec working_dir = launch_info.GetWorkingDirectory();
- if (working_dir &&
- (!working_dir.ResolvePath() ||
- working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
- {
- error.SetErrorStringWithFormat("No such file or directory: %s",
- working_dir.GetCString());
- return error;
- }
-
- SetPrivateState(eStateLaunching);
-
- const lldb_private::FileAction *file_action;
-
- // Default of empty will mean to use existing open file descriptors
- FileSpec stdin_file_spec{};
- FileSpec stdout_file_spec{};
- FileSpec stderr_file_spec{};
-
- const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL,0), false};
-
- file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
- stdin_file_spec = GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec);
-
- file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
- stdout_file_spec = GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec);
-
- file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
- stderr_file_spec = GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec);
-
- m_monitor = new ProcessMonitor(this,
- module,
- launch_info.GetArguments().GetConstArgumentVector(),
- launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
- stdin_file_spec,
- stdout_file_spec,
- stderr_file_spec,
- working_dir,
- launch_info,
- error);
-
- m_module = module;
-
- if (!error.Success())
- return error;
-
- int terminal = m_monitor->GetTerminalFD();
- if (terminal >= 0) {
- // The reader thread will close the file descriptor when done, so we pass it a copy.
- int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0);
- if (stdio == -1) {
- error.SetErrorToErrno();
- return error;
- }
- SetSTDIOFileDescriptor(stdio);
- }
-
- SetID(m_monitor->GetPID());
- return error;
-}
-
-void
-ProcessPOSIX::DidLaunch()
-{
-}
-
-Error
-ProcessPOSIX::DoResume()
-{
- StateType state = GetPrivateState();
-
- assert(state == eStateStopped);
-
- SetPrivateState(eStateRunning);
-
- bool did_resume = false;
-
- Mutex::Locker lock(m_thread_list.GetMutex());
-
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- did_resume = thread->Resume() || did_resume;
- }
- assert(did_resume && "Process resume failed!");
-
- return Error();
-}
-
-addr_t
-ProcessPOSIX::GetImageInfoAddress()
-{
- Target *target = &GetTarget();
- ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress(target);
-
- if (addr.IsValid())
- return addr.GetLoadAddress(target);
- return LLDB_INVALID_ADDRESS;
-}
-
-Error
-ProcessPOSIX::DoHalt(bool &caused_stop)
-{
- Error error;
-
- if (IsStopped())
- {
- caused_stop = false;
- }
- else if (kill(GetID(), SIGSTOP))
- {
- caused_stop = false;
- error.SetErrorToErrno();
- }
- else
- {
- caused_stop = true;
- }
- return error;
-}
-
-Error
-ProcessPOSIX::DoSignal(int signal)
-{
- Error error;
-
- if (kill(GetID(), signal))
- error.SetErrorToErrno();
-
- return error;
-}
-
-Error
-ProcessPOSIX::DoDestroy()
-{
- Error error;
-
- if (!HasExited())
- {
- assert(m_monitor);
- m_exit_now = true;
- if (GetID() == LLDB_INVALID_PROCESS_ID)
- {
- error.SetErrorString("invalid process id");
- return error;
- }
- if (!m_monitor->Kill())
- {
- error.SetErrorToErrno();
- return error;
- }
-
- SetPrivateState(eStateExited);
- }
-
- return error;
-}
-
-void
-ProcessPOSIX::DoDidExec()
-{
- Target *target = &GetTarget();
- if (target)
- {
- PlatformSP platform_sp (target->GetPlatform());
- assert (platform_sp.get());
- if (platform_sp)
- {
- ProcessInstanceInfo process_info;
- platform_sp->GetProcessInfo(GetID(), process_info);
- ModuleSP exe_module_sp;
- ModuleSpec exe_module_spec(process_info.GetExecutableFile(), target->GetArchitecture());
- FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
- Error error = platform_sp->ResolveExecutable(exe_module_spec,
- exe_module_sp,
- executable_search_paths.GetSize() ? &executable_search_paths : NULL);
- if (!error.Success())
- return;
- target->SetExecutableModule(exe_module_sp, true);
- }
- }
-}
-
-void
-ProcessPOSIX::SendMessage(const ProcessMessage &message)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
-
- Mutex::Locker lock(m_message_mutex);
-
- Mutex::Locker thread_lock(m_thread_list.GetMutex());
-
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.FindThreadByID(message.GetTID(), false).get());
-
- switch (message.GetKind())
- {
- case ProcessMessage::eInvalidMessage:
- return;
-
- case ProcessMessage::eAttachMessage:
- SetPrivateState(eStateStopped);
- return;
-
- case ProcessMessage::eLimboMessage:
- assert(thread);
- thread->SetState(eStateStopped);
- if (message.GetTID() == GetID())
- {
- m_exit_status = message.GetExitStatus();
- if (m_exit_now)
- {
- SetPrivateState(eStateExited);
- m_monitor->Detach(GetID());
- }
- else
- {
- SetPrivateState(eStateStopped);
- }
- }
- else
- {
- SetPrivateState(eStateStopped);
- }
- break;
-
- case ProcessMessage::eExitMessage:
- if (thread != nullptr)
- thread->SetState(eStateExited);
- else
- {
- if (log)
- log->Warning ("ProcessPOSIX::%s eExitMessage for TID %" PRIu64 " failed to find a thread to mark as eStateExited, ignoring", __FUNCTION__, message.GetTID ());
- }
-
- // FIXME: I'm not sure we need to do this.
- if (message.GetTID() == GetID())
- {
- SetExitStatus(message.GetExitStatus(), NULL);
- }
- else if (!IsAThreadRunning())
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eSignalMessage:
- case ProcessMessage::eSignalDeliveredMessage:
- if (message.GetSignal() == SIGSTOP &&
- AddThreadForInitialStopIfNeeded(message.GetTID()))
- return;
- // Intentional fall-through
-
- case ProcessMessage::eBreakpointMessage:
- case ProcessMessage::eTraceMessage:
- case ProcessMessage::eWatchpointMessage:
- case ProcessMessage::eCrashMessage:
- assert(thread);
- thread->SetState(eStateStopped);
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eNewThreadMessage:
- {
- lldb::tid_t new_tid = message.GetChildTID();
- if (WaitingForInitialStop(new_tid))
- {
- m_monitor->WaitForInitialTIDStop(new_tid);
- }
- assert(thread);
- thread->SetState(eStateStopped);
- SetPrivateState(eStateStopped);
- break;
- }
-
- case ProcessMessage::eExecMessage:
- {
- assert(thread);
- thread->SetState(eStateStopped);
- SetPrivateState(eStateStopped);
- break;
- }
- }
-
-
- m_message_queue.push(message);
-}
-
-bool
-ProcessPOSIX::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid)
-{
- bool added_to_set = false;
- ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid);
- if (it == m_seen_initial_stop.end())
- {
- m_seen_initial_stop.insert(stop_tid);
- added_to_set = true;
- }
- return added_to_set;
-}
-
-bool
-ProcessPOSIX::WaitingForInitialStop(lldb::tid_t stop_tid)
-{
- return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
-}
-
-POSIXThread *
-ProcessPOSIX::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid)
-{
- return new POSIXThread(process, tid);
-}
-
-void
-ProcessPOSIX::RefreshStateAfterStop()
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());
-
- Mutex::Locker lock(m_message_mutex);
-
- // This method used to only handle one message. Changing it to loop allows
- // it to handle the case where we hit a breakpoint while handling a different
- // breakpoint.
- while (!m_message_queue.empty())
- {
- ProcessMessage &message = m_message_queue.front();
-
- // Resolve the thread this message corresponds to and pass it along.
- lldb::tid_t tid = message.GetTID();
- if (log)
- log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
-
- if (message.GetKind() == ProcessMessage::eNewThreadMessage)
- {
- if (log)
- log->Printf ("ProcessPOSIX::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID());
- lldb::tid_t child_tid = message.GetChildTID();
- ThreadSP thread_sp;
- thread_sp.reset(CreateNewPOSIXThread(*this, child_tid));
-
- Mutex::Locker lock(m_thread_list.GetMutex());
-
- m_thread_list.AddThread(thread_sp);
- }
-
- m_thread_list.RefreshStateAfterStop();
-
- POSIXThread *thread = static_cast<POSIXThread*>(
- GetThreadList().FindThreadByID(tid, false).get());
- if (thread)
- thread->Notify(message);
-
- if (message.GetKind() == ProcessMessage::eExitMessage)
- {
- // FIXME: We should tell the user about this, but the limbo message is probably better for that.
- if (log)
- log->Printf ("ProcessPOSIX::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);
-
- Mutex::Locker lock(m_thread_list.GetMutex());
-
- ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
- thread_sp.reset();
- m_seen_initial_stop.erase(tid);
- }
-
- m_message_queue.pop();
- }
-}
-
-bool
-ProcessPOSIX::IsAlive()
-{
- StateType state = GetPrivateState();
- return state != eStateDetached
- && state != eStateExited
- && state != eStateInvalid
- && state != eStateUnloaded;
-}
-
-size_t
-ProcessPOSIX::DoReadMemory(addr_t vm_addr,
- void *buf, size_t size, Error &error)
-{
- assert(m_monitor);
- return m_monitor->ReadMemory(vm_addr, buf, size, error);
-}
-
-size_t
-ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
- Error &error)
-{
- assert(m_monitor);
- return m_monitor->WriteMemory(vm_addr, buf, size, error);
-}
-
-addr_t
-ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions,
- Error &error)
-{
- addr_t allocated_addr = LLDB_INVALID_ADDRESS;
-
- unsigned prot = 0;
- if (permissions & lldb::ePermissionsReadable)
- prot |= eMmapProtRead;
- if (permissions & lldb::ePermissionsWritable)
- prot |= eMmapProtWrite;
- if (permissions & lldb::ePermissionsExecutable)
- prot |= eMmapProtExec;
-
- if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
- eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
- m_addr_to_mmap_size[allocated_addr] = size;
- error.Clear();
- } else {
- allocated_addr = LLDB_INVALID_ADDRESS;
- error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
- }
-
- return allocated_addr;
-}
-
-Error
-ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr)
-{
- Error error;
- MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
- if (pos != m_addr_to_mmap_size.end() &&
- InferiorCallMunmap(this, addr, pos->second))
- m_addr_to_mmap_size.erase (pos);
- else
- error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
-
- return error;
-}
-
-size_t
-ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
-{
- static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xD4 };
- static const uint8_t g_i386_opcode[] = { 0xCC };
-
- ArchSpec arch = GetTarget().GetArchitecture();
- const uint8_t *opcode = NULL;
- size_t opcode_size = 0;
-
- switch (arch.GetMachine())
- {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case llvm::Triple::arm:
- {
- // The ARM reference recommends the use of 0xe7fddefe and 0xdefe
- // but the linux kernel does otherwise.
- static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 };
- static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };
-
- lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
- AddressClass addr_class = eAddressClassUnknown;
-
- if (bp_loc_sp)
- addr_class = bp_loc_sp->GetAddress ().GetAddressClass ();
-
- if (addr_class == eAddressClassCodeAlternateISA
- || (addr_class == eAddressClassUnknown
- && bp_loc_sp->GetAddress().GetOffset() & 1))
- {
- opcode = g_thumb_breakpoint_opcode;
- opcode_size = sizeof(g_thumb_breakpoint_opcode);
- }
- else
- {
- opcode = g_arm_breakpoint_opcode;
- opcode_size = sizeof(g_arm_breakpoint_opcode);
- }
- }
- break;
- case llvm::Triple::aarch64:
- opcode = g_aarch64_opcode;
- opcode_size = sizeof(g_aarch64_opcode);
- break;
-
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- opcode = g_i386_opcode;
- opcode_size = sizeof(g_i386_opcode);
- break;
- }
-
- bp_site->SetTrapOpcode(opcode, opcode_size);
- return opcode_size;
-}
-
-Error
-ProcessPOSIX::EnableBreakpointSite(BreakpointSite *bp_site)
-{
- return EnableSoftwareBreakpoint(bp_site);
-}
-
-Error
-ProcessPOSIX::DisableBreakpointSite(BreakpointSite *bp_site)
-{
- return DisableSoftwareBreakpoint(bp_site);
-}
-
-Error
-ProcessPOSIX::EnableWatchpoint(Watchpoint *wp, bool notify)
-{
- Error error;
- if (wp)
- {
- user_id_t watchID = wp->GetID();
- addr_t addr = wp->GetLoadAddress();
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64 ")",
- watchID);
- if (wp->IsEnabled())
- {
- if (log)
- log->Printf("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64
- ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
- watchID, (uint64_t)addr);
- return error;
- }
-
- // Try to find a vacant watchpoint slot in the inferiors' main thread
- uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
- Mutex::Locker lock(m_thread_list.GetMutex());
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(0, false).get());
-
- if (thread)
- wp_hw_index = thread->FindVacantWatchpointIndex();
-
- if (wp_hw_index == LLDB_INVALID_INDEX32)
- {
- error.SetErrorString("Setting hardware watchpoint failed.");
- }
- else
- {
- wp->SetHardwareIndex(wp_hw_index);
- bool wp_enabled = true;
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- if (thread)
- wp_enabled &= thread->EnableHardwareWatchpoint(wp);
- else
- wp_enabled = false;
- }
- if (wp_enabled)
- {
- wp->SetEnabled(true, notify);
- return error;
- }
- else
- {
- // Watchpoint enabling failed on at least one
- // of the threads so roll back all of them
- DisableWatchpoint(wp, false);
- error.SetErrorString("Setting hardware watchpoint failed");
- }
- }
- }
- else
- error.SetErrorString("Watchpoint argument was NULL.");
- return error;
-}
-
-Error
-ProcessPOSIX::DisableWatchpoint(Watchpoint *wp, bool notify)
-{
- Error error;
- if (wp)
- {
- user_id_t watchID = wp->GetID();
- addr_t addr = wp->GetLoadAddress();
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- if (log)
- log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64 ")",
- watchID);
- if (!wp->IsEnabled())
- {
- if (log)
- log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64
- ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
- watchID, (uint64_t)addr);
- // This is needed (for now) to keep watchpoints disabled correctly
- wp->SetEnabled(false, notify);
- return error;
- }
-
- if (wp->IsHardware())
- {
- bool wp_disabled = true;
- Mutex::Locker lock(m_thread_list.GetMutex());
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- if (thread)
- wp_disabled &= thread->DisableHardwareWatchpoint(wp);
- else
- wp_disabled = false;
- }
- if (wp_disabled)
- {
- wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
- wp->SetEnabled(false, notify);
- return error;
- }
- else
- error.SetErrorString("Disabling hardware watchpoint failed");
- }
- }
- else
- error.SetErrorString("Watchpoint argument was NULL.");
- return error;
-}
-
-Error
-ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num)
-{
- Error error;
- Mutex::Locker lock(m_thread_list.GetMutex());
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(0, false).get());
- if (thread)
- num = thread->NumSupportedHardwareWatchpoints();
- else
- error.SetErrorString("Process does not exist.");
- return error;
-}
-
-Error
-ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num, bool &after)
-{
- Error error = GetWatchpointSupportInfo(num);
- // Watchpoints trigger and halt the inferior after
- // the corresponding instruction has been executed.
- after = true;
- return error;
-}
-
-uint32_t
-ProcessPOSIX::UpdateThreadListIfNeeded()
-{
- Mutex::Locker lock(m_thread_list.GetMutex());
- // Do not allow recursive updates.
- return m_thread_list.GetSize(false);
-}
-
-bool
-ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());
-
- bool has_updated = false;
- // Update the process thread list with this new thread.
- // FIXME: We should be using tid, not pid.
- assert(m_monitor);
- ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
- if (!thread_sp) {
- thread_sp.reset(CreateNewPOSIXThread(*this, GetID()));
- has_updated = true;
- }
-
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
- new_thread_list.AddThread(thread_sp);
-
- return has_updated; // the list has been updated
-}
-
-ByteOrder
-ProcessPOSIX::GetByteOrder() const
-{
- // FIXME: We should be able to extract this value directly. See comment in
- // ProcessPOSIX().
- return m_byte_order;
-}
-
-size_t
-ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error)
-{
- ssize_t status;
- if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)
- {
- error.SetErrorToErrno();
- return 0;
- }
- return status;
-}
-
-//------------------------------------------------------------------------------
-// Utility functions.
-
-bool
-ProcessPOSIX::HasExited()
-{
- switch (GetPrivateState())
- {
- default:
- break;
-
- case eStateDetached:
- case eStateExited:
- return true;
- }
-
- return false;
-}
-
-bool
-ProcessPOSIX::IsStopped()
-{
- switch (GetPrivateState())
- {
- default:
- break;
-
- case eStateStopped:
- case eStateCrashed:
- case eStateSuspended:
- return true;
- }
-
- return false;
-}
-
-bool
-ProcessPOSIX::IsAThreadRunning()
-{
- bool is_running = false;
- Mutex::Locker lock(m_thread_list.GetMutex());
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- StateType thread_state = thread->GetState();
- if (thread_state == eStateRunning || thread_state == eStateStepping)
- {
- is_running = true;
- break;
- }
- }
- return is_running;
-}
-
-const DataBufferSP
-ProcessPOSIX::GetAuxvData ()
-{
- // If we're the local platform, we can ask the host for auxv data.
- PlatformSP platform_sp = m_target.GetPlatform ();
- if (platform_sp && platform_sp->IsHost ())
- return lldb_private::Host::GetAuxvData(this);
-
- // Somewhat unexpected - the process is not running locally or we don't have a platform.
- assert (false && "no platform or not the host - how did we get here with ProcessPOSIX?");
- return DataBufferSP ();
-}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessPOSIX.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessPOSIX.h
deleted file mode 100644
index ee44e92..0000000
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessPOSIX.h
+++ /dev/null
@@ -1,205 +0,0 @@
-//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ProcessPOSIX_H_
-#define liblldb_ProcessPOSIX_H_
-
-// C Includes
-
-// C++ Includes
-#include <queue>
-#include <set>
-
-// Other libraries and framework includes
-#include "lldb/Target/Process.h"
-#include "Plugins/Process/POSIX/ProcessMessage.h"
-
-class ProcessMonitor;
-class POSIXThread;
-
-class ProcessPOSIX :
- public lldb_private::Process
-{
-public:
-
- //------------------------------------------------------------------
- // Constructors and destructors
- //------------------------------------------------------------------
- ProcessPOSIX(lldb_private::Target& target,
- lldb_private::Listener &listener,
- lldb::UnixSignalsSP &unix_signals_sp);
-
- virtual
- ~ProcessPOSIX();
-
- //------------------------------------------------------------------
- // Process protocol.
- //------------------------------------------------------------------
- void
- Finalize() override;
-
- bool
- CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override;
-
- lldb_private::Error
- WillLaunch(lldb_private::Module *module) override;
-
- lldb_private::Error
- DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override;
-
- lldb_private::Error
- DoLaunch (lldb_private::Module *exe_module,
- lldb_private::ProcessLaunchInfo &launch_info) override;
-
- void
- DidLaunch() override;
-
- lldb_private::Error
- DoResume() override;
-
- lldb_private::Error
- DoHalt(bool &caused_stop) override;
-
- lldb_private::Error
- DoDetach(bool keep_stopped) override = 0;
-
- lldb_private::Error
- DoSignal(int signal) override;
-
- lldb_private::Error
- DoDestroy() override;
-
- void
- DoDidExec() override;
-
- void
- RefreshStateAfterStop() override;
-
- bool
- IsAlive() override;
-
- size_t
- DoReadMemory(lldb::addr_t vm_addr,
- void *buf,
- size_t size,
- lldb_private::Error &error) override;
-
- size_t
- DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
- lldb_private::Error &error) override;
-
- lldb::addr_t
- DoAllocateMemory(size_t size, uint32_t permissions,
- lldb_private::Error &error) override;
-
- lldb_private::Error
- DoDeallocateMemory(lldb::addr_t ptr) override;
-
- virtual size_t
- GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
-
- lldb_private::Error
- EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
-
- lldb_private::Error
- DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
-
- lldb_private::Error
- EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
-
- lldb_private::Error
- DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
-
- lldb_private::Error
- GetWatchpointSupportInfo(uint32_t &num) override;
-
- lldb_private::Error
- GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
-
- virtual uint32_t
- UpdateThreadListIfNeeded();
-
- bool
- UpdateThreadList(lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &new_thread_list) override = 0;
-
- virtual lldb::ByteOrder
- GetByteOrder() const;
-
- lldb::addr_t
- GetImageInfoAddress() override;
-
- size_t
- PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override;
-
- const lldb::DataBufferSP
- GetAuxvData () override;
-
- //--------------------------------------------------------------------------
- // ProcessPOSIX internal API.
-
- /// Registers the given message with this process.
- virtual void
- SendMessage(const ProcessMessage &message);
-
- ProcessMonitor &
- GetMonitor() { assert(m_monitor); return *m_monitor; }
-
- lldb_private::FileSpec
- GetFileSpec(const lldb_private::FileAction *file_action,
- const lldb_private::FileSpec &default_file_spec,
- const lldb_private::FileSpec &dbg_pts_file_spec);
-
- /// Adds the thread to the list of threads for which we have received the initial stopping signal.
- /// The \p stop_tid parameter indicates the thread which the stop happened for.
- bool
- AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
-
- bool
- WaitingForInitialStop(lldb::tid_t stop_tid);
-
- virtual POSIXThread *
- CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid);
-
-protected:
- /// Target byte order.
- lldb::ByteOrder m_byte_order;
-
- /// Process monitor;
- ProcessMonitor *m_monitor;
-
- /// The module we are executing.
- lldb_private::Module *m_module;
-
- /// Message queue notifying this instance of inferior process state changes.
- lldb_private::Mutex m_message_mutex;
- std::queue<ProcessMessage> m_message_queue;
-
- /// Drive any exit events to completion.
- bool m_exit_now;
-
- /// Returns true if the process has exited.
- bool HasExited();
-
- /// Returns true if the process is stopped.
- bool IsStopped();
-
- /// Returns true if at least one running is currently running
- bool IsAThreadRunning();
-
- typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
- MMapMap m_addr_to_mmap_size;
-
- typedef std::set<lldb::tid_t> ThreadStopSet;
- /// Every thread begins with a stop signal. This keeps track
- /// of the threads for which we have received the stop signal.
- ThreadStopSet m_seen_initial_stop;
-};
-
-#endif // liblldb_MacOSXProcess_H_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
index 6ddd9cf..6ddd9cf 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
index f6d029e..d557071 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
@@ -12,7 +12,7 @@
#include "lldb/Target/Thread.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
-#include "ProcessPOSIX.h"
+#include "ProcessFreeBSD.h"
#include "RegisterContextPOSIXProcessMonitor_arm.h"
#include "ProcessMonitor.h"
@@ -32,7 +32,7 @@ ProcessMonitor &
RegisterContextPOSIXProcessMonitor_arm::GetMonitor()
{
ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());
return process->GetMonitor();
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h
index 12a43c7..3787502 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h
@@ -10,6 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_arm_H_
+#include "RegisterContextPOSIX.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
class RegisterContextPOSIXProcessMonitor_arm:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
index 44cb603..a1a0cab 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
@@ -12,7 +12,7 @@
#include "lldb/Target/Thread.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
-#include "ProcessPOSIX.h"
+#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_arm64.h"
@@ -32,7 +32,7 @@ ProcessMonitor &
RegisterContextPOSIXProcessMonitor_arm64::GetMonitor()
{
lldb::ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());
return process->GetMonitor();
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h
index eb24d48..729385c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h
@@ -10,6 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
+#include "RegisterContextPOSIX.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
class RegisterContextPOSIXProcessMonitor_arm64:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
index 893a0f2..eeada4b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
@@ -12,7 +12,7 @@
#include "lldb/Target/Thread.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
-#include "ProcessPOSIX.h"
+#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_mips64.h"
@@ -32,7 +32,7 @@ ProcessMonitor &
RegisterContextPOSIXProcessMonitor_mips64::GetMonitor()
{
ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());
return process->GetMonitor();
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h
index 79e4468..e61621b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h
@@ -10,6 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
+#include "RegisterContextPOSIX.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
class RegisterContextPOSIXProcessMonitor_mips64:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
index 1e4a402..170d839 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
@@ -12,7 +12,7 @@
#include "lldb/Target/Thread.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
-#include "ProcessPOSIX.h"
+#include "ProcessFreeBSD.h"
#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
#include "ProcessMonitor.h"
@@ -32,7 +32,7 @@ ProcessMonitor &
RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor()
{
ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());
return process->GetMonitor();
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h
index 5c686df..ff1d0f3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h
@@ -10,6 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
+#include "RegisterContextPOSIX.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
class RegisterContextPOSIXProcessMonitor_powerpc:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
index 9245441..31b9e7a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
@@ -11,7 +11,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "Plugins/Process/FreeBSD/ProcessPOSIX.h"
+#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h"
#include "RegisterContextPOSIXProcessMonitor_x86.h"
#include "Plugins/Process/FreeBSD/ProcessMonitor.h"
@@ -58,13 +58,16 @@ RegisterContextPOSIXProcessMonitor_x86_64::RegisterContextPOSIXProcessMonitor_x8
lldb_private::RegisterInfoInterface *register_info)
: RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info)
{
+ // Store byte offset of fctrl (i.e. first register of FPR) wrt 'UserArea'
+ const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
+ m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
}
ProcessMonitor &
RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor()
{
ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());
return process->GetMonitor();
}
@@ -254,10 +257,20 @@ RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const RegisterInfo *reg_
}
// Get pointer to m_fpr.xstate.fxsave variable and set the data from it.
- assert (reg_info->byte_offset < sizeof(m_fpr));
- uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
+ // Byte offsets of all registers are calculated wrt 'UserArea' structure.
+ // However, ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)}
+ // and stores them in 'm_fpr' (of type FPR structure). To extract values of fpu
+ // registers, m_fpr should be read at byte offsets calculated wrt to FPR structure.
+
+ // Since, FPR structure is also one of the member of UserArea structure.
+ // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea)
+ assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
+ uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
switch (reg_info->byte_size)
{
+ case 1:
+ value.SetUInt8(*(uint8_t *)src);
+ return true;
case 2:
value.SetUInt16(*(uint16_t *)src);
return true;
@@ -308,10 +321,20 @@ RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const RegisterInfo *reg
else
{
// Get pointer to m_fpr.xstate.fxsave variable and set the data to it.
- assert (reg_info->byte_offset < sizeof(m_fpr));
- uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset;
+ // Byte offsets of all registers are calculated wrt 'UserArea' structure.
+ // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only fpu
+ // registers using ptrace(PT_SETFPREGS,..) API. Hence fpu registers should
+ // be written in m_fpr at byte offsets calculated wrt FPR structure.
+
+ // Since, FPR structure is also one of the member of UserArea structure.
+ // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea)
+ assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
+ uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
switch (reg_info->byte_size)
{
+ case 1:
+ *(uint8_t *)dst = value.GetAsUInt8();
+ break;
case 2:
*(uint16_t *)dst = value.GetAsUInt16();
break;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h
index 2afb195..f55d917 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h
@@ -10,6 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
+#include "RegisterContextPOSIX.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
class RegisterContextPOSIXProcessMonitor_x86_64:
@@ -90,6 +91,7 @@ protected:
private:
ProcessMonitor &
GetMonitor();
+ uint32_t m_fctrl_offset_in_userarea; // Offset of 'fctrl' in 'UserArea' Structure
};
#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/POSIX/CrashReason.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
index 6de13f4..44409a4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
@@ -28,11 +28,12 @@ GetCrashReasonForSIGSEGV(const siginfo_t& info)
switch (info.si_code)
{
+#ifdef SI_KERNEL
case SI_KERNEL:
- // Linux will occasionally send spurious SI_KERNEL codes.
- // (this is poorly documented in sigaction)
+ // Some platforms will occasionally send nonstandard spurious SI_KERNEL codes.
// One way to get this is via unaligned SIMD loads.
return CrashReason::eInvalidAddress; // for lack of anything better
+#endif
case SEGV_MAPERR:
return CrashReason::eInvalidAddress;
case SEGV_ACCERR:
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 4eff442..26de4b5 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -99,7 +99,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, con
return 0;
}
- // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2,
+ // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'ehframe' : 2,
// 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
RegisterInfo reg_info;
std::vector<uint32_t> value_regs;
@@ -325,8 +325,12 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, con
// Fill in the register numbers
reg_info.kinds[lldb::eRegisterKindLLDB] = i;
- reg_info.kinds[lldb::eRegisterKindGDB] = i;
- reg_info_dict->GetValueForKeyAsInteger("gcc", reg_info.kinds[lldb::eRegisterKindGCC], LLDB_INVALID_REGNUM);
+ reg_info.kinds[lldb::eRegisterKindProcessPlugin] = i;
+ uint32_t eh_frame_regno = LLDB_INVALID_REGNUM;
+ reg_info_dict->GetValueForKeyAsInteger("gcc", eh_frame_regno, LLDB_INVALID_REGNUM);
+ if (eh_frame_regno == LLDB_INVALID_REGNUM)
+ reg_info_dict->GetValueForKeyAsInteger("ehframe", eh_frame_regno, LLDB_INVALID_REGNUM);
+ reg_info.kinds[lldb::eRegisterKindEHFrame] = eh_frame_regno;
reg_info_dict->GetValueForKeyAsInteger("dwarf", reg_info.kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM);
std::string generic_str;
if (reg_info_dict->GetValueForKeyAsString("generic", generic_str))
@@ -703,12 +707,12 @@ DynamicRegisterInfo::Dump () const
m_regs[i].byte_offset,
m_regs[i].encoding,
FormatManager::GetFormatAsCString (m_regs[i].format));
- if (m_regs[i].kinds[eRegisterKindGDB] != LLDB_INVALID_REGNUM)
- s.Printf(", gdb = %3u", m_regs[i].kinds[eRegisterKindGDB]);
+ if (m_regs[i].kinds[eRegisterKindProcessPlugin] != LLDB_INVALID_REGNUM)
+ s.Printf(", process plugin = %3u", m_regs[i].kinds[eRegisterKindProcessPlugin]);
if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
s.Printf(", dwarf = %3u", m_regs[i].kinds[eRegisterKindDWARF]);
- if (m_regs[i].kinds[eRegisterKindGCC] != LLDB_INVALID_REGNUM)
- s.Printf(", gcc = %3u", m_regs[i].kinds[eRegisterKindGCC]);
+ if (m_regs[i].kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
+ s.Printf(", ehframe = %3u", m_regs[i].kinds[eRegisterKindEHFrame]);
if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
s.Printf(", generic = %3u", m_regs[i].kinds[eRegisterKindGeneric]);
if (m_regs[i].alt_name)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp
index c143d36..e575e2c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/FreeBSDSignals.cpp
@@ -26,70 +26,70 @@ FreeBSDSignals::Reset()
{
UnixSignals::Reset();
- // SIGNO NAME SHORT NAME SUPPRESS STOP NOTIFY DESCRIPTION
- // ====== ============ ========== ======== ====== ====== ===================================================
- AddSignal (32, "SIGTHR", "THR", false, true , true , "thread interrupt");
- AddSignal (33, "SIGLIBRT", "LIBRT", false, true , true , "reserved by real-time library");
- AddSignal (65, "SIGRTMIN", "RTMIN", false, true , true , "real time signal 0");
- AddSignal (66, "SIGRTMIN+1", "RTMIN+1", false, true , true , "real time signal 1");
- AddSignal (67, "SIGRTMIN+2", "RTMIN+2", false, true , true , "real time signal 2");
- AddSignal (68, "SIGRTMIN+3", "RTMIN+3", false, true , true , "real time signal 3");
- AddSignal (69, "SIGRTMIN+4", "RTMIN+4", false, true , true , "real time signal 4");
- AddSignal (70, "SIGRTMIN+5", "RTMIN+5", false, true , true , "real time signal 5");
- AddSignal (71, "SIGRTMIN+6", "RTMIN+6", false, true , true , "real time signal 6");
- AddSignal (72, "SIGRTMIN+7", "RTMIN+7", false, true , true , "real time signal 7");
- AddSignal (73, "SIGRTMIN+8", "RTMIN+8", false, true , true , "real time signal 8");
- AddSignal (74, "SIGRTMIN+9", "RTMIN+9", false, true , true , "real time signal 9");
- AddSignal (75, "SIGRTMIN+10", "RTMIN+10", false, true , true , "real time signal 10");
- AddSignal (76, "SIGRTMIN+11", "RTMIN+11", false, true , true , "real time signal 11");
- AddSignal (77, "SIGRTMIN+12", "RTMIN+12", false, true , true , "real time signal 12");
- AddSignal (78, "SIGRTMIN+13", "RTMIN+13", false, true , true , "real time signal 13");
- AddSignal (79, "SIGRTMIN+14", "RTMIN+14", false, true , true , "real time signal 14");
- AddSignal (80, "SIGRTMIN+15", "RTMIN+15", false, true , true , "real time signal 15");
- AddSignal (81, "SIGRTMIN+16", "RTMIN+16", false, true , true , "real time signal 16");
- AddSignal (82, "SIGRTMIN+17", "RTMIN+17", false, true , true , "real time signal 17");
- AddSignal (83, "SIGRTMIN+18", "RTMIN+18", false, true , true , "real time signal 18");
- AddSignal (84, "SIGRTMIN+19", "RTMIN+19", false, true , true , "real time signal 19");
- AddSignal (85, "SIGRTMIN+20", "RTMIN+20", false, true , true , "real time signal 20");
- AddSignal (86, "SIGRTMIN+21", "RTMIN+21", false, true , true , "real time signal 21");
- AddSignal (87, "SIGRTMIN+22", "RTMIN+22", false, true , true , "real time signal 22");
- AddSignal (88, "SIGRTMIN+23", "RTMIN+23", false, true , true , "real time signal 23");
- AddSignal (89, "SIGRTMIN+24", "RTMIN+24", false, true , true , "real time signal 24");
- AddSignal (90, "SIGRTMIN+25", "RTMIN+25", false, true , true , "real time signal 25");
- AddSignal (91, "SIGRTMIN+26", "RTMIN+26", false, true , true , "real time signal 26");
- AddSignal (92, "SIGRTMIN+27", "RTMIN+27", false, true , true , "real time signal 27");
- AddSignal (93, "SIGRTMIN+28", "RTMIN+28", false, true , true , "real time signal 28");
- AddSignal (94, "SIGRTMIN+29", "RTMIN+29", false, true , true , "real time signal 29");
- AddSignal (95, "SIGRTMIN+30", "RTMIN+30", false, true , true , "real time signal 30");
- AddSignal (96, "SIGRTMAX-30", "RTMAX-30", false, true , true , "real time signal 31");
- AddSignal (97, "SIGRTMAX-29", "RTMAX-29", false, true , true , "real time signal 32");
- AddSignal (98, "SIGRTMAX-28", "RTMAX-28", false, true , true , "real time signal 33");
- AddSignal (99, "SIGRTMAX-27", "RTMAX-27", false, true , true , "real time signal 34");
- AddSignal (100, "SIGRTMAX-26", "RTMAX-26", false, true , true , "real time signal 35");
- AddSignal (101, "SIGRTMAX-25", "RTMAX-25", false, true , true , "real time signal 36");
- AddSignal (102, "SIGRTMAX-24", "RTMAX-24", false, true , true , "real time signal 37");
- AddSignal (103, "SIGRTMAX-23", "RTMAX-23", false, true , true , "real time signal 38");
- AddSignal (104, "SIGRTMAX-22", "RTMAX-22", false, true , true , "real time signal 39");
- AddSignal (105, "SIGRTMAX-21", "RTMAX-21", false, true , true , "real time signal 40");
- AddSignal (106, "SIGRTMAX-20", "RTMAX-20", false, true , true , "real time signal 41");
- AddSignal (107, "SIGRTMAX-19", "RTMAX-19", false, true , true , "real time signal 42");
- AddSignal (108, "SIGRTMAX-18", "RTMAX-18", false, true , true , "real time signal 43");
- AddSignal (109, "SIGRTMAX-17", "RTMAX-17", false, true , true , "real time signal 44");
- AddSignal (110, "SIGRTMAX-16", "RTMAX-16", false, true , true , "real time signal 45");
- AddSignal (111, "SIGRTMAX-15", "RTMAX-15", false, true , true , "real time signal 46");
- AddSignal (112, "SIGRTMAX-14", "RTMAX-14", false, true , true , "real time signal 47");
- AddSignal (113, "SIGRTMAX-13", "RTMAX-13", false, true , true , "real time signal 48");
- AddSignal (114, "SIGRTMAX-12", "RTMAX-12", false, true , true , "real time signal 49");
- AddSignal (115, "SIGRTMAX-11", "RTMAX-11", false, true , true , "real time signal 50");
- AddSignal (116, "SIGRTMAX-10", "RTMAX-10", false, true , true , "real time signal 51");
- AddSignal (117, "SIGRTMAX-9", "RTMAX-9", false, true , true , "real time signal 52");
- AddSignal (118, "SIGRTMAX-8", "RTMAX-8", false, true , true , "real time signal 53");
- AddSignal (119, "SIGRTMAX-7", "RTMAX-7", false, true , true , "real time signal 54");
- AddSignal (120, "SIGRTMAX-6", "RTMAX-6", false, true , true , "real time signal 55");
- AddSignal (121, "SIGRTMAX-5", "RTMAX-5", false, true , true , "real time signal 56");
- AddSignal (122, "SIGRTMAX-4", "RTMAX-4", false, true , true , "real time signal 57");
- AddSignal (123, "SIGRTMAX-3", "RTMAX-3", false, true , true , "real time signal 58");
- AddSignal (124, "SIGRTMAX-2", "RTMAX-2", false, true , true , "real time signal 59");
- AddSignal (125, "SIGRTMAX-1", "RTMAX-1", false, true , true , "real time signal 60");
- AddSignal (126, "SIGRTMAX", "RTMAX", false, true , true , "real time signal 61");
+ // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION
+ // ====== ============ ======== ====== ====== ===================================================
+ AddSignal (32, "SIGTHR", false, false, false, "thread interrupt");
+ AddSignal (33, "SIGLIBRT", false, false, false, "reserved by real-time library");
+ AddSignal (65, "SIGRTMIN", false, false, false, "real time signal 0");
+ AddSignal (66, "SIGRTMIN+1", false, false, false, "real time signal 1");
+ AddSignal (67, "SIGRTMIN+2", false, false, false, "real time signal 2");
+ AddSignal (68, "SIGRTMIN+3", false, false, false, "real time signal 3");
+ AddSignal (69, "SIGRTMIN+4", false, false, false, "real time signal 4");
+ AddSignal (70, "SIGRTMIN+5", false, false, false, "real time signal 5");
+ AddSignal (71, "SIGRTMIN+6", false, false, false, "real time signal 6");
+ AddSignal (72, "SIGRTMIN+7", false, false, false, "real time signal 7");
+ AddSignal (73, "SIGRTMIN+8", false, false, false, "real time signal 8");
+ AddSignal (74, "SIGRTMIN+9", false, false, false, "real time signal 9");
+ AddSignal (75, "SIGRTMIN+10", false, false, false, "real time signal 10");
+ AddSignal (76, "SIGRTMIN+11", false, false, false, "real time signal 11");
+ AddSignal (77, "SIGRTMIN+12", false, false, false, "real time signal 12");
+ AddSignal (78, "SIGRTMIN+13", false, false, false, "real time signal 13");
+ AddSignal (79, "SIGRTMIN+14", false, false, false, "real time signal 14");
+ AddSignal (80, "SIGRTMIN+15", false, false, false, "real time signal 15");
+ AddSignal (81, "SIGRTMIN+16", false, false, false, "real time signal 16");
+ AddSignal (82, "SIGRTMIN+17", false, false, false, "real time signal 17");
+ AddSignal (83, "SIGRTMIN+18", false, false, false, "real time signal 18");
+ AddSignal (84, "SIGRTMIN+19", false, false, false, "real time signal 19");
+ AddSignal (85, "SIGRTMIN+20", false, false, false, "real time signal 20");
+ AddSignal (86, "SIGRTMIN+21", false, false, false, "real time signal 21");
+ AddSignal (87, "SIGRTMIN+22", false, false, false, "real time signal 22");
+ AddSignal (88, "SIGRTMIN+23", false, false, false, "real time signal 23");
+ AddSignal (89, "SIGRTMIN+24", false, false, false, "real time signal 24");
+ AddSignal (90, "SIGRTMIN+25", false, false, false, "real time signal 25");
+ AddSignal (91, "SIGRTMIN+26", false, false, false, "real time signal 26");
+ AddSignal (92, "SIGRTMIN+27", false, false, false, "real time signal 27");
+ AddSignal (93, "SIGRTMIN+28", false, false, false, "real time signal 28");
+ AddSignal (94, "SIGRTMIN+29", false, false, false, "real time signal 29");
+ AddSignal (95, "SIGRTMIN+30", false, false, false, "real time signal 30");
+ AddSignal (96, "SIGRTMAX-30", false, false, false, "real time signal 31");
+ AddSignal (97, "SIGRTMAX-29", false, false, false, "real time signal 32");
+ AddSignal (98, "SIGRTMAX-28", false, false, false, "real time signal 33");
+ AddSignal (99, "SIGRTMAX-27", false, false, false, "real time signal 34");
+ AddSignal (100, "SIGRTMAX-26", false, false, false, "real time signal 35");
+ AddSignal (101, "SIGRTMAX-25", false, false, false, "real time signal 36");
+ AddSignal (102, "SIGRTMAX-24", false, false, false, "real time signal 37");
+ AddSignal (103, "SIGRTMAX-23", false, false, false, "real time signal 38");
+ AddSignal (104, "SIGRTMAX-22", false, false, false, "real time signal 39");
+ AddSignal (105, "SIGRTMAX-21", false, false, false, "real time signal 40");
+ AddSignal (106, "SIGRTMAX-20", false, false, false, "real time signal 41");
+ AddSignal (107, "SIGRTMAX-19", false, false, false, "real time signal 42");
+ AddSignal (108, "SIGRTMAX-18", false, false, false, "real time signal 43");
+ AddSignal (109, "SIGRTMAX-17", false, false, false, "real time signal 44");
+ AddSignal (110, "SIGRTMAX-16", false, false, false, "real time signal 45");
+ AddSignal (111, "SIGRTMAX-15", false, false, false, "real time signal 46");
+ AddSignal (112, "SIGRTMAX-14", false, false, false, "real time signal 47");
+ AddSignal (113, "SIGRTMAX-13", false, false, false, "real time signal 48");
+ AddSignal (114, "SIGRTMAX-12", false, false, false, "real time signal 49");
+ AddSignal (115, "SIGRTMAX-11", false, false, false, "real time signal 50");
+ AddSignal (116, "SIGRTMAX-10", false, false, false, "real time signal 51");
+ AddSignal (117, "SIGRTMAX-9", false, false, false, "real time signal 52");
+ AddSignal (118, "SIGRTMAX-8", false, false, false, "real time signal 53");
+ AddSignal (119, "SIGRTMAX-7", false, false, false, "real time signal 54");
+ AddSignal (120, "SIGRTMAX-6", false, false, false, "real time signal 55");
+ AddSignal (121, "SIGRTMAX-5", false, false, false, "real time signal 56");
+ AddSignal (122, "SIGRTMAX-4", false, false, false, "real time signal 57");
+ AddSignal (123, "SIGRTMAX-3", false, false, false, "real time signal 58");
+ AddSignal (124, "SIGRTMAX-2", false, false, false, "real time signal 59");
+ AddSignal (125, "SIGRTMAX-1", false, false, false, "real time signal 60");
+ AddSignal (126, "SIGRTMAX", false, false, false, "real time signal 61");
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryThread.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryThread.h
index 51173c6..e87f649 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryThread.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryThread.h
@@ -10,6 +10,10 @@
#ifndef liblldb_HistoryThread_h_
#define liblldb_HistoryThread_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Core/Broadcaster.h"
@@ -37,52 +41,55 @@ class HistoryThread : public lldb_private::Thread
public:
HistoryThread (lldb_private::Process &process, lldb::tid_t tid, std::vector<lldb::addr_t> pcs, uint32_t stop_id, bool stop_id_is_valid);
- virtual ~HistoryThread ();
+ ~HistoryThread() override;
- virtual lldb::RegisterContextSP
- GetRegisterContext ();
+ lldb::RegisterContextSP
+ GetRegisterContext() override;
- virtual lldb::RegisterContextSP
- CreateRegisterContextForFrame (StackFrame *frame);
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(StackFrame *frame) override;
- virtual void
- RefreshStateAfterStop() { }
+ void
+ RefreshStateAfterStop() override { }
bool
- CalculateStopInfo () { return false; }
+ CalculateStopInfo() override
+ {
+ return false;
+ }
void
- SetExtendedBacktraceToken (uint64_t token)
+ SetExtendedBacktraceToken(uint64_t token) override
{
m_extended_unwind_token = token;
}
uint64_t
- GetExtendedBacktraceToken ()
+ GetExtendedBacktraceToken() override
{
return m_extended_unwind_token;
}
const char *
- GetQueueName ()
+ GetQueueName() override
{
return m_queue_name.c_str();
}
void
- SetQueueName (const char *name)
+ SetQueueName(const char *name) override
{
m_queue_name = name;
}
lldb::queue_id_t
- GetQueueID ()
+ GetQueueID() override
{
return m_queue_id;
}
void
- SetQueueID (lldb::queue_id_t queue)
+ SetQueueID(lldb::queue_id_t queue) override
{
m_queue_id = queue;
}
@@ -94,7 +101,7 @@ public:
}
uint32_t
- GetExtendedBacktraceOriginatingIndexID ();
+ GetExtendedBacktraceOriginatingIndexID() override;
void
SetThreadName (const char *name)
@@ -102,14 +109,14 @@ public:
m_thread_name = name;
}
- virtual const char *
- GetName ()
+ const char *
+ GetName() override
{
return m_thread_name.c_str();
}
- virtual void
- SetName(const char *name)
+ void
+ SetName(const char *name) override
{
m_thread_name = name;
}
@@ -133,4 +140,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_HistoryThread_h_
+#endif // liblldb_HistoryThread_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryUnwind.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryUnwind.h
index 733f93e..2cb78bc 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryUnwind.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/HistoryUnwind.h
@@ -10,8 +10,12 @@
#ifndef liblldb_HistoryUnwind_h_
#define liblldb_HistoryUnwind_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/Unwind.h"
@@ -23,21 +27,21 @@ class HistoryUnwind : public lldb_private::Unwind
public:
HistoryUnwind (Thread &thread, std::vector<lldb::addr_t> pcs, bool stop_id_is_valid);
- virtual ~HistoryUnwind ();
+ ~HistoryUnwind() override;
protected:
void
- DoClear();
+ DoClear() override;
lldb::RegisterContextSP
- DoCreateRegisterContextForFrame (StackFrame *frame);
+ DoCreateRegisterContextForFrame(StackFrame *frame) override;
bool
- DoGetFrameInfoAtIndex (uint32_t frame_idx,
- lldb::addr_t& cfa,
- lldb::addr_t& pc);
+ DoGetFrameInfoAtIndex(uint32_t frame_idx,
+ lldb::addr_t& cfa,
+ lldb::addr_t& pc) override;
uint32_t
- DoGetFrameCount ();
+ DoGetFrameCount() override;
private:
@@ -47,4 +51,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_HistoryUnwind_h_
+#endif // liblldb_HistoryUnwind_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 3923c54..ebeba8c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -72,6 +72,7 @@ lldb_private::InferiorCallMmap (Process *process,
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
+ options.SetTrapExceptions(false);
addr_t prot_arg, flags_arg = 0;
if (prot == eMmapProtNone)
@@ -93,7 +94,7 @@ lldb_private::InferiorCallMmap (Process *process,
if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
{
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
- ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset };
lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
mmap_range.GetBaseAddress(),
@@ -103,9 +104,6 @@ lldb_private::InferiorCallMmap (Process *process,
if (call_plan_sp)
{
StreamFile error_strm;
- // This plan is a utility plan, so set it to discard itself when done.
- call_plan_sp->SetIsMasterPlan (true);
- call_plan_sp->SetOkayToDiscard(true);
StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
if (frame)
@@ -175,6 +173,7 @@ lldb_private::InferiorCallMunmap (Process *process,
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
+ options.SetTrapExceptions(false);
AddressRange munmap_range;
if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
@@ -182,15 +181,12 @@ lldb_private::InferiorCallMunmap (Process *process,
lldb::addr_t args[] = { addr, length };
lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
munmap_range.GetBaseAddress(),
- ClangASTType(),
+ CompilerType(),
args,
options));
if (call_plan_sp)
{
StreamFile error_strm;
- // This plan is a utility plan, so set it to discard itself when done.
- call_plan_sp->SetIsMasterPlan (true);
- call_plan_sp->SetOkayToDiscard(true);
StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
if (frame)
@@ -220,7 +216,8 @@ lldb_private::InferiorCallMunmap (Process *process,
bool
lldb_private::InferiorCall (Process *process,
const Address *address,
- addr_t &returned_func)
+ addr_t &returned_func,
+ bool trap_exceptions)
{
Thread *thread = process->GetThreadList().GetSelectedThread().get();
if (thread == NULL || address == NULL)
@@ -233,9 +230,10 @@ lldb_private::InferiorCall (Process *process,
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
+ options.SetTrapExceptions(trap_exceptions);
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
- ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
*address,
clang_void_ptr_type,
@@ -244,9 +242,6 @@ lldb_private::InferiorCall (Process *process,
if (call_plan_sp)
{
StreamString error_strm;
- // This plan is a utility plan, so set it to discard itself when done.
- call_plan_sp->SetIsMasterPlan (true);
- call_plan_sp->SetOkayToDiscard(true);
StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
if (frame)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h
index e56e95c..d10e849 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h
@@ -31,7 +31,8 @@ bool InferiorCallMmap(Process *proc, lldb::addr_t &allocated_addr,
bool InferiorCallMunmap(Process *proc, lldb::addr_t addr, lldb::addr_t length);
-bool InferiorCall(Process *proc, const Address *address, lldb::addr_t &returned_func);
+bool InferiorCall(Process *proc, const Address *address, lldb::addr_t &returned_func,
+ bool trap_exceptions = false);
} // namespace lldb_private
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp
index cd1fc81..5687577 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp
@@ -24,72 +24,70 @@ void
LinuxSignals::Reset()
{
m_signals.clear();
-
- AddSignal (1, "SIGHUP", "HUP", false, true , true , "hangup");
- AddSignal (2, "SIGINT", "INT", true , true , true , "interrupt");
- AddSignal (3, "SIGQUIT", "QUIT", false, true , true , "quit");
- AddSignal (4, "SIGILL", "ILL", false, true , true , "illegal instruction");
- AddSignal (5, "SIGTRAP", "TRAP", true , true , true , "trace trap (not reset when caught)");
- AddSignal (6, "SIGABRT", "ABRT", false, true , true , "abort()");
- AddSignal (6, "SIGIOT", "IOT", false, true , true , "IOT trap");
- AddSignal (7, "SIGBUS", "BUS", false, true , true , "bus error");
- AddSignal (8, "SIGFPE", "FPE", false, true , true , "floating point exception");
- AddSignal (9, "SIGKILL", "KILL", false, true , true , "kill");
- AddSignal (10, "SIGUSR1", "USR1", false, true , true , "user defined signal 1");
- AddSignal (11, "SIGSEGV", "SEGV", false, true , true , "segmentation violation");
- AddSignal (12, "SIGUSR2", "USR2", false, true , true , "user defined signal 2");
- AddSignal (13, "SIGPIPE", "PIPE", false, true , true , "write to pipe with reading end closed");
- AddSignal (14, "SIGALRM", "ALRM", false, false, false, "alarm");
- AddSignal (15, "SIGTERM", "TERM", false, true , true , "termination requested");
- AddSignal (16, "SIGSTKFLT", "STKFLT", false, true , true , "stack fault");
- AddSignal (16, "SIGCLD", "CLD", false, false, true , "same as SIGCHLD");
- AddSignal (17, "SIGCHLD", "CHLD", false, false, true , "child status has changed");
- AddSignal (18, "SIGCONT", "CONT", false, true , true , "process continue");
- AddSignal (19, "SIGSTOP", "STOP", true , true , true , "process stop");
- AddSignal (20, "SIGTSTP", "TSTP", false, true , true , "tty stop");
- AddSignal (21, "SIGTTIN", "TTIN", false, true , true , "background tty read");
- AddSignal (22, "SIGTTOU", "TTOU", false, true , true , "background tty write");
- AddSignal (23, "SIGURG", "URG", false, true , true , "urgent data on socket");
- AddSignal (24, "SIGXCPU", "XCPU", false, true , true , "CPU resource exceeded");
- AddSignal (25, "SIGXFSZ", "XFSZ", false, true , true , "file size limit exceeded");
- AddSignal (26, "SIGVTALRM", "VTALRM", false, true , true , "virtual time alarm");
- AddSignal (27, "SIGPROF", "PROF", false, false, false, "profiling time alarm");
- AddSignal (28, "SIGWINCH", "WINCH", false, true , true , "window size changes");
- AddSignal (29, "SIGPOLL", "POLL", false, true , true , "pollable event");
- AddSignal (29, "SIGIO", "IO", false, true , true , "input/output ready");
- AddSignal (30, "SIGPWR", "PWR", false, true , true , "power failure");
- AddSignal (31, "SIGSYS", "SYS", false, true , true , "invalid system call");
- AddSignal (32, "SIG32", "SIG32", false, true , true , "threading library internal signal 1");
- AddSignal (33, "SIG33", "SIG33", false, true , true , "threading library internal signal 2");
- AddSignal (34, "SIGRTMIN", "RTMIN", false, true , true , "real time signal 0");
- AddSignal (35, "SIGRTMIN+1", "RTMIN+1", false, true , true , "real time signal 1");
- AddSignal (36, "SIGRTMIN+2", "RTMIN+2", false, true , true , "real time signal 2");
- AddSignal (37, "SIGRTMIN+3", "RTMIN+3", false, true , true , "real time signal 3");
- AddSignal (38, "SIGRTMIN+4", "RTMIN+4", false, true , true , "real time signal 4");
- AddSignal (39, "SIGRTMIN+5", "RTMIN+5", false, true , true , "real time signal 5");
- AddSignal (40, "SIGRTMIN+6", "RTMIN+6", false, true , true , "real time signal 6");
- AddSignal (41, "SIGRTMIN+7", "RTMIN+7", false, true , true , "real time signal 7");
- AddSignal (42, "SIGRTMIN+8", "RTMIN+8", false, true , true , "real time signal 8");
- AddSignal (43, "SIGRTMIN+9", "RTMIN+9", false, true , true , "real time signal 9");
- AddSignal (44, "SIGRTMIN+10", "RTMIN+10", false, true , true , "real time signal 10");
- AddSignal (45, "SIGRTMIN+11", "RTMIN+11", false, true , true , "real time signal 11");
- AddSignal (46, "SIGRTMIN+12", "RTMIN+12", false, true , true , "real time signal 12");
- AddSignal (47, "SIGRTMIN+13", "RTMIN+13", false, true , true , "real time signal 13");
- AddSignal (48, "SIGRTMIN+14", "RTMIN+14", false, true , true , "real time signal 14");
- AddSignal (49, "SIGRTMIN+15", "RTMIN+15", false, true , true , "real time signal 15");
- AddSignal (50, "SIGRTMAX-14", "RTMAX-14", false, true , true , "real time signal 16"); // switching to SIGRTMAX-xxx to match "kill -l" output
- AddSignal (51, "SIGRTMAX-13", "RTMAX-13", false, true , true , "real time signal 17");
- AddSignal (52, "SIGRTMAX-12", "RTMAX-12", false, true , true , "real time signal 18");
- AddSignal (53, "SIGRTMAX-11", "RTMAX-11", false, true , true , "real time signal 19");
- AddSignal (54, "SIGRTMAX-10", "RTMAX-10", false, true , true , "real time signal 20");
- AddSignal (55, "SIGRTMAX-9", "RTMAX-9", false, true , true , "real time signal 21");
- AddSignal (56, "SIGRTMAX-8", "RTMAX-8", false, true , true , "real time signal 22");
- AddSignal (57, "SIGRTMAX-7", "RTMAX-7", false, true , true , "real time signal 23");
- AddSignal (58, "SIGRTMAX-6", "RTMAX-6", false, true , true , "real time signal 24");
- AddSignal (59, "SIGRTMAX-5", "RTMAX-5", false, true , true , "real time signal 25");
- AddSignal (60, "SIGRTMAX-4", "RTMAX-4", false, true , true , "real time signal 26");
- AddSignal (61, "SIGRTMAX-3", "RTMAX-3", false, true , true , "real time signal 27");
- AddSignal (62, "SIGRTMAX-2", "RTMAX-2", false, true , true , "real time signal 28");
- AddSignal (63, "SIGRTMAX-1", "RTMAX-1", false, true , true , "real time signal 29");
- AddSignal (64, "SIGRTMAX", "RTMAX", false, true , true , "real time signal 30");
+ // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION ALIAS
+ // ===== =========== ======== ===== ====== ====================================== ======
+ AddSignal (1, "SIGHUP", false, true , true , "hangup" );
+ AddSignal (2, "SIGINT", true , true , true , "interrupt" );
+ AddSignal (3, "SIGQUIT", false, true , true , "quit" );
+ AddSignal (4, "SIGILL", false, true , true , "illegal instruction" );
+ AddSignal (5, "SIGTRAP", true , true , true , "trace trap (not reset when caught)" );
+ AddSignal (6, "SIGABRT", false, true , true , "abort()/IOT trap", "SIGIOT");
+ AddSignal (7, "SIGBUS", false, true , true , "bus error" );
+ AddSignal (8, "SIGFPE", false, true , true , "floating point exception" );
+ AddSignal (9, "SIGKILL", false, true , true , "kill" );
+ AddSignal (10, "SIGUSR1", false, true , true , "user defined signal 1" );
+ AddSignal (11, "SIGSEGV", false, true , true , "segmentation violation" );
+ AddSignal (12, "SIGUSR2", false, true , true , "user defined signal 2" );
+ AddSignal (13, "SIGPIPE", false, true , true , "write to pipe with reading end closed" );
+ AddSignal (14, "SIGALRM", false, false, false, "alarm" );
+ AddSignal (15, "SIGTERM", false, true , true , "termination requested" );
+ AddSignal (16, "SIGSTKFLT", false, true , true , "stack fault" );
+ AddSignal (17, "SIGCHLD", false, false, true , "child status has changed", "SIGCLD");
+ AddSignal (18, "SIGCONT", false, true , true , "process continue" );
+ AddSignal (19, "SIGSTOP", true , true , true , "process stop" );
+ AddSignal (20, "SIGTSTP", false, true , true , "tty stop" );
+ AddSignal (21, "SIGTTIN", false, true , true , "background tty read" );
+ AddSignal (22, "SIGTTOU", false, true , true , "background tty write" );
+ AddSignal (23, "SIGURG", false, true , true , "urgent data on socket" );
+ AddSignal (24, "SIGXCPU", false, true , true , "CPU resource exceeded" );
+ AddSignal (25, "SIGXFSZ", false, true , true , "file size limit exceeded" );
+ AddSignal (26, "SIGVTALRM", false, true , true , "virtual time alarm" );
+ AddSignal (27, "SIGPROF", false, false, false, "profiling time alarm" );
+ AddSignal (28, "SIGWINCH", false, true , true , "window size changes" );
+ AddSignal (29, "SIGIO", false, true , true , "input/output ready/Pollable event", "SIGPOLL");
+ AddSignal (30, "SIGPWR", false, true , true , "power failure" );
+ AddSignal (31, "SIGSYS", false, true , true , "invalid system call" );
+ AddSignal (32, "SIG32", false, false, false, "threading library internal signal 1" );
+ AddSignal (33, "SIG33", false, false, false, "threading library internal signal 2" );
+ AddSignal (34, "SIGRTMIN", false, false, false, "real time signal 0" );
+ AddSignal (35, "SIGRTMIN+1", false, false, false, "real time signal 1" );
+ AddSignal (36, "SIGRTMIN+2", false, false, false, "real time signal 2" );
+ AddSignal (37, "SIGRTMIN+3", false, false, false, "real time signal 3" );
+ AddSignal (38, "SIGRTMIN+4", false, false, false, "real time signal 4" );
+ AddSignal (39, "SIGRTMIN+5", false, false, false, "real time signal 5" );
+ AddSignal (40, "SIGRTMIN+6", false, false, false, "real time signal 6" );
+ AddSignal (41, "SIGRTMIN+7", false, false, false, "real time signal 7" );
+ AddSignal (42, "SIGRTMIN+8", false, false, false, "real time signal 8" );
+ AddSignal (43, "SIGRTMIN+9", false, false, false, "real time signal 9" );
+ AddSignal (44, "SIGRTMIN+10", false, false, false, "real time signal 10" );
+ AddSignal (45, "SIGRTMIN+11", false, false, false, "real time signal 11" );
+ AddSignal (46, "SIGRTMIN+12", false, false, false, "real time signal 12" );
+ AddSignal (47, "SIGRTMIN+13", false, false, false, "real time signal 13" );
+ AddSignal (48, "SIGRTMIN+14", false, false, false, "real time signal 14" );
+ AddSignal (49, "SIGRTMIN+15", false, false, false, "real time signal 15" );
+ AddSignal (50, "SIGRTMAX-14", false, false, false, "real time signal 16" ); // switching to SIGRTMAX-xxx to match "kill -l" output
+ AddSignal (51, "SIGRTMAX-13", false, false, false, "real time signal 17" );
+ AddSignal (52, "SIGRTMAX-12", false, false, false, "real time signal 18" );
+ AddSignal (53, "SIGRTMAX-11", false, false, false, "real time signal 19" );
+ AddSignal (54, "SIGRTMAX-10", false, false, false, "real time signal 20" );
+ AddSignal (55, "SIGRTMAX-9", false, false, false, "real time signal 21" );
+ AddSignal (56, "SIGRTMAX-8", false, false, false, "real time signal 22" );
+ AddSignal (57, "SIGRTMAX-7", false, false, false, "real time signal 23" );
+ AddSignal (58, "SIGRTMAX-6", false, false, false, "real time signal 24" );
+ AddSignal (59, "SIGRTMAX-5", false, false, false, "real time signal 25" );
+ AddSignal (60, "SIGRTMAX-4", false, false, false, "real time signal 26" );
+ AddSignal (61, "SIGRTMAX-3", false, false, false, "real time signal 27" );
+ AddSignal (62, "SIGRTMAX-2", false, false, false, "real time signal 28" );
+ AddSignal (63, "SIGRTMAX-1", false, false, false, "real time signal 29" );
+ AddSignal (64, "SIGRTMAX", false, false, false, "real time signal 30" );
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
index 1dc0be8..422fc9b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
@@ -24,72 +24,70 @@ void
MipsLinuxSignals::Reset()
{
m_signals.clear();
-
- AddSignal (1, "SIGHUP", "HUP", false, true , true , "hangup");
- AddSignal (2, "SIGINT", "INT", true , true , true , "interrupt");
- AddSignal (3, "SIGQUIT", "QUIT", false, true , true , "quit");
- AddSignal (4, "SIGILL", "ILL", false, true , true , "illegal instruction");
- AddSignal (5, "SIGTRAP", "TRAP", true , true , true , "trace trap (not reset when caught)");
- AddSignal (6, "SIGABRT", "ABRT", false, true , true , "abort()");
- AddSignal (6, "SIGIOT", "IOT", false, true , true , "IOT trap");
- AddSignal (7, "SIGEMT", "EMT", false, true , true , "terminate process with core dump");
- AddSignal (8, "SIGFPE", "FPE", false, true , true , "floating point exception");
- AddSignal (9, "SIGKILL", "KILL", false, true , true , "kill");
- AddSignal (10, "SIGBUS", "BUS", false, true , true , "bus error");
- AddSignal (11, "SIGSEGV", "SEGV", false, true , true , "segmentation violation");
- AddSignal (12, "SIGSYS", "SYS", false, true , true , "invalid system call");
- AddSignal (13, "SIGPIPE", "PIPE", false, true , true , "write to pipe with reading end closed");
- AddSignal (14, "SIGALRM", "ALRM", false, false, false, "alarm");
- AddSignal (15, "SIGTERM", "TERM", false, true , true , "termination requested");
- AddSignal (16, "SIGUSR1", "USR1", false, true , true , "user defined signal 1");
- AddSignal (17, "SIGUSR2", "USR2", false, true , true , "user defined signal 2");
- AddSignal (18, "SIGCLD", "CLD", false, false, true , "same as SIGCHLD");
- AddSignal (18, "SIGCHLD", "CHLD", false, false, true , "child status has changed");
- AddSignal (19, "SIGPWR", "PWR", false, true , true , "power failure");
- AddSignal (20, "SIGWINCH", "WINCH", false, true , true , "window size changes");
- AddSignal (21, "SIGURG", "URG", false, true , true , "urgent data on socket");
- AddSignal (22, "SIGIO", "IO", false, true , true , "input/output ready");
- AddSignal (22, "SIGPOLL", "POLL", false, true , true , "pollable event");
- AddSignal (23, "SIGSTOP", "STOP", true , true , true , "process stop");
- AddSignal (24, "SIGTSTP", "TSTP", false, true , true , "tty stop");
- AddSignal (25, "SIGCONT", "CONT", false, true , true , "process continue");
- AddSignal (26, "SIGTTIN", "TTIN", false, true , true , "background tty read");
- AddSignal (27, "SIGTTOU", "TTOU", false, true , true , "background tty write");
- AddSignal (28, "SIGVTALRM", "VTALRM", false, true , true , "virtual time alarm");
- AddSignal (29, "SIGPROF", "PROF", false, false, false, "profiling time alarm");
- AddSignal (30, "SIGXCPU", "XCPU", false, true , true , "CPU resource exceeded");
- AddSignal (31, "SIGXFSZ", "XFSZ", false, true , true , "file size limit exceeded");
- AddSignal (32, "SIG32", "SIG32", false, true , true , "threading library internal signal 1");
- AddSignal (33, "SIG33", "SIG33", false, true , true , "threading library internal signal 2");
- AddSignal (34, "SIGRTMIN", "RTMIN", false, true , true , "real time signal 0");
- AddSignal (35, "SIGRTMIN+1", "RTMIN+1", false, true , true , "real time signal 1");
- AddSignal (36, "SIGRTMIN+2", "RTMIN+2", false, true , true , "real time signal 2");
- AddSignal (37, "SIGRTMIN+3", "RTMIN+3", false, true , true , "real time signal 3");
- AddSignal (38, "SIGRTMIN+4", "RTMIN+4", false, true , true , "real time signal 4");
- AddSignal (39, "SIGRTMIN+5", "RTMIN+5", false, true , true , "real time signal 5");
- AddSignal (40, "SIGRTMIN+6", "RTMIN+6", false, true , true , "real time signal 6");
- AddSignal (41, "SIGRTMIN+7", "RTMIN+7", false, true , true , "real time signal 7");
- AddSignal (42, "SIGRTMIN+8", "RTMIN+8", false, true , true , "real time signal 8");
- AddSignal (43, "SIGRTMIN+9", "RTMIN+9", false, true , true , "real time signal 9");
- AddSignal (44, "SIGRTMIN+10", "RTMIN+10", false, true , true , "real time signal 10");
- AddSignal (45, "SIGRTMIN+11", "RTMIN+11", false, true , true , "real time signal 11");
- AddSignal (46, "SIGRTMIN+12", "RTMIN+12", false, true , true , "real time signal 12");
- AddSignal (47, "SIGRTMIN+13", "RTMIN+13", false, true , true , "real time signal 13");
- AddSignal (48, "SIGRTMIN+14", "RTMIN+14", false, true , true , "real time signal 14");
- AddSignal (49, "SIGRTMIN+15", "RTMIN+15", false, true , true , "real time signal 15");
- AddSignal (50, "SIGRTMAX-14", "RTMAX-14", false, true , true , "real time signal 16"); // switching to SIGRTMAX-xxx to match "kill -l" output
- AddSignal (51, "SIGRTMAX-13", "RTMAX-13", false, true , true , "real time signal 17");
- AddSignal (52, "SIGRTMAX-12", "RTMAX-12", false, true , true , "real time signal 18");
- AddSignal (53, "SIGRTMAX-11", "RTMAX-11", false, true , true , "real time signal 19");
- AddSignal (54, "SIGRTMAX-10", "RTMAX-10", false, true , true , "real time signal 20");
- AddSignal (55, "SIGRTMAX-9", "RTMAX-9", false, true , true , "real time signal 21");
- AddSignal (56, "SIGRTMAX-8", "RTMAX-8", false, true , true , "real time signal 22");
- AddSignal (57, "SIGRTMAX-7", "RTMAX-7", false, true , true , "real time signal 23");
- AddSignal (58, "SIGRTMAX-6", "RTMAX-6", false, true , true , "real time signal 24");
- AddSignal (59, "SIGRTMAX-5", "RTMAX-5", false, true , true , "real time signal 25");
- AddSignal (60, "SIGRTMAX-4", "RTMAX-4", false, true , true , "real time signal 26");
- AddSignal (61, "SIGRTMAX-3", "RTMAX-3", false, true , true , "real time signal 27");
- AddSignal (62, "SIGRTMAX-2", "RTMAX-2", false, true , true , "real time signal 28");
- AddSignal (63, "SIGRTMAX-1", "RTMAX-1", false, true , true , "real time signal 29");
- AddSignal (64, "SIGRTMAX", "RTMAX", false, true , true , "real time signal 30");
+ // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION ALIAS
+ // ===== =========== ======== ===== ====== ====================================== ========
+ AddSignal (1, "SIGHUP", false, true , true , "hangup" );
+ AddSignal (2, "SIGINT", true , true , true , "interrupt" );
+ AddSignal (3, "SIGQUIT", false, true , true , "quit" );
+ AddSignal (4, "SIGILL", false, true , true , "illegal instruction" );
+ AddSignal (5, "SIGTRAP", true , true , true , "trace trap (not reset when caught)" );
+ AddSignal (6, "SIGABRT", false, true , true , "abort()/IOT trap", "SIGIOT");
+ AddSignal (7, "SIGEMT", false, true , true , "terminate process with core dump" );
+ AddSignal (8, "SIGFPE", false, true , true , "floating point exception" );
+ AddSignal (9, "SIGKILL", false, true , true , "kill" );
+ AddSignal (10, "SIGBUS", false, true , true , "bus error" );
+ AddSignal (11, "SIGSEGV", false, true , true , "segmentation violation" );
+ AddSignal (12, "SIGSYS", false, true , true , "invalid system call" );
+ AddSignal (13, "SIGPIPE", false, true , true , "write to pipe with reading end closed" );
+ AddSignal (14, "SIGALRM", false, false, false, "alarm" );
+ AddSignal (15, "SIGTERM", false, true , true , "termination requested" );
+ AddSignal (16, "SIGUSR1", false, true , true , "user defined signal 1" );
+ AddSignal (17, "SIGUSR2", false, true , true , "user defined signal 2" );
+ AddSignal (18, "SIGCHLD", false, false, true , "child status has changed", "SIGCLD");
+ AddSignal (19, "SIGPWR", false, true , true , "power failure" );
+ AddSignal (20, "SIGWINCH", false, true , true , "window size changes" );
+ AddSignal (21, "SIGURG", false, true , true , "urgent data on socket" );
+ AddSignal (22, "SIGIO", false, true , true , "input/output ready/Pollable event", "SIGPOLL");
+ AddSignal (23, "SIGSTOP", true , true , true , "process stop" );
+ AddSignal (24, "SIGTSTP", false, true , true , "tty stop" );
+ AddSignal (25, "SIGCONT", false, true , true , "process continue" );
+ AddSignal (26, "SIGTTIN", false, true , true , "background tty read" );
+ AddSignal (27, "SIGTTOU", false, true , true , "background tty write" );
+ AddSignal (28, "SIGVTALRM", false, true , true , "virtual time alarm" );
+ AddSignal (29, "SIGPROF", false, false, false, "profiling time alarm" );
+ AddSignal (30, "SIGXCPU", false, true , true , "CPU resource exceeded" );
+ AddSignal (31, "SIGXFSZ", false, true , true , "file size limit exceeded" );
+ AddSignal (32, "SIG32", false, false, false, "threading library internal signal 1" );
+ AddSignal (33, "SIG33", false, false, false, "threading library internal signal 2" );
+ AddSignal (34, "SIGRTMIN", false, false, false, "real time signal 0" );
+ AddSignal (35, "SIGRTMIN+1", false, false, false, "real time signal 1" );
+ AddSignal (36, "SIGRTMIN+2", false, false, false, "real time signal 2" );
+ AddSignal (37, "SIGRTMIN+3", false, false, false, "real time signal 3" );
+ AddSignal (38, "SIGRTMIN+4", false, false, false, "real time signal 4" );
+ AddSignal (39, "SIGRTMIN+5", false, false, false, "real time signal 5" );
+ AddSignal (40, "SIGRTMIN+6", false, false, false, "real time signal 6" );
+ AddSignal (41, "SIGRTMIN+7", false, false, false, "real time signal 7" );
+ AddSignal (42, "SIGRTMIN+8", false, false, false, "real time signal 8" );
+ AddSignal (43, "SIGRTMIN+9", false, false, false, "real time signal 9" );
+ AddSignal (44, "SIGRTMIN+10", false, false, false, "real time signal 10" );
+ AddSignal (45, "SIGRTMIN+11", false, false, false, "real time signal 11" );
+ AddSignal (46, "SIGRTMIN+12", false, false, false, "real time signal 12" );
+ AddSignal (47, "SIGRTMIN+13", false, false, false, "real time signal 13" );
+ AddSignal (48, "SIGRTMIN+14", false, false, false, "real time signal 14" );
+ AddSignal (49, "SIGRTMIN+15", false, false, false, "real time signal 15" );
+ AddSignal (50, "SIGRTMAX-14", false, false, false, "real time signal 16" ); // switching to SIGRTMAX-xxx to match "kill -l" output
+ AddSignal (51, "SIGRTMAX-13", false, false, false, "real time signal 17" );
+ AddSignal (52, "SIGRTMAX-12", false, false, false, "real time signal 18" );
+ AddSignal (53, "SIGRTMAX-11", false, false, false, "real time signal 19" );
+ AddSignal (54, "SIGRTMAX-10", false, false, false, "real time signal 20" );
+ AddSignal (55, "SIGRTMAX-9", false, false, false, "real time signal 21" );
+ AddSignal (56, "SIGRTMAX-8", false, false, false, "real time signal 22" );
+ AddSignal (57, "SIGRTMAX-7", false, false, false, "real time signal 23" );
+ AddSignal (58, "SIGRTMAX-6", false, false, false, "real time signal 24" );
+ AddSignal (59, "SIGRTMAX-5", false, false, false, "real time signal 25" );
+ AddSignal (60, "SIGRTMAX-4", false, false, false, "real time signal 26" );
+ AddSignal (61, "SIGRTMAX-3", false, false, false, "real time signal 27" );
+ AddSignal (62, "SIGRTMAX-2", false, false, false, "real time signal 28" );
+ AddSignal (63, "SIGRTMAX-1", false, false, false, "real time signal 29" );
+ AddSignal (64, "SIGRTMAX", false, false, false, "real time signal 30" );
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp
new file mode 100644
index 0000000..5dce516
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/NetBSDSignals.cpp
@@ -0,0 +1,34 @@
+//===-- NetBSDSignals.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "NetBSDSignals.h"
+
+using namespace lldb_private;
+
+NetBSDSignals::NetBSDSignals()
+ : UnixSignals()
+{
+ Reset();
+}
+
+void
+NetBSDSignals::Reset()
+{
+ UnixSignals::Reset();
+ // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION
+ // ====== ============ ======== ====== ====== ===================================================
+ AddSignal (32, "SIGPWR", false, true , true , "power fail/restart (not reset when caught)");
+#ifdef SIGRTMIN /* SIGRTMAX */
+ /* Kernel only; not exposed to userland yet */
+#endif
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/NetBSDSignals.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/NetBSDSignals.h
new file mode 100644
index 0000000..441402b
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/NetBSDSignals.h
@@ -0,0 +1,31 @@
+//===-- NetBSDSignals.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_NetBSDSignals_H_
+#define liblldb_NetBSDSignals_H_
+
+// Project includes
+#include "lldb/Target/UnixSignals.h"
+
+namespace lldb_private {
+
+/// NetBSD specific set of Unix signals.
+class NetBSDSignals : public UnixSignals
+{
+public:
+ NetBSDSignals();
+
+private:
+ void
+ Reset() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_NetBSDSignals_H_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index 4138a6a..452fb47 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -34,8 +34,8 @@
#endif
// Project includes
-#include "ARM_GCC_Registers.h"
#include "ARM_DWARF_Registers.h"
+#include "Utility/ARM_ehframe_Registers.h"
#include "llvm/ADT/STLExtras.h"
@@ -172,89 +172,69 @@ enum
};
-RegisterContextDarwin_arm::RegisterContextDarwin_arm(Thread &thread, uint32_t concrete_frame_idx) :
- RegisterContext(thread, concrete_frame_idx),
- gpr(),
- fpu(),
- exc()
-{
- uint32_t i;
- for (i=0; i<kNumErrors; i++)
- {
- gpr_errs[i] = -1;
- fpu_errs[i] = -1;
- exc_errs[i] = -1;
- }
-}
-
-RegisterContextDarwin_arm::~RegisterContextDarwin_arm()
-{
-}
-
-
#define GPR_OFFSET(idx) ((idx) * 4)
#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR))
#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU))
#define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextDarwin_arm::DBG, reg) + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC)))
-#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL
+#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL
#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC))
static RegisterInfo g_register_infos[] = {
// General purpose registers
-// NAME ALT SZ OFFSET ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+// NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= ========== ===============
-{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_INVALID_REGNUM, gdb_arm_r0, gpr_r0 }, NULL, NULL},
-{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_INVALID_REGNUM, gdb_arm_r1, gpr_r1 }, NULL, NULL},
-{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_INVALID_REGNUM, gdb_arm_r2, gpr_r2 }, NULL, NULL},
-{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_INVALID_REGNUM, gdb_arm_r3, gpr_r3 }, NULL, NULL},
-{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, gpr_r4 }, NULL, NULL},
-{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, gpr_r5 }, NULL, NULL},
-{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, gpr_r6 }, NULL, NULL},
-{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, gpr_r7 }, NULL, NULL},
-{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, gpr_r8 }, NULL, NULL},
-{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, gpr_r9 }, NULL, NULL},
-{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, gpr_r10 }, NULL, NULL},
-{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, gpr_r11 }, NULL, NULL},
-{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, gpr_r12 }, NULL, NULL},
-{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, gpr_sp }, NULL, NULL},
-{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, gpr_lr }, NULL, NULL},
-{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, gpr_pc }, NULL, NULL},
-{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, gpr_cpsr }, NULL, NULL},
-
-{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, fpu_s0 }, NULL, NULL},
-{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, fpu_s1 }, NULL, NULL},
-{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, fpu_s2 }, NULL, NULL},
-{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, fpu_s3 }, NULL, NULL},
-{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, fpu_s4 }, NULL, NULL},
-{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, fpu_s5 }, NULL, NULL},
-{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, fpu_s6 }, NULL, NULL},
-{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, fpu_s7 }, NULL, NULL},
-{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, fpu_s8 }, NULL, NULL},
-{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, fpu_s9 }, NULL, NULL},
-{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, fpu_s10 }, NULL, NULL},
-{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, fpu_s11 }, NULL, NULL},
-{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, fpu_s12 }, NULL, NULL},
-{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, fpu_s13 }, NULL, NULL},
-{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, fpu_s14 }, NULL, NULL},
-{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, fpu_s15 }, NULL, NULL},
-{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, fpu_s16 }, NULL, NULL},
-{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, fpu_s17 }, NULL, NULL},
-{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, fpu_s18 }, NULL, NULL},
-{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, fpu_s19 }, NULL, NULL},
-{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, fpu_s20 }, NULL, NULL},
-{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, fpu_s21 }, NULL, NULL},
-{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, fpu_s22 }, NULL, NULL},
-{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, fpu_s23 }, NULL, NULL},
-{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, fpu_s24 }, NULL, NULL},
-{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, fpu_s25 }, NULL, NULL},
-{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, fpu_s26 }, NULL, NULL},
-{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, fpu_s27 }, NULL, NULL},
-{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, fpu_s28 }, NULL, NULL},
-{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, fpu_s29 }, NULL, NULL},
-{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, fpu_s30 }, NULL, NULL},
-{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, fpu_s31 }, NULL, NULL},
-{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, fpu_fpscr }, NULL, NULL},
+{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { ehframe_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r0 }, NULL, NULL},
+{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { ehframe_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r1 }, NULL, NULL},
+{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { ehframe_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r2 }, NULL, NULL},
+{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { ehframe_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r3 }, NULL, NULL},
+{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r4 }, NULL, NULL},
+{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r5 }, NULL, NULL},
+{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r6 }, NULL, NULL},
+{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_r7 }, NULL, NULL},
+{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r8 }, NULL, NULL},
+{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r9 }, NULL, NULL},
+{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r10 }, NULL, NULL},
+{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r11 }, NULL, NULL},
+{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r12 }, NULL, NULL},
+{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_sp }, NULL, NULL},
+{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_lr }, NULL, NULL},
+{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc }, NULL, NULL},
+{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_cpsr }, NULL, NULL},
+
+{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s0 }, NULL, NULL},
+{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s1 }, NULL, NULL},
+{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s2 }, NULL, NULL},
+{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s3 }, NULL, NULL},
+{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s4 }, NULL, NULL},
+{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s5 }, NULL, NULL},
+{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s6 }, NULL, NULL},
+{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s7 }, NULL, NULL},
+{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s8 }, NULL, NULL},
+{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s9 }, NULL, NULL},
+{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s10 }, NULL, NULL},
+{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s11 }, NULL, NULL},
+{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s12 }, NULL, NULL},
+{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s13 }, NULL, NULL},
+{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s14 }, NULL, NULL},
+{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s15 }, NULL, NULL},
+{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s16 }, NULL, NULL},
+{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s17 }, NULL, NULL},
+{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s18 }, NULL, NULL},
+{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s19 }, NULL, NULL},
+{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s20 }, NULL, NULL},
+{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s21 }, NULL, NULL},
+{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s22 }, NULL, NULL},
+{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s23 }, NULL, NULL},
+{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s24 }, NULL, NULL},
+{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s25 }, NULL, NULL},
+{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s26 }, NULL, NULL},
+{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s27 }, NULL, NULL},
+{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s28 }, NULL, NULL},
+{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s29 }, NULL, NULL},
+{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s30 }, NULL, NULL},
+{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s31 }, NULL, NULL},
+{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpscr }, NULL, NULL},
{ "exception",NULL, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, NULL, NULL},
{ "fsr", NULL, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }, NULL, NULL},
@@ -403,6 +383,26 @@ g_exc_regnums[] =
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+RegisterContextDarwin_arm::RegisterContextDarwin_arm(Thread &thread, uint32_t concrete_frame_idx) :
+ RegisterContext(thread, concrete_frame_idx),
+ gpr(),
+ fpu(),
+ exc()
+{
+ uint32_t i;
+ for (i=0; i<kNumErrors; i++)
+ {
+ gpr_errs[i] = -1;
+ fpu_errs[i] = -1;
+ exc_errs[i] = -1;
+ }
+}
+
+RegisterContextDarwin_arm::~RegisterContextDarwin_arm()
+{
+}
+
+
void
RegisterContextDarwin_arm::InvalidateAllRegisters ()
{
@@ -940,27 +940,27 @@ RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber (lldb::RegisterKi
break;
}
}
- else if (kind == eRegisterKindGCC)
+ else if (kind == eRegisterKindEHFrame)
{
switch (reg)
{
- case gcc_r0: return gpr_r0;
- case gcc_r1: return gpr_r1;
- case gcc_r2: return gpr_r2;
- case gcc_r3: return gpr_r3;
- case gcc_r4: return gpr_r4;
- case gcc_r5: return gpr_r5;
- case gcc_r6: return gpr_r6;
- case gcc_r7: return gpr_r7;
- case gcc_r8: return gpr_r8;
- case gcc_r9: return gpr_r9;
- case gcc_r10: return gpr_r10;
- case gcc_r11: return gpr_r11;
- case gcc_r12: return gpr_r12;
- case gcc_sp: return gpr_sp;
- case gcc_lr: return gpr_lr;
- case gcc_pc: return gpr_pc;
- case gcc_cpsr: return gpr_cpsr;
+ case ehframe_r0: return gpr_r0;
+ case ehframe_r1: return gpr_r1;
+ case ehframe_r2: return gpr_r2;
+ case ehframe_r3: return gpr_r3;
+ case ehframe_r4: return gpr_r4;
+ case ehframe_r5: return gpr_r5;
+ case ehframe_r6: return gpr_r6;
+ case ehframe_r7: return gpr_r7;
+ case ehframe_r8: return gpr_r8;
+ case ehframe_r9: return gpr_r9;
+ case ehframe_r10: return gpr_r10;
+ case ehframe_r11: return gpr_r11;
+ case ehframe_r12: return gpr_r12;
+ case ehframe_sp: return gpr_sp;
+ case ehframe_lr: return gpr_lr;
+ case ehframe_pc: return gpr_pc;
+ case ehframe_cpsr: return gpr_cpsr;
}
}
else if (kind == eRegisterKindLLDB)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
index 23134ef..f4d8225 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
@@ -51,61 +51,59 @@
class RegisterContextDarwin_arm : public lldb_private::RegisterContext
{
public:
-
RegisterContextDarwin_arm(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
- virtual
- ~RegisterContextDarwin_arm();
+ ~RegisterContextDarwin_arm() override;
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &reg_value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &reg_value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &reg_value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &reg_value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
- virtual uint32_t
- NumSupportedHardwareBreakpoints ();
+ uint32_t
+ NumSupportedHardwareBreakpoints() override;
- virtual uint32_t
- SetHardwareBreakpoint (lldb::addr_t addr, size_t size);
+ uint32_t
+ SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
- virtual bool
- ClearHardwareBreakpoint (uint32_t hw_idx);
+ bool
+ ClearHardwareBreakpoint(uint32_t hw_idx) override;
- virtual uint32_t
- NumSupportedHardwareWatchpoints ();
+ uint32_t
+ NumSupportedHardwareWatchpoints() override;
- virtual uint32_t
- SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
+ uint32_t
+ SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override;
- virtual bool
- ClearHardwareWatchpoint (uint32_t hw_index);
+ bool
+ ClearHardwareWatchpoint(uint32_t hw_index) override;
struct GPR
{
@@ -113,7 +111,6 @@ public:
uint32_t cpsr; // CPSR
};
-
struct QReg
{
uint8_t bytes[16];
@@ -163,7 +160,6 @@ public:
LogDBGRegisters (lldb_private::Log *log, const DBG& dbg);
protected:
-
enum
{
GPRRegSet = 1, // ARM_THREAD_STATE
@@ -330,4 +326,4 @@ protected:
GetRegisterInfos ();
};
-#endif // liblldb_RegisterContextDarwin_arm_h_
+#endif // liblldb_RegisterContextDarwin_arm_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
index e08a873..7de042d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -36,31 +36,11 @@
#endif
// Project includes
-#include "ARM64_GCC_Registers.h"
#include "ARM64_DWARF_Registers.h"
using namespace lldb;
using namespace lldb_private;
-RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(Thread &thread, uint32_t concrete_frame_idx) :
- RegisterContext(thread, concrete_frame_idx),
- gpr(),
- fpu(),
- exc()
-{
- uint32_t i;
- for (i=0; i<kNumErrors; i++)
- {
- gpr_errs[i] = -1;
- fpu_errs[i] = -1;
- exc_errs[i] = -1;
- }
-}
-
-RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64()
-{
-}
-
#define GPR_OFFSET(idx) ((idx) * 8)
#define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::GPR, reg))
@@ -71,7 +51,7 @@ RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64()
#define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::EXC, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU))
#define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::DBG, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC))
-#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL
+#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL
#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC))
//-----------------------------------------------------------------------------
@@ -173,6 +153,26 @@ g_exc_regnums[] =
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos_arm64);
+RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(Thread &thread, uint32_t concrete_frame_idx) :
+ RegisterContext(thread, concrete_frame_idx),
+ gpr(),
+ fpu(),
+ exc()
+{
+ uint32_t i;
+ for (i=0; i<kNumErrors; i++)
+ {
+ gpr_errs[i] = -1;
+ fpu_errs[i] = -1;
+ exc_errs[i] = -1;
+ }
+}
+
+RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64()
+{
+}
+
+
void
RegisterContextDarwin_arm64::InvalidateAllRegisters ()
{
@@ -488,7 +488,7 @@ RegisterContextDarwin_arm64::ReadRegister (const RegisterInfo *reg_info, Registe
case fpu_v29:
case fpu_v30:
case fpu_v31:
- value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder());
+ value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, endian::InlHostByteOrder());
break;
case fpu_fpsr:
@@ -770,44 +770,44 @@ RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber (RegisterKind k
break;
}
}
- else if (kind == eRegisterKindGCC)
+ else if (kind == eRegisterKindEHFrame)
{
switch (reg)
{
- case arm64_gcc::x0: return gpr_x0;
- case arm64_gcc::x1: return gpr_x1;
- case arm64_gcc::x2: return gpr_x2;
- case arm64_gcc::x3: return gpr_x3;
- case arm64_gcc::x4: return gpr_x4;
- case arm64_gcc::x5: return gpr_x5;
- case arm64_gcc::x6: return gpr_x6;
- case arm64_gcc::x7: return gpr_x7;
- case arm64_gcc::x8: return gpr_x8;
- case arm64_gcc::x9: return gpr_x9;
- case arm64_gcc::x10: return gpr_x10;
- case arm64_gcc::x11: return gpr_x11;
- case arm64_gcc::x12: return gpr_x12;
- case arm64_gcc::x13: return gpr_x13;
- case arm64_gcc::x14: return gpr_x14;
- case arm64_gcc::x15: return gpr_x15;
- case arm64_gcc::x16: return gpr_x16;
- case arm64_gcc::x17: return gpr_x17;
- case arm64_gcc::x18: return gpr_x18;
- case arm64_gcc::x19: return gpr_x19;
- case arm64_gcc::x20: return gpr_x20;
- case arm64_gcc::x21: return gpr_x21;
- case arm64_gcc::x22: return gpr_x22;
- case arm64_gcc::x23: return gpr_x23;
- case arm64_gcc::x24: return gpr_x24;
- case arm64_gcc::x25: return gpr_x25;
- case arm64_gcc::x26: return gpr_x26;
- case arm64_gcc::x27: return gpr_x27;
- case arm64_gcc::x28: return gpr_x28;
- case arm64_gcc::fp: return gpr_fp;
- case arm64_gcc::sp: return gpr_sp;
- case arm64_gcc::lr: return gpr_lr;
- case arm64_gcc::pc: return gpr_pc;
- case arm64_gcc::cpsr: return gpr_cpsr;
+ case arm64_ehframe::x0: return gpr_x0;
+ case arm64_ehframe::x1: return gpr_x1;
+ case arm64_ehframe::x2: return gpr_x2;
+ case arm64_ehframe::x3: return gpr_x3;
+ case arm64_ehframe::x4: return gpr_x4;
+ case arm64_ehframe::x5: return gpr_x5;
+ case arm64_ehframe::x6: return gpr_x6;
+ case arm64_ehframe::x7: return gpr_x7;
+ case arm64_ehframe::x8: return gpr_x8;
+ case arm64_ehframe::x9: return gpr_x9;
+ case arm64_ehframe::x10: return gpr_x10;
+ case arm64_ehframe::x11: return gpr_x11;
+ case arm64_ehframe::x12: return gpr_x12;
+ case arm64_ehframe::x13: return gpr_x13;
+ case arm64_ehframe::x14: return gpr_x14;
+ case arm64_ehframe::x15: return gpr_x15;
+ case arm64_ehframe::x16: return gpr_x16;
+ case arm64_ehframe::x17: return gpr_x17;
+ case arm64_ehframe::x18: return gpr_x18;
+ case arm64_ehframe::x19: return gpr_x19;
+ case arm64_ehframe::x20: return gpr_x20;
+ case arm64_ehframe::x21: return gpr_x21;
+ case arm64_ehframe::x22: return gpr_x22;
+ case arm64_ehframe::x23: return gpr_x23;
+ case arm64_ehframe::x24: return gpr_x24;
+ case arm64_ehframe::x25: return gpr_x25;
+ case arm64_ehframe::x26: return gpr_x26;
+ case arm64_ehframe::x27: return gpr_x27;
+ case arm64_ehframe::x28: return gpr_x28;
+ case arm64_ehframe::fp: return gpr_fp;
+ case arm64_ehframe::sp: return gpr_sp;
+ case arm64_ehframe::lr: return gpr_lr;
+ case arm64_ehframe::pc: return gpr_pc;
+ case arm64_ehframe::cpsr: return gpr_cpsr;
}
}
else if (kind == eRegisterKindLLDB)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
index aeac15e..b228c42 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
@@ -32,52 +32,50 @@
class RegisterContextDarwin_arm64 : public lldb_private::RegisterContext
{
public:
-
RegisterContextDarwin_arm64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
- virtual
- ~RegisterContextDarwin_arm64();
+ ~RegisterContextDarwin_arm64() override;
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &reg_value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &reg_value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &reg_value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &reg_value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
- virtual uint32_t
- NumSupportedHardwareWatchpoints ();
+ uint32_t
+ NumSupportedHardwareWatchpoints() override;
- virtual uint32_t
- SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
+ uint32_t
+ SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override;
- virtual bool
- ClearHardwareWatchpoint (uint32_t hw_index);
+ bool
+ ClearHardwareWatchpoint(uint32_t hw_index) override;
// mirrors <mach/arm/thread_status.h> arm_thread_state64_t
struct GPR
@@ -90,7 +88,6 @@ public:
uint32_t cpsr; // cpsr
};
-
struct VReg
{
uint8_t bytes[16];
@@ -126,7 +123,6 @@ public:
LogDBGRegisters (lldb_private::Log *log, const DBG& dbg);
protected:
-
enum
{
GPRRegSet = 6, // ARM_THREAD_STATE64
@@ -293,4 +289,4 @@ protected:
GetRegisterInfos ();
};
-#endif // liblldb_RegisterContextDarwin_arm64_h_
+#endif // liblldb_RegisterContextDarwin_arm64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index 08144bf..1b01c28 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -98,16 +98,16 @@ enum
enum
{
- gcc_eax = 0,
- gcc_ecx,
- gcc_edx,
- gcc_ebx,
- gcc_ebp,
- gcc_esp,
- gcc_esi,
- gcc_edi,
- gcc_eip,
- gcc_eflags
+ ehframe_eax = 0,
+ ehframe_ecx,
+ ehframe_edx,
+ ehframe_ebx,
+ ehframe_ebp,
+ ehframe_esp,
+ ehframe_esi,
+ ehframe_edi,
+ ehframe_eip,
+ ehframe_eflags
};
enum
@@ -140,79 +140,6 @@ enum
dwarf_xmm7
};
-enum
-{
- gdb_eax = 0,
- gdb_ecx = 1,
- gdb_edx = 2,
- gdb_ebx = 3,
- gdb_esp = 4,
- gdb_ebp = 5,
- gdb_esi = 6,
- gdb_edi = 7,
- gdb_eip = 8,
- gdb_eflags = 9,
- gdb_cs = 10,
- gdb_ss = 11,
- gdb_ds = 12,
- gdb_es = 13,
- gdb_fs = 14,
- gdb_gs = 15,
- gdb_stmm0 = 16,
- gdb_stmm1 = 17,
- gdb_stmm2 = 18,
- gdb_stmm3 = 19,
- gdb_stmm4 = 20,
- gdb_stmm5 = 21,
- gdb_stmm6 = 22,
- gdb_stmm7 = 23,
- gdb_fctrl = 24, gdb_fcw = gdb_fctrl,
- gdb_fstat = 25, gdb_fsw = gdb_fstat,
- gdb_ftag = 26, gdb_ftw = gdb_ftag,
- gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg,
- gdb_fioff = 28, gdb_ip = gdb_fioff,
- gdb_foseg = 29, gdb_fpu_ds = gdb_foseg,
- gdb_fooff = 30, gdb_dp = gdb_fooff,
- gdb_fop = 31,
- gdb_xmm0 = 32,
- gdb_xmm1 = 33,
- gdb_xmm2 = 34,
- gdb_xmm3 = 35,
- gdb_xmm4 = 36,
- gdb_xmm5 = 37,
- gdb_xmm6 = 38,
- gdb_xmm7 = 39,
- gdb_mxcsr = 40,
- gdb_mm0 = 41,
- gdb_mm1 = 42,
- gdb_mm2 = 43,
- gdb_mm3 = 44,
- gdb_mm4 = 45,
- gdb_mm5 = 46,
- gdb_mm6 = 47,
- gdb_mm7 = 48
-};
-
-RegisterContextDarwin_i386::RegisterContextDarwin_i386 (Thread &thread, uint32_t concrete_frame_idx) :
- RegisterContext(thread, concrete_frame_idx),
- gpr(),
- fpu(),
- exc()
-{
- uint32_t i;
- for (i=0; i<kNumErrors; i++)
- {
- gpr_errs[i] = -1;
- fpu_errs[i] = -1;
- exc_errs[i] = -1;
- }
-}
-
-RegisterContextDarwin_i386::~RegisterContextDarwin_i386()
-{
-}
-
-
#define GPR_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::GPR, reg))
#define FPU_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::FPU, reg) + sizeof (RegisterContextDarwin_i386::GPR))
@@ -224,42 +151,42 @@ RegisterContextDarwin_i386::~RegisterContextDarwin_i386()
// sizes and offsets.
#define DEFINE_GPR(reg, alt) #reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex
#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex
-#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL
+#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_##reg##i }, NULL, NULL
#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextDarwin_i386::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex
#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_i386::GPR) + sizeof (RegisterContextDarwin_i386::FPU) + sizeof (RegisterContextDarwin_i386::EXC))
static RegisterInfo g_register_infos[] =
{
-// Macro auto defines most stuff GCC DWARF GENERIC GDB LLDB VALUE REGS INVALIDATE REGS
+// Macro auto defines most stuff eh_frame DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVALIDATE REGS
// =============================== ======================= =================== ========================= ================== ================= ========== ===============
- { DEFINE_GPR(eax , NULL) , { gcc_eax , dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , gpr_eax }, NULL, NULL},
- { DEFINE_GPR(ebx , NULL) , { gcc_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , gpr_ebx }, NULL, NULL},
- { DEFINE_GPR(ecx , NULL) , { gcc_ecx , dwarf_ecx , LLDB_INVALID_REGNUM , gdb_ecx , gpr_ecx }, NULL, NULL},
- { DEFINE_GPR(edx , NULL) , { gcc_edx , dwarf_edx , LLDB_INVALID_REGNUM , gdb_edx , gpr_edx }, NULL, NULL},
- { DEFINE_GPR(edi , NULL) , { gcc_edi , dwarf_edi , LLDB_INVALID_REGNUM , gdb_edi , gpr_edi }, NULL, NULL},
- { DEFINE_GPR(esi , NULL) , { gcc_esi , dwarf_esi , LLDB_INVALID_REGNUM , gdb_esi , gpr_esi }, NULL, NULL},
- { DEFINE_GPR(ebp , "fp") , { gcc_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , gpr_ebp }, NULL, NULL},
- { DEFINE_GPR(esp , "sp") , { gcc_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , gpr_esp }, NULL, NULL},
- { DEFINE_GPR(ss , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ss , gpr_ss }, NULL, NULL},
- { DEFINE_GPR(eflags , "flags") , { gcc_eflags , dwarf_eflags , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , gpr_eflags }, NULL, NULL},
- { DEFINE_GPR(eip , "pc") , { gcc_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , gpr_eip }, NULL, NULL},
- { DEFINE_GPR(cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_cs , gpr_cs }, NULL, NULL},
- { DEFINE_GPR(ds , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ds , gpr_ds }, NULL, NULL},
- { DEFINE_GPR(es , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_es , gpr_es }, NULL, NULL},
- { DEFINE_GPR(fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fs , gpr_fs }, NULL, NULL},
- { DEFINE_GPR(gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gs , gpr_gs }, NULL, NULL},
-
- { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fcw , fpu_fcw }, NULL, NULL},
- { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fsw , fpu_fsw }, NULL, NULL},
- { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ftw , fpu_ftw }, NULL, NULL},
- { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fop , fpu_fop }, NULL, NULL},
- { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ip , fpu_ip }, NULL, NULL},
- { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_cs , fpu_cs }, NULL, NULL},
- { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_dp , fpu_dp }, NULL, NULL},
- { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ds , fpu_ds }, NULL, NULL},
- { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_mxcsr , fpu_mxcsr }, NULL, NULL},
- { DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsrmask}, NULL, NULL},
+ { DEFINE_GPR(eax , NULL) , { ehframe_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_eax }, NULL, NULL},
+ { DEFINE_GPR(ebx , NULL) , { ehframe_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ebx }, NULL, NULL},
+ { DEFINE_GPR(ecx , NULL) , { ehframe_ecx , dwarf_ecx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ecx }, NULL, NULL},
+ { DEFINE_GPR(edx , NULL) , { ehframe_edx , dwarf_edx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_edx }, NULL, NULL},
+ { DEFINE_GPR(edi , NULL) , { ehframe_edi , dwarf_edi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_edi }, NULL, NULL},
+ { DEFINE_GPR(esi , NULL) , { ehframe_esi , dwarf_esi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_esi }, NULL, NULL},
+ { DEFINE_GPR(ebp , "fp") , { ehframe_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, gpr_ebp }, NULL, NULL},
+ { DEFINE_GPR(esp , "sp") , { ehframe_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, gpr_esp }, NULL, NULL},
+ { DEFINE_GPR(ss , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ss }, NULL, NULL},
+ { DEFINE_GPR(eflags , "flags") , { ehframe_eflags , dwarf_eflags , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, gpr_eflags }, NULL, NULL},
+ { DEFINE_GPR(eip , "pc") , { ehframe_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, gpr_eip }, NULL, NULL},
+ { DEFINE_GPR(cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_cs }, NULL, NULL},
+ { DEFINE_GPR(ds , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ds }, NULL, NULL},
+ { DEFINE_GPR(es , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_es }, NULL, NULL},
+ { DEFINE_GPR(fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_fs }, NULL, NULL},
+ { DEFINE_GPR(gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_gs }, NULL, NULL},
+
+ { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fcw }, NULL, NULL},
+ { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fsw }, NULL, NULL},
+ { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ftw }, NULL, NULL},
+ { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fop }, NULL, NULL},
+ { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ip }, NULL, NULL},
+ { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_cs }, NULL, NULL},
+ { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_dp }, NULL, NULL},
+ { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ds }, NULL, NULL},
+ { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsr }, NULL, NULL},
+ { DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsrmask}, NULL, NULL},
{ DEFINE_FPU_VECT(stmm,0) },
{ DEFINE_FPU_VECT(stmm,1) },
{ DEFINE_FPU_VECT(stmm,2) },
@@ -277,13 +204,33 @@ static RegisterInfo g_register_infos[] =
{ DEFINE_FPU_VECT(xmm,6) },
{ DEFINE_FPU_VECT(xmm,7) },
- { DEFINE_EXC(trapno) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_trapno }, NULL, NULL},
- { DEFINE_EXC(err) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_err }, NULL, NULL},
- { DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_faultvaddr }, NULL, NULL}
+ { DEFINE_EXC(trapno) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_trapno }, NULL, NULL},
+ { DEFINE_EXC(err) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_err }, NULL, NULL},
+ { DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_faultvaddr }, NULL, NULL}
};
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+RegisterContextDarwin_i386::RegisterContextDarwin_i386 (Thread &thread, uint32_t concrete_frame_idx) :
+ RegisterContext(thread, concrete_frame_idx),
+ gpr(),
+ fpu(),
+ exc()
+{
+ uint32_t i;
+ for (i=0; i<kNumErrors; i++)
+ {
+ gpr_errs[i] = -1;
+ fpu_errs[i] = -1;
+ exc_errs[i] = -1;
+ }
+}
+
+RegisterContextDarwin_i386::~RegisterContextDarwin_i386()
+{
+}
+
+
void
RegisterContextDarwin_i386::InvalidateAllRegisters ()
{
@@ -859,7 +806,7 @@ RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber (lldb::RegisterK
break;
}
}
- else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+ else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF)
{
switch (reg)
{
@@ -893,55 +840,6 @@ RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber (lldb::RegisterK
break;
}
}
- else if (kind == eRegisterKindGDB)
- {
- switch (reg)
- {
- case gdb_eax : return gpr_eax;
- case gdb_ebx : return gpr_ebx;
- case gdb_ecx : return gpr_ecx;
- case gdb_edx : return gpr_edx;
- case gdb_esi : return gpr_esi;
- case gdb_edi : return gpr_edi;
- case gdb_ebp : return gpr_ebp;
- case gdb_esp : return gpr_esp;
- case gdb_eip : return gpr_eip;
- case gdb_eflags : return gpr_eflags;
- case gdb_cs : return gpr_cs;
- case gdb_ss : return gpr_ss;
- case gdb_ds : return gpr_ds;
- case gdb_es : return gpr_es;
- case gdb_fs : return gpr_fs;
- case gdb_gs : return gpr_gs;
- case gdb_stmm0 : return fpu_stmm0;
- case gdb_stmm1 : return fpu_stmm1;
- case gdb_stmm2 : return fpu_stmm2;
- case gdb_stmm3 : return fpu_stmm3;
- case gdb_stmm4 : return fpu_stmm4;
- case gdb_stmm5 : return fpu_stmm5;
- case gdb_stmm6 : return fpu_stmm6;
- case gdb_stmm7 : return fpu_stmm7;
- case gdb_fctrl : return fpu_fctrl;
- case gdb_fstat : return fpu_fstat;
- case gdb_ftag : return fpu_ftag;
- case gdb_fiseg : return fpu_fiseg;
- case gdb_fioff : return fpu_fioff;
- case gdb_foseg : return fpu_foseg;
- case gdb_fooff : return fpu_fooff;
- case gdb_fop : return fpu_fop;
- case gdb_xmm0 : return fpu_xmm0;
- case gdb_xmm1 : return fpu_xmm1;
- case gdb_xmm2 : return fpu_xmm2;
- case gdb_xmm3 : return fpu_xmm3;
- case gdb_xmm4 : return fpu_xmm4;
- case gdb_xmm5 : return fpu_xmm5;
- case gdb_xmm6 : return fpu_xmm6;
- case gdb_xmm7 : return fpu_xmm7;
- case gdb_mxcsr : return fpu_mxcsr;
- default:
- break;
- }
- }
else if (kind == eRegisterKindLLDB)
{
return reg;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
index 1d03feb..9568b03 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
@@ -20,45 +20,45 @@
class RegisterContextDarwin_i386 : public lldb_private::RegisterContext
{
public:
-
RegisterContextDarwin_i386(lldb_private::Thread &thread,
- uint32_t concrete_frame_idx);
+ uint32_t concrete_frame_idx);
- virtual
- ~RegisterContextDarwin_i386();
+ ~RegisterContextDarwin_i386() override;
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
- virtual bool
- HardwareSingleStep (bool enable);
+ bool
+ HardwareSingleStep(bool enable) override;
struct GPR
{
@@ -121,7 +121,6 @@ public:
};
protected:
-
enum
{
GPRRegSet = 1,
@@ -266,4 +265,4 @@ protected:
GetRegisterInfos ();
};
-#endif // liblldb_RegisterContextDarwin_i386_h_
+#endif // liblldb_RegisterContextDarwin_i386_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index 54124d1..aee6e12 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -111,132 +111,52 @@ enum
fpu_fooff = fpu_dp
};
-enum gcc_dwarf_regnums
-{
- gcc_dwarf_gpr_rax = 0,
- gcc_dwarf_gpr_rdx,
- gcc_dwarf_gpr_rcx,
- gcc_dwarf_gpr_rbx,
- gcc_dwarf_gpr_rsi,
- gcc_dwarf_gpr_rdi,
- gcc_dwarf_gpr_rbp,
- gcc_dwarf_gpr_rsp,
- gcc_dwarf_gpr_r8,
- gcc_dwarf_gpr_r9,
- gcc_dwarf_gpr_r10,
- gcc_dwarf_gpr_r11,
- gcc_dwarf_gpr_r12,
- gcc_dwarf_gpr_r13,
- gcc_dwarf_gpr_r14,
- gcc_dwarf_gpr_r15,
- gcc_dwarf_gpr_rip,
- gcc_dwarf_fpu_xmm0,
- gcc_dwarf_fpu_xmm1,
- gcc_dwarf_fpu_xmm2,
- gcc_dwarf_fpu_xmm3,
- gcc_dwarf_fpu_xmm4,
- gcc_dwarf_fpu_xmm5,
- gcc_dwarf_fpu_xmm6,
- gcc_dwarf_fpu_xmm7,
- gcc_dwarf_fpu_xmm8,
- gcc_dwarf_fpu_xmm9,
- gcc_dwarf_fpu_xmm10,
- gcc_dwarf_fpu_xmm11,
- gcc_dwarf_fpu_xmm12,
- gcc_dwarf_fpu_xmm13,
- gcc_dwarf_fpu_xmm14,
- gcc_dwarf_fpu_xmm15,
- gcc_dwarf_fpu_stmm0,
- gcc_dwarf_fpu_stmm1,
- gcc_dwarf_fpu_stmm2,
- gcc_dwarf_fpu_stmm3,
- gcc_dwarf_fpu_stmm4,
- gcc_dwarf_fpu_stmm5,
- gcc_dwarf_fpu_stmm6,
- gcc_dwarf_fpu_stmm7
-
-};
+enum ehframe_dwarf_regnums
+{
+ ehframe_dwarf_gpr_rax = 0,
+ ehframe_dwarf_gpr_rdx,
+ ehframe_dwarf_gpr_rcx,
+ ehframe_dwarf_gpr_rbx,
+ ehframe_dwarf_gpr_rsi,
+ ehframe_dwarf_gpr_rdi,
+ ehframe_dwarf_gpr_rbp,
+ ehframe_dwarf_gpr_rsp,
+ ehframe_dwarf_gpr_r8,
+ ehframe_dwarf_gpr_r9,
+ ehframe_dwarf_gpr_r10,
+ ehframe_dwarf_gpr_r11,
+ ehframe_dwarf_gpr_r12,
+ ehframe_dwarf_gpr_r13,
+ ehframe_dwarf_gpr_r14,
+ ehframe_dwarf_gpr_r15,
+ ehframe_dwarf_gpr_rip,
+ ehframe_dwarf_fpu_xmm0,
+ ehframe_dwarf_fpu_xmm1,
+ ehframe_dwarf_fpu_xmm2,
+ ehframe_dwarf_fpu_xmm3,
+ ehframe_dwarf_fpu_xmm4,
+ ehframe_dwarf_fpu_xmm5,
+ ehframe_dwarf_fpu_xmm6,
+ ehframe_dwarf_fpu_xmm7,
+ ehframe_dwarf_fpu_xmm8,
+ ehframe_dwarf_fpu_xmm9,
+ ehframe_dwarf_fpu_xmm10,
+ ehframe_dwarf_fpu_xmm11,
+ ehframe_dwarf_fpu_xmm12,
+ ehframe_dwarf_fpu_xmm13,
+ ehframe_dwarf_fpu_xmm14,
+ ehframe_dwarf_fpu_xmm15,
+ ehframe_dwarf_fpu_stmm0,
+ ehframe_dwarf_fpu_stmm1,
+ ehframe_dwarf_fpu_stmm2,
+ ehframe_dwarf_fpu_stmm3,
+ ehframe_dwarf_fpu_stmm4,
+ ehframe_dwarf_fpu_stmm5,
+ ehframe_dwarf_fpu_stmm6,
+ ehframe_dwarf_fpu_stmm7
-enum gdb_regnums
-{
- gdb_gpr_rax = 0,
- gdb_gpr_rbx = 1,
- gdb_gpr_rcx = 2,
- gdb_gpr_rdx = 3,
- gdb_gpr_rsi = 4,
- gdb_gpr_rdi = 5,
- gdb_gpr_rbp = 6,
- gdb_gpr_rsp = 7,
- gdb_gpr_r8 = 8,
- gdb_gpr_r9 = 9,
- gdb_gpr_r10 = 10,
- gdb_gpr_r11 = 11,
- gdb_gpr_r12 = 12,
- gdb_gpr_r13 = 13,
- gdb_gpr_r14 = 14,
- gdb_gpr_r15 = 15,
- gdb_gpr_rip = 16,
- gdb_gpr_rflags = 17,
- gdb_gpr_cs = 18,
- gdb_gpr_ss = 19,
- gdb_gpr_ds = 20,
- gdb_gpr_es = 21,
- gdb_gpr_fs = 22,
- gdb_gpr_gs = 23,
- gdb_fpu_stmm0 = 24,
- gdb_fpu_stmm1 = 25,
- gdb_fpu_stmm2 = 26,
- gdb_fpu_stmm3 = 27,
- gdb_fpu_stmm4 = 28,
- gdb_fpu_stmm5 = 29,
- gdb_fpu_stmm6 = 30,
- gdb_fpu_stmm7 = 31,
- gdb_fpu_fctrl = 32, gdb_fpu_fcw = gdb_fpu_fctrl,
- gdb_fpu_fstat = 33, gdb_fpu_fsw = gdb_fpu_fstat,
- gdb_fpu_ftag = 34, gdb_fpu_ftw = gdb_fpu_ftag,
- gdb_fpu_fiseg = 35, gdb_fpu_cs = gdb_fpu_fiseg,
- gdb_fpu_fioff = 36, gdb_fpu_ip = gdb_fpu_fioff,
- gdb_fpu_foseg = 37, gdb_fpu_ds = gdb_fpu_foseg,
- gdb_fpu_fooff = 38, gdb_fpu_dp = gdb_fpu_fooff,
- gdb_fpu_fop = 39,
- gdb_fpu_xmm0 = 40,
- gdb_fpu_xmm1 = 41,
- gdb_fpu_xmm2 = 42,
- gdb_fpu_xmm3 = 43,
- gdb_fpu_xmm4 = 44,
- gdb_fpu_xmm5 = 45,
- gdb_fpu_xmm6 = 46,
- gdb_fpu_xmm7 = 47,
- gdb_fpu_xmm8 = 48,
- gdb_fpu_xmm9 = 49,
- gdb_fpu_xmm10 = 50,
- gdb_fpu_xmm11 = 51,
- gdb_fpu_xmm12 = 52,
- gdb_fpu_xmm13 = 53,
- gdb_fpu_xmm14 = 54,
- gdb_fpu_xmm15 = 55,
- gdb_fpu_mxcsr = 56
};
-RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64 (Thread &thread, uint32_t concrete_frame_idx) :
- RegisterContext (thread, concrete_frame_idx),
- gpr(),
- fpu(),
- exc()
-{
- uint32_t i;
- for (i=0; i<kNumErrors; i++)
- {
- gpr_errs[i] = -1;
- fpu_errs[i] = -1;
- exc_errs[i] = -1;
- }
-}
-
-RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64()
-{
-}
-
#define GPR_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::GPR, reg))
#define FPU_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::FPU, reg) + sizeof (RegisterContextDarwin_x86_64::GPR))
#define EXC_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::EXC, reg) + sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::FPU))
@@ -247,7 +167,7 @@ RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64()
// sizes and offsets.
#define DEFINE_GPR(reg, alt) #reg, alt, sizeof(((RegisterContextDarwin_x86_64::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex
#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex
-#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL
+#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { ehframe_dwarf_fpu_##reg##i, ehframe_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_##reg##i }, NULL, NULL
#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex
#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::FPU) + sizeof (RegisterContextDarwin_x86_64::EXC))
@@ -255,39 +175,39 @@ RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64()
// General purpose registers for 64 bit
static RegisterInfo g_register_infos[] =
{
-// Macro auto defines most stuff GCC DWARF GENERIC GDB LLDB VALUE REGS INVALIDATE REGS
-// =============================== ====================== =================== ========================== ==================== =================== ========== ===============
- { DEFINE_GPR (rax , NULL) , { gcc_dwarf_gpr_rax , gcc_dwarf_gpr_rax , LLDB_INVALID_REGNUM , gdb_gpr_rax , gpr_rax }, NULL, NULL},
- { DEFINE_GPR (rbx , NULL) , { gcc_dwarf_gpr_rbx , gcc_dwarf_gpr_rbx , LLDB_INVALID_REGNUM , gdb_gpr_rbx , gpr_rbx }, NULL, NULL},
- { DEFINE_GPR (rcx , NULL) , { gcc_dwarf_gpr_rcx , gcc_dwarf_gpr_rcx , LLDB_INVALID_REGNUM , gdb_gpr_rcx , gpr_rcx }, NULL, NULL},
- { DEFINE_GPR (rdx , NULL) , { gcc_dwarf_gpr_rdx , gcc_dwarf_gpr_rdx , LLDB_INVALID_REGNUM , gdb_gpr_rdx , gpr_rdx }, NULL, NULL},
- { DEFINE_GPR (rdi , NULL) , { gcc_dwarf_gpr_rdi , gcc_dwarf_gpr_rdi , LLDB_INVALID_REGNUM , gdb_gpr_rdi , gpr_rdi }, NULL, NULL},
- { DEFINE_GPR (rsi , NULL) , { gcc_dwarf_gpr_rsi , gcc_dwarf_gpr_rsi , LLDB_INVALID_REGNUM , gdb_gpr_rsi , gpr_rsi }, NULL, NULL},
- { DEFINE_GPR (rbp , "fp") , { gcc_dwarf_gpr_rbp , gcc_dwarf_gpr_rbp , LLDB_REGNUM_GENERIC_FP , gdb_gpr_rbp , gpr_rbp }, NULL, NULL},
- { DEFINE_GPR (rsp , "sp") , { gcc_dwarf_gpr_rsp , gcc_dwarf_gpr_rsp , LLDB_REGNUM_GENERIC_SP , gdb_gpr_rsp , gpr_rsp }, NULL, NULL},
- { DEFINE_GPR (r8 , NULL) , { gcc_dwarf_gpr_r8 , gcc_dwarf_gpr_r8 , LLDB_INVALID_REGNUM , gdb_gpr_r8 , gpr_r8 }, NULL, NULL},
- { DEFINE_GPR (r9 , NULL) , { gcc_dwarf_gpr_r9 , gcc_dwarf_gpr_r9 , LLDB_INVALID_REGNUM , gdb_gpr_r9 , gpr_r9 }, NULL, NULL},
- { DEFINE_GPR (r10 , NULL) , { gcc_dwarf_gpr_r10 , gcc_dwarf_gpr_r10 , LLDB_INVALID_REGNUM , gdb_gpr_r10 , gpr_r10 }, NULL, NULL},
- { DEFINE_GPR (r11 , NULL) , { gcc_dwarf_gpr_r11 , gcc_dwarf_gpr_r11 , LLDB_INVALID_REGNUM , gdb_gpr_r11 , gpr_r11 }, NULL, NULL},
- { DEFINE_GPR (r12 , NULL) , { gcc_dwarf_gpr_r12 , gcc_dwarf_gpr_r12 , LLDB_INVALID_REGNUM , gdb_gpr_r12 , gpr_r12 }, NULL, NULL},
- { DEFINE_GPR (r13 , NULL) , { gcc_dwarf_gpr_r13 , gcc_dwarf_gpr_r13 , LLDB_INVALID_REGNUM , gdb_gpr_r13 , gpr_r13 }, NULL, NULL},
- { DEFINE_GPR (r14 , NULL) , { gcc_dwarf_gpr_r14 , gcc_dwarf_gpr_r14 , LLDB_INVALID_REGNUM , gdb_gpr_r14 , gpr_r14 }, NULL, NULL},
- { DEFINE_GPR (r15 , NULL) , { gcc_dwarf_gpr_r15 , gcc_dwarf_gpr_r15 , LLDB_INVALID_REGNUM , gdb_gpr_r15 , gpr_r15 }, NULL, NULL},
- { DEFINE_GPR (rip , "pc") , { gcc_dwarf_gpr_rip , gcc_dwarf_gpr_rip , LLDB_REGNUM_GENERIC_PC , gdb_gpr_rip , gpr_rip }, NULL, NULL},
- { DEFINE_GPR (rflags, "flags") , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags , gpr_rflags }, NULL, NULL},
- { DEFINE_GPR (cs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gpr_cs , gpr_cs }, NULL, NULL},
- { DEFINE_GPR (fs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gpr_fs , gpr_fs }, NULL, NULL},
- { DEFINE_GPR (gs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gpr_gs , gpr_gs }, NULL, NULL},
-
- { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_fcw , fpu_fcw }, NULL, NULL},
- { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_fsw , fpu_fsw }, NULL, NULL},
- { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_ftw , fpu_ftw }, NULL, NULL},
- { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_fop , fpu_fop }, NULL, NULL},
- { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_ip , fpu_ip }, NULL, NULL},
- { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_cs , fpu_cs }, NULL, NULL},
- { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_dp , fpu_dp }, NULL, NULL},
- { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_ds , fpu_ds }, NULL, NULL},
- { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_mxcsr , fpu_mxcsr }, NULL, NULL},
+// Macro auto defines most stuff EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVALIDATE REGS
+// =============================== ====================== =================== ========================== ==================== =================== ========== ===============
+ { DEFINE_GPR (rax , NULL) , { ehframe_dwarf_gpr_rax , ehframe_dwarf_gpr_rax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rax }, NULL, NULL},
+ { DEFINE_GPR (rbx , NULL) , { ehframe_dwarf_gpr_rbx , ehframe_dwarf_gpr_rbx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rbx }, NULL, NULL},
+ { DEFINE_GPR (rcx , NULL) , { ehframe_dwarf_gpr_rcx , ehframe_dwarf_gpr_rcx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rcx }, NULL, NULL},
+ { DEFINE_GPR (rdx , NULL) , { ehframe_dwarf_gpr_rdx , ehframe_dwarf_gpr_rdx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rdx }, NULL, NULL},
+ { DEFINE_GPR (rdi , NULL) , { ehframe_dwarf_gpr_rdi , ehframe_dwarf_gpr_rdi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rdi }, NULL, NULL},
+ { DEFINE_GPR (rsi , NULL) , { ehframe_dwarf_gpr_rsi , ehframe_dwarf_gpr_rsi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rsi }, NULL, NULL},
+ { DEFINE_GPR (rbp , "fp") , { ehframe_dwarf_gpr_rbp , ehframe_dwarf_gpr_rbp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, gpr_rbp }, NULL, NULL},
+ { DEFINE_GPR (rsp , "sp") , { ehframe_dwarf_gpr_rsp , ehframe_dwarf_gpr_rsp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, gpr_rsp }, NULL, NULL},
+ { DEFINE_GPR (r8 , NULL) , { ehframe_dwarf_gpr_r8 , ehframe_dwarf_gpr_r8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r8 }, NULL, NULL},
+ { DEFINE_GPR (r9 , NULL) , { ehframe_dwarf_gpr_r9 , ehframe_dwarf_gpr_r9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r9 }, NULL, NULL},
+ { DEFINE_GPR (r10 , NULL) , { ehframe_dwarf_gpr_r10 , ehframe_dwarf_gpr_r10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r10 }, NULL, NULL},
+ { DEFINE_GPR (r11 , NULL) , { ehframe_dwarf_gpr_r11 , ehframe_dwarf_gpr_r11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r11 }, NULL, NULL},
+ { DEFINE_GPR (r12 , NULL) , { ehframe_dwarf_gpr_r12 , ehframe_dwarf_gpr_r12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r12 }, NULL, NULL},
+ { DEFINE_GPR (r13 , NULL) , { ehframe_dwarf_gpr_r13 , ehframe_dwarf_gpr_r13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r13 }, NULL, NULL},
+ { DEFINE_GPR (r14 , NULL) , { ehframe_dwarf_gpr_r14 , ehframe_dwarf_gpr_r14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r14 }, NULL, NULL},
+ { DEFINE_GPR (r15 , NULL) , { ehframe_dwarf_gpr_r15 , ehframe_dwarf_gpr_r15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r15 }, NULL, NULL},
+ { DEFINE_GPR (rip , "pc") , { ehframe_dwarf_gpr_rip , ehframe_dwarf_gpr_rip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, gpr_rip }, NULL, NULL},
+ { DEFINE_GPR (rflags, "flags") , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_rflags }, NULL, NULL},
+ { DEFINE_GPR (cs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_cs }, NULL, NULL},
+ { DEFINE_GPR (fs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_fs }, NULL, NULL},
+ { DEFINE_GPR (gs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_gs }, NULL, NULL},
+
+ { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fcw }, NULL, NULL},
+ { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fsw }, NULL, NULL},
+ { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ftw }, NULL, NULL},
+ { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fop }, NULL, NULL},
+ { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ip }, NULL, NULL},
+ { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_cs }, NULL, NULL},
+ { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_dp }, NULL, NULL},
+ { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ds }, NULL, NULL},
+ { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsr }, NULL, NULL},
{ DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsrmask }, NULL, NULL},
{ DEFINE_FPU_VECT(stmm,0) },
{ DEFINE_FPU_VECT(stmm,1) },
@@ -321,6 +241,25 @@ static RegisterInfo g_register_infos[] =
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64 (Thread &thread, uint32_t concrete_frame_idx) :
+ RegisterContext (thread, concrete_frame_idx),
+ gpr(),
+ fpu(),
+ exc()
+{
+ uint32_t i;
+ for (i=0; i<kNumErrors; i++)
+ {
+ gpr_errs[i] = -1;
+ fpu_errs[i] = -1;
+ exc_errs[i] = -1;
+ }
+}
+
+RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64()
+{
+}
+
void
RegisterContextDarwin_x86_64::InvalidateAllRegisters ()
@@ -687,7 +626,7 @@ RegisterContextDarwin_x86_64::ReadRegister (const RegisterInfo *reg_info,
case fpu_stmm5:
case fpu_stmm6:
case fpu_stmm7:
- value.SetBytes(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder());
+ value.SetBytes(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, endian::InlHostByteOrder());
break;
case fpu_xmm0:
@@ -706,7 +645,7 @@ RegisterContextDarwin_x86_64::ReadRegister (const RegisterInfo *reg_info,
case fpu_xmm13:
case fpu_xmm14:
case fpu_xmm15:
- value.SetBytes(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder());
+ value.SetBytes(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, endian::InlHostByteOrder());
break;
case exc_trapno:
@@ -919,116 +858,51 @@ RegisterContextDarwin_x86_64::ConvertRegisterKindToRegisterNumber (lldb::Registe
break;
}
}
- else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
- {
- switch (reg)
- {
- case gcc_dwarf_gpr_rax: return gpr_rax;
- case gcc_dwarf_gpr_rdx: return gpr_rdx;
- case gcc_dwarf_gpr_rcx: return gpr_rcx;
- case gcc_dwarf_gpr_rbx: return gpr_rbx;
- case gcc_dwarf_gpr_rsi: return gpr_rsi;
- case gcc_dwarf_gpr_rdi: return gpr_rdi;
- case gcc_dwarf_gpr_rbp: return gpr_rbp;
- case gcc_dwarf_gpr_rsp: return gpr_rsp;
- case gcc_dwarf_gpr_r8: return gpr_r8;
- case gcc_dwarf_gpr_r9: return gpr_r9;
- case gcc_dwarf_gpr_r10: return gpr_r10;
- case gcc_dwarf_gpr_r11: return gpr_r11;
- case gcc_dwarf_gpr_r12: return gpr_r12;
- case gcc_dwarf_gpr_r13: return gpr_r13;
- case gcc_dwarf_gpr_r14: return gpr_r14;
- case gcc_dwarf_gpr_r15: return gpr_r15;
- case gcc_dwarf_gpr_rip: return gpr_rip;
- case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
- case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
- case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
- case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
- case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
- case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
- case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
- case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
- case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
- case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
- case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
- case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
- case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
- case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
- case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
- case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
- case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
- case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
- case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
- case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
- case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
- case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
- case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
- case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
- default:
- break;
- }
- }
- else if (kind == eRegisterKindGDB)
+ else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF)
{
switch (reg)
{
- case gdb_gpr_rax : return gpr_rax;
- case gdb_gpr_rbx : return gpr_rbx;
- case gdb_gpr_rcx : return gpr_rcx;
- case gdb_gpr_rdx : return gpr_rdx;
- case gdb_gpr_rsi : return gpr_rsi;
- case gdb_gpr_rdi : return gpr_rdi;
- case gdb_gpr_rbp : return gpr_rbp;
- case gdb_gpr_rsp : return gpr_rsp;
- case gdb_gpr_r8 : return gpr_r8;
- case gdb_gpr_r9 : return gpr_r9;
- case gdb_gpr_r10 : return gpr_r10;
- case gdb_gpr_r11 : return gpr_r11;
- case gdb_gpr_r12 : return gpr_r12;
- case gdb_gpr_r13 : return gpr_r13;
- case gdb_gpr_r14 : return gpr_r14;
- case gdb_gpr_r15 : return gpr_r15;
- case gdb_gpr_rip : return gpr_rip;
- case gdb_gpr_rflags : return gpr_rflags;
- case gdb_gpr_cs : return gpr_cs;
- case gdb_gpr_ss : return gpr_gs; // HACK: For now for "ss", just copy what is in "gs"
- case gdb_gpr_ds : return gpr_gs; // HACK: For now for "ds", just copy what is in "gs"
- case gdb_gpr_es : return gpr_gs; // HACK: For now for "es", just copy what is in "gs"
- case gdb_gpr_fs : return gpr_fs;
- case gdb_gpr_gs : return gpr_gs;
- case gdb_fpu_stmm0 : return fpu_stmm0;
- case gdb_fpu_stmm1 : return fpu_stmm1;
- case gdb_fpu_stmm2 : return fpu_stmm2;
- case gdb_fpu_stmm3 : return fpu_stmm3;
- case gdb_fpu_stmm4 : return fpu_stmm4;
- case gdb_fpu_stmm5 : return fpu_stmm5;
- case gdb_fpu_stmm6 : return fpu_stmm6;
- case gdb_fpu_stmm7 : return fpu_stmm7;
- case gdb_fpu_fctrl : return fpu_fctrl;
- case gdb_fpu_fstat : return fpu_fstat;
- case gdb_fpu_ftag : return fpu_ftag;
- case gdb_fpu_fiseg : return fpu_fiseg;
- case gdb_fpu_fioff : return fpu_fioff;
- case gdb_fpu_foseg : return fpu_foseg;
- case gdb_fpu_fooff : return fpu_fooff;
- case gdb_fpu_fop : return fpu_fop;
- case gdb_fpu_xmm0 : return fpu_xmm0;
- case gdb_fpu_xmm1 : return fpu_xmm1;
- case gdb_fpu_xmm2 : return fpu_xmm2;
- case gdb_fpu_xmm3 : return fpu_xmm3;
- case gdb_fpu_xmm4 : return fpu_xmm4;
- case gdb_fpu_xmm5 : return fpu_xmm5;
- case gdb_fpu_xmm6 : return fpu_xmm6;
- case gdb_fpu_xmm7 : return fpu_xmm7;
- case gdb_fpu_xmm8 : return fpu_xmm8;
- case gdb_fpu_xmm9 : return fpu_xmm9;
- case gdb_fpu_xmm10 : return fpu_xmm10;
- case gdb_fpu_xmm11 : return fpu_xmm11;
- case gdb_fpu_xmm12 : return fpu_xmm12;
- case gdb_fpu_xmm13 : return fpu_xmm13;
- case gdb_fpu_xmm14 : return fpu_xmm14;
- case gdb_fpu_xmm15 : return fpu_xmm15;
- case gdb_fpu_mxcsr : return fpu_mxcsr;
+ case ehframe_dwarf_gpr_rax: return gpr_rax;
+ case ehframe_dwarf_gpr_rdx: return gpr_rdx;
+ case ehframe_dwarf_gpr_rcx: return gpr_rcx;
+ case ehframe_dwarf_gpr_rbx: return gpr_rbx;
+ case ehframe_dwarf_gpr_rsi: return gpr_rsi;
+ case ehframe_dwarf_gpr_rdi: return gpr_rdi;
+ case ehframe_dwarf_gpr_rbp: return gpr_rbp;
+ case ehframe_dwarf_gpr_rsp: return gpr_rsp;
+ case ehframe_dwarf_gpr_r8: return gpr_r8;
+ case ehframe_dwarf_gpr_r9: return gpr_r9;
+ case ehframe_dwarf_gpr_r10: return gpr_r10;
+ case ehframe_dwarf_gpr_r11: return gpr_r11;
+ case ehframe_dwarf_gpr_r12: return gpr_r12;
+ case ehframe_dwarf_gpr_r13: return gpr_r13;
+ case ehframe_dwarf_gpr_r14: return gpr_r14;
+ case ehframe_dwarf_gpr_r15: return gpr_r15;
+ case ehframe_dwarf_gpr_rip: return gpr_rip;
+ case ehframe_dwarf_fpu_xmm0: return fpu_xmm0;
+ case ehframe_dwarf_fpu_xmm1: return fpu_xmm1;
+ case ehframe_dwarf_fpu_xmm2: return fpu_xmm2;
+ case ehframe_dwarf_fpu_xmm3: return fpu_xmm3;
+ case ehframe_dwarf_fpu_xmm4: return fpu_xmm4;
+ case ehframe_dwarf_fpu_xmm5: return fpu_xmm5;
+ case ehframe_dwarf_fpu_xmm6: return fpu_xmm6;
+ case ehframe_dwarf_fpu_xmm7: return fpu_xmm7;
+ case ehframe_dwarf_fpu_xmm8: return fpu_xmm8;
+ case ehframe_dwarf_fpu_xmm9: return fpu_xmm9;
+ case ehframe_dwarf_fpu_xmm10: return fpu_xmm10;
+ case ehframe_dwarf_fpu_xmm11: return fpu_xmm11;
+ case ehframe_dwarf_fpu_xmm12: return fpu_xmm12;
+ case ehframe_dwarf_fpu_xmm13: return fpu_xmm13;
+ case ehframe_dwarf_fpu_xmm14: return fpu_xmm14;
+ case ehframe_dwarf_fpu_xmm15: return fpu_xmm15;
+ case ehframe_dwarf_fpu_stmm0: return fpu_stmm0;
+ case ehframe_dwarf_fpu_stmm1: return fpu_stmm1;
+ case ehframe_dwarf_fpu_stmm2: return fpu_stmm2;
+ case ehframe_dwarf_fpu_stmm3: return fpu_stmm3;
+ case ehframe_dwarf_fpu_stmm4: return fpu_stmm4;
+ case ehframe_dwarf_fpu_stmm5: return fpu_stmm5;
+ case ehframe_dwarf_fpu_stmm6: return fpu_stmm6;
+ case ehframe_dwarf_fpu_stmm7: return fpu_stmm7;
default:
break;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
index 09e35e9..ed627e1 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
@@ -23,41 +23,42 @@ public:
RegisterContextDarwin_x86_64 (lldb_private::Thread &thread,
uint32_t concrete_frame_idx);
- virtual
- ~RegisterContextDarwin_x86_64();
+ ~RegisterContextDarwin_x86_64() override;
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
- virtual bool
- HardwareSingleStep (bool enable);
+ bool
+ HardwareSingleStep(bool enable) override;
struct GPR
{
@@ -268,7 +269,6 @@ protected:
static const lldb_private::RegisterInfo *
GetRegisterInfos ();
-
};
-#endif // liblldb_RegisterContextDarwin_x86_64_h_
+#endif // liblldb_RegisterContextDarwin_x86_64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp
index 329b0a7..0859e4e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp
@@ -51,10 +51,10 @@ RegisterContext (thread, concrete_frame_idx)
m_pc_reg_info.format = eFormatPointer;
m_pc_reg_info.invalidate_regs = NULL;
m_pc_reg_info.value_regs = NULL;
- m_pc_reg_info.kinds[eRegisterKindGCC] = LLDB_INVALID_REGNUM;
+ m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
- m_pc_reg_info.kinds[eRegisterKindGDB] = LLDB_INVALID_REGNUM;
+ m_pc_reg_info.kinds[eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h
index ddf4667..9f6a8dc 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h
@@ -10,8 +10,12 @@
#ifndef lldb_RegisterContextDummy_h_
#define lldb_RegisterContextDummy_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -25,42 +29,39 @@ public:
RegisterContextDummy (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size);
- ///
- // pure virtual functions from the base class that we must implement
- ///
+ ~RegisterContextDummy() override;
- virtual
- ~RegisterContextDummy ();
+ void
+ InvalidateAllRegisters() override;
- virtual void
- InvalidateAllRegisters ();
+ size_t
+ GetRegisterCount() override;
- virtual size_t
- GetRegisterCount ();
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ size_t
+ GetRegisterSetCount() override;
- virtual size_t
- GetRegisterSetCount ();
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t reg_set);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
-
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
private:
//------------------------------------------------------------------
@@ -72,6 +73,7 @@ private:
DISALLOW_COPY_AND_ASSIGN (RegisterContextDummy);
};
+
} // namespace lldb_private
-#endif // lldb_RegisterContextDummy_h_
+#endif // lldb_RegisterContextDummy_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp
index 8005a63..a507dad 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp
@@ -23,6 +23,7 @@ using namespace lldb_private;
// http://svnweb.freebsd.org/base/head/sys/arm/include/reg.h
#define GPR_OFFSET(idx) ((idx) * 4)
#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextFreeBSD_arm::GPR))
+#define FPSCR_OFFSET (LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm::FPU, fpscr) + sizeof (RegisterContextFreeBSD_arm::GPR))
#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextFreeBSD_arm::GPR) + sizeof (RegisterContextFreeBSD_arm::FPU))
#define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm::DBG, reg) + sizeof (RegisterContextFreeBSD_arm::GPR) + sizeof (RegisterContextFreeBSD_arm::FPU) + sizeof (RegisterContextFreeBSD_arm::EXC)))
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h
index c4287e9..f2d9364 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h
@@ -12,7 +12,6 @@
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
-#include "RegisterContextPOSIX.h"
#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_arm
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h
index 249027a..cfdae4d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextFreeBSD_arm64_H_
#define liblldb_RegisterContextFreeBSD_arm64_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_arm64:
public lldb_private::RegisterInfoInterface
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h
index 62792c0..9527fc03 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextFreeBSD_i386_H_
#define liblldb_RegisterContextFreeBSD_i386_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_i386
: public lldb_private::RegisterInfoInterface
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h
index f9a3ce0..5c042af 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextFreeBSD_mips64_H_
#define liblldb_RegisterContextFreeBSD_mips64_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_mips64:
public lldb_private::RegisterInfoInterface
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
index b907fe9..930683f8 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
@@ -7,17 +7,21 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextFreeBSD_powerpc_H_
-#define liblldb_RegisterContextFreeBSD_powerpc_H_
+#ifndef liblldb_RegisterContextFreeBSD_powerpc_h_
+#define liblldb_RegisterContextFreeBSD_powerpc_h_
-#include "RegisterContextPOSIX.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_powerpc:
public lldb_private::RegisterInfoInterface
{
public:
RegisterContextFreeBSD_powerpc(const lldb_private::ArchSpec &target_arch);
- virtual ~RegisterContextFreeBSD_powerpc();
+ ~RegisterContextFreeBSD_powerpc() override;
size_t
GetGPRSize() const override;
@@ -34,7 +38,7 @@ class RegisterContextFreeBSD_powerpc32:
{
public:
RegisterContextFreeBSD_powerpc32(const lldb_private::ArchSpec &target_arch);
- virtual ~RegisterContextFreeBSD_powerpc32();
+ ~RegisterContextFreeBSD_powerpc32() override;
size_t
GetGPRSize() const override;
@@ -51,7 +55,7 @@ class RegisterContextFreeBSD_powerpc64:
{
public:
RegisterContextFreeBSD_powerpc64(const lldb_private::ArchSpec &target_arch);
- virtual ~RegisterContextFreeBSD_powerpc64();
+ ~RegisterContextFreeBSD_powerpc64() override;
size_t
GetGPRSize() const override;
@@ -63,4 +67,4 @@ public:
GetRegisterCount() const override;
};
-#endif
+#endif // liblldb_RegisterContextFreeBSD_powerpc_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h
index 21fbdb4..e739fa5 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_
#define liblldb_RegisterContextFreeBSD_x86_64_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_x86_64:
public lldb_private::RegisterInfoInterface
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp
index 3c37010..9d21813 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp
@@ -52,10 +52,10 @@ RegisterContext (thread, concrete_frame_idx),
m_pc_reg_info.format = eFormatPointer;
m_pc_reg_info.invalidate_regs = NULL;
m_pc_reg_info.value_regs = NULL;
- m_pc_reg_info.kinds[eRegisterKindGCC] = LLDB_INVALID_REGNUM;
+ m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
- m_pc_reg_info.kinds[eRegisterKindGDB] = LLDB_INVALID_REGNUM;
+ m_pc_reg_info.kinds[eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h
index 04842c6..3f44a1f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h
@@ -10,8 +10,12 @@
#ifndef lldb_RegisterContextHistory_h_
#define lldb_RegisterContextHistory_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -25,42 +29,39 @@ public:
RegisterContextHistory (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size, lldb::addr_t pc_value);
- ///
- // pure virtual functions from the base class that we must implement
- ///
+ ~RegisterContextHistory() override;
- virtual
- ~RegisterContextHistory ();
+ void
+ InvalidateAllRegisters() override;
- virtual void
- InvalidateAllRegisters ();
+ size_t
+ GetRegisterCount() override;
- virtual size_t
- GetRegisterCount ();
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ size_t
+ GetRegisterSetCount() override;
- virtual size_t
- GetRegisterSetCount ();
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t reg_set);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
-
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
private:
//------------------------------------------------------------------
@@ -76,4 +77,4 @@ private:
};
} // namespace lldb_private
-#endif // lldb_RegisterContextHistory_h_
+#endif // lldb_RegisterContextHistory_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 37b007c..efda0ed 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -17,6 +17,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/Function.h"
@@ -264,9 +265,32 @@ RegisterContextLLDB::InitializeZerothFrame()
if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))
{
- UnwindLogMsg ("could not read CFA register for this frame.");
- m_frame_type = eNotAValidFrame;
- return;
+ // Try the fall back unwind plan since the
+ // full unwind plan failed.
+ FuncUnwindersSP func_unwinders_sp;
+ UnwindPlanSP call_site_unwind_plan;
+ bool cfa_status = false;
+
+ if (m_sym_ctx_valid)
+ {
+ func_unwinders_sp = pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
+ }
+
+ if(func_unwinders_sp.get() != nullptr)
+ call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one);
+
+ if (call_site_unwind_plan.get() != nullptr)
+ {
+ m_fallback_unwind_plan_sp = call_site_unwind_plan;
+ if(TryFallbackUnwindPlan())
+ cfa_status = true;
+ }
+ if (!cfa_status)
+ {
+ UnwindLogMsg ("could not read CFA value for first frame.");
+ m_frame_type = eNotAValidFrame;
+ return;
+ }
}
UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 " using %s UnwindPlan",
@@ -634,28 +658,30 @@ bool
RegisterContextLLDB::CheckIfLoopingStack ()
{
// If we have a bad stack setup, we can get the same CFA value multiple times -- or even
- // more devious, we can actually oscillate between two CFA values. Detect that here and
+ // more devious, we can actually oscillate between two CFA values. Detect that here and
// break out to avoid a possible infinite loop in lldb trying to unwind the stack.
- addr_t next_frame_cfa;
- addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS;
- if (GetNextFrame().get() && GetNextFrame()->GetCFA(next_frame_cfa))
+ // To detect when we have the same CFA value multiple times, we compare the CFA of the current
+ // frame with the 2nd next frame because in some specail case (e.g. signal hanlders, hand
+ // written assembly without ABI compiance) we can have 2 frames with the same CFA (in theory we
+ // can have arbitrary number of frames with the same CFA, but more then 2 is very very unlikely)
+
+ RegisterContextLLDB::SharedPtr next_frame = GetNextFrame();
+ if (next_frame)
{
- if (next_frame_cfa == m_cfa)
+ RegisterContextLLDB::SharedPtr next_next_frame = next_frame->GetNextFrame();
+ addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS;
+ if (next_next_frame && next_next_frame->GetCFA(next_next_frame_cfa))
{
- // We have a loop in the stack unwind
- return true;
- }
- if (GetNextFrame()->GetNextFrame().get() && GetNextFrame()->GetNextFrame()->GetCFA(next_next_frame_cfa)
- && next_next_frame_cfa == m_cfa)
- {
- // We have a loop in the stack unwind
- return true;
+ if (next_next_frame_cfa == m_cfa)
+ {
+ // We have a loop in the stack unwind
+ return true;
+ }
}
}
return false;
}
-
bool
RegisterContextLLDB::IsFrameZero () const
{
@@ -792,24 +818,38 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
func_unwinders_sp = pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
}
- // No FuncUnwinders available for this pc (i.e. a stripped function symbol and -fomit-frame-pointer).
- // Try using the eh_frame information relative to the current PC,
- // and finally fall back on the architectural default unwind.
+ // No FuncUnwinders available for this pc (stripped function symbols, lldb could not augment its
+ // function table with another source, like LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO).
+ // See if eh_frame or the .ARM.exidx tables have unwind information for this address, else fall
+ // back to the architectural default unwind.
if (!func_unwinders_sp)
{
- DWARFCallFrameInfo *eh_frame = pc_module_sp && pc_module_sp->GetObjectFile() ?
- pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo() : nullptr;
-
m_frame_type = eNormalFrame;
- if (eh_frame && m_current_pc.IsValid())
+
+ if (!pc_module_sp || !pc_module_sp->GetObjectFile() || !m_current_pc.IsValid())
+ return arch_default_unwind_plan_sp;
+
+ // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.
+ DWARFCallFrameInfo *eh_frame = pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo();
+ if (eh_frame)
{
unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
- // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.
if (eh_frame->GetUnwindPlan (m_current_pc, *unwind_plan_sp))
return unwind_plan_sp;
else
unwind_plan_sp.reset();
}
+
+ ArmUnwindInfo *arm_exidx = pc_module_sp->GetObjectFile()->GetUnwindTable().GetArmUnwindInfo();
+ if (arm_exidx)
+ {
+ unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+ if (arm_exidx->GetUnwindPlan (exe_ctx.GetTargetRef(), m_current_pc, *unwind_plan_sp))
+ return unwind_plan_sp;
+ else
+ unwind_plan_sp.reset();
+ }
+
return arch_default_unwind_plan_sp;
}
@@ -864,12 +904,12 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// then the architecture default plan and for hand written assembly code it is often
// written in a way that it valid at all location what helps in the most common
// cases when the instruction emulation fails.
- UnwindPlanSP eh_frame_unwind_plan = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one);
- if (eh_frame_unwind_plan &&
- eh_frame_unwind_plan.get() != unwind_plan_sp.get() &&
- eh_frame_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
+ UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one);
+ if (call_site_unwind_plan &&
+ call_site_unwind_plan.get() != unwind_plan_sp.get() &&
+ call_site_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
{
- m_fallback_unwind_plan_sp = eh_frame_unwind_plan;
+ m_fallback_unwind_plan_sp = call_site_unwind_plan;
}
else
{
@@ -909,12 +949,12 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// more reliable even on non call sites then the architecture default plan and for hand
// written assembly code it is often written in a way that it valid at all location what
// helps in the most common cases when the instruction emulation fails.
- UnwindPlanSP eh_frame_unwind_plan = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one);
- if (eh_frame_unwind_plan &&
- eh_frame_unwind_plan.get() != unwind_plan_sp.get() &&
- eh_frame_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
+ UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one);
+ if (call_site_unwind_plan &&
+ call_site_unwind_plan.get() != unwind_plan_sp.get() &&
+ call_site_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
{
- m_fallback_unwind_plan_sp = eh_frame_unwind_plan;
+ m_fallback_unwind_plan_sp = call_site_unwind_plan;
}
else
{
@@ -1488,7 +1528,11 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
unwindplan_regloc.GetDWARFExpressionLength(),
process->GetByteOrder(), process->GetAddressByteSize());
ModuleSP opcode_ctx;
- DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
+ DWARFExpression dwarfexpr (opcode_ctx,
+ dwarfdata,
+ nullptr,
+ 0,
+ unwindplan_regloc.GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind (unwindplan_registerkind);
Value result;
Error error;
@@ -1784,7 +1828,11 @@ RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind,
row->GetCFAValue().GetDWARFExpressionLength(),
process->GetByteOrder(), process->GetAddressByteSize());
ModuleSP opcode_ctx;
- DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, row->GetCFAValue().GetDWARFExpressionLength());
+ DWARFExpression dwarfexpr (opcode_ctx,
+ dwarfdata,
+ nullptr,
+ 0,
+ row->GetCFAValue().GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind (row_register_kind);
Value result;
Error error;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
index 5f94a97..68dca3d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -10,8 +10,12 @@
#ifndef lldb_RegisterContextLLDB_h_
#define lldb_RegisterContextLLDB_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Symbol/UnwindPlan.h"
@@ -33,42 +37,39 @@ public:
lldb_private::SymbolContext& sym_ctx,
uint32_t frame_number, lldb_private::UnwindLLDB& unwind_lldb);
- ///
- // pure virtual functions from the base class that we must implement
- ///
-
- virtual
- ~RegisterContextLLDB () { }
+ ~RegisterContextLLDB() override = default;
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t reg_set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
bool
IsValid () const;
@@ -99,7 +100,6 @@ private:
// UnwindLLDB needs to pass around references to RegisterLocations
friend class UnwindLLDB;
-
// Returns true if we have an unwind loop -- the same stack frame unwinding
// multiple times.
bool
@@ -130,7 +130,6 @@ private:
bool
IsSkipFrame () const;
-
//------------------------------------------------------------------
/// Determines if a SymbolContext is a trap handler or not
///
@@ -221,7 +220,6 @@ private:
bool
IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset);
-
lldb_private::Thread& m_thread;
///
@@ -269,4 +267,4 @@ private:
} // namespace lldb_private
-#endif // lldb_RegisterContextLLDB_h_
+#endif // lldb_RegisterContextLLDB_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp
index e7784b1..f8d97aa 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp
@@ -22,6 +22,7 @@ using namespace lldb_private;
// Based on RegisterContextDarwin_arm.cpp
#define GPR_OFFSET(idx) ((idx) * 4)
#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextLinux_arm::GPR))
+#define FPSCR_OFFSET (LLVM_EXTENSION offsetof (RegisterContextLinux_arm::FPU, fpscr) + sizeof (RegisterContextLinux_arm::GPR))
#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU))
#define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextLinux_arm::DBG, reg) + sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU) + sizeof (RegisterContextLinux_arm::EXC)))
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.h
index 7087eb4..c3d41f6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm.h
@@ -12,7 +12,6 @@
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
-#include "RegisterContextPOSIX.h"
#include "RegisterInfoInterface.h"
class RegisterContextLinux_arm
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp
index 8c23e39..a4ab083 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp
@@ -21,7 +21,7 @@
#define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::GPR, reg))
#define FPU_OFFSET(idx) ((idx) * 16 + sizeof (RegisterContextLinux_arm64::GPR))
-#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::FPU, reg))
+#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::FPU, reg) + sizeof (RegisterContextLinux_arm64::GPR))
#define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::EXC, reg) + sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU))
#define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::DBG, reg) + sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU) + sizeof (RegisterContextLinux_arm64::EXC))
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h
index a9a5a09..3de94b8 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h
@@ -12,7 +12,6 @@
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
-#include "RegisterContextPOSIX.h"
#include "RegisterInfoInterface.h"
class RegisterContextLinux_arm64
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp
index 4f6bbc8..e39beef 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp
@@ -26,7 +26,7 @@ struct GPR
uint32_t es;
uint32_t fs;
uint32_t gs;
- uint32_t orig_ax;
+ uint32_t orig_eax;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
@@ -38,7 +38,8 @@ struct FPR_i386
{
uint16_t fctrl; // FPU Control Word (fcw)
uint16_t fstat; // FPU Status Word (fsw)
- uint16_t ftag; // FPU Tag Word (ftw)
+ uint8_t ftag; // FPU Tag Word (ftw)
+ uint8_t reserved_1; // Reserved
uint16_t fop; // Last Instruction Opcode (fop)
union
{
@@ -98,6 +99,9 @@ struct UserArea
RegisterContextLinux_i386::RegisterContextLinux_i386(const ArchSpec &target_arch) :
RegisterInfoInterface(target_arch)
{
+ RegisterInfo orig_ax = { "orig_eax", NULL, sizeof(((GPR*)NULL)->orig_eax), (LLVM_EXTENSION offsetof(GPR, orig_eax)), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL };
+ d_register_infos.push_back(orig_ax);
}
size_t
@@ -131,3 +135,9 @@ RegisterContextLinux_i386::GetUserRegisterCount () const
{
return static_cast<uint32_t> (k_num_user_registers_i386);
}
+
+const std::vector<lldb_private::RegisterInfo> *
+RegisterContextLinux_i386::GetDynamicRegisterInfoP() const
+{
+ return &d_register_infos;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h
index cb71d79..6c4768f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextLinux_i386_H_
#define liblldb_RegisterContextLinux_i386_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextLinux_i386
: public lldb_private::RegisterInfoInterface
@@ -29,6 +29,12 @@ public:
uint32_t
GetUserRegisterCount () const override;
+
+ const std::vector<lldb_private::RegisterInfo> *
+ GetDynamicRegisterInfoP() const override;
+
+private:
+ std::vector<lldb_private::RegisterInfo> d_register_infos;
};
#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp
index 4d58b85..1b22810 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp
@@ -10,7 +10,7 @@
#include <vector>
#include <stddef.h>
-// For GDB, GCC and DWARF Register numbers
+// For eh_frame and DWARF Register numbers
#include "RegisterContextLinux_mips.h"
// Internal codes for mips registers
@@ -29,8 +29,17 @@ using namespace lldb;
#include "RegisterInfos_mips.h"
#undef DECLARE_REGISTER_INFOS_MIPS_STRUCT
-RegisterContextLinux_mips::RegisterContextLinux_mips(const ArchSpec &target_arch) :
- RegisterInfoInterface(target_arch)
+uint32_t
+GetUserRegisterInfoCount (bool msa_present)
+{
+ if (msa_present)
+ return static_cast<uint32_t> (k_num_user_registers_mips);
+ return static_cast<uint32_t> (k_num_user_registers_mips - k_num_msa_registers_mips);
+}
+
+RegisterContextLinux_mips::RegisterContextLinux_mips(const ArchSpec &target_arch, bool msa_present) :
+ RegisterInfoInterface(target_arch),
+ m_user_register_count (GetUserRegisterInfoCount (msa_present))
{
}
@@ -63,5 +72,5 @@ RegisterContextLinux_mips::GetRegisterCount () const
uint32_t
RegisterContextLinux_mips::GetUserRegisterCount () const
{
- return static_cast<uint32_t> (k_num_user_registers_mips);
+ return static_cast<uint32_t> (m_user_register_count);
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h
index bcc2d00..c0bd5ad4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h
@@ -17,7 +17,7 @@ class RegisterContextLinux_mips
: public lldb_private::RegisterInfoInterface
{
public:
- RegisterContextLinux_mips(const lldb_private::ArchSpec &target_arch);
+ RegisterContextLinux_mips(const lldb_private::ArchSpec &target_arch, bool msa_present = true);
size_t
GetGPRSize() const override;
@@ -30,6 +30,9 @@ public:
uint32_t
GetUserRegisterCount () const override;
+
+private:
+ uint32_t m_user_register_count;
};
#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp
index 7f512f8..f2871e3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp
@@ -12,7 +12,7 @@
#include <vector>
#include <stddef.h>
-// For GDB, GCC and DWARF Register numbers
+// For eh_frame and DWARF Register numbers
#include "RegisterContextLinux_mips64.h"
// For GP and FP buffers
@@ -75,27 +75,31 @@ GetRegisterInfoCount (const ArchSpec &target_arch)
}
uint32_t
-GetUserRegisterInfoCount (const ArchSpec &target_arch)
+GetUserRegisterInfoCount (const ArchSpec &target_arch, bool msa_present)
{
switch (target_arch.GetMachine())
{
case llvm::Triple::mips:
case llvm::Triple::mipsel:
- return static_cast<uint32_t> (k_num_user_registers_mips);
+ if (msa_present)
+ return static_cast<uint32_t> (k_num_user_registers_mips);
+ return static_cast<uint32_t> (k_num_user_registers_mips - k_num_msa_registers_mips);
case llvm::Triple::mips64el:
case llvm::Triple::mips64:
- return static_cast<uint32_t> (k_num_user_registers_mips64);
+ if (msa_present)
+ return static_cast<uint32_t> (k_num_user_registers_mips64);
+ return static_cast<uint32_t> (k_num_user_registers_mips64 - k_num_msa_registers_mips64);
default:
assert(false && "Unhandled target architecture.");
return 0;
}
}
-RegisterContextLinux_mips64::RegisterContextLinux_mips64(const ArchSpec &target_arch) :
+RegisterContextLinux_mips64::RegisterContextLinux_mips64(const ArchSpec &target_arch, bool msa_present) :
lldb_private::RegisterInfoInterface(target_arch),
m_register_info_p (GetRegisterInfoPtr (target_arch)),
m_register_info_count (GetRegisterInfoCount (target_arch)),
- m_user_register_count (GetUserRegisterInfoCount (target_arch))
+ m_user_register_count (GetUserRegisterInfoCount (target_arch, msa_present))
{
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h
index 86c662c..843328c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h
@@ -19,7 +19,7 @@ class RegisterContextLinux_mips64
: public lldb_private::RegisterInfoInterface
{
public:
- RegisterContextLinux_mips64(const lldb_private::ArchSpec &target_arch);
+ RegisterContextLinux_mips64(const lldb_private::ArchSpec &target_arch, bool msa_present = true);
size_t
GetGPRSize() const override;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
index c0993b4..78afe72 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
@@ -32,7 +32,7 @@ typedef struct _GPR
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
- uint64_t orig_ax;
+ uint64_t orig_rax;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
@@ -171,6 +171,9 @@ RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_
m_register_info_count (GetRegisterInfoCount (target_arch)),
m_user_register_count (GetUserRegisterInfoCount (target_arch))
{
+ RegisterInfo orig_ax = { "orig_rax", NULL, sizeof(((GPR*)NULL)->orig_rax), (LLVM_EXTENSION offsetof(GPR, orig_rax)), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL };
+ d_register_infos.push_back(orig_ax);
}
size_t
@@ -179,6 +182,12 @@ RegisterContextLinux_x86_64::GetGPRSize() const
return sizeof(GPR);
}
+const std::vector<lldb_private::RegisterInfo> *
+RegisterContextLinux_x86_64::GetDynamicRegisterInfoP() const
+{
+ return &d_register_infos;
+}
+
const RegisterInfo *
RegisterContextLinux_x86_64::GetRegisterInfo() const
{
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h
index 0cdfae9..ed0b7de 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextLinux_x86_64_H_
#define liblldb_RegisterContextLinux_x86_64_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextLinux_x86_64
: public lldb_private::RegisterInfoInterface
@@ -30,10 +30,15 @@ public:
uint32_t
GetUserRegisterCount () const override;
+ const std::vector<lldb_private::RegisterInfo> *
+ GetDynamicRegisterInfoP() const override;
+
private:
const lldb_private::RegisterInfo *m_register_info_p;
uint32_t m_register_info_count;
uint32_t m_user_register_count;
+ std::vector<lldb_private::RegisterInfo> d_register_infos;
+
};
#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
index 505b8d4..0ddadbe 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
@@ -22,56 +22,49 @@
class RegisterContextMacOSXFrameBackchain : public lldb_private::RegisterContext
{
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
RegisterContextMacOSXFrameBackchain (lldb_private::Thread &thread,
uint32_t concrete_frame_idx,
const UnwindMacOSXFrameBackchain::Cursor &cursor);
- virtual
- ~RegisterContextMacOSXFrameBackchain ();
+ ~RegisterContextMacOSXFrameBackchain() override;
- //------------------------------------------------------------------
- // Subclasses must override these functions
- //------------------------------------------------------------------
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t reg_set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
private:
UnwindMacOSXFrameBackchain::Cursor m_cursor;
bool m_cursor_is_valid;
- //------------------------------------------------------------------
- // For RegisterContextMacOSXFrameBackchain only
- //------------------------------------------------------------------
+
DISALLOW_COPY_AND_ASSIGN (RegisterContextMacOSXFrameBackchain);
};
-#endif // lldb_RegisterContextMacOSXFrameBackchain_h_
+#endif // lldb_RegisterContextMacOSXFrameBackchain_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h
index 9d97dfa..d61aba9 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h
@@ -25,39 +25,31 @@ class DynamicRegisterInfo;
class RegisterContextMemory : public lldb_private::RegisterContext
{
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
RegisterContextMemory (lldb_private::Thread &thread,
uint32_t concrete_frame_idx,
DynamicRegisterInfo &reg_info,
lldb::addr_t reg_data_addr);
- virtual
- ~RegisterContextMemory ();
+ ~RegisterContextMemory() override;
- //------------------------------------------------------------------
- // Subclasses must override these functions
- //------------------------------------------------------------------
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t reg_set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
-
//------------------------------------------------------------------
// If all of the thread register are in a contiguous buffer in
// memory, then the default ReadRegister/WriteRegister and
@@ -66,24 +58,24 @@ public:
// class and modify the read/write functions as needed.
//------------------------------------------------------------------
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &reg_value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &reg_value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &reg_value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &reg_value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
void
SetAllRegisterData (const lldb::DataBufferSP &data_sp);
+
protected:
-
void
SetAllRegisterValid (bool b);
@@ -93,10 +85,7 @@ protected:
lldb::addr_t m_reg_data_addr; // If this is valid, then we have a register context that is stored in memmory
private:
- //------------------------------------------------------------------
- // For RegisterContextMemory only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (RegisterContextMemory);
};
-#endif // lldb_RegisterContextMemory_h_
+#endif // lldb_RegisterContextMemory_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
index d306f86..029a0e73 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
@@ -88,6 +88,54 @@ static const uint32_t g_fpu_regnums_arm[] =
fpu_s30_arm,
fpu_s31_arm,
fpu_fpscr_arm,
+ fpu_d0_arm,
+ fpu_d1_arm,
+ fpu_d2_arm,
+ fpu_d3_arm,
+ fpu_d4_arm,
+ fpu_d5_arm,
+ fpu_d6_arm,
+ fpu_d7_arm,
+ fpu_d8_arm,
+ fpu_d9_arm,
+ fpu_d10_arm,
+ fpu_d11_arm,
+ fpu_d12_arm,
+ fpu_d13_arm,
+ fpu_d14_arm,
+ fpu_d15_arm,
+ fpu_d16_arm,
+ fpu_d17_arm,
+ fpu_d18_arm,
+ fpu_d19_arm,
+ fpu_d20_arm,
+ fpu_d21_arm,
+ fpu_d22_arm,
+ fpu_d23_arm,
+ fpu_d24_arm,
+ fpu_d25_arm,
+ fpu_d26_arm,
+ fpu_d27_arm,
+ fpu_d28_arm,
+ fpu_d29_arm,
+ fpu_d30_arm,
+ fpu_d31_arm,
+ fpu_q0_arm,
+ fpu_q1_arm,
+ fpu_q2_arm,
+ fpu_q3_arm,
+ fpu_q4_arm,
+ fpu_q5_arm,
+ fpu_q6_arm,
+ fpu_q7_arm,
+ fpu_q8_arm,
+ fpu_q9_arm,
+ fpu_q10_arm,
+ fpu_q11_arm,
+ fpu_q12_arm,
+ fpu_q13_arm,
+ fpu_q14_arm,
+ fpu_q15_arm,
LLDB_INVALID_REGNUM // register sets need to end with this flag
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
index a3a2926..fbbcb94 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
@@ -1,4 +1,4 @@
-//===-- RegisterContextPOSIX_arm.h ----------------------------*- C++ -*-===//
+//===-- RegisterContextPOSIX_arm.h ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextPOSIX_arm_H_
-#define liblldb_RegisterContextPOSIX_arm_H_
+#ifndef liblldb_RegisterContextPOSIX_arm_h_
+#define liblldb_RegisterContextPOSIX_arm_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
#include "lldb-arm-register-enums.h"
-#include "RegisterContextPOSIX.h"
class ProcessMonitor;
@@ -24,16 +29,16 @@ public:
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
- ~RegisterContextPOSIX_arm();
+ ~RegisterContextPOSIX_arm() override;
void
Invalidate();
void
- InvalidateAllRegisters();
+ InvalidateAllRegisters() override;
size_t
- GetRegisterCount();
+ GetRegisterCount() override;
virtual size_t
GetGPRSize();
@@ -45,19 +50,19 @@ public:
GetRegisterOffset(unsigned reg);
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
+ GetRegisterInfoAtIndex(size_t reg) override;
size_t
- GetRegisterSetCount();
+ GetRegisterSetCount() override;
const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
+ GetRegisterSet(size_t set) override;
const char *
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
protected:
struct RegInfo
@@ -117,5 +122,4 @@ protected:
virtual bool WriteFPR() = 0;
};
-#endif // #ifndef liblldb_RegisterContextPOSIX_arm_H_
-
+#endif // liblldb_RegisterContextPOSIX_arm_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
index 29e7a7d..225d4f2 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
@@ -7,12 +7,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextPOSIX_arm64_H_
-#define liblldb_RegisterContextPOSIX_arm64_H_
+#ifndef liblldb_RegisterContextPOSIX_arm64_h_
+#define liblldb_RegisterContextPOSIX_arm64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
#include "lldb-arm64-register-enums.h"
-#include "RegisterContextPOSIX.h"
class ProcessMonitor;
@@ -24,16 +29,16 @@ public:
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
- ~RegisterContextPOSIX_arm64();
+ ~RegisterContextPOSIX_arm64() override;
void
Invalidate();
void
- InvalidateAllRegisters();
+ InvalidateAllRegisters() override;
size_t
- GetRegisterCount();
+ GetRegisterCount() override;
virtual size_t
GetGPRSize();
@@ -45,19 +50,19 @@ public:
GetRegisterOffset(unsigned reg);
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
+ GetRegisterInfoAtIndex(size_t reg) override;
size_t
- GetRegisterSetCount();
+ GetRegisterSetCount() override;
const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
+ GetRegisterSet(size_t set) override;
const char *
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
protected:
struct RegInfo
@@ -116,4 +121,4 @@ protected:
virtual bool WriteFPR() = 0;
};
-#endif // #ifndef liblldb_RegisterContextPOSIX_arm64_H_
+#endif // liblldb_RegisterContextPOSIX_arm64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h
index 612a034..07552d8 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h
@@ -7,11 +7,16 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextPOSIX_mips64_H_
-#define liblldb_RegisterContextPOSIX_mips64_H_
+#ifndef liblldb_RegisterContextPOSIX_mips64_h_
+#define liblldb_RegisterContextPOSIX_mips64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
-#include "RegisterContextPOSIX.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
#include "RegisterContext_mips.h"
#include "lldb-mips-freebsd-register-enums.h"
@@ -27,16 +32,16 @@ public:
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
- ~RegisterContextPOSIX_mips64();
+ ~RegisterContextPOSIX_mips64() override;
void
Invalidate();
void
- InvalidateAllRegisters();
+ InvalidateAllRegisters() override;
size_t
- GetRegisterCount();
+ GetRegisterCount() override;
virtual size_t
GetGPRSize();
@@ -48,19 +53,19 @@ public:
GetRegisterOffset(unsigned reg);
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
+ GetRegisterInfoAtIndex(size_t reg) override;
size_t
- GetRegisterSetCount();
+ GetRegisterSetCount() override;
const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
+ GetRegisterSet(size_t set) override;
const char *
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
protected:
uint64_t m_gpr_mips64[k_num_gpr_registers_mips64]; // general purpose registers.
@@ -87,4 +92,4 @@ protected:
virtual bool WriteFPR() = 0;
};
-#endif // #ifndef liblldb_RegisterContextPOSIX_mips64_H_
+#endif // liblldb_RegisterContextPOSIX_mips64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
index c7a2451..4168e46 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
@@ -1,4 +1,4 @@
-//===-- RegisterContextPOSIX_powerpc.h ---------------------------*- C++ -*-===//
+//===-- RegisterContextPOSIX_powerpc.h --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,11 +7,16 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextPOSIX_powerpc_H_
-#define liblldb_RegisterContextPOSIX_powerpc_H_
+#ifndef liblldb_RegisterContextPOSIX_powerpc_h_
+#define liblldb_RegisterContextPOSIX_powerpc_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
-#include "RegisterContextPOSIX.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
#include "RegisterContext_powerpc.h"
class ProcessMonitor;
@@ -148,16 +153,16 @@ public:
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
- ~RegisterContextPOSIX_powerpc();
+ ~RegisterContextPOSIX_powerpc() override;
void
Invalidate();
void
- InvalidateAllRegisters();
+ InvalidateAllRegisters() override;
size_t
- GetRegisterCount();
+ GetRegisterCount() override;
virtual size_t
GetGPRSize();
@@ -169,19 +174,19 @@ public:
GetRegisterOffset(unsigned reg);
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
+ GetRegisterInfoAtIndex(size_t reg) override;
size_t
- GetRegisterSetCount();
+ GetRegisterSetCount() override;
const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
+ GetRegisterSet(size_t set) override;
const char *
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
protected:
uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc]; // general purpose registers.
@@ -215,4 +220,4 @@ protected:
virtual bool WriteVMX() = 0;
};
-#endif // #ifndef liblldb_RegisterContextPOSIX_powerpc_H_
+#endif // liblldb_RegisterContextPOSIX_powerpc_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
index 0eec1d9..b470825 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
@@ -7,13 +7,18 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextPOSIX_x86_H_
-#define liblldb_RegisterContextPOSIX_x86_H_
+#ifndef liblldb_RegisterContextPOSIX_x86_h_
+#define liblldb_RegisterContextPOSIX_x86_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
-#include "lldb-x86-register-enums.h"
-#include "RegisterContextPOSIX.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
#include "RegisterContext_x86.h"
+#include "lldb-x86-register-enums.h"
class ProcessMonitor;
@@ -25,16 +30,16 @@ public:
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
- ~RegisterContextPOSIX_x86();
+ ~RegisterContextPOSIX_x86() override;
void
Invalidate();
void
- InvalidateAllRegisters();
+ InvalidateAllRegisters() override;
size_t
- GetRegisterCount();
+ GetRegisterCount() override;
virtual size_t
GetGPRSize();
@@ -46,19 +51,19 @@ public:
GetRegisterOffset(unsigned reg);
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
+ GetRegisterInfoAtIndex(size_t reg) override;
size_t
- GetRegisterSetCount();
+ GetRegisterSetCount() override;
const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
+ GetRegisterSet(size_t set) override;
const char *
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
//---------------------------------------------------------------------------
// Note: prefer kernel definitions over user-land
@@ -186,4 +191,4 @@ protected:
virtual bool WriteFPR() = 0;
};
-#endif // #ifndef liblldb_RegisterContextPOSIX_x86_H_
+#endif // liblldb_RegisterContextPOSIX_x86_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
index 161ef04..b4680de 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
@@ -10,8 +10,12 @@
#ifndef lldb_RegisterContextThreadMemory_h_
#define lldb_RegisterContextThreadMemory_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -24,30 +28,28 @@ public:
RegisterContextThreadMemory (Thread &thread,
lldb::addr_t register_data_addr);
- virtual ~RegisterContextThreadMemory();
- //------------------------------------------------------------------
- // Subclasses must override these functions
- //------------------------------------------------------------------
- virtual void
- InvalidateAllRegisters ();
+ ~RegisterContextThreadMemory() override;
+
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const RegisterSet *
- GetRegisterSet (size_t reg_set);
+ const RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual bool
- ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value);
+ bool
+ ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value) override;
- virtual bool
- WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value);
+ bool
+ WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value) override;
// These two functions are used to implement "push" and "pop" of register states. They are used primarily
// for expression evaluation, where we need to push a new state (storing the old one in data_sp) and then
@@ -56,48 +58,50 @@ public:
// may mean e.g. interrupting a thread that is sitting in a kernel trap. That is a somewhat disruptive operation,
// so these API's should only be used when this behavior is needed.
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
CopyFromRegisterContext (lldb::RegisterContextSP context);
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
-
- //------------------------------------------------------------------
- // Subclasses can override these functions if desired
- //------------------------------------------------------------------
- virtual uint32_t
- NumSupportedHardwareBreakpoints ();
-
- virtual uint32_t
- SetHardwareBreakpoint (lldb::addr_t addr, size_t size);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
- virtual bool
- ClearHardwareBreakpoint (uint32_t hw_idx);
+ uint32_t
+ NumSupportedHardwareBreakpoints() override;
- virtual uint32_t
- NumSupportedHardwareWatchpoints ();
+ uint32_t
+ SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
- virtual uint32_t
- SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
-
- virtual bool
- ClearHardwareWatchpoint (uint32_t hw_index);
+ bool
+ ClearHardwareBreakpoint(uint32_t hw_idx) override;
- virtual bool
- HardwareSingleStep (bool enable);
+ uint32_t
+ NumSupportedHardwareWatchpoints() override;
- virtual Error
- ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue &reg_value);
+ uint32_t
+ SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override;
- virtual Error
- WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue &reg_value);
+ bool
+ ClearHardwareWatchpoint(uint32_t hw_index) override;
+ bool
+ HardwareSingleStep(bool enable) override;
+
+ Error
+ ReadRegisterValueFromMemory(const lldb_private::RegisterInfo *reg_info,
+ lldb::addr_t src_addr,
+ uint32_t src_len,
+ RegisterValue &reg_value) override;
+
+ Error
+ WriteRegisterValueToMemory(const lldb_private::RegisterInfo *reg_info,
+ lldb::addr_t dst_addr, uint32_t dst_len,
+ const RegisterValue &reg_value) override;
+
protected:
void
UpdateRegisterContext ();
@@ -106,9 +110,11 @@ protected:
lldb::RegisterContextSP m_reg_ctx_sp;
lldb::addr_t m_register_data_addr;
uint32_t m_stop_id;
+
private:
DISALLOW_COPY_AND_ASSIGN (RegisterContextThreadMemory);
};
+
} // namespace lldb_private
-#endif // lldb_RegisterContextThreadMemory_h_
+#endif // lldb_RegisterContextThreadMemory_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h
index de2b4d6..3603227 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_mips.h
@@ -15,455 +15,228 @@
enum
{
// GP Registers
- gcc_dwarf_zero_mips = 0,
- gcc_dwarf_r1_mips,
- gcc_dwarf_r2_mips,
- gcc_dwarf_r3_mips,
- gcc_dwarf_r4_mips,
- gcc_dwarf_r5_mips,
- gcc_dwarf_r6_mips,
- gcc_dwarf_r7_mips,
- gcc_dwarf_r8_mips,
- gcc_dwarf_r9_mips,
- gcc_dwarf_r10_mips,
- gcc_dwarf_r11_mips,
- gcc_dwarf_r12_mips,
- gcc_dwarf_r13_mips,
- gcc_dwarf_r14_mips,
- gcc_dwarf_r15_mips,
- gcc_dwarf_r16_mips,
- gcc_dwarf_r17_mips,
- gcc_dwarf_r18_mips,
- gcc_dwarf_r19_mips,
- gcc_dwarf_r20_mips,
- gcc_dwarf_r21_mips,
- gcc_dwarf_r22_mips,
- gcc_dwarf_r23_mips,
- gcc_dwarf_r24_mips,
- gcc_dwarf_r25_mips,
- gcc_dwarf_r26_mips,
- gcc_dwarf_r27_mips,
- gcc_dwarf_gp_mips,
- gcc_dwarf_sp_mips,
- gcc_dwarf_r30_mips,
- gcc_dwarf_ra_mips,
- gcc_dwarf_sr_mips,
- gcc_dwarf_lo_mips,
- gcc_dwarf_hi_mips,
- gcc_dwarf_bad_mips,
- gcc_dwarf_cause_mips,
- gcc_dwarf_pc_mips,
- gcc_dwarf_f0_mips,
- gcc_dwarf_f1_mips,
- gcc_dwarf_f2_mips,
- gcc_dwarf_f3_mips,
- gcc_dwarf_f4_mips,
- gcc_dwarf_f5_mips,
- gcc_dwarf_f6_mips,
- gcc_dwarf_f7_mips,
- gcc_dwarf_f8_mips,
- gcc_dwarf_f9_mips,
- gcc_dwarf_f10_mips,
- gcc_dwarf_f11_mips,
- gcc_dwarf_f12_mips,
- gcc_dwarf_f13_mips,
- gcc_dwarf_f14_mips,
- gcc_dwarf_f15_mips,
- gcc_dwarf_f16_mips,
- gcc_dwarf_f17_mips,
- gcc_dwarf_f18_mips,
- gcc_dwarf_f19_mips,
- gcc_dwarf_f20_mips,
- gcc_dwarf_f21_mips,
- gcc_dwarf_f22_mips,
- gcc_dwarf_f23_mips,
- gcc_dwarf_f24_mips,
- gcc_dwarf_f25_mips,
- gcc_dwarf_f26_mips,
- gcc_dwarf_f27_mips,
- gcc_dwarf_f28_mips,
- gcc_dwarf_f29_mips,
- gcc_dwarf_f30_mips,
- gcc_dwarf_f31_mips,
- gcc_dwarf_fcsr_mips,
- gcc_dwarf_fir_mips,
- gcc_dwarf_w0_mips,
- gcc_dwarf_w1_mips,
- gcc_dwarf_w2_mips,
- gcc_dwarf_w3_mips,
- gcc_dwarf_w4_mips,
- gcc_dwarf_w5_mips,
- gcc_dwarf_w6_mips,
- gcc_dwarf_w7_mips,
- gcc_dwarf_w8_mips,
- gcc_dwarf_w9_mips,
- gcc_dwarf_w10_mips,
- gcc_dwarf_w11_mips,
- gcc_dwarf_w12_mips,
- gcc_dwarf_w13_mips,
- gcc_dwarf_w14_mips,
- gcc_dwarf_w15_mips,
- gcc_dwarf_w16_mips,
- gcc_dwarf_w17_mips,
- gcc_dwarf_w18_mips,
- gcc_dwarf_w19_mips,
- gcc_dwarf_w20_mips,
- gcc_dwarf_w21_mips,
- gcc_dwarf_w22_mips,
- gcc_dwarf_w23_mips,
- gcc_dwarf_w24_mips,
- gcc_dwarf_w25_mips,
- gcc_dwarf_w26_mips,
- gcc_dwarf_w27_mips,
- gcc_dwarf_w28_mips,
- gcc_dwarf_w29_mips,
- gcc_dwarf_w30_mips,
- gcc_dwarf_w31_mips,
- gcc_dwarf_mcsr_mips,
- gcc_dwarf_mir_mips,
- gcc_dwarf_config5_mips,
- gcc_dwarf_ic_mips,
- gcc_dwarf_dummy_mips
+ dwarf_zero_mips = 0,
+ dwarf_r1_mips,
+ dwarf_r2_mips,
+ dwarf_r3_mips,
+ dwarf_r4_mips,
+ dwarf_r5_mips,
+ dwarf_r6_mips,
+ dwarf_r7_mips,
+ dwarf_r8_mips,
+ dwarf_r9_mips,
+ dwarf_r10_mips,
+ dwarf_r11_mips,
+ dwarf_r12_mips,
+ dwarf_r13_mips,
+ dwarf_r14_mips,
+ dwarf_r15_mips,
+ dwarf_r16_mips,
+ dwarf_r17_mips,
+ dwarf_r18_mips,
+ dwarf_r19_mips,
+ dwarf_r20_mips,
+ dwarf_r21_mips,
+ dwarf_r22_mips,
+ dwarf_r23_mips,
+ dwarf_r24_mips,
+ dwarf_r25_mips,
+ dwarf_r26_mips,
+ dwarf_r27_mips,
+ dwarf_gp_mips,
+ dwarf_sp_mips,
+ dwarf_r30_mips,
+ dwarf_ra_mips,
+ dwarf_sr_mips,
+ dwarf_lo_mips,
+ dwarf_hi_mips,
+ dwarf_bad_mips,
+ dwarf_cause_mips,
+ dwarf_pc_mips,
+ dwarf_f0_mips,
+ dwarf_f1_mips,
+ dwarf_f2_mips,
+ dwarf_f3_mips,
+ dwarf_f4_mips,
+ dwarf_f5_mips,
+ dwarf_f6_mips,
+ dwarf_f7_mips,
+ dwarf_f8_mips,
+ dwarf_f9_mips,
+ dwarf_f10_mips,
+ dwarf_f11_mips,
+ dwarf_f12_mips,
+ dwarf_f13_mips,
+ dwarf_f14_mips,
+ dwarf_f15_mips,
+ dwarf_f16_mips,
+ dwarf_f17_mips,
+ dwarf_f18_mips,
+ dwarf_f19_mips,
+ dwarf_f20_mips,
+ dwarf_f21_mips,
+ dwarf_f22_mips,
+ dwarf_f23_mips,
+ dwarf_f24_mips,
+ dwarf_f25_mips,
+ dwarf_f26_mips,
+ dwarf_f27_mips,
+ dwarf_f28_mips,
+ dwarf_f29_mips,
+ dwarf_f30_mips,
+ dwarf_f31_mips,
+ dwarf_fcsr_mips,
+ dwarf_fir_mips,
+ dwarf_w0_mips,
+ dwarf_w1_mips,
+ dwarf_w2_mips,
+ dwarf_w3_mips,
+ dwarf_w4_mips,
+ dwarf_w5_mips,
+ dwarf_w6_mips,
+ dwarf_w7_mips,
+ dwarf_w8_mips,
+ dwarf_w9_mips,
+ dwarf_w10_mips,
+ dwarf_w11_mips,
+ dwarf_w12_mips,
+ dwarf_w13_mips,
+ dwarf_w14_mips,
+ dwarf_w15_mips,
+ dwarf_w16_mips,
+ dwarf_w17_mips,
+ dwarf_w18_mips,
+ dwarf_w19_mips,
+ dwarf_w20_mips,
+ dwarf_w21_mips,
+ dwarf_w22_mips,
+ dwarf_w23_mips,
+ dwarf_w24_mips,
+ dwarf_w25_mips,
+ dwarf_w26_mips,
+ dwarf_w27_mips,
+ dwarf_w28_mips,
+ dwarf_w29_mips,
+ dwarf_w30_mips,
+ dwarf_w31_mips,
+ dwarf_mcsr_mips,
+ dwarf_mir_mips,
+ dwarf_config5_mips,
+ dwarf_ic_mips,
+ dwarf_dummy_mips
};
enum
{
- gcc_dwarf_zero_mips64 = 0,
- gcc_dwarf_r1_mips64,
- gcc_dwarf_r2_mips64,
- gcc_dwarf_r3_mips64,
- gcc_dwarf_r4_mips64,
- gcc_dwarf_r5_mips64,
- gcc_dwarf_r6_mips64,
- gcc_dwarf_r7_mips64,
- gcc_dwarf_r8_mips64,
- gcc_dwarf_r9_mips64,
- gcc_dwarf_r10_mips64,
- gcc_dwarf_r11_mips64,
- gcc_dwarf_r12_mips64,
- gcc_dwarf_r13_mips64,
- gcc_dwarf_r14_mips64,
- gcc_dwarf_r15_mips64,
- gcc_dwarf_r16_mips64,
- gcc_dwarf_r17_mips64,
- gcc_dwarf_r18_mips64,
- gcc_dwarf_r19_mips64,
- gcc_dwarf_r20_mips64,
- gcc_dwarf_r21_mips64,
- gcc_dwarf_r22_mips64,
- gcc_dwarf_r23_mips64,
- gcc_dwarf_r24_mips64,
- gcc_dwarf_r25_mips64,
- gcc_dwarf_r26_mips64,
- gcc_dwarf_r27_mips64,
- gcc_dwarf_gp_mips64,
- gcc_dwarf_sp_mips64,
- gcc_dwarf_r30_mips64,
- gcc_dwarf_ra_mips64,
- gcc_dwarf_sr_mips64,
- gcc_dwarf_lo_mips64,
- gcc_dwarf_hi_mips64,
- gcc_dwarf_bad_mips64,
- gcc_dwarf_cause_mips64,
- gcc_dwarf_pc_mips64,
- gcc_dwarf_f0_mips64,
- gcc_dwarf_f1_mips64,
- gcc_dwarf_f2_mips64,
- gcc_dwarf_f3_mips64,
- gcc_dwarf_f4_mips64,
- gcc_dwarf_f5_mips64,
- gcc_dwarf_f6_mips64,
- gcc_dwarf_f7_mips64,
- gcc_dwarf_f8_mips64,
- gcc_dwarf_f9_mips64,
- gcc_dwarf_f10_mips64,
- gcc_dwarf_f11_mips64,
- gcc_dwarf_f12_mips64,
- gcc_dwarf_f13_mips64,
- gcc_dwarf_f14_mips64,
- gcc_dwarf_f15_mips64,
- gcc_dwarf_f16_mips64,
- gcc_dwarf_f17_mips64,
- gcc_dwarf_f18_mips64,
- gcc_dwarf_f19_mips64,
- gcc_dwarf_f20_mips64,
- gcc_dwarf_f21_mips64,
- gcc_dwarf_f22_mips64,
- gcc_dwarf_f23_mips64,
- gcc_dwarf_f24_mips64,
- gcc_dwarf_f25_mips64,
- gcc_dwarf_f26_mips64,
- gcc_dwarf_f27_mips64,
- gcc_dwarf_f28_mips64,
- gcc_dwarf_f29_mips64,
- gcc_dwarf_f30_mips64,
- gcc_dwarf_f31_mips64,
- gcc_dwarf_fcsr_mips64,
- gcc_dwarf_fir_mips64,
- gcc_dwarf_ic_mips64,
- gcc_dwarf_dummy_mips64,
- gcc_dwarf_w0_mips64,
- gcc_dwarf_w1_mips64,
- gcc_dwarf_w2_mips64,
- gcc_dwarf_w3_mips64,
- gcc_dwarf_w4_mips64,
- gcc_dwarf_w5_mips64,
- gcc_dwarf_w6_mips64,
- gcc_dwarf_w7_mips64,
- gcc_dwarf_w8_mips64,
- gcc_dwarf_w9_mips64,
- gcc_dwarf_w10_mips64,
- gcc_dwarf_w11_mips64,
- gcc_dwarf_w12_mips64,
- gcc_dwarf_w13_mips64,
- gcc_dwarf_w14_mips64,
- gcc_dwarf_w15_mips64,
- gcc_dwarf_w16_mips64,
- gcc_dwarf_w17_mips64,
- gcc_dwarf_w18_mips64,
- gcc_dwarf_w19_mips64,
- gcc_dwarf_w20_mips64,
- gcc_dwarf_w21_mips64,
- gcc_dwarf_w22_mips64,
- gcc_dwarf_w23_mips64,
- gcc_dwarf_w24_mips64,
- gcc_dwarf_w25_mips64,
- gcc_dwarf_w26_mips64,
- gcc_dwarf_w27_mips64,
- gcc_dwarf_w28_mips64,
- gcc_dwarf_w29_mips64,
- gcc_dwarf_w30_mips64,
- gcc_dwarf_w31_mips64,
- gcc_dwarf_mcsr_mips64,
- gcc_dwarf_mir_mips64,
- gcc_dwarf_config5_mips64,
-};
-
-// GDB Register numbers (eRegisterKindGDB)
-enum
-{
- gdb_zero_mips = 0,
- gdb_r1_mips,
- gdb_r2_mips,
- gdb_r3_mips,
- gdb_r4_mips,
- gdb_r5_mips,
- gdb_r6_mips,
- gdb_r7_mips,
- gdb_r8_mips,
- gdb_r9_mips,
- gdb_r10_mips,
- gdb_r11_mips,
- gdb_r12_mips,
- gdb_r13_mips,
- gdb_r14_mips,
- gdb_r15_mips,
- gdb_r16_mips,
- gdb_r17_mips,
- gdb_r18_mips,
- gdb_r19_mips,
- gdb_r20_mips,
- gdb_r21_mips,
- gdb_r22_mips,
- gdb_r23_mips,
- gdb_r24_mips,
- gdb_r25_mips,
- gdb_r26_mips,
- gdb_r27_mips,
- gdb_gp_mips,
- gdb_sp_mips,
- gdb_r30_mips,
- gdb_ra_mips,
- gdb_sr_mips,
- gdb_lo_mips,
- gdb_hi_mips,
- gdb_bad_mips,
- gdb_cause_mips,
- gdb_pc_mips,
- gdb_f0_mips,
- gdb_f1_mips,
- gdb_f2_mips,
- gdb_f3_mips,
- gdb_f4_mips,
- gdb_f5_mips,
- gdb_f6_mips,
- gdb_f7_mips,
- gdb_f8_mips,
- gdb_f9_mips,
- gdb_f10_mips,
- gdb_f11_mips,
- gdb_f12_mips,
- gdb_f13_mips,
- gdb_f14_mips,
- gdb_f15_mips,
- gdb_f16_mips,
- gdb_f17_mips,
- gdb_f18_mips,
- gdb_f19_mips,
- gdb_f20_mips,
- gdb_f21_mips,
- gdb_f22_mips,
- gdb_f23_mips,
- gdb_f24_mips,
- gdb_f25_mips,
- gdb_f26_mips,
- gdb_f27_mips,
- gdb_f28_mips,
- gdb_f29_mips,
- gdb_f30_mips,
- gdb_f31_mips,
- gdb_fcsr_mips,
- gdb_fir_mips,
- gdb_w0_mips,
- gdb_w1_mips,
- gdb_w2_mips,
- gdb_w3_mips,
- gdb_w4_mips,
- gdb_w5_mips,
- gdb_w6_mips,
- gdb_w7_mips,
- gdb_w8_mips,
- gdb_w9_mips,
- gdb_w10_mips,
- gdb_w11_mips,
- gdb_w12_mips,
- gdb_w13_mips,
- gdb_w14_mips,
- gdb_w15_mips,
- gdb_w16_mips,
- gdb_w17_mips,
- gdb_w18_mips,
- gdb_w19_mips,
- gdb_w20_mips,
- gdb_w21_mips,
- gdb_w22_mips,
- gdb_w23_mips,
- gdb_w24_mips,
- gdb_w25_mips,
- gdb_w26_mips,
- gdb_w27_mips,
- gdb_w28_mips,
- gdb_w29_mips,
- gdb_w30_mips,
- gdb_w31_mips,
- gdb_mcsr_mips,
- gdb_mir_mips,
- gdb_config5_mips,
- gdb_ic_mips,
- gdb_dummy_mips
-};
-
-enum
-{
- gdb_zero_mips64 = 0,
- gdb_r1_mips64,
- gdb_r2_mips64,
- gdb_r3_mips64,
- gdb_r4_mips64,
- gdb_r5_mips64,
- gdb_r6_mips64,
- gdb_r7_mips64,
- gdb_r8_mips64,
- gdb_r9_mips64,
- gdb_r10_mips64,
- gdb_r11_mips64,
- gdb_r12_mips64,
- gdb_r13_mips64,
- gdb_r14_mips64,
- gdb_r15_mips64,
- gdb_r16_mips64,
- gdb_r17_mips64,
- gdb_r18_mips64,
- gdb_r19_mips64,
- gdb_r20_mips64,
- gdb_r21_mips64,
- gdb_r22_mips64,
- gdb_r23_mips64,
- gdb_r24_mips64,
- gdb_r25_mips64,
- gdb_r26_mips64,
- gdb_r27_mips64,
- gdb_gp_mips64,
- gdb_sp_mips64,
- gdb_r30_mips64,
- gdb_ra_mips64,
- gdb_sr_mips64,
- gdb_lo_mips64,
- gdb_hi_mips64,
- gdb_bad_mips64,
- gdb_cause_mips64,
- gdb_pc_mips64,
- gdb_f0_mips64,
- gdb_f1_mips64,
- gdb_f2_mips64,
- gdb_f3_mips64,
- gdb_f4_mips64,
- gdb_f5_mips64,
- gdb_f6_mips64,
- gdb_f7_mips64,
- gdb_f8_mips64,
- gdb_f9_mips64,
- gdb_f10_mips64,
- gdb_f11_mips64,
- gdb_f12_mips64,
- gdb_f13_mips64,
- gdb_f14_mips64,
- gdb_f15_mips64,
- gdb_f16_mips64,
- gdb_f17_mips64,
- gdb_f18_mips64,
- gdb_f19_mips64,
- gdb_f20_mips64,
- gdb_f21_mips64,
- gdb_f22_mips64,
- gdb_f23_mips64,
- gdb_f24_mips64,
- gdb_f25_mips64,
- gdb_f26_mips64,
- gdb_f27_mips64,
- gdb_f28_mips64,
- gdb_f29_mips64,
- gdb_f30_mips64,
- gdb_f31_mips64,
- gdb_fcsr_mips64,
- gdb_fir_mips64,
- gdb_ic_mips64,
- gdb_dummy_mips64,
- gdb_w0_mips64,
- gdb_w1_mips64,
- gdb_w2_mips64,
- gdb_w3_mips64,
- gdb_w4_mips64,
- gdb_w5_mips64,
- gdb_w6_mips64,
- gdb_w7_mips64,
- gdb_w8_mips64,
- gdb_w9_mips64,
- gdb_w10_mips64,
- gdb_w11_mips64,
- gdb_w12_mips64,
- gdb_w13_mips64,
- gdb_w14_mips64,
- gdb_w15_mips64,
- gdb_w16_mips64,
- gdb_w17_mips64,
- gdb_w18_mips64,
- gdb_w19_mips64,
- gdb_w20_mips64,
- gdb_w21_mips64,
- gdb_w22_mips64,
- gdb_w23_mips64,
- gdb_w24_mips64,
- gdb_w25_mips64,
- gdb_w26_mips64,
- gdb_w27_mips64,
- gdb_w28_mips64,
- gdb_w29_mips64,
- gdb_w30_mips64,
- gdb_w31_mips64,
- gdb_mcsr_mips64,
- gdb_mir_mips64,
- gdb_config5_mips64,
+ dwarf_zero_mips64 = 0,
+ dwarf_r1_mips64,
+ dwarf_r2_mips64,
+ dwarf_r3_mips64,
+ dwarf_r4_mips64,
+ dwarf_r5_mips64,
+ dwarf_r6_mips64,
+ dwarf_r7_mips64,
+ dwarf_r8_mips64,
+ dwarf_r9_mips64,
+ dwarf_r10_mips64,
+ dwarf_r11_mips64,
+ dwarf_r12_mips64,
+ dwarf_r13_mips64,
+ dwarf_r14_mips64,
+ dwarf_r15_mips64,
+ dwarf_r16_mips64,
+ dwarf_r17_mips64,
+ dwarf_r18_mips64,
+ dwarf_r19_mips64,
+ dwarf_r20_mips64,
+ dwarf_r21_mips64,
+ dwarf_r22_mips64,
+ dwarf_r23_mips64,
+ dwarf_r24_mips64,
+ dwarf_r25_mips64,
+ dwarf_r26_mips64,
+ dwarf_r27_mips64,
+ dwarf_gp_mips64,
+ dwarf_sp_mips64,
+ dwarf_r30_mips64,
+ dwarf_ra_mips64,
+ dwarf_sr_mips64,
+ dwarf_lo_mips64,
+ dwarf_hi_mips64,
+ dwarf_bad_mips64,
+ dwarf_cause_mips64,
+ dwarf_pc_mips64,
+ dwarf_f0_mips64,
+ dwarf_f1_mips64,
+ dwarf_f2_mips64,
+ dwarf_f3_mips64,
+ dwarf_f4_mips64,
+ dwarf_f5_mips64,
+ dwarf_f6_mips64,
+ dwarf_f7_mips64,
+ dwarf_f8_mips64,
+ dwarf_f9_mips64,
+ dwarf_f10_mips64,
+ dwarf_f11_mips64,
+ dwarf_f12_mips64,
+ dwarf_f13_mips64,
+ dwarf_f14_mips64,
+ dwarf_f15_mips64,
+ dwarf_f16_mips64,
+ dwarf_f17_mips64,
+ dwarf_f18_mips64,
+ dwarf_f19_mips64,
+ dwarf_f20_mips64,
+ dwarf_f21_mips64,
+ dwarf_f22_mips64,
+ dwarf_f23_mips64,
+ dwarf_f24_mips64,
+ dwarf_f25_mips64,
+ dwarf_f26_mips64,
+ dwarf_f27_mips64,
+ dwarf_f28_mips64,
+ dwarf_f29_mips64,
+ dwarf_f30_mips64,
+ dwarf_f31_mips64,
+ dwarf_fcsr_mips64,
+ dwarf_fir_mips64,
+ dwarf_ic_mips64,
+ dwarf_dummy_mips64,
+ dwarf_w0_mips64,
+ dwarf_w1_mips64,
+ dwarf_w2_mips64,
+ dwarf_w3_mips64,
+ dwarf_w4_mips64,
+ dwarf_w5_mips64,
+ dwarf_w6_mips64,
+ dwarf_w7_mips64,
+ dwarf_w8_mips64,
+ dwarf_w9_mips64,
+ dwarf_w10_mips64,
+ dwarf_w11_mips64,
+ dwarf_w12_mips64,
+ dwarf_w13_mips64,
+ dwarf_w14_mips64,
+ dwarf_w15_mips64,
+ dwarf_w16_mips64,
+ dwarf_w17_mips64,
+ dwarf_w18_mips64,
+ dwarf_w19_mips64,
+ dwarf_w20_mips64,
+ dwarf_w21_mips64,
+ dwarf_w22_mips64,
+ dwarf_w23_mips64,
+ dwarf_w24_mips64,
+ dwarf_w25_mips64,
+ dwarf_w26_mips64,
+ dwarf_w27_mips64,
+ dwarf_w28_mips64,
+ dwarf_w29_mips64,
+ dwarf_w30_mips64,
+ dwarf_w31_mips64,
+ dwarf_mcsr_mips64,
+ dwarf_mir_mips64,
+ dwarf_config5_mips64,
};
struct IOVEC_mips
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h
index 7438b88..2e3053c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h
@@ -10,223 +10,114 @@
#ifndef liblldb_RegisterContext_powerpc_H_
#define liblldb_RegisterContext_powerpc_H_
-// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF)
+// eh_frame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF)
enum
{
- gcc_dwarf_r0_powerpc = 0,
- gcc_dwarf_r1_powerpc,
- gcc_dwarf_r2_powerpc,
- gcc_dwarf_r3_powerpc,
- gcc_dwarf_r4_powerpc,
- gcc_dwarf_r5_powerpc,
- gcc_dwarf_r6_powerpc,
- gcc_dwarf_r7_powerpc,
- gcc_dwarf_r8_powerpc,
- gcc_dwarf_r9_powerpc,
- gcc_dwarf_r10_powerpc,
- gcc_dwarf_r11_powerpc,
- gcc_dwarf_r12_powerpc,
- gcc_dwarf_r13_powerpc,
- gcc_dwarf_r14_powerpc,
- gcc_dwarf_r15_powerpc,
- gcc_dwarf_r16_powerpc,
- gcc_dwarf_r17_powerpc,
- gcc_dwarf_r18_powerpc,
- gcc_dwarf_r19_powerpc,
- gcc_dwarf_r20_powerpc,
- gcc_dwarf_r21_powerpc,
- gcc_dwarf_r22_powerpc,
- gcc_dwarf_r23_powerpc,
- gcc_dwarf_r24_powerpc,
- gcc_dwarf_r25_powerpc,
- gcc_dwarf_r26_powerpc,
- gcc_dwarf_r27_powerpc,
- gcc_dwarf_r28_powerpc,
- gcc_dwarf_r29_powerpc,
- gcc_dwarf_r30_powerpc,
- gcc_dwarf_r31_powerpc,
- gcc_dwarf_f0_powerpc,
- gcc_dwarf_f1_powerpc,
- gcc_dwarf_f2_powerpc,
- gcc_dwarf_f3_powerpc,
- gcc_dwarf_f4_powerpc,
- gcc_dwarf_f5_powerpc,
- gcc_dwarf_f6_powerpc,
- gcc_dwarf_f7_powerpc,
- gcc_dwarf_f8_powerpc,
- gcc_dwarf_f9_powerpc,
- gcc_dwarf_f10_powerpc,
- gcc_dwarf_f11_powerpc,
- gcc_dwarf_f12_powerpc,
- gcc_dwarf_f13_powerpc,
- gcc_dwarf_f14_powerpc,
- gcc_dwarf_f15_powerpc,
- gcc_dwarf_f16_powerpc,
- gcc_dwarf_f17_powerpc,
- gcc_dwarf_f18_powerpc,
- gcc_dwarf_f19_powerpc,
- gcc_dwarf_f20_powerpc,
- gcc_dwarf_f21_powerpc,
- gcc_dwarf_f22_powerpc,
- gcc_dwarf_f23_powerpc,
- gcc_dwarf_f24_powerpc,
- gcc_dwarf_f25_powerpc,
- gcc_dwarf_f26_powerpc,
- gcc_dwarf_f27_powerpc,
- gcc_dwarf_f28_powerpc,
- gcc_dwarf_f29_powerpc,
- gcc_dwarf_f30_powerpc,
- gcc_dwarf_f31_powerpc,
- gcc_dwarf_cr_powerpc,
- gcc_dwarf_fpscr_powerpc,
- gcc_dwarf_msr_powerpc,
- gcc_dwarf_vscr_powerpc,
- gcc_dwarf_xer_powerpc = 101,
- gcc_dwarf_lr_powerpc = 108,
- gcc_dwarf_ctr_powerpc,
- gcc_dwarf_pc_powerpc,
- gcc_dwarf_vrsave_powerpc = 356,
- gcc_dwarf_v0_powerpc = 1124,
- gcc_dwarf_v1_powerpc,
- gcc_dwarf_v2_powerpc,
- gcc_dwarf_v3_powerpc,
- gcc_dwarf_v4_powerpc,
- gcc_dwarf_v5_powerpc,
- gcc_dwarf_v6_powerpc,
- gcc_dwarf_v7_powerpc,
- gcc_dwarf_v8_powerpc,
- gcc_dwarf_v9_powerpc,
- gcc_dwarf_v10_powerpc,
- gcc_dwarf_v11_powerpc,
- gcc_dwarf_v12_powerpc,
- gcc_dwarf_v13_powerpc,
- gcc_dwarf_v14_powerpc,
- gcc_dwarf_v15_powerpc,
- gcc_dwarf_v16_powerpc,
- gcc_dwarf_v17_powerpc,
- gcc_dwarf_v18_powerpc,
- gcc_dwarf_v19_powerpc,
- gcc_dwarf_v20_powerpc,
- gcc_dwarf_v21_powerpc,
- gcc_dwarf_v22_powerpc,
- gcc_dwarf_v23_powerpc,
- gcc_dwarf_v24_powerpc,
- gcc_dwarf_v25_powerpc,
- gcc_dwarf_v26_powerpc,
- gcc_dwarf_v27_powerpc,
- gcc_dwarf_v28_powerpc,
- gcc_dwarf_v29_powerpc,
- gcc_dwarf_v30_powerpc,
- gcc_dwarf_v31_powerpc,
-};
-
-// GDB Register numbers (eRegisterKindGDB)
-enum
-{
- gdb_r0_powerpc = 0,
- gdb_r1_powerpc,
- gdb_r2_powerpc,
- gdb_r3_powerpc,
- gdb_r4_powerpc,
- gdb_r5_powerpc,
- gdb_r6_powerpc,
- gdb_r7_powerpc,
- gdb_r8_powerpc,
- gdb_r9_powerpc,
- gdb_r10_powerpc,
- gdb_r11_powerpc,
- gdb_r12_powerpc,
- gdb_r13_powerpc,
- gdb_r14_powerpc,
- gdb_r15_powerpc,
- gdb_r16_powerpc,
- gdb_r17_powerpc,
- gdb_r18_powerpc,
- gdb_r19_powerpc,
- gdb_r20_powerpc,
- gdb_r21_powerpc,
- gdb_r22_powerpc,
- gdb_r23_powerpc,
- gdb_r24_powerpc,
- gdb_r25_powerpc,
- gdb_r26_powerpc,
- gdb_r27_powerpc,
- gdb_r28_powerpc,
- gdb_r29_powerpc,
- gdb_r30_powerpc,
- gdb_r31_powerpc,
- gdb_f0_powerpc,
- gdb_f1_powerpc,
- gdb_f2_powerpc,
- gdb_f3_powerpc,
- gdb_f4_powerpc,
- gdb_f5_powerpc,
- gdb_f6_powerpc,
- gdb_f7_powerpc,
- gdb_f8_powerpc,
- gdb_f9_powerpc,
- gdb_f10_powerpc,
- gdb_f11_powerpc,
- gdb_f12_powerpc,
- gdb_f13_powerpc,
- gdb_f14_powerpc,
- gdb_f15_powerpc,
- gdb_f16_powerpc,
- gdb_f17_powerpc,
- gdb_f18_powerpc,
- gdb_f19_powerpc,
- gdb_f20_powerpc,
- gdb_f21_powerpc,
- gdb_f22_powerpc,
- gdb_f23_powerpc,
- gdb_f24_powerpc,
- gdb_f25_powerpc,
- gdb_f26_powerpc,
- gdb_f27_powerpc,
- gdb_f28_powerpc,
- gdb_f29_powerpc,
- gdb_f30_powerpc,
- gdb_f31_powerpc,
- gdb_pc_powerpc,
- gdb_cr_powerpc = 66,
- gdb_lr_powerpc,
- gdb_ctr_powerpc,
- gdb_xer_powerpc,
- gdb_fpscr_powerpc,
- gdb_v0_powerpc = 106,
- gdb_v1_powerpc,
- gdb_v2_powerpc,
- gdb_v3_powerpc,
- gdb_v4_powerpc,
- gdb_v5_powerpc,
- gdb_v6_powerpc,
- gdb_v7_powerpc,
- gdb_v8_powerpc,
- gdb_v9_powerpc,
- gdb_v10_powerpc,
- gdb_v11_powerpc,
- gdb_v12_powerpc,
- gdb_v13_powerpc,
- gdb_v14_powerpc,
- gdb_v15_powerpc,
- gdb_v16_powerpc,
- gdb_v17_powerpc,
- gdb_v18_powerpc,
- gdb_v19_powerpc,
- gdb_v20_powerpc,
- gdb_v21_powerpc,
- gdb_v22_powerpc,
- gdb_v23_powerpc,
- gdb_v24_powerpc,
- gdb_v25_powerpc,
- gdb_v26_powerpc,
- gdb_v27_powerpc,
- gdb_v28_powerpc,
- gdb_v29_powerpc,
- gdb_v30_powerpc,
- gdb_v31_powerpc,
- gdb_vscr_powerpc,
- gdb_vrsave_powerpc,
+ dwarf_r0_powerpc = 0,
+ dwarf_r1_powerpc,
+ dwarf_r2_powerpc,
+ dwarf_r3_powerpc,
+ dwarf_r4_powerpc,
+ dwarf_r5_powerpc,
+ dwarf_r6_powerpc,
+ dwarf_r7_powerpc,
+ dwarf_r8_powerpc,
+ dwarf_r9_powerpc,
+ dwarf_r10_powerpc,
+ dwarf_r11_powerpc,
+ dwarf_r12_powerpc,
+ dwarf_r13_powerpc,
+ dwarf_r14_powerpc,
+ dwarf_r15_powerpc,
+ dwarf_r16_powerpc,
+ dwarf_r17_powerpc,
+ dwarf_r18_powerpc,
+ dwarf_r19_powerpc,
+ dwarf_r20_powerpc,
+ dwarf_r21_powerpc,
+ dwarf_r22_powerpc,
+ dwarf_r23_powerpc,
+ dwarf_r24_powerpc,
+ dwarf_r25_powerpc,
+ dwarf_r26_powerpc,
+ dwarf_r27_powerpc,
+ dwarf_r28_powerpc,
+ dwarf_r29_powerpc,
+ dwarf_r30_powerpc,
+ dwarf_r31_powerpc,
+ dwarf_f0_powerpc,
+ dwarf_f1_powerpc,
+ dwarf_f2_powerpc,
+ dwarf_f3_powerpc,
+ dwarf_f4_powerpc,
+ dwarf_f5_powerpc,
+ dwarf_f6_powerpc,
+ dwarf_f7_powerpc,
+ dwarf_f8_powerpc,
+ dwarf_f9_powerpc,
+ dwarf_f10_powerpc,
+ dwarf_f11_powerpc,
+ dwarf_f12_powerpc,
+ dwarf_f13_powerpc,
+ dwarf_f14_powerpc,
+ dwarf_f15_powerpc,
+ dwarf_f16_powerpc,
+ dwarf_f17_powerpc,
+ dwarf_f18_powerpc,
+ dwarf_f19_powerpc,
+ dwarf_f20_powerpc,
+ dwarf_f21_powerpc,
+ dwarf_f22_powerpc,
+ dwarf_f23_powerpc,
+ dwarf_f24_powerpc,
+ dwarf_f25_powerpc,
+ dwarf_f26_powerpc,
+ dwarf_f27_powerpc,
+ dwarf_f28_powerpc,
+ dwarf_f29_powerpc,
+ dwarf_f30_powerpc,
+ dwarf_f31_powerpc,
+ dwarf_cr_powerpc,
+ dwarf_fpscr_powerpc,
+ dwarf_msr_powerpc,
+ dwarf_vscr_powerpc,
+ dwarf_xer_powerpc = 101,
+ dwarf_lr_powerpc = 108,
+ dwarf_ctr_powerpc,
+ dwarf_pc_powerpc,
+ dwarf_vrsave_powerpc = 356,
+ dwarf_v0_powerpc = 1124,
+ dwarf_v1_powerpc,
+ dwarf_v2_powerpc,
+ dwarf_v3_powerpc,
+ dwarf_v4_powerpc,
+ dwarf_v5_powerpc,
+ dwarf_v6_powerpc,
+ dwarf_v7_powerpc,
+ dwarf_v8_powerpc,
+ dwarf_v9_powerpc,
+ dwarf_v10_powerpc,
+ dwarf_v11_powerpc,
+ dwarf_v12_powerpc,
+ dwarf_v13_powerpc,
+ dwarf_v14_powerpc,
+ dwarf_v15_powerpc,
+ dwarf_v16_powerpc,
+ dwarf_v17_powerpc,
+ dwarf_v18_powerpc,
+ dwarf_v19_powerpc,
+ dwarf_v20_powerpc,
+ dwarf_v21_powerpc,
+ dwarf_v22_powerpc,
+ dwarf_v23_powerpc,
+ dwarf_v24_powerpc,
+ dwarf_v25_powerpc,
+ dwarf_v26_powerpc,
+ dwarf_v27_powerpc,
+ dwarf_v28_powerpc,
+ dwarf_v29_powerpc,
+ dwarf_v30_powerpc,
+ dwarf_v31_powerpc,
};
#endif // liblldb_RegisterContext_powerpc_H_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h
index 6b3f6fb..252f125 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContext_x86.h
@@ -11,67 +11,56 @@
#define liblldb_RegisterContext_x86_H_
//---------------------------------------------------------------------------
-// i386 gcc, dwarf, gdb enums
+// i386 ehframe, dwarf regnums
//---------------------------------------------------------------------------
-// Register numbers seen in eh_frame (eRegisterKindGCC)
+// Register numbers seen in eh_frame (eRegisterKindEHFrame) on i386 systems (non-Darwin)
//
-// From Jason Molenda: "gcc registers" is the register numbering used in the eh_frame
-// CFI. The only registers that are described in eh_frame CFI are those that are
-// preserved across function calls aka callee-saved aka non-volatile. And none
-// of the floating point registers on x86 are preserved across function calls.
-//
-// The only reason there is a "gcc register" and a "dwarf register" is because of a
-// mistake years and years ago with i386 where they got esp and ebp
-// backwards when they emitted the eh_frame instructions. Once there were
-// binaries In The Wild using the reversed numbering, we had to stick with it
-// forever.
enum
{
- // 2nd parameter in DwarfRegNum() is regnum for exception handling on x86-32.
- // See http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register
- gcc_eax_i386 = 0,
- gcc_ecx_i386,
- gcc_edx_i386,
- gcc_ebx_i386,
+ ehframe_eax_i386 = 0,
+ ehframe_ecx_i386,
+ ehframe_edx_i386,
+ ehframe_ebx_i386,
// on Darwin esp & ebp are reversed in the eh_frame section for i386 (versus dwarf's reg numbering).
// To be specific:
// i386+darwin eh_frame: 4 is ebp, 5 is esp
// i386+everyone else eh_frame: 4 is esp, 5 is ebp
// i386 dwarf: 4 is esp, 5 is ebp
- // lldb will get the darwin-specific eh_frame reg numberings from debugserver instead of here so we
- // only encode the 4 == esp, 5 == ebp numbers in this generic header.
- gcc_esp_i386,
- gcc_ebp_i386,
- gcc_esi_i386,
- gcc_edi_i386,
- gcc_eip_i386,
- gcc_eflags_i386,
- gcc_st0_i386 = 12,
- gcc_st1_i386,
- gcc_st2_i386,
- gcc_st3_i386,
- gcc_st4_i386,
- gcc_st5_i386,
- gcc_st6_i386,
- gcc_st7_i386,
- gcc_xmm0_i386 = 21,
- gcc_xmm1_i386,
- gcc_xmm2_i386,
- gcc_xmm3_i386,
- gcc_xmm4_i386,
- gcc_xmm5_i386,
- gcc_xmm6_i386,
- gcc_xmm7_i386,
- gcc_mm0_i386 = 29,
- gcc_mm1_i386,
- gcc_mm2_i386,
- gcc_mm3_i386,
- gcc_mm4_i386,
- gcc_mm5_i386,
- gcc_mm6_i386,
- gcc_mm7_i386,
+ // lldb will get the darwin-specific eh_frame reg numberings from debugserver, or the ABI, so we
+ // only encode the generally correct 4 == esp, 5 == ebp numbers in this generic header.
+
+ ehframe_esp_i386,
+ ehframe_ebp_i386,
+ ehframe_esi_i386,
+ ehframe_edi_i386,
+ ehframe_eip_i386,
+ ehframe_eflags_i386,
+ ehframe_st0_i386 = 12,
+ ehframe_st1_i386,
+ ehframe_st2_i386,
+ ehframe_st3_i386,
+ ehframe_st4_i386,
+ ehframe_st5_i386,
+ ehframe_st6_i386,
+ ehframe_st7_i386,
+ ehframe_xmm0_i386 = 21,
+ ehframe_xmm1_i386,
+ ehframe_xmm2_i386,
+ ehframe_xmm3_i386,
+ ehframe_xmm4_i386,
+ ehframe_xmm5_i386,
+ ehframe_xmm6_i386,
+ ehframe_xmm7_i386,
+ ehframe_mm0_i386 = 29,
+ ehframe_mm1_i386,
+ ehframe_mm2_i386,
+ ehframe_mm3_i386,
+ ehframe_mm4_i386,
+ ehframe_mm5_i386,
+ ehframe_mm6_i386,
+ ehframe_mm7_i386,
};
// DWARF register numbers (eRegisterKindDWARF)
@@ -130,258 +119,109 @@ enum
// then differentiate based on size of the register.
};
-// Register numbers GDB uses (eRegisterKindGDB)
-//
-// From Jason Molenda: The "gdb numbers" are what you would see in the stabs debug format.
-enum
-{
- gdb_eax_i386,
- gdb_ecx_i386,
- gdb_edx_i386,
- gdb_ebx_i386,
- gdb_esp_i386,
- gdb_ebp_i386,
- gdb_esi_i386,
- gdb_edi_i386,
- gdb_eip_i386,
- gdb_eflags_i386,
- gdb_cs_i386,
- gdb_ss_i386,
- gdb_ds_i386,
- gdb_es_i386,
- gdb_fs_i386,
- gdb_gs_i386,
- gdb_st0_i386 = 16,
- gdb_st1_i386,
- gdb_st2_i386,
- gdb_st3_i386,
- gdb_st4_i386,
- gdb_st5_i386,
- gdb_st6_i386,
- gdb_st7_i386,
- gdb_fctrl_i386, // FPU Control Word
- gdb_fstat_i386, // FPU Status Word
- gdb_ftag_i386, // FPU Tag Word
- gdb_fiseg_i386, // FPU IP Selector
- gdb_fioff_i386, // FPU IP Offset
- gdb_foseg_i386, // FPU Operand Pointer Selector
- gdb_fooff_i386, // FPU Operand Pointer Offset
- gdb_fop_i386, // Last Instruction Opcode
- gdb_xmm0_i386 = 32,
- gdb_xmm1_i386,
- gdb_xmm2_i386,
- gdb_xmm3_i386,
- gdb_xmm4_i386,
- gdb_xmm5_i386,
- gdb_xmm6_i386,
- gdb_xmm7_i386,
- gdb_mxcsr_i386 = 40,
- gdb_ymm0h_i386,
- gdb_ymm1h_i386,
- gdb_ymm2h_i386,
- gdb_ymm3h_i386,
- gdb_ymm4h_i386,
- gdb_ymm5h_i386,
- gdb_ymm6h_i386,
- gdb_ymm7h_i386,
- gdb_mm0_i386,
- gdb_mm1_i386,
- gdb_mm2_i386,
- gdb_mm3_i386,
- gdb_mm4_i386,
- gdb_mm5_i386,
- gdb_mm6_i386,
- gdb_mm7_i386,
-};
-
//---------------------------------------------------------------------------
-// AMD x86_64, AMD64, Intel EM64T, or Intel 64 gcc, dwarf, gdb enums
+// AMD x86_64, AMD64, Intel EM64T, or Intel 64 ehframe, dwarf regnums
//---------------------------------------------------------------------------
-// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF)
+// EHFrame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF)
// This is the spec I used (as opposed to x86-64-abi-0.99.pdf):
// http://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf
enum
{
// GP Registers
- gcc_dwarf_rax_x86_64 = 0,
- gcc_dwarf_rdx_x86_64,
- gcc_dwarf_rcx_x86_64,
- gcc_dwarf_rbx_x86_64,
- gcc_dwarf_rsi_x86_64,
- gcc_dwarf_rdi_x86_64,
- gcc_dwarf_rbp_x86_64,
- gcc_dwarf_rsp_x86_64,
+ dwarf_rax_x86_64 = 0,
+ dwarf_rdx_x86_64,
+ dwarf_rcx_x86_64,
+ dwarf_rbx_x86_64,
+ dwarf_rsi_x86_64,
+ dwarf_rdi_x86_64,
+ dwarf_rbp_x86_64,
+ dwarf_rsp_x86_64,
// Extended GP Registers
- gcc_dwarf_r8_x86_64 = 8,
- gcc_dwarf_r9_x86_64,
- gcc_dwarf_r10_x86_64,
- gcc_dwarf_r11_x86_64,
- gcc_dwarf_r12_x86_64,
- gcc_dwarf_r13_x86_64,
- gcc_dwarf_r14_x86_64,
- gcc_dwarf_r15_x86_64,
+ dwarf_r8_x86_64 = 8,
+ dwarf_r9_x86_64,
+ dwarf_r10_x86_64,
+ dwarf_r11_x86_64,
+ dwarf_r12_x86_64,
+ dwarf_r13_x86_64,
+ dwarf_r14_x86_64,
+ dwarf_r15_x86_64,
// Return Address (RA) mapped to RIP
- gcc_dwarf_rip_x86_64 = 16,
+ dwarf_rip_x86_64 = 16,
// SSE Vector Registers
- gcc_dwarf_xmm0_x86_64 = 17,
- gcc_dwarf_xmm1_x86_64,
- gcc_dwarf_xmm2_x86_64,
- gcc_dwarf_xmm3_x86_64,
- gcc_dwarf_xmm4_x86_64,
- gcc_dwarf_xmm5_x86_64,
- gcc_dwarf_xmm6_x86_64,
- gcc_dwarf_xmm7_x86_64,
- gcc_dwarf_xmm8_x86_64,
- gcc_dwarf_xmm9_x86_64,
- gcc_dwarf_xmm10_x86_64,
- gcc_dwarf_xmm11_x86_64,
- gcc_dwarf_xmm12_x86_64,
- gcc_dwarf_xmm13_x86_64,
- gcc_dwarf_xmm14_x86_64,
- gcc_dwarf_xmm15_x86_64,
+ dwarf_xmm0_x86_64 = 17,
+ dwarf_xmm1_x86_64,
+ dwarf_xmm2_x86_64,
+ dwarf_xmm3_x86_64,
+ dwarf_xmm4_x86_64,
+ dwarf_xmm5_x86_64,
+ dwarf_xmm6_x86_64,
+ dwarf_xmm7_x86_64,
+ dwarf_xmm8_x86_64,
+ dwarf_xmm9_x86_64,
+ dwarf_xmm10_x86_64,
+ dwarf_xmm11_x86_64,
+ dwarf_xmm12_x86_64,
+ dwarf_xmm13_x86_64,
+ dwarf_xmm14_x86_64,
+ dwarf_xmm15_x86_64,
// Floating Point Registers
- gcc_dwarf_st0_x86_64 = 33,
- gcc_dwarf_st1_x86_64,
- gcc_dwarf_st2_x86_64,
- gcc_dwarf_st3_x86_64,
- gcc_dwarf_st4_x86_64,
- gcc_dwarf_st5_x86_64,
- gcc_dwarf_st6_x86_64,
- gcc_dwarf_st7_x86_64,
+ dwarf_st0_x86_64 = 33,
+ dwarf_st1_x86_64,
+ dwarf_st2_x86_64,
+ dwarf_st3_x86_64,
+ dwarf_st4_x86_64,
+ dwarf_st5_x86_64,
+ dwarf_st6_x86_64,
+ dwarf_st7_x86_64,
// MMX Registers
- gcc_dwarf_mm0_x86_64 = 41,
- gcc_dwarf_mm1_x86_64,
- gcc_dwarf_mm2_x86_64,
- gcc_dwarf_mm3_x86_64,
- gcc_dwarf_mm4_x86_64,
- gcc_dwarf_mm5_x86_64,
- gcc_dwarf_mm6_x86_64,
- gcc_dwarf_mm7_x86_64,
+ dwarf_mm0_x86_64 = 41,
+ dwarf_mm1_x86_64,
+ dwarf_mm2_x86_64,
+ dwarf_mm3_x86_64,
+ dwarf_mm4_x86_64,
+ dwarf_mm5_x86_64,
+ dwarf_mm6_x86_64,
+ dwarf_mm7_x86_64,
// Control and Status Flags Register
- gcc_dwarf_rflags_x86_64 = 49,
+ dwarf_rflags_x86_64 = 49,
// selector registers
- gcc_dwarf_es_x86_64 = 50,
- gcc_dwarf_cs_x86_64,
- gcc_dwarf_ss_x86_64,
- gcc_dwarf_ds_x86_64,
- gcc_dwarf_fs_x86_64,
- gcc_dwarf_gs_x86_64,
+ dwarf_es_x86_64 = 50,
+ dwarf_cs_x86_64,
+ dwarf_ss_x86_64,
+ dwarf_ds_x86_64,
+ dwarf_fs_x86_64,
+ dwarf_gs_x86_64,
// Floating point control registers
- gcc_dwarf_mxcsr_x86_64 = 64, // Media Control and Status
- gcc_dwarf_fctrl_x86_64, // x87 control word
- gcc_dwarf_fstat_x86_64, // x87 status word
+ dwarf_mxcsr_x86_64 = 64, // Media Control and Status
+ dwarf_fctrl_x86_64, // x87 control word
+ dwarf_fstat_x86_64, // x87 status word
// Upper Vector Registers
- gcc_dwarf_ymm0h_x86_64 = 67,
- gcc_dwarf_ymm1h_x86_64,
- gcc_dwarf_ymm2h_x86_64,
- gcc_dwarf_ymm3h_x86_64,
- gcc_dwarf_ymm4h_x86_64,
- gcc_dwarf_ymm5h_x86_64,
- gcc_dwarf_ymm6h_x86_64,
- gcc_dwarf_ymm7h_x86_64,
- gcc_dwarf_ymm8h_x86_64,
- gcc_dwarf_ymm9h_x86_64,
- gcc_dwarf_ymm10h_x86_64,
- gcc_dwarf_ymm11h_x86_64,
- gcc_dwarf_ymm12h_x86_64,
- gcc_dwarf_ymm13h_x86_64,
- gcc_dwarf_ymm14h_x86_64,
- gcc_dwarf_ymm15h_x86_64,
+ dwarf_ymm0h_x86_64 = 67,
+ dwarf_ymm1h_x86_64,
+ dwarf_ymm2h_x86_64,
+ dwarf_ymm3h_x86_64,
+ dwarf_ymm4h_x86_64,
+ dwarf_ymm5h_x86_64,
+ dwarf_ymm6h_x86_64,
+ dwarf_ymm7h_x86_64,
+ dwarf_ymm8h_x86_64,
+ dwarf_ymm9h_x86_64,
+ dwarf_ymm10h_x86_64,
+ dwarf_ymm11h_x86_64,
+ dwarf_ymm12h_x86_64,
+ dwarf_ymm13h_x86_64,
+ dwarf_ymm14h_x86_64,
+ dwarf_ymm15h_x86_64,
// AVX2 Vector Mask Registers
- // gcc_dwarf_k0_x86_64 = 118,
- // gcc_dwarf_k1_x86_64,
- // gcc_dwarf_k2_x86_64,
- // gcc_dwarf_k3_x86_64,
- // gcc_dwarf_k4_x86_64,
- // gcc_dwarf_k5_x86_64,
- // gcc_dwarf_k6_x86_64,
- // gcc_dwarf_k7_x86_64,
-};
-
-// GDB Register numbers (eRegisterKindGDB)
-enum
-{
- // GP Registers
- gdb_rax_x86_64 = 0,
- gdb_rbx_x86_64,
- gdb_rcx_x86_64,
- gdb_rdx_x86_64,
- gdb_rsi_x86_64,
- gdb_rdi_x86_64,
- gdb_rbp_x86_64,
- gdb_rsp_x86_64,
- // Extended GP Registers
- gdb_r8_x86_64,
- gdb_r9_x86_64,
- gdb_r10_x86_64,
- gdb_r11_x86_64,
- gdb_r12_x86_64,
- gdb_r13_x86_64,
- gdb_r14_x86_64,
- gdb_r15_x86_64,
- // Return Address (RA) mapped to RIP
- gdb_rip_x86_64,
- // Control and Status Flags Register
- gdb_rflags_x86_64,
- gdb_cs_x86_64,
- gdb_ss_x86_64,
- gdb_ds_x86_64,
- gdb_es_x86_64,
- gdb_fs_x86_64,
- gdb_gs_x86_64,
- // Floating Point Registers
- gdb_st0_x86_64,
- gdb_st1_x86_64,
- gdb_st2_x86_64,
- gdb_st3_x86_64,
- gdb_st4_x86_64,
- gdb_st5_x86_64,
- gdb_st6_x86_64,
- gdb_st7_x86_64,
- gdb_fctrl_x86_64,
- gdb_fstat_x86_64,
- gdb_ftag_x86_64,
- gdb_fiseg_x86_64,
- gdb_fioff_x86_64,
- gdb_foseg_x86_64,
- gdb_fooff_x86_64,
- gdb_fop_x86_64,
- // SSE Vector Registers
- gdb_xmm0_x86_64 = 40,
- gdb_xmm1_x86_64,
- gdb_xmm2_x86_64,
- gdb_xmm3_x86_64,
- gdb_xmm4_x86_64,
- gdb_xmm5_x86_64,
- gdb_xmm6_x86_64,
- gdb_xmm7_x86_64,
- gdb_xmm8_x86_64,
- gdb_xmm9_x86_64,
- gdb_xmm10_x86_64,
- gdb_xmm11_x86_64,
- gdb_xmm12_x86_64,
- gdb_xmm13_x86_64,
- gdb_xmm14_x86_64,
- gdb_xmm15_x86_64,
- // Floating point control registers
- gdb_mxcsr_x86_64 = 56,
- gdb_ymm0h_x86_64,
- gdb_ymm1h_x86_64,
- gdb_ymm2h_x86_64,
- gdb_ymm3h_x86_64,
- gdb_ymm4h_x86_64,
- gdb_ymm5h_x86_64,
- gdb_ymm6h_x86_64,
- gdb_ymm7h_x86_64,
- gdb_ymm8h_x86_64,
- gdb_ymm9h_x86_64,
- gdb_ymm10h_x86_64,
- gdb_ymm11h_x86_64,
- gdb_ymm12h_x86_64,
- gdb_ymm13h_x86_64,
- gdb_ymm14h_x86_64,
- gdb_ymm15h_x86_64
+ // dwarf_k0_x86_64 = 118,
+ // dwarf_k1_x86_64,
+ // dwarf_k2_x86_64,
+ // dwarf_k3_x86_64,
+ // dwarf_k4_x86_64,
+ // dwarf_k5_x86_64,
+ // dwarf_k6_x86_64,
+ // dwarf_k7_x86_64,
};
//---------------------------------------------------------------------------
@@ -404,7 +244,8 @@ struct FXSAVE
{
uint16_t fctrl; // FPU Control Word (fcw)
uint16_t fstat; // FPU Status Word (fsw)
- uint16_t ftag; // FPU Tag Word (ftw)
+ uint8_t ftag; // FPU Tag Word (ftw)
+ uint8_t reserved_1; // Reserved
uint16_t fop; // Last Instruction Opcode (fop)
union
{
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
index 94cb5cc..801885d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
@@ -10,6 +10,8 @@
#ifndef lldb_RegisterInfoInterface_h
#define lldb_RegisterInfoInterface_h
+#include <vector>
+
#include "lldb/Core/ArchSpec.h"
namespace lldb_private
@@ -50,6 +52,26 @@ namespace lldb_private
GetTargetArchitecture() const
{ return m_target_arch; }
+ virtual const lldb_private::RegisterInfo *
+ GetDynamicRegisterInfo(const char *reg_name) const
+ {
+ const std::vector <lldb_private::RegisterInfo> * d_register_infos = GetDynamicRegisterInfoP();
+ if(d_register_infos != nullptr)
+ {
+ std::vector <lldb_private::RegisterInfo> ::const_iterator pos = d_register_infos->begin();
+ for(; pos < d_register_infos->end() ; pos++)
+ {
+ if(::strcmp(reg_name, pos->name) == 0)
+ return(d_register_infos->data() + (pos - d_register_infos->begin()) );
+ }
+ }
+ return nullptr;
+ }
+
+ virtual const std::vector<lldb_private::RegisterInfo> *
+ GetDynamicRegisterInfoP() const
+ { return nullptr; }
+
public:
// FIXME make private.
lldb_private::ArchSpec m_target_arch;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
index 3d144d6..0345772 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
@@ -1,21 +1,25 @@
-//===-- RegisterInfos_arm.h ----------------------------------*- C++ -*-===//
+//===-- RegisterInfos_arm.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
#ifdef DECLARE_REGISTER_INFOS_ARM_STRUCT
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
-#include "Utility/ARM_GCC_Registers.h"
+#include "Utility/ARM_ehframe_Registers.h"
#include "Utility/ARM_DWARF_Registers.h"
using namespace lldb;
@@ -25,17 +29,16 @@ using namespace lldb_private;
#error GPR_OFFSET must be defined before including this header file
#endif
-
#ifndef FPU_OFFSET
#error FPU_OFFSET must be defined before including this header file
#endif
-#ifndef EXC_OFFSET
-#error EXC_OFFSET_NAME must be defined before including this header file
+#ifndef FPSCR_OFFSET
+#error FPSCR_OFFSET must be defined before including this header file
#endif
-#ifndef DBG_OFFSET
-#error DBG_OFFSET_NAME must be defined before including this header file
+#ifndef EXC_OFFSET
+#error EXC_OFFSET_NAME must be defined before including this header file
#endif
#ifndef DEFINE_DBG
@@ -96,6 +99,56 @@ enum
fpu_s31,
fpu_fpscr,
+ fpu_d0,
+ fpu_d1,
+ fpu_d2,
+ fpu_d3,
+ fpu_d4,
+ fpu_d5,
+ fpu_d6,
+ fpu_d7,
+ fpu_d8,
+ fpu_d9,
+ fpu_d10,
+ fpu_d11,
+ fpu_d12,
+ fpu_d13,
+ fpu_d14,
+ fpu_d15,
+ fpu_d16,
+ fpu_d17,
+ fpu_d18,
+ fpu_d19,
+ fpu_d20,
+ fpu_d21,
+ fpu_d22,
+ fpu_d23,
+ fpu_d24,
+ fpu_d25,
+ fpu_d26,
+ fpu_d27,
+ fpu_d28,
+ fpu_d29,
+ fpu_d30,
+ fpu_d31,
+
+ fpu_q0,
+ fpu_q1,
+ fpu_q2,
+ fpu_q3,
+ fpu_q4,
+ fpu_q5,
+ fpu_q6,
+ fpu_q7,
+ fpu_q8,
+ fpu_q9,
+ fpu_q10,
+ fpu_q11,
+ fpu_q12,
+ fpu_q13,
+ fpu_q14,
+ fpu_q15,
+
exc_exception,
exc_fsr,
exc_far,
@@ -171,65 +224,214 @@ enum
k_num_registers
};
+static uint32_t g_s0_invalidates[] = { fpu_d0, fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_s1_invalidates[] = { fpu_d0, fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_s2_invalidates[] = { fpu_d1, fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_s3_invalidates[] = { fpu_d1, fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_s4_invalidates[] = { fpu_d2, fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_s5_invalidates[] = { fpu_d2, fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_s6_invalidates[] = { fpu_d3, fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_s7_invalidates[] = { fpu_d3, fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_s8_invalidates[] = { fpu_d4, fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_s9_invalidates[] = { fpu_d4, fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_s10_invalidates[] = { fpu_d5, fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_s11_invalidates[] = { fpu_d5, fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_s12_invalidates[] = { fpu_d6, fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_s13_invalidates[] = { fpu_d6, fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_s14_invalidates[] = { fpu_d7, fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_s15_invalidates[] = { fpu_d7, fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_s16_invalidates[] = { fpu_d8, fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_s17_invalidates[] = { fpu_d8, fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_s18_invalidates[] = { fpu_d9, fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_s19_invalidates[] = { fpu_d9, fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_s20_invalidates[] = { fpu_d10, fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_s21_invalidates[] = { fpu_d10, fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_s22_invalidates[] = { fpu_d11, fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_s23_invalidates[] = { fpu_d11, fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_s24_invalidates[] = { fpu_d12, fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_s25_invalidates[] = { fpu_d12, fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_s26_invalidates[] = { fpu_d13, fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_s27_invalidates[] = { fpu_d13, fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_s28_invalidates[] = { fpu_d14, fpu_q7, LLDB_INVALID_REGNUM };
+static uint32_t g_s29_invalidates[] = { fpu_d14, fpu_q7, LLDB_INVALID_REGNUM };
+static uint32_t g_s30_invalidates[] = { fpu_d15, fpu_q7, LLDB_INVALID_REGNUM };
+static uint32_t g_s31_invalidates[] = { fpu_d15, fpu_q7, LLDB_INVALID_REGNUM };
+
+static uint32_t g_d0_contains[] = { fpu_s0, fpu_s1, LLDB_INVALID_REGNUM };
+static uint32_t g_d1_contains[] = { fpu_s2, fpu_s3, LLDB_INVALID_REGNUM };
+static uint32_t g_d2_contains[] = { fpu_s4, fpu_s5, LLDB_INVALID_REGNUM };
+static uint32_t g_d3_contains[] = { fpu_s6, fpu_s7, LLDB_INVALID_REGNUM };
+static uint32_t g_d4_contains[] = { fpu_s8, fpu_s9, LLDB_INVALID_REGNUM };
+static uint32_t g_d5_contains[] = { fpu_s10, fpu_s11, LLDB_INVALID_REGNUM };
+static uint32_t g_d6_contains[] = { fpu_s12, fpu_s13, LLDB_INVALID_REGNUM };
+static uint32_t g_d7_contains[] = { fpu_s14, fpu_s15, LLDB_INVALID_REGNUM };
+static uint32_t g_d8_contains[] = { fpu_s16, fpu_s17, LLDB_INVALID_REGNUM };
+static uint32_t g_d9_contains[] = { fpu_s18, fpu_s19, LLDB_INVALID_REGNUM };
+static uint32_t g_d10_contains[] = { fpu_s20, fpu_s21, LLDB_INVALID_REGNUM };
+static uint32_t g_d11_contains[] = { fpu_s22, fpu_s23, LLDB_INVALID_REGNUM };
+static uint32_t g_d12_contains[] = { fpu_s24, fpu_s25, LLDB_INVALID_REGNUM };
+static uint32_t g_d13_contains[] = { fpu_s26, fpu_s27, LLDB_INVALID_REGNUM };
+static uint32_t g_d14_contains[] = { fpu_s28, fpu_s29, LLDB_INVALID_REGNUM };
+static uint32_t g_d15_contains[] = { fpu_s30, fpu_s31, LLDB_INVALID_REGNUM };
+
+static uint32_t g_d0_invalidates[] = { fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_d1_invalidates[] = { fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_d2_invalidates[] = { fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_d3_invalidates[] = { fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_d4_invalidates[] = { fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_d5_invalidates[] = { fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_d6_invalidates[] = { fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_d7_invalidates[] = { fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_d8_invalidates[] = { fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_d9_invalidates[] = { fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_d10_invalidates[] = { fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_d11_invalidates[] = { fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_d12_invalidates[] = { fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_d13_invalidates[] = { fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_d14_invalidates[] = { fpu_q7, LLDB_INVALID_REGNUM };
+static uint32_t g_d15_invalidates[] = { fpu_q7, LLDB_INVALID_REGNUM };
+static uint32_t g_d16_invalidates[] = { fpu_q8, LLDB_INVALID_REGNUM };
+static uint32_t g_d17_invalidates[] = { fpu_q8, LLDB_INVALID_REGNUM };
+static uint32_t g_d18_invalidates[] = { fpu_q9, LLDB_INVALID_REGNUM };
+static uint32_t g_d19_invalidates[] = { fpu_q9, LLDB_INVALID_REGNUM };
+static uint32_t g_d20_invalidates[] = { fpu_q10, LLDB_INVALID_REGNUM };
+static uint32_t g_d21_invalidates[] = { fpu_q10, LLDB_INVALID_REGNUM };
+static uint32_t g_d22_invalidates[] = { fpu_q11, LLDB_INVALID_REGNUM };
+static uint32_t g_d23_invalidates[] = { fpu_q11, LLDB_INVALID_REGNUM };
+static uint32_t g_d24_invalidates[] = { fpu_q12, LLDB_INVALID_REGNUM };
+static uint32_t g_d25_invalidates[] = { fpu_q12, LLDB_INVALID_REGNUM };
+static uint32_t g_d26_invalidates[] = { fpu_q13, LLDB_INVALID_REGNUM };
+static uint32_t g_d27_invalidates[] = { fpu_q13, LLDB_INVALID_REGNUM };
+static uint32_t g_d28_invalidates[] = { fpu_q14, LLDB_INVALID_REGNUM };
+static uint32_t g_d29_invalidates[] = { fpu_q14, LLDB_INVALID_REGNUM };
+static uint32_t g_d30_invalidates[] = { fpu_q15, LLDB_INVALID_REGNUM };
+static uint32_t g_d31_invalidates[] = { fpu_q15, LLDB_INVALID_REGNUM };
+
+static uint32_t g_q0_contains[] = { fpu_d0, fpu_d1, fpu_s0, fpu_s1, fpu_s2, fpu_s3, LLDB_INVALID_REGNUM };
+static uint32_t g_q1_contains[] = { fpu_d2, fpu_d3, fpu_s4, fpu_s5, fpu_s6, fpu_s7, LLDB_INVALID_REGNUM };
+static uint32_t g_q2_contains[] = { fpu_d4, fpu_d5, fpu_s8, fpu_s9, fpu_s10, fpu_s11, LLDB_INVALID_REGNUM };
+static uint32_t g_q3_contains[] = { fpu_d6, fpu_d7, fpu_s12, fpu_s13, fpu_s14, fpu_s15, LLDB_INVALID_REGNUM };
+static uint32_t g_q4_contains[] = { fpu_d8, fpu_d9, fpu_s16, fpu_s17, fpu_s18, fpu_s19, LLDB_INVALID_REGNUM };
+static uint32_t g_q5_contains[] = { fpu_d10, fpu_d11, fpu_s20, fpu_s21, fpu_s22, fpu_s23, LLDB_INVALID_REGNUM };
+static uint32_t g_q6_contains[] = { fpu_d12, fpu_d13, fpu_s24, fpu_s25, fpu_s26, fpu_s27, LLDB_INVALID_REGNUM };
+static uint32_t g_q7_contains[] = { fpu_d14, fpu_d15, fpu_s28, fpu_s29, fpu_s30, fpu_s31, LLDB_INVALID_REGNUM };
+static uint32_t g_q8_contains[] = { fpu_d16, fpu_d17, LLDB_INVALID_REGNUM };
+static uint32_t g_q9_contains[] = { fpu_d18, fpu_d19, LLDB_INVALID_REGNUM };
+static uint32_t g_q10_contains[] = { fpu_d20, fpu_d21, LLDB_INVALID_REGNUM };
+static uint32_t g_q11_contains[] = { fpu_d22, fpu_d23, LLDB_INVALID_REGNUM };
+static uint32_t g_q12_contains[] = { fpu_d24, fpu_d25, LLDB_INVALID_REGNUM };
+static uint32_t g_q13_contains[] = { fpu_d26, fpu_d27, LLDB_INVALID_REGNUM };
+static uint32_t g_q14_contains[] = { fpu_d28, fpu_d29, LLDB_INVALID_REGNUM };
+static uint32_t g_q15_contains[] = { fpu_d30, fpu_d31, LLDB_INVALID_REGNUM };
+
static RegisterInfo g_register_infos_arm[] = {
-// General purpose registers
-// NAME ALT SZ OFFSET ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
-// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= ========== ===============
-{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, gpr_r0 }, NULL, NULL},
-{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, gpr_r1 }, NULL, NULL},
-{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, gpr_r2 }, NULL, NULL},
-{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, gpr_r3 }, NULL, NULL},
-{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, gpr_r4 }, NULL, NULL},
-{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, gpr_r5 }, NULL, NULL},
-{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, gpr_r6 }, NULL, NULL},
-{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_INVALID_REGNUM, gdb_arm_r7, gpr_r7 }, NULL, NULL},
-{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, gpr_r8 }, NULL, NULL},
-{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, gpr_r9 }, NULL, NULL},
-{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, gpr_r10 }, NULL, NULL},
-{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, gdb_arm_r11, gpr_r11 }, NULL, NULL},
-{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, gpr_r12 }, NULL, NULL},
-{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, gpr_sp }, NULL, NULL},
-{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, gpr_lr }, NULL, NULL},
-{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, gpr_pc }, NULL, NULL},
-{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, gpr_cpsr }, NULL, NULL},
-
-{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, fpu_s0 }, NULL, NULL},
-{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, fpu_s1 }, NULL, NULL},
-{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, fpu_s2 }, NULL, NULL},
-{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, fpu_s3 }, NULL, NULL},
-{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, fpu_s4 }, NULL, NULL},
-{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, fpu_s5 }, NULL, NULL},
-{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, fpu_s6 }, NULL, NULL},
-{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, fpu_s7 }, NULL, NULL},
-{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, fpu_s8 }, NULL, NULL},
-{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, fpu_s9 }, NULL, NULL},
-{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, fpu_s10 }, NULL, NULL},
-{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, fpu_s11 }, NULL, NULL},
-{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, fpu_s12 }, NULL, NULL},
-{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, fpu_s13 }, NULL, NULL},
-{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, fpu_s14 }, NULL, NULL},
-{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, fpu_s15 }, NULL, NULL},
-{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, fpu_s16 }, NULL, NULL},
-{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, fpu_s17 }, NULL, NULL},
-{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, fpu_s18 }, NULL, NULL},
-{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, fpu_s19 }, NULL, NULL},
-{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, fpu_s20 }, NULL, NULL},
-{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, fpu_s21 }, NULL, NULL},
-{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, fpu_s22 }, NULL, NULL},
-{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, fpu_s23 }, NULL, NULL},
-{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, fpu_s24 }, NULL, NULL},
-{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, fpu_s25 }, NULL, NULL},
-{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, fpu_s26 }, NULL, NULL},
-{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, fpu_s27 }, NULL, NULL},
-{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, fpu_s28 }, NULL, NULL},
-{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, fpu_s29 }, NULL, NULL},
-{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, fpu_s30 }, NULL, NULL},
-{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, fpu_s31 }, NULL, NULL},
-{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, fpu_fpscr }, NULL, NULL},
-
-{ "exception",NULL, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, NULL, NULL},
-{ "fsr", NULL, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }, NULL, NULL},
-{ "far", NULL, 4, EXC_OFFSET(2), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, NULL, NULL},
+// NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
+// =========== ======= == ============== ================ ==================== =================== =================== ========================== =================== ============= ============== =================
+{ "r0", nullptr, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, gpr_r0 }, nullptr, nullptr },
+{ "r1", nullptr, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, gpr_r1 }, nullptr, nullptr },
+{ "r2", nullptr, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, gpr_r2 }, nullptr, nullptr },
+{ "r3", nullptr, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, gpr_r3 }, nullptr, nullptr },
+{ "r4", nullptr, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r4 }, nullptr, nullptr },
+{ "r5", nullptr, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r5 }, nullptr, nullptr },
+{ "r6", nullptr, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r6 }, nullptr, nullptr },
+{ "r7", nullptr, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { ehframe_r7, dwarf_r7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r7 }, nullptr, nullptr },
+{ "r8", nullptr, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r8 }, nullptr, nullptr },
+{ "r9", nullptr, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r9 }, nullptr, nullptr },
+{ "r10", nullptr, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r10 }, nullptr, nullptr },
+{ "r11", nullptr, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { ehframe_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_r11 }, nullptr, nullptr },
+{ "r12", nullptr, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r12 }, nullptr, nullptr },
+{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_sp }, nullptr, nullptr },
+{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_lr }, nullptr, nullptr },
+{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc }, nullptr, nullptr },
+{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_cpsr }, nullptr, nullptr },
+
+{ "s0", nullptr, 4, FPU_OFFSET(0), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s0 }, nullptr, g_s0_invalidates },
+{ "s1", nullptr, 4, FPU_OFFSET(1), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s1 }, nullptr, g_s1_invalidates },
+{ "s2", nullptr, 4, FPU_OFFSET(2), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s2 }, nullptr, g_s2_invalidates },
+{ "s3", nullptr, 4, FPU_OFFSET(3), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s3 }, nullptr, g_s3_invalidates },
+{ "s4", nullptr, 4, FPU_OFFSET(4), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s4 }, nullptr, g_s4_invalidates },
+{ "s5", nullptr, 4, FPU_OFFSET(5), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s5 }, nullptr, g_s5_invalidates },
+{ "s6", nullptr, 4, FPU_OFFSET(6), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s6 }, nullptr, g_s6_invalidates },
+{ "s7", nullptr, 4, FPU_OFFSET(7), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s7 }, nullptr, g_s7_invalidates },
+{ "s8", nullptr, 4, FPU_OFFSET(8), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s8 }, nullptr, g_s8_invalidates },
+{ "s9", nullptr, 4, FPU_OFFSET(9), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s9 }, nullptr, g_s9_invalidates },
+{ "s10", nullptr, 4, FPU_OFFSET(10), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s10 }, nullptr, g_s10_invalidates },
+{ "s11", nullptr, 4, FPU_OFFSET(11), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s11 }, nullptr, g_s11_invalidates },
+{ "s12", nullptr, 4, FPU_OFFSET(12), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s12 }, nullptr, g_s12_invalidates },
+{ "s13", nullptr, 4, FPU_OFFSET(13), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s13 }, nullptr, g_s13_invalidates },
+{ "s14", nullptr, 4, FPU_OFFSET(14), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s14 }, nullptr, g_s14_invalidates },
+{ "s15", nullptr, 4, FPU_OFFSET(15), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s15 }, nullptr, g_s15_invalidates },
+{ "s16", nullptr, 4, FPU_OFFSET(16), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s16 }, nullptr, g_s16_invalidates },
+{ "s17", nullptr, 4, FPU_OFFSET(17), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s17 }, nullptr, g_s17_invalidates },
+{ "s18", nullptr, 4, FPU_OFFSET(18), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s18 }, nullptr, g_s18_invalidates },
+{ "s19", nullptr, 4, FPU_OFFSET(19), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s19 }, nullptr, g_s19_invalidates },
+{ "s20", nullptr, 4, FPU_OFFSET(20), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s20 }, nullptr, g_s20_invalidates },
+{ "s21", nullptr, 4, FPU_OFFSET(21), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s21 }, nullptr, g_s21_invalidates },
+{ "s22", nullptr, 4, FPU_OFFSET(22), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s22 }, nullptr, g_s22_invalidates },
+{ "s23", nullptr, 4, FPU_OFFSET(23), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s23 }, nullptr, g_s23_invalidates },
+{ "s24", nullptr, 4, FPU_OFFSET(24), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s24 }, nullptr, g_s24_invalidates },
+{ "s25", nullptr, 4, FPU_OFFSET(25), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s25 }, nullptr, g_s25_invalidates },
+{ "s26", nullptr, 4, FPU_OFFSET(26), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s26 }, nullptr, g_s26_invalidates },
+{ "s27", nullptr, 4, FPU_OFFSET(27), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s27 }, nullptr, g_s27_invalidates },
+{ "s28", nullptr, 4, FPU_OFFSET(28), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s28 }, nullptr, g_s28_invalidates },
+{ "s29", nullptr, 4, FPU_OFFSET(29), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s29 }, nullptr, g_s29_invalidates },
+{ "s30", nullptr, 4, FPU_OFFSET(30), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s30 }, nullptr, g_s30_invalidates },
+{ "s31", nullptr, 4, FPU_OFFSET(31), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s31 }, nullptr, g_s31_invalidates },
+{ "fpscr", nullptr, 4, FPSCR_OFFSET, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpscr }, nullptr, nullptr },
+
+{ "d0", nullptr, 8, FPU_OFFSET(0), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d0 }, g_d0_contains, g_d0_invalidates },
+{ "d1", nullptr, 8, FPU_OFFSET(2), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d1 }, g_d1_contains, g_d1_invalidates },
+{ "d2", nullptr, 8, FPU_OFFSET(4), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d2 }, g_d2_contains, g_d2_invalidates },
+{ "d3", nullptr, 8, FPU_OFFSET(6), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d3 }, g_d3_contains, g_d3_invalidates },
+{ "d4", nullptr, 8, FPU_OFFSET(8), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d4 }, g_d4_contains, g_d4_invalidates },
+{ "d5", nullptr, 8, FPU_OFFSET(10), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d5 }, g_d5_contains, g_d5_invalidates },
+{ "d6", nullptr, 8, FPU_OFFSET(12), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d6 }, g_d6_contains, g_d6_invalidates },
+{ "d7", nullptr, 8, FPU_OFFSET(14), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d7 }, g_d7_contains, g_d7_invalidates },
+{ "d8", nullptr, 8, FPU_OFFSET(16), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d8 }, g_d8_contains, g_d8_invalidates },
+{ "d9", nullptr, 8, FPU_OFFSET(18), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d9 }, g_d9_contains, g_d9_invalidates },
+{ "d10", nullptr, 8, FPU_OFFSET(20), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d10 }, g_d10_contains, g_d10_invalidates },
+{ "d11", nullptr, 8, FPU_OFFSET(22), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d11 }, g_d11_contains, g_d11_invalidates },
+{ "d12", nullptr, 8, FPU_OFFSET(24), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d12 }, g_d12_contains, g_d12_invalidates },
+{ "d13", nullptr, 8, FPU_OFFSET(26), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d13 }, g_d13_contains, g_d13_invalidates },
+{ "d14", nullptr, 8, FPU_OFFSET(28), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d14 }, g_d14_contains, g_d14_invalidates },
+{ "d15", nullptr, 8, FPU_OFFSET(30), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d15 }, g_d15_contains, g_d15_invalidates },
+{ "d16", nullptr, 8, FPU_OFFSET(32), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d16 }, nullptr, g_d16_invalidates },
+{ "d17", nullptr, 8, FPU_OFFSET(34), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d17 }, nullptr, g_d17_invalidates },
+{ "d18", nullptr, 8, FPU_OFFSET(36), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d18 }, nullptr, g_d18_invalidates },
+{ "d19", nullptr, 8, FPU_OFFSET(38), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d19 }, nullptr, g_d19_invalidates },
+{ "d20", nullptr, 8, FPU_OFFSET(40), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d20 }, nullptr, g_d20_invalidates },
+{ "d21", nullptr, 8, FPU_OFFSET(42), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d21 }, nullptr, g_d21_invalidates },
+{ "d22", nullptr, 8, FPU_OFFSET(44), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d22 }, nullptr, g_d22_invalidates },
+{ "d23", nullptr, 8, FPU_OFFSET(46), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d23 }, nullptr, g_d23_invalidates },
+{ "d24", nullptr, 8, FPU_OFFSET(48), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d24 }, nullptr, g_d24_invalidates },
+{ "d25", nullptr, 8, FPU_OFFSET(50), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d25 }, nullptr, g_d25_invalidates },
+{ "d26", nullptr, 8, FPU_OFFSET(52), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d26 }, nullptr, g_d26_invalidates },
+{ "d27", nullptr, 8, FPU_OFFSET(54), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d27 }, nullptr, g_d27_invalidates },
+{ "d28", nullptr, 8, FPU_OFFSET(56), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d28 }, nullptr, g_d28_invalidates },
+{ "d29", nullptr, 8, FPU_OFFSET(58), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d29 }, nullptr, g_d29_invalidates },
+{ "d30", nullptr, 8, FPU_OFFSET(60), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d30 }, nullptr, g_d30_invalidates },
+{ "d31", nullptr, 8, FPU_OFFSET(62), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d31 }, nullptr, g_d31_invalidates },
+
+{ "q0", nullptr, 16, FPU_OFFSET(0), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q0 }, g_q0_contains, nullptr, },
+{ "q1", nullptr, 16, FPU_OFFSET(4), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q1 }, g_q1_contains, nullptr, },
+{ "q2", nullptr, 16, FPU_OFFSET(8), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q2 }, g_q2_contains, nullptr, },
+{ "q3", nullptr, 16, FPU_OFFSET(12), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q3 }, g_q3_contains, nullptr, },
+{ "q4", nullptr, 16, FPU_OFFSET(16), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q4 }, g_q4_contains, nullptr, },
+{ "q5", nullptr, 16, FPU_OFFSET(20), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q5 }, g_q5_contains, nullptr, },
+{ "q6", nullptr, 16, FPU_OFFSET(24), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q6 }, g_q6_contains, nullptr, },
+{ "q7", nullptr, 16, FPU_OFFSET(28), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q7 }, g_q7_contains, nullptr, },
+{ "q8", nullptr, 16, FPU_OFFSET(32), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q8 }, g_q8_contains, nullptr, },
+{ "q9", nullptr, 16, FPU_OFFSET(36), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q9 }, g_q9_contains, nullptr, },
+{ "q10", nullptr, 16, FPU_OFFSET(40), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q10 }, g_q10_contains, nullptr, },
+{ "q11", nullptr, 16, FPU_OFFSET(44), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q11 }, g_q11_contains, nullptr, },
+{ "q12", nullptr, 16, FPU_OFFSET(48), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q12 }, g_q12_contains, nullptr, },
+{ "q13", nullptr, 16, FPU_OFFSET(52), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q13 }, g_q13_contains, nullptr, },
+{ "q14", nullptr, 16, FPU_OFFSET(56), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q14 }, g_q14_contains, nullptr, },
+{ "q15", nullptr, 16, FPU_OFFSET(60), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q15 }, g_q15_contains, nullptr, },
+
+{ "exception", nullptr, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, nullptr, nullptr },
+{ "fsr", nullptr, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }, nullptr, nullptr },
+{ "far", nullptr, 4, EXC_OFFSET(2), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, nullptr, nullptr },
{ DEFINE_DBG (bvr, 0) },
{ DEFINE_DBG (bvr, 1) },
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
index 0255a3b..7153211 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
@@ -1,22 +1,26 @@
-//===-- RegisterInfos_arm64.h ----------------------------------*- C++ -*-===//
+//===-- RegisterInfos_arm64.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
#ifdef DECLARE_REGISTER_INFOS_ARM64_STRUCT
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
-#include "Utility/ARM64_GCC_Registers.h"
#include "Utility/ARM64_DWARF_Registers.h"
+#include "Utility/ARM64_ehframe_Registers.h"
#ifndef GPR_OFFSET
#error GPR_OFFSET must be defined before including this header file
@@ -196,84 +200,84 @@ enum
static lldb_private::RegisterInfo g_register_infos_arm64[] = {
// General purpose registers
-// NAME ALT SZ OFFSET ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
-// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= ========== ===============
-{ "x0", NULL, 8, GPR_OFFSET(0), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x0, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, arm64_gcc::x0, gpr_x0 }, NULL, NULL},
-{ "x1", NULL, 8, GPR_OFFSET(1), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x1, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, arm64_gcc::x1, gpr_x1 }, NULL, NULL},
-{ "x2", NULL, 8, GPR_OFFSET(2), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x2, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, arm64_gcc::x2, gpr_x2 }, NULL, NULL},
-{ "x3", NULL, 8, GPR_OFFSET(3), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x3, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, arm64_gcc::x3, gpr_x3 }, NULL, NULL},
-{ "x4", NULL, 8, GPR_OFFSET(4), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x4, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, arm64_gcc::x4, gpr_x4 }, NULL, NULL},
-{ "x5", NULL, 8, GPR_OFFSET(5), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x5, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, arm64_gcc::x5, gpr_x5 }, NULL, NULL},
-{ "x6", NULL, 8, GPR_OFFSET(6), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x6, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, arm64_gcc::x6, gpr_x6 }, NULL, NULL},
-{ "x7", NULL, 8, GPR_OFFSET(7), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x7, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, arm64_gcc::x7, gpr_x7 }, NULL, NULL},
-{ "x8", NULL, 8, GPR_OFFSET(8), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x8, arm64_dwarf::x8, LLDB_INVALID_REGNUM, arm64_gcc::x8, gpr_x8 }, NULL, NULL},
-{ "x9", NULL, 8, GPR_OFFSET(9), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x9, arm64_dwarf::x9, LLDB_INVALID_REGNUM, arm64_gcc::x9, gpr_x9 }, NULL, NULL},
-{ "x10", NULL, 8, GPR_OFFSET(10), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x10, arm64_dwarf::x10, LLDB_INVALID_REGNUM, arm64_gcc::x10, gpr_x10 }, NULL, NULL},
-{ "x11", NULL, 8, GPR_OFFSET(11), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x11, arm64_dwarf::x11, LLDB_INVALID_REGNUM, arm64_gcc::x11, gpr_x11 }, NULL, NULL},
-{ "x12", NULL, 8, GPR_OFFSET(12), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x12, arm64_dwarf::x12, LLDB_INVALID_REGNUM, arm64_gcc::x12, gpr_x12 }, NULL, NULL},
-{ "x13", NULL, 8, GPR_OFFSET(13), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x13, arm64_dwarf::x13, LLDB_INVALID_REGNUM, arm64_gcc::x13, gpr_x13 }, NULL, NULL},
-{ "x14", NULL, 8, GPR_OFFSET(14), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x14, arm64_dwarf::x14, LLDB_INVALID_REGNUM, arm64_gcc::x14, gpr_x14 }, NULL, NULL},
-{ "x15", NULL, 8, GPR_OFFSET(15), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x15, arm64_dwarf::x15, LLDB_INVALID_REGNUM, arm64_gcc::x15, gpr_x15 }, NULL, NULL},
-{ "x16", NULL, 8, GPR_OFFSET(16), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x16, arm64_dwarf::x16, LLDB_INVALID_REGNUM, arm64_gcc::x16, gpr_x16 }, NULL, NULL},
-{ "x17", NULL, 8, GPR_OFFSET(17), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x17, arm64_dwarf::x17, LLDB_INVALID_REGNUM, arm64_gcc::x17, gpr_x17 }, NULL, NULL},
-{ "x18", NULL, 8, GPR_OFFSET(18), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x18, arm64_dwarf::x18, LLDB_INVALID_REGNUM, arm64_gcc::x18, gpr_x18 }, NULL, NULL},
-{ "x19", NULL, 8, GPR_OFFSET(19), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x19, arm64_dwarf::x19, LLDB_INVALID_REGNUM, arm64_gcc::x19, gpr_x19 }, NULL, NULL},
-{ "x20", NULL, 8, GPR_OFFSET(20), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x20, arm64_dwarf::x20, LLDB_INVALID_REGNUM, arm64_gcc::x20, gpr_x20 }, NULL, NULL},
-{ "x21", NULL, 8, GPR_OFFSET(21), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x21, arm64_dwarf::x21, LLDB_INVALID_REGNUM, arm64_gcc::x21, gpr_x21 }, NULL, NULL},
-{ "x22", NULL, 8, GPR_OFFSET(22), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x22, arm64_dwarf::x22, LLDB_INVALID_REGNUM, arm64_gcc::x22, gpr_x22 }, NULL, NULL},
-{ "x23", NULL, 8, GPR_OFFSET(23), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x23, arm64_dwarf::x23, LLDB_INVALID_REGNUM, arm64_gcc::x23, gpr_x23 }, NULL, NULL},
-{ "x24", NULL, 8, GPR_OFFSET(24), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x24, arm64_dwarf::x24, LLDB_INVALID_REGNUM, arm64_gcc::x24, gpr_x24 }, NULL, NULL},
-{ "x25", NULL, 8, GPR_OFFSET(25), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x25, arm64_dwarf::x25, LLDB_INVALID_REGNUM, arm64_gcc::x25, gpr_x25 }, NULL, NULL},
-{ "x26", NULL, 8, GPR_OFFSET(26), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x26, arm64_dwarf::x26, LLDB_INVALID_REGNUM, arm64_gcc::x26, gpr_x26 }, NULL, NULL},
-{ "x27", NULL, 8, GPR_OFFSET(27), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x27, arm64_dwarf::x27, LLDB_INVALID_REGNUM, arm64_gcc::x27, gpr_x27 }, NULL, NULL},
-{ "x28", NULL, 8, GPR_OFFSET(28), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x28, arm64_dwarf::x28, LLDB_INVALID_REGNUM, arm64_gcc::x28, gpr_x28 }, NULL, NULL},
+// NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
+// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= ========== ===============
+{ "x0", nullptr, 8, GPR_OFFSET(0), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x0, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, gpr_x0 }, nullptr, nullptr},
+{ "x1", nullptr, 8, GPR_OFFSET(1), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x1, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, gpr_x1 }, nullptr, nullptr},
+{ "x2", nullptr, 8, GPR_OFFSET(2), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x2, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, gpr_x2 }, nullptr, nullptr},
+{ "x3", nullptr, 8, GPR_OFFSET(3), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x3, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, gpr_x3 }, nullptr, nullptr},
+{ "x4", nullptr, 8, GPR_OFFSET(4), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x4, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, gpr_x4 }, nullptr, nullptr},
+{ "x5", nullptr, 8, GPR_OFFSET(5), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x5, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, gpr_x5 }, nullptr, nullptr},
+{ "x6", nullptr, 8, GPR_OFFSET(6), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x6, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, gpr_x6 }, nullptr, nullptr},
+{ "x7", nullptr, 8, GPR_OFFSET(7), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x7, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, gpr_x7 }, nullptr, nullptr},
+{ "x8", nullptr, 8, GPR_OFFSET(8), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x8, arm64_dwarf::x8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x8 }, nullptr, nullptr},
+{ "x9", nullptr, 8, GPR_OFFSET(9), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x9, arm64_dwarf::x9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x9 }, nullptr, nullptr},
+{ "x10", nullptr, 8, GPR_OFFSET(10), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x10, arm64_dwarf::x10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x10 }, nullptr, nullptr},
+{ "x11", nullptr, 8, GPR_OFFSET(11), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x11, arm64_dwarf::x11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x11 }, nullptr, nullptr},
+{ "x12", nullptr, 8, GPR_OFFSET(12), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x12, arm64_dwarf::x12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x12 }, nullptr, nullptr},
+{ "x13", nullptr, 8, GPR_OFFSET(13), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x13, arm64_dwarf::x13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x13 }, nullptr, nullptr},
+{ "x14", nullptr, 8, GPR_OFFSET(14), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x14, arm64_dwarf::x14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x14 }, nullptr, nullptr},
+{ "x15", nullptr, 8, GPR_OFFSET(15), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x15, arm64_dwarf::x15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x15 }, nullptr, nullptr},
+{ "x16", nullptr, 8, GPR_OFFSET(16), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x16, arm64_dwarf::x16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x16 }, nullptr, nullptr},
+{ "x17", nullptr, 8, GPR_OFFSET(17), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x17, arm64_dwarf::x17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x17 }, nullptr, nullptr},
+{ "x18", nullptr, 8, GPR_OFFSET(18), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x18, arm64_dwarf::x18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x18 }, nullptr, nullptr},
+{ "x19", nullptr, 8, GPR_OFFSET(19), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x19, arm64_dwarf::x19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x19 }, nullptr, nullptr},
+{ "x20", nullptr, 8, GPR_OFFSET(20), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x20, arm64_dwarf::x20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x20 }, nullptr, nullptr},
+{ "x21", nullptr, 8, GPR_OFFSET(21), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x21, arm64_dwarf::x21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x21 }, nullptr, nullptr},
+{ "x22", nullptr, 8, GPR_OFFSET(22), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x22, arm64_dwarf::x22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x22 }, nullptr, nullptr},
+{ "x23", nullptr, 8, GPR_OFFSET(23), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x23, arm64_dwarf::x23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x23 }, nullptr, nullptr},
+{ "x24", nullptr, 8, GPR_OFFSET(24), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x24, arm64_dwarf::x24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x24 }, nullptr, nullptr},
+{ "x25", nullptr, 8, GPR_OFFSET(25), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x25, arm64_dwarf::x25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x25 }, nullptr, nullptr},
+{ "x26", nullptr, 8, GPR_OFFSET(26), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x26, arm64_dwarf::x26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x26 }, nullptr, nullptr},
+{ "x27", nullptr, 8, GPR_OFFSET(27), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x27, arm64_dwarf::x27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x27 }, nullptr, nullptr},
+{ "x28", nullptr, 8, GPR_OFFSET(28), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x28, arm64_dwarf::x28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x28 }, nullptr, nullptr},
-{ "fp", "x29", 8, GPR_OFFSET(29), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::fp, arm64_dwarf::fp, LLDB_REGNUM_GENERIC_FP, arm64_gcc::fp, gpr_fp }, NULL, NULL},
-{ "lr", "x30", 8, GPR_OFFSET(30), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::lr, arm64_dwarf::lr, LLDB_REGNUM_GENERIC_RA, arm64_gcc::lr, gpr_lr }, NULL, NULL},
-{ "sp", "x31", 8, GPR_OFFSET(31), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::sp, arm64_dwarf::sp, LLDB_REGNUM_GENERIC_SP, arm64_gcc::sp, gpr_sp }, NULL, NULL},
-{ "pc", NULL, 8, GPR_OFFSET(32), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, arm64_gcc::pc, gpr_pc }, NULL, NULL},
+{ "fp", "x29", 8, GPR_OFFSET(29), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::fp, arm64_dwarf::fp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_fp }, nullptr, nullptr},
+{ "lr", "x30", 8, GPR_OFFSET(30), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::lr, arm64_dwarf::lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_lr }, nullptr, nullptr},
+{ "sp", "x31", 8, GPR_OFFSET(31), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::sp, arm64_dwarf::sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_sp }, nullptr, nullptr},
+{ "pc", nullptr, 8, GPR_OFFSET(32), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc }, nullptr, nullptr},
-{ "cpsr", NULL, 4, GPR_OFFSET_NAME(cpsr), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, arm64_gcc::cpsr, gpr_cpsr }, NULL, NULL},
+{ "cpsr", nullptr, 4, GPR_OFFSET_NAME(cpsr), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_cpsr }, nullptr, nullptr},
-{ "v0", NULL, 16, FPU_OFFSET(0), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, arm64_gcc::v0, fpu_v0 }, NULL, NULL},
-{ "v1", NULL, 16, FPU_OFFSET(1), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, arm64_gcc::v1, fpu_v1 }, NULL, NULL},
-{ "v2", NULL, 16, FPU_OFFSET(2), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, arm64_gcc::v2, fpu_v2 }, NULL, NULL},
-{ "v3", NULL, 16, FPU_OFFSET(3), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, arm64_gcc::v3, fpu_v3 }, NULL, NULL},
-{ "v4", NULL, 16, FPU_OFFSET(4), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, arm64_gcc::v4, fpu_v4 }, NULL, NULL},
-{ "v5", NULL, 16, FPU_OFFSET(5), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, arm64_gcc::v5, fpu_v5 }, NULL, NULL},
-{ "v6", NULL, 16, FPU_OFFSET(6), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, arm64_gcc::v6, fpu_v6 }, NULL, NULL},
-{ "v7", NULL, 16, FPU_OFFSET(7), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, arm64_gcc::v7, fpu_v7 }, NULL, NULL},
-{ "v8", NULL, 16, FPU_OFFSET(8), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, arm64_gcc::v8, fpu_v8 }, NULL, NULL},
-{ "v9", NULL, 16, FPU_OFFSET(9), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, arm64_gcc::v9, fpu_v9 }, NULL, NULL},
-{ "v10", NULL, 16, FPU_OFFSET(10), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, arm64_gcc::v10, fpu_v10 }, NULL, NULL},
-{ "v11", NULL, 16, FPU_OFFSET(11), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, arm64_gcc::v11, fpu_v11 }, NULL, NULL},
-{ "v12", NULL, 16, FPU_OFFSET(12), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, arm64_gcc::v12, fpu_v12 }, NULL, NULL},
-{ "v13", NULL, 16, FPU_OFFSET(13), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, arm64_gcc::v13, fpu_v13 }, NULL, NULL},
-{ "v14", NULL, 16, FPU_OFFSET(14), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, arm64_gcc::v14, fpu_v14 }, NULL, NULL},
-{ "v15", NULL, 16, FPU_OFFSET(15), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, arm64_gcc::v15, fpu_v15 }, NULL, NULL},
-{ "v16", NULL, 16, FPU_OFFSET(16), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, arm64_gcc::v16, fpu_v16 }, NULL, NULL},
-{ "v17", NULL, 16, FPU_OFFSET(17), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, arm64_gcc::v17, fpu_v17 }, NULL, NULL},
-{ "v18", NULL, 16, FPU_OFFSET(18), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, arm64_gcc::v18, fpu_v18 }, NULL, NULL},
-{ "v19", NULL, 16, FPU_OFFSET(19), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, arm64_gcc::v19, fpu_v19 }, NULL, NULL},
-{ "v20", NULL, 16, FPU_OFFSET(20), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, arm64_gcc::v20, fpu_v20 }, NULL, NULL},
-{ "v21", NULL, 16, FPU_OFFSET(21), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, arm64_gcc::v21, fpu_v21 }, NULL, NULL},
-{ "v22", NULL, 16, FPU_OFFSET(22), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, arm64_gcc::v22, fpu_v22 }, NULL, NULL},
-{ "v23", NULL, 16, FPU_OFFSET(23), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, arm64_gcc::v23, fpu_v23 }, NULL, NULL},
-{ "v24", NULL, 16, FPU_OFFSET(24), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, arm64_gcc::v24, fpu_v24 }, NULL, NULL},
-{ "v25", NULL, 16, FPU_OFFSET(25), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, arm64_gcc::v25, fpu_v25 }, NULL, NULL},
-{ "v26", NULL, 16, FPU_OFFSET(26), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, arm64_gcc::v26, fpu_v26 }, NULL, NULL},
-{ "v27", NULL, 16, FPU_OFFSET(27), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, arm64_gcc::v27, fpu_v27 }, NULL, NULL},
-{ "v28", NULL, 16, FPU_OFFSET(28), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, arm64_gcc::v28, fpu_v28 }, NULL, NULL},
-{ "v29", NULL, 16, FPU_OFFSET(29), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, arm64_gcc::v29, fpu_v29 }, NULL, NULL},
-{ "v30", NULL, 16, FPU_OFFSET(30), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, arm64_gcc::v30, fpu_v30 }, NULL, NULL},
-{ "v31", NULL, 16, FPU_OFFSET(31), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, arm64_gcc::v31, fpu_v31 }, NULL, NULL},
+{ "v0", nullptr, 16, FPU_OFFSET(0), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v0 }, nullptr, nullptr},
+{ "v1", nullptr, 16, FPU_OFFSET(1), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v1 }, nullptr, nullptr},
+{ "v2", nullptr, 16, FPU_OFFSET(2), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v2 }, nullptr, nullptr},
+{ "v3", nullptr, 16, FPU_OFFSET(3), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v3 }, nullptr, nullptr},
+{ "v4", nullptr, 16, FPU_OFFSET(4), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v4 }, nullptr, nullptr},
+{ "v5", nullptr, 16, FPU_OFFSET(5), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v5 }, nullptr, nullptr},
+{ "v6", nullptr, 16, FPU_OFFSET(6), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v6 }, nullptr, nullptr},
+{ "v7", nullptr, 16, FPU_OFFSET(7), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v7 }, nullptr, nullptr},
+{ "v8", nullptr, 16, FPU_OFFSET(8), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v8 }, nullptr, nullptr},
+{ "v9", nullptr, 16, FPU_OFFSET(9), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v9 }, nullptr, nullptr},
+{ "v10", nullptr, 16, FPU_OFFSET(10), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v10 }, nullptr, nullptr},
+{ "v11", nullptr, 16, FPU_OFFSET(11), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v11 }, nullptr, nullptr},
+{ "v12", nullptr, 16, FPU_OFFSET(12), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v12 }, nullptr, nullptr},
+{ "v13", nullptr, 16, FPU_OFFSET(13), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v13 }, nullptr, nullptr},
+{ "v14", nullptr, 16, FPU_OFFSET(14), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v14 }, nullptr, nullptr},
+{ "v15", nullptr, 16, FPU_OFFSET(15), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v15 }, nullptr, nullptr},
+{ "v16", nullptr, 16, FPU_OFFSET(16), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v16 }, nullptr, nullptr},
+{ "v17", nullptr, 16, FPU_OFFSET(17), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v17 }, nullptr, nullptr},
+{ "v18", nullptr, 16, FPU_OFFSET(18), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v18 }, nullptr, nullptr},
+{ "v19", nullptr, 16, FPU_OFFSET(19), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v19 }, nullptr, nullptr},
+{ "v20", nullptr, 16, FPU_OFFSET(20), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v20 }, nullptr, nullptr},
+{ "v21", nullptr, 16, FPU_OFFSET(21), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v21 }, nullptr, nullptr},
+{ "v22", nullptr, 16, FPU_OFFSET(22), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v22 }, nullptr, nullptr},
+{ "v23", nullptr, 16, FPU_OFFSET(23), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v23 }, nullptr, nullptr},
+{ "v24", nullptr, 16, FPU_OFFSET(24), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v24 }, nullptr, nullptr},
+{ "v25", nullptr, 16, FPU_OFFSET(25), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v25 }, nullptr, nullptr},
+{ "v26", nullptr, 16, FPU_OFFSET(26), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v26 }, nullptr, nullptr},
+{ "v27", nullptr, 16, FPU_OFFSET(27), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v27 }, nullptr, nullptr},
+{ "v28", nullptr, 16, FPU_OFFSET(28), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v28 }, nullptr, nullptr},
+{ "v29", nullptr, 16, FPU_OFFSET(29), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v29 }, nullptr, nullptr},
+{ "v30", nullptr, 16, FPU_OFFSET(30), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v30 }, nullptr, nullptr},
+{ "v31", nullptr, 16, FPU_OFFSET(31), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v31 }, nullptr, nullptr},
-{ "fpsr", NULL, 4, FPU_OFFSET_NAME(fpsr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpsr }, NULL, NULL},
-{ "fpcr", NULL, 4, FPU_OFFSET_NAME(fpcr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpcr }, NULL, NULL},
+{ "fpsr", nullptr, 4, FPU_OFFSET_NAME(fpsr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpsr }, nullptr, nullptr},
+{ "fpcr", nullptr, 4, FPU_OFFSET_NAME(fpcr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpcr }, nullptr, nullptr},
-{ "far", NULL, 8, EXC_OFFSET_NAME(far), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, NULL, NULL},
-{ "esr", NULL, 4, EXC_OFFSET_NAME(esr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_esr }, NULL, NULL},
-{ "exception",NULL, 4, EXC_OFFSET_NAME(exception), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, NULL, NULL},
+{ "far", nullptr, 8, EXC_OFFSET_NAME(far), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, nullptr, nullptr},
+{ "esr", nullptr, 4, EXC_OFFSET_NAME(esr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_esr }, nullptr, nullptr},
+{ "exception",nullptr, 4, EXC_OFFSET_NAME(exception), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, nullptr, nullptr},
{ DEFINE_DBG (bvr, 0) },
{ DEFINE_DBG (bvr, 1) },
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h
index 6982536..904ec4d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_i386.h
@@ -1,15 +1,21 @@
-//===-- RegisterInfos_i386.h -----------------------------------*- C++ -*-===//
+//===-- RegisterInfos_i386.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
-#include "llvm/Support/Compiler.h"
+//===----------------------------------------------------------------------===//
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/Compiler.h"
+
+// Project includes
+
#ifdef DECLARE_REGISTER_INFOS_I386_STRUCT
// Computes the offset of the given GPR in the user data area.
@@ -52,31 +58,31 @@
{ #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
eFormatHex, { kind1, kind2, kind3, kind4, lldb_##name##_i386 }, NULL, NULL }
-// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
#define DEFINE_FP_ST(reg, i) \
{ #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, gdb_st##i##_i386, lldb_st##i##_i386 }, \
+ { ehframe_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_st##i##_i386 }, \
NULL, NULL }
#define DEFINE_FP_MM(reg, i) \
{ #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
eEncodingUint, eFormatHex, \
- { gcc_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, gdb_mm##i##_i386, lldb_mm##i##_i386 }, \
+ { ehframe_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_mm##i##_i386 }, \
NULL, NULL }
#define DEFINE_XMM(reg, i) \
{ #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##_i386, lldb_##reg##i##_i386}, \
+ { ehframe_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_i386}, \
NULL, NULL }
// I believe the YMM registers use dwarf_xmm_%_i386 register numbers and then differentiate based on register size.
#define DEFINE_YMM(reg, i) \
{ #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(i), \
eEncodingVector, eFormatVectorOfUInt8, \
- { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##h_i386, lldb_##reg##i##_i386 }, \
+ { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_i386 }, \
NULL, NULL }
#define DEFINE_DR(reg, i) \
@@ -98,22 +104,22 @@ static RegisterInfo
g_register_infos_i386[] =
{
// General purpose registers.
- DEFINE_GPR(eax, NULL, gcc_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, gdb_eax_i386),
- DEFINE_GPR(ebx, NULL, gcc_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, gdb_ebx_i386),
- DEFINE_GPR(ecx, NULL, gcc_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, gdb_ecx_i386),
- DEFINE_GPR(edx, NULL, gcc_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, gdb_edx_i386),
- DEFINE_GPR(edi, NULL, gcc_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, gdb_edi_i386),
- DEFINE_GPR(esi, NULL, gcc_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, gdb_esi_i386),
- DEFINE_GPR(ebp, "fp", gcc_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, gdb_ebp_i386),
- DEFINE_GPR(esp, "sp", gcc_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, gdb_esp_i386),
- DEFINE_GPR(eip, "pc", gcc_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, gdb_eip_i386),
- DEFINE_GPR(eflags, "flags", gcc_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags_i386),
- DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, dwarf_cs_i386, LLDB_INVALID_REGNUM, gdb_cs_i386),
- DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, dwarf_fs_i386, LLDB_INVALID_REGNUM, gdb_fs_i386),
- DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, dwarf_gs_i386, LLDB_INVALID_REGNUM, gdb_gs_i386),
- DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, dwarf_ss_i386, LLDB_INVALID_REGNUM, gdb_ss_i386),
- DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, dwarf_ds_i386, LLDB_INVALID_REGNUM, gdb_ds_i386),
- DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, dwarf_es_i386, LLDB_INVALID_REGNUM, gdb_es_i386),
+ DEFINE_GPR(eax, nullptr, ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ebx, nullptr, ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ecx, nullptr, ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(edx, nullptr, ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(edi, nullptr, ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(esi, nullptr, ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ebp, "fp", ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(esp, "sp", ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(eip, "pc", ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(eflags, "flags", ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cs, nullptr, LLDB_INVALID_REGNUM, dwarf_cs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(fs, nullptr, LLDB_INVALID_REGNUM, dwarf_fs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(gs, nullptr, LLDB_INVALID_REGNUM, dwarf_gs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ss, nullptr, LLDB_INVALID_REGNUM, dwarf_ss_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ds, nullptr, LLDB_INVALID_REGNUM, dwarf_ds_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(es, nullptr, LLDB_INVALID_REGNUM, dwarf_es_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_GPR_PSEUDO_16(ax, eax),
DEFINE_GPR_PSEUDO_16(bx, ebx),
@@ -133,15 +139,15 @@ g_register_infos_i386[] =
DEFINE_GPR_PSEUDO_8L(dl, edx),
// i387 Floating point registers.
- DEFINE_FPR(fctrl, fctrl, LLDB_INVALID_REGNUM, dwarf_fctrl_i386, LLDB_INVALID_REGNUM, gdb_fctrl_i386),
- DEFINE_FPR(fstat, fstat, LLDB_INVALID_REGNUM, dwarf_fstat_i386, LLDB_INVALID_REGNUM, gdb_fstat_i386),
- DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftag_i386),
- DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop_i386),
- DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_i386),
- DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_i386),
- DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_i386),
- DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_i386),
- DEFINE_FPR(mxcsr, mxcsr, LLDB_INVALID_REGNUM, dwarf_mxcsr_i386, LLDB_INVALID_REGNUM, gdb_mxcsr_i386),
+ DEFINE_FPR(fctrl, fctrl, LLDB_INVALID_REGNUM, dwarf_fctrl_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fstat, fstat, LLDB_INVALID_REGNUM, dwarf_fstat_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(mxcsr, mxcsr, LLDB_INVALID_REGNUM, dwarf_mxcsr_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
// FP registers.
@@ -192,6 +198,7 @@ g_register_infos_i386[] =
DEFINE_DR(dr, 6),
DEFINE_DR(dr, 7)
};
+
static_assert((sizeof(g_register_infos_i386) / sizeof(g_register_infos_i386[0])) == k_num_registers_i386,
"g_register_infos_x86_64 has wrong number of register infos");
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h
index 83ce6f0..eef27f0 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h
@@ -6,10 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
-#include "llvm/Support/Compiler.h"
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/Compiler.h"
+
+// Project includes
+
#ifdef DECLARE_REGISTER_INFOS_MIPS_STRUCT
// Computes the offset of the given GPR in the user data area.
@@ -44,123 +50,124 @@
{ #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingUint, \
eFormatHex, { kind1, kind2, kind3, kind4, msa_##reg##_mips }, NULL, NULL }
-// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+// RegisterKind: EH_Frame, DWARF, Generic, Procss Plugin, LLDB
static RegisterInfo
g_register_infos_mips[] =
{
- DEFINE_GPR (zero, "zero", gcc_dwarf_zero_mips, gcc_dwarf_zero_mips, LLDB_INVALID_REGNUM, gdb_zero_mips),
- DEFINE_GPR (r1, "at", gcc_dwarf_r1_mips, gcc_dwarf_r1_mips, LLDB_INVALID_REGNUM, gdb_r1_mips),
- DEFINE_GPR (r2, NULL, gcc_dwarf_r2_mips, gcc_dwarf_r2_mips, LLDB_INVALID_REGNUM, gdb_r2_mips),
- DEFINE_GPR (r3, NULL, gcc_dwarf_r3_mips, gcc_dwarf_r3_mips, LLDB_INVALID_REGNUM, gdb_r3_mips),
- DEFINE_GPR (r4, NULL, gcc_dwarf_r4_mips, gcc_dwarf_r4_mips, LLDB_REGNUM_GENERIC_ARG1, gdb_r4_mips),
- DEFINE_GPR (r5, NULL, gcc_dwarf_r5_mips, gcc_dwarf_r5_mips, LLDB_REGNUM_GENERIC_ARG2, gdb_r5_mips),
- DEFINE_GPR (r6, NULL, gcc_dwarf_r6_mips, gcc_dwarf_r6_mips, LLDB_REGNUM_GENERIC_ARG3, gdb_r6_mips),
- DEFINE_GPR (r7, NULL, gcc_dwarf_r7_mips, gcc_dwarf_r7_mips, LLDB_REGNUM_GENERIC_ARG4, gdb_r7_mips),
- DEFINE_GPR (r8, NULL, gcc_dwarf_r8_mips, gcc_dwarf_r8_mips, LLDB_INVALID_REGNUM, gdb_r8_mips),
- DEFINE_GPR (r9, NULL, gcc_dwarf_r9_mips, gcc_dwarf_r9_mips, LLDB_INVALID_REGNUM, gdb_r9_mips),
- DEFINE_GPR (r10, NULL, gcc_dwarf_r10_mips, gcc_dwarf_r10_mips, LLDB_INVALID_REGNUM, gdb_r10_mips),
- DEFINE_GPR (r11, NULL, gcc_dwarf_r11_mips, gcc_dwarf_r11_mips, LLDB_INVALID_REGNUM, gdb_r11_mips),
- DEFINE_GPR (r12, NULL, gcc_dwarf_r12_mips, gcc_dwarf_r12_mips, LLDB_INVALID_REGNUM, gdb_r12_mips),
- DEFINE_GPR (r13, NULL, gcc_dwarf_r13_mips, gcc_dwarf_r13_mips, LLDB_INVALID_REGNUM, gdb_r13_mips),
- DEFINE_GPR (r14, NULL, gcc_dwarf_r14_mips, gcc_dwarf_r14_mips, LLDB_INVALID_REGNUM, gdb_r14_mips),
- DEFINE_GPR (r15, NULL, gcc_dwarf_r15_mips, gcc_dwarf_r15_mips, LLDB_INVALID_REGNUM, gdb_r15_mips),
- DEFINE_GPR (r16, NULL, gcc_dwarf_r16_mips, gcc_dwarf_r16_mips, LLDB_INVALID_REGNUM, gdb_r16_mips),
- DEFINE_GPR (r17, NULL, gcc_dwarf_r17_mips, gcc_dwarf_r17_mips, LLDB_INVALID_REGNUM, gdb_r17_mips),
- DEFINE_GPR (r18, NULL, gcc_dwarf_r18_mips, gcc_dwarf_r18_mips, LLDB_INVALID_REGNUM, gdb_r18_mips),
- DEFINE_GPR (r19, NULL, gcc_dwarf_r19_mips, gcc_dwarf_r19_mips, LLDB_INVALID_REGNUM, gdb_r19_mips),
- DEFINE_GPR (r20, NULL, gcc_dwarf_r20_mips, gcc_dwarf_r20_mips, LLDB_INVALID_REGNUM, gdb_r20_mips),
- DEFINE_GPR (r21, NULL, gcc_dwarf_r21_mips, gcc_dwarf_r21_mips, LLDB_INVALID_REGNUM, gdb_r21_mips),
- DEFINE_GPR (r22, NULL, gcc_dwarf_r22_mips, gcc_dwarf_r22_mips, LLDB_INVALID_REGNUM, gdb_r22_mips),
- DEFINE_GPR (r23, NULL, gcc_dwarf_r23_mips, gcc_dwarf_r23_mips, LLDB_INVALID_REGNUM, gdb_r23_mips),
- DEFINE_GPR (r24, NULL, gcc_dwarf_r24_mips, gcc_dwarf_r24_mips, LLDB_INVALID_REGNUM, gdb_r24_mips),
- DEFINE_GPR (r25, NULL, gcc_dwarf_r25_mips, gcc_dwarf_r25_mips, LLDB_INVALID_REGNUM, gdb_r25_mips),
- DEFINE_GPR (r26, NULL, gcc_dwarf_r26_mips, gcc_dwarf_r26_mips, LLDB_INVALID_REGNUM, gdb_r26_mips),
- DEFINE_GPR (r27, NULL, gcc_dwarf_r27_mips, gcc_dwarf_r27_mips, LLDB_INVALID_REGNUM, gdb_r27_mips),
- DEFINE_GPR (gp, "gp", gcc_dwarf_gp_mips, gcc_dwarf_gp_mips, LLDB_INVALID_REGNUM, gdb_gp_mips),
- DEFINE_GPR (sp, "sp", gcc_dwarf_sp_mips, gcc_dwarf_sp_mips, LLDB_REGNUM_GENERIC_SP, gdb_sp_mips),
- DEFINE_GPR (r30, "fp", gcc_dwarf_r30_mips, gcc_dwarf_r30_mips, LLDB_REGNUM_GENERIC_FP, gdb_r30_mips),
- DEFINE_GPR (ra, "ra", gcc_dwarf_ra_mips, gcc_dwarf_ra_mips, LLDB_REGNUM_GENERIC_RA, gdb_ra_mips),
- DEFINE_GPR (sr, "status", gcc_dwarf_sr_mips, gcc_dwarf_sr_mips, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
- DEFINE_GPR (mullo, NULL, gcc_dwarf_lo_mips, gcc_dwarf_lo_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR (mulhi, NULL, gcc_dwarf_hi_mips, gcc_dwarf_hi_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR (badvaddr, NULL, gcc_dwarf_bad_mips, gcc_dwarf_bad_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR (cause, NULL, gcc_dwarf_cause_mips, gcc_dwarf_cause_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR (pc, NULL, gcc_dwarf_pc_mips, gcc_dwarf_pc_mips, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
- DEFINE_GPR (config5, NULL, gcc_dwarf_config5_mips, gcc_dwarf_config5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_FPR (f0, NULL, gcc_dwarf_f0_mips, gcc_dwarf_f0_mips, LLDB_INVALID_REGNUM, gdb_f0_mips),
- DEFINE_FPR (f1, NULL, gcc_dwarf_f1_mips, gcc_dwarf_f1_mips, LLDB_INVALID_REGNUM, gdb_f1_mips),
- DEFINE_FPR (f2, NULL, gcc_dwarf_f2_mips, gcc_dwarf_f2_mips, LLDB_INVALID_REGNUM, gdb_f2_mips),
- DEFINE_FPR (f3, NULL, gcc_dwarf_f3_mips, gcc_dwarf_f3_mips, LLDB_INVALID_REGNUM, gdb_f3_mips),
- DEFINE_FPR (f4, NULL, gcc_dwarf_f4_mips, gcc_dwarf_f4_mips, LLDB_INVALID_REGNUM, gdb_f4_mips),
- DEFINE_FPR (f5, NULL, gcc_dwarf_f5_mips, gcc_dwarf_f5_mips, LLDB_INVALID_REGNUM, gdb_f5_mips),
- DEFINE_FPR (f6, NULL, gcc_dwarf_f6_mips, gcc_dwarf_f6_mips, LLDB_INVALID_REGNUM, gdb_f6_mips),
- DEFINE_FPR (f7, NULL, gcc_dwarf_f7_mips, gcc_dwarf_f7_mips, LLDB_INVALID_REGNUM, gdb_f7_mips),
- DEFINE_FPR (f8, NULL, gcc_dwarf_f8_mips, gcc_dwarf_f8_mips, LLDB_INVALID_REGNUM, gdb_f8_mips),
- DEFINE_FPR (f9, NULL, gcc_dwarf_f9_mips, gcc_dwarf_f9_mips, LLDB_INVALID_REGNUM, gdb_f9_mips),
- DEFINE_FPR (f10, NULL, gcc_dwarf_f10_mips, gcc_dwarf_f10_mips, LLDB_INVALID_REGNUM, gdb_f10_mips),
- DEFINE_FPR (f11, NULL, gcc_dwarf_f11_mips, gcc_dwarf_f11_mips, LLDB_INVALID_REGNUM, gdb_f11_mips),
- DEFINE_FPR (f12, NULL, gcc_dwarf_f12_mips, gcc_dwarf_f12_mips, LLDB_INVALID_REGNUM, gdb_f12_mips),
- DEFINE_FPR (f13, NULL, gcc_dwarf_f13_mips, gcc_dwarf_f13_mips, LLDB_INVALID_REGNUM, gdb_f13_mips),
- DEFINE_FPR (f14, NULL, gcc_dwarf_f14_mips, gcc_dwarf_f14_mips, LLDB_INVALID_REGNUM, gdb_f14_mips),
- DEFINE_FPR (f15, NULL, gcc_dwarf_f15_mips, gcc_dwarf_f15_mips, LLDB_INVALID_REGNUM, gdb_f15_mips),
- DEFINE_FPR (f16, NULL, gcc_dwarf_f16_mips, gcc_dwarf_f16_mips, LLDB_INVALID_REGNUM, gdb_f16_mips),
- DEFINE_FPR (f17, NULL, gcc_dwarf_f17_mips, gcc_dwarf_f17_mips, LLDB_INVALID_REGNUM, gdb_f17_mips),
- DEFINE_FPR (f18, NULL, gcc_dwarf_f18_mips, gcc_dwarf_f18_mips, LLDB_INVALID_REGNUM, gdb_f18_mips),
- DEFINE_FPR (f19, NULL, gcc_dwarf_f19_mips, gcc_dwarf_f19_mips, LLDB_INVALID_REGNUM, gdb_f19_mips),
- DEFINE_FPR (f20, NULL, gcc_dwarf_f20_mips, gcc_dwarf_f20_mips, LLDB_INVALID_REGNUM, gdb_f20_mips),
- DEFINE_FPR (f21, NULL, gcc_dwarf_f21_mips, gcc_dwarf_f21_mips, LLDB_INVALID_REGNUM, gdb_f21_mips),
- DEFINE_FPR (f22, NULL, gcc_dwarf_f22_mips, gcc_dwarf_f22_mips, LLDB_INVALID_REGNUM, gdb_f22_mips),
- DEFINE_FPR (f23, NULL, gcc_dwarf_f23_mips, gcc_dwarf_f23_mips, LLDB_INVALID_REGNUM, gdb_f23_mips),
- DEFINE_FPR (f24, NULL, gcc_dwarf_f24_mips, gcc_dwarf_f24_mips, LLDB_INVALID_REGNUM, gdb_f24_mips),
- DEFINE_FPR (f25, NULL, gcc_dwarf_f25_mips, gcc_dwarf_f25_mips, LLDB_INVALID_REGNUM, gdb_f25_mips),
- DEFINE_FPR (f26, NULL, gcc_dwarf_f26_mips, gcc_dwarf_f26_mips, LLDB_INVALID_REGNUM, gdb_f26_mips),
- DEFINE_FPR (f27, NULL, gcc_dwarf_f27_mips, gcc_dwarf_f27_mips, LLDB_INVALID_REGNUM, gdb_f27_mips),
- DEFINE_FPR (f28, NULL, gcc_dwarf_f28_mips, gcc_dwarf_f28_mips, LLDB_INVALID_REGNUM, gdb_f28_mips),
- DEFINE_FPR (f29, NULL, gcc_dwarf_f29_mips, gcc_dwarf_f29_mips, LLDB_INVALID_REGNUM, gdb_f29_mips),
- DEFINE_FPR (f30, NULL, gcc_dwarf_f30_mips, gcc_dwarf_f30_mips, LLDB_INVALID_REGNUM, gdb_f30_mips),
- DEFINE_FPR (f31, NULL, gcc_dwarf_f31_mips, gcc_dwarf_f31_mips, LLDB_INVALID_REGNUM, gdb_f31_mips),
- DEFINE_FPR (fcsr, NULL, gcc_dwarf_fcsr_mips, gcc_dwarf_fcsr_mips, LLDB_INVALID_REGNUM, gdb_fcsr_mips),
- DEFINE_FPR (fir, NULL, gcc_dwarf_fir_mips, gcc_dwarf_fir_mips, LLDB_INVALID_REGNUM, gdb_fir_mips),
- DEFINE_FPR (config5, NULL, gcc_dwarf_config5_mips, gcc_dwarf_config5_mips, LLDB_INVALID_REGNUM, gdb_config5_mips),
- DEFINE_MSA (w0, NULL, gcc_dwarf_w0_mips, gcc_dwarf_w0_mips, LLDB_INVALID_REGNUM, gdb_w0_mips),
- DEFINE_MSA (w1, NULL, gcc_dwarf_w1_mips, gcc_dwarf_w1_mips, LLDB_INVALID_REGNUM, gdb_w1_mips),
- DEFINE_MSA (w2, NULL, gcc_dwarf_w2_mips, gcc_dwarf_w2_mips, LLDB_INVALID_REGNUM, gdb_w2_mips),
- DEFINE_MSA (w3, NULL, gcc_dwarf_w3_mips, gcc_dwarf_w3_mips, LLDB_INVALID_REGNUM, gdb_w3_mips),
- DEFINE_MSA (w4, NULL, gcc_dwarf_w4_mips, gcc_dwarf_w4_mips, LLDB_INVALID_REGNUM, gdb_w4_mips),
- DEFINE_MSA (w5, NULL, gcc_dwarf_w5_mips, gcc_dwarf_w5_mips, LLDB_INVALID_REGNUM, gdb_w5_mips),
- DEFINE_MSA (w6, NULL, gcc_dwarf_w6_mips, gcc_dwarf_w6_mips, LLDB_INVALID_REGNUM, gdb_w6_mips),
- DEFINE_MSA (w7, NULL, gcc_dwarf_w7_mips, gcc_dwarf_w7_mips, LLDB_INVALID_REGNUM, gdb_w7_mips),
- DEFINE_MSA (w8, NULL, gcc_dwarf_w8_mips, gcc_dwarf_w8_mips, LLDB_INVALID_REGNUM, gdb_w8_mips),
- DEFINE_MSA (w9, NULL, gcc_dwarf_w9_mips, gcc_dwarf_w9_mips, LLDB_INVALID_REGNUM, gdb_w9_mips),
- DEFINE_MSA (w10, NULL, gcc_dwarf_w10_mips, gcc_dwarf_w10_mips, LLDB_INVALID_REGNUM, gdb_w10_mips),
- DEFINE_MSA (w11, NULL, gcc_dwarf_w11_mips, gcc_dwarf_w11_mips, LLDB_INVALID_REGNUM, gdb_w11_mips),
- DEFINE_MSA (w12, NULL, gcc_dwarf_w12_mips, gcc_dwarf_w12_mips, LLDB_INVALID_REGNUM, gdb_w12_mips),
- DEFINE_MSA (w13, NULL, gcc_dwarf_w13_mips, gcc_dwarf_w13_mips, LLDB_INVALID_REGNUM, gdb_w13_mips),
- DEFINE_MSA (w14, NULL, gcc_dwarf_w14_mips, gcc_dwarf_w14_mips, LLDB_INVALID_REGNUM, gdb_w14_mips),
- DEFINE_MSA (w15, NULL, gcc_dwarf_w15_mips, gcc_dwarf_w15_mips, LLDB_INVALID_REGNUM, gdb_w15_mips),
- DEFINE_MSA (w16, NULL, gcc_dwarf_w16_mips, gcc_dwarf_w16_mips, LLDB_INVALID_REGNUM, gdb_w16_mips),
- DEFINE_MSA (w17, NULL, gcc_dwarf_w17_mips, gcc_dwarf_w17_mips, LLDB_INVALID_REGNUM, gdb_w17_mips),
- DEFINE_MSA (w18, NULL, gcc_dwarf_w18_mips, gcc_dwarf_w18_mips, LLDB_INVALID_REGNUM, gdb_w18_mips),
- DEFINE_MSA (w19, NULL, gcc_dwarf_w19_mips, gcc_dwarf_w19_mips, LLDB_INVALID_REGNUM, gdb_w19_mips),
- DEFINE_MSA (w20, NULL, gcc_dwarf_w10_mips, gcc_dwarf_w20_mips, LLDB_INVALID_REGNUM, gdb_w20_mips),
- DEFINE_MSA (w21, NULL, gcc_dwarf_w21_mips, gcc_dwarf_w21_mips, LLDB_INVALID_REGNUM, gdb_w21_mips),
- DEFINE_MSA (w22, NULL, gcc_dwarf_w22_mips, gcc_dwarf_w22_mips, LLDB_INVALID_REGNUM, gdb_w22_mips),
- DEFINE_MSA (w23, NULL, gcc_dwarf_w23_mips, gcc_dwarf_w23_mips, LLDB_INVALID_REGNUM, gdb_w23_mips),
- DEFINE_MSA (w24, NULL, gcc_dwarf_w24_mips, gcc_dwarf_w24_mips, LLDB_INVALID_REGNUM, gdb_w24_mips),
- DEFINE_MSA (w25, NULL, gcc_dwarf_w25_mips, gcc_dwarf_w25_mips, LLDB_INVALID_REGNUM, gdb_w25_mips),
- DEFINE_MSA (w26, NULL, gcc_dwarf_w26_mips, gcc_dwarf_w26_mips, LLDB_INVALID_REGNUM, gdb_w26_mips),
- DEFINE_MSA (w27, NULL, gcc_dwarf_w27_mips, gcc_dwarf_w27_mips, LLDB_INVALID_REGNUM, gdb_w27_mips),
- DEFINE_MSA (w28, NULL, gcc_dwarf_w28_mips, gcc_dwarf_w28_mips, LLDB_INVALID_REGNUM, gdb_w28_mips),
- DEFINE_MSA (w29, NULL, gcc_dwarf_w29_mips, gcc_dwarf_w29_mips, LLDB_INVALID_REGNUM, gdb_w29_mips),
- DEFINE_MSA (w30, NULL, gcc_dwarf_w30_mips, gcc_dwarf_w30_mips, LLDB_INVALID_REGNUM, gdb_w30_mips),
- DEFINE_MSA (w31, NULL, gcc_dwarf_w31_mips, gcc_dwarf_w31_mips, LLDB_INVALID_REGNUM, gdb_w31_mips),
- DEFINE_MSA_INFO (mcsr, NULL, gcc_dwarf_mcsr_mips, gcc_dwarf_mcsr_mips, LLDB_INVALID_REGNUM, gdb_mcsr_mips),
- DEFINE_MSA_INFO (mir, NULL, gcc_dwarf_mir_mips, gcc_dwarf_mir_mips, LLDB_INVALID_REGNUM, gdb_mir_mips),
- DEFINE_MSA_INFO (fcsr, NULL, gcc_dwarf_fcsr_mips, gcc_dwarf_fcsr_mips, LLDB_INVALID_REGNUM, gdb_fcsr_mips),
- DEFINE_MSA_INFO (fir, NULL, gcc_dwarf_fir_mips, gcc_dwarf_fir_mips, LLDB_INVALID_REGNUM, gdb_fir_mips),
- DEFINE_MSA_INFO (config5, NULL, gcc_dwarf_config5_mips, gcc_dwarf_config5_mips, LLDB_INVALID_REGNUM, gdb_config5_mips)
+ DEFINE_GPR (zero, "zero", dwarf_zero_mips, dwarf_zero_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r1, "at", dwarf_r1_mips, dwarf_r1_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r2, nullptr, dwarf_r2_mips, dwarf_r2_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r3, nullptr, dwarf_r3_mips, dwarf_r3_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r4, nullptr, dwarf_r4_mips, dwarf_r4_mips, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r5, nullptr, dwarf_r5_mips, dwarf_r5_mips, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r6, nullptr, dwarf_r6_mips, dwarf_r6_mips, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r7, nullptr, dwarf_r7_mips, dwarf_r7_mips, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r8, nullptr, dwarf_r8_mips, dwarf_r8_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r9, nullptr, dwarf_r9_mips, dwarf_r9_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r10, nullptr, dwarf_r10_mips, dwarf_r10_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r11, nullptr, dwarf_r11_mips, dwarf_r11_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r12, nullptr, dwarf_r12_mips, dwarf_r12_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r13, nullptr, dwarf_r13_mips, dwarf_r13_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r14, nullptr, dwarf_r14_mips, dwarf_r14_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r15, nullptr, dwarf_r15_mips, dwarf_r15_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r16, nullptr, dwarf_r16_mips, dwarf_r16_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r17, nullptr, dwarf_r17_mips, dwarf_r17_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r18, nullptr, dwarf_r18_mips, dwarf_r18_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r19, nullptr, dwarf_r19_mips, dwarf_r19_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r20, nullptr, dwarf_r20_mips, dwarf_r20_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r21, nullptr, dwarf_r21_mips, dwarf_r21_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r22, nullptr, dwarf_r22_mips, dwarf_r22_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r23, nullptr, dwarf_r23_mips, dwarf_r23_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r24, nullptr, dwarf_r24_mips, dwarf_r24_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r25, nullptr, dwarf_r25_mips, dwarf_r25_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r26, nullptr, dwarf_r26_mips, dwarf_r26_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r27, nullptr, dwarf_r27_mips, dwarf_r27_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (gp, "gp", dwarf_gp_mips, dwarf_gp_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (sp, "sp", dwarf_sp_mips, dwarf_sp_mips, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r30, "fp", dwarf_r30_mips, dwarf_r30_mips, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (ra, "ra", dwarf_ra_mips, dwarf_ra_mips, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (sr, "status", dwarf_sr_mips, dwarf_sr_mips, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (mullo, nullptr, dwarf_lo_mips, dwarf_lo_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (mulhi, nullptr, dwarf_hi_mips, dwarf_hi_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (badvaddr, nullptr, dwarf_bad_mips, dwarf_bad_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (cause, nullptr, dwarf_cause_mips, dwarf_cause_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (pc, nullptr, dwarf_pc_mips, dwarf_pc_mips, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f0, nullptr, dwarf_f0_mips, dwarf_f0_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f1, nullptr, dwarf_f1_mips, dwarf_f1_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f2, nullptr, dwarf_f2_mips, dwarf_f2_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f3, nullptr, dwarf_f3_mips, dwarf_f3_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f4, nullptr, dwarf_f4_mips, dwarf_f4_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f5, nullptr, dwarf_f5_mips, dwarf_f5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f6, nullptr, dwarf_f6_mips, dwarf_f6_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f7, nullptr, dwarf_f7_mips, dwarf_f7_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f8, nullptr, dwarf_f8_mips, dwarf_f8_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f9, nullptr, dwarf_f9_mips, dwarf_f9_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f10, nullptr, dwarf_f10_mips, dwarf_f10_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f11, nullptr, dwarf_f11_mips, dwarf_f11_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f12, nullptr, dwarf_f12_mips, dwarf_f12_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f13, nullptr, dwarf_f13_mips, dwarf_f13_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f14, nullptr, dwarf_f14_mips, dwarf_f14_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f15, nullptr, dwarf_f15_mips, dwarf_f15_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f16, nullptr, dwarf_f16_mips, dwarf_f16_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f17, nullptr, dwarf_f17_mips, dwarf_f17_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f18, nullptr, dwarf_f18_mips, dwarf_f18_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f19, nullptr, dwarf_f19_mips, dwarf_f19_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f20, nullptr, dwarf_f20_mips, dwarf_f20_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f21, nullptr, dwarf_f21_mips, dwarf_f21_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f22, nullptr, dwarf_f22_mips, dwarf_f22_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f23, nullptr, dwarf_f23_mips, dwarf_f23_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f24, nullptr, dwarf_f24_mips, dwarf_f24_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f25, nullptr, dwarf_f25_mips, dwarf_f25_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f26, nullptr, dwarf_f26_mips, dwarf_f26_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f27, nullptr, dwarf_f27_mips, dwarf_f27_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f28, nullptr, dwarf_f28_mips, dwarf_f28_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f29, nullptr, dwarf_f29_mips, dwarf_f29_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f30, nullptr, dwarf_f30_mips, dwarf_f30_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f31, nullptr, dwarf_f31_mips, dwarf_f31_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (fcsr, nullptr, dwarf_fcsr_mips, dwarf_fcsr_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (fir, nullptr, dwarf_fir_mips, dwarf_fir_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w0, nullptr, dwarf_w0_mips, dwarf_w0_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w1, nullptr, dwarf_w1_mips, dwarf_w1_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w2, nullptr, dwarf_w2_mips, dwarf_w2_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w3, nullptr, dwarf_w3_mips, dwarf_w3_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w4, nullptr, dwarf_w4_mips, dwarf_w4_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w5, nullptr, dwarf_w5_mips, dwarf_w5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w6, nullptr, dwarf_w6_mips, dwarf_w6_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w7, nullptr, dwarf_w7_mips, dwarf_w7_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w8, nullptr, dwarf_w8_mips, dwarf_w8_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w9, nullptr, dwarf_w9_mips, dwarf_w9_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w10, nullptr, dwarf_w10_mips, dwarf_w10_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w11, nullptr, dwarf_w11_mips, dwarf_w11_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w12, nullptr, dwarf_w12_mips, dwarf_w12_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w13, nullptr, dwarf_w13_mips, dwarf_w13_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w14, nullptr, dwarf_w14_mips, dwarf_w14_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w15, nullptr, dwarf_w15_mips, dwarf_w15_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w16, nullptr, dwarf_w16_mips, dwarf_w16_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w17, nullptr, dwarf_w17_mips, dwarf_w17_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w18, nullptr, dwarf_w18_mips, dwarf_w18_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w19, nullptr, dwarf_w19_mips, dwarf_w19_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w20, nullptr, dwarf_w10_mips, dwarf_w20_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w21, nullptr, dwarf_w21_mips, dwarf_w21_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w22, nullptr, dwarf_w22_mips, dwarf_w22_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w23, nullptr, dwarf_w23_mips, dwarf_w23_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w24, nullptr, dwarf_w24_mips, dwarf_w24_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w25, nullptr, dwarf_w25_mips, dwarf_w25_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w26, nullptr, dwarf_w26_mips, dwarf_w26_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w27, nullptr, dwarf_w27_mips, dwarf_w27_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w28, nullptr, dwarf_w28_mips, dwarf_w28_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w29, nullptr, dwarf_w29_mips, dwarf_w29_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w30, nullptr, dwarf_w30_mips, dwarf_w30_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w31, nullptr, dwarf_w31_mips, dwarf_w31_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (mcsr, nullptr, dwarf_mcsr_mips, dwarf_mcsr_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (mir, nullptr, dwarf_mir_mips, dwarf_mir_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (fcsr, nullptr, dwarf_fcsr_mips, dwarf_fcsr_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (fir, nullptr, dwarf_fir_mips, dwarf_fir_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM)
};
+
static_assert((sizeof(g_register_infos_mips) / sizeof(g_register_infos_mips[0])) == k_num_registers_mips,
"g_register_infos_mips has wrong number of register infos");
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h
index 101842e..45853d7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h
@@ -1,15 +1,21 @@
-//===-- RegisterInfos_mips64.h ---------------------------------*- C++ -*-===//
+//===-- RegisterInfos_mips64.h ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
-#include "llvm/Support/Compiler.h"
+//===----------------------------------------------------------------------===//
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/Compiler.h"
+
+// Project includes
+
#ifdef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
// Computes the offset of the given GPR in the user data area.
@@ -32,7 +38,7 @@
(LLVM_EXTENSION offsetof(UserArea, msa) + \
LLVM_EXTENSION offsetof(MSA_linux_mips, regname))
-// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
// Note that the size and offset will be updated by platform-specific classes.
#ifdef LINUX_MIPS64
@@ -64,161 +70,160 @@
static RegisterInfo
g_register_infos_mips64[] =
{
- // General purpose registers. GCC, DWARF, Generic, GDB
+ // General purpose registers. EH_Frame, DWARF, Generic, Process Plugin
#ifndef LINUX_MIPS64
- DEFINE_GPR(zero, "r0", gcc_dwarf_zero_mips64, gcc_dwarf_zero_mips64, LLDB_INVALID_REGNUM, gdb_zero_mips64),
- DEFINE_GPR(r1, NULL, gcc_dwarf_r1_mips64, gcc_dwarf_r1_mips64, LLDB_INVALID_REGNUM, gdb_r1_mips64),
- DEFINE_GPR(r2, NULL, gcc_dwarf_r2_mips64, gcc_dwarf_r2_mips64, LLDB_INVALID_REGNUM, gdb_r2_mips64),
- DEFINE_GPR(r3, NULL, gcc_dwarf_r3_mips64, gcc_dwarf_r3_mips64, LLDB_INVALID_REGNUM, gdb_r3_mips64),
- DEFINE_GPR(r4, NULL, gcc_dwarf_r4_mips64, gcc_dwarf_r4_mips64, LLDB_REGNUM_GENERIC_ARG1, gdb_r4_mips64),
- DEFINE_GPR(r5, NULL, gcc_dwarf_r5_mips64, gcc_dwarf_r5_mips64, LLDB_REGNUM_GENERIC_ARG2, gdb_r5_mips64),
- DEFINE_GPR(r6, NULL, gcc_dwarf_r6_mips64, gcc_dwarf_r6_mips64, LLDB_REGNUM_GENERIC_ARG3, gdb_r6_mips64),
- DEFINE_GPR(r7, NULL, gcc_dwarf_r7_mips64, gcc_dwarf_r7_mips64, LLDB_REGNUM_GENERIC_ARG4, gdb_r7_mips64),
- DEFINE_GPR(r8, NULL, gcc_dwarf_r8_mips64, gcc_dwarf_r8_mips64, LLDB_REGNUM_GENERIC_ARG5, gdb_r8_mips64),
- DEFINE_GPR(r9, NULL, gcc_dwarf_r9_mips64, gcc_dwarf_r9_mips64, LLDB_REGNUM_GENERIC_ARG6, gdb_r9_mips64),
- DEFINE_GPR(r10, NULL, gcc_dwarf_r10_mips64, gcc_dwarf_r10_mips64, LLDB_REGNUM_GENERIC_ARG7, gdb_r10_mips64),
- DEFINE_GPR(r11, NULL, gcc_dwarf_r11_mips64, gcc_dwarf_r11_mips64, LLDB_REGNUM_GENERIC_ARG8, gdb_r11_mips64),
- DEFINE_GPR(r12, NULL, gcc_dwarf_r12_mips64, gcc_dwarf_r12_mips64, LLDB_INVALID_REGNUM, gdb_r12_mips64),
- DEFINE_GPR(r13, NULL, gcc_dwarf_r13_mips64, gcc_dwarf_r13_mips64, LLDB_INVALID_REGNUM, gdb_r13_mips64),
- DEFINE_GPR(r14, NULL, gcc_dwarf_r14_mips64, gcc_dwarf_r14_mips64, LLDB_INVALID_REGNUM, gdb_r14_mips64),
- DEFINE_GPR(r15, NULL, gcc_dwarf_r15_mips64, gcc_dwarf_r15_mips64, LLDB_INVALID_REGNUM, gdb_r15_mips64),
- DEFINE_GPR(r16, NULL, gcc_dwarf_r16_mips64, gcc_dwarf_r16_mips64, LLDB_INVALID_REGNUM, gdb_r16_mips64),
- DEFINE_GPR(r17, NULL, gcc_dwarf_r17_mips64, gcc_dwarf_r17_mips64, LLDB_INVALID_REGNUM, gdb_r17_mips64),
- DEFINE_GPR(r18, NULL, gcc_dwarf_r18_mips64, gcc_dwarf_r18_mips64, LLDB_INVALID_REGNUM, gdb_r18_mips64),
- DEFINE_GPR(r19, NULL, gcc_dwarf_r19_mips64, gcc_dwarf_r19_mips64, LLDB_INVALID_REGNUM, gdb_r19_mips64),
- DEFINE_GPR(r20, NULL, gcc_dwarf_r20_mips64, gcc_dwarf_r20_mips64, LLDB_INVALID_REGNUM, gdb_r20_mips64),
- DEFINE_GPR(r21, NULL, gcc_dwarf_r21_mips64, gcc_dwarf_r21_mips64, LLDB_INVALID_REGNUM, gdb_r21_mips64),
- DEFINE_GPR(r22, NULL, gcc_dwarf_r22_mips64, gcc_dwarf_r22_mips64, LLDB_INVALID_REGNUM, gdb_r22_mips64),
- DEFINE_GPR(r23, NULL, gcc_dwarf_r23_mips64, gcc_dwarf_r23_mips64, LLDB_INVALID_REGNUM, gdb_r23_mips64),
- DEFINE_GPR(r24, NULL, gcc_dwarf_r24_mips64, gcc_dwarf_r24_mips64, LLDB_INVALID_REGNUM, gdb_r24_mips64),
- DEFINE_GPR(r25, NULL, gcc_dwarf_r25_mips64, gcc_dwarf_r25_mips64, LLDB_INVALID_REGNUM, gdb_r25_mips64),
- DEFINE_GPR(r26, NULL, gcc_dwarf_r26_mips64, gcc_dwarf_r26_mips64, LLDB_INVALID_REGNUM, gdb_r26_mips64),
- DEFINE_GPR(r27, NULL, gcc_dwarf_r27_mips64, gcc_dwarf_r27_mips64, LLDB_INVALID_REGNUM, gdb_r27_mips64),
- DEFINE_GPR(gp, "r28", gcc_dwarf_gp_mips64, gcc_dwarf_gp_mips64, LLDB_INVALID_REGNUM, gdb_gp_mips64),
- DEFINE_GPR(sp, "r29", gcc_dwarf_sp_mips64, gcc_dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, gdb_sp_mips64),
- DEFINE_GPR(r30, NULL, gcc_dwarf_r30_mips64, gcc_dwarf_r30_mips64, LLDB_REGNUM_GENERIC_FP, gdb_r30_mips64),
- DEFINE_GPR(ra, "r31", gcc_dwarf_ra_mips64, gcc_dwarf_ra_mips64, LLDB_REGNUM_GENERIC_RA, gdb_ra_mips64),
- DEFINE_GPR(sr, NULL, gcc_dwarf_sr_mips64, gcc_dwarf_sr_mips64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
- DEFINE_GPR(mullo, NULL, gcc_dwarf_lo_mips64, gcc_dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(mulhi, NULL, gcc_dwarf_hi_mips64, gcc_dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(badvaddr, NULL, gcc_dwarf_bad_mips64, gcc_dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(cause, NULL, gcc_dwarf_cause_mips64, gcc_dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", gcc_dwarf_pc_mips64, gcc_dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
- DEFINE_GPR(ic, NULL, gcc_dwarf_ic_mips64, gcc_dwarf_ic_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(dummy, NULL, gcc_dwarf_dummy_mips64, gcc_dwarf_dummy_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r2, nullptr, dwarf_r2_mips64, dwarf_r2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r3, nullptr, dwarf_r3_mips64, dwarf_r3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r4, nullptr, dwarf_r4_mips64, dwarf_r4_mips64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r5, nullptr, dwarf_r5_mips64, dwarf_r5_mips64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r6, nullptr, dwarf_r6_mips64, dwarf_r6_mips64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r7, nullptr, dwarf_r7_mips64, dwarf_r7_mips64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r8, nullptr, dwarf_r8_mips64, dwarf_r8_mips64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r9, nullptr, dwarf_r9_mips64, dwarf_r9_mips64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r10, nullptr, dwarf_r10_mips64, dwarf_r10_mips64, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r11, nullptr, dwarf_r11_mips64, dwarf_r11_mips64, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r12, nullptr, dwarf_r12_mips64, dwarf_r12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r13, nullptr, dwarf_r13_mips64, dwarf_r13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r14, nullptr, dwarf_r14_mips64, dwarf_r14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r15, nullptr, dwarf_r15_mips64, dwarf_r15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r16, nullptr, dwarf_r16_mips64, dwarf_r16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r17, nullptr, dwarf_r17_mips64, dwarf_r17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r18, nullptr, dwarf_r18_mips64, dwarf_r18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r19, nullptr, dwarf_r19_mips64, dwarf_r19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r20, nullptr, dwarf_r20_mips64, dwarf_r20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r21, nullptr, dwarf_r21_mips64, dwarf_r21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r22, nullptr, dwarf_r22_mips64, dwarf_r22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r23, nullptr, dwarf_r23_mips64, dwarf_r23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r24, nullptr, dwarf_r24_mips64, dwarf_r24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r25, nullptr, dwarf_r25_mips64, dwarf_r25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r26, nullptr, dwarf_r26_mips64, dwarf_r26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r27, nullptr, dwarf_r27_mips64, dwarf_r27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(gp, "r28", dwarf_gp_mips64, dwarf_gp_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(sp, "r29", dwarf_sp_mips64, dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r30, nullptr, dwarf_r30_mips64, dwarf_r30_mips64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ra, "r31", dwarf_ra_mips64, dwarf_ra_mips64, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(sr, nullptr, dwarf_sr_mips64, dwarf_sr_mips64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mullo, nullptr, dwarf_lo_mips64, dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips64, dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips64, dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cause, nullptr, dwarf_cause_mips64, dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", dwarf_pc_mips64, dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ic, nullptr, dwarf_ic_mips64, dwarf_ic_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(dummy, nullptr, dwarf_dummy_mips64, dwarf_dummy_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
#else
-
- DEFINE_GPR(zero, "r0", gcc_dwarf_zero_mips64, gcc_dwarf_zero_mips64, LLDB_INVALID_REGNUM, gdb_zero_mips64),
- DEFINE_GPR(r1, NULL, gcc_dwarf_r1_mips64, gcc_dwarf_r1_mips64, LLDB_INVALID_REGNUM, gdb_r1_mips64),
- DEFINE_GPR(r2, NULL, gcc_dwarf_r2_mips64, gcc_dwarf_r2_mips64, LLDB_INVALID_REGNUM, gdb_r2_mips64),
- DEFINE_GPR(r3, NULL, gcc_dwarf_r3_mips64, gcc_dwarf_r3_mips64, LLDB_INVALID_REGNUM, gdb_r3_mips64),
- DEFINE_GPR(r4, NULL, gcc_dwarf_r4_mips64, gcc_dwarf_r4_mips64, LLDB_REGNUM_GENERIC_ARG1, gdb_r4_mips64),
- DEFINE_GPR(r5, NULL, gcc_dwarf_r5_mips64, gcc_dwarf_r5_mips64, LLDB_REGNUM_GENERIC_ARG2, gdb_r5_mips64),
- DEFINE_GPR(r6, NULL, gcc_dwarf_r6_mips64, gcc_dwarf_r6_mips64, LLDB_REGNUM_GENERIC_ARG3, gdb_r6_mips64),
- DEFINE_GPR(r7, NULL, gcc_dwarf_r7_mips64, gcc_dwarf_r7_mips64, LLDB_REGNUM_GENERIC_ARG4, gdb_r7_mips64),
- DEFINE_GPR(r8, NULL, gcc_dwarf_r8_mips64, gcc_dwarf_r8_mips64, LLDB_REGNUM_GENERIC_ARG5, gdb_r8_mips64),
- DEFINE_GPR(r9, NULL, gcc_dwarf_r9_mips64, gcc_dwarf_r9_mips64, LLDB_REGNUM_GENERIC_ARG6, gdb_r9_mips64),
- DEFINE_GPR(r10, NULL, gcc_dwarf_r10_mips64, gcc_dwarf_r10_mips64, LLDB_REGNUM_GENERIC_ARG7, gdb_r10_mips64),
- DEFINE_GPR(r11, NULL, gcc_dwarf_r11_mips64, gcc_dwarf_r11_mips64, LLDB_REGNUM_GENERIC_ARG8, gdb_r11_mips64),
- DEFINE_GPR(r12, NULL, gcc_dwarf_r12_mips64, gcc_dwarf_r12_mips64, LLDB_INVALID_REGNUM, gdb_r12_mips64),
- DEFINE_GPR(r13, NULL, gcc_dwarf_r13_mips64, gcc_dwarf_r13_mips64, LLDB_INVALID_REGNUM, gdb_r13_mips64),
- DEFINE_GPR(r14, NULL, gcc_dwarf_r14_mips64, gcc_dwarf_r14_mips64, LLDB_INVALID_REGNUM, gdb_r14_mips64),
- DEFINE_GPR(r15, NULL, gcc_dwarf_r15_mips64, gcc_dwarf_r15_mips64, LLDB_INVALID_REGNUM, gdb_r15_mips64),
- DEFINE_GPR(r16, NULL, gcc_dwarf_r16_mips64, gcc_dwarf_r16_mips64, LLDB_INVALID_REGNUM, gdb_r16_mips64),
- DEFINE_GPR(r17, NULL, gcc_dwarf_r17_mips64, gcc_dwarf_r17_mips64, LLDB_INVALID_REGNUM, gdb_r17_mips64),
- DEFINE_GPR(r18, NULL, gcc_dwarf_r18_mips64, gcc_dwarf_r18_mips64, LLDB_INVALID_REGNUM, gdb_r18_mips64),
- DEFINE_GPR(r19, NULL, gcc_dwarf_r19_mips64, gcc_dwarf_r19_mips64, LLDB_INVALID_REGNUM, gdb_r19_mips64),
- DEFINE_GPR(r20, NULL, gcc_dwarf_r20_mips64, gcc_dwarf_r20_mips64, LLDB_INVALID_REGNUM, gdb_r20_mips64),
- DEFINE_GPR(r21, NULL, gcc_dwarf_r21_mips64, gcc_dwarf_r21_mips64, LLDB_INVALID_REGNUM, gdb_r21_mips64),
- DEFINE_GPR(r22, NULL, gcc_dwarf_r22_mips64, gcc_dwarf_r22_mips64, LLDB_INVALID_REGNUM, gdb_r22_mips64),
- DEFINE_GPR(r23, NULL, gcc_dwarf_r23_mips64, gcc_dwarf_r23_mips64, LLDB_INVALID_REGNUM, gdb_r23_mips64),
- DEFINE_GPR(r24, NULL, gcc_dwarf_r24_mips64, gcc_dwarf_r24_mips64, LLDB_INVALID_REGNUM, gdb_r24_mips64),
- DEFINE_GPR(r25, NULL, gcc_dwarf_r25_mips64, gcc_dwarf_r25_mips64, LLDB_INVALID_REGNUM, gdb_r25_mips64),
- DEFINE_GPR(r26, NULL, gcc_dwarf_r26_mips64, gcc_dwarf_r26_mips64, LLDB_INVALID_REGNUM, gdb_r26_mips64),
- DEFINE_GPR(r27, NULL, gcc_dwarf_r27_mips64, gcc_dwarf_r27_mips64, LLDB_INVALID_REGNUM, gdb_r27_mips64),
- DEFINE_GPR(gp, "r28", gcc_dwarf_gp_mips64, gcc_dwarf_gp_mips64, LLDB_INVALID_REGNUM, gdb_gp_mips64),
- DEFINE_GPR(sp, "r29", gcc_dwarf_sp_mips64, gcc_dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, gdb_sp_mips64),
- DEFINE_GPR(r30, NULL, gcc_dwarf_r30_mips64, gcc_dwarf_r30_mips64, LLDB_REGNUM_GENERIC_FP, gdb_r30_mips64),
- DEFINE_GPR(ra, "r31", gcc_dwarf_ra_mips64, gcc_dwarf_ra_mips64, LLDB_REGNUM_GENERIC_RA, gdb_ra_mips64),
- DEFINE_GPR_INFO(sr, NULL, gcc_dwarf_sr_mips64, gcc_dwarf_sr_mips64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
- DEFINE_GPR(mullo, NULL, gcc_dwarf_lo_mips64, gcc_dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(mulhi, NULL, gcc_dwarf_hi_mips64, gcc_dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(badvaddr, NULL, gcc_dwarf_bad_mips64, gcc_dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR_INFO(cause, NULL, gcc_dwarf_cause_mips64, gcc_dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", gcc_dwarf_pc_mips64, gcc_dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
- DEFINE_GPR_INFO(config5, NULL, gcc_dwarf_config5_mips64, gcc_dwarf_config5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_FPR (f0, NULL, gcc_dwarf_f0_mips64, gcc_dwarf_f0_mips64, LLDB_INVALID_REGNUM, gdb_f0_mips64),
- DEFINE_FPR (f1, NULL, gcc_dwarf_f1_mips64, gcc_dwarf_f1_mips64, LLDB_INVALID_REGNUM, gdb_f1_mips64),
- DEFINE_FPR (f2, NULL, gcc_dwarf_f2_mips64, gcc_dwarf_f2_mips64, LLDB_INVALID_REGNUM, gdb_f2_mips64),
- DEFINE_FPR (f3, NULL, gcc_dwarf_f3_mips64, gcc_dwarf_f3_mips64, LLDB_INVALID_REGNUM, gdb_f3_mips64),
- DEFINE_FPR (f4, NULL, gcc_dwarf_f4_mips64, gcc_dwarf_f4_mips64, LLDB_INVALID_REGNUM, gdb_f4_mips64),
- DEFINE_FPR (f5, NULL, gcc_dwarf_f5_mips64, gcc_dwarf_f5_mips64, LLDB_INVALID_REGNUM, gdb_f5_mips64),
- DEFINE_FPR (f6, NULL, gcc_dwarf_f6_mips64, gcc_dwarf_f6_mips64, LLDB_INVALID_REGNUM, gdb_f6_mips64),
- DEFINE_FPR (f7, NULL, gcc_dwarf_f7_mips64, gcc_dwarf_f7_mips64, LLDB_INVALID_REGNUM, gdb_f7_mips64),
- DEFINE_FPR (f8, NULL, gcc_dwarf_f8_mips64, gcc_dwarf_f8_mips64, LLDB_INVALID_REGNUM, gdb_f8_mips64),
- DEFINE_FPR (f9, NULL, gcc_dwarf_f9_mips64, gcc_dwarf_f9_mips64, LLDB_INVALID_REGNUM, gdb_f9_mips64),
- DEFINE_FPR (f10, NULL, gcc_dwarf_f10_mips64, gcc_dwarf_f10_mips64, LLDB_INVALID_REGNUM, gdb_f10_mips64),
- DEFINE_FPR (f11, NULL, gcc_dwarf_f11_mips64, gcc_dwarf_f11_mips64, LLDB_INVALID_REGNUM, gdb_f11_mips64),
- DEFINE_FPR (f12, NULL, gcc_dwarf_f12_mips64, gcc_dwarf_f12_mips64, LLDB_INVALID_REGNUM, gdb_f12_mips64),
- DEFINE_FPR (f13, NULL, gcc_dwarf_f13_mips64, gcc_dwarf_f13_mips64, LLDB_INVALID_REGNUM, gdb_f13_mips64),
- DEFINE_FPR (f14, NULL, gcc_dwarf_f14_mips64, gcc_dwarf_f14_mips64, LLDB_INVALID_REGNUM, gdb_f14_mips64),
- DEFINE_FPR (f15, NULL, gcc_dwarf_f15_mips64, gcc_dwarf_f15_mips64, LLDB_INVALID_REGNUM, gdb_f15_mips64),
- DEFINE_FPR (f16, NULL, gcc_dwarf_f16_mips64, gcc_dwarf_f16_mips64, LLDB_INVALID_REGNUM, gdb_f16_mips64),
- DEFINE_FPR (f17, NULL, gcc_dwarf_f17_mips64, gcc_dwarf_f17_mips64, LLDB_INVALID_REGNUM, gdb_f17_mips64),
- DEFINE_FPR (f18, NULL, gcc_dwarf_f18_mips64, gcc_dwarf_f18_mips64, LLDB_INVALID_REGNUM, gdb_f18_mips64),
- DEFINE_FPR (f19, NULL, gcc_dwarf_f19_mips64, gcc_dwarf_f19_mips64, LLDB_INVALID_REGNUM, gdb_f19_mips64),
- DEFINE_FPR (f20, NULL, gcc_dwarf_f20_mips64, gcc_dwarf_f20_mips64, LLDB_INVALID_REGNUM, gdb_f20_mips64),
- DEFINE_FPR (f21, NULL, gcc_dwarf_f21_mips64, gcc_dwarf_f21_mips64, LLDB_INVALID_REGNUM, gdb_f21_mips64),
- DEFINE_FPR (f22, NULL, gcc_dwarf_f22_mips64, gcc_dwarf_f22_mips64, LLDB_INVALID_REGNUM, gdb_f22_mips64),
- DEFINE_FPR (f23, NULL, gcc_dwarf_f23_mips64, gcc_dwarf_f23_mips64, LLDB_INVALID_REGNUM, gdb_f23_mips64),
- DEFINE_FPR (f24, NULL, gcc_dwarf_f24_mips64, gcc_dwarf_f24_mips64, LLDB_INVALID_REGNUM, gdb_f24_mips64),
- DEFINE_FPR (f25, NULL, gcc_dwarf_f25_mips64, gcc_dwarf_f25_mips64, LLDB_INVALID_REGNUM, gdb_f25_mips64),
- DEFINE_FPR (f26, NULL, gcc_dwarf_f26_mips64, gcc_dwarf_f26_mips64, LLDB_INVALID_REGNUM, gdb_f26_mips64),
- DEFINE_FPR (f27, NULL, gcc_dwarf_f27_mips64, gcc_dwarf_f27_mips64, LLDB_INVALID_REGNUM, gdb_f27_mips64),
- DEFINE_FPR (f28, NULL, gcc_dwarf_f28_mips64, gcc_dwarf_f28_mips64, LLDB_INVALID_REGNUM, gdb_f28_mips64),
- DEFINE_FPR (f29, NULL, gcc_dwarf_f29_mips64, gcc_dwarf_f29_mips64, LLDB_INVALID_REGNUM, gdb_f29_mips64),
- DEFINE_FPR (f30, NULL, gcc_dwarf_f30_mips64, gcc_dwarf_f30_mips64, LLDB_INVALID_REGNUM, gdb_f30_mips64),
- DEFINE_FPR (f31, NULL, gcc_dwarf_f31_mips64, gcc_dwarf_f31_mips64, LLDB_INVALID_REGNUM, gdb_f31_mips64),
- DEFINE_FPR (fcsr, NULL, gcc_dwarf_fcsr_mips64, gcc_dwarf_fcsr_mips64, LLDB_INVALID_REGNUM, gdb_fcsr_mips64),
- DEFINE_FPR (fir, NULL, gcc_dwarf_fir_mips64, gcc_dwarf_fir_mips64, LLDB_INVALID_REGNUM, gdb_fir_mips64),
- DEFINE_FPR (config5, NULL, gcc_dwarf_config5_mips64, gcc_dwarf_config5_mips64, LLDB_INVALID_REGNUM, gdb_config5_mips64),
- DEFINE_MSA (w0, NULL, gcc_dwarf_w0_mips64, gcc_dwarf_w0_mips64, LLDB_INVALID_REGNUM, gdb_w0_mips64),
- DEFINE_MSA (w1, NULL, gcc_dwarf_w1_mips64, gcc_dwarf_w1_mips64, LLDB_INVALID_REGNUM, gdb_w1_mips64),
- DEFINE_MSA (w2, NULL, gcc_dwarf_w2_mips64, gcc_dwarf_w2_mips64, LLDB_INVALID_REGNUM, gdb_w2_mips64),
- DEFINE_MSA (w3, NULL, gcc_dwarf_w3_mips64, gcc_dwarf_w3_mips64, LLDB_INVALID_REGNUM, gdb_w3_mips64),
- DEFINE_MSA (w4, NULL, gcc_dwarf_w4_mips64, gcc_dwarf_w4_mips64, LLDB_INVALID_REGNUM, gdb_w4_mips64),
- DEFINE_MSA (w5, NULL, gcc_dwarf_w5_mips64, gcc_dwarf_w5_mips64, LLDB_INVALID_REGNUM, gdb_w5_mips64),
- DEFINE_MSA (w6, NULL, gcc_dwarf_w6_mips64, gcc_dwarf_w6_mips64, LLDB_INVALID_REGNUM, gdb_w6_mips64),
- DEFINE_MSA (w7, NULL, gcc_dwarf_w7_mips64, gcc_dwarf_w7_mips64, LLDB_INVALID_REGNUM, gdb_w7_mips64),
- DEFINE_MSA (w8, NULL, gcc_dwarf_w8_mips64, gcc_dwarf_w8_mips64, LLDB_INVALID_REGNUM, gdb_w8_mips64),
- DEFINE_MSA (w9, NULL, gcc_dwarf_w9_mips64, gcc_dwarf_w9_mips64, LLDB_INVALID_REGNUM, gdb_w9_mips64),
- DEFINE_MSA (w10, NULL, gcc_dwarf_w10_mips64, gcc_dwarf_w10_mips64, LLDB_INVALID_REGNUM, gdb_w10_mips64),
- DEFINE_MSA (w11, NULL, gcc_dwarf_w11_mips64, gcc_dwarf_w11_mips64, LLDB_INVALID_REGNUM, gdb_w11_mips64),
- DEFINE_MSA (w12, NULL, gcc_dwarf_w12_mips64, gcc_dwarf_w12_mips64, LLDB_INVALID_REGNUM, gdb_w12_mips64),
- DEFINE_MSA (w13, NULL, gcc_dwarf_w13_mips64, gcc_dwarf_w13_mips64, LLDB_INVALID_REGNUM, gdb_w13_mips64),
- DEFINE_MSA (w14, NULL, gcc_dwarf_w14_mips64, gcc_dwarf_w14_mips64, LLDB_INVALID_REGNUM, gdb_w14_mips64),
- DEFINE_MSA (w15, NULL, gcc_dwarf_w15_mips64, gcc_dwarf_w15_mips64, LLDB_INVALID_REGNUM, gdb_w15_mips64),
- DEFINE_MSA (w16, NULL, gcc_dwarf_w16_mips64, gcc_dwarf_w16_mips64, LLDB_INVALID_REGNUM, gdb_w16_mips64),
- DEFINE_MSA (w17, NULL, gcc_dwarf_w17_mips64, gcc_dwarf_w17_mips64, LLDB_INVALID_REGNUM, gdb_w17_mips64),
- DEFINE_MSA (w18, NULL, gcc_dwarf_w18_mips64, gcc_dwarf_w18_mips64, LLDB_INVALID_REGNUM, gdb_w18_mips64),
- DEFINE_MSA (w19, NULL, gcc_dwarf_w19_mips64, gcc_dwarf_w19_mips64, LLDB_INVALID_REGNUM, gdb_w19_mips64),
- DEFINE_MSA (w20, NULL, gcc_dwarf_w10_mips64, gcc_dwarf_w20_mips64, LLDB_INVALID_REGNUM, gdb_w20_mips64),
- DEFINE_MSA (w21, NULL, gcc_dwarf_w21_mips64, gcc_dwarf_w21_mips64, LLDB_INVALID_REGNUM, gdb_w21_mips64),
- DEFINE_MSA (w22, NULL, gcc_dwarf_w22_mips64, gcc_dwarf_w22_mips64, LLDB_INVALID_REGNUM, gdb_w22_mips64),
- DEFINE_MSA (w23, NULL, gcc_dwarf_w23_mips64, gcc_dwarf_w23_mips64, LLDB_INVALID_REGNUM, gdb_w23_mips64),
- DEFINE_MSA (w24, NULL, gcc_dwarf_w24_mips64, gcc_dwarf_w24_mips64, LLDB_INVALID_REGNUM, gdb_w24_mips64),
- DEFINE_MSA (w25, NULL, gcc_dwarf_w25_mips64, gcc_dwarf_w25_mips64, LLDB_INVALID_REGNUM, gdb_w25_mips64),
- DEFINE_MSA (w26, NULL, gcc_dwarf_w26_mips64, gcc_dwarf_w26_mips64, LLDB_INVALID_REGNUM, gdb_w26_mips64),
- DEFINE_MSA (w27, NULL, gcc_dwarf_w27_mips64, gcc_dwarf_w27_mips64, LLDB_INVALID_REGNUM, gdb_w27_mips64),
- DEFINE_MSA (w28, NULL, gcc_dwarf_w28_mips64, gcc_dwarf_w28_mips64, LLDB_INVALID_REGNUM, gdb_w28_mips64),
- DEFINE_MSA (w29, NULL, gcc_dwarf_w29_mips64, gcc_dwarf_w29_mips64, LLDB_INVALID_REGNUM, gdb_w29_mips64),
- DEFINE_MSA (w30, NULL, gcc_dwarf_w30_mips64, gcc_dwarf_w30_mips64, LLDB_INVALID_REGNUM, gdb_w30_mips64),
- DEFINE_MSA (w31, NULL, gcc_dwarf_w31_mips64, gcc_dwarf_w31_mips64, LLDB_INVALID_REGNUM, gdb_w31_mips64),
- DEFINE_MSA_INFO (mcsr, NULL, gcc_dwarf_mcsr_mips64, gcc_dwarf_mcsr_mips64, LLDB_INVALID_REGNUM, gdb_mcsr_mips64),
- DEFINE_MSA_INFO (mir, NULL, gcc_dwarf_mir_mips64, gcc_dwarf_mir_mips64, LLDB_INVALID_REGNUM, gdb_mir_mips64),
- DEFINE_MSA_INFO (fcsr, NULL, gcc_dwarf_fcsr_mips64, gcc_dwarf_fcsr_mips64, LLDB_INVALID_REGNUM, gdb_fcsr_mips64),
- DEFINE_MSA_INFO (fir, NULL, gcc_dwarf_fir_mips64, gcc_dwarf_fir_mips64, LLDB_INVALID_REGNUM, gdb_fir_mips64),
- DEFINE_MSA_INFO (config5, NULL, gcc_dwarf_config5_mips64, gcc_dwarf_config5_mips64, LLDB_INVALID_REGNUM, gdb_config5_mips64)
+ DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r2, nullptr, dwarf_r2_mips64, dwarf_r2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r3, nullptr, dwarf_r3_mips64, dwarf_r3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r4, nullptr, dwarf_r4_mips64, dwarf_r4_mips64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r5, nullptr, dwarf_r5_mips64, dwarf_r5_mips64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r6, nullptr, dwarf_r6_mips64, dwarf_r6_mips64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r7, nullptr, dwarf_r7_mips64, dwarf_r7_mips64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r8, nullptr, dwarf_r8_mips64, dwarf_r8_mips64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r9, nullptr, dwarf_r9_mips64, dwarf_r9_mips64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r10, nullptr, dwarf_r10_mips64, dwarf_r10_mips64, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r11, nullptr, dwarf_r11_mips64, dwarf_r11_mips64, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r12, nullptr, dwarf_r12_mips64, dwarf_r12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r13, nullptr, dwarf_r13_mips64, dwarf_r13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r14, nullptr, dwarf_r14_mips64, dwarf_r14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r15, nullptr, dwarf_r15_mips64, dwarf_r15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r16, nullptr, dwarf_r16_mips64, dwarf_r16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r17, nullptr, dwarf_r17_mips64, dwarf_r17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r18, nullptr, dwarf_r18_mips64, dwarf_r18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r19, nullptr, dwarf_r19_mips64, dwarf_r19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r20, nullptr, dwarf_r20_mips64, dwarf_r20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r21, nullptr, dwarf_r21_mips64, dwarf_r21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r22, nullptr, dwarf_r22_mips64, dwarf_r22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r23, nullptr, dwarf_r23_mips64, dwarf_r23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r24, nullptr, dwarf_r24_mips64, dwarf_r24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r25, nullptr, dwarf_r25_mips64, dwarf_r25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r26, nullptr, dwarf_r26_mips64, dwarf_r26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r27, nullptr, dwarf_r27_mips64, dwarf_r27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(gp, "r28", dwarf_gp_mips64, dwarf_gp_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(sp, "r29", dwarf_sp_mips64, dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r30, nullptr, dwarf_r30_mips64, dwarf_r30_mips64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ra, "r31", dwarf_ra_mips64, dwarf_ra_mips64, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM),
+ DEFINE_GPR_INFO(sr, nullptr, dwarf_sr_mips64, dwarf_sr_mips64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mullo, nullptr, dwarf_lo_mips64, dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips64, dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips64, dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR_INFO(cause, nullptr, dwarf_cause_mips64, dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", dwarf_pc_mips64, dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR_INFO(config5, nullptr, dwarf_config5_mips64, dwarf_config5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f0, nullptr, dwarf_f0_mips64, dwarf_f0_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f1, nullptr, dwarf_f1_mips64, dwarf_f1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f2, nullptr, dwarf_f2_mips64, dwarf_f2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f3, nullptr, dwarf_f3_mips64, dwarf_f3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f4, nullptr, dwarf_f4_mips64, dwarf_f4_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f5, nullptr, dwarf_f5_mips64, dwarf_f5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f6, nullptr, dwarf_f6_mips64, dwarf_f6_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f7, nullptr, dwarf_f7_mips64, dwarf_f7_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f8, nullptr, dwarf_f8_mips64, dwarf_f8_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f9, nullptr, dwarf_f9_mips64, dwarf_f9_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f10, nullptr, dwarf_f10_mips64, dwarf_f10_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f11, nullptr, dwarf_f11_mips64, dwarf_f11_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f12, nullptr, dwarf_f12_mips64, dwarf_f12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f13, nullptr, dwarf_f13_mips64, dwarf_f13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f14, nullptr, dwarf_f14_mips64, dwarf_f14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f15, nullptr, dwarf_f15_mips64, dwarf_f15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f16, nullptr, dwarf_f16_mips64, dwarf_f16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f17, nullptr, dwarf_f17_mips64, dwarf_f17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f18, nullptr, dwarf_f18_mips64, dwarf_f18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f19, nullptr, dwarf_f19_mips64, dwarf_f19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f20, nullptr, dwarf_f20_mips64, dwarf_f20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f21, nullptr, dwarf_f21_mips64, dwarf_f21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f22, nullptr, dwarf_f22_mips64, dwarf_f22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f23, nullptr, dwarf_f23_mips64, dwarf_f23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f24, nullptr, dwarf_f24_mips64, dwarf_f24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f25, nullptr, dwarf_f25_mips64, dwarf_f25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f26, nullptr, dwarf_f26_mips64, dwarf_f26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f27, nullptr, dwarf_f27_mips64, dwarf_f27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f28, nullptr, dwarf_f28_mips64, dwarf_f28_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f29, nullptr, dwarf_f29_mips64, dwarf_f29_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f30, nullptr, dwarf_f30_mips64, dwarf_f30_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f31, nullptr, dwarf_f31_mips64, dwarf_f31_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (config5, nullptr, dwarf_config5_mips64, dwarf_config5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w0, nullptr, dwarf_w0_mips64, dwarf_w0_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w1, nullptr, dwarf_w1_mips64, dwarf_w1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w2, nullptr, dwarf_w2_mips64, dwarf_w2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w3, nullptr, dwarf_w3_mips64, dwarf_w3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w4, nullptr, dwarf_w4_mips64, dwarf_w4_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w5, nullptr, dwarf_w5_mips64, dwarf_w5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w6, nullptr, dwarf_w6_mips64, dwarf_w6_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w7, nullptr, dwarf_w7_mips64, dwarf_w7_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w8, nullptr, dwarf_w8_mips64, dwarf_w8_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w9, nullptr, dwarf_w9_mips64, dwarf_w9_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w10, nullptr, dwarf_w10_mips64, dwarf_w10_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w11, nullptr, dwarf_w11_mips64, dwarf_w11_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w12, nullptr, dwarf_w12_mips64, dwarf_w12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w13, nullptr, dwarf_w13_mips64, dwarf_w13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w14, nullptr, dwarf_w14_mips64, dwarf_w14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w15, nullptr, dwarf_w15_mips64, dwarf_w15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w16, nullptr, dwarf_w16_mips64, dwarf_w16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w17, nullptr, dwarf_w17_mips64, dwarf_w17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w18, nullptr, dwarf_w18_mips64, dwarf_w18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w19, nullptr, dwarf_w19_mips64, dwarf_w19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w20, nullptr, dwarf_w10_mips64, dwarf_w20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w21, nullptr, dwarf_w21_mips64, dwarf_w21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w22, nullptr, dwarf_w22_mips64, dwarf_w22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w23, nullptr, dwarf_w23_mips64, dwarf_w23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w24, nullptr, dwarf_w24_mips64, dwarf_w24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w25, nullptr, dwarf_w25_mips64, dwarf_w25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w26, nullptr, dwarf_w26_mips64, dwarf_w26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w27, nullptr, dwarf_w27_mips64, dwarf_w27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w28, nullptr, dwarf_w28_mips64, dwarf_w28_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w29, nullptr, dwarf_w29_mips64, dwarf_w29_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w30, nullptr, dwarf_w30_mips64, dwarf_w30_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w31, nullptr, dwarf_w31_mips64, dwarf_w31_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (mcsr, nullptr, dwarf_mcsr_mips64, dwarf_mcsr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (mir, nullptr, dwarf_mir_mips64, dwarf_mir_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (config5, nullptr, dwarf_config5_mips64, dwarf_config5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM)
#endif
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
index fe145e9..95347ae 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
@@ -24,15 +24,15 @@
// Note that the size and offset will be updated by platform-specific classes.
#define DEFINE_GPR(reg, alt, lldb_kind) \
{ #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, gpr_##reg##_powerpc }, NULL, NULL }
+ eFormatHex, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, gpr_##reg##_powerpc }, NULL, NULL }
#define DEFINE_FPR(reg, lldb_kind) \
{ #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, \
- eFormatFloat, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, fpr_##reg##_powerpc }, NULL, NULL }
+ eFormatFloat, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, fpr_##reg##_powerpc }, NULL, NULL }
#define DEFINE_VMX(reg, lldb_kind) \
{ #reg, NULL, 16, VMX_OFFSET(reg), eEncodingVector, \
- eFormatVectorOfUInt32, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, vmx_##reg##_powerpc }, NULL, NULL }
+ eFormatVectorOfUInt32, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, vmx_##reg##_powerpc }, NULL, NULL }
- // General purpose registers. GCC, DWARF, Generic, GDB
+ // General purpose registers. EH_Frame, DWARF, Generic, Process Plugin
#define POWERPC_REGS \
DEFINE_GPR(r0, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r1, "sp", LLDB_REGNUM_GENERIC_SP), \
@@ -103,7 +103,7 @@
DEFINE_FPR(f29, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f30, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f31, LLDB_INVALID_REGNUM), \
- { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL }, \
+ { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { dwarf_fpscr_powerpc, dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_fpscr_powerpc }, NULL, NULL }, \
DEFINE_VMX(v0, LLDB_INVALID_REGNUM), \
DEFINE_VMX(v1, LLDB_INVALID_REGNUM), \
DEFINE_VMX(v2, LLDB_INVALID_REGNUM), \
@@ -136,8 +136,8 @@
DEFINE_VMX(v29, LLDB_INVALID_REGNUM), \
DEFINE_VMX(v30, LLDB_INVALID_REGNUM), \
DEFINE_VMX(v31, LLDB_INVALID_REGNUM), \
- { "vrsave", NULL, 4, VMX_OFFSET(vrsave), eEncodingUint, eFormatHex, { gcc_dwarf_vrsave_powerpc, gcc_dwarf_vrsave_powerpc, LLDB_INVALID_REGNUM, gdb_vrsave_powerpc, vmx_vrsave_powerpc }, NULL, NULL }, \
- { "vscr", NULL, 4, VMX_OFFSET(vscr), eEncodingUint, eFormatHex, { gcc_dwarf_vscr_powerpc, gcc_dwarf_vscr_powerpc, LLDB_INVALID_REGNUM, gdb_vscr_powerpc, vmx_vscr_powerpc }, NULL, NULL },
+ { "vrsave", NULL, 4, VMX_OFFSET(vrsave), eEncodingUint, eFormatHex, { dwarf_vrsave_powerpc, dwarf_vrsave_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vrsave_powerpc }, NULL, NULL }, \
+ { "vscr", NULL, 4, VMX_OFFSET(vscr), eEncodingUint, eFormatHex, { dwarf_vscr_powerpc, dwarf_vscr_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vscr_powerpc }, NULL, NULL },
static RegisterInfo
g_register_infos_powerpc64[] =
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
index 5da74ff..a393089 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
@@ -1,15 +1,21 @@
-//===-- RegisterInfos_x86_64.h ---------------------------------*- C++ -*-===//
+//===-- RegisterInfos_x86_64.h ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
-#include "llvm/Support/Compiler.h"
+//===----------------------------------------------------------------------===//
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/Compiler.h"
+
+// Project includes
+
// Computes the offset of the given GPR in the user data area.
#define GPR_OFFSET(regname) \
(LLVM_EXTENSION offsetof(GPR, regname))
@@ -44,7 +50,7 @@
#define DR_SIZE sizeof(((DBG*)NULL)->dr[0])
-// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
// Note that the size and offset will be updated by platform-specific classes.
#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
@@ -58,25 +64,25 @@
#define DEFINE_FP_ST(reg, i) \
{ #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_dwarf_st##i##_x86_64, gcc_dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, lldb_st##i##_x86_64 }, \
+ { dwarf_st##i##_x86_64, dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_st##i##_x86_64 }, \
NULL, NULL }
#define DEFINE_FP_MM(reg, i) \
{ #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
eEncodingUint, eFormatHex, \
- { gcc_dwarf_mm##i##_x86_64, gcc_dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, lldb_mm##i##_x86_64 }, \
+ { dwarf_mm##i##_x86_64, dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_mm##i##_x86_64 }, \
NULL, NULL }
#define DEFINE_XMM(reg, i) \
{ #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_dwarf_##reg##i##_x86_64, gcc_dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##_x86_64, lldb_##reg##i##_x86_64}, \
+ { dwarf_##reg##i##_x86_64, dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_x86_64}, \
NULL, NULL }
#define DEFINE_YMM(reg, i) \
{ #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(i), \
eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_dwarf_##reg##i##h_x86_64, gcc_dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##h_x86_64, lldb_##reg##i##_x86_64 }, \
+ { dwarf_##reg##i##h_x86_64, dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_x86_64 }, \
NULL, NULL }
#define DEFINE_DR(reg, i) \
@@ -100,31 +106,31 @@
static RegisterInfo
g_register_infos_x86_64[] =
{
- // General purpose registers. GCC, DWARF, Generic, GDB
- DEFINE_GPR(rax, NULL, gcc_dwarf_rax_x86_64, gcc_dwarf_rax_x86_64, LLDB_INVALID_REGNUM, gdb_rax_x86_64),
- DEFINE_GPR(rbx, NULL, gcc_dwarf_rbx_x86_64, gcc_dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, gdb_rbx_x86_64),
- DEFINE_GPR(rcx, "arg4", gcc_dwarf_rcx_x86_64, gcc_dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG4, gdb_rcx_x86_64),
- DEFINE_GPR(rdx, "arg3", gcc_dwarf_rdx_x86_64, gcc_dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG3, gdb_rdx_x86_64),
- DEFINE_GPR(rdi, "arg1", gcc_dwarf_rdi_x86_64, gcc_dwarf_rdi_x86_64, LLDB_REGNUM_GENERIC_ARG1, gdb_rdi_x86_64),
- DEFINE_GPR(rsi, "arg2", gcc_dwarf_rsi_x86_64, gcc_dwarf_rsi_x86_64, LLDB_REGNUM_GENERIC_ARG2, gdb_rsi_x86_64),
- DEFINE_GPR(rbp, "fp", gcc_dwarf_rbp_x86_64, gcc_dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, gdb_rbp_x86_64),
- DEFINE_GPR(rsp, "sp", gcc_dwarf_rsp_x86_64, gcc_dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, gdb_rsp_x86_64),
- DEFINE_GPR(r8, "arg5", gcc_dwarf_r8_x86_64, gcc_dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG5, gdb_r8_x86_64),
- DEFINE_GPR(r9, "arg6", gcc_dwarf_r9_x86_64, gcc_dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG6, gdb_r9_x86_64),
- DEFINE_GPR(r10, NULL, gcc_dwarf_r10_x86_64, gcc_dwarf_r10_x86_64, LLDB_INVALID_REGNUM, gdb_r10_x86_64),
- DEFINE_GPR(r11, NULL, gcc_dwarf_r11_x86_64, gcc_dwarf_r11_x86_64, LLDB_INVALID_REGNUM, gdb_r11_x86_64),
- DEFINE_GPR(r12, NULL, gcc_dwarf_r12_x86_64, gcc_dwarf_r12_x86_64, LLDB_INVALID_REGNUM, gdb_r12_x86_64),
- DEFINE_GPR(r13, NULL, gcc_dwarf_r13_x86_64, gcc_dwarf_r13_x86_64, LLDB_INVALID_REGNUM, gdb_r13_x86_64),
- DEFINE_GPR(r14, NULL, gcc_dwarf_r14_x86_64, gcc_dwarf_r14_x86_64, LLDB_INVALID_REGNUM, gdb_r14_x86_64),
- DEFINE_GPR(r15, NULL, gcc_dwarf_r15_x86_64, gcc_dwarf_r15_x86_64, LLDB_INVALID_REGNUM, gdb_r15_x86_64),
- DEFINE_GPR(rip, "pc", gcc_dwarf_rip_x86_64, gcc_dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, gdb_rip_x86_64),
- DEFINE_GPR(rflags, "flags", gcc_dwarf_rflags_x86_64, gcc_dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, gdb_rflags_x86_64),
- DEFINE_GPR(cs, NULL, gcc_dwarf_cs_x86_64, gcc_dwarf_cs_x86_64, LLDB_INVALID_REGNUM, gdb_cs_x86_64),
- DEFINE_GPR(fs, NULL, gcc_dwarf_fs_x86_64, gcc_dwarf_fs_x86_64, LLDB_INVALID_REGNUM, gdb_fs_x86_64),
- DEFINE_GPR(gs, NULL, gcc_dwarf_gs_x86_64, gcc_dwarf_gs_x86_64, LLDB_INVALID_REGNUM, gdb_gs_x86_64),
- DEFINE_GPR(ss, NULL, gcc_dwarf_ss_x86_64, gcc_dwarf_ss_x86_64, LLDB_INVALID_REGNUM, gdb_ss_x86_64),
- DEFINE_GPR(ds, NULL, gcc_dwarf_ds_x86_64, gcc_dwarf_ds_x86_64, LLDB_INVALID_REGNUM, gdb_ds_x86_64),
- DEFINE_GPR(es, NULL, gcc_dwarf_es_x86_64, gcc_dwarf_es_x86_64, LLDB_INVALID_REGNUM, gdb_es_x86_64),
+ // General purpose registers. EH_Frame, DWARF, Generic, Process Plugin
+ DEFINE_GPR(rax, nullptr, dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rbx, nullptr, dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rcx, "arg4", dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rdx, "arg3", dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rdi, "arg1", dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rsi, "arg2", dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rbp, "fp", dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rsp, "sp", dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r8, "arg5", dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r9, "arg6", dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r10, nullptr, dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r11, nullptr, dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r12, nullptr, dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r13, nullptr, dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r14, nullptr, dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r15, nullptr, dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rip, "pc", dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rflags, "flags", dwarf_rflags_x86_64, dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cs, nullptr, dwarf_cs_x86_64, dwarf_cs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_GPR_PSEUDO_32(eax, rax),
DEFINE_GPR_PSEUDO_32(ebx, rbx),
@@ -179,16 +185,16 @@ g_register_infos_x86_64[] =
DEFINE_GPR_PSEUDO_8L(r14l, r14),
DEFINE_GPR_PSEUDO_8L(r15l, r15),
- // i387 Floating point registers. GCC, DWARF, Generic, GDB
- DEFINE_FPR(fctrl, fctrl, gcc_dwarf_fctrl_x86_64, gcc_dwarf_fctrl_x86_64, LLDB_INVALID_REGNUM, gdb_fctrl_x86_64),
- DEFINE_FPR(fstat, fstat, gcc_dwarf_fstat_x86_64, gcc_dwarf_fstat_x86_64, LLDB_INVALID_REGNUM, gdb_fstat_x86_64),
- DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftag_x86_64),
- DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop_x86_64),
- DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_x86_64),
- DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_x86_64),
- DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_x86_64),
- DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_x86_64),
- DEFINE_FPR(mxcsr, mxcsr, gcc_dwarf_mxcsr_x86_64, gcc_dwarf_mxcsr_x86_64, LLDB_INVALID_REGNUM, gdb_mxcsr_x86_64),
+ // i387 Floating point registers. EH_frame, DWARF, Generic, Process Plugin
+ DEFINE_FPR(fctrl, fctrl, dwarf_fctrl_x86_64, dwarf_fctrl_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fstat, fstat, dwarf_fstat_x86_64, dwarf_fstat_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(mxcsr, mxcsr, dwarf_mxcsr_x86_64, dwarf_mxcsr_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
// FP registers.
@@ -255,6 +261,7 @@ g_register_infos_x86_64[] =
DEFINE_DR(dr, 6),
DEFINE_DR(dr, 7)
};
+
static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[0])) == k_num_registers_x86_64,
"g_register_infos_x86_64 has wrong number of register infos");
@@ -275,7 +282,6 @@ static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[
#endif // DECLARE_REGISTER_INFOS_X86_64_STRUCT
-
#ifdef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
#define UPDATE_GPR_INFO(reg, reg64) \
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 7c68d0d..3bf766e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -58,6 +58,7 @@ StopInfoMachException::GetDescription ()
}
break;
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
switch (m_exc_code)
{
case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
@@ -104,6 +105,7 @@ StopInfoMachException::GetDescription ()
break;
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
if (m_exc_code == 1)
code_desc = "EXC_ARM_UNDEFINED";
break;
@@ -188,6 +190,7 @@ StopInfoMachException::GetDescription ()
break;
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
switch (m_exc_code)
{
case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
@@ -408,6 +411,7 @@ StopInfoMachException::CreateStopReasonWithMachException
break;
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
{
// It's a watchpoint, then, if the exc_sub_code indicates a known/enabled
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
index 130ee0b..25e05ec 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
@@ -38,19 +38,16 @@ public:
{
}
- virtual ~StopInfoMachException()
- {
- }
+ ~StopInfoMachException() override = default;
-
- virtual lldb::StopReason
- GetStopReason () const
+ lldb::StopReason
+ GetStopReason() const override
{
return lldb::eStopReasonException;
}
- virtual const char *
- GetDescription ();
+ const char *
+ GetDescription() override;
// Since some mach exceptions will be reported as breakpoints, signals,
// or trace, we use this static accessor which will translate the mach
@@ -71,7 +68,6 @@ protected:
uint64_t m_exc_subcode;
};
-
} // namespace lldb_private
-#endif // liblldb_StopInfoMachException_h_
+#endif // liblldb_StopInfoMachException_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/ThreadMemory.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/ThreadMemory.h
index 07eb45d..1e7cbfa 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/ThreadMemory.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/ThreadMemory.h
@@ -1,4 +1,4 @@
-//===-- ThreadMemory.h -----------------------------------------*- C++ -*-===//
+//===-- ThreadMemory.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,13 +10,18 @@
#ifndef liblldb_ThreadMemory_h_
#define liblldb_ThreadMemory_h_
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/Target/Thread.h"
class ThreadMemory :
public lldb_private::Thread
{
public:
-
ThreadMemory (lldb_private::Process &process,
lldb::tid_t tid,
const lldb::ValueObjectSP &thread_info_valobj_sp);
@@ -27,69 +32,65 @@ public:
const char *queue,
lldb::addr_t register_data_addr);
- virtual
- ~ThreadMemory();
+ ~ThreadMemory() override;
- //------------------------------------------------------------------
- // lldb_private::Thread methods
- //------------------------------------------------------------------
- virtual lldb::RegisterContextSP
- GetRegisterContext ();
+ lldb::RegisterContextSP
+ GetRegisterContext() override;
- virtual lldb::RegisterContextSP
- CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
- virtual bool
- CalculateStopInfo ();
+ bool
+ CalculateStopInfo() override;
- virtual const char *
- GetInfo ()
+ const char *
+ GetInfo() override
{
if (m_backing_thread_sp)
m_backing_thread_sp->GetInfo();
- return NULL;
+ return nullptr;
}
- virtual const char *
- GetName ()
+ const char *
+ GetName() override
{
if (!m_name.empty())
return m_name.c_str();
if (m_backing_thread_sp)
m_backing_thread_sp->GetName();
- return NULL;
+ return nullptr;
}
- virtual const char *
- GetQueueName ()
+ const char *
+ GetQueueName() override
{
if (!m_queue.empty())
return m_queue.c_str();
if (m_backing_thread_sp)
m_backing_thread_sp->GetQueueName();
- return NULL;
+ return nullptr;
}
- virtual void
- WillResume (lldb::StateType resume_state);
+ void
+ WillResume(lldb::StateType resume_state) override;
- virtual void
- DidResume ()
+ void
+ DidResume() override
{
if (m_backing_thread_sp)
m_backing_thread_sp->DidResume();
}
- virtual lldb::user_id_t
- GetProtocolID () const
+ lldb::user_id_t
+ GetProtocolID() const override
{
if (m_backing_thread_sp)
return m_backing_thread_sp->GetProtocolID();
return Thread::GetProtocolID();
}
- virtual void
- RefreshStateAfterStop();
+ void
+ RefreshStateAfterStop() override;
lldb::ValueObjectSP &
GetValueObject ()
@@ -97,41 +98,36 @@ public:
return m_thread_info_valobj_sp;
}
- virtual void
- ClearStackFrames ();
+ void
+ ClearStackFrames() override;
- virtual void
- ClearBackingThread ()
+ void
+ ClearBackingThread() override
{
m_backing_thread_sp.reset();
}
- virtual bool
- SetBackingThread (const lldb::ThreadSP &thread_sp)
+ bool
+ SetBackingThread(const lldb::ThreadSP &thread_sp) override
{
//printf ("Thread 0x%llx is being backed by thread 0x%llx\n", GetID(), thread_sp->GetID());
m_backing_thread_sp = thread_sp;
return (bool)thread_sp;
}
- virtual lldb::ThreadSP
- GetBackingThread () const
+ lldb::ThreadSP
+ GetBackingThread() const override
{
return m_backing_thread_sp;
}
protected:
-
- virtual bool
- IsOperatingSystemPluginThread () const
+ bool
+ IsOperatingSystemPluginThread() const override
{
return true;
}
-
- //------------------------------------------------------------------
- // For ThreadMemory and subclasses
- //------------------------------------------------------------------
// If this memory thread is actually represented by a thread from the
// lldb_private::Process subclass, then fill in the thread here and
// all APIs will be routed through this thread object. If m_backing_thread_sp
@@ -142,11 +138,9 @@ protected:
std::string m_name;
std::string m_queue;
lldb::addr_t m_register_data_addr;
+
private:
- //------------------------------------------------------------------
- // For ThreadMemory only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (ThreadMemory);
};
-#endif // liblldb_ThreadMemory_h_
+#endif // liblldb_ThreadMemory_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 1cdae90..9be09c4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -86,6 +86,9 @@ UnwindLLDB::AddFirstFrame ()
if (m_frames.size() > 0)
return true;
+ ProcessSP process_sp (m_thread.GetProcess());
+ ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
+
// First, set up the 0th (initial) frame
CursorSP first_cursor_sp(new Cursor ());
RegisterContextLLDBSP reg_ctx_sp (new RegisterContextLLDB (m_thread,
@@ -108,6 +111,10 @@ UnwindLLDB::AddFirstFrame ()
// cursor own it in its shared pointer
first_cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;
m_frames.push_back (first_cursor_sp);
+
+ // Update the Full Unwind Plan for this frame if not valid
+ UpdateUnwindPlanForFirstFrameIfInvalid(abi);
+
return true;
unwind_done:
@@ -161,7 +168,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf ("%*sFrame %d did not get a RegisterContext, stopping.",
@@ -175,7 +189,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
// See if the regctx below this on the stack has a fallback unwind plan it can use.
// Subsequent calls to TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk",
@@ -187,7 +208,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk",
@@ -212,7 +240,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
|| abi->CallFrameAddressIsValid(cursor_sp->cfa) == false)
{
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
@@ -232,7 +267,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk",
@@ -244,7 +286,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk",
@@ -263,6 +312,33 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
return cursor_sp;
}
+void
+UnwindLLDB::UpdateUnwindPlanForFirstFrameIfInvalid (ABI *abi)
+{
+ // This function is called for First Frame only.
+ assert (m_frames.size() == 1 && "No. of cursor frames are not 1");
+
+ bool old_m_unwind_complete = m_unwind_complete;
+ CursorSP old_m_candidate_frame = m_candidate_frame;
+
+ // Try to unwind 2 more frames using the Unwinder. It uses Full UnwindPlan
+ // and if Full UnwindPlan fails, then uses FallBack UnwindPlan. Also
+ // update the cfa of Frame 0 (if required).
+ AddOneMoreFrame(abi);
+
+ // Remove all the frames added by above function as the purpose of
+ // using above function was just to check whether Unwinder of Frame 0
+ // works or not.
+ for(uint32_t i=1; i<m_frames.size(); i++)
+ m_frames.pop_back();
+
+ // Restore status after calling AddOneMoreFrame
+ m_unwind_complete = old_m_unwind_complete;
+ m_candidate_frame = old_m_candidate_frame;
+ return;
+}
+
+
bool
UnwindLLDB::AddOneMoreFrame (ABI *abi)
{
@@ -321,9 +397,17 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
m_frames.push_back(new_frame_v2);
m_candidate_frame = GetOneMoreFrame(abi);
if (m_candidate_frame)
+ {
+ // If control reached here then TryFallbackUnwindPlan had succeeded for Cursor::m_frames[m_frames.size() - 2].
+ // It also succeeded to Unwind next 2 frames i.e. m_frames[m_frames.size() - 1] and a frame after that.
+ // For Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was already updated during TryFallbackUnwindPlan
+ // call above. However, cfa field still needs to be updated. Hence updating it here and then returning.
+ if ( !(m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA(m_frames[m_frames.size() - 2]->cfa)))
+ return false;
return true;
+ }
- // The new frame isn't helped in unwinding. Fall back to the original one as the default unwind
+ // The new frame hasn't helped in unwinding. Fall back to the original one as the default unwind
// plan is usually more reliable then the fallback one.
m_frames.pop_back();
m_frames.push_back(new_frame);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
index ce897cd..d3c0707 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -10,8 +10,12 @@
#ifndef lldb_UnwindLLDB_h_
#define lldb_UnwindLLDB_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Symbol/FuncUnwinders.h"
@@ -27,9 +31,8 @@ class UnwindLLDB : public lldb_private::Unwind
{
public:
UnwindLLDB (lldb_private::Thread &thread);
-
- virtual
- ~UnwindLLDB() { }
+
+ ~UnwindLLDB() override = default;
enum RegisterSearchResult
{
@@ -62,23 +65,23 @@ protected:
};
void
- DoClear()
+ DoClear() override
{
m_frames.clear();
m_candidate_frame.reset();
m_unwind_complete = false;
}
- virtual uint32_t
- DoGetFrameCount();
+ uint32_t
+ DoGetFrameCount() override;
bool
- DoGetFrameInfoAtIndex (uint32_t frame_idx,
- lldb::addr_t& cfa,
- lldb::addr_t& start_pc);
+ DoGetFrameInfoAtIndex(uint32_t frame_idx,
+ lldb::addr_t& cfa,
+ lldb::addr_t& start_pc) override;
lldb::RegisterContextSP
- DoCreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+ DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
typedef std::shared_ptr<RegisterContextLLDB> RegisterContextLLDBSP;
@@ -112,7 +115,6 @@ protected:
}
private:
-
struct Cursor
{
lldb::addr_t start_pc; // The start address of the function/symbol for this frame - current pc if unknown
@@ -134,6 +136,15 @@ private:
std::vector<ConstString> m_user_supplied_trap_handler_functions;
+ //-----------------------------------------------------------------
+ // Check if Full UnwindPlan of First frame is valid or not.
+ // If not then try Fallback UnwindPlan of the frame. If Fallback
+ // UnwindPlan succeeds then update the Full UnwindPlan with the
+ // Fallback UnwindPlan.
+ //-----------------------------------------------------------------
+ void
+ UpdateUnwindPlanForFirstFrameIfInvalid (ABI* abi);
+
CursorSP
GetOneMoreFrame (ABI* abi);
@@ -149,6 +160,6 @@ private:
DISALLOW_COPY_AND_ASSIGN (UnwindLLDB);
};
-} // namespace lldb_private
+} // namespace lldb_private
-#endif // lldb_UnwindLLDB_h_
+#endif // lldb_UnwindLLDB_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
index 2695376..f195514 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
@@ -15,7 +15,6 @@
#include <vector>
// Other libraries and framework includes
-
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/Unwind.h"
@@ -24,29 +23,26 @@ class UnwindMacOSXFrameBackchain : public lldb_private::Unwind
{
public:
UnwindMacOSXFrameBackchain (lldb_private::Thread &thread);
-
- virtual
- ~UnwindMacOSXFrameBackchain()
- {
- }
-
+
+ ~UnwindMacOSXFrameBackchain() override = default;
+
protected:
- virtual void
- DoClear()
+ void
+ DoClear() override
{
m_cursors.clear();
}
- virtual uint32_t
- DoGetFrameCount();
+ uint32_t
+ DoGetFrameCount() override;
bool
- DoGetFrameInfoAtIndex (uint32_t frame_idx,
- lldb::addr_t& cfa,
- lldb::addr_t& pc);
+ DoGetFrameInfoAtIndex(uint32_t frame_idx,
+ lldb::addr_t& cfa,
+ lldb::addr_t& pc) override;
lldb::RegisterContextSP
- DoCreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+ DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
friend class RegisterContextMacOSXFrameBackchain;
@@ -71,4 +67,4 @@ private:
DISALLOW_COPY_AND_ASSIGN (UnwindMacOSXFrameBackchain);
};
-#endif // lldb_UnwindMacOSXFrameBackchain_h_
+#endif // lldb_UnwindMacOSXFrameBackchain_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h
index a617f65..4d82c10 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/Utility/lldb-arm-register-enums.h
@@ -74,7 +74,55 @@ namespace lldb_private
fpu_s30_arm,
fpu_s31_arm,
fpu_fpscr_arm,
- k_last_fpr_arm = fpu_fpscr_arm,
+ fpu_d0_arm,
+ fpu_d1_arm,
+ fpu_d2_arm,
+ fpu_d3_arm,
+ fpu_d4_arm,
+ fpu_d5_arm,
+ fpu_d6_arm,
+ fpu_d7_arm,
+ fpu_d8_arm,
+ fpu_d9_arm,
+ fpu_d10_arm,
+ fpu_d11_arm,
+ fpu_d12_arm,
+ fpu_d13_arm,
+ fpu_d14_arm,
+ fpu_d15_arm,
+ fpu_d16_arm,
+ fpu_d17_arm,
+ fpu_d18_arm,
+ fpu_d19_arm,
+ fpu_d20_arm,
+ fpu_d21_arm,
+ fpu_d22_arm,
+ fpu_d23_arm,
+ fpu_d24_arm,
+ fpu_d25_arm,
+ fpu_d26_arm,
+ fpu_d27_arm,
+ fpu_d28_arm,
+ fpu_d29_arm,
+ fpu_d30_arm,
+ fpu_d31_arm,
+ fpu_q0_arm,
+ fpu_q1_arm,
+ fpu_q2_arm,
+ fpu_q3_arm,
+ fpu_q4_arm,
+ fpu_q5_arm,
+ fpu_q6_arm,
+ fpu_q7_arm,
+ fpu_q8_arm,
+ fpu_q9_arm,
+ fpu_q10_arm,
+ fpu_q11_arm,
+ fpu_q12_arm,
+ fpu_q13_arm,
+ fpu_q14_arm,
+ fpu_q15_arm,
+ k_last_fpr_arm = fpu_q15_arm,
exc_exception_arm,
exc_fsr_arm,
exc_far_arm,
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index bf5cad8..5b5d98a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -57,7 +57,7 @@ ProcessElfCore::Terminate()
lldb::ProcessSP
-ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file)
+ProcessElfCore::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file)
{
lldb::ProcessSP process_sp;
if (crash_file)
@@ -75,7 +75,7 @@ ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSp
if (elf_header.Parse(data, &data_offset))
{
if (elf_header.e_type == llvm::ELF::ET_CORE)
- process_sp.reset(new ProcessElfCore (target, listener, *crash_file));
+ process_sp.reset(new ProcessElfCore (target_sp, listener, *crash_file));
}
}
}
@@ -83,12 +83,12 @@ ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSp
}
bool
-ProcessElfCore::CanDebug(Target &target, bool plugin_specified_by_name)
+ProcessElfCore::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name)
{
// For now we are just making sure the file exists for a given module
if (!m_core_module_sp && m_core_file.Exists())
{
- ModuleSpec core_module_spec(m_core_file, target.GetArchitecture());
+ ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture());
Error error (ModuleList::GetSharedModule (core_module_spec, m_core_module_sp,
NULL, NULL, NULL));
if (m_core_module_sp)
@@ -104,9 +104,9 @@ ProcessElfCore::CanDebug(Target &target, bool plugin_specified_by_name)
//----------------------------------------------------------------------
// ProcessElfCore constructor
//----------------------------------------------------------------------
-ProcessElfCore::ProcessElfCore(Target& target, Listener &listener,
+ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp, Listener &listener,
const FileSpec &core_file) :
- Process (target, listener),
+ Process (target_sp, listener),
m_core_module_sp (),
m_core_file (core_file),
m_dyld_plugin_name (),
@@ -233,10 +233,29 @@ ProcessElfCore::DoLoadCore ()
// it to match the core file which is always single arch.
ArchSpec arch (m_core_module_sp->GetArchitecture());
if (arch.IsValid())
- m_target.SetArchitecture(arch);
+ GetTarget().SetArchitecture(arch);
SetUnixSignals(UnixSignals::Create(GetArchitecture()));
+ // Core files are useless without the main executable. See if we can locate the main
+ // executable using data we found in the core file notes.
+ lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
+ if (!exe_module_sp)
+ {
+ // The first entry in the NT_FILE might be our executable
+ if (!m_nt_file_entries.empty())
+ {
+ ModuleSpec exe_module_spec;
+ exe_module_spec.GetArchitecture() = arch;
+ exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path.GetCString(), false);
+ if (exe_module_spec.GetFileSpec())
+ {
+ exe_module_sp = GetTarget().GetSharedModule(exe_module_spec);
+ if (exe_module_sp)
+ GetTarget().SetExecutableModule(exe_module_sp, false);
+ }
+ }
+ }
return error;
}
@@ -258,7 +277,7 @@ ProcessElfCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_t
for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
{
const ThreadData &td = m_thread_data[tid];
- lldb::ThreadSP thread_sp(new ThreadElfCore (*this, tid, td));
+ lldb::ThreadSP thread_sp(new ThreadElfCore (*this, td));
new_thread_list.AddThread (thread_sp);
}
return new_thread_list.GetSize(false) > 0;
@@ -352,8 +371,7 @@ ProcessElfCore::Clear()
m_thread_list.Clear();
m_os = llvm::Triple::UnknownOS;
- static const auto s_default_unix_signals_sp = std::make_shared<UnixSignals>();
- SetUnixSignals(s_default_unix_signals_sp);
+ SetUnixSignals(std::make_shared<UnixSignals>());
}
void
@@ -371,12 +389,11 @@ ProcessElfCore::Initialize()
lldb::addr_t
ProcessElfCore::GetImageInfoAddress()
{
- Target *target = &GetTarget();
- ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress(target);
+ ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();
+ Address addr = obj_file->GetImageInfoAddress(&GetTarget());
if (addr.IsValid())
- return addr.GetLoadAddress(target);
+ return addr.GetLoadAddress(&GetTarget());
return LLDB_INVALID_ADDRESS;
}
@@ -387,7 +404,8 @@ enum {
NT_PRPSINFO,
NT_TASKSTRUCT,
NT_PLATFORM,
- NT_AUXV
+ NT_AUXV,
+ NT_FILE = 0x46494c45
};
namespace FREEBSD {
@@ -429,7 +447,7 @@ ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
offset += 16;
thread_data.signo = data.GetU32(&offset); // pr_cursig
- offset += 4; // pr_pid
+ thread_data.tid = data.GetU32(&offset); // pr_pid
if (lp64)
offset += 4;
@@ -503,6 +521,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
// Store the NOTE information in the current thread
DataExtractor note_data (segment_data, note_start, note_size);
+ note_data.SetAddressByteSize(m_core_module_sp->GetArchitecture().GetAddressByteSize());
if (note.n_name == "FreeBSD")
{
m_os = llvm::Triple::FreeBSD;
@@ -532,7 +551,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
break;
}
}
- else
+ else if (note.n_name == "CORE")
{
switch (note.n_type)
{
@@ -543,6 +562,8 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
header_size = ELFLinuxPrStatus::GetSize(arch);
len = note_data.GetByteSize() - header_size;
thread_data->gpregset = DataExtractor(note_data, header_size, len);
+ // FIXME: Obtain actual tid on Linux
+ thread_data->tid = m_thread_data.size();
break;
case NT_FPREGSET:
thread_data->fpregset = note_data;
@@ -555,6 +576,28 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
case NT_AUXV:
m_auxv = DataExtractor(note_data);
break;
+ case NT_FILE:
+ {
+ m_nt_file_entries.clear();
+ lldb::offset_t offset = 0;
+ const uint64_t count = note_data.GetAddress(&offset);
+ note_data.GetAddress(&offset); // Skip page size
+ for (uint64_t i = 0; i<count; ++i)
+ {
+ NT_FILE_Entry entry;
+ entry.start = note_data.GetAddress(&offset);
+ entry.end = note_data.GetAddress(&offset);
+ entry.file_ofs = note_data.GetAddress(&offset);
+ m_nt_file_entries.push_back(entry);
+ }
+ for (uint64_t i = 0; i<count; ++i)
+ {
+ const char *path = note_data.GetCStr(&offset);
+ if (path && path[0])
+ m_nt_file_entries[i].path.SetCString(path);
+ }
+ }
+ break;
default:
break;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
index 775d9e9..12ce04c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -1,4 +1,4 @@
-//===-- ProcessElfCore.h ---------------------------------------*- C++ -*-===//
+//===-- ProcessElfCore.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,18 +10,20 @@
// 2) The ELF file's PT_NOTE and PT_LOAD segments describes the program's
// address space and thread contexts.
// 3) PT_NOTE segment contains note entries which describes a thread context.
-// 4) PT_LOAD segment describes a valid contigous range of process address
+// 4) PT_LOAD segment describes a valid contiguous range of process address
// space.
//===----------------------------------------------------------------------===//
#ifndef liblldb_ProcessElfCore_h_
#define liblldb_ProcessElfCore_h_
+// C Includes
// C++ Includes
#include <list>
#include <vector>
// Other libraries and framework includes
+// Project includes
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
#include "lldb/Target/Process.h"
@@ -37,7 +39,7 @@ public:
// Constructors and Destructors
//------------------------------------------------------------------
static lldb::ProcessSP
- CreateInstance (lldb_private::Target& target,
+ CreateInstance (lldb::TargetSP target_sp,
lldb_private::Listener &listener,
const lldb_private::FileSpec *crash_file_path);
@@ -56,17 +58,16 @@ public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- ProcessElfCore(lldb_private::Target& target,
- lldb_private::Listener &listener,
- const lldb_private::FileSpec &core_file);
+ ProcessElfCore(lldb::TargetSP target_sp,
+ lldb_private::Listener &listener,
+ const lldb_private::FileSpec &core_file);
- virtual
- ~ProcessElfCore();
+ ~ProcessElfCore() override;
//------------------------------------------------------------------
// Check if a given Process
//------------------------------------------------------------------
- bool CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override;
+ bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override;
//------------------------------------------------------------------
// Creating a new process, or attaching to an existing one
@@ -118,6 +119,14 @@ protected:
lldb_private::ThreadList &new_thread_list) override;
private:
+ struct NT_FILE_Entry
+ {
+ lldb::addr_t start;
+ lldb::addr_t end;
+ lldb::addr_t file_ofs;
+ lldb_private::ConstString path;
+ };
+
//------------------------------------------------------------------
// For ProcessElfCore only
//------------------------------------------------------------------
@@ -143,6 +152,9 @@ private:
// Address ranges found in the core
VMRangeToFileOffset m_core_aranges;
+ // NT_FILE entries found from the NOTE segment
+ std::vector<NT_FILE_Entry> m_nt_file_entries;
+
// Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment
void
ParseThreadContextsFromNoteSegment (const elf::ELFProgramHeader *segment_header,
@@ -157,4 +169,4 @@ private:
AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header);
};
-#endif // liblldb_ProcessElffCore_h_
+#endif // liblldb_ProcessElfCore_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
index f046c112..6778aea 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_arm.h"
using namespace lldb_private;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h
index 73e2ef7..0e74897 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h
@@ -1,15 +1,19 @@
-//===-- RegisterContextCorePOSIX_arm.h -----------------------*- C++ -*-===//
+//===-- RegisterContextCorePOSIX_arm.h --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextCorePOSIX_arm_H_
-#define liblldb_RegisterContextCorePOSIX_arm_H_
+#ifndef liblldb_RegisterContextCorePOSIX_arm_h_
+#define liblldb_RegisterContextCorePOSIX_arm_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/DataBufferHeap.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
@@ -22,39 +26,41 @@ public:
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
- ~RegisterContextCorePOSIX_arm();
+ ~RegisterContextCorePOSIX_arm() override;
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
- HardwareSingleStep(bool enable);
+ HardwareSingleStep(bool enable) override;
protected:
bool
- ReadGPR();
+ ReadGPR() override;
bool
- ReadFPR();
+ ReadFPR() override;
bool
- WriteGPR();
+ WriteGPR() override;
bool
- WriteFPR();
+ WriteFPR() override;
private:
lldb::DataBufferSP m_gpr_buffer;
lldb_private::DataExtractor m_gpr;
};
-#endif // #ifndef liblldb_RegisterContextCorePOSIX_arm_H_
+#endif // liblldb_RegisterContextCorePOSIX_arm_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
index 53c0c83..7cfdd41 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_arm64.h"
using namespace lldb_private;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
index 2e1d6b4..9b05edb 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
@@ -1,15 +1,19 @@
-//===-- RegisterContextCorePOSIX_arm64.h -----------------------*- C++ -*-===//
+//===-- RegisterContextCorePOSIX_arm64.h ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextCorePOSIX_arm64_H_
-#define liblldb_RegisterContextCorePOSIX_arm64_H_
+#ifndef liblldb_RegisterContextCorePOSIX_arm64_h_
+#define liblldb_RegisterContextCorePOSIX_arm64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/DataBufferHeap.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
@@ -22,39 +26,41 @@ public:
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
- ~RegisterContextCorePOSIX_arm64();
+ ~RegisterContextCorePOSIX_arm64() override;
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
- HardwareSingleStep(bool enable);
+ HardwareSingleStep(bool enable) override;
protected:
bool
- ReadGPR();
+ ReadGPR() override;
bool
- ReadFPR();
+ ReadFPR() override;
bool
- WriteGPR();
+ WriteGPR() override;
bool
- WriteFPR();
+ WriteFPR() override;
private:
lldb::DataBufferSP m_gpr_buffer;
lldb_private::DataExtractor m_gpr;
};
-#endif // #ifndef liblldb_RegisterContextCorePOSIX_arm64_H_
+#endif // liblldb_RegisterContextCorePOSIX_arm64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
index f0750a0..9d908e3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_mips64.h"
using namespace lldb_private;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
index ca29d4f..6cbfd50 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
@@ -1,15 +1,19 @@
-//===-- RegisterContextCorePOSIX_mips64.h ----------------------*- C++ -*-===//
+//===-- RegisterContextCorePOSIX_mips64.h -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextCorePOSIX_mips64_H_
-#define liblldb_RegisterContextCorePOSIX_mips64_H_
+#ifndef liblldb_RegisterContextCorePOSIX_mips64_h_
+#define liblldb_RegisterContextCorePOSIX_mips64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/DataBufferHeap.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
@@ -22,39 +26,41 @@ public:
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
- ~RegisterContextCorePOSIX_mips64();
+ ~RegisterContextCorePOSIX_mips64() override;
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
- HardwareSingleStep(bool enable);
+ HardwareSingleStep(bool enable) override;
protected:
bool
- ReadGPR();
+ ReadGPR() override;
bool
- ReadFPR();
+ ReadFPR() override;
bool
- WriteGPR();
+ WriteGPR() override;
bool
- WriteFPR();
+ WriteFPR() override;
private:
lldb::DataBufferSP m_gpr_buffer;
lldb_private::DataExtractor m_gpr;
};
-#endif // #ifndef liblldb_RegisterContextCorePOSIX_mips64_H_
+#endif // liblldb_RegisterContextCorePOSIX_mips64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
index d12df21..9d8c978 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_powerpc.h"
using namespace lldb_private;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
index a359060..0f587fd 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
@@ -5,11 +5,15 @@
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_
-#define liblldb_RegisterContextCorePOSIX_powerpc_H_
+#ifndef liblldb_RegisterContextCorePOSIX_powerpc_h_
+#define liblldb_RegisterContextCorePOSIX_powerpc_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/DataBufferHeap.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
@@ -23,41 +27,43 @@ public:
const lldb_private::DataExtractor &fpregset,
const lldb_private::DataExtractor &vregset);
- ~RegisterContextCorePOSIX_powerpc();
+ ~RegisterContextCorePOSIX_powerpc() override;
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
- HardwareSingleStep(bool enable);
+ HardwareSingleStep(bool enable) override;
protected:
bool
- ReadGPR();
+ ReadGPR() override;
bool
- ReadFPR();
+ ReadFPR() override;
bool
- ReadVMX();
+ ReadVMX() override;
bool
- WriteGPR();
+ WriteGPR() override;
bool
- WriteFPR();
+ WriteFPR() override;
bool
- WriteVMX();
+ WriteVMX() override;
private:
lldb::DataBufferSP m_gpr_buffer;
@@ -68,4 +74,4 @@ private:
lldb_private::DataExtractor m_vec;
};
-#endif // #ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_
+#endif // liblldb_RegisterContextCorePOSIX_powerpc_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
index 412c7ad..926c7af 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_x86_64.h"
using namespace lldb_private;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
index ac0f49c..60f2ad3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
@@ -1,15 +1,19 @@
-//===-- RegisterContextCorePOSIX_x86_64.h ----------------------*- C++ -*-===//
+//===-- RegisterContextCorePOSIX_x86_64.h -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextCorePOSIX_x86_64_H_
-#define liblldb_RegisterContextCorePOSIX_x86_64_H_
+#ifndef liblldb_RegisterContextCorePOSIX_x86_64_h_
+#define liblldb_RegisterContextCorePOSIX_x86_64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
class RegisterContextCorePOSIX_x86_64 :
@@ -21,38 +25,40 @@ public:
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
- ~RegisterContextCorePOSIX_x86_64();
+ ~RegisterContextCorePOSIX_x86_64() override;
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
- HardwareSingleStep(bool enable);
+ HardwareSingleStep(bool enable) override;
protected:
bool
- ReadGPR();
+ ReadGPR() override;
bool
- ReadFPR();
+ ReadFPR() override;
bool
- WriteGPR();
+ WriteGPR() override;
bool
- WriteFPR();
+ WriteFPR() override;
private:
uint8_t *m_gpregset;
};
-#endif // #ifndef liblldb_RegisterContextCorePOSIX_x86_64_H_
+#endif // liblldb_RegisterContextCorePOSIX_x86_64_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index 2abb6ba..9cc7829 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -37,9 +37,8 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// Construct a Thread object with given data
//----------------------------------------------------------------------
-ThreadElfCore::ThreadElfCore (Process &process, tid_t tid,
- const ThreadData &td) :
- Thread(process, tid),
+ThreadElfCore::ThreadElfCore (Process &process, const ThreadData &td) :
+ Thread(process, td.tid),
m_thread_name(td.name),
m_thread_reg_ctx_sp (),
m_signo(td.signo),
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
index 50502c1..d3a42e0 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
@@ -1,4 +1,4 @@
-//===-- ThreadElfCore.h ----------------------------------------*- C++ -*-===//
+//===-- ThreadElfCore.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,8 +10,12 @@
#ifndef liblldb_ThreadElfCore_h_
#define liblldb_ThreadElfCore_h_
+// C Includes
+// C++ Includes
#include <string>
+// Other libraries and framework includes
+// Project includes
#include "lldb/Target/Thread.h"
#include "lldb/Core/DataExtractor.h"
@@ -104,7 +108,6 @@ struct ELFLinuxPrPsInfo
return 0;
}
}
-
};
struct ThreadData
@@ -112,6 +115,7 @@ struct ThreadData
lldb_private::DataExtractor gpregset;
lldb_private::DataExtractor fpregset;
lldb_private::DataExtractor vregset;
+ lldb::tid_t tid;
int signo;
std::string name;
};
@@ -119,23 +123,21 @@ struct ThreadData
class ThreadElfCore : public lldb_private::Thread
{
public:
- ThreadElfCore (lldb_private::Process &process, lldb::tid_t tid,
- const ThreadData &td);
+ ThreadElfCore (lldb_private::Process &process, const ThreadData &td);
- virtual
- ~ThreadElfCore ();
+ ~ThreadElfCore() override;
- virtual void
- RefreshStateAfterStop();
+ void
+ RefreshStateAfterStop() override;
- virtual lldb::RegisterContextSP
- GetRegisterContext ();
+ lldb::RegisterContextSP
+ GetRegisterContext() override;
- virtual lldb::RegisterContextSP
- CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
- virtual void
- ClearStackFrames ();
+ void
+ ClearStackFrames() override;
static bool
ThreadIDIsValid (lldb::tid_t thread)
@@ -143,8 +145,8 @@ public:
return thread != 0;
}
- virtual const char *
- GetName ()
+ const char *
+ GetName() override
{
if (m_thread_name.empty())
return NULL;
@@ -152,7 +154,7 @@ public:
}
void
- SetName (const char *name)
+ SetName(const char *name) override
{
if (name && name[0])
m_thread_name.assign (name);
@@ -173,8 +175,7 @@ protected:
lldb_private::DataExtractor m_fpregset_data;
lldb_private::DataExtractor m_vregset_data;
- virtual bool CalculateStopInfo();
-
+ bool CalculateStopInfo() override;
};
-#endif // liblldb_ThreadElfCore_h_
+#endif // liblldb_ThreadElfCore_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 9c263c8..2ea1f20 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -30,6 +30,7 @@
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "llvm/ADT/SmallString.h"
@@ -574,15 +575,24 @@ GDBRemoteCommunication::DecompressPacket ()
return true;
if (m_bytes[1] != 'C' && m_bytes[1] != 'N')
return true;
- if (m_bytes[pkt_size - 3] != '#')
+
+ size_t hash_mark_idx = m_bytes.find ('#');
+ if (hash_mark_idx == std::string::npos)
+ return true;
+ if (hash_mark_idx + 2 >= m_bytes.size())
return true;
- if (!::isxdigit (m_bytes[pkt_size - 2]) || !::isxdigit (m_bytes[pkt_size - 1]))
+
+ if (!::isxdigit (m_bytes[hash_mark_idx + 1]) || !::isxdigit (m_bytes[hash_mark_idx + 2]))
return true;
- size_t content_length = pkt_size - 5; // not counting '$', 'C' | 'N', '#', & the two hex checksum chars
- size_t content_start = 2; // The first character of the compressed/not-compressed text of the packet
- size_t hash_mark_idx = pkt_size - 3; // The '#' character marking the end of the packet
- size_t checksum_idx = pkt_size - 2; // The first character of the two hex checksum characters
+ size_t content_length = pkt_size - 5; // not counting '$', 'C' | 'N', '#', & the two hex checksum chars
+ size_t content_start = 2; // The first character of the compressed/not-compressed text of the packet
+ size_t checksum_idx = hash_mark_idx + 1; // The first character of the two hex checksum characters
+
+ // Normally size_of_first_packet == m_bytes.size() but m_bytes may contain multiple packets.
+ // size_of_first_packet is the size of the initial packet which we'll replace with the decompressed
+ // version of, leaving the rest of m_bytes unmodified.
+ size_t size_of_first_packet = hash_mark_idx + 3;
// Compressed packets ("$C") start with a base10 number which is the size of the uncompressed payload,
// then a : and then the compressed data. e.g. $C1024:<binary>#00
@@ -604,7 +614,7 @@ GDBRemoteCommunication::DecompressPacket ()
decompressed_bufsize = ::strtoul (bufsize_str.c_str(), NULL, 10);
if (errno != 0 || decompressed_bufsize == ULONG_MAX)
{
- m_bytes.erase (0, pkt_size);
+ m_bytes.erase (0, size_of_first_packet);
return false;
}
}
@@ -633,7 +643,7 @@ GDBRemoteCommunication::DecompressPacket ()
if (!success)
{
SendNack();
- m_bytes.erase (0, pkt_size);
+ m_bytes.erase (0, size_of_first_packet);
return false;
}
else
@@ -677,7 +687,7 @@ GDBRemoteCommunication::DecompressPacket ()
decompressed_buffer = (uint8_t *) malloc (decompressed_bufsize + 1);
if (decompressed_buffer == nullptr)
{
- m_bytes.erase (0, pkt_size);
+ m_bytes.erase (0, size_of_first_packet);
return false;
}
@@ -751,7 +761,7 @@ GDBRemoteCommunication::DecompressPacket ()
{
if (decompressed_buffer)
free (decompressed_buffer);
- m_bytes.erase (0, pkt_size);
+ m_bytes.erase (0, size_of_first_packet);
return false;
}
@@ -773,7 +783,7 @@ GDBRemoteCommunication::DecompressPacket ()
new_packet.push_back ('0');
}
- m_bytes = new_packet;
+ m_bytes.replace (0, size_of_first_packet, new_packet.data(), new_packet.size());
free (decompressed_buffer);
return true;
@@ -927,8 +937,10 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
{
for (size_t i=0; !binary && i<total_length; ++i)
{
- if (isprint(m_bytes[i]) == 0)
+ if (isprint (m_bytes[i]) == 0 && isspace (m_bytes[i]) == 0)
+ {
binary = true;
+ }
}
}
if (binary)
@@ -1100,16 +1112,16 @@ GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg)
}
Error
-GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
- uint16_t in_port,
+GDBRemoteCommunication::StartDebugserverProcess (const char *url,
+ Platform *platform,
ProcessLaunchInfo &launch_info,
- uint16_t &out_port)
+ uint16_t *port,
+ const Args& inferior_args)
{
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
if (log)
- log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16 ", out_port=%" PRIu16, __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port);
+ log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16, __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0));
- out_port = in_port;
Error error;
// If we locate debugserver, keep that located version around
static FileSpec g_debugserver_file_spec;
@@ -1146,11 +1158,20 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
}
else
{
- if (log)
- log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
-
+ debugserver_file_spec = platform->LocateExecutable(DEBUGSERVER_BASENAME);
+ if (debugserver_file_spec)
+ {
+ // Platform::LocateExecutable() wouldn't return a path if it doesn't exist
+ debugserver_exists = true;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
+ }
+ // Don't cache the platform specific GDB server binary as it could change
+ // from platform to platform
g_debugserver_file_spec.Clear();
- debugserver_file_spec.Clear();
}
}
}
@@ -1171,17 +1192,9 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
debugserver_args.AppendArgument("gdbserver");
#endif
- // If a host and port is supplied then use it
- char host_and_port[128];
- if (hostname)
- {
- snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port);
- debugserver_args.AppendArgument(host_and_port);
- }
- else
- {
- host_and_port[0] = '\0';
- }
+ // If a url is supplied then use it
+ if (url)
+ debugserver_args.AppendArgument(url);
// use native registers, not the GDB registers
debugserver_args.AppendArgument("--native-regs");
@@ -1192,30 +1205,41 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
}
llvm::SmallString<PATH_MAX> named_pipe_path;
- Pipe port_pipe;
-
- if (host_and_port[0] && in_port == 0)
+ // socket_pipe is used by debug server to communicate back either
+ // TCP port or domain socket name which it listens on.
+ // The second purpose of the pipe to serve as a synchronization point -
+ // once data is written to the pipe, debug server is up and running.
+ Pipe socket_pipe;
+
+ // port is null when debug server should listen on domain socket -
+ // we're not interested in port value but rather waiting for debug server
+ // to become available.
+ if ((port != nullptr && *port == 0) || port == nullptr)
{
- // Create a temporary file to get the stdout/stderr and redirect the
- // output of the command into this file. We will later read this file
- // if all goes well and fill the data into "command_output_ptr"
-
- // Binding to port zero, we need to figure out what port it ends up
- // using using a named pipe...
- error = port_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path);
- if (error.Success())
+ if (url)
{
+ // Create a temporary file to get the stdout/stderr and redirect the
+ // output of the command into this file. We will later read this file
+ // if all goes well and fill the data into "command_output_ptr"
+
+#if defined(__APPLE__)
+ // Binding to port zero, we need to figure out what port it ends up
+ // using using a named pipe...
+ error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() "
+ "named pipe creation failed: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
+ }
debugserver_args.AppendArgument("--named-pipe");
debugserver_args.AppendArgument(named_pipe_path.c_str());
- }
- else
- {
- if (log)
- log->Printf("GDBRemoteCommunication::%s() "
- "named pipe creation failed: %s",
- __FUNCTION__, error.AsCString());
- // let's try an unnamed pipe
- error = port_pipe.CreateNew(true);
+#else
+ // Binding to port zero, we need to figure out what port it ends up
+ // using using an unnamed pipe...
+ error = socket_pipe.CreateNew(true);
if (error.Fail())
{
if (log)
@@ -1224,42 +1248,43 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
__FUNCTION__, error.AsCString());
return error;
}
- int write_fd = port_pipe.GetWriteFileDescriptor();
+ int write_fd = socket_pipe.GetWriteFileDescriptor();
debugserver_args.AppendArgument("--pipe");
debugserver_args.AppendArgument(std::to_string(write_fd).c_str());
- launch_info.AppendCloseFileAction(port_pipe.GetReadFileDescriptor());
- }
- }
- else
- {
- // No host and port given, so lets listen on our end and make the debugserver
- // connect to us..
- error = StartListenThread ("127.0.0.1", 0);
- if (error.Fail())
- {
- if (log)
- log->Printf ("GDBRemoteCommunication::%s() unable to start listen thread: %s", __FUNCTION__, error.AsCString());
- return error;
- }
-
- ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
- // Wait for 10 seconds to resolve the bound port
- out_port = connection->GetListeningPort(10);
- if (out_port > 0)
- {
- char port_cstr[32];
- snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port);
- // Send the host and port down that debugserver and specify an option
- // so that it connects back to the port we are listening to in this process
- debugserver_args.AppendArgument("--reverse-connect");
- debugserver_args.AppendArgument(port_cstr);
+ launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor());
+#endif
}
else
{
- error.SetErrorString ("failed to bind to port 0 on 127.0.0.1");
- if (log)
- log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString());
- return error;
+ // No host and port given, so lets listen on our end and make the debugserver
+ // connect to us..
+ error = StartListenThread ("127.0.0.1", 0);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s() unable to start listen thread: %s", __FUNCTION__, error.AsCString());
+ return error;
+ }
+
+ ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
+ // Wait for 10 seconds to resolve the bound port
+ *port = connection->GetListeningPort(10);
+ if (*port > 0)
+ {
+ char port_cstr[32];
+ snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", *port);
+ // Send the host and port down that debugserver and specify an option
+ // so that it connects back to the port we are listening to in this process
+ debugserver_args.AppendArgument("--reverse-connect");
+ debugserver_args.AppendArgument(port_cstr);
+ }
+ else
+ {
+ error.SetErrorString ("failed to bind to port 0 on 127.0.0.1");
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString());
+ return error;
+ }
}
}
@@ -1304,6 +1329,20 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
}
} while (has_env_var);
+ if (inferior_args.GetArgumentCount() > 0)
+ {
+ debugserver_args.AppendArgument ("--");
+ debugserver_args.AppendArguments (inferior_args);
+ }
+
+ // Copy the current environment to the gdbserver/debugserver instance
+ StringList env;
+ if (Host::GetEnvironment(env))
+ {
+ for (size_t i = 0; i < env.GetSize(); ++i)
+ launch_info.GetEnvironmentEntries().AppendArgument(env[i].c_str());
+ }
+
// Close STDIN, STDOUT and STDERR.
launch_info.AppendCloseFileAction (STDIN_FILENO);
launch_info.AppendCloseFileAction (STDOUT_FILENO);
@@ -1316,11 +1355,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
error = Host::LaunchProcess(launch_info);
- if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
+ if (error.Success() &&
+ launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
{
if (named_pipe_path.size() > 0)
{
- error = port_pipe.OpenAsReader(named_pipe_path, false);
+ error = socket_pipe.OpenAsReader(named_pipe_path, false);
if (error.Fail())
if (log)
log->Printf("GDBRemoteCommunication::%s() "
@@ -1328,24 +1368,24 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
__FUNCTION__, named_pipe_path.c_str(), error.AsCString());
}
- if (port_pipe.CanWrite())
- port_pipe.CloseWriteFileDescriptor();
- if (port_pipe.CanRead())
+ if (socket_pipe.CanWrite())
+ socket_pipe.CloseWriteFileDescriptor();
+ if (socket_pipe.CanRead())
{
- char port_cstr[256];
+ char port_cstr[PATH_MAX] = {0};
port_cstr[0] = '\0';
size_t num_bytes = sizeof(port_cstr);
// Read port from pipe with 10 second timeout.
- error = port_pipe.ReadWithTimeout(port_cstr, num_bytes,
+ error = socket_pipe.ReadWithTimeout(port_cstr, num_bytes,
std::chrono::seconds{10}, num_bytes);
- if (error.Success())
+ if (error.Success() && (port != nullptr))
{
assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
- out_port = StringConvert::ToUInt32(port_cstr, 0);
+ *port = StringConvert::ToUInt32(port_cstr, 0);
if (log)
log->Printf("GDBRemoteCommunication::%s() "
- "debugserver listens %u port",
- __FUNCTION__, out_port);
+ "debugserver listens %u port",
+ __FUNCTION__, *port);
}
else
{
@@ -1355,12 +1395,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
__FUNCTION__, named_pipe_path.c_str(), error.AsCString());
}
- port_pipe.Close();
+ socket_pipe.Close();
}
if (named_pipe_path.size() > 0)
{
- const auto err = port_pipe.Delete(named_pipe_path);
+ const auto err = socket_pipe.Delete(named_pipe_path);
if (err.Fail())
{
if (log)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 7379bb3..2a01bce 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -12,9 +12,9 @@
// C Includes
// C++ Includes
-#include <list>
#include <string>
#include <queue>
+#include <vector>
// Other libraries and framework includes
// Project includes
@@ -25,6 +25,7 @@
#include "lldb/Host/Mutex.h"
#include "lldb/Host/Predicate.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Interpreter/Args.h"
#include "Utility/StringExtractorGDBRemote.h"
@@ -94,14 +95,10 @@ public:
uint32_t m_saved_timeout;
};
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
GDBRemoteCommunication(const char *comm_name,
const char *listener_name);
- virtual
- ~GDBRemoteCommunication();
+ ~GDBRemoteCommunication() override;
PacketResult
GetAck ();
@@ -117,12 +114,13 @@ public:
size_t payload_length);
bool
- GetSequenceMutex (Mutex::Locker& locker, const char *failure_message = NULL);
+ GetSequenceMutex(Mutex::Locker& locker, const char *failure_message = nullptr);
PacketType
CheckForPacket (const uint8_t *src,
size_t src_len,
StringExtractorGDBRemote &packet);
+
bool
IsRunning() const
{
@@ -162,21 +160,22 @@ public:
{
return m_packet_timeout * TimeValue::MicroSecPerSec;
}
+
//------------------------------------------------------------------
// Start a debugserver instance on the current host using the
// supplied connection URL.
//------------------------------------------------------------------
Error
- StartDebugserverProcess (const char *hostname,
- uint16_t in_port, // If set to zero, then out_port will contain the bound port on exit
- ProcessLaunchInfo &launch_info,
- uint16_t &out_port);
+ StartDebugserverProcess(const char *url,
+ Platform *platform, // If non nullptr, then check with the platform for the GDB server binary if it can't be located
+ ProcessLaunchInfo &launch_info,
+ uint16_t *port,
+ const Args& inferior_args = Args());
void
DumpHistory(Stream &strm);
protected:
-
class History
{
public:
@@ -223,6 +222,7 @@ protected:
AddPacket (char packet_char,
PacketType type,
uint32_t bytes_transmitted);
+
void
AddPacket (const std::string &src,
uint32_t src_len,
@@ -241,7 +241,7 @@ protected:
return m_dumped_to_log;
}
-protected:
+ protected:
uint32_t
GetFirstSavedPacketIndex () const
{
@@ -275,13 +275,30 @@ protected:
return i % m_packets.size();
}
-
std::vector<Entry> m_packets;
uint32_t m_curr_idx;
uint32_t m_total_packet_count;
mutable bool m_dumped_to_log;
};
+ uint32_t m_packet_timeout;
+ uint32_t m_echo_number;
+ LazyBool m_supports_qEcho;
+#ifdef ENABLE_MUTEX_ERROR_CHECKING
+ TrackingMutex m_sequence_mutex;
+#else
+ Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time
+#endif
+ Predicate<bool> m_public_is_running;
+ Predicate<bool> m_private_is_running;
+ History m_history;
+ bool m_send_acks;
+ bool m_is_platform; // Set to true if this class represents a platform,
+ // false if this class represents a debug session for
+ // a single process
+
+ CompressionType m_compression_type;
+
PacketResult
SendPacket (const char *payload,
size_t payload_length);
@@ -321,27 +338,6 @@ protected:
bool
DecompressPacket ();
- //------------------------------------------------------------------
- // Classes that inherit from GDBRemoteCommunication can see and modify these
- //------------------------------------------------------------------
- uint32_t m_packet_timeout;
- uint32_t m_echo_number;
- LazyBool m_supports_qEcho;
-#ifdef ENABLE_MUTEX_ERROR_CHECKING
- TrackingMutex m_sequence_mutex;
-#else
- Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time
-#endif
- Predicate<bool> m_public_is_running;
- Predicate<bool> m_private_is_running;
- History m_history;
- bool m_send_acks;
- bool m_is_platform; // Set to true if this class represents a platform,
- // false if this class represents a debug session for
- // a single process
-
- CompressionType m_compression_type;
-
Error
StartListenThread (const char *hostname = "127.0.0.1", uint16_t port = 0);
@@ -361,10 +357,12 @@ protected:
// This method is defined as part of communication.h
// when the read thread gets any bytes it will pass them on to this function
- virtual void AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, lldb::ConnectionStatus status);
+ void AppendBytesToCache(const uint8_t * bytes,
+ size_t len,
+ bool broadcast,
+ lldb::ConnectionStatus status) override;
private:
-
std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue
lldb_private::Mutex m_packet_queue_mutex; // Mutex for accessing queue
Condition m_condition_queue_not_empty; // Condition variable to wait for packets
@@ -372,13 +370,10 @@ private:
HostThread m_listen_thread;
std::string m_listen_url;
- //------------------------------------------------------------------
- // For GDBRemoteCommunication only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunication);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_GDBRemoteCommunication_h_
+#endif // liblldb_GDBRemoteCommunication_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index b8c67c5..c0ea9cc 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -101,6 +101,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() :
m_supports_QEnvironment (true),
m_supports_QEnvironmentHexEncoded (true),
m_supports_qSymbol (true),
+ m_qSymbol_requests_done (false),
+ m_supports_qModuleInfo (true),
m_supports_jThreadsInfo (true),
m_curr_pid (LLDB_INVALID_PROCESS_ID),
m_curr_tid (LLDB_INVALID_THREAD_ID),
@@ -376,6 +378,8 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings (bool did_exec)
m_supports_QEnvironment = true;
m_supports_QEnvironmentHexEncoded = true;
m_supports_qSymbol = true;
+ m_qSymbol_requests_done = false;
+ m_supports_qModuleInfo = true;
m_host_arch.Clear();
m_os_version_major = UINT32_MAX;
m_os_version_minor = UINT32_MAX;
@@ -619,7 +623,6 @@ GDBRemoteCommunicationClient::GetThreadsInfo()
if (m_supports_jThreadsInfo)
{
StringExtractorGDBRemote response;
- m_supports_jThreadExtendedInfo = eLazyBoolNo;
if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == PacketResult::Success)
{
if (response.IsUnsupportedResponse())
@@ -782,7 +785,7 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
// In order to stop async notifications from being processed in the middle of the
- // send/recieve sequence Hijack the broadcast. Then rebroadcast any events when we are done.
+ // send/receive sequence Hijack the broadcast. Then rebroadcast any events when we are done.
static Listener hijack_listener("lldb.NotifyHijacker");
HijackBroadcaster(&hijack_listener, eBroadcastBitGdbReadThreadGotNotify);
@@ -878,10 +881,10 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
}
}
- // Remove our Hijacking listner from the broadcast.
+ // Remove our Hijacking listener from the broadcast.
RestoreBroadcaster();
- // If a notification event occured, rebroadcast since it can now be processed safely.
+ // If a notification event occurred, rebroadcast since it can now be processed safely.
EventSP event_sp;
if (hijack_listener.GetNextEvent(event_sp))
BroadcastEvent(event_sp);
@@ -1050,7 +1053,6 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
Mutex::Locker locker(m_sequence_mutex);
StateType state = eStateRunning;
- BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
m_public_is_running.SetValue (true, eBroadcastNever);
// Set the starting continue packet into "continue_packet". This packet
// may change if we are interrupted and we continue after an async packet...
@@ -1060,6 +1062,7 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
const auto sigint_signo = process->GetUnixSignals()->GetSignalNumberFromName("SIGINT");
bool got_async_packet = false;
+ bool broadcast_sent = false;
while (state == eStateRunning)
{
@@ -1072,6 +1075,12 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
else
m_interrupt_sent = false;
+ if (! broadcast_sent)
+ {
+ BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
+ broadcast_sent = true;
+ }
+
m_private_is_running.SetValue (true, eBroadcastAlways);
}
@@ -1133,10 +1142,10 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
continue_after_async = false;
// We didn't get a SIGINT or SIGSTOP, so try for a
- // very brief time (1 ms) to get another stop reply
+ // very brief time (0.1s) to get another stop reply
// packet to make sure it doesn't get in the way
StringExtractorGDBRemote extra_stop_reply_packet;
- uint32_t timeout_usec = 1000;
+ uint32_t timeout_usec = 100000;
if (ReadPacket (extra_stop_reply_packet, timeout_usec, false) == PacketResult::Success)
{
switch (extra_stop_reply_packet.GetChar())
@@ -1262,9 +1271,13 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
got_async_packet = true;
std::string inferior_stdout;
inferior_stdout.reserve(response.GetBytesLeft () / 2);
- char ch;
- while ((ch = response.GetHexU8()) != '\0')
- inferior_stdout.append(1, ch);
+
+ uint8_t ch;
+ while (response.GetHexU8Ex(ch))
+ {
+ if (ch != 0)
+ inferior_stdout.append(1, (char)ch);
+ }
process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
}
break;
@@ -1574,6 +1587,8 @@ GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_valu
{
case '$':
case '#':
+ case '*':
+ case '}':
send_hex_encoding = true;
break;
default:
@@ -2308,7 +2323,8 @@ GDBRemoteCommunicationClient::Detach (bool keep_stopped)
const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success
+ && response.IsOKResponse())
{
m_supports_detach_stay_stopped = eLazyBoolYes;
}
@@ -2326,7 +2342,7 @@ GDBRemoteCommunicationClient::Detach (bool keep_stopped)
else
{
StringExtractorGDBRemote response;
- PacketResult packet_result = SendPacketAndWaitForResponse ("D1", 1, response, false);
+ PacketResult packet_result = SendPacketAndWaitForResponse ("D1", 2, response, false);
if (packet_result != PacketResult::Success)
error.SetErrorString ("Sending extended disconnect packet failed.");
}
@@ -3311,10 +3327,16 @@ GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t
return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success;
}
-uint16_t
-GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname)
+bool
+GDBRemoteCommunicationClient::LaunchGDBServer (const char *remote_accept_hostname,
+ lldb::pid_t &pid,
+ uint16_t &port,
+ std::string &socket_name)
{
pid = LLDB_INVALID_PROCESS_ID;
+ port = 0;
+ socket_name.clear();
+
StringExtractorGDBRemote response;
StreamString stream;
stream.PutCString("qLaunchGDBServer;");
@@ -3339,22 +3361,67 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const
// give the process a few seconds to startup
GDBRemoteCommunication::ScopedTimeout timeout (*this, 10);
-
+
if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
std::string name;
std::string value;
- uint16_t port = 0;
+ StringExtractor extractor;
while (response.GetNameColonValue(name, value))
{
if (name.compare("port") == 0)
port = StringConvert::ToUInt32(value.c_str(), 0, 0);
else if (name.compare("pid") == 0)
pid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
+ else if (name.compare("socket_name") == 0)
+ {
+ extractor.GetStringRef().swap(value);
+ extractor.SetFilePos(0);
+ extractor.GetHexByteString(value);
+
+ socket_name = value;
+ }
}
- return port;
+ return true;
}
- return 0;
+ return false;
+}
+
+size_t
+GDBRemoteCommunicationClient::QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls)
+{
+ connection_urls.clear();
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) != PacketResult::Success)
+ return 0;
+
+ StructuredData::ObjectSP data = StructuredData::ParseJSON(response.GetStringRef());
+ if (!data)
+ return 0;
+
+ StructuredData::Array* array = data->GetAsArray();
+ if (!array)
+ return 0;
+
+ for (size_t i = 0, count = array->GetSize(); i < count; ++i)
+ {
+ StructuredData::Dictionary* element = nullptr;
+ if (!array->GetItemAtIndexAsDictionary(i, element))
+ continue;
+
+ uint16_t port = 0;
+ if (StructuredData::ObjectSP port_osp = element->GetValueForKey(llvm::StringRef("port")))
+ port = port_osp->GetIntegerValue(0);
+
+ std::string socket_name;
+ if (StructuredData::ObjectSP socket_name_osp = element->GetValueForKey(llvm::StringRef("socket_name")))
+ socket_name = socket_name_osp->GetStringValue();
+
+ if (port != 0 || !socket_name.empty())
+ connection_urls.emplace_back(port, socket_name);
+ }
+ return connection_urls.size();
}
bool
@@ -3395,6 +3462,17 @@ GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)
m_curr_tid = tid;
return true;
}
+
+ /*
+ * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hg packet.
+ * The reply from '?' packet could be as simple as 'S05'. There is no packet which can
+ * give us pid and/or tid. Assume pid=tid=1 in such cases.
+ */
+ if (response.IsUnsupportedResponse() && IsConnected())
+ {
+ m_curr_tid = 1;
+ return true;
+ }
}
return false;
}
@@ -3421,6 +3499,17 @@ GDBRemoteCommunicationClient::SetCurrentThreadForRun (uint64_t tid)
m_curr_tid_run = tid;
return true;
}
+
+ /*
+ * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hc packet.
+ * The reply from '?' packet could be as simple as 'S05'. There is no packet which can
+ * give us pid and/or tid. Assume pid=tid=1 in such cases.
+ */
+ if (response.IsUnsupportedResponse() && IsConnected())
+ {
+ m_curr_tid_run = 1;
+ return true;
+ }
}
return false;
}
@@ -3546,6 +3635,17 @@ GDBRemoteCommunicationClient::GetCurrentThreadIDs (std::vector<lldb::tid_t> &thr
} while (ch == ','); // Make sure we got a comma separator
}
}
+
+ /*
+ * Connected bare-iron target (like YAMON gdb-stub) may not have support for
+ * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet could
+ * be as simple as 'S05'. There is no packet which can give us pid and/or tid.
+ * Assume pid=tid=1 in such cases.
+ */
+ if (response.IsUnsupportedResponse() && thread_ids.size() == 0 && IsConnected())
+ {
+ thread_ids.push_back (1);
+ }
}
else
{
@@ -4188,6 +4288,9 @@ GDBRemoteCommunicationClient::GetModuleInfo (const FileSpec& module_file_spec,
const lldb_private::ArchSpec& arch_spec,
ModuleSpec &module_spec)
{
+ if (!m_supports_qModuleInfo)
+ return false;
+
std::string module_path = module_file_spec.GetPath (false);
if (module_path.empty ())
return false;
@@ -4203,9 +4306,15 @@ GDBRemoteCommunicationClient::GetModuleInfo (const FileSpec& module_file_spec,
if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) != PacketResult::Success)
return false;
- if (response.IsErrorResponse () || response.IsUnsupportedResponse ())
+ if (response.IsErrorResponse ())
return false;
+ if (response.IsUnsupportedResponse ())
+ {
+ m_supports_qModuleInfo = false;
+ return false;
+ }
+
std::string name;
std::string value;
bool success;
@@ -4336,111 +4445,152 @@ GDBRemoteCommunicationClient::ReadExtFeature (const lldb_private::ConstString ob
// qSymbol:<sym_name> The target requests the value of symbol sym_name (hex encoded).
// LLDB may provide the value by sending another qSymbol packet
// in the form of"qSymbol:<sym_value>:<sym_name>".
+//
+// Three examples:
+//
+// lldb sends: qSymbol::
+// lldb receives: OK
+// Remote gdb stub does not need to know the addresses of any symbols, lldb does not
+// need to ask again in this session.
+//
+// lldb sends: qSymbol::
+// lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
+// lldb sends: qSymbol::64697370617463685f71756575655f6f666673657473
+// lldb receives: OK
+// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb does not know
+// the address at this time. lldb needs to send qSymbol:: again when it has more
+// solibs loaded.
+//
+// lldb sends: qSymbol::
+// lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
+// lldb sends: qSymbol:2bc97554:64697370617463685f71756575655f6f666673657473
+// lldb receives: OK
+// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb says that it
+// is at address 0x2bc97554. Remote gdb stub sends 'OK' indicating that it does not
+// need any more symbols. lldb does not need to ask again in this session.
void
GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process)
{
- if (m_supports_qSymbol)
+ // Set to true once we've resolved a symbol to an address for the remote stub.
+ // If we get an 'OK' response after this, the remote stub doesn't need any more
+ // symbols and we can stop asking.
+ bool symbol_response_provided = false;
+
+ // Is this the inital qSymbol:: packet?
+ bool first_qsymbol_query = true;
+
+ if (m_supports_qSymbol && m_qSymbol_requests_done == false)
{
Mutex::Locker locker;
if (GetSequenceMutex(locker, "GDBRemoteCommunicationClient::ServeSymbolLookups() failed due to not getting the sequence mutex"))
{
StreamString packet;
packet.PutCString ("qSymbol::");
- while (1)
+ StringExtractorGDBRemote response;
+ while (SendPacketAndWaitForResponseNoLock(packet.GetData(), packet.GetSize(), response) == PacketResult::Success)
{
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponseNoLock(packet.GetData(), packet.GetSize(), response) == PacketResult::Success)
+ if (response.IsOKResponse())
{
- if (response.IsOKResponse())
+ if (symbol_response_provided || first_qsymbol_query)
{
- // We are done serving symbols requests
- return;
+ m_qSymbol_requests_done = true;
}
- if (response.IsUnsupportedResponse())
- {
- // qSymbol is not supported by the current GDB server we are connected to
- m_supports_qSymbol = false;
- return;
- }
- else
+ // We are done serving symbols requests
+ return;
+ }
+ first_qsymbol_query = false;
+
+ if (response.IsUnsupportedResponse())
+ {
+ // qSymbol is not supported by the current GDB server we are connected to
+ m_supports_qSymbol = false;
+ return;
+ }
+ else
+ {
+ llvm::StringRef response_str(response.GetStringRef());
+ if (response_str.startswith("qSymbol:"))
{
- llvm::StringRef response_str(response.GetStringRef());
- if (response_str.startswith("qSymbol:"))
+ response.SetFilePos(strlen("qSymbol:"));
+ std::string symbol_name;
+ if (response.GetHexByteString(symbol_name))
{
- response.SetFilePos(strlen("qSymbol:"));
- std::string symbol_name;
- if (response.GetHexByteString(symbol_name))
- {
- if (symbol_name.empty())
- return;
+ if (symbol_name.empty())
+ return;
- addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
- lldb_private::SymbolContextList sc_list;
- if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list))
+ addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
+ lldb_private::SymbolContextList sc_list;
+ if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list))
+ {
+ const size_t num_scs = sc_list.GetSize();
+ for (size_t sc_idx=0; sc_idx<num_scs && symbol_load_addr == LLDB_INVALID_ADDRESS; ++sc_idx)
{
- const size_t num_scs = sc_list.GetSize();
- for (size_t sc_idx=0; sc_idx<num_scs && symbol_load_addr == LLDB_INVALID_ADDRESS; ++sc_idx)
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(sc_idx, sc))
{
- SymbolContext sc;
- if (sc_list.GetContextAtIndex(sc_idx, sc))
+ if (sc.symbol)
{
- if (sc.symbol)
+ switch (sc.symbol->GetType())
{
- switch (sc.symbol->GetType())
- {
- case eSymbolTypeInvalid:
- case eSymbolTypeAbsolute:
- case eSymbolTypeUndefined:
- case eSymbolTypeSourceFile:
- case eSymbolTypeHeaderFile:
- case eSymbolTypeObjectFile:
- case eSymbolTypeCommonBlock:
- case eSymbolTypeBlock:
- case eSymbolTypeLocal:
- case eSymbolTypeParam:
- case eSymbolTypeVariable:
- case eSymbolTypeVariableType:
- case eSymbolTypeLineEntry:
- case eSymbolTypeLineHeader:
- case eSymbolTypeScopeBegin:
- case eSymbolTypeScopeEnd:
- case eSymbolTypeAdditional:
- case eSymbolTypeCompiler:
- case eSymbolTypeInstrumentation:
- case eSymbolTypeTrampoline:
- break;
-
- case eSymbolTypeCode:
- case eSymbolTypeResolver:
- case eSymbolTypeData:
- case eSymbolTypeRuntime:
- case eSymbolTypeException:
- case eSymbolTypeObjCClass:
- case eSymbolTypeObjCMetaClass:
- case eSymbolTypeObjCIVar:
- case eSymbolTypeReExported:
- symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget());
- break;
- }
+ case eSymbolTypeInvalid:
+ case eSymbolTypeAbsolute:
+ case eSymbolTypeUndefined:
+ case eSymbolTypeSourceFile:
+ case eSymbolTypeHeaderFile:
+ case eSymbolTypeObjectFile:
+ case eSymbolTypeCommonBlock:
+ case eSymbolTypeBlock:
+ case eSymbolTypeLocal:
+ case eSymbolTypeParam:
+ case eSymbolTypeVariable:
+ case eSymbolTypeVariableType:
+ case eSymbolTypeLineEntry:
+ case eSymbolTypeLineHeader:
+ case eSymbolTypeScopeBegin:
+ case eSymbolTypeScopeEnd:
+ case eSymbolTypeAdditional:
+ case eSymbolTypeCompiler:
+ case eSymbolTypeInstrumentation:
+ case eSymbolTypeTrampoline:
+ break;
+
+ case eSymbolTypeCode:
+ case eSymbolTypeResolver:
+ case eSymbolTypeData:
+ case eSymbolTypeRuntime:
+ case eSymbolTypeException:
+ case eSymbolTypeObjCClass:
+ case eSymbolTypeObjCMetaClass:
+ case eSymbolTypeObjCIVar:
+ case eSymbolTypeReExported:
+ symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget());
+ break;
}
}
}
}
- // This is the normal path where our symbol lookup was successful and we want
- // to send a packet with the new symbol value and see if another lookup needs to be
- // done.
-
- // Change "packet" to contain the requested symbol value and name
- packet.Clear();
- packet.PutCString("qSymbol:");
- if (symbol_load_addr != LLDB_INVALID_ADDRESS)
- packet.Printf("%" PRIx64, symbol_load_addr);
- packet.PutCString(":");
- packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size());
- continue; // go back to the while loop and send "packet" and wait for another response
}
+ // This is the normal path where our symbol lookup was successful and we want
+ // to send a packet with the new symbol value and see if another lookup needs to be
+ // done.
+
+ // Change "packet" to contain the requested symbol value and name
+ packet.Clear();
+ packet.PutCString("qSymbol:");
+ if (symbol_load_addr != LLDB_INVALID_ADDRESS)
+ {
+ packet.Printf("%" PRIx64, symbol_load_addr);
+ symbol_response_provided = true;
+ }
+ else
+ {
+ symbol_response_provided = false;
+ }
+ packet.PutCString(":");
+ packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size());
+ continue; // go back to the while loop and send "packet" and wait for another response
}
}
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index b08ff06..311b0f3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <map>
+#include <string>
#include <vector>
// Other libraries and framework includes
@@ -28,12 +30,9 @@ namespace process_gdb_remote {
class GDBRemoteCommunicationClient : public GDBRemoteCommunication
{
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
GDBRemoteCommunicationClient();
- ~GDBRemoteCommunicationClient();
+ ~GDBRemoteCommunicationClient() override;
//------------------------------------------------------------------
// After connecting, send the handshake to the server to make sure
@@ -79,6 +78,7 @@ public:
const char *packet_payload,
size_t packet_length,
StringExtractorGDBRemote &response);
+
bool
SendvContPacket (ProcessGDBRemote *process,
const char *payload,
@@ -114,9 +114,15 @@ public:
bool
GetLaunchSuccess (std::string &error_str);
- uint16_t
- LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname);
-
+ bool
+ LaunchGDBServer (const char *remote_accept_hostname,
+ lldb::pid_t &pid,
+ uint16_t &port,
+ std::string &socket_name);
+
+ size_t
+ QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls);
+
bool
KillSpawnedProcess (lldb::pid_t pid);
@@ -161,7 +167,7 @@ public:
SendLaunchArchPacket (const char *arch);
int
- SendLaunchEventDataPacket (const char *data, bool *was_supported = NULL);
+ SendLaunchEventDataPacket(const char *data, bool *was_supported = nullptr);
//------------------------------------------------------------------
/// Sends a "vAttach:PID" where PID is in hex.
@@ -182,7 +188,6 @@ public:
SendAttach (lldb::pid_t pid,
StringExtractorGDBRemote& response);
-
//------------------------------------------------------------------
/// Sends a GDB remote protocol 'I' packet that delivers stdin
/// data to the remote process.
@@ -396,6 +401,7 @@ public:
default: return false;
}
}
+
uint8_t
SendGDBStoppointTypePacket (GDBStoppointType type, // Type of breakpoint or watchpoint
bool insert, // Insert or remove?
@@ -505,11 +511,11 @@ public:
GetFileExists (const FileSpec& file_spec);
Error
- RunShellCommand(const char *command, // Shouldn't be NULL
+ RunShellCommand(const char *command, // Shouldn't be nullptr
const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory
- int *status_ptr, // Pass NULL if you don't want the process exit status
- int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
- std::string *command_output, // Pass NULL if you don't want the command output
+ int *status_ptr, // Pass nullptr if you don't want the process exit status
+ int *signo_ptr, // Pass nullptr if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass nullptr if you don't want the command output
uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
bool
@@ -567,26 +573,6 @@ public:
ServeSymbolLookups(lldb_private::Process *process);
protected:
-
- PacketResult
- SendPacketAndWaitForResponseNoLock (const char *payload,
- size_t payload_length,
- StringExtractorGDBRemote &response);
-
- bool
- GetCurrentProcessInfo (bool allow_lazy_pid = true);
-
- bool
- GetGDBServerVersion();
-
- // Given the list of compression types that the remote debug stub can support,
- // possibly enable compression if we find an encoding we can handle.
- void
- MaybeEnableCompression (std::vector<std::string> supported_compressions);
-
- //------------------------------------------------------------------
- // Classes that inherit from GDBRemoteCommunicationClient can see and modify these
- //------------------------------------------------------------------
LazyBool m_supports_not_sending_acks;
LazyBool m_supports_thread_suffix;
LazyBool m_supports_threads_in_stop_reply;
@@ -633,13 +619,14 @@ protected:
m_supports_QEnvironment:1,
m_supports_QEnvironmentHexEncoded:1,
m_supports_qSymbol:1,
+ m_qSymbol_requests_done:1,
+ m_supports_qModuleInfo:1,
m_supports_jThreadsInfo:1;
lldb::pid_t m_curr_pid;
lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations
lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for continue, step, etc
-
uint32_t m_num_supported_hardware_watchpoints;
// If we need to send a packet while the target is running, the m_async_XXX
@@ -667,18 +654,31 @@ protected:
uint32_t m_default_packet_timeout;
uint64_t m_max_packet_size; // as returned by qSupported
-
+ PacketResult
+ SendPacketAndWaitForResponseNoLock (const char *payload,
+ size_t payload_length,
+ StringExtractorGDBRemote &response);
+
+ bool
+ GetCurrentProcessInfo (bool allow_lazy_pid = true);
+
+ bool
+ GetGDBServerVersion();
+
+ // Given the list of compression types that the remote debug stub can support,
+ // possibly enable compression if we find an encoding we can handle.
+ void
+ MaybeEnableCompression (std::vector<std::string> supported_compressions);
+
bool
DecodeProcessInfoResponse (StringExtractorGDBRemote &response,
ProcessInstanceInfo &process_info);
+
private:
- //------------------------------------------------------------------
- // For GDBRemoteCommunicationClient only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationClient);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_GDBRemoteCommunicationClient_h_
+#endif // liblldb_GDBRemoteCommunicationClient_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 44c0f6a..1d512bf 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -39,8 +39,7 @@ public:
GDBRemoteCommunicationServer(const char *comm_name,
const char *listener_name);
- virtual
- ~GDBRemoteCommunicationServer();
+ ~GDBRemoteCommunicationServer() override;
void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type,
PacketHandler handler);
@@ -73,13 +72,10 @@ protected:
SendOKResponse ();
private:
- //------------------------------------------------------------------
- // For GDBRemoteCommunicationServer only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServer);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_GDBRemoteCommunicationServer_h_
+#endif // liblldb_GDBRemoteCommunicationServer_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 698854e..7f876fb 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -58,8 +58,6 @@ using namespace lldb_private::process_gdb_remote;
//----------------------------------------------------------------------
GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name) :
GDBRemoteCommunicationServer (comm_name, listener_name),
- m_spawned_pids (),
- m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
m_process_launch_info (),
m_process_launch_error (),
m_proc_infos (),
@@ -79,8 +77,6 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(const cha
&GDBRemoteCommunicationServerCommon::Handle_qGroupName);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qHostInfo,
&GDBRemoteCommunicationServerCommon::Handle_qHostInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
- &GDBRemoteCommunicationServerCommon::Handle_qKillSpawnedProcess);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QLaunchArch,
&GDBRemoteCommunicationServerCommon::Handle_QLaunchArch);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess,
@@ -185,14 +181,20 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo (StringExtractorGDBRemote &
else
response.Printf("watchpoint_exceptions_received:after;");
#else
- if (host_arch.GetMachine() == llvm::Triple::mips64 ||
- host_arch.GetMachine() == llvm::Triple::mips64el)
+ if (host_arch.GetMachine() == llvm::Triple::aarch64 ||
+ host_arch.GetMachine() == llvm::Triple::aarch64_be ||
+ host_arch.GetMachine() == llvm::Triple::arm ||
+ host_arch.GetMachine() == llvm::Triple::armeb ||
+ host_arch.GetMachine() == llvm::Triple::mips64 ||
+ host_arch.GetMachine() == llvm::Triple::mips64el ||
+ host_arch.GetMachine() == llvm::Triple::mips ||
+ host_arch.GetMachine() == llvm::Triple::mipsel)
response.Printf("watchpoint_exceptions_received:before;");
else
response.Printf("watchpoint_exceptions_received:after;");
#endif
- switch (lldb::endian::InlHostByteOrder())
+ switch (endian::InlHostByteOrder())
{
case eByteOrderBig: response.PutCString ("endian:big;"); break;
case eByteOrderLittle: response.PutCString ("endian:little;"); break;
@@ -485,94 +487,6 @@ GDBRemoteCommunicationServerCommon::Handle_qSpeedTest (StringExtractorGDBRemote
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
-
- lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
-
- // verify that we know anything about this pid.
- // Scope for locker
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- {
- // not a pid we know about
- return SendErrorResponse (10);
- }
- }
-
- // go ahead and attempt to kill the spawned process
- if (KillSpawnedProcess (pid))
- return SendOKResponse ();
- else
- return SendErrorResponse (11);
-}
-
-bool
-GDBRemoteCommunicationServerCommon::KillSpawnedProcess (lldb::pid_t pid)
-{
- // make sure we know about this process
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return false;
- }
-
- // first try a SIGTERM (standard kill)
- Host::Kill (pid, SIGTERM);
-
- // check if that worked
- for (size_t i=0; i<10; ++i)
- {
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- {
- // it is now killed
- return true;
- }
- }
- usleep (10000);
- }
-
- // check one more time after the final usleep
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return true;
- }
-
- // the launched process still lives. Now try killing it again,
- // this time with an unblockable signal.
- Host::Kill (pid, SIGKILL);
-
- for (size_t i=0; i<10; ++i)
- {
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- {
- // it is now killed
- return true;
- }
- }
- usleep (10000);
- }
-
- // check one more time after the final usleep
- // Scope for locker
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return true;
- }
-
- // no luck - the process still lives
- return false;
-}
-
-GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_vFile_Open (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:open:"));
@@ -1299,6 +1213,7 @@ GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse_DebugServerStyle (
switch (proc_triple.getArch ())
{
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
case llvm::Triple::aarch64:
ostype = "ios";
break;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
index 62b129b..f55b2eb 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
@@ -12,14 +12,14 @@
// C Includes
// C++ Includes
-#include <set>
+#include <string>
// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private-forward.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
-// Project includes
#include "GDBRemoteCommunicationServer.h"
#include "GDBRemoteCommunicationServerCommon.h"
@@ -36,12 +36,9 @@ class GDBRemoteCommunicationServerCommon :
public:
GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name);
- virtual
- ~GDBRemoteCommunicationServerCommon();
+ ~GDBRemoteCommunicationServerCommon() override;
protected:
- std::set<lldb::pid_t> m_spawned_pids;
- Mutex m_spawned_pids_mutex;
ProcessLaunchInfo m_process_launch_info;
Error m_process_launch_error;
ProcessInstanceInfoList m_proc_infos;
@@ -74,9 +71,6 @@ protected:
Handle_qSpeedTest (StringExtractorGDBRemote &packet);
PacketResult
- Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
-
- PacketResult
Handle_vFile_Open (StringExtractorGDBRemote &packet);
PacketResult
@@ -160,9 +154,6 @@ protected:
PacketResult
Handle_QLaunchArch (StringExtractorGDBRemote &packet);
- bool
- KillSpawnedProcess (lldb::pid_t pid);
-
static void
CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info,
StreamString &response);
@@ -213,4 +204,4 @@ protected:
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_GDBRemoteCommunicationServerCommon_h_
+#endif // liblldb_GDBRemoteCommunicationServerCommon_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index c452325..921369c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -43,6 +43,8 @@
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "lldb/Utility/JSON.h"
+#include "lldb/Utility/LLDBAssert.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
@@ -96,20 +98,6 @@ GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
RegisterPacketHandlers();
}
-//----------------------------------------------------------------------
-// Destructor
-//----------------------------------------------------------------------
-GDBRemoteCommunicationServerLLGS::~GDBRemoteCommunicationServerLLGS()
-{
- Mutex::Locker locker (m_debugged_process_mutex);
-
- if (m_debugged_process_sp)
- {
- m_debugged_process_sp->Terminate ();
- m_debugged_process_sp.reset ();
- }
-}
-
void
GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()
{
@@ -126,7 +114,7 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
&GDBRemoteCommunicationServerLLGS::Handle_interrupt);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_m,
- &GDBRemoteCommunicationServerLLGS::Handle_m);
+ &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M,
&GDBRemoteCommunicationServerLLGS::Handle_M);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p,
@@ -161,6 +149,8 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()
&GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo,
&GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jThreadsInfo,
+ &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo,
&GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read,
@@ -175,6 +165,8 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()
&GDBRemoteCommunicationServerLLGS::Handle_vCont);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vCont_actions,
&GDBRemoteCommunicationServerLLGS::Handle_vCont_actions);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_x,
+ &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z,
&GDBRemoteCommunicationServerLLGS::Handle_Z);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z,
@@ -223,6 +215,7 @@ GDBRemoteCommunicationServerLLGS::LaunchProcess ()
error = NativeProcessProtocol::Launch(
m_process_launch_info,
*this,
+ m_mainloop,
m_debugged_process_sp);
}
@@ -274,17 +267,6 @@ GDBRemoteCommunicationServerLLGS::LaunchProcess ()
printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID ());
- // Add to list of spawned processes.
- lldb::pid_t pid;
- if ((pid = m_process_launch_info.GetProcessID ()) != LLDB_INVALID_PROCESS_ID)
- {
- // add to spawned pids
- Mutex::Locker locker (m_spawned_pids_mutex);
- // On an lldb-gdbserver, we would expect there to be only one.
- assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed");
- m_spawned_pids.insert (pid);
- }
-
return error;
}
@@ -297,48 +279,37 @@ GDBRemoteCommunicationServerLLGS::AttachToProcess (lldb::pid_t pid)
if (log)
log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, __FUNCTION__, pid);
- // Scope for mutex locker.
+ // Before we try to attach, make sure we aren't already monitoring something else.
+ if (m_debugged_process_sp && m_debugged_process_sp->GetID() != LLDB_INVALID_PROCESS_ID)
+ return Error("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, m_debugged_process_sp->GetID());
+
+ // Try to attach.
+ error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, m_debugged_process_sp);
+ if (!error.Success ())
{
- // Before we try to attach, make sure we aren't already monitoring something else.
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (!m_spawned_pids.empty ())
- {
- error.SetErrorStringWithFormat ("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, *m_spawned_pids.begin());
- return error;
- }
+ fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ());
+ return error;
+ }
- // Try to attach.
- error = NativeProcessProtocol::Attach(pid, *this, m_debugged_process_sp);
- if (!error.Success ())
- {
- fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ());
+ // Setup stdout/stderr mapping from inferior.
+ auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor ();
+ if (terminal_fd >= 0)
+ {
+ if (log)
+ log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd);
+ error = SetSTDIOFileDescriptor (terminal_fd);
+ if (error.Fail ())
return error;
- }
-
- // Setup stdout/stderr mapping from inferior.
- auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor ();
- if (terminal_fd >= 0)
- {
- if (log)
- log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd);
- error = SetSTDIOFileDescriptor (terminal_fd);
- if (error.Fail ())
- return error;
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd);
- }
-
- printf ("Attached to process %" PRIu64 "...\n", pid);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd);
+ }
- // Add to list of spawned processes.
- assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed");
- m_spawned_pids.insert (pid);
+ printf ("Attached to process %" PRIu64 "...\n", pid);
- return error;
- }
+ return error;
}
void
@@ -455,6 +426,178 @@ WriteRegisterValueInHexFixedWidth (StreamString &response,
}
}
+static JSONObject::SP
+GetRegistersAsJSON(NativeThreadProtocol &thread, bool abridged)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD));
+
+ NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext ();
+ if (! reg_ctx_sp)
+ return nullptr;
+
+ JSONObject::SP register_object_sp = std::make_shared<JSONObject>();
+
+#ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET
+ // Expedite all registers in the first register set (i.e. should be GPRs) that are not contained in other registers.
+ const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0);
+ if (! reg_set_p)
+ return nullptr;
+ for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p)
+ {
+ uint32_t reg_num = *reg_num_p;
+#else
+ // Expedite only a couple of registers until we figure out why sending registers is
+ // expensive.
+ static const uint32_t k_expedited_registers[] = {
+ LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM
+ };
+ static const uint32_t k_abridged_expedited_registers[] = {
+ LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM
+ };
+
+ for (const uint32_t *generic_reg_p = abridged ? k_abridged_expedited_registers : k_expedited_registers;
+ *generic_reg_p != LLDB_INVALID_REGNUM;
+ ++generic_reg_p)
+ {
+ uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, *generic_reg_p);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ continue; // Target does not support the given register.
+#endif
+
+ const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex(reg_num);
+ if (reg_info_p == nullptr)
+ {
+ if (log)
+ log->Printf("%s failed to get register info for register index %" PRIu32,
+ __FUNCTION__, reg_num);
+ continue;
+ }
+
+ if (reg_info_p->value_regs != nullptr)
+ continue; // Only expedite registers that are not contained in other registers.
+
+ RegisterValue reg_value;
+ Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__,
+ reg_info_p->name ? reg_info_p->name : "<unnamed-register>", reg_num,
+ error.AsCString ());
+ continue;
+ }
+
+ StreamString stream;
+ WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, &reg_value);
+
+ register_object_sp->SetObject(std::to_string(reg_num),
+ std::make_shared<JSONString>(stream.GetString()));
+ }
+
+ return register_object_sp;
+}
+
+static const char *
+GetStopReasonString(StopReason stop_reason)
+{
+ switch (stop_reason)
+ {
+ case eStopReasonTrace:
+ return "trace";
+ case eStopReasonBreakpoint:
+ return "breakpoint";
+ case eStopReasonWatchpoint:
+ return "watchpoint";
+ case eStopReasonSignal:
+ return "signal";
+ case eStopReasonException:
+ return "exception";
+ case eStopReasonExec:
+ return "exec";
+ case eStopReasonInstrumentation:
+ case eStopReasonInvalid:
+ case eStopReasonPlanComplete:
+ case eStopReasonThreadExiting:
+ case eStopReasonNone:
+ break; // ignored
+ }
+ return nullptr;
+}
+
+static JSONArray::SP
+GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+
+ JSONArray::SP threads_array_sp = std::make_shared<JSONArray>();
+
+ // Ensure we can get info on the given thread.
+ uint32_t thread_idx = 0;
+ for ( NativeThreadProtocolSP thread_sp;
+ (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr;
+ ++thread_idx)
+ {
+
+ lldb::tid_t tid = thread_sp->GetID();
+
+ // Grab the reason this thread stopped.
+ struct ThreadStopInfo tid_stop_info;
+ std::string description;
+ if (!thread_sp->GetStopReason (tid_stop_info, description))
+ return nullptr;
+
+ const int signum = tid_stop_info.details.signal.signo;
+ if (log)
+ {
+ log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
+ __FUNCTION__,
+ process.GetID (),
+ tid,
+ signum,
+ tid_stop_info.reason,
+ tid_stop_info.details.exception.type);
+ }
+
+ JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>();
+ threads_array_sp->AppendObject(thread_obj_sp);
+
+ if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp, abridged))
+ thread_obj_sp->SetObject("registers", registers_sp);
+
+ thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid));
+ if (signum != 0)
+ thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum));
+
+ const std::string thread_name = thread_sp->GetName ();
+ if (! thread_name.empty())
+ thread_obj_sp->SetObject("name", std::make_shared<JSONString>(thread_name));
+
+ if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason))
+ thread_obj_sp->SetObject("reason", std::make_shared<JSONString>(stop_reason_str));
+
+ if (! description.empty())
+ thread_obj_sp->SetObject("description", std::make_shared<JSONString>(description));
+
+ if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type)
+ {
+ thread_obj_sp->SetObject("metype",
+ std::make_shared<JSONNumber>(tid_stop_info.details.exception.type));
+
+ JSONArray::SP medata_array_sp = std::make_shared<JSONArray>();
+ for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i)
+ {
+ medata_array_sp->AppendObject(std::make_shared<JSONNumber>(
+ tid_stop_info.details.exception.data[i]));
+ }
+ thread_obj_sp->SetObject("medata", medata_array_sp);
+ }
+
+ // TODO: Expedite interesting regions of inferior memory
+ }
+
+ return threads_array_sp;
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)
{
@@ -548,6 +691,31 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)
response.Printf ("%" PRIx64, listed_thread_sp->GetID ());
}
response.PutChar (';');
+
+ // Include JSON info that describes the stop reason for any threads
+ // that actually have stop reasons. We use the new "jstopinfo" key
+ // whose values is hex ascii JSON that contains the thread IDs
+ // thread stop info only for threads that have stop reasons. Only send
+ // this if we have more than one thread otherwise this packet has all
+ // the info it needs.
+ if (thread_index > 0)
+ {
+ const bool threads_with_valid_stop_info_only = true;
+ JSONArray::SP threads_info_sp = GetJSONThreadsInfo(*m_debugged_process_sp,
+ threads_with_valid_stop_info_only);
+ if (threads_info_sp)
+ {
+ response.PutCString("jstopinfo:");
+ StreamString unescaped_response;
+ threads_info_sp->Write(unescaped_response);
+ response.PutCStringAsRawHex8(unescaped_response.GetData());
+ response.PutChar(';');
+ }
+ else if (log)
+ log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a jstopinfo field for pid %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID());
+
+ }
}
//
@@ -595,34 +763,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)
}
}
- const char* reason_str = nullptr;
- switch (tid_stop_info.reason)
- {
- case eStopReasonTrace:
- reason_str = "trace";
- break;
- case eStopReasonBreakpoint:
- reason_str = "breakpoint";
- break;
- case eStopReasonWatchpoint:
- reason_str = "watchpoint";
- break;
- case eStopReasonSignal:
- reason_str = "signal";
- break;
- case eStopReasonException:
- reason_str = "exception";
- break;
- case eStopReasonExec:
- reason_str = "exec";
- break;
- case eStopReasonInstrumentation:
- case eStopReasonInvalid:
- case eStopReasonPlanComplete:
- case eStopReasonThreadExiting:
- case eStopReasonNone:
- break;
- }
+ const char* reason_str = GetStopReasonString(tid_stop_info.reason);
if (reason_str != nullptr)
{
response.Printf ("reason:%s;", reason_str);
@@ -663,43 +804,15 @@ GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited (NativeProcessProto
if (log)
log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
- // Send the exit result, and don't flush output.
- // Note: flushing output here would join the inferior stdio reflection thread, which
- // would gunk up the waitpid monitor thread that is calling this.
- PacketResult result = SendStopReasonForState (StateType::eStateExited, false);
+ PacketResult result = SendStopReasonForState(StateType::eStateExited);
if (result != PacketResult::Success)
{
if (log)
log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to send stop notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID ());
}
- // Remove the process from the list of spawned pids.
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.erase (process->GetID ()) < 1)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to remove PID %" PRIu64 " from the spawned pids list", __FUNCTION__, process->GetID ());
-
- }
- }
-
- // FIXME can't do this yet - since process state propagation is currently
- // synchronous, it is running off the NativeProcessProtocol's innards and
- // will tear down the NPP while it still has code to execute.
-#if 0
- // Clear the NativeProcessProtocol pointer.
- {
- Mutex::Locker locker (m_debugged_process_mutex);
- m_debugged_process_sp.reset();
- }
-#endif
-
// Close the pipe to the inferior terminal i/o if we launched it
- // and set one up. Otherwise, 'k' and its flush of stdio could
- // end up waiting on a thread join that will never end. Consider
- // adding a timeout to the connection thread join call so we
- // can avoid that scenario altogether.
+ // and set one up.
MaybeCloseInferiorTerminalConnection ();
// We are ready to exit the debug monitor.
@@ -725,7 +838,7 @@ GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped (NativeProcessProt
break;
default:
// In all other cases, send the stop reason.
- PacketResult result = SendStopReasonForState (StateType::eStateStopped, false);
+ PacketResult result = SendStopReasonForState(StateType::eStateStopped);
if (result != PacketResult::Success)
{
if (log)
@@ -748,21 +861,30 @@ GDBRemoteCommunicationServerLLGS::ProcessStateChanged (NativeProcessProtocol *pr
StateAsCString (state));
}
- // Make sure we get all of the pending stdout/stderr from the inferior
- // and send it to the lldb host before we send the state change
- // notification
- m_stdio_communication.SynchronizeWithReadThread();
-
switch (state)
{
- case StateType::eStateExited:
- HandleInferiorState_Exited (process);
+ case StateType::eStateRunning:
+ StartSTDIOForwarding();
break;
case StateType::eStateStopped:
+ // Make sure we get all of the pending stdout/stderr from the inferior
+ // and send it to the lldb host before we send the state change
+ // notification
+ SendProcessOutput();
+ // Then stop the forwarding, so that any late output (see llvm.org/pr25652) does not
+ // interfere with our protocol.
+ StopSTDIOForwarding();
HandleInferiorState_Stopped (process);
break;
+ case StateType::eStateExited:
+ // Same as above
+ SendProcessOutput();
+ StopSTDIOForwarding();
+ HandleInferiorState_Exited (process);
+ break;
+
default:
if (log)
{
@@ -796,7 +918,6 @@ GDBRemoteCommunicationServerLLGS::DataAvailableCallback ()
if(log)
log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with client failed, exiting",
__FUNCTION__);
- m_read_handle_up.reset();
m_mainloop.RequestTermination();
return;
}
@@ -817,7 +938,6 @@ GDBRemoteCommunicationServerLLGS::DataAvailableCallback ()
if(log)
log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet failed: %s",
__FUNCTION__, error.AsCString());
- m_read_handle_up.reset();
m_mainloop.RequestTermination();
break;
}
@@ -831,7 +951,7 @@ GDBRemoteCommunicationServerLLGS::InitializeConnection (std::unique_ptr<Connecti
GDBRemoteCommunicationServer::SetConnection(connection.release());
Error error;
- m_read_handle_up = m_mainloop.RegisterReadObject(read_object_sp,
+ m_network_handle_up = m_mainloop.RegisterReadObject(read_object_sp,
[this] (MainLoopBase &) { DataAvailableCallback(); }, error);
return error;
}
@@ -857,7 +977,7 @@ GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor (int fd)
{
Error error;
- // Set up the Read Thread for reading/handling process I/O
+ // Set up the reading/handling of process I/O
std::unique_ptr<ConnectionFileDescriptor> conn_up (new ConnectionFileDescriptor (fd, true));
if (!conn_up)
{
@@ -873,29 +993,73 @@ GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor (int fd)
return error;
}
+ return Error();
+}
+
+void
+GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding()
+{
+ // Don't forward if not connected (e.g. when attaching).
+ if (! m_stdio_communication.IsConnected())
+ return;
+
// llgs local-process debugging may specify PTY paths, which will make these
// file actions non-null
// process launch -e/o will also make these file actions non-null
// nullptr means that the traffic is expected to flow over gdb-remote protocol
- if (
- m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
- m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr
- )
+ if ( m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) &&
+ m_process_launch_info.GetFileActionForFD(STDERR_FILENO))
+ return;
+
+ Error error;
+ lldbassert(! m_stdio_handle_up);
+ m_stdio_handle_up = m_mainloop.RegisterReadObject(
+ m_stdio_communication.GetConnection()->GetReadObject(),
+ [this] (MainLoopBase &) { SendProcessOutput(); }, error);
+
+ if (! m_stdio_handle_up)
{
- // output from the process must be forwarded over gdb-remote
- // create a thread to read the handle and send the data
- m_stdio_communication.SetReadThreadBytesReceivedCallback (STDIOReadThreadBytesReceived, this);
- m_stdio_communication.StartReadThread();
+ // Not much we can do about the failure. Log it and continue without forwarding.
+ if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio forwarding: %s",
+ __FUNCTION__, error.AsCString());
}
+}
- return error;
+void
+GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding()
+{
+ m_stdio_handle_up.reset();
}
void
-GDBRemoteCommunicationServerLLGS::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len)
+GDBRemoteCommunicationServerLLGS::SendProcessOutput()
{
- GDBRemoteCommunicationServerLLGS *server = reinterpret_cast<GDBRemoteCommunicationServerLLGS*> (baton);
- static_cast<void> (server->SendONotification (static_cast<const char *>(src), src_len));
+ char buffer[1024];
+ ConnectionStatus status;
+ Error error;
+ while (true)
+ {
+ size_t bytes_read = m_stdio_communication.Read(buffer, sizeof buffer, 0, status, &error);
+ switch (status)
+ {
+ case eConnectionStatusSuccess:
+ SendONotification(buffer, bytes_read);
+ break;
+ case eConnectionStatusLostConnection:
+ case eConnectionStatusEndOfFile:
+ case eConnectionStatusError:
+ case eConnectionStatusNoConnection:
+ if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio forwarding as communication returned status %d (error: %s)", __FUNCTION__, status, error.AsCString());
+ m_stdio_handle_up.reset();
+ return;
+
+ case eConnectionStatusInterrupted:
+ case eConnectionStatusTimedOut:
+ return;
+ }
+ }
}
GDBRemoteCommunication::PacketResult
@@ -941,49 +1105,24 @@ GDBRemoteCommunicationServerLLGS::Handle_qC (StringExtractorGDBRemote &packet)
return SendPacketNoLock (response.GetData(), response.GetSize());
}
-bool
-GDBRemoteCommunicationServerLLGS::DebuggedProcessReaped (lldb::pid_t pid)
-{
- // reap a process that we were debugging (but not debugserver)
- Mutex::Locker locker (m_spawned_pids_mutex);
- return m_spawned_pids.erase(pid) > 0;
-}
-
-bool
-GDBRemoteCommunicationServerLLGS::ReapDebuggedProcess (void *callback_baton,
- lldb::pid_t pid,
- bool exited,
- int signal, // Zero for no signal
- int status) // Exit value of process if signal is zero
-{
- GDBRemoteCommunicationServerLLGS *server = (GDBRemoteCommunicationServerLLGS *)callback_baton;
- server->DebuggedProcessReaped (pid);
- return true;
-}
-
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_k (StringExtractorGDBRemote &packet)
{
- // shutdown all spawned processes
- std::set<lldb::pid_t> spawned_pids_copy;
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- // copy pids
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- spawned_pids_copy.insert (m_spawned_pids.begin (), m_spawned_pids.end ());
- }
+ StopSTDIOForwarding();
- // nuke the spawned processes
- for (auto it = spawned_pids_copy.begin (); it != spawned_pids_copy.end (); ++it)
+ if (! m_debugged_process_sp)
{
- lldb::pid_t spawned_pid = *it;
- if (!KillSpawnedProcess (spawned_pid))
- {
- fprintf (stderr, "%s: failed to kill spawned pid %" PRIu64 ", ignoring.\n", __FUNCTION__, spawned_pid);
- }
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s No debugged process found.", __FUNCTION__);
+ return PacketResult::Success;
}
- FlushInferiorOutput ();
+ Error error = m_debugged_process_sp->Kill();
+ if (error.Fail() && log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to kill debugged process %" PRIu64 ": %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString());
// No OK response for kill packet.
// return SendOKResponse ();
@@ -1316,11 +1455,11 @@ GDBRemoteCommunicationServerLLGS::Handle_stop_reason (StringExtractorGDBRemote &
if (!m_debugged_process_sp)
return SendErrorResponse (02);
- return SendStopReasonForState (m_debugged_process_sp->GetState (), true);
+ return SendStopReasonForState (m_debugged_process_sp->GetState());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit)
+GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType process_state)
{
Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -1349,8 +1488,6 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType proces
case eStateInvalid:
case eStateUnloaded:
case eStateExited:
- if (flush_on_exit)
- FlushInferiorOutput ();
return SendWResponse(m_debugged_process_sp.get());
default:
@@ -1448,8 +1585,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo (StringExtractorGDBRemote
response.PutChar (';');
}
- if (reg_info->kinds[RegisterKind::eRegisterKindGCC] != LLDB_INVALID_REGNUM)
- response.Printf ("gcc:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindGCC]);
+ if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
+ response.Printf ("ehframe:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);
if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
response.Printf ("dwarf:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
@@ -1856,7 +1993,7 @@ GDBRemoteCommunicationServerLLGS::Handle_interrupt (StringExtractorGDBRemote &pa
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet)
+GDBRemoteCommunicationServerLLGS::Handle_memory_read(StringExtractorGDBRemote &packet)
{
Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -1889,7 +2026,7 @@ GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet)
{
if (log)
log->Printf ("GDBRemoteCommunicationServerLLGS::%s nothing to read: zero-length packet", __FUNCTION__);
- return PacketResult::Success;
+ return SendOKResponse();
}
// Allocate the response buffer.
@@ -1916,8 +2053,16 @@ GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet)
}
StreamGDBRemote response;
- for (size_t i = 0; i < bytes_read; ++i)
- response.PutHex8(buf[i]);
+ packet.SetFilePos(0);
+ char kind = packet.GetChar('?');
+ if (kind == 'x')
+ response.PutEscapedBytes(buf.data(), byte_count);
+ else
+ {
+ assert(kind == 'm');
+ for (size_t i = 0; i < bytes_read; ++i)
+ response.PutHex8(buf[i]);
+ }
return SendPacketNoLock(response.GetData(), response.GetSize());
}
@@ -2108,6 +2253,7 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)
bool want_breakpoint = true;
bool want_hardware = false;
+ uint32_t watch_flags = 0;
const GDBStoppointType stoppoint_type =
GDBStoppointType(packet.GetS32 (eStoppointInvalid));
@@ -2118,10 +2264,13 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)
case eBreakpointHardware:
want_hardware = true; want_breakpoint = true; break;
case eWatchpointWrite:
+ watch_flags = 1;
want_hardware = true; want_breakpoint = false; break;
case eWatchpointRead:
+ watch_flags = 2;
want_hardware = true; want_breakpoint = false; break;
case eWatchpointReadWrite:
+ watch_flags = 3;
want_hardware = true; want_breakpoint = false; break;
case eStoppointInvalid:
return SendIllFormedResponse(packet, "Z packet had invalid software/hardware specifier");
@@ -2161,11 +2310,6 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)
}
else
{
- uint32_t watch_flags =
- stoppoint_type == eWatchpointWrite
- ? 0x1 // Write
- : 0x3; // ReadWrite
-
// Try to set the watchpoint.
const Error error = m_debugged_process_sp->SetWatchpoint (
addr, size, watch_flags, want_hardware);
@@ -2555,7 +2699,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach (StringExtractorGDBRemote &pack
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState (m_debugged_process_sp->GetState (), true);
+ return SendStopReasonForState (m_debugged_process_sp->GetState ());
}
GDBRemoteCommunication::PacketResult
@@ -2563,8 +2707,7 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)
{
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));
- // Scope for mutex locker.
- Mutex::Locker locker (m_spawned_pids_mutex);
+ StopSTDIOForwarding();
// Fail if we don't have a current process.
if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
@@ -2574,14 +2717,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)
return SendErrorResponse (0x15);
}
- if (m_spawned_pids.find(m_debugged_process_sp->GetID ()) == m_spawned_pids.end())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to find PID %" PRIu64 " in spawned pids list",
- __FUNCTION__, m_debugged_process_sp->GetID ());
- return SendErrorResponse (0x1);
- }
-
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
// Consume the ';' after D.
@@ -2603,11 +2738,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)
return SendIllFormedResponse (packet, "Invalid pid");
}
- if (m_stdio_communication.IsConnected ())
- {
- m_stdio_communication.StopReadThread ();
- }
-
const Error error = m_debugged_process_sp->Detach ();
if (error.Fail ())
{
@@ -2617,7 +2747,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)
return SendErrorResponse (0x01);
}
- m_spawned_pids.erase (m_debugged_process_sp->GetID ());
return SendOKResponse ();
}
@@ -2638,6 +2767,38 @@ GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo (StringExtractorGDBRemo
}
GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo (StringExtractorGDBRemote &)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+
+ // Ensure we have a debugged process.
+ if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse (50);
+
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID());
+
+
+ StreamString response;
+ const bool threads_with_valid_stop_info_only = false;
+ JSONArray::SP threads_array_sp = GetJSONThreadsInfo(*m_debugged_process_sp,
+ threads_with_valid_stop_info_only);
+ if (! threads_array_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a packet for pid %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID());
+ return SendErrorResponse(52);
+ }
+
+ threads_array_sp->Write(response);
+ StreamGDBRemote escaped_response;
+ escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
+ return SendPacketNoLock (escaped_response.GetData(), escaped_response.GetSize());
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet)
{
// Fail if we don't have a current process.
@@ -2686,21 +2847,6 @@ GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress (StringExtractorGDBRem
}
void
-GDBRemoteCommunicationServerLLGS::FlushInferiorOutput ()
-{
- // If we're not monitoring an inferior's terminal, ignore this.
- if (!m_stdio_communication.IsConnected())
- return;
-
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s() called", __FUNCTION__);
-
- // FIXME implement a timeout on the join.
- m_stdio_communication.JoinReadThread();
-}
-
-void
GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection ()
{
Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index 29f3fde..f160577 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -42,9 +42,6 @@ public:
//------------------------------------------------------------------
GDBRemoteCommunicationServerLLGS(const lldb::PlatformSP& platform_sp, MainLoop &mainloop);
- virtual
- ~GDBRemoteCommunicationServerLLGS();
-
//------------------------------------------------------------------
/// Specify the program to launch and its arguments.
///
@@ -119,12 +116,15 @@ public:
protected:
lldb::PlatformSP m_platform_sp;
MainLoop &m_mainloop;
- MainLoop::ReadHandleUP m_read_handle_up;
+ MainLoop::ReadHandleUP m_network_handle_up;
lldb::tid_t m_current_tid;
lldb::tid_t m_continue_tid;
Mutex m_debugged_process_mutex;
NativeProcessProtocolSP m_debugged_process_sp;
+
Communication m_stdio_communication;
+ MainLoop::ReadHandleUP m_stdio_handle_up;
+
lldb::StateType m_inferior_prev_state;
lldb::DataBufferSP m_active_auxv_buffer_sp;
Mutex m_saved_registers_mutex;
@@ -142,7 +142,7 @@ protected:
SendStopReplyPacketForThread (lldb::tid_t tid);
PacketResult
- SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit);
+ SendStopReasonForState (lldb::StateType process_state);
PacketResult
Handle_k (StringExtractorGDBRemote &packet);
@@ -201,8 +201,9 @@ protected:
PacketResult
Handle_interrupt (StringExtractorGDBRemote &packet);
+ // Handles $m and $x packets.
PacketResult
- Handle_m (StringExtractorGDBRemote &packet);
+ Handle_memory_read (StringExtractorGDBRemote &packet);
PacketResult
Handle_M (StringExtractorGDBRemote &packet);
@@ -241,6 +242,9 @@ protected:
Handle_qThreadStopInfo (StringExtractorGDBRemote &packet);
PacketResult
+ Handle_jThreadsInfo (StringExtractorGDBRemote &packet);
+
+ PacketResult
Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet);
PacketResult
@@ -261,32 +265,16 @@ protected:
Error
SetSTDIOFileDescriptor (int fd);
- static void
- STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
-
FileSpec
FindModuleFile (const std::string& module_path, const ArchSpec& arch) override;
private:
- bool
- DebuggedProcessReaped (lldb::pid_t pid);
-
- static bool
- ReapDebuggedProcess (void *callback_baton,
- lldb::pid_t pid,
- bool exited,
- int signal,
- int status);
-
void
HandleInferiorState_Exited (NativeProcessProtocol *process);
void
HandleInferiorState_Stopped (NativeProcessProtocol *process);
- void
- FlushInferiorOutput ();
-
NativeThreadProtocolSP
GetThreadFromSuffix (StringExtractorGDBRemote &packet);
@@ -305,6 +293,15 @@ private:
void
DataAvailableCallback ();
+ void
+ SendProcessOutput ();
+
+ void
+ StartSTDIOForwarding();
+
+ void
+ StopSTDIOForwarding();
+
//------------------------------------------------------------------
// For GDBRemoteCommunicationServerLLGS only
//------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 1205049..f88ac12 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -15,19 +15,26 @@
// C++ Includes
#include <cstring>
#include <chrono>
+#include <mutex>
+#include <sstream>
// Other libraries and framework includes
+#include "llvm/Support/FileSystem.h"
+
#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamGDBRemote.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/JSON.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
@@ -40,18 +47,29 @@ using namespace lldb_private::process_gdb_remote;
//----------------------------------------------------------------------
// GDBRemoteCommunicationServerPlatform constructor
//----------------------------------------------------------------------
-GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform() :
+GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol,
+ const char* socket_scheme) :
GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"),
+ m_socket_protocol(socket_protocol),
+ m_socket_scheme(socket_scheme),
+ m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
m_platform_sp (Platform::GetHostPlatform ()),
m_port_map (),
m_port_offset(0)
{
+ m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
+ m_pending_gdb_server.port = 0;
+
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
&GDBRemoteCommunicationServerPlatform::Handle_qC);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
&GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
&GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
+ &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
+ &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
&GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
@@ -78,38 +96,16 @@ GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform()
{
}
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
+Error
+GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& args,
+ std::string hostname,
+ lldb::pid_t& pid,
+ uint16_t& port,
+ std::string& socket_name)
{
-#ifdef _WIN32
- return SendErrorResponse(9);
-#else
- // Spawn a local debugserver as a platform so we can then attach or launch
- // a process...
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__);
-
- // Sleep and wait a bit for debugserver to start to listen...
- ConnectionFileDescriptor file_conn;
- std::string hostname;
- // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
- // with the TMPDIR environment variable
- packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
- std::string name;
- std::string value;
- uint16_t port = UINT16_MAX;
- while (packet.GetNameColonValue(name, value))
- {
- if (name.compare ("host") == 0)
- hostname.swap(value);
- else if (name.compare ("port") == 0)
- port = StringConvert::ToUInt32(value.c_str(), 0, 0);
- }
if (port == UINT16_MAX)
port = GetNextAvailablePort();
-
+
// Spawn a new thread to accept the port that gets bound after
// binding to port 0 (zero).
@@ -120,6 +116,8 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD
ProcessLaunchInfo debugserver_launch_info;
if (hostname.empty())
hostname = "127.0.0.1";
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
@@ -133,53 +131,210 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD
int platform_port;
std::string platform_path;
bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path);
+ UNUSED_IF_ASSERT_DISABLED(ok);
assert(ok);
- Error error = StartDebugserverProcess (
- platform_ip.c_str(),
- port,
- debugserver_launch_info,
- port);
- lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+ std::ostringstream url;
+ uint16_t* port_ptr = &port;
+ if (m_socket_protocol == Socket::ProtocolTcp)
+ url << platform_ip << ":" << port;
+ else
+ {
+ socket_name = GetDomainSocketPath("gdbserver").GetPath();
+ url << socket_name;
+ port_ptr = nullptr;
+ }
+ Error error = StartDebugserverProcess (url.str().c_str(),
+ nullptr,
+ debugserver_launch_info,
+ port_ptr,
+ args);
- if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ pid = debugserver_launch_info.GetProcessID();
+ if (pid != LLDB_INVALID_PROCESS_ID)
{
Mutex::Locker locker (m_spawned_pids_mutex);
- m_spawned_pids.insert(debugserver_pid);
+ m_spawned_pids.insert(pid);
if (port > 0)
- AssociatePortWithProcess(port, debugserver_pid);
+ AssociatePortWithProcess(port, pid);
}
else
{
if (port > 0)
- FreePort (port);
+ FreePort(port);
+ }
+ return error;
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
+{
+#ifdef _WIN32
+ return SendErrorResponse(9);
+#else
+ // Spawn a local debugserver as a platform so we can then attach or launch
+ // a process...
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__);
+
+ ConnectionFileDescriptor file_conn;
+ std::string hostname;
+ packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
+ std::string name;
+ std::string value;
+ uint16_t port = UINT16_MAX;
+ while (packet.GetNameColonValue(name, value))
+ {
+ if (name.compare ("host") == 0)
+ hostname.swap(value);
+ else if (name.compare ("port") == 0)
+ port = StringConvert::ToUInt32(value.c_str(), 0, 0);
}
- if (error.Success())
+ lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ std::string socket_name;
+ Error error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
+ if (error.Fail())
{
if (log)
- log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
+ log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
+ return SendErrorResponse(9);
+ }
- char response[256];
- const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
- assert (response_len < (int)sizeof(response));
- PacketResult packet_result = SendPacketNoLock (response, response_len);
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
- if (packet_result != PacketResult::Success)
+ StreamGDBRemote response;
+ response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
+ if (!socket_name.empty())
+ {
+ response.PutCString("socket_name:");
+ response.PutCStringAsRawHex8(socket_name.c_str());
+ response.PutChar(';');
+ }
+
+ PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize());
+ if (packet_result != PacketResult::Success)
+ {
+ if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ ::kill (debugserver_pid, SIGINT);
+ }
+ return packet_result;
+#endif
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer (StringExtractorGDBRemote &packet)
+{
+ if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse(4);
+
+ JSONObject::SP server_sp = std::make_shared<JSONObject>();
+ server_sp->SetObject("port", std::make_shared<JSONNumber>(m_pending_gdb_server.port));
+ if (!m_pending_gdb_server.socket_name.empty())
+ server_sp->SetObject("socket_name",
+ std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
+
+ JSONArray server_list;
+ server_list.AppendObject(server_sp);
+
+ StreamGDBRemote response;
+ server_list.Write(response);
+
+ StreamGDBRemote escaped_response;
+ escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
+ return SendPacketNoLock(escaped_response.GetData(), escaped_response.GetSize());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+
+ lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
+
+ // verify that we know anything about this pid.
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
{
- if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
- ::kill (debugserver_pid, SIGINT);
+ // not a pid we know about
+ return SendErrorResponse (10);
}
- return packet_result;
}
+
+ // go ahead and attempt to kill the spawned process
+ if (KillSpawnedProcess (pid))
+ return SendOKResponse ();
else
+ return SendErrorResponse (11);
+}
+
+bool
+GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid)
+{
+ // make sure we know about this process
{
- if (log)
- log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return false;
}
- return SendErrorResponse (9);
-#endif
+
+ // first try a SIGTERM (standard kill)
+ Host::Kill (pid, SIGTERM);
+
+ // check if that worked
+ for (size_t i=0; i<10; ++i)
+ {
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ {
+ // it is now killed
+ return true;
+ }
+ }
+ usleep (10000);
+ }
+
+ // check one more time after the final usleep
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+
+ // the launched process still lives. Now try killing it again,
+ // this time with an unblockable signal.
+ Host::Kill (pid, SIGKILL);
+
+ for (size_t i=0; i<10; ++i)
+ {
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ {
+ // it is now killed
+ return true;
+ }
+ }
+ usleep (10000);
+ }
+
+ // check one more time after the final usleep
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+
+ // no luck - the process still lives
+ return false;
}
GDBRemoteCommunication::PacketResult
@@ -402,8 +557,48 @@ GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)
return false;
}
+const FileSpec&
+GDBRemoteCommunicationServerPlatform::GetDomainSocketDir()
+{
+ static FileSpec g_domainsocket_dir;
+ static std::once_flag g_once_flag;
+
+ std::call_once(g_once_flag, []() {
+ const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
+ if (domainsocket_dir_env != nullptr)
+ g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
+ else
+ HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
+ });
+
+ return g_domainsocket_dir;
+}
+
+FileSpec
+GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix)
+{
+ llvm::SmallString<PATH_MAX> socket_path;
+ llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str());
+
+ FileSpec socket_path_spec(GetDomainSocketDir());
+ socket_path_spec.AppendPathComponent(socket_name.c_str());
+
+ llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
+ return FileSpec(socket_path.c_str(), false);
+}
+
void
-GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset)
+GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset)
{
m_port_offset = port_offset;
}
+
+void
+GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(lldb::pid_t pid,
+ uint16_t port,
+ const std::string& socket_name)
+{
+ m_pending_gdb_server.pid = pid;
+ m_pending_gdb_server.port = port;
+ m_pending_gdb_server.socket_name = socket_name;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
index 5c01137..1fe7207 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
@@ -10,7 +10,15 @@
#ifndef liblldb_GDBRemoteCommunicationServerPlatform_h_
#define liblldb_GDBRemoteCommunicationServerPlatform_h_
+// C Includes
+// C++ Includes
+#include <map>
+#include <set>
+
+// Other libraries and framework includes
+// Project includes
#include "GDBRemoteCommunicationServerCommon.h"
+#include "lldb/Host/Socket.h"
namespace lldb_private {
namespace process_gdb_remote {
@@ -21,10 +29,10 @@ class GDBRemoteCommunicationServerPlatform :
public:
typedef std::map<uint16_t, lldb::pid_t> PortMap;
- GDBRemoteCommunicationServerPlatform();
+ GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol,
+ const char* socket_scheme);
- virtual
- ~GDBRemoteCommunicationServerPlatform();
+ ~GDBRemoteCommunicationServerPlatform() override;
Error
LaunchProcess () override;
@@ -58,16 +66,40 @@ public:
void
SetPortOffset (uint16_t port_offset);
+ void
+ SetInferiorArguments (const lldb_private::Args& args);
+
+ Error
+ LaunchGDBServer(const lldb_private::Args& args,
+ std::string hostname,
+ lldb::pid_t& pid,
+ uint16_t& port,
+ std::string& socket_name);
+
+ void
+ SetPendingGdbServer(lldb::pid_t pid, uint16_t port, const std::string& socket_name);
+
protected:
+ const Socket::SocketProtocol m_socket_protocol;
+ const std::string m_socket_scheme;
+ Mutex m_spawned_pids_mutex;
+ std::set<lldb::pid_t> m_spawned_pids;
lldb::PlatformSP m_platform_sp;
PortMap m_port_map;
uint16_t m_port_offset;
+ struct { lldb::pid_t pid; uint16_t port; std::string socket_name; } m_pending_gdb_server;
PacketResult
Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
PacketResult
+ Handle_qQueryGDBServer (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
+
+ PacketResult
Handle_qProcessInfo (StringExtractorGDBRemote &packet);
PacketResult
@@ -84,6 +116,9 @@ protected:
private:
bool
+ KillSpawnedProcess (lldb::pid_t pid);
+
+ bool
DebugserverProcessReaped (lldb::pid_t pid);
static bool
@@ -93,13 +128,16 @@ private:
int signal,
int status);
- //------------------------------------------------------------------
- // For GDBRemoteCommunicationServerPlatform only
- //------------------------------------------------------------------
+ static const FileSpec&
+ GetDomainSocketDir();
+
+ static FileSpec
+ GetDomainSocketPath(const char* prefix);
+
DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServerPlatform);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_GDBRemoteCommunicationServerPlatform_h_
+#endif // liblldb_GDBRemoteCommunicationServerPlatform_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index f5f134e..b0a1eaa 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -17,9 +17,6 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
-#ifndef LLDB_DISABLE_PYTHON
-#include "lldb/Interpreter/PythonDataObjects.h"
-#endif
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Utils.h"
@@ -28,8 +25,8 @@
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"
-#include "Utility/ARM_GCC_Registers.h"
#include "Utility/ARM_DWARF_Registers.h"
+#include "Utility/ARM_ehframe_Registers.h"
using namespace lldb;
using namespace lldb_private;
@@ -150,6 +147,52 @@ GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor
return success;
}
+bool
+GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, uint64_t new_reg_val)
+{
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+ if (reg_info == NULL)
+ return false;
+
+ // Early in process startup, we can get a thread that has an invalid byte order
+ // because the process hasn't been completely set up yet (see the ctor where the
+ // byte order is setfrom the process). If that's the case, we can't set the
+ // value here.
+ if (m_reg_data.GetByteOrder() == eByteOrderInvalid)
+ {
+ return false;
+ }
+
+ // Invalidate if needed
+ InvalidateIfNeeded (false);
+
+ DataBufferSP buffer_sp (new DataBufferHeap (&new_reg_val, sizeof (new_reg_val)));
+ DataExtractor data (buffer_sp, endian::InlHostByteOrder(), sizeof (void*));
+
+ // If our register context and our register info disagree, which should never happen, don't
+ // overwrite past the end of the buffer.
+ if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
+ return false;
+
+ // Grab a pointer to where we are going to put this register
+ uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
+
+ if (dst == NULL)
+ return false;
+
+
+ if (data.CopyByteOrderedData (0, // src offset
+ reg_info->byte_size, // src length
+ dst, // dst
+ reg_info->byte_size, // dst length
+ m_reg_data.GetByteOrder())) // dst byte order
+ {
+ SetRegisterIsValid (reg, true);
+ return true;
+ }
+ return false;
+}
+
// Helper function for GDBRemoteRegisterContext::ReadRegisterBytes().
bool
GDBRemoteRegisterContext::GetPrimordialRegister(const RegisterInfo *reg_info,
@@ -186,7 +229,8 @@ GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataE
if (!gdb_comm.ReadAllRegisters(m_thread.GetProtocolID(), response))
return false;
if (response.IsNormalResponse())
- if (response.GetHexBytes ((void *)m_reg_data.GetDataStart(), m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
+ if (response.GetHexBytes(const_cast<void *>(reinterpret_cast<const void *>(m_reg_data.GetDataStart())),
+ m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
SetAllRegisterValid (true);
}
else if (reg_info->value_regs)
@@ -275,8 +319,8 @@ GDBRemoteRegisterContext::SetPrimordialRegister(const RegisterInfo *reg_info,
packet.Printf ("P%x=", reg);
packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
reg_info->byte_size,
- lldb::endian::InlHostByteOrder(),
- lldb::endian::InlHostByteOrder());
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
if (gdb_comm.GetThreadSuffixSupported())
packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
@@ -372,8 +416,8 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const RegisterInfo *reg_info, Data
packet.PutChar ('G');
packet.PutBytesAsRawHex8 (m_reg_data.GetDataStart(),
m_reg_data.GetByteSize(),
- lldb::endian::InlHostByteOrder(),
- lldb::endian::InlHostByteOrder());
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
if (thread_suffix_supported)
packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
@@ -772,8 +816,8 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
packet.Printf ("P%x=", reg);
packet.PutBytesAsRawHex8 (restore_src,
reg_byte_size,
- lldb::endian::InlHostByteOrder(),
- lldb::endian::InlHostByteOrder());
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
if (thread_suffix_supported)
packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
@@ -795,8 +839,8 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
packet.Printf ("P%x=", reg);
packet.PutBytesAsRawHex8 (restore_src,
reg_byte_size,
- lldb::endian::InlHostByteOrder(),
- lldb::endian::InlHostByteOrder());
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
if (thread_suffix_supported)
packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
@@ -851,7 +895,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
}
StreamString packet;
packet.Printf ("P%x=", reg_info->kinds[eRegisterKindLLDB]);
- packet.PutBytesAsRawHex8 (data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
+ packet.PutBytesAsRawHex8 (data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size, endian::InlHostByteOrder(), endian::InlHostByteOrder());
if (thread_suffix_supported)
packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
@@ -941,115 +985,115 @@ GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)
};
static RegisterInfo g_register_infos[] = {
-// NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB VALUE REGS INVALIDATE REGS
-// ====== ====== === === ============= ============ =================== =================== ====================== === ==== ========== ===============
- { "r0", "arg1", 4, 0, eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1,0, 0 }, NULL, NULL},
- { "r1", "arg2", 4, 0, eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2,1, 1 }, NULL, NULL},
- { "r2", "arg3", 4, 0, eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3,2, 2 }, NULL, NULL},
- { "r3", "arg4", 4, 0, eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4,3, 3 }, NULL, NULL},
- { "r4", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, 4, 4 }, NULL, NULL},
- { "r5", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, 5, 5 }, NULL, NULL},
- { "r6", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, 6, 6 }, NULL, NULL},
- { "r7", "fp", 4, 0, eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, 7, 7 }, NULL, NULL},
- { "r8", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, 8, 8 }, NULL, NULL},
- { "r9", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, 9, 9 }, NULL, NULL},
- { "r10", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, 10, 10 }, NULL, NULL},
- { "r11", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, 11, 11 }, NULL, NULL},
- { "r12", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, 12, 12 }, NULL, NULL},
- { "sp", "r13", 4, 0, eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, 13, 13 }, NULL, NULL},
- { "lr", "r14", 4, 0, eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, 14, 14 }, NULL, NULL},
- { "pc", "r15", 4, 0, eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, 15, 15 }, NULL, NULL},
- { "f0", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 16, 16 }, NULL, NULL},
- { "f1", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 17, 17 }, NULL, NULL},
- { "f2", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 18, 18 }, NULL, NULL},
- { "f3", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 19, 19 }, NULL, NULL},
- { "f4", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 20, 20 }, NULL, NULL},
- { "f5", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 21, 21 }, NULL, NULL},
- { "f6", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 22, 22 }, NULL, NULL},
- { "f7", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 23, 23 }, NULL, NULL},
- { "fps", NULL, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 24, 24 }, NULL, NULL},
- { "cpsr","flags", 4, 0, eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_INVALID_REGNUM, 25, 25 }, NULL, NULL},
- { "s0", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, 26, 26 }, NULL, NULL},
- { "s1", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, 27, 27 }, NULL, NULL},
- { "s2", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, 28, 28 }, NULL, NULL},
- { "s3", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, 29, 29 }, NULL, NULL},
- { "s4", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, 30, 30 }, NULL, NULL},
- { "s5", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, 31, 31 }, NULL, NULL},
- { "s6", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, 32, 32 }, NULL, NULL},
- { "s7", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, 33, 33 }, NULL, NULL},
- { "s8", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, 34, 34 }, NULL, NULL},
- { "s9", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, 35, 35 }, NULL, NULL},
- { "s10", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, 36, 36 }, NULL, NULL},
- { "s11", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, 37, 37 }, NULL, NULL},
- { "s12", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, 38, 38 }, NULL, NULL},
- { "s13", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, 39, 39 }, NULL, NULL},
- { "s14", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, 40, 40 }, NULL, NULL},
- { "s15", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, 41, 41 }, NULL, NULL},
- { "s16", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, 42, 42 }, NULL, NULL},
- { "s17", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, 43, 43 }, NULL, NULL},
- { "s18", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, 44, 44 }, NULL, NULL},
- { "s19", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, 45, 45 }, NULL, NULL},
- { "s20", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, 46, 46 }, NULL, NULL},
- { "s21", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, 47, 47 }, NULL, NULL},
- { "s22", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, 48, 48 }, NULL, NULL},
- { "s23", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, 49, 49 }, NULL, NULL},
- { "s24", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, 50, 50 }, NULL, NULL},
- { "s25", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, 51, 51 }, NULL, NULL},
- { "s26", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, 52, 52 }, NULL, NULL},
- { "s27", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, 53, 53 }, NULL, NULL},
- { "s28", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, 54, 54 }, NULL, NULL},
- { "s29", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, 55, 55 }, NULL, NULL},
- { "s30", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, 56, 56 }, NULL, NULL},
- { "s31", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, 57, 57 }, NULL, NULL},
- { "fpscr",NULL, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 58, 58 }, NULL, NULL},
- { "d16", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, 59, 59 }, NULL, NULL},
- { "d17", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, 60, 60 }, NULL, NULL},
- { "d18", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, 61, 61 }, NULL, NULL},
- { "d19", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, 62, 62 }, NULL, NULL},
- { "d20", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, 63, 63 }, NULL, NULL},
- { "d21", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, 64, 64 }, NULL, NULL},
- { "d22", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, 65, 65 }, NULL, NULL},
- { "d23", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, 66, 66 }, NULL, NULL},
- { "d24", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, 67, 67 }, NULL, NULL},
- { "d25", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, 68, 68 }, NULL, NULL},
- { "d26", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, 69, 69 }, NULL, NULL},
- { "d27", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, 70, 70 }, NULL, NULL},
- { "d28", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, 71, 71 }, NULL, NULL},
- { "d29", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, 72, 72 }, NULL, NULL},
- { "d30", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, 73, 73 }, NULL, NULL},
- { "d31", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, 74, 74 }, NULL, NULL},
- { "d0", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, 75, 75 }, g_d0_regs, NULL},
- { "d1", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, 76, 76 }, g_d1_regs, NULL},
- { "d2", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, 77, 77 }, g_d2_regs, NULL},
- { "d3", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, 78, 78 }, g_d3_regs, NULL},
- { "d4", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, 79, 79 }, g_d4_regs, NULL},
- { "d5", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, 80, 80 }, g_d5_regs, NULL},
- { "d6", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, 81, 81 }, g_d6_regs, NULL},
- { "d7", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, 82, 82 }, g_d7_regs, NULL},
- { "d8", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, 83, 83 }, g_d8_regs, NULL},
- { "d9", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, 84, 84 }, g_d9_regs, NULL},
- { "d10", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, 85, 85 }, g_d10_regs, NULL},
- { "d11", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, 86, 86 }, g_d11_regs, NULL},
- { "d12", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, 87, 87 }, g_d12_regs, NULL},
- { "d13", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, 88, 88 }, g_d13_regs, NULL},
- { "d14", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, 89, 89 }, g_d14_regs, NULL},
- { "d15", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, 90, 90 }, g_d15_regs, NULL},
- { "q0", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0, LLDB_INVALID_REGNUM, 91, 91 }, g_q0_regs, NULL},
- { "q1", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1, LLDB_INVALID_REGNUM, 92, 92 }, g_q1_regs, NULL},
- { "q2", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2, LLDB_INVALID_REGNUM, 93, 93 }, g_q2_regs, NULL},
- { "q3", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3, LLDB_INVALID_REGNUM, 94, 94 }, g_q3_regs, NULL},
- { "q4", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4, LLDB_INVALID_REGNUM, 95, 95 }, g_q4_regs, NULL},
- { "q5", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5, LLDB_INVALID_REGNUM, 96, 96 }, g_q5_regs, NULL},
- { "q6", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6, LLDB_INVALID_REGNUM, 97, 97 }, g_q6_regs, NULL},
- { "q7", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7, LLDB_INVALID_REGNUM, 98, 98 }, g_q7_regs, NULL},
- { "q8", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8, LLDB_INVALID_REGNUM, 99, 99 }, g_q8_regs, NULL},
- { "q9", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9, LLDB_INVALID_REGNUM, 100, 100 }, g_q9_regs, NULL},
- { "q10", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10, LLDB_INVALID_REGNUM, 101, 101 }, g_q10_regs, NULL},
- { "q11", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11, LLDB_INVALID_REGNUM, 102, 102 }, g_q11_regs, NULL},
- { "q12", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12, LLDB_INVALID_REGNUM, 103, 103 }, g_q12_regs, NULL},
- { "q13", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13, LLDB_INVALID_REGNUM, 104, 104 }, g_q13_regs, NULL},
- { "q14", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14, LLDB_INVALID_REGNUM, 105, 105 }, g_q14_regs, NULL},
- { "q15", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15, LLDB_INVALID_REGNUM, 106, 106 }, g_q15_regs, NULL}
+// NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVALIDATE REGS
+// ====== ====== === === ============= ============ =================== =================== ====================== ============= ==== ========== ===============
+ { "r0", "arg1", 4, 0, eEncodingUint, eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1,0, 0 }, NULL, NULL},
+ { "r1", "arg2", 4, 0, eEncodingUint, eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2,1, 1 }, NULL, NULL},
+ { "r2", "arg3", 4, 0, eEncodingUint, eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3,2, 2 }, NULL, NULL},
+ { "r3", "arg4", 4, 0, eEncodingUint, eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4,3, 3 }, NULL, NULL},
+ { "r4", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, 4, 4 }, NULL, NULL},
+ { "r5", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, 5, 5 }, NULL, NULL},
+ { "r6", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, 6, 6 }, NULL, NULL},
+ { "r7", "fp", 4, 0, eEncodingUint, eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, 7, 7 }, NULL, NULL},
+ { "r8", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, 8, 8 }, NULL, NULL},
+ { "r9", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, 9, 9 }, NULL, NULL},
+ { "r10", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, 10, 10 }, NULL, NULL},
+ { "r11", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, 11, 11 }, NULL, NULL},
+ { "r12", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, 12, 12 }, NULL, NULL},
+ { "sp", "r13", 4, 0, eEncodingUint, eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, 13, 13 }, NULL, NULL},
+ { "lr", "r14", 4, 0, eEncodingUint, eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, 14, 14 }, NULL, NULL},
+ { "pc", "r15", 4, 0, eEncodingUint, eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, 15, 15 }, NULL, NULL},
+ { "f0", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 16, 16 }, NULL, NULL},
+ { "f1", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 17, 17 }, NULL, NULL},
+ { "f2", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 18, 18 }, NULL, NULL},
+ { "f3", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 19, 19 }, NULL, NULL},
+ { "f4", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 20, 20 }, NULL, NULL},
+ { "f5", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 21, 21 }, NULL, NULL},
+ { "f6", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 22, 22 }, NULL, NULL},
+ { "f7", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 23, 23 }, NULL, NULL},
+ { "fps", NULL, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 24, 24 }, NULL, NULL},
+ { "cpsr","flags", 4, 0, eEncodingUint, eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_INVALID_REGNUM, 25, 25 }, NULL, NULL},
+ { "s0", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, 26, 26 }, NULL, NULL},
+ { "s1", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, 27, 27 }, NULL, NULL},
+ { "s2", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, 28, 28 }, NULL, NULL},
+ { "s3", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, 29, 29 }, NULL, NULL},
+ { "s4", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, 30, 30 }, NULL, NULL},
+ { "s5", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, 31, 31 }, NULL, NULL},
+ { "s6", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, 32, 32 }, NULL, NULL},
+ { "s7", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, 33, 33 }, NULL, NULL},
+ { "s8", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, 34, 34 }, NULL, NULL},
+ { "s9", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, 35, 35 }, NULL, NULL},
+ { "s10", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, 36, 36 }, NULL, NULL},
+ { "s11", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, 37, 37 }, NULL, NULL},
+ { "s12", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, 38, 38 }, NULL, NULL},
+ { "s13", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, 39, 39 }, NULL, NULL},
+ { "s14", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, 40, 40 }, NULL, NULL},
+ { "s15", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, 41, 41 }, NULL, NULL},
+ { "s16", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, 42, 42 }, NULL, NULL},
+ { "s17", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, 43, 43 }, NULL, NULL},
+ { "s18", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, 44, 44 }, NULL, NULL},
+ { "s19", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, 45, 45 }, NULL, NULL},
+ { "s20", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, 46, 46 }, NULL, NULL},
+ { "s21", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, 47, 47 }, NULL, NULL},
+ { "s22", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, 48, 48 }, NULL, NULL},
+ { "s23", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, 49, 49 }, NULL, NULL},
+ { "s24", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, 50, 50 }, NULL, NULL},
+ { "s25", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, 51, 51 }, NULL, NULL},
+ { "s26", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, 52, 52 }, NULL, NULL},
+ { "s27", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, 53, 53 }, NULL, NULL},
+ { "s28", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, 54, 54 }, NULL, NULL},
+ { "s29", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, 55, 55 }, NULL, NULL},
+ { "s30", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, 56, 56 }, NULL, NULL},
+ { "s31", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, 57, 57 }, NULL, NULL},
+ { "fpscr",NULL, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 58, 58 }, NULL, NULL},
+ { "d16", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, 59, 59 }, NULL, NULL},
+ { "d17", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, 60, 60 }, NULL, NULL},
+ { "d18", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, 61, 61 }, NULL, NULL},
+ { "d19", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, 62, 62 }, NULL, NULL},
+ { "d20", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, 63, 63 }, NULL, NULL},
+ { "d21", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, 64, 64 }, NULL, NULL},
+ { "d22", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, 65, 65 }, NULL, NULL},
+ { "d23", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, 66, 66 }, NULL, NULL},
+ { "d24", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, 67, 67 }, NULL, NULL},
+ { "d25", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, 68, 68 }, NULL, NULL},
+ { "d26", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, 69, 69 }, NULL, NULL},
+ { "d27", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, 70, 70 }, NULL, NULL},
+ { "d28", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, 71, 71 }, NULL, NULL},
+ { "d29", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, 72, 72 }, NULL, NULL},
+ { "d30", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, 73, 73 }, NULL, NULL},
+ { "d31", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, 74, 74 }, NULL, NULL},
+ { "d0", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, 75, 75 }, g_d0_regs, NULL},
+ { "d1", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, 76, 76 }, g_d1_regs, NULL},
+ { "d2", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, 77, 77 }, g_d2_regs, NULL},
+ { "d3", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, 78, 78 }, g_d3_regs, NULL},
+ { "d4", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, 79, 79 }, g_d4_regs, NULL},
+ { "d5", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, 80, 80 }, g_d5_regs, NULL},
+ { "d6", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, 81, 81 }, g_d6_regs, NULL},
+ { "d7", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, 82, 82 }, g_d7_regs, NULL},
+ { "d8", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, 83, 83 }, g_d8_regs, NULL},
+ { "d9", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, 84, 84 }, g_d9_regs, NULL},
+ { "d10", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, 85, 85 }, g_d10_regs, NULL},
+ { "d11", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, 86, 86 }, g_d11_regs, NULL},
+ { "d12", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, 87, 87 }, g_d12_regs, NULL},
+ { "d13", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, 88, 88 }, g_d13_regs, NULL},
+ { "d14", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, 89, 89 }, g_d14_regs, NULL},
+ { "d15", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, 90, 90 }, g_d15_regs, NULL},
+ { "q0", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0, LLDB_INVALID_REGNUM, 91, 91 }, g_q0_regs, NULL},
+ { "q1", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1, LLDB_INVALID_REGNUM, 92, 92 }, g_q1_regs, NULL},
+ { "q2", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2, LLDB_INVALID_REGNUM, 93, 93 }, g_q2_regs, NULL},
+ { "q3", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3, LLDB_INVALID_REGNUM, 94, 94 }, g_q3_regs, NULL},
+ { "q4", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4, LLDB_INVALID_REGNUM, 95, 95 }, g_q4_regs, NULL},
+ { "q5", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5, LLDB_INVALID_REGNUM, 96, 96 }, g_q5_regs, NULL},
+ { "q6", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6, LLDB_INVALID_REGNUM, 97, 97 }, g_q6_regs, NULL},
+ { "q7", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7, LLDB_INVALID_REGNUM, 98, 98 }, g_q7_regs, NULL},
+ { "q8", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8, LLDB_INVALID_REGNUM, 99, 99 }, g_q8_regs, NULL},
+ { "q9", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9, LLDB_INVALID_REGNUM, 100, 100 }, g_q9_regs, NULL},
+ { "q10", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10, LLDB_INVALID_REGNUM, 101, 101 }, g_q10_regs, NULL},
+ { "q11", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11, LLDB_INVALID_REGNUM, 102, 102 }, g_q11_regs, NULL},
+ { "q12", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12, LLDB_INVALID_REGNUM, 103, 103 }, g_q12_regs, NULL},
+ { "q13", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13, LLDB_INVALID_REGNUM, 104, 104 }, g_q13_regs, NULL},
+ { "q14", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14, LLDB_INVALID_REGNUM, 105, 105 }, g_q14_regs, NULL},
+ { "q15", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15, LLDB_INVALID_REGNUM, 106, 106 }, g_q15_regs, NULL}
};
static const uint32_t num_registers = llvm::array_lengthof(g_register_infos);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 117d280..0e26c69 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -42,32 +42,22 @@ public:
{
}
- ~GDBRemoteDynamicRegisterInfo ()
- {
- }
+ ~GDBRemoteDynamicRegisterInfo() override = default;
void
HardcodeARMRegisters(bool from_scratch);
-
};
class GDBRemoteRegisterContext : public RegisterContext
{
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
GDBRemoteRegisterContext (ThreadGDBRemote &thread,
uint32_t concrete_frame_idx,
GDBRemoteDynamicRegisterInfo &reg_info,
bool read_all_at_once);
- virtual
- ~GDBRemoteRegisterContext ();
+ ~GDBRemoteRegisterContext() override;
- //------------------------------------------------------------------
- // Subclasses must override these functions
- //------------------------------------------------------------------
void
InvalidateAllRegisters () override;
@@ -119,6 +109,9 @@ protected:
bool
PrivateSetRegisterValue (uint32_t reg, StringExtractor &response);
+ bool
+ PrivateSetRegisterValue (uint32_t reg, uint64_t val);
+
void
SetAllRegisterValid (bool b);
@@ -166,13 +159,10 @@ private:
bool SetPrimordialRegister(const RegisterInfo *reg_info,
GDBRemoteCommunicationClient &gdb_comm);
- //------------------------------------------------------------------
- // For GDBRemoteRegisterContext only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (GDBRemoteRegisterContext);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // lldb_GDBRemoteRegisterContext_h_
+#endif // lldb_GDBRemoteRegisterContext_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 0a8d559..6bee4e1 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -40,6 +40,7 @@
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/Symbols.h"
@@ -56,6 +57,7 @@
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
@@ -106,35 +108,35 @@ namespace {
{ "target-definition-file" , OptionValue::eTypeFileSpec , true, 0 , NULL, NULL, "The file that provides the description for remote target registers." },
{ NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL }
};
-
+
enum
{
ePropertyPacketTimeout,
ePropertyTargetDefinitionFile
};
-
+
class PluginProperties : public Properties
{
public:
-
+
static ConstString
GetSettingName ()
{
return ProcessGDBRemote::GetPluginNameStatic();
}
-
+
PluginProperties() :
Properties ()
{
m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
m_collection_sp->Initialize(g_properties);
}
-
+
virtual
~PluginProperties()
{
}
-
+
uint64_t
GetPacketTimeout()
{
@@ -156,9 +158,9 @@ namespace {
return m_collection_sp->GetPropertyAtIndexAsFileSpec (NULL, idx);
}
};
-
+
typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
-
+
static const ProcessKDPPropertiesSP &
GetGlobalPluginProperties()
{
@@ -167,109 +169,8 @@ namespace {
g_settings_sp.reset (new PluginProperties ());
return g_settings_sp;
}
-
-} // anonymous namespace end
-
-class ProcessGDBRemote::GDBLoadedModuleInfoList
-{
-public:
-
- class LoadedModuleInfo
- {
- public:
- enum e_data_point
- {
- e_has_name = 0,
- e_has_base ,
- e_has_dynamic ,
- e_has_link_map ,
- e_num
- };
-
- LoadedModuleInfo ()
- {
- for (uint32_t i = 0; i < e_num; ++i)
- m_has[i] = false;
- };
-
- void set_name (const std::string & name)
- {
- m_name = name;
- m_has[e_has_name] = true;
- }
- bool get_name (std::string & out) const
- {
- out = m_name;
- return m_has[e_has_name];
- }
-
- void set_base (const lldb::addr_t base)
- {
- m_base = base;
- m_has[e_has_base] = true;
- }
- bool get_base (lldb::addr_t & out) const
- {
- out = m_base;
- return m_has[e_has_base];
- }
-
- void set_link_map (const lldb::addr_t addr)
- {
- m_link_map = addr;
- m_has[e_has_link_map] = true;
- }
- bool get_link_map (lldb::addr_t & out) const
- {
- out = m_link_map;
- return m_has[e_has_link_map];
- }
-
- void set_dynamic (const lldb::addr_t addr)
- {
- m_dynamic = addr;
- m_has[e_has_dynamic] = true;
- }
- bool get_dynamic (lldb::addr_t & out) const
- {
- out = m_dynamic;
- return m_has[e_has_dynamic];
- }
-
- bool has_info (e_data_point datum)
- {
- assert (datum < e_num);
- return m_has[datum];
- }
-
- protected:
-
- bool m_has[e_num];
- std::string m_name;
- lldb::addr_t m_link_map;
- lldb::addr_t m_base;
- lldb::addr_t m_dynamic;
- };
-
- GDBLoadedModuleInfoList ()
- : m_list ()
- , m_link_map (LLDB_INVALID_ADDRESS)
- {}
-
- void add (const LoadedModuleInfo & mod)
- {
- m_list.push_back (mod);
- }
-
- void clear ()
- {
- m_list.clear ();
- }
-
- std::vector<LoadedModuleInfo> m_list;
- lldb::addr_t m_link_map;
-};
+} // anonymous namespace end
// TODO Randomly assigning a port is unsafe. We should get an unused
// ephemeral port from the kernel and make sure we reserve it before passing
@@ -321,22 +222,22 @@ ProcessGDBRemote::Terminate()
lldb::ProcessSP
-ProcessGDBRemote::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file_path)
+ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file_path)
{
lldb::ProcessSP process_sp;
if (crash_file_path == NULL)
- process_sp.reset (new ProcessGDBRemote (target, listener));
+ process_sp.reset (new ProcessGDBRemote (target_sp, listener));
return process_sp;
}
bool
-ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)
+ProcessGDBRemote::CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name)
{
if (plugin_specified_by_name)
return true;
// For now we are just making sure the file exists for a given module
- Module *exe_module = target.GetExecutableModulePointer();
+ Module *exe_module = target_sp->GetExecutableModulePointer();
if (exe_module)
{
ObjectFile *exe_objfile = exe_module->GetObjectFile();
@@ -365,17 +266,20 @@ ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)
//----------------------------------------------------------------------
// ProcessGDBRemote constructor
//----------------------------------------------------------------------
-ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
- Process (target, listener),
+ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, Listener &listener) :
+ Process (target_sp, listener),
m_flags (0),
m_gdb_comm (),
m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
m_last_stop_packet_mutex (Mutex::eMutexTypeRecursive),
m_register_info (),
m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"),
+ m_async_listener("lldb.process.gdb-remote.async-listener"),
m_async_thread_state_mutex(Mutex::eMutexTypeRecursive),
m_thread_ids (),
- m_threads_info_sp (),
+ m_thread_pcs (),
+ m_jstopinfo_sp (),
+ m_jthreadsinfo_sp (),
m_continue_c_tids (),
m_continue_C_tids (),
m_continue_s_tids (),
@@ -393,6 +297,25 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadDidExit, "async thread did exit");
+
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_ASYNC));
+
+ const uint32_t async_event_mask = eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;
+
+ if (m_async_listener.StartListeningForEvents(&m_async_broadcaster, async_event_mask) != async_event_mask)
+ {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s failed to listen for m_async_broadcaster events", __FUNCTION__);
+ }
+
+ const uint32_t gdb_event_mask = Communication::eBroadcastBitReadThreadDidExit |
+ GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify;
+ if (m_async_listener.StartListeningForEvents(&m_gdb_comm, gdb_event_mask) != gdb_event_mask)
+ {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", __FUNCTION__);
+ }
+
const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout();
if (timeout_seconds > 0)
m_gdb_comm.SetPacketTimeout(timeout_seconds);
@@ -410,7 +333,7 @@ ProcessGDBRemote::~ProcessGDBRemote()
// destruct this class, then Process::~Process() might have problems
// trying to fully destroy the broadcaster.
Finalize();
-
+
// The general Finalize is going to try to destroy the process and that SHOULD
// shut down the async thread. However, if we don't kill it it will get stranded and
// its connection will go away so when it wakes up it will crash. So kill it for sure here.
@@ -480,6 +403,40 @@ ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_
return false;
}
+// If the remote stub didn't give us eh_frame or DWARF register numbers for a register,
+// see if the ABI can provide them.
+// DWARF and eh_frame register numbers are defined as a part of the ABI.
+static void
+AugmentRegisterInfoViaABI (RegisterInfo &reg_info, ConstString reg_name, ABISP abi_sp)
+{
+ if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM
+ || reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM)
+ {
+ if (abi_sp)
+ {
+ RegisterInfo abi_reg_info;
+ if (abi_sp->GetRegisterInfoByName (reg_name, abi_reg_info))
+ {
+ if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM &&
+ abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
+ {
+ reg_info.kinds[eRegisterKindEHFrame] = abi_reg_info.kinds[eRegisterKindEHFrame];
+ }
+ if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM &&
+ abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
+ {
+ reg_info.kinds[eRegisterKindDWARF] = abi_reg_info.kinds[eRegisterKindDWARF];
+ }
+ if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM &&
+ abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
+ {
+ reg_info.kinds[eRegisterKindGeneric] = abi_reg_info.kinds[eRegisterKindGeneric];
+ }
+ }
+ }
+ }
+}
+
static size_t
SplitCommaSeparatedRegisterNumberString(const llvm::StringRef &comma_separated_regiter_numbers, std::vector<uint32_t> &regnums, int base)
{
@@ -517,27 +474,39 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout);
}
- // Register info search order:
+ // Register info search order:
// 1 - Use the target definition python file if one is specified.
// 2 - If the target definition doesn't have any of the info from the target.xml (registers) then proceed to read the target.xml.
// 3 - Fall back on the qRegisterInfo packets.
FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();
+ if (!target_definition_fspec.Exists())
+ {
+ // If the filename doesn't exist, it may be a ~ not having been expanded - try to resolve it.
+ target_definition_fspec.ResolvePath();
+ }
if (target_definition_fspec)
{
// See if we can get register definitions from a python file
if (ParsePythonTargetDefinition (target_definition_fspec))
+ {
return;
+ }
+ else
+ {
+ StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream();
+ stream_sp->Printf ("ERROR: target description file %s failed to parse.\n", target_definition_fspec.GetPath().c_str());
+ }
}
if (GetGDBServerRegisterInfo ())
return;
-
+
char packet[128];
uint32_t reg_offset = 0;
uint32_t reg_num = 0;
for (StringExtractorGDBRemote::ResponseType response_type = StringExtractorGDBRemote::eResponse;
- response_type == StringExtractorGDBRemote::eResponse;
+ response_type == StringExtractorGDBRemote::eResponse;
++reg_num)
{
const int packet_len = ::snprintf (packet, sizeof(packet), "qRegisterInfo%x", reg_num);
@@ -560,12 +529,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
0, // byte size
reg_offset, // offset
eEncodingUint, // encoding
- eFormatHex, // formate
+ eFormatHex, // format
{
- LLDB_INVALID_REGNUM, // GCC reg num
+ LLDB_INVALID_REGNUM, // eh_frame reg num
LLDB_INVALID_REGNUM, // DWARF reg num
LLDB_INVALID_REGNUM, // generic reg num
- reg_num, // GDB reg num
+ reg_num, // process plugin reg num
reg_num // native register number
},
NULL,
@@ -634,9 +603,9 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
{
set_name.SetCString(value.c_str());
}
- else if (name.compare("gcc") == 0)
+ else if (name.compare("gcc") == 0 || name.compare("ehframe") == 0)
{
- reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
+ reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
}
else if (name.compare("dwarf") == 0)
{
@@ -670,6 +639,8 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
reg_info.invalidate_regs = invalidate_regs.data();
}
+ AugmentRegisterInfoViaABI (reg_info, reg_name, GetABI ());
+
m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
}
else
@@ -710,11 +681,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
if (!target_arch.IsValid())
{
if (remote_arch.IsValid()
- && remote_arch.GetMachine() == llvm::Triple::arm
+ && (remote_arch.GetMachine() == llvm::Triple::arm || remote_arch.GetMachine() == llvm::Triple::thumb)
&& remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)
m_register_info.HardcodeARMRegisters(from_scratch);
}
- else if (target_arch.GetMachine() == llvm::Triple::arm)
+ else if (target_arch.GetMachine() == llvm::Triple::arm
+ || target_arch.GetMachine() == llvm::Triple::thumb)
{
m_register_info.HardcodeARMRegisters(from_scratch);
}
@@ -746,7 +718,7 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
{
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
Error error (WillLaunchOrAttach ());
-
+
if (error.Fail())
return error;
@@ -760,7 +732,7 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
if (pid == LLDB_INVALID_PROCESS_ID)
{
// We don't have a valid process ID, so note that we are connected
- // and could now request to launch or attach, or get remote process
+ // and could now request to launch or attach, or get remote process
// listings...
SetPrivateState (eStateConnected);
}
@@ -778,20 +750,21 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
if (GetTarget().GetNonStopModeEnabled())
HandleStopReplySequence();
- if (!m_target.GetArchitecture().IsValid())
+ Target &target = GetTarget();
+ if (!target.GetArchitecture().IsValid())
{
if (m_gdb_comm.GetProcessArchitecture().IsValid())
{
- m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
}
else
{
- m_target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
+ target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
}
}
const StateType state = SetThreadStopInfo (response);
- if (state == eStateStopped)
+ if (state != eStateInvalid)
{
SetPrivateState (state);
}
@@ -909,27 +882,22 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
ObjectFile * object_file = exe_module->GetObjectFile();
if (object_file)
{
- // Make sure we aren't already connected?
- if (!m_gdb_comm.IsConnected())
- {
- error = LaunchAndConnectToDebugserver (launch_info);
- }
-
+ error = EstablishConnectionIfNeeded (launch_info);
if (error.Success())
{
lldb_utility::PseudoTerminal pty;
const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
- PlatformSP platform_sp (m_target.GetPlatform());
+ PlatformSP platform_sp (GetTarget().GetPlatform());
if (disable_stdio)
{
// set to /dev/null unless redirected to a file above
if (!stdin_file_spec)
- stdin_file_spec.SetFile("/dev/null", false);
+ stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);
if (!stdout_file_spec)
- stdout_file_spec.SetFile("/dev/null", false);
+ stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);
if (!stderr_file_spec)
- stderr_file_spec.SetFile("/dev/null", false);
+ stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);
}
else if (platform_sp && platform_sp->IsHost())
{
@@ -976,12 +944,12 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError);
- m_gdb_comm.SendLaunchArchPacket (m_target.GetArchitecture().GetArchitectureName());
-
+ m_gdb_comm.SendLaunchArchPacket (GetTarget().GetArchitecture().GetArchitectureName());
+
const char * launch_event_data = launch_info.GetLaunchEventData();
if (launch_event_data != NULL && *launch_event_data != '\0')
m_gdb_comm.SendLaunchEventDataPacket (launch_event_data);
-
+
if (working_dir)
{
m_gdb_comm.SetWorkingDir (working_dir);
@@ -1043,17 +1011,17 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
if (process_arch.IsValid())
{
- m_target.MergeArchitecture(process_arch);
+ GetTarget().MergeArchitecture(process_arch);
}
else
{
const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();
if (host_arch.IsValid())
- m_target.MergeArchitecture(host_arch);
+ GetTarget().MergeArchitecture(host_arch);
}
SetPrivateState (SetThreadStopInfo (response));
-
+
if (!disable_stdio)
{
if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd)
@@ -1071,8 +1039,8 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
{
// Set our user ID to an invalid process ID.
SetID(LLDB_INVALID_PROCESS_ID);
- error.SetErrorStringWithFormat ("failed to get object file from '%s' for arch %s",
- exe_module->GetFileSpec().GetFilename().AsCString(),
+ error.SetErrorStringWithFormat ("failed to get object file from '%s' for arch %s",
+ exe_module->GetFileSpec().GetFilename().AsCString(),
exe_module->GetArchitecture().GetArchitectureName());
}
return error;
@@ -1086,7 +1054,7 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
Error error;
// Only connect if we have a valid connect URL
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
-
+
if (connect_url && connect_url[0])
{
if (log)
@@ -1108,9 +1076,9 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
// If we were interrupted, don't keep retrying.
break;
}
-
+
retry_count++;
-
+
if (retry_count >= max_retry_count)
break;
@@ -1135,7 +1103,7 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
// We always seem to be able to open a connection to a local port
// so we need to make sure we can then send data to it. If we can't
// then we aren't actually connected to anything, so try and do the
- // handshake with the remote GDB server and make sure that goes
+ // handshake with the remote GDB server and make sure that goes
// alright.
if (!m_gdb_comm.HandshakeWithServer (&error))
{
@@ -1225,8 +1193,8 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)
// it has, so we really need to take the remote host architecture as our
// defacto architecture in this case.
- if (process_arch.GetMachine() == llvm::Triple::arm &&
- process_arch.GetTriple().getVendor() == llvm::Triple::Apple)
+ if ((process_arch.GetMachine() == llvm::Triple::arm || process_arch.GetMachine() == llvm::Triple::thumb)
+ && process_arch.GetTriple().getVendor() == llvm::Triple::Apple)
{
GetTarget().SetArchitecture (process_arch);
if (log)
@@ -1294,30 +1262,18 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process
Clear();
if (attach_pid != LLDB_INVALID_PROCESS_ID)
{
- // Make sure we aren't already connected?
- if (!m_gdb_comm.IsConnected())
- {
- error = LaunchAndConnectToDebugserver (attach_info);
-
- if (error.Fail())
- {
- const char *error_string = error.AsCString();
- if (error_string == NULL)
- error_string = "unable to launch " DEBUGSERVER_BASENAME;
-
- SetExitStatus (-1, error_string);
- }
- }
-
+ error = EstablishConnectionIfNeeded (attach_info);
if (error.Success())
{
m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
char packet[64];
const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid);
- SetID (attach_pid);
+ SetID (attach_pid);
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));
}
+ else
+ SetExitStatus (-1, error.AsCString());
}
return error;
@@ -1332,27 +1288,13 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro
if (process_name && process_name[0])
{
- // Make sure we aren't already connected?
- if (!m_gdb_comm.IsConnected())
- {
- error = LaunchAndConnectToDebugserver (attach_info);
-
- if (error.Fail())
- {
- const char *error_string = error.AsCString();
- if (error_string == NULL)
- error_string = "unable to launch " DEBUGSERVER_BASENAME;
-
- SetExitStatus (-1, error_string);
- }
- }
-
+ error = EstablishConnectionIfNeeded (attach_info);
if (error.Success())
{
StreamString packet;
-
+
m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
-
+
if (attach_info.GetWaitForLaunch())
{
if (!m_gdb_comm.GetVAttachOrWaitSupported())
@@ -1370,11 +1312,13 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro
else
packet.PutCString("vAttachName");
packet.PutChar(';');
- packet.PutBytesAsRawHex8(process_name, strlen(process_name), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
-
+ packet.PutBytesAsRawHex8(process_name, strlen(process_name), endian::InlHostByteOrder(), endian::InlHostByteOrder());
+
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize()));
}
+ else
+ SetExitStatus (-1, error.AsCString());
}
return error;
}
@@ -1402,6 +1346,8 @@ ProcessGDBRemote::WillResume ()
m_continue_C_tids.clear();
m_continue_s_tids.clear();
m_continue_S_tids.clear();
+ m_jstopinfo_sp.reset();
+ m_jthreadsinfo_sp.reset();
return Error();
}
@@ -1412,12 +1358,12 @@ ProcessGDBRemote::DoResume ()
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::Resume()");
-
+
Listener listener ("gdb-remote.resume-packet-sent");
if (listener.StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent))
{
listener.StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit);
-
+
const size_t num_threads = GetThreadList().GetSize();
StreamString continue_packet;
@@ -1437,7 +1383,7 @@ ProcessGDBRemote::DoResume ()
else
{
continue_packet.PutCString ("vCont");
-
+
if (!m_continue_c_tids.empty())
{
if (m_gdb_comm.GetVContSupported ('c'))
@@ -1445,10 +1391,10 @@ ProcessGDBRemote::DoResume ()
for (tid_collection::const_iterator t_pos = m_continue_c_tids.begin(), t_end = m_continue_c_tids.end(); t_pos != t_end; ++t_pos)
continue_packet.Printf(";c:%4.4" PRIx64, *t_pos);
}
- else
+ else
continue_packet_error = true;
}
-
+
if (!continue_packet_error && !m_continue_C_tids.empty())
{
if (m_gdb_comm.GetVContSupported ('C'))
@@ -1456,7 +1402,7 @@ ProcessGDBRemote::DoResume ()
for (tid_sig_collection::const_iterator s_pos = m_continue_C_tids.begin(), s_end = m_continue_C_tids.end(); s_pos != s_end; ++s_pos)
continue_packet.Printf(";C%2.2x:%4.4" PRIx64, s_pos->second, s_pos->first);
}
- else
+ else
continue_packet_error = true;
}
@@ -1467,10 +1413,10 @@ ProcessGDBRemote::DoResume ()
for (tid_collection::const_iterator t_pos = m_continue_s_tids.begin(), t_end = m_continue_s_tids.end(); t_pos != t_end; ++t_pos)
continue_packet.Printf(";s:%4.4" PRIx64, *t_pos);
}
- else
+ else
continue_packet_error = true;
}
-
+
if (!continue_packet_error && !m_continue_S_tids.empty())
{
if (m_gdb_comm.GetVContSupported ('S'))
@@ -1481,14 +1427,14 @@ ProcessGDBRemote::DoResume ()
else
continue_packet_error = true;
}
-
+
if (continue_packet_error)
continue_packet.GetString().clear();
}
}
else
continue_packet_error = true;
-
+
if (continue_packet_error)
{
// Either no vCont support, or we tried to use part of the vCont
@@ -1504,33 +1450,33 @@ ProcessGDBRemote::DoResume ()
{
// All threads are resuming...
m_gdb_comm.SetCurrentThreadForRun (-1);
- continue_packet.PutChar ('c');
+ continue_packet.PutChar ('c');
continue_packet_error = false;
}
else if (num_continue_c_tids == 1 &&
- num_continue_C_tids == 0 &&
- num_continue_s_tids == 0 &&
+ num_continue_C_tids == 0 &&
+ num_continue_s_tids == 0 &&
num_continue_S_tids == 0 )
{
// Only one thread is continuing
m_gdb_comm.SetCurrentThreadForRun (m_continue_c_tids.front());
- continue_packet.PutChar ('c');
+ continue_packet.PutChar ('c');
continue_packet_error = false;
}
}
if (continue_packet_error && num_continue_C_tids > 0)
{
- if ((num_continue_C_tids + num_continue_c_tids) == num_threads &&
- num_continue_C_tids > 0 &&
- num_continue_s_tids == 0 &&
+ if ((num_continue_C_tids + num_continue_c_tids) == num_threads &&
+ num_continue_C_tids > 0 &&
+ num_continue_s_tids == 0 &&
num_continue_S_tids == 0 )
{
const int continue_signo = m_continue_C_tids.front().second;
// Only one thread is continuing
if (num_continue_C_tids > 1)
{
- // More that one thread with a signal, yet we don't have
+ // More that one thread with a signal, yet we don't have
// vCont support and we are being asked to resume each
// thread with a signal, we need to make sure they are
// all the same signal, or we can't issue the continue
@@ -1582,13 +1528,13 @@ ProcessGDBRemote::DoResume ()
continue_packet_error = false;
}
else if (num_continue_c_tids == 0 &&
- num_continue_C_tids == 0 &&
- num_continue_s_tids == 1 &&
+ num_continue_C_tids == 0 &&
+ num_continue_s_tids == 1 &&
num_continue_S_tids == 0 )
{
// Only one thread is stepping
m_gdb_comm.SetCurrentThreadForRun (m_continue_s_tids.front());
- continue_packet.PutChar ('s');
+ continue_packet.PutChar ('s');
continue_packet_error = false;
}
}
@@ -1616,8 +1562,8 @@ ProcessGDBRemote::DoResume ()
}
}
else if (num_continue_c_tids == 0 &&
- num_continue_C_tids == 0 &&
- num_continue_s_tids == 0 &&
+ num_continue_C_tids == 0 &&
+ num_continue_s_tids == 0 &&
num_continue_S_tids == 1 )
{
// Only one thread is stepping with signal
@@ -1645,7 +1591,7 @@ ProcessGDBRemote::DoResume ()
log->Printf ("ProcessGDBRemote::DoResume: Trying to resume but the async thread is dead.");
return error;
}
-
+
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize()));
if (listener.WaitForEvent (&timeout, event_sp) == false)
@@ -1693,12 +1639,14 @@ ProcessGDBRemote::ClearThreadIDList ()
{
Mutex::Locker locker(m_thread_list_real.GetMutex());
m_thread_ids.clear();
+ m_thread_pcs.clear();
}
size_t
ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)
{
m_thread_ids.clear();
+ m_thread_pcs.clear();
size_t comma_pos;
lldb::tid_t tid;
while ((comma_pos = value.find(',')) != std::string::npos)
@@ -1716,18 +1664,39 @@ ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)
return m_thread_ids.size();
}
+size_t
+ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue (std::string &value)
+{
+ m_thread_pcs.clear();
+ size_t comma_pos;
+ lldb::addr_t pc;
+ while ((comma_pos = value.find(',')) != std::string::npos)
+ {
+ value[comma_pos] = '\0';
+ pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_ADDRESS)
+ m_thread_pcs.push_back (pc);
+ value.erase(0, comma_pos + 1);
+ }
+ pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_THREAD_ID)
+ m_thread_pcs.push_back (pc);
+ return m_thread_pcs.size();
+}
+
bool
ProcessGDBRemote::UpdateThreadIDList ()
{
Mutex::Locker locker(m_thread_list_real.GetMutex());
- if (m_threads_info_sp)
+ if (m_jthreadsinfo_sp)
{
// If we have the JSON threads info, we can get the thread list from that
- StructuredData::Array *thread_infos = m_threads_info_sp->GetAsArray();
+ StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
if (thread_infos && thread_infos->GetSize() > 0)
{
m_thread_ids.clear();
+ m_thread_pcs.clear();
thread_infos->ForEach([this](StructuredData::Object* object) -> bool {
StructuredData::Dictionary *thread_dict = object->GetAsDictionary();
if (thread_dict)
@@ -1750,25 +1719,43 @@ ProcessGDBRemote::UpdateThreadIDList ()
// that might contain a "threads" key/value pair
// Lock the thread stack while we access it
- Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
- // Get the number of stop packets on the stack
- int nItems = m_stop_packet_stack.size();
- // Iterate over them
- for (int i = 0; i < nItems; i++)
+ //Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
+ Mutex::Locker stop_stack_lock;
+ if (stop_stack_lock.TryLock(m_last_stop_packet_mutex))
{
- // Get the thread stop info
- StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i];
- const std::string &stop_info_str = stop_info.GetStringRef();
- const size_t threads_pos = stop_info_str.find(";threads:");
- if (threads_pos != std::string::npos)
+ // Get the number of stop packets on the stack
+ int nItems = m_stop_packet_stack.size();
+ // Iterate over them
+ for (int i = 0; i < nItems; i++)
{
- const size_t start = threads_pos + strlen(";threads:");
- const size_t end = stop_info_str.find(';', start);
- if (end != std::string::npos)
+ // Get the thread stop info
+ StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i];
+ const std::string &stop_info_str = stop_info.GetStringRef();
+
+ m_thread_pcs.clear();
+ const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:");
+ if (thread_pcs_pos != std::string::npos)
{
- std::string value = stop_info_str.substr(start, end - start);
- if (UpdateThreadIDsFromStopReplyThreadsValue(value))
- return true;
+ const size_t start = thread_pcs_pos + strlen(";thread-pcs:");
+ const size_t end = stop_info_str.find(';', start);
+ if (end != std::string::npos)
+ {
+ std::string value = stop_info_str.substr(start, end - start);
+ UpdateThreadPCsFromStopReplyThreadsValue(value);
+ }
+ }
+
+ const size_t threads_pos = stop_info_str.find(";threads:");
+ if (threads_pos != std::string::npos)
+ {
+ const size_t start = threads_pos + strlen(";threads:");
+ const size_t end = stop_info_str.find(';', start);
+ if (end != std::string::npos)
+ {
+ std::string value = stop_info_str.substr(start, end - start);
+ if (UpdateThreadIDsFromStopReplyThreadsValue(value))
+ return true;
+ }
}
}
}
@@ -1790,7 +1777,7 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD));
if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
log->Printf ("ProcessGDBRemote::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());
-
+
size_t num_thread_ids = m_thread_ids.size();
// The "m_thread_ids" thread ID list should always be updated after each stop
// reply packet, but in case it isn't, update it here.
@@ -1825,10 +1812,29 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new
__FUNCTION__, static_cast<void*>(thread_sp.get()),
thread_sp->GetID());
}
+ // The m_thread_pcs vector has pc values in big-endian order, not target-endian, unlike most
+ // of the register read/write packets in gdb-remote protocol.
+ // Early in the process startup, we may not yet have set the process ByteOrder so we ignore these;
+ // they are a performance improvement over fetching thread register values individually, the
+ // method we will fall back to if needed.
+ if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && GetByteOrder() != eByteOrderInvalid)
+ {
+ ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
+ RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext());
+ if (reg_ctx_sp)
+ {
+ uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber
+ (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ if (pc_regnum != LLDB_INVALID_REGNUM)
+ {
+ gdb_thread->PrivateSetRegisterValue (pc_regnum, m_thread_pcs[i]);
+ }
+ }
+ }
new_thread_list.AddThread(thread_sp);
}
}
-
+
// Whatever that is left in old_thread_list_copy are not
// present in new_thread_list. Remove non-existent threads from internal id table.
size_t old_num_thread_ids = old_thread_list_copy.GetSize(false);
@@ -1841,17 +1847,18 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new
m_thread_id_to_index_id_map.erase(old_thread_id);
}
}
-
+
return true;
}
+
bool
-ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)
+ProcessGDBRemote::GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp)
{
// See if we got thread stop infos for all threads via the "jThreadsInfo" packet
- if (m_threads_info_sp)
+ if (thread_infos_sp)
{
- StructuredData::Array *thread_infos = m_threads_info_sp->GetAsArray();
+ StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray();
if (thread_infos)
{
lldb::tid_t tid;
@@ -1864,12 +1871,36 @@ ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)
if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid, LLDB_INVALID_THREAD_ID))
{
if (tid == thread->GetID())
- return SetThreadStopInfo(thread_dict);
+ return (bool)SetThreadStopInfo(thread_dict);
}
}
}
}
}
+ return false;
+}
+
+bool
+ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)
+{
+ // See if we got thread stop infos for all threads via the "jThreadsInfo" packet
+ if (GetThreadStopInfoFromJSON (thread, m_jthreadsinfo_sp))
+ return true;
+
+ // See if we got thread stop info for any threads valid stop info reasons threads
+ // via the "jstopinfo" packet stop reply packet key/value pair?
+ if (m_jstopinfo_sp)
+ {
+ // If we have "jstopinfo" then we have stop descriptions for all threads
+ // that have stop reasons, and if there is no entry for a thread, then
+ // it has no stop reason.
+ thread->GetRegisterContext()->InvalidateIfNeeded(true);
+ if (!GetThreadStopInfoFromJSON (thread, m_jstopinfo_sp))
+ {
+ thread->SetStopInfo (StopInfoSP());
+ }
+ return true;
+ }
// Fall back to using the qThreadStopInfo packet
StringExtractorGDBRemote stop_packet;
@@ -1890,6 +1921,8 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
const std::vector<addr_t> &exc_data,
addr_t thread_dispatch_qaddr,
bool queue_vars_valid, // Set to true if queue_name, queue_kind and queue_serial are valid
+ LazyBool associated_with_dispatch_queue,
+ addr_t dispatch_queue_t,
std::string &queue_name,
QueueKind queue_kind,
uint64_t queue_serial)
@@ -1925,156 +1958,173 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
gdb_thread->PrivateSetRegisterValue (pair.first, reg_value_extractor);
}
- // Clear the stop info just in case we don't set it to anything
- thread_sp->SetStopInfo (StopInfoSP());
thread_sp->SetName (thread_name.empty() ? NULL : thread_name.c_str());
gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr);
// Check if the GDB server was able to provide the queue name, kind and serial number
if (queue_vars_valid)
- gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial);
+ gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial, dispatch_queue_t, associated_with_dispatch_queue);
else
gdb_thread->ClearQueueInfo();
+ gdb_thread->SetAssociatedWithLibdispatchQueue (associated_with_dispatch_queue);
- if (exc_type != 0)
- {
- const size_t exc_data_size = exc_data.size();
-
- thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp,
- exc_type,
- exc_data_size,
- exc_data_size >= 1 ? exc_data[0] : 0,
- exc_data_size >= 2 ? exc_data[1] : 0,
- exc_data_size >= 3 ? exc_data[2] : 0));
- }
- else
+ if (dispatch_queue_t != LLDB_INVALID_ADDRESS)
+ gdb_thread->SetQueueLibdispatchQueueAddress (dispatch_queue_t);
+
+ // Make sure we update our thread stop reason just once
+ if (!thread_sp->StopInfoIsUpToDate())
{
- bool handled = false;
- bool did_exec = false;
- if (!reason.empty())
+ thread_sp->SetStopInfo (StopInfoSP());
+ // If there's a memory thread backed by this thread, we need to use it to calcualte StopInfo.
+ ThreadSP memory_thread_sp = m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID());
+ if (memory_thread_sp)
+ thread_sp = memory_thread_sp;
+
+ if (exc_type != 0)
{
- if (reason.compare("trace") == 0)
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
- handled = true;
- }
- else if (reason.compare("breakpoint") == 0)
+ const size_t exc_data_size = exc_data.size();
+
+ thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp,
+ exc_type,
+ exc_data_size,
+ exc_data_size >= 1 ? exc_data[0] : 0,
+ exc_data_size >= 2 ? exc_data[1] : 0,
+ exc_data_size >= 3 ? exc_data[2] : 0));
+ }
+ else
+ {
+ bool handled = false;
+ bool did_exec = false;
+ if (!reason.empty())
{
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
- lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
- if (bp_site_sp)
+ if (reason.compare("trace") == 0)
{
- // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
handled = true;
- if (bp_site_sp->ValidForThisThread (thread_sp.get()))
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
- }
- else
+ }
+ else if (reason.compare("breakpoint") == 0)
+ {
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
+ if (bp_site_sp)
{
- StopInfoSP invalid_stop_info_sp;
- thread_sp->SetStopInfo (invalid_stop_info_sp);
+ // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
+ // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
+ // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+ handled = true;
+ if (bp_site_sp->ValidForThisThread (thread_sp.get()))
+ {
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
+ }
+ else
+ {
+ StopInfoSP invalid_stop_info_sp;
+ thread_sp->SetStopInfo (invalid_stop_info_sp);
+ }
}
}
- }
- else if (reason.compare("trap") == 0)
- {
- // Let the trap just use the standard signal stop reason below...
- }
- else if (reason.compare("watchpoint") == 0)
- {
- StringExtractor desc_extractor(description.c_str());
- addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
- uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
- addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
- watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
- if (wp_addr != LLDB_INVALID_ADDRESS)
+ else if (reason.compare("trap") == 0)
{
- WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);
- if (wp_sp)
+ // Let the trap just use the standard signal stop reason below...
+ }
+ else if (reason.compare("watchpoint") == 0)
+ {
+ StringExtractor desc_extractor(description.c_str());
+ addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
+ uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
+ addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
+ watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
+ if (wp_addr != LLDB_INVALID_ADDRESS)
+ {
+ WatchpointSP wp_sp;
+ ArchSpec::Core core = GetTarget().GetArchitecture().GetCore();
+ if (core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last)
+ wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr);
+ if (!wp_sp)
+ wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);
+ if (wp_sp)
+ {
+ wp_sp->SetHardwareIndex(wp_index);
+ watch_id = wp_sp->GetID();
+ }
+ }
+ if (watch_id == LLDB_INVALID_WATCH_ID)
{
- wp_sp->SetHardwareIndex(wp_index);
- watch_id = wp_sp->GetID();
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS));
+ if (log) log->Printf ("failed to find watchpoint");
}
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr));
+ handled = true;
}
- if (watch_id == LLDB_INVALID_WATCH_ID)
+ else if (reason.compare("exception") == 0)
{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS));
- if (log) log->Printf ("failed to find watchpoint");
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str()));
+ handled = true;
+ }
+ else if (reason.compare("exec") == 0)
+ {
+ did_exec = true;
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp));
+ handled = true;
}
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr));
- handled = true;
- }
- else if (reason.compare("exception") == 0)
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str()));
- handled = true;
- }
- else if (reason.compare("exec") == 0)
- {
- did_exec = true;
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp));
- handled = true;
}
- }
- if (!handled && signo && did_exec == false)
- {
- if (signo == SIGTRAP)
+ if (!handled && signo && did_exec == false)
{
- // Currently we are going to assume SIGTRAP means we are either
- // hitting a breakpoint or hardware single stepping.
- handled = true;
- addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
- lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
-
- if (bp_site_sp)
+ if (signo == SIGTRAP)
{
- // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
- if (bp_site_sp->ValidForThisThread (thread_sp.get()))
+ // Currently we are going to assume SIGTRAP means we are either
+ // hitting a breakpoint or hardware single stepping.
+ handled = true;
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
+ lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
+
+ if (bp_site_sp)
{
- if(m_breakpoint_pc_offset != 0)
- thread_sp->GetRegisterContext()->SetPC(pc);
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
+ // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
+ // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
+ // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+ if (bp_site_sp->ValidForThisThread (thread_sp.get()))
+ {
+ if(m_breakpoint_pc_offset != 0)
+ thread_sp->GetRegisterContext()->SetPC(pc);
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
+ }
+ else
+ {
+ StopInfoSP invalid_stop_info_sp;
+ thread_sp->SetStopInfo (invalid_stop_info_sp);
+ }
}
else
{
- StopInfoSP invalid_stop_info_sp;
- thread_sp->SetStopInfo (invalid_stop_info_sp);
+ // If we were stepping then assume the stop was the result of the trace. If we were
+ // not stepping then report the SIGTRAP.
+ // FIXME: We are still missing the case where we single step over a trap instruction.
+ if (thread_sp->GetTemporaryResumeState() == eStateStepping)
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
+ else
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str()));
}
}
- else
- {
- // If we were stepping then assume the stop was the result of the trace. If we were
- // not stepping then report the SIGTRAP.
- // FIXME: We are still missing the case where we single step over a trap instruction.
- if (thread_sp->GetTemporaryResumeState() == eStateStepping)
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
- else
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str()));
- }
+ if (!handled)
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str()));
}
- if (!handled)
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str()));
- }
- if (!description.empty())
- {
- lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
- if (stop_info_sp)
- {
- const char *stop_info_desc = stop_info_sp->GetDescription();
- if (!stop_info_desc || !stop_info_desc[0])
- stop_info_sp->SetDescription (description.c_str());
- }
- else
+ if (!description.empty())
{
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str()));
+ lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
+ if (stop_info_sp)
+ {
+ const char *stop_info_desc = stop_info_sp->GetDescription();
+ if (!stop_info_desc || !stop_info_desc[0])
+ stop_info_sp->SetDescription (description.c_str());
+ }
+ else
+ {
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str()));
+ }
}
}
}
@@ -2083,7 +2133,7 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
return thread_sp;
}
-StateType
+lldb::ThreadSP
ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
{
static ConstString g_key_tid("tid");
@@ -2092,14 +2142,17 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
static ConstString g_key_metype("metype");
static ConstString g_key_medata("medata");
static ConstString g_key_qaddr("qaddr");
+ static ConstString g_key_dispatch_queue_t("dispatch_queue_t");
+ static ConstString g_key_associated_with_dispatch_queue("associated_with_dispatch_queue");
static ConstString g_key_queue_name("qname");
static ConstString g_key_queue_kind("qkind");
- static ConstString g_key_queue_serial("qserial");
+ static ConstString g_key_queue_serial_number("qserialnum");
static ConstString g_key_registers("registers");
static ConstString g_key_memory("memory");
static ConstString g_key_address("address");
static ConstString g_key_bytes("bytes");
static ConstString g_key_description("description");
+ static ConstString g_key_signal("signal");
// Stop with signal and thread info
lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
@@ -2113,9 +2166,11 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
ExpeditedRegisterMap expedited_register_map;
bool queue_vars_valid = false;
+ addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
+ LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
std::string queue_name;
QueueKind queue_kind = eQueueKindUnknown;
- uint64_t queue_serial = 0;
+ uint64_t queue_serial_number = 0;
// Iterate through all of the thread dictionary key/value pairs from the structured data dictionary
thread_dict->ForEach([this,
@@ -2129,9 +2184,11 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
&exc_data,
&thread_dispatch_qaddr,
&queue_vars_valid,
+ &associated_with_dispatch_queue,
+ &dispatch_queue_t,
&queue_name,
&queue_kind,
- &queue_serial]
+ &queue_serial_number]
(ConstString key, StructuredData::Object* object) -> bool
{
if (key == g_key_tid)
@@ -2158,7 +2215,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
}
else if (key == g_key_name)
{
- thread_name = std::move(object->GetStringValue());
+ thread_name = object->GetStringValue();
}
else if (key == g_key_qaddr)
{
@@ -2167,7 +2224,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
else if (key == g_key_queue_name)
{
queue_vars_valid = true;
- queue_name = std::move(object->GetStringValue());
+ queue_name = object->GetStringValue();
}
else if (key == g_key_queue_kind)
{
@@ -2183,19 +2240,34 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
queue_kind = eQueueKindConcurrent;
}
}
- else if (key == g_key_queue_serial)
+ else if (key == g_key_queue_serial_number)
{
- queue_serial = object->GetIntegerValue(0);
- if (queue_serial != 0)
+ queue_serial_number = object->GetIntegerValue(0);
+ if (queue_serial_number != 0)
queue_vars_valid = true;
}
+ else if (key == g_key_dispatch_queue_t)
+ {
+ dispatch_queue_t = object->GetIntegerValue(0);
+ if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS)
+ queue_vars_valid = true;
+ }
+ else if (key == g_key_associated_with_dispatch_queue)
+ {
+ queue_vars_valid = true;
+ bool associated = object->GetBooleanValue ();
+ if (associated)
+ associated_with_dispatch_queue = eLazyBoolYes;
+ else
+ associated_with_dispatch_queue = eLazyBoolNo;
+ }
else if (key == g_key_reason)
{
- reason = std::move(object->GetStringValue());
+ reason = object->GetStringValue();
}
else if (key == g_key_description)
{
- description = std::move(object->GetStringValue());
+ description = object->GetStringValue();
}
else if (key == g_key_registers)
{
@@ -2206,7 +2278,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
registers_dict->ForEach([&expedited_register_map](ConstString key, StructuredData::Object* object) -> bool {
const uint32_t reg = StringConvert::ToUInt32 (key.GetCString(), UINT32_MAX, 10);
if (reg != UINT32_MAX)
- expedited_register_map[reg] = std::move(object->GetStringValue());
+ expedited_register_map[reg] = object->GetStringValue();
return true; // Keep iterating through all array items
});
}
@@ -2244,24 +2316,26 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
}
}
+ else if (key == g_key_signal)
+ signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER);
return true; // Keep iterating through all dictionary key/value pairs
});
- SetThreadStopInfo (tid,
- expedited_register_map,
- signo,
- thread_name,
- reason,
- description,
- exc_type,
- exc_data,
- thread_dispatch_qaddr,
- queue_vars_valid,
- queue_name,
- queue_kind,
- queue_serial);
-
- return eStateExited;
+ return SetThreadStopInfo (tid,
+ expedited_register_map,
+ signo,
+ thread_name,
+ reason,
+ description,
+ exc_type,
+ exc_data,
+ thread_dispatch_qaddr,
+ queue_vars_valid,
+ associated_with_dispatch_queue,
+ dispatch_queue_t,
+ queue_name,
+ queue_kind,
+ queue_serial_number);
}
StateType
@@ -2304,9 +2378,11 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
std::vector<addr_t> exc_data;
addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
bool queue_vars_valid = false; // says if locals below that start with "queue_" are valid
+ addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
+ LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
std::string queue_name;
QueueKind queue_kind = eQueueKindUnknown;
- uint64_t queue_serial = 0;
+ uint64_t queue_serial_number = 0;
ExpeditedRegisterMap expedited_register_map;
while (stop_packet.GetNameColonValue(key, value))
{
@@ -2347,6 +2423,39 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
if (tid != LLDB_INVALID_THREAD_ID)
m_thread_ids.push_back (tid);
}
+ else if (key.compare("thread-pcs") == 0)
+ {
+ m_thread_pcs.clear();
+ // A comma separated list of all threads in the current
+ // process that includes the thread for this stop reply
+ // packet
+ size_t comma_pos;
+ lldb::addr_t pc;
+ while ((comma_pos = value.find(',')) != std::string::npos)
+ {
+ value[comma_pos] = '\0';
+ // thread in big endian hex
+ pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_ADDRESS)
+ m_thread_pcs.push_back (pc);
+ value.erase(0, comma_pos + 1);
+ }
+ pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_ADDRESS)
+ m_thread_pcs.push_back (pc);
+ }
+ else if (key.compare("jstopinfo") == 0)
+ {
+ StringExtractor json_extractor;
+ // Swap "value" over into "name_extractor"
+ json_extractor.GetStringRef().swap(value);
+ // Now convert the HEX bytes into a string value
+ json_extractor.GetHexByteString (value);
+
+ // This JSON contains thread IDs and thread stop info for all threads.
+ // It doesn't contain expedited registers, memory or queue info.
+ m_jstopinfo_sp = StructuredData::ParseJSON (value);
+ }
else if (key.compare("hexname") == 0)
{
StringExtractor name_extractor;
@@ -2364,6 +2473,11 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
{
thread_dispatch_qaddr = StringConvert::ToUInt64 (value.c_str(), 0, 16);
}
+ else if (key.compare("dispatch_queue_t") == 0)
+ {
+ queue_vars_valid = true;
+ dispatch_queue_t = StringConvert::ToUInt64 (value.c_str(), 0, 16);
+ }
else if (key.compare("qname") == 0)
{
queue_vars_valid = true;
@@ -2387,10 +2501,10 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
queue_kind = eQueueKindConcurrent;
}
}
- else if (key.compare("qserial") == 0)
+ else if (key.compare("qserialnum") == 0)
{
- queue_serial = StringConvert::ToUInt64 (value.c_str(), 0, 0);
- if (queue_serial != 0)
+ queue_serial_number = StringConvert::ToUInt64 (value.c_str(), 0, 0);
+ if (queue_serial_number != 0)
queue_vars_valid = true;
}
else if (key.compare("reason") == 0)
@@ -2430,7 +2544,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
if (mem_cache_addr != LLDB_INVALID_ADDRESS)
{
StringExtractor bytes;
- bytes.GetStringRef() = std::move(pair.second.str());
+ bytes.GetStringRef() = pair.second.str();
const size_t byte_size = bytes.GetStringRef().size()/2;
DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetBytes(), byte_size, 0);
@@ -2454,6 +2568,10 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index);
description = ostr.GetString().c_str();
}
+ else if (key.compare("library") == 0)
+ {
+ LoadModules();
+ }
else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1]))
{
uint32_t reg = StringConvert::ToUInt32 (key.c_str(), UINT32_MAX, 16);
@@ -2464,10 +2582,10 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
if (tid == LLDB_INVALID_THREAD_ID)
{
- // A thread id may be invalid if the response is old style 'S' packet which does not provide the
+ // A thread id may be invalid if the response is old style 'S' packet which does not provide the
// thread information. So update the thread list and choose the first one.
UpdateThreadIDList ();
-
+
if (!m_thread_ids.empty ())
{
tid = m_thread_ids.front ();
@@ -2484,9 +2602,11 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
exc_data,
thread_dispatch_qaddr,
queue_vars_valid,
+ associated_with_dispatch_queue,
+ dispatch_queue_t,
queue_name,
queue_kind,
- queue_serial);
+ queue_serial_number);
return eStateStopped;
}
@@ -2508,6 +2628,7 @@ ProcessGDBRemote::RefreshStateAfterStop ()
{
Mutex::Locker locker(m_thread_list_real.GetMutex());
m_thread_ids.clear();
+ m_thread_pcs.clear();
// Set the thread stop info. It might have a "threads" key whose value is
// a list of all thread IDs in the current process, so m_thread_ids might
// get set.
@@ -2544,15 +2665,10 @@ ProcessGDBRemote::RefreshStateAfterStop ()
m_initial_tid = LLDB_INVALID_THREAD_ID;
}
- // Fetch the threads via an efficient packet that gets stop infos for all threads
- // only if we have more than one thread
- if (m_thread_ids.size() > 1)
- m_threads_info_sp = m_gdb_comm.GetThreadsInfo();
-
// Let all threads recover from stopping and do any clean up based
// on the previous thread state (if any).
m_thread_list_real.RefreshStateAfterStop();
-
+
}
Error
@@ -2562,7 +2678,7 @@ ProcessGDBRemote::DoHalt (bool &caused_stop)
bool timed_out = false;
Mutex::Locker locker;
-
+
if (m_public_state.GetValue() == eStateAttaching)
{
// We are being asked to halt during an attach. We need to just close
@@ -2578,7 +2694,7 @@ ProcessGDBRemote::DoHalt (bool &caused_stop)
else
error.SetErrorString("unknown error sending interrupt packet");
}
-
+
caused_stop = m_gdb_comm.GetInterruptWasSent ();
}
return error;
@@ -2591,7 +2707,7 @@ ProcessGDBRemote::DoDetach(bool keep_stopped)
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped);
-
+
error = m_gdb_comm.Detach (keep_stopped);
if (log)
{
@@ -2600,7 +2716,7 @@ ProcessGDBRemote::DoDetach(bool keep_stopped)
else
log->Printf ("ProcessGDBRemote::DoDetach() detach packet send failed: %s", error.AsCString() ? error.AsCString() : "<unknown error>");
}
-
+
if (!error.Success())
return error;
@@ -2644,7 +2760,7 @@ ProcessGDBRemote::DoDestroy ()
if (!m_gdb_comm.GetThreadSuffixSupported() && m_public_state.GetValue() != eStateRunning)
{
PlatformSP platform_sp = GetTarget().GetPlatform();
-
+
// FIXME: These should be ConstStrings so we aren't doing strcmp'ing.
if (platform_sp
&& platform_sp->GetName()
@@ -2656,18 +2772,18 @@ ProcessGDBRemote::DoDestroy ()
log->PutCString ("ProcessGDBRemote::DoDestroy() - Tried resuming to destroy once already, not doing it again.");
}
else
- {
+ {
// At present, the plans are discarded and the breakpoints disabled Process::Destroy,
// but we really need it to happen here and it doesn't matter if we do it twice.
m_thread_list.DiscardThreadPlans();
DisableAllBreakpointSites();
-
+
bool stop_looks_like_crash = false;
ThreadList &threads = GetThreadList();
-
+
{
Mutex::Locker locker(threads.GetMutex());
-
+
size_t num_threads = threads.GetSize();
for (size_t i = 0; i < num_threads; i++)
{
@@ -2688,21 +2804,21 @@ ProcessGDBRemote::DoDestroy ()
}
}
}
-
+
if (stop_looks_like_crash)
{
if (log)
log->PutCString ("ProcessGDBRemote::DoDestroy() - Stopped at a breakpoint, continue and then kill.");
m_destroy_tried_resuming = true;
-
- // If we are going to run again before killing, it would be good to suspend all the threads
+
+ // If we are going to run again before killing, it would be good to suspend all the threads
// before resuming so they won't get into more trouble. Sadly, for the threads stopped with
// the breakpoint or exception, the exception doesn't get cleared if it is suspended, so we do
// have to run the risk of letting those threads proceed a bit.
-
+
{
Mutex::Locker locker(threads.GetMutex());
-
+
size_t num_threads = threads.GetSize();
for (size_t i = 0; i < num_threads; i++)
{
@@ -2728,7 +2844,7 @@ ProcessGDBRemote::DoDestroy ()
}
}
#endif
-
+
// Interrupt if our inferior is running...
int exit_status = SIGABRT;
std::string exit_string;
@@ -2825,6 +2941,12 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
{
// Lock the thread stack while we access it
Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
+
+ // We are are not using non-stop mode, there can only be one last stop
+ // reply packet, so clear the list.
+ if (GetTarget().GetNonStopModeEnabled() == false)
+ m_stop_packet_stack.clear();
+
// Add this stop packet to the stop packet stack
// This stack will get popped and examined when we switch to the
// Stopped state
@@ -2832,6 +2954,11 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
}
}
+void
+ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp)
+{
+ Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp));
+}
//------------------------------------------------------------------
// Process Queries
@@ -2840,7 +2967,7 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
bool
ProcessGDBRemote::IsAlive ()
{
- return m_gdb_comm.IsConnected() && m_private_state.GetValue() != eStateExited;
+ return m_gdb_comm.IsConnected() && Process::IsAlive();
}
addr_t
@@ -2852,7 +2979,7 @@ ProcessGDBRemote::GetImageInfoAddress()
// the loaded module list can also provides a link map address
if (addr == LLDB_INVALID_ADDRESS)
{
- GDBLoadedModuleInfoList list;
+ LoadedModuleInfoList list;
if (GetLoadedModuleList (list).Success())
addr = list.m_link_map;
}
@@ -2860,6 +2987,35 @@ ProcessGDBRemote::GetImageInfoAddress()
return addr;
}
+void
+ProcessGDBRemote::WillPublicStop ()
+{
+ // See if the GDB remote client supports the JSON threads info.
+ // If so, we gather stop info for all threads, expedited registers,
+ // expedited memory, runtime queue information (iOS and MacOSX only),
+ // and more. Expediting memory will help stack backtracing be much
+ // faster. Expediting registers will make sure we don't have to read
+ // the thread registers for GPRs.
+ m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo();
+
+ if (m_jthreadsinfo_sp)
+ {
+ // Now set the stop info for each thread and also expedite any registers
+ // and memory that was in the jThreadsInfo response.
+ StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
+ if (thread_infos)
+ {
+ const size_t n = thread_infos->GetSize();
+ for (size_t i=0; i<n; ++i)
+ {
+ StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary();
+ if (thread_dict)
+ SetThreadStopInfo(thread_dict);
+ }
+ }
+ }
+}
+
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
@@ -2870,7 +3026,7 @@ ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &erro
if (size > m_max_memory_size)
{
// Keep memory read sizes down to a sane limit. This function will be
- // called multiple times in order to complete the task by
+ // called multiple times in order to complete the task by
// lldb_private::Process so it is ok to do this.
size = m_max_memory_size;
}
@@ -2878,14 +3034,8 @@ ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &erro
char packet[64];
int packet_len;
bool binary_memory_read = m_gdb_comm.GetxPacketSupported();
- if (binary_memory_read)
- {
- packet_len = ::snprintf (packet, sizeof(packet), "x0x%" PRIx64 ",0x%" PRIx64, (uint64_t)addr, (uint64_t)size);
- }
- else
- {
- packet_len = ::snprintf (packet, sizeof(packet), "m%" PRIx64 ",%" PRIx64, (uint64_t)addr, (uint64_t)size);
- }
+ packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64,
+ binary_memory_read ? 'x' : 'm', (uint64_t)addr, (uint64_t)size);
assert (packet_len + 1 < (int)sizeof(packet));
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true) == GDBRemoteCommunication::PacketResult::Success)
@@ -2934,14 +3084,14 @@ ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Erro
if (size > m_max_memory_size)
{
// Keep memory read sizes down to a sane limit. This function will be
- // called multiple times in order to complete the task by
+ // called multiple times in order to complete the task by
// lldb_private::Process so it is ok to do this.
size = m_max_memory_size;
}
StreamString packet;
packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
- packet.PutBytesAsRawHex8(buf, size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
+ packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), endian::InlHostByteOrder());
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true) == GDBRemoteCommunication::PacketResult::Success)
{
@@ -2969,7 +3119,7 @@ ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &er
{
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_EXPRESSIONS));
addr_t allocated_addr = LLDB_INVALID_ADDRESS;
-
+
LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();
switch (supported)
{
@@ -3000,7 +3150,7 @@ ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &er
}
break;
}
-
+
if (allocated_addr == LLDB_INVALID_ADDRESS)
error.SetErrorStringWithFormat("unable to allocate %" PRIu64 " bytes of memory with permissions %s", (uint64_t)size, GetPermissionsAsCString (permissions));
else
@@ -3009,10 +3159,10 @@ ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &er
}
Error
-ProcessGDBRemote::GetMemoryRegionInfo (addr_t load_addr,
+ProcessGDBRemote::GetMemoryRegionInfo (addr_t load_addr,
MemoryRegionInfo &region_info)
{
-
+
Error error (m_gdb_comm.GetMemoryRegionInfo (load_addr, region_info));
return error;
}
@@ -3020,7 +3170,7 @@ ProcessGDBRemote::GetMemoryRegionInfo (addr_t load_addr,
Error
ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num)
{
-
+
Error error (m_gdb_comm.GetWatchpointSupportInfo (num));
return error;
}
@@ -3035,13 +3185,13 @@ ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num, bool& after)
Error
ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr)
{
- Error error;
+ Error error;
LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();
switch (supported)
{
case eLazyBoolCalculate:
- // We should never be deallocating memory without allocating memory
+ // We should never be deallocating memory without allocating memory
// first so we should never get eLazyBoolCalculate
error.SetErrorString ("tried to deallocate memory without ever allocating memory");
break;
@@ -3050,7 +3200,7 @@ ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr)
if (!m_gdb_comm.DeallocateMemory (addr))
error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
break;
-
+
case eLazyBoolNo:
// Call munmap() to deallocate memory in the inferior..
{
@@ -3226,7 +3376,7 @@ ProcessGDBRemote::DisableBreakpointSite (BreakpointSite *bp_site)
stoppoint_type = eBreakpointHardware;
else
stoppoint_type = eBreakpointSoftware;
-
+
if (m_gdb_comm.SendGDBStoppointTypePacket(stoppoint_type, false, addr, bp_op_size))
error.SetErrorToGenericError();
}
@@ -3332,7 +3482,7 @@ ProcessGDBRemote::DisableWatchpoint (Watchpoint *wp, bool notify)
wp->SetEnabled(false, notify);
return error;
}
-
+
if (wp->IsHardware())
{
GDBStoppointType type = GetGDBStoppointType(wp);
@@ -3343,7 +3493,7 @@ ProcessGDBRemote::DisableWatchpoint (Watchpoint *wp, bool notify)
return error;
}
else
- error.SetErrorString("sending gdb watchpoint packet failed");
+ error.SetErrorString("sending gdb watchpoint packet failed");
}
// TODO: clear software watchpoints if we implement them
}
@@ -3378,6 +3528,27 @@ ProcessGDBRemote::DoSignal (int signo)
}
Error
+ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info)
+{
+ // Make sure we aren't already connected?
+ if (m_gdb_comm.IsConnected())
+ return Error();
+
+ PlatformSP platform_sp (GetTarget ().GetPlatform ());
+ if (platform_sp && !platform_sp->IsHost ())
+ return Error("Lost debug server connection");
+
+ auto error = LaunchAndConnectToDebugserver (process_info);
+ if (error.Fail())
+ {
+ const char *error_string = error.AsCString();
+ if (error_string == nullptr)
+ error_string = "unable to launch " DEBUGSERVER_BASENAME;
+ }
+ return error;
+}
+
+Error
ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info)
{
Error error;
@@ -3402,14 +3573,22 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
// Set hostname being NULL to do the reverse connect where debugserver
// will bind to port zero and it will communicate back to us the port
// that we will connect to
- const char *hostname = NULL;
+ const char *hostname = nullptr;
uint16_t port = 0;
#endif
- error = m_gdb_comm.StartDebugserverProcess (hostname,
- port,
+ StreamString url_str;
+ const char* url = nullptr;
+ if (hostname != nullptr)
+ {
+ url_str.Printf("%s:%u", hostname, port);
+ url = url_str.GetData();
+ }
+
+ error = m_gdb_comm.StartDebugserverProcess (url,
+ GetTarget().GetPlatform().get(),
debugserver_launch_info,
- port);
+ &port);
if (error.Success ())
m_debugserver_pid = debugserver_launch_info.GetProcessID();
@@ -3418,7 +3597,7 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
StartAsyncThread ();
-
+
if (error.Fail())
{
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
@@ -3427,7 +3606,7 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
log->Printf("failed to start debugserver process: %s", error.AsCString());
return error;
}
-
+
if (m_gdb_comm.IsConnected())
{
// Finish the connection process by doing the handshake without connecting (send NULL URL)
@@ -3457,7 +3636,7 @@ ProcessGDBRemote::MonitorDebugserverProcess
// The baton is a "ProcessGDBRemote *". Now this class might be gone
// and might not exist anymore, so we need to carefully try to get the
// target for this process first since we have a race condition when
- // we are done running between getting the notice that the inferior
+ // we are done running between getting the notice that the inferior
// process has died and the debugserver that was debugging this process.
// In our test suite, we are also continually running process after
// process, so we must be very careful to make sure:
@@ -3487,7 +3666,7 @@ ProcessGDBRemote::MonitorDebugserverProcess
ProcessSP process_sp (target_sp->GetProcessSP());
// Now we have a shared pointer to the process that can't go away on us
// so we now make sure it was the same as the one passed in, and also make
- // sure that our previous "process *" didn't get deleted and have a new
+ // sure that our previous "process *" didn't get deleted and have a new
// "process *" created in its place with the same pointer. To verify this
// we make sure the process has our debugserver process ID. If we pass all
// of these tests, then we are sure that this process is the one we were
@@ -3501,7 +3680,7 @@ ProcessGDBRemote::MonitorDebugserverProcess
// If our process hasn't yet exited, debugserver might have died.
// If the process did exit, the we are reaping it.
const StateType state = process->GetState();
-
+
if (process->m_debugserver_pid != LLDB_INVALID_PROCESS_ID &&
state != eStateInvalid &&
state != eStateUnloaded &&
@@ -3577,7 +3756,7 @@ ProcessGDBRemote::StartAsyncThread ()
if (log)
log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
-
+
Mutex::Locker start_locker(m_async_thread_state_mutex);
if (!m_async_thread.IsJoinable())
{
@@ -3604,7 +3783,7 @@ ProcessGDBRemote::StopAsyncThread ()
if (m_async_thread.IsJoinable())
{
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
-
+
// This will shut down the async thread.
m_gdb_comm.Disconnect(); // Disconnect from the debug server.
@@ -3654,164 +3833,174 @@ ProcessGDBRemote::AsyncThread (void *arg)
if (log)
log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, arg, process->GetID());
- Listener listener ("ProcessGDBRemote::AsyncThread");
EventSP event_sp;
- const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
- eBroadcastBitAsyncThreadShouldExit;
-
- if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
+ bool done = false;
+ while (!done)
{
- listener.StartListeningForEvents (&process->m_gdb_comm, Communication::eBroadcastBitReadThreadDidExit |
- GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify);
-
- bool done = false;
- while (!done)
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
+ if (process->m_async_listener.WaitForEvent (NULL, event_sp))
{
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
- if (listener.WaitForEvent (NULL, event_sp))
+ const uint32_t event_type = event_sp->GetType();
+ if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
{
- const uint32_t event_type = event_sp->GetType();
- if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
+
+ switch (event_type)
{
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
+ case eBroadcastBitAsyncContinue:
+ {
+ const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
- switch (event_type)
- {
- case eBroadcastBitAsyncContinue:
+ if (continue_packet)
{
- const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
+ const char *continue_cstr = (const char *)continue_packet->GetBytes ();
+ const size_t continue_cstr_len = continue_packet->GetByteSize ();
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
- if (continue_packet)
+ if (::strstr (continue_cstr, "vAttach") == NULL)
+ process->SetPrivateState(eStateRunning);
+ StringExtractorGDBRemote response;
+
+ // If in Non-Stop-Mode
+ if (process->GetTarget().GetNonStopModeEnabled())
{
- const char *continue_cstr = (const char *)continue_packet->GetBytes ();
- const size_t continue_cstr_len = continue_packet->GetByteSize ();
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
-
- if (::strstr (continue_cstr, "vAttach") == NULL)
- process->SetPrivateState(eStateRunning);
- StringExtractorGDBRemote response;
-
- // If in Non-Stop-Mode
- if (process->GetTarget().GetNonStopModeEnabled())
+ // send the vCont packet
+ if (!process->GetGDBRemote().SendvContPacket(process, continue_cstr, continue_cstr_len, response))
{
- // send the vCont packet
- if (!process->GetGDBRemote().SendvContPacket(process, continue_cstr, continue_cstr_len, response))
- {
- // Something went wrong
- done = true;
- break;
- }
+ // Something went wrong
+ done = true;
+ break;
}
- // If in All-Stop-Mode
- else
- {
- StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
+ }
+ // If in All-Stop-Mode
+ else
+ {
+ StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
- // We need to immediately clear the thread ID list so we are sure to get a valid list of threads.
- // The thread ID list might be contained within the "response", or the stop reply packet that
- // caused the stop. So clear it now before we give the stop reply packet to the process
- // using the process->SetLastStopPacket()...
- process->ClearThreadIDList ();
+ // We need to immediately clear the thread ID list so we are sure to get a valid list of threads.
+ // The thread ID list might be contained within the "response", or the stop reply packet that
+ // caused the stop. So clear it now before we give the stop reply packet to the process
+ // using the process->SetLastStopPacket()...
+ process->ClearThreadIDList ();
- switch (stop_state)
- {
- case eStateStopped:
- case eStateCrashed:
- case eStateSuspended:
- process->SetLastStopPacket (response);
- process->SetPrivateState (stop_state);
- break;
-
- case eStateExited:
+ switch (stop_state)
+ {
+ case eStateStopped:
+ case eStateCrashed:
+ case eStateSuspended:
+ process->SetLastStopPacket (response);
+ process->SetPrivateState (stop_state);
+ break;
+
+ case eStateExited:
+ {
+ process->SetLastStopPacket (response);
+ process->ClearThreadIDList();
+ response.SetFilePos(1);
+
+ int exit_status = response.GetHexU8();
+ const char *desc_cstr = NULL;
+ StringExtractor extractor;
+ std::string desc_string;
+ if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';')
{
- process->SetLastStopPacket (response);
- process->ClearThreadIDList();
- response.SetFilePos(1);
-
- int exit_status = response.GetHexU8();
- const char *desc_cstr = NULL;
- StringExtractor extractor;
- std::string desc_string;
- if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';')
+ std::string desc_token;
+ while (response.GetNameColonValue (desc_token, desc_string))
{
- std::string desc_token;
- while (response.GetNameColonValue (desc_token, desc_string))
+ if (desc_token == "description")
{
- if (desc_token == "description")
- {
- extractor.GetStringRef().swap(desc_string);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (desc_string);
- desc_cstr = desc_string.c_str();
- }
+ extractor.GetStringRef().swap(desc_string);
+ extractor.SetFilePos(0);
+ extractor.GetHexByteString (desc_string);
+ desc_cstr = desc_string.c_str();
}
}
- process->SetExitStatus(exit_status, desc_cstr);
- done = true;
- break;
}
- case eStateInvalid:
+ process->SetExitStatus(exit_status, desc_cstr);
+ done = true;
+ break;
+ }
+ case eStateInvalid:
+ {
+ // Check to see if we were trying to attach and if we got back
+ // the "E87" error code from debugserver -- this indicates that
+ // the process is not debuggable. Return a slightly more helpful
+ // error message about why the attach failed.
+ if (::strstr (continue_cstr, "vAttach") != NULL
+ && response.GetError() == 0x87)
+ {
+ process->SetExitStatus(-1, "cannot attach to process due to System Integrity Protection");
+ }
+ // E01 code from vAttach means that the attach failed
+ if (::strstr (continue_cstr, "vAttach") != NULL
+ && response.GetError() == 0x1)
+ {
+ process->SetExitStatus(-1, "unable to attach");
+ }
+ else
+ {
process->SetExitStatus(-1, "lost connection");
+ }
break;
+ }
- default:
- process->SetPrivateState (stop_state);
- break;
- } // switch(stop_state)
- } // else // if in All-stop-mode
- } // if (continue_packet)
- } // case eBroadcastBitAysncContinue
- break;
+ default:
+ process->SetPrivateState (stop_state);
+ break;
+ } // switch(stop_state)
+ } // else // if in All-stop-mode
+ } // if (continue_packet)
+ } // case eBroadcastBitAysncContinue
+ break;
- case eBroadcastBitAsyncThreadShouldExit:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
- done = true;
- break;
+ case eBroadcastBitAsyncThreadShouldExit:
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
+ done = true;
+ break;
- default:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
- done = true;
- break;
- }
+ default:
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
+ done = true;
+ break;
}
- else if (event_sp->BroadcasterIs (&process->m_gdb_comm))
+ }
+ else if (event_sp->BroadcasterIs (&process->m_gdb_comm))
+ {
+ switch (event_type)
{
- switch (event_type)
- {
- case Communication::eBroadcastBitReadThreadDidExit:
- process->SetExitStatus (-1, "lost connection");
- done = true;
- break;
-
- case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify:
- {
- lldb_private::Event *event = event_sp.get();
- const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event);
- StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes());
- // Hand this over to the process to handle
- process->HandleNotifyPacket(notify);
- break;
- }
+ case Communication::eBroadcastBitReadThreadDidExit:
+ process->SetExitStatus (-1, "lost connection");
+ done = true;
+ break;
- default:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
- done = true;
- break;
+ case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify:
+ {
+ lldb_private::Event *event = event_sp.get();
+ const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event);
+ StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes());
+ // Hand this over to the process to handle
+ process->HandleNotifyPacket(notify);
+ break;
}
+
+ default:
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
+ done = true;
+ break;
}
}
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
- done = true;
- }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
+ done = true;
}
}
@@ -3830,7 +4019,7 @@ ProcessGDBRemote::AsyncThread (void *arg)
// {
// return Host::ListProcessesMatchingName (name, matches, pids);
// }
-// else
+// else
// {
// // FIXME: Implement talking to the remote debugserver.
// return 0;
@@ -3844,7 +4033,7 @@ ProcessGDBRemote::NewThreadNotifyBreakpointHit (void *baton,
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id)
{
- // I don't think I have to do anything here, just make sure I notice the new thread when it starts to
+ // I don't think I have to do anything here, just make sure I notice the new thread when it starts to
// run so I can stop it if that's what I want to do.
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
@@ -3865,10 +4054,10 @@ ProcessGDBRemote::StartNoticingNewThreads()
}
else
{
- PlatformSP platform_sp (m_target.GetPlatform());
+ PlatformSP platform_sp (GetTarget().GetPlatform());
if (platform_sp)
{
- m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(m_target);
+ m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(GetTarget());
if (m_thread_create_bp_sp)
{
if (log && log->GetVerbose())
@@ -3887,7 +4076,7 @@ ProcessGDBRemote::StartNoticingNewThreads()
bool
ProcessGDBRemote::StopNoticingNewThreads()
-{
+{
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log && log->GetVerbose())
log->Printf ("Disabling new thread notification breakpoint.");
@@ -3897,7 +4086,7 @@ ProcessGDBRemote::StopNoticingNewThreads()
return true;
}
-
+
DynamicLoader *
ProcessGDBRemote::GetDynamicLoader ()
{
@@ -3911,9 +4100,9 @@ ProcessGDBRemote::SendEventData(const char *data)
{
int return_value;
bool was_supported;
-
+
Error error;
-
+
return_value = m_gdb_comm.SendLaunchEventDataPacket (data, &was_supported);
if (return_value != 0)
{
@@ -3987,6 +4176,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres
if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported())
{
+ // Scope for the scoped timeout object
+ GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10);
+
StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address);
args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count);
@@ -4010,8 +4202,6 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres
{
if (!response.Empty())
{
- // The packet has already had the 0x7d xor quoting stripped out at the
- // GDBRemoteCommunication packet receive level.
object_sp = StructuredData::ParseJSON (response.GetStringRef());
}
}
@@ -4020,11 +4210,10 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres
return object_sp;
}
-
// Establish the largest memory read/write payloads we should use.
// If the remote stub has a max packet size, stay under that size.
-//
-// If the remote stub's max packet size is crazy large, use a
+//
+// If the remote stub's max packet size is crazy large, use a
// reasonable largeish default.
//
// If the remote stub doesn't advertise a max packet size, use a
@@ -4114,6 +4303,18 @@ ProcessGDBRemote::GetModuleSpec(const FileSpec& module_file_spec,
return true;
}
+bool
+ProcessGDBRemote::GetHostOSVersion(uint32_t &major,
+ uint32_t &minor,
+ uint32_t &update)
+{
+ if (m_gdb_comm.GetOSVersion(major, minor, update))
+ return true;
+ // We failed to get the host OS version, defer to the base
+ // implementation to correctly invalidate the arguments.
+ return Process::GetHostOSVersion(major, minor, update);
+}
+
namespace {
typedef std::vector<std::string> stringVec;
@@ -4125,7 +4326,7 @@ struct RegisterSetInfo
};
typedef std::map<uint32_t, RegisterSetInfo> RegisterSetMap;
-
+
struct GdbServerTargetInfo
{
std::string arch;
@@ -4134,17 +4335,17 @@ struct GdbServerTargetInfo
RegisterSetMap reg_set_map;
XMLNode feature_node;
};
-
+
bool
-ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info)
+ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp)
{
if (!feature_node)
return false;
-
- uint32_t prev_reg_num = 0;
+
+ uint32_t cur_reg_num = 0;
uint32_t reg_offset = 0;
- feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &prev_reg_num, &reg_offset](const XMLNode &reg_node) -> bool {
+ feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &cur_reg_num, &reg_offset, &abi_sp](const XMLNode &reg_node) -> bool {
std::string gdb_group;
std::string gdb_type;
ConstString reg_name;
@@ -4159,19 +4360,19 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
0, // byte size
reg_offset, // offset
eEncodingUint, // encoding
- eFormatHex, // formate
+ eFormatHex, // format
{
- LLDB_INVALID_REGNUM, // GCC reg num
+ LLDB_INVALID_REGNUM, // eh_frame reg num
LLDB_INVALID_REGNUM, // DWARF reg num
LLDB_INVALID_REGNUM, // generic reg num
- prev_reg_num, // GDB reg num
- prev_reg_num // native register number
+ cur_reg_num, // process plugin reg num
+ cur_reg_num // native register number
},
NULL,
NULL
};
-
- reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, &reg_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, &reg_info, &prev_reg_num, &reg_offset](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
+
+ reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, &reg_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, &reg_info, &cur_reg_num, &reg_offset](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
if (name == "name")
{
reg_name.SetString(value);
@@ -4193,9 +4394,7 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
const uint32_t regnum = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
if (regnum != LLDB_INVALID_REGNUM)
{
- reg_info.kinds[eRegisterKindGDB] = regnum;
- reg_info.kinds[eRegisterKindLLDB] = regnum;
- prev_reg_num = regnum;
+ reg_info.kinds[eRegisterKindProcessPlugin] = regnum;
}
}
else if (name == "offset")
@@ -4241,9 +4440,9 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
if (pos != target_info.reg_set_map.end())
set_name = pos->second.name;
}
- else if (name == "gcc_regnum")
+ else if (name == "gcc_regnum" || name == "ehframe_regnum")
{
- reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
+ reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
}
else if (name == "dwarf_regnum")
{
@@ -4267,7 +4466,7 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
}
return true; // Keep iterating through all attributes
});
-
+
if (!gdb_type.empty() && !(encoding_set || format_set))
{
if (gdb_type.find("int") == 0)
@@ -4286,12 +4485,12 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
reg_info.encoding = eEncodingIEEE754;
}
}
-
+
// Only update the register set name if we didn't get a "reg_set" attribute.
// "set_name" will be empty if we didn't have a "reg_set" attribute.
if (!set_name && !gdb_group.empty())
set_name.SetCString(gdb_group.c_str());
-
+
reg_info.byte_offset = reg_offset;
assert (reg_info.byte_size != 0);
reg_offset += reg_info.byte_size;
@@ -4305,15 +4504,16 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
invalidate_regs.push_back(LLDB_INVALID_REGNUM);
reg_info.invalidate_regs = invalidate_regs.data();
}
-
- ++prev_reg_num;
+
+ ++cur_reg_num;
+ AugmentRegisterInfoViaABI (reg_info, reg_name, abi_sp);
dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);
-
+
return true; // Keep iterating through all "reg" elements
});
return true;
}
-
+
} // namespace {}
@@ -4345,14 +4545,14 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
{
return false;
}
-
+
XMLDocument xml_document;
if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml"))
{
GdbServerTargetInfo target_info;
-
+
XMLNode target_node = xml_document.GetRootElement("target");
if (target_node)
{
@@ -4383,7 +4583,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
node.ForEachChildElementWithName("group", [&target_info](const XMLNode &node) -> bool {
uint32_t set_id = UINT32_MAX;
RegisterSetInfo set_info;
-
+
node.ForEachAttribute([&set_id, &set_info](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
if (name == "id")
set_id = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
@@ -4391,7 +4591,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
set_info.name = ConstString(value);
return true; // Keep iterating through all attributes
});
-
+
if (set_id != UINT32_MAX)
target_info.reg_set_map[set_id] = set_info;
return true; // Keep iterating through all "group" elements
@@ -4399,12 +4599,12 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
}
return true; // Keep iterating through all children of the target_node
});
-
+
if (feature_node)
{
- ParseRegisters(feature_node, target_info, this->m_register_info);
+ ParseRegisters(feature_node, target_info, this->m_register_info, GetABI());
}
-
+
for (const auto &include : target_info.includes)
{
// request register file
@@ -4420,7 +4620,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
XMLNode include_feature_node = include_xml_document.GetRootElement("feature");
if (include_feature_node)
{
- ParseRegisters(include_feature_node, target_info, this->m_register_info);
+ ParseRegisters(include_feature_node, target_info, this->m_register_info, GetABI());
}
}
this->m_register_info.Finalize(GetTarget().GetArchitecture());
@@ -4431,7 +4631,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
}
Error
-ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
+ProcessGDBRemote::GetLoadedModuleList (LoadedModuleInfoList & list)
{
// Make sure LLDB has an XML parser it can use first
if (!XMLDocument::XMLEnabled())
@@ -4458,7 +4658,7 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
if (log)
log->Printf ("parsing: %s", raw.c_str());
XMLDocument doc;
-
+
if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
return Error (0, ErrorType::eErrorTypeGeneric);
@@ -4475,10 +4675,10 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
- GDBLoadedModuleInfoList::LoadedModuleInfo module;
+ LoadedModuleInfoList::LoadedModuleInfo module;
library.ForEachAttribute([log, &module](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
-
+
if (name == "name")
module.set_name (value.str());
else if (name == "lm")
@@ -4490,14 +4690,15 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
{
// the displacement as read from the field 'l_addr' of the link_map struct.
module.set_base(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
-
+ // base address is always a displacement, not an absolute value.
+ module.set_base_is_offset(true);
}
else if (name == "l_ld")
{
// the memory address of the libraries PT_DYAMIC section.
module.set_dynamic(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
}
-
+
return true; // Keep iterating over all properties of "library"
});
@@ -4505,13 +4706,15 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
{
std::string name;
lldb::addr_t lm=0, base=0, ld=0;
+ bool base_is_offset;
module.get_name (name);
module.get_link_map (lm);
module.get_base (base);
+ module.get_base_is_offset (base_is_offset);
module.get_dynamic (ld);
- log->Printf ("found (link_map:0x08%" PRIx64 ", base:0x08%" PRIx64 ", ld:0x08%" PRIx64 ", name:'%s')", lm, base, ld, name.c_str());
+ log->Printf ("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 "[%s], ld:0x%08" PRIx64 ", name:'%s')", lm, base, (base_is_offset ? "offset" : "absolute"), ld, name.c_str());
}
list.add (module);
@@ -4542,7 +4745,7 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
return Error();
root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
- GDBLoadedModuleInfoList::LoadedModuleInfo module;
+ LoadedModuleInfoList::LoadedModuleInfo module;
llvm::StringRef name = library.GetAttributeValue("name");
module.set_name(name.str());
@@ -4553,15 +4756,19 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
const XMLNode &section = library.FindFirstChildElementWithName("section");
llvm::StringRef address = section.GetAttributeValue("address");
module.set_base(StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0));
+ // These addresses are absolute values.
+ module.set_base_is_offset(false);
if (log)
{
std::string name;
lldb::addr_t base = 0;
+ bool base_is_offset;
module.get_name (name);
module.get_base (base);
+ module.get_base_is_offset (base_is_offset);
- log->Printf ("found (base:0x%" PRIx64 ", name:'%s')", base, name.c_str());
+ log->Printf ("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, (base_is_offset ? "offset" : "absolute"), name.c_str());
}
list.add (module);
@@ -4578,7 +4785,7 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
}
lldb::ModuleSP
-ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr)
+ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset)
{
Target &target = m_process->GetTarget();
ModuleList &modules = target.GetImages();
@@ -4589,37 +4796,38 @@ ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_a
ModuleSpec module_spec (file, target.GetArchitecture());
if ((module_sp = modules.FindFirstModule (module_spec)))
{
- module_sp->SetLoadAddress (target, base_addr, true, changed);
+ module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed);
}
else if ((module_sp = target.GetSharedModule (module_spec)))
{
- module_sp->SetLoadAddress (target, base_addr, true, changed);
+ module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed);
}
return module_sp;
}
size_t
-ProcessGDBRemote::LoadModules ()
+ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list)
{
using lldb_private::process_gdb_remote::ProcessGDBRemote;
// request a list of loaded libraries from GDBServer
- GDBLoadedModuleInfoList module_list;
if (GetLoadedModuleList (module_list).Fail())
return 0;
// get a list of all the modules
ModuleList new_modules;
- for (GDBLoadedModuleInfoList::LoadedModuleInfo & modInfo : module_list.m_list)
+ for (LoadedModuleInfoList::LoadedModuleInfo & modInfo : module_list.m_list)
{
std::string mod_name;
lldb::addr_t mod_base;
+ bool mod_base_is_offset;
bool valid = true;
valid &= modInfo.get_name (mod_name);
valid &= modInfo.get_base (mod_base);
+ valid &= modInfo.get_base_is_offset (mod_base_is_offset);
if (!valid)
continue;
@@ -4631,7 +4839,7 @@ ProcessGDBRemote::LoadModules ()
marker += 1;
FileSpec file (mod_name.c_str()+marker, true);
- lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base);
+ lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base, mod_base_is_offset);
if (module_sp.get())
new_modules.Append (module_sp);
@@ -4639,7 +4847,7 @@ ProcessGDBRemote::LoadModules ()
if (new_modules.GetSize() > 0)
{
- Target & target = m_target;
+ Target &target = GetTarget();
new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) -> bool
{
@@ -4661,6 +4869,14 @@ ProcessGDBRemote::LoadModules ()
}
return new_modules.GetSize();
+
+}
+
+size_t
+ProcessGDBRemote::LoadModules ()
+{
+ LoadedModuleInfoList module_list;
+ return LoadModules (module_list);
}
Error
@@ -4794,7 +5010,7 @@ protected:
class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed
{
private:
-
+
public:
CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
@@ -4803,11 +5019,11 @@ public:
NULL)
{
}
-
+
~CommandObjectProcessGDBRemotePacketHistory ()
{
}
-
+
bool
DoExecute (Args& command, CommandReturnObject &result) override
{
@@ -4834,7 +5050,7 @@ public:
class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed
{
private:
-
+
public:
CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
@@ -4843,11 +5059,11 @@ public:
NULL)
{
}
-
+
~CommandObjectProcessGDBRemotePacketXferSize ()
{
}
-
+
bool
DoExecute (Args& command, CommandReturnObject &result) override
{
@@ -4881,7 +5097,7 @@ public:
class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed
{
private:
-
+
public:
CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
@@ -4891,11 +5107,11 @@ public:
NULL)
{
}
-
+
~CommandObjectProcessGDBRemotePacketSend ()
{
}
-
+
bool
DoExecute (Args& command, CommandReturnObject &result) override
{
@@ -4906,7 +5122,7 @@ public:
result.SetStatus (eReturnStatusFailed);
return false;
}
-
+
ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
if (process)
{
@@ -4920,7 +5136,7 @@ public:
Stream &output_strm = result.GetOutputStream();
output_strm.Printf (" packet: %s\n", packet_cstr);
std::string &response_str = response.GetStringRef();
-
+
if (strstr(packet_cstr, "qGetProfileData") != NULL)
{
response_str = process->GetGDBRemote().HarmonizeThreadIdsForProfileData(process, response);
@@ -4939,7 +5155,7 @@ public:
class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw
{
private:
-
+
public:
CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter) :
CommandObjectRaw (interpreter,
@@ -4949,11 +5165,11 @@ public:
NULL)
{
}
-
+
~CommandObjectProcessGDBRemotePacketMonitor ()
{
}
-
+
bool
DoExecute (const char *command, CommandReturnObject &result) override
{
@@ -4963,7 +5179,7 @@ public:
result.SetStatus (eReturnStatusFailed);
return false;
}
-
+
ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
if (process)
{
@@ -4971,7 +5187,7 @@ public:
packet.PutCString("qRcmd,");
packet.PutBytesAsRawHex8(command, strlen(command));
const char *packet_cstr = packet.GetString().c_str();
-
+
bool send_async = true;
StringExtractorGDBRemote response;
process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async);
@@ -4979,7 +5195,7 @@ public:
Stream &output_strm = result.GetOutputStream();
output_strm.Printf (" packet: %s\n", packet_cstr);
const std::string &response_str = response.GetStringRef();
-
+
if (response_str.empty())
output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n");
else
@@ -4992,7 +5208,7 @@ public:
class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword
{
private:
-
+
public:
CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) :
CommandObjectMultiword (interpreter,
@@ -5006,10 +5222,10 @@ public:
LoadSubCommand ("xfer-size", CommandObjectSP (new CommandObjectProcessGDBRemotePacketXferSize (interpreter)));
LoadSubCommand ("speed-test", CommandObjectSP (new CommandObjectProcessGDBRemoteSpeedTest (interpreter)));
}
-
+
~CommandObjectProcessGDBRemotePacket ()
{
- }
+ }
};
class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 45c74ea..b48edd8 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -11,12 +11,14 @@
#define liblldb_ProcessGDBRemote_h_
// C Includes
-
// C++ Includes
-#include <list>
+#include <atomic>
+#include <map>
+#include <string>
#include <vector>
// Other libraries and framework includes
+// Project includes
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/ConstString.h"
@@ -25,6 +27,7 @@
#include "lldb/Core/StringList.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/ThreadSafeValue.h"
+#include "lldb/Core/LoadedModuleInfoList.h"
#include "lldb/Host/HostThread.h"
#include "lldb/lldb-private-forward.h"
#include "lldb/Utility/StringExtractor.h"
@@ -42,11 +45,12 @@ class ThreadGDBRemote;
class ProcessGDBRemote : public Process
{
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
+ ProcessGDBRemote(lldb::TargetSP target_sp, Listener &listener);
+
+ ~ProcessGDBRemote() override;
+
static lldb::ProcessSP
- CreateInstance (Target& target,
+ CreateInstance (lldb::TargetSP target_sp,
Listener &listener,
const FileSpec *crash_file_path);
@@ -66,18 +70,10 @@ public:
GetPluginDescriptionStatic();
//------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- ProcessGDBRemote(Target& target, Listener &listener);
-
- virtual
- ~ProcessGDBRemote();
-
- //------------------------------------------------------------------
// Check if a given Process
//------------------------------------------------------------------
bool
- CanDebug (Target &target, bool plugin_specified_by_name) override;
+ CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name) override;
CommandObject *
GetPluginCommandObject() override;
@@ -152,6 +148,9 @@ public:
void
RefreshStateAfterStop() override;
+ void
+ SetUnixSignals(const lldb::UnixSignalsSP &signals_sp);
+
//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------
@@ -161,6 +160,9 @@ public:
lldb::addr_t
GetImageInfoAddress() override;
+ void
+ WillPublicStop () override;
+
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
@@ -238,6 +240,14 @@ public:
const ArchSpec& arch,
ModuleSpec &module_spec) override;
+ bool
+ GetHostOSVersion(uint32_t &major,
+ uint32_t &minor,
+ uint32_t &update) override;
+
+ size_t
+ LoadModules(LoadedModuleInfoList &module_list) override;
+
size_t
LoadModules() override;
@@ -255,7 +265,47 @@ protected:
friend class GDBRemoteCommunicationClient;
friend class GDBRemoteRegisterContext;
- class GDBLoadedModuleInfoList;
+ //------------------------------------------------------------------
+ /// Broadcaster event bits definitions.
+ //------------------------------------------------------------------
+ enum
+ {
+ eBroadcastBitAsyncContinue = (1 << 0),
+ eBroadcastBitAsyncThreadShouldExit = (1 << 1),
+ eBroadcastBitAsyncThreadDidExit = (1 << 2)
+ };
+
+ Flags m_flags; // Process specific flags (see eFlags enums)
+ GDBRemoteCommunicationClient m_gdb_comm;
+ std::atomic<lldb::pid_t> m_debugserver_pid;
+ std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet stack replaces the last stop packet variable
+ Mutex m_last_stop_packet_mutex;
+ GDBRemoteDynamicRegisterInfo m_register_info;
+ Broadcaster m_async_broadcaster;
+ Listener m_async_listener;
+ HostThread m_async_thread;
+ Mutex m_async_thread_state_mutex;
+ typedef std::vector<lldb::tid_t> tid_collection;
+ typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
+ typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
+ typedef std::map<uint32_t, std::string> ExpeditedRegisterMap;
+ tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping
+ std::vector<lldb::addr_t> m_thread_pcs; // PC values for all the threads.
+ StructuredData::ObjectSP m_jstopinfo_sp; // Stop info only for any threads that have valid stop infos
+ StructuredData::ObjectSP m_jthreadsinfo_sp; // Full stop info, expedited registers and memory for all threads if "jThreadsInfo" packet is supported
+ tid_collection m_continue_c_tids; // 'c' for continue
+ tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
+ tid_collection m_continue_s_tids; // 's' for step
+ tid_sig_collection m_continue_S_tids; // 'S' for step with signal
+ uint64_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
+ uint64_t m_remote_stub_max_memory_size; // The maximum memory size the remote gdb stub can handle
+ MMapMap m_addr_to_mmap_size;
+ lldb::BreakpointSP m_thread_create_bp_sp;
+ bool m_waiting_for_attach;
+ bool m_destroy_tried_resuming;
+ lldb::CommandObjectSP m_command_sp;
+ int64_t m_breakpoint_pc_offset;
+ lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
//----------------------------------------------------------------------
// Accessors
@@ -263,14 +313,15 @@ protected:
bool
IsRunning ( lldb::StateType state )
{
- return state == lldb::eStateRunning || IsStepping(state);
+ return state == lldb::eStateRunning || IsStepping(state);
}
bool
IsStepping ( lldb::StateType state)
{
- return state == lldb::eStateStepping;
+ return state == lldb::eStateStepping;
}
+
bool
CanResume ( lldb::StateType state)
{
@@ -306,6 +357,9 @@ protected:
ThreadList &new_thread_list) override;
Error
+ EstablishConnectionIfNeeded (const ProcessInfo &process_info);
+
+ Error
LaunchAndConnectToDebugserver (const ProcessInfo &process_info);
void
@@ -333,46 +387,10 @@ protected:
CalculateThreadStopInfo (ThreadGDBRemote *thread);
size_t
- UpdateThreadIDsFromStopReplyThreadsValue (std::string &value);
+ UpdateThreadPCsFromStopReplyThreadsValue (std::string &value);
- //------------------------------------------------------------------
- /// Broadcaster event bits definitions.
- //------------------------------------------------------------------
- enum
- {
- eBroadcastBitAsyncContinue = (1 << 0),
- eBroadcastBitAsyncThreadShouldExit = (1 << 1),
- eBroadcastBitAsyncThreadDidExit = (1 << 2)
- };
-
- Flags m_flags; // Process specific flags (see eFlags enums)
- GDBRemoteCommunicationClient m_gdb_comm;
- std::atomic<lldb::pid_t> m_debugserver_pid;
- std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet stack replaces the last stop packet variable
- Mutex m_last_stop_packet_mutex;
- GDBRemoteDynamicRegisterInfo m_register_info;
- Broadcaster m_async_broadcaster;
- HostThread m_async_thread;
- Mutex m_async_thread_state_mutex;
- typedef std::vector<lldb::tid_t> tid_collection;
- typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
- typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
- typedef std::map<uint32_t, std::string> ExpeditedRegisterMap;
- tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping
- StructuredData::ObjectSP m_threads_info_sp; // Stop info for all threads if "jThreadsInfo" packet is supported
- tid_collection m_continue_c_tids; // 'c' for continue
- tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
- tid_collection m_continue_s_tids; // 's' for step
- tid_sig_collection m_continue_S_tids; // 'S' for step with signal
- uint64_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
- uint64_t m_remote_stub_max_memory_size; // The maximum memory size the remote gdb stub can handle
- MMapMap m_addr_to_mmap_size;
- lldb::BreakpointSP m_thread_create_bp_sp;
- bool m_waiting_for_attach;
- bool m_destroy_tried_resuming;
- lldb::CommandObjectSP m_command_sp;
- int64_t m_breakpoint_pc_offset;
- lldb::tid_t m_initial_tid; // The inital thread ID, given by stub on attach
+ size_t
+ UpdateThreadIDsFromStopReplyThreadsValue (std::string &value);
bool
HandleNotifyPacket(StringExtractorGDBRemote &packet);
@@ -396,7 +414,10 @@ protected:
lldb::StateType
SetThreadStopInfo (StringExtractor& stop_packet);
- lldb::StateType
+ bool
+ GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp);
+
+ lldb::ThreadSP
SetThreadStopInfo (StructuredData::Dictionary *thread_dict);
lldb::ThreadSP
@@ -410,6 +431,8 @@ protected:
const std::vector<lldb::addr_t> &exc_data,
lldb::addr_t thread_dispatch_qaddr,
bool queue_vars_valid,
+ lldb_private::LazyBool associated_with_libdispatch_queue,
+ lldb::addr_t dispatch_queue_t,
std::string &queue_name,
lldb::QueueKind queue_kind,
uint64_t queue_serial);
@@ -442,10 +465,10 @@ protected:
// Query remote GDBServer for a detailed loaded library list
Error
- GetLoadedModuleList (GDBLoadedModuleInfoList &);
+ GetLoadedModuleList (LoadedModuleInfoList &);
lldb::ModuleSP
- LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr);
+ LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset);
private:
//------------------------------------------------------------------
@@ -458,10 +481,9 @@ private:
lldb::user_id_t break_loc_id);
DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote);
-
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_ProcessGDBRemote_h_
+#endif // liblldb_ProcessGDBRemote_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index d2a6503..a4af12c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -41,8 +41,10 @@ ThreadGDBRemote::ThreadGDBRemote (Process &process, lldb::tid_t tid) :
m_thread_name (),
m_dispatch_queue_name (),
m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS),
- m_queue_kind(eQueueKindUnknown),
- m_queue_serial(0)
+ m_dispatch_queue_t (LLDB_INVALID_ADDRESS),
+ m_queue_kind (eQueueKindUnknown),
+ m_queue_serial_number (LLDB_INVALID_QUEUE_ID),
+ m_associated_with_libdispatch_queue (eLazyBoolCalculate)
{
ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)",
this,
@@ -73,15 +75,19 @@ ThreadGDBRemote::ClearQueueInfo ()
{
m_dispatch_queue_name.clear();
m_queue_kind = eQueueKindUnknown;
- m_queue_serial = 0;
+ m_queue_serial_number = 0;
+ m_dispatch_queue_t = LLDB_INVALID_ADDRESS;
+ m_associated_with_libdispatch_queue = eLazyBoolCalculate;
}
void
-ThreadGDBRemote::SetQueueInfo (std::string &&queue_name, QueueKind queue_kind, uint64_t queue_serial)
+ThreadGDBRemote::SetQueueInfo (std::string &&queue_name, QueueKind queue_kind, uint64_t queue_serial, addr_t dispatch_queue_t, LazyBool associated_with_libdispatch_queue)
{
m_dispatch_queue_name = queue_name;
m_queue_kind = queue_kind;
- m_queue_serial = queue_serial;
+ m_queue_serial_number = queue_serial;
+ m_dispatch_queue_t = dispatch_queue_t;
+ m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
}
@@ -100,7 +106,10 @@ ThreadGDBRemote::GetQueueName ()
}
// Always re-fetch the dispatch queue name since it can change
- if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
+ return nullptr;
+
+ if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
{
ProcessSP process_sp (GetProcess());
if (process_sp)
@@ -118,6 +127,35 @@ ThreadGDBRemote::GetQueueName ()
return NULL;
}
+QueueKind
+ThreadGDBRemote::GetQueueKind ()
+{
+ // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...)
+ // with valid information that was gleaned from the stop reply packet. In this case we trust
+ // that the info is valid in m_dispatch_queue_name without refetching it
+ if (CachedQueueInfoIsValid())
+ {
+ return m_queue_kind;
+ }
+
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
+ return eQueueKindUnknown;
+
+ if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ {
+ ProcessSP process_sp (GetProcess());
+ if (process_sp)
+ {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime ();
+ if (runtime)
+ m_queue_kind = runtime->GetQueueKind (m_thread_dispatch_qaddr);
+ return m_queue_kind;
+ }
+ }
+ return eQueueKindUnknown;
+}
+
+
queue_id_t
ThreadGDBRemote::GetQueueID ()
{
@@ -125,9 +163,12 @@ ThreadGDBRemote::GetQueueID ()
// with valid information that was gleaned from the stop reply packet. In this case we trust
// that the info is valid in m_dispatch_queue_name without refetching it
if (CachedQueueInfoIsValid())
- return m_queue_serial;
+ return m_queue_serial_number;
+
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
+ return LLDB_INVALID_QUEUE_ID;
- if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
{
ProcessSP process_sp (GetProcess());
if (process_sp)
@@ -161,20 +202,54 @@ ThreadGDBRemote::GetQueue ()
addr_t
ThreadGDBRemote::GetQueueLibdispatchQueueAddress ()
{
- addr_t dispatch_queue_t_addr = LLDB_INVALID_ADDRESS;
- if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ if (m_dispatch_queue_t == LLDB_INVALID_ADDRESS)
{
- ProcessSP process_sp (GetProcess());
- if (process_sp)
+ if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
{
- SystemRuntime *runtime = process_sp->GetSystemRuntime ();
- if (runtime)
+ ProcessSP process_sp (GetProcess());
+ if (process_sp)
{
- dispatch_queue_t_addr = runtime->GetLibdispatchQueueAddressFromThreadQAddress (m_thread_dispatch_qaddr);
+ SystemRuntime *runtime = process_sp->GetSystemRuntime ();
+ if (runtime)
+ {
+ m_dispatch_queue_t = runtime->GetLibdispatchQueueAddressFromThreadQAddress (m_thread_dispatch_qaddr);
+ }
}
}
}
- return dispatch_queue_t_addr;
+ return m_dispatch_queue_t;
+}
+
+void
+ThreadGDBRemote::SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t)
+{
+ m_dispatch_queue_t = dispatch_queue_t;
+}
+
+bool
+ThreadGDBRemote::ThreadHasQueueInformation () const
+{
+ if (m_thread_dispatch_qaddr != 0
+ && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS
+ && m_dispatch_queue_t != LLDB_INVALID_ADDRESS
+ && m_queue_kind != eQueueKindUnknown
+ && m_queue_serial_number != 0)
+ {
+ return true;
+ }
+ return false;
+}
+
+LazyBool
+ThreadGDBRemote::GetAssociatedWithLibdispatchQueue ()
+{
+ return m_associated_with_libdispatch_queue;
+}
+
+void
+ThreadGDBRemote::SetAssociatedWithLibdispatchQueue (LazyBool associated_with_libdispatch_queue)
+{
+ m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
}
StructuredData::ObjectSP
@@ -313,6 +388,14 @@ ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &respons
}
bool
+ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, uint64_t regval)
+{
+ GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get());
+ assert (gdb_reg_ctx);
+ return gdb_reg_ctx->PrivateSetRegisterValue (reg, regval);
+}
+
+bool
ThreadGDBRemote::CalculateStopInfo ()
{
ProcessSP process_sp (GetProcess());
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index 175433a..d7619f4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -10,8 +10,12 @@
#ifndef liblldb_ThreadGDBRemote_h_
#define liblldb_ThreadGDBRemote_h_
+// C Includes
+// C++ Includes
#include <string>
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/StructuredData.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
@@ -28,8 +32,7 @@ class ThreadGDBRemote : public Thread
public:
ThreadGDBRemote (Process &process, lldb::tid_t tid);
- virtual
- ~ThreadGDBRemote ();
+ ~ThreadGDBRemote() override;
void
WillResume (lldb::StateType resume_state) override;
@@ -43,6 +46,9 @@ public:
const char *
GetQueueName () override;
+ lldb::QueueKind
+ GetQueueKind () override;
+
lldb::queue_id_t
GetQueueID () override;
@@ -52,6 +58,12 @@ public:
lldb::addr_t
GetQueueLibdispatchQueueAddress () override;
+ void
+ SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t) override;
+
+ bool
+ ThreadHasQueueInformation () const override;
+
lldb::RegisterContextSP
GetRegisterContext () override;
@@ -95,36 +107,41 @@ public:
ClearQueueInfo ();
void
- SetQueueInfo (std::string &&queue_name, lldb::QueueKind queue_kind, uint64_t queue_serial);
+ SetQueueInfo (std::string &&queue_name, lldb::QueueKind queue_kind, uint64_t queue_serial, lldb::addr_t dispatch_queue_t, lldb_private::LazyBool associated_with_libdispatch_queue);
+
+ lldb_private::LazyBool
+ GetAssociatedWithLibdispatchQueue () override;
+
+ void
+ SetAssociatedWithLibdispatchQueue (lldb_private::LazyBool associated_with_libdispatch_queue) override;
StructuredData::ObjectSP
FetchThreadExtendedInfo () override;
protected:
-
friend class ProcessGDBRemote;
+ std::string m_thread_name;
+ std::string m_dispatch_queue_name;
+ lldb::addr_t m_thread_dispatch_qaddr;
+ lldb::addr_t m_dispatch_queue_t;
+ lldb::QueueKind m_queue_kind; // Queue info from stop reply/stop info for thread
+ uint64_t m_queue_serial_number; // Queue info from stop reply/stop info for thread
+ lldb_private::LazyBool m_associated_with_libdispatch_queue;
+
bool
PrivateSetRegisterValue (uint32_t reg,
StringExtractor &response);
bool
+ PrivateSetRegisterValue (uint32_t reg,
+ uint64_t regval);
+
+ bool
CachedQueueInfoIsValid() const
{
return m_queue_kind != lldb::eQueueKindUnknown;
}
- //------------------------------------------------------------------
- // Member variables.
- //------------------------------------------------------------------
- std::string m_thread_name;
- std::string m_dispatch_queue_name;
- lldb::addr_t m_thread_dispatch_qaddr;
- lldb::QueueKind m_queue_kind; // Queue info from stop reply/stop info for thread
- uint64_t m_queue_serial; // Queue info from stop reply/stop info for thread
- //------------------------------------------------------------------
- // Member variables.
- //------------------------------------------------------------------
-
void
SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id);
@@ -135,4 +152,4 @@ protected:
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_ThreadGDBRemote_h_
+#endif // liblldb_ThreadGDBRemote_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
new file mode 100644
index 0000000..1a352fa
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
@@ -0,0 +1,93 @@
+//===-- ScriptInterpreterNone.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ScriptInterpreterNone.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+#include <mutex>
+
+using namespace lldb;
+using namespace lldb_private;
+
+ScriptInterpreterNone::ScriptInterpreterNone(CommandInterpreter &interpreter)
+ : ScriptInterpreter(interpreter, eScriptLanguageNone)
+{
+}
+
+ScriptInterpreterNone::~ScriptInterpreterNone()
+{
+}
+
+bool
+ScriptInterpreterNone::ExecuteOneLine(const char *command, CommandReturnObject *, const ExecuteScriptOptions &)
+{
+ m_interpreter.GetDebugger().GetErrorFile()->PutCString(
+ "error: there is no embedded script interpreter in this mode.\n");
+ return false;
+}
+
+void
+ScriptInterpreterNone::ExecuteInterpreterLoop()
+{
+ m_interpreter.GetDebugger().GetErrorFile()->PutCString(
+ "error: there is no embedded script interpreter in this mode.\n");
+}
+
+void
+ScriptInterpreterNone::Initialize()
+{
+ static std::once_flag g_once_flag;
+
+ std::call_once(g_once_flag, []()
+ {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(),
+ lldb::eScriptLanguageNone, CreateInstance);
+ });
+}
+
+void
+ScriptInterpreterNone::Terminate()
+{
+}
+
+lldb::ScriptInterpreterSP
+ScriptInterpreterNone::CreateInstance(CommandInterpreter &interpreter)
+{
+ return std::make_shared<ScriptInterpreterNone>(interpreter);
+}
+
+lldb_private::ConstString
+ScriptInterpreterNone::GetPluginNameStatic()
+{
+ static ConstString g_name("script-none");
+ return g_name;
+}
+
+const char *
+ScriptInterpreterNone::GetPluginDescriptionStatic()
+{
+ return "Null script interpreter";
+}
+
+lldb_private::ConstString
+ScriptInterpreterNone::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ScriptInterpreterNone::GetPluginVersion()
+{
+ return 1;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
new file mode 100644
index 0000000..49fd4fa
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
@@ -0,0 +1,66 @@
+//===-- ScriptInterpreterNone.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ScriptInterpreterNone_h_
+#define liblldb_ScriptInterpreterNone_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/ScriptInterpreter.h"
+
+namespace lldb_private
+{
+
+class ScriptInterpreterNone : public ScriptInterpreter
+{
+ public:
+ ScriptInterpreterNone(CommandInterpreter &interpreter);
+
+ ~ScriptInterpreterNone() override;
+
+ bool
+ ExecuteOneLine(const char *command, CommandReturnObject *result,
+ const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
+
+ void
+ ExecuteInterpreterLoop() override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ScriptInterpreterSP
+ CreateInstance(CommandInterpreter &interpreter);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ScriptInterpreterNone_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
new file mode 100644
index 0000000..23bacc9
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -0,0 +1,1173 @@
+//===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef LLDB_DISABLE_PYTHON
+
+// Python is disabled in this build
+
+#else
+
+#include "lldb-python.h"
+#include "PythonDataObjects.h"
+#include "ScriptInterpreterPython.h"
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Host/File.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+
+#include <stdio.h>
+
+using namespace lldb_private;
+using namespace lldb;
+
+void
+StructuredPythonObject::Dump(Stream &s) const
+{
+ s << "Python Obj: 0x" << GetValue();
+}
+
+//----------------------------------------------------------------------
+// PythonObject
+//----------------------------------------------------------------------
+
+void
+PythonObject::Dump(Stream &strm) const
+{
+ if (m_py_obj)
+ {
+ FILE *file = ::tmpfile();
+ if (file)
+ {
+ ::PyObject_Print (m_py_obj, file, 0);
+ const long length = ftell (file);
+ if (length)
+ {
+ ::rewind(file);
+ std::vector<char> file_contents (length,'\0');
+ const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
+ if (length_read > 0)
+ strm.Write (file_contents.data(), length_read);
+ }
+ ::fclose (file);
+ }
+ }
+ else
+ strm.PutCString ("NULL");
+}
+
+PyObjectType
+PythonObject::GetObjectType() const
+{
+ if (!IsAllocated())
+ return PyObjectType::None;
+
+ if (PythonModule::Check(m_py_obj))
+ return PyObjectType::Module;
+ if (PythonList::Check(m_py_obj))
+ return PyObjectType::List;
+ if (PythonTuple::Check(m_py_obj))
+ return PyObjectType::Tuple;
+ if (PythonDictionary::Check(m_py_obj))
+ return PyObjectType::Dictionary;
+ if (PythonString::Check(m_py_obj))
+ return PyObjectType::String;
+#if PY_MAJOR_VERSION >= 3
+ if (PythonBytes::Check(m_py_obj))
+ return PyObjectType::Bytes;
+#endif
+ if (PythonInteger::Check(m_py_obj))
+ return PyObjectType::Integer;
+ if (PythonFile::Check(m_py_obj))
+ return PyObjectType::File;
+ if (PythonCallable::Check(m_py_obj))
+ return PyObjectType::Callable;
+ return PyObjectType::Unknown;
+}
+
+PythonString
+PythonObject::Repr() const
+{
+ if (!m_py_obj)
+ return PythonString();
+ PyObject *repr = PyObject_Repr(m_py_obj);
+ if (!repr)
+ return PythonString();
+ return PythonString(PyRefType::Owned, repr);
+}
+
+PythonString
+PythonObject::Str() const
+{
+ if (!m_py_obj)
+ return PythonString();
+ PyObject *str = PyObject_Str(m_py_obj);
+ if (!str)
+ return PythonString();
+ return PythonString(PyRefType::Owned, str);
+}
+
+PythonObject
+PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
+{
+ size_t dot_pos = name.find_first_of('.');
+ llvm::StringRef piece = name.substr(0, dot_pos);
+ PythonObject result = dict.GetItemForKey(PythonString(piece));
+ if (dot_pos == llvm::StringRef::npos)
+ {
+ // There was no dot, we're done.
+ return result;
+ }
+
+ // There was a dot. The remaining portion of the name should be looked up in
+ // the context of the object that was found in the dictionary.
+ return result.ResolveName(name.substr(dot_pos + 1));
+}
+
+PythonObject
+PythonObject::ResolveName(llvm::StringRef name) const
+{
+ // Resolve the name in the context of the specified object. If,
+ // for example, `this` refers to a PyModule, then this will look for
+ // `name` in this module. If `this` refers to a PyType, then it will
+ // resolve `name` as an attribute of that type. If `this` refers to
+ // an instance of an object, then it will resolve `name` as the value
+ // of the specified field.
+ //
+ // This function handles dotted names so that, for example, if `m_py_obj`
+ // refers to the `sys` module, and `name` == "path.append", then it
+ // will find the function `sys.path.append`.
+
+ size_t dot_pos = name.find_first_of('.');
+ if (dot_pos == llvm::StringRef::npos)
+ {
+ // No dots in the name, we should be able to find the value immediately
+ // as an attribute of `m_py_obj`.
+ return GetAttributeValue(name);
+ }
+
+ // Look up the first piece of the name, and resolve the rest as a child of that.
+ PythonObject parent = ResolveName(name.substr(0, dot_pos));
+ if (!parent.IsAllocated())
+ return PythonObject();
+
+ // Tail recursion.. should be optimized by the compiler
+ return parent.ResolveName(name.substr(dot_pos + 1));
+}
+
+bool
+PythonObject::HasAttribute(llvm::StringRef attr) const
+{
+ if (!IsValid())
+ return false;
+ PythonString py_attr(attr);
+ return !!PyObject_HasAttr(m_py_obj, py_attr.get());
+}
+
+PythonObject
+PythonObject::GetAttributeValue(llvm::StringRef attr) const
+{
+ if (!IsValid())
+ return PythonObject();
+
+ PythonString py_attr(attr);
+ if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
+ return PythonObject();
+
+ return PythonObject(PyRefType::Owned,
+ PyObject_GetAttr(m_py_obj, py_attr.get()));
+}
+
+bool
+PythonObject::IsNone() const
+{
+ return m_py_obj == Py_None;
+}
+
+bool
+PythonObject::IsValid() const
+{
+ return m_py_obj != nullptr;
+}
+
+bool
+PythonObject::IsAllocated() const
+{
+ return IsValid() && !IsNone();
+}
+
+StructuredData::ObjectSP
+PythonObject::CreateStructuredObject() const
+{
+ switch (GetObjectType())
+ {
+ case PyObjectType::Dictionary:
+ return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
+ case PyObjectType::Integer:
+ return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
+ case PyObjectType::List:
+ return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
+ case PyObjectType::String:
+ return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
+ case PyObjectType::Bytes:
+ return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
+ case PyObjectType::None:
+ return StructuredData::ObjectSP();
+ default:
+ return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
+ }
+}
+
+//----------------------------------------------------------------------
+// PythonString
+//----------------------------------------------------------------------
+PythonBytes::PythonBytes() : PythonObject()
+{
+}
+
+PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject()
+{
+ SetBytes(bytes);
+}
+
+PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject()
+{
+ SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
+}
+
+PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
+}
+
+PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object)
+{
+}
+
+PythonBytes::~PythonBytes()
+{
+}
+
+bool
+PythonBytes::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+ if (PyBytes_Check(py_obj))
+ return true;
+ return false;
+}
+
+void
+PythonBytes::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonBytes::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+llvm::ArrayRef<uint8_t>
+PythonBytes::GetBytes() const
+{
+ if (!IsValid())
+ return llvm::ArrayRef<uint8_t>();
+
+ Py_ssize_t size;
+ char *c;
+
+ PyBytes_AsStringAndSize(m_py_obj, &c, &size);
+ return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
+}
+
+size_t
+PythonBytes::GetSize() const
+{
+ if (!IsValid())
+ return 0;
+ return PyBytes_Size(m_py_obj);
+}
+
+void
+PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes)
+{
+ const char *data = reinterpret_cast<const char *>(bytes.data());
+ PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
+ PythonObject::Reset(PyRefType::Owned, py_bytes);
+}
+
+StructuredData::StringSP
+PythonBytes::CreateStructuredString() const
+{
+ StructuredData::StringSP result(new StructuredData::String);
+ Py_ssize_t size;
+ char *c;
+ PyBytes_AsStringAndSize(m_py_obj, &c, &size);
+ result->SetValue(std::string(c, size));
+ return result;
+}
+
+//----------------------------------------------------------------------
+// PythonString
+//----------------------------------------------------------------------
+
+PythonString::PythonString(PyRefType type, PyObject *py_obj)
+ : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
+}
+
+PythonString::PythonString(const PythonString &object)
+ : PythonObject(object)
+{
+}
+
+PythonString::PythonString(llvm::StringRef string)
+ : PythonObject()
+{
+ SetString(string);
+}
+
+PythonString::PythonString(const char *string)
+ : PythonObject()
+{
+ SetString(llvm::StringRef(string));
+}
+
+PythonString::PythonString()
+ : PythonObject()
+{
+}
+
+PythonString::~PythonString ()
+{
+}
+
+bool
+PythonString::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+
+ if (PyUnicode_Check(py_obj))
+ return true;
+#if PY_MAJOR_VERSION < 3
+ if (PyString_Check(py_obj))
+ return true;
+#endif
+ return false;
+}
+
+void
+PythonString::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonString::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+#if PY_MAJOR_VERSION < 3
+ // In Python 2, Don't store PyUnicode objects directly, because we need
+ // access to their underlying character buffers which Python 2 doesn't
+ // provide.
+ if (PyUnicode_Check(py_obj))
+ result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
+#endif
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+llvm::StringRef
+PythonString::GetString() const
+{
+ if (!IsValid())
+ return llvm::StringRef();
+
+ Py_ssize_t size;
+ char *c;
+
+#if PY_MAJOR_VERSION >= 3
+ c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
+#else
+ PyString_AsStringAndSize(m_py_obj, &c, &size);
+#endif
+ return llvm::StringRef(c, size);
+}
+
+size_t
+PythonString::GetSize() const
+{
+ if (IsValid())
+ {
+#if PY_MAJOR_VERSION >= 3
+ return PyUnicode_GetSize(m_py_obj);
+#else
+ return PyString_Size(m_py_obj);
+#endif
+ }
+ return 0;
+}
+
+void
+PythonString::SetString (llvm::StringRef string)
+{
+#if PY_MAJOR_VERSION >= 3
+ PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
+ PythonObject::Reset(PyRefType::Owned, unicode);
+#else
+ PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
+ PythonObject::Reset(PyRefType::Owned, str);
+#endif
+}
+
+StructuredData::StringSP
+PythonString::CreateStructuredString() const
+{
+ StructuredData::StringSP result(new StructuredData::String);
+ result->SetValue(GetString());
+ return result;
+}
+
+//----------------------------------------------------------------------
+// PythonInteger
+//----------------------------------------------------------------------
+
+PythonInteger::PythonInteger()
+ : PythonObject()
+{
+
+}
+
+PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
+ : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
+}
+
+PythonInteger::PythonInteger(const PythonInteger &object)
+ : PythonObject(object)
+{
+}
+
+PythonInteger::PythonInteger(int64_t value)
+ : PythonObject()
+{
+ SetInteger(value);
+}
+
+
+PythonInteger::~PythonInteger ()
+{
+}
+
+bool
+PythonInteger::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+
+#if PY_MAJOR_VERSION >= 3
+ // Python 3 does not have PyInt_Check. There is only one type of
+ // integral value, long.
+ return PyLong_Check(py_obj);
+#else
+ return PyLong_Check(py_obj) || PyInt_Check(py_obj);
+#endif
+}
+
+void
+PythonInteger::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonInteger::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+#if PY_MAJOR_VERSION < 3
+ // Always store this as a PyLong, which makes interoperability between
+ // Python 2.x and Python 3.x easier. This is only necessary in 2.x,
+ // since 3.x doesn't even have a PyInt.
+ if (PyInt_Check(py_obj))
+ {
+ // Since we converted the original object to a different type, the new
+ // object is an owned object regardless of the ownership semantics requested
+ // by the user.
+ result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
+ }
+#endif
+
+ assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+int64_t
+PythonInteger::GetInteger() const
+{
+ if (m_py_obj)
+ {
+ assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
+
+ return PyLong_AsLongLong(m_py_obj);
+ }
+ return UINT64_MAX;
+}
+
+void
+PythonInteger::SetInteger(int64_t value)
+{
+ PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
+}
+
+StructuredData::IntegerSP
+PythonInteger::CreateStructuredInteger() const
+{
+ StructuredData::IntegerSP result(new StructuredData::Integer);
+ result->SetValue(GetInteger());
+ return result;
+}
+
+//----------------------------------------------------------------------
+// PythonList
+//----------------------------------------------------------------------
+
+PythonList::PythonList(PyInitialValue value)
+ : PythonObject()
+{
+ if (value == PyInitialValue::Empty)
+ Reset(PyRefType::Owned, PyList_New(0));
+}
+
+PythonList::PythonList(int list_size)
+ : PythonObject()
+{
+ Reset(PyRefType::Owned, PyList_New(list_size));
+}
+
+PythonList::PythonList(PyRefType type, PyObject *py_obj)
+ : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
+}
+
+PythonList::PythonList(const PythonList &list)
+ : PythonObject(list)
+{
+}
+
+PythonList::~PythonList ()
+{
+}
+
+bool
+PythonList::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+ return PyList_Check(py_obj);
+}
+
+void
+PythonList::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonList::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+uint32_t
+PythonList::GetSize() const
+{
+ if (IsValid())
+ return PyList_GET_SIZE(m_py_obj);
+ return 0;
+}
+
+PythonObject
+PythonList::GetItemAtIndex(uint32_t index) const
+{
+ if (IsValid())
+ return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
+ return PythonObject();
+}
+
+void
+PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
+{
+ if (IsAllocated() && object.IsValid())
+ {
+ // PyList_SetItem is documented to "steal" a reference, so we need to
+ // convert it to an owned reference by incrementing it.
+ Py_INCREF(object.get());
+ PyList_SetItem(m_py_obj, index, object.get());
+ }
+}
+
+void
+PythonList::AppendItem(const PythonObject &object)
+{
+ if (IsAllocated() && object.IsValid())
+ {
+ // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
+ // here like we do with `PyList_SetItem`.
+ PyList_Append(m_py_obj, object.get());
+ }
+}
+
+StructuredData::ArraySP
+PythonList::CreateStructuredArray() const
+{
+ StructuredData::ArraySP result(new StructuredData::Array);
+ uint32_t count = GetSize();
+ for (uint32_t i = 0; i < count; ++i)
+ {
+ PythonObject obj = GetItemAtIndex(i);
+ result->AddItem(obj.CreateStructuredObject());
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------
+// PythonTuple
+//----------------------------------------------------------------------
+
+PythonTuple::PythonTuple(PyInitialValue value)
+ : PythonObject()
+{
+ if (value == PyInitialValue::Empty)
+ Reset(PyRefType::Owned, PyTuple_New(0));
+}
+
+PythonTuple::PythonTuple(int tuple_size)
+ : PythonObject()
+{
+ Reset(PyRefType::Owned, PyTuple_New(tuple_size));
+}
+
+PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj)
+ : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
+}
+
+PythonTuple::PythonTuple(const PythonTuple &tuple)
+ : PythonObject(tuple)
+{
+}
+
+PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects)
+{
+ m_py_obj = PyTuple_New(objects.size());
+
+ uint32_t idx = 0;
+ for (auto object : objects)
+ {
+ if (object.IsValid())
+ SetItemAtIndex(idx, object);
+ idx++;
+ }
+}
+
+PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects)
+{
+ m_py_obj = PyTuple_New(objects.size());
+
+ uint32_t idx = 0;
+ for (auto py_object : objects)
+ {
+ PythonObject object(PyRefType::Borrowed, py_object);
+ if (object.IsValid())
+ SetItemAtIndex(idx, object);
+ idx++;
+ }
+}
+
+PythonTuple::~PythonTuple()
+{
+}
+
+bool
+PythonTuple::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+ return PyTuple_Check(py_obj);
+}
+
+void
+PythonTuple::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonTuple::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+uint32_t
+PythonTuple::GetSize() const
+{
+ if (IsValid())
+ return PyTuple_GET_SIZE(m_py_obj);
+ return 0;
+}
+
+PythonObject
+PythonTuple::GetItemAtIndex(uint32_t index) const
+{
+ if (IsValid())
+ return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
+ return PythonObject();
+}
+
+void
+PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object)
+{
+ if (IsAllocated() && object.IsValid())
+ {
+ // PyTuple_SetItem is documented to "steal" a reference, so we need to
+ // convert it to an owned reference by incrementing it.
+ Py_INCREF(object.get());
+ PyTuple_SetItem(m_py_obj, index, object.get());
+ }
+}
+
+StructuredData::ArraySP
+PythonTuple::CreateStructuredArray() const
+{
+ StructuredData::ArraySP result(new StructuredData::Array);
+ uint32_t count = GetSize();
+ for (uint32_t i = 0; i < count; ++i)
+ {
+ PythonObject obj = GetItemAtIndex(i);
+ result->AddItem(obj.CreateStructuredObject());
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------
+// PythonDictionary
+//----------------------------------------------------------------------
+
+PythonDictionary::PythonDictionary(PyInitialValue value)
+ : PythonObject()
+{
+ if (value == PyInitialValue::Empty)
+ Reset(PyRefType::Owned, PyDict_New());
+}
+
+PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
+ : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
+}
+
+PythonDictionary::PythonDictionary(const PythonDictionary &object)
+ : PythonObject(object)
+{
+}
+
+PythonDictionary::~PythonDictionary ()
+{
+}
+
+bool
+PythonDictionary::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+
+ return PyDict_Check(py_obj);
+}
+
+void
+PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonDictionary::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+uint32_t
+PythonDictionary::GetSize() const
+{
+ if (IsValid())
+ return PyDict_Size(m_py_obj);
+ return 0;
+}
+
+PythonList
+PythonDictionary::GetKeys() const
+{
+ if (IsValid())
+ return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
+ return PythonList(PyInitialValue::Invalid);
+}
+
+PythonObject
+PythonDictionary::GetItemForKey(const PythonObject &key) const
+{
+ if (IsAllocated() && key.IsValid())
+ return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
+ return PythonObject();
+}
+
+void
+PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
+{
+ if (IsAllocated() && key.IsValid() && value.IsValid())
+ PyDict_SetItem(m_py_obj, key.get(), value.get());
+}
+
+StructuredData::DictionarySP
+PythonDictionary::CreateStructuredDictionary() const
+{
+ StructuredData::DictionarySP result(new StructuredData::Dictionary);
+ PythonList keys(GetKeys());
+ uint32_t num_keys = keys.GetSize();
+ for (uint32_t i = 0; i < num_keys; ++i)
+ {
+ PythonObject key = keys.GetItemAtIndex(i);
+ PythonObject value = GetItemForKey(key);
+ StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
+ result->AddItem(key.Str().GetString(), structured_value);
+ }
+ return result;
+}
+
+PythonModule::PythonModule() : PythonObject()
+{
+}
+
+PythonModule::PythonModule(PyRefType type, PyObject *py_obj)
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
+}
+
+PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict)
+{
+}
+
+PythonModule::~PythonModule()
+{
+}
+
+PythonModule
+PythonModule::BuiltinsModule()
+{
+#if PY_MAJOR_VERSION >= 3
+ return AddModule("builtins");
+#else
+ return AddModule("__builtin__");
+#endif
+}
+
+PythonModule
+PythonModule::MainModule()
+{
+ return AddModule("__main__");
+}
+
+PythonModule
+PythonModule::AddModule(llvm::StringRef module)
+{
+ std::string str = module.str();
+ return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
+}
+
+
+PythonModule
+PythonModule::ImportModule(llvm::StringRef module)
+{
+ std::string str = module.str();
+ return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str()));
+}
+
+bool
+PythonModule::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+
+ return PyModule_Check(py_obj);
+}
+
+void
+PythonModule::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonModule::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+PythonDictionary
+PythonModule::GetDictionary() const
+{
+ return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
+}
+
+PythonCallable::PythonCallable() : PythonObject()
+{
+}
+
+PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj)
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
+}
+
+PythonCallable::PythonCallable(const PythonCallable &callable)
+ : PythonObject(callable)
+{
+}
+
+PythonCallable::~PythonCallable()
+{
+}
+
+bool
+PythonCallable::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+
+ return PyCallable_Check(py_obj);
+}
+
+void
+PythonCallable::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonCallable::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+
+PythonCallable::ArgInfo
+PythonCallable::GetNumArguments() const
+{
+ ArgInfo result = { 0, false, false };
+ if (!IsValid())
+ return result;
+
+ PyObject *py_func_obj = m_py_obj;
+ if (PyMethod_Check(py_func_obj))
+ py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
+
+ if (!py_func_obj)
+ return result;
+
+ PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj);
+ if (!code)
+ return result;
+
+ result.count = code->co_argcount;
+ result.has_varargs = !!(code->co_flags & CO_VARARGS);
+ result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
+ return result;
+}
+
+PythonObject
+PythonCallable::operator ()()
+{
+ return PythonObject(PyRefType::Owned,
+ PyObject_CallObject(m_py_obj, nullptr));
+}
+
+PythonObject
+PythonCallable::operator ()(std::initializer_list<PyObject*> args)
+{
+ PythonTuple arg_tuple(args);
+ return PythonObject(PyRefType::Owned,
+ PyObject_CallObject(m_py_obj, arg_tuple.get()));
+}
+
+PythonObject
+PythonCallable::operator ()(std::initializer_list<PythonObject> args)
+{
+ PythonTuple arg_tuple(args);
+ return PythonObject(PyRefType::Owned,
+ PyObject_CallObject(m_py_obj, arg_tuple.get()));
+}
+
+PythonFile::PythonFile()
+ : PythonObject()
+{
+}
+
+PythonFile::PythonFile(File &file, const char *mode)
+{
+ Reset(file, mode);
+}
+
+PythonFile::PythonFile(const char *path, const char *mode)
+{
+ FILE *fp = nullptr;
+ fp = fopen(path, mode);
+ lldb_private::File file(fp, true);
+ Reset(file, mode);
+}
+
+PythonFile::PythonFile(PyRefType type, PyObject *o)
+{
+ Reset(type, o);
+}
+
+PythonFile::~PythonFile()
+{
+}
+
+bool
+PythonFile::Check(PyObject *py_obj)
+{
+#if PY_MAJOR_VERSION < 3
+ return PyFile_Check(py_obj);
+#else
+ // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
+ // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper
+ // over `io.open()`, which returns some object derived from `io.IOBase`.
+ // As a result, the only way to detect a file in Python 3 is to check whether
+ // it inherits from `io.IOBase`. Since it is possible for non-files to also
+ // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
+ // attribute, which should guarantee that it is backed by the file system.
+ PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
+ PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get()));
+ PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
+
+ PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
+
+ if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
+ return false;
+ if (!object_type.HasAttribute("fileno"))
+ return false;
+
+ return true;
+#endif
+}
+
+void
+PythonFile::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonFile::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+void
+PythonFile::Reset(File &file, const char *mode)
+{
+ if (!file.IsValid())
+ {
+ Reset();
+ return;
+ }
+
+ char *cmode = const_cast<char *>(mode);
+#if PY_MAJOR_VERSION >= 3
+ Reset(PyRefType::Owned,
+ PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0));
+#else
+ // Read through the Python source, doesn't seem to modify these strings
+ Reset(PyRefType::Owned,
+ PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr));
+#endif
+}
+
+bool
+PythonFile::GetUnderlyingFile(File &file) const
+{
+ if (!IsValid())
+ return false;
+
+ file.Close();
+ // We don't own the file descriptor returned by this function, make sure the
+ // File object knows about that.
+ file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
+ return file.IsValid();
+}
+
+
+#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
new file mode 100644
index 0000000..06264b6
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -0,0 +1,535 @@
+//===-- PythonDataObjects.h--------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
+
+#ifndef LLDB_DISABLE_PYTHON
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-defines.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/StructuredData.h"
+#include "lldb/Core/Flags.h"
+#include "lldb/Host/File.h"
+#include "lldb/Interpreter/OptionValue.h"
+
+#include "llvm/ADT/ArrayRef.h"
+
+namespace lldb_private {
+
+class PythonBytes;
+class PythonString;
+class PythonList;
+class PythonDictionary;
+class PythonInteger;
+
+class StructuredPythonObject : public StructuredData::Generic
+{
+public:
+ StructuredPythonObject()
+ : StructuredData::Generic()
+ {
+ }
+
+ StructuredPythonObject(void *obj)
+ : StructuredData::Generic(obj)
+ {
+ Py_XINCREF(GetValue());
+ }
+
+ ~StructuredPythonObject() override
+ {
+ if (Py_IsInitialized())
+ Py_XDECREF(GetValue());
+ SetValue(nullptr);
+ }
+
+ bool
+ IsValid() const override
+ {
+ return GetValue() && GetValue() != Py_None;
+ }
+
+ void Dump(Stream &s) const override;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
+};
+
+enum class PyObjectType
+{
+ Unknown,
+ None,
+ Integer,
+ Dictionary,
+ List,
+ String,
+ Bytes,
+ Module,
+ Callable,
+ Tuple,
+ File
+};
+
+enum class PyRefType
+{
+ Borrowed, // We are not given ownership of the incoming PyObject.
+ // We cannot safely hold it without calling Py_INCREF.
+ Owned // We have ownership of the incoming PyObject. We should
+ // not call Py_INCREF.
+};
+
+enum class PyInitialValue
+{
+ Invalid,
+ Empty
+};
+
+class PythonObject
+{
+public:
+ PythonObject()
+ : m_py_obj(nullptr)
+ {
+ }
+
+ PythonObject(PyRefType type, PyObject *py_obj)
+ : m_py_obj(nullptr)
+ {
+ Reset(type, py_obj);
+ }
+
+ PythonObject(const PythonObject &rhs)
+ : m_py_obj(nullptr)
+ {
+ Reset(rhs);
+ }
+
+ virtual ~PythonObject()
+ {
+ Reset();
+ }
+
+ void
+ Reset()
+ {
+ // Avoid calling the virtual method since it's not necessary
+ // to actually validate the type of the PyObject if we're
+ // just setting to null.
+ if (Py_IsInitialized())
+ Py_XDECREF(m_py_obj);
+ m_py_obj = nullptr;
+ }
+
+ void
+ Reset(const PythonObject &rhs)
+ {
+ // Avoid calling the virtual method if it's not necessary
+ // to actually validate the type of the PyObject.
+ if (!rhs.IsValid())
+ Reset();
+ else
+ Reset(PyRefType::Borrowed, rhs.m_py_obj);
+ }
+
+ // PythonObject is implicitly convertible to PyObject *, which will call the
+ // wrong overload. We want to explicitly disallow this, since a PyObject
+ // *always* owns its reference. Therefore the overload which takes a
+ // PyRefType doesn't make sense, and the copy constructor should be used.
+ void
+ Reset(PyRefType type, const PythonObject &ref) = delete;
+
+ virtual void
+ Reset(PyRefType type, PyObject *py_obj)
+ {
+ if (py_obj == m_py_obj)
+ return;
+
+ if (Py_IsInitialized())
+ Py_XDECREF(m_py_obj);
+
+ m_py_obj = py_obj;
+
+ // If this is a borrowed reference, we need to convert it to
+ // an owned reference by incrementing it. If it is an owned
+ // reference (for example the caller allocated it with PyDict_New()
+ // then we must *not* increment it.
+ if (Py_IsInitialized() && type == PyRefType::Borrowed)
+ Py_XINCREF(m_py_obj);
+ }
+
+ void
+ Dump () const
+ {
+ if (m_py_obj)
+ _PyObject_Dump (m_py_obj);
+ else
+ puts ("NULL");
+ }
+
+ void
+ Dump (Stream &strm) const;
+
+ PyObject*
+ get() const
+ {
+ return m_py_obj;
+ }
+
+ PyObject*
+ release()
+ {
+ PyObject *result = m_py_obj;
+ m_py_obj = nullptr;
+ return result;
+ }
+
+ PythonObject &
+ operator=(const PythonObject &other)
+ {
+ Reset(PyRefType::Borrowed, other.get());
+ return *this;
+ }
+
+ PyObjectType
+ GetObjectType() const;
+
+ PythonString
+ Repr() const;
+
+ PythonString
+ Str() const;
+
+ static PythonObject
+ ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict);
+
+ template<typename T>
+ static T
+ ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
+ {
+ return ResolveNameWithDictionary(name, dict).AsType<T>();
+ }
+
+ PythonObject
+ ResolveName(llvm::StringRef name) const;
+
+ template<typename T>
+ T
+ ResolveName(llvm::StringRef name) const
+ {
+ return ResolveName(name).AsType<T>();
+ }
+
+ bool
+ HasAttribute(llvm::StringRef attribute) const;
+
+ PythonObject
+ GetAttributeValue(llvm::StringRef attribute) const;
+
+ bool
+ IsValid() const;
+
+ bool
+ IsAllocated() const;
+
+ bool
+ IsNone() const;
+
+ template<typename T>
+ T AsType() const
+ {
+ if (!T::Check(m_py_obj))
+ return T();
+ return T(PyRefType::Borrowed, m_py_obj);
+ }
+
+ StructuredData::ObjectSP
+ CreateStructuredObject() const;
+
+protected:
+ PyObject* m_py_obj;
+};
+
+class PythonBytes : public PythonObject
+{
+public:
+ PythonBytes();
+ explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
+ PythonBytes(const uint8_t *bytes, size_t length);
+ PythonBytes(PyRefType type, PyObject *o);
+ PythonBytes(const PythonBytes &object);
+
+ ~PythonBytes() override;
+
+ static bool
+ Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void
+ Reset(PyRefType type, PyObject *py_obj) override;
+
+ llvm::ArrayRef<uint8_t>
+ GetBytes() const;
+
+ size_t
+ GetSize() const;
+
+ void
+ SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
+
+ StructuredData::StringSP
+ CreateStructuredString() const;
+};
+
+class PythonString : public PythonObject
+{
+public:
+ PythonString();
+ explicit PythonString(llvm::StringRef string);
+ explicit PythonString(const char *string);
+ PythonString(PyRefType type, PyObject *o);
+ PythonString(const PythonString &object);
+
+ ~PythonString() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ llvm::StringRef
+ GetString() const;
+
+ size_t
+ GetSize() const;
+
+ void SetString(llvm::StringRef string);
+
+ StructuredData::StringSP CreateStructuredString() const;
+};
+
+class PythonInteger : public PythonObject
+{
+public:
+ PythonInteger();
+ explicit PythonInteger(int64_t value);
+ PythonInteger(PyRefType type, PyObject *o);
+ PythonInteger(const PythonInteger &object);
+
+ ~PythonInteger() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ int64_t GetInteger() const;
+
+ void
+ SetInteger (int64_t value);
+
+ StructuredData::IntegerSP CreateStructuredInteger() const;
+};
+
+class PythonList : public PythonObject
+{
+public:
+ PythonList() {}
+ explicit PythonList(PyInitialValue value);
+ explicit PythonList(int list_size);
+ PythonList(PyRefType type, PyObject *o);
+ PythonList(const PythonList &list);
+
+ ~PythonList() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ uint32_t GetSize() const;
+
+ PythonObject GetItemAtIndex(uint32_t index) const;
+
+ void SetItemAtIndex(uint32_t index, const PythonObject &object);
+
+ void AppendItem(const PythonObject &object);
+
+ StructuredData::ArraySP CreateStructuredArray() const;
+};
+
+class PythonTuple : public PythonObject
+{
+public:
+ PythonTuple() {}
+ explicit PythonTuple(PyInitialValue value);
+ explicit PythonTuple(int tuple_size);
+ PythonTuple(PyRefType type, PyObject *o);
+ PythonTuple(const PythonTuple &tuple);
+ PythonTuple(std::initializer_list<PythonObject> objects);
+ PythonTuple(std::initializer_list<PyObject*> objects);
+
+ ~PythonTuple() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ uint32_t GetSize() const;
+
+ PythonObject GetItemAtIndex(uint32_t index) const;
+
+ void SetItemAtIndex(uint32_t index, const PythonObject &object);
+
+ StructuredData::ArraySP CreateStructuredArray() const;
+};
+
+class PythonDictionary : public PythonObject
+{
+public:
+ PythonDictionary() {}
+ explicit PythonDictionary(PyInitialValue value);
+ PythonDictionary(PyRefType type, PyObject *o);
+ PythonDictionary(const PythonDictionary &dict);
+
+ ~PythonDictionary() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ uint32_t GetSize() const;
+
+ PythonList GetKeys() const;
+
+ PythonObject GetItemForKey(const PythonObject &key) const;
+ void SetItemForKey(const PythonObject &key, const PythonObject &value);
+
+ StructuredData::DictionarySP CreateStructuredDictionary() const;
+};
+
+class PythonModule : public PythonObject
+{
+ public:
+ PythonModule();
+ PythonModule(PyRefType type, PyObject *o);
+ PythonModule(const PythonModule &dict);
+
+ ~PythonModule() override;
+
+ static bool Check(PyObject *py_obj);
+
+ static PythonModule
+ BuiltinsModule();
+
+ static PythonModule
+ MainModule();
+
+ static PythonModule
+ AddModule(llvm::StringRef module);
+
+ static PythonModule
+ ImportModule(llvm::StringRef module);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ PythonDictionary GetDictionary() const;
+};
+
+class PythonCallable : public PythonObject
+{
+public:
+ struct ArgInfo {
+ size_t count;
+ bool has_varargs : 1;
+ bool has_kwargs : 1;
+ };
+
+ PythonCallable();
+ PythonCallable(PyRefType type, PyObject *o);
+ PythonCallable(const PythonCallable &dict);
+
+ ~PythonCallable() override;
+
+ static bool
+ Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void
+ Reset(PyRefType type, PyObject *py_obj) override;
+
+ ArgInfo
+ GetNumArguments() const;
+
+ PythonObject
+ operator ()();
+
+ PythonObject
+ operator ()(std::initializer_list<PyObject*> args);
+
+ PythonObject
+ operator ()(std::initializer_list<PythonObject> args);
+
+ template<typename Arg, typename... Args>
+ PythonObject
+ operator ()(const Arg &arg, Args... args)
+ {
+ return operator()({ arg, args... });
+ }
+};
+
+
+class PythonFile : public PythonObject
+{
+ public:
+ PythonFile();
+ PythonFile(File &file, const char *mode);
+ PythonFile(const char *path, const char *mode);
+ PythonFile(PyRefType type, PyObject *o);
+
+ ~PythonFile() override;
+
+ static bool Check(PyObject *py_obj);
+
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(File &file, const char *mode);
+
+ bool GetUnderlyingFile(File &file) const;
+};
+
+} // namespace lldb_private
+
+#endif
+
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
new file mode 100644
index 0000000..2cbd85b
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
@@ -0,0 +1,201 @@
+//===-- PythonExceptionState.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_DISABLE_PYTHON
+
+#include "lldb-python.h"
+#include "PythonExceptionState.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace lldb_private;
+
+PythonExceptionState::PythonExceptionState(bool restore_on_exit)
+ : m_restore_on_exit(restore_on_exit)
+{
+ Acquire(restore_on_exit);
+}
+
+PythonExceptionState::~PythonExceptionState()
+{
+ if (m_restore_on_exit)
+ Restore();
+}
+
+void
+PythonExceptionState::Acquire(bool restore_on_exit)
+{
+ // If a state is already acquired, the user needs to decide whether they
+ // want to discard or restore it. Don't allow the potential silent
+ // loss of a valid state.
+ assert(!IsError());
+
+ if (!HasErrorOccurred())
+ return;
+
+ PyObject *py_type = nullptr;
+ PyObject *py_value = nullptr;
+ PyObject *py_traceback = nullptr;
+ PyErr_Fetch(&py_type, &py_value, &py_traceback);
+ // PyErr_Fetch clears the error flag.
+ assert(!HasErrorOccurred());
+
+ // Ownership of the objects returned by `PyErr_Fetch` is transferred
+ // to us.
+ m_type.Reset(PyRefType::Owned, py_type);
+ m_value.Reset(PyRefType::Owned, py_value);
+ m_traceback.Reset(PyRefType::Owned, py_traceback);
+ m_restore_on_exit = restore_on_exit;
+}
+
+void
+PythonExceptionState::Restore()
+{
+ if (m_type.IsValid())
+ {
+ // The documentation for PyErr_Restore says "Do not pass a null type and
+ // non-null value or traceback. So only restore if type was non-null
+ // to begin with. In this case we're passing ownership back to Python
+ // so release them all.
+ PyErr_Restore(m_type.release(), m_value.release(), m_traceback.release());
+ }
+
+ // After we restore, we should not hold onto the exception state. Demand that
+ // it be re-acquired.
+ Discard();
+}
+
+void
+PythonExceptionState::Discard()
+{
+ m_type.Reset();
+ m_value.Reset();
+ m_traceback.Reset();
+}
+
+void
+PythonExceptionState::Reset()
+{
+ if (m_restore_on_exit)
+ Restore();
+ else
+ Discard();
+}
+
+bool
+PythonExceptionState::HasErrorOccurred()
+{
+ return PyErr_Occurred();
+}
+
+bool
+PythonExceptionState::IsError() const
+{
+ return m_type.IsValid() || m_value.IsValid() || m_traceback.IsValid();
+}
+
+PythonObject
+PythonExceptionState::GetType() const
+{
+ return m_type;
+}
+
+PythonObject
+PythonExceptionState::GetValue() const
+{
+ return m_value;
+}
+
+PythonObject
+PythonExceptionState::GetTraceback() const
+{
+ return m_traceback;
+}
+
+std::string
+PythonExceptionState::Format() const
+{
+ // Don't allow this function to modify the error state.
+ PythonExceptionState state(true);
+
+ std::string backtrace = ReadBacktrace();
+ if (!IsError())
+ return std::string();
+
+ // It's possible that ReadPythonBacktrace generated another exception.
+ // If this happens we have to clear the exception, because otherwise
+ // PyObject_Str() will assert below. That's why we needed to do the
+ // save / restore at the beginning of this function.
+ PythonExceptionState bt_error_state(false);
+
+ std::string error_string;
+ llvm::raw_string_ostream error_stream(error_string);
+ error_stream << m_value.Str().GetString() << "\n";
+
+ if (!bt_error_state.IsError())
+ {
+ // If we were able to read the backtrace, just append it.
+ error_stream << backtrace << "\n";
+ }
+ else
+ {
+ // Otherwise, append some information about why we were unable to
+ // obtain the backtrace.
+ PythonString bt_error = bt_error_state.GetValue().Str();
+ error_stream << "An error occurred while retrieving the backtrace: " << bt_error.GetString() << "\n";
+ }
+ return error_stream.str();
+}
+
+std::string
+PythonExceptionState::ReadBacktrace() const
+{
+ std::string retval("backtrace unavailable");
+
+ auto traceback_module = PythonModule::ImportModule("traceback");
+#if PY_MAJOR_VERSION >= 3
+ auto stringIO_module = PythonModule::ImportModule("io");
+#else
+ auto stringIO_module = PythonModule::ImportModule("StringIO");
+#endif
+ if (!m_traceback.IsAllocated())
+ return retval;
+
+ if (!traceback_module.IsAllocated() || !stringIO_module.IsAllocated())
+ return retval;
+
+ auto stringIO_builder = stringIO_module.ResolveName<PythonCallable>("StringIO");
+ if (!stringIO_builder.IsAllocated())
+ return retval;
+
+ auto stringIO_buffer = stringIO_builder();
+ if (!stringIO_buffer.IsAllocated())
+ return retval;
+
+ auto printTB = traceback_module.ResolveName<PythonCallable>("print_tb");
+ if (!printTB.IsAllocated())
+ return retval;
+
+ auto printTB_result = printTB(m_traceback.get(), Py_None, stringIO_buffer.get());
+ auto stringIO_getvalue = stringIO_buffer.ResolveName<PythonCallable>("getvalue");
+ if (!stringIO_getvalue.IsAllocated())
+ return retval;
+
+ auto printTB_string = stringIO_getvalue().AsType<PythonString>();
+ if (!printTB_string.IsAllocated())
+ return retval;
+
+ llvm::StringRef string_data(printTB_string.GetString());
+ retval.assign(string_data.data(), string_data.size());
+
+ return retval;
+}
+
+#endif
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h
new file mode 100644
index 0000000..c74e52b
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h
@@ -0,0 +1,70 @@
+//===-- PythonExceptionState.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H
+
+#ifndef LLDB_DISABLE_PYTHON
+
+#include "PythonDataObjects.h"
+
+namespace lldb_private
+{
+
+class PythonExceptionState
+{
+ public:
+ explicit PythonExceptionState(bool restore_on_exit);
+ ~PythonExceptionState();
+
+ void
+ Acquire(bool restore_on_exit);
+
+ void
+ Restore();
+
+ void
+ Discard();
+
+ void
+ Reset();
+
+ static bool
+ HasErrorOccurred();
+
+ bool
+ IsError() const;
+
+ PythonObject
+ GetType() const;
+
+ PythonObject
+ GetValue() const;
+
+ PythonObject
+ GetTraceback() const;
+
+ std::string
+ Format() const;
+
+ private:
+ std::string
+ ReadBacktrace() const;
+
+ bool m_restore_on_exit;
+
+ PythonObject m_type;
+ PythonObject m_value;
+ PythonObject m_traceback;
+};
+}
+
+#endif
+
+#endif
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 8f60793..19ad86d 100644
--- a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -7,20 +7,21 @@
//
//===----------------------------------------------------------------------===//
-// In order to guarantee correct working with Python, Python.h *MUST* be
-// the *FIRST* header file included here.
#ifdef LLDB_DISABLE_PYTHON
// Python is disabled in this build
#else
-#include "lldb/lldb-python.h"
-#include "lldb/Interpreter/ScriptInterpreterPython.h"
+#include "lldb-python.h"
+#include "ScriptInterpreterPython.h"
+#include "PythonDataObjects.h"
+#include "PythonExceptionState.h"
#include <stdlib.h>
#include <stdio.h>
+#include <mutex>
#include <string>
#include "lldb/API/SBValue.h"
@@ -29,15 +30,16 @@
#include "lldb/Breakpoint/WatchpointOptions.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Pipe.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/PythonDataObjects.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
@@ -46,6 +48,7 @@
#endif
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
@@ -79,8 +82,102 @@ static ScriptInterpreterPython::SWIGPythonCallThreadPlan g_swig_call_thread_plan
static bool g_initialized = false;
-static std::string
-ReadPythonBacktrace (PyObject* py_backtrace);
+namespace
+{
+
+// Initializing Python is not a straightforward process. We cannot control what
+// external code may have done before getting to this point in LLDB, including
+// potentially having already initialized Python, so we need to do a lot of work
+// to ensure that the existing state of the system is maintained across our
+// initialization. We do this by using an RAII pattern where we save off initial
+// state at the beginning, and restore it at the end
+struct InitializePythonRAII
+{
+public:
+ InitializePythonRAII() :
+ m_gil_state(PyGILState_UNLOCKED),
+ m_was_already_initialized(false)
+ {
+ // Python will muck with STDIN terminal state, so save off any current TTY
+ // settings so we can restore them.
+ m_stdin_tty_state.Save(STDIN_FILENO, false);
+
+ InitializePythonHome();
+
+ // Python < 3.2 and Python >= 3.2 reversed the ordering requirements for
+ // calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you
+ // call `PyEval_InitThreads` first, and >= 3.2 requires that you call it last.
+#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2) || (PY_MAJOR_VERSION > 3)
+ Py_InitializeEx(0);
+ InitializeThreadsPrivate();
+#else
+ InitializeThreadsPrivate();
+ Py_InitializeEx(0);
+#endif
+ }
+
+ ~InitializePythonRAII()
+ {
+ if (m_was_already_initialized)
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+
+ if (log)
+ {
+ log->Printf("Releasing PyGILState. Returning to state = %slocked\n",
+ m_was_already_initialized == PyGILState_UNLOCKED ? "un" : "");
+ }
+ PyGILState_Release(m_gil_state);
+ }
+ else
+ {
+ // We initialized the threads in this function, just unlock the GIL.
+ PyEval_SaveThread();
+ }
+
+ m_stdin_tty_state.Restore();
+ }
+
+private:
+ void InitializePythonHome()
+ {
+#if defined(LLDB_PYTHON_HOME)
+#if PY_MAJOR_VERSION >= 3
+ size_t size = 0;
+ static wchar_t *g_python_home = Py_DecodeLocale(LLDB_PYTHON_HOME, &size);
+#else
+ static char *g_python_home = LLDB_PYTHON_HOME;
+#endif
+ Py_SetPythonHome(g_python_home);
+#endif
+ }
+
+ void InitializeThreadsPrivate()
+ {
+ if (PyEval_ThreadsInitialized())
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+
+ m_was_already_initialized = true;
+ m_gil_state = PyGILState_Ensure();
+ if (log)
+ {
+ log->Printf("Ensured PyGILState. Previous state = %slocked\n",
+ m_gil_state == PyGILState_UNLOCKED ? "un" : "");
+ }
+ return;
+ }
+
+ // InitThreads acquires the GIL if it hasn't been called before.
+ PyEval_InitThreads();
+ }
+
+ TerminalState m_stdin_tty_state;
+ PyGILState_STATE m_gil_state;
+ bool m_was_already_initialized;
+};
+
+}
ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter,
uint16_t on_entry,
@@ -116,7 +213,7 @@ ScriptInterpreterPython::Locker::DoAcquireLock()
// place outside of Python (e.g. printing to screen, waiting for the network, ...)
// in that case, _PyThreadState_Current will be NULL - and we would be unable
// to set the asynchronous exception - not a desirable situation
- m_python_interpreter->SetThreadState (_PyThreadState_Current);
+ m_python_interpreter->SetThreadState(PyThreadState_Get());
m_python_interpreter->IncrementLockCount();
return true;
}
@@ -156,29 +253,28 @@ ScriptInterpreterPython::Locker::~Locker()
DoFreeLock();
}
-
-ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) :
- ScriptInterpreter (interpreter, eScriptLanguagePython),
+ScriptInterpreterPython::ScriptInterpreterPython(CommandInterpreter &interpreter) :
+ ScriptInterpreter(interpreter, eScriptLanguagePython),
IOHandlerDelegateMultiline("DONE"),
- m_saved_stdin (),
- m_saved_stdout (),
- m_saved_stderr (),
- m_main_module (),
- m_lldb_module (),
- m_session_dict (false), // Don't create an empty dictionary, leave it invalid
- m_sys_module_dict (false), // Don't create an empty dictionary, leave it invalid
- m_run_one_line_function (),
- m_run_one_line_str_global (),
- m_dictionary_name (interpreter.GetDebugger().GetInstanceName().AsCString()),
- m_terminal_state (),
- m_active_io_handler (eIOHandlerNone),
- m_session_is_active (false),
- m_pty_slave_is_open (false),
- m_valid_session (true),
- m_lock_count (0),
- m_command_thread_state (nullptr)
-{
- assert(g_initialized && "ScriptInterpreterPython created but initialize has not been called!");
+ m_saved_stdin(),
+ m_saved_stdout(),
+ m_saved_stderr(),
+ m_main_module(),
+ m_lldb_module(),
+ m_session_dict(PyInitialValue::Invalid),
+ m_sys_module_dict(PyInitialValue::Invalid),
+ m_run_one_line_function(),
+ m_run_one_line_str_global(),
+ m_dictionary_name(interpreter.GetDebugger().GetInstanceName().AsCString()),
+ m_terminal_state(),
+ m_active_io_handler(eIOHandlerNone),
+ m_session_is_active(false),
+ m_pty_slave_is_open(false),
+ m_valid_session(true),
+ m_lock_count(0),
+ m_command_thread_state(nullptr)
+{
+ assert(g_initialized && "ScriptInterpreterPython created but InitializePrivate has not been called!");
m_dictionary_name.append("_dict");
StreamString run_string;
@@ -190,10 +286,15 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete
PyRun_SimpleString (run_string.GetData());
run_string.Clear();
-
run_string.Printf ("run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')", m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
+ // Reloading modules requires a different syntax in Python 2 and Python 3. This provides
+ // a consistent syntax no matter what version of Python.
+ run_string.Clear();
+ run_string.Printf("run_one_line (%s, 'from six.moves import reload_module')", m_dictionary_name.c_str());
+ PyRun_SimpleString(run_string.GetData());
+
// WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set
// and letting the individual formatter classes exploit APIs to check whether they can/cannot do their task
run_string.Clear();
@@ -212,6 +313,67 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete
ScriptInterpreterPython::~ScriptInterpreterPython ()
{
+ // the session dictionary may hold objects with complex state
+ // which means that they may need to be torn down with some level of smarts
+ // and that, in turn, requires a valid thread state
+ // force Python to procure itself such a thread state, nuke the session dictionary
+ // and then release it for others to use and proceed with the rest of the shutdown
+ auto gil_state = PyGILState_Ensure();
+ m_session_dict.Reset();
+ PyGILState_Release(gil_state);
+}
+
+void
+ScriptInterpreterPython::Initialize()
+{
+ static std::once_flag g_once_flag;
+
+ std::call_once(g_once_flag, []()
+ {
+ InitializePrivate();
+
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ lldb::eScriptLanguagePython,
+ CreateInstance);
+ });
+}
+
+void
+ScriptInterpreterPython::Terminate()
+{
+
+}
+
+lldb::ScriptInterpreterSP
+ScriptInterpreterPython::CreateInstance(CommandInterpreter &interpreter)
+{
+ return std::make_shared<ScriptInterpreterPython>(interpreter);
+}
+
+lldb_private::ConstString
+ScriptInterpreterPython::GetPluginNameStatic()
+{
+ static ConstString g_name("script-python");
+ return g_name;
+}
+
+const char *
+ScriptInterpreterPython::GetPluginDescriptionStatic()
+{
+ return "Embedded Python interpreter";
+}
+
+lldb_private::ConstString
+ScriptInterpreterPython::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ScriptInterpreterPython::GetPluginVersion()
+{
+ return 1;
}
void
@@ -361,21 +523,21 @@ ScriptInterpreterPython::LeaveSession ()
if (PyThreadState_GetDict())
{
PythonDictionary &sys_module_dict = GetSysModuleDictionary ();
- if (sys_module_dict)
+ if (sys_module_dict.IsValid())
{
- if (m_saved_stdin)
+ if (m_saved_stdin.IsValid())
{
- sys_module_dict.SetItemForKey("stdin", m_saved_stdin);
+ sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);
m_saved_stdin.Reset ();
}
- if (m_saved_stdout)
+ if (m_saved_stdout.IsValid())
{
- sys_module_dict.SetItemForKey("stdout", m_saved_stdout);
+ sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);
m_saved_stdout.Reset ();
}
- if (m_saved_stderr)
+ if (m_saved_stderr.IsValid())
{
- sys_module_dict.SetItemForKey("stderr", m_saved_stderr);
+ sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);
m_saved_stderr.Reset ();
}
}
@@ -384,13 +546,6 @@ ScriptInterpreterPython::LeaveSession ()
m_session_is_active = false;
}
-static PyObject *
-PyFile_FromFile_Const(FILE *fp, const char *name, const char *mode, int (*close)(FILE *))
-{
- // Read through the Python source, doesn't seem to modify these strings
- return PyFile_FromFile(fp, const_cast<char*>(name), const_cast<char*>(mode), close);
-}
-
bool
ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags,
FILE *in,
@@ -437,12 +592,16 @@ ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags,
run_string.Clear();
PythonDictionary &sys_module_dict = GetSysModuleDictionary ();
- if (sys_module_dict)
+ if (sys_module_dict.IsValid())
{
+ File in_file(in, false);
+ File out_file(out, false);
+ File err_file(err, false);
+
lldb::StreamFileSP in_sp;
lldb::StreamFileSP out_sp;
lldb::StreamFileSP err_sp;
- if (in == nullptr || out == nullptr || err == nullptr)
+ if (!in_file.IsValid() || !out_file.IsValid() || !err_file.IsValid())
m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp);
m_saved_stdin.Reset();
@@ -450,40 +609,46 @@ ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags,
if ((on_entry_flags & Locker::NoSTDIN) == 0)
{
// STDIN is enabled
- if (in == nullptr && in_sp)
- in = in_sp->GetFile().GetStream();
- if (in)
+ if (!in_file.IsValid() && in_sp)
+ in_file = in_sp->GetFile();
+ if (in_file.IsValid())
{
- m_saved_stdin.Reset(sys_module_dict.GetItemForKey("stdin"));
+ // Flush the file before giving it to python to avoid interleaved output.
+ in_file.Flush();
+
+ m_saved_stdin = sys_module_dict.GetItemForKey(PythonString("stdin")).AsType<PythonFile>();
// This call can deadlock your process if the file is locked
- PyObject *new_file = PyFile_FromFile_Const (in, "", "r", nullptr);
- sys_module_dict.SetItemForKey ("stdin", new_file);
- Py_DECREF (new_file);
+ PythonFile new_file(in_file, "r");
+ sys_module_dict.SetItemForKey (PythonString("stdin"), new_file);
}
}
- if (out == nullptr && out_sp)
- out = out_sp->GetFile().GetStream();
- if (out)
+ if (!out_file.IsValid() && out_sp)
+ out_file = out_sp->GetFile();
+ if (out_file.IsValid())
{
- m_saved_stdout.Reset(sys_module_dict.GetItemForKey("stdout"));
+ // Flush the file before giving it to python to avoid interleaved output.
+ out_file.Flush();
+
+ m_saved_stdout = sys_module_dict.GetItemForKey(PythonString("stdout")).AsType<PythonFile>();
- PyObject *new_file = PyFile_FromFile_Const (out, "", "w", nullptr);
- sys_module_dict.SetItemForKey ("stdout", new_file);
- Py_DECREF (new_file);
+ PythonFile new_file(out_file, "w");
+ sys_module_dict.SetItemForKey (PythonString("stdout"), new_file);
}
else
m_saved_stdout.Reset();
- if (err == nullptr && err_sp)
- err = err_sp->GetFile().GetStream();
- if (err)
+ if (!err_file.IsValid() && err_sp)
+ err_file = err_sp->GetFile();
+ if (err_file.IsValid())
{
- m_saved_stderr.Reset(sys_module_dict.GetItemForKey("stderr"));
+ // Flush the file before giving it to python to avoid interleaved output.
+ err_file.Flush();
- PyObject *new_file = PyFile_FromFile_Const (err, "", "w", nullptr);
- sys_module_dict.SetItemForKey ("stderr", new_file);
- Py_DECREF (new_file);
+ m_saved_stderr = sys_module_dict.GetItemForKey(PythonString("stderr")).AsType<PythonFile>();
+
+ PythonFile new_file(err_file, "w");
+ sys_module_dict.SetItemForKey (PythonString("stderr"), new_file);
}
else
m_saved_stderr.Reset();
@@ -496,40 +661,41 @@ ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags,
}
PythonObject &
-ScriptInterpreterPython::GetMainModule ()
+ScriptInterpreterPython::GetMainModule()
{
- if (!m_main_module)
- m_main_module.Reset(PyImport_AddModule ("__main__"));
+ if (!m_main_module.IsValid())
+ m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__"));
return m_main_module;
}
PythonDictionary &
ScriptInterpreterPython::GetSessionDictionary ()
{
- if (!m_session_dict)
- {
- PythonObject &main_module = GetMainModule ();
- if (main_module)
- {
- PythonDictionary main_dict(PyModule_GetDict (main_module.get()));
- if (main_dict)
- {
- m_session_dict = main_dict.GetItemForKey(m_dictionary_name.c_str());
- }
- }
- }
+ if (m_session_dict.IsValid())
+ return m_session_dict;
+
+ PythonObject &main_module = GetMainModule();
+ if (!main_module.IsValid())
+ return m_session_dict;
+
+ PythonDictionary main_dict(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
+ if (!main_dict.IsValid())
+ return m_session_dict;
+
+ PythonObject item = main_dict.GetItemForKey(PythonString(m_dictionary_name));
+ m_session_dict.Reset(PyRefType::Borrowed, item.get());
return m_session_dict;
}
PythonDictionary &
ScriptInterpreterPython::GetSysModuleDictionary ()
{
- if (!m_sys_module_dict)
- {
- PyObject *sys_module = PyImport_AddModule ("sys");
- if (sys_module)
- m_sys_module_dict.Reset(PyModule_GetDict (sys_module));
- }
+ if (m_sys_module_dict.IsValid())
+ return m_sys_module_dict;
+
+ PythonObject sys_module(PyRefType::Borrowed, PyImport_AddModule("sys"));
+ if (sys_module.IsValid())
+ m_sys_module_dict.Reset(PyRefType::Borrowed, PyModule_GetDict(sys_module.get()));
return m_sys_module_dict;
}
@@ -554,20 +720,20 @@ GenerateUniqueName (const char* base_name_wanted,
bool
ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects ()
{
- if (!m_run_one_line_function)
- {
- PyObject *module = PyImport_AddModule ("lldb.embedded_interpreter");
- if (module != nullptr)
- {
- PythonDictionary module_dict (PyModule_GetDict (module));
- if (module_dict)
- {
- m_run_one_line_function = module_dict.GetItemForKey("run_one_line");
- m_run_one_line_str_global = module_dict.GetItemForKey("g_run_one_line_str");
- }
- }
- }
- return (bool)m_run_one_line_function;
+ if (m_run_one_line_function.IsValid())
+ return true;
+
+ PythonObject module(PyRefType::Borrowed, PyImport_AddModule ("lldb.embedded_interpreter"));
+ if (!module.IsValid())
+ return false;
+
+ PythonDictionary module_dict(PyRefType::Borrowed, PyModule_GetDict(module.get()));
+ if (!module_dict.IsValid())
+ return false;
+
+ m_run_one_line_function = module_dict.GetItemForKey(PythonString("run_one_line"));
+ m_run_one_line_str_global = module_dict.GetItemForKey(PythonString("g_run_one_line_str"));
+ return m_run_one_line_function.IsValid();
}
static void
@@ -641,58 +807,64 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec
else
{
input_file_sp.reset (new StreamFile ());
- input_file_sp->GetFile().Open("/dev/null", File::eOpenOptionRead);
+ input_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionRead);
output_file_sp.reset (new StreamFile ());
- output_file_sp->GetFile().Open("/dev/null", File::eOpenOptionWrite);
+ output_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionWrite);
error_file_sp = output_file_sp;
}
FILE *in_file = input_file_sp->GetFile().GetStream();
FILE *out_file = output_file_sp->GetFile().GetStream();
FILE *err_file = error_file_sp->GetFile().GetStream();
- Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock |
- ScriptInterpreterPython::Locker::InitSession |
- (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) |
- ((result && result->GetInteractive()) ? 0: Locker::NoSTDIN),
- ScriptInterpreterPython::Locker::FreeAcquiredLock |
- ScriptInterpreterPython::Locker::TearDownSession,
- in_file,
- out_file,
- err_file);
-
bool success = false;
-
- // Find the correct script interpreter dictionary in the main module.
- PythonDictionary &session_dict = GetSessionDictionary ();
- if (session_dict)
{
- if (GetEmbeddedInterpreterModuleObjects ())
+ // WARNING! It's imperative that this RAII scope be as tight as possible. In particular, the
+ // scope must end *before* we try to join the read thread. The reason for this is that a
+ // pre-requisite for joining the read thread is that we close the write handle (to break the
+ // pipe and cause it to wake up and exit). But acquiring the GIL as below will redirect Python's
+ // stdio to use this same handle. If we close the handle while Python is still using it, bad
+ // things will happen.
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock |
+ ScriptInterpreterPython::Locker::InitSession |
+ (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) |
+ ((result && result->GetInteractive()) ? 0: Locker::NoSTDIN),
+ ScriptInterpreterPython::Locker::FreeAcquiredLock |
+ ScriptInterpreterPython::Locker::TearDownSession,
+ in_file,
+ out_file,
+ err_file);
+
+ // Find the correct script interpreter dictionary in the main module.
+ PythonDictionary &session_dict = GetSessionDictionary ();
+ if (session_dict.IsValid())
{
- PyObject *pfunc = m_run_one_line_function.get();
-
- if (pfunc && PyCallable_Check (pfunc))
+ if (GetEmbeddedInterpreterModuleObjects ())
{
- PythonObject pargs (Py_BuildValue("(Os)", session_dict.get(), command));
- if (pargs)
+ if (PyCallable_Check(m_run_one_line_function.get()))
{
- PythonObject return_value(PyObject_CallObject (pfunc, pargs.get()));
- if (return_value)
- success = true;
- else if (options.GetMaskoutErrors() && PyErr_Occurred ())
+ PythonObject pargs(PyRefType::Owned, Py_BuildValue("(Os)", session_dict.get(), command));
+ if (pargs.IsValid())
{
- PyErr_Print();
- PyErr_Clear();
+ PythonObject return_value(PyRefType::Owned,
+ PyObject_CallObject(m_run_one_line_function.get(), pargs.get()));
+ if (return_value.IsValid())
+ success = true;
+ else if (options.GetMaskoutErrors() && PyErr_Occurred ())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
}
}
}
}
- }
- // Flush our output and error file handles
- ::fflush (out_file);
- if (out_file != err_file)
- ::fflush (err_file);
+ // Flush our output and error file handles
+ ::fflush (out_file);
+ if (out_file != err_file)
+ ::fflush (err_file);
+ }
if (join_read_thread)
{
@@ -847,13 +1019,13 @@ ScriptInterpreterPython::Interrupt()
if (IsExecutingPython())
{
- PyThreadState* state = _PyThreadState_Current;
+ PyThreadState *state = PyThreadState_Get();
if (!state)
state = GetThreadState();
if (state)
{
long tid = state->thread_id;
- _PyThreadState_Current = state;
+ PyThreadState_Swap(state);
int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
if (log)
log->Printf("ScriptInterpreterPython::Interrupt() sending PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid, num_threads);
@@ -876,139 +1048,140 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN,
ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
- PyObject *py_return = nullptr;
- PythonObject &main_module = GetMainModule ();
- PythonDictionary globals (PyModule_GetDict(main_module.get()));
- PyObject *py_error = nullptr;
+ PythonObject py_return;
+ PythonObject &main_module = GetMainModule();
+ PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
+ PythonObject py_error;
bool ret_success = false;
int success;
PythonDictionary locals = GetSessionDictionary ();
- if (!locals)
+ if (!locals.IsValid())
{
- locals = PyObject_GetAttrString (globals.get(), m_dictionary_name.c_str());
+ locals.Reset(PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
}
- if (!locals)
+ if (!locals.IsValid())
locals = globals;
- py_error = PyErr_Occurred();
- if (py_error != nullptr)
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
PyErr_Clear();
if (in_string != nullptr)
{
{ // scope for PythonInputReaderManager
//PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
- py_return = PyRun_String (in_string, Py_eval_input, globals.get(), locals.get());
- if (py_return == nullptr)
- {
- py_error = PyErr_Occurred ();
- if (py_error != nullptr)
- PyErr_Clear ();
-
- py_return = PyRun_String (in_string, Py_single_input, globals.get(), locals.get());
+ py_return.Reset(PyRefType::Owned, PyRun_String(in_string, Py_eval_input, globals.get(), locals.get()));
+ if (!py_return.IsValid())
+ {
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
+ PyErr_Clear();
+
+ py_return.Reset(PyRefType::Owned, PyRun_String(in_string, Py_single_input, globals.get(), locals.get()));
}
}
- if (py_return != nullptr)
+ if (py_return.IsValid())
{
switch (return_type)
{
case eScriptReturnTypeCharPtr: // "char *"
{
const char format[3] = "s#";
- success = PyArg_Parse (py_return, format, (char **) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (char **) ret_value);
break;
}
case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == Py_None
{
const char format[3] = "z";
- success = PyArg_Parse (py_return, format, (char **) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (char **) ret_value);
break;
}
case eScriptReturnTypeBool:
{
const char format[2] = "b";
- success = PyArg_Parse (py_return, format, (bool *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (bool *) ret_value);
break;
}
case eScriptReturnTypeShortInt:
{
const char format[2] = "h";
- success = PyArg_Parse (py_return, format, (short *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (short *) ret_value);
break;
}
case eScriptReturnTypeShortIntUnsigned:
{
const char format[2] = "H";
- success = PyArg_Parse (py_return, format, (unsigned short *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (unsigned short *) ret_value);
break;
}
case eScriptReturnTypeInt:
{
const char format[2] = "i";
- success = PyArg_Parse (py_return, format, (int *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (int *) ret_value);
break;
}
case eScriptReturnTypeIntUnsigned:
{
const char format[2] = "I";
- success = PyArg_Parse (py_return, format, (unsigned int *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (unsigned int *) ret_value);
break;
}
case eScriptReturnTypeLongInt:
{
const char format[2] = "l";
- success = PyArg_Parse (py_return, format, (long *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (long *) ret_value);
break;
}
case eScriptReturnTypeLongIntUnsigned:
{
const char format[2] = "k";
- success = PyArg_Parse (py_return, format, (unsigned long *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (unsigned long *) ret_value);
break;
}
case eScriptReturnTypeLongLong:
{
const char format[2] = "L";
- success = PyArg_Parse (py_return, format, (long long *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (long long *) ret_value);
break;
}
case eScriptReturnTypeLongLongUnsigned:
{
const char format[2] = "K";
- success = PyArg_Parse (py_return, format, (unsigned long long *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (unsigned long long *) ret_value);
break;
}
case eScriptReturnTypeFloat:
{
const char format[2] = "f";
- success = PyArg_Parse (py_return, format, (float *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (float *) ret_value);
break;
}
case eScriptReturnTypeDouble:
{
const char format[2] = "d";
- success = PyArg_Parse (py_return, format, (double *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (double *) ret_value);
break;
}
case eScriptReturnTypeChar:
{
const char format[2] = "c";
- success = PyArg_Parse (py_return, format, (char *) ret_value);
+ success = PyArg_Parse (py_return.get(), format, (char *) ret_value);
break;
}
case eScriptReturnTypeOpaqueObject:
{
success = true;
- Py_XINCREF(py_return);
- *((PyObject**)ret_value) = py_return;
+ PyObject *saved_value = py_return.get();
+ Py_XINCREF(saved_value);
+ *((PyObject **)ret_value) = saved_value;
break;
}
}
- Py_XDECREF (py_return);
+
if (success)
ret_success = true;
else
@@ -1016,13 +1189,13 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
}
}
- py_error = PyErr_Occurred();
- if (py_error != nullptr)
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
{
ret_success = false;
if (options.GetMaskoutErrors())
{
- if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
+ if (PyErr_GivenExceptionMatches (py_error.get(), PyExc_SyntaxError))
PyErr_Print ();
PyErr_Clear();
}
@@ -1041,68 +1214,45 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec
ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
PythonObject return_value;
- PythonObject &main_module = GetMainModule ();
- PythonDictionary globals (PyModule_GetDict(main_module.get()));
- PyObject *py_error = nullptr;
+ PythonObject &main_module = GetMainModule();
+ PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
+ PythonObject py_error;
- PythonDictionary locals = GetSessionDictionary ();
-
- if (!locals)
- {
- locals = PyObject_GetAttrString (globals.get(), m_dictionary_name.c_str());
- }
+ PythonDictionary locals = GetSessionDictionary();
- if (!locals)
- {
+ if (!locals.IsValid())
+ locals.Reset(PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
+
+ if (!locals.IsValid())
locals = globals;
- }
- py_error = PyErr_Occurred();
- if (py_error != nullptr)
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
PyErr_Clear();
if (in_string != nullptr)
{
- struct _node *compiled_node = PyParser_SimpleParseString (in_string, Py_file_input);
- if (compiled_node)
- {
- PyCodeObject *compiled_code = PyNode_Compile (compiled_node, "temp.py");
- if (compiled_code)
- {
- return_value.Reset(PyEval_EvalCode (compiled_code, globals.get(), locals.get()));
- }
- }
- }
+ PythonObject code_object;
+ code_object.Reset(PyRefType::Owned, Py_CompileString(in_string, "temp.py", Py_file_input));
- py_error = PyErr_Occurred ();
- if (py_error != nullptr)
- {
-// puts(in_string);
-// _PyObject_Dump (py_error);
-// PyErr_Print();
-// success = false;
-
- PyObject *type = nullptr;
- PyObject *value = nullptr;
- PyObject *traceback = nullptr;
- PyErr_Fetch (&type,&value,&traceback);
-
- // get the backtrace
- std::string bt = ReadPythonBacktrace(traceback);
-
- if (value && value != Py_None)
- error.SetErrorStringWithFormat("%s\n%s", PyString_AsString(PyObject_Str(value)),bt.c_str());
- else
- error.SetErrorStringWithFormat("%s",bt.c_str());
- Py_XDECREF(type);
- Py_XDECREF(value);
- Py_XDECREF(traceback);
- if (options.GetMaskoutErrors())
+ if (code_object.IsValid())
{
- PyErr_Clear();
+ // In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it takes
+ // a PyObject. They are convertible (hence the function PyCode_Check(PyObject*), so
+ // we have to do the cast for Python 2.x
+#if PY_MAJOR_VERSION >= 3
+ PyObject *py_code_obj = code_object.get();
+#else
+ PyCodeObject *py_code_obj = reinterpret_cast<PyCodeObject *>(code_object.get());
+#endif
+ return_value.Reset(PyRefType::Owned, PyEval_EvalCode(py_code_obj, globals.get(), locals.get()));
}
}
+ PythonExceptionState exception_state(!options.GetMaskoutErrors());
+ if (exception_state.IsError())
+ error.SetErrorString(exception_state.Format().c_str());
+
return error;
}
@@ -1372,53 +1522,42 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugi
if (!generic)
return nullptr;
- PyObject *implementor = (PyObject *)generic->GetValue();
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
- if (implementor == nullptr || implementor == Py_None)
+ if (!implementor.IsAllocated())
return StructuredData::DictionarySP();
- PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
-
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- if (pmeth == nullptr || pmeth == Py_None)
- {
- Py_XDECREF(pmeth);
+
+ if (!pmeth.IsAllocated())
return StructuredData::DictionarySP();
- }
- if (PyCallable_Check(pmeth) == 0)
+ if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
- Py_XDECREF(pmeth);
return StructuredData::DictionarySP();
}
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- Py_XDECREF(pmeth);
// right now we know this function exists and is callable..
- PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr);
-
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
+ assert(PythonDictionary::Check(py_return.get()) && "get_register_info returned unknown object type!");
- PythonDictionary result_dict(py_return);
+ PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
return result_dict.CreateStructuredDictionary();
}
@@ -1437,45 +1576,34 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
if (!generic)
return nullptr;
- PyObject *implementor = (PyObject *)generic->GetValue();
- if (implementor == nullptr || implementor == Py_None)
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
+
+ if (!implementor.IsAllocated())
return StructuredData::ArraySP();
- PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
-
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- if (pmeth == nullptr || pmeth == Py_None)
- {
- Py_XDECREF(pmeth);
+
+ if (!pmeth.IsAllocated())
return StructuredData::ArraySP();
- }
- if (PyCallable_Check(pmeth) == 0)
+ if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
- Py_XDECREF(pmeth);
return StructuredData::ArraySP();
}
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- Py_XDECREF(pmeth);
// right now we know this function exists and is callable..
- PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr);
-
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
@@ -1483,8 +1611,10 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin
PyErr_Clear();
}
- PythonList ResultList(py_return);
- return ResultList.CreateStructuredArray();
+ assert(PythonList::Check(py_return.get()) && "get_thread_info returned unknown object type!");
+
+ PythonList result_list(PyRefType::Borrowed, py_return.get());
+ return result_list.CreateStructuredArray();
}
// GetPythonValueFormatString provides a system independent type safe way to
@@ -1529,44 +1659,31 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData(StructuredData::ObjectSP o
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
if (!generic)
return nullptr;
- PyObject *implementor = (PyObject *)generic->GetValue();
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
- if (implementor == nullptr || implementor == Py_None)
+ if (!implementor.IsAllocated())
return StructuredData::StringSP();
- PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
-
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- if (pmeth == nullptr || pmeth == Py_None)
- {
- Py_XDECREF(pmeth);
+
+ if (!pmeth.IsAllocated())
return StructuredData::StringSP();
- }
- if (PyCallable_Check(pmeth) == 0)
+ if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- Py_XDECREF(pmeth);
return StructuredData::StringSP();
}
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- Py_XDECREF(pmeth);
// right now we know this function exists and is callable..
- PyObject* py_return = PyObject_CallMethod(implementor, callee_name, param_format, tid);
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, param_format, tid));
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
@@ -1574,8 +1691,11 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData(StructuredData::ObjectSP o
PyErr_Print();
PyErr_Clear();
}
- PythonString result_string(py_return);
- return result_string.CreateStructuredString();
+
+ assert(PythonBytes::Check(py_return.get()) && "get_register_data returned unknown object type!");
+
+ PythonBytes result(PyRefType::Borrowed, py_return.get());
+ return result.CreateStructuredString();
}
StructuredData::DictionarySP
@@ -1596,45 +1716,33 @@ ScriptInterpreterPython::OSPlugin_CreateThread(StructuredData::ObjectSP os_plugi
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
if (!generic)
return nullptr;
- PyObject *implementor = (PyObject *)generic->GetValue();
- if (implementor == nullptr || implementor == Py_None)
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
+
+ if (!implementor.IsAllocated())
return StructuredData::DictionarySP();
- PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
-
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- if (pmeth == nullptr || pmeth == Py_None)
- {
- Py_XDECREF(pmeth);
+
+ if (!pmeth.IsAllocated())
return StructuredData::DictionarySP();
- }
- if (PyCallable_Check(pmeth) == 0)
+ if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- Py_XDECREF(pmeth);
return StructuredData::DictionarySP();
}
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- Py_XDECREF(pmeth);
// right now we know this function exists and is callable..
- PyObject* py_return = PyObject_CallMethod(implementor, callee_name, &param_format[0], tid, context);
-
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, &param_format[0], tid, context));
+
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
@@ -1642,7 +1750,9 @@ ScriptInterpreterPython::OSPlugin_CreateThread(StructuredData::ObjectSP os_plugi
PyErr_Clear();
}
- PythonDictionary result_dict(py_return);
+ assert(PythonDictionary::Check(py_return.get()) && "create_thread returned unknown object type!");
+
+ PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
return result_dict.CreateStructuredDictionary();
}
@@ -1756,16 +1866,15 @@ ScriptInterpreterPython::GetDynamicSettings(StructuredData::ObjectSP plugin_modu
if (!generic)
return StructuredData::DictionarySP();
- PyObject *reply_pyobj = nullptr;
-
+ PythonObject reply_pyobj;
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
TargetSP target_sp(target->shared_from_this());
- reply_pyobj = (PyObject *)g_swig_plugin_get(generic->GetValue(), setting_name, target_sp);
+ reply_pyobj.Reset(PyRefType::Owned,
+ (PyObject *)g_swig_plugin_get(generic->GetValue(), setting_name, target_sp));
}
- PythonDictionary py_dict(reply_pyobj);
-
+ PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get());
return py_dict.CreateStructuredDictionary();
}
@@ -2066,7 +2175,7 @@ ScriptInterpreterPython::WatchpointCallbackFunction
}
size_t
-ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &implementor_sp)
+ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &implementor_sp, uint32_t max)
{
if (!implementor_sp)
return 0;
@@ -2084,7 +2193,7 @@ ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &im
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- ret_val = g_swig_calc_children (implementor);
+ ret_val = g_swig_calc_children (implementor, max);
}
return ret_val;
@@ -2244,63 +2353,6 @@ ScriptInterpreterPython::GetSyntheticValue(const StructuredData::ObjectSP &imple
return ret_val;
}
-static std::string
-ReadPythonBacktrace (PyObject* py_backtrace)
-{
- PyObject* traceback_module = nullptr,
- *stringIO_module = nullptr,
- *stringIO_builder = nullptr,
- *stringIO_buffer = nullptr,
- *printTB = nullptr,
- *printTB_args = nullptr,
- *printTB_result = nullptr,
- *stringIO_getvalue = nullptr,
- *printTB_string = nullptr;
-
- std::string retval("backtrace unavailable");
-
- if (py_backtrace && py_backtrace != Py_None)
- {
- traceback_module = PyImport_ImportModule("traceback");
- stringIO_module = PyImport_ImportModule("StringIO");
-
- if (traceback_module && traceback_module != Py_None && stringIO_module && stringIO_module != Py_None)
- {
- stringIO_builder = PyObject_GetAttrString(stringIO_module, "StringIO");
- if (stringIO_builder && stringIO_builder != Py_None)
- {
- stringIO_buffer = PyObject_CallObject(stringIO_builder, nullptr);
- if (stringIO_buffer && stringIO_buffer != Py_None)
- {
- printTB = PyObject_GetAttrString(traceback_module, "print_tb");
- if (printTB && printTB != Py_None)
- {
- printTB_args = Py_BuildValue("OOO",py_backtrace,Py_None,stringIO_buffer);
- printTB_result = PyObject_CallObject(printTB, printTB_args);
- stringIO_getvalue = PyObject_GetAttrString(stringIO_buffer, "getvalue");
- if (stringIO_getvalue && stringIO_getvalue != Py_None)
- {
- printTB_string = PyObject_CallObject (stringIO_getvalue,nullptr);
- if (printTB_string && printTB_string != Py_None && PyString_Check(printTB_string))
- retval.assign(PyString_AsString(printTB_string));
- }
- }
- }
- }
- }
- }
- Py_XDECREF(traceback_module);
- Py_XDECREF(stringIO_module);
- Py_XDECREF(stringIO_builder);
- Py_XDECREF(stringIO_buffer);
- Py_XDECREF(printTB);
- Py_XDECREF(printTB_args);
- Py_XDECREF(printTB_result);
- Py_XDECREF(stringIO_getvalue);
- Py_XDECREF(printTB_string);
- return retval;
-}
-
bool
ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
Process* process,
@@ -2563,7 +2615,7 @@ ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_relo
// this call will fail if the module was not imported in this Debugger before
command_stream.Clear();
command_stream.Printf("sys.getrefcount(%s)",basename.c_str());
- bool was_imported_locally = !(GetSessionDictionary().GetItemForKey(basename.c_str()).IsNULLOrNone());
+ bool was_imported_locally = GetSessionDictionary().GetItemForKey(PythonString(basename)).IsAllocated();
bool was_imported = (was_imported_globally || was_imported_locally);
@@ -2579,9 +2631,9 @@ ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_relo
if (was_imported)
{
if (!was_imported_locally)
- command_stream.Printf("import %s ; reload(%s)",basename.c_str(),basename.c_str());
+ command_stream.Printf("import %s ; reload_module(%s)",basename.c_str(),basename.c_str());
else
- command_stream.Printf("reload(%s)",basename.c_str());
+ command_stream.Printf("reload_module(%s)",basename.c_str());
}
else
command_stream.Printf("import %s",basename.c_str());
@@ -2817,63 +2869,47 @@ ScriptInterpreterPython::GetShortHelpForCommandObject (StructuredData::GenericSP
if (!cmd_obj_sp)
return false;
-
- PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue();
-
- if (implementor == nullptr || implementor == Py_None)
+
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
return false;
-
- PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
-
+
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- if (pmeth == nullptr || pmeth == Py_None)
- {
- Py_XDECREF(pmeth);
+
+ if (!pmeth.IsAllocated())
return false;
- }
- if (PyCallable_Check(pmeth) == 0)
+ if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- Py_XDECREF(pmeth);
return false;
}
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- Py_XDECREF(pmeth);
// right now we know this function exists and is callable..
- PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr);
-
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
-
- if (py_return != nullptr && py_return != Py_None)
+
+ if (py_return.IsAllocated() && PythonString::Check(py_return.get()))
{
- if (PyString_Check(py_return))
- {
- dest.assign(PyString_AsString(py_return));
- got_string = true;
- }
+ PythonString py_string(PyRefType::Borrowed, py_return.get());
+ llvm::StringRef return_data(py_string.GetString());
+ dest.assign(return_data.data(), return_data.size());
+ got_string = true;
}
- Py_XDECREF(py_return);
-
return got_string;
}
@@ -2890,61 +2926,45 @@ ScriptInterpreterPython::GetFlagsForCommandObject (StructuredData::GenericSP cmd
if (!cmd_obj_sp)
return result;
-
- PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue();
-
- if (implementor == nullptr || implementor == Py_None)
+
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
return result;
-
- PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
-
+
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- if (pmeth == nullptr || pmeth == Py_None)
- {
- Py_XDECREF(pmeth);
+
+ if (!pmeth.IsAllocated())
return result;
- }
- if (PyCallable_Check(pmeth) == 0)
+ if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- Py_XDECREF(pmeth);
return result;
}
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- Py_XDECREF(pmeth);
// right now we know this function exists and is callable..
- PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr);
-
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
-
- if (py_return != nullptr && py_return != Py_None)
+
+ if (py_return.IsAllocated() && PythonInteger::Check(py_return.get()))
{
- if (PyInt_Check(py_return))
- result = (uint32_t)PyInt_AsLong(py_return);
- else if (PyLong_Check(py_return))
- result = (uint32_t)PyLong_AsLong(py_return);
+ PythonInteger int_value(PyRefType::Borrowed, py_return.get());
+ result = int_value.GetInteger();
}
- Py_XDECREF(py_return);
return result;
}
@@ -2964,62 +2984,48 @@ ScriptInterpreterPython::GetLongHelpForCommandObject (StructuredData::GenericSP
if (!cmd_obj_sp)
return false;
-
- PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue();
-
- if (implementor == nullptr || implementor == Py_None)
+
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
return false;
-
- PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
-
+
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- if (pmeth == nullptr || pmeth == Py_None)
- {
- Py_XDECREF(pmeth);
+
+ if (!pmeth.IsAllocated())
return false;
- }
- if (PyCallable_Check(pmeth) == 0)
+ if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
- Py_XDECREF(pmeth);
return false;
}
if (PyErr_Occurred())
- {
PyErr_Clear();
- }
-
- Py_XDECREF(pmeth);
// right now we know this function exists and is callable..
- PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr);
-
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
-
- if (py_return != nullptr && py_return != Py_None)
+
+ if (py_return.IsAllocated() && PythonString::Check(py_return.get()))
{
- if (PyString_Check(py_return))
- {
- dest.assign(PyString_AsString(py_return));
- got_string = true;
- }
+ PythonString str(PyRefType::Borrowed, py_return.get());
+ llvm::StringRef str_data(str.GetString());
+ dest.assign(str_data.data(), str_data.size());
+ got_string = true;
}
- Py_XDECREF(py_return);
return got_string;
}
@@ -3097,27 +3103,10 @@ ScriptInterpreterPython::InitializePrivate ()
Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
- // Python will muck with STDIN terminal state, so save off any current TTY
- // settings so we can restore them.
- TerminalState stdin_tty_state;
- stdin_tty_state.Save(STDIN_FILENO, false);
-
-#if defined(LLDB_PYTHON_HOME)
- Py_SetPythonHome(LLDB_PYTHON_HOME);
-#endif
- PyGILState_STATE gstate;
- Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
- bool threads_already_initialized = false;
- if (PyEval_ThreadsInitialized ()) {
- gstate = PyGILState_Ensure ();
- if (log)
- log->Printf("Ensured PyGILState. Previous state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : "");
- threads_already_initialized = true;
- } else {
- // InitThreads acquires the GIL if it hasn't been called before.
- PyEval_InitThreads ();
- }
- Py_InitializeEx (0);
+ // RAII-based initialization which correctly handles multiple-initialization, version-
+ // specific differences among Python 2 and Python 3, and saving and restoring various
+ // other pieces of state that can get mucked with during initialization.
+ InitializePythonRAII initialize_guard;
if (g_swig_init_callback)
g_swig_init_callback ();
@@ -3138,17 +3127,6 @@ ScriptInterpreterPython::InitializePrivate ()
AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line");
-
- if (threads_already_initialized) {
- if (log)
- log->Printf("Releasing PyGILState. Returning to state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : "");
- PyGILState_Release (gstate);
- } else {
- // We initialized the threads in this function, just unlock the GIL.
- PyEval_SaveThread();
- }
-
- stdin_tty_state.Restore();
}
void
diff --git a/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
index 058058e..4c6eb39 100644
--- a/contrib/llvm/tools/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
@@ -7,9 +7,8 @@
//
//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ScriptInterpreterPython_h_
-#define liblldb_ScriptInterpreterPython_h_
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
#ifdef LLDB_DISABLE_PYTHON
@@ -17,11 +16,18 @@
#else
-#include "lldb/lldb-python.h"
+// C Includes
+// C++ Includes
+#include <memory>
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
+#include "PythonDataObjects.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Interpreter/PythonDataObjects.h"
#include "lldb/Host/Terminal.h"
class IOHandlerPythonInterpreter;
@@ -33,7 +39,11 @@ class ScriptInterpreterPython :
public IOHandlerDelegateMultiline
{
public:
- typedef void (*SWIGInitCallback) (void);
+#if PY_MAJOR_VERSION >= 3
+ typedef PyObject*(*SWIGInitCallback) (void);
+#else
+ typedef void(*SWIGInitCallback) (void);
+#endif
typedef bool (*SWIGBreakpointCallbackFunction) (const char *python_function_name,
const char *session_dictionary_name,
@@ -70,13 +80,20 @@ public:
const char *session_dictionary_name,
const lldb::ProcessSP& process_sp);
- typedef size_t (*SWIGPythonCalculateNumChildren) (void *implementor);
+ typedef size_t (*SWIGPythonCalculateNumChildren) (void *implementor, uint32_t max);
+
typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx);
+
typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name);
+
typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data);
+
typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue) (void* data);
+
typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data);
+
typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data);
+
typedef void* (*SWIGPythonGetValueSynthProviderInstance) (void *implementor);
typedef bool (*SWIGPythonCallCommand) (const char *python_function_name,
@@ -92,7 +109,6 @@ public:
lldb_private::CommandReturnObject& cmd_retobj,
lldb::ExecutionContextRefSP exe_ctx_ref_sp);
-
typedef bool (*SWIGPythonCallModuleInit) (const char *python_module_name,
const char *session_dictionary_name,
lldb::DebuggerSP& debugger);
@@ -101,6 +117,7 @@ public:
const char* session_dictionary_name,
lldb::ProcessSP& process,
std::string& output);
+
typedef bool (*SWIGPythonScriptKeyword_Thread) (const char* python_function_name,
const char* session_dictionary_name,
lldb::ThreadSP& thread,
@@ -129,7 +146,7 @@ public:
ScriptInterpreterPython (CommandInterpreter &interpreter);
- ~ScriptInterpreterPython ();
+ ~ScriptInterpreterPython() override;
bool
Interrupt() override;
@@ -156,17 +173,17 @@ public:
ExportFunctionDefinitionToInterpreter (StringList &function_def) override;
bool
- GenerateTypeScriptFunction (StringList &input, std::string& output, const void* name_token = NULL) override;
+ GenerateTypeScriptFunction(StringList &input, std::string& output, const void* name_token = nullptr) override;
bool
- GenerateTypeSynthClass (StringList &input, std::string& output, const void* name_token = NULL) override;
+ GenerateTypeSynthClass(StringList &input, std::string& output, const void* name_token = nullptr) override;
bool
- GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token = NULL) override;
+ GenerateTypeSynthClass(const char* oneliner, std::string& output, const void* name_token = nullptr) override;
// use this if the function code is just a one-liner script
bool
- GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token = NULL) override;
+ GenerateTypeScriptFunction(const char* oneliner, std::string& output, const void* name_token = nullptr) override;
bool
GenerateScriptAliasFunction (StringList &input, std::string& output) override;
@@ -178,7 +195,9 @@ public:
StructuredData::ObjectSP CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan) override;
bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override;
+
bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override;
+
lldb::StateType ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) override;
StructuredData::GenericSP OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp) override;
@@ -197,7 +216,7 @@ public:
StructuredData::DictionarySP GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name,
lldb_private::Error &error) override;
- size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor) override;
+ size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor, uint32_t max) override;
lldb::ValueObjectSP GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) override;
@@ -389,7 +408,6 @@ public:
return m_dictionary_name.c_str();
}
-
PyThreadState *
GetThreadState()
{
@@ -412,40 +430,36 @@ public:
void
IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override;
-protected:
-
- bool
- EnterSession (uint16_t on_entry_flags,
- FILE *in,
- FILE *out,
- FILE *err);
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
- void
- LeaveSession ();
+ static void
+ Terminate();
- void
- SaveTerminalState (int fd);
-
- void
- RestoreTerminalState ();
+ static lldb::ScriptInterpreterSP
+ CreateInstance(CommandInterpreter &interpreter);
- class SynchronicityHandler
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+
+ class Locker : public ScriptInterpreterLocker
{
- private:
- lldb::DebuggerSP m_debugger_sp;
- ScriptedCommandSynchronicity m_synch_wanted;
- bool m_old_asynch;
public:
- SynchronicityHandler(lldb::DebuggerSP,
- ScriptedCommandSynchronicity);
- ~SynchronicityHandler();
- };
-
-public:
- class Locker : public ScriptInterpreterLocker
- {
- public:
-
enum OnEntry
{
AcquireLock = 0x0001,
@@ -461,17 +475,16 @@ public:
TearDownSession = 0x0004
};
- Locker (ScriptInterpreterPython *py_interpreter = NULL,
- uint16_t on_entry = AcquireLock | InitSession,
- uint16_t on_leave = FreeLock | TearDownSession,
- FILE *in = NULL,
- FILE *out = NULL,
- FILE *err = NULL);
+ Locker(ScriptInterpreterPython *py_interpreter = nullptr,
+ uint16_t on_entry = AcquireLock | InitSession,
+ uint16_t on_leave = FreeLock | TearDownSession,
+ FILE *in = nullptr,
+ FILE *out = nullptr,
+ FILE *err = nullptr);
- ~Locker ();
+ ~Locker () override;
- private:
-
+ private:
bool
DoAcquireLock ();
@@ -491,8 +504,23 @@ public:
ScriptInterpreterPython *m_python_interpreter;
// FILE* m_tmp_fh;
PyGILState_STATE m_GILState;
- };
+ };
+
protected:
+ class SynchronicityHandler
+ {
+ private:
+ lldb::DebuggerSP m_debugger_sp;
+ ScriptedCommandSynchronicity m_synch_wanted;
+ bool m_old_asynch;
+
+ public:
+ SynchronicityHandler(lldb::DebuggerSP,
+ ScriptedCommandSynchronicity);
+
+ ~SynchronicityHandler();
+ };
+
enum class AddLocation
{
Beginning,
@@ -501,6 +529,21 @@ protected:
static void AddToSysPath(AddLocation location, std::string path);
+ bool
+ EnterSession(uint16_t on_entry_flags,
+ FILE *in,
+ FILE *out,
+ FILE *err);
+
+ void
+ LeaveSession();
+
+ void
+ SaveTerminalState(int fd);
+
+ void
+ RestoreTerminalState();
+
uint32_t
IsExecutingPython () const
{
@@ -526,9 +569,9 @@ protected:
eIOHandlerBreakpoint,
eIOHandlerWatchpoint
};
- PythonObject &
- GetMainModule ();
-
+
+ PythonObject &GetMainModule();
+
PythonDictionary &
GetSessionDictionary ();
@@ -537,10 +580,10 @@ protected:
bool
GetEmbeddedInterpreterModuleObjects ();
-
- PythonObject m_saved_stdin;
- PythonObject m_saved_stdout;
- PythonObject m_saved_stderr;
+
+ PythonFile m_saved_stdin;
+ PythonFile m_saved_stdout;
+ PythonFile m_saved_stderr;
PythonObject m_main_module;
PythonObject m_lldb_module;
PythonDictionary m_session_dict;
@@ -556,8 +599,9 @@ protected:
uint32_t m_lock_count;
PyThreadState *m_command_thread_state;
};
+
} // namespace lldb_private
-#endif // #ifdef LLDB_DISABLE_PYTHON
+#endif // LLDB_DISABLE_PYTHON
-#endif // #ifndef liblldb_ScriptInterpreterPython_h_
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
diff --git a/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
new file mode 100644
index 0000000..013492c
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
@@ -0,0 +1,31 @@
+//===-- lldb-python.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
+
+// Python.h needs to be included before any system headers in order to avoid redefinition of macros
+
+#ifdef LLDB_DISABLE_PYTHON
+// Python is disabled in this build
+#else
+#if defined(__linux__)
+// features.h will define _POSIX_C_SOURCE if _GNU_SOURCE is defined. This value
+// may be different from the value that Python defines it to be which results
+// in a warning. Undefine _POSIX_C_SOURCE before including Python.h The same
+// holds for _XOPEN_SOURCE.
+#undef _POSIX_C_SOURCE
+#undef _XOPEN_SOURCE
+#endif
+
+// Include python for non windows machines
+#include <Python.h>
+#endif // LLDB_DISABLE_PYTHON
+
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp
new file mode 100644
index 0000000..c0754a1
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp
@@ -0,0 +1,56 @@
+//===-- DIERef.cpp ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DIERef.h"
+#include "DWARFCompileUnit.h"
+#include "DWARFFormValue.h"
+
+DIERef::DIERef() :
+ cu_offset(DW_INVALID_OFFSET),
+ die_offset(DW_INVALID_OFFSET)
+{}
+
+DIERef::DIERef(dw_offset_t d) :
+ cu_offset(DW_INVALID_OFFSET),
+ die_offset(d)
+{}
+
+DIERef::DIERef(dw_offset_t c, dw_offset_t d) :
+ cu_offset(c),
+ die_offset(d)
+{}
+
+DIERef::DIERef(lldb::user_id_t uid) :
+ cu_offset(uid>>32),
+ die_offset(uid&0xffffffff)
+{}
+
+DIERef::DIERef(const DWARFFormValue& form_value) :
+ cu_offset(DW_INVALID_OFFSET),
+ die_offset(DW_INVALID_OFFSET)
+{
+ if (form_value.IsValid())
+ {
+ const DWARFCompileUnit* dwarf_cu = form_value.GetCompileUnit();
+ if (dwarf_cu)
+ {
+ if (dwarf_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
+ cu_offset = dwarf_cu->GetBaseObjOffset();
+ else
+ cu_offset = dwarf_cu->GetOffset();
+ }
+ die_offset = form_value.Reference();
+ }
+}
+
+lldb::user_id_t
+DIERef::GetUID() const
+{
+ return ((lldb::user_id_t)cu_offset) << 32 | die_offset;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h
new file mode 100644
index 0000000..3df07d5
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h
@@ -0,0 +1,54 @@
+//===-- DIERef.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DIERef_h_
+#define SymbolFileDWARF_DIERef_h_
+
+#include "lldb/Core/dwarf.h"
+#include "lldb/lldb-defines.h"
+
+class DWARFFormValue;
+
+struct DIERef
+{
+ DIERef();
+
+ explicit
+ DIERef(dw_offset_t d);
+
+ DIERef(dw_offset_t c, dw_offset_t d);
+
+ explicit
+ DIERef(lldb::user_id_t uid);
+
+ explicit
+ DIERef(const DWARFFormValue& form_value);
+
+ lldb::user_id_t
+ GetUID() const;
+
+ bool
+ operator< (const DIERef &ref) const
+ {
+ return die_offset < ref.die_offset;
+ }
+
+ bool
+ operator< (const DIERef &ref)
+ {
+ return die_offset < ref.die_offset;
+ }
+
+ dw_offset_t cu_offset;
+ dw_offset_t die_offset;
+};
+
+typedef std::vector<DIERef> DIEArray;
+
+#endif // SymbolFileDWARF_DIERef_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
new file mode 100644
index 0000000..ab20844
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -0,0 +1,65 @@
+//===-- DWARFASTParser.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFASTParser_h_
+#define SymbolFileDWARF_DWARFASTParser_h_
+
+#include "DWARFDefines.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
+
+class DWARFDIE;
+
+class DWARFASTParser
+{
+public:
+ virtual ~DWARFASTParser() {}
+
+ virtual lldb::TypeSP
+ ParseTypeFromDWARF (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ lldb_private::Log *log,
+ bool *type_is_new_ptr) = 0;
+
+ virtual lldb_private::Function *
+ ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die) = 0;
+
+ virtual bool
+ CanCompleteType (const lldb_private::CompilerType &compiler_type)
+ {
+ return false;
+ }
+
+ virtual bool
+ CompleteType (const lldb_private::CompilerType &compiler_type)
+ {
+ return false;
+ }
+
+ virtual bool
+ CompleteTypeFromDWARF (const DWARFDIE &die,
+ lldb_private::Type *type,
+ lldb_private::CompilerType &compiler_type) = 0;
+
+ virtual lldb_private::CompilerDecl
+ GetDeclForUIDFromDWARF (const DWARFDIE &die) = 0;
+
+ virtual lldb_private::CompilerDeclContext
+ GetDeclContextForUIDFromDWARF (const DWARFDIE &die) = 0;
+
+ virtual lldb_private::CompilerDeclContext
+ GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) = 0;
+
+ virtual std::vector<DWARFDIE>
+ GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) = 0;
+};
+
+#endif // SymbolFileDWARF_DWARFASTParser_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
new file mode 100644
index 0000000..74b54d6
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -0,0 +1,4034 @@
+//===-- DWARFASTParserClang.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFASTParserClang.h"
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDeclContext.h"
+#include "DWARFDefines.h"
+#include "DWARFDIE.h"
+#include "DWARFDIECollection.h"
+#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+#include "UniqueDWARFASTType.h"
+
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/TypeMap.h"
+#include "lldb/Target/Language.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+
+#include <map>
+#include <vector>
+
+//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
+
+#ifdef ENABLE_DEBUG_PRINTF
+#include <stdio.h>
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+
+using namespace lldb;
+using namespace lldb_private;
+DWARFASTParserClang::DWARFASTParserClang (ClangASTContext &ast) :
+ m_ast (ast),
+ m_die_to_decl_ctx (),
+ m_decl_ctx_to_die ()
+{
+}
+
+DWARFASTParserClang::~DWARFASTParserClang ()
+{
+}
+
+
+static AccessType
+DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility)
+{
+ switch (dwarf_accessibility)
+ {
+ case DW_ACCESS_public: return eAccessPublic;
+ case DW_ACCESS_private: return eAccessPrivate;
+ case DW_ACCESS_protected: return eAccessProtected;
+ default: break;
+ }
+ return eAccessNone;
+}
+
+static bool
+DeclKindIsCXXClass (clang::Decl::Kind decl_kind)
+{
+ switch (decl_kind)
+ {
+ case clang::Decl::CXXRecord:
+ case clang::Decl::ClassTemplateSpecialization:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+struct BitfieldInfo
+{
+ uint64_t bit_size;
+ uint64_t bit_offset;
+
+ BitfieldInfo () :
+ bit_size (LLDB_INVALID_ADDRESS),
+ bit_offset (LLDB_INVALID_ADDRESS)
+ {
+ }
+
+ void
+ Clear()
+ {
+ bit_size = LLDB_INVALID_ADDRESS;
+ bit_offset = LLDB_INVALID_ADDRESS;
+ }
+
+ bool IsValid ()
+ {
+ return (bit_size != LLDB_INVALID_ADDRESS) &&
+ (bit_offset != LLDB_INVALID_ADDRESS);
+ }
+};
+
+
+ClangASTImporter &
+DWARFASTParserClang::GetClangASTImporter()
+{
+ if (!m_clang_ast_importer_ap)
+ {
+ m_clang_ast_importer_ap.reset (new ClangASTImporter);
+ }
+ return *m_clang_ast_importer_ap;
+}
+
+
+TypeSP
+DWARFASTParserClang::ParseTypeFromDWO (const DWARFDIE &die, Log *log)
+{
+ ModuleSP dwo_module_sp = die.GetContainingDWOModule();
+ if (dwo_module_sp)
+ {
+ // This type comes from an external DWO module
+ std::vector<CompilerContext> dwo_context;
+ die.GetDWOContext(dwo_context);
+ TypeMap dwo_types;
+ if (dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true, dwo_types))
+ {
+ const size_t num_dwo_types = dwo_types.GetSize();
+ if (num_dwo_types == 1)
+ {
+ // We found a real definition for this type elsewhere
+ // so lets use it and cache the fact that we found
+ // a complete type for this die
+ TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
+ if (dwo_type_sp)
+ {
+ lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType();
+
+ lldb_private::CompilerType type = GetClangASTImporter().CopyType (m_ast, dwo_type);
+
+ //printf ("copied_qual_type: ast = %p, clang_type = %p, name = '%s'\n", m_ast, copied_qual_type.getAsOpaquePtr(), external_type->GetName().GetCString());
+ if (type)
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ TypeSP type_sp (new Type (die.GetID(),
+ dwarf,
+ dwo_type_sp->GetName(),
+ dwo_type_sp->GetByteSize(),
+ NULL,
+ LLDB_INVALID_UID,
+ Type::eEncodingInvalid,
+ &dwo_type_sp->GetDeclaration(),
+ type,
+ Type::eResolveStateForward));
+
+ dwarf->GetTypeList()->Insert(type_sp);
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type);
+ if (tag_decl)
+ LinkDeclContextToDIE(tag_decl, die);
+ else
+ {
+ clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die);
+ if (defn_decl_ctx)
+ LinkDeclContextToDIE(defn_decl_ctx, die);
+ }
+ return type_sp;
+ }
+ }
+ }
+ }
+ }
+ return TypeSP();
+}
+
+TypeSP
+DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
+ const DWARFDIE &die,
+ Log *log,
+ bool *type_is_new_ptr)
+{
+ TypeSP type_sp;
+
+ if (type_is_new_ptr)
+ *type_is_new_ptr = false;
+
+ AccessType accessibility = eAccessNone;
+ if (die)
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ if (log)
+ {
+ DWARFDIE context_die;
+ clang::DeclContext *context = GetClangDeclContextContainingDIE (die, &context_die);
+
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')",
+ die.GetOffset(),
+ static_cast<void*>(context),
+ context_die.GetOffset(),
+ die.GetTagAsCString(),
+ die.GetName());
+
+ }
+ //
+ // Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+ // if (log && dwarf_cu)
+ // {
+ // StreamString s;
+ // die->DumpLocation (this, dwarf_cu, s);
+ // dwarf->GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData());
+ //
+ // }
+
+ Type *type_ptr = dwarf->GetDIEToType().lookup (die.GetDIE());
+ TypeList* type_list = dwarf->GetTypeList();
+ if (type_ptr == NULL)
+ {
+ if (type_is_new_ptr)
+ *type_is_new_ptr = true;
+
+ const dw_tag_t tag = die.Tag();
+
+ bool is_forward_declaration = false;
+ DWARFAttributes attributes;
+ const char *type_name_cstr = NULL;
+ ConstString type_name_const_str;
+ Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
+ uint64_t byte_size = 0;
+ Declaration decl;
+
+ Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
+ CompilerType clang_type;
+ DWARFFormValue form_value;
+
+ dw_attr_t attr;
+
+ switch (tag)
+ {
+ case DW_TAG_base_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
+ case DW_TAG_typedef:
+ case DW_TAG_const_type:
+ case DW_TAG_restrict_type:
+ case DW_TAG_volatile_type:
+ case DW_TAG_unspecified_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ const size_t num_attributes = die.GetAttributes (attributes);
+ uint32_t encoding = 0;
+ lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_name:
+
+ type_name_cstr = form_value.AsCString();
+ // Work around a bug in llvm-gcc where they give a name to a reference type which doesn't
+ // include the "&"...
+ if (tag == DW_TAG_reference_type)
+ {
+ if (strchr (type_name_cstr, '&') == NULL)
+ type_name_cstr = NULL;
+ }
+ if (type_name_cstr)
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+ case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
+ case DW_AT_encoding: encoding = form_value.Unsigned(); break;
+ case DW_AT_type: encoding_uid = DIERef(form_value).GetUID(); break;
+ default:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+ }
+
+ DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid);
+
+ switch (tag)
+ {
+ default:
+ break;
+
+ case DW_TAG_unspecified_type:
+ if (strcmp(type_name_cstr, "nullptr_t") == 0 ||
+ strcmp(type_name_cstr, "decltype(nullptr)") == 0 )
+ {
+ resolve_state = Type::eResolveStateFull;
+ clang_type = m_ast.GetBasicType(eBasicTypeNullPtr);
+ break;
+ }
+ // Fall through to base type below in case we can handle the type there...
+
+ case DW_TAG_base_type:
+ resolve_state = Type::eResolveStateFull;
+ clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize (type_name_cstr,
+ encoding,
+ byte_size * 8);
+ break;
+
+ case DW_TAG_pointer_type: encoding_data_type = Type::eEncodingIsPointerUID; break;
+ case DW_TAG_reference_type: encoding_data_type = Type::eEncodingIsLValueReferenceUID; break;
+ case DW_TAG_rvalue_reference_type: encoding_data_type = Type::eEncodingIsRValueReferenceUID; break;
+ case DW_TAG_typedef: encoding_data_type = Type::eEncodingIsTypedefUID; break;
+ case DW_TAG_const_type: encoding_data_type = Type::eEncodingIsConstUID; break;
+ case DW_TAG_restrict_type: encoding_data_type = Type::eEncodingIsRestrictUID; break;
+ case DW_TAG_volatile_type: encoding_data_type = Type::eEncodingIsVolatileUID; break;
+ }
+
+ if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL)
+ {
+ bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus);
+
+ if (translation_unit_is_objc)
+ {
+ if (type_name_cstr != NULL)
+ {
+ static ConstString g_objc_type_name_id("id");
+ static ConstString g_objc_type_name_Class("Class");
+ static ConstString g_objc_type_name_selector("SEL");
+
+ if (type_name_const_str == g_objc_type_name_id)
+ {
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.",
+ die.GetOffset(),
+ die.GetTagAsCString(),
+ die.GetName());
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
+ encoding_data_type = Type::eEncodingIsUID;
+ encoding_uid = LLDB_INVALID_UID;
+ resolve_state = Type::eResolveStateFull;
+
+ }
+ else if (type_name_const_str == g_objc_type_name_Class)
+ {
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.",
+ die.GetOffset(),
+ die.GetTagAsCString(),
+ die.GetName());
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCClass);
+ encoding_data_type = Type::eEncodingIsUID;
+ encoding_uid = LLDB_INVALID_UID;
+ resolve_state = Type::eResolveStateFull;
+ }
+ else if (type_name_const_str == g_objc_type_name_selector)
+ {
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.",
+ die.GetOffset(),
+ die.GetTagAsCString(),
+ die.GetName());
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCSel);
+ encoding_data_type = Type::eEncodingIsUID;
+ encoding_uid = LLDB_INVALID_UID;
+ resolve_state = Type::eResolveStateFull;
+ }
+ }
+ else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID)
+ {
+ // Clang sometimes erroneously emits id as objc_object*. In that case we fix up the type to "id".
+
+ const DWARFDIE encoding_die = die.GetDIE(encoding_uid);
+
+ if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type)
+ {
+ if (const char *struct_name = encoding_die.GetName())
+ {
+ if (!strcmp(struct_name, "objc_object"))
+ {
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is 'objc_object*', which we overrode to 'id'.",
+ die.GetOffset(),
+ die.GetTagAsCString(),
+ die.GetName());
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
+ encoding_data_type = Type::eEncodingIsUID;
+ encoding_uid = LLDB_INVALID_UID;
+ resolve_state = Type::eResolveStateFull;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ type_sp.reset( new Type (die.GetID(),
+ dwarf,
+ type_name_const_str,
+ byte_size,
+ NULL,
+ encoding_uid,
+ encoding_data_type,
+ &decl,
+ clang_type,
+ resolve_state));
+
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+
+ // Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false);
+ // if (encoding_type != NULL)
+ // {
+ // if (encoding_type != DIE_IS_BEING_PARSED)
+ // type_sp->SetEncodingType(encoding_type);
+ // else
+ // m_indirect_fixups.push_back(type_sp.get());
+ // }
+ }
+ break;
+
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+ bool byte_size_valid = false;
+
+ LanguageType class_language = eLanguageTypeUnknown;
+ bool is_complete_objc_class = false;
+ //bool struct_is_class = false;
+ const size_t num_attributes = die.GetAttributes (attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file:
+ if (die.GetCU()->DW_AT_decl_file_attributes_are_invalid())
+ {
+ // llvm-gcc outputs invalid DW_AT_decl_file attributes that always
+ // point to the compile unit file, so we clear this invalid value
+ // so that we can still unique types efficiently.
+ decl.SetFile(FileSpec ("<invalid>", false));
+ }
+ else
+ decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned()));
+ break;
+
+ case DW_AT_decl_line:
+ decl.SetLine(form_value.Unsigned());
+ break;
+
+ case DW_AT_decl_column:
+ decl.SetColumn(form_value.Unsigned());
+ break;
+
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_byte_size:
+ byte_size = form_value.Unsigned();
+ byte_size_valid = true;
+ break;
+
+ case DW_AT_accessibility:
+ accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
+ break;
+
+ case DW_AT_declaration:
+ is_forward_declaration = form_value.Boolean();
+ break;
+
+ case DW_AT_APPLE_runtime_class:
+ class_language = (LanguageType)form_value.Signed();
+ break;
+
+ case DW_AT_APPLE_objc_complete_type:
+ is_complete_objc_class = form_value.Signed();
+ break;
+
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_data_location:
+ case DW_AT_description:
+ case DW_AT_start_scope:
+ case DW_AT_visibility:
+ default:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+ }
+
+ // UniqueDWARFASTType is large, so don't create a local variables on the
+ // stack, put it on the heap. This function is often called recursively
+ // and clang isn't good and sharing the stack space for variables in different blocks.
+ std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType());
+
+ if (type_name_const_str)
+ {
+ LanguageType die_language = die.GetLanguage();
+ bool handled = false;
+ if (Language::LanguageIsCPlusPlus(die_language))
+ {
+ std::string qualified_name;
+ if (die.GetQualifiedName(qualified_name))
+ {
+ handled = true;
+ ConstString const_qualified_name(qualified_name);
+ if (dwarf->GetUniqueDWARFASTTypeMap().Find(const_qualified_name, die, Declaration(),
+ byte_size_valid ? byte_size : -1,
+ *unique_ast_entry_ap))
+ {
+ type_sp = unique_ast_entry_ap->m_type_sp;
+ if (type_sp)
+ {
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ return type_sp;
+ }
+ }
+ }
+ }
+
+ if (!handled)
+ {
+ if (dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
+ byte_size_valid ? byte_size : -1,
+ *unique_ast_entry_ap))
+ {
+ type_sp = unique_ast_entry_ap->m_type_sp;
+ if (type_sp)
+ {
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ return type_sp;
+ }
+ }
+ }
+ }
+
+ DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr);
+
+ int tag_decl_kind = -1;
+ AccessType default_accessibility = eAccessNone;
+ if (tag == DW_TAG_structure_type)
+ {
+ tag_decl_kind = clang::TTK_Struct;
+ default_accessibility = eAccessPublic;
+ }
+ else if (tag == DW_TAG_union_type)
+ {
+ tag_decl_kind = clang::TTK_Union;
+ default_accessibility = eAccessPublic;
+ }
+ else if (tag == DW_TAG_class_type)
+ {
+ tag_decl_kind = clang::TTK_Class;
+ default_accessibility = eAccessPrivate;
+ }
+
+ if (byte_size_valid && byte_size == 0 && type_name_cstr &&
+ die.HasChildren() == false &&
+ sc.comp_unit->GetLanguage() == eLanguageTypeObjC)
+ {
+ // Work around an issue with clang at the moment where
+ // forward declarations for objective C classes are emitted
+ // as:
+ // DW_TAG_structure_type [2]
+ // DW_AT_name( "ForwardObjcClass" )
+ // DW_AT_byte_size( 0x00 )
+ // DW_AT_decl_file( "..." )
+ // DW_AT_decl_line( 1 )
+ //
+ // Note that there is no DW_AT_declaration and there are
+ // no children, and the byte size is zero.
+ is_forward_declaration = true;
+ }
+
+ if (class_language == eLanguageTypeObjC ||
+ class_language == eLanguageTypeObjC_plus_plus)
+ {
+ if (!is_complete_objc_class && die.Supports_DW_AT_APPLE_objc_complete_type())
+ {
+ // We have a valid eSymbolTypeObjCClass class symbol whose
+ // name matches the current objective C class that we
+ // are trying to find and this DIE isn't the complete
+ // definition (we checked is_complete_objc_class above and
+ // know it is false), so the real definition is in here somewhere
+ type_sp = dwarf->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true);
+
+ if (!type_sp)
+ {
+ SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
+ if (debug_map_symfile)
+ {
+ // We weren't able to find a full declaration in
+ // this DWARF, see if we have a declaration anywhere
+ // else...
+ type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true);
+ }
+ }
+
+ if (type_sp)
+ {
+ if (log)
+ {
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8" PRIx64,
+ static_cast<void*>(this),
+ die.GetOffset(),
+ DW_TAG_value_to_name(tag),
+ type_name_cstr,
+ type_sp->GetID());
+ }
+
+ // We found a real definition for this type elsewhere
+ // so lets use it and cache the fact that we found
+ // a complete type for this die
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ return type_sp;
+ }
+ }
+ }
+
+
+ if (is_forward_declaration)
+ {
+ // We have a forward declaration to a type and we need
+ // to try and find a full declaration. We look in the
+ // current type index just in case we have a forward
+ // declaration followed by an actual declarations in the
+ // DWARF. If this fails, we need to look elsewhere...
+ if (log)
+ {
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type",
+ static_cast<void*>(this),
+ die.GetOffset(),
+ DW_TAG_value_to_name(tag),
+ type_name_cstr);
+ }
+
+ // See if the type comes from a DWO module and if so, track down that type.
+ type_sp = ParseTypeFromDWO(die, log);
+ if (type_sp)
+ return type_sp;
+
+ DWARFDeclContext die_decl_ctx;
+ die.GetDWARFDeclContext(die_decl_ctx);
+
+ //type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str);
+ type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
+
+ if (!type_sp)
+ {
+ SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
+ if (debug_map_symfile)
+ {
+ // We weren't able to find a full declaration in
+ // this DWARF, see if we have a declaration anywhere
+ // else...
+ type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
+ }
+ }
+
+ if (type_sp)
+ {
+ if (log)
+ {
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64,
+ static_cast<void*>(this),
+ die.GetOffset(),
+ DW_TAG_value_to_name(tag),
+ type_name_cstr,
+ type_sp->GetID());
+ }
+
+ // We found a real definition for this type elsewhere
+ // so lets use it and cache the fact that we found
+ // a complete type for this die
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(
+ dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID())));
+ if (defn_decl_ctx)
+ LinkDeclContextToDIE(defn_decl_ctx, die);
+ return type_sp;
+ }
+ }
+ assert (tag_decl_kind != -1);
+ bool clang_type_was_created = false;
+ clang_type.SetCompilerType(&m_ast, dwarf->GetForwardDeclDieToClangType().lookup (die.GetDIE()));
+ if (!clang_type)
+ {
+ clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE (die, nullptr);
+ if (accessibility == eAccessNone && decl_ctx)
+ {
+ // Check the decl context that contains this class/struct/union.
+ // If it is a class we must give it an accessibility.
+ const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind();
+ if (DeclKindIsCXXClass (containing_decl_kind))
+ accessibility = default_accessibility;
+ }
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
+ metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual (die));
+
+ if (type_name_cstr && strchr (type_name_cstr, '<'))
+ {
+ ClangASTContext::TemplateParameterInfos template_param_infos;
+ if (ParseTemplateParameterInfos (die, template_param_infos))
+ {
+ clang::ClassTemplateDecl *class_template_decl = m_ast.ParseClassTemplateDecl (decl_ctx,
+ accessibility,
+ type_name_cstr,
+ tag_decl_kind,
+ template_param_infos);
+
+ clang::ClassTemplateSpecializationDecl *class_specialization_decl = m_ast.CreateClassTemplateSpecializationDecl (decl_ctx,
+ class_template_decl,
+ tag_decl_kind,
+ template_param_infos);
+ clang_type = m_ast.CreateClassTemplateSpecializationType (class_specialization_decl);
+ clang_type_was_created = true;
+
+ m_ast.SetMetadata (class_template_decl, metadata);
+ m_ast.SetMetadata (class_specialization_decl, metadata);
+ }
+ }
+
+ if (!clang_type_was_created)
+ {
+ clang_type_was_created = true;
+ clang_type = m_ast.CreateRecordType (decl_ctx,
+ accessibility,
+ type_name_cstr,
+ tag_decl_kind,
+ class_language,
+ &metadata);
+ }
+ }
+
+ // Store a forward declaration to this class type in case any
+ // parameters in any class methods need it for the clang
+ // types for function prototypes.
+ LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die);
+ type_sp.reset (new Type (die.GetID(),
+ dwarf,
+ type_name_const_str,
+ byte_size,
+ NULL,
+ LLDB_INVALID_UID,
+ Type::eEncodingIsUID,
+ &decl,
+ clang_type,
+ Type::eResolveStateForward));
+
+ type_sp->SetIsCompleteObjCClass(is_complete_objc_class);
+
+
+ // Add our type to the unique type map so we don't
+ // end up creating many copies of the same type over
+ // and over in the ASTContext for our module
+ unique_ast_entry_ap->m_type_sp = type_sp;
+ unique_ast_entry_ap->m_die = die;
+ unique_ast_entry_ap->m_declaration = decl;
+ unique_ast_entry_ap->m_byte_size = byte_size;
+ dwarf->GetUniqueDWARFASTTypeMap().Insert (type_name_const_str,
+ *unique_ast_entry_ap);
+
+ if (is_forward_declaration && die.HasChildren())
+ {
+ // Check to see if the DIE actually has a definition, some version of GCC will
+ // emit DIEs with DW_AT_declaration set to true, but yet still have subprogram,
+ // members, or inheritance, so we can't trust it
+ DWARFDIE child_die = die.GetFirstChild();
+ while (child_die)
+ {
+ switch (child_die.Tag())
+ {
+ case DW_TAG_inheritance:
+ case DW_TAG_subprogram:
+ case DW_TAG_member:
+ case DW_TAG_APPLE_property:
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_typedef:
+ case DW_TAG_union_type:
+ child_die.Clear();
+ is_forward_declaration = false;
+ break;
+ default:
+ child_die = child_die.GetSibling();
+ break;
+ }
+ }
+ }
+
+ if (!is_forward_declaration)
+ {
+ // Always start the definition for a class type so that
+ // if the class has child classes or types that require
+ // the class to be created for use as their decl contexts
+ // the class will be ready to accept these child definitions.
+ if (die.HasChildren() == false)
+ {
+ // No children for this struct/union/class, lets finish it
+ ClangASTContext::StartTagDeclarationDefinition (clang_type);
+ ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
+
+ if (tag == DW_TAG_structure_type) // this only applies in C
+ {
+ clang::RecordDecl *record_decl = ClangASTContext::GetAsRecordDecl(clang_type);
+
+ if (record_decl)
+ m_record_decl_to_layout_map.insert(std::make_pair(record_decl, LayoutInfo()));
+ }
+ }
+ else if (clang_type_was_created)
+ {
+ // Start the definition if the class is not objective C since
+ // the underlying decls respond to isCompleteDefinition(). Objective
+ // C decls don't respond to isCompleteDefinition() so we can't
+ // start the declaration definition right away. For C++ class/union/structs
+ // we want to start the definition in case the class is needed as the
+ // declaration context for a contained class or type without the need
+ // to complete that type..
+
+ if (class_language != eLanguageTypeObjC &&
+ class_language != eLanguageTypeObjC_plus_plus)
+ ClangASTContext::StartTagDeclarationDefinition (clang_type);
+
+ // Leave this as a forward declaration until we need
+ // to know the details of the type. lldb_private::Type
+ // will automatically call the SymbolFile virtual function
+ // "SymbolFileDWARF::CompleteType(Type *)"
+ // When the definition needs to be defined.
+ assert(!dwarf->GetForwardDeclClangTypeToDie().count(ClangASTContext::RemoveFastQualifiers(clang_type).GetOpaqueQualType()) &&
+ "Type already in the forward declaration map!");
+ assert(((SymbolFileDWARF*)m_ast.GetSymbolFile())->UserIDMatches(die.GetDIERef().GetUID()) &&
+ "Adding incorrect type to forward declaration map");
+ dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = clang_type.GetOpaqueQualType();
+ dwarf->GetForwardDeclClangTypeToDie()[ClangASTContext::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = die.GetDIERef();
+ m_ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), true);
+ }
+ }
+ }
+ break;
+
+ case DW_TAG_enumeration_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ DWARFFormValue encoding_form;
+
+ const size_t num_attributes = die.GetAttributes (attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+ case DW_AT_type: encoding_form = form_value; break;
+ case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
+ case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
+ case DW_AT_declaration: is_forward_declaration = form_value.Boolean(); break;
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_bit_stride:
+ case DW_AT_byte_stride:
+ case DW_AT_data_location:
+ case DW_AT_description:
+ case DW_AT_start_scope:
+ case DW_AT_visibility:
+ case DW_AT_specification:
+ case DW_AT_abstract_origin:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+
+ if (is_forward_declaration)
+ {
+ type_sp = ParseTypeFromDWO(die, log);
+ if (type_sp)
+ return type_sp;
+
+ DWARFDeclContext die_decl_ctx;
+ die.GetDWARFDeclContext(die_decl_ctx);
+
+ type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
+
+ if (!type_sp)
+ {
+ SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
+ if (debug_map_symfile)
+ {
+ // We weren't able to find a full declaration in
+ // this DWARF, see if we have a declaration anywhere
+ // else...
+ type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
+ }
+ }
+
+ if (type_sp)
+ {
+ if (log)
+ {
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64,
+ static_cast<void*>(this),
+ die.GetOffset(),
+ DW_TAG_value_to_name(tag),
+ type_name_cstr,
+ type_sp->GetID());
+ }
+
+ // We found a real definition for this type elsewhere
+ // so lets use it and cache the fact that we found
+ // a complete type for this die
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(
+ dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID())));
+ if (defn_decl_ctx)
+ LinkDeclContextToDIE(defn_decl_ctx, die);
+ return type_sp;
+ }
+
+ }
+ DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr);
+
+ CompilerType enumerator_clang_type;
+ clang_type.SetCompilerType (&m_ast, dwarf->GetForwardDeclDieToClangType().lookup (die.GetDIE()));
+ if (!clang_type)
+ {
+ if (encoding_form.IsValid())
+ {
+ Type *enumerator_type = dwarf->ResolveTypeUID(DIERef(encoding_form).GetUID());
+ if (enumerator_type)
+ enumerator_clang_type = enumerator_type->GetFullCompilerType ();
+ }
+
+ if (!enumerator_clang_type)
+ enumerator_clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL,
+ DW_ATE_signed,
+ byte_size * 8);
+
+ clang_type = m_ast.CreateEnumerationType (type_name_cstr,
+ GetClangDeclContextContainingDIE (die, nullptr),
+ decl,
+ enumerator_clang_type);
+ }
+ else
+ {
+ enumerator_clang_type = m_ast.GetEnumerationIntegerType (clang_type.GetOpaqueQualType());
+ }
+
+ LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), die);
+
+ type_sp.reset( new Type (die.GetID(),
+ dwarf,
+ type_name_const_str,
+ byte_size,
+ NULL,
+ DIERef(encoding_form).GetUID(),
+ Type::eEncodingIsUID,
+ &decl,
+ clang_type,
+ Type::eResolveStateForward));
+
+ ClangASTContext::StartTagDeclarationDefinition (clang_type);
+ if (die.HasChildren())
+ {
+ SymbolContext cu_sc(die.GetLLDBCompileUnit());
+ bool is_signed = false;
+ enumerator_clang_type.IsIntegerType(is_signed);
+ ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), die);
+ }
+ ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
+ }
+ }
+ break;
+
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ DWARFFormValue type_die_form;
+ bool is_variadic = false;
+ bool is_inline = false;
+ bool is_static = false;
+ bool is_virtual = false;
+ bool is_explicit = false;
+ bool is_artificial = false;
+ DWARFFormValue specification_die_form;
+ DWARFFormValue abstract_origin_die_form;
+ dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET;
+
+ unsigned type_quals = 0;
+ clang::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern
+
+
+ const size_t num_attributes = die.GetAttributes (attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_linkage_name:
+ case DW_AT_MIPS_linkage_name: break; // mangled = form_value.AsCString(&dwarf->get_debug_str_data()); break;
+ case DW_AT_type: type_die_form = form_value; break;
+ case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
+ case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break;
+ case DW_AT_inline: is_inline = form_value.Boolean(); break;
+ case DW_AT_virtuality: is_virtual = form_value.Boolean(); break;
+ case DW_AT_explicit: is_explicit = form_value.Boolean(); break;
+ case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
+
+
+ case DW_AT_external:
+ if (form_value.Unsigned())
+ {
+ if (storage == clang::SC_None)
+ storage = clang::SC_Extern;
+ else
+ storage = clang::SC_PrivateExtern;
+ }
+ break;
+
+ case DW_AT_specification:
+ specification_die_form = form_value;
+ break;
+
+ case DW_AT_abstract_origin:
+ abstract_origin_die_form = form_value;
+ break;
+
+ case DW_AT_object_pointer:
+ object_pointer_die_offset = form_value.Reference();
+ break;
+
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_address_class:
+ case DW_AT_calling_convention:
+ case DW_AT_data_location:
+ case DW_AT_elemental:
+ case DW_AT_entry_pc:
+ case DW_AT_frame_base:
+ case DW_AT_high_pc:
+ case DW_AT_low_pc:
+ case DW_AT_prototyped:
+ case DW_AT_pure:
+ case DW_AT_ranges:
+ case DW_AT_recursive:
+ case DW_AT_return_addr:
+ case DW_AT_segment:
+ case DW_AT_start_scope:
+ case DW_AT_static_link:
+ case DW_AT_trampoline:
+ case DW_AT_visibility:
+ case DW_AT_vtable_elem_location:
+ case DW_AT_description:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+ }
+
+ std::string object_pointer_name;
+ if (object_pointer_die_offset != DW_INVALID_OFFSET)
+ {
+ DWARFDIE object_pointer_die = die.GetDIE (object_pointer_die_offset);
+ if (object_pointer_die)
+ {
+ const char *object_pointer_name_cstr = object_pointer_die.GetName();
+ if (object_pointer_name_cstr)
+ object_pointer_name = object_pointer_name_cstr;
+ }
+ }
+
+ DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr);
+
+ CompilerType return_clang_type;
+ Type *func_type = NULL;
+
+ if (type_die_form.IsValid())
+ func_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID());
+
+ if (func_type)
+ return_clang_type = func_type->GetForwardCompilerType ();
+ else
+ return_clang_type = m_ast.GetBasicType(eBasicTypeVoid);
+
+
+ std::vector<CompilerType> function_param_types;
+ std::vector<clang::ParmVarDecl*> function_param_decls;
+
+ // Parse the function children for the parameters
+
+ DWARFDIE decl_ctx_die;
+ clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (die, &decl_ctx_die);
+ const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind();
+
+ const bool is_cxx_method = DeclKindIsCXXClass (containing_decl_kind);
+ // Start off static. This will be set to false in ParseChildParameters(...)
+ // if we find a "this" parameters as the first parameter
+ if (is_cxx_method)
+ is_static = true;
+
+ if (die.HasChildren())
+ {
+ bool skip_artificial = true;
+ ParseChildParameters (sc,
+ containing_decl_ctx,
+ die,
+ skip_artificial,
+ is_static,
+ is_variadic,
+ function_param_types,
+ function_param_decls,
+ type_quals);
+ }
+
+ // clang_type will get the function prototype clang type after this call
+ clang_type = m_ast.CreateFunctionType (return_clang_type,
+ function_param_types.data(),
+ function_param_types.size(),
+ is_variadic,
+ type_quals);
+
+ bool ignore_containing_context = false;
+
+ if (type_name_cstr)
+ {
+ bool type_handled = false;
+ if (tag == DW_TAG_subprogram ||
+ tag == DW_TAG_inlined_subroutine)
+ {
+ ObjCLanguage::MethodName objc_method (type_name_cstr, true);
+ if (objc_method.IsValid(true))
+ {
+ CompilerType class_opaque_type;
+ ConstString class_name(objc_method.GetClassName());
+ if (class_name)
+ {
+ TypeSP complete_objc_class_type_sp (dwarf->FindCompleteObjCDefinitionTypeForDIE (DWARFDIE(), class_name, false));
+
+ if (complete_objc_class_type_sp)
+ {
+ CompilerType type_clang_forward_type = complete_objc_class_type_sp->GetForwardCompilerType ();
+ if (ClangASTContext::IsObjCObjectOrInterfaceType(type_clang_forward_type))
+ class_opaque_type = type_clang_forward_type;
+ }
+ }
+
+ if (class_opaque_type)
+ {
+ // If accessibility isn't set to anything valid, assume public for
+ // now...
+ if (accessibility == eAccessNone)
+ accessibility = eAccessPublic;
+
+ clang::ObjCMethodDecl *objc_method_decl = m_ast.AddMethodToObjCObjectType (class_opaque_type,
+ type_name_cstr,
+ clang_type,
+ accessibility,
+ is_artificial);
+ type_handled = objc_method_decl != NULL;
+ if (type_handled)
+ {
+ LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(objc_method_decl), die);
+ m_ast.SetMetadataAsUserID (objc_method_decl, die.GetID());
+ }
+ else
+ {
+ dwarf->GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), please file a bug and attach the file at the start of this error message",
+ die.GetOffset(),
+ tag,
+ DW_TAG_value_to_name(tag));
+ }
+ }
+ }
+ else if (is_cxx_method)
+ {
+ // Look at the parent of this DIE and see if is is
+ // a class or struct and see if this is actually a
+ // C++ method
+ Type *class_type = dwarf->ResolveType (decl_ctx_die);
+ if (class_type)
+ {
+ bool alternate_defn = false;
+ if (class_type->GetID() != decl_ctx_die.GetID() || decl_ctx_die.GetContainingDWOModuleDIE())
+ {
+ alternate_defn = true;
+
+ // We uniqued the parent class of this function to another class
+ // so we now need to associate all dies under "decl_ctx_die" to
+ // DIEs in the DIE for "class_type"...
+ SymbolFileDWARF *class_symfile = NULL;
+ DWARFDIE class_type_die;
+
+ SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
+ if (debug_map_symfile)
+ {
+ class_symfile = debug_map_symfile->GetSymbolFileByOSOIndex(SymbolFileDWARFDebugMap::GetOSOIndexFromUserID(class_type->GetID()));
+ class_type_die = class_symfile->DebugInfo()->GetDIE (DIERef(class_type->GetID()));
+ }
+ else
+ {
+ class_symfile = dwarf;
+ class_type_die = dwarf->DebugInfo()->GetDIE (DIERef(class_type->GetID()));
+ }
+ if (class_type_die)
+ {
+ DWARFDIECollection failures;
+
+ CopyUniqueClassMethodTypes (decl_ctx_die,
+ class_type_die,
+ class_type,
+ failures);
+
+ // FIXME do something with these failures that's smarter than
+ // just dropping them on the ground. Unfortunately classes don't
+ // like having stuff added to them after their definitions are
+ // complete...
+
+ type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
+ if (type_ptr && type_ptr != DIE_IS_BEING_PARSED)
+ {
+ type_sp = type_ptr->shared_from_this();
+ break;
+ }
+ }
+ }
+
+ if (specification_die_form.IsValid())
+ {
+ // We have a specification which we are going to base our function
+ // prototype off of, so we need this type to be completed so that the
+ // m_die_to_decl_ctx for the method in the specification has a valid
+ // clang decl context.
+ class_type->GetForwardCompilerType ();
+ // If we have a specification, then the function type should have been
+ // made with the specification and not with this die.
+ DWARFDIE spec_die = dwarf->DebugInfo()->GetDIE(DIERef(specification_die_form));
+ clang::DeclContext *spec_clang_decl_ctx = GetClangDeclContextForDIE (spec_die);
+ if (spec_clang_decl_ctx)
+ {
+ LinkDeclContextToDIE(spec_clang_decl_ctx, die);
+ }
+ else
+ {
+ dwarf->GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8" PRIx64 ") has no decl\n",
+ die.GetID(),
+ specification_die_form.Reference());
+ }
+ type_handled = true;
+ }
+ else if (abstract_origin_die_form.IsValid())
+ {
+ // We have a specification which we are going to base our function
+ // prototype off of, so we need this type to be completed so that the
+ // m_die_to_decl_ctx for the method in the abstract origin has a valid
+ // clang decl context.
+ class_type->GetForwardCompilerType ();
+
+ DWARFDIE abs_die = dwarf->DebugInfo()->GetDIE (DIERef(abstract_origin_die_form));
+ clang::DeclContext *abs_clang_decl_ctx = GetClangDeclContextForDIE (abs_die);
+ if (abs_clang_decl_ctx)
+ {
+ LinkDeclContextToDIE (abs_clang_decl_ctx, die);
+ }
+ else
+ {
+ dwarf->GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8" PRIx64 ") has no decl\n",
+ die.GetID(),
+ abstract_origin_die_form.Reference());
+ }
+ type_handled = true;
+ }
+ else
+ {
+ CompilerType class_opaque_type = class_type->GetForwardCompilerType ();
+ if (ClangASTContext::IsCXXClassType(class_opaque_type))
+ {
+ if (class_opaque_type.IsBeingDefined () || alternate_defn)
+ {
+ if (!is_static && !die.HasChildren())
+ {
+ // We have a C++ member function with no children (this pointer!)
+ // and clang will get mad if we try and make a function that isn't
+ // well formed in the DWARF, so we will just skip it...
+ type_handled = true;
+ }
+ else
+ {
+ bool add_method = true;
+ if (alternate_defn)
+ {
+ // If an alternate definition for the class exists, then add the method only if an
+ // equivalent is not already present.
+ clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(class_opaque_type.GetOpaqueQualType());
+ if (record_decl)
+ {
+ for (auto method_iter = record_decl->method_begin();
+ method_iter != record_decl->method_end();
+ method_iter++)
+ {
+ clang::CXXMethodDecl *method_decl = *method_iter;
+ if (method_decl->getNameInfo().getAsString() == std::string(type_name_cstr))
+ {
+ if (method_decl->getType() == ClangASTContext::GetQualType(clang_type))
+ {
+ add_method = false;
+ LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(method_decl), die);
+ type_handled = true;
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (add_method)
+ {
+ // REMOVE THE CRASH DESCRIPTION BELOW
+ Host::SetCrashDescriptionWithFormat ("SymbolFileDWARF::ParseType() is adding a method %s to class %s in DIE 0x%8.8" PRIx64 " from %s",
+ type_name_cstr,
+ class_type->GetName().GetCString(),
+ die.GetID(),
+ dwarf->GetObjectFile()->GetFileSpec().GetPath().c_str());
+
+ const bool is_attr_used = false;
+ // Neither GCC 4.2 nor clang++ currently set a valid accessibility
+ // in the DWARF for C++ methods... Default to public for now...
+ if (accessibility == eAccessNone)
+ accessibility = eAccessPublic;
+
+ clang::CXXMethodDecl *cxx_method_decl;
+ cxx_method_decl = m_ast.AddMethodToCXXRecordType (class_opaque_type.GetOpaqueQualType(),
+ type_name_cstr,
+ clang_type,
+ accessibility,
+ is_virtual,
+ is_static,
+ is_inline,
+ is_explicit,
+ is_attr_used,
+ is_artificial);
+
+ type_handled = cxx_method_decl != NULL;
+
+ if (type_handled)
+ {
+ LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die);
+
+ Host::SetCrashDescription (NULL);
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
+
+ if (!object_pointer_name.empty())
+ {
+ metadata.SetObjectPtrName(object_pointer_name.c_str());
+ if (log)
+ log->Printf ("Setting object pointer name: %s on method object %p.\n",
+ object_pointer_name.c_str(),
+ static_cast<void*>(cxx_method_decl));
+ }
+ m_ast.SetMetadata (cxx_method_decl, metadata);
+ }
+ else
+ {
+ ignore_containing_context = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ // We were asked to parse the type for a method in a class, yet the
+ // class hasn't been asked to complete itself through the
+ // clang::ExternalASTSource protocol, so we need to just have the
+ // class complete itself and do things the right way, then our
+ // DIE should then have an entry in the dwarf->GetDIEToType() map. First
+ // we need to modify the dwarf->GetDIEToType() so it doesn't think we are
+ // trying to parse this DIE anymore...
+ dwarf->GetDIEToType()[die.GetDIE()] = NULL;
+
+ // Now we get the full type to force our class type to complete itself
+ // using the clang::ExternalASTSource protocol which will parse all
+ // base classes and all methods (including the method for this DIE).
+ class_type->GetFullCompilerType ();
+
+ // The type for this DIE should have been filled in the function call above
+ type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
+ if (type_ptr && type_ptr != DIE_IS_BEING_PARSED)
+ {
+ type_sp = type_ptr->shared_from_this();
+ break;
+ }
+
+ // FIXME This is fixing some even uglier behavior but we really need to
+ // uniq the methods of each class as well as the class itself.
+ // <rdar://problem/11240464>
+ type_handled = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!type_handled)
+ {
+ // We just have a function that isn't part of a class
+ clang::FunctionDecl *function_decl = m_ast.CreateFunctionDeclaration (ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx,
+ type_name_cstr,
+ clang_type,
+ storage,
+ is_inline);
+
+ // if (template_param_infos.GetSize() > 0)
+ // {
+ // clang::FunctionTemplateDecl *func_template_decl = CreateFunctionTemplateDecl (containing_decl_ctx,
+ // function_decl,
+ // type_name_cstr,
+ // template_param_infos);
+ //
+ // CreateFunctionTemplateSpecializationInfo (function_decl,
+ // func_template_decl,
+ // template_param_infos);
+ // }
+ // Add the decl to our DIE to decl context map
+ assert (function_decl);
+ LinkDeclContextToDIE(function_decl, die);
+ if (!function_param_decls.empty())
+ m_ast.SetFunctionParameters (function_decl,
+ &function_param_decls.front(),
+ function_param_decls.size());
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
+
+ if (!object_pointer_name.empty())
+ {
+ metadata.SetObjectPtrName(object_pointer_name.c_str());
+ if (log)
+ log->Printf ("Setting object pointer name: %s on function object %p.",
+ object_pointer_name.c_str(),
+ static_cast<void*>(function_decl));
+ }
+ m_ast.SetMetadata (function_decl, metadata);
+ }
+ }
+ type_sp.reset( new Type (die.GetID(),
+ dwarf,
+ type_name_const_str,
+ 0,
+ NULL,
+ LLDB_INVALID_UID,
+ Type::eEncodingIsUID,
+ &decl,
+ clang_type,
+ Type::eResolveStateFull));
+ assert(type_sp.get());
+ }
+ break;
+
+ case DW_TAG_array_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ DWARFFormValue type_die_form;
+ int64_t first_index = 0;
+ uint32_t byte_stride = 0;
+ uint32_t bit_stride = 0;
+ bool is_vector = false;
+ const size_t num_attributes = die.GetAttributes (attributes);
+
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_type: type_die_form = form_value; break;
+ case DW_AT_byte_size: break; // byte_size = form_value.Unsigned(); break;
+ case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break;
+ case DW_AT_bit_stride: bit_stride = form_value.Unsigned(); break;
+ case DW_AT_GNU_vector: is_vector = form_value.Boolean(); break;
+ case DW_AT_accessibility: break; // accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
+ case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break;
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_data_location:
+ case DW_AT_description:
+ case DW_AT_ordering:
+ case DW_AT_start_scope:
+ case DW_AT_visibility:
+ case DW_AT_specification:
+ case DW_AT_abstract_origin:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+
+ DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr);
+
+ Type *element_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID());
+
+ if (element_type)
+ {
+ std::vector<uint64_t> element_orders;
+ ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride);
+ if (byte_stride == 0 && bit_stride == 0)
+ byte_stride = element_type->GetByteSize();
+ CompilerType array_element_type = element_type->GetForwardCompilerType ();
+ uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;
+ if (element_orders.size() > 0)
+ {
+ uint64_t num_elements = 0;
+ std::vector<uint64_t>::const_reverse_iterator pos;
+ std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend();
+ for (pos = element_orders.rbegin(); pos != end; ++pos)
+ {
+ num_elements = *pos;
+ clang_type = m_ast.CreateArrayType (array_element_type,
+ num_elements,
+ is_vector);
+ array_element_type = clang_type;
+ array_element_bit_stride = num_elements ?
+ array_element_bit_stride * num_elements :
+ array_element_bit_stride;
+ }
+ }
+ else
+ {
+ clang_type = m_ast.CreateArrayType (array_element_type, 0, is_vector);
+ }
+ ConstString empty_name;
+ type_sp.reset( new Type (die.GetID(),
+ dwarf,
+ empty_name,
+ array_element_bit_stride / 8,
+ NULL,
+ DIERef(type_die_form).GetUID(),
+ Type::eEncodingIsUID,
+ &decl,
+ clang_type,
+ Type::eResolveStateFull));
+ type_sp->SetEncodingType (element_type);
+ }
+ }
+ }
+ break;
+
+ case DW_TAG_ptr_to_member_type:
+ {
+ DWARFFormValue type_die_form;
+ DWARFFormValue containing_type_die_form;
+
+ const size_t num_attributes = die.GetAttributes (attributes);
+
+ if (num_attributes > 0) {
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_type:
+ type_die_form = form_value; break;
+ case DW_AT_containing_type:
+ containing_type_die_form = form_value; break;
+ }
+ }
+ }
+
+ Type *pointee_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID());
+ Type *class_type = dwarf->ResolveTypeUID(DIERef(containing_type_die_form).GetUID());
+
+ CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType ();
+ CompilerType class_clang_type = class_type->GetLayoutCompilerType ();
+
+ clang_type = ClangASTContext::CreateMemberPointerType(class_clang_type, pointee_clang_type);
+
+ byte_size = clang_type.GetByteSize(nullptr);
+
+ type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, byte_size, NULL,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, NULL, clang_type,
+ Type::eResolveStateForward));
+ }
+
+ break;
+ }
+ default:
+ dwarf->GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and attach the file at the start of this error message",
+ die.GetOffset(),
+ tag,
+ DW_TAG_value_to_name(tag));
+ break;
+ }
+
+ if (type_sp.get())
+ {
+ DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
+ dw_tag_t sc_parent_tag = sc_parent_die.Tag();
+
+ SymbolContextScope * symbol_context_scope = NULL;
+ if (sc_parent_tag == DW_TAG_compile_unit)
+ {
+ symbol_context_scope = sc.comp_unit;
+ }
+ else if (sc.function != NULL && sc_parent_die)
+ {
+ symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
+ if (symbol_context_scope == NULL)
+ symbol_context_scope = sc.function;
+ }
+
+ if (symbol_context_scope != NULL)
+ {
+ type_sp->SetSymbolContextScope(symbol_context_scope);
+ }
+
+ // We are ready to put this type into the uniqued list up at the module level
+ type_list->Insert (type_sp);
+
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ }
+ }
+ else if (type_ptr != DIE_IS_BEING_PARSED)
+ {
+ type_sp = type_ptr->shared_from_this();
+ }
+ }
+ return type_sp;
+}
+
+// DWARF parsing functions
+
+class DWARFASTParserClang::DelayedAddObjCClassProperty
+{
+public:
+ DelayedAddObjCClassProperty(const CompilerType &class_opaque_type,
+ const char *property_name,
+ const CompilerType &property_opaque_type, // The property type is only required if you don't have an ivar decl
+ clang::ObjCIvarDecl *ivar_decl,
+ const char *property_setter_name,
+ const char *property_getter_name,
+ uint32_t property_attributes,
+ const ClangASTMetadata *metadata) :
+ m_class_opaque_type (class_opaque_type),
+ m_property_name (property_name),
+ m_property_opaque_type (property_opaque_type),
+ m_ivar_decl (ivar_decl),
+ m_property_setter_name (property_setter_name),
+ m_property_getter_name (property_getter_name),
+ m_property_attributes (property_attributes)
+ {
+ if (metadata != NULL)
+ {
+ m_metadata_ap.reset(new ClangASTMetadata());
+ *m_metadata_ap = *metadata;
+ }
+ }
+
+ DelayedAddObjCClassProperty (const DelayedAddObjCClassProperty &rhs)
+ {
+ *this = rhs;
+ }
+
+ DelayedAddObjCClassProperty& operator= (const DelayedAddObjCClassProperty &rhs)
+ {
+ m_class_opaque_type = rhs.m_class_opaque_type;
+ m_property_name = rhs.m_property_name;
+ m_property_opaque_type = rhs.m_property_opaque_type;
+ m_ivar_decl = rhs.m_ivar_decl;
+ m_property_setter_name = rhs.m_property_setter_name;
+ m_property_getter_name = rhs.m_property_getter_name;
+ m_property_attributes = rhs.m_property_attributes;
+
+ if (rhs.m_metadata_ap.get())
+ {
+ m_metadata_ap.reset (new ClangASTMetadata());
+ *m_metadata_ap = *rhs.m_metadata_ap;
+ }
+ return *this;
+ }
+
+ bool
+ Finalize()
+ {
+ return ClangASTContext::AddObjCClassProperty (m_class_opaque_type,
+ m_property_name,
+ m_property_opaque_type,
+ m_ivar_decl,
+ m_property_setter_name,
+ m_property_getter_name,
+ m_property_attributes,
+ m_metadata_ap.get());
+ }
+
+private:
+ CompilerType m_class_opaque_type;
+ const char *m_property_name;
+ CompilerType m_property_opaque_type;
+ clang::ObjCIvarDecl *m_ivar_decl;
+ const char *m_property_setter_name;
+ const char *m_property_getter_name;
+ uint32_t m_property_attributes;
+ std::unique_ptr<ClangASTMetadata> m_metadata_ap;
+};
+
+bool
+DWARFASTParserClang::ParseTemplateDIE (const DWARFDIE &die,
+ ClangASTContext::TemplateParameterInfos &template_param_infos)
+{
+ const dw_tag_t tag = die.Tag();
+
+ switch (tag)
+ {
+ case DW_TAG_template_type_parameter:
+ case DW_TAG_template_value_parameter:
+ {
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes (attributes);
+ const char *name = NULL;
+ Type *lldb_type = NULL;
+ CompilerType clang_type;
+ uint64_t uval64 = 0;
+ bool uval64_valid = false;
+ if (num_attributes > 0)
+ {
+ DWARFFormValue form_value;
+ for (size_t i=0; i<num_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+
+ switch (attr)
+ {
+ case DW_AT_name:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ name = form_value.AsCString();
+ break;
+
+ case DW_AT_type:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ lldb_type = die.ResolveTypeUID(DIERef(form_value).GetUID());
+ if (lldb_type)
+ clang_type = lldb_type->GetForwardCompilerType ();
+ }
+ break;
+
+ case DW_AT_const_value:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ uval64_valid = true;
+ uval64 = form_value.Unsigned();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ clang::ASTContext *ast = m_ast.getASTContext();
+ if (!clang_type)
+ clang_type = m_ast.GetBasicType(eBasicTypeVoid);
+
+ if (clang_type)
+ {
+ bool is_signed = false;
+ if (name && name[0])
+ template_param_infos.names.push_back(name);
+ else
+ template_param_infos.names.push_back(NULL);
+
+ if (tag == DW_TAG_template_value_parameter &&
+ lldb_type != NULL &&
+ clang_type.IsIntegerType (is_signed) &&
+ uval64_valid)
+ {
+ llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed);
+ template_param_infos.args.push_back (clang::TemplateArgument (*ast,
+ llvm::APSInt(apint),
+ ClangASTContext::GetQualType(clang_type)));
+ }
+ else
+ {
+ template_param_infos.args.push_back (clang::TemplateArgument (ClangASTContext::GetQualType(clang_type)));
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+ }
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+}
+
+bool
+DWARFASTParserClang::ParseTemplateParameterInfos (const DWARFDIE &parent_die,
+ ClangASTContext::TemplateParameterInfos &template_param_infos)
+{
+
+ if (!parent_die)
+ return false;
+
+ Args template_parameter_names;
+ for (DWARFDIE die = parent_die.GetFirstChild();
+ die.IsValid();
+ die = die.GetSibling())
+ {
+ const dw_tag_t tag = die.Tag();
+
+ switch (tag)
+ {
+ case DW_TAG_template_type_parameter:
+ case DW_TAG_template_value_parameter:
+ ParseTemplateDIE (die, template_param_infos);
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (template_param_infos.args.empty())
+ return false;
+ return template_param_infos.args.size() == template_param_infos.names.size();
+}
+
+bool
+DWARFASTParserClang::CanCompleteType (const lldb_private::CompilerType &compiler_type)
+{
+ if (m_clang_ast_importer_ap)
+ return ClangASTContext::CanImport(compiler_type, GetClangASTImporter());
+ else
+ return false;
+}
+
+bool
+DWARFASTParserClang::CompleteType (const lldb_private::CompilerType &compiler_type)
+{
+ if (CanCompleteType(compiler_type))
+ {
+ if (ClangASTContext::Import(compiler_type, GetClangASTImporter()))
+ {
+ ClangASTContext::CompleteTagDeclarationDefinition(compiler_type);
+ return true;
+ }
+ else
+ {
+ ClangASTContext::SetHasExternalStorage (compiler_type.GetOpaqueQualType(), false);
+ }
+ }
+ return false;
+}
+
+bool
+DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die,
+ lldb_private::Type *type,
+ CompilerType &clang_type)
+{
+ // Disable external storage for this type so we don't get anymore
+ // clang::ExternalASTSource queries for this type.
+ m_ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), false);
+
+ if (!die)
+ return false;
+
+ const dw_tag_t tag = die.Tag();
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+
+ Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log,
+ "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...",
+ die.GetID(),
+ die.GetTagAsCString(),
+ type->GetName().AsCString());
+ assert (clang_type);
+ DWARFAttributes attributes;
+ switch (tag)
+ {
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ {
+ LayoutInfo layout_info;
+
+ {
+ if (die.HasChildren())
+ {
+ LanguageType class_language = eLanguageTypeUnknown;
+ if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type))
+ {
+ class_language = eLanguageTypeObjC;
+ // For objective C we don't start the definition when
+ // the class is created.
+ ClangASTContext::StartTagDeclarationDefinition (clang_type);
+ }
+
+ int tag_decl_kind = -1;
+ AccessType default_accessibility = eAccessNone;
+ if (tag == DW_TAG_structure_type)
+ {
+ tag_decl_kind = clang::TTK_Struct;
+ default_accessibility = eAccessPublic;
+ }
+ else if (tag == DW_TAG_union_type)
+ {
+ tag_decl_kind = clang::TTK_Union;
+ default_accessibility = eAccessPublic;
+ }
+ else if (tag == DW_TAG_class_type)
+ {
+ tag_decl_kind = clang::TTK_Class;
+ default_accessibility = eAccessPrivate;
+ }
+
+ SymbolContext sc(die.GetLLDBCompileUnit());
+ std::vector<clang::CXXBaseSpecifier *> base_classes;
+ std::vector<int> member_accessibilities;
+ bool is_a_class = false;
+ // Parse members and base classes first
+ DWARFDIECollection member_function_dies;
+
+ DelayedPropertyList delayed_properties;
+ ParseChildMembers (sc,
+ die,
+ clang_type,
+ class_language,
+ base_classes,
+ member_accessibilities,
+ member_function_dies,
+ delayed_properties,
+ default_accessibility,
+ is_a_class,
+ layout_info);
+
+ // Now parse any methods if there were any...
+ size_t num_functions = member_function_dies.Size();
+ if (num_functions > 0)
+ {
+ for (size_t i=0; i<num_functions; ++i)
+ {
+ dwarf->ResolveType(member_function_dies.GetDIEAtIndex(i));
+ }
+ }
+
+ if (class_language == eLanguageTypeObjC)
+ {
+ ConstString class_name (clang_type.GetTypeName());
+ if (class_name)
+ {
+ DIEArray method_die_offsets;
+ dwarf->GetObjCMethodDIEOffsets(class_name, method_die_offsets);
+
+ if (!method_die_offsets.empty())
+ {
+ DWARFDebugInfo* debug_info = dwarf->DebugInfo();
+
+ const size_t num_matches = method_die_offsets.size();
+ for (size_t i=0; i<num_matches; ++i)
+ {
+ const DIERef& die_ref = method_die_offsets[i];
+ DWARFDIE method_die = debug_info->GetDIE (die_ref);
+
+ if (method_die)
+ method_die.ResolveType ();
+ }
+ }
+
+ for (DelayedPropertyList::iterator pi = delayed_properties.begin(), pe = delayed_properties.end();
+ pi != pe;
+ ++pi)
+ pi->Finalize();
+ }
+ }
+
+ // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
+ // need to tell the clang type it is actually a class.
+ if (class_language != eLanguageTypeObjC)
+ {
+ if (is_a_class && tag_decl_kind != clang::TTK_Class)
+ m_ast.SetTagTypeKind (ClangASTContext::GetQualType(clang_type), clang::TTK_Class);
+ }
+
+ // Since DW_TAG_structure_type gets used for both classes
+ // and structures, we may need to set any DW_TAG_member
+ // fields to have a "private" access if none was specified.
+ // When we parsed the child members we tracked that actual
+ // accessibility value for each DW_TAG_member in the
+ // "member_accessibilities" array. If the value for the
+ // member is zero, then it was set to the "default_accessibility"
+ // which for structs was "public". Below we correct this
+ // by setting any fields to "private" that weren't correctly
+ // set.
+ if (is_a_class && !member_accessibilities.empty())
+ {
+ // This is a class and all members that didn't have
+ // their access specified are private.
+ m_ast.SetDefaultAccessForRecordFields (m_ast.GetAsRecordDecl(clang_type),
+ eAccessPrivate,
+ &member_accessibilities.front(),
+ member_accessibilities.size());
+ }
+
+ if (!base_classes.empty())
+ {
+ // Make sure all base classes refer to complete types and not
+ // forward declarations. If we don't do this, clang will crash
+ // with an assertion in the call to clang_type.SetBaseClassesForClassType()
+ for (auto &base_class : base_classes)
+ {
+ clang::TypeSourceInfo *type_source_info = base_class->getTypeSourceInfo();
+ if (type_source_info)
+ {
+ CompilerType base_class_type (&m_ast, type_source_info->getType().getAsOpaquePtr());
+ if (base_class_type.GetCompleteType() == false)
+ {
+ auto module = dwarf->GetObjectFile()->GetModule();
+ module->ReportError (
+ ":: Class '%s' has a base class '%s' which does not have a complete definition.",
+ die.GetName(),
+ base_class_type.GetTypeName().GetCString());
+ if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang)
+ module->ReportError (":: Try compiling the source file with -fno-limit-debug-info.");
+
+ // We have no choice other than to pretend that the base class
+ // is complete. If we don't do this, clang will crash when we
+ // call setBases() inside of "clang_type.SetBaseClassesForClassType()"
+ // below. Since we provide layout assistance, all ivars in this
+ // class and other classes will be fine, this is the best we can do
+ // short of crashing.
+ ClangASTContext::StartTagDeclarationDefinition (base_class_type);
+ ClangASTContext::CompleteTagDeclarationDefinition (base_class_type);
+ }
+ }
+ }
+ m_ast.SetBaseClassesForClassType (clang_type.GetOpaqueQualType(),
+ &base_classes.front(),
+ base_classes.size());
+
+ // Clang will copy each CXXBaseSpecifier in "base_classes"
+ // so we have to free them all.
+ ClangASTContext::DeleteBaseClassSpecifiers (&base_classes.front(),
+ base_classes.size());
+ }
+ }
+ }
+
+ ClangASTContext::BuildIndirectFields (clang_type);
+ ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
+
+ if (!layout_info.field_offsets.empty() ||
+ !layout_info.base_offsets.empty() ||
+ !layout_info.vbase_offsets.empty() )
+ {
+ if (type)
+ layout_info.bit_size = type->GetByteSize() * 8;
+ if (layout_info.bit_size == 0)
+ layout_info.bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
+
+ clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
+ if (record_decl)
+ {
+ if (log)
+ {
+ ModuleSP module_sp = dwarf->GetObjectFile()->GetModule();
+
+ if (module_sp)
+ {
+ module_sp->LogMessage (log,
+ "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) caching layout info for record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u], base_offsets[%u], vbase_offsets[%u])",
+ static_cast<void*>(clang_type.GetOpaqueQualType()),
+ static_cast<void*>(record_decl),
+ layout_info.bit_size,
+ layout_info.alignment,
+ static_cast<uint32_t>(layout_info.field_offsets.size()),
+ static_cast<uint32_t>(layout_info.base_offsets.size()),
+ static_cast<uint32_t>(layout_info.vbase_offsets.size()));
+
+ uint32_t idx;
+ {
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t>::const_iterator pos,
+ end = layout_info.field_offsets.end();
+ for (idx = 0, pos = layout_info.field_offsets.begin(); pos != end; ++pos, ++idx)
+ {
+ module_sp->LogMessage(log,
+ "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) field[%u] = { bit_offset=%u, name='%s' }",
+ static_cast<void *>(clang_type.GetOpaqueQualType()),
+ idx,
+ static_cast<uint32_t>(pos->second),
+ pos->first->getNameAsString().c_str());
+ }
+ }
+
+ {
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator base_pos,
+ base_end = layout_info.base_offsets.end();
+ for (idx = 0, base_pos = layout_info.base_offsets.begin(); base_pos != base_end; ++base_pos, ++idx)
+ {
+ module_sp->LogMessage(log,
+ "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) base[%u] = { byte_offset=%u, name='%s' }",
+ clang_type.GetOpaqueQualType(), idx, (uint32_t)base_pos->second.getQuantity(),
+ base_pos->first->getNameAsString().c_str());
+ }
+ }
+ {
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator vbase_pos,
+ vbase_end = layout_info.vbase_offsets.end();
+ for (idx = 0, vbase_pos = layout_info.vbase_offsets.begin(); vbase_pos != vbase_end; ++vbase_pos, ++idx)
+ {
+ module_sp->LogMessage(log,
+ "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) vbase[%u] = { byte_offset=%u, name='%s' }",
+ static_cast<void *>(clang_type.GetOpaqueQualType()), idx,
+ static_cast<uint32_t>(vbase_pos->second.getQuantity()),
+ vbase_pos->first->getNameAsString().c_str());
+ }
+ }
+
+ }
+ }
+ m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info));
+ }
+ }
+ }
+
+ return (bool)clang_type;
+
+ case DW_TAG_enumeration_type:
+ ClangASTContext::StartTagDeclarationDefinition (clang_type);
+ if (die.HasChildren())
+ {
+ SymbolContext sc(die.GetLLDBCompileUnit());
+ bool is_signed = false;
+ clang_type.IsIntegerType(is_signed);
+ ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), die);
+ }
+ ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
+ return (bool)clang_type;
+
+ default:
+ assert(false && "not a forward clang type decl!");
+ break;
+ }
+
+ return false;
+}
+
+std::vector<DWARFDIE>
+DWARFASTParserClang::GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context)
+{
+ std::vector<DWARFDIE> result;
+ for (auto it = m_decl_ctx_to_die.find((clang::DeclContext *)decl_context.GetOpaqueDeclContext()); it != m_decl_ctx_to_die.end(); it++)
+ result.push_back(it->second);
+ return result;
+}
+
+CompilerDecl
+DWARFASTParserClang::GetDeclForUIDFromDWARF (const DWARFDIE &die)
+{
+ clang::Decl *clang_decl = GetClangDeclForDIE(die);
+ if (clang_decl != nullptr)
+ return CompilerDecl(&m_ast, clang_decl);
+ return CompilerDecl();
+}
+
+CompilerDeclContext
+DWARFASTParserClang::GetDeclContextForUIDFromDWARF (const DWARFDIE &die)
+{
+ clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE (die);
+ if (clang_decl_ctx)
+ return CompilerDeclContext(&m_ast, clang_decl_ctx);
+ return CompilerDeclContext();
+}
+
+CompilerDeclContext
+DWARFASTParserClang::GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die)
+{
+ clang::DeclContext *clang_decl_ctx = GetClangDeclContextContainingDIE (die, nullptr);
+ if (clang_decl_ctx)
+ return CompilerDeclContext(&m_ast, clang_decl_ctx);
+ return CompilerDeclContext();
+}
+
+size_t
+DWARFASTParserClang::ParseChildEnumerators (const SymbolContext& sc,
+ lldb_private::CompilerType &clang_type,
+ bool is_signed,
+ uint32_t enumerator_byte_size,
+ const DWARFDIE &parent_die)
+{
+ if (!parent_die)
+ return 0;
+
+ size_t enumerators_added = 0;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ const dw_tag_t tag = die.Tag();
+ if (tag == DW_TAG_enumerator)
+ {
+ DWARFAttributes attributes;
+ const size_t num_child_attributes = die.GetAttributes(attributes);
+ if (num_child_attributes > 0)
+ {
+ const char *name = NULL;
+ bool got_value = false;
+ int64_t enum_value = 0;
+ Declaration decl;
+
+ uint32_t i;
+ for (i=0; i<num_child_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_const_value:
+ got_value = true;
+ if (is_signed)
+ enum_value = form_value.Signed();
+ else
+ enum_value = form_value.Unsigned();
+ break;
+
+ case DW_AT_name:
+ name = form_value.AsCString();
+ break;
+
+ case DW_AT_description:
+ default:
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+
+ if (name && name[0] && got_value)
+ {
+ m_ast.AddEnumerationValueToEnumerationType (clang_type.GetOpaqueQualType(),
+ m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()),
+ decl,
+ name,
+ enum_value,
+ enumerator_byte_size * 8);
+ ++enumerators_added;
+ }
+ }
+ }
+ }
+ return enumerators_added;
+}
+
+#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
+
+class DIEStack
+{
+public:
+
+ void Push (const DWARFDIE &die)
+ {
+ m_dies.push_back (die);
+ }
+
+
+ void LogDIEs (Log *log)
+ {
+ StreamString log_strm;
+ const size_t n = m_dies.size();
+ log_strm.Printf("DIEStack[%" PRIu64 "]:\n", (uint64_t)n);
+ for (size_t i=0; i<n; i++)
+ {
+ std::string qualified_name;
+ const DWARFDIE &die = m_dies[i];
+ die.GetQualifiedName(qualified_name);
+ log_strm.Printf ("[%" PRIu64 "] 0x%8.8x: %s name='%s'\n",
+ (uint64_t)i,
+ die.GetOffset(),
+ die.GetTagAsCString(),
+ qualified_name.c_str());
+ }
+ log->PutCString(log_strm.GetData());
+ }
+ void Pop ()
+ {
+ m_dies.pop_back();
+ }
+
+ class ScopedPopper
+ {
+ public:
+ ScopedPopper (DIEStack &die_stack) :
+ m_die_stack (die_stack),
+ m_valid (false)
+ {
+ }
+
+ void
+ Push (const DWARFDIE &die)
+ {
+ m_valid = true;
+ m_die_stack.Push (die);
+ }
+
+ ~ScopedPopper ()
+ {
+ if (m_valid)
+ m_die_stack.Pop();
+ }
+
+
+
+ protected:
+ DIEStack &m_die_stack;
+ bool m_valid;
+ };
+
+protected:
+ typedef std::vector<DWARFDIE> Stack;
+ Stack m_dies;
+};
+#endif
+
+Function *
+DWARFASTParserClang::ParseFunctionFromDWARF (const SymbolContext& sc,
+ const DWARFDIE &die)
+{
+ DWARFRangeList func_ranges;
+ const char *name = NULL;
+ const char *mangled = NULL;
+ int decl_file = 0;
+ int decl_line = 0;
+ int decl_column = 0;
+ int call_file = 0;
+ int call_line = 0;
+ int call_column = 0;
+ DWARFExpression frame_base(die.GetCU());
+
+ const dw_tag_t tag = die.Tag();
+
+ if (tag != DW_TAG_subprogram)
+ return NULL;
+
+ if (die.GetDIENamesAndRanges (name,
+ mangled,
+ func_ranges,
+ decl_file,
+ decl_line,
+ decl_column,
+ call_file,
+ call_line,
+ call_column,
+ &frame_base))
+ {
+
+ // Union of all ranges in the function DIE (if the function is discontiguous)
+ AddressRange func_range;
+ lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase (0);
+ lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd (0);
+ if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr)
+ {
+ ModuleSP module_sp (die.GetModule());
+ func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, module_sp->GetSectionList());
+ if (func_range.GetBaseAddress().IsValid())
+ func_range.SetByteSize(highest_func_addr - lowest_func_addr);
+ }
+
+ if (func_range.GetBaseAddress().IsValid())
+ {
+ Mangled func_name;
+ if (mangled)
+ func_name.SetValue(ConstString(mangled), true);
+ else if (die.GetParent().Tag() == DW_TAG_compile_unit &&
+ Language::LanguageIsCPlusPlus(die.GetLanguage()) &&
+ name && strcmp(name, "main") != 0)
+ {
+ // If the mangled name is not present in the DWARF, generate the demangled name
+ // using the decl context. We skip if the function is "main" as its name is
+ // never mangled.
+ bool is_static = false;
+ bool is_variadic = false;
+ unsigned type_quals = 0;
+ std::vector<CompilerType> param_types;
+ std::vector<clang::ParmVarDecl*> param_decls;
+ DWARFDeclContext decl_ctx;
+ StreamString sstr;
+
+ die.GetDWARFDeclContext(decl_ctx);
+ sstr << decl_ctx.GetQualifiedName();
+
+ clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(die, nullptr);
+ ParseChildParameters(sc,
+ containing_decl_ctx,
+ die,
+ true,
+ is_static,
+ is_variadic,
+ param_types,
+ param_decls,
+ type_quals);
+ sstr << "(";
+ for (size_t i = 0; i < param_types.size(); i++)
+ {
+ if (i > 0)
+ sstr << ", ";
+ sstr << param_types[i].GetTypeName();
+ }
+ if (is_variadic)
+ sstr << ", ...";
+ sstr << ")";
+ if (type_quals & clang::Qualifiers::Const)
+ sstr << " const";
+
+ func_name.SetValue(ConstString(sstr.GetData()), false);
+ }
+ else
+ func_name.SetValue(ConstString(name), false);
+
+ FunctionSP func_sp;
+ std::unique_ptr<Declaration> decl_ap;
+ if (decl_file != 0 || decl_line != 0 || decl_column != 0)
+ decl_ap.reset(new Declaration (sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
+ decl_line,
+ decl_column));
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ // Supply the type _only_ if it has already been parsed
+ Type *func_type = dwarf->GetDIEToType().lookup (die.GetDIE());
+
+ assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
+
+ if (dwarf->FixupAddress (func_range.GetBaseAddress()))
+ {
+ const user_id_t func_user_id = die.GetID();
+ func_sp.reset(new Function (sc.comp_unit,
+ func_user_id, // UserID is the DIE offset
+ func_user_id,
+ func_name,
+ func_type,
+ func_range)); // first address range
+
+ if (func_sp.get() != NULL)
+ {
+ if (frame_base.IsValid())
+ func_sp->GetFrameBaseExpression() = frame_base;
+ sc.comp_unit->AddFunction(func_sp);
+ return func_sp.get();
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+
+bool
+DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc,
+ const DWARFDIE &parent_die,
+ CompilerType &class_clang_type,
+ const LanguageType class_language,
+ std::vector<clang::CXXBaseSpecifier *>& base_classes,
+ std::vector<int>& member_accessibilities,
+ DWARFDIECollection& member_function_dies,
+ DelayedPropertyList& delayed_properties,
+ AccessType& default_accessibility,
+ bool &is_a_class,
+ LayoutInfo &layout_info)
+{
+ if (!parent_die)
+ return 0;
+
+ uint32_t member_idx = 0;
+ BitfieldInfo last_field_info;
+
+ ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(class_clang_type.GetTypeSystem());
+ if (ast == nullptr)
+ return 0;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ dw_tag_t tag = die.Tag();
+
+ switch (tag)
+ {
+ case DW_TAG_member:
+ case DW_TAG_APPLE_property:
+ {
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes (attributes);
+ if (num_attributes > 0)
+ {
+ Declaration decl;
+ //DWARFExpression location;
+ const char *name = NULL;
+ const char *prop_name = NULL;
+ const char *prop_getter_name = NULL;
+ const char *prop_setter_name = NULL;
+ uint32_t prop_attributes = 0;
+
+
+ bool is_artificial = false;
+ DWARFFormValue encoding_form;
+ AccessType accessibility = eAccessNone;
+ uint32_t member_byte_offset = UINT32_MAX;
+ size_t byte_size = 0;
+ size_t bit_offset = 0;
+ size_t bit_size = 0;
+ bool is_external = false; // On DW_TAG_members, this means the member is static
+ uint32_t i;
+ for (i=0; i<num_attributes && !is_artificial; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_name: name = form_value.AsCString(); break;
+ case DW_AT_type: encoding_form = form_value; break;
+ case DW_AT_bit_offset: bit_offset = form_value.Unsigned(); break;
+ case DW_AT_bit_size: bit_size = form_value.Unsigned(); break;
+ case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
+ case DW_AT_data_member_location:
+ if (form_value.BlockData())
+ {
+ Value initialValue(0);
+ Value memberOffset(0);
+ const DWARFDataExtractor& debug_info_data = die.GetDWARF()->get_debug_info_data();
+ uint32_t block_length = form_value.Unsigned();
+ uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+ if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
+ NULL, // ClangExpressionVariableList *
+ NULL, // ClangExpressionDeclMap *
+ NULL, // RegisterContext *
+ module_sp,
+ debug_info_data,
+ die.GetCU(),
+ block_offset,
+ block_length,
+ eRegisterKindDWARF,
+ &initialValue,
+ memberOffset,
+ NULL))
+ {
+ member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
+ }
+ }
+ else
+ {
+ // With DWARF 3 and later, if the value is an integer constant,
+ // this form value is the offset in bytes from the beginning
+ // of the containing entity.
+ member_byte_offset = form_value.Unsigned();
+ }
+ break;
+
+ case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType (form_value.Unsigned()); break;
+ case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
+ case DW_AT_APPLE_property_name: prop_name = form_value.AsCString();
+ break;
+ case DW_AT_APPLE_property_getter: prop_getter_name = form_value.AsCString();
+ break;
+ case DW_AT_APPLE_property_setter: prop_setter_name = form_value.AsCString();
+ break;
+ case DW_AT_APPLE_property_attribute: prop_attributes = form_value.Unsigned(); break;
+ case DW_AT_external: is_external = form_value.Boolean(); break;
+
+ default:
+ case DW_AT_declaration:
+ case DW_AT_description:
+ case DW_AT_mutable:
+ case DW_AT_visibility:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+
+ if (prop_name)
+ {
+ ConstString fixed_getter;
+ ConstString fixed_setter;
+
+ // Check if the property getter/setter were provided as full
+ // names. We want basenames, so we extract them.
+
+ if (prop_getter_name && prop_getter_name[0] == '-')
+ {
+ ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
+ prop_getter_name = prop_getter_method.GetSelector().GetCString();
+ }
+
+ if (prop_setter_name && prop_setter_name[0] == '-')
+ {
+ ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true);
+ prop_setter_name = prop_setter_method.GetSelector().GetCString();
+ }
+
+ // If the names haven't been provided, they need to be
+ // filled in.
+
+ if (!prop_getter_name)
+ {
+ prop_getter_name = prop_name;
+ }
+ if (!prop_setter_name && prop_name[0] && !(prop_attributes & DW_APPLE_PROPERTY_readonly))
+ {
+ StreamString ss;
+
+ ss.Printf("set%c%s:",
+ toupper(prop_name[0]),
+ &prop_name[1]);
+
+ fixed_setter.SetCString(ss.GetData());
+ prop_setter_name = fixed_setter.GetCString();
+ }
+ }
+
+ // Clang has a DWARF generation bug where sometimes it
+ // represents fields that are references with bad byte size
+ // and bit size/offset information such as:
+ //
+ // DW_AT_byte_size( 0x00 )
+ // DW_AT_bit_size( 0x40 )
+ // DW_AT_bit_offset( 0xffffffffffffffc0 )
+ //
+ // So check the bit offset to make sure it is sane, and if
+ // the values are not sane, remove them. If we don't do this
+ // then we will end up with a crash if we try to use this
+ // type in an expression when clang becomes unhappy with its
+ // recycled debug info.
+
+ if (bit_offset > 128)
+ {
+ bit_size = 0;
+ bit_offset = 0;
+ }
+
+ // FIXME: Make Clang ignore Objective-C accessibility for expressions
+ if (class_language == eLanguageTypeObjC ||
+ class_language == eLanguageTypeObjC_plus_plus)
+ accessibility = eAccessNone;
+
+ if (member_idx == 0 && !is_artificial && name && (strstr (name, "_vptr$") == name))
+ {
+ // Not all compilers will mark the vtable pointer
+ // member as artificial (llvm-gcc). We can't have
+ // the virtual members in our classes otherwise it
+ // throws off all child offsets since we end up
+ // having and extra pointer sized member in our
+ // class layouts.
+ is_artificial = true;
+ }
+
+ // Handle static members
+ if (is_external && member_byte_offset == UINT32_MAX)
+ {
+ Type *var_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID());
+
+ if (var_type)
+ {
+ if (accessibility == eAccessNone)
+ accessibility = eAccessPublic;
+ ClangASTContext::AddVariableToRecordType (class_clang_type,
+ name,
+ var_type->GetLayoutCompilerType (),
+ accessibility);
+ }
+ break;
+ }
+
+ if (is_artificial == false)
+ {
+ Type *member_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID());
+
+ clang::FieldDecl *field_decl = NULL;
+ if (tag == DW_TAG_member)
+ {
+ if (member_type)
+ {
+ if (accessibility == eAccessNone)
+ accessibility = default_accessibility;
+ member_accessibilities.push_back(accessibility);
+
+ uint64_t field_bit_offset = (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
+ if (bit_size > 0)
+ {
+
+ BitfieldInfo this_field_info;
+ this_field_info.bit_offset = field_bit_offset;
+ this_field_info.bit_size = bit_size;
+
+ /////////////////////////////////////////////////////////////
+ // How to locate a field given the DWARF debug information
+ //
+ // AT_byte_size indicates the size of the word in which the
+ // bit offset must be interpreted.
+ //
+ // AT_data_member_location indicates the byte offset of the
+ // word from the base address of the structure.
+ //
+ // AT_bit_offset indicates how many bits into the word
+ // (according to the host endianness) the low-order bit of
+ // the field starts. AT_bit_offset can be negative.
+ //
+ // AT_bit_size indicates the size of the field in bits.
+ /////////////////////////////////////////////////////////////
+
+ if (byte_size == 0)
+ byte_size = member_type->GetByteSize();
+
+ if (die.GetDWARF()->GetObjectFile()->GetByteOrder() == eByteOrderLittle)
+ {
+ this_field_info.bit_offset += byte_size * 8;
+ this_field_info.bit_offset -= (bit_offset + bit_size);
+ }
+ else
+ {
+ this_field_info.bit_offset += bit_offset;
+ }
+
+ // Update the field bit offset we will report for layout
+ field_bit_offset = this_field_info.bit_offset;
+
+ // If the member to be emitted did not start on a character boundary and there is
+ // empty space between the last field and this one, then we need to emit an
+ // anonymous member filling up the space up to its start. There are three cases
+ // here:
+ //
+ // 1 If the previous member ended on a character boundary, then we can emit an
+ // anonymous member starting at the most recent character boundary.
+ //
+ // 2 If the previous member did not end on a character boundary and the distance
+ // from the end of the previous member to the current member is less than a
+ // word width, then we can emit an anonymous member starting right after the
+ // previous member and right before this member.
+ //
+ // 3 If the previous member did not end on a character boundary and the distance
+ // from the end of the previous member to the current member is greater than
+ // or equal a word width, then we act as in Case 1.
+
+ const uint64_t character_width = 8;
+ const uint64_t word_width = 32;
+
+ // Objective-C has invalid DW_AT_bit_offset values in older versions
+ // of clang, so we have to be careful and only insert unnamed bitfields
+ // if we have a new enough clang.
+ bool detect_unnamed_bitfields = true;
+
+ if (class_language == eLanguageTypeObjC || class_language == eLanguageTypeObjC_plus_plus)
+ detect_unnamed_bitfields = die.GetCU()->Supports_unnamed_objc_bitfields ();
+
+ if (detect_unnamed_bitfields)
+ {
+ BitfieldInfo anon_field_info;
+
+ if ((this_field_info.bit_offset % character_width) != 0) // not char aligned
+ {
+ uint64_t last_field_end = 0;
+
+ if (last_field_info.IsValid())
+ last_field_end = last_field_info.bit_offset + last_field_info.bit_size;
+
+ if (this_field_info.bit_offset != last_field_end)
+ {
+ if (((last_field_end % character_width) == 0) || // case 1
+ (this_field_info.bit_offset - last_field_end >= word_width)) // case 3
+ {
+ anon_field_info.bit_size = this_field_info.bit_offset % character_width;
+ anon_field_info.bit_offset = this_field_info.bit_offset - anon_field_info.bit_size;
+ }
+ else // case 2
+ {
+ anon_field_info.bit_size = this_field_info.bit_offset - last_field_end;
+ anon_field_info.bit_offset = last_field_end;
+ }
+ }
+ }
+
+ if (anon_field_info.IsValid())
+ {
+ clang::FieldDecl *unnamed_bitfield_decl =
+ ClangASTContext::AddFieldToRecordType (class_clang_type,
+ NULL,
+ m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width),
+ accessibility,
+ anon_field_info.bit_size);
+
+ layout_info.field_offsets.insert(
+ std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset));
+ }
+ }
+ last_field_info = this_field_info;
+ }
+ else
+ {
+ last_field_info.Clear();
+ }
+
+ CompilerType member_clang_type = member_type->GetLayoutCompilerType ();
+ if (!member_clang_type.IsCompleteType())
+ member_clang_type.GetCompleteType();
+
+ {
+ // Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>).
+ // If the current field is at the end of the structure, then there is definitely no room for extra
+ // elements and we override the type to array[0].
+
+ CompilerType member_array_element_type;
+ uint64_t member_array_size;
+ bool member_array_is_incomplete;
+
+ if (member_clang_type.IsArrayType(&member_array_element_type,
+ &member_array_size,
+ &member_array_is_incomplete) &&
+ !member_array_is_incomplete)
+ {
+ uint64_t parent_byte_size = parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX);
+
+ if (member_byte_offset >= parent_byte_size)
+ {
+ if (member_array_size != 1 && (member_array_size != 0 || member_byte_offset > parent_byte_size))
+ {
+ module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which extends beyond the bounds of 0x%8.8" PRIx64,
+ die.GetID(),
+ name,
+ encoding_form.Reference(),
+ parent_die.GetID());
+ }
+
+ member_clang_type = m_ast.CreateArrayType(member_array_element_type, 0, false);
+ }
+ }
+ }
+
+ if (ClangASTContext::IsCXXClassType(member_clang_type) && member_clang_type.GetCompleteType() == false)
+ {
+ if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang)
+ module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nTry compiling the source file with -fno-limit-debug-info",
+ parent_die.GetOffset(),
+ parent_die.GetName(),
+ die.GetOffset(),
+ name);
+ else
+ module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s",
+ parent_die.GetOffset(),
+ parent_die.GetName(),
+ die.GetOffset(),
+ name,
+ sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file");
+ // We have no choice other than to pretend that the member class
+ // is complete. If we don't do this, clang will crash when trying
+ // to layout the class. Since we provide layout assistance, all
+ // ivars in this class and other classes will be fine, this is
+ // the best we can do short of crashing.
+ ClangASTContext::StartTagDeclarationDefinition(member_clang_type);
+ ClangASTContext::CompleteTagDeclarationDefinition(member_clang_type);
+ }
+
+ field_decl = ClangASTContext::AddFieldToRecordType (class_clang_type,
+ name,
+ member_clang_type,
+ accessibility,
+ bit_size);
+
+ m_ast.SetMetadataAsUserID (field_decl, die.GetID());
+
+ layout_info.field_offsets.insert(std::make_pair(field_decl, field_bit_offset));
+ }
+ else
+ {
+ if (name)
+ module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which was unable to be parsed",
+ die.GetID(),
+ name,
+ encoding_form.Reference());
+ else
+ module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8" PRIx64 " which was unable to be parsed",
+ die.GetID(),
+ encoding_form.Reference());
+ }
+ }
+
+ if (prop_name != NULL && member_type)
+ {
+ clang::ObjCIvarDecl *ivar_decl = NULL;
+
+ if (field_decl)
+ {
+ ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl);
+ assert (ivar_decl != NULL);
+ }
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID (die.GetID());
+ delayed_properties.push_back(DelayedAddObjCClassProperty(class_clang_type,
+ prop_name,
+ member_type->GetLayoutCompilerType (),
+ ivar_decl,
+ prop_setter_name,
+ prop_getter_name,
+ prop_attributes,
+ &metadata));
+
+ if (ivar_decl)
+ m_ast.SetMetadataAsUserID (ivar_decl, die.GetID());
+ }
+ }
+ }
+ ++member_idx;
+ }
+ break;
+
+ case DW_TAG_subprogram:
+ // Let the type parsing code handle this one for us.
+ member_function_dies.Append (die);
+ break;
+
+ case DW_TAG_inheritance:
+ {
+ is_a_class = true;
+ if (default_accessibility == eAccessNone)
+ default_accessibility = eAccessPrivate;
+ // TODO: implement DW_TAG_inheritance type parsing
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes (attributes);
+ if (num_attributes > 0)
+ {
+ Declaration decl;
+ DWARFExpression location(die.GetCU());
+ DWARFFormValue encoding_form;
+ AccessType accessibility = default_accessibility;
+ bool is_virtual = false;
+ bool is_base_of_class = true;
+ off_t member_byte_offset = 0;
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_type: encoding_form = form_value; break;
+ case DW_AT_data_member_location:
+ if (form_value.BlockData())
+ {
+ Value initialValue(0);
+ Value memberOffset(0);
+ const DWARFDataExtractor& debug_info_data = die.GetDWARF()->get_debug_info_data();
+ uint32_t block_length = form_value.Unsigned();
+ uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+ if (DWARFExpression::Evaluate (NULL,
+ NULL,
+ NULL,
+ NULL,
+ module_sp,
+ debug_info_data,
+ die.GetCU(),
+ block_offset,
+ block_length,
+ eRegisterKindDWARF,
+ &initialValue,
+ memberOffset,
+ NULL))
+ {
+ member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
+ }
+ }
+ else
+ {
+ // With DWARF 3 and later, if the value is an integer constant,
+ // this form value is the offset in bytes from the beginning
+ // of the containing entity.
+ member_byte_offset = form_value.Unsigned();
+ }
+ break;
+
+ case DW_AT_accessibility:
+ accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
+ break;
+
+ case DW_AT_virtuality:
+ is_virtual = form_value.Boolean();
+ break;
+
+ case DW_AT_sibling:
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ Type *base_class_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID());
+ if (base_class_type == NULL)
+ {
+ module_sp->ReportError("0x%8.8x: DW_TAG_inheritance failed to resolve the base class at 0x%8.8" PRIx64 " from enclosing type 0x%8.8x. \nPlease file a bug and attach the file at the start of this error message",
+ die.GetOffset(),
+ encoding_form.Reference(),
+ parent_die.GetOffset());
+ break;
+ }
+
+ CompilerType base_class_clang_type = base_class_type->GetFullCompilerType ();
+ assert (base_class_clang_type);
+ if (class_language == eLanguageTypeObjC)
+ {
+ ast->SetObjCSuperClass(class_clang_type, base_class_clang_type);
+ }
+ else
+ {
+ base_classes.push_back (ast->CreateBaseClassSpecifier (base_class_clang_type.GetOpaqueQualType(),
+ accessibility,
+ is_virtual,
+ is_base_of_class));
+
+ if (is_virtual)
+ {
+ // Do not specify any offset for virtual inheritance. The DWARF produced by clang doesn't
+ // give us a constant offset, but gives us a DWARF expressions that requires an actual object
+ // in memory. the DW_AT_data_member_location for a virtual base class looks like:
+ // DW_AT_data_member_location( DW_OP_dup, DW_OP_deref, DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref, DW_OP_plus )
+ // Given this, there is really no valid response we can give to clang for virtual base
+ // class offsets, and this should eventually be removed from LayoutRecordType() in the external
+ // AST source in clang.
+ }
+ else
+ {
+ layout_info.base_offsets.insert(
+ std::make_pair(ast->GetAsCXXRecordDecl(base_class_clang_type.GetOpaqueQualType()),
+ clang::CharUnits::fromQuantity(member_byte_offset)));
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+size_t
+DWARFASTParserClang::ParseChildParameters (const SymbolContext& sc,
+ clang::DeclContext *containing_decl_ctx,
+ const DWARFDIE &parent_die,
+ bool skip_artificial,
+ bool &is_static,
+ bool &is_variadic,
+ std::vector<CompilerType>& function_param_types,
+ std::vector<clang::ParmVarDecl*>& function_param_decls,
+ unsigned &type_quals)
+{
+ if (!parent_die)
+ return 0;
+
+ size_t arg_idx = 0;
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ const dw_tag_t tag = die.Tag();
+ switch (tag)
+ {
+ case DW_TAG_formal_parameter:
+ {
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ const char *name = NULL;
+ Declaration decl;
+ DWARFFormValue param_type_die_form;
+ bool is_artificial = false;
+ // one of None, Auto, Register, Extern, Static, PrivateExtern
+
+ clang::StorageClass storage = clang::SC_None;
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_name: name = form_value.AsCString();
+ break;
+ case DW_AT_type: param_type_die_form = form_value; break;
+ case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
+ case DW_AT_location:
+ // if (form_value.BlockData())
+ // {
+ // const DWARFDataExtractor& debug_info_data = debug_info();
+ // uint32_t block_length = form_value.Unsigned();
+ // DWARFDataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length);
+ // }
+ // else
+ // {
+ // }
+ // break;
+ case DW_AT_const_value:
+ case DW_AT_default_value:
+ case DW_AT_description:
+ case DW_AT_endianity:
+ case DW_AT_is_optional:
+ case DW_AT_segment:
+ case DW_AT_variable_parameter:
+ default:
+ case DW_AT_abstract_origin:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+
+ bool skip = false;
+ if (skip_artificial)
+ {
+ if (is_artificial)
+ {
+ // In order to determine if a C++ member function is
+ // "const" we have to look at the const-ness of "this"...
+ // Ugly, but that
+ if (arg_idx == 0)
+ {
+ if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()))
+ {
+ // Often times compilers omit the "this" name for the
+ // specification DIEs, so we can't rely upon the name
+ // being in the formal parameter DIE...
+ if (name == NULL || ::strcmp(name, "this")==0)
+ {
+ Type *this_type = die.ResolveTypeUID (DIERef(param_type_die_form).GetUID());
+ if (this_type)
+ {
+ uint32_t encoding_mask = this_type->GetEncodingMask();
+ if (encoding_mask & Type::eEncodingIsPointerUID)
+ {
+ is_static = false;
+
+ if (encoding_mask & (1u << Type::eEncodingIsConstUID))
+ type_quals |= clang::Qualifiers::Const;
+ if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
+ type_quals |= clang::Qualifiers::Volatile;
+ }
+ }
+ }
+ }
+ }
+ skip = true;
+ }
+ else
+ {
+
+ // HACK: Objective C formal parameters "self" and "_cmd"
+ // are not marked as artificial in the DWARF...
+ CompileUnit *comp_unit = die.GetLLDBCompileUnit();
+ if (comp_unit)
+ {
+ switch (comp_unit->GetLanguage())
+ {
+ case eLanguageTypeObjC:
+ case eLanguageTypeObjC_plus_plus:
+ if (name && name[0] && (strcmp (name, "self") == 0 || strcmp (name, "_cmd") == 0))
+ skip = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ if (!skip)
+ {
+ Type *type = die.ResolveTypeUID(DIERef(param_type_die_form).GetUID());
+ if (type)
+ {
+ function_param_types.push_back (type->GetForwardCompilerType ());
+
+ clang::ParmVarDecl *param_var_decl = m_ast.CreateParameterDeclaration (name,
+ type->GetForwardCompilerType (),
+ storage);
+ assert(param_var_decl);
+ function_param_decls.push_back(param_var_decl);
+
+ m_ast.SetMetadataAsUserID (param_var_decl, die.GetID());
+ }
+ }
+ }
+ arg_idx++;
+ }
+ break;
+
+ case DW_TAG_unspecified_parameters:
+ is_variadic = true;
+ break;
+
+ case DW_TAG_template_type_parameter:
+ case DW_TAG_template_value_parameter:
+ // The one caller of this was never using the template_param_infos,
+ // and the local variable was taking up a large amount of stack space
+ // in SymbolFileDWARF::ParseType() so this was removed. If we ever need
+ // the template params back, we can add them back.
+ // ParseTemplateDIE (dwarf_cu, die, template_param_infos);
+ break;
+
+ default:
+ break;
+ }
+ }
+ return arg_idx;
+}
+
+void
+DWARFASTParserClang::ParseChildArrayInfo (const SymbolContext& sc,
+ const DWARFDIE &parent_die,
+ int64_t& first_index,
+ std::vector<uint64_t>& element_orders,
+ uint32_t& byte_stride,
+ uint32_t& bit_stride)
+{
+ if (!parent_die)
+ return;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ const dw_tag_t tag = die.Tag();
+ switch (tag)
+ {
+ case DW_TAG_subrange_type:
+ {
+ DWARFAttributes attributes;
+ const size_t num_child_attributes = die.GetAttributes(attributes);
+ if (num_child_attributes > 0)
+ {
+ uint64_t num_elements = 0;
+ uint64_t lower_bound = 0;
+ uint64_t upper_bound = 0;
+ bool upper_bound_valid = false;
+ uint32_t i;
+ for (i=0; i<num_child_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ break;
+
+ case DW_AT_count:
+ num_elements = form_value.Unsigned();
+ break;
+
+ case DW_AT_bit_stride:
+ bit_stride = form_value.Unsigned();
+ break;
+
+ case DW_AT_byte_stride:
+ byte_stride = form_value.Unsigned();
+ break;
+
+ case DW_AT_lower_bound:
+ lower_bound = form_value.Unsigned();
+ break;
+
+ case DW_AT_upper_bound:
+ upper_bound_valid = true;
+ upper_bound = form_value.Unsigned();
+ break;
+
+ default:
+ case DW_AT_abstract_origin:
+ case DW_AT_accessibility:
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_data_location:
+ case DW_AT_declaration:
+ case DW_AT_description:
+ case DW_AT_sibling:
+ case DW_AT_threads_scaled:
+ case DW_AT_type:
+ case DW_AT_visibility:
+ break;
+ }
+ }
+ }
+
+ if (num_elements == 0)
+ {
+ if (upper_bound_valid && upper_bound >= lower_bound)
+ num_elements = upper_bound - lower_bound + 1;
+ }
+
+ element_orders.push_back (num_elements);
+ }
+ }
+ break;
+ }
+ }
+}
+
+Type *
+DWARFASTParserClang::GetTypeForDIE (const DWARFDIE &die)
+{
+ if (die)
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ DWARFFormValue type_die_form;
+ for (size_t i = 0; i < num_attributes; ++i)
+ {
+ dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+
+ if (attr == DW_AT_type && attributes.ExtractFormValueAtIndex(i, form_value))
+ return dwarf->ResolveTypeUID(DIERef(form_value).GetUID());
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+clang::Decl *
+DWARFASTParserClang::GetClangDeclForDIE (const DWARFDIE &die)
+{
+ if (!die)
+ return nullptr;
+
+ switch (die.Tag())
+ {
+ case DW_TAG_variable:
+ case DW_TAG_constant:
+ case DW_TAG_formal_parameter:
+ case DW_TAG_imported_declaration:
+ case DW_TAG_imported_module:
+ break;
+ default:
+ return nullptr;
+ }
+
+ DIEToDeclMap::iterator cache_pos = m_die_to_decl.find(die.GetDIE());
+ if (cache_pos != m_die_to_decl.end())
+ return cache_pos->second;
+
+ if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification))
+ {
+ clang::Decl *decl = GetClangDeclForDIE(spec_die);
+ m_die_to_decl[die.GetDIE()] = decl;
+ m_decl_to_die[decl].insert(die.GetDIE());
+ return decl;
+ }
+
+ clang::Decl *decl = nullptr;
+ switch (die.Tag())
+ {
+ case DW_TAG_variable:
+ case DW_TAG_constant:
+ case DW_TAG_formal_parameter:
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ Type *type = GetTypeForDIE(die);
+ const char *name = die.GetName();
+ clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID()));
+ decl = m_ast.CreateVariableDeclaration(
+ decl_context,
+ name,
+ ClangASTContext::GetQualType(type->GetForwardCompilerType()));
+ break;
+ }
+ case DW_TAG_imported_declaration:
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ lldb::user_id_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET);
+
+ if (dwarf->UserIDMatches(imported_uid))
+ {
+ CompilerDecl imported_decl = dwarf->GetDeclForUID(imported_uid);
+ if (imported_decl)
+ {
+ clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID()));
+ if (clang::NamedDecl *clang_imported_decl = llvm::dyn_cast<clang::NamedDecl>((clang::Decl *)imported_decl.GetOpaqueDecl()))
+ decl = m_ast.CreateUsingDeclaration(decl_context, clang_imported_decl);
+ }
+ }
+ break;
+ }
+ case DW_TAG_imported_module:
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ lldb::user_id_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET);
+
+ if (dwarf->UserIDMatches(imported_uid))
+ {
+ CompilerDeclContext imported_decl = dwarf->GetDeclContextForUID(imported_uid);
+ if (imported_decl)
+ {
+ clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID()));
+ if (clang::NamespaceDecl *ns_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(imported_decl))
+ decl = m_ast.CreateUsingDirectiveDeclaration(decl_context, ns_decl);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ m_die_to_decl[die.GetDIE()] = decl;
+ m_decl_to_die[decl].insert(die.GetDIE());
+
+ return decl;
+}
+
+clang::DeclContext *
+DWARFASTParserClang::GetClangDeclContextForDIE (const DWARFDIE &die)
+{
+ if (die)
+ {
+ clang::DeclContext *decl_ctx = GetCachedClangDeclContextForDIE (die);
+ if (decl_ctx)
+ return decl_ctx;
+
+ bool try_parsing_type = true;
+ switch (die.Tag())
+ {
+ case DW_TAG_compile_unit:
+ decl_ctx = m_ast.GetTranslationUnitDecl();
+ try_parsing_type = false;
+ break;
+
+ case DW_TAG_namespace:
+ decl_ctx = ResolveNamespaceDIE (die);
+ try_parsing_type = false;
+ break;
+
+ case DW_TAG_lexical_block:
+ decl_ctx = (clang::DeclContext *)ResolveBlockDIE(die);
+ try_parsing_type = false;
+ break;
+
+ default:
+ break;
+ }
+
+ if (decl_ctx == nullptr && try_parsing_type)
+ {
+ Type* type = die.GetDWARF()->ResolveType (die);
+ if (type)
+ decl_ctx = GetCachedClangDeclContextForDIE (die);
+ }
+
+ if (decl_ctx)
+ {
+ LinkDeclContextToDIE (decl_ctx, die);
+ return decl_ctx;
+ }
+ }
+ return nullptr;
+}
+
+clang::BlockDecl *
+DWARFASTParserClang::ResolveBlockDIE (const DWARFDIE &die)
+{
+ if (die && die.Tag() == DW_TAG_lexical_block)
+ {
+ clang::BlockDecl *decl = llvm::cast_or_null<clang::BlockDecl>(m_die_to_decl_ctx[die.GetDIE()]);
+
+ if (!decl)
+ {
+ DWARFDIE decl_context_die;
+ clang::DeclContext *decl_context = GetClangDeclContextContainingDIE(die, &decl_context_die);
+ decl = m_ast.CreateBlockDeclaration(decl_context);
+
+ if (decl)
+ LinkDeclContextToDIE((clang::DeclContext *)decl, die);
+ }
+
+ return decl;
+ }
+ return nullptr;
+}
+
+clang::NamespaceDecl *
+DWARFASTParserClang::ResolveNamespaceDIE (const DWARFDIE &die)
+{
+ if (die && die.Tag() == DW_TAG_namespace)
+ {
+ // See if we already parsed this namespace DIE and associated it with a
+ // uniqued namespace declaration
+ clang::NamespaceDecl *namespace_decl = static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die.GetDIE()]);
+ if (namespace_decl)
+ return namespace_decl;
+ else
+ {
+ const char *namespace_name = die.GetName();
+ clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (die, nullptr);
+ namespace_decl = m_ast.GetUniqueNamespaceDeclaration (namespace_name, containing_decl_ctx);
+ Log *log = nullptr;// (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+ if (log)
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ if (namespace_name)
+ {
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace with DW_AT_name(\"%s\") => clang::NamespaceDecl *%p (original = %p)",
+ static_cast<void*>(m_ast.getASTContext()),
+ die.GetID(),
+ namespace_name,
+ static_cast<void*>(namespace_decl),
+ static_cast<void*>(namespace_decl->getOriginalNamespace()));
+ }
+ else
+ {
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)",
+ static_cast<void*>(m_ast.getASTContext()),
+ die.GetID(),
+ static_cast<void*>(namespace_decl),
+ static_cast<void*>(namespace_decl->getOriginalNamespace()));
+ }
+ }
+
+ if (namespace_decl)
+ LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die);
+ return namespace_decl;
+ }
+ }
+ return nullptr;
+}
+
+clang::DeclContext *
+DWARFASTParserClang::GetClangDeclContextContainingDIE (const DWARFDIE &die,
+ DWARFDIE *decl_ctx_die_copy)
+{
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+
+ DWARFDIE decl_ctx_die = dwarf->GetDeclContextDIEContainingDIE (die);
+
+ if (decl_ctx_die_copy)
+ *decl_ctx_die_copy = decl_ctx_die;
+
+ if (decl_ctx_die)
+ {
+ clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE (decl_ctx_die);
+ if (clang_decl_ctx)
+ return clang_decl_ctx;
+ }
+ return m_ast.GetTranslationUnitDecl();
+}
+
+clang::DeclContext *
+DWARFASTParserClang::GetCachedClangDeclContextForDIE (const DWARFDIE &die)
+{
+ if (die)
+ {
+ DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die.GetDIE());
+ if (pos != m_die_to_decl_ctx.end())
+ return pos->second;
+ }
+ return nullptr;
+}
+
+void
+DWARFASTParserClang::LinkDeclContextToDIE (clang::DeclContext *decl_ctx, const DWARFDIE &die)
+{
+ m_die_to_decl_ctx[die.GetDIE()] = decl_ctx;
+ // There can be many DIEs for a single decl context
+ //m_decl_ctx_to_die[decl_ctx].insert(die.GetDIE());
+ m_decl_ctx_to_die.insert(std::make_pair(decl_ctx, die));
+}
+
+bool
+DWARFASTParserClang::CopyUniqueClassMethodTypes (const DWARFDIE &src_class_die,
+ const DWARFDIE &dst_class_die,
+ lldb_private::Type *class_type,
+ DWARFDIECollection &failures)
+{
+ if (!class_type || !src_class_die || !dst_class_die)
+ return false;
+ if (src_class_die.Tag() != dst_class_die.Tag())
+ return false;
+
+ // We need to complete the class type so we can get all of the method types
+ // parsed so we can then unique those types to their equivalent counterparts
+ // in "dst_cu" and "dst_class_die"
+ class_type->GetFullCompilerType ();
+
+ DWARFDIE src_die;
+ DWARFDIE dst_die;
+ UniqueCStringMap<DWARFDIE> src_name_to_die;
+ UniqueCStringMap<DWARFDIE> dst_name_to_die;
+ UniqueCStringMap<DWARFDIE> src_name_to_die_artificial;
+ UniqueCStringMap<DWARFDIE> dst_name_to_die_artificial;
+ for (src_die = src_class_die.GetFirstChild(); src_die.IsValid(); src_die = src_die.GetSibling())
+ {
+ if (src_die.Tag() == DW_TAG_subprogram)
+ {
+ // Make sure this is a declaration and not a concrete instance by looking
+ // for DW_AT_declaration set to 1. Sometimes concrete function instances
+ // are placed inside the class definitions and shouldn't be included in
+ // the list of things are are tracking here.
+ if (src_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1)
+ {
+ const char *src_name = src_die.GetMangledName ();
+ if (src_name)
+ {
+ ConstString src_const_name(src_name);
+ if (src_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
+ src_name_to_die_artificial.Append(src_const_name.GetCString(), src_die);
+ else
+ src_name_to_die.Append(src_const_name.GetCString(), src_die);
+ }
+ }
+ }
+ }
+ for (dst_die = dst_class_die.GetFirstChild(); dst_die.IsValid(); dst_die = dst_die.GetSibling())
+ {
+ if (dst_die.Tag() == DW_TAG_subprogram)
+ {
+ // Make sure this is a declaration and not a concrete instance by looking
+ // for DW_AT_declaration set to 1. Sometimes concrete function instances
+ // are placed inside the class definitions and shouldn't be included in
+ // the list of things are are tracking here.
+ if (dst_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1)
+ {
+ const char *dst_name = dst_die.GetMangledName ();
+ if (dst_name)
+ {
+ ConstString dst_const_name(dst_name);
+ if ( dst_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
+ dst_name_to_die_artificial.Append(dst_const_name.GetCString(), dst_die);
+ else
+ dst_name_to_die.Append(dst_const_name.GetCString(), dst_die);
+ }
+ }
+ }
+ }
+ const uint32_t src_size = src_name_to_die.GetSize ();
+ const uint32_t dst_size = dst_name_to_die.GetSize ();
+ Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_TYPE_COMPLETION));
+
+ // Is everything kosher so we can go through the members at top speed?
+ bool fast_path = true;
+
+ if (src_size != dst_size)
+ {
+ if (src_size != 0 && dst_size != 0)
+ {
+ if (log)
+ log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, but they didn't have the same size (src=%d, dst=%d)",
+ src_class_die.GetOffset(),
+ dst_class_die.GetOffset(),
+ src_size,
+ dst_size);
+ }
+
+ fast_path = false;
+ }
+
+ uint32_t idx;
+
+ if (fast_path)
+ {
+ for (idx = 0; idx < src_size; ++idx)
+ {
+ src_die = src_name_to_die.GetValueAtIndexUnchecked (idx);
+ dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx);
+
+ if (src_die.Tag() != dst_die.Tag())
+ {
+ if (log)
+ log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)",
+ src_class_die.GetOffset(),
+ dst_class_die.GetOffset(),
+ src_die.GetOffset(),
+ src_die.GetTagAsCString(),
+ dst_die.GetOffset(),
+ dst_die.GetTagAsCString());
+ fast_path = false;
+ }
+
+ const char *src_name = src_die.GetMangledName ();
+ const char *dst_name = dst_die.GetMangledName ();
+
+ // Make sure the names match
+ if (src_name == dst_name || (strcmp (src_name, dst_name) == 0))
+ continue;
+
+ if (log)
+ log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)",
+ src_class_die.GetOffset(),
+ dst_class_die.GetOffset(),
+ src_die.GetOffset(),
+ src_name,
+ dst_die.GetOffset(),
+ dst_name);
+
+ fast_path = false;
+ }
+ }
+
+ DWARFASTParserClang *src_dwarf_ast_parser = (DWARFASTParserClang *)src_die.GetDWARFParser();
+ DWARFASTParserClang *dst_dwarf_ast_parser = (DWARFASTParserClang *)dst_die.GetDWARFParser();
+
+ // Now do the work of linking the DeclContexts and Types.
+ if (fast_path)
+ {
+ // We can do this quickly. Just run across the tables index-for-index since
+ // we know each node has matching names and tags.
+ for (idx = 0; idx < src_size; ++idx)
+ {
+ src_die = src_name_to_die.GetValueAtIndexUnchecked (idx);
+ dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx);
+
+ clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()];
+ if (src_decl_ctx)
+ {
+ if (log)
+ log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_decl_ctx),
+ src_die.GetOffset(), dst_die.GetOffset());
+ dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found",
+ src_die.GetOffset(), dst_die.GetOffset());
+ }
+
+ Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()];
+ if (src_child_type)
+ {
+ if (log)
+ log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_child_type),
+ src_child_type->GetID(),
+ src_die.GetOffset(), dst_die.GetOffset());
+ dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset());
+ }
+ }
+ }
+ else
+ {
+ // We must do this slowly. For each member of the destination, look
+ // up a member in the source with the same name, check its tag, and
+ // unique them if everything matches up. Report failures.
+
+ if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty())
+ {
+ src_name_to_die.Sort();
+
+ for (idx = 0; idx < dst_size; ++idx)
+ {
+ const char *dst_name = dst_name_to_die.GetCStringAtIndex(idx);
+ dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
+ src_die = src_name_to_die.Find(dst_name, DWARFDIE());
+
+ if (src_die && (src_die.Tag() == dst_die.Tag()))
+ {
+ clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()];
+ if (src_decl_ctx)
+ {
+ if (log)
+ log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_decl_ctx),
+ src_die.GetOffset(),
+ dst_die.GetOffset());
+ dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset());
+ }
+
+ Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()];
+ if (src_child_type)
+ {
+ if (log)
+ log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_child_type),
+ src_child_type->GetID(),
+ src_die.GetOffset(),
+ dst_die.GetOffset());
+ dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset());
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: couldn't find a match for 0x%8.8x", dst_die.GetOffset());
+
+ failures.Append(dst_die);
+ }
+ }
+ }
+ }
+
+ const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize ();
+ const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize ();
+
+ if (src_size_artificial && dst_size_artificial)
+ {
+ dst_name_to_die_artificial.Sort();
+
+ for (idx = 0; idx < src_size_artificial; ++idx)
+ {
+ const char *src_name_artificial = src_name_to_die_artificial.GetCStringAtIndex(idx);
+ src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked (idx);
+ dst_die = dst_name_to_die_artificial.Find(src_name_artificial, DWARFDIE());
+
+ if (dst_die)
+ {
+ // Both classes have the artificial types, link them
+ clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()];
+ if (src_decl_ctx)
+ {
+ if (log)
+ log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_decl_ctx),
+ src_die.GetOffset(), dst_die.GetOffset());
+ dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset());
+ }
+
+ Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()];
+ if (src_child_type)
+ {
+ if (log)
+ log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_child_type),
+ src_child_type->GetID(),
+ src_die.GetOffset(), dst_die.GetOffset());
+ dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset());
+ }
+ }
+ }
+ }
+
+ if (dst_size_artificial)
+ {
+ for (idx = 0; idx < dst_size_artificial; ++idx)
+ {
+ const char *dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx);
+ dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked (idx);
+ if (log)
+ log->Printf ("warning: need to create artificial method for 0x%8.8x for method '%s'", dst_die.GetOffset(), dst_name_artificial);
+
+ failures.Append(dst_die);
+ }
+ }
+
+ return (failures.Size() != 0);
+}
+
+
+bool
+DWARFASTParserClang::LayoutRecordType(const clang::RecordDecl *record_decl,
+ uint64_t &bit_size,
+ uint64_t &alignment,
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
+{
+ RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find (record_decl);
+ bool success = false;
+ base_offsets.clear();
+ vbase_offsets.clear();
+ if (pos != m_record_decl_to_layout_map.end())
+ {
+ bit_size = pos->second.bit_size;
+ alignment = pos->second.alignment;
+ field_offsets.swap(pos->second.field_offsets);
+ base_offsets.swap (pos->second.base_offsets);
+ vbase_offsets.swap (pos->second.vbase_offsets);
+ m_record_decl_to_layout_map.erase(pos);
+ success = true;
+ }
+ else
+ {
+ bit_size = 0;
+ alignment = 0;
+ field_offsets.clear();
+ }
+ return success;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
new file mode 100644
index 0000000..3814758
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -0,0 +1,213 @@
+//===-- DWARFASTParserClang.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFASTParserClang_h_
+#define SymbolFileDWARF_DWARFASTParserClang_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "clang/AST/CharUnits.h"
+
+// Project includes
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "DWARFDefines.h"
+#include "DWARFASTParser.h"
+
+class DWARFDebugInfoEntry;
+class DWARFDIECollection;
+
+class DWARFASTParserClang : public DWARFASTParser
+{
+public:
+ DWARFASTParserClang (lldb_private::ClangASTContext &ast);
+
+ ~DWARFASTParserClang() override;
+
+ lldb::TypeSP
+ ParseTypeFromDWARF (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ lldb_private::Log *log,
+ bool *type_is_new_ptr) override;
+
+
+ lldb_private::Function *
+ ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die) override;
+
+ bool
+ CanCompleteType (const lldb_private::CompilerType &compiler_type) override;
+
+ bool
+ CompleteType (const lldb_private::CompilerType &compiler_type) override;
+
+ bool
+ CompleteTypeFromDWARF (const DWARFDIE &die,
+ lldb_private::Type *type,
+ lldb_private::CompilerType &compiler_type) override;
+
+ lldb_private::CompilerDecl
+ GetDeclForUIDFromDWARF (const DWARFDIE &die) override;
+
+ std::vector<DWARFDIE>
+ GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextForUIDFromDWARF (const DWARFDIE &die) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) override;
+
+ bool
+ LayoutRecordType(const clang::RecordDecl *record_decl,
+ uint64_t &bit_size,
+ uint64_t &alignment,
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
+
+protected:
+ class DelayedAddObjCClassProperty;
+ typedef std::vector <DelayedAddObjCClassProperty> DelayedPropertyList;
+
+ struct LayoutInfo
+ {
+ LayoutInfo () :
+ bit_size(0),
+ alignment(0),
+ field_offsets(),
+ base_offsets(),
+ vbase_offsets()
+ {
+ }
+ uint64_t bit_size;
+ uint64_t alignment;
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets;
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets;
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets;
+ };
+
+ clang::BlockDecl *
+ ResolveBlockDIE (const DWARFDIE &die);
+
+ clang::NamespaceDecl *
+ ResolveNamespaceDIE (const DWARFDIE &die);
+
+ typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> RecordDeclToLayoutMap;
+
+ bool
+ ParseTemplateDIE (const DWARFDIE &die,
+ lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
+ bool
+ ParseTemplateParameterInfos (const DWARFDIE &parent_die,
+ lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
+
+ bool
+ ParseChildMembers (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ lldb_private::CompilerType &class_compiler_type,
+ const lldb::LanguageType class_language,
+ std::vector<clang::CXXBaseSpecifier *>& base_classes,
+ std::vector<int>& member_accessibilities,
+ DWARFDIECollection& member_function_dies,
+ DelayedPropertyList& delayed_properties,
+ lldb::AccessType &default_accessibility,
+ bool &is_a_class,
+ LayoutInfo &layout_info);
+
+ size_t
+ ParseChildParameters (const lldb_private::SymbolContext& sc,
+ clang::DeclContext *containing_decl_ctx,
+ const DWARFDIE &parent_die,
+ bool skip_artificial,
+ bool &is_static,
+ bool &is_variadic,
+ std::vector<lldb_private::CompilerType>& function_args,
+ std::vector<clang::ParmVarDecl*>& function_param_decls,
+ unsigned &type_quals);
+
+ void
+ ParseChildArrayInfo (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &parent_die,
+ int64_t& first_index,
+ std::vector<uint64_t>& element_orders,
+ uint32_t& byte_stride,
+ uint32_t& bit_stride);
+
+ size_t
+ ParseChildEnumerators (const lldb_private::SymbolContext& sc,
+ lldb_private::CompilerType &compiler_type,
+ bool is_signed,
+ uint32_t enumerator_byte_size,
+ const DWARFDIE &parent_die);
+
+ lldb_private::Type *
+ GetTypeForDIE (const DWARFDIE &die);
+
+ clang::Decl *
+ GetClangDeclForDIE (const DWARFDIE &die);
+
+ clang::DeclContext *
+ GetClangDeclContextForDIE (const DWARFDIE &die);
+
+ clang::DeclContext *
+ GetClangDeclContextContainingDIE (const DWARFDIE &die,
+ DWARFDIE *decl_ctx_die);
+
+ bool
+ CopyUniqueClassMethodTypes (const DWARFDIE &src_class_die,
+ const DWARFDIE &dst_class_die,
+ lldb_private::Type *class_type,
+ DWARFDIECollection &failures);
+
+ clang::DeclContext *
+ GetCachedClangDeclContextForDIE (const DWARFDIE &die);
+
+ void
+ LinkDeclContextToDIE (clang::DeclContext *decl_ctx,
+ const DWARFDIE &die);
+
+ void
+ LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die);
+
+ lldb_private::ClangASTImporter &
+ GetClangASTImporter();
+
+ lldb::TypeSP
+ ParseTypeFromDWO (const DWARFDIE &die, lldb_private::Log *log);
+
+ //----------------------------------------------------------------------
+ // Return true if this type is a declaration to a type in an external
+ // module.
+ //----------------------------------------------------------------------
+ lldb::ModuleSP
+ GetModuleForType (const DWARFDIE &die);
+
+ typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet;
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
+ //typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
+ typedef std::multimap<const clang::DeclContext *, const DWARFDIE> DeclContextToDIEMap;
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> DIEToDeclMap;
+ typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap;
+
+ lldb_private::ClangASTContext &m_ast;
+ DIEToDeclMap m_die_to_decl;
+ DeclToDIEMap m_decl_to_die;
+ DIEToDeclContextMap m_die_to_decl_ctx;
+ DeclContextToDIEMap m_decl_ctx_to_die;
+ RecordDeclToLayoutMap m_record_decl_to_layout_map;
+ std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_ap;
+};
+
+#endif // SymbolFileDWARF_DWARFASTParserClang_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
new file mode 100644
index 0000000..bde2694
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
@@ -0,0 +1,828 @@
+//===-- DWARFASTParserGo.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFASTParserGo.h"
+
+#include "DWARFASTParserGo.h"
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDeclContext.h"
+#include "DWARFDefines.h"
+#include "DWARFDIE.h"
+#include "DWARFDIECollection.h"
+#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+#include "UniqueDWARFASTType.h"
+
+#include "clang/Basic/Specifiers.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/TypeList.h"
+
+//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
+
+#ifdef ENABLE_DEBUG_PRINTF
+#include <stdio.h>
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+#define DW_AT_go_kind 0x2900
+#define DW_AT_go_key 0x2901
+#define DW_AT_go_elem 0x2902
+
+using namespace lldb;
+using namespace lldb_private;
+DWARFASTParserGo::DWARFASTParserGo(GoASTContext &ast)
+ : m_ast(ast)
+{
+}
+
+DWARFASTParserGo::~DWARFASTParserGo()
+{
+}
+
+TypeSP
+DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log,
+ bool *type_is_new_ptr)
+{
+ TypeSP type_sp;
+
+ if (type_is_new_ptr)
+ *type_is_new_ptr = false;
+
+ if (die)
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ if (log)
+ {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log, "DWARFASTParserGo::ParseTypeFromDWARF (die = 0x%8.8x) %s name = '%s')", die.GetOffset(),
+ DW_TAG_value_to_name(die.Tag()), die.GetName());
+ }
+
+ Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE());
+ TypeList *type_list = dwarf->GetTypeList();
+ if (type_ptr == NULL)
+ {
+ if (type_is_new_ptr)
+ *type_is_new_ptr = true;
+
+ const dw_tag_t tag = die.Tag();
+
+ bool is_forward_declaration = false;
+ DWARFAttributes attributes;
+ const char *type_name_cstr = NULL;
+ ConstString type_name_const_str;
+ Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
+ uint64_t byte_size = 0;
+ uint64_t go_kind = 0;
+ Declaration decl;
+
+ Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
+ CompilerType compiler_type;
+ DWARFFormValue form_value;
+
+ dw_attr_t attr;
+
+ switch (tag)
+ {
+ case DW_TAG_base_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_typedef:
+ case DW_TAG_unspecified_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ const size_t num_attributes = die.GetAttributes(attributes);
+ lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ if (type_name_cstr)
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+ case DW_AT_byte_size:
+ byte_size = form_value.Unsigned();
+ break;
+ case DW_AT_encoding:
+ // = form_value.Unsigned();
+ break;
+ case DW_AT_type:
+ encoding_uid = form_value.Reference();
+ break;
+ case DW_AT_go_kind:
+ go_kind = form_value.Unsigned();
+ break;
+ default:
+ // Do we care about DW_AT_go_key or DW_AT_go_elem?
+ break;
+ }
+ }
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid);
+
+ switch (tag)
+ {
+ default:
+ break;
+
+ case DW_TAG_unspecified_type:
+ resolve_state = Type::eResolveStateFull;
+ compiler_type = m_ast.CreateVoidType(type_name_const_str);
+ break;
+
+ case DW_TAG_base_type:
+ resolve_state = Type::eResolveStateFull;
+ compiler_type = m_ast.CreateBaseType(go_kind, type_name_const_str, byte_size);
+ break;
+
+ case DW_TAG_pointer_type:
+ encoding_data_type = Type::eEncodingIsPointerUID;
+ break;
+ case DW_TAG_typedef:
+ encoding_data_type = Type::eEncodingIsTypedefUID;
+ CompilerType impl;
+ Type *type = dwarf->ResolveTypeUID(encoding_uid);
+ if (type)
+ {
+ if (go_kind == 0 && type->GetName() == type_name_const_str)
+ {
+ // Go emits extra typedefs as a forward declaration. Ignore these.
+ dwarf->m_die_to_type[die.GetDIE()] = type;
+ return type->shared_from_this();
+ }
+ impl = type->GetForwardCompilerType();
+ compiler_type = m_ast.CreateTypedefType (go_kind, type_name_const_str, impl);
+ }
+ break;
+ }
+
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size,
+ NULL, encoding_uid, encoding_data_type, &decl, compiler_type, resolve_state));
+
+ dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
+ }
+ break;
+
+ case DW_TAG_structure_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+ bool byte_size_valid = false;
+
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_byte_size:
+ byte_size = form_value.Unsigned();
+ byte_size_valid = true;
+ break;
+
+ case DW_AT_go_kind:
+ go_kind = form_value.Unsigned();
+ break;
+
+ // TODO: Should we use SLICETYPE's DW_AT_go_elem?
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ // TODO(ribrdb): Do we need this?
+
+ // UniqueDWARFASTType is large, so don't create a local variables on the
+ // stack, put it on the heap. This function is often called recursively
+ // and clang isn't good and sharing the stack space for variables in different blocks.
+ std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType());
+
+ // Only try and unique the type if it has a name.
+ if (type_name_const_str &&
+ dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
+ byte_size_valid ? byte_size : -1, *unique_ast_entry_ap))
+ {
+ // We have already parsed this type or from another
+ // compile unit. GCC loves to use the "one definition
+ // rule" which can result in multiple definitions
+ // of the same class over and over in each compile
+ // unit.
+ type_sp = unique_ast_entry_ap->m_type_sp;
+ if (type_sp)
+ {
+ dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
+ return type_sp;
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr);
+
+ bool compiler_type_was_created = false;
+ compiler_type.SetCompilerType(&m_ast, dwarf->m_forward_decl_die_to_clang_type.lookup(die.GetDIE()));
+ if (!compiler_type)
+ {
+ compiler_type_was_created = true;
+ compiler_type = m_ast.CreateStructType(go_kind, type_name_const_str, byte_size);
+ }
+
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size,
+ NULL, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type,
+ Type::eResolveStateForward));
+
+ // Add our type to the unique type map so we don't
+ // end up creating many copies of the same type over
+ // and over in the ASTContext for our module
+ unique_ast_entry_ap->m_type_sp = type_sp;
+ unique_ast_entry_ap->m_die = die;
+ unique_ast_entry_ap->m_declaration = decl;
+ unique_ast_entry_ap->m_byte_size = byte_size;
+ dwarf->GetUniqueDWARFASTTypeMap().Insert(type_name_const_str, *unique_ast_entry_ap);
+
+ if (!is_forward_declaration)
+ {
+ // Always start the definition for a class type so that
+ // if the class has child classes or types that require
+ // the class to be created for use as their decl contexts
+ // the class will be ready to accept these child definitions.
+ if (die.HasChildren() == false)
+ {
+ // No children for this struct/union/class, lets finish it
+ m_ast.CompleteStructType(compiler_type);
+ }
+ else if (compiler_type_was_created)
+ {
+ // Leave this as a forward declaration until we need
+ // to know the details of the type. lldb_private::Type
+ // will automatically call the SymbolFile virtual function
+ // "SymbolFileDWARF::CompleteType(Type *)"
+ // When the definition needs to be defined.
+ dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] = compiler_type.GetOpaqueQualType();
+ dwarf->m_forward_decl_clang_type_to_die[compiler_type.GetOpaqueQualType()] = die.GetDIERef();
+ // SetHasExternalStorage (compiler_type.GetOpaqueQualType(), true);
+ }
+ }
+ }
+ break;
+
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ bool is_variadic = false;
+ clang::StorageClass storage = clang::SC_None; //, Extern, Static, PrivateExtern
+
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_external:
+ if (form_value.Unsigned())
+ {
+ if (storage == clang::SC_None)
+ storage = clang::SC_Extern;
+ else
+ storage = clang::SC_PrivateExtern;
+ }
+ break;
+
+ case DW_AT_high_pc:
+ case DW_AT_low_pc:
+ break;
+ }
+ }
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr);
+
+ std::vector<CompilerType> function_param_types;
+
+ // Parse the function children for the parameters
+
+ if (die.HasChildren())
+ {
+ ParseChildParameters(sc, die, is_variadic, function_param_types);
+ }
+
+ // compiler_type will get the function prototype clang type after this call
+ compiler_type = m_ast.CreateFunctionType(type_name_const_str, function_param_types.data(),
+ function_param_types.size(), is_variadic);
+
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, 0, NULL,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type,
+ Type::eResolveStateFull));
+ assert(type_sp.get());
+ }
+ break;
+
+ case DW_TAG_array_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
+ int64_t first_index = 0;
+ uint32_t byte_stride = 0;
+ uint32_t bit_stride = 0;
+ const size_t num_attributes = die.GetAttributes(attributes);
+
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_type:
+ type_die_offset = form_value.Reference();
+ break;
+ case DW_AT_byte_size:
+ break; // byte_size = form_value.Unsigned(); break;
+ case DW_AT_go_kind:
+ go_kind = form_value.Unsigned();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr);
+
+ Type *element_type = dwarf->ResolveTypeUID(type_die_offset);
+
+ if (element_type)
+ {
+ std::vector<uint64_t> element_orders;
+ ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride);
+ if (byte_stride == 0)
+ byte_stride = element_type->GetByteSize();
+ CompilerType array_element_type = element_type->GetForwardCompilerType();
+ if (element_orders.size() > 0)
+ {
+ if (element_orders.size() > 1)
+ printf("golang: unsupported multi-dimensional array %s\n", type_name_cstr);
+ compiler_type =
+ m_ast.CreateArrayType(type_name_const_str, array_element_type, element_orders[0]);
+ }
+ else
+ {
+ compiler_type = m_ast.CreateArrayType(type_name_const_str, array_element_type, 0);
+ }
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str,
+ byte_stride, NULL, type_die_offset, Type::eEncodingIsUID, &decl,
+ compiler_type, Type::eResolveStateFull));
+ type_sp->SetEncodingType(element_type);
+ }
+ }
+ }
+ break;
+
+ default:
+ dwarf->GetObjectFile()->GetModule()->ReportError("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), "
+ "please file a bug and attach the file at the "
+ "start of this error message",
+ die.GetOffset(), tag, DW_TAG_value_to_name(tag));
+ break;
+ }
+
+ if (type_sp.get())
+ {
+ DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
+ dw_tag_t sc_parent_tag = sc_parent_die.Tag();
+
+ SymbolContextScope *symbol_context_scope = NULL;
+ if (sc_parent_tag == DW_TAG_compile_unit)
+ {
+ symbol_context_scope = sc.comp_unit;
+ }
+ else if (sc.function != NULL && sc_parent_die)
+ {
+ symbol_context_scope =
+ sc.function->GetBlock(true).FindBlockByID(dwarf->MakeUserID(sc_parent_die.GetOffset()));
+ if (symbol_context_scope == NULL)
+ symbol_context_scope = sc.function;
+ }
+
+ if (symbol_context_scope != NULL)
+ {
+ type_sp->SetSymbolContextScope(symbol_context_scope);
+ }
+
+ // We are ready to put this type into the uniqued list up at the module level
+ type_list->Insert(type_sp);
+
+ dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
+ }
+ }
+ else if (type_ptr != DIE_IS_BEING_PARSED)
+ {
+ type_sp = type_ptr->shared_from_this();
+ }
+ }
+ return type_sp;
+}
+
+size_t
+DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc,
+
+ const DWARFDIE &parent_die, bool &is_variadic,
+ std::vector<CompilerType> &function_param_types)
+{
+ if (!parent_die)
+ return 0;
+
+ size_t arg_idx = 0;
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+
+ dw_tag_t tag = die.Tag();
+ switch (tag)
+ {
+ case DW_TAG_formal_parameter:
+ {
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ Declaration decl;
+ dw_offset_t param_type_die_offset = DW_INVALID_OFFSET;
+
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ // = form_value.AsCString();
+ break;
+ case DW_AT_type:
+ param_type_die_offset = form_value.Reference();
+ break;
+ case DW_AT_location:
+ // if (form_value.BlockData())
+ // {
+ // const DWARFDataExtractor& debug_info_data =
+ // debug_info();
+ // uint32_t block_length = form_value.Unsigned();
+ // DWARFDataExtractor location(debug_info_data,
+ // form_value.BlockData() - debug_info_data.GetDataStart(),
+ // block_length);
+ // }
+ // else
+ // {
+ // }
+ // break;
+ default:
+ break;
+ }
+ }
+ }
+
+ Type *type = parent_die.ResolveTypeUID(param_type_die_offset);
+ if (type)
+ {
+ function_param_types.push_back(type->GetForwardCompilerType());
+ }
+ }
+ arg_idx++;
+ }
+ break;
+
+ case DW_TAG_unspecified_parameters:
+ is_variadic = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return arg_idx;
+}
+
+void
+DWARFASTParserGo::ParseChildArrayInfo(const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
+ std::vector<uint64_t> &element_orders, uint32_t &byte_stride,
+ uint32_t &bit_stride)
+{
+ if (!parent_die)
+ return;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ const dw_tag_t tag = die.Tag();
+ switch (tag)
+ {
+ case DW_TAG_subrange_type:
+ {
+ DWARFAttributes attributes;
+ const size_t num_child_attributes = die.GetAttributes(attributes);
+ if (num_child_attributes > 0)
+ {
+ uint64_t num_elements = 0;
+ uint32_t i;
+ for (i = 0; i < num_child_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_count:
+ num_elements = form_value.Unsigned();
+ break;
+
+ default:
+ case DW_AT_type:
+ break;
+ }
+ }
+ }
+
+ element_orders.push_back(num_elements);
+ }
+ }
+ break;
+ }
+ }
+}
+
+bool
+DWARFASTParserGo::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, CompilerType &compiler_type)
+{
+ if (!die)
+ return false;
+
+ const dw_tag_t tag = die.Tag();
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
+ log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type->GetName().AsCString());
+ assert(compiler_type);
+ DWARFAttributes attributes;
+
+ switch (tag)
+ {
+ case DW_TAG_structure_type:
+ {
+ {
+ if (die.HasChildren())
+ {
+ SymbolContext sc(die.GetLLDBCompileUnit());
+
+ ParseChildMembers(sc, die, compiler_type);
+ }
+ }
+ m_ast.CompleteStructType(compiler_type);
+ return (bool)compiler_type;
+ }
+
+ default:
+ assert(false && "not a forward go type decl!");
+ break;
+ }
+
+ return false;
+}
+
+size_t
+DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &parent_die, CompilerType &class_compiler_type)
+{
+ size_t count = 0;
+ uint32_t member_idx = 0;
+
+ ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
+ GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(class_compiler_type.GetTypeSystem());
+ if (ast == nullptr)
+ return 0;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ dw_tag_t tag = die.Tag();
+
+ switch (tag)
+ {
+ case DW_TAG_member:
+ {
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ Declaration decl;
+ const char *name = NULL;
+
+ lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+ uint32_t member_byte_offset = UINT32_MAX;
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ name = form_value.AsCString();
+ break;
+ case DW_AT_type:
+ encoding_uid = form_value.Reference();
+ break;
+ case DW_AT_data_member_location:
+ if (form_value.BlockData())
+ {
+ Value initialValue(0);
+ Value memberOffset(0);
+ const DWARFDataExtractor &debug_info_data =
+ die.GetDWARF()->get_debug_info_data();
+ uint32_t block_length = form_value.Unsigned();
+ uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+ if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
+ NULL, // ClangExpressionVariableList *
+ NULL, // ClangExpressionDeclMap *
+ NULL, // RegisterContext *
+ module_sp, debug_info_data, die.GetCU(),
+ block_offset, block_length, eRegisterKindDWARF,
+ &initialValue, memberOffset, NULL))
+ {
+ member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
+ }
+ }
+ else
+ {
+ // With DWARF 3 and later, if the value is an integer constant,
+ // this form value is the offset in bytes from the beginning
+ // of the containing entity.
+ member_byte_offset = form_value.Unsigned();
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ Type *member_type = die.ResolveTypeUID(encoding_uid);
+ if (member_type)
+ {
+ CompilerType member_go_type = member_type->GetFullCompilerType();
+ ConstString name_const_str(name);
+ m_ast.AddFieldToStruct(class_compiler_type, name_const_str, member_go_type, member_byte_offset);
+ }
+ }
+ ++member_idx;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return count;
+}
+
+Function *
+DWARFASTParserGo::ParseFunctionFromDWARF(const SymbolContext &sc, const DWARFDIE &die)
+{
+ DWARFRangeList func_ranges;
+ const char *name = NULL;
+ const char *mangled = NULL;
+ int decl_file = 0;
+ int decl_line = 0;
+ int decl_column = 0;
+ int call_file = 0;
+ int call_line = 0;
+ int call_column = 0;
+ DWARFExpression frame_base(die.GetCU());
+
+ assert(die.Tag() == DW_TAG_subprogram);
+
+ if (die.Tag() != DW_TAG_subprogram)
+ return NULL;
+
+ if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line,
+ call_column, &frame_base))
+ {
+ // Union of all ranges in the function DIE (if the function is discontiguous)
+ AddressRange func_range;
+ lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0);
+ lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0);
+ if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr)
+ {
+ ModuleSP module_sp(die.GetModule());
+ func_range.GetBaseAddress().ResolveAddressUsingFileSections(lowest_func_addr, module_sp->GetSectionList());
+ if (func_range.GetBaseAddress().IsValid())
+ func_range.SetByteSize(highest_func_addr - lowest_func_addr);
+ }
+
+ if (func_range.GetBaseAddress().IsValid())
+ {
+ Mangled func_name;
+ func_name.SetValue(ConstString(name), false);
+
+ FunctionSP func_sp;
+ std::unique_ptr<Declaration> decl_ap;
+ if (decl_file != 0 || decl_line != 0 || decl_column != 0)
+ decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line,
+ decl_column));
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ // Supply the type _only_ if it has already been parsed
+ Type *func_type = dwarf->m_die_to_type.lookup(die.GetDIE());
+
+ assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
+
+ if (dwarf->FixupAddress(func_range.GetBaseAddress()))
+ {
+ const user_id_t func_user_id = dwarf->MakeUserID(die.GetOffset());
+ func_sp.reset(new Function(sc.comp_unit,
+ dwarf->MakeUserID(func_user_id), // UserID is the DIE offset
+ dwarf->MakeUserID(func_user_id), func_name, func_type,
+ func_range)); // first address range
+
+ if (func_sp.get() != NULL)
+ {
+ if (frame_base.IsValid())
+ func_sp->GetFrameBaseExpression() = frame_base;
+ sc.comp_unit->AddFunction(func_sp);
+ return func_sp.get();
+ }
+ }
+ }
+ }
+ return NULL;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
new file mode 100644
index 0000000..5039fc7
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
@@ -0,0 +1,84 @@
+//===-- DWARFASTParserGo.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFASTParserGo_h_
+#define SymbolFileDWARF_DWARFASTParserGo_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+// Project includes
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Symbol/GoASTContext.h"
+#include "DWARFDefines.h"
+#include "DWARFASTParser.h"
+#include "DWARFDIE.h"
+
+class DWARFDebugInfoEntry;
+class DWARFDIECollection;
+
+class DWARFASTParserGo : public DWARFASTParser
+{
+public:
+ DWARFASTParserGo(lldb_private::GoASTContext &ast);
+
+ ~DWARFASTParserGo() override;
+
+ lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log,
+ bool *type_is_new_ptr) override;
+
+ lldb_private::Function *
+ ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
+ const DWARFDIE &die) override;
+
+ bool
+ CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,
+ lldb_private::CompilerType &go_type) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override
+ {
+ return lldb_private::CompilerDeclContext();
+ }
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override
+ {
+ return lldb_private::CompilerDeclContext();
+ }
+
+ lldb_private::CompilerDecl
+ GetDeclForUIDFromDWARF (const DWARFDIE &die) override
+ {
+ return lldb_private::CompilerDecl();
+ }
+
+ std::vector<DWARFDIE>
+ GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override
+ {
+ return std::vector<DWARFDIE>();
+ }
+
+private:
+ size_t ParseChildParameters(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, bool &is_variadic,
+ std::vector<lldb_private::CompilerType> &function_param_types);
+ void ParseChildArrayInfo(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
+ std::vector<uint64_t> &element_orders, uint32_t &byte_stride, uint32_t &bit_stride);
+
+ size_t ParseChildMembers(const lldb_private::SymbolContext &sc, const DWARFDIE &die,
+ lldb_private::CompilerType &class_compiler_type);
+
+ lldb_private::GoASTContext &m_ast;
+};
+
+#endif // SymbolFileDWARF_DWARFASTParserGo_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
new file mode 100644
index 0000000..a522bcb
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
@@ -0,0 +1,90 @@
+//===-- DWARFAttribute.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFAttribute.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFCompileUnit.h"
+
+DWARFAttributes::DWARFAttributes() :
+ m_infos()
+{
+}
+
+DWARFAttributes::~DWARFAttributes()
+{
+}
+
+
+uint32_t
+DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const
+{
+ collection::const_iterator end = m_infos.end();
+ collection::const_iterator beg = m_infos.begin();
+ collection::const_iterator pos;
+ for (pos = beg; pos != end; ++pos)
+ {
+ if (pos->attr.get_attr() == attr)
+ return std::distance(beg, pos);
+ }
+ return UINT32_MAX;
+}
+
+void
+DWARFAttributes::Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form)
+{
+ AttributeValue attr_value = { cu, attr_die_offset, { attr, form } };
+ m_infos.push_back(attr_value);
+}
+
+bool
+DWARFAttributes::ContainsAttribute(dw_attr_t attr) const
+{
+ return FindAttributeIndex(attr) != UINT32_MAX;
+}
+
+bool
+DWARFAttributes::RemoveAttribute(dw_attr_t attr)
+{
+ uint32_t attr_index = FindAttributeIndex(attr);
+ if (attr_index != UINT32_MAX)
+ {
+ m_infos.erase(m_infos.begin() + attr_index);
+ return true;
+ }
+ return false;
+}
+
+bool
+DWARFAttributes::ExtractFormValueAtIndex (uint32_t i, DWARFFormValue &form_value) const
+{
+ const DWARFCompileUnit *cu = CompileUnitAtIndex(i);
+ form_value.SetCompileUnit(cu);
+ form_value.SetForm(FormAtIndex(i));
+ lldb::offset_t offset = DIEOffsetAtIndex(i);
+ return form_value.ExtractValue(cu->GetSymbolFileDWARF()->get_debug_info_data(), &offset);
+}
+
+uint64_t
+DWARFAttributes::FormValueAsUnsigned (dw_attr_t attr, uint64_t fail_value) const
+{
+ const uint32_t attr_idx = FindAttributeIndex (attr);
+ if (attr_idx != UINT32_MAX)
+ return FormValueAsUnsignedAtIndex (attr_idx, fail_value);
+ return fail_value;
+}
+
+uint64_t
+DWARFAttributes::FormValueAsUnsignedAtIndex(uint32_t i, uint64_t fail_value) const
+{
+ DWARFFormValue form_value;
+ if (ExtractFormValueAtIndex(i, form_value))
+ return form_value.Reference();
+ return fail_value;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
index 40c8af3..f5ca9cc 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -10,36 +10,72 @@
#ifndef SymbolFileDWARF_DWARFAttribute_h_
#define SymbolFileDWARF_DWARFAttribute_h_
+#include "llvm/ADT/SmallVector.h"
#include "DWARFDefines.h"
#include <vector>
+class DWARFCompileUnit;
+class DWARFFormValue;
+
class DWARFAttribute
{
public:
DWARFAttribute(dw_attr_t attr, dw_form_t form) :
- m_attr_form ( attr << 16 | form )
+ m_attr (attr),
+ m_form (form)
{
}
- void set(dw_attr_t attr, dw_form_t form) { m_attr_form = (attr << 16) | form; }
- void set_attr(dw_attr_t attr) { m_attr_form = (m_attr_form & 0x0000ffffu) | (attr << 16); }
- void set_form(dw_form_t form) { m_attr_form = (m_attr_form & 0xffff0000u) | form; }
- dw_attr_t get_attr() const { return m_attr_form >> 16; }
- dw_form_t get_form() const { return (dw_form_t)m_attr_form; }
- void get(dw_attr_t& attr, dw_form_t& form) const
+ void set (dw_attr_t attr, dw_form_t form) { m_attr = attr; m_form = form; }
+ void set_attr (dw_attr_t attr) { m_attr = attr; }
+ void set_form (dw_form_t form) { m_form = form; }
+ dw_attr_t get_attr () const { return m_attr; }
+ dw_form_t get_form () const { return m_form; }
+ void get (dw_attr_t& attr, dw_form_t& form) const
{
- uint32_t attr_form = m_attr_form;
- attr = attr_form >> 16;
- form = (dw_form_t)attr_form;
+ attr = m_attr;
+ form = m_form;
}
- bool operator == (const DWARFAttribute& rhs) const { return m_attr_form == rhs.m_attr_form; }
+ bool operator == (const DWARFAttribute& rhs) const { return m_attr == rhs.m_attr && m_form == rhs.m_form; }
typedef std::vector<DWARFAttribute> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
protected:
- uint32_t m_attr_form; // Upper 16 bits is attribute, lower 16 bits is form
+ dw_attr_t m_attr;
+ dw_form_t m_form;
};
+class DWARFAttributes
+{
+public:
+ DWARFAttributes();
+ ~DWARFAttributes();
+
+ void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form);
+ const DWARFCompileUnit * CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; }
+ dw_offset_t DIEOffsetAtIndex(uint32_t i) const { return m_infos[i].die_offset; }
+ dw_attr_t AttributeAtIndex(uint32_t i) const { return m_infos[i].attr.get_attr(); }
+ dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].attr.get_form(); }
+ bool ExtractFormValueAtIndex (uint32_t i, DWARFFormValue &form_value) const;
+ uint64_t FormValueAsUnsignedAtIndex (uint32_t i, uint64_t fail_value) const;
+ uint64_t FormValueAsUnsigned (dw_attr_t attr, uint64_t fail_value) const;
+ uint32_t FindAttributeIndex(dw_attr_t attr) const;
+ bool ContainsAttribute(dw_attr_t attr) const;
+ bool RemoveAttribute(dw_attr_t attr);
+ void Clear() { m_infos.clear(); }
+ size_t Size() const { return m_infos.size(); }
+
+protected:
+ struct AttributeValue
+ {
+ const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in case we have DW_FORM_ref_addr values
+ dw_offset_t die_offset;
+ DWARFAttribute attr;
+ };
+ typedef llvm::SmallVector<AttributeValue, 8> collection;
+ collection m_infos;
+};
+
#endif // SymbolFileDWARF_DWARFAttribute_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index 6093310..e7cb2b4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -12,12 +12,13 @@
#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
@@ -27,6 +28,7 @@
#include "LogChannelDWARF.h"
#include "NameToDIE.h"
#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDwo.h"
#include "SymbolFileDWARFDebugMap.h"
using namespace lldb;
@@ -52,10 +54,16 @@ DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) :
m_producer_version_minor (0),
m_producer_version_update (0),
m_language_type (eLanguageTypeUnknown),
- m_is_dwarf64 (false)
+ m_is_dwarf64 (false),
+ m_is_optimized (eLazyBoolCalculate),
+ m_addr_base (0),
+ m_base_obj_offset (DW_INVALID_OFFSET)
{
}
+DWARFCompileUnit::~DWARFCompileUnit()
+{}
+
void
DWARFCompileUnit::Clear()
{
@@ -71,6 +79,9 @@ DWARFCompileUnit::Clear()
m_producer = eProducerInvalid;
m_language_type = eLanguageTypeUnknown;
m_is_dwarf64 = false;
+ m_is_optimized = eLazyBoolCalculate;
+ m_addr_base = 0;
+ m_base_obj_offset = DW_INVALID_OFFSET;
}
bool
@@ -128,6 +139,9 @@ DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die)
if (keep_compile_unit_die)
m_die_array.push_back(tmp_array.front());
}
+
+ if (m_dwo_symbol_file)
+ m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(keep_compile_unit_die);
}
//----------------------------------------------------------------------
@@ -174,7 +188,8 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
die_index_stack.reserve(32);
die_index_stack.push_back(0);
bool prev_die_had_children = false;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);
while (offset < next_cu_offset &&
die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset))
{
@@ -188,12 +203,12 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
const bool null_die = die.IsNULL();
if (depth == 0)
{
- uint64_t base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+ if (initial_die_array_size == 0)
+ AddCompileUnitDIE(die);
+ uint64_t base_addr = die.GetAttributeValueAsAddress(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
if (base_addr == LLDB_INVALID_ADDRESS)
- base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_entry_pc, 0);
+ base_addr = die.GetAttributeValueAsAddress(m_dwarf2Data, this, DW_AT_entry_pc, 0);
SetBaseAddress (base_addr);
- if (initial_die_array_size == 0)
- AddDIE (die);
if (cu_die_only)
return 1;
}
@@ -283,9 +298,83 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
verbose_log->PutCString (strm.GetString().c_str());
}
- return m_die_array.size();
+ if (!m_dwo_symbol_file)
+ return m_die_array.size();
+
+ DWARFCompileUnit* dwo_cu = m_dwo_symbol_file->GetCompileUnit();
+ size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(cu_die_only);
+ return m_die_array.size() + dwo_die_count - 1; // We have 2 CU die, but we waht to count it only as one
}
+void
+DWARFCompileUnit::AddCompileUnitDIE(DWARFDebugInfoEntry& die)
+{
+ assert (m_die_array.empty() && "Compile unit DIE already added");
+ AddDIE(die);
+
+ DWARFDebugInfoEntry& cu_die = m_die_array.front();
+
+ const char* dwo_name = cu_die.GetAttributeValueAsString(m_dwarf2Data,
+ this,
+ DW_AT_GNU_dwo_name,
+ nullptr);
+ if (!dwo_name)
+ return;
+
+ FileSpec dwo_file(dwo_name, true);
+ if (dwo_file.IsRelative())
+ {
+ const char* comp_dir = cu_die.GetAttributeValueAsString(m_dwarf2Data,
+ this,
+ DW_AT_comp_dir,
+ nullptr);
+ if (!comp_dir)
+ return;
+
+ dwo_file.SetFile(comp_dir, true);
+ dwo_file.AppendPathComponent(dwo_name);
+ }
+
+ if (!dwo_file.Exists())
+ return;
+
+ DataBufferSP dwo_file_data_sp;
+ lldb::offset_t dwo_file_data_offset = 0;
+ ObjectFileSP dwo_obj_file = ObjectFile::FindPlugin(m_dwarf2Data->GetObjectFile()->GetModule(),
+ &dwo_file,
+ 0 /* file_offset */,
+ dwo_file.GetByteSize(),
+ dwo_file_data_sp,
+ dwo_file_data_offset);
+ if (dwo_obj_file == nullptr)
+ return;
+
+ std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file(new SymbolFileDWARFDwo(dwo_obj_file, this));
+
+ DWARFCompileUnit* dwo_cu = dwo_symbol_file->GetCompileUnit();
+ if (!dwo_cu)
+ return; // Can't fetch the compile unit from the dwo file.
+
+ DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly();
+ if (!dwo_cu_die.IsValid())
+ return; // Can't fetch the compile unit DIE from the dwo file.
+
+ uint64_t main_dwo_id = cu_die.GetAttributeValueAsUnsigned(m_dwarf2Data,
+ this,
+ DW_AT_GNU_dwo_id,
+ 0);
+ uint64_t sub_dwo_id = dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0);
+ if (main_dwo_id != sub_dwo_id)
+ return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to a differectn compilation.
+
+ m_dwo_symbol_file = std::move(dwo_symbol_file);
+
+ dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf2Data,
+ this,
+ DW_AT_GNU_addr_base,
+ 0);
+ dwo_cu->SetAddrBase(addr_base, m_offset);
+}
dw_offset_t
DWARFCompileUnit::GetAbbrevOffset() const
@@ -373,6 +462,16 @@ DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size)
g_default_addr_size = addr_size;
}
+lldb::user_id_t
+DWARFCompileUnit::GetID () const
+{
+ dw_offset_t local_id = m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset;
+ if (m_dwarf2Data)
+ return m_dwarf2Data->MakeUserID(local_id);
+ else
+ return local_id;
+}
+
void
DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
DWARFDebugAranges* debug_aranges)
@@ -381,13 +480,15 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
// in order to produce a compile unit level set of address ranges that
// is accurate.
+ size_t num_debug_aranges = debug_aranges->GetNumRanges();
+
// First get the compile unit DIE only and check if it has a DW_AT_ranges
- const DWARFDebugInfoEntry* die = GetCompileUnitDIEOnly();
+ const DWARFDebugInfoEntry* die = GetCompileUnitDIEPtrOnly();
const dw_offset_t cu_offset = GetOffset();
if (die)
{
- DWARFDebugRanges::RangeList ranges;
+ DWARFRangeList ranges;
const size_t num_ranges = die->GetAttributeAddressRanges(dwarf2Data, this, ranges, false);
if (num_ranges > 0)
{
@@ -397,7 +498,7 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
// this with recent GCC builds.
for (size_t i=0; i<num_ranges; ++i)
{
- const DWARFDebugRanges::RangeList::Entry &range = ranges.GetEntryRef(i);
+ const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);
debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd());
}
@@ -411,11 +512,11 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
// and then throwing them all away to keep memory usage down.
const bool clear_dies = ExtractDIEsIfNeeded (false) > 1;
- die = DIE();
+ die = DIEPtr();
if (die)
die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges);
- if (debug_aranges->IsEmpty())
+ if (debug_aranges->GetNumRanges() == num_debug_aranges)
{
// We got nothing from the functions, maybe we have a line tables only
// situation. Check the line tables and build the arange table from this.
@@ -437,7 +538,6 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
{
const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);
debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd());
- printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
}
}
}
@@ -446,7 +546,7 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
}
}
- if (debug_aranges->IsEmpty())
+ if (debug_aranges->GetNumRanges() == num_debug_aranges)
{
// We got nothing from the functions, maybe we have a line tables only
// situation. Check the line tables and build the arange table from this.
@@ -465,7 +565,6 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
{
const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);
debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
- printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
}
}
}
@@ -493,119 +592,85 @@ DWARFCompileUnit::GetFunctionAranges ()
"DWARFCompileUnit::GetFunctionAranges() for compile unit at .debug_info[0x%8.8x]",
GetOffset());
}
- const DWARFDebugInfoEntry* die = DIE();
+ const DWARFDebugInfoEntry* die = DIEPtr();
if (die)
die->BuildFunctionAddressRangeTable (m_dwarf2Data, this, m_func_aranges_ap.get());
+
+ if (m_dwo_symbol_file)
+ {
+ DWARFCompileUnit* dwo_cu = m_dwo_symbol_file->GetCompileUnit();
+ const DWARFDebugInfoEntry* dwo_die = dwo_cu->DIEPtr();
+ if (dwo_die)
+ dwo_die->BuildFunctionAddressRangeTable (m_dwo_symbol_file.get(),
+ dwo_cu,
+ m_func_aranges_ap.get());
+ }
+
const bool minimize = false;
m_func_aranges_ap->Sort(minimize);
}
return *m_func_aranges_ap.get();
}
-bool
-DWARFCompileUnit::LookupAddress
-(
- const dw_addr_t address,
- DWARFDebugInfoEntry** function_die_handle,
- DWARFDebugInfoEntry** block_die_handle
-)
+DWARFDIE
+DWARFCompileUnit::LookupAddress (const dw_addr_t address)
{
- bool success = false;
-
- if (function_die_handle != NULL && DIE())
+ if (DIE())
{
-
const DWARFDebugAranges &func_aranges = GetFunctionAranges ();
// Re-check the aranges auto pointer contents in case it was created above
if (!func_aranges.IsEmpty())
- {
- *function_die_handle = GetDIEPtr(func_aranges.FindAddress(address));
- if (*function_die_handle != NULL)
- {
- success = true;
- if (block_die_handle != NULL)
- {
- DWARFDebugInfoEntry* child = (*function_die_handle)->GetFirstChild();
- while (child)
- {
- if (child->LookupAddress(address, m_dwarf2Data, this, NULL, block_die_handle))
- break;
- child = child->GetSibling();
- }
- }
- }
- }
+ return GetDIE(func_aranges.FindAddress(address));
}
- return success;
+ return DWARFDIE();
}
//----------------------------------------------------------------------
// Compare function DWARFDebugAranges::Range structures
//----------------------------------------------------------------------
-static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2)
+static bool CompareDIEOffset (const DWARFDebugInfoEntry& die, const dw_offset_t die_offset)
{
- return die1.GetOffset() < die2.GetOffset();
+ return die.GetOffset() < die_offset;
}
//----------------------------------------------------------------------
-// GetDIEPtr()
+// GetDIE()
//
-// Get the DIE (Debug Information Entry) with the specified offset.
+// Get the DIE (Debug Information Entry) with the specified offset by
+// first checking if the DIE is contained within this compile unit and
+// grabbing the DIE from this compile unit. Otherwise we grab the DIE
+// from the DWARF file.
//----------------------------------------------------------------------
-DWARFDebugInfoEntry*
-DWARFCompileUnit::GetDIEPtr(dw_offset_t die_offset)
+DWARFDIE
+DWARFCompileUnit::GetDIE (dw_offset_t die_offset)
{
if (die_offset != DW_INVALID_OFFSET)
{
- ExtractDIEsIfNeeded (false);
- DWARFDebugInfoEntry compare_die;
- compare_die.SetOffset(die_offset);
- DWARFDebugInfoEntry::iterator end = m_die_array.end();
- DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset);
- if (pos != end)
- {
- if (die_offset == (*pos).GetOffset())
- return &(*pos);
- }
- }
- return NULL; // Not found in any compile units
-}
+ if (m_dwo_symbol_file)
+ return m_dwo_symbol_file->GetCompileUnit()->GetDIE(die_offset);
-//----------------------------------------------------------------------
-// GetDIEPtrContainingOffset()
-//
-// Get the DIE (Debug Information Entry) that contains the specified
-// .debug_info offset.
-//----------------------------------------------------------------------
-const DWARFDebugInfoEntry*
-DWARFCompileUnit::GetDIEPtrContainingOffset(dw_offset_t die_offset)
-{
- if (die_offset != DW_INVALID_OFFSET)
- {
- ExtractDIEsIfNeeded (false);
- DWARFDebugInfoEntry compare_die;
- compare_die.SetOffset(die_offset);
- DWARFDebugInfoEntry::iterator end = m_die_array.end();
- DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset);
- if (pos != end)
+ if (ContainsDIEOffset(die_offset))
{
- if (die_offset >= (*pos).GetOffset())
+ ExtractDIEsIfNeeded (false);
+ DWARFDebugInfoEntry::iterator end = m_die_array.end();
+ DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, die_offset, CompareDIEOffset);
+ if (pos != end)
{
- DWARFDebugInfoEntry::iterator next = pos + 1;
- if (next != end)
- {
- if (die_offset < (*next).GetOffset())
- return &(*pos);
- }
+ if (die_offset == (*pos).GetOffset())
+ return DWARFDIE(this, &(*pos));
}
}
+ else
+ {
+ // Don't specify the compile unit offset as we don't know it because the DIE belongs to
+ // a different compile unit in the same symbol file.
+ return m_dwarf2Data->DebugInfo()->GetDIE (DIERef(die_offset));
+ }
}
- return NULL; // Not found in any compile units
+ return DWARFDIE(); // Not found
}
-
-
size_t
DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& dies, uint32_t depth) const
{
@@ -615,7 +680,7 @@ DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& die
for (pos = m_die_array.begin(); pos != end; ++pos)
{
if (pos->Tag() == tag)
- dies.Append (&(*pos));
+ dies.Append (DWARFDIE(this, &(*pos)));
}
// Return the number of DIEs added to the collection
@@ -646,8 +711,7 @@ DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& die
void
-DWARFCompileUnit::Index (const uint32_t cu_idx,
- NameToDIE& func_basenames,
+DWARFCompileUnit::Index (NameToDIE& func_basenames,
NameToDIE& func_fullnames,
NameToDIE& func_methods,
NameToDIE& func_selectors,
@@ -656,10 +720,6 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
NameToDIE& types,
NameToDIE& namespaces)
{
- const DWARFDataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data();
-
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);
-
Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS));
if (log)
@@ -670,9 +730,57 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
}
const LanguageType cu_language = GetLanguageType();
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);
+
+ IndexPrivate(this,
+ cu_language,
+ fixed_form_sizes,
+ GetOffset(),
+ func_basenames,
+ func_fullnames,
+ func_methods,
+ func_selectors,
+ objc_class_selectors,
+ globals,
+ types,
+ namespaces);
+
+ SymbolFileDWARFDwo* dwo_symbol_file = GetDwoSymbolFile();
+ if (dwo_symbol_file)
+ {
+ IndexPrivate(dwo_symbol_file->GetCompileUnit(),
+ cu_language,
+ fixed_form_sizes,
+ GetOffset(),
+ func_basenames,
+ func_fullnames,
+ func_methods,
+ func_selectors,
+ objc_class_selectors,
+ globals,
+ types,
+ namespaces);
+ }
+}
+
+void
+DWARFCompileUnit::IndexPrivate (DWARFCompileUnit* dwarf_cu,
+ const LanguageType cu_language,
+ const DWARFFormValue::FixedFormSizes& fixed_form_sizes,
+ const dw_offset_t cu_offset,
+ NameToDIE& func_basenames,
+ NameToDIE& func_fullnames,
+ NameToDIE& func_methods,
+ NameToDIE& func_selectors,
+ NameToDIE& objc_class_selectors,
+ NameToDIE& globals,
+ NameToDIE& types,
+ NameToDIE& namespaces)
+{
DWARFDebugInfoEntry::const_iterator pos;
- DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin();
- DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
+ DWARFDebugInfoEntry::const_iterator begin = dwarf_cu->m_die_array.begin();
+ DWARFDebugInfoEntry::const_iterator end = dwarf_cu->m_die_array.end();
for (pos = begin; pos != end; ++pos)
{
const DWARFDebugInfoEntry &die = *pos;
@@ -701,17 +809,17 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
continue;
}
- DWARFDebugInfoEntry::Attributes attributes;
+ DWARFAttributes attributes;
const char *name = NULL;
const char *mangled_cstr = NULL;
bool is_declaration = false;
//bool is_artificial = false;
bool has_address = false;
- bool has_location = false;
+ bool has_location_or_const_value = false;
bool is_global_or_static_variable = false;
- dw_offset_t specification_die_offset = DW_INVALID_OFFSET;
- const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, fixed_form_sizes, attributes);
+ DWARFFormValue specification_die_form;
+ const size_t num_attributes = die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes);
if (num_attributes > 0)
{
for (uint32_t i=0; i<num_attributes; ++i)
@@ -721,24 +829,24 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
switch (attr)
{
case DW_AT_name:
- if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
- name = form_value.AsCString(debug_str);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ name = form_value.AsCString();
break;
case DW_AT_declaration:
- if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
is_declaration = form_value.Unsigned() != 0;
break;
// case DW_AT_artificial:
-// if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+// if (attributes.ExtractFormValueAtIndex(i, form_value))
// is_artificial = form_value.Unsigned() != 0;
// break;
case DW_AT_MIPS_linkage_name:
case DW_AT_linkage_name:
- if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
- mangled_cstr = form_value.AsCString(debug_str);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ mangled_cstr = form_value.AsCString();
break;
case DW_AT_low_pc:
@@ -752,7 +860,8 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
break;
case DW_AT_location:
- has_location = true;
+ case DW_AT_const_value:
+ has_location_or_const_value = true;
if (tag == DW_TAG_variable)
{
const DWARFDebugInfoEntry* parent_die = die.GetParent();
@@ -800,8 +909,8 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
break;
case DW_AT_specification:
- if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
- specification_die_offset = form_value.Reference();
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ specification_die_form = form_value;
break;
}
}
@@ -814,24 +923,22 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
{
if (name)
{
- // Note, this check is also done in ParseMethodName, but since this is a hot loop, we do the
- // simple inlined check outside the call.
- ObjCLanguageRuntime::MethodName objc_method(name, true);
+ ObjCLanguage::MethodName objc_method(name, true);
if (objc_method.IsValid(true))
{
ConstString objc_class_name_with_category (objc_method.GetClassNameWithCategory());
ConstString objc_selector_name (objc_method.GetSelector());
ConstString objc_fullname_no_category_name (objc_method.GetFullNameWithoutCategory(true));
ConstString objc_class_name_no_category (objc_method.GetClassName());
- func_fullnames.Insert (ConstString(name), die.GetOffset());
+ func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
if (objc_class_name_with_category)
- objc_class_selectors.Insert(objc_class_name_with_category, die.GetOffset());
+ objc_class_selectors.Insert(objc_class_name_with_category, DIERef(cu_offset, die.GetOffset()));
if (objc_class_name_no_category && objc_class_name_no_category != objc_class_name_with_category)
- objc_class_selectors.Insert(objc_class_name_no_category, die.GetOffset());
+ objc_class_selectors.Insert(objc_class_name_no_category, DIERef(cu_offset, die.GetOffset()));
if (objc_selector_name)
- func_selectors.Insert (objc_selector_name, die.GetOffset());
+ func_selectors.Insert (objc_selector_name, DIERef(cu_offset, die.GetOffset()));
if (objc_fullname_no_category_name)
- func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset());
+ func_fullnames.Insert (objc_fullname_no_category_name, DIERef(cu_offset, die.GetOffset()));
}
// If we have a mangled name, then the DW_AT_name attribute
// is usually the method name without the class or any parameters
@@ -846,32 +953,23 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
}
else
{
- if (specification_die_offset != DW_INVALID_OFFSET)
+ if (specification_die_form.IsValid())
{
- const DWARFDebugInfoEntry *specification_die = m_dwarf2Data->DebugInfo()->GetDIEPtr (specification_die_offset, NULL);
- if (specification_die)
- {
- parent = specification_die->GetParent();
- if (parent)
- {
- parent_tag = parent->Tag();
-
- if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type)
- is_method = true;
- }
- }
+ DWARFDIE specification_die = dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE (DIERef(specification_die_form));
+ if (specification_die.GetParent().IsStructOrClass())
+ is_method = true;
}
}
}
if (is_method)
- func_methods.Insert (ConstString(name), die.GetOffset());
+ func_methods.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
else
- func_basenames.Insert (ConstString(name), die.GetOffset());
+ func_basenames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
- func_fullnames.Insert (ConstString(name), die.GetOffset());
+ func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
}
if (mangled_cstr)
{
@@ -882,10 +980,10 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (name && ::strcmp(name, mangled_cstr) != 0)))
{
Mangled mangled (ConstString(mangled_cstr), true);
- func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
+ func_fullnames.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
- func_fullnames.Insert (demangled, die.GetOffset());
+ func_fullnames.Insert (demangled, DIERef(cu_offset, die.GetOffset()));
}
}
}
@@ -895,7 +993,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
if (has_address)
{
if (name)
- func_basenames.Insert (ConstString(name), die.GetOffset());
+ func_basenames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
if (mangled_cstr)
{
// Make sure our mangled name isn't the same string table entry
@@ -905,14 +1003,14 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))
{
Mangled mangled (ConstString(mangled_cstr), true);
- func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
+ func_fullnames.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
- func_fullnames.Insert (demangled, die.GetOffset());
+ func_fullnames.Insert (demangled, DIERef(cu_offset, die.GetOffset()));
}
}
else
- func_fullnames.Insert (ConstString(name), die.GetOffset());
+ func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
}
break;
@@ -928,19 +1026,19 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
case DW_TAG_unspecified_type:
if (name && is_declaration == false)
{
- types.Insert (ConstString(name), die.GetOffset());
+ types.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
}
break;
case DW_TAG_namespace:
if (name)
- namespaces.Insert (ConstString(name), die.GetOffset());
+ namespaces.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
break;
case DW_TAG_variable:
- if (name && has_location && is_global_or_static_variable)
+ if (name && has_location_or_const_value && is_global_or_static_variable)
{
- globals.Insert (ConstString(name), die.GetOffset());
+ globals.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
// Be sure to include variables by their mangled and demangled
// names if they have any since a variable can have a basename
// "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled
@@ -953,10 +1051,10 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))
{
Mangled mangled (ConstString(mangled_cstr), true);
- globals.Insert (mangled.GetMangledName(), die.GetOffset());
+ globals.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
- globals.Insert (demangled, die.GetOffset());
+ globals.Insert (demangled, DIERef(cu_offset, die.GetOffset()));
}
}
break;
@@ -1004,7 +1102,7 @@ DWARFCompileUnit::ParseProducerInfo ()
m_producer_version_minor = UINT32_MAX;
m_producer_version_update = UINT32_MAX;
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly();
+ const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
if (die)
{
@@ -1095,10 +1193,9 @@ DWARFCompileUnit::GetLanguageType()
if (m_language_type != eLanguageTypeUnknown)
return m_language_type;
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly();
+ const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
if (die)
- m_language_type = LanguageTypeFromDWARF(
- die->GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_language, 0));
+ m_language_type = LanguageTypeFromDWARF(die->GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_language, 0));
return m_language_type;
}
@@ -1108,3 +1205,57 @@ DWARFCompileUnit::IsDWARF64() const
return m_is_dwarf64;
}
+bool
+DWARFCompileUnit::GetIsOptimized ()
+{
+ if (m_is_optimized == eLazyBoolCalculate)
+ {
+ const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
+ if (die)
+ {
+ m_is_optimized = eLazyBoolNo;
+ if (die->GetAttributeValueAsUnsigned (m_dwarf2Data, this, DW_AT_APPLE_optimized, 0) == 1)
+ {
+ m_is_optimized = eLazyBoolYes;
+ }
+ }
+ }
+ if (m_is_optimized == eLazyBoolYes)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+DWARFFormValue::FixedFormSizes
+DWARFCompileUnit::GetFixedFormSizes ()
+{
+ return DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), IsDWARF64());
+}
+
+TypeSystem *
+DWARFCompileUnit::GetTypeSystem ()
+{
+ if (m_dwarf2Data)
+ return m_dwarf2Data->GetTypeSystemForLanguage(GetLanguageType());
+ else
+ return nullptr;
+}
+
+void
+DWARFCompileUnit::SetUserData(void *d)
+{
+ m_user_data = d;
+ if (m_dwo_symbol_file)
+ m_dwo_symbol_file->GetCompileUnit()->SetUserData(d);
+}
+
+void
+DWARFCompileUnit::SetAddrBase(dw_addr_t addr_base, dw_offset_t base_obj_offset)
+{
+ m_addr_base = addr_base;
+ m_base_obj_offset = base_obj_offset;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index 93c8df8..0fcaaca 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -12,9 +12,11 @@
#include "lldb/lldb-enumerations.h"
#include "DWARFDebugInfoEntry.h"
-#include "SymbolFileDWARF.h"
+#include "DWARFDIE.h"
class NameToDIE;
+class SymbolFileDWARF;
+class SymbolFileDWARFDwo;
class DWARFCompileUnit
{
@@ -29,19 +31,17 @@ public:
};
DWARFCompileUnit(SymbolFileDWARF* dwarf2Data);
+ ~DWARFCompileUnit();
bool Extract(const lldb_private::DWARFDataExtractor &debug_info, lldb::offset_t *offset_ptr);
size_t ExtractDIEsIfNeeded (bool cu_die_only);
- bool LookupAddress(
- const dw_addr_t address,
- DWARFDebugInfoEntry** function_die,
- DWARFDebugInfoEntry** block_die);
-
+ DWARFDIE LookupAddress(const dw_addr_t address);
size_t AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& matching_dies, uint32_t depth = UINT32_MAX) const;
void Clear();
bool Verify(lldb_private::Stream *s) const;
void Dump(lldb_private::Stream *s) const;
dw_offset_t GetOffset() const { return m_offset; }
+ lldb::user_id_t GetID () const;
uint32_t Size() const { return m_is_dwarf64 ? 23 : 11; /* Size in bytes of the compile unit header */ }
bool ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && die_offset < GetNextCompileUnitOffset(); }
dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); }
@@ -53,32 +53,35 @@ public:
dw_offset_t GetAbbrevOffset() const;
uint8_t GetAddressByteSize() const { return m_addr_size; }
dw_addr_t GetBaseAddress() const { return m_base_addr; }
+ dw_addr_t GetAddrBase() const { return m_addr_base; }
+ void SetAddrBase(dw_addr_t addr_base, dw_offset_t base_obj_offset);
void ClearDIEs(bool keep_compile_unit_die);
void BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
DWARFDebugAranges* debug_aranges);
+
+ lldb_private::TypeSystem *
+ GetTypeSystem();
+
+ DWARFFormValue::FixedFormSizes
+ GetFixedFormSizes ();
+
void
SetBaseAddress(dw_addr_t base_addr)
{
m_base_addr = base_addr;
}
- const DWARFDebugInfoEntry*
+ DWARFDIE
GetCompileUnitDIEOnly()
{
- ExtractDIEsIfNeeded (true);
- if (m_die_array.empty())
- return NULL;
- return &m_die_array[0];
+ return DWARFDIE(this, GetCompileUnitDIEPtrOnly());
}
- const DWARFDebugInfoEntry*
- DIE()
+ DWARFDIE
+ DIE ()
{
- ExtractDIEsIfNeeded (false);
- if (m_die_array.empty())
- return NULL;
- return &m_die_array[0];
+ return DWARFDIE(this, DIEPtr());
}
void
@@ -97,6 +100,9 @@ public:
m_die_array.reserve(GetDebugInfoSize() / 24);
m_die_array.push_back(die);
}
+
+ void
+ AddCompileUnitDIE (DWARFDebugInfoEntry& die);
bool
HasDIEsParsed () const
@@ -104,17 +110,8 @@ public:
return m_die_array.size() > 1;
}
- DWARFDebugInfoEntry*
- GetDIEAtIndexUnchecked (uint32_t idx)
- {
- return &m_die_array[idx];
- }
-
- DWARFDebugInfoEntry*
- GetDIEPtr (dw_offset_t die_offset);
-
- const DWARFDebugInfoEntry*
- GetDIEPtrContainingOffset (dw_offset_t die_offset);
+ DWARFDIE
+ GetDIE (dw_offset_t die_offset);
static uint8_t
GetAddressByteSize(const DWARFCompileUnit* cu);
@@ -135,10 +132,7 @@ public:
}
void
- SetUserData(void *d)
- {
- m_user_data = d;
- }
+ SetUserData(void *d);
bool
Supports_DW_AT_APPLE_objc_complete_type ();
@@ -149,15 +143,8 @@ public:
bool
Supports_unnamed_objc_bitfields ();
-// void
-// AddGlobalDIEByIndex (uint32_t die_idx);
-//
-// void
-// AddGlobal (const DWARFDebugInfoEntry* die);
-//
void
- Index (const uint32_t cu_idx,
- NameToDIE& func_basenames,
+ Index (NameToDIE& func_basenames,
NameToDIE& func_fullnames,
NameToDIE& func_methods,
NameToDIE& func_selectors,
@@ -196,8 +183,24 @@ public:
bool
IsDWARF64() const;
+ bool
+ GetIsOptimized ();
+
+ SymbolFileDWARFDwo*
+ GetDwoSymbolFile() const
+ {
+ return m_dwo_symbol_file.get();
+ }
+
+ dw_offset_t
+ GetBaseObjOffset() const
+ {
+ return m_base_obj_offset;
+ }
+
protected:
SymbolFileDWARF* m_dwarf2Data;
+ std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file;
const DWARFAbbreviationDeclarationSet *m_abbrevs;
void * m_user_data;
DWARFDebugInfoEntry::collection m_die_array; // The compile unit debug information entry item
@@ -213,10 +216,49 @@ protected:
uint32_t m_producer_version_update;
lldb::LanguageType m_language_type;
bool m_is_dwarf64;
-
+ lldb_private::LazyBool m_is_optimized;
+ dw_addr_t m_addr_base; // Value of DW_AT_addr_base
+ dw_offset_t m_base_obj_offset; // If this is a dwo compile unit this is the offset of
+ // the base compile unit in the main object file
+
void
ParseProducerInfo ();
+
+ static void
+ IndexPrivate (DWARFCompileUnit* dwarf_cu,
+ const lldb::LanguageType cu_language,
+ const DWARFFormValue::FixedFormSizes& fixed_form_sizes,
+ const dw_offset_t cu_offset,
+ NameToDIE& func_basenames,
+ NameToDIE& func_fullnames,
+ NameToDIE& func_methods,
+ NameToDIE& func_selectors,
+ NameToDIE& objc_class_selectors,
+ NameToDIE& globals,
+ NameToDIE& types,
+ NameToDIE& namespaces);
+
private:
+
+ const DWARFDebugInfoEntry*
+ GetCompileUnitDIEPtrOnly()
+ {
+ ExtractDIEsIfNeeded (true);
+ if (m_die_array.empty())
+ return NULL;
+ return &m_die_array[0];
+ }
+
+ const DWARFDebugInfoEntry*
+ DIEPtr()
+ {
+ ExtractDIEsIfNeeded (false);
+ if (m_die_array.empty())
+ return NULL;
+ return &m_die_array[0];
+ }
+
+
DISALLOW_COPY_AND_ASSIGN (DWARFCompileUnit);
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
new file mode 100644
index 0000000..0564de9
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -0,0 +1,543 @@
+//===-- DWARFDIE.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDIE.h"
+
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugAbbrev.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDebugInfoEntry.h"
+#include "DWARFDebugRanges.h"
+#include "DWARFDeclContext.h"
+#include "DWARFDIECollection.h"
+#include "DWARFFormValue.h"
+#include "SymbolFileDWARF.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeSystem.h"
+
+using namespace lldb_private;
+
+DIERef
+DWARFDIE::GetDIERef() const
+{
+ if (!IsValid())
+ return DIERef();
+
+ dw_offset_t cu_offset = m_cu->GetOffset();
+ if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
+ cu_offset = m_cu->GetBaseObjOffset();
+ return DIERef(cu_offset, m_die->GetOffset());
+}
+
+dw_tag_t
+DWARFDIE::Tag() const
+{
+ if (m_die)
+ return m_die->Tag();
+ else
+ return 0;
+}
+
+const char *
+DWARFDIE::GetTagAsCString () const
+{
+ return lldb_private::DW_TAG_value_to_name (Tag());
+}
+
+DWARFDIE
+DWARFDIE::GetParent () const
+{
+ if (IsValid())
+ return DWARFDIE(m_cu, m_die->GetParent());
+ else
+ return DWARFDIE();
+}
+
+DWARFDIE
+DWARFDIE::GetFirstChild () const
+{
+ if (IsValid())
+ return DWARFDIE(m_cu, m_die->GetFirstChild());
+ else
+ return DWARFDIE();
+}
+
+DWARFDIE
+DWARFDIE::GetSibling () const
+{
+ if (IsValid())
+ return DWARFDIE(m_cu, m_die->GetSibling());
+ else
+ return DWARFDIE();
+}
+
+DWARFDIE
+DWARFDIE::GetReferencedDIE (const dw_attr_t attr) const
+{
+ const dw_offset_t die_offset = GetAttributeValueAsReference (attr, DW_INVALID_OFFSET);
+ if (die_offset != DW_INVALID_OFFSET)
+ return GetDIE(die_offset);
+ else
+ return DWARFDIE();
+}
+
+DWARFDIE
+DWARFDIE::GetDIE (dw_offset_t die_offset) const
+{
+ if (IsValid())
+ return m_cu->GetDIE(die_offset);
+ else
+ return DWARFDIE();
+}
+
+const char *
+DWARFDIE::GetAttributeValueAsString (const dw_attr_t attr, const char *fail_value) const
+{
+ if (IsValid())
+ return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr, fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t
+DWARFDIE::GetAttributeValueAsUnsigned (const dw_attr_t attr, uint64_t fail_value) const
+{
+ if (IsValid())
+ return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr, fail_value);
+ else
+ return fail_value;
+}
+
+int64_t
+DWARFDIE::GetAttributeValueAsSigned (const dw_attr_t attr, int64_t fail_value) const
+{
+ if (IsValid())
+ return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr, fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t
+DWARFDIE::GetAttributeValueAsReference (const dw_attr_t attr, uint64_t fail_value) const
+{
+ if (IsValid())
+ return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr, fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t
+DWARFDIE::GetAttributeValueAsAddress (const dw_attr_t attr, uint64_t fail_value) const
+{
+ if (IsValid())
+ return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr, fail_value);
+ else
+ return fail_value;
+}
+
+
+DWARFDIE
+DWARFDIE::LookupDeepestBlock (lldb::addr_t file_addr) const
+{
+ if (IsValid())
+ {
+ SymbolFileDWARF *dwarf= GetDWARF();
+ DWARFCompileUnit *cu = GetCU();
+ DWARFDebugInfoEntry* function_die = nullptr;
+ DWARFDebugInfoEntry* block_die = nullptr;
+ if (m_die->LookupAddress (file_addr,
+ dwarf,
+ cu,
+ &function_die,
+ &block_die))
+ {
+ if (block_die && block_die != function_die)
+ {
+ if (cu->ContainsDIEOffset(block_die->GetOffset()))
+ return DWARFDIE(cu, block_die);
+ else
+ return DWARFDIE(dwarf->DebugInfo()->GetCompileUnitContainingDIE(DIERef(cu->GetOffset(), block_die->GetOffset())), block_die);
+ }
+ }
+ }
+ return DWARFDIE();
+}
+
+lldb::user_id_t
+DWARFDIE::GetID () const
+{
+ const dw_offset_t die_offset = GetOffset();
+ if (die_offset != DW_INVALID_OFFSET)
+ {
+ lldb::user_id_t id = 0;
+ SymbolFileDWARF *dwarf = GetDWARF();
+ if (dwarf)
+ id = dwarf->MakeUserID(die_offset);
+ else
+ id = die_offset;
+
+ if (m_cu)
+ {
+ lldb::user_id_t cu_id = m_cu->GetID()&0xffffffff00000000ull;
+ assert ((id&0xffffffff00000000ull) == 0 ||
+ (cu_id&0xffffffff00000000ll) == 0 ||
+ (id&0xffffffff00000000ull) == (cu_id&0xffffffff00000000ll));
+ id |= cu_id;
+ }
+ return id;
+ }
+ return LLDB_INVALID_UID;
+}
+
+const char *
+DWARFDIE::GetName () const
+{
+ if (IsValid())
+ return m_die->GetName (GetDWARF(), m_cu);
+ else
+ return nullptr;
+}
+
+const char *
+DWARFDIE::GetMangledName () const
+{
+ if (IsValid())
+ return m_die->GetMangledName (GetDWARF(), m_cu);
+ else
+ return nullptr;
+}
+
+const char *
+DWARFDIE::GetPubname () const
+{
+ if (IsValid())
+ return m_die->GetPubname (GetDWARF(), m_cu);
+ else
+ return nullptr;
+}
+
+const char *
+DWARFDIE::GetQualifiedName (std::string &storage) const
+{
+ if (IsValid())
+ return m_die->GetQualifiedName (GetDWARF(), m_cu, storage);
+ else
+ return nullptr;
+}
+
+lldb::LanguageType
+DWARFDIE::GetLanguage () const
+{
+ if (IsValid())
+ return m_cu->GetLanguageType();
+ else
+ return lldb::eLanguageTypeUnknown;
+}
+
+
+lldb::ModuleSP
+DWARFDIE::GetModule () const
+{
+ SymbolFileDWARF *dwarf = GetDWARF();
+ if (dwarf)
+ return dwarf->GetObjectFile()->GetModule();
+ else
+ return lldb::ModuleSP();
+}
+
+lldb_private::CompileUnit *
+DWARFDIE::GetLLDBCompileUnit () const
+{
+ if (IsValid())
+ return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU());
+ else
+ return nullptr;
+}
+
+lldb_private::Type *
+DWARFDIE::ResolveType () const
+{
+ if (IsValid())
+ return GetDWARF()->ResolveType(*this, true);
+ else
+ return nullptr;
+}
+
+lldb_private::Type *
+DWARFDIE::ResolveTypeUID (lldb::user_id_t uid) const
+{
+ SymbolFileDWARF *dwarf = GetDWARF();
+ if (dwarf)
+ return dwarf->ResolveTypeUID(uid);
+ else
+ return nullptr;
+}
+
+void
+DWARFDIE::GetDeclContextDIEs (DWARFDIECollection &decl_context_dies) const
+{
+ if (IsValid())
+ {
+ DWARFDIE parent_decl_ctx_die = m_die->GetParentDeclContextDIE (GetDWARF(), GetCU());
+ if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != GetDIE())
+ {
+ decl_context_dies.Append(parent_decl_ctx_die);
+ parent_decl_ctx_die.GetDeclContextDIEs (decl_context_dies);
+ }
+ }
+}
+
+void
+DWARFDIE::GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const
+{
+ if (IsValid())
+ {
+ m_die->GetDWARFDeclContext (GetDWARF(), GetCU(), dwarf_decl_ctx);
+ }
+ else
+ {
+ dwarf_decl_ctx.Clear();
+ }
+}
+
+void
+DWARFDIE::GetDWOContext (std::vector<CompilerContext> &context) const
+{
+ const dw_tag_t tag = Tag();
+ if (tag == DW_TAG_compile_unit)
+ return;
+ DWARFDIE parent = GetParent();
+ if (parent)
+ parent.GetDWOContext(context);
+ switch (tag)
+ {
+ case DW_TAG_module:
+ context.push_back(CompilerContext(CompilerContextKind::Module, ConstString(GetName())));
+ break;
+ case DW_TAG_namespace:
+ context.push_back(CompilerContext(CompilerContextKind::Namespace, ConstString(GetName())));
+ break;
+ case DW_TAG_structure_type:
+ context.push_back(CompilerContext(CompilerContextKind::Structure, ConstString(GetName())));
+ break;
+ case DW_TAG_union_type:
+ context.push_back(CompilerContext(CompilerContextKind::Union, ConstString(GetName())));
+ break;
+ case DW_TAG_class_type:
+ context.push_back(CompilerContext(CompilerContextKind::Class, ConstString(GetName())));
+ break;
+ case DW_TAG_enumeration_type:
+ context.push_back(CompilerContext(CompilerContextKind::Enumeration, ConstString(GetName())));
+ break;
+ case DW_TAG_subprogram:
+ context.push_back(CompilerContext(CompilerContextKind::Function, ConstString(GetPubname())));
+ break;
+ case DW_TAG_variable:
+ context.push_back(CompilerContext(CompilerContextKind::Variable, ConstString(GetPubname())));
+ break;
+ case DW_TAG_typedef:
+ context.push_back(CompilerContext(CompilerContextKind::Typedef, ConstString(GetName())));
+ break;
+ default:
+ break;
+ }
+}
+
+
+
+DWARFDIE
+DWARFDIE::GetParentDeclContextDIE () const
+{
+ if (IsValid())
+ return m_die->GetParentDeclContextDIE(GetDWARF(), m_cu);
+ else
+ return DWARFDIE();
+}
+
+
+dw_offset_t
+DWARFDIE::GetOffset () const
+{
+ if (IsValid())
+ return m_die->GetOffset();
+ else
+ return DW_INVALID_OFFSET;
+}
+
+dw_offset_t
+DWARFDIE::GetCompileUnitRelativeOffset () const
+{
+ if (IsValid())
+ return m_die->GetOffset() - m_cu->GetOffset();
+ else
+ return DW_INVALID_OFFSET;
+}
+
+SymbolFileDWARF *
+DWARFDIE::GetDWARF () const
+{
+ if (m_cu)
+ return m_cu->GetSymbolFileDWARF();
+ else
+ return nullptr;
+}
+
+lldb_private::TypeSystem *
+DWARFDIE::GetTypeSystem () const
+{
+ if (m_cu)
+ return m_cu->GetTypeSystem();
+ else
+ return nullptr;
+}
+
+DWARFASTParser *
+DWARFDIE::GetDWARFParser () const
+{
+ lldb_private::TypeSystem *type_system = GetTypeSystem ();
+ if (type_system)
+ return type_system->GetDWARFParser();
+ else
+ return nullptr;
+}
+
+bool
+DWARFDIE::IsStructOrClass () const
+{
+ const dw_tag_t tag = Tag();
+ return tag == DW_TAG_class_type || tag == DW_TAG_structure_type;
+}
+
+
+DWARFDIE
+DWARFDIE::GetContainingDWOModuleDIE () const
+{
+ if (IsValid())
+ {
+ DWARFDIE top_module_die;
+ // Now make sure this DIE is scoped in a DW_TAG_module tag and return true if so
+ for (DWARFDIE parent = GetParent(); parent.IsValid(); parent = parent.GetParent())
+ {
+ const dw_tag_t tag = parent.Tag();
+ if (tag == DW_TAG_module)
+ top_module_die = parent;
+ else if (tag == DW_TAG_compile_unit)
+ break;
+ }
+
+ return top_module_die;
+ }
+ return DWARFDIE();
+}
+
+lldb::ModuleSP
+DWARFDIE::GetContainingDWOModule () const
+{
+ if (IsValid())
+ {
+ DWARFDIE dwo_module_die = GetContainingDWOModuleDIE();
+
+ if (dwo_module_die)
+ {
+ const char *module_name = dwo_module_die.GetName();
+ if (module_name)
+ return GetDWARF()->GetDWOModule (lldb_private::ConstString(module_name));
+ }
+ }
+ return lldb::ModuleSP();
+}
+
+bool
+DWARFDIE::HasChildren () const
+{
+ if (m_die)
+ return m_die->HasChildren();
+ else
+ return false;
+}
+
+bool
+DWARFDIE::Supports_DW_AT_APPLE_objc_complete_type () const
+{
+ if (IsValid())
+ return GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu);
+ else
+ return false;
+}
+
+size_t
+DWARFDIE::GetAttributes (DWARFAttributes &attributes, uint32_t depth) const
+{
+ if (IsValid())
+ {
+ return m_die->GetAttributes (m_cu,
+ m_cu->GetFixedFormSizes(),
+ attributes,
+ depth);
+ }
+ if (depth == 0)
+ attributes.Clear();
+ return 0;
+}
+
+
+bool
+DWARFDIE::GetDIENamesAndRanges (const char * &name,
+ const char * &mangled,
+ DWARFRangeList& ranges,
+ int& decl_file,
+ int& decl_line,
+ int& decl_column,
+ int& call_file,
+ int& call_line,
+ int& call_column,
+ lldb_private::DWARFExpression *frame_base) const
+{
+ if (IsValid())
+ {
+ return m_die->GetDIENamesAndRanges (GetDWARF(),
+ GetCU(),
+ name,
+ mangled,
+ ranges,
+ decl_file,
+ decl_line,
+ decl_column,
+ call_file,
+ call_line,
+ call_column,
+ frame_base);
+ }
+ else
+ return false;
+}
+
+void
+DWARFDIE::Dump (lldb_private::Stream *s, const uint32_t recurse_depth) const
+{
+ if (s && IsValid())
+ m_die->Dump (GetDWARF(), GetCU(), *s, recurse_depth);
+}
+
+
+bool operator == (const DWARFDIE &lhs, const DWARFDIE &rhs)
+{
+ return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU();
+}
+
+bool operator != (const DWARFDIE &lhs, const DWARFDIE &rhs)
+{
+ return lhs.GetDIE() != rhs.GetDIE() || lhs.GetCU() != rhs.GetCU();
+}
+
+
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
new file mode 100644
index 0000000..db37a45
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -0,0 +1,281 @@
+//===-- DWARFDIE.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDIE_h_
+#define SymbolFileDWARF_DWARFDIE_h_
+
+#include "lldb/lldb-types.h"
+#include "lldb/Core/dwarf.h"
+
+struct DIERef;
+class DWARFASTParser;
+class DWARFAttributes;
+class DWARFCompileUnit;
+class DWARFDebugInfoEntry;
+class DWARFDeclContext;
+class DWARFDIECollection;
+class SymbolFileDWARF;
+
+class DWARFDIE
+{
+public:
+ DWARFDIE () :
+ m_cu (nullptr),
+ m_die (nullptr)
+ {
+ }
+
+ DWARFDIE (DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) :
+ m_cu (cu),
+ m_die (die)
+ {
+ }
+
+ DWARFDIE (const DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) :
+ m_cu (const_cast<DWARFCompileUnit *>(cu)),
+ m_die (die)
+ {
+ }
+
+ DWARFDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) :
+ m_cu (cu),
+ m_die (const_cast<DWARFDebugInfoEntry *>(die))
+ {
+ }
+
+ DWARFDIE (const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) :
+ m_cu (const_cast<DWARFCompileUnit *>(cu)),
+ m_die (const_cast<DWARFDebugInfoEntry *>(die))
+ {
+ }
+
+ //----------------------------------------------------------------------
+ // Tests
+ //----------------------------------------------------------------------
+ operator bool () const
+ {
+ return IsValid();
+ }
+
+ bool
+ IsValid() const
+ {
+ return m_cu && m_die;
+ }
+
+ bool
+ IsStructOrClass () const;
+
+ bool
+ HasChildren () const;
+
+ bool
+ Supports_DW_AT_APPLE_objc_complete_type () const;
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+ SymbolFileDWARF *
+ GetDWARF () const;
+
+ DWARFCompileUnit *
+ GetCU() const
+ {
+ return m_cu;
+ }
+
+ DWARFDebugInfoEntry *
+ GetDIE() const
+ {
+ return m_die;
+ }
+
+ DIERef
+ GetDIERef() const;
+
+ lldb_private::TypeSystem *
+ GetTypeSystem () const;
+
+ DWARFASTParser *
+ GetDWARFParser () const;
+
+ void
+ Set (DWARFCompileUnit *cu, DWARFDebugInfoEntry *die)
+ {
+ if (cu && die)
+ {
+ m_cu = cu;
+ m_die = die;
+ }
+ else
+ {
+ Clear();
+ }
+ }
+
+ void
+ Clear ()
+ {
+ m_cu = nullptr;
+ m_die = nullptr;
+ }
+
+ lldb::ModuleSP
+ GetContainingDWOModule () const;
+
+ DWARFDIE
+ GetContainingDWOModuleDIE () const;
+
+ //----------------------------------------------------------------------
+ // Accessing information about a DIE
+ //----------------------------------------------------------------------
+ dw_tag_t
+ Tag() const;
+
+ const char *
+ GetTagAsCString () const;
+
+ dw_offset_t
+ GetOffset () const;
+
+ dw_offset_t
+ GetCompileUnitRelativeOffset () const;
+
+ //----------------------------------------------------------------------
+ // Get the LLDB user ID for this DIE. This is often just the DIE offset,
+ // but it might have a SymbolFileDWARF::GetID() in the high 32 bits if
+ // we are doing Darwin DWARF in .o file, or DWARF stand alone debug
+ // info.
+ //----------------------------------------------------------------------
+ lldb::user_id_t
+ GetID() const;
+
+ const char *
+ GetName () const;
+
+ const char *
+ GetMangledName () const;
+
+ const char *
+ GetPubname () const;
+
+ const char *
+ GetQualifiedName (std::string &storage) const;
+
+ lldb::LanguageType
+ GetLanguage () const;
+
+ lldb::ModuleSP
+ GetModule () const;
+
+ lldb_private::CompileUnit *
+ GetLLDBCompileUnit () const;
+
+ lldb_private::Type *
+ ResolveType () const;
+
+ // Resolve a type by UID using this DIE's DWARF file
+ lldb_private::Type *
+ ResolveTypeUID (lldb::user_id_t uid) const;
+
+ //----------------------------------------------------------------------
+ // Functions for obtaining DIE relations and references
+ //----------------------------------------------------------------------
+
+ DWARFDIE
+ GetParent () const;
+
+ DWARFDIE
+ GetFirstChild () const;
+
+ DWARFDIE
+ GetSibling () const;
+
+ DWARFDIE
+ GetReferencedDIE (const dw_attr_t attr) const;
+
+ //----------------------------------------------------------------------
+ // Get a another DIE from the same DWARF file as this DIE. This will
+ // check the current DIE's compile unit first to see if "die_offset" is
+ // in the same compile unit, and fall back to checking the DWARF file.
+ //----------------------------------------------------------------------
+ DWARFDIE
+ GetDIE (dw_offset_t die_offset) const;
+
+ DWARFDIE
+ LookupDeepestBlock (lldb::addr_t file_addr) const;
+
+ DWARFDIE
+ GetParentDeclContextDIE () const;
+
+ //----------------------------------------------------------------------
+ // DeclContext related functions
+ //----------------------------------------------------------------------
+ void
+ GetDeclContextDIEs (DWARFDIECollection &decl_context_dies) const;
+
+ void
+ GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const;
+
+ void
+ GetDWOContext (std::vector<lldb_private::CompilerContext> &context) const;
+
+ //----------------------------------------------------------------------
+ // Getting attribute values from the DIE.
+ //
+ // GetAttributeValueAsXXX() functions should only be used if you are
+ // looking for one or two attributes on a DIE. If you are trying to
+ // parse all attributes, use GetAttributes (...) instead
+ //----------------------------------------------------------------------
+ const char *
+ GetAttributeValueAsString (const dw_attr_t attr, const char *fail_value) const;
+
+ uint64_t
+ GetAttributeValueAsUnsigned (const dw_attr_t attr, uint64_t fail_value) const;
+
+ int64_t
+ GetAttributeValueAsSigned (const dw_attr_t attr, int64_t fail_value) const;
+
+ uint64_t
+ GetAttributeValueAsReference (const dw_attr_t attr, uint64_t fail_value) const;
+
+ uint64_t
+ GetAttributeValueAsAddress (const dw_attr_t attr, uint64_t fail_value) const;
+
+ size_t
+ GetAttributes (DWARFAttributes &attributes, uint32_t depth = 0) const;
+
+ bool
+ GetDIENamesAndRanges (const char * &name,
+ const char * &mangled,
+ DWARFRangeList& ranges,
+ int& decl_file,
+ int& decl_line,
+ int& decl_column,
+ int& call_file,
+ int& call_line,
+ int& call_column,
+ lldb_private::DWARFExpression *frame_base) const;
+
+ //----------------------------------------------------------------------
+ // Pretty printing
+ //----------------------------------------------------------------------
+
+ void
+ Dump (lldb_private::Stream *s, const uint32_t recurse_depth) const;
+
+protected:
+ DWARFCompileUnit *m_cu;
+ DWARFDebugInfoEntry *m_die;
+};
+
+bool operator == (const DWARFDIE &lhs, const DWARFDIE &rhs);
+bool operator != (const DWARFDIE &lhs, const DWARFDIE &rhs);
+
+#endif // SymbolFileDWARF_DWARFDIE_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp
index 1beb75d..9e021c7 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp
@@ -13,13 +13,11 @@
#include "lldb/Core/Stream.h"
-#include "DWARFDebugInfoEntry.h"
-
using namespace lldb_private;
using namespace std;
bool
-DWARFDIECollection::Insert(const DWARFDebugInfoEntry *die)
+DWARFDIECollection::Insert(const DWARFDIE &die)
{
iterator end_pos = m_dies.end();
iterator insert_pos = upper_bound(m_dies.begin(), end_pos, die);
@@ -30,17 +28,17 @@ DWARFDIECollection::Insert(const DWARFDebugInfoEntry *die)
}
void
-DWARFDIECollection::Append (const DWARFDebugInfoEntry *die)
+DWARFDIECollection::Append (const DWARFDIE &die)
{
m_dies.push_back (die);
}
-const DWARFDebugInfoEntry *
-DWARFDIECollection::GetDIEPtrAtIndex(uint32_t idx) const
+DWARFDIE
+DWARFDIECollection::GetDIEAtIndex(uint32_t idx) const
{
if (idx < m_dies.size())
return m_dies[idx];
- return NULL;
+ return DWARFDIE();
}
@@ -55,8 +53,6 @@ DWARFDIECollection::Dump(Stream *s, const char* title) const
{
if (title && title[0] != '\0')
s->Printf( "%s\n", title);
- const_iterator end_pos = m_dies.end();
- const_iterator pos;
- for (pos = m_dies.begin(); pos != end_pos; ++pos)
- s->Printf( "0x%8.8x\n", (*pos)->GetOffset());
+ for (const auto &die : m_dies)
+ s->Printf( "0x%8.8x\n", die.GetOffset());
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h
index 173d0a5..e39e1aa 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h
@@ -10,7 +10,7 @@
#ifndef SymbolFileDWARF_DWARFDIECollection_h_
#define SymbolFileDWARF_DWARFDIECollection_h_
-#include "SymbolFileDWARF.h"
+#include "DWARFDIE.h"
#include <vector>
class DWARFDIECollection
@@ -25,22 +25,22 @@ public:
}
void
- Append (const DWARFDebugInfoEntry *die);
+ Append (const DWARFDIE &die);
void
Dump(lldb_private::Stream *s, const char* title) const;
- const DWARFDebugInfoEntry*
- GetDIEPtrAtIndex(uint32_t idx) const;
+ DWARFDIE
+ GetDIEAtIndex (uint32_t idx) const;
bool
- Insert(const DWARFDebugInfoEntry *die);
+ Insert(const DWARFDIE &die);
size_t
Size() const;
protected:
- typedef std::vector<const DWARFDebugInfoEntry *> collection;
+ typedef std::vector<DWARFDIE> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
index ba2e8ad..0281b5a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
@@ -19,10 +19,10 @@ namespace lldb_private {
class DWARFDataExtractor : public lldb_private::DataExtractor
{
public:
- DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) { };
+ DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) { }
DWARFDataExtractor (const DWARFDataExtractor& data, lldb::offset_t offset, lldb::offset_t length) :
- DataExtractor(data, offset, length), m_is_dwarf64(false) { };
+ DataExtractor(data, offset, length), m_is_dwarf64(false) { }
uint64_t
GetDWARFInitialLength(lldb::offset_t *offset_ptr) const;
@@ -43,4 +43,3 @@ protected:
}
#endif // liblldb_DWARFDataExtractor_h_
-
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 39343480..a1b00d1 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -103,57 +103,6 @@ DWARFDebugInfo::GetCompileUnitAranges ()
return *m_cu_aranges_ap.get();
}
-
-//----------------------------------------------------------------------
-// LookupAddress
-//----------------------------------------------------------------------
-bool
-DWARFDebugInfo::LookupAddress
-(
- const dw_addr_t address,
- const dw_offset_t hint_die_offset,
- DWARFCompileUnitSP& cu_sp,
- DWARFDebugInfoEntry** function_die,
- DWARFDebugInfoEntry** block_die
-)
-{
-
- if (hint_die_offset != DW_INVALID_OFFSET)
- cu_sp = GetCompileUnit(hint_die_offset);
- else
- {
- DWARFDebugAranges &cu_aranges = GetCompileUnitAranges ();
- const dw_offset_t cu_offset = cu_aranges.FindAddress (address);
- cu_sp = GetCompileUnit(cu_offset);
- }
-
- if (cu_sp.get())
- {
- if (cu_sp->LookupAddress(address, function_die, block_die))
- return true;
- cu_sp.reset();
- }
- else
- {
- // The hint_die_offset may have been a pointer to the actual item that
- // we are looking for
- DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp);
- if (die_ptr)
- {
- if (cu_sp.get())
- {
- if (function_die || block_die)
- return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die);
-
- // We only wanted the compile unit that contained this address
- return true;
- }
- }
- }
- return false;
-}
-
-
void
DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded()
{
@@ -213,19 +162,13 @@ DWARFDebugInfo::ContainsCompileUnit (const DWARFCompileUnit *cu) const
return false;
}
-static int
-CompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem)
+bool
+DWARFDebugInfo::OffsetLessThanCompileUnitOffset (dw_offset_t offset, const DWARFCompileUnitSP& cu_sp)
{
- const dw_offset_t key_cu_offset = *(dw_offset_t*) key;
- const dw_offset_t cu_offset = ((DWARFCompileUnitSP *)arrmem)->get()->GetOffset();
- if (key_cu_offset < cu_offset)
- return -1;
- if (key_cu_offset > cu_offset)
- return 1;
- return 0;
+ return offset < cu_sp->GetOffset();
}
-DWARFCompileUnitSP
+DWARFCompileUnit *
DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr)
{
DWARFCompileUnitSP cu_sp;
@@ -234,41 +177,80 @@ DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr)
{
ParseCompileUnitHeadersIfNeeded();
- DWARFCompileUnitSP* match = (DWARFCompileUnitSP*)bsearch(&cu_offset, &m_compile_units[0], m_compile_units.size(), sizeof(DWARFCompileUnitSP), CompareDWARFCompileUnitSPOffset);
- if (match)
+ // Watch out for single compile unit executable as they are pretty common
+ const size_t num_cus = m_compile_units.size();
+ if (num_cus == 1)
{
- cu_sp = *match;
- cu_idx = match - &m_compile_units[0];
+ if (m_compile_units[0]->GetOffset() == cu_offset)
+ {
+ cu_sp = m_compile_units[0];
+ cu_idx = 0;
+ }
+ }
+ else if (num_cus)
+ {
+ CompileUnitColl::const_iterator end_pos = m_compile_units.end();
+ CompileUnitColl::const_iterator begin_pos = m_compile_units.begin();
+ CompileUnitColl::const_iterator pos = std::upper_bound(begin_pos, end_pos, cu_offset, OffsetLessThanCompileUnitOffset);
+ if (pos != begin_pos)
+ {
+ --pos;
+ if ((*pos)->GetOffset() == cu_offset)
+ {
+ cu_sp = *pos;
+ cu_idx = std::distance(begin_pos, pos);
+ }
+ }
}
}
if (idx_ptr)
*idx_ptr = cu_idx;
- return cu_sp;
+ return cu_sp.get();
}
-DWARFCompileUnitSP
-DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset)
+DWARFCompileUnit *
+DWARFDebugInfo::GetCompileUnitContainingDIE (const DIERef& die_ref)
{
+ dw_offset_t search_offset = die_ref.die_offset;
+ bool is_cu_offset = false;
+ if (m_dwarf2Data->GetID() == 0 && die_ref.cu_offset != DW_INVALID_OFFSET)
+ {
+ is_cu_offset = true;
+ search_offset = die_ref.cu_offset;
+ }
+
DWARFCompileUnitSP cu_sp;
- if (die_offset != DW_INVALID_OFFSET)
+ if (search_offset != DW_INVALID_OFFSET)
{
ParseCompileUnitHeadersIfNeeded();
- CompileUnitColl::const_iterator end_pos = m_compile_units.end();
- CompileUnitColl::const_iterator pos;
-
- for (pos = m_compile_units.begin(); pos != end_pos; ++pos)
+ // Watch out for single compile unit executable as they are pretty common
+ const size_t num_cus = m_compile_units.size();
+ if (num_cus == 1)
{
- dw_offset_t cu_start_offset = (*pos)->GetOffset();
- dw_offset_t cu_end_offset = (*pos)->GetNextCompileUnitOffset();
- if (cu_start_offset <= die_offset && die_offset < cu_end_offset)
+ if ((is_cu_offset && m_compile_units[0]->GetOffset() == search_offset) ||
+ (!is_cu_offset && m_compile_units[0]->ContainsDIEOffset(search_offset)))
{
- cu_sp = *pos;
- break;
+ cu_sp = m_compile_units[0];
+ }
+ }
+ else if (num_cus)
+ {
+ CompileUnitColl::const_iterator end_pos = m_compile_units.end();
+ CompileUnitColl::const_iterator begin_pos = m_compile_units.begin();
+ CompileUnitColl::const_iterator pos = std::upper_bound(begin_pos, end_pos, search_offset, OffsetLessThanCompileUnitOffset);
+ if (pos != begin_pos)
+ {
+ --pos;
+ if ((is_cu_offset && (*pos)->GetOffset() == search_offset) ||
+ (!is_cu_offset && (*pos)->ContainsDIEOffset(search_offset)))
+ {
+ cu_sp = *pos;
+ }
}
}
}
- return cu_sp;
+ return cu_sp.get();
}
//----------------------------------------------------------------------
@@ -276,73 +258,15 @@ DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset)
//
// Get the DIE (Debug Information Entry) with the specified offset.
//----------------------------------------------------------------------
-DWARFDebugInfoEntry*
-DWARFDebugInfo::GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
-{
- DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
- if (cu_sp_ptr)
- *cu_sp_ptr = cu_sp;
- if (cu_sp.get())
- return cu_sp->GetDIEPtr(die_offset);
- return NULL; // Not found in any compile units
-}
-
-DWARFDebugInfoEntry*
-DWARFDebugInfo::GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle)
-{
- assert (cu_handle);
- DWARFDebugInfoEntry* die = NULL;
- if (*cu_handle)
- die = (*cu_handle)->GetDIEPtr(die_offset);
-
- if (die == NULL)
- {
- DWARFCompileUnitSP cu_sp (GetCompileUnitContainingDIE(die_offset));
- if (cu_sp.get())
- {
- *cu_handle = cu_sp.get();
- die = cu_sp->GetDIEPtr(die_offset);
- }
- }
- if (die == NULL)
- *cu_handle = NULL;
- return die;
-}
-
-
-const DWARFDebugInfoEntry*
-DWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
-{
- DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
- if (cu_sp_ptr)
- *cu_sp_ptr = cu_sp;
- if (cu_sp.get())
- return cu_sp->GetDIEPtrContainingOffset(die_offset);
-
- return NULL; // Not found in any compile units
-
-}
-
-//----------------------------------------------------------------------
-// AddCompileUnit
-//----------------------------------------------------------------------
-void
-DWARFDebugInfo::AddCompileUnit(DWARFCompileUnitSP& cu)
+DWARFDIE
+DWARFDebugInfo::GetDIE(const DIERef& die_ref)
{
- m_compile_units.push_back(cu);
+ DWARFCompileUnit *cu = GetCompileUnitContainingDIE(die_ref);
+ if (cu)
+ return cu->GetDIE (die_ref.die_offset);
+ return DWARFDIE(); // Not found
}
-/*
-void
-DWARFDebugInfo::AddDIE(DWARFDebugInfoEntry& die)
-{
- m_die_array.push_back(die);
-}
-*/
-
-
-
-
//----------------------------------------------------------------------
// Parse
//
@@ -372,7 +296,7 @@ DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* user
depth = 0;
// Call the callback function with no DIE pointer for the compile unit
// and get the offset that we are to continue to parse from
- offset = callback(dwarf2Data, cu, NULL, offset, depth, userData);
+ offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData);
// Make sure we are within our compile unit
if (offset < next_cu_offset)
@@ -383,7 +307,7 @@ DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* user
while (!done && die.Extract(dwarf2Data, cu.get(), &offset))
{
// Call the callback function with DIE pointer that falls within the compile unit
- offset = callback(dwarf2Data, cu, &die, offset, depth, userData);
+ offset = callback(dwarf2Data, cu.get(), &die, offset, depth, userData);
if (die.IsNULL())
{
@@ -450,7 +374,7 @@ typedef struct DumpInfo
static dw_offset_t DumpCallback
(
SymbolFileDWARF* dwarf2Data,
- DWARFCompileUnitSP& cu_sp,
+ DWARFCompileUnit* cu,
DWARFDebugInfoEntry* die,
const dw_offset_t next_offset,
const uint32_t curr_depth,
@@ -458,9 +382,6 @@ static dw_offset_t DumpCallback
)
{
DumpInfo* dumpInfo = (DumpInfo*)userData;
-
- const DWARFCompileUnit* cu = cu_sp.get();
-
Stream *s = dumpInfo->strm;
bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors);
@@ -676,12 +597,12 @@ DWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recur
ParseCompileUnitHeadersIfNeeded();
for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos)
{
- const DWARFCompileUnitSP& cu_sp = *pos;
- DumpCallback(m_dwarf2Data, (DWARFCompileUnitSP&)cu_sp, NULL, 0, curr_depth, &dumpInfo);
+ DWARFCompileUnit *cu = pos->get();
+ DumpCallback(m_dwarf2Data, cu, NULL, 0, curr_depth, &dumpInfo);
- const DWARFDebugInfoEntry* die = cu_sp->DIE();
+ const DWARFDIE die = cu->DIE();
if (die)
- die->Dump(m_dwarf2Data, cu_sp.get(), *s, recurse_depth);
+ die.Dump(s, recurse_depth);
}
}
@@ -707,7 +628,7 @@ typedef struct FindCallbackStringInfoTag
static dw_offset_t FindCallbackString
(
SymbolFileDWARF* dwarf2Data,
- DWARFCompileUnitSP& cu_sp,
+ DWARFCompileUnit* cu,
DWARFDebugInfoEntry* die,
const dw_offset_t next_offset,
const uint32_t curr_depth,
@@ -715,7 +636,6 @@ static dw_offset_t FindCallbackString
)
{
FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData;
- const DWARFCompileUnit* cu = cu_sp.get();
if (die)
{
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
index 50a7ae7..ea2e204 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -16,19 +16,18 @@
#include "lldb/lldb-private.h"
#include "lldb/lldb-private.h"
#include "SymbolFileDWARF.h"
+#include "DWARFDIE.h"
typedef std::multimap<const char*, dw_offset_t, CStringCompareFunctionObject> CStringToDIEMap;
typedef CStringToDIEMap::iterator CStringToDIEMapIter;
typedef CStringToDIEMap::const_iterator CStringToDIEMapConstIter;
-typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP;
-
class DWARFDebugInfo
{
public:
typedef dw_offset_t (*Callback)(
SymbolFileDWARF* dwarf2Data,
- DWARFCompileUnitSP& cu_shared_ptr,
+ DWARFCompileUnit* cu,
DWARFDebugInfoEntry* die,
const dw_offset_t next_offset,
const uint32_t depth,
@@ -37,24 +36,13 @@ public:
DWARFDebugInfo();
void SetDwarfData(SymbolFileDWARF* dwarf2Data);
- bool LookupAddress(
- const dw_addr_t address,
- const dw_offset_t cu_offset, // Can be valid (find in .debug_aranges), or DW_INVALID_OFFSET if we need to search manually
- DWARFCompileUnitSP& cu_shared_ptr,
- DWARFDebugInfoEntry** function_die,
- DWARFDebugInfoEntry** block_die);
-
- void AddCompileUnit(DWARFCompileUnitSP& cu);
size_t GetNumCompileUnits();
bool ContainsCompileUnit (const DWARFCompileUnit *cu) const;
- DWARFCompileUnit* GetCompileUnitAtIndex(uint32_t idx);
- DWARFCompileUnitSP GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr = NULL);
- DWARFCompileUnitSP GetCompileUnitContainingDIE(dw_offset_t die_offset);
+ DWARFCompileUnit* GetCompileUnitAtIndex (uint32_t idx);
+ DWARFCompileUnit* GetCompileUnit (dw_offset_t cu_offset, uint32_t* idx_ptr = NULL);
+ DWARFCompileUnit* GetCompileUnitContainingDIE (const DIERef& die_ref);
- DWARFDebugInfoEntry* GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr);
- DWARFDebugInfoEntry* GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle);
-
- const DWARFDebugInfoEntry* GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr);
+ DWARFDIE GetDIE (const DIERef& die_ref);
void Dump(lldb_private::Stream *s, const uint32_t die_offset, const uint32_t recurse_depth);
static void Parse(SymbolFileDWARF* parser, Callback callback, void* userData);
@@ -74,8 +62,17 @@ public:
GetCompileUnitAranges ();
protected:
- SymbolFileDWARF* m_dwarf2Data;
+ typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP;
+
+ static bool
+ OffsetLessThanCompileUnitOffset (dw_offset_t offset, const DWARFCompileUnitSP& cu_sp);
+
typedef std::vector<DWARFCompileUnitSP> CompileUnitColl;
+
+ //----------------------------------------------------------------------
+ // Member variables
+ //----------------------------------------------------------------------
+ SymbolFileDWARF* m_dwarf2Data;
CompileUnitColl m_compile_units;
std::unique_ptr<DWARFDebugAranges> m_cu_aranges_ap; // A quick address to compile unit table
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 0ad1f1a..b9d8254 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -19,107 +19,26 @@
#include "lldb/Symbol/ObjectFile.h"
#include "DWARFCompileUnit.h"
-#include "SymbolFileDWARF.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
#include "DWARFDebugInfo.h"
#include "DWARFDeclContext.h"
#include "DWARFDIECollection.h"
#include "DWARFFormValue.h"
-#include "DWARFLocationDescription.h"
-#include "DWARFLocationList.h"
#include "DWARFDebugRanges.h"
+#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDwo.h"
using namespace lldb_private;
using namespace std;
extern int g_verbose;
-
-
-DWARFDebugInfoEntry::Attributes::Attributes() :
- m_infos()
-{
-}
-
-DWARFDebugInfoEntry::Attributes::~Attributes()
-{
-}
-
-
-uint32_t
-DWARFDebugInfoEntry::Attributes::FindAttributeIndex(dw_attr_t attr) const
-{
- collection::const_iterator end = m_infos.end();
- collection::const_iterator beg = m_infos.begin();
- collection::const_iterator pos;
- for (pos = beg; pos != end; ++pos)
- {
- if (pos->attr == attr)
- return std::distance(beg, pos);
- }
- return UINT32_MAX;
-}
-
-void
-DWARFDebugInfoEntry::Attributes::Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form)
-{
- Info info = { cu, attr_die_offset, attr, form };
- m_infos.push_back(info);
-}
-
-bool
-DWARFDebugInfoEntry::Attributes::ContainsAttribute(dw_attr_t attr) const
-{
- return FindAttributeIndex(attr) != UINT32_MAX;
-}
-
-bool
-DWARFDebugInfoEntry::Attributes::RemoveAttribute(dw_attr_t attr)
-{
- uint32_t attr_index = FindAttributeIndex(attr);
- if (attr_index != UINT32_MAX)
- {
- m_infos.erase(m_infos.begin() + attr_index);
- return true;
- }
- return false;
-}
-
-bool
-DWARFDebugInfoEntry::Attributes::ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const
-{
- form_value.SetCompileUnit(CompileUnitAtIndex(i));
- form_value.SetForm(FormAtIndex(i));
- lldb::offset_t offset = DIEOffsetAtIndex(i);
- return form_value.ExtractValue(dwarf2Data->get_debug_info_data(), &offset);
-}
-
-uint64_t
-DWARFDebugInfoEntry::Attributes::FormValueAsUnsigned (SymbolFileDWARF* dwarf2Data, dw_attr_t attr, uint64_t fail_value) const
-{
- const uint32_t attr_idx = FindAttributeIndex (attr);
- if (attr_idx != UINT32_MAX)
- return FormValueAsUnsignedAtIndex (dwarf2Data, attr_idx, fail_value);
- return fail_value;
-}
-
-uint64_t
-DWARFDebugInfoEntry::Attributes::FormValueAsUnsignedAtIndex(SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const
-{
- DWARFFormValue form_value;
- if (ExtractFormValueAtIndex(dwarf2Data, i, form_value))
- return form_value.Reference();
- return fail_value;
-}
-
-
-
bool
DWARFDebugInfoEntry::FastExtract
(
const DWARFDataExtractor& debug_info_data,
const DWARFCompileUnit* cu,
- const uint8_t *fixed_form_sizes,
+ const DWARFFormValue::FixedFormSizes& fixed_form_sizes,
lldb::offset_t *offset_ptr
)
{
@@ -158,7 +77,7 @@ DWARFDebugInfoEntry::FastExtract
{
form = abbrevDecl->GetFormByIndexUnchecked(i);
- const uint8_t fixed_skip_size = fixed_form_sizes [form];
+ const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form);
if (fixed_skip_size)
offset += fixed_skip_size;
else
@@ -226,9 +145,11 @@ DWARFDebugInfoEntry::FastExtract
break;
// signed or unsigned LEB 128 values
- case DW_FORM_sdata :
- case DW_FORM_udata :
- case DW_FORM_ref_udata :
+ case DW_FORM_sdata :
+ case DW_FORM_udata :
+ case DW_FORM_ref_udata :
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index :
debug_info_data.Skip_LEB128 (&offset);
break;
@@ -306,7 +227,7 @@ DWARFDebugInfoEntry::Extract
bool isCompileUnitTag = m_tag == DW_TAG_compile_unit;
if (cu && isCompileUnitTag)
- ((DWARFCompileUnit*)cu)->SetBaseAddress(0);
+ const_cast<DWARFCompileUnit *>(cu)->SetBaseAddress(0);
// Skip all data in the .debug_info for the attributes
const uint32_t numAttributes = abbrevDecl->NumAttributes();
@@ -323,7 +244,7 @@ DWARFDebugInfoEntry::Extract
if (form_value.ExtractValue(debug_info_data, &offset))
{
if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
- ((DWARFCompileUnit*)cu)->SetBaseAddress(form_value.Unsigned());
+ const_cast<DWARFCompileUnit*>(cu)->SetBaseAddress(form_value.Address());
}
}
else
@@ -389,9 +310,11 @@ DWARFDebugInfoEntry::Extract
break;
// signed or unsigned LEB 128 values
- case DW_FORM_sdata :
- case DW_FORM_udata :
- case DW_FORM_ref_udata :
+ case DW_FORM_sdata :
+ case DW_FORM_udata :
+ case DW_FORM_ref_udata :
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index :
debug_info_data.Skip_LEB128(&offset);
break;
@@ -456,276 +379,6 @@ DWARFDebugInfoEntry::DumpAncestry
}
//----------------------------------------------------------------------
-// Compare two DIE by comparing all their attributes values, and
-// following all DW_FORM_ref attributes and comparing their contents as
-// well (except for DW_AT_sibling attributes.
-//
-// DWARFDebugInfoEntry::CompareState compare_state;
-// int result = DWARFDebugInfoEntry::Compare(this, 0x00017ccb, 0x0001eb2b, compare_state, false, true);
-//----------------------------------------------------------------------
-//int
-//DWARFDebugInfoEntry::Compare
-//(
-// SymbolFileDWARF* dwarf2Data,
-// dw_offset_t a_die_offset,
-// dw_offset_t b_die_offset,
-// CompareState &compare_state,
-// bool compare_siblings,
-// bool compare_children
-//)
-//{
-// if (a_die_offset == b_die_offset)
-// return 0;
-//
-// DWARFCompileUnitSP a_cu_sp;
-// DWARFCompileUnitSP b_cu_sp;
-// const DWARFDebugInfoEntry* a_die = dwarf2Data->DebugInfo()->GetDIEPtr(a_die_offset, &a_cu_sp);
-// const DWARFDebugInfoEntry* b_die = dwarf2Data->DebugInfo()->GetDIEPtr(b_die_offset, &b_cu_sp);
-//
-// return Compare(dwarf2Data, a_cu_sp.get(), a_die, b_cu_sp.get(), b_die, compare_state, compare_siblings, compare_children);
-//}
-//
-//int
-//DWARFDebugInfoEntry::Compare
-//(
-// SymbolFileDWARF* dwarf2Data,
-// DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die,
-// DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die,
-// CompareState &compare_state,
-// bool compare_siblings,
-// bool compare_children
-//)
-//{
-// if (a_die == b_die)
-// return 0;
-//
-// if (!compare_state.AddTypePair(a_die->GetOffset(), b_die->GetOffset()))
-// {
-// // We are already comparing both of these types, so let
-// // compares complete for the real result
-// return 0;
-// }
-//
-// //printf("DWARFDebugInfoEntry::Compare(0x%8.8x, 0x%8.8x)\n", a_die->GetOffset(), b_die->GetOffset());
-//
-// // Do we have two valid DIEs?
-// if (a_die && b_die)
-// {
-// // Both DIE are valid
-// int result = 0;
-//
-// const dw_tag_t a_tag = a_die->Tag();
-// const dw_tag_t b_tag = b_die->Tag();
-// if (a_tag == 0 && b_tag == 0)
-// return 0;
-//
-// //printf(" comparing tags: %s and %s\n", DW_TAG_value_to_name(a_tag), DW_TAG_value_to_name(b_tag));
-//
-// if (a_tag < b_tag)
-// return -1;
-// else if (a_tag > b_tag)
-// return 1;
-//
-// DWARFDebugInfoEntry::Attributes a_attrs;
-// DWARFDebugInfoEntry::Attributes b_attrs;
-// size_t a_attr_count = a_die->GetAttributes(dwarf2Data, a_cu, a_attrs);
-// size_t b_attr_count = b_die->GetAttributes(dwarf2Data, b_cu, b_attrs);
-// if (a_attr_count != b_attr_count)
-// {
-// a_attrs.RemoveAttribute(DW_AT_sibling);
-// b_attrs.RemoveAttribute(DW_AT_sibling);
-// }
-//
-// a_attr_count = a_attrs.Size();
-// b_attr_count = b_attrs.Size();
-//
-// DWARFFormValue a_form_value;
-// DWARFFormValue b_form_value;
-//
-// if (a_attr_count != b_attr_count)
-// {
-// uint32_t is_decl_index = a_attrs.FindAttributeIndex(DW_AT_declaration);
-// uint32_t a_name_index = UINT32_MAX;
-// uint32_t b_name_index = UINT32_MAX;
-// if (is_decl_index != UINT32_MAX)
-// {
-// if (a_attr_count == 2)
-// {
-// a_name_index = a_attrs.FindAttributeIndex(DW_AT_name);
-// b_name_index = b_attrs.FindAttributeIndex(DW_AT_name);
-// }
-// }
-// else
-// {
-// is_decl_index = b_attrs.FindAttributeIndex(DW_AT_declaration);
-// if (is_decl_index != UINT32_MAX && a_attr_count == 2)
-// {
-// a_name_index = a_attrs.FindAttributeIndex(DW_AT_name);
-// b_name_index = b_attrs.FindAttributeIndex(DW_AT_name);
-// }
-// }
-// if (a_name_index != UINT32_MAX && b_name_index != UINT32_MAX)
-// {
-// if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, a_name_index, a_form_value) &&
-// b_attrs.ExtractFormValueAtIndex(dwarf2Data, b_name_index, b_form_value))
-// {
-// result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, &dwarf2Data->get_debug_str_data());
-// if (result == 0)
-// {
-// a_attr_count = b_attr_count = 0;
-// compare_children = false;
-// }
-// }
-// }
-// }
-//
-// if (a_attr_count < b_attr_count)
-// return -1;
-// if (a_attr_count > b_attr_count)
-// return 1;
-//
-//
-// // The number of attributes are the same...
-// if (a_attr_count > 0)
-// {
-// const DWARFDataExtractor* debug_str_data_ptr = &dwarf2Data->get_debug_str_data();
-//
-// uint32_t i;
-// for (i=0; i<a_attr_count; ++i)
-// {
-// const dw_attr_t a_attr = a_attrs.AttributeAtIndex(i);
-// const dw_attr_t b_attr = b_attrs.AttributeAtIndex(i);
-// //printf(" comparing attributes\n\t\t0x%8.8x: %s %s\t\t0x%8.8x: %s %s\n",
-// // a_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(a_attrs.FormAtIndex(i)), DW_AT_value_to_name(a_attr),
-// // b_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(b_attrs.FormAtIndex(i)), DW_AT_value_to_name(b_attr));
-//
-// if (a_attr < b_attr)
-// return -1;
-// else if (a_attr > b_attr)
-// return 1;
-//
-// switch (a_attr)
-// {
-// // Since we call a form of GetAttributes which inlines the
-// // attributes from DW_AT_abstract_origin and DW_AT_specification
-// // we don't care if their values mismatch...
-// case DW_AT_abstract_origin:
-// case DW_AT_specification:
-// case DW_AT_sibling:
-// case DW_AT_containing_type:
-// //printf(" action = IGNORE\n");
-// result = 0;
-// break; // ignore
-//
-// default:
-// if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, i, a_form_value) &&
-// b_attrs.ExtractFormValueAtIndex(dwarf2Data, i, b_form_value))
-// result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, debug_str_data_ptr);
-// break;
-// }
-//
-// //printf("\t result = %i\n", result);
-//
-// if (result != 0)
-// {
-// // Attributes weren't equal, lets see if we care?
-// switch (a_attr)
-// {
-// case DW_AT_decl_file:
-// // TODO: add the ability to compare files in two different compile units
-// if (a_cu == b_cu)
-// {
-// //printf(" action = RETURN RESULT\n");
-// return result; // Only return the compare results when the compile units are the same and the decl_file attributes can be compared
-// }
-// else
-// {
-// result = 0;
-// //printf(" action = IGNORE\n");
-// }
-// break;
-//
-// default:
-// switch (a_attrs.FormAtIndex(i))
-// {
-// case DW_FORM_ref1:
-// case DW_FORM_ref2:
-// case DW_FORM_ref4:
-// case DW_FORM_ref8:
-// case DW_FORM_ref_udata:
-// case DW_FORM_ref_addr:
-// //printf(" action = COMPARE DIEs 0x%8.8x 0x%8.8x\n", (dw_offset_t)a_form_value.Reference(a_cu), (dw_offset_t)b_form_value.Reference(b_cu));
-// // These attribute values refer to other DIEs, so lets compare those instead of their DIE offsets...
-// result = Compare(dwarf2Data, a_form_value.Reference(a_cu), b_form_value.Reference(b_cu), compare_state, false, true);
-// if (result != 0)
-// return result;
-// break;
-//
-// default:
-// // We do care that they were different, return this result...
-// //printf(" action = RETURN RESULT\n");
-// return result;
-// }
-// }
-// }
-// }
-// }
-// //printf(" SUCCESS\n\t\t0x%8.8x: %s\n\t\t0x%8.8x: %s\n", a_die->GetOffset(), DW_TAG_value_to_name(a_tag), b_die->GetOffset(), DW_TAG_value_to_name(b_tag));
-//
-// if (compare_children)
-// {
-// bool a_has_children = a_die->HasChildren();
-// bool b_has_children = b_die->HasChildren();
-// if (a_has_children == b_has_children)
-// {
-// // Both either have kids or don't
-// if (a_has_children)
-// result = Compare( dwarf2Data,
-// a_cu, a_die->GetFirstChild(),
-// b_cu, b_die->GetFirstChild(),
-// compare_state, true, compare_children);
-// else
-// result = 0;
-// }
-// else if (!a_has_children)
-// result = -1; // A doesn't have kids, but B does
-// else
-// result = 1; // A has kids, but B doesn't
-// }
-//
-// if (compare_siblings)
-// {
-// result = Compare( dwarf2Data,
-// a_cu, a_die->GetSibling(),
-// b_cu, b_die->GetSibling(),
-// compare_state, true, compare_children);
-// }
-//
-// return result;
-// }
-//
-// if (a_die == NULL)
-// return -1; // a_die is NULL, yet b_die is non-NULL
-// else
-// return 1; // a_die is non-NULL, yet b_die is NULL
-//
-//}
-//
-//
-//int
-//DWARFDebugInfoEntry::Compare
-//(
-// SymbolFileDWARF* dwarf2Data,
-// const DWARFCompileUnit* cu_a,
-// const DWARFDebugInfoEntry* die_a,
-// const DWARFCompileUnit* cu_a,
-// const DWARFDebugInfoEntry* die_b,
-// CompareState &compare_state
-//)
-//{
-//}
-
-//----------------------------------------------------------------------
// GetDIENamesAndRanges
//
// Gets the valid address ranges for a given DIE by looking for a
@@ -739,7 +392,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
const DWARFCompileUnit* cu,
const char * &name,
const char * &mangled,
- DWARFDebugRanges::RangeList& ranges,
+ DWARFRangeList& ranges,
int& decl_file,
int& decl_line,
int& decl_column,
@@ -749,12 +402,27 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
DWARFExpression *frame_base
) const
{
- if (dwarf2Data == NULL)
+ if (dwarf2Data == nullptr)
return false;
+ SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile();
+ if (dwo_symbol_file)
+ return GetDIENamesAndRanges(dwo_symbol_file,
+ dwo_symbol_file->GetCompileUnit(),
+ name,
+ mangled,
+ ranges,
+ decl_file,
+ decl_line,
+ decl_column,
+ call_file,
+ call_line,
+ call_column,
+ frame_base);
+
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
- std::vector<dw_offset_t> die_offsets;
+ std::vector<DIERef> die_refs;
bool set_frame_base_loclist_addr = false;
lldb::offset_t offset;
@@ -784,7 +452,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
switch (attr)
{
case DW_AT_low_pc:
- lo_pc = form_value.Unsigned();
+ lo_pc = form_value.Address();
if (do_offset)
hi_pc += lo_pc;
@@ -792,13 +460,18 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
break;
case DW_AT_entry_pc:
- lo_pc = form_value.Unsigned();
+ lo_pc = form_value.Address();
break;
case DW_AT_high_pc:
- hi_pc = form_value.Unsigned();
- if (form_value.Form() != DW_FORM_addr)
+ if (form_value.Form() == DW_FORM_addr ||
+ form_value.Form() == DW_FORM_GNU_addr_index)
{
+ hi_pc = form_value.Address();
+ }
+ else
+ {
+ hi_pc = form_value.Unsigned();
if (lo_pc == LLDB_INVALID_ADDRESS)
do_offset = hi_pc != LLDB_INVALID_ADDRESS;
else
@@ -819,21 +492,21 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
case DW_AT_name:
if (name == NULL)
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+ name = form_value.AsCString();
break;
case DW_AT_MIPS_linkage_name:
case DW_AT_linkage_name:
if (mangled == NULL)
- mangled = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+ mangled = form_value.AsCString();
break;
case DW_AT_abstract_origin:
- die_offsets.push_back(form_value.Reference());
+ die_refs.emplace_back(form_value);
break;
case DW_AT_specification:
- die_offsets.push_back(form_value.Reference());
+ die_refs.emplace_back(form_value);
break;
case DW_AT_decl_file:
@@ -880,7 +553,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
const DWARFDataExtractor &debug_loc_data = dwarf2Data->get_debug_loc_data();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
- size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
+ size_t loc_list_length = DWARFExpression::LocationListSize(cu, debug_loc_data, debug_loc_offset);
if (loc_list_length > 0)
{
frame_base->SetOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length);
@@ -910,9 +583,9 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
if (lo_pc != LLDB_INVALID_ADDRESS)
{
if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc)
- ranges.Append(DWARFDebugRanges::Range (lo_pc, hi_pc - lo_pc));
+ ranges.Append(DWARFRangeList::Entry (lo_pc, hi_pc - lo_pc));
else
- ranges.Append(DWARFDebugRanges::Range (lo_pc, 0));
+ ranges.Append(DWARFRangeList::Entry (lo_pc, 0));
}
}
@@ -925,18 +598,13 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
if (ranges.IsEmpty() || name == NULL || mangled == NULL)
{
- std::vector<dw_offset_t>::const_iterator pos;
- std::vector<dw_offset_t>::const_iterator end = die_offsets.end();
- for (pos = die_offsets.begin(); pos != end; ++pos)
+ for (const DIERef& die_ref : die_refs)
{
- DWARFCompileUnitSP cu_sp_ptr;
- const DWARFDebugInfoEntry* die = NULL;
- dw_offset_t die_offset = *pos;
- if (die_offset != DW_INVALID_OFFSET)
+ if (die_ref.die_offset != DW_INVALID_OFFSET)
{
- die = dwarf2Data->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
+ DWARFDIE die = dwarf2Data->DebugInfo()->GetDIE(die_ref);
if (die)
- die->GetDIENamesAndRanges(dwarf2Data, cu_sp_ptr.get(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column);
+ die.GetDIE()->GetDIENamesAndRanges(die.GetDWARF(), die.GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column);
}
}
}
@@ -1023,10 +691,10 @@ DWARFDebugInfoEntry::DumpLocation
Stream &s
) const
{
- const DWARFDebugInfoEntry *cu_die = cu->GetCompileUnitDIEOnly();
+ const DWARFDIE cu_die = cu->GetCompileUnitDIEOnly();
const char *cu_name = NULL;
- if (cu_die != NULL)
- cu_name = cu_die->GetName (dwarf2Data, cu);
+ if (cu_die)
+ cu_name = cu_die.GetName ();
const char *obj_file_name = NULL;
ObjectFile *obj_file = dwarf2Data->GetObjectFile();
if (obj_file)
@@ -1062,7 +730,6 @@ DWARFDebugInfoEntry::DumpAttribute
bool verbose = s.GetVerbose();
bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm);
- const DWARFDataExtractor* debug_str_data = dwarf2Data ? &dwarf2Data->get_debug_str_data() : NULL;
if (verbose)
s.Offset (*offset_ptr);
else
@@ -1094,7 +761,7 @@ DWARFDebugInfoEntry::DumpAttribute
// Always dump form value if verbose is enabled
if (verbose)
{
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
}
@@ -1127,12 +794,16 @@ DWARFDebugInfoEntry::DumpAttribute
if (blockData)
{
if (!verbose)
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
// Location description is inlined in data in the form value
DWARFDataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned());
if ( verbose ) s.PutCString(" ( ");
- print_dwarf_expression (s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false);
+ DWARFExpression::PrintDWARFExpression(s,
+ locationData,
+ DWARFCompileUnit::GetAddressByteSize(cu),
+ 4,
+ false);
if ( verbose ) s.PutCString(" )");
}
else
@@ -1144,13 +815,16 @@ DWARFDebugInfoEntry::DumpAttribute
if (dwarf2Data)
{
if ( !verbose )
- form_value.Dump(s, debug_str_data);
- DWARFLocationList::Dump(s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset);
+ form_value.Dump(s);
+ DWARFExpression::PrintDWARFLocationList(s,
+ cu,
+ dwarf2Data->get_debug_loc_data(),
+ debug_loc_offset);
}
else
{
if ( !verbose )
- form_value.Dump(s, NULL);
+ form_value.Dump(s);
}
}
}
@@ -1160,7 +834,7 @@ DWARFDebugInfoEntry::DumpAttribute
case DW_AT_specification:
{
uint64_t abstract_die_offset = form_value.Reference();
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
// *ostrm_ptr << HEX32 << abstract_die_offset << " ( ";
if ( verbose ) s.PutCString(" ( ");
GetName(dwarf2Data, cu, abstract_die_offset, s);
@@ -1172,7 +846,7 @@ DWARFDebugInfoEntry::DumpAttribute
{
uint64_t type_die_offset = form_value.Reference();
if (!verbose)
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
s.PutCString(" ( ");
AppendTypeName(dwarf2Data, cu, type_die_offset, s);
s.PutCString(" )");
@@ -1182,7 +856,7 @@ DWARFDebugInfoEntry::DumpAttribute
case DW_AT_ranges:
{
if ( !verbose )
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
lldb::offset_t ranges_offset = form_value.Unsigned();
dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
if (dwarf2Data)
@@ -1192,7 +866,7 @@ DWARFDebugInfoEntry::DumpAttribute
default:
if ( !verbose )
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
break;
}
@@ -1206,24 +880,37 @@ DWARFDebugInfoEntry::DumpAttribute
// take precedence (this can happen for declaration attributes).
//----------------------------------------------------------------------
size_t
-DWARFDebugInfoEntry::GetAttributes
-(
- SymbolFileDWARF* dwarf2Data,
- const DWARFCompileUnit* cu,
- const uint8_t *fixed_form_sizes,
- DWARFDebugInfoEntry::Attributes& attributes,
- uint32_t curr_depth
-) const
+DWARFDebugInfoEntry::GetAttributes (const DWARFCompileUnit* cu,
+ DWARFFormValue::FixedFormSizes fixed_form_sizes,
+ DWARFAttributes& attributes,
+ uint32_t curr_depth) const
{
- lldb::offset_t offset;
- const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
+ SymbolFileDWARF* dwarf2Data = nullptr;
+ const DWARFAbbreviationDeclaration* abbrevDecl = nullptr;
+ lldb::offset_t offset = 0;
+ if (cu)
+ {
+ if (m_tag != DW_TAG_compile_unit)
+ {
+ SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile();
+ if (dwo_symbol_file)
+ return GetAttributes(dwo_symbol_file->GetCompileUnit(),
+ fixed_form_sizes,
+ attributes,
+ curr_depth);
+ }
+
+ dwarf2Data = cu->GetSymbolFileDWARF();
+ abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
+ }
if (abbrevDecl)
{
const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
- if (fixed_form_sizes == NULL)
- fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize(), cu->IsDWARF64());
+ if (fixed_form_sizes.Empty())
+ fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(
+ cu->GetAddressByteSize(), cu->IsDWARF64());
const uint32_t num_attributes = abbrevDecl->NumAttributes();
uint32_t i;
@@ -1258,26 +945,15 @@ DWARFDebugInfoEntry::GetAttributes
DWARFFormValue form_value (cu, form);
if (form_value.ExtractValue(debug_info_data, &offset))
{
- const DWARFDebugInfoEntry* die = NULL;
dw_offset_t die_offset = form_value.Reference();
- if (cu->ContainsDIEOffset(die_offset))
- {
- die = const_cast<DWARFCompileUnit*>(cu)->GetDIEPtr(die_offset);
- if (die)
- die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes, curr_depth + 1);
- }
- else
- {
- DWARFCompileUnitSP cu_sp_ptr;
- die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
- if (die)
- die->GetAttributes(dwarf2Data, cu_sp_ptr.get(), fixed_form_sizes, attributes, curr_depth + 1);
- }
+ DWARFDIE spec_die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(die_offset);
+ if (spec_die)
+ spec_die.GetAttributes(attributes, curr_depth + 1);
}
}
else
{
- const uint8_t fixed_skip_size = fixed_form_sizes [form];
+ const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form);
if (fixed_skip_size)
offset += fixed_skip_size;
else
@@ -1308,9 +984,19 @@ DWARFDebugInfoEntry::GetAttributeValue
const DWARFCompileUnit* cu,
const dw_attr_t attr,
DWARFFormValue& form_value,
- dw_offset_t* end_attr_offset_ptr
+ dw_offset_t* end_attr_offset_ptr,
+ bool check_specification_or_abstract_origin
) const
{
+ SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile();
+ if (dwo_symbol_file && m_tag != DW_TAG_compile_unit)
+ return GetAttributeValue(dwo_symbol_file,
+ dwo_symbol_file->GetCompileUnit(),
+ attr,
+ form_value,
+ end_attr_offset_ptr,
+ check_specification_or_abstract_origin);
+
lldb::offset_t offset;
const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
@@ -1338,7 +1024,58 @@ DWARFDebugInfoEntry::GetAttributeValue
}
}
- return 0;
+ if (check_specification_or_abstract_origin)
+ {
+ if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
+ {
+ DWARFDIE die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(form_value.Reference());
+ if (die)
+ {
+ dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(die.GetDWARF(),
+ die.GetCU(),
+ attr,
+ form_value,
+ end_attr_offset_ptr,
+ false);
+ if (die_offset)
+ return die_offset;
+ }
+ }
+
+ if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value))
+ {
+ DWARFDIE die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(form_value.Reference());
+ if (die)
+ {
+ dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(die.GetDWARF(),
+ die.GetCU(),
+ attr,
+ form_value,
+ end_attr_offset_ptr,
+ false);
+ if (die_offset)
+ return die_offset;
+ }
+ }
+ }
+
+ if (!dwo_symbol_file)
+ return 0;
+
+ DWARFCompileUnit* dwo_cu = dwo_symbol_file->GetCompileUnit();
+ if (!dwo_cu)
+ return 0;
+
+ DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly();
+ if (!dwo_cu_die.IsValid())
+ return 0;
+
+ return dwo_cu_die.GetDIE()->GetAttributeValue(dwo_symbol_file,
+ dwo_cu,
+ attr,
+ form_value,
+ end_attr_offset_ptr,
+ check_specification_or_abstract_origin);
}
//----------------------------------------------------------------------
@@ -1355,11 +1092,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsString
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- const char* fail_value) const
+ const char* fail_value,
+ bool check_specification_or_abstract_origin) const
{
DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
- return form_value.AsCString(&dwarf2Data->get_debug_str_data());
+ if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))
+ return form_value.AsCString();
return fail_value;
}
@@ -1374,11 +1112,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsUnsigned
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- uint64_t fail_value
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin
) const
{
DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+ if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))
return form_value.Unsigned();
return fail_value;
}
@@ -1394,11 +1133,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsSigned
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- int64_t fail_value
+ int64_t fail_value,
+ bool check_specification_or_abstract_origin
) const
{
DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+ if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))
return form_value.Signed();
return fail_value;
}
@@ -1415,15 +1155,32 @@ DWARFDebugInfoEntry::GetAttributeValueAsReference
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- uint64_t fail_value
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin
) const
{
DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+ if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))
return form_value.Reference();
return fail_value;
}
+uint64_t
+DWARFDebugInfoEntry::GetAttributeValueAsAddress
+(
+ SymbolFileDWARF* dwarf2Data,
+ const DWARFCompileUnit* cu,
+ const dw_attr_t attr,
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin
+) const
+{
+ DWARFFormValue form_value;
+ if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))
+ return form_value.Address();
+ return fail_value;
+}
+
//----------------------------------------------------------------------
// GetAttributeHighPC
//
@@ -1438,17 +1195,19 @@ DWARFDebugInfoEntry::GetAttributeHighPC
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
dw_addr_t lo_pc,
- uint64_t fail_value
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin
) const
{
DWARFFormValue form_value;
-
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value))
+ if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value, nullptr, check_specification_or_abstract_origin))
{
- dw_addr_t hi_pc = form_value.Unsigned();
- if (form_value.Form() != DW_FORM_addr)
- hi_pc += lo_pc; // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
- return hi_pc;
+ dw_form_t form = form_value.Form();
+ if (form == DW_FORM_addr || form == DW_FORM_GNU_addr_index)
+ return form_value.Address();
+
+ // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
+ return lo_pc + form_value.Unsigned();
}
return fail_value;
}
@@ -1468,13 +1227,14 @@ DWARFDebugInfoEntry::GetAttributeAddressRange
const DWARFCompileUnit* cu,
dw_addr_t& lo_pc,
dw_addr_t& hi_pc,
- uint64_t fail_value
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin
) const
{
- lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, fail_value);
+ lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, fail_value, check_specification_or_abstract_origin);
if (lo_pc != fail_value)
{
- hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, fail_value);
+ hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, fail_value, check_specification_or_abstract_origin);
if (hi_pc != fail_value)
return true;
}
@@ -1484,89 +1244,40 @@ DWARFDebugInfoEntry::GetAttributeAddressRange
}
size_t
-DWARFDebugInfoEntry::GetAttributeAddressRanges(SymbolFileDWARF* dwarf2Data,
- const DWARFCompileUnit* cu,
- DWARFDebugRanges::RangeList &ranges,
- bool check_hi_lo_pc) const
+DWARFDebugInfoEntry::GetAttributeAddressRanges (SymbolFileDWARF* dwarf2Data,
+ const DWARFCompileUnit* cu,
+ DWARFRangeList &ranges,
+ bool check_hi_lo_pc,
+ bool check_specification_or_abstract_origin) const
{
ranges.Clear();
- dw_offset_t ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
- if (ranges_offset != DW_INVALID_OFFSET)
+ dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data,
+ cu,
+ DW_AT_ranges,
+ DW_INVALID_OFFSET,
+ check_specification_or_abstract_origin);
+ if (debug_ranges_offset != DW_INVALID_OFFSET)
{
- dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
- if (debug_ranges_offset != DW_INVALID_OFFSET)
- {
- DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
-
- debug_ranges->FindRanges(debug_ranges_offset, ranges);
- ranges.Slide (cu->GetBaseAddress());
- }
+ DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
+
+ debug_ranges->FindRanges(debug_ranges_offset, ranges);
+ ranges.Slide (cu->GetBaseAddress());
}
else if (check_hi_lo_pc)
{
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
- if (GetAttributeAddressRange (dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS))
+ if (GetAttributeAddressRange (dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS, check_specification_or_abstract_origin))
{
if (lo_pc < hi_pc)
- ranges.Append(DWARFDebugRanges::RangeList::Entry(lo_pc, hi_pc - lo_pc));
+ ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
}
}
return ranges.GetSize();
}
//----------------------------------------------------------------------
-// GetAttributeValueAsLocation
-//
-// Get the value of an attribute as reference and fix up and compile
-// unit relative offsets as needed.
-//----------------------------------------------------------------------
-dw_offset_t
-DWARFDebugInfoEntry::GetAttributeValueAsLocation
-(
- SymbolFileDWARF* dwarf2Data,
- const DWARFCompileUnit* cu,
- const dw_attr_t attr,
- DWARFDataExtractor& location_data,
- uint32_t &block_size
-) const
-{
- block_size = 0;
- DWARFFormValue form_value;
-
- // Empty out data in case we don't find anything
- location_data.Clear();
- dw_offset_t end_addr_offset = DW_INVALID_OFFSET;
- const dw_offset_t attr_offset = GetAttributeValue(dwarf2Data, cu, attr, form_value, &end_addr_offset);
- if (attr_offset)
- {
- const uint8_t* blockData = form_value.BlockData();
- if (blockData)
- {
- // We have an inlined location list in the .debug_info section
- const DWARFDataExtractor& debug_info = dwarf2Data->get_debug_info_data();
- dw_offset_t block_offset = blockData - debug_info.GetDataStart();
- block_size = (end_addr_offset - attr_offset) - form_value.Unsigned();
- location_data.SetData(debug_info, block_offset, block_size);
- }
- else
- {
- // We have a location list offset as the value that is
- // the offset into the .debug_loc section that describes
- // the value over it's lifetime
- lldb::offset_t debug_loc_offset = form_value.Unsigned();
- if (dwarf2Data)
- {
- assert(dwarf2Data->get_debug_loc_data().GetAddressByteSize() == cu->GetAddressByteSize());
- return DWARFLocationList::Extract(dwarf2Data->get_debug_loc_data(), &debug_loc_offset, location_data);
- }
- }
- }
- return attr_offset;
-}
-
-//----------------------------------------------------------------------
// GetName
//
// Get value of the DW_AT_name attribute and return it if one exists,
@@ -1579,27 +1290,9 @@ DWARFDebugInfoEntry::GetName
const DWARFCompileUnit* cu
) const
{
- DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
- return form_value.AsCString(&dwarf2Data->get_debug_str_data());
- else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
- {
- DWARFCompileUnitSP cu_sp_ptr;
- const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr);
- if (die)
- return die->GetName(dwarf2Data, cu_sp_ptr.get());
- }
- else if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value))
- {
- DWARFCompileUnitSP cu_sp_ptr;
- const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr);
- if (die)
- return die->GetName(dwarf2Data, cu_sp_ptr.get());
- }
- return nullptr;
+ return GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);
}
-
//----------------------------------------------------------------------
// GetMangledName
//
@@ -1614,20 +1307,20 @@ DWARFDebugInfoEntry::GetMangledName
bool substitute_name_allowed
) const
{
- const char* name = NULL;
- DWARFFormValue form_value;
+ const char* name = nullptr;
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, nullptr, true);
+ if (name)
+ return name;
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_linkage_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, true);
+ if (name)
+ return name;
- if (substitute_name_allowed && name == NULL)
- {
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
- }
+ if (!substitute_name_allowed)
+ return nullptr;
+
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);
return name;
}
@@ -1645,27 +1338,19 @@ DWARFDebugInfoEntry::GetPubname
const DWARFCompileUnit* cu
) const
{
- const char* name = NULL;
+ const char* name = nullptr;
if (!dwarf2Data)
return name;
-
- DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
- else if (GetAttributeValue(dwarf2Data, cu, DW_AT_linkage_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
- else if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
- else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
- {
- // The specification DIE may be in another compile unit so we need
- // to get a die and its compile unit.
- DWARFCompileUnitSP cu_sp_ptr;
- const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr);
- if (die)
- return die->GetPubname(dwarf2Data, cu_sp_ptr.get());
- }
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, nullptr, true);
+ if (name)
+ return name;
+
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, true);
+ if (name)
+ return name;
+
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);
return name;
}
@@ -1705,15 +1390,11 @@ DWARFDebugInfoEntry::GetName
}
else
{
- DWARFFormValue form_value;
- if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+ const char* name = die.GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);
+ if (name)
{
- const char* name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
- if (name)
- {
- s.PutCString(name);
- return true;
- }
+ s.PutCString(name);
+ return true;
}
}
}
@@ -1755,8 +1436,6 @@ DWARFDebugInfoEntry::AppendTypeName
else
{
const char* name = die.GetPubname(dwarf2Data, cu);
- // if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
- // name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
if (name)
s.PutCString(name);
else
@@ -1909,16 +1588,12 @@ DWARFDebugInfoEntry::BuildFunctionAddressRangeTable
}
void
-DWARFDebugInfoEntry::GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data,
- DWARFCompileUnit* cu,
+DWARFDebugInfoEntry::GetDeclContextDIEs (DWARFCompileUnit* cu,
DWARFDIECollection &decl_context_dies) const
{
- const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
- if (parent_decl_ctx_die && parent_decl_ctx_die != this)
- {
- decl_context_dies.Append(parent_decl_ctx_die);
- parent_decl_ctx_die->GetDeclContextDIEs (dwarf2Data, cu, decl_context_dies);
- }
+
+ DWARFDIE die (cu, const_cast<DWARFDebugInfoEntry *>(this));
+ die.GetDeclContextDIEs(decl_context_dies);
}
void
@@ -1930,11 +1605,11 @@ DWARFDebugInfoEntry::GetDWARFDeclContext (SymbolFileDWARF* dwarf2Data,
if (tag != DW_TAG_compile_unit)
{
dwarf_decl_ctx.AppendDeclContext(tag, GetName(dwarf2Data, cu));
- const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
- if (parent_decl_ctx_die && parent_decl_ctx_die != this)
+ DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
+ if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != this)
{
- if (parent_decl_ctx_die->Tag() != DW_TAG_compile_unit)
- parent_decl_ctx_die->GetDWARFDeclContext (dwarf2Data, cu, dwarf_decl_ctx);
+ if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit)
+ parent_decl_ctx_die.GetDIE()->GetDWARFDeclContext (parent_decl_ctx_die.GetDWARF(), parent_decl_ctx_die.GetCU(), dwarf_decl_ctx);
}
}
}
@@ -1951,30 +1626,30 @@ DWARFDebugInfoEntry::MatchesDWARFDeclContext (SymbolFileDWARF* dwarf2Data,
return this_dwarf_decl_ctx == dwarf_decl_ctx;
}
-const DWARFDebugInfoEntry *
+DWARFDIE
DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu) const
{
- DWARFDebugInfoEntry::Attributes attributes;
- GetAttributes(dwarf2Data, cu, NULL, attributes);
+ DWARFAttributes attributes;
+ GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes);
return GetParentDeclContextDIE (dwarf2Data, cu, attributes);
}
-const DWARFDebugInfoEntry *
+DWARFDIE
DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry::Attributes& attributes) const
+ const DWARFAttributes& attributes) const
{
- const DWARFDebugInfoEntry * die = this;
-
- while (die != NULL)
+ DWARFDIE die (cu, const_cast<DWARFDebugInfoEntry *>(this));
+
+ while (die)
{
// If this is the original DIE that we are searching for a declaration
// for, then don't look in the cache as we don't want our own decl
// context to be our decl context...
- if (die != this)
+ if (die.GetDIE() != this)
{
- switch (die->Tag())
+ switch (die.Tag())
{
case DW_TAG_compile_unit:
case DW_TAG_namespace:
@@ -1990,33 +1665,33 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
dw_offset_t die_offset;
- die_offset = attributes.FormValueAsUnsigned(dwarf2Data, DW_AT_specification, DW_INVALID_OFFSET);
+ die_offset = attributes.FormValueAsUnsigned(DW_AT_specification, DW_INVALID_OFFSET);
if (die_offset != DW_INVALID_OFFSET)
{
- const DWARFDebugInfoEntry *spec_die = cu->GetDIEPtr (die_offset);
+ DWARFDIE spec_die = cu->GetDIE (die_offset);
if (spec_die)
- {
- const DWARFDebugInfoEntry *spec_die_decl_ctx_die = spec_die->GetParentDeclContextDIE (dwarf2Data, cu);
- if (spec_die_decl_ctx_die)
- return spec_die_decl_ctx_die;
- }
+ {
+ DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE();
+ if (decl_ctx_die)
+ return decl_ctx_die;
+ }
}
- die_offset = attributes.FormValueAsUnsigned(dwarf2Data, DW_AT_abstract_origin, DW_INVALID_OFFSET);
+ die_offset = attributes.FormValueAsUnsigned(DW_AT_abstract_origin, DW_INVALID_OFFSET);
if (die_offset != DW_INVALID_OFFSET)
{
- const DWARFDebugInfoEntry *abs_die = cu->GetDIEPtr (die_offset);
+ DWARFDIE abs_die = cu->GetDIE (die_offset);
if (abs_die)
{
- const DWARFDebugInfoEntry *abs_die_decl_ctx_die = abs_die->GetParentDeclContextDIE (dwarf2Data, cu);
- if (abs_die_decl_ctx_die)
- return abs_die_decl_ctx_die;
+ DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE();
+ if (decl_ctx_die)
+ return decl_ctx_die;
}
}
- die = die->GetParent();
+ die = die.GetParent();
}
- return NULL;
+ return DWARFDIE();
}
@@ -2025,15 +1700,15 @@ DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
std::string &storage) const
{
- DWARFDebugInfoEntry::Attributes attributes;
- GetAttributes(dwarf2Data, cu, NULL, attributes);
+ DWARFAttributes attributes;
+ GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes);
return GetQualifiedName (dwarf2Data, cu, attributes, storage);
}
const char*
DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry::Attributes& attributes,
+ const DWARFAttributes& attributes,
std::string &storage) const
{
@@ -2041,47 +1716,47 @@ DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data,
if (name)
{
- const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
+ DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
storage.clear();
// TODO: change this to get the correct decl context parent....
while (parent_decl_ctx_die)
{
- const dw_tag_t parent_tag = parent_decl_ctx_die->Tag();
+ const dw_tag_t parent_tag = parent_decl_ctx_die.Tag();
switch (parent_tag)
{
case DW_TAG_namespace:
- {
- const char *namespace_name = parent_decl_ctx_die->GetName (dwarf2Data, cu);
- if (namespace_name)
- {
- storage.insert (0, "::");
- storage.insert (0, namespace_name);
- }
- else
- {
- storage.insert (0, "(anonymous namespace)::");
- }
- parent_decl_ctx_die = parent_decl_ctx_die->GetParentDeclContextDIE(dwarf2Data, cu);
- }
+ {
+ const char *namespace_name = parent_decl_ctx_die.GetName ();
+ if (namespace_name)
+ {
+ storage.insert (0, "::");
+ storage.insert (0, namespace_name);
+ }
+ else
+ {
+ storage.insert (0, "(anonymous namespace)::");
+ }
+ parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
+ }
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
- {
- const char *class_union_struct_name = parent_decl_ctx_die->GetName (dwarf2Data, cu);
-
- if (class_union_struct_name)
- {
- storage.insert (0, "::");
- storage.insert (0, class_union_struct_name);
- }
- parent_decl_ctx_die = parent_decl_ctx_die->GetParentDeclContextDIE(dwarf2Data, cu);
- }
+ {
+ const char *class_union_struct_name = parent_decl_ctx_die.GetName ();
+
+ if (class_union_struct_name)
+ {
+ storage.insert (0, "::");
+ storage.insert (0, class_union_struct_name);
+ }
+ parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
+ }
break;
default:
- parent_decl_ctx_die = NULL;
+ parent_decl_ctx_die.Clear();
break;
}
}
@@ -2179,7 +1854,7 @@ DWARFDebugInfoEntry::LookupAddress
if (match_addr_range)
{
- dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+ dw_addr_t lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
if (lo_pc != LLDB_INVALID_ADDRESS)
{
dw_addr_t hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, LLDB_INVALID_ADDRESS);
@@ -2229,7 +1904,7 @@ DWARFDebugInfoEntry::LookupAddress
dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
if (debug_ranges_offset != DW_INVALID_OFFSET)
{
- DWARFDebugRanges::RangeList ranges;
+ DWARFRangeList ranges;
DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
debug_ranges->FindRanges(debug_ranges_offset, ranges);
// All DW_AT_ranges are relative to the base address of the
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 3949ad3..02bbff8 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -57,56 +57,6 @@ public:
typedef offset_collection::iterator offset_collection_iterator;
typedef offset_collection::const_iterator offset_collection_const_iterator;
- class Attributes
- {
- public:
- Attributes();
- ~Attributes();
-
- void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form);
- const DWARFCompileUnit * CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; }
- dw_offset_t DIEOffsetAtIndex(uint32_t i) const { return m_infos[i].die_offset; }
- dw_attr_t AttributeAtIndex(uint32_t i) const { return m_infos[i].attr; }
- dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].form; }
- bool ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const;
- uint64_t FormValueAsUnsignedAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const;
- uint64_t FormValueAsUnsigned (SymbolFileDWARF* dwarf2Data, dw_attr_t attr, uint64_t fail_value) const;
- uint32_t FindAttributeIndex(dw_attr_t attr) const;
- bool ContainsAttribute(dw_attr_t attr) const;
- bool RemoveAttribute(dw_attr_t attr);
- void Clear() { m_infos.clear(); }
- size_t Size() const { return m_infos.size(); }
-
- protected:
- struct Info
- {
- const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in case we have DW_FORM_ref_addr values
- dw_offset_t die_offset;
- dw_attr_t attr;
- dw_form_t form;
- };
-
- typedef llvm::SmallVector<Info, 8> collection;
- collection m_infos;
- };
-
- struct CompareState
- {
- CompareState() :
- die_offset_pairs()
- {
- assert(sizeof(dw_offset_t)*2 == sizeof(uint64_t));
- }
-
- bool AddTypePair(dw_offset_t a, dw_offset_t b)
- {
- uint64_t a_b_offsets = (uint64_t)a << 32 | (uint64_t)b;
- // Return true if this type was inserted, false otherwise
- return die_offset_pairs.insert(a_b_offsets).second;
- }
- std::set< uint64_t > die_offset_pairs;
- };
-
DWARFDebugInfoEntry():
m_offset (DW_INVALID_OFFSET),
m_parent_idx (0),
@@ -144,7 +94,7 @@ public:
bool FastExtract(
const lldb_private::DWARFDataExtractor& debug_info_data,
const DWARFCompileUnit* cu,
- const uint8_t *fixed_form_sizes,
+ const DWARFFormValue::FixedFormSizes& fixed_form_sizes,
lldb::offset_t* offset_ptr);
bool Extract(
@@ -160,68 +110,67 @@ public:
DWARFDebugInfoEntry** block_die);
size_t GetAttributes(
- SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
- const uint8_t *fixed_form_sizes,
- DWARFDebugInfoEntry::Attributes& attrs,
+ DWARFFormValue::FixedFormSizes fixed_form_sizes,
+ DWARFAttributes& attrs,
uint32_t curr_depth = 0) const; // "curr_depth" for internal use only, don't set this yourself!!!
- dw_offset_t GetAttributeValue(
- SymbolFileDWARF* dwarf2Data,
- const DWARFCompileUnit* cu,
- const dw_attr_t attr,
- DWARFFormValue& formValue,
- dw_offset_t* end_attr_offset_ptr = NULL) const;
-
const char* GetAttributeValueAsString(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- const char* fail_value) const;
+ const char* fail_value,
+ bool check_specification_or_abstract_origin = false) const;
uint64_t GetAttributeValueAsUnsigned(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- uint64_t fail_value) const;
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
uint64_t GetAttributeValueAsReference(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- uint64_t fail_value) const;
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
int64_t GetAttributeValueAsSigned(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- int64_t fail_value) const;
+ int64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
+
+ uint64_t GetAttributeValueAsAddress(
+ SymbolFileDWARF* dwarf2Data,
+ const DWARFCompileUnit* cu,
+ const dw_attr_t attr,
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
dw_addr_t GetAttributeHighPC(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
dw_addr_t lo_pc,
- uint64_t fail_value) const;
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
bool GetAttributeAddressRange(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
dw_addr_t& lo_pc,
dw_addr_t& hi_pc,
- uint64_t fail_value) const;
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
size_t GetAttributeAddressRanges (
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
- DWARFDebugRanges::RangeList &ranges,
- bool check_hi_lo_pc) const;
-
- dw_offset_t GetAttributeValueAsLocation(
- SymbolFileDWARF* dwarf2Data,
- const DWARFCompileUnit* cu,
- const dw_attr_t attr,
- lldb_private::DWARFDataExtractor& data,
- uint32_t &block_size) const;
+ DWARFRangeList &ranges,
+ bool check_hi_lo_pc,
+ bool check_specification_or_abstract_origin = false) const;
const char* GetName(
SymbolFileDWARF* dwarf2Data,
@@ -256,25 +205,9 @@ public:
const char * GetQualifiedName (
SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry::Attributes& attributes,
+ const DWARFAttributes& attributes,
std::string &storage) const;
-// static int Compare(
-// SymbolFileDWARF* dwarf2Data,
-// dw_offset_t a_die_offset,
-// dw_offset_t b_die_offset,
-// CompareState &compare_state,
-// bool compare_siblings,
-// bool compare_children);
-//
-// static int Compare(
-// SymbolFileDWARF* dwarf2Data,
-// DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die,
-// DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die,
-// CompareState &compare_state,
-// bool compare_siblings,
-// bool compare_children);
-
static bool OffsetLessThan (
const DWARFDebugInfoEntry& a,
const DWARFDebugInfoEntry& b);
@@ -311,7 +244,7 @@ public:
const DWARFCompileUnit* cu,
const char * &name,
const char * &mangled,
- DWARFDebugRanges::RangeList& rangeList,
+ DWARFRangeList& rangeList,
int& decl_file,
int& decl_line,
int& decl_column,
@@ -376,8 +309,7 @@ public:
const DWARFDebugInfoEntry* GetFirstChild() const { return (HasChildren() && !m_empty_children) ? this + 1 : NULL; }
- void GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data,
- DWARFCompileUnit* cu,
+ void GetDeclContextDIEs (DWARFCompileUnit* cu,
DWARFDIECollection &decl_context_dies) const;
void GetDWARFDeclContext (SymbolFileDWARF* dwarf2Data,
@@ -389,11 +321,11 @@ public:
DWARFCompileUnit* cu,
const DWARFDeclContext &dwarf_decl_ctx) const;
- const DWARFDebugInfoEntry* GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
+ DWARFDIE GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu) const;
- const DWARFDebugInfoEntry* GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
+ DWARFDIE GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry::Attributes& attributes) const;
+ const DWARFAttributes& attributes) const;
void
SetParent (DWARFDebugInfoEntry* parent)
@@ -450,6 +382,13 @@ public:
DWARFDebugInfoEntry::collection &die_collection);
protected:
+ dw_offset_t GetAttributeValue(SymbolFileDWARF* dwarf2Data,
+ const DWARFCompileUnit* cu,
+ const dw_attr_t attr,
+ DWARFFormValue& formValue,
+ dw_offset_t* end_attr_offset_ptr = nullptr,
+ bool check_specification_or_abstract_origin = false) const;
+
dw_offset_t m_offset; // Offset within the .debug_info of the start of this entry
uint32_t m_parent_idx; // How many to subtract from "this" to get the parent. If zero this die has no parent
uint32_t m_sibling_idx:31, // How many to add to "this" to get the sibling.
@@ -457,7 +396,6 @@ protected:
uint32_t m_abbr_idx:DIE_ABBR_IDX_BITSIZE,
m_has_children:1, // Set to 1 if this DIE has children
m_tag:16; // A copy of the DW_TAG value so we don't have to go through the compile unit abbrev table
-
};
#endif // SymbolFileDWARF_DWARFDebugInfoEntry_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
index 48e11bd..84c2142 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -249,7 +249,7 @@ DWARFDebugLine::DumpStatementOpcodes(Log *log, const DWARFDataExtractor& debug_l
fileEntry.length = debug_line_data.GetULEB128(&offset);
log->Printf( "0x%8.8x: DW_LNE_define_file('%s', dir=%i, mod_time=0x%8.8x, length=%i )",
op_offset,
- fileEntry.name.c_str(),
+ fileEntry.name,
fileEntry.dir_idx,
fileEntry.mod_time,
fileEntry.length);
@@ -486,65 +486,25 @@ DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp,
FileSpecList &support_files)
{
lldb::offset_t offset = stmt_list;
- // Skip the total length
- (void)debug_line_data.GetDWARFInitialLength(&offset);
- uint32_t version = debug_line_data.GetU16(&offset);
- if (version < 2 || version > 4)
- return false;
- const dw_offset_t end_prologue_offset = debug_line_data.GetDWARFOffset(&offset) + offset;
- // Skip instruction length, default is stmt, line base, line range
- offset += 4;
- // For DWARF4, skip maximum operations per instruction
- if (version >= 4)
- offset += 1;
- // Skip opcode base, and all opcode lengths
- const uint8_t opcode_base = debug_line_data.GetU8(&offset);
- offset += opcode_base - 1;
- std::vector<FileSpec> include_directories{{}}; // Directory at index zero doesn't exist
- while (offset < end_prologue_offset)
+ Prologue prologue;
+ if (!ParsePrologue(debug_line_data, &offset, &prologue))
{
- FileSpec dir{debug_line_data.GetCStr(&offset), false};
- if (dir)
- include_directories.emplace_back(std::move(dir));
- else
- break;
+ Host::SystemLog (Host::eSystemLogError, "error: parsing line table prologue at 0x%8.8x (parsing ended around 0x%8.8" PRIx64 "\n", stmt_list, offset);
+ return false;
}
- while (offset < end_prologue_offset)
- {
- FileSpec file_spec{debug_line_data.GetCStr(&offset), false};
- if (file_spec)
- {
- uint32_t dir_idx = debug_line_data.GetULEB128(&offset);
- debug_line_data.Skip_LEB128(&offset); // Skip mod_time
- debug_line_data.Skip_LEB128(&offset); // Skip length
- if (file_spec.IsRelative())
- {
- if (0 < dir_idx && dir_idx < include_directories.size())
- {
- const FileSpec &dir = include_directories[dir_idx];
- file_spec.PrependPathComponent(dir);
- }
- if (file_spec.IsRelative())
- file_spec.PrependPathComponent(cu_comp_dir);
- }
- std::string remapped_file;
- if (module_sp->RemapSourceFile(file_spec.GetCString(), remapped_file))
- file_spec.SetFile(remapped_file, false);
- support_files.Append(file_spec);
- }
- }
+ FileSpec file_spec;
+ std::string remapped_file;
- if (offset != end_prologue_offset)
+ for (uint32_t file_idx = 1; prologue.GetFile(file_idx, cu_comp_dir, file_spec); ++file_idx)
{
- Host::SystemLog (Host::eSystemLogError,
- "warning: parsing line table prologue at 0x%8.8x should have ended at 0x%8.8x but it ended at 0x%8.8" PRIx64 "\n",
- stmt_list,
- end_prologue_offset,
- offset);
+ if (module_sp->RemapSourceFile(file_spec.GetCString(), remapped_file))
+ file_spec.SetFile(remapped_file, false);
+ support_files.Append(file_spec);
+
}
- return end_prologue_offset;
+ return true;
}
//----------------------------------------------------------------------
@@ -900,7 +860,7 @@ DWARFDebugLine::Prologue::Dump(Log *log)
{
for (i=0; i<include_directories.size(); ++i)
{
- log->Printf( "include_directories[%3u] = '%s'", i+1, include_directories[i].c_str());
+ log->Printf( "include_directories[%3u] = '%s'", i+1, include_directories[i]);
}
}
@@ -916,7 +876,7 @@ DWARFDebugLine::Prologue::Dump(Log *log)
fileEntry.dir_idx,
fileEntry.mod_time,
fileEntry.length,
- fileEntry.name.c_str());
+ fileEntry.name);
}
}
}
@@ -959,17 +919,28 @@ DWARFDebugLine::Prologue::Dump(Log *log)
//}
-bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, std::string& path, std::string& directory) const
+bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, const char *comp_dir, FileSpec &file) const
{
uint32_t idx = file_idx - 1; // File indexes are 1 based...
if (idx < file_names.size())
{
- path = file_names[idx].name;
- uint32_t dir_idx = file_names[idx].dir_idx - 1;
- if (dir_idx < include_directories.size())
- directory = include_directories[dir_idx];
- else
- directory.clear();
+ file.SetFile(file_names[idx].name, false);
+ if (file.IsRelative())
+ {
+ if (file_names[idx].dir_idx > 0)
+ {
+ const uint32_t dir_idx = file_names[idx].dir_idx - 1;
+ if (dir_idx < include_directories.size())
+ {
+ file.PrependPathComponent(include_directories[dir_idx]);
+ if (!file.IsRelative())
+ return true;
+ }
+ }
+
+ if (comp_dir && comp_dir[0])
+ file.PrependPathComponent(comp_dir);
+ }
return true;
}
return false;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
index 7da0e76..9f2219b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
@@ -20,7 +20,6 @@
#include "DWARFDefines.h"
class SymbolFileDWARF;
-class DWARFDebugInfoEntry;
//----------------------------------------------------------------------
// DWARFDebugLine
@@ -34,14 +33,14 @@ public:
struct FileNameEntry
{
FileNameEntry() :
- name(),
+ name(nullptr),
dir_idx(0),
mod_time(0),
length(0)
{
}
- std::string name;
+ const char* name;
dw_sleb128_t dir_idx;
dw_sleb128_t mod_time;
dw_sleb128_t length;
@@ -81,7 +80,7 @@ public:
uint8_t line_range; // This parameter affects the meaning of the special opcodes. See below.
uint8_t opcode_base; // The number assigned to the first special opcode.
std::vector<uint8_t> standard_opcode_lengths;
- std::vector<std::string> include_directories;
+ std::vector<const char *> include_directories;
std::vector<FileNameEntry> file_names;
int32_t MaxLineIncrementForSpecialOpcode() const { return line_base + (int8_t)line_range - 1; }
@@ -96,7 +95,7 @@ public:
include_directories.clear();
file_names.clear();
}
- bool GetFile(uint32_t file_idx, std::string& file, std::string& dir) const;
+ bool GetFile(uint32_t file_idx, const char *comp_dir, lldb_private::FileSpec &file) const;
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp
new file mode 100644
index 0000000..75c812e
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp
@@ -0,0 +1,128 @@
+//===-- DWARFDebugMacro.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugMacro.h"
+#include "SymbolFileDWARF.h"
+
+#include "lldb/Symbol/DebugMacros.h"
+
+#include "DWARFDataExtractor.h"
+
+using namespace lldb_private;
+
+DWARFDebugMacroHeader
+DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset)
+{
+ DWARFDebugMacroHeader header;
+
+ // Skip over the version field in header.
+ header.m_version = debug_macro_data.GetU16(offset);
+
+ uint8_t flags = debug_macro_data.GetU8(offset);
+ header.m_offset_is_64_bit = flags & OFFSET_SIZE_MASK ? true : false;
+
+ if (flags & DEBUG_LINE_OFFSET_MASK)
+ {
+ if (header.m_offset_is_64_bit)
+ header.m_debug_line_offset = debug_macro_data.GetU64(offset);
+ else
+ header.m_debug_line_offset = debug_macro_data.GetU32(offset);
+ }
+
+ // Skip over the operands table if it is present.
+ if (flags & OPCODE_OPERANDS_TABLE_MASK)
+ SkipOperandTable(debug_macro_data, offset);
+
+ return header;
+}
+
+void
+DWARFDebugMacroHeader::SkipOperandTable(const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset)
+{
+ uint8_t entry_count = debug_macro_data.GetU8(offset);
+ for (uint8_t i = 0; i < entry_count; i++)
+ {
+ // Skip over the opcode number.
+ debug_macro_data.GetU8(offset);
+
+ uint64_t operand_count = debug_macro_data.GetULEB128(offset);
+
+ for (uint64_t j = 0; j < operand_count; j++)
+ {
+ // Skip over the operand form
+ debug_macro_data.GetU8(offset);
+ }
+ }
+}
+
+void
+DWARFDebugMacroEntry::ReadMacroEntries(const DWARFDataExtractor &debug_macro_data,
+ const DWARFDataExtractor &debug_str_data,
+ const bool offset_is_64_bit,
+ lldb::offset_t *offset,
+ SymbolFileDWARF *sym_file_dwarf,
+ DebugMacrosSP &debug_macros_sp)
+{
+ llvm::dwarf::MacroEntryType type = static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset));
+ while (type != 0)
+ {
+ lldb::offset_t new_offset = 0, str_offset = 0;
+ uint32_t line = 0;
+ const char *macro_str = nullptr;
+ uint32_t debug_line_file_idx = 0;
+
+ switch (type)
+ {
+ case DW_MACRO_define:
+ case DW_MACRO_undef:
+ line = debug_macro_data.GetULEB128(offset);
+ macro_str = debug_macro_data.GetCStr(offset);
+ if (type == DW_MACRO_define)
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateDefineEntry(line, macro_str));
+ else
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateUndefEntry(line, macro_str));
+ break;
+ case DW_MACRO_define_indirect:
+ case DW_MACRO_undef_indirect:
+ line = debug_macro_data.GetULEB128(offset);
+ if (offset_is_64_bit)
+ str_offset = debug_macro_data.GetU64(offset);
+ else
+ str_offset = debug_macro_data.GetU32(offset);
+ macro_str = debug_str_data.GetCStr(&str_offset);
+ if (type == DW_MACRO_define_indirect)
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateDefineEntry(line, macro_str));
+ else
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateUndefEntry(line, macro_str));
+ break;
+ case DW_MACRO_start_file:
+ line = debug_macro_data.GetULEB128(offset);
+ debug_line_file_idx = debug_macro_data.GetULEB128(offset);
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateStartFileEntry(line, debug_line_file_idx));
+ break;
+ case DW_MACRO_end_file:
+ // This operation has no operands.
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateEndFileEntry());
+ break;
+ case DW_MACRO_transparent_include:
+ if (offset_is_64_bit)
+ new_offset = debug_macro_data.GetU64(offset);
+ else
+ new_offset = debug_macro_data.GetU32(offset);
+ debug_macros_sp->AddMacroEntry(
+ DebugMacroEntry::CreateIndirectEntry(sym_file_dwarf->ParseDebugMacros(&new_offset)));
+ break;
+ default:
+ // TODO: Add support for other standard operations.
+ // TODO: Provide mechanism to hook handling of non-standard/extension operands.
+ return;
+ }
+ type = static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset));
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h
new file mode 100644
index 0000000..c60b974
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h
@@ -0,0 +1,68 @@
+//===-- DWARFDebugMacro.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugMacro_h_
+#define SymbolFileDWARF_DWARFDebugMacro_h_
+
+#include <map>
+
+#include "lldb/lldb-types.h"
+#include "lldb/Core/dwarf.h"
+#include "lldb/Symbol/DebugMacros.h"
+
+namespace lldb_private
+{
+
+class DWARFDataExtractor;
+
+} // namespace lldb_private
+
+class SymbolFileDWARF;
+
+class DWARFDebugMacroHeader
+{
+public:
+ enum HeaderFlagMask
+ {
+ OFFSET_SIZE_MASK = 0x1,
+ DEBUG_LINE_OFFSET_MASK = 0x2,
+ OPCODE_OPERANDS_TABLE_MASK = 0x4
+ };
+
+ static DWARFDebugMacroHeader
+ ParseHeader(const lldb_private::DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset);
+
+ bool
+ OffsetIs64Bit() const
+ {
+ return m_offset_is_64_bit;
+ }
+
+private:
+ static void
+ SkipOperandTable(const lldb_private::DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset);
+
+ uint16_t m_version;
+ bool m_offset_is_64_bit;
+ uint64_t m_debug_line_offset;
+};
+
+class DWARFDebugMacroEntry
+{
+public:
+ static void
+ ReadMacroEntries(const lldb_private::DWARFDataExtractor &debug_macro_data,
+ const lldb_private::DWARFDataExtractor &debug_str_data,
+ const bool offset_is_64_bit,
+ lldb::offset_t *sect_offset,
+ SymbolFileDWARF *sym_file_dwarf,
+ lldb_private::DebugMacrosSP &debug_macros_sp);
+};
+
+#endif // SymbolFileDWARF_DWARFDebugMacro_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
index 8469b78..547bd0c 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
@@ -77,9 +77,6 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
if (debug_info)
{
-
- const DWARFDataExtractor* debug_str = &dwarf2Data->get_debug_str_data();
-
uint32_t cu_idx = 0;
const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
@@ -87,7 +84,9 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(), cu->IsDWARF64());
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(),
+ cu->IsDWARF64());
bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1;
@@ -101,17 +100,17 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
size_t die_idx;
for (die_idx = 0; die_idx < die_count; ++die_idx)
{
- const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
- DWARFDebugInfoEntry::Attributes attributes;
+ DWARFDIE die = dies.GetDIEAtIndex(die_idx);
+ DWARFAttributes attributes;
const char *name = NULL;
const char *mangled = NULL;
bool add_die = false;
- const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes);
+ const size_t num_attributes = die.GetDIE()->GetAttributes(die.GetCU(), fixed_form_sizes, attributes);
if (num_attributes > 0)
{
uint32_t i;
- dw_tag_t tag = die->Tag();
+ dw_tag_t tag = die.Tag();
for (i=0; i<num_attributes; ++i)
{
@@ -120,14 +119,14 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
switch (attr)
{
case DW_AT_name:
- if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
- name = form_value.AsCString(debug_str);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ name = form_value.AsCString();
break;
case DW_AT_MIPS_linkage_name:
case DW_AT_linkage_name:
- if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
- mangled = form_value.AsCString(debug_str);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ mangled = form_value.AsCString();
break;
case DW_AT_low_pc:
@@ -140,10 +139,10 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
case DW_AT_location:
if (tag == DW_TAG_variable)
{
- const DWARFDebugInfoEntry* parent_die = die->GetParent();
- while ( parent_die != NULL )
+ DWARFDIE parent_die = die.GetParent();
+ while ( parent_die )
{
- switch (parent_die->Tag())
+ switch (parent_die.Tag())
{
case DW_TAG_subprogram:
case DW_TAG_lexical_block:
@@ -153,31 +152,16 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
// if the location describes a hard coded address, but we don't want the performance
// penalty of that right now.
add_die = false;
-// if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
-// {
-// // If we have valid block data, then we have location expression bytes
-// // that are fixed (not a location list).
-// const uint8_t *block_data = form_value.BlockData();
-// if (block_data)
-// {
-// uint32_t block_length = form_value.Unsigned();
-// if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
-// {
-// if (block_data[0] == DW_OP_addr)
-// add_die = true;
-// }
-// }
-// }
- parent_die = NULL; // Terminate the while loop.
+ parent_die.Clear(); // Terminate the while loop.
break;
case DW_TAG_compile_unit:
add_die = true;
- parent_die = NULL; // Terminate the while loop.
+ parent_die.Clear(); // Terminate the while loop.
break;
default:
- parent_die = parent_die->GetParent(); // Keep going in the while loop.
+ parent_die = parent_die.GetParent(); // Keep going in the while loop.
break;
}
}
@@ -189,7 +173,7 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
if (add_die && (name || mangled))
{
- pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, mangled ? mangled : name);
+ pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), mangled ? mangled : name);
}
}
@@ -231,13 +215,11 @@ DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data)
size_t die_idx;
for (die_idx = 0; die_idx < die_count; ++die_idx)
{
- const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
- const char *name = die->GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, NULL);
+ DWARFDIE die = dies.GetDIEAtIndex (die_idx);
+ const char *name = die.GetName();
if (name)
- {
- pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, name);
- }
+ pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name);
}
if (pubnames_set.NumDescriptors() > 0)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
index 0953554..fc2831f 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -27,7 +27,7 @@ DWARFDebugRanges::~DWARFDebugRanges()
void
DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data)
{
- RangeList range_list;
+ DWARFRangeList range_list;
lldb::offset_t offset = 0;
dw_offset_t debug_ranges_offset = offset;
while (Extract(dwarf2Data, &offset, range_list))
@@ -38,52 +38,8 @@ DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data)
}
}
-//void
-//DWARFDebugRanges::RangeList::AddOffset(dw_addr_t offset)
-//{
-// if (!ranges.empty())
-// {
-// Range::iterator pos = ranges.begin();
-// Range::iterator end_pos = ranges.end();
-// for (pos = ranges.begin(); pos != end_pos; ++pos)
-// {
-// // assert for unsigned overflows
-// assert (~pos->begin_offset >= offset);
-// assert (~pos->end_offset >= offset);
-// pos->begin_offset += offset;
-// pos->end_offset += offset;
-// }
-// }
-//}
-//
-//void
-//DWARFDebugRanges::RangeList::SubtractOffset(dw_addr_t offset)
-//{
-// if (!ranges.empty())
-// {
-// Range::iterator pos = ranges.begin();
-// Range::iterator end_pos = ranges.end();
-// for (pos = ranges.begin(); pos != end_pos; ++pos)
-// {
-// assert (pos->begin_offset >= offset);
-// assert (pos->end_offset >= offset);
-// pos->begin_offset -= offset;
-// pos->end_offset -= offset;
-// }
-// }
-//}
-//
-//
-//const DWARFDebugRanges::Range*
-//DWARFDebugRanges::RangeList::RangeAtIndex(size_t i) const
-//{
-// if (i < ranges.size())
-// return &ranges[i];
-// return NULL;
-//}
-
bool
-DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, RangeList &range_list)
+DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, DWARFRangeList &range_list)
{
range_list.Clear();
@@ -118,13 +74,13 @@ DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_pt
break;
default:
- assert(!"DWARFDebugRanges::RangeList::Extract() unsupported address size.");
+ assert(!"DWARFRangeList::Extract() unsupported address size.");
break;
}
// Filter out empty ranges
if (begin < end)
- range_list.Append(Range(begin, end - begin));
+ range_list.Append(DWARFRangeList::Entry(begin, end - begin));
}
// Make sure we consumed at least something
@@ -178,7 +134,7 @@ DWARFDebugRanges::Dump(Stream &s, const DWARFDataExtractor& debug_ranges_data, l
}
bool
-DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, RangeList& range_list) const
+DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, DWARFRangeList& range_list) const
{
range_map_const_iterator pos = m_range_map.find(debug_ranges_offset);
if (pos != m_range_map.end())
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
index 50af91d..3ff4ea3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
@@ -11,34 +11,30 @@
#define SymbolFileDWARF_DWARFDebugRanges_h_
#include "SymbolFileDWARF.h"
+#include "DWARFDIE.h"
#include <map>
-#include <vector>
-
-#include "lldb/Core/RangeMap.h"
class DWARFDebugRanges
{
public:
- typedef lldb_private::RangeArray<dw_addr_t, dw_addr_t, 2> RangeList;
- typedef RangeList::Entry Range;
DWARFDebugRanges();
~DWARFDebugRanges();
void Extract(SymbolFileDWARF* dwarf2Data);
static void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr);
- bool FindRanges(dw_offset_t debug_ranges_offset, DWARFDebugRanges::RangeList& range_list) const;
+ bool FindRanges(dw_offset_t debug_ranges_offset, DWARFRangeList& range_list) const;
protected:
bool
Extract (SymbolFileDWARF* dwarf2Data,
lldb::offset_t *offset_ptr,
- RangeList &range_list);
+ DWARFRangeList &range_list);
- typedef std::map<dw_offset_t, RangeList> range_map;
- typedef range_map::iterator range_map_iterator;
- typedef range_map::const_iterator range_map_const_iterator;
+ typedef std::map<dw_offset_t, DWARFRangeList> range_map;
+ typedef range_map::iterator range_map_iterator;
+ typedef range_map::const_iterator range_map_const_iterator;
range_map m_range_map;
};
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
index 3a99d2b..4c29447 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
@@ -108,6 +108,13 @@ public:
return lldb_private::ConstString (GetQualifiedName ());
}
+ void
+ Clear()
+ {
+ m_entries.clear();
+ m_qualified_name.clear();
+ }
+
protected:
typedef std::vector<Entry> collection;
collection m_entries;
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index c733832..a0ed973 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -136,21 +136,21 @@ g_form_sizes_addr8_dwarf64[] =
8, // 0x20 DW_FORM_ref_sig8
};
-const uint8_t *
+DWARFFormValue::FixedFormSizes
DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64)
{
if (!is_dwarf64) {
switch (addr_size)
{
- case 4: return g_form_sizes_addr4;
- case 8: return g_form_sizes_addr8;
+ case 4: return FixedFormSizes(g_form_sizes_addr4, sizeof(g_form_sizes_addr4));
+ case 8: return FixedFormSizes(g_form_sizes_addr8, sizeof(g_form_sizes_addr8));
}
} else {
if (addr_size == 8)
- return g_form_sizes_addr8_dwarf64;
+ return FixedFormSizes(g_form_sizes_addr8_dwarf64, sizeof(g_form_sizes_addr8_dwarf64));
// is_dwarf64 && addr_size == 4 : no provider does this.
}
- return NULL;
+ return FixedFormSizes();
}
DWARFFormValue::DWARFFormValue() :
@@ -187,11 +187,7 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off
case DW_FORM_data2: m_value.value.uval = data.GetU16(offset_ptr); break;
case DW_FORM_data4: m_value.value.uval = data.GetU32(offset_ptr); break;
case DW_FORM_data8: m_value.value.uval = data.GetU64(offset_ptr); break;
- case DW_FORM_string: m_value.value.cstr = data.GetCStr(offset_ptr);
- // Set the string value to also be the data for inlined cstr form values only
- // so we can tell the difference between DW_FORM_string and DW_FORM_strp form
- // values;
- m_value.data = (const uint8_t*)m_value.value.cstr; break;
+ case DW_FORM_string: m_value.value.cstr = data.GetCStr(offset_ptr); break;
case DW_FORM_exprloc:
case DW_FORM_block: m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true; break;
case DW_FORM_block1: m_value.value.uval = data.GetU8(offset_ptr); is_block = true; break;
@@ -219,10 +215,12 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off
indirect = true;
break;
- case DW_FORM_sec_offset: assert(m_cu);
- m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break;
- case DW_FORM_flag_present: m_value.value.uval = 1; break;
- case DW_FORM_ref_sig8: m_value.value.uval = data.GetU64(offset_ptr); break;
+ case DW_FORM_sec_offset: assert(m_cu);
+ m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break;
+ case DW_FORM_flag_present: m_value.value.uval = 1; break;
+ case DW_FORM_ref_sig8: m_value.value.uval = data.GetU64(offset_ptr); break;
+ case DW_FORM_GNU_str_index: m_value.value.uval = data.GetULEB128(offset_ptr); break;
+ case DW_FORM_GNU_addr_index: m_value.value.uval = data.GetULEB128(offset_ptr); break;
default:
return false;
break;
@@ -322,6 +320,8 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d
case DW_FORM_sdata:
case DW_FORM_udata:
case DW_FORM_ref_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index:
debug_info_data.Skip_LEB128(offset_ptr);
return true;
@@ -342,7 +342,7 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d
void
-DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const
+DWARFFormValue::Dump(Stream &s) const
{
uint64_t uvalue = Unsigned();
bool cu_relative_offset = false;
@@ -353,13 +353,13 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const
{
case DW_FORM_addr: s.Address(uvalue, sizeof (uint64_t)); break;
case DW_FORM_flag:
- case DW_FORM_data1: s.PutHex8(uvalue); break;
+ case DW_FORM_data1: s.PutHex8(uvalue); break;
case DW_FORM_data2: s.PutHex16(uvalue); break;
case DW_FORM_sec_offset:
case DW_FORM_data4: s.PutHex32(uvalue); break;
case DW_FORM_ref_sig8:
case DW_FORM_data8: s.PutHex64(uvalue); break;
- case DW_FORM_string: s.QuotedCString(AsCString(NULL)); break;
+ case DW_FORM_string: s.QuotedCString(AsCString()); break;
case DW_FORM_exprloc:
case DW_FORM_block:
case DW_FORM_block1:
@@ -395,18 +395,18 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const
case DW_FORM_sdata: s.PutSLEB128(uvalue); break;
case DW_FORM_udata: s.PutULEB128(uvalue); break;
case DW_FORM_strp:
- if (debug_str_data)
{
- if (verbose)
- s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
-
- const char* dbg_str = AsCString(debug_str_data);
+ const char* dbg_str = AsCString();
if (dbg_str)
+ {
+ if (verbose)
+ s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
s.QuotedCString(dbg_str);
- }
- else
- {
- s.PutHex32(uvalue);
+ }
+ else
+ {
+ s.PutHex32(uvalue);
+ }
}
break;
@@ -444,13 +444,52 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const
}
const char*
-DWARFFormValue::AsCString(const DWARFDataExtractor* debug_str_data_ptr) const
+DWARFFormValue::AsCString() const
{
- if (IsInlinedCStr())
+ SymbolFileDWARF* symbol_file = m_cu->GetSymbolFileDWARF();
+
+ if (m_form == DW_FORM_string)
+ {
return m_value.value.cstr;
- else if (debug_str_data_ptr)
- return debug_str_data_ptr->PeekCStr(m_value.value.uval);
- return NULL;
+ }
+ else if (m_form == DW_FORM_strp)
+ {
+ if (!symbol_file)
+ return nullptr;
+
+ return symbol_file->get_debug_str_data().PeekCStr(m_value.value.uval);
+ }
+ else if (m_form == DW_FORM_GNU_str_index)
+ {
+ if (!symbol_file)
+ return nullptr;
+
+ uint32_t index_size = m_cu->IsDWARF64() ? 8 : 4;
+ lldb::offset_t offset = m_value.value.uval * index_size;
+ dw_offset_t str_offset = symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, index_size);
+ return symbol_file->get_debug_str_data().PeekCStr(str_offset);
+ }
+ return nullptr;
+}
+
+dw_addr_t
+DWARFFormValue::Address() const
+{
+ SymbolFileDWARF* symbol_file = m_cu->GetSymbolFileDWARF();
+
+ if (m_form == DW_FORM_addr)
+ return Unsigned();
+
+ assert(m_cu);
+ assert(m_form == DW_FORM_GNU_addr_index);
+
+ if (!symbol_file)
+ return 0;
+
+ uint32_t index_size = m_cu->GetAddressByteSize();
+ dw_offset_t addr_base = m_cu->GetAddrBase();
+ lldb::offset_t offset = addr_base + m_value.value.uval * index_size;
+ return symbol_file->get_debug_addr_data().GetMaxU64(&offset, index_size);
}
uint64_t
@@ -500,9 +539,7 @@ DWARFFormValue::Reference (dw_offset_t base_offset) const
const uint8_t*
DWARFFormValue::BlockData() const
{
- if (!IsInlinedCStr())
- return m_value.data;
- return NULL;
+ return m_value.data;
}
@@ -537,7 +574,8 @@ DWARFFormValue::IsDataForm(const dw_form_t form)
}
int
-DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFDataExtractor* debug_str_data_ptr)
+DWARFFormValue::Compare (const DWARFFormValue& a_value,
+ const DWARFFormValue& b_value)
{
dw_form_t a_form = a_value.Form();
dw_form_t b_form = b_value.Form();
@@ -558,6 +596,7 @@ DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_
case DW_FORM_sec_offset:
case DW_FORM_flag_present:
case DW_FORM_ref_sig8:
+ case DW_FORM_GNU_addr_index:
{
uint64_t a = a_value.Unsigned();
uint64_t b = b_value.Unsigned();
@@ -581,9 +620,10 @@ DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_
case DW_FORM_string:
case DW_FORM_strp:
+ case DW_FORM_GNU_str_index:
{
- const char *a_string = a_value.AsCString(debug_str_data_ptr);
- const char *b_string = b_value.AsCString(debug_str_data_ptr);
+ const char *a_string = a_value.AsCString();
+ const char *b_string = b_value.AsCString();
if (a_string == b_string)
return 0;
else if (a_string && b_string)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index 392df26..b10f4d3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -35,6 +35,34 @@ public:
} value;
const uint8_t* data;
} ValueType;
+
+ class FixedFormSizes
+ {
+ public:
+ FixedFormSizes() :
+ m_fix_sizes(nullptr), m_size(0)
+ {}
+
+ FixedFormSizes(const uint8_t* fix_sizes, size_t size) :
+ m_fix_sizes(fix_sizes), m_size(size)
+ {}
+
+ uint8_t
+ GetSize(uint32_t index) const
+ {
+ return index < m_size ? m_fix_sizes[index] : 0;
+ }
+
+ bool
+ Empty() const
+ {
+ return m_size == 0;
+ }
+
+ private:
+ const uint8_t* m_fix_sizes;
+ size_t m_size;
+ };
enum
{
@@ -52,10 +80,9 @@ public:
dw_form_t Form() const { return m_form; }
void SetForm(dw_form_t form) { m_form = form; }
const ValueType& Value() const { return m_value; }
- void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor* debug_str_data) const;
+ void Dump(lldb_private::Stream &s) const;
bool ExtractValue(const lldb_private::DWARFDataExtractor& data,
lldb::offset_t* offset_ptr);
- bool IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (const uint8_t*)m_value.value.cstr; }
const uint8_t* BlockData() const;
uint64_t Reference() const;
uint64_t Reference (dw_offset_t offset) const;
@@ -64,13 +91,16 @@ public:
void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; }
int64_t Signed() const { return m_value.value.sval; }
void SetSigned(int64_t sval) { m_value.value.sval = sval; }
- const char* AsCString(const lldb_private::DWARFDataExtractor* debug_str_data_ptr) const;
+ const char* AsCString() const;
+ dw_addr_t Address() const;
+ bool IsValid() const { return m_form != 0; }
bool SkipValue(const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr) const;
static bool SkipValue(const dw_form_t form, const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu);
static bool IsBlockForm(const dw_form_t form);
static bool IsDataForm(const dw_form_t form);
- static const uint8_t * GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64);
- static int Compare (const DWARFFormValue& a, const DWARFFormValue& b, const lldb_private::DWARFDataExtractor* debug_str_data_ptr);
+ static FixedFormSizes GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64);
+ static int Compare (const DWARFFormValue& a,
+ const DWARFFormValue& b);
protected:
const DWARFCompileUnit* m_cu; // Compile unit for this form
dw_form_t m_form; // Form for this value
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
deleted file mode 100644
index d79ae79..0000000
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-//===-- DWARFLocationDescription.cpp ----------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DWARFLocationDescription.h"
-#include "DWARFDefines.h"
-#include "lldb/lldb-private.h"
-#include "lldb/Core/Stream.h"
-
-
-using namespace lldb_private;
-
-static int print_dwarf_exp_op (Stream &s, const DWARFDataExtractor& data, lldb::offset_t *offset_ptr, int address_size, int dwarf_ref_size);
-
-int
-print_dwarf_expression (Stream &s,
- const DWARFDataExtractor& data,
- int address_size,
- int dwarf_ref_size,
- bool location_expression)
-{
- int op_count = 0;
- lldb::offset_t offset = 0;
- while (data.ValidOffset(offset))
- {
- if (location_expression && op_count > 0)
- {
- // err (baton, "Dwarf location expressions may only have one operand!");
- return 1;
- }
- if (op_count > 0)
- {
- s.PutCString(", ");
- }
- if (print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size) == 1)
- return 1;
- op_count++;
- }
-
- return 0;
-}
-
-static int
-print_dwarf_exp_op (Stream &s,
- const DWARFDataExtractor& data,
- lldb::offset_t *offset_ptr,
- int address_size,
- int dwarf_ref_size)
-{
- uint8_t opcode = data.GetU8(offset_ptr);
- DRC_class opcode_class;
- uint64_t uint;
- int64_t sint;
-
- int size;
-
- opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3);
-
- s.Printf("%s ", DW_OP_value_to_name (opcode));
-
- /* Does this take zero parameters? If so we can shortcut this function. */
- if (opcode_class == DRC_ZEROOPERANDS)
- return 0;
-
- if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx)
- {
- uint = data.GetULEB128(offset_ptr);
- sint = data.GetSLEB128(offset_ptr);
- s.Printf("%" PRIu64 " %" PRIi64, uint, sint);
- return 0;
- }
- if (opcode_class != DRC_ONEOPERAND)
- {
- s.Printf("UNKNOWN OP %u", opcode);
- return 1;
- }
-
- switch (opcode)
- {
- case DW_OP_addr: size = address_size; break;
- case DW_OP_const1u: size = 1; break;
- case DW_OP_const1s: size = -1; break;
- case DW_OP_const2u: size = 2; break;
- case DW_OP_const2s: size = -2; break;
- case DW_OP_const4u: size = 4; break;
- case DW_OP_const4s: size = -4; break;
- case DW_OP_const8u: size = 8; break;
- case DW_OP_const8s: size = -8; break;
- case DW_OP_constu: size = 128; break;
- case DW_OP_consts: size = -128; break;
- case DW_OP_fbreg: size = -128; break;
- case DW_OP_breg0:
- case DW_OP_breg1:
- case DW_OP_breg2:
- case DW_OP_breg3:
- case DW_OP_breg4:
- case DW_OP_breg5:
- case DW_OP_breg6:
- case DW_OP_breg7:
- case DW_OP_breg8:
- case DW_OP_breg9:
- case DW_OP_breg10:
- case DW_OP_breg11:
- case DW_OP_breg12:
- case DW_OP_breg13:
- case DW_OP_breg14:
- case DW_OP_breg15:
- case DW_OP_breg16:
- case DW_OP_breg17:
- case DW_OP_breg18:
- case DW_OP_breg19:
- case DW_OP_breg20:
- case DW_OP_breg21:
- case DW_OP_breg22:
- case DW_OP_breg23:
- case DW_OP_breg24:
- case DW_OP_breg25:
- case DW_OP_breg26:
- case DW_OP_breg27:
- case DW_OP_breg28:
- case DW_OP_breg29:
- case DW_OP_breg30:
- case DW_OP_breg31:
- size = -128; break;
- case DW_OP_pick:
- size = 1; break;
- case DW_OP_deref_size:
- size = 1; break;
- case DW_OP_xderef_size:
- size = 1; break;
- case DW_OP_plus_uconst:
- size = 128; break;
- case DW_OP_skip:
- size = -2; break;
- case DW_OP_bra:
- size = -2; break;
- case DW_OP_call2:
- size = 2; break;
- case DW_OP_call4:
- size = 4; break;
- case DW_OP_call_ref:
- size = dwarf_ref_size; break;
- case DW_OP_piece:
- size = 128; break;
- case DW_OP_regx:
- size = 128; break;
- default:
- s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
- return 1;
- }
-
- switch (size)
- {
- case -1: sint = (int8_t) data.GetU8(offset_ptr); s.Printf("%+" PRIi64, sint); break;
- case -2: sint = (int16_t) data.GetU16(offset_ptr); s.Printf("%+" PRIi64, sint); break;
- case -4: sint = (int32_t) data.GetU32(offset_ptr); s.Printf("%+" PRIi64, sint); break;
- case -8: sint = (int64_t) data.GetU64(offset_ptr); s.Printf("%+" PRIi64, sint); break;
- case -128: sint = data.GetSLEB128(offset_ptr); s.Printf("%+" PRIi64, sint); break;
- case 1: uint = data.GetU8(offset_ptr); s.Printf("0x%2.2" PRIx64, uint); break;
- case 2: uint = data.GetU16(offset_ptr); s.Printf("0x%4.4" PRIx64, uint); break;
- case 4: uint = data.GetU32(offset_ptr); s.Printf("0x%8.8" PRIx64, uint); break;
- case 8: uint = data.GetU64(offset_ptr); s.Printf("0x%16.16" PRIx64, uint); break;
- case 128: uint = data.GetULEB128(offset_ptr); s.Printf("0x%" PRIx64, uint); break;
- }
-
- return 0;
-}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
deleted file mode 100644
index 69cc0c1..0000000
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//===-- DWARFLocationDescription.h ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SymbolFileDWARF_DWARFLocationDescription_h_
-#define SymbolFileDWARF_DWARFLocationDescription_h_
-
-#include "SymbolFileDWARF.h"
-
-int
-print_dwarf_expression (lldb_private::Stream &s,
- const lldb_private::DWARFDataExtractor& data,
- int address_size,
- int dwarf_ref_size,
- bool location_expression);
-
-
-
-#endif // SymbolFileDWARF_DWARFLocationDescription_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
deleted file mode 100644
index 26768f0..0000000
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-//===-- DWARFLocationList.cpp -----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DWARFLocationList.h"
-
-#include "lldb/Core/Stream.h"
-
-#include "DWARFCompileUnit.h"
-#include "DWARFDebugInfo.h"
-#include "DWARFLocationDescription.h"
-
-using namespace lldb_private;
-
-dw_offset_t
-DWARFLocationList::Dump(Stream &s, const DWARFCompileUnit* cu, const DWARFDataExtractor& debug_loc_data, lldb::offset_t offset)
-{
- uint64_t start_addr, end_addr;
- uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu);
- s.SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu));
- dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
- while (debug_loc_data.ValidOffset(offset))
- {
- start_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
- end_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
-
- if (start_addr == 0 && end_addr == 0)
- break;
-
- s.PutCString("\n ");
- s.Indent();
- if (cu)
- s.AddressRange (start_addr + base_addr,
- end_addr + base_addr,
- cu->GetAddressByteSize(),
- NULL,
- ": ");
- uint32_t loc_length = debug_loc_data.GetU16(&offset);
-
- DWARFDataExtractor locationData(debug_loc_data, offset, loc_length);
- // if ( dump_flags & DWARFDebugInfo::eDumpFlag_Verbose ) *ostrm_ptr << " ( ";
- print_dwarf_expression (s, locationData, addr_size, 4, false);
- offset += loc_length;
- }
-
- return offset;
-}
-
-bool
-DWARFLocationList::Extract(const DWARFDataExtractor& debug_loc_data, lldb::offset_t* offset_ptr, DWARFDataExtractor& location_list_data)
-{
- // Initialize with no data just in case we don't find anything
- location_list_data.Clear();
-
- size_t loc_list_length = Size(debug_loc_data, *offset_ptr);
- if (loc_list_length > 0)
- {
- location_list_data.SetData(debug_loc_data, *offset_ptr, loc_list_length);
- *offset_ptr += loc_list_length;
- return true;
- }
-
- return false;
-}
-
-size_t
-DWARFLocationList::Size(const DWARFDataExtractor& debug_loc_data, lldb::offset_t offset)
-{
- const dw_offset_t debug_loc_offset = offset;
-
- while (debug_loc_data.ValidOffset(offset))
- {
- dw_addr_t start_addr = debug_loc_data.GetAddress(&offset);
- dw_addr_t end_addr = debug_loc_data.GetAddress(&offset);
-
- if (start_addr == 0 && end_addr == 0)
- break;
-
- uint16_t loc_length = debug_loc_data.GetU16(&offset);
- offset += loc_length;
- }
-
- if (offset > debug_loc_offset)
- return offset - debug_loc_offset;
- return 0;
-}
-
-
-
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
deleted file mode 100644
index 6dcc0d7..0000000
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===-- DWARFLocationList.h -------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SymbolFileDWARF_DWARFLocationList_h_
-#define SymbolFileDWARF_DWARFLocationList_h_
-
-#include "SymbolFileDWARF.h"
-
-class DWARFLocationList
-{
-public:
- static dw_offset_t
- Dump (lldb_private::Stream &s,
- const DWARFCompileUnit* cu,
- const lldb_private::DWARFDataExtractor& debug_loc_data,
- lldb::offset_t offset);
-
- static bool
- Extract (const lldb_private::DWARFDataExtractor& debug_loc_data,
- lldb::offset_t* offset_ptr,
- lldb_private::DWARFDataExtractor& location_list_data);
-
- static size_t
- Size (const lldb_private::DWARFDataExtractor& debug_loc_data,
- lldb::offset_t offset);
-
-};
-#endif // SymbolFileDWARF_DWARFLocationList_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
new file mode 100644
index 0000000..0db4160
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
@@ -0,0 +1,747 @@
+//===-- HashedNameToDIE.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "HashedNameToDIE.h"
+
+void
+DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array, DIEArray &die_offsets)
+{
+ const size_t count = die_info_array.size();
+ for (size_t i=0; i<count; ++i)
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+}
+
+void
+DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array,
+ const dw_tag_t tag,
+ DIEArray &die_offsets)
+{
+ if (tag == 0)
+ {
+ ExtractDIEArray (die_info_array, die_offsets);
+ }
+ else
+ {
+ const size_t count = die_info_array.size();
+ for (size_t i=0; i<count; ++i)
+ {
+ const dw_tag_t die_tag = die_info_array[i].tag;
+ bool tag_matches = die_tag == 0 || tag == die_tag;
+ if (!tag_matches)
+ {
+ if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
+ tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
+ }
+ if (tag_matches)
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+ }
+ }
+}
+
+void
+DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array,
+ const dw_tag_t tag,
+ const uint32_t qualified_name_hash,
+ DIEArray &die_offsets)
+{
+ if (tag == 0)
+ {
+ ExtractDIEArray (die_info_array, die_offsets);
+ }
+ else
+ {
+ const size_t count = die_info_array.size();
+ for (size_t i=0; i<count; ++i)
+ {
+ if (qualified_name_hash != die_info_array[i].qualified_name_hash)
+ continue;
+ const dw_tag_t die_tag = die_info_array[i].tag;
+ bool tag_matches = die_tag == 0 || tag == die_tag;
+ if (!tag_matches)
+ {
+ if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
+ tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
+ }
+ if (tag_matches)
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+ }
+ }
+}
+
+void
+DWARFMappedHash::ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
+ bool return_implementation_only_if_available,
+ DIEArray &die_offsets)
+{
+ const size_t count = die_info_array.size();
+ for (size_t i=0; i<count; ++i)
+ {
+ const dw_tag_t die_tag = die_info_array[i].tag;
+ if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
+ {
+ if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation)
+ {
+ if (return_implementation_only_if_available)
+ {
+ // We found the one true definition for this class, so
+ // only return that
+ die_offsets.clear();
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+ return;
+ }
+ else
+ {
+ // Put the one true definition as the first entry so it
+ // matches first
+ die_offsets.emplace(die_offsets.begin(), die_info_array[i].cu_offset, die_info_array[i].offset);
+ }
+ }
+ else
+ {
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+ }
+ }
+ }
+}
+
+void
+DWARFMappedHash::ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
+ uint32_t type_flag_mask,
+ uint32_t type_flag_value,
+ DIEArray &die_offsets)
+{
+ const size_t count = die_info_array.size();
+ for (size_t i=0; i<count; ++i)
+ {
+ if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value)
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+ }
+}
+
+const char *
+DWARFMappedHash::GetAtomTypeName (uint16_t atom)
+{
+ switch (atom)
+ {
+ case eAtomTypeNULL: return "NULL";
+ case eAtomTypeDIEOffset: return "die-offset";
+ case eAtomTypeCUOffset: return "cu-offset";
+ case eAtomTypeTag: return "die-tag";
+ case eAtomTypeNameFlags: return "name-flags";
+ case eAtomTypeTypeFlags: return "type-flags";
+ case eAtomTypeQualNameHash: return "qualified-name-hash";
+ }
+ return "<invalid>";
+}
+
+DWARFMappedHash::DIEInfo::DIEInfo () :
+ cu_offset (DW_INVALID_OFFSET),
+ offset (DW_INVALID_OFFSET),
+ tag (0),
+ type_flags (0),
+ qualified_name_hash (0)
+{
+}
+
+DWARFMappedHash::DIEInfo::DIEInfo (dw_offset_t c,
+ dw_offset_t o,
+ dw_tag_t t,
+ uint32_t f,
+ uint32_t h) :
+ cu_offset (c),
+ offset (o),
+ tag (t),
+ type_flags (f),
+ qualified_name_hash (h)
+{
+}
+
+DWARFMappedHash::Prologue::Prologue (dw_offset_t _die_base_offset) :
+ die_base_offset (_die_base_offset),
+ atoms(),
+ atom_mask (0),
+ min_hash_data_byte_size(0),
+ hash_data_has_fixed_byte_size(true)
+{
+ // Define an array of DIE offsets by first defining an array,
+ // and then define the atom type for the array, in this case
+ // we have an array of DIE offsets
+ AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
+}
+
+void
+DWARFMappedHash::Prologue::ClearAtoms ()
+{
+ hash_data_has_fixed_byte_size = true;
+ min_hash_data_byte_size = 0;
+ atom_mask = 0;
+ atoms.clear();
+}
+
+bool
+DWARFMappedHash::Prologue::ContainsAtom (AtomType atom_type) const
+{
+ return (atom_mask & (1u << atom_type)) != 0;
+}
+
+void
+DWARFMappedHash::Prologue::Clear ()
+{
+ die_base_offset = 0;
+ ClearAtoms ();
+}
+
+void
+DWARFMappedHash::Prologue::AppendAtom (AtomType type, dw_form_t form)
+{
+ atoms.push_back ({type, form});
+ atom_mask |= 1u << type;
+ switch (form)
+ {
+ case DW_FORM_indirect:
+ case DW_FORM_exprloc:
+ case DW_FORM_flag_present:
+ case DW_FORM_ref_sig8:
+ assert (!"Unhandled atom form");
+ break;
+
+ case DW_FORM_string:
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_sdata:
+ case DW_FORM_udata:
+ case DW_FORM_ref_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index:
+ hash_data_has_fixed_byte_size = false;
+ // Fall through to the cases below...
+ case DW_FORM_flag:
+ case DW_FORM_data1:
+ case DW_FORM_ref1:
+ case DW_FORM_sec_offset:
+ min_hash_data_byte_size += 1;
+ break;
+
+ case DW_FORM_block2:
+ hash_data_has_fixed_byte_size = false;
+ // Fall through to the cases below...
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ min_hash_data_byte_size += 2;
+ break;
+
+ case DW_FORM_block4:
+ hash_data_has_fixed_byte_size = false;
+ // Fall through to the cases below...
+ case DW_FORM_data4:
+ case DW_FORM_ref4:
+ case DW_FORM_addr:
+ case DW_FORM_ref_addr:
+ case DW_FORM_strp:
+ min_hash_data_byte_size += 4;
+ break;
+
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ min_hash_data_byte_size += 8;
+ break;
+
+ }
+}
+
+lldb::offset_t
+DWARFMappedHash::Prologue::Read (const lldb_private::DataExtractor &data,
+ lldb::offset_t offset)
+{
+ ClearAtoms ();
+
+ die_base_offset = data.GetU32 (&offset);
+
+ const uint32_t atom_count = data.GetU32 (&offset);
+ if (atom_count == 0x00060003u)
+ {
+ // Old format, deal with contents of old pre-release format
+ while (data.GetU32(&offset))
+ /* do nothing */;
+
+ // Hardcode to the only known value for now.
+ AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
+ }
+ else
+ {
+ for (uint32_t i=0; i<atom_count; ++i)
+ {
+ AtomType type = (AtomType)data.GetU16 (&offset);
+ dw_form_t form = (dw_form_t)data.GetU16 (&offset);
+ AppendAtom (type, form);
+ }
+ }
+ return offset;
+}
+
+size_t
+DWARFMappedHash::Prologue::GetByteSize () const
+{
+ // Add an extra count to the atoms size for the zero termination Atom that gets
+ // written to disk
+ return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom);
+}
+
+size_t
+DWARFMappedHash::Prologue::GetMinimumHashDataByteSize () const
+{
+ return min_hash_data_byte_size;
+}
+
+bool
+DWARFMappedHash::Prologue::HashDataHasFixedByteSize() const
+{
+ return hash_data_has_fixed_byte_size;
+}
+
+size_t
+DWARFMappedHash::Header::GetByteSize (const HeaderData &header_data)
+{
+ return header_data.GetByteSize();
+}
+
+lldb::offset_t
+DWARFMappedHash::Header::Read (lldb_private::DataExtractor &data, lldb::offset_t offset)
+{
+ offset = MappedHash::Header<Prologue>::Read (data, offset);
+ if (offset != UINT32_MAX)
+ {
+ offset = header_data.Read (data, offset);
+ }
+ return offset;
+}
+
+bool
+DWARFMappedHash::Header::Read (const lldb_private::DWARFDataExtractor &data,
+ lldb::offset_t *offset_ptr,
+ DIEInfo &hash_data) const
+{
+ const size_t num_atoms = header_data.atoms.size();
+ if (num_atoms == 0)
+ return false;
+
+ for (size_t i=0; i<num_atoms; ++i)
+ {
+ DWARFFormValue form_value (NULL, header_data.atoms[i].form);
+
+ if (!form_value.ExtractValue(data, offset_ptr))
+ return false;
+
+ switch (header_data.atoms[i].type)
+ {
+ case eAtomTypeDIEOffset: // DIE offset, check form for encoding
+ hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset);
+ break;
+
+ case eAtomTypeTag: // DW_TAG value for the DIE
+ hash_data.tag = (dw_tag_t)form_value.Unsigned ();
+
+ case eAtomTypeTypeFlags: // Flags from enum TypeFlags
+ hash_data.type_flags = (uint32_t)form_value.Unsigned ();
+ break;
+
+ case eAtomTypeQualNameHash: // Flags from enum TypeFlags
+ hash_data.qualified_name_hash = form_value.Unsigned ();
+ break;
+
+ default:
+ // We can always skip atoms we don't know about
+ break;
+ }
+ }
+ return true;
+}
+
+void
+DWARFMappedHash::Header::Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const
+{
+ const size_t num_atoms = header_data.atoms.size();
+ for (size_t i=0; i<num_atoms; ++i)
+ {
+ if (i > 0)
+ strm.PutCString (", ");
+
+ DWARFFormValue form_value (NULL, header_data.atoms[i].form);
+ switch (header_data.atoms[i].type)
+ {
+ case eAtomTypeDIEOffset: // DIE offset, check form for encoding
+ strm.Printf ("{0x%8.8x}", hash_data.offset);
+ break;
+
+ case eAtomTypeTag: // DW_TAG value for the DIE
+ {
+ const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag);
+ if (tag_cstr)
+ strm.PutCString (tag_cstr);
+ else
+ strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag);
+ }
+ break;
+
+ case eAtomTypeTypeFlags: // Flags from enum TypeFlags
+ strm.Printf ("0x%2.2x", hash_data.type_flags);
+ if (hash_data.type_flags)
+ {
+ strm.PutCString (" (");
+ if (hash_data.type_flags & eTypeFlagClassIsImplementation)
+ strm.PutCString (" implementation");
+ strm.PutCString (" )");
+ }
+ break;
+
+ case eAtomTypeQualNameHash: // Flags from enum TypeFlags
+ strm.Printf ("0x%8.8x", hash_data.qualified_name_hash);
+ break;
+
+ default:
+ strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type);
+ break;
+ }
+ }
+}
+
+DWARFMappedHash::MemoryTable::MemoryTable (lldb_private::DWARFDataExtractor &table_data,
+ const lldb_private::DWARFDataExtractor &string_table,
+ const char *name) :
+ MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data),
+ m_data (table_data),
+ m_string_table (string_table),
+ m_name (name)
+{
+}
+
+const char *
+DWARFMappedHash::MemoryTable::GetStringForKeyType (KeyType key) const
+{
+ // The key in the DWARF table is the .debug_str offset for the string
+ return m_string_table.PeekCStr (key);
+}
+
+bool
+DWARFMappedHash::MemoryTable::ReadHashData (uint32_t hash_data_offset, HashData &hash_data) const
+{
+ lldb::offset_t offset = hash_data_offset;
+ offset += 4; // Skip string table offset that contains offset of hash name in .debug_str
+ const uint32_t count = m_data.GetU32 (&offset);
+ if (count > 0)
+ {
+ hash_data.resize(count);
+ for (uint32_t i=0; i<count; ++i)
+ {
+ if (!m_header.Read(m_data, &offset, hash_data[i]))
+ return false;
+ }
+ }
+ else
+ hash_data.clear();
+ return true;
+}
+
+DWARFMappedHash::MemoryTable::Result
+DWARFMappedHash::MemoryTable::GetHashDataForName (const char *name,
+ lldb::offset_t* hash_data_offset_ptr,
+ Pair &pair) const
+{
+ pair.key = m_data.GetU32 (hash_data_offset_ptr);
+ pair.value.clear();
+
+ // If the key is zero, this terminates our chain of HashData objects
+ // for this hash value.
+ if (pair.key == 0)
+ return eResultEndOfHashData;
+
+ // There definitely should be a string for this string offset, if
+ // there isn't, there is something wrong, return and error
+ const char *strp_cstr = m_string_table.PeekCStr (pair.key);
+ if (strp_cstr == NULL)
+ {
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+
+ const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
+ const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
+ if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
+ {
+ // We have at least one HashData entry, and we have enough
+ // data to parse at least "count" HashData entries.
+
+ // First make sure the entire C string matches...
+ const bool match = strcmp (name, strp_cstr) == 0;
+
+ if (!match && m_header.header_data.HashDataHasFixedByteSize())
+ {
+ // If the string doesn't match and we have fixed size data,
+ // we can just add the total byte size of all HashData objects
+ // to the hash data offset and be done...
+ *hash_data_offset_ptr += min_total_hash_data_size;
+ }
+ else
+ {
+ // If the string does match, or we don't have fixed size data
+ // then we need to read the hash data as a stream. If the
+ // string matches we also append all HashData objects to the
+ // value array.
+ for (uint32_t i=0; i<count; ++i)
+ {
+ DIEInfo die_info;
+ if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
+ {
+ // Only happened if the HashData of the string matched...
+ if (match)
+ pair.value.push_back (die_info);
+ }
+ else
+ {
+ // Something went wrong while reading the data
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+ }
+ }
+ // Return the correct response depending on if the string matched
+ // or not...
+ if (match)
+ return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
+ else
+ return eResultKeyMismatch; // The key doesn't match, this function will get called
+ // again for the next key/value or the key terminator
+ // which in our case is a zero .debug_str offset.
+ }
+ else
+ {
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+}
+
+DWARFMappedHash::MemoryTable::Result
+DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression (
+ const lldb_private::RegularExpression& regex,
+ lldb::offset_t* hash_data_offset_ptr,
+ Pair &pair) const
+{
+ pair.key = m_data.GetU32 (hash_data_offset_ptr);
+ // If the key is zero, this terminates our chain of HashData objects
+ // for this hash value.
+ if (pair.key == 0)
+ return eResultEndOfHashData;
+
+ // There definitely should be a string for this string offset, if
+ // there isn't, there is something wrong, return and error
+ const char *strp_cstr = m_string_table.PeekCStr (pair.key);
+ if (strp_cstr == NULL)
+ return eResultError;
+
+ const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
+ const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
+ if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
+ {
+ const bool match = regex.Execute(strp_cstr);
+
+ if (!match && m_header.header_data.HashDataHasFixedByteSize())
+ {
+ // If the regex doesn't match and we have fixed size data,
+ // we can just add the total byte size of all HashData objects
+ // to the hash data offset and be done...
+ *hash_data_offset_ptr += min_total_hash_data_size;
+ }
+ else
+ {
+ // If the string does match, or we don't have fixed size data
+ // then we need to read the hash data as a stream. If the
+ // string matches we also append all HashData objects to the
+ // value array.
+ for (uint32_t i=0; i<count; ++i)
+ {
+ DIEInfo die_info;
+ if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
+ {
+ // Only happened if the HashData of the string matched...
+ if (match)
+ pair.value.push_back (die_info);
+ }
+ else
+ {
+ // Something went wrong while reading the data
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+ }
+ }
+ // Return the correct response depending on if the string matched
+ // or not...
+ if (match)
+ return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
+ else
+ return eResultKeyMismatch; // The key doesn't match, this function will get called
+ // again for the next key/value or the key terminator
+ // which in our case is a zero .debug_str offset.
+ }
+ else
+ {
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+}
+
+size_t
+DWARFMappedHash::MemoryTable::AppendAllDIEsThatMatchingRegex (
+ const lldb_private::RegularExpression& regex,
+ DIEInfoArray &die_info_array) const
+{
+ const uint32_t hash_count = m_header.hashes_count;
+ Pair pair;
+ for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
+ {
+ lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
+ while (hash_data_offset != UINT32_MAX)
+ {
+ const lldb::offset_t prev_hash_data_offset = hash_data_offset;
+ Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair);
+ if (prev_hash_data_offset == hash_data_offset)
+ break;
+
+ // Check the result of getting our hash data
+ switch (hash_result)
+ {
+ case eResultKeyMatch:
+ case eResultKeyMismatch:
+ // Whether we matches or not, it doesn't matter, we
+ // keep looking.
+ break;
+
+ case eResultEndOfHashData:
+ case eResultError:
+ hash_data_offset = UINT32_MAX;
+ break;
+ }
+ }
+ }
+ die_info_array.swap (pair.value);
+ return die_info_array.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::AppendAllDIEsInRange (const uint32_t die_offset_start,
+ const uint32_t die_offset_end,
+ DIEInfoArray &die_info_array) const
+{
+ const uint32_t hash_count = m_header.hashes_count;
+ for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
+ {
+ bool done = false;
+ lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
+ while (!done && hash_data_offset != UINT32_MAX)
+ {
+ KeyType key = m_data.GetU32 (&hash_data_offset);
+ // If the key is zero, this terminates our chain of HashData objects
+ // for this hash value.
+ if (key == 0)
+ break;
+
+ const uint32_t count = m_data.GetU32 (&hash_data_offset);
+ for (uint32_t i=0; i<count; ++i)
+ {
+ DIEInfo die_info;
+ if (m_header.Read(m_data, &hash_data_offset, die_info))
+ {
+ if (die_info.offset == 0)
+ done = true;
+ if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end)
+ die_info_array.push_back(die_info);
+ }
+ }
+ }
+ }
+ return die_info_array.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEArray &die_offsets)
+{
+ DIEInfoArray die_info_array;
+ if (FindByName(name, die_info_array))
+ DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets);
+ return die_info_array.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::FindByNameAndTag (const char *name,
+ const dw_tag_t tag,
+ DIEArray &die_offsets)
+{
+ DIEInfoArray die_info_array;
+ if (FindByName(name, die_info_array))
+ DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets);
+ return die_info_array.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::FindByNameAndTagAndQualifiedNameHash (const char *name,
+ const dw_tag_t tag,
+ const uint32_t qualified_name_hash,
+ DIEArray &die_offsets)
+{
+ DIEInfoArray die_info_array;
+ if (FindByName(name, die_info_array))
+ DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets);
+ return die_info_array.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::FindCompleteObjCClassByName (const char *name,
+ DIEArray &die_offsets,
+ bool must_be_implementation)
+{
+ DIEInfoArray die_info_array;
+ if (FindByName(name, die_info_array))
+ {
+ if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags))
+ {
+ // If we have two atoms, then we have the DIE offset and
+ // the type flags so we can find the objective C class
+ // efficiently.
+ DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array,
+ UINT32_MAX,
+ eTypeFlagClassIsImplementation,
+ die_offsets);
+ }
+ else
+ {
+ // We don't only want the one true definition, so try and see
+ // what we can find, and only return class or struct DIEs.
+ // If we do have the full implementation, then return it alone,
+ // else return all possible matches.
+ const bool return_implementation_only_if_available = true;
+ DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array,
+ return_implementation_only_if_available,
+ die_offsets);
+ }
+ }
+ return die_offsets.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEInfoArray &die_info_array)
+{
+ Pair kv_pair;
+ size_t old_size = die_info_array.size();
+ if (Find (name, kv_pair))
+ {
+ die_info_array.swap(kv_pair.value);
+ return die_info_array.size() - old_size;
+ }
+ return 0;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index f8a8cc6..bcde558 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -12,139 +12,36 @@
#include <vector>
-#include "DWARFDefines.h"
-#include "DWARFFormValue.h"
-
#include "lldb/lldb-defines.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/MappedHash.h"
+#include "DWARFDefines.h"
+#include "DWARFFormValue.h"
+#include "NameToDIE.h"
class SymbolFileDWARF;
class DWARFCompileUnit;
class DWARFDebugInfoEntry;
-struct DWARFMappedHash
+class DWARFMappedHash
{
- struct DIEInfo
- {
- dw_offset_t offset; // The DIE offset
- dw_tag_t tag;
- uint32_t type_flags; // Any flags for this DIEInfo
- uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name
-
- DIEInfo () :
- offset (DW_INVALID_OFFSET),
- tag (0),
- type_flags (0),
- qualified_name_hash (0)
- {
- }
-
- DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h) :
- offset(o),
- tag (t),
- type_flags (f),
- qualified_name_hash (h)
- {
- }
-
- void
- Clear()
- {
- offset = DW_INVALID_OFFSET;
- tag = 0;
- type_flags = 0;
- qualified_name_hash = 0;
- }
- };
-
- typedef std::vector<DIEInfo> DIEInfoArray;
- typedef std::vector<uint32_t> DIEArray;
-
- static void
- ExtractDIEArray (const DIEInfoArray &die_info_array,
- DIEArray &die_offsets)
- {
- const size_t count = die_info_array.size();
- for (size_t i=0; i<count; ++i)
- {
- die_offsets.push_back (die_info_array[i].offset);
- }
- }
-
- static void
- ExtractDIEArray (const DIEInfoArray &die_info_array,
- const dw_tag_t tag,
- DIEArray &die_offsets)
- {
- if (tag == 0)
- {
- ExtractDIEArray (die_info_array, die_offsets);
- }
- else
- {
- const size_t count = die_info_array.size();
- for (size_t i=0; i<count; ++i)
- {
- const dw_tag_t die_tag = die_info_array[i].tag;
- bool tag_matches = die_tag == 0 || tag == die_tag;
- if (!tag_matches)
- {
- if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
- tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
- }
- if (tag_matches)
- die_offsets.push_back (die_info_array[i].offset);
- }
- }
- }
-
- static void
- ExtractDIEArray (const DIEInfoArray &die_info_array,
- const dw_tag_t tag,
- const uint32_t qualified_name_hash,
- DIEArray &die_offsets)
- {
- if (tag == 0)
- {
- ExtractDIEArray (die_info_array, die_offsets);
- }
- else
- {
- const size_t count = die_info_array.size();
- for (size_t i=0; i<count; ++i)
- {
- if (qualified_name_hash != die_info_array[i].qualified_name_hash)
- continue;
- const dw_tag_t die_tag = die_info_array[i].tag;
- bool tag_matches = die_tag == 0 || tag == die_tag;
- if (!tag_matches)
- {
- if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
- tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
- }
- if (tag_matches)
- die_offsets.push_back (die_info_array[i].offset);
- }
- }
- }
-
- enum AtomType
+public:
+ enum AtomType : uint16_t
{
- eAtomTypeNULL = 0u,
- eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding
- eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that contains the item in question
- eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2
- eAtomTypeNameFlags = 4u, // Flags from enum NameFlags
- eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags,
+ eAtomTypeNULL = 0u,
+ eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding
+ eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that contains the item in question
+ eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2
+ eAtomTypeNameFlags = 4u, // Flags from enum NameFlags
+ eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags,
eAtomTypeQualNameHash = 6u // A 32 bit hash of the full qualified name (since all hash entries are basename only)
// For example a type like "std::vector<int>::iterator" would have a name of "iterator"
// and a 32 bit hash for "std::vector<int>::iterator" to allow us to not have to pull
// in debug info for a type when we know the fully qualified name.
};
-
+
// Bit definitions for the eAtomTypeTypeFlags flags
enum TypeFlags
{
@@ -152,782 +49,171 @@ struct DWARFMappedHash
// @implementation for class
eTypeFlagClassIsImplementation = ( 1u << 1 )
};
-
- static void
- ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
- bool return_implementation_only_if_available,
- DIEArray &die_offsets)
+ struct DIEInfo
{
- const size_t count = die_info_array.size();
- for (size_t i=0; i<count; ++i)
- {
- const dw_tag_t die_tag = die_info_array[i].tag;
- if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
- {
- if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation)
- {
- if (return_implementation_only_if_available)
- {
- // We found the one true definition for this class, so
- // only return that
- die_offsets.clear();
- die_offsets.push_back (die_info_array[i].offset);
- return;
- }
- else
- {
- // Put the one true definition as the first entry so it
- // matches first
- die_offsets.insert (die_offsets.begin(), die_info_array[i].offset);
- }
- }
- else
- {
- die_offsets.push_back (die_info_array[i].offset);
- }
- }
- }
- }
+ dw_offset_t cu_offset;
+ dw_offset_t offset; // The DIE offset
+ dw_tag_t tag;
+ uint32_t type_flags; // Any flags for this DIEInfo
+ uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name
- static void
- ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
- uint32_t type_flag_mask,
- uint32_t type_flag_value,
- DIEArray &die_offsets)
- {
- const size_t count = die_info_array.size();
- for (size_t i=0; i<count; ++i)
- {
- if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value)
- die_offsets.push_back (die_info_array[i].offset);
- }
- }
+ DIEInfo ();
+ DIEInfo (dw_offset_t c, dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h);
+ };
struct Atom
{
- uint16_t type;
+ AtomType type;
dw_form_t form;
-
- Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) :
- type (t),
- form (f)
- {
- }
};
-
+
+ typedef std::vector<DIEInfo> DIEInfoArray;
typedef std::vector<Atom> AtomArray;
-
- static uint32_t
- GetTypeFlags (SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry* die);
-
- static const char *
- GetAtomTypeName (uint16_t atom)
- {
- switch (atom)
- {
- case eAtomTypeNULL: return "NULL";
- case eAtomTypeDIEOffset: return "die-offset";
- case eAtomTypeCUOffset: return "cu-offset";
- case eAtomTypeTag: return "die-tag";
- case eAtomTypeNameFlags: return "name-flags";
- case eAtomTypeTypeFlags: return "type-flags";
- case eAtomTypeQualNameHash: return "qualified-name-hash";
- }
- return "<invalid>";
- }
- struct Prologue
+ class Prologue
{
- // DIE offset base so die offsets in hash_data can be CU relative
- dw_offset_t die_base_offset;
- AtomArray atoms;
- uint32_t atom_mask;
- size_t min_hash_data_byte_size;
- bool hash_data_has_fixed_byte_size;
-
- Prologue (dw_offset_t _die_base_offset = 0) :
- die_base_offset (_die_base_offset),
- atoms(),
- atom_mask (0),
- min_hash_data_byte_size(0),
- hash_data_has_fixed_byte_size(true)
- {
- // Define an array of DIE offsets by first defining an array,
- // and then define the atom type for the array, in this case
- // we have an array of DIE offsets
- AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
- }
-
- virtual ~Prologue()
- {
- }
+ public:
+ Prologue (dw_offset_t _die_base_offset = 0);
void
- ClearAtoms ()
- {
- hash_data_has_fixed_byte_size = true;
- min_hash_data_byte_size = 0;
- atom_mask = 0;
- atoms.clear();
- }
+ ClearAtoms ();
bool
- ContainsAtom (AtomType atom_type) const
- {
- return (atom_mask & (1u << atom_type)) != 0;
- }
-
- virtual void
- Clear ()
- {
- die_base_offset = 0;
- ClearAtoms ();
- }
-
+ ContainsAtom (AtomType atom_type) const;
+
void
- AppendAtom (AtomType type, dw_form_t form)
- {
- atoms.push_back (Atom(type, form));
- atom_mask |= 1u << type;
- switch (form)
- {
- case DW_FORM_indirect:
- case DW_FORM_exprloc:
- case DW_FORM_flag_present:
- case DW_FORM_ref_sig8:
- assert (!"Unhandled atom form");
- break;
-
- case DW_FORM_string:
- case DW_FORM_block:
- case DW_FORM_block1:
- case DW_FORM_sdata:
- case DW_FORM_udata:
- case DW_FORM_ref_udata:
- hash_data_has_fixed_byte_size = false;
- // Fall through to the cases below...
- case DW_FORM_flag:
- case DW_FORM_data1:
- case DW_FORM_ref1:
- case DW_FORM_sec_offset:
- min_hash_data_byte_size += 1;
- break;
-
- case DW_FORM_block2:
- hash_data_has_fixed_byte_size = false;
- // Fall through to the cases below...
- case DW_FORM_data2:
- case DW_FORM_ref2:
- min_hash_data_byte_size += 2;
- break;
-
- case DW_FORM_block4:
- hash_data_has_fixed_byte_size = false;
- // Fall through to the cases below...
- case DW_FORM_data4:
- case DW_FORM_ref4:
- case DW_FORM_addr:
- case DW_FORM_ref_addr:
- case DW_FORM_strp:
- min_hash_data_byte_size += 4;
- break;
-
- case DW_FORM_data8:
- case DW_FORM_ref8:
- min_hash_data_byte_size += 8;
- break;
-
- }
- }
-
-// void
-// Dump (std::ostream* ostrm_ptr);
-
+ Clear ();
+
+ void
+ AppendAtom (AtomType type, dw_form_t form);
+
lldb::offset_t
- Read (const lldb_private::DataExtractor &data,
- lldb::offset_t offset)
- {
- ClearAtoms ();
-
- die_base_offset = data.GetU32 (&offset);
-
- const uint32_t atom_count = data.GetU32 (&offset);
- if (atom_count == 0x00060003u)
- {
- // Old format, deal with contents of old pre-release format
- while (data.GetU32(&offset))
- /* do nothing */;
-
- // Hardcode to the only known value for now.
- AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
- }
- else
- {
- for (uint32_t i=0; i<atom_count; ++i)
- {
- AtomType type = (AtomType)data.GetU16 (&offset);
- dw_form_t form = (dw_form_t)data.GetU16 (&offset);
- AppendAtom (type, form);
- }
- }
- return offset;
- }
-
-// virtual void
-// Write (BinaryStreamBuf &s);
-
+ Read (const lldb_private::DataExtractor &data, lldb::offset_t offset);
+
size_t
- GetByteSize () const
- {
- // Add an extra count to the atoms size for the zero termination Atom that gets
- // written to disk
- return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom);
- }
-
+ GetByteSize () const;
+
size_t
- GetMinimumHashDataByteSize () const
- {
- return min_hash_data_byte_size;
- }
+ GetMinimumHashDataByteSize () const;
bool
- HashDataHasFixedByteSize() const
- {
- return hash_data_has_fixed_byte_size;
- }
+ HashDataHasFixedByteSize() const;
+
+ // DIE offset base so die offsets in hash_data can be CU relative
+ dw_offset_t die_base_offset;
+ AtomArray atoms;
+ uint32_t atom_mask;
+ size_t min_hash_data_byte_size;
+ bool hash_data_has_fixed_byte_size;
};
- struct Header : public MappedHash::Header<Prologue>
+ class Header : public MappedHash::Header<Prologue>
{
- Header (dw_offset_t _die_base_offset = 0)
- {
- }
-
- virtual
- ~Header()
- {
- }
-
- virtual size_t
- GetByteSize (const HeaderData &header_data)
- {
- return header_data.GetByteSize();
- }
-
- // virtual void
- // Dump (std::ostream* ostrm_ptr);
- //
- virtual lldb::offset_t
- Read (lldb_private::DataExtractor &data, lldb::offset_t offset)
- {
- offset = MappedHash::Header<Prologue>::Read (data, offset);
- if (offset != UINT32_MAX)
- {
- offset = header_data.Read (data, offset);
- }
- return offset;
- }
-
+ public:
+ size_t
+ GetByteSize (const HeaderData &header_data) override;
+
+ lldb::offset_t
+ Read (lldb_private::DataExtractor &data, lldb::offset_t offset) override;
+
bool
Read (const lldb_private::DWARFDataExtractor &data,
lldb::offset_t *offset_ptr,
- DIEInfo &hash_data) const
- {
- const size_t num_atoms = header_data.atoms.size();
- if (num_atoms == 0)
- return false;
-
- for (size_t i=0; i<num_atoms; ++i)
- {
- DWARFFormValue form_value (NULL, header_data.atoms[i].form);
-
- if (!form_value.ExtractValue(data, offset_ptr))
- return false;
-
- switch (header_data.atoms[i].type)
- {
- case eAtomTypeDIEOffset: // DIE offset, check form for encoding
- hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset);
- break;
-
- case eAtomTypeTag: // DW_TAG value for the DIE
- hash_data.tag = (dw_tag_t)form_value.Unsigned ();
-
- case eAtomTypeTypeFlags: // Flags from enum TypeFlags
- hash_data.type_flags = (uint32_t)form_value.Unsigned ();
- break;
-
- case eAtomTypeQualNameHash: // Flags from enum TypeFlags
- hash_data.qualified_name_hash = form_value.Unsigned ();
- break;
-
- default:
- // We can always skip atoms we don't know about
- break;
- }
- }
- return true;
- }
-
+ DIEInfo &hash_data) const;
+
void
- Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const
- {
- const size_t num_atoms = header_data.atoms.size();
- for (size_t i=0; i<num_atoms; ++i)
- {
- if (i > 0)
- strm.PutCString (", ");
-
- DWARFFormValue form_value (NULL, header_data.atoms[i].form);
- switch (header_data.atoms[i].type)
- {
- case eAtomTypeDIEOffset: // DIE offset, check form for encoding
- strm.Printf ("{0x%8.8x}", hash_data.offset);
- break;
-
- case eAtomTypeTag: // DW_TAG value for the DIE
- {
- const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag);
- if (tag_cstr)
- strm.PutCString (tag_cstr);
- else
- strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag);
- }
- break;
-
- case eAtomTypeTypeFlags: // Flags from enum TypeFlags
- strm.Printf ("0x%2.2x", hash_data.type_flags);
- if (hash_data.type_flags)
- {
- strm.PutCString (" (");
- if (hash_data.type_flags & eTypeFlagClassIsImplementation)
- strm.PutCString (" implementation");
- strm.PutCString (" )");
- }
- break;
-
- case eAtomTypeQualNameHash: // Flags from enum TypeFlags
- strm.Printf ("0x%8.8x", hash_data.qualified_name_hash);
- break;
-
- default:
- strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type);
- break;
- }
- }
- }
+ Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const;
};
-
-// class ExportTable
-// {
-// public:
-// ExportTable ();
-//
-// void
-// AppendNames (DWARFDebugPubnamesSet &pubnames_set,
-// StringTable &string_table);
-//
-// void
-// AppendNamesEntry (SymbolFileDWARF *dwarf2Data,
-// const DWARFCompileUnit* cu,
-// const DWARFDebugInfoEntry* die,
-// StringTable &string_table);
-//
-// void
-// AppendTypesEntry (DWARFData *dwarf2Data,
-// const DWARFCompileUnit* cu,
-// const DWARFDebugInfoEntry* die,
-// StringTable &string_table);
-//
-// size_t
-// Save (BinaryStreamBuf &names_data, const StringTable &string_table);
-//
-// void
-// AppendName (const char *name,
-// uint32_t die_offset,
-// StringTable &string_table,
-// dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied
-// void
-// AppendType (const char *name,
-// uint32_t die_offset,
-// StringTable &string_table);
-//
-//
-// protected:
-// struct Entry
-// {
-// uint32_t hash;
-// uint32_t str_offset;
-// uint32_t die_offset;
-// };
-//
-// // Map uniqued .debug_str offset to the corresponding DIE offsets
-// typedef std::map<uint32_t, DIEInfoArray> NameInfo;
-// // Map a name hash to one or more name infos
-// typedef std::map<uint32_t, NameInfo> BucketEntry;
-//
-// static uint32_t
-// GetByteSize (const NameInfo &name_info);
-//
-// typedef std::vector<BucketEntry> BucketEntryColl;
-// typedef std::vector<Entry> EntryColl;
-// EntryColl m_entries;
-//
-// };
-
-
+
// A class for reading and using a saved hash table from a block of data
// in memory
class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray>
{
public:
-
MemoryTable (lldb_private::DWARFDataExtractor &table_data,
const lldb_private::DWARFDataExtractor &string_table,
- const char *name) :
- MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data),
- m_data (table_data),
- m_string_table (string_table),
- m_name (name)
- {
- }
-
- virtual
- ~MemoryTable ()
- {
- }
-
- virtual const char *
- GetStringForKeyType (KeyType key) const
- {
- // The key in the DWARF table is the .debug_str offset for the string
- return m_string_table.PeekCStr (key);
- }
+ const char *name);
+
+ const char *
+ GetStringForKeyType (KeyType key) const override;
- virtual bool
- ReadHashData (uint32_t hash_data_offset,
- HashData &hash_data) const
- {
- lldb::offset_t offset = hash_data_offset;
- offset += 4; // Skip string table offset that contains offset of hash name in .debug_str
- const uint32_t count = m_data.GetU32 (&offset);
- if (count > 0)
- {
- hash_data.resize(count);
- for (uint32_t i=0; i<count; ++i)
- {
- if (!m_header.Read(m_data, &offset, hash_data[i]))
- return false;
- }
- }
- else
- hash_data.clear();
- return true;
- }
-
- virtual Result
- GetHashDataForName (const char *name,
- lldb::offset_t* hash_data_offset_ptr,
- Pair &pair) const
- {
- pair.key = m_data.GetU32 (hash_data_offset_ptr);
- pair.value.clear();
-
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
- if (pair.key == 0)
- return eResultEndOfHashData;
-
- // There definitely should be a string for this string offset, if
- // there isn't, there is something wrong, return and error
- const char *strp_cstr = m_string_table.PeekCStr (pair.key);
- if (strp_cstr == NULL)
- {
- *hash_data_offset_ptr = UINT32_MAX;
- return eResultError;
- }
-
- const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
- const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
- if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
- {
- // We have at least one HashData entry, and we have enough
- // data to parse at least "count" HashData entries.
-
- // First make sure the entire C string matches...
- const bool match = strcmp (name, strp_cstr) == 0;
-
- if (!match && m_header.header_data.HashDataHasFixedByteSize())
- {
- // If the string doesn't match and we have fixed size data,
- // we can just add the total byte size of all HashData objects
- // to the hash data offset and be done...
- *hash_data_offset_ptr += min_total_hash_data_size;
- }
- else
- {
- // If the string does match, or we don't have fixed size data
- // then we need to read the hash data as a stream. If the
- // string matches we also append all HashData objects to the
- // value array.
- for (uint32_t i=0; i<count; ++i)
- {
- DIEInfo die_info;
- if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
- {
- // Only happened if the HashData of the string matched...
- if (match)
- pair.value.push_back (die_info);
- }
- else
- {
- // Something went wrong while reading the data
- *hash_data_offset_ptr = UINT32_MAX;
- return eResultError;
- }
- }
- }
- // Return the correct response depending on if the string matched
- // or not...
- if (match)
- return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
- else
- return eResultKeyMismatch; // The key doesn't match, this function will get called
- // again for the next key/value or the key terminator
- // which in our case is a zero .debug_str offset.
- }
- else
- {
- *hash_data_offset_ptr = UINT32_MAX;
- return eResultError;
- }
- }
-
- virtual Result
- AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex,
- lldb::offset_t* hash_data_offset_ptr,
- Pair &pair) const
- {
- pair.key = m_data.GetU32 (hash_data_offset_ptr);
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
- if (pair.key == 0)
- return eResultEndOfHashData;
-
- // There definitely should be a string for this string offset, if
- // there isn't, there is something wrong, return and error
- const char *strp_cstr = m_string_table.PeekCStr (pair.key);
- if (strp_cstr == NULL)
- return eResultError;
-
- const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
- const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
- if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
- {
- const bool match = regex.Execute(strp_cstr);
-
- if (!match && m_header.header_data.HashDataHasFixedByteSize())
- {
- // If the regex doesn't match and we have fixed size data,
- // we can just add the total byte size of all HashData objects
- // to the hash data offset and be done...
- *hash_data_offset_ptr += min_total_hash_data_size;
- }
- else
- {
- // If the string does match, or we don't have fixed size data
- // then we need to read the hash data as a stream. If the
- // string matches we also append all HashData objects to the
- // value array.
- for (uint32_t i=0; i<count; ++i)
- {
- DIEInfo die_info;
- if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
- {
- // Only happened if the HashData of the string matched...
- if (match)
- pair.value.push_back (die_info);
- }
- else
- {
- // Something went wrong while reading the data
- *hash_data_offset_ptr = UINT32_MAX;
- return eResultError;
- }
- }
- }
- // Return the correct response depending on if the string matched
- // or not...
- if (match)
- return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
- else
- return eResultKeyMismatch; // The key doesn't match, this function will get called
- // again for the next key/value or the key terminator
- // which in our case is a zero .debug_str offset.
- }
- else
- {
- *hash_data_offset_ptr = UINT32_MAX;
- return eResultError;
- }
- }
+ bool
+ ReadHashData (uint32_t hash_data_offset, HashData &hash_data) const override;
size_t
AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex,
- DIEInfoArray &die_info_array) const
- {
- const uint32_t hash_count = m_header.hashes_count;
- Pair pair;
- for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
- {
- lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
- while (hash_data_offset != UINT32_MAX)
- {
- const lldb::offset_t prev_hash_data_offset = hash_data_offset;
- Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair);
- if (prev_hash_data_offset == hash_data_offset)
- break;
-
- // Check the result of getting our hash data
- switch (hash_result)
- {
- case eResultKeyMatch:
- case eResultKeyMismatch:
- // Whether we matches or not, it doesn't matter, we
- // keep looking.
- break;
-
- case eResultEndOfHashData:
- case eResultError:
- hash_data_offset = UINT32_MAX;
- break;
- }
- }
- }
- die_info_array.swap (pair.value);
- return die_info_array.size();
- }
-
+ DIEInfoArray &die_info_array) const;
+
size_t
AppendAllDIEsInRange (const uint32_t die_offset_start,
const uint32_t die_offset_end,
- DIEInfoArray &die_info_array) const
- {
- const uint32_t hash_count = m_header.hashes_count;
- for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
- {
- bool done = false;
- lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
- while (!done && hash_data_offset != UINT32_MAX)
- {
- KeyType key = m_data.GetU32 (&hash_data_offset);
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
- if (key == 0)
- break;
-
- const uint32_t count = m_data.GetU32 (&hash_data_offset);
- for (uint32_t i=0; i<count; ++i)
- {
- DIEInfo die_info;
- if (m_header.Read(m_data, &hash_data_offset, die_info))
- {
- if (die_info.offset == 0)
- done = true;
- if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end)
- die_info_array.push_back(die_info);
- }
- }
- }
- }
- return die_info_array.size();
- }
+ DIEInfoArray &die_info_array) const;
size_t
- FindByName (const char *name, DIEArray &die_offsets)
- {
- DIEInfoArray die_info_array;
- if (FindByName(name, die_info_array))
- DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets);
- return die_info_array.size();
- }
+ FindByName (const char *name, DIEArray &die_offsets);
size_t
- FindByNameAndTag (const char *name,
- const dw_tag_t tag,
- DIEArray &die_offsets)
- {
- DIEInfoArray die_info_array;
- if (FindByName(name, die_info_array))
- DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets);
- return die_info_array.size();
- }
+ FindByNameAndTag (const char *name, const dw_tag_t tag, DIEArray &die_offsets);
size_t
FindByNameAndTagAndQualifiedNameHash (const char *name,
const dw_tag_t tag,
const uint32_t qualified_name_hash,
- DIEArray &die_offsets)
- {
- DIEInfoArray die_info_array;
- if (FindByName(name, die_info_array))
- DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets);
- return die_info_array.size();
- }
+ DIEArray &die_offsets);
size_t
- FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation)
- {
- DIEInfoArray die_info_array;
- if (FindByName(name, die_info_array))
- {
- if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags))
- {
- // If we have two atoms, then we have the DIE offset and
- // the type flags so we can find the objective C class
- // efficiently.
- DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array,
- UINT32_MAX,
- eTypeFlagClassIsImplementation,
- die_offsets);
- }
- else
- {
- // We don't only want the one true definition, so try and see
- // what we can find, and only return class or struct DIEs.
- // If we do have the full implementation, then return it alone,
- // else return all possible matches.
- const bool return_implementation_only_if_available = true;
- DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array,
- return_implementation_only_if_available,
- die_offsets);
- }
- }
- return die_offsets.size();
- }
+ FindCompleteObjCClassByName (const char *name,
+ DIEArray &die_offsets,
+ bool must_be_implementation);
- size_t
- FindByName (const char *name, DIEInfoArray &die_info_array)
- {
- Pair kv_pair;
- size_t old_size = die_info_array.size();
- if (Find (name, kv_pair))
- {
- die_info_array.swap(kv_pair.value);
- return die_info_array.size() - old_size;
- }
- return 0;
- }
-
protected:
+ Result
+ AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex,
+ lldb::offset_t* hash_data_offset_ptr,
+ Pair &pair) const;
+
+ size_t
+ FindByName (const char *name, DIEInfoArray &die_info_array);
+
+ Result
+ GetHashDataForName (const char *name,
+ lldb::offset_t* hash_data_offset_ptr,
+ Pair &pair) const override;
+
const lldb_private::DWARFDataExtractor &m_data;
const lldb_private::DWARFDataExtractor &m_string_table;
std::string m_name;
};
-};
+ static void
+ ExtractDIEArray (const DIEInfoArray &die_info_array, DIEArray &die_offsets);
+
+protected:
+ static void
+ ExtractDIEArray (const DIEInfoArray &die_info_array,
+ const dw_tag_t tag,
+ DIEArray &die_offsets);
+
+ static void
+ ExtractDIEArray (const DIEInfoArray &die_info_array,
+ const dw_tag_t tag,
+ const uint32_t qualified_name_hash,
+ DIEArray &die_offsets);
+
+ static void
+ ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
+ bool return_implementation_only_if_available,
+ DIEArray &die_offsets);
+
+ static void
+ ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
+ uint32_t type_flag_mask,
+ uint32_t type_flag_value,
+ DIEArray &die_offsets);
+
+ static const char *
+ GetAtomTypeName (uint16_t atom);
+};
#endif // SymbolFileDWARF_HashedNameToDIE_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
index 2091a84..24fa7d1 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
@@ -1,4 +1,4 @@
-//===-- LogChannelDWARF.h --------------------------------------*- C++ -*-===//
+//===-- LogChannelDWARF.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,7 +13,6 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
-
// Project includes
#include "lldb/Core/Log.h"
@@ -34,8 +33,7 @@ class LogChannelDWARF : public lldb_private::LogChannel
public:
LogChannelDWARF ();
- virtual
- ~LogChannelDWARF ();
+ ~LogChannelDWARF() override;
static void
Initialize();
@@ -52,26 +50,26 @@ public:
static lldb_private::LogChannel *
CreateInstance ();
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
- virtual void
- Disable (const char** categories, lldb_private::Stream *feedback_strm);
+ void
+ Disable(const char** categories, lldb_private::Stream *feedback_strm) override;
void
Delete ();
- virtual bool
- Enable (lldb::StreamSP &log_stream_sp,
- uint32_t log_options,
- lldb_private::Stream *feedback_strm, // Feedback stream for argument errors etc
- const char **categories); // The categories to enable within this logging stream, if empty, enable default set
+ bool
+ Enable(lldb::StreamSP &log_stream_sp,
+ uint32_t log_options,
+ lldb_private::Stream *feedback_strm, // Feedback stream for argument errors etc
+ const char **categories) override; // The categories to enable within this logging stream, if empty, enable default set
- virtual void
- ListCategories (lldb_private::Stream *strm);
+ void
+ ListCategories(lldb_private::Stream *strm) override;
static lldb_private::Log *
GetLog ();
@@ -86,4 +84,4 @@ public:
LogIf (uint32_t mask, const char *format, ...);
};
-#endif // SymbolFileDWARF_LogChannelDWARF_h_
+#endif // SymbolFileDWARF_LogChannelDWARF_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
index c49237b..fe02adb 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -18,6 +18,7 @@
#include "DWARFDebugInfo.h"
#include "DWARFDebugInfoEntry.h"
#include "SymbolFileDWARF.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -29,9 +30,9 @@ NameToDIE::Finalize()
}
void
-NameToDIE::Insert (const ConstString& name, uint32_t die_offset)
+NameToDIE::Insert (const ConstString& name, const DIERef& die_ref)
{
- m_map.Append(name.GetCString(), die_offset);
+ m_map.Append(name.GetCString(), die_ref);
}
size_t
@@ -47,17 +48,15 @@ NameToDIE::Find (const RegularExpression& regex, DIEArray &info_array) const
}
size_t
-NameToDIE::FindAllEntriesForCompileUnit (uint32_t cu_offset,
- uint32_t cu_end_offset,
- DIEArray &info_array) const
+NameToDIE::FindAllEntriesForCompileUnit (dw_offset_t cu_offset, DIEArray &info_array) const
{
const size_t initial_size = info_array.size();
const uint32_t size = m_map.GetSize();
for (uint32_t i=0; i<size; ++i)
{
- const uint32_t die_offset = m_map.GetValueAtIndexUnchecked(i);
- if (cu_offset < die_offset && die_offset < cu_end_offset)
- info_array.push_back (die_offset);
+ const DIERef& die_ref = m_map.GetValueAtIndexUnchecked(i);
+ if (cu_offset == die_ref.cu_offset)
+ info_array.push_back (die_ref);
}
return info_array.size() - initial_size;
}
@@ -69,18 +68,29 @@ NameToDIE::Dump (Stream *s)
for (uint32_t i=0; i<size; ++i)
{
const char *cstr = m_map.GetCStringAtIndex(i);
- s->Printf("%p: {0x%8.8x} \"%s\"\n", (const void *)cstr, m_map.GetValueAtIndexUnchecked(i), cstr);
+ const DIERef& die_ref = m_map.GetValueAtIndexUnchecked(i);
+ s->Printf("%p: {0x%8.8x/0x%8.8x} \"%s\"\n", (const void*) cstr, die_ref.cu_offset, die_ref.die_offset, cstr);
}
}
void
-NameToDIE::ForEach (std::function <bool(const char *name, uint32_t die_offset)> const &callback) const
+NameToDIE::ForEach (std::function <bool(const char *name, const DIERef& die_ref)> const &callback) const
{
const uint32_t size = m_map.GetSize();
for (uint32_t i=0; i<size; ++i)
{
- if (!callback(m_map.GetCStringAtIndexUnchecked(i),
- m_map.GetValueAtIndexUnchecked (i)))
+ if (!callback(m_map.GetCStringAtIndexUnchecked(i), m_map.GetValueAtIndexUnchecked (i)))
break;
}
}
+
+void
+NameToDIE::Append (const NameToDIE& other)
+{
+ const uint32_t size = other.m_map.GetSize();
+ for (uint32_t i = 0; i < size; ++i)
+ {
+ m_map.Append(other.m_map.GetCStringAtIndexUnchecked (i),
+ other.m_map.GetValueAtIndexUnchecked (i));
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
index f9a1273..7fc6613 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -10,56 +10,53 @@
#ifndef SymbolFileDWARF_NameToDIE_h_
#define SymbolFileDWARF_NameToDIE_h_
-#include "lldb/Core/UniqueCStringMap.h"
-
#include <functional>
+#include "lldb/Core/dwarf.h"
+#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/lldb-defines.h"
+#include "DIERef.h"
class SymbolFileDWARF;
-typedef std::vector<uint32_t> DIEArray;
-
class NameToDIE
{
public:
- NameToDIE () :
+ NameToDIE () :
m_map()
{
}
-
+
~NameToDIE ()
{
}
-
+
void
Dump (lldb_private::Stream *s);
void
- Insert (const lldb_private::ConstString& name, uint32_t die_offset);
+ Insert (const lldb_private::ConstString& name, const DIERef& die_ref);
+
+ void
+ Append (const NameToDIE& other);
void
Finalize();
size_t
- Find (const lldb_private::ConstString &name,
- DIEArray &info_array) const;
+ Find (const lldb_private::ConstString &name, DIEArray &info_array) const;
size_t
- Find (const lldb_private::RegularExpression& regex,
- DIEArray &info_array) const;
+ Find (const lldb_private::RegularExpression& regex, DIEArray &info_array) const;
size_t
- FindAllEntriesForCompileUnit (uint32_t cu_offset,
- uint32_t cu_end_offset,
- DIEArray &info_array) const;
+ FindAllEntriesForCompileUnit (dw_offset_t cu_offset, DIEArray &info_array) const;
void
- ForEach (std::function <bool(const char *name, uint32_t die_offset)> const &callback) const;
+ ForEach (std::function <bool(const char *name, const DIERef& die_ref)> const &callback) const;
protected:
- lldb_private::UniqueCStringMap<uint32_t> m_map;
-
+ lldb_private::UniqueCStringMap<DIERef> m_map;
};
#endif // SymbolFileDWARF_NameToDIE_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index ea8aedc..2088864 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -10,20 +10,6 @@
#include "SymbolFileDWARF.h"
// Other libraries and framework includes
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclGroup.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/Specifiers.h"
-#include "clang/Sema/DeclSpec.h"
-
#include "llvm/Support/Casting.h"
#include "lldb/Core/ArchSpec.h"
@@ -39,34 +25,48 @@
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
+#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/OptionValueFileSpecList.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
+
#include "lldb/Symbol/Block.h"
-#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
+#include "lldb/Symbol/TypeMap.h"
+
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+
+#include "lldb/Target/Language.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/CPPLanguageRuntime.h"
+#include "lldb/Utility/TaskPool.h"
+#include "DWARFASTParser.h"
#include "DWARFCompileUnit.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
#include "DWARFDebugInfo.h"
-#include "DWARFDebugInfoEntry.h"
#include "DWARFDebugLine.h"
+#include "DWARFDebugMacro.h"
#include "DWARFDebugPubnames.h"
#include "DWARFDebugRanges.h"
#include "DWARFDeclContext.h"
#include "DWARFDIECollection.h"
#include "DWARFFormValue.h"
-#include "DWARFLocationList.h"
#include "LogChannelDWARF.h"
+#include "SymbolFileDWARFDwo.h"
#include "SymbolFileDWARFDebugMap.h"
#include <map>
@@ -83,8 +83,6 @@
#define DEBUG_PRINTF(fmt, ...)
#endif
-#define DIE_IS_BEING_PARSED ((lldb_private::Type*)1)
-
using namespace lldb;
using namespace lldb_private;
@@ -105,18 +103,58 @@ using namespace lldb_private;
// return false;
//}
//
-static AccessType
-DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility)
-{
- switch (dwarf_accessibility)
+
+namespace {
+
+ PropertyDefinition
+ g_properties[] =
+ {
+ { "comp-dir-symlink-paths" , OptionValue::eTypeFileSpecList, true, 0 , nullptr, nullptr, "If the DW_AT_comp_dir matches any of these paths the symbolic links will be resolved at DWARF parse time." },
+ { nullptr , OptionValue::eTypeInvalid , false, 0, nullptr, nullptr, nullptr }
+ };
+
+ enum
+ {
+ ePropertySymLinkPaths
+ };
+
+
+ class PluginProperties : public Properties
+ {
+ public:
+ static ConstString
+ GetSettingName()
+ {
+ return SymbolFileDWARF::GetPluginNameStatic();
+ }
+
+ PluginProperties()
+ {
+ m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
+ m_collection_sp->Initialize(g_properties);
+ }
+
+ FileSpecList&
+ GetSymLinkPaths()
+ {
+ OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, true, ePropertySymLinkPaths);
+ assert(option_value);
+ return option_value->GetCurrentValue();
+ }
+
+ };
+
+ typedef std::shared_ptr<PluginProperties> SymbolFileDWARFPropertiesSP;
+
+ static const SymbolFileDWARFPropertiesSP&
+ GetGlobalPluginProperties()
{
- case DW_ACCESS_public: return eAccessPublic;
- case DW_ACCESS_private: return eAccessPrivate;
- case DW_ACCESS_protected: return eAccessProtected;
- default: break;
+ static const auto g_settings_sp(std::make_shared<PluginProperties>());
+ return g_settings_sp;
}
- return eAccessNone;
-}
+
+} // anonymous namespace end
+
static const char*
removeHostnameFromPathname(const char* path_from_dwarf)
@@ -125,9 +163,15 @@ removeHostnameFromPathname(const char* path_from_dwarf)
{
return path_from_dwarf;
}
-
+
const char *colon_pos = strchr(path_from_dwarf, ':');
- if (!colon_pos)
+ if (nullptr == colon_pos)
+ {
+ return path_from_dwarf;
+ }
+
+ const char *slash_pos = strchr(path_from_dwarf, '/');
+ if (slash_pos && (slash_pos < colon_pos))
{
return path_from_dwarf;
}
@@ -142,89 +186,42 @@ removeHostnameFromPathname(const char* path_from_dwarf)
{
return path_from_dwarf;
}
-
+
return colon_pos + 1;
}
-#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
-
-class DIEStack
+static const char*
+resolveCompDir(const char* path_from_dwarf)
{
-public:
-
- void Push (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
- {
- m_dies.push_back (DIEInfo(cu, die));
- }
+ if (!path_from_dwarf)
+ return nullptr;
-
- void LogDIEs (Log *log, SymbolFileDWARF *dwarf)
- {
- StreamString log_strm;
- const size_t n = m_dies.size();
- log_strm.Printf("DIEStack[%" PRIu64 "]:\n", (uint64_t)n);
- for (size_t i=0; i<n; i++)
- {
- DWARFCompileUnit *cu = m_dies[i].cu;
- const DWARFDebugInfoEntry *die = m_dies[i].die;
- std::string qualified_name;
- die->GetQualifiedName(dwarf, cu, qualified_name);
- log_strm.Printf ("[%" PRIu64 "] 0x%8.8x: %s name='%s'\n",
- (uint64_t)i,
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- qualified_name.c_str());
- }
- log->PutCString(log_strm.GetData());
- }
- void Pop ()
- {
- m_dies.pop_back();
- }
-
- class ScopedPopper
- {
- public:
- ScopedPopper (DIEStack &die_stack) :
- m_die_stack (die_stack),
- m_valid (false)
- {
- }
-
- void
- Push (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
- {
- m_valid = true;
- m_die_stack.Push (cu, die);
- }
-
- ~ScopedPopper ()
- {
- if (m_valid)
- m_die_stack.Pop();
- }
-
-
-
- protected:
- DIEStack &m_die_stack;
- bool m_valid;
- };
+ // DWARF2/3 suggests the form hostname:pathname for compilation directory.
+ // Remove the host part if present.
+ const char* local_path = removeHostnameFromPathname(path_from_dwarf);
+ if (!local_path)
+ return nullptr;
+
+ bool is_symlink = false;
+ FileSpec local_path_spec(local_path, false);
+ const auto& file_specs = GetGlobalPluginProperties()->GetSymLinkPaths();
+ for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i)
+ is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i), local_path_spec, true);
+
+ if (!is_symlink)
+ return local_path;
+
+ if (!local_path_spec.IsSymbolicLink())
+ return local_path;
+
+ FileSpec resolved_local_path_spec;
+ const auto error = FileSystem::Readlink(local_path_spec, resolved_local_path_spec);
+ if (error.Success())
+ return resolved_local_path_spec.GetCString();
+
+ return nullptr;
+}
-protected:
- struct DIEInfo {
- DIEInfo (DWARFCompileUnit *c, const DWARFDebugInfoEntry *d) :
- cu(c),
- die(d)
- {
- }
- DWARFCompileUnit *cu;
- const DWARFDebugInfoEntry *die;
- };
- typedef std::vector<DIEInfo> Stack;
- Stack m_dies;
-};
-#endif
void
SymbolFileDWARF::Initialize()
@@ -232,7 +229,21 @@ SymbolFileDWARF::Initialize()
LogChannelDWARF::Initialize();
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
- CreateInstance);
+ CreateInstance,
+ DebuggerInitialize);
+}
+
+void
+SymbolFileDWARF::DebuggerInitialize(Debugger &debugger)
+{
+ if (!PluginManager::GetSettingForSymbolFilePlugin(debugger, PluginProperties::GetSettingName()))
+ {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForSymbolFilePlugin(debugger,
+ GetGlobalPluginProperties()->GetValueProperties(),
+ ConstString ("Properties for the dwarf symbol-file plug-in."),
+ is_global_setting);
+ }
}
void
@@ -272,65 +283,61 @@ SymbolFileDWARF::GetTypeList ()
}
void
-SymbolFileDWARF::GetTypes (DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry *die,
+SymbolFileDWARF::GetTypes (const DWARFDIE &die,
dw_offset_t min_die_offset,
dw_offset_t max_die_offset,
uint32_t type_mask,
TypeSet &type_set)
{
- if (cu)
+ if (die)
{
- if (die)
+ const dw_offset_t die_offset = die.GetOffset();
+
+ if (die_offset >= max_die_offset)
+ return;
+
+ if (die_offset >= min_die_offset)
{
- const dw_offset_t die_offset = die->GetOffset();
+ const dw_tag_t tag = die.Tag();
- if (die_offset >= max_die_offset)
- return;
-
- if (die_offset >= min_die_offset)
- {
- const dw_tag_t tag = die->Tag();
-
- bool add_type = false;
+ bool add_type = false;
- switch (tag)
- {
- case DW_TAG_array_type: add_type = (type_mask & eTypeClassArray ) != 0; break;
- case DW_TAG_unspecified_type:
- case DW_TAG_base_type: add_type = (type_mask & eTypeClassBuiltin ) != 0; break;
- case DW_TAG_class_type: add_type = (type_mask & eTypeClassClass ) != 0; break;
- case DW_TAG_structure_type: add_type = (type_mask & eTypeClassStruct ) != 0; break;
- case DW_TAG_union_type: add_type = (type_mask & eTypeClassUnion ) != 0; break;
- case DW_TAG_enumeration_type: add_type = (type_mask & eTypeClassEnumeration ) != 0; break;
- case DW_TAG_subroutine_type:
- case DW_TAG_subprogram:
- case DW_TAG_inlined_subroutine: add_type = (type_mask & eTypeClassFunction ) != 0; break;
- case DW_TAG_pointer_type: add_type = (type_mask & eTypeClassPointer ) != 0; break;
- case DW_TAG_rvalue_reference_type:
- case DW_TAG_reference_type: add_type = (type_mask & eTypeClassReference ) != 0; break;
- case DW_TAG_typedef: add_type = (type_mask & eTypeClassTypedef ) != 0; break;
- case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer ) != 0; break;
- }
+ switch (tag)
+ {
+ case DW_TAG_array_type: add_type = (type_mask & eTypeClassArray ) != 0; break;
+ case DW_TAG_unspecified_type:
+ case DW_TAG_base_type: add_type = (type_mask & eTypeClassBuiltin ) != 0; break;
+ case DW_TAG_class_type: add_type = (type_mask & eTypeClassClass ) != 0; break;
+ case DW_TAG_structure_type: add_type = (type_mask & eTypeClassStruct ) != 0; break;
+ case DW_TAG_union_type: add_type = (type_mask & eTypeClassUnion ) != 0; break;
+ case DW_TAG_enumeration_type: add_type = (type_mask & eTypeClassEnumeration ) != 0; break;
+ case DW_TAG_subroutine_type:
+ case DW_TAG_subprogram:
+ case DW_TAG_inlined_subroutine: add_type = (type_mask & eTypeClassFunction ) != 0; break;
+ case DW_TAG_pointer_type: add_type = (type_mask & eTypeClassPointer ) != 0; break;
+ case DW_TAG_rvalue_reference_type:
+ case DW_TAG_reference_type: add_type = (type_mask & eTypeClassReference ) != 0; break;
+ case DW_TAG_typedef: add_type = (type_mask & eTypeClassTypedef ) != 0; break;
+ case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer ) != 0; break;
+ }
- if (add_type)
+ if (add_type)
+ {
+ const bool assert_not_being_parsed = true;
+ Type *type = ResolveTypeUID (die, assert_not_being_parsed);
+ if (type)
{
- const bool assert_not_being_parsed = true;
- Type *type = ResolveTypeUID (cu, die, assert_not_being_parsed);
- if (type)
- {
- if (type_set.find(type) == type_set.end())
- type_set.insert(type);
- }
+ if (type_set.find(type) == type_set.end())
+ type_set.insert(type);
}
}
-
- for (const DWARFDebugInfoEntry *child_die = die->GetFirstChild();
- child_die != NULL;
- child_die = child_die->GetSibling())
- {
- GetTypes (cu, child_die, min_die_offset, max_die_offset, type_mask, type_set);
- }
+ }
+
+ for (DWARFDIE child_die = die.GetFirstChild();
+ child_die.IsValid();
+ child_die = child_die.GetSibling())
+ {
+ GetTypes (child_die, min_die_offset, max_die_offset, type_mask, type_set);
}
}
}
@@ -353,8 +360,7 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,
dwarf_cu = GetDWARFCompileUnit(comp_unit);
if (dwarf_cu == 0)
return 0;
- GetTypes (dwarf_cu,
- dwarf_cu->DIE(),
+ GetTypes (dwarf_cu->DIE(),
dwarf_cu->GetOffset(),
dwarf_cu->GetNextCompileUnitOffset(),
type_mask,
@@ -371,8 +377,7 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,
dwarf_cu = info->GetCompileUnitAtIndex(cu_idx);
if (dwarf_cu)
{
- GetTypes (dwarf_cu,
- dwarf_cu->DIE(),
+ GetTypes (dwarf_cu->DIE(),
0,
UINT32_MAX,
type_mask,
@@ -381,76 +386,15 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,
}
}
}
-// if (m_using_apple_tables)
-// {
-// DWARFMappedHash::MemoryTable *apple_types = m_apple_types_ap.get();
-// if (apple_types)
-// {
-// apple_types->ForEach([this, &type_set, apple_types, type_mask](const DWARFMappedHash::DIEInfoArray &die_info_array) -> bool {
-//
-// for (auto die_info: die_info_array)
-// {
-// bool add_type = TagMatchesTypeMask (type_mask, 0);
-// if (!add_type)
-// {
-// dw_tag_t tag = die_info.tag;
-// if (tag == 0)
-// {
-// const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_info.offset, NULL);
-// tag = die->Tag();
-// }
-// add_type = TagMatchesTypeMask (type_mask, tag);
-// }
-// if (add_type)
-// {
-// Type *type = ResolveTypeUID(die_info.offset);
-//
-// if (type_set.find(type) == type_set.end())
-// type_set.insert(type);
-// }
-// }
-// return true; // Keep iterating
-// });
-// }
-// }
-// else
-// {
-// if (!m_indexed)
-// Index ();
-//
-// m_type_index.ForEach([this, &type_set, type_mask](const char *name, uint32_t die_offset) -> bool {
-//
-// bool add_type = TagMatchesTypeMask (type_mask, 0);
-//
-// if (!add_type)
-// {
-// const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_offset, NULL);
-// if (die)
-// {
-// const dw_tag_t tag = die->Tag();
-// add_type = TagMatchesTypeMask (type_mask, tag);
-// }
-// }
-//
-// if (add_type)
-// {
-// Type *type = ResolveTypeUID(die_offset);
-//
-// if (type_set.find(type) == type_set.end())
-// type_set.insert(type);
-// }
-// return true; // Keep iterating
-// });
-// }
-
- std::set<ClangASTType> clang_type_set;
+
+ std::set<CompilerType> compiler_type_set;
size_t num_types_added = 0;
for (Type *type : type_set)
{
- ClangASTType clang_type = type->GetClangForwardType();
- if (clang_type_set.find(clang_type) == clang_type_set.end())
+ CompilerType compiler_type = type->GetForwardCompilerType ();
+ if (compiler_type_set.find(compiler_type) == compiler_type_set.end())
{
- clang_type_set.insert(clang_type);
+ compiler_type_set.insert(compiler_type);
type_list.Insert (type->shared_from_this());
++num_types_added;
}
@@ -463,13 +407,13 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,
// Gets the first parent that is a lexical block, function or inlined
// subroutine, or compile unit.
//----------------------------------------------------------------------
-static const DWARFDebugInfoEntry *
-GetParentSymbolContextDIE(const DWARFDebugInfoEntry *child_die)
+DWARFDIE
+SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die)
{
- const DWARFDebugInfoEntry *die;
- for (die = child_die->GetParent(); die != NULL; die = die->GetParent())
+ DWARFDIE die;
+ for (die = child_die.GetParent(); die; die = die.GetParent())
{
- dw_tag_t tag = die->Tag();
+ dw_tag_t tag = die.Tag();
switch (tag)
{
@@ -480,7 +424,7 @@ GetParentSymbolContextDIE(const DWARFDebugInfoEntry *child_die)
return die;
}
}
- return NULL;
+ return DWARFDIE();
}
@@ -489,13 +433,12 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
UserID (0), // Used by SymbolFileDWARFDebugMap to when this class parses .o files to contain the .o file index/ID
m_debug_map_module_wp (),
m_debug_map_symfile (NULL),
- m_clang_tu_decl (NULL),
- m_flags(),
m_data_debug_abbrev (),
m_data_debug_aranges (),
m_data_debug_frame (),
m_data_debug_info (),
m_data_debug_line (),
+ m_data_debug_macro (),
m_data_debug_loc (),
m_data_debug_ranges (),
m_data_debug_str (),
@@ -518,7 +461,6 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
m_type_index(),
m_namespace_index(),
m_indexed (false),
- m_is_external_ast_source (false),
m_using_apple_tables (false),
m_fetched_external_modules (false),
m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate),
@@ -529,12 +471,6 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
SymbolFileDWARF::~SymbolFileDWARF()
{
- if (m_is_external_ast_source)
- {
- ModuleSP module_sp (m_obj_file->GetModule());
- if (module_sp)
- module_sp->GetClangASTContext().RemoveExternalSource ();
- }
}
static const ConstString &
@@ -552,36 +488,31 @@ SymbolFileDWARF::GetUniqueDWARFASTTypeMap ()
return m_unique_ast_type_map;
}
-ClangASTContext &
-SymbolFileDWARF::GetClangASTContext ()
+TypeSystem *
+SymbolFileDWARF::GetTypeSystemForLanguage (LanguageType language)
{
- if (GetDebugMapSymfile ())
- return m_debug_map_symfile->GetClangASTContext ();
-
- ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext();
- if (!m_is_external_ast_source)
+ SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile ();
+ TypeSystem *type_system;
+ if (debug_map_symfile)
+ {
+ type_system = debug_map_symfile->GetTypeSystemForLanguage(language);
+ }
+ else
{
- m_is_external_ast_source = true;
- llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap (
- new ClangExternalASTSourceCallbacks (SymbolFileDWARF::CompleteTagDecl,
- SymbolFileDWARF::CompleteObjCInterfaceDecl,
- SymbolFileDWARF::FindExternalVisibleDeclsByName,
- SymbolFileDWARF::LayoutRecordType,
- this));
- ast.SetExternalSource (ast_source_ap);
+ type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
+ if (type_system)
+ type_system->SetSymbolFile(this);
}
- return ast;
+ return type_system;
}
void
SymbolFileDWARF::InitializeObject()
{
- // Install our external AST source callbacks so we can complete Clang types.
ModuleSP module_sp (m_obj_file->GetModule());
if (module_sp)
{
const SectionList *section_list = module_sp->GetSectionList();
-
const Section* section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get();
// Memory map the DWARF mach-o segment so we have everything mmap'ed
@@ -589,19 +520,24 @@ SymbolFileDWARF::InitializeObject()
if (section)
m_obj_file->MemoryMapSectionData(section, m_dwarf_data);
}
+
get_apple_names_data();
- if (m_data_apple_names.GetByteSize() > 0)
+ if (m_data_apple_names.m_data.GetByteSize() > 0)
{
- m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names, get_debug_str_data(), ".apple_names"));
+ m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names.m_data,
+ get_debug_str_data(),
+ ".apple_names"));
if (m_apple_names_ap->IsValid())
m_using_apple_tables = true;
else
m_apple_names_ap.reset();
}
get_apple_types_data();
- if (m_data_apple_types.GetByteSize() > 0)
+ if (m_data_apple_types.m_data.GetByteSize() > 0)
{
- m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types, get_debug_str_data(), ".apple_types"));
+ m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types.m_data,
+ get_debug_str_data(),
+ ".apple_types"));
if (m_apple_types_ap->IsValid())
m_using_apple_tables = true;
else
@@ -609,9 +545,11 @@ SymbolFileDWARF::InitializeObject()
}
get_apple_namespaces_data();
- if (m_data_apple_namespaces.GetByteSize() > 0)
+ if (m_data_apple_namespaces.m_data.GetByteSize() > 0)
{
- m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces, get_debug_str_data(), ".apple_namespaces"));
+ m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces.m_data,
+ get_debug_str_data(),
+ ".apple_namespaces"));
if (m_apple_namespaces_ap->IsValid())
m_using_apple_tables = true;
else
@@ -619,9 +557,11 @@ SymbolFileDWARF::InitializeObject()
}
get_apple_objc_data();
- if (m_data_apple_objc.GetByteSize() > 0)
+ if (m_data_apple_objc.m_data.GetByteSize() > 0)
{
- m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc, get_debug_str_data(), ".apple_objc"));
+ m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc.m_data,
+ get_debug_str_data(),
+ ".apple_objc"));
if (m_apple_objc_ap->IsValid())
m_using_apple_tables = true;
else
@@ -663,46 +603,10 @@ SymbolFileDWARF::CalculateAbilities ()
section = section_list->FindSectionByType (eSectionTypeDWARFDebugAbbrev, true).get();
if (section)
debug_abbrev_file_size = section->GetFileSize();
- else
- m_flags.Set (flagsGotDebugAbbrevData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugAranges, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugArangesData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugFrame, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugFrameData);
section = section_list->FindSectionByType (eSectionTypeDWARFDebugLine, true).get();
if (section)
debug_line_file_size = section->GetFileSize();
- else
- m_flags.Set (flagsGotDebugLineData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugLoc, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugLocData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugMacInfo, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugMacInfoData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubNames, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugPubNamesData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubTypes, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugPubTypesData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugRanges, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugRangesData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugStr, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugStrData);
}
else
{
@@ -737,104 +641,128 @@ SymbolFileDWARF::CalculateAbilities ()
}
const DWARFDataExtractor&
-SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type, DWARFDataExtractor &data)
+SymbolFileDWARF::GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment)
{
- if (m_flags.IsClear (got_flag))
+ std::call_once(data_segment.m_flag,
+ &SymbolFileDWARF::LoadSectionData,
+ this,
+ sect_type,
+ std::ref(data_segment.m_data));
+ return data_segment.m_data;
+}
+
+void
+SymbolFileDWARF::LoadSectionData (lldb::SectionType sect_type, DWARFDataExtractor& data)
+{
+ ModuleSP module_sp (m_obj_file->GetModule());
+ const SectionList *section_list = module_sp->GetSectionList();
+ if (section_list)
{
- ModuleSP module_sp (m_obj_file->GetModule());
- m_flags.Set (got_flag);
- const SectionList *section_list = module_sp->GetSectionList();
- if (section_list)
+ SectionSP section_sp (section_list->FindSectionByType(sect_type, true));
+ if (section_sp)
{
- SectionSP section_sp (section_list->FindSectionByType(sect_type, true));
- if (section_sp)
+ // See if we memory mapped the DWARF segment?
+ if (m_dwarf_data.GetByteSize())
{
- // See if we memory mapped the DWARF segment?
- if (m_dwarf_data.GetByteSize())
- {
- data.SetData(m_dwarf_data, section_sp->GetOffset (), section_sp->GetFileSize());
- }
- else
- {
- if (m_obj_file->ReadSectionData (section_sp.get(), data) == 0)
- data.Clear();
- }
+ data.SetData(m_dwarf_data, section_sp->GetOffset(), section_sp->GetFileSize());
+ }
+ else
+ {
+ if (m_obj_file->ReadSectionData(section_sp.get(), data) == 0)
+ data.Clear();
}
}
}
- return data;
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_abbrev_data()
{
- return GetCachedSectionData (flagsGotDebugAbbrevData, eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev);
+ return GetCachedSectionData (eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev);
+}
+
+const DWARFDataExtractor&
+SymbolFileDWARF::get_debug_addr_data()
+{
+ return GetCachedSectionData (eSectionTypeDWARFDebugAddr, m_data_debug_addr);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_aranges_data()
{
- return GetCachedSectionData (flagsGotDebugArangesData, eSectionTypeDWARFDebugAranges, m_data_debug_aranges);
+ return GetCachedSectionData (eSectionTypeDWARFDebugAranges, m_data_debug_aranges);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_frame_data()
{
- return GetCachedSectionData (flagsGotDebugFrameData, eSectionTypeDWARFDebugFrame, m_data_debug_frame);
+ return GetCachedSectionData (eSectionTypeDWARFDebugFrame, m_data_debug_frame);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_info_data()
{
- return GetCachedSectionData (flagsGotDebugInfoData, eSectionTypeDWARFDebugInfo, m_data_debug_info);
+ return GetCachedSectionData (eSectionTypeDWARFDebugInfo, m_data_debug_info);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_line_data()
{
- return GetCachedSectionData (flagsGotDebugLineData, eSectionTypeDWARFDebugLine, m_data_debug_line);
+ return GetCachedSectionData (eSectionTypeDWARFDebugLine, m_data_debug_line);
+}
+
+const DWARFDataExtractor&
+SymbolFileDWARF::get_debug_macro_data()
+{
+ return GetCachedSectionData (eSectionTypeDWARFDebugMacro, m_data_debug_macro);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_loc_data()
{
- return GetCachedSectionData (flagsGotDebugLocData, eSectionTypeDWARFDebugLoc, m_data_debug_loc);
+ return GetCachedSectionData (eSectionTypeDWARFDebugLoc, m_data_debug_loc);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_ranges_data()
{
- return GetCachedSectionData (flagsGotDebugRangesData, eSectionTypeDWARFDebugRanges, m_data_debug_ranges);
+ return GetCachedSectionData (eSectionTypeDWARFDebugRanges, m_data_debug_ranges);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_str_data()
{
- return GetCachedSectionData (flagsGotDebugStrData, eSectionTypeDWARFDebugStr, m_data_debug_str);
+ return GetCachedSectionData (eSectionTypeDWARFDebugStr, m_data_debug_str);
+}
+
+const DWARFDataExtractor&
+SymbolFileDWARF::get_debug_str_offsets_data()
+{
+ return GetCachedSectionData (eSectionTypeDWARFDebugStrOffsets, m_data_debug_str_offsets);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_names_data()
{
- return GetCachedSectionData (flagsGotAppleNamesData, eSectionTypeDWARFAppleNames, m_data_apple_names);
+ return GetCachedSectionData (eSectionTypeDWARFAppleNames, m_data_apple_names);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_types_data()
{
- return GetCachedSectionData (flagsGotAppleTypesData, eSectionTypeDWARFAppleTypes, m_data_apple_types);
+ return GetCachedSectionData (eSectionTypeDWARFAppleTypes, m_data_apple_types);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_namespaces_data()
{
- return GetCachedSectionData (flagsGotAppleNamespacesData, eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces);
+ return GetCachedSectionData (eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_objc_data()
{
- return GetCachedSectionData (flagsGotAppleObjCData, eSectionTypeDWARFAppleObjC, m_data_apple_objc);
+ return GetCachedSectionData (eSectionTypeDWARFAppleObjC, m_data_apple_objc);
}
@@ -889,6 +817,9 @@ SymbolFileDWARF::DebugInfo() const
DWARFCompileUnit*
SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)
{
+ if (!comp_unit)
+ return nullptr;
+
DWARFDebugInfo* info = DebugInfo();
if (info)
{
@@ -900,7 +831,7 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)
// TODO: modify to support LTO .o files where each .o file might
// have multiple DW_TAG_compile_unit tags.
- DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(0).get();
+ DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(0);
if (dwarf_cu && dwarf_cu->GetUserData() == NULL)
dwarf_cu->SetUserData(comp_unit);
return dwarf_cu;
@@ -910,7 +841,7 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)
// Just a normal DWARF file whose user ID for the compile unit is
// the DWARF offset itself
- DWARFCompileUnit *dwarf_cu = info->GetCompileUnit((dw_offset_t)comp_unit->GetID()).get();
+ DWARFCompileUnit *dwarf_cu = info->GetCompileUnit((dw_offset_t)comp_unit->GetID());
if (dwarf_cu && dwarf_cu->GetUserData() == NULL)
dwarf_cu->SetUserData(comp_unit);
return dwarf_cu;
@@ -958,7 +889,11 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
}
else
{
- if (GetDebugMapSymfile ())
+ if (dwarf_cu->GetSymbolFileDWARF() != this)
+ {
+ return dwarf_cu->GetSymbolFileDWARF()->ParseCompileUnit(dwarf_cu, cu_idx);
+ }
+ else if (GetDebugMapSymfile ())
{
// Let the debug map create the compile unit
cu_sp = m_debug_map_symfile->GetCompileUnit(this);
@@ -969,20 +904,18 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
ModuleSP module_sp (m_obj_file->GetModule());
if (module_sp)
{
- const DWARFDebugInfoEntry * cu_die = dwarf_cu->GetCompileUnitDIEOnly ();
+ const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly ();
if (cu_die)
{
- FileSpec cu_file_spec{cu_die->GetName(this, dwarf_cu), false};
+ FileSpec cu_file_spec{cu_die.GetName(), false};
if (cu_file_spec)
{
// If we have a full path to the compile unit, we don't need to resolve
// the file. This can be expensive e.g. when the source files are NFS mounted.
if (cu_file_spec.IsRelative())
{
- // DWARF2/3 suggests the form hostname:pathname for compilation directory.
- // Remove the host part if present.
- const char *cu_comp_dir{cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, nullptr)};
- cu_file_spec.PrependPathComponent(removeHostnameFromPathname(cu_comp_dir));
+ const char *cu_comp_dir{cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)};
+ cu_file_spec.PrependPathComponent(resolveCompDir(cu_comp_dir));
}
std::string remapped_file;
@@ -990,13 +923,15 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
cu_file_spec.SetFile(remapped_file, false);
}
- LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0));
+ LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0));
+ bool is_optimized = dwarf_cu->GetIsOptimized ();
cu_sp.reset(new CompileUnit (module_sp,
dwarf_cu,
cu_file_spec,
- MakeUserID(dwarf_cu->GetOffset()),
- cu_language));
+ dwarf_cu->GetID(),
+ cu_language,
+ is_optimized));
if (cu_sp)
{
// If we just created a compile unit with an invalid file spec, try and get the
@@ -1053,137 +988,20 @@ SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx)
}
Function *
-SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die)
+SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, const DWARFDIE &die)
{
- DWARFDebugRanges::RangeList func_ranges;
- const char *name = NULL;
- const char *mangled = NULL;
- int decl_file = 0;
- int decl_line = 0;
- int decl_column = 0;
- int call_file = 0;
- int call_line = 0;
- int call_column = 0;
- DWARFExpression frame_base;
-
- assert (die->Tag() == DW_TAG_subprogram);
-
- if (die->Tag() != DW_TAG_subprogram)
- return NULL;
-
- if (die->GetDIENamesAndRanges (this,
- dwarf_cu,
- name,
- mangled,
- func_ranges,
- decl_file,
- decl_line,
- decl_column,
- call_file,
- call_line,
- call_column,
- &frame_base))
+ if (die.IsValid())
{
- // Union of all ranges in the function DIE (if the function is discontiguous)
- AddressRange func_range;
- lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase (0);
- lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd (0);
- if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr)
- {
- ModuleSP module_sp (m_obj_file->GetModule());
- func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, module_sp->GetSectionList());
- if (func_range.GetBaseAddress().IsValid())
- func_range.SetByteSize(highest_func_addr - lowest_func_addr);
- }
+ TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType());
- if (func_range.GetBaseAddress().IsValid())
+ if (type_system)
{
- Mangled func_name;
- if (mangled)
- func_name.SetValue(ConstString(mangled), true);
- else if (die->GetParent()->Tag() == DW_TAG_compile_unit &&
- LanguageRuntime::LanguageIsCPlusPlus(dwarf_cu->GetLanguageType()) &&
- name && strcmp(name, "main") != 0)
- {
- // If the mangled name is not present in the DWARF, generate the demangled name
- // using the decl context. We skip if the function is "main" as its name is
- // never mangled.
- bool is_static = false;
- bool is_variadic = false;
- unsigned type_quals = 0;
- std::vector<ClangASTType> param_types;
- std::vector<clang::ParmVarDecl*> param_decls;
- const DWARFDebugInfoEntry *decl_ctx_die = NULL;
- DWARFDeclContext decl_ctx;
- StreamString sstr;
-
- die->GetDWARFDeclContext(this, dwarf_cu, decl_ctx);
- sstr << decl_ctx.GetQualifiedName();
-
- clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(dwarf_cu,
- die,
- &decl_ctx_die);
- ParseChildParameters(sc,
- containing_decl_ctx,
- dwarf_cu,
- die,
- true,
- is_static,
- is_variadic,
- param_types,
- param_decls,
- type_quals);
- sstr << "(";
- for (size_t i = 0; i < param_types.size(); i++)
- {
- if (i > 0)
- sstr << ", ";
- sstr << param_types[i].GetTypeName();
- }
- if (is_variadic)
- sstr << ", ...";
- sstr << ")";
- if (type_quals & clang::Qualifiers::Const)
- sstr << " const";
-
- func_name.SetValue(ConstString(sstr.GetData()), false);
- }
- else
- func_name.SetValue(ConstString(name), false);
-
- FunctionSP func_sp;
- std::unique_ptr<Declaration> decl_ap;
- if (decl_file != 0 || decl_line != 0 || decl_column != 0)
- decl_ap.reset(new Declaration (sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
- decl_line,
- decl_column));
-
- // Supply the type _only_ if it has already been parsed
- Type *func_type = m_die_to_type.lookup (die);
-
- assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
-
- if (FixupAddress (func_range.GetBaseAddress()))
- {
- const user_id_t func_user_id = MakeUserID(die->GetOffset());
- func_sp.reset(new Function (sc.comp_unit,
- MakeUserID(func_user_id), // UserID is the DIE offset
- MakeUserID(func_user_id),
- func_name,
- func_type,
- func_range)); // first address range
-
- if (func_sp.get() != NULL)
- {
- if (frame_base.IsValid())
- func_sp->GetFrameBaseExpression() = frame_base;
- sc.comp_unit->AddFunction(func_sp);
- return func_sp.get();
- }
- }
+ DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->ParseFunctionFromDWARF(sc, die);
}
}
- return NULL;
+ return nullptr;
}
bool
@@ -1203,12 +1021,9 @@ SymbolFileDWARF::ParseCompileUnitLanguage (const SymbolContext& sc)
assert (sc.comp_unit);
DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
- {
- const DWARFDebugInfoEntry *die = dwarf_cu->GetCompileUnitDIEOnly();
- if (die)
- return DWARFCompileUnit::LanguageTypeFromDWARF(die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0));
- }
- return eLanguageTypeUnknown;
+ return dwarf_cu->GetLanguageType();
+ else
+ return eLanguageTypeUnknown;
}
size_t
@@ -1224,10 +1039,10 @@ SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc)
size_t func_idx;
for (func_idx = 0; func_idx < num_functions; ++func_idx)
{
- const DWARFDebugInfoEntry *die = function_dies.GetDIEPtrAtIndex(func_idx);
- if (sc.comp_unit->FindFunctionByUID (MakeUserID(die->GetOffset())).get() == NULL)
+ DWARFDIE die = function_dies.GetDIEAtIndex(func_idx);
+ if (sc.comp_unit->FindFunctionByUID (die.GetID()).get() == NULL)
{
- if (ParseCompileUnitFunction(sc, dwarf_cu, die))
+ if (ParseCompileUnitFunction(sc, die))
++functions_added;
}
}
@@ -1243,23 +1058,24 @@ SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpec
DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
{
- const DWARFDebugInfoEntry * cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly();
if (cu_die)
{
- const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, NULL);
-
- // DWARF2/3 suggests the form hostname:pathname for compilation directory.
- // Remove the host part if present.
- cu_comp_dir = removeHostnameFromPathname(cu_comp_dir);
-
- dw_offset_t stmt_list = cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET);
-
- // All file indexes in DWARF are one based and a file of index zero is
- // supposed to be the compile unit itself.
- support_files.Append (*sc.comp_unit);
+ const char * cu_comp_dir = resolveCompDir(cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr));
- return DWARFDebugLine::ParseSupportFiles(sc.comp_unit->GetModule(), get_debug_line_data(), cu_comp_dir, stmt_list, support_files);
+ const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET);
+ if (stmt_list != DW_INVALID_OFFSET)
+ {
+ // All file indexes in DWARF are one based and a file of index zero is
+ // supposed to be the compile unit itself.
+ support_files.Append (*sc.comp_unit);
+ return DWARFDebugLine::ParseSupportFiles(sc.comp_unit->GetModule(),
+ get_debug_line_data(),
+ cu_comp_dir,
+ stmt_list,
+ support_files);
+ }
}
}
return false;
@@ -1275,9 +1091,9 @@ SymbolFileDWARF::ParseImportedModules (const lldb_private::SymbolContext &sc, st
if (ClangModulesDeclVendor::LanguageSupportsClangModules(sc.comp_unit->GetLanguage()))
{
UpdateExternalModuleListIfNeeded();
- for (const std::pair<uint64_t, const ClangModuleInfo> &external_type_module : m_external_type_modules)
+ for (const auto &pair : m_external_type_modules)
{
- imported_modules.push_back(external_type_module.second.m_name);
+ imported_modules.push_back(pair.first);
}
}
}
@@ -1288,6 +1104,7 @@ struct ParseDWARFLineTableCallbackInfo
{
LineTable* line_table;
std::unique_ptr<LineSequence> sequence_ap;
+ lldb::addr_t addr_mask;
};
//----------------------------------------------------------------------
@@ -1317,7 +1134,7 @@ ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& sta
assert(info->sequence_ap.get());
}
line_table->AppendLineEntryToSequence (info->sequence_ap.get(),
- state.address,
+ state.address & info->addr_mask,
state.line,
state.column,
state.file,
@@ -1346,10 +1163,10 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)
DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
{
- const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
if (dwarf_cu_die)
{
- const dw_offset_t cu_line_offset = dwarf_cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET);
+ const dw_offset_t cu_line_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET);
if (cu_line_offset != DW_INVALID_OFFSET)
{
std::unique_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit));
@@ -1357,6 +1174,28 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)
{
ParseDWARFLineTableCallbackInfo info;
info.line_table = line_table_ap.get();
+
+ /*
+ * MIPS:
+ * The SymbolContext may not have a valid target, thus we may not be able
+ * to call Address::GetOpcodeLoadAddress() which would clear the bit #0
+ * for MIPS. Use ArchSpec to clear the bit #0.
+ */
+ ArchSpec arch;
+ GetObjectFile()->GetArchitecture(arch);
+ switch (arch.GetMachine())
+ {
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ info.addr_mask = ~((lldb::addr_t)1);
+ break;
+ default:
+ info.addr_mask = ~((lldb::addr_t)0);
+ break;
+ }
+
lldb::offset_t offset = cu_line_offset;
DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info);
if (m_debug_map_symfile)
@@ -1379,21 +1218,63 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)
return false;
}
+lldb_private::DebugMacrosSP
+SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset)
+{
+ auto iter = m_debug_macros_map.find(*offset);
+ if (iter != m_debug_macros_map.end())
+ return iter->second;
+
+ const DWARFDataExtractor &debug_macro_data = get_debug_macro_data();
+ if (debug_macro_data.GetByteSize() == 0)
+ return DebugMacrosSP();
+
+ lldb_private::DebugMacrosSP debug_macros_sp(new lldb_private::DebugMacros());
+ m_debug_macros_map[*offset] = debug_macros_sp;
+
+ const DWARFDebugMacroHeader &header = DWARFDebugMacroHeader::ParseHeader(debug_macro_data, offset);
+ DWARFDebugMacroEntry::ReadMacroEntries(
+ debug_macro_data, get_debug_str_data(), header.OffsetIs64Bit(), offset, this, debug_macros_sp);
+
+ return debug_macros_sp;
+}
+
+bool
+SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext& sc)
+{
+ assert (sc.comp_unit);
+
+ DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ if (dwarf_cu == nullptr)
+ return false;
+
+ const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ if (!dwarf_cu_die)
+ return false;
+
+ lldb::offset_t sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_macros, DW_INVALID_OFFSET);
+ if (sect_offset == DW_INVALID_OFFSET)
+ sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_macros, DW_INVALID_OFFSET);
+ if (sect_offset == DW_INVALID_OFFSET)
+ return false;
+
+ sc.comp_unit->SetDebugMacros(ParseDebugMacros(&sect_offset));
+
+ return true;
+}
+
size_t
-SymbolFileDWARF::ParseFunctionBlocks
-(
- const SymbolContext& sc,
- Block *parent_block,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- addr_t subprogram_low_pc,
- uint32_t depth
-)
+SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext& sc,
+ Block *parent_block,
+ const DWARFDIE &orig_die,
+ addr_t subprogram_low_pc,
+ uint32_t depth)
{
size_t blocks_added = 0;
- while (die != NULL)
+ DWARFDIE die = orig_die;
+ while (die)
{
- dw_tag_t tag = die->Tag();
+ dw_tag_t tag = die.Tag();
switch (tag)
{
@@ -1415,11 +1296,11 @@ SymbolFileDWARF::ParseFunctionBlocks
}
else
{
- BlockSP block_sp(new Block (MakeUserID(die->GetOffset())));
+ BlockSP block_sp(new Block (die.GetID()));
parent_block->AddChild(block_sp);
block = block_sp.get();
}
- DWARFDebugRanges::RangeList ranges;
+ DWARFRangeList ranges;
const char *name = NULL;
const char *mangled_name = NULL;
@@ -1429,13 +1310,11 @@ SymbolFileDWARF::ParseFunctionBlocks
int call_file = 0;
int call_line = 0;
int call_column = 0;
- if (die->GetDIENamesAndRanges (this,
- dwarf_cu,
- name,
- mangled_name,
- ranges,
- decl_file, decl_line, decl_column,
- call_file, call_line, call_column))
+ if (die.GetDIENamesAndRanges (name,
+ mangled_name,
+ ranges,
+ decl_file, decl_line, decl_column,
+ call_file, call_line, call_column, nullptr))
{
if (tag == DW_TAG_subprogram)
{
@@ -1461,7 +1340,7 @@ SymbolFileDWARF::ParseFunctionBlocks
const size_t num_ranges = ranges.GetSize();
for (size_t i = 0; i<num_ranges; ++i)
{
- const DWARFDebugRanges::Range &range = ranges.GetEntryRef (i);
+ const DWARFRangeList::Entry &range = ranges.GetEntryRef (i);
const addr_t range_base = range.GetRangeBase();
if (range_base >= subprogram_low_pc)
block->AddRange(Block::Range (range_base - subprogram_low_pc, range.GetByteSize()));
@@ -1493,12 +1372,11 @@ SymbolFileDWARF::ParseFunctionBlocks
++blocks_added;
- if (die->HasChildren())
+ if (die.HasChildren())
{
blocks_added += ParseFunctionBlocks (sc,
block,
- dwarf_cu,
- die->GetFirstChild(),
+ die.GetFirstChild(),
subprogram_low_pc,
depth + 1);
}
@@ -1514,278 +1392,21 @@ SymbolFileDWARF::ParseFunctionBlocks
// DW_TAG_subprogram DIE
if (depth == 0)
- die = NULL;
+ die.Clear();
else
- die = die->GetSibling();
+ die = die.GetSibling();
}
return blocks_added;
}
bool
-SymbolFileDWARF::ParseTemplateDIE (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- ClangASTContext::TemplateParameterInfos &template_param_infos)
-{
- const dw_tag_t tag = die->Tag();
-
- switch (tag)
- {
- case DW_TAG_template_type_parameter:
- case DW_TAG_template_value_parameter:
- {
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
-
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_attributes = die->GetAttributes (this,
- dwarf_cu,
- fixed_form_sizes,
- attributes);
- const char *name = NULL;
- Type *lldb_type = NULL;
- ClangASTType clang_type;
- uint64_t uval64 = 0;
- bool uval64_valid = false;
- if (num_attributes > 0)
- {
- DWARFFormValue form_value;
- for (size_t i=0; i<num_attributes; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
-
- switch (attr)
- {
- case DW_AT_name:
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- name = form_value.AsCString(&get_debug_str_data());
- break;
-
- case DW_AT_type:
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- const dw_offset_t type_die_offset = form_value.Reference();
- lldb_type = ResolveTypeUID(type_die_offset);
- if (lldb_type)
- clang_type = lldb_type->GetClangForwardType();
- }
- break;
-
- case DW_AT_const_value:
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- uval64_valid = true;
- uval64 = form_value.Unsigned();
- }
- break;
- default:
- break;
- }
- }
-
- clang::ASTContext *ast = GetClangASTContext().getASTContext();
- if (!clang_type)
- clang_type = GetClangASTContext().GetBasicType(eBasicTypeVoid);
-
- if (clang_type)
- {
- bool is_signed = false;
- if (name && name[0])
- template_param_infos.names.push_back(name);
- else
- template_param_infos.names.push_back(NULL);
-
- if (tag == DW_TAG_template_value_parameter &&
- lldb_type != NULL &&
- clang_type.IsIntegerType (is_signed) &&
- uval64_valid)
- {
- llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed);
- template_param_infos.args.push_back (clang::TemplateArgument (*ast,
- llvm::APSInt(apint),
- clang_type.GetQualType()));
- }
- else
- {
- template_param_infos.args.push_back (clang::TemplateArgument (clang_type.GetQualType()));
- }
- }
- else
- {
- return false;
- }
-
- }
- }
- return true;
-
- default:
- break;
- }
- return false;
-}
-
-bool
-SymbolFileDWARF::ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- ClangASTContext::TemplateParameterInfos &template_param_infos)
-{
-
- if (parent_die == NULL)
- return false;
-
- Args template_parameter_names;
- for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild();
- die != NULL;
- die = die->GetSibling())
- {
- const dw_tag_t tag = die->Tag();
-
- switch (tag)
- {
- case DW_TAG_template_type_parameter:
- case DW_TAG_template_value_parameter:
- ParseTemplateDIE (dwarf_cu, die, template_param_infos);
- break;
-
- default:
- break;
- }
- }
- if (template_param_infos.args.empty())
- return false;
- return template_param_infos.args.size() == template_param_infos.names.size();
-}
-
-clang::ClassTemplateDecl *
-SymbolFileDWARF::ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
- lldb::AccessType access_type,
- const char *parent_name,
- int tag_decl_kind,
- const ClangASTContext::TemplateParameterInfos &template_param_infos)
-{
- if (template_param_infos.IsValid())
- {
- std::string template_basename(parent_name);
- template_basename.erase (template_basename.find('<'));
- ClangASTContext &ast = GetClangASTContext();
-
- return ast.CreateClassTemplateDecl (decl_ctx,
- access_type,
- template_basename.c_str(),
- tag_decl_kind,
- template_param_infos);
- }
- return NULL;
-}
-
-class SymbolFileDWARF::DelayedAddObjCClassProperty
-{
-public:
- DelayedAddObjCClassProperty
- (
- const ClangASTType &class_opaque_type,
- const char *property_name,
- const ClangASTType &property_opaque_type, // The property type is only required if you don't have an ivar decl
- clang::ObjCIvarDecl *ivar_decl,
- const char *property_setter_name,
- const char *property_getter_name,
- uint32_t property_attributes,
- const ClangASTMetadata *metadata
- ) :
- m_class_opaque_type (class_opaque_type),
- m_property_name (property_name),
- m_property_opaque_type (property_opaque_type),
- m_ivar_decl (ivar_decl),
- m_property_setter_name (property_setter_name),
- m_property_getter_name (property_getter_name),
- m_property_attributes (property_attributes)
- {
- if (metadata != NULL)
- {
- m_metadata_ap.reset(new ClangASTMetadata());
- *m_metadata_ap = *metadata;
- }
- }
-
- DelayedAddObjCClassProperty (const DelayedAddObjCClassProperty &rhs)
- {
- *this = rhs;
- }
-
- DelayedAddObjCClassProperty& operator= (const DelayedAddObjCClassProperty &rhs)
- {
- m_class_opaque_type = rhs.m_class_opaque_type;
- m_property_name = rhs.m_property_name;
- m_property_opaque_type = rhs.m_property_opaque_type;
- m_ivar_decl = rhs.m_ivar_decl;
- m_property_setter_name = rhs.m_property_setter_name;
- m_property_getter_name = rhs.m_property_getter_name;
- m_property_attributes = rhs.m_property_attributes;
-
- if (rhs.m_metadata_ap.get())
- {
- m_metadata_ap.reset (new ClangASTMetadata());
- *m_metadata_ap = *rhs.m_metadata_ap;
- }
- return *this;
- }
-
- bool
- Finalize()
- {
- return m_class_opaque_type.AddObjCClassProperty (m_property_name,
- m_property_opaque_type,
- m_ivar_decl,
- m_property_setter_name,
- m_property_getter_name,
- m_property_attributes,
- m_metadata_ap.get());
- }
-private:
- ClangASTType m_class_opaque_type;
- const char *m_property_name;
- ClangASTType m_property_opaque_type;
- clang::ObjCIvarDecl *m_ivar_decl;
- const char *m_property_setter_name;
- const char *m_property_getter_name;
- uint32_t m_property_attributes;
- std::unique_ptr<ClangASTMetadata> m_metadata_ap;
-};
-
-struct BitfieldInfo
-{
- uint64_t bit_size;
- uint64_t bit_offset;
-
- BitfieldInfo () :
- bit_size (LLDB_INVALID_ADDRESS),
- bit_offset (LLDB_INVALID_ADDRESS)
- {
- }
-
- void
- Clear()
- {
- bit_size = LLDB_INVALID_ADDRESS;
- bit_offset = LLDB_INVALID_ADDRESS;
- }
-
- bool IsValid ()
- {
- return (bit_size != LLDB_INVALID_ADDRESS) &&
- (bit_offset != LLDB_INVALID_ADDRESS);
- }
-};
-
-
-bool
-SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die)
+SymbolFileDWARF::ClassOrStructIsVirtual (const DWARFDIE &parent_die)
{
if (parent_die)
{
- for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+ for (DWARFDIE die = parent_die.GetFirstChild(); die; die = die.GetSibling())
{
- dw_tag_t tag = die->Tag();
+ dw_tag_t tag = die.Tag();
bool check_virtuality = false;
switch (tag)
{
@@ -1798,7 +1419,7 @@ SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu,
}
if (check_virtuality)
{
- if (die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_virtuality, 0) != 0)
+ if (die.GetAttributeValueAsUnsigned(DW_AT_virtuality, 0) != 0)
return true;
}
}
@@ -1806,602 +1427,79 @@ SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu,
return false;
}
-size_t
-SymbolFileDWARF::ParseChildMembers
-(
- const SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- ClangASTType &class_clang_type,
- const LanguageType class_language,
- std::vector<clang::CXXBaseSpecifier *>& base_classes,
- std::vector<int>& member_accessibilities,
- DWARFDIECollection& member_function_dies,
- DelayedPropertyList& delayed_properties,
- AccessType& default_accessibility,
- bool &is_a_class,
- LayoutInfo &layout_info
-)
+void
+SymbolFileDWARF::ParseDeclsForContext (CompilerDeclContext decl_ctx)
{
- if (parent_die == NULL)
- return 0;
+ TypeSystem *type_system = decl_ctx.GetTypeSystem();
+ DWARFASTParser *ast_parser = type_system->GetDWARFParser();
+ std::vector<DWARFDIE> decl_ctx_die_list = ast_parser->GetDIEForDeclContext(decl_ctx);
- size_t count = 0;
- const DWARFDebugInfoEntry *die;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
- uint32_t member_idx = 0;
- BitfieldInfo last_field_info;
- ModuleSP module = GetObjectFile()->GetModule();
+ for (DWARFDIE decl_ctx_die : decl_ctx_die_list)
+ for (DWARFDIE decl = decl_ctx_die.GetFirstChild(); decl; decl = decl.GetSibling())
+ ast_parser->GetDeclForUIDFromDWARF(decl);
+}
- for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+CompilerDecl
+SymbolFileDWARF::GetDeclForUID (lldb::user_id_t type_uid)
+{
+ if (UserIDMatches(type_uid))
{
- dw_tag_t tag = die->Tag();
-
- switch (tag)
+ DWARFDebugInfo* debug_info = DebugInfo();
+ if (debug_info)
{
- case DW_TAG_member:
- case DW_TAG_APPLE_property:
- {
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_attributes = die->GetAttributes (this,
- dwarf_cu,
- fixed_form_sizes,
- attributes);
- if (num_attributes > 0)
- {
- Declaration decl;
- //DWARFExpression location;
- const char *name = NULL;
- const char *prop_name = NULL;
- const char *prop_getter_name = NULL;
- const char *prop_setter_name = NULL;
- uint32_t prop_attributes = 0;
-
-
- bool is_artificial = false;
- lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
- AccessType accessibility = eAccessNone;
- uint32_t member_byte_offset = UINT32_MAX;
- size_t byte_size = 0;
- size_t bit_offset = 0;
- size_t bit_size = 0;
- bool is_external = false; // On DW_TAG_members, this means the member is static
- uint32_t i;
- for (i=0; i<num_attributes && !is_artificial; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: encoding_uid = form_value.Reference(); break;
- case DW_AT_bit_offset: bit_offset = form_value.Unsigned(); break;
- case DW_AT_bit_size: bit_size = form_value.Unsigned(); break;
- case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
- case DW_AT_data_member_location:
- if (form_value.BlockData())
- {
- Value initialValue(0);
- Value memberOffset(0);
- const DWARFDataExtractor& debug_info_data = get_debug_info_data();
- uint32_t block_length = form_value.Unsigned();
- uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
- if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
- NULL, // ClangExpressionVariableList *
- NULL, // ClangExpressionDeclMap *
- NULL, // RegisterContext *
- module,
- debug_info_data,
- block_offset,
- block_length,
- eRegisterKindDWARF,
- &initialValue,
- memberOffset,
- NULL))
- {
- member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
- }
- }
- else
- {
- // With DWARF 3 and later, if the value is an integer constant,
- // this form value is the offset in bytes from the beginning
- // of the containing entity.
- member_byte_offset = form_value.Unsigned();
- }
- break;
-
- case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType (form_value.Unsigned()); break;
- case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
- case DW_AT_APPLE_property_name: prop_name = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_APPLE_property_getter: prop_getter_name = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_APPLE_property_setter: prop_setter_name = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_APPLE_property_attribute: prop_attributes = form_value.Unsigned(); break;
- case DW_AT_external: is_external = form_value.Boolean(); break;
-
- default:
- case DW_AT_declaration:
- case DW_AT_description:
- case DW_AT_mutable:
- case DW_AT_visibility:
- case DW_AT_sibling:
- break;
- }
- }
- }
-
- if (prop_name)
- {
- ConstString fixed_getter;
- ConstString fixed_setter;
-
- // Check if the property getter/setter were provided as full
- // names. We want basenames, so we extract them.
-
- if (prop_getter_name && prop_getter_name[0] == '-')
- {
- ObjCLanguageRuntime::MethodName prop_getter_method(prop_getter_name, true);
- prop_getter_name = prop_getter_method.GetSelector().GetCString();
- }
-
- if (prop_setter_name && prop_setter_name[0] == '-')
- {
- ObjCLanguageRuntime::MethodName prop_setter_method(prop_setter_name, true);
- prop_setter_name = prop_setter_method.GetSelector().GetCString();
- }
-
- // If the names haven't been provided, they need to be
- // filled in.
-
- if (!prop_getter_name)
- {
- prop_getter_name = prop_name;
- }
- if (!prop_setter_name && prop_name[0] && !(prop_attributes & DW_APPLE_PROPERTY_readonly))
- {
- StreamString ss;
-
- ss.Printf("set%c%s:",
- toupper(prop_name[0]),
- &prop_name[1]);
-
- fixed_setter.SetCString(ss.GetData());
- prop_setter_name = fixed_setter.GetCString();
- }
- }
-
- // Clang has a DWARF generation bug where sometimes it
- // represents fields that are references with bad byte size
- // and bit size/offset information such as:
- //
- // DW_AT_byte_size( 0x00 )
- // DW_AT_bit_size( 0x40 )
- // DW_AT_bit_offset( 0xffffffffffffffc0 )
- //
- // So check the bit offset to make sure it is sane, and if
- // the values are not sane, remove them. If we don't do this
- // then we will end up with a crash if we try to use this
- // type in an expression when clang becomes unhappy with its
- // recycled debug info.
-
- if (bit_offset > 128)
- {
- bit_size = 0;
- bit_offset = 0;
- }
-
- // FIXME: Make Clang ignore Objective-C accessibility for expressions
- if (class_language == eLanguageTypeObjC ||
- class_language == eLanguageTypeObjC_plus_plus)
- accessibility = eAccessNone;
-
- if (member_idx == 0 && !is_artificial && name && (strstr (name, "_vptr$") == name))
- {
- // Not all compilers will mark the vtable pointer
- // member as artificial (llvm-gcc). We can't have
- // the virtual members in our classes otherwise it
- // throws off all child offsets since we end up
- // having and extra pointer sized member in our
- // class layouts.
- is_artificial = true;
- }
-
- // Handle static members
- if (is_external && member_byte_offset == UINT32_MAX)
- {
- Type *var_type = ResolveTypeUID(encoding_uid);
-
- if (var_type)
- {
- if (accessibility == eAccessNone)
- accessibility = eAccessPublic;
- class_clang_type.AddVariableToRecordType (name,
- var_type->GetClangLayoutType(),
- accessibility);
- }
- break;
- }
-
- if (is_artificial == false)
- {
- Type *member_type = ResolveTypeUID(encoding_uid);
-
- clang::FieldDecl *field_decl = NULL;
- if (tag == DW_TAG_member)
- {
- if (member_type)
- {
- if (accessibility == eAccessNone)
- accessibility = default_accessibility;
- member_accessibilities.push_back(accessibility);
-
- uint64_t field_bit_offset = (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
- if (bit_size > 0)
- {
-
- BitfieldInfo this_field_info;
- this_field_info.bit_offset = field_bit_offset;
- this_field_info.bit_size = bit_size;
-
- /////////////////////////////////////////////////////////////
- // How to locate a field given the DWARF debug information
- //
- // AT_byte_size indicates the size of the word in which the
- // bit offset must be interpreted.
- //
- // AT_data_member_location indicates the byte offset of the
- // word from the base address of the structure.
- //
- // AT_bit_offset indicates how many bits into the word
- // (according to the host endianness) the low-order bit of
- // the field starts. AT_bit_offset can be negative.
- //
- // AT_bit_size indicates the size of the field in bits.
- /////////////////////////////////////////////////////////////
-
- if (byte_size == 0)
- byte_size = member_type->GetByteSize();
-
- if (GetObjectFile()->GetByteOrder() == eByteOrderLittle)
- {
- this_field_info.bit_offset += byte_size * 8;
- this_field_info.bit_offset -= (bit_offset + bit_size);
- }
- else
- {
- this_field_info.bit_offset += bit_offset;
- }
-
- // Update the field bit offset we will report for layout
- field_bit_offset = this_field_info.bit_offset;
-
- // If the member to be emitted did not start on a character boundary and there is
- // empty space between the last field and this one, then we need to emit an
- // anonymous member filling up the space up to its start. There are three cases
- // here:
- //
- // 1 If the previous member ended on a character boundary, then we can emit an
- // anonymous member starting at the most recent character boundary.
- //
- // 2 If the previous member did not end on a character boundary and the distance
- // from the end of the previous member to the current member is less than a
- // word width, then we can emit an anonymous member starting right after the
- // previous member and right before this member.
- //
- // 3 If the previous member did not end on a character boundary and the distance
- // from the end of the previous member to the current member is greater than
- // or equal a word width, then we act as in Case 1.
-
- const uint64_t character_width = 8;
- const uint64_t word_width = 32;
-
- // Objective-C has invalid DW_AT_bit_offset values in older versions
- // of clang, so we have to be careful and only insert unnamed bitfields
- // if we have a new enough clang.
- bool detect_unnamed_bitfields = true;
-
- if (class_language == eLanguageTypeObjC || class_language == eLanguageTypeObjC_plus_plus)
- detect_unnamed_bitfields = dwarf_cu->Supports_unnamed_objc_bitfields ();
-
- if (detect_unnamed_bitfields)
- {
- BitfieldInfo anon_field_info;
-
- if ((this_field_info.bit_offset % character_width) != 0) // not char aligned
- {
- uint64_t last_field_end = 0;
-
- if (last_field_info.IsValid())
- last_field_end = last_field_info.bit_offset + last_field_info.bit_size;
-
- if (this_field_info.bit_offset != last_field_end)
- {
- if (((last_field_end % character_width) == 0) || // case 1
- (this_field_info.bit_offset - last_field_end >= word_width)) // case 3
- {
- anon_field_info.bit_size = this_field_info.bit_offset % character_width;
- anon_field_info.bit_offset = this_field_info.bit_offset - anon_field_info.bit_size;
- }
- else // case 2
- {
- anon_field_info.bit_size = this_field_info.bit_offset - last_field_end;
- anon_field_info.bit_offset = last_field_end;
- }
- }
- }
-
- if (anon_field_info.IsValid())
- {
- clang::FieldDecl *unnamed_bitfield_decl = class_clang_type.AddFieldToRecordType (NULL,
- GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width),
- accessibility,
- anon_field_info.bit_size);
-
- layout_info.field_offsets.insert(
- std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset));
- }
- }
- last_field_info = this_field_info;
- }
- else
- {
- last_field_info.Clear();
- }
-
- ClangASTType member_clang_type = member_type->GetClangLayoutType();
-
- {
- // Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>).
- // If the current field is at the end of the structure, then there is definitely no room for extra
- // elements and we override the type to array[0].
-
- ClangASTType member_array_element_type;
- uint64_t member_array_size;
- bool member_array_is_incomplete;
-
- if (member_clang_type.IsArrayType(&member_array_element_type,
- &member_array_size,
- &member_array_is_incomplete) &&
- !member_array_is_incomplete)
- {
- uint64_t parent_byte_size = parent_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_byte_size, UINT64_MAX);
-
- if (member_byte_offset >= parent_byte_size)
- {
- if (member_array_size != 1)
- {
- GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which extends beyond the bounds of 0x%8.8" PRIx64,
- MakeUserID(die->GetOffset()),
- name,
- encoding_uid,
- MakeUserID(parent_die->GetOffset()));
- }
-
- member_clang_type = GetClangASTContext().CreateArrayType(member_array_element_type, 0, false);
- }
- }
- }
-
- field_decl = class_clang_type.AddFieldToRecordType (name,
- member_clang_type,
- accessibility,
- bit_size);
-
- GetClangASTContext().SetMetadataAsUserID (field_decl, MakeUserID(die->GetOffset()));
-
- layout_info.field_offsets.insert(std::make_pair(field_decl, field_bit_offset));
- }
- else
- {
- if (name)
- GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which was unable to be parsed",
- MakeUserID(die->GetOffset()),
- name,
- encoding_uid);
- else
- GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8" PRIx64 " which was unable to be parsed",
- MakeUserID(die->GetOffset()),
- encoding_uid);
- }
- }
-
- if (prop_name != NULL && member_type)
- {
- clang::ObjCIvarDecl *ivar_decl = NULL;
-
- if (field_decl)
- {
- ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl);
- assert (ivar_decl != NULL);
- }
-
- ClangASTMetadata metadata;
- metadata.SetUserID (MakeUserID(die->GetOffset()));
- delayed_properties.push_back(DelayedAddObjCClassProperty(class_clang_type,
- prop_name,
- member_type->GetClangLayoutType(),
- ivar_decl,
- prop_setter_name,
- prop_getter_name,
- prop_attributes,
- &metadata));
-
- if (ivar_decl)
- GetClangASTContext().SetMetadataAsUserID (ivar_decl, MakeUserID(die->GetOffset()));
- }
- }
- }
- ++member_idx;
- }
- break;
-
- case DW_TAG_subprogram:
- // Let the type parsing code handle this one for us.
- member_function_dies.Append (die);
- break;
-
- case DW_TAG_inheritance:
+ DWARFDIE die = debug_info->GetDIE(DIERef(type_uid));
+ if (die)
{
- is_a_class = true;
- if (default_accessibility == eAccessNone)
- default_accessibility = eAccessPrivate;
- // TODO: implement DW_TAG_inheritance type parsing
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_attributes = die->GetAttributes (this,
- dwarf_cu,
- fixed_form_sizes,
- attributes);
- if (num_attributes > 0)
- {
- Declaration decl;
- DWARFExpression location;
- lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
- AccessType accessibility = default_accessibility;
- bool is_virtual = false;
- bool is_base_of_class = true;
- off_t member_byte_offset = 0;
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_type: encoding_uid = form_value.Reference(); break;
- case DW_AT_data_member_location:
- if (form_value.BlockData())
- {
- Value initialValue(0);
- Value memberOffset(0);
- const DWARFDataExtractor& debug_info_data = get_debug_info_data();
- uint32_t block_length = form_value.Unsigned();
- uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
- if (DWARFExpression::Evaluate (NULL,
- NULL,
- NULL,
- NULL,
- module,
- debug_info_data,
- block_offset,
- block_length,
- eRegisterKindDWARF,
- &initialValue,
- memberOffset,
- NULL))
- {
- member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
- }
- }
- else
- {
- // With DWARF 3 and later, if the value is an integer constant,
- // this form value is the offset in bytes from the beginning
- // of the containing entity.
- member_byte_offset = form_value.Unsigned();
- }
- break;
-
- case DW_AT_accessibility:
- accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
- break;
-
- case DW_AT_virtuality:
- is_virtual = form_value.Boolean();
- break;
-
- case DW_AT_sibling:
- break;
-
- default:
- break;
- }
- }
- }
-
- Type *base_class_type = ResolveTypeUID(encoding_uid);
- if (base_class_type == NULL)
- {
- GetObjectFile()->GetModule()->ReportError("0x%8.8x: DW_TAG_inheritance failed to resolve the base class at 0x%8.8" PRIx64 " from enclosing type 0x%8.8x. \nPlease file a bug and attach the file at the start of this error message",
- die->GetOffset(),
- encoding_uid,
- parent_die->GetOffset());
- break;
- }
-
- ClangASTType base_class_clang_type = base_class_type->GetClangFullType();
- assert (base_class_clang_type);
- if (class_language == eLanguageTypeObjC)
- {
- class_clang_type.SetObjCSuperClass(base_class_clang_type);
- }
- else
- {
- base_classes.push_back (base_class_clang_type.CreateBaseClassSpecifier (accessibility,
- is_virtual,
- is_base_of_class));
-
- if (is_virtual)
- {
- // Do not specify any offset for virtual inheritance. The DWARF produced by clang doesn't
- // give us a constant offset, but gives us a DWARF expressions that requires an actual object
- // in memory. the DW_AT_data_member_location for a virtual base class looks like:
- // DW_AT_data_member_location( DW_OP_dup, DW_OP_deref, DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref, DW_OP_plus )
- // Given this, there is really no valid response we can give to clang for virtual base
- // class offsets, and this should eventually be removed from LayoutRecordType() in the external
- // AST source in clang.
- }
- else
- {
- layout_info.base_offsets.insert(
- std::make_pair(base_class_clang_type.GetAsCXXRecordDecl(),
- clang::CharUnits::fromQuantity(member_byte_offset)));
- }
- }
- }
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->GetDeclForUIDFromDWARF(die);
}
- break;
-
- default:
- break;
}
}
-
- return count;
+ return CompilerDecl();
}
-
-clang::DeclContext*
-SymbolFileDWARF::GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid)
+CompilerDeclContext
+SymbolFileDWARF::GetDeclContextForUID (lldb::user_id_t type_uid)
{
- DWARFDebugInfo* debug_info = DebugInfo();
- if (debug_info && UserIDMatches(type_uid))
+ if (UserIDMatches(type_uid))
{
- DWARFCompileUnitSP cu_sp;
- const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(type_uid, &cu_sp);
- if (die)
- return GetClangDeclContextContainingDIE (cu_sp.get(), die, NULL);
+ DWARFDebugInfo* debug_info = DebugInfo();
+ if (debug_info)
+ {
+ DWARFDIE die = debug_info->GetDIE(DIERef(type_uid));
+ if (die)
+ {
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->GetDeclContextForUIDFromDWARF(die);
+ }
+ }
}
- return NULL;
+ return CompilerDeclContext();
}
-clang::DeclContext*
-SymbolFileDWARF::GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid)
+CompilerDeclContext
+SymbolFileDWARF::GetDeclContextContainingUID (lldb::user_id_t type_uid)
{
if (UserIDMatches(type_uid))
- return GetClangDeclContextForDIEOffset (sc, type_uid);
- return NULL;
+ {
+ DWARFDebugInfo* debug_info = DebugInfo();
+ if (debug_info)
+ {
+ DWARFDIE die = debug_info->GetDIE(DIERef(type_uid));
+ if (die)
+ {
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->GetDeclContextContainingUIDFromDWARF(die);
+ }
+ }
+ }
+ return CompilerDeclContext();
}
+
Type*
SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid)
{
@@ -2410,418 +1508,143 @@ SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid)
DWARFDebugInfo* debug_info = DebugInfo();
if (debug_info)
{
- DWARFCompileUnitSP cu_sp;
- const DWARFDebugInfoEntry* type_die = debug_info->GetDIEPtr(type_uid, &cu_sp);
- const bool assert_not_being_parsed = true;
- return ResolveTypeUID (cu_sp.get(), type_die, assert_not_being_parsed);
+ DWARFDIE type_die = debug_info->GetDIE (DIERef(type_uid));
+ if (type_die)
+ {
+ const bool assert_not_being_parsed = true;
+ return ResolveTypeUID (type_die, assert_not_being_parsed);
+ }
}
}
return NULL;
}
Type*
-SymbolFileDWARF::ResolveTypeUID (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* die, bool assert_not_being_parsed)
+SymbolFileDWARF::ResolveTypeUID (const DWARFDIE &die, bool assert_not_being_parsed)
{
- if (die != NULL)
+ if (die)
{
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
if (log)
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, cu));
+ die.GetOffset(),
+ die.GetTagAsCString(),
+ die.GetName());
// We might be coming in in the middle of a type tree (a class
// withing a class, an enum within a class), so parse any needed
// parent DIEs before we get to this one...
- const DWARFDebugInfoEntry *decl_ctx_die = GetDeclContextDIEContainingDIE (cu, die);
- switch (decl_ctx_die->Tag())
+ DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE (die);
+ if (decl_ctx_die)
{
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type:
+ if (log)
{
- // Get the type, which could be a forward declaration
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, cu),
- decl_ctx_die->GetOffset());
-//
-// Type *parent_type = ResolveTypeUID (cu, decl_ctx_die, assert_not_being_parsed);
-// if (child_requires_parent_class_union_or_struct_to_be_completed(die->Tag()))
-// {
-// if (log)
-// GetObjectFile()->GetModule()->LogMessage (log,
-// "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent full type for 0x%8.8x since die is a function",
-// die->GetOffset(),
-// DW_TAG_value_to_name(die->Tag()),
-// die->GetName(this, cu),
-// decl_ctx_die->GetOffset());
-// // Ask the type to complete itself if it already hasn't since if we
-// // want a function (method or static) from a class, the class must
-// // create itself and add it's own methods and class functions.
-// if (parent_type)
-// parent_type->GetClangFullType();
-// }
- }
- break;
+ switch (decl_ctx_die.Tag())
+ {
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ {
+ // Get the type, which could be a forward declaration
+ if (log)
+ GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x",
+ die.GetOffset(),
+ die.GetTagAsCString(),
+ die.GetName(),
+ decl_ctx_die.GetOffset());
+ }
+ break;
- default:
- break;
+ default:
+ break;
+ }
+ }
}
- return ResolveType (cu, die);
+ return ResolveType (die);
}
return NULL;
}
// This function is used when SymbolFileDWARFDebugMap owns a bunch of
// SymbolFileDWARF objects to detect if this DWARF file is the one that
-// can resolve a clang_type.
+// can resolve a compiler_type.
bool
-SymbolFileDWARF::HasForwardDeclForClangType (const ClangASTType &clang_type)
+SymbolFileDWARF::HasForwardDeclForClangType (const CompilerType &compiler_type)
{
- ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers();
- const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType());
- return die != NULL;
+ CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type);
+ if (GetForwardDeclClangTypeToDie().count (compiler_type_no_qualifiers.GetOpaqueQualType()))
+ {
+ return true;
+ }
+ TypeSystem *type_system = compiler_type.GetTypeSystem();
+ if (type_system)
+ {
+ DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->CanCompleteType(compiler_type);
+ }
+ return false;
}
bool
-SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
+SymbolFileDWARF::CompleteType (CompilerType &compiler_type)
{
+ TypeSystem *type_system = compiler_type.GetTypeSystem();
+ if (type_system)
+ {
+ DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+ if (dwarf_ast && dwarf_ast->CanCompleteType(compiler_type))
+ return dwarf_ast->CompleteType(compiler_type);
+ }
+
// We have a struct/union/class/enum that needs to be fully resolved.
- ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers();
- const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType());
- if (die == NULL)
+ CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type);
+ auto die_it = GetForwardDeclClangTypeToDie().find (compiler_type_no_qualifiers.GetOpaqueQualType());
+ if (die_it == GetForwardDeclClangTypeToDie().end())
{
// We have already resolved this type...
return true;
}
+
+ DWARFDebugInfo* debug_info = DebugInfo();
+ DWARFDIE dwarf_die = debug_info->GetDIE(die_it->getSecond());
+
+ assert(UserIDMatches(die_it->getSecond().GetUID()) && "CompleteType called on the wrong SymbolFile");
+
// Once we start resolving this type, remove it from the forward declaration
// map in case anyone child members or other types require this type to get resolved.
// The type will get resolved when all of the calls to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition
// are done.
- m_forward_decl_clang_type_to_die.erase (clang_type_no_qualifiers.GetOpaqueQualType());
-
- // Disable external storage for this type so we don't get anymore
- // clang::ExternalASTSource queries for this type.
- clang_type.SetHasExternalStorage (false);
-
- DWARFDebugInfo* debug_info = DebugInfo();
-
- DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitContainingDIE (die->GetOffset()).get();
- Type *type = m_die_to_type.lookup (die);
+ GetForwardDeclClangTypeToDie().erase (die_it);
- const dw_tag_t tag = die->Tag();
+ Type *type = GetDIEToType().lookup (dwarf_die.GetDIE());
Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
if (log)
GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log,
"0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...",
- MakeUserID(die->GetOffset()),
- DW_TAG_value_to_name(tag),
+ dwarf_die.GetID(),
+ dwarf_die.GetTagAsCString(),
type->GetName().AsCString());
- assert (clang_type);
- DWARFDebugInfoEntry::Attributes attributes;
-
- switch (tag)
- {
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type:
- {
- LayoutInfo layout_info;
-
- {
- if (die->HasChildren())
- {
- LanguageType class_language = eLanguageTypeUnknown;
- if (clang_type.IsObjCObjectOrInterfaceType())
- {
- class_language = eLanguageTypeObjC;
- // For objective C we don't start the definition when
- // the class is created.
- clang_type.StartTagDeclarationDefinition ();
- }
-
- int tag_decl_kind = -1;
- AccessType default_accessibility = eAccessNone;
- if (tag == DW_TAG_structure_type)
- {
- tag_decl_kind = clang::TTK_Struct;
- default_accessibility = eAccessPublic;
- }
- else if (tag == DW_TAG_union_type)
- {
- tag_decl_kind = clang::TTK_Union;
- default_accessibility = eAccessPublic;
- }
- else if (tag == DW_TAG_class_type)
- {
- tag_decl_kind = clang::TTK_Class;
- default_accessibility = eAccessPrivate;
- }
-
- SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu));
- std::vector<clang::CXXBaseSpecifier *> base_classes;
- std::vector<int> member_accessibilities;
- bool is_a_class = false;
- // Parse members and base classes first
- DWARFDIECollection member_function_dies;
-
- DelayedPropertyList delayed_properties;
- ParseChildMembers (sc,
- dwarf_cu,
- die,
- clang_type,
- class_language,
- base_classes,
- member_accessibilities,
- member_function_dies,
- delayed_properties,
- default_accessibility,
- is_a_class,
- layout_info);
-
- // Now parse any methods if there were any...
- size_t num_functions = member_function_dies.Size();
- if (num_functions > 0)
- {
- for (size_t i=0; i<num_functions; ++i)
- {
- ResolveType(dwarf_cu, member_function_dies.GetDIEPtrAtIndex(i));
- }
- }
-
- if (class_language == eLanguageTypeObjC)
- {
- ConstString class_name (clang_type.GetTypeName());
- if (class_name)
- {
- DIEArray method_die_offsets;
- if (m_using_apple_tables)
- {
- if (m_apple_objc_ap.get())
- m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets);
- }
- else
- {
- if (!m_indexed)
- Index ();
-
- m_objc_class_selectors_index.Find (class_name, method_die_offsets);
- }
-
- if (!method_die_offsets.empty())
- {
- DWARFDebugInfo* debug_info = DebugInfo();
-
- DWARFCompileUnit* method_cu = NULL;
- const size_t num_matches = method_die_offsets.size();
- for (size_t i=0; i<num_matches; ++i)
- {
- const dw_offset_t die_offset = method_die_offsets[i];
- DWARFDebugInfoEntry *method_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &method_cu);
-
- if (method_die)
- ResolveType (method_cu, method_die);
- else
- {
- if (m_using_apple_tables)
- {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_objc accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, class_name.GetCString());
- }
- }
- }
- }
-
- for (DelayedPropertyList::iterator pi = delayed_properties.begin(), pe = delayed_properties.end();
- pi != pe;
- ++pi)
- pi->Finalize();
- }
- }
-
- // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
- // need to tell the clang type it is actually a class.
- if (class_language != eLanguageTypeObjC)
- {
- if (is_a_class && tag_decl_kind != clang::TTK_Class)
- clang_type.SetTagTypeKind (clang::TTK_Class);
- }
-
- // Since DW_TAG_structure_type gets used for both classes
- // and structures, we may need to set any DW_TAG_member
- // fields to have a "private" access if none was specified.
- // When we parsed the child members we tracked that actual
- // accessibility value for each DW_TAG_member in the
- // "member_accessibilities" array. If the value for the
- // member is zero, then it was set to the "default_accessibility"
- // which for structs was "public". Below we correct this
- // by setting any fields to "private" that weren't correctly
- // set.
- if (is_a_class && !member_accessibilities.empty())
- {
- // This is a class and all members that didn't have
- // their access specified are private.
- clang_type.SetDefaultAccessForRecordFields (eAccessPrivate,
- &member_accessibilities.front(),
- member_accessibilities.size());
- }
-
- if (!base_classes.empty())
- {
- // Make sure all base classes refer to complete types and not
- // forward declarations. If we don't do this, clang will crash
- // with an assertion in the call to clang_type.SetBaseClassesForClassType()
- bool base_class_error = false;
- for (auto &base_class : base_classes)
- {
- clang::TypeSourceInfo *type_source_info = base_class->getTypeSourceInfo();
- if (type_source_info)
- {
- ClangASTType base_class_type (GetClangASTContext().getASTContext(), type_source_info->getType());
- if (base_class_type.GetCompleteType() == false)
- {
- if (!base_class_error)
- {
- GetObjectFile()->GetModule()->ReportError ("DWARF DIE at 0x%8.8x for class '%s' has a base class '%s' that is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s",
- die->GetOffset(),
- die->GetName(this, dwarf_cu),
- base_class_type.GetTypeName().GetCString(),
- sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file");
- }
- // We have no choice other than to pretend that the base class
- // is complete. If we don't do this, clang will crash when we
- // call setBases() inside of "clang_type.SetBaseClassesForClassType()"
- // below. Since we provide layout assistance, all ivars in this
- // class and other classes will be fine, this is the best we can do
- // short of crashing.
- base_class_type.StartTagDeclarationDefinition ();
- base_class_type.CompleteTagDeclarationDefinition ();
- }
- }
- }
- clang_type.SetBaseClassesForClassType (&base_classes.front(),
- base_classes.size());
-
- // Clang will copy each CXXBaseSpecifier in "base_classes"
- // so we have to free them all.
- ClangASTType::DeleteBaseClassSpecifiers (&base_classes.front(),
- base_classes.size());
- }
- }
- }
-
- clang_type.BuildIndirectFields ();
- clang_type.CompleteTagDeclarationDefinition ();
-
- if (!layout_info.field_offsets.empty() ||
- !layout_info.base_offsets.empty() ||
- !layout_info.vbase_offsets.empty() )
- {
- if (type)
- layout_info.bit_size = type->GetByteSize() * 8;
- if (layout_info.bit_size == 0)
- layout_info.bit_size = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_byte_size, 0) * 8;
-
- clang::CXXRecordDecl *record_decl = clang_type.GetAsCXXRecordDecl();
- if (record_decl)
- {
- if (log)
- {
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) caching layout info for record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u], base_offsets[%u], vbase_offsets[%u])",
- static_cast<void*>(clang_type.GetOpaqueQualType()),
- static_cast<void*>(record_decl),
- layout_info.bit_size,
- layout_info.alignment,
- static_cast<uint32_t>(layout_info.field_offsets.size()),
- static_cast<uint32_t>(layout_info.base_offsets.size()),
- static_cast<uint32_t>(layout_info.vbase_offsets.size()));
-
- uint32_t idx;
- {
- llvm::DenseMap<const clang::FieldDecl *, uint64_t>::const_iterator pos,
- end = layout_info.field_offsets.end();
- for (idx = 0, pos = layout_info.field_offsets.begin(); pos != end; ++pos, ++idx)
- {
- GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) field[%u] = "
- "{ bit_offset=%u, name='%s' }",
- static_cast<void *>(clang_type.GetOpaqueQualType()), idx,
- static_cast<uint32_t>(pos->second), pos->first->getNameAsString().c_str());
- }
- }
-
- {
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator base_pos,
- base_end = layout_info.base_offsets.end();
- for (idx = 0, base_pos = layout_info.base_offsets.begin(); base_pos != base_end;
- ++base_pos, ++idx)
- {
- GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) base[%u] "
- "= { byte_offset=%u, name='%s' }",
- clang_type.GetOpaqueQualType(), idx, (uint32_t)base_pos->second.getQuantity(),
- base_pos->first->getNameAsString().c_str());
- }
- }
- {
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator vbase_pos,
- vbase_end = layout_info.vbase_offsets.end();
- for (idx = 0, vbase_pos = layout_info.vbase_offsets.begin(); vbase_pos != vbase_end;
- ++vbase_pos, ++idx)
- {
- GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) "
- "vbase[%u] = { byte_offset=%u, name='%s' }",
- static_cast<void *>(clang_type.GetOpaqueQualType()), idx,
- static_cast<uint32_t>(vbase_pos->second.getQuantity()),
- vbase_pos->first->getNameAsString().c_str());
- }
- }
- }
- m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info));
- }
- }
- }
-
- return (bool)clang_type;
-
- case DW_TAG_enumeration_type:
- clang_type.StartTagDeclarationDefinition ();
- if (die->HasChildren())
- {
- SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu));
- bool is_signed = false;
- clang_type.IsIntegerType(is_signed);
- ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), dwarf_cu, die);
- }
- clang_type.CompleteTagDeclarationDefinition ();
- return (bool)clang_type;
-
- default:
- assert(false && "not a forward clang type decl!");
- break;
- }
+ assert (compiler_type);
+ DWARFASTParser *dwarf_ast = dwarf_die.GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->CompleteTypeFromDWARF (dwarf_die, type, compiler_type);
return false;
}
Type*
-SymbolFileDWARF::ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* type_die, bool assert_not_being_parsed)
+SymbolFileDWARF::ResolveType (const DWARFDIE &die, bool assert_not_being_parsed, bool resolve_function_context)
{
- if (type_die != NULL)
+ if (die)
{
- Type *type = m_die_to_type.lookup (type_die);
+ Type *type = GetDIEToType().lookup (die.GetDIE());
if (type == NULL)
- type = GetTypeForDIE (dwarf_cu, type_die).get();
+ type = GetTypeForDIE (die, resolve_function_context).get();
if (assert_not_being_parsed)
{
@@ -2829,15 +1652,15 @@ SymbolFileDWARF::ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEn
return type;
GetObjectFile()->GetModule()->ReportError ("Parsing a die that is being parsed die: 0x%8.8x: %s %s",
- type_die->GetOffset(),
- DW_TAG_value_to_name(type_die->Tag()),
- type_die->GetName(this, dwarf_cu));
+ die.GetOffset(),
+ die.GetTagAsCString(),
+ die.GetName());
}
else
return type;
}
- return NULL;
+ return nullptr;
}
CompileUnit*
@@ -2853,26 +1676,60 @@ SymbolFileDWARF::GetCompUnitForDWARFCompUnit (DWARFCompileUnit* dwarf_cu, uint32
return (CompileUnit*)dwarf_cu->GetUserData();
}
+size_t
+SymbolFileDWARF::GetObjCMethodDIEOffsets (ConstString class_name, DIEArray &method_die_offsets)
+{
+ method_die_offsets.clear();
+ if (m_using_apple_tables)
+ {
+ if (m_apple_objc_ap.get())
+ m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets);
+ }
+ else
+ {
+ if (!m_indexed)
+ Index ();
+
+ m_objc_class_selectors_index.Find (class_name, method_die_offsets);
+ }
+ return method_die_offsets.size();
+}
+
bool
-SymbolFileDWARF::GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* func_die, SymbolContext& sc)
+SymbolFileDWARF::GetFunction (const DWARFDIE &die, SymbolContext& sc)
{
sc.Clear(false);
- // Check if the symbol vendor already knows about this compile unit?
- sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
- sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(func_die->GetOffset())).get();
- if (sc.function == NULL)
- sc.function = ParseCompileUnitFunction(sc, dwarf_cu, func_die);
-
- if (sc.function)
- {
- sc.module_sp = sc.function->CalculateSymbolContextModule();
- return true;
+ if (die)
+ {
+ // Check if the symbol vendor already knows about this compile unit?
+ sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX);
+
+ sc.function = sc.comp_unit->FindFunctionByUID (die.GetID()).get();
+ if (sc.function == NULL)
+ sc.function = ParseCompileUnitFunction(sc, die);
+
+ if (sc.function)
+ {
+ sc.module_sp = sc.function->CalculateSymbolContextModule();
+ return true;
+ }
}
return false;
}
+lldb::ModuleSP
+SymbolFileDWARF::GetDWOModule (ConstString name)
+{
+ UpdateExternalModuleListIfNeeded();
+ const auto &pos = m_external_type_modules.find(name);
+ if (pos != m_external_type_modules.end())
+ return pos->second;
+ else
+ return lldb::ModuleSP();
+}
+
void
SymbolFileDWARF::UpdateExternalModuleListIfNeeded()
{
@@ -2881,47 +1738,33 @@ SymbolFileDWARF::UpdateExternalModuleListIfNeeded()
m_fetched_external_modules = true;
DWARFDebugInfo * debug_info = DebugInfo();
- debug_info->GetNumCompileUnits();
-
+
const uint32_t num_compile_units = GetNumCompileUnits();
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
{
DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- const DWARFDebugInfoEntry *die = dwarf_cu->GetCompileUnitDIEOnly();
- if (die && die->HasChildren() == false)
+ const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
+ if (die && die.HasChildren() == false)
{
- const uint64_t name_strp = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_name, UINT64_MAX);
- const uint64_t dwo_path_strp = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_GNU_dwo_name, UINT64_MAX);
-
- if (name_strp != UINT64_MAX)
+ const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
+
+ if (name)
{
- if (m_external_type_modules.find(dwo_path_strp) == m_external_type_modules.end())
+ ConstString const_name(name);
+ if (m_external_type_modules.find(const_name) == m_external_type_modules.end())
{
- const char *name = get_debug_str_data().PeekCStr(name_strp);
- const char *dwo_path = get_debug_str_data().PeekCStr(dwo_path_strp);
- if (name || dwo_path)
+ ModuleSP module_sp;
+ const char *dwo_path = die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
+ if (dwo_path)
{
- ModuleSP module_sp;
- if (dwo_path)
- {
- ModuleSpec dwo_module_spec;
- dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
- dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture();
- //printf ("Loading dwo = '%s'\n", dwo_path);
- Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL);
- }
-
- if (dwo_path_strp != LLDB_INVALID_UID)
- {
- m_external_type_modules[dwo_path_strp] = ClangModuleInfo { ConstString(name), module_sp };
- }
- else
- {
- // This hack should be removed promptly once clang emits both.
- m_external_type_modules[name_strp] = ClangModuleInfo { ConstString(name), module_sp };
- }
+ ModuleSpec dwo_module_spec;
+ dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
+ dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture();
+ //printf ("Loading dwo = '%s'\n", dwo_path);
+ Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL);
}
+ m_external_type_modules[const_name] = module_sp;
}
}
}
@@ -3025,7 +1868,7 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_
else
{
uint32_t cu_idx = DW_INVALID_INDEX;
- DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx).get();
+ DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx);
if (dwarf_cu)
{
sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx);
@@ -3036,22 +1879,16 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_
bool force_check_line_table = false;
if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock))
{
- DWARFDebugInfoEntry *function_die = NULL;
- DWARFDebugInfoEntry *block_die = NULL;
- if (resolve_scope & eSymbolContextBlock)
- {
- dwarf_cu->LookupAddress(file_vm_addr, &function_die, &block_die);
- }
- else
- {
- dwarf_cu->LookupAddress(file_vm_addr, &function_die, NULL);
- }
-
- if (function_die != NULL)
+ DWARFDIE function_die = dwarf_cu->LookupAddress(file_vm_addr);
+ DWARFDIE block_die;
+ if (function_die)
{
- sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(function_die->GetOffset())).get();
+ sc.function = sc.comp_unit->FindFunctionByUID (function_die.GetID()).get();
if (sc.function == NULL)
- sc.function = ParseCompileUnitFunction(sc, dwarf_cu, function_die);
+ sc.function = ParseCompileUnitFunction(sc, function_die);
+
+ if (sc.function && (resolve_scope & eSymbolContextBlock))
+ block_die = function_die.LookupDeepestBlock(file_vm_addr);
}
else
{
@@ -3072,10 +1909,10 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_
{
Block& block = sc.function->GetBlock (true);
- if (block_die != NULL)
- sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset()));
+ if (block_die)
+ sc.block = block.FindBlockByID (block_die.GetID());
else
- sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset()));
+ sc.block = block.FindBlockByID (function_die.GetID());
if (sc.block)
resolved |= eSymbolContextBlock;
}
@@ -3190,25 +2027,26 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line,
const lldb::addr_t file_vm_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress();
if (file_vm_addr != LLDB_INVALID_ADDRESS)
{
- DWARFDebugInfoEntry *function_die = NULL;
- DWARFDebugInfoEntry *block_die = NULL;
- dwarf_cu->LookupAddress(file_vm_addr, &function_die, resolve_scope & eSymbolContextBlock ? &block_die : NULL);
-
- if (function_die != NULL)
+ DWARFDIE function_die = dwarf_cu->LookupAddress(file_vm_addr);
+ DWARFDIE block_die;
+ if (function_die)
{
- sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(function_die->GetOffset())).get();
+ sc.function = sc.comp_unit->FindFunctionByUID (function_die.GetID()).get();
if (sc.function == NULL)
- sc.function = ParseCompileUnitFunction(sc, dwarf_cu, function_die);
+ sc.function = ParseCompileUnitFunction(sc, function_die);
+
+ if (sc.function && (resolve_scope & eSymbolContextBlock))
+ block_die = function_die.LookupDeepestBlock(file_vm_addr);
}
if (sc.function != NULL)
{
Block& block = sc.function->GetBlock (true);
- if (block_die != NULL)
- sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset()));
- else if (function_die != NULL)
- sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset()));
+ if (block_die)
+ sc.block = block.FindBlockByID (block_die.GetID());
+ else if (function_die)
+ sc.block = block.FindBlockByID (function_die.GetID());
}
}
}
@@ -3255,38 +2093,77 @@ SymbolFileDWARF::Index ()
DWARFDebugInfo* debug_info = DebugInfo();
if (debug_info)
{
- uint32_t cu_idx = 0;
const uint32_t num_compile_units = GetNumCompileUnits();
- for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+ std::vector<NameToDIE> function_basename_index(num_compile_units);
+ std::vector<NameToDIE> function_fullname_index(num_compile_units);
+ std::vector<NameToDIE> function_method_index(num_compile_units);
+ std::vector<NameToDIE> function_selector_index(num_compile_units);
+ std::vector<NameToDIE> objc_class_selectors_index(num_compile_units);
+ std::vector<NameToDIE> global_index(num_compile_units);
+ std::vector<NameToDIE> type_index(num_compile_units);
+ std::vector<NameToDIE> namespace_index(num_compile_units);
+
+ auto parser_fn = [this,
+ debug_info,
+ &function_basename_index,
+ &function_fullname_index,
+ &function_method_index,
+ &function_selector_index,
+ &objc_class_selectors_index,
+ &global_index,
+ &type_index,
+ &namespace_index](uint32_t cu_idx)
{
DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+ bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded(false) > 1;
+
+ dwarf_cu->Index(function_basename_index[cu_idx],
+ function_fullname_index[cu_idx],
+ function_method_index[cu_idx],
+ function_selector_index[cu_idx],
+ objc_class_selectors_index[cu_idx],
+ global_index[cu_idx],
+ type_index[cu_idx],
+ namespace_index[cu_idx]);
- bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded (false) > 1;
-
- dwarf_cu->Index (cu_idx,
- m_function_basename_index,
- m_function_fullname_index,
- m_function_method_index,
- m_function_selector_index,
- m_objc_class_selectors_index,
- m_global_index,
- m_type_index,
- m_namespace_index);
-
// Keep memory down by clearing DIEs if this generate function
// caused them to be parsed
if (clear_dies)
- dwarf_cu->ClearDIEs (true);
+ dwarf_cu->ClearDIEs(true);
+
+ return cu_idx;
+ };
+
+ TaskRunner<uint32_t> task_runner;
+ for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+ task_runner.AddTask(parser_fn, cu_idx);
+
+ while (true)
+ {
+ std::future<uint32_t> f = task_runner.WaitForNextCompletedTask();
+ if (!f.valid())
+ break;
+ uint32_t cu_idx = f.get();
+
+ m_function_basename_index.Append(function_basename_index[cu_idx]);
+ m_function_fullname_index.Append(function_fullname_index[cu_idx]);
+ m_function_method_index.Append(function_method_index[cu_idx]);
+ m_function_selector_index.Append(function_selector_index[cu_idx]);
+ m_objc_class_selectors_index.Append(objc_class_selectors_index[cu_idx]);
+ m_global_index.Append(global_index[cu_idx]);
+ m_type_index.Append(type_index[cu_idx]);
+ m_namespace_index.Append(namespace_index[cu_idx]);
}
-
- m_function_basename_index.Finalize();
- m_function_fullname_index.Finalize();
- m_function_method_index.Finalize();
- m_function_selector_index.Finalize();
- m_objc_class_selectors_index.Finalize();
- m_global_index.Finalize();
- m_type_index.Finalize();
- m_namespace_index.Finalize();
+
+ TaskPool::RunTasks(
+ [&]() { m_function_basename_index.Finalize(); },
+ [&]() { m_function_fullname_index.Finalize(); },
+ [&]() { m_function_method_index.Finalize(); },
+ [&]() { m_function_selector_index.Finalize(); },
+ [&]() { m_objc_class_selectors_index.Finalize(); },
+ [&]() { m_global_index.Finalize(); },
+ [&]() { m_type_index.Finalize(); },
+ [&]() { m_namespace_index.Finalize(); });
#if defined (ENABLE_DEBUG_PRINTF)
StreamFile s(stdout, false);
@@ -3299,30 +2176,26 @@ SymbolFileDWARF::Index ()
s.Printf("\nObjective C class selectors:\n"); m_objc_class_selectors_index.Dump (&s);
s.Printf("\nGlobals and statics:\n"); m_global_index.Dump (&s);
s.Printf("\nTypes:\n"); m_type_index.Dump (&s);
- s.Printf("\nNamepaces:\n"); m_namespace_index.Dump (&s);
+ s.Printf("\nNamespaces:\n") m_namespace_index.Dump (&s);
#endif
}
}
bool
-SymbolFileDWARF::NamespaceDeclMatchesThisSymbolFile (const ClangNamespaceDecl *namespace_decl)
+SymbolFileDWARF::DeclContextMatchesThisSymbolFile (const lldb_private::CompilerDeclContext *decl_ctx)
{
- if (namespace_decl == NULL)
+ if (decl_ctx == nullptr || !decl_ctx->IsValid())
{
// Invalid namespace decl which means we aren't matching only things
// in this symbol file, so return true to indicate it matches this
// symbol file.
return true;
}
-
- clang::ASTContext *namespace_ast = namespace_decl->GetASTContext();
- if (namespace_ast == NULL)
- return true; // No AST in the "namespace_decl", return true since it
- // could then match any symbol file, including this one
-
- if (namespace_ast == GetClangASTContext().getASTContext())
- return true; // The ASTs match, return true
+ TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem();
+ TypeSystem *type_system = GetTypeSystemForLanguage(decl_ctx_type_system->GetMinimumLanguage(nullptr));
+ if (decl_ctx_type_system == type_system)
+ return true; // The type systems match, return true
// The namespace AST was valid, and it does not match...
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
@@ -3333,66 +2206,19 @@ SymbolFileDWARF::NamespaceDeclMatchesThisSymbolFile (const ClangNamespaceDecl *n
return false;
}
-bool
-SymbolFileDWARF::DIEIsInNamespace (const ClangNamespaceDecl *namespace_decl,
- DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry* die)
-{
- // No namespace specified, so the answer is
- if (namespace_decl == NULL)
- return true;
-
- Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
-
- const DWARFDebugInfoEntry *decl_ctx_die = NULL;
- clang::DeclContext *die_clang_decl_ctx = GetClangDeclContextContainingDIE (cu, die, &decl_ctx_die);
- if (decl_ctx_die)
- {
- clang::NamespaceDecl *clang_namespace_decl = namespace_decl->GetNamespaceDecl();
-
- if (clang_namespace_decl)
- {
- if (decl_ctx_die->Tag() != DW_TAG_namespace)
- {
- if (log)
- GetObjectFile()->GetModule()->LogMessage(log, "Found a match, but its parent is not a namespace");
- return false;
- }
-
- if (clang_namespace_decl == die_clang_decl_ctx)
- return true;
- else
- return false;
- }
- else
- {
- // We have a namespace_decl that was not NULL but it contained
- // a NULL "clang::NamespaceDecl", so this means the global namespace
- // So as long the contained decl context DIE isn't a namespace
- // we should be ok.
- if (decl_ctx_die->Tag() != DW_TAG_namespace)
- return true;
- }
- }
-
- if (log)
- GetObjectFile()->GetModule()->LogMessage(log, "Found a match, but its parent doesn't exist");
-
- return false;
-}
uint32_t
-SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
+SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, VariableList& variables)
{
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
if (log)
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables)",
+ "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", parent_decl_ctx=%p, append=%u, max_matches=%u, variables)",
name.GetCString(),
- static_cast<const void*>(namespace_decl),
+ static_cast<const void*>(parent_decl_ctx),
append, max_matches);
- if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
return 0;
DWARFDebugInfo* info = DebugInfo();
@@ -3417,7 +2243,7 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
llvm::StringRef basename;
llvm::StringRef context;
- if (!CPPLanguageRuntime::ExtractContextAndIdentifier(name_cstr, context, basename))
+ if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, basename))
basename = name_cstr;
m_apple_names_ap->FindByName (basename.data(), die_offsets);
@@ -3440,17 +2266,15 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
assert (sc.module_sp);
DWARFDebugInfo* debug_info = DebugInfo();
- DWARFCompileUnit* dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
bool done = false;
for (size_t i=0; i<num_die_matches && !done; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
if (die)
{
- switch (die->Tag())
+ switch (die.Tag())
{
default:
case DW_TAG_subprogram:
@@ -3461,12 +2285,20 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
case DW_TAG_variable:
{
- sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
+ sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX);
- if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
- continue;
+ if (parent_decl_ctx)
+ {
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
+ {
+ CompilerDeclContext actual_parent_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF (die);
+ if (!actual_parent_decl_ctx || actual_parent_decl_ctx != *parent_decl_ctx)
+ continue;
+ }
+ }
- ParseVariables(sc, dwarf_cu, LLDB_INVALID_ADDRESS, die, false, false, &variables);
+ ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables);
if (variables.GetSize() - original_size >= max_matches)
done = true;
@@ -3479,7 +2311,7 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, name.GetCString());
+ die_ref.die_offset, name.GetCString());
}
}
}
@@ -3490,9 +2322,9 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
if (log && num_matches > 0)
{
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables) => %u",
+ "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", parent_decl_ctx=%p, append=%u, max_matches=%u, variables) => %u",
name.GetCString(),
- static_cast<const void*>(namespace_decl),
+ static_cast<const void*>(parent_decl_ctx),
append, max_matches,
num_matches);
}
@@ -3525,7 +2357,7 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
const uint32_t original_size = variables.GetSize();
DIEArray die_offsets;
-
+
if (m_using_apple_tables)
{
if (m_apple_names_ap.get())
@@ -3548,22 +2380,20 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
sc.module_sp = m_obj_file->GetModule();
assert (sc.module_sp);
- DWARFCompileUnit* dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
const size_t num_matches = die_offsets.size();
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
if (die)
{
- sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
+ sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX);
- ParseVariables(sc, dwarf_cu, LLDB_INVALID_ADDRESS, die, false, false, &variables);
+ ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables);
if (variables.GetSize() - original_size >= max_matches)
break;
@@ -3573,7 +2403,7 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for regex '%s')\n",
- die_offset, regex.GetText());
+ die_ref.die_offset, regex.GetText());
}
}
}
@@ -3585,53 +2415,59 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
bool
-SymbolFileDWARF::ResolveFunction (dw_offset_t die_offset,
- DWARFCompileUnit *&dwarf_cu,
+SymbolFileDWARF::ResolveFunction (const DIERef& die_ref,
bool include_inlines,
SymbolContextList& sc_list)
{
- const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
- return ResolveFunction (dwarf_cu, die, include_inlines, sc_list);
+ DWARFDIE die = DebugInfo()->GetDIE (die_ref);
+ return ResolveFunction (die, include_inlines, sc_list);
}
bool
-SymbolFileDWARF::ResolveFunction (DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
+SymbolFileDWARF::ResolveFunction (const DWARFDIE &orig_die,
bool include_inlines,
SymbolContextList& sc_list)
{
SymbolContext sc;
- if (die == NULL)
+ if (!orig_die)
return false;
// If we were passed a die that is not a function, just return false...
- if (! (die->Tag() == DW_TAG_subprogram || (include_inlines && die->Tag() == DW_TAG_inlined_subroutine)))
+ if (!(orig_die.Tag() == DW_TAG_subprogram || (include_inlines && orig_die.Tag() == DW_TAG_inlined_subroutine)))
return false;
-
- const DWARFDebugInfoEntry* inlined_die = NULL;
- if (die->Tag() == DW_TAG_inlined_subroutine)
+
+ DWARFDIE die = orig_die;
+ DWARFDIE inlined_die;
+ if (die.Tag() == DW_TAG_inlined_subroutine)
{
inlined_die = die;
- while ((die = die->GetParent()) != NULL)
+ while (1)
{
- if (die->Tag() == DW_TAG_subprogram)
+ die = die.GetParent();
+
+ if (die)
+ {
+ if (die.Tag() == DW_TAG_subprogram)
+ break;
+ }
+ else
break;
}
}
- assert (die && die->Tag() == DW_TAG_subprogram);
- if (GetFunction (cu, die, sc))
+ assert (die && die.Tag() == DW_TAG_subprogram);
+ if (GetFunction (die, sc))
{
Address addr;
// Parse all blocks if needed
if (inlined_die)
{
Block &function_block = sc.function->GetBlock (true);
- sc.block = function_block.FindBlockByID (MakeUserID(inlined_die->GetOffset()));
+ sc.block = function_block.FindBlockByID (inlined_die.GetID());
if (sc.block == NULL)
- sc.block = function_block.FindBlockByID (inlined_die->GetOffset());
+ sc.block = function_block.FindBlockByID (inlined_die.GetOffset());
if (sc.block == NULL || sc.block->GetStartAddress (addr) == false)
addr.Clear();
}
@@ -3702,131 +2538,37 @@ SymbolFileDWARF::ParseFunctions (const DIEArray &die_offsets,
const size_t num_matches = die_offsets.size();
if (num_matches)
{
- DWARFCompileUnit* dwarf_cu = NULL;
for (size_t i=0; i<num_matches; ++i)
- {
- const dw_offset_t die_offset = die_offsets[i];
- ResolveFunction (die_offset, dwarf_cu, include_inlines, sc_list);
- }
+ ResolveFunction (die_offsets[i], include_inlines, sc_list);
}
}
bool
-SymbolFileDWARF::FunctionDieMatchesPartialName (const DWARFDebugInfoEntry* die,
- const DWARFCompileUnit *dwarf_cu,
- uint32_t name_type_mask,
- const char *partial_name,
- const char *base_name_start,
- const char *base_name_end)
+SymbolFileDWARF::DIEInDeclContext (const CompilerDeclContext *decl_ctx,
+ const DWARFDIE &die)
{
- // If we are looking only for methods, throw away all the ones that are or aren't in C++ classes:
- if (name_type_mask == eFunctionNameTypeMethod || name_type_mask == eFunctionNameTypeBase)
- {
- clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIEOffset(die->GetOffset());
- if (!containing_decl_ctx)
- return false;
-
- bool is_cxx_method = DeclKindIsCXXClass(containing_decl_ctx->getDeclKind());
-
- if (name_type_mask == eFunctionNameTypeMethod)
- {
- if (is_cxx_method == false)
- return false;
- }
-
- if (name_type_mask == eFunctionNameTypeBase)
- {
- if (is_cxx_method == true)
- return false;
- }
- }
+ // If we have no parent decl context to match this DIE matches, and if the parent
+ // decl context isn't valid, we aren't trying to look for any particular decl
+ // context so any die matches.
+ if (decl_ctx == nullptr || !decl_ctx->IsValid())
+ return true;
- // Now we need to check whether the name we got back for this type matches the extra specifications
- // that were in the name we're looking up:
- if (base_name_start != partial_name || *base_name_end != '\0')
+ if (die)
{
- // First see if the stuff to the left matches the full name. To do that let's see if
- // we can pull out the mips linkage name attribute:
-
- Mangled best_name;
- DWARFDebugInfoEntry::Attributes attributes;
- DWARFFormValue form_value;
- die->GetAttributes(this, dwarf_cu, NULL, attributes);
- uint32_t idx = attributes.FindAttributeIndex(DW_AT_MIPS_linkage_name);
- if (idx == UINT32_MAX)
- idx = attributes.FindAttributeIndex(DW_AT_linkage_name);
- if (idx != UINT32_MAX)
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
{
- if (attributes.ExtractFormValueAtIndex(this, idx, form_value))
- {
- const char *mangled_name = form_value.AsCString(&get_debug_str_data());
- if (mangled_name)
- best_name.SetValue (ConstString(mangled_name), true);
- }
- }
-
- if (!best_name)
- {
- idx = attributes.FindAttributeIndex(DW_AT_name);
- if (idx != UINT32_MAX && attributes.ExtractFormValueAtIndex(this, idx, form_value))
- {
- const char *name = form_value.AsCString(&get_debug_str_data());
- best_name.SetValue (ConstString(name), false);
- }
- }
-
- const LanguageType cu_language = const_cast<DWARFCompileUnit *>(dwarf_cu)->GetLanguageType();
- if (best_name.GetDemangledName(cu_language))
- {
- const char *demangled = best_name.GetDemangledName(cu_language).GetCString();
- if (demangled)
- {
- std::string name_no_parens(partial_name, base_name_end - partial_name);
- const char *partial_in_demangled = strstr (demangled, name_no_parens.c_str());
- if (partial_in_demangled == NULL)
- return false;
- else
- {
- // Sort out the case where our name is something like "Process::Destroy" and the match is
- // "SBProcess::Destroy" - that shouldn't be a match. We should really always match on
- // namespace boundaries...
-
- if (partial_name[0] == ':' && partial_name[1] == ':')
- {
- // The partial name was already on a namespace boundary so all matches are good.
- return true;
- }
- else if (partial_in_demangled == demangled)
- {
- // They both start the same, so this is an good match.
- return true;
- }
- else
- {
- if (partial_in_demangled - demangled == 1)
- {
- // Only one character difference, can't be a namespace boundary...
- return false;
- }
- else if (*(partial_in_demangled - 1) == ':' && *(partial_in_demangled - 2) == ':')
- {
- // We are on a namespace boundary, so this is also good.
- return true;
- }
- else
- return false;
- }
- }
- }
+ CompilerDeclContext actual_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF (die);
+ if (actual_decl_ctx)
+ return actual_decl_ctx == *decl_ctx;
}
}
-
- return true;
+ return false;
}
uint32_t
-SymbolFileDWARF::FindFunctions (const ConstString &name,
- const lldb_private::ClangNamespaceDecl *namespace_decl,
+SymbolFileDWARF::FindFunctions (const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
uint32_t name_type_mask,
bool include_inlines,
bool append,
@@ -3854,7 +2596,7 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
if (!append)
sc_list.Clear();
- if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
return 0;
// If name is empty then we won't find anything.
@@ -3872,7 +2614,6 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
if (info == NULL)
return 0;
- DWARFCompileUnit *dwarf_cu = NULL;
std::set<const DWARFDebugInfoEntry *> resolved_dies;
if (m_using_apple_tables)
{
@@ -3891,30 +2632,30 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
for (uint32_t i = 0; i < num_matches; i++)
{
- const dw_offset_t die_offset = die_offsets[i];
- const DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = info->GetDIE (die_ref);
if (die)
{
- if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
- continue;
-
- if (resolved_dies.find(die) == resolved_dies.end())
+ if (!DIEInDeclContext(parent_decl_ctx, die))
+ continue; // The containing decl contexts don't match
+
+ if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())
{
- if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list))
- resolved_dies.insert(die);
+ if (ResolveFunction (die, include_inlines, sc_list))
+ resolved_dies.insert(die.GetDIE());
}
}
else
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
- die_offset, name_cstr);
+ die_ref.die_offset, name_cstr);
}
}
}
if (name_type_mask & eFunctionNameTypeSelector)
{
- if (namespace_decl && *namespace_decl)
+ if (parent_decl_ctx && parent_decl_ctx->IsValid())
return 0; // no selectors in namespaces
num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
@@ -3923,30 +2664,30 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
for (uint32_t i = 0; i < num_matches; i++)
{
- const dw_offset_t die_offset = die_offsets[i];
- const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = info->GetDIE (die_ref);
if (die)
{
- const char *die_name = die->GetName(this, dwarf_cu);
- if (ObjCLanguageRuntime::IsPossibleObjCMethodName(die_name))
+ const char *die_name = die.GetName();
+ if (ObjCLanguage::IsPossibleObjCMethodName(die_name))
{
- if (resolved_dies.find(die) == resolved_dies.end())
+ if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())
{
- if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list))
- resolved_dies.insert(die);
+ if (ResolveFunction (die, include_inlines, sc_list))
+ resolved_dies.insert(die.GetDIE());
}
}
}
else
{
GetObjectFile()->GetModule()->ReportError ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
- die_offset, name_cstr);
+ die_ref.die_offset, name_cstr);
}
}
die_offsets.clear();
}
- if (((name_type_mask & eFunctionNameTypeMethod) && !namespace_decl) || name_type_mask & eFunctionNameTypeBase)
+ if (((name_type_mask & eFunctionNameTypeMethod) && !parent_decl_ctx) || name_type_mask & eFunctionNameTypeBase)
{
// The apple_names table stores just the "base name" of C++ methods in the table. So we have to
// extract the base name, look that up, and if there is any other information in the name we were
@@ -3957,16 +2698,16 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
for (uint32_t i = 0; i < num_matches; i++)
{
- const dw_offset_t die_offset = die_offsets[i];
- const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = info->GetDIE (die_ref);
if (die)
{
- if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
- continue;
+ if (!DIEInDeclContext(parent_decl_ctx, die))
+ continue; // The containing decl contexts don't match
+
// If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die) == resolved_dies.end())
- if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list))
+ if (resolved_dies.find(die.GetDIE()) == resolved_dies.end() && ResolveFunction (die, include_inlines, sc_list))
{
bool keep_die = true;
if ((name_type_mask & (eFunctionNameTypeBase|eFunctionNameTypeMethod)) != (eFunctionNameTypeBase|eFunctionNameTypeMethod))
@@ -3986,8 +2727,8 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
if (type)
{
- clang::DeclContext* decl_ctx = GetClangDeclContextContainingTypeUID (type->GetID());
- if (decl_ctx->isRecord())
+ CompilerDeclContext decl_ctx = GetDeclContextContainingUID (type->GetID());
+ if (decl_ctx.IsStructUnionOrClass())
{
if (name_type_mask & eFunctionNameTypeBase)
{
@@ -4007,19 +2748,19 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
else
{
GetObjectFile()->GetModule()->ReportWarning ("function at die offset 0x%8.8x had no function type",
- die_offset);
+ die_ref.die_offset);
}
}
}
}
if (keep_die)
- resolved_dies.insert(die);
+ resolved_dies.insert(die.GetDIE());
}
}
else
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
- die_offset, name_cstr);
+ die_ref.die_offset, name_cstr);
}
}
die_offsets.clear();
@@ -4046,10 +2787,10 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
// TODO: The arch in the object file isn't correct for MSVC
// binaries on windows, we should find a way to make it
// correct and handle those symbols as well.
- if (sc_list.GetSize() == 0)
+ if (sc_list.GetSize() == original_size)
{
ArchSpec arch;
- if (!namespace_decl &&
+ if (!parent_decl_ctx &&
GetObjectFile()->GetArchitecture(arch) &&
(arch.GetTriple().isOSFreeBSD() || arch.GetTriple().isOSLinux() ||
arch.GetMachine() == llvm::Triple::hexagon))
@@ -4076,24 +2817,22 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
}
}
DIEArray die_offsets;
- DWARFCompileUnit *dwarf_cu = NULL;
-
if (name_type_mask & eFunctionNameTypeBase)
{
uint32_t num_base = m_function_basename_index.Find(name, die_offsets);
for (uint32_t i = 0; i < num_base; i++)
{
- const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu);
+ DWARFDIE die = info->GetDIE (die_offsets[i]);
if (die)
{
- if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
- continue;
-
+ if (!DIEInDeclContext(parent_decl_ctx, die))
+ continue; // The containing decl contexts don't match
+
// If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die) == resolved_dies.end())
+ if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())
{
- if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list))
- resolved_dies.insert(die);
+ if (ResolveFunction (die, include_inlines, sc_list))
+ resolved_dies.insert(die.GetDIE());
}
}
}
@@ -4102,21 +2841,21 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
if (name_type_mask & eFunctionNameTypeMethod)
{
- if (namespace_decl && *namespace_decl)
+ if (parent_decl_ctx && parent_decl_ctx->IsValid())
return 0; // no methods in namespaces
uint32_t num_base = m_function_method_index.Find(name, die_offsets);
{
for (uint32_t i = 0; i < num_base; i++)
{
- const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu);
+ DWARFDIE die = info->GetDIE (die_offsets[i]);
if (die)
{
// If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die) == resolved_dies.end())
+ if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())
{
- if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list))
- resolved_dies.insert(die);
+ if (ResolveFunction (die, include_inlines, sc_list))
+ resolved_dies.insert(die.GetDIE());
}
}
}
@@ -4124,7 +2863,7 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
die_offsets.clear();
}
- if ((name_type_mask & eFunctionNameTypeSelector) && (!namespace_decl || !*namespace_decl))
+ if ((name_type_mask & eFunctionNameTypeSelector) && (!parent_decl_ctx || !parent_decl_ctx->IsValid()))
{
FindFunctions (name, m_function_selector_index, include_inlines, sc_list);
}
@@ -4193,13 +2932,47 @@ SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool include_inli
return sc_list.GetSize() - original_size;
}
+void
+SymbolFileDWARF::GetMangledNamesForFunction (const std::string &scope_qualified_name,
+ std::vector<ConstString> &mangled_names)
+{
+ DWARFDebugInfo* info = DebugInfo();
+ uint32_t num_comp_units = 0;
+ if (info)
+ num_comp_units = info->GetNumCompileUnits();
+
+ for (uint32_t i = 0; i < num_comp_units; i++)
+ {
+ DWARFCompileUnit *cu = info->GetCompileUnitAtIndex(i);
+ if (cu == nullptr)
+ continue;
+
+ SymbolFileDWARFDwo *dwo = cu->GetDwoSymbolFile();
+ if (dwo)
+ dwo->GetMangledNamesForFunction(scope_qualified_name, mangled_names);
+ }
+
+ NameToOffsetMap::iterator iter = m_function_scope_qualified_name_map.find(scope_qualified_name);
+ if (iter == m_function_scope_qualified_name_map.end())
+ return;
+
+ DIERefSetSP set_sp = (*iter).second;
+ std::set<DIERef>::iterator set_iter;
+ for (set_iter = set_sp->begin(); set_iter != set_sp->end(); set_iter++)
+ {
+ DWARFDIE die = DebugInfo()->GetDIE (*set_iter);
+ mangled_names.push_back(ConstString(die.GetMangledName()));
+ }
+}
+
+
uint32_t
SymbolFileDWARF::FindTypes (const SymbolContext& sc,
const ConstString &name,
- const lldb_private::ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
bool append,
uint32_t max_matches,
- TypeList& types)
+ TypeMap& types)
{
DWARFDebugInfo* info = DebugInfo();
if (info == NULL)
@@ -4209,16 +2982,16 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
if (log)
{
- if (namespace_decl)
+ if (parent_decl_ctx)
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list)",
+ "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = %p (\"%s\"), append=%u, max_matches=%u, type_list)",
name.GetCString(),
- static_cast<void*>(namespace_decl->GetNamespaceDecl()),
- namespace_decl->GetQualifiedName().c_str(),
+ static_cast<const void*>(parent_decl_ctx),
+ parent_decl_ctx->GetName().AsCString("<NULL>"),
append, max_matches);
else
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list)",
+ "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = NULL, append=%u, max_matches=%u, type_list)",
name.GetCString(), append,
max_matches);
}
@@ -4227,7 +3000,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
if (!append)
types.Clear();
- if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
return 0;
DIEArray die_offsets;
@@ -4253,20 +3026,18 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
if (num_die_matches)
{
const uint32_t initial_types_size = types.GetSize();
- DWARFCompileUnit* dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_die_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
if (die)
{
- if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
- continue;
+ if (!DIEInDeclContext(parent_decl_ctx, die))
+ continue; // The containing decl contexts don't match
- Type *matching_type = ResolveType (dwarf_cu, die);
+ Type *matching_type = ResolveType (die, true, true);
if (matching_type)
{
// We found a type pointer, now find the shared pointer form our type list
@@ -4280,7 +3051,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, name.GetCString());
+ die_ref.die_offset, name.GetCString());
}
}
@@ -4288,20 +3059,20 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
const uint32_t num_matches = types.GetSize() - initial_types_size;
if (log && num_matches)
{
- if (namespace_decl)
+ if (parent_decl_ctx)
{
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list) => %u",
+ "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = %p (\"%s\"), append=%u, max_matches=%u, type_list) => %u",
name.GetCString(),
- static_cast<void*>(namespace_decl->GetNamespaceDecl()),
- namespace_decl->GetQualifiedName().c_str(),
+ static_cast<const void*>(parent_decl_ctx),
+ parent_decl_ctx->GetName().AsCString("<NULL>"),
append, max_matches,
num_matches);
}
else
{
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list) => %u",
+ "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = NULL, append=%u, max_matches=%u, type_list) => %u",
name.GetCString(),
append, max_matches,
num_matches);
@@ -4309,14 +3080,112 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
}
return num_matches;
}
+ else
+ {
+ UpdateExternalModuleListIfNeeded();
+
+ for (const auto &pair : m_external_type_modules)
+ {
+ ModuleSP external_module_sp = pair.second;
+ if (external_module_sp)
+ {
+ SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor();
+ if (sym_vendor)
+ {
+ const uint32_t num_external_matches = sym_vendor->FindTypes (sc,
+ name,
+ parent_decl_ctx,
+ append,
+ max_matches,
+ types);
+ if (num_external_matches)
+ return num_external_matches;
+ }
+ }
+ }
+ }
+
return 0;
}
-ClangNamespaceDecl
+size_t
+SymbolFileDWARF::FindTypes (const std::vector<CompilerContext> &context,
+ bool append,
+ TypeMap& types)
+{
+ if (!append)
+ types.Clear();
+
+ if (context.empty())
+ return 0;
+
+ DIEArray die_offsets;
+
+ ConstString name = context.back().name;
+
+ if (m_using_apple_tables)
+ {
+ if (m_apple_types_ap.get())
+ {
+ const char *name_cstr = name.GetCString();
+ m_apple_types_ap->FindByName (name_cstr, die_offsets);
+ }
+ }
+ else
+ {
+ if (!m_indexed)
+ Index ();
+
+ m_type_index.Find (name, die_offsets);
+ }
+
+ const size_t num_die_matches = die_offsets.size();
+
+ if (num_die_matches)
+ {
+ size_t num_matches = 0;
+ DWARFDebugInfo* debug_info = DebugInfo();
+ for (size_t i=0; i<num_die_matches; ++i)
+ {
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
+
+ if (die)
+ {
+ std::vector<CompilerContext> die_context;
+ die.GetDWOContext(die_context);
+ if (die_context != context)
+ continue;
+
+ Type *matching_type = ResolveType (die, true, true);
+ if (matching_type)
+ {
+ // We found a type pointer, now find the shared pointer form our type list
+ types.InsertUnique (matching_type->shared_from_this());
+ ++num_matches;
+ }
+ }
+ else
+ {
+ if (m_using_apple_tables)
+ {
+ GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
+ die_ref.die_offset, name.GetCString());
+ }
+ }
+
+ }
+ return num_matches;
+ }
+ return 0;
+}
+
+
+CompilerDeclContext
SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
const ConstString &name,
- const lldb_private::ClangNamespaceDecl *parent_namespace_decl)
+ const CompilerDeclContext *parent_decl_ctx)
{
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
@@ -4326,11 +3195,13 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
"SymbolFileDWARF::FindNamespace (sc, name=\"%s\")",
name.GetCString());
}
-
- if (!NamespaceDeclMatchesThisSymbolFile(parent_namespace_decl))
- return ClangNamespaceDecl();
- ClangNamespaceDecl namespace_decl;
+ CompilerDeclContext namespace_decl_ctx;
+
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
+ return namespace_decl_ctx;
+
+
DWARFDebugInfo* info = DebugInfo();
if (info)
{
@@ -4354,28 +3225,26 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
m_namespace_index.Find (name, die_offsets);
}
- DWARFCompileUnit* dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
const size_t num_matches = die_offsets.size();
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
-
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
+
if (die)
{
- if (parent_namespace_decl && !DIEIsInNamespace (parent_namespace_decl, dwarf_cu, die))
- continue;
+ if (!DIEInDeclContext (parent_decl_ctx, die))
+ continue; // The containing decl contexts don't match
- clang::NamespaceDecl *clang_namespace_decl = ResolveNamespaceDIE (dwarf_cu, die);
- if (clang_namespace_decl)
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
{
- namespace_decl.SetASTContext (GetClangASTContext().getASTContext());
- namespace_decl.SetNamespaceDecl (clang_namespace_decl);
- break;
+ namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF (die);
+ if (namespace_decl_ctx)
+ break;
}
}
else
@@ -4383,421 +3252,50 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_namespaces accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, name.GetCString());
+ die_ref.die_offset, name.GetCString());
}
}
}
}
}
- if (log && namespace_decl.GetNamespaceDecl())
+ if (log && namespace_decl_ctx)
{
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => clang::NamespaceDecl(%p) \"%s\"",
+ "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => CompilerDeclContext(%p/%p) \"%s\"",
name.GetCString(),
- static_cast<const void*>(namespace_decl.GetNamespaceDecl()),
- namespace_decl.GetQualifiedName().c_str());
- }
-
- return namespace_decl;
-}
-
-uint32_t
-SymbolFileDWARF::FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, TypeList& types)
-{
- // Remember how many sc_list are in the list before we search in case
- // we are appending the results to a variable list.
- uint32_t original_size = types.GetSize();
-
- const uint32_t num_die_offsets = die_offsets.size();
- // Parse all of the types we found from the pubtypes matches
- uint32_t i;
- uint32_t num_matches = 0;
- for (i = 0; i < num_die_offsets; ++i)
- {
- Type *matching_type = ResolveTypeUID (die_offsets[i]);
- if (matching_type)
- {
- // We found a type pointer, now find the shared pointer form our type list
- types.InsertUnique (matching_type->shared_from_this());
- ++num_matches;
- if (num_matches >= max_matches)
- break;
- }
- }
-
- // Return the number of variable that were appended to the list
- return types.GetSize() - original_size;
-}
-
-
-size_t
-SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc,
- clang::DeclContext *containing_decl_ctx,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- bool skip_artificial,
- bool &is_static,
- bool &is_variadic,
- std::vector<ClangASTType>& function_param_types,
- std::vector<clang::ParmVarDecl*>& function_param_decls,
- unsigned &type_quals) // ,
- // ClangASTContext::TemplateParameterInfos &template_param_infos))
-{
- if (parent_die == NULL)
- return 0;
-
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
-
- size_t arg_idx = 0;
- const DWARFDebugInfoEntry *die;
- for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
- {
- dw_tag_t tag = die->Tag();
- switch (tag)
- {
- case DW_TAG_formal_parameter:
- {
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes);
- if (num_attributes > 0)
- {
- const char *name = NULL;
- Declaration decl;
- dw_offset_t param_type_die_offset = DW_INVALID_OFFSET;
- bool is_artificial = false;
- // one of None, Auto, Register, Extern, Static, PrivateExtern
-
- clang::StorageClass storage = clang::SC_None;
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: param_type_die_offset = form_value.Reference(); break;
- case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
- case DW_AT_location:
- // if (form_value.BlockData())
- // {
- // const DWARFDataExtractor& debug_info_data = debug_info();
- // uint32_t block_length = form_value.Unsigned();
- // DWARFDataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length);
- // }
- // else
- // {
- // }
- // break;
- case DW_AT_const_value:
- case DW_AT_default_value:
- case DW_AT_description:
- case DW_AT_endianity:
- case DW_AT_is_optional:
- case DW_AT_segment:
- case DW_AT_variable_parameter:
- default:
- case DW_AT_abstract_origin:
- case DW_AT_sibling:
- break;
- }
- }
- }
-
- bool skip = false;
- if (skip_artificial)
- {
- if (is_artificial)
- {
- // In order to determine if a C++ member function is
- // "const" we have to look at the const-ness of "this"...
- // Ugly, but that
- if (arg_idx == 0)
- {
- if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()))
- {
- // Often times compilers omit the "this" name for the
- // specification DIEs, so we can't rely upon the name
- // being in the formal parameter DIE...
- if (name == NULL || ::strcmp(name, "this")==0)
- {
- Type *this_type = ResolveTypeUID (param_type_die_offset);
- if (this_type)
- {
- uint32_t encoding_mask = this_type->GetEncodingMask();
- if (encoding_mask & Type::eEncodingIsPointerUID)
- {
- is_static = false;
-
- if (encoding_mask & (1u << Type::eEncodingIsConstUID))
- type_quals |= clang::Qualifiers::Const;
- if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
- type_quals |= clang::Qualifiers::Volatile;
- }
- }
- }
- }
- }
- skip = true;
- }
- else
- {
-
- // HACK: Objective C formal parameters "self" and "_cmd"
- // are not marked as artificial in the DWARF...
- CompileUnit *comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
- if (comp_unit)
- {
- switch (comp_unit->GetLanguage())
- {
- case eLanguageTypeObjC:
- case eLanguageTypeObjC_plus_plus:
- if (name && name[0] && (strcmp (name, "self") == 0 || strcmp (name, "_cmd") == 0))
- skip = true;
- break;
- default:
- break;
- }
- }
- }
- }
-
- if (!skip)
- {
- Type *type = ResolveTypeUID(param_type_die_offset);
- if (type)
- {
- function_param_types.push_back (type->GetClangForwardType());
-
- clang::ParmVarDecl *param_var_decl = GetClangASTContext().CreateParameterDeclaration (name,
- type->GetClangForwardType(),
- storage);
- assert(param_var_decl);
- function_param_decls.push_back(param_var_decl);
-
- GetClangASTContext().SetMetadataAsUserID (param_var_decl, MakeUserID(die->GetOffset()));
- }
- }
- }
- arg_idx++;
- }
- break;
-
- case DW_TAG_unspecified_parameters:
- is_variadic = true;
- break;
-
- case DW_TAG_template_type_parameter:
- case DW_TAG_template_value_parameter:
- // The one caller of this was never using the template_param_infos,
- // and the local variable was taking up a large amount of stack space
- // in SymbolFileDWARF::ParseType() so this was removed. If we ever need
- // the template params back, we can add them back.
- // ParseTemplateDIE (dwarf_cu, die, template_param_infos);
- break;
-
- default:
- break;
- }
- }
- return arg_idx;
-}
-
-size_t
-SymbolFileDWARF::ParseChildEnumerators
-(
- const SymbolContext& sc,
- lldb_private::ClangASTType &clang_type,
- bool is_signed,
- uint32_t enumerator_byte_size,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die
-)
-{
- if (parent_die == NULL)
- return 0;
-
- size_t enumerators_added = 0;
- const DWARFDebugInfoEntry *die;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
-
- for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
- {
- const dw_tag_t tag = die->Tag();
- if (tag == DW_TAG_enumerator)
- {
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes);
- if (num_child_attributes > 0)
- {
- const char *name = NULL;
- bool got_value = false;
- int64_t enum_value = 0;
- Declaration decl;
-
- uint32_t i;
- for (i=0; i<num_child_attributes; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_const_value:
- got_value = true;
- if (is_signed)
- enum_value = form_value.Signed();
- else
- enum_value = form_value.Unsigned();
- break;
-
- case DW_AT_name:
- name = form_value.AsCString(&get_debug_str_data());
- break;
-
- case DW_AT_description:
- default:
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_sibling:
- break;
- }
- }
- }
-
- if (name && name[0] && got_value)
- {
- clang_type.AddEnumerationValueToEnumerationType (clang_type.GetEnumerationIntegerType(),
- decl,
- name,
- enum_value,
- enumerator_byte_size * 8);
- ++enumerators_added;
- }
- }
- }
+ static_cast<const void*>(namespace_decl_ctx.GetTypeSystem()),
+ static_cast<const void*>(namespace_decl_ctx.GetOpaqueDeclContext()),
+ namespace_decl_ctx.GetName().AsCString("<NULL>"));
}
- return enumerators_added;
-}
-
-void
-SymbolFileDWARF::ParseChildArrayInfo
-(
- const SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- int64_t& first_index,
- std::vector<uint64_t>& element_orders,
- uint32_t& byte_stride,
- uint32_t& bit_stride
-)
-{
- if (parent_die == NULL)
- return;
-
- const DWARFDebugInfoEntry *die;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
- for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
- {
- const dw_tag_t tag = die->Tag();
- switch (tag)
- {
- case DW_TAG_subrange_type:
- {
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes);
- if (num_child_attributes > 0)
- {
- uint64_t num_elements = 0;
- uint64_t lower_bound = 0;
- uint64_t upper_bound = 0;
- bool upper_bound_valid = false;
- uint32_t i;
- for (i=0; i<num_child_attributes; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_name:
- break;
-
- case DW_AT_count:
- num_elements = form_value.Unsigned();
- break;
-
- case DW_AT_bit_stride:
- bit_stride = form_value.Unsigned();
- break;
-
- case DW_AT_byte_stride:
- byte_stride = form_value.Unsigned();
- break;
-
- case DW_AT_lower_bound:
- lower_bound = form_value.Unsigned();
- break;
-
- case DW_AT_upper_bound:
- upper_bound_valid = true;
- upper_bound = form_value.Unsigned();
- break;
-
- default:
- case DW_AT_abstract_origin:
- case DW_AT_accessibility:
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_data_location:
- case DW_AT_declaration:
- case DW_AT_description:
- case DW_AT_sibling:
- case DW_AT_threads_scaled:
- case DW_AT_type:
- case DW_AT_visibility:
- break;
- }
- }
- }
-
- if (num_elements == 0)
- {
- if (upper_bound_valid && upper_bound >= lower_bound)
- num_elements = upper_bound - lower_bound + 1;
- }
- element_orders.push_back (num_elements);
- }
- }
- break;
- }
- }
+ return namespace_decl_ctx;
}
TypeSP
-SymbolFileDWARF::GetTypeForDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfoEntry* die)
+SymbolFileDWARF::GetTypeForDIE (const DWARFDIE &die, bool resolve_function_context)
{
TypeSP type_sp;
- if (die != NULL)
+ if (die)
{
- assert(dwarf_cu != NULL);
- Type *type_ptr = m_die_to_type.lookup (die);
+ Type *type_ptr = GetDIEToType().lookup (die.GetDIE());
if (type_ptr == NULL)
{
- CompileUnit* lldb_cu = GetCompUnitForDWARFCompUnit(dwarf_cu);
+ CompileUnit* lldb_cu = GetCompUnitForDWARFCompUnit(die.GetCU());
assert (lldb_cu);
SymbolContext sc(lldb_cu);
- type_sp = ParseType(sc, dwarf_cu, die, NULL);
+ const DWARFDebugInfoEntry* parent_die = die.GetParent().GetDIE();
+ while (parent_die != nullptr)
+ {
+ if (parent_die->Tag() == DW_TAG_subprogram)
+ break;
+ parent_die = parent_die->GetParent();
+ }
+ SymbolContext sc_backup = sc;
+ if (resolve_function_context && parent_die != nullptr && !GetFunction(DWARFDIE(die.GetCU(),parent_die), sc))
+ sc = sc_backup;
+
+ type_sp = ParseType(sc, die, NULL);
}
else if (type_ptr != DIE_IS_BEING_PARSED)
{
@@ -4809,215 +3307,57 @@ SymbolFileDWARF::GetTypeForDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfo
return type_sp;
}
-clang::DeclContext *
-SymbolFileDWARF::GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset)
-{
- if (die_offset != DW_INVALID_OFFSET)
- {
- DWARFCompileUnitSP cu_sp;
- const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr(die_offset, &cu_sp);
- return GetClangDeclContextContainingDIE (cu_sp.get(), die, NULL);
- }
- return NULL;
-}
-
-clang::DeclContext *
-SymbolFileDWARF::GetClangDeclContextForDIEOffset (const SymbolContext &sc, dw_offset_t die_offset)
-{
- if (die_offset != DW_INVALID_OFFSET)
- {
- DWARFDebugInfo* debug_info = DebugInfo();
- if (debug_info)
- {
- DWARFCompileUnitSP cu_sp;
- const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(die_offset, &cu_sp);
- if (die)
- return GetClangDeclContextForDIE (sc, cu_sp.get(), die);
- }
- }
- return NULL;
-}
-clang::NamespaceDecl *
-SymbolFileDWARF::ResolveNamespaceDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfoEntry *die)
+DWARFDIE
+SymbolFileDWARF::GetDeclContextDIEContainingDIE (const DWARFDIE &orig_die)
{
- if (die && die->Tag() == DW_TAG_namespace)
+ if (orig_die)
{
- // See if we already parsed this namespace DIE and associated it with a
- // uniqued namespace declaration
- clang::NamespaceDecl *namespace_decl = static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die]);
- if (namespace_decl)
- return namespace_decl;
- else
- {
- const char *namespace_name = die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL);
- clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, NULL);
- namespace_decl = GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, containing_decl_ctx);
- Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- if (log)
- {
- if (namespace_name)
- {
- GetObjectFile()->GetModule()->LogMessage (log,
- "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace with DW_AT_name(\"%s\") => clang::NamespaceDecl *%p (original = %p)",
- static_cast<void*>(GetClangASTContext().getASTContext()),
- MakeUserID(die->GetOffset()),
- namespace_name,
- static_cast<void*>(namespace_decl),
- static_cast<void*>(namespace_decl->getOriginalNamespace()));
- }
- else
- {
- GetObjectFile()->GetModule()->LogMessage (log,
- "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)",
- static_cast<void*>(GetClangASTContext().getASTContext()),
- MakeUserID(die->GetOffset()),
- static_cast<void*>(namespace_decl),
- static_cast<void*>(namespace_decl->getOriginalNamespace()));
- }
- }
-
- if (namespace_decl)
- LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die);
- return namespace_decl;
- }
- }
- return NULL;
-}
-
-clang::DeclContext *
-SymbolFileDWARF::GetClangDeclContextForDIE (const SymbolContext &sc, DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
-{
- clang::DeclContext *clang_decl_ctx = GetCachedClangDeclContextForDIE (die);
- if (clang_decl_ctx)
- return clang_decl_ctx;
- // If this DIE has a specification, or an abstract origin, then trace to those.
-
- dw_offset_t die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_specification, DW_INVALID_OFFSET);
- if (die_offset != DW_INVALID_OFFSET)
- return GetClangDeclContextForDIEOffset (sc, die_offset);
-
- die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET);
- if (die_offset != DW_INVALID_OFFSET)
- return GetClangDeclContextForDIEOffset (sc, die_offset);
-
- Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- if (log)
- GetObjectFile()->GetModule()->LogMessage(log, "SymbolFileDWARF::GetClangDeclContextForDIE (die = 0x%8.8x) %s '%s'", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), die->GetName(this, cu));
- // This is the DIE we want. Parse it, then query our map.
- bool assert_not_being_parsed = true;
- ResolveTypeUID (cu, die, assert_not_being_parsed);
-
- clang_decl_ctx = GetCachedClangDeclContextForDIE (die);
-
- return clang_decl_ctx;
-}
-
-clang::DeclContext *
-SymbolFileDWARF::GetClangDeclContextContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die, const DWARFDebugInfoEntry **decl_ctx_die_copy)
-{
- if (m_clang_tu_decl == NULL)
- m_clang_tu_decl = GetClangASTContext().getASTContext()->getTranslationUnitDecl();
-
- const DWARFDebugInfoEntry *decl_ctx_die = GetDeclContextDIEContainingDIE (cu, die);
-
- if (decl_ctx_die_copy)
- *decl_ctx_die_copy = decl_ctx_die;
+ DWARFDIE die = orig_die;
- if (decl_ctx_die)
- {
-
- DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find (decl_ctx_die);
- if (pos != m_die_to_decl_ctx.end())
- return pos->second;
-
- switch (decl_ctx_die->Tag())
- {
- case DW_TAG_compile_unit:
- return m_clang_tu_decl;
-
- case DW_TAG_namespace:
- return ResolveNamespaceDIE (cu, decl_ctx_die);
- break;
-
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type:
- {
- Type* type = ResolveType (cu, decl_ctx_die);
- if (type)
- {
- clang::DeclContext *decl_ctx = type->GetClangForwardType().GetDeclContextForType ();
- if (decl_ctx)
- {
- LinkDeclContextToDIE (decl_ctx, decl_ctx_die);
- if (decl_ctx)
- return decl_ctx;
- }
- }
- }
- break;
-
- default:
- break;
- }
- }
- return m_clang_tu_decl;
-}
-
-
-const DWARFDebugInfoEntry *
-SymbolFileDWARF::GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
-{
- if (cu && die)
- {
- const DWARFDebugInfoEntry * const decl_die = die;
-
- while (die != NULL)
+ while (die)
{
// If this is the original DIE that we are searching for a declaration
// for, then don't look in the cache as we don't want our own decl
// context to be our decl context...
- if (decl_die != die)
+ if (orig_die != die)
{
- switch (die->Tag())
+ switch (die.Tag())
{
case DW_TAG_compile_unit:
case DW_TAG_namespace:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_class_type:
+ case DW_TAG_lexical_block:
+ case DW_TAG_subprogram:
return die;
default:
break;
}
}
-
- dw_offset_t die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_specification, DW_INVALID_OFFSET);
- if (die_offset != DW_INVALID_OFFSET)
+
+ DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification);
+ if (spec_die)
{
- DWARFCompileUnit *spec_cu = cu;
- const DWARFDebugInfoEntry *spec_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &spec_cu);
- const DWARFDebugInfoEntry *spec_die_decl_ctx_die = GetDeclContextDIEContainingDIE (spec_cu, spec_die);
- if (spec_die_decl_ctx_die)
- return spec_die_decl_ctx_die;
+ DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(spec_die);
+ if (decl_ctx_die)
+ return decl_ctx_die;
}
-
- die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET);
- if (die_offset != DW_INVALID_OFFSET)
+
+ DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin);
+ if (abs_die)
{
- DWARFCompileUnit *abs_cu = cu;
- const DWARFDebugInfoEntry *abs_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &abs_cu);
- const DWARFDebugInfoEntry *abs_die_decl_ctx_die = GetDeclContextDIEContainingDIE (abs_cu, abs_die);
- if (abs_die_decl_ctx_die)
- return abs_die_decl_ctx_die;
+ DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(abs_die);
+ if (decl_ctx_die)
+ return decl_ctx_die;
}
-
- die = die->GetParent();
+
+ die = die.GetParent();
}
}
- return NULL;
+ return DWARFDIE();
}
@@ -5075,7 +3415,7 @@ SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu)
// This function can be used when a DIE is found that is a forward declaration
// DIE and we want to try and find a type that has the complete definition.
TypeSP
-SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die,
+SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die,
const ConstString &type_name,
bool must_be_implementation)
{
@@ -5105,15 +3445,13 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
const size_t num_matches = die_offsets.size();
- DWARFCompileUnit* type_cu = NULL;
- const DWARFDebugInfoEntry* type_die = NULL;
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE type_die = debug_info->GetDIE (die_ref);
if (type_die)
{
@@ -5122,7 +3460,7 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
// Don't try and resolve the DIE we are looking for with the DIE itself!
if (type_die != die)
{
- switch (type_die->Tag())
+ switch (type_die.Tag())
{
case DW_TAG_class_type:
case DW_TAG_structure_type:
@@ -5135,22 +3473,22 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
if (try_resolving_type)
{
- if (must_be_implementation && type_cu->Supports_DW_AT_APPLE_objc_complete_type())
- try_resolving_type = type_die->GetAttributeValueAsUnsigned (this, type_cu, DW_AT_APPLE_objc_complete_type, 0);
+ if (must_be_implementation && type_die.Supports_DW_AT_APPLE_objc_complete_type())
+ try_resolving_type = type_die.GetAttributeValueAsUnsigned (DW_AT_APPLE_objc_complete_type, 0);
if (try_resolving_type)
{
- Type *resolved_type = ResolveType (type_cu, type_die, false);
+ Type *resolved_type = ResolveType (type_die, false, true);
if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
{
DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n",
- MakeUserID(die->GetOffset()),
+ die.GetID(),
m_obj_file->GetFileSpec().GetFilename().AsCString("<Unknown>"),
- MakeUserID(type_die->GetOffset()),
- MakeUserID(type_cu->GetOffset()));
+ type_die.GetID(),
+ type_cu->GetID());
if (die)
- m_die_to_type[die] = resolved_type;
+ GetDIEToType()[die.GetDIE()] = resolved_type;
type_sp = resolved_type->shared_from_this();
break;
}
@@ -5162,7 +3500,7 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, type_name.GetCString());
+ die_ref.die_offset, type_name.GetCString());
}
}
@@ -5185,19 +3523,12 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
// when they don't.
//----------------------------------------------------------------------
bool
-SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1,
- DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2)
+SymbolFileDWARF::DIEDeclContextsMatch (const DWARFDIE &die1,
+ const DWARFDIE &die2)
{
if (die1 == die2)
return true;
-#if defined (LLDB_CONFIGURATION_DEBUG)
- // You can't and shouldn't call this function with a compile unit from
- // two different SymbolFileDWARF instances.
- assert (DebugInfo()->ContainsCompileUnit (cu1));
- assert (DebugInfo()->ContainsCompileUnit (cu2));
-#endif
-
DWARFDIECollection decl_ctx_1;
DWARFDIECollection decl_ctx_2;
//The declaration DIE stack is a stack of the declaration context
@@ -5215,8 +3546,8 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn
// all the way back to the compiler unit.
// First lets grab the decl contexts for both DIEs
- die1->GetDeclContextDIEs (this, cu1, decl_ctx_1);
- die2->GetDeclContextDIEs (this, cu2, decl_ctx_2);
+ die1.GetDeclContextDIEs (decl_ctx_1);
+ die2.GetDeclContextDIEs (decl_ctx_2);
// Make sure the context arrays have the same size, otherwise
// we are done
const size_t count1 = decl_ctx_1.Size();
@@ -5226,32 +3557,32 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn
// Make sure the DW_TAG values match all the way back up the
// compile unit. If they don't, then we are done.
- const DWARFDebugInfoEntry *decl_ctx_die1;
- const DWARFDebugInfoEntry *decl_ctx_die2;
+ DWARFDIE decl_ctx_die1;
+ DWARFDIE decl_ctx_die2;
size_t i;
for (i=0; i<count1; i++)
{
- decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i);
- decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i);
- if (decl_ctx_die1->Tag() != decl_ctx_die2->Tag())
+ decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex (i);
+ decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex (i);
+ if (decl_ctx_die1.Tag() != decl_ctx_die2.Tag())
return false;
}
#if defined LLDB_CONFIGURATION_DEBUG
// Make sure the top item in the decl context die array is always
// DW_TAG_compile_unit. If it isn't then something went wrong in
- // the DWARFDebugInfoEntry::GetDeclContextDIEs() function...
- assert (decl_ctx_1.GetDIEPtrAtIndex (count1 - 1)->Tag() == DW_TAG_compile_unit);
+ // the DWARFDIE::GetDeclContextDIEs() function...
+ assert (decl_ctx_1.GetDIEAtIndex (count1 - 1).Tag() == DW_TAG_compile_unit);
#endif
// Always skip the compile unit when comparing by only iterating up to
// "count - 1". Here we compare the names as we go.
for (i=0; i<count1 - 1; i++)
{
- decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i);
- decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i);
- const char *name1 = decl_ctx_die1->GetName(this, cu1);
- const char *name2 = decl_ctx_die2->GetName(this, cu2);
+ decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex (i);
+ decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex (i);
+ const char *name1 = decl_ctx_die1.GetName();
+ const char *name2 = decl_ctx_die2.GetName();
// If the string was from a DW_FORM_strp, then the pointer will often
// be the same!
if (name1 == name2)
@@ -5338,22 +3669,20 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
const size_t num_matches = die_offsets.size();
- DWARFCompileUnit* type_cu = NULL;
- const DWARFDebugInfoEntry* type_die = NULL;
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE type_die = debug_info->GetDIE (die_ref);
if (type_die)
{
bool try_resolving_type = false;
// Don't try and resolve the DIE we are looking for with the DIE itself!
- const dw_tag_t type_tag = type_die->Tag();
+ const dw_tag_t type_tag = type_die.Tag();
// Make sure the tags match
if (type_tag == tag)
{
@@ -5386,7 +3715,7 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
if (try_resolving_type)
{
DWARFDeclContext type_dwarf_decl_ctx;
- type_die->GetDWARFDeclContext (this, type_cu, type_dwarf_decl_ctx);
+ type_die.GetDWARFDeclContext (type_dwarf_decl_ctx);
if (log)
{
@@ -5394,14 +3723,14 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
"SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') trying die=0x%8.8x (%s)",
DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
dwarf_decl_ctx.GetQualifiedName(),
- type_die->GetOffset(),
+ type_die.GetOffset(),
type_dwarf_decl_ctx.GetQualifiedName());
}
// Make sure the decl contexts match all the way up
if (dwarf_decl_ctx == type_dwarf_decl_ctx)
{
- Type *resolved_type = ResolveType (type_cu, type_die, false);
+ Type *resolved_type = ResolveType (type_die, false);
if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
{
type_sp = resolved_type->shared_from_this();
@@ -5414,12 +3743,12 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
if (log)
{
std::string qualified_name;
- type_die->GetQualifiedName(this, type_cu, qualified_name);
+ type_die.GetQualifiedName(qualified_name);
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') ignoring die=0x%8.8x (%s)",
DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
dwarf_decl_ctx.GetQualifiedName(),
- type_die->GetOffset(),
+ type_die.GetOffset(),
qualified_name.c_str());
}
}
@@ -5429,7 +3758,7 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, type_name.GetCString());
+ die_ref.die_offset, type_name.GetCString());
}
}
@@ -5440,1744 +3769,50 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
return type_sp;
}
-bool
-SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
- Type *class_type,
- DWARFCompileUnit* src_cu,
- const DWARFDebugInfoEntry *src_class_die,
- DWARFCompileUnit* dst_cu,
- const DWARFDebugInfoEntry *dst_class_die,
- DWARFDIECollection &failures)
-{
- if (!class_type || !src_cu || !src_class_die || !dst_cu || !dst_class_die)
- return false;
- if (src_class_die->Tag() != dst_class_die->Tag())
- return false;
-
- // We need to complete the class type so we can get all of the method types
- // parsed so we can then unique those types to their equivalent counterparts
- // in "dst_cu" and "dst_class_die"
- class_type->GetClangFullType();
-
- const DWARFDebugInfoEntry *src_die;
- const DWARFDebugInfoEntry *dst_die;
- UniqueCStringMap<const DWARFDebugInfoEntry *> src_name_to_die;
- UniqueCStringMap<const DWARFDebugInfoEntry *> dst_name_to_die;
- UniqueCStringMap<const DWARFDebugInfoEntry *> src_name_to_die_artificial;
- UniqueCStringMap<const DWARFDebugInfoEntry *> dst_name_to_die_artificial;
- for (src_die = src_class_die->GetFirstChild(); src_die != NULL; src_die = src_die->GetSibling())
- {
- if (src_die->Tag() == DW_TAG_subprogram)
- {
- // Make sure this is a declaration and not a concrete instance by looking
- // for DW_AT_declaration set to 1. Sometimes concrete function instances
- // are placed inside the class definitions and shouldn't be included in
- // the list of things are are tracking here.
- if (src_die->GetAttributeValueAsUnsigned(src_symfile, src_cu, DW_AT_declaration, 0) == 1)
- {
- const char *src_name = src_die->GetMangledName (src_symfile, src_cu);
- if (src_name)
- {
- ConstString src_const_name(src_name);
- if (src_die->GetAttributeValueAsUnsigned(src_symfile, src_cu, DW_AT_artificial, 0))
- src_name_to_die_artificial.Append(src_const_name.GetCString(), src_die);
- else
- src_name_to_die.Append(src_const_name.GetCString(), src_die);
- }
- }
- }
- }
- for (dst_die = dst_class_die->GetFirstChild(); dst_die != NULL; dst_die = dst_die->GetSibling())
- {
- if (dst_die->Tag() == DW_TAG_subprogram)
- {
- // Make sure this is a declaration and not a concrete instance by looking
- // for DW_AT_declaration set to 1. Sometimes concrete function instances
- // are placed inside the class definitions and shouldn't be included in
- // the list of things are are tracking here.
- if (dst_die->GetAttributeValueAsUnsigned(this, dst_cu, DW_AT_declaration, 0) == 1)
- {
- const char *dst_name = dst_die->GetMangledName (this, dst_cu);
- if (dst_name)
- {
- ConstString dst_const_name(dst_name);
- if (dst_die->GetAttributeValueAsUnsigned(this, dst_cu, DW_AT_artificial, 0))
- dst_name_to_die_artificial.Append(dst_const_name.GetCString(), dst_die);
- else
- dst_name_to_die.Append(dst_const_name.GetCString(), dst_die);
- }
- }
- }
- }
- const uint32_t src_size = src_name_to_die.GetSize ();
- const uint32_t dst_size = dst_name_to_die.GetSize ();
- Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_TYPE_COMPLETION));
-
- // Is everything kosher so we can go through the members at top speed?
- bool fast_path = true;
-
- if (src_size != dst_size)
- {
- if (src_size != 0 && dst_size != 0)
- {
- if (log)
- log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, but they didn't have the same size (src=%d, dst=%d)",
- src_class_die->GetOffset(),
- dst_class_die->GetOffset(),
- src_size,
- dst_size);
- }
-
- fast_path = false;
- }
-
- uint32_t idx;
-
- if (fast_path)
- {
- for (idx = 0; idx < src_size; ++idx)
- {
- src_die = src_name_to_die.GetValueAtIndexUnchecked (idx);
- dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx);
-
- if (src_die->Tag() != dst_die->Tag())
- {
- if (log)
- log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)",
- src_class_die->GetOffset(),
- dst_class_die->GetOffset(),
- src_die->GetOffset(),
- DW_TAG_value_to_name(src_die->Tag()),
- dst_die->GetOffset(),
- DW_TAG_value_to_name(src_die->Tag()));
- fast_path = false;
- }
-
- const char *src_name = src_die->GetMangledName (src_symfile, src_cu);
- const char *dst_name = dst_die->GetMangledName (this, dst_cu);
-
- // Make sure the names match
- if (src_name == dst_name || (strcmp (src_name, dst_name) == 0))
- continue;
-
- if (log)
- log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)",
- src_class_die->GetOffset(),
- dst_class_die->GetOffset(),
- src_die->GetOffset(),
- src_name,
- dst_die->GetOffset(),
- dst_name);
-
- fast_path = false;
- }
- }
-
- // Now do the work of linking the DeclContexts and Types.
- if (fast_path)
- {
- // We can do this quickly. Just run across the tables index-for-index since
- // we know each node has matching names and tags.
- for (idx = 0; idx < src_size; ++idx)
- {
- src_die = src_name_to_die.GetValueAtIndexUnchecked (idx);
- dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx);
-
- clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die];
- if (src_decl_ctx)
- {
- if (log)
- log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_decl_ctx),
- src_die->GetOffset(), dst_die->GetOffset());
- LinkDeclContextToDIE (src_decl_ctx, dst_die);
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found",
- src_die->GetOffset(), dst_die->GetOffset());
- }
-
- Type *src_child_type = m_die_to_type[src_die];
- if (src_child_type)
- {
- if (log)
- log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_child_type),
- src_child_type->GetID(),
- src_die->GetOffset(), dst_die->GetOffset());
- m_die_to_type[dst_die] = src_child_type;
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
- }
- }
- }
- else
- {
- // We must do this slowly. For each member of the destination, look
- // up a member in the source with the same name, check its tag, and
- // unique them if everything matches up. Report failures.
-
- if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty())
- {
- src_name_to_die.Sort();
-
- for (idx = 0; idx < dst_size; ++idx)
- {
- const char *dst_name = dst_name_to_die.GetCStringAtIndex(idx);
- dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
- src_die = src_name_to_die.Find(dst_name, NULL);
-
- if (src_die && (src_die->Tag() == dst_die->Tag()))
- {
- clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die];
- if (src_decl_ctx)
- {
- if (log)
- log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_decl_ctx),
- src_die->GetOffset(),
- dst_die->GetOffset());
- LinkDeclContextToDIE (src_decl_ctx, dst_die);
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
- }
-
- Type *src_child_type = m_die_to_type[src_die];
- if (src_child_type)
- {
- if (log)
- log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_child_type),
- src_child_type->GetID(),
- src_die->GetOffset(),
- dst_die->GetOffset());
- m_die_to_type[dst_die] = src_child_type;
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
- }
- }
- else
- {
- if (log)
- log->Printf ("warning: couldn't find a match for 0x%8.8x", dst_die->GetOffset());
-
- failures.Append(dst_die);
- }
- }
- }
- }
-
- const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize ();
- const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize ();
-
- UniqueCStringMap<const DWARFDebugInfoEntry *> name_to_die_artificial_not_in_src;
-
- if (src_size_artificial && dst_size_artificial)
- {
- dst_name_to_die_artificial.Sort();
-
- for (idx = 0; idx < src_size_artificial; ++idx)
- {
- const char *src_name_artificial = src_name_to_die_artificial.GetCStringAtIndex(idx);
- src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked (idx);
- dst_die = dst_name_to_die_artificial.Find(src_name_artificial, NULL);
-
- if (dst_die)
- {
- // Both classes have the artificial types, link them
- clang::DeclContext *src_decl_ctx = m_die_to_decl_ctx[src_die];
- if (src_decl_ctx)
- {
- if (log)
- log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_decl_ctx),
- src_die->GetOffset(), dst_die->GetOffset());
- LinkDeclContextToDIE (src_decl_ctx, dst_die);
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
- }
-
- Type *src_child_type = m_die_to_type[src_die];
- if (src_child_type)
- {
- if (log)
- log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_child_type),
- src_child_type->GetID(),
- src_die->GetOffset(), dst_die->GetOffset());
- m_die_to_type[dst_die] = src_child_type;
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
- }
- }
- }
- }
-
- if (dst_size_artificial)
- {
- for (idx = 0; idx < dst_size_artificial; ++idx)
- {
- const char *dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx);
- dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked (idx);
- if (log)
- log->Printf ("warning: need to create artificial method for 0x%8.8x for method '%s'", dst_die->GetOffset(), dst_name_artificial);
-
- failures.Append(dst_die);
- }
- }
-
- return (failures.Size() != 0);
-}
-
TypeSP
-SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool *type_is_new_ptr)
+SymbolFileDWARF::ParseType (const SymbolContext& sc, const DWARFDIE &die, bool *type_is_new_ptr)
{
TypeSP type_sp;
- if (type_is_new_ptr)
- *type_is_new_ptr = false;
-
-#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
- static DIEStack g_die_stack;
- DIEStack::ScopedPopper scoped_die_logger(g_die_stack);
-#endif
-
- AccessType accessibility = eAccessNone;
- if (die != NULL)
+ if (die)
{
- Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- if (log)
- {
- const DWARFDebugInfoEntry *context_die;
- clang::DeclContext *context = GetClangDeclContextContainingDIE (dwarf_cu, die, &context_die);
-
- GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')",
- die->GetOffset(),
- static_cast<void*>(context),
- context_die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, dwarf_cu));
-
-#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
- scoped_die_logger.Push (dwarf_cu, die);
- g_die_stack.LogDIEs(log, this);
-#endif
- }
-//
-// Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
-// if (log && dwarf_cu)
-// {
-// StreamString s;
-// die->DumpLocation (this, dwarf_cu, s);
-// GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData());
-//
-// }
-
- Type *type_ptr = m_die_to_type.lookup (die);
- TypeList* type_list = GetTypeList();
- if (type_ptr == NULL)
- {
- ClangASTContext &ast = GetClangASTContext();
- if (type_is_new_ptr)
- *type_is_new_ptr = true;
-
- const dw_tag_t tag = die->Tag();
-
- bool is_forward_declaration = false;
- DWARFDebugInfoEntry::Attributes attributes;
- const char *type_name_cstr = NULL;
- ConstString type_name_const_str;
- Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
- uint64_t byte_size = 0;
- Declaration decl;
-
- Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
- ClangASTType clang_type;
- DWARFFormValue form_value;
-
- dw_attr_t attr;
+ TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType());
- switch (tag)
+ if (type_system)
+ {
+ DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+ if (dwarf_ast)
{
- case DW_TAG_base_type:
- case DW_TAG_pointer_type:
- case DW_TAG_reference_type:
- case DW_TAG_rvalue_reference_type:
- case DW_TAG_typedef:
- case DW_TAG_const_type:
- case DW_TAG_restrict_type:
- case DW_TAG_volatile_type:
- case DW_TAG_unspecified_type:
- {
- // Set a bit that lets us know that we are currently parsing this
- m_die_to_type[die] = DIE_IS_BEING_PARSED;
-
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
- uint32_t encoding = 0;
- lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
-
- if (num_attributes > 0)
- {
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name:
-
- type_name_cstr = form_value.AsCString(&get_debug_str_data());
- // Work around a bug in llvm-gcc where they give a name to a reference type which doesn't
- // include the "&"...
- if (tag == DW_TAG_reference_type)
- {
- if (strchr (type_name_cstr, '&') == NULL)
- type_name_cstr = NULL;
- }
- if (type_name_cstr)
- type_name_const_str.SetCString(type_name_cstr);
- break;
- case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
- case DW_AT_encoding: encoding = form_value.Unsigned(); break;
- case DW_AT_type: encoding_uid = form_value.Reference(); break;
- default:
- case DW_AT_sibling:
- break;
- }
- }
- }
- }
-
- DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid);
-
- switch (tag)
- {
- default:
- break;
-
- case DW_TAG_unspecified_type:
- if (strcmp(type_name_cstr, "nullptr_t") == 0 ||
- strcmp(type_name_cstr, "decltype(nullptr)") == 0 )
- {
- resolve_state = Type::eResolveStateFull;
- clang_type = ast.GetBasicType(eBasicTypeNullPtr);
- break;
- }
- // Fall through to base type below in case we can handle the type there...
-
- case DW_TAG_base_type:
- resolve_state = Type::eResolveStateFull;
- clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (type_name_cstr,
- encoding,
- byte_size * 8);
- break;
-
- case DW_TAG_pointer_type: encoding_data_type = Type::eEncodingIsPointerUID; break;
- case DW_TAG_reference_type: encoding_data_type = Type::eEncodingIsLValueReferenceUID; break;
- case DW_TAG_rvalue_reference_type: encoding_data_type = Type::eEncodingIsRValueReferenceUID; break;
- case DW_TAG_typedef: encoding_data_type = Type::eEncodingIsTypedefUID; break;
- case DW_TAG_const_type: encoding_data_type = Type::eEncodingIsConstUID; break;
- case DW_TAG_restrict_type: encoding_data_type = Type::eEncodingIsRestrictUID; break;
- case DW_TAG_volatile_type: encoding_data_type = Type::eEncodingIsVolatileUID; break;
- }
-
- if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL)
- {
- bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus);
-
- if (translation_unit_is_objc)
- {
- if (type_name_cstr != NULL)
- {
- static ConstString g_objc_type_name_id("id");
- static ConstString g_objc_type_name_Class("Class");
- static ConstString g_objc_type_name_selector("SEL");
-
- if (type_name_const_str == g_objc_type_name_id)
- {
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, dwarf_cu));
- clang_type = ast.GetBasicType(eBasicTypeObjCID);
- encoding_data_type = Type::eEncodingIsUID;
- encoding_uid = LLDB_INVALID_UID;
- resolve_state = Type::eResolveStateFull;
-
- }
- else if (type_name_const_str == g_objc_type_name_Class)
- {
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, dwarf_cu));
- clang_type = ast.GetBasicType(eBasicTypeObjCClass);
- encoding_data_type = Type::eEncodingIsUID;
- encoding_uid = LLDB_INVALID_UID;
- resolve_state = Type::eResolveStateFull;
- }
- else if (type_name_const_str == g_objc_type_name_selector)
- {
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, dwarf_cu));
- clang_type = ast.GetBasicType(eBasicTypeObjCSel);
- encoding_data_type = Type::eEncodingIsUID;
- encoding_uid = LLDB_INVALID_UID;
- resolve_state = Type::eResolveStateFull;
- }
- }
- else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID)
- {
- // Clang sometimes erroneously emits id as objc_object*. In that case we fix up the type to "id".
-
- DWARFDebugInfoEntry* encoding_die = dwarf_cu->GetDIEPtr(encoding_uid);
-
- if (encoding_die && encoding_die->Tag() == DW_TAG_structure_type)
- {
- if (const char *struct_name = encoding_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL))
- {
- if (!strcmp(struct_name, "objc_object"))
- {
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is 'objc_object*', which we overrode to 'id'.",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, dwarf_cu));
- clang_type = ast.GetBasicType(eBasicTypeObjCID);
- encoding_data_type = Type::eEncodingIsUID;
- encoding_uid = LLDB_INVALID_UID;
- resolve_state = Type::eResolveStateFull;
- }
- }
- }
- }
- }
- }
-
- type_sp.reset( new Type (MakeUserID(die->GetOffset()),
- this,
- type_name_const_str,
- byte_size,
- NULL,
- encoding_uid,
- encoding_data_type,
- &decl,
- clang_type,
- resolve_state));
-
- m_die_to_type[die] = type_sp.get();
-
-// Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false);
-// if (encoding_type != NULL)
-// {
-// if (encoding_type != DIE_IS_BEING_PARSED)
-// type_sp->SetEncodingType(encoding_type);
-// else
-// m_indirect_fixups.push_back(type_sp.get());
-// }
- }
- break;
-
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type:
- {
- // Set a bit that lets us know that we are currently parsing this
- m_die_to_type[die] = DIE_IS_BEING_PARSED;
- bool byte_size_valid = false;
-
- LanguageType class_language = eLanguageTypeUnknown;
- bool is_complete_objc_class = false;
- //bool struct_is_class = false;
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
- if (num_attributes > 0)
- {
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file:
- if (dwarf_cu->DW_AT_decl_file_attributes_are_invalid())
- {
- // llvm-gcc outputs invalid DW_AT_decl_file attributes that always
- // point to the compile unit file, so we clear this invalid value
- // so that we can still unique types efficiently.
- decl.SetFile(FileSpec ("<invalid>", false));
- }
- else
- decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned()));
- break;
-
- case DW_AT_decl_line:
- decl.SetLine(form_value.Unsigned());
- break;
-
- case DW_AT_decl_column:
- decl.SetColumn(form_value.Unsigned());
- break;
-
- case DW_AT_name:
- type_name_cstr = form_value.AsCString(&get_debug_str_data());
- type_name_const_str.SetCString(type_name_cstr);
- break;
-
- case DW_AT_byte_size:
- byte_size = form_value.Unsigned();
- byte_size_valid = true;
- break;
-
- case DW_AT_accessibility:
- accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
- break;
-
- case DW_AT_declaration:
- is_forward_declaration = form_value.Boolean();
- break;
-
- case DW_AT_APPLE_runtime_class:
- class_language = (LanguageType)form_value.Signed();
- break;
-
- case DW_AT_APPLE_objc_complete_type:
- is_complete_objc_class = form_value.Signed();
- break;
-
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_data_location:
- case DW_AT_description:
- case DW_AT_start_scope:
- case DW_AT_visibility:
- default:
- case DW_AT_sibling:
- break;
- }
- }
- }
- }
-
- // UniqueDWARFASTType is large, so don't create a local variables on the
- // stack, put it on the heap. This function is often called recursively
- // and clang isn't good and sharing the stack space for variables in different blocks.
- std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType());
-
- // Only try and unique the type if it has a name.
- if (type_name_const_str &&
- GetUniqueDWARFASTTypeMap().Find (type_name_const_str,
- this,
- dwarf_cu,
- die,
- decl,
- byte_size_valid ? byte_size : -1,
- *unique_ast_entry_ap))
- {
- // We have already parsed this type or from another
- // compile unit. GCC loves to use the "one definition
- // rule" which can result in multiple definitions
- // of the same class over and over in each compile
- // unit.
- type_sp = unique_ast_entry_ap->m_type_sp;
- if (type_sp)
- {
- m_die_to_type[die] = type_sp.get();
- return type_sp;
- }
- }
-
- DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
-
- int tag_decl_kind = -1;
- AccessType default_accessibility = eAccessNone;
- if (tag == DW_TAG_structure_type)
- {
- tag_decl_kind = clang::TTK_Struct;
- default_accessibility = eAccessPublic;
- }
- else if (tag == DW_TAG_union_type)
- {
- tag_decl_kind = clang::TTK_Union;
- default_accessibility = eAccessPublic;
- }
- else if (tag == DW_TAG_class_type)
- {
- tag_decl_kind = clang::TTK_Class;
- default_accessibility = eAccessPrivate;
- }
-
- if (byte_size_valid && byte_size == 0 && type_name_cstr &&
- die->HasChildren() == false &&
- sc.comp_unit->GetLanguage() == eLanguageTypeObjC)
- {
- // Work around an issue with clang at the moment where
- // forward declarations for objective C classes are emitted
- // as:
- // DW_TAG_structure_type [2]
- // DW_AT_name( "ForwardObjcClass" )
- // DW_AT_byte_size( 0x00 )
- // DW_AT_decl_file( "..." )
- // DW_AT_decl_line( 1 )
- //
- // Note that there is no DW_AT_declaration and there are
- // no children, and the byte size is zero.
- is_forward_declaration = true;
- }
-
- if (class_language == eLanguageTypeObjC ||
- class_language == eLanguageTypeObjC_plus_plus)
- {
- if (!is_complete_objc_class && Supports_DW_AT_APPLE_objc_complete_type(dwarf_cu))
- {
- // We have a valid eSymbolTypeObjCClass class symbol whose
- // name matches the current objective C class that we
- // are trying to find and this DIE isn't the complete
- // definition (we checked is_complete_objc_class above and
- // know it is false), so the real definition is in here somewhere
- type_sp = FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true);
-
- if (!type_sp && GetDebugMapSymfile ())
- {
- // We weren't able to find a full declaration in
- // this DWARF, see if we have a declaration anywhere
- // else...
- type_sp = m_debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true);
- }
-
- if (type_sp)
- {
- if (log)
- {
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8" PRIx64,
- static_cast<void*>(this),
- die->GetOffset(),
- DW_TAG_value_to_name(tag),
- type_name_cstr,
- type_sp->GetID());
- }
-
- // We found a real definition for this type elsewhere
- // so lets use it and cache the fact that we found
- // a complete type for this die
- m_die_to_type[die] = type_sp.get();
- return type_sp;
- }
- }
- }
-
-
- if (is_forward_declaration)
- {
- // We have a forward declaration to a type and we need
- // to try and find a full declaration. We look in the
- // current type index just in case we have a forward
- // declaration followed by an actual declarations in the
- // DWARF. If this fails, we need to look elsewhere...
- if (log)
- {
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type",
- static_cast<void*>(this),
- die->GetOffset(),
- DW_TAG_value_to_name(tag),
- type_name_cstr);
- }
-
- DWARFDeclContext die_decl_ctx;
- die->GetDWARFDeclContext(this, dwarf_cu, die_decl_ctx);
-
- //type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str);
- type_sp = FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
-
- if (!type_sp && GetDebugMapSymfile ())
- {
- // We weren't able to find a full declaration in
- // this DWARF, see if we have a declaration anywhere
- // else...
- type_sp = m_debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
- }
-
- if (type_sp)
- {
- if (log)
- {
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64,
- static_cast<void*>(this),
- die->GetOffset(),
- DW_TAG_value_to_name(tag),
- type_name_cstr,
- type_sp->GetID());
- }
-
- // We found a real definition for this type elsewhere
- // so lets use it and cache the fact that we found
- // a complete type for this die
- m_die_to_type[die] = type_sp.get();
- return type_sp;
- }
- }
- assert (tag_decl_kind != -1);
- bool clang_type_was_created = false;
- clang_type.SetClangType(ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die));
- if (!clang_type)
- {
- const DWARFDebugInfoEntry *decl_ctx_die;
-
- clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die);
- if (accessibility == eAccessNone && decl_ctx)
- {
- // Check the decl context that contains this class/struct/union.
- // If it is a class we must give it an accessibility.
- const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind();
- if (DeclKindIsCXXClass (containing_decl_kind))
- accessibility = default_accessibility;
- }
-
- ClangASTMetadata metadata;
- metadata.SetUserID(MakeUserID(die->GetOffset()));
- metadata.SetIsDynamicCXXType(ClassOrStructIsVirtual (dwarf_cu, die));
-
- if (type_name_cstr && strchr (type_name_cstr, '<'))
- {
- ClangASTContext::TemplateParameterInfos template_param_infos;
- if (ParseTemplateParameterInfos (dwarf_cu, die, template_param_infos))
- {
- clang::ClassTemplateDecl *class_template_decl = ParseClassTemplateDecl (decl_ctx,
- accessibility,
- type_name_cstr,
- tag_decl_kind,
- template_param_infos);
-
- clang::ClassTemplateSpecializationDecl *class_specialization_decl = ast.CreateClassTemplateSpecializationDecl (decl_ctx,
- class_template_decl,
- tag_decl_kind,
- template_param_infos);
- clang_type = ast.CreateClassTemplateSpecializationType (class_specialization_decl);
- clang_type_was_created = true;
-
- GetClangASTContext().SetMetadata (class_template_decl, metadata);
- GetClangASTContext().SetMetadata (class_specialization_decl, metadata);
- }
- }
-
- if (!clang_type_was_created)
- {
- clang_type_was_created = true;
- clang_type = ast.CreateRecordType (decl_ctx,
- accessibility,
- type_name_cstr,
- tag_decl_kind,
- class_language,
- &metadata);
- }
- }
-
- // Store a forward declaration to this class type in case any
- // parameters in any class methods need it for the clang
- // types for function prototypes.
- LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die);
- type_sp.reset (new Type (MakeUserID(die->GetOffset()),
- this,
- type_name_const_str,
- byte_size,
- NULL,
- LLDB_INVALID_UID,
- Type::eEncodingIsUID,
- &decl,
- clang_type,
- Type::eResolveStateForward));
-
- type_sp->SetIsCompleteObjCClass(is_complete_objc_class);
-
-
- // Add our type to the unique type map so we don't
- // end up creating many copies of the same type over
- // and over in the ASTContext for our module
- unique_ast_entry_ap->m_type_sp = type_sp;
- unique_ast_entry_ap->m_symfile = this;
- unique_ast_entry_ap->m_cu = dwarf_cu;
- unique_ast_entry_ap->m_die = die;
- unique_ast_entry_ap->m_declaration = decl;
- unique_ast_entry_ap->m_byte_size = byte_size;
- GetUniqueDWARFASTTypeMap().Insert (type_name_const_str,
- *unique_ast_entry_ap);
-
- if (is_forward_declaration && die->HasChildren())
- {
- // Check to see if the DIE actually has a definition, some version of GCC will
- // emit DIEs with DW_AT_declaration set to true, but yet still have subprogram,
- // members, or inheritance, so we can't trust it
- const DWARFDebugInfoEntry *child_die = die->GetFirstChild();
- while (child_die)
- {
- switch (child_die->Tag())
- {
- case DW_TAG_inheritance:
- case DW_TAG_subprogram:
- case DW_TAG_member:
- case DW_TAG_APPLE_property:
- case DW_TAG_class_type:
- case DW_TAG_structure_type:
- case DW_TAG_enumeration_type:
- case DW_TAG_typedef:
- case DW_TAG_union_type:
- child_die = NULL;
- is_forward_declaration = false;
- break;
- default:
- child_die = child_die->GetSibling();
- break;
- }
- }
- }
-
- if (!is_forward_declaration)
- {
- // Always start the definition for a class type so that
- // if the class has child classes or types that require
- // the class to be created for use as their decl contexts
- // the class will be ready to accept these child definitions.
- if (die->HasChildren() == false)
- {
- // No children for this struct/union/class, lets finish it
- clang_type.StartTagDeclarationDefinition ();
- clang_type.CompleteTagDeclarationDefinition ();
-
- if (tag == DW_TAG_structure_type) // this only applies in C
- {
- clang::RecordDecl *record_decl = clang_type.GetAsRecordDecl();
-
- if (record_decl)
- m_record_decl_to_layout_map.insert(std::make_pair(record_decl, LayoutInfo()));
- }
- }
- else if (clang_type_was_created)
- {
- // Start the definition if the class is not objective C since
- // the underlying decls respond to isCompleteDefinition(). Objective
- // C decls don't respond to isCompleteDefinition() so we can't
- // start the declaration definition right away. For C++ class/union/structs
- // we want to start the definition in case the class is needed as the
- // declaration context for a contained class or type without the need
- // to complete that type..
-
- if (class_language != eLanguageTypeObjC &&
- class_language != eLanguageTypeObjC_plus_plus)
- clang_type.StartTagDeclarationDefinition ();
-
- // Leave this as a forward declaration until we need
- // to know the details of the type. lldb_private::Type
- // will automatically call the SymbolFile virtual function
- // "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition(Type *)"
- // When the definition needs to be defined.
- m_forward_decl_die_to_clang_type[die] = clang_type.GetOpaqueQualType();
- m_forward_decl_clang_type_to_die[clang_type.RemoveFastQualifiers().GetOpaqueQualType()] = die;
- clang_type.SetHasExternalStorage (true);
- }
- }
-
- }
- break;
-
- case DW_TAG_enumeration_type:
+ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
+ type_sp = dwarf_ast->ParseTypeFromDWARF (sc, die, log, type_is_new_ptr);
+ if (type_sp)
{
- // Set a bit that lets us know that we are currently parsing this
- m_die_to_type[die] = DIE_IS_BEING_PARSED;
-
- lldb::user_id_t encoding_uid = DW_INVALID_OFFSET;
-
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
- if (num_attributes > 0)
- {
- uint32_t i;
-
- for (i=0; i<num_attributes; ++i)
- {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name:
- type_name_cstr = form_value.AsCString(&get_debug_str_data());
- type_name_const_str.SetCString(type_name_cstr);
- break;
- case DW_AT_type: encoding_uid = form_value.Reference(); break;
- case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
- case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
- case DW_AT_declaration: break; //is_forward_declaration = form_value.Boolean(); break;
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_bit_stride:
- case DW_AT_byte_stride:
- case DW_AT_data_location:
- case DW_AT_description:
- case DW_AT_start_scope:
- case DW_AT_visibility:
- case DW_AT_specification:
- case DW_AT_abstract_origin:
- case DW_AT_sibling:
- break;
- }
- }
- }
-
- DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
+ TypeList* type_list = GetTypeList();
+ if (type_list)
+ type_list->Insert(type_sp);
- ClangASTType enumerator_clang_type;
- clang_type.SetClangType (ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die));
- if (!clang_type)
- {
- if (encoding_uid != DW_INVALID_OFFSET)
- {
- Type *enumerator_type = ResolveTypeUID(encoding_uid);
- if (enumerator_type)
- enumerator_clang_type = enumerator_type->GetClangFullType();
- }
-
- if (!enumerator_clang_type)
- enumerator_clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL,
- DW_ATE_signed,
- byte_size * 8);
-
- clang_type = ast.CreateEnumerationType (type_name_cstr,
- GetClangDeclContextContainingDIE (dwarf_cu, die, NULL),
- decl,
- enumerator_clang_type);
- }
- else
- {
- enumerator_clang_type = clang_type.GetEnumerationIntegerType ();
- }
-
- LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die);
-
- type_sp.reset( new Type (MakeUserID(die->GetOffset()),
- this,
- type_name_const_str,
- byte_size,
- NULL,
- encoding_uid,
- Type::eEncodingIsUID,
- &decl,
- clang_type,
- Type::eResolveStateForward));
-
- clang_type.StartTagDeclarationDefinition ();
- if (die->HasChildren())
- {
- SymbolContext cu_sc(GetCompUnitForDWARFCompUnit(dwarf_cu));
- bool is_signed = false;
- enumerator_clang_type.IsIntegerType(is_signed);
- ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), dwarf_cu, die);
- }
- clang_type.CompleteTagDeclarationDefinition ();
- }
- }
- break;
-
- case DW_TAG_inlined_subroutine:
- case DW_TAG_subprogram:
- case DW_TAG_subroutine_type:
- {
- // Set a bit that lets us know that we are currently parsing this
- m_die_to_type[die] = DIE_IS_BEING_PARSED;
-
- //const char *mangled = NULL;
- dw_offset_t type_die_offset = DW_INVALID_OFFSET;
- bool is_variadic = false;
- bool is_inline = false;
- bool is_static = false;
- bool is_virtual = false;
- bool is_explicit = false;
- bool is_artificial = false;
- dw_offset_t specification_die_offset = DW_INVALID_OFFSET;
- dw_offset_t abstract_origin_die_offset = DW_INVALID_OFFSET;
- dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET;
-
- unsigned type_quals = 0;
- clang::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern
-
-
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
- if (num_attributes > 0)
+ if (die.Tag() == DW_TAG_subprogram)
{
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
+ DIERef die_ref = die.GetDIERef();
+ std::string scope_qualified_name(GetDeclContextForUID(die.GetID()).GetScopeQualifiedName().AsCString(""));
+ if (scope_qualified_name.size())
{
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name:
- type_name_cstr = form_value.AsCString(&get_debug_str_data());
- type_name_const_str.SetCString(type_name_cstr);
- break;
-
- case DW_AT_linkage_name:
- case DW_AT_MIPS_linkage_name: break; // mangled = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: type_die_offset = form_value.Reference(); break;
- case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
- case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break;
- case DW_AT_inline: is_inline = form_value.Boolean(); break;
- case DW_AT_virtuality: is_virtual = form_value.Boolean(); break;
- case DW_AT_explicit: is_explicit = form_value.Boolean(); break;
- case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
-
-
- case DW_AT_external:
- if (form_value.Unsigned())
- {
- if (storage == clang::SC_None)
- storage = clang::SC_Extern;
- else
- storage = clang::SC_PrivateExtern;
- }
- break;
-
- case DW_AT_specification:
- specification_die_offset = form_value.Reference();
- break;
-
- case DW_AT_abstract_origin:
- abstract_origin_die_offset = form_value.Reference();
- break;
-
- case DW_AT_object_pointer:
- object_pointer_die_offset = form_value.Reference();
- break;
-
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_address_class:
- case DW_AT_calling_convention:
- case DW_AT_data_location:
- case DW_AT_elemental:
- case DW_AT_entry_pc:
- case DW_AT_frame_base:
- case DW_AT_high_pc:
- case DW_AT_low_pc:
- case DW_AT_prototyped:
- case DW_AT_pure:
- case DW_AT_ranges:
- case DW_AT_recursive:
- case DW_AT_return_addr:
- case DW_AT_segment:
- case DW_AT_start_scope:
- case DW_AT_static_link:
- case DW_AT_trampoline:
- case DW_AT_visibility:
- case DW_AT_vtable_elem_location:
- case DW_AT_description:
- case DW_AT_sibling:
- break;
- }
- }
- }
- }
-
- std::string object_pointer_name;
- if (object_pointer_die_offset != DW_INVALID_OFFSET)
- {
- // Get the name from the object pointer die
- StreamString s;
- if (DWARFDebugInfoEntry::GetName (this, dwarf_cu, object_pointer_die_offset, s))
- {
- object_pointer_name.assign(s.GetData());
- }
- }
-
- DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
-
- ClangASTType return_clang_type;
- Type *func_type = NULL;
-
- if (type_die_offset != DW_INVALID_OFFSET)
- func_type = ResolveTypeUID(type_die_offset);
-
- if (func_type)
- return_clang_type = func_type->GetClangForwardType();
- else
- return_clang_type = ast.GetBasicType(eBasicTypeVoid);
-
-
- std::vector<ClangASTType> function_param_types;
- std::vector<clang::ParmVarDecl*> function_param_decls;
-
- // Parse the function children for the parameters
-
- const DWARFDebugInfoEntry *decl_ctx_die = NULL;
- clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die);
- const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind();
-
- const bool is_cxx_method = DeclKindIsCXXClass (containing_decl_kind);
- // Start off static. This will be set to false in ParseChildParameters(...)
- // if we find a "this" parameters as the first parameter
- if (is_cxx_method)
- is_static = true;
-
- if (die->HasChildren())
- {
- bool skip_artificial = true;
- ParseChildParameters (sc,
- containing_decl_ctx,
- dwarf_cu,
- die,
- skip_artificial,
- is_static,
- is_variadic,
- function_param_types,
- function_param_decls,
- type_quals);
- }
-
- // clang_type will get the function prototype clang type after this call
- clang_type = ast.CreateFunctionType (return_clang_type,
- function_param_types.data(),
- function_param_types.size(),
- is_variadic,
- type_quals);
-
- bool ignore_containing_context = false;
-
- if (type_name_cstr)
- {
- bool type_handled = false;
- if (tag == DW_TAG_subprogram)
- {
- ObjCLanguageRuntime::MethodName objc_method (type_name_cstr, true);
- if (objc_method.IsValid(true))
- {
- ClangASTType class_opaque_type;
- ConstString class_name(objc_method.GetClassName());
- if (class_name)
- {
- TypeSP complete_objc_class_type_sp (FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, false));
-
- if (complete_objc_class_type_sp)
- {
- ClangASTType type_clang_forward_type = complete_objc_class_type_sp->GetClangForwardType();
- if (type_clang_forward_type.IsObjCObjectOrInterfaceType ())
- class_opaque_type = type_clang_forward_type;
- }
- }
-
- if (class_opaque_type)
- {
- // If accessibility isn't set to anything valid, assume public for
- // now...
- if (accessibility == eAccessNone)
- accessibility = eAccessPublic;
-
- clang::ObjCMethodDecl *objc_method_decl = class_opaque_type.AddMethodToObjCObjectType (type_name_cstr,
- clang_type,
- accessibility,
- is_artificial);
- type_handled = objc_method_decl != NULL;
- if (type_handled)
- {
- LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(objc_method_decl), die);
- GetClangASTContext().SetMetadataAsUserID (objc_method_decl, MakeUserID(die->GetOffset()));
- }
- else
- {
- GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), please file a bug and attach the file at the start of this error message",
- die->GetOffset(),
- tag,
- DW_TAG_value_to_name(tag));
- }
- }
- }
- else if (is_cxx_method)
- {
- // Look at the parent of this DIE and see if is is
- // a class or struct and see if this is actually a
- // C++ method
- Type *class_type = ResolveType (dwarf_cu, decl_ctx_die);
- if (class_type)
- {
- if (class_type->GetID() != MakeUserID(decl_ctx_die->GetOffset()))
- {
- // We uniqued the parent class of this function to another class
- // so we now need to associate all dies under "decl_ctx_die" to
- // DIEs in the DIE for "class_type"...
- SymbolFileDWARF *class_symfile = NULL;
- DWARFCompileUnitSP class_type_cu_sp;
- const DWARFDebugInfoEntry *class_type_die = NULL;
-
- SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
- if (debug_map_symfile)
- {
- class_symfile = debug_map_symfile->GetSymbolFileByOSOIndex(SymbolFileDWARFDebugMap::GetOSOIndexFromUserID(class_type->GetID()));
- class_type_die = class_symfile->DebugInfo()->GetDIEPtr(class_type->GetID(), &class_type_cu_sp);
- }
- else
- {
- class_symfile = this;
- class_type_die = DebugInfo()->GetDIEPtr(class_type->GetID(), &class_type_cu_sp);
- }
- if (class_type_die)
- {
- DWARFDIECollection failures;
-
- CopyUniqueClassMethodTypes (class_symfile,
- class_type,
- class_type_cu_sp.get(),
- class_type_die,
- dwarf_cu,
- decl_ctx_die,
- failures);
-
- // FIXME do something with these failures that's smarter than
- // just dropping them on the ground. Unfortunately classes don't
- // like having stuff added to them after their definitions are
- // complete...
-
- type_ptr = m_die_to_type[die];
- if (type_ptr && type_ptr != DIE_IS_BEING_PARSED)
- {
- type_sp = type_ptr->shared_from_this();
- break;
- }
- }
- }
-
- if (specification_die_offset != DW_INVALID_OFFSET)
- {
- // We have a specification which we are going to base our function
- // prototype off of, so we need this type to be completed so that the
- // m_die_to_decl_ctx for the method in the specification has a valid
- // clang decl context.
- class_type->GetClangForwardType();
- // If we have a specification, then the function type should have been
- // made with the specification and not with this die.
- DWARFCompileUnitSP spec_cu_sp;
- const DWARFDebugInfoEntry* spec_die = DebugInfo()->GetDIEPtr(specification_die_offset, &spec_cu_sp);
- clang::DeclContext *spec_clang_decl_ctx = GetClangDeclContextForDIE (sc, dwarf_cu, spec_die);
- if (spec_clang_decl_ctx)
- {
- LinkDeclContextToDIE(spec_clang_decl_ctx, die);
- }
- else
- {
- GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x) has no decl\n",
- MakeUserID(die->GetOffset()),
- specification_die_offset);
- }
- type_handled = true;
- }
- else if (abstract_origin_die_offset != DW_INVALID_OFFSET)
- {
- // We have a specification which we are going to base our function
- // prototype off of, so we need this type to be completed so that the
- // m_die_to_decl_ctx for the method in the abstract origin has a valid
- // clang decl context.
- class_type->GetClangForwardType();
-
- DWARFCompileUnitSP abs_cu_sp;
- const DWARFDebugInfoEntry* abs_die = DebugInfo()->GetDIEPtr(abstract_origin_die_offset, &abs_cu_sp);
- clang::DeclContext *abs_clang_decl_ctx = GetClangDeclContextForDIE (sc, dwarf_cu, abs_die);
- if (abs_clang_decl_ctx)
- {
- LinkDeclContextToDIE (abs_clang_decl_ctx, die);
- }
- else
- {
- GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x) has no decl\n",
- MakeUserID(die->GetOffset()),
- abstract_origin_die_offset);
- }
- type_handled = true;
- }
- else
- {
- ClangASTType class_opaque_type = class_type->GetClangForwardType();
- if (class_opaque_type.IsCXXClassType ())
- {
- if (class_opaque_type.IsBeingDefined ())
- {
- // Neither GCC 4.2 nor clang++ currently set a valid accessibility
- // in the DWARF for C++ methods... Default to public for now...
- if (accessibility == eAccessNone)
- accessibility = eAccessPublic;
-
- if (!is_static && !die->HasChildren())
- {
- // We have a C++ member function with no children (this pointer!)
- // and clang will get mad if we try and make a function that isn't
- // well formed in the DWARF, so we will just skip it...
- type_handled = true;
- }
- else
- {
- clang::CXXMethodDecl *cxx_method_decl;
- // REMOVE THE CRASH DESCRIPTION BELOW
- Host::SetCrashDescriptionWithFormat ("SymbolFileDWARF::ParseType() is adding a method %s to class %s in DIE 0x%8.8" PRIx64 " from %s",
- type_name_cstr,
- class_type->GetName().GetCString(),
- MakeUserID(die->GetOffset()),
- m_obj_file->GetFileSpec().GetPath().c_str());
-
- const bool is_attr_used = false;
-
- cxx_method_decl = class_opaque_type.AddMethodToCXXRecordType (type_name_cstr,
- clang_type,
- accessibility,
- is_virtual,
- is_static,
- is_inline,
- is_explicit,
- is_attr_used,
- is_artificial);
-
- type_handled = cxx_method_decl != NULL;
-
- if (type_handled)
- {
- LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die);
-
- Host::SetCrashDescription (NULL);
-
-
- ClangASTMetadata metadata;
- metadata.SetUserID(MakeUserID(die->GetOffset()));
-
- if (!object_pointer_name.empty())
- {
- metadata.SetObjectPtrName(object_pointer_name.c_str());
- if (log)
- log->Printf ("Setting object pointer name: %s on method object %p.\n",
- object_pointer_name.c_str(),
- static_cast<void*>(cxx_method_decl));
- }
- GetClangASTContext().SetMetadata (cxx_method_decl, metadata);
- }
- else
- {
- ignore_containing_context = true;
- }
- }
- }
- else
- {
- // We were asked to parse the type for a method in a class, yet the
- // class hasn't been asked to complete itself through the
- // clang::ExternalASTSource protocol, so we need to just have the
- // class complete itself and do things the right way, then our
- // DIE should then have an entry in the m_die_to_type map. First
- // we need to modify the m_die_to_type so it doesn't think we are
- // trying to parse this DIE anymore...
- m_die_to_type[die] = NULL;
-
- // Now we get the full type to force our class type to complete itself
- // using the clang::ExternalASTSource protocol which will parse all
- // base classes and all methods (including the method for this DIE).
- class_type->GetClangFullType();
-
- // The type for this DIE should have been filled in the function call above
- type_ptr = m_die_to_type[die];
- if (type_ptr && type_ptr != DIE_IS_BEING_PARSED)
- {
- type_sp = type_ptr->shared_from_this();
- break;
- }
-
- // FIXME This is fixing some even uglier behavior but we really need to
- // uniq the methods of each class as well as the class itself.
- // <rdar://problem/11240464>
- type_handled = true;
- }
- }
- }
- }
- }
- }
-
- if (!type_handled)
- {
- // We just have a function that isn't part of a class
- clang::FunctionDecl *function_decl = ast.CreateFunctionDeclaration (ignore_containing_context ? GetClangASTContext().GetTranslationUnitDecl() : containing_decl_ctx,
- type_name_cstr,
- clang_type,
- storage,
- is_inline);
-
-// if (template_param_infos.GetSize() > 0)
-// {
-// clang::FunctionTemplateDecl *func_template_decl = ast.CreateFunctionTemplateDecl (containing_decl_ctx,
-// function_decl,
-// type_name_cstr,
-// template_param_infos);
-//
-// ast.CreateFunctionTemplateSpecializationInfo (function_decl,
-// func_template_decl,
-// template_param_infos);
-// }
- // Add the decl to our DIE to decl context map
- assert (function_decl);
- LinkDeclContextToDIE(function_decl, die);
- if (!function_param_decls.empty())
- ast.SetFunctionParameters (function_decl,
- &function_param_decls.front(),
- function_param_decls.size());
-
- ClangASTMetadata metadata;
- metadata.SetUserID(MakeUserID(die->GetOffset()));
-
- if (!object_pointer_name.empty())
- {
- metadata.SetObjectPtrName(object_pointer_name.c_str());
- if (log)
- log->Printf ("Setting object pointer name: %s on function object %p.",
- object_pointer_name.c_str(),
- static_cast<void*>(function_decl));
- }
- GetClangASTContext().SetMetadata (function_decl, metadata);
- }
- }
- type_sp.reset( new Type (MakeUserID(die->GetOffset()),
- this,
- type_name_const_str,
- 0,
- NULL,
- LLDB_INVALID_UID,
- Type::eEncodingIsUID,
- &decl,
- clang_type,
- Type::eResolveStateFull));
- assert(type_sp.get());
- }
- break;
-
- case DW_TAG_array_type:
- {
- // Set a bit that lets us know that we are currently parsing this
- m_die_to_type[die] = DIE_IS_BEING_PARSED;
-
- lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
- int64_t first_index = 0;
- uint32_t byte_stride = 0;
- uint32_t bit_stride = 0;
- bool is_vector = false;
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
-
- if (num_attributes > 0)
- {
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name:
- type_name_cstr = form_value.AsCString(&get_debug_str_data());
- type_name_const_str.SetCString(type_name_cstr);
- break;
-
- case DW_AT_type: type_die_offset = form_value.Reference(); break;
- case DW_AT_byte_size: break; // byte_size = form_value.Unsigned(); break;
- case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break;
- case DW_AT_bit_stride: bit_stride = form_value.Unsigned(); break;
- case DW_AT_GNU_vector: is_vector = form_value.Boolean(); break;
- case DW_AT_accessibility: break; // accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
- case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break;
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_data_location:
- case DW_AT_description:
- case DW_AT_ordering:
- case DW_AT_start_scope:
- case DW_AT_visibility:
- case DW_AT_specification:
- case DW_AT_abstract_origin:
- case DW_AT_sibling:
- break;
- }
- }
- }
-
- DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
-
- Type *element_type = ResolveTypeUID(type_die_offset);
-
- if (element_type)
- {
- std::vector<uint64_t> element_orders;
- ParseChildArrayInfo(sc, dwarf_cu, die, first_index, element_orders, byte_stride, bit_stride);
- if (byte_stride == 0 && bit_stride == 0)
- byte_stride = element_type->GetByteSize();
- ClangASTType array_element_type = element_type->GetClangForwardType();
- uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;
- if (element_orders.size() > 0)
- {
- uint64_t num_elements = 0;
- std::vector<uint64_t>::const_reverse_iterator pos;
- std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend();
- for (pos = element_orders.rbegin(); pos != end; ++pos)
- {
- num_elements = *pos;
- clang_type = ast.CreateArrayType (array_element_type,
- num_elements,
- is_vector);
- array_element_type = clang_type;
- array_element_bit_stride = num_elements ?
- array_element_bit_stride * num_elements :
- array_element_bit_stride;
- }
- }
+ NameToOffsetMap::iterator iter = m_function_scope_qualified_name_map.find(scope_qualified_name);
+ if (iter != m_function_scope_qualified_name_map.end())
+ (*iter).second->insert(die_ref);
else
{
- clang_type = ast.CreateArrayType (array_element_type, 0, is_vector);
+ DIERefSetSP new_set(new std::set<DIERef>);
+ new_set->insert(die_ref);
+ m_function_scope_qualified_name_map.emplace(std::make_pair(scope_qualified_name, new_set));
}
- ConstString empty_name;
- type_sp.reset( new Type (MakeUserID(die->GetOffset()),
- this,
- empty_name,
- array_element_bit_stride / 8,
- NULL,
- type_die_offset,
- Type::eEncodingIsUID,
- &decl,
- clang_type,
- Type::eResolveStateFull));
- type_sp->SetEncodingType (element_type);
}
}
}
- break;
-
- case DW_TAG_ptr_to_member_type:
- {
- dw_offset_t type_die_offset = DW_INVALID_OFFSET;
- dw_offset_t containing_type_die_offset = DW_INVALID_OFFSET;
-
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
-
- if (num_attributes > 0) {
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_type:
- type_die_offset = form_value.Reference(); break;
- case DW_AT_containing_type:
- containing_type_die_offset = form_value.Reference(); break;
- }
- }
- }
-
- Type *pointee_type = ResolveTypeUID(type_die_offset);
- Type *class_type = ResolveTypeUID(containing_type_die_offset);
-
- ClangASTType pointee_clang_type = pointee_type->GetClangForwardType();
- ClangASTType class_clang_type = class_type->GetClangLayoutType();
-
- clang_type = pointee_clang_type.CreateMemberPointerType(class_clang_type);
-
- byte_size = clang_type.GetByteSize(nullptr);
-
- type_sp.reset( new Type (MakeUserID(die->GetOffset()),
- this,
- type_name_const_str,
- byte_size,
- NULL,
- LLDB_INVALID_UID,
- Type::eEncodingIsUID,
- NULL,
- clang_type,
- Type::eResolveStateForward));
- }
-
- break;
- }
- default:
- GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and attach the file at the start of this error message",
- die->GetOffset(),
- tag,
- DW_TAG_value_to_name(tag));
- break;
- }
-
- if (type_sp.get())
- {
- const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
- dw_tag_t sc_parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
-
- SymbolContextScope * symbol_context_scope = NULL;
- if (sc_parent_tag == DW_TAG_compile_unit)
- {
- symbol_context_scope = sc.comp_unit;
- }
- else if (sc.function != NULL && sc_parent_die)
- {
- symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset()));
- if (symbol_context_scope == NULL)
- symbol_context_scope = sc.function;
- }
-
- if (symbol_context_scope != NULL)
- {
- type_sp->SetSymbolContextScope(symbol_context_scope);
- }
-
- // We are ready to put this type into the uniqued list up at the module level
- type_list->Insert (type_sp);
-
- m_die_to_type[die] = type_sp.get();
}
}
- else if (type_ptr != DIE_IS_BEING_PARSED)
- {
- type_sp = type_ptr->shared_from_this();
- }
}
+
return type_sp;
}
@@ -7185,38 +3820,38 @@ size_t
SymbolFileDWARF::ParseTypes
(
const SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
+ const DWARFDIE &orig_die,
bool parse_siblings,
bool parse_children
)
{
size_t types_added = 0;
- while (die != NULL)
+ DWARFDIE die = orig_die;
+ while (die)
{
bool type_is_new = false;
- if (ParseType(sc, dwarf_cu, die, &type_is_new).get())
+ if (ParseType(sc, die, &type_is_new).get())
{
if (type_is_new)
++types_added;
}
- if (parse_children && die->HasChildren())
+ if (parse_children && die.HasChildren())
{
- if (die->Tag() == DW_TAG_subprogram)
+ if (die.Tag() == DW_TAG_subprogram)
{
SymbolContext child_sc(sc);
- child_sc.function = sc.comp_unit->FindFunctionByUID(MakeUserID(die->GetOffset())).get();
- types_added += ParseTypes(child_sc, dwarf_cu, die->GetFirstChild(), true, true);
+ child_sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get();
+ types_added += ParseTypes(child_sc, die.GetFirstChild(), true, true);
}
else
- types_added += ParseTypes(sc, dwarf_cu, die->GetFirstChild(), true, true);
+ types_added += ParseTypes(sc, die.GetFirstChild(), true, true);
}
if (parse_siblings)
- die = die->GetSibling();
+ die = die.GetSibling();
else
- die = NULL;
+ die.Clear();
}
return types_added;
}
@@ -7230,11 +3865,11 @@ SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext &sc)
DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
{
- dw_offset_t function_die_offset = sc.function->GetID();
- const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(function_die_offset);
+ const dw_offset_t function_die_offset = sc.function->GetID();
+ DWARFDIE function_die = dwarf_cu->GetDIE (function_die_offset);
if (function_die)
{
- ParseFunctionBlocks(sc, &sc.function->GetBlock (false), dwarf_cu, function_die, LLDB_INVALID_ADDRESS, 0);
+ ParseFunctionBlocks(sc, &sc.function->GetBlock (false), function_die, LLDB_INVALID_ADDRESS, 0);
}
}
@@ -7254,18 +3889,18 @@ SymbolFileDWARF::ParseTypes (const SymbolContext &sc)
if (sc.function)
{
dw_offset_t function_die_offset = sc.function->GetID();
- const DWARFDebugInfoEntry *func_die = dwarf_cu->GetDIEPtr(function_die_offset);
- if (func_die && func_die->HasChildren())
+ DWARFDIE func_die = dwarf_cu->GetDIE(function_die_offset);
+ if (func_die && func_die.HasChildren())
{
- types_added = ParseTypes(sc, dwarf_cu, func_die->GetFirstChild(), true, true);
+ types_added = ParseTypes(sc, func_die.GetFirstChild(), true, true);
}
}
else
{
- const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->DIE();
- if (dwarf_cu_die && dwarf_cu_die->HasChildren())
+ DWARFDIE dwarf_cu_die = dwarf_cu->DIE();
+ if (dwarf_cu_die && dwarf_cu_die.HasChildren())
{
- types_added = ParseTypes(sc, dwarf_cu, dwarf_cu_die->GetFirstChild(), true, true);
+ types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true);
}
}
}
@@ -7284,17 +3919,12 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
if (sc.function)
{
- DWARFCompileUnit* dwarf_cu = info->GetCompileUnitContainingDIE(sc.function->GetID()).get();
+ DWARFDIE function_die = info->GetDIE(DIERef(sc.function->GetID()));
- if (dwarf_cu == NULL)
- return 0;
-
- const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(sc.function->GetID());
-
- dw_addr_t func_lo_pc = function_die->GetAttributeValueAsUnsigned (this, dwarf_cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+ const dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress (DW_AT_low_pc, LLDB_INVALID_ADDRESS);
if (func_lo_pc != LLDB_INVALID_ADDRESS)
{
- const size_t num_variables = ParseVariables(sc, dwarf_cu, func_lo_pc, function_die->GetFirstChild(), true, true);
+ const size_t num_variables = ParseVariables(sc, function_die.GetFirstChild(), func_lo_pc, true, true);
// Let all blocks know they have parse all their variables
sc.function->GetBlock (false).SetDidParseVariables (true, true);
@@ -7303,7 +3933,7 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
}
else if (sc.comp_unit)
{
- DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID()).get();
+ DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID());
if (dwarf_cu == NULL)
return 0;
@@ -7316,8 +3946,6 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
variables.reset(new VariableList());
sc.comp_unit->SetVariableList(variables);
- DWARFCompileUnit* match_dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
DIEArray die_offsets;
if (m_using_apple_tables)
{
@@ -7340,7 +3968,6 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
Index ();
m_global_index.FindAllEntriesForCompileUnit (dwarf_cu->GetOffset(),
- dwarf_cu->GetNextCompileUnitOffset(),
die_offsets);
}
@@ -7350,11 +3977,11 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &match_dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
if (die)
{
- VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, LLDB_INVALID_ADDRESS));
+ VariableSP var_sp (ParseVariableDIE(sc, die, LLDB_INVALID_ADDRESS));
if (var_sp)
{
variables->AddVariableIfUnique (var_sp);
@@ -7365,7 +3992,7 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
{
if (m_using_apple_tables)
{
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x)\n", die_offset);
+ GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x)\n", die_ref.die_offset);
}
}
@@ -7378,37 +4005,43 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
return 0;
}
-
VariableSP
SymbolFileDWARF::ParseVariableDIE
(
const SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
+ const DWARFDIE &die,
const lldb::addr_t func_low_pc
)
{
- VariableSP var_sp (m_die_to_variable_sp[die]);
+ if (die.GetDWARF() != this)
+ return die.GetDWARF()->ParseVariableDIE(sc, die, func_low_pc);
+
+ VariableSP var_sp;
+ if (!die)
+ return var_sp;
+
+ var_sp = GetDIEToVariable()[die.GetDIE()];
if (var_sp)
return var_sp; // Already been parsed!
- const dw_tag_t tag = die->Tag();
+ const dw_tag_t tag = die.Tag();
ModuleSP module = GetObjectFile()->GetModule();
if ((tag == DW_TAG_variable) ||
(tag == DW_TAG_constant) ||
(tag == DW_TAG_formal_parameter && sc.function))
{
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ DWARFDIE spec_die;
if (num_attributes > 0)
{
const char *name = NULL;
const char *mangled = NULL;
Declaration decl;
uint32_t i;
- lldb::user_id_t type_uid = LLDB_INVALID_UID;
- DWARFExpression location;
+ DWARFFormValue type_die_form;
+ DWARFExpression location(die.GetCU());
bool is_external = false;
bool is_artificial = false;
bool location_is_const_value_data = false;
@@ -7421,17 +4054,17 @@ SymbolFileDWARF::ParseVariableDIE
dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
{
switch (attr)
{
case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
+ case DW_AT_name: name = form_value.AsCString(); break;
case DW_AT_linkage_name:
- case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: type_uid = form_value.Reference(); break;
+ case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(); break;
+ case DW_AT_type: type_die_form = form_value; break;
case DW_AT_external: is_external = form_value.Boolean(); break;
case DW_AT_const_value:
// If we have already found a DW_AT_location attribute, ignore this attribute.
@@ -7450,9 +4083,12 @@ SymbolFileDWARF::ParseVariableDIE
else if (DWARFFormValue::IsDataForm(form_value.Form()))
{
// Retrieve the value as a data expression.
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64());
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize (
+ attributes.CompileUnitAtIndex(i)->GetAddressByteSize(),
+ attributes.CompileUnitAtIndex(i)->IsDWARF64());
uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
- uint32_t data_length = fixed_form_sizes[form_value.Form()];
+ uint32_t data_length = fixed_form_sizes.GetSize(form_value.Form());
if (data_length == 0)
{
const uint8_t *data_pointer = form_value.BlockData();
@@ -7474,14 +4110,17 @@ SymbolFileDWARF::ParseVariableDIE
// Retrieve the value as a string expression.
if (form_value.Form() == DW_FORM_strp)
{
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64());
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize (
+ attributes.CompileUnitAtIndex(i)->GetAddressByteSize(),
+ attributes.CompileUnitAtIndex(i)->IsDWARF64());
uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
- uint32_t data_length = fixed_form_sizes[form_value.Form()];
+ uint32_t data_length = fixed_form_sizes.GetSize(form_value.Form());
location.CopyOpcodeData(module, debug_info_data, data_offset, data_length);
}
else
{
- const char *str = form_value.AsCString(&debug_info_data);
+ const char *str = form_value.AsCString();
uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart();
uint32_t string_length = strlen(str) + 1;
location.CopyOpcodeData(module, debug_info_data, string_offset, string_length);
@@ -7503,10 +4142,10 @@ SymbolFileDWARF::ParseVariableDIE
}
else
{
- const DWARFDataExtractor& debug_loc_data = get_debug_loc_data();
+ const DWARFDataExtractor& debug_loc_data = get_debug_loc_data();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
- size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
+ size_t loc_list_length = DWARFExpression::LocationListSize(die.GetCU(), debug_loc_data, debug_loc_offset);
if (loc_list_length > 0)
{
location.CopyOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length);
@@ -7516,7 +4155,13 @@ SymbolFileDWARF::ParseVariableDIE
}
}
break;
-
+ case DW_AT_specification:
+ {
+ DWARFDebugInfo* debug_info = DebugInfo();
+ if (debug_info)
+ spec_die = debug_info->GetDIE(DIERef(form_value));
+ break;
+ }
case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
case DW_AT_declaration:
@@ -7528,16 +4173,18 @@ SymbolFileDWARF::ParseVariableDIE
default:
case DW_AT_abstract_origin:
case DW_AT_sibling:
- case DW_AT_specification:
break;
}
}
}
+ const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
+ const dw_tag_t parent_tag = die.GetParent().Tag();
+ bool is_static_member = parent_tag == DW_TAG_compile_unit && (parent_context_die.Tag() == DW_TAG_class_type || parent_context_die.Tag() == DW_TAG_structure_type);
+
ValueType scope = eValueTypeInvalid;
- const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
- dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
+ const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
SymbolContextScope * symbol_context_scope = NULL;
if (!mangled)
@@ -7548,12 +4195,12 @@ SymbolFileDWARF::ParseVariableDIE
// B which in turn is contained in a namespace A, the command "frame var j" returns
// "(int) A::B::j = 4". If the compiler does not emit a linkage name, we should be able
// to generate a fully qualified name from the declaration context.
- if (die->GetParent()->Tag() == DW_TAG_compile_unit &&
- LanguageRuntime::LanguageIsCPlusPlus(dwarf_cu->GetLanguageType()))
+ if (parent_tag == DW_TAG_compile_unit &&
+ Language::LanguageIsCPlusPlus(die.GetLanguage()))
{
DWARFDeclContext decl_ctx;
- die->GetDWARFDeclContext(this, dwarf_cu, decl_ctx);
+ die.GetDWARFDeclContext(decl_ctx);
mangled = decl_ctx.GetQualifiedNameAsConstString().GetCString();
}
}
@@ -7582,7 +4229,7 @@ SymbolFileDWARF::ParseVariableDIE
{
StreamString strm;
location.DumpLocationForAddress (&strm, eDescriptionLevelFull, 0, 0, NULL);
- GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), strm.GetString().c_str());
+ GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die.GetOffset(), die.GetTagAsCString(), strm.GetString().c_str());
}
}
@@ -7670,7 +4317,10 @@ SymbolFileDWARF::ParseVariableDIE
}
else
{
- scope = eValueTypeVariableLocal;
+ if (location_is_const_value_data)
+ scope = eValueTypeVariableStatic;
+ else
+ scope = eValueTypeVariableLocal;
}
}
@@ -7683,7 +4333,7 @@ SymbolFileDWARF::ParseVariableDIE
case DW_TAG_lexical_block:
if (sc.function)
{
- symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset()));
+ symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
if (symbol_context_scope == NULL)
symbol_context_scope = sc.function;
}
@@ -7697,12 +4347,12 @@ SymbolFileDWARF::ParseVariableDIE
if (symbol_context_scope)
{
- SymbolFileTypeSP type_sp(new SymbolFileType(*this, type_uid));
+ SymbolFileTypeSP type_sp(new SymbolFileType(*this, DIERef(type_die_form).GetUID()));
if (const_value.Form() && type_sp && type_sp->GetType())
- location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), dwarf_cu->GetAddressByteSize());
+ location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), die.GetCU()->GetAddressByteSize());
- var_sp.reset (new Variable (MakeUserID(die->GetOffset()),
+ var_sp.reset (new Variable (die.GetID(),
name,
mangled,
type_sp,
@@ -7711,7 +4361,8 @@ SymbolFileDWARF::ParseVariableDIE
&decl,
location,
is_external,
- is_artificial));
+ is_artificial,
+ is_static_member));
var_sp->SetLocationIsConstantValueData (location_is_const_value_data);
}
@@ -7727,57 +4378,42 @@ SymbolFileDWARF::ParseVariableDIE
// was missing vital information to be able to be displayed in the debugger
// (missing location due to optimization, etc)) so we don't re-parse
// this DIE over and over later...
- m_die_to_variable_sp[die] = var_sp;
+ GetDIEToVariable()[die.GetDIE()] = var_sp;
+ if (spec_die)
+ GetDIEToVariable()[spec_die.GetDIE()] = var_sp;
}
return var_sp;
}
-const DWARFDebugInfoEntry *
-SymbolFileDWARF::FindBlockContainingSpecification (dw_offset_t func_die_offset,
- dw_offset_t spec_block_die_offset,
- DWARFCompileUnit **result_die_cu_handle)
+DWARFDIE
+SymbolFileDWARF::FindBlockContainingSpecification (const DIERef& func_die_ref,
+ dw_offset_t spec_block_die_offset)
{
// Give the concrete function die specified by "func_die_offset", find the
// concrete block whose DW_AT_specification or DW_AT_abstract_origin points
// to "spec_block_die_offset"
- DWARFDebugInfo* info = DebugInfo();
-
- const DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint(func_die_offset, result_die_cu_handle);
- if (die)
- {
- assert (*result_die_cu_handle);
- return FindBlockContainingSpecification (*result_die_cu_handle, die, spec_block_die_offset, result_die_cu_handle);
- }
- return NULL;
+ return FindBlockContainingSpecification (DebugInfo()->GetDIE (func_die_ref), spec_block_die_offset);
}
-const DWARFDebugInfoEntry *
-SymbolFileDWARF::FindBlockContainingSpecification(DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- dw_offset_t spec_block_die_offset,
- DWARFCompileUnit **result_die_cu_handle)
+DWARFDIE
+SymbolFileDWARF::FindBlockContainingSpecification(const DWARFDIE &die,
+ dw_offset_t spec_block_die_offset)
{
if (die)
{
- switch (die->Tag())
+ switch (die.Tag())
{
case DW_TAG_subprogram:
case DW_TAG_inlined_subroutine:
case DW_TAG_lexical_block:
{
- if (die->GetAttributeValueAsReference (this, dwarf_cu, DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset)
- {
- *result_die_cu_handle = dwarf_cu;
+ if (die.GetAttributeValueAsReference (DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset)
return die;
- }
- if (die->GetAttributeValueAsReference (this, dwarf_cu, DW_AT_abstract_origin, DW_INVALID_OFFSET) == spec_block_die_offset)
- {
- *result_die_cu_handle = dwarf_cu;
+ if (die.GetAttributeValueAsReference (DW_AT_abstract_origin, DW_INVALID_OFFSET) == spec_block_die_offset)
return die;
- }
}
break;
}
@@ -7785,49 +4421,42 @@ SymbolFileDWARF::FindBlockContainingSpecification(DWARFCompileUnit* dwarf_cu,
// Give the concrete function die specified by "func_die_offset", find the
// concrete block whose DW_AT_specification or DW_AT_abstract_origin points
// to "spec_block_die_offset"
- for (const DWARFDebugInfoEntry *child_die = die->GetFirstChild(); child_die != NULL; child_die = child_die->GetSibling())
+ for (DWARFDIE child_die = die.GetFirstChild(); child_die; child_die = child_die.GetSibling())
{
- const DWARFDebugInfoEntry *result_die = FindBlockContainingSpecification (dwarf_cu,
- child_die,
- spec_block_die_offset,
- result_die_cu_handle);
+ DWARFDIE result_die = FindBlockContainingSpecification (child_die, spec_block_die_offset);
if (result_die)
return result_die;
}
}
- *result_die_cu_handle = NULL;
- return NULL;
+ return DWARFDIE();
}
size_t
-SymbolFileDWARF::ParseVariables
-(
- const SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const lldb::addr_t func_low_pc,
- const DWARFDebugInfoEntry *orig_die,
- bool parse_siblings,
- bool parse_children,
- VariableList* cc_variable_list
-)
+SymbolFileDWARF::ParseVariables (const SymbolContext& sc,
+ const DWARFDIE &orig_die,
+ const lldb::addr_t func_low_pc,
+ bool parse_siblings,
+ bool parse_children,
+ VariableList* cc_variable_list)
{
- if (orig_die == NULL)
+ if (!orig_die)
return 0;
VariableListSP variable_list_sp;
size_t vars_added = 0;
- const DWARFDebugInfoEntry *die = orig_die;
- while (die != NULL)
+ DWARFDIE die = orig_die;
+ while (die)
{
- dw_tag_t tag = die->Tag();
+ dw_tag_t tag = die.Tag();
// Check to see if we have already parsed this variable or constant?
- if (m_die_to_variable_sp[die])
+ VariableSP var_sp = GetDIEToVariable()[die.GetDIE()];
+ if (var_sp)
{
if (cc_variable_list)
- cc_variable_list->AddVariableIfUnique (m_die_to_variable_sp[die]);
+ cc_variable_list->AddVariableIfUnique (var_sp);
}
else
{
@@ -7838,8 +4467,8 @@ SymbolFileDWARF::ParseVariables
{
if (variable_list_sp.get() == NULL)
{
- const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(orig_die);
- dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
+ DWARFDIE sc_parent_die = GetParentSymbolContextDIE(orig_die);
+ dw_tag_t parent_tag = sc_parent_die.Tag();
switch (parent_tag)
{
case DW_TAG_compile_unit:
@@ -7855,10 +4484,10 @@ SymbolFileDWARF::ParseVariables
else
{
GetObjectFile()->GetModule()->ReportError ("parent 0x%8.8" PRIx64 " %s with no valid compile unit in symbol context for 0x%8.8" PRIx64 " %s.\n",
- MakeUserID(sc_parent_die->GetOffset()),
- DW_TAG_value_to_name (parent_tag),
- MakeUserID(orig_die->GetOffset()),
- DW_TAG_value_to_name (orig_die->Tag()));
+ sc_parent_die.GetID(),
+ sc_parent_die.GetTagAsCString(),
+ orig_die.GetID(),
+ orig_die.GetTagAsCString());
}
break;
@@ -7869,19 +4498,17 @@ SymbolFileDWARF::ParseVariables
{
// Check to see if we already have parsed the variables for the given scope
- Block *block = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset()));
+ Block *block = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
if (block == NULL)
{
// This must be a specification or abstract origin with
// a concrete block counterpart in the current function. We need
// to find the concrete block so we can correctly add the
// variable to it
- DWARFCompileUnit *concrete_block_die_cu = dwarf_cu;
- const DWARFDebugInfoEntry *concrete_block_die = FindBlockContainingSpecification (sc.function->GetID(),
- sc_parent_die->GetOffset(),
- &concrete_block_die_cu);
+ const DWARFDIE concrete_block_die = FindBlockContainingSpecification (DIERef(sc.function->GetID()),
+ sc_parent_die.GetOffset());
if (concrete_block_die)
- block = sc.function->GetBlock(true).FindBlockByID(MakeUserID(concrete_block_die->GetOffset()));
+ block = sc.function->GetBlock(true).FindBlockByID(concrete_block_die.GetID());
}
if (block != NULL)
@@ -7899,15 +4526,15 @@ SymbolFileDWARF::ParseVariables
default:
GetObjectFile()->GetModule()->ReportError ("didn't find appropriate parent DIE for variable list for 0x%8.8" PRIx64 " %s.\n",
- MakeUserID(orig_die->GetOffset()),
- DW_TAG_value_to_name (orig_die->Tag()));
+ orig_die.GetID(),
+ orig_die.GetTagAsCString());
break;
}
}
if (variable_list_sp)
{
- VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, func_low_pc));
+ VariableSP var_sp (ParseVariableDIE(sc, die, func_low_pc));
if (var_sp)
{
variable_list_sp->AddVariableIfUnique (var_sp);
@@ -7921,15 +4548,15 @@ SymbolFileDWARF::ParseVariables
bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram);
- if (!skip_children && parse_children && die->HasChildren())
+ if (!skip_children && parse_children && die.HasChildren())
{
- vars_added += ParseVariables(sc, dwarf_cu, func_low_pc, die->GetFirstChild(), true, true, cc_variable_list);
+ vars_added += ParseVariables(sc, die.GetFirstChild(), func_low_pc, true, true, cc_variable_list);
}
if (parse_siblings)
- die = die->GetSibling();
+ die = die.GetSibling();
else
- die = NULL;
+ die.Clear();
}
return vars_added;
}
@@ -7950,24 +4577,6 @@ SymbolFileDWARF::GetPluginVersion()
}
void
-SymbolFileDWARF::CompleteTagDecl (void *baton, clang::TagDecl *decl)
-{
- SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
- ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
- if (clang_type)
- symbol_file_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
-}
-
-void
-SymbolFileDWARF::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl)
-{
- SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
- ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
- if (clang_type)
- symbol_file_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
-}
-
-void
SymbolFileDWARF::DumpIndexes ()
{
StreamFile s(stdout, false);
@@ -7982,147 +4591,7 @@ SymbolFileDWARF::DumpIndexes ()
s.Printf("\nObjective C class selectors:\n"); m_objc_class_selectors_index.Dump (&s);
s.Printf("\nGlobals and statics:\n"); m_global_index.Dump (&s);
s.Printf("\nTypes:\n"); m_type_index.Dump (&s);
- s.Printf("\nNamepaces:\n"); m_namespace_index.Dump (&s);
-}
-
-void
-SymbolFileDWARF::SearchDeclContext (const clang::DeclContext *decl_context,
- const char *name,
- llvm::SmallVectorImpl <clang::NamedDecl *> *results)
-{
- DeclContextToDIEMap::iterator iter = m_decl_ctx_to_die.find(decl_context);
-
- if (iter == m_decl_ctx_to_die.end())
- return;
-
- for (DIEPointerSet::iterator pos = iter->second.begin(), end = iter->second.end(); pos != end; ++pos)
- {
- const DWARFDebugInfoEntry *context_die = *pos;
-
- if (!results)
- return;
-
- DWARFDebugInfo* info = DebugInfo();
-
- DIEArray die_offsets;
-
- DWARFCompileUnit* dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
-
- if (m_using_apple_tables)
- {
- if (m_apple_types_ap.get())
- m_apple_types_ap->FindByName (name, die_offsets);
- }
- else
- {
- if (!m_indexed)
- Index ();
-
- m_type_index.Find (ConstString(name), die_offsets);
- }
-
- const size_t num_matches = die_offsets.size();
-
- if (num_matches)
- {
- for (size_t i = 0; i < num_matches; ++i)
- {
- const dw_offset_t die_offset = die_offsets[i];
- die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
-
- if (die->GetParent() != context_die)
- continue;
-
- Type *matching_type = ResolveType (dwarf_cu, die);
-
- clang::QualType qual_type = matching_type->GetClangForwardType().GetQualType();
-
- if (const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()))
- {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- results->push_back(tag_decl);
- }
- else if (const clang::TypedefType *typedef_type = llvm::dyn_cast<clang::TypedefType>(qual_type.getTypePtr()))
- {
- clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
- results->push_back(typedef_decl);
- }
- }
- }
- }
-}
-
-void
-SymbolFileDWARF::FindExternalVisibleDeclsByName (void *baton,
- const clang::DeclContext *decl_context,
- clang::DeclarationName decl_name,
- llvm::SmallVectorImpl <clang::NamedDecl *> *results)
-{
-
- switch (decl_context->getDeclKind())
- {
- case clang::Decl::Namespace:
- case clang::Decl::TranslationUnit:
- {
- SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
- symbol_file_dwarf->SearchDeclContext (decl_context, decl_name.getAsString().c_str(), results);
- }
- break;
- default:
- break;
- }
-}
-
-bool
-SymbolFileDWARF::LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size,
- uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
-{
- SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
- return symbol_file_dwarf->LayoutRecordType (record_decl, size, alignment, field_offsets, base_offsets, vbase_offsets);
-}
-
-bool
-SymbolFileDWARF::LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &bit_size, uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
-{
- Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find (record_decl);
- bool success = false;
- base_offsets.clear();
- vbase_offsets.clear();
- if (pos != m_record_decl_to_layout_map.end())
- {
- bit_size = pos->second.bit_size;
- alignment = pos->second.alignment;
- field_offsets.swap(pos->second.field_offsets);
- base_offsets.swap (pos->second.base_offsets);
- vbase_offsets.swap (pos->second.vbase_offsets);
- m_record_decl_to_layout_map.erase(pos);
- success = true;
- }
- else
- {
- bit_size = 0;
- alignment = 0;
- field_offsets.clear();
- }
-
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::LayoutRecordType (record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u],base_offsets[%u], vbase_offsets[%u]) success = %i",
- static_cast<const void*>(record_decl),
- bit_size, alignment,
- static_cast<uint32_t>(field_offsets.size()),
- static_cast<uint32_t>(base_offsets.size()),
- static_cast<uint32_t>(vbase_offsets.size()),
- success);
- return success;
+ s.Printf("\nNamespaces:\n"); m_namespace_index.Dump (&s);
}
@@ -8142,4 +4611,8 @@ SymbolFileDWARF::GetDebugMapSymfile ()
return m_debug_map_symfile;
}
-
+DWARFExpression::LocationListFormat
+SymbolFileDWARF::GetLocationListFormat() const
+{
+ return DWARFExpression::RegularLocationList;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 2f0b3f0..be09759 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -14,24 +14,22 @@
// C++ Includes
#include <list>
#include <map>
+#include <mutex>
#include <set>
+#include <unordered_map>
#include <vector>
// Other libraries and framework includes
-#include "clang/AST/CharUnits.h"
-#include "clang/AST/ExternalASTSource.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
#include "lldb/lldb-private.h"
-#include "lldb/Core/ClangForward.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Core/Flags.h"
#include "lldb/Core/RangeMap.h"
#include "lldb/Core/UniqueCStringMap.h"
-#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -61,12 +59,18 @@ class DWARFDIECollection;
class DWARFFormValue;
class SymbolFileDWARFDebugMap;
+#define DIE_IS_BEING_PARSED ((lldb_private::Type*)1)
+
class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::UserID
{
public:
friend class SymbolFileDWARFDebugMap;
+ friend class SymbolFileDWARFDwo;
friend class DebugMapModule;
friend class DWARFCompileUnit;
+ friend class DWARFASTParserClang;
+ friend class DWARFASTParserGo;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -76,6 +80,9 @@ public:
static void
Terminate();
+ static void
+ DebuggerInitialize(lldb_private::Debugger &debugger);
+
static lldb_private::ConstString
GetPluginNameStatic();
@@ -84,481 +91,423 @@ public:
static lldb_private::SymbolFile*
CreateInstance (lldb_private::ObjectFile* obj_file);
+
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- SymbolFileDWARF(lldb_private::ObjectFile* ofile);
- virtual ~SymbolFileDWARF();
- virtual uint32_t CalculateAbilities ();
- virtual void InitializeObject();
+ SymbolFileDWARF(lldb_private::ObjectFile* ofile);
+
+ ~SymbolFileDWARF() override;
+
+ uint32_t
+ CalculateAbilities () override;
+
+ void
+ InitializeObject() override;
//------------------------------------------------------------------
// Compile Unit function calls
//------------------------------------------------------------------
- virtual uint32_t GetNumCompileUnits();
- virtual lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index);
-
- virtual lldb::LanguageType ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc);
- virtual size_t ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
- virtual bool ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
- virtual bool ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList& support_files);
- virtual bool ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules);
- virtual size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
- virtual size_t ParseTypes (const lldb_private::SymbolContext& sc);
- virtual size_t ParseVariablesForContext (const lldb_private::SymbolContext& sc);
-
- virtual lldb_private::Type* ResolveTypeUID(lldb::user_id_t type_uid);
- virtual bool ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type);
-
- virtual lldb_private::Type* ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* type_die, bool assert_not_being_parsed = true);
- virtual clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid);
- virtual clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid);
-
- virtual uint32_t ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc);
- virtual uint32_t ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list);
- virtual uint32_t FindGlobalVariables(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
- virtual uint32_t FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
- virtual uint32_t FindFunctions(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
- virtual uint32_t FindFunctions(const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
- virtual uint32_t FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types);
- virtual lldb_private::TypeList *
- GetTypeList ();
- virtual size_t GetTypes (lldb_private::SymbolContextScope *sc_scope,
- uint32_t type_mask,
- lldb_private::TypeList &type_list);
-
- virtual lldb_private::ClangASTContext &
- GetClangASTContext ();
-
- virtual lldb_private::ClangNamespaceDecl
- FindNamespace (const lldb_private::SymbolContext& sc,
- const lldb_private::ConstString &name,
- const lldb_private::ClangNamespaceDecl *parent_namespace_decl);
+ uint32_t
+ GetNumCompileUnits() override;
- //------------------------------------------------------------------
- // ClangASTContext callbacks for external source lookups.
- //------------------------------------------------------------------
- static void
- CompleteTagDecl (void *baton, clang::TagDecl *);
-
- static void
- CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *);
+ lldb::CompUnitSP
+ ParseCompileUnitAtIndex(uint32_t index) override;
+
+ lldb::LanguageType
+ ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc) override;
+
+ size_t
+ ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc) override;
+
+ bool
+ ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc) override;
+
+ bool
+ ParseCompileUnitDebugMacros (const lldb_private::SymbolContext& sc) override;
+
+ bool
+ ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc,
+ lldb_private::FileSpecList& support_files) override;
+
+ bool
+ ParseImportedModules (const lldb_private::SymbolContext &sc,
+ std::vector<lldb_private::ConstString> &imported_modules) override;
+
+ size_t
+ ParseFunctionBlocks (const lldb_private::SymbolContext& sc) override;
+
+ size_t
+ ParseTypes (const lldb_private::SymbolContext& sc) override;
+
+ size_t
+ ParseVariablesForContext (const lldb_private::SymbolContext& sc) override;
+
+ lldb_private::Type *
+ ResolveTypeUID(lldb::user_id_t type_uid) override;
+
+ bool
+ CompleteType (lldb_private::CompilerType& compiler_type) override;
+
+ lldb_private::Type *
+ ResolveType (const DWARFDIE &die,
+ bool assert_not_being_parsed = true,
+ bool resolve_function_context = false);
+
+ lldb_private::CompilerDecl
+ GetDeclForUID (lldb::user_id_t uid) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextForUID (lldb::user_id_t uid) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextContainingUID (lldb::user_id_t uid) override;
+
+ void
+ ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx) override;
- static void
- FindExternalVisibleDeclsByName (void *baton,
- const clang::DeclContext *DC,
- clang::DeclarationName Name,
- llvm::SmallVectorImpl <clang::NamedDecl *> *results);
-
- static bool LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
-
- bool LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
-
- struct LayoutInfo
- {
- LayoutInfo () :
- bit_size(0),
- alignment(0),
- field_offsets(),
- base_offsets(),
- vbase_offsets()
- {
- }
- uint64_t bit_size;
- uint64_t alignment;
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets;
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets;
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets;
- };
+
+ uint32_t
+ ResolveSymbolContext (const lldb_private::Address& so_addr,
+ uint32_t resolve_scope,
+ lldb_private::SymbolContext& sc) override;
+
+ uint32_t
+ ResolveSymbolContext (const lldb_private::FileSpec& file_spec,
+ uint32_t line,
+ bool check_inlines,
+ uint32_t resolve_scope,
+ lldb_private::SymbolContextList& sc_list) override;
+
+ uint32_t
+ FindGlobalVariables (const lldb_private::ConstString &name,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ bool append,
+ uint32_t max_matches,
+ lldb_private::VariableList& variables) override;
+
+ uint32_t
+ FindGlobalVariables (const lldb_private::RegularExpression& regex,
+ bool append,
+ uint32_t max_matches,
+ lldb_private::VariableList& variables) override;
+
+ uint32_t
+ FindFunctions (const lldb_private::ConstString &name,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ uint32_t name_type_mask,
+ bool include_inlines,
+ bool append,
+ lldb_private::SymbolContextList& sc_list) override;
+
+ uint32_t
+ FindFunctions (const lldb_private::RegularExpression& regex,
+ bool include_inlines,
+ bool append,
+ lldb_private::SymbolContextList& sc_list) override;
+
+ void
+ GetMangledNamesForFunction (const std::string &scope_qualified_name,
+ std::vector<lldb_private::ConstString> &mangled_names) override;
+
+ uint32_t
+ FindTypes (const lldb_private::SymbolContext& sc,
+ const lldb_private::ConstString &name,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ bool append,
+ uint32_t max_matches,
+ lldb_private::TypeMap& types) override;
+
+ size_t
+ FindTypes (const std::vector<lldb_private::CompilerContext> &context,
+ bool append,
+ lldb_private::TypeMap& types) override;
+
+ lldb_private::TypeList *
+ GetTypeList () override;
+
+ size_t
+ GetTypes (lldb_private::SymbolContextScope *sc_scope,
+ uint32_t type_mask,
+ lldb_private::TypeList &type_list) override;
+
+ lldb_private::TypeSystem *
+ GetTypeSystemForLanguage (lldb::LanguageType language) override;
+
+ lldb_private::CompilerDeclContext
+ FindNamespace (const lldb_private::SymbolContext& sc,
+ const lldb_private::ConstString &name,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx) override;
+
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
-
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
- // Approach 2 - count + accessor
- // Index compile units would scan the initial compile units and register
- // them with the module. This would only be done on demand if and only if
- // the compile units were needed.
- //virtual size_t GetCompUnitCount() = 0;
- //virtual CompUnitSP GetCompUnitAtIndex(size_t cu_idx) = 0;
+ uint32_t
+ GetPluginVersion() override;
const lldb_private::DWARFDataExtractor& get_debug_abbrev_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_addr_data ();
const lldb_private::DWARFDataExtractor& get_debug_aranges_data ();
const lldb_private::DWARFDataExtractor& get_debug_frame_data ();
const lldb_private::DWARFDataExtractor& get_debug_info_data ();
const lldb_private::DWARFDataExtractor& get_debug_line_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_macro_data ();
const lldb_private::DWARFDataExtractor& get_debug_loc_data ();
const lldb_private::DWARFDataExtractor& get_debug_ranges_data ();
const lldb_private::DWARFDataExtractor& get_debug_str_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_str_offsets_data ();
const lldb_private::DWARFDataExtractor& get_apple_names_data ();
const lldb_private::DWARFDataExtractor& get_apple_types_data ();
const lldb_private::DWARFDataExtractor& get_apple_namespaces_data ();
const lldb_private::DWARFDataExtractor& get_apple_objc_data ();
- DWARFDebugAbbrev* DebugAbbrev();
- const DWARFDebugAbbrev* DebugAbbrev() const;
+ DWARFDebugAbbrev*
+ DebugAbbrev();
- DWARFDebugInfo* DebugInfo();
- const DWARFDebugInfo* DebugInfo() const;
+ const DWARFDebugAbbrev*
+ DebugAbbrev() const;
- DWARFDebugRanges* DebugRanges();
- const DWARFDebugRanges* DebugRanges() const;
+ DWARFDebugInfo*
+ DebugInfo();
- const lldb_private::DWARFDataExtractor&
- GetCachedSectionData (uint32_t got_flag,
- lldb::SectionType sect_type,
- lldb_private::DWARFDataExtractor &data);
+ const DWARFDebugInfo*
+ DebugInfo() const;
+
+ DWARFDebugRanges*
+ DebugRanges();
+
+ const DWARFDebugRanges*
+ DebugRanges() const;
static bool
SupportedVersion(uint16_t version);
- clang::DeclContext *
- GetCachedClangDeclContextForDIE (const DWARFDebugInfoEntry *die)
- {
- DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die);
- if (pos != m_die_to_decl_ctx.end())
- return pos->second;
- else
- return NULL;
- }
+ DWARFDIE
+ GetDeclContextDIEContainingDIE (const DWARFDIE &die);
- clang::DeclContext *
- GetClangDeclContextForDIE (const lldb_private::SymbolContext &sc, DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die);
-
- clang::DeclContext *
- GetClangDeclContextForDIEOffset (const lldb_private::SymbolContext &sc, dw_offset_t die_offset);
-
- clang::DeclContext *
- GetClangDeclContextContainingDIE (DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
- const DWARFDebugInfoEntry **decl_ctx_die);
-
- clang::DeclContext *
- GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset);
+ bool
+ HasForwardDeclForClangType (const lldb_private::CompilerType &compiler_type);
- const DWARFDebugInfoEntry *
- GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die);
+ lldb_private::CompileUnit*
+ GetCompUnitForDWARFCompUnit(DWARFCompileUnit* dwarf_cu,
+ uint32_t cu_idx = UINT32_MAX);
- void
- SearchDeclContext (const clang::DeclContext *decl_context,
- const char *name,
- llvm::SmallVectorImpl <clang::NamedDecl *> *results);
-
- lldb_private::Flags&
- GetFlags ()
+ lldb::user_id_t
+ MakeUserID (dw_offset_t die_offset) const
{
- return m_flags;
+ return GetID() | die_offset;
}
- const lldb_private::Flags&
- GetFlags () const
- {
- return m_flags;
- }
+ size_t
+ GetObjCMethodDIEOffsets (lldb_private::ConstString class_name,
+ DIEArray &method_die_offsets);
bool
- HasForwardDeclForClangType (const lldb_private::ClangASTType &clang_type);
+ Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu);
+
+ lldb_private::DebugMacrosSP
+ ParseDebugMacros(lldb::offset_t *offset);
+
+ static DWARFDIE
+ GetParentSymbolContextDIE(const DWARFDIE &die);
+
+ virtual lldb::CompUnitSP
+ ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx);
+
+ virtual lldb_private::DWARFExpression::LocationListFormat
+ GetLocationListFormat() const;
+
+ lldb::ModuleSP
+ GetDWOModule (lldb_private::ConstString name);
protected:
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr;
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP;
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::opaque_compiler_type_t> DIEToClangType;
+ typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> ClangTypeToDIE;
- enum
+ struct DWARFDataSegment
{
- flagsGotDebugAbbrevData = (1 << 0),
- flagsGotDebugArangesData = (1 << 1),
- flagsGotDebugFrameData = (1 << 2),
- flagsGotDebugInfoData = (1 << 3),
- flagsGotDebugLineData = (1 << 4),
- flagsGotDebugLocData = (1 << 5),
- flagsGotDebugMacInfoData = (1 << 6),
- flagsGotDebugPubNamesData = (1 << 7),
- flagsGotDebugPubTypesData = (1 << 8),
- flagsGotDebugRangesData = (1 << 9),
- flagsGotDebugStrData = (1 << 10),
- flagsGotAppleNamesData = (1 << 11),
- flagsGotAppleTypesData = (1 << 12),
- flagsGotAppleNamespacesData = (1 << 13),
- flagsGotAppleObjCData = (1 << 14)
+ std::once_flag m_flag;
+ lldb_private::DWARFDataExtractor m_data;
};
-
- bool NamespaceDeclMatchesThisSymbolFile (const lldb_private::ClangNamespaceDecl *namespace_decl);
-
- bool DIEIsInNamespace (const lldb_private::ClangNamespaceDecl *namespace_decl,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry* die);
DISALLOW_COPY_AND_ASSIGN (SymbolFileDWARF);
- lldb::CompUnitSP ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx);
- DWARFCompileUnit* GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit);
- DWARFCompileUnit* GetNextUnparsedDWARFCompileUnit(DWARFCompileUnit* prev_cu);
- lldb_private::CompileUnit* GetCompUnitForDWARFCompUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx = UINT32_MAX);
- bool GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* func_die, lldb_private::SymbolContext& sc);
- lldb_private::Function * ParseCompileUnitFunction (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die);
- size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc,
- lldb_private::Block *parent_block,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- lldb::addr_t subprogram_low_pc,
- uint32_t depth);
- size_t ParseTypes (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children);
- lldb::TypeSP ParseType (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool *type_is_new);
- lldb_private::Type* ResolveTypeUID (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* die, bool assert_not_being_parsed);
-
- lldb::VariableSP ParseVariableDIE(
- const lldb_private::SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- const lldb::addr_t func_low_pc);
-
- size_t ParseVariables(
- const lldb_private::SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const lldb::addr_t func_low_pc,
- const DWARFDebugInfoEntry *die,
- bool parse_siblings,
- bool parse_children,
- lldb_private::VariableList* cc_variable_list = NULL);
-
- class DelayedAddObjCClassProperty;
- typedef std::vector <DelayedAddObjCClassProperty> DelayedPropertyList;
-
- bool ClassOrStructIsVirtual (
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die);
-
- size_t ParseChildMembers(
- const lldb_private::SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- lldb_private::ClangASTType &class_clang_type,
- const lldb::LanguageType class_language,
- std::vector<clang::CXXBaseSpecifier *>& base_classes,
- std::vector<int>& member_accessibilities,
- DWARFDIECollection& member_function_dies,
- DelayedPropertyList& delayed_properties,
- lldb::AccessType &default_accessibility,
- bool &is_a_class,
- LayoutInfo &layout_info);
-
- size_t ParseChildParameters(
- const lldb_private::SymbolContext& sc,
- clang::DeclContext *containing_decl_ctx,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- bool skip_artificial,
- bool &is_static,
- bool &is_variadic,
- std::vector<lldb_private::ClangASTType>& function_args,
- std::vector<clang::ParmVarDecl*>& function_param_decls,
- unsigned &type_quals);
- // lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); // not currently needed
-
-
- size_t ParseChildEnumerators(
- const lldb_private::SymbolContext& sc,
- lldb_private::ClangASTType &clang_type,
- bool is_signed,
- uint32_t enumerator_byte_size,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *enum_die);
-
- void ParseChildArrayInfo(
- const lldb_private::SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- int64_t& first_index,
- std::vector<uint64_t>& element_orders,
- uint32_t& byte_stride,
- uint32_t& bit_stride);
-
- // Given a die_offset, figure out the symbol context representing that die.
- bool ResolveFunction (dw_offset_t offset,
- DWARFCompileUnit *&dwarf_cu,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
-
- bool ResolveFunction (DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
-
- bool FunctionDieMatchesPartialName (
- const DWARFDebugInfoEntry* die,
- const DWARFCompileUnit *dwarf_cu,
- uint32_t name_type_mask,
- const char *partial_name,
- const char *base_name_start,
- const char *base_name_end);
-
- void FindFunctions(
- const lldb_private::ConstString &name,
- const NameToDIE &name_to_die,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
-
- void FindFunctions (
- const lldb_private::RegularExpression &regex,
- const NameToDIE &name_to_die,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
-
- void FindFunctions (
- const lldb_private::RegularExpression &regex,
- const DWARFMappedHash::MemoryTable &memory_table,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
-
- lldb::TypeSP FindDefinitionTypeForDWARFDeclContext (
- const DWARFDeclContext &die_decl_ctx);
-
- lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE (
- const DWARFDebugInfoEntry *die,
- const lldb_private::ConstString &type_name,
- bool must_be_implementation);
-
- bool Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu);
-
- lldb::TypeSP FindCompleteObjCDefinitionType (const lldb_private::ConstString &type_name,
- bool header_definition_ok);
-
- lldb_private::Symbol * GetObjCClassSymbol (const lldb_private::ConstString &objc_class_name);
-
- void ParseFunctions (const DIEArray &die_offsets,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
- lldb::TypeSP GetTypeForDIE (DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry* die);
-
- uint32_t FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, lldb_private::TypeList& types);
-
- void Index();
-
- void DumpIndexes();
- void SetDebugMapModule (const lldb::ModuleSP &module_sp)
- {
- m_debug_map_module_wp = module_sp;
- }
+ const lldb_private::DWARFDataExtractor&
+ GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment);
+
+ virtual void
+ LoadSectionData (lldb::SectionType sect_type, lldb_private::DWARFDataExtractor& data);
+
+ bool
+ DeclContextMatchesThisSymbolFile (const lldb_private::CompilerDeclContext *decl_ctx);
+
+ bool
+ DIEInDeclContext (const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ const DWARFDIE &die);
+
+ virtual DWARFCompileUnit*
+ GetDWARFCompileUnit (lldb_private::CompileUnit *comp_unit);
+
+ DWARFCompileUnit*
+ GetNextUnparsedDWARFCompileUnit (DWARFCompileUnit* prev_cu);
+
+ bool
+ GetFunction (const DWARFDIE &die,
+ lldb_private::SymbolContext& sc);
+
+ lldb_private::Function *
+ ParseCompileUnitFunction (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die);
+
+ size_t
+ ParseFunctionBlocks (const lldb_private::SymbolContext& sc,
+ lldb_private::Block *parent_block,
+ const DWARFDIE &die,
+ lldb::addr_t subprogram_low_pc,
+ uint32_t depth);
+
+ size_t
+ ParseTypes (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ bool parse_siblings,
+ bool parse_children);
+
+ lldb::TypeSP
+ ParseType (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ bool *type_is_new);
+
+ lldb_private::Type *
+ ResolveTypeUID (const DWARFDIE &die,
+ bool assert_not_being_parsed);
+
+ lldb::VariableSP
+ ParseVariableDIE(const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ const lldb::addr_t func_low_pc);
+
+ size_t
+ ParseVariables (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &orig_die,
+ const lldb::addr_t func_low_pc,
+ bool parse_siblings,
+ bool parse_children,
+ lldb_private::VariableList* cc_variable_list = NULL);
+
+ bool
+ ClassOrStructIsVirtual (const DWARFDIE &die);
+
+ // Given a die_offset, figure out the symbol context representing that die.
+ bool
+ ResolveFunction (const DIERef& die_ref,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ bool
+ ResolveFunction (const DWARFDIE &die,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ void
+ FindFunctions(const lldb_private::ConstString &name,
+ const NameToDIE &name_to_die,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ void
+ FindFunctions (const lldb_private::RegularExpression &regex,
+ const NameToDIE &name_to_die,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ void
+ FindFunctions (const lldb_private::RegularExpression &regex,
+ const DWARFMappedHash::MemoryTable &memory_table,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ virtual lldb::TypeSP
+ FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx);
+
+ lldb::TypeSP
+ FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die,
+ const lldb_private::ConstString &type_name,
+ bool must_be_implementation);
+
+ lldb::TypeSP
+ FindCompleteObjCDefinitionType (const lldb_private::ConstString &type_name,
+ bool header_definition_ok);
+
+ lldb_private::Symbol *
+ GetObjCClassSymbol (const lldb_private::ConstString &objc_class_name);
+
+ void
+ ParseFunctions (const DIEArray &die_offsets,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ lldb::TypeSP
+ GetTypeForDIE (const DWARFDIE &die, bool resolve_function_context = false);
+
+ void
+ Index();
- SymbolFileDWARFDebugMap *
- GetDebugMapSymfile ();
+ void
+ DumpIndexes();
- const DWARFDebugInfoEntry *
- FindBlockContainingSpecification (dw_offset_t func_die_offset,
- dw_offset_t spec_block_die_offset,
- DWARFCompileUnit **dwarf_cu_handle);
+ void
+ SetDebugMapModule (const lldb::ModuleSP &module_sp)
+ {
+ m_debug_map_module_wp = module_sp;
+ }
+
+ SymbolFileDWARFDebugMap *
+ GetDebugMapSymfile ();
- const DWARFDebugInfoEntry *
- FindBlockContainingSpecification (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- dw_offset_t spec_block_die_offset,
- DWARFCompileUnit **dwarf_cu_handle);
+ DWARFDIE
+ FindBlockContainingSpecification (const DIERef& func_die_ref, dw_offset_t spec_block_die_offset);
- clang::NamespaceDecl *
- ResolveNamespaceDIE (DWARFCompileUnit *curr_cu, const DWARFDebugInfoEntry *die);
+ DWARFDIE
+ FindBlockContainingSpecification (const DWARFDIE &die, dw_offset_t spec_block_die_offset);
- UniqueDWARFASTTypeMap &
+ virtual UniqueDWARFASTTypeMap &
GetUniqueDWARFASTTypeMap ();
-
- void LinkDeclContextToDIE (clang::DeclContext *decl_ctx,
- const DWARFDebugInfoEntry *die)
- {
- m_die_to_decl_ctx[die] = decl_ctx;
- // There can be many DIEs for a single decl context
- m_decl_ctx_to_die[decl_ctx].insert(die);
- }
bool
UserIDMatches (lldb::user_id_t uid) const
{
const lldb::user_id_t high_uid = uid & 0xffffffff00000000ull;
- if (high_uid)
+ if (high_uid != 0 && GetID() != 0)
return high_uid == GetID();
return true;
}
- lldb::user_id_t
- MakeUserID (dw_offset_t die_offset) const
- {
- return GetID() | die_offset;
- }
-
- static bool
- DeclKindIsCXXClass (clang::Decl::Kind decl_kind)
- {
- switch (decl_kind)
- {
- case clang::Decl::CXXRecord:
- case clang::Decl::ClassTemplateSpecialization:
- return true;
- default:
- break;
- }
- return false;
- }
-
- bool
- ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
-
bool
- ParseTemplateDIE (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
-
- clang::ClassTemplateDecl *
- ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
- lldb::AccessType access_type,
- const char *parent_name,
- int tag_decl_kind,
- const lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
-
- bool
- DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1,
- DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2);
+ DIEDeclContextsMatch (const DWARFDIE &die1,
+ const DWARFDIE &die2);
bool
- ClassContainsSelector (DWARFCompileUnit *dwarf_cu,
- const DWARFDebugInfoEntry *class_die,
+ ClassContainsSelector (const DWARFDIE &class_die,
const lldb_private::ConstString &selector);
bool
- CopyUniqueClassMethodTypes (SymbolFileDWARF *class_symfile,
- lldb_private::Type *class_type,
- DWARFCompileUnit* src_cu,
- const DWARFDebugInfoEntry *src_class_die,
- DWARFCompileUnit* dst_cu,
- const DWARFDebugInfoEntry *dst_class_die,
- DWARFDIECollection &failures);
-
- bool
FixupAddress (lldb_private::Address &addr);
typedef std::set<lldb_private::Type *> TypeSet;
- typedef struct {
- lldb_private::ConstString m_name;
- lldb::ModuleSP m_module_sp;
- } ClangModuleInfo;
-
- typedef std::map<uint64_t, ClangModuleInfo> ExternalTypeModuleMap;
+ typedef std::map<lldb_private::ConstString, lldb::ModuleSP> ExternalTypeModuleMap;
void
- GetTypes (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
+ GetTypes (const DWARFDIE &die,
dw_offset_t min_die_offset,
dw_offset_t max_die_offset,
uint32_t type_mask,
@@ -572,23 +521,37 @@ protected:
void
UpdateExternalModuleListIfNeeded();
+ virtual DIEToTypePtr&
+ GetDIEToType() { return m_die_to_type; }
+
+ virtual DIEToVariableSP&
+ GetDIEToVariable() { return m_die_to_variable_sp; }
+
+ virtual DIEToClangType&
+ GetForwardDeclDieToClangType() { return m_forward_decl_die_to_clang_type; }
+
+ virtual ClangTypeToDIE&
+ GetForwardDeclClangTypeToDie() { return m_forward_decl_clang_type_to_die; }
+
lldb::ModuleWP m_debug_map_module_wp;
SymbolFileDWARFDebugMap * m_debug_map_symfile;
- clang::TranslationUnitDecl * m_clang_tu_decl;
- lldb_private::Flags m_flags;
- lldb_private::DWARFDataExtractor m_dwarf_data;
- lldb_private::DWARFDataExtractor m_data_debug_abbrev;
- lldb_private::DWARFDataExtractor m_data_debug_aranges;
- lldb_private::DWARFDataExtractor m_data_debug_frame;
- lldb_private::DWARFDataExtractor m_data_debug_info;
- lldb_private::DWARFDataExtractor m_data_debug_line;
- lldb_private::DWARFDataExtractor m_data_debug_loc;
- lldb_private::DWARFDataExtractor m_data_debug_ranges;
- lldb_private::DWARFDataExtractor m_data_debug_str;
- lldb_private::DWARFDataExtractor m_data_apple_names;
- lldb_private::DWARFDataExtractor m_data_apple_types;
- lldb_private::DWARFDataExtractor m_data_apple_namespaces;
- lldb_private::DWARFDataExtractor m_data_apple_objc;
+ lldb_private::DWARFDataExtractor m_dwarf_data;
+
+ DWARFDataSegment m_data_debug_abbrev;
+ DWARFDataSegment m_data_debug_addr;
+ DWARFDataSegment m_data_debug_aranges;
+ DWARFDataSegment m_data_debug_frame;
+ DWARFDataSegment m_data_debug_info;
+ DWARFDataSegment m_data_debug_line;
+ DWARFDataSegment m_data_debug_macro;
+ DWARFDataSegment m_data_debug_loc;
+ DWARFDataSegment m_data_debug_ranges;
+ DWARFDataSegment m_data_debug_str;
+ DWARFDataSegment m_data_debug_str_offsets;
+ DWARFDataSegment m_data_apple_names;
+ DWARFDataSegment m_data_apple_types;
+ DWARFDataSegment m_data_apple_namespaces;
+ DWARFDataSegment m_data_apple_objc;
// The unique pointer items below are generated on demand if and when someone accesses
// them through a non const version of this class.
@@ -600,6 +563,10 @@ protected:
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap;
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_ap;
std::unique_ptr<GlobalVariableMap> m_global_aranges_ap;
+
+ typedef std::unordered_map<lldb::offset_t, lldb_private::DebugMacrosSP> DebugMacrosMap;
+ DebugMacrosMap m_debug_macros_map;
+
ExternalTypeModuleMap m_external_type_modules;
NameToDIE m_function_basename_index; // All concrete functions
NameToDIE m_function_fullname_index; // All concrete functions
@@ -610,28 +577,19 @@ protected:
NameToDIE m_type_index; // All type DIE offsets
NameToDIE m_namespace_index; // All type DIE offsets
bool m_indexed:1,
- m_is_external_ast_source:1,
m_using_apple_tables:1,
m_fetched_external_modules:1;
lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
+ typedef std::shared_ptr<std::set<DIERef> > DIERefSetSP;
+ typedef std::unordered_map<std::string, DIERefSetSP> NameToOffsetMap;
+ NameToOffsetMap m_function_scope_qualified_name_map;
std::unique_ptr<DWARFDebugRanges> m_ranges;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
- typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet;
- typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
- typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
- typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr;
- typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP;
- typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::clang_type_t> DIEToClangType;
- typedef llvm::DenseMap<lldb::clang_type_t, const DWARFDebugInfoEntry *> ClangTypeToDIE;
- typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> RecordDeclToLayoutMap;
- DIEToDeclContextMap m_die_to_decl_ctx;
- DeclContextToDIEMap m_decl_ctx_to_die;
DIEToTypePtr m_die_to_type;
DIEToVariableSP m_die_to_variable_sp;
DIEToClangType m_forward_decl_die_to_clang_type;
ClangTypeToDIE m_forward_decl_clang_type_to_die;
- RecordDeclToLayoutMap m_record_decl_to_layout_map;
};
#endif // SymbolFileDWARF_SymbolFileDWARF_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index de972ac..be25dfc 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -1,4 +1,4 @@
-//===-- SymbolFileDWARFDebugMap.cpp ----------------------------*- C++ -*-===//
+//===-- SymbolFileDWARFDebugMap.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "SymbolFileDWARFDebugMap.h"
#include "DWARFDebugAranges.h"
@@ -24,11 +28,11 @@
#endif
#include "lldb/Core/Timer.h"
-#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/VariableList.h"
#include "LogChannelDWARF.h"
@@ -41,9 +45,6 @@ using namespace lldb_private;
// (so we can fixup the object file sections) and also for "Module::GetSymbolVendor()"
// (so we can fixup the symbol file id.
-
-
-
const SymbolFileDWARFDebugMap::FileRangeMap &
SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile)
{
@@ -173,7 +174,6 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
return file_range_map;
}
-
class DebugMapModule : public Module
{
public:
@@ -190,14 +190,10 @@ public:
{
}
- virtual
- ~DebugMapModule ()
- {
- }
+ ~DebugMapModule() override = default;
-
- virtual SymbolVendor*
- GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL)
+ SymbolVendor*
+ GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL) override
{
// Scope for locker
if (m_symfile_ap.get() || can_create == false)
@@ -259,7 +255,6 @@ SymbolFileDWARFDebugMap::Terminate()
PluginManager::UnregisterPlugin (CreateInstance);
}
-
lldb_private::ConstString
SymbolFileDWARFDebugMap::GetPluginNameStatic()
{
@@ -279,7 +274,6 @@ SymbolFileDWARFDebugMap::CreateInstance (ObjectFile* obj_file)
return new SymbolFileDWARFDebugMap (obj_file);
}
-
SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap (ObjectFile* ofile) :
SymbolFile(ofile),
m_flags(),
@@ -290,7 +284,6 @@ SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap (ObjectFile* ofile) :
{
}
-
SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap()
{
}
@@ -298,15 +291,6 @@ SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap()
void
SymbolFileDWARFDebugMap::InitializeObject()
{
- // Install our external AST source callbacks so we can complete Clang types.
- llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap (
- new ClangExternalASTSourceCallbacks (SymbolFileDWARFDebugMap::CompleteTagDecl,
- SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl,
- NULL,
- SymbolFileDWARFDebugMap::LayoutRecordType,
- this));
-
- GetClangASTContext().SetExternalSource (ast_source_ap);
}
void
@@ -517,7 +501,6 @@ SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo (CompileUnitInfo *comp_unit_inf
return NULL;
}
-
bool
SymbolFileDWARFDebugMap::GetFileSpecForSO (uint32_t oso_idx, FileSpec &file_spec)
{
@@ -532,8 +515,6 @@ SymbolFileDWARFDebugMap::GetFileSpecForSO (uint32_t oso_idx, FileSpec &file_spec
return false;
}
-
-
ObjectFile *
SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex (uint32_t oso_idx)
{
@@ -561,7 +542,6 @@ SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo (CompileUnitInfo *comp_unit
return NULL;
}
-
uint32_t
SymbolFileDWARFDebugMap::GetCompUnitInfoIndex (const CompileUnitInfo *comp_unit_info)
{
@@ -637,7 +617,6 @@ SymbolFileDWARFDebugMap::GetNumCompileUnits()
return m_compile_unit_infos.size();
}
-
CompUnitSP
SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx)
{
@@ -660,7 +639,8 @@ SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx)
NULL,
so_file_spec,
cu_id,
- eLanguageTypeUnknown));
+ eLanguageTypeUnknown,
+ false));
if (m_compile_unit_infos[cu_idx].compile_unit_sp)
{
@@ -687,7 +667,6 @@ SymbolFileDWARFDebugMap::GetCompUnitInfo (const SymbolContext& sc)
return NULL;
}
-
size_t
SymbolFileDWARFDebugMap::GetCompUnitInfosForModule (const lldb_private::Module *module, std::vector<CompileUnitInfo *>& cu_infos)
{
@@ -728,6 +707,15 @@ SymbolFileDWARFDebugMap::ParseCompileUnitLineTable (const SymbolContext& sc)
}
bool
+SymbolFileDWARFDebugMap::ParseCompileUnitDebugMacros (const SymbolContext& sc)
+{
+ SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+ if (oso_dwarf)
+ return oso_dwarf->ParseCompileUnitDebugMacros (sc);
+ return false;
+}
+
+bool
SymbolFileDWARFDebugMap::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
{
SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
@@ -754,7 +742,6 @@ SymbolFileDWARFDebugMap::ParseFunctionBlocks (const SymbolContext& sc)
return 0;
}
-
size_t
SymbolFileDWARFDebugMap::ParseTypes (const SymbolContext& sc)
{
@@ -764,7 +751,6 @@ SymbolFileDWARFDebugMap::ParseTypes (const SymbolContext& sc)
return 0;
}
-
size_t
SymbolFileDWARFDebugMap::ParseVariablesForContext (const SymbolContext& sc)
{
@@ -774,8 +760,6 @@ SymbolFileDWARFDebugMap::ParseVariablesForContext (const SymbolContext& sc)
return 0;
}
-
-
Type*
SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid)
{
@@ -787,10 +771,22 @@ SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid)
}
bool
-SymbolFileDWARFDebugMap::ResolveClangOpaqueTypeDefinition (ClangASTType& clang_type)
+SymbolFileDWARFDebugMap::CompleteType (CompilerType& compiler_type)
{
- // We have a struct/union/class/enum that needs to be fully resolved.
- return false;
+ bool success = false;
+ if (compiler_type)
+ {
+ ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+ if (oso_dwarf->HasForwardDeclForClangType (compiler_type))
+ {
+ oso_dwarf->CompleteType (compiler_type);
+ success = true;
+ return true;
+ }
+ return false;
+ });
+ }
+ return success;
}
uint32_t
@@ -834,7 +830,6 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext (const Address& exe_so_addr, uint3
return resolved_flags;
}
-
uint32_t
SymbolFileDWARFDebugMap::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
{
@@ -871,7 +866,7 @@ uint32_t
SymbolFileDWARFDebugMap::PrivateFindGlobalVariables
(
const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
const std::vector<uint32_t> &indexes, // Indexes into the symbol table that match "name"
uint32_t max_matches,
VariableList& variables
@@ -888,7 +883,7 @@ SymbolFileDWARFDebugMap::PrivateFindGlobalVariables
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
if (oso_dwarf)
{
- if (oso_dwarf->FindGlobalVariables(name, namespace_decl, true, max_matches, variables))
+ if (oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, true, max_matches, variables))
if (variables.GetSize() > max_matches)
break;
}
@@ -898,7 +893,11 @@ SymbolFileDWARFDebugMap::PrivateFindGlobalVariables
}
uint32_t
-SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
+SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
+ bool append,
+ uint32_t max_matches,
+ VariableList& variables)
{
// If we aren't appending the results to this list, then clear the list
@@ -913,7 +912,7 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const Cla
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
const uint32_t oso_matches = oso_dwarf->FindGlobalVariables (name,
- namespace_decl,
+ parent_decl_ctx,
true,
max_matches,
variables);
@@ -941,7 +940,6 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const Cla
return variables.GetSize() - original_size;
}
-
uint32_t
SymbolFileDWARFDebugMap::FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
{
@@ -983,7 +981,6 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const RegularExpression& regex, bo
return variables.GetSize() - original_size;
}
-
int
SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex (uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info)
{
@@ -998,7 +995,6 @@ SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex (uint32_t *symbol_idx_ptr
return 1;
}
-
int
SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID (user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info)
{
@@ -1013,7 +1009,6 @@ SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID (user_id_t *symbol_idx_ptr,
return 1;
}
-
SymbolFileDWARFDebugMap::CompileUnitInfo*
SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex (uint32_t symbol_idx, uint32_t *oso_idx_ptr)
{
@@ -1062,7 +1057,6 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID (user_id_t symbol_id,
return comp_unit_info;
}
-
static void
RemoveFunctionsWithModuleNotEqualTo (const ModuleSP &module_sp, SymbolContextList &sc_list, uint32_t start_idx)
{
@@ -1091,7 +1085,12 @@ RemoveFunctionsWithModuleNotEqualTo (const ModuleSP &module_sp, SymbolContextLis
}
uint32_t
-SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list)
+SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
+ uint32_t name_type_mask,
+ bool include_inlines,
+ bool append,
+ SymbolContextList& sc_list)
{
Timer scoped_timer (__PRETTY_FUNCTION__,
"SymbolFileDWARFDebugMap::FindFunctions (name = %s)",
@@ -1105,7 +1104,7 @@ SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNames
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
uint32_t sc_idx = sc_list.GetSize();
- if (oso_dwarf->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, true, sc_list))
+ if (oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask, include_inlines, true, sc_list))
{
RemoveFunctionsWithModuleNotEqualTo (m_obj_file->GetModule(), sc_list, sc_idx);
}
@@ -1115,7 +1114,6 @@ SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNames
return sc_list.GetSize() - initial_size;
}
-
uint32_t
SymbolFileDWARFDebugMap::FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)
{
@@ -1150,8 +1148,7 @@ SymbolFileDWARFDebugMap::GetTypes (SymbolContextScope *sc_scope,
Timer scoped_timer (__PRETTY_FUNCTION__,
"SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)",
type_mask);
-
-
+
uint32_t initial_size = type_list.GetSize();
SymbolFileDWARF *oso_dwarf = NULL;
if (sc_scope)
@@ -1177,7 +1174,6 @@ SymbolFileDWARFDebugMap::GetTypes (SymbolContextScope *sc_scope,
return type_list.GetSize() - initial_size;
}
-
TypeSP
SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx)
{
@@ -1189,8 +1185,6 @@ SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclC
return type_sp;
}
-
-
bool
SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso)
{
@@ -1210,7 +1204,7 @@ SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWAR
}
TypeSP
-SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die,
+SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die,
const ConstString &type_name,
bool must_be_implementation)
{
@@ -1280,10 +1274,10 @@ SymbolFileDWARFDebugMap::FindTypes
(
const SymbolContext& sc,
const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
- bool append,
+ const CompilerDeclContext *parent_decl_ctx,
+ bool append,
uint32_t max_matches,
- TypeList& types
+ TypeMap& types
)
{
if (!append)
@@ -1296,12 +1290,12 @@ SymbolFileDWARFDebugMap::FindTypes
{
oso_dwarf = GetSymbolFile (sc);
if (oso_dwarf)
- return oso_dwarf->FindTypes (sc, name, namespace_decl, append, max_matches, types);
+ return oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, types);
}
else
{
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- oso_dwarf->FindTypes (sc, name, namespace_decl, append, max_matches, types);
+ oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, types);
return false;
});
}
@@ -1320,24 +1314,24 @@ SymbolFileDWARFDebugMap::FindTypes
//}
-ClangNamespaceDecl
+CompilerDeclContext
SymbolFileDWARFDebugMap::FindNamespace (const lldb_private::SymbolContext& sc,
const lldb_private::ConstString &name,
- const ClangNamespaceDecl *parent_namespace_decl)
+ const CompilerDeclContext *parent_decl_ctx)
{
- ClangNamespaceDecl matching_namespace;
+ CompilerDeclContext matching_namespace;
SymbolFileDWARF *oso_dwarf;
if (sc.comp_unit)
{
oso_dwarf = GetSymbolFile (sc);
if (oso_dwarf)
- matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_namespace_decl);
+ matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_decl_ctx);
}
else
{
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_namespace_decl);
+ matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_decl_ctx);
return (bool)matching_namespace;
});
@@ -1401,7 +1395,6 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfo (SymbolFileDWARF *oso_dwarf)
return NULL;
}
-
void
SymbolFileDWARFDebugMap::SetCompileUnit (SymbolFileDWARF *oso_dwarf, const CompUnitSP &cu_sp)
{
@@ -1427,78 +1420,33 @@ SymbolFileDWARFDebugMap::SetCompileUnit (SymbolFileDWARF *oso_dwarf, const CompU
}
}
-
-void
-SymbolFileDWARFDebugMap::CompleteTagDecl (void *baton, clang::TagDecl *decl)
-{
- SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton;
- ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
- if (clang_type)
- {
- symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- if (oso_dwarf->HasForwardDeclForClangType (clang_type))
- {
- oso_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
- return true;
- }
- return false;
- });
- }
-}
-
-void
-SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl)
-{
- SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton;
- ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
- if (clang_type)
- {
- symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- if (oso_dwarf->HasForwardDeclForClangType (clang_type))
- {
- oso_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
- return true;
- }
- return false;
- });
- }
-}
-
-bool
-SymbolFileDWARFDebugMap::LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size,
- uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
-{
- SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton;
- bool laid_out = false;
- symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- return (laid_out = oso_dwarf->LayoutRecordType (record_decl, size, alignment, field_offsets, base_offsets, vbase_offsets));
- });
- return laid_out;
-}
-
-
-
-clang::DeclContext*
-SymbolFileDWARFDebugMap::GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid)
+CompilerDeclContext
+SymbolFileDWARFDebugMap::GetDeclContextForUID (lldb::user_id_t type_uid)
{
const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid);
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
if (oso_dwarf)
- return oso_dwarf->GetClangDeclContextContainingTypeUID (type_uid);
- return NULL;
+ return oso_dwarf->GetDeclContextForUID (type_uid);
+ return CompilerDeclContext();
}
-clang::DeclContext*
-SymbolFileDWARFDebugMap::GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid)
+CompilerDeclContext
+SymbolFileDWARFDebugMap::GetDeclContextContainingUID (lldb::user_id_t type_uid)
{
const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid);
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
if (oso_dwarf)
- return oso_dwarf->GetClangDeclContextForTypeUID (sc, type_uid);
- return NULL;
+ return oso_dwarf->GetDeclContextContainingUID (type_uid);
+ return CompilerDeclContext();
+}
+
+void
+SymbolFileDWARFDebugMap::ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx)
+{
+ ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+ oso_dwarf->ParseDeclsForContext (decl_ctx);
+ return true; // Keep iterating
+ });
}
bool
@@ -1613,7 +1561,6 @@ SymbolFileDWARFDebugMap::AddOSOARanges (SymbolFileDWARF* dwarf2Data, DWARFDebugA
const FileRangeMap::Entry* entry = file_range_map.GetEntryAtIndex(idx);
if (entry)
{
- printf ("[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", entry->GetRangeBase(), entry->GetRangeEnd());
debug_aranges->AppendRange(dwarf2Data->GetID(), entry->GetRangeBase(), entry->GetRangeEnd());
num_line_entries_added++;
}
@@ -1622,4 +1569,3 @@ SymbolFileDWARFDebugMap::AddOSOARanges (SymbolFileDWARF* dwarf2Data, DWARFDebugA
}
return num_line_entries_added;
}
-
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index ce0cfd7..1eb33c9 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -14,19 +14,14 @@
#include <vector>
#include <bitset>
-#include "clang/AST/CharUnits.h"
-
#include "lldb/Core/RangeMap.h"
#include "lldb/Symbol/SymbolFile.h"
#include "UniqueDWARFASTType.h"
class SymbolFileDWARF;
-class DWARFCompileUnit;
class DWARFDebugAranges;
-class DWARFDebugInfoEntry;
class DWARFDeclContext;
-class DebugMapModule;
class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile
{
@@ -57,7 +52,6 @@ public:
~SymbolFileDWARFDebugMap () override;
uint32_t CalculateAbilities () override;
-
void InitializeObject() override;
//------------------------------------------------------------------
@@ -69,6 +63,7 @@ public:
lldb::LanguageType ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc) override;
size_t ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc) override;
bool ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc) override;
+ bool ParseCompileUnitDebugMacros (const lldb_private::SymbolContext& sc) override;
bool ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files) override;
bool ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules) override;
size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc) override;
@@ -76,39 +71,26 @@ public:
size_t ParseVariablesForContext (const lldb_private::SymbolContext& sc) override;
lldb_private::Type* ResolveTypeUID (lldb::user_id_t type_uid) override;
- clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) override;
- clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) override;
- bool ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type) override;
+ lldb_private::CompilerDeclContext GetDeclContextForUID (lldb::user_id_t uid) override;
+ lldb_private::CompilerDeclContext GetDeclContextContainingUID (lldb::user_id_t uid) override;
+ void ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx) override;
+
+ bool CompleteType (lldb_private::CompilerType& compiler_type) override;
uint32_t ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc) override;
uint32_t ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list) override;
- uint32_t FindGlobalVariables (const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override;
+ uint32_t FindGlobalVariables (const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override;
uint32_t FindGlobalVariables (const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override;
- uint32_t FindFunctions (const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override;
+ uint32_t FindFunctions (const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override;
uint32_t FindFunctions (const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override;
- uint32_t FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types) override;
- lldb_private::ClangNamespaceDecl
+ uint32_t FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, lldb_private::TypeMap& types) override;
+ lldb_private::CompilerDeclContext
FindNamespace (const lldb_private::SymbolContext& sc,
const lldb_private::ConstString &name,
- const lldb_private::ClangNamespaceDecl *parent_namespace_decl) override;
+ const lldb_private::CompilerDeclContext *parent_decl_ctx) override;
size_t GetTypes (lldb_private::SymbolContextScope *sc_scope,
uint32_t type_mask,
lldb_private::TypeList &type_list) override;
-
- //------------------------------------------------------------------
- // ClangASTContext callbacks for external source lookups.
- //------------------------------------------------------------------
- static void
- CompleteTagDecl (void *baton, clang::TagDecl *);
-
- static void
- CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *);
-
- static bool LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -128,6 +110,7 @@ protected:
friend class DWARFCompileUnit;
friend class SymbolFileDWARF;
friend class DebugMapModule;
+ friend class DWARFASTParserClang;
struct OSOInfo
{
lldb::ModuleSP module_sp;
@@ -259,7 +242,7 @@ protected:
uint32_t
PrivateFindGlobalVariables (const lldb_private::ConstString &name,
- const lldb_private::ClangNamespaceDecl *namespace_decl,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
const std::vector<uint32_t> &name_symbol_indexes,
uint32_t max_matches,
lldb_private::VariableList& variables);
@@ -281,7 +264,7 @@ protected:
Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso);
lldb::TypeSP
- FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die,
+ FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die,
const lldb_private::ConstString &type_name,
bool must_be_implementation);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
new file mode 100644
index 0000000..326c397
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -0,0 +1,131 @@
+//===-- SymbolFileDWARFDwo.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileDWARFDwo.h"
+
+#include "lldb/Core/Section.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile, DWARFCompileUnit* dwarf_cu) :
+ SymbolFileDWARF(objfile.get()),
+ m_obj_file_sp(objfile),
+ m_base_dwarf_cu(dwarf_cu)
+{
+ SetID(((lldb::user_id_t)dwarf_cu->GetOffset())<<32);
+}
+
+void
+SymbolFileDWARFDwo::LoadSectionData (lldb::SectionType sect_type, DWARFDataExtractor& data)
+{
+ const SectionList* section_list = m_obj_file->GetSectionList(false /* update_module_section_list */);
+ if (section_list)
+ {
+ SectionSP section_sp (section_list->FindSectionByType(sect_type, true));
+ if (section_sp)
+ {
+ // See if we memory mapped the DWARF segment?
+ if (m_dwarf_data.GetByteSize())
+ {
+ data.SetData(m_dwarf_data, section_sp->GetOffset(), section_sp->GetFileSize());
+ return;
+ }
+
+ if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0)
+ return;
+
+ data.Clear();
+ }
+ }
+
+ SymbolFileDWARF::LoadSectionData(sect_type, data);
+}
+
+lldb::CompUnitSP
+SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
+{
+ assert(GetCompileUnit() == dwarf_cu && "SymbolFileDWARFDwo::ParseCompileUnit called with incompatible compile unit");
+ return GetBaseSymbolFile()->ParseCompileUnit(m_base_dwarf_cu, UINT32_MAX);
+}
+
+DWARFCompileUnit*
+SymbolFileDWARFDwo::GetCompileUnit()
+{
+ // Only dwo files with 1 compile unit is supported
+ if (GetNumCompileUnits() == 1)
+ return DebugInfo()->GetCompileUnitAtIndex(0);
+ else
+ return nullptr;
+}
+
+DWARFCompileUnit*
+SymbolFileDWARFDwo::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)
+{
+ return GetCompileUnit();
+}
+
+SymbolFileDWARF::DIEToTypePtr&
+SymbolFileDWARFDwo::GetDIEToType()
+{
+ return GetBaseSymbolFile()->GetDIEToType();
+}
+
+SymbolFileDWARF::DIEToVariableSP&
+SymbolFileDWARFDwo::GetDIEToVariable()
+{
+ return GetBaseSymbolFile()->GetDIEToVariable();
+}
+
+SymbolFileDWARF::DIEToClangType&
+SymbolFileDWARFDwo::GetForwardDeclDieToClangType()
+{
+ return GetBaseSymbolFile()->GetForwardDeclDieToClangType();
+}
+
+SymbolFileDWARF::ClangTypeToDIE&
+SymbolFileDWARFDwo::GetForwardDeclClangTypeToDie()
+{
+ return GetBaseSymbolFile()->GetForwardDeclClangTypeToDie();
+}
+
+UniqueDWARFASTTypeMap&
+SymbolFileDWARFDwo::GetUniqueDWARFASTTypeMap()
+{
+ return GetBaseSymbolFile()->GetUniqueDWARFASTTypeMap();
+}
+
+lldb::TypeSP
+SymbolFileDWARFDwo::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx)
+{
+ return GetBaseSymbolFile()->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
+}
+
+SymbolFileDWARF*
+SymbolFileDWARFDwo::GetBaseSymbolFile()
+{
+ return m_base_dwarf_cu->GetSymbolFileDWARF();
+}
+
+DWARFExpression::LocationListFormat
+SymbolFileDWARFDwo::GetLocationListFormat() const
+{
+ return DWARFExpression::SplitDwarfLocationList;
+}
+
+TypeSystem*
+SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language)
+{
+ return GetBaseSymbolFile()->GetTypeSystemForLanguage(language);
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
new file mode 100644
index 0000000..39ed650
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -0,0 +1,70 @@
+//===-- SymbolFileDWARFDwo.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_
+#define SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "SymbolFileDWARF.h"
+
+class SymbolFileDWARFDwo : public SymbolFileDWARF
+{
+public:
+ SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFCompileUnit* dwarf_cu);
+
+ ~SymbolFileDWARFDwo() override = default;
+
+ lldb::CompUnitSP
+ ParseCompileUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) override;
+
+ DWARFCompileUnit*
+ GetCompileUnit();
+
+ DWARFCompileUnit*
+ GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) override;
+
+ lldb_private::DWARFExpression::LocationListFormat
+ GetLocationListFormat() const override;
+
+ lldb_private::TypeSystem*
+ GetTypeSystemForLanguage(lldb::LanguageType language) override;
+
+protected:
+ void
+ LoadSectionData (lldb::SectionType sect_type, lldb_private::DWARFDataExtractor& data) override;
+
+ DIEToTypePtr&
+ GetDIEToType() override;
+
+ DIEToVariableSP&
+ GetDIEToVariable() override;
+
+ DIEToClangType&
+ GetForwardDeclDieToClangType() override;
+
+ ClangTypeToDIE&
+ GetForwardDeclClangTypeToDie() override;
+
+ UniqueDWARFASTTypeMap&
+ GetUniqueDWARFASTTypeMap() override;
+
+ lldb::TypeSP
+ FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx) override;
+
+ SymbolFileDWARF*
+ GetBaseSymbolFile();
+
+ lldb::ObjectFileSP m_obj_file_sp;
+ DWARFCompileUnit* m_base_dwarf_cu;
+};
+
+#endif // SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 94044c0..2ca407b 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -15,58 +15,51 @@
// Project includes
#include "lldb/Symbol/Declaration.h"
-#include "DWARFDebugInfoEntry.h"
-
bool
-UniqueDWARFASTTypeList::Find
-(
- SymbolFileDWARF *symfile,
- const DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
- const lldb_private::Declaration &decl,
- const int32_t byte_size,
- UniqueDWARFASTType &entry
-) const
+UniqueDWARFASTTypeList::Find (const DWARFDIE &die,
+ const lldb_private::Declaration &decl,
+ const int32_t byte_size,
+ UniqueDWARFASTType &entry) const
{
- collection::const_iterator pos, end = m_collection.end();
- for (pos = m_collection.begin(); pos != end; ++pos)
+ for (const UniqueDWARFASTType &udt : m_collection)
{
// Make sure the tags match
- if (pos->m_die->Tag() == die->Tag())
+ if (udt.m_die.Tag() == die.Tag())
{
// Validate byte sizes of both types only if both are valid.
- if (pos->m_byte_size < 0 || byte_size < 0 || pos->m_byte_size == byte_size)
+ if (udt.m_byte_size < 0 || byte_size < 0 || udt.m_byte_size == byte_size)
{
// Make sure the file and line match
- if (pos->m_declaration == decl)
+ if (udt.m_declaration == decl)
{
// The type has the same name, and was defined on the same
// file and line. Now verify all of the parent DIEs match.
- const DWARFDebugInfoEntry *parent_arg_die = die->GetParent();
- const DWARFDebugInfoEntry *parend_pos_die = pos->m_die->GetParent();
+ DWARFDIE parent_arg_die = die.GetParent();
+ DWARFDIE parent_pos_die = udt.m_die.GetParent();
bool match = true;
bool done = false;
- while (!done && match && parent_arg_die && parend_pos_die)
+ while (!done && match && parent_arg_die && parent_pos_die)
{
- if (parent_arg_die->Tag() == parend_pos_die->Tag())
+ const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
+ const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
+ if (parent_arg_tag == parent_pos_tag)
{
- const dw_tag_t tag = parent_arg_die->Tag();
- switch (tag)
+ switch (parent_arg_tag)
{
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_namespace:
{
- const char *parent_arg_die_name = parent_arg_die->GetName(symfile, cu);
+ const char *parent_arg_die_name = parent_arg_die.GetName();
if (parent_arg_die_name == NULL) // Anonymous (i.e. no-name) struct
{
match = false;
}
else
{
- const char *parent_pos_die_name = parend_pos_die->GetName(pos->m_symfile, pos->m_cu);
- if (parent_pos_die_name == NULL || strcmp (parent_arg_die_name, parent_pos_die_name))
+ const char *parent_pos_die_name = parent_pos_die.GetName();
+ if (parent_pos_die_name == NULL || ((parent_arg_die_name != parent_pos_die_name) && strcmp (parent_arg_die_name, parent_pos_die_name)))
match = false;
}
}
@@ -77,13 +70,13 @@ UniqueDWARFASTTypeList::Find
break;
}
}
- parent_arg_die = parent_arg_die->GetParent();
- parend_pos_die = parend_pos_die->GetParent();
+ parent_arg_die = parent_arg_die.GetParent();
+ parent_pos_die = parent_pos_die.GetParent();
}
if (match)
{
- entry = *pos;
+ entry = udt;
return true;
}
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
index c85e175..b7b18ef 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
@@ -19,10 +19,7 @@
// Project includes
#include "lldb/Symbol/Declaration.h"
-
-class DWARFCompileUnit;
-class DWARFDebugInfoEntry;
-class SymbolFileDWARF;
+#include "DWARFDIE.h"
class UniqueDWARFASTType
{
@@ -32,23 +29,17 @@ public:
//------------------------------------------------------------------
UniqueDWARFASTType () :
m_type_sp (),
- m_symfile (NULL),
- m_cu (NULL),
- m_die (NULL),
+ m_die (),
m_declaration (),
m_byte_size (-1) // Set to negative value to make sure we have a valid value
{
}
UniqueDWARFASTType (lldb::TypeSP &type_sp,
- SymbolFileDWARF *symfile,
- DWARFCompileUnit *cu,
- DWARFDebugInfoEntry *die,
+ const DWARFDIE &die,
const lldb_private::Declaration &decl,
int32_t byte_size) :
m_type_sp (type_sp),
- m_symfile (symfile),
- m_cu (cu),
m_die (die),
m_declaration (decl),
m_byte_size (byte_size)
@@ -57,8 +48,6 @@ public:
UniqueDWARFASTType (const UniqueDWARFASTType &rhs) :
m_type_sp (rhs.m_type_sp),
- m_symfile (rhs.m_symfile),
- m_cu (rhs.m_cu),
m_die (rhs.m_die),
m_declaration (rhs.m_declaration),
m_byte_size (rhs.m_byte_size)
@@ -75,8 +64,6 @@ public:
if (this != &rhs)
{
m_type_sp = rhs.m_type_sp;
- m_symfile = rhs.m_symfile;
- m_cu = rhs.m_cu;
m_die = rhs.m_die;
m_declaration = rhs.m_declaration;
m_byte_size = rhs.m_byte_size;
@@ -85,9 +72,7 @@ public:
}
lldb::TypeSP m_type_sp;
- SymbolFileDWARF *m_symfile;
- const DWARFCompileUnit *m_cu;
- const DWARFDebugInfoEntry *m_die;
+ DWARFDIE m_die;
lldb_private::Declaration m_declaration;
int32_t m_byte_size;
};
@@ -117,9 +102,7 @@ public:
}
bool
- Find (SymbolFileDWARF *symfile,
- const DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
+ Find (const DWARFDIE &die,
const lldb_private::Declaration &decl,
const int32_t byte_size,
UniqueDWARFASTType &entry) const;
@@ -149,10 +132,8 @@ public:
}
bool
- Find (const lldb_private::ConstString &name,
- SymbolFileDWARF *symfile,
- const DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
+ Find (const lldb_private::ConstString &name,
+ const DWARFDIE &die,
const lldb_private::Declaration &decl,
const int32_t byte_size,
UniqueDWARFASTType &entry) const
@@ -161,7 +142,7 @@ public:
collection::const_iterator pos = m_collection.find (unique_name_cstr);
if (pos != m_collection.end())
{
- return pos->second.Find (symfile, cu, die, decl, byte_size, entry);
+ return pos->second.Find (die, decl, byte_size, entry);
}
return false;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
index 09b9197..d3dd1ae 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -12,7 +12,6 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Timer.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -79,14 +78,6 @@ SymbolFileSymtab::~SymbolFileSymtab()
{
}
-ClangASTContext &
-SymbolFileSymtab::GetClangASTContext ()
-{
- ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext();
-
- return ast;
-}
-
uint32_t
SymbolFileSymtab::CalculateAbilities ()
{
@@ -115,6 +106,7 @@ SymbolFileSymtab::CalculateAbilities ()
if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny, m_code_indexes))
{
symtab->SortSymbolIndexesByValue(m_code_indexes, true);
+ abilities |= Functions;
}
if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData, m_data_indexes))
@@ -161,7 +153,7 @@ SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx)
{
const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
if (cu_symbol)
- cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown));
+ cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown, false));
}
return cu_sp;
}
@@ -261,6 +253,12 @@ SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc)
}
bool
+SymbolFileSymtab::ParseCompileUnitDebugMacros (const SymbolContext &sc)
+{
+ return false;
+}
+
+bool
SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
{
return false;
@@ -299,17 +297,11 @@ SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid)
}
bool
-SymbolFileSymtab::ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_opaque_type)
+SymbolFileSymtab::CompleteType (lldb_private::CompilerType& compiler_type)
{
return false;
}
-ClangNamespaceDecl
-SymbolFileSymtab::FindNamespace (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl)
-{
- return ClangNamespaceDecl();
-}
-
uint32_t
SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
{
@@ -326,63 +318,6 @@ SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve
return resolved_flags;
}
-uint32_t
-SymbolFileSymtab::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
-{
- return 0;
-}
-
-uint32_t
-SymbolFileSymtab::FindGlobalVariables(const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
-{
- return 0;
-}
-
-uint32_t
-SymbolFileSymtab::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
-{
- return 0;
-}
-
-uint32_t
-SymbolFileSymtab::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list)
-{
- Timer scoped_timer (__PRETTY_FUNCTION__,
- "SymbolFileSymtab::FindFunctions (name = '%s')",
- name.GetCString());
- // If we ever support finding STABS or COFF debug info symbols,
- // we will need to add support here. We are not trying to find symbols
- // here, just "lldb_private::Function" objects that come from complete
- // debug information. Any symbol queries should go through the symbol
- // table itself in the module's object file.
- return 0;
-}
-
-uint32_t
-SymbolFileSymtab::FindFunctions(const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)
-{
- Timer scoped_timer (__PRETTY_FUNCTION__,
- "SymbolFileSymtab::FindFunctions (regex = '%s')",
- regex.GetText());
- // If we ever support finding STABS or COFF debug info symbols,
- // we will need to add support here. We are not trying to find symbols
- // here, just "lldb_private::Function" objects that come from complete
- // debug information. Any symbol queries should go through the symbol
- // table itself in the module's object file.
- return 0;
-}
-
-uint32_t
-SymbolFileSymtab::FindTypes (const lldb_private::SymbolContext& sc,
- const lldb_private::ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
- bool append,
- uint32_t max_matches,
- lldb_private::TypeList& types)
-{
- return 0;
-}
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
index d606419..4648da4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
@@ -10,14 +10,26 @@
#ifndef liblldb_SymbolFileSymtab_h_
#define liblldb_SymbolFileSymtab_h_
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/Symtab.h"
-#include <vector>
class SymbolFileSymtab : public lldb_private::SymbolFile
{
public:
//------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ SymbolFileSymtab(lldb_private::ObjectFile* obj_file);
+
+ ~SymbolFileSymtab() override;
+
+ //------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
static void
@@ -35,94 +47,71 @@ public:
static lldb_private::SymbolFile*
CreateInstance (lldb_private::ObjectFile* obj_file);
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- SymbolFileSymtab(lldb_private::ObjectFile* obj_file);
-
- virtual
- ~SymbolFileSymtab();
-
- virtual uint32_t CalculateAbilities ();
+ uint32_t
+ CalculateAbilities() override;
//------------------------------------------------------------------
// Compile Unit function calls
//------------------------------------------------------------------
- virtual uint32_t
- GetNumCompileUnits();
-
- virtual lldb::CompUnitSP
- ParseCompileUnitAtIndex(uint32_t index);
-
- virtual lldb::LanguageType
- ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc);
-
- virtual size_t
- ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
-
- virtual bool
- ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
+ uint32_t
+ GetNumCompileUnits() override;
- virtual bool
- ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files);
-
- virtual bool
- ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules);
-
- virtual size_t
- ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
-
- virtual size_t
- ParseTypes (const lldb_private::SymbolContext& sc);
+ lldb::CompUnitSP
+ ParseCompileUnitAtIndex(uint32_t index) override;
- virtual size_t
- ParseVariablesForContext (const lldb_private::SymbolContext& sc);
+ lldb::LanguageType
+ ParseCompileUnitLanguage(const lldb_private::SymbolContext& sc) override;
- virtual lldb_private::Type*
- ResolveTypeUID(lldb::user_id_t type_uid);
+ size_t
+ ParseCompileUnitFunctions(const lldb_private::SymbolContext& sc) override;
- virtual bool
- ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type);
+ bool
+ ParseCompileUnitLineTable(const lldb_private::SymbolContext& sc) override;
- virtual uint32_t
- ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc);
+ bool
+ ParseCompileUnitDebugMacros(const lldb_private::SymbolContext& sc) override;
- virtual uint32_t
- ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list);
+ bool
+ ParseCompileUnitSupportFiles(const lldb_private::SymbolContext& sc,
+ lldb_private::FileSpecList &support_files) override;
+
+ bool
+ ParseImportedModules(const lldb_private::SymbolContext &sc,
+ std::vector<lldb_private::ConstString> &imported_modules) override;
- virtual uint32_t
- FindGlobalVariables(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+ size_t
+ ParseFunctionBlocks(const lldb_private::SymbolContext& sc) override;
- virtual uint32_t
- FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+ size_t
+ ParseTypes(const lldb_private::SymbolContext& sc) override;
- virtual uint32_t
- FindFunctions(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
+ size_t
+ ParseVariablesForContext(const lldb_private::SymbolContext& sc) override;
- virtual uint32_t
- FindFunctions(const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
+ lldb_private::Type*
+ ResolveTypeUID(lldb::user_id_t type_uid) override;
- virtual uint32_t
- FindTypes (const lldb_private::SymbolContext& sc,const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types);
+ bool
+ CompleteType(lldb_private::CompilerType& compiler_type) override;
- virtual size_t
- GetTypes (lldb_private::SymbolContextScope *sc_scope,
- uint32_t type_mask,
- lldb_private::TypeList &type_list);
+ uint32_t
+ ResolveSymbolContext(const lldb_private::Address& so_addr,
+ uint32_t resolve_scope,
+ lldb_private::SymbolContext& sc) override;
- virtual lldb_private::ClangNamespaceDecl
- FindNamespace (const lldb_private::SymbolContext& sc,
- const lldb_private::ConstString &name,
- const lldb_private::ClangNamespaceDecl *parent_namespace_decl);
+ size_t
+ GetTypes(lldb_private::SymbolContextScope *sc_scope,
+ uint32_t type_mask,
+ lldb_private::TypeList &type_list) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
protected:
typedef std::map<lldb_private::ConstString, lldb::TypeSP> TypeMap;
@@ -133,13 +122,9 @@ protected:
lldb_private::Symtab::IndexCollection m_data_indexes;
lldb_private::Symtab::NameToIndexMap m_objc_class_name_to_index;
TypeMap m_objc_class_types;
-
- lldb_private::ClangASTContext &
- GetClangASTContext ();
private:
DISALLOW_COPY_AND_ASSIGN (SymbolFileSymtab);
};
-
-#endif // liblldb_SymbolFileSymtab_h_
+#endif // liblldb_SymbolFileSymtab_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index a9f8f36..3cd1b68 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -142,17 +142,19 @@ SymbolVendorELF::CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::
static const SectionType g_sections[] =
{
- eSectionTypeDWARFDebugAranges,
- eSectionTypeDWARFDebugInfo,
eSectionTypeDWARFDebugAbbrev,
+ eSectionTypeDWARFDebugAddr,
+ eSectionTypeDWARFDebugAranges,
eSectionTypeDWARFDebugFrame,
+ eSectionTypeDWARFDebugInfo,
eSectionTypeDWARFDebugLine,
- eSectionTypeDWARFDebugStr,
eSectionTypeDWARFDebugLoc,
eSectionTypeDWARFDebugMacInfo,
eSectionTypeDWARFDebugPubNames,
eSectionTypeDWARFDebugPubTypes,
eSectionTypeDWARFDebugRanges,
+ eSectionTypeDWARFDebugStr,
+ eSectionTypeDWARFDebugStrOffsets,
eSectionTypeELFSymbolTable,
};
for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); ++idx)
diff --git a/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h b/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
index acd62b6..425ff9e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
@@ -1,4 +1,4 @@
-//===-- SymbolVendorELF.h ------------------------------------*- C++ -*-===//
+//===-- SymbolVendorELF.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,6 +10,10 @@
#ifndef liblldb_SymbolVendorELF_h_
#define liblldb_SymbolVendorELF_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Symbol/SymbolVendor.h"
@@ -17,6 +21,13 @@ class SymbolVendorELF : public lldb_private::SymbolVendor
{
public:
//------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ SymbolVendorELF (const lldb::ModuleSP &module_sp);
+
+ ~SymbolVendorELF() override;
+
+ //------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
static void
@@ -35,24 +46,16 @@ public:
CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm);
//------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- SymbolVendorELF (const lldb::ModuleSP &module_sp);
-
- virtual
- ~SymbolVendorELF();
-
- //------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
private:
DISALLOW_COPY_AND_ASSIGN (SymbolVendorELF);
};
-#endif // liblldb_SymbolVendorELF_h_
+#endif // liblldb_SymbolVendorELF_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index 8f5d926..eb5fec3 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -117,21 +117,13 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&
// cache the pc register number (in whatever register numbering this UnwindPlan uses) for
// quick reference during instruction parsing.
- uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
RegisterInfo pc_reg_info;
- if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info))
- pc_reg_num = pc_reg_info.kinds[unwind_plan.GetRegisterKind()];
- else
- pc_reg_num = LLDB_INVALID_REGNUM;
+ m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info);
// cache the return address register number (in whatever register numbering this UnwindPlan uses) for
// quick reference during instruction parsing.
- uint32_t ra_reg_num = LLDB_INVALID_REGNUM;
RegisterInfo ra_reg_info;
- if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info))
- ra_reg_num = ra_reg_info.kinds[unwind_plan.GetRegisterKind()];
- else
- ra_reg_num = LLDB_INVALID_REGNUM;
+ m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info);
for (size_t idx=0; idx<num_instructions; ++idx)
{
@@ -511,7 +503,8 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
log->PutCString(strm.GetData());
}
- SetRegisterValue (*reg_info, reg_value);
+ if (!instruction->IsInstructionConditional())
+ SetRegisterValue (*reg_info, reg_value);
switch (context.type)
{
@@ -573,18 +566,45 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
case EmulateInstruction::eContextPopRegisterOffStack:
{
- const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
- const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric];
- if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
+ if (!instruction->IsInstructionConditional())
{
- m_curr_row->SetRegisterLocationToSame (reg_num, /*must_replace*/ false);
- m_curr_row_modified = true;
+ const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
+ const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric];
+ if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
+ {
+ switch (context.info_type)
+ {
+ case EmulateInstruction::eInfoTypeAddress:
+ if (m_pushed_regs.find(reg_num) != m_pushed_regs.end() &&
+ context.info.address == m_pushed_regs[reg_num])
+ {
+ m_curr_row->SetRegisterLocationToSame(reg_num,
+ false /*must_replace*/);
+ m_curr_row_modified = true;
+ }
+ break;
+ case EmulateInstruction::eInfoTypeISA:
+ assert((generic_regnum == LLDB_REGNUM_GENERIC_PC ||
+ generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) &&
+ "eInfoTypeISA used for poping a register other the the PC/FLAGS");
+ if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS)
+ {
+ m_curr_row->SetRegisterLocationToSame(reg_num,
+ false /*must_replace*/);
+ m_curr_row_modified = true;
+ }
+ break;
+ default:
+ assert(false && "unhandled case, add code to handle this!");
+ break;
+ }
+ }
}
}
break;
case EmulateInstruction::eContextSetFramePointer:
- if (!m_fp_is_cfa)
+ if (!m_fp_is_cfa && !instruction->IsInstructionConditional())
{
m_fp_is_cfa = true;
m_cfa_reg_info = *reg_info;
@@ -599,7 +619,7 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
case EmulateInstruction::eContextAdjustStackPointer:
// If we have created a frame using the frame pointer, don't follow
// subsequent adjustments to the stack pointer.
- if (!m_fp_is_cfa)
+ if (!m_fp_is_cfa && !instruction->IsInstructionConditional())
{
m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(
m_curr_row->GetCFAValue().GetRegisterNumber(),
diff --git a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
index bf6d017..61d3ece 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
@@ -1,4 +1,4 @@
-//===-- UnwindAssemblyInstEmulation.h ----------------------------*- C++ -*-===//
+//===-- UnwindAssemblyInstEmulation.h ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,6 +10,10 @@
#ifndef liblldb_UnwindAssemblyInstEmulation_h_
#define liblldb_UnwindAssemblyInstEmulation_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/RegisterValue.h"
@@ -19,32 +23,28 @@
class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly
{
public:
+ ~UnwindAssemblyInstEmulation() override = default;
- virtual
- ~UnwindAssemblyInstEmulation ()
- {
- }
-
- virtual bool
- GetNonCallSiteUnwindPlanFromAssembly (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan& unwind_plan);
+ bool
+ GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan& unwind_plan) override;
- virtual bool
- AugmentUnwindPlanFromCallSite (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan& unwind_plan);
+ bool
+ AugmentUnwindPlanFromCallSite(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan& unwind_plan) override;
- virtual bool
- GetFastUnwindPlan (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan &unwind_plan);
+ bool
+ GetFastUnwindPlan(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan &unwind_plan) override;
// thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch).
- virtual bool
- FirstNonPrologueInsn (lldb_private::AddressRange& func,
- const lldb_private::ExecutionContext &exe_ctx,
- lldb_private::Address& first_non_prologue_insn);
+ bool
+ FirstNonPrologueInsn(lldb_private::AddressRange& func,
+ const lldb_private::ExecutionContext &exe_ctx,
+ lldb_private::Address& first_non_prologue_insn) override;
static lldb_private::UnwindAssembly *
CreateInstance (const lldb_private::ArchSpec &arch);
@@ -64,14 +64,36 @@ public:
static const char *
GetPluginDescriptionStatic();
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
private:
-
+ // Call CreateInstance to get an instance of this class
+ UnwindAssemblyInstEmulation(const lldb_private::ArchSpec &arch,
+ lldb_private::EmulateInstruction *inst_emulator) :
+ UnwindAssembly (arch),
+ m_inst_emulator_ap (inst_emulator),
+ m_range_ptr (NULL),
+ m_thread_ptr (NULL),
+ m_unwind_plan_ptr (NULL),
+ m_curr_row (),
+ m_cfa_reg_info (),
+ m_fp_is_cfa (false),
+ m_register_values (),
+ m_pushed_regs(),
+ m_curr_row_modified (false),
+ m_forward_branch_offset (0)
+ {
+ if (m_inst_emulator_ap.get())
+ {
+ m_inst_emulator_ap->SetBaton (this);
+ m_inst_emulator_ap->SetCallbacks (ReadMemory, WriteMemory, ReadRegister, WriteRegister);
+ }
+ }
+
static size_t
ReadMemory (lldb_private::EmulateInstruction *instruction,
void *baton,
@@ -101,7 +123,6 @@ private:
const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &reg_value);
-
// size_t
// ReadMemory (lldb_private::EmulateInstruction *instruction,
// const lldb_private::EmulateInstruction::Context &context,
@@ -127,29 +148,6 @@ private:
const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &reg_value);
- // Call CreateInstance to get an instance of this class
- UnwindAssemblyInstEmulation (const lldb_private::ArchSpec &arch,
- lldb_private::EmulateInstruction *inst_emulator) :
- UnwindAssembly (arch),
- m_inst_emulator_ap (inst_emulator),
- m_range_ptr (NULL),
- m_thread_ptr (NULL),
- m_unwind_plan_ptr (NULL),
- m_curr_row (),
- m_cfa_reg_info (),
- m_fp_is_cfa (false),
- m_register_values (),
- m_pushed_regs(),
- m_curr_row_modified (false),
- m_forward_branch_offset (0)
- {
- if (m_inst_emulator_ap.get())
- {
- m_inst_emulator_ap->SetBaton (this);
- m_inst_emulator_ap->SetCallbacks (ReadMemory, WriteMemory, ReadRegister, WriteRegister);
- }
- }
-
static uint64_t
MakeRegisterKindValuePair (const lldb_private::RegisterInfo &reg_info);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index 7e4c696..76f0b48 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -155,6 +155,7 @@ private:
bool mov_reg_to_local_stack_frame_p (int& regno, int& fp_offset);
bool ret_pattern_p ();
bool pop_rbp_pattern_p ();
+ bool leave_pattern_p ();
bool call_next_insn_pattern_p();
uint32_t extract_4 (uint8_t *b);
bool machine_regno_to_lldb_regno (int machine_regno, uint32_t& lldb_regno);
@@ -492,6 +493,14 @@ AssemblyParse_x86::pop_rbp_pattern_p ()
return (*p == 0x5d);
}
+// leave [0xc9]
+bool
+AssemblyParse_x86::leave_pattern_p ()
+{
+ uint8_t *p = m_cur_insn_bytes;
+ return (*p == 0xc9);
+}
+
// call $0 [0xe8 0x0 0x0 0x0 0x0]
bool
AssemblyParse_x86::call_next_insn_pattern_p ()
@@ -780,8 +789,7 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
if (machine_regno == (int)m_machine_fp_regnum)
{
- row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum,
- row->GetCFAValue().GetOffset());
+ row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
}
in_epilogue = true;
@@ -792,12 +800,35 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
// we need to add a new row of instructions.
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum)
{
- row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_sp_regnum,
- current_sp_bytes_offset_from_cfa);
+ row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa);
row_updated = true;
}
}
+ // The LEAVE instruction moves the value from rbp into rsp and pops
+ // a value off the stack into rbp (restoring the caller's rbp value).
+ // It is the opposite of ENTER, or 'push rbp, mov rsp rbp'.
+ else if (leave_pattern_p ())
+ {
+ // We're going to copy the value in rbp into rsp, so re-set the sp offset
+ // based on the CFAValue. Also, adjust it to recognize that we're popping
+ // the saved rbp value off the stack.
+ current_sp_bytes_offset_from_cfa = row->GetCFAValue().GetOffset();
+ current_sp_bytes_offset_from_cfa -= m_wordsize;
+ row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa);
+
+ // rbp is restored to the caller's value
+ saved_registers[m_machine_fp_regnum] = false;
+ row->RemoveRegisterInfo (m_lldb_fp_regnum);
+
+ // cfa is now in terms of rsp again.
+ row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
+ row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa);
+
+ in_epilogue = true;
+ row_updated = true;
+ }
+
else if (mov_reg_to_local_stack_frame_p (machine_regno, stack_offset)
&& nonvolatile_reg_p (machine_regno)
&& machine_regno_to_lldb_regno (machine_regno, lldb_regno)
@@ -1137,15 +1168,15 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
// The only case we care about is epilogue:
// [0x5d] pop %rbp/%ebp
// => [0xc3] ret
- if (pop_rbp_pattern_p ())
+ if (pop_rbp_pattern_p () || leave_pattern_p ())
{
if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes,
1, error) != static_cast<size_t>(-1)
&& ret_pattern_p ())
{
row->SetOffset (offset);
- row->GetCFAValue().SetIsRegisterPlusOffset (
- first_row->GetCFAValue().GetRegisterNumber(), m_wordsize);
+ row->GetCFAValue().SetIsRegisterPlusOffset (first_row->GetCFAValue().GetRegisterNumber(),
+ m_wordsize);
UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
unwind_plan.InsertRow (new_row);
diff --git a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
index 8a4fe7c..4d43a6e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
@@ -1,4 +1,4 @@
-//===-- UnwindAssembly-x86.h -------------------------------------*- C++ -*-===//
+//===-- UnwindAssembly-x86.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,42 +10,44 @@
#ifndef liblldb_UnwindAssembly_x86_h_
#define liblldb_UnwindAssembly_x86_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
#include "llvm-c/Disassembler.h"
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/UnwindAssembly.h"
class UnwindAssembly_x86 : public lldb_private::UnwindAssembly
{
public:
+ ~UnwindAssembly_x86() override;
- ~UnwindAssembly_x86 ();
+ bool
+ GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan& unwind_plan) override;
- virtual bool
- GetNonCallSiteUnwindPlanFromAssembly (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan& unwind_plan);
+ bool
+ AugmentUnwindPlanFromCallSite(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan& unwind_plan) override;
- virtual bool
- AugmentUnwindPlanFromCallSite (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan& unwind_plan);
-
- virtual bool
- GetFastUnwindPlan (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan &unwind_plan);
+ bool
+ GetFastUnwindPlan(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan &unwind_plan) override;
// thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch).
- virtual bool
- FirstNonPrologueInsn (lldb_private::AddressRange& func,
- const lldb_private::ExecutionContext &exe_ctx,
- lldb_private::Address& first_non_prologue_insn);
+ bool
+ FirstNonPrologueInsn(lldb_private::AddressRange& func,
+ const lldb_private::ExecutionContext &exe_ctx,
+ lldb_private::Address& first_non_prologue_insn) override;
static lldb_private::UnwindAssembly *
CreateInstance (const lldb_private::ArchSpec &arch);
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -61,11 +63,11 @@ public:
static const char *
GetPluginDescriptionStatic();
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
private:
UnwindAssembly_x86 (const lldb_private::ArchSpec &arch, int cpu);
@@ -74,5 +76,4 @@ private:
lldb_private::ArchSpec m_arch;
};
-
#endif // liblldb_UnwindAssembly_x86_h_
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ArmUnwindInfo.cpp b/contrib/llvm/tools/lldb/source/Symbol/ArmUnwindInfo.cpp
new file mode 100644
index 0000000..0d3e974
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Symbol/ArmUnwindInfo.cpp
@@ -0,0 +1,445 @@
+//===-- ArmUnwindInfo.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "Utility/ARM_DWARF_Registers.h"
+
+/*
+ * Unwind information reader and parser for the ARM exception handling ABI
+ *
+ * Implemented based on:
+ * Exception Handling ABI for the ARM Architecture
+ * Document number: ARM IHI 0038A (current through ABI r2.09)
+ * Date of Issue: 25th January 2007, reissued 30th November 2012
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
+ */
+
+using namespace lldb;
+using namespace lldb_private;
+
+// Converts a prel31 avlue to lldb::addr_t with sign extension
+static addr_t
+Prel31ToAddr(uint32_t prel31)
+{
+ addr_t res = prel31;
+ if (prel31 & (1<<30))
+ res |= 0xffffffff80000000ULL;
+ return res;
+}
+
+ArmUnwindInfo::ArmExidxEntry::ArmExidxEntry(uint32_t f, lldb::addr_t a, uint32_t d) :
+ file_address(f), address(a), data(d)
+{
+}
+
+bool
+ArmUnwindInfo::ArmExidxEntry::operator<(const ArmExidxEntry& other) const
+{
+ return address < other.address;
+}
+
+ArmUnwindInfo::ArmUnwindInfo(const ObjectFile& objfile,
+ SectionSP& arm_exidx,
+ SectionSP& arm_extab) :
+ m_byte_order(objfile.GetByteOrder()),
+ m_arm_exidx_sp(arm_exidx),
+ m_arm_extab_sp(arm_extab)
+{
+ objfile.ReadSectionData(arm_exidx.get(), m_arm_exidx_data);
+ objfile.ReadSectionData(arm_extab.get(), m_arm_extab_data);
+
+ addr_t exidx_base_addr = m_arm_exidx_sp->GetFileAddress();
+
+ offset_t offset = 0;
+ while (m_arm_exidx_data.ValidOffset(offset))
+ {
+ lldb::addr_t file_addr = exidx_base_addr + offset;
+ lldb::addr_t addr = exidx_base_addr +
+ (addr_t)offset +
+ Prel31ToAddr(m_arm_exidx_data.GetU32(&offset));
+ uint32_t data = m_arm_exidx_data.GetU32(&offset);
+ m_exidx_entries.emplace_back(file_addr, addr, data);
+ }
+
+ // Sort the entries in the exidx section. The entries should be sorted inside the section but
+ // some old compiler isn't sorted them.
+ std::sort(m_exidx_entries.begin(), m_exidx_entries.end());
+}
+
+ArmUnwindInfo::~ArmUnwindInfo()
+{
+}
+
+// Read a byte from the unwind instruction stream with the given offset.
+// Custom function is required because have to red in order of significance within their containing
+// word (most significant byte first) and in increasing word address order.
+uint8_t
+ArmUnwindInfo::GetByteAtOffset(const uint32_t* data, uint16_t offset) const
+{
+ uint32_t value = data[offset / 4];
+ if (m_byte_order != endian::InlHostByteOrder())
+ value = llvm::ByteSwap_32(value);
+ return (value >> ((3 - (offset % 4)) * 8)) & 0xff;
+}
+
+uint64_t
+ArmUnwindInfo::GetULEB128(const uint32_t* data, uint16_t& offset, uint16_t max_offset) const
+{
+ uint64_t result = 0;
+ uint8_t shift = 0;
+ while (offset < max_offset)
+ {
+ uint8_t byte = GetByteAtOffset(data, offset++);
+ result |= (byte & 0x7f) << shift;
+ if ((byte & 0x80) == 0)
+ break;
+ shift += 7;
+ }
+ return result;
+}
+
+bool
+ArmUnwindInfo::GetUnwindPlan(Target &target, const Address& addr, UnwindPlan& unwind_plan)
+{
+ const uint32_t* data = (const uint32_t*)GetExceptionHandlingTableEntry(addr);
+ if (data == nullptr)
+ return false; // No unwind information for the function
+
+ if (data[0] == 0x1)
+ return false; // EXIDX_CANTUNWIND
+
+ uint16_t byte_count = 0;
+ uint16_t byte_offset = 0;
+ if (data[0] & 0x80000000)
+ {
+ switch ((data[0] >> 24) & 0x0f)
+ {
+ case 0:
+ byte_count = 4;
+ byte_offset = 1;
+ break;
+ case 1:
+ case 2:
+ byte_count = 4 * ((data[0] >> 16) & 0xff) + 4;
+ byte_offset = 2;
+ break;
+ default:
+ // Unhandled personality routine index
+ return false;
+ }
+ }
+ else
+ {
+ byte_count = 4 * ((data[1] >> 24) & 0xff) + 8;
+ byte_offset = 5;
+ }
+
+ uint8_t vsp_reg = dwarf_sp;
+ int32_t vsp = 0;
+ std::vector<std::pair<uint32_t, int32_t>> register_offsets; // register -> (offset from vsp_reg)
+
+ while (byte_offset < byte_count)
+ {
+ uint8_t byte1 = GetByteAtOffset(data, byte_offset++);
+ if ((byte1&0xc0) == 0x00)
+ {
+ // 00xxxxxx
+ // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive
+ vsp += ((byte1 & 0x3f) << 2) + 4;
+ }
+ else if ((byte1&0xc0) == 0x40)
+ {
+ // 01xxxxxx
+ // vsp = vsp – (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive
+ vsp -= ((byte1 & 0x3f) << 2) + 4;
+ }
+ else if ((byte1&0xf0) == 0x80)
+ {
+ if (byte_offset >= byte_count)
+ return false;
+
+ uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
+ if (byte1 == 0x80 && byte2 == 0)
+ {
+ // 10000000 00000000
+ // Refuse to unwind (for example, out of a cleanup) (see remark a)
+ return false;
+ }
+ else
+ {
+ // 1000iiii iiiiiiii (i not all 0)
+ // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} (see remark b)
+ uint16_t regs = ((byte1&0x0f) << 8) | byte2;
+ for (uint8_t i = 0; i < 12; ++i)
+ {
+ if (regs & (1<<i))
+ {
+ register_offsets.emplace_back(dwarf_r4 + i, vsp);
+ vsp += 4;
+ }
+ }
+ }
+ }
+ else if ((byte1&0xff) == 0x9d)
+ {
+ // 10011101
+ // Reserved as prefix for ARM register to register moves
+ return false;
+ }
+ else if ((byte1&0xff) == 0x9f)
+ {
+ // 10011111
+ // Reserved as prefix for Intel Wireless MMX register to register moves
+ return false;
+ }
+ else if ((byte1&0xf0) == 0x90)
+ {
+ // 1001nnnn (nnnn != 13,15)
+ // Set vsp = r[nnnn]
+ vsp_reg = dwarf_r0 + (byte1&0x0f);
+ }
+ else if ((byte1&0xf8) == 0xa0)
+ {
+ // 10100nnn
+ // Pop r4-r[4+nnn]
+ uint8_t n = byte1&0x7;
+ for (uint8_t i = 0; i <= n; ++i)
+ {
+ register_offsets.emplace_back(dwarf_r4 + i, vsp);
+ vsp += 4;
+ }
+ }
+ else if ((byte1&0xf8) == 0xa8)
+ {
+ // 10101nnn
+ // Pop r4-r[4+nnn], r14
+ uint8_t n = byte1&0x7;
+ for (uint8_t i = 0; i <= n; ++i)
+ {
+ register_offsets.emplace_back(dwarf_r4 + i, vsp);
+ vsp += 4;
+ }
+
+ register_offsets.emplace_back(dwarf_lr, vsp);
+ vsp += 4;
+ }
+ else if ((byte1&0xff) == 0xb0)
+ {
+ // 10110000
+ // Finish (see remark c)
+ break;
+ }
+ else if ((byte1&0xff) == 0xb1)
+ {
+ if (byte_offset >= byte_count)
+ return false;
+
+ uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
+ if ((byte2&0xff) == 0x00)
+ {
+ // 10110001 00000000
+ // Spare (see remark f)
+ return false;
+ }
+ else if ((byte2&0xf0) == 0x00)
+ {
+ // 10110001 0000iiii (i not all 0)
+ // Pop integer registers under mask {r3, r2, r1, r0}
+ for (uint8_t i = 0; i < 4; ++i)
+ {
+ if (byte2 & (1<<i))
+ {
+ register_offsets.emplace_back(dwarf_r0 + i, vsp);
+ vsp += 4;
+ }
+ }
+ }
+ else
+ {
+ // 10110001 xxxxyyyy
+ // Spare (xxxx != 0000)
+ return false;
+ }
+ }
+ else if ((byte1&0xff) == 0xb2)
+ {
+ // 10110010 uleb128
+ // vsp = vsp + 0x204+ (uleb128 << 2)
+ uint64_t uleb128 = GetULEB128(data, byte_offset, byte_count);
+ vsp += 0x204 + (uleb128 << 2);
+ }
+ else if ((byte1&0xff) == 0xb3)
+ {
+ // 10110011 sssscccc
+ // Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDX (see remark d)
+ if (byte_offset >= byte_count)
+ return false;
+
+ uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
+ uint8_t s = (byte2&0xf0) >> 4;
+ uint8_t c = (byte2&0x0f) >> 0;
+ for (uint8_t i = 0; i <= c; ++i)
+ {
+ register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
+ vsp += 8;
+ }
+ vsp += 4;
+ }
+ else if ((byte1&0xfc) == 0xb4)
+ {
+ // 101101nn
+ // Spare (was Pop FPA)
+ return false;
+ }
+ else if ((byte1&0xf8) == 0xb8)
+ {
+ // 10111nnn
+ // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDX (see remark d)
+ uint8_t n = byte1&0x07;
+ for (uint8_t i = 0; i <= n; ++i)
+ {
+ register_offsets.emplace_back(dwarf_d8 + i, vsp);
+ vsp += 8;
+ }
+ vsp += 4;
+ }
+ else if ((byte1&0xf8) == 0xc0)
+ {
+ // 11000nnn (nnn != 6,7)
+ // Intel Wireless MMX pop wR[10]-wR[10+nnn]
+
+ // 11000110 sssscccc
+ // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] (see remark e)
+
+ // 11000111 00000000
+ // Spare
+
+ // 11000111 0000iiii
+ // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0}
+
+ // 11000111 xxxxyyyy
+ // Spare (xxxx != 0000)
+
+ return false;
+ }
+ else if ((byte1&0xff) == 0xc8)
+ {
+ // 11001000 sssscccc
+ // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved (as if) by FSTMFDD (see remarks d,e)
+ if (byte_offset >= byte_count)
+ return false;
+
+ uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
+ uint8_t s = (byte2&0xf0) >> 4;
+ uint8_t c = (byte2&0x0f) >> 0;
+ for (uint8_t i = 0; i <= c; ++i)
+ {
+ register_offsets.emplace_back(dwarf_d16 + s + i, vsp);
+ vsp += 8;
+ }
+ }
+ else if ((byte1&0xff) == 0xc9)
+ {
+ // 11001001 sssscccc
+ // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDD (see remark d)
+ if (byte_offset >= byte_count)
+ return false;
+
+ uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
+ uint8_t s = (byte2&0xf0) >> 4;
+ uint8_t c = (byte2&0x0f) >> 0;
+ for (uint8_t i = 0; i <= c; ++i)
+ {
+ register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
+ vsp += 8;
+ }
+ }
+ else if ((byte1&0xf8) == 0xc8)
+ {
+ // 11001yyy
+ // Spare (yyy != 000, 001)
+ return false;
+ }
+ else if ((byte1&0xf8) == 0xc0)
+ {
+ // 11010nnn
+ // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDD (see remark d)
+ uint8_t n = byte1&0x07;
+ for (uint8_t i = 0; i <= n; ++i)
+ {
+ register_offsets.emplace_back(dwarf_d8 + i, vsp);
+ vsp += 8;
+ }
+ }
+ else if ((byte1&0xc0) == 0xc0)
+ {
+ // 11xxxyyy Spare (xxx != 000, 001, 010)
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>();
+ row->SetOffset(0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(vsp_reg, vsp);
+
+ bool have_location_for_pc = false;
+ for (const auto& offset : register_offsets)
+ {
+ have_location_for_pc |= offset.first == dwarf_pc;
+ row->SetRegisterLocationToAtCFAPlusOffset(offset.first, offset.second - vsp, true);
+ }
+
+ if (!have_location_for_pc)
+ {
+ UnwindPlan::Row::RegisterLocation lr_location;
+ if (row->GetRegisterInfo(dwarf_lr, lr_location))
+ row->SetRegisterInfo(dwarf_pc, lr_location);
+ else
+ row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false);
+ }
+
+ unwind_plan.AppendRow(row);
+ unwind_plan.SetSourceName ("ARM.exidx unwind info");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ return true;
+}
+
+const uint8_t*
+ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address& addr)
+{
+ auto it = std::upper_bound(m_exidx_entries.begin(),
+ m_exidx_entries.end(),
+ ArmExidxEntry{0, addr.GetFileAddress(), 0});
+ if (it == m_exidx_entries.begin())
+ return nullptr;
+ --it;
+
+ if (it->data == 0x1)
+ return nullptr; // EXIDX_CANTUNWIND
+
+ if (it->data & 0x80000000)
+ return (const uint8_t*)&it->data;
+
+ addr_t data_file_addr = it->file_address + 4 + Prel31ToAddr(it->data);
+ return m_arm_extab_data.GetDataStart() + (data_file_addr - m_arm_extab_sp->GetFileAddress());
+}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Block.cpp b/contrib/llvm/tools/lldb/source/Symbol/Block.cpp
index 94fa166..dfe9217 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Block.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Block.cpp
@@ -546,27 +546,24 @@ Block::AppendVariables
return num_variables_added;
}
-clang::DeclContext *
-Block::GetClangDeclContext()
+CompilerDeclContext
+Block::GetDeclContext()
{
- SymbolContext sc;
-
- CalculateSymbolContext (&sc);
-
- if (!sc.module_sp)
- return nullptr;
-
- SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
-
- if (!sym_vendor)
- return nullptr;
-
- SymbolFile *sym_file = sym_vendor->GetSymbolFile();
+ ModuleSP module_sp = CalculateSymbolContextModule ();
+
+ if (module_sp)
+ {
+ SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
- if (!sym_file)
- return nullptr;
+ if (sym_vendor)
+ {
+ SymbolFile *sym_file = sym_vendor->GetSymbolFile();
- return sym_file->GetClangDeclContextForTypeUID (sc, m_uid);
+ if (sym_file)
+ return sym_file->GetDeclContextForUID (GetID());
+ }
+ }
+ return CompilerDeclContext();
}
void
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp
index 68bcde8..621bd16 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/ClangASTContext.cpp
@@ -13,6 +13,7 @@
// C++ Includes
#include <mutex> // std::once
#include <string>
+#include <vector>
// Other libraries and framework includes
@@ -39,8 +40,10 @@
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
+#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
@@ -58,19 +61,33 @@
#include <assert.h>
#endif
+#include "llvm/Support/Signals.h"
+
#include "lldb/Core/ArchSpec.h"
-#include "lldb/Core/dwarf.h"
#include "lldb/Core/Flags.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ThreadSafeDenseMap.h"
#include "lldb/Core/UniqueCStringMap.h"
-#include "lldb/Expression/ASTDumper.h"
+#include "Plugins/ExpressionParser/Clang/ClangUserExpression.h"
+#include "Plugins/ExpressionParser/Clang/ClangFunctionCaller.h"
+#include "Plugins/ExpressionParser/Clang/ClangUtilityFunction.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/VerifyDecl.h"
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
#include <stdio.h>
@@ -81,6 +98,17 @@ using namespace lldb_private;
using namespace llvm;
using namespace clang;
+namespace
+{
+ static inline bool ClangASTContextSupportsLanguage (lldb::LanguageType language)
+ {
+ return language == eLanguageTypeUnknown || // Clang is the default type system
+ Language::LanguageIsC (language) ||
+ Language::LanguageIsCPlusPlus (language) ||
+ Language::LanguageIsObjC (language);
+ }
+}
+
typedef lldb_private::ThreadSafeDenseMap<clang::ASTContext *, ClangASTContext*> ClangASTMap;
static ClangASTMap &
@@ -277,22 +305,23 @@ ParseLangArgs (LangOptions &Opts, InputKind IK, const char* triple)
}
-ClangASTContext::ClangASTContext (const char *target_triple) :
- m_target_triple(),
- m_ast_ap(),
- m_language_options_ap(),
- m_source_manager_ap(),
- m_diagnostics_engine_ap(),
- m_target_options_rp(),
- m_target_info_ap(),
- m_identifier_table_ap(),
- m_selector_table_ap(),
- m_builtins_ap(),
+ClangASTContext::ClangASTContext (const char *target_triple) :
+ TypeSystem (TypeSystem::eKindClang),
+ m_target_triple (),
+ m_ast_ap (),
+ m_language_options_ap (),
+ m_source_manager_ap (),
+ m_diagnostics_engine_ap (),
+ m_target_options_rp (),
+ m_target_info_ap (),
+ m_identifier_table_ap (),
+ m_selector_table_ap (),
+ m_builtins_ap (),
m_callback_tag_decl (nullptr),
m_callback_objc_decl (nullptr),
m_callback_baton (nullptr),
- m_pointer_byte_size (0)
-
+ m_pointer_byte_size (0),
+ m_ast_owned (false)
{
if (target_triple && target_triple[0])
SetTargetTriple (target_triple);
@@ -306,6 +335,8 @@ ClangASTContext::~ClangASTContext()
if (m_ast_ap.get())
{
GetASTMap().Erase(m_ast_ap.get());
+ if (!m_ast_owned)
+ m_ast_ap.release();
}
m_builtins_ap.reset();
@@ -319,6 +350,127 @@ ClangASTContext::~ClangASTContext()
m_ast_ap.reset();
}
+ConstString
+ClangASTContext::GetPluginNameStatic()
+{
+ return ConstString("clang");
+}
+
+ConstString
+ClangASTContext::GetPluginName()
+{
+ return ClangASTContext::GetPluginNameStatic();
+}
+
+uint32_t
+ClangASTContext::GetPluginVersion()
+{
+ return 1;
+}
+
+lldb::TypeSystemSP
+ClangASTContext::CreateInstance (lldb::LanguageType language,
+ lldb_private::Module *module,
+ Target *target)
+{
+ if (ClangASTContextSupportsLanguage(language))
+ {
+ ArchSpec arch;
+ if (module)
+ arch = module->GetArchitecture();
+ else if (target)
+ arch = target->GetArchitecture();
+
+ if (arch.IsValid())
+ {
+ ArchSpec fixed_arch = arch;
+ // LLVM wants this to be set to iOS or MacOSX; if we're working on
+ // a bare-boards type image, change the triple for llvm's benefit.
+ if (fixed_arch.GetTriple().getVendor() == llvm::Triple::Apple &&
+ fixed_arch.GetTriple().getOS() == llvm::Triple::UnknownOS)
+ {
+ if (fixed_arch.GetTriple().getArch() == llvm::Triple::arm ||
+ fixed_arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
+ fixed_arch.GetTriple().getArch() == llvm::Triple::thumb)
+ {
+ fixed_arch.GetTriple().setOS(llvm::Triple::IOS);
+ }
+ else
+ {
+ fixed_arch.GetTriple().setOS(llvm::Triple::MacOSX);
+ }
+ }
+
+ if (module)
+ {
+ std::shared_ptr<ClangASTContext> ast_sp(new ClangASTContext);
+ if (ast_sp)
+ {
+ ast_sp->SetArchitecture (fixed_arch);
+ }
+ return ast_sp;
+ }
+ else if (target && target->IsValid())
+ {
+ std::shared_ptr<ClangASTContextForExpressions> ast_sp(new ClangASTContextForExpressions(*target));
+ if (ast_sp)
+ {
+ ast_sp->SetArchitecture(fixed_arch);
+ ast_sp->m_scratch_ast_source_ap.reset (new ClangASTSource(target->shared_from_this()));
+ ast_sp->m_scratch_ast_source_ap->InstallASTContext(ast_sp->getASTContext());
+ llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(ast_sp->m_scratch_ast_source_ap->CreateProxy());
+ ast_sp->SetExternalSource(proxy_ast_source);
+ return ast_sp;
+ }
+ }
+ }
+ }
+ return lldb::TypeSystemSP();
+}
+
+void
+ClangASTContext::EnumerateSupportedLanguages(std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions)
+{
+ static std::vector<lldb::LanguageType> s_supported_languages_for_types({
+ lldb::eLanguageTypeC89,
+ lldb::eLanguageTypeC,
+ lldb::eLanguageTypeC11,
+ lldb::eLanguageTypeC_plus_plus,
+ lldb::eLanguageTypeC99,
+ lldb::eLanguageTypeObjC,
+ lldb::eLanguageTypeObjC_plus_plus,
+ lldb::eLanguageTypeC_plus_plus_03,
+ lldb::eLanguageTypeC_plus_plus_11,
+ lldb::eLanguageTypeC11,
+ lldb::eLanguageTypeC_plus_plus_14});
+
+ static std::vector<lldb::LanguageType> s_supported_languages_for_expressions({
+ lldb::eLanguageTypeC_plus_plus,
+ lldb::eLanguageTypeObjC_plus_plus,
+ lldb::eLanguageTypeC_plus_plus_03,
+ lldb::eLanguageTypeC_plus_plus_11,
+ lldb::eLanguageTypeC_plus_plus_14});
+
+ languages_for_types.insert(s_supported_languages_for_types.begin(), s_supported_languages_for_types.end());
+ languages_for_expressions.insert(s_supported_languages_for_expressions.begin(), s_supported_languages_for_expressions.end());
+}
+
+
+void
+ClangASTContext::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "clang base AST context plug-in",
+ CreateInstance,
+ EnumerateSupportedLanguages);
+}
+
+void
+ClangASTContext::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
void
ClangASTContext::Clear()
@@ -389,13 +541,23 @@ ClangASTContext::RemoveExternalSource ()
}
}
-
+void
+ClangASTContext::setASTContext(clang::ASTContext *ast_ctx)
+{
+ if (!m_ast_owned) {
+ m_ast_ap.release();
+ }
+ m_ast_owned = false;
+ m_ast_ap.reset(ast_ctx);
+ GetASTMap().Insert(ast_ctx, this);
+}
ASTContext *
ClangASTContext::getASTContext()
{
if (m_ast_ap.get() == nullptr)
{
+ m_ast_owned = true;
m_ast_ap.reset(new ASTContext (*getLanguageOptions(),
*getSourceManager(),
*getIdentifierTable(),
@@ -417,6 +579,13 @@ ClangASTContext::getASTContext()
}
GetASTMap().Insert(m_ast_ap.get(), this);
+
+ llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap (new ClangExternalASTSourceCallbacks (ClangASTContext::CompleteTagDecl,
+ ClangASTContext::CompleteObjCInterfaceDecl,
+ nullptr,
+ ClangASTContext::LayoutRecordType,
+ this));
+ SetExternalSource (ast_source_ap);
}
return m_ast_ap.get();
}
@@ -494,6 +663,14 @@ ClangASTContext::getDiagnosticsEngine()
return m_diagnostics_engine_ap.get();
}
+clang::MangleContext *
+ClangASTContext::getMangleContext()
+{
+ if (m_mangle_ctx_ap.get() == nullptr)
+ m_mangle_ctx_ap.reset (getASTContext()->createMangleContext());
+ return m_mangle_ctx_ap.get();
+}
+
class NullDiagnosticConsumer : public DiagnosticConsumer
{
public:
@@ -561,72 +738,74 @@ QualTypeMatchesBitSize(const uint64_t bit_size, ASTContext *ast, QualType qual_t
return true;
return false;
}
-ClangASTType
-ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (Encoding encoding, uint32_t bit_size)
+
+CompilerType
+ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (Encoding encoding, size_t bit_size)
{
return ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (getASTContext(), encoding, bit_size);
}
-ClangASTType
+CompilerType
ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (ASTContext *ast, Encoding encoding, uint32_t bit_size)
{
if (!ast)
- return ClangASTType();
-
+ return CompilerType();
switch (encoding)
{
case eEncodingInvalid:
if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy))
- return ClangASTType (ast, ast->VoidPtrTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->VoidPtrTy);
break;
case eEncodingUint:
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy))
- return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedCharTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy))
- return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedShortTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy))
- return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedIntTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy))
- return ClangASTType (ast, ast->UnsignedLongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedLongTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy))
- return ClangASTType (ast, ast->UnsignedLongLongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedLongLongTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty))
- return ClangASTType (ast, ast->UnsignedInt128Ty.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedInt128Ty);
break;
case eEncodingSint:
if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy))
- return ClangASTType (ast, ast->CharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->CharTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy))
- return ClangASTType (ast, ast->ShortTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->ShortTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy))
- return ClangASTType (ast, ast->IntTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->IntTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy))
- return ClangASTType (ast, ast->LongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->LongTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy))
- return ClangASTType (ast, ast->LongLongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->LongLongTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty))
- return ClangASTType (ast, ast->Int128Ty.getAsOpaquePtr());
+ return CompilerType (ast, ast->Int128Ty);
break;
case eEncodingIEEE754:
if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy))
- return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->FloatTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy))
- return ClangASTType (ast, ast->DoubleTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->DoubleTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy))
- return ClangASTType (ast, ast->LongDoubleTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->LongDoubleTy);
+ if (QualTypeMatchesBitSize (bit_size, ast, ast->HalfTy))
+ return CompilerType (ast, ast->HalfTy);
break;
case eEncodingVector:
// Sanity check that bit_size is a multiple of 8's.
if (bit_size && !(bit_size & 0x7u))
- return ClangASTType (ast, ast->getExtVectorType (ast->UnsignedCharTy, bit_size/8).getAsOpaquePtr());
+ return CompilerType (ast, ast->getExtVectorType (ast->UnsignedCharTy, bit_size/8));
break;
}
- return ClangASTType();
+ return CompilerType();
}
@@ -694,7 +873,7 @@ ClangASTContext::GetBasicTypeEnumeration (const ConstString &name)
return eBasicTypeInvalid;
}
-ClangASTType
+CompilerType
ClangASTContext::GetBasicType (ASTContext *ast, const ConstString &name)
{
if (ast)
@@ -702,7 +881,7 @@ ClangASTContext::GetBasicType (ASTContext *ast, const ConstString &name)
lldb::BasicType basic_type = ClangASTContext::GetBasicTypeEnumeration (name);
return ClangASTContext::GetBasicType (ast, basic_type);
}
- return ClangASTType();
+ return CompilerType();
}
uint32_t
@@ -713,18 +892,18 @@ ClangASTContext::GetPointerByteSize ()
return m_pointer_byte_size;
}
-ClangASTType
+CompilerType
ClangASTContext::GetBasicType (lldb::BasicType basic_type)
{
return GetBasicType (getASTContext(), basic_type);
}
-ClangASTType
+CompilerType
ClangASTContext::GetBasicType (ASTContext *ast, lldb::BasicType basic_type)
{
if (ast)
{
- clang_type_t clang_type = nullptr;
+ lldb::opaque_compiler_type_t clang_type = nullptr;
switch (basic_type)
{
@@ -827,13 +1006,13 @@ ClangASTContext::GetBasicType (ASTContext *ast, lldb::BasicType basic_type)
}
if (clang_type)
- return ClangASTType (ast, clang_type);
+ return CompilerType (GetASTContext(ast), clang_type);
}
- return ClangASTType();
+ return CompilerType();
}
-ClangASTType
+CompilerType
ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name, uint32_t dw_ate, uint32_t bit_size)
{
ASTContext *ast = getASTContext();
@@ -849,18 +1028,18 @@ ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name
case DW_ATE_address:
if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy))
- return ClangASTType (ast, ast->VoidPtrTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->VoidPtrTy);
break;
case DW_ATE_boolean:
if (QualTypeMatchesBitSize (bit_size, ast, ast->BoolTy))
- return ClangASTType (ast, ast->BoolTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->BoolTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy))
- return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedCharTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy))
- return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedShortTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy))
- return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedIntTy);
break;
case DW_ATE_lo_user:
@@ -869,40 +1048,42 @@ ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name
{
if (::strstr(type_name, "complex"))
{
- ClangASTType complex_int_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("int", DW_ATE_signed, bit_size/2);
- return ClangASTType (ast, ast->getComplexType (complex_int_clang_type.GetQualType()).getAsOpaquePtr());
+ CompilerType complex_int_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("int", DW_ATE_signed, bit_size/2);
+ return CompilerType (ast, ast->getComplexType (GetQualType(complex_int_clang_type)));
}
}
break;
case DW_ATE_complex_float:
if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatComplexTy))
- return ClangASTType (ast, ast->FloatComplexTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->FloatComplexTy);
else if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleComplexTy))
- return ClangASTType (ast, ast->DoubleComplexTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->DoubleComplexTy);
else if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleComplexTy))
- return ClangASTType (ast, ast->LongDoubleComplexTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->LongDoubleComplexTy);
else
{
- ClangASTType complex_float_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("float", DW_ATE_float, bit_size/2);
- return ClangASTType (ast, ast->getComplexType (complex_float_clang_type.GetQualType()).getAsOpaquePtr());
+ CompilerType complex_float_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("float", DW_ATE_float, bit_size/2);
+ return CompilerType (ast, ast->getComplexType (GetQualType(complex_float_clang_type)));
}
break;
case DW_ATE_float:
if (streq(type_name, "float") && QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy))
- return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->FloatTy);
if (streq(type_name, "double") && QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy))
- return ClangASTType (ast, ast->DoubleTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->DoubleTy);
if (streq(type_name, "long double") && QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy))
- return ClangASTType (ast, ast->LongDoubleTy.getAsOpaquePtr());
- // Fall back to not requring a name match
+ return CompilerType (ast, ast->LongDoubleTy);
+ // Fall back to not requiring a name match
if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy))
- return ClangASTType (ast, ast->FloatTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->FloatTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy))
- return ClangASTType (ast, ast->DoubleTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->DoubleTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy))
- return ClangASTType (ast, ast->LongDoubleTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->LongDoubleTy);
+ if (QualTypeMatchesBitSize (bit_size, ast, ast->HalfTy))
+ return CompilerType (ast, ast->HalfTy);
break;
case DW_ATE_signed:
@@ -911,57 +1092,57 @@ ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name
if (streq(type_name, "wchar_t") &&
QualTypeMatchesBitSize (bit_size, ast, ast->WCharTy) &&
(getTargetInfo() && TargetInfo::isTypeSigned (getTargetInfo()->getWCharType())))
- return ClangASTType (ast, ast->WCharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->WCharTy);
if (streq(type_name, "void") &&
QualTypeMatchesBitSize (bit_size, ast, ast->VoidTy))
- return ClangASTType (ast, ast->VoidTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->VoidTy);
if (strstr(type_name, "long long") &&
QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy))
- return ClangASTType (ast, ast->LongLongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->LongLongTy);
if (strstr(type_name, "long") &&
QualTypeMatchesBitSize (bit_size, ast, ast->LongTy))
- return ClangASTType (ast, ast->LongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->LongTy);
if (strstr(type_name, "short") &&
QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy))
- return ClangASTType (ast, ast->ShortTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->ShortTy);
if (strstr(type_name, "char"))
{
if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy))
- return ClangASTType (ast, ast->CharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->CharTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy))
- return ClangASTType (ast, ast->SignedCharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->SignedCharTy);
}
if (strstr(type_name, "int"))
{
if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy))
- return ClangASTType (ast, ast->IntTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->IntTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty))
- return ClangASTType (ast, ast->Int128Ty.getAsOpaquePtr());
+ return CompilerType (ast, ast->Int128Ty);
}
}
// We weren't able to match up a type name, just search by size
if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy))
- return ClangASTType (ast, ast->CharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->CharTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy))
- return ClangASTType (ast, ast->ShortTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->ShortTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy))
- return ClangASTType (ast, ast->IntTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->IntTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy))
- return ClangASTType (ast, ast->LongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->LongTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy))
- return ClangASTType (ast, ast->LongLongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->LongLongTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty))
- return ClangASTType (ast, ast->Int128Ty.getAsOpaquePtr());
+ return CompilerType (ast, ast->Int128Ty);
break;
case DW_ATE_signed_char:
if (ast->getLangOpts().CharIsSigned && type_name && streq(type_name, "char"))
{
if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy))
- return ClangASTType (ast, ast->CharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->CharTy);
}
if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy))
- return ClangASTType (ast, ast->SignedCharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->SignedCharTy);
break;
case DW_ATE_unsigned:
@@ -972,62 +1153,62 @@ ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name
if (QualTypeMatchesBitSize (bit_size, ast, ast->WCharTy))
{
if (!(getTargetInfo() && TargetInfo::isTypeSigned (getTargetInfo()->getWCharType())))
- return ClangASTType (ast, ast->WCharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->WCharTy);
}
}
if (strstr(type_name, "long long"))
{
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy))
- return ClangASTType (ast, ast->UnsignedLongLongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedLongLongTy);
}
else if (strstr(type_name, "long"))
{
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy))
- return ClangASTType (ast, ast->UnsignedLongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedLongTy);
}
else if (strstr(type_name, "short"))
{
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy))
- return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedShortTy);
}
else if (strstr(type_name, "char"))
{
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy))
- return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedCharTy);
}
else if (strstr(type_name, "int"))
{
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy))
- return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedIntTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty))
- return ClangASTType (ast, ast->UnsignedInt128Ty.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedInt128Ty);
}
}
// We weren't able to match up a type name, just search by size
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy))
- return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedCharTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy))
- return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedShortTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy))
- return ClangASTType (ast, ast->UnsignedIntTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedIntTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy))
- return ClangASTType (ast, ast->UnsignedLongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedLongTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy))
- return ClangASTType (ast, ast->UnsignedLongLongTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedLongLongTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty))
- return ClangASTType (ast, ast->UnsignedInt128Ty.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedInt128Ty);
break;
case DW_ATE_unsigned_char:
if (!ast->getLangOpts().CharIsSigned && type_name && streq(type_name, "char"))
{
if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy))
- return ClangASTType (ast, ast->CharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->CharTy);
}
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy))
- return ClangASTType (ast, ast->UnsignedCharTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedCharTy);
if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy))
- return ClangASTType (ast, ast->UnsignedShortTy.getAsOpaquePtr());
+ return CompilerType (ast, ast->UnsignedShortTy);
break;
case DW_ATE_imaginary_float:
@@ -1038,11 +1219,11 @@ ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name
{
if (streq(type_name, "char16_t"))
{
- return ClangASTType (ast, ast->Char16Ty.getAsOpaquePtr());
+ return CompilerType (ast, ast->Char16Ty);
}
else if (streq(type_name, "char32_t"))
{
- return ClangASTType (ast, ast->Char32Ty.getAsOpaquePtr());
+ return CompilerType (ast, ast->Char32Ty);
}
}
break;
@@ -1058,18 +1239,18 @@ ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name
{
Host::SystemLog (Host::eSystemLogError, "error: need to add support for DW_TAG_base_type encoded with DW_ATE = 0x%x, bit_size = %u\n", dw_ate, bit_size);
}
- return ClangASTType ();
+ return CompilerType ();
}
-ClangASTType
+CompilerType
ClangASTContext::GetUnknownAnyType(clang::ASTContext *ast)
{
if (ast)
- return ClangASTType (ast, ast->UnknownAnyTy.getAsOpaquePtr());
- return ClangASTType();
+ return CompilerType (ast, ast->UnknownAnyTy);
+ return CompilerType();
}
-ClangASTType
+CompilerType
ClangASTContext::GetCStringType (bool is_const)
{
ASTContext *ast = getASTContext();
@@ -1078,7 +1259,7 @@ ClangASTContext::GetCStringType (bool is_const)
if (is_const)
char_type.addConst();
- return ClangASTType (ast, ast->getPointerType(char_type).getAsOpaquePtr());
+ return CompilerType (ast, ast->getPointerType(char_type));
}
clang::DeclContext *
@@ -1087,23 +1268,6 @@ ClangASTContext::GetTranslationUnitDecl (clang::ASTContext *ast)
return ast->getTranslationUnitDecl();
}
-ClangASTType
-ClangASTContext::CopyType (ASTContext *dst_ast,
- ClangASTType src)
-{
- FileSystemOptions file_system_options;
- ASTContext *src_ast = src.GetASTContext();
- FileManager file_manager (file_system_options);
- ASTImporter importer(*dst_ast, file_manager,
- *src_ast, file_manager,
- false);
-
- QualType dst (importer.Import(src.GetQualType()));
-
- return ClangASTType (dst_ast, dst.getAsOpaquePtr());
-}
-
-
clang::Decl *
ClangASTContext::CopyDecl (ASTContext *dst_ast,
ASTContext *src_ast,
@@ -1119,19 +1283,19 @@ ClangASTContext::CopyDecl (ASTContext *dst_ast,
}
bool
-ClangASTContext::AreTypesSame (ClangASTType type1,
- ClangASTType type2,
+ClangASTContext::AreTypesSame (CompilerType type1,
+ CompilerType type2,
bool ignore_qualifiers)
{
- ASTContext *ast = type1.GetASTContext();
- if (ast != type2.GetASTContext())
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type1.GetTypeSystem());
+ if (!ast || ast != type2.GetTypeSystem())
return false;
if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType())
return true;
- QualType type1_qual = type1.GetQualType();
- QualType type2_qual = type2.GetQualType();
+ QualType type1_qual = GetQualType(type1);
+ QualType type2_qual = GetQualType(type2);
if (ignore_qualifiers)
{
@@ -1139,21 +1303,21 @@ ClangASTContext::AreTypesSame (ClangASTType type1,
type2_qual = type2_qual.getUnqualifiedType();
}
- return ast->hasSameType (type1_qual, type2_qual);
+ return ast->getASTContext()->hasSameType (type1_qual, type2_qual);
}
-ClangASTType
+CompilerType
ClangASTContext::GetTypeForDecl (clang::NamedDecl *decl)
{
if (clang::ObjCInterfaceDecl *interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl))
return GetTypeForDecl(interface_decl);
if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl))
return GetTypeForDecl(tag_decl);
- return ClangASTType();
+ return CompilerType();
}
-ClangASTType
+CompilerType
ClangASTContext::GetTypeForDecl (TagDecl *decl)
{
// No need to call the getASTContext() accessor (which can create the AST
@@ -1161,11 +1325,11 @@ ClangASTContext::GetTypeForDecl (TagDecl *decl)
// AST if our AST didn't already exist...
ASTContext *ast = &decl->getASTContext();
if (ast)
- return ClangASTType (ast, ast->getTagDeclType(decl).getAsOpaquePtr());
- return ClangASTType();
+ return CompilerType (ast, ast->getTagDeclType(decl));
+ return CompilerType();
}
-ClangASTType
+CompilerType
ClangASTContext::GetTypeForDecl (ObjCInterfaceDecl *decl)
{
// No need to call the getASTContext() accessor (which can create the AST
@@ -1173,13 +1337,13 @@ ClangASTContext::GetTypeForDecl (ObjCInterfaceDecl *decl)
// AST if our AST didn't already exist...
ASTContext *ast = &decl->getASTContext();
if (ast)
- return ClangASTType (ast, ast->getObjCInterfaceType(decl).getAsOpaquePtr());
- return ClangASTType();
+ return CompilerType (ast, ast->getObjCInterfaceType(decl));
+ return CompilerType();
}
#pragma mark Structure, Unions, Classes
-ClangASTType
+CompilerType
ClangASTContext::CreateRecordType (DeclContext *decl_ctx,
AccessType access_type,
const char *name,
@@ -1230,9 +1394,9 @@ ClangASTContext::CreateRecordType (DeclContext *decl_ctx,
if (decl_ctx)
decl_ctx->addDecl (decl);
- return ClangASTType(ast, ast->getTagDeclType(decl).getAsOpaquePtr());
+ return CompilerType(ast, ast->getTagDeclType(decl));
}
- return ClangASTType();
+ return CompilerType();
}
static TemplateParameterList *
@@ -1282,8 +1446,7 @@ CreateTemplateParameterList (ASTContext *ast,
TemplateParameterList *template_param_list = TemplateParameterList::Create (*ast,
SourceLocation(),
SourceLocation(),
- &template_param_decls.front(),
- template_param_decls.size(),
+ template_param_decls,
SourceLocation());
return template_param_list;
}
@@ -1434,16 +1597,16 @@ ClangASTContext::CreateClassTemplateSpecializationDecl (DeclContext *decl_ctx,
return class_template_specialization_decl;
}
-ClangASTType
+CompilerType
ClangASTContext::CreateClassTemplateSpecializationType (ClassTemplateSpecializationDecl *class_template_specialization_decl)
{
if (class_template_specialization_decl)
{
ASTContext *ast = getASTContext();
if (ast)
- return ClangASTType(ast, ast->getTagDeclType(class_template_specialization_decl).getAsOpaquePtr());
+ return CompilerType(ast, ast->getTagDeclType(class_template_specialization_decl));
}
- return ClangASTType();
+ return CompilerType();
}
static inline bool
@@ -1571,7 +1734,7 @@ ClangASTContext::RecordHasFields (const RecordDecl *record_decl)
#pragma mark Objective C Classes
-ClangASTType
+CompilerType
ClangASTContext::CreateObjCClass
(
const char *name,
@@ -1600,7 +1763,7 @@ ClangASTContext::CreateObjCClass
if (decl && metadata)
SetMetadata(ast, decl, *metadata);
- return ClangASTType (ast, ast->getObjCInterfaceType(decl));
+ return CompilerType (ast, ast->getObjCInterfaceType(decl));
}
static inline bool
@@ -1714,24 +1877,6 @@ ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *d
// BAD!!!
}
}
-
-
- if (namespace_decl)
- {
- // If we make it here, we are creating the anonymous namespace decl
- // for the first time, so we need to do the using directive magic
- // like SEMA does
- UsingDirectiveDecl* using_directive_decl = UsingDirectiveDecl::Create (*ast,
- decl_ctx,
- SourceLocation(),
- SourceLocation(),
- NestedNameSpecifierLoc(),
- SourceLocation(),
- namespace_decl,
- decl_ctx);
- using_directive_decl->setImplicit();
- decl_ctx->addDecl(using_directive_decl);
- }
}
#ifdef LLDB_CONFIGURATION_DEBUG
VerifyDecl(namespace_decl);
@@ -1740,12 +1885,104 @@ ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *d
}
+clang::BlockDecl *
+ClangASTContext::CreateBlockDeclaration (clang::DeclContext *ctx)
+{
+ if (ctx != nullptr)
+ {
+ clang::BlockDecl *decl = clang::BlockDecl::Create(*getASTContext(), ctx, clang::SourceLocation());
+ ctx->addDecl(decl);
+ return decl;
+ }
+ return nullptr;
+}
+
+clang::DeclContext *
+FindLCABetweenDecls(clang::DeclContext *left, clang::DeclContext *right, clang::DeclContext *root)
+{
+ if (root == nullptr)
+ return nullptr;
+
+ std::set<clang::DeclContext *> path_left;
+ for (clang::DeclContext *d = left; d != nullptr; d = d->getParent())
+ path_left.insert(d);
+
+ for (clang::DeclContext *d = right; d != nullptr; d = d->getParent())
+ if (path_left.find(d) != path_left.end())
+ return d;
+
+ return nullptr;
+}
+
+clang::UsingDirectiveDecl *
+ClangASTContext::CreateUsingDirectiveDeclaration (clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl)
+{
+ if (decl_ctx != nullptr && ns_decl != nullptr)
+ {
+ clang::TranslationUnitDecl *translation_unit = (clang::TranslationUnitDecl *)GetTranslationUnitDecl(getASTContext());
+ clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create(*getASTContext(),
+ decl_ctx,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ clang::NestedNameSpecifierLoc(),
+ clang::SourceLocation(),
+ ns_decl,
+ FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit));
+ decl_ctx->addDecl(using_decl);
+ return using_decl;
+ }
+ return nullptr;
+}
+
+clang::UsingDecl *
+ClangASTContext::CreateUsingDeclaration (clang::DeclContext *current_decl_ctx, clang::NamedDecl *target)
+{
+ if (current_decl_ctx != nullptr && target != nullptr)
+ {
+ clang::UsingDecl *using_decl = clang::UsingDecl::Create(*getASTContext(),
+ current_decl_ctx,
+ clang::SourceLocation(),
+ clang::NestedNameSpecifierLoc(),
+ clang::DeclarationNameInfo(),
+ false);
+ clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(*getASTContext(),
+ current_decl_ctx,
+ clang::SourceLocation(),
+ using_decl,
+ target);
+ using_decl->addShadowDecl(shadow_decl);
+ current_decl_ctx->addDecl(using_decl);
+ return using_decl;
+ }
+ return nullptr;
+}
+
+clang::VarDecl *
+ClangASTContext::CreateVariableDeclaration (clang::DeclContext *decl_context, const char *name, clang::QualType type)
+{
+ if (decl_context != nullptr)
+ {
+ clang::VarDecl *var_decl = clang::VarDecl::Create(*getASTContext(),
+ decl_context,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ name && name[0] ? &getASTContext()->Idents.getOwn(name) : nullptr,
+ type,
+ nullptr,
+ clang::SC_None);
+ var_decl->setAccess(clang::AS_public);
+ decl_context->addDecl(var_decl);
+ return var_decl;
+ }
+ return nullptr;
+}
+
#pragma mark Function Types
FunctionDecl *
ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx,
const char *name,
- const ClangASTType &function_clang_type,
+ const CompilerType &function_clang_type,
int storage,
bool is_inline)
{
@@ -1765,7 +2002,7 @@ ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx,
SourceLocation(),
SourceLocation(),
DeclarationName (&ast->Idents.get(name)),
- function_clang_type.GetQualType(),
+ GetQualType(function_clang_type),
nullptr,
(clang::StorageClass)storage,
is_inline,
@@ -1779,7 +2016,7 @@ ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx,
SourceLocation(),
SourceLocation(),
DeclarationName (),
- function_clang_type.GetQualType(),
+ GetQualType(function_clang_type),
nullptr,
(clang::StorageClass)storage,
is_inline,
@@ -1796,10 +2033,10 @@ ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx,
return func_decl;
}
-ClangASTType
+CompilerType
ClangASTContext::CreateFunctionType (ASTContext *ast,
- const ClangASTType& result_type,
- const ClangASTType *args,
+ const CompilerType& result_type,
+ const CompilerType *args,
unsigned num_args,
bool is_variadic,
unsigned type_quals)
@@ -1807,7 +2044,7 @@ ClangASTContext::CreateFunctionType (ASTContext *ast,
assert (ast != nullptr);
std::vector<QualType> qual_type_args;
for (unsigned i=0; i<num_args; ++i)
- qual_type_args.push_back (args[i].GetQualType());
+ qual_type_args.push_back (GetQualType(args[i]));
// TODO: Detect calling convention in DWARF?
FunctionProtoType::ExtProtoInfo proto_info;
@@ -1816,13 +2053,13 @@ ClangASTContext::CreateFunctionType (ASTContext *ast,
proto_info.TypeQuals = type_quals;
proto_info.RefQualifier = RQ_None;
- return ClangASTType (ast, ast->getFunctionType (result_type.GetQualType(),
+ return CompilerType (ast, ast->getFunctionType (GetQualType(result_type),
qual_type_args,
- proto_info).getAsOpaquePtr());
+ proto_info));
}
ParmVarDecl *
-ClangASTContext::CreateParameterDeclaration (const char *name, const ClangASTType &param_type, int storage)
+ClangASTContext::CreateParameterDeclaration (const char *name, const CompilerType &param_type, int storage)
{
ASTContext *ast = getASTContext();
assert (ast != nullptr);
@@ -1831,7 +2068,7 @@ ClangASTContext::CreateParameterDeclaration (const char *name, const ClangASTTyp
SourceLocation(),
SourceLocation(),
name && name[0] ? &ast->Idents.get(name) : nullptr,
- param_type.GetQualType(),
+ GetQualType(param_type),
nullptr,
(clang::StorageClass)storage,
nullptr);
@@ -1847,8 +2084,8 @@ ClangASTContext::SetFunctionParameters (FunctionDecl *function_decl, ParmVarDecl
#pragma mark Array Types
-ClangASTType
-ClangASTContext::CreateArrayType (const ClangASTType &element_type,
+CompilerType
+ClangASTContext::CreateArrayType (const CompilerType &element_type,
size_t element_count,
bool is_vector)
{
@@ -1859,7 +2096,7 @@ ClangASTContext::CreateArrayType (const ClangASTType &element_type,
if (is_vector)
{
- return ClangASTType (ast, ast->getExtVectorType(element_type.GetQualType(), element_count).getAsOpaquePtr());
+ return CompilerType (ast, ast->getExtVectorType(GetQualType(element_type), element_count));
}
else
{
@@ -1867,59 +2104,59 @@ ClangASTContext::CreateArrayType (const ClangASTType &element_type,
llvm::APInt ap_element_count (64, element_count);
if (element_count == 0)
{
- return ClangASTType (ast, ast->getIncompleteArrayType (element_type.GetQualType(),
+ return CompilerType (ast, ast->getIncompleteArrayType (GetQualType(element_type),
ArrayType::Normal,
- 0).getAsOpaquePtr());
+ 0));
}
else
{
- return ClangASTType (ast, ast->getConstantArrayType (element_type.GetQualType(),
+ return CompilerType (ast, ast->getConstantArrayType (GetQualType(element_type),
ap_element_count,
ArrayType::Normal,
- 0).getAsOpaquePtr());
+ 0));
}
}
}
- return ClangASTType();
+ return CompilerType();
}
-ClangASTType
+CompilerType
ClangASTContext::GetOrCreateStructForIdentifier (const ConstString &type_name,
- const std::initializer_list< std::pair < const char *, ClangASTType > >& type_fields,
+ const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields,
bool packed)
{
- ClangASTType type;
+ CompilerType type;
if ((type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid())
return type;
type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC);
- type.StartTagDeclarationDefinition();
+ StartTagDeclarationDefinition(type);
for (const auto& field : type_fields)
- type.AddFieldToRecordType(field.first, field.second, lldb::eAccessPublic, 0);
+ AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic, 0);
if (packed)
- type.SetIsPacked();
- type.CompleteTagDeclarationDefinition();
+ SetIsPacked(type);
+ CompleteTagDeclarationDefinition(type);
return type;
}
#pragma mark Enumeration Types
-ClangASTType
-ClangASTContext::CreateEnumerationType
+CompilerType
+ClangASTContext::CreateEnumerationType
(
- const char *name,
- DeclContext *decl_ctx,
- const Declaration &decl,
- const ClangASTType &integer_clang_type
-)
+ const char *name,
+ DeclContext *decl_ctx,
+ const Declaration &decl,
+ const CompilerType &integer_clang_type
+ )
{
// TODO: Do something intelligent with the Declaration object passed in
// like maybe filling in the SourceLocation with it...
ASTContext *ast = getASTContext();
-
+
// TODO: ask about these...
-// const bool IsScoped = false;
-// const bool IsFixed = false;
-
+ // const bool IsScoped = false;
+ // const bool IsFixed = false;
+
EnumDecl *enum_decl = EnumDecl::Create (*ast,
decl_ctx,
SourceLocation(),
@@ -1934,13 +2171,13 @@ ClangASTContext::CreateEnumerationType
if (enum_decl)
{
// TODO: check if we should be setting the promotion type too?
- enum_decl->setIntegerType(integer_clang_type.GetQualType());
+ enum_decl->setIntegerType(GetQualType(integer_clang_type));
enum_decl->setAccess(AS_public); // TODO respect what's in the debug info
- return ClangASTType (ast, ast->getTagDeclType(enum_decl).getAsOpaquePtr());
+ return CompilerType (ast, ast->getTagDeclType(enum_decl));
}
- return ClangASTType();
+ return CompilerType();
}
// Disable this for now since I can't seem to get a nicely formatted float
@@ -1950,7 +2187,7 @@ ClangASTContext::CreateEnumerationType
// so we can support remote targets. The code below also requires a patch to
// llvm::APInt.
//bool
-//ClangASTContext::ConvertFloatValueToString (ASTContext *ast, clang_type_t clang_type, const uint8_t* bytes, size_t byte_size, int apint_byte_order, std::string &float_str)
+//ClangASTContext::ConvertFloatValueToString (ASTContext *ast, lldb::opaque_compiler_type_t clang_type, const uint8_t* bytes, size_t byte_size, int apint_byte_order, std::string &float_str)
//{
// uint32_t count = 0;
// bool is_complex = false;
@@ -1984,7 +2221,7 @@ ClangASTContext::CreateEnumerationType
// return false;
//}
-ClangASTType
+CompilerType
ClangASTContext::GetIntTypeFromBitSize (clang::ASTContext *ast,
size_t bit_size, bool is_signed)
{
@@ -1993,74 +2230,207 @@ ClangASTContext::GetIntTypeFromBitSize (clang::ASTContext *ast,
if (is_signed)
{
if (bit_size == ast->getTypeSize(ast->SignedCharTy))
- return ClangASTType(ast, ast->SignedCharTy.getAsOpaquePtr());
+ return CompilerType(ast, ast->SignedCharTy);
if (bit_size == ast->getTypeSize(ast->ShortTy))
- return ClangASTType(ast, ast->ShortTy.getAsOpaquePtr());
+ return CompilerType(ast, ast->ShortTy);
if (bit_size == ast->getTypeSize(ast->IntTy))
- return ClangASTType(ast, ast->IntTy.getAsOpaquePtr());
+ return CompilerType(ast, ast->IntTy);
if (bit_size == ast->getTypeSize(ast->LongTy))
- return ClangASTType(ast, ast->LongTy.getAsOpaquePtr());
+ return CompilerType(ast, ast->LongTy);
if (bit_size == ast->getTypeSize(ast->LongLongTy))
- return ClangASTType(ast, ast->LongLongTy.getAsOpaquePtr());
+ return CompilerType(ast, ast->LongLongTy);
if (bit_size == ast->getTypeSize(ast->Int128Ty))
- return ClangASTType(ast, ast->Int128Ty.getAsOpaquePtr());
+ return CompilerType(ast, ast->Int128Ty);
}
else
{
if (bit_size == ast->getTypeSize(ast->UnsignedCharTy))
- return ClangASTType(ast, ast->UnsignedCharTy.getAsOpaquePtr());
+ return CompilerType(ast, ast->UnsignedCharTy);
if (bit_size == ast->getTypeSize(ast->UnsignedShortTy))
- return ClangASTType(ast, ast->UnsignedShortTy.getAsOpaquePtr());
+ return CompilerType(ast, ast->UnsignedShortTy);
if (bit_size == ast->getTypeSize(ast->UnsignedIntTy))
- return ClangASTType(ast, ast->UnsignedIntTy.getAsOpaquePtr());
+ return CompilerType(ast, ast->UnsignedIntTy);
if (bit_size == ast->getTypeSize(ast->UnsignedLongTy))
- return ClangASTType(ast, ast->UnsignedLongTy.getAsOpaquePtr());
+ return CompilerType(ast, ast->UnsignedLongTy);
if (bit_size == ast->getTypeSize(ast->UnsignedLongLongTy))
- return ClangASTType(ast, ast->UnsignedLongLongTy.getAsOpaquePtr());
+ return CompilerType(ast, ast->UnsignedLongLongTy);
if (bit_size == ast->getTypeSize(ast->UnsignedInt128Ty))
- return ClangASTType(ast, ast->UnsignedInt128Ty.getAsOpaquePtr());
+ return CompilerType(ast, ast->UnsignedInt128Ty);
}
}
- return ClangASTType();
+ return CompilerType();
}
-ClangASTType
+CompilerType
ClangASTContext::GetPointerSizedIntType (clang::ASTContext *ast, bool is_signed)
{
if (ast)
return GetIntTypeFromBitSize(ast, ast->getTypeSize(ast->VoidPtrTy), is_signed);
- return ClangASTType();
+ return CompilerType();
}
-ClangASTType
-ClangASTContext::GetFloatTypeFromBitSize (clang::ASTContext *ast,
- size_t bit_size)
+void
+ClangASTContext::DumpDeclContextHiearchy (clang::DeclContext *decl_ctx)
{
- if (ast)
+ if (decl_ctx)
+ {
+ DumpDeclContextHiearchy (decl_ctx->getParent());
+
+ clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl_ctx);
+ if (named_decl)
+ {
+ printf ("%20s: %s\n", decl_ctx->getDeclKindName(), named_decl->getDeclName().getAsString().c_str());
+ }
+ else
+ {
+ printf ("%20s\n", decl_ctx->getDeclKindName());
+ }
+ }
+}
+
+void
+ClangASTContext::DumpDeclHiearchy (clang::Decl *decl)
+{
+ if (decl == nullptr)
+ return;
+ DumpDeclContextHiearchy(decl->getDeclContext());
+
+ clang::RecordDecl *record_decl = llvm::dyn_cast<clang::RecordDecl>(decl);
+ if (record_decl)
{
- if (bit_size == ast->getTypeSize(ast->FloatTy))
- return ClangASTType(ast, ast->FloatTy.getAsOpaquePtr());
- else if (bit_size == ast->getTypeSize(ast->DoubleTy))
- return ClangASTType(ast, ast->DoubleTy.getAsOpaquePtr());
- else if (bit_size == ast->getTypeSize(ast->LongDoubleTy))
- return ClangASTType(ast, ast->LongDoubleTy.getAsOpaquePtr());
- else if (bit_size == ast->getTypeSize(ast->HalfTy))
- return ClangASTType(ast, ast->HalfTy.getAsOpaquePtr());
+ printf ("%20s: %s%s\n", decl->getDeclKindName(), record_decl->getDeclName().getAsString().c_str(), record_decl->isInjectedClassName() ? " (injected class name)" : "");
+
+ }
+ else
+ {
+ clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl);
+ if (named_decl)
+ {
+ printf ("%20s: %s\n", decl->getDeclKindName(), named_decl->getDeclName().getAsString().c_str());
+ }
+ else
+ {
+ printf ("%20s\n", decl->getDeclKindName());
+ }
}
- return ClangASTType();
}
bool
+ClangASTContext::DeclsAreEquivalent (clang::Decl *lhs_decl, clang::Decl *rhs_decl)
+{
+ if (lhs_decl && rhs_decl)
+ {
+ //----------------------------------------------------------------------
+ // Make sure the decl kinds match first
+ //----------------------------------------------------------------------
+ const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind();
+ const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind();
+
+ if (lhs_decl_kind == rhs_decl_kind)
+ {
+ //------------------------------------------------------------------
+ // Now check that the decl contexts kinds are all equivalent
+ // before we have to check any names of the decl contexts...
+ //------------------------------------------------------------------
+ clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext();
+ clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext();
+ if (lhs_decl_ctx && rhs_decl_ctx)
+ {
+ while (1)
+ {
+ if (lhs_decl_ctx && rhs_decl_ctx)
+ {
+ const clang::Decl::Kind lhs_decl_ctx_kind = lhs_decl_ctx->getDeclKind();
+ const clang::Decl::Kind rhs_decl_ctx_kind = rhs_decl_ctx->getDeclKind();
+ if (lhs_decl_ctx_kind == rhs_decl_ctx_kind)
+ {
+ lhs_decl_ctx = lhs_decl_ctx->getParent();
+ rhs_decl_ctx = rhs_decl_ctx->getParent();
+
+ if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr)
+ break;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+ }
+
+ //--------------------------------------------------------------
+ // Now make sure the name of the decls match
+ //--------------------------------------------------------------
+ clang::NamedDecl *lhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(lhs_decl);
+ clang::NamedDecl *rhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(rhs_decl);
+ if (lhs_named_decl && rhs_named_decl)
+ {
+ clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName();
+ clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName();
+ if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind())
+ {
+ if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
+ return false;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+
+ //--------------------------------------------------------------
+ // We know that the decl context kinds all match, so now we need
+ // to make sure the names match as well
+ //--------------------------------------------------------------
+ lhs_decl_ctx = lhs_decl->getDeclContext();
+ rhs_decl_ctx = rhs_decl->getDeclContext();
+ while (1)
+ {
+ switch (lhs_decl_ctx->getDeclKind())
+ {
+ case clang::Decl::TranslationUnit:
+ // We don't care about the translation unit names
+ return true;
+ default:
+ {
+ clang::NamedDecl *lhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx);
+ clang::NamedDecl *rhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx);
+ if (lhs_named_decl && rhs_named_decl)
+ {
+ clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName();
+ clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName();
+ if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind())
+ {
+ if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
+ return false;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+ }
+ break;
+
+ }
+ lhs_decl_ctx = lhs_decl_ctx->getParent();
+ rhs_decl_ctx = rhs_decl_ctx->getParent();
+ }
+ }
+ }
+ }
+ return false;
+}
+bool
ClangASTContext::GetCompleteDecl (clang::ASTContext *ast,
clang::Decl *decl)
{
@@ -2148,46 +2518,7499 @@ ClangASTContext::GetAsDeclContext (clang::ObjCMethodDecl *objc_method_decl)
return llvm::dyn_cast<clang::DeclContext>(objc_method_decl);
}
+bool
+ClangASTContext::SetTagTypeKind (clang::QualType tag_qual_type, int kind) const
+{
+ const clang::Type *clang_type = tag_qual_type.getTypePtr();
+ if (clang_type)
+ {
+ const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(clang_type);
+ if (tag_type)
+ {
+ clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl());
+ if (tag_decl)
+ {
+ tag_decl->setTagKind ((clang::TagDecl::TagKind)kind);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
bool
-ClangASTContext::GetClassMethodInfoForDeclContext (clang::DeclContext *decl_ctx,
- lldb::LanguageType &language,
- bool &is_instance_method,
- ConstString &language_object_name)
+ClangASTContext::SetDefaultAccessForRecordFields (clang::RecordDecl* record_decl,
+ int default_accessibility,
+ int *assigned_accessibilities,
+ size_t num_assigned_accessibilities)
{
- language_object_name.Clear();
- language = eLanguageTypeUnknown;
- is_instance_method = false;
+ if (record_decl)
+ {
+ uint32_t field_idx;
+ clang::RecordDecl::field_iterator field, field_end;
+ for (field = record_decl->field_begin(), field_end = record_decl->field_end(), field_idx = 0;
+ field != field_end;
+ ++field, ++field_idx)
+ {
+ // If no accessibility was assigned, assign the correct one
+ if (field_idx < num_assigned_accessibilities && assigned_accessibilities[field_idx] == clang::AS_none)
+ field->setAccess ((clang::AccessSpecifier)default_accessibility);
+ }
+ return true;
+ }
+ return false;
+}
- if (decl_ctx)
+clang::DeclContext *
+ClangASTContext::GetDeclContextForType (const CompilerType& type)
+{
+ return GetDeclContextForType(GetQualType(type));
+}
+
+clang::DeclContext *
+ClangASTContext::GetDeclContextForType (clang::QualType type)
+{
+ if (type.isNull())
+ return nullptr;
+
+ clang::QualType qual_type = type.getCanonicalType();
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::ObjCInterface: return llvm::cast<clang::ObjCObjectType>(qual_type.getTypePtr())->getInterface();
+ case clang::Type::ObjCObjectPointer: return GetDeclContextForType (llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType());
+ case clang::Type::Record: return llvm::cast<clang::RecordType>(qual_type)->getDecl();
+ case clang::Type::Enum: return llvm::cast<clang::EnumType>(qual_type)->getDecl();
+ case clang::Type::Typedef: return GetDeclContextForType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType());
+ case clang::Type::Auto: return GetDeclContextForType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType());
+ case clang::Type::Elaborated: return GetDeclContextForType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType());
+ case clang::Type::Paren: return GetDeclContextForType (llvm::cast<clang::ParenType>(qual_type)->desugar());
+ default:
+ break;
+ }
+ // No DeclContext in this type...
+ return nullptr;
+}
+
+static bool
+GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool allow_completion = true)
+{
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::ConstantArray:
+ case clang::Type::IncompleteArray:
+ case clang::Type::VariableArray:
+ {
+ const clang::ArrayType *array_type = llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr());
+
+ if (array_type)
+ return GetCompleteQualType (ast, array_type->getElementType(), allow_completion);
+ }
+ break;
+ case clang::Type::Record:
+ {
+ clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ if (cxx_record_decl->hasExternalLexicalStorage())
+ {
+ const bool is_complete = cxx_record_decl->isCompleteDefinition();
+ const bool fields_loaded = cxx_record_decl->hasLoadedFieldsFromExternalStorage();
+ if (is_complete && fields_loaded)
+ return true;
+
+ if (!allow_completion)
+ return false;
+
+ // Call the field_begin() accessor to for it to use the external source
+ // to load the fields...
+ clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
+ if (external_ast_source)
+ {
+ external_ast_source->CompleteType(cxx_record_decl);
+ if (cxx_record_decl->isCompleteDefinition())
+ {
+ cxx_record_decl->setHasLoadedFieldsFromExternalStorage (true);
+ cxx_record_decl->field_begin();
+ }
+ }
+ }
+ }
+ const clang::TagType *tag_type = llvm::cast<clang::TagType>(qual_type.getTypePtr());
+ return !tag_type->isIncompleteType();
+ }
+ break;
+
+ case clang::Type::Enum:
+ {
+ const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
+ if (tag_type)
+ {
+ clang::TagDecl *tag_decl = tag_type->getDecl();
+ if (tag_decl)
+ {
+ if (tag_decl->getDefinition())
+ return true;
+
+ if (!allow_completion)
+ return false;
+
+ if (tag_decl->hasExternalLexicalStorage())
+ {
+ if (ast)
+ {
+ clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
+ if (external_ast_source)
+ {
+ external_ast_source->CompleteType(tag_decl);
+ return !tag_type->isIncompleteType();
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ }
+ break;
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ // We currently can't complete objective C types through the newly added ASTContext
+ // because it only supports TagDecl objects right now...
+ if (class_interface_decl)
+ {
+ if (class_interface_decl->getDefinition())
+ return true;
+
+ if (!allow_completion)
+ return false;
+
+ if (class_interface_decl->hasExternalLexicalStorage())
+ {
+ if (ast)
+ {
+ clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
+ if (external_ast_source)
+ {
+ external_ast_source->CompleteType (class_interface_decl);
+ return !objc_class_type->isIncompleteType();
+ }
+ }
+ }
+ return false;
+ }
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ return GetCompleteQualType (ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType(), allow_completion);
+
+ case clang::Type::Auto:
+ return GetCompleteQualType (ast, llvm::cast<clang::AutoType>(qual_type)->getDeducedType(), allow_completion);
+
+ case clang::Type::Elaborated:
+ return GetCompleteQualType (ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(), allow_completion);
+
+ case clang::Type::Paren:
+ return GetCompleteQualType (ast, llvm::cast<clang::ParenType>(qual_type)->desugar(), allow_completion);
+
+ case clang::Type::Attributed:
+ return GetCompleteQualType (ast, llvm::cast<clang::AttributedType>(qual_type)->getModifiedType(), allow_completion);
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static clang::ObjCIvarDecl::AccessControl
+ConvertAccessTypeToObjCIvarAccessControl (AccessType access)
+{
+ switch (access)
+ {
+ case eAccessNone: return clang::ObjCIvarDecl::None;
+ case eAccessPublic: return clang::ObjCIvarDecl::Public;
+ case eAccessPrivate: return clang::ObjCIvarDecl::Private;
+ case eAccessProtected: return clang::ObjCIvarDecl::Protected;
+ case eAccessPackage: return clang::ObjCIvarDecl::Package;
+ }
+ return clang::ObjCIvarDecl::None;
+}
+
+
+//----------------------------------------------------------------------
+// Tests
+//----------------------------------------------------------------------
+
+bool
+ClangASTContext::IsAggregateType (lldb::opaque_compiler_type_t type)
+{
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::IncompleteArray:
+ case clang::Type::VariableArray:
+ case clang::Type::ConstantArray:
+ case clang::Type::ExtVector:
+ case clang::Type::Vector:
+ case clang::Type::Record:
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ return true;
+ case clang::Type::Auto:
+ return IsAggregateType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr());
+ case clang::Type::Elaborated:
+ return IsAggregateType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr());
+ case clang::Type::Typedef:
+ return IsAggregateType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr());
+ case clang::Type::Paren:
+ return IsAggregateType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr());
+ default:
+ break;
+ }
+ // The clang type does have a value
+ return false;
+}
+
+bool
+ClangASTContext::IsAnonymousType (lldb::opaque_compiler_type_t type)
+{
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ {
+ if (const clang::RecordType *record_type = llvm::dyn_cast_or_null<clang::RecordType>(qual_type.getTypePtrOrNull()))
+ {
+ if (const clang::RecordDecl *record_decl = record_type->getDecl())
+ {
+ return record_decl->isAnonymousStructOrUnion();
+ }
+ }
+ break;
+ }
+ case clang::Type::Auto:
+ return IsAnonymousType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr());
+ case clang::Type::Elaborated:
+ return IsAnonymousType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr());
+ case clang::Type::Typedef:
+ return IsAnonymousType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr());
+ case clang::Type::Paren:
+ return IsAnonymousType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr());
+ default:
+ break;
+ }
+ // The clang type does have a value
+ return false;
+}
+
+bool
+ClangASTContext::IsArrayType (lldb::opaque_compiler_type_t type,
+ CompilerType *element_type_ptr,
+ uint64_t *size,
+ bool *is_incomplete)
+{
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ default:
+ break;
+
+ case clang::Type::ConstantArray:
+ if (element_type_ptr)
+ element_type_ptr->SetCompilerType (getASTContext(), llvm::cast<clang::ConstantArrayType>(qual_type)->getElementType());
+ if (size)
+ *size = llvm::cast<clang::ConstantArrayType>(qual_type)->getSize().getLimitedValue(ULLONG_MAX);
+ if (is_incomplete)
+ *is_incomplete = false;
+ return true;
+
+ case clang::Type::IncompleteArray:
+ if (element_type_ptr)
+ element_type_ptr->SetCompilerType (getASTContext(), llvm::cast<clang::IncompleteArrayType>(qual_type)->getElementType());
+ if (size)
+ *size = 0;
+ if (is_incomplete)
+ *is_incomplete = true;
+ return true;
+
+ case clang::Type::VariableArray:
+ if (element_type_ptr)
+ element_type_ptr->SetCompilerType (getASTContext(), llvm::cast<clang::VariableArrayType>(qual_type)->getElementType());
+ if (size)
+ *size = 0;
+ if (is_incomplete)
+ *is_incomplete = false;
+ return true;
+
+ case clang::Type::DependentSizedArray:
+ if (element_type_ptr)
+ element_type_ptr->SetCompilerType (getASTContext(), llvm::cast<clang::DependentSizedArrayType>(qual_type)->getElementType());
+ if (size)
+ *size = 0;
+ if (is_incomplete)
+ *is_incomplete = false;
+ return true;
+
+ case clang::Type::Typedef:
+ return IsArrayType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(),
+ element_type_ptr,
+ size,
+ is_incomplete);
+ case clang::Type::Auto:
+ return IsArrayType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(),
+ element_type_ptr,
+ size,
+ is_incomplete);
+ case clang::Type::Elaborated:
+ return IsArrayType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(),
+ element_type_ptr,
+ size,
+ is_incomplete);
+ case clang::Type::Paren:
+ return IsArrayType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
+ element_type_ptr,
+ size,
+ is_incomplete);
+ }
+ if (element_type_ptr)
+ element_type_ptr->Clear();
+ if (size)
+ *size = 0;
+ if (is_incomplete)
+ *is_incomplete = false;
+ return false;
+}
+
+bool
+ClangASTContext::IsVectorType (lldb::opaque_compiler_type_t type,
+ CompilerType *element_type,
+ uint64_t *size)
+{
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Vector:
+ {
+ const clang::VectorType *vector_type = qual_type->getAs<clang::VectorType>();
+ if (vector_type)
+ {
+ if (size)
+ *size = vector_type->getNumElements();
+ if (element_type)
+ *element_type = CompilerType(getASTContext(), vector_type->getElementType());
+ }
+ return true;
+ }
+ break;
+ case clang::Type::ExtVector:
+ {
+ const clang::ExtVectorType *ext_vector_type = qual_type->getAs<clang::ExtVectorType>();
+ if (ext_vector_type)
+ {
+ if (size)
+ *size = ext_vector_type->getNumElements();
+ if (element_type)
+ *element_type = CompilerType(getASTContext(), ext_vector_type->getElementType());
+ }
+ return true;
+ }
+ default:
+ break;
+ }
+ return false;
+}
+
+bool
+ClangASTContext::IsRuntimeGeneratedType (lldb::opaque_compiler_type_t type)
+{
+ clang::DeclContext* decl_ctx = ClangASTContext::GetASTContext(getASTContext())->GetDeclContextForType(GetQualType(type));
+ if (!decl_ctx)
+ return false;
+
+ if (!llvm::isa<clang::ObjCInterfaceDecl>(decl_ctx))
+ return false;
+
+ clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
+
+ ClangASTMetadata* ast_metadata = ClangASTContext::GetMetadata(getASTContext(), result_iface_decl);
+ if (!ast_metadata)
+ return false;
+ return (ast_metadata->GetISAPtr() != 0);
+}
+
+bool
+ClangASTContext::IsCharType (lldb::opaque_compiler_type_t type)
+{
+ return GetQualType(type).getUnqualifiedType()->isCharType();
+}
+
+
+bool
+ClangASTContext::IsCompleteType (lldb::opaque_compiler_type_t type)
+{
+ const bool allow_completion = false;
+ return GetCompleteQualType (getASTContext(), GetQualType(type), allow_completion);
+}
+
+bool
+ClangASTContext::IsConst(lldb::opaque_compiler_type_t type)
+{
+ return GetQualType(type).isConstQualified();
+}
+
+bool
+ClangASTContext::IsCStringType (lldb::opaque_compiler_type_t type, uint32_t &length)
+{
+ CompilerType pointee_or_element_clang_type;
+ length = 0;
+ Flags type_flags (GetTypeInfo (type, &pointee_or_element_clang_type));
+
+ if (!pointee_or_element_clang_type.IsValid())
+ return false;
+
+ if (type_flags.AnySet (eTypeIsArray | eTypeIsPointer))
+ {
+ if (pointee_or_element_clang_type.IsCharType())
+ {
+ if (type_flags.Test (eTypeIsArray))
+ {
+ // We know the size of the array and it could be a C string
+ // since it is an array of characters
+ length = llvm::cast<clang::ConstantArrayType>(GetCanonicalQualType(type).getTypePtr())->getSize().getLimitedValue();
+ }
+ return true;
+
+ }
+ }
+ return false;
+}
+
+bool
+ClangASTContext::IsFunctionType (lldb::opaque_compiler_type_t type, bool *is_variadic_ptr)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ if (qual_type->isFunctionType())
+ {
+ if (is_variadic_ptr)
+ {
+ const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
+ if (function_proto_type)
+ *is_variadic_ptr = function_proto_type->isVariadic();
+ else
+ *is_variadic_ptr = false;
+ }
+ return true;
+ }
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ default:
+ break;
+ case clang::Type::Typedef:
+ return IsFunctionType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), nullptr);
+ case clang::Type::Auto:
+ return IsFunctionType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), nullptr);
+ case clang::Type::Elaborated:
+ return IsFunctionType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), nullptr);
+ case clang::Type::Paren:
+ return IsFunctionType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), nullptr);
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ {
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+ if (reference_type)
+ return IsFunctionType(reference_type->getPointeeType().getAsOpaquePtr(), nullptr);
+ }
+ break;
+ }
+ }
+ return false;
+}
+
+// Used to detect "Homogeneous Floating-point Aggregates"
+uint32_t
+ClangASTContext::IsHomogeneousAggregate (lldb::opaque_compiler_type_t type, CompilerType* base_type_ptr)
+{
+ if (!type)
+ return 0;
+
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType (type))
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ if (cxx_record_decl->getNumBases() ||
+ cxx_record_decl->isDynamicClass())
+ return 0;
+ }
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ if (record_type)
+ {
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ if (record_decl)
+ {
+ // We are looking for a structure that contains only floating point types
+ clang::RecordDecl::field_iterator field_pos, field_end = record_decl->field_end();
+ uint32_t num_fields = 0;
+ bool is_hva = false;
+ bool is_hfa = false;
+ clang::QualType base_qual_type;
+ for (field_pos = record_decl->field_begin(); field_pos != field_end; ++field_pos)
+ {
+ clang::QualType field_qual_type = field_pos->getType();
+ if (field_qual_type->isFloatingType())
+ {
+ if (field_qual_type->isComplexType())
+ return 0;
+ else
+ {
+ if (num_fields == 0)
+ base_qual_type = field_qual_type;
+ else
+ {
+ if (is_hva)
+ return 0;
+ is_hfa = true;
+ if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr())
+ return 0;
+ }
+ }
+ }
+ else if (field_qual_type->isVectorType() || field_qual_type->isExtVectorType())
+ {
+ const clang::VectorType *array = field_qual_type.getTypePtr()->getAs<clang::VectorType>();
+ if (array && array->getNumElements() <= 4)
+ {
+ if (num_fields == 0)
+ base_qual_type = array->getElementType();
+ else
+ {
+ if (is_hfa)
+ return 0;
+ is_hva = true;
+ if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr())
+ return 0;
+ }
+ }
+ else
+ return 0;
+ }
+ else
+ return 0;
+ ++num_fields;
+ }
+ if (base_type_ptr)
+ *base_type_ptr = CompilerType (getASTContext(), base_qual_type);
+ return num_fields;
+ }
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ return IsHomogeneousAggregate(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), base_type_ptr);
+
+ case clang::Type::Auto:
+ return IsHomogeneousAggregate(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), base_type_ptr);
+
+ case clang::Type::Elaborated:
+ return IsHomogeneousAggregate(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), base_type_ptr);
+ default:
+ break;
+ }
+ return 0;
+}
+
+size_t
+ClangASTContext::GetNumberOfFunctionArguments (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
+ if (func)
+ return func->getNumParams();
+ }
+ return 0;
+}
+
+CompilerType
+ClangASTContext::GetFunctionArgumentAtIndex (lldb::opaque_compiler_type_t type, const size_t index)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
+ if (func)
+ {
+ if (index < func->getNumParams())
+ return CompilerType(getASTContext(), func->getParamType(index));
+ }
+ }
+ return CompilerType();
+}
+
+bool
+ClangASTContext::IsFunctionPointerType (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ if (qual_type->isFunctionPointerType())
+ return true;
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ default:
+ break;
+ case clang::Type::Typedef:
+ return IsFunctionPointerType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr());
+ case clang::Type::Auto:
+ return IsFunctionPointerType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr());
+ case clang::Type::Elaborated:
+ return IsFunctionPointerType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr());
+ case clang::Type::Paren:
+ return IsFunctionPointerType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr());
+
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ {
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+ if (reference_type)
+ return IsFunctionPointerType(reference_type->getPointeeType().getAsOpaquePtr());
+ }
+ break;
+ }
+ }
+ return false;
+
+}
+
+bool
+ClangASTContext::IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_signed)
+{
+ if (!type)
+ return false;
+
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());
+
+ if (builtin_type)
+ {
+ if (builtin_type->isInteger())
+ {
+ is_signed = builtin_type->isSignedInteger();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+ClangASTContext::IsPointerType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Builtin:
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
+ {
+ default:
+ break;
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ return true;
+ }
+ return false;
+ case clang::Type::ObjCObjectPointer:
+ if (pointee_type)
+ pointee_type->SetCompilerType (getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType());
+ return true;
+ case clang::Type::BlockPointer:
+ if (pointee_type)
+ pointee_type->SetCompilerType (getASTContext(), llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType());
+ return true;
+ case clang::Type::Pointer:
+ if (pointee_type)
+ pointee_type->SetCompilerType (getASTContext(), llvm::cast<clang::PointerType>(qual_type)->getPointeeType());
+ return true;
+ case clang::Type::MemberPointer:
+ if (pointee_type)
+ pointee_type->SetCompilerType (getASTContext(), llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType());
+ return true;
+ case clang::Type::Typedef:
+ return IsPointerType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type);
+ case clang::Type::Auto:
+ return IsPointerType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), pointee_type);
+ case clang::Type::Elaborated:
+ return IsPointerType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type);
+ case clang::Type::Paren:
+ return IsPointerType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), pointee_type);
+ default:
+ break;
+ }
+ }
+ if (pointee_type)
+ pointee_type->Clear();
+ return false;
+}
+
+
+bool
+ClangASTContext::IsPointerOrReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Builtin:
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
+ {
+ default:
+ break;
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ return true;
+ }
+ return false;
+ case clang::Type::ObjCObjectPointer:
+ if (pointee_type)
+ pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType());
+ return true;
+ case clang::Type::BlockPointer:
+ if (pointee_type)
+ pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType());
+ return true;
+ case clang::Type::Pointer:
+ if (pointee_type)
+ pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::PointerType>(qual_type)->getPointeeType());
+ return true;
+ case clang::Type::MemberPointer:
+ if (pointee_type)
+ pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType());
+ return true;
+ case clang::Type::LValueReference:
+ if (pointee_type)
+ pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::LValueReferenceType>(qual_type)->desugar());
+ return true;
+ case clang::Type::RValueReference:
+ if (pointee_type)
+ pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::RValueReferenceType>(qual_type)->desugar());
+ return true;
+ case clang::Type::Typedef:
+ return IsPointerOrReferenceType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type);
+ case clang::Type::Auto:
+ return IsPointerOrReferenceType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), pointee_type);
+ case clang::Type::Elaborated:
+ return IsPointerOrReferenceType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type);
+ case clang::Type::Paren:
+ return IsPointerOrReferenceType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), pointee_type);
+ default:
+ break;
+ }
+ }
+ if (pointee_type)
+ pointee_type->Clear();
+ return false;
+}
+
+
+bool
+ClangASTContext::IsReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool* is_rvalue)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+
+ switch (type_class)
+ {
+ case clang::Type::LValueReference:
+ if (pointee_type)
+ pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::LValueReferenceType>(qual_type)->desugar());
+ if (is_rvalue)
+ *is_rvalue = false;
+ return true;
+ case clang::Type::RValueReference:
+ if (pointee_type)
+ pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::RValueReferenceType>(qual_type)->desugar());
+ if (is_rvalue)
+ *is_rvalue = true;
+ return true;
+ case clang::Type::Typedef:
+ return IsReferenceType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type, is_rvalue);
+ case clang::Type::Auto:
+ return IsReferenceType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), pointee_type, is_rvalue);
+ case clang::Type::Elaborated:
+ return IsReferenceType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type, is_rvalue);
+ case clang::Type::Paren:
+ return IsReferenceType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), pointee_type, is_rvalue);
+
+ default:
+ break;
+ }
+ }
+ if (pointee_type)
+ pointee_type->Clear();
+ return false;
+}
+
+bool
+ClangASTContext::IsFloatingPointType (lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal()))
+ {
+ clang::BuiltinType::Kind kind = BT->getKind();
+ if (kind >= clang::BuiltinType::Float && kind <= clang::BuiltinType::LongDouble)
+ {
+ count = 1;
+ is_complex = false;
+ return true;
+ }
+ }
+ else if (const clang::ComplexType *CT = llvm::dyn_cast<clang::ComplexType>(qual_type->getCanonicalTypeInternal()))
+ {
+ if (IsFloatingPointType (CT->getElementType().getAsOpaquePtr(), count, is_complex))
+ {
+ count = 2;
+ is_complex = true;
+ return true;
+ }
+ }
+ else if (const clang::VectorType *VT = llvm::dyn_cast<clang::VectorType>(qual_type->getCanonicalTypeInternal()))
+ {
+ if (IsFloatingPointType (VT->getElementType().getAsOpaquePtr(), count, is_complex))
+ {
+ count = VT->getNumElements();
+ is_complex = false;
+ return true;
+ }
+ }
+ }
+ count = 0;
+ is_complex = false;
+ return false;
+}
+
+
+bool
+ClangASTContext::IsDefined(lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return false;
+
+ clang::QualType qual_type(GetQualType(type));
+ const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
+ if (tag_type)
+ {
+ clang::TagDecl *tag_decl = tag_type->getDecl();
+ if (tag_decl)
+ return tag_decl->isCompleteDefinition();
+ return false;
+ }
+ else
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ if (class_interface_decl)
+ return class_interface_decl->getDefinition() != nullptr;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+ClangASTContext::IsObjCClassType (const CompilerType& type)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
+
+ if (obj_pointer_type)
+ return obj_pointer_type->isObjCClassType();
+ }
+ return false;
+}
+
+bool
+ClangASTContext::IsObjCObjectOrInterfaceType (const CompilerType& type)
+{
+ if (IsClangType(type))
+ return GetCanonicalQualType(type)->isObjCObjectOrInterfaceType();
+ return false;
+}
+
+bool
+ClangASTContext::IsPolymorphicClass (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
+ {
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ if (record_decl)
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+ if (cxx_record_decl)
+ return cxx_record_decl->isPolymorphic();
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+bool
+ClangASTContext::IsPossibleDynamicType (lldb::opaque_compiler_type_t type, CompilerType *dynamic_pointee_type,
+ bool check_cplusplus,
+ bool check_objc)
+{
+ clang::QualType pointee_qual_type;
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ bool success = false;
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Builtin:
+ if (check_objc && llvm::cast<clang::BuiltinType>(qual_type)->getKind() == clang::BuiltinType::ObjCId)
+ {
+ if (dynamic_pointee_type)
+ dynamic_pointee_type->SetCompilerType(this, type);
+ return true;
+ }
+ break;
+
+ case clang::Type::ObjCObjectPointer:
+ if (check_objc)
+ {
+ if (dynamic_pointee_type)
+ dynamic_pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType());
+ return true;
+ }
+ break;
+
+ case clang::Type::Pointer:
+ pointee_qual_type = llvm::cast<clang::PointerType>(qual_type)->getPointeeType();
+ success = true;
+ break;
+
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ pointee_qual_type = llvm::cast<clang::ReferenceType>(qual_type)->getPointeeType();
+ success = true;
+ break;
+
+ case clang::Type::Typedef:
+ return IsPossibleDynamicType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(),
+ dynamic_pointee_type,
+ check_cplusplus,
+ check_objc);
+
+ case clang::Type::Auto:
+ return IsPossibleDynamicType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(),
+ dynamic_pointee_type,
+ check_cplusplus,
+ check_objc);
+
+ case clang::Type::Elaborated:
+ return IsPossibleDynamicType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(),
+ dynamic_pointee_type,
+ check_cplusplus,
+ check_objc);
+
+ case clang::Type::Paren:
+ return IsPossibleDynamicType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(),
+ dynamic_pointee_type,
+ check_cplusplus,
+ check_objc);
+ default:
+ break;
+ }
+
+ if (success)
+ {
+ // Check to make sure what we are pointing too is a possible dynamic C++ type
+ // We currently accept any "void *" (in case we have a class that has been
+ // watered down to an opaque pointer) and virtual C++ classes.
+ const clang::Type::TypeClass pointee_type_class = pointee_qual_type.getCanonicalType()->getTypeClass();
+ switch (pointee_type_class)
+ {
+ case clang::Type::Builtin:
+ switch (llvm::cast<clang::BuiltinType>(pointee_qual_type)->getKind())
+ {
+ case clang::BuiltinType::UnknownAny:
+ case clang::BuiltinType::Void:
+ if (dynamic_pointee_type)
+ dynamic_pointee_type->SetCompilerType(getASTContext(), pointee_qual_type);
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case clang::Type::Record:
+ if (check_cplusplus)
+ {
+ clang::CXXRecordDecl *cxx_record_decl = pointee_qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ bool is_complete = cxx_record_decl->isCompleteDefinition();
+
+ if (is_complete)
+ success = cxx_record_decl->isDynamicClass();
+ else
+ {
+ ClangASTMetadata *metadata = ClangASTContext::GetMetadata (getASTContext(), cxx_record_decl);
+ if (metadata)
+ success = metadata->GetIsDynamicCXXType();
+ else
+ {
+ is_complete = CompilerType(getASTContext(), pointee_qual_type).GetCompleteType();
+ if (is_complete)
+ success = cxx_record_decl->isDynamicClass();
+ else
+ success = false;
+ }
+ }
+
+ if (success)
+ {
+ if (dynamic_pointee_type)
+ dynamic_pointee_type->SetCompilerType(getASTContext(), pointee_qual_type);
+ return true;
+ }
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ if (check_objc)
+ {
+ if (dynamic_pointee_type)
+ dynamic_pointee_type->SetCompilerType(getASTContext(), pointee_qual_type);
+ return true;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ if (dynamic_pointee_type)
+ dynamic_pointee_type->Clear();
+ return false;
+}
+
+
+bool
+ClangASTContext::IsScalarType (lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return false;
+
+ return (GetTypeInfo (type, nullptr) & eTypeIsScalar) != 0;
+}
+
+bool
+ClangASTContext::IsTypedefType (lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return false;
+ return GetQualType(type)->getTypeClass() == clang::Type::Typedef;
+}
+
+bool
+ClangASTContext::IsVoidType (lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return false;
+ return GetCanonicalQualType(type)->isVoidType();
+}
+
+bool
+ClangASTContext::SupportsLanguage (lldb::LanguageType language)
+{
+ return ClangASTContextSupportsLanguage(language);
+}
+
+bool
+ClangASTContext::GetCXXClassName (const CompilerType& type, std::string &class_name)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ if (!qual_type.isNull())
+ {
+ clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ class_name.assign(cxx_record_decl->getIdentifier()->getNameStart());
+ return true;
+ }
+ }
+ }
+ class_name.clear();
+ return false;
+}
+
+
+bool
+ClangASTContext::IsCXXClassType (const CompilerType& type)
+{
+ if (!type)
+ return false;
+
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ if (!qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr)
+ return true;
+ return false;
+}
+
+bool
+ClangASTContext::IsBeingDefined (lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return false;
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type);
+ if (tag_type)
+ return tag_type->isBeingDefined();
+ return false;
+}
+
+bool
+ClangASTContext::IsObjCObjectPointerType (const CompilerType& type, CompilerType *class_type_ptr)
+{
+ if (!type)
+ return false;
+
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ if (!qual_type.isNull() && qual_type->isObjCObjectPointerType())
+ {
+ if (class_type_ptr)
+ {
+ if (!qual_type->isObjCClassType() &&
+ !qual_type->isObjCIdType())
+ {
+ const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
+ if (obj_pointer_type == nullptr)
+ class_type_ptr->Clear();
+ else
+ class_type_ptr->SetCompilerType (type.GetTypeSystem(), clang::QualType(obj_pointer_type->getInterfaceType(), 0).getAsOpaquePtr());
+ }
+ }
+ return true;
+ }
+ if (class_type_ptr)
+ class_type_ptr->Clear();
+ return false;
+}
+
+bool
+ClangASTContext::GetObjCClassName (const CompilerType& type, std::string &class_name)
+{
+ if (!type)
+ return false;
+
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ const clang::ObjCObjectType *object_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+ if (object_type)
+ {
+ const clang::ObjCInterfaceDecl *interface = object_type->getInterface();
+ if (interface)
+ {
+ class_name = interface->getNameAsString();
+ return true;
+ }
+ }
+ return false;
+}
+
+
+//----------------------------------------------------------------------
+// Type Completion
+//----------------------------------------------------------------------
+
+bool
+ClangASTContext::GetCompleteType (lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return false;
+ const bool allow_completion = true;
+ return GetCompleteQualType (getASTContext(), GetQualType(type), allow_completion);
+}
+
+ConstString
+ClangASTContext::GetTypeName (lldb::opaque_compiler_type_t type)
+{
+ std::string type_name;
+ if (type)
{
- if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_ctx))
+ clang::PrintingPolicy printing_policy (getASTContext()->getPrintingPolicy());
+ clang::QualType qual_type(GetQualType(type));
+ printing_policy.SuppressTagKeyword = true;
+ printing_policy.LangOpts.WChar = true;
+ const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
+ if (typedef_type)
{
- if (method_decl->isStatic())
+ const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
+ type_name = typedef_decl->getQualifiedNameAsString();
+ }
+ else
+ {
+ type_name = qual_type.getAsString(printing_policy);
+ }
+ }
+ return ConstString(type_name);
+}
+
+uint32_t
+ClangASTContext::GetTypeInfo (lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_clang_type)
+{
+ if (!type)
+ return 0;
+
+ if (pointee_or_element_clang_type)
+ pointee_or_element_clang_type->Clear();
+
+ clang::QualType qual_type (GetQualType(type));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Builtin:
+ {
+ const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());
+
+ uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue;
+ switch (builtin_type->getKind())
{
- is_instance_method = false;
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ if (pointee_or_element_clang_type)
+ pointee_or_element_clang_type->SetCompilerType(getASTContext(), getASTContext()->ObjCBuiltinClassTy);
+ builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
+ break;
+
+ case clang::BuiltinType::ObjCSel:
+ if (pointee_or_element_clang_type)
+ pointee_or_element_clang_type->SetCompilerType(getASTContext(), getASTContext()->CharTy);
+ builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
+ break;
+
+ case clang::BuiltinType::Bool:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::Int128:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::LongDouble:
+ builtin_type_flags |= eTypeIsScalar;
+ if (builtin_type->isInteger())
+ {
+ builtin_type_flags |= eTypeIsInteger;
+ if (builtin_type->isSignedInteger())
+ builtin_type_flags |= eTypeIsSigned;
+ }
+ else if (builtin_type->isFloatingPoint())
+ builtin_type_flags |= eTypeIsFloat;
+ break;
+ default:
+ break;
}
+ return builtin_type_flags;
+ }
+
+ case clang::Type::BlockPointer:
+ if (pointee_or_element_clang_type)
+ pointee_or_element_clang_type->SetCompilerType(getASTContext(), qual_type->getPointeeType());
+ return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock;
+
+ case clang::Type::Complex:
+ {
+ uint32_t complex_type_flags = eTypeIsBuiltIn | eTypeHasValue | eTypeIsComplex;
+ const clang::ComplexType *complex_type = llvm::dyn_cast<clang::ComplexType>(qual_type->getCanonicalTypeInternal());
+ if (complex_type)
+ {
+ clang::QualType complex_element_type (complex_type->getElementType());
+ if (complex_element_type->isIntegerType())
+ complex_type_flags |= eTypeIsFloat;
+ else if (complex_element_type->isFloatingType())
+ complex_type_flags |= eTypeIsInteger;
+ }
+ return complex_type_flags;
+ }
+ break;
+
+ case clang::Type::ConstantArray:
+ case clang::Type::DependentSizedArray:
+ case clang::Type::IncompleteArray:
+ case clang::Type::VariableArray:
+ if (pointee_or_element_clang_type)
+ pointee_or_element_clang_type->SetCompilerType(getASTContext(), llvm::cast<clang::ArrayType>(qual_type.getTypePtr())->getElementType());
+ return eTypeHasChildren | eTypeIsArray;
+
+ case clang::Type::DependentName: return 0;
+ case clang::Type::DependentSizedExtVector: return eTypeHasChildren | eTypeIsVector;
+ case clang::Type::DependentTemplateSpecialization: return eTypeIsTemplate;
+ case clang::Type::Decltype: return 0;
+
+ case clang::Type::Enum:
+ if (pointee_or_element_clang_type)
+ pointee_or_element_clang_type->SetCompilerType(getASTContext(), llvm::cast<clang::EnumType>(qual_type)->getDecl()->getIntegerType());
+ return eTypeIsEnumeration | eTypeHasValue;
+
+ case clang::Type::Auto:
+ return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetTypeInfo (pointee_or_element_clang_type);
+ case clang::Type::Elaborated:
+ return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetTypeInfo (pointee_or_element_clang_type);
+ case clang::Type::Paren:
+ return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetTypeInfo (pointee_or_element_clang_type);
+
+ case clang::Type::FunctionProto: return eTypeIsFuncPrototype | eTypeHasValue;
+ case clang::Type::FunctionNoProto: return eTypeIsFuncPrototype | eTypeHasValue;
+ case clang::Type::InjectedClassName: return 0;
+
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ if (pointee_or_element_clang_type)
+ pointee_or_element_clang_type->SetCompilerType(getASTContext(), llvm::cast<clang::ReferenceType>(qual_type.getTypePtr())->getPointeeType());
+ return eTypeHasChildren | eTypeIsReference | eTypeHasValue;
+
+ case clang::Type::MemberPointer: return eTypeIsPointer | eTypeIsMember | eTypeHasValue;
+
+ case clang::Type::ObjCObjectPointer:
+ if (pointee_or_element_clang_type)
+ pointee_or_element_clang_type->SetCompilerType(getASTContext(), qual_type->getPointeeType());
+ return eTypeHasChildren | eTypeIsObjC | eTypeIsClass | eTypeIsPointer | eTypeHasValue;
+
+ case clang::Type::ObjCObject: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass;
+ case clang::Type::ObjCInterface: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass;
+
+ case clang::Type::Pointer:
+ if (pointee_or_element_clang_type)
+ pointee_or_element_clang_type->SetCompilerType(getASTContext(), qual_type->getPointeeType());
+ return eTypeHasChildren | eTypeIsPointer | eTypeHasValue;
+
+ case clang::Type::Record:
+ if (qual_type->getAsCXXRecordDecl())
+ return eTypeHasChildren | eTypeIsClass | eTypeIsCPlusPlus;
else
+ return eTypeHasChildren | eTypeIsStructUnion;
+ break;
+ case clang::Type::SubstTemplateTypeParm: return eTypeIsTemplate;
+ case clang::Type::TemplateTypeParm: return eTypeIsTemplate;
+ case clang::Type::TemplateSpecialization: return eTypeIsTemplate;
+
+ case clang::Type::Typedef:
+ return eTypeIsTypedef | CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetTypeInfo (pointee_or_element_clang_type);
+ case clang::Type::TypeOfExpr: return 0;
+ case clang::Type::TypeOf: return 0;
+ case clang::Type::UnresolvedUsing: return 0;
+
+ case clang::Type::ExtVector:
+ case clang::Type::Vector:
+ {
+ uint32_t vector_type_flags = eTypeHasChildren | eTypeIsVector;
+ const clang::VectorType *vector_type = llvm::dyn_cast<clang::VectorType>(qual_type->getCanonicalTypeInternal());
+ if (vector_type)
{
- language_object_name.SetCString("this");
- is_instance_method = true;
+ if (vector_type->isIntegerType())
+ vector_type_flags |= eTypeIsFloat;
+ else if (vector_type->isFloatingType())
+ vector_type_flags |= eTypeIsInteger;
}
- language = eLanguageTypeC_plus_plus;
+ return vector_type_flags;
+ }
+ default: return 0;
+ }
+ return 0;
+}
+
+
+
+lldb::LanguageType
+ClangASTContext::GetMinimumLanguage (lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return lldb::eLanguageTypeC;
+
+ // If the type is a reference, then resolve it to what it refers to first:
+ clang::QualType qual_type (GetCanonicalQualType(type).getNonReferenceType());
+ if (qual_type->isAnyPointerType())
+ {
+ if (qual_type->isObjCObjectPointerType())
+ return lldb::eLanguageTypeObjC;
+
+ clang::QualType pointee_type (qual_type->getPointeeType());
+ if (pointee_type->getPointeeCXXRecordDecl() != nullptr)
+ return lldb::eLanguageTypeC_plus_plus;
+ if (pointee_type->isObjCObjectOrInterfaceType())
+ return lldb::eLanguageTypeObjC;
+ if (pointee_type->isObjCClassType())
+ return lldb::eLanguageTypeObjC;
+ if (pointee_type.getTypePtr() == getASTContext()->ObjCBuiltinIdTy.getTypePtr())
+ return lldb::eLanguageTypeObjC;
+ }
+ else
+ {
+ if (qual_type->isObjCObjectOrInterfaceType())
+ return lldb::eLanguageTypeObjC;
+ if (qual_type->getAsCXXRecordDecl())
+ return lldb::eLanguageTypeC_plus_plus;
+ switch (qual_type->getTypeClass())
+ {
+ default:
+ break;
+ case clang::Type::Builtin:
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
+ {
+ default:
+ case clang::BuiltinType::Void:
+ case clang::BuiltinType::Bool:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::Int128:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::LongDouble:
+ break;
+
+ case clang::BuiltinType::NullPtr:
+ return eLanguageTypeC_plus_plus;
+
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCSel:
+ return eLanguageTypeObjC;
+
+ case clang::BuiltinType::Dependent:
+ case clang::BuiltinType::Overload:
+ case clang::BuiltinType::BoundMember:
+ case clang::BuiltinType::UnknownAny:
+ break;
+ }
+ break;
+ case clang::Type::Typedef:
+ return CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetMinimumLanguage();
+ }
+ }
+ return lldb::eLanguageTypeC;
+}
+
+lldb::TypeClass
+ClangASTContext::GetTypeClass (lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return lldb::eTypeClassInvalid;
+
+ clang::QualType qual_type(GetQualType(type));
+
+ switch (qual_type->getTypeClass())
+ {
+ case clang::Type::UnaryTransform: break;
+ case clang::Type::FunctionNoProto: return lldb::eTypeClassFunction;
+ case clang::Type::FunctionProto: return lldb::eTypeClassFunction;
+ case clang::Type::IncompleteArray: return lldb::eTypeClassArray;
+ case clang::Type::VariableArray: return lldb::eTypeClassArray;
+ case clang::Type::ConstantArray: return lldb::eTypeClassArray;
+ case clang::Type::DependentSizedArray: return lldb::eTypeClassArray;
+ case clang::Type::DependentSizedExtVector: return lldb::eTypeClassVector;
+ case clang::Type::ExtVector: return lldb::eTypeClassVector;
+ case clang::Type::Vector: return lldb::eTypeClassVector;
+ case clang::Type::Builtin: return lldb::eTypeClassBuiltin;
+ case clang::Type::ObjCObjectPointer: return lldb::eTypeClassObjCObjectPointer;
+ case clang::Type::BlockPointer: return lldb::eTypeClassBlockPointer;
+ case clang::Type::Pointer: return lldb::eTypeClassPointer;
+ case clang::Type::LValueReference: return lldb::eTypeClassReference;
+ case clang::Type::RValueReference: return lldb::eTypeClassReference;
+ case clang::Type::MemberPointer: return lldb::eTypeClassMemberPointer;
+ case clang::Type::Complex:
+ if (qual_type->isComplexType())
+ return lldb::eTypeClassComplexFloat;
+ else
+ return lldb::eTypeClassComplexInteger;
+ case clang::Type::ObjCObject: return lldb::eTypeClassObjCObject;
+ case clang::Type::ObjCInterface: return lldb::eTypeClassObjCInterface;
+ case clang::Type::Record:
+ {
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ if (record_decl->isUnion())
+ return lldb::eTypeClassUnion;
+ else if (record_decl->isStruct())
+ return lldb::eTypeClassStruct;
+ else
+ return lldb::eTypeClassClass;
+ }
+ break;
+ case clang::Type::Enum: return lldb::eTypeClassEnumeration;
+ case clang::Type::Typedef: return lldb::eTypeClassTypedef;
+ case clang::Type::UnresolvedUsing: break;
+ case clang::Type::Paren:
+ return CompilerType(getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetTypeClass();
+ case clang::Type::Auto:
+ return CompilerType(getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetTypeClass();
+ case clang::Type::Elaborated:
+ return CompilerType(getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetTypeClass();
+
+ case clang::Type::Attributed: break;
+ case clang::Type::TemplateTypeParm: break;
+ case clang::Type::SubstTemplateTypeParm: break;
+ case clang::Type::SubstTemplateTypeParmPack:break;
+ case clang::Type::InjectedClassName: break;
+ case clang::Type::DependentName: break;
+ case clang::Type::DependentTemplateSpecialization: break;
+ case clang::Type::PackExpansion: break;
+
+ case clang::Type::TypeOfExpr: break;
+ case clang::Type::TypeOf: break;
+ case clang::Type::Decltype: break;
+ case clang::Type::TemplateSpecialization: break;
+ case clang::Type::Atomic: break;
+ case clang::Type::Pipe: break;
+
+ // pointer type decayed from an array or function type.
+ case clang::Type::Decayed: break;
+ case clang::Type::Adjusted: break;
+ }
+ // We don't know hot to display this type...
+ return lldb::eTypeClassOther;
+
+}
+
+unsigned
+ClangASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ return GetQualType(type).getQualifiers().getCVRQualifiers();
+ return 0;
+}
+
+//----------------------------------------------------------------------
+// Creating related types
+//----------------------------------------------------------------------
+
+CompilerType
+ClangASTContext::GetArrayElementType (lldb::opaque_compiler_type_t type, uint64_t *stride)
+{
+ if (type)
+ {
+ clang::QualType qual_type(GetCanonicalQualType(type));
+
+ const clang::Type *array_eletype = qual_type.getTypePtr()->getArrayElementTypeNoTypeQual();
+
+ if (!array_eletype)
+ return CompilerType();
+
+ CompilerType element_type (getASTContext(), array_eletype->getCanonicalTypeUnqualified());
+
+ // TODO: the real stride will be >= this value.. find the real one!
+ if (stride)
+ *stride = element_type.GetByteSize(nullptr);
+
+ return element_type;
+
+ }
+ return CompilerType();
+}
+
+CompilerType
+ClangASTContext::GetCanonicalType (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ return CompilerType (getASTContext(), GetCanonicalQualType(type));
+ return CompilerType();
+}
+
+static clang::QualType
+GetFullyUnqualifiedType_Impl (clang::ASTContext *ast, clang::QualType qual_type)
+{
+ if (qual_type->isPointerType())
+ qual_type = ast->getPointerType(GetFullyUnqualifiedType_Impl(ast, qual_type->getPointeeType()));
+ else
+ qual_type = qual_type.getUnqualifiedType();
+ qual_type.removeLocalConst();
+ qual_type.removeLocalRestrict();
+ qual_type.removeLocalVolatile();
+ return qual_type;
+}
+
+CompilerType
+ClangASTContext::GetFullyUnqualifiedType (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ return CompilerType(getASTContext(), GetFullyUnqualifiedType_Impl(getASTContext(), GetQualType(type)));
+ return CompilerType();
+}
+
+
+int
+ClangASTContext::GetFunctionArgumentCount (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType(type));
+ if (func)
+ return func->getNumParams();
+ }
+ return -1;
+}
+
+CompilerType
+ClangASTContext::GetFunctionArgumentTypeAtIndex (lldb::opaque_compiler_type_t type, size_t idx)
+{
+ if (type)
+ {
+ const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(GetQualType(type));
+ if (func)
+ {
+ const uint32_t num_args = func->getNumParams();
+ if (idx < num_args)
+ return CompilerType(getASTContext(), func->getParamType(idx));
+ }
+ }
+ return CompilerType();
+}
+
+CompilerType
+ClangASTContext::GetFunctionReturnType (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ clang::QualType qual_type(GetQualType(type));
+ const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
+ if (func)
+ return CompilerType(getASTContext(), func->getReturnType());
+ }
+ return CompilerType();
+}
+
+size_t
+ClangASTContext::GetNumMemberFunctions (lldb::opaque_compiler_type_t type)
+{
+ size_t num_functions = 0;
+ if (type)
+ {
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ switch (qual_type->getTypeClass()) {
+ case clang::Type::Record:
+ if (GetCompleteQualType (getASTContext(), qual_type))
+ {
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ assert(record_decl);
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+ if (cxx_record_decl)
+ num_functions = std::distance(cxx_record_decl->method_begin(), cxx_record_decl->method_end());
+ }
+ break;
+
+ case clang::Type::ObjCObjectPointer:
+ if (GetCompleteType(type))
+ {
+ const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
+ if (class_interface_decl)
+ num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end());
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ if (GetCompleteType(type))
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ if (class_interface_decl)
+ num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end());
+ }
+ }
+ break;
+
+
+ case clang::Type::Typedef:
+ return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumMemberFunctions();
+
+ case clang::Type::Auto:
+ return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetNumMemberFunctions();
+
+ case clang::Type::Elaborated:
+ return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumMemberFunctions();
+
+ case clang::Type::Paren:
+ return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumMemberFunctions();
+
+ default:
+ break;
+ }
+ }
+ return num_functions;
+}
+
+TypeMemberFunctionImpl
+ClangASTContext::GetMemberFunctionAtIndex (lldb::opaque_compiler_type_t type, size_t idx)
+{
+ std::string name;
+ MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown);
+ CompilerType clang_type;
+ CompilerDecl clang_decl;
+ if (type)
+ {
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ switch (qual_type->getTypeClass()) {
+ case clang::Type::Record:
+ if (GetCompleteQualType (getASTContext(), qual_type))
+ {
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ assert(record_decl);
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+ if (cxx_record_decl)
+ {
+ auto method_iter = cxx_record_decl->method_begin();
+ auto method_end = cxx_record_decl->method_end();
+ if (idx < static_cast<size_t>(std::distance(method_iter, method_end)))
+ {
+ std::advance(method_iter, idx);
+ clang::CXXMethodDecl *cxx_method_decl = method_iter->getCanonicalDecl();
+ if (cxx_method_decl)
+ {
+ name = cxx_method_decl->getDeclName().getAsString();
+ if (cxx_method_decl->isStatic())
+ kind = lldb::eMemberFunctionKindStaticMethod;
+ else if (llvm::isa<clang::CXXConstructorDecl>(cxx_method_decl))
+ kind = lldb::eMemberFunctionKindConstructor;
+ else if (llvm::isa<clang::CXXDestructorDecl>(cxx_method_decl))
+ kind = lldb::eMemberFunctionKindDestructor;
+ else
+ kind = lldb::eMemberFunctionKindInstanceMethod;
+ clang_type = CompilerType(this, cxx_method_decl->getType().getAsOpaquePtr());
+ clang_decl = CompilerDecl(this, cxx_method_decl);
+ }
+ }
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObjectPointer:
+ if (GetCompleteType(type))
+ {
+ const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
+ if (class_interface_decl)
+ {
+ auto method_iter = class_interface_decl->meth_begin();
+ auto method_end = class_interface_decl->meth_end();
+ if (idx < static_cast<size_t>(std::distance(method_iter, method_end)))
+ {
+ std::advance(method_iter, idx);
+ clang::ObjCMethodDecl *objc_method_decl = method_iter->getCanonicalDecl();
+ if (objc_method_decl)
+ {
+ clang_decl = CompilerDecl(this, objc_method_decl);
+ name = objc_method_decl->getSelector().getAsString();
+ if (objc_method_decl->isClassMethod())
+ kind = lldb::eMemberFunctionKindStaticMethod;
+ else
+ kind = lldb::eMemberFunctionKindInstanceMethod;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ if (GetCompleteType(type))
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ if (class_interface_decl)
+ {
+ auto method_iter = class_interface_decl->meth_begin();
+ auto method_end = class_interface_decl->meth_end();
+ if (idx < static_cast<size_t>(std::distance(method_iter, method_end)))
+ {
+ std::advance(method_iter, idx);
+ clang::ObjCMethodDecl *objc_method_decl = method_iter->getCanonicalDecl();
+ if (objc_method_decl)
+ {
+ clang_decl = CompilerDecl(this, objc_method_decl);
+ name = objc_method_decl->getSelector().getAsString();
+ if (objc_method_decl->isClassMethod())
+ kind = lldb::eMemberFunctionKindStaticMethod;
+ else
+ kind = lldb::eMemberFunctionKindInstanceMethod;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ return GetMemberFunctionAtIndex(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), idx);
+
+ case clang::Type::Auto:
+ return GetMemberFunctionAtIndex(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), idx);
+
+ case clang::Type::Elaborated:
+ return GetMemberFunctionAtIndex(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), idx);
+
+ case clang::Type::Paren:
+ return GetMemberFunctionAtIndex(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), idx);
+
+ default:
+ break;
+ }
+ }
+
+ if (kind == eMemberFunctionKindUnknown)
+ return TypeMemberFunctionImpl();
+ else
+ return TypeMemberFunctionImpl(clang_type, clang_decl, name, kind);
+}
+
+CompilerType
+ClangASTContext::GetNonReferenceType (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ return CompilerType(getASTContext(), GetQualType(type).getNonReferenceType());
+ return CompilerType();
+}
+
+CompilerType
+ClangASTContext::CreateTypedefType (const CompilerType& type,
+ const char *typedef_name,
+ const CompilerDeclContext &compiler_decl_ctx)
+{
+ if (type && typedef_name && typedef_name[0])
+ {
+ ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (!ast)
+ return CompilerType();
+ clang::ASTContext* clang_ast = ast->getASTContext();
+ clang::QualType qual_type (GetQualType(type));
+
+ clang::DeclContext *decl_ctx = ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx);
+ if (decl_ctx == nullptr)
+ decl_ctx = ast->getASTContext()->getTranslationUnitDecl();
+
+ clang::TypedefDecl *decl = clang::TypedefDecl::Create (*clang_ast,
+ decl_ctx,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ &clang_ast->Idents.get(typedef_name),
+ clang_ast->getTrivialTypeSourceInfo(qual_type));
+
+ decl->setAccess(clang::AS_public); // TODO respect proper access specifier
+
+ // Get a uniqued clang::QualType for the typedef decl type
+ return CompilerType (clang_ast, clang_ast->getTypedefType (decl));
+ }
+ return CompilerType();
+
+}
+
+CompilerType
+ClangASTContext::GetPointeeType (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ clang::QualType qual_type(GetQualType(type));
+ return CompilerType (getASTContext(), qual_type.getTypePtr()->getPointeeType());
+ }
+ return CompilerType();
+}
+
+CompilerType
+ClangASTContext::GetPointerType (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetQualType(type));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ return CompilerType(getASTContext(), getASTContext()->getObjCObjectPointerType(qual_type));
+
+ default:
+ return CompilerType(getASTContext(), getASTContext()->getPointerType(qual_type));
+ }
+ }
+ return CompilerType();
+}
+
+
+CompilerType
+ClangASTContext::GetLValueReferenceType (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ return CompilerType(this, getASTContext()->getLValueReferenceType(GetQualType(type)).getAsOpaquePtr());
+ else
+ return CompilerType();
+}
+
+CompilerType
+ClangASTContext::GetRValueReferenceType (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ return CompilerType(this, getASTContext()->getRValueReferenceType(GetQualType(type)).getAsOpaquePtr());
+ else
+ return CompilerType();
+}
+
+CompilerType
+ClangASTContext::AddConstModifier (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ clang::QualType result(GetQualType(type));
+ result.addConst();
+ return CompilerType (this, result.getAsOpaquePtr());
+ }
+ return CompilerType();
+}
+
+CompilerType
+ClangASTContext::AddVolatileModifier (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ clang::QualType result(GetQualType(type));
+ result.addVolatile();
+ return CompilerType (this, result.getAsOpaquePtr());
+ }
+ return CompilerType();
+
+}
+
+CompilerType
+ClangASTContext::AddRestrictModifier (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ clang::QualType result(GetQualType(type));
+ result.addRestrict();
+ return CompilerType (this, result.getAsOpaquePtr());
+ }
+ return CompilerType();
+
+}
+
+CompilerType
+ClangASTContext::CreateTypedef (lldb::opaque_compiler_type_t type, const char *typedef_name, const CompilerDeclContext &compiler_decl_ctx)
+{
+ if (type)
+ {
+ clang::ASTContext* clang_ast = getASTContext();
+ clang::QualType qual_type (GetQualType(type));
+
+ clang::DeclContext *decl_ctx = ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx);
+ if (decl_ctx == nullptr)
+ decl_ctx = getASTContext()->getTranslationUnitDecl();
+
+ clang::TypedefDecl *decl = clang::TypedefDecl::Create (*clang_ast,
+ decl_ctx,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ &clang_ast->Idents.get(typedef_name),
+ clang_ast->getTrivialTypeSourceInfo(qual_type));
+
+ decl->setAccess(clang::AS_public); // TODO respect proper access specifier
+
+ // Get a uniqued clang::QualType for the typedef decl type
+ return CompilerType (this, clang_ast->getTypedefType (decl).getAsOpaquePtr());
+
+ }
+ return CompilerType();
+
+}
+
+CompilerType
+ClangASTContext::GetTypedefedType (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ const clang::TypedefType *typedef_type = llvm::dyn_cast<clang::TypedefType>(GetQualType(type));
+ if (typedef_type)
+ return CompilerType (getASTContext(), typedef_type->getDecl()->getUnderlyingType());
+ }
+ return CompilerType();
+}
+
+CompilerType
+ClangASTContext::RemoveFastQualifiers (const CompilerType& type)
+{
+ if (IsClangType(type))
+ {
+ clang::QualType qual_type(GetQualType(type));
+ qual_type.getQualifiers().removeFastQualifiers();
+ return CompilerType (type.GetTypeSystem(), qual_type.getAsOpaquePtr());
+ }
+ return type;
+}
+
+
+//----------------------------------------------------------------------
+// Create related types using the current type's AST
+//----------------------------------------------------------------------
+
+CompilerType
+ClangASTContext::GetBasicTypeFromAST (lldb::BasicType basic_type)
+{
+ return ClangASTContext::GetBasicType(getASTContext(), basic_type);
+}
+//----------------------------------------------------------------------
+// Exploring the type
+//----------------------------------------------------------------------
+
+uint64_t
+ClangASTContext::GetBitSize (lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope)
+{
+ if (GetCompleteType (type))
+ {
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ switch (qual_type->getTypeClass())
+ {
+ case clang::Type::ObjCInterface:
+ case clang::Type::ObjCObject:
+ {
+ ExecutionContext exe_ctx (exe_scope);
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process)
+ {
+ ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
+ if (objc_runtime)
+ {
+ uint64_t bit_size = 0;
+ if (objc_runtime->GetTypeBitSize(CompilerType(getASTContext(), qual_type), bit_size))
+ return bit_size;
+ }
+ }
+ else
+ {
+ static bool g_printed = false;
+ if (!g_printed)
+ {
+ StreamString s;
+ DumpTypeDescription(type, &s);
+
+ llvm::outs() << "warning: trying to determine the size of type ";
+ llvm::outs() << s.GetString() << "\n";
+ llvm::outs() << "without a valid ExecutionContext. this is not reliable. please file a bug against LLDB.\n";
+ llvm::outs() << "backtrace:\n";
+ llvm::sys::PrintStackTrace(llvm::outs());
+ llvm::outs() << "\n";
+ g_printed = true;
+ }
+ }
+ }
+ // fallthrough
+ default:
+ const uint32_t bit_size = getASTContext()->getTypeSize (qual_type);
+ if (bit_size == 0)
+ {
+ if (qual_type->isIncompleteArrayType())
+ return getASTContext()->getTypeSize (qual_type->getArrayElementTypeNoTypeQual()->getCanonicalTypeUnqualified());
+ }
+ if (qual_type->isObjCObjectOrInterfaceType())
+ return bit_size + getASTContext()->getTypeSize(getASTContext()->ObjCBuiltinClassTy);
+ return bit_size;
+ }
+ }
+ return 0;
+}
+
+size_t
+ClangASTContext::GetTypeBitAlign (lldb::opaque_compiler_type_t type)
+{
+ if (GetCompleteType(type))
+ return getASTContext()->getTypeAlign(GetQualType(type));
+ return 0;
+}
+
+
+lldb::Encoding
+ClangASTContext::GetEncoding (lldb::opaque_compiler_type_t type, uint64_t &count)
+{
+ if (!type)
+ return lldb::eEncodingInvalid;
+
+ count = 1;
+ clang::QualType qual_type(GetCanonicalQualType(type));
+
+ switch (qual_type->getTypeClass())
+ {
+ case clang::Type::UnaryTransform:
+ break;
+
+ case clang::Type::FunctionNoProto:
+ case clang::Type::FunctionProto:
+ break;
+
+ case clang::Type::IncompleteArray:
+ case clang::Type::VariableArray:
+ break;
+
+ case clang::Type::ConstantArray:
+ break;
+
+ case clang::Type::ExtVector:
+ case clang::Type::Vector:
+ // TODO: Set this to more than one???
+ break;
+
+ case clang::Type::Builtin:
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
+ {
+ case clang::BuiltinType::Void:
+ break;
+
+ case clang::BuiltinType::Bool:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::Int128: return lldb::eEncodingSint;
+
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::UInt128: return lldb::eEncodingUint;
+
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::LongDouble: return lldb::eEncodingIEEE754;
+
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCSel: return lldb::eEncodingUint;
+
+ case clang::BuiltinType::NullPtr: return lldb::eEncodingUint;
+
+ case clang::BuiltinType::Kind::ARCUnbridgedCast:
+ case clang::BuiltinType::Kind::BoundMember:
+ case clang::BuiltinType::Kind::BuiltinFn:
+ case clang::BuiltinType::Kind::Dependent:
+ case clang::BuiltinType::Kind::OCLClkEvent:
+ case clang::BuiltinType::Kind::OCLEvent:
+ case clang::BuiltinType::Kind::OCLImage1d:
+ case clang::BuiltinType::Kind::OCLImage1dArray:
+ case clang::BuiltinType::Kind::OCLImage1dBuffer:
+ case clang::BuiltinType::Kind::OCLImage2d:
+ case clang::BuiltinType::Kind::OCLImage2dArray:
+ case clang::BuiltinType::Kind::OCLImage2dArrayDepth:
+ case clang::BuiltinType::Kind::OCLImage2dArrayMSAA:
+ case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepth:
+ case clang::BuiltinType::Kind::OCLImage2dDepth:
+ case clang::BuiltinType::Kind::OCLImage2dMSAA:
+ case clang::BuiltinType::Kind::OCLImage2dMSAADepth:
+ case clang::BuiltinType::Kind::OCLImage3d:
+ case clang::BuiltinType::Kind::OCLQueue:
+ case clang::BuiltinType::Kind::OCLNDRange:
+ case clang::BuiltinType::Kind::OCLReserveID:
+ case clang::BuiltinType::Kind::OCLSampler:
+ case clang::BuiltinType::Kind::OMPArraySection:
+ case clang::BuiltinType::Kind::Overload:
+ case clang::BuiltinType::Kind::PseudoObject:
+ case clang::BuiltinType::Kind::UnknownAny:
+ break;
+ }
+ break;
+ // All pointer types are represented as unsigned integer encodings.
+ // We may nee to add a eEncodingPointer if we ever need to know the
+ // difference
+ case clang::Type::ObjCObjectPointer:
+ case clang::Type::BlockPointer:
+ case clang::Type::Pointer:
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ case clang::Type::MemberPointer: return lldb::eEncodingUint;
+ case clang::Type::Complex:
+ {
+ lldb::Encoding encoding = lldb::eEncodingIEEE754;
+ if (qual_type->isComplexType())
+ encoding = lldb::eEncodingIEEE754;
+ else
+ {
+ const clang::ComplexType *complex_type = qual_type->getAsComplexIntegerType();
+ if (complex_type)
+ encoding = CompilerType(getASTContext(), complex_type->getElementType()).GetEncoding(count);
+ else
+ encoding = lldb::eEncodingSint;
+ }
+ count = 2;
+ return encoding;
+ }
+
+ case clang::Type::ObjCInterface: break;
+ case clang::Type::Record: break;
+ case clang::Type::Enum: return lldb::eEncodingSint;
+ case clang::Type::Typedef:
+ return CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetEncoding(count);
+
+ case clang::Type::Auto:
+ return CompilerType(getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetEncoding(count);
+
+ case clang::Type::Elaborated:
+ return CompilerType(getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetEncoding(count);
+
+ case clang::Type::Paren:
+ return CompilerType(getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetEncoding(count);
+
+ case clang::Type::DependentSizedArray:
+ case clang::Type::DependentSizedExtVector:
+ case clang::Type::UnresolvedUsing:
+ case clang::Type::Attributed:
+ case clang::Type::TemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParmPack:
+ case clang::Type::InjectedClassName:
+ case clang::Type::DependentName:
+ case clang::Type::DependentTemplateSpecialization:
+ case clang::Type::PackExpansion:
+ case clang::Type::ObjCObject:
+
+ case clang::Type::TypeOfExpr:
+ case clang::Type::TypeOf:
+ case clang::Type::Decltype:
+ case clang::Type::TemplateSpecialization:
+ case clang::Type::Atomic:
+ case clang::Type::Adjusted:
+ case clang::Type::Pipe:
+ break;
+
+ // pointer type decayed from an array or function type.
+ case clang::Type::Decayed:
+ break;
+ }
+ count = 0;
+ return lldb::eEncodingInvalid;
+}
+
+lldb::Format
+ClangASTContext::GetFormat (lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return lldb::eFormatDefault;
+
+ clang::QualType qual_type(GetCanonicalQualType(type));
+
+ switch (qual_type->getTypeClass())
+ {
+ case clang::Type::UnaryTransform:
+ break;
+
+ case clang::Type::FunctionNoProto:
+ case clang::Type::FunctionProto:
+ break;
+
+ case clang::Type::IncompleteArray:
+ case clang::Type::VariableArray:
+ break;
+
+ case clang::Type::ConstantArray:
+ return lldb::eFormatVoid; // no value
+
+ case clang::Type::ExtVector:
+ case clang::Type::Vector:
+ break;
+
+ case clang::Type::Builtin:
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
+ {
+ //default: assert(0 && "Unknown builtin type!");
+ case clang::BuiltinType::UnknownAny:
+ case clang::BuiltinType::Void:
+ case clang::BuiltinType::BoundMember:
+ break;
+
+ case clang::BuiltinType::Bool: return lldb::eFormatBoolean;
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::WChar_U: return lldb::eFormatChar;
+ case clang::BuiltinType::Char16: return lldb::eFormatUnicode16;
+ case clang::BuiltinType::Char32: return lldb::eFormatUnicode32;
+ case clang::BuiltinType::UShort: return lldb::eFormatUnsigned;
+ case clang::BuiltinType::Short: return lldb::eFormatDecimal;
+ case clang::BuiltinType::UInt: return lldb::eFormatUnsigned;
+ case clang::BuiltinType::Int: return lldb::eFormatDecimal;
+ case clang::BuiltinType::ULong: return lldb::eFormatUnsigned;
+ case clang::BuiltinType::Long: return lldb::eFormatDecimal;
+ case clang::BuiltinType::ULongLong: return lldb::eFormatUnsigned;
+ case clang::BuiltinType::LongLong: return lldb::eFormatDecimal;
+ case clang::BuiltinType::UInt128: return lldb::eFormatUnsigned;
+ case clang::BuiltinType::Int128: return lldb::eFormatDecimal;
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::LongDouble: return lldb::eFormatFloat;
+ default:
+ return lldb::eFormatHex;
+ }
+ break;
+ case clang::Type::ObjCObjectPointer: return lldb::eFormatHex;
+ case clang::Type::BlockPointer: return lldb::eFormatHex;
+ case clang::Type::Pointer: return lldb::eFormatHex;
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference: return lldb::eFormatHex;
+ case clang::Type::MemberPointer: break;
+ case clang::Type::Complex:
+ {
+ if (qual_type->isComplexType())
+ return lldb::eFormatComplex;
+ else
+ return lldb::eFormatComplexInteger;
+ }
+ case clang::Type::ObjCInterface: break;
+ case clang::Type::Record: break;
+ case clang::Type::Enum: return lldb::eFormatEnum;
+ case clang::Type::Typedef:
+ return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetFormat();
+ case clang::Type::Auto:
+ return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->desugar()).GetFormat();
+ case clang::Type::Paren:
+ return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetFormat();
+ case clang::Type::Elaborated:
+ return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetFormat();
+ case clang::Type::DependentSizedArray:
+ case clang::Type::DependentSizedExtVector:
+ case clang::Type::UnresolvedUsing:
+ case clang::Type::Attributed:
+ case clang::Type::TemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParmPack:
+ case clang::Type::InjectedClassName:
+ case clang::Type::DependentName:
+ case clang::Type::DependentTemplateSpecialization:
+ case clang::Type::PackExpansion:
+ case clang::Type::ObjCObject:
+
+ case clang::Type::TypeOfExpr:
+ case clang::Type::TypeOf:
+ case clang::Type::Decltype:
+ case clang::Type::TemplateSpecialization:
+ case clang::Type::Atomic:
+ case clang::Type::Adjusted:
+ case clang::Type::Pipe:
+ break;
+
+ // pointer type decayed from an array or function type.
+ case clang::Type::Decayed:
+ break;
+ }
+ // We don't know hot to display this type...
+ return lldb::eFormatBytes;
+}
+
+static bool
+ObjCDeclHasIVars (clang::ObjCInterfaceDecl *class_interface_decl, bool check_superclass)
+{
+ while (class_interface_decl)
+ {
+ if (class_interface_decl->ivar_size() > 0)
return true;
+
+ if (check_superclass)
+ class_interface_decl = class_interface_decl->getSuperClass();
+ else
+ break;
+ }
+ return false;
+}
+
+uint32_t
+ClangASTContext::GetNumChildren (lldb::opaque_compiler_type_t type, bool omit_empty_base_classes)
+{
+ if (!type)
+ return 0;
+
+ uint32_t num_children = 0;
+ clang::QualType qual_type(GetQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Builtin:
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
+ {
+ case clang::BuiltinType::ObjCId: // child is Class
+ case clang::BuiltinType::ObjCClass: // child is Class
+ num_children = 1;
+ break;
+
+ default:
+ break;
}
- else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_ctx))
+ break;
+
+ case clang::Type::Complex: return 0;
+
+ case clang::Type::Record:
+ if (GetCompleteQualType (getASTContext(), qual_type))
+ {
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ assert(record_decl);
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+ if (cxx_record_decl)
+ {
+ if (omit_empty_base_classes)
+ {
+ // Check each base classes to see if it or any of its
+ // base classes contain any fields. This can help
+ // limit the noise in variable views by not having to
+ // show base classes that contain no members.
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+ base_class != base_class_end;
+ ++base_class)
+ {
+ const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
+
+ // Skip empty base classes
+ if (ClangASTContext::RecordHasFields(base_class_decl) == false)
+ continue;
+
+ num_children++;
+ }
+ }
+ else
+ {
+ // Include all base classes
+ num_children += cxx_record_decl->getNumBases();
+ }
+
+ }
+ clang::RecordDecl::field_iterator field, field_end;
+ for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field)
+ ++num_children;
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ if (GetCompleteQualType (getASTContext(), qual_type))
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+ assert (objc_class_type);
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
+ if (class_interface_decl)
+ {
+
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+ if (superclass_interface_decl)
+ {
+ if (omit_empty_base_classes)
+ {
+ if (ObjCDeclHasIVars (superclass_interface_decl, true))
+ ++num_children;
+ }
+ else
+ ++num_children;
+ }
+
+ num_children += class_interface_decl->ivar_size();
+ }
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObjectPointer:
+ {
+ const clang::ObjCObjectPointerType *pointer_type = llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr());
+ clang::QualType pointee_type = pointer_type->getPointeeType();
+ uint32_t num_pointee_children = CompilerType (getASTContext(),pointee_type).GetNumChildren (omit_empty_base_classes);
+ // If this type points to a simple type, then it has 1 child
+ if (num_pointee_children == 0)
+ num_children = 1;
+ else
+ num_children = num_pointee_children;
+ }
+ break;
+
+ case clang::Type::Vector:
+ case clang::Type::ExtVector:
+ num_children = llvm::cast<clang::VectorType>(qual_type.getTypePtr())->getNumElements();
+ break;
+
+ case clang::Type::ConstantArray:
+ num_children = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue();
+ break;
+
+ case clang::Type::Pointer:
{
- // Both static and instance methods have a "self" object in objective C
- language_object_name.SetCString("self");
- if (method_decl->isInstanceMethod())
+ const clang::PointerType *pointer_type = llvm::cast<clang::PointerType>(qual_type.getTypePtr());
+ clang::QualType pointee_type (pointer_type->getPointeeType());
+ uint32_t num_pointee_children = CompilerType (getASTContext(),pointee_type).GetNumChildren (omit_empty_base_classes);
+ if (num_pointee_children == 0)
{
- is_instance_method = true;
+ // We have a pointer to a pointee type that claims it has no children.
+ // We will want to look at
+ num_children = GetNumPointeeChildren (pointee_type);
}
else
+ num_children = num_pointee_children;
+ }
+ break;
+
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ {
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+ clang::QualType pointee_type = reference_type->getPointeeType();
+ uint32_t num_pointee_children = CompilerType (getASTContext(), pointee_type).GetNumChildren (omit_empty_base_classes);
+ // If this type points to a simple type, then it has 1 child
+ if (num_pointee_children == 0)
+ num_children = 1;
+ else
+ num_children = num_pointee_children;
+ }
+ break;
+
+
+ case clang::Type::Typedef:
+ num_children = CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumChildren (omit_empty_base_classes);
+ break;
+
+ case clang::Type::Auto:
+ num_children = CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetNumChildren (omit_empty_base_classes);
+ break;
+
+ case clang::Type::Elaborated:
+ num_children = CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumChildren (omit_empty_base_classes);
+ break;
+
+ case clang::Type::Paren:
+ num_children = CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumChildren (omit_empty_base_classes);
+ break;
+ default:
+ break;
+ }
+ return num_children;
+}
+
+CompilerType
+ClangASTContext::GetBuiltinTypeByName (const ConstString &name)
+{
+ return GetBasicType (GetBasicTypeEnumeration (name));
+}
+
+lldb::BasicType
+ClangASTContext::GetBasicTypeEnumeration (lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ {
+ clang::QualType qual_type(GetQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ if (type_class == clang::Type::Builtin)
+ {
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
+ {
+ case clang::BuiltinType::Void: return eBasicTypeVoid;
+ case clang::BuiltinType::Bool: return eBasicTypeBool;
+ case clang::BuiltinType::Char_S: return eBasicTypeSignedChar;
+ case clang::BuiltinType::Char_U: return eBasicTypeUnsignedChar;
+ case clang::BuiltinType::Char16: return eBasicTypeChar16;
+ case clang::BuiltinType::Char32: return eBasicTypeChar32;
+ case clang::BuiltinType::UChar: return eBasicTypeUnsignedChar;
+ case clang::BuiltinType::SChar: return eBasicTypeSignedChar;
+ case clang::BuiltinType::WChar_S: return eBasicTypeSignedWChar;
+ case clang::BuiltinType::WChar_U: return eBasicTypeUnsignedWChar;
+ case clang::BuiltinType::Short: return eBasicTypeShort;
+ case clang::BuiltinType::UShort: return eBasicTypeUnsignedShort;
+ case clang::BuiltinType::Int: return eBasicTypeInt;
+ case clang::BuiltinType::UInt: return eBasicTypeUnsignedInt;
+ case clang::BuiltinType::Long: return eBasicTypeLong;
+ case clang::BuiltinType::ULong: return eBasicTypeUnsignedLong;
+ case clang::BuiltinType::LongLong: return eBasicTypeLongLong;
+ case clang::BuiltinType::ULongLong: return eBasicTypeUnsignedLongLong;
+ case clang::BuiltinType::Int128: return eBasicTypeInt128;
+ case clang::BuiltinType::UInt128: return eBasicTypeUnsignedInt128;
+
+ case clang::BuiltinType::Half: return eBasicTypeHalf;
+ case clang::BuiltinType::Float: return eBasicTypeFloat;
+ case clang::BuiltinType::Double: return eBasicTypeDouble;
+ case clang::BuiltinType::LongDouble:return eBasicTypeLongDouble;
+
+ case clang::BuiltinType::NullPtr: return eBasicTypeNullPtr;
+ case clang::BuiltinType::ObjCId: return eBasicTypeObjCID;
+ case clang::BuiltinType::ObjCClass: return eBasicTypeObjCClass;
+ case clang::BuiltinType::ObjCSel: return eBasicTypeObjCSel;
+ default:
+ return eBasicTypeOther;
+ }
+ }
+ }
+ return eBasicTypeInvalid;
+}
+
+void
+ClangASTContext::ForEachEnumerator (lldb::opaque_compiler_type_t type, std::function <bool (const CompilerType &integer_type, const ConstString &name, const llvm::APSInt &value)> const &callback)
+{
+ const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type));
+ if (enum_type)
+ {
+ const clang::EnumDecl *enum_decl = enum_type->getDecl();
+ if (enum_decl)
+ {
+ CompilerType integer_type(this, enum_decl->getIntegerType().getAsOpaquePtr());
+
+ clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
+ for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
+ {
+ ConstString name(enum_pos->getNameAsString().c_str());
+ if (!callback (integer_type, name, enum_pos->getInitVal()))
+ break;
+ }
+ }
+ }
+}
+
+
+#pragma mark Aggregate Types
+
+uint32_t
+ClangASTContext::GetNumFields (lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return 0;
+
+ uint32_t count = 0;
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
{
- is_instance_method = false;
+ const clang::RecordType *record_type = llvm::dyn_cast<clang::RecordType>(qual_type.getTypePtr());
+ if (record_type)
+ {
+ clang::RecordDecl *record_decl = record_type->getDecl();
+ if (record_decl)
+ {
+ uint32_t field_idx = 0;
+ clang::RecordDecl::field_iterator field, field_end;
+ for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field)
+ ++field_idx;
+ count = field_idx;
+ }
+ }
}
- language = eLanguageTypeObjC;
+ break;
+
+ case clang::Type::Typedef:
+ count = CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumFields();
+ break;
+
+ case clang::Type::Auto:
+ count = CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetNumFields();
+ break;
+
+ case clang::Type::Elaborated:
+ count = CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumFields();
+ break;
+
+ case clang::Type::Paren:
+ count = CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumFields();
+ break;
+
+ case clang::Type::ObjCObjectPointer:
+ if (GetCompleteType(type))
+ {
+ const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
+
+ if (class_interface_decl)
+ count = class_interface_decl->ivar_size();
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ if (GetCompleteType(type))
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
+ if (class_interface_decl)
+ count = class_interface_decl->ivar_size();
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ return count;
+}
+
+static lldb::opaque_compiler_type_t
+GetObjCFieldAtIndex (clang::ASTContext *ast,
+ clang::ObjCInterfaceDecl *class_interface_decl,
+ size_t idx,
+ std::string& name,
+ uint64_t *bit_offset_ptr,
+ uint32_t *bitfield_bit_size_ptr,
+ bool *is_bitfield_ptr)
+{
+ if (class_interface_decl)
+ {
+ if (idx < (class_interface_decl->ivar_size()))
+ {
+ clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
+ uint32_t ivar_idx = 0;
+
+ for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++ivar_idx)
+ {
+ if (ivar_idx == idx)
+ {
+ const clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
+
+ clang::QualType ivar_qual_type(ivar_decl->getType());
+
+ name.assign(ivar_decl->getNameAsString());
+
+ if (bit_offset_ptr)
+ {
+ const clang::ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl);
+ *bit_offset_ptr = interface_layout.getFieldOffset (ivar_idx);
+ }
+
+ const bool is_bitfield = ivar_pos->isBitField();
+
+ if (bitfield_bit_size_ptr)
+ {
+ *bitfield_bit_size_ptr = 0;
+
+ if (is_bitfield && ast)
+ {
+ clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth();
+ llvm::APSInt bitfield_apsint;
+ if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *ast))
+ {
+ *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
+ }
+ }
+ }
+ if (is_bitfield_ptr)
+ *is_bitfield_ptr = is_bitfield;
+
+ return ivar_qual_type.getAsOpaquePtr();
+ }
+ }
+ }
+ }
+ return nullptr;
+}
+
+CompilerType
+ClangASTContext::GetFieldAtIndex (lldb::opaque_compiler_type_t type, size_t idx,
+ std::string& name,
+ uint64_t *bit_offset_ptr,
+ uint32_t *bitfield_bit_size_ptr,
+ bool *is_bitfield_ptr)
+{
+ if (!type)
+ return CompilerType();
+
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
+ {
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ uint32_t field_idx = 0;
+ clang::RecordDecl::field_iterator field, field_end;
+ for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx)
+ {
+ if (idx == field_idx)
+ {
+ // Print the member type if requested
+ // Print the member name and equal sign
+ name.assign(field->getNameAsString());
+
+ // Figure out the type byte size (field_type_info.first) and
+ // alignment (field_type_info.second) from the AST context.
+ if (bit_offset_ptr)
+ {
+ const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(record_decl);
+ *bit_offset_ptr = record_layout.getFieldOffset (field_idx);
+ }
+
+ const bool is_bitfield = field->isBitField();
+
+ if (bitfield_bit_size_ptr)
+ {
+ *bitfield_bit_size_ptr = 0;
+
+ if (is_bitfield)
+ {
+ clang::Expr *bitfield_bit_size_expr = field->getBitWidth();
+ llvm::APSInt bitfield_apsint;
+ if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *getASTContext()))
+ {
+ *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
+ }
+ }
+ }
+ if (is_bitfield_ptr)
+ *is_bitfield_ptr = is_bitfield;
+
+ return CompilerType (getASTContext(), field->getType());
+ }
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObjectPointer:
+ if (GetCompleteType(type))
+ {
+ const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
+ return CompilerType (this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr));
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ if (GetCompleteType(type))
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+ assert (objc_class_type);
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ return CompilerType (this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr));
+ }
+ }
+ break;
+
+
+ case clang::Type::Typedef:
+ return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).
+ GetFieldAtIndex (idx,
+ name,
+ bit_offset_ptr,
+ bitfield_bit_size_ptr,
+ is_bitfield_ptr);
+
+ case clang::Type::Auto:
+ return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).
+ GetFieldAtIndex (idx,
+ name,
+ bit_offset_ptr,
+ bitfield_bit_size_ptr,
+ is_bitfield_ptr);
+
+ case clang::Type::Elaborated:
+ return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).
+ GetFieldAtIndex (idx,
+ name,
+ bit_offset_ptr,
+ bitfield_bit_size_ptr,
+ is_bitfield_ptr);
+
+ case clang::Type::Paren:
+ return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).
+ GetFieldAtIndex (idx,
+ name,
+ bit_offset_ptr,
+ bitfield_bit_size_ptr,
+ is_bitfield_ptr);
+
+ default:
+ break;
+ }
+ return CompilerType();
+}
+
+uint32_t
+ClangASTContext::GetNumDirectBaseClasses (lldb::opaque_compiler_type_t type)
+{
+ uint32_t count = 0;
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ count = cxx_record_decl->getNumBases();
+ }
+ break;
+
+ case clang::Type::ObjCObjectPointer:
+ count = GetPointeeType(type).GetNumDirectBaseClasses();
+ break;
+
+ case clang::Type::ObjCObject:
+ if (GetCompleteType(type))
+ {
+ const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
+ if (class_interface_decl && class_interface_decl->getSuperClass())
+ count = 1;
+ }
+ }
+ break;
+ case clang::Type::ObjCInterface:
+ if (GetCompleteType(type))
+ {
+ const clang::ObjCInterfaceType *objc_interface_type = qual_type->getAs<clang::ObjCInterfaceType>();
+ if (objc_interface_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
+
+ if (class_interface_decl && class_interface_decl->getSuperClass())
+ count = 1;
+ }
+ }
+ break;
+
+
+ case clang::Type::Typedef:
+ count = GetNumDirectBaseClasses(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr());
+ break;
+
+ case clang::Type::Auto:
+ count = GetNumDirectBaseClasses(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr());
+ break;
+
+ case clang::Type::Elaborated:
+ count = GetNumDirectBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr());
+ break;
+
+ case clang::Type::Paren:
+ return GetNumDirectBaseClasses(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr());
+
+ default:
+ break;
+ }
+ return count;
+
+}
+
+uint32_t
+ClangASTContext::GetNumVirtualBaseClasses (lldb::opaque_compiler_type_t type)
+{
+ uint32_t count = 0;
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ count = cxx_record_decl->getNumVBases();
+ }
+ break;
+
+ case clang::Type::Typedef:
+ count = GetNumVirtualBaseClasses(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr());
+ break;
+
+ case clang::Type::Auto:
+ count = GetNumVirtualBaseClasses(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr());
+ break;
+
+ case clang::Type::Elaborated:
+ count = GetNumVirtualBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr());
+ break;
+
+ case clang::Type::Paren:
+ count = GetNumVirtualBaseClasses(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr());
+ break;
+
+ default:
+ break;
+ }
+ return count;
+
+}
+
+CompilerType
+ClangASTContext::GetDirectBaseClassAtIndex (lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr)
+{
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ uint32_t curr_idx = 0;
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+ base_class != base_class_end;
+ ++base_class, ++curr_idx)
+ {
+ if (curr_idx == idx)
+ {
+ if (bit_offset_ptr)
+ {
+ const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(cxx_record_decl);
+ const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
+ if (base_class->isVirtual())
+ *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
+ else
+ *bit_offset_ptr = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8;
+ }
+ return CompilerType (this, base_class->getType().getAsOpaquePtr());
+ }
+ }
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObjectPointer:
+ return GetPointeeType(type).GetDirectBaseClassAtIndex(idx, bit_offset_ptr);
+
+ case clang::Type::ObjCObject:
+ if (idx == 0 && GetCompleteType(type))
+ {
+ const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
+ if (class_interface_decl)
+ {
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+ if (superclass_interface_decl)
+ {
+ if (bit_offset_ptr)
+ *bit_offset_ptr = 0;
+ return CompilerType (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl));
+ }
+ }
+ }
+ }
+ break;
+ case clang::Type::ObjCInterface:
+ if (idx == 0 && GetCompleteType(type))
+ {
+ const clang::ObjCObjectType *objc_interface_type = qual_type->getAs<clang::ObjCInterfaceType>();
+ if (objc_interface_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
+
+ if (class_interface_decl)
+ {
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+ if (superclass_interface_decl)
+ {
+ if (bit_offset_ptr)
+ *bit_offset_ptr = 0;
+ return CompilerType (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl));
+ }
+ }
+ }
+ }
+ break;
+
+
+ case clang::Type::Typedef:
+ return GetDirectBaseClassAtIndex (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), idx, bit_offset_ptr);
+
+ case clang::Type::Auto:
+ return GetDirectBaseClassAtIndex (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), idx, bit_offset_ptr);
+
+ case clang::Type::Elaborated:
+ return GetDirectBaseClassAtIndex (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), idx, bit_offset_ptr);
+
+ case clang::Type::Paren:
+ return GetDirectBaseClassAtIndex (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), idx, bit_offset_ptr);
+
+ default:
+ break;
+ }
+ return CompilerType();
+}
+
+CompilerType
+ClangASTContext::GetVirtualBaseClassAtIndex (lldb::opaque_compiler_type_t type,
+ size_t idx,
+ uint32_t *bit_offset_ptr)
+{
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ uint32_t curr_idx = 0;
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ for (base_class = cxx_record_decl->vbases_begin(), base_class_end = cxx_record_decl->vbases_end();
+ base_class != base_class_end;
+ ++base_class, ++curr_idx)
+ {
+ if (curr_idx == idx)
+ {
+ if (bit_offset_ptr)
+ {
+ const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(cxx_record_decl);
+ const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
+ *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
+
+ }
+ return CompilerType (this, base_class->getType().getAsOpaquePtr());
+ }
+ }
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ return GetVirtualBaseClassAtIndex (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), idx, bit_offset_ptr);
+
+ case clang::Type::Auto:
+ return GetVirtualBaseClassAtIndex (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), idx, bit_offset_ptr);
+
+ case clang::Type::Elaborated:
+ return GetVirtualBaseClassAtIndex (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), idx, bit_offset_ptr);
+
+ case clang::Type::Paren:
+ return GetVirtualBaseClassAtIndex (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), idx, bit_offset_ptr);
+
+ default:
+ break;
+ }
+ return CompilerType();
+
+}
+
+// If a pointer to a pointee type (the clang_type arg) says that it has no
+// children, then we either need to trust it, or override it and return a
+// different result. For example, an "int *" has one child that is an integer,
+// but a function pointer doesn't have any children. Likewise if a Record type
+// claims it has no children, then there really is nothing to show.
+uint32_t
+ClangASTContext::GetNumPointeeChildren (clang::QualType type)
+{
+ if (type.isNull())
+ return 0;
+
+ clang::QualType qual_type(type.getCanonicalType());
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Builtin:
+ switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
+ {
+ case clang::BuiltinType::UnknownAny:
+ case clang::BuiltinType::Void:
+ case clang::BuiltinType::NullPtr:
+ case clang::BuiltinType::OCLEvent:
+ case clang::BuiltinType::OCLImage1d:
+ case clang::BuiltinType::OCLImage1dArray:
+ case clang::BuiltinType::OCLImage1dBuffer:
+ case clang::BuiltinType::OCLImage2d:
+ case clang::BuiltinType::OCLImage2dArray:
+ case clang::BuiltinType::OCLImage3d:
+ case clang::BuiltinType::OCLSampler:
+ return 0;
+ case clang::BuiltinType::Bool:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::Int128:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::LongDouble:
+ case clang::BuiltinType::Dependent:
+ case clang::BuiltinType::Overload:
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCSel:
+ case clang::BuiltinType::BoundMember:
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::ARCUnbridgedCast:
+ case clang::BuiltinType::PseudoObject:
+ case clang::BuiltinType::BuiltinFn:
+ case clang::BuiltinType::OMPArraySection:
+ return 1;
+ default:
+ return 0;
+ }
+ break;
+
+ case clang::Type::Complex: return 1;
+ case clang::Type::Pointer: return 1;
+ case clang::Type::BlockPointer: return 0; // If block pointers don't have debug info, then no children for them
+ case clang::Type::LValueReference: return 1;
+ case clang::Type::RValueReference: return 1;
+ case clang::Type::MemberPointer: return 0;
+ case clang::Type::ConstantArray: return 0;
+ case clang::Type::IncompleteArray: return 0;
+ case clang::Type::VariableArray: return 0;
+ case clang::Type::DependentSizedArray: return 0;
+ case clang::Type::DependentSizedExtVector: return 0;
+ case clang::Type::Vector: return 0;
+ case clang::Type::ExtVector: return 0;
+ case clang::Type::FunctionProto: return 0; // When we function pointers, they have no children...
+ case clang::Type::FunctionNoProto: return 0; // When we function pointers, they have no children...
+ case clang::Type::UnresolvedUsing: return 0;
+ case clang::Type::Paren: return GetNumPointeeChildren (llvm::cast<clang::ParenType>(qual_type)->desugar());
+ case clang::Type::Typedef: return GetNumPointeeChildren (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType());
+ case clang::Type::Auto: return GetNumPointeeChildren (llvm::cast<clang::AutoType>(qual_type)->getDeducedType());
+ case clang::Type::Elaborated: return GetNumPointeeChildren (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType());
+ case clang::Type::TypeOfExpr: return 0;
+ case clang::Type::TypeOf: return 0;
+ case clang::Type::Decltype: return 0;
+ case clang::Type::Record: return 0;
+ case clang::Type::Enum: return 1;
+ case clang::Type::TemplateTypeParm: return 1;
+ case clang::Type::SubstTemplateTypeParm: return 1;
+ case clang::Type::TemplateSpecialization: return 1;
+ case clang::Type::InjectedClassName: return 0;
+ case clang::Type::DependentName: return 1;
+ case clang::Type::DependentTemplateSpecialization: return 1;
+ case clang::Type::ObjCObject: return 0;
+ case clang::Type::ObjCInterface: return 0;
+ case clang::Type::ObjCObjectPointer: return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+CompilerType
+ClangASTContext::GetChildCompilerTypeAtIndex (lldb::opaque_compiler_type_t type,
+ ExecutionContext *exe_ctx,
+ size_t idx,
+ bool transparent_pointers,
+ bool omit_empty_base_classes,
+ bool ignore_array_bounds,
+ std::string& child_name,
+ uint32_t &child_byte_size,
+ int32_t &child_byte_offset,
+ uint32_t &child_bitfield_bit_size,
+ uint32_t &child_bitfield_bit_offset,
+ bool &child_is_base_class,
+ bool &child_is_deref_of_parent,
+ ValueObject *valobj,
+ uint64_t &language_flags)
+{
+ if (!type)
+ return CompilerType();
+
+ clang::QualType parent_qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass parent_type_class = parent_qual_type->getTypeClass();
+ child_bitfield_bit_size = 0;
+ child_bitfield_bit_offset = 0;
+ child_is_base_class = false;
+ language_flags = 0;
+
+ const bool idx_is_valid = idx < GetNumChildren (type, omit_empty_base_classes);
+ uint32_t bit_offset;
+ switch (parent_type_class)
+ {
+ case clang::Type::Builtin:
+ if (idx_is_valid)
+ {
+ switch (llvm::cast<clang::BuiltinType>(parent_qual_type)->getKind())
+ {
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ child_name = "isa";
+ child_byte_size = getASTContext()->getTypeSize(getASTContext()->ObjCBuiltinClassTy) / CHAR_BIT;
+ return CompilerType (getASTContext(), getASTContext()->ObjCBuiltinClassTy);
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case clang::Type::Record:
+ if (idx_is_valid && GetCompleteType(type))
+ {
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(parent_qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ assert(record_decl);
+ const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(record_decl);
+ uint32_t child_idx = 0;
+
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+ if (cxx_record_decl)
+ {
+ // We might have base classes to print out first
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+ base_class != base_class_end;
+ ++base_class)
+ {
+ const clang::CXXRecordDecl *base_class_decl = nullptr;
+
+ // Skip empty base classes
+ if (omit_empty_base_classes)
+ {
+ base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
+ if (ClangASTContext::RecordHasFields(base_class_decl) == false)
+ continue;
+ }
+
+ if (idx == child_idx)
+ {
+ if (base_class_decl == nullptr)
+ base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
+
+
+ if (base_class->isVirtual())
+ {
+ bool handled = false;
+ if (valobj)
+ {
+ Error err;
+ AddressType addr_type = eAddressTypeInvalid;
+ lldb::addr_t vtable_ptr_addr = valobj->GetCPPVTableAddress(addr_type);
+
+ if (vtable_ptr_addr != LLDB_INVALID_ADDRESS && addr_type == eAddressTypeLoad)
+ {
+
+ ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process)
+ {
+ clang::VTableContextBase *vtable_ctx = getASTContext()->getVTableContext();
+ if (vtable_ctx)
+ {
+ if (vtable_ctx->isMicrosoft())
+ {
+ clang::MicrosoftVTableContext *msoft_vtable_ctx = static_cast<clang::MicrosoftVTableContext *>(vtable_ctx);
+
+ if (vtable_ptr_addr)
+ {
+ const lldb::addr_t vbtable_ptr_addr = vtable_ptr_addr + record_layout.getVBPtrOffset().getQuantity();
+
+ const lldb::addr_t vbtable_ptr = process->ReadPointerFromMemory(vbtable_ptr_addr, err);
+ if (vbtable_ptr != LLDB_INVALID_ADDRESS)
+ {
+ // Get the index into the virtual base table. The index is the index in uint32_t from vbtable_ptr
+ const unsigned vbtable_index = msoft_vtable_ctx->getVBTableIndex(cxx_record_decl, base_class_decl);
+ const lldb::addr_t base_offset_addr = vbtable_ptr + vbtable_index * 4;
+ const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err);
+ if (base_offset != UINT32_MAX)
+ {
+ handled = true;
+ bit_offset = base_offset * 8;
+ }
+ }
+ }
+ }
+ else
+ {
+ clang::ItaniumVTableContext *itanium_vtable_ctx = static_cast<clang::ItaniumVTableContext *>(vtable_ctx);
+ if (vtable_ptr_addr)
+ {
+ const lldb::addr_t vtable_ptr = process->ReadPointerFromMemory(vtable_ptr_addr, err);
+ if (vtable_ptr != LLDB_INVALID_ADDRESS)
+ {
+ clang::CharUnits base_offset_offset = itanium_vtable_ctx->getVirtualBaseOffsetOffset(cxx_record_decl, base_class_decl);
+ const lldb::addr_t base_offset_addr = vtable_ptr + base_offset_offset.getQuantity();
+ const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err);
+ if (base_offset != UINT32_MAX)
+ {
+ handled = true;
+ bit_offset = base_offset * 8;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+ if (!handled)
+ bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
+ }
+ else
+ bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8;
+
+ // Base classes should be a multiple of 8 bits in size
+ child_byte_offset = bit_offset/8;
+ CompilerType base_class_clang_type(getASTContext(), base_class->getType());
+ child_name = base_class_clang_type.GetTypeName().AsCString("");
+ uint64_t base_class_clang_type_bit_size = base_class_clang_type.GetBitSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+
+ // Base classes bit sizes should be a multiple of 8 bits in size
+ assert (base_class_clang_type_bit_size % 8 == 0);
+ child_byte_size = base_class_clang_type_bit_size / 8;
+ child_is_base_class = true;
+ return base_class_clang_type;
+ }
+ // We don't increment the child index in the for loop since we might
+ // be skipping empty base classes
+ ++child_idx;
+ }
+ }
+ // Make sure index is in range...
+ uint32_t field_idx = 0;
+ clang::RecordDecl::field_iterator field, field_end;
+ for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx)
+ {
+ if (idx == child_idx)
+ {
+ // Print the member type if requested
+ // Print the member name and equal sign
+ child_name.assign(field->getNameAsString().c_str());
+
+ // Figure out the type byte size (field_type_info.first) and
+ // alignment (field_type_info.second) from the AST context.
+ CompilerType field_clang_type (getASTContext(), field->getType());
+ assert(field_idx < record_layout.getFieldCount());
+ child_byte_size = field_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+
+ // Figure out the field offset within the current struct/union/class type
+ bit_offset = record_layout.getFieldOffset (field_idx);
+ child_byte_offset = bit_offset / 8;
+ if (ClangASTContext::FieldIsBitfield (getASTContext(), *field, child_bitfield_bit_size))
+ child_bitfield_bit_offset = bit_offset % 8;
+
+ return field_clang_type;
+ }
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ if (idx_is_valid && GetCompleteType(type))
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(parent_qual_type.getTypePtr());
+ assert (objc_class_type);
+ if (objc_class_type)
+ {
+ uint32_t child_idx = 0;
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
+ if (class_interface_decl)
+ {
+
+ const clang::ASTRecordLayout &interface_layout = getASTContext()->getASTObjCInterfaceLayout(class_interface_decl);
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+ if (superclass_interface_decl)
+ {
+ if (omit_empty_base_classes)
+ {
+ CompilerType base_class_clang_type (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl));
+ if (base_class_clang_type.GetNumChildren(omit_empty_base_classes) > 0)
+ {
+ if (idx == 0)
+ {
+ clang::QualType ivar_qual_type(getASTContext()->getObjCInterfaceType(superclass_interface_decl));
+
+
+ child_name.assign(superclass_interface_decl->getNameAsString().c_str());
+
+ clang::TypeInfo ivar_type_info = getASTContext()->getTypeInfo(ivar_qual_type.getTypePtr());
+
+ child_byte_size = ivar_type_info.Width / 8;
+ child_byte_offset = 0;
+ child_is_base_class = true;
+
+ return CompilerType (getASTContext(), ivar_qual_type);
+ }
+
+ ++child_idx;
+ }
+ }
+ else
+ ++child_idx;
+ }
+
+ const uint32_t superclass_idx = child_idx;
+
+ if (idx < (child_idx + class_interface_decl->ivar_size()))
+ {
+ clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
+
+ for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos)
+ {
+ if (child_idx == idx)
+ {
+ clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
+
+ clang::QualType ivar_qual_type(ivar_decl->getType());
+
+ child_name.assign(ivar_decl->getNameAsString().c_str());
+
+ clang::TypeInfo ivar_type_info = getASTContext()->getTypeInfo(ivar_qual_type.getTypePtr());
+
+ child_byte_size = ivar_type_info.Width / 8;
+
+ // Figure out the field offset within the current struct/union/class type
+ // For ObjC objects, we can't trust the bit offset we get from the Clang AST, since
+ // that doesn't account for the space taken up by unbacked properties, or from
+ // the changing size of base classes that are newer than this class.
+ // So if we have a process around that we can ask about this object, do so.
+ child_byte_offset = LLDB_INVALID_IVAR_OFFSET;
+ Process *process = nullptr;
+ if (exe_ctx)
+ process = exe_ctx->GetProcessPtr();
+ if (process)
+ {
+ ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
+ if (objc_runtime != nullptr)
+ {
+ CompilerType parent_ast_type (getASTContext(), parent_qual_type);
+ child_byte_offset = objc_runtime->GetByteOffsetForIvar (parent_ast_type, ivar_decl->getNameAsString().c_str());
+ }
+ }
+
+ // Setting this to UINT32_MAX to make sure we don't compute it twice...
+ bit_offset = UINT32_MAX;
+
+ if (child_byte_offset == static_cast<int32_t>(LLDB_INVALID_IVAR_OFFSET))
+ {
+ bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx);
+ child_byte_offset = bit_offset / 8;
+ }
+
+ // Note, the ObjC Ivar Byte offset is just that, it doesn't account for the bit offset
+ // of a bitfield within its containing object. So regardless of where we get the byte
+ // offset from, we still need to get the bit offset for bitfields from the layout.
+
+ if (ClangASTContext::FieldIsBitfield (getASTContext(), ivar_decl, child_bitfield_bit_size))
+ {
+ if (bit_offset == UINT32_MAX)
+ bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx);
+
+ child_bitfield_bit_offset = bit_offset % 8;
+ }
+ return CompilerType (getASTContext(), ivar_qual_type);
+ }
+ ++child_idx;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObjectPointer:
+ if (idx_is_valid)
+ {
+ CompilerType pointee_clang_type (GetPointeeType(type));
+
+ if (transparent_pointers && pointee_clang_type.IsAggregateType())
+ {
+ child_is_deref_of_parent = false;
+ bool tmp_child_is_deref_of_parent = false;
+ return pointee_clang_type.GetChildCompilerTypeAtIndex (exe_ctx,
+ idx,
+ transparent_pointers,
+ omit_empty_base_classes,
+ ignore_array_bounds,
+ child_name,
+ child_byte_size,
+ child_byte_offset,
+ child_bitfield_bit_size,
+ child_bitfield_bit_offset,
+ child_is_base_class,
+ tmp_child_is_deref_of_parent,
+ valobj,
+ language_flags);
+ }
+ else
+ {
+ child_is_deref_of_parent = true;
+ const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL;
+ if (parent_name)
+ {
+ child_name.assign(1, '*');
+ child_name += parent_name;
+ }
+
+ // We have a pointer to an simple type
+ if (idx == 0 && pointee_clang_type.GetCompleteType())
+ {
+ child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+ child_byte_offset = 0;
+ return pointee_clang_type;
+ }
+ }
+ }
+ break;
+
+ case clang::Type::Vector:
+ case clang::Type::ExtVector:
+ if (idx_is_valid)
+ {
+ const clang::VectorType *array = llvm::cast<clang::VectorType>(parent_qual_type.getTypePtr());
+ if (array)
+ {
+ CompilerType element_type (getASTContext(), array->getElementType());
+ if (element_type.GetCompleteType())
+ {
+ char element_name[64];
+ ::snprintf (element_name, sizeof (element_name), "[%" PRIu64 "]", static_cast<uint64_t>(idx));
+ child_name.assign(element_name);
+ child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+ child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
+ return element_type;
+ }
+ }
+ }
+ break;
+
+ case clang::Type::ConstantArray:
+ case clang::Type::IncompleteArray:
+ if (ignore_array_bounds || idx_is_valid)
+ {
+ const clang::ArrayType *array = GetQualType(type)->getAsArrayTypeUnsafe();
+ if (array)
+ {
+ CompilerType element_type (getASTContext(), array->getElementType());
+ if (element_type.GetCompleteType())
+ {
+ char element_name[64];
+ ::snprintf (element_name, sizeof (element_name), "[%" PRIu64 "]", static_cast<uint64_t>(idx));
+ child_name.assign(element_name);
+ child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+ child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
+ return element_type;
+ }
+ }
+ }
+ break;
+
+
+ case clang::Type::Pointer:
+ if (idx_is_valid)
+ {
+ CompilerType pointee_clang_type (GetPointeeType(type));
+
+ // Don't dereference "void *" pointers
+ if (pointee_clang_type.IsVoidType())
+ return CompilerType();
+
+ if (transparent_pointers && pointee_clang_type.IsAggregateType ())
+ {
+ child_is_deref_of_parent = false;
+ bool tmp_child_is_deref_of_parent = false;
+ return pointee_clang_type.GetChildCompilerTypeAtIndex (exe_ctx,
+ idx,
+ transparent_pointers,
+ omit_empty_base_classes,
+ ignore_array_bounds,
+ child_name,
+ child_byte_size,
+ child_byte_offset,
+ child_bitfield_bit_size,
+ child_bitfield_bit_offset,
+ child_is_base_class,
+ tmp_child_is_deref_of_parent,
+ valobj,
+ language_flags);
+ }
+ else
+ {
+ child_is_deref_of_parent = true;
+
+ const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL;
+ if (parent_name)
+ {
+ child_name.assign(1, '*');
+ child_name += parent_name;
+ }
+
+ // We have a pointer to an simple type
+ if (idx == 0)
+ {
+ child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+ child_byte_offset = 0;
+ return pointee_clang_type;
+ }
+ }
+ }
+ break;
+
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ if (idx_is_valid)
+ {
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr());
+ CompilerType pointee_clang_type (getASTContext(), reference_type->getPointeeType());
+ if (transparent_pointers && pointee_clang_type.IsAggregateType ())
+ {
+ child_is_deref_of_parent = false;
+ bool tmp_child_is_deref_of_parent = false;
+ return pointee_clang_type.GetChildCompilerTypeAtIndex (exe_ctx,
+ idx,
+ transparent_pointers,
+ omit_empty_base_classes,
+ ignore_array_bounds,
+ child_name,
+ child_byte_size,
+ child_byte_offset,
+ child_bitfield_bit_size,
+ child_bitfield_bit_offset,
+ child_is_base_class,
+ tmp_child_is_deref_of_parent,
+ valobj,
+ language_flags);
+ }
+ else
+ {
+ const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL;
+ if (parent_name)
+ {
+ child_name.assign(1, '&');
+ child_name += parent_name;
+ }
+
+ // We have a pointer to an simple type
+ if (idx == 0)
+ {
+ child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+ child_byte_offset = 0;
+ return pointee_clang_type;
+ }
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ {
+ CompilerType typedefed_clang_type (getASTContext(), llvm::cast<clang::TypedefType>(parent_qual_type)->getDecl()->getUnderlyingType());
+ return typedefed_clang_type.GetChildCompilerTypeAtIndex (exe_ctx,
+ idx,
+ transparent_pointers,
+ omit_empty_base_classes,
+ ignore_array_bounds,
+ child_name,
+ child_byte_size,
+ child_byte_offset,
+ child_bitfield_bit_size,
+ child_bitfield_bit_offset,
+ child_is_base_class,
+ child_is_deref_of_parent,
+ valobj,
+ language_flags);
+ }
+ break;
+
+ case clang::Type::Auto:
+ {
+ CompilerType elaborated_clang_type (getASTContext(), llvm::cast<clang::AutoType>(parent_qual_type)->getDeducedType());
+ return elaborated_clang_type.GetChildCompilerTypeAtIndex (exe_ctx,
+ idx,
+ transparent_pointers,
+ omit_empty_base_classes,
+ ignore_array_bounds,
+ child_name,
+ child_byte_size,
+ child_byte_offset,
+ child_bitfield_bit_size,
+ child_bitfield_bit_offset,
+ child_is_base_class,
+ child_is_deref_of_parent,
+ valobj,
+ language_flags);
+ }
+
+ case clang::Type::Elaborated:
+ {
+ CompilerType elaborated_clang_type (getASTContext(), llvm::cast<clang::ElaboratedType>(parent_qual_type)->getNamedType());
+ return elaborated_clang_type.GetChildCompilerTypeAtIndex (exe_ctx,
+ idx,
+ transparent_pointers,
+ omit_empty_base_classes,
+ ignore_array_bounds,
+ child_name,
+ child_byte_size,
+ child_byte_offset,
+ child_bitfield_bit_size,
+ child_bitfield_bit_offset,
+ child_is_base_class,
+ child_is_deref_of_parent,
+ valobj,
+ language_flags);
+ }
+
+ case clang::Type::Paren:
+ {
+ CompilerType paren_clang_type (getASTContext(), llvm::cast<clang::ParenType>(parent_qual_type)->desugar());
+ return paren_clang_type.GetChildCompilerTypeAtIndex (exe_ctx,
+ idx,
+ transparent_pointers,
+ omit_empty_base_classes,
+ ignore_array_bounds,
+ child_name,
+ child_byte_size,
+ child_byte_offset,
+ child_bitfield_bit_size,
+ child_bitfield_bit_offset,
+ child_is_base_class,
+ child_is_deref_of_parent,
+ valobj,
+ language_flags);
+ }
+
+
+ default:
+ break;
+ }
+ return CompilerType();
+}
+
+static uint32_t
+GetIndexForRecordBase
+(
+ const clang::RecordDecl *record_decl,
+ const clang::CXXBaseSpecifier *base_spec,
+ bool omit_empty_base_classes
+ )
+{
+ uint32_t child_idx = 0;
+
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+
+ // const char *super_name = record_decl->getNameAsCString();
+ // const char *base_name = base_spec->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString();
+ // printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name);
+ //
+ if (cxx_record_decl)
+ {
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+ base_class != base_class_end;
+ ++base_class)
+ {
+ if (omit_empty_base_classes)
+ {
+ if (BaseSpecifierIsEmpty (base_class))
+ continue;
+ }
+
+ // printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n", super_name, base_name,
+ // child_idx,
+ // base_class->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString());
+ //
+ //
+ if (base_class == base_spec)
+ return child_idx;
+ ++child_idx;
+ }
+ }
+
+ return UINT32_MAX;
+}
+
+
+static uint32_t
+GetIndexForRecordChild (const clang::RecordDecl *record_decl,
+ clang::NamedDecl *canonical_decl,
+ bool omit_empty_base_classes)
+{
+ uint32_t child_idx = ClangASTContext::GetNumBaseClasses (llvm::dyn_cast<clang::CXXRecordDecl>(record_decl),
+ omit_empty_base_classes);
+
+ clang::RecordDecl::field_iterator field, field_end;
+ for (field = record_decl->field_begin(), field_end = record_decl->field_end();
+ field != field_end;
+ ++field, ++child_idx)
+ {
+ if (field->getCanonicalDecl() == canonical_decl)
+ return child_idx;
+ }
+
+ return UINT32_MAX;
+}
+
+// Look for a child member (doesn't include base classes, but it does include
+// their members) in the type hierarchy. Returns an index path into "clang_type"
+// on how to reach the appropriate member.
+//
+// class A
+// {
+// public:
+// int m_a;
+// int m_b;
+// };
+//
+// class B
+// {
+// };
+//
+// class C :
+// public B,
+// public A
+// {
+// };
+//
+// If we have a clang type that describes "class C", and we wanted to looked
+// "m_b" in it:
+//
+// With omit_empty_base_classes == false we would get an integer array back with:
+// { 1, 1 }
+// The first index 1 is the child index for "class A" within class C
+// The second index 1 is the child index for "m_b" within class A
+//
+// With omit_empty_base_classes == true we would get an integer array back with:
+// { 0, 1 }
+// The first index 0 is the child index for "class A" within class C (since class B doesn't have any members it doesn't count)
+// The second index 1 is the child index for "m_b" within class A
+
+size_t
+ClangASTContext::GetIndexOfChildMemberWithName (lldb::opaque_compiler_type_t type, const char *name,
+ bool omit_empty_base_classes,
+ std::vector<uint32_t>& child_indexes)
+{
+ if (type && name && name[0])
+ {
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
+ {
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+
+ assert(record_decl);
+ uint32_t child_idx = 0;
+
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+
+ // Try and find a field that matches NAME
+ clang::RecordDecl::field_iterator field, field_end;
+ llvm::StringRef name_sref(name);
+ for (field = record_decl->field_begin(), field_end = record_decl->field_end();
+ field != field_end;
+ ++field, ++child_idx)
+ {
+ llvm::StringRef field_name = field->getName();
+ if (field_name.empty())
+ {
+ CompilerType field_type(getASTContext(),field->getType());
+ child_indexes.push_back(child_idx);
+ if (field_type.GetIndexOfChildMemberWithName(name, omit_empty_base_classes, child_indexes))
+ return child_indexes.size();
+ child_indexes.pop_back();
+
+ }
+ else if (field_name.equals (name_sref))
+ {
+ // We have to add on the number of base classes to this index!
+ child_indexes.push_back (child_idx + ClangASTContext::GetNumBaseClasses (cxx_record_decl, omit_empty_base_classes));
+ return child_indexes.size();
+ }
+ }
+
+ if (cxx_record_decl)
+ {
+ const clang::RecordDecl *parent_record_decl = cxx_record_decl;
+
+ //printf ("parent = %s\n", parent_record_decl->getNameAsCString());
+
+ //const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl();
+ // Didn't find things easily, lets let clang do its thang...
+ clang::IdentifierInfo & ident_ref = getASTContext()->Idents.get(name_sref);
+ clang::DeclarationName decl_name(&ident_ref);
+
+ clang::CXXBasePaths paths;
+ if (cxx_record_decl->lookupInBases([decl_name](const clang::CXXBaseSpecifier *specifier, clang::CXXBasePath &path) {
+ return clang::CXXRecordDecl::FindOrdinaryMember(specifier, path, decl_name);
+ },
+ paths))
+ {
+ clang::CXXBasePaths::const_paths_iterator path, path_end = paths.end();
+ for (path = paths.begin(); path != path_end; ++path)
+ {
+ const size_t num_path_elements = path->size();
+ for (size_t e=0; e<num_path_elements; ++e)
+ {
+ clang::CXXBasePathElement elem = (*path)[e];
+
+ child_idx = GetIndexForRecordBase (parent_record_decl, elem.Base, omit_empty_base_classes);
+ if (child_idx == UINT32_MAX)
+ {
+ child_indexes.clear();
+ return 0;
+ }
+ else
+ {
+ child_indexes.push_back (child_idx);
+ parent_record_decl = llvm::cast<clang::RecordDecl>(elem.Base->getType()->getAs<clang::RecordType>()->getDecl());
+ }
+ }
+ for (clang::NamedDecl *path_decl : path->Decls)
+ {
+ child_idx = GetIndexForRecordChild (parent_record_decl, path_decl, omit_empty_base_classes);
+ if (child_idx == UINT32_MAX)
+ {
+ child_indexes.clear();
+ return 0;
+ }
+ else
+ {
+ child_indexes.push_back (child_idx);
+ }
+ }
+ }
+ return child_indexes.size();
+ }
+ }
+
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ if (GetCompleteType(type))
+ {
+ llvm::StringRef name_sref(name);
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+ assert (objc_class_type);
+ if (objc_class_type)
+ {
+ uint32_t child_idx = 0;
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
+ if (class_interface_decl)
+ {
+ clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+
+ for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx)
+ {
+ const clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
+
+ if (ivar_decl->getName().equals (name_sref))
+ {
+ if ((!omit_empty_base_classes && superclass_interface_decl) ||
+ ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true)))
+ ++child_idx;
+
+ child_indexes.push_back (child_idx);
+ return child_indexes.size();
+ }
+ }
+
+ if (superclass_interface_decl)
+ {
+ // The super class index is always zero for ObjC classes,
+ // so we push it onto the child indexes in case we find
+ // an ivar in our superclass...
+ child_indexes.push_back (0);
+
+ CompilerType superclass_clang_type (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl));
+ if (superclass_clang_type.GetIndexOfChildMemberWithName (name,
+ omit_empty_base_classes,
+ child_indexes))
+ {
+ // We did find an ivar in a superclass so just
+ // return the results!
+ return child_indexes.size();
+ }
+
+ // We didn't find an ivar matching "name" in our
+ // superclass, pop the superclass zero index that
+ // we pushed on above.
+ child_indexes.pop_back();
+ }
+ }
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObjectPointer:
+ {
+ CompilerType objc_object_clang_type (getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType());
+ return objc_object_clang_type.GetIndexOfChildMemberWithName (name,
+ omit_empty_base_classes,
+ child_indexes);
+ }
+ break;
+
+
+ case clang::Type::ConstantArray:
+ {
+ // const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr());
+ // const uint64_t element_count = array->getSize().getLimitedValue();
+ //
+ // if (idx < element_count)
+ // {
+ // std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(array->getElementType());
+ //
+ // char element_name[32];
+ // ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx);
+ //
+ // child_name.assign(element_name);
+ // assert(field_type_info.first % 8 == 0);
+ // child_byte_size = field_type_info.first / 8;
+ // child_byte_offset = idx * child_byte_size;
+ // return array->getElementType().getAsOpaquePtr();
+ // }
+ }
+ break;
+
+ // case clang::Type::MemberPointerType:
+ // {
+ // MemberPointerType *mem_ptr_type = llvm::cast<MemberPointerType>(qual_type.getTypePtr());
+ // clang::QualType pointee_type = mem_ptr_type->getPointeeType();
+ //
+ // if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+ // {
+ // return GetIndexOfChildWithName (ast,
+ // mem_ptr_type->getPointeeType().getAsOpaquePtr(),
+ // name);
+ // }
+ // }
+ // break;
+ //
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ {
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+ clang::QualType pointee_type(reference_type->getPointeeType());
+ CompilerType pointee_clang_type (getASTContext(), pointee_type);
+
+ if (pointee_clang_type.IsAggregateType ())
+ {
+ return pointee_clang_type.GetIndexOfChildMemberWithName (name,
+ omit_empty_base_classes,
+ child_indexes);
+ }
+ }
+ break;
+
+ case clang::Type::Pointer:
+ {
+ CompilerType pointee_clang_type (GetPointeeType(type));
+
+ if (pointee_clang_type.IsAggregateType ())
+ {
+ return pointee_clang_type.GetIndexOfChildMemberWithName (name,
+ omit_empty_base_classes,
+ child_indexes);
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildMemberWithName (name,
+ omit_empty_base_classes,
+ child_indexes);
+
+ case clang::Type::Auto:
+ return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetIndexOfChildMemberWithName (name,
+ omit_empty_base_classes,
+ child_indexes);
+
+ case clang::Type::Elaborated:
+ return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildMemberWithName (name,
+ omit_empty_base_classes,
+ child_indexes);
+
+ case clang::Type::Paren:
+ return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildMemberWithName (name,
+ omit_empty_base_classes,
+ child_indexes);
+
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+
+// Get the index of the child of "clang_type" whose name matches. This function
+// doesn't descend into the children, but only looks one level deep and name
+// matches can include base class names.
+
+uint32_t
+ClangASTContext::GetIndexOfChildWithName (lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes)
+{
+ if (type && name && name[0])
+ {
+ clang::QualType qual_type(GetCanonicalQualType(type));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
+ {
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+
+ assert(record_decl);
+ uint32_t child_idx = 0;
+
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+
+ if (cxx_record_decl)
+ {
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+ base_class != base_class_end;
+ ++base_class)
+ {
+ // Skip empty base classes
+ clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
+ if (omit_empty_base_classes && ClangASTContext::RecordHasFields(base_class_decl) == false)
+ continue;
+
+ CompilerType base_class_clang_type (getASTContext(), base_class->getType());
+ std::string base_class_type_name (base_class_clang_type.GetTypeName().AsCString(""));
+ if (base_class_type_name.compare (name) == 0)
+ return child_idx;
+ ++child_idx;
+ }
+ }
+
+ // Try and find a field that matches NAME
+ clang::RecordDecl::field_iterator field, field_end;
+ llvm::StringRef name_sref(name);
+ for (field = record_decl->field_begin(), field_end = record_decl->field_end();
+ field != field_end;
+ ++field, ++child_idx)
+ {
+ if (field->getName().equals (name_sref))
+ return child_idx;
+ }
+
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ if (GetCompleteType(type))
+ {
+ llvm::StringRef name_sref(name);
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+ assert (objc_class_type);
+ if (objc_class_type)
+ {
+ uint32_t child_idx = 0;
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
+ if (class_interface_decl)
+ {
+ clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
+ clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+
+ for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx)
+ {
+ const clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
+
+ if (ivar_decl->getName().equals (name_sref))
+ {
+ if ((!omit_empty_base_classes && superclass_interface_decl) ||
+ ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true)))
+ ++child_idx;
+
+ return child_idx;
+ }
+ }
+
+ if (superclass_interface_decl)
+ {
+ if (superclass_interface_decl->getName().equals (name_sref))
+ return 0;
+ }
+ }
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObjectPointer:
+ {
+ CompilerType pointee_clang_type (getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType());
+ return pointee_clang_type.GetIndexOfChildWithName (name, omit_empty_base_classes);
+ }
+ break;
+
+ case clang::Type::ConstantArray:
+ {
+ // const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr());
+ // const uint64_t element_count = array->getSize().getLimitedValue();
+ //
+ // if (idx < element_count)
+ // {
+ // std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(array->getElementType());
+ //
+ // char element_name[32];
+ // ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx);
+ //
+ // child_name.assign(element_name);
+ // assert(field_type_info.first % 8 == 0);
+ // child_byte_size = field_type_info.first / 8;
+ // child_byte_offset = idx * child_byte_size;
+ // return array->getElementType().getAsOpaquePtr();
+ // }
+ }
+ break;
+
+ // case clang::Type::MemberPointerType:
+ // {
+ // MemberPointerType *mem_ptr_type = llvm::cast<MemberPointerType>(qual_type.getTypePtr());
+ // clang::QualType pointee_type = mem_ptr_type->getPointeeType();
+ //
+ // if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+ // {
+ // return GetIndexOfChildWithName (ast,
+ // mem_ptr_type->getPointeeType().getAsOpaquePtr(),
+ // name);
+ // }
+ // }
+ // break;
+ //
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ {
+ const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
+ CompilerType pointee_type (getASTContext(), reference_type->getPointeeType());
+
+ if (pointee_type.IsAggregateType ())
+ {
+ return pointee_type.GetIndexOfChildWithName (name, omit_empty_base_classes);
+ }
+ }
+ break;
+
+ case clang::Type::Pointer:
+ {
+ const clang::PointerType *pointer_type = llvm::cast<clang::PointerType>(qual_type.getTypePtr());
+ CompilerType pointee_type (getASTContext(), pointer_type->getPointeeType());
+
+ if (pointee_type.IsAggregateType ())
+ {
+ return pointee_type.GetIndexOfChildWithName (name, omit_empty_base_classes);
+ }
+ else
+ {
+ // if (parent_name)
+ // {
+ // child_name.assign(1, '*');
+ // child_name += parent_name;
+ // }
+ //
+ // // We have a pointer to an simple type
+ // if (idx == 0)
+ // {
+ // std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type);
+ // assert(clang_type_info.first % 8 == 0);
+ // child_byte_size = clang_type_info.first / 8;
+ // child_byte_offset = 0;
+ // return pointee_type.getAsOpaquePtr();
+ // }
+ }
+ }
+ break;
+
+ case clang::Type::Auto:
+ return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetIndexOfChildWithName (name, omit_empty_base_classes);
+
+ case clang::Type::Elaborated:
+ return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildWithName (name, omit_empty_base_classes);
+
+ case clang::Type::Paren:
+ return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildWithName (name, omit_empty_base_classes);
+
+ case clang::Type::Typedef:
+ return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildWithName (name, omit_empty_base_classes);
+
+ default:
+ break;
+ }
+ }
+ return UINT32_MAX;
+}
+
+
+size_t
+ClangASTContext::GetNumTemplateArguments (lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return 0;
+
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(cxx_record_decl);
+ if (template_decl)
+ return template_decl->getTemplateArgs().size();
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ return (CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType())).GetNumTemplateArguments();
+
+ case clang::Type::Auto:
+ return (CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType())).GetNumTemplateArguments();
+
+ case clang::Type::Elaborated:
+ return (CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType())).GetNumTemplateArguments();
+
+ case clang::Type::Paren:
+ return (CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar())).GetNumTemplateArguments();
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+CompilerType
+ClangASTContext::GetTemplateArgument (lldb::opaque_compiler_type_t type, size_t arg_idx, lldb::TemplateArgumentKind &kind)
+{
+ if (!type)
+ return CompilerType();
+
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(cxx_record_decl);
+ if (template_decl && arg_idx < template_decl->getTemplateArgs().size())
+ {
+ const clang::TemplateArgument &template_arg = template_decl->getTemplateArgs()[arg_idx];
+ switch (template_arg.getKind())
+ {
+ case clang::TemplateArgument::Null:
+ kind = eTemplateArgumentKindNull;
+ return CompilerType();
+
+ case clang::TemplateArgument::Type:
+ kind = eTemplateArgumentKindType;
+ return CompilerType(getASTContext(), template_arg.getAsType());
+
+ case clang::TemplateArgument::Declaration:
+ kind = eTemplateArgumentKindDeclaration;
+ return CompilerType();
+
+ case clang::TemplateArgument::Integral:
+ kind = eTemplateArgumentKindIntegral;
+ return CompilerType(getASTContext(), template_arg.getIntegralType());
+
+ case clang::TemplateArgument::Template:
+ kind = eTemplateArgumentKindTemplate;
+ return CompilerType();
+
+ case clang::TemplateArgument::TemplateExpansion:
+ kind = eTemplateArgumentKindTemplateExpansion;
+ return CompilerType();
+
+ case clang::TemplateArgument::Expression:
+ kind = eTemplateArgumentKindExpression;
+ return CompilerType();
+
+ case clang::TemplateArgument::Pack:
+ kind = eTemplateArgumentKindPack;
+ return CompilerType();
+
+ default:
+ assert (!"Unhandled clang::TemplateArgument::ArgKind");
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ return (CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType())).GetTemplateArgument(arg_idx, kind);
+
+ case clang::Type::Auto:
+ return (CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType())).GetTemplateArgument(arg_idx, kind);
+
+ case clang::Type::Elaborated:
+ return (CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType())).GetTemplateArgument(arg_idx, kind);
+
+ case clang::Type::Paren:
+ return (CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar())).GetTemplateArgument(arg_idx, kind);
+
+ default:
+ break;
+ }
+ kind = eTemplateArgumentKindNull;
+ return CompilerType ();
+}
+
+CompilerType
+ClangASTContext::GetTypeForFormatters (void* type)
+{
+ if (type)
+ return RemoveFastQualifiers(CompilerType(this, type));
+ return CompilerType();
+}
+
+static bool
+IsOperator (const char *name, clang::OverloadedOperatorKind &op_kind)
+{
+ if (name == nullptr || name[0] == '\0')
+ return false;
+
+#define OPERATOR_PREFIX "operator"
+#define OPERATOR_PREFIX_LENGTH (sizeof (OPERATOR_PREFIX) - 1)
+
+ const char *post_op_name = nullptr;
+
+ bool no_space = true;
+
+ if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH))
+ return false;
+
+ post_op_name = name + OPERATOR_PREFIX_LENGTH;
+
+ if (post_op_name[0] == ' ')
+ {
+ post_op_name++;
+ no_space = false;
+ }
+
+#undef OPERATOR_PREFIX
+#undef OPERATOR_PREFIX_LENGTH
+
+ // This is an operator, set the overloaded operator kind to invalid
+ // in case this is a conversion operator...
+ op_kind = clang::NUM_OVERLOADED_OPERATORS;
+
+ switch (post_op_name[0])
+ {
+ default:
+ if (no_space)
+ return false;
+ break;
+ case 'n':
+ if (no_space)
+ return false;
+ if (strcmp (post_op_name, "new") == 0)
+ op_kind = clang::OO_New;
+ else if (strcmp (post_op_name, "new[]") == 0)
+ op_kind = clang::OO_Array_New;
+ break;
+
+ case 'd':
+ if (no_space)
+ return false;
+ if (strcmp (post_op_name, "delete") == 0)
+ op_kind = clang::OO_Delete;
+ else if (strcmp (post_op_name, "delete[]") == 0)
+ op_kind = clang::OO_Array_Delete;
+ break;
+
+ case '+':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Plus;
+ else if (post_op_name[2] == '\0')
+ {
+ if (post_op_name[1] == '=')
+ op_kind = clang::OO_PlusEqual;
+ else if (post_op_name[1] == '+')
+ op_kind = clang::OO_PlusPlus;
+ }
+ break;
+
+ case '-':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Minus;
+ else if (post_op_name[2] == '\0')
+ {
+ switch (post_op_name[1])
+ {
+ case '=': op_kind = clang::OO_MinusEqual; break;
+ case '-': op_kind = clang::OO_MinusMinus; break;
+ case '>': op_kind = clang::OO_Arrow; break;
+ }
+ }
+ else if (post_op_name[3] == '\0')
+ {
+ if (post_op_name[2] == '*')
+ op_kind = clang::OO_ArrowStar; break;
+ }
+ break;
+
+ case '*':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Star;
+ else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
+ op_kind = clang::OO_StarEqual;
+ break;
+
+ case '/':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Slash;
+ else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
+ op_kind = clang::OO_SlashEqual;
+ break;
+
+ case '%':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Percent;
+ else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
+ op_kind = clang::OO_PercentEqual;
+ break;
+
+
+ case '^':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Caret;
+ else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
+ op_kind = clang::OO_CaretEqual;
+ break;
+
+ case '&':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Amp;
+ else if (post_op_name[2] == '\0')
+ {
+ switch (post_op_name[1])
+ {
+ case '=': op_kind = clang::OO_AmpEqual; break;
+ case '&': op_kind = clang::OO_AmpAmp; break;
+ }
+ }
+ break;
+
+ case '|':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Pipe;
+ else if (post_op_name[2] == '\0')
+ {
+ switch (post_op_name[1])
+ {
+ case '=': op_kind = clang::OO_PipeEqual; break;
+ case '|': op_kind = clang::OO_PipePipe; break;
+ }
+ }
+ break;
+
+ case '~':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Tilde;
+ break;
+
+ case '!':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Exclaim;
+ else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
+ op_kind = clang::OO_ExclaimEqual;
+ break;
+
+ case '=':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Equal;
+ else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
+ op_kind = clang::OO_EqualEqual;
+ break;
+
+ case '<':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Less;
+ else if (post_op_name[2] == '\0')
+ {
+ switch (post_op_name[1])
+ {
+ case '<': op_kind = clang::OO_LessLess; break;
+ case '=': op_kind = clang::OO_LessEqual; break;
+ }
+ }
+ else if (post_op_name[3] == '\0')
+ {
+ if (post_op_name[2] == '=')
+ op_kind = clang::OO_LessLessEqual;
+ }
+ break;
+
+ case '>':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Greater;
+ else if (post_op_name[2] == '\0')
+ {
+ switch (post_op_name[1])
+ {
+ case '>': op_kind = clang::OO_GreaterGreater; break;
+ case '=': op_kind = clang::OO_GreaterEqual; break;
+ }
+ }
+ else if (post_op_name[1] == '>' &&
+ post_op_name[2] == '=' &&
+ post_op_name[3] == '\0')
+ {
+ op_kind = clang::OO_GreaterGreaterEqual;
+ }
+ break;
+
+ case ',':
+ if (post_op_name[1] == '\0')
+ op_kind = clang::OO_Comma;
+ break;
+
+ case '(':
+ if (post_op_name[1] == ')' && post_op_name[2] == '\0')
+ op_kind = clang::OO_Call;
+ break;
+
+ case '[':
+ if (post_op_name[1] == ']' && post_op_name[2] == '\0')
+ op_kind = clang::OO_Subscript;
+ break;
+ }
+
+ return true;
+}
+
+clang::EnumDecl *
+ClangASTContext::GetAsEnumDecl (const CompilerType& type)
+{
+ const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type));
+ if (enutype)
+ return enutype->getDecl();
+ return NULL;
+}
+
+clang::RecordDecl *
+ClangASTContext::GetAsRecordDecl (const CompilerType& type)
+{
+ const clang::RecordType *record_type = llvm::dyn_cast<clang::RecordType>(GetCanonicalQualType(type));
+ if (record_type)
+ return record_type->getDecl();
+ return nullptr;
+}
+
+clang::TagDecl *
+ClangASTContext::GetAsTagDecl (const CompilerType& type)
+{
+ clang::QualType qual_type = GetCanonicalQualType(type);
+ if (qual_type.isNull())
+ return nullptr;
+ else
+ return qual_type->getAsTagDecl();
+}
+
+clang::CXXRecordDecl *
+ClangASTContext::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type)
+{
+ return GetCanonicalQualType(type)->getAsCXXRecordDecl();
+}
+
+clang::ObjCInterfaceDecl *
+ClangASTContext::GetAsObjCInterfaceDecl (const CompilerType& type)
+{
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(GetCanonicalQualType(type));
+ if (objc_class_type)
+ return objc_class_type->getInterface();
+ return nullptr;
+}
+
+clang::FieldDecl *
+ClangASTContext::AddFieldToRecordType (const CompilerType& type, const char *name,
+ const CompilerType &field_clang_type,
+ AccessType access,
+ uint32_t bitfield_bit_size)
+{
+ if (!type.IsValid() || !field_clang_type.IsValid())
+ return nullptr;
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
+ if (!ast)
+ return nullptr;
+ clang::ASTContext* clang_ast = ast->getASTContext();
+
+ clang::FieldDecl *field = nullptr;
+
+ clang::Expr *bit_width = nullptr;
+ if (bitfield_bit_size != 0)
+ {
+ llvm::APInt bitfield_bit_size_apint(clang_ast->getTypeSize(clang_ast->IntTy), bitfield_bit_size);
+ bit_width = new (*clang_ast)clang::IntegerLiteral (*clang_ast, bitfield_bit_size_apint, clang_ast->IntTy, clang::SourceLocation());
+ }
+
+ clang::RecordDecl *record_decl = ast->GetAsRecordDecl (type);
+ if (record_decl)
+ {
+ field = clang::FieldDecl::Create (*clang_ast,
+ record_decl,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ name ? &clang_ast->Idents.get(name) : nullptr, // Identifier
+ GetQualType(field_clang_type), // Field type
+ nullptr, // TInfo *
+ bit_width, // BitWidth
+ false, // Mutable
+ clang::ICIS_NoInit); // HasInit
+
+ if (!name)
+ {
+ // Determine whether this field corresponds to an anonymous
+ // struct or union.
+ if (const clang::TagType *TagT = field->getType()->getAs<clang::TagType>()) {
+ if (clang::RecordDecl *Rec = llvm::dyn_cast<clang::RecordDecl>(TagT->getDecl()))
+ if (!Rec->getDeclName()) {
+ Rec->setAnonymousStructOrUnion(true);
+ field->setImplicit();
+
+ }
+ }
+ }
+
+ if (field)
+ {
+ field->setAccess (ClangASTContext::ConvertAccessTypeToAccessSpecifier (access));
+
+ record_decl->addDecl(field);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+ VerifyDecl(field);
+#endif
+ }
+ }
+ else
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = ast->GetAsObjCInterfaceDecl (type);
+
+ if (class_interface_decl)
+ {
+ const bool is_synthesized = false;
+
+ field_clang_type.GetCompleteType();
+
+ field = clang::ObjCIvarDecl::Create (*clang_ast,
+ class_interface_decl,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ name ? &clang_ast->Idents.get(name) : nullptr, // Identifier
+ GetQualType(field_clang_type), // Field type
+ nullptr, // TypeSourceInfo *
+ ConvertAccessTypeToObjCIvarAccessControl (access),
+ bit_width,
+ is_synthesized);
+
+ if (field)
+ {
+ class_interface_decl->addDecl(field);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+ VerifyDecl(field);
+#endif
+ }
+ }
+ }
+ return field;
+}
+
+void
+ClangASTContext::BuildIndirectFields (const CompilerType& type)
+{
+ if (!type)
+ return;
+
+ ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (!ast)
+ return;
+
+ clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
+
+ if (!record_decl)
+ return;
+
+ typedef llvm::SmallVector <clang::IndirectFieldDecl *, 1> IndirectFieldVector;
+
+ IndirectFieldVector indirect_fields;
+ clang::RecordDecl::field_iterator field_pos;
+ clang::RecordDecl::field_iterator field_end_pos = record_decl->field_end();
+ clang::RecordDecl::field_iterator last_field_pos = field_end_pos;
+ for (field_pos = record_decl->field_begin(); field_pos != field_end_pos; last_field_pos = field_pos++)
+ {
+ if (field_pos->isAnonymousStructOrUnion())
+ {
+ clang::QualType field_qual_type = field_pos->getType();
+
+ const clang::RecordType *field_record_type = field_qual_type->getAs<clang::RecordType>();
+
+ if (!field_record_type)
+ continue;
+
+ clang::RecordDecl *field_record_decl = field_record_type->getDecl();
+
+ if (!field_record_decl)
+ continue;
+
+ for (clang::RecordDecl::decl_iterator di = field_record_decl->decls_begin(), de = field_record_decl->decls_end();
+ di != de;
+ ++di)
+ {
+ if (clang::FieldDecl *nested_field_decl = llvm::dyn_cast<clang::FieldDecl>(*di))
+ {
+ clang::NamedDecl **chain = new (*ast->getASTContext()) clang::NamedDecl*[2];
+ chain[0] = *field_pos;
+ chain[1] = nested_field_decl;
+ clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*ast->getASTContext(),
+ record_decl,
+ clang::SourceLocation(),
+ nested_field_decl->getIdentifier(),
+ nested_field_decl->getType(),
+ chain,
+ 2);
+
+ indirect_field->setImplicit();
+
+ indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(field_pos->getAccess(),
+ nested_field_decl->getAccess()));
+
+ indirect_fields.push_back(indirect_field);
+ }
+ else if (clang::IndirectFieldDecl *nested_indirect_field_decl = llvm::dyn_cast<clang::IndirectFieldDecl>(*di))
+ {
+ int nested_chain_size = nested_indirect_field_decl->getChainingSize();
+ clang::NamedDecl **chain = new (*ast->getASTContext()) clang::NamedDecl*[nested_chain_size + 1];
+ chain[0] = *field_pos;
+
+ int chain_index = 1;
+ for (clang::IndirectFieldDecl::chain_iterator nci = nested_indirect_field_decl->chain_begin(),
+ nce = nested_indirect_field_decl->chain_end();
+ nci < nce;
+ ++nci)
+ {
+ chain[chain_index] = *nci;
+ chain_index++;
+ }
+
+ clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*ast->getASTContext(),
+ record_decl,
+ clang::SourceLocation(),
+ nested_indirect_field_decl->getIdentifier(),
+ nested_indirect_field_decl->getType(),
+ chain,
+ nested_chain_size + 1);
+
+ indirect_field->setImplicit();
+
+ indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(field_pos->getAccess(),
+ nested_indirect_field_decl->getAccess()));
+
+ indirect_fields.push_back(indirect_field);
+ }
+ }
+ }
+ }
+
+ // Check the last field to see if it has an incomplete array type as its
+ // last member and if it does, the tell the record decl about it
+ if (last_field_pos != field_end_pos)
+ {
+ if (last_field_pos->getType()->isIncompleteArrayType())
+ record_decl->hasFlexibleArrayMember();
+ }
+
+ for (IndirectFieldVector::iterator ifi = indirect_fields.begin(), ife = indirect_fields.end();
+ ifi < ife;
+ ++ifi)
+ {
+ record_decl->addDecl(*ifi);
+ }
+}
+
+void
+ClangASTContext::SetIsPacked (const CompilerType& type)
+{
+ if (type)
+ {
+ ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (ast)
+ {
+ clang::RecordDecl *record_decl = GetAsRecordDecl(type);
+
+ if (!record_decl)
+ return;
+
+ record_decl->addAttr(clang::PackedAttr::CreateImplicit(*ast->getASTContext()));
+ }
+ }
+}
+
+clang::VarDecl *
+ClangASTContext::AddVariableToRecordType (const CompilerType& type, const char *name,
+ const CompilerType &var_type,
+ AccessType access)
+{
+ clang::VarDecl *var_decl = nullptr;
+
+ if (!type.IsValid() || !var_type.IsValid())
+ return nullptr;
+ ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (!ast)
+ return nullptr;
+
+ clang::RecordDecl *record_decl = ast->GetAsRecordDecl (type);
+ if (record_decl)
+ {
+ var_decl = clang::VarDecl::Create (*ast->getASTContext(), // ASTContext &
+ record_decl, // DeclContext *
+ clang::SourceLocation(), // clang::SourceLocation StartLoc
+ clang::SourceLocation(), // clang::SourceLocation IdLoc
+ name ? &ast->getASTContext()->Idents.get(name) : nullptr, // clang::IdentifierInfo *
+ GetQualType(var_type), // Variable clang::QualType
+ nullptr, // TypeSourceInfo *
+ clang::SC_Static); // StorageClass
+ if (var_decl)
+ {
+ var_decl->setAccess(ClangASTContext::ConvertAccessTypeToAccessSpecifier (access));
+ record_decl->addDecl(var_decl);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+ VerifyDecl(var_decl);
+#endif
+ }
+ }
+ return var_decl;
+}
+
+
+clang::CXXMethodDecl *
+ClangASTContext::AddMethodToCXXRecordType (lldb::opaque_compiler_type_t type, const char *name,
+ const CompilerType &method_clang_type,
+ lldb::AccessType access,
+ bool is_virtual,
+ bool is_static,
+ bool is_inline,
+ bool is_explicit,
+ bool is_attr_used,
+ bool is_artificial)
+{
+ if (!type || !method_clang_type.IsValid() || name == nullptr || name[0] == '\0')
+ return nullptr;
+
+ clang::QualType record_qual_type(GetCanonicalQualType(type));
+
+ clang::CXXRecordDecl *cxx_record_decl = record_qual_type->getAsCXXRecordDecl();
+
+ if (cxx_record_decl == nullptr)
+ return nullptr;
+
+ clang::QualType method_qual_type (GetQualType(method_clang_type));
+
+ clang::CXXMethodDecl *cxx_method_decl = nullptr;
+
+ clang::DeclarationName decl_name (&getASTContext()->Idents.get(name));
+
+ const clang::FunctionType *function_type = llvm::dyn_cast<clang::FunctionType>(method_qual_type.getTypePtr());
+
+ if (function_type == nullptr)
+ return nullptr;
+
+ const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast<clang::FunctionProtoType>(function_type));
+
+ if (!method_function_prototype)
+ return nullptr;
+
+ unsigned int num_params = method_function_prototype->getNumParams();
+
+ clang::CXXDestructorDecl *cxx_dtor_decl(nullptr);
+ clang::CXXConstructorDecl *cxx_ctor_decl(nullptr);
+
+ if (is_artificial)
+ return nullptr; // skip everything artificial
+
+ if (name[0] == '~')
+ {
+ cxx_dtor_decl = clang::CXXDestructorDecl::Create (*getASTContext(),
+ cxx_record_decl,
+ clang::SourceLocation(),
+ clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXDestructorName (getASTContext()->getCanonicalType (record_qual_type)), clang::SourceLocation()),
+ method_qual_type,
+ nullptr,
+ is_inline,
+ is_artificial);
+ cxx_method_decl = cxx_dtor_decl;
+ }
+ else if (decl_name == cxx_record_decl->getDeclName())
+ {
+ cxx_ctor_decl = clang::CXXConstructorDecl::Create (*getASTContext(),
+ cxx_record_decl,
+ clang::SourceLocation(),
+ clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXConstructorName (getASTContext()->getCanonicalType (record_qual_type)), clang::SourceLocation()),
+ method_qual_type,
+ nullptr, // TypeSourceInfo *
+ is_explicit,
+ is_inline,
+ is_artificial,
+ false /*is_constexpr*/);
+ cxx_method_decl = cxx_ctor_decl;
+ }
+ else
+ {
+ clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None;
+ clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
+
+ if (IsOperator (name, op_kind))
+ {
+ if (op_kind != clang::NUM_OVERLOADED_OPERATORS)
+ {
+ // Check the number of operator parameters. Sometimes we have
+ // seen bad DWARF that doesn't correctly describe operators and
+ // if we try to create a method and add it to the class, clang
+ // will assert and crash, so we need to make sure things are
+ // acceptable.
+ if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount (op_kind, num_params))
+ return nullptr;
+ cxx_method_decl = clang::CXXMethodDecl::Create (*getASTContext(),
+ cxx_record_decl,
+ clang::SourceLocation(),
+ clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXOperatorName (op_kind), clang::SourceLocation()),
+ method_qual_type,
+ nullptr, // TypeSourceInfo *
+ SC,
+ is_inline,
+ false /*is_constexpr*/,
+ clang::SourceLocation());
+ }
+ else if (num_params == 0)
+ {
+ // Conversion operators don't take params...
+ cxx_method_decl = clang::CXXConversionDecl::Create (*getASTContext(),
+ cxx_record_decl,
+ clang::SourceLocation(),
+ clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXConversionFunctionName (getASTContext()->getCanonicalType (function_type->getReturnType())), clang::SourceLocation()),
+ method_qual_type,
+ nullptr, // TypeSourceInfo *
+ is_inline,
+ is_explicit,
+ false /*is_constexpr*/,
+ clang::SourceLocation());
+ }
+ }
+
+ if (cxx_method_decl == nullptr)
+ {
+ cxx_method_decl = clang::CXXMethodDecl::Create (*getASTContext(),
+ cxx_record_decl,
+ clang::SourceLocation(),
+ clang::DeclarationNameInfo (decl_name, clang::SourceLocation()),
+ method_qual_type,
+ nullptr, // TypeSourceInfo *
+ SC,
+ is_inline,
+ false /*is_constexpr*/,
+ clang::SourceLocation());
+ }
+ }
+
+ clang::AccessSpecifier access_specifier = ClangASTContext::ConvertAccessTypeToAccessSpecifier (access);
+
+ cxx_method_decl->setAccess (access_specifier);
+ cxx_method_decl->setVirtualAsWritten (is_virtual);
+
+ if (is_attr_used)
+ cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(*getASTContext()));
+
+ // Populate the method decl with parameter decls
+
+ llvm::SmallVector<clang::ParmVarDecl *, 12> params;
+
+ for (unsigned param_index = 0;
+ param_index < num_params;
+ ++param_index)
+ {
+ params.push_back (clang::ParmVarDecl::Create (*getASTContext(),
+ cxx_method_decl,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ nullptr, // anonymous
+ method_function_prototype->getParamType(param_index),
+ nullptr,
+ clang::SC_None,
+ nullptr));
+ }
+
+ cxx_method_decl->setParams (llvm::ArrayRef<clang::ParmVarDecl*>(params));
+
+ cxx_record_decl->addDecl (cxx_method_decl);
+
+ // Sometimes the debug info will mention a constructor (default/copy/move),
+ // destructor, or assignment operator (copy/move) but there won't be any
+ // version of this in the code. So we check if the function was artificially
+ // generated and if it is trivial and this lets the compiler/backend know
+ // that it can inline the IR for these when it needs to and we can avoid a
+ // "missing function" error when running expressions.
+
+ if (is_artificial)
+ {
+ if (cxx_ctor_decl &&
+ ((cxx_ctor_decl->isDefaultConstructor() && cxx_record_decl->hasTrivialDefaultConstructor ()) ||
+ (cxx_ctor_decl->isCopyConstructor() && cxx_record_decl->hasTrivialCopyConstructor ()) ||
+ (cxx_ctor_decl->isMoveConstructor() && cxx_record_decl->hasTrivialMoveConstructor ()) ))
+ {
+ cxx_ctor_decl->setDefaulted();
+ cxx_ctor_decl->setTrivial(true);
+ }
+ else if (cxx_dtor_decl)
+ {
+ if (cxx_record_decl->hasTrivialDestructor())
+ {
+ cxx_dtor_decl->setDefaulted();
+ cxx_dtor_decl->setTrivial(true);
+ }
+ }
+ else if ((cxx_method_decl->isCopyAssignmentOperator() && cxx_record_decl->hasTrivialCopyAssignment()) ||
+ (cxx_method_decl->isMoveAssignmentOperator() && cxx_record_decl->hasTrivialMoveAssignment()))
+ {
+ cxx_method_decl->setDefaulted();
+ cxx_method_decl->setTrivial(true);
+ }
+ }
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+ VerifyDecl(cxx_method_decl);
+#endif
+
+ // printf ("decl->isPolymorphic() = %i\n", cxx_record_decl->isPolymorphic());
+ // printf ("decl->isAggregate() = %i\n", cxx_record_decl->isAggregate());
+ // printf ("decl->isPOD() = %i\n", cxx_record_decl->isPOD());
+ // printf ("decl->isEmpty() = %i\n", cxx_record_decl->isEmpty());
+ // printf ("decl->isAbstract() = %i\n", cxx_record_decl->isAbstract());
+ // printf ("decl->hasTrivialConstructor() = %i\n", cxx_record_decl->hasTrivialConstructor());
+ // printf ("decl->hasTrivialCopyConstructor() = %i\n", cxx_record_decl->hasTrivialCopyConstructor());
+ // printf ("decl->hasTrivialCopyAssignment() = %i\n", cxx_record_decl->hasTrivialCopyAssignment());
+ // printf ("decl->hasTrivialDestructor() = %i\n", cxx_record_decl->hasTrivialDestructor());
+ return cxx_method_decl;
+}
+
+
+#pragma mark C++ Base Classes
+
+clang::CXXBaseSpecifier *
+ClangASTContext::CreateBaseClassSpecifier (lldb::opaque_compiler_type_t type, AccessType access, bool is_virtual, bool base_of_class)
+{
+ if (type)
+ return new clang::CXXBaseSpecifier (clang::SourceRange(),
+ is_virtual,
+ base_of_class,
+ ClangASTContext::ConvertAccessTypeToAccessSpecifier (access),
+ getASTContext()->getTrivialTypeSourceInfo (GetQualType(type)),
+ clang::SourceLocation());
+ return nullptr;
+}
+
+void
+ClangASTContext::DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes, unsigned num_base_classes)
+{
+ for (unsigned i=0; i<num_base_classes; ++i)
+ {
+ delete base_classes[i];
+ base_classes[i] = nullptr;
+ }
+}
+
+bool
+ClangASTContext::SetBaseClassesForClassType (lldb::opaque_compiler_type_t type, clang::CXXBaseSpecifier const * const *base_classes,
+ unsigned num_base_classes)
+{
+ if (type)
+ {
+ clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl(type);
+ if (cxx_record_decl)
+ {
+ cxx_record_decl->setBases(base_classes, num_base_classes);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+ClangASTContext::SetObjCSuperClass (const CompilerType& type, const CompilerType &superclass_clang_type)
+{
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem());
+ if (!ast)
+ return false;
+ clang::ASTContext* clang_ast = ast->getASTContext();
+
+ if (type && superclass_clang_type.IsValid() && superclass_clang_type.GetTypeSystem() == type.GetTypeSystem())
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (type);
+ clang::ObjCInterfaceDecl *super_interface_decl = GetAsObjCInterfaceDecl (superclass_clang_type);
+ if (class_interface_decl && super_interface_decl)
+ {
+ class_interface_decl->setSuperClass(clang_ast->getTrivialTypeSourceInfo(clang_ast->getObjCInterfaceType(super_interface_decl)));
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+ClangASTContext::AddObjCClassProperty (const CompilerType& type,
+ const char *property_name,
+ const CompilerType &property_clang_type,
+ clang::ObjCIvarDecl *ivar_decl,
+ const char *property_setter_name,
+ const char *property_getter_name,
+ uint32_t property_attributes,
+ ClangASTMetadata *metadata)
+{
+ if (!type || !property_clang_type.IsValid() || property_name == nullptr || property_name[0] == '\0')
+ return false;
+ ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (!ast)
+ return false;
+ clang::ASTContext* clang_ast = ast->getASTContext();
+
+ clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (type);
+
+ if (class_interface_decl)
+ {
+ CompilerType property_clang_type_to_access;
+
+ if (property_clang_type.IsValid())
+ property_clang_type_to_access = property_clang_type;
+ else if (ivar_decl)
+ property_clang_type_to_access = CompilerType (clang_ast, ivar_decl->getType());
+
+ if (class_interface_decl && property_clang_type_to_access.IsValid())
+ {
+ clang::TypeSourceInfo *prop_type_source;
+ if (ivar_decl)
+ prop_type_source = clang_ast->getTrivialTypeSourceInfo (ivar_decl->getType());
+ else
+ prop_type_source = clang_ast->getTrivialTypeSourceInfo (GetQualType(property_clang_type));
+
+ clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create (*clang_ast,
+ class_interface_decl,
+ clang::SourceLocation(), // Source Location
+ &clang_ast->Idents.get(property_name),
+ clang::SourceLocation(), //Source Location for AT
+ clang::SourceLocation(), //Source location for (
+ ivar_decl ? ivar_decl->getType() : ClangASTContext::GetQualType(property_clang_type),
+ prop_type_source);
+
+ if (property_decl)
+ {
+ if (metadata)
+ ClangASTContext::SetMetadata(clang_ast, property_decl, *metadata);
+
+ class_interface_decl->addDecl (property_decl);
+
+ clang::Selector setter_sel, getter_sel;
+
+ if (property_setter_name != nullptr)
+ {
+ std::string property_setter_no_colon(property_setter_name, strlen(property_setter_name) - 1);
+ clang::IdentifierInfo *setter_ident = &clang_ast->Idents.get(property_setter_no_colon.c_str());
+ setter_sel = clang_ast->Selectors.getSelector(1, &setter_ident);
+ }
+ else if (!(property_attributes & DW_APPLE_PROPERTY_readonly))
+ {
+ std::string setter_sel_string("set");
+ setter_sel_string.push_back(::toupper(property_name[0]));
+ setter_sel_string.append(&property_name[1]);
+ clang::IdentifierInfo *setter_ident = &clang_ast->Idents.get(setter_sel_string.c_str());
+ setter_sel = clang_ast->Selectors.getSelector(1, &setter_ident);
+ }
+ property_decl->setSetterName(setter_sel);
+ property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_setter);
+
+ if (property_getter_name != nullptr)
+ {
+ clang::IdentifierInfo *getter_ident = &clang_ast->Idents.get(property_getter_name);
+ getter_sel = clang_ast->Selectors.getSelector(0, &getter_ident);
+ }
+ else
+ {
+ clang::IdentifierInfo *getter_ident = &clang_ast->Idents.get(property_name);
+ getter_sel = clang_ast->Selectors.getSelector(0, &getter_ident);
+ }
+ property_decl->setGetterName(getter_sel);
+ property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_getter);
+
+ if (ivar_decl)
+ property_decl->setPropertyIvarDecl (ivar_decl);
+
+ if (property_attributes & DW_APPLE_PROPERTY_readonly)
+ property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readonly);
+ if (property_attributes & DW_APPLE_PROPERTY_readwrite)
+ property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readwrite);
+ if (property_attributes & DW_APPLE_PROPERTY_assign)
+ property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_assign);
+ if (property_attributes & DW_APPLE_PROPERTY_retain)
+ property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_retain);
+ if (property_attributes & DW_APPLE_PROPERTY_copy)
+ property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_copy);
+ if (property_attributes & DW_APPLE_PROPERTY_nonatomic)
+ property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_nonatomic);
+
+ if (!getter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(getter_sel))
+ {
+ const bool isInstance = true;
+ const bool isVariadic = false;
+ const bool isSynthesized = false;
+ const bool isImplicitlyDeclared = true;
+ const bool isDefined = false;
+ const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None;
+ const bool HasRelatedResultType = false;
+
+ clang::ObjCMethodDecl *getter = clang::ObjCMethodDecl::Create (*clang_ast,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ getter_sel,
+ GetQualType(property_clang_type_to_access),
+ nullptr,
+ class_interface_decl,
+ isInstance,
+ isVariadic,
+ isSynthesized,
+ isImplicitlyDeclared,
+ isDefined,
+ impControl,
+ HasRelatedResultType);
+
+ if (getter && metadata)
+ ClangASTContext::SetMetadata(clang_ast, getter, *metadata);
+
+ if (getter)
+ {
+ getter->setMethodParams(*clang_ast, llvm::ArrayRef<clang::ParmVarDecl*>(), llvm::ArrayRef<clang::SourceLocation>());
+
+ class_interface_decl->addDecl(getter);
+ }
+ }
+
+ if (!setter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(setter_sel))
+ {
+ clang::QualType result_type = clang_ast->VoidTy;
+
+ const bool isInstance = true;
+ const bool isVariadic = false;
+ const bool isSynthesized = false;
+ const bool isImplicitlyDeclared = true;
+ const bool isDefined = false;
+ const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None;
+ const bool HasRelatedResultType = false;
+
+ clang::ObjCMethodDecl *setter = clang::ObjCMethodDecl::Create (*clang_ast,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ setter_sel,
+ result_type,
+ nullptr,
+ class_interface_decl,
+ isInstance,
+ isVariadic,
+ isSynthesized,
+ isImplicitlyDeclared,
+ isDefined,
+ impControl,
+ HasRelatedResultType);
+
+ if (setter && metadata)
+ ClangASTContext::SetMetadata(clang_ast, setter, *metadata);
+
+ llvm::SmallVector<clang::ParmVarDecl *, 1> params;
+
+ params.push_back (clang::ParmVarDecl::Create (*clang_ast,
+ setter,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ nullptr, // anonymous
+ GetQualType(property_clang_type_to_access),
+ nullptr,
+ clang::SC_Auto,
+ nullptr));
+
+ if (setter)
+ {
+ setter->setMethodParams(*clang_ast, llvm::ArrayRef<clang::ParmVarDecl*>(params), llvm::ArrayRef<clang::SourceLocation>());
+
+ class_interface_decl->addDecl(setter);
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool
+ClangASTContext::IsObjCClassTypeAndHasIVars (const CompilerType& type, bool check_superclass)
+{
+ clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (type);
+ if (class_interface_decl)
+ return ObjCDeclHasIVars (class_interface_decl, check_superclass);
+ return false;
+}
+
+
+clang::ObjCMethodDecl *
+ClangASTContext::AddMethodToObjCObjectType (const CompilerType& type,
+ const char *name, // the full symbol name as seen in the symbol table (lldb::opaque_compiler_type_t type, "-[NString stringWithCString:]")
+ const CompilerType &method_clang_type,
+ lldb::AccessType access,
+ bool is_artificial)
+{
+ if (!type || !method_clang_type.IsValid())
+ return nullptr;
+
+ clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type);
+
+ if (class_interface_decl == nullptr)
+ return nullptr;
+ ClangASTContext *lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (lldb_ast == nullptr)
+ return nullptr;
+ clang::ASTContext *ast = lldb_ast->getASTContext();
+
+ const char *selector_start = ::strchr (name, ' ');
+ if (selector_start == nullptr)
+ return nullptr;
+
+ selector_start++;
+ llvm::SmallVector<clang::IdentifierInfo *, 12> selector_idents;
+
+ size_t len = 0;
+ const char *start;
+ //printf ("name = '%s'\n", name);
+
+ unsigned num_selectors_with_args = 0;
+ for (start = selector_start;
+ start && *start != '\0' && *start != ']';
+ start += len)
+ {
+ len = ::strcspn(start, ":]");
+ bool has_arg = (start[len] == ':');
+ if (has_arg)
+ ++num_selectors_with_args;
+ selector_idents.push_back (&ast->Idents.get (llvm::StringRef (start, len)));
+ if (has_arg)
+ len += 1;
+ }
+
+
+ if (selector_idents.size() == 0)
+ return nullptr;
+
+ clang::Selector method_selector = ast->Selectors.getSelector (num_selectors_with_args ? selector_idents.size() : 0,
+ selector_idents.data());
+
+ clang::QualType method_qual_type (GetQualType(method_clang_type));
+
+ // Populate the method decl with parameter decls
+ const clang::Type *method_type(method_qual_type.getTypePtr());
+
+ if (method_type == nullptr)
+ return nullptr;
+
+ const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast<clang::FunctionProtoType>(method_type));
+
+ if (!method_function_prototype)
+ return nullptr;
+
+
+ bool is_variadic = false;
+ bool is_synthesized = false;
+ bool is_defined = false;
+ clang::ObjCMethodDecl::ImplementationControl imp_control = clang::ObjCMethodDecl::None;
+
+ const unsigned num_args = method_function_prototype->getNumParams();
+
+ if (num_args != num_selectors_with_args)
+ return nullptr; // some debug information is corrupt. We are not going to deal with it.
+
+ clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create (*ast,
+ clang::SourceLocation(), // beginLoc,
+ clang::SourceLocation(), // endLoc,
+ method_selector,
+ method_function_prototype->getReturnType(),
+ nullptr, // TypeSourceInfo *ResultTInfo,
+ ClangASTContext::GetASTContext(ast)->GetDeclContextForType(GetQualType(type)),
+ name[0] == '-',
+ is_variadic,
+ is_synthesized,
+ true, // is_implicitly_declared; we force this to true because we don't have source locations
+ is_defined,
+ imp_control,
+ false /*has_related_result_type*/);
+
+
+ if (objc_method_decl == nullptr)
+ return nullptr;
+
+ if (num_args > 0)
+ {
+ llvm::SmallVector<clang::ParmVarDecl *, 12> params;
+
+ for (unsigned param_index = 0; param_index < num_args; ++param_index)
+ {
+ params.push_back (clang::ParmVarDecl::Create (*ast,
+ objc_method_decl,
+ clang::SourceLocation(),
+ clang::SourceLocation(),
+ nullptr, // anonymous
+ method_function_prototype->getParamType(param_index),
+ nullptr,
+ clang::SC_Auto,
+ nullptr));
+ }
+
+ objc_method_decl->setMethodParams(*ast, llvm::ArrayRef<clang::ParmVarDecl*>(params), llvm::ArrayRef<clang::SourceLocation>());
+ }
+
+ class_interface_decl->addDecl (objc_method_decl);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+ VerifyDecl(objc_method_decl);
+#endif
+
+ return objc_method_decl;
+}
+
+bool
+ClangASTContext::GetHasExternalStorage (const CompilerType &type)
+{
+ if (IsClangType(type))
+ return false;
+
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ {
+ clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ return cxx_record_decl->hasExternalLexicalStorage () || cxx_record_decl->hasExternalVisibleStorage();
+ }
+ break;
+
+ case clang::Type::Enum:
+ {
+ clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
+ if (enum_decl)
+ return enum_decl->hasExternalLexicalStorage () || enum_decl->hasExternalVisibleStorage();
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+ assert (objc_class_type);
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
+ if (class_interface_decl)
+ return class_interface_decl->hasExternalLexicalStorage () || class_interface_decl->hasExternalVisibleStorage ();
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()));
+
+ case clang::Type::Auto:
+ return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()));
+
+ case clang::Type::Elaborated:
+ return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()));
+
+ case clang::Type::Paren:
+ return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
+
+ default:
+ break;
+ }
+ return false;
+}
+
+
+bool
+ClangASTContext::SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool has_extern)
+{
+ if (!type)
+ return false;
+
+ clang::QualType qual_type (GetCanonicalQualType(type));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ {
+ clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ cxx_record_decl->setHasExternalLexicalStorage (has_extern);
+ cxx_record_decl->setHasExternalVisibleStorage (has_extern);
+ return true;
+ }
+ }
+ break;
+
+ case clang::Type::Enum:
+ {
+ clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
+ if (enum_decl)
+ {
+ enum_decl->setHasExternalLexicalStorage (has_extern);
+ enum_decl->setHasExternalVisibleStorage (has_extern);
+ return true;
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+ assert (objc_class_type);
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+
+ if (class_interface_decl)
+ {
+ class_interface_decl->setHasExternalLexicalStorage (has_extern);
+ class_interface_decl->setHasExternalVisibleStorage (has_extern);
+ return true;
+ }
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ return SetHasExternalStorage(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), has_extern);
+
+ case clang::Type::Auto:
+ return SetHasExternalStorage (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), has_extern);
+
+ case clang::Type::Elaborated:
+ return SetHasExternalStorage (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), has_extern);
+
+ case clang::Type::Paren:
+ return SetHasExternalStorage (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), has_extern);
+
+ default:
+ break;
+ }
+ return false;
+}
+
+
+bool
+ClangASTContext::CanImport (const CompilerType &type, lldb_private::ClangASTImporter &importer)
+{
+ if (IsClangType(type))
+ {
+ // TODO: remove external completion BOOL
+ // CompleteAndFetchChildren should get the Decl out and check for the
+
+ clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type)));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ if (importer.ResolveDeclOrigin (cxx_record_decl, NULL, NULL))
+ return true;
+ }
+ }
+ break;
+
+ case clang::Type::Enum:
+ {
+ clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
+ if (enum_decl)
+ {
+ if (importer.ResolveDeclOrigin (enum_decl, NULL, NULL))
+ return true;
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ // We currently can't complete objective C types through the newly added ASTContext
+ // because it only supports TagDecl objects right now...
+ if (class_interface_decl)
+ {
+ if (importer.ResolveDeclOrigin (class_interface_decl, NULL, NULL))
+ return true;
+ }
+ }
+ }
+ break;
+
+
+ case clang::Type::Typedef:
+ return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()), importer);
+
+ case clang::Type::Auto:
+ return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()), importer);
+
+ case clang::Type::Elaborated:
+ return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()), importer);
+
+ case clang::Type::Paren:
+ return CanImport(CompilerType (type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()), importer);
+
+ default:
+ break;
+ }
+ }
+ return false;
+}
+bool
+ClangASTContext::Import (const CompilerType &type, lldb_private::ClangASTImporter &importer)
+{
+ if (IsClangType(type))
+ {
+ // TODO: remove external completion BOOL
+ // CompleteAndFetchChildren should get the Decl out and check for the
+
+ clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type)));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ {
+ if (importer.ResolveDeclOrigin (cxx_record_decl, NULL, NULL))
+ return importer.CompleteAndFetchChildren(qual_type);
+ }
+ }
+ break;
+
+ case clang::Type::Enum:
+ {
+ clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
+ if (enum_decl)
+ {
+ if (importer.ResolveDeclOrigin (enum_decl, NULL, NULL))
+ return importer.CompleteAndFetchChildren(qual_type);
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ // We currently can't complete objective C types through the newly added ASTContext
+ // because it only supports TagDecl objects right now...
+ if (class_interface_decl)
+ {
+ if (importer.ResolveDeclOrigin (class_interface_decl, NULL, NULL))
+ return importer.CompleteAndFetchChildren(qual_type);
+ }
+ }
+ }
+ break;
+
+
+ case clang::Type::Typedef:
+ return Import (CompilerType(type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()), importer);
+
+ case clang::Type::Auto:
+ return Import (CompilerType(type.GetTypeSystem(),llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()), importer);
+
+ case clang::Type::Elaborated:
+ return Import (CompilerType(type.GetTypeSystem(),llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()), importer);
+
+ case clang::Type::Paren:
+ return Import (CompilerType(type.GetTypeSystem(),llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()), importer);
+
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+
+#pragma mark TagDecl
+
+bool
+ClangASTContext::StartTagDeclarationDefinition (const CompilerType &type)
+{
+ clang::QualType qual_type (ClangASTContext::GetQualType(type));
+ if (!qual_type.isNull())
+ {
+ const clang::TagType *tag_type = qual_type->getAs<clang::TagType>();
+ if (tag_type)
+ {
+ clang::TagDecl *tag_decl = tag_type->getDecl();
+ if (tag_decl)
+ {
+ tag_decl->startDefinition();
+ return true;
+ }
+ }
+
+ const clang::ObjCObjectType *object_type = qual_type->getAs<clang::ObjCObjectType>();
+ if (object_type)
+ {
+ clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface();
+ if (interface_decl)
+ {
+ interface_decl->startDefinition();
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool
+ClangASTContext::CompleteTagDeclarationDefinition (const CompilerType& type)
+{
+ clang::QualType qual_type (ClangASTContext::GetQualType(type));
+ if (!qual_type.isNull())
+ {
+ clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+
+ if (cxx_record_decl)
+ {
+ if (!cxx_record_decl->isCompleteDefinition())
+ cxx_record_decl->completeDefinition();
+ cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true);
+ cxx_record_decl->setHasExternalLexicalStorage (false);
+ cxx_record_decl->setHasExternalVisibleStorage (false);
+ return true;
+ }
+
+ const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>();
+
+ if (enutype)
+ {
+ clang::EnumDecl *enum_decl = enutype->getDecl();
+
+ if (enum_decl)
+ {
+ if (!enum_decl->isCompleteDefinition())
+ {
+ ClangASTContext *lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (lldb_ast == nullptr)
+ return false;
+ clang::ASTContext *ast = lldb_ast->getASTContext();
+
+ /// TODO This really needs to be fixed.
+
+ unsigned NumPositiveBits = 1;
+ unsigned NumNegativeBits = 0;
+
+ clang::QualType promotion_qual_type;
+ // If the enum integer type is less than an integer in bit width,
+ // then we must promote it to an integer size.
+ if (ast->getTypeSize(enum_decl->getIntegerType()) < ast->getTypeSize(ast->IntTy))
+ {
+ if (enum_decl->getIntegerType()->isSignedIntegerType())
+ promotion_qual_type = ast->IntTy;
+ else
+ promotion_qual_type = ast->UnsignedIntTy;
+ }
+ else
+ promotion_qual_type = enum_decl->getIntegerType();
+
+ enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits);
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool
+ClangASTContext::AddEnumerationValueToEnumerationType (lldb::opaque_compiler_type_t type,
+ const CompilerType &enumerator_clang_type,
+ const Declaration &decl,
+ const char *name,
+ int64_t enum_value,
+ uint32_t enum_value_bit_size)
+{
+ if (type && enumerator_clang_type.IsValid() && name && name[0])
+ {
+ clang::QualType enum_qual_type (GetCanonicalQualType(type));
+
+ bool is_signed = false;
+ enumerator_clang_type.IsIntegerType (is_signed);
+ const clang::Type *clang_type = enum_qual_type.getTypePtr();
+ if (clang_type)
+ {
+ const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(clang_type);
+
+ if (enutype)
+ {
+ llvm::APSInt enum_llvm_apsint(enum_value_bit_size, is_signed);
+ enum_llvm_apsint = enum_value;
+ clang::EnumConstantDecl *enumerator_decl =
+ clang::EnumConstantDecl::Create (*getASTContext(),
+ enutype->getDecl(),
+ clang::SourceLocation(),
+ name ? &getASTContext()->Idents.get(name) : nullptr, // Identifier
+ GetQualType(enumerator_clang_type),
+ nullptr,
+ enum_llvm_apsint);
+
+ if (enumerator_decl)
+ {
+ enutype->getDecl()->addDecl(enumerator_decl);
+
+#ifdef LLDB_CONFIGURATION_DEBUG
+ VerifyDecl(enumerator_decl);
+#endif
+
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+CompilerType
+ClangASTContext::GetEnumerationIntegerType (lldb::opaque_compiler_type_t type)
+{
+ clang::QualType enum_qual_type (GetCanonicalQualType(type));
+ const clang::Type *clang_type = enum_qual_type.getTypePtr();
+ if (clang_type)
+ {
+ const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(clang_type);
+ if (enutype)
+ {
+ clang::EnumDecl *enum_decl = enutype->getDecl();
+ if (enum_decl)
+ return CompilerType (getASTContext(), enum_decl->getIntegerType());
+ }
+ }
+ return CompilerType();
+}
+
+CompilerType
+ClangASTContext::CreateMemberPointerType (const CompilerType& type, const CompilerType &pointee_type)
+{
+ if (type && pointee_type.IsValid() && type.GetTypeSystem() == pointee_type.GetTypeSystem())
+ {
+ ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (!ast)
+ return CompilerType();
+ return CompilerType (ast->getASTContext(),
+ ast->getASTContext()->getMemberPointerType (GetQualType(pointee_type),
+ GetQualType(type).getTypePtr()));
+ }
+ return CompilerType();
+}
+
+
+size_t
+ClangASTContext::ConvertStringToFloatValue (lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst, size_t dst_size)
+{
+ if (type)
+ {
+ clang::QualType qual_type (GetCanonicalQualType(type));
+ uint32_t count = 0;
+ bool is_complex = false;
+ if (IsFloatingPointType (type, count, is_complex))
+ {
+ // TODO: handle complex and vector types
+ if (count != 1)
+ return false;
+
+ llvm::StringRef s_sref(s);
+ llvm::APFloat ap_float(getASTContext()->getFloatTypeSemantics(qual_type), s_sref);
+
+ const uint64_t bit_size = getASTContext()->getTypeSize (qual_type);
+ const uint64_t byte_size = bit_size / 8;
+ if (dst_size >= byte_size)
+ {
+ if (bit_size == sizeof(float)*8)
+ {
+ float float32 = ap_float.convertToFloat();
+ ::memcpy (dst, &float32, byte_size);
+ return byte_size;
+ }
+ else if (bit_size >= 64)
+ {
+ llvm::APInt ap_int(ap_float.bitcastToAPInt());
+ ::memcpy (dst, ap_int.getRawData(), byte_size);
+ return byte_size;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+
+//----------------------------------------------------------------------
+// Dumping types
+//----------------------------------------------------------------------
+#define DEPTH_INCREMENT 2
+
+void
+ClangASTContext::DumpValue (lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
+ Stream *s,
+ lldb::Format format,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t data_byte_offset,
+ size_t data_byte_size,
+ uint32_t bitfield_bit_size,
+ uint32_t bitfield_bit_offset,
+ bool show_types,
+ bool show_summary,
+ bool verbose,
+ uint32_t depth)
+{
+ if (!type)
+ return;
+
+ clang::QualType qual_type(GetQualType(type));
+ switch (qual_type->getTypeClass())
+ {
+ case clang::Type::Record:
+ if (GetCompleteType(type))
+ {
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ assert(record_decl);
+ uint32_t field_bit_offset = 0;
+ uint32_t field_byte_offset = 0;
+ const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(record_decl);
+ uint32_t child_idx = 0;
+
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+ if (cxx_record_decl)
+ {
+ // We might have base classes to print out first
+ clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+ for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+ base_class != base_class_end;
+ ++base_class)
+ {
+ const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
+
+ // Skip empty base classes
+ if (verbose == false && ClangASTContext::RecordHasFields(base_class_decl) == false)
+ continue;
+
+ if (base_class->isVirtual())
+ field_bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
+ else
+ field_bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8;
+ field_byte_offset = field_bit_offset / 8;
+ assert (field_bit_offset % 8 == 0);
+ if (child_idx == 0)
+ s->PutChar('{');
+ else
+ s->PutChar(',');
+
+ clang::QualType base_class_qual_type = base_class->getType();
+ std::string base_class_type_name(base_class_qual_type.getAsString());
+
+ // Indent and print the base class type name
+ s->Printf("\n%*s%s ", depth + DEPTH_INCREMENT, "", base_class_type_name.c_str());
+
+ clang::TypeInfo base_class_type_info = getASTContext()->getTypeInfo(base_class_qual_type);
+
+ // Dump the value of the member
+ CompilerType base_clang_type(getASTContext(), base_class_qual_type);
+ base_clang_type.DumpValue (exe_ctx,
+ s, // Stream to dump to
+ base_clang_type.GetFormat(), // The format with which to display the member
+ data, // Data buffer containing all bytes for this type
+ data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from
+ base_class_type_info.Width / 8, // Size of this type in bytes
+ 0, // Bitfield bit size
+ 0, // Bitfield bit offset
+ show_types, // Boolean indicating if we should show the variable types
+ show_summary, // Boolean indicating if we should show a summary for the current type
+ verbose, // Verbose output?
+ depth + DEPTH_INCREMENT); // Scope depth for any types that have children
+
+ ++child_idx;
+ }
+ }
+ uint32_t field_idx = 0;
+ clang::RecordDecl::field_iterator field, field_end;
+ for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx)
+ {
+ // Print the starting squiggly bracket (if this is the
+ // first member) or comma (for member 2 and beyond) for
+ // the struct/union/class member.
+ if (child_idx == 0)
+ s->PutChar('{');
+ else
+ s->PutChar(',');
+
+ // Indent
+ s->Printf("\n%*s", depth + DEPTH_INCREMENT, "");
+
+ clang::QualType field_type = field->getType();
+ // Print the member type if requested
+ // Figure out the type byte size (field_type_info.first) and
+ // alignment (field_type_info.second) from the AST context.
+ clang::TypeInfo field_type_info = getASTContext()->getTypeInfo(field_type);
+ assert(field_idx < record_layout.getFieldCount());
+ // Figure out the field offset within the current struct/union/class type
+ field_bit_offset = record_layout.getFieldOffset (field_idx);
+ field_byte_offset = field_bit_offset / 8;
+ uint32_t field_bitfield_bit_size = 0;
+ uint32_t field_bitfield_bit_offset = 0;
+ if (ClangASTContext::FieldIsBitfield (getASTContext(), *field, field_bitfield_bit_size))
+ field_bitfield_bit_offset = field_bit_offset % 8;
+
+ if (show_types)
+ {
+ std::string field_type_name(field_type.getAsString());
+ if (field_bitfield_bit_size > 0)
+ s->Printf("(%s:%u) ", field_type_name.c_str(), field_bitfield_bit_size);
+ else
+ s->Printf("(%s) ", field_type_name.c_str());
+ }
+ // Print the member name and equal sign
+ s->Printf("%s = ", field->getNameAsString().c_str());
+
+
+ // Dump the value of the member
+ CompilerType field_clang_type (getASTContext(), field_type);
+ field_clang_type.DumpValue (exe_ctx,
+ s, // Stream to dump to
+ field_clang_type.GetFormat(), // The format with which to display the member
+ data, // Data buffer containing all bytes for this type
+ data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from
+ field_type_info.Width / 8, // Size of this type in bytes
+ field_bitfield_bit_size, // Bitfield bit size
+ field_bitfield_bit_offset, // Bitfield bit offset
+ show_types, // Boolean indicating if we should show the variable types
+ show_summary, // Boolean indicating if we should show a summary for the current type
+ verbose, // Verbose output?
+ depth + DEPTH_INCREMENT); // Scope depth for any types that have children
+ }
+
+ // Indent the trailing squiggly bracket
+ if (child_idx > 0)
+ s->Printf("\n%*s}", depth, "");
+ }
+ return;
+
+ case clang::Type::Enum:
+ if (GetCompleteType(type))
+ {
+ const clang::EnumType *enutype = llvm::cast<clang::EnumType>(qual_type.getTypePtr());
+ const clang::EnumDecl *enum_decl = enutype->getDecl();
+ assert(enum_decl);
+ clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
+ lldb::offset_t offset = data_byte_offset;
+ const int64_t enum_value = data.GetMaxU64Bitfield(&offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset);
+ for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
+ {
+ if (enum_pos->getInitVal() == enum_value)
+ {
+ s->Printf("%s", enum_pos->getNameAsString().c_str());
+ return;
+ }
+ }
+ // If we have gotten here we didn't get find the enumerator in the
+ // enum decl, so just print the integer.
+ s->Printf("%" PRIi64, enum_value);
+ }
+ return;
+
+ case clang::Type::ConstantArray:
+ {
+ const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr());
+ bool is_array_of_characters = false;
+ clang::QualType element_qual_type = array->getElementType();
+
+ const clang::Type *canonical_type = element_qual_type->getCanonicalTypeInternal().getTypePtr();
+ if (canonical_type)
+ is_array_of_characters = canonical_type->isCharType();
+
+ const uint64_t element_count = array->getSize().getLimitedValue();
+
+ clang::TypeInfo field_type_info = getASTContext()->getTypeInfo(element_qual_type);
+
+ uint32_t element_idx = 0;
+ uint32_t element_offset = 0;
+ uint64_t element_byte_size = field_type_info.Width / 8;
+ uint32_t element_stride = element_byte_size;
+
+ if (is_array_of_characters)
+ {
+ s->PutChar('"');
+ data.Dump(s, data_byte_offset, lldb::eFormatChar, element_byte_size, element_count, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+ s->PutChar('"');
+ return;
+ }
+ else
+ {
+ CompilerType element_clang_type(getASTContext(), element_qual_type);
+ lldb::Format element_format = element_clang_type.GetFormat();
+
+ for (element_idx = 0; element_idx < element_count; ++element_idx)
+ {
+ // Print the starting squiggly bracket (if this is the
+ // first member) or comman (for member 2 and beyong) for
+ // the struct/union/class member.
+ if (element_idx == 0)
+ s->PutChar('{');
+ else
+ s->PutChar(',');
+
+ // Indent and print the index
+ s->Printf("\n%*s[%u] ", depth + DEPTH_INCREMENT, "", element_idx);
+
+ // Figure out the field offset within the current struct/union/class type
+ element_offset = element_idx * element_stride;
+
+ // Dump the value of the member
+ element_clang_type.DumpValue (exe_ctx,
+ s, // Stream to dump to
+ element_format, // The format with which to display the element
+ data, // Data buffer containing all bytes for this type
+ data_byte_offset + element_offset,// Offset into "data" where to grab value from
+ element_byte_size, // Size of this type in bytes
+ 0, // Bitfield bit size
+ 0, // Bitfield bit offset
+ show_types, // Boolean indicating if we should show the variable types
+ show_summary, // Boolean indicating if we should show a summary for the current type
+ verbose, // Verbose output?
+ depth + DEPTH_INCREMENT); // Scope depth for any types that have children
+ }
+
+ // Indent the trailing squiggly bracket
+ if (element_idx > 0)
+ s->Printf("\n%*s}", depth, "");
+ }
+ }
+ return;
+
+ case clang::Type::Typedef:
+ {
+ clang::QualType typedef_qual_type = llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType();
+
+ CompilerType typedef_clang_type (getASTContext(), typedef_qual_type);
+ lldb::Format typedef_format = typedef_clang_type.GetFormat();
+ clang::TypeInfo typedef_type_info = getASTContext()->getTypeInfo(typedef_qual_type);
+ uint64_t typedef_byte_size = typedef_type_info.Width / 8;
+
+ return typedef_clang_type.DumpValue (exe_ctx,
+ s, // Stream to dump to
+ typedef_format, // The format with which to display the element
+ data, // Data buffer containing all bytes for this type
+ data_byte_offset, // Offset into "data" where to grab value from
+ typedef_byte_size, // Size of this type in bytes
+ bitfield_bit_size, // Bitfield bit size
+ bitfield_bit_offset,// Bitfield bit offset
+ show_types, // Boolean indicating if we should show the variable types
+ show_summary, // Boolean indicating if we should show a summary for the current type
+ verbose, // Verbose output?
+ depth); // Scope depth for any types that have children
+ }
+ break;
+
+ case clang::Type::Auto:
+ {
+ clang::QualType elaborated_qual_type = llvm::cast<clang::AutoType>(qual_type)->getDeducedType();
+ CompilerType elaborated_clang_type (getASTContext(), elaborated_qual_type);
+ lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
+ clang::TypeInfo elaborated_type_info = getASTContext()->getTypeInfo(elaborated_qual_type);
+ uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
+
+ return elaborated_clang_type.DumpValue (exe_ctx,
+ s, // Stream to dump to
+ elaborated_format, // The format with which to display the element
+ data, // Data buffer containing all bytes for this type
+ data_byte_offset, // Offset into "data" where to grab value from
+ elaborated_byte_size, // Size of this type in bytes
+ bitfield_bit_size, // Bitfield bit size
+ bitfield_bit_offset,// Bitfield bit offset
+ show_types, // Boolean indicating if we should show the variable types
+ show_summary, // Boolean indicating if we should show a summary for the current type
+ verbose, // Verbose output?
+ depth); // Scope depth for any types that have children
+ }
+ break;
+
+ case clang::Type::Elaborated:
+ {
+ clang::QualType elaborated_qual_type = llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType();
+ CompilerType elaborated_clang_type (getASTContext(), elaborated_qual_type);
+ lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
+ clang::TypeInfo elaborated_type_info = getASTContext()->getTypeInfo(elaborated_qual_type);
+ uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
+
+ return elaborated_clang_type.DumpValue (exe_ctx,
+ s, // Stream to dump to
+ elaborated_format, // The format with which to display the element
+ data, // Data buffer containing all bytes for this type
+ data_byte_offset, // Offset into "data" where to grab value from
+ elaborated_byte_size, // Size of this type in bytes
+ bitfield_bit_size, // Bitfield bit size
+ bitfield_bit_offset,// Bitfield bit offset
+ show_types, // Boolean indicating if we should show the variable types
+ show_summary, // Boolean indicating if we should show a summary for the current type
+ verbose, // Verbose output?
+ depth); // Scope depth for any types that have children
+ }
+ break;
+
+ case clang::Type::Paren:
+ {
+ clang::QualType desugar_qual_type = llvm::cast<clang::ParenType>(qual_type)->desugar();
+ CompilerType desugar_clang_type (getASTContext(), desugar_qual_type);
+
+ lldb::Format desugar_format = desugar_clang_type.GetFormat();
+ clang::TypeInfo desugar_type_info = getASTContext()->getTypeInfo(desugar_qual_type);
+ uint64_t desugar_byte_size = desugar_type_info.Width / 8;
+
+ return desugar_clang_type.DumpValue (exe_ctx,
+ s, // Stream to dump to
+ desugar_format, // The format with which to display the element
+ data, // Data buffer containing all bytes for this type
+ data_byte_offset, // Offset into "data" where to grab value from
+ desugar_byte_size, // Size of this type in bytes
+ bitfield_bit_size, // Bitfield bit size
+ bitfield_bit_offset,// Bitfield bit offset
+ show_types, // Boolean indicating if we should show the variable types
+ show_summary, // Boolean indicating if we should show a summary for the current type
+ verbose, // Verbose output?
+ depth); // Scope depth for any types that have children
+ }
+ break;
+
+ default:
+ // We are down to a scalar type that we just need to display.
+ data.Dump(s,
+ data_byte_offset,
+ format,
+ data_byte_size,
+ 1,
+ UINT32_MAX,
+ LLDB_INVALID_ADDRESS,
+ bitfield_bit_size,
+ bitfield_bit_offset);
+
+ if (show_summary)
+ DumpSummary (type, exe_ctx, s, data, data_byte_offset, data_byte_size);
+ break;
+ }
+}
+
+
+
+
+bool
+ClangASTContext::DumpTypeValue (lldb::opaque_compiler_type_t type, Stream *s,
+ lldb::Format format,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t byte_offset,
+ size_t byte_size,
+ uint32_t bitfield_bit_size,
+ uint32_t bitfield_bit_offset,
+ ExecutionContextScope *exe_scope)
+{
+ if (!type)
+ return false;
+ if (IsAggregateType(type))
+ {
+ return false;
+ }
+ else
+ {
+ clang::QualType qual_type(GetQualType(type));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Typedef:
+ {
+ clang::QualType typedef_qual_type = llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType();
+ CompilerType typedef_clang_type (getASTContext(), typedef_qual_type);
+ if (format == eFormatDefault)
+ format = typedef_clang_type.GetFormat();
+ clang::TypeInfo typedef_type_info = getASTContext()->getTypeInfo(typedef_qual_type);
+ uint64_t typedef_byte_size = typedef_type_info.Width / 8;
+
+ return typedef_clang_type.DumpTypeValue (s,
+ format, // The format with which to display the element
+ data, // Data buffer containing all bytes for this type
+ byte_offset, // Offset into "data" where to grab value from
+ typedef_byte_size, // Size of this type in bytes
+ bitfield_bit_size, // Size in bits of a bitfield value, if zero don't treat as a bitfield
+ bitfield_bit_offset, // Offset in bits of a bitfield value if bitfield_bit_size != 0
+ exe_scope);
+ }
+ break;
+
+ case clang::Type::Enum:
+ // If our format is enum or default, show the enumeration value as
+ // its enumeration string value, else just display it as requested.
+ if ((format == eFormatEnum || format == eFormatDefault) && GetCompleteType(type))
+ {
+ const clang::EnumType *enutype = llvm::cast<clang::EnumType>(qual_type.getTypePtr());
+ const clang::EnumDecl *enum_decl = enutype->getDecl();
+ assert(enum_decl);
+ clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
+ const bool is_signed = qual_type->isSignedIntegerOrEnumerationType();
+ lldb::offset_t offset = byte_offset;
+ if (is_signed)
+ {
+ const int64_t enum_svalue = data.GetMaxS64Bitfield (&offset, byte_size, bitfield_bit_size, bitfield_bit_offset);
+ for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
+ {
+ if (enum_pos->getInitVal().getSExtValue() == enum_svalue)
+ {
+ s->PutCString (enum_pos->getNameAsString().c_str());
+ return true;
+ }
+ }
+ // If we have gotten here we didn't get find the enumerator in the
+ // enum decl, so just print the integer.
+ s->Printf("%" PRIi64, enum_svalue);
+ }
+ else
+ {
+ const uint64_t enum_uvalue = data.GetMaxU64Bitfield (&offset, byte_size, bitfield_bit_size, bitfield_bit_offset);
+ for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
+ {
+ if (enum_pos->getInitVal().getZExtValue() == enum_uvalue)
+ {
+ s->PutCString (enum_pos->getNameAsString().c_str());
+ return true;
+ }
+ }
+ // If we have gotten here we didn't get find the enumerator in the
+ // enum decl, so just print the integer.
+ s->Printf("%" PRIu64, enum_uvalue);
+ }
+ return true;
+ }
+ // format was not enum, just fall through and dump the value as requested....
+
+ default:
+ // We are down to a scalar type that we just need to display.
+ {
+ uint32_t item_count = 1;
+ // A few formats, we might need to modify our size and count for depending
+ // on how we are trying to display the value...
+ switch (format)
+ {
+ default:
+ case eFormatBoolean:
+ case eFormatBinary:
+ case eFormatComplex:
+ case eFormatCString: // NULL terminated C strings
+ case eFormatDecimal:
+ case eFormatEnum:
+ case eFormatHex:
+ case eFormatHexUppercase:
+ case eFormatFloat:
+ case eFormatOctal:
+ case eFormatOSType:
+ case eFormatUnsigned:
+ case eFormatPointer:
+ case eFormatVectorOfChar:
+ case eFormatVectorOfSInt8:
+ case eFormatVectorOfUInt8:
+ case eFormatVectorOfSInt16:
+ case eFormatVectorOfUInt16:
+ case eFormatVectorOfSInt32:
+ case eFormatVectorOfUInt32:
+ case eFormatVectorOfSInt64:
+ case eFormatVectorOfUInt64:
+ case eFormatVectorOfFloat32:
+ case eFormatVectorOfFloat64:
+ case eFormatVectorOfUInt128:
+ break;
+
+ case eFormatChar:
+ case eFormatCharPrintable:
+ case eFormatCharArray:
+ case eFormatBytes:
+ case eFormatBytesWithASCII:
+ item_count = byte_size;
+ byte_size = 1;
+ break;
+
+ case eFormatUnicode16:
+ item_count = byte_size / 2;
+ byte_size = 2;
+ break;
+
+ case eFormatUnicode32:
+ item_count = byte_size / 4;
+ byte_size = 4;
+ break;
+ }
+ return data.Dump (s,
+ byte_offset,
+ format,
+ byte_size,
+ item_count,
+ UINT32_MAX,
+ LLDB_INVALID_ADDRESS,
+ bitfield_bit_size,
+ bitfield_bit_offset,
+ exe_scope);
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+
+
+void
+ClangASTContext::DumpSummary (lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
+ Stream *s,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t data_byte_offset,
+ size_t data_byte_size)
+{
+ uint32_t length = 0;
+ if (IsCStringType (type, length))
+ {
+ if (exe_ctx)
+ {
+ Process *process = exe_ctx->GetProcessPtr();
+ if (process)
+ {
+ lldb::offset_t offset = data_byte_offset;
+ lldb::addr_t pointer_address = data.GetMaxU64(&offset, data_byte_size);
+ std::vector<uint8_t> buf;
+ if (length > 0)
+ buf.resize (length);
+ else
+ buf.resize (256);
+
+ lldb_private::DataExtractor cstr_data(&buf.front(), buf.size(), process->GetByteOrder(), 4);
+ buf.back() = '\0';
+ size_t bytes_read;
+ size_t total_cstr_len = 0;
+ Error error;
+ while ((bytes_read = process->ReadMemory (pointer_address, &buf.front(), buf.size(), error)) > 0)
+ {
+ const size_t len = strlen((const char *)&buf.front());
+ if (len == 0)
+ break;
+ if (total_cstr_len == 0)
+ s->PutCString (" \"");
+ cstr_data.Dump(s, 0, lldb::eFormatChar, 1, len, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+ total_cstr_len += len;
+ if (len < buf.size())
+ break;
+ pointer_address += total_cstr_len;
+ }
+ if (total_cstr_len > 0)
+ s->PutChar ('"');
+ }
+ }
+ }
+}
+
+void
+ClangASTContext::DumpTypeDescription (lldb::opaque_compiler_type_t type)
+{
+ StreamFile s (stdout, false);
+ DumpTypeDescription (type, &s);
+ ClangASTMetadata *metadata = ClangASTContext::GetMetadata (getASTContext(), type);
+ if (metadata)
+ {
+ metadata->Dump (&s);
+ }
+}
+
+void
+ClangASTContext::DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream *s)
+{
+ if (type)
+ {
+ clang::QualType qual_type(GetQualType(type));
+
+ llvm::SmallVector<char, 1024> buf;
+ llvm::raw_svector_ostream llvm_ostrm (buf);
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ {
+ GetCompleteType(type);
+
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
+ assert (objc_class_type);
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ if (class_interface_decl)
+ {
+ clang::PrintingPolicy policy = getASTContext()->getPrintingPolicy();
+ class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel());
+ }
+ }
+ }
+ break;
+
+ case clang::Type::Typedef:
+ {
+ const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
+ if (typedef_type)
+ {
+ const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
+ std::string clang_typedef_name (typedef_decl->getQualifiedNameAsString());
+ if (!clang_typedef_name.empty())
+ {
+ s->PutCString ("typedef ");
+ s->PutCString (clang_typedef_name.c_str());
+ }
+ }
+ }
+ break;
+
+ case clang::Type::Auto:
+ CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).DumpTypeDescription(s);
+ return;
+
+ case clang::Type::Elaborated:
+ CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).DumpTypeDescription(s);
+ return;
+
+ case clang::Type::Paren:
+ CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).DumpTypeDescription(s);
+ return;
+
+ case clang::Type::Record:
+ {
+ GetCompleteType(type);
+
+ const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
+ const clang::RecordDecl *record_decl = record_type->getDecl();
+ const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
+
+ if (cxx_record_decl)
+ cxx_record_decl->print(llvm_ostrm, getASTContext()->getPrintingPolicy(), s->GetIndentLevel());
+ else
+ record_decl->print(llvm_ostrm, getASTContext()->getPrintingPolicy(), s->GetIndentLevel());
+ }
+ break;
+
+ default:
+ {
+ const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
+ if (tag_type)
+ {
+ clang::TagDecl *tag_decl = tag_type->getDecl();
+ if (tag_decl)
+ tag_decl->print(llvm_ostrm, 0);
+ }
+ else
+ {
+ std::string clang_type_name(qual_type.getAsString());
+ if (!clang_type_name.empty())
+ s->PutCString (clang_type_name.c_str());
+ }
+ }
+ }
+
+ if (buf.size() > 0)
+ {
+ s->Write (buf.data(), buf.size());
+ }
+ }
+}
+
+void
+ClangASTContext::DumpTypeName (const CompilerType &type)
+{
+ if (IsClangType(type))
+ {
+ clang::QualType qual_type(GetCanonicalQualType(RemoveFastQualifiers(type)));
+
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ switch (type_class)
+ {
+ case clang::Type::Record:
+ {
+ const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+ if (cxx_record_decl)
+ printf("class %s", cxx_record_decl->getName().str().c_str());
+ }
+ break;
+
+ case clang::Type::Enum:
+ {
+ clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
+ if (enum_decl)
+ {
+ printf("enum %s", enum_decl->getName().str().c_str());
+ }
+ }
+ break;
+
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ {
+ const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
+ if (objc_class_type)
+ {
+ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+ // We currently can't complete objective C types through the newly added ASTContext
+ // because it only supports TagDecl objects right now...
+ if (class_interface_decl)
+ printf("@class %s", class_interface_decl->getName().str().c_str());
+ }
+ }
+ break;
+
+
+ case clang::Type::Typedef:
+ printf("typedef %s", llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getName().str().c_str());
+ break;
+
+ case clang::Type::Auto:
+ printf("auto ");
+ return DumpTypeName (CompilerType (type.GetTypeSystem(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()));
+
+ case clang::Type::Elaborated:
+ printf("elaborated ");
+ return DumpTypeName (CompilerType (type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()));
+
+ case clang::Type::Paren:
+ printf("paren ");
+ return DumpTypeName (CompilerType (type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()));
+
+ default:
+ printf("ClangASTContext::DumpTypeName() type_class = %u", type_class);
+ break;
+ }
+ }
+
+}
+
+
+
+clang::ClassTemplateDecl *
+ClangASTContext::ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
+ lldb::AccessType access_type,
+ const char *parent_name,
+ int tag_decl_kind,
+ const ClangASTContext::TemplateParameterInfos &template_param_infos)
+{
+ if (template_param_infos.IsValid())
+ {
+ std::string template_basename(parent_name);
+ template_basename.erase (template_basename.find('<'));
+
+ return CreateClassTemplateDecl (decl_ctx,
+ access_type,
+ template_basename.c_str(),
+ tag_decl_kind,
+ template_param_infos);
+ }
+ return NULL;
+}
+
+void
+ClangASTContext::CompleteTagDecl (void *baton, clang::TagDecl *decl)
+{
+ ClangASTContext *ast = (ClangASTContext *)baton;
+ SymbolFile *sym_file = ast->GetSymbolFile();
+ if (sym_file)
+ {
+ CompilerType clang_type = GetTypeForDecl (decl);
+ if (clang_type)
+ sym_file->CompleteType (clang_type);
+ }
+}
+
+void
+ClangASTContext::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl)
+{
+ ClangASTContext *ast = (ClangASTContext *)baton;
+ SymbolFile *sym_file = ast->GetSymbolFile();
+ if (sym_file)
+ {
+ CompilerType clang_type = GetTypeForDecl (decl);
+ if (clang_type)
+ sym_file->CompleteType (clang_type);
+ }
+}
+
+
+DWARFASTParser *
+ClangASTContext::GetDWARFParser ()
+{
+ if (!m_dwarf_ast_parser_ap)
+ m_dwarf_ast_parser_ap.reset(new DWARFASTParserClang(*this));
+ return m_dwarf_ast_parser_ap.get();
+}
+
+
+bool
+ClangASTContext::LayoutRecordType(void *baton,
+ const clang::RecordDecl *record_decl,
+ uint64_t &bit_size,
+ uint64_t &alignment,
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
+{
+ ClangASTContext *ast = (ClangASTContext *)baton;
+ DWARFASTParserClang *dwarf_ast_parser = (DWARFASTParserClang *)ast->GetDWARFParser();
+ return dwarf_ast_parser->LayoutRecordType(record_decl, bit_size, alignment, field_offsets, base_offsets, vbase_offsets);
+}
+
+//----------------------------------------------------------------------
+// CompilerDecl override functions
+//----------------------------------------------------------------------
+lldb::VariableSP
+ClangASTContext::DeclGetVariable (void *opaque_decl)
+{
+ if (llvm::dyn_cast<clang::VarDecl>((clang::Decl *)opaque_decl))
+ {
+ auto decl_search_it = m_decl_objects.find(opaque_decl);
+ if (decl_search_it != m_decl_objects.end())
+ return std::static_pointer_cast<Variable>(decl_search_it->second);
+ }
+ return VariableSP();
+}
+
+void
+ClangASTContext::DeclLinkToObject (void *opaque_decl, std::shared_ptr<void> object)
+{
+ if (m_decl_objects.find(opaque_decl) == m_decl_objects.end())
+ m_decl_objects.insert(std::make_pair(opaque_decl, object));
+}
+
+ConstString
+ClangASTContext::DeclGetName (void *opaque_decl)
+{
+ if (opaque_decl)
+ {
+ clang::NamedDecl *nd = llvm::dyn_cast<NamedDecl>((clang::Decl*)opaque_decl);
+ if (nd != nullptr)
+ return ConstString(nd->getDeclName().getAsString());
+ }
+ return ConstString();
+}
+
+ConstString
+ClangASTContext::DeclGetMangledName (void *opaque_decl)
+{
+ if (opaque_decl)
+ {
+ clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>((clang::Decl*)opaque_decl);
+ if (nd != nullptr && !llvm::isa<clang::ObjCMethodDecl>(nd))
+ {
+ clang::MangleContext *mc = getMangleContext();
+ if (mc && mc->shouldMangleCXXName(nd))
+ {
+ llvm::SmallVector<char, 1024> buf;
+ llvm::raw_svector_ostream llvm_ostrm (buf);
+ if (llvm::isa<clang::CXXConstructorDecl>(nd))
+ {
+ mc->mangleCXXCtor(llvm::dyn_cast<clang::CXXConstructorDecl>(nd), Ctor_Complete, llvm_ostrm);
+ }
+ else if (llvm::isa<clang::CXXDestructorDecl>(nd))
+ {
+ mc->mangleCXXDtor(llvm::dyn_cast<clang::CXXDestructorDecl>(nd), Dtor_Complete, llvm_ostrm);
+ }
+ else
+ {
+ mc->mangleName(nd, llvm_ostrm);
+ }
+ if (buf.size() > 0)
+ return ConstString(buf.data(), buf.size());
+ }
+ }
+ }
+ return ConstString();
+}
+
+CompilerDeclContext
+ClangASTContext::DeclGetDeclContext (void *opaque_decl)
+{
+ if (opaque_decl)
+ return CompilerDeclContext(this, ((clang::Decl*)opaque_decl)->getDeclContext());
+ else
+ return CompilerDeclContext();
+}
+
+CompilerType
+ClangASTContext::DeclGetFunctionReturnType(void *opaque_decl)
+{
+ if (clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>((clang::Decl*)opaque_decl))
+ return CompilerType(this, func_decl->getReturnType().getAsOpaquePtr());
+ if (clang::ObjCMethodDecl *objc_method = llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl*)opaque_decl))
+ return CompilerType(this, objc_method->getReturnType().getAsOpaquePtr());
+ else
+ return CompilerType();
+}
+
+size_t
+ClangASTContext::DeclGetFunctionNumArguments(void *opaque_decl)
+{
+ if (clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>((clang::Decl*)opaque_decl))
+ return func_decl->param_size();
+ if (clang::ObjCMethodDecl *objc_method = llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl*)opaque_decl))
+ return objc_method->param_size();
+ else
+ return 0;
+}
+
+CompilerType
+ClangASTContext::DeclGetFunctionArgumentType (void *opaque_decl, size_t idx)
+{
+ if (clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>((clang::Decl*)opaque_decl))
+ {
+ if (idx < func_decl->param_size())
+ {
+ ParmVarDecl *var_decl = func_decl->getParamDecl(idx);
+ if (var_decl)
+ return CompilerType(this, var_decl->getOriginalType().getAsOpaquePtr());
+ }
+ }
+ else if (clang::ObjCMethodDecl *objc_method = llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl*)opaque_decl))
+ {
+ if (idx < objc_method->param_size())
+ return CompilerType(this, objc_method->parameters()[idx]->getOriginalType().getAsOpaquePtr());
+ }
+ return CompilerType();
+}
+
+//----------------------------------------------------------------------
+// CompilerDeclContext functions
+//----------------------------------------------------------------------
+
+std::vector<CompilerDecl>
+ClangASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name)
+{
+ std::vector<CompilerDecl> found_decls;
+ if (opaque_decl_ctx)
+ {
+ DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx;
+ std::set<DeclContext *> searched;
+ std::multimap<DeclContext *, DeclContext *> search_queue;
+ SymbolFile *symbol_file = GetSymbolFile();
+
+ for (clang::DeclContext *decl_context = root_decl_ctx; decl_context != nullptr && found_decls.empty(); decl_context = decl_context->getParent())
+ {
+ search_queue.insert(std::make_pair(decl_context, decl_context));
+
+ for (auto it = search_queue.find(decl_context); it != search_queue.end(); it++)
+ {
+ if (!searched.insert(it->second).second)
+ continue;
+ symbol_file->ParseDeclsForContext(CompilerDeclContext(this, it->second));
+
+ for (clang::Decl *child : it->second->decls())
+ {
+ if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast<clang::UsingDirectiveDecl>(child))
+ {
+ clang::DeclContext *from = ud->getCommonAncestor();
+ if (searched.find(ud->getNominatedNamespace()) == searched.end())
+ search_queue.insert(std::make_pair(from, ud->getNominatedNamespace()));
+ }
+ else if (clang::UsingDecl *ud = llvm::dyn_cast<clang::UsingDecl>(child))
+ {
+ for (clang::UsingShadowDecl *usd : ud->shadows())
+ {
+ clang::Decl *target = usd->getTargetDecl();
+ if (clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(target))
+ {
+ IdentifierInfo *ii = nd->getIdentifier();
+ if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr)))
+ found_decls.push_back(CompilerDecl(this, nd));
+ }
+ }
+ }
+ else if (clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(child))
+ {
+ IdentifierInfo *ii = nd->getIdentifier();
+ if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr)))
+ found_decls.push_back(CompilerDecl(this, nd));
+ }
+ }
+ }
+ }
+ }
+ return found_decls;
+}
+
+// Look for child_decl_ctx's lookup scope in frame_decl_ctx and its parents,
+// and return the number of levels it took to find it, or LLDB_INVALID_DECL_LEVEL
+// if not found. If the decl was imported via a using declaration, its name and/or
+// type, if set, will be used to check that the decl found in the scope is a match.
+//
+// The optional name is required by languages (like C++) to handle using declarations
+// like:
+//
+// void poo();
+// namespace ns {
+// void foo();
+// void goo();
+// }
+// void bar() {
+// using ns::foo;
+// // CountDeclLevels returns 0 for 'foo', 1 for 'poo', and
+// // LLDB_INVALID_DECL_LEVEL for 'goo'.
+// }
+//
+// The optional type is useful in the case that there's a specific overload
+// that we're looking for that might otherwise be shadowed, like:
+//
+// void foo(int);
+// namespace ns {
+// void foo();
+// }
+// void bar() {
+// using ns::foo;
+// // CountDeclLevels returns 0 for { 'foo', void() },
+// // 1 for { 'foo', void(int) }, and
+// // LLDB_INVALID_DECL_LEVEL for { 'foo', void(int, int) }.
+// }
+//
+// NOTE: Because file statics are at the TranslationUnit along with globals, a
+// function at file scope will return the same level as a function at global scope.
+// Ideally we'd like to treat the file scope as an additional scope just below the
+// global scope. More work needs to be done to recognise that, if the decl we're
+// trying to look up is static, we should compare its source file with that of the
+// current scope and return a lower number for it.
+uint32_t
+ClangASTContext::CountDeclLevels (clang::DeclContext *frame_decl_ctx,
+ clang::DeclContext *child_decl_ctx,
+ ConstString *child_name,
+ CompilerType *child_type)
+{
+ if (frame_decl_ctx)
+ {
+ std::set<DeclContext *> searched;
+ std::multimap<DeclContext *, DeclContext *> search_queue;
+ SymbolFile *symbol_file = GetSymbolFile();
+
+ // Get the lookup scope for the decl we're trying to find.
+ clang::DeclContext *parent_decl_ctx = child_decl_ctx->getParent();
+
+ // Look for it in our scope's decl context and its parents.
+ uint32_t level = 0;
+ for (clang::DeclContext *decl_ctx = frame_decl_ctx; decl_ctx != nullptr; decl_ctx = decl_ctx->getParent())
+ {
+ if (!decl_ctx->isLookupContext())
+ continue;
+ if (decl_ctx == parent_decl_ctx)
+ // Found it!
+ return level;
+ search_queue.insert(std::make_pair(decl_ctx, decl_ctx));
+ for (auto it = search_queue.find(decl_ctx); it != search_queue.end(); it++)
+ {
+ if (searched.find(it->second) != searched.end())
+ continue;
+ searched.insert(it->second);
+ symbol_file->ParseDeclsForContext(CompilerDeclContext(this, it->second));
+
+ for (clang::Decl *child : it->second->decls())
+ {
+ if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast<clang::UsingDirectiveDecl>(child))
+ {
+ clang::DeclContext *ns = ud->getNominatedNamespace();
+ if (ns == parent_decl_ctx)
+ // Found it!
+ return level;
+ clang::DeclContext *from = ud->getCommonAncestor();
+ if (searched.find(ns) == searched.end())
+ search_queue.insert(std::make_pair(from, ns));
+ }
+ else if (child_name)
+ {
+ if (clang::UsingDecl *ud = llvm::dyn_cast<clang::UsingDecl>(child))
+ {
+ for (clang::UsingShadowDecl *usd : ud->shadows())
+ {
+ clang::Decl *target = usd->getTargetDecl();
+ clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(target);
+ if (!nd)
+ continue;
+ // Check names.
+ IdentifierInfo *ii = nd->getIdentifier();
+ if (ii == nullptr || !ii->getName().equals(child_name->AsCString(nullptr)))
+ continue;
+ // Check types, if one was provided.
+ if (child_type)
+ {
+ CompilerType clang_type = ClangASTContext::GetTypeForDecl(nd);
+ if (!AreTypesSame(clang_type, *child_type, /*ignore_qualifiers=*/true))
+ continue;
+ }
+ // Found it!
+ return level;
+ }
+ }
+ }
+ }
+ }
+ ++level;
+ }
+ }
+ return LLDB_INVALID_DECL_LEVEL;
+}
+
+bool
+ClangASTContext::DeclContextIsStructUnionOrClass (void *opaque_decl_ctx)
+{
+ if (opaque_decl_ctx)
+ return ((clang::DeclContext *)opaque_decl_ctx)->isRecord();
+ else
+ return false;
+}
+
+ConstString
+ClangASTContext::DeclContextGetName (void *opaque_decl_ctx)
+{
+ if (opaque_decl_ctx)
+ {
+ clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx);
+ if (named_decl)
+ return ConstString(named_decl->getName());
+ }
+ return ConstString();
+}
+
+ConstString
+ClangASTContext::DeclContextGetScopeQualifiedName (void *opaque_decl_ctx)
+{
+ if (opaque_decl_ctx)
+ {
+ clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx);
+ if (named_decl)
+ return ConstString(llvm::StringRef(named_decl->getQualifiedNameAsString()));
+ }
+ return ConstString();
+}
+
+bool
+ClangASTContext::DeclContextIsClassMethod (void *opaque_decl_ctx,
+ lldb::LanguageType *language_ptr,
+ bool *is_instance_method_ptr,
+ ConstString *language_object_name_ptr)
+{
+ if (opaque_decl_ctx)
+ {
+ clang::DeclContext *decl_ctx = (clang::DeclContext *)opaque_decl_ctx;
+ if (ObjCMethodDecl *objc_method = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_ctx))
+ {
+ if (is_instance_method_ptr)
+ *is_instance_method_ptr = objc_method->isInstanceMethod();
+ if (language_ptr)
+ *language_ptr = eLanguageTypeObjC;
+ if (language_object_name_ptr)
+ language_object_name_ptr->SetCString("self");
+ return true;
+ }
+ else if (CXXMethodDecl *cxx_method = llvm::dyn_cast<clang::CXXMethodDecl>(decl_ctx))
+ {
+ if (is_instance_method_ptr)
+ *is_instance_method_ptr = cxx_method->isInstance();
+ if (language_ptr)
+ *language_ptr = eLanguageTypeC_plus_plus;
+ if (language_object_name_ptr)
+ language_object_name_ptr->SetCString("this");
return true;
}
else if (clang::FunctionDecl *function_decl = llvm::dyn_cast<clang::FunctionDecl>(decl_ctx))
@@ -2195,13 +10018,129 @@ ClangASTContext::GetClassMethodInfoForDeclContext (clang::DeclContext *decl_ctx,
ClangASTMetadata *metadata = GetMetadata (&decl_ctx->getParentASTContext(), function_decl);
if (metadata && metadata->HasObjectPtr())
{
- language_object_name.SetCString (metadata->GetObjectPtrName());
- language = eLanguageTypeObjC;
- is_instance_method = true;
+ if (is_instance_method_ptr)
+ *is_instance_method_ptr = true;
+ if (language_ptr)
+ *language_ptr = eLanguageTypeObjC;
+ if (language_object_name_ptr)
+ language_object_name_ptr->SetCString (metadata->GetObjectPtrName());
+ return true;
}
- return true;
}
}
return false;
}
+clang::DeclContext *
+ClangASTContext::DeclContextGetAsDeclContext (const CompilerDeclContext &dc)
+{
+ if (dc.IsClang())
+ return (clang::DeclContext *)dc.GetOpaqueDeclContext();
+ return nullptr;
+}
+
+
+ObjCMethodDecl *
+ClangASTContext::DeclContextGetAsObjCMethodDecl (const CompilerDeclContext &dc)
+{
+ if (dc.IsClang())
+ return llvm::dyn_cast<clang::ObjCMethodDecl>((clang::DeclContext *)dc.GetOpaqueDeclContext());
+ return nullptr;
+}
+
+CXXMethodDecl *
+ClangASTContext::DeclContextGetAsCXXMethodDecl (const CompilerDeclContext &dc)
+{
+ if (dc.IsClang())
+ return llvm::dyn_cast<clang::CXXMethodDecl>((clang::DeclContext *)dc.GetOpaqueDeclContext());
+ return nullptr;
+}
+
+clang::FunctionDecl *
+ClangASTContext::DeclContextGetAsFunctionDecl (const CompilerDeclContext &dc)
+{
+ if (dc.IsClang())
+ return llvm::dyn_cast<clang::FunctionDecl>((clang::DeclContext *)dc.GetOpaqueDeclContext());
+ return nullptr;
+}
+
+clang::NamespaceDecl *
+ClangASTContext::DeclContextGetAsNamespaceDecl (const CompilerDeclContext &dc)
+{
+ if (dc.IsClang())
+ return llvm::dyn_cast<clang::NamespaceDecl>((clang::DeclContext *)dc.GetOpaqueDeclContext());
+ return nullptr;
+}
+
+ClangASTMetadata *
+ClangASTContext::DeclContextGetMetaData (const CompilerDeclContext &dc, const void *object)
+{
+ clang::ASTContext *ast = DeclContextGetClangASTContext (dc);
+ if (ast)
+ return ClangASTContext::GetMetadata (ast, object);
+ return nullptr;
+}
+
+clang::ASTContext *
+ClangASTContext::DeclContextGetClangASTContext (const CompilerDeclContext &dc)
+{
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(dc.GetTypeSystem());
+ if (ast)
+ return ast->getASTContext();
+ return nullptr;
+}
+
+ClangASTContextForExpressions::ClangASTContextForExpressions (Target &target) :
+ ClangASTContext (target.GetArchitecture().GetTriple().getTriple().c_str()),
+ m_target_wp(target.shared_from_this()),
+ m_persistent_variables (new ClangPersistentVariables)
+{
+}
+
+UserExpression *
+ClangASTContextForExpressions::GetUserExpression (const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ Expression::ResultType desired_type,
+ const EvaluateExpressionOptions &options)
+{
+ TargetSP target_sp = m_target_wp.lock();
+ if (!target_sp)
+ return nullptr;
+
+ return new ClangUserExpression(*target_sp.get(), expr, expr_prefix, language, desired_type, options);
+}
+
+FunctionCaller *
+ClangASTContextForExpressions::GetFunctionCaller (const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name)
+{
+ TargetSP target_sp = m_target_wp.lock();
+ if (!target_sp)
+ return nullptr;
+
+ Process *process = target_sp->GetProcessSP().get();
+ if (!process)
+ return nullptr;
+
+ return new ClangFunctionCaller (*process, return_type, function_address, arg_value_list, name);
+}
+
+UtilityFunction *
+ClangASTContextForExpressions::GetUtilityFunction (const char *text,
+ const char *name)
+{
+ TargetSP target_sp = m_target_wp.lock();
+ if (!target_sp)
+ return nullptr;
+
+ return new ClangUtilityFunction(*target_sp.get(), text, name);
+}
+
+PersistentExpressionState *
+ClangASTContextForExpressions::GetPersistentExpressionState ()
+{
+ return m_persistent_variables.get();
+}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp
index dd73b35..1419370 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/ClangASTImporter.cpp
@@ -16,7 +16,6 @@
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Utility/LLDBAssert.h"
using namespace lldb_private;
@@ -60,14 +59,39 @@ ClangASTImporter::CopyType (clang::ASTContext *dst_ast,
return QualType();
}
-lldb::clang_type_t
+lldb::opaque_compiler_type_t
ClangASTImporter::CopyType (clang::ASTContext *dst_ast,
clang::ASTContext *src_ast,
- lldb::clang_type_t type)
+ lldb::opaque_compiler_type_t type)
{
return CopyType (dst_ast, src_ast, QualType::getFromOpaquePtr(type)).getAsOpaquePtr();
}
+CompilerType
+ClangASTImporter::CopyType (ClangASTContext &dst_ast,
+ const CompilerType &src_type)
+{
+ clang::ASTContext *dst_clang_ast = dst_ast.getASTContext();
+ if (dst_clang_ast)
+ {
+ ClangASTContext *src_ast = llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem());
+ if (src_ast)
+ {
+ clang::ASTContext *src_clang_ast = src_ast->getASTContext();
+ if (src_clang_ast)
+ {
+ lldb::opaque_compiler_type_t dst_clang_type = CopyType(dst_clang_ast,
+ src_clang_ast,
+ src_type.GetOpaqueQualType());
+
+ if (dst_clang_type)
+ return CompilerType(&dst_ast, dst_clang_type);
+ }
+ }
+ }
+ return CompilerType();
+}
+
clang::Decl *
ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast,
clang::ASTContext *src_ast,
@@ -238,11 +262,19 @@ public:
}
};
-lldb::clang_type_t
+lldb::opaque_compiler_type_t
ClangASTImporter::DeportType (clang::ASTContext *dst_ctx,
clang::ASTContext *src_ctx,
- lldb::clang_type_t type)
-{
+ lldb::opaque_compiler_type_t type)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf(" [ClangASTImporter] DeportType called on (%sType*)0x%llx from (ASTContext*)%p to (ASTContext*)%p",
+ QualType::getFromOpaquePtr(type)->getTypeClassName(), (unsigned long long)type,
+ static_cast<void*>(src_ctx),
+ static_cast<void*>(dst_ctx));
+
MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
if (!minion_sp)
@@ -261,7 +293,7 @@ ClangASTImporter::DeportType (clang::ASTContext *dst_ctx,
minion_sp->InitDeportWorkQueues(&decls_to_deport,
&decls_already_deported);
- lldb::clang_type_t result = CopyType(dst_ctx, src_ctx, type);
+ lldb::opaque_compiler_type_t result = CopyType(dst_ctx, src_ctx, type);
minion_sp->ExecuteDeportWorkQueues();
@@ -280,7 +312,7 @@ ClangASTImporter::DeportDecl (clang::ASTContext *dst_ctx,
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
- log->Printf(" [ClangASTImporter] DeportDecl called on (%sDecl*)%p from (ASTContext*)%p to (ASTContex*)%p",
+ log->Printf(" [ClangASTImporter] DeportDecl called on (%sDecl*)%p from (ASTContext*)%p to (ASTContext*)%p",
decl->getDeclKindName(), static_cast<void*>(decl),
static_cast<void*>(src_ctx),
static_cast<void*>(dst_ctx));
@@ -422,6 +454,68 @@ ClangASTImporter::CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface
}
bool
+ClangASTImporter::CompleteAndFetchChildren (clang::QualType type)
+{
+ if (!RequireCompleteType(type))
+ return false;
+
+ if (const TagType *tag_type = type->getAs<TagType>())
+ {
+ TagDecl *tag_decl = tag_type->getDecl();
+
+ DeclOrigin decl_origin = GetDeclOrigin(tag_decl);
+
+ if (!decl_origin.Valid())
+ return false;
+
+ MinionSP minion_sp (GetMinion(&tag_decl->getASTContext(), decl_origin.ctx));
+
+ TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(decl_origin.decl);
+
+ for (Decl *origin_child_decl : origin_tag_decl->decls())
+ {
+ minion_sp->Import(origin_child_decl);
+ }
+
+ if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl))
+ {
+ record_decl->setHasLoadedFieldsFromExternalStorage(true);
+ }
+
+ return true;
+ }
+
+ if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>())
+ {
+ if (ObjCInterfaceDecl *objc_interface_decl = objc_object_type->getInterface())
+ {
+ DeclOrigin decl_origin = GetDeclOrigin(objc_interface_decl);
+
+ if (!decl_origin.Valid())
+ return false;
+
+ MinionSP minion_sp (GetMinion(&objc_interface_decl->getASTContext(), decl_origin.ctx));
+
+ ObjCInterfaceDecl *origin_interface_decl = llvm::dyn_cast<ObjCInterfaceDecl>(decl_origin.decl);
+
+ for (Decl *origin_child_decl : origin_interface_decl->decls())
+ {
+ minion_sp->Import(origin_child_decl);
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+bool
ClangASTImporter::RequireCompleteType (clang::QualType type)
{
if (type.isNull())
@@ -600,7 +694,7 @@ void
ClangASTImporter::Minion::InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport,
std::set<clang::NamedDecl *> *decls_already_deported)
{
- assert(!m_decls_to_deport); // TODO make debug only
+ assert(!m_decls_to_deport);
assert(!m_decls_already_deported);
m_decls_to_deport = decls_to_deport;
@@ -610,7 +704,7 @@ ClangASTImporter::Minion::InitDeportWorkQueues (std::set<clang::NamedDecl *> *de
void
ClangASTImporter::Minion::ExecuteDeportWorkQueues ()
{
- assert(m_decls_to_deport); // TODO make debug only
+ assert(m_decls_to_deport);
assert(m_decls_already_deported);
ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&getToContext());
@@ -623,6 +717,7 @@ ClangASTImporter::Minion::ExecuteDeportWorkQueues ()
m_decls_to_deport->erase(decl);
DeclOrigin &origin = to_context_md->m_origins[decl];
+ UNUSED_IF_ASSERT_DISABLED(origin);
assert (origin.ctx == m_source_ctx); // otherwise we should never have added this
// because it doesn't need to be deported
@@ -763,7 +858,8 @@ ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
user_id != LLDB_INVALID_UID)
{
- to_context_md->m_origins[to] = origin_iter->second;
+ if (origin_iter->second.ctx != &to->getASTContext())
+ to_context_md->m_origins[to] = origin_iter->second;
}
MinionSP direct_completer = m_master.GetMinion(&to->getASTContext(), origin_iter->second.ctx);
@@ -784,10 +880,14 @@ ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
{
if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to))
{
- NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
-
- if (!m_decls_already_deported->count(to_named_decl))
- m_decls_to_deport->insert(to_named_decl);
+ RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from);
+ if (from_record_decl == nullptr || from_record_decl->isInjectedClassName() == false)
+ {
+ NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
+
+ if (!m_decls_already_deported->count(to_named_decl))
+ m_decls_to_deport->insert(to_named_decl);
+ }
}
}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangASTType.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangASTType.cpp
deleted file mode 100644
index 6f1002f..0000000
--- a/contrib/llvm/tools/lldb/source/Symbol/ClangASTType.cpp
+++ /dev/null
@@ -1,7057 +0,0 @@
-//===-- ClangASTType.cpp ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangASTType.h"
-
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/CXXInheritance.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclGroup.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/AST/Type.h"
-#include "clang/AST/VTableBuilder.h"
-
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TargetInfo.h"
-
-#include "llvm/Support/Format.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include "lldb/Core/ConstString.h"
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Scalar.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Symbol/VerifyDecl.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/Process.h"
-
-#include <iterator>
-#include <mutex>
-
-using namespace lldb;
-using namespace lldb_private;
-
-static bool
-GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool allow_completion = true)
-{
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::ConstantArray:
- case clang::Type::IncompleteArray:
- case clang::Type::VariableArray:
- {
- const clang::ArrayType *array_type = llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr());
-
- if (array_type)
- return GetCompleteQualType (ast, array_type->getElementType(), allow_completion);
- }
- break;
-
- case clang::Type::Record:
- case clang::Type::Enum:
- {
- const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
- if (tag_type)
- {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- if (tag_decl)
- {
- if (tag_decl->isCompleteDefinition())
- return true;
-
- if (!allow_completion)
- return false;
-
- if (tag_decl->hasExternalLexicalStorage())
- {
- if (ast)
- {
- clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
- if (external_ast_source)
- {
- external_ast_source->CompleteType(tag_decl);
- return !tag_type->isIncompleteType();
- }
- }
- }
- return false;
- }
- }
-
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- {
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
- // We currently can't complete objective C types through the newly added ASTContext
- // because it only supports TagDecl objects right now...
- if (class_interface_decl)
- {
- if (class_interface_decl->getDefinition())
- return true;
-
- if (!allow_completion)
- return false;
-
- if (class_interface_decl->hasExternalLexicalStorage())
- {
- if (ast)
- {
- clang::ExternalASTSource *external_ast_source = ast->getExternalSource();
- if (external_ast_source)
- {
- external_ast_source->CompleteType (class_interface_decl);
- return !objc_class_type->isIncompleteType();
- }
- }
- }
- return false;
- }
- }
- }
- break;
-
- case clang::Type::Typedef:
- return GetCompleteQualType (ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType(), allow_completion);
-
- case clang::Type::Elaborated:
- return GetCompleteQualType (ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(), allow_completion);
-
- case clang::Type::Paren:
- return GetCompleteQualType (ast, llvm::cast<clang::ParenType>(qual_type)->desugar(), allow_completion);
-
- default:
- break;
- }
-
- return true;
-}
-
-static clang::ObjCIvarDecl::AccessControl
-ConvertAccessTypeToObjCIvarAccessControl (AccessType access)
-{
- switch (access)
- {
- case eAccessNone: return clang::ObjCIvarDecl::None;
- case eAccessPublic: return clang::ObjCIvarDecl::Public;
- case eAccessPrivate: return clang::ObjCIvarDecl::Private;
- case eAccessProtected: return clang::ObjCIvarDecl::Protected;
- case eAccessPackage: return clang::ObjCIvarDecl::Package;
- }
- return clang::ObjCIvarDecl::None;
-}
-
-//----------------------------------------------------------------------
-// Tests
-//----------------------------------------------------------------------
-
-ClangASTType::ClangASTType (clang::ASTContext *ast,
- clang::QualType qual_type) :
- m_type (qual_type.getAsOpaquePtr()),
- m_ast (ast)
-{
-}
-
-ClangASTType::~ClangASTType()
-{
-}
-
-//----------------------------------------------------------------------
-// Tests
-//----------------------------------------------------------------------
-
-bool
-ClangASTType::IsAggregateType () const
-{
- if (!IsValid())
- return false;
-
- clang::QualType qual_type (GetCanonicalQualType());
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::IncompleteArray:
- case clang::Type::VariableArray:
- case clang::Type::ConstantArray:
- case clang::Type::ExtVector:
- case clang::Type::Vector:
- case clang::Type::Record:
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- return true;
- case clang::Type::Elaborated:
- return ClangASTType(m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsAggregateType();
- case clang::Type::Typedef:
- return ClangASTType(m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsAggregateType();
- case clang::Type::Paren:
- return ClangASTType(m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsAggregateType();
- default:
- break;
- }
- // The clang type does have a value
- return false;
-}
-
-bool
-ClangASTType::IsArrayType (ClangASTType *element_type_ptr,
- uint64_t *size,
- bool *is_incomplete) const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- default:
- break;
-
- case clang::Type::ConstantArray:
- if (element_type_ptr)
- element_type_ptr->SetClangType (m_ast, llvm::cast<clang::ConstantArrayType>(qual_type)->getElementType());
- if (size)
- *size = llvm::cast<clang::ConstantArrayType>(qual_type)->getSize().getLimitedValue(ULLONG_MAX);
- return true;
-
- case clang::Type::IncompleteArray:
- if (element_type_ptr)
- element_type_ptr->SetClangType (m_ast, llvm::cast<clang::IncompleteArrayType>(qual_type)->getElementType());
- if (size)
- *size = 0;
- if (is_incomplete)
- *is_incomplete = true;
- return true;
-
- case clang::Type::VariableArray:
- if (element_type_ptr)
- element_type_ptr->SetClangType (m_ast, llvm::cast<clang::VariableArrayType>(qual_type)->getElementType());
- if (size)
- *size = 0;
- return true;
-
- case clang::Type::DependentSizedArray:
- if (element_type_ptr)
- element_type_ptr->SetClangType (m_ast, llvm::cast<clang::DependentSizedArrayType>(qual_type)->getElementType());
- if (size)
- *size = 0;
- return true;
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsArrayType (element_type_ptr,
- size,
- is_incomplete);
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsArrayType (element_type_ptr,
- size,
- is_incomplete);
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsArrayType (element_type_ptr,
- size,
- is_incomplete);
- }
- }
- if (element_type_ptr)
- element_type_ptr->Clear();
- if (size)
- *size = 0;
- if (is_incomplete)
- *is_incomplete = false;
- return 0;
-}
-
-bool
-ClangASTType::IsVectorType (ClangASTType *element_type,
- uint64_t *size) const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Vector:
- {
- const clang::VectorType *vector_type = qual_type->getAs<clang::VectorType>();
- if (vector_type)
- {
- if (size)
- *size = vector_type->getNumElements();
- if (element_type)
- *element_type = ClangASTType(m_ast, vector_type->getElementType().getAsOpaquePtr());
- }
- return true;
- }
- break;
- case clang::Type::ExtVector:
- {
- const clang::ExtVectorType *ext_vector_type = qual_type->getAs<clang::ExtVectorType>();
- if (ext_vector_type)
- {
- if (size)
- *size = ext_vector_type->getNumElements();
- if (element_type)
- *element_type = ClangASTType(m_ast, ext_vector_type->getElementType().getAsOpaquePtr());
- }
- return true;
- }
- default:
- break;
- }
- }
- return false;
-}
-
-bool
-ClangASTType::IsRuntimeGeneratedType () const
-{
- if (!IsValid())
- return false;
-
- clang::DeclContext* decl_ctx = GetDeclContextForType();
- if (!decl_ctx)
- return false;
-
- if (!llvm::isa<clang::ObjCInterfaceDecl>(decl_ctx))
- return false;
-
- clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
-
- ClangASTMetadata* ast_metadata = ClangASTContext::GetMetadata(m_ast, result_iface_decl);
- if (!ast_metadata)
- return false;
- return (ast_metadata->GetISAPtr() != 0);
-}
-
-bool
-ClangASTType::IsCharType () const
-{
- if (!IsValid())
- return false;
- return GetQualType().getUnqualifiedType()->isCharType();
-}
-
-
-bool
-ClangASTType::IsCompleteType () const
-{
- if (!IsValid())
- return false;
- const bool allow_completion = false;
- return GetCompleteQualType (m_ast, GetQualType(), allow_completion);
-}
-
-bool
-ClangASTType::IsConst() const
-{
- return GetQualType().isConstQualified();
-}
-
-bool
-ClangASTType::IsCStringType (uint32_t &length) const
-{
- ClangASTType pointee_or_element_clang_type;
- length = 0;
- Flags type_flags (GetTypeInfo (&pointee_or_element_clang_type));
-
- if (!pointee_or_element_clang_type.IsValid())
- return false;
-
- if (type_flags.AnySet (eTypeIsArray | eTypeIsPointer))
- {
- if (pointee_or_element_clang_type.IsCharType())
- {
- if (type_flags.Test (eTypeIsArray))
- {
- // We know the size of the array and it could be a C string
- // since it is an array of characters
- length = llvm::cast<clang::ConstantArrayType>(GetCanonicalQualType().getTypePtr())->getSize().getLimitedValue();
- }
- return true;
-
- }
- }
- return false;
-}
-
-bool
-ClangASTType::IsFunctionType (bool *is_variadic_ptr) const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
-
- if (qual_type->isFunctionType())
- {
- if (is_variadic_ptr)
- {
- const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
- if (function_proto_type)
- *is_variadic_ptr = function_proto_type->isVariadic();
- else
- *is_variadic_ptr = false;
- }
- return true;
- }
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- default:
- break;
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsFunctionType();
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsFunctionType();
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsFunctionType();
-
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- {
- const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- if (reference_type)
- return ClangASTType (m_ast, reference_type->getPointeeType()).IsFunctionType();
- }
- break;
- }
- }
- return false;
-}
-
-// Used to detect "Homogeneous Floating-point Aggregates"
-uint32_t
-ClangASTType::IsHomogeneousAggregate (ClangASTType* base_type_ptr) const
-{
- if (!IsValid())
- return 0;
-
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType ())
- {
- const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- {
- if (cxx_record_decl->getNumBases() ||
- cxx_record_decl->isDynamicClass())
- return 0;
- }
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- if (record_type)
- {
- const clang::RecordDecl *record_decl = record_type->getDecl();
- if (record_decl)
- {
- // We are looking for a structure that contains only floating point types
- clang::RecordDecl::field_iterator field_pos, field_end = record_decl->field_end();
- uint32_t num_fields = 0;
- bool is_hva = false;
- bool is_hfa = false;
- clang::QualType base_qual_type;
- for (field_pos = record_decl->field_begin(); field_pos != field_end; ++field_pos)
- {
- clang::QualType field_qual_type = field_pos->getType();
- if (field_qual_type->isFloatingType())
- {
- if (field_qual_type->isComplexType())
- return 0;
- else
- {
- if (num_fields == 0)
- base_qual_type = field_qual_type;
- else
- {
- if (is_hva)
- return 0;
- is_hfa = true;
- if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr())
- return 0;
- }
- }
- }
- else if (field_qual_type->isVectorType() || field_qual_type->isExtVectorType())
- {
- const clang::VectorType *array = field_qual_type.getTypePtr()->getAs<clang::VectorType>();
- if (array && array->getNumElements() <= 4)
- {
- if (num_fields == 0)
- base_qual_type = array->getElementType();
- else
- {
- if (is_hfa)
- return 0;
- is_hva = true;
- if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr())
- return 0;
- }
- }
- else
- return 0;
- }
- else
- return 0;
- ++num_fields;
- }
- if (base_type_ptr)
- *base_type_ptr = ClangASTType (m_ast, base_qual_type);
- return num_fields;
- }
- }
- }
- break;
-
- case clang::Type::Typedef:
- return ClangASTType(m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsHomogeneousAggregate (base_type_ptr);
-
- case clang::Type::Elaborated:
- return ClangASTType(m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsHomogeneousAggregate (base_type_ptr);
- default:
- break;
- }
- return 0;
-}
-
-size_t
-ClangASTType::GetNumberOfFunctionArguments () const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
- const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
- if (func)
- return func->getNumParams();
- }
- return 0;
-}
-
-ClangASTType
-ClangASTType::GetFunctionArgumentAtIndex (const size_t index) const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
- const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
- if (func)
- {
- if (index < func->getNumParams())
- return ClangASTType(m_ast, func->getParamType(index).getAsOpaquePtr());
- }
- }
- return ClangASTType();
-}
-
-bool
-ClangASTType::IsFunctionPointerType () const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
-
- if (qual_type->isFunctionPointerType())
- return true;
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- default:
- break;
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsFunctionPointerType();
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsFunctionPointerType();
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsFunctionPointerType();
-
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- {
- const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- if (reference_type)
- return ClangASTType (m_ast, reference_type->getPointeeType()).IsFunctionPointerType();
- }
- break;
- }
- }
- return false;
-
-}
-
-bool
-ClangASTType::IsIntegerType (bool &is_signed) const
-{
- if (!IsValid())
- return false;
-
- clang::QualType qual_type (GetCanonicalQualType());
- const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());
-
- if (builtin_type)
- {
- if (builtin_type->isInteger())
- {
- is_signed = builtin_type->isSignedInteger();
- return true;
- }
- }
-
- return false;
-}
-
-bool
-ClangASTType::IsPointerType (ClangASTType *pointee_type) const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
- {
- default:
- break;
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- return true;
- }
- return false;
- case clang::Type::ObjCObjectPointer:
- if (pointee_type)
- pointee_type->SetClangType (m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType());
- return true;
- case clang::Type::BlockPointer:
- if (pointee_type)
- pointee_type->SetClangType (m_ast, llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType());
- return true;
- case clang::Type::Pointer:
- if (pointee_type)
- pointee_type->SetClangType (m_ast, llvm::cast<clang::PointerType>(qual_type)->getPointeeType());
- return true;
- case clang::Type::MemberPointer:
- if (pointee_type)
- pointee_type->SetClangType (m_ast, llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType());
- return true;
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPointerType(pointee_type);
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsPointerType(pointee_type);
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsPointerType(pointee_type);
- default:
- break;
- }
- }
- if (pointee_type)
- pointee_type->Clear();
- return false;
-}
-
-
-bool
-ClangASTType::IsPointerOrReferenceType (ClangASTType *pointee_type) const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
- {
- default:
- break;
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- return true;
- }
- return false;
- case clang::Type::ObjCObjectPointer:
- if (pointee_type)
- pointee_type->SetClangType(m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType());
- return true;
- case clang::Type::BlockPointer:
- if (pointee_type)
- pointee_type->SetClangType(m_ast, llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType());
- return true;
- case clang::Type::Pointer:
- if (pointee_type)
- pointee_type->SetClangType(m_ast, llvm::cast<clang::PointerType>(qual_type)->getPointeeType());
- return true;
- case clang::Type::MemberPointer:
- if (pointee_type)
- pointee_type->SetClangType(m_ast, llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType());
- return true;
- case clang::Type::LValueReference:
- if (pointee_type)
- pointee_type->SetClangType(m_ast, llvm::cast<clang::LValueReferenceType>(qual_type)->desugar());
- return true;
- case clang::Type::RValueReference:
- if (pointee_type)
- pointee_type->SetClangType(m_ast, llvm::cast<clang::RValueReferenceType>(qual_type)->desugar());
- return true;
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPointerOrReferenceType(pointee_type);
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsPointerOrReferenceType(pointee_type);
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsPointerOrReferenceType(pointee_type);
- default:
- break;
- }
- }
- if (pointee_type)
- pointee_type->Clear();
- return false;
-}
-
-
-bool
-ClangASTType::IsReferenceType (ClangASTType *pointee_type, bool* is_rvalue) const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-
- switch (type_class)
- {
- case clang::Type::LValueReference:
- if (pointee_type)
- pointee_type->SetClangType(m_ast, llvm::cast<clang::LValueReferenceType>(qual_type)->desugar());
- if (is_rvalue)
- *is_rvalue = false;
- return true;
- case clang::Type::RValueReference:
- if (pointee_type)
- pointee_type->SetClangType(m_ast, llvm::cast<clang::RValueReferenceType>(qual_type)->desugar());
- if (is_rvalue)
- *is_rvalue = true;
- return true;
- case clang::Type::Typedef:
- return ClangASTType(m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsReferenceType(pointee_type, is_rvalue);
- case clang::Type::Elaborated:
- return ClangASTType(m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsReferenceType(pointee_type, is_rvalue);
- case clang::Type::Paren:
- return ClangASTType(m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).IsReferenceType(pointee_type, is_rvalue);
-
- default:
- break;
- }
- }
- if (pointee_type)
- pointee_type->Clear();
- return false;
-}
-
-bool
-ClangASTType::IsFloatingPointType (uint32_t &count, bool &is_complex) const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
-
- if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal()))
- {
- clang::BuiltinType::Kind kind = BT->getKind();
- if (kind >= clang::BuiltinType::Float && kind <= clang::BuiltinType::LongDouble)
- {
- count = 1;
- is_complex = false;
- return true;
- }
- }
- else if (const clang::ComplexType *CT = llvm::dyn_cast<clang::ComplexType>(qual_type->getCanonicalTypeInternal()))
- {
- if (ClangASTType (m_ast, CT->getElementType()).IsFloatingPointType (count, is_complex))
- {
- count = 2;
- is_complex = true;
- return true;
- }
- }
- else if (const clang::VectorType *VT = llvm::dyn_cast<clang::VectorType>(qual_type->getCanonicalTypeInternal()))
- {
- if (ClangASTType (m_ast, VT->getElementType()).IsFloatingPointType (count, is_complex))
- {
- count = VT->getNumElements();
- is_complex = false;
- return true;
- }
- }
- }
- count = 0;
- is_complex = false;
- return false;
-}
-
-
-bool
-ClangASTType::IsDefined() const
-{
- if (!IsValid())
- return false;
-
- clang::QualType qual_type(GetQualType());
- const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
- if (tag_type)
- {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- if (tag_decl)
- return tag_decl->isCompleteDefinition();
- return false;
- }
- else
- {
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
- if (class_interface_decl)
- return class_interface_decl->getDefinition() != nullptr;
- return false;
- }
- }
- return true;
-}
-
-bool
-ClangASTType::IsObjCClassType () const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
-
- const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
-
- if (obj_pointer_type)
- return obj_pointer_type->isObjCClassType();
- }
- return false;
-}
-
-bool
-ClangASTType::IsObjCObjectOrInterfaceType () const
-{
- if (IsValid())
- return GetCanonicalQualType()->isObjCObjectOrInterfaceType();
- return false;
-}
-
-bool
-ClangASTType::IsPolymorphicClass () const
-{
- if (IsValid())
- {
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType())
- {
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- if (record_decl)
- {
- const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
- if (cxx_record_decl)
- return cxx_record_decl->isPolymorphic();
- }
- }
- break;
-
- default:
- break;
- }
- }
- return false;
-}
-
-bool
-ClangASTType::IsPossibleDynamicType (ClangASTType *dynamic_pointee_type,
- bool check_cplusplus,
- bool check_objc) const
-{
- clang::QualType pointee_qual_type;
- if (m_type)
- {
- clang::QualType qual_type (GetCanonicalQualType());
- bool success = false;
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Builtin:
- if (check_objc && llvm::cast<clang::BuiltinType>(qual_type)->getKind() == clang::BuiltinType::ObjCId)
- {
- if (dynamic_pointee_type)
- dynamic_pointee_type->SetClangType(m_ast, m_type);
- return true;
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- if (check_objc)
- {
- if (dynamic_pointee_type)
- dynamic_pointee_type->SetClangType(m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType());
- return true;
- }
- break;
-
- case clang::Type::Pointer:
- pointee_qual_type = llvm::cast<clang::PointerType>(qual_type)->getPointeeType();
- success = true;
- break;
-
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- pointee_qual_type = llvm::cast<clang::ReferenceType>(qual_type)->getPointeeType();
- success = true;
- break;
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast,
- llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).IsPossibleDynamicType (dynamic_pointee_type,
- check_cplusplus,
- check_objc);
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast,
- llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).IsPossibleDynamicType (dynamic_pointee_type,
- check_cplusplus,
- check_objc);
-
- case clang::Type::Paren:
- return ClangASTType (m_ast,
- llvm::cast<clang::ParenType>(qual_type)->desugar()).IsPossibleDynamicType (dynamic_pointee_type,
- check_cplusplus,
- check_objc);
- default:
- break;
- }
-
- if (success)
- {
- // Check to make sure what we are pointing too is a possible dynamic C++ type
- // We currently accept any "void *" (in case we have a class that has been
- // watered down to an opaque pointer) and virtual C++ classes.
- const clang::Type::TypeClass pointee_type_class = pointee_qual_type.getCanonicalType()->getTypeClass();
- switch (pointee_type_class)
- {
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(pointee_qual_type)->getKind())
- {
- case clang::BuiltinType::UnknownAny:
- case clang::BuiltinType::Void:
- if (dynamic_pointee_type)
- dynamic_pointee_type->SetClangType(m_ast, pointee_qual_type);
- return true;
-
- case clang::BuiltinType::NullPtr:
- case clang::BuiltinType::Bool:
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::WChar_U:
- case clang::BuiltinType::Char16:
- case clang::BuiltinType::Char32:
- case clang::BuiltinType::UShort:
- case clang::BuiltinType::UInt:
- case clang::BuiltinType::ULong:
- case clang::BuiltinType::ULongLong:
- case clang::BuiltinType::UInt128:
- case clang::BuiltinType::Char_S:
- case clang::BuiltinType::SChar:
- case clang::BuiltinType::WChar_S:
- case clang::BuiltinType::Short:
- case clang::BuiltinType::Int:
- case clang::BuiltinType::Long:
- case clang::BuiltinType::LongLong:
- case clang::BuiltinType::Int128:
- case clang::BuiltinType::Float:
- case clang::BuiltinType::Double:
- case clang::BuiltinType::LongDouble:
- case clang::BuiltinType::Dependent:
- case clang::BuiltinType::Overload:
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- case clang::BuiltinType::ObjCSel:
- case clang::BuiltinType::BoundMember:
- case clang::BuiltinType::Half:
- case clang::BuiltinType::ARCUnbridgedCast:
- case clang::BuiltinType::PseudoObject:
- case clang::BuiltinType::BuiltinFn:
- case clang::BuiltinType::OCLEvent:
- case clang::BuiltinType::OCLImage1d:
- case clang::BuiltinType::OCLImage1dArray:
- case clang::BuiltinType::OCLImage1dBuffer:
- case clang::BuiltinType::OCLImage2d:
- case clang::BuiltinType::OCLImage2dArray:
- case clang::BuiltinType::OCLImage3d:
- case clang::BuiltinType::OCLSampler:
- break;
- }
- break;
-
- case clang::Type::Record:
- if (check_cplusplus)
- {
- clang::CXXRecordDecl *cxx_record_decl = pointee_qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- {
- bool is_complete = cxx_record_decl->isCompleteDefinition();
-
- if (is_complete)
- success = cxx_record_decl->isDynamicClass();
- else
- {
- ClangASTMetadata *metadata = ClangASTContext::GetMetadata (m_ast, cxx_record_decl);
- if (metadata)
- success = metadata->GetIsDynamicCXXType();
- else
- {
- is_complete = ClangASTType(m_ast, pointee_qual_type).GetCompleteType();
- if (is_complete)
- success = cxx_record_decl->isDynamicClass();
- else
- success = false;
- }
- }
-
- if (success)
- {
- if (dynamic_pointee_type)
- dynamic_pointee_type->SetClangType(m_ast, pointee_qual_type);
- return true;
- }
- }
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (check_objc)
- {
- if (dynamic_pointee_type)
- dynamic_pointee_type->SetClangType(m_ast, pointee_qual_type);
- return true;
- }
- break;
-
- default:
- break;
- }
- }
- }
- if (dynamic_pointee_type)
- dynamic_pointee_type->Clear();
- return false;
-}
-
-
-bool
-ClangASTType::IsScalarType () const
-{
- if (!IsValid())
- return false;
-
- return (GetTypeInfo (nullptr) & eTypeIsScalar) != 0;
-}
-
-bool
-ClangASTType::IsTypedefType () const
-{
- if (!IsValid())
- return false;
- return GetQualType()->getTypeClass() == clang::Type::Typedef;
-}
-
-bool
-ClangASTType::IsVoidType () const
-{
- if (!IsValid())
- return false;
- return GetCanonicalQualType()->isVoidType();
-}
-
-bool
-ClangASTType::IsPointerToScalarType () const
-{
- if (!IsValid())
- return false;
-
- return IsPointerType() && GetPointeeType().IsScalarType();
-}
-
-bool
-ClangASTType::IsArrayOfScalarType () const
-{
- ClangASTType element_type;
- if (IsArrayType(&element_type, nullptr, nullptr))
- return element_type.IsScalarType();
- return false;
-}
-
-
-bool
-ClangASTType::GetCXXClassName (std::string &class_name) const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
-
- clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- {
- class_name.assign (cxx_record_decl->getIdentifier()->getNameStart());
- return true;
- }
- }
- class_name.clear();
- return false;
-}
-
-
-bool
-ClangASTType::IsCXXClassType () const
-{
- if (!IsValid())
- return false;
-
- clang::QualType qual_type (GetCanonicalQualType());
- if (qual_type->getAsCXXRecordDecl() != nullptr)
- return true;
- return false;
-}
-
-bool
-ClangASTType::IsBeingDefined () const
-{
- if (!IsValid())
- return false;
- clang::QualType qual_type (GetCanonicalQualType());
- const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type);
- if (tag_type)
- return tag_type->isBeingDefined();
- return false;
-}
-
-bool
-ClangASTType::IsObjCObjectPointerType (ClangASTType *class_type_ptr)
-{
- if (!IsValid())
- return false;
-
- clang::QualType qual_type (GetCanonicalQualType());
-
- if (qual_type->isObjCObjectPointerType())
- {
- if (class_type_ptr)
- {
- if (!qual_type->isObjCClassType() &&
- !qual_type->isObjCIdType())
- {
- const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type);
- if (obj_pointer_type == nullptr)
- class_type_ptr->Clear();
- else
- class_type_ptr->SetClangType (m_ast, clang::QualType(obj_pointer_type->getInterfaceType(), 0));
- }
- }
- return true;
- }
- if (class_type_ptr)
- class_type_ptr->Clear();
- return false;
-}
-
-bool
-ClangASTType::GetObjCClassName (std::string &class_name)
-{
- if (!IsValid())
- return false;
-
- clang::QualType qual_type (GetCanonicalQualType());
-
- const clang::ObjCObjectType *object_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type);
- if (object_type)
- {
- const clang::ObjCInterfaceDecl *interface = object_type->getInterface();
- if (interface)
- {
- class_name = interface->getNameAsString();
- return true;
- }
- }
- return false;
-}
-
-
-//----------------------------------------------------------------------
-// Type Completion
-//----------------------------------------------------------------------
-
-bool
-ClangASTType::GetCompleteType () const
-{
- if (!IsValid())
- return false;
- const bool allow_completion = true;
- return GetCompleteQualType (m_ast, GetQualType(), allow_completion);
-}
-
-//----------------------------------------------------------------------
-// AST related queries
-//----------------------------------------------------------------------
-size_t
-ClangASTType::GetPointerByteSize () const
-{
- if (m_ast)
- return m_ast->getTypeSize(m_ast->VoidPtrTy) / 8;
- return 0;
-}
-
-ConstString
-ClangASTType::GetConstQualifiedTypeName () const
-{
- return GetConstTypeName ();
-}
-
-ConstString
-ClangASTType::GetConstTypeName () const
-{
- if (IsValid())
- {
- ConstString type_name (GetTypeName());
- if (type_name)
- return type_name;
- }
- return ConstString("<invalid>");
-}
-
-ConstString
-ClangASTType::GetTypeName () const
-{
- std::string type_name;
- if (IsValid())
- {
- clang::PrintingPolicy printing_policy (m_ast->getPrintingPolicy());
- clang::QualType qual_type(GetQualType());
- printing_policy.SuppressTagKeyword = true;
- printing_policy.LangOpts.WChar = true;
- const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
- if (typedef_type)
- {
- const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
- type_name = typedef_decl->getQualifiedNameAsString();
- }
- else
- {
- type_name = qual_type.getAsString(printing_policy);
- }
- }
- return ConstString(type_name);
-}
-
-ConstString
-ClangASTType::GetDisplayTypeName () const
-{
- return GetTypeName();
-}
-
-uint32_t
-ClangASTType::GetTypeInfo (ClangASTType *pointee_or_element_clang_type) const
-{
- if (!IsValid())
- return 0;
-
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->Clear();
-
- clang::QualType qual_type (GetQualType());
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Builtin:
- {
- const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());
-
- uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue;
- switch (builtin_type->getKind())
- {
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetClangType(m_ast, m_ast->ObjCBuiltinClassTy);
- builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
- break;
-
- case clang::BuiltinType::ObjCSel:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetClangType(m_ast, m_ast->CharTy);
- builtin_type_flags |= eTypeIsPointer | eTypeIsObjC;
- break;
-
- case clang::BuiltinType::Bool:
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::WChar_U:
- case clang::BuiltinType::Char16:
- case clang::BuiltinType::Char32:
- case clang::BuiltinType::UShort:
- case clang::BuiltinType::UInt:
- case clang::BuiltinType::ULong:
- case clang::BuiltinType::ULongLong:
- case clang::BuiltinType::UInt128:
- case clang::BuiltinType::Char_S:
- case clang::BuiltinType::SChar:
- case clang::BuiltinType::WChar_S:
- case clang::BuiltinType::Short:
- case clang::BuiltinType::Int:
- case clang::BuiltinType::Long:
- case clang::BuiltinType::LongLong:
- case clang::BuiltinType::Int128:
- case clang::BuiltinType::Float:
- case clang::BuiltinType::Double:
- case clang::BuiltinType::LongDouble:
- builtin_type_flags |= eTypeIsScalar;
- if (builtin_type->isInteger())
- {
- builtin_type_flags |= eTypeIsInteger;
- if (builtin_type->isSignedInteger())
- builtin_type_flags |= eTypeIsSigned;
- }
- else if (builtin_type->isFloatingPoint())
- builtin_type_flags |= eTypeIsFloat;
- break;
- default:
- break;
- }
- return builtin_type_flags;
- }
-
- case clang::Type::BlockPointer:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetClangType(m_ast, qual_type->getPointeeType());
- return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock;
-
- case clang::Type::Complex:
- {
- uint32_t complex_type_flags = eTypeIsBuiltIn | eTypeHasValue | eTypeIsComplex;
- const clang::ComplexType *complex_type = llvm::dyn_cast<clang::ComplexType>(qual_type->getCanonicalTypeInternal());
- if (complex_type)
- {
- clang::QualType complex_element_type (complex_type->getElementType());
- if (complex_element_type->isIntegerType())
- complex_type_flags |= eTypeIsFloat;
- else if (complex_element_type->isFloatingType())
- complex_type_flags |= eTypeIsInteger;
- }
- return complex_type_flags;
- }
- break;
-
- case clang::Type::ConstantArray:
- case clang::Type::DependentSizedArray:
- case clang::Type::IncompleteArray:
- case clang::Type::VariableArray:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetClangType(m_ast, llvm::cast<clang::ArrayType>(qual_type.getTypePtr())->getElementType());
- return eTypeHasChildren | eTypeIsArray;
-
- case clang::Type::DependentName: return 0;
- case clang::Type::DependentSizedExtVector: return eTypeHasChildren | eTypeIsVector;
- case clang::Type::DependentTemplateSpecialization: return eTypeIsTemplate;
- case clang::Type::Decltype: return 0;
-
- case clang::Type::Enum:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetClangType(m_ast, llvm::cast<clang::EnumType>(qual_type)->getDecl()->getIntegerType());
- return eTypeIsEnumeration | eTypeHasValue;
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetTypeInfo (pointee_or_element_clang_type);
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetTypeInfo (pointee_or_element_clang_type);
-
- case clang::Type::FunctionProto: return eTypeIsFuncPrototype | eTypeHasValue;
- case clang::Type::FunctionNoProto: return eTypeIsFuncPrototype | eTypeHasValue;
- case clang::Type::InjectedClassName: return 0;
-
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetClangType(m_ast, llvm::cast<clang::ReferenceType>(qual_type.getTypePtr())->getPointeeType());
- return eTypeHasChildren | eTypeIsReference | eTypeHasValue;
-
- case clang::Type::MemberPointer: return eTypeIsPointer | eTypeIsMember | eTypeHasValue;
-
- case clang::Type::ObjCObjectPointer:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetClangType(m_ast, qual_type->getPointeeType());
- return eTypeHasChildren | eTypeIsObjC | eTypeIsClass | eTypeIsPointer | eTypeHasValue;
-
- case clang::Type::ObjCObject: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass;
- case clang::Type::ObjCInterface: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass;
-
- case clang::Type::Pointer:
- if (pointee_or_element_clang_type)
- pointee_or_element_clang_type->SetClangType(m_ast, qual_type->getPointeeType());
- return eTypeHasChildren | eTypeIsPointer | eTypeHasValue;
-
- case clang::Type::Record:
- if (qual_type->getAsCXXRecordDecl())
- return eTypeHasChildren | eTypeIsClass | eTypeIsCPlusPlus;
- else
- return eTypeHasChildren | eTypeIsStructUnion;
- break;
- case clang::Type::SubstTemplateTypeParm: return eTypeIsTemplate;
- case clang::Type::TemplateTypeParm: return eTypeIsTemplate;
- case clang::Type::TemplateSpecialization: return eTypeIsTemplate;
-
- case clang::Type::Typedef:
- return eTypeIsTypedef | ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetTypeInfo (pointee_or_element_clang_type);
- case clang::Type::TypeOfExpr: return 0;
- case clang::Type::TypeOf: return 0;
- case clang::Type::UnresolvedUsing: return 0;
-
- case clang::Type::ExtVector:
- case clang::Type::Vector:
- {
- uint32_t vector_type_flags = eTypeHasChildren | eTypeIsVector;
- const clang::VectorType *vector_type = llvm::dyn_cast<clang::VectorType>(qual_type->getCanonicalTypeInternal());
- if (vector_type)
- {
- if (vector_type->isIntegerType())
- vector_type_flags |= eTypeIsFloat;
- else if (vector_type->isFloatingType())
- vector_type_flags |= eTypeIsInteger;
- }
- return vector_type_flags;
- }
- default: return 0;
- }
- return 0;
-}
-
-
-
-lldb::LanguageType
-ClangASTType::GetMinimumLanguage ()
-{
- if (!IsValid())
- return lldb::eLanguageTypeC;
-
- // If the type is a reference, then resolve it to what it refers to first:
- clang::QualType qual_type (GetCanonicalQualType().getNonReferenceType());
- if (qual_type->isAnyPointerType())
- {
- if (qual_type->isObjCObjectPointerType())
- return lldb::eLanguageTypeObjC;
-
- clang::QualType pointee_type (qual_type->getPointeeType());
- if (pointee_type->getPointeeCXXRecordDecl() != nullptr)
- return lldb::eLanguageTypeC_plus_plus;
- if (pointee_type->isObjCObjectOrInterfaceType())
- return lldb::eLanguageTypeObjC;
- if (pointee_type->isObjCClassType())
- return lldb::eLanguageTypeObjC;
- if (pointee_type.getTypePtr() == m_ast->ObjCBuiltinIdTy.getTypePtr())
- return lldb::eLanguageTypeObjC;
- }
- else
- {
- if (qual_type->isObjCObjectOrInterfaceType())
- return lldb::eLanguageTypeObjC;
- if (qual_type->getAsCXXRecordDecl())
- return lldb::eLanguageTypeC_plus_plus;
- switch (qual_type->getTypeClass())
- {
- default:
- break;
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
- {
- default:
- case clang::BuiltinType::Void:
- case clang::BuiltinType::Bool:
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::WChar_U:
- case clang::BuiltinType::Char16:
- case clang::BuiltinType::Char32:
- case clang::BuiltinType::UShort:
- case clang::BuiltinType::UInt:
- case clang::BuiltinType::ULong:
- case clang::BuiltinType::ULongLong:
- case clang::BuiltinType::UInt128:
- case clang::BuiltinType::Char_S:
- case clang::BuiltinType::SChar:
- case clang::BuiltinType::WChar_S:
- case clang::BuiltinType::Short:
- case clang::BuiltinType::Int:
- case clang::BuiltinType::Long:
- case clang::BuiltinType::LongLong:
- case clang::BuiltinType::Int128:
- case clang::BuiltinType::Float:
- case clang::BuiltinType::Double:
- case clang::BuiltinType::LongDouble:
- break;
-
- case clang::BuiltinType::NullPtr:
- return eLanguageTypeC_plus_plus;
-
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- case clang::BuiltinType::ObjCSel:
- return eLanguageTypeObjC;
-
- case clang::BuiltinType::Dependent:
- case clang::BuiltinType::Overload:
- case clang::BuiltinType::BoundMember:
- case clang::BuiltinType::UnknownAny:
- break;
- }
- break;
- case clang::Type::Typedef:
- return ClangASTType(m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetMinimumLanguage();
- }
- }
- return lldb::eLanguageTypeC;
-}
-
-lldb::TypeClass
-ClangASTType::GetTypeClass () const
-{
- if (!IsValid())
- return lldb::eTypeClassInvalid;
-
- clang::QualType qual_type(GetQualType());
-
- switch (qual_type->getTypeClass())
- {
- case clang::Type::UnaryTransform: break;
- case clang::Type::FunctionNoProto: return lldb::eTypeClassFunction;
- case clang::Type::FunctionProto: return lldb::eTypeClassFunction;
- case clang::Type::IncompleteArray: return lldb::eTypeClassArray;
- case clang::Type::VariableArray: return lldb::eTypeClassArray;
- case clang::Type::ConstantArray: return lldb::eTypeClassArray;
- case clang::Type::DependentSizedArray: return lldb::eTypeClassArray;
- case clang::Type::DependentSizedExtVector: return lldb::eTypeClassVector;
- case clang::Type::ExtVector: return lldb::eTypeClassVector;
- case clang::Type::Vector: return lldb::eTypeClassVector;
- case clang::Type::Builtin: return lldb::eTypeClassBuiltin;
- case clang::Type::ObjCObjectPointer: return lldb::eTypeClassObjCObjectPointer;
- case clang::Type::BlockPointer: return lldb::eTypeClassBlockPointer;
- case clang::Type::Pointer: return lldb::eTypeClassPointer;
- case clang::Type::LValueReference: return lldb::eTypeClassReference;
- case clang::Type::RValueReference: return lldb::eTypeClassReference;
- case clang::Type::MemberPointer: return lldb::eTypeClassMemberPointer;
- case clang::Type::Complex:
- if (qual_type->isComplexType())
- return lldb::eTypeClassComplexFloat;
- else
- return lldb::eTypeClassComplexInteger;
- case clang::Type::ObjCObject: return lldb::eTypeClassObjCObject;
- case clang::Type::ObjCInterface: return lldb::eTypeClassObjCInterface;
- case clang::Type::Record:
- {
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- if (record_decl->isUnion())
- return lldb::eTypeClassUnion;
- else if (record_decl->isStruct())
- return lldb::eTypeClassStruct;
- else
- return lldb::eTypeClassClass;
- }
- break;
- case clang::Type::Enum: return lldb::eTypeClassEnumeration;
- case clang::Type::Typedef: return lldb::eTypeClassTypedef;
- case clang::Type::UnresolvedUsing: break;
- case clang::Type::Paren:
- return ClangASTType(m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetTypeClass();
- case clang::Type::Elaborated:
- return ClangASTType(m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetTypeClass();
-
- case clang::Type::Attributed: break;
- case clang::Type::TemplateTypeParm: break;
- case clang::Type::SubstTemplateTypeParm: break;
- case clang::Type::SubstTemplateTypeParmPack:break;
- case clang::Type::Auto: break;
- case clang::Type::InjectedClassName: break;
- case clang::Type::DependentName: break;
- case clang::Type::DependentTemplateSpecialization: break;
- case clang::Type::PackExpansion: break;
-
- case clang::Type::TypeOfExpr: break;
- case clang::Type::TypeOf: break;
- case clang::Type::Decltype: break;
- case clang::Type::TemplateSpecialization: break;
- case clang::Type::Atomic: break;
-
- // pointer type decayed from an array or function type.
- case clang::Type::Decayed: break;
- case clang::Type::Adjusted: break;
- }
- // We don't know hot to display this type...
- return lldb::eTypeClassOther;
-
-}
-
-void
-ClangASTType::SetClangType (clang::ASTContext *ast, clang::QualType qual_type)
-{
- m_ast = ast;
- m_type = qual_type.getAsOpaquePtr();
-}
-
-unsigned
-ClangASTType::GetTypeQualifiers() const
-{
- if (IsValid())
- return GetQualType().getQualifiers().getCVRQualifiers();
- return 0;
-}
-
-//----------------------------------------------------------------------
-// Creating related types
-//----------------------------------------------------------------------
-
-ClangASTType
-ClangASTType::AddConstModifier () const
-{
- if (m_type)
- {
- clang::QualType result(GetQualType());
- result.addConst();
- return ClangASTType (m_ast, result);
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::AddRestrictModifier () const
-{
- if (m_type)
- {
- clang::QualType result(GetQualType());
- result.getQualifiers().setRestrict (true);
- return ClangASTType (m_ast, result);
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::AddVolatileModifier () const
-{
- if (m_type)
- {
- clang::QualType result(GetQualType());
- result.getQualifiers().setVolatile (true);
- return ClangASTType (m_ast, result);
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::GetArrayElementType (uint64_t *stride) const
-{
- if (IsValid())
- {
- clang::QualType qual_type(GetCanonicalQualType());
-
- const clang::Type *array_elem_type = qual_type.getTypePtr()->getArrayElementTypeNoTypeQual();
-
- if (!array_elem_type)
- return ClangASTType();
-
- ClangASTType element_type (m_ast, array_elem_type->getCanonicalTypeUnqualified());
-
- // TODO: the real stride will be >= this value.. find the real one!
- if (stride)
- *stride = element_type.GetByteSize(nullptr);
-
- return element_type;
-
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::GetCanonicalType () const
-{
- if (IsValid())
- return ClangASTType (m_ast, GetCanonicalQualType());
- return ClangASTType();
-}
-
-static clang::QualType
-GetFullyUnqualifiedType_Impl (clang::ASTContext *ast, clang::QualType qual_type)
-{
- if (qual_type->isPointerType())
- qual_type = ast->getPointerType(GetFullyUnqualifiedType_Impl(ast, qual_type->getPointeeType()));
- else
- qual_type = qual_type.getUnqualifiedType();
- qual_type.removeLocalConst();
- qual_type.removeLocalRestrict();
- qual_type.removeLocalVolatile();
- return qual_type;
-}
-
-ClangASTType
-ClangASTType::GetFullyUnqualifiedType () const
-{
- if (IsValid())
- return ClangASTType(m_ast, GetFullyUnqualifiedType_Impl(m_ast, GetQualType()));
- return ClangASTType();
-}
-
-
-int
-ClangASTType::GetFunctionArgumentCount () const
-{
- if (IsValid())
- {
- const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType());
- if (func)
- return func->getNumParams();
- }
- return -1;
-}
-
-ClangASTType
-ClangASTType::GetFunctionArgumentTypeAtIndex (size_t idx) const
-{
- if (IsValid())
- {
- const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType());
- if (func)
- {
- const uint32_t num_args = func->getNumParams();
- if (idx < num_args)
- return ClangASTType(m_ast, func->getParamType(idx));
- }
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::GetFunctionReturnType () const
-{
- if (IsValid())
- {
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr());
- if (func)
- return ClangASTType(m_ast, func->getReturnType());
- }
- return ClangASTType();
-}
-
-size_t
-ClangASTType::GetNumMemberFunctions () const
-{
- size_t num_functions = 0;
- if (IsValid())
- {
- clang::QualType qual_type(GetCanonicalQualType());
- switch (qual_type->getTypeClass()) {
- case clang::Type::Record:
- if (GetCompleteQualType (m_ast, qual_type))
- {
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- assert(record_decl);
- const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
- if (cxx_record_decl)
- num_functions = std::distance(cxx_record_decl->method_begin(), cxx_record_decl->method_end());
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- if (GetCompleteType())
- {
- const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
- if (class_interface_decl)
- num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end());
- }
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (GetCompleteType())
- {
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
- if (class_interface_decl)
- num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end());
- }
- }
- break;
-
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumMemberFunctions();
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumMemberFunctions();
-
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumMemberFunctions();
-
- default:
- break;
- }
- }
- return num_functions;
-}
-
-TypeMemberFunctionImpl
-ClangASTType::GetMemberFunctionAtIndex (size_t idx)
-{
- std::string name("");
- MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown);
- ClangASTType type{};
- clang::ObjCMethodDecl *method_decl(nullptr);
- if (IsValid())
- {
- clang::QualType qual_type(GetCanonicalQualType());
- switch (qual_type->getTypeClass()) {
- case clang::Type::Record:
- if (GetCompleteQualType (m_ast, qual_type))
- {
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- assert(record_decl);
- const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
- if (cxx_record_decl)
- {
- auto method_iter = cxx_record_decl->method_begin();
- auto method_end = cxx_record_decl->method_end();
- if (idx < static_cast<size_t>(std::distance(method_iter, method_end)))
- {
- std::advance(method_iter, idx);
- auto method_decl = method_iter->getCanonicalDecl();
- if (method_decl)
- {
- if (!method_decl->getName().empty())
- name.assign(method_decl->getName().data());
- else
- name.clear();
- if (method_decl->isStatic())
- kind = lldb::eMemberFunctionKindStaticMethod;
- else if (llvm::isa<clang::CXXConstructorDecl>(method_decl))
- kind = lldb::eMemberFunctionKindConstructor;
- else if (llvm::isa<clang::CXXDestructorDecl>(method_decl))
- kind = lldb::eMemberFunctionKindDestructor;
- else
- kind = lldb::eMemberFunctionKindInstanceMethod;
- type = ClangASTType(m_ast,method_decl->getType().getAsOpaquePtr());
- }
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- if (GetCompleteType())
- {
- const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
- if (class_interface_decl)
- {
- auto method_iter = class_interface_decl->meth_begin();
- auto method_end = class_interface_decl->meth_end();
- if (idx < static_cast<size_t>(std::distance(method_iter, method_end)))
- {
- std::advance(method_iter, idx);
- method_decl = method_iter->getCanonicalDecl();
- if (method_decl)
- {
- name = method_decl->getSelector().getAsString();
- if (method_decl->isClassMethod())
- kind = lldb::eMemberFunctionKindStaticMethod;
- else
- kind = lldb::eMemberFunctionKindInstanceMethod;
- }
- }
- }
- }
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (GetCompleteType())
- {
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
- if (class_interface_decl)
- {
- auto method_iter = class_interface_decl->meth_begin();
- auto method_end = class_interface_decl->meth_end();
- if (idx < static_cast<size_t>(std::distance(method_iter, method_end)))
- {
- std::advance(method_iter, idx);
- method_decl = method_iter->getCanonicalDecl();
- if (method_decl)
- {
- name = method_decl->getSelector().getAsString();
- if (method_decl->isClassMethod())
- kind = lldb::eMemberFunctionKindStaticMethod;
- else
- kind = lldb::eMemberFunctionKindInstanceMethod;
- }
- }
- }
- }
- }
- break;
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetMemberFunctionAtIndex(idx);
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetMemberFunctionAtIndex(idx);
-
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetMemberFunctionAtIndex(idx);
-
- default:
- break;
- }
- }
-
- if (kind == eMemberFunctionKindUnknown)
- return TypeMemberFunctionImpl();
- if (method_decl)
- return TypeMemberFunctionImpl(method_decl, name, kind);
- if (type)
- return TypeMemberFunctionImpl(type, name, kind);
-
- return TypeMemberFunctionImpl();
-}
-
-ClangASTType
-ClangASTType::GetLValueReferenceType () const
-{
- if (IsValid())
- {
- return ClangASTType(m_ast, m_ast->getLValueReferenceType(GetQualType()));
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::GetRValueReferenceType () const
-{
- if (IsValid())
- {
- return ClangASTType(m_ast, m_ast->getRValueReferenceType(GetQualType()));
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::GetNonReferenceType () const
-{
- if (IsValid())
- return ClangASTType(m_ast, GetQualType().getNonReferenceType());
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::CreateTypedefType (const char *typedef_name,
- clang::DeclContext *decl_ctx) const
-{
- if (IsValid() && typedef_name && typedef_name[0])
- {
- clang::QualType qual_type (GetQualType());
- if (decl_ctx == nullptr)
- decl_ctx = m_ast->getTranslationUnitDecl();
- clang::TypedefDecl *decl = clang::TypedefDecl::Create (*m_ast,
- decl_ctx,
- clang::SourceLocation(),
- clang::SourceLocation(),
- &m_ast->Idents.get(typedef_name),
- m_ast->getTrivialTypeSourceInfo(qual_type));
-
- decl->setAccess(clang::AS_public); // TODO respect proper access specifier
-
- // Get a uniqued clang::QualType for the typedef decl type
- return ClangASTType (m_ast, m_ast->getTypedefType (decl));
- }
- return ClangASTType();
-
-}
-
-ClangASTType
-ClangASTType::GetPointeeType () const
-{
- if (m_type)
- {
- clang::QualType qual_type(GetQualType());
- return ClangASTType (m_ast, qual_type.getTypePtr()->getPointeeType());
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::GetPointerType () const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetQualType());
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- return ClangASTType(m_ast, m_ast->getObjCObjectPointerType(qual_type).getAsOpaquePtr());
-
- default:
- return ClangASTType(m_ast, m_ast->getPointerType(qual_type).getAsOpaquePtr());
- }
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::GetTypedefedType () const
-{
- if (IsValid())
- {
- const clang::TypedefType *typedef_type = llvm::dyn_cast<clang::TypedefType>(GetQualType());
- if (typedef_type)
- return ClangASTType (m_ast, typedef_type->getDecl()->getUnderlyingType());
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::RemoveFastQualifiers () const
-{
- if (m_type)
- {
- clang::QualType qual_type(GetQualType());
- qual_type.getQualifiers().removeFastQualifiers();
- return ClangASTType (m_ast, qual_type);
- }
- return ClangASTType();
-}
-
-
-//----------------------------------------------------------------------
-// Create related types using the current type's AST
-//----------------------------------------------------------------------
-
-ClangASTType
-ClangASTType::GetBasicTypeFromAST (lldb::BasicType basic_type) const
-{
- if (IsValid())
- return ClangASTContext::GetBasicType(m_ast, basic_type);
- return ClangASTType();
-}
-//----------------------------------------------------------------------
-// Exploring the type
-//----------------------------------------------------------------------
-
-uint64_t
-ClangASTType::GetBitSize (ExecutionContextScope *exe_scope) const
-{
- if (GetCompleteType ())
- {
- clang::QualType qual_type(GetCanonicalQualType());
- switch (qual_type->getTypeClass())
- {
- case clang::Type::ObjCInterface:
- case clang::Type::ObjCObject:
- {
- ExecutionContext exe_ctx (exe_scope);
- Process *process = exe_ctx.GetProcessPtr();
- if (process)
- {
- ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
- if (objc_runtime)
- {
- uint64_t bit_size = 0;
- if (objc_runtime->GetTypeBitSize(*this, bit_size))
- return bit_size;
- }
- }
- else
- {
- static bool g_printed = false;
- if (!g_printed)
- {
- StreamString s;
- DumpTypeDescription(&s);
-
- llvm::outs() << "warning: trying to determine the size of type ";
- llvm::outs() << s.GetString() << "\n";
- llvm::outs() << "without a valid ExecutionContext. this is not reliable. please file a bug against LLDB.\n";
- llvm::outs() << "backtrace:\n";
- llvm::sys::PrintStackTrace(llvm::outs());
- llvm::outs() << "\n";
- g_printed = true;
- }
- }
- }
- // fallthrough
- default:
- const uint32_t bit_size = m_ast->getTypeSize (qual_type);
- if (bit_size == 0)
- {
- if (qual_type->isIncompleteArrayType())
- return m_ast->getTypeSize (qual_type->getArrayElementTypeNoTypeQual()->getCanonicalTypeUnqualified());
- }
- if (qual_type->isObjCObjectOrInterfaceType())
- return bit_size + m_ast->getTypeSize(m_ast->ObjCBuiltinClassTy);
- return bit_size;
- }
- }
- return 0;
-}
-
-uint64_t
-ClangASTType::GetByteSize (ExecutionContextScope *exe_scope) const
-{
- return (GetBitSize (exe_scope) + 7) / 8;
-}
-
-
-size_t
-ClangASTType::GetTypeBitAlign () const
-{
- if (GetCompleteType ())
- return m_ast->getTypeAlign(GetQualType());
- return 0;
-}
-
-
-lldb::Encoding
-ClangASTType::GetEncoding (uint64_t &count) const
-{
- if (!IsValid())
- return lldb::eEncodingInvalid;
-
- count = 1;
- clang::QualType qual_type(GetCanonicalQualType());
-
- switch (qual_type->getTypeClass())
- {
- case clang::Type::UnaryTransform:
- break;
-
- case clang::Type::FunctionNoProto:
- case clang::Type::FunctionProto:
- break;
-
- case clang::Type::IncompleteArray:
- case clang::Type::VariableArray:
- break;
-
- case clang::Type::ConstantArray:
- break;
-
- case clang::Type::ExtVector:
- case clang::Type::Vector:
- // TODO: Set this to more than one???
- break;
-
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
- {
- default: assert(0 && "Unknown builtin type!");
- case clang::BuiltinType::Void:
- break;
-
- case clang::BuiltinType::Bool:
- case clang::BuiltinType::Char_S:
- case clang::BuiltinType::SChar:
- case clang::BuiltinType::WChar_S:
- case clang::BuiltinType::Char16:
- case clang::BuiltinType::Char32:
- case clang::BuiltinType::Short:
- case clang::BuiltinType::Int:
- case clang::BuiltinType::Long:
- case clang::BuiltinType::LongLong:
- case clang::BuiltinType::Int128: return lldb::eEncodingSint;
-
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::WChar_U:
- case clang::BuiltinType::UShort:
- case clang::BuiltinType::UInt:
- case clang::BuiltinType::ULong:
- case clang::BuiltinType::ULongLong:
- case clang::BuiltinType::UInt128: return lldb::eEncodingUint;
-
- case clang::BuiltinType::Float:
- case clang::BuiltinType::Double:
- case clang::BuiltinType::LongDouble: return lldb::eEncodingIEEE754;
-
- case clang::BuiltinType::ObjCClass:
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCSel: return lldb::eEncodingUint;
-
- case clang::BuiltinType::NullPtr: return lldb::eEncodingUint;
-
- case clang::BuiltinType::Kind::ARCUnbridgedCast:
- case clang::BuiltinType::Kind::BoundMember:
- case clang::BuiltinType::Kind::BuiltinFn:
- case clang::BuiltinType::Kind::Dependent:
- case clang::BuiltinType::Kind::Half:
- case clang::BuiltinType::Kind::OCLEvent:
- case clang::BuiltinType::Kind::OCLImage1d:
- case clang::BuiltinType::Kind::OCLImage1dArray:
- case clang::BuiltinType::Kind::OCLImage1dBuffer:
- case clang::BuiltinType::Kind::OCLImage2d:
- case clang::BuiltinType::Kind::OCLImage2dArray:
- case clang::BuiltinType::Kind::OCLImage3d:
- case clang::BuiltinType::Kind::OCLSampler:
- case clang::BuiltinType::Kind::Overload:
- case clang::BuiltinType::Kind::PseudoObject:
- case clang::BuiltinType::Kind::UnknownAny:
- break;
- }
- break;
- // All pointer types are represented as unsigned integer encodings.
- // We may nee to add a eEncodingPointer if we ever need to know the
- // difference
- case clang::Type::ObjCObjectPointer:
- case clang::Type::BlockPointer:
- case clang::Type::Pointer:
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- case clang::Type::MemberPointer: return lldb::eEncodingUint;
- case clang::Type::Complex:
- {
- lldb::Encoding encoding = lldb::eEncodingIEEE754;
- if (qual_type->isComplexType())
- encoding = lldb::eEncodingIEEE754;
- else
- {
- const clang::ComplexType *complex_type = qual_type->getAsComplexIntegerType();
- if (complex_type)
- encoding = ClangASTType(m_ast, complex_type->getElementType()).GetEncoding(count);
- else
- encoding = lldb::eEncodingSint;
- }
- count = 2;
- return encoding;
- }
-
- case clang::Type::ObjCInterface: break;
- case clang::Type::Record: break;
- case clang::Type::Enum: return lldb::eEncodingSint;
- case clang::Type::Typedef:
- return ClangASTType(m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetEncoding(count);
-
- case clang::Type::Elaborated:
- return ClangASTType(m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetEncoding(count);
-
- case clang::Type::Paren:
- return ClangASTType(m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetEncoding(count);
-
- case clang::Type::DependentSizedArray:
- case clang::Type::DependentSizedExtVector:
- case clang::Type::UnresolvedUsing:
- case clang::Type::Attributed:
- case clang::Type::TemplateTypeParm:
- case clang::Type::SubstTemplateTypeParm:
- case clang::Type::SubstTemplateTypeParmPack:
- case clang::Type::Auto:
- case clang::Type::InjectedClassName:
- case clang::Type::DependentName:
- case clang::Type::DependentTemplateSpecialization:
- case clang::Type::PackExpansion:
- case clang::Type::ObjCObject:
-
- case clang::Type::TypeOfExpr:
- case clang::Type::TypeOf:
- case clang::Type::Decltype:
- case clang::Type::TemplateSpecialization:
- case clang::Type::Atomic:
- case clang::Type::Adjusted:
- break;
-
- // pointer type decayed from an array or function type.
- case clang::Type::Decayed:
- break;
- }
- count = 0;
- return lldb::eEncodingInvalid;
-}
-
-lldb::Format
-ClangASTType::GetFormat () const
-{
- if (!IsValid())
- return lldb::eFormatDefault;
-
- clang::QualType qual_type(GetCanonicalQualType());
-
- switch (qual_type->getTypeClass())
- {
- case clang::Type::UnaryTransform:
- break;
-
- case clang::Type::FunctionNoProto:
- case clang::Type::FunctionProto:
- break;
-
- case clang::Type::IncompleteArray:
- case clang::Type::VariableArray:
- break;
-
- case clang::Type::ConstantArray:
- return lldb::eFormatVoid; // no value
-
- case clang::Type::ExtVector:
- case clang::Type::Vector:
- break;
-
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
- {
- //default: assert(0 && "Unknown builtin type!");
- case clang::BuiltinType::UnknownAny:
- case clang::BuiltinType::Void:
- case clang::BuiltinType::BoundMember:
- break;
-
- case clang::BuiltinType::Bool: return lldb::eFormatBoolean;
- case clang::BuiltinType::Char_S:
- case clang::BuiltinType::SChar:
- case clang::BuiltinType::WChar_S:
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::WChar_U: return lldb::eFormatChar;
- case clang::BuiltinType::Char16: return lldb::eFormatUnicode16;
- case clang::BuiltinType::Char32: return lldb::eFormatUnicode32;
- case clang::BuiltinType::UShort: return lldb::eFormatUnsigned;
- case clang::BuiltinType::Short: return lldb::eFormatDecimal;
- case clang::BuiltinType::UInt: return lldb::eFormatUnsigned;
- case clang::BuiltinType::Int: return lldb::eFormatDecimal;
- case clang::BuiltinType::ULong: return lldb::eFormatUnsigned;
- case clang::BuiltinType::Long: return lldb::eFormatDecimal;
- case clang::BuiltinType::ULongLong: return lldb::eFormatUnsigned;
- case clang::BuiltinType::LongLong: return lldb::eFormatDecimal;
- case clang::BuiltinType::UInt128: return lldb::eFormatUnsigned;
- case clang::BuiltinType::Int128: return lldb::eFormatDecimal;
- case clang::BuiltinType::Float: return lldb::eFormatFloat;
- case clang::BuiltinType::Double: return lldb::eFormatFloat;
- case clang::BuiltinType::LongDouble: return lldb::eFormatFloat;
- case clang::BuiltinType::NullPtr:
- case clang::BuiltinType::Overload:
- case clang::BuiltinType::Dependent:
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- case clang::BuiltinType::ObjCSel:
- case clang::BuiltinType::Half:
- case clang::BuiltinType::ARCUnbridgedCast:
- case clang::BuiltinType::PseudoObject:
- case clang::BuiltinType::BuiltinFn:
- case clang::BuiltinType::OCLEvent:
- case clang::BuiltinType::OCLImage1d:
- case clang::BuiltinType::OCLImage1dArray:
- case clang::BuiltinType::OCLImage1dBuffer:
- case clang::BuiltinType::OCLImage2d:
- case clang::BuiltinType::OCLImage2dArray:
- case clang::BuiltinType::OCLImage3d:
- case clang::BuiltinType::OCLSampler:
- return lldb::eFormatHex;
- }
- break;
- case clang::Type::ObjCObjectPointer: return lldb::eFormatHex;
- case clang::Type::BlockPointer: return lldb::eFormatHex;
- case clang::Type::Pointer: return lldb::eFormatHex;
- case clang::Type::LValueReference:
- case clang::Type::RValueReference: return lldb::eFormatHex;
- case clang::Type::MemberPointer: break;
- case clang::Type::Complex:
- {
- if (qual_type->isComplexType())
- return lldb::eFormatComplex;
- else
- return lldb::eFormatComplexInteger;
- }
- case clang::Type::ObjCInterface: break;
- case clang::Type::Record: break;
- case clang::Type::Enum: return lldb::eFormatEnum;
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetFormat();
- case clang::Type::Auto:
- return ClangASTType (m_ast, llvm::cast<clang::AutoType>(qual_type)->desugar()).GetFormat();
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetFormat();
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetFormat();
- case clang::Type::DependentSizedArray:
- case clang::Type::DependentSizedExtVector:
- case clang::Type::UnresolvedUsing:
- case clang::Type::Attributed:
- case clang::Type::TemplateTypeParm:
- case clang::Type::SubstTemplateTypeParm:
- case clang::Type::SubstTemplateTypeParmPack:
- case clang::Type::InjectedClassName:
- case clang::Type::DependentName:
- case clang::Type::DependentTemplateSpecialization:
- case clang::Type::PackExpansion:
- case clang::Type::ObjCObject:
-
- case clang::Type::TypeOfExpr:
- case clang::Type::TypeOf:
- case clang::Type::Decltype:
- case clang::Type::TemplateSpecialization:
- case clang::Type::Atomic:
- case clang::Type::Adjusted:
- break;
-
- // pointer type decayed from an array or function type.
- case clang::Type::Decayed:
- break;
- }
- // We don't know hot to display this type...
- return lldb::eFormatBytes;
-}
-
-static bool
-ObjCDeclHasIVars (clang::ObjCInterfaceDecl *class_interface_decl, bool check_superclass)
-{
- while (class_interface_decl)
- {
- if (class_interface_decl->ivar_size() > 0)
- return true;
-
- if (check_superclass)
- class_interface_decl = class_interface_decl->getSuperClass();
- else
- break;
- }
- return false;
-}
-
-uint32_t
-ClangASTType::GetNumChildren (bool omit_empty_base_classes) const
-{
- if (!IsValid())
- return 0;
-
- uint32_t num_children = 0;
- clang::QualType qual_type(GetQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
- {
- case clang::BuiltinType::ObjCId: // child is Class
- case clang::BuiltinType::ObjCClass: // child is Class
- num_children = 1;
- break;
-
- default:
- break;
- }
- break;
-
- case clang::Type::Complex: return 0;
-
- case clang::Type::Record:
- if (GetCompleteQualType (m_ast, qual_type))
- {
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- assert(record_decl);
- const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
- if (cxx_record_decl)
- {
- if (omit_empty_base_classes)
- {
- // Check each base classes to see if it or any of its
- // base classes contain any fields. This can help
- // limit the noise in variable views by not having to
- // show base classes that contain no members.
- clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
- for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
- base_class != base_class_end;
- ++base_class)
- {
- const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
-
- // Skip empty base classes
- if (ClangASTContext::RecordHasFields(base_class_decl) == false)
- continue;
-
- num_children++;
- }
- }
- else
- {
- // Include all base classes
- num_children += cxx_record_decl->getNumBases();
- }
-
- }
- clang::RecordDecl::field_iterator field, field_end;
- for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field)
- ++num_children;
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (GetCompleteQualType (m_ast, qual_type))
- {
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert (objc_class_type);
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
-
- if (class_interface_decl)
- {
-
- clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
- if (superclass_interface_decl)
- {
- if (omit_empty_base_classes)
- {
- if (ObjCDeclHasIVars (superclass_interface_decl, true))
- ++num_children;
- }
- else
- ++num_children;
- }
-
- num_children += class_interface_decl->ivar_size();
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- {
- const clang::ObjCObjectPointerType *pointer_type = llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr());
- clang::QualType pointee_type = pointer_type->getPointeeType();
- uint32_t num_pointee_children = ClangASTType (m_ast,pointee_type).GetNumChildren (omit_empty_base_classes);
- // If this type points to a simple type, then it has 1 child
- if (num_pointee_children == 0)
- num_children = 1;
- else
- num_children = num_pointee_children;
- }
- break;
-
- case clang::Type::Vector:
- case clang::Type::ExtVector:
- num_children = llvm::cast<clang::VectorType>(qual_type.getTypePtr())->getNumElements();
- break;
-
- case clang::Type::ConstantArray:
- num_children = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue();
- break;
-
- case clang::Type::Pointer:
- {
- const clang::PointerType *pointer_type = llvm::cast<clang::PointerType>(qual_type.getTypePtr());
- clang::QualType pointee_type (pointer_type->getPointeeType());
- uint32_t num_pointee_children = ClangASTType (m_ast,pointee_type).GetNumChildren (omit_empty_base_classes);
- if (num_pointee_children == 0)
- {
- // We have a pointer to a pointee type that claims it has no children.
- // We will want to look at
- num_children = ClangASTType (m_ast, pointee_type).GetNumPointeeChildren();
- }
- else
- num_children = num_pointee_children;
- }
- break;
-
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- {
- const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- clang::QualType pointee_type = reference_type->getPointeeType();
- uint32_t num_pointee_children = ClangASTType (m_ast, pointee_type).GetNumChildren (omit_empty_base_classes);
- // If this type points to a simple type, then it has 1 child
- if (num_pointee_children == 0)
- num_children = 1;
- else
- num_children = num_pointee_children;
- }
- break;
-
-
- case clang::Type::Typedef:
- num_children = ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumChildren (omit_empty_base_classes);
- break;
-
- case clang::Type::Elaborated:
- num_children = ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumChildren (omit_empty_base_classes);
- break;
-
- case clang::Type::Paren:
- num_children = ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumChildren (omit_empty_base_classes);
- break;
- default:
- break;
- }
- return num_children;
-}
-
-lldb::BasicType
-ClangASTType::GetBasicTypeEnumeration () const
-{
- if (IsValid())
- {
- clang::QualType qual_type(GetQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- if (type_class == clang::Type::Builtin)
- {
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
- {
- case clang::BuiltinType::Void: return eBasicTypeVoid;
- case clang::BuiltinType::Bool: return eBasicTypeBool;
- case clang::BuiltinType::Char_S: return eBasicTypeSignedChar;
- case clang::BuiltinType::Char_U: return eBasicTypeUnsignedChar;
- case clang::BuiltinType::Char16: return eBasicTypeChar16;
- case clang::BuiltinType::Char32: return eBasicTypeChar32;
- case clang::BuiltinType::UChar: return eBasicTypeUnsignedChar;
- case clang::BuiltinType::SChar: return eBasicTypeSignedChar;
- case clang::BuiltinType::WChar_S: return eBasicTypeSignedWChar;
- case clang::BuiltinType::WChar_U: return eBasicTypeUnsignedWChar;
- case clang::BuiltinType::Short: return eBasicTypeShort;
- case clang::BuiltinType::UShort: return eBasicTypeUnsignedShort;
- case clang::BuiltinType::Int: return eBasicTypeInt;
- case clang::BuiltinType::UInt: return eBasicTypeUnsignedInt;
- case clang::BuiltinType::Long: return eBasicTypeLong;
- case clang::BuiltinType::ULong: return eBasicTypeUnsignedLong;
- case clang::BuiltinType::LongLong: return eBasicTypeLongLong;
- case clang::BuiltinType::ULongLong: return eBasicTypeUnsignedLongLong;
- case clang::BuiltinType::Int128: return eBasicTypeInt128;
- case clang::BuiltinType::UInt128: return eBasicTypeUnsignedInt128;
-
- case clang::BuiltinType::Half: return eBasicTypeHalf;
- case clang::BuiltinType::Float: return eBasicTypeFloat;
- case clang::BuiltinType::Double: return eBasicTypeDouble;
- case clang::BuiltinType::LongDouble:return eBasicTypeLongDouble;
-
- case clang::BuiltinType::NullPtr: return eBasicTypeNullPtr;
- case clang::BuiltinType::ObjCId: return eBasicTypeObjCID;
- case clang::BuiltinType::ObjCClass: return eBasicTypeObjCClass;
- case clang::BuiltinType::ObjCSel: return eBasicTypeObjCSel;
- case clang::BuiltinType::Dependent:
- case clang::BuiltinType::Overload:
- case clang::BuiltinType::BoundMember:
- case clang::BuiltinType::PseudoObject:
- case clang::BuiltinType::UnknownAny:
- case clang::BuiltinType::BuiltinFn:
- case clang::BuiltinType::ARCUnbridgedCast:
- case clang::BuiltinType::OCLEvent:
- case clang::BuiltinType::OCLImage1d:
- case clang::BuiltinType::OCLImage1dArray:
- case clang::BuiltinType::OCLImage1dBuffer:
- case clang::BuiltinType::OCLImage2d:
- case clang::BuiltinType::OCLImage2dArray:
- case clang::BuiltinType::OCLImage3d:
- case clang::BuiltinType::OCLSampler:
- return eBasicTypeOther;
- }
- }
- }
- return eBasicTypeInvalid;
-}
-
-
-#pragma mark Aggregate Types
-
-uint32_t
-ClangASTType::GetNumDirectBaseClasses () const
-{
- if (!IsValid())
- return 0;
-
- uint32_t count = 0;
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType())
- {
- const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- count = cxx_record_decl->getNumBases();
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- count = GetPointeeType().GetNumDirectBaseClasses();
- break;
-
- case clang::Type::ObjCObject:
- if (GetCompleteType())
- {
- const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
-
- if (class_interface_decl && class_interface_decl->getSuperClass())
- count = 1;
- }
- }
- break;
- case clang::Type::ObjCInterface:
- if (GetCompleteType())
- {
- const clang::ObjCInterfaceType *objc_interface_type = qual_type->getAs<clang::ObjCInterfaceType>();
- if (objc_interface_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
-
- if (class_interface_decl && class_interface_decl->getSuperClass())
- count = 1;
- }
- }
- break;
-
-
- case clang::Type::Typedef:
- count = ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumDirectBaseClasses ();
- break;
-
- case clang::Type::Elaborated:
- count = ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumDirectBaseClasses ();
- break;
-
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumDirectBaseClasses ();
-
- default:
- break;
- }
- return count;
-}
-
-uint32_t
-ClangASTType::GetNumVirtualBaseClasses () const
-{
- if (!IsValid())
- return 0;
-
- uint32_t count = 0;
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType())
- {
- const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- count = cxx_record_decl->getNumVBases();
- }
- break;
-
- case clang::Type::Typedef:
- count = ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumVirtualBaseClasses();
- break;
-
- case clang::Type::Elaborated:
- count = ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumVirtualBaseClasses();
- break;
-
- case clang::Type::Paren:
- count = ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumVirtualBaseClasses();
- break;
-
- default:
- break;
- }
- return count;
-}
-
-uint32_t
-ClangASTType::GetNumFields () const
-{
- if (!IsValid())
- return 0;
-
- uint32_t count = 0;
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType())
- {
- const clang::RecordType *record_type = llvm::dyn_cast<clang::RecordType>(qual_type.getTypePtr());
- if (record_type)
- {
- clang::RecordDecl *record_decl = record_type->getDecl();
- if (record_decl)
- {
- uint32_t field_idx = 0;
- clang::RecordDecl::field_iterator field, field_end;
- for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field)
- ++field_idx;
- count = field_idx;
- }
- }
- }
- break;
-
- case clang::Type::Typedef:
- count = ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumFields();
- break;
-
- case clang::Type::Elaborated:
- count = ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumFields();
- break;
-
- case clang::Type::Paren:
- count = ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumFields();
- break;
-
- case clang::Type::ObjCObjectPointer:
- if (GetCompleteType())
- {
- const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
-
- if (class_interface_decl)
- count = class_interface_decl->ivar_size();
- }
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (GetCompleteType())
- {
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
-
- if (class_interface_decl)
- count = class_interface_decl->ivar_size();
- }
- }
- break;
-
- default:
- break;
- }
- return count;
-}
-
-ClangASTType
-ClangASTType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) const
-{
- if (!IsValid())
- return ClangASTType();
-
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType())
- {
- const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- {
- uint32_t curr_idx = 0;
- clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
- for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
- base_class != base_class_end;
- ++base_class, ++curr_idx)
- {
- if (curr_idx == idx)
- {
- if (bit_offset_ptr)
- {
- const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(cxx_record_decl);
- const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
- if (base_class->isVirtual())
- *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
- else
- *bit_offset_ptr = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8;
- }
- return ClangASTType (m_ast, base_class->getType());
- }
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- return GetPointeeType().GetDirectBaseClassAtIndex(idx,bit_offset_ptr);
-
- case clang::Type::ObjCObject:
- if (idx == 0 && GetCompleteType())
- {
- const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType();
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
-
- if (class_interface_decl)
- {
- clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
- if (superclass_interface_decl)
- {
- if (bit_offset_ptr)
- *bit_offset_ptr = 0;
- return ClangASTType (m_ast, m_ast->getObjCInterfaceType(superclass_interface_decl));
- }
- }
- }
- }
- break;
- case clang::Type::ObjCInterface:
- if (idx == 0 && GetCompleteType())
- {
- const clang::ObjCObjectType *objc_interface_type = qual_type->getAs<clang::ObjCInterfaceType>();
- if (objc_interface_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface();
-
- if (class_interface_decl)
- {
- clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
- if (superclass_interface_decl)
- {
- if (bit_offset_ptr)
- *bit_offset_ptr = 0;
- return ClangASTType (m_ast, m_ast->getObjCInterfaceType(superclass_interface_decl));
- }
- }
- }
- }
- break;
-
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr);
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr);
-
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetDirectBaseClassAtIndex (idx, bit_offset_ptr);
-
- default:
- break;
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::GetVirtualBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) const
-{
- if (!IsValid())
- return ClangASTType();
-
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType())
- {
- const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- {
- uint32_t curr_idx = 0;
- clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
- for (base_class = cxx_record_decl->vbases_begin(), base_class_end = cxx_record_decl->vbases_end();
- base_class != base_class_end;
- ++base_class, ++curr_idx)
- {
- if (curr_idx == idx)
- {
- if (bit_offset_ptr)
- {
- const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(cxx_record_decl);
- const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
- *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
-
- }
- return ClangASTType (m_ast, base_class->getType());
- }
- }
- }
- }
- break;
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr);
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr);
-
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetVirtualBaseClassAtIndex (idx, bit_offset_ptr);
-
- default:
- break;
- }
- return ClangASTType();
-}
-
-static clang_type_t
-GetObjCFieldAtIndex (clang::ASTContext *ast,
- clang::ObjCInterfaceDecl *class_interface_decl,
- size_t idx,
- std::string& name,
- uint64_t *bit_offset_ptr,
- uint32_t *bitfield_bit_size_ptr,
- bool *is_bitfield_ptr)
-{
- if (class_interface_decl)
- {
- if (idx < (class_interface_decl->ivar_size()))
- {
- clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
- uint32_t ivar_idx = 0;
-
- for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++ivar_idx)
- {
- if (ivar_idx == idx)
- {
- const clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
-
- clang::QualType ivar_qual_type(ivar_decl->getType());
-
- name.assign(ivar_decl->getNameAsString());
-
- if (bit_offset_ptr)
- {
- const clang::ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl);
- *bit_offset_ptr = interface_layout.getFieldOffset (ivar_idx);
- }
-
- const bool is_bitfield = ivar_pos->isBitField();
-
- if (bitfield_bit_size_ptr)
- {
- *bitfield_bit_size_ptr = 0;
-
- if (is_bitfield && ast)
- {
- clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth();
- llvm::APSInt bitfield_apsint;
- if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *ast))
- {
- *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
- }
- }
- }
- if (is_bitfield_ptr)
- *is_bitfield_ptr = is_bitfield;
-
- return ivar_qual_type.getAsOpaquePtr();
- }
- }
- }
- }
- return nullptr;
-}
-
-ClangASTType
-ClangASTType::GetFieldAtIndex (size_t idx,
- std::string& name,
- uint64_t *bit_offset_ptr,
- uint32_t *bitfield_bit_size_ptr,
- bool *is_bitfield_ptr) const
-{
- if (!IsValid())
- return ClangASTType();
-
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType())
- {
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- uint32_t field_idx = 0;
- clang::RecordDecl::field_iterator field, field_end;
- for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx)
- {
- if (idx == field_idx)
- {
- // Print the member type if requested
- // Print the member name and equal sign
- name.assign(field->getNameAsString());
-
- // Figure out the type byte size (field_type_info.first) and
- // alignment (field_type_info.second) from the AST context.
- if (bit_offset_ptr)
- {
- const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl);
- *bit_offset_ptr = record_layout.getFieldOffset (field_idx);
- }
-
- const bool is_bitfield = field->isBitField();
-
- if (bitfield_bit_size_ptr)
- {
- *bitfield_bit_size_ptr = 0;
-
- if (is_bitfield)
- {
- clang::Expr *bitfield_bit_size_expr = field->getBitWidth();
- llvm::APSInt bitfield_apsint;
- if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *m_ast))
- {
- *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
- }
- }
- }
- if (is_bitfield_ptr)
- *is_bitfield_ptr = is_bitfield;
-
- return ClangASTType (m_ast, field->getType());
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- if (GetCompleteType())
- {
- const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType();
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl();
- return ClangASTType (m_ast, GetObjCFieldAtIndex(m_ast, class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr));
- }
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (GetCompleteType())
- {
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert (objc_class_type);
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
- return ClangASTType (m_ast, GetObjCFieldAtIndex(m_ast, class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr));
- }
- }
- break;
-
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).
- GetFieldAtIndex (idx,
- name,
- bit_offset_ptr,
- bitfield_bit_size_ptr,
- is_bitfield_ptr);
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).
- GetFieldAtIndex (idx,
- name,
- bit_offset_ptr,
- bitfield_bit_size_ptr,
- is_bitfield_ptr);
-
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).
- GetFieldAtIndex (idx,
- name,
- bit_offset_ptr,
- bitfield_bit_size_ptr,
- is_bitfield_ptr);
-
- default:
- break;
- }
- return ClangASTType();
-}
-
-uint32_t
-ClangASTType::GetIndexOfFieldWithName (const char* name,
- ClangASTType* field_clang_type_ptr,
- uint64_t *bit_offset_ptr,
- uint32_t *bitfield_bit_size_ptr,
- bool *is_bitfield_ptr) const
-{
- unsigned count = GetNumFields();
- std::string field_name;
- for (unsigned index = 0; index < count; index++)
- {
- ClangASTType field_clang_type (GetFieldAtIndex(index, field_name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr));
- if (strcmp(field_name.c_str(), name) == 0)
- {
- if (field_clang_type_ptr)
- *field_clang_type_ptr = field_clang_type;
- return index;
- }
- }
- return UINT32_MAX;
-}
-
-// If a pointer to a pointee type (the clang_type arg) says that it has no
-// children, then we either need to trust it, or override it and return a
-// different result. For example, an "int *" has one child that is an integer,
-// but a function pointer doesn't have any children. Likewise if a Record type
-// claims it has no children, then there really is nothing to show.
-uint32_t
-ClangASTType::GetNumPointeeChildren () const
-{
- if (!IsValid())
- return 0;
-
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Builtin:
- switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind())
- {
- case clang::BuiltinType::UnknownAny:
- case clang::BuiltinType::Void:
- case clang::BuiltinType::NullPtr:
- case clang::BuiltinType::OCLEvent:
- case clang::BuiltinType::OCLImage1d:
- case clang::BuiltinType::OCLImage1dArray:
- case clang::BuiltinType::OCLImage1dBuffer:
- case clang::BuiltinType::OCLImage2d:
- case clang::BuiltinType::OCLImage2dArray:
- case clang::BuiltinType::OCLImage3d:
- case clang::BuiltinType::OCLSampler:
- return 0;
- case clang::BuiltinType::Bool:
- case clang::BuiltinType::Char_U:
- case clang::BuiltinType::UChar:
- case clang::BuiltinType::WChar_U:
- case clang::BuiltinType::Char16:
- case clang::BuiltinType::Char32:
- case clang::BuiltinType::UShort:
- case clang::BuiltinType::UInt:
- case clang::BuiltinType::ULong:
- case clang::BuiltinType::ULongLong:
- case clang::BuiltinType::UInt128:
- case clang::BuiltinType::Char_S:
- case clang::BuiltinType::SChar:
- case clang::BuiltinType::WChar_S:
- case clang::BuiltinType::Short:
- case clang::BuiltinType::Int:
- case clang::BuiltinType::Long:
- case clang::BuiltinType::LongLong:
- case clang::BuiltinType::Int128:
- case clang::BuiltinType::Float:
- case clang::BuiltinType::Double:
- case clang::BuiltinType::LongDouble:
- case clang::BuiltinType::Dependent:
- case clang::BuiltinType::Overload:
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- case clang::BuiltinType::ObjCSel:
- case clang::BuiltinType::BoundMember:
- case clang::BuiltinType::Half:
- case clang::BuiltinType::ARCUnbridgedCast:
- case clang::BuiltinType::PseudoObject:
- case clang::BuiltinType::BuiltinFn:
- return 1;
- }
- break;
-
- case clang::Type::Complex: return 1;
- case clang::Type::Pointer: return 1;
- case clang::Type::BlockPointer: return 0; // If block pointers don't have debug info, then no children for them
- case clang::Type::LValueReference: return 1;
- case clang::Type::RValueReference: return 1;
- case clang::Type::MemberPointer: return 0;
- case clang::Type::ConstantArray: return 0;
- case clang::Type::IncompleteArray: return 0;
- case clang::Type::VariableArray: return 0;
- case clang::Type::DependentSizedArray: return 0;
- case clang::Type::DependentSizedExtVector: return 0;
- case clang::Type::Vector: return 0;
- case clang::Type::ExtVector: return 0;
- case clang::Type::FunctionProto: return 0; // When we function pointers, they have no children...
- case clang::Type::FunctionNoProto: return 0; // When we function pointers, they have no children...
- case clang::Type::UnresolvedUsing: return 0;
- case clang::Type::Paren: return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumPointeeChildren ();
- case clang::Type::Typedef: return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumPointeeChildren ();
- case clang::Type::Elaborated: return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumPointeeChildren ();
- case clang::Type::TypeOfExpr: return 0;
- case clang::Type::TypeOf: return 0;
- case clang::Type::Decltype: return 0;
- case clang::Type::Record: return 0;
- case clang::Type::Enum: return 1;
- case clang::Type::TemplateTypeParm: return 1;
- case clang::Type::SubstTemplateTypeParm: return 1;
- case clang::Type::TemplateSpecialization: return 1;
- case clang::Type::InjectedClassName: return 0;
- case clang::Type::DependentName: return 1;
- case clang::Type::DependentTemplateSpecialization: return 1;
- case clang::Type::ObjCObject: return 0;
- case clang::Type::ObjCInterface: return 0;
- case clang::Type::ObjCObjectPointer: return 1;
- default:
- break;
- }
- return 0;
-}
-
-
-ClangASTType
-ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
- size_t idx,
- bool transparent_pointers,
- bool omit_empty_base_classes,
- bool ignore_array_bounds,
- std::string& child_name,
- uint32_t &child_byte_size,
- int32_t &child_byte_offset,
- uint32_t &child_bitfield_bit_size,
- uint32_t &child_bitfield_bit_offset,
- bool &child_is_base_class,
- bool &child_is_deref_of_parent,
- ValueObject *valobj) const
-{
- if (!IsValid())
- return ClangASTType();
-
- clang::QualType parent_qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass parent_type_class = parent_qual_type->getTypeClass();
- child_bitfield_bit_size = 0;
- child_bitfield_bit_offset = 0;
- child_is_base_class = false;
-
- const bool idx_is_valid = idx < GetNumChildren (omit_empty_base_classes);
- uint32_t bit_offset;
- switch (parent_type_class)
- {
- case clang::Type::Builtin:
- if (idx_is_valid)
- {
- switch (llvm::cast<clang::BuiltinType>(parent_qual_type)->getKind())
- {
- case clang::BuiltinType::ObjCId:
- case clang::BuiltinType::ObjCClass:
- child_name = "isa";
- child_byte_size = m_ast->getTypeSize(m_ast->ObjCBuiltinClassTy) / CHAR_BIT;
- return ClangASTType (m_ast, m_ast->ObjCBuiltinClassTy);
-
- default:
- break;
- }
- }
- break;
-
- case clang::Type::Record:
- if (idx_is_valid && GetCompleteType())
- {
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(parent_qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- assert(record_decl);
- const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl);
- uint32_t child_idx = 0;
-
- const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
- if (cxx_record_decl)
- {
- // We might have base classes to print out first
- clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
- for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
- base_class != base_class_end;
- ++base_class)
- {
- const clang::CXXRecordDecl *base_class_decl = nullptr;
-
- // Skip empty base classes
- if (omit_empty_base_classes)
- {
- base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
- if (ClangASTContext::RecordHasFields(base_class_decl) == false)
- continue;
- }
-
- if (idx == child_idx)
- {
- if (base_class_decl == nullptr)
- base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
-
-
- if (base_class->isVirtual())
- {
- bool handled = false;
- if (valobj)
- {
- Error err;
- AddressType addr_type = eAddressTypeInvalid;
- lldb::addr_t vtable_ptr_addr = valobj->GetCPPVTableAddress(addr_type);
-
- if (vtable_ptr_addr != LLDB_INVALID_ADDRESS && addr_type == eAddressTypeLoad)
- {
-
- ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
- Process *process = exe_ctx.GetProcessPtr();
- if (process)
- {
- clang::VTableContextBase *vtable_ctx = m_ast->getVTableContext();
- if (vtable_ctx)
- {
- if (vtable_ctx->isMicrosoft())
- {
- clang::MicrosoftVTableContext *msoft_vtable_ctx = static_cast<clang::MicrosoftVTableContext *>(vtable_ctx);
-
- if (vtable_ptr_addr)
- {
- const lldb::addr_t vbtable_ptr_addr = vtable_ptr_addr + record_layout.getVBPtrOffset().getQuantity();
-
- const lldb::addr_t vbtable_ptr = process->ReadPointerFromMemory(vbtable_ptr_addr, err);
- if (vbtable_ptr != LLDB_INVALID_ADDRESS)
- {
- // Get the index into the virtual base table. The index is the index in uint32_t from vbtable_ptr
- const unsigned vbtable_index = msoft_vtable_ctx->getVBTableIndex(cxx_record_decl, base_class_decl);
- const lldb::addr_t base_offset_addr = vbtable_ptr + vbtable_index * 4;
- const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err);
- if (base_offset != UINT32_MAX)
- {
- handled = true;
- bit_offset = base_offset * 8;
- }
- }
- }
- }
- else
- {
- clang::ItaniumVTableContext *itanium_vtable_ctx = static_cast<clang::ItaniumVTableContext *>(vtable_ctx);
- if (vtable_ptr_addr)
- {
- const lldb::addr_t vtable_ptr = process->ReadPointerFromMemory(vtable_ptr_addr, err);
- if (vtable_ptr != LLDB_INVALID_ADDRESS)
- {
- clang::CharUnits base_offset_offset = itanium_vtable_ctx->getVirtualBaseOffsetOffset(cxx_record_decl, base_class_decl);
- const lldb::addr_t base_offset_addr = vtable_ptr + base_offset_offset.getQuantity();
- const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err);
- if (base_offset != UINT32_MAX)
- {
- handled = true;
- bit_offset = base_offset * 8;
- }
- }
- }
- }
- }
- }
- }
-
- }
- if (!handled)
- bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
- }
- else
- bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8;
-
- // Base classes should be a multiple of 8 bits in size
- child_byte_offset = bit_offset/8;
- ClangASTType base_class_clang_type(m_ast, base_class->getType());
- child_name = base_class_clang_type.GetTypeName().AsCString("");
- uint64_t base_class_clang_type_bit_size = base_class_clang_type.GetBitSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
-
- // Base classes bit sizes should be a multiple of 8 bits in size
- assert (base_class_clang_type_bit_size % 8 == 0);
- child_byte_size = base_class_clang_type_bit_size / 8;
- child_is_base_class = true;
- return base_class_clang_type;
- }
- // We don't increment the child index in the for loop since we might
- // be skipping empty base classes
- ++child_idx;
- }
- }
- // Make sure index is in range...
- uint32_t field_idx = 0;
- clang::RecordDecl::field_iterator field, field_end;
- for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx)
- {
- if (idx == child_idx)
- {
- // Print the member type if requested
- // Print the member name and equal sign
- child_name.assign(field->getNameAsString().c_str());
-
- // Figure out the type byte size (field_type_info.first) and
- // alignment (field_type_info.second) from the AST context.
- ClangASTType field_clang_type (m_ast, field->getType());
- assert(field_idx < record_layout.getFieldCount());
- child_byte_size = field_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
-
- // Figure out the field offset within the current struct/union/class type
- bit_offset = record_layout.getFieldOffset (field_idx);
- child_byte_offset = bit_offset / 8;
- if (ClangASTContext::FieldIsBitfield (m_ast, *field, child_bitfield_bit_size))
- child_bitfield_bit_offset = bit_offset % 8;
-
- return field_clang_type;
- }
- }
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (idx_is_valid && GetCompleteType())
- {
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(parent_qual_type.getTypePtr());
- assert (objc_class_type);
- if (objc_class_type)
- {
- uint32_t child_idx = 0;
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
-
- if (class_interface_decl)
- {
-
- const clang::ASTRecordLayout &interface_layout = m_ast->getASTObjCInterfaceLayout(class_interface_decl);
- clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
- if (superclass_interface_decl)
- {
- if (omit_empty_base_classes)
- {
- ClangASTType base_class_clang_type (m_ast, m_ast->getObjCInterfaceType(superclass_interface_decl));
- if (base_class_clang_type.GetNumChildren(omit_empty_base_classes) > 0)
- {
- if (idx == 0)
- {
- clang::QualType ivar_qual_type(m_ast->getObjCInterfaceType(superclass_interface_decl));
-
-
- child_name.assign(superclass_interface_decl->getNameAsString().c_str());
-
- clang::TypeInfo ivar_type_info = m_ast->getTypeInfo(ivar_qual_type.getTypePtr());
-
- child_byte_size = ivar_type_info.Width / 8;
- child_byte_offset = 0;
- child_is_base_class = true;
-
- return ClangASTType (m_ast, ivar_qual_type);
- }
-
- ++child_idx;
- }
- }
- else
- ++child_idx;
- }
-
- const uint32_t superclass_idx = child_idx;
-
- if (idx < (child_idx + class_interface_decl->ivar_size()))
- {
- clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
-
- for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos)
- {
- if (child_idx == idx)
- {
- clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
-
- clang::QualType ivar_qual_type(ivar_decl->getType());
-
- child_name.assign(ivar_decl->getNameAsString().c_str());
-
- clang::TypeInfo ivar_type_info = m_ast->getTypeInfo(ivar_qual_type.getTypePtr());
-
- child_byte_size = ivar_type_info.Width / 8;
-
- // Figure out the field offset within the current struct/union/class type
- // For ObjC objects, we can't trust the bit offset we get from the Clang AST, since
- // that doesn't account for the space taken up by unbacked properties, or from
- // the changing size of base classes that are newer than this class.
- // So if we have a process around that we can ask about this object, do so.
- child_byte_offset = LLDB_INVALID_IVAR_OFFSET;
- Process *process = nullptr;
- if (exe_ctx)
- process = exe_ctx->GetProcessPtr();
- if (process)
- {
- ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
- if (objc_runtime != nullptr)
- {
- ClangASTType parent_ast_type (m_ast, parent_qual_type);
- child_byte_offset = objc_runtime->GetByteOffsetForIvar (parent_ast_type, ivar_decl->getNameAsString().c_str());
- }
- }
-
- // Setting this to UINT32_MAX to make sure we don't compute it twice...
- bit_offset = UINT32_MAX;
-
- if (child_byte_offset == static_cast<int32_t>(LLDB_INVALID_IVAR_OFFSET))
- {
- bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx);
- child_byte_offset = bit_offset / 8;
- }
-
- // Note, the ObjC Ivar Byte offset is just that, it doesn't account for the bit offset
- // of a bitfield within its containing object. So regardless of where we get the byte
- // offset from, we still need to get the bit offset for bitfields from the layout.
-
- if (ClangASTContext::FieldIsBitfield (m_ast, ivar_decl, child_bitfield_bit_size))
- {
- if (bit_offset == UINT32_MAX)
- bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx);
-
- child_bitfield_bit_offset = bit_offset % 8;
- }
- return ClangASTType (m_ast, ivar_qual_type);
- }
- ++child_idx;
- }
- }
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- if (idx_is_valid)
- {
- ClangASTType pointee_clang_type (GetPointeeType());
-
- if (transparent_pointers && pointee_clang_type.IsAggregateType())
- {
- child_is_deref_of_parent = false;
- bool tmp_child_is_deref_of_parent = false;
- return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- idx,
- transparent_pointers,
- omit_empty_base_classes,
- ignore_array_bounds,
- child_name,
- child_byte_size,
- child_byte_offset,
- child_bitfield_bit_size,
- child_bitfield_bit_offset,
- child_is_base_class,
- tmp_child_is_deref_of_parent,
- valobj);
- }
- else
- {
- child_is_deref_of_parent = true;
- const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL;
- if (parent_name)
- {
- child_name.assign(1, '*');
- child_name += parent_name;
- }
-
- // We have a pointer to an simple type
- if (idx == 0 && pointee_clang_type.GetCompleteType())
- {
- child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = 0;
- return pointee_clang_type;
- }
- }
- }
- break;
-
- case clang::Type::Vector:
- case clang::Type::ExtVector:
- if (idx_is_valid)
- {
- const clang::VectorType *array = llvm::cast<clang::VectorType>(parent_qual_type.getTypePtr());
- if (array)
- {
- ClangASTType element_type (m_ast, array->getElementType());
- if (element_type.GetCompleteType())
- {
- char element_name[64];
- ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]", static_cast<uint64_t>(idx));
- child_name.assign(element_name);
- child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
- return element_type;
- }
- }
- }
- break;
-
- case clang::Type::ConstantArray:
- case clang::Type::IncompleteArray:
- if (ignore_array_bounds || idx_is_valid)
- {
- const clang::ArrayType *array = GetQualType()->getAsArrayTypeUnsafe();
- if (array)
- {
- ClangASTType element_type (m_ast, array->getElementType());
- if (element_type.GetCompleteType())
- {
- char element_name[64];
- ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]", static_cast<uint64_t>(idx));
- child_name.assign(element_name);
- child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
- return element_type;
- }
- }
- }
- break;
-
-
- case clang::Type::Pointer:
- if (idx_is_valid)
- {
- ClangASTType pointee_clang_type (GetPointeeType());
-
- // Don't dereference "void *" pointers
- if (pointee_clang_type.IsVoidType())
- return ClangASTType();
-
- if (transparent_pointers && pointee_clang_type.IsAggregateType ())
- {
- child_is_deref_of_parent = false;
- bool tmp_child_is_deref_of_parent = false;
- return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- idx,
- transparent_pointers,
- omit_empty_base_classes,
- ignore_array_bounds,
- child_name,
- child_byte_size,
- child_byte_offset,
- child_bitfield_bit_size,
- child_bitfield_bit_offset,
- child_is_base_class,
- tmp_child_is_deref_of_parent,
- valobj);
- }
- else
- {
- child_is_deref_of_parent = true;
-
- const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL;
- if (parent_name)
- {
- child_name.assign(1, '*');
- child_name += parent_name;
- }
-
- // We have a pointer to an simple type
- if (idx == 0)
- {
- child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = 0;
- return pointee_clang_type;
- }
- }
- }
- break;
-
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- if (idx_is_valid)
- {
- const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr());
- ClangASTType pointee_clang_type (m_ast, reference_type->getPointeeType());
- if (transparent_pointers && pointee_clang_type.IsAggregateType ())
- {
- child_is_deref_of_parent = false;
- bool tmp_child_is_deref_of_parent = false;
- return pointee_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- idx,
- transparent_pointers,
- omit_empty_base_classes,
- ignore_array_bounds,
- child_name,
- child_byte_size,
- child_byte_offset,
- child_bitfield_bit_size,
- child_bitfield_bit_offset,
- child_is_base_class,
- tmp_child_is_deref_of_parent,
- valobj);
- }
- else
- {
- const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL;
- if (parent_name)
- {
- child_name.assign(1, '&');
- child_name += parent_name;
- }
-
- // We have a pointer to an simple type
- if (idx == 0)
- {
- child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = 0;
- return pointee_clang_type;
- }
- }
- }
- break;
-
- case clang::Type::Typedef:
- {
- ClangASTType typedefed_clang_type (m_ast, llvm::cast<clang::TypedefType>(parent_qual_type)->getDecl()->getUnderlyingType());
- return typedefed_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- idx,
- transparent_pointers,
- omit_empty_base_classes,
- ignore_array_bounds,
- child_name,
- child_byte_size,
- child_byte_offset,
- child_bitfield_bit_size,
- child_bitfield_bit_offset,
- child_is_base_class,
- child_is_deref_of_parent,
- valobj);
- }
- break;
-
- case clang::Type::Elaborated:
- {
- ClangASTType elaborated_clang_type (m_ast, llvm::cast<clang::ElaboratedType>(parent_qual_type)->getNamedType());
- return elaborated_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- idx,
- transparent_pointers,
- omit_empty_base_classes,
- ignore_array_bounds,
- child_name,
- child_byte_size,
- child_byte_offset,
- child_bitfield_bit_size,
- child_bitfield_bit_offset,
- child_is_base_class,
- child_is_deref_of_parent,
- valobj);
- }
-
- case clang::Type::Paren:
- {
- ClangASTType paren_clang_type (m_ast, llvm::cast<clang::ParenType>(parent_qual_type)->desugar());
- return paren_clang_type.GetChildClangTypeAtIndex (exe_ctx,
- idx,
- transparent_pointers,
- omit_empty_base_classes,
- ignore_array_bounds,
- child_name,
- child_byte_size,
- child_byte_offset,
- child_bitfield_bit_size,
- child_bitfield_bit_offset,
- child_is_base_class,
- child_is_deref_of_parent,
- valobj);
- }
-
-
- default:
- break;
- }
- return ClangASTType();
-}
-
-static inline bool
-BaseSpecifierIsEmpty (const clang::CXXBaseSpecifier *b)
-{
- return ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()) == false;
-}
-
-static uint32_t
-GetIndexForRecordBase
-(
- const clang::RecordDecl *record_decl,
- const clang::CXXBaseSpecifier *base_spec,
- bool omit_empty_base_classes
- )
-{
- uint32_t child_idx = 0;
-
- const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
- // const char *super_name = record_decl->getNameAsCString();
- // const char *base_name = base_spec->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString();
- // printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name);
- //
- if (cxx_record_decl)
- {
- clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
- for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
- base_class != base_class_end;
- ++base_class)
- {
- if (omit_empty_base_classes)
- {
- if (BaseSpecifierIsEmpty (base_class))
- continue;
- }
-
- // printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n", super_name, base_name,
- // child_idx,
- // base_class->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString());
- //
- //
- if (base_class == base_spec)
- return child_idx;
- ++child_idx;
- }
- }
-
- return UINT32_MAX;
-}
-
-
-static uint32_t
-GetIndexForRecordChild (const clang::RecordDecl *record_decl,
- clang::NamedDecl *canonical_decl,
- bool omit_empty_base_classes)
-{
- uint32_t child_idx = ClangASTContext::GetNumBaseClasses (llvm::dyn_cast<clang::CXXRecordDecl>(record_decl),
- omit_empty_base_classes);
-
- clang::RecordDecl::field_iterator field, field_end;
- for (field = record_decl->field_begin(), field_end = record_decl->field_end();
- field != field_end;
- ++field, ++child_idx)
- {
- if (field->getCanonicalDecl() == canonical_decl)
- return child_idx;
- }
-
- return UINT32_MAX;
-}
-
-// Look for a child member (doesn't include base classes, but it does include
-// their members) in the type hierarchy. Returns an index path into "clang_type"
-// on how to reach the appropriate member.
-//
-// class A
-// {
-// public:
-// int m_a;
-// int m_b;
-// };
-//
-// class B
-// {
-// };
-//
-// class C :
-// public B,
-// public A
-// {
-// };
-//
-// If we have a clang type that describes "class C", and we wanted to looked
-// "m_b" in it:
-//
-// With omit_empty_base_classes == false we would get an integer array back with:
-// { 1, 1 }
-// The first index 1 is the child index for "class A" within class C
-// The second index 1 is the child index for "m_b" within class A
-//
-// With omit_empty_base_classes == true we would get an integer array back with:
-// { 0, 1 }
-// The first index 0 is the child index for "class A" within class C (since class B doesn't have any members it doesn't count)
-// The second index 1 is the child index for "m_b" within class A
-
-size_t
-ClangASTType::GetIndexOfChildMemberWithName (const char *name,
- bool omit_empty_base_classes,
- std::vector<uint32_t>& child_indexes) const
-{
- if (IsValid() && name && name[0])
- {
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType ())
- {
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
-
- assert(record_decl);
- uint32_t child_idx = 0;
-
- const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
- // Try and find a field that matches NAME
- clang::RecordDecl::field_iterator field, field_end;
- llvm::StringRef name_sref(name);
- for (field = record_decl->field_begin(), field_end = record_decl->field_end();
- field != field_end;
- ++field, ++child_idx)
- {
- llvm::StringRef field_name = field->getName();
- if (field_name.empty())
- {
- ClangASTType field_type(m_ast,field->getType());
- child_indexes.push_back(child_idx);
- if (field_type.GetIndexOfChildMemberWithName(name, omit_empty_base_classes, child_indexes))
- return child_indexes.size();
- child_indexes.pop_back();
-
- }
- else if (field_name.equals (name_sref))
- {
- // We have to add on the number of base classes to this index!
- child_indexes.push_back (child_idx + ClangASTContext::GetNumBaseClasses (cxx_record_decl, omit_empty_base_classes));
- return child_indexes.size();
- }
- }
-
- if (cxx_record_decl)
- {
- const clang::RecordDecl *parent_record_decl = cxx_record_decl;
-
- //printf ("parent = %s\n", parent_record_decl->getNameAsCString());
-
- //const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl();
- // Didn't find things easily, lets let clang do its thang...
- clang::IdentifierInfo & ident_ref = m_ast->Idents.get(name_sref);
- clang::DeclarationName decl_name(&ident_ref);
-
- clang::CXXBasePaths paths;
- if (cxx_record_decl->lookupInBases(clang::CXXRecordDecl::FindOrdinaryMember,
- decl_name.getAsOpaquePtr(),
- paths))
- {
- clang::CXXBasePaths::const_paths_iterator path, path_end = paths.end();
- for (path = paths.begin(); path != path_end; ++path)
- {
- const size_t num_path_elements = path->size();
- for (size_t e=0; e<num_path_elements; ++e)
- {
- clang::CXXBasePathElement elem = (*path)[e];
-
- child_idx = GetIndexForRecordBase (parent_record_decl, elem.Base, omit_empty_base_classes);
- if (child_idx == UINT32_MAX)
- {
- child_indexes.clear();
- return 0;
- }
- else
- {
- child_indexes.push_back (child_idx);
- parent_record_decl = llvm::cast<clang::RecordDecl>(elem.Base->getType()->getAs<clang::RecordType>()->getDecl());
- }
- }
- for (clang::NamedDecl *path_decl : path->Decls)
- {
- child_idx = GetIndexForRecordChild (parent_record_decl, path_decl, omit_empty_base_classes);
- if (child_idx == UINT32_MAX)
- {
- child_indexes.clear();
- return 0;
- }
- else
- {
- child_indexes.push_back (child_idx);
- }
- }
- }
- return child_indexes.size();
- }
- }
-
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (GetCompleteType ())
- {
- llvm::StringRef name_sref(name);
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert (objc_class_type);
- if (objc_class_type)
- {
- uint32_t child_idx = 0;
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
-
- if (class_interface_decl)
- {
- clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
- clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
-
- for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx)
- {
- const clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
-
- if (ivar_decl->getName().equals (name_sref))
- {
- if ((!omit_empty_base_classes && superclass_interface_decl) ||
- ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true)))
- ++child_idx;
-
- child_indexes.push_back (child_idx);
- return child_indexes.size();
- }
- }
-
- if (superclass_interface_decl)
- {
- // The super class index is always zero for ObjC classes,
- // so we push it onto the child indexes in case we find
- // an ivar in our superclass...
- child_indexes.push_back (0);
-
- ClangASTType superclass_clang_type (m_ast, m_ast->getObjCInterfaceType(superclass_interface_decl));
- if (superclass_clang_type.GetIndexOfChildMemberWithName (name,
- omit_empty_base_classes,
- child_indexes))
- {
- // We did find an ivar in a superclass so just
- // return the results!
- return child_indexes.size();
- }
-
- // We didn't find an ivar matching "name" in our
- // superclass, pop the superclass zero index that
- // we pushed on above.
- child_indexes.pop_back();
- }
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- {
- ClangASTType objc_object_clang_type (m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType());
- return objc_object_clang_type.GetIndexOfChildMemberWithName (name,
- omit_empty_base_classes,
- child_indexes);
- }
- break;
-
-
- case clang::Type::ConstantArray:
- {
- // const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr());
- // const uint64_t element_count = array->getSize().getLimitedValue();
- //
- // if (idx < element_count)
- // {
- // std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(array->getElementType());
- //
- // char element_name[32];
- // ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx);
- //
- // child_name.assign(element_name);
- // assert(field_type_info.first % 8 == 0);
- // child_byte_size = field_type_info.first / 8;
- // child_byte_offset = idx * child_byte_size;
- // return array->getElementType().getAsOpaquePtr();
- // }
- }
- break;
-
- // case clang::Type::MemberPointerType:
- // {
- // MemberPointerType *mem_ptr_type = llvm::cast<MemberPointerType>(qual_type.getTypePtr());
- // clang::QualType pointee_type = mem_ptr_type->getPointeeType();
- //
- // if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
- // {
- // return GetIndexOfChildWithName (ast,
- // mem_ptr_type->getPointeeType().getAsOpaquePtr(),
- // name);
- // }
- // }
- // break;
- //
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- {
- const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- clang::QualType pointee_type(reference_type->getPointeeType());
- ClangASTType pointee_clang_type (m_ast, pointee_type);
-
- if (pointee_clang_type.IsAggregateType ())
- {
- return pointee_clang_type.GetIndexOfChildMemberWithName (name,
- omit_empty_base_classes,
- child_indexes);
- }
- }
- break;
-
- case clang::Type::Pointer:
- {
- ClangASTType pointee_clang_type (GetPointeeType());
-
- if (pointee_clang_type.IsAggregateType ())
- {
- return pointee_clang_type.GetIndexOfChildMemberWithName (name,
- omit_empty_base_classes,
- child_indexes);
- }
- }
- break;
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildMemberWithName (name,
- omit_empty_base_classes,
- child_indexes);
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildMemberWithName (name,
- omit_empty_base_classes,
- child_indexes);
-
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildMemberWithName (name,
- omit_empty_base_classes,
- child_indexes);
-
- default:
- break;
- }
- }
- return 0;
-}
-
-
-// Get the index of the child of "clang_type" whose name matches. This function
-// doesn't descend into the children, but only looks one level deep and name
-// matches can include base class names.
-
-uint32_t
-ClangASTType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_classes) const
-{
- if (IsValid() && name && name[0])
- {
- clang::QualType qual_type(GetCanonicalQualType());
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
-
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType ())
- {
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
-
- assert(record_decl);
- uint32_t child_idx = 0;
-
- const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
- if (cxx_record_decl)
- {
- clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
- for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
- base_class != base_class_end;
- ++base_class)
- {
- // Skip empty base classes
- clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
- if (omit_empty_base_classes && ClangASTContext::RecordHasFields(base_class_decl) == false)
- continue;
-
- ClangASTType base_class_clang_type (m_ast, base_class->getType());
- std::string base_class_type_name (base_class_clang_type.GetTypeName().AsCString(""));
- if (base_class_type_name.compare (name) == 0)
- return child_idx;
- ++child_idx;
- }
- }
-
- // Try and find a field that matches NAME
- clang::RecordDecl::field_iterator field, field_end;
- llvm::StringRef name_sref(name);
- for (field = record_decl->field_begin(), field_end = record_decl->field_end();
- field != field_end;
- ++field, ++child_idx)
- {
- if (field->getName().equals (name_sref))
- return child_idx;
- }
-
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- if (GetCompleteType())
- {
- llvm::StringRef name_sref(name);
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert (objc_class_type);
- if (objc_class_type)
- {
- uint32_t child_idx = 0;
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
-
- if (class_interface_decl)
- {
- clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
- clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
-
- for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx)
- {
- const clang::ObjCIvarDecl* ivar_decl = *ivar_pos;
-
- if (ivar_decl->getName().equals (name_sref))
- {
- if ((!omit_empty_base_classes && superclass_interface_decl) ||
- ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true)))
- ++child_idx;
-
- return child_idx;
- }
- }
-
- if (superclass_interface_decl)
- {
- if (superclass_interface_decl->getName().equals (name_sref))
- return 0;
- }
- }
- }
- }
- break;
-
- case clang::Type::ObjCObjectPointer:
- {
- ClangASTType pointee_clang_type (m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType());
- return pointee_clang_type.GetIndexOfChildWithName (name, omit_empty_base_classes);
- }
- break;
-
- case clang::Type::ConstantArray:
- {
- // const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr());
- // const uint64_t element_count = array->getSize().getLimitedValue();
- //
- // if (idx < element_count)
- // {
- // std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(array->getElementType());
- //
- // char element_name[32];
- // ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx);
- //
- // child_name.assign(element_name);
- // assert(field_type_info.first % 8 == 0);
- // child_byte_size = field_type_info.first / 8;
- // child_byte_offset = idx * child_byte_size;
- // return array->getElementType().getAsOpaquePtr();
- // }
- }
- break;
-
- // case clang::Type::MemberPointerType:
- // {
- // MemberPointerType *mem_ptr_type = llvm::cast<MemberPointerType>(qual_type.getTypePtr());
- // clang::QualType pointee_type = mem_ptr_type->getPointeeType();
- //
- // if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
- // {
- // return GetIndexOfChildWithName (ast,
- // mem_ptr_type->getPointeeType().getAsOpaquePtr(),
- // name);
- // }
- // }
- // break;
- //
- case clang::Type::LValueReference:
- case clang::Type::RValueReference:
- {
- const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr());
- ClangASTType pointee_type (m_ast, reference_type->getPointeeType());
-
- if (pointee_type.IsAggregateType ())
- {
- return pointee_type.GetIndexOfChildWithName (name, omit_empty_base_classes);
- }
- }
- break;
-
- case clang::Type::Pointer:
- {
- const clang::PointerType *pointer_type = llvm::cast<clang::PointerType>(qual_type.getTypePtr());
- ClangASTType pointee_type (m_ast, pointer_type->getPointeeType());
-
- if (pointee_type.IsAggregateType ())
- {
- return pointee_type.GetIndexOfChildWithName (name, omit_empty_base_classes);
- }
- else
- {
- // if (parent_name)
- // {
- // child_name.assign(1, '*');
- // child_name += parent_name;
- // }
- //
- // // We have a pointer to an simple type
- // if (idx == 0)
- // {
- // std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type);
- // assert(clang_type_info.first % 8 == 0);
- // child_byte_size = clang_type_info.first / 8;
- // child_byte_offset = 0;
- // return pointee_type.getAsOpaquePtr();
- // }
- }
- }
- break;
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildWithName (name, omit_empty_base_classes);
-
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildWithName (name, omit_empty_base_classes);
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildWithName (name, omit_empty_base_classes);
-
- default:
- break;
- }
- }
- return UINT32_MAX;
-}
-
-
-size_t
-ClangASTType::GetNumTemplateArguments () const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType ())
- {
- const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- {
- const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(cxx_record_decl);
- if (template_decl)
- return template_decl->getTemplateArgs().size();
- }
- }
- break;
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumTemplateArguments();
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumTemplateArguments();
-
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumTemplateArguments();
-
- default:
- break;
- }
- }
- return 0;
-}
-
-ClangASTType
-ClangASTType::GetTemplateArgument (size_t arg_idx, lldb::TemplateArgumentKind &kind) const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- if (GetCompleteType ())
- {
- const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- {
- const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(cxx_record_decl);
- if (template_decl && arg_idx < template_decl->getTemplateArgs().size())
- {
- const clang::TemplateArgument &template_arg = template_decl->getTemplateArgs()[arg_idx];
- switch (template_arg.getKind())
- {
- case clang::TemplateArgument::Null:
- kind = eTemplateArgumentKindNull;
- return ClangASTType();
-
- case clang::TemplateArgument::Type:
- kind = eTemplateArgumentKindType;
- return ClangASTType(m_ast, template_arg.getAsType());
-
- case clang::TemplateArgument::Declaration:
- kind = eTemplateArgumentKindDeclaration;
- return ClangASTType();
-
- case clang::TemplateArgument::Integral:
- kind = eTemplateArgumentKindIntegral;
- return ClangASTType(m_ast, template_arg.getIntegralType());
-
- case clang::TemplateArgument::Template:
- kind = eTemplateArgumentKindTemplate;
- return ClangASTType();
-
- case clang::TemplateArgument::TemplateExpansion:
- kind = eTemplateArgumentKindTemplateExpansion;
- return ClangASTType();
-
- case clang::TemplateArgument::Expression:
- kind = eTemplateArgumentKindExpression;
- return ClangASTType();
-
- case clang::TemplateArgument::Pack:
- kind = eTemplateArgumentKindPack;
- return ClangASTType();
-
- default:
- assert (!"Unhandled clang::TemplateArgument::ArgKind");
- break;
- }
- }
- }
- }
- break;
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetTemplateArgument (arg_idx, kind);
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetTemplateArgument (arg_idx, kind);
-
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetTemplateArgument (arg_idx, kind);
-
- default:
- break;
- }
- }
- kind = eTemplateArgumentKindNull;
- return ClangASTType ();
-}
-
-static bool
-IsOperator (const char *name, clang::OverloadedOperatorKind &op_kind)
-{
- if (name == nullptr || name[0] == '\0')
- return false;
-
-#define OPERATOR_PREFIX "operator"
-#define OPERATOR_PREFIX_LENGTH (sizeof (OPERATOR_PREFIX) - 1)
-
- const char *post_op_name = nullptr;
-
- bool no_space = true;
-
- if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH))
- return false;
-
- post_op_name = name + OPERATOR_PREFIX_LENGTH;
-
- if (post_op_name[0] == ' ')
- {
- post_op_name++;
- no_space = false;
- }
-
-#undef OPERATOR_PREFIX
-#undef OPERATOR_PREFIX_LENGTH
-
- // This is an operator, set the overloaded operator kind to invalid
- // in case this is a conversion operator...
- op_kind = clang::NUM_OVERLOADED_OPERATORS;
-
- switch (post_op_name[0])
- {
- default:
- if (no_space)
- return false;
- break;
- case 'n':
- if (no_space)
- return false;
- if (strcmp (post_op_name, "new") == 0)
- op_kind = clang::OO_New;
- else if (strcmp (post_op_name, "new[]") == 0)
- op_kind = clang::OO_Array_New;
- break;
-
- case 'd':
- if (no_space)
- return false;
- if (strcmp (post_op_name, "delete") == 0)
- op_kind = clang::OO_Delete;
- else if (strcmp (post_op_name, "delete[]") == 0)
- op_kind = clang::OO_Array_Delete;
- break;
-
- case '+':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Plus;
- else if (post_op_name[2] == '\0')
- {
- if (post_op_name[1] == '=')
- op_kind = clang::OO_PlusEqual;
- else if (post_op_name[1] == '+')
- op_kind = clang::OO_PlusPlus;
- }
- break;
-
- case '-':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Minus;
- else if (post_op_name[2] == '\0')
- {
- switch (post_op_name[1])
- {
- case '=': op_kind = clang::OO_MinusEqual; break;
- case '-': op_kind = clang::OO_MinusMinus; break;
- case '>': op_kind = clang::OO_Arrow; break;
- }
- }
- else if (post_op_name[3] == '\0')
- {
- if (post_op_name[2] == '*')
- op_kind = clang::OO_ArrowStar; break;
- }
- break;
-
- case '*':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Star;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = clang::OO_StarEqual;
- break;
-
- case '/':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Slash;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = clang::OO_SlashEqual;
- break;
-
- case '%':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Percent;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = clang::OO_PercentEqual;
- break;
-
-
- case '^':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Caret;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = clang::OO_CaretEqual;
- break;
-
- case '&':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Amp;
- else if (post_op_name[2] == '\0')
- {
- switch (post_op_name[1])
- {
- case '=': op_kind = clang::OO_AmpEqual; break;
- case '&': op_kind = clang::OO_AmpAmp; break;
- }
- }
- break;
-
- case '|':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Pipe;
- else if (post_op_name[2] == '\0')
- {
- switch (post_op_name[1])
- {
- case '=': op_kind = clang::OO_PipeEqual; break;
- case '|': op_kind = clang::OO_PipePipe; break;
- }
- }
- break;
-
- case '~':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Tilde;
- break;
-
- case '!':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Exclaim;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = clang::OO_ExclaimEqual;
- break;
-
- case '=':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Equal;
- else if (post_op_name[1] == '=' && post_op_name[2] == '\0')
- op_kind = clang::OO_EqualEqual;
- break;
-
- case '<':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Less;
- else if (post_op_name[2] == '\0')
- {
- switch (post_op_name[1])
- {
- case '<': op_kind = clang::OO_LessLess; break;
- case '=': op_kind = clang::OO_LessEqual; break;
- }
- }
- else if (post_op_name[3] == '\0')
- {
- if (post_op_name[2] == '=')
- op_kind = clang::OO_LessLessEqual;
- }
- break;
-
- case '>':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Greater;
- else if (post_op_name[2] == '\0')
- {
- switch (post_op_name[1])
- {
- case '>': op_kind = clang::OO_GreaterGreater; break;
- case '=': op_kind = clang::OO_GreaterEqual; break;
- }
- }
- else if (post_op_name[1] == '>' &&
- post_op_name[2] == '=' &&
- post_op_name[3] == '\0')
- {
- op_kind = clang::OO_GreaterGreaterEqual;
- }
- break;
-
- case ',':
- if (post_op_name[1] == '\0')
- op_kind = clang::OO_Comma;
- break;
-
- case '(':
- if (post_op_name[1] == ')' && post_op_name[2] == '\0')
- op_kind = clang::OO_Call;
- break;
-
- case '[':
- if (post_op_name[1] == ']' && post_op_name[2] == '\0')
- op_kind = clang::OO_Subscript;
- break;
- }
-
- return true;
-}
-
-clang::EnumDecl *
-ClangASTType::GetAsEnumDecl () const
-{
- const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType());
- if (enum_type)
- return enum_type->getDecl();
- return NULL;
-}
-
-clang::RecordDecl *
-ClangASTType::GetAsRecordDecl () const
-{
- const clang::RecordType *record_type = llvm::dyn_cast<clang::RecordType>(GetCanonicalQualType());
- if (record_type)
- return record_type->getDecl();
- return nullptr;
-}
-
-clang::CXXRecordDecl *
-ClangASTType::GetAsCXXRecordDecl () const
-{
- return GetCanonicalQualType()->getAsCXXRecordDecl();
-}
-
-clang::ObjCInterfaceDecl *
-ClangASTType::GetAsObjCInterfaceDecl () const
-{
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(GetCanonicalQualType());
- if (objc_class_type)
- return objc_class_type->getInterface();
- return nullptr;
-}
-
-clang::FieldDecl *
-ClangASTType::AddFieldToRecordType (const char *name,
- const ClangASTType &field_clang_type,
- AccessType access,
- uint32_t bitfield_bit_size)
-{
- if (!IsValid() || !field_clang_type.IsValid())
- return nullptr;
-
- clang::FieldDecl *field = nullptr;
-
- clang::Expr *bit_width = nullptr;
- if (bitfield_bit_size != 0)
- {
- llvm::APInt bitfield_bit_size_apint(m_ast->getTypeSize(m_ast->IntTy), bitfield_bit_size);
- bit_width = new (*m_ast)clang::IntegerLiteral (*m_ast, bitfield_bit_size_apint, m_ast->IntTy, clang::SourceLocation());
- }
-
- clang::RecordDecl *record_decl = GetAsRecordDecl ();
- if (record_decl)
- {
- field = clang::FieldDecl::Create (*m_ast,
- record_decl,
- clang::SourceLocation(),
- clang::SourceLocation(),
- name ? &m_ast->Idents.get(name) : nullptr, // Identifier
- field_clang_type.GetQualType(), // Field type
- nullptr, // TInfo *
- bit_width, // BitWidth
- false, // Mutable
- clang::ICIS_NoInit); // HasInit
-
- if (!name)
- {
- // Determine whether this field corresponds to an anonymous
- // struct or union.
- if (const clang::TagType *TagT = field->getType()->getAs<clang::TagType>()) {
- if (clang::RecordDecl *Rec = llvm::dyn_cast<clang::RecordDecl>(TagT->getDecl()))
- if (!Rec->getDeclName()) {
- Rec->setAnonymousStructOrUnion(true);
- field->setImplicit();
-
- }
- }
- }
-
- if (field)
- {
- field->setAccess (ClangASTContext::ConvertAccessTypeToAccessSpecifier (access));
-
- record_decl->addDecl(field);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(field);
-#endif
- }
- }
- else
- {
- clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
-
- if (class_interface_decl)
- {
- const bool is_synthesized = false;
-
- field_clang_type.GetCompleteType();
-
- field = clang::ObjCIvarDecl::Create (*m_ast,
- class_interface_decl,
- clang::SourceLocation(),
- clang::SourceLocation(),
- name ? &m_ast->Idents.get(name) : nullptr, // Identifier
- field_clang_type.GetQualType(), // Field type
- nullptr, // TypeSourceInfo *
- ConvertAccessTypeToObjCIvarAccessControl (access),
- bit_width,
- is_synthesized);
-
- if (field)
- {
- class_interface_decl->addDecl(field);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(field);
-#endif
- }
- }
- }
- return field;
-}
-
-void
-ClangASTType::BuildIndirectFields ()
-{
- clang::RecordDecl *record_decl = GetAsRecordDecl();
-
- if (!record_decl)
- return;
-
- typedef llvm::SmallVector <clang::IndirectFieldDecl *, 1> IndirectFieldVector;
-
- IndirectFieldVector indirect_fields;
- clang::RecordDecl::field_iterator field_pos;
- clang::RecordDecl::field_iterator field_end_pos = record_decl->field_end();
- clang::RecordDecl::field_iterator last_field_pos = field_end_pos;
- for (field_pos = record_decl->field_begin(); field_pos != field_end_pos; last_field_pos = field_pos++)
- {
- if (field_pos->isAnonymousStructOrUnion())
- {
- clang::QualType field_qual_type = field_pos->getType();
-
- const clang::RecordType *field_record_type = field_qual_type->getAs<clang::RecordType>();
-
- if (!field_record_type)
- continue;
-
- clang::RecordDecl *field_record_decl = field_record_type->getDecl();
-
- if (!field_record_decl)
- continue;
-
- for (clang::RecordDecl::decl_iterator di = field_record_decl->decls_begin(), de = field_record_decl->decls_end();
- di != de;
- ++di)
- {
- if (clang::FieldDecl *nested_field_decl = llvm::dyn_cast<clang::FieldDecl>(*di))
- {
- clang::NamedDecl **chain = new (*m_ast) clang::NamedDecl*[2];
- chain[0] = *field_pos;
- chain[1] = nested_field_decl;
- clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*m_ast,
- record_decl,
- clang::SourceLocation(),
- nested_field_decl->getIdentifier(),
- nested_field_decl->getType(),
- chain,
- 2);
-
- indirect_field->setImplicit();
-
- indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(field_pos->getAccess(),
- nested_field_decl->getAccess()));
-
- indirect_fields.push_back(indirect_field);
- }
- else if (clang::IndirectFieldDecl *nested_indirect_field_decl = llvm::dyn_cast<clang::IndirectFieldDecl>(*di))
- {
- int nested_chain_size = nested_indirect_field_decl->getChainingSize();
- clang::NamedDecl **chain = new (*m_ast) clang::NamedDecl*[nested_chain_size + 1];
- chain[0] = *field_pos;
-
- int chain_index = 1;
- for (clang::IndirectFieldDecl::chain_iterator nci = nested_indirect_field_decl->chain_begin(),
- nce = nested_indirect_field_decl->chain_end();
- nci < nce;
- ++nci)
- {
- chain[chain_index] = *nci;
- chain_index++;
- }
-
- clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*m_ast,
- record_decl,
- clang::SourceLocation(),
- nested_indirect_field_decl->getIdentifier(),
- nested_indirect_field_decl->getType(),
- chain,
- nested_chain_size + 1);
-
- indirect_field->setImplicit();
-
- indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(field_pos->getAccess(),
- nested_indirect_field_decl->getAccess()));
-
- indirect_fields.push_back(indirect_field);
- }
- }
- }
- }
-
- // Check the last field to see if it has an incomplete array type as its
- // last member and if it does, the tell the record decl about it
- if (last_field_pos != field_end_pos)
- {
- if (last_field_pos->getType()->isIncompleteArrayType())
- record_decl->hasFlexibleArrayMember();
- }
-
- for (IndirectFieldVector::iterator ifi = indirect_fields.begin(), ife = indirect_fields.end();
- ifi < ife;
- ++ifi)
- {
- record_decl->addDecl(*ifi);
- }
-}
-
-void
-ClangASTType::SetIsPacked ()
-{
- clang::RecordDecl *record_decl = GetAsRecordDecl();
-
- if (!record_decl)
- return;
-
- record_decl->addAttr(clang::PackedAttr::CreateImplicit(*m_ast));
-}
-
-clang::VarDecl *
-ClangASTType::AddVariableToRecordType (const char *name,
- const ClangASTType &var_type,
- AccessType access)
-{
- clang::VarDecl *var_decl = nullptr;
-
- if (!IsValid() || !var_type.IsValid())
- return nullptr;
-
- clang::RecordDecl *record_decl = GetAsRecordDecl ();
- if (record_decl)
- {
- var_decl = clang::VarDecl::Create (*m_ast, // ASTContext &
- record_decl, // DeclContext *
- clang::SourceLocation(), // clang::SourceLocation StartLoc
- clang::SourceLocation(), // clang::SourceLocation IdLoc
- name ? &m_ast->Idents.get(name) : nullptr, // clang::IdentifierInfo *
- var_type.GetQualType(), // Variable clang::QualType
- nullptr, // TypeSourceInfo *
- clang::SC_Static); // StorageClass
- if (var_decl)
- {
- var_decl->setAccess(ClangASTContext::ConvertAccessTypeToAccessSpecifier (access));
- record_decl->addDecl(var_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(var_decl);
-#endif
- }
- }
- return var_decl;
-}
-
-
-clang::CXXMethodDecl *
-ClangASTType::AddMethodToCXXRecordType (const char *name,
- const ClangASTType &method_clang_type,
- lldb::AccessType access,
- bool is_virtual,
- bool is_static,
- bool is_inline,
- bool is_explicit,
- bool is_attr_used,
- bool is_artificial)
-{
- if (!IsValid() || !method_clang_type.IsValid() || name == nullptr || name[0] == '\0')
- return nullptr;
-
- clang::QualType record_qual_type(GetCanonicalQualType());
-
- clang::CXXRecordDecl *cxx_record_decl = record_qual_type->getAsCXXRecordDecl();
-
- if (cxx_record_decl == nullptr)
- return nullptr;
-
- clang::QualType method_qual_type (method_clang_type.GetQualType());
-
- clang::CXXMethodDecl *cxx_method_decl = nullptr;
-
- clang::DeclarationName decl_name (&m_ast->Idents.get(name));
-
- const clang::FunctionType *function_type = llvm::dyn_cast<clang::FunctionType>(method_qual_type.getTypePtr());
-
- if (function_type == nullptr)
- return nullptr;
-
- const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast<clang::FunctionProtoType>(function_type));
-
- if (!method_function_prototype)
- return nullptr;
-
- unsigned int num_params = method_function_prototype->getNumParams();
-
- clang::CXXDestructorDecl *cxx_dtor_decl(nullptr);
- clang::CXXConstructorDecl *cxx_ctor_decl(nullptr);
-
- if (is_artificial)
- return nullptr; // skip everything artificial
-
- if (name[0] == '~')
- {
- cxx_dtor_decl = clang::CXXDestructorDecl::Create (*m_ast,
- cxx_record_decl,
- clang::SourceLocation(),
- clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXDestructorName (m_ast->getCanonicalType (record_qual_type)), clang::SourceLocation()),
- method_qual_type,
- nullptr,
- is_inline,
- is_artificial);
- cxx_method_decl = cxx_dtor_decl;
- }
- else if (decl_name == cxx_record_decl->getDeclName())
- {
- cxx_ctor_decl = clang::CXXConstructorDecl::Create (*m_ast,
- cxx_record_decl,
- clang::SourceLocation(),
- clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXConstructorName (m_ast->getCanonicalType (record_qual_type)), clang::SourceLocation()),
- method_qual_type,
- nullptr, // TypeSourceInfo *
- is_explicit,
- is_inline,
- is_artificial,
- false /*is_constexpr*/);
- cxx_method_decl = cxx_ctor_decl;
- }
- else
- {
- clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None;
- clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
-
- if (IsOperator (name, op_kind))
- {
- if (op_kind != clang::NUM_OVERLOADED_OPERATORS)
- {
- // Check the number of operator parameters. Sometimes we have
- // seen bad DWARF that doesn't correctly describe operators and
- // if we try to create a method and add it to the class, clang
- // will assert and crash, so we need to make sure things are
- // acceptable.
- if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount (op_kind, num_params))
- return nullptr;
- cxx_method_decl = clang::CXXMethodDecl::Create (*m_ast,
- cxx_record_decl,
- clang::SourceLocation(),
- clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXOperatorName (op_kind), clang::SourceLocation()),
- method_qual_type,
- nullptr, // TypeSourceInfo *
- SC,
- is_inline,
- false /*is_constexpr*/,
- clang::SourceLocation());
- }
- else if (num_params == 0)
- {
- // Conversion operators don't take params...
- cxx_method_decl = clang::CXXConversionDecl::Create (*m_ast,
- cxx_record_decl,
- clang::SourceLocation(),
- clang::DeclarationNameInfo (m_ast->DeclarationNames.getCXXConversionFunctionName (m_ast->getCanonicalType (function_type->getReturnType())), clang::SourceLocation()),
- method_qual_type,
- nullptr, // TypeSourceInfo *
- is_inline,
- is_explicit,
- false /*is_constexpr*/,
- clang::SourceLocation());
- }
- }
-
- if (cxx_method_decl == nullptr)
- {
- cxx_method_decl = clang::CXXMethodDecl::Create (*m_ast,
- cxx_record_decl,
- clang::SourceLocation(),
- clang::DeclarationNameInfo (decl_name, clang::SourceLocation()),
- method_qual_type,
- nullptr, // TypeSourceInfo *
- SC,
- is_inline,
- false /*is_constexpr*/,
- clang::SourceLocation());
- }
- }
-
- clang::AccessSpecifier access_specifier = ClangASTContext::ConvertAccessTypeToAccessSpecifier (access);
-
- cxx_method_decl->setAccess (access_specifier);
- cxx_method_decl->setVirtualAsWritten (is_virtual);
-
- if (is_attr_used)
- cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(*m_ast));
-
- // Populate the method decl with parameter decls
-
- llvm::SmallVector<clang::ParmVarDecl *, 12> params;
-
- for (unsigned param_index = 0;
- param_index < num_params;
- ++param_index)
- {
- params.push_back (clang::ParmVarDecl::Create (*m_ast,
- cxx_method_decl,
- clang::SourceLocation(),
- clang::SourceLocation(),
- nullptr, // anonymous
- method_function_prototype->getParamType(param_index),
- nullptr,
- clang::SC_None,
- nullptr));
- }
-
- cxx_method_decl->setParams (llvm::ArrayRef<clang::ParmVarDecl*>(params));
-
- cxx_record_decl->addDecl (cxx_method_decl);
-
- // Sometimes the debug info will mention a constructor (default/copy/move),
- // destructor, or assignment operator (copy/move) but there won't be any
- // version of this in the code. So we check if the function was artificially
- // generated and if it is trivial and this lets the compiler/backend know
- // that it can inline the IR for these when it needs to and we can avoid a
- // "missing function" error when running expressions.
-
- if (is_artificial)
- {
- if (cxx_ctor_decl &&
- ((cxx_ctor_decl->isDefaultConstructor() && cxx_record_decl->hasTrivialDefaultConstructor ()) ||
- (cxx_ctor_decl->isCopyConstructor() && cxx_record_decl->hasTrivialCopyConstructor ()) ||
- (cxx_ctor_decl->isMoveConstructor() && cxx_record_decl->hasTrivialMoveConstructor ()) ))
- {
- cxx_ctor_decl->setDefaulted();
- cxx_ctor_decl->setTrivial(true);
- }
- else if (cxx_dtor_decl)
- {
- if (cxx_record_decl->hasTrivialDestructor())
- {
- cxx_dtor_decl->setDefaulted();
- cxx_dtor_decl->setTrivial(true);
- }
- }
- else if ((cxx_method_decl->isCopyAssignmentOperator() && cxx_record_decl->hasTrivialCopyAssignment()) ||
- (cxx_method_decl->isMoveAssignmentOperator() && cxx_record_decl->hasTrivialMoveAssignment()))
- {
- cxx_method_decl->setDefaulted();
- cxx_method_decl->setTrivial(true);
- }
- }
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(cxx_method_decl);
-#endif
-
- // printf ("decl->isPolymorphic() = %i\n", cxx_record_decl->isPolymorphic());
- // printf ("decl->isAggregate() = %i\n", cxx_record_decl->isAggregate());
- // printf ("decl->isPOD() = %i\n", cxx_record_decl->isPOD());
- // printf ("decl->isEmpty() = %i\n", cxx_record_decl->isEmpty());
- // printf ("decl->isAbstract() = %i\n", cxx_record_decl->isAbstract());
- // printf ("decl->hasTrivialConstructor() = %i\n", cxx_record_decl->hasTrivialConstructor());
- // printf ("decl->hasTrivialCopyConstructor() = %i\n", cxx_record_decl->hasTrivialCopyConstructor());
- // printf ("decl->hasTrivialCopyAssignment() = %i\n", cxx_record_decl->hasTrivialCopyAssignment());
- // printf ("decl->hasTrivialDestructor() = %i\n", cxx_record_decl->hasTrivialDestructor());
- return cxx_method_decl;
-}
-
-
-#pragma mark C++ Base Classes
-
-clang::CXXBaseSpecifier *
-ClangASTType::CreateBaseClassSpecifier (AccessType access, bool is_virtual, bool base_of_class)
-{
- if (IsValid())
- return new clang::CXXBaseSpecifier (clang::SourceRange(),
- is_virtual,
- base_of_class,
- ClangASTContext::ConvertAccessTypeToAccessSpecifier (access),
- m_ast->getTrivialTypeSourceInfo (GetQualType()),
- clang::SourceLocation());
- return nullptr;
-}
-
-void
-ClangASTType::DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes, unsigned num_base_classes)
-{
- for (unsigned i=0; i<num_base_classes; ++i)
- {
- delete base_classes[i];
- base_classes[i] = nullptr;
- }
-}
-
-bool
-ClangASTType::SetBaseClassesForClassType (clang::CXXBaseSpecifier const * const *base_classes,
- unsigned num_base_classes)
-{
- if (IsValid())
- {
- clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl();
- if (cxx_record_decl)
- {
- cxx_record_decl->setBases(base_classes, num_base_classes);
- return true;
- }
- }
- return false;
-}
-
-bool
-ClangASTType::SetObjCSuperClass (const ClangASTType &superclass_clang_type)
-{
- if (IsValid() && superclass_clang_type.IsValid())
- {
- clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
- clang::ObjCInterfaceDecl *super_interface_decl = superclass_clang_type.GetAsObjCInterfaceDecl ();
- if (class_interface_decl && super_interface_decl)
- {
-
- class_interface_decl->setSuperClass(
- m_ast->getTrivialTypeSourceInfo(m_ast->getObjCInterfaceType(super_interface_decl)));
- return true;
- }
- }
- return false;
-}
-
-bool
-ClangASTType::AddObjCClassProperty (const char *property_name,
- const ClangASTType &property_clang_type,
- clang::ObjCIvarDecl *ivar_decl,
- const char *property_setter_name,
- const char *property_getter_name,
- uint32_t property_attributes,
- ClangASTMetadata *metadata)
-{
- if (!IsValid() || !property_clang_type.IsValid() || property_name == nullptr || property_name[0] == '\0')
- return false;
-
- clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
-
- if (class_interface_decl)
- {
- ClangASTType property_clang_type_to_access;
-
- if (property_clang_type.IsValid())
- property_clang_type_to_access = property_clang_type;
- else if (ivar_decl)
- property_clang_type_to_access = ClangASTType (m_ast, ivar_decl->getType());
-
- if (class_interface_decl && property_clang_type_to_access.IsValid())
- {
- clang::TypeSourceInfo *prop_type_source;
- if (ivar_decl)
- prop_type_source = m_ast->getTrivialTypeSourceInfo (ivar_decl->getType());
- else
- prop_type_source = m_ast->getTrivialTypeSourceInfo (property_clang_type.GetQualType());
-
- clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create (*m_ast,
- class_interface_decl,
- clang::SourceLocation(), // Source Location
- &m_ast->Idents.get(property_name),
- clang::SourceLocation(), //Source Location for AT
- clang::SourceLocation(), //Source location for (
- ivar_decl ? ivar_decl->getType() : property_clang_type.GetQualType(),
- prop_type_source);
-
- if (property_decl)
- {
- if (metadata)
- ClangASTContext::SetMetadata(m_ast, property_decl, *metadata);
-
- class_interface_decl->addDecl (property_decl);
-
- clang::Selector setter_sel, getter_sel;
-
- if (property_setter_name != nullptr)
- {
- std::string property_setter_no_colon(property_setter_name, strlen(property_setter_name) - 1);
- clang::IdentifierInfo *setter_ident = &m_ast->Idents.get(property_setter_no_colon.c_str());
- setter_sel = m_ast->Selectors.getSelector(1, &setter_ident);
- }
- else if (!(property_attributes & DW_APPLE_PROPERTY_readonly))
- {
- std::string setter_sel_string("set");
- setter_sel_string.push_back(::toupper(property_name[0]));
- setter_sel_string.append(&property_name[1]);
- clang::IdentifierInfo *setter_ident = &m_ast->Idents.get(setter_sel_string.c_str());
- setter_sel = m_ast->Selectors.getSelector(1, &setter_ident);
- }
- property_decl->setSetterName(setter_sel);
- property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_setter);
-
- if (property_getter_name != nullptr)
- {
- clang::IdentifierInfo *getter_ident = &m_ast->Idents.get(property_getter_name);
- getter_sel = m_ast->Selectors.getSelector(0, &getter_ident);
- }
- else
- {
- clang::IdentifierInfo *getter_ident = &m_ast->Idents.get(property_name);
- getter_sel = m_ast->Selectors.getSelector(0, &getter_ident);
- }
- property_decl->setGetterName(getter_sel);
- property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_getter);
-
- if (ivar_decl)
- property_decl->setPropertyIvarDecl (ivar_decl);
-
- if (property_attributes & DW_APPLE_PROPERTY_readonly)
- property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readonly);
- if (property_attributes & DW_APPLE_PROPERTY_readwrite)
- property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readwrite);
- if (property_attributes & DW_APPLE_PROPERTY_assign)
- property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_assign);
- if (property_attributes & DW_APPLE_PROPERTY_retain)
- property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_retain);
- if (property_attributes & DW_APPLE_PROPERTY_copy)
- property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_copy);
- if (property_attributes & DW_APPLE_PROPERTY_nonatomic)
- property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_nonatomic);
-
- if (!getter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(getter_sel))
- {
- const bool isInstance = true;
- const bool isVariadic = false;
- const bool isSynthesized = false;
- const bool isImplicitlyDeclared = true;
- const bool isDefined = false;
- const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None;
- const bool HasRelatedResultType = false;
-
- clang::ObjCMethodDecl *getter = clang::ObjCMethodDecl::Create (*m_ast,
- clang::SourceLocation(),
- clang::SourceLocation(),
- getter_sel,
- property_clang_type_to_access.GetQualType(),
- nullptr,
- class_interface_decl,
- isInstance,
- isVariadic,
- isSynthesized,
- isImplicitlyDeclared,
- isDefined,
- impControl,
- HasRelatedResultType);
-
- if (getter && metadata)
- ClangASTContext::SetMetadata(m_ast, getter, *metadata);
-
- if (getter)
- {
- getter->setMethodParams(*m_ast, llvm::ArrayRef<clang::ParmVarDecl*>(), llvm::ArrayRef<clang::SourceLocation>());
-
- class_interface_decl->addDecl(getter);
- }
- }
-
- if (!setter_sel.isNull() && !class_interface_decl->lookupInstanceMethod(setter_sel))
- {
- clang::QualType result_type = m_ast->VoidTy;
-
- const bool isInstance = true;
- const bool isVariadic = false;
- const bool isSynthesized = false;
- const bool isImplicitlyDeclared = true;
- const bool isDefined = false;
- const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None;
- const bool HasRelatedResultType = false;
-
- clang::ObjCMethodDecl *setter = clang::ObjCMethodDecl::Create (*m_ast,
- clang::SourceLocation(),
- clang::SourceLocation(),
- setter_sel,
- result_type,
- nullptr,
- class_interface_decl,
- isInstance,
- isVariadic,
- isSynthesized,
- isImplicitlyDeclared,
- isDefined,
- impControl,
- HasRelatedResultType);
-
- if (setter && metadata)
- ClangASTContext::SetMetadata(m_ast, setter, *metadata);
-
- llvm::SmallVector<clang::ParmVarDecl *, 1> params;
-
- params.push_back (clang::ParmVarDecl::Create (*m_ast,
- setter,
- clang::SourceLocation(),
- clang::SourceLocation(),
- nullptr, // anonymous
- property_clang_type_to_access.GetQualType(),
- nullptr,
- clang::SC_Auto,
- nullptr));
-
- if (setter)
- {
- setter->setMethodParams(*m_ast, llvm::ArrayRef<clang::ParmVarDecl*>(params), llvm::ArrayRef<clang::SourceLocation>());
-
- class_interface_decl->addDecl(setter);
- }
- }
-
- return true;
- }
- }
- }
- return false;
-}
-
-bool
-ClangASTType::IsObjCClassTypeAndHasIVars (bool check_superclass) const
-{
- clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl ();
- if (class_interface_decl)
- return ObjCDeclHasIVars (class_interface_decl, check_superclass);
- return false;
-}
-
-
-clang::ObjCMethodDecl *
-ClangASTType::AddMethodToObjCObjectType (const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]")
- const ClangASTType &method_clang_type,
- lldb::AccessType access,
- bool is_artificial)
-{
- if (!IsValid() || !method_clang_type.IsValid())
- return nullptr;
-
- clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl();
-
- if (class_interface_decl == nullptr)
- return nullptr;
-
- const char *selector_start = ::strchr (name, ' ');
- if (selector_start == nullptr)
- return nullptr;
-
- selector_start++;
- llvm::SmallVector<clang::IdentifierInfo *, 12> selector_idents;
-
- size_t len = 0;
- const char *start;
- //printf ("name = '%s'\n", name);
-
- unsigned num_selectors_with_args = 0;
- for (start = selector_start;
- start && *start != '\0' && *start != ']';
- start += len)
- {
- len = ::strcspn(start, ":]");
- bool has_arg = (start[len] == ':');
- if (has_arg)
- ++num_selectors_with_args;
- selector_idents.push_back (&m_ast->Idents.get (llvm::StringRef (start, len)));
- if (has_arg)
- len += 1;
- }
-
-
- if (selector_idents.size() == 0)
- return nullptr;
-
- clang::Selector method_selector = m_ast->Selectors.getSelector (num_selectors_with_args ? selector_idents.size() : 0,
- selector_idents.data());
-
- clang::QualType method_qual_type (method_clang_type.GetQualType());
-
- // Populate the method decl with parameter decls
- const clang::Type *method_type(method_qual_type.getTypePtr());
-
- if (method_type == nullptr)
- return nullptr;
-
- const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast<clang::FunctionProtoType>(method_type));
-
- if (!method_function_prototype)
- return nullptr;
-
-
- bool is_variadic = false;
- bool is_synthesized = false;
- bool is_defined = false;
- clang::ObjCMethodDecl::ImplementationControl imp_control = clang::ObjCMethodDecl::None;
-
- const unsigned num_args = method_function_prototype->getNumParams();
-
- if (num_args != num_selectors_with_args)
- return nullptr; // some debug information is corrupt. We are not going to deal with it.
-
- clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create (*m_ast,
- clang::SourceLocation(), // beginLoc,
- clang::SourceLocation(), // endLoc,
- method_selector,
- method_function_prototype->getReturnType(),
- nullptr, // TypeSourceInfo *ResultTInfo,
- GetDeclContextForType (),
- name[0] == '-',
- is_variadic,
- is_synthesized,
- true, // is_implicitly_declared; we force this to true because we don't have source locations
- is_defined,
- imp_control,
- false /*has_related_result_type*/);
-
-
- if (objc_method_decl == nullptr)
- return nullptr;
-
- if (num_args > 0)
- {
- llvm::SmallVector<clang::ParmVarDecl *, 12> params;
-
- for (unsigned param_index = 0; param_index < num_args; ++param_index)
- {
- params.push_back (clang::ParmVarDecl::Create (*m_ast,
- objc_method_decl,
- clang::SourceLocation(),
- clang::SourceLocation(),
- nullptr, // anonymous
- method_function_prototype->getParamType(param_index),
- nullptr,
- clang::SC_Auto,
- nullptr));
- }
-
- objc_method_decl->setMethodParams(*m_ast, llvm::ArrayRef<clang::ParmVarDecl*>(params), llvm::ArrayRef<clang::SourceLocation>());
- }
-
- class_interface_decl->addDecl (objc_method_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(objc_method_decl);
-#endif
-
- return objc_method_decl;
-}
-
-
-clang::DeclContext *
-ClangASTType::GetDeclContextForType () const
-{
- if (!IsValid())
- return nullptr;
-
- clang::QualType qual_type(GetCanonicalQualType());
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::UnaryTransform: break;
- case clang::Type::FunctionNoProto: break;
- case clang::Type::FunctionProto: break;
- case clang::Type::IncompleteArray: break;
- case clang::Type::VariableArray: break;
- case clang::Type::ConstantArray: break;
- case clang::Type::DependentSizedArray: break;
- case clang::Type::ExtVector: break;
- case clang::Type::DependentSizedExtVector: break;
- case clang::Type::Vector: break;
- case clang::Type::Builtin: break;
- case clang::Type::BlockPointer: break;
- case clang::Type::Pointer: break;
- case clang::Type::LValueReference: break;
- case clang::Type::RValueReference: break;
- case clang::Type::MemberPointer: break;
- case clang::Type::Complex: break;
- case clang::Type::ObjCObject: break;
- case clang::Type::ObjCInterface: return llvm::cast<clang::ObjCObjectType>(qual_type.getTypePtr())->getInterface();
- case clang::Type::ObjCObjectPointer: return ClangASTType (m_ast, llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType()).GetDeclContextForType();
- case clang::Type::Record: return llvm::cast<clang::RecordType>(qual_type)->getDecl();
- case clang::Type::Enum: return llvm::cast<clang::EnumType>(qual_type)->getDecl();
- case clang::Type::Typedef: return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetDeclContextForType();
- case clang::Type::Elaborated: return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetDeclContextForType();
- case clang::Type::Paren: return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).GetDeclContextForType();
- case clang::Type::TypeOfExpr: break;
- case clang::Type::TypeOf: break;
- case clang::Type::Decltype: break;
- //case clang::Type::QualifiedName: break;
- case clang::Type::TemplateSpecialization: break;
- case clang::Type::DependentTemplateSpecialization: break;
- case clang::Type::TemplateTypeParm: break;
- case clang::Type::SubstTemplateTypeParm: break;
- case clang::Type::SubstTemplateTypeParmPack:break;
- case clang::Type::PackExpansion: break;
- case clang::Type::UnresolvedUsing: break;
- case clang::Type::Attributed: break;
- case clang::Type::Auto: break;
- case clang::Type::InjectedClassName: break;
- case clang::Type::DependentName: break;
- case clang::Type::Atomic: break;
- case clang::Type::Adjusted: break;
-
- // pointer type decayed from an array or function type.
- case clang::Type::Decayed: break;
- }
- // No DeclContext in this type...
- return nullptr;
-}
-
-bool
-ClangASTType::SetDefaultAccessForRecordFields (int default_accessibility,
- int *assigned_accessibilities,
- size_t num_assigned_accessibilities)
-{
- if (IsValid())
- {
- clang::RecordDecl *record_decl = GetAsRecordDecl();
- if (record_decl)
- {
- uint32_t field_idx;
- clang::RecordDecl::field_iterator field, field_end;
- for (field = record_decl->field_begin(), field_end = record_decl->field_end(), field_idx = 0;
- field != field_end;
- ++field, ++field_idx)
- {
- // If no accessibility was assigned, assign the correct one
- if (field_idx < num_assigned_accessibilities && assigned_accessibilities[field_idx] == clang::AS_none)
- field->setAccess ((clang::AccessSpecifier)default_accessibility);
- }
- return true;
- }
- }
- return false;
-}
-
-
-bool
-ClangASTType::SetHasExternalStorage (bool has_extern)
-{
- if (!IsValid())
- return false;
-
- clang::QualType qual_type (GetCanonicalQualType());
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Record:
- {
- clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
- if (cxx_record_decl)
- {
- cxx_record_decl->setHasExternalLexicalStorage (has_extern);
- cxx_record_decl->setHasExternalVisibleStorage (has_extern);
- return true;
- }
- }
- break;
-
- case clang::Type::Enum:
- {
- clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl();
- if (enum_decl)
- {
- enum_decl->setHasExternalLexicalStorage (has_extern);
- enum_decl->setHasExternalVisibleStorage (has_extern);
- return true;
- }
- }
- break;
-
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- {
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert (objc_class_type);
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
-
- if (class_interface_decl)
- {
- class_interface_decl->setHasExternalLexicalStorage (has_extern);
- class_interface_decl->setHasExternalVisibleStorage (has_extern);
- return true;
- }
- }
- }
- break;
-
- case clang::Type::Typedef:
- return ClangASTType (m_ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).SetHasExternalStorage (has_extern);
-
- case clang::Type::Elaborated:
- return ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).SetHasExternalStorage (has_extern);
-
- case clang::Type::Paren:
- return ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).SetHasExternalStorage (has_extern);
-
- default:
- break;
- }
- return false;
-}
-
-bool
-ClangASTType::SetTagTypeKind (int kind) const
-{
- if (IsValid())
- {
- clang::QualType tag_qual_type(GetQualType());
- const clang::Type *clang_type = tag_qual_type.getTypePtr();
- if (clang_type)
- {
- const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(clang_type);
- if (tag_type)
- {
- clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl());
- if (tag_decl)
- {
- tag_decl->setTagKind ((clang::TagDecl::TagKind)kind);
- return true;
- }
- }
- }
- }
- return false;
-}
-
-
-#pragma mark TagDecl
-
-bool
-ClangASTType::StartTagDeclarationDefinition ()
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetQualType());
- const clang::Type *t = qual_type.getTypePtr();
- if (t)
- {
- const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(t);
- if (tag_type)
- {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- if (tag_decl)
- {
- tag_decl->startDefinition();
- return true;
- }
- }
-
- const clang::ObjCObjectType *object_type = llvm::dyn_cast<clang::ObjCObjectType>(t);
- if (object_type)
- {
- clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface();
- if (interface_decl)
- {
- interface_decl->startDefinition();
- return true;
- }
- }
- }
- }
- return false;
-}
-
-bool
-ClangASTType::CompleteTagDeclarationDefinition ()
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetQualType());
-
- clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
-
- if (cxx_record_decl)
- {
- cxx_record_decl->completeDefinition();
-
- return true;
- }
-
- const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(qual_type.getTypePtr());
-
- if (enum_type)
- {
- clang::EnumDecl *enum_decl = enum_type->getDecl();
-
- if (enum_decl)
- {
- /// TODO This really needs to be fixed.
-
- unsigned NumPositiveBits = 1;
- unsigned NumNegativeBits = 0;
-
- clang::QualType promotion_qual_type;
- // If the enum integer type is less than an integer in bit width,
- // then we must promote it to an integer size.
- if (m_ast->getTypeSize(enum_decl->getIntegerType()) < m_ast->getTypeSize(m_ast->IntTy))
- {
- if (enum_decl->getIntegerType()->isSignedIntegerType())
- promotion_qual_type = m_ast->IntTy;
- else
- promotion_qual_type = m_ast->UnsignedIntTy;
- }
- else
- promotion_qual_type = enum_decl->getIntegerType();
-
- enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits);
- return true;
- }
- }
- }
- return false;
-}
-
-
-
-
-
-
-
-bool
-ClangASTType::AddEnumerationValueToEnumerationType (const ClangASTType &enumerator_clang_type,
- const Declaration &decl,
- const char *name,
- int64_t enum_value,
- uint32_t enum_value_bit_size)
-{
- if (IsValid() && enumerator_clang_type.IsValid() && name && name[0])
- {
- clang::QualType enum_qual_type (GetCanonicalQualType());
-
- bool is_signed = false;
- enumerator_clang_type.IsIntegerType (is_signed);
- const clang::Type *clang_type = enum_qual_type.getTypePtr();
- if (clang_type)
- {
- const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(clang_type);
-
- if (enum_type)
- {
- llvm::APSInt enum_llvm_apsint(enum_value_bit_size, is_signed);
- enum_llvm_apsint = enum_value;
- clang::EnumConstantDecl *enumerator_decl =
- clang::EnumConstantDecl::Create (*m_ast,
- enum_type->getDecl(),
- clang::SourceLocation(),
- name ? &m_ast->Idents.get(name) : nullptr, // Identifier
- enumerator_clang_type.GetQualType(),
- nullptr,
- enum_llvm_apsint);
-
- if (enumerator_decl)
- {
- enum_type->getDecl()->addDecl(enumerator_decl);
-
-#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(enumerator_decl);
-#endif
-
- return true;
- }
- }
- }
- }
- return false;
-}
-
-
-ClangASTType
-ClangASTType::GetEnumerationIntegerType () const
-{
- clang::QualType enum_qual_type (GetCanonicalQualType());
- const clang::Type *clang_type = enum_qual_type.getTypePtr();
- if (clang_type)
- {
- const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(clang_type);
- if (enum_type)
- {
- clang::EnumDecl *enum_decl = enum_type->getDecl();
- if (enum_decl)
- return ClangASTType (m_ast, enum_decl->getIntegerType());
- }
- }
- return ClangASTType();
-}
-
-ClangASTType
-ClangASTType::CreateMemberPointerType (const ClangASTType &pointee_type) const
-{
- if (IsValid() && pointee_type.IsValid())
- {
- return ClangASTType (m_ast, m_ast->getMemberPointerType (pointee_type.GetQualType(),
- GetQualType().getTypePtr()));
- }
- return ClangASTType();
-}
-
-
-size_t
-ClangASTType::ConvertStringToFloatValue (const char *s, uint8_t *dst, size_t dst_size) const
-{
- if (IsValid())
- {
- clang::QualType qual_type (GetCanonicalQualType());
- uint32_t count = 0;
- bool is_complex = false;
- if (IsFloatingPointType (count, is_complex))
- {
- // TODO: handle complex and vector types
- if (count != 1)
- return false;
-
- llvm::StringRef s_sref(s);
- llvm::APFloat ap_float(m_ast->getFloatTypeSemantics(qual_type), s_sref);
-
- const uint64_t bit_size = m_ast->getTypeSize (qual_type);
- const uint64_t byte_size = bit_size / 8;
- if (dst_size >= byte_size)
- {
- if (bit_size == sizeof(float)*8)
- {
- float float32 = ap_float.convertToFloat();
- ::memcpy (dst, &float32, byte_size);
- return byte_size;
- }
- else if (bit_size >= 64)
- {
- llvm::APInt ap_int(ap_float.bitcastToAPInt());
- ::memcpy (dst, ap_int.getRawData(), byte_size);
- return byte_size;
- }
- }
- }
- }
- return 0;
-}
-
-
-
-//----------------------------------------------------------------------
-// Dumping types
-//----------------------------------------------------------------------
-#define DEPTH_INCREMENT 2
-
-void
-ClangASTType::DumpValue (ExecutionContext *exe_ctx,
- Stream *s,
- lldb::Format format,
- const lldb_private::DataExtractor &data,
- lldb::offset_t data_byte_offset,
- size_t data_byte_size,
- uint32_t bitfield_bit_size,
- uint32_t bitfield_bit_offset,
- bool show_types,
- bool show_summary,
- bool verbose,
- uint32_t depth)
-{
- if (!IsValid())
- return;
-
- clang::QualType qual_type(GetQualType());
- switch (qual_type->getTypeClass())
- {
- case clang::Type::Record:
- if (GetCompleteType ())
- {
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- assert(record_decl);
- uint32_t field_bit_offset = 0;
- uint32_t field_byte_offset = 0;
- const clang::ASTRecordLayout &record_layout = m_ast->getASTRecordLayout(record_decl);
- uint32_t child_idx = 0;
-
- const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
- if (cxx_record_decl)
- {
- // We might have base classes to print out first
- clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
- for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
- base_class != base_class_end;
- ++base_class)
- {
- const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl());
-
- // Skip empty base classes
- if (verbose == false && ClangASTContext::RecordHasFields(base_class_decl) == false)
- continue;
-
- if (base_class->isVirtual())
- field_bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
- else
- field_bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8;
- field_byte_offset = field_bit_offset / 8;
- assert (field_bit_offset % 8 == 0);
- if (child_idx == 0)
- s->PutChar('{');
- else
- s->PutChar(',');
-
- clang::QualType base_class_qual_type = base_class->getType();
- std::string base_class_type_name(base_class_qual_type.getAsString());
-
- // Indent and print the base class type name
- s->Printf("\n%*s%s ", depth + DEPTH_INCREMENT, "", base_class_type_name.c_str());
-
- clang::TypeInfo base_class_type_info = m_ast->getTypeInfo(base_class_qual_type);
-
- // Dump the value of the member
- ClangASTType base_clang_type(m_ast, base_class_qual_type);
- base_clang_type.DumpValue (exe_ctx,
- s, // Stream to dump to
- base_clang_type.GetFormat(), // The format with which to display the member
- data, // Data buffer containing all bytes for this type
- data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from
- base_class_type_info.Width / 8, // Size of this type in bytes
- 0, // Bitfield bit size
- 0, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable types
- show_summary, // Boolean indicating if we should show a summary for the current type
- verbose, // Verbose output?
- depth + DEPTH_INCREMENT); // Scope depth for any types that have children
-
- ++child_idx;
- }
- }
- uint32_t field_idx = 0;
- clang::RecordDecl::field_iterator field, field_end;
- for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx)
- {
- // Print the starting squiggly bracket (if this is the
- // first member) or comma (for member 2 and beyond) for
- // the struct/union/class member.
- if (child_idx == 0)
- s->PutChar('{');
- else
- s->PutChar(',');
-
- // Indent
- s->Printf("\n%*s", depth + DEPTH_INCREMENT, "");
-
- clang::QualType field_type = field->getType();
- // Print the member type if requested
- // Figure out the type byte size (field_type_info.first) and
- // alignment (field_type_info.second) from the AST context.
- clang::TypeInfo field_type_info = m_ast->getTypeInfo(field_type);
- assert(field_idx < record_layout.getFieldCount());
- // Figure out the field offset within the current struct/union/class type
- field_bit_offset = record_layout.getFieldOffset (field_idx);
- field_byte_offset = field_bit_offset / 8;
- uint32_t field_bitfield_bit_size = 0;
- uint32_t field_bitfield_bit_offset = 0;
- if (ClangASTContext::FieldIsBitfield (m_ast, *field, field_bitfield_bit_size))
- field_bitfield_bit_offset = field_bit_offset % 8;
-
- if (show_types)
- {
- std::string field_type_name(field_type.getAsString());
- if (field_bitfield_bit_size > 0)
- s->Printf("(%s:%u) ", field_type_name.c_str(), field_bitfield_bit_size);
- else
- s->Printf("(%s) ", field_type_name.c_str());
- }
- // Print the member name and equal sign
- s->Printf("%s = ", field->getNameAsString().c_str());
-
-
- // Dump the value of the member
- ClangASTType field_clang_type (m_ast, field_type);
- field_clang_type.DumpValue (exe_ctx,
- s, // Stream to dump to
- field_clang_type.GetFormat(), // The format with which to display the member
- data, // Data buffer containing all bytes for this type
- data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from
- field_type_info.Width / 8, // Size of this type in bytes
- field_bitfield_bit_size, // Bitfield bit size
- field_bitfield_bit_offset, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable types
- show_summary, // Boolean indicating if we should show a summary for the current type
- verbose, // Verbose output?
- depth + DEPTH_INCREMENT); // Scope depth for any types that have children
- }
-
- // Indent the trailing squiggly bracket
- if (child_idx > 0)
- s->Printf("\n%*s}", depth, "");
- }
- return;
-
- case clang::Type::Enum:
- if (GetCompleteType ())
- {
- const clang::EnumType *enum_type = llvm::cast<clang::EnumType>(qual_type.getTypePtr());
- const clang::EnumDecl *enum_decl = enum_type->getDecl();
- assert(enum_decl);
- clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
- lldb::offset_t offset = data_byte_offset;
- const int64_t enum_value = data.GetMaxU64Bitfield(&offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset);
- for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
- {
- if (enum_pos->getInitVal() == enum_value)
- {
- s->Printf("%s", enum_pos->getNameAsString().c_str());
- return;
- }
- }
- // If we have gotten here we didn't get find the enumerator in the
- // enum decl, so just print the integer.
- s->Printf("%" PRIi64, enum_value);
- }
- return;
-
- case clang::Type::ConstantArray:
- {
- const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr());
- bool is_array_of_characters = false;
- clang::QualType element_qual_type = array->getElementType();
-
- const clang::Type *canonical_type = element_qual_type->getCanonicalTypeInternal().getTypePtr();
- if (canonical_type)
- is_array_of_characters = canonical_type->isCharType();
-
- const uint64_t element_count = array->getSize().getLimitedValue();
-
- clang::TypeInfo field_type_info = m_ast->getTypeInfo(element_qual_type);
-
- uint32_t element_idx = 0;
- uint32_t element_offset = 0;
- uint64_t element_byte_size = field_type_info.Width / 8;
- uint32_t element_stride = element_byte_size;
-
- if (is_array_of_characters)
- {
- s->PutChar('"');
- data.Dump(s, data_byte_offset, lldb::eFormatChar, element_byte_size, element_count, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
- s->PutChar('"');
- return;
- }
- else
- {
- ClangASTType element_clang_type(m_ast, element_qual_type);
- lldb::Format element_format = element_clang_type.GetFormat();
-
- for (element_idx = 0; element_idx < element_count; ++element_idx)
- {
- // Print the starting squiggly bracket (if this is the
- // first member) or comma (for member 2 and beyond) for
- // the struct/union/class member.
- if (element_idx == 0)
- s->PutChar('{');
- else
- s->PutChar(',');
-
- // Indent and print the index
- s->Printf("\n%*s[%u] ", depth + DEPTH_INCREMENT, "", element_idx);
-
- // Figure out the field offset within the current struct/union/class type
- element_offset = element_idx * element_stride;
-
- // Dump the value of the member
- element_clang_type.DumpValue (exe_ctx,
- s, // Stream to dump to
- element_format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- data_byte_offset + element_offset,// Offset into "data" where to grab value from
- element_byte_size, // Size of this type in bytes
- 0, // Bitfield bit size
- 0, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable types
- show_summary, // Boolean indicating if we should show a summary for the current type
- verbose, // Verbose output?
- depth + DEPTH_INCREMENT); // Scope depth for any types that have children
- }
-
- // Indent the trailing squiggly bracket
- if (element_idx > 0)
- s->Printf("\n%*s}", depth, "");
- }
- }
- return;
-
- case clang::Type::Typedef:
- {
- clang::QualType typedef_qual_type = llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType();
-
- ClangASTType typedef_clang_type (m_ast, typedef_qual_type);
- lldb::Format typedef_format = typedef_clang_type.GetFormat();
- clang::TypeInfo typedef_type_info = m_ast->getTypeInfo(typedef_qual_type);
- uint64_t typedef_byte_size = typedef_type_info.Width / 8;
-
- return typedef_clang_type.DumpValue (exe_ctx,
- s, // Stream to dump to
- typedef_format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- data_byte_offset, // Offset into "data" where to grab value from
- typedef_byte_size, // Size of this type in bytes
- bitfield_bit_size, // Bitfield bit size
- bitfield_bit_offset,// Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable types
- show_summary, // Boolean indicating if we should show a summary for the current type
- verbose, // Verbose output?
- depth); // Scope depth for any types that have children
- }
- break;
-
- case clang::Type::Elaborated:
- {
- clang::QualType elaborated_qual_type = llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType();
- ClangASTType elaborated_clang_type (m_ast, elaborated_qual_type);
- lldb::Format elaborated_format = elaborated_clang_type.GetFormat();
- clang::TypeInfo elaborated_type_info = m_ast->getTypeInfo(elaborated_qual_type);
- uint64_t elaborated_byte_size = elaborated_type_info.Width / 8;
-
- return elaborated_clang_type.DumpValue (exe_ctx,
- s, // Stream to dump to
- elaborated_format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- data_byte_offset, // Offset into "data" where to grab value from
- elaborated_byte_size, // Size of this type in bytes
- bitfield_bit_size, // Bitfield bit size
- bitfield_bit_offset,// Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable types
- show_summary, // Boolean indicating if we should show a summary for the current type
- verbose, // Verbose output?
- depth); // Scope depth for any types that have children
- }
- break;
-
- case clang::Type::Paren:
- {
- clang::QualType desugar_qual_type = llvm::cast<clang::ParenType>(qual_type)->desugar();
- ClangASTType desugar_clang_type (m_ast, desugar_qual_type);
-
- lldb::Format desugar_format = desugar_clang_type.GetFormat();
- clang::TypeInfo desugar_type_info = m_ast->getTypeInfo(desugar_qual_type);
- uint64_t desugar_byte_size = desugar_type_info.Width / 8;
-
- return desugar_clang_type.DumpValue (exe_ctx,
- s, // Stream to dump to
- desugar_format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- data_byte_offset, // Offset into "data" where to grab value from
- desugar_byte_size, // Size of this type in bytes
- bitfield_bit_size, // Bitfield bit size
- bitfield_bit_offset,// Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable types
- show_summary, // Boolean indicating if we should show a summary for the current type
- verbose, // Verbose output?
- depth); // Scope depth for any types that have children
- }
- break;
-
- default:
- // We are down to a scalar type that we just need to display.
- data.Dump(s,
- data_byte_offset,
- format,
- data_byte_size,
- 1,
- UINT32_MAX,
- LLDB_INVALID_ADDRESS,
- bitfield_bit_size,
- bitfield_bit_offset);
-
- if (show_summary)
- DumpSummary (exe_ctx, s, data, data_byte_offset, data_byte_size);
- break;
- }
-}
-
-
-
-
-bool
-ClangASTType::DumpTypeValue (Stream *s,
- lldb::Format format,
- const lldb_private::DataExtractor &data,
- lldb::offset_t byte_offset,
- size_t byte_size,
- uint32_t bitfield_bit_size,
- uint32_t bitfield_bit_offset,
- ExecutionContextScope *exe_scope)
-{
- if (!IsValid())
- return false;
- if (IsAggregateType())
- {
- return false;
- }
- else
- {
- clang::QualType qual_type(GetQualType());
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::Typedef:
- {
- clang::QualType typedef_qual_type = llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType();
- ClangASTType typedef_clang_type (m_ast, typedef_qual_type);
- if (format == eFormatDefault)
- format = typedef_clang_type.GetFormat();
- clang::TypeInfo typedef_type_info = m_ast->getTypeInfo(typedef_qual_type);
- uint64_t typedef_byte_size = typedef_type_info.Width / 8;
-
- return typedef_clang_type.DumpTypeValue (s,
- format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- byte_offset, // Offset into "data" where to grab value from
- typedef_byte_size, // Size of this type in bytes
- bitfield_bit_size, // Size in bits of a bitfield value, if zero don't treat as a bitfield
- bitfield_bit_offset, // Offset in bits of a bitfield value if bitfield_bit_size != 0
- exe_scope);
- }
- break;
-
- case clang::Type::Enum:
- // If our format is enum or default, show the enumeration value as
- // its enumeration string value, else just display it as requested.
- if ((format == eFormatEnum || format == eFormatDefault) && GetCompleteType ())
- {
- const clang::EnumType *enum_type = llvm::cast<clang::EnumType>(qual_type.getTypePtr());
- const clang::EnumDecl *enum_decl = enum_type->getDecl();
- assert(enum_decl);
- clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos;
- const bool is_signed = qual_type->isSignedIntegerOrEnumerationType();
- lldb::offset_t offset = byte_offset;
- if (is_signed)
- {
- const int64_t enum_svalue = data.GetMaxS64Bitfield (&offset, byte_size, bitfield_bit_size, bitfield_bit_offset);
- for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
- {
- if (enum_pos->getInitVal().getSExtValue() == enum_svalue)
- {
- s->PutCString (enum_pos->getNameAsString().c_str());
- return true;
- }
- }
- // If we have gotten here we didn't get find the enumerator in the
- // enum decl, so just print the integer.
- s->Printf("%" PRIi64, enum_svalue);
- }
- else
- {
- const uint64_t enum_uvalue = data.GetMaxU64Bitfield (&offset, byte_size, bitfield_bit_size, bitfield_bit_offset);
- for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos)
- {
- if (enum_pos->getInitVal().getZExtValue() == enum_uvalue)
- {
- s->PutCString (enum_pos->getNameAsString().c_str());
- return true;
- }
- }
- // If we have gotten here we didn't get find the enumerator in the
- // enum decl, so just print the integer.
- s->Printf("%" PRIu64, enum_uvalue);
- }
- return true;
- }
- // format was not enum, just fall through and dump the value as requested....
-
- default:
- // We are down to a scalar type that we just need to display.
- {
- uint32_t item_count = 1;
- // A few formats, we might need to modify our size and count for depending
- // on how we are trying to display the value...
- switch (format)
- {
- default:
- case eFormatBoolean:
- case eFormatBinary:
- case eFormatComplex:
- case eFormatCString: // NULL terminated C strings
- case eFormatDecimal:
- case eFormatEnum:
- case eFormatHex:
- case eFormatHexUppercase:
- case eFormatFloat:
- case eFormatOctal:
- case eFormatOSType:
- case eFormatUnsigned:
- case eFormatPointer:
- case eFormatVectorOfChar:
- case eFormatVectorOfSInt8:
- case eFormatVectorOfUInt8:
- case eFormatVectorOfSInt16:
- case eFormatVectorOfUInt16:
- case eFormatVectorOfSInt32:
- case eFormatVectorOfUInt32:
- case eFormatVectorOfSInt64:
- case eFormatVectorOfUInt64:
- case eFormatVectorOfFloat32:
- case eFormatVectorOfFloat64:
- case eFormatVectorOfUInt128:
- break;
-
- case eFormatChar:
- case eFormatCharPrintable:
- case eFormatCharArray:
- case eFormatBytes:
- case eFormatBytesWithASCII:
- item_count = byte_size;
- byte_size = 1;
- break;
-
- case eFormatUnicode16:
- item_count = byte_size / 2;
- byte_size = 2;
- break;
-
- case eFormatUnicode32:
- item_count = byte_size / 4;
- byte_size = 4;
- break;
- }
- return data.Dump (s,
- byte_offset,
- format,
- byte_size,
- item_count,
- UINT32_MAX,
- LLDB_INVALID_ADDRESS,
- bitfield_bit_size,
- bitfield_bit_offset,
- exe_scope);
- }
- break;
- }
- }
- return 0;
-}
-
-
-
-void
-ClangASTType::DumpSummary (ExecutionContext *exe_ctx,
- Stream *s,
- const lldb_private::DataExtractor &data,
- lldb::offset_t data_byte_offset,
- size_t data_byte_size)
-{
- uint32_t length = 0;
- if (IsCStringType (length))
- {
- if (exe_ctx)
- {
- Process *process = exe_ctx->GetProcessPtr();
- if (process)
- {
- lldb::offset_t offset = data_byte_offset;
- lldb::addr_t pointer_address = data.GetMaxU64(&offset, data_byte_size);
- std::vector<uint8_t> buf;
- if (length > 0)
- buf.resize (length);
- else
- buf.resize (256);
-
- lldb_private::DataExtractor cstr_data(&buf.front(), buf.size(), process->GetByteOrder(), 4);
- buf.back() = '\0';
- size_t bytes_read;
- size_t total_cstr_len = 0;
- Error error;
- while ((bytes_read = process->ReadMemory (pointer_address, &buf.front(), buf.size(), error)) > 0)
- {
- const size_t len = strlen((const char *)&buf.front());
- if (len == 0)
- break;
- if (total_cstr_len == 0)
- s->PutCString (" \"");
- cstr_data.Dump(s, 0, lldb::eFormatChar, 1, len, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
- total_cstr_len += len;
- if (len < buf.size())
- break;
- pointer_address += total_cstr_len;
- }
- if (total_cstr_len > 0)
- s->PutChar ('"');
- }
- }
- }
-}
-
-void
-ClangASTType::DumpTypeDescription () const
-{
- StreamFile s (stdout, false);
- DumpTypeDescription (&s);
- ClangASTMetadata *metadata = ClangASTContext::GetMetadata (m_ast, m_type);
- if (metadata)
- {
- metadata->Dump (&s);
- }
-}
-
-void
-ClangASTType::DumpTypeDescription (Stream *s) const
-{
- if (IsValid())
- {
- clang::QualType qual_type(GetQualType());
-
- llvm::SmallVector<char, 1024> buf;
- llvm::raw_svector_ostream llvm_ostrm (buf);
-
- const clang::Type::TypeClass type_class = qual_type->getTypeClass();
- switch (type_class)
- {
- case clang::Type::ObjCObject:
- case clang::Type::ObjCInterface:
- {
- GetCompleteType ();
-
- const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr());
- assert (objc_class_type);
- if (objc_class_type)
- {
- clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
- if (class_interface_decl)
- {
- clang::PrintingPolicy policy = m_ast->getPrintingPolicy();
- class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel());
- }
- }
- }
- break;
-
- case clang::Type::Typedef:
- {
- const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>();
- if (typedef_type)
- {
- const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
- std::string clang_typedef_name (typedef_decl->getQualifiedNameAsString());
- if (!clang_typedef_name.empty())
- {
- s->PutCString ("typedef ");
- s->PutCString (clang_typedef_name.c_str());
- }
- }
- }
- break;
-
- case clang::Type::Elaborated:
- ClangASTType (m_ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).DumpTypeDescription(s);
- return;
-
- case clang::Type::Paren:
- ClangASTType (m_ast, llvm::cast<clang::ParenType>(qual_type)->desugar()).DumpTypeDescription(s);
- return;
-
- case clang::Type::Record:
- {
- GetCompleteType ();
-
- const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr());
- const clang::RecordDecl *record_decl = record_type->getDecl();
- const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl);
-
- if (cxx_record_decl)
- cxx_record_decl->print(llvm_ostrm, m_ast->getPrintingPolicy(), s->GetIndentLevel());
- else
- record_decl->print(llvm_ostrm, m_ast->getPrintingPolicy(), s->GetIndentLevel());
- }
- break;
-
- default:
- {
- const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
- if (tag_type)
- {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- if (tag_decl)
- tag_decl->print(llvm_ostrm, 0);
- }
- else
- {
- std::string clang_type_name(qual_type.getAsString());
- if (!clang_type_name.empty())
- s->PutCString (clang_type_name.c_str());
- }
- }
- }
-
- llvm_ostrm.flush();
- if (buf.size() > 0)
- {
- s->Write (buf.data(), buf.size());
- }
- }
-}
-
-bool
-ClangASTType::GetValueAsScalar (const lldb_private::DataExtractor &data,
- lldb::offset_t data_byte_offset,
- size_t data_byte_size,
- Scalar &value) const
-{
- if (!IsValid())
- return false;
-
- if (IsAggregateType ())
- {
- return false; // Aggregate types don't have scalar values
- }
- else
- {
- uint64_t count = 0;
- lldb::Encoding encoding = GetEncoding (count);
-
- if (encoding == lldb::eEncodingInvalid || count != 1)
- return false;
-
- const uint64_t byte_size = GetByteSize(nullptr);
- lldb::offset_t offset = data_byte_offset;
- switch (encoding)
- {
- case lldb::eEncodingInvalid:
- break;
- case lldb::eEncodingVector:
- break;
- case lldb::eEncodingUint:
- if (byte_size <= sizeof(unsigned long long))
- {
- uint64_t uval64 = data.GetMaxU64 (&offset, byte_size);
- if (byte_size <= sizeof(unsigned int))
- {
- value = (unsigned int)uval64;
- return true;
- }
- else if (byte_size <= sizeof(unsigned long))
- {
- value = (unsigned long)uval64;
- return true;
- }
- else if (byte_size <= sizeof(unsigned long long))
- {
- value = (unsigned long long )uval64;
- return true;
- }
- else
- value.Clear();
- }
- break;
-
- case lldb::eEncodingSint:
- if (byte_size <= sizeof(long long))
- {
- int64_t sval64 = data.GetMaxS64 (&offset, byte_size);
- if (byte_size <= sizeof(int))
- {
- value = (int)sval64;
- return true;
- }
- else if (byte_size <= sizeof(long))
- {
- value = (long)sval64;
- return true;
- }
- else if (byte_size <= sizeof(long long))
- {
- value = (long long )sval64;
- return true;
- }
- else
- value.Clear();
- }
- break;
-
- case lldb::eEncodingIEEE754:
- if (byte_size <= sizeof(long double))
- {
- uint32_t u32;
- uint64_t u64;
- if (byte_size == sizeof(float))
- {
- if (sizeof(float) == sizeof(uint32_t))
- {
- u32 = data.GetU32(&offset);
- value = *((float *)&u32);
- return true;
- }
- else if (sizeof(float) == sizeof(uint64_t))
- {
- u64 = data.GetU64(&offset);
- value = *((float *)&u64);
- return true;
- }
- }
- else
- if (byte_size == sizeof(double))
- {
- if (sizeof(double) == sizeof(uint32_t))
- {
- u32 = data.GetU32(&offset);
- value = *((double *)&u32);
- return true;
- }
- else if (sizeof(double) == sizeof(uint64_t))
- {
- u64 = data.GetU64(&offset);
- value = *((double *)&u64);
- return true;
- }
- }
- else
- if (byte_size == sizeof(long double))
- {
- if (sizeof(long double) == sizeof(uint32_t))
- {
- u32 = data.GetU32(&offset);
- value = *((long double *)&u32);
- return true;
- }
- else if (sizeof(long double) == sizeof(uint64_t))
- {
- u64 = data.GetU64(&offset);
- value = *((long double *)&u64);
- return true;
- }
- }
- }
- break;
- }
- }
- return false;
-}
-
-bool
-ClangASTType::SetValueFromScalar (const Scalar &value, Stream &strm)
-{
- // Aggregate types don't have scalar values
- if (!IsAggregateType ())
- {
- strm.GetFlags().Set(Stream::eBinary);
- uint64_t count = 0;
- lldb::Encoding encoding = GetEncoding (count);
-
- if (encoding == lldb::eEncodingInvalid || count != 1)
- return false;
-
- const uint64_t bit_width = GetBitSize(nullptr);
- // This function doesn't currently handle non-byte aligned assignments
- if ((bit_width % 8) != 0)
- return false;
-
- const uint64_t byte_size = (bit_width + 7 ) / 8;
- switch (encoding)
- {
- case lldb::eEncodingInvalid:
- break;
- case lldb::eEncodingVector:
- break;
- case lldb::eEncodingUint:
- switch (byte_size)
- {
- case 1: strm.PutHex8(value.UInt()); return true;
- case 2: strm.PutHex16(value.UInt()); return true;
- case 4: strm.PutHex32(value.UInt()); return true;
- case 8: strm.PutHex64(value.ULongLong()); return true;
- default:
- break;
- }
- break;
-
- case lldb::eEncodingSint:
- switch (byte_size)
- {
- case 1: strm.PutHex8(value.SInt()); return true;
- case 2: strm.PutHex16(value.SInt()); return true;
- case 4: strm.PutHex32(value.SInt()); return true;
- case 8: strm.PutHex64(value.SLongLong()); return true;
- default:
- break;
- }
- break;
-
- case lldb::eEncodingIEEE754:
- if (byte_size <= sizeof(long double))
- {
- if (byte_size == sizeof(float))
- {
- strm.PutFloat(value.Float());
- return true;
- }
- else
- if (byte_size == sizeof(double))
- {
- strm.PutDouble(value.Double());
- return true;
- }
- else
- if (byte_size == sizeof(long double))
- {
- strm.PutDouble(value.LongDouble());
- return true;
- }
- }
- break;
- }
- }
- return false;
-}
-
-bool
-ClangASTType::ReadFromMemory (lldb_private::ExecutionContext *exe_ctx,
- lldb::addr_t addr,
- AddressType address_type,
- lldb_private::DataExtractor &data)
-{
- if (!IsValid())
- return false;
-
- // Can't convert a file address to anything valid without more
- // context (which Module it came from)
- if (address_type == eAddressTypeFile)
- return false;
-
- if (!GetCompleteType())
- return false;
-
- const uint64_t byte_size = GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- if (data.GetByteSize() < byte_size)
- {
- lldb::DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0'));
- data.SetData(data_sp);
- }
-
- uint8_t* dst = (uint8_t*)data.PeekData(0, byte_size);
- if (dst != nullptr)
- {
- if (address_type == eAddressTypeHost)
- {
- if (addr == 0)
- return false;
- // The address is an address in this process, so just copy it
- memcpy (dst, (uint8_t*)nullptr + addr, byte_size);
- return true;
- }
- else
- {
- Process *process = nullptr;
- if (exe_ctx)
- process = exe_ctx->GetProcessPtr();
- if (process)
- {
- Error error;
- return process->ReadMemory(addr, dst, byte_size, error) == byte_size;
- }
- }
- }
- return false;
-}
-
-bool
-ClangASTType::WriteToMemory (lldb_private::ExecutionContext *exe_ctx,
- lldb::addr_t addr,
- AddressType address_type,
- StreamString &new_value)
-{
- if (!IsValid())
- return false;
-
- // Can't convert a file address to anything valid without more
- // context (which Module it came from)
- if (address_type == eAddressTypeFile)
- return false;
-
- if (!GetCompleteType())
- return false;
-
- const uint64_t byte_size = GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
-
- if (byte_size > 0)
- {
- if (address_type == eAddressTypeHost)
- {
- // The address is an address in this process, so just copy it
- memcpy ((void *)addr, new_value.GetData(), byte_size);
- return true;
- }
- else
- {
- Process *process = nullptr;
- if (exe_ctx)
- process = exe_ctx->GetProcessPtr();
- if (process)
- {
- Error error;
- return process->WriteMemory(addr, new_value.GetData(), byte_size, error) == byte_size;
- }
- }
- }
- return false;
-}
-
-
-//clang::CXXRecordDecl *
-//ClangASTType::GetAsCXXRecordDecl (lldb::clang_type_t opaque_clang_qual_type)
-//{
-// if (opaque_clang_qual_type)
-// return clang::QualType::getFromOpaquePtr(opaque_clang_qual_type)->getAsCXXRecordDecl();
-// return NULL;
-//}
-
-bool
-lldb_private::operator == (const lldb_private::ClangASTType &lhs, const lldb_private::ClangASTType &rhs)
-{
- return lhs.GetASTContext() == rhs.GetASTContext() && lhs.GetOpaqueQualType() == rhs.GetOpaqueQualType();
-}
-
-
-bool
-lldb_private::operator != (const lldb_private::ClangASTType &lhs, const lldb_private::ClangASTType &rhs)
-{
- return lhs.GetASTContext() != rhs.GetASTContext() || lhs.GetOpaqueQualType() != rhs.GetOpaqueQualType();
-}
-
-
-
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp
index cd6972c..6c804f4 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp
@@ -41,6 +41,7 @@
#endif
#include "lldb/Core/Log.h"
+#include "clang/AST/Decl.h"
using namespace clang;
using namespace lldb_private;
@@ -160,3 +161,16 @@ ClangExternalASTSourceCallbacks::layoutRecordType(
return false;
}
+void
+ClangExternalASTSourceCallbacks::FindExternalLexicalDecls (const clang::DeclContext *decl_ctx,
+ llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
+ llvm::SmallVectorImpl<clang::Decl *> &decls)
+{
+ if (m_callback_tag_decl && decl_ctx)
+ {
+ clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(const_cast<clang::DeclContext *>(decl_ctx));
+ if (tag_decl)
+ CompleteType(tag_decl);
+ }
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ClangNamespaceDecl.cpp b/contrib/llvm/tools/lldb/source/Symbol/ClangNamespaceDecl.cpp
deleted file mode 100644
index 568b026..0000000
--- a/contrib/llvm/tools/lldb/source/Symbol/ClangNamespaceDecl.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===-- ClangNamespaceDecl.cpp ----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Symbol/ClangNamespaceDecl.h"
-
-#include "clang/AST/Decl.h"
-
-namespace lldb_private {
-
-std::string
-ClangNamespaceDecl::GetQualifiedName () const
-{
- if (m_namespace_decl)
- return m_namespace_decl->getQualifiedNameAsString();
- return std::string();
-}
-
-
-}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp b/contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp
index afef4e4..233ca91 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/CompactUnwindInfo.cpp
@@ -297,7 +297,7 @@ CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp)
Host::SystemLog (Host::eSystemLogError,
"error: Invalid offset encountered in compact unwind info, skipping\n");
// don't trust anything from this compact_unwind section if it looks
- // blatently invalid data in the header.
+ // blatantly invalid data in the header.
m_indexes_computed = eLazyBoolNo;
return;
}
@@ -693,7 +693,7 @@ enum x86_64_eh_regnum {
};
// Convert the compact_unwind_info.h register numbering scheme
-// to eRegisterKindGCC (eh_frame) register numbering scheme.
+// to eRegisterKindEHFrame (eh_frame) register numbering scheme.
uint32_t
translate_to_eh_frame_regnum_x86_64 (uint32_t unwind_regno)
{
@@ -722,7 +722,7 @@ CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &functi
unwind_plan.SetSourceName ("compact unwind info");
unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
- unwind_plan.SetRegisterKind (eRegisterKindGCC);
+ unwind_plan.SetRegisterKind (eRegisterKindEHFrame);
unwind_plan.SetLSDAAddress (function_info.lsda_address);
unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address);
@@ -976,7 +976,7 @@ enum i386_eh_regnum {
};
// Convert the compact_unwind_info.h register numbering scheme
-// to eRegisterKindGCC (eh_frame) register numbering scheme.
+// to eRegisterKindEHFrame (eh_frame) register numbering scheme.
uint32_t
translate_to_eh_frame_regnum_i386 (uint32_t unwind_regno)
{
@@ -1006,7 +1006,7 @@ CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function
unwind_plan.SetSourceName ("compact unwind info");
unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
- unwind_plan.SetRegisterKind (eRegisterKindGCC);
+ unwind_plan.SetRegisterKind (eRegisterKindEHFrame);
unwind_plan.SetLSDAAddress (function_info.lsda_address);
unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address);
diff --git a/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp b/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp
index d43ef44..50eda88 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/CompileUnit.cpp
@@ -9,15 +9,15 @@
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/Language.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/Language.h"
using namespace lldb;
using namespace lldb_private;
-CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, lldb::LanguageType language) :
+CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, lldb::LanguageType language, bool is_optimized) :
ModuleChild(module_sp),
FileSpec (pathname, false),
UserID(cu_sym_id),
@@ -27,14 +27,15 @@ CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, cons
m_functions (),
m_support_files (),
m_line_table_ap (),
- m_variables()
+ m_variables(),
+ m_is_optimized (is_optimized)
{
if (language != eLanguageTypeUnknown)
m_flags.Set(flagsParsedLanguage);
assert(module_sp);
}
-CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, lldb::LanguageType language) :
+CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, lldb::LanguageType language, bool is_optimized) :
ModuleChild(module_sp),
FileSpec (fspec),
UserID(cu_sym_id),
@@ -44,7 +45,8 @@ CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, cons
m_functions (),
m_support_files (),
m_line_table_ap (),
- m_variables()
+ m_variables(),
+ m_is_optimized (is_optimized)
{
if (language != eLanguageTypeUnknown)
m_flags.Set(flagsParsedLanguage);
@@ -85,7 +87,7 @@ CompileUnit::DumpSymbolContext(Stream *s)
void
CompileUnit::GetDescription(Stream *s, lldb::DescriptionLevel level) const
{
- Language language(m_language);
+ const char* language = Language::GetNameForLanguageType(m_language);
*s << "id = " << (const UserID&)*this << ", file = \"" << (const FileSpec&)*this << "\", language = \"" << language << '"';
}
@@ -99,10 +101,12 @@ CompileUnit::GetDescription(Stream *s, lldb::DescriptionLevel level) const
void
CompileUnit::Dump(Stream *s, bool show_context) const
{
+ const char* language = Language::GetNameForLanguageType(m_language);
+
s->Printf("%p: ", static_cast<const void*>(this));
s->Indent();
*s << "CompileUnit" << static_cast<const UserID&>(*this)
- << ", language = \"" << reinterpret_cast<const Language&>(*this)
+ << ", language = \"" << language
<< "\", file = '" << static_cast<const FileSpec&>(*this) << "'\n";
// m_types.Dump(s);
@@ -264,6 +268,37 @@ CompileUnit::SetLineTable(LineTable* line_table)
m_line_table_ap.reset(line_table);
}
+DebugMacros*
+CompileUnit::GetDebugMacros()
+{
+ if (m_debug_macros_sp.get() == nullptr)
+ {
+ if (m_flags.IsClear(flagsParsedDebugMacros))
+ {
+ m_flags.Set(flagsParsedDebugMacros);
+ SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor();
+ if (symbol_vendor)
+ {
+ SymbolContext sc;
+ CalculateSymbolContext(&sc);
+ symbol_vendor->ParseCompileUnitDebugMacros(sc);
+ }
+ }
+ }
+
+ return m_debug_macros_sp.get();
+}
+
+void
+CompileUnit::SetDebugMacros(const DebugMacrosSP &debug_macros_sp)
+{
+ if (debug_macros_sp.get() == nullptr)
+ m_flags.Clear(flagsParsedDebugMacros);
+ else
+ m_flags.Set(flagsParsedDebugMacros);
+ m_debug_macros_sp = debug_macros_sp;
+}
+
VariableListSP
CompileUnit::GetVariableList(bool can_create)
{
@@ -430,6 +465,12 @@ CompileUnit::ResolveSymbolContext
return sc_list.GetSize() - prev_size;
}
+bool
+CompileUnit::GetIsOptimized ()
+{
+ return m_is_optimized;
+}
+
void
CompileUnit::SetVariableList(VariableListSP &variables)
{
diff --git a/contrib/llvm/tools/lldb/source/Symbol/CompilerDecl.cpp b/contrib/llvm/tools/lldb/source/Symbol/CompilerDecl.cpp
new file mode 100644
index 0000000..42e5fb08
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Symbol/CompilerDecl.cpp
@@ -0,0 +1,76 @@
+//===-- CompilerDecl.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/Symbol/TypeSystem.h"
+
+using namespace lldb_private;
+
+bool
+CompilerDecl::IsClang () const
+{
+ return IsValid() && m_type_system->getKind() == TypeSystem::eKindClang;
+}
+
+ConstString
+CompilerDecl::GetName() const
+{
+ return m_type_system->DeclGetName(m_opaque_decl);
+}
+
+ConstString
+CompilerDecl::GetMangledName () const
+{
+ return m_type_system->DeclGetMangledName(m_opaque_decl);
+}
+
+lldb::VariableSP
+CompilerDecl::GetAsVariable ()
+{
+ return m_type_system->DeclGetVariable(m_opaque_decl);
+}
+
+CompilerDeclContext
+CompilerDecl::GetDeclContext() const
+{
+ return m_type_system->DeclGetDeclContext(m_opaque_decl);
+}
+
+CompilerType
+CompilerDecl::GetFunctionReturnType() const
+{
+ return m_type_system->DeclGetFunctionReturnType(m_opaque_decl);
+}
+
+size_t
+CompilerDecl::GetNumFunctionArguments() const
+{
+ return m_type_system->DeclGetFunctionNumArguments(m_opaque_decl);
+}
+
+CompilerType
+CompilerDecl::GetFunctionArgumentType (size_t arg_idx) const
+{
+ return m_type_system->DeclGetFunctionArgumentType(m_opaque_decl, arg_idx);
+}
+
+bool
+lldb_private::operator == (const lldb_private::CompilerDecl &lhs, const lldb_private::CompilerDecl &rhs)
+{
+ return lhs.GetTypeSystem() == rhs.GetTypeSystem() && lhs.GetOpaqueDecl() == rhs.GetOpaqueDecl();
+}
+
+
+bool
+lldb_private::operator != (const lldb_private::CompilerDecl &lhs, const lldb_private::CompilerDecl &rhs)
+{
+ return lhs.GetTypeSystem() != rhs.GetTypeSystem() || lhs.GetOpaqueDecl() != rhs.GetOpaqueDecl();
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Symbol/CompilerDeclContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/CompilerDeclContext.cpp
new file mode 100644
index 0000000..8bee1b4
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Symbol/CompilerDeclContext.cpp
@@ -0,0 +1,84 @@
+//===-- CompilerDeclContext.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include <vector>
+
+using namespace lldb_private;
+
+std::vector<CompilerDecl>
+CompilerDeclContext::FindDeclByName (ConstString name)
+{
+ if (IsValid())
+ return m_type_system->DeclContextFindDeclByName(m_opaque_decl_ctx, name);
+ else
+ return std::vector<CompilerDecl>();
+}
+
+bool
+CompilerDeclContext::IsClang () const
+{
+ return IsValid() && m_type_system->getKind() == TypeSystem::eKindClang;
+}
+
+ConstString
+CompilerDeclContext::GetName () const
+{
+ if (IsValid())
+ return m_type_system->DeclContextGetName(m_opaque_decl_ctx);
+ else
+ return ConstString();
+}
+
+ConstString
+CompilerDeclContext::GetScopeQualifiedName () const
+{
+ if (IsValid())
+ return m_type_system->DeclContextGetScopeQualifiedName(m_opaque_decl_ctx);
+ else
+ return ConstString();
+}
+
+bool
+CompilerDeclContext::IsStructUnionOrClass () const
+{
+ if (IsValid())
+ return m_type_system->DeclContextIsStructUnionOrClass(m_opaque_decl_ctx);
+ else
+ return false;
+}
+
+bool
+CompilerDeclContext::IsClassMethod (lldb::LanguageType *language_ptr,
+ bool *is_instance_method_ptr,
+ ConstString *language_object_name_ptr)
+{
+ if (IsValid())
+ return m_type_system->DeclContextIsClassMethod (m_opaque_decl_ctx,
+ language_ptr,
+ is_instance_method_ptr,
+ language_object_name_ptr);
+ else
+ return false;
+}
+
+bool
+lldb_private::operator == (const lldb_private::CompilerDeclContext &lhs, const lldb_private::CompilerDeclContext &rhs)
+{
+ return lhs.GetTypeSystem() == rhs.GetTypeSystem() && lhs.GetOpaqueDeclContext() == rhs.GetOpaqueDeclContext();
+}
+
+
+bool
+lldb_private::operator != (const lldb_private::CompilerDeclContext &lhs, const lldb_private::CompilerDeclContext &rhs)
+{
+ return lhs.GetTypeSystem() != rhs.GetTypeSystem() || lhs.GetOpaqueDeclContext() != rhs.GetOpaqueDeclContext();
+}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/CompilerType.cpp b/contrib/llvm/tools/lldb/source/Symbol/CompilerType.cpp
new file mode 100644
index 0000000..000a949
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Symbol/CompilerType.cpp
@@ -0,0 +1,1320 @@
+//===-- CompilerType.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/CompilerType.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+
+#include <iterator>
+#include <mutex>
+
+using namespace lldb;
+using namespace lldb_private;
+
+CompilerType::CompilerType (TypeSystem *type_system,
+ lldb::opaque_compiler_type_t type) :
+ m_type (type),
+ m_type_system (type_system)
+{
+}
+
+CompilerType::CompilerType (clang::ASTContext *ast,
+ clang::QualType qual_type) :
+ m_type (qual_type.getAsOpaquePtr()),
+ m_type_system (ClangASTContext::GetASTContext(ast))
+{
+#ifdef LLDB_CONFIGURATION_DEBUG
+ if (m_type)
+ assert(m_type_system != nullptr);
+#endif
+}
+
+CompilerType::~CompilerType()
+{
+}
+
+//----------------------------------------------------------------------
+// Tests
+//----------------------------------------------------------------------
+
+bool
+CompilerType::IsAggregateType () const
+{
+ if (IsValid())
+ return m_type_system->IsAggregateType(m_type);
+ return false;
+}
+
+bool
+CompilerType::IsAnonymousType () const
+{
+ if (IsValid())
+ return m_type_system->IsAnonymousType(m_type);
+ return false;
+}
+
+bool
+CompilerType::IsArrayType (CompilerType *element_type_ptr,
+ uint64_t *size,
+ bool *is_incomplete) const
+{
+ if (IsValid())
+ return m_type_system->IsArrayType(m_type, element_type_ptr, size, is_incomplete);
+
+ if (element_type_ptr)
+ element_type_ptr->Clear();
+ if (size)
+ *size = 0;
+ if (is_incomplete)
+ *is_incomplete = false;
+ return false;
+}
+
+bool
+CompilerType::IsVectorType (CompilerType *element_type,
+ uint64_t *size) const
+{
+ if (IsValid())
+ return m_type_system->IsVectorType(m_type, element_type, size);
+ return false;
+}
+
+bool
+CompilerType::IsRuntimeGeneratedType () const
+{
+ if (IsValid())
+ return m_type_system->IsRuntimeGeneratedType(m_type);
+ return false;
+}
+
+bool
+CompilerType::IsCharType () const
+{
+ if (IsValid())
+ return m_type_system->IsCharType(m_type);
+ return false;
+}
+
+
+bool
+CompilerType::IsCompleteType () const
+{
+ if (IsValid())
+ return m_type_system->IsCompleteType(m_type);
+ return false;
+}
+
+bool
+CompilerType::IsConst() const
+{
+ if (IsValid())
+ return m_type_system->IsConst(m_type);
+ return false;
+}
+
+bool
+CompilerType::IsCStringType (uint32_t &length) const
+{
+ if (IsValid())
+ return m_type_system->IsCStringType(m_type, length);
+ return false;
+}
+
+bool
+CompilerType::IsFunctionType (bool *is_variadic_ptr) const
+{
+ if (IsValid())
+ return m_type_system->IsFunctionType(m_type, is_variadic_ptr);
+ return false;
+}
+
+// Used to detect "Homogeneous Floating-point Aggregates"
+uint32_t
+CompilerType::IsHomogeneousAggregate (CompilerType* base_type_ptr) const
+{
+ if (IsValid())
+ return m_type_system->IsHomogeneousAggregate(m_type, base_type_ptr);
+ return 0;
+}
+
+size_t
+CompilerType::GetNumberOfFunctionArguments () const
+{
+ if (IsValid())
+ return m_type_system->GetNumberOfFunctionArguments(m_type);
+ return 0;
+}
+
+CompilerType
+CompilerType::GetFunctionArgumentAtIndex (const size_t index) const
+{
+ if (IsValid())
+ return m_type_system->GetFunctionArgumentAtIndex(m_type, index);
+ return CompilerType();
+}
+
+bool
+CompilerType::IsFunctionPointerType () const
+{
+ if (IsValid())
+ return m_type_system->IsFunctionPointerType(m_type);
+ return false;
+
+}
+
+bool
+CompilerType::IsIntegerType (bool &is_signed) const
+{
+ if (IsValid())
+ return m_type_system->IsIntegerType(m_type, is_signed);
+ return false;
+}
+
+bool
+CompilerType::IsPointerType (CompilerType *pointee_type) const
+{
+ if (IsValid())
+ {
+ return m_type_system->IsPointerType(m_type, pointee_type);
+ }
+ if (pointee_type)
+ pointee_type->Clear();
+ return false;
+}
+
+
+bool
+CompilerType::IsPointerOrReferenceType (CompilerType *pointee_type) const
+{
+ if (IsValid())
+ {
+ return m_type_system->IsPointerOrReferenceType(m_type, pointee_type);
+ }
+ if (pointee_type)
+ pointee_type->Clear();
+ return false;
+}
+
+
+bool
+CompilerType::IsReferenceType (CompilerType *pointee_type, bool* is_rvalue) const
+{
+ if (IsValid())
+ {
+ return m_type_system->IsReferenceType(m_type, pointee_type, is_rvalue);
+ }
+ if (pointee_type)
+ pointee_type->Clear();
+ return false;
+}
+
+bool
+CompilerType::ShouldTreatScalarValueAsAddress () const
+{
+ if (IsValid())
+ return m_type_system->ShouldTreatScalarValueAsAddress(m_type);
+ return false;
+}
+
+bool
+CompilerType::IsFloatingPointType (uint32_t &count, bool &is_complex) const
+{
+ if (IsValid())
+ {
+ return m_type_system->IsFloatingPointType(m_type, count, is_complex);
+ }
+ count = 0;
+ is_complex = false;
+ return false;
+}
+
+
+bool
+CompilerType::IsDefined() const
+{
+ if (IsValid())
+ return m_type_system->IsDefined(m_type);
+ return true;
+}
+
+bool
+CompilerType::IsPolymorphicClass () const
+{
+ if (IsValid())
+ {
+ return m_type_system->IsPolymorphicClass(m_type);
+ }
+ return false;
+}
+
+bool
+CompilerType::IsPossibleDynamicType (CompilerType *dynamic_pointee_type,
+ bool check_cplusplus,
+ bool check_objc) const
+{
+ if (IsValid())
+ return m_type_system->IsPossibleDynamicType(m_type, dynamic_pointee_type, check_cplusplus, check_objc);
+ return false;
+}
+
+
+bool
+CompilerType::IsScalarType () const
+{
+ if (!IsValid())
+ return false;
+
+ return m_type_system->IsScalarType(m_type);
+}
+
+bool
+CompilerType::IsTypedefType () const
+{
+ if (!IsValid())
+ return false;
+ return m_type_system->IsTypedefType(m_type);
+}
+
+bool
+CompilerType::IsVoidType () const
+{
+ if (!IsValid())
+ return false;
+ return m_type_system->IsVoidType(m_type);
+}
+
+bool
+CompilerType::IsPointerToScalarType () const
+{
+ if (!IsValid())
+ return false;
+
+ return IsPointerType() && GetPointeeType().IsScalarType();
+}
+
+bool
+CompilerType::IsArrayOfScalarType () const
+{
+ CompilerType element_type;
+ if (IsArrayType(&element_type, nullptr, nullptr))
+ return element_type.IsScalarType();
+ return false;
+}
+
+bool
+CompilerType::IsBeingDefined () const
+{
+ if (!IsValid())
+ return false;
+ return m_type_system->IsBeingDefined(m_type);
+}
+
+//----------------------------------------------------------------------
+// Type Completion
+//----------------------------------------------------------------------
+
+bool
+CompilerType::GetCompleteType () const
+{
+ if (!IsValid())
+ return false;
+ return m_type_system->GetCompleteType(m_type);
+}
+
+//----------------------------------------------------------------------
+// AST related queries
+//----------------------------------------------------------------------
+size_t
+CompilerType::GetPointerByteSize () const
+{
+ if (m_type_system)
+ return m_type_system->GetPointerByteSize();
+ return 0;
+}
+
+ConstString
+CompilerType::GetConstQualifiedTypeName () const
+{
+ return GetConstTypeName ();
+}
+
+ConstString
+CompilerType::GetConstTypeName () const
+{
+ if (IsValid())
+ {
+ ConstString type_name (GetTypeName());
+ if (type_name)
+ return type_name;
+ }
+ return ConstString("<invalid>");
+}
+
+ConstString
+CompilerType::GetTypeName () const
+{
+ if (IsValid())
+ {
+ return m_type_system->GetTypeName(m_type);
+ }
+ return ConstString("<invalid>");
+}
+
+ConstString
+CompilerType::GetDisplayTypeName () const
+{
+ return GetTypeName();
+}
+
+uint32_t
+CompilerType::GetTypeInfo (CompilerType *pointee_or_element_compiler_type) const
+{
+ if (!IsValid())
+ return 0;
+
+ return m_type_system->GetTypeInfo(m_type, pointee_or_element_compiler_type);
+}
+
+
+
+lldb::LanguageType
+CompilerType::GetMinimumLanguage ()
+{
+ if (!IsValid())
+ return lldb::eLanguageTypeC;
+
+ return m_type_system->GetMinimumLanguage(m_type);
+}
+
+lldb::TypeClass
+CompilerType::GetTypeClass () const
+{
+ if (!IsValid())
+ return lldb::eTypeClassInvalid;
+
+ return m_type_system->GetTypeClass(m_type);
+
+}
+
+void
+CompilerType::SetCompilerType (TypeSystem* type_system, lldb::opaque_compiler_type_t type)
+{
+ m_type_system = type_system;
+ m_type = type;
+}
+
+void
+CompilerType::SetCompilerType (clang::ASTContext *ast, clang::QualType qual_type)
+{
+ m_type_system = ClangASTContext::GetASTContext(ast);
+ m_type = qual_type.getAsOpaquePtr();
+}
+
+unsigned
+CompilerType::GetTypeQualifiers() const
+{
+ if (IsValid())
+ return m_type_system->GetTypeQualifiers(m_type);
+ return 0;
+}
+
+//----------------------------------------------------------------------
+// Creating related types
+//----------------------------------------------------------------------
+
+CompilerType
+CompilerType::GetArrayElementType (uint64_t *stride) const
+{
+ if (IsValid())
+ {
+ return m_type_system->GetArrayElementType(m_type, stride);
+
+ }
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::GetCanonicalType () const
+{
+ if (IsValid())
+ return m_type_system->GetCanonicalType(m_type);
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::GetFullyUnqualifiedType () const
+{
+ if (IsValid())
+ return m_type_system->GetFullyUnqualifiedType(m_type);
+ return CompilerType();
+}
+
+
+int
+CompilerType::GetFunctionArgumentCount () const
+{
+ if (IsValid())
+ {
+ return m_type_system->GetFunctionArgumentCount(m_type);
+ }
+ return -1;
+}
+
+CompilerType
+CompilerType::GetFunctionArgumentTypeAtIndex (size_t idx) const
+{
+ if (IsValid())
+ {
+ return m_type_system->GetFunctionArgumentTypeAtIndex(m_type, idx);
+ }
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::GetFunctionReturnType () const
+{
+ if (IsValid())
+ {
+ return m_type_system->GetFunctionReturnType(m_type);
+ }
+ return CompilerType();
+}
+
+size_t
+CompilerType::GetNumMemberFunctions () const
+{
+ if (IsValid())
+ {
+ return m_type_system->GetNumMemberFunctions(m_type);
+ }
+ return 0;
+}
+
+TypeMemberFunctionImpl
+CompilerType::GetMemberFunctionAtIndex (size_t idx)
+{
+ if (IsValid())
+ {
+ return m_type_system->GetMemberFunctionAtIndex(m_type, idx);
+ }
+ return TypeMemberFunctionImpl();
+}
+
+CompilerType
+CompilerType::GetNonReferenceType () const
+{
+ if (IsValid())
+ return m_type_system->GetNonReferenceType(m_type);
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::GetPointeeType () const
+{
+ if (IsValid())
+ {
+ return m_type_system->GetPointeeType(m_type);
+ }
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::GetPointerType () const
+{
+ if (IsValid())
+ {
+ return m_type_system->GetPointerType(m_type);
+ }
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::GetLValueReferenceType () const
+{
+ if (IsValid())
+ return m_type_system->GetLValueReferenceType(m_type);
+ else
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::GetRValueReferenceType () const
+{
+ if (IsValid())
+ return m_type_system->GetRValueReferenceType(m_type);
+ else
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::AddConstModifier () const
+{
+ if (IsValid())
+ return m_type_system->AddConstModifier(m_type);
+ else
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::AddVolatileModifier () const
+{
+ if (IsValid())
+ return m_type_system->AddVolatileModifier(m_type);
+ else
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::AddRestrictModifier () const
+{
+ if (IsValid())
+ return m_type_system->AddRestrictModifier(m_type);
+ else
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const
+{
+ if (IsValid())
+ return m_type_system->CreateTypedef(m_type, name, decl_ctx);
+ else
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::GetTypedefedType () const
+{
+ if (IsValid())
+ return m_type_system->GetTypedefedType(m_type);
+ else
+ return CompilerType();
+}
+
+//----------------------------------------------------------------------
+// Create related types using the current type's AST
+//----------------------------------------------------------------------
+
+CompilerType
+CompilerType::GetBasicTypeFromAST (lldb::BasicType basic_type) const
+{
+ if (IsValid())
+ return m_type_system->GetBasicTypeFromAST(basic_type);
+ return CompilerType();
+}
+//----------------------------------------------------------------------
+// Exploring the type
+//----------------------------------------------------------------------
+
+uint64_t
+CompilerType::GetBitSize (ExecutionContextScope *exe_scope) const
+{
+ if (IsValid())
+ {
+ return m_type_system->GetBitSize(m_type, exe_scope);
+ }
+ return 0;
+}
+
+uint64_t
+CompilerType::GetByteSize (ExecutionContextScope *exe_scope) const
+{
+ return (GetBitSize (exe_scope) + 7) / 8;
+}
+
+
+size_t
+CompilerType::GetTypeBitAlign () const
+{
+ if (IsValid())
+ return m_type_system->GetTypeBitAlign(m_type);
+ return 0;
+}
+
+
+lldb::Encoding
+CompilerType::GetEncoding (uint64_t &count) const
+{
+ if (!IsValid())
+ return lldb::eEncodingInvalid;
+
+ return m_type_system->GetEncoding(m_type, count);
+}
+
+lldb::Format
+CompilerType::GetFormat () const
+{
+ if (!IsValid())
+ return lldb::eFormatDefault;
+
+ return m_type_system->GetFormat(m_type);
+}
+
+uint32_t
+CompilerType::GetNumChildren (bool omit_empty_base_classes) const
+{
+ if (!IsValid())
+ return 0;
+ return m_type_system->GetNumChildren(m_type, omit_empty_base_classes);
+}
+
+lldb::BasicType
+CompilerType::GetBasicTypeEnumeration () const
+{
+ if (IsValid())
+ return m_type_system->GetBasicTypeEnumeration(m_type);
+ return eBasicTypeInvalid;
+}
+
+void
+CompilerType::ForEachEnumerator (std::function <bool (const CompilerType &integer_type, const ConstString &name, const llvm::APSInt &value)> const &callback) const
+{
+ if (IsValid())
+ return m_type_system->ForEachEnumerator (m_type, callback);
+}
+
+
+uint32_t
+CompilerType::GetNumFields () const
+{
+ if (!IsValid())
+ return 0;
+ return m_type_system->GetNumFields(m_type);
+}
+
+CompilerType
+CompilerType::GetFieldAtIndex (size_t idx,
+ std::string& name,
+ uint64_t *bit_offset_ptr,
+ uint32_t *bitfield_bit_size_ptr,
+ bool *is_bitfield_ptr) const
+{
+ if (!IsValid())
+ return CompilerType();
+ return m_type_system->GetFieldAtIndex(m_type, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr);
+}
+
+uint32_t
+CompilerType::GetNumDirectBaseClasses () const
+{
+ if (IsValid())
+ return m_type_system->GetNumDirectBaseClasses (m_type);
+ return 0;
+}
+
+uint32_t
+CompilerType::GetNumVirtualBaseClasses () const
+{
+ if (IsValid())
+ return m_type_system->GetNumVirtualBaseClasses (m_type);
+ return 0;
+}
+
+CompilerType
+CompilerType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) const
+{
+ if (IsValid())
+ return m_type_system->GetDirectBaseClassAtIndex (m_type, idx, bit_offset_ptr);
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::GetVirtualBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) const
+{
+ if (IsValid())
+ return m_type_system->GetVirtualBaseClassAtIndex (m_type, idx, bit_offset_ptr);
+ return CompilerType();
+}
+
+uint32_t
+CompilerType::GetIndexOfFieldWithName (const char* name,
+ CompilerType* field_compiler_type_ptr,
+ uint64_t *bit_offset_ptr,
+ uint32_t *bitfield_bit_size_ptr,
+ bool *is_bitfield_ptr) const
+{
+ unsigned count = GetNumFields();
+ std::string field_name;
+ for (unsigned index = 0; index < count; index++)
+ {
+ CompilerType field_compiler_type (GetFieldAtIndex(index, field_name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr));
+ if (strcmp(field_name.c_str(), name) == 0)
+ {
+ if (field_compiler_type_ptr)
+ *field_compiler_type_ptr = field_compiler_type;
+ return index;
+ }
+ }
+ return UINT32_MAX;
+}
+
+
+CompilerType
+CompilerType::GetChildCompilerTypeAtIndex (ExecutionContext *exe_ctx,
+ size_t idx,
+ bool transparent_pointers,
+ bool omit_empty_base_classes,
+ bool ignore_array_bounds,
+ std::string& child_name,
+ uint32_t &child_byte_size,
+ int32_t &child_byte_offset,
+ uint32_t &child_bitfield_bit_size,
+ uint32_t &child_bitfield_bit_offset,
+ bool &child_is_base_class,
+ bool &child_is_deref_of_parent,
+ ValueObject *valobj,
+ uint64_t &language_flags) const
+{
+ if (!IsValid())
+ return CompilerType();
+ return m_type_system->GetChildCompilerTypeAtIndex(m_type,
+ exe_ctx,
+ idx,
+ transparent_pointers,
+ omit_empty_base_classes,
+ ignore_array_bounds,
+ child_name,
+ child_byte_size,
+ child_byte_offset,
+ child_bitfield_bit_size,
+ child_bitfield_bit_offset,
+ child_is_base_class,
+ child_is_deref_of_parent,
+ valobj,
+ language_flags);
+}
+
+// Look for a child member (doesn't include base classes, but it does include
+// their members) in the type hierarchy. Returns an index path into "clang_type"
+// on how to reach the appropriate member.
+//
+// class A
+// {
+// public:
+// int m_a;
+// int m_b;
+// };
+//
+// class B
+// {
+// };
+//
+// class C :
+// public B,
+// public A
+// {
+// };
+//
+// If we have a clang type that describes "class C", and we wanted to looked
+// "m_b" in it:
+//
+// With omit_empty_base_classes == false we would get an integer array back with:
+// { 1, 1 }
+// The first index 1 is the child index for "class A" within class C
+// The second index 1 is the child index for "m_b" within class A
+//
+// With omit_empty_base_classes == true we would get an integer array back with:
+// { 0, 1 }
+// The first index 0 is the child index for "class A" within class C (since class B doesn't have any members it doesn't count)
+// The second index 1 is the child index for "m_b" within class A
+
+size_t
+CompilerType::GetIndexOfChildMemberWithName (const char *name,
+ bool omit_empty_base_classes,
+ std::vector<uint32_t>& child_indexes) const
+{
+ if (IsValid() && name && name[0])
+ {
+ return m_type_system->GetIndexOfChildMemberWithName(m_type, name, omit_empty_base_classes, child_indexes);
+ }
+ return 0;
+}
+
+size_t
+CompilerType::GetNumTemplateArguments () const
+{
+ if (IsValid())
+ {
+ return m_type_system->GetNumTemplateArguments(m_type);
+ }
+ return 0;
+}
+
+CompilerType
+CompilerType::GetTemplateArgument (size_t idx,
+ lldb::TemplateArgumentKind &kind) const
+{
+ if (IsValid())
+ {
+ return m_type_system->GetTemplateArgument(m_type, idx, kind);
+ }
+ return CompilerType();
+}
+
+CompilerType
+CompilerType::GetTypeForFormatters () const
+{
+ if (IsValid())
+ return m_type_system->GetTypeForFormatters(m_type);
+ return CompilerType();
+}
+
+LazyBool
+CompilerType::ShouldPrintAsOneLiner (ValueObject* valobj) const
+{
+ if (IsValid())
+ return m_type_system->ShouldPrintAsOneLiner(m_type, valobj);
+ return eLazyBoolCalculate;
+}
+
+bool
+CompilerType::IsMeaninglessWithoutDynamicResolution () const
+{
+ if (IsValid())
+ return m_type_system->IsMeaninglessWithoutDynamicResolution(m_type);
+ return false;
+}
+
+// Get the index of the child of "clang_type" whose name matches. This function
+// doesn't descend into the children, but only looks one level deep and name
+// matches can include base class names.
+
+uint32_t
+CompilerType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_classes) const
+{
+ if (IsValid() && name && name[0])
+ {
+ return m_type_system->GetIndexOfChildWithName(m_type, name, omit_empty_base_classes);
+ }
+ return UINT32_MAX;
+}
+
+size_t
+CompilerType::ConvertStringToFloatValue (const char *s, uint8_t *dst, size_t dst_size) const
+{
+ if (IsValid())
+ return m_type_system->ConvertStringToFloatValue(m_type, s, dst, dst_size);
+ return 0;
+}
+
+
+
+//----------------------------------------------------------------------
+// Dumping types
+//----------------------------------------------------------------------
+#define DEPTH_INCREMENT 2
+
+void
+CompilerType::DumpValue (ExecutionContext *exe_ctx,
+ Stream *s,
+ lldb::Format format,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t data_byte_offset,
+ size_t data_byte_size,
+ uint32_t bitfield_bit_size,
+ uint32_t bitfield_bit_offset,
+ bool show_types,
+ bool show_summary,
+ bool verbose,
+ uint32_t depth)
+{
+ if (!IsValid())
+ return;
+ m_type_system->DumpValue(m_type, exe_ctx, s, format, data, data_byte_offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset, show_types, show_summary, verbose, depth);
+}
+
+
+
+
+bool
+CompilerType::DumpTypeValue (Stream *s,
+ lldb::Format format,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t byte_offset,
+ size_t byte_size,
+ uint32_t bitfield_bit_size,
+ uint32_t bitfield_bit_offset,
+ ExecutionContextScope *exe_scope)
+{
+ if (!IsValid())
+ return false;
+ return m_type_system->DumpTypeValue(m_type, s, format, data, byte_offset, byte_size, bitfield_bit_size, bitfield_bit_offset, exe_scope);
+}
+
+
+
+void
+CompilerType::DumpSummary (ExecutionContext *exe_ctx,
+ Stream *s,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t data_byte_offset,
+ size_t data_byte_size)
+{
+ if (IsValid())
+ m_type_system->DumpSummary(m_type, exe_ctx, s, data, data_byte_offset, data_byte_size);
+}
+
+void
+CompilerType::DumpTypeDescription () const
+{
+ if (IsValid())
+ m_type_system->DumpTypeDescription(m_type);
+}
+
+void
+CompilerType::DumpTypeDescription (Stream *s) const
+{
+ if (IsValid())
+ {
+ m_type_system->DumpTypeDescription(m_type, s);
+ }
+}
+
+bool
+CompilerType::GetValueAsScalar (const lldb_private::DataExtractor &data,
+ lldb::offset_t data_byte_offset,
+ size_t data_byte_size,
+ Scalar &value) const
+{
+ if (!IsValid())
+ return false;
+
+ if (IsAggregateType ())
+ {
+ return false; // Aggregate types don't have scalar values
+ }
+ else
+ {
+ uint64_t count = 0;
+ lldb::Encoding encoding = GetEncoding (count);
+
+ if (encoding == lldb::eEncodingInvalid || count != 1)
+ return false;
+
+ const uint64_t byte_size = GetByteSize(nullptr);
+ lldb::offset_t offset = data_byte_offset;
+ switch (encoding)
+ {
+ case lldb::eEncodingInvalid:
+ break;
+ case lldb::eEncodingVector:
+ break;
+ case lldb::eEncodingUint:
+ if (byte_size <= sizeof(unsigned long long))
+ {
+ uint64_t uval64 = data.GetMaxU64 (&offset, byte_size);
+ if (byte_size <= sizeof(unsigned int))
+ {
+ value = (unsigned int)uval64;
+ return true;
+ }
+ else if (byte_size <= sizeof(unsigned long))
+ {
+ value = (unsigned long)uval64;
+ return true;
+ }
+ else if (byte_size <= sizeof(unsigned long long))
+ {
+ value = (unsigned long long )uval64;
+ return true;
+ }
+ else
+ value.Clear();
+ }
+ break;
+
+ case lldb::eEncodingSint:
+ if (byte_size <= sizeof(long long))
+ {
+ int64_t sval64 = data.GetMaxS64 (&offset, byte_size);
+ if (byte_size <= sizeof(int))
+ {
+ value = (int)sval64;
+ return true;
+ }
+ else if (byte_size <= sizeof(long))
+ {
+ value = (long)sval64;
+ return true;
+ }
+ else if (byte_size <= sizeof(long long))
+ {
+ value = (long long )sval64;
+ return true;
+ }
+ else
+ value.Clear();
+ }
+ break;
+
+ case lldb::eEncodingIEEE754:
+ if (byte_size <= sizeof(long double))
+ {
+ uint32_t u32;
+ uint64_t u64;
+ if (byte_size == sizeof(float))
+ {
+ if (sizeof(float) == sizeof(uint32_t))
+ {
+ u32 = data.GetU32(&offset);
+ value = *((float *)&u32);
+ return true;
+ }
+ else if (sizeof(float) == sizeof(uint64_t))
+ {
+ u64 = data.GetU64(&offset);
+ value = *((float *)&u64);
+ return true;
+ }
+ }
+ else
+ if (byte_size == sizeof(double))
+ {
+ if (sizeof(double) == sizeof(uint32_t))
+ {
+ u32 = data.GetU32(&offset);
+ value = *((double *)&u32);
+ return true;
+ }
+ else if (sizeof(double) == sizeof(uint64_t))
+ {
+ u64 = data.GetU64(&offset);
+ value = *((double *)&u64);
+ return true;
+ }
+ }
+ else
+ if (byte_size == sizeof(long double))
+ {
+ if (sizeof(long double) == sizeof(uint32_t))
+ {
+ u32 = data.GetU32(&offset);
+ value = *((long double *)&u32);
+ return true;
+ }
+ else if (sizeof(long double) == sizeof(uint64_t))
+ {
+ u64 = data.GetU64(&offset);
+ value = *((long double *)&u64);
+ return true;
+ }
+ }
+ }
+ break;
+ }
+ }
+ return false;
+}
+
+bool
+CompilerType::SetValueFromScalar (const Scalar &value, Stream &strm)
+{
+ if (!IsValid())
+ return false;
+
+ // Aggregate types don't have scalar values
+ if (!IsAggregateType ())
+ {
+ strm.GetFlags().Set(Stream::eBinary);
+ uint64_t count = 0;
+ lldb::Encoding encoding = GetEncoding (count);
+
+ if (encoding == lldb::eEncodingInvalid || count != 1)
+ return false;
+
+ const uint64_t bit_width = GetBitSize(nullptr);
+ // This function doesn't currently handle non-byte aligned assignments
+ if ((bit_width % 8) != 0)
+ return false;
+
+ const uint64_t byte_size = (bit_width + 7 ) / 8;
+ switch (encoding)
+ {
+ case lldb::eEncodingInvalid:
+ break;
+ case lldb::eEncodingVector:
+ break;
+ case lldb::eEncodingUint:
+ switch (byte_size)
+ {
+ case 1: strm.PutHex8(value.UInt()); return true;
+ case 2: strm.PutHex16(value.UInt()); return true;
+ case 4: strm.PutHex32(value.UInt()); return true;
+ case 8: strm.PutHex64(value.ULongLong()); return true;
+ default:
+ break;
+ }
+ break;
+
+ case lldb::eEncodingSint:
+ switch (byte_size)
+ {
+ case 1: strm.PutHex8(value.SInt()); return true;
+ case 2: strm.PutHex16(value.SInt()); return true;
+ case 4: strm.PutHex32(value.SInt()); return true;
+ case 8: strm.PutHex64(value.SLongLong()); return true;
+ default:
+ break;
+ }
+ break;
+
+ case lldb::eEncodingIEEE754:
+ if (byte_size <= sizeof(long double))
+ {
+ if (byte_size == sizeof(float))
+ {
+ strm.PutFloat(value.Float());
+ return true;
+ }
+ else
+ if (byte_size == sizeof(double))
+ {
+ strm.PutDouble(value.Double());
+ return true;
+ }
+ else
+ if (byte_size == sizeof(long double))
+ {
+ strm.PutDouble(value.LongDouble());
+ return true;
+ }
+ }
+ break;
+ }
+ }
+ return false;
+}
+
+bool
+CompilerType::ReadFromMemory (lldb_private::ExecutionContext *exe_ctx,
+ lldb::addr_t addr,
+ AddressType address_type,
+ lldb_private::DataExtractor &data)
+{
+ if (!IsValid())
+ return false;
+
+ // Can't convert a file address to anything valid without more
+ // context (which Module it came from)
+ if (address_type == eAddressTypeFile)
+ return false;
+
+ if (!GetCompleteType())
+ return false;
+
+ const uint64_t byte_size = GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+ if (data.GetByteSize() < byte_size)
+ {
+ lldb::DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0'));
+ data.SetData(data_sp);
+ }
+
+ uint8_t* dst = const_cast<uint8_t*>(data.PeekData(0, byte_size));
+ if (dst != nullptr)
+ {
+ if (address_type == eAddressTypeHost)
+ {
+ if (addr == 0)
+ return false;
+ // The address is an address in this process, so just copy it
+ memcpy (dst, (uint8_t*)nullptr + addr, byte_size);
+ return true;
+ }
+ else
+ {
+ Process *process = nullptr;
+ if (exe_ctx)
+ process = exe_ctx->GetProcessPtr();
+ if (process)
+ {
+ Error error;
+ return process->ReadMemory(addr, dst, byte_size, error) == byte_size;
+ }
+ }
+ }
+ return false;
+}
+
+bool
+CompilerType::WriteToMemory (lldb_private::ExecutionContext *exe_ctx,
+ lldb::addr_t addr,
+ AddressType address_type,
+ StreamString &new_value)
+{
+ if (!IsValid())
+ return false;
+
+ // Can't convert a file address to anything valid without more
+ // context (which Module it came from)
+ if (address_type == eAddressTypeFile)
+ return false;
+
+ if (!GetCompleteType())
+ return false;
+
+ const uint64_t byte_size = GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+
+ if (byte_size > 0)
+ {
+ if (address_type == eAddressTypeHost)
+ {
+ // The address is an address in this process, so just copy it
+ memcpy ((void *)addr, new_value.GetData(), byte_size);
+ return true;
+ }
+ else
+ {
+ Process *process = nullptr;
+ if (exe_ctx)
+ process = exe_ctx->GetProcessPtr();
+ if (process)
+ {
+ Error error;
+ return process->WriteMemory(addr, new_value.GetData(), byte_size, error) == byte_size;
+ }
+ }
+ }
+ return false;
+}
+
+//clang::CXXRecordDecl *
+//CompilerType::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t opaque_compiler_qual_type)
+//{
+// if (opaque_compiler_qual_type)
+// return clang::QualType::getFromOpaquePtr(opaque_compiler_qual_type)->getAsCXXRecordDecl();
+// return NULL;
+//}
+
+bool
+lldb_private::operator == (const lldb_private::CompilerType &lhs, const lldb_private::CompilerType &rhs)
+{
+ return lhs.GetTypeSystem() == rhs.GetTypeSystem() && lhs.GetOpaqueQualType() == rhs.GetOpaqueQualType();
+}
+
+
+bool
+lldb_private::operator != (const lldb_private::CompilerType &lhs, const lldb_private::CompilerType &rhs)
+{
+ return lhs.GetTypeSystem() != rhs.GetTypeSystem() || lhs.GetOpaqueQualType() != rhs.GetOpaqueQualType();
+}
+
+
+
diff --git a/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp
index a5f9017..c357a50 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/DWARFCallFrameInfo.cpp
@@ -342,7 +342,7 @@ DWARFCallFrameInfo::GetFDEIndex ()
"error: Invalid fde/cie next entry offset of 0x%x found in cie/fde at 0x%x\n",
next_entry,
current_entry);
- // Don't trust anything in this eh_frame section if we find blatently
+ // Don't trust anything in this eh_frame section if we find blatantly
// invalid data.
m_fde_index.Clear();
m_fde_index_initialized = true;
@@ -354,7 +354,7 @@ DWARFCallFrameInfo::GetFDEIndex ()
"error: Invalid cie offset of 0x%x found in cie/fde at 0x%x\n",
cie_offset,
current_entry);
- // Don't trust anything in this eh_frame section if we find blatently
+ // Don't trust anything in this eh_frame section if we find blatantly
// invalid data.
m_fde_index.Clear();
m_fde_index_initialized = true;
@@ -535,7 +535,7 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
// We only keep enough register locations around to
// unwind what is in our thread, and these are organized
// by the register index in that state, so we need to convert our
- // GCC register number from the EH frame info, to a register index
+ // eh_frame register number from the EH frame info, to a register index
if (unwind_plan.IsValidRowIndex(0) && unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num, reg_location))
row->SetRegisterInfo (reg_num, reg_location);
diff --git a/contrib/llvm/tools/lldb/source/Symbol/DebugMacros.cpp b/contrib/llvm/tools/lldb/source/Symbol/DebugMacros.cpp
new file mode 100644
index 0000000..88a28ba
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Symbol/DebugMacros.cpp
@@ -0,0 +1,65 @@
+//===-- DebugMacros.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/DebugMacros.h"
+
+#include "lldb/Symbol/CompileUnit.h"
+
+using namespace lldb_private;
+
+DebugMacroEntry::DebugMacroEntry(EntryType type,
+ uint32_t line,
+ uint32_t debug_line_file_idx,
+ const char *str)
+ : m_type(type),
+ m_line(line),
+ m_debug_line_file_idx(debug_line_file_idx),
+ m_str(str)
+{ }
+
+DebugMacroEntry::DebugMacroEntry(EntryType type,
+ const DebugMacrosSP &debug_macros_sp)
+ : m_type(type), m_line(0), m_debug_line_file_idx(0), m_debug_macros_sp(debug_macros_sp)
+{ }
+
+const FileSpec&
+DebugMacroEntry::GetFileSpec(CompileUnit *comp_unit) const
+{
+ return comp_unit->GetSupportFiles().GetFileSpecAtIndex(m_debug_line_file_idx);
+}
+
+DebugMacroEntry
+DebugMacroEntry::CreateDefineEntry(uint32_t line, const char *str)
+{
+ return DebugMacroEntry(DebugMacroEntry::DEFINE, line, 0, str);
+}
+
+DebugMacroEntry
+DebugMacroEntry::CreateUndefEntry(uint32_t line, const char *str)
+{
+ return DebugMacroEntry(DebugMacroEntry::UNDEF, line, 0, str);
+}
+
+DebugMacroEntry
+DebugMacroEntry::CreateStartFileEntry(uint32_t line, uint32_t debug_line_file_idx)
+{
+ return DebugMacroEntry(DebugMacroEntry::START_FILE, line, debug_line_file_idx, nullptr);
+}
+
+DebugMacroEntry
+DebugMacroEntry::CreateEndFileEntry()
+{
+ return DebugMacroEntry(DebugMacroEntry::END_FILE, 0, 0, nullptr);
+}
+
+DebugMacroEntry
+DebugMacroEntry::CreateIndirectEntry(const DebugMacrosSP &debug_macros_sp)
+{
+ return DebugMacroEntry(DebugMacroEntry::INDIRECT, debug_macros_sp);
+}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp b/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp
index 000df72..4c96b1a 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/FuncUnwinders.cpp
@@ -10,6 +10,7 @@
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Address.h"
#include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/CompactUnwindInfo.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -37,6 +38,7 @@ FuncUnwinders::FuncUnwinders (UnwindTable& unwind_table, AddressRange range) :
m_unwind_plan_eh_frame_sp (),
m_unwind_plan_eh_frame_augmented_sp (),
m_unwind_plan_compact_unwind (),
+ m_unwind_plan_arm_unwind_sp (),
m_unwind_plan_fast_sp (),
m_unwind_plan_arch_default_sp (),
m_unwind_plan_arch_default_at_func_entry_sp (),
@@ -44,6 +46,7 @@ FuncUnwinders::FuncUnwinders (UnwindTable& unwind_table, AddressRange range) :
m_tried_unwind_plan_eh_frame (false),
m_tried_unwind_plan_eh_frame_augmented (false),
m_tried_unwind_plan_compact_unwind (false),
+ m_tried_unwind_plan_arm_unwind (false),
m_tried_unwind_fast (false),
m_tried_unwind_arch_default (false),
m_tried_unwind_arch_default_at_func_entry (false),
@@ -65,12 +68,18 @@ FuncUnwinders::GetUnwindPlanAtCallSite (Target &target, int current_offset)
Mutex::Locker locker (m_mutex);
UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, current_offset);
- if (unwind_plan_sp.get() == nullptr)
- {
- unwind_plan_sp = GetCompactUnwindUnwindPlan (target, current_offset);
- }
+ if (unwind_plan_sp)
+ return unwind_plan_sp;
+
+ unwind_plan_sp = GetCompactUnwindUnwindPlan (target, current_offset);
+ if (unwind_plan_sp)
+ return unwind_plan_sp;
+
+ unwind_plan_sp = GetArmUnwindUnwindPlan (target, current_offset);
+ if (unwind_plan_sp)
+ return unwind_plan_sp;
- return unwind_plan_sp;
+ return nullptr;
}
UnwindPlanSP
@@ -127,6 +136,30 @@ FuncUnwinders::GetEHFrameUnwindPlan (Target &target, int current_offset)
}
UnwindPlanSP
+FuncUnwinders::GetArmUnwindUnwindPlan (Target &target, int current_offset)
+{
+ if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind)
+ return m_unwind_plan_arm_unwind_sp;
+
+ Mutex::Locker lock (m_mutex);
+ m_tried_unwind_plan_arm_unwind = true;
+ if (m_range.GetBaseAddress().IsValid())
+ {
+ Address current_pc (m_range.GetBaseAddress ());
+ if (current_offset != -1)
+ current_pc.SetOffset (current_pc.GetOffset() + current_offset);
+ ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo();
+ if (arm_unwind_info)
+ {
+ m_unwind_plan_arm_unwind_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+ if (!arm_unwind_info->GetUnwindPlan (target, current_pc, *m_unwind_plan_arm_unwind_sp))
+ m_unwind_plan_arm_unwind_sp.reset();
+ }
+ }
+ return m_unwind_plan_arm_unwind_sp;
+}
+
+UnwindPlanSP
FuncUnwinders::GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, int current_offset)
{
if (m_unwind_plan_eh_frame_augmented_sp.get() || m_tried_unwind_plan_eh_frame_augmented)
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Function.cpp b/contrib/llvm/tools/lldb/source/Symbol/Function.cpp
index 77448d4..33cc0c4 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Function.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Function.cpp
@@ -12,11 +12,12 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/Host.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Target/Language.h"
#include "llvm/Support/Casting.h"
using namespace lldb;
@@ -217,7 +218,7 @@ Function::Function
m_mangled (mangled),
m_block (func_uid),
m_range (range),
- m_frame_base (),
+ m_frame_base (nullptr),
m_flags (),
m_prologue_byte_size (0)
{
@@ -241,7 +242,7 @@ Function::Function
m_mangled (ConstString(mangled), true),
m_block (func_uid),
m_range (range),
- m_frame_base (),
+ m_frame_base (nullptr),
m_flags (),
m_prologue_byte_size (0)
{
@@ -466,6 +467,32 @@ Function::MemorySize () const
return mem_size;
}
+bool
+Function::GetIsOptimized ()
+{
+ bool result = false;
+
+ // Currently optimization is only indicted by the
+ // vendor extension DW_AT_APPLE_optimized which
+ // is set on a compile unit level.
+ if (m_comp_unit)
+ {
+ result = m_comp_unit->GetIsOptimized();
+ }
+ return result;
+}
+
+bool
+Function::IsTopLevelFunction ()
+{
+ bool result = false;
+
+ if (Language* language = Language::FindPlugin(GetLanguage()))
+ result = language->IsTopLevelFunction(*this);
+
+ return result;
+}
+
ConstString
Function::GetDisplayName () const
{
@@ -474,27 +501,24 @@ Function::GetDisplayName () const
return m_mangled.GetDisplayDemangledName(GetLanguage());
}
-clang::DeclContext *
-Function::GetClangDeclContext()
+CompilerDeclContext
+Function::GetDeclContext()
{
- SymbolContext sc;
-
- CalculateSymbolContext (&sc);
-
- if (!sc.module_sp)
- return nullptr;
-
- SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor();
-
- if (!sym_vendor)
- return nullptr;
-
- SymbolFile *sym_file = sym_vendor->GetSymbolFile();
-
- if (!sym_file)
- return nullptr;
-
- return sym_file->GetClangDeclContextForTypeUID (sc, m_uid);
+ ModuleSP module_sp = CalculateSymbolContextModule ();
+
+ if (module_sp)
+ {
+ SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
+
+ if (sym_vendor)
+ {
+ SymbolFile *sym_file = sym_vendor->GetSymbolFile();
+
+ if (sym_file)
+ return sym_file->GetDeclContextForUID (GetID());
+ }
+ }
+ return CompilerDeclContext();
}
Type*
@@ -530,13 +554,13 @@ Function::GetType() const
return m_type;
}
-ClangASTType
-Function::GetClangType()
+CompilerType
+Function::GetCompilerType()
{
Type *function_type = GetType();
if (function_type)
- return function_type->GetClangFullType();
- return ClangASTType();
+ return function_type->GetFullCompilerType ();
+ return CompilerType();
}
uint32_t
diff --git a/contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp
new file mode 100644
index 0000000..4ba51f7
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Symbol/GoASTContext.cpp
@@ -0,0 +1,1519 @@
+//===-- GoASTContext.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mutex>
+#include <utility>
+#include <vector>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/GoASTContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
+
+#include "Plugins/ExpressionParser/Go/GoUserExpression.h"
+#include "Plugins/SymbolFile/DWARF/DWARFASTParserGo.h"
+
+using namespace lldb;
+
+namespace lldb_private
+{
+class GoArray;
+class GoFunction;
+class GoStruct;
+
+class GoType
+{
+ public:
+ enum
+ {
+ KIND_BOOL = 1,
+ KIND_INT = 2,
+ KIND_INT8 = 3,
+ KIND_INT16 = 4,
+ KIND_INT32 = 5,
+ KIND_INT64 = 6,
+ KIND_UINT = 7,
+ KIND_UINT8 = 8,
+ KIND_UINT16 = 9,
+ KIND_UINT32 = 10,
+ KIND_UINT64 = 11,
+ KIND_UINTPTR = 12,
+ KIND_FLOAT32 = 13,
+ KIND_FLOAT64 = 14,
+ KIND_COMPLEX64 = 15,
+ KIND_COMPLEX128 = 16,
+ KIND_ARRAY = 17,
+ KIND_CHAN = 18,
+ KIND_FUNC = 19,
+ KIND_INTERFACE = 20,
+ KIND_MAP = 21,
+ KIND_PTR = 22,
+ KIND_SLICE = 23,
+ KIND_STRING = 24,
+ KIND_STRUCT = 25,
+ KIND_UNSAFEPOINTER = 26,
+ KIND_LLDB_VOID, // Extension for LLDB, not used by go runtime.
+ KIND_MASK = (1 << 5) - 1,
+ KIND_DIRECT_IFACE = 1 << 5
+ };
+ GoType(int kind, const ConstString &name)
+ : m_kind(kind & KIND_MASK)
+ , m_name(name)
+ {
+ if (m_kind == KIND_FUNC)
+ m_kind = KIND_FUNC;
+ }
+ virtual ~GoType() {}
+
+ int
+ GetGoKind() const
+ {
+ return m_kind;
+ }
+ const ConstString &
+ GetName() const
+ {
+ return m_name;
+ }
+ virtual CompilerType
+ GetElementType() const
+ {
+ return CompilerType();
+ }
+
+ bool
+ IsTypedef() const
+ {
+ switch (m_kind)
+ {
+ case KIND_CHAN:
+ case KIND_MAP:
+ case KIND_INTERFACE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ GoArray *GetArray();
+ GoFunction *GetFunction();
+ GoStruct *GetStruct();
+
+ private:
+ int m_kind;
+ ConstString m_name;
+ GoType(const GoType &) = delete;
+ const GoType &operator=(const GoType &) = delete;
+};
+
+class GoElem : public GoType
+{
+ public:
+ GoElem(int kind, const ConstString &name, const CompilerType &elem)
+ : GoType(kind, name)
+ , m_elem(elem)
+ {
+ }
+ virtual CompilerType
+ GetElementType() const
+ {
+ return m_elem;
+ }
+
+ private:
+ // TODO: should we store this differently?
+ CompilerType m_elem;
+
+ GoElem(const GoElem &) = delete;
+ const GoElem &operator=(const GoElem &) = delete;
+};
+
+class GoArray : public GoElem
+{
+ public:
+ GoArray(const ConstString &name, uint64_t length, const CompilerType &elem)
+ : GoElem(KIND_ARRAY, name, elem)
+ , m_length(length)
+ {
+ }
+
+ uint64_t
+ GetLength() const
+ {
+ return m_length;
+ }
+
+ private:
+ uint64_t m_length;
+ GoArray(const GoArray &) = delete;
+ const GoArray &operator=(const GoArray &) = delete;
+};
+
+class GoFunction : public GoType
+{
+ public:
+ GoFunction(const ConstString &name, bool is_variadic)
+ : GoType(KIND_FUNC, name)
+ , m_is_variadic(is_variadic)
+ {
+ }
+
+ bool
+ IsVariadic() const
+ {
+ return m_is_variadic;
+ }
+
+ private:
+ bool m_is_variadic;
+ GoFunction(const GoFunction &) = delete;
+ const GoFunction &operator=(const GoFunction &) = delete;
+};
+
+class GoStruct : public GoType
+{
+ public:
+ struct Field
+ {
+ Field(const ConstString &name, const CompilerType &type, uint64_t offset)
+ : m_name(name)
+ , m_type(type)
+ , m_byte_offset(offset)
+ {
+ }
+ ConstString m_name;
+ CompilerType m_type;
+ uint64_t m_byte_offset;
+ };
+
+ GoStruct(int kind, const ConstString &name, int64_t byte_size)
+ : GoType(kind == 0 ? KIND_STRUCT : kind, name), m_is_complete(false), m_byte_size(byte_size)
+ {
+ }
+
+ uint32_t
+ GetNumFields() const
+ {
+ return m_fields.size();
+ }
+
+ const Field *
+ GetField(uint32_t i) const
+ {
+ if (i < m_fields.size())
+ return &m_fields[i];
+ return nullptr;
+ }
+
+ void
+ AddField(const ConstString &name, const CompilerType &type, uint64_t offset)
+ {
+ m_fields.push_back(Field(name, type, offset));
+ }
+
+ bool
+ IsComplete() const
+ {
+ return m_is_complete;
+ }
+
+ void
+ SetComplete()
+ {
+ m_is_complete = true;
+ }
+
+ int64_t
+ GetByteSize() const
+ {
+ return m_byte_size;
+ }
+
+ private:
+ bool m_is_complete;
+ int64_t m_byte_size;
+ std::vector<Field> m_fields;
+
+ GoStruct(const GoStruct &) = delete;
+ const GoStruct &operator=(const GoStruct &) = delete;
+};
+
+GoArray *
+GoType::GetArray()
+{
+ if (m_kind == KIND_ARRAY)
+ {
+ return static_cast<GoArray *>(this);
+ }
+ return nullptr;
+}
+
+GoFunction *
+GoType::GetFunction()
+{
+ if (m_kind == KIND_FUNC)
+ {
+ return static_cast<GoFunction *>(this);
+ }
+ return nullptr;
+}
+
+GoStruct *
+GoType::GetStruct()
+{
+ switch (m_kind)
+ {
+ case KIND_STRING:
+ case KIND_STRUCT:
+ case KIND_SLICE:
+ return static_cast<GoStruct *>(this);
+ }
+ return nullptr;
+}
+} // namespace lldb_private
+using namespace lldb_private;
+
+GoASTContext::GoASTContext()
+ : TypeSystem(eKindGo)
+ , m_pointer_byte_size(0)
+ , m_int_byte_size(0)
+ , m_types(new TypeMap)
+{
+}
+GoASTContext::~GoASTContext()
+{
+}
+
+//------------------------------------------------------------------
+// PluginInterface functions
+//------------------------------------------------------------------
+
+ConstString
+GoASTContext::GetPluginNameStatic()
+{
+ return ConstString("go");
+}
+
+ConstString
+GoASTContext::GetPluginName()
+{
+ return GoASTContext::GetPluginNameStatic();
+}
+
+uint32_t
+GoASTContext::GetPluginVersion()
+{
+ return 1;
+}
+
+lldb::TypeSystemSP
+GoASTContext::CreateInstance (lldb::LanguageType language, Module *module, Target *target)
+{
+ if (language == eLanguageTypeGo)
+ {
+ ArchSpec arch;
+ std::shared_ptr<GoASTContext> go_ast_sp;
+ if (module)
+ {
+ arch = module->GetArchitecture();
+ go_ast_sp = std::shared_ptr<GoASTContext>(new GoASTContext);
+ }
+ else if (target)
+ {
+ arch = target->GetArchitecture();
+ go_ast_sp = std::shared_ptr<GoASTContextForExpr>(new GoASTContextForExpr(target->shared_from_this()));
+ }
+
+ if (arch.IsValid())
+ {
+ go_ast_sp->SetAddressByteSize(arch.GetAddressByteSize());
+ return go_ast_sp;
+ }
+ }
+ return lldb::TypeSystemSP();
+}
+
+void
+GoASTContext::EnumerateSupportedLanguages(std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions)
+{
+ static std::vector<lldb::LanguageType> s_supported_languages_for_types({
+ lldb::eLanguageTypeGo});
+
+ static std::vector<lldb::LanguageType> s_supported_languages_for_expressions({});
+
+ languages_for_types.insert(s_supported_languages_for_types.begin(), s_supported_languages_for_types.end());
+ languages_for_expressions.insert(s_supported_languages_for_expressions.begin(), s_supported_languages_for_expressions.end());
+}
+
+
+void
+GoASTContext::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "AST context plug-in",
+ CreateInstance,
+ EnumerateSupportedLanguages);
+}
+
+void
+GoASTContext::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+//----------------------------------------------------------------------
+// Tests
+//----------------------------------------------------------------------
+
+bool
+GoASTContext::IsArrayType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size, bool *is_incomplete)
+{
+ if (element_type)
+ element_type->Clear();
+ if (size)
+ *size = 0;
+ if (is_incomplete)
+ *is_incomplete = false;
+ GoArray *array = static_cast<GoType *>(type)->GetArray();
+ if (array)
+ {
+ if (size)
+ *size = array->GetLength();
+ if (element_type)
+ *element_type = array->GetElementType();
+ return true;
+ }
+ return false;
+}
+
+bool
+GoASTContext::IsVectorType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size)
+{
+ if (element_type)
+ element_type->Clear();
+ if (size)
+ *size = 0;
+ return false;
+}
+
+bool
+GoASTContext::IsAggregateType(lldb::opaque_compiler_type_t type)
+{
+ int kind = static_cast<GoType *>(type)->GetGoKind();
+ if (kind < GoType::KIND_ARRAY)
+ return false;
+ if (kind == GoType::KIND_PTR)
+ return false;
+ if (kind == GoType::KIND_CHAN)
+ return false;
+ if (kind == GoType::KIND_MAP)
+ return false;
+ if (kind == GoType::KIND_STRING)
+ return false;
+ if (kind == GoType::KIND_UNSAFEPOINTER)
+ return false;
+ return true;
+}
+
+bool
+GoASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsCharType(lldb::opaque_compiler_type_t type)
+{
+ // Go's DWARF doesn't distinguish between rune and int32.
+ return false;
+}
+
+bool
+GoASTContext::IsCompleteType(lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return false;
+ GoType *t = static_cast<GoType *>(type);
+ if (GoStruct *s = t->GetStruct())
+ return s->IsComplete();
+ if (t->IsTypedef() || t->GetGoKind() == GoType::KIND_PTR)
+ return t->GetElementType().IsCompleteType();
+ return true;
+}
+
+bool
+GoASTContext::IsConst(lldb::opaque_compiler_type_t type)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsDefined(lldb::opaque_compiler_type_t type)
+{
+ return type != nullptr;
+}
+
+bool
+GoASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex)
+{
+ int kind = static_cast<GoType *>(type)->GetGoKind();
+ if (kind >= GoType::KIND_FLOAT32 && kind <= GoType::KIND_COMPLEX128)
+ {
+ if (kind >= GoType::KIND_COMPLEX64)
+ {
+ is_complex = true;
+ count = 2;
+ }
+ else
+ {
+ is_complex = false;
+ count = 1;
+ }
+ return true;
+ }
+ count = 0;
+ is_complex = false;
+ return false;
+}
+
+bool
+GoASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, bool *is_variadic_ptr)
+{
+ GoFunction *func = static_cast<GoType *>(type)->GetFunction();
+ if (func)
+ {
+ if (is_variadic_ptr)
+ *is_variadic_ptr = func->IsVariadic();
+ return true;
+ }
+ if (is_variadic_ptr)
+ *is_variadic_ptr = false;
+ return false;
+}
+
+uint32_t
+GoASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, CompilerType *base_type_ptr)
+{
+ return false;
+}
+
+size_t
+GoASTContext::GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type)
+{
+ return 0;
+}
+
+CompilerType
+GoASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, const size_t index)
+{
+ return CompilerType();
+}
+
+bool
+GoASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type)
+{
+ return IsFunctionType(type);
+}
+
+bool
+GoASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed)
+{
+ is_signed = false;
+ // TODO: Is bool an integer?
+ if (type)
+ {
+ int kind = static_cast<GoType *>(type)->GetGoKind();
+ if (kind <= GoType::KIND_UINTPTR)
+ {
+ is_signed = (kind != GoType::KIND_BOOL) & (kind <= GoType::KIND_INT64);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+GoASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
+ CompilerType *target_type, // Can pass NULL
+ bool check_cplusplus, bool check_objc)
+{
+ if (target_type)
+ target_type->Clear();
+ if (type)
+ return static_cast<GoType *>(type)->GetGoKind() == GoType::KIND_INTERFACE;
+ return false;
+}
+
+bool
+GoASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsPointerType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type)
+{
+ if (!type)
+ return false;
+ GoType *t = static_cast<GoType *>(type);
+ if (pointee_type)
+ {
+ *pointee_type = t->GetElementType();
+ }
+ switch (t->GetGoKind())
+ {
+ case GoType::KIND_PTR:
+ case GoType::KIND_UNSAFEPOINTER:
+ case GoType::KIND_CHAN:
+ case GoType::KIND_MAP:
+ // TODO: is function a pointer?
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+GoASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type)
+{
+ return IsPointerType(type, pointee_type);
+}
+
+bool
+GoASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool *is_rvalue)
+{
+ return false;
+}
+
+bool
+GoASTContext::IsScalarType(lldb::opaque_compiler_type_t type)
+{
+ return !IsAggregateType(type);
+}
+
+bool
+GoASTContext::IsTypedefType(lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ return static_cast<GoType *>(type)->IsTypedef();
+ return false;
+}
+
+bool
+GoASTContext::IsVoidType(lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return false;
+ return static_cast<GoType *>(type)->GetGoKind() == GoType::KIND_LLDB_VOID;
+}
+
+bool
+GoASTContext::SupportsLanguage (lldb::LanguageType language)
+{
+ return language == eLanguageTypeGo;
+}
+
+//----------------------------------------------------------------------
+// Type Completion
+//----------------------------------------------------------------------
+
+bool
+GoASTContext::GetCompleteType(lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return false;
+ GoType *t = static_cast<GoType *>(type);
+ if (t->IsTypedef() || t->GetGoKind() == GoType::KIND_PTR || t->GetArray())
+ return t->GetElementType().GetCompleteType();
+ if (GoStruct *s = t->GetStruct())
+ {
+ if (s->IsComplete())
+ return true;
+ CompilerType compiler_type(this, s);
+ SymbolFile *symbols = GetSymbolFile();
+ return symbols && symbols->CompleteType(compiler_type);
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------
+// AST related queries
+//----------------------------------------------------------------------
+
+uint32_t
+GoASTContext::GetPointerByteSize()
+{
+ return m_pointer_byte_size;
+}
+
+//----------------------------------------------------------------------
+// Accessors
+//----------------------------------------------------------------------
+
+ConstString
+GoASTContext::GetTypeName(lldb::opaque_compiler_type_t type)
+{
+ if (type)
+ return static_cast<GoType *>(type)->GetName();
+ return ConstString();
+}
+
+uint32_t
+GoASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type)
+{
+ if (pointee_or_element_compiler_type)
+ pointee_or_element_compiler_type->Clear();
+ if (!type)
+ return 0;
+ GoType *t = static_cast<GoType *>(type);
+ if (pointee_or_element_compiler_type)
+ *pointee_or_element_compiler_type = t->GetElementType();
+ int kind = t->GetGoKind();
+ if (kind == GoType::KIND_ARRAY)
+ return eTypeHasChildren | eTypeIsArray;
+ if (kind < GoType::KIND_ARRAY)
+ {
+ uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue;
+ if (kind < GoType::KIND_FLOAT32)
+ {
+ builtin_type_flags |= eTypeIsInteger | eTypeIsScalar;
+ if (kind >= GoType::KIND_INT && kind <= GoType::KIND_INT64)
+ builtin_type_flags |= eTypeIsSigned;
+ }
+ else
+ {
+ builtin_type_flags |= eTypeIsFloat;
+ if (kind < GoType::KIND_COMPLEX64)
+ builtin_type_flags |= eTypeIsComplex;
+ else
+ builtin_type_flags |= eTypeIsScalar;
+ }
+ return builtin_type_flags;
+ }
+ if (kind == GoType::KIND_STRING)
+ return eTypeHasValue | eTypeIsBuiltIn;
+ if (kind == GoType::KIND_FUNC)
+ return eTypeIsFuncPrototype | eTypeHasValue;
+ if (IsPointerType(type))
+ return eTypeIsPointer | eTypeHasValue | eTypeHasChildren;
+ if (kind == GoType::KIND_LLDB_VOID)
+ return 0;
+ return eTypeHasChildren | eTypeIsStructUnion;
+}
+
+lldb::TypeClass
+GoASTContext::GetTypeClass(lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return eTypeClassInvalid;
+ int kind = static_cast<GoType *>(type)->GetGoKind();
+ if (kind == GoType::KIND_FUNC)
+ return eTypeClassFunction;
+ if (IsPointerType(type))
+ return eTypeClassPointer;
+ if (kind < GoType::KIND_COMPLEX64)
+ return eTypeClassBuiltin;
+ if (kind <= GoType::KIND_COMPLEX128)
+ return eTypeClassComplexFloat;
+ if (kind == GoType::KIND_LLDB_VOID)
+ return eTypeClassInvalid;
+ return eTypeClassStruct;
+}
+
+lldb::BasicType
+GoASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type)
+{
+ ConstString name = GetTypeName(type);
+ if (name)
+ {
+ typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap;
+ static TypeNameToBasicTypeMap g_type_map;
+ static std::once_flag g_once_flag;
+ std::call_once(g_once_flag, [](){
+ // "void"
+ g_type_map.Append(ConstString("void").GetCString(), eBasicTypeVoid);
+ // "int"
+ g_type_map.Append(ConstString("int").GetCString(), eBasicTypeInt);
+ g_type_map.Append(ConstString("uint").GetCString(), eBasicTypeUnsignedInt);
+
+ // Miscellaneous
+ g_type_map.Append(ConstString("bool").GetCString(), eBasicTypeBool);
+
+ // Others. Should these map to C types?
+ g_type_map.Append(ConstString("byte").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("uint8").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("uint16").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("uint32").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("uint64").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("int8").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("int16").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("int32").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("int64").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("float32").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("float64").GetCString(), eBasicTypeOther);
+ g_type_map.Append(ConstString("uintptr").GetCString(), eBasicTypeOther);
+
+ g_type_map.Sort();
+ });
+
+ return g_type_map.Find(name.GetCString(), eBasicTypeInvalid);
+ }
+ return eBasicTypeInvalid;
+}
+
+lldb::LanguageType
+GoASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type)
+{
+ return lldb::eLanguageTypeGo;
+}
+
+unsigned
+GoASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type)
+{
+ return 0;
+}
+
+//----------------------------------------------------------------------
+// Creating related types
+//----------------------------------------------------------------------
+
+CompilerType
+GoASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, uint64_t *stride)
+{
+ GoArray *array = static_cast<GoType *>(type)->GetArray();
+ if (array)
+ {
+ if (stride)
+ {
+ *stride = array->GetElementType().GetByteSize(nullptr);
+ }
+ return array->GetElementType();
+ }
+ return CompilerType();
+}
+
+CompilerType
+GoASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type)
+{
+ GoType *t = static_cast<GoType *>(type);
+ if (t->IsTypedef())
+ return t->GetElementType();
+ return CompilerType(this, type);
+}
+
+CompilerType
+GoASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type)
+{
+ return CompilerType(this, type);
+}
+
+// Returns -1 if this isn't a function of if the function doesn't have a prototype
+// Returns a value >= 0 if there is a prototype.
+int
+GoASTContext::GetFunctionArgumentCount(lldb::opaque_compiler_type_t type)
+{
+ return GetNumberOfFunctionArguments(type);
+}
+
+CompilerType
+GoASTContext::GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, size_t idx)
+{
+ return GetFunctionArgumentAtIndex(type, idx);
+}
+
+CompilerType
+GoASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type)
+{
+ CompilerType result;
+ if (type)
+ {
+ GoType *t = static_cast<GoType *>(type);
+ if (t->GetGoKind() == GoType::KIND_FUNC)
+ result = t->GetElementType();
+ }
+ return result;
+}
+
+size_t
+GoASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type)
+{
+ return 0;
+}
+
+TypeMemberFunctionImpl
+GoASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx)
+{
+ return TypeMemberFunctionImpl();
+}
+
+CompilerType
+GoASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type)
+{
+ return CompilerType(this, type);
+}
+
+CompilerType
+GoASTContext::GetPointeeType(lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return CompilerType();
+ return static_cast<GoType *>(type)->GetElementType();
+}
+
+CompilerType
+GoASTContext::GetPointerType(lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return CompilerType();
+ ConstString type_name = GetTypeName(type);
+ ConstString pointer_name(std::string("*") + type_name.GetCString());
+ GoType *pointer = (*m_types)[pointer_name].get();
+ if (pointer == nullptr)
+ {
+ pointer = new GoElem(GoType::KIND_PTR, pointer_name, CompilerType(this, type));
+ (*m_types)[pointer_name].reset(pointer);
+ }
+ return CompilerType(this, pointer);
+}
+
+// If the current object represents a typedef type, get the underlying type
+CompilerType
+GoASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type)
+{
+ if (IsTypedefType(type))
+ return static_cast<GoType *>(type)->GetElementType();
+ return CompilerType();
+}
+
+//----------------------------------------------------------------------
+// Create related types using the current type's AST
+//----------------------------------------------------------------------
+CompilerType
+GoASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type)
+{
+ return CompilerType();
+}
+
+CompilerType
+GoASTContext::GetBuiltinTypeForEncodingAndBitSize (lldb::Encoding encoding,
+ size_t bit_size)
+{
+ return CompilerType();
+}
+
+
+//----------------------------------------------------------------------
+// Exploring the type
+//----------------------------------------------------------------------
+
+uint64_t
+GoASTContext::GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope)
+{
+ if (!type)
+ return 0;
+ if (!GetCompleteType(type))
+ return 0;
+ GoType *t = static_cast<GoType *>(type);
+ GoArray *array = nullptr;
+ switch (t->GetGoKind())
+ {
+ case GoType::KIND_BOOL:
+ case GoType::KIND_INT8:
+ case GoType::KIND_UINT8:
+ return 8;
+ case GoType::KIND_INT16:
+ case GoType::KIND_UINT16:
+ return 16;
+ case GoType::KIND_INT32:
+ case GoType::KIND_UINT32:
+ case GoType::KIND_FLOAT32:
+ return 32;
+ case GoType::KIND_INT64:
+ case GoType::KIND_UINT64:
+ case GoType::KIND_FLOAT64:
+ case GoType::KIND_COMPLEX64:
+ return 64;
+ case GoType::KIND_COMPLEX128:
+ return 128;
+ case GoType::KIND_INT:
+ case GoType::KIND_UINT:
+ return m_int_byte_size * 8;
+ case GoType::KIND_UINTPTR:
+ case GoType::KIND_FUNC: // I assume this is a pointer?
+ case GoType::KIND_CHAN:
+ case GoType::KIND_PTR:
+ case GoType::KIND_UNSAFEPOINTER:
+ case GoType::KIND_MAP:
+ return m_pointer_byte_size * 8;
+ case GoType::KIND_ARRAY:
+ array = t->GetArray();
+ return array->GetLength() * array->GetElementType().GetBitSize(exe_scope);
+ case GoType::KIND_INTERFACE:
+ return t->GetElementType().GetBitSize(exe_scope);
+ case GoType::KIND_SLICE:
+ case GoType::KIND_STRING:
+ case GoType::KIND_STRUCT:
+ return t->GetStruct()->GetByteSize() * 8;
+ default:
+ assert(false);
+ }
+ return 0;
+}
+
+lldb::Encoding
+GoASTContext::GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count)
+{
+ count = 1;
+ bool is_signed;
+ if (IsIntegerType(type, is_signed))
+ return is_signed ? lldb::eEncodingSint : eEncodingUint;
+ bool is_complex;
+ uint32_t complex_count;
+ if (IsFloatingPointType(type, complex_count, is_complex))
+ {
+ count = complex_count;
+ return eEncodingIEEE754;
+ }
+ if (IsPointerType(type))
+ return eEncodingUint;
+ return eEncodingInvalid;
+}
+
+lldb::Format
+GoASTContext::GetFormat(lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return eFormatDefault;
+ switch (static_cast<GoType *>(type)->GetGoKind())
+ {
+ case GoType::KIND_BOOL:
+ return eFormatBoolean;
+ case GoType::KIND_INT:
+ case GoType::KIND_INT8:
+ case GoType::KIND_INT16:
+ case GoType::KIND_INT32:
+ case GoType::KIND_INT64:
+ return eFormatDecimal;
+ case GoType::KIND_UINT:
+ case GoType::KIND_UINT8:
+ case GoType::KIND_UINT16:
+ case GoType::KIND_UINT32:
+ case GoType::KIND_UINT64:
+ return eFormatUnsigned;
+ case GoType::KIND_FLOAT32:
+ case GoType::KIND_FLOAT64:
+ return eFormatFloat;
+ case GoType::KIND_COMPLEX64:
+ case GoType::KIND_COMPLEX128:
+ return eFormatComplexFloat;
+ case GoType::KIND_UINTPTR:
+ case GoType::KIND_CHAN:
+ case GoType::KIND_PTR:
+ case GoType::KIND_MAP:
+ case GoType::KIND_UNSAFEPOINTER:
+ return eFormatHex;
+ case GoType::KIND_STRING:
+ return eFormatCString;
+ case GoType::KIND_ARRAY:
+ case GoType::KIND_INTERFACE:
+ case GoType::KIND_SLICE:
+ case GoType::KIND_STRUCT:
+ default:
+ // Don't know how to display this.
+ return eFormatBytes;
+ }
+}
+
+size_t
+GoASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type)
+{
+ return 0;
+}
+
+uint32_t
+GoASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes)
+{
+ if (!type || !GetCompleteType(type))
+ return 0;
+ GoType *t = static_cast<GoType *>(type);
+ if (t->GetGoKind() == GoType::KIND_PTR)
+ {
+ CompilerType elem = t->GetElementType();
+ if (elem.IsAggregateType())
+ return elem.GetNumChildren(omit_empty_base_classes);
+ return 1;
+ }
+ else if (GoArray *array = t->GetArray())
+ {
+ return array->GetLength();
+ }
+ else if (t->IsTypedef())
+ {
+ return t->GetElementType().GetNumChildren(omit_empty_base_classes);
+ }
+
+ return GetNumFields(type);
+}
+
+uint32_t
+GoASTContext::GetNumFields(lldb::opaque_compiler_type_t type)
+{
+ if (!type || !GetCompleteType(type))
+ return 0;
+ GoType *t = static_cast<GoType *>(type);
+ if (t->IsTypedef())
+ return t->GetElementType().GetNumFields();
+ GoStruct *s = t->GetStruct();
+ if (s)
+ return s->GetNumFields();
+ return 0;
+}
+
+CompilerType
+GoASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx, std::string &name, uint64_t *bit_offset_ptr,
+ uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr)
+{
+ if (bit_offset_ptr)
+ *bit_offset_ptr = 0;
+ if (bitfield_bit_size_ptr)
+ *bitfield_bit_size_ptr = 0;
+ if (is_bitfield_ptr)
+ *is_bitfield_ptr = false;
+
+ if (!type || !GetCompleteType(type))
+ return CompilerType();
+
+ GoType *t = static_cast<GoType *>(type);
+ if (t->IsTypedef())
+ return t->GetElementType().GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr);
+
+ GoStruct *s = t->GetStruct();
+ if (s)
+ {
+ const auto *field = s->GetField(idx);
+ if (field)
+ {
+ name = field->m_name.GetStringRef();
+ if (bit_offset_ptr)
+ *bit_offset_ptr = field->m_byte_offset * 8;
+ return field->m_type;
+ }
+ }
+ return CompilerType();
+}
+
+CompilerType
+GoASTContext::GetChildCompilerTypeAtIndex(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers,
+ bool omit_empty_base_classes, bool ignore_array_bounds, std::string &child_name,
+ uint32_t &child_byte_size, int32_t &child_byte_offset,
+ uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
+ bool &child_is_base_class, bool &child_is_deref_of_parent, ValueObject *valobj, uint64_t &language_flags)
+{
+ child_name.clear();
+ child_byte_size = 0;
+ child_byte_offset = 0;
+ child_bitfield_bit_size = 0;
+ child_bitfield_bit_offset = 0;
+ child_is_base_class = false;
+ child_is_deref_of_parent = false;
+ language_flags = 0;
+
+ if (!type || !GetCompleteType(type))
+ return CompilerType();
+
+ GoType *t = static_cast<GoType *>(type);
+ if (t->GetStruct())
+ {
+ uint64_t bit_offset;
+ CompilerType ret = GetFieldAtIndex(type, idx, child_name, &bit_offset, nullptr, nullptr);
+ child_byte_size = ret.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
+ child_byte_offset = bit_offset / 8;
+ return ret;
+ }
+ else if (t->GetGoKind() == GoType::KIND_PTR)
+ {
+ CompilerType pointee = t->GetElementType();
+ if (!pointee.IsValid() || pointee.IsVoidType())
+ return CompilerType();
+ if (transparent_pointers && pointee.IsAggregateType())
+ {
+ bool tmp_child_is_deref_of_parent = false;
+ return pointee.GetChildCompilerTypeAtIndex(exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
+ ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
+ child_bitfield_bit_size, child_bitfield_bit_offset,
+ child_is_base_class, tmp_child_is_deref_of_parent, valobj, language_flags);
+ }
+ else
+ {
+ child_is_deref_of_parent = true;
+ const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL;
+ if (parent_name)
+ {
+ child_name.assign(1, '*');
+ child_name += parent_name;
+ }
+
+ // We have a pointer to an simple type
+ if (idx == 0 && pointee.GetCompleteType())
+ {
+ child_byte_size = pointee.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+ child_byte_offset = 0;
+ return pointee;
+ }
+ }
+ }
+ else if (GoArray *a = t->GetArray())
+ {
+ if (ignore_array_bounds || idx < a->GetLength())
+ {
+ CompilerType element_type = a->GetElementType();
+ if (element_type.GetCompleteType())
+ {
+ char element_name[64];
+ ::snprintf(element_name, sizeof(element_name), "[%zu]", idx);
+ child_name.assign(element_name);
+ child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+ child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
+ return element_type;
+ }
+ }
+ }
+ else if (t->IsTypedef())
+ {
+ return t->GetElementType().GetChildCompilerTypeAtIndex(
+ exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name,
+ child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
+ child_is_deref_of_parent, valobj, language_flags);
+ }
+ return CompilerType();
+}
+
+// Lookup a child given a name. This function will match base class names
+// and member member names in "clang_type" only, not descendants.
+uint32_t
+GoASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes)
+{
+ if (!type || !GetCompleteType(type))
+ return UINT_MAX;
+
+ GoType *t = static_cast<GoType *>(type);
+ GoStruct *s = t->GetStruct();
+ if (s)
+ {
+ for (uint32_t i = 0; i < s->GetNumFields(); ++i)
+ {
+ const GoStruct::Field *f = s->GetField(i);
+ if (f->m_name.GetStringRef() == name)
+ return i;
+ }
+ }
+ else if (t->GetGoKind() == GoType::KIND_PTR || t->IsTypedef())
+ {
+ return t->GetElementType().GetIndexOfChildWithName(name, omit_empty_base_classes);
+ }
+ return UINT_MAX;
+}
+
+// Lookup a child member given a name. This function will match member names
+// only and will descend into "clang_type" children in search for the first
+// member in this class, or any base class that matches "name".
+// TODO: Return all matches for a given name by returning a vector<vector<uint32_t>>
+// so we catch all names that match a given child name, not just the first.
+size_t
+GoASTContext::GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes,
+ std::vector<uint32_t> &child_indexes)
+{
+ uint32_t index = GetIndexOfChildWithName(type, name, omit_empty_base_classes);
+ if (index == UINT_MAX)
+ return 0;
+ child_indexes.push_back(index);
+ return 1;
+}
+
+// Converts "s" to a floating point value and place resulting floating
+// point bytes in the "dst" buffer.
+size_t
+GoASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst, size_t dst_size)
+{
+ assert(false);
+ return 0;
+}
+//----------------------------------------------------------------------
+// Dumping types
+//----------------------------------------------------------------------
+void
+GoASTContext::DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format,
+ const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size,
+ uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, bool show_summary,
+ bool verbose, uint32_t depth)
+{
+ assert(false);
+}
+
+bool
+GoASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, const DataExtractor &data,
+ lldb::offset_t byte_offset, size_t byte_size, uint32_t bitfield_bit_size,
+ uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope)
+{
+ if (!type)
+ return false;
+ if (IsAggregateType(type))
+ {
+ return false;
+ }
+ else
+ {
+ GoType *t = static_cast<GoType *>(type);
+ if (t->IsTypedef())
+ {
+ CompilerType typedef_compiler_type = t->GetElementType();
+ if (format == eFormatDefault)
+ format = typedef_compiler_type.GetFormat();
+ uint64_t typedef_byte_size = typedef_compiler_type.GetByteSize(exe_scope);
+
+ return typedef_compiler_type.DumpTypeValue(
+ s,
+ format, // The format with which to display the element
+ data, // Data buffer containing all bytes for this type
+ byte_offset, // Offset into "data" where to grab value from
+ typedef_byte_size, // Size of this type in bytes
+ bitfield_bit_size, // Size in bits of a bitfield value, if zero don't treat as a bitfield
+ bitfield_bit_offset, // Offset in bits of a bitfield value if bitfield_bit_size != 0
+ exe_scope);
+ }
+
+ uint32_t item_count = 1;
+ // A few formats, we might need to modify our size and count for depending
+ // on how we are trying to display the value...
+ switch (format)
+ {
+ default:
+ case eFormatBoolean:
+ case eFormatBinary:
+ case eFormatComplex:
+ case eFormatCString: // NULL terminated C strings
+ case eFormatDecimal:
+ case eFormatEnum:
+ case eFormatHex:
+ case eFormatHexUppercase:
+ case eFormatFloat:
+ case eFormatOctal:
+ case eFormatOSType:
+ case eFormatUnsigned:
+ case eFormatPointer:
+ case eFormatVectorOfChar:
+ case eFormatVectorOfSInt8:
+ case eFormatVectorOfUInt8:
+ case eFormatVectorOfSInt16:
+ case eFormatVectorOfUInt16:
+ case eFormatVectorOfSInt32:
+ case eFormatVectorOfUInt32:
+ case eFormatVectorOfSInt64:
+ case eFormatVectorOfUInt64:
+ case eFormatVectorOfFloat32:
+ case eFormatVectorOfFloat64:
+ case eFormatVectorOfUInt128:
+ break;
+
+ case eFormatChar:
+ case eFormatCharPrintable:
+ case eFormatCharArray:
+ case eFormatBytes:
+ case eFormatBytesWithASCII:
+ item_count = byte_size;
+ byte_size = 1;
+ break;
+
+ case eFormatUnicode16:
+ item_count = byte_size / 2;
+ byte_size = 2;
+ break;
+
+ case eFormatUnicode32:
+ item_count = byte_size / 4;
+ byte_size = 4;
+ break;
+ }
+ return data.Dump(s, byte_offset, format, byte_size, item_count, UINT32_MAX, LLDB_INVALID_ADDRESS,
+ bitfield_bit_size, bitfield_bit_offset, exe_scope);
+ }
+ return 0;
+}
+
+void
+GoASTContext::DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, const DataExtractor &data,
+ lldb::offset_t data_offset, size_t data_byte_size)
+{
+ assert(false);
+}
+
+void
+GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type)
+{
+ assert(false);
+} // Dump to stdout
+
+void
+GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, Stream *s)
+{
+ assert(false);
+}
+
+CompilerType
+GoASTContext::CreateArrayType(const ConstString &name, const CompilerType &element_type, uint64_t length)
+{
+ GoType *type = new GoArray(name, length, element_type);
+ (*m_types)[name].reset(type);
+ return CompilerType(this, type);
+}
+
+CompilerType
+GoASTContext::CreateBaseType(int go_kind, const lldb_private::ConstString &name, uint64_t byte_size)
+{
+ if (go_kind == GoType::KIND_UINT || go_kind == GoType::KIND_INT)
+ m_int_byte_size = byte_size;
+ GoType *type = new GoType(go_kind, name);
+ (*m_types)[name].reset(type);
+ return CompilerType(this, type);
+}
+
+CompilerType
+GoASTContext::CreateTypedefType(int kind, const ConstString &name, CompilerType impl)
+{
+ GoType *type = new GoElem(kind, name, impl);
+ (*m_types)[name].reset(type);
+ return CompilerType(this, type);
+}
+
+CompilerType
+GoASTContext::CreateVoidType(const lldb_private::ConstString &name)
+{
+ GoType *type = new GoType(GoType::KIND_LLDB_VOID, name);
+ (*m_types)[name].reset(type);
+ return CompilerType(this, type);
+}
+
+CompilerType
+GoASTContext::CreateStructType(int kind, const lldb_private::ConstString &name, uint32_t byte_size)
+{
+ GoType *type = new GoStruct(kind, name, byte_size);
+ (*m_types)[name].reset(type);
+ return CompilerType(this, type);
+}
+
+void
+GoASTContext::AddFieldToStruct(const lldb_private::CompilerType &struct_type, const lldb_private::ConstString &name,
+ const lldb_private::CompilerType &field_type, uint32_t byte_offset)
+{
+ if (!struct_type)
+ return;
+ GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(struct_type.GetTypeSystem());
+ if (!ast)
+ return;
+ GoType *type = static_cast<GoType *>(struct_type.GetOpaqueQualType());
+ if (GoStruct *s = type->GetStruct())
+ s->AddField(name, field_type, byte_offset);
+}
+
+void
+GoASTContext::CompleteStructType(const lldb_private::CompilerType &struct_type)
+{
+ if (!struct_type)
+ return;
+ GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(struct_type.GetTypeSystem());
+ if (!ast)
+ return;
+ GoType *type = static_cast<GoType *>(struct_type.GetOpaqueQualType());
+ if (GoStruct *s = type->GetStruct())
+ s->SetComplete();
+}
+
+CompilerType
+GoASTContext::CreateFunctionType(const lldb_private::ConstString &name, CompilerType *params, size_t params_count,
+ bool is_variadic)
+{
+ GoType *type = new GoFunction(name, is_variadic);
+ (*m_types)[name].reset(type);
+ return CompilerType(this, type);
+}
+
+bool
+GoASTContext::IsGoString(const lldb_private::CompilerType &type)
+{
+ if (!type.IsValid() || !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem()))
+ return false;
+ return GoType::KIND_STRING == static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind();
+}
+
+bool
+GoASTContext::IsGoSlice(const lldb_private::CompilerType &type)
+{
+ if (!type.IsValid() || !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem()))
+ return false;
+ return GoType::KIND_SLICE == static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind();
+}
+
+bool
+GoASTContext::IsGoInterface(const lldb_private::CompilerType &type)
+{
+ if (!type.IsValid() || !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem()))
+ return false;
+ return GoType::KIND_INTERFACE == static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind();
+}
+
+bool
+GoASTContext::IsPointerKind(uint8_t kind)
+{
+ return (kind & GoType::KIND_MASK) == GoType::KIND_PTR;
+}
+
+bool
+GoASTContext::IsDirectIface(uint8_t kind)
+{
+ return (kind & GoType::KIND_DIRECT_IFACE) == GoType::KIND_DIRECT_IFACE;
+}
+
+DWARFASTParser *
+GoASTContext::GetDWARFParser()
+{
+ if (!m_dwarf_ast_parser_ap)
+ m_dwarf_ast_parser_ap.reset(new DWARFASTParserGo(*this));
+ return m_dwarf_ast_parser_ap.get();
+}
+
+UserExpression *
+GoASTContextForExpr::GetUserExpression(const char *expr, const char *expr_prefix, lldb::LanguageType language,
+ Expression::ResultType desired_type, const EvaluateExpressionOptions &options)
+{
+ TargetSP target = m_target_wp.lock();
+ if (target)
+ return new GoUserExpression(*target, expr, expr_prefix, language, desired_type, options);
+ return nullptr;
+}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/LineEntry.cpp b/contrib/llvm/tools/lldb/source/Symbol/LineEntry.cpp
index 08a2392..8151013 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/LineEntry.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/LineEntry.cpp
@@ -244,3 +244,42 @@ LineEntry::Compare (const LineEntry& a, const LineEntry& b)
return FileSpec::Compare (a.file, b.file, true);
}
+AddressRange
+LineEntry::GetSameLineContiguousAddressRange () const
+{
+ // Add each LineEntry's range to complete_line_range until we find
+ // a different file / line number.
+ AddressRange complete_line_range = range;
+
+ while (true)
+ {
+ SymbolContext next_line_sc;
+ Address range_end (complete_line_range.GetBaseAddress());
+ range_end.Slide (complete_line_range.GetByteSize());
+ range_end.CalculateSymbolContext (&next_line_sc, lldb::eSymbolContextLineEntry);
+
+ if (next_line_sc.line_entry.IsValid()
+ && next_line_sc.line_entry.range.GetByteSize() > 0
+ && file == next_line_sc.line_entry.file)
+ {
+ // Include any line 0 entries - they indicate that this is compiler-generated code
+ // that does not correspond to user source code.
+ if (next_line_sc.line_entry.line == 0)
+ {
+ complete_line_range.SetByteSize (complete_line_range.GetByteSize() + next_line_sc.line_entry.range.GetByteSize());
+ continue;
+ }
+
+ if (line == next_line_sc.line_entry.line)
+ {
+ // next_line_sc is the same file & line as this LineEntry, so extend our
+ // AddressRange by its size and continue to see if there are more LineEntries
+ // that we can combine.
+ complete_line_range.SetByteSize (complete_line_range.GetByteSize() + next_line_sc.line_entry.range.GetByteSize());
+ continue;
+ }
+ }
+ break;
+ }
+ return complete_line_range;
+}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp b/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp
index 3b951f5..f9a42a7 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/LineTable.cpp
@@ -104,7 +104,17 @@ LineTable::AppendLineEntryToSequence
// here to avoid these kinds of inconsistencies. We will need tor revisit this if the DWARF line
// tables are updated to allow multiple entries at the same address legally.
if (!entries.empty() && entries.back().file_addr == file_addr)
+ {
+ // GCC don't use the is_prologue_end flag to mark the first instruction after the prologue.
+ // Instead of it it is issueing a line table entry for the first instruction of the prologue
+ // and one for the first instruction after the prologue. If the size of the prologue is 0
+ // instruction then the 2 line entry will have the same file address. Removing it will remove
+ // our ability to properly detect the location of the end of prologe so we set the prologue_end
+ // flag to preserve this information (setting the prologue_end flag for an entry what is after
+ // the prologue end don't have any effect)
+ entry.is_prologue_end = entry.file_idx == entries.back().file_idx;
entries.back() = entry;
+ }
else
entries.push_back (entry);
}
@@ -133,6 +143,13 @@ LineTable::InsertSequence (LineSequence* sequence)
entry_collection::iterator end_pos = m_entries.end();
LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp);
+
+ // We should never insert a sequence in the middle of another sequence
+ if (pos != begin_pos) {
+ while (pos < end_pos && !((pos - 1)->is_terminal_entry))
+ pos++;
+ }
+
#ifdef LLDB_CONFIGURATION_DEBUG
// If we aren't inserting at the beginning, the previous entry should
// terminate a sequence.
@@ -215,7 +232,7 @@ LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry
--pos;
else if (pos->file_addr == search_entry.file_addr)
{
- // If this is a termination entry, it should't match since
+ // If this is a termination entry, it shouldn't match since
// entries with the "is_terminal_entry" member set to true
// are termination entries that define the range for the
// previous entry.
@@ -529,7 +546,7 @@ LineTable::LinkLineTable (const FileRangeMap &file_range_map)
{
entry_linked_file_addr = entry.file_addr - file_range_entry->GetRangeBase() + file_range_entry->data;
// Determine if we need to terminate the previous entry when the previous
- // entry was not contguous with this one after being linked.
+ // entry was not contiguous with this one after being linked.
if (range_changed && prev_file_range_entry)
{
prev_end_entry_linked_file_addr = std::min<lldb::addr_t>(entry.file_addr, prev_file_range_entry->GetRangeEnd()) - prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data;
diff --git a/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp b/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp
index 22a313c..99f9236 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/ObjectFile.cpp
@@ -351,25 +351,31 @@ ObjectFile::GetAddressClass (addr_t file_addr)
case eSectionTypeZeroFill:
case eSectionTypeDataObjCMessageRefs:
case eSectionTypeDataObjCCFStrings:
+ case eSectionTypeGoSymtab:
return eAddressClassData;
case eSectionTypeDebug:
case eSectionTypeDWARFDebugAbbrev:
+ case eSectionTypeDWARFDebugAddr:
case eSectionTypeDWARFDebugAranges:
case eSectionTypeDWARFDebugFrame:
case eSectionTypeDWARFDebugInfo:
case eSectionTypeDWARFDebugLine:
case eSectionTypeDWARFDebugLoc:
case eSectionTypeDWARFDebugMacInfo:
+ case eSectionTypeDWARFDebugMacro:
case eSectionTypeDWARFDebugPubNames:
case eSectionTypeDWARFDebugPubTypes:
case eSectionTypeDWARFDebugRanges:
case eSectionTypeDWARFDebugStr:
+ case eSectionTypeDWARFDebugStrOffsets:
case eSectionTypeDWARFAppleNames:
case eSectionTypeDWARFAppleTypes:
case eSectionTypeDWARFAppleNamespaces:
case eSectionTypeDWARFAppleObjC:
return eAddressClassDebug;
case eSectionTypeEHFrame:
+ case eSectionTypeARMexidx:
+ case eSectionTypeARMextab:
case eSectionTypeCompactUnwind:
return eAddressClassRuntime;
case eSectionTypeELFSymbolTable:
@@ -532,6 +538,7 @@ ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data
}
}
}
+ return GetData(section->GetFileOffset(), section->GetFileSize(), section_data);
}
else
{
@@ -600,16 +607,49 @@ ObjectFile::ClearSymtab ()
}
SectionList *
-ObjectFile::GetSectionList()
+ObjectFile::GetSectionList(bool update_module_section_list)
{
if (m_sections_ap.get() == nullptr)
{
- ModuleSP module_sp(GetModule());
- if (module_sp)
+ if (update_module_section_list)
+ {
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ CreateSections(*module_sp->GetUnifiedSectionList());
+ }
+ }
+ else
{
- lldb_private::Mutex::Locker locker(module_sp->GetMutex());
- CreateSections(*module_sp->GetUnifiedSectionList());
+ SectionList unified_section_list;
+ CreateSections(unified_section_list);
}
}
return m_sections_ap.get();
}
+
+lldb::SymbolType
+ObjectFile::GetSymbolTypeFromName (llvm::StringRef name,
+ lldb::SymbolType symbol_type_hint)
+{
+ if (!name.empty())
+ {
+ if (name.startswith("_OBJC_"))
+ {
+ // ObjC
+ if (name.startswith("_OBJC_CLASS_$_"))
+ return lldb::eSymbolTypeObjCClass;
+ if (name.startswith("_OBJC_METACLASS_$_"))
+ return lldb::eSymbolTypeObjCMetaClass;
+ if (name.startswith("_OBJC_IVAR_$_"))
+ return lldb::eSymbolTypeObjCIVar;
+ }
+ else if (name.startswith(".objc_class_name_"))
+ {
+ // ObjC v1
+ return lldb::eSymbolTypeObjCClass;
+ }
+ }
+ return symbol_type_hint;
+}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp b/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp
index 4fb0dbc..54db5e0 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/SymbolContext.cpp
@@ -391,24 +391,24 @@ SymbolContext::GetResolvedMask () const
void
SymbolContext::Dump(Stream *s, Target *target) const
{
- *s << (void *)this << ": ";
+ *s << this << ": ";
s->Indent();
s->PutCString("SymbolContext");
s->IndentMore();
s->EOL();
s->IndentMore();
s->Indent();
- *s << "Module = " << (void *)module_sp.get() << ' ';
+ *s << "Module = " << module_sp.get() << ' ';
if (module_sp)
module_sp->GetFileSpec().Dump(s);
s->EOL();
s->Indent();
- *s << "CompileUnit = " << (void *)comp_unit;
+ *s << "CompileUnit = " << comp_unit;
if (comp_unit != nullptr)
*s << " {0x" << comp_unit->GetID() << "} " << *(static_cast<FileSpec*> (comp_unit));
s->EOL();
s->Indent();
- *s << "Function = " << (void *)function;
+ *s << "Function = " << function;
if (function != nullptr)
{
*s << " {0x" << function->GetID() << "} " << function->GetType()->GetName() << ", address-range = ";
@@ -424,7 +424,7 @@ SymbolContext::Dump(Stream *s, Target *target) const
}
s->EOL();
s->Indent();
- *s << "Block = " << (void *)block;
+ *s << "Block = " << block;
if (block != nullptr)
*s << " {0x" << block->GetID() << '}';
// Dump the block and pass it a negative depth to we print all the parent blocks
@@ -436,11 +436,11 @@ SymbolContext::Dump(Stream *s, Target *target) const
line_entry.Dump (s, target, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true);
s->EOL();
s->Indent();
- *s << "Symbol = " << (void *)symbol;
+ *s << "Symbol = " << symbol;
if (symbol != nullptr && symbol->GetMangled())
*s << ' ' << symbol->GetName().AsCString();
s->EOL();
- *s << "Variable = " << (void *)variable;
+ *s << "Variable = " << variable;
if (variable != nullptr)
{
*s << " {0x" << variable->GetID() << "} " << variable->GetType()->GetName();
@@ -525,6 +525,38 @@ SymbolContext::GetAddressRange (uint32_t scope,
return false;
}
+LanguageType
+SymbolContext::GetLanguage () const
+{
+ LanguageType lang;
+ if (function &&
+ (lang = function->GetLanguage()) != eLanguageTypeUnknown)
+ {
+ return lang;
+ }
+ else if (variable &&
+ (lang = variable->GetLanguage()) != eLanguageTypeUnknown)
+ {
+ return lang;
+ }
+ else if (symbol &&
+ (lang = symbol->GetLanguage()) != eLanguageTypeUnknown)
+ {
+ return lang;
+ }
+ else if (comp_unit &&
+ (lang = comp_unit->GetLanguage()) != eLanguageTypeUnknown)
+ {
+ return lang;
+ }
+ else if (symbol)
+ {
+ // If all else fails, try to guess the language from the name.
+ return symbol->GetMangled().GuessLanguage();
+ }
+ return eLanguageTypeUnknown;
+}
+
bool
SymbolContext::GetParentOfInlinedScope (const Address &curr_frame_pc,
SymbolContext &next_frame_sc,
@@ -649,23 +681,124 @@ SymbolContext::GetFunctionMethodInfo (lldb::LanguageType &language,
{
- Block *function_block = GetFunctionBlock ();
+ Block *function_block = GetFunctionBlock();
if (function_block)
{
- clang::DeclContext *decl_context = function_block->GetClangDeclContext();
-
- if (decl_context)
+ CompilerDeclContext decl_ctx = function_block->GetDeclContext();
+ if (decl_ctx)
+ return decl_ctx.IsClassMethod(&language, &is_instance_method, &language_object_name);
+ }
+ return false;
+}
+
+void
+SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const
+{
+ Block * curr_block = block;
+ bool isInlinedblock = false;
+ if (curr_block != nullptr && curr_block->GetContainingInlinedBlock() != nullptr)
+ isInlinedblock = true;
+
+ //----------------------------------------------------------------------
+ // Find all types that match the current block if we have one and put
+ // them first in the list. Keep iterating up through all blocks.
+ //----------------------------------------------------------------------
+ while (curr_block != nullptr && !isInlinedblock)
+ {
+ type_map.ForEach([curr_block, &type_list](const lldb::TypeSP& type_sp) -> bool {
+ SymbolContextScope *scs = type_sp->GetSymbolContextScope();
+ if (scs && curr_block == scs->CalculateSymbolContextBlock())
+ type_list.Insert(type_sp);
+ return true; // Keep iterating
+ });
+
+ // Remove any entries that are now in "type_list" from "type_map"
+ // since we can't remove from type_map while iterating
+ type_list.ForEach([&type_map](const lldb::TypeSP& type_sp) -> bool {
+ type_map.Remove(type_sp);
+ return true; // Keep iterating
+ });
+ curr_block = curr_block->GetParent();
+ }
+ //----------------------------------------------------------------------
+ // Find all types that match the current function, if we have onem, and
+ // put them next in the list.
+ //----------------------------------------------------------------------
+ if (function != nullptr && !type_map.Empty())
+ {
+ const size_t old_type_list_size = type_list.GetSize();
+ type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool {
+ SymbolContextScope *scs = type_sp->GetSymbolContextScope();
+ if (scs && function == scs->CalculateSymbolContextFunction())
+ type_list.Insert(type_sp);
+ return true; // Keep iterating
+ });
+
+ // Remove any entries that are now in "type_list" from "type_map"
+ // since we can't remove from type_map while iterating
+ const size_t new_type_list_size = type_list.GetSize();
+ if (new_type_list_size > old_type_list_size)
{
- return ClangASTContext::GetClassMethodInfoForDeclContext (decl_context,
- language,
- is_instance_method,
- language_object_name);
+ for (size_t i=old_type_list_size; i<new_type_list_size; ++i)
+ type_map.Remove(type_list.GetTypeAtIndex(i));
}
}
- language = eLanguageTypeUnknown;
- is_instance_method = false;
- language_object_name.Clear();
- return false;
+ //----------------------------------------------------------------------
+ // Find all types that match the current compile unit, if we have one,
+ // and put them next in the list.
+ //----------------------------------------------------------------------
+ if (comp_unit != nullptr && !type_map.Empty())
+ {
+ const size_t old_type_list_size = type_list.GetSize();
+
+ type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool {
+ SymbolContextScope *scs = type_sp->GetSymbolContextScope();
+ if (scs && comp_unit == scs->CalculateSymbolContextCompileUnit())
+ type_list.Insert(type_sp);
+ return true; // Keep iterating
+ });
+
+ // Remove any entries that are now in "type_list" from "type_map"
+ // since we can't remove from type_map while iterating
+ const size_t new_type_list_size = type_list.GetSize();
+ if (new_type_list_size > old_type_list_size)
+ {
+ for (size_t i=old_type_list_size; i<new_type_list_size; ++i)
+ type_map.Remove(type_list.GetTypeAtIndex(i));
+ }
+ }
+ //----------------------------------------------------------------------
+ // Find all types that match the current module, if we have one, and put
+ // them next in the list.
+ //----------------------------------------------------------------------
+ if (module_sp && !type_map.Empty())
+ {
+ const size_t old_type_list_size = type_list.GetSize();
+ type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool {
+ SymbolContextScope *scs = type_sp->GetSymbolContextScope();
+ if (scs && module_sp == scs->CalculateSymbolContextModule())
+ type_list.Insert(type_sp);
+ return true; // Keep iterating
+ });
+ // Remove any entries that are now in "type_list" from "type_map"
+ // since we can't remove from type_map while iterating
+ const size_t new_type_list_size = type_list.GetSize();
+ if (new_type_list_size > old_type_list_size)
+ {
+ for (size_t i=old_type_list_size; i<new_type_list_size; ++i)
+ type_map.Remove(type_list.GetTypeAtIndex(i));
+ }
+ }
+ //----------------------------------------------------------------------
+ // Any types that are left get copied into the list an any order.
+ //----------------------------------------------------------------------
+ if (!type_map.Empty())
+ {
+ type_map.ForEach([&type_list](const lldb::TypeSP& type_sp) -> bool {
+ type_list.Insert(type_sp);
+ return true; // Keep iterating
+ });
+ }
}
ConstString
@@ -930,7 +1063,7 @@ SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
}
else if (sc.symbol != nullptr)
{
- if (!sc.symbol->GetMangled().NameMatches(func_name, sc.function->GetLanguage()))
+ if (!sc.symbol->GetMangled().NameMatches(func_name, sc.symbol->GetLanguage()))
return false;
}
}
@@ -1178,7 +1311,7 @@ void
SymbolContextList::Dump(Stream *s, Target *target) const
{
- *s << (void *)this << ": ";
+ *s << this << ": ";
s->Indent();
s->PutCString("SymbolContextList");
s->EOL();
diff --git a/contrib/llvm/tools/lldb/source/Symbol/SymbolFile.cpp b/contrib/llvm/tools/lldb/source/Symbol/SymbolFile.cpp
index a5b138b..82bbceb 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/SymbolFile.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/SymbolFile.cpp
@@ -15,6 +15,9 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/TypeMap.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Symbol/VariableList.h"
using namespace lldb_private;
@@ -82,8 +85,74 @@ SymbolFile::GetTypeList ()
return nullptr;
}
-lldb_private::ClangASTContext &
-SymbolFile::GetClangASTContext ()
+TypeSystem *
+SymbolFile::GetTypeSystemForLanguage (lldb::LanguageType language)
{
- return m_obj_file->GetModule()->GetClangASTContext();
+ TypeSystem *type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
+ if (type_system)
+ type_system->SetSymbolFile(this);
+ return type_system;
+}
+
+uint32_t
+SymbolFile::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+ return 0;
+}
+
+
+uint32_t
+SymbolFile::FindGlobalVariables (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, VariableList& variables)
+{
+ if (!append)
+ variables.Clear();
+ return 0;
+}
+
+
+uint32_t
+SymbolFile::FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
+{
+ if (!append)
+ variables.Clear();
+ return 0;
+}
+
+uint32_t
+SymbolFile::FindFunctions (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list)
+{
+ if (!append)
+ sc_list.Clear();
+ return 0;
+}
+
+uint32_t
+SymbolFile::FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)
+{
+ if (!append)
+ sc_list.Clear();
+ return 0;
+}
+
+void
+SymbolFile::GetMangledNamesForFunction(const std::string &scope_qualified_name, std::vector<ConstString> &mangled_names)
+{
+ return;
+}
+
+uint32_t
+SymbolFile::FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, TypeMap& types)
+{
+ if (!append)
+ types.Clear();
+ return 0;
+}
+
+
+size_t
+SymbolFile::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types)
+{
+ if (!append)
+ types.Clear();
+ return 0;
}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/SymbolVendor.cpp b/contrib/llvm/tools/lldb/source/Symbol/SymbolVendor.cpp
index 6ec9f38..b9ec9a1 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/SymbolVendor.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/SymbolVendor.cpp
@@ -77,7 +77,7 @@ SymbolVendor::~SymbolVendor()
}
//----------------------------------------------------------------------
-// Add a represention given an object file.
+// Add a representation given an object file.
//----------------------------------------------------------------------
void
SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp)
@@ -186,6 +186,18 @@ SymbolVendor::ParseCompileUnitLineTable (const SymbolContext &sc)
}
bool
+SymbolVendor::ParseCompileUnitDebugMacros (const SymbolContext &sc)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->ParseCompileUnitDebugMacros(sc);
+ }
+ return false;
+}
+bool
SymbolVendor::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files)
{
ModuleSP module_sp(GetModule());
@@ -293,14 +305,14 @@ SymbolVendor::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bo
}
size_t
-SymbolVendor::FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, size_t max_matches, VariableList& variables)
+SymbolVendor::FindGlobalVariables (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, VariableList& variables)
{
ModuleSP module_sp(GetModule());
if (module_sp)
{
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->FindGlobalVariables(name, namespace_decl, append, max_matches, variables);
+ return m_sym_file_ap->FindGlobalVariables(name, parent_decl_ctx, append, max_matches, variables);
}
return 0;
}
@@ -319,14 +331,14 @@ SymbolVendor::FindGlobalVariables (const RegularExpression& regex, bool append,
}
size_t
-SymbolVendor::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list)
+SymbolVendor::FindFunctions(const ConstString &name, const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list)
{
ModuleSP module_sp(GetModule());
if (module_sp)
{
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list);
+ return m_sym_file_ap->FindFunctions(name, parent_decl_ctx, name_type_mask, include_inlines, append, sc_list);
}
return 0;
}
@@ -346,14 +358,29 @@ SymbolVendor::FindFunctions(const RegularExpression& regex, bool include_inlines
size_t
-SymbolVendor::FindTypes (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, size_t max_matches, TypeList& types)
+SymbolVendor::FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, TypeMap& types)
+{
+ ModuleSP module_sp(GetModule());
+ if (module_sp)
+ {
+ lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+ if (m_sym_file_ap.get())
+ return m_sym_file_ap->FindTypes(sc, name, parent_decl_ctx, append, max_matches, types);
+ }
+ if (!append)
+ types.Clear();
+ return 0;
+}
+
+size_t
+SymbolVendor::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types)
{
ModuleSP module_sp(GetModule());
if (module_sp)
{
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->FindTypes(sc, name, namespace_decl, append, max_matches, types);
+ return m_sym_file_ap->FindTypes(context, append, types);
}
if (!append)
types.Clear();
@@ -375,18 +402,18 @@ SymbolVendor::GetTypes (SymbolContextScope *sc_scope,
return 0;
}
-ClangNamespaceDecl
-SymbolVendor::FindNamespace(const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *parent_namespace_decl)
+CompilerDeclContext
+SymbolVendor::FindNamespace(const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx)
{
- ClangNamespaceDecl namespace_decl;
+ CompilerDeclContext namespace_decl_ctx;
ModuleSP module_sp(GetModule());
if (module_sp)
{
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
if (m_sym_file_ap.get())
- namespace_decl = m_sym_file_ap->FindNamespace (sc, name, parent_namespace_decl);
+ namespace_decl_ctx = m_sym_file_ap->FindNamespace (sc, name, parent_decl_ctx);
}
- return namespace_decl;
+ return namespace_decl_ctx;
}
void
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp b/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp
index c11efc0..b20504a 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Symtab.cpp
@@ -8,17 +8,19 @@
//===----------------------------------------------------------------------===//
#include <map>
+#include <set>
#include "lldb/Core/Module.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Section.h"
+#include "lldb/Core/Stream.h"
#include "lldb/Core/Timer.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Symtab.h"
-#include "lldb/Target/CPPLanguageRuntime.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
using namespace lldb;
using namespace lldb_private;
@@ -329,7 +331,7 @@ Symtab::InitNameIndexes()
entry.cstring[2] != 'G' && // avoid guard variables
entry.cstring[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
{
- CPPLanguageRuntime::MethodName cxx_method (mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus));
+ CPlusPlusLanguage::MethodName cxx_method (mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus));
entry.cstring = ConstString(cxx_method.GetBasename()).GetCString();
if (entry.cstring && entry.cstring[0])
{
@@ -392,7 +394,7 @@ Symtab::InitNameIndexes()
// If the demangled name turns out to be an ObjC name, and
// is a category name, add the version without categories to the index too.
- ObjCLanguageRuntime::MethodName objc_method (entry.cstring, true);
+ ObjCLanguage::MethodName objc_method (entry.cstring, true);
if (objc_method.IsValid(true))
{
entry.cstring = objc_method.GetSelector().GetCString();
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Type.cpp b/contrib/llvm/tools/lldb/source/Symbol/Type.cpp
index 0927d55..8061e01 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Type.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Type.cpp
@@ -7,22 +7,26 @@
//
//===----------------------------------------------------------------------===//
-// Other libraries and framework includes
+// C Includes
+#include <stdio.h>
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Symbol/ClangASTType.h"
-#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContextScope.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
@@ -36,6 +40,26 @@
using namespace lldb;
using namespace lldb_private;
+void
+CompilerContext::Dump() const
+{
+ switch (type)
+ {
+ case CompilerContextKind::Invalid: printf("Invalid"); break;
+ case CompilerContextKind::TranslationUnit: printf("TranslationUnit"); break;
+ case CompilerContextKind::Module: printf("Module"); break;
+ case CompilerContextKind::Namespace: printf("Namespace"); break;
+ case CompilerContextKind::Class: printf("Class"); break;
+ case CompilerContextKind::Structure: printf("Structure"); break;
+ case CompilerContextKind::Union: printf("Union"); break;
+ case CompilerContextKind::Function: printf("Function"); break;
+ case CompilerContextKind::Variable: printf("Variable"); break;
+ case CompilerContextKind::Enumeration: printf("Enumeration"); break;
+ case CompilerContextKind::Typedef: printf("Typedef"); break;
+ }
+ printf("(\"%s\")\n", name.GetCString());
+}
+
class TypeAppendVisitor
{
public:
@@ -62,6 +86,13 @@ TypeListImpl::Append (const lldb_private::TypeList &type_list)
type_list.ForEach(cb);
}
+SymbolFileType::SymbolFileType (SymbolFile &symbol_file, const lldb::TypeSP &type_sp) :
+ UserID (type_sp ? type_sp->GetID() : LLDB_INVALID_UID),
+ m_symbol_file (symbol_file),
+ m_type_sp (type_sp)
+{
+}
+
Type *
SymbolFileType::GetType ()
@@ -86,8 +117,8 @@ Type::Type
user_id_t encoding_uid,
EncodingDataType encoding_uid_type,
const Declaration& decl,
- const ClangASTType &clang_type,
- ResolveState clang_type_resolve_state
+ const CompilerType &compiler_type,
+ ResolveState compiler_type_resolve_state
) :
std::enable_shared_from_this<Type> (),
UserID (uid),
@@ -99,9 +130,9 @@ Type::Type
m_encoding_uid_type (encoding_uid_type),
m_byte_size (byte_size),
m_decl (decl),
- m_clang_type (clang_type)
+ m_compiler_type (compiler_type)
{
- m_flags.clang_type_resolve_state = (clang_type ? clang_type_resolve_state : eResolveStateUnresolved);
+ m_flags.compiler_type_resolve_state = (compiler_type ? compiler_type_resolve_state : eResolveStateUnresolved);
m_flags.is_complete_objc_class = false;
}
@@ -116,9 +147,9 @@ Type::Type () :
m_encoding_uid_type (eEncodingInvalid),
m_byte_size (0),
m_decl (),
- m_clang_type ()
+ m_compiler_type ()
{
- m_flags.clang_type_resolve_state = eResolveStateUnresolved;
+ m_flags.compiler_type_resolve_state = eResolveStateUnresolved;
m_flags.is_complete_objc_class = false;
}
@@ -134,7 +165,7 @@ Type::Type (const Type &rhs) :
m_encoding_uid_type (rhs.m_encoding_uid_type),
m_byte_size (rhs.m_byte_size),
m_decl (rhs.m_decl),
- m_clang_type (rhs.m_clang_type),
+ m_compiler_type (rhs.m_compiler_type),
m_flags (rhs.m_flags)
{
}
@@ -175,10 +206,10 @@ Type::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_name)
bool show_fullpaths = (level == lldb::eDescriptionLevelVerbose);
m_decl.Dump(s, show_fullpaths);
- if (m_clang_type.IsValid())
+ if (m_compiler_type.IsValid())
{
- *s << ", clang_type = \"";
- GetClangForwardType().DumpTypeDescription(s);
+ *s << ", compiler_type = \"";
+ GetForwardCompilerType ().DumpTypeDescription(s);
*s << '"';
}
else if (m_encoding_uid != LLDB_INVALID_UID)
@@ -223,10 +254,10 @@ Type::Dump (Stream *s, bool show_context)
bool show_fullpaths = false;
m_decl.Dump (s,show_fullpaths);
- if (m_clang_type.IsValid())
+ if (m_compiler_type.IsValid())
{
- *s << ", clang_type = " << m_clang_type.GetOpaqueQualType() << ' ';
- GetClangForwardType().DumpTypeDescription (s);
+ *s << ", compiler_type = " << m_compiler_type.GetOpaqueQualType() << ' ';
+ GetForwardCompilerType ().DumpTypeDescription (s);
}
else if (m_encoding_uid != LLDB_INVALID_UID)
{
@@ -256,7 +287,7 @@ const ConstString &
Type::GetName()
{
if (!m_name)
- m_name = GetClangForwardType().GetConstTypeName();
+ m_name = GetForwardCompilerType ().GetConstTypeName();
return m_name;
}
@@ -291,7 +322,7 @@ Type::DumpValue
s->PutCString(") ");
}
- GetClangForwardType().DumpValue (exe_ctx,
+ GetForwardCompilerType ().DumpValue (exe_ctx,
s,
format == lldb::eFormatDefault ? GetFormat() : format,
data,
@@ -336,7 +367,7 @@ Type::GetByteSize()
if (encoding_type)
m_byte_size = encoding_type->GetByteSize();
if (m_byte_size == 0)
- m_byte_size = GetClangLayoutType().GetByteSize(nullptr);
+ m_byte_size = GetLayoutCompilerType ().GetByteSize(nullptr);
}
break;
@@ -344,7 +375,11 @@ Type::GetByteSize()
case eEncodingIsPointerUID:
case eEncodingIsLValueReferenceUID:
case eEncodingIsRValueReferenceUID:
- m_byte_size = m_symbol_file->GetClangASTContext().GetPointerByteSize();
+ {
+ ArchSpec arch;
+ if (m_symbol_file->GetObjectFile()->GetArchitecture(arch))
+ m_byte_size = arch.GetAddressByteSize();
+ }
break;
}
}
@@ -355,13 +390,13 @@ Type::GetByteSize()
uint32_t
Type::GetNumChildren (bool omit_empty_base_classes)
{
- return GetClangForwardType().GetNumChildren(omit_empty_base_classes);
+ return GetForwardCompilerType ().GetNumChildren(omit_empty_base_classes);
}
bool
Type::IsAggregateType ()
{
- return GetClangForwardType().IsAggregateType();
+ return GetForwardCompilerType ().IsAggregateType();
}
lldb::TypeSP
@@ -382,7 +417,7 @@ Type::GetTypedefType()
lldb::Format
Type::GetFormat ()
{
- return GetClangForwardType().GetFormat();
+ return GetForwardCompilerType ().GetFormat();
}
@@ -391,7 +426,7 @@ lldb::Encoding
Type::GetEncoding (uint64_t &count)
{
// Make sure we resolve our type if it already hasn't been.
- return GetClangForwardType().GetEncoding(count);
+ return GetForwardCompilerType ().GetEncoding(count);
}
bool
@@ -441,7 +476,7 @@ Type::ReadFromMemory (ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType
data.SetData(data_sp);
}
- uint8_t* dst = (uint8_t*)data.PeekData(0, byte_size);
+ uint8_t* dst = const_cast<uint8_t*>(data.PeekData(0, byte_size));
if (dst != nullptr)
{
if (address_type == eAddressTypeHost)
@@ -489,10 +524,11 @@ Type::GetDeclaration () const
}
bool
-Type::ResolveClangType (ResolveState clang_type_resolve_state)
+Type::ResolveClangType (ResolveState compiler_type_resolve_state)
{
+ // TODO: This needs to consider the correct type system to use.
Type *encoding_type = nullptr;
- if (!m_clang_type.IsValid())
+ if (!m_compiler_type.IsValid())
{
encoding_type = GetEncodingType();
if (encoding_type)
@@ -501,43 +537,43 @@ Type::ResolveClangType (ResolveState clang_type_resolve_state)
{
case eEncodingIsUID:
{
- ClangASTType encoding_clang_type = encoding_type->GetClangForwardType();
- if (encoding_clang_type.IsValid())
+ CompilerType encoding_compiler_type = encoding_type->GetForwardCompilerType ();
+ if (encoding_compiler_type.IsValid())
{
- m_clang_type = encoding_clang_type;
- m_flags.clang_type_resolve_state = encoding_type->m_flags.clang_type_resolve_state;
+ m_compiler_type = encoding_compiler_type;
+ m_flags.compiler_type_resolve_state = encoding_type->m_flags.compiler_type_resolve_state;
}
}
break;
case eEncodingIsConstUID:
- m_clang_type = encoding_type->GetClangForwardType().AddConstModifier();
+ m_compiler_type = encoding_type->GetForwardCompilerType ().AddConstModifier();
break;
case eEncodingIsRestrictUID:
- m_clang_type = encoding_type->GetClangForwardType().AddRestrictModifier();
+ m_compiler_type = encoding_type->GetForwardCompilerType ().AddRestrictModifier();
break;
case eEncodingIsVolatileUID:
- m_clang_type = encoding_type->GetClangForwardType().AddVolatileModifier();
+ m_compiler_type = encoding_type->GetForwardCompilerType ().AddVolatileModifier();
break;
case eEncodingIsTypedefUID:
- m_clang_type = encoding_type->GetClangForwardType().CreateTypedefType (GetName().AsCString(),
- GetSymbolFile()->GetClangDeclContextContainingTypeUID(GetID()));
+ m_compiler_type = encoding_type->GetForwardCompilerType ().CreateTypedef(GetName().AsCString(),
+ GetSymbolFile()->GetDeclContextContainingUID(GetID()));
m_name.Clear();
break;
case eEncodingIsPointerUID:
- m_clang_type = encoding_type->GetClangForwardType().GetPointerType();
+ m_compiler_type = encoding_type->GetForwardCompilerType ().GetPointerType();
break;
case eEncodingIsLValueReferenceUID:
- m_clang_type = encoding_type->GetClangForwardType().GetLValueReferenceType();
+ m_compiler_type = encoding_type->GetForwardCompilerType ().GetLValueReferenceType();
break;
case eEncodingIsRValueReferenceUID:
- m_clang_type = encoding_type->GetClangForwardType().GetRValueReferenceType();
+ m_compiler_type = encoding_type->GetForwardCompilerType ().GetRValueReferenceType();
break;
default:
@@ -548,40 +584,41 @@ Type::ResolveClangType (ResolveState clang_type_resolve_state)
else
{
// We have no encoding type, return void?
- ClangASTType void_clang_type (ClangASTContext::GetBasicType(GetClangASTContext().getASTContext(), eBasicTypeVoid));
+ TypeSystem *type_system = m_symbol_file->GetTypeSystemForLanguage(eLanguageTypeC);
+ CompilerType void_compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeVoid);
switch (m_encoding_uid_type)
{
case eEncodingIsUID:
- m_clang_type = void_clang_type;
+ m_compiler_type = void_compiler_type;
break;
case eEncodingIsConstUID:
- m_clang_type = void_clang_type.AddConstModifier ();
+ m_compiler_type = void_compiler_type.AddConstModifier();
break;
case eEncodingIsRestrictUID:
- m_clang_type = void_clang_type.AddRestrictModifier ();
+ m_compiler_type = void_compiler_type.AddRestrictModifier();
break;
case eEncodingIsVolatileUID:
- m_clang_type = void_clang_type.AddVolatileModifier ();
+ m_compiler_type = void_compiler_type.AddVolatileModifier();
break;
case eEncodingIsTypedefUID:
- m_clang_type = void_clang_type.CreateTypedefType (GetName().AsCString(),
- GetSymbolFile()->GetClangDeclContextContainingTypeUID(GetID()));
+ m_compiler_type = void_compiler_type.CreateTypedef(GetName().AsCString(),
+ GetSymbolFile()->GetDeclContextContainingUID(GetID()));
break;
case eEncodingIsPointerUID:
- m_clang_type = void_clang_type.GetPointerType ();
+ m_compiler_type = void_compiler_type.GetPointerType ();
break;
case eEncodingIsLValueReferenceUID:
- m_clang_type = void_clang_type.GetLValueReferenceType ();
+ m_compiler_type = void_compiler_type.GetLValueReferenceType();
break;
case eEncodingIsRValueReferenceUID:
- m_clang_type = void_clang_type.GetRValueReferenceType ();
+ m_compiler_type = void_compiler_type.GetRValueReferenceType();
break;
default:
@@ -590,25 +627,25 @@ Type::ResolveClangType (ResolveState clang_type_resolve_state)
}
}
- // When we have a EncodingUID, our "m_flags.clang_type_resolve_state" is set to eResolveStateUnresolved
+ // When we have a EncodingUID, our "m_flags.compiler_type_resolve_state" is set to eResolveStateUnresolved
// so we need to update it to say that we now have a forward declaration since that is what we created
// above.
- if (m_clang_type.IsValid())
- m_flags.clang_type_resolve_state = eResolveStateForward;
+ if (m_compiler_type.IsValid())
+ m_flags.compiler_type_resolve_state = eResolveStateForward;
}
// Check if we have a forward reference to a class/struct/union/enum?
- if (clang_type_resolve_state == eResolveStateLayout || clang_type_resolve_state == eResolveStateFull)
+ if (compiler_type_resolve_state == eResolveStateLayout || compiler_type_resolve_state == eResolveStateFull)
{
// Check if we have a forward reference to a class/struct/union/enum?
- if (m_clang_type.IsValid() && m_flags.clang_type_resolve_state < clang_type_resolve_state)
+ if (m_compiler_type.IsValid() && m_flags.compiler_type_resolve_state < compiler_type_resolve_state)
{
- m_flags.clang_type_resolve_state = eResolveStateFull;
- if (!m_clang_type.IsDefined ())
+ m_flags.compiler_type_resolve_state = eResolveStateFull;
+ if (!m_compiler_type.IsDefined ())
{
// We have a forward declaration, we need to resolve it to a complete definition.
- m_symbol_file->ResolveClangOpaqueTypeDefinition (m_clang_type);
+ m_symbol_file->CompleteType (m_compiler_type);
}
}
}
@@ -621,25 +658,25 @@ Type::ResolveClangType (ResolveState clang_type_resolve_state)
encoding_type = GetEncodingType();
if (encoding_type)
{
- ResolveState encoding_clang_type_resolve_state = clang_type_resolve_state;
+ ResolveState encoding_compiler_type_resolve_state = compiler_type_resolve_state;
- if (clang_type_resolve_state == eResolveStateLayout)
+ if (compiler_type_resolve_state == eResolveStateLayout)
{
switch (m_encoding_uid_type)
{
case eEncodingIsPointerUID:
case eEncodingIsLValueReferenceUID:
case eEncodingIsRValueReferenceUID:
- encoding_clang_type_resolve_state = eResolveStateForward;
+ encoding_compiler_type_resolve_state = eResolveStateForward;
break;
default:
break;
}
}
- encoding_type->ResolveClangType (encoding_clang_type_resolve_state);
+ encoding_type->ResolveClangType (encoding_compiler_type_resolve_state);
}
}
- return m_clang_type.IsValid();
+ return m_compiler_type.IsValid();
}
uint32_t
Type::GetEncodingMask ()
@@ -652,31 +689,25 @@ Type::GetEncodingMask ()
return encoding_mask;
}
-ClangASTType
-Type::GetClangFullType ()
+CompilerType
+Type::GetFullCompilerType ()
{
ResolveClangType(eResolveStateFull);
- return m_clang_type;
+ return m_compiler_type;
}
-ClangASTType
-Type::GetClangLayoutType ()
+CompilerType
+Type::GetLayoutCompilerType ()
{
ResolveClangType(eResolveStateLayout);
- return m_clang_type;
+ return m_compiler_type;
}
-ClangASTType
-Type::GetClangForwardType ()
+CompilerType
+Type::GetForwardCompilerType ()
{
ResolveClangType (eResolveStateForward);
- return m_clang_type;
-}
-
-ClangASTContext &
-Type::GetClangASTContext ()
-{
- return m_symbol_file->GetClangASTContext();
+ return m_compiler_type;
}
int
@@ -690,64 +721,14 @@ Type::Compare(const Type &a, const Type &b)
if (a_uid > b_uid)
return 1;
return 0;
-// if (a.getQualType() == b.getQualType())
-// return 0;
-}
-
-
-#if 0 // START REMOVE
-// Move this into ClangASTType
-void *
-Type::CreateClangPointerType (Type *type)
-{
- assert(type);
- return GetClangASTContext().CreatePointerType(type->GetClangForwardType());
-}
-
-void *
-Type::CreateClangTypedefType (Type *typedef_type, Type *base_type)
-{
- assert(typedef_type && base_type);
- return GetClangASTContext().CreateTypedefType (typedef_type->GetName().AsCString(),
- base_type->GetClangForwardType(),
- typedef_type->GetSymbolFile()->GetClangDeclContextContainingTypeUID(typedef_type->GetID()));
-}
-
-void *
-Type::CreateClangLValueReferenceType (Type *type)
-{
- assert(type);
- return GetClangASTContext().CreateLValueReferenceType(type->GetClangForwardType());
-}
-
-void *
-Type::CreateClangRValueReferenceType (Type *type)
-{
- assert(type);
- return GetClangASTContext().CreateRValueReferenceType (type->GetClangForwardType());
-}
-#endif // END REMOVE
-
-bool
-Type::IsRealObjCClass()
-{
- // For now we are just skipping ObjC classes that get made by hand from the runtime, because
- // those don't have any information. We could extend this to only return true for "full
- // definitions" if we can figure that out.
-
- if (m_clang_type.IsObjCObjectOrInterfaceType() && GetByteSize() != 0)
- return true;
- else
- return false;
}
ConstString
Type::GetQualifiedName ()
{
- return GetClangForwardType().GetConstTypeName();
+ return GetForwardCompilerType ().GetConstTypeName();
}
-
bool
Type::GetTypeScopeAndBasename (const char* &name_cstr,
std::string &scope,
@@ -905,9 +886,9 @@ TypeAndOrName::SetTypeSP (lldb::TypeSP type_sp)
}
void
-TypeAndOrName::SetClangASTType (ClangASTType clang_type)
+TypeAndOrName::SetCompilerType (CompilerType compiler_type)
{
- m_type_pair.SetType(clang_type);
+ m_type_pair.SetType(compiler_type);
if (m_type_pair)
m_type_name = m_type_pair.GetName();
}
@@ -941,9 +922,9 @@ TypeAndOrName::HasTypeSP () const
}
bool
-TypeAndOrName::HasClangASTType () const
+TypeAndOrName::HasCompilerType () const
{
- return m_type_pair.GetClangASTType().IsValid();
+ return m_type_pair.GetCompilerType().IsValid();
}
@@ -969,15 +950,15 @@ TypeImpl::TypeImpl (const lldb::TypeSP &type_sp) :
SetType (type_sp);
}
-TypeImpl::TypeImpl (const ClangASTType &clang_type) :
+TypeImpl::TypeImpl (const CompilerType &compiler_type) :
m_module_wp (),
m_static_type(),
m_dynamic_type()
{
- SetType (clang_type);
+ SetType (compiler_type);
}
-TypeImpl::TypeImpl (const lldb::TypeSP &type_sp, const ClangASTType &dynamic) :
+TypeImpl::TypeImpl (const lldb::TypeSP &type_sp, const CompilerType &dynamic) :
m_module_wp (),
m_static_type (type_sp),
m_dynamic_type(dynamic)
@@ -985,7 +966,7 @@ TypeImpl::TypeImpl (const lldb::TypeSP &type_sp, const ClangASTType &dynamic) :
SetType (type_sp, dynamic);
}
-TypeImpl::TypeImpl (const ClangASTType &static_type, const ClangASTType &dynamic_type) :
+TypeImpl::TypeImpl (const CompilerType &static_type, const CompilerType &dynamic_type) :
m_module_wp (),
m_static_type (),
m_dynamic_type()
@@ -993,7 +974,7 @@ TypeImpl::TypeImpl (const ClangASTType &static_type, const ClangASTType &dynamic
SetType (static_type, dynamic_type);
}
-TypeImpl::TypeImpl (const TypePair &pair, const ClangASTType &dynamic) :
+TypeImpl::TypeImpl (const TypePair &pair, const CompilerType &dynamic) :
m_module_wp (),
m_static_type (),
m_dynamic_type()
@@ -1012,29 +993,29 @@ TypeImpl::SetType (const lldb::TypeSP &type_sp)
}
void
-TypeImpl::SetType (const ClangASTType &clang_type)
+TypeImpl::SetType (const CompilerType &compiler_type)
{
m_module_wp = lldb::ModuleWP();
- m_static_type.SetType (clang_type);
+ m_static_type.SetType (compiler_type);
}
void
-TypeImpl::SetType (const lldb::TypeSP &type_sp, const ClangASTType &dynamic)
+TypeImpl::SetType (const lldb::TypeSP &type_sp, const CompilerType &dynamic)
{
SetType (type_sp);
m_dynamic_type = dynamic;
}
void
-TypeImpl::SetType (const ClangASTType &clang_type, const ClangASTType &dynamic)
+TypeImpl::SetType (const CompilerType &compiler_type, const CompilerType &dynamic)
{
m_module_wp = lldb::ModuleWP();
- m_static_type.SetType (clang_type);
+ m_static_type.SetType (compiler_type);
m_dynamic_type = dynamic;
}
void
-TypeImpl::SetType (const TypePair &pair, const ClangASTType &dynamic)
+TypeImpl::SetType (const TypePair &pair, const CompilerType &dynamic)
{
m_module_wp = pair.GetModule();
m_static_type = pair;
@@ -1249,8 +1230,8 @@ TypeImpl::GetCanonicalType() const
return TypeImpl();
}
-ClangASTType
-TypeImpl::GetClangASTType (bool prefer_dynamic)
+CompilerType
+TypeImpl::GetCompilerType (bool prefer_dynamic)
{
ModuleSP module_sp;
if (CheckModule (module_sp))
@@ -1260,13 +1241,13 @@ TypeImpl::GetClangASTType (bool prefer_dynamic)
if (m_dynamic_type.IsValid())
return m_dynamic_type;
}
- return m_static_type.GetClangASTType();
+ return m_static_type.GetCompilerType();
}
- return ClangASTType();
+ return CompilerType();
}
-clang::ASTContext *
-TypeImpl::GetClangASTContext (bool prefer_dynamic)
+TypeSystem *
+TypeImpl::GetTypeSystem (bool prefer_dynamic)
{
ModuleSP module_sp;
if (CheckModule (module_sp))
@@ -1274,9 +1255,9 @@ TypeImpl::GetClangASTContext (bool prefer_dynamic)
if (prefer_dynamic)
{
if (m_dynamic_type.IsValid())
- return m_dynamic_type.GetASTContext();
+ return m_dynamic_type.GetTypeSystem();
}
- return m_static_type.GetClangASTContext();
+ return m_static_type.GetCompilerType().GetTypeSystem();
}
return NULL;
}
@@ -1294,7 +1275,7 @@ TypeImpl::GetDescription (lldb_private::Stream &strm,
m_dynamic_type.DumpTypeDescription(&strm);
strm.Printf("\nStatic:\n");
}
- m_static_type.GetClangASTType().DumpTypeDescription(&strm);
+ m_static_type.GetCompilerType().DumpTypeDescription(&strm);
}
else
{
@@ -1303,19 +1284,6 @@ TypeImpl::GetDescription (lldb_private::Stream &strm,
return true;
}
-TypeMemberFunctionImpl&
-TypeMemberFunctionImpl::operator = (const TypeMemberFunctionImpl& rhs)
-{
- if (this != &rhs)
- {
- m_type = rhs.m_type;
- m_objc_method_decl = rhs.m_objc_method_decl;
- m_name = rhs.m_name;
- m_kind = rhs.m_kind;
- }
- return *this;
-}
-
bool
TypeMemberFunctionImpl::IsValid ()
{
@@ -1328,7 +1296,13 @@ TypeMemberFunctionImpl::GetName () const
return m_name;
}
-ClangASTType
+ConstString
+TypeMemberFunctionImpl::GetMangledName () const
+{
+ return m_decl.GetMangledName();
+}
+
+CompilerType
TypeMemberFunctionImpl::GetType () const
{
return m_type;
@@ -1340,21 +1314,6 @@ TypeMemberFunctionImpl::GetKind () const
return m_kind;
}
-std::string
-TypeMemberFunctionImpl::GetPrintableTypeName ()
-{
- if (m_type)
- return m_type.GetTypeName().AsCString("<unknown>");
- if (m_objc_method_decl)
- {
- if (m_objc_method_decl->getClassInterface())
- {
- return m_objc_method_decl->getClassInterface()->getName();
- }
- }
- return "<unknown>";
-}
-
bool
TypeMemberFunctionImpl::GetDescription (Stream& stream)
{
@@ -1362,33 +1321,31 @@ TypeMemberFunctionImpl::GetDescription (Stream& stream)
case lldb::eMemberFunctionKindUnknown:
return false;
case lldb::eMemberFunctionKindConstructor:
- stream.Printf("constructor for %s", GetPrintableTypeName().c_str());
+ stream.Printf("constructor for %s", m_type.GetTypeName().AsCString("<unknown>"));
break;
case lldb::eMemberFunctionKindDestructor:
- stream.Printf("destructor for %s", GetPrintableTypeName().c_str());
+ stream.Printf("destructor for %s", m_type.GetTypeName().AsCString("<unknown>"));
break;
case lldb::eMemberFunctionKindInstanceMethod:
stream.Printf("instance method %s of type %s",
m_name.AsCString(),
- GetPrintableTypeName().c_str());
+ m_decl.GetDeclContext().GetName().AsCString());
break;
case lldb::eMemberFunctionKindStaticMethod:
stream.Printf("static method %s of type %s",
m_name.AsCString(),
- GetPrintableTypeName().c_str());
+ m_decl.GetDeclContext().GetName().AsCString());
break;
}
return true;
}
-ClangASTType
+CompilerType
TypeMemberFunctionImpl::GetReturnType () const
{
if (m_type)
return m_type.GetFunctionReturnType();
- if (m_objc_method_decl)
- return ClangASTType(&m_objc_method_decl->getASTContext(),m_objc_method_decl->getReturnType().getAsOpaquePtr());
- return ClangASTType();
+ return m_decl.GetFunctionReturnType();
}
size_t
@@ -1396,37 +1353,26 @@ TypeMemberFunctionImpl::GetNumArguments () const
{
if (m_type)
return m_type.GetNumberOfFunctionArguments();
- if (m_objc_method_decl)
- return m_objc_method_decl->param_size();
- return 0;
+ else
+ return m_decl.GetNumFunctionArguments();
}
-ClangASTType
+CompilerType
TypeMemberFunctionImpl::GetArgumentAtIndex (size_t idx) const
{
if (m_type)
return m_type.GetFunctionArgumentAtIndex (idx);
- if (m_objc_method_decl)
- {
- if (idx < m_objc_method_decl->param_size())
- return ClangASTType(&m_objc_method_decl->getASTContext(), m_objc_method_decl->parameters()[idx]->getOriginalType().getAsOpaquePtr());
- }
- return ClangASTType();
+ else
+ return m_decl.GetFunctionArgumentType(idx);
}
-TypeEnumMemberImpl::TypeEnumMemberImpl (const clang::EnumConstantDecl* enum_member_decl,
- const lldb_private::ClangASTType& integer_type) :
- m_integer_type_sp(),
- m_name(),
- m_value(),
- m_valid(false)
+TypeEnumMemberImpl::TypeEnumMemberImpl (const lldb::TypeImplSP &integer_type_sp,
+ const ConstString &name,
+ const llvm::APSInt &value) :
+ m_integer_type_sp(integer_type_sp),
+ m_name(name),
+ m_value(value),
+ m_valid((bool)name && (bool)integer_type_sp)
{
- if (enum_member_decl)
- {
- m_integer_type_sp.reset(new TypeImpl(integer_type));
- m_name = ConstString(enum_member_decl->getNameAsString().c_str());
- m_value = enum_member_decl->getInitVal();
- m_valid = true;
- }
}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/TypeList.cpp b/contrib/llvm/tools/lldb/source/Symbol/TypeList.cpp
index 8d97b2b..f181dd6 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/TypeList.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/TypeList.cpp
@@ -13,18 +13,6 @@
#include <vector>
// Other libraries and framework includes
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclGroup.h"
-
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TargetInfo.h"
-
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
@@ -36,7 +24,6 @@
using namespace lldb;
using namespace lldb_private;
-using namespace clang;
TypeList::TypeList() :
m_types ()
@@ -55,26 +42,7 @@ TypeList::Insert (const TypeSP& type_sp)
{
// Just push each type on the back for now. We will worry about uniquing later
if (type_sp)
- m_types.insert(std::make_pair(type_sp->GetID(), type_sp));
-}
-
-
-bool
-TypeList::InsertUnique (const TypeSP& type_sp)
-{
- if (type_sp)
- {
- user_id_t type_uid = type_sp->GetID();
- iterator pos, end = m_types.end();
-
- for (pos = m_types.find(type_uid); pos != end && pos->second->GetID() == type_uid; ++pos)
- {
- if (pos->second.get() == type_sp.get())
- return false;
- }
- }
- Insert (type_sp);
- return true;
+ m_types.push_back(type_sp);
}
//----------------------------------------------------------------------
@@ -129,7 +97,7 @@ TypeList::GetTypeAtIndex(uint32_t idx)
for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
{
if (i == 0)
- return pos->second;
+ return *pos;
--i;
}
return TypeSP();
@@ -140,7 +108,7 @@ TypeList::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &call
{
for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
{
- if (!callback(pos->second))
+ if (!callback(*pos))
break;
}
}
@@ -150,32 +118,17 @@ TypeList::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback)
{
for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
{
- if (!callback(pos->second))
+ if (!callback(*pos))
break;
}
}
-
-bool
-TypeList::RemoveTypeWithUID (user_id_t uid)
-{
- iterator pos = m_types.find(uid);
-
- if (pos != m_types.end())
- {
- m_types.erase(pos);
- return true;
- }
- return false;
-}
-
-
void
TypeList::Dump(Stream *s, bool show_context)
{
for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
{
- pos->second->Dump(s, show_context);
+ pos->get()->Dump(s, show_context);
}
}
@@ -210,13 +163,13 @@ TypeList::RemoveMismatchedTypes (const std::string &type_scope,
for (pos = m_types.begin(); pos != end; ++pos)
{
- Type* the_type = pos->second.get();
+ Type* the_type = pos->get();
bool keep_match = false;
TypeClass match_type_class = eTypeClassAny;
if (type_class != eTypeClassAny)
{
- match_type_class = the_type->GetClangForwardType().GetTypeClass ();
+ match_type_class = the_type->GetForwardCompilerType ().GetTypeClass ();
if ((match_type_class & type_class) == 0)
continue;
}
@@ -249,9 +202,9 @@ TypeList::RemoveMismatchedTypes (const std::string &type_scope,
{
if (type_scope_pos >= 2)
{
- // Our match scope ends with the type scope we were lookikng for,
+ // Our match scope ends with the type scope we were looking for,
// but we need to make sure what comes before the matching
- // type scope is a namepace boundary in case we are trying to match:
+ // type scope is a namespace boundary in case we are trying to match:
// type_basename = "d"
// type_scope = "b::c::"
// We want to match:
@@ -282,7 +235,7 @@ TypeList::RemoveMismatchedTypes (const std::string &type_scope,
if (keep_match)
{
- matching_types.insert (*pos);
+ matching_types.push_back(*pos);
}
}
m_types.swap(matching_types);
@@ -304,10 +257,10 @@ TypeList::RemoveMismatchedTypes (TypeClass type_class)
for (pos = m_types.begin(); pos != end; ++pos)
{
- Type* the_type = pos->second.get();
- TypeClass match_type_class = the_type->GetClangForwardType().GetTypeClass ();
+ Type* the_type = pos->get();
+ TypeClass match_type_class = the_type->GetForwardCompilerType ().GetTypeClass ();
if (match_type_class & type_class)
- matching_types.insert (*pos);
+ matching_types.push_back (*pos);
}
m_types.swap(matching_types);
}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/TypeMap.cpp b/contrib/llvm/tools/lldb/source/Symbol/TypeMap.cpp
new file mode 100644
index 0000000..6dc22cc
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Symbol/TypeMap.cpp
@@ -0,0 +1,322 @@
+//===-- TypeMap.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/raw_ostream.h"
+
+// Project includes
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeMap.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace clang;
+
+TypeMap::TypeMap() :
+ m_types ()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+TypeMap::~TypeMap()
+{
+}
+
+void
+TypeMap::Insert (const TypeSP& type_sp)
+{
+ // Just push each type on the back for now. We will worry about uniquing later
+ if (type_sp)
+ m_types.insert(std::make_pair(type_sp->GetID(), type_sp));
+}
+
+
+bool
+TypeMap::InsertUnique (const TypeSP& type_sp)
+{
+ if (type_sp)
+ {
+ user_id_t type_uid = type_sp->GetID();
+ iterator pos, end = m_types.end();
+
+ for (pos = m_types.find(type_uid); pos != end && pos->second->GetID() == type_uid; ++pos)
+ {
+ if (pos->second.get() == type_sp.get())
+ return false;
+ }
+ Insert (type_sp);
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------
+// Find a base type by its unique ID.
+//----------------------------------------------------------------------
+//TypeSP
+//TypeMap::FindType(lldb::user_id_t uid)
+//{
+// iterator pos = m_types.find(uid);
+// if (pos != m_types.end())
+// return pos->second;
+// return TypeSP();
+//}
+
+//----------------------------------------------------------------------
+// Find a type by name.
+//----------------------------------------------------------------------
+//TypeMap
+//TypeMap::FindTypes (const ConstString &name)
+//{
+// // Do we ever need to make a lookup by name map? Here we are doing
+// // a linear search which isn't going to be fast.
+// TypeMap types(m_ast.getTargetInfo()->getTriple().getTriple().c_str());
+// iterator pos, end;
+// for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
+// if (pos->second->GetName() == name)
+// types.Insert (pos->second);
+// return types;
+//}
+
+void
+TypeMap::Clear()
+{
+ m_types.clear();
+}
+
+uint32_t
+TypeMap::GetSize() const
+{
+ return m_types.size();
+}
+
+bool
+TypeMap::Empty() const
+{
+ return m_types.empty();
+}
+
+// GetTypeAtIndex isn't used a lot for large type lists, currently only for
+// type lists that are returned for "image dump -t TYPENAME" commands and other
+// simple symbol queries that grab the first result...
+
+TypeSP
+TypeMap::GetTypeAtIndex(uint32_t idx)
+{
+ iterator pos, end;
+ uint32_t i = idx;
+ for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
+ {
+ if (i == 0)
+ return pos->second;
+ --i;
+ }
+ return TypeSP();
+}
+
+void
+TypeMap::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const
+{
+ for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
+ {
+ if (!callback(pos->second))
+ break;
+ }
+}
+
+void
+TypeMap::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback)
+{
+ for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
+ {
+ if (!callback(pos->second))
+ break;
+ }
+}
+
+bool
+TypeMap::Remove (const lldb::TypeSP &type_sp)
+{
+ if (type_sp)
+ {
+ lldb::user_id_t uid = type_sp->GetID();
+ for (iterator pos = m_types.find(uid), end = m_types.end(); pos != end && pos->first == uid; ++pos)
+ {
+ if (pos->second == type_sp)
+ {
+ m_types.erase(pos);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void
+TypeMap::Dump(Stream *s, bool show_context)
+{
+ for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos)
+ {
+ pos->second->Dump(s, show_context);
+ }
+}
+
+void
+TypeMap::RemoveMismatchedTypes (const char *qualified_typename,
+ bool exact_match)
+{
+ std::string type_scope;
+ std::string type_basename;
+ TypeClass type_class = eTypeClassAny;
+ if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class))
+ {
+ type_basename = qualified_typename;
+ type_scope.clear();
+ }
+ return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match);
+}
+
+void
+TypeMap::RemoveMismatchedTypes (const std::string &type_scope,
+ const std::string &type_basename,
+ TypeClass type_class,
+ bool exact_match)
+{
+ // Our "collection" type currently is a std::map which doesn't
+ // have any good way to iterate and remove items from the map
+ // so we currently just make a new list and add all of the matching
+ // types to it, and then swap it into m_types at the end
+ collection matching_types;
+
+ iterator pos, end = m_types.end();
+
+ for (pos = m_types.begin(); pos != end; ++pos)
+ {
+ Type* the_type = pos->second.get();
+ bool keep_match = false;
+ TypeClass match_type_class = eTypeClassAny;
+
+ if (type_class != eTypeClassAny)
+ {
+ match_type_class = the_type->GetForwardCompilerType ().GetTypeClass ();
+ if ((match_type_class & type_class) == 0)
+ continue;
+ }
+
+ ConstString match_type_name_const_str (the_type->GetQualifiedName());
+ if (match_type_name_const_str)
+ {
+ const char *match_type_name = match_type_name_const_str.GetCString();
+ std::string match_type_scope;
+ std::string match_type_basename;
+ if (Type::GetTypeScopeAndBasename (match_type_name,
+ match_type_scope,
+ match_type_basename,
+ match_type_class))
+ {
+ if (match_type_basename == type_basename)
+ {
+ const size_t type_scope_size = type_scope.size();
+ const size_t match_type_scope_size = match_type_scope.size();
+ if (exact_match || (type_scope_size == match_type_scope_size))
+ {
+ keep_match = match_type_scope == type_scope;
+ }
+ else
+ {
+ if (match_type_scope_size > type_scope_size)
+ {
+ const size_t type_scope_pos = match_type_scope.rfind(type_scope);
+ if (type_scope_pos == match_type_scope_size - type_scope_size)
+ {
+ if (type_scope_pos >= 2)
+ {
+ // Our match scope ends with the type scope we were looking for,
+ // but we need to make sure what comes before the matching
+ // type scope is a namespace boundary in case we are trying to match:
+ // type_basename = "d"
+ // type_scope = "b::c::"
+ // We want to match:
+ // match_type_scope "a::b::c::"
+ // But not:
+ // match_type_scope "a::bb::c::"
+ // So below we make sure what comes before "b::c::" in match_type_scope
+ // is "::", or the namespace boundary
+ if (match_type_scope[type_scope_pos - 1] == ':' &&
+ match_type_scope[type_scope_pos - 2] == ':')
+ {
+ keep_match = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // The type we are currently looking at doesn't exists
+ // in a namespace or class, so it only matches if there
+ // is no type scope...
+ keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0;
+ }
+ }
+
+ if (keep_match)
+ {
+ matching_types.insert (*pos);
+ }
+ }
+ m_types.swap(matching_types);
+}
+
+void
+TypeMap::RemoveMismatchedTypes (TypeClass type_class)
+{
+ if (type_class == eTypeClassAny)
+ return;
+
+ // Our "collection" type currently is a std::map which doesn't
+ // have any good way to iterate and remove items from the map
+ // so we currently just make a new list and add all of the matching
+ // types to it, and then swap it into m_types at the end
+ collection matching_types;
+
+ iterator pos, end = m_types.end();
+
+ for (pos = m_types.begin(); pos != end; ++pos)
+ {
+ Type* the_type = pos->second.get();
+ TypeClass match_type_class = the_type->GetForwardCompilerType ().GetTypeClass ();
+ if (match_type_class & type_class)
+ matching_types.insert (*pos);
+ }
+ m_types.swap(matching_types);
+}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/TypeSystem.cpp b/contrib/llvm/tools/lldb/source/Symbol/TypeSystem.cpp
new file mode 100644
index 0000000..5c2ab5c
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Symbol/TypeSystem.cpp
@@ -0,0 +1,255 @@
+//
+// TypeSystem.cpp
+// lldb
+//
+// Created by Ryan Brown on 3/29/15.
+//
+//
+
+#include "lldb/Symbol/TypeSystem.h"
+
+#include <set>
+
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/CompilerType.h"
+
+using namespace lldb_private;
+
+TypeSystem::TypeSystem(LLVMCastKind kind) :
+ m_kind (kind),
+ m_sym_file (nullptr)
+{
+}
+
+TypeSystem::~TypeSystem()
+{
+}
+
+lldb::TypeSystemSP
+TypeSystem::CreateInstance (lldb::LanguageType language, Module *module)
+{
+ uint32_t i = 0;
+ TypeSystemCreateInstance create_callback;
+ while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex (i++)) != nullptr)
+ {
+ lldb::TypeSystemSP type_system_sp = create_callback(language, module, nullptr);
+ if (type_system_sp)
+ return type_system_sp;
+ }
+
+ return lldb::TypeSystemSP();
+}
+
+lldb::TypeSystemSP
+TypeSystem::CreateInstance (lldb::LanguageType language, Target *target)
+{
+ uint32_t i = 0;
+ TypeSystemCreateInstance create_callback;
+ while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex (i++)) != nullptr)
+ {
+ lldb::TypeSystemSP type_system_sp = create_callback(language, nullptr, target);
+ if (type_system_sp)
+ return type_system_sp;
+ }
+
+ return lldb::TypeSystemSP();
+}
+
+bool
+TypeSystem::IsAnonymousType (lldb::opaque_compiler_type_t type)
+{
+ return false;
+}
+
+CompilerType
+TypeSystem::GetLValueReferenceType (lldb::opaque_compiler_type_t type)
+{
+ return CompilerType();
+}
+
+CompilerType
+TypeSystem::GetRValueReferenceType (lldb::opaque_compiler_type_t type)
+{
+ return CompilerType();
+}
+
+CompilerType
+TypeSystem::AddConstModifier (lldb::opaque_compiler_type_t type)
+{
+ return CompilerType();
+}
+
+CompilerType
+TypeSystem::AddVolatileModifier (lldb::opaque_compiler_type_t type)
+{
+ return CompilerType();
+}
+
+CompilerType
+TypeSystem::AddRestrictModifier (lldb::opaque_compiler_type_t type)
+{
+ return CompilerType();
+}
+
+CompilerType
+TypeSystem::CreateTypedef (lldb::opaque_compiler_type_t type, const char *name, const CompilerDeclContext &decl_ctx)
+{
+ return CompilerType();
+}
+
+CompilerType
+TypeSystem::GetBuiltinTypeByName (const ConstString &name)
+{
+ return CompilerType();
+}
+
+CompilerType
+TypeSystem::GetTypeForFormatters (void* type)
+{
+ return CompilerType(this, type);
+}
+
+LazyBool
+TypeSystem::ShouldPrintAsOneLiner (void* type, ValueObject* valobj)
+{
+ return eLazyBoolCalculate;
+}
+
+bool
+TypeSystem::IsMeaninglessWithoutDynamicResolution (void* type)
+{
+ return false;
+}
+
+ConstString
+TypeSystem::DeclGetMangledName (void *opaque_decl)
+{
+ return ConstString();
+}
+
+CompilerDeclContext
+TypeSystem::DeclGetDeclContext (void *opaque_decl)
+{
+ return CompilerDeclContext();
+}
+
+CompilerType
+TypeSystem::DeclGetFunctionReturnType(void *opaque_decl)
+{
+ return CompilerType();
+}
+
+size_t
+TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl)
+{
+ return 0;
+}
+
+CompilerType
+TypeSystem::DeclGetFunctionArgumentType (void *opaque_decl, size_t arg_idx)
+{
+ return CompilerType();
+}
+
+
+std::vector<CompilerDecl>
+TypeSystem::DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name)
+{
+ return std::vector<CompilerDecl>();
+}
+
+
+#pragma mark TypeSystemMap
+
+TypeSystemMap::TypeSystemMap() :
+ m_mutex (),
+ m_map ()
+{
+}
+
+TypeSystemMap::~TypeSystemMap()
+{
+}
+
+void
+TypeSystemMap::Clear ()
+{
+ Mutex::Locker locker (m_mutex);
+ m_map.clear();
+}
+
+
+void
+TypeSystemMap::ForEach (std::function <bool(TypeSystem *)> const &callback)
+{
+ Mutex::Locker locker (m_mutex);
+ // Use a std::set so we only call the callback once for each unique
+ // TypeSystem instance
+ std::set<TypeSystem *> visited;
+ for (auto pair : m_map)
+ {
+ TypeSystem *type_system = pair.second.get();
+ if (type_system && !visited.count(type_system))
+ {
+ visited.insert(type_system);
+ if (callback (type_system) == false)
+ break;
+ }
+ }
+}
+
+TypeSystem *
+TypeSystemMap::GetTypeSystemForLanguage (lldb::LanguageType language, Module *module, bool can_create)
+{
+ Mutex::Locker locker (m_mutex);
+ collection::iterator pos = m_map.find(language);
+ if (pos != m_map.end())
+ return pos->second.get();
+
+ for (const auto &pair : m_map)
+ {
+ if (pair.second && pair.second->SupportsLanguage(language))
+ {
+ // Add a new mapping for "language" to point to an already existing
+ // TypeSystem that supports this language
+ m_map[language] = pair.second;
+ return pair.second.get();
+ }
+ }
+
+ if (!can_create)
+ return nullptr;
+
+ // Cache even if we get a shared pointer that contains null type system back
+ lldb::TypeSystemSP type_system_sp = TypeSystem::CreateInstance (language, module);
+ m_map[language] = type_system_sp;
+ return type_system_sp.get();
+}
+
+TypeSystem *
+TypeSystemMap::GetTypeSystemForLanguage (lldb::LanguageType language, Target *target, bool can_create)
+{
+ Mutex::Locker locker (m_mutex);
+ collection::iterator pos = m_map.find(language);
+ if (pos != m_map.end())
+ return pos->second.get();
+
+ for (const auto &pair : m_map)
+ {
+ if (pair.second && pair.second->SupportsLanguage(language))
+ {
+ // Add a new mapping for "language" to point to an already existing
+ // TypeSystem that supports this language
+ m_map[language] = pair.second;
+ return pair.second.get();
+ }
+ }
+
+ if (!can_create)
+ return nullptr;
+
+ // Cache even if we get a shared pointer that contains null type system back
+ lldb::TypeSystemSP type_system_sp = TypeSystem::CreateInstance (language, target);
+ m_map[language] = type_system_sp;
+ return type_system_sp.get();
+}
diff --git a/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp b/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp
index 90b33a6..ac7a9b0 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/UnwindTable.cpp
@@ -17,6 +17,7 @@
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
#include "lldb/Symbol/CompactUnwindInfo.h"
// There is one UnwindTable object per ObjectFile.
@@ -31,8 +32,9 @@ UnwindTable::UnwindTable (ObjectFile& objfile) :
m_unwinds (),
m_initialized (false),
m_mutex (),
- m_eh_frame (nullptr),
- m_compact_unwind (nullptr)
+ m_eh_frame_up (),
+ m_compact_unwind_up (),
+ m_arm_unwind_up ()
{
}
@@ -56,12 +58,21 @@ UnwindTable::Initialize ()
SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true);
if (sect.get())
{
- m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true);
+ m_eh_frame_up.reset(new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindEHFrame, true));
}
sect = sl->FindSectionByType (eSectionTypeCompactUnwind, true);
if (sect.get())
{
- m_compact_unwind = new CompactUnwindInfo(m_object_file, sect);
+ m_compact_unwind_up.reset(new CompactUnwindInfo(m_object_file, sect));
+ }
+ sect = sl->FindSectionByType (eSectionTypeARMexidx, true);
+ if (sect.get())
+ {
+ SectionSP sect_extab = sl->FindSectionByType (eSectionTypeARMextab, true);
+ if (sect_extab.get())
+ {
+ m_arm_unwind_up.reset(new ArmUnwindInfo(m_object_file, sect, sect_extab));
+ }
}
}
@@ -70,8 +81,6 @@ UnwindTable::Initialize ()
UnwindTable::~UnwindTable ()
{
- if (m_eh_frame)
- delete m_eh_frame;
}
FuncUnwindersSP
@@ -102,7 +111,7 @@ UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolConte
if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
{
// Does the eh_frame unwind info has a function bounds for this addr?
- if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
+ if (m_eh_frame_up == nullptr || !m_eh_frame_up->GetAddressRange (addr, range))
{
return no_unwind_found;
}
@@ -129,7 +138,7 @@ UnwindTable::GetUncachedFuncUnwindersContainingAddress (const Address& addr, Sym
if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
{
// Does the eh_frame unwind info has a function bounds for this addr?
- if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
+ if (m_eh_frame_up == nullptr || !m_eh_frame_up->GetAddressRange (addr, range))
{
return no_unwind_found;
}
@@ -158,14 +167,21 @@ DWARFCallFrameInfo *
UnwindTable::GetEHFrameInfo ()
{
Initialize();
- return m_eh_frame;
+ return m_eh_frame_up.get();
}
CompactUnwindInfo *
UnwindTable::GetCompactUnwindInfo ()
{
Initialize();
- return m_compact_unwind;
+ return m_compact_unwind_up.get();
+}
+
+ArmUnwindInfo *
+UnwindTable::GetArmUnwindInfo ()
+{
+ Initialize();
+ return m_arm_unwind_up.get();
}
bool
diff --git a/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp b/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp
index 2490e98..51d11b7 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/Variable.cpp
@@ -15,10 +15,14 @@
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/Process.h"
@@ -33,19 +37,17 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// Variable constructor
//----------------------------------------------------------------------
-Variable::Variable
-(
- lldb::user_id_t uid,
- const char *name,
- const char *mangled, // The mangled or fully qualified name of the variable.
- const lldb::SymbolFileTypeSP &symfile_type_sp,
- ValueType scope,
- SymbolContextScope *context,
- Declaration* decl_ptr,
- const DWARFExpression& location,
- bool external,
- bool artificial
-) :
+Variable::Variable (lldb::user_id_t uid,
+ const char *name,
+ const char *mangled, // The mangled or fully qualified name of the variable.
+ const lldb::SymbolFileTypeSP &symfile_type_sp,
+ ValueType scope,
+ SymbolContextScope *context,
+ Declaration* decl_ptr,
+ const DWARFExpression& location,
+ bool external,
+ bool artificial,
+ bool static_member) :
UserID(uid),
m_name(name),
m_mangled (ConstString(mangled)),
@@ -55,7 +57,8 @@ Variable::Variable
m_declaration(decl_ptr),
m_location(location),
m_external(external),
- m_artificial(artificial)
+ m_artificial(artificial),
+ m_static_member(static_member)
{
}
@@ -87,6 +90,13 @@ Variable::GetName() const
return m_name;
}
+ConstString
+Variable::GetUnqualifiedName() const
+{
+ return m_name;
+}
+
+
bool
Variable::NameMatches (const ConstString &name) const
{
@@ -228,6 +238,22 @@ Variable::MemorySize() const
return sizeof(Variable);
}
+CompilerDeclContext
+Variable::GetDeclContext ()
+{
+ Type *type = GetType();
+ return type->GetSymbolFile()->GetDeclContextContainingUID(GetID());
+}
+
+CompilerDecl
+Variable::GetDecl ()
+{
+ Type *type = GetType();
+ CompilerDecl decl = type->GetSymbolFile()->GetDeclForUID(GetID());
+ if (decl)
+ decl.GetTypeSystem()->DeclLinkToObject(decl.GetOpaqueDecl(), shared_from_this());
+ return decl;
+}
void
Variable::CalculateSymbolContext (SymbolContext *sc)
@@ -558,7 +584,7 @@ static void
PrivateAutoComplete (StackFrame *frame,
const std::string &partial_path,
const std::string &prefix_path, // Anything that has been resolved already will be in here
- const ClangASTType& clang_type,
+ const CompilerType& compiler_type,
StringList &matches,
bool &word_complete);
@@ -567,7 +593,7 @@ PrivateAutoCompleteMembers (StackFrame *frame,
const std::string &partial_member_name,
const std::string &partial_path,
const std::string &prefix_path, // Anything that has been resolved already will be in here
- const ClangASTType& clang_type,
+ const CompilerType& compiler_type,
StringList &matches,
bool &word_complete);
@@ -576,19 +602,19 @@ PrivateAutoCompleteMembers (StackFrame *frame,
const std::string &partial_member_name,
const std::string &partial_path,
const std::string &prefix_path, // Anything that has been resolved already will be in here
- const ClangASTType& clang_type,
+ const CompilerType& compiler_type,
StringList &matches,
bool &word_complete)
{
// We are in a type parsing child members
- const uint32_t num_bases = clang_type.GetNumDirectBaseClasses();
+ const uint32_t num_bases = compiler_type.GetNumDirectBaseClasses();
if (num_bases > 0)
{
for (uint32_t i = 0; i < num_bases; ++i)
{
- ClangASTType base_class_type (clang_type.GetDirectBaseClassAtIndex (i, nullptr));
+ CompilerType base_class_type = compiler_type.GetDirectBaseClassAtIndex(i, nullptr);
PrivateAutoCompleteMembers (frame,
partial_member_name,
@@ -600,13 +626,13 @@ PrivateAutoCompleteMembers (StackFrame *frame,
}
}
- const uint32_t num_vbases = clang_type.GetNumVirtualBaseClasses();
+ const uint32_t num_vbases = compiler_type.GetNumVirtualBaseClasses();
if (num_vbases > 0)
{
for (uint32_t i = 0; i < num_vbases; ++i)
{
- ClangASTType vbase_class_type (clang_type.GetVirtualBaseClassAtIndex(i,nullptr));
+ CompilerType vbase_class_type = compiler_type.GetVirtualBaseClassAtIndex(i,nullptr);
PrivateAutoCompleteMembers (frame,
partial_member_name,
@@ -619,7 +645,7 @@ PrivateAutoCompleteMembers (StackFrame *frame,
}
// We are in a type parsing child members
- const uint32_t num_fields = clang_type.GetNumFields();
+ const uint32_t num_fields = compiler_type.GetNumFields();
if (num_fields > 0)
{
@@ -627,7 +653,7 @@ PrivateAutoCompleteMembers (StackFrame *frame,
{
std::string member_name;
- ClangASTType member_clang_type = clang_type.GetFieldAtIndex (i, member_name, nullptr, nullptr, nullptr);
+ CompilerType member_compiler_type = compiler_type.GetFieldAtIndex (i, member_name, nullptr, nullptr, nullptr);
if (partial_member_name.empty() ||
member_name.find(partial_member_name) == 0)
@@ -637,7 +663,7 @@ PrivateAutoCompleteMembers (StackFrame *frame,
PrivateAutoComplete (frame,
partial_path,
prefix_path + member_name, // Anything that has been resolved already will be in here
- member_clang_type.GetCanonicalType(),
+ member_compiler_type.GetCanonicalType(),
matches,
word_complete);
}
@@ -654,17 +680,17 @@ static void
PrivateAutoComplete (StackFrame *frame,
const std::string &partial_path,
const std::string &prefix_path, // Anything that has been resolved already will be in here
- const ClangASTType& clang_type,
+ const CompilerType& compiler_type,
StringList &matches,
bool &word_complete)
{
// printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path = '%s'\n", prefix_path.c_str(), partial_path.c_str());
std::string remaining_partial_path;
- const lldb::TypeClass type_class = clang_type.GetTypeClass();
+ const lldb::TypeClass type_class = compiler_type.GetTypeClass();
if (partial_path.empty())
{
- if (clang_type.IsValid())
+ if (compiler_type.IsValid())
{
switch (type_class)
{
@@ -700,7 +726,7 @@ PrivateAutoComplete (StackFrame *frame,
case eTypeClassPointer:
{
bool omit_empty_base_classes = true;
- if (clang_type.GetNumChildren (omit_empty_base_classes) > 0)
+ if (compiler_type.GetNumChildren (omit_empty_base_classes) > 0)
matches.AppendString (prefix_path + "->");
else
{
@@ -742,7 +768,7 @@ PrivateAutoComplete (StackFrame *frame,
PrivateAutoComplete (frame,
partial_path.substr(1),
std::string("*"),
- clang_type,
+ compiler_type,
matches,
word_complete);
}
@@ -754,7 +780,7 @@ PrivateAutoComplete (StackFrame *frame,
PrivateAutoComplete (frame,
partial_path.substr(1),
std::string("&"),
- clang_type,
+ compiler_type,
matches,
word_complete);
}
@@ -767,7 +793,7 @@ PrivateAutoComplete (StackFrame *frame,
{
case lldb::eTypeClassPointer:
{
- ClangASTType pointee_type(clang_type.GetPointeeType());
+ CompilerType pointee_type(compiler_type.GetPointeeType());
if (partial_path[2])
{
// If there is more after the "->", then search deeper
@@ -797,7 +823,7 @@ PrivateAutoComplete (StackFrame *frame,
break;
case '.':
- if (clang_type.IsValid())
+ if (compiler_type.IsValid())
{
switch (type_class)
{
@@ -810,7 +836,7 @@ PrivateAutoComplete (StackFrame *frame,
PrivateAutoComplete (frame,
partial_path.substr(1),
prefix_path + ".",
- clang_type,
+ compiler_type,
matches,
word_complete);
@@ -822,7 +848,7 @@ PrivateAutoComplete (StackFrame *frame,
std::string(),
partial_path,
prefix_path + ".",
- clang_type,
+ compiler_type,
matches,
word_complete);
}
@@ -850,13 +876,13 @@ PrivateAutoComplete (StackFrame *frame,
std::string token(partial_path, 0, pos);
remaining_partial_path = partial_path.substr(pos);
- if (clang_type.IsValid())
+ if (compiler_type.IsValid())
{
PrivateAutoCompleteMembers (frame,
token,
remaining_partial_path,
prefix_path,
- clang_type,
+ compiler_type,
matches,
word_complete);
}
@@ -886,11 +912,11 @@ PrivateAutoComplete (StackFrame *frame,
Type *variable_type = variable->GetType();
if (variable_type)
{
- ClangASTType variable_clang_type (variable_type->GetClangForwardType());
+ CompilerType variable_compiler_type (variable_type->GetForwardCompilerType ());
PrivateAutoComplete (frame,
remaining_partial_path,
prefix_path + token, // Anything that has been resolved already will be in here
- variable_clang_type.GetCanonicalType(),
+ variable_compiler_type.GetCanonicalType(),
matches,
word_complete);
}
@@ -923,14 +949,14 @@ Variable::AutoComplete (const ExecutionContext &exe_ctx,
word_complete = false;
std::string partial_path;
std::string prefix_path;
- ClangASTType clang_type;
+ CompilerType compiler_type;
if (partial_path_cstr && partial_path_cstr[0])
partial_path = partial_path_cstr;
PrivateAutoComplete (exe_ctx.GetFramePtr(),
partial_path,
prefix_path,
- clang_type,
+ compiler_type,
matches,
word_complete);
diff --git a/contrib/llvm/tools/lldb/source/Symbol/VariableList.cpp b/contrib/llvm/tools/lldb/source/Symbol/VariableList.cpp
index 75eb870..487c571 100644
--- a/contrib/llvm/tools/lldb/source/Symbol/VariableList.cpp
+++ b/contrib/llvm/tools/lldb/source/Symbol/VariableList.cpp
@@ -100,7 +100,7 @@ VariableList::FindVariableIndex (const VariableSP &var_sp)
}
VariableSP
-VariableList::FindVariable(const ConstString& name)
+VariableList::FindVariable(const ConstString& name, bool include_static_members)
{
VariableSP var_sp;
iterator pos, end = m_variables.end();
@@ -108,15 +108,18 @@ VariableList::FindVariable(const ConstString& name)
{
if ((*pos)->NameMatches(name))
{
- var_sp = (*pos);
- break;
+ if (include_static_members || !(*pos)->IsStaticMember())
+ {
+ var_sp = (*pos);
+ break;
+ }
}
}
return var_sp;
}
VariableSP
-VariableList::FindVariable (const ConstString& name, lldb::ValueType value_type)
+VariableList::FindVariable (const ConstString& name, lldb::ValueType value_type, bool include_static_members)
{
VariableSP var_sp;
iterator pos, end = m_variables.end();
@@ -124,8 +127,11 @@ VariableList::FindVariable (const ConstString& name, lldb::ValueType value_type)
{
if ((*pos)->NameMatches(name) && (*pos)->GetScope() == value_type)
{
- var_sp = (*pos);
- break;
+ if (include_static_members || !(*pos)->IsStaticMember())
+ {
+ var_sp = (*pos);
+ break;
+ }
}
}
return var_sp;
diff --git a/contrib/llvm/tools/lldb/source/Target/ABI.cpp b/contrib/llvm/tools/lldb/source/Target/ABI.cpp
index 8809c1e..4d67cb4 100644
--- a/contrib/llvm/tools/lldb/source/Target/ABI.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ABI.cpp
@@ -11,8 +11,9 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Symbol/ClangASTType.h"
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -84,7 +85,7 @@ ABI::GetRegisterInfoByName (const ConstString &name, RegisterInfo &info)
bool
ABI::GetRegisterInfoByKind (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &info)
{
- if (reg_kind < eRegisterKindGCC || reg_kind >= kNumRegisterKinds)
+ if (reg_kind < eRegisterKindEHFrame || reg_kind >= kNumRegisterKinds)
return false;
uint32_t count = 0;
@@ -105,7 +106,7 @@ ABI::GetRegisterInfoByKind (RegisterKind reg_kind, uint32_t reg_num, RegisterInf
ValueObjectSP
ABI::GetReturnValueObject (Thread &thread,
- ClangASTType &ast_type,
+ CompilerType &ast_type,
bool persistent) const
{
if (!ast_type.IsValid())
@@ -123,8 +124,12 @@ ABI::GetReturnValueObject (Thread &thread,
if (persistent)
{
- ClangPersistentVariables& persistent_variables = thread.CalculateTarget()->GetPersistentVariables();
- ConstString persistent_variable_name (persistent_variables.GetNextPersistentVariableName());
+ PersistentExpressionState *persistent_expression_state = thread.CalculateTarget()->GetPersistentExpressionStateForLanguage(ast_type.GetMinimumLanguage());
+
+ if (!persistent_expression_state)
+ return ValueObjectSP();
+
+ ConstString persistent_variable_name (persistent_expression_state->GetNextPersistentVariableName());
lldb::ValueObjectSP const_valobj_sp;
@@ -141,7 +146,7 @@ ABI::GetReturnValueObject (Thread &thread,
return_valobj_sp = const_valobj_sp;
- ClangExpressionVariableSP clang_expr_variable_sp(persistent_variables.CreatePersistentVariable(return_valobj_sp));
+ ExpressionVariableSP clang_expr_variable_sp(persistent_expression_state->CreatePersistentVariable(return_valobj_sp));
assert (clang_expr_variable_sp.get());
diff --git a/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp
index f048c67..28cfab1 100644
--- a/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/CPPLanguageRuntime.cpp
@@ -20,137 +20,6 @@
using namespace lldb;
using namespace lldb_private;
-class CPPRuntimeEquivalents
-{
-public:
- CPPRuntimeEquivalents ()
- {
-
- m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("basic_string<char>"));
-
- // these two (with a prefixed std::) occur when c++stdlib string class occurs as a template argument in some STL container
- m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("std::basic_string<char>"));
-
- m_impl.Sort();
- }
-
- void
- Add (ConstString& type_name,
- ConstString& type_equivalent)
- {
- m_impl.Insert(type_name.AsCString(), type_equivalent);
- }
-
- uint32_t
- FindExactMatches (ConstString& type_name,
- std::vector<ConstString>& equivalents)
- {
-
- uint32_t count = 0;
-
- for (ImplData match = m_impl.FindFirstValueForName(type_name.AsCString());
- match != NULL;
- match = m_impl.FindNextValueForName(match))
- {
- equivalents.push_back(match->value);
- count++;
- }
-
- return count;
- }
-
- // partial matches can occur when a name with equivalents is a template argument.
- // e.g. we may have "class Foo" be a match for "struct Bar". if we have a typename
- // such as "class Templatized<class Foo, Anything>" we want this to be replaced with
- // "class Templatized<struct Bar, Anything>". Since partial matching is time consuming
- // once we get a partial match, we add it to the exact matches list for faster retrieval
- uint32_t
- FindPartialMatches (ConstString& type_name,
- std::vector<ConstString>& equivalents)
- {
-
- uint32_t count = 0;
-
- const char* type_name_cstr = type_name.AsCString();
-
- size_t items_count = m_impl.GetSize();
-
- for (size_t item = 0; item < items_count; item++)
- {
- const char* key_cstr = m_impl.GetCStringAtIndex(item);
- if ( strstr(type_name_cstr,key_cstr) )
- {
- count += AppendReplacements(type_name_cstr,
- key_cstr,
- equivalents);
- }
- }
-
- return count;
-
- }
-
-private:
-
- std::string& replace (std::string& target,
- std::string& pattern,
- std::string& with)
- {
- size_t pos;
- size_t pattern_len = pattern.size();
-
- while ( (pos = target.find(pattern)) != std::string::npos )
- target.replace(pos, pattern_len, with);
-
- return target;
- }
-
- uint32_t
- AppendReplacements (const char* original,
- const char *matching_key,
- std::vector<ConstString>& equivalents)
- {
-
- std::string matching_key_str(matching_key);
- ConstString original_const(original);
-
- uint32_t count = 0;
-
- for (ImplData match = m_impl.FindFirstValueForName(matching_key);
- match != NULL;
- match = m_impl.FindNextValueForName(match))
- {
- std::string target(original);
- std::string equiv_class(match->value.AsCString());
-
- replace (target, matching_key_str, equiv_class);
-
- ConstString target_const(target.c_str());
-
-// you will most probably want to leave this off since it might make this map grow indefinitely
-#ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW
- Add(original_const, target_const);
-#endif
- equivalents.push_back(target_const);
-
- count++;
- }
-
- return count;
- }
-
- typedef UniqueCStringMap<ConstString> Impl;
- typedef const Impl::Entry* ImplData;
- Impl m_impl;
-};
-
-static CPPRuntimeEquivalents&
-GetEquivalentsMap ()
-{
- static CPPRuntimeEquivalents g_equivalents_map;
- return g_equivalents_map;
-}
-
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
@@ -177,244 +46,3 @@ CPPLanguageRuntime::GetObjectDescription (Stream &str, Value &value, ExecutionCo
// C++ has no generic way to do this.
return false;
}
-
-bool
-CPPLanguageRuntime::IsCPPMangledName (const char *name)
-{
- // FIXME, we should really run through all the known C++ Language plugins and ask each one if
- // this is a C++ mangled name, but we can put that off till there is actually more than one
- // we care about.
-
- if (name && name[0] == '_' && name[1] == 'Z')
- return true;
- else
- return false;
-}
-
-bool
-CPPLanguageRuntime::ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier)
-{
- static RegularExpression g_basename_regex("^(([A-Za-z_][A-Za-z_0-9]*::)*)([A-Za-z_][A-Za-z_0-9]*)$");
- RegularExpression::Match match(4);
- if (g_basename_regex.Execute (name, &match))
- {
- match.GetMatchAtIndex(name, 1, context);
- match.GetMatchAtIndex(name, 3, identifier);
- return true;
- }
- return false;
-}
-
-uint32_t
-CPPLanguageRuntime::FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents)
-{
- uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents);
-
- bool might_have_partials=
- ( count == 0 ) // if we have a full name match just use it
- && (strchr(type_name.AsCString(), '<') != NULL // we should only have partial matches when templates are involved, check that we have
- && strchr(type_name.AsCString(), '>') != NULL); // angle brackets in the type_name before trying to scan for partial matches
-
- if ( might_have_partials )
- count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents);
-
- return count;
-}
-
-void
-CPPLanguageRuntime::MethodName::Clear()
-{
- m_full.Clear();
- m_basename = llvm::StringRef();
- m_context = llvm::StringRef();
- m_arguments = llvm::StringRef();
- m_qualifiers = llvm::StringRef();
- m_type = eTypeInvalid;
- m_parsed = false;
- m_parse_error = false;
-}
-
-bool
-ReverseFindMatchingChars (const llvm::StringRef &s,
- const llvm::StringRef &left_right_chars,
- size_t &left_pos,
- size_t &right_pos,
- size_t pos = llvm::StringRef::npos)
-{
- assert (left_right_chars.size() == 2);
- left_pos = llvm::StringRef::npos;
- const char left_char = left_right_chars[0];
- const char right_char = left_right_chars[1];
- pos = s.find_last_of(left_right_chars, pos);
- if (pos == llvm::StringRef::npos || s[pos] == left_char)
- return false;
- right_pos = pos;
- uint32_t depth = 1;
- while (pos > 0 && depth > 0)
- {
- pos = s.find_last_of(left_right_chars, pos);
- if (pos == llvm::StringRef::npos)
- return false;
- if (s[pos] == left_char)
- {
- if (--depth == 0)
- {
- left_pos = pos;
- return left_pos < right_pos;
- }
- }
- else if (s[pos] == right_char)
- {
- ++depth;
- }
- }
- return false;
-}
-
-
-void
-CPPLanguageRuntime::MethodName::Parse()
-{
- if (!m_parsed && m_full)
- {
-// ConstString mangled;
-// m_full.GetMangledCounterpart(mangled);
-// printf ("\n parsing = '%s'\n", m_full.GetCString());
-// if (mangled)
-// printf (" mangled = '%s'\n", mangled.GetCString());
- m_parse_error = false;
- m_parsed = true;
- llvm::StringRef full (m_full.GetCString());
-
- size_t arg_start, arg_end;
- llvm::StringRef parens("()", 2);
- if (ReverseFindMatchingChars (full, parens, arg_start, arg_end))
- {
- m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
- if (arg_end + 1 < full.size())
- m_qualifiers = full.substr(arg_end + 1);
- if (arg_start > 0)
- {
- size_t basename_end = arg_start;
- size_t context_start = 0;
- size_t context_end = llvm::StringRef::npos;
- if (basename_end > 0 && full[basename_end-1] == '>')
- {
- // TODO: handle template junk...
- // Templated function
- size_t template_start, template_end;
- llvm::StringRef lt_gt("<>", 2);
- if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end))
- {
- context_end = full.rfind(':', template_start);
- if (context_end == llvm::StringRef::npos)
- {
- // Check for templated functions that include return type like:
- // 'void foo<Int>()'
- context_end = full.rfind(' ', template_start);
- if (context_end != llvm::StringRef::npos)
- {
- context_start = context_end;
- }
- }
- }
- else
- {
- context_end = full.rfind(':', basename_end);
- }
- }
- else if (context_end == llvm::StringRef::npos)
- {
- context_end = full.rfind(':', basename_end);
- }
-
- if (context_end == llvm::StringRef::npos)
- m_basename = full.substr(0, basename_end);
- else
- {
- if (context_start < context_end)
- m_context = full.substr(context_start, context_end - 1);
- const size_t basename_begin = context_end + 1;
- m_basename = full.substr(basename_begin, basename_end - basename_begin);
- }
- m_type = eTypeUnknownMethod;
- }
- else
- {
- m_parse_error = true;
- return;
- }
-
-// if (!m_context.empty())
-// printf (" context = '%s'\n", m_context.str().c_str());
-// if (m_basename)
-// printf (" basename = '%s'\n", m_basename.GetCString());
-// if (!m_arguments.empty())
-// printf (" arguments = '%s'\n", m_arguments.str().c_str());
-// if (!m_qualifiers.empty())
-// printf ("qualifiers = '%s'\n", m_qualifiers.str().c_str());
-
- // Make sure we have a valid C++ basename with optional template args
- static RegularExpression g_identifier_regex("^~?([A-Za-z_][A-Za-z_0-9]*)(<.*>)?$");
- std::string basename_str(m_basename.str());
- bool basename_is_valid = g_identifier_regex.Execute (basename_str.c_str(), NULL);
- if (!basename_is_valid)
- {
- // Check for C++ operators
- if (m_basename.startswith("operator"))
- {
- static RegularExpression g_operator_regex("^(operator)( ?)([A-Za-z_][A-Za-z_0-9]*|\\(\\)|\\[\\]|[\\^<>=!\\/*+-]+)(<.*>)?(\\[\\])?$");
- basename_is_valid = g_operator_regex.Execute(basename_str.c_str(), NULL);
- }
- }
- if (!basename_is_valid)
- {
- // The C++ basename doesn't match our regular expressions so this can't
- // be a valid C++ method, clear everything out and indicate an error
- m_context = llvm::StringRef();
- m_basename = llvm::StringRef();
- m_arguments = llvm::StringRef();
- m_qualifiers = llvm::StringRef();
- m_parse_error = true;
- }
- }
- else
- {
- m_parse_error = true;
-// printf ("error: didn't find matching parens for arguments\n");
- }
- }
-}
-
-llvm::StringRef
-CPPLanguageRuntime::MethodName::GetBasename ()
-{
- if (!m_parsed)
- Parse();
- return m_basename;
-}
-
-llvm::StringRef
-CPPLanguageRuntime::MethodName::GetContext ()
-{
- if (!m_parsed)
- Parse();
- return m_context;
-}
-
-llvm::StringRef
-CPPLanguageRuntime::MethodName::GetArguments ()
-{
- if (!m_parsed)
- Parse();
- return m_arguments;
-}
-
-llvm::StringRef
-CPPLanguageRuntime::MethodName::GetQualifiers ()
-{
- if (!m_parsed)
- Parse();
- return m_qualifiers;
-}
-
diff --git a/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp b/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp
index 0371472..ff58436 100644
--- a/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ExecutionContext.cpp
@@ -262,7 +262,7 @@ ExecutionContext::GetByteOrder() const
m_target_sp->GetArchitecture().GetByteOrder();
if (m_process_sp)
m_process_sp->GetByteOrder();
- return lldb::endian::InlHostByteOrder();
+ return endian::InlHostByteOrder();
}
RegisterContext *
diff --git a/contrib/llvm/tools/lldb/source/Target/Language.cpp b/contrib/llvm/tools/lldb/source/Target/Language.cpp
new file mode 100644
index 0000000..d6c7e0a
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Target/Language.cpp
@@ -0,0 +1,458 @@
+//===-- Language.cpp -------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <functional>
+#include <map>
+#include <mutex>
+
+#include "lldb/Target/Language.h"
+
+#include "lldb/Host/Mutex.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+typedef std::unique_ptr<Language> LanguageUP;
+typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap;
+
+static LanguagesMap&
+GetLanguagesMap ()
+{
+ static LanguagesMap *g_map = nullptr;
+ static std::once_flag g_initialize;
+
+ std::call_once(g_initialize, [] {
+ g_map = new LanguagesMap(); // NOTE: INTENTIONAL LEAK due to global destructor chain
+ });
+
+ return *g_map;
+}
+static Mutex&
+GetLanguagesMutex ()
+{
+ static Mutex *g_mutex = nullptr;
+ static std::once_flag g_initialize;
+
+ std::call_once(g_initialize, [] {
+ g_mutex = new Mutex(); // NOTE: INTENTIONAL LEAK due to global destructor chain
+ });
+
+ return *g_mutex;
+}
+
+Language*
+Language::FindPlugin (lldb::LanguageType language)
+{
+ Mutex::Locker locker(GetLanguagesMutex());
+ LanguagesMap& map(GetLanguagesMap());
+ auto iter = map.find(language), end = map.end();
+ if (iter != end)
+ return iter->second.get();
+
+ Language *language_ptr = nullptr;
+ LanguageCreateInstance create_callback;
+
+ for (uint32_t idx = 0;
+ (create_callback = PluginManager::GetLanguageCreateCallbackAtIndex(idx)) != nullptr;
+ ++idx)
+ {
+ language_ptr = create_callback(language);
+
+ if (language_ptr)
+ {
+ map[language] = std::unique_ptr<Language>(language_ptr);
+ return language_ptr;
+ }
+ }
+
+ return nullptr;
+}
+
+void
+Language::ForEach (std::function<bool(Language*)> callback)
+{
+ Mutex::Locker locker(GetLanguagesMutex());
+ LanguagesMap& map(GetLanguagesMap());
+ for (const auto& entry : map)
+ {
+ if (!callback(entry.second.get()))
+ break;
+ }
+}
+
+bool
+Language::IsTopLevelFunction (Function& function)
+{
+ return false;
+}
+
+lldb::TypeCategoryImplSP
+Language::GetFormatters ()
+{
+ return nullptr;
+}
+
+HardcodedFormatters::HardcodedFormatFinder
+Language::GetHardcodedFormats ()
+{
+ return {};
+}
+
+HardcodedFormatters::HardcodedSummaryFinder
+Language::GetHardcodedSummaries ()
+{
+ return {};
+}
+
+HardcodedFormatters::HardcodedSyntheticFinder
+Language::GetHardcodedSynthetics ()
+{
+ return {};
+}
+
+HardcodedFormatters::HardcodedValidatorFinder
+Language::GetHardcodedValidators ()
+{
+ return {};
+}
+
+std::vector<ConstString>
+Language::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
+{
+ return {};
+}
+
+lldb_private::formatters::StringPrinter::EscapingHelper
+Language::GetStringPrinterEscapingHelper (lldb_private::formatters::StringPrinter::GetPrintableElementType elem_type)
+{
+ return StringPrinter::GetDefaultEscapingHelper(elem_type);
+}
+
+struct language_name_pair {
+ const char *name;
+ LanguageType type;
+};
+
+struct language_name_pair language_names[] =
+{
+ // To allow GetNameForLanguageType to be a simple array lookup, the first
+ // part of this array must follow enum LanguageType exactly.
+ { "unknown", eLanguageTypeUnknown },
+ { "c89", eLanguageTypeC89 },
+ { "c", eLanguageTypeC },
+ { "ada83", eLanguageTypeAda83 },
+ { "c++", eLanguageTypeC_plus_plus },
+ { "cobol74", eLanguageTypeCobol74 },
+ { "cobol85", eLanguageTypeCobol85 },
+ { "fortran77", eLanguageTypeFortran77 },
+ { "fortran90", eLanguageTypeFortran90 },
+ { "pascal83", eLanguageTypePascal83 },
+ { "modula2", eLanguageTypeModula2 },
+ { "java", eLanguageTypeJava },
+ { "c99", eLanguageTypeC99 },
+ { "ada95", eLanguageTypeAda95 },
+ { "fortran95", eLanguageTypeFortran95 },
+ { "pli", eLanguageTypePLI },
+ { "objective-c", eLanguageTypeObjC },
+ { "objective-c++", eLanguageTypeObjC_plus_plus },
+ { "upc", eLanguageTypeUPC },
+ { "d", eLanguageTypeD },
+ { "python", eLanguageTypePython },
+ { "opencl", eLanguageTypeOpenCL },
+ { "go", eLanguageTypeGo },
+ { "modula3", eLanguageTypeModula3 },
+ { "haskell", eLanguageTypeHaskell },
+ { "c++03", eLanguageTypeC_plus_plus_03 },
+ { "c++11", eLanguageTypeC_plus_plus_11 },
+ { "ocaml", eLanguageTypeOCaml },
+ { "rust", eLanguageTypeRust },
+ { "c11", eLanguageTypeC11 },
+ { "swift", eLanguageTypeSwift },
+ { "julia", eLanguageTypeJulia },
+ { "dylan", eLanguageTypeDylan },
+ { "c++14", eLanguageTypeC_plus_plus_14 },
+ { "fortran03", eLanguageTypeFortran03 },
+ { "fortran08", eLanguageTypeFortran08 },
+ // Vendor Extensions
+ { "mipsassem", eLanguageTypeMipsAssembler },
+ { "renderscript", eLanguageTypeExtRenderScript},
+ // Now synonyms, in arbitrary order
+ { "objc", eLanguageTypeObjC },
+ { "objc++", eLanguageTypeObjC_plus_plus },
+ { "pascal", eLanguageTypePascal83 }
+};
+
+static uint32_t num_languages = sizeof(language_names) / sizeof (struct language_name_pair);
+
+LanguageType
+Language::GetLanguageTypeFromString (const char *string)
+{
+ for (uint32_t i = 0; i < num_languages; i++)
+ {
+ if (strcasecmp (language_names[i].name, string) == 0)
+ return (LanguageType) language_names[i].type;
+ }
+ return eLanguageTypeUnknown;
+}
+
+const char *
+Language::GetNameForLanguageType (LanguageType language)
+{
+ if (language < num_languages)
+ return language_names[language].name;
+ else
+ return language_names[eLanguageTypeUnknown].name;
+}
+
+void
+Language::PrintAllLanguages (Stream &s, const char *prefix, const char *suffix)
+{
+ for (uint32_t i = 1; i < num_languages; i++)
+ {
+ s.Printf("%s%s%s", prefix, language_names[i].name, suffix);
+ }
+}
+
+void
+Language::ForAllLanguages (std::function<bool(lldb::LanguageType)> callback)
+{
+ for (uint32_t i = 1; i < num_languages; i++)
+ {
+ if (!callback(language_names[i].type))
+ break;
+ }
+}
+
+bool
+Language::LanguageIsCPlusPlus (LanguageType language)
+{
+ switch (language)
+ {
+ case eLanguageTypeC_plus_plus:
+ case eLanguageTypeC_plus_plus_03:
+ case eLanguageTypeC_plus_plus_11:
+ case eLanguageTypeC_plus_plus_14:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+Language::LanguageIsObjC (LanguageType language)
+{
+ switch (language)
+ {
+ case eLanguageTypeObjC:
+ case eLanguageTypeObjC_plus_plus:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+Language::LanguageIsC (LanguageType language)
+{
+ switch (language)
+ {
+ case eLanguageTypeC:
+ case eLanguageTypeC89:
+ case eLanguageTypeC99:
+ case eLanguageTypeC11:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+Language::LanguageIsPascal (LanguageType language)
+{
+ switch (language)
+ {
+ case eLanguageTypePascal83:
+ return true;
+ default:
+ return false;
+ }
+}
+
+LanguageType
+Language::GetPrimaryLanguage (LanguageType language)
+{
+ switch (language)
+ {
+ case eLanguageTypeC_plus_plus:
+ case eLanguageTypeC_plus_plus_03:
+ case eLanguageTypeC_plus_plus_11:
+ case eLanguageTypeC_plus_plus_14:
+ return eLanguageTypeC_plus_plus;
+ case eLanguageTypeC:
+ case eLanguageTypeC89:
+ case eLanguageTypeC99:
+ case eLanguageTypeC11:
+ return eLanguageTypeC;
+ case eLanguageTypeObjC:
+ case eLanguageTypeObjC_plus_plus:
+ return eLanguageTypeObjC;
+ case eLanguageTypePascal83:
+ case eLanguageTypeCobol74:
+ case eLanguageTypeCobol85:
+ case eLanguageTypeFortran77:
+ case eLanguageTypeFortran90:
+ case eLanguageTypeFortran95:
+ case eLanguageTypeFortran03:
+ case eLanguageTypeFortran08:
+ case eLanguageTypeAda83:
+ case eLanguageTypeAda95:
+ case eLanguageTypeModula2:
+ case eLanguageTypeJava:
+ case eLanguageTypePLI:
+ case eLanguageTypeUPC:
+ case eLanguageTypeD:
+ case eLanguageTypePython:
+ case eLanguageTypeOpenCL:
+ case eLanguageTypeGo:
+ case eLanguageTypeModula3:
+ case eLanguageTypeHaskell:
+ case eLanguageTypeOCaml:
+ case eLanguageTypeRust:
+ case eLanguageTypeSwift:
+ case eLanguageTypeJulia:
+ case eLanguageTypeDylan:
+ case eLanguageTypeMipsAssembler:
+ case eLanguageTypeExtRenderScript:
+ case eLanguageTypeUnknown:
+ default:
+ return language;
+ }
+}
+
+void
+Language::GetLanguagesSupportingTypeSystems (std::set<lldb::LanguageType> &languages,
+ std::set<lldb::LanguageType> &languages_for_expressions)
+{
+ uint32_t idx = 0;
+
+ while (TypeSystemEnumerateSupportedLanguages enumerate = PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex(idx++))
+ {
+ (*enumerate)(languages, languages_for_expressions);
+ }
+}
+
+void
+Language::GetLanguagesSupportingREPLs (std::set<lldb::LanguageType> &languages)
+{
+ uint32_t idx = 0;
+
+ while (REPLEnumerateSupportedLanguages enumerate = PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex(idx++))
+ {
+ (*enumerate)(languages);
+ }
+}
+
+std::unique_ptr<Language::TypeScavenger>
+Language::GetTypeScavenger ()
+{
+ return nullptr;
+}
+
+size_t
+Language::TypeScavenger::Find (ExecutionContextScope *exe_scope,
+ const char *key,
+ ResultSet &results,
+ bool append)
+{
+ if (!exe_scope || !exe_scope->CalculateTarget().get())
+ return false;
+
+ if (!key || !key[0])
+ return false;
+
+ if (!append)
+ results.clear();
+
+ size_t old_size = results.size();
+
+ if (this->Find_Impl(exe_scope, key, results))
+ return results.size() - old_size;
+ return 0;
+}
+
+bool
+Language::GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint,
+ std::string& prefix, std::string& suffix)
+{
+ return false;
+}
+
+DumpValueObjectOptions::DeclPrintingHelper
+Language::GetDeclPrintingHelper ()
+{
+ return nullptr;
+}
+
+LazyBool
+Language::IsLogicalTrue (ValueObject& valobj,
+ Error& error)
+{
+ return eLazyBoolCalculate;
+}
+
+bool
+Language::IsNilReference (ValueObject& valobj)
+{
+ return false;
+}
+
+bool
+Language::IsUninitializedReference (ValueObject& valobj)
+{
+ return false;
+}
+
+bool
+Language::GetFunctionDisplayName (const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ FunctionNameRepresentation representation,
+ Stream& s)
+{
+ return false;
+}
+
+void
+Language::GetExceptionResolverDescription(bool catch_on, bool throw_on, Stream &s)
+{
+ GetDefaultExceptionResolverDescription(catch_on, throw_on, s);
+}
+
+void
+Language::GetDefaultExceptionResolverDescription(bool catch_on, bool throw_on, Stream &s)
+{
+ s.Printf ("Exception breakpoint (catch: %s throw: %s)",
+ catch_on ? "on" : "off",
+ throw_on ? "on" : "off");
+}
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+Language::Language()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Language::~Language()
+{
+}
diff --git a/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp
index 9c7b441..b1e2b3e 100644
--- a/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/LanguageRuntime.cpp
@@ -1,4 +1,4 @@
-//===-- LanguageRuntime.cpp -------------------------------------------------*- C++ -*-===//
+//===-- LanguageRuntime.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,13 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Target/LanguageRuntime.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Core/PluginManager.h"
@@ -17,7 +23,6 @@
using namespace lldb;
using namespace lldb_private;
-
class ExceptionSearchFilter : public SearchFilter
{
public:
@@ -33,8 +38,7 @@ public:
UpdateModuleListIfNeeded ();
}
- virtual
- ~ExceptionSearchFilter() {};
+ ~ExceptionSearchFilter() override = default;
bool
ModulePasses (const lldb::ModuleSP &module_sp) override
@@ -52,7 +56,6 @@ public:
if (m_filter_sp)
return m_filter_sp->ModulePasses (spec);
return false;
-
}
void
@@ -133,11 +136,8 @@ public:
{
}
- virtual
- ~ExceptionBreakpointResolver()
- {
- }
-
+ ~ExceptionBreakpointResolver() override = default;
+
Searcher::CallbackReturn
SearchCallback (SearchFilter &filter,
SymbolContext &context,
@@ -163,10 +163,12 @@ public:
void
GetDescription (Stream *s) override
{
- s->Printf ("Exception breakpoint (catch: %s throw: %s)",
- m_catch_bp ? "on" : "off",
- m_throw_bp ? "on" : "off");
-
+ Language *language_plugin = Language::FindPlugin(m_language);
+ if (language_plugin)
+ language_plugin->GetExceptionResolverDescription(m_catch_bp, m_throw_bp, *s);
+ else
+ Language::GetDefaultExceptionResolverDescription(m_catch_bp, m_throw_bp, *s);
+
SetActualResolver();
if (m_actual_resolver_sp)
{
@@ -187,6 +189,7 @@ public:
static inline bool classof(const BreakpointResolver *V) {
return V->getResolverID() == BreakpointResolver::ExceptionResolver;
}
+
protected:
BreakpointResolverSP
CopyForBreakpoint (Breakpoint &breakpoint) override
@@ -244,7 +247,6 @@ protected:
bool m_throw_bp;
};
-
LanguageRuntime*
LanguageRuntime::FindPlugin (Process *process, lldb::LanguageType language)
{
@@ -264,20 +266,12 @@ LanguageRuntime::FindPlugin (Process *process, lldb::LanguageType language)
return NULL;
}
-//----------------------------------------------------------------------
-// Constructor
-//----------------------------------------------------------------------
LanguageRuntime::LanguageRuntime(Process *process) :
m_process (process)
{
}
-//----------------------------------------------------------------------
-// Destructor
-//----------------------------------------------------------------------
-LanguageRuntime::~LanguageRuntime()
-{
-}
+LanguageRuntime::~LanguageRuntime() = default;
Breakpoint::BreakpointPreconditionSP
LanguageRuntime::CreateExceptionPrecondition (lldb::LanguageType language,
@@ -321,105 +315,6 @@ LanguageRuntime::CreateExceptionBreakpoint (Target &target,
return exc_breakpt_sp;
}
-struct language_name_pair {
- const char *name;
- LanguageType type;
-};
-
-struct language_name_pair language_names[] =
-{
- // To allow GetNameForLanguageType to be a simple array lookup, the first
- // part of this array must follow enum LanguageType exactly.
- { "unknown", eLanguageTypeUnknown },
- { "c89", eLanguageTypeC89 },
- { "c", eLanguageTypeC },
- { "ada83", eLanguageTypeAda83 },
- { "c++", eLanguageTypeC_plus_plus },
- { "cobol74", eLanguageTypeCobol74 },
- { "cobol85", eLanguageTypeCobol85 },
- { "fortran77", eLanguageTypeFortran77 },
- { "fortran90", eLanguageTypeFortran90 },
- { "pascal83", eLanguageTypePascal83 },
- { "modula2", eLanguageTypeModula2 },
- { "java", eLanguageTypeJava },
- { "c99", eLanguageTypeC99 },
- { "ada95", eLanguageTypeAda95 },
- { "fortran95", eLanguageTypeFortran95 },
- { "pli", eLanguageTypePLI },
- { "objective-c", eLanguageTypeObjC },
- { "objective-c++", eLanguageTypeObjC_plus_plus },
- { "upc", eLanguageTypeUPC },
- { "d", eLanguageTypeD },
- { "python", eLanguageTypePython },
- { "opencl", eLanguageTypeOpenCL },
- { "go", eLanguageTypeGo },
- { "modula3", eLanguageTypeModula3 },
- { "haskell", eLanguageTypeHaskell },
- { "c++03", eLanguageTypeC_plus_plus_03 },
- { "c++11", eLanguageTypeC_plus_plus_11 },
- { "ocaml", eLanguageTypeOCaml },
- { "rust", eLanguageTypeRust },
- { "c11", eLanguageTypeC11 },
- { "swift", eLanguageTypeSwift },
- { "julia", eLanguageTypeJulia },
- { "dylan", eLanguageTypeDylan },
- { "c++14", eLanguageTypeC_plus_plus_14 },
- { "fortran03", eLanguageTypeFortran03 },
- { "fortran08", eLanguageTypeFortran08 },
- // Vendor Extensions
- { "mipsassem", eLanguageTypeMipsAssembler },
- { "renderscript", eLanguageTypeExtRenderScript},
- // Now synonyms, in arbitrary order
- { "objc", eLanguageTypeObjC },
- { "objc++", eLanguageTypeObjC_plus_plus }
-};
-
-static uint32_t num_languages = sizeof(language_names) / sizeof (struct language_name_pair);
-
-LanguageType
-LanguageRuntime::GetLanguageTypeFromString (const char *string)
-{
- for (uint32_t i = 0; i < num_languages; i++)
- {
- if (strcasecmp (language_names[i].name, string) == 0)
- return (LanguageType) language_names[i].type;
- }
- return eLanguageTypeUnknown;
-}
-
-const char *
-LanguageRuntime::GetNameForLanguageType (LanguageType language)
-{
- if (language < num_languages)
- return language_names[language].name;
- else
- return language_names[eLanguageTypeUnknown].name;
-}
-
-void
-LanguageRuntime::PrintAllLanguages (Stream &s, const char *prefix, const char *suffix)
-{
- for (uint32_t i = 1; i < num_languages; i++)
- {
- s.Printf("%s%s%s", prefix, language_names[i].name, suffix);
- }
-}
-
-bool
-LanguageRuntime::LanguageIsCPlusPlus (LanguageType language)
-{
- switch (language)
- {
- case eLanguageTypeC_plus_plus:
- case eLanguageTypeC_plus_plus_03:
- case eLanguageTypeC_plus_plus_11:
- case eLanguageTypeC_plus_plus_14:
- return true;
- default:
- return false;
- }
-}
-
void
LanguageRuntime::InitializeCommands (CommandObject* parent)
{
@@ -452,6 +347,3 @@ LanguageRuntime::CreateExceptionSearchFilter ()
{
return m_process->GetTarget().GetSearchFilterForModule(NULL);
}
-
-
-
diff --git a/contrib/llvm/tools/lldb/source/Target/Memory.cpp b/contrib/llvm/tools/lldb/source/Target/Memory.cpp
index e61b3ab..c89fd51 100644
--- a/contrib/llvm/tools/lldb/source/Target/Memory.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Memory.cpp
@@ -164,24 +164,16 @@ MemoryCache::Read (addr_t addr,
if (!m_L1_cache.empty())
{
AddrRange read_range(addr, dst_len);
- BlockMap::iterator pos = m_L1_cache.lower_bound(addr);
- if (pos != m_L1_cache.end())
+ BlockMap::iterator pos = m_L1_cache.upper_bound(addr);
+ if (pos != m_L1_cache.begin ())
{
- AddrRange chunk_range(pos->first, pos->second->GetByteSize());
- bool match = chunk_range.Contains(read_range);
- if (!match && pos != m_L1_cache.begin())
- {
- --pos;
- chunk_range.SetRangeBase(pos->first);
- chunk_range.SetByteSize(pos->second->GetByteSize());
- match = chunk_range.Contains(read_range);
- }
-
- if (match)
- {
- memcpy(dst, pos->second->GetBytes() + addr - chunk_range.GetRangeBase(), dst_len);
- return dst_len;
- }
+ --pos;
+ }
+ AddrRange chunk_range(pos->first, pos->second->GetByteSize());
+ if (chunk_range.Contains(read_range))
+ {
+ memcpy(dst, pos->second->GetBytes() + addr - chunk_range.GetRangeBase(), dst_len);
+ return dst_len;
}
}
diff --git a/contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp b/contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp
index e54dd5b..a18e4c6 100644
--- a/contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ObjCLanguageRuntime.cpp
@@ -136,7 +136,7 @@ ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
{
TypeSP type_sp (types.GetTypeAtIndex(i));
- if (type_sp->GetClangForwardType().IsObjCObjectOrInterfaceType())
+ if (ClangASTContext::IsObjCObjectOrInterfaceType(type_sp->GetForwardCompilerType ()))
{
if (type_sp->IsCompleteObjCClass())
{
@@ -152,288 +152,11 @@ ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
}
size_t
-ObjCLanguageRuntime::GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name)
+ObjCLanguageRuntime::GetByteOffsetForIvar (CompilerType &parent_qual_type, const char *ivar_name)
{
return LLDB_INVALID_IVAR_OFFSET;
}
-void
-ObjCLanguageRuntime::MethodName::Clear()
-{
- m_full.Clear();
- m_class.Clear();
- m_category.Clear();
- m_selector.Clear();
- m_type = eTypeUnspecified;
- m_category_is_valid = false;
-}
-
-//bool
-//ObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict)
-//{
-// Clear();
-// if (name && name[0])
-// {
-// // If "strict" is true. then the method must be specified with a
-// // '+' or '-' at the beginning. If "strict" is false, then the '+'
-// // or '-' can be omitted
-// bool valid_prefix = false;
-//
-// if (name[0] == '+' || name[0] == '-')
-// {
-// valid_prefix = name[1] == '[';
-// }
-// else if (!strict)
-// {
-// // "strict" is false, the name just needs to start with '['
-// valid_prefix = name[0] == '[';
-// }
-//
-// if (valid_prefix)
-// {
-// static RegularExpression g_regex("^([-+]?)\\[([A-Za-z_][A-Za-z_0-9]*)(\\([A-Za-z_][A-Za-z_0-9]*\\))? ([A-Za-z_][A-Za-z_0-9:]*)\\]$");
-// llvm::StringRef matches[4];
-// // Since we are using a global regular expression, we must use the threadsafe version of execute
-// if (g_regex.ExecuteThreadSafe(name, matches, 4))
-// {
-// m_full.SetCString(name);
-// if (matches[0].empty())
-// m_type = eTypeUnspecified;
-// else if (matches[0][0] == '+')
-// m_type = eTypeClassMethod;
-// else
-// m_type = eTypeInstanceMethod;
-// m_class.SetString(matches[1]);
-// m_selector.SetString(matches[3]);
-// if (!matches[2].empty())
-// m_category.SetString(matches[2]);
-// }
-// }
-// }
-// return IsValid(strict);
-//}
-
-bool
-ObjCLanguageRuntime::MethodName::SetName (const char *name, bool strict)
-{
- Clear();
- if (name && name[0])
- {
- // If "strict" is true. then the method must be specified with a
- // '+' or '-' at the beginning. If "strict" is false, then the '+'
- // or '-' can be omitted
- bool valid_prefix = false;
-
- if (name[0] == '+' || name[0] == '-')
- {
- valid_prefix = name[1] == '[';
- if (name[0] == '+')
- m_type = eTypeClassMethod;
- else
- m_type = eTypeInstanceMethod;
- }
- else if (!strict)
- {
- // "strict" is false, the name just needs to start with '['
- valid_prefix = name[0] == '[';
- }
-
- if (valid_prefix)
- {
- int name_len = strlen (name);
- // Objective C methods must have at least:
- // "-[" or "+[" prefix
- // One character for a class name
- // One character for the space between the class name
- // One character for the method name
- // "]" suffix
- if (name_len >= (5 + (strict ? 1 : 0)) && name[name_len - 1] == ']')
- {
- m_full.SetCStringWithLength(name, name_len);
- }
- }
- }
- return IsValid(strict);
-}
-
-const ConstString &
-ObjCLanguageRuntime::MethodName::GetClassName ()
-{
- if (!m_class)
- {
- if (IsValid(false))
- {
- const char *full = m_full.GetCString();
- const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
- const char *paren_pos = strchr (class_start, '(');
- if (paren_pos)
- {
- m_class.SetCStringWithLength (class_start, paren_pos - class_start);
- }
- else
- {
- // No '(' was found in the full name, we can definitively say
- // that our category was valid (and empty).
- m_category_is_valid = true;
- const char *space_pos = strchr (full, ' ');
- if (space_pos)
- {
- m_class.SetCStringWithLength (class_start, space_pos - class_start);
- if (!m_class_category)
- {
- // No category in name, so we can also fill in the m_class_category
- m_class_category = m_class;
- }
- }
- }
- }
- }
- return m_class;
-}
-
-const ConstString &
-ObjCLanguageRuntime::MethodName::GetClassNameWithCategory ()
-{
- if (!m_class_category)
- {
- if (IsValid(false))
- {
- const char *full = m_full.GetCString();
- const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
- const char *space_pos = strchr (full, ' ');
- if (space_pos)
- {
- m_class_category.SetCStringWithLength (class_start, space_pos - class_start);
- // If m_class hasn't been filled in and the class with category doesn't
- // contain a '(', then we can also fill in the m_class
- if (!m_class && strchr (m_class_category.GetCString(), '(') == NULL)
- {
- m_class = m_class_category;
- // No '(' was found in the full name, we can definitively say
- // that our category was valid (and empty).
- m_category_is_valid = true;
-
- }
- }
- }
- }
- return m_class_category;
-}
-
-const ConstString &
-ObjCLanguageRuntime::MethodName::GetSelector ()
-{
- if (!m_selector)
- {
- if (IsValid(false))
- {
- const char *full = m_full.GetCString();
- const char *space_pos = strchr (full, ' ');
- if (space_pos)
- {
- ++space_pos; // skip the space
- m_selector.SetCStringWithLength (space_pos, m_full.GetLength() - (space_pos - full) - 1);
- }
- }
- }
- return m_selector;
-}
-
-const ConstString &
-ObjCLanguageRuntime::MethodName::GetCategory ()
-{
- if (!m_category_is_valid && !m_category)
- {
- if (IsValid(false))
- {
- m_category_is_valid = true;
- const char *full = m_full.GetCString();
- const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
- const char *open_paren_pos = strchr (class_start, '(');
- if (open_paren_pos)
- {
- ++open_paren_pos; // Skip the open paren
- const char *close_paren_pos = strchr (open_paren_pos, ')');
- if (close_paren_pos)
- m_category.SetCStringWithLength (open_paren_pos, close_paren_pos - open_paren_pos);
- }
- }
- }
- return m_category;
-}
-
-ConstString
-ObjCLanguageRuntime::MethodName::GetFullNameWithoutCategory (bool empty_if_no_category)
-{
- if (IsValid(false))
- {
- if (HasCategory())
- {
- StreamString strm;
- if (m_type == eTypeClassMethod)
- strm.PutChar('+');
- else if (m_type == eTypeInstanceMethod)
- strm.PutChar('-');
- strm.Printf("[%s %s]", GetClassName().GetCString(), GetSelector().GetCString());
- return ConstString(strm.GetString().c_str());
- }
-
- if (!empty_if_no_category)
- {
- // Just return the full name since it doesn't have a category
- return GetFullName();
- }
- }
- return ConstString();
-}
-
-size_t
-ObjCLanguageRuntime::MethodName::GetFullNames (std::vector<ConstString> &names, bool append)
-{
- if (!append)
- names.clear();
- if (IsValid(false))
- {
- StreamString strm;
- const bool is_class_method = m_type == eTypeClassMethod;
- const bool is_instance_method = m_type == eTypeInstanceMethod;
- const ConstString &category = GetCategory();
- if (is_class_method || is_instance_method)
- {
- names.push_back (m_full);
- if (category)
- {
- strm.Printf("%c[%s %s]",
- is_class_method ? '+' : '-',
- GetClassName().GetCString(),
- GetSelector().GetCString());
- names.push_back(ConstString(strm.GetString().c_str()));
- }
- }
- else
- {
- const ConstString &class_name = GetClassName();
- const ConstString &selector = GetSelector();
- strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString());
- names.push_back(ConstString(strm.GetString().c_str()));
- strm.Clear();
- strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString());
- names.push_back(ConstString(strm.GetString().c_str()));
- strm.Clear();
- if (category)
- {
- strm.Printf("+[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
- names.push_back(ConstString(strm.GetString().c_str()));
- strm.Clear();
- strm.Printf("-[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
- names.push_back(ConstString(strm.GetString().c_str()));
- }
- }
- }
- return names.size();
-}
-
-
bool
ObjCLanguageRuntime::ClassDescriptor::IsPointerValid (lldb::addr_t value,
uint32_t ptr_size,
@@ -549,7 +272,7 @@ ObjCLanguageRuntime::GetClassDescriptor (ValueObject& valobj)
// if we get an invalid VO (which might still happen when playing around
// with pointers returned by the expression parser, don't consider this
// a valid ObjC object)
- if (valobj.GetClangType().IsValid())
+ if (valobj.GetCompilerType().IsValid())
{
addr_t isa_pointer = valobj.GetPointerValue();
if (isa_pointer != LLDB_INVALID_ADDRESS)
@@ -619,20 +342,20 @@ ObjCLanguageRuntime::GetNonKVOClassDescriptor (ObjCISA isa)
}
-ClangASTType
+CompilerType
ObjCLanguageRuntime::EncodingToType::RealizeType (const char* name, bool for_expression)
{
if (m_scratch_ast_ctx_ap)
return RealizeType(*m_scratch_ast_ctx_ap, name, for_expression);
- return ClangASTType();
+ return CompilerType();
}
-ClangASTType
+CompilerType
ObjCLanguageRuntime::EncodingToType::RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression)
{
clang::ASTContext *clang_ast = ast_ctx.getASTContext();
if (!clang_ast)
- return ClangASTType();
+ return CompilerType();
return RealizeType(*clang_ast, name, for_expression);
}
@@ -645,16 +368,16 @@ ObjCLanguageRuntime::GetEncodingToType ()
}
bool
-ObjCLanguageRuntime::GetTypeBitSize (const ClangASTType& clang_type,
+ObjCLanguageRuntime::GetTypeBitSize (const CompilerType& compiler_type,
uint64_t &size)
{
- void *opaque_ptr = clang_type.GetQualType().getAsOpaquePtr();
+ void *opaque_ptr = compiler_type.GetOpaqueQualType();
size = m_type_size_cache.Lookup(opaque_ptr);
// an ObjC object will at least have an ISA, so 0 is definitely not OK
if (size > 0)
return true;
- ClassDescriptorSP class_descriptor_sp = GetClassDescriptorFromClassName(clang_type.GetTypeName());
+ ClassDescriptorSP class_descriptor_sp = GetClassDescriptorFromClassName(compiler_type.GetTypeName());
if (!class_descriptor_sp)
return false;
@@ -703,7 +426,7 @@ ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(StoppointCa
}
void
-ObjCLanguageRuntime::ObjCExceptionPrecondition::DescribePrecondition(Stream &stream, lldb::DescriptionLevel level)
+ObjCLanguageRuntime::ObjCExceptionPrecondition::GetDescription(Stream &stream, lldb::DescriptionLevel level)
{
}
diff --git a/contrib/llvm/tools/lldb/source/Target/Platform.cpp b/contrib/llvm/tools/lldb/source/Target/Platform.cpp
index 2b58693..5077ca2 100644
--- a/contrib/llvm/tools/lldb/source/Target/Platform.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Platform.cpp
@@ -26,6 +26,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/FileSystem.h"
@@ -39,9 +40,11 @@
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/Utils.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
#include "Utility/ModuleCache.h"
+
// Define these constants from POSIX mman.h rather than include the file
// so that they will be correct even when compiled on Linux.
#define MAP_PRIVATE 2
@@ -99,13 +102,17 @@ PlatformProperties::PlatformProperties ()
m_collection_sp->Initialize (g_properties);
auto module_cache_dir = GetModuleCacheDirectory ();
- if (!module_cache_dir)
- {
- if (!HostInfo::GetLLDBPath (ePathTypeGlobalLLDBTempSystemDir, module_cache_dir))
- module_cache_dir = FileSpec ("/tmp/lldb", false);
- module_cache_dir.AppendPathComponent ("module_cache");
- SetModuleCacheDirectory (module_cache_dir);
- }
+ if (module_cache_dir)
+ return;
+
+ llvm::SmallString<64> user_home_dir;
+ if (!llvm::sys::path::home_directory (user_home_dir))
+ return;
+
+ module_cache_dir = FileSpec (user_home_dir.c_str(), false);
+ module_cache_dir.AppendPathComponent (".lldb");
+ module_cache_dir.AppendPathComponent ("module_cache");
+ SetModuleCacheDirectory (module_cache_dir);
}
bool
@@ -272,8 +279,11 @@ Platform::GetSharedModule (const ModuleSpec &module_spec,
module_sp,
[&](const ModuleSpec &spec)
{
- return ModuleList::GetSharedModule (
+ Error error = ModuleList::GetSharedModule (
spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr, false);
+ if (error.Success() && module_sp)
+ module_sp->SetPlatformFileSpec(spec.GetFileSpec());
+ return error;
},
did_create_ptr);
}
@@ -466,7 +476,11 @@ Platform::GetStatus (Stream &strm)
if (arch.IsValid())
{
if (!arch.GetTriple().str().empty())
- strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str());
+ {
+ strm.Printf(" Triple: ");
+ arch.DumpTriple(strm);
+ strm.EOL();
+ }
}
if (GetOSVersion(major, minor, update))
@@ -515,7 +529,8 @@ Platform::GetStatus (Stream &strm)
bool
Platform::GetOSVersion (uint32_t &major,
uint32_t &minor,
- uint32_t &update)
+ uint32_t &update,
+ Process *process)
{
Mutex::Locker locker (m_mutex);
@@ -566,6 +581,12 @@ Platform::GetOSVersion (uint32_t &major,
minor = m_minor_os_version;
update = m_update_os_version;
}
+ else if (process)
+ {
+ // Check with the process in case it can answer the question if
+ // a process was provided
+ return process->GetHostOSVersion(major, minor, update);
+ }
return success;
}
@@ -947,6 +968,12 @@ Platform::GetHostname ()
return m_name.c_str();
}
+ConstString
+Platform::GetFullNameForDylib (ConstString basename)
+{
+ return basename;
+}
+
bool
Platform::SetRemoteWorkingDirectory(const FileSpec &working_dir)
{
@@ -1811,7 +1838,7 @@ Platform::GetRemoteSharedModule (const ModuleSpec &module_spec,
{
// Try to get module information from the process
if (process->GetModuleSpec (module_spec.GetFileSpec (), module_spec.GetArchitecture (), resolved_module_spec))
- got_module_spec = true;
+ got_module_spec = true;
}
if (!got_module_spec)
@@ -1838,7 +1865,8 @@ Platform::GetCachedSharedModule (const ModuleSpec &module_spec,
bool *did_create_ptr)
{
if (IsHost() ||
- !GetGlobalPlatformProperties ()->GetUseModuleCache ())
+ !GetGlobalPlatformProperties ()->GetUseModuleCache () ||
+ !GetGlobalPlatformProperties ()->GetModuleCacheDirectory ())
return false;
Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM);
@@ -1848,7 +1876,7 @@ Platform::GetCachedSharedModule (const ModuleSpec &module_spec,
GetModuleCacheRoot (),
GetCacheHostname (),
module_spec,
- [=](const ModuleSpec &module_spec, const FileSpec &tmp_download_file_spec)
+ [this](const ModuleSpec &module_spec, const FileSpec &tmp_download_file_spec)
{
return DownloadModuleSlice (module_spec.GetFileSpec (),
module_spec.GetObjectOffset (),
@@ -1856,6 +1884,10 @@ Platform::GetCachedSharedModule (const ModuleSpec &module_spec,
tmp_download_file_spec);
},
+ [this](const ModuleSP& module_sp, const FileSpec& tmp_download_file_spec)
+ {
+ return DownloadSymbolFile (module_sp, tmp_download_file_spec);
+ },
module_sp,
did_create_ptr);
if (error.Success ())
@@ -1918,6 +1950,12 @@ Platform::DownloadModuleSlice (const FileSpec& src_file_spec,
return error;
}
+Error
+Platform::DownloadSymbolFile (const lldb::ModuleSP& module_sp, const FileSpec& dst_file_spec)
+{
+ return Error ("Symbol file downloading not supported by the default platform.");
+}
+
FileSpec
Platform::GetModuleCacheRoot ()
{
@@ -1946,3 +1984,106 @@ Platform::GetUnixSignals()
return Host::GetUnixSignals();
return GetRemoteUnixSignals();
}
+
+uint32_t
+Platform::LoadImage(lldb_private::Process* process,
+ const lldb_private::FileSpec& local_file,
+ const lldb_private::FileSpec& remote_file,
+ lldb_private::Error& error)
+{
+ if (local_file && remote_file)
+ {
+ // Both local and remote file was specified. Install the local file to the given location.
+ if (IsRemote() || local_file != remote_file)
+ {
+ error = Install(local_file, remote_file);
+ if (error.Fail())
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+ return DoLoadImage(process, remote_file, error);
+ }
+
+ if (local_file)
+ {
+ // Only local file was specified. Install it to the current working directory.
+ FileSpec target_file = GetWorkingDirectory();
+ target_file.AppendPathComponent(local_file.GetFilename().AsCString());
+ if (IsRemote() || local_file != target_file)
+ {
+ error = Install(local_file, target_file);
+ if (error.Fail())
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+ return DoLoadImage(process, target_file, error);
+ }
+
+ if (remote_file)
+ {
+ // Only remote file was specified so we don't have to do any copying
+ return DoLoadImage(process, remote_file, error);
+ }
+
+ error.SetErrorString("Neither local nor remote file was specified");
+ return LLDB_INVALID_IMAGE_TOKEN;
+}
+
+uint32_t
+Platform::DoLoadImage (lldb_private::Process* process,
+ const lldb_private::FileSpec& remote_file,
+ lldb_private::Error& error)
+{
+ error.SetErrorString("LoadImage is not supported on the current platform");
+ return LLDB_INVALID_IMAGE_TOKEN;
+}
+
+Error
+Platform::UnloadImage(lldb_private::Process* process, uint32_t image_token)
+{
+ return Error("UnloadImage is not supported on the current platform");
+}
+
+lldb::ProcessSP
+Platform::ConnectProcess(const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error)
+{
+ error.Clear();
+
+ if (!target)
+ {
+ TargetSP new_target_sp;
+ error = debugger.GetTargetList().CreateTarget(debugger,
+ nullptr,
+ nullptr,
+ false,
+ nullptr,
+ new_target_sp);
+ target = new_target_sp.get();
+ }
+
+ if (!target || error.Fail())
+ return nullptr;
+
+ debugger.GetTargetList().SetSelectedTarget(target);
+
+ lldb::ProcessSP process_sp = target->CreateProcess(debugger.GetListener(),
+ plugin_name,
+ nullptr);
+ if (!process_sp)
+ return nullptr;
+
+ error = process_sp->ConnectRemote(debugger.GetOutputFile().get(), connect_url);
+ if (error.Fail())
+ return nullptr;
+
+ return process_sp;
+}
+
+size_t
+Platform::ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& error)
+{
+ error.Clear();
+ return 0;
+}
diff --git a/contrib/llvm/tools/lldb/source/Target/Process.cpp b/contrib/llvm/tools/lldb/source/Target/Process.cpp
index 3abae4f..e4fe419 100644
--- a/contrib/llvm/tools/lldb/source/Target/Process.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Process.cpp
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -18,9 +22,10 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Pipe.h"
@@ -28,6 +33,7 @@
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
@@ -56,7 +62,6 @@
using namespace lldb;
using namespace lldb_private;
-
// Comment out line below to disable memory caching, overriding the process setting
// target.process.disable-memory-cache
#define ENABLE_MEMORY_CACHING
@@ -83,8 +88,8 @@ public:
{
}
- virtual const Property *
- GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
+ const Property *
+ GetPropertyAtIndex(const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const override
{
// When getting the value for a key from the process options, we will always
// try and grab the setting from the current process if there is one. Else we just
@@ -115,6 +120,7 @@ g_properties[] =
{ "stop-on-sharedlibrary-events" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, stop when a shared library is loaded or unloaded." },
{ "detach-keeps-stopped" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, detach will attempt to keep the process stopped." },
{ "memory-cache-line-size" , OptionValue::eTypeUInt64, false, 512, NULL, NULL, "The memory cache line size" },
+ { "optimization-warnings" , OptionValue::eTypeBoolean, false, true, NULL, NULL, "If true, warn when stopped in code that is optimized where stepping and variable availability may not behave as expected." },
{ NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL }
};
@@ -126,7 +132,8 @@ enum {
ePropertyPythonOSPluginPath,
ePropertyStopOnSharedLibraryEvents,
ePropertyDetachKeepsStopped,
- ePropertyMemCacheLineSize
+ ePropertyMemCacheLineSize,
+ ePropertyWarningOptimization
};
ProcessProperties::ProcessProperties (lldb_private::Process *process) :
@@ -150,9 +157,7 @@ ProcessProperties::ProcessProperties (lldb_private::Process *process) :
}
}
-ProcessProperties::~ProcessProperties()
-{
-}
+ProcessProperties::~ProcessProperties() = default;
void
ProcessProperties::OptionValueChangedCallback (void *baton, OptionValue *option_value)
@@ -206,7 +211,6 @@ ProcessProperties::SetPythonOSPluginPath (const FileSpec &file)
m_collection_sp->SetPropertyAtIndexAsFileSpec(NULL, idx, file);
}
-
bool
ProcessProperties::GetIgnoreBreakpointsInExpressions () const
{
@@ -263,6 +267,13 @@ ProcessProperties::SetDetachKeepsStopped (bool stop)
m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, stop);
}
+bool
+ProcessProperties::GetWarningsOptimization () const
+{
+ const uint32_t idx = ePropertyWarningOptimization;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
void
ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const
{
@@ -306,8 +317,12 @@ ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const
}
}
- if (m_arch.IsValid())
- s.Printf (" arch = %s\n", m_arch.GetTriple().str().c_str());
+ if (m_arch.IsValid())
+ {
+ s.Printf (" arch = ");
+ m_arch.DumpTriple(s);
+ s.EOL();
+ }
if (m_uid != UINT32_MAX)
{
@@ -360,7 +375,10 @@ ProcessInstanceInfo::DumpAsTableRow (Stream &s, Platform *platform, bool show_ar
const char *cstr;
s.Printf ("%-6" PRIu64 " %-6" PRIu64 " ", m_pid, m_parent_pid);
-
+ StreamString arch_strm;
+ if (m_arch.IsValid())
+ m_arch.DumpTriple(arch_strm);
+
if (verbose)
{
cstr = platform->GetUserName (m_uid);
@@ -386,13 +404,14 @@ ProcessInstanceInfo::DumpAsTableRow (Stream &s, Platform *platform, bool show_ar
s.Printf ("%-10s ", cstr);
else
s.Printf ("%-10u ", m_egid);
- s.Printf ("%-24s ", m_arch.IsValid() ? m_arch.GetTriple().str().c_str() : "");
+
+ s.Printf ("%-24s ", arch_strm.GetString().c_str());
}
else
{
s.Printf ("%-10s %-24s ",
platform->GetUserName (m_euid),
- m_arch.IsValid() ? m_arch.GetTriple().str().c_str() : "");
+ arch_strm.GetString().c_str());
}
if (verbose || show_args)
@@ -460,7 +479,7 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op
case 'n': // Disable STDIO
{
FileAction action;
- const FileSpec dev_null{"/dev/null", false};
+ const FileSpec dev_null{FileSystem::DEV_NULL, false};
if (action.Open(STDIN_FILENO, dev_null, true, false))
launch_info.AppendFileAction (action);
if (action.Open(STDOUT_FILENO, dev_null, false, true))
@@ -545,8 +564,6 @@ ProcessLaunchCommandOptions::g_option_table[] =
{ 0 , false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
-
-
bool
ProcessInstanceInfoMatch::NameMatches (const char *process_name) const
{
@@ -626,7 +643,6 @@ ProcessInstanceInfoMatch::MatchAllProcesses () const
return false;
return true;
-
}
void
@@ -638,7 +654,7 @@ ProcessInstanceInfoMatch::Clear()
}
ProcessSP
-Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener, const FileSpec *crash_file_path)
+Process::FindPlugin (lldb::TargetSP target_sp, const char *plugin_name, Listener &listener, const FileSpec *crash_file_path)
{
static uint32_t g_process_unique_id = 0;
@@ -650,10 +666,10 @@ Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener
create_callback = PluginManager::GetProcessCreateCallbackForPluginName (const_plugin_name);
if (create_callback)
{
- process_sp = create_callback(target, listener, crash_file_path);
+ process_sp = create_callback(target_sp, listener, crash_file_path);
if (process_sp)
{
- if (process_sp->CanDebug(target, true))
+ if (process_sp->CanDebug(target_sp, true))
{
process_sp->m_process_unique_id = ++g_process_unique_id;
}
@@ -666,10 +682,10 @@ Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener
{
for (uint32_t idx = 0; (create_callback = PluginManager::GetProcessCreateCallbackAtIndex(idx)) != NULL; ++idx)
{
- process_sp = create_callback(target, listener, crash_file_path);
+ process_sp = create_callback(target_sp, listener, crash_file_path);
if (process_sp)
{
- if (process_sp->CanDebug(target, false))
+ if (process_sp->CanDebug(target_sp, false))
{
process_sp->m_process_unique_id = ++g_process_unique_id;
break;
@@ -689,21 +705,18 @@ Process::GetStaticBroadcasterClass ()
return class_name;
}
-//----------------------------------------------------------------------
-// Process constructor
-//----------------------------------------------------------------------
-Process::Process(Target &target, Listener &listener) :
- Process(target, listener, UnixSignals::Create(HostInfo::GetArchitecture()))
+Process::Process(lldb::TargetSP target_sp, Listener &listener) :
+ Process(target_sp, listener, UnixSignals::Create(HostInfo::GetArchitecture()))
{
// This constructor just delegates to the full Process constructor,
// defaulting to using the Host's UnixSignals.
}
-Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_signals_sp) :
+Process::Process(lldb::TargetSP target_sp, Listener &listener, const UnixSignalsSP &unix_signals_sp) :
ProcessProperties (this),
UserID (LLDB_INVALID_PROCESS_ID),
- Broadcaster (&(target.GetDebugger()), Process::GetStaticBroadcasterClass().AsCString()),
- m_target (target),
+ Broadcaster (&(target_sp->GetDebugger()), Process::GetStaticBroadcasterClass().AsCString()),
+ m_target_sp (target_sp),
m_public_state (eStateUnloaded),
m_private_state (eStateUnloaded),
m_private_state_broadcaster (NULL, "lldb.process.internal_state_broadcaster"),
@@ -746,7 +759,6 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s
m_next_event_action_ap(),
m_public_run_lock (),
m_private_run_lock (),
- m_currently_handling_event(false),
m_stop_info_override_callback (NULL),
m_finalizing (false),
m_finalize_called (false),
@@ -755,6 +767,7 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s
m_last_broadcast_state (eStateInvalid),
m_destroy_in_process (false),
m_can_interpret_function_calls(false),
+ m_warnings_issued (),
m_can_jit(eCanJITDontKnow)
{
CheckInWithManager ();
@@ -793,11 +806,15 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s
eBroadcastInternalStateControlResume);
// We need something valid here, even if just the default UnixSignalsSP.
assert (m_unix_signals_sp && "null m_unix_signals_sp after initialization");
+
+ // Allow the platform to override the default cache line size
+ OptionValueSP value_sp =
+ m_collection_sp->GetPropertyAtIndex(nullptr, true, ePropertyMemCacheLineSize)->GetValue();
+ uint32_t platform_cache_line_size = target_sp->GetPlatform()->GetDefaultMemoryCacheLineSize();
+ if (! value_sp->OptionWasSet() && platform_cache_line_size != 0)
+ value_sp->SetUInt64Value(platform_cache_line_size);
}
-//----------------------------------------------------------------------
-// Destructor
-//----------------------------------------------------------------------
Process::~Process()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
@@ -974,7 +991,8 @@ Process::WaitForProcessToStop (const TimeValue *timeout,
EventSP *event_sp_ptr,
bool wait_always,
Listener *hijack_listener,
- Stream *stream)
+ Stream *stream,
+ bool use_run_lock)
{
// We can't just wait for a "stopped" event, because the stopped event may have restarted the target.
// We have to actually check each event, and in the case of a stopped event check the restarted flag
@@ -1001,7 +1019,7 @@ Process::WaitForProcessToStop (const TimeValue *timeout,
__FUNCTION__);
// We need to toggle the run lock as this won't get done in
// SetPublicState() if the process is hijacked.
- if (hijack_listener)
+ if (hijack_listener && use_run_lock)
m_public_run_lock.SetStopped();
return state;
}
@@ -1024,7 +1042,7 @@ Process::WaitForProcessToStop (const TimeValue *timeout,
case eStateUnloaded:
// We need to toggle the run lock as this won't get done in
// SetPublicState() if the process is hijacked.
- if (hijack_listener)
+ if (hijack_listener && use_run_lock)
m_public_run_lock.SetStopped();
return state;
case eStateStopped:
@@ -1034,7 +1052,7 @@ Process::WaitForProcessToStop (const TimeValue *timeout,
{
// We need to toggle the run lock as this won't get done in
// SetPublicState() if the process is hijacked.
- if (hijack_listener)
+ if (hijack_listener && use_run_lock)
m_public_run_lock.SetStopped();
return state;
}
@@ -1247,14 +1265,10 @@ Process::HandleProcessStateChangedEvent (const EventSP &event_sp,
return true;
}
-
StateType
-Process::WaitForState
-(
- const TimeValue *timeout,
- const StateType *match_states,
- const uint32_t num_match_states
-)
+Process::WaitForState(const TimeValue *timeout,
+ const StateType *match_states,
+ const uint32_t num_match_states)
{
EventSP event_sp;
uint32_t i;
@@ -1294,23 +1308,6 @@ Process::RestoreProcessEvents ()
RestoreBroadcaster();
}
-bool
-Process::HijackPrivateProcessEvents (Listener *listener)
-{
- if (listener != NULL)
- {
- return m_private_state_broadcaster.HijackBroadcaster(listener, eBroadcastBitStateChanged | eBroadcastBitInterrupt);
- }
- else
- return false;
-}
-
-void
-Process::RestorePrivateProcessEvents ()
-{
- m_private_state_broadcaster.RestoreBroadcaster();
-}
-
StateType
Process::WaitForStateChangedEvents (const TimeValue *timeout, EventSP &event_sp, Listener *hijack_listener)
{
@@ -1429,7 +1426,6 @@ Process::GetExitStatus ()
return -1;
}
-
const char *
Process::GetExitDescription ()
{
@@ -1468,12 +1464,7 @@ Process::SetExitStatus (int status, const char *cstr)
else
m_exit_string.clear();
- // When we exit, we no longer need to the communication channel
- m_stdio_communication.Disconnect();
- m_stdio_communication.StopReadThread();
- m_stdin_forward = false;
-
- // And we don't need the input reader anymore as well
+ // When we exit, we don't need the input reader anymore
if (m_process_input_reader)
{
m_process_input_reader->SetIsDone(true);
@@ -1493,6 +1484,29 @@ Process::SetExitStatus (int status, const char *cstr)
return true;
}
+bool
+Process::IsAlive ()
+{
+ switch (m_private_state.GetValue())
+ {
+ case eStateInvalid:
+ case eStateUnloaded:
+ case eStateDetached:
+ case eStateExited:
+ return false;
+
+ case eStateConnected:
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateStopped:
+ case eStateRunning:
+ case eStateStepping:
+ case eStateCrashed:
+ case eStateSuspended:
+ return true;
+ }
+}
+
// This static callback can be used to watch for local child processes on
// the current host. The child process exits, the process will be
// found in the global target list (we want to be completely sure that the
@@ -1534,7 +1548,6 @@ Process::SetProcessExitStatus (void *callback_baton,
return false;
}
-
void
Process::UpdateThreadListIfNeeded ()
{
@@ -1558,41 +1571,38 @@ Process::UpdateThreadListIfNeeded ()
// Don't call into the OperatingSystem to update the thread list if we are shutting down, since
// that may call back into the SBAPI's, requiring the API lock which is already held by whoever is
// shutting us down, causing a deadlock.
- if (!m_destroy_in_process)
+ OperatingSystem *os = GetOperatingSystem ();
+ if (os && !m_destroy_in_process)
{
- OperatingSystem *os = GetOperatingSystem ();
- if (os)
- {
- // Clear any old backing threads where memory threads might have been
- // backed by actual threads from the lldb_private::Process subclass
- size_t num_old_threads = old_thread_list.GetSize(false);
- for (size_t i=0; i<num_old_threads; ++i)
- old_thread_list.GetThreadAtIndex(i, false)->ClearBackingThread();
-
- // Turn off dynamic types to ensure we don't run any expressions. Objective C
- // can run an expression to determine if a SBValue is a dynamic type or not
- // and we need to avoid this. OperatingSystem plug-ins can't run expressions
- // that require running code...
-
- Target &target = GetTarget();
- const lldb::DynamicValueType saved_prefer_dynamic = target.GetPreferDynamicValue ();
- if (saved_prefer_dynamic != lldb::eNoDynamicValues)
- target.SetPreferDynamicValue(lldb::eNoDynamicValues);
-
- // Now let the OperatingSystem plug-in update the thread list
-
- os->UpdateThreadList (old_thread_list, // Old list full of threads created by OS plug-in
- real_thread_list, // The actual thread list full of threads created by each lldb_private::Process subclass
- new_thread_list); // The new thread list that we will show to the user that gets filled in
-
- if (saved_prefer_dynamic != lldb::eNoDynamicValues)
- target.SetPreferDynamicValue(saved_prefer_dynamic);
- }
- else
- {
- // No OS plug-in, the new thread list is the same as the real thread list
- new_thread_list = real_thread_list;
- }
+ // Clear any old backing threads where memory threads might have been
+ // backed by actual threads from the lldb_private::Process subclass
+ size_t num_old_threads = old_thread_list.GetSize(false);
+ for (size_t i=0; i<num_old_threads; ++i)
+ old_thread_list.GetThreadAtIndex(i, false)->ClearBackingThread();
+
+ // Turn off dynamic types to ensure we don't run any expressions. Objective C
+ // can run an expression to determine if a SBValue is a dynamic type or not
+ // and we need to avoid this. OperatingSystem plug-ins can't run expressions
+ // that require running code...
+
+ Target &target = GetTarget();
+ const lldb::DynamicValueType saved_prefer_dynamic = target.GetPreferDynamicValue ();
+ if (saved_prefer_dynamic != lldb::eNoDynamicValues)
+ target.SetPreferDynamicValue(lldb::eNoDynamicValues);
+
+ // Now let the OperatingSystem plug-in update the thread list
+
+ os->UpdateThreadList (old_thread_list, // Old list full of threads created by OS plug-in
+ real_thread_list, // The actual thread list full of threads created by each lldb_private::Process subclass
+ new_thread_list); // The new thread list that we will show to the user that gets filled in
+
+ if (saved_prefer_dynamic != lldb::eNoDynamicValues)
+ target.SetPreferDynamicValue(saved_prefer_dynamic);
+ }
+ else
+ {
+ // No OS plug-in, the new thread list is the same as the real thread list
+ new_thread_list = real_thread_list;
}
m_thread_list_real.Update(real_thread_list);
@@ -1648,15 +1658,7 @@ Process::GetNextThreadIndexID (uint64_t thread_id)
bool
Process::HasAssignedIndexIDToThread(uint64_t thread_id)
{
- std::map<uint64_t, uint32_t>::iterator iterator = m_thread_id_to_index_id_map.find(thread_id);
- if (iterator == m_thread_id_to_index_id_map.end())
- {
- return false;
- }
- else
- {
- return true;
- }
+ return (m_thread_id_to_index_id_map.find(thread_id) != m_thread_id_to_index_id_map.end());
}
uint32_t
@@ -1866,225 +1868,11 @@ Process::GetImageInfoAddress()
return LLDB_INVALID_ADDRESS;
}
-//----------------------------------------------------------------------
-// LoadImage
-//
-// This function provides a default implementation that works for most
-// unix variants. Any Process subclasses that need to do shared library
-// loading differently should override LoadImage and UnloadImage and
-// do what is needed.
-//----------------------------------------------------------------------
-uint32_t
-Process::LoadImage (const FileSpec &image_spec, Error &error)
-{
- if (m_finalizing)
- {
- error.SetErrorString("process is tearing itself down");
- return LLDB_INVALID_IMAGE_TOKEN;
- }
-
- char path[PATH_MAX];
- image_spec.GetPath(path, sizeof(path));
-
- DynamicLoader *loader = GetDynamicLoader();
- if (loader)
- {
- error = loader->CanLoadImage();
- if (error.Fail())
- return LLDB_INVALID_IMAGE_TOKEN;
- }
-
- if (error.Success())
- {
- ThreadSP thread_sp(GetThreadList ().GetSelectedThread());
-
- if (thread_sp)
- {
- StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex (0));
-
- if (frame_sp)
- {
- ExecutionContext exe_ctx;
- frame_sp->CalculateExecutionContext (exe_ctx);
- EvaluateExpressionOptions expr_options;
- expr_options.SetUnwindOnError(true);
- expr_options.SetIgnoreBreakpoints(true);
- expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
- expr_options.SetResultIsInternal(true);
-
- StreamString expr;
- expr.Printf(R"(
- struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result;
- the_result.image_ptr = dlopen ("%s", 2);
- if (the_result.image_ptr == (void *) 0x0)
- {
- the_result.error_str = dlerror();
- }
- else
- {
- the_result.error_str = (const char *) 0x0;
- }
- the_result;
- )",
- path);
- const char *prefix = R"(
- extern "C" void* dlopen (const char *path, int mode);
- extern "C" const char *dlerror (void);
- )";
- lldb::ValueObjectSP result_valobj_sp;
- Error expr_error;
- ClangUserExpression::Evaluate (exe_ctx,
- expr_options,
- expr.GetData(),
- prefix,
- result_valobj_sp,
- expr_error);
- if (expr_error.Success())
- {
- error = result_valobj_sp->GetError();
- if (error.Success())
- {
- Scalar scalar;
- ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true);
- if (image_ptr_sp && image_ptr_sp->ResolveValue (scalar))
- {
- addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
- if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS)
- {
- uint32_t image_token = m_image_tokens.size();
- m_image_tokens.push_back (image_ptr);
- return image_token;
- }
- else if (image_ptr == 0)
- {
- ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true);
- if (error_str_sp)
- {
- if (error_str_sp->IsCStringContainer(true))
- {
- DataBufferSP buffer_sp(new DataBufferHeap(10240,0));
- size_t num_chars = error_str_sp->ReadPointedString (buffer_sp, error, 10240);
- if (error.Success() && num_chars > 0)
- {
- error.Clear();
- error.SetErrorStringWithFormat("dlopen error: %s", buffer_sp->GetBytes());
- }
- else
- {
- error.Clear();
- error.SetErrorStringWithFormat("dlopen failed for unknown reasons.");
- }
- }
- }
- }
- }
- }
- }
- else
- error = expr_error;
- }
- }
- }
- if (!error.AsCString())
- error.SetErrorStringWithFormat("unable to load '%s'", path);
- return LLDB_INVALID_IMAGE_TOKEN;
-}
-
-//----------------------------------------------------------------------
-// UnloadImage
-//
-// This function provides a default implementation that works for most
-// unix variants. Any Process subclasses that need to do shared library
-// loading differently should override LoadImage and UnloadImage and
-// do what is needed.
-//----------------------------------------------------------------------
-Error
-Process::UnloadImage (uint32_t image_token)
-{
- Error error;
-
- if (m_finalizing)
- {
- error.SetErrorString("process is tearing itself down");
- return error;
- }
-
- if (image_token < m_image_tokens.size())
- {
- const addr_t image_addr = m_image_tokens[image_token];
- if (image_addr == LLDB_INVALID_ADDRESS)
- {
- error.SetErrorString("image already unloaded");
- }
- else
- {
- DynamicLoader *loader = GetDynamicLoader();
- if (loader)
- error = loader->CanLoadImage();
-
- if (error.Success())
- {
- ThreadSP thread_sp(GetThreadList ().GetSelectedThread());
-
- if (thread_sp)
- {
- StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex (0));
-
- if (frame_sp)
- {
- ExecutionContext exe_ctx;
- frame_sp->CalculateExecutionContext (exe_ctx);
- EvaluateExpressionOptions expr_options;
- expr_options.SetUnwindOnError(true);
- expr_options.SetIgnoreBreakpoints(true);
- expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
- StreamString expr;
- expr.Printf("dlclose ((void *)0x%" PRIx64 ")", image_addr);
- const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
- lldb::ValueObjectSP result_valobj_sp;
- Error expr_error;
- ClangUserExpression::Evaluate (exe_ctx,
- expr_options,
- expr.GetData(),
- prefix,
- result_valobj_sp,
- expr_error);
- if (result_valobj_sp->GetError().Success())
- {
- Scalar scalar;
- if (result_valobj_sp->ResolveValue (scalar))
- {
- if (scalar.UInt(1))
- {
- error.SetErrorStringWithFormat("expression failed: \"%s\"", expr.GetData());
- }
- else
- {
- m_image_tokens[image_token] = LLDB_INVALID_ADDRESS;
- }
- }
- }
- else
- {
- error = result_valobj_sp->GetError();
- }
- }
- }
- }
- }
- }
- else
- {
- error.SetErrorString("invalid image token");
- }
- return error;
-}
-
const lldb::ABISP &
Process::GetABI()
{
if (!m_abi_sp)
- m_abi_sp = ABI::FindPlugin(m_target.GetArchitecture());
+ m_abi_sp = ABI::FindPlugin(GetTarget().GetArchitecture());
return m_abi_sp;
}
@@ -2167,7 +1955,6 @@ Process::GetBreakpointSiteList() const
return m_breakpoint_site_list;
}
-
void
Process::DisableAllBreakpointSites ()
{
@@ -2264,22 +2051,22 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw
load_addr = ResolveIndirectFunction (&symbol_address, error);
if (!error.Success() && show_error)
{
- m_target.GetDebugger().GetErrorFile()->Printf ("warning: failed to resolve indirect function at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
- symbol->GetLoadAddress(&m_target),
- owner->GetBreakpoint().GetID(),
- owner->GetID(),
- error.AsCString() ? error.AsCString() : "unknown error");
+ GetTarget().GetDebugger().GetErrorFile()->Printf ("warning: failed to resolve indirect function at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
+ symbol->GetLoadAddress(&GetTarget()),
+ owner->GetBreakpoint().GetID(),
+ owner->GetID(),
+ error.AsCString() ? error.AsCString() : "unknown error");
return LLDB_INVALID_BREAK_ID;
}
Address resolved_address(load_addr);
- load_addr = resolved_address.GetOpcodeLoadAddress (&m_target);
+ load_addr = resolved_address.GetOpcodeLoadAddress (&GetTarget());
owner->SetIsIndirect(true);
}
else
- load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target);
+ load_addr = owner->GetAddress().GetOpcodeLoadAddress (&GetTarget());
}
else
- load_addr = owner->GetAddress().GetOpcodeLoadAddress (&m_target);
+ load_addr = owner->GetAddress().GetOpcodeLoadAddress (&GetTarget());
if (load_addr != LLDB_INVALID_ADDRESS)
{
@@ -2312,11 +2099,11 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw
if (show_error)
{
// Report error for setting breakpoint...
- m_target.GetDebugger().GetErrorFile()->Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
- load_addr,
- owner->GetBreakpoint().GetID(),
- owner->GetID(),
- error.AsCString() ? error.AsCString() : "unknown error");
+ GetTarget().GetDebugger().GetErrorFile()->Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
+ load_addr,
+ owner->GetBreakpoint().GetID(),
+ owner->GetID(),
+ error.AsCString() ? error.AsCString() : "unknown error");
}
}
}
@@ -2324,7 +2111,6 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw
}
// We failed to enable the breakpoint
return LLDB_INVALID_BREAK_ID;
-
}
void
@@ -2340,7 +2126,6 @@ Process::RemoveOwnerFromBreakpointSite (lldb::user_id_t owner_id, lldb::user_id_
}
}
-
size_t
Process::RemoveBreakpointOpcodesFromBuffer (addr_t bp_addr, size_t size, uint8_t *buf) const
{
@@ -2369,14 +2154,12 @@ Process::RemoveBreakpointOpcodesFromBuffer (addr_t bp_addr, size_t size, uint8_t
return bytes_removed;
}
-
-
size_t
Process::GetSoftwareBreakpointTrapOpcode (BreakpointSite* bp_site)
{
- PlatformSP platform_sp (m_target.GetPlatform());
+ PlatformSP platform_sp (GetTarget().GetPlatform());
if (platform_sp)
- return platform_sp->GetSoftwareBreakpointTrapOpcode (m_target, bp_site);
+ return platform_sp->GetSoftwareBreakpointTrapOpcode (GetTarget(), bp_site);
return 0;
}
@@ -2550,7 +2333,6 @@ Process::DisableSoftwareBreakpoint (BreakpointSite *bp_site)
(uint64_t)bp_addr,
error.AsCString());
return error;
-
}
// Uncomment to verify memory caching works after making changes to caching code
@@ -2622,7 +2404,6 @@ Process::ReadCStringFromMemory (addr_t addr, std::string &out_str, Error &error)
return out_str.size();
}
-
size_t
Process::ReadStringFromMemory (addr_t addr, char *dst, size_t max_bytes, Error &error,
size_t type_width)
@@ -2772,7 +2553,6 @@ Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error)
return LLDB_INVALID_ADDRESS;
}
-
bool
Process::WritePointerToMemory (lldb::addr_t vm_addr,
lldb::addr_t ptr_value,
@@ -2843,6 +2623,7 @@ Process::WriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
size_t intersect_size;
size_t opcode_offset;
const bool intersects = bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset);
+ UNUSED_IF_ASSERT_DISABLED(intersects);
assert(intersects);
assert(addr <= intersect_addr && intersect_addr < addr + size);
assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size);
@@ -2975,6 +2756,18 @@ Process::AllocateMemory(size_t size, uint32_t permissions, Error &error)
#endif
}
+addr_t
+Process::CallocateMemory(size_t size, uint32_t permissions, Error &error)
+{
+ addr_t return_addr = AllocateMemory(size, permissions, error);
+ if (error.Success())
+ {
+ std::string buffer(size, 0);
+ WriteMemory(return_addr, buffer.c_str(), size, error);
+ }
+ return return_addr;
+}
+
bool
Process::CanJIT ()
{
@@ -3042,12 +2835,16 @@ Process::DeallocateMemory (addr_t ptr)
return error;
}
-
ModuleSP
Process::ReadModuleFromMemory (const FileSpec& file_spec,
lldb::addr_t header_addr,
size_t size_to_read)
{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ if (log)
+ {
+ log->Printf ("Process::ReadModuleFromMemory reading %s binary from memory", file_spec.GetPath().c_str());
+ }
ModuleSP module_sp (new Module (file_spec, ArchSpec()));
if (module_sp)
{
@@ -3148,7 +2945,7 @@ Process::Launch (ProcessLaunchInfo &launch_info)
m_process_input_reader.reset();
m_stop_info_override_callback = NULL;
- Module *exe_module = m_target.GetExecutableModulePointer();
+ Module *exe_module = GetTarget().GetExecutableModulePointer();
if (exe_module)
{
char local_exec_file_path[PATH_MAX];
@@ -3214,7 +3011,6 @@ Process::Launch (ProcessLaunchInfo &launch_info)
}
else if (state == eStateStopped || state == eStateCrashed)
{
-
DidLaunch ();
DynamicLoader *dyld = GetDynamicLoader ();
@@ -3264,7 +3060,6 @@ Process::Launch (ProcessLaunchInfo &launch_info)
return error;
}
-
Error
Process::LoadCore ()
{
@@ -3495,7 +3290,7 @@ Process::Attach (ProcessAttachInfo &attach_info)
else
{
ProcessInstanceInfoList process_infos;
- PlatformSP platform_sp (m_target.GetPlatform ());
+ PlatformSP platform_sp (GetTarget().GetPlatform ());
if (platform_sp)
{
@@ -3597,7 +3392,7 @@ Process::CompleteAttach ()
if (process_arch.IsValid())
{
- m_target.SetArchitecture(process_arch);
+ GetTarget().SetArchitecture(process_arch);
if (log)
{
const char *triple_str = process_arch.GetTriple().getTriple().c_str ();
@@ -3609,19 +3404,19 @@ Process::CompleteAttach ()
// We just attached. If we have a platform, ask it for the process architecture, and if it isn't
// the same as the one we've already set, switch architectures.
- PlatformSP platform_sp (m_target.GetPlatform ());
+ PlatformSP platform_sp (GetTarget().GetPlatform ());
assert (platform_sp.get());
if (platform_sp)
{
- const ArchSpec &target_arch = m_target.GetArchitecture();
+ const ArchSpec &target_arch = GetTarget().GetArchitecture();
if (target_arch.IsValid() && !platform_sp->IsCompatibleArchitecture (target_arch, false, NULL))
{
ArchSpec platform_arch;
platform_sp = platform_sp->GetPlatformForArchitecture (target_arch, &platform_arch);
if (platform_sp)
{
- m_target.SetPlatform (platform_sp);
- m_target.SetArchitecture(platform_arch);
+ GetTarget().SetPlatform (platform_sp);
+ GetTarget().SetArchitecture(platform_arch);
if (log)
log->Printf ("Process::%s switching platform to %s and architecture to %s based on info from attach", __FUNCTION__, platform_sp->GetName().AsCString (""), platform_arch.GetTriple().getTriple().c_str ());
}
@@ -3631,9 +3426,9 @@ Process::CompleteAttach ()
ProcessInstanceInfo process_info;
platform_sp->GetProcessInfo (GetID(), process_info);
const ArchSpec &process_arch = process_info.GetArchitecture();
- if (process_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(process_arch))
+ if (process_arch.IsValid() && !GetTarget().GetArchitecture().IsExactMatch(process_arch))
{
- m_target.SetArchitecture (process_arch);
+ GetTarget().SetArchitecture (process_arch);
if (log)
log->Printf ("Process::%s switching architecture to %s based on info the platform retrieved for pid %" PRIu64, __FUNCTION__, process_arch.GetTriple().getTriple().c_str (), GetID ());
}
@@ -3648,7 +3443,7 @@ Process::CompleteAttach ()
dyld->DidAttach();
if (log)
{
- ModuleSP exe_module_sp = m_target.GetExecutableModule ();
+ ModuleSP exe_module_sp = GetTarget().GetExecutableModule ();
log->Printf ("Process::%s after DynamicLoader::DidAttach(), target executable is %s (using %s plugin)",
__FUNCTION__,
exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>",
@@ -3664,7 +3459,7 @@ Process::CompleteAttach ()
system_runtime->DidAttach();
if (log)
{
- ModuleSP exe_module_sp = m_target.GetExecutableModule ();
+ ModuleSP exe_module_sp = GetTarget().GetExecutableModule ();
log->Printf ("Process::%s after SystemRuntime::DidAttach(), target executable is %s (using %s plugin)",
__FUNCTION__,
exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>",
@@ -3674,7 +3469,7 @@ Process::CompleteAttach ()
m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
// Figure out which one is the executable, and set that in our target:
- const ModuleList &target_modules = m_target.GetImages();
+ const ModuleList &target_modules = GetTarget().GetImages();
Mutex::Locker modules_locker(target_modules.GetMutex());
size_t num_modules = target_modules.GetSize();
ModuleSP new_executable_module_sp;
@@ -3684,17 +3479,17 @@ Process::CompleteAttach ()
ModuleSP module_sp (target_modules.GetModuleAtIndexUnlocked (i));
if (module_sp && module_sp->IsExecutable())
{
- if (m_target.GetExecutableModulePointer() != module_sp.get())
+ if (GetTarget().GetExecutableModulePointer() != module_sp.get())
new_executable_module_sp = module_sp;
break;
}
}
if (new_executable_module_sp)
{
- m_target.SetExecutableModule (new_executable_module_sp, false);
+ GetTarget().SetExecutableModule (new_executable_module_sp, false);
if (log)
{
- ModuleSP exe_module_sp = m_target.GetExecutableModule ();
+ ModuleSP exe_module_sp = GetTarget().GetExecutableModule ();
log->Printf ("Process::%s after looping through modules, target executable is %s",
__FUNCTION__,
exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<none>");
@@ -3742,7 +3537,6 @@ Process::ConnectRemote (Stream *strm, const char *remote_url)
return error;
}
-
Error
Process::PrivateResume ()
{
@@ -3803,150 +3597,99 @@ Process::PrivateResume ()
}
Error
-Process::Halt (bool clear_thread_plans)
+Process::Halt (bool clear_thread_plans, bool use_run_lock)
{
+ if (! StateIsRunningState(m_public_state.GetValue()))
+ return Error("Process is not running.");
+
// Don't clear the m_clear_thread_plans_on_stop, only set it to true if
// in case it was already set and some thread plan logic calls halt on its
// own.
m_clear_thread_plans_on_stop |= clear_thread_plans;
- // First make sure we aren't in the middle of handling an event, or we might restart. This is pretty weak, since
- // we could just straightaway get another event. It just narrows the window...
- m_currently_handling_event.WaitForValueEqualTo(false);
-
-
- // Pause our private state thread so we can ensure no one else eats
- // the stop event out from under us.
Listener halt_listener ("lldb.process.halt_listener");
- HijackPrivateProcessEvents(&halt_listener);
+ HijackProcessEvents(&halt_listener);
EventSP event_sp;
- Error error (WillHalt());
- bool restored_process_events = false;
- if (error.Success())
+ SendAsyncInterrupt();
+
+ if (m_public_state.GetValue() == eStateAttaching)
{
-
- bool caused_stop = false;
-
- // Ask the process subclass to actually halt our process
- error = DoHalt(caused_stop);
- if (error.Success())
- {
- if (m_public_state.GetValue() == eStateAttaching)
- {
- // Don't hijack and eat the eStateExited as the code that was doing
- // the attach will be waiting for this event...
- RestorePrivateProcessEvents();
- restored_process_events = true;
- SetExitStatus(SIGKILL, "Cancelled async attach.");
- Destroy (false);
- }
- else
- {
- // If "caused_stop" is true, then DoHalt stopped the process. If
- // "caused_stop" is false, the process was already stopped.
- // If the DoHalt caused the process to stop, then we want to catch
- // this event and set the interrupted bool to true before we pass
- // this along so clients know that the process was interrupted by
- // a halt command.
- if (caused_stop)
- {
- // Wait for 1 second for the process to stop.
- TimeValue timeout_time;
- timeout_time = TimeValue::Now();
- timeout_time.OffsetWithSeconds(10);
- bool got_event = halt_listener.WaitForEvent (&timeout_time, event_sp);
- StateType state = ProcessEventData::GetStateFromEvent(event_sp.get());
-
- if (!got_event || state == eStateInvalid)
- {
- // We timeout out and didn't get a stop event...
- error.SetErrorStringWithFormat ("Halt timed out. State = %s", StateAsCString(GetState()));
- }
- else
- {
- if (StateIsStoppedState (state, false))
- {
- // We caused the process to interrupt itself, so mark this
- // as such in the stop event so clients can tell an interrupted
- // process from a natural stop
- ProcessEventData::SetInterruptedInEvent (event_sp.get(), true);
- }
- else
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("Process::Halt() failed to stop, state is: %s", StateAsCString(state));
- error.SetErrorString ("Did not get stopped event after halt.");
- }
- }
- }
- DidHalt();
- }
- }
+ // Don't hijack and eat the eStateExited as the code that was doing
+ // the attach will be waiting for this event...
+ RestoreProcessEvents();
+ SetExitStatus(SIGKILL, "Cancelled async attach.");
+ Destroy (false);
+ return Error();
}
- // Resume our private state thread before we post the event (if any)
- if (!restored_process_events)
- RestorePrivateProcessEvents();
- // Post any event we might have consumed. If all goes well, we will have
- // stopped the process, intercepted the event and set the interrupted
- // bool in the event. Post it to the private event queue and that will end up
- // correctly setting the state.
- if (event_sp)
- m_private_state_broadcaster.BroadcastEvent(event_sp);
+ // Wait for 10 second for the process to stop.
+ TimeValue timeout_time;
+ timeout_time = TimeValue::Now();
+ timeout_time.OffsetWithSeconds(10);
+ StateType state = WaitForProcessToStop(&timeout_time, &event_sp, true, &halt_listener,
+ nullptr, use_run_lock);
+ RestoreProcessEvents();
- return error;
+ if (state == eStateInvalid || ! event_sp)
+ {
+ // We timed out and didn't get a stop event...
+ return Error("Halt timed out. State = %s", StateAsCString(GetState()));
+ }
+
+ BroadcastEvent(event_sp);
+
+ return Error();
}
Error
-Process::HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp)
+Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp)
{
Error error;
if (m_public_state.GetValue() == eStateRunning)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
- log->Printf("Process::Destroy() About to halt.");
- error = Halt();
- if (error.Success())
+ log->Printf("Process::%s() About to stop.", __FUNCTION__);
+
+ ListenerSP listener_sp (new Listener("lldb.Process.StopForDestroyOrDetach.hijack"));
+ HijackProcessEvents(listener_sp.get());
+
+ SendAsyncInterrupt();
+
+ // Consume the interrupt event.
+ TimeValue timeout (TimeValue::Now());
+ timeout.OffsetWithSeconds(10);
+
+ StateType state = WaitForProcessToStop (&timeout, &exit_event_sp, true, listener_sp.get());
+
+ RestoreProcessEvents();
+
+ // If the process exited while we were waiting for it to stop, put the exited event into
+ // the shared pointer passed in and return. Our caller doesn't need to do anything else, since
+ // they don't have a process anymore...
+
+ if (state == eStateExited || m_private_state.GetValue() == eStateExited)
{
- // Consume the halt event.
- TimeValue timeout (TimeValue::Now());
- timeout.OffsetWithSeconds(1);
- StateType state = WaitForProcessToStop (&timeout, &exit_event_sp);
-
- // If the process exited while we were waiting for it to stop, put the exited event into
- // the shared pointer passed in and return. Our caller doesn't need to do anything else, since
- // they don't have a process anymore...
-
- if (state == eStateExited || m_private_state.GetValue() == eStateExited)
- {
- if (log)
- log->Printf("Process::HaltForDestroyOrDetach() Process exited while waiting to Halt.");
- return error;
- }
- else
- exit_event_sp.reset(); // It is ok to consume any non-exit stop events
-
- if (state != eStateStopped)
- {
- if (log)
- log->Printf("Process::HaltForDestroyOrDetach() Halt failed to stop, state is: %s", StateAsCString(state));
- // If we really couldn't stop the process then we should just error out here, but if the
- // lower levels just bobbled sending the event and we really are stopped, then continue on.
- StateType private_state = m_private_state.GetValue();
- if (private_state != eStateStopped)
- {
- return error;
- }
- }
+ if (log)
+ log->Printf("Process::%s() Process exited while waiting to stop.", __FUNCTION__);
+ return error;
}
else
+ exit_event_sp.reset(); // It is ok to consume any non-exit stop events
+
+ if (state != eStateStopped)
{
if (log)
- log->Printf("Process::HaltForDestroyOrDetach() Halt got error: %s", error.AsCString());
+ log->Printf("Process::%s() failed to stop, state is: %s", __FUNCTION__, StateAsCString(state));
+ // If we really couldn't stop the process then we should just error out here, but if the
+ // lower levels just bobbled sending the event and we really are stopped, then continue on.
+ StateType private_state = m_private_state.GetValue();
+ if (private_state != eStateStopped)
+ {
+ return error;
+ }
}
}
return error;
@@ -3965,7 +3708,7 @@ Process::Detach (bool keep_stopped)
{
if (DetachRequiresHalt())
{
- error = HaltForDestroyOrDetach (exit_event_sp);
+ error = StopForDestroyOrDetach (exit_event_sp);
if (!error.Success())
{
m_destroy_in_process = false;
@@ -4016,7 +3759,7 @@ Process::Detach (bool keep_stopped)
Error
Process::Destroy (bool force_kill)
{
-
+
// Tell ourselves we are in the process of destroying the process, so that we don't do any unnecessary work
// that might hinder the destruction. Remember to set this back to false when we are done. That way if the attempt
// failed and the process stays around for some reason it won't be in a confused state.
@@ -4039,7 +3782,7 @@ Process::Destroy (bool force_kill)
EventSP exit_event_sp;
if (DestroyRequiresHalt())
{
- error = HaltForDestroyOrDetach(exit_event_sp);
+ error = StopForDestroyOrDetach(exit_event_sp);
}
if (m_public_state.GetValue() != eStateRunning)
@@ -4103,7 +3846,7 @@ Process::Signal (int signal)
}
void
-Process::SetUnixSignals (const UnixSignalsSP &signals_sp)
+Process::SetUnixSignals(UnixSignalsSP &&signals_sp)
{
assert (signals_sp && "null signals_sp");
m_unix_signals_sp = signals_sp;
@@ -4119,16 +3862,15 @@ Process::GetUnixSignals ()
lldb::ByteOrder
Process::GetByteOrder () const
{
- return m_target.GetArchitecture().GetByteOrder();
+ return GetTarget().GetArchitecture().GetByteOrder();
}
uint32_t
Process::GetAddressByteSize () const
{
- return m_target.GetArchitecture().GetAddressByteSize();
+ return GetTarget().GetArchitecture().GetAddressByteSize();
}
-
bool
Process::ShouldBroadcastEvent (Event *event_ptr)
{
@@ -4142,6 +3884,10 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
case eStateExited:
case eStateUnloaded:
m_stdio_communication.SynchronizeWithReadThread();
+ m_stdio_communication.Disconnect();
+ m_stdio_communication.StopReadThread();
+ m_stdin_forward = false;
+
// fall-through
case eStateConnected:
case eStateAttaching:
@@ -4234,7 +3980,7 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
{
Vote stop_vote = m_thread_list.ShouldReportStop (event_ptr);
if (log)
- log->Printf ("Process::ShouldBroadcastEvent: should_stop: %i state: %s was_restarted: %i stop_vote: %d.",
+ log->Printf ("Process::ShouldBroadcastEvent: should_resume: %i state: %s was_restarted: %i stop_vote: %d.",
should_resume, StateAsCString(state),
was_restarted, stop_vote);
@@ -4258,7 +4004,6 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
ProcessEventData::SetRestartedInEvent(event_ptr, true);
PrivateResume ();
}
-
}
else
{
@@ -4291,7 +4036,6 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
return return_value;
}
-
bool
Process::StartPrivateStateThread (bool is_secondary_thread)
{
@@ -4326,7 +4070,7 @@ Process::StartPrivateStateThread (bool is_secondary_thread)
// Create the private state thread, and start it running.
PrivateStateThreadArgs args = {this, is_secondary_thread};
- m_private_state_thread = ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread, (void *) &args, NULL);
+ m_private_state_thread = ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread, (void *) &args, NULL, 8 * 1024 * 1024);
if (m_private_state_thread.IsJoinable())
{
ResumePrivateStateThread();
@@ -4432,8 +4176,6 @@ Process::HandlePrivateEvent (EventSP &event_sp)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
m_resume_requested = false;
- m_currently_handling_event.SetValue(true, eBroadcastNever);
-
const StateType new_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
// First check to see if anybody wants a shot at this event:
@@ -4460,7 +4202,6 @@ Process::HandlePrivateEvent (EventSP &event_sp)
{
// FIXME: should cons up an exited event, and discard this one.
SetExitStatus(0, m_next_event_action_ap->GetExitString());
- m_currently_handling_event.SetValue(false, eBroadcastAlways);
SetNextEventAction(NULL);
return;
}
@@ -4532,7 +4273,7 @@ Process::HandlePrivateEvent (EventSP &event_sp)
// events) and we do need the IO handler to be pushed and popped
// correctly.
- if (is_hijacked || m_target.GetDebugger().IsHandlingEvents() == false)
+ if (is_hijacked || GetTarget().GetDebugger().IsHandlingEvents() == false)
PopProcessIOHandler ();
}
}
@@ -4550,7 +4291,22 @@ Process::HandlePrivateEvent (EventSP &event_sp)
StateAsCString (GetState ()));
}
}
- m_currently_handling_event.SetValue(false, eBroadcastAlways);
+}
+
+Error
+Process::HaltPrivate()
+{
+ EventSP event_sp;
+ Error error (WillHalt());
+ if (error.Fail())
+ return error;
+
+ // Ask the process subclass to actually halt our process
+ bool caused_stop;
+ error = DoHalt(caused_stop);
+
+ DidHalt();
+ return error;
}
thread_result_t
@@ -4573,6 +4329,7 @@ Process::RunPrivateStateThread (bool is_secondary_thread)
__FUNCTION__, static_cast<void*>(this), GetID());
bool exit_now = false;
+ bool interrupt_requested = false;
while (!exit_now)
{
EventSP event_sp;
@@ -4612,13 +4369,32 @@ Process::RunPrivateStateThread (bool is_secondary_thread)
GetID());
BroadcastEvent (eBroadcastBitInterrupt, NULL);
}
- else
+ else if(StateIsRunningState(m_last_broadcast_state))
{
if (log)
log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") woke up with an interrupt - Halting.",
__FUNCTION__, static_cast<void*>(this),
GetID());
- Halt();
+ Error error = HaltPrivate();
+ if (error.Fail() && log)
+ log->Printf ("Process::%s (arg = %p, pid = %" PRIu64 ") failed to halt the process: %s",
+ __FUNCTION__, static_cast<void*>(this),
+ GetID(), error.AsCString());
+ // Halt should generate a stopped event. Make a note of the fact that we were
+ // doing the interrupt, so we can set the interrupted flag after we receive the
+ // event. We deliberately set this to true even if HaltPrivate failed, so that we
+ // can interrupt on the next natural stop.
+ interrupt_requested = true;
+ }
+ else
+ {
+ // This can happen when someone (e.g. Process::Halt) sees that we are running and
+ // sends an interrupt request, but the process actually stops before we receive
+ // it. In that case, we can just ignore the request. We use
+ // m_last_broadcast_state, because the Stopped event may not have been popped of
+ // the event queue yet, which is when the public state gets updated.
+ if (log)
+ log->Printf("Process::%s ignoring interrupt as we have already stopped.", __FUNCTION__);
}
continue;
}
@@ -4633,6 +4409,23 @@ Process::RunPrivateStateThread (bool is_secondary_thread)
m_clear_thread_plans_on_stop = false;
m_thread_list.DiscardThreadPlans();
}
+
+ if (interrupt_requested)
+ {
+ if (StateIsStoppedState (internal_state, true))
+ {
+ // We requested the interrupt, so mark this as such in the stop event so
+ // clients can tell an interrupted process from a natural stop
+ ProcessEventData::SetInterruptedInEvent (event_sp.get(), true);
+ interrupt_requested = false;
+ }
+ else if (log)
+ {
+ log->Printf("Process::%s interrupt_requested, but a non-stopped state '%s' received.",
+ __FUNCTION__, StateAsCString(internal_state));
+ }
+ }
+
HandlePrivateEvent (event_sp);
}
@@ -4690,9 +4483,7 @@ Process::ProcessEventData::ProcessEventData (const ProcessSP &process_sp, StateT
m_process_wp = process_sp;
}
-Process::ProcessEventData::~ProcessEventData()
-{
-}
+Process::ProcessEventData::~ProcessEventData() = default;
const ConstString &
Process::ProcessEventData::GetFlavorString ()
@@ -4734,7 +4525,12 @@ Process::ProcessEventData::DoOnRemoval (Event *event_ptr)
// If we're stopped and haven't restarted, then do the StopInfo actions here:
if (m_state == eStateStopped && ! m_restarted)
- {
+ {
+ // Let process subclasses know we are about to do a public stop and
+ // do anything they might need to in order to speed up register and
+ // memory accesses.
+ process_sp->WillPublicStop();
+
ThreadList &curr_thread_list = process_sp->GetThreadList();
uint32_t num_threads = curr_thread_list.GetSize();
uint32_t idx;
@@ -4818,7 +4614,6 @@ Process::ProcessEventData::DoOnRemoval (Event *event_ptr)
still_should_stop = this_thread_wants_to_stop;
}
}
-
if (!GetRestarted())
{
@@ -4967,13 +4762,13 @@ Process::ProcessEventData::SetUpdateStateOnRemoval (Event *event_ptr)
lldb::TargetSP
Process::CalculateTarget ()
{
- return m_target.shared_from_this();
+ return m_target_sp.lock();
}
void
Process::CalculateExecutionContext (ExecutionContext &exe_ctx)
{
- exe_ctx.SetTargetPtr (&m_target);
+ exe_ctx.SetTargetPtr (&GetTarget());
exe_ctx.SetProcessPtr (this);
exe_ctx.SetThreadPtr(NULL);
exe_ctx.SetFramePtr (NULL);
@@ -5052,7 +4847,6 @@ Process::GetAsyncProfileData (char *buf, size_t buf_size, Error &error)
return bytes_available;
}
-
//------------------------------------------------------------------
// Process STDIO
//------------------------------------------------------------------
@@ -5084,7 +4878,6 @@ Process::GetSTDOUT (char *buf, size_t buf_size, Error &error)
return bytes_available;
}
-
size_t
Process::GetSTDERR (char *buf, size_t buf_size, Error &error)
{
@@ -5135,12 +4928,8 @@ public:
m_read_file.SetDescriptor(GetInputFD(), false);
}
- virtual
- ~IOHandlerProcessSTDIO ()
- {
-
- }
-
+ ~IOHandlerProcessSTDIO() override = default;
+
// Each IOHandler gets to run until it is done. It should read data
// from the "in" and place output into "out" and "err and return
// when done.
@@ -5207,7 +4996,7 @@ public:
break;
case 'i':
if (StateIsRunningState(m_process->GetState()))
- m_process->Halt();
+ m_process->SendAsyncInterrupt();
break;
}
}
@@ -5232,8 +5021,8 @@ public:
// Do only things that are safe to do in an interrupt context (like in
// a SIGINT handler), like write 1 byte to a file descriptor. This will
// interrupt the IOHandlerProcessSTDIO::Run() and we can look at the byte
- // that was written to the pipe and then call m_process->Halt() from a
- // much safer location in code.
+ // that was written to the pipe and then call m_process->SendAsyncInterrupt()
+ // from a much safer location in code.
if (m_active)
{
char ch = 'i'; // Send 'i' for interrupt
@@ -5263,7 +5052,6 @@ public:
void
GotEOF() override
{
-
}
protected:
@@ -5301,7 +5089,7 @@ Process::ProcessIOHandlerIsActive ()
{
IOHandlerSP io_handler_sp (m_process_input_reader);
if (io_handler_sp)
- return m_target.GetDebugger().IsTopIOHandler (io_handler_sp);
+ return GetTarget().GetDebugger().IsTopIOHandler (io_handler_sp);
return false;
}
bool
@@ -5315,7 +5103,7 @@ Process::PushProcessIOHandler ()
log->Printf("Process::%s pushing IO handler", __FUNCTION__);
io_handler_sp->SetIsDone(false);
- m_target.GetDebugger().PushIOHandler (io_handler_sp);
+ GetTarget().GetDebugger().PushIOHandler (io_handler_sp);
return true;
}
return false;
@@ -5326,7 +5114,7 @@ Process::PopProcessIOHandler ()
{
IOHandlerSP io_handler_sp (m_process_input_reader);
if (io_handler_sp)
- return m_target.GetDebugger().PopIOHandler (io_handler_sp);
+ return GetTarget().GetDebugger().PopIOHandler (io_handler_sp);
return false;
}
@@ -5343,6 +5131,54 @@ Process::SettingsTerminate ()
Thread::SettingsTerminate ();
}
+namespace
+{
+ // RestorePlanState is used to record the "is private", "is master" and "okay to discard" fields of
+ // the plan we are running, and reset it on Clean or on destruction.
+ // It will only reset the state once, so you can call Clean and then monkey with the state and it
+ // won't get reset on you again.
+
+ class RestorePlanState
+ {
+ public:
+ RestorePlanState (lldb::ThreadPlanSP thread_plan_sp) :
+ m_thread_plan_sp(thread_plan_sp),
+ m_already_reset(false)
+ {
+ if (m_thread_plan_sp)
+ {
+ m_private = m_thread_plan_sp->GetPrivate();
+ m_is_master = m_thread_plan_sp->IsMasterPlan();
+ m_okay_to_discard = m_thread_plan_sp->OkayToDiscard();
+ }
+ }
+
+ ~RestorePlanState()
+ {
+ Clean();
+ }
+
+ void
+ Clean ()
+ {
+ if (!m_already_reset && m_thread_plan_sp)
+ {
+ m_already_reset = true;
+ m_thread_plan_sp->SetPrivate(m_private);
+ m_thread_plan_sp->SetIsMasterPlan (m_is_master);
+ m_thread_plan_sp->SetOkayToDiscard(m_okay_to_discard);
+ }
+ }
+
+ private:
+ lldb::ThreadPlanSP m_thread_plan_sp;
+ bool m_already_reset;
+ bool m_private;
+ bool m_is_master;
+ bool m_okay_to_discard;
+ };
+} // anonymous namespace
+
ExpressionResults
Process::RunThreadPlan (ExecutionContext &exe_ctx,
lldb::ThreadPlanSP &thread_plan_sp,
@@ -5376,12 +5212,22 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
return eExpressionSetupError;
}
+ // We need to change some of the thread plan attributes for the thread plan runner. This will restore them
+ // when we are done:
+
+ RestorePlanState thread_plan_restorer(thread_plan_sp);
+
// We rely on the thread plan we are running returning "PlanCompleted" if when it successfully completes.
// For that to be true the plan can't be private - since private plans suppress themselves in the
// GetCompletedPlan call.
- bool orig_plan_private = thread_plan_sp->GetPrivate();
thread_plan_sp->SetPrivate(false);
+
+ // The plans run with RunThreadPlan also need to be terminal master plans or when they are done we will end
+ // up asking the plan above us whether we should stop, which may give the wrong answer.
+
+ thread_plan_sp->SetIsMasterPlan (true);
+ thread_plan_sp->SetOkayToDiscard(false);
if (m_private_state.GetValue() != eStateStopped)
{
@@ -5553,7 +5399,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
}
one_thread_timeout_usec = computed_one_thread_timeout;
all_threads_timeout_usec = timeout_usec - one_thread_timeout_usec;
-
}
}
@@ -5595,8 +5440,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
#endif
TimeValue one_thread_timeout;
TimeValue final_timeout;
-
-
+
while (1)
{
// We usually want to resume the process if we get to the top of the loop.
@@ -5664,7 +5508,9 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
// This is probably an overabundance of caution, I don't think I should ever get a stopped & restarted
// event here. But if I do, the best thing is to Halt and then get out of here.
- Halt();
+ const bool clear_thread_plans = false;
+ const bool use_run_lock = false;
+ Halt(clear_thread_plans, use_run_lock);
}
errors.Printf("Didn't get running event after initial resume, got %s instead.",
@@ -5758,7 +5604,9 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
bool keep_going = false;
if (event_sp->GetType() == eBroadcastBitInterrupt)
{
- Halt();
+ const bool clear_thread_plans = false;
+ const bool use_run_lock = false;
+ Halt(clear_thread_plans, use_run_lock);
return_value = eExpressionInterrupted;
errors.Printf ("Execution halted by user interrupt.");
if (log)
@@ -5796,7 +5644,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
keep_going = true;
do_resume = false;
handle_running_event = true;
-
}
else
{
@@ -5811,10 +5658,10 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->PutCString ("Process::RunThreadPlan(): execution completed successfully.");
- // Now mark this plan as private so it doesn't get reported as the stop reason
- // after this point.
- if (thread_plan_sp)
- thread_plan_sp->SetPrivate (orig_plan_private);
+
+ // Restore the plan state so it will get reported as intended when we are done.
+ thread_plan_restorer.Clean();
+
return_value = eExpressionCompleted;
}
else
@@ -5827,6 +5674,13 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
return_value = eExpressionHitBreakpoint;
if (!options.DoesIgnoreBreakpoints())
{
+ // Restore the plan state and then force Private to false. We are
+ // going to stop because of this plan so we need it to become a public
+ // plan or it won't report correctly when we continue to its termination
+ // later on.
+ thread_plan_restorer.Clean();
+ if (thread_plan_sp)
+ thread_plan_sp->SetPrivate(false);
event_to_broadcast_sp = event_sp;
}
}
@@ -5929,7 +5783,9 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->Printf ("Process::RunThreadPlan(): Running Halt.");
- halt_error = Halt();
+ const bool clear_thread_plans = false;
+ const bool use_run_lock = false;
+ Halt(clear_thread_plans, use_run_lock);
}
if (halt_error.Success())
{
@@ -6045,6 +5901,19 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
m_public_state.SetValueNoLock(old_state);
}
+ if (return_value != eExpressionCompleted && log)
+ {
+ // Print a backtrace into the log so we can figure out where we are:
+ StreamString s;
+ s.PutCString("Thread state after unsuccessful completion: \n");
+ thread->GetStackFrameStatus (s,
+ 0,
+ UINT32_MAX,
+ true,
+ UINT32_MAX);
+ log->PutCString(s.GetData());
+
+ }
// Restore the thread state if we are going to discard the plan execution. There are three cases where this
// could happen:
// 1) The execution successfully completed
@@ -6133,7 +6002,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
else
ts.Printf("[ip unknown] ");
- lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
+ // Show the private stop info here, the public stop info will be from the last natural stop.
+ lldb::StopInfoSP stop_info_sp = thread->GetPrivateStopInfo();
if (stop_info_sp)
{
const char *stop_desc = stop_info_sp->GetDescription();
@@ -6159,7 +6029,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.",
static_cast<void*>(thread_plan_sp.get()));
thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
- thread_plan_sp->SetPrivate (orig_plan_private);
}
else
{
@@ -6176,7 +6045,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (options.DoesUnwindOnError())
{
thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
- thread_plan_sp->SetPrivate (orig_plan_private);
}
}
else
@@ -6202,7 +6070,6 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (log)
log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause unwind_on_error is set.");
thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
- thread_plan_sp->SetPrivate (orig_plan_private);
}
}
}
@@ -6360,7 +6227,6 @@ Process::GetThreadStatus (Stream &strm,
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
log->Printf("Process::GetThreadStatus - thread 0x" PRIu64 " vanished while running Thread::GetStatus.");
-
}
}
return num_thread_infos_dumped;
@@ -6529,6 +6395,65 @@ Process::ModulesDidLoad (ModuleList &module_list)
if (language_runtime_sp)
language_runtime_sp->ModulesDidLoad(module_list);
}
+
+ LoadOperatingSystemPlugin(false);
+}
+
+void
+Process::PrintWarning (uint64_t warning_type, const void *repeat_key, const char *fmt, ...)
+{
+ bool print_warning = true;
+
+ StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream();
+ if (stream_sp.get() == nullptr)
+ return;
+ if (warning_type == eWarningsOptimization
+ && GetWarningsOptimization() == false)
+ {
+ return;
+ }
+
+ if (repeat_key != nullptr)
+ {
+ WarningsCollection::iterator it = m_warnings_issued.find (warning_type);
+ if (it == m_warnings_issued.end())
+ {
+ m_warnings_issued[warning_type] = WarningsPointerSet();
+ m_warnings_issued[warning_type].insert (repeat_key);
+ }
+ else
+ {
+ if (it->second.find (repeat_key) != it->second.end())
+ {
+ print_warning = false;
+ }
+ else
+ {
+ it->second.insert (repeat_key);
+ }
+ }
+ }
+
+ if (print_warning)
+ {
+ va_list args;
+ va_start (args, fmt);
+ stream_sp->PrintfVarArg (fmt, args);
+ va_end (args);
+ }
+}
+
+void
+Process::PrintWarningOptimization (const SymbolContext &sc)
+{
+ if (GetWarningsOptimization() == true
+ && sc.module_sp.get()
+ && sc.module_sp->GetFileSpec().GetFilename().IsEmpty() == false
+ && sc.function
+ && sc.function->GetIsOptimized() == true)
+ {
+ PrintWarning (Process::Warnings::eWarningsOptimization, sc.module_sp.get(), "%s was compiled with optimization - stepping may behave oddly; variables may not be available.\n", sc.module_sp->GetFileSpec().GetFilename().GetCString());
+ }
}
ThreadCollectionSP
@@ -6568,3 +6493,87 @@ Process::GetModuleSpec(const FileSpec& module_file_spec,
module_spec.Clear();
return false;
}
+
+size_t
+Process::AddImageToken(lldb::addr_t image_ptr)
+{
+ m_image_tokens.push_back(image_ptr);
+ return m_image_tokens.size() - 1;
+}
+
+lldb::addr_t
+Process::GetImagePtrFromToken(size_t token) const
+{
+ if (token < m_image_tokens.size())
+ return m_image_tokens[token];
+ return LLDB_INVALID_IMAGE_TOKEN;
+}
+
+void
+Process::ResetImageToken(size_t token)
+{
+ if (token < m_image_tokens.size())
+ m_image_tokens[token] = LLDB_INVALID_IMAGE_TOKEN;
+}
+
+Address
+Process::AdvanceAddressToNextBranchInstruction (Address default_stop_addr, AddressRange range_bounds)
+{
+ Target &target = GetTarget();
+ DisassemblerSP disassembler_sp;
+ InstructionList *insn_list = NULL;
+
+ Address retval = default_stop_addr;
+
+ if (target.GetUseFastStepping() == false)
+ return retval;
+ if (default_stop_addr.IsValid() == false)
+ return retval;
+
+ ExecutionContext exe_ctx (this);
+ const char *plugin_name = nullptr;
+ const char *flavor = nullptr;
+ const bool prefer_file_cache = true;
+ disassembler_sp = Disassembler::DisassembleRange(target.GetArchitecture(),
+ plugin_name,
+ flavor,
+ exe_ctx,
+ range_bounds,
+ prefer_file_cache);
+ if (disassembler_sp.get())
+ insn_list = &disassembler_sp->GetInstructionList();
+
+ if (insn_list == NULL)
+ {
+ return retval;
+ }
+
+ size_t insn_offset = insn_list->GetIndexOfInstructionAtAddress (default_stop_addr);
+ if (insn_offset == UINT32_MAX)
+ {
+ return retval;
+ }
+
+ uint32_t branch_index = insn_list->GetIndexOfNextBranchInstruction (insn_offset, target);
+ if (branch_index == UINT32_MAX)
+ {
+ return retval;
+ }
+
+ if (branch_index > insn_offset)
+ {
+ Address next_branch_insn_address = insn_list->GetInstructionAtIndex (branch_index)->GetAddress();
+ if (next_branch_insn_address.IsValid() && range_bounds.ContainsFileAddress (next_branch_insn_address))
+ {
+ retval = next_branch_insn_address;
+ }
+ }
+
+ if (disassembler_sp.get())
+ {
+ // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions.
+ disassembler_sp->GetInstructionList().Clear();
+ }
+
+ return retval;
+}
diff --git a/contrib/llvm/tools/lldb/source/Target/ProcessLaunchInfo.cpp b/contrib/llvm/tools/lldb/source/Target/ProcessLaunchInfo.cpp
index bd2e1bc..fc17fe6 100644
--- a/contrib/llvm/tools/lldb/source/Target/ProcessLaunchInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ProcessLaunchInfo.cpp
@@ -11,6 +11,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Target.h"
@@ -129,7 +130,7 @@ bool
ProcessLaunchInfo::AppendSuppressFileAction (int fd, bool read, bool write)
{
FileAction file_action;
- if (file_action.Open(fd, FileSpec{"/dev/null", false}, read, write))
+ if (file_action.Open(fd, FileSpec{FileSystem::DEV_NULL, false}, read, write))
{
AppendFileAction (file_action);
return true;
diff --git a/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp b/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp
index 97f6f21..afc815b 100644
--- a/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/RegisterContext.cpp
@@ -20,6 +20,7 @@
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
@@ -103,7 +104,20 @@ uint64_t
RegisterContext::GetPC(uint64_t fail_value)
{
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- return ReadRegisterAsUnsigned (reg, fail_value);
+ uint64_t pc = ReadRegisterAsUnsigned (reg, fail_value);
+
+ if (pc != fail_value)
+ {
+ TargetSP target_sp = m_thread.CalculateTarget();
+ if (target_sp)
+ {
+ Target *target = target_sp.get();
+ if (target)
+ pc = target->GetOpcodeLoadAddress (pc, eAddressClassCode);
+ }
+ }
+
+ return pc;
}
bool
@@ -557,7 +571,7 @@ RegisterContext::ConvertBetweenRegisterKinds (lldb::RegisterKind source_rk, uint
// case 1:
// {
// int8_t v;
-// if (data.ExtractBytes (0, sizeof (int8_t), lldb::endian::InlHostByteOrder(), &v) != sizeof (int8_t))
+// if (data.ExtractBytes (0, sizeof (int8_t), endian::InlHostByteOrder(), &v) != sizeof (int8_t))
// return false;
// value = v;
// return true;
@@ -565,7 +579,7 @@ RegisterContext::ConvertBetweenRegisterKinds (lldb::RegisterKind source_rk, uint
// case 2:
// {
// int16_t v;
-// if (data.ExtractBytes (0, sizeof (int16_t), lldb::endian::InlHostByteOrder(), &v) != sizeof (int16_t))
+// if (data.ExtractBytes (0, sizeof (int16_t), endian::InlHostByteOrder(), &v) != sizeof (int16_t))
// return false;
// value = v;
// return true;
@@ -573,7 +587,7 @@ RegisterContext::ConvertBetweenRegisterKinds (lldb::RegisterKind source_rk, uint
// case 4:
// {
// int32_t v;
-// if (data.ExtractBytes (0, sizeof (int32_t), lldb::endian::InlHostByteOrder(), &v) != sizeof (int32_t))
+// if (data.ExtractBytes (0, sizeof (int32_t), endian::InlHostByteOrder(), &v) != sizeof (int32_t))
// return false;
// value = v;
// return true;
@@ -581,7 +595,7 @@ RegisterContext::ConvertBetweenRegisterKinds (lldb::RegisterKind source_rk, uint
// case 8:
// {
// int64_t v;
-// if (data.ExtractBytes (0, sizeof (int64_t), lldb::endian::InlHostByteOrder(), &v) != sizeof (int64_t))
+// if (data.ExtractBytes (0, sizeof (int64_t), endian::InlHostByteOrder(), &v) != sizeof (int64_t))
// return false;
// value = v;
// return true;
@@ -594,7 +608,7 @@ RegisterContext::ConvertBetweenRegisterKinds (lldb::RegisterKind source_rk, uint
// case sizeof (float):
// {
// float v;
-// if (data.ExtractBytes (0, sizeof (float), lldb::endian::InlHostByteOrder(), &v) != sizeof (float))
+// if (data.ExtractBytes (0, sizeof (float), endian::InlHostByteOrder(), &v) != sizeof (float))
// return false;
// value = v;
// return true;
@@ -602,7 +616,7 @@ RegisterContext::ConvertBetweenRegisterKinds (lldb::RegisterKind source_rk, uint
// case sizeof (double):
// {
// double v;
-// if (data.ExtractBytes (0, sizeof (double), lldb::endian::InlHostByteOrder(), &v) != sizeof (double))
+// if (data.ExtractBytes (0, sizeof (double), endian::InlHostByteOrder(), &v) != sizeof (double))
// return false;
// value = v;
// return true;
@@ -610,7 +624,7 @@ RegisterContext::ConvertBetweenRegisterKinds (lldb::RegisterKind source_rk, uint
// case sizeof (long double):
// {
// double v;
-// if (data.ExtractBytes (0, sizeof (long double), lldb::endian::InlHostByteOrder(), &v) != sizeof (long double))
+// if (data.ExtractBytes (0, sizeof (long double), endian::InlHostByteOrder(), &v) != sizeof (long double))
// return false;
// value = v;
// return true;
diff --git a/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp b/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp
index 7c5b022..e835521 100644
--- a/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/StackFrame.cpp
@@ -24,6 +24,7 @@
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContextScope.h"
+#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
@@ -259,7 +260,7 @@ StackFrame::GetFrameCodeAddress()
TargetSP target_sp (thread_sp->CalculateTarget());
if (target_sp)
{
- if (m_frame_code_addr.SetOpcodeLoadAddress (m_frame_code_addr.GetOffset(), target_sp.get()))
+ if (m_frame_code_addr.SetOpcodeLoadAddress (m_frame_code_addr.GetOffset(), target_sp.get(), eAddressClassCode))
{
ModuleSP module_sp (m_frame_code_addr.GetModule());
if (module_sp)
@@ -659,7 +660,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
else
name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx);
- var_sp = variable_list->FindVariable(name_const_string);
+ var_sp = variable_list->FindVariable(name_const_string, false);
bool synthetically_added_instance_object = false;
@@ -667,7 +668,8 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
{
var_path.erase (0, name_const_string.GetLength ());
}
- else if (options & eExpressionPathOptionsAllowDirectIVarAccess)
+
+ if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess))
{
// Check for direct ivars access which helps us with implicit
// access to ivars with the "this->" or "self->"
@@ -689,13 +691,43 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
}
}
}
+
+ if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions))
+ {
+ // Check if any anonymous unions are there which contain a variable with the name we need
+ for (size_t i = 0;
+ i < variable_list->GetSize();
+ i++)
+ {
+ if (VariableSP variable_sp = variable_list->GetVariableAtIndex(i))
+ {
+ if (variable_sp->GetName().IsEmpty())
+ {
+ if (Type *var_type = variable_sp->GetType())
+ {
+ if (var_type->GetForwardCompilerType().IsAnonymousType())
+ {
+ valobj_sp = GetValueObjectForFrameVariable (variable_sp, use_dynamic);
+ if (!valobj_sp)
+ return valobj_sp;
+ valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string, true);
+ if (valobj_sp)
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
- if (var_sp)
+ if (var_sp && !valobj_sp)
{
valobj_sp = GetValueObjectForFrameVariable (var_sp, use_dynamic);
if (!valobj_sp)
return valobj_sp;
-
+ }
+ if (valobj_sp)
+ {
// We are dumping at least one child
while (separator_idx != std::string::npos)
{
@@ -713,7 +745,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
{
// Make sure we aren't trying to deref an objective
// C ivar if this is not allowed
- const uint32_t pointer_type_flags = valobj_sp->GetClangType().GetTypeInfo (NULL);
+ const uint32_t pointer_type_flags = valobj_sp->GetCompilerType().GetTypeInfo (NULL);
if ((pointer_type_flags & eTypeIsObjC) &&
(pointer_type_flags & eTypeIsPointer))
{
@@ -827,7 +859,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
if (end && *end == ']'
&& *(end-1) != '[') // this code forces an error in the case of arr[]. as bitfield[] is not a good syntax we're good to go
{
- if (valobj_sp->GetClangType().IsPointerToScalarType() && deref)
+ if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref)
{
// what we have is *ptr[low]. the most similar C++ syntax is to deref ptr
// and extract bit low out of it. reading array item low
@@ -845,7 +877,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
valobj_sp = temp;
deref = false;
}
- else if (valobj_sp->GetClangType().IsArrayOfScalarType() && deref)
+ else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref)
{
// what we have is *arr[low]. the most similar C++ syntax is to get arr[0]
// (an operation that is equivalent to deref-ing arr)
@@ -870,9 +902,9 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
{
bool is_objc_pointer = true;
- if (valobj_sp->GetClangType().GetMinimumLanguage() != eLanguageTypeObjC)
+ if (valobj_sp->GetCompilerType().GetMinimumLanguage() != eLanguageTypeObjC)
is_objc_pointer = false;
- else if (!valobj_sp->GetClangType().IsPointerType())
+ else if (!valobj_sp->GetCompilerType().IsPointerType())
is_objc_pointer = false;
if (no_synth_child && is_objc_pointer)
@@ -929,7 +961,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
}
}
}
- else if (valobj_sp->GetClangType().IsArrayType (NULL, NULL, &is_incomplete_array))
+ else if (valobj_sp->GetCompilerType().IsArrayType (NULL, NULL, &is_incomplete_array))
{
// Pass false to dynamic_value here so we can tell the difference between
// no dynamic value and no member of this type...
@@ -946,7 +978,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
var_expr_path_strm.GetString().c_str());
}
}
- else if (valobj_sp->GetClangType().IsScalarType())
+ else if (valobj_sp->GetCompilerType().IsScalarType())
{
// this is a bitfield asking to display just one bit
child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, child_index, true);
@@ -1029,7 +1061,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
final_index = temp;
}
- if (valobj_sp->GetClangType().IsPointerToScalarType() && deref)
+ if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref)
{
// what we have is *ptr[low-high]. the most similar C++ syntax is to deref ptr
// and extract bits low thru high out of it. reading array items low thru high
@@ -1047,7 +1079,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
valobj_sp = temp;
deref = false;
}
- else if (valobj_sp->GetClangType().IsArrayOfScalarType() && deref)
+ else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref)
{
// what we have is *arr[low-high]. the most similar C++ syntax is to get arr[0]
// (an operation that is equivalent to deref-ing arr)
@@ -1316,6 +1348,15 @@ StackFrame::IsInlined ()
return false;
}
+lldb::LanguageType
+StackFrame::GetLanguage ()
+{
+ CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit;
+ if (cu)
+ return cu->GetLanguage();
+ return lldb::eLanguageTypeUnknown;
+}
+
TargetSP
StackFrame::CalculateTarget ()
{
@@ -1478,7 +1519,7 @@ StackFrame::GetStatus (Stream& strm,
if (show_source)
{
ExecutionContext exe_ctx (shared_from_this());
- bool have_source = false;
+ bool have_source = false, have_debuginfo = false;
Debugger::StopDisassemblyType disasm_display = Debugger::eStopDisassemblyTypeNever;
Target *target = exe_ctx.GetTargetPtr();
if (target)
@@ -1491,26 +1532,35 @@ StackFrame::GetStatus (Stream& strm,
GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);
if (m_sc.comp_unit && m_sc.line_entry.IsValid())
{
- have_source = true;
+ have_debuginfo = true;
if (source_lines_before > 0 || source_lines_after > 0)
{
- target->GetSourceManager().DisplaySourceLinesWithLineNumbers (m_sc.line_entry.file,
+ size_t num_lines = target->GetSourceManager().DisplaySourceLinesWithLineNumbers (m_sc.line_entry.file,
m_sc.line_entry.line,
source_lines_before,
source_lines_after,
"->",
&strm);
+ if (num_lines != 0)
+ have_source = true;
+ // TODO: Give here a one time warning if source file is missing.
}
}
switch (disasm_display)
{
case Debugger::eStopDisassemblyTypeNever:
break;
-
+
+ case Debugger::eStopDisassemblyTypeNoDebugInfo:
+ if (have_debuginfo)
+ break;
+ // Fall through to next case
+
case Debugger::eStopDisassemblyTypeNoSource:
if (have_source)
break;
// Fall through to next case
+
case Debugger::eStopDisassemblyTypeAlways:
if (target)
{
diff --git a/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp b/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp
index 05923d7..f2f3cad 100644
--- a/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/StackFrameList.cpp
@@ -105,9 +105,13 @@ StackFrameList::GetCurrentInlinedDepth ()
void
StackFrameList::ResetCurrentInlinedDepth ()
{
+ Mutex::Locker locker (m_mutex);
+
if (m_show_inlined_frames)
{
GetFramesUpTo(0);
+ if (m_frames.size() == 0)
+ return;
if (!m_frames[0]->IsInlined())
{
m_current_inlined_depth = UINT32_MAX;
@@ -362,8 +366,8 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx)
// adjustment it will point to an other section. In that case resolve the
// address again to the correct section plus offset form.
TargetSP target = m_thread.CalculateTarget();
- addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(target.get());
- curr_frame_address.SetOpcodeLoadAddress(load_addr - 1, target.get());
+ addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(target.get(), eAddressClassCode);
+ curr_frame_address.SetOpcodeLoadAddress(load_addr - 1, target.get(), eAddressClassCode);
}
else
{
@@ -457,9 +461,9 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx)
}
#if defined (DEBUG_STACK_FRAMES)
- s.PutCString("\n\nNew frames:\n");
- Dump (&s);
- s.EOL();
+ s.PutCString("\n\nNew frames:\n");
+ Dump (&s);
+ s.EOL();
#endif
}
else
diff --git a/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp b/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp
index 9bbb00d..e88b646 100644
--- a/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/StopInfo.cpp
@@ -1,4 +1,4 @@
-//===-- StopInfo.cpp ---------------------------------------------*- C++ -*-===//
+//===-- StopInfo.cpp --------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,14 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/StopInfo.h"
-
// C Includes
// C++ Includes
#include <string>
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/StopInfo.h"
#include "lldb/Core/Log.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -23,7 +22,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
@@ -133,6 +132,8 @@ public:
StoreBPInfo();
}
+ ~StopInfoBreakpoint() override = default;
+
void
StoreBPInfo ()
{
@@ -156,12 +157,8 @@ public:
}
}
- virtual ~StopInfoBreakpoint ()
- {
- }
-
- virtual bool
- IsValidForOperatingSystemThread (Thread &thread)
+ bool
+ IsValidForOperatingSystemThread(Thread &thread) override
{
ProcessSP process_sp (thread.GetProcess());
if (process_sp)
@@ -173,14 +170,14 @@ public:
return false;
}
- virtual StopReason
- GetStopReason () const
+ StopReason
+ GetStopReason() const override
{
return eStopReasonBreakpoint;
}
- virtual bool
- ShouldStopSynchronous (Event *event_ptr)
+ bool
+ ShouldStopSynchronous(Event *event_ptr) override
{
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
@@ -212,8 +209,8 @@ public:
return false;
}
- virtual bool
- DoShouldNotify (Event *event_ptr)
+ bool
+ DoShouldNotify(Event *event_ptr) override
{
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
@@ -237,8 +234,8 @@ public:
return true;
}
- virtual const char *
- GetDescription ()
+ const char *
+ GetDescription() override
{
if (m_description.empty())
{
@@ -312,7 +309,7 @@ public:
protected:
bool
- ShouldStop (Event *event_ptr)
+ ShouldStop(Event *event_ptr) override
{
// This just reports the work done by PerformAction or the synchronous stop. It should
// only ever get called after they have had a chance to run.
@@ -320,8 +317,8 @@ protected:
return m_should_stop;
}
- virtual void
- PerformAction (Event *event_ptr)
+ void
+ PerformAction(Event *event_ptr) override
{
if (!m_should_perform_action)
return;
@@ -350,7 +347,10 @@ protected:
if (bp_site_sp)
{
- size_t num_owners = bp_site_sp->GetNumberOfOwners();
+ // Let's copy the owners list out of the site and store them in a local list. That way if
+ // one of the breakpoint actions changes the site, then we won't be operating on a bad list.
+ BreakpointLocationCollection site_locations;
+ size_t num_owners = bp_site_sp->CopyOwnersList(site_locations);
if (num_owners == 0)
{
@@ -416,20 +416,16 @@ protected:
StoppointCallbackContext context (event_ptr, exe_ctx, false);
- // Let's copy the breakpoint locations out of the site and store them in a local list. That way if
- // one of the breakpoint actions changes the site, then we won't be operating on a bad list.
// For safety's sake let's also grab an extra reference to the breakpoint owners of the locations we're
// going to examine, since the locations are going to have to get back to their breakpoints, and the
// locations don't keep their owners alive. I'm just sticking the BreakpointSP's in a vector since
- // I'm only really using it to locally increment their retain counts.
+ // I'm only using it to locally increment their retain counts.
- BreakpointLocationCollection site_locations;
std::vector<lldb::BreakpointSP> location_owners;
for (size_t j = 0; j < num_owners; j++)
{
- BreakpointLocationSP loc(bp_site_sp->GetOwnerAtIndex(j));
- site_locations.Add(loc);
+ BreakpointLocationSP loc(site_locations.GetByIndex(j));
location_owners.push_back(loc->GetBreakpoint().shared_from_this());
}
@@ -576,7 +572,6 @@ private:
bool m_was_one_shot;
};
-
//----------------------------------------------------------------------
// StopInfoWatchpoint
//----------------------------------------------------------------------
@@ -598,6 +593,7 @@ public:
process->DisableWatchpoint(watchpoint, notify);
}
}
+
~WatchpointSentry()
{
if (process && watchpoint)
@@ -610,6 +606,7 @@ public:
watchpoint->TurnOffEphemeralMode();
}
}
+
private:
Process *process;
Watchpoint *watchpoint;
@@ -622,19 +619,17 @@ public:
m_watch_hit_addr(watch_hit_addr)
{
}
-
- virtual ~StopInfoWatchpoint ()
- {
- }
- virtual StopReason
- GetStopReason () const
+ ~StopInfoWatchpoint() override = default;
+
+ StopReason
+ GetStopReason() const override
{
return eStopReasonWatchpoint;
}
- virtual const char *
- GetDescription ()
+ const char *
+ GetDescription() override
{
if (m_description.empty())
{
@@ -646,8 +641,8 @@ public:
}
protected:
- virtual bool
- ShouldStopSynchronous (Event *event_ptr)
+ bool
+ ShouldStopSynchronous(Event *event_ptr) override
{
// ShouldStop() method is idempotent and should not affect hit count.
// See Process::RunPrivateStateThread()->Process()->HandlePrivateEvent()
@@ -686,7 +681,7 @@ protected:
}
bool
- ShouldStop (Event *event_ptr)
+ ShouldStop(Event *event_ptr) override
{
// This just reports the work done by PerformAction or the synchronous stop. It should
// only ever get called after they have had a chance to run.
@@ -694,8 +689,8 @@ protected:
return m_should_stop;
}
- virtual void
- PerformAction (Event *event_ptr)
+ void
+ PerformAction(Event *event_ptr) override
{
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS);
// We're going to calculate if we should stop or not in some way during the course of
@@ -758,9 +753,22 @@ protected:
{
WatchpointSP wp_hit_sp = thread_sp->CalculateTarget()->GetWatchpointList().FindByAddress(m_watch_hit_addr);
if (!wp_hit_sp)
+ {
m_should_stop = false;
+ wp_sp->IncrementFalseAlarmsAndReviseHitCount();
+ }
}
-
+
+ // TODO: This condition should be checked in the synchronous part of the watchpoint code
+ // (Watchpoint::ShouldStop), so that we avoid pulling an event even if the watchpoint fails
+ // the ignore count condition. It is moved here temporarily, because for archs with
+ // watchpoint_exceptions_received=before, the code in the previous lines takes care of moving
+ // the inferior to next PC. We have to check the ignore count condition after this is done,
+ // otherwise we will hit same watchpoint multiple times until we pass ignore condition, but we
+ // won't actually be ignoring them.
+ if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount())
+ m_should_stop = false;
+
if (m_should_stop && wp_sp->GetConditionText() != NULL)
{
// We need to make sure the user sees any parse errors in their condition, so we'll hook the
@@ -771,12 +779,13 @@ protected:
expr_options.SetIgnoreBreakpoints(true);
ValueObjectSP result_value_sp;
Error error;
- result_code = ClangUserExpression::Evaluate (exe_ctx,
- expr_options,
- wp_sp->GetConditionText(),
- NULL,
- result_value_sp,
- error);
+ result_code = UserExpression::Evaluate (exe_ctx,
+ expr_options,
+ wp_sp->GetConditionText(),
+ NULL,
+ result_value_sp,
+ error);
+
if (result_code == eExpressionCompleted)
{
if (result_value_sp)
@@ -876,8 +885,6 @@ private:
lldb::addr_t m_watch_hit_addr;
};
-
-
//----------------------------------------------------------------------
// StopInfoUnixSignal
//----------------------------------------------------------------------
@@ -885,26 +892,22 @@ private:
class StopInfoUnixSignal : public StopInfo
{
public:
-
StopInfoUnixSignal (Thread &thread, int signo, const char *description) :
StopInfo (thread, signo)
{
SetDescription (description);
}
-
- virtual ~StopInfoUnixSignal ()
- {
- }
+ ~StopInfoUnixSignal() override = default;
- virtual StopReason
- GetStopReason () const
+ StopReason
+ GetStopReason() const override
{
return eStopReasonSignal;
}
- virtual bool
- ShouldStopSynchronous (Event *event_ptr)
+ bool
+ ShouldStopSynchronous(Event *event_ptr) override
{
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
@@ -912,19 +915,18 @@ public:
return false;
}
- virtual bool
- ShouldStop (Event *event_ptr)
+ bool
+ ShouldStop(Event *event_ptr) override
{
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);
return false;
}
-
-
+
// If should stop returns false, check if we should notify of this event
- virtual bool
- DoShouldNotify (Event *event_ptr)
+ bool
+ DoShouldNotify(Event *event_ptr) override
{
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
@@ -943,9 +945,8 @@ public:
return true;
}
-
- virtual void
- WillResume (lldb::StateType resume_state)
+ void
+ WillResume(lldb::StateType resume_state) override
{
ThreadSP thread_sp (m_thread_wp.lock());
if (thread_sp)
@@ -955,8 +956,8 @@ public:
}
}
- virtual const char *
- GetDescription ()
+ const char *
+ GetDescription() override
{
if (m_description.empty())
{
@@ -983,33 +984,29 @@ public:
class StopInfoTrace : public StopInfo
{
public:
-
StopInfoTrace (Thread &thread) :
StopInfo (thread, LLDB_INVALID_UID)
{
}
-
- virtual ~StopInfoTrace ()
- {
- }
-
- virtual StopReason
- GetStopReason () const
+
+ ~StopInfoTrace() override = default;
+
+ StopReason
+ GetStopReason() const override
{
return eStopReasonTrace;
}
- virtual const char *
- GetDescription ()
+ const char *
+ GetDescription() override
{
if (m_description.empty())
- return "trace";
+ return "trace";
else
return m_description.c_str();
}
};
-
//----------------------------------------------------------------------
// StopInfoException
//----------------------------------------------------------------------
@@ -1017,27 +1014,23 @@ public:
class StopInfoException : public StopInfo
{
public:
-
StopInfoException (Thread &thread, const char *description) :
StopInfo (thread, LLDB_INVALID_UID)
{
if (description)
SetDescription (description);
}
-
- virtual
- ~StopInfoException ()
- {
- }
-
- virtual StopReason
- GetStopReason () const
+
+ ~StopInfoException() override = default;
+
+ StopReason
+ GetStopReason() const override
{
return eStopReasonException;
}
- virtual const char *
- GetDescription ()
+ const char *
+ GetDescription() override
{
if (m_description.empty())
return "exception";
@@ -1046,7 +1039,6 @@ public:
}
};
-
//----------------------------------------------------------------------
// StopInfoThreadPlan
//----------------------------------------------------------------------
@@ -1054,27 +1046,24 @@ public:
class StopInfoThreadPlan : public StopInfo
{
public:
-
- StopInfoThreadPlan (ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp, ClangExpressionVariableSP &expression_variable_sp) :
+ StopInfoThreadPlan (ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp, ExpressionVariableSP &expression_variable_sp) :
StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID),
m_plan_sp (plan_sp),
m_return_valobj_sp (return_valobj_sp),
m_expression_variable_sp (expression_variable_sp)
{
}
-
- virtual ~StopInfoThreadPlan ()
- {
- }
- virtual StopReason
- GetStopReason () const
+ ~StopInfoThreadPlan() override = default;
+
+ StopReason
+ GetStopReason() const override
{
return eStopReasonPlanComplete;
}
- virtual const char *
- GetDescription ()
+ const char *
+ GetDescription() override
{
if (m_description.empty())
{
@@ -1091,15 +1080,15 @@ public:
return m_return_valobj_sp;
}
- ClangExpressionVariableSP
+ ExpressionVariableSP
GetExpressionVariable()
{
return m_expression_variable_sp;
}
protected:
- virtual bool
- ShouldStop (Event *event_ptr)
+ bool
+ ShouldStop(Event *event_ptr) override
{
if (m_plan_sp)
return m_plan_sp->ShouldStop(event_ptr);
@@ -1110,39 +1099,35 @@ protected:
private:
ThreadPlanSP m_plan_sp;
ValueObjectSP m_return_valobj_sp;
- ClangExpressionVariableSP m_expression_variable_sp;
+ ExpressionVariableSP m_expression_variable_sp;
};
class StopInfoExec : public StopInfo
{
public:
-
StopInfoExec (Thread &thread) :
StopInfo (thread, LLDB_INVALID_UID),
m_performed_action (false)
{
}
-
- virtual
- ~StopInfoExec ()
- {
- }
-
- virtual StopReason
- GetStopReason () const
+
+ ~StopInfoExec() override = default;
+
+ StopReason
+ GetStopReason() const override
{
return eStopReasonExec;
}
- virtual const char *
- GetDescription ()
+ const char *
+ GetDescription() override
{
return "exec";
}
+
protected:
-
- virtual void
- PerformAction (Event *event_ptr)
+ void
+ PerformAction(Event *event_ptr) override
{
// Only perform the action once
if (m_performed_action)
@@ -1191,7 +1176,7 @@ StopInfo::CreateStopReasonToTrace (Thread &thread)
StopInfoSP
StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp,
ValueObjectSP return_valobj_sp,
- ClangExpressionVariableSP expression_variable_sp)
+ ExpressionVariableSP expression_variable_sp)
{
return StopInfoSP (new StopInfoThreadPlan (plan_sp, return_valobj_sp, expression_variable_sp));
}
@@ -1220,7 +1205,7 @@ StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp)
return ValueObjectSP();
}
-ClangExpressionVariableSP
+ExpressionVariableSP
StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp)
{
if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonPlanComplete)
@@ -1229,5 +1214,5 @@ StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp)
return plan_stop_info->GetExpressionVariable();
}
else
- return ClangExpressionVariableSP();
+ return ExpressionVariableSP();
}
diff --git a/contrib/llvm/tools/lldb/source/Target/Target.cpp b/contrib/llvm/tools/lldb/source/Target/Target.cpp
index 6ba09f4..d2aa1ba 100644
--- a/contrib/llvm/tools/lldb/source/Target/Target.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Target.cpp
@@ -7,12 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/Target.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/Target.h"
#include "lldb/Breakpoint/BreakpointResolver.h"
#include "lldb/Breakpoint/BreakpointResolverAddress.h"
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
@@ -31,10 +30,11 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Expression/ClangUserExpression.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
+#include "lldb/Expression/REPL.h"
+#include "lldb/Expression/UserExpression.h"
+#include "Plugins/ExpressionParser/Clang/ClangASTSource.h"
+#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
+#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -44,6 +44,9 @@
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
@@ -52,6 +55,7 @@
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
+#include "lldb/Utility/LLDBAssert.h"
using namespace lldb;
using namespace lldb_private;
@@ -63,9 +67,6 @@ Target::GetStaticBroadcasterClass ()
return class_name;
}
-//----------------------------------------------------------------------
-// Target constructor
-//----------------------------------------------------------------------
Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::PlatformSP &platform_sp, bool is_dummy_target) :
TargetProperties (this),
Broadcaster (&debugger, Target::GetStaticBroadcasterClass().AsCString()),
@@ -82,10 +83,7 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
m_process_sp (),
m_search_filter_sp (),
m_image_search_paths (ImageSearchPathsChanged, this),
- m_scratch_ast_context_ap (),
- m_scratch_ast_source_ap (),
- m_ast_importer_ap (),
- m_persistent_variables (new ClangPersistentVariables),
+ m_ast_importer_sp (),
m_source_manager_ap(),
m_stop_hooks (),
m_stop_hook_next_id (0),
@@ -111,6 +109,14 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
}
}
+Target::~Target()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf ("%p Target::~Target()", static_cast<void*>(this));
+ DeleteCurrentProcess ();
+}
+
void
Target::PrimeFromDummyTarget(Target *target)
{
@@ -129,17 +135,6 @@ Target::PrimeFromDummyTarget(Target *target)
}
}
-//----------------------------------------------------------------------
-// Destructor
-//----------------------------------------------------------------------
-Target::~Target()
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
- if (log)
- log->Printf ("%p Target::~Target()", static_cast<void*>(this));
- DeleteCurrentProcess ();
-}
-
void
Target::Dump (Stream *s, lldb::DescriptionLevel description_level)
{
@@ -183,7 +178,7 @@ Target::CleanupProcess ()
void
Target::DeleteCurrentProcess ()
{
- if (m_process_sp.get())
+ if (m_process_sp)
{
m_section_load_history.Clear();
if (m_process_sp->IsAlive())
@@ -201,7 +196,7 @@ const lldb::ProcessSP &
Target::CreateProcess (Listener &listener, const char *plugin_name, const FileSpec *crash_file)
{
DeleteCurrentProcess ();
- m_process_sp = Process::FindPlugin(*this, plugin_name, listener, crash_file);
+ m_process_sp = Process::FindPlugin(shared_from_this(), plugin_name, listener, crash_file);
return m_process_sp;
}
@@ -211,6 +206,69 @@ Target::GetProcessSP () const
return m_process_sp;
}
+lldb::REPLSP
+Target::GetREPL (Error &err, lldb::LanguageType language, const char *repl_options, bool can_create)
+{
+ if (language == eLanguageTypeUnknown)
+ {
+ std::set<LanguageType> repl_languages;
+
+ Language::GetLanguagesSupportingREPLs(repl_languages);
+
+ if (repl_languages.size() == 1)
+ {
+ language = *repl_languages.begin();
+ }
+ else if (repl_languages.size() == 0)
+ {
+ err.SetErrorStringWithFormat("LLDB isn't configured with support support for any REPLs.");
+ return REPLSP();
+ }
+ else
+ {
+ err.SetErrorStringWithFormat("Multiple possible REPL languages. Please specify a language.");
+ return REPLSP();
+ }
+ }
+
+ REPLMap::iterator pos = m_repl_map.find(language);
+
+ if (pos != m_repl_map.end())
+ {
+ return pos->second;
+ }
+
+ if (!can_create)
+ {
+ err.SetErrorStringWithFormat("Couldn't find an existing REPL for %s, and can't create a new one", Language::GetNameForLanguageType(language));
+ return lldb::REPLSP();
+ }
+
+ Debugger *const debugger = nullptr;
+ lldb::REPLSP ret = REPL::Create(err, language, debugger, this, repl_options);
+
+ if (ret)
+ {
+ m_repl_map[language] = ret;
+ return m_repl_map[language];
+ }
+
+ if (err.Success())
+ {
+ err.SetErrorStringWithFormat("Couldn't create a REPL for %s", Language::GetNameForLanguageType(language));
+ }
+
+ return lldb::REPLSP();
+}
+
+void
+Target::SetREPL (lldb::LanguageType language, lldb::REPLSP repl_sp)
+{
+ lldbassert(!m_repl_map.count(language));
+
+ m_repl_map[language] = repl_sp;
+}
+
void
Target::Destroy()
{
@@ -228,13 +286,11 @@ Target::Destroy()
m_last_created_watchpoint.reset();
m_search_filter_sp.reset();
m_image_search_paths.Clear(notify);
- m_persistent_variables->Clear();
m_stop_hooks.clear();
m_stop_hook_next_id = 0;
m_suppress_stop_hooks = false;
}
-
BreakpointList &
Target::GetBreakpointList(bool internal)
{
@@ -277,11 +333,10 @@ Target::CreateSourceRegexBreakpoint (const FileSpecList *containingModules,
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, source_file_spec_list));
if (move_to_nearest_code == eLazyBoolCalculate)
move_to_nearest_code = GetMoveToNearestCode() ? eLazyBoolYes : eLazyBoolNo;
- BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex (NULL, source_regex, !static_cast<bool>(move_to_nearest_code)));
+ BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex(nullptr, source_regex, !static_cast<bool>(move_to_nearest_code)));
return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
-
BreakpointSP
Target::CreateBreakpoint (const FileSpecList *containingModules,
const FileSpec &file,
@@ -330,20 +385,23 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
if (move_to_nearest_code == eLazyBoolCalculate)
move_to_nearest_code = GetMoveToNearestCode() ? eLazyBoolYes : eLazyBoolNo;
- BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine (NULL,
- file,
- line_no,
- check_inlines,
- skip_prologue,
- !static_cast<bool>(move_to_nearest_code)));
+ BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine(nullptr,
+ file,
+ line_no,
+ check_inlines,
+ skip_prologue,
+ !static_cast<bool>(move_to_nearest_code)));
return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
-
BreakpointSP
Target::CreateBreakpoint (lldb::addr_t addr, bool internal, bool hardware)
{
Address so_addr;
+
+ // Check for any reason we want to move this breakpoint to other address.
+ addr = GetBreakableLoadAddress(addr);
+
// Attempt to resolve our load address if possible, though it is ok if
// it doesn't resolve to section/offset.
@@ -359,18 +417,30 @@ Target::CreateBreakpoint (lldb::addr_t addr, bool internal, bool hardware)
}
BreakpointSP
-Target::CreateBreakpoint (Address &addr, bool internal, bool hardware)
+Target::CreateBreakpoint (const Address &addr, bool internal, bool hardware)
{
SearchFilterSP filter_sp(new SearchFilterForUnconstrainedSearches (shared_from_this()));
- BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr));
+ BreakpointResolverSP resolver_sp(new BreakpointResolverAddress(nullptr, addr));
return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, false);
}
+lldb::BreakpointSP
+Target::CreateAddressInModuleBreakpoint (lldb::addr_t file_addr,
+ bool internal,
+ const FileSpec *file_spec,
+ bool request_hardware)
+{
+ SearchFilterSP filter_sp(new SearchFilterForUnconstrainedSearches (shared_from_this()));
+ BreakpointResolverSP resolver_sp(new BreakpointResolverAddress(nullptr, file_addr, file_spec));
+ return CreateBreakpoint (filter_sp, resolver_sp, internal, request_hardware, false);
+}
+
BreakpointSP
Target::CreateBreakpoint (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
const char *func_name,
uint32_t func_name_type_mask,
+ LanguageType language,
LazyBool skip_prologue,
bool internal,
bool hardware)
@@ -382,12 +452,15 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
if (skip_prologue == eLazyBoolCalculate)
skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo;
-
- BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL,
- func_name,
- func_name_type_mask,
- Breakpoint::Exact,
- skip_prologue));
+ if (language == lldb::eLanguageTypeUnknown)
+ language = GetLanguage();
+
+ BreakpointResolverSP resolver_sp(new BreakpointResolverName(nullptr,
+ func_name,
+ func_name_type_mask,
+ language,
+ Breakpoint::Exact,
+ skip_prologue));
bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
return bp_sp;
@@ -398,6 +471,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
const std::vector<std::string> &func_names,
uint32_t func_name_type_mask,
+ LanguageType language,
LazyBool skip_prologue,
bool internal,
bool hardware)
@@ -410,11 +484,14 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
if (skip_prologue == eLazyBoolCalculate)
skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo;
-
- BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL,
- func_names,
- func_name_type_mask,
- skip_prologue));
+ if (language == lldb::eLanguageTypeUnknown)
+ language = GetLanguage();
+
+ BreakpointResolverSP resolver_sp(new BreakpointResolverName(nullptr,
+ func_names,
+ func_name_type_mask,
+ language,
+ skip_prologue));
bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
return bp_sp;
@@ -426,6 +503,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
const char *func_names[],
size_t num_names,
uint32_t func_name_type_mask,
+ LanguageType language,
LazyBool skip_prologue,
bool internal,
bool hardware)
@@ -437,12 +515,15 @@ Target::CreateBreakpoint (const FileSpecList *containingModules,
if (skip_prologue == eLazyBoolCalculate)
skip_prologue = GetSkipPrologue() ? eLazyBoolYes : eLazyBoolNo;
-
- BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL,
- func_names,
- num_names,
- func_name_type_mask,
- skip_prologue));
+ if (language == lldb::eLanguageTypeUnknown)
+ language = GetLanguage();
+
+ BreakpointResolverSP resolver_sp(new BreakpointResolverName(nullptr,
+ func_names,
+ num_names,
+ func_name_type_mask,
+ language,
+ skip_prologue));
bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
return bp_sp;
@@ -452,7 +533,7 @@ SearchFilterSP
Target::GetSearchFilterForModule (const FileSpec *containingModule)
{
SearchFilterSP filter_sp;
- if (containingModule != NULL)
+ if (containingModule != nullptr)
{
// TODO: We should look into sharing module based search filters
// across many breakpoints like we do for the simple target based one
@@ -460,7 +541,7 @@ Target::GetSearchFilterForModule (const FileSpec *containingModule)
}
else
{
- if (m_search_filter_sp.get() == NULL)
+ if (!m_search_filter_sp)
m_search_filter_sp.reset (new SearchFilterForUnconstrainedSearches (shared_from_this()));
filter_sp = m_search_filter_sp;
}
@@ -479,7 +560,7 @@ Target::GetSearchFilterForModuleList (const FileSpecList *containingModules)
}
else
{
- if (m_search_filter_sp.get() == NULL)
+ if (!m_search_filter_sp)
m_search_filter_sp.reset (new SearchFilterForUnconstrainedSearches (shared_from_this()));
filter_sp = m_search_filter_sp;
}
@@ -490,11 +571,11 @@ SearchFilterSP
Target::GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles)
{
- if (containingSourceFiles == NULL || containingSourceFiles->GetSize() == 0)
+ if (containingSourceFiles == nullptr || containingSourceFiles->GetSize() == 0)
return GetSearchFilterForModuleList(containingModules);
SearchFilterSP filter_sp;
- if (containingModules == NULL)
+ if (containingModules == nullptr)
{
// We could make a special "CU List only SearchFilter". Better yet was if these could be composable,
// but that will take a little reworking.
@@ -512,6 +593,7 @@ BreakpointSP
Target::CreateFuncRegexBreakpoint (const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
RegularExpression &func_regex,
+ lldb::LanguageType requested_language,
LazyBool skip_prologue,
bool internal,
bool hardware)
@@ -520,9 +602,10 @@ Target::CreateFuncRegexBreakpoint (const FileSpecList *containingModules,
bool skip =
(skip_prologue == eLazyBoolCalculate) ? GetSkipPrologue()
: static_cast<bool>(skip_prologue);
- BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL,
- func_regex,
- skip));
+ BreakpointResolverSP resolver_sp(new BreakpointResolverName(nullptr,
+ func_regex,
+ requested_language,
+ skip));
return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, true);
}
@@ -608,7 +691,7 @@ CheckIfWatchpointsExhausted(Target *target, Error &error)
// See also Watchpoint::SetWatchpointType(uint32_t type) and
// the OptionGroupWatchpoint::WatchType enum type.
WatchpointSP
-Target::CreateWatchpoint(lldb::addr_t addr, size_t size, const ClangASTType *type, uint32_t kind, Error &error)
+Target::CreateWatchpoint(lldb::addr_t addr, size_t size, const CompilerType *type, uint32_t kind, Error &error)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
if (log)
@@ -1105,9 +1188,8 @@ Target::ClearModules(bool delete_locations)
ModulesDidUnload (m_images, delete_locations);
m_section_load_history.Clear();
m_images.Clear();
- m_scratch_ast_context_ap.reset();
- m_scratch_ast_source_ap.reset();
- m_ast_importer_ap.reset();
+ m_scratch_type_system_map.Clear();
+ m_ast_importer_sp.reset();
}
void
@@ -1124,7 +1206,7 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TARGET));
ClearModules(false);
- if (executable_sp.get())
+ if (executable_sp)
{
Timer scoped_timer (__PRETTY_FUNCTION__,
"Target::SetExecutableModule (executable = '%s')",
@@ -1151,13 +1233,13 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
FileSpec dependent_file_spec (dependent_files.GetFileSpecPointerAtIndex(i));
FileSpec platform_dependent_file_spec;
if (m_platform_sp)
- m_platform_sp->GetFileWithUUID (dependent_file_spec, NULL, platform_dependent_file_spec);
+ m_platform_sp->GetFileWithUUID(dependent_file_spec, nullptr, platform_dependent_file_spec);
else
platform_dependent_file_spec = dependent_file_spec;
ModuleSpec module_spec (platform_dependent_file_spec, m_arch);
ModuleSP image_module_sp(GetSharedModule (module_spec));
- if (image_module_sp.get())
+ if (image_module_sp)
{
ObjectFile *objfile = image_module_sp->GetObjectFile();
if (objfile)
@@ -1168,49 +1250,74 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
}
}
-
bool
Target::SetArchitecture (const ArchSpec &arch_spec)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TARGET));
- if (m_arch.IsCompatibleMatch(arch_spec) || !m_arch.IsValid())
+ bool missing_local_arch = !m_arch.IsValid();
+ bool replace_local_arch = true;
+ bool compatible_local_arch = false;
+ ArchSpec other(arch_spec);
+
+ if (!missing_local_arch)
+ {
+ if (m_arch.IsCompatibleMatch(arch_spec))
+ {
+ other.MergeFrom(m_arch);
+
+ if (m_arch.IsCompatibleMatch(other))
+ {
+ compatible_local_arch = true;
+ bool arch_changed, vendor_changed, os_changed, os_ver_changed, env_changed;
+
+ m_arch.PiecewiseTripleCompare(other,
+ arch_changed,
+ vendor_changed,
+ os_changed,
+ os_ver_changed,
+ env_changed);
+
+ if (!arch_changed && !vendor_changed && !os_changed)
+ replace_local_arch = false;
+ }
+ }
+ }
+
+ if (compatible_local_arch || missing_local_arch)
{
- // If we haven't got a valid arch spec, or the architectures are
- // compatible, so just update the architecture. Architectures can be
- // equal, yet the triple OS and vendor might change, so we need to do
- // the assignment here just in case.
- m_arch = arch_spec;
+ // If we haven't got a valid arch spec, or the architectures are compatible
+ // update the architecture, unless the one we already have is more specified
+ if (replace_local_arch)
+ m_arch = other;
if (log)
- log->Printf ("Target::SetArchitecture setting architecture to %s (%s)", arch_spec.GetArchitectureName(), arch_spec.GetTriple().getTriple().c_str());
+ log->Printf ("Target::SetArchitecture set architecture to %s (%s)", m_arch.GetArchitectureName(), m_arch.GetTriple().getTriple().c_str());
return true;
}
- else
+
+ // If we have an executable file, try to reset the executable to the desired architecture
+ if (log)
+ log->Printf ("Target::SetArchitecture changing architecture to %s (%s)", arch_spec.GetArchitectureName(), arch_spec.GetTriple().getTriple().c_str());
+ m_arch = other;
+ ModuleSP executable_sp = GetExecutableModule ();
+
+ ClearModules(true);
+ // Need to do something about unsetting breakpoints.
+
+ if (executable_sp)
{
- // If we have an executable file, try to reset the executable to the desired architecture
if (log)
- log->Printf ("Target::SetArchitecture changing architecture to %s (%s)", arch_spec.GetArchitectureName(), arch_spec.GetTriple().getTriple().c_str());
- m_arch = arch_spec;
- ModuleSP executable_sp = GetExecutableModule ();
-
- ClearModules(true);
- // Need to do something about unsetting breakpoints.
-
- if (executable_sp)
+ log->Printf("Target::SetArchitecture Trying to select executable file architecture %s (%s)", arch_spec.GetArchitectureName(), arch_spec.GetTriple().getTriple().c_str());
+ ModuleSpec module_spec (executable_sp->GetFileSpec(), other);
+ Error error = ModuleList::GetSharedModule(module_spec,
+ executable_sp,
+ &GetExecutableSearchPaths(),
+ nullptr,
+ nullptr);
+
+ if (!error.Fail() && executable_sp)
{
- if (log)
- log->Printf("Target::SetArchitecture Trying to select executable file architecture %s (%s)", arch_spec.GetArchitectureName(), arch_spec.GetTriple().getTriple().c_str());
- ModuleSpec module_spec (executable_sp->GetFileSpec(), arch_spec);
- Error error = ModuleList::GetSharedModule (module_spec,
- executable_sp,
- &GetExecutableSearchPaths(),
- NULL,
- NULL);
-
- if (!error.Fail() && executable_sp)
- {
- SetExecutableModule (executable_sp, true);
- return true;
- }
+ SetExecutableModule (executable_sp, true);
+ return true;
}
}
return false;
@@ -1261,7 +1368,7 @@ Target::ModuleAdded (const ModuleList& module_list, const ModuleSP &module_sp)
void
Target::ModuleRemoved (const ModuleList& module_list, const ModuleSP &module_sp)
{
- // A module is being added to this target for the first time
+ // A module is being removed from this target.
if (m_valid)
{
ModuleList my_module_list;
@@ -1275,7 +1382,10 @@ Target::ModuleUpdated (const ModuleList& module_list, const ModuleSP &old_module
{
// A module is replacing an already added module
if (m_valid)
+ {
m_breakpoint_list.UpdateBreakpointsWhenModuleIsReplaced(old_module_sp, new_module_sp);
+ m_internal_breakpoint_list.UpdateBreakpointsWhenModuleIsReplaced(old_module_sp, new_module_sp);
+ }
}
void
@@ -1284,6 +1394,7 @@ Target::ModulesDidLoad (ModuleList &module_list)
if (m_valid && module_list.GetSize())
{
m_breakpoint_list.UpdateBreakpoints (module_list, true, false);
+ m_internal_breakpoint_list.UpdateBreakpoints (module_list, true, false);
if (m_process_sp)
{
m_process_sp->ModulesDidLoad (module_list);
@@ -1308,6 +1419,7 @@ Target::SymbolsDidLoad (ModuleList &module_list)
}
m_breakpoint_list.UpdateBreakpoints (module_list, true, false);
+ m_internal_breakpoint_list.UpdateBreakpoints (module_list, true, false);
BroadcastEvent (eBroadcastBitSymbolsLoaded, new TargetEventData (this->shared_from_this(), module_list));
}
}
@@ -1319,6 +1431,7 @@ Target::ModulesDidUnload (ModuleList &module_list, bool delete_locations)
{
UnloadModuleSections (module_list);
m_breakpoint_list.UpdateBreakpoints (module_list, false, delete_locations);
+ m_internal_breakpoint_list.UpdateBreakpoints (module_list, false, delete_locations);
BroadcastEvent (eBroadcastBitModulesUnloaded, new TargetEventData (this->shared_from_this(), module_list));
}
}
@@ -1439,7 +1552,6 @@ Target::ReadMemory (const Address& addr,
}
if (!resolved_addr.IsValid())
resolved_addr = addr;
-
if (prefer_file_cache)
{
@@ -1526,7 +1638,6 @@ Target::ReadCStringFromMemory (const Address& addr, std::string &out_str, Error
return out_str.size();
}
-
size_t
Target::ReadCStringFromMemory (const Address& addr, char *dst, size_t dst_max_len, Error &result_error)
{
@@ -1575,7 +1686,7 @@ Target::ReadCStringFromMemory (const Address& addr, char *dst, size_t dst_max_le
}
else
{
- if (dst == NULL)
+ if (dst == nullptr)
result_error.SetErrorString("invalid arguments");
else
result_error.Clear();
@@ -1821,7 +1932,6 @@ Target::GetSharedModule (const ModuleSpec &module_spec, Error *error_ptr)
return module_sp;
}
-
TargetSP
Target::CalculateTarget ()
{
@@ -1860,11 +1970,8 @@ Target::GetImageSearchPathList ()
}
void
-Target::ImageSearchPathsChanged
-(
- const PathMappingList &path_list,
- void *baton
-)
+Target::ImageSearchPathsChanged(const PathMappingList &path_list,
+ void *baton)
{
Target *target = (Target *)baton;
ModuleSP exe_module_sp (target->GetExecutableModule());
@@ -1872,33 +1979,157 @@ Target::ImageSearchPathsChanged
target->SetExecutableModule (exe_module_sp, true);
}
+TypeSystem *
+Target::GetScratchTypeSystemForLanguage (Error *error, lldb::LanguageType language, bool create_on_demand)
+{
+ if (!m_valid)
+ return nullptr;
+
+ if (error)
+ {
+ error->Clear();
+ }
+
+ if (language == eLanguageTypeMipsAssembler // GNU AS and LLVM use it for all assembly code
+ || language == eLanguageTypeUnknown)
+ {
+ std::set<lldb::LanguageType> languages_for_types;
+ std::set<lldb::LanguageType> languages_for_expressions;
+
+ Language::GetLanguagesSupportingTypeSystems(languages_for_types, languages_for_expressions);
+
+ if (languages_for_expressions.count(eLanguageTypeC))
+ {
+ language = eLanguageTypeC; // LLDB's default. Override by setting the target language.
+ }
+ else
+ {
+ if (languages_for_expressions.empty())
+ {
+ return nullptr;
+ }
+ else
+ {
+ language = *languages_for_expressions.begin();
+ }
+ }
+ }
+
+ return m_scratch_type_system_map.GetTypeSystemForLanguage(language, this, create_on_demand);
+}
+
+PersistentExpressionState *
+Target::GetPersistentExpressionStateForLanguage (lldb::LanguageType language)
+{
+ TypeSystem *type_system = GetScratchTypeSystemForLanguage(nullptr, language, true);
+
+ if (type_system)
+ {
+ return type_system->GetPersistentExpressionState();
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+UserExpression *
+Target::GetUserExpressionForLanguage(const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ Expression::ResultType desired_type,
+ const EvaluateExpressionOptions &options,
+ Error &error)
+{
+ Error type_system_error;
+
+ TypeSystem *type_system = GetScratchTypeSystemForLanguage (&type_system_error, language);
+ UserExpression *user_expr = nullptr;
+
+ if (!type_system)
+ {
+ error.SetErrorStringWithFormat("Could not find type system for language %s: %s", Language::GetNameForLanguageType(language), type_system_error.AsCString());
+ return nullptr;
+ }
+
+ user_expr = type_system->GetUserExpression(expr, expr_prefix, language, desired_type, options);
+ if (!user_expr)
+ error.SetErrorStringWithFormat("Could not create an expression for language %s", Language::GetNameForLanguageType(language));
+
+ return user_expr;
+}
+
+FunctionCaller *
+Target::GetFunctionCallerForLanguage (lldb::LanguageType language,
+ const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name,
+ Error &error)
+{
+ Error type_system_error;
+ TypeSystem *type_system = GetScratchTypeSystemForLanguage (&type_system_error, language);
+ FunctionCaller *persistent_fn = nullptr;
+
+ if (!type_system)
+ {
+ error.SetErrorStringWithFormat("Could not find type system for language %s: %s", Language::GetNameForLanguageType(language), type_system_error.AsCString());
+ return persistent_fn;
+ }
+
+ persistent_fn = type_system->GetFunctionCaller (return_type, function_address, arg_value_list, name);
+ if (!persistent_fn)
+ error.SetErrorStringWithFormat("Could not create an expression for language %s", Language::GetNameForLanguageType(language));
+
+ return persistent_fn;
+}
+
+UtilityFunction *
+Target::GetUtilityFunctionForLanguage (const char *text,
+ lldb::LanguageType language,
+ const char *name,
+ Error &error)
+{
+ Error type_system_error;
+ TypeSystem *type_system = GetScratchTypeSystemForLanguage (&type_system_error, language);
+ UtilityFunction *utility_fn = nullptr;
+
+ if (!type_system)
+ {
+ error.SetErrorStringWithFormat("Could not find type system for language %s: %s", Language::GetNameForLanguageType(language), type_system_error.AsCString());
+ return utility_fn;
+ }
+
+ utility_fn = type_system->GetUtilityFunction (text, name);
+ if (!utility_fn)
+ error.SetErrorStringWithFormat("Could not create an expression for language %s", Language::GetNameForLanguageType(language));
+
+ return utility_fn;
+}
+
ClangASTContext *
Target::GetScratchClangASTContext(bool create_on_demand)
{
- // Now see if we know the target triple, and if so, create our scratch AST context:
- if (m_scratch_ast_context_ap.get() == NULL && m_arch.IsValid() && create_on_demand)
+ if (m_valid)
{
- m_scratch_ast_context_ap.reset (new ClangASTContext(m_arch.GetTriple().str().c_str()));
- m_scratch_ast_source_ap.reset (new ClangASTSource(shared_from_this()));
- m_scratch_ast_source_ap->InstallASTContext(m_scratch_ast_context_ap->getASTContext());
- llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(m_scratch_ast_source_ap->CreateProxy());
- m_scratch_ast_context_ap->SetExternalSource(proxy_ast_source);
+ if (TypeSystem* type_system = GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC, create_on_demand))
+ return llvm::dyn_cast<ClangASTContext>(type_system);
}
- return m_scratch_ast_context_ap.get();
+ return nullptr;
}
-ClangASTImporter *
+ClangASTImporterSP
Target::GetClangASTImporter()
{
- ClangASTImporter *ast_importer = m_ast_importer_ap.get();
-
- if (!ast_importer)
+ if (m_valid)
{
- ast_importer = new ClangASTImporter();
- m_ast_importer_ap.reset(ast_importer);
+ if (!m_ast_importer_sp)
+ {
+ m_ast_importer_sp.reset(new ClangASTImporter());
+ }
+ return m_ast_importer_sp;
}
-
- return ast_importer;
+ return ClangASTImporterSP();
}
void
@@ -1967,28 +2198,25 @@ Target::GetTargetFromContexts (const ExecutionContext *exe_ctx_ptr, const Symbol
// the "target_sp" member of SymbolContext. This accessor helper function
// will get the target from one of these locations.
- Target *target = NULL;
- if (sc_ptr != NULL)
+ Target *target = nullptr;
+ if (sc_ptr != nullptr)
target = sc_ptr->target_sp.get();
- if (target == NULL && exe_ctx_ptr)
+ if (target == nullptr && exe_ctx_ptr)
target = exe_ctx_ptr->GetTargetPtr();
return target;
}
ExpressionResults
-Target::EvaluateExpression
-(
- const char *expr_cstr,
- StackFrame *frame,
- lldb::ValueObjectSP &result_valobj_sp,
- const EvaluateExpressionOptions& options
-)
+Target::EvaluateExpression(const char *expr_cstr,
+ ExecutionContextScope *exe_scope,
+ lldb::ValueObjectSP &result_valobj_sp,
+ const EvaluateExpressionOptions& options)
{
result_valobj_sp.reset();
ExpressionResults execution_results = eExpressionSetupError;
- if (expr_cstr == NULL || expr_cstr[0] == '\0')
+ if (expr_cstr == nullptr || expr_cstr[0] == '\0')
return execution_results;
// We shouldn't run stop hooks in expressions.
@@ -1998,9 +2226,9 @@ Target::EvaluateExpression
ExecutionContext exe_ctx;
- if (frame)
+ if (exe_scope)
{
- frame->CalculateExecutionContext(exe_ctx);
+ exe_scope->CalculateExecutionContext(exe_ctx);
}
else if (m_process_sp)
{
@@ -2013,10 +2241,10 @@ Target::EvaluateExpression
// Make sure we aren't just trying to see the value of a persistent
// variable (something like "$0")
- lldb::ClangExpressionVariableSP persistent_var_sp;
+ lldb::ExpressionVariableSP persistent_var_sp;
// Only check for persistent variables the expression starts with a '$'
if (expr_cstr[0] == '$')
- persistent_var_sp = m_persistent_variables->GetVariable (expr_cstr);
+ persistent_var_sp = GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC)->GetPersistentExpressionState()->GetVariable (expr_cstr);
if (persistent_var_sp)
{
@@ -2027,12 +2255,12 @@ Target::EvaluateExpression
{
const char *prefix = GetExpressionPrefixContentsAsCString();
Error error;
- execution_results = ClangUserExpression::Evaluate (exe_ctx,
- options,
- expr_cstr,
- prefix,
- result_valobj_sp,
- error);
+ execution_results = UserExpression::Evaluate (exe_ctx,
+ options,
+ expr_cstr,
+ prefix,
+ result_valobj_sp,
+ error);
}
m_suppress_stop_hooks = old_suppress_value;
@@ -2040,10 +2268,40 @@ Target::EvaluateExpression
return execution_results;
}
-ClangPersistentVariables &
-Target::GetPersistentVariables()
+lldb::ExpressionVariableSP
+Target::GetPersistentVariable(const ConstString &name)
{
- return *m_persistent_variables;
+ lldb::ExpressionVariableSP variable_sp;
+ m_scratch_type_system_map.ForEach([this, name, &variable_sp](TypeSystem *type_system) -> bool
+ {
+ if (PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState())
+ {
+ variable_sp = persistent_state->GetVariable(name);
+
+ if (variable_sp)
+ return false; // Stop iterating the ForEach
+ }
+ return true; // Keep iterating the ForEach
+ });
+ return variable_sp;
+}
+
+lldb::addr_t
+Target::GetPersistentSymbol(const ConstString &name)
+{
+ lldb::addr_t address = LLDB_INVALID_ADDRESS;
+
+ m_scratch_type_system_map.ForEach([this, name, &address](TypeSystem *type_system) -> bool
+ {
+ if (PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState())
+ {
+ address = persistent_state->LookupSymbol(name);
+ if (address != LLDB_INVALID_ADDRESS)
+ return false; // Stop iterating the ForEach
+ }
+ return true; // Keep iterating the ForEach
+ });
+ return address;
}
lldb::addr_t
@@ -2052,6 +2310,27 @@ Target::GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class)
addr_t code_addr = load_addr;
switch (m_arch.GetMachine())
{
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ switch (addr_class)
+ {
+ case eAddressClassData:
+ case eAddressClassDebug:
+ return LLDB_INVALID_ADDRESS;
+
+ case eAddressClassUnknown:
+ case eAddressClassInvalid:
+ case eAddressClassCode:
+ case eAddressClassCodeAlternateISA:
+ case eAddressClassRuntime:
+ if ((code_addr & 2ull) || (addr_class == eAddressClassCodeAlternateISA))
+ code_addr |= 1ull;
+ break;
+ }
+ break;
+
case llvm::Triple::arm:
case llvm::Triple::thumb:
switch (addr_class)
@@ -2097,6 +2376,10 @@ Target::GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) c
addr_t opcode_addr = load_addr;
switch (m_arch.GetMachine())
{
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
case llvm::Triple::arm:
case llvm::Triple::thumb:
switch (addr_class)
@@ -2121,10 +2404,174 @@ Target::GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) c
return opcode_addr;
}
+lldb::addr_t
+Target::GetBreakableLoadAddress (lldb::addr_t addr)
+{
+ addr_t breakable_addr = addr;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
+
+ switch (m_arch.GetMachine())
+ {
+ default:
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ {
+ addr_t function_start = 0;
+ addr_t current_offset = 0;
+ uint32_t loop_count = 0;
+ Address resolved_addr;
+ uint32_t arch_flags = m_arch.GetFlags ();
+ bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
+ bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
+ SectionLoadList &section_load_list = GetSectionLoadList();
+
+ if (section_load_list.IsEmpty())
+ // No sections are loaded, so we must assume we are not running yet
+ // and need to operate only on file address.
+ m_images.ResolveFileAddress (addr, resolved_addr);
+ else
+ section_load_list.ResolveLoadAddress(addr, resolved_addr);
+
+ // Get the function boundaries to make sure we don't scan back before the beginning of the current function.
+ ModuleSP temp_addr_module_sp (resolved_addr.GetModule());
+ if (temp_addr_module_sp)
+ {
+ SymbolContext sc;
+ uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
+ temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr, resolve_scope, sc);
+ if (sc.function)
+ {
+ function_start = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(this);
+ if (function_start == LLDB_INVALID_ADDRESS)
+ function_start = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
+ }
+ else if (sc.symbol)
+ {
+ Address sym_addr = sc.symbol->GetAddress();
+ function_start = sym_addr.GetFileAddress();
+ }
+ current_offset = addr - function_start;
+ }
+
+ // If breakpoint address is start of function then we dont have to do anything.
+ if (current_offset == 0)
+ return breakable_addr;
+ else
+ loop_count = current_offset / 2;
+
+ if (loop_count > 3)
+ {
+ // Scan previous 6 bytes
+ if (IsMips16 | IsMicromips)
+ loop_count = 3;
+ // For mips-only, instructions are always 4 bytes, so scan previous 4 bytes only.
+ else
+ loop_count = 2;
+ }
+
+ // Create Disassembler Instance
+ lldb::DisassemblerSP disasm_sp(Disassembler::FindPlugin(m_arch, nullptr, nullptr));
+
+ ExecutionContext exe_ctx;
+ CalculateExecutionContext(exe_ctx);
+ InstructionList instruction_list;
+ InstructionSP prev_insn;
+ bool prefer_file_cache = true; // Read from file
+ uint32_t inst_to_choose = 0;
+
+ for (uint32_t i = 1; i <= loop_count; i++)
+ {
+ // Adjust the address to read from.
+ resolved_addr.Slide (-2);
+ AddressRange range(resolved_addr, i*2);
+ uint32_t insn_size = 0;
+
+ disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache);
+
+ uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
+ if (num_insns)
+ {
+ prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0);
+ insn_size = prev_insn->GetOpcode().GetByteSize();
+ if (i == 1 && insn_size == 2)
+ {
+ // This looks like a valid 2-byte instruction (but it could be a part of upper 4 byte instruction).
+ instruction_list.Append(prev_insn);
+ inst_to_choose = 1;
+ }
+ else if (i == 2)
+ {
+ // Here we may get one 4-byte instruction or two 2-byte instructions.
+ if (num_insns == 2)
+ {
+ // Looks like there are two 2-byte instructions above our breakpoint target address.
+ // Now the upper 2-byte instruction is either a valid 2-byte instruction or could be a part of it's upper 4-byte instruction.
+ // In both cases we don't care because in this case lower 2-byte instruction is definitely a valid instruction
+ // and whatever i=1 iteration has found out is true.
+ inst_to_choose = 1;
+ break;
+ }
+ else if (insn_size == 4)
+ {
+ // This instruction claims its a valid 4-byte instruction. But it could be a part of it's upper 4-byte instruction.
+ // Lets try scanning upper 2 bytes to verify this.
+ instruction_list.Append(prev_insn);
+ inst_to_choose = 2;
+ }
+ }
+ else if (i == 3)
+ {
+ if (insn_size == 4)
+ // FIXME: We reached here that means instruction at [target - 4] has already claimed to be a 4-byte instruction,
+ // and now instruction at [target - 6] is also claiming that it's a 4-byte instruction. This can not be true.
+ // In this case we can not decide the valid previous instruction so we let lldb set the breakpoint at the address given by user.
+ inst_to_choose = 0;
+ else
+ // This is straight-forward
+ inst_to_choose = 2;
+ break;
+ }
+ }
+ else
+ {
+ // Decode failed, bytes do not form a valid instruction. So whatever previous iteration has found out is true.
+ if (i > 1)
+ {
+ inst_to_choose = i - 1;
+ break;
+ }
+ }
+ }
+
+ // Check if we are able to find any valid instruction.
+ if (inst_to_choose)
+ {
+ if (inst_to_choose > instruction_list.GetSize())
+ inst_to_choose--;
+ prev_insn = instruction_list.GetInstructionAtIndex(inst_to_choose - 1);
+
+ if (prev_insn->HasDelaySlot())
+ {
+ uint32_t shift_size = prev_insn->GetOpcode().GetByteSize();
+ // Adjust the breakable address
+ breakable_addr = addr - shift_size;
+ if (log)
+ log->Printf ("Target::%s Breakpoint at 0x%8.8" PRIx64 " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n", __FUNCTION__, addr, breakable_addr);
+ }
+ }
+ break;
+ }
+ }
+ return breakable_addr;
+}
+
SourceManager &
Target::GetSourceManager ()
{
- if (m_source_manager_ap.get() == NULL)
+ if (!m_source_manager_ap)
m_source_manager_ap.reset (new SourceManager(shared_from_this()));
return *m_source_manager_ap;
}
@@ -2158,12 +2605,8 @@ Target::CreateStopHook ()
bool
Target::RemoveStopHookByID (lldb::user_id_t user_id)
{
- size_t num_removed;
- num_removed = m_stop_hooks.erase (user_id);
- if (num_removed == 0)
- return false;
- else
- return true;
+ size_t num_removed = m_stop_hooks.erase(user_id);
+ return (num_removed != 0);
}
void
@@ -2266,19 +2709,9 @@ Target::RunStopHooks ()
bool keep_going = true;
bool hooks_ran = false;
- bool print_hook_header;
- bool print_thread_header;
+ bool print_hook_header = (m_stop_hooks.size() != 1);
+ bool print_thread_header = (num_exe_ctx != 1);
- if (num_exe_ctx == 1)
- print_thread_header = false;
- else
- print_thread_header = true;
-
- if (m_stop_hooks.size() == 1)
- print_hook_header = false;
- else
- print_hook_header = true;
-
for (pos = m_stop_hooks.begin(); keep_going && pos != end; pos++)
{
// result.Clear();
@@ -2289,9 +2722,9 @@ Target::RunStopHooks ()
bool any_thread_matched = false;
for (size_t i = 0; keep_going && i < num_exe_ctx; i++)
{
- if ((cur_hook_sp->GetSpecifier () == NULL
+ if ((cur_hook_sp->GetSpecifier() == nullptr
|| cur_hook_sp->GetSpecifier()->SymbolContextMatches(sym_ctx_with_reasons[i]))
- && (cur_hook_sp->GetThreadSpecifier() == NULL
+ && (cur_hook_sp->GetThreadSpecifier() == nullptr
|| cur_hook_sp->GetThreadSpecifier()->ThreadPassesBasicTests(exc_ctx_with_reasons[i].GetThreadRef())))
{
if (!hooks_ran)
@@ -2302,7 +2735,7 @@ Target::RunStopHooks ()
{
const char *cmd = (cur_hook_sp->GetCommands().GetSize() == 1 ?
cur_hook_sp->GetCommands().GetStringAtIndex(0) :
- NULL);
+ nullptr);
if (cmd)
result.AppendMessageWithFormat("\n- Hook %" PRIu64 " (%s)\n", cur_hook_sp->GetID(), cmd);
else
@@ -2347,7 +2780,7 @@ Target::GetGlobalProperties()
static TargetPropertiesSP g_settings_sp;
if (!g_settings_sp)
{
- g_settings_sp.reset (new TargetProperties (NULL));
+ g_settings_sp.reset(new TargetProperties(nullptr));
}
return g_settings_sp;
}
@@ -2439,7 +2872,6 @@ Target::SetSectionLoadAddress (const SectionSP &section_sp, addr_t new_section_l
return true; // Return true if the section load address was changed...
}
return false; // Return false to indicate nothing changed
-
}
size_t
@@ -2506,7 +2938,6 @@ Target::ClearAllLoadedSections ()
m_section_load_history.Clear();
}
-
Error
Target::Launch (ProcessLaunchInfo &launch_info, Stream *stream)
{
@@ -2609,7 +3040,7 @@ Target::Launch (ProcessLaunchInfo &launch_info, Stream *stream)
{
// Use a Process plugin to construct the process.
const char *plugin_name = launch_info.GetProcessPluginName();
- CreateProcess (launch_info.GetListenerForProcess(debugger), plugin_name, NULL);
+ CreateProcess(launch_info.GetListenerForProcess(debugger), plugin_name, nullptr);
}
// Since we didn't have a platform launch the process, launch it here.
@@ -2626,7 +3057,7 @@ Target::Launch (ProcessLaunchInfo &launch_info, Stream *stream)
if (error.Success())
{
- if (synchronous_execution || launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
+ if (synchronous_execution || !launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
{
ListenerSP hijack_listener_sp (launch_info.GetHijackListener());
if (!hijack_listener_sp)
@@ -2636,7 +3067,7 @@ Target::Launch (ProcessLaunchInfo &launch_info, Stream *stream)
m_process_sp->HijackProcessEvents(hijack_listener_sp.get());
}
- StateType state = m_process_sp->WaitForProcessToStop (NULL, NULL, false, hijack_listener_sp.get(), NULL);
+ StateType state = m_process_sp->WaitForProcessToStop(nullptr, nullptr, false, hijack_listener_sp.get(), nullptr);
if (state == eStateStopped)
{
@@ -2647,7 +3078,7 @@ Target::Launch (ProcessLaunchInfo &launch_info, Stream *stream)
error = m_process_sp->PrivateResume();
if (error.Success())
{
- state = m_process_sp->WaitForProcessToStop (NULL, NULL, true, hijack_listener_sp.get(), stream);
+ state = m_process_sp->WaitForProcessToStop(nullptr, nullptr, true, hijack_listener_sp.get(), stream);
const bool must_be_alive = false; // eStateExited is ok, so this must be false
if (!StateIsStoppedState(state, must_be_alive))
{
@@ -2721,9 +3152,6 @@ Target::Attach (ProcessAttachInfo &attach_info, Stream *stream)
}
}
- ListenerSP hijack_listener_sp (new Listener ("lldb.Target.Attach.attach.hijack"));
- attach_info.SetHijackListener (hijack_listener_sp);
-
const ModuleSP old_exec_module_sp = GetExecutableModule ();
// If no process info was specified, then use the target executable
@@ -2740,6 +3168,13 @@ Target::Attach (ProcessAttachInfo &attach_info, Stream *stream)
}
const auto platform_sp = GetDebugger ().GetPlatformList ().GetSelectedPlatform ();
+ ListenerSP hijack_listener_sp;
+ const bool async = attach_info.GetAsync();
+ if (!async)
+ {
+ hijack_listener_sp.reset (new Listener ("lldb.Target.Attach.attach.hijack"));
+ attach_info.SetHijackListener (hijack_listener_sp);
+ }
Error error;
if (state != eStateConnected && platform_sp != nullptr && platform_sp->CanDebugProcess ())
@@ -2759,23 +3194,31 @@ Target::Attach (ProcessAttachInfo &attach_info, Stream *stream)
return error;
}
}
- process_sp->HijackProcessEvents (hijack_listener_sp.get ());
+ if (hijack_listener_sp)
+ process_sp->HijackProcessEvents (hijack_listener_sp.get ());
error = process_sp->Attach (attach_info);
}
if (error.Success () && process_sp)
{
- state = process_sp->WaitForProcessToStop (nullptr, nullptr, false, attach_info.GetHijackListener ().get (), stream);
- process_sp->RestoreProcessEvents ();
-
- if (state != eStateStopped)
+ if (async)
{
- const char *exit_desc = process_sp->GetExitDescription ();
- if (exit_desc)
- error.SetErrorStringWithFormat ("attach failed: %s", exit_desc);
- else
- error.SetErrorString ("attach failed: process did not stop (no such process or permission problem?)");
- process_sp->Destroy (false);
+ process_sp->RestoreProcessEvents ();
+ }
+ else
+ {
+ state = process_sp->WaitForProcessToStop (nullptr, nullptr, false, attach_info.GetHijackListener ().get (), stream);
+ process_sp->RestoreProcessEvents ();
+
+ if (state != eStateStopped)
+ {
+ const char *exit_desc = process_sp->GetExitDescription ();
+ if (exit_desc)
+ error.SetErrorStringWithFormat ("%s", exit_desc);
+ else
+ error.SetErrorString ("process did not stop (no such process or permission problem?)");
+ process_sp->Destroy (false);
+ }
}
}
return error;
@@ -2802,14 +3245,11 @@ Target::StopHook::StopHook (const StopHook &rhs) :
m_thread_spec_ap (),
m_active (rhs.m_active)
{
- if (rhs.m_thread_spec_ap.get() != NULL)
+ if (rhs.m_thread_spec_ap)
m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get()));
}
-
-Target::StopHook::~StopHook ()
-{
-}
+Target::StopHook::~StopHook() = default;
void
Target::StopHook::SetSpecifier(SymbolContextSpecifier *specifier)
@@ -2822,7 +3262,6 @@ Target::StopHook::SetThreadSpecifier (ThreadSpec *specifier)
{
m_thread_spec_ap.reset (specifier);
}
-
void
Target::StopHook::GetDescription (Stream *s, lldb::DescriptionLevel level) const
@@ -2846,7 +3285,7 @@ Target::StopHook::GetDescription (Stream *s, lldb::DescriptionLevel level) const
s->SetIndentLevel (indent_level + 2);
}
- if (m_thread_spec_ap.get() != NULL)
+ if (m_thread_spec_ap)
{
StreamString tmp;
s->Indent("Thread:\n");
@@ -2878,7 +3317,7 @@ lldb_private::g_dynamic_value_types[] =
{ eNoDynamicValues, "no-dynamic-values", "Don't calculate the dynamic type of values"},
{ eDynamicCanRunTarget, "run-target", "Calculate the dynamic type of values even if you have to run the target."},
{ eDynamicDontRunTarget, "no-run-target", "Calculate the dynamic type of values, but don't run the target."},
- { 0, NULL, NULL }
+ { 0, nullptr, nullptr }
};
static OptionEnumValueElement
@@ -2887,7 +3326,7 @@ g_inline_breakpoint_enums[] =
{ eInlineBreakpointsNever, "never", "Never look for inline breakpoint locations (fastest). This setting should only be used if you know that no inlining occurs in your programs."},
{ eInlineBreakpointsHeaders, "headers", "Only check for inline breakpoint locations when setting breakpoints in header files, but not when setting breakpoint in implementation source files (default)."},
{ eInlineBreakpointsAlways, "always", "Always look for inline breakpoint locations when setting file and line breakpoints (slower but most accurate)."},
- { 0, NULL, NULL }
+ { 0, nullptr, nullptr }
};
typedef enum x86DisassemblyFlavor
@@ -2903,7 +3342,7 @@ g_x86_dis_flavor_value_types[] =
{ eX86DisFlavorDefault, "default", "Disassembler default (currently att)."},
{ eX86DisFlavorIntel, "intel", "Intel disassembler flavor."},
{ eX86DisFlavorATT, "att", "AT&T disassembler flavor."},
- { 0, NULL, NULL }
+ { 0, nullptr, nullptr }
};
static OptionEnumValueElement
@@ -2911,7 +3350,7 @@ g_hex_immediate_style_values[] =
{
{ Disassembler::eHexStyleC, "c", "C-style (0xffff)."},
{ Disassembler::eHexStyleAsm, "asm", "Asm-style (0ffffh)."},
- { 0, NULL, NULL }
+ { 0, nullptr, nullptr }
};
static OptionEnumValueElement
@@ -2920,52 +3359,52 @@ g_load_script_from_sym_file_values[] =
{ eLoadScriptFromSymFileTrue, "true", "Load debug scripts inside symbol files"},
{ eLoadScriptFromSymFileFalse, "false", "Do not load debug scripts inside symbol files."},
{ eLoadScriptFromSymFileWarn, "warn", "Warn about debug scripts inside symbol files but do not load them."},
- { 0, NULL, NULL }
+ { 0, nullptr, nullptr }
};
-
static OptionEnumValueElement
g_memory_module_load_level_values[] =
{
{ eMemoryModuleLoadLevelMinimal, "minimal" , "Load minimal information when loading modules from memory. Currently this setting loads sections only."},
{ eMemoryModuleLoadLevelPartial, "partial" , "Load partial information when loading modules from memory. Currently this setting loads sections and function bounds."},
{ eMemoryModuleLoadLevelComplete, "complete", "Load complete information when loading modules from memory. Currently this setting loads sections and all symbols."},
- { 0, NULL, NULL }
+ { 0, nullptr, nullptr }
};
static PropertyDefinition
g_properties[] =
{
- { "default-arch" , OptionValue::eTypeArch , true , 0 , NULL, NULL, "Default architecture to choose, when there's a choice." },
- { "move-to-nearest-code" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Move breakpoints to nearest code." },
- { "expr-prefix" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "Path to a file containing expressions to be prepended to all expressions." },
- { "prefer-dynamic-value" , OptionValue::eTypeEnum , false, eDynamicDontRunTarget , NULL, g_dynamic_value_types, "Should printed values be shown as their dynamic value." },
- { "enable-synthetic-value" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Should synthetic values be used by default whenever available." },
- { "skip-prologue" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Skip function prologues when setting breakpoints by name." },
- { "source-map" , OptionValue::eTypePathMap , false, 0 , NULL, NULL, "Source path remappings used to track the change of location between a source file when built, and "
+ { "default-arch" , OptionValue::eTypeArch , true , 0 , nullptr, nullptr, "Default architecture to choose, when there's a choice." },
+ { "move-to-nearest-code" , OptionValue::eTypeBoolean , false, true , nullptr, nullptr, "Move breakpoints to nearest code." },
+ { "language" , OptionValue::eTypeLanguage , false, eLanguageTypeUnknown , nullptr, nullptr, "The language to use when interpreting expressions entered in commands." },
+ { "expr-prefix" , OptionValue::eTypeFileSpec , false, 0 , nullptr, nullptr, "Path to a file containing expressions to be prepended to all expressions." },
+ { "prefer-dynamic-value" , OptionValue::eTypeEnum , false, eDynamicDontRunTarget , nullptr, g_dynamic_value_types, "Should printed values be shown as their dynamic value." },
+ { "enable-synthetic-value" , OptionValue::eTypeBoolean , false, true , nullptr, nullptr, "Should synthetic values be used by default whenever available." },
+ { "skip-prologue" , OptionValue::eTypeBoolean , false, true , nullptr, nullptr, "Skip function prologues when setting breakpoints by name." },
+ { "source-map" , OptionValue::eTypePathMap , false, 0 , nullptr, nullptr, "Source path remappings are used to track the change of location between a source file when built, and "
"where it exists on the current system. It consists of an array of duples, the first element of each duple is "
"some part (starting at the root) of the path to the file when it was built, "
"and the second is where the remainder of the original build hierarchy is rooted on the local system. "
"Each element of the array is checked in order and the first one that results in a match wins." },
- { "exec-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , NULL, NULL, "Executable search paths to use when locating executable files whose paths don't match the local file system." },
- { "debug-file-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , NULL, NULL, "List of directories to be searched when locating debug symbol files." },
- { "clang-module-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , NULL, NULL, "List of directories to be searched when locating modules for Clang." },
- { "auto-import-clang-modules" , OptionValue::eTypeBoolean , false, false , NULL, NULL, "Automatically load Clang modules referred to by the program." },
- { "max-children-count" , OptionValue::eTypeSInt64 , false, 256 , NULL, NULL, "Maximum number of children to expand in any level of depth." },
- { "max-string-summary-length" , OptionValue::eTypeSInt64 , false, 1024 , NULL, NULL, "Maximum number of characters to show when using %s in summary strings." },
- { "max-memory-read-size" , OptionValue::eTypeSInt64 , false, 1024 , NULL, NULL, "Maximum number of bytes that 'memory read' will fetch before --force must be specified." },
- { "breakpoints-use-platform-avoid-list", OptionValue::eTypeBoolean , false, true , NULL, NULL, "Consult the platform module avoid list when setting non-module specific breakpoints." },
- { "arg0" , OptionValue::eTypeString , false, 0 , NULL, NULL, "The first argument passed to the program in the argument array which can be different from the executable itself." },
- { "run-args" , OptionValue::eTypeArgs , false, 0 , NULL, NULL, "A list containing all the arguments to be passed to the executable when it is run. Note that this does NOT include the argv[0] which is in target.arg0." },
- { "env-vars" , OptionValue::eTypeDictionary, false, OptionValue::eTypeString , NULL, NULL, "A list of all the environment variables to be passed to the executable's environment, and their values." },
- { "inherit-env" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Inherit the environment from the process that is running LLDB." },
- { "input-path" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "The file/path to be used by the executable program for reading its standard input." },
- { "output-path" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "The file/path to be used by the executable program for writing its standard output." },
- { "error-path" , OptionValue::eTypeFileSpec , false, 0 , NULL, NULL, "The file/path to be used by the executable program for writing its standard error." },
- { "detach-on-error" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "debugserver will detach (rather than killing) a process if it loses connection with lldb." },
- { "disable-aslr" , OptionValue::eTypeBoolean , false, true , NULL, NULL, "Disable Address Space Layout Randomization (ASLR)" },
- { "disable-stdio" , OptionValue::eTypeBoolean , false, false , NULL, NULL, "Disable stdin/stdout for process (e.g. for a GUI application)" },
- { "inline-breakpoint-strategy" , OptionValue::eTypeEnum , false, eInlineBreakpointsAlways , NULL, g_inline_breakpoint_enums, "The strategy to use when settings breakpoints by file and line. "
+ { "exec-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , nullptr, nullptr, "Executable search paths to use when locating executable files whose paths don't match the local file system." },
+ { "debug-file-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , nullptr, nullptr, "List of directories to be searched when locating debug symbol files." },
+ { "clang-module-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , nullptr, nullptr, "List of directories to be searched when locating modules for Clang." },
+ { "auto-import-clang-modules" , OptionValue::eTypeBoolean , false, false , nullptr, nullptr, "Automatically load Clang modules referred to by the program." },
+ { "max-children-count" , OptionValue::eTypeSInt64 , false, 256 , nullptr, nullptr, "Maximum number of children to expand in any level of depth." },
+ { "max-string-summary-length" , OptionValue::eTypeSInt64 , false, 1024 , nullptr, nullptr, "Maximum number of characters to show when using %s in summary strings." },
+ { "max-memory-read-size" , OptionValue::eTypeSInt64 , false, 1024 , nullptr, nullptr, "Maximum number of bytes that 'memory read' will fetch before --force must be specified." },
+ { "breakpoints-use-platform-avoid-list", OptionValue::eTypeBoolean , false, true , nullptr, nullptr, "Consult the platform module avoid list when setting non-module specific breakpoints." },
+ { "arg0" , OptionValue::eTypeString , false, 0 , nullptr, nullptr, "The first argument passed to the program in the argument array which can be different from the executable itself." },
+ { "run-args" , OptionValue::eTypeArgs , false, 0 , nullptr, nullptr, "A list containing all the arguments to be passed to the executable when it is run. Note that this does NOT include the argv[0] which is in target.arg0." },
+ { "env-vars" , OptionValue::eTypeDictionary, false, OptionValue::eTypeString , nullptr, nullptr, "A list of all the environment variables to be passed to the executable's environment, and their values." },
+ { "inherit-env" , OptionValue::eTypeBoolean , false, true , nullptr, nullptr, "Inherit the environment from the process that is running LLDB." },
+ { "input-path" , OptionValue::eTypeFileSpec , false, 0 , nullptr, nullptr, "The file/path to be used by the executable program for reading its standard input." },
+ { "output-path" , OptionValue::eTypeFileSpec , false, 0 , nullptr, nullptr, "The file/path to be used by the executable program for writing its standard output." },
+ { "error-path" , OptionValue::eTypeFileSpec , false, 0 , nullptr, nullptr, "The file/path to be used by the executable program for writing its standard error." },
+ { "detach-on-error" , OptionValue::eTypeBoolean , false, true , nullptr, nullptr, "debugserver will detach (rather than killing) a process if it loses connection with lldb." },
+ { "disable-aslr" , OptionValue::eTypeBoolean , false, true , nullptr, nullptr, "Disable Address Space Layout Randomization (ASLR)" },
+ { "disable-stdio" , OptionValue::eTypeBoolean , false, false , nullptr, nullptr, "Disable stdin/stdout for process (e.g. for a GUI application)" },
+ { "inline-breakpoint-strategy" , OptionValue::eTypeEnum , false, eInlineBreakpointsAlways , nullptr, g_inline_breakpoint_enums, "The strategy to use when settings breakpoints by file and line. "
"Breakpoint locations can end up being inlined by the compiler, so that a compile unit 'a.c' might contain an inlined function from another source file. "
"Usually this is limited to breakpoint locations from inlined functions from header or other include files, or more accurately non-implementation source files. "
"Sometimes code might #include implementation files and cause inlined breakpoint locations in inlined implementation files. "
@@ -2974,28 +3413,29 @@ g_properties[] =
"This setting allows you to control exactly which strategy is used when setting "
"file and line breakpoints." },
// FIXME: This is the wrong way to do per-architecture settings, but we don't have a general per architecture settings system in place yet.
- { "x86-disassembly-flavor" , OptionValue::eTypeEnum , false, eX86DisFlavorDefault, NULL, g_x86_dis_flavor_value_types, "The default disassembly flavor to use for x86 or x86-64 targets." },
- { "use-hex-immediates" , OptionValue::eTypeBoolean , false, true, NULL, NULL, "Show immediates in disassembly as hexadecimal." },
- { "hex-immediate-style" , OptionValue::eTypeEnum , false, Disassembler::eHexStyleC, NULL, g_hex_immediate_style_values, "Which style to use for printing hexadecimal disassembly values." },
- { "use-fast-stepping" , OptionValue::eTypeBoolean , false, true, NULL, NULL, "Use a fast stepping algorithm based on running from branch to branch rather than instruction single-stepping." },
- { "load-script-from-symbol-file" , OptionValue::eTypeEnum , false, eLoadScriptFromSymFileWarn, NULL, g_load_script_from_sym_file_values, "Allow LLDB to load scripting resources embedded in symbol files when available." },
- { "memory-module-load-level" , OptionValue::eTypeEnum , false, eMemoryModuleLoadLevelComplete, NULL, g_memory_module_load_level_values,
+ { "x86-disassembly-flavor" , OptionValue::eTypeEnum , false, eX86DisFlavorDefault, nullptr, g_x86_dis_flavor_value_types, "The default disassembly flavor to use for x86 or x86-64 targets." },
+ { "use-hex-immediates" , OptionValue::eTypeBoolean , false, true, nullptr, nullptr, "Show immediates in disassembly as hexadecimal." },
+ { "hex-immediate-style" , OptionValue::eTypeEnum , false, Disassembler::eHexStyleC, nullptr, g_hex_immediate_style_values, "Which style to use for printing hexadecimal disassembly values." },
+ { "use-fast-stepping" , OptionValue::eTypeBoolean , false, true, nullptr, nullptr, "Use a fast stepping algorithm based on running from branch to branch rather than instruction single-stepping." },
+ { "load-script-from-symbol-file" , OptionValue::eTypeEnum , false, eLoadScriptFromSymFileWarn, nullptr, g_load_script_from_sym_file_values, "Allow LLDB to load scripting resources embedded in symbol files when available." },
+ { "memory-module-load-level" , OptionValue::eTypeEnum , false, eMemoryModuleLoadLevelComplete, nullptr, g_memory_module_load_level_values,
"Loading modules from memory can be slow as reading the symbol tables and other data can take a long time depending on your connection to the debug target. "
"This setting helps users control how much information gets loaded when loading modules from memory."
"'complete' is the default value for this setting which will load all sections and symbols by reading them from memory (slowest, most accurate). "
"'partial' will load sections and attempt to find function bounds without downloading the symbol table (faster, still accurate, missing symbol names). "
"'minimal' is the fastest setting and will load section data with no symbols, but should rarely be used as stack frames in these memory regions will be inaccurate and not provide any context (fastest). " },
- { "display-expression-in-crashlogs" , OptionValue::eTypeBoolean , false, false, NULL, NULL, "Expressions that crash will show up in crash logs if the host system supports executable specific crash log strings and this setting is set to true." },
- { "trap-handler-names" , OptionValue::eTypeArray , true, OptionValue::eTypeString, NULL, NULL, "A list of trap handler function names, e.g. a common Unix user process one is _sigtramp." },
- { "display-runtime-support-values" , OptionValue::eTypeBoolean , false, false, NULL, NULL, "If true, LLDB will show variables that are meant to support the operation of a language's runtime support." },
- { "non-stop-mode" , OptionValue::eTypeBoolean , false, 0, NULL, NULL, "Disable lock-step debugging, instead control threads independently." },
- { NULL , OptionValue::eTypeInvalid , false, 0 , NULL, NULL, NULL }
+ { "display-expression-in-crashlogs" , OptionValue::eTypeBoolean , false, false, nullptr, nullptr, "Expressions that crash will show up in crash logs if the host system supports executable specific crash log strings and this setting is set to true." },
+ { "trap-handler-names" , OptionValue::eTypeArray , true, OptionValue::eTypeString, nullptr, nullptr, "A list of trap handler function names, e.g. a common Unix user process one is _sigtramp." },
+ { "display-runtime-support-values" , OptionValue::eTypeBoolean , false, false, nullptr, nullptr, "If true, LLDB will show variables that are meant to support the operation of a language's runtime support." },
+ { "non-stop-mode" , OptionValue::eTypeBoolean , false, 0, nullptr, nullptr, "Disable lock-step debugging, instead control threads independently." },
+ { nullptr , OptionValue::eTypeInvalid , false, 0 , nullptr, nullptr, nullptr }
};
enum
{
ePropertyDefaultArch,
ePropertyMoveToNearestCode,
+ ePropertyLanguage,
ePropertyExprPrefix,
ePropertyPreferDynamic,
ePropertyEnableSynthetic,
@@ -3032,13 +3472,12 @@ enum
ePropertyNonStopModeEnabled
};
-
class TargetOptionValueProperties : public OptionValueProperties
{
public:
TargetOptionValueProperties (const ConstString &name) :
OptionValueProperties (name),
- m_target (NULL),
+ m_target(nullptr),
m_got_host_env (false)
{
}
@@ -3053,8 +3492,8 @@ public:
{
}
- virtual const Property *
- GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
+ const Property *
+ GetPropertyAtIndex(const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const override
{
// When getting the value for a key from the target options, we will always
// try and grab the setting from the current target if there is one. Else we just
@@ -3082,7 +3521,6 @@ public:
}
protected:
-
void
GetHostEnvironmentIfNeeded () const
{
@@ -3092,7 +3530,7 @@ protected:
{
m_got_host_env = true;
const uint32_t idx = ePropertyInheritEnv;
- if (GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0))
+ if (GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0))
{
PlatformSP platform_sp (m_target->GetPlatform());
if (platform_sp)
@@ -3100,7 +3538,7 @@ protected:
StringList env;
if (platform_sp->GetEnvironment(env))
{
- OptionValueDictionary *env_dict = GetPropertyAtIndexAsOptionValueDictionary (NULL, ePropertyEnvVars);
+ OptionValueDictionary *env_dict = GetPropertyAtIndexAsOptionValueDictionary(nullptr, ePropertyEnvVars);
if (env_dict)
{
const bool can_replace = false;
@@ -3113,7 +3551,7 @@ protected:
const char *equal_pos = ::strchr(env_entry, '=');
ConstString key;
// It is ok to have environment variables with no values
- const char *value = NULL;
+ const char *value = nullptr;
if (equal_pos)
{
key.SetCStringWithLength(env_entry, equal_pos - env_entry);
@@ -3162,15 +3600,15 @@ TargetProperties::TargetProperties (Target *target) :
m_collection_sp->SetValueChangedCallback(ePropertyDisableSTDIO, TargetProperties::DisableSTDIOValueChangedCallback, this);
// Update m_launch_info once it was created
- Arg0ValueChangedCallback(this, NULL);
- RunArgsValueChangedCallback(this, NULL);
- //EnvVarsValueChangedCallback(this, NULL); // FIXME: cause segfault in Target::GetPlatform()
- InputPathValueChangedCallback(this, NULL);
- OutputPathValueChangedCallback(this, NULL);
- ErrorPathValueChangedCallback(this, NULL);
- DetachOnErrorValueChangedCallback(this, NULL);
- DisableASLRValueChangedCallback(this, NULL);
- DisableSTDIOValueChangedCallback(this, NULL);
+ Arg0ValueChangedCallback(this, nullptr);
+ RunArgsValueChangedCallback(this, nullptr);
+ //EnvVarsValueChangedCallback(this, nullptr); // FIXME: cause segfault in Target::GetPlatform()
+ InputPathValueChangedCallback(this, nullptr);
+ OutputPathValueChangedCallback(this, nullptr);
+ ErrorPathValueChangedCallback(this, nullptr);
+ DetachOnErrorValueChangedCallback(this, nullptr);
+ DisableASLRValueChangedCallback(this, nullptr);
+ DisableSTDIOValueChangedCallback(this, nullptr);
}
else
{
@@ -3181,16 +3619,14 @@ TargetProperties::TargetProperties (Target *target) :
true,
Process::GetGlobalProperties()->GetValueProperties());
}
-
}
-TargetProperties::~TargetProperties ()
-{
-}
+TargetProperties::~TargetProperties() = default;
+
ArchSpec
TargetProperties::GetDefaultArchitecture () const
{
- OptionValueArch *value = m_collection_sp->GetPropertyAtIndexAsOptionValueArch (NULL, ePropertyDefaultArch);
+ OptionValueArch *value = m_collection_sp->GetPropertyAtIndexAsOptionValueArch(nullptr, ePropertyDefaultArch);
if (value)
return value->GetCurrentValue();
return ArchSpec();
@@ -3199,7 +3635,7 @@ TargetProperties::GetDefaultArchitecture () const
void
TargetProperties::SetDefaultArchitecture (const ArchSpec& arch)
{
- OptionValueArch *value = m_collection_sp->GetPropertyAtIndexAsOptionValueArch (NULL, ePropertyDefaultArch);
+ OptionValueArch *value = m_collection_sp->GetPropertyAtIndexAsOptionValueArch(nullptr, ePropertyDefaultArch);
if (value)
return value->SetCurrentValue(arch, true);
}
@@ -3208,64 +3644,63 @@ bool
TargetProperties::GetMoveToNearestCode() const
{
const uint32_t idx = ePropertyMoveToNearestCode;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
lldb::DynamicValueType
TargetProperties::GetPreferDynamicValue() const
{
const uint32_t idx = ePropertyPreferDynamic;
- return (lldb::DynamicValueType)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value);
+ return (lldb::DynamicValueType)m_collection_sp->GetPropertyAtIndexAsEnumeration(nullptr, idx, g_properties[idx].default_uint_value);
}
bool
TargetProperties::SetPreferDynamicValue (lldb::DynamicValueType d)
{
const uint32_t idx = ePropertyPreferDynamic;
- return m_collection_sp->SetPropertyAtIndexAsEnumeration(NULL, idx, d);
+ return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, d);
}
-
bool
TargetProperties::GetDisableASLR () const
{
const uint32_t idx = ePropertyDisableASLR;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
void
TargetProperties::SetDisableASLR (bool b)
{
const uint32_t idx = ePropertyDisableASLR;
- m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
bool
TargetProperties::GetDetachOnError () const
{
const uint32_t idx = ePropertyDetachOnError;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
void
TargetProperties::SetDetachOnError (bool b)
{
const uint32_t idx = ePropertyDetachOnError;
- m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
bool
TargetProperties::GetDisableSTDIO () const
{
const uint32_t idx = ePropertyDisableSTDIO;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
void
TargetProperties::SetDisableSTDIO (bool b)
{
const uint32_t idx = ePropertyDisableSTDIO;
- m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
const char *
@@ -3274,7 +3709,7 @@ TargetProperties::GetDisassemblyFlavor () const
const uint32_t idx = ePropertyDisassemblyFlavor;
const char *return_value;
- x86DisassemblyFlavor flavor_value = (x86DisassemblyFlavor) m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value);
+ x86DisassemblyFlavor flavor_value = (x86DisassemblyFlavor) m_collection_sp->GetPropertyAtIndexAsEnumeration(nullptr, idx, g_properties[idx].default_uint_value);
return_value = g_x86_dis_flavor_value_types[flavor_value].string_value;
return return_value;
}
@@ -3283,21 +3718,21 @@ InlineStrategy
TargetProperties::GetInlineStrategy () const
{
const uint32_t idx = ePropertyInlineStrategy;
- return (InlineStrategy)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value);
+ return (InlineStrategy)m_collection_sp->GetPropertyAtIndexAsEnumeration(nullptr, idx, g_properties[idx].default_uint_value);
}
const char *
TargetProperties::GetArg0 () const
{
const uint32_t idx = ePropertyArg0;
- return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, NULL);
+ return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, nullptr);
}
void
TargetProperties::SetArg0 (const char *arg)
{
const uint32_t idx = ePropertyArg0;
- m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, arg);
+ m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, arg);
m_launch_info.SetArg0(arg);
}
@@ -3305,14 +3740,14 @@ bool
TargetProperties::GetRunArguments (Args &args) const
{
const uint32_t idx = ePropertyRunArgs;
- return m_collection_sp->GetPropertyAtIndexAsArgs (NULL, idx, args);
+ return m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, idx, args);
}
void
TargetProperties::SetRunArguments (const Args &args)
{
const uint32_t idx = ePropertyRunArgs;
- m_collection_sp->SetPropertyAtIndexFromArgs (NULL, idx, args);
+ m_collection_sp->SetPropertyAtIndexFromArgs(nullptr, idx, args);
m_launch_info.GetArguments() = args;
}
@@ -3320,14 +3755,14 @@ size_t
TargetProperties::GetEnvironmentAsArgs (Args &env) const
{
const uint32_t idx = ePropertyEnvVars;
- return m_collection_sp->GetPropertyAtIndexAsArgs (NULL, idx, env);
+ return m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, idx, env);
}
void
TargetProperties::SetEnvironmentFromArgs (const Args &env)
{
const uint32_t idx = ePropertyEnvVars;
- m_collection_sp->SetPropertyAtIndexFromArgs (NULL, idx, env);
+ m_collection_sp->SetPropertyAtIndexFromArgs(nullptr, idx, env);
m_launch_info.GetEnvironmentEntries() = env;
}
@@ -3335,14 +3770,14 @@ bool
TargetProperties::GetSkipPrologue() const
{
const uint32_t idx = ePropertySkipPrologue;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
PathMappingList &
TargetProperties::GetSourcePathMap () const
{
const uint32_t idx = ePropertySourceMap;
- OptionValuePathMappings *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValuePathMappings (NULL, false, idx);
+ OptionValuePathMappings *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValuePathMappings(nullptr, false, idx);
assert(option_value);
return option_value->GetCurrentValue();
}
@@ -3351,7 +3786,7 @@ FileSpecList &
TargetProperties::GetExecutableSearchPaths ()
{
const uint32_t idx = ePropertyExecutableSearchPaths;
- OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx);
+ OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, false, idx);
assert(option_value);
return option_value->GetCurrentValue();
}
@@ -3360,7 +3795,7 @@ FileSpecList &
TargetProperties::GetDebugFileSearchPaths ()
{
const uint32_t idx = ePropertyDebugFileSearchPaths;
- OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx);
+ OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, false, idx);
assert(option_value);
return option_value->GetCurrentValue();
}
@@ -3369,7 +3804,7 @@ FileSpecList &
TargetProperties::GetClangModuleSearchPaths ()
{
const uint32_t idx = ePropertyClangModuleSearchPaths;
- OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx);
+ OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, false, idx);
assert(option_value);
return option_value->GetCurrentValue();
}
@@ -3378,77 +3813,86 @@ bool
TargetProperties::GetEnableAutoImportClangModules() const
{
const uint32_t idx = ePropertyAutoImportClangModules;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
bool
TargetProperties::GetEnableSyntheticValue () const
{
const uint32_t idx = ePropertyEnableSynthetic;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
uint32_t
TargetProperties::GetMaximumNumberOfChildrenToDisplay() const
{
const uint32_t idx = ePropertyMaxChildrenCount;
- return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value);
+ return m_collection_sp->GetPropertyAtIndexAsSInt64(nullptr, idx, g_properties[idx].default_uint_value);
}
uint32_t
TargetProperties::GetMaximumSizeOfStringSummary() const
{
const uint32_t idx = ePropertyMaxSummaryLength;
- return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value);
+ return m_collection_sp->GetPropertyAtIndexAsSInt64(nullptr, idx, g_properties[idx].default_uint_value);
}
uint32_t
TargetProperties::GetMaximumMemReadSize () const
{
const uint32_t idx = ePropertyMaxMemReadSize;
- return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value);
+ return m_collection_sp->GetPropertyAtIndexAsSInt64(nullptr, idx, g_properties[idx].default_uint_value);
}
FileSpec
TargetProperties::GetStandardInputPath () const
{
const uint32_t idx = ePropertyInputPath;
- return m_collection_sp->GetPropertyAtIndexAsFileSpec (NULL, idx);
+ return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx);
}
void
TargetProperties::SetStandardInputPath (const char *p)
{
const uint32_t idx = ePropertyInputPath;
- m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, p);
+ m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
}
FileSpec
TargetProperties::GetStandardOutputPath () const
{
const uint32_t idx = ePropertyOutputPath;
- return m_collection_sp->GetPropertyAtIndexAsFileSpec (NULL, idx);
+ return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx);
}
void
TargetProperties::SetStandardOutputPath (const char *p)
{
const uint32_t idx = ePropertyOutputPath;
- m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, p);
+ m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
}
FileSpec
TargetProperties::GetStandardErrorPath () const
{
const uint32_t idx = ePropertyErrorPath;
- return m_collection_sp->GetPropertyAtIndexAsFileSpec(NULL, idx);
+ return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx);
+}
+
+LanguageType
+TargetProperties::GetLanguage () const
+{
+ OptionValueLanguage *value = m_collection_sp->GetPropertyAtIndexAsOptionValueLanguage(nullptr, ePropertyLanguage);
+ if (value)
+ return value->GetCurrentValue();
+ return LanguageType();
}
const char *
TargetProperties::GetExpressionPrefixContentsAsCString ()
{
const uint32_t idx = ePropertyExprPrefix;
- OptionValueFileSpec *file = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpec (NULL, false, idx);
+ OptionValueFileSpec *file = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpec(nullptr, false, idx);
if (file)
{
const bool null_terminate = true;
@@ -3456,105 +3900,105 @@ TargetProperties::GetExpressionPrefixContentsAsCString ()
if (data_sp)
return (const char *) data_sp->GetBytes();
}
- return NULL;
+ return nullptr;
}
void
TargetProperties::SetStandardErrorPath (const char *p)
{
const uint32_t idx = ePropertyErrorPath;
- m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, p);
+ m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
}
bool
TargetProperties::GetBreakpointsConsultPlatformAvoidList ()
{
const uint32_t idx = ePropertyBreakpointUseAvoidList;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
bool
TargetProperties::GetUseHexImmediates () const
{
const uint32_t idx = ePropertyUseHexImmediates;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
bool
TargetProperties::GetUseFastStepping () const
{
const uint32_t idx = ePropertyUseFastStepping;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
bool
TargetProperties::GetDisplayExpressionsInCrashlogs () const
{
const uint32_t idx = ePropertyDisplayExpressionsInCrashlogs;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
LoadScriptFromSymFile
TargetProperties::GetLoadScriptFromSymbolFile () const
{
const uint32_t idx = ePropertyLoadScriptFromSymbolFile;
- return (LoadScriptFromSymFile)m_collection_sp->GetPropertyAtIndexAsEnumeration(NULL, idx, g_properties[idx].default_uint_value);
+ return (LoadScriptFromSymFile)m_collection_sp->GetPropertyAtIndexAsEnumeration(nullptr, idx, g_properties[idx].default_uint_value);
}
Disassembler::HexImmediateStyle
TargetProperties::GetHexImmediateStyle () const
{
const uint32_t idx = ePropertyHexImmediateStyle;
- return (Disassembler::HexImmediateStyle)m_collection_sp->GetPropertyAtIndexAsEnumeration(NULL, idx, g_properties[idx].default_uint_value);
+ return (Disassembler::HexImmediateStyle)m_collection_sp->GetPropertyAtIndexAsEnumeration(nullptr, idx, g_properties[idx].default_uint_value);
}
MemoryModuleLoadLevel
TargetProperties::GetMemoryModuleLoadLevel() const
{
const uint32_t idx = ePropertyMemoryModuleLoadLevel;
- return (MemoryModuleLoadLevel)m_collection_sp->GetPropertyAtIndexAsEnumeration(NULL, idx, g_properties[idx].default_uint_value);
+ return (MemoryModuleLoadLevel)m_collection_sp->GetPropertyAtIndexAsEnumeration(nullptr, idx, g_properties[idx].default_uint_value);
}
bool
TargetProperties::GetUserSpecifiedTrapHandlerNames (Args &args) const
{
const uint32_t idx = ePropertyTrapHandlerNames;
- return m_collection_sp->GetPropertyAtIndexAsArgs (NULL, idx, args);
+ return m_collection_sp->GetPropertyAtIndexAsArgs(nullptr, idx, args);
}
void
TargetProperties::SetUserSpecifiedTrapHandlerNames (const Args &args)
{
const uint32_t idx = ePropertyTrapHandlerNames;
- m_collection_sp->SetPropertyAtIndexFromArgs (NULL, idx, args);
+ m_collection_sp->SetPropertyAtIndexFromArgs(nullptr, idx, args);
}
bool
TargetProperties::GetDisplayRuntimeSupportValues () const
{
const uint32_t idx = ePropertyDisplayRuntimeSupportValues;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, false);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, false);
}
void
TargetProperties::SetDisplayRuntimeSupportValues (bool b)
{
const uint32_t idx = ePropertyDisplayRuntimeSupportValues;
- m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
bool
TargetProperties::GetNonStopModeEnabled () const
{
const uint32_t idx = ePropertyNonStopModeEnabled;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, false);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, false);
}
void
TargetProperties::SetNonStopModeEnabled (bool b)
{
const uint32_t idx = ePropertyNonStopModeEnabled;
- m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
const ProcessLaunchInfo &
@@ -3691,9 +4135,7 @@ Target::TargetEventData::TargetEventData (const lldb::TargetSP &target_sp, const
{
}
-Target::TargetEventData::~TargetEventData()
-{
-}
+Target::TargetEventData::~TargetEventData() = default;
const ConstString &
Target::TargetEventData::GetFlavorString ()
@@ -3716,7 +4158,7 @@ Target::TargetEventData::GetEventDataFromEvent (const Event *event_ptr)
if (event_data && event_data->GetFlavor() == TargetEventData::GetFlavorString())
return static_cast <const TargetEventData *> (event_ptr->GetData());
}
- return NULL;
+ return nullptr;
}
TargetSP
diff --git a/contrib/llvm/tools/lldb/source/Target/TargetList.cpp b/contrib/llvm/tools/lldb/source/Target/TargetList.cpp
index 552e951..ffec758 100644
--- a/contrib/llvm/tools/lldb/source/Target/TargetList.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/TargetList.cpp
@@ -10,6 +10,8 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
+#include "llvm/ADT/SmallString.h"
+
// Project includes
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Debugger.h"
@@ -27,8 +29,6 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"
-#include "llvm/ADT/SmallString.h"
-
using namespace lldb;
using namespace lldb_private;
@@ -179,9 +179,14 @@ TargetList::CreateTargetInternal (Debugger &debugger,
}
else
{
+ StreamString platform_arch_strm;
+ StreamString module_arch_strm;
+
+ platform_arch.DumpTriple(platform_arch_strm);
+ matching_module_spec.GetArchitecture().DumpTriple(module_arch_strm);
error.SetErrorStringWithFormat("the specified architecture '%s' is not compatible with '%s' in '%s'",
- platform_arch.GetTriple().str().c_str(),
- matching_module_spec.GetArchitecture().GetTriple().str().c_str(),
+ platform_arch_strm.GetString().c_str(),
+ module_arch_strm.GetString().c_str(),
module_spec.GetFileSpec().GetPath().c_str());
return error;
}
@@ -222,7 +227,7 @@ TargetList::CreateTargetInternal (Debugger &debugger,
// since the user may have specified it.
if (platform_sp)
{
- if (platform_sp->IsCompatibleArchitecture(module_spec.GetArchitecture(), false, NULL))
+ if (platform_sp->IsCompatibleArchitecture(module_spec.GetArchitecture(), false, nullptr))
{
platforms.push_back(platform_sp);
continue;
@@ -232,7 +237,7 @@ TargetList::CreateTargetInternal (Debugger &debugger,
// Next check the host platform it if wasn't already checked above
if (host_platform_sp && (!platform_sp || host_platform_sp->GetName() != platform_sp->GetName()))
{
- if (host_platform_sp->IsCompatibleArchitecture(module_spec.GetArchitecture(), false, NULL))
+ if (host_platform_sp->IsCompatibleArchitecture(module_spec.GetArchitecture(), false, nullptr))
{
platforms.push_back(host_platform_sp);
continue;
@@ -240,18 +245,24 @@ TargetList::CreateTargetInternal (Debugger &debugger,
}
// Just find a platform that matches the architecture in the executable file
- platforms.push_back(Platform::GetPlatformForArchitecture(module_spec.GetArchitecture(), nullptr));
+ PlatformSP fallback_platform_sp (Platform::GetPlatformForArchitecture(module_spec.GetArchitecture(), nullptr));
+ if (fallback_platform_sp)
+ {
+ platforms.push_back(fallback_platform_sp);
+ }
}
}
- Platform *platform_ptr = NULL;
+ Platform *platform_ptr = nullptr;
+ bool more_than_one_platforms = false;
for (const auto &the_platform_sp : platforms)
{
if (platform_ptr)
{
if (platform_ptr->GetName() != the_platform_sp->GetName())
{
- platform_ptr = NULL;
+ more_than_one_platforms = true;
+ platform_ptr = nullptr;
break;
}
}
@@ -266,6 +277,12 @@ TargetList::CreateTargetInternal (Debugger &debugger,
// All platforms for all modules in the exectuable match, so we can select this platform
platform_sp = platforms.front();
}
+ else if (more_than_one_platforms == false)
+ {
+ // No platforms claim to support this file
+ error.SetErrorString ("No matching platforms found for this file, specify one with the --platform option");
+ return error;
+ }
else
{
// More than one platform claims to support this file, so the --platform option must be specified
@@ -369,7 +386,6 @@ TargetList::CreateTargetInternal (Debugger &debugger,
lldb::TargetSP &target_sp,
bool is_dummy_target)
{
-
Timer scoped_timer (__PRETTY_FUNCTION__,
"TargetList::CreateTarget (file = '%s', arch = '%s')",
user_exe_path,
@@ -380,7 +396,7 @@ TargetList::CreateTargetInternal (Debugger &debugger,
if (arch.IsValid())
{
- if (!platform_sp || !platform_sp->IsCompatibleArchitecture(arch, false, NULL))
+ if (!platform_sp || !platform_sp->IsCompatibleArchitecture(arch, false, nullptr))
platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
}
@@ -436,14 +452,14 @@ TargetList::CreateTargetInternal (Debugger &debugger,
{
FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
ModuleSpec module_spec(file, arch);
- error = platform_sp->ResolveExecutable (module_spec,
- exe_module_sp,
- executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+ error = platform_sp->ResolveExecutable(module_spec,
+ exe_module_sp,
+ executable_search_paths.GetSize() ? &executable_search_paths : nullptr);
}
if (error.Success() && exe_module_sp)
{
- if (exe_module_sp->GetObjectFile() == NULL)
+ if (exe_module_sp->GetObjectFile() == nullptr)
{
if (arch.IsValid())
{
@@ -531,13 +547,9 @@ TargetList::DeleteTarget (TargetSP &target_sp)
return false;
}
-
TargetSP
-TargetList::FindTargetWithExecutableAndArchitecture
-(
- const FileSpec &exe_file_spec,
- const ArchSpec *exe_arch_ptr
-) const
+TargetList::FindTargetWithExecutableAndArchitecture(const FileSpec &exe_file_spec,
+ const ArchSpec *exe_arch_ptr) const
{
Mutex::Locker locker (m_target_list_mutex);
TargetSP target_sp;
@@ -583,7 +595,6 @@ TargetList::FindTargetWithProcessID (lldb::pid_t pid) const
return target_sp;
}
-
TargetSP
TargetList::FindTargetWithProcess (Process *process) const
{
@@ -632,7 +643,7 @@ TargetList::SendAsyncInterrupt (lldb::pid_t pid)
if (pid != LLDB_INVALID_PROCESS_ID)
{
TargetSP target_sp(FindTargetWithProcessID (pid));
- if (target_sp.get())
+ if (target_sp)
{
Process* process = target_sp->GetProcessSP().get();
if (process)
@@ -646,7 +657,7 @@ TargetList::SendAsyncInterrupt (lldb::pid_t pid)
{
// We don't have a valid pid to broadcast to, so broadcast to the target
// list's async broadcaster...
- BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
+ BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr);
}
return num_async_interrupts_sent;
@@ -656,7 +667,7 @@ uint32_t
TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
{
uint32_t num_signals_sent = 0;
- Process *process = NULL;
+ Process *process = nullptr;
if (pid == LLDB_INVALID_PROCESS_ID)
{
// Signal all processes with signal
@@ -679,7 +690,7 @@ TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
{
// Signal a specific process with signal
TargetSP target_sp(FindTargetWithProcessID (pid));
- if (target_sp.get())
+ if (target_sp)
{
process = target_sp->GetProcessSP().get();
if (process)
diff --git a/contrib/llvm/tools/lldb/source/Target/Thread.cpp b/contrib/llvm/tools/lldb/source/Target/Thread.cpp
index 29ba86a..551e480 100644
--- a/contrib/llvm/tools/lldb/source/Target/Thread.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/Thread.cpp
@@ -7,14 +7,20 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/FormatEntity.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/ValueObject.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueProperties.h"
@@ -23,7 +29,6 @@
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
@@ -47,11 +52,9 @@
#include "Plugins/Process/Utility/UnwindLLDB.h"
#include "Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h"
-
using namespace lldb;
using namespace lldb_private;
-
const ThreadPropertiesSP &
Thread::GetGlobalProperties()
{
@@ -64,13 +67,13 @@ Thread::GetGlobalProperties()
static PropertyDefinition
g_properties[] =
{
- { "step-in-avoid-nodebug", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, step-in will not stop in functions with no debug information." },
- { "step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, when step-in/step-out/step-over leave the current frame, they will continue to step out till they come to a function with "
+ { "step-in-avoid-nodebug", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, step-in will not stop in functions with no debug information." },
+ { "step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, when step-in/step-out/step-over leave the current frame, they will continue to step out till they come to a function with "
"debug information. Passing a frame argument to step-out will override this option." },
- { "step-avoid-regexp", OptionValue::eTypeRegex , true , 0, "^std::", NULL, "A regular expression defining functions step-in won't stop in." },
- { "step-avoid-libraries", OptionValue::eTypeFileSpecList , true , 0, NULL, NULL, "A list of libraries that source stepping won't stop in." },
- { "trace-thread", OptionValue::eTypeBoolean, false, false, NULL, NULL, "If true, this thread will single-step and log execution." },
- { NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL }
+ { "step-avoid-regexp", OptionValue::eTypeRegex , true , 0, "^std::", nullptr, "A regular expression defining functions step-in won't stop in." },
+ { "step-avoid-libraries", OptionValue::eTypeFileSpecList , true , 0, nullptr, nullptr, "A list of libraries that source stepping won't stop in." },
+ { "trace-thread", OptionValue::eTypeBoolean, false, false, nullptr, nullptr, "If true, this thread will single-step and log execution." },
+ { nullptr , OptionValue::eTypeInvalid, false, 0 , nullptr, nullptr, nullptr }
};
enum {
@@ -81,7 +84,6 @@ enum {
ePropertyEnableThreadTrace
};
-
class ThreadOptionValueProperties : public OptionValueProperties
{
public:
@@ -98,8 +100,8 @@ public:
{
}
- virtual const Property *
- GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
+ const Property *
+ GetPropertyAtIndex(const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const override
{
// When getting the value for a key from the thread options, we will always
// try and grab the setting from the current thread if there is one. Else we just
@@ -118,8 +120,6 @@ public:
}
};
-
-
ThreadProperties::ThreadProperties (bool is_global) :
Properties ()
{
@@ -132,22 +132,20 @@ ThreadProperties::ThreadProperties (bool is_global) :
m_collection_sp.reset (new ThreadOptionValueProperties(Thread::GetGlobalProperties().get()));
}
-ThreadProperties::~ThreadProperties()
-{
-}
+ThreadProperties::~ThreadProperties() = default;
const RegularExpression *
ThreadProperties::GetSymbolsToAvoidRegexp()
{
const uint32_t idx = ePropertyStepAvoidRegex;
- return m_collection_sp->GetPropertyAtIndexAsOptionValueRegex (NULL, idx);
+ return m_collection_sp->GetPropertyAtIndexAsOptionValueRegex(nullptr, idx);
}
FileSpecList &
ThreadProperties::GetLibrariesToAvoid() const
{
const uint32_t idx = ePropertyStepAvoidLibraries;
- OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx);
+ OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, false, idx);
assert(option_value);
return option_value->GetCurrentValue();
}
@@ -156,29 +154,27 @@ bool
ThreadProperties::GetTraceEnabledState() const
{
const uint32_t idx = ePropertyEnableThreadTrace;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
bool
ThreadProperties::GetStepInAvoidsNoDebug() const
{
const uint32_t idx = ePropertyStepInAvoidsNoDebug;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
bool
ThreadProperties::GetStepOutAvoidsNoDebug() const
{
const uint32_t idx = ePropertyStepOutAvoidsNoDebug;
- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0);
}
-
//------------------------------------------------------------------
// Thread Event Data
//------------------------------------------------------------------
-
const ConstString &
Thread::ThreadEventData::GetFlavorString ()
{
@@ -204,14 +200,11 @@ Thread::ThreadEventData::ThreadEventData () :
{
}
-Thread::ThreadEventData::~ThreadEventData ()
-{
-}
+Thread::ThreadEventData::~ThreadEventData() = default;
void
Thread::ThreadEventData::Dump (Stream *s) const
{
-
}
const Thread::ThreadEventData *
@@ -223,7 +216,7 @@ Thread::ThreadEventData::GetEventDataFromEvent (const Event *event_ptr)
if (event_data && event_data->GetFlavor() == ThreadEventData::GetFlavorString())
return static_cast <const ThreadEventData *> (event_ptr->GetData());
}
- return NULL;
+ return nullptr;
}
ThreadSP
@@ -308,7 +301,6 @@ Thread::Thread (Process &process, lldb::tid_t tid, bool use_invalid_index_id) :
QueueFundamentalPlan(true);
}
-
Thread::~Thread()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
@@ -360,12 +352,22 @@ Thread::BroadcastSelectedFrameChange(StackID &new_frame_id)
BroadcastEvent(eBroadcastBitSelectedFrameChanged, new ThreadEventData (this->shared_from_this(), new_frame_id));
}
+lldb::StackFrameSP
+Thread::GetSelectedFrame()
+{
+ StackFrameListSP stack_frame_list_sp(GetStackFrameList());
+ StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex (stack_frame_list_sp->GetSelectedFrameIndex());
+ FunctionOptimizationWarning (frame_sp.get());
+ return frame_sp;
+}
+
uint32_t
Thread::SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast)
{
uint32_t ret_value = GetStackFrameList()->SetSelectedFrame(frame);
if (broadcast)
BroadcastSelectedFrameChange(frame->GetStackID());
+ FunctionOptimizationWarning (frame);
return ret_value;
}
@@ -378,6 +380,7 @@ Thread::SetSelectedFrameByIndex (uint32_t frame_idx, bool broadcast)
GetStackFrameList()->SetSelectedFrame(frame_sp.get());
if (broadcast)
BroadcastSelectedFrameChange(frame_sp->GetStackID());
+ FunctionOptimizationWarning (frame_sp.get());
return true;
}
else
@@ -403,6 +406,7 @@ Thread::SetSelectedFrameByIndexNoisily (uint32_t frame_idx, Stream &output_strea
bool show_frame_info = true;
bool show_source = !already_shown;
+ FunctionOptimizationWarning (frame_sp.get());
return frame_sp->GetStatus (output_stream, show_frame_info, show_source);
}
return false;
@@ -411,6 +415,15 @@ Thread::SetSelectedFrameByIndexNoisily (uint32_t frame_idx, Stream &output_strea
return false;
}
+void
+Thread::FunctionOptimizationWarning (StackFrame *frame)
+{
+ if (frame && frame->HasDebugInformation() && GetProcess()->GetWarningsOptimization())
+ {
+ SymbolContext sc = frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextModule);
+ GetProcess()->PrintWarningOptimization (sc);
+ }
+}
lldb::StopInfoSP
Thread::GetStopInfo ()
@@ -464,7 +477,7 @@ Thread::GetPrivateStopInfo ()
if (!m_stop_info_sp)
{
- if (CalculateStopInfo() == false)
+ if (!CalculateStopInfo())
SetStopInfo (StopInfoSP());
}
}
@@ -490,7 +503,6 @@ Thread::GetPrivateStopInfo ()
return m_stop_info_sp;
}
-
lldb::StopReason
Thread::GetStopReason()
{
@@ -500,7 +512,15 @@ Thread::GetStopReason()
return eStopReasonNone;
}
-
+bool
+Thread::StopInfoIsUpToDate() const
+{
+ ProcessSP process_sp (GetProcess());
+ if (process_sp)
+ return m_stop_info_stop_id == process_sp->GetStopID();
+ else
+ return true; // Process is no longer around so stop info is always up to date...
+}
void
Thread::SetStopInfo (const lldb::StopInfoSP &stop_info_sp)
@@ -650,7 +670,6 @@ Thread::SetupForResume ()
{
if (GetResumeState() != eStateSuspended)
{
-
// If we're at a breakpoint push the step-over breakpoint plan. Do this before
// telling the current plan it will resume, since we might change what the current
// plan is.
@@ -707,14 +726,17 @@ Thread::ShouldResume (StateType resume_state)
m_discarded_plan_stack.clear();
m_override_should_notify = eLazyBoolCalculate;
- m_temporary_resume_state = resume_state;
+ StateType prev_resume_state = GetTemporaryResumeState();
+
+ SetTemporaryResumeState(resume_state);
lldb::ThreadSP backing_thread_sp (GetBackingThread ());
if (backing_thread_sp)
- backing_thread_sp->m_temporary_resume_state = resume_state;
+ backing_thread_sp->SetTemporaryResumeState(resume_state);
- // Make sure m_stop_info_sp is valid
- GetPrivateStopInfo();
+ // Make sure m_stop_info_sp is valid. Don't do this for threads we suspended in the previous run.
+ if (prev_resume_state != eStateSuspended)
+ GetPrivateStopInfo();
// This is a little dubious, but we are trying to limit how often we actually fetch stop info from
// the target, 'cause that slows down single stepping. So assume that if we got to the point where
@@ -739,7 +761,7 @@ Thread::ShouldResume (StateType resume_state)
{
need_to_resume = plan_ptr->WillResume(resume_state, true);
- while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
+ while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr)
{
plan_ptr->WillResume (resume_state, false);
}
@@ -804,7 +826,7 @@ Thread::ShouldStop (Event* event_ptr)
// thread caused the process to stop. NOTE: this must take place before
// the plan is moved from the current plan stack to the completed plan
// stack.
- if (ThreadStoppedForAReason() == false)
+ if (!ThreadStoppedForAReason())
{
if (log)
log->Printf ("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64 ", pc = 0x%16.16" PRIx64 ", should_stop = 0 (ignore since no stop reason)",
@@ -835,7 +857,7 @@ Thread::ShouldStop (Event* event_ptr)
// command on internal breakpoints. If a synchronous stop reason says we should not stop, then we don't have to
// do any more work on this stop.
StopInfoSP private_stop_info (GetPrivateStopInfo());
- if (private_stop_info && private_stop_info->ShouldStopSynchronous(event_ptr) == false)
+ if (private_stop_info && !private_stop_info->ShouldStopSynchronous(event_ptr))
{
if (log)
log->Printf ("StopInfo::ShouldStop async callback says we should not stop, returning ShouldStop of false.");
@@ -868,7 +890,7 @@ Thread::ShouldStop (Event* event_ptr)
// If the current plan doesn't explain the stop, then find one that
// does and let it handle the situation.
ThreadPlan *plan_ptr = current_plan;
- while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL)
+ while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr)
{
if (plan_ptr->PlanExplainsStop(event_ptr))
{
@@ -891,17 +913,13 @@ Thread::ShouldStop (Event* event_ptr)
while ((current_plan = GetCurrentPlan()) != prev_plan_ptr);
// Now, if the responsible plan was not "Okay to discard" then we're done,
// otherwise we forward this to the next plan in the stack below.
- if (plan_ptr->IsMasterPlan() && !plan_ptr->OkayToDiscard())
- done_processing_current_plan = true;
- else
- done_processing_current_plan = false;
+ done_processing_current_plan = (plan_ptr->IsMasterPlan() && !plan_ptr->OkayToDiscard());
}
else
done_processing_current_plan = true;
break;
}
-
}
}
}
@@ -949,11 +967,10 @@ Thread::ShouldStop (Event* event_ptr)
}
else
{
-
PopPlan();
current_plan = GetCurrentPlan();
- if (current_plan == NULL)
+ if (current_plan == nullptr)
{
break;
}
@@ -968,7 +985,6 @@ Thread::ShouldStop (Event* event_ptr)
if (over_ride_stop)
should_stop = false;
-
}
// One other potential problem is that we set up a master plan, then stop in before it is complete - for instance
@@ -1103,10 +1119,7 @@ Thread::ShouldReportRun (Event* event_ptr)
bool
Thread::MatchesSpec (const ThreadSpec *spec)
{
- if (spec == NULL)
- return true;
-
- return spec->ThreadPassesBasicTests(*this);
+ return (spec == nullptr) ? true : spec->ThreadPassesBasicTests(*this);
}
void
@@ -1174,9 +1187,7 @@ Thread::GetCurrentPlan ()
{
// There will always be at least the base plan. If somebody is mucking with a
// thread with an empty plan stack, we should assert right away.
- if (m_plan_stack.empty())
- return NULL;
- return m_plan_stack.back().get();
+ return m_plan_stack.empty() ? nullptr : m_plan_stack.back().get();
}
ThreadPlanSP
@@ -1212,20 +1223,20 @@ Thread::GetReturnValueObject ()
return ValueObjectSP();
}
-ClangExpressionVariableSP
+ExpressionVariableSP
Thread::GetExpressionVariable ()
{
if (!m_completed_plan_stack.empty())
{
for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
{
- ClangExpressionVariableSP expression_variable_sp;
+ ExpressionVariableSP expression_variable_sp;
expression_variable_sp = m_completed_plan_stack[i]->GetExpressionVariable();
if (expression_variable_sp)
return expression_variable_sp;
}
}
- return ClangExpressionVariableSP();
+ return ExpressionVariableSP();
}
bool
@@ -1259,8 +1270,8 @@ Thread::WasThreadPlanDiscarded (ThreadPlan *plan)
ThreadPlan *
Thread::GetPreviousPlan (ThreadPlan *current_plan)
{
- if (current_plan == NULL)
- return NULL;
+ if (current_plan == nullptr)
+ return nullptr;
int stack_size = m_completed_plan_stack.size();
for (int i = stack_size - 1; i > 0; i--)
@@ -1271,10 +1282,7 @@ Thread::GetPreviousPlan (ThreadPlan *current_plan)
if (stack_size > 0 && m_completed_plan_stack[0].get() == current_plan)
{
- if (m_plan_stack.size() > 0)
- return m_plan_stack.back().get();
- else
- return NULL;
+ return GetCurrentPlan();
}
stack_size = m_plan_stack.size();
@@ -1283,7 +1291,7 @@ Thread::GetPreviousPlan (ThreadPlan *current_plan)
if (current_plan == m_plan_stack[i].get())
return m_plan_stack[i-1].get();
}
- return NULL;
+ return nullptr;
}
void
@@ -1295,7 +1303,6 @@ Thread::QueueThreadPlan (ThreadPlanSP &thread_plan_sp, bool abort_other_plans)
PushPlan (thread_plan_sp);
}
-
void
Thread::EnableTracer (bool value, bool single_stepping)
{
@@ -1346,7 +1353,6 @@ Thread::DiscardUserThreadPlansUpToIndex (uint32_t thread_index)
DiscardThreadPlansUpToPlan(up_to_plan_ptr);
return true;
}
-
void
Thread::DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp)
@@ -1364,10 +1370,10 @@ Thread::DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr)
int stack_size = m_plan_stack.size();
- // If the input plan is NULL, discard all plans. Otherwise make sure this plan is in the
+ // If the input plan is nullptr, discard all plans. Otherwise make sure this plan is in the
// stack, and if so discard up to and including it.
- if (up_to_plan_ptr == NULL)
+ if (up_to_plan_ptr == nullptr)
{
for (int i = stack_size - 1; i > 0; i--)
DiscardPlan();
@@ -1391,7 +1397,6 @@ Thread::DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr)
}
}
}
- return;
}
void
@@ -1415,7 +1420,6 @@ Thread::DiscardThreadPlans(bool force)
while (1)
{
-
int master_plan_idx;
bool discard = true;
@@ -1434,7 +1438,6 @@ Thread::DiscardThreadPlans(bool force)
// First pop all the dependent plans:
for (int i = m_plan_stack.size() - 1; i > master_plan_idx; i--)
{
-
// FIXME: Do we need a finalize here, or is the rule that "PrepareForStop"
// for the plan leaves it in a state that it is safe to pop the plan
// with no more notice?
@@ -1454,7 +1457,6 @@ Thread::DiscardThreadPlans(bool force)
// If the master plan doesn't want to get discarded, then we're done.
break;
}
-
}
}
@@ -1475,7 +1477,7 @@ Thread::UnwindInnermostExpression()
Error error;
int stack_size = m_plan_stack.size();
- // If the input plan is NULL, discard all plans. Otherwise make sure this plan is in the
+ // If the input plan is nullptr, discard all plans. Otherwise make sure this plan is in the
// stack, and if so discard up to and including it.
for (int i = stack_size - 1; i > 0; i--)
@@ -1490,7 +1492,6 @@ Thread::UnwindInnermostExpression()
return error;
}
-
ThreadPlanSP
Thread::QueueFundamentalPlan (bool abort_other_plans)
{
@@ -1500,12 +1501,9 @@ Thread::QueueFundamentalPlan (bool abort_other_plans)
}
ThreadPlanSP
-Thread::QueueThreadPlanForStepSingleInstruction
-(
- bool step_over,
- bool abort_other_plans,
- bool stop_other_threads
-)
+Thread::QueueThreadPlanForStepSingleInstruction(bool step_over,
+ bool abort_other_plans,
+ bool stop_other_threads)
{
ThreadPlanSP thread_plan_sp (new ThreadPlanStepInstruction (*this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
QueueThreadPlan (thread_plan_sp, abort_other_plans);
@@ -1513,14 +1511,11 @@ Thread::QueueThreadPlanForStepSingleInstruction
}
ThreadPlanSP
-Thread::QueueThreadPlanForStepOverRange
-(
- bool abort_other_plans,
- const AddressRange &range,
- const SymbolContext &addr_context,
- lldb::RunMode stop_other_threads,
- LazyBool step_out_avoids_code_withoug_debug_info
-)
+Thread::QueueThreadPlanForStepOverRange(bool abort_other_plans,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ lldb::RunMode stop_other_threads,
+ LazyBool step_out_avoids_code_withoug_debug_info)
{
ThreadPlanSP thread_plan_sp;
thread_plan_sp.reset (new ThreadPlanStepOverRange (*this, range, addr_context, stop_other_threads, step_out_avoids_code_withoug_debug_info));
@@ -1529,17 +1524,29 @@ Thread::QueueThreadPlanForStepOverRange
return thread_plan_sp;
}
+// Call the QueueThreadPlanForStepOverRange method which takes an address range.
ThreadPlanSP
-Thread::QueueThreadPlanForStepInRange
-(
- bool abort_other_plans,
- const AddressRange &range,
- const SymbolContext &addr_context,
- const char *step_in_target,
- lldb::RunMode stop_other_threads,
- LazyBool step_in_avoids_code_without_debug_info,
- LazyBool step_out_avoids_code_without_debug_info
-)
+Thread::QueueThreadPlanForStepOverRange(bool abort_other_plans,
+ const LineEntry &line_entry,
+ const SymbolContext &addr_context,
+ lldb::RunMode stop_other_threads,
+ LazyBool step_out_avoids_code_withoug_debug_info)
+{
+ return QueueThreadPlanForStepOverRange (abort_other_plans,
+ line_entry.GetSameLineContiguousAddressRange(),
+ addr_context,
+ stop_other_threads,
+ step_out_avoids_code_withoug_debug_info);
+}
+
+ThreadPlanSP
+Thread::QueueThreadPlanForStepInRange(bool abort_other_plans,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ const char *step_in_target,
+ lldb::RunMode stop_other_threads,
+ LazyBool step_in_avoids_code_without_debug_info,
+ LazyBool step_out_avoids_code_without_debug_info)
{
ThreadPlanSP thread_plan_sp (new ThreadPlanStepInRange (*this,
range,
@@ -1556,19 +1563,35 @@ Thread::QueueThreadPlanForStepInRange
return thread_plan_sp;
}
+// Call the QueueThreadPlanForStepInRange method which takes an address range.
+ThreadPlanSP
+Thread::QueueThreadPlanForStepInRange(bool abort_other_plans,
+ const LineEntry &line_entry,
+ const SymbolContext &addr_context,
+ const char *step_in_target,
+ lldb::RunMode stop_other_threads,
+ LazyBool step_in_avoids_code_without_debug_info,
+ LazyBool step_out_avoids_code_without_debug_info)
+{
+ return QueueThreadPlanForStepInRange (abort_other_plans,
+ line_entry.GetSameLineContiguousAddressRange(),
+ addr_context,
+ step_in_target,
+ stop_other_threads,
+ step_in_avoids_code_without_debug_info,
+ step_out_avoids_code_without_debug_info);
+}
+
ThreadPlanSP
-Thread::QueueThreadPlanForStepOut
-(
- bool abort_other_plans,
- SymbolContext *addr_context,
- bool first_insn,
- bool stop_other_threads,
- Vote stop_vote,
- Vote run_vote,
- uint32_t frame_idx,
- LazyBool step_out_avoids_code_withoug_debug_info
-)
+Thread::QueueThreadPlanForStepOut(bool abort_other_plans,
+ SymbolContext *addr_context,
+ bool first_insn,
+ bool stop_other_threads,
+ Vote stop_vote,
+ Vote run_vote,
+ uint32_t frame_idx,
+ LazyBool step_out_avoids_code_without_debug_info)
{
ThreadPlanSP thread_plan_sp (new ThreadPlanStepOut (*this,
addr_context,
@@ -1577,9 +1600,9 @@ Thread::QueueThreadPlanForStepOut
stop_vote,
run_vote,
frame_idx,
- step_out_avoids_code_withoug_debug_info));
+ step_out_avoids_code_without_debug_info));
- if (thread_plan_sp->ValidatePlan(NULL))
+ if (thread_plan_sp->ValidatePlan(nullptr))
{
QueueThreadPlan (thread_plan_sp, abort_other_plans);
return thread_plan_sp;
@@ -1591,16 +1614,14 @@ Thread::QueueThreadPlanForStepOut
}
ThreadPlanSP
-Thread::QueueThreadPlanForStepOutNoShouldStop
-(
- bool abort_other_plans,
- SymbolContext *addr_context,
- bool first_insn,
- bool stop_other_threads,
- Vote stop_vote,
- Vote run_vote,
- uint32_t frame_idx
-)
+Thread::QueueThreadPlanForStepOutNoShouldStop(bool abort_other_plans,
+ SymbolContext *addr_context,
+ bool first_insn,
+ bool stop_other_threads,
+ Vote stop_vote,
+ Vote run_vote,
+ uint32_t frame_idx,
+ bool continue_to_next_branch)
{
ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut (*this,
addr_context,
@@ -1609,12 +1630,13 @@ Thread::QueueThreadPlanForStepOutNoShouldStop
stop_vote,
run_vote,
frame_idx,
- eLazyBoolNo));
+ eLazyBoolNo,
+ continue_to_next_branch));
ThreadPlanStepOut *new_plan = static_cast<ThreadPlanStepOut *>(thread_plan_sp.get());
new_plan->ClearShouldStopHereCallbacks();
- if (thread_plan_sp->ValidatePlan(NULL))
+ if (thread_plan_sp->ValidatePlan(nullptr))
{
QueueThreadPlan (thread_plan_sp, abort_other_plans);
return thread_plan_sp;
@@ -1629,7 +1651,7 @@ ThreadPlanSP
Thread::QueueThreadPlanForStepThrough (StackID &return_stack_id, bool abort_other_plans, bool stop_other_threads)
{
ThreadPlanSP thread_plan_sp(new ThreadPlanStepThrough (*this, return_stack_id, stop_other_threads));
- if (!thread_plan_sp || !thread_plan_sp->ValidatePlan (NULL))
+ if (!thread_plan_sp || !thread_plan_sp->ValidatePlan(nullptr))
return ThreadPlanSP();
QueueThreadPlan (thread_plan_sp, abort_other_plans);
@@ -1677,7 +1699,6 @@ Thread::QueueThreadPlanForStepScripted (bool abort_other_plans,
}
else
return thread_plan_sp;
-
}
uint32_t
@@ -1768,7 +1789,6 @@ Thread::CalculateTarget ()
if (process_sp)
target_sp = process_sp->CalculateTarget();
return target_sp;
-
}
ProcessSP
@@ -1795,7 +1815,6 @@ Thread::CalculateExecutionContext (ExecutionContext &exe_ctx)
exe_ctx.SetContext (shared_from_this());
}
-
StackFrameListSP
Thread::GetStackFrameList ()
{
@@ -1839,7 +1858,6 @@ Thread::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx)
return GetStackFrameList()->GetFrameWithConcreteFrameIndex (unwind_idx);
}
-
Error
Thread::ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp, bool broadcast)
{
@@ -1886,12 +1904,12 @@ Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return
// FIXME: ValueObject::Cast doesn't currently work correctly, at least not for scalars.
// Turn that back on when that works.
- if (/* DISABLES CODE */ (0) && sc.function != NULL)
+ if (/* DISABLES CODE */ (0) && sc.function != nullptr)
{
Type *function_type = sc.function->GetType();
if (function_type)
{
- ClangASTType return_type = sc.function->GetClangType().GetFunctionReturnType();
+ CompilerType return_type = sc.function->GetCompilerType().GetFunctionReturnType();
if (return_type)
{
StreamString s;
@@ -2024,7 +2042,7 @@ Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx)
{
ExecutionContext exe_ctx (shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
- if (process == NULL)
+ if (process == nullptr)
return;
StackFrameSP frame_sp;
@@ -2044,10 +2062,10 @@ Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx)
FormatEntity::Format(*thread_format,
strm,
- frame_sp ? &frame_sc : NULL,
+ frame_sp ? &frame_sc : nullptr,
&exe_ctx,
- NULL,
- NULL,
+ nullptr,
+ nullptr,
false,
false);
}
@@ -2119,7 +2137,6 @@ Thread::StopReasonAsCString (lldb::StopReason reason)
case eStopReasonInstrumentation: return "instrumentation break";
}
-
static char unknown_state_string[64];
snprintf(unknown_state_string, sizeof (unknown_state_string), "StopReason = %i", reason);
return unknown_state_string;
@@ -2176,7 +2193,7 @@ Thread::GetStatus (Stream &strm, uint32_t start_frame, uint32_t num_frames, uint
const bool show_frame_info = true;
- const char *selected_frame_marker = NULL;
+ const char *selected_frame_marker = nullptr;
if (num_frames == 1 || (GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID()))
strm.IndentMore ();
else
@@ -2302,7 +2319,7 @@ Thread::GetStackFrameStatus (Stream& strm,
Unwind *
Thread::GetUnwinder ()
{
- if (m_unwinder_ap.get() == NULL)
+ if (!m_unwinder_ap)
{
const ArchSpec target_arch (CalculateTarget()->GetArchitecture ());
const llvm::Triple::ArchType machine = target_arch.GetMachine();
@@ -2332,7 +2349,6 @@ Thread::GetUnwinder ()
return m_unwinder_ap.get();
}
-
void
Thread::Flush ()
{
@@ -2364,7 +2380,6 @@ Thread::IsStillAtLastBreakpointHit ()
return false;
}
-
Error
Thread::StepIn (bool source_step,
LazyBool step_in_avoids_code_without_debug_info,
@@ -2383,13 +2398,13 @@ Thread::StepIn (bool source_step,
if (source_step && frame_sp && frame_sp->HasDebugInformation ())
{
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
- new_plan_sp = QueueThreadPlanForStepInRange (abort_other_plans,
- sc.line_entry.range,
- sc,
- NULL,
- run_mode,
- step_in_avoids_code_without_debug_info,
- step_out_avoids_code_without_debug_info);
+ new_plan_sp = QueueThreadPlanForStepInRange(abort_other_plans,
+ sc.line_entry,
+ sc,
+ nullptr,
+ run_mode,
+ step_in_avoids_code_without_debug_info,
+ step_out_avoids_code_without_debug_info);
}
else
{
@@ -2430,7 +2445,7 @@ Thread::StepOver (bool source_step,
{
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = QueueThreadPlanForStepOverRange (abort_other_plans,
- sc.line_entry.range,
+ sc.line_entry,
sc,
run_mode,
step_out_avoids_code_without_debug_info);
@@ -2467,13 +2482,13 @@ Thread::StepOut ()
const bool stop_other_threads = false;
const bool abort_other_plans = false;
- ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut (abort_other_plans,
- NULL,
- first_instruction,
- stop_other_threads,
- eVoteYes,
- eVoteNoOpinion,
- 0));
+ ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut(abort_other_plans,
+ nullptr,
+ first_instruction,
+ stop_other_threads,
+ eVoteYes,
+ eVoteNoOpinion,
+ 0));
new_plan_sp->SetIsMasterPlan(true);
new_plan_sp->SetOkayToDiscard(false);
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp
index d581a7c..a34cb0f 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadList.cpp
@@ -6,10 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+
+// C Includes
#include <stdlib.h>
+// C++ Includes
#include <algorithm>
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
#include "lldb/Target/RegisterContext.h"
@@ -18,6 +23,7 @@
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/ConvertEnum.h"
+#include "lldb/Utility/LLDBAssert.h"
using namespace lldb;
using namespace lldb_private;
@@ -46,7 +52,7 @@ ThreadList::operator = (const ThreadList& rhs)
if (this != &rhs)
{
// Lock both mutexes to make sure neither side changes anyone on us
- // while the assignement occurs
+ // while the assignment occurs
Mutex::Locker locker(GetMutex());
m_process = rhs.m_process;
m_stop_id = rhs.m_stop_id;
@@ -257,7 +263,24 @@ ThreadList::ShouldStop (Event *event_ptr)
Mutex::Locker locker(GetMutex());
m_process->UpdateThreadListIfNeeded();
- threads_copy = m_threads;
+ for (lldb::ThreadSP thread_sp : m_threads)
+ {
+ // This is an optimization... If we didn't let a thread run in between the previous stop and this
+ // one, we shouldn't have to consult it for ShouldStop. So just leave it off the list we are going to
+ // inspect.
+ // On Linux, if a thread-specific conditional breakpoint was hit, it won't necessarily be the thread
+ // that hit the breakpoint itself that evaluates the conditional expression, so the thread that hit
+ // the breakpoint could still be asked to stop, even though it hasn't been allowed to run since the
+ // previous stop.
+ if (thread_sp->GetTemporaryResumeState () != eStateSuspended || thread_sp->IsStillAtLastBreakpointHit())
+ threads_copy.push_back(thread_sp);
+ }
+
+ // It is possible the threads we were allowing to run all exited and then maybe the user interrupted
+ // or something, then fall back on looking at all threads:
+
+ if (threads_copy.size() == 0)
+ threads_copy = m_threads;
}
collection::iterator pos, end = threads_copy.end();
@@ -265,7 +288,10 @@ ThreadList::ShouldStop (Event *event_ptr)
if (log)
{
log->PutCString("");
- log->Printf ("ThreadList::%s: %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size());
+ log->Printf ("ThreadList::%s: %" PRIu64 " threads, %" PRIu64 " unsuspended threads",
+ __FUNCTION__,
+ (uint64_t)m_threads.size(),
+ (uint64_t)threads_copy.size());
}
bool did_anybody_stop_for_a_reason = false;
@@ -518,6 +544,7 @@ ThreadList::WillResume ()
for (pos = m_threads.begin(); pos != end; ++pos)
{
+ lldbassert((*pos)->GetCurrentPlan() && "thread should not have null thread plan");
if ((*pos)->GetResumeState() != eStateSuspended &&
(*pos)->GetCurrentPlan()->StopOthers())
{
@@ -750,7 +777,7 @@ ThreadList::Update (ThreadList &rhs)
if (this != &rhs)
{
// Lock both mutexes to make sure neither side changes anyone on us
- // while the assignement occurs
+ // while the assignment occurs
Mutex::Locker locker(GetMutex());
m_process = rhs.m_process;
m_stop_id = rhs.m_stop_id;
@@ -773,7 +800,8 @@ ThreadList::Update (ThreadList &rhs)
const uint32_t num_threads = m_threads.size();
for (uint32_t idx = 0; idx < num_threads; ++idx)
{
- if (m_threads[idx]->GetID() == tid)
+ ThreadSP backing_thread = m_threads[idx]->GetBackingThread();
+ if (m_threads[idx]->GetID() == tid || (backing_thread && backing_thread->GetID() == tid))
{
thread_is_alive = true;
break;
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlan.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlan.cpp
index 094a6bf..2432333 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlan.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlan.cpp
@@ -7,12 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/ThreadPlan.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/ThreadPlan.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
@@ -48,9 +47,7 @@ ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vo
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-ThreadPlan::~ThreadPlan()
-{
-}
+ThreadPlan::~ThreadPlan() = default;
bool
ThreadPlan::PlanExplainsStop (Event *event_ptr)
@@ -130,10 +127,7 @@ ThreadPlan::StopOthers ()
{
ThreadPlan *prev_plan;
prev_plan = GetPreviousPlan ();
- if (prev_plan == NULL)
- return false;
- else
- return prev_plan->StopOthers();
+ return (prev_plan == nullptr) ? false : prev_plan->StopOthers();
}
void
@@ -191,10 +185,7 @@ ThreadPlan::WillPop()
bool
ThreadPlan::OkayToDiscard()
{
- if (!IsMasterPlan())
- return true;
- else
- return m_okay_to_discard;
+ return IsMasterPlan() ? m_okay_to_discard : true;
}
lldb::StateType
@@ -206,6 +197,23 @@ ThreadPlan::RunState ()
return GetPlanRunState();
}
+bool
+ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason)
+{
+ switch (reason)
+ {
+ case eStopReasonWatchpoint:
+ case eStopReasonSignal:
+ case eStopReasonException:
+ case eStopReasonExec:
+ case eStopReasonThreadExiting:
+ case eStopReasonInstrumentation:
+ return true;
+ default:
+ return false;
+ }
+}
+
//----------------------------------------------------------------------
// ThreadPlanNull
//----------------------------------------------------------------------
@@ -219,9 +227,7 @@ ThreadPlanNull::ThreadPlanNull (Thread &thread) :
{
}
-ThreadPlanNull::~ThreadPlanNull ()
-{
-}
+ThreadPlanNull::~ThreadPlanNull() = default;
void
ThreadPlanNull::GetDescription (Stream *s,
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunction.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunction.cpp
index e7b3abd..01ca126 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunction.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunction.cpp
@@ -7,13 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/ThreadPlanCallFunction.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
-
// Project includes
+#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Address.h"
@@ -76,7 +74,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
Module *exe_module = GetTarget().GetExecutableModulePointer();
- if (exe_module == NULL)
+ if (exe_module == nullptr)
{
m_constructor_errors.Printf ("Can't execute code without an executable module.");
if (log)
@@ -135,7 +133,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
const Address &function,
- const ClangASTType &return_type,
+ const CompilerType &return_type,
llvm::ArrayRef<addr_t> args,
const EvaluateExpressionOptions &options) :
ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
@@ -188,9 +186,8 @@ ThreadPlanCallFunction::ThreadPlanCallFunction(Thread &thread,
m_should_clear_objc_exception_bp(false),
m_should_clear_cxx_exception_bp(false),
m_stop_address(LLDB_INVALID_ADDRESS),
- m_return_type(ClangASTType())
+ m_return_type(CompilerType())
{
-
}
ThreadPlanCallFunction::~ThreadPlanCallFunction ()
@@ -263,7 +260,6 @@ ThreadPlanCallFunction::DoTakedown (bool success)
ClearBreakpoints();
if (log && log->GetVerbose())
ReportRegisterState ("Restoring thread state after function call. Restored register state:");
-
}
else
{
@@ -312,7 +308,6 @@ ThreadPlanCallFunction::ValidatePlan (Stream *error)
return true;
}
-
Vote
ThreadPlanCallFunction::ShouldReportStop(Event *event_ptr)
{
@@ -330,7 +325,7 @@ ThreadPlanCallFunction::DoPlanExplainsStop (Event *event_ptr)
// If our subplan knows why we stopped, even if it's done (which would forward the question to us)
// we answer yes.
- if (m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop(event_ptr))
+ if (m_subplan_sp && m_subplan_sp->PlanExplainsStop(event_ptr))
{
SetPlanComplete();
return true;
@@ -360,8 +355,7 @@ ThreadPlanCallFunction::DoPlanExplainsStop (Event *event_ptr)
// We control breakpoints separately from other "stop reasons." So first,
// check the case where we stopped for an internal breakpoint, in that case, continue on.
// If it is not an internal breakpoint, consult m_ignore_breakpoints.
-
-
+
if (stop_reason == eStopReasonBreakpoint)
{
ProcessSP process_sp (m_thread.CalculateProcess());
@@ -426,15 +420,7 @@ ThreadPlanCallFunction::DoPlanExplainsStop (Event *event_ptr)
if (m_real_stop_info_sp && m_real_stop_info_sp->ShouldStopSynchronous(event_ptr))
{
SetPlanComplete(false);
- if (m_subplan_sp)
- {
- if (m_unwind_on_error)
- return true;
- else
- return false;
- }
- else
- return false;
+ return m_subplan_sp ? m_unwind_on_error : false;
}
else
return true;
@@ -583,19 +569,17 @@ ThreadPlanCallFunction::SetStopOthers (bool new_value)
m_subplan_sp->SetStopOthers(new_value);
}
-
bool
ThreadPlanCallFunction::RestoreThreadState()
{
return GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state);
}
-
void
ThreadPlanCallFunction::SetReturnValue()
{
ProcessSP process_sp(m_thread.GetProcess());
- const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
+ const ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr;
if (abi && m_return_type.IsValid())
{
const bool persistent = false;
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunctionUsingABI.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunctionUsingABI.cpp
index 53fabd2..df23edc 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunctionUsingABI.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallFunctionUsingABI.cpp
@@ -1,4 +1,4 @@
-//===-- ThreadPlanCallFunctionUsingABI.cpp ------------------------------*- C++ -*-===//
+//===-- ThreadPlanCallFunctionUsingABI.cpp ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,13 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
-
// Project includes
+#include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
@@ -57,10 +55,7 @@ ThreadPlanCallFunctionUsingABI::ThreadPlanCallFunctionUsingABI (Thread &thread,
m_valid = true;
}
-ThreadPlanCallFunctionUsingABI::~ThreadPlanCallFunctionUsingABI()
-{
-
-}
+ThreadPlanCallFunctionUsingABI::~ThreadPlanCallFunctionUsingABI() = default;
void
ThreadPlanCallFunctionUsingABI::GetDescription(Stream *s, DescriptionLevel level)
@@ -80,7 +75,7 @@ void
ThreadPlanCallFunctionUsingABI::SetReturnValue()
{
ProcessSP process_sp(m_thread.GetProcess());
- const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
+ const ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr;
// Ask the abi for the return value
if (abi)
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallUserExpression.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallUserExpression.cpp
index 1773777..b24f74b 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallUserExpression.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanCallUserExpression.cpp
@@ -19,7 +19,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/LanguageRuntime.h"
@@ -41,8 +41,8 @@ ThreadPlanCallUserExpression::ThreadPlanCallUserExpression (Thread &thread,
Address &function,
llvm::ArrayRef<lldb::addr_t> args,
const EvaluateExpressionOptions &options,
- lldb::ClangUserExpressionSP &user_expression_sp) :
- ThreadPlanCallFunction (thread, function, ClangASTType(), args, options),
+ lldb::UserExpressionSP &user_expression_sp) :
+ ThreadPlanCallFunction (thread, function, CompilerType(), args, options),
m_user_expression_sp (user_expression_sp)
{
// User expressions are generally "User generated" so we should set them up to stop when done.
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp
index 54ae1dc..18c43da 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanRunToAddress.cpp
@@ -7,12 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/ThreadPlanRunToAddress.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Target/Target.h"
@@ -88,7 +87,7 @@ ThreadPlanRunToAddress::SetInitialBreakpoints ()
{
Breakpoint *breakpoint;
breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true, false).get();
- if (breakpoint != NULL)
+ if (breakpoint != nullptr)
{
m_break_ids[i] = breakpoint->GetID();
breakpoint->SetThreadID(m_thread.GetID());
@@ -195,7 +194,7 @@ ThreadPlanRunToAddress::DoPlanExplainsStop (Event *event_ptr)
bool
ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
{
- return false;
+ return AtOurAddress();
}
bool
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanShouldStopHere.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanShouldStopHere.cpp
index e89f5d2..55aaaf0 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanShouldStopHere.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanShouldStopHere.cpp
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanShouldStopHere.h"
@@ -15,19 +19,14 @@
using namespace lldb;
using namespace lldb_private;
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-
//----------------------------------------------------------------------
// ThreadPlanShouldStopHere constructor
//----------------------------------------------------------------------
ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner) :
- m_callbacks (),
- m_baton (NULL),
- m_owner (owner),
- m_flags (ThreadPlanShouldStopHere::eNone)
+ m_callbacks(),
+ m_baton(nullptr),
+ m_owner(owner),
+ m_flags(ThreadPlanShouldStopHere::eNone)
{
m_callbacks.should_stop_here_callback = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback;
m_callbacks.step_from_here_callback = ThreadPlanShouldStopHere::DefaultStepFromHereCallback;
@@ -42,12 +41,7 @@ ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner, const Thre
SetShouldStopHereCallbacks(callbacks, baton);
}
-//----------------------------------------------------------------------
-// Destructor
-//----------------------------------------------------------------------
-ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere()
-{
-}
+ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere() = default;
bool
ThreadPlanShouldStopHere::InvokeShouldStopHereCallback (FrameComparison operation)
@@ -135,13 +129,14 @@ ThreadPlanShouldStopHere::DefaultStepFromHereCallback (ThreadPlan *current_plan,
}
if (!return_plan_sp)
- return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop (false,
- NULL,
- true,
- stop_others,
- eVoteNo,
- eVoteNoOpinion,
- frame_index);
+ return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop(false,
+ nullptr,
+ true,
+ stop_others,
+ eVoteNo,
+ eVoteNoOpinion,
+ frame_index,
+ true);
return return_plan_sp;
}
@@ -154,7 +149,6 @@ ThreadPlanShouldStopHere::QueueStepOutFromHerePlan(lldb_private::Flags &flags, l
return_plan_sp = m_callbacks.step_from_here_callback (m_owner, flags, operation, m_baton);
}
return return_plan_sp;
-
}
lldb::ThreadPlanSP
@@ -165,4 +159,3 @@ ThreadPlanShouldStopHere::CheckShouldStopHereAndQueueStepOut (lldb::FrameCompari
else
return ThreadPlanSP();
}
-
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp
index 3ee5792..3771e21 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp
@@ -7,12 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/ThreadPlanStepInRange.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Stream.h"
@@ -76,9 +75,7 @@ ThreadPlanStepInRange::ThreadPlanStepInRange
SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, step_out_avoids_code_without_debug_info);
}
-ThreadPlanStepInRange::~ThreadPlanStepInRange ()
-{
-}
+ThreadPlanStepInRange::~ThreadPlanStepInRange() = default;
void
ThreadPlanStepInRange::SetupAvoidNoDebug(LazyBool step_in_avoids_code_without_debug_info,
@@ -193,11 +190,7 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
// Stepping through should be done running other threads in general, since we're setting a breakpoint and
// continuing. So only stop others if we are explicitly told to do so.
- bool stop_others;
- if (m_stop_others == lldb::eOnlyThisThread)
- stop_others = true;
- else
- stop_others = false;
+ bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
FrameComparison frame_order = CompareCurrentFrameToStartFrame();
@@ -220,7 +213,6 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
{
log->Printf("Thought I stepped out, but in fact arrived at a trampoline.");
}
-
}
else if (frame_order == eFrameCompareEqual && InSymbol())
{
@@ -322,7 +314,7 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
void
ThreadPlanStepInRange::SetAvoidRegexp(const char *name)
{
- if (m_avoid_regexp_ap.get() == NULL)
+ if (!m_avoid_regexp_ap)
m_avoid_regexp_ap.reset (new RegularExpression(name));
m_avoid_regexp_ap->Compile (name);
@@ -367,15 +359,15 @@ ThreadPlanStepInRange::FrameMatchesAvoidCriteria ()
return true;
const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get();
- if (avoid_regexp_to_use == NULL)
+ if (avoid_regexp_to_use == nullptr)
avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp();
- if (avoid_regexp_to_use != NULL)
+ if (avoid_regexp_to_use != nullptr)
{
SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
- if (sc.symbol != NULL)
+ if (sc.symbol != nullptr)
{
- const char *frame_function_name = sc.GetFunctionName().GetCString();
+ const char *frame_function_name = sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments).GetCString();
if (frame_function_name)
{
size_t num_matches = 0;
@@ -424,7 +416,7 @@ ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
if (step_in_range_plan->m_step_into_target)
{
SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
- if (sc.symbol != NULL)
+ if (sc.symbol != nullptr)
{
// First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare.
if (step_in_range_plan->m_step_into_target == sc.GetFunctionName())
@@ -436,9 +428,9 @@ ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
const char *target_name = step_in_range_plan->m_step_into_target.AsCString();
const char *function_name = sc.GetFunctionName().AsCString();
- if (function_name == NULL)
+ if (function_name == nullptr)
should_stop_here = false;
- else if (strstr (function_name, target_name) == NULL)
+ else if (strstr(function_name, target_name) == nullptr)
should_stop_here = false;
}
if (log && !should_stop_here)
@@ -476,7 +468,7 @@ ThreadPlanStepInRange::DoPlanExplainsStop (Event *event_ptr)
// The only variation is that if we are doing "step by running to next branch" in which case
// if we hit our branch breakpoint we don't set the plan to complete.
- bool return_value;
+ bool return_value = false;
if (m_virtual_step)
{
@@ -488,30 +480,24 @@ ThreadPlanStepInRange::DoPlanExplainsStop (Event *event_ptr)
if (stop_info_sp)
{
StopReason reason = stop_info_sp->GetStopReason();
-
- switch (reason)
+
+ if (reason == eStopReasonBreakpoint)
{
- case eStopReasonBreakpoint:
if (NextRangeBreakpointExplainsStop(stop_info_sp))
{
return_value = true;
- break;
- }
- case eStopReasonWatchpoint:
- case eStopReasonSignal:
- case eStopReasonException:
- case eStopReasonExec:
- case eStopReasonThreadExiting:
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- if (log)
- log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
}
+ }
+ else if (IsUsuallyUnexplainedStopReason(reason))
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ if (log)
+ log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
return_value = false;
- break;
- default:
+ }
+ else
+ {
return_value = true;
- break;
}
}
else
@@ -549,5 +535,5 @@ ThreadPlanStepInRange::DoWillResume (lldb::StateType resume_state, bool current_
bool
ThreadPlanStepInRange::IsVirtualStep()
{
- return m_virtual_step;
+ return m_virtual_step;
}
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInstruction.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInstruction.cpp
index 1ce26df..9d7d521 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInstruction.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInstruction.cpp
@@ -7,13 +7,11 @@
//
//===----------------------------------------------------------------------===//
-
-#include "lldb/Target/ThreadPlanStepInstruction.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Target/Process.h"
@@ -46,9 +44,7 @@ ThreadPlanStepInstruction::ThreadPlanStepInstruction
SetUpState();
}
-ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
-{
-}
+ThreadPlanStepInstruction::~ThreadPlanStepInstruction() = default;
void
ThreadPlanStepInstruction::SetUpState()
@@ -57,7 +53,7 @@ ThreadPlanStepInstruction::SetUpState()
StackFrameSP start_frame_sp(m_thread.GetStackFrameAtIndex(0));
m_stack_id = start_frame_sp->GetStackID();
- m_start_has_symbol = start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL;
+ m_start_has_symbol = start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != nullptr;
StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1);
if (parent_frame_sp)
@@ -103,10 +99,7 @@ ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr)
if (stop_info_sp)
{
StopReason reason = stop_info_sp->GetStopReason();
- if (reason == eStopReasonTrace || reason == eStopReasonNone)
- return true;
- else
- return false;
+ return (reason == eStopReasonTrace || reason == eStopReasonNone);
}
return false;
}
@@ -118,19 +111,13 @@ ThreadPlanStepInstruction::IsPlanStale ()
StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
if (cur_frame_id == m_stack_id)
{
- if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
- return true;
- else
- return false;
+ return (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr);
}
else if (cur_frame_id < m_stack_id)
{
// If the current frame is younger than the start frame and we are stepping over, then we need to continue,
// but if we are doing just one step, we're done.
- if (m_step_over)
- return false;
- else
- return true;
+ return !m_step_over;
}
else
{
@@ -222,7 +209,7 @@ ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
// run others.
const bool stop_others = false;
m_thread.QueueThreadPlanForStepOutNoShouldStop(false,
- NULL,
+ nullptr,
true,
stop_others,
eVoteNo,
@@ -248,9 +235,7 @@ ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
SetPlanComplete();
return true;
}
-
}
-
}
else
{
@@ -308,4 +293,3 @@ ThreadPlanStepInstruction::MischiefManaged ()
return false;
}
}
-
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp
index 8b702a2..82b823b 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOut.cpp
@@ -7,18 +7,18 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/ThreadPlanStepOut.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/Process.h"
@@ -45,7 +45,8 @@ ThreadPlanStepOut::ThreadPlanStepOut
Vote stop_vote,
Vote run_vote,
uint32_t frame_idx,
- LazyBool step_out_avoids_code_without_debug_info
+ LazyBool step_out_avoids_code_without_debug_info,
+ bool continue_to_next_branch
) :
ThreadPlan (ThreadPlan::eKindStepOut, "Step out", thread, stop_vote, run_vote),
ThreadPlanShouldStopHere (this),
@@ -53,7 +54,7 @@ ThreadPlanStepOut::ThreadPlanStepOut
m_return_bp_id (LLDB_INVALID_BREAK_ID),
m_return_addr (LLDB_INVALID_ADDRESS),
m_stop_others (stop_others),
- m_immediate_step_from_function(NULL)
+ m_immediate_step_from_function(nullptr)
{
SetFlagsToDefault();
SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
@@ -80,14 +81,15 @@ ThreadPlanStepOut::ThreadPlanStepOut
{
// First queue a plan that gets us to this inlined frame, and when we get there we'll queue a second
// plan that walks us out of this frame.
- m_step_out_to_inline_plan_sp.reset (new ThreadPlanStepOut(m_thread,
- NULL,
- false,
- stop_others,
- eVoteNoOpinion,
- eVoteNoOpinion,
- frame_idx - 1,
- eLazyBoolNo));
+ m_step_out_to_inline_plan_sp.reset(new ThreadPlanStepOut(m_thread,
+ nullptr,
+ false,
+ stop_others,
+ eVoteNoOpinion,
+ eVoteNoOpinion,
+ frame_idx - 1,
+ eLazyBoolNo,
+ continue_to_next_branch));
static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get())->SetShouldStopHereCallbacks(nullptr, nullptr);
m_step_out_to_inline_plan_sp->SetPrivate(true);
}
@@ -96,20 +98,39 @@ ThreadPlanStepOut::ThreadPlanStepOut
// If we're already at the inlined frame we're stepping through, then just do that now.
QueueInlinedStepPlan(false);
}
-
}
else if (return_frame_sp)
{
// Find the return address and set a breakpoint there:
// FIXME - can we do this more securely if we know first_insn?
- m_return_addr = return_frame_sp->GetFrameCodeAddress().GetLoadAddress(&m_thread.GetProcess()->GetTarget());
+ Address return_address (return_frame_sp->GetFrameCodeAddress());
+ if (continue_to_next_branch)
+ {
+ SymbolContext return_address_sc;
+ AddressRange range;
+ Address return_address_decr_pc = return_address;
+ if (return_address_decr_pc.GetOffset() > 0)
+ return_address_decr_pc.Slide (-1);
+
+ return_address_decr_pc.CalculateSymbolContext (&return_address_sc, lldb::eSymbolContextLineEntry);
+ if (return_address_sc.line_entry.IsValid())
+ {
+ range = return_address_sc.line_entry.GetSameLineContiguousAddressRange();
+ if (range.GetByteSize() > 0)
+ {
+ return_address = m_thread.GetProcess()->AdvanceAddressToNextBranchInstruction (return_address,
+ range);
+ }
+ }
+ }
+ m_return_addr = return_address.GetLoadAddress(&m_thread.GetProcess()->GetTarget());
if (m_return_addr == LLDB_INVALID_ADDRESS)
return;
Breakpoint *return_bp = m_thread.CalculateTarget()->CreateBreakpoint (m_return_addr, true, false).get();
- if (return_bp != NULL)
+ if (return_bp != nullptr)
{
return_bp->SetThreadID(m_thread.GetID());
m_return_bp_id = return_bp->GetID();
@@ -125,7 +146,6 @@ ThreadPlanStepOut::ThreadPlanStepOut
}
}
}
-
}
void
@@ -192,7 +212,7 @@ ThreadPlanStepOut::GetDescription (Stream *s, lldb::DescriptionLevel level)
// FIXME: find some useful way to present the m_return_id, since there may be multiple copies of the
// same function on the stack.
- s->Printf ("returning to frame at ");
+ s->Printf (" returning to frame at ");
if (tmp_address.SetLoadAddress (m_return_addr, &GetTarget()))
{
tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription, Address::DumpStyleLoadAddress);
@@ -231,10 +251,7 @@ ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
// If the step out plan is done, then we just need to step through the inlined frame.
if (m_step_out_to_inline_plan_sp)
{
- if (m_step_out_to_inline_plan_sp->MischiefManaged())
- return true;
- else
- return false;
+ return m_step_out_to_inline_plan_sp->MischiefManaged();
}
else if (m_step_through_inline_plan_sp)
{
@@ -249,10 +266,7 @@ ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
}
else if (m_step_out_further_plan_sp)
{
- if (m_step_out_further_plan_sp->MischiefManaged())
- return true;
- else
- return false;
+ return m_step_out_further_plan_sp->MischiefManaged();
}
// We don't explain signals or breakpoints (breakpoints that handle stepping in or
@@ -262,9 +276,7 @@ ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
if (stop_info_sp)
{
StopReason reason = stop_info_sp->GetStopReason();
- switch (reason)
- {
- case eStopReasonBreakpoint:
+ if (reason == eStopReasonBreakpoint)
{
// If this is OUR breakpoint, we're fine, otherwise we don't know why this happened...
BreakpointSiteSP site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (stop_info_sp->GetValue()));
@@ -284,10 +296,7 @@ ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
}
else
{
- if (m_immediate_step_from_id < frame_zero_id)
- done = true;
- else
- done = false;
+ done = (m_immediate_step_from_id < frame_zero_id);
}
if (done)
@@ -306,20 +315,13 @@ ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
if (site_sp->GetNumberOfOwners() == 1)
return true;
-
}
return false;
}
- case eStopReasonWatchpoint:
- case eStopReasonSignal:
- case eStopReasonException:
- case eStopReasonExec:
- case eStopReasonThreadExiting:
+ else if (IsUsuallyUnexplainedStopReason(reason))
return false;
-
- default:
+ else
return true;
- }
}
return true;
}
@@ -367,10 +369,7 @@ ThreadPlanStepOut::ShouldStop (Event *event_ptr)
if (!done)
{
StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
- if (frame_zero_id < m_step_out_to_id)
- done = false;
- else
- done = true;
+ done = !(frame_zero_id < m_step_out_to_id);
}
// The normal step out computations think we are done, so all we need to do is consult the ShouldStopHere,
@@ -417,7 +416,7 @@ ThreadPlanStepOut::DoWillResume (StateType resume_state, bool current_plan)
if (current_plan)
{
Breakpoint *return_bp = m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
- if (return_bp != NULL)
+ if (return_bp != nullptr)
return_bp->SetEnabled (true);
}
return true;
@@ -429,7 +428,7 @@ ThreadPlanStepOut::WillStop ()
if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
{
Breakpoint *return_bp = m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
- if (return_bp != NULL)
+ if (return_bp != nullptr)
return_bp->SetEnabled (false);
}
@@ -539,14 +538,14 @@ ThreadPlanStepOut::CalculateReturnValue ()
if (m_return_valobj_sp)
return;
- if (m_immediate_step_from_function != NULL)
+ if (m_immediate_step_from_function != nullptr)
{
- ClangASTType return_clang_type = m_immediate_step_from_function->GetClangType().GetFunctionReturnType();
- if (return_clang_type)
+ CompilerType return_compiler_type = m_immediate_step_from_function->GetCompilerType().GetFunctionReturnType();
+ if (return_compiler_type)
{
lldb::ABISP abi_sp = m_thread.GetProcess()->GetABI();
if (abi_sp)
- m_return_valobj_sp = abi_sp->GetReturnValueObject(m_thread, return_clang_type);
+ m_return_valobj_sp = abi_sp->GetReturnValueObject(m_thread, return_compiler_type);
}
}
}
@@ -558,8 +557,5 @@ ThreadPlanStepOut::IsPlanStale()
// there's something for us to do. Otherwise, we're stale.
StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
- if (frame_zero_id < m_step_out_to_id)
- return false;
- else
- return true;
+ return !(frame_zero_id < m_step_out_to_id);
}
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp
index aba8922..2e731a8 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepOverRange.cpp
@@ -7,12 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/ThreadPlanStepOverRange.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/ThreadPlanStepOverRange.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/Block.h"
@@ -52,9 +51,7 @@ ThreadPlanStepOverRange::ThreadPlanStepOverRange
SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
}
-ThreadPlanStepOverRange::~ThreadPlanStepOverRange ()
-{
-}
+ThreadPlanStepOverRange::~ThreadPlanStepOverRange() = default;
void
ThreadPlanStepOverRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
@@ -111,7 +108,6 @@ ThreadPlanStepOverRange::SetupAvoidNoDebug(LazyBool step_out_avoids_code_without
bool
ThreadPlanStepOverRange::IsEquivalentContext(const SymbolContext &context)
{
-
// Match as much as is specified in the m_addr_context:
// This is a fairly loose sanity check. Note, sometimes the target doesn't get filled
// in so I left out the target check. And sometimes the module comes in as the .o file from the
@@ -150,14 +146,8 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
// If we're out of the range but in the same frame or in our caller's frame
// then we should stop.
// When stepping out we only stop others if we are forcing running one thread.
- bool stop_others;
- if (m_stop_others == lldb::eOnlyThisThread)
- stop_others = true;
- else
- stop_others = false;
-
+ bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
ThreadPlanSP new_plan_sp;
-
FrameComparison frame_order = CompareCurrentFrameToStartFrame();
if (frame_order == eFrameCompareOlder)
@@ -189,13 +179,14 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
const SymbolContext &older_context = older_frame_sp->GetSymbolContext(eSymbolContextEverything);
if (IsEquivalentContext(older_context))
{
- new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop (false,
- NULL,
- true,
- stop_others,
- eVoteNo,
- eVoteNoOpinion,
- 0);
+ new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(false,
+ nullptr,
+ true,
+ stop_others,
+ eVoteNo,
+ eVoteNoOpinion,
+ 0,
+ true);
break;
}
else
@@ -216,7 +207,6 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
return false;
}
-
if (!InSymbol())
{
// This one is a little tricky. Sometimes we may be in a stub or something similar,
@@ -283,7 +273,6 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
step_past_remaining_inline = true;
}
-
}
}
}
@@ -303,10 +292,14 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
if (next_line_entry.file == m_addr_context.line_entry.file)
{
const bool abort_other_plans = false;
- const bool stop_other_threads = false;
- new_plan_sp = m_thread.QueueThreadPlanForRunToAddress(abort_other_plans,
- next_line_address,
- stop_other_threads);
+ const RunMode stop_other_threads = RunMode::eAllThreads;
+ lldb::addr_t cur_pc = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
+ AddressRange step_range(cur_pc, next_line_address.GetLoadAddress(&GetTarget()) - cur_pc);
+
+ new_plan_sp = m_thread.QueueThreadPlanForStepOverRange (abort_other_plans,
+ step_range,
+ sc,
+ stop_other_threads);
break;
}
look_ahead_step++;
@@ -368,27 +361,19 @@ ThreadPlanStepOverRange::DoPlanExplainsStop (Event *event_ptr)
{
StopReason reason = stop_info_sp->GetStopReason();
- switch (reason)
+ if (reason == eStopReasonTrace)
{
- case eStopReasonTrace:
return_value = true;
- break;
- case eStopReasonBreakpoint:
- if (NextRangeBreakpointExplainsStop(stop_info_sp))
- return_value = true;
- else
- return_value = false;
- break;
- case eStopReasonWatchpoint:
- case eStopReasonSignal:
- case eStopReasonException:
- case eStopReasonExec:
- case eStopReasonThreadExiting:
- default:
+ }
+ else if (reason == eStopReasonBreakpoint)
+ {
+ return_value = NextRangeBreakpointExplainsStop(stop_info_sp);
+ }
+ else
+ {
if (log)
log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
return_value = false;
- break;
}
}
else
@@ -447,4 +432,3 @@ ThreadPlanStepOverRange::DoWillResume (lldb::StateType resume_state, bool curren
return true;
}
-
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp
index 3aed858..02667f8 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -7,12 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/ThreadPlanStepRange.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/ThreadPlanStepRange.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Disassembler.h"
@@ -31,7 +30,6 @@
using namespace lldb;
using namespace lldb_private;
-
//----------------------------------------------------------------------
// ThreadPlanStepRange: Step through a stack range, either stepping over or into
// based on the value of \a type.
@@ -127,7 +125,7 @@ ThreadPlanStepRange::DumpRanges(Stream *s)
{
for (size_t i = 0; i < num_ranges; i++)
{
- s->PutCString("%d: ");
+ s->Printf(" %" PRIu64 ": ", uint64_t(i));
m_address_ranges[i].Dump (s, m_thread.CalculateTarget().get(), Address::DumpStyleLoadAddress);
}
}
@@ -162,7 +160,7 @@ ThreadPlanStepRange::InRange ()
if (m_addr_context.line_entry.line == new_context.line_entry.line)
{
m_addr_context = new_context;
- AddRange(m_addr_context.line_entry.range);
+ AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange());
ret_value = true;
if (log)
{
@@ -181,7 +179,7 @@ ThreadPlanStepRange::InRange ()
{
new_context.line_entry.line = m_addr_context.line_entry.line;
m_addr_context = new_context;
- AddRange(m_addr_context.line_entry.range);
+ AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange());
ret_value = true;
if (log)
{
@@ -221,12 +219,9 @@ ThreadPlanStepRange::InRange ()
new_context.line_entry.line,
s.GetData());
}
-
}
}
-
}
-
}
if (!ret_value && log)
@@ -239,7 +234,7 @@ bool
ThreadPlanStepRange::InSymbol()
{
lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
- if (m_addr_context.function != NULL)
+ if (m_addr_context.function != nullptr)
{
return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get());
}
@@ -291,11 +286,7 @@ ThreadPlanStepRange::CompareCurrentFrameToStartFrame()
bool
ThreadPlanStepRange::StopOthers ()
{
- if (m_stop_others == lldb::eOnlyThisThread
- || m_stop_others == lldb::eOnlyDuringStepping)
- return true;
- else
- return false;
+ return (m_stop_others == lldb::eOnlyThisThread || m_stop_others == lldb::eOnlyDuringStepping);
}
InstructionList *
@@ -308,14 +299,14 @@ ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_
{
// Some joker added a zero size range to the stepping range...
if (m_address_ranges[i].GetByteSize() == 0)
- return NULL;
+ return nullptr;
if (!m_instruction_ranges[i])
{
//Disassemble the address range given:
ExecutionContext exe_ctx (m_thread.GetProcess());
- const char *plugin_name = NULL;
- const char *flavor = NULL;
+ const char *plugin_name = nullptr;
+ const char *flavor = nullptr;
const bool prefer_file_cache = true;
m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(),
plugin_name,
@@ -323,18 +314,17 @@ ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_
exe_ctx,
m_address_ranges[i],
prefer_file_cache);
-
}
if (!m_instruction_ranges[i])
- return NULL;
+ return nullptr;
else
{
// Find where we are in the instruction list as well. If we aren't at an instruction,
- // return NULL. In this case, we're probably lost, and shouldn't try to do anything fancy.
+ // return nullptr. In this case, we're probably lost, and shouldn't try to do anything fancy.
insn_offset = m_instruction_ranges[i]->GetInstructionList().GetIndexOfInstructionAtLoadAddress(addr, GetTarget());
if (insn_offset == UINT32_MAX)
- return NULL;
+ return nullptr;
else
{
range_index = i;
@@ -343,7 +333,7 @@ ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_
}
}
}
- return NULL;
+ return nullptr;
}
void
@@ -376,7 +366,7 @@ ThreadPlanStepRange::SetNextBranchBreakpoint ()
size_t pc_index;
size_t range_index;
InstructionList *instructions = GetInstructionsForAddress (cur_addr, range_index, pc_index);
- if (instructions == NULL)
+ if (instructions == nullptr)
return false;
else
{
@@ -389,13 +379,23 @@ ThreadPlanStepRange::SetNextBranchBreakpoint ()
// If we didn't find a branch, run to the end of the range.
if (branch_index == UINT32_MAX)
{
- branch_index = instructions->GetSize() - 1;
+ uint32_t last_index = instructions->GetSize() - 1;
+ if (last_index - pc_index > 1)
+ {
+ InstructionSP last_inst = instructions->GetInstructionAtIndex(last_index);
+ size_t last_inst_size = last_inst->GetOpcode().GetByteSize();
+ run_to_address = last_inst->GetAddress();
+ run_to_address.Slide(last_inst_size);
+ }
+ }
+ else if (branch_index - pc_index > 1)
+ {
+ run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress();
}
- if (branch_index - pc_index > 1)
+ if (run_to_address.IsValid())
{
const bool is_internal = true;
- run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress();
m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal, false);
if (m_next_branch_bp_sp)
{
@@ -501,15 +501,7 @@ ThreadPlanStepRange::MischiefManaged ()
else
{
FrameComparison frame_order = CompareCurrentFrameToStartFrame();
- if (frame_order != eFrameCompareOlder)
- {
- if (m_no_more_plans)
- done = true;
- else
- done = false;
- }
- else
- done = true;
+ done = (frame_order != eFrameCompareOlder) ? m_no_more_plans : true;
}
}
@@ -526,7 +518,6 @@ ThreadPlanStepRange::MischiefManaged ()
{
return false;
}
-
}
bool
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp
index 068d8e6..a5346a4 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepThrough.cpp
@@ -7,12 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/ThreadPlanStepThrough.h"
-
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/ThreadPlanStepThrough.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Target/DynamicLoader.h"
@@ -39,7 +38,6 @@ ThreadPlanStepThrough::ThreadPlanStepThrough (Thread &thread, StackID &m_stack_i
m_return_stack_id (m_stack_id),
m_stop_others (stop_others)
{
-
LookForPlanToStepThroughFromCurrentPC();
// If we don't get a valid step through plan, don't bother to set up a backstop.
@@ -56,7 +54,7 @@ ThreadPlanStepThrough::ThreadPlanStepThrough (Thread &thread, StackID &m_stack_i
{
m_backstop_addr = return_frame_sp->GetFrameCodeAddress().GetLoadAddress(m_thread.CalculateTarget().get());
Breakpoint *return_bp = m_thread.GetProcess()->GetTarget().CreateBreakpoint (m_backstop_addr, true, false).get();
- if (return_bp != NULL)
+ if (return_bp != nullptr)
{
return_bp->SetThreadID(m_thread.GetID());
m_backstop_bkpt_id = return_bp->GetID();
@@ -137,7 +135,7 @@ ThreadPlanStepThrough::GetDescription (Stream *s, lldb::DescriptionLevel level)
bool
ThreadPlanStepThrough::ValidatePlan (Stream *error)
{
- return m_sub_plan_sp.get() != NULL;
+ return m_sub_plan_sp.get() != nullptr;
}
bool
@@ -147,10 +145,7 @@ ThreadPlanStepThrough::DoPlanExplainsStop (Event *event_ptr)
// we won't get asked. The only time we would be the one directly asked this question
// is if we hit our backstop breakpoint.
- if (HitOurBackstopBreakpoint())
- return true;
- else
- return false;
+ return HitOurBackstopBreakpoint();
}
bool
@@ -289,4 +284,3 @@ ThreadPlanStepThrough::HitOurBackstopBreakpoint()
}
return false;
}
-
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp
index 4c3d4a6..2581fc7 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepUntil.cpp
@@ -6,17 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//m_should_stop
-
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Target/ThreadPlanStepUntil.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/ThreadPlanStepUntil.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Core/Log.h"
#include "lldb/Target/Process.h"
@@ -68,7 +63,7 @@ ThreadPlanStepUntil::ThreadPlanStepUntil
// TODO: add inline functionality
m_return_addr = return_frame_sp->GetStackID().GetPC();
Breakpoint *return_bp = target_sp->CreateBreakpoint (m_return_addr, true, false).get();
- if (return_bp != NULL)
+ if (return_bp != nullptr)
{
return_bp->SetThreadID(thread_id);
m_return_bp_id = return_bp->GetID();
@@ -82,7 +77,7 @@ ThreadPlanStepUntil::ThreadPlanStepUntil
for (size_t i = 0; i < num_addresses; i++)
{
Breakpoint *until_bp = target_sp->CreateBreakpoint (address_list[i], true, false).get();
- if (until_bp != NULL)
+ if (until_bp != nullptr)
{
until_bp->SetThreadID(thread_id);
m_until_points[address_list[i]] = until_bp->GetID();
@@ -183,122 +178,111 @@ ThreadPlanStepUntil::AnalyzeStop()
{
StopReason reason = stop_info_sp->GetStopReason();
- switch (reason)
+ if (reason == eStopReasonBreakpoint)
{
- case eStopReasonBreakpoint:
+ // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened...
+ BreakpointSiteSP this_site = m_thread.GetProcess()->GetBreakpointSiteList().FindByID (stop_info_sp->GetValue());
+ if (!this_site)
{
- // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened...
- BreakpointSiteSP this_site = m_thread.GetProcess()->GetBreakpointSiteList().FindByID (stop_info_sp->GetValue());
- if (!this_site)
- {
- m_explains_stop = false;
- return;
- }
+ m_explains_stop = false;
+ return;
+ }
- if (this_site->IsBreakpointAtThisSite (m_return_bp_id))
+ if (this_site->IsBreakpointAtThisSite (m_return_bp_id))
+ {
+ // If we are at our "step out" breakpoint, and the stack depth has shrunk, then
+ // this is indeed our stop.
+ // If the stack depth has grown, then we've hit our step out breakpoint recursively.
+ // If we are the only breakpoint at that location, then we do explain the stop, and
+ // we'll just continue.
+ // If there was another breakpoint here, then we don't explain the stop, but we won't
+ // mark ourselves Completed, because maybe that breakpoint will continue, and then
+ // we'll finish the "until".
+ bool done;
+ StackID cur_frame_zero_id;
+
+ done = (m_stack_id < cur_frame_zero_id);
+
+ if (done)
{
- // If we are at our "step out" breakpoint, and the stack depth has shrunk, then
- // this is indeed our stop.
- // If the stack depth has grown, then we've hit our step out breakpoint recursively.
- // If we are the only breakpoint at that location, then we do explain the stop, and
- // we'll just continue.
- // If there was another breakpoint here, then we don't explain the stop, but we won't
- // mark ourselves Completed, because maybe that breakpoint will continue, and then
- // we'll finish the "until".
- bool done;
- StackID cur_frame_zero_id;
-
- if (m_stack_id < cur_frame_zero_id)
- done = true;
- else
- done = false;
-
- if (done)
- {
- m_stepped_out = true;
- SetPlanComplete();
- }
- else
- m_should_stop = false;
-
- if (this_site->GetNumberOfOwners() == 1)
- m_explains_stop = true;
- else
- m_explains_stop = false;
- return;
+ m_stepped_out = true;
+ SetPlanComplete();
}
else
+ m_should_stop = false;
+
+ if (this_site->GetNumberOfOwners() == 1)
+ m_explains_stop = true;
+ else
+ m_explains_stop = false;
+ return;
+ }
+ else
+ {
+ // Check if we've hit one of our "until" breakpoints.
+ until_collection::iterator pos, end = m_until_points.end();
+ for (pos = m_until_points.begin(); pos != end; pos++)
{
- // Check if we've hit one of our "until" breakpoints.
- until_collection::iterator pos, end = m_until_points.end();
- for (pos = m_until_points.begin(); pos != end; pos++)
+ if (this_site->IsBreakpointAtThisSite ((*pos).second))
{
- if (this_site->IsBreakpointAtThisSite ((*pos).second))
+ // If we're at the right stack depth, then we're done.
+
+ bool done;
+ StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
+
+ if (frame_zero_id == m_stack_id)
+ done = true;
+ else if (frame_zero_id < m_stack_id)
+ done = false;
+ else
{
- // If we're at the right stack depth, then we're done.
-
- bool done;
- StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
-
- if (frame_zero_id == m_stack_id)
- done = true;
- else if (frame_zero_id < m_stack_id)
- done = false;
- else
+ StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1);
+
+ // But if we can't even unwind one frame we should just get out of here & stop...
+ if (older_frame_sp)
{
- StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1);
-
- // But if we can't even unwind one frame we should just get out of here & stop...
- if (older_frame_sp)
- {
- const SymbolContext &older_context
- = older_frame_sp->GetSymbolContext(eSymbolContextEverything);
- SymbolContext stack_context;
- m_stack_id.GetSymbolContextScope()->CalculateSymbolContext(&stack_context);
-
- if (older_context == stack_context)
- done = true;
- else
- done = false;
- }
- else
- done = false;
+ const SymbolContext &older_context
+ = older_frame_sp->GetSymbolContext(eSymbolContextEverything);
+ SymbolContext stack_context;
+ m_stack_id.GetSymbolContextScope()->CalculateSymbolContext(&stack_context);
+
+ done = (older_context == stack_context);
}
-
- if (done)
- SetPlanComplete();
- else
- m_should_stop = false;
-
- // Otherwise we've hit this breakpoint recursively. If we're the
- // only breakpoint here, then we do explain the stop, and we'll continue.
- // If not then we should let higher plans handle this stop.
- if (this_site->GetNumberOfOwners() == 1)
- m_explains_stop = true;
else
- {
- m_should_stop = true;
- m_explains_stop = false;
- }
- return;
+ done = false;
+ }
+
+ if (done)
+ SetPlanComplete();
+ else
+ m_should_stop = false;
+
+ // Otherwise we've hit this breakpoint recursively. If we're the
+ // only breakpoint here, then we do explain the stop, and we'll continue.
+ // If not then we should let higher plans handle this stop.
+ if (this_site->GetNumberOfOwners() == 1)
+ m_explains_stop = true;
+ else
+ {
+ m_should_stop = true;
+ m_explains_stop = false;
}
+ return;
}
}
- // If we get here we haven't hit any of our breakpoints, so let the higher
- // plans take care of the stop.
- m_explains_stop = false;
- return;
}
- case eStopReasonWatchpoint:
- case eStopReasonSignal:
- case eStopReasonException:
- case eStopReasonExec:
- case eStopReasonThreadExiting:
- m_explains_stop = false;
- break;
- default:
- m_explains_stop = true;
- break;
+ // If we get here we haven't hit any of our breakpoints, so let the higher
+ // plans take care of the stop.
+ m_explains_stop = false;
+ return;
+ }
+ else if (IsUsuallyUnexplainedStopReason(reason))
+ {
+ m_explains_stop = false;
+ }
+ else
+ {
+ m_explains_stop = true;
}
}
}
@@ -348,14 +332,14 @@ ThreadPlanStepUntil::DoWillResume (StateType resume_state, bool current_plan)
if (target_sp)
{
Breakpoint *return_bp = target_sp->GetBreakpointByID(m_return_bp_id).get();
- if (return_bp != NULL)
+ if (return_bp != nullptr)
return_bp->SetEnabled (true);
until_collection::iterator pos, end = m_until_points.end();
for (pos = m_until_points.begin(); pos != end; pos++)
{
Breakpoint *until_bp = target_sp->GetBreakpointByID((*pos).second).get();
- if (until_bp != NULL)
+ if (until_bp != nullptr)
until_bp->SetEnabled (true);
}
}
@@ -374,14 +358,14 @@ ThreadPlanStepUntil::WillStop ()
if (target_sp)
{
Breakpoint *return_bp = target_sp->GetBreakpointByID(m_return_bp_id).get();
- if (return_bp != NULL)
+ if (return_bp != nullptr)
return_bp->SetEnabled (false);
until_collection::iterator pos, end = m_until_points.end();
for (pos = m_until_points.begin(); pos != end; pos++)
{
Breakpoint *until_bp = target_sp->GetBreakpointByID((*pos).second).get();
- if (until_bp != NULL)
+ if (until_bp != nullptr)
until_bp->SetEnabled (false);
}
}
@@ -391,7 +375,6 @@ ThreadPlanStepUntil::WillStop ()
bool
ThreadPlanStepUntil::MischiefManaged ()
{
-
// I'm letting "PlanExplainsStop" do all the work, and just reporting that here.
bool done = false;
if (IsPlanComplete())
@@ -407,6 +390,4 @@ ThreadPlanStepUntil::MischiefManaged ()
ThreadPlan::MischiefManaged ();
return done;
-
}
-
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp
index 406708f..e3fcbaa 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanTracer.cpp
@@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Target/ThreadPlan.h"
-
// C Includes
-#include <string.h>
// C++ Includes
+#include <cstring>
+
// Other libraries and framework includes
// Project includes
+#include "lldb/Target/ThreadPlan.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
@@ -24,8 +24,8 @@
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
@@ -57,8 +57,7 @@ ThreadPlanTracer::ThreadPlanTracer (Thread &thread) :
Stream *
ThreadPlanTracer::GetLogStream ()
{
-
- if (m_stream_sp.get())
+ if (m_stream_sp)
return m_stream_sp.get();
else
{
@@ -66,7 +65,7 @@ ThreadPlanTracer::GetLogStream ()
if (target_sp)
return target_sp->GetDebugger().GetOutputFile().get();
}
- return NULL;
+ return nullptr;
}
void
@@ -83,7 +82,6 @@ ThreadPlanTracer::Log()
stream->Printf("\n");
stream->Flush();
}
-
}
bool
@@ -92,10 +90,7 @@ ThreadPlanTracer::TracerExplainsStop ()
if (m_enabled && m_single_step)
{
lldb::StopInfoSP stop_info = m_thread.GetStopInfo();
- if (stop_info->GetStopReason() == eStopReasonTrace)
- return true;
- else
- return false;
+ return (stop_info->GetStopReason() == eStopReasonTrace);
}
else
return false;
@@ -122,8 +117,8 @@ ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer (Thread &thread) :
Disassembler *
ThreadPlanAssemblyTracer::GetDisassembler ()
{
- if (m_disassembler_sp.get() == NULL)
- m_disassembler_sp = Disassembler::FindPlugin(m_thread.GetProcess()->GetTarget().GetArchitecture(), NULL, NULL);
+ if (!m_disassembler_sp)
+ m_disassembler_sp = Disassembler::FindPlugin(m_thread.GetProcess()->GetTarget().GetArchitecture(), nullptr, nullptr);
return m_disassembler_sp.get();
}
@@ -135,29 +130,22 @@ ThreadPlanAssemblyTracer::GetIntPointerType()
TargetSP target_sp (m_thread.CalculateTarget());
if (target_sp)
{
- Module *exe_module = target_sp->GetExecutableModulePointer();
-
- if (exe_module)
- {
- m_intptr_type = TypeFromUser(exe_module->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, target_sp->GetArchitecture().GetAddressByteSize() * 8));
- }
+ TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(nullptr, eLanguageTypeC);
+ if (type_system)
+ m_intptr_type = TypeFromUser(type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, target_sp->GetArchitecture().GetAddressByteSize() * 8));
}
}
return m_intptr_type;
}
-
-
-ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer()
-{
-}
+ThreadPlanAssemblyTracer::~ThreadPlanAssemblyTracer() = default;
void
ThreadPlanAssemblyTracer::TracingStarted ()
{
RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
- if (m_register_values.size() == 0)
+ if (m_register_values.empty())
m_register_values.resize (reg_ctx->GetRegisterCount());
}
@@ -214,15 +202,15 @@ ThreadPlanAssemblyTracer::Log ()
const bool show_address = true;
Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
const FormatEntity::Entry *disassemble_format = m_thread.GetProcess()->GetTarget().GetDebugger().GetDisassemblyFormat();
- instruction->Dump (stream,
- max_opcode_byte_size,
- show_address,
- show_bytes,
- NULL,
- NULL,
- NULL,
- disassemble_format,
- 0);
+ instruction->Dump(stream,
+ max_opcode_byte_size,
+ show_address,
+ show_bytes,
+ nullptr,
+ nullptr,
+ nullptr,
+ disassemble_format,
+ 0);
}
}
}
@@ -240,7 +228,7 @@ ThreadPlanAssemblyTracer::Log ()
Value value;
value.SetValueType (Value::eValueTypeScalar);
// value.SetContext (Value::eContextTypeClangType, intptr_type.GetOpaqueQualType());
- value.SetClangType (intptr_type);
+ value.SetCompilerType (intptr_type);
value_list.PushValue (value);
}
@@ -255,8 +243,7 @@ ThreadPlanAssemblyTracer::Log ()
}
}
}
-
-
+
RegisterValue reg_value;
for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount();
reg_num < num_registers;
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadSpec.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadSpec.cpp
index cb54469..f877f52 100644
--- a/contrib/llvm/tools/lldb/source/Target/ThreadSpec.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/ThreadSpec.cpp
@@ -1,4 +1,4 @@
-//===-- ThreadSpec.cpp ----------------------------------------------*- C++ -*-===//
+//===-- ThreadSpec.cpp ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
@@ -21,7 +25,7 @@ ThreadSpec::ThreadSpec() :
{
}
-ThreadSpec::ThreadSpec (const ThreadSpec &rhs) :
+ThreadSpec::ThreadSpec(const ThreadSpec &rhs) :
m_index(rhs.m_index),
m_tid(rhs.m_tid),
m_name(rhs.m_name),
@@ -42,19 +46,13 @@ ThreadSpec::operator=(const ThreadSpec &rhs)
const char *
ThreadSpec::GetName () const
{
- if (m_name.empty())
- return NULL;
- else
- return m_name.c_str();
+ return m_name.empty() ? nullptr : m_name.c_str();
}
const char *
ThreadSpec::GetQueueName () const
{
- if (m_queue_name.empty())
- return NULL;
- else
- return m_queue_name.c_str();
+ return m_queue_name.empty() ? nullptr : m_queue_name.c_str();
}
bool
@@ -66,6 +64,7 @@ ThreadSpec::TIDMatches (Thread &thread) const
lldb::tid_t thread_id = thread.GetID();
return TIDMatches (thread_id);
}
+
bool
ThreadSpec::IndexMatches (Thread &thread) const
{
@@ -74,6 +73,7 @@ ThreadSpec::IndexMatches (Thread &thread) const
uint32_t index = thread.GetIndexID();
return IndexMatches (index);
}
+
bool
ThreadSpec::NameMatches (Thread &thread) const
{
@@ -83,6 +83,7 @@ ThreadSpec::NameMatches (Thread &thread) const
const char *name = thread.GetName();
return NameMatches (name);
}
+
bool
ThreadSpec::QueueNameMatches (Thread &thread) const
{
@@ -96,7 +97,6 @@ ThreadSpec::QueueNameMatches (Thread &thread) const
bool
ThreadSpec::ThreadPassesBasicTests (Thread &thread) const
{
-
if (!HasSpecification())
return true;
@@ -113,7 +113,6 @@ ThreadSpec::ThreadPassesBasicTests (Thread &thread) const
return false;
return true;
-
}
bool
@@ -121,6 +120,7 @@ ThreadSpec::HasSpecification() const
{
return (m_index != UINT32_MAX || m_tid != LLDB_INVALID_THREAD_ID || !m_name.empty() || !m_queue_name.empty());
}
+
void
ThreadSpec::GetDescription (Stream *s, lldb::DescriptionLevel level) const
{
diff --git a/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp b/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp
index 91579e8..8a98c21 100644
--- a/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp
+++ b/contrib/llvm/tools/lldb/source/Target/UnixSignals.cpp
@@ -19,20 +19,21 @@
#include "Plugins/Process/Utility/FreeBSDSignals.h"
#include "Plugins/Process/Utility/LinuxSignals.h"
#include "Plugins/Process/Utility/MipsLinuxSignals.h"
+#include "Plugins/Process/Utility/NetBSDSignals.h"
using namespace lldb_private;
UnixSignals::Signal::Signal
(
const char *name,
- const char *short_name,
bool default_suppress,
bool default_stop,
bool default_notify,
- const char *description
+ const char *description,
+ const char *alias
) :
m_name (name),
- m_short_name (short_name),
+ m_alias (alias),
m_description (),
m_suppress (default_suppress),
m_stop (default_stop),
@@ -63,8 +64,9 @@ UnixSignals::Create(const ArchSpec &arch)
}
case llvm::Triple::FreeBSD:
case llvm::Triple::OpenBSD:
- case llvm::Triple::NetBSD:
return std::make_shared<FreeBSDSignals>();
+ case llvm::Triple::NetBSD:
+ return std::make_shared<NetBSDSignals>();
default:
return std::make_shared<UnixSignals>();
}
@@ -97,39 +99,39 @@ UnixSignals::Reset ()
// order, you can either subclass this class, and use Add & Remove to change them
// or you can subclass and build them afresh in your constructor;
m_signals.clear();
- // SIGNO NAME SHORT NAME SUPPRESS STOP NOTIFY DESCRIPTION
- // ====== ============ ========== ======== ====== ====== ===================================================
- AddSignal (1, "SIGHUP", "HUP", false, true , true , "hangup");
- AddSignal (2, "SIGINT", "INT", true , true , true , "interrupt");
- AddSignal (3, "SIGQUIT", "QUIT", false, true , true , "quit");
- AddSignal (4, "SIGILL", "ILL", false, true , true , "illegal instruction");
- AddSignal (5, "SIGTRAP", "TRAP", true , true , true , "trace trap (not reset when caught)");
- AddSignal (6, "SIGABRT", "ABRT", false, true , true , "abort()");
- AddSignal (7, "SIGEMT", "EMT", false, true , true , "pollable event");
- AddSignal (8, "SIGFPE", "FPE", false, true , true , "floating point exception");
- AddSignal (9, "SIGKILL", "KILL", false, true , true , "kill");
- AddSignal (10, "SIGBUS", "BUS", false, true , true , "bus error");
- AddSignal (11, "SIGSEGV", "SEGV", false, true , true , "segmentation violation");
- AddSignal (12, "SIGSYS", "SYS", false, true , true , "bad argument to system call");
- AddSignal (13, "SIGPIPE", "PIPE", false, true , true , "write on a pipe with no one to read it");
- AddSignal (14, "SIGALRM", "ALRM", false, false, false, "alarm clock");
- AddSignal (15, "SIGTERM", "TERM", false, true , true , "software termination signal from kill");
- AddSignal (16, "SIGURG", "URG", false, false, false, "urgent condition on IO channel");
- AddSignal (17, "SIGSTOP", "STOP", true , true , true , "sendable stop signal not from tty");
- AddSignal (18, "SIGTSTP", "TSTP", false, true , true , "stop signal from tty");
- AddSignal (19, "SIGCONT", "CONT", false, true , true , "continue a stopped process");
- AddSignal (20, "SIGCHLD", "CHLD", false, false, false, "to parent on child stop or exit");
- AddSignal (21, "SIGTTIN", "TTIN", false, true , true , "to readers process group upon background tty read");
- AddSignal (22, "SIGTTOU", "TTOU", false, true , true , "to readers process group upon background tty write");
- AddSignal (23, "SIGIO", "IO", false, false, false, "input/output possible signal");
- AddSignal (24, "SIGXCPU", "XCPU", false, true , true , "exceeded CPU time limit");
- AddSignal (25, "SIGXFSZ", "XFSZ", false, true , true , "exceeded file size limit");
- AddSignal (26, "SIGVTALRM", "VTALRM", false, false, false, "virtual time alarm");
- AddSignal (27, "SIGPROF", "PROF", false, false, false, "profiling time alarm");
- AddSignal (28, "SIGWINCH", "WINCH", false, false, false, "window size changes");
- AddSignal (29, "SIGINFO", "INFO", false, true , true , "information request");
- AddSignal (30, "SIGUSR1", "USR1", false, true , true , "user defined signal 1");
- AddSignal (31, "SIGUSR2", "USR2", false, true , true , "user defined signal 2");
+ // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION
+ // ====== ============ ======== ====== ====== ===================================================
+ AddSignal (1, "SIGHUP", false, true , true , "hangup");
+ AddSignal (2, "SIGINT", true , true , true , "interrupt");
+ AddSignal (3, "SIGQUIT", false, true , true , "quit");
+ AddSignal (4, "SIGILL", false, true , true , "illegal instruction");
+ AddSignal (5, "SIGTRAP", true , true , true , "trace trap (not reset when caught)");
+ AddSignal (6, "SIGABRT", false, true , true , "abort()");
+ AddSignal (7, "SIGEMT", false, true , true , "pollable event");
+ AddSignal (8, "SIGFPE", false, true , true , "floating point exception");
+ AddSignal (9, "SIGKILL", false, true , true , "kill");
+ AddSignal (10, "SIGBUS", false, true , true , "bus error");
+ AddSignal (11, "SIGSEGV", false, true , true , "segmentation violation");
+ AddSignal (12, "SIGSYS", false, true , true , "bad argument to system call");
+ AddSignal (13, "SIGPIPE", false, true , true , "write on a pipe with no one to read it");
+ AddSignal (14, "SIGALRM", false, false, false, "alarm clock");
+ AddSignal (15, "SIGTERM", false, true , true , "software termination signal from kill");
+ AddSignal (16, "SIGURG", false, false, false, "urgent condition on IO channel");
+ AddSignal (17, "SIGSTOP", true , true , true , "sendable stop signal not from tty");
+ AddSignal (18, "SIGTSTP", false, true , true , "stop signal from tty");
+ AddSignal (19, "SIGCONT", false, true , true , "continue a stopped process");
+ AddSignal (20, "SIGCHLD", false, false, false, "to parent on child stop or exit");
+ AddSignal (21, "SIGTTIN", false, true , true , "to readers process group upon background tty read");
+ AddSignal (22, "SIGTTOU", false, true , true , "to readers process group upon background tty write");
+ AddSignal (23, "SIGIO", false, false, false, "input/output possible signal");
+ AddSignal (24, "SIGXCPU", false, true , true , "exceeded CPU time limit");
+ AddSignal (25, "SIGXFSZ", false, true , true , "exceeded file size limit");
+ AddSignal (26, "SIGVTALRM", false, false, false, "virtual time alarm");
+ AddSignal (27, "SIGPROF", false, false, false, "profiling time alarm");
+ AddSignal (28, "SIGWINCH", false, false, false, "window size changes");
+ AddSignal (29, "SIGINFO", false, true , true , "information request");
+ AddSignal (30, "SIGUSR1", false, true , true , "user defined signal 1");
+ AddSignal (31, "SIGUSR2", false, true , true , "user defined signal 2");
}
void
@@ -137,14 +139,14 @@ UnixSignals::AddSignal
(
int signo,
const char *name,
- const char *short_name,
bool default_suppress,
bool default_stop,
bool default_notify,
- const char *description
+ const char *description,
+ const char *alias
)
{
- Signal new_signal (name, short_name, default_suppress, default_stop, default_notify, description);
+ Signal new_signal (name, default_suppress, default_stop, default_notify, description, alias);
m_signals.insert (std::make_pair(signo, new_signal));
}
@@ -173,6 +175,16 @@ UnixSignals::SignalIsValid (int32_t signo) const
return m_signals.find (signo) != m_signals.end();
}
+ConstString
+UnixSignals::GetShortName(ConstString name) const
+{
+ if (name)
+ {
+ char* signame = (char*)(name.AsCString());
+ return ConstString(signame + 3); // Remove "SIG" from name
+ }
+ return name;
+}
int32_t
UnixSignals::GetSignalNumberFromName (const char *name) const
@@ -182,7 +194,8 @@ UnixSignals::GetSignalNumberFromName (const char *name) const
collection::const_iterator pos, end = m_signals.end ();
for (pos = m_signals.begin (); pos != end; pos++)
{
- if ((const_name == pos->second.m_name) || (const_name == pos->second.m_short_name))
+ if ((const_name == pos->second.m_name) || (const_name == pos->second.m_alias) ||
+ (const_name == GetShortName(pos->second.m_name)) || (const_name == GetShortName(pos->second.m_alias)))
return pos->first;
}
diff --git a/contrib/llvm/tools/lldb/source/Utility/ARM64_GCC_Registers.h b/contrib/llvm/tools/lldb/source/Utility/ARM64_ehframe_Registers.h
index 2166b3b..0a5c68c 100644
--- a/contrib/llvm/tools/lldb/source/Utility/ARM64_GCC_Registers.h
+++ b/contrib/llvm/tools/lldb/source/Utility/ARM64_ehframe_Registers.h
@@ -1,4 +1,4 @@
-//===-- ARM64_gdb_Registers.h -------------------------------------*- C++ -*-===//
+//===-- ARM64_ehframe_Registers.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,10 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef utility_ARM64_gdb_Registers_h_
-#define utility_ARM64_gdb_Registers_h_
+#ifndef utility_ARM64_ehframe_Registers_h_
+#define utility_ARM64_ehframe_Registers_h_
-namespace arm64_gcc {
+// The register numbers used in the eh_frame unwind information.
+// Should be the same as DWARF register numbers.
+
+namespace arm64_ehframe {
enum
{
@@ -88,5 +91,5 @@ enum
}
-#endif // utility_ARM64_gdb_Registers_h_
+#endif // utility_ARM64_ehframe_Registers_h_
diff --git a/contrib/llvm/tools/lldb/source/Utility/ARM_GCC_Registers.h b/contrib/llvm/tools/lldb/source/Utility/ARM_GCC_Registers.h
deleted file mode 100644
index 974d01b..0000000
--- a/contrib/llvm/tools/lldb/source/Utility/ARM_GCC_Registers.h
+++ /dev/null
@@ -1,146 +0,0 @@
-//===-- ARM_GCC_Registers.h -------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef utility_ARM_GCC_Registers_h_
-#define utility_ARM_GCC_Registers_h_
-
-enum
-{
- gcc_r0 = 0,
- gcc_r1,
- gcc_r2,
- gcc_r3,
- gcc_r4,
- gcc_r5,
- gcc_r6,
- gcc_r7,
- gcc_r8,
- gcc_r9,
- gcc_r10,
- gcc_r11,
- gcc_r12,
- gcc_sp,
- gcc_lr,
- gcc_pc,
- gcc_cpsr
-};
-
-enum
-{
-// Name Nr Rel Offset Size Type Raw value
- gdb_arm_r0 = 0, // 0 0 4 int32_t
- gdb_arm_r1 = 1, // 1 4 4 int32_t
- gdb_arm_r2 = 2, // 2 8 4 int32_t
- gdb_arm_r3 = 3, // 3 12 4 int32_t
- gdb_arm_r4 = 4, // 4 16 4 int32_t
- gdb_arm_r5 = 5, // 5 20 4 int32_t
- gdb_arm_r6 = 6, // 6 24 4 int32_t
- gdb_arm_r7 = 7, // 7 28 4 int32_t
- gdb_arm_r8 = 8, // 8 32 4 int32_t
- gdb_arm_r9 = 9, // 9 36 4 int32_t
- gdb_arm_r10 = 10, // 10 40 4 int32_t
- gdb_arm_r11 = 11, // 11 44 4 int32_t
- gdb_arm_r12 = 12, // 12 48 4 int32_t
- gdb_arm_sp = 13, // 13 52 4 int32_t
- gdb_arm_lr = 14, // 14 56 4 int32_t
- gdb_arm_pc = 15, // 15 60 4 int32_t
- gdb_arm_f0 = 16, // 16 64 12 _arm_ext_littlebyte_bigword
- gdb_arm_f1 = 17, // 17 76 12 _arm_ext_littlebyte_bigword
- gdb_arm_f2 = 18, // 18 88 12 _arm_ext_littlebyte_bigword
- gdb_arm_f3 = 19, // 19 100 12 _arm_ext_littlebyte_bigword
- gdb_arm_f4 = 20, // 20 112 12 _arm_ext_littlebyte_bigword
- gdb_arm_f5 = 21, // 21 124 12 _arm_ext_littlebyte_bigword
- gdb_arm_f6 = 22, // 22 136 12 _arm_ext_littlebyte_bigword
- gdb_arm_f7 = 23, // 23 148 12 _arm_ext_littlebyte_bigword
- gdb_arm_f8 = 24, // 24 160 12 _arm_ext_littlebyte_bigword
- gdb_arm_cpsr = 25, // 25 172 4 int32_t
- gdb_arm_s0 = 26, // 26 176 4 _ieee_single_little
- gdb_arm_s1 = 27, // 27 180 4 _ieee_single_little
- gdb_arm_s2 = 28, // 28 184 4 _ieee_single_little
- gdb_arm_s3 = 29, // 29 188 4 _ieee_single_little
- gdb_arm_s4 = 30, // 30 192 4 _ieee_single_little
- gdb_arm_s5 = 31, // 31 196 4 _ieee_single_little
- gdb_arm_s6 = 32, // 32 200 4 _ieee_single_little
- gdb_arm_s7 = 33, // 33 204 4 _ieee_single_little
- gdb_arm_s8 = 34, // 34 208 4 _ieee_single_little
- gdb_arm_s9 = 35, // 35 212 4 _ieee_single_little
- gdb_arm_s10 = 36, // 36 216 4 _ieee_single_little
- gdb_arm_s11 = 37, // 37 220 4 _ieee_single_little
- gdb_arm_s12 = 38, // 38 224 4 _ieee_single_little
- gdb_arm_s13 = 39, // 39 228 4 _ieee_single_little
- gdb_arm_s14 = 40, // 40 232 4 _ieee_single_little
- gdb_arm_s15 = 41, // 41 236 4 _ieee_single_little
- gdb_arm_s16 = 42, // 42 240 4 _ieee_single_little
- gdb_arm_s17 = 43, // 43 244 4 _ieee_single_little
- gdb_arm_s18 = 44, // 44 248 4 _ieee_single_little
- gdb_arm_s19 = 45, // 45 252 4 _ieee_single_little
- gdb_arm_s20 = 46, // 46 256 4 _ieee_single_little
- gdb_arm_s21 = 47, // 47 260 4 _ieee_single_little
- gdb_arm_s22 = 48, // 48 264 4 _ieee_single_little
- gdb_arm_s23 = 49, // 49 268 4 _ieee_single_little
- gdb_arm_s24 = 50, // 50 272 4 _ieee_single_little
- gdb_arm_s25 = 51, // 51 276 4 _ieee_single_little
- gdb_arm_s26 = 52, // 52 280 4 _ieee_single_little
- gdb_arm_s27 = 53, // 53 284 4 _ieee_single_little
- gdb_arm_s28 = 54, // 54 288 4 _ieee_single_little
- gdb_arm_s29 = 55, // 55 292 4 _ieee_single_little
- gdb_arm_s30 = 56, // 56 296 4 _ieee_single_little
- gdb_arm_s31 = 57, // 57 300 4 _ieee_single_little
- gdb_arm_fpscr = 58, // 58 304 4 int32_t
- gdb_arm_d16 = 59, // 59 308 8 _ieee_double_little
- gdb_arm_d17 = 60, // 60 316 8 _ieee_double_little
- gdb_arm_d18 = 61, // 61 324 8 _ieee_double_little
- gdb_arm_d19 = 62, // 62 332 8 _ieee_double_little
- gdb_arm_d20 = 63, // 63 340 8 _ieee_double_little
- gdb_arm_d21 = 64, // 64 348 8 _ieee_double_little
- gdb_arm_d22 = 65, // 65 356 8 _ieee_double_little
- gdb_arm_d23 = 66, // 66 364 8 _ieee_double_little
- gdb_arm_d24 = 67, // 67 372 8 _ieee_double_little
- gdb_arm_d25 = 68, // 68 380 8 _ieee_double_little
- gdb_arm_d26 = 69, // 69 388 8 _ieee_double_little
- gdb_arm_d27 = 70, // 70 396 8 _ieee_double_little
- gdb_arm_d28 = 71, // 71 404 8 _ieee_double_little
- gdb_arm_d29 = 72, // 72 412 8 _ieee_double_little
- gdb_arm_d30 = 73, // 73 420 8 _ieee_double_little
- gdb_arm_d31 = 74, // 74 428 8 _ieee_double_little
- gdb_arm_d0 = 75, // 0 436 8 _ieee_double_little
- gdb_arm_d1 = 76, // 1 444 8 _ieee_double_little
- gdb_arm_d2 = 77, // 2 452 8 _ieee_double_little
- gdb_arm_d3 = 78, // 3 460 8 _ieee_double_little
- gdb_arm_d4 = 79, // 4 468 8 _ieee_double_little
- gdb_arm_d5 = 80, // 5 476 8 _ieee_double_little
- gdb_arm_d6 = 81, // 6 484 8 _ieee_double_little
- gdb_arm_d7 = 82, // 7 492 8 _ieee_double_little
- gdb_arm_d8 = 83, // 8 500 8 _ieee_double_little
- gdb_arm_d9 = 84, // 9 508 8 _ieee_double_little
- gdb_arm_d10 = 85, // 10 516 8 _ieee_double_little
- gdb_arm_d11 = 86, // 11 524 8 _ieee_double_little
- gdb_arm_d12 = 87, // 12 532 8 _ieee_double_little
- gdb_arm_d13 = 88, // 13 540 8 _ieee_double_little
- gdb_arm_d14 = 89, // 14 548 8 _ieee_double_little
- gdb_arm_d15 = 90, // 15 556 8 _ieee_double_little
- gdb_arm_q0 = 91, // 16 564 16 _vec128
- gdb_arm_q1 = 92, // 17 580 16 _vec128
- gdb_arm_q2 = 93, // 18 596 16 _vec128
- gdb_arm_q3 = 94, // 19 612 16 _vec128
- gdb_arm_q4 = 95, // 20 628 16 _vec128
- gdb_arm_q5 = 96, // 21 644 16 _vec128
- gdb_arm_q6 = 97, // 22 660 16 _vec128
- gdb_arm_q7 = 98, // 23 676 16 _vec128
- gdb_arm_q8 = 99, // 24 692 16 _vec128
- gdb_arm_q9 = 100, // 25 708 16 _vec128
- gdb_arm_q10 = 101, // 26 724 16 _vec128
- gdb_arm_q11 = 102, // 27 740 16 _vec128
- gdb_arm_q12 = 103, // 28 756 16 _vec128
- gdb_arm_q13 = 104, // 29 772 16 _vec128
- gdb_arm_q14 = 105, // 30 788 16 _vec128
- gdb_arm_q15 = 106 // 31 804 16 _vec128
-};
-#endif // utility_ARM_GCC_Registers_h_
-
diff --git a/contrib/llvm/tools/lldb/source/Utility/ARM_ehframe_Registers.h b/contrib/llvm/tools/lldb/source/Utility/ARM_ehframe_Registers.h
new file mode 100644
index 0000000..7d4951d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Utility/ARM_ehframe_Registers.h
@@ -0,0 +1,38 @@
+//===-- ARM_ehframe_Registers.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_ARM_ehframe_Registers_h_
+#define utility_ARM_ehframe_Registers_h_
+
+// The register numbers used in the eh_frame unwind information.
+// Should be the same as DWARF register numbers.
+
+enum
+{
+ ehframe_r0 = 0,
+ ehframe_r1,
+ ehframe_r2,
+ ehframe_r3,
+ ehframe_r4,
+ ehframe_r5,
+ ehframe_r6,
+ ehframe_r7,
+ ehframe_r8,
+ ehframe_r9,
+ ehframe_r10,
+ ehframe_r11,
+ ehframe_r12,
+ ehframe_sp,
+ ehframe_lr,
+ ehframe_pc,
+ ehframe_cpsr
+};
+
+#endif // utility_ARM_ehframe_Registers_h_
+
diff --git a/contrib/llvm/tools/lldb/source/Utility/ConvertEnum.cpp b/contrib/llvm/tools/lldb/source/Utility/ConvertEnum.cpp
index e108f5e..3231397 100644
--- a/contrib/llvm/tools/lldb/source/Utility/ConvertEnum.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/ConvertEnum.cpp
@@ -63,6 +63,8 @@ lldb_private::GetSectionTypeAsCString(lldb::SectionType sect_type)
return "objc-cfstrings";
case eSectionTypeDWARFDebugAbbrev:
return "dwarf-abbrev";
+ case eSectionTypeDWARFDebugAddr:
+ return "dwarf-addr";
case eSectionTypeDWARFDebugAranges:
return "dwarf-aranges";
case eSectionTypeDWARFDebugFrame:
@@ -75,6 +77,8 @@ lldb_private::GetSectionTypeAsCString(lldb::SectionType sect_type)
return "dwarf-loc";
case eSectionTypeDWARFDebugMacInfo:
return "dwarf-macinfo";
+ case eSectionTypeDWARFDebugMacro:
+ return "dwarf-macro";
case eSectionTypeDWARFDebugPubNames:
return "dwarf-pubnames";
case eSectionTypeDWARFDebugPubTypes:
@@ -83,6 +87,8 @@ lldb_private::GetSectionTypeAsCString(lldb::SectionType sect_type)
return "dwarf-ranges";
case eSectionTypeDWARFDebugStr:
return "dwarf-str";
+ case eSectionTypeDWARFDebugStrOffsets:
+ return "dwarf-str-offsets";
case eSectionTypeELFSymbolTable:
return "elf-symbol-table";
case eSectionTypeELFDynamicSymbols:
@@ -101,8 +107,14 @@ lldb_private::GetSectionTypeAsCString(lldb::SectionType sect_type)
return "apple-objc";
case eSectionTypeEHFrame:
return "eh-frame";
+ case eSectionTypeARMexidx:
+ return "ARM.exidx";
+ case eSectionTypeARMextab:
+ return "ARM.extab";
case eSectionTypeCompactUnwind:
return "compact-unwind";
+ case eSectionTypeGoSymtab:
+ return "go-symtab";
case eSectionTypeOther:
return "regular";
}
diff --git a/contrib/llvm/tools/lldb/source/Utility/JSON.cpp b/contrib/llvm/tools/lldb/source/Utility/JSON.cpp
index 1e16a5a..8b96a06 100644
--- a/contrib/llvm/tools/lldb/source/Utility/JSON.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/JSON.cpp
@@ -12,6 +12,7 @@
#include <limits.h>
#include "lldb/Core/StreamString.h"
#include "lldb/Host/StringConvert.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace lldb_private;
@@ -60,38 +61,66 @@ JSONString::Write (Stream& s)
s.Printf("\"%s\"", json_string_quote_metachars(m_data).c_str());
}
-JSONNumber::JSONNumber () :
- JSONValue(JSONValue::Kind::Number),
- m_is_integer(true),
- m_data(0),
- m_double(0.0)
+uint64_t
+JSONNumber::GetAsUnsigned() const
{
+ switch (m_data_type)
+ {
+ case DataType::Unsigned:
+ return m_data.m_unsigned;
+ case DataType::Signed:
+ return (uint64_t)m_data.m_signed;
+ case DataType::Double:
+ return (uint64_t)m_data.m_double;
+ }
+ llvm_unreachable("Unhandled data type");
}
-JSONNumber::JSONNumber (uint64_t i) :
- JSONValue(JSONValue::Kind::Number),
- m_is_integer(true),
- m_data(i),
- m_double(0.0)
+int64_t
+JSONNumber::GetAsSigned() const
{
+ switch (m_data_type)
+ {
+ case DataType::Unsigned:
+ return (int64_t)m_data.m_unsigned;
+ case DataType::Signed:
+ return m_data.m_signed;
+ case DataType::Double:
+ return (int64_t)m_data.m_double;
+ }
+ llvm_unreachable("Unhandled data type");
}
-
-JSONNumber::JSONNumber (double d) :
- JSONValue(JSONValue::Kind::Number),
- m_is_integer(false),
- m_data(0),
- m_double(d)
+double
+JSONNumber::GetAsDouble() const
{
+ switch (m_data_type)
+ {
+ case DataType::Unsigned:
+ return (double)m_data.m_unsigned;
+ case DataType::Signed:
+ return (double)m_data.m_signed;
+ case DataType::Double:
+ return m_data.m_double;
+ }
+ llvm_unreachable("Unhandled data type");
}
void
JSONNumber::Write (Stream& s)
{
- if (m_is_integer)
- s.Printf("%" PRIu64, m_data);
- else
- s.Printf("%g", m_double);
+ switch (m_data_type)
+ {
+ case DataType::Unsigned:
+ s.Printf("%" PRIu64, m_data.m_unsigned);
+ break;
+ case DataType::Signed:
+ s.Printf("%" PRId64, m_data.m_signed);
+ break;
+ case DataType::Double:
+ s.Printf("%g", m_data.m_double);
+ break;
+ }
}
JSONTrue::JSONTrue () :
@@ -392,7 +421,7 @@ JSONParser::GetToken (std::string &value)
case 'E':
if (exp_index != 0)
{
- error.Printf("error: extra expenent character found at offset %" PRIu64, start_index);
+ error.Printf("error: extra exponent character found at offset %" PRIu64, start_index);
value = std::move(error.GetString());
return Token::Error;
}
@@ -617,10 +646,20 @@ JSONParser::ParseJSONValue ()
case JSONParser::Token::Integer:
{
- bool success = false;
- uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
- if (success)
- return JSONValue::SP(new JSONNumber(uval));
+ if (value.front() == '-')
+ {
+ bool success = false;
+ int64_t sval = StringConvert::ToSInt64(value.c_str(), 0, 0, &success);
+ if (success)
+ return JSONValue::SP(new JSONNumber(sval));
+ }
+ else
+ {
+ bool success = false;
+ uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
+ if (success)
+ return JSONValue::SP(new JSONNumber(uval));
+ }
}
break;
diff --git a/contrib/llvm/tools/lldb/source/Utility/ModuleCache.cpp b/contrib/llvm/tools/lldb/source/Utility/ModuleCache.cpp
index ce0df24..7c57d0b 100644
--- a/contrib/llvm/tools/lldb/source/Utility/ModuleCache.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/ModuleCache.cpp
@@ -9,7 +9,9 @@
#include "ModuleCache.h"
+#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
@@ -27,8 +29,22 @@ using namespace lldb_private;
namespace {
const char* kModulesSubdir = ".cache";
-const char* kLockFileName = ".lock";
+const char* kLockDirName = ".lock";
const char* kTempFileName = ".temp";
+const char* kTempSymFileName = ".symtemp";
+const char* kSymFileExtension = ".sym";
+
+class ModuleLock
+{
+private:
+ File m_file;
+ std::unique_ptr<lldb_private::LockFile> m_lock;
+ FileSpec m_file_spec;
+
+public:
+ ModuleLock (const FileSpec &root_dir_spec, const UUID &uuid, Error& error);
+ void Delete ();
+};
FileSpec
JoinPath (const FileSpec &path1, const char* path2)
@@ -59,13 +75,76 @@ GetModuleDirectory (const FileSpec &root_dir_spec, const UUID &uuid)
return JoinPath (modules_dir_spec, uuid.GetAsString ().c_str ());
}
+FileSpec
+GetSymbolFileSpec(const FileSpec& module_file_spec)
+{
+ return FileSpec((module_file_spec.GetPath() + kSymFileExtension).c_str(), false);
+}
+
+void
+DeleteExistingModule (const FileSpec &root_dir_spec, const FileSpec &sysroot_module_path_spec)
+{
+ Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES));
+ UUID module_uuid;
+ {
+ auto module_sp = std::make_shared<Module>(ModuleSpec (sysroot_module_path_spec));
+ module_uuid = module_sp->GetUUID ();
+ }
+
+ if (!module_uuid.IsValid ())
+ return;
+
+ Error error;
+ ModuleLock lock (root_dir_spec, module_uuid, error);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("Failed to lock module %s: %s",
+ module_uuid.GetAsString ().c_str (),
+ error.AsCString ());
+ }
+
+ auto link_count = FileSystem::GetHardlinkCount (sysroot_module_path_spec);
+ if (link_count == -1)
+ return;
+
+ if (link_count > 2) // module is referred by other hosts.
+ return;
+
+ const auto module_spec_dir = GetModuleDirectory (root_dir_spec, module_uuid);
+ FileSystem::DeleteDirectory (module_spec_dir, true);
+ lock.Delete();
+}
+
+void
+DecrementRefExistingModule (const FileSpec &root_dir_spec, const FileSpec &sysroot_module_path_spec)
+{
+ // Remove $platform/.cache/$uuid folder if nobody else references it.
+ DeleteExistingModule (root_dir_spec, sysroot_module_path_spec);
+
+ // Remove sysroot link.
+ FileSystem::Unlink (sysroot_module_path_spec);
+
+ FileSpec symfile_spec = GetSymbolFileSpec (sysroot_module_path_spec);
+ if (symfile_spec.Exists ()) // delete module's symbol file if exists.
+ FileSystem::Unlink (symfile_spec);
+}
+
Error
-CreateHostSysRootModuleLink (const FileSpec &root_dir_spec, const char *hostname, const FileSpec &platform_module_spec, const FileSpec &local_module_spec)
+CreateHostSysRootModuleLink (const FileSpec &root_dir_spec, const char *hostname,
+ const FileSpec &platform_module_spec,
+ const FileSpec &local_module_spec,
+ bool delete_existing)
{
const auto sysroot_module_path_spec = JoinPath (
JoinPath (root_dir_spec, hostname), platform_module_spec.GetPath ().c_str ());
if (sysroot_module_path_spec.Exists())
- return Error ();
+ {
+ if (!delete_existing)
+ return Error ();
+
+ DecrementRefExistingModule (root_dir_spec, sysroot_module_path_spec);
+ }
const auto error = MakeDirectory (FileSpec (sysroot_module_path_spec.GetDirectory ().AsCString (), false));
if (error.Fail ())
@@ -76,14 +155,48 @@ CreateHostSysRootModuleLink (const FileSpec &root_dir_spec, const char *hostname
} // namespace
+ModuleLock::ModuleLock (const FileSpec &root_dir_spec, const UUID &uuid, Error& error)
+{
+ const auto lock_dir_spec = JoinPath (root_dir_spec, kLockDirName);
+ error = MakeDirectory (lock_dir_spec);
+ if (error.Fail ())
+ return;
+
+ m_file_spec = JoinPath (lock_dir_spec, uuid.GetAsString ().c_str ());
+ m_file.Open (m_file_spec.GetCString (),
+ File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionCloseOnExec);
+ if (!m_file)
+ {
+ error.SetErrorToErrno ();
+ return;
+ }
+
+ m_lock.reset (new lldb_private::LockFile (m_file.GetDescriptor ()));
+ error = m_lock->WriteLock (0, 1);
+ if (error.Fail ())
+ error.SetErrorStringWithFormat ("Failed to lock file: %s", error.AsCString ());
+}
+
+void ModuleLock::Delete ()
+{
+ if (!m_file)
+ return;
+
+ m_file.Close ();
+ FileSystem::Unlink (m_file_spec);
+}
+
+/////////////////////////////////////////////////////////////////////////
+
Error
ModuleCache::Put (const FileSpec &root_dir_spec,
const char *hostname,
const ModuleSpec &module_spec,
- const FileSpec &tmp_file)
+ const FileSpec &tmp_file,
+ const FileSpec &target_file)
{
const auto module_spec_dir = GetModuleDirectory (root_dir_spec, module_spec.GetUUID ());
- const auto module_file_path = JoinPath (module_spec_dir, module_spec.GetFileSpec ().GetFilename ().AsCString ());
+ const auto module_file_path = JoinPath (module_spec_dir, target_file.GetFilename ().AsCString ());
const auto tmp_file_path = tmp_file.GetPath ();
const auto err_code = llvm::sys::fs::rename (tmp_file_path.c_str (), module_file_path.GetPath ().c_str ());
@@ -91,7 +204,7 @@ ModuleCache::Put (const FileSpec &root_dir_spec,
return Error ("Failed to rename file %s to %s: %s",
tmp_file_path.c_str (), module_file_path.GetPath ().c_str (), err_code.message ().c_str ());
- const auto error = CreateHostSysRootModuleLink(root_dir_spec, hostname, module_spec.GetFileSpec(), module_file_path);
+ const auto error = CreateHostSysRootModuleLink(root_dir_spec, hostname, target_file, module_file_path, true);
if (error.Fail ())
return Error ("Failed to create link to %s: %s", module_file_path.GetPath ().c_str (), error.AsCString ());
return Error ();
@@ -122,7 +235,7 @@ ModuleCache::Get (const FileSpec &root_dir_spec,
return Error ("Module %s has invalid file size", module_file_path.GetPath ().c_str ());
// We may have already cached module but downloaded from an another host - in this case let's create a link to it.
- const auto error = CreateHostSysRootModuleLink(root_dir_spec, hostname, module_spec.GetFileSpec(), module_file_path);
+ auto error = CreateHostSysRootModuleLink(root_dir_spec, hostname, module_spec.GetFileSpec(), module_file_path, false);
if (error.Fail ())
return Error ("Failed to create link to %s: %s", module_file_path.GetPath().c_str(), error.AsCString());
@@ -130,9 +243,19 @@ ModuleCache::Get (const FileSpec &root_dir_spec,
cached_module_spec.GetUUID ().Clear (); // Clear UUID since it may contain md5 content hash instead of real UUID.
cached_module_spec.GetFileSpec () = module_file_path;
cached_module_spec.GetPlatformFileSpec () = module_spec.GetFileSpec ();
- cached_module_sp.reset (new Module (cached_module_spec));
- if (did_create_ptr)
- *did_create_ptr = true;
+
+ error = ModuleList::GetSharedModule(cached_module_spec,
+ cached_module_sp,
+ nullptr,
+ nullptr,
+ did_create_ptr,
+ false);
+ if (error.Fail())
+ return error;
+
+ FileSpec symfile_spec = GetSymbolFileSpec(cached_module_sp->GetFileSpec ());
+ if (symfile_spec.Exists ())
+ cached_module_sp->SetSymbolFileFileSpec (symfile_spec);
m_loaded_modules.insert (std::make_pair (module_spec.GetUUID ().GetAsString (), cached_module_sp));
@@ -143,7 +266,8 @@ Error
ModuleCache::GetAndPut (const FileSpec &root_dir_spec,
const char *hostname,
const ModuleSpec &module_spec,
- const Downloader &downloader,
+ const ModuleDownloader &module_downloader,
+ const SymfileDownloader &symfile_downloader,
lldb::ModuleSP &cached_module_sp,
bool *did_create_ptr)
{
@@ -152,18 +276,9 @@ ModuleCache::GetAndPut (const FileSpec &root_dir_spec,
if (error.Fail ())
return error;
- // Open lock file.
- const auto lock_file_spec = JoinPath (module_spec_dir, kLockFileName);
- File lock_file (lock_file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionCloseOnExec);
- if (!lock_file)
- {
- error.SetErrorToErrno ();
- return Error("Failed to open lock file %s: %s", lock_file_spec.GetPath ().c_str (), error.AsCString ());
- }
- LockFile lock (lock_file.GetDescriptor ());
- error = lock.WriteLock (0, 1);
+ ModuleLock lock (root_dir_spec, module_spec.GetUUID (), error);
if (error.Fail ())
- return Error("Failed to lock file %s:%s", lock_file_spec.GetPath ().c_str (), error.AsCString ());
+ return Error("Failed to lock module %s: %s", module_spec.GetUUID ().GetAsString().c_str(), error.AsCString ());
// Check local cache for a module.
error = Get (root_dir_spec, hostname, module_spec, cached_module_sp, did_create_ptr);
@@ -171,16 +286,37 @@ ModuleCache::GetAndPut (const FileSpec &root_dir_spec,
return error;
const auto tmp_download_file_spec = JoinPath (module_spec_dir, kTempFileName);
- error = downloader (module_spec, tmp_download_file_spec);
+ error = module_downloader (module_spec, tmp_download_file_spec);
llvm::FileRemover tmp_file_remover (tmp_download_file_spec.GetPath ().c_str ());
if (error.Fail ())
return Error("Failed to download module: %s", error.AsCString ());
// Put downloaded file into local module cache.
- error = Put (root_dir_spec, hostname, module_spec, tmp_download_file_spec);
+ error = Put (root_dir_spec, hostname, module_spec, tmp_download_file_spec, module_spec.GetFileSpec ());
if (error.Fail ())
return Error ("Failed to put module into cache: %s", error.AsCString ());
tmp_file_remover.releaseFile ();
- return Get (root_dir_spec, hostname, module_spec, cached_module_sp, did_create_ptr);
+ error = Get (root_dir_spec, hostname, module_spec, cached_module_sp, did_create_ptr);
+ if (error.Fail ())
+ return error;
+
+ // Fetching a symbol file for the module
+ const auto tmp_download_sym_file_spec = JoinPath (module_spec_dir, kTempSymFileName);
+ error = symfile_downloader (cached_module_sp, tmp_download_sym_file_spec);
+ llvm::FileRemover tmp_symfile_remover (tmp_download_sym_file_spec.GetPath ().c_str ());
+ if (error.Fail ())
+ // Failed to download a symfile but fetching the module was successful. The module might
+ // contain the neccessary symbols and the debugging is also possible without a symfile.
+ return Error ();
+
+ error = Put (root_dir_spec, hostname, module_spec, tmp_download_sym_file_spec, GetSymbolFileSpec(module_spec.GetFileSpec ()));
+ if (error.Fail ())
+ return Error ("Failed to put symbol file into cache: %s", error.AsCString ());
+
+ tmp_symfile_remover.releaseFile();
+
+ FileSpec symfile_spec = GetSymbolFileSpec (cached_module_sp->GetFileSpec ());
+ cached_module_sp->SetSymbolFileFileSpec (symfile_spec);
+ return Error ();
}
diff --git a/contrib/llvm/tools/lldb/source/Utility/ModuleCache.h b/contrib/llvm/tools/lldb/source/Utility/ModuleCache.h
index 791e2b3..bb9b308 100644
--- a/contrib/llvm/tools/lldb/source/Utility/ModuleCache.h
+++ b/contrib/llvm/tools/lldb/source/Utility/ModuleCache.h
@@ -46,13 +46,15 @@ class UUID;
class ModuleCache
{
public:
- using Downloader = std::function<Error (const ModuleSpec&, const FileSpec&)>;
+ using ModuleDownloader = std::function<Error (const ModuleSpec&, const FileSpec&)>;
+ using SymfileDownloader = std::function<Error (const lldb::ModuleSP&, const FileSpec&)>;
Error
GetAndPut(const FileSpec &root_dir_spec,
const char *hostname,
const ModuleSpec &module_spec,
- const Downloader &downloader,
+ const ModuleDownloader &module_downloader,
+ const SymfileDownloader &symfile_downloader,
lldb::ModuleSP &cached_module_sp,
bool *did_create_ptr);
@@ -61,7 +63,8 @@ private:
Put (const FileSpec &root_dir_spec,
const char *hostname,
const ModuleSpec &module_spec,
- const FileSpec &tmp_file);
+ const FileSpec &tmp_file,
+ const FileSpec &target_file);
Error
Get (const FileSpec &root_dir_spec,
diff --git a/contrib/llvm/tools/lldb/source/Utility/SharingPtr.cpp b/contrib/llvm/tools/lldb/source/Utility/SharingPtr.cpp
index 4083975..7f12785 100644
--- a/contrib/llvm/tools/lldb/source/Utility/SharingPtr.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/SharingPtr.cpp
@@ -11,7 +11,7 @@
#if defined (ENABLE_SP_LOGGING)
-// If ENABLE_SP_LOGGING is defined, then log all shared pointer assignements
+// If ENABLE_SP_LOGGING is defined, then log all shared pointer assignments
// and allow them to be queried using a pointer by a call to:
#include <execinfo.h>
#include <map>
diff --git a/contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp b/contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp
index 6302c03..ae92704 100644
--- a/contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/StringExtractor.cpp
@@ -120,19 +120,30 @@ StringExtractor::DecodeHexU8()
//----------------------------------------------------------------------
// Extract an unsigned character from two hex ASCII chars in the packet
-// string
+// string, or return fail_value on failure
//----------------------------------------------------------------------
uint8_t
StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
{
+ // On success, fail_value will be overwritten with the next
+ // character in the stream
+ GetHexU8Ex(fail_value, set_eof_on_fail);
+ return fail_value;
+}
+
+bool
+StringExtractor::GetHexU8Ex (uint8_t& ch, bool set_eof_on_fail)
+{
int byte = DecodeHexU8();
if (byte == -1)
{
if (set_eof_on_fail || m_index >= m_packet.size())
m_index = UINT64_MAX;
- return fail_value;
+ // ch should not be changed in case of failure
+ return false;
}
- return (uint8_t)byte;
+ ch = (uint8_t)byte;
+ return true;
}
uint32_t
diff --git a/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.cpp
index 17ee0b6..56df0be 100644
--- a/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -163,12 +163,12 @@ StringExtractorGDBRemote::GetServerPacketType () const
case 'K':
if (PACKET_STARTS_WITH ("qKillSpawnedProcess")) return eServerPacketType_qKillSpawnedProcess;
break;
-
+
case 'L':
if (PACKET_STARTS_WITH ("qLaunchGDBServer")) return eServerPacketType_qLaunchGDBServer;
if (PACKET_MATCHES ("qLaunchSuccess")) return eServerPacketType_qLaunchSuccess;
break;
-
+
case 'M':
if (PACKET_STARTS_WITH ("qMemoryRegionInfo:")) return eServerPacketType_qMemoryRegionInfo;
if (PACKET_MATCHES ("qMemoryRegionInfo")) return eServerPacketType_qMemoryRegionInfoSupported;
@@ -182,7 +182,11 @@ StringExtractorGDBRemote::GetServerPacketType () const
if (PACKET_STARTS_WITH ("qPlatform_chmod:")) return eServerPacketType_qPlatform_chmod;
if (PACKET_MATCHES ("qProcessInfo")) return eServerPacketType_qProcessInfo;
break;
-
+
+ case 'Q':
+ if (PACKET_MATCHES ("qQueryGDBServer")) return eServerPacketType_qQueryGDBServer;
+ break;
+
case 'R':
if (PACKET_STARTS_WITH ("qRcmd,")) return eServerPacketType_qRcmd;
if (PACKET_STARTS_WITH ("qRegisterInfo")) return eServerPacketType_qRegisterInfo;
@@ -221,7 +225,9 @@ StringExtractorGDBRemote::GetServerPacketType () const
break;
case 'j':
- if (PACKET_MATCHES("jSignalInfo")) return eServerPacketType_jSignalsInfo;
+ if (PACKET_MATCHES("jSignalsInfo")) return eServerPacketType_jSignalsInfo;
+ if (PACKET_MATCHES("jThreadsInfo")) return eServerPacketType_jThreadsInfo;
+
case 'v':
if (PACKET_STARTS_WITH("vFile:"))
@@ -308,6 +314,12 @@ StringExtractorGDBRemote::GetServerPacketType () const
case 'S':
return eServerPacketType_S;
+ case 'x':
+ return eServerPacketType_x;
+
+ case 'X':
+ return eServerPacketType_X;
+
case 'T':
return eServerPacketType_T;
diff --git a/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.h b/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.h
index 475b5a8..7e2f1e7 100644
--- a/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.h
+++ b/contrib/llvm/tools/lldb/source/Utility/StringExtractorGDBRemote.h
@@ -54,6 +54,7 @@ public:
eServerPacketType_qGroupName,
eServerPacketType_qHostInfo,
eServerPacketType_qLaunchGDBServer,
+ eServerPacketType_qQueryGDBServer,
eServerPacketType_qKillSpawnedProcess,
eServerPacketType_qLaunchSuccess,
eServerPacketType_qModuleInfo,
@@ -97,6 +98,7 @@ public:
eServerPacketType_QSyncThreadState,
eServerPacketType_QThreadSuffixSupported,
+ eServerPacketType_jThreadsInfo,
eServerPacketType_qsThreadInfo,
eServerPacketType_qfThreadInfo,
eServerPacketType_qGetPid,
@@ -144,6 +146,8 @@ public:
eServerPacketType_s,
eServerPacketType_S,
eServerPacketType_T,
+ eServerPacketType_x,
+ eServerPacketType_X,
eServerPacketType_Z,
eServerPacketType_z,
diff --git a/contrib/llvm/tools/lldb/source/Utility/TaskPool.cpp b/contrib/llvm/tools/lldb/source/Utility/TaskPool.cpp
new file mode 100644
index 0000000..75fe59d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Utility/TaskPool.cpp
@@ -0,0 +1,88 @@
+//===--------------------- TaskPool.cpp -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/TaskPool.h"
+
+namespace
+{
+ class TaskPoolImpl
+ {
+ public:
+ static TaskPoolImpl&
+ GetInstance();
+
+ void
+ AddTask(std::function<void()>&& task_fn);
+
+ private:
+ TaskPoolImpl();
+
+ static void
+ Worker(TaskPoolImpl* pool);
+
+ std::queue<std::function<void()>> m_tasks;
+ std::mutex m_tasks_mutex;
+ uint32_t m_thread_count;
+ };
+
+} // end of anonymous namespace
+
+TaskPoolImpl&
+TaskPoolImpl::GetInstance()
+{
+ static TaskPoolImpl g_task_pool_impl;
+ return g_task_pool_impl;
+}
+
+void
+TaskPool::AddTaskImpl(std::function<void()>&& task_fn)
+{
+ TaskPoolImpl::GetInstance().AddTask(std::move(task_fn));
+}
+
+TaskPoolImpl::TaskPoolImpl() :
+ m_thread_count(0)
+{
+}
+
+void
+TaskPoolImpl::AddTask(std::function<void()>&& task_fn)
+{
+ static const uint32_t max_threads = std::thread::hardware_concurrency();
+
+ std::unique_lock<std::mutex> lock(m_tasks_mutex);
+ m_tasks.emplace(std::move(task_fn));
+ if (m_thread_count < max_threads)
+ {
+ m_thread_count++;
+ lock.unlock();
+
+ std::thread (Worker, this).detach();
+ }
+}
+
+void
+TaskPoolImpl::Worker(TaskPoolImpl* pool)
+{
+ while (true)
+ {
+ std::unique_lock<std::mutex> lock(pool->m_tasks_mutex);
+ if (pool->m_tasks.empty())
+ {
+ pool->m_thread_count--;
+ break;
+ }
+
+ std::function<void()> f = pool->m_tasks.front();
+ pool->m_tasks.pop();
+ lock.unlock();
+
+ f();
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Utility/UriParser.cpp b/contrib/llvm/tools/lldb/source/Utility/UriParser.cpp
index 86020d1..77e16b0 100644
--- a/contrib/llvm/tools/lldb/source/Utility/UriParser.cpp
+++ b/contrib/llvm/tools/lldb/source/Utility/UriParser.cpp
@@ -10,10 +10,10 @@
#include "Utility/UriParser.h"
// C Includes
-#include <stdlib.h>
-#include <stdio.h>
// C++ Includes
+#include <cstring>
+
// Other libraries and framework includes
// Project includes
#include "lldb/Host/StringConvert.h"
@@ -24,43 +24,71 @@ using namespace lldb_private;
// UriParser::Parse
//----------------------------------------------------------------------
bool
-UriParser::Parse(const char* uri,
- std::string& scheme,
- std::string& hostname,
- int& port,
- std::string& path
- )
+UriParser::Parse(const std::string& uri,
+ std::string& scheme,
+ std::string& hostname,
+ int& port,
+ std::string& path)
{
- char scheme_buf[100] = {0};
- char hostname_buf[256] = {0};
- char port_buf[11] = {0}; // 10==strlen(2^32)
- char path_buf[2049] = {'/', 0};
-
- bool ok = false;
- if (4==sscanf(uri, "%99[^:/]://%255[^/:]:%10[^/]/%2047s", scheme_buf, hostname_buf, port_buf, path_buf+1)) { ok = true; }
- else if (3==sscanf(uri, "%99[^:/]://%255[^/:]:%10[^/]", scheme_buf, hostname_buf, port_buf)) { ok = true; }
- else if (3==sscanf(uri, "%99[^:/]://%255[^/]/%2047s", scheme_buf, hostname_buf, path_buf+1)) { ok = true; }
- else if (2==sscanf(uri, "%99[^:/]://%255[^/]", scheme_buf, hostname_buf)) { ok = true; }
+ std::string tmp_scheme, tmp_hostname, tmp_port, tmp_path;
+
+ static const char* kSchemeSep = "://";
+ auto pos = uri.find(kSchemeSep);
+ if (pos == std::string::npos)
+ return false;
+
+ // Extract path.
+ tmp_scheme = uri.substr(0, pos);
+ auto host_pos = pos + strlen(kSchemeSep);
+ auto path_pos = uri.find('/', host_pos);
+ if (path_pos != std::string::npos)
+ tmp_path = uri.substr(path_pos);
+ else
+ tmp_path = "/";
+
+ auto host_port = uri.substr(
+ host_pos, ((path_pos != std::string::npos) ? path_pos : uri.size()) - host_pos);
+
+ // Extract hostname
+ if (host_port[0] == '[')
+ {
+ // hostname is enclosed with square brackets.
+ pos = host_port.find(']');
+ if (pos == std::string::npos)
+ return false;
+
+ tmp_hostname = host_port.substr(1, pos - 1);
+ host_port.erase(0, pos + 1);
+ }
+ else
+ {
+ pos = host_port.find(':');
+ tmp_hostname = host_port.substr(0, (pos != std::string::npos) ? pos : host_port.size());
+ host_port.erase(0, (pos != std::string::npos) ? pos : host_port.size());
+ }
- bool success = false;
- int port_tmp = -1;
- if (port_buf[0])
+ // Extract port
+ tmp_port = host_port;
+ if (!tmp_port.empty())
{
- port_tmp = StringConvert::ToUInt32(port_buf, UINT32_MAX, 10, &success);
+ if (tmp_port[0] != ':')
+ return false;
+ tmp_port = tmp_port.substr(1);
+ bool success = false;
+ auto port_tmp = StringConvert::ToUInt32(tmp_port.c_str(), UINT32_MAX, 10, &success);
if (!success || port_tmp > 65535)
{
// there are invalid characters in port_buf
return false;
}
- }
-
- if (ok)
- {
- scheme.assign(scheme_buf);
- hostname.assign(hostname_buf);
port = port_tmp;
- path.assign(path_buf);
}
- return ok;
+ else
+ port = -1;
+
+ scheme = tmp_scheme;
+ hostname = tmp_hostname;
+ path = tmp_path;
+ return true;
}
diff --git a/contrib/llvm/tools/lldb/source/Utility/UriParser.h b/contrib/llvm/tools/lldb/source/Utility/UriParser.h
index fb129ea..8cbaaea 100644
--- a/contrib/llvm/tools/lldb/source/Utility/UriParser.h
+++ b/contrib/llvm/tools/lldb/source/Utility/UriParser.h
@@ -28,12 +28,12 @@ public:
//
// if the url is invalid, function returns false and
// output parameters remain unchanged
- static bool Parse(const char* uri,
- std::string& scheme,
- std::string& hostname,
- int& port,
- std::string& path
- );
+ static bool
+ Parse(const std::string& uri,
+ std::string& scheme,
+ std::string& hostname,
+ int& port,
+ std::string& path);
};
#endif // utility_UriParser_h_
diff --git a/contrib/llvm/tools/lldb/source/lldb.cpp b/contrib/llvm/tools/lldb/source/lldb.cpp
index 89bb485..1e02d2a 100644
--- a/contrib/llvm/tools/lldb/source/lldb.cpp
+++ b/contrib/llvm/tools/lldb/source/lldb.cpp
@@ -67,7 +67,7 @@ lldb_private::GetVersion ()
return g_version_string;
#else
- // On Linux/FreeBSD/Windows, report a version number in the same style as the clang tool.
+ // On platforms other than Darwin, report a version number in the same style as the clang tool.
static std::string g_version_str;
if (g_version_str.empty())
{
diff --git a/contrib/llvm/tools/lldb/tools/argdumper/exports b/contrib/llvm/tools/lldb/tools/argdumper/argdumper.exports
index e69de29..e69de29 100644
--- a/contrib/llvm/tools/lldb/tools/argdumper/exports
+++ b/contrib/llvm/tools/lldb/tools/argdumper/argdumper.exports
diff --git a/contrib/llvm/tools/lldb/tools/driver/Driver.cpp b/contrib/llvm/tools/lldb/tools/driver/Driver.cpp
index 3b2eadd..0b72e22 100644
--- a/contrib/llvm/tools/lldb/tools/driver/Driver.cpp
+++ b/contrib/llvm/tools/lldb/tools/driver/Driver.cpp
@@ -35,6 +35,7 @@
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBHostOS.h"
+#include "lldb/API/SBLanguageRuntime.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBTarget.h"
@@ -132,6 +133,10 @@ static OptionDefinition g_options[] =
"extensions have been implemented." },
{ LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone,
"Tells the debugger to print out extra information for debugging itself." },
+ { LLDB_OPT_SET_7, true , "repl" , 'r', optional_argument, 0, eArgTypeNone,
+ "Runs lldb in REPL mode with a stub process." },
+ { LLDB_OPT_SET_7, true , "repl-language" , 'R', required_argument, 0, eArgTypeNone,
+ "Chooses the language for the REPL." },
{ 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL }
};
@@ -341,21 +346,27 @@ ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
indent_level, "");
indent_level += 5;
- fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed from left to right in order, "
- "\n%*swith the source files and commands interleaved. The same is true of the \"-S\" and \"-O\" options."
- "\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out."
- "\n%*sThe order of the file specifiers (\"-c\", \"-f\", etc.) is not significant in this regard.\n\n",
+ fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed"
+ "\n%*sfrom left to right in order, with the source files and commands"
+ "\n%*sinterleaved. The same is true of the \"-S\" and \"-O\" options. The before"
+ "\n%*sfile and after file sets can intermixed freely, the command parser will"
+ "\n%*ssort them out. The order of the file specifiers (\"-c\", \"-f\", etc.) is"
+ "\n%*snot significant in this regard.\n\n",
indent_level, "",
indent_level, "",
indent_level, "",
+ indent_level, "",
+ indent_level, "",
indent_level, "");
- fprintf (out, "\n%*sIf you don't provide -f then the first argument will be the file to be debugged"
- "\n%*swhich means that '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
- "\n%*sBut remember to end the options with \"--\" if any of your arguments have a \"-\" in them.\n\n",
+ fprintf (out, "\n%*sIf you don't provide -f then the first argument will be the file to be"
+ "\n%*sdebugged which means that '%s -- <filename> [<ARG1> [<ARG2>]]' also"
+ "\n%*sworks. But remember to end the options with \"--\" if any of your"
+ "\n%*sarguments have a \"-\" in them.\n\n",
indent_level, "",
indent_level, "",
name,
+ indent_level, "",
indent_level, "");
}
@@ -408,6 +419,9 @@ Driver::OptionData::OptionData () :
m_print_python_path (false),
m_print_help (false),
m_wait_for(false),
+ m_repl (false),
+ m_repl_lang (eLanguageTypeUnknown),
+ m_repl_options (),
m_process_name(),
m_process_pid(LLDB_INVALID_PROCESS_ID),
m_use_external_editor(false),
@@ -769,6 +783,23 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting)
optarg);
}
break;
+
+ case 'r':
+ m_option_data.m_repl = true;
+ if (optarg && optarg[0])
+ m_option_data.m_repl_options = optarg;
+ else
+ m_option_data.m_repl_options.clear();
+ break;
+
+ case 'R':
+ m_option_data.m_repl_lang = SBLanguageRuntime::GetLanguageTypeFromString (optarg);
+ if (m_option_data.m_repl_lang == eLanguageTypeUnknown)
+ {
+ error.SetErrorStringWithFormat ("Unrecognized language name: \"%s\"", optarg);
+ }
+ break;
+
case 's':
m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, true, error);
break;
@@ -1056,96 +1087,114 @@ Driver::MainLoop ()
bool handle_events = true;
bool spawn_thread = false;
- // Check if we have any data in the commands stream, and if so, save it to a temp file
- // so we can then run the command interpreter using the file contents.
- const char *commands_data = commands_stream.GetData();
- const size_t commands_size = commands_stream.GetSize();
-
- // The command file might have requested that we quit, this variable will track that.
- bool quit_requested = false;
- bool stopped_for_crash = false;
- if (commands_data && commands_size)
+ if (m_option_data.m_repl)
{
- int initial_commands_fds[2];
- bool success = true;
- FILE *commands_file = PrepareCommandsForSourcing (commands_data, commands_size, initial_commands_fds);
- if (commands_file)
+ const char *repl_options = NULL;
+ if (!m_option_data.m_repl_options.empty())
+ repl_options = m_option_data.m_repl_options.c_str();
+ SBError error (m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options));
+ if (error.Fail())
{
- m_debugger.SetInputFileHandle (commands_file, true);
-
- // Set the debugger into Sync mode when running the command file. Otherwise command files
- // that run the target won't run in a sensible way.
- bool old_async = m_debugger.GetAsync();
- m_debugger.SetAsync(false);
- int num_errors;
-
- SBCommandInterpreterRunOptions options;
- options.SetStopOnError (true);
- if (m_option_data.m_batch)
- options.SetStopOnCrash (true);
-
- m_debugger.RunCommandInterpreter(handle_events,
- spawn_thread,
- options,
- num_errors,
- quit_requested,
- stopped_for_crash);
-
- if (m_option_data.m_batch && stopped_for_crash && !m_option_data.m_after_crash_commands.empty())
+ const char *error_cstr = error.GetCString();
+ if (error_cstr && error_cstr[0])
+ fprintf (stderr, "error: %s\n", error_cstr);
+ else
+ fprintf (stderr, "error: %u\n", error.GetError());
+ }
+ }
+ else
+ {
+ // Check if we have any data in the commands stream, and if so, save it to a temp file
+ // so we can then run the command interpreter using the file contents.
+ const char *commands_data = commands_stream.GetData();
+ const size_t commands_size = commands_stream.GetSize();
+
+ // The command file might have requested that we quit, this variable will track that.
+ bool quit_requested = false;
+ bool stopped_for_crash = false;
+ if (commands_data && commands_size)
+ {
+ int initial_commands_fds[2];
+ bool success = true;
+ FILE *commands_file = PrepareCommandsForSourcing (commands_data, commands_size, initial_commands_fds);
+ if (commands_file)
{
- int crash_command_fds[2];
- SBStream crash_commands_stream;
- WriteCommandsForSourcing (eCommandPlacementAfterCrash, crash_commands_stream);
- const char *crash_commands_data = crash_commands_stream.GetData();
- const size_t crash_commands_size = crash_commands_stream.GetSize();
- commands_file = PrepareCommandsForSourcing (crash_commands_data, crash_commands_size, crash_command_fds);
- if (commands_file)
+ m_debugger.SetInputFileHandle (commands_file, true);
+
+ // Set the debugger into Sync mode when running the command file. Otherwise command files
+ // that run the target won't run in a sensible way.
+ bool old_async = m_debugger.GetAsync();
+ m_debugger.SetAsync(false);
+ int num_errors;
+
+ SBCommandInterpreterRunOptions options;
+ options.SetStopOnError (true);
+ if (m_option_data.m_batch)
+ options.SetStopOnCrash (true);
+
+ m_debugger.RunCommandInterpreter(handle_events,
+ spawn_thread,
+ options,
+ num_errors,
+ quit_requested,
+ stopped_for_crash);
+
+ if (m_option_data.m_batch && stopped_for_crash && !m_option_data.m_after_crash_commands.empty())
{
- bool local_quit_requested;
- bool local_stopped_for_crash;
- m_debugger.SetInputFileHandle (commands_file, true);
-
- m_debugger.RunCommandInterpreter(handle_events,
- spawn_thread,
- options,
- num_errors,
- local_quit_requested,
- local_stopped_for_crash);
- if (local_quit_requested)
- quit_requested = true;
+ int crash_command_fds[2];
+ SBStream crash_commands_stream;
+ WriteCommandsForSourcing (eCommandPlacementAfterCrash, crash_commands_stream);
+ const char *crash_commands_data = crash_commands_stream.GetData();
+ const size_t crash_commands_size = crash_commands_stream.GetSize();
+ commands_file = PrepareCommandsForSourcing (crash_commands_data, crash_commands_size, crash_command_fds);
+ if (commands_file)
+ {
+ bool local_quit_requested;
+ bool local_stopped_for_crash;
+ m_debugger.SetInputFileHandle (commands_file, true);
+
+ m_debugger.RunCommandInterpreter(handle_events,
+ spawn_thread,
+ options,
+ num_errors,
+ local_quit_requested,
+ local_stopped_for_crash);
+ if (local_quit_requested)
+ quit_requested = true;
+ }
}
+ m_debugger.SetAsync(old_async);
}
- m_debugger.SetAsync(old_async);
- }
- else
- success = false;
+ else
+ success = false;
- // Close any pipes that we still have ownership of
- CleanupAfterCommandSourcing(initial_commands_fds);
+ // Close any pipes that we still have ownership of
+ CleanupAfterCommandSourcing(initial_commands_fds);
- // Something went wrong with command pipe
- if (!success)
- {
- exit(1);
- }
+ // Something went wrong with command pipe
+ if (!success)
+ {
+ exit(1);
+ }
- }
+ }
- // Now set the input file handle to STDIN and run the command
- // interpreter again in interactive mode and let the debugger
- // take ownership of stdin
+ // Now set the input file handle to STDIN and run the command
+ // interpreter again in interactive mode and let the debugger
+ // take ownership of stdin
- bool go_interactive = true;
- if (quit_requested)
- go_interactive = false;
- else if (m_option_data.m_batch && !stopped_for_crash)
- go_interactive = false;
+ bool go_interactive = true;
+ if (quit_requested)
+ go_interactive = false;
+ else if (m_option_data.m_batch && !stopped_for_crash)
+ go_interactive = false;
- if (go_interactive)
- {
- m_debugger.SetInputFileHandle (stdin, true);
- m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
+ if (go_interactive)
+ {
+ m_debugger.SetInputFileHandle (stdin, true);
+ m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
+ }
}
reset_stdin_termios();
diff --git a/contrib/llvm/tools/lldb/tools/driver/Driver.h b/contrib/llvm/tools/lldb/tools/driver/Driver.h
index b1e536d..639ac41 100644
--- a/contrib/llvm/tools/lldb/tools/driver/Driver.h
+++ b/contrib/llvm/tools/lldb/tools/driver/Driver.h
@@ -105,6 +105,9 @@ public:
bool m_print_python_path;
bool m_print_help;
bool m_wait_for;
+ bool m_repl;
+ lldb::LanguageType m_repl_lang;
+ std::string m_repl_options;
std::string m_process_name;
lldb::pid_t m_process_pid;
bool m_use_external_editor; // FIXME: When we have set/show variables we can remove this from here.
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgContext.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgContext.cpp
index 7a1bbf7..8ce5bfb 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgContext.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgContext.cpp
@@ -1,4 +1,4 @@
-//===-- MICmnArgContext.cpp -------------------------------------*- C++ -*-===//
+//===-- MICmdArgContext.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,7 +17,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgContext::CMICmdArgContext(void)
+CMICmdArgContext::CMICmdArgContext()
{
}
@@ -40,7 +40,7 @@ CMICmdArgContext::CMICmdArgContext(const CMIUtilString &vrCmdLineArgsRaw)
// Return: None.
// Throws: None.
//--
-CMICmdArgContext::~CMICmdArgContext(void)
+CMICmdArgContext::~CMICmdArgContext()
{
}
@@ -52,7 +52,7 @@ CMICmdArgContext::~CMICmdArgContext(void)
// Throws: None.
//--
const CMIUtilString &
-CMICmdArgContext::GetArgsLeftToParse(void) const
+CMICmdArgContext::GetArgsLeftToParse() const
{
return m_strCmdArgsAndOptions;
}
@@ -65,7 +65,7 @@ CMICmdArgContext::GetArgsLeftToParse(void) const
// Throws: None.
//--
bool
-CMICmdArgContext::IsEmpty(void) const
+CMICmdArgContext::IsEmpty() const
{
return m_strCmdArgsAndOptions.empty();
}
@@ -130,7 +130,7 @@ CMICmdArgContext::RemoveArg(const CMIUtilString &vArg)
}
const size_t nPosEnd = nLen + nExtraSpace;
- m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.replace(nPos, nPosEnd, "").c_str();
+ m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.replace(nPos, nPosEnd, "");
m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.Trim();
return MIstatus::success;
@@ -149,9 +149,9 @@ CMICmdArgContext::RemoveArg(const CMIUtilString &vArg)
// Throws: None.
//--
bool
-CMICmdArgContext::RemoveArgAtPos(const CMIUtilString &vArg, const MIuint nArgIndex)
+CMICmdArgContext::RemoveArgAtPos(const CMIUtilString &vArg, size_t nArgIndex)
{
- MIuint nWordIndex = 0;
+ size_t nWordIndex = 0;
CMIUtilString strBuildContextUp;
const CMIUtilString::VecString_t vecWords(GetArgs());
const bool bSpaceRequired(GetNumberArgsPresent() > 2);
@@ -202,11 +202,11 @@ CMICmdArgContext::RemoveArgAtPos(const CMIUtilString &vArg, const MIuint nArgInd
// Details: Retrieve number of arguments or options present in the command's option text.
// Type: Method.
// Args: None.
-// Return: MIuint - 0 to n arguments present.
+// Return: size_t - 0 to n arguments present.
// Throws: None.
//--
-MIuint
-CMICmdArgContext::GetNumberArgsPresent(void) const
+size_t
+CMICmdArgContext::GetNumberArgsPresent() const
{
CMIUtilString::VecString_t vecOptions;
return m_strCmdArgsAndOptions.SplitConsiderQuotes(" ", vecOptions);
@@ -220,7 +220,7 @@ CMICmdArgContext::GetNumberArgsPresent(void) const
// Throws: None.
//--
CMIUtilString::VecString_t
-CMICmdArgContext::GetArgs(void) const
+CMICmdArgContext::GetArgs() const
{
CMIUtilString::VecString_t vecOptions;
m_strCmdArgsAndOptions.SplitConsiderQuotes(" ", vecOptions);
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgContext.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgContext.h
index baeb923..2b32c4b 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgContext.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgContext.h
@@ -16,30 +16,27 @@
// Details: MI common code class. Command arguments and options string. Holds
// the context string.
// Based on the Interpreter pattern.
-// Gotchas: None.
-// Authors: Illya Rudkin 14/04/2014.
-// Changes: None.
//--
class CMICmdArgContext
{
// Methods:
public:
- /* ctor */ CMICmdArgContext(void);
+ /* ctor */ CMICmdArgContext();
/* ctor */ CMICmdArgContext(const CMIUtilString &vrCmdLineArgsRaw);
//
- const CMIUtilString &GetArgsLeftToParse(void) const;
- MIuint GetNumberArgsPresent(void) const;
- CMIUtilString::VecString_t GetArgs(void) const;
- bool IsEmpty(void) const;
+ const CMIUtilString &GetArgsLeftToParse() const;
+ size_t GetNumberArgsPresent() const;
+ CMIUtilString::VecString_t GetArgs() const;
+ bool IsEmpty() const;
bool RemoveArg(const CMIUtilString &vArg);
- bool RemoveArgAtPos(const CMIUtilString &vArg, const MIuint nArgIndex);
+ bool RemoveArgAtPos(const CMIUtilString &vArg, size_t nArgIndex);
//
CMICmdArgContext &operator=(const CMICmdArgContext &vOther);
// Overridden:
public:
// From CMIUtilString
- /* dtor */ virtual ~CMICmdArgContext(void);
+ /* dtor */ virtual ~CMICmdArgContext();
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgSet.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgSet.cpp
index 3d63a61..9fe5b2d 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgSet.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgSet.cpp
@@ -20,7 +20,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgSet::CMICmdArgSet(void)
+CMICmdArgSet::CMICmdArgSet()
: m_bIsArgsPresentButNotHandledByCmd(false)
, m_constStrCommaSpc(", ")
{
@@ -33,7 +33,7 @@ CMICmdArgSet::CMICmdArgSet(void)
// Return: None.
// Throws: None.
//--
-CMICmdArgSet::~CMICmdArgSet(void)
+CMICmdArgSet::~CMICmdArgSet()
{
// Tidy up
Destroy();
@@ -47,7 +47,7 @@ CMICmdArgSet::~CMICmdArgSet(void)
// Throws: None.
//--
void
-CMICmdArgSet::Destroy(void)
+CMICmdArgSet::Destroy()
{
// Delete command argument objects
if (!m_setCmdArgs.empty())
@@ -81,7 +81,7 @@ CMICmdArgSet::Destroy(void)
// Throws: None.
//--
bool
-CMICmdArgSet::IsArgsPresentButNotHandledByCmd(void) const
+CMICmdArgSet::IsArgsPresentButNotHandledByCmd() const
{
return m_bIsArgsPresentButNotHandledByCmd;
}
@@ -90,17 +90,13 @@ CMICmdArgSet::IsArgsPresentButNotHandledByCmd(void) const
// Details: Add the list of command's arguments to parse and validate another one.
// Type: Method.
// Args: vArg - (R) A command argument object.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
-CMICmdArgSet::Add(const CMICmdArgValBase &vArg)
+void
+CMICmdArgSet::Add(CMICmdArgValBase *vArg)
{
- CMICmdArgValBase *pArg = const_cast<CMICmdArgValBase *>(&vArg);
- m_setCmdArgs.push_back(pArg);
-
- return MIstatus::success;
+ m_setCmdArgs.push_back(vArg);
}
//++ ------------------------------------------------------------------------------------
@@ -113,7 +109,7 @@ CMICmdArgSet::Add(const CMICmdArgValBase &vArg)
// Throws: None.
//--
const CMICmdArgSet::SetCmdArgs_t &
-CMICmdArgSet::GetArgsThatAreMissing(void) const
+CMICmdArgSet::GetArgsThatAreMissing() const
{
return m_setCmdArgsThatAreMissing;
}
@@ -128,7 +124,7 @@ CMICmdArgSet::GetArgsThatAreMissing(void) const
// Throws: None.
//--
const CMICmdArgSet::SetCmdArgs_t &
-CMICmdArgSet::GetArgsThatInvalid(void) const
+CMICmdArgSet::GetArgsThatInvalid() const
{
return m_setCmdArgsThatNotValid;
}
@@ -146,7 +142,7 @@ CMICmdArgSet::GetArgsThatInvalid(void) const
// Throws: None.
//--
const CMICmdArgSet::SetCmdArgs_t &
-CMICmdArgSet::GetArgsNotHandledByCmd(void) const
+CMICmdArgSet::GetArgsNotHandledByCmd() const
{
return m_setCmdArgsNotHandledByCmd;
}
@@ -172,25 +168,25 @@ CMICmdArgSet::Validate(const CMIUtilString &vStrMiCmd, CMICmdArgContext &vwCmdAr
SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin();
while (it != m_setCmdArgs.end())
{
- const CMICmdArgValBase *pArg(*it);
+ CMICmdArgValBase *pArg = *it;
- if (!const_cast<CMICmdArgValBase *>(pArg)->Validate(vwCmdArgsText))
+ if (!pArg->Validate(vwCmdArgsText))
{
if (pArg->GetFound())
{
if (pArg->GetIsMissingOptions())
- m_setCmdArgsMissingInfo.push_back(const_cast<CMICmdArgValBase *>(pArg));
+ m_setCmdArgsMissingInfo.push_back(pArg);
else if (!pArg->GetValid())
- m_setCmdArgsThatNotValid.push_back(const_cast<CMICmdArgValBase *>(pArg));
+ m_setCmdArgsThatNotValid.push_back(pArg);
}
else if (pArg->GetIsMandatory())
- m_setCmdArgsThatAreMissing.push_back(const_cast<CMICmdArgValBase *>(pArg));
+ m_setCmdArgsThatAreMissing.push_back(pArg);
}
if (pArg->GetFound() && !pArg->GetIsHandledByCmd())
{
m_bIsArgsPresentButNotHandledByCmd = true;
- m_setCmdArgsNotHandledByCmd.push_back(const_cast<CMICmdArgValBase *>(pArg));
+ m_setCmdArgsNotHandledByCmd.push_back(pArg);
}
// Next
@@ -326,7 +322,7 @@ CMICmdArgSet::ValidationFormErrorMessages(const CMICmdArgContext &vwCmdArgsText)
// Throws: None.
//--
bool
-CMICmdArgSet::IsArgContextEmpty(void) const
+CMICmdArgSet::IsArgContextEmpty() const
{
return m_cmdArgContext.IsEmpty();
}
@@ -335,11 +331,11 @@ CMICmdArgSet::IsArgContextEmpty(void) const
// Details: Retrieve the number of arguments that are being used for the command.
// Type: Method.
// Args: None.
-// Return: MIuint - Argument count.
+// Return: size_t - Argument count.
// Throws: None.
//--
-MIuint
-CMICmdArgSet::GetCount(void) const
+size_t
+CMICmdArgSet::GetCount() const
{
return m_setCmdArgs.size();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgSet.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgSet.h
index 0dd2933..2b43925 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgSet.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgSet.h
@@ -9,10 +9,12 @@
#pragma once
-// Third party headers:
+// C Includes
+// C++ Includes
#include <vector>
-// In-house headers:
+// Other libraries and framework includes
+// Project includes
#include "MICmnBase.h"
#include "MICmdArgContext.h"
@@ -30,9 +32,6 @@ class CMICmdArgValBase;
// objects on the heap.
// It is assumed the arguments to be parsed are read from left to right in
// order. The order added to *this container is the order they will parsed.
-// Gotchas: None.
-// Authors: Illya Rudkin 14/04/2014.
-// Changes: None.
//--
class CMICmdArgSet : public CMICmnBase
{
@@ -44,48 +43,44 @@ class CMICmdArgSet : public CMICmnBase
class IArg
{
public:
- virtual bool GetFound(void) const = 0;
- virtual bool GetIsHandledByCmd(void) const = 0;
- virtual bool GetIsMandatory(void) const = 0;
- virtual bool GetIsMissingOptions(void) const = 0;
- virtual const CMIUtilString &GetName(void) const = 0;
- virtual bool GetValid(void) const = 0;
+ virtual bool GetFound() const = 0;
+ virtual bool GetIsHandledByCmd() const = 0;
+ virtual bool GetIsMandatory() const = 0;
+ virtual bool GetIsMissingOptions() const = 0;
+ virtual const CMIUtilString &GetName() const = 0;
+ virtual bool GetValid() const = 0;
virtual bool Validate(CMICmdArgContext &vwArgContext) = 0;
- /* dtor */ virtual ~IArg(void){};
+ virtual ~IArg() = default;
};
// Typedefs:
- public:
typedef std::vector<CMICmdArgValBase *> SetCmdArgs_t;
// Methods:
- public:
- /* ctor */ CMICmdArgSet(void);
+ CMICmdArgSet();
- bool Add(const CMICmdArgValBase &vArg);
+ void Add(CMICmdArgValBase *vArg);
bool GetArg(const CMIUtilString &vArgName, CMICmdArgValBase *&vpArg) const;
- const SetCmdArgs_t &GetArgsThatAreMissing(void) const;
- const SetCmdArgs_t &GetArgsThatInvalid(void) const;
- MIuint GetCount(void) const;
- bool IsArgContextEmpty(void) const;
- bool IsArgsPresentButNotHandledByCmd(void) const;
+ const SetCmdArgs_t &GetArgsThatAreMissing() const;
+ const SetCmdArgs_t &GetArgsThatInvalid() const;
+ size_t GetCount() const;
+ bool IsArgContextEmpty() const;
+ bool IsArgsPresentButNotHandledByCmd() const;
void WarningArgsNotHandledbyCmdLogFile(const CMIUtilString &vrCmdName);
bool Validate(const CMIUtilString &vStrMiCmd, CMICmdArgContext &vwCmdArgsText);
// Overrideable:
- public:
- /* dtor */ virtual ~CMICmdArgSet(void);
+ ~CMICmdArgSet() override;
// Methods:
private:
- const SetCmdArgs_t &GetArgsNotHandledByCmd(void) const;
+ const SetCmdArgs_t &GetArgsNotHandledByCmd() const;
void
- Destroy(void); // Release resources used by *this object
+ Destroy(); // Release resources used by *this object
bool ValidationFormErrorMessages(const CMICmdArgContext &vwCmdArgsText);
// Attributes:
- private:
bool m_bIsArgsPresentButNotHandledByCmd; // True = The driver's client presented the command with options recognised but not handled by
// a command, false = all args handled
SetCmdArgs_t m_setCmdArgs; // The set of arguments that are that the command is expecting to find in the options string
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValBase.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValBase.cpp
index dfaacbc..ddbf957 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValBase.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValBase.cpp
@@ -7,7 +7,10 @@
//
//===----------------------------------------------------------------------===//
-// In-house headers:
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "MICmdArgValBase.h"
#include "MIUtilString.h"
#include "MICmdArgContext.h"
@@ -19,7 +22,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgValBase::CMICmdArgValBase(void)
+CMICmdArgValBase::CMICmdArgValBase()
: m_bFound(false)
, m_bValid(false)
, m_bMandatory(false)
@@ -48,17 +51,6 @@ CMICmdArgValBase::CMICmdArgValBase(const CMIUtilString &vrArgName, const bool vb
}
//++ ------------------------------------------------------------------------------------
-// Details: CMICmdArgValBase destructor.
-// Type: Overrideable.
-// Args: None.
-// Return: None.
-// Throws: None.
-//--
-CMICmdArgValBase::~CMICmdArgValBase(void)
-{
-}
-
-//++ ------------------------------------------------------------------------------------
// Details: Retrieve the state flag of whether the argument is handled by the command or
// not.
// Type: Method.
@@ -68,7 +60,7 @@ CMICmdArgValBase::~CMICmdArgValBase(void)
// Throws: None.
//--
bool
-CMICmdArgValBase::GetIsMissingOptions(void) const
+CMICmdArgValBase::GetIsMissingOptions() const
{
return m_bIsMissingOptions;
}
@@ -83,7 +75,7 @@ CMICmdArgValBase::GetIsMissingOptions(void) const
// Throws: None.
//--
bool
-CMICmdArgValBase::GetIsHandledByCmd(void) const
+CMICmdArgValBase::GetIsHandledByCmd() const
{
return m_bHandled;
}
@@ -96,7 +88,7 @@ CMICmdArgValBase::GetIsHandledByCmd(void) const
// Throws: None.
//--
const CMIUtilString &
-CMICmdArgValBase::GetName(void) const
+CMICmdArgValBase::GetName() const
{
return m_strArgName;
}
@@ -111,7 +103,7 @@ CMICmdArgValBase::GetName(void) const
// Throws: None.
//--
bool
-CMICmdArgValBase::GetFound(void) const
+CMICmdArgValBase::GetFound() const
{
return m_bFound;
}
@@ -126,7 +118,7 @@ CMICmdArgValBase::GetFound(void) const
// Throws: None.
//--
bool
-CMICmdArgValBase::GetValid(void) const
+CMICmdArgValBase::GetValid() const
{
return m_bValid;
}
@@ -141,7 +133,7 @@ CMICmdArgValBase::GetValid(void) const
// Throws: None.
//--
bool
-CMICmdArgValBase::GetIsMandatory(void) const
+CMICmdArgValBase::GetIsMandatory() const
{
return m_bMandatory;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValBase.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValBase.h
index 3aaae49..c343b33 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValBase.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValBase.h
@@ -1,4 +1,4 @@
-//===-- CMICmdArgValBase.h --------------------------------------*- C++ -*-===//
+//===-- MICmdArgValBase.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -9,7 +9,10 @@
#pragma once
-// In-house headers:
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "MIUtilString.h"
#include "MICmdArgSet.h"
@@ -30,30 +33,25 @@
// hardwired to fail and catch arguments or options that presented by
// different driver clients.
// Based on the Interpreter pattern.
-// Gotchas: None.
-// Authors: Illya Rudkin 14/04/2014.
-// Changes: None.
//--
class CMICmdArgValBase : public CMICmdArgSet::IArg
{
// Methods:
public:
- /* ctor */ CMICmdArgValBase(void);
- /* ctor */ CMICmdArgValBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd);
+ CMICmdArgValBase();
+ CMICmdArgValBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd);
// Overrideable:
- public:
- /* dtor */ ~CMICmdArgValBase(void) override;
+ ~CMICmdArgValBase() override = default;
// Overridden:
- public:
// From CMICmdArgSet::IArg
- bool GetFound(void) const override;
- bool GetIsHandledByCmd(void) const override;
- bool GetIsMandatory(void) const override;
- bool GetIsMissingOptions(void) const override;
- const CMIUtilString &GetName(void) const override;
- bool GetValid(void) const override;
+ bool GetFound() const override;
+ bool GetIsHandledByCmd() const override;
+ bool GetIsMandatory() const override;
+ bool GetIsMissingOptions() const override;
+ const CMIUtilString &GetName() const override;
+ bool GetValid() const override;
bool Validate(CMICmdArgContext &vwArgContext) override;
// Attributes:
@@ -68,22 +66,18 @@ class CMICmdArgValBase : public CMICmdArgSet::IArg
//++ ============================================================================
// Details: MI common code class. Templated command argument base class.
-// Gotchas: None.
-// Authors: Illya Rudkin 14/04/2014.
-// Changes: None.
//--
template <class T> class CMICmdArgValBaseTemplate : public CMICmdArgValBase
{
// Methods:
public:
- /* ctor */ CMICmdArgValBaseTemplate(void);
- /* ctor */ CMICmdArgValBaseTemplate(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd);
+ CMICmdArgValBaseTemplate() = default;
+ CMICmdArgValBaseTemplate(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd);
//
- const T &GetValue(void) const;
+ const T &GetValue() const;
// Overrideable:
- public:
- /* dtor */ virtual ~CMICmdArgValBaseTemplate(void);
+ ~CMICmdArgValBaseTemplate() override = default;
// Attributes:
protected:
@@ -93,17 +87,6 @@ template <class T> class CMICmdArgValBaseTemplate : public CMICmdArgValBase
//++ ------------------------------------------------------------------------------------
// Details: CMICmdArgValBaseTemplate constructor.
// Type: Method.
-// Args: None.
-// Return: None.
-// Throws: None.
-//--
-template <class T> CMICmdArgValBaseTemplate<T>::CMICmdArgValBaseTemplate(void)
-{
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: CMICmdArgValBaseTemplate constructor.
-// Type: Method.
// Args: vrArgName - (R) Argument's name to search by.
// vbMandatory - (R) True = Yes must be present, false = optional argument.
// vbHandleByCmd - (R) True = Command processes *this option, false = not handled.
@@ -117,17 +100,6 @@ CMICmdArgValBaseTemplate<T>::CMICmdArgValBaseTemplate(const CMIUtilString &vrArg
}
//++ ------------------------------------------------------------------------------------
-// Details: CMICmdArgValBaseTemplate destructor.
-// Type: Overrideable.
-// Args: None.
-// Return: None.
-// Throws: None.
-//--
-template <class T> CMICmdArgValBaseTemplate<T>::~CMICmdArgValBaseTemplate(void)
-{
-}
-
-//++ ------------------------------------------------------------------------------------
// Details: Retrieve the value the argument parsed from the command's argument / options
// text string.
// Type: Method.
@@ -137,7 +109,7 @@ template <class T> CMICmdArgValBaseTemplate<T>::~CMICmdArgValBaseTemplate(void)
//--
template <class T>
const T &
-CMICmdArgValBaseTemplate<T>::GetValue(void) const
+CMICmdArgValBaseTemplate<T>::GetValue() const
{
return m_argValue;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValConsume.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValConsume.cpp
index c2fe994..12d3291 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValConsume.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValConsume.cpp
@@ -1,4 +1,4 @@
-//===-- MICmdArgValConsume.cpp -------------------------------------*- C++ -*-===//
+//===-- MICmdArgValConsume.cpp ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,7 +18,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgValConsume::CMICmdArgValConsume(void)
+CMICmdArgValConsume::CMICmdArgValConsume()
{
}
@@ -42,7 +42,7 @@ CMICmdArgValConsume::CMICmdArgValConsume(const CMIUtilString &vrArgName, const b
// Return: None.
// Throws: None.
//--
-CMICmdArgValConsume::~CMICmdArgValConsume(void)
+CMICmdArgValConsume::~CMICmdArgValConsume()
{
}
@@ -72,12 +72,10 @@ CMICmdArgValConsume::Validate(CMICmdArgContext &vwArgContext)
{
m_bFound = true;
m_bValid = true;
+ if ( !vwArgContext.RemoveArg( rTxt ) )
+ return MIstatus::failure;
return MIstatus::success;
}
-
- if ( !vwArgContext.RemoveArg( rTxt ) )
- return MIstatus::failure;
-
// Next
++it;
}
@@ -94,7 +92,7 @@ CMICmdArgValConsume::Validate(CMICmdArgContext &vwArgContext)
// Throws: None.
//--
bool
-CMICmdArgValConsume::IsOk(void) const
+CMICmdArgValConsume::IsOk() const
{
return true;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValConsume.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValConsume.h
index 75768ff..792a9be 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValConsume.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValConsume.h
@@ -1,4 +1,4 @@
-//===-- MICmdArgValConsume.h ---------------------------------------*- C++ -*-===//
+//===-- MICmdArgValConsume.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -29,23 +29,20 @@ class CMICmdArgContext;
// a value for the argument but is not the case for *this argument type
// object.
// Based on the Interpreter pattern.
-// Gotchas: None.
-// Authors: Illya Rudkin 20/05/2014.
-// Changes: None.
//--
class CMICmdArgValConsume : public CMICmdArgValBaseTemplate<CMIUtilString>
{
// Methods:
public:
- /* ctor */ CMICmdArgValConsume(void);
+ /* ctor */ CMICmdArgValConsume();
/* ctor */ CMICmdArgValConsume(const CMIUtilString &vrArgName, const bool vbMandatory);
//
- bool IsOk(void) const;
+ bool IsOk() const;
// Overridden:
public:
// From CMICmdArgValBase
- /* dtor */ ~CMICmdArgValConsume(void) override;
+ /* dtor */ ~CMICmdArgValConsume() override;
// From CMICmdArgSet::IArg
bool Validate(CMICmdArgContext &vwArgContext) override;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValFile.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValFile.cpp
index 400610f..7f5b20e 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValFile.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValFile.cpp
@@ -18,7 +18,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgValFile::CMICmdArgValFile(void)
+CMICmdArgValFile::CMICmdArgValFile()
{
}
@@ -43,7 +43,7 @@ CMICmdArgValFile::CMICmdArgValFile(const CMIUtilString &vrArgName, const bool vb
// Return: None.
// Throws: None.
//--
-CMICmdArgValFile::~CMICmdArgValFile(void)
+CMICmdArgValFile::~CMICmdArgValFile()
{
}
@@ -142,23 +142,23 @@ CMICmdArgValFile::IsFilePath(const CMIUtilString &vrFileNamePath) const
if (vrFileNamePath.empty())
return false;
- const bool bHavePosSlash = (vrFileNamePath.find_first_of("/") != std::string::npos);
- const bool bHaveBckSlash = (vrFileNamePath.find_first_of("\\") != std::string::npos);
+ const bool bHavePosSlash = (vrFileNamePath.find('/') != std::string::npos);
+ const bool bHaveBckSlash = (vrFileNamePath.find('\\') != std::string::npos);
// Look for --someLongOption
- size_t nPos = vrFileNamePath.find_first_of("--");
+ size_t nPos = vrFileNamePath.find("--");
const bool bLong = (nPos == 0);
if (bLong)
return false;
// Look for -f type short parameters
- nPos = vrFileNamePath.find_first_of("-");
+ nPos = vrFileNamePath.find('-');
const bool bShort = (nPos == 0);
if (bShort)
return false;
// Look for i1 i2 i3....
- nPos = vrFileNamePath.find_first_of("i");
+ nPos = vrFileNamePath.find('i');
const bool bFoundI1 = ((nPos == 0) && (::isdigit(vrFileNamePath[1])));
if (bFoundI1)
return false;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValFile.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValFile.h
index 07abc4b..25d9842 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValFile.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValFile.h
@@ -22,15 +22,12 @@ class CMICmdArgContext;
// interpret the options (context) string to find and validate a matching
// argument and so extract a value from it .
// Based on the Interpreter pattern.
-// Gotchas: None.
-// Authors: Illya Rudkin 15/04/2014.
-// Changes: None.
//--
class CMICmdArgValFile : public CMICmdArgValBaseTemplate<CMIUtilString>
{
// Methods:
public:
- /* ctor */ CMICmdArgValFile(void);
+ /* ctor */ CMICmdArgValFile();
/* ctor */ CMICmdArgValFile(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd);
//
bool IsFilePath(const CMIUtilString &vrFileNamePath) const;
@@ -39,7 +36,7 @@ class CMICmdArgValFile : public CMICmdArgValBaseTemplate<CMIUtilString>
// Overridden:
public:
// From CMICmdArgValBase
- /* dtor */ ~CMICmdArgValFile(void) override;
+ /* dtor */ ~CMICmdArgValFile() override;
// From CMICmdArgSet::IArg
bool Validate(CMICmdArgContext &vwArgContext) override;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListBase.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListBase.cpp
index 61d72fb..0539628 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListBase.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListBase.cpp
@@ -25,7 +25,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgValListBase::CMICmdArgValListBase(void)
+CMICmdArgValListBase::CMICmdArgValListBase()
: m_eArgType(eArgValType_invalid)
{
}
@@ -69,7 +69,7 @@ CMICmdArgValListBase::CMICmdArgValListBase(const CMIUtilString &vrArgName, const
// Return: None.
// Throws: None.
//--
-CMICmdArgValListBase::~CMICmdArgValListBase(void)
+CMICmdArgValListBase::~CMICmdArgValListBase()
{
// Tidy up
Destroy();
@@ -83,7 +83,7 @@ CMICmdArgValListBase::~CMICmdArgValListBase(void)
// Throws: None.
//--
void
-CMICmdArgValListBase::Destroy(void)
+CMICmdArgValListBase::Destroy()
{
// Tidy up
VecArgObjPtr_t::const_iterator it = m_argValue.begin();
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListBase.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListBase.h
index f013562..59ef3bb 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListBase.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListBase.h
@@ -31,9 +31,6 @@ class CMICmdArgContext;
// container. The option arguments belong to that derived class and will
// be deleted that object goes out of scope.
// Based on the Interpreter pattern.
-// Gotchas: None.
-// Authors: Illya Rudkin 16/04/2014.
-// Changes: None.
//--
class CMICmdArgValListBase : public CMICmdArgValBaseTemplate<std::vector<CMICmdArgValBase *>>
{
@@ -67,7 +64,7 @@ class CMICmdArgValListBase : public CMICmdArgValBaseTemplate<std::vector<CMICmdA
// Methods:
public:
- /* ctor */ CMICmdArgValListBase(void);
+ /* ctor */ CMICmdArgValListBase();
/* ctor */ CMICmdArgValListBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd);
/* ctor */ CMICmdArgValListBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd,
const ArgValType_e veType);
@@ -75,7 +72,7 @@ class CMICmdArgValListBase : public CMICmdArgValBaseTemplate<std::vector<CMICmdA
// Overridden:
public:
// From CMICmdArgValBase
- /* dtor */ ~CMICmdArgValListBase(void) override;
+ /* dtor */ ~CMICmdArgValListBase() override;
// Methods:
protected:
@@ -88,5 +85,5 @@ class CMICmdArgValListBase : public CMICmdArgValBaseTemplate<std::vector<CMICmdA
// Methods:
private:
- void Destroy(void);
+ void Destroy();
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListOfN.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListOfN.cpp
index 8e479d5..78f5fdc 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListOfN.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListOfN.cpp
@@ -24,7 +24,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgValListOfN::CMICmdArgValListOfN(void)
+CMICmdArgValListOfN::CMICmdArgValListOfN()
{
}
@@ -51,7 +51,7 @@ CMICmdArgValListOfN::CMICmdArgValListOfN(const CMIUtilString &vrArgName, const b
// Return: None.
// Throws: None.
//--
-CMICmdArgValListOfN::~CMICmdArgValListOfN(void)
+CMICmdArgValListOfN::~CMICmdArgValListOfN()
{
}
@@ -170,7 +170,7 @@ CMICmdArgValListOfN::IsListOfN(const CMIUtilString &vrTxt) const
// Throws: None.
//--
const CMICmdArgValListBase::VecArgObjPtr_t &
-CMICmdArgValListOfN::GetExpectedOptions(void) const
+CMICmdArgValListOfN::GetExpectedOptions() const
{
return m_argValue;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListOfN.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListOfN.h
index 496bc65..7499a7f 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListOfN.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValListOfN.h
@@ -31,25 +31,22 @@ class CMICmdArgContext;
// If vbMandatory argument is true it takes on the (...)+ specification
// otherwise assumed to be (...)* specification.
// Based on the Interpreter pattern.
-// Gotchas: None.
-// Authors: Illya Rudkin 16/04/2014.
-// Changes: None.
//--
class CMICmdArgValListOfN : public CMICmdArgValListBase
{
// Methods:
public:
- /* ctor */ CMICmdArgValListOfN(void);
+ /* ctor */ CMICmdArgValListOfN();
/* ctor */ CMICmdArgValListOfN(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd,
const ArgValType_e veType);
//
- const VecArgObjPtr_t &GetExpectedOptions(void) const;
+ const VecArgObjPtr_t &GetExpectedOptions() const;
template <class T1, typename T2> bool GetExpectedOption(T2 &vrwValue, const VecArgObjPtr_t::size_type vnAt = 0) const;
// Overridden:
public:
// From CMICmdArgValBase
- /* dtor */ ~CMICmdArgValListOfN(void) override;
+ /* dtor */ ~CMICmdArgValListOfN() override;
// From CMICmdArgSet::IArg
bool Validate(CMICmdArgContext &vArgContext) override;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValNumber.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValNumber.cpp
index 75e9700..5d907ca 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValNumber.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValNumber.cpp
@@ -18,7 +18,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgValNumber::CMICmdArgValNumber(void)
+CMICmdArgValNumber::CMICmdArgValNumber()
: m_nNumberFormatMask(CMICmdArgValNumber::eArgValNumberFormat_Decimal)
, m_nNumber(0)
{
@@ -49,7 +49,7 @@ CMICmdArgValNumber::CMICmdArgValNumber(const CMIUtilString &vrArgName, const boo
// Return: None.
// Throws: None.
//--
-CMICmdArgValNumber::~CMICmdArgValNumber(void)
+CMICmdArgValNumber::~CMICmdArgValNumber()
{
}
@@ -165,7 +165,7 @@ CMICmdArgValNumber::ExtractNumber(const CMIUtilString &vrTxt)
// Throws: None.
//--
MIint64
-CMICmdArgValNumber::GetNumber(void) const
+CMICmdArgValNumber::GetNumber() const
{
return m_nNumber;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValNumber.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValNumber.h
index 58a28b3..0b05e57 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValNumber.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValNumber.h
@@ -22,9 +22,6 @@ class CMICmdArgContext;
// interpret the options (context) string to find and validate a matching
// argument and so extract a value from it .
// Based on the Interpreter pattern.
-// Gotchas: None.
-// Authors: Illya Rudkin 14/04/2014.
-// Changes: None.
//--
class CMICmdArgValNumber : public CMICmdArgValBaseTemplate<MIint64>
{
@@ -43,7 +40,7 @@ class CMICmdArgValNumber : public CMICmdArgValBaseTemplate<MIint64>
// Methods:
public:
- /* ctor */ CMICmdArgValNumber(void);
+ /* ctor */ CMICmdArgValNumber();
/* ctor */ CMICmdArgValNumber(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd,
const MIuint vnNumberFormatMask = eArgValNumberFormat_Decimal);
//
@@ -52,14 +49,14 @@ class CMICmdArgValNumber : public CMICmdArgValBaseTemplate<MIint64>
// Overridden:
public:
// From CMICmdArgValBase
- /* dtor */ ~CMICmdArgValNumber(void) override;
+ /* dtor */ ~CMICmdArgValNumber() override;
// From CMICmdArgSet::IArg
bool Validate(CMICmdArgContext &vwArgContext) override;
// Methods:
private:
bool ExtractNumber(const CMIUtilString &vrTxt);
- MIint64 GetNumber(void) const;
+ MIint64 GetNumber() const;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionLong.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionLong.cpp
index 0eaf6e0..3c95789 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionLong.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionLong.cpp
@@ -18,7 +18,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgValOptionLong::CMICmdArgValOptionLong(void)
+CMICmdArgValOptionLong::CMICmdArgValOptionLong()
: m_nExpectingNOptions(0)
, m_eExpectingOptionType(eArgValType_invalid)
{
@@ -66,7 +66,7 @@ CMICmdArgValOptionLong::CMICmdArgValOptionLong(const CMIUtilString &vrArgName, c
// Return: None.
// Throws: None.
//--
-CMICmdArgValOptionLong::~CMICmdArgValOptionLong(void)
+CMICmdArgValOptionLong::~CMICmdArgValOptionLong()
{
// Tidy up
Destroy();
@@ -80,7 +80,7 @@ CMICmdArgValOptionLong::~CMICmdArgValOptionLong(void)
// Throws: None.
//--
void
-CMICmdArgValOptionLong::Destroy(void)
+CMICmdArgValOptionLong::Destroy()
{
// Tidy up
VecArgObjPtr_t::const_iterator it = m_vecArgsExpected.begin();
@@ -249,19 +249,19 @@ CMICmdArgValOptionLong::ExtractExpectedOptions(CMICmdArgContext &vrwTxt, const M
bool
CMICmdArgValOptionLong::IsArgLongOption(const CMIUtilString &vrTxt) const
{
- const bool bHavePosSlash = (vrTxt.find_first_of("/") != std::string::npos);
- const bool bHaveBckSlash = (vrTxt.find_first_of("\\") != std::string::npos);
+ const bool bHavePosSlash = (vrTxt.find('/') != std::string::npos);
+ const bool bHaveBckSlash = (vrTxt.find('\\') != std::string::npos);
if (bHavePosSlash || bHaveBckSlash)
return false;
- const size_t nPos = vrTxt.find_first_of("--");
+ const size_t nPos = vrTxt.find("--");
if (nPos != 0)
return false;
if (vrTxt.length() < 3)
return false;
- const CMIUtilString strArg = vrTxt.substr(2).c_str();
+ const CMIUtilString strArg = vrTxt.substr(2);
if (strArg.IsNumber())
return false;
@@ -293,7 +293,7 @@ CMICmdArgValOptionLong::IsArgOptionCorrect(const CMIUtilString &vrTxt) const
bool
CMICmdArgValOptionLong::ArgNameMatch(const CMIUtilString &vrTxt) const
{
- const CMIUtilString strArg = vrTxt.substr(2).c_str();
+ const CMIUtilString strArg = vrTxt.substr(2);
return (strArg == GetName());
}
@@ -307,7 +307,7 @@ CMICmdArgValOptionLong::ArgNameMatch(const CMIUtilString &vrTxt) const
// Throws: None.
//--
const CMICmdArgValListBase::VecArgObjPtr_t &
-CMICmdArgValOptionLong::GetExpectedOptions(void) const
+CMICmdArgValOptionLong::GetExpectedOptions() const
{
return m_vecArgsExpected;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionLong.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionLong.h
index ac55c47..9d074fc 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionLong.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionLong.h
@@ -26,27 +26,24 @@ class CMIUtilString;
// created to hold each of those option's values belong to *this argument
// object and so are deleted when *this object goes out of scope.
// Based on the Interpreter pattern.
-// Gotchas: None.
-// Authors: Illya Rudkin 16/04/2014.
-// Changes: None.
//--
class CMICmdArgValOptionLong : public CMICmdArgValListBase
{
// Methods:
public:
- /* ctor */ CMICmdArgValOptionLong(void);
+ /* ctor */ CMICmdArgValOptionLong();
/* ctor */ CMICmdArgValOptionLong(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd);
/* ctor */ CMICmdArgValOptionLong(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd,
const ArgValType_e veType, const MIuint vnExpectingNOptions);
//
bool IsArgLongOption(const CMIUtilString &vrTxt) const;
- const VecArgObjPtr_t &GetExpectedOptions(void) const;
+ const VecArgObjPtr_t &GetExpectedOptions() const;
template <class T1, typename T2> bool GetExpectedOption(T2 &vrwValue) const;
// Overridden:
public:
// From CMICmdArgValBase
- /* dtor */ ~CMICmdArgValOptionLong(void) override;
+ /* dtor */ ~CMICmdArgValOptionLong() override;
// From CMICmdArgSet::IArg
bool Validate(CMICmdArgContext &vArgContext) override;
@@ -61,7 +58,7 @@ class CMICmdArgValOptionLong : public CMICmdArgValListBase
// Methods:
private:
- void Destroy(void);
+ void Destroy();
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionShort.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionShort.cpp
index d18f72e..d5bdfa0 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionShort.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionShort.cpp
@@ -18,7 +18,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgValOptionShort::CMICmdArgValOptionShort(void)
+CMICmdArgValOptionShort::CMICmdArgValOptionShort()
{
}
@@ -60,7 +60,7 @@ CMICmdArgValOptionShort::CMICmdArgValOptionShort(const CMIUtilString &vrArgName,
// Return: None.
// Throws: None.
//--
-CMICmdArgValOptionShort::~CMICmdArgValOptionShort(void)
+CMICmdArgValOptionShort::~CMICmdArgValOptionShort()
{
}
@@ -115,6 +115,6 @@ CMICmdArgValOptionShort::IsArgOptionCorrect(const CMIUtilString &vrTxt) const
bool
CMICmdArgValOptionShort::ArgNameMatch(const CMIUtilString &vrTxt) const
{
- const CMIUtilString strArg = vrTxt.substr(1).c_str();
+ const CMIUtilString strArg = vrTxt.substr(1);
return (strArg == GetName());
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionShort.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionShort.h
index 9157b37..0f1c2fc 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionShort.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValOptionShort.h
@@ -26,15 +26,12 @@ class CMIUtilString;
// created to hold each of those option's values belong to *this argument
// object and so are deleted when *this object goes out of scope.
// Based on the Interpreter pattern.
-// Gotchas: None.
-// Authors: Illya Rudkin 16/04/2014.
-// Changes: None.
//--
class CMICmdArgValOptionShort : public CMICmdArgValOptionLong
{
// Methods:
public:
- /* ctor */ CMICmdArgValOptionShort(void);
+ /* ctor */ CMICmdArgValOptionShort();
/* ctor */ CMICmdArgValOptionShort(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd);
/* ctor */ CMICmdArgValOptionShort(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd,
const ArgValType_e veType, const MIuint vnExpectingNOptions);
@@ -44,7 +41,7 @@ class CMICmdArgValOptionShort : public CMICmdArgValOptionLong
// Overridden:
public:
// From CMICmdArgValBase
- /* dtor */ ~CMICmdArgValOptionShort(void) override;
+ /* dtor */ ~CMICmdArgValOptionShort() override;
// Overridden:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValPrintValues.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValPrintValues.cpp
index 3030782..3b6eddd 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValPrintValues.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValPrintValues.cpp
@@ -18,7 +18,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgValPrintValues::CMICmdArgValPrintValues(void)
+CMICmdArgValPrintValues::CMICmdArgValPrintValues()
: m_nPrintValues(0)
{
}
@@ -45,7 +45,7 @@ CMICmdArgValPrintValues::CMICmdArgValPrintValues(const CMIUtilString &vrArgName,
// Return: None.
// Throws: None.
//--
-CMICmdArgValPrintValues::~CMICmdArgValPrintValues(void)
+CMICmdArgValPrintValues::~CMICmdArgValPrintValues()
{
}
@@ -123,7 +123,7 @@ CMICmdArgValPrintValues::ExtractPrintValues(const CMIUtilString &vrTxt)
// Throws: None.
//--
MIuint
-CMICmdArgValPrintValues::GetPrintValues(void) const
+CMICmdArgValPrintValues::GetPrintValues() const
{
return m_nPrintValues;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValPrintValues.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValPrintValues.h
index 9ac3238..fa8ec8a 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValPrintValues.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValPrintValues.h
@@ -30,7 +30,7 @@ class CMICmdArgValPrintValues : public CMICmdArgValBaseTemplate<MIuint>
{
// Methods:
public:
- /* ctor */ CMICmdArgValPrintValues(void);
+ /* ctor */ CMICmdArgValPrintValues();
/* ctor */ CMICmdArgValPrintValues(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd);
//
bool IsArgPrintValues(const CMIUtilString &vrTxt) const;
@@ -38,14 +38,14 @@ class CMICmdArgValPrintValues : public CMICmdArgValBaseTemplate<MIuint>
// Overridden:
public:
// From CMICmdArgValBase
- /* dtor */ ~CMICmdArgValPrintValues(void) override;
+ /* dtor */ ~CMICmdArgValPrintValues() override;
// From CMICmdArgSet::IArg
bool Validate(CMICmdArgContext &vArgContext) override;
// Methods:
private:
bool ExtractPrintValues(const CMIUtilString &vrTxt);
- MIuint GetPrintValues(void) const;
+ MIuint GetPrintValues() const;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValString.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValString.cpp
index 1c3e5f8..bea5935 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValString.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValString.cpp
@@ -18,7 +18,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgValString::CMICmdArgValString(void)
+CMICmdArgValString::CMICmdArgValString()
: m_bHandleQuotedString(false)
, m_bAcceptNumbers(false)
, m_bHandleDirPaths(false)
@@ -91,7 +91,7 @@ CMICmdArgValString::CMICmdArgValString(const CMIUtilString &vrArgName, const boo
// Return: None.
// Throws: None.
//--
-CMICmdArgValString::~CMICmdArgValString(void)
+CMICmdArgValString::~CMICmdArgValString()
{
}
@@ -220,8 +220,8 @@ CMICmdArgValString::IsStringArgSingleText(const CMIUtilString &vrTxt) const
if (!m_bHandleDirPaths)
{
// Look for directory file paths, if found reject
- const bool bHavePosSlash = (vrTxt.find_first_of("/") != std::string::npos);
- const bool bHaveBckSlash = (vrTxt.find_first_of("\\") != std::string::npos);
+ const bool bHavePosSlash = (vrTxt.find('/') != std::string::npos);
+ const bool bHaveBckSlash = (vrTxt.find('\\') != std::string::npos);
if (bHavePosSlash || bHaveBckSlash)
return false;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValString.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValString.h
index 8b58a0a..cf4d00e 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValString.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValString.h
@@ -22,15 +22,12 @@ class CMICmdArgContext;
// interpret the options (context) string to find and validate a matching
// argument and so extract a value from it .
// Based on the Interpreter pattern.
-// Gotchas: None.
-// Authors: Illya Rudkin 15/04/2014.
-// Changes: None.
//--
class CMICmdArgValString : public CMICmdArgValBaseTemplate<CMIUtilString>
{
// Methods:
public:
- /* ctor */ CMICmdArgValString(void);
+ /* ctor */ CMICmdArgValString();
/* ctor */ CMICmdArgValString(const bool vbAnything);
/* ctor */ CMICmdArgValString(const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths);
/* ctor */ CMICmdArgValString(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd,
@@ -41,7 +38,7 @@ class CMICmdArgValString : public CMICmdArgValBaseTemplate<CMIUtilString>
// Overridden:
public:
// From CMICmdArgValBase
- /* dtor */ ~CMICmdArgValString(void) override;
+ /* dtor */ ~CMICmdArgValString() override;
// From CMICmdArgSet::IArg
bool Validate(CMICmdArgContext &vrwArgContext) override;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValThreadGrp.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValThreadGrp.cpp
index c7e663c..43e9c72 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValThreadGrp.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValThreadGrp.cpp
@@ -18,7 +18,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdArgValThreadGrp::CMICmdArgValThreadGrp(void)
+CMICmdArgValThreadGrp::CMICmdArgValThreadGrp()
: m_nThreadGrp(0)
{
}
@@ -45,7 +45,7 @@ CMICmdArgValThreadGrp::CMICmdArgValThreadGrp(const CMIUtilString &vrArgName, con
// Return: None.
// Throws: None.
//--
-CMICmdArgValThreadGrp::~CMICmdArgValThreadGrp(void)
+CMICmdArgValThreadGrp::~CMICmdArgValThreadGrp()
{
}
@@ -117,11 +117,11 @@ bool
CMICmdArgValThreadGrp::IsArgThreadGrp(const CMIUtilString &vrTxt) const
{
// Look for i1 i2 i3....
- const MIint nPos = vrTxt.find_first_of("i");
+ const MIint nPos = vrTxt.find('i');
if (nPos != 0)
return false;
- const CMIUtilString strNum = vrTxt.substr(1).c_str();
+ const CMIUtilString strNum = vrTxt.substr(1);
if (!strNum.IsNumber())
return false;
@@ -139,7 +139,7 @@ CMICmdArgValThreadGrp::IsArgThreadGrp(const CMIUtilString &vrTxt) const
bool
CMICmdArgValThreadGrp::ExtractNumber(const CMIUtilString &vrTxt)
{
- const CMIUtilString strNum = vrTxt.substr(1).c_str();
+ const CMIUtilString strNum = vrTxt.substr(1);
MIint64 nNumber = 0;
bool bOk = strNum.ExtractNumber(nNumber);
if (bOk)
@@ -158,7 +158,7 @@ CMICmdArgValThreadGrp::ExtractNumber(const CMIUtilString &vrTxt)
// Throws: None.
//--
MIuint
-CMICmdArgValThreadGrp::GetNumber(void) const
+CMICmdArgValThreadGrp::GetNumber() const
{
return m_nThreadGrp;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValThreadGrp.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValThreadGrp.h
index 64c1140..5c4936c 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValThreadGrp.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdArgValThreadGrp.h
@@ -23,15 +23,12 @@ class CMICmdArgContext;
// argument and so extract a value from it. Thread group looks like
// "i1" in the options text.
// Based on the Interpreter pattern.
-// Gotchas: None.
-// Authors: Illya Rudkin 15/04/2014.
-// Changes: None.
//--
class CMICmdArgValThreadGrp : public CMICmdArgValBaseTemplate<MIuint>
{
// Methods:
public:
- /* ctor */ CMICmdArgValThreadGrp(void);
+ /* ctor */ CMICmdArgValThreadGrp();
/* ctor */ CMICmdArgValThreadGrp(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd);
//
bool IsArgThreadGrp(const CMIUtilString &vrTxt) const;
@@ -39,14 +36,14 @@ class CMICmdArgValThreadGrp : public CMICmdArgValBaseTemplate<MIuint>
// Overridden:
public:
// From CMICmdArgValBase
- /* dtor */ ~CMICmdArgValThreadGrp(void) override;
+ /* dtor */ ~CMICmdArgValThreadGrp() override;
// From CMICmdArgSet::IArg
bool Validate(CMICmdArgContext &vArgContext) override;
// Methods:
private:
bool ExtractNumber(const CMIUtilString &vrTxt);
- MIuint GetNumber(void) const;
+ MIuint GetNumber() const;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.cpp
index 97bf5a0..2f63205 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.cpp
@@ -11,6 +11,8 @@
#include "MICmdBase.h"
#include "MICmnMIValueConst.h"
#include "MICmnLLDBDebugSessionInfo.h"
+#include "MICmdArgValOptionLong.h"
+#include "MICmdArgValConsume.h"
//++ ------------------------------------------------------------------------------------
// Details: CMICmdBase constructor.
@@ -19,10 +21,17 @@
// Return: None.
// Throws: None.
//--
-CMICmdBase::CMICmdBase(void)
+CMICmdBase::CMICmdBase()
: m_pSelfCreatorFn(nullptr)
, m_rLLDBDebugSessionInfo(CMICmnLLDBDebugSessionInfo::Instance())
, m_bHasResultRecordExtra(false)
+ , m_constStrArgThreadGroup("thread-group")
+ , m_constStrArgThread("thread")
+ , m_constStrArgFrame("frame")
+ , m_constStrArgConsume("--")
+ , m_ThreadGrpArgMandatory(false)
+ , m_ThreadArgMandatory(false)
+ , m_FrameArgMandatory(false)
{
}
@@ -33,7 +42,7 @@ CMICmdBase::CMICmdBase(void)
// Return: None.
// Throws: None.
//--
-CMICmdBase::~CMICmdBase(void)
+CMICmdBase::~CMICmdBase()
{
}
@@ -45,7 +54,7 @@ CMICmdBase::~CMICmdBase(void)
// Throws: None.
//--
const SMICmdData &
-CMICmdBase::GetCmdData(void) const
+CMICmdBase::GetCmdData() const
{
return m_cmdData;
}
@@ -59,7 +68,7 @@ CMICmdBase::GetCmdData(void) const
// Throws: None.
//--
const CMIUtilString &
-CMICmdBase::GetErrorDescription(void) const
+CMICmdBase::GetErrorDescription() const
{
return m_strCurrentErrDescription;
}
@@ -73,26 +82,38 @@ CMICmdBase::GetErrorDescription(void) const
// Throws: None.
//--
const CMIUtilString &
-CMICmdBase::GetMiCmd(void) const
+CMICmdBase::GetMiCmd() const
{
return m_strMiCmd;
}
//++ ------------------------------------------------------------------------------------
+// Details: Help parse the arguments that are common to all commands.
+// Args: None.
+// Return: None
+// Throws: None.
+//--
+void
+CMICmdBase::AddCommonArgs()
+{
+ m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgThreadGroup, m_ThreadGrpArgMandatory, true, CMICmdArgValListBase::eArgValType_ThreadGrp, 1));
+ m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgThread, m_ThreadArgMandatory, true, CMICmdArgValListBase::eArgValType_Number, 1));
+ m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgFrame, m_FrameArgMandatory, true, CMICmdArgValListBase::eArgValType_Number, 1));
+ m_setCmdArgs.Add(new CMICmdArgValConsume(m_constStrArgConsume, false));
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. A command must be given working data and
// provide data about its status or provide information to other objects.
// Type: Overridden.
// Args: None.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmdBase::SetCmdData(const SMICmdData &vCmdData)
{
m_cmdData = vCmdData;
-
- return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@@ -104,7 +125,7 @@ CMICmdBase::SetCmdData(const SMICmdData &vCmdData)
// Throws: None.
//--
CMICmdFactory::CmdCreatorFnPtr
-CMICmdBase::GetCmdCreatorFn(void) const
+CMICmdBase::GetCmdCreatorFn() const
{
return m_pSelfCreatorFn;
}
@@ -120,7 +141,7 @@ CMICmdBase::GetCmdCreatorFn(void) const
// Throws: None.
//--
void
-CMICmdBase::CmdFinishedTellInvoker(void) const
+CMICmdBase::CmdFinishedTellInvoker() const
{
CMICmdInvoker::Instance().CmdExecuteFinished(const_cast<CMICmdBase &>(*this));
}
@@ -134,7 +155,7 @@ CMICmdBase::CmdFinishedTellInvoker(void) const
// Throws: None.
//--
const CMIUtilString &
-CMICmdBase::GetMIResultRecord(void) const
+CMICmdBase::GetMIResultRecord() const
{
return m_miResultRecord.GetString();
}
@@ -149,7 +170,7 @@ CMICmdBase::GetMIResultRecord(void) const
// Throws: None.
//--
const CMIUtilString &
-CMICmdBase::GetMIResultRecordExtra(void) const
+CMICmdBase::GetMIResultRecordExtra() const
{
return m_miResultRecordExtra;
}
@@ -164,7 +185,7 @@ CMICmdBase::GetMIResultRecordExtra(void) const
// Throws: None.
//--
bool
-CMICmdBase::HasMIResultRecordExtra(void) const
+CMICmdBase::HasMIResultRecordExtra() const
{
return m_bHasResultRecordExtra;
}
@@ -198,7 +219,7 @@ CMICmdBase::SetError(const CMIUtilString &rErrMsg)
// Throws: None.
//--
MIuint
-CMICmdBase::GetGUID(void)
+CMICmdBase::GetGUID()
{
MIuint64 vptr = reinterpret_cast<MIuint64>(this);
MIuint id = (vptr)&0xFFFFFFFF;
@@ -217,7 +238,7 @@ CMICmdBase::GetGUID(void)
// Throws: None.
//--
bool
-CMICmdBase::ParseArgs(void)
+CMICmdBase::ParseArgs()
{
// Do nothing - override to implement
@@ -236,7 +257,7 @@ CMICmdBase::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdBase::ParseValidateCmdOptions(void)
+CMICmdBase::ParseValidateCmdOptions()
{
CMICmdArgContext argCntxt(m_cmdData.strMiCmdOption);
if (m_setCmdArgs.Validate(m_cmdData.strMiCmd, argCntxt))
@@ -259,7 +280,7 @@ CMICmdBase::ParseValidateCmdOptions(void)
// Throws: None.
//--
bool
-CMICmdBase::GetExitAppOnCommandFailure(void) const
+CMICmdBase::GetExitAppOnCommandFailure() const
{
return false;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.h
index df1e429..aa56748 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdBase.h
@@ -9,7 +9,10 @@
#pragma once
-// In-house headers:
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "MIUtilString.h"
#include "MICmnBase.h"
#include "MICmnResources.h"
@@ -42,46 +45,41 @@ class CMICmnLLDBDebugSessionInfo;
// to factor handling and parsing of different types of arguments
// presented to a command. A command will produce an error should it
// be presented with arguments or options it does not understand.
-// Gotchas: None.
-// Authors: Illya Rudkin 18/02/2014.
-// Changes: None.
//--
class CMICmdBase : public CMICmnBase, public CMICmdInvoker::ICmd, public CMICmdFactory::ICmd
{
// Methods:
public:
- /* ctor */ CMICmdBase(void);
+ CMICmdBase();
// Overridden:
- public:
// From CMICmdInvoker::ICmd
- virtual const SMICmdData &GetCmdData(void) const;
- virtual const CMIUtilString &GetErrorDescription(void) const;
- virtual bool SetCmdData(const SMICmdData &vCmdData);
- virtual void CmdFinishedTellInvoker(void) const;
- virtual const CMIUtilString &GetMIResultRecord(void) const;
- virtual const CMIUtilString &GetMIResultRecordExtra(void) const;
- virtual bool HasMIResultRecordExtra(void) const;
- virtual bool ParseArgs(void);
+ const SMICmdData &GetCmdData() const override;
+ const CMIUtilString &GetErrorDescription() const override;
+ void SetCmdData(const SMICmdData &vCmdData) override;
+ void CmdFinishedTellInvoker() const override;
+ const CMIUtilString &GetMIResultRecord() const override;
+ const CMIUtilString &GetMIResultRecordExtra() const override;
+ bool HasMIResultRecordExtra() const override;
+ bool ParseArgs() override;
// From CMICmdFactory::ICmd
- virtual const CMIUtilString &GetMiCmd(void) const;
- virtual CMICmdFactory::CmdCreatorFnPtr GetCmdCreatorFn(void) const;
+ const CMIUtilString &GetMiCmd() const override;
+ CMICmdFactory::CmdCreatorFnPtr GetCmdCreatorFn() const override;
- virtual MIuint GetGUID(void);
+ virtual MIuint GetGUID();
+ void AddCommonArgs();
// Overrideable:
- public:
- /* dtor */ virtual ~CMICmdBase(void);
- virtual bool GetExitAppOnCommandFailure(void) const;
+ ~CMICmdBase() override;
+ virtual bool GetExitAppOnCommandFailure() const;
// Methods:
protected:
void SetError(const CMIUtilString &rErrMsg);
template <class T> T *GetOption(const CMIUtilString &vStrOptionName);
- bool ParseValidateCmdOptions(void);
+ bool ParseValidateCmdOptions();
// Attributes:
- protected:
CMICmdFactory::CmdCreatorFnPtr m_pSelfCreatorFn;
CMIUtilString m_strCurrentErrDescription; // Reason for Execute or Acknowledge function failure
SMICmdData m_cmdData; // Holds information/status of *this command. Used by other MI code to report or determine state of a command.
@@ -97,6 +95,16 @@ class CMICmdBase : public CMICmnBase, public CMICmdInvoker::ICmd, public CMICmdF
bool m_bHasResultRecordExtra; // True = Yes command produced additional MI output to its 1 line response, false = no extra MI output
// formed.
CMICmdArgSet m_setCmdArgs; // The list of arguments *this command needs to parse from the options string to carry out work.
+ const CMIUtilString m_constStrArgThreadGroup;
+ const CMIUtilString m_constStrArgThread;
+ const CMIUtilString m_constStrArgFrame;
+ const CMIUtilString m_constStrArgConsume;
+
+ // These 3 members can be used by the derived classes to make any of
+ // "thread", "frame" or "thread-group" mandatory.
+ bool m_ThreadGrpArgMandatory;
+ bool m_ThreadArgMandatory;
+ bool m_FrameArgMandatory;
};
//++ ------------------------------------------------------------------------------------
@@ -109,7 +117,7 @@ class CMICmdBase : public CMICmnBase, public CMICmdInvoker::ICmd, public CMICmdF
// Args: vStrOptionName - (R) The text name of the argument or option to search for in
// the list of the command's possible arguments or options.
// Return: T * - CMICmdArgValBase derived object.
-// - NULL = function has failed, unable to retrieve the option/arg object.
+// - nullptr = function has failed, unable to retrieve the option/arg object.
// Throws: None.
//--
template <class T>
@@ -136,7 +144,7 @@ CMICmdBase::GetOption(const CMIUtilString &vStrOptionName)
// c - (R) The text name of the argument or option to search for in the list of
// the command's possible arguments or options.
// Return: T * - CMICmdArgValBase derived object.
-// - NULL = function has failed, unable to retrieve the option/arg object.
+// - nullptr = function has failed, unable to retrieve the option/arg object.
// Throws: None.
//--
#define CMICMDBASE_GETOPTION(a, b, c) \
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmd.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmd.cpp
index fbfc609..c666111 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmd.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmd.cpp
@@ -22,7 +22,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdEnablePrettyPrinting::CMICmdCmdEnablePrettyPrinting(void)
+CMICmdCmdEnablePrettyPrinting::CMICmdCmdEnablePrettyPrinting()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "enable-pretty-printing";
@@ -38,7 +38,7 @@ CMICmdCmdEnablePrettyPrinting::CMICmdCmdEnablePrettyPrinting(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdEnablePrettyPrinting::~CMICmdCmdEnablePrettyPrinting(void)
+CMICmdCmdEnablePrettyPrinting::~CMICmdCmdEnablePrettyPrinting()
{
}
@@ -52,7 +52,7 @@ CMICmdCmdEnablePrettyPrinting::~CMICmdCmdEnablePrettyPrinting(void)
// Throws: None.
//--
bool
-CMICmdCmdEnablePrettyPrinting::Execute(void)
+CMICmdCmdEnablePrettyPrinting::Execute()
{
// Do nothing
return MIstatus::success;
@@ -68,7 +68,7 @@ CMICmdCmdEnablePrettyPrinting::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdEnablePrettyPrinting::Acknowledge(void)
+CMICmdCmdEnablePrettyPrinting::Acknowledge()
{
const CMICmnMIValueConst miValueConst("0");
const CMICmnMIValueResult miValueResult("supported", miValueConst);
@@ -87,7 +87,7 @@ CMICmdCmdEnablePrettyPrinting::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdEnablePrettyPrinting::CreateSelf(void)
+CMICmdCmdEnablePrettyPrinting::CreateSelf()
{
return new CMICmdCmdEnablePrettyPrinting();
}
@@ -103,7 +103,7 @@ CMICmdCmdEnablePrettyPrinting::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdSource::CMICmdCmdSource(void)
+CMICmdCmdSource::CMICmdCmdSource()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "source";
@@ -119,7 +119,7 @@ CMICmdCmdSource::CMICmdCmdSource(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdSource::~CMICmdCmdSource(void)
+CMICmdCmdSource::~CMICmdCmdSource()
{
}
@@ -133,7 +133,7 @@ CMICmdCmdSource::~CMICmdCmdSource(void)
// Throws: None.
//--
bool
-CMICmdCmdSource::Execute(void)
+CMICmdCmdSource::Execute()
{
// Do nothing
return MIstatus::success;
@@ -149,7 +149,7 @@ CMICmdCmdSource::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdSource::Acknowledge(void)
+CMICmdCmdSource::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -166,7 +166,7 @@ CMICmdCmdSource::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdSource::CreateSelf(void)
+CMICmdCmdSource::CreateSelf()
{
return new CMICmdCmdSource();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmd.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmd.h
index 2669764..6753c3b 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmd.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmd.h
@@ -41,53 +41,47 @@ MI commands implemented are:
// *this class implements MI command "enable-pretty-printing".
// Enables Python base pretty printing.
// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html
-// Gotchas: None.
-// Authors: Illya Rudkin 03/03/2014.
-// Changes: None.
//--
class CMICmdCmdEnablePrettyPrinting : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdEnablePrettyPrinting(void);
+ /* ctor */ CMICmdCmdEnablePrettyPrinting();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdEnablePrettyPrinting(void) override;
+ /* dtor */ ~CMICmdCmdEnablePrettyPrinting() override;
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "source".
-// Gotchas: None.
-// Authors: Illya Rudkin 05/03/2014.
-// Changes: None.
//--
class CMICmdCmdSource : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdSource(void);
+ /* ctor */ CMICmdCmdSource();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdSource(void) override;
+ /* dtor */ ~CMICmdCmdSource() override;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp
index 8a310c7..e758a3d 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.cpp
@@ -40,7 +40,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakInsert::CMICmdCmdBreakInsert(void)
+CMICmdCmdBreakInsert::CMICmdCmdBreakInsert()
: m_bBrkPtIsTemp(false)
, m_bBrkPtIsPending(false)
, m_nBrkPtIgnoreCount(0)
@@ -57,7 +57,6 @@ CMICmdCmdBreakInsert::CMICmdCmdBreakInsert(void)
, m_constStrArgNamedInoreCnt("i")
, m_constStrArgNamedRestrictBrkPtToThreadId("p")
, m_constStrArgNamedLocation("location")
- , m_constStrArgNamedThreadGroup("thread-group")
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "break-insert";
@@ -73,7 +72,7 @@ CMICmdCmdBreakInsert::CMICmdCmdBreakInsert(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert(void)
+CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert()
{
}
@@ -87,29 +86,41 @@ CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakInsert::ParseArgs(void)
+CMICmdCmdBreakInsert::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedTempBrkPt, false, true)));
- // Not implemented bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedHWBrkPt, false, false ) ) );
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedPendinfBrkPt, false, true,
- CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedDisableBrkPt, false, false)));
- // Not implemented bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedTracePt, false, false ) ) );
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedConditionalBrkPt, false, true,
- CMICmdArgValListBase::eArgValType_StringQuoted, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(
- *(new CMICmdArgValOptionShort(m_constStrArgNamedInoreCnt, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedRestrictBrkPtToThreadId, false, true,
- CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedLocation, false, true)));
- bOk = bOk &&
- m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGroup, false, true, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedTempBrkPt, false, true));
+ // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort( m_constStrArgNamedHWBrkPt, false, false));
+ m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedPendinfBrkPt, false, true,
+ CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1));
+ m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedDisableBrkPt, false, false));
+ // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort( m_constStrArgNamedTracePt, false, false));
+ m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedConditionalBrkPt, false, true,
+ CMICmdArgValListBase::eArgValType_StringQuoted, 1));
+ m_setCmdArgs.Add(
+ new CMICmdArgValOptionShort(m_constStrArgNamedInoreCnt, false, true, CMICmdArgValListBase::eArgValType_Number, 1));
+ m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedRestrictBrkPtToThreadId, false, true,
+ CMICmdArgValListBase::eArgValType_Number, 1));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedLocation, false, true));
+ return ParseValidateCmdOptions();
+}
+
+//++ ------------------------------------------------------------------------------------
+// Helper function for CMICmdCmdBreakInsert::Execute().
+//
+// Given a string, return the position of the ':' separator in 'file:func'
+// or 'file:line', if any. If not found, return npos. For example, return
+// 5 for 'foo.c:std::string'.
+//--
+static size_t findFileSeparatorPos(const std::string& x)
+{
+ // Full paths in windows can have ':' after a drive letter, so we
+ // search backwards, taking care to skip C++ namespace tokens '::'.
+ size_t n = x.rfind(':');
+ while (n != std::string::npos && n > 1 && x[n-1] == ':')
+ {
+ n = x.rfind(':', n - 2);
+ }
+ return n;
}
//++ ------------------------------------------------------------------------------------
@@ -122,10 +133,10 @@ CMICmdCmdBreakInsert::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakInsert::Execute(void)
+CMICmdCmdBreakInsert::Execute()
{
CMICMDBASE_GETOPTION(pArgTempBrkPt, OptionShort, m_constStrArgNamedTempBrkPt);
- CMICMDBASE_GETOPTION(pArgThreadGroup, OptionLong, m_constStrArgNamedThreadGroup);
+ CMICMDBASE_GETOPTION(pArgThreadGroup, OptionLong, m_constStrArgThreadGroup);
CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgNamedLocation);
CMICMDBASE_GETOPTION(pArgIgnoreCnt, OptionShort, m_constStrArgNamedInoreCnt);
CMICMDBASE_GETOPTION(pArgPendingBrkPt, OptionShort, m_constStrArgNamedPendinfBrkPt);
@@ -166,17 +177,16 @@ CMICmdCmdBreakInsert::Execute(void)
// Determine if break on a file line or at a function
BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet;
- const CMIUtilString cColon = ":";
CMIUtilString fileName;
MIuint nFileLine = 0;
CMIUtilString strFileFn;
CMIUtilString rStrLineOrFn;
- // Full path in windows can have : after drive letter. So look for the
- // last colon
- const size_t nPosColon = m_brkName.find_last_of(cColon);
+ // Is the string in the form 'file:func' or 'file:line'?
+ // If so, find the position of the ':' separator.
+ const size_t nPosColon = findFileSeparatorPos(m_brkName);
if (nPosColon != std::string::npos)
{
- // extract file name and line number from it
+ // Extract file name and line number from it
fileName = m_brkName.substr(0, nPosColon);
rStrLineOrFn = m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1);
@@ -226,8 +236,13 @@ CMICmdCmdBreakInsert::Execute(void)
m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress);
break;
case eBreakPoint_ByFileFn:
- m_brkPt = sbTarget.BreakpointCreateByName(strFileFn.c_str(), fileName.c_str());
+ {
+ lldb::SBFileSpecList module; // search in all modules
+ lldb::SBFileSpecList compUnit;
+ compUnit.Append (lldb::SBFileSpec(fileName.c_str()));
+ m_brkPt = sbTarget.BreakpointCreateByName(strFileFn.c_str(), module, compUnit);
break;
+ }
case eBreakPoint_ByFileLine:
m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine);
break;
@@ -306,7 +321,7 @@ CMICmdCmdBreakInsert::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakInsert::Acknowledge(void)
+CMICmdCmdBreakInsert::Acknowledge()
{
// Get breakpoint information
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
@@ -336,7 +351,7 @@ CMICmdCmdBreakInsert::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdBreakInsert::CreateSelf(void)
+CMICmdCmdBreakInsert::CreateSelf()
{
return new CMICmdCmdBreakInsert();
}
@@ -352,9 +367,8 @@ CMICmdCmdBreakInsert::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakDelete::CMICmdCmdBreakDelete(void)
+CMICmdCmdBreakDelete::CMICmdCmdBreakDelete()
: m_constStrArgNamedBrkPt("breakpoint")
- , m_constStrArgNamedThreadGrp("thread-group")
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "break-delete";
@@ -370,7 +384,7 @@ CMICmdCmdBreakDelete::CMICmdCmdBreakDelete(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete(void)
+CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete()
{
}
@@ -384,13 +398,10 @@ CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakDelete::ParseArgs(void)
+CMICmdCmdBreakDelete::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)));
- bOk =
- bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -403,7 +414,7 @@ CMICmdCmdBreakDelete::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakDelete::Execute(void)
+CMICmdCmdBreakDelete::Execute()
{
CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
@@ -437,7 +448,7 @@ CMICmdCmdBreakDelete::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakDelete::Acknowledge(void)
+CMICmdCmdBreakDelete::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -454,7 +465,7 @@ CMICmdCmdBreakDelete::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdBreakDelete::CreateSelf(void)
+CMICmdCmdBreakDelete::CreateSelf()
{
return new CMICmdCmdBreakDelete();
}
@@ -470,9 +481,8 @@ CMICmdCmdBreakDelete::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakDisable::CMICmdCmdBreakDisable(void)
- : m_constStrArgNamedThreadGrp("thread-group")
- , m_constStrArgNamedBrkPt("breakpoint")
+CMICmdCmdBreakDisable::CMICmdCmdBreakDisable()
+ : m_constStrArgNamedBrkPt("breakpoint")
, m_bBrkPtDisabledOk(false)
, m_nBrkPtId(0)
{
@@ -490,7 +500,7 @@ CMICmdCmdBreakDisable::CMICmdCmdBreakDisable(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable(void)
+CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable()
{
}
@@ -504,13 +514,10 @@ CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakDisable::ParseArgs(void)
+CMICmdCmdBreakDisable::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)));
- bOk =
- bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -523,7 +530,7 @@ CMICmdCmdBreakDisable::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakDisable::Execute(void)
+CMICmdCmdBreakDisable::Execute()
{
CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
@@ -557,7 +564,7 @@ CMICmdCmdBreakDisable::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakDisable::Acknowledge(void)
+CMICmdCmdBreakDisable::Acknowledge()
{
if (m_bBrkPtDisabledOk)
{
@@ -566,10 +573,10 @@ CMICmdCmdBreakDisable::Acknowledge(void)
CMICmnMIValueTuple miValueTuple(miValueResult);
const CMICmnMIValueConst miValueConst2("n");
const CMICmnMIValueResult miValueResult2("enabled", miValueConst2);
- bool bOk = miValueTuple.Add(miValueResult2);
+ miValueTuple.Add(miValueResult2);
const CMICmnMIValueResult miValueResult3("bkpt", miValueTuple);
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3);
- bOk = bOk && CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
+ bool bOk = CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -594,7 +601,7 @@ CMICmdCmdBreakDisable::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdBreakDisable::CreateSelf(void)
+CMICmdCmdBreakDisable::CreateSelf()
{
return new CMICmdCmdBreakDisable();
}
@@ -610,9 +617,8 @@ CMICmdCmdBreakDisable::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakEnable::CMICmdCmdBreakEnable(void)
- : m_constStrArgNamedThreadGrp("thread-group")
- , m_constStrArgNamedBrkPt("breakpoint")
+CMICmdCmdBreakEnable::CMICmdCmdBreakEnable()
+ : m_constStrArgNamedBrkPt("breakpoint")
, m_bBrkPtEnabledOk(false)
, m_nBrkPtId(0)
{
@@ -630,7 +636,7 @@ CMICmdCmdBreakEnable::CMICmdCmdBreakEnable(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable(void)
+CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable()
{
}
@@ -644,13 +650,10 @@ CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakEnable::ParseArgs(void)
+CMICmdCmdBreakEnable::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)));
- bOk =
- bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -663,7 +666,7 @@ CMICmdCmdBreakEnable::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakEnable::Execute(void)
+CMICmdCmdBreakEnable::Execute()
{
CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt);
@@ -697,7 +700,7 @@ CMICmdCmdBreakEnable::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakEnable::Acknowledge(void)
+CMICmdCmdBreakEnable::Acknowledge()
{
if (m_bBrkPtEnabledOk)
{
@@ -706,10 +709,10 @@ CMICmdCmdBreakEnable::Acknowledge(void)
CMICmnMIValueTuple miValueTuple(miValueResult);
const CMICmnMIValueConst miValueConst2("y");
const CMICmnMIValueResult miValueResult2("enabled", miValueConst2);
- bool bOk = miValueTuple.Add(miValueResult2);
+ miValueTuple.Add(miValueResult2);
const CMICmnMIValueResult miValueResult3("bkpt", miValueTuple);
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3);
- bOk = bOk && CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
+ bool bOk = CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -734,7 +737,7 @@ CMICmdCmdBreakEnable::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdBreakEnable::CreateSelf(void)
+CMICmdCmdBreakEnable::CreateSelf()
{
return new CMICmdCmdBreakEnable();
}
@@ -750,9 +753,8 @@ CMICmdCmdBreakEnable::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakAfter::CMICmdCmdBreakAfter(void)
- : m_constStrArgNamedThreadGrp("thread-group")
- , m_constStrArgNamedNumber("number")
+CMICmdCmdBreakAfter::CMICmdCmdBreakAfter()
+ : m_constStrArgNamedNumber("number")
, m_constStrArgNamedCount("count")
, m_nBrkPtId(0)
, m_nBrkPtCount(0)
@@ -771,7 +773,7 @@ CMICmdCmdBreakAfter::CMICmdCmdBreakAfter(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter(void)
+CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter()
{
}
@@ -785,13 +787,11 @@ CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakAfter::ParseArgs(void)
+CMICmdCmdBreakAfter::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -804,7 +804,7 @@ CMICmdCmdBreakAfter::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakAfter::Execute(void)
+CMICmdCmdBreakAfter::Execute()
{
CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount);
@@ -847,7 +847,7 @@ CMICmdCmdBreakAfter::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakAfter::Acknowledge(void)
+CMICmdCmdBreakAfter::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -864,7 +864,7 @@ CMICmdCmdBreakAfter::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdBreakAfter::CreateSelf(void)
+CMICmdCmdBreakAfter::CreateSelf()
{
return new CMICmdCmdBreakAfter();
}
@@ -880,9 +880,8 @@ CMICmdCmdBreakAfter::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakCondition::CMICmdCmdBreakCondition(void)
- : m_constStrArgNamedThreadGrp("thread-group")
- , m_constStrArgNamedNumber("number")
+CMICmdCmdBreakCondition::CMICmdCmdBreakCondition()
+ : m_constStrArgNamedNumber("number")
, m_constStrArgNamedExpr("expr")
, m_constStrArgNamedExprNoQuotes(
"expression not surround by quotes") // Not specified in MI spec, we need to handle expressions not surrounded by quotes
@@ -902,7 +901,7 @@ CMICmdCmdBreakCondition::CMICmdCmdBreakCondition(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition(void)
+CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition()
{
}
@@ -916,16 +915,13 @@ CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakCondition::ParseArgs(void)
+CMICmdCmdBreakCondition::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true)));
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedExprNoQuotes, true, false,
- CMICmdArgValListBase::eArgValType_StringQuotedNumber)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedExprNoQuotes, false, false,
+ CMICmdArgValListBase::eArgValType_StringQuotedNumber));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -938,7 +934,7 @@ CMICmdCmdBreakCondition::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakCondition::Execute(void)
+CMICmdCmdBreakCondition::Execute()
{
CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber);
CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr);
@@ -982,7 +978,7 @@ CMICmdCmdBreakCondition::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdBreakCondition::Acknowledge(void)
+CMICmdCmdBreakCondition::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -999,7 +995,7 @@ CMICmdCmdBreakCondition::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdBreakCondition::CreateSelf(void)
+CMICmdCmdBreakCondition::CreateSelf()
{
return new CMICmdCmdBreakCondition();
}
@@ -1021,14 +1017,13 @@ CMICmdCmdBreakCondition::CreateSelf(void)
// Throws: None.
//--
CMIUtilString
-CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes(void)
+CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes()
{
CMIUtilString strExpression;
CMICmdArgValListOfN *pArgExprNoQuotes = CMICmdBase::GetOption<CMICmdArgValListOfN>(m_constStrArgNamedExprNoQuotes);
if (pArgExprNoQuotes != nullptr)
{
- CMIUtilString strExpression;
const CMICmdArgValListBase::VecArgObjPtr_t &rVecExprParts(pArgExprNoQuotes->GetExpectedOptions());
if (!rVecExprParts.empty())
{
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.h
index 476ab45..b8c4240 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdBreak.h
@@ -35,29 +35,26 @@
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "break-insert".
// This command does not follow the MI documentation exactly.
-// Gotchas: None.
-// Authors: Illya Rudkin 11/03/2014.
-// Changes: None.
//--
class CMICmdCmdBreakInsert : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdBreakInsert(void);
+ /* ctor */ CMICmdCmdBreakInsert();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdBreakInsert(void) override;
+ /* dtor */ ~CMICmdCmdBreakInsert() override;
// Enumerations:
private:
@@ -98,72 +95,63 @@ class CMICmdCmdBreakInsert : public CMICmdBase
const CMIUtilString m_constStrArgNamedInoreCnt;
const CMIUtilString m_constStrArgNamedRestrictBrkPtToThreadId;
const CMIUtilString m_constStrArgNamedLocation;
- const CMIUtilString m_constStrArgNamedThreadGroup; // Not specified in MI spec but Eclipse gives this option sometimes
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "break-delete".
-// Gotchas: None.
-// Authors: Illya Rudkin 11/03/2014.
-// Changes: None.
//--
class CMICmdCmdBreakDelete : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdBreakDelete(void);
+ /* ctor */ CMICmdCmdBreakDelete();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdBreakDelete(void) override;
+ /* dtor */ ~CMICmdCmdBreakDelete() override;
// Attributes:
private:
const CMIUtilString m_constStrArgNamedBrkPt;
- const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "break-disable".
-// Gotchas: None.
-// Authors: Illya Rudkin 19/05/2014.
-// Changes: None.
//--
class CMICmdCmdBreakDisable : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdBreakDisable(void);
+ /* ctor */ CMICmdCmdBreakDisable();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdBreakDisable(void) override;
+ /* dtor */ ~CMICmdCmdBreakDisable() override;
// Attributes:
private:
- const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgNamedBrkPt;
bool m_bBrkPtDisabledOk;
MIuint m_nBrkPtId;
@@ -172,33 +160,29 @@ class CMICmdCmdBreakDisable : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "break-enable".
-// Gotchas: None.
-// Authors: Illya Rudkin 19/05/2014.
-// Changes: None.
//--
class CMICmdCmdBreakEnable : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdBreakEnable(void);
+ /* ctor */ CMICmdCmdBreakEnable();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdBreakEnable(void) override;
+ /* dtor */ ~CMICmdCmdBreakEnable() override;
// Attributes:
private:
- const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgNamedBrkPt;
bool m_bBrkPtEnabledOk;
MIuint m_nBrkPtId;
@@ -207,33 +191,29 @@ class CMICmdCmdBreakEnable : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "break-after".
-// Gotchas: None.
-// Authors: Illya Rudkin 29/05/2014.
-// Changes: None.
//--
class CMICmdCmdBreakAfter : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdBreakAfter(void);
+ /* ctor */ CMICmdCmdBreakAfter();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdBreakAfter(void) override;
+ /* dtor */ ~CMICmdCmdBreakAfter() override;
// Attributes:
private:
- const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgNamedNumber;
const CMIUtilString m_constStrArgNamedCount;
MIuint m_nBrkPtId;
@@ -243,37 +223,33 @@ class CMICmdCmdBreakAfter : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "break-condition".
-// Gotchas: None.
-// Authors: Illya Rudkin 29/05/2014.
-// Changes: None.
//--
class CMICmdCmdBreakCondition : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdBreakCondition(void);
+ /* ctor */ CMICmdCmdBreakCondition();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdBreakCondition(void) override;
+ /* dtor */ ~CMICmdCmdBreakCondition() override;
// Methods:
private:
- CMIUtilString GetRestOfExpressionNotSurroundedInQuotes(void);
+ CMIUtilString GetRestOfExpressionNotSurroundedInQuotes();
// Attributes:
private:
- const CMIUtilString m_constStrArgNamedThreadGrp; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgNamedNumber;
const CMIUtilString m_constStrArgNamedExpr;
const CMIUtilString m_constStrArgNamedExprNoQuotes; // Not specified in MI spec, we need to handle expressions not surrounded by quotes
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.cpp
index 21036f8..0e0cf12 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.cpp
@@ -42,6 +42,7 @@
#include "MICmdArgValConsume.h"
#include "MICmnLLDBDebugSessionInfoVarObj.h"
#include "MICmnLLDBUtilSBValue.h"
+#include "MIUtilParse.h"
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdDataEvaluateExpression constructor.
@@ -50,15 +51,12 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression(void)
+CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression()
: m_bExpressionValid(true)
, m_bEvaluatedExpression(true)
, m_strValue("??")
- , m_bCompositeVarType(false)
, m_bFoundInvalidChar(false)
, m_cExpressionInvalidChar(0x00)
- , m_constStrArgThread("thread")
- , m_constStrArgFrame("frame")
, m_constStrArgExpr("expr")
{
// Command factory matches this name with that received from the stdin stream
@@ -75,7 +73,7 @@ CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression(void)
+CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression()
{
}
@@ -89,14 +87,10 @@ CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression(void)
// Throws: None.
//--
bool
-CMICmdCmdDataEvaluateExpression::ParseArgs(void)
+CMICmdCmdDataEvaluateExpression::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, false, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgExpr, true, true, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpr, true, true, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -109,7 +103,7 @@ CMICmdCmdDataEvaluateExpression::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdDataEvaluateExpression::Execute(void)
+CMICmdCmdDataEvaluateExpression::Execute()
{
CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr);
@@ -147,41 +141,7 @@ CMICmdCmdDataEvaluateExpression::Execute(void)
m_strValue = rExpression.Trim('\"');
return MIstatus::success;
}
-
- MIuint64 nNumber = 0;
- if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(value, nNumber) == MIstatus::success)
- {
- const lldb::ValueType eValueType = value.GetValueType();
- MIunused(eValueType);
- m_strValue = utilValue.GetValue().Escape().AddSlashes();
- return MIstatus::success;
- }
-
- // Composite type i.e. struct
- m_bCompositeVarType = true;
- const MIuint nChild = value.GetNumChildren();
- for (MIuint i = 0; i < nChild; i++)
- {
- lldb::SBValue member = value.GetChildAtIndex(i);
- const bool bValid = member.IsValid();
- CMIUtilString strType(MIRSRC(IDS_WORD_UNKNOWNTYPE_BRKTS));
- if (bValid)
- {
- const CMIUtilString strValue(
- CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural));
- const char *pTypeName = member.GetName();
- if (pTypeName != nullptr)
- strType = pTypeName;
-
- // MI print "{variable = 1, variable2 = 3, variable3 = 5}"
- const bool bNoQuotes = true;
- const CMICmnMIValueConst miValueConst(strValue, bNoQuotes);
- const bool bUseSpaces = true;
- const CMICmnMIValueResult miValueResult(strType, miValueConst, bUseSpaces);
- m_miValueTuple.Add(miValueResult, bUseSpaces);
- }
- }
-
+ m_strValue = utilValue.GetValue(true).Escape().AddSlashes();
return MIstatus::success;
}
@@ -195,21 +155,12 @@ CMICmdCmdDataEvaluateExpression::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdDataEvaluateExpression::Acknowledge(void)
+CMICmdCmdDataEvaluateExpression::Acknowledge()
{
if (m_bExpressionValid)
{
if (m_bEvaluatedExpression)
{
- if (m_bCompositeVarType)
- {
- const CMICmnMIValueConst miValueConst(m_miValueTuple.GetString());
- const CMICmnMIValueResult miValueResult("value", miValueConst);
- const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
- m_miResultRecord = miRecordResult;
- return MIstatus::success;
- }
-
if (m_bFoundInvalidChar)
{
const CMICmnMIValueConst miValueConst(
@@ -251,7 +202,7 @@ CMICmdCmdDataEvaluateExpression::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdDataEvaluateExpression::CreateSelf(void)
+CMICmdCmdDataEvaluateExpression::CreateSelf()
{
return new CMICmdCmdDataEvaluateExpression();
}
@@ -285,11 +236,9 @@ CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(const CMIUtilS
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble(void)
- : m_constStrArgThread("thread")
- , m_constStrArgAddrStart("s")
+CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble()
+ : m_constStrArgAddrStart("s")
, m_constStrArgAddrEnd("e")
- , m_constStrArgConsume("--")
, m_constStrArgMode("mode")
, m_miValueList(true)
{
@@ -307,7 +256,7 @@ CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble(void)
+CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble()
{
}
@@ -321,19 +270,14 @@ CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble(void)
// Throws: None.
//--
bool
-CMICmdCmdDataDisassemble::ParseArgs(void)
+CMICmdCmdDataDisassemble::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(
- *(new CMICmdArgValOptionShort(m_constStrArgAddrStart, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(
- *(new CMICmdArgValOptionShort(m_constStrArgAddrEnd, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValConsume(m_constStrArgConsume, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgMode, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(
+ new CMICmdArgValOptionShort(m_constStrArgAddrStart, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
+ m_setCmdArgs.Add(
+ new CMICmdArgValOptionShort(m_constStrArgAddrEnd, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMode, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -346,7 +290,7 @@ CMICmdCmdDataDisassemble::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdDataDisassemble::Execute(void)
+CMICmdCmdDataDisassemble::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
CMICMDBASE_GETOPTION(pArgAddrStart, OptionShort, m_constStrArgAddrStart);
@@ -476,7 +420,7 @@ CMICmdCmdDataDisassemble::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdDataDisassemble::Acknowledge(void)
+CMICmdCmdDataDisassemble::Acknowledge()
{
const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList);
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
@@ -494,7 +438,7 @@ CMICmdCmdDataDisassemble::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdDataDisassemble::CreateSelf(void)
+CMICmdCmdDataDisassemble::CreateSelf()
{
return new CMICmdCmdDataDisassemble();
}
@@ -510,10 +454,8 @@ CMICmdCmdDataDisassemble::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes(void)
- : m_constStrArgThread("thread")
- , m_constStrArgFrame("frame")
- , m_constStrArgByteOffset("o")
+CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes()
+ : m_constStrArgByteOffset("o")
, m_constStrArgAddrExpr("address")
, m_constStrArgNumBytes("count")
, m_pBufferMemory(nullptr)
@@ -534,7 +476,7 @@ CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes(void)
+CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes()
{
if (m_pBufferMemory != nullptr)
{
@@ -553,18 +495,12 @@ CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes(void)
// Throws: None.
//--
bool
-CMICmdCmdDataReadMemoryBytes::ParseArgs(void)
+CMICmdCmdDataReadMemoryBytes::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk =
- bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -577,7 +513,7 @@ CMICmdCmdDataReadMemoryBytes::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdDataReadMemoryBytes::Execute(void)
+CMICmdCmdDataReadMemoryBytes::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
@@ -700,7 +636,7 @@ CMICmdCmdDataReadMemoryBytes::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdDataReadMemoryBytes::Acknowledge(void)
+CMICmdCmdDataReadMemoryBytes::Acknowledge()
{
// MI: memory=[{begin=\"0x%016" PRIx64 "\",offset=\"0x%016" PRIx64" \",end=\"0x%016" PRIx64 "\",contents=\" \" }]"
const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart));
@@ -742,7 +678,7 @@ CMICmdCmdDataReadMemoryBytes::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdDataReadMemoryBytes::CreateSelf(void)
+CMICmdCmdDataReadMemoryBytes::CreateSelf()
{
return new CMICmdCmdDataReadMemoryBytes();
}
@@ -758,7 +694,7 @@ CMICmdCmdDataReadMemoryBytes::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory(void)
+CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "data-read-memory";
@@ -774,7 +710,7 @@ CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory(void)
+CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory()
{
}
@@ -788,7 +724,7 @@ CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory(void)
// Throws: None.
//--
bool
-CMICmdCmdDataReadMemory::Execute(void)
+CMICmdCmdDataReadMemory::Execute()
{
// Do nothing - command deprecated use "data-read-memory-bytes" command
return MIstatus::success;
@@ -804,7 +740,7 @@ CMICmdCmdDataReadMemory::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdDataReadMemory::Acknowledge(void)
+CMICmdCmdDataReadMemory::Acknowledge()
{
// Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which causes this command not to be called
const CMICmnMIValueConst miValueConst(MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED));
@@ -824,7 +760,7 @@ CMICmdCmdDataReadMemory::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdDataReadMemory::CreateSelf(void)
+CMICmdCmdDataReadMemory::CreateSelf()
{
return new CMICmdCmdDataReadMemory();
}
@@ -840,9 +776,8 @@ CMICmdCmdDataReadMemory::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames(void)
- : m_constStrArgThreadGroup("thread-group")
- , m_constStrArgRegNo("regno")
+CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames()
+ : m_constStrArgRegNo("regno")
, m_miValueList(true)
{
// Command factory matches this name with that received from the stdin stream
@@ -859,7 +794,7 @@ CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames(void)
+CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames()
{
}
@@ -873,12 +808,10 @@ CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames(void)
// Throws: None.
//--
bool
-CMICmdCmdDataListRegisterNames::ParseArgs(void)
+CMICmdCmdDataListRegisterNames::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgThreadGroup, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgRegNo, false, false, CMICmdArgValListBase::eArgValType_Number)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgRegNo, false, false, CMICmdArgValListBase::eArgValType_Number));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -891,7 +824,7 @@ CMICmdCmdDataListRegisterNames::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdDataListRegisterNames::Execute(void)
+CMICmdCmdDataListRegisterNames::Execute()
{
CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
@@ -940,9 +873,7 @@ CMICmdCmdDataListRegisterNames::Execute(void)
if (regValue.IsValid())
{
const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName());
- const bool bOk = m_miValueList.Add(miValueConst);
- if (!bOk)
- return MIstatus::failure;
+ m_miValueList.Add(miValueConst);
}
}
}
@@ -961,7 +892,7 @@ CMICmdCmdDataListRegisterNames::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdDataListRegisterNames::Acknowledge(void)
+CMICmdCmdDataListRegisterNames::Acknowledge()
{
const CMICmnMIValueResult miValueResult("register-names", m_miValueList);
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
@@ -979,7 +910,7 @@ CMICmdCmdDataListRegisterNames::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdDataListRegisterNames::CreateSelf(void)
+CMICmdCmdDataListRegisterNames::CreateSelf()
{
return new CMICmdCmdDataListRegisterNames();
}
@@ -1031,9 +962,8 @@ CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues(void)
- : m_constStrArgThread("thread")
- , m_constStrArgSkip("skip-unavailable")
+CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues()
+ : m_constStrArgSkip("skip-unavailable")
, m_constStrArgFormat("fmt")
, m_constStrArgRegNo("regno")
, m_miValueList(true)
@@ -1052,7 +982,7 @@ CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues(void)
+CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues()
{
}
@@ -1066,14 +996,13 @@ CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues(void)
// Throws: None.
//--
bool
-CMICmdCmdDataListRegisterValues::ParseArgs(void)
+CMICmdCmdDataListRegisterValues::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgFormat, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgRegNo, false, true, CMICmdArgValListBase::eArgValType_Number)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1));
+ m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormat, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgRegNo, false, true, CMICmdArgValListBase::eArgValType_Number));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -1086,7 +1015,7 @@ CMICmdCmdDataListRegisterValues::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdDataListRegisterValues::Execute(void)
+CMICmdCmdDataListRegisterValues::Execute()
{
CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat);
CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
@@ -1124,9 +1053,7 @@ CMICmdCmdDataListRegisterValues::Execute(void)
lldb::SBValue regValue = GetRegister(nRegIndex);
if (regValue.IsValid())
{
- const bool bOk = AddToOutput(nRegIndex, regValue, eFormat);
- if (!bOk)
- return MIstatus::failure;
+ AddToOutput(nRegIndex, regValue, eFormat);
}
// Next
@@ -1150,9 +1077,7 @@ CMICmdCmdDataListRegisterValues::Execute(void)
lldb::SBValue regValue = value.GetChildAtIndex(j);
if (regValue.IsValid())
{
- const bool bOk = AddToOutput(nRegIndex, regValue, eFormat);
- if (!bOk)
- return MIstatus::failure;
+ AddToOutput(nRegIndex, regValue, eFormat);
}
// Next
@@ -1174,7 +1099,7 @@ CMICmdCmdDataListRegisterValues::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdDataListRegisterValues::Acknowledge(void)
+CMICmdCmdDataListRegisterValues::Acknowledge()
{
const CMICmnMIValueResult miValueResult("register-values", m_miValueList);
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
@@ -1192,7 +1117,7 @@ CMICmdCmdDataListRegisterValues::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdDataListRegisterValues::CreateSelf(void)
+CMICmdCmdDataListRegisterValues::CreateSelf()
{
return new CMICmdCmdDataListRegisterValues();
}
@@ -1240,7 +1165,7 @@ CMICmdCmdDataListRegisterValues::GetRegister(const MIuint vRegisterIndex) const
// Return: None
// Throws: None.
//--
-bool
+void
CMICmdCmdDataListRegisterValues::AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue,
CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat)
{
@@ -1250,8 +1175,8 @@ CMICmdCmdDataListRegisterValues::AddToOutput(const MIuint vnIndex, const lldb::S
const CMIUtilString strRegValue(CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(vrValue, veVarFormat));
const CMICmnMIValueConst miValueConst2(strRegValue);
const CMICmnMIValueResult miValueResult2("value", miValueConst2);
- bool bOk = miValueTuple.Add(miValueResult2);
- return bOk && m_miValueList.Add(miValueTuple);
+ miValueTuple.Add(miValueResult2);
+ m_miValueList.Add(miValueTuple);
}
//---------------------------------------------------------------------------------------
@@ -1265,7 +1190,7 @@ CMICmdCmdDataListRegisterValues::AddToOutput(const MIuint vnIndex, const lldb::S
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged(void)
+CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "data-list-changed-registers";
@@ -1281,7 +1206,7 @@ CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged(void)
+CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged()
{
}
@@ -1295,7 +1220,7 @@ CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged(void)
// Throws: None.
//--
bool
-CMICmdCmdDataListRegisterChanged::Execute(void)
+CMICmdCmdDataListRegisterChanged::Execute()
{
// Do nothing
@@ -1312,7 +1237,7 @@ CMICmdCmdDataListRegisterChanged::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdDataListRegisterChanged::Acknowledge(void)
+CMICmdCmdDataListRegisterChanged::Acknowledge()
{
const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
const CMICmnMIValueResult miValueResult("msg", miValueConst);
@@ -1331,7 +1256,7 @@ CMICmdCmdDataListRegisterChanged::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdDataListRegisterChanged::CreateSelf(void)
+CMICmdCmdDataListRegisterChanged::CreateSelf()
{
return new CMICmdCmdDataListRegisterChanged();
}
@@ -1347,9 +1272,8 @@ CMICmdCmdDataListRegisterChanged::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes(void)
- : m_constStrArgThread("thread")
- , m_constStrArgAddr("address")
+CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes()
+ : m_constStrArgAddr("address")
, m_constStrArgContents("contents")
, m_constStrArgCount("count")
{
@@ -1367,7 +1291,7 @@ CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes(void)
+CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes()
{
}
@@ -1381,14 +1305,12 @@ CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes(void)
// Throws: None.
//--
bool
-CMICmdCmdDataWriteMemoryBytes::ParseArgs(void)
+CMICmdCmdDataWriteMemoryBytes::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgAddr, true, true, false, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgContents, true, true, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgCount, false, true, false, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgAddr, true, true, false, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgContents, true, true, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgCount, false, true, false, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -1401,7 +1323,7 @@ CMICmdCmdDataWriteMemoryBytes::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdDataWriteMemoryBytes::Execute(void)
+CMICmdCmdDataWriteMemoryBytes::Execute()
{
// Do nothing - not reproduceable (yet) in Eclipse
// CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset );
@@ -1425,7 +1347,7 @@ CMICmdCmdDataWriteMemoryBytes::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdDataWriteMemoryBytes::Acknowledge(void)
+CMICmdCmdDataWriteMemoryBytes::Acknowledge()
{
const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
const CMICmnMIValueResult miValueResult("msg", miValueConst);
@@ -1444,7 +1366,7 @@ CMICmdCmdDataWriteMemoryBytes::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdDataWriteMemoryBytes::CreateSelf(void)
+CMICmdCmdDataWriteMemoryBytes::CreateSelf()
{
return new CMICmdCmdDataWriteMemoryBytes();
}
@@ -1460,9 +1382,8 @@ CMICmdCmdDataWriteMemoryBytes::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory(void)
- : m_constStrArgThread("thread")
- , m_constStrArgOffset("o")
+CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory()
+ : m_constStrArgOffset("o")
, m_constStrArgAddr("address")
, m_constStrArgD("d")
, m_constStrArgNumber("a number")
@@ -1485,7 +1406,7 @@ CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory(void)
+CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory()
{
if (m_pBufferMemory != nullptr)
{
@@ -1504,17 +1425,14 @@ CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory(void)
// Throws: None.
//--
bool
-CMICmdCmdDataWriteMemory::ParseArgs(void)
+CMICmdCmdDataWriteMemory::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgAddr, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgD, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgContents, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1));
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgAddr, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgD, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgContents, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -1527,7 +1445,7 @@ CMICmdCmdDataWriteMemory::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdDataWriteMemory::Execute(void)
+CMICmdCmdDataWriteMemory::Execute()
{
CMICMDBASE_GETOPTION(pArgOffset, OptionShort, m_constStrArgOffset);
CMICMDBASE_GETOPTION(pArgAddr, Number, m_constStrArgAddr);
@@ -1585,7 +1503,7 @@ CMICmdCmdDataWriteMemory::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdDataWriteMemory::Acknowledge(void)
+CMICmdCmdDataWriteMemory::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -1602,7 +1520,7 @@ CMICmdCmdDataWriteMemory::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdDataWriteMemory::CreateSelf(void)
+CMICmdCmdDataWriteMemory::CreateSelf()
{
return new CMICmdCmdDataWriteMemory();
}
@@ -1618,7 +1536,7 @@ CMICmdCmdDataWriteMemory::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine(void)
+CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine()
: m_constStrArgLocation("location")
{
// Command factory matches this name with that received from the stdin stream
@@ -1635,7 +1553,7 @@ CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine(void)
+CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine()
{
}
@@ -1649,10 +1567,10 @@ CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine(void)
// Throws: None.
//--
bool
-CMICmdCmdDataInfoLine::ParseArgs(void)
+CMICmdCmdDataInfoLine::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgLocation, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgLocation, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -1665,7 +1583,7 @@ CMICmdCmdDataInfoLine::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdDataInfoLine::Execute(void)
+CMICmdCmdDataInfoLine::Execute()
{
CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation);
@@ -1676,7 +1594,7 @@ CMICmdCmdDataInfoLine::Execute(void)
// Parse argument:
// *0x12345
// ^^^^^^^ -- address
- const CMIUtilString strAddress(strLocation.c_str() + 1);
+ const CMIUtilString strAddress(strLocation.substr(1));
strCmdOptionsLocation = CMIUtilString::Format("--address %s", strAddress.c_str());
}
else
@@ -1692,8 +1610,8 @@ CMICmdCmdDataInfoLine::Execute(void)
// hello.cpp:5
// ^^^^^^^^^ -- file
// ^ -- line
- const CMIUtilString strFile(strLocation.substr(0, nLineStartPos).c_str());
- const CMIUtilString strLine(strLocation.substr(nLineStartPos + 1).c_str());
+ const CMIUtilString strFile(strLocation.substr(0, nLineStartPos));
+ const CMIUtilString strLine(strLocation.substr(nLineStartPos + 1));
strCmdOptionsLocation = CMIUtilString::Format("--file \"%s\" --line %s", strFile.AddSlashes().c_str(), strLine.c_str());
}
const CMIUtilString strCmd(CMIUtilString::Format("target modules lookup -v %s", strCmdOptionsLocation.c_str()));
@@ -1706,6 +1624,53 @@ CMICmdCmdDataInfoLine::Execute(void)
}
//++ ------------------------------------------------------------------------------------
+// Details: Helper function for parsing a line entry returned from lldb for the command:
+// target modules lookup -v <location>
+// where the line entry is of the format:
+// LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/file:3[:1]
+// start end file line column(opt)
+// Args: input - (R) Input string to parse.
+// start - (W) String representing the start address.
+// end - (W) String representing the end address.
+// file - (W) String representing the file.
+// line - (W) String representing the line.
+// Return: bool - True = input was parsed successfully, false = input could not be parsed.
+// Throws: None.
+//--
+static bool
+ParseLLDBLineEntry(const char *input, CMIUtilString &start, CMIUtilString &end,
+ CMIUtilString &file, CMIUtilString &line)
+{
+ // Note: Ambiguities arise because the column is optional, and
+ // because : can appear in filenames or as a byte in a multibyte
+ // UTF8 character. We keep those cases to a minimum by using regex
+ // to work on the string from both the left and right, so that what
+ // is remains is assumed to be the filename.
+
+ // Match LineEntry using regex.
+ static MIUtilParse::CRegexParser g_lineentry_nocol_regex(
+ "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$");
+ static MIUtilParse::CRegexParser g_lineentry_col_regex(
+ "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$");
+ // ^1=start ^2=end ^3=f ^4=line ^5=:col(opt)
+
+ MIUtilParse::CRegexParser::Match match(6);
+
+ // First try matching the LineEntry with the column,
+ // then try without the column.
+ const bool ok = g_lineentry_col_regex.Execute(input, match) ||
+ g_lineentry_nocol_regex.Execute(input, match);
+ if (ok)
+ {
+ start = match.GetMatchAtIndex(1);
+ end = match.GetMatchAtIndex(2);
+ file = match.GetMatchAtIndex(3);
+ line = match.GetMatchAtIndex(4);
+ }
+ return ok;
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
@@ -1715,7 +1680,7 @@ CMICmdCmdDataInfoLine::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdDataInfoLine::Acknowledge(void)
+CMICmdCmdDataInfoLine::Acknowledge()
{
if (m_lldbResult.GetErrorSize() > 0)
{
@@ -1736,67 +1701,28 @@ CMICmdCmdDataInfoLine::Acknowledge(void)
// String looks like:
// LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
const CMIUtilString &rLine(vecLines[i]);
+ CMIUtilString strStart;
+ CMIUtilString strEnd;
+ CMIUtilString strFile;
+ CMIUtilString strLine;
- // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
- // ^^^^^^^^^ -- property
- const size_t nPropertyStartPos = rLine.find_first_not_of(' ');
- const size_t nPropertyEndPos = rLine.find(':');
- const size_t nPropertyLen = nPropertyEndPos - nPropertyStartPos;
- const CMIUtilString strProperty(rLine.substr(nPropertyStartPos, nPropertyLen).c_str());
-
- // Skip all except LineEntry
- if (!CMIUtilString::Compare(strProperty, "LineEntry"))
+ if (!ParseLLDBLineEntry(rLine.c_str(), strStart, strEnd, strFile, strLine))
continue;
- // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
- // ^^^^^^^^^^^^^^^^^^ -- start address
- const size_t nStartAddressStartPos = rLine.find('[');
- const size_t nStartAddressEndPos = rLine.find('-');
- const size_t nStartAddressLen = nStartAddressEndPos - nStartAddressStartPos - 1;
- const CMIUtilString strStartAddress(rLine.substr(nStartAddressStartPos + 1, nStartAddressLen).c_str());
- const CMICmnMIValueConst miValueConst(strStartAddress);
+ const CMICmnMIValueConst miValueConst(strStart);
const CMICmnMIValueResult miValueResult("start", miValueConst);
- CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
-
- // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
- // ^^^^^^^^^^^^^^^^^^ -- end address
- const size_t nEndAddressEndPos = rLine.find(')');
- const size_t nEndAddressLen = nEndAddressEndPos - nStartAddressEndPos - 1;
- const CMIUtilString strEndAddress(rLine.substr(nStartAddressEndPos + 1, nEndAddressLen).c_str());
- const CMICmnMIValueConst miValueConst2(strEndAddress);
+ CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken,
+ CMICmnMIResultRecord::eResultClass_Done,
+ miValueResult);
+ const CMICmnMIValueConst miValueConst2(strEnd);
const CMICmnMIValueResult miValueResult2("end", miValueConst2);
- bool bOk = miRecordResult.Add(miValueResult2);
- if (!bOk)
- return MIstatus::failure;
-
- // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
- // ^^^^^^^^^^^^^ -- file
- // ^ -- line
- // ^ -- column (optional)
- const size_t nFileStartPos = rLine.find_first_not_of(' ', nEndAddressEndPos + 2);
- const size_t nFileOrLineEndPos = rLine.rfind(':');
- const size_t nFileOrLineStartPos = rLine.rfind(':', nFileOrLineEndPos - 1);
- const size_t nFileEndPos = nFileStartPos < nFileOrLineStartPos ? nFileOrLineStartPos : nFileOrLineEndPos;
- const size_t nFileLen = nFileEndPos - nFileStartPos;
- const CMIUtilString strFile(rLine.substr(nFileStartPos, nFileLen).c_str());
+ miRecordResult.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3(strFile);
const CMICmnMIValueResult miValueResult3("file", miValueConst3);
- bOk = miRecordResult.Add(miValueResult3);
- if (!bOk)
- return MIstatus::failure;
-
- // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
- // ^ -- line
- const size_t nLineStartPos = nFileEndPos + 1;
- const size_t nLineEndPos = rLine.find(':', nLineStartPos);
- const size_t nLineLen = nLineEndPos != std::string::npos ? nLineEndPos - nLineStartPos
- : std::string::npos;
- const CMIUtilString strLine(rLine.substr(nLineStartPos, nLineLen).c_str());
+ miRecordResult.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4(strLine);
const CMICmnMIValueResult miValueResult4("line", miValueConst4);
- bOk = miRecordResult.Add(miValueResult4);
- if (!bOk)
- return MIstatus::failure;
+ miRecordResult.Add(miValueResult4);
// MI print "%s^done,start=\"%d\",end=\"%d\"",file=\"%s\",line=\"%d\"
m_miResultRecord = miRecordResult;
@@ -1823,7 +1749,7 @@ CMICmdCmdDataInfoLine::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdDataInfoLine::CreateSelf(void)
+CMICmdCmdDataInfoLine::CreateSelf()
{
return new CMICmdCmdDataInfoLine();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.h
index 5764410..028c713 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdData.h
@@ -42,29 +42,26 @@
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "data-evaluate-expression".
-// Gotchas: None.
-// Authors: Illya Rudkin 26/03/2014.
-// Changes: None.
//--
class CMICmdCmdDataEvaluateExpression : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdDataEvaluateExpression(void);
+ /* ctor */ CMICmdCmdDataEvaluateExpression();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdDataEvaluateExpression(void) override;
+ /* dtor */ ~CMICmdCmdDataEvaluateExpression() override;
// Methods:
private:
@@ -76,47 +73,39 @@ class CMICmdCmdDataEvaluateExpression : public CMICmdBase
bool m_bEvaluatedExpression; // True = yes is expression evaluated, false = failed
CMIUtilString m_strValue;
CMICmnMIValueTuple m_miValueTuple;
- bool m_bCompositeVarType; // True = yes composite type, false = internal type
bool m_bFoundInvalidChar; // True = yes found unexpected character in the expression, false = all ok
char m_cExpressionInvalidChar;
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
- const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
const CMIUtilString m_constStrArgExpr;
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "data-disassemble".
-// Gotchas: None.
-// Authors: Illya Rudkin 19/05/2014.
-// Changes: None.
//--
class CMICmdCmdDataDisassemble : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdDataDisassemble(void);
+ /* ctor */ CMICmdCmdDataDisassemble();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdDataDisassemble(void) override;
+ /* dtor */ ~CMICmdCmdDataDisassemble() override;
// Attributes:
private:
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
const CMIUtilString m_constStrArgAddrStart; // MI spec non mandatory, *this command mandatory
const CMIUtilString m_constStrArgAddrEnd; // MI spec non mandatory, *this command mandatory
- const CMIUtilString m_constStrArgConsume;
const CMIUtilString m_constStrArgMode;
CMICmnMIValueList m_miValueList;
};
@@ -124,34 +113,29 @@ class CMICmdCmdDataDisassemble : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "data-read-memory-bytes".
-// Gotchas: None.
-// Authors: Illya Rudkin 20/05/2014.
-// Changes: None.
//--
class CMICmdCmdDataReadMemoryBytes : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdDataReadMemoryBytes(void);
+ /* ctor */ CMICmdCmdDataReadMemoryBytes();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdDataReadMemoryBytes(void) override;
+ /* dtor */ ~CMICmdCmdDataReadMemoryBytes() override;
// Attributes:
private:
- const CMIUtilString m_constStrArgThread; // Not in the MI spec but implemented by GDB.
- const CMIUtilString m_constStrArgFrame; // Not in the MI spec but implemented by GDB.
const CMIUtilString m_constStrArgByteOffset;
const CMIUtilString m_constStrArgAddrExpr;
const CMIUtilString m_constStrArgNumBytes;
@@ -163,56 +147,50 @@ class CMICmdCmdDataReadMemoryBytes : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "data-read-memory".
-// Gotchas: None.
-// Authors: Illya Rudkin 21/05/2014.
-// Changes: None.
//--
class CMICmdCmdDataReadMemory : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdDataReadMemory(void);
+ /* ctor */ CMICmdCmdDataReadMemory();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdDataReadMemory(void) override;
+ /* dtor */ ~CMICmdCmdDataReadMemory() override;
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "data-list-register-names".
-// Gotchas: None.
-// Authors: Illya Rudkin 21/05/2014.
-// Changes: None.
//--
class CMICmdCmdDataListRegisterNames : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdDataListRegisterNames(void);
+ /* ctor */ CMICmdCmdDataListRegisterNames();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdDataListRegisterNames(void) override;
+ /* dtor */ ~CMICmdCmdDataListRegisterNames() override;
// Methods:
private:
@@ -220,7 +198,6 @@ class CMICmdCmdDataListRegisterNames : public CMICmdBase
// Attributes:
private:
- const CMIUtilString m_constStrArgThreadGroup; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgRegNo; // Not handled by *this command
CMICmnMIValueList m_miValueList;
};
@@ -228,38 +205,34 @@ class CMICmdCmdDataListRegisterNames : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "data-list-register-values".
-// Gotchas: None.
-// Authors: Illya Rudkin 21/05/2014.
-// Changes: None.
//--
class CMICmdCmdDataListRegisterValues : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdDataListRegisterValues(void);
+ /* ctor */ CMICmdCmdDataListRegisterValues();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdDataListRegisterValues(void) override;
+ /* dtor */ ~CMICmdCmdDataListRegisterValues() override;
// Methods:
private:
lldb::SBValue GetRegister(const MIuint vRegisterIndex) const;
- bool AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue, CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat);
+ void AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue, CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat);
// Attributes:
private:
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgSkip; // Not handled by *this command
const CMIUtilString m_constStrArgFormat;
const CMIUtilString m_constStrArgRegNo;
@@ -269,60 +242,53 @@ class CMICmdCmdDataListRegisterValues : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "data-list-changed-registers".
-// Gotchas: None.
-// Authors: Illya Rudkin 22/05/2014.
-// Changes: None.
//--
class CMICmdCmdDataListRegisterChanged : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdDataListRegisterChanged(void);
+ /* ctor */ CMICmdCmdDataListRegisterChanged();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdDataListRegisterChanged(void) override;
+ /* dtor */ ~CMICmdCmdDataListRegisterChanged() override;
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "data-read-memory-bytes".
-// Gotchas: None.
-// Authors: Illya Rudkin 30/05/2014.
-// Changes: None.
//--
class CMICmdCmdDataWriteMemoryBytes : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdDataWriteMemoryBytes(void);
+ /* ctor */ CMICmdCmdDataWriteMemoryBytes();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdDataWriteMemoryBytes(void) override;
+ /* dtor */ ~CMICmdCmdDataWriteMemoryBytes() override;
// Attributes:
private:
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
const CMIUtilString m_constStrArgAddr;
const CMIUtilString m_constStrArgContents;
const CMIUtilString m_constStrArgCount;
@@ -333,33 +299,29 @@ class CMICmdCmdDataWriteMemoryBytes : public CMICmdBase
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "data-read-memory".
// Not specified in MI spec but Eclipse gives *this command.
-// Gotchas: None.
-// Authors: Illya Rudkin 02/05/2014.
-// Changes: None.
//--
class CMICmdCmdDataWriteMemory : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdDataWriteMemory(void);
+ /* ctor */ CMICmdCmdDataWriteMemory();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdDataWriteMemory(void) override;
+ /* dtor */ ~CMICmdCmdDataWriteMemory() override;
// Attributes:
private:
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
const CMIUtilString m_constStrArgOffset; // Not specified in MI spec but Eclipse gives this option.
const CMIUtilString m_constStrArgAddr; // Not specified in MI spec but Eclipse gives this option.
const CMIUtilString m_constStrArgD; // Not specified in MI spec but Eclipse gives this option.
@@ -381,20 +343,20 @@ class CMICmdCmdDataInfoLine : public CMICmdBase
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdDataInfoLine(void);
+ /* ctor */ CMICmdCmdDataInfoLine();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdDataInfoLine(void) override;
+ /* dtor */ ~CMICmdCmdDataInfoLine() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdEnviro.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdEnviro.cpp
index dd16784..adacc2a 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdEnviro.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdEnviro.cpp
@@ -24,7 +24,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdEnvironmentCd::CMICmdCmdEnvironmentCd(void)
+CMICmdCmdEnvironmentCd::CMICmdCmdEnvironmentCd()
: m_constStrArgNamePathDir("pathdir")
{
// Command factory matches this name with that received from the stdin stream
@@ -41,7 +41,7 @@ CMICmdCmdEnvironmentCd::CMICmdCmdEnvironmentCd(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdEnvironmentCd::~CMICmdCmdEnvironmentCd(void)
+CMICmdCmdEnvironmentCd::~CMICmdCmdEnvironmentCd()
{
}
@@ -55,11 +55,11 @@ CMICmdCmdEnvironmentCd::~CMICmdCmdEnvironmentCd(void)
// Throws: None.
//--
bool
-CMICmdCmdEnvironmentCd::ParseArgs(void)
+CMICmdCmdEnvironmentCd::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValFile(m_constStrArgNamePathDir, true, true)));
+ m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNamePathDir, true, true));
CMICmdArgContext argCntxt(m_cmdData.strMiCmdOption);
- return (bOk && ParseValidateCmdOptions());
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -72,7 +72,7 @@ CMICmdCmdEnvironmentCd::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdEnvironmentCd::Execute(void)
+CMICmdCmdEnvironmentCd::Execute()
{
CMICMDBASE_GETOPTION(pArgPathDir, File, m_constStrArgNamePathDir);
const CMIUtilString &strWkDir(pArgPathDir->GetValue());
@@ -104,7 +104,7 @@ CMICmdCmdEnvironmentCd::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdEnvironmentCd::Acknowledge(void)
+CMICmdCmdEnvironmentCd::Acknowledge()
{
const CMIUtilString &rStrKeyWkDir(m_rLLDBDebugSessionInfo.m_constStrSharedDataKeyWkDir);
CMIUtilString strWkDir;
@@ -131,7 +131,7 @@ CMICmdCmdEnvironmentCd::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdEnvironmentCd::CreateSelf(void)
+CMICmdCmdEnvironmentCd::CreateSelf()
{
return new CMICmdCmdEnvironmentCd();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdEnviro.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdEnviro.h
index 7d5cf98..6f06cb6 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdEnviro.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdEnviro.h
@@ -28,29 +28,26 @@
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "environment-cd".
-// Gotchas: None.
-// Authors: Illya Rudkin 03/03/2014.
-// Changes: None.
//--
class CMICmdCmdEnvironmentCd : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdEnvironmentCd(void);
+ /* ctor */ CMICmdCmdEnvironmentCd();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdEnvironmentCd(void) override;
+ /* dtor */ ~CMICmdCmdEnvironmentCd() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.cpp
index f0208c8..dccfe12 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.cpp
@@ -47,7 +47,8 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecRun::CMICmdCmdExecRun(void)
+CMICmdCmdExecRun::CMICmdCmdExecRun()
+ : m_constStrArgStart("start")
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "exec-run";
@@ -63,11 +64,28 @@ CMICmdCmdExecRun::CMICmdCmdExecRun(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecRun::~CMICmdCmdExecRun(void)
+CMICmdCmdExecRun::~CMICmdCmdExecRun()
{
}
//++ ------------------------------------------------------------------------------------
+// Details: The invoker requires this function. It parses the command line options'
+// arguments to extract values for each of those arguments.
+// Type: Overridden.
+// Args: None.
+// Return: MIstatus::success - Functional succeeded.
+// MIstatus::failure - Functional failed.
+// Throws: None.
+//--
+bool
+CMICmdCmdExecRun::ParseArgs()
+{
+ m_setCmdArgs.Add(
+ new CMICmdArgValOptionLong(m_constStrArgStart, false, true, CMICmdArgValListBase::eArgValType_OptionLong, 0));
+ return ParseValidateCmdOptions();
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command does work in this function.
// The command is likely to communicate with the LLDB SBDebugger in here.
// Type: Overridden.
@@ -77,13 +95,21 @@ CMICmdCmdExecRun::~CMICmdCmdExecRun(void)
// Throws: None.
//--
bool
-CMICmdCmdExecRun::Execute(void)
+CMICmdCmdExecRun::Execute()
{
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
lldb::SBError error;
lldb::SBStream errMsg;
lldb::SBLaunchInfo launchInfo = rSessionInfo.GetTarget().GetLaunchInfo();
launchInfo.SetListener(rSessionInfo.GetListener());
+
+ // Run to first instruction or main() requested?
+ CMICMDBASE_GETOPTION(pArgStart, OptionLong, m_constStrArgStart);
+ if (pArgStart->GetFound())
+ {
+ launchInfo.SetLaunchFlags(launchInfo.GetLaunchFlags() | lldb::eLaunchFlagStopAtEntry);
+ }
+
lldb::SBProcess process = rSessionInfo.GetTarget().Launch(launchInfo, error);
if ((!process.IsValid()) || (error.Fail()))
{
@@ -103,6 +129,7 @@ CMICmdCmdExecRun::Execute(void)
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
+// Called only if Execute() set status as successful on completion.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
@@ -110,33 +137,23 @@ CMICmdCmdExecRun::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdExecRun::Acknowledge(void)
+CMICmdCmdExecRun::Acknowledge()
{
- if (m_lldbResult.GetErrorSize() > 0)
- {
- const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
- const CMICmnMIValueResult miValueResult("message", miValueConst);
- const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
- m_miResultRecord = miRecordResult;
- }
- else
- {
- const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
- m_miResultRecord = miRecordResult;
+ const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
+ m_miResultRecord = miRecordResult;
- CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
- lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID();
- // Give the client '=thread-group-started,id="i1" pid="xyz"'
- m_bHasResultRecordExtra = true;
- const CMICmnMIValueConst miValueConst2("i1");
- const CMICmnMIValueResult miValueResult2("id", miValueConst2);
- const CMIUtilString strPid(CMIUtilString::Format("%lld", pid));
- const CMICmnMIValueConst miValueConst(strPid);
- const CMICmnMIValueResult miValueResult("pid", miValueConst);
- CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2);
- miOutOfBand.Add(miValueResult);
- m_miResultRecordExtra = miOutOfBand.GetString();
- }
+ CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
+ lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID();
+ // Give the client '=thread-group-started,id="i1" pid="xyz"'
+ m_bHasResultRecordExtra = true;
+ const CMICmnMIValueConst miValueConst2("i1");
+ const CMICmnMIValueResult miValueResult2("id", miValueConst2);
+ const CMIUtilString strPid(CMIUtilString::Format("%lld", pid));
+ const CMICmnMIValueConst miValueConst(strPid);
+ const CMICmnMIValueResult miValueResult("pid", miValueConst);
+ CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2);
+ miOutOfBand.Add(miValueResult);
+ m_miResultRecordExtra = miOutOfBand.GetString();
return MIstatus::success;
}
@@ -150,7 +167,7 @@ CMICmdCmdExecRun::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdExecRun::CreateSelf(void)
+CMICmdCmdExecRun::CreateSelf()
{
return new CMICmdCmdExecRun();
}
@@ -166,7 +183,7 @@ CMICmdCmdExecRun::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecContinue::CMICmdCmdExecContinue(void)
+CMICmdCmdExecContinue::CMICmdCmdExecContinue()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "exec-continue";
@@ -182,7 +199,7 @@ CMICmdCmdExecContinue::CMICmdCmdExecContinue(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecContinue::~CMICmdCmdExecContinue(void)
+CMICmdCmdExecContinue::~CMICmdCmdExecContinue()
{
}
@@ -196,7 +213,7 @@ CMICmdCmdExecContinue::~CMICmdCmdExecContinue(void)
// Throws: None.
//--
bool
-CMICmdCmdExecContinue::Execute(void)
+CMICmdCmdExecContinue::Execute()
{
const char *pCmd = "continue";
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
@@ -238,7 +255,7 @@ CMICmdCmdExecContinue::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdExecContinue::Acknowledge(void)
+CMICmdCmdExecContinue::Acknowledge()
{
if (m_lldbResult.GetErrorSize() > 0)
{
@@ -265,7 +282,7 @@ CMICmdCmdExecContinue::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdExecContinue::CreateSelf(void)
+CMICmdCmdExecContinue::CreateSelf()
{
return new CMICmdCmdExecContinue();
}
@@ -281,9 +298,8 @@ CMICmdCmdExecContinue::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecNext::CMICmdCmdExecNext(void)
- : m_constStrArgThread("thread")
- , m_constStrArgNumber("number")
+CMICmdCmdExecNext::CMICmdCmdExecNext()
+ : m_constStrArgNumber("number")
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "exec-next";
@@ -299,7 +315,7 @@ CMICmdCmdExecNext::CMICmdCmdExecNext(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecNext::~CMICmdCmdExecNext(void)
+CMICmdCmdExecNext::~CMICmdCmdExecNext()
{
}
@@ -313,12 +329,10 @@ CMICmdCmdExecNext::~CMICmdCmdExecNext(void)
// Throws: None.
//--
bool
-CMICmdCmdExecNext::ParseArgs(void)
+CMICmdCmdExecNext::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -331,7 +345,7 @@ CMICmdCmdExecNext::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdExecNext::Execute(void)
+CMICmdCmdExecNext::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
@@ -363,7 +377,7 @@ CMICmdCmdExecNext::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdExecNext::Acknowledge(void)
+CMICmdCmdExecNext::Acknowledge()
{
if (m_lldbResult.GetErrorSize() > 0)
{
@@ -392,7 +406,7 @@ CMICmdCmdExecNext::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdExecNext::CreateSelf(void)
+CMICmdCmdExecNext::CreateSelf()
{
return new CMICmdCmdExecNext();
}
@@ -408,9 +422,8 @@ CMICmdCmdExecNext::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecStep::CMICmdCmdExecStep(void)
- : m_constStrArgThread("thread")
- , m_constStrArgNumber("number")
+CMICmdCmdExecStep::CMICmdCmdExecStep()
+ : m_constStrArgNumber("number")
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "exec-step";
@@ -426,7 +439,7 @@ CMICmdCmdExecStep::CMICmdCmdExecStep(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecStep::~CMICmdCmdExecStep(void)
+CMICmdCmdExecStep::~CMICmdCmdExecStep()
{
}
@@ -440,12 +453,10 @@ CMICmdCmdExecStep::~CMICmdCmdExecStep(void)
// Throws: None.
//--
bool
-CMICmdCmdExecStep::ParseArgs(void)
+CMICmdCmdExecStep::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -458,7 +469,7 @@ CMICmdCmdExecStep::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdExecStep::Execute(void)
+CMICmdCmdExecStep::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
@@ -490,7 +501,7 @@ CMICmdCmdExecStep::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdExecStep::Acknowledge(void)
+CMICmdCmdExecStep::Acknowledge()
{
if (m_lldbResult.GetErrorSize() > 0)
{
@@ -519,7 +530,7 @@ CMICmdCmdExecStep::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdExecStep::CreateSelf(void)
+CMICmdCmdExecStep::CreateSelf()
{
return new CMICmdCmdExecStep();
}
@@ -535,9 +546,8 @@ CMICmdCmdExecStep::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecNextInstruction::CMICmdCmdExecNextInstruction(void)
- : m_constStrArgThread("thread")
- , m_constStrArgNumber("number")
+CMICmdCmdExecNextInstruction::CMICmdCmdExecNextInstruction()
+ : m_constStrArgNumber("number")
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "exec-next-instruction";
@@ -553,7 +563,7 @@ CMICmdCmdExecNextInstruction::CMICmdCmdExecNextInstruction(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecNextInstruction::~CMICmdCmdExecNextInstruction(void)
+CMICmdCmdExecNextInstruction::~CMICmdCmdExecNextInstruction()
{
}
@@ -567,12 +577,10 @@ CMICmdCmdExecNextInstruction::~CMICmdCmdExecNextInstruction(void)
// Throws: None.
//--
bool
-CMICmdCmdExecNextInstruction::ParseArgs(void)
+CMICmdCmdExecNextInstruction::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -585,7 +593,7 @@ CMICmdCmdExecNextInstruction::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdExecNextInstruction::Execute(void)
+CMICmdCmdExecNextInstruction::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
@@ -617,7 +625,7 @@ CMICmdCmdExecNextInstruction::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdExecNextInstruction::Acknowledge(void)
+CMICmdCmdExecNextInstruction::Acknowledge()
{
if (m_lldbResult.GetErrorSize() > 0)
{
@@ -646,7 +654,7 @@ CMICmdCmdExecNextInstruction::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdExecNextInstruction::CreateSelf(void)
+CMICmdCmdExecNextInstruction::CreateSelf()
{
return new CMICmdCmdExecNextInstruction();
}
@@ -662,9 +670,8 @@ CMICmdCmdExecNextInstruction::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecStepInstruction::CMICmdCmdExecStepInstruction(void)
- : m_constStrArgThread("thread")
- , m_constStrArgNumber("number")
+CMICmdCmdExecStepInstruction::CMICmdCmdExecStepInstruction()
+ : m_constStrArgNumber("number")
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "exec-step-instruction";
@@ -680,7 +687,7 @@ CMICmdCmdExecStepInstruction::CMICmdCmdExecStepInstruction(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecStepInstruction::~CMICmdCmdExecStepInstruction(void)
+CMICmdCmdExecStepInstruction::~CMICmdCmdExecStepInstruction()
{
}
@@ -694,12 +701,10 @@ CMICmdCmdExecStepInstruction::~CMICmdCmdExecStepInstruction(void)
// Throws: None.
//--
bool
-CMICmdCmdExecStepInstruction::ParseArgs(void)
+CMICmdCmdExecStepInstruction::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -712,7 +717,7 @@ CMICmdCmdExecStepInstruction::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdExecStepInstruction::Execute(void)
+CMICmdCmdExecStepInstruction::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
@@ -744,7 +749,7 @@ CMICmdCmdExecStepInstruction::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdExecStepInstruction::Acknowledge(void)
+CMICmdCmdExecStepInstruction::Acknowledge()
{
if (m_lldbResult.GetErrorSize() > 0)
{
@@ -773,7 +778,7 @@ CMICmdCmdExecStepInstruction::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdExecStepInstruction::CreateSelf(void)
+CMICmdCmdExecStepInstruction::CreateSelf()
{
return new CMICmdCmdExecStepInstruction();
}
@@ -789,9 +794,7 @@ CMICmdCmdExecStepInstruction::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecFinish::CMICmdCmdExecFinish(void)
- : m_constStrArgThread("thread")
- , m_constStrArgFrame("frame")
+CMICmdCmdExecFinish::CMICmdCmdExecFinish()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "exec-finish";
@@ -807,7 +810,7 @@ CMICmdCmdExecFinish::CMICmdCmdExecFinish(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecFinish::~CMICmdCmdExecFinish(void)
+CMICmdCmdExecFinish::~CMICmdCmdExecFinish()
{
}
@@ -821,13 +824,9 @@ CMICmdCmdExecFinish::~CMICmdCmdExecFinish(void)
// Throws: None.
//--
bool
-CMICmdCmdExecFinish::ParseArgs(void)
+CMICmdCmdExecFinish::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, false, CMICmdArgValListBase::eArgValType_Number, 1)));
- return (bOk && ParseValidateCmdOptions());
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -840,7 +839,7 @@ CMICmdCmdExecFinish::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdExecFinish::Execute(void)
+CMICmdCmdExecFinish::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
@@ -872,7 +871,7 @@ CMICmdCmdExecFinish::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdExecFinish::Acknowledge(void)
+CMICmdCmdExecFinish::Acknowledge()
{
if (m_lldbResult.GetErrorSize() > 0)
{
@@ -901,7 +900,7 @@ CMICmdCmdExecFinish::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdExecFinish::CreateSelf(void)
+CMICmdCmdExecFinish::CreateSelf()
{
return new CMICmdCmdExecFinish();
}
@@ -917,7 +916,7 @@ CMICmdCmdExecFinish::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecInterrupt::CMICmdCmdExecInterrupt(void)
+CMICmdCmdExecInterrupt::CMICmdCmdExecInterrupt()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "exec-interrupt";
@@ -933,7 +932,7 @@ CMICmdCmdExecInterrupt::CMICmdCmdExecInterrupt(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecInterrupt::~CMICmdCmdExecInterrupt(void)
+CMICmdCmdExecInterrupt::~CMICmdCmdExecInterrupt()
{
}
@@ -947,7 +946,7 @@ CMICmdCmdExecInterrupt::~CMICmdCmdExecInterrupt(void)
// Throws: None.
//--
bool
-CMICmdCmdExecInterrupt::Execute(void)
+CMICmdCmdExecInterrupt::Execute()
{
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger();
@@ -976,7 +975,7 @@ CMICmdCmdExecInterrupt::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdExecInterrupt::Acknowledge(void)
+CMICmdCmdExecInterrupt::Acknowledge()
{
if (m_lldbResult.GetErrorSize() > 0)
{
@@ -1003,7 +1002,7 @@ CMICmdCmdExecInterrupt::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdExecInterrupt::CreateSelf(void)
+CMICmdCmdExecInterrupt::CreateSelf()
{
return new CMICmdCmdExecInterrupt();
}
@@ -1019,7 +1018,7 @@ CMICmdCmdExecInterrupt::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecArguments::CMICmdCmdExecArguments(void)
+CMICmdCmdExecArguments::CMICmdCmdExecArguments()
: m_constStrArgArguments("arguments")
{
// Command factory matches this name with that received from the stdin stream
@@ -1036,7 +1035,7 @@ CMICmdCmdExecArguments::CMICmdCmdExecArguments(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecArguments::~CMICmdCmdExecArguments(void)
+CMICmdCmdExecArguments::~CMICmdCmdExecArguments()
{
}
@@ -1050,11 +1049,11 @@ CMICmdCmdExecArguments::~CMICmdCmdExecArguments(void)
// Throws: None.
//--
bool
-CMICmdCmdExecArguments::ParseArgs(void)
+CMICmdCmdExecArguments::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(
- *(new CMICmdArgValListOfN(m_constStrArgArguments, false, true, CMICmdArgValListBase::eArgValType_StringAnything)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(
+ new CMICmdArgValListOfN(m_constStrArgArguments, false, true, CMICmdArgValListBase::eArgValType_StringAnything));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -1067,7 +1066,7 @@ CMICmdCmdExecArguments::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdExecArguments::Execute(void)
+CMICmdCmdExecArguments::Execute()
{
CMICMDBASE_GETOPTION(pArgArguments, ListOfN, m_constStrArgArguments);
@@ -1106,7 +1105,7 @@ CMICmdCmdExecArguments::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdExecArguments::Acknowledge(void)
+CMICmdCmdExecArguments::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -1123,7 +1122,7 @@ CMICmdCmdExecArguments::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdExecArguments::CreateSelf(void)
+CMICmdCmdExecArguments::CreateSelf()
{
return new CMICmdCmdExecArguments();
}
@@ -1139,7 +1138,7 @@ CMICmdCmdExecArguments::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecAbort::CMICmdCmdExecAbort(void)
+CMICmdCmdExecAbort::CMICmdCmdExecAbort()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "exec-abort";
@@ -1155,7 +1154,7 @@ CMICmdCmdExecAbort::CMICmdCmdExecAbort(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdExecAbort::~CMICmdCmdExecAbort(void)
+CMICmdCmdExecAbort::~CMICmdCmdExecAbort()
{
}
@@ -1169,7 +1168,7 @@ CMICmdCmdExecAbort::~CMICmdCmdExecAbort(void)
// Throws: None.
//--
bool
-CMICmdCmdExecAbort::Execute(void)
+CMICmdCmdExecAbort::Execute()
{
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
@@ -1199,7 +1198,7 @@ CMICmdCmdExecAbort::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdExecAbort::Acknowledge(void)
+CMICmdCmdExecAbort::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -1215,7 +1214,7 @@ CMICmdCmdExecAbort::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdExecAbort::CreateSelf(void)
+CMICmdCmdExecAbort::CreateSelf()
{
return new CMICmdCmdExecAbort();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.h
index 94d646f..c131132 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdExec.h
@@ -38,59 +38,55 @@
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "exec-run".
-// Gotchas: None.
-// Authors: Illya Rudkin 07/03/2014.
-// Changes: None.
//--
class CMICmdCmdExecRun : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdExecRun(void);
+ /* ctor */ CMICmdCmdExecRun();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdExecRun(void) override;
+ /* dtor */ ~CMICmdCmdExecRun() override;
// Attributes:
private:
+ const CMIUtilString m_constStrArgStart; // StopAtEntry - run to first instruction or main() if specified
lldb::SBCommandReturnObject m_lldbResult;
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "exec-continue".
-// Gotchas: None.
-// Authors: Illya Rudkin 07/03/2014.
-// Changes: None.
//--
class CMICmdCmdExecContinue : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdExecContinue(void);
+ /* ctor */ CMICmdCmdExecContinue();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdExecContinue(void) override;
+ /* dtor */ ~CMICmdCmdExecContinue() override;
// Attributes:
private:
@@ -100,171 +96,150 @@ class CMICmdCmdExecContinue : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "exec-next".
-// Gotchas: None.
-// Authors: Illya Rudkin 25/03/2014.
-// Changes: None.
//--
class CMICmdCmdExecNext : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdExecNext(void);
+ /* ctor */ CMICmdCmdExecNext();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdExecNext(void) override;
+ /* dtor */ ~CMICmdCmdExecNext() override;
// Attributes:
private:
lldb::SBCommandReturnObject m_lldbResult;
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "exec-step".
-// Gotchas: None.
-// Authors: Illya Rudkin 25/03/2014.
-// Changes: None.
//--
class CMICmdCmdExecStep : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdExecStep(void);
+ /* ctor */ CMICmdCmdExecStep();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdExecStep(void) override;
+ /* dtor */ ~CMICmdCmdExecStep() override;
// Attributes:
private:
lldb::SBCommandReturnObject m_lldbResult;
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "exec-next-instruction".
-// Gotchas: None.
-// Authors: Illya Rudkin 25/03/2014.
-// Changes: None.
//--
class CMICmdCmdExecNextInstruction : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdExecNextInstruction(void);
+ /* ctor */ CMICmdCmdExecNextInstruction();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdExecNextInstruction(void) override;
+ /* dtor */ ~CMICmdCmdExecNextInstruction() override;
// Attributes:
private:
lldb::SBCommandReturnObject m_lldbResult;
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "exec-step-instruction".
-// Gotchas: None.
-// Authors: Illya Rudkin 25/03/2014.
-// Changes: None.
//--
class CMICmdCmdExecStepInstruction : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdExecStepInstruction(void);
+ /* ctor */ CMICmdCmdExecStepInstruction();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdExecStepInstruction(void) override;
+ /* dtor */ ~CMICmdCmdExecStepInstruction() override;
// Attributes:
private:
lldb::SBCommandReturnObject m_lldbResult;
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "exec-finish".
-// Gotchas: None.
-// Authors: Illya Rudkin 25/03/2014.
-// Changes: None.
//--
class CMICmdCmdExecFinish : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdExecFinish(void);
+ /* ctor */ CMICmdCmdExecFinish();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdExecFinish(void) override;
+ /* dtor */ ~CMICmdCmdExecFinish() override;
// Attributes:
private:
lldb::SBCommandReturnObject m_lldbResult;
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
- const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option
};
// CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
@@ -273,27 +248,25 @@ class CMICmdCmdExecFinish : public CMICmdBase
// *this class implements MI command "exec-interrupt".
// Gotchas: Using Eclipse this command is injected into the command system when a
// SIGINT signal is received while running an inferior program.
-// Authors: Illya Rudkin 03/06/2014.
-// Changes: None.
//--
class CMICmdCmdExecInterrupt : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdExecInterrupt(void);
+ /* ctor */ CMICmdCmdExecInterrupt();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdExecInterrupt(void) override;
+ /* dtor */ ~CMICmdCmdExecInterrupt() override;
// Attributes:
private:
@@ -303,29 +276,26 @@ class CMICmdCmdExecInterrupt : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "exec-arguments".
-// Gotchas: None.
-// Authors: Ilia Kirianovskii 25/11/2014.
-// Changes: None.
//--
class CMICmdCmdExecArguments : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdExecArguments(void);
+ /* ctor */ CMICmdCmdExecArguments();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdExecArguments(void) override;
+ /* dtor */ ~CMICmdCmdExecArguments() override;
// Attributes:
private:
@@ -341,17 +311,17 @@ class CMICmdCmdExecAbort : public CMICmdBase
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdExecAbort(void);
+ /* ctor */ CMICmdCmdExecAbort();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdExecAbort(void) override;
+ /* dtor */ ~CMICmdCmdExecAbort() override;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdFile.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdFile.cpp
index b28060e..3316c8e 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdFile.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdFile.cpp
@@ -30,9 +30,8 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdFileExecAndSymbols::CMICmdCmdFileExecAndSymbols(void)
+CMICmdCmdFileExecAndSymbols::CMICmdCmdFileExecAndSymbols()
: m_constStrArgNameFile("file")
- , m_constStrArgThreadGrp("thread-group")
, m_constStrArgNamedPlatformName("p")
, m_constStrArgNamedRemotePath("r")
{
@@ -50,7 +49,7 @@ CMICmdCmdFileExecAndSymbols::CMICmdCmdFileExecAndSymbols(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdFileExecAndSymbols::~CMICmdCmdFileExecAndSymbols(void)
+CMICmdCmdFileExecAndSymbols::~CMICmdCmdFileExecAndSymbols()
{
}
@@ -64,18 +63,14 @@ CMICmdCmdFileExecAndSymbols::~CMICmdCmdFileExecAndSymbols(void)
// Throws: None.
//--
bool
-CMICmdCmdFileExecAndSymbols::ParseArgs(void)
+CMICmdCmdFileExecAndSymbols::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValFile(m_constStrArgNameFile, true, true)));
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedPlatformName, false, true,
- CMICmdArgValListBase::eArgValType_String, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedRemotePath, false, true,
- CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNameFile, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedPlatformName, false, true,
+ CMICmdArgValListBase::eArgValType_String, 1));
+ m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedRemotePath, false, true,
+ CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -90,7 +85,7 @@ CMICmdCmdFileExecAndSymbols::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdFileExecAndSymbols::Execute(void)
+CMICmdCmdFileExecAndSymbols::Execute()
{
CMICMDBASE_GETOPTION(pArgNamedFile, File, m_constStrArgNameFile);
CMICMDBASE_GETOPTION(pArgPlatformName, OptionShort, m_constStrArgNamedPlatformName);
@@ -168,7 +163,7 @@ CMICmdCmdFileExecAndSymbols::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdFileExecAndSymbols::Acknowledge(void)
+CMICmdCmdFileExecAndSymbols::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -185,7 +180,7 @@ CMICmdCmdFileExecAndSymbols::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdFileExecAndSymbols::CreateSelf(void)
+CMICmdCmdFileExecAndSymbols::CreateSelf()
{
return new CMICmdCmdFileExecAndSymbols();
}
@@ -202,7 +197,7 @@ CMICmdCmdFileExecAndSymbols::CreateSelf(void)
// Throws: None.
//--
bool
-CMICmdCmdFileExecAndSymbols::GetExitAppOnCommandFailure(void) const
+CMICmdCmdFileExecAndSymbols::GetExitAppOnCommandFailure() const
{
return true;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdFile.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdFile.h
index 2c1b59c..b6bf5e5 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdFile.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdFile.h
@@ -31,35 +31,31 @@
// This command does not follow the MI documentation exactly.
// Gotchas: This command has additional flags that were not available in GDB MI.
// See MIextensions.txt for details.
-// Authors: Illya Rudkin 25/02/2014.
-// Changes: None.
//--
class CMICmdCmdFileExecAndSymbols : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdFileExecAndSymbols(void);
+ /* ctor */ CMICmdCmdFileExecAndSymbols();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdFileExecAndSymbols(void) override;
- bool GetExitAppOnCommandFailure(void) const override;
+ /* dtor */ ~CMICmdCmdFileExecAndSymbols() override;
+ bool GetExitAppOnCommandFailure() const override;
// Attributes:
private:
const CMIUtilString m_constStrArgNameFile;
- const CMIUtilString
- m_constStrArgThreadGrp; // Not handled by *this command. Not specified in MI spec but Eclipse gives this option sometimes
const CMIUtilString m_constStrArgNamedPlatformName; // Added to support iOS platform selection
const CMIUtilString m_constStrArgNamedRemotePath; // Added to support iOS device remote file location
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbInfo.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbInfo.cpp
index 25e0ff4..c57c4ac 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbInfo.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbInfo.cpp
@@ -1,4 +1,4 @@
-//===-- MICmdCmdGdbInfo.cpp ------------------------*- C++ -*-===//
+//===-- MICmdCmdGdbInfo.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -32,7 +32,7 @@ const CMICmdCmdGdbInfo::MapPrintFnNameToPrintFn_t CMICmdCmdGdbInfo::ms_mapPrintF
// Return: None.
// Throws: None.
//--
-CMICmdCmdGdbInfo::CMICmdCmdGdbInfo(void)
+CMICmdCmdGdbInfo::CMICmdCmdGdbInfo()
: m_constStrArgNamedPrint("print")
, m_bPrintFnRecognised(true)
, m_bPrintFnSuccessful(false)
@@ -52,7 +52,7 @@ CMICmdCmdGdbInfo::CMICmdCmdGdbInfo(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdGdbInfo::~CMICmdCmdGdbInfo(void)
+CMICmdCmdGdbInfo::~CMICmdCmdGdbInfo()
{
}
@@ -66,10 +66,10 @@ CMICmdCmdGdbInfo::~CMICmdCmdGdbInfo(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbInfo::ParseArgs(void)
+CMICmdCmdGdbInfo::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedPrint, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedPrint, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -82,7 +82,7 @@ CMICmdCmdGdbInfo::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbInfo::Execute(void)
+CMICmdCmdGdbInfo::Execute()
{
CMICMDBASE_GETOPTION(pArgPrint, String, m_constStrArgNamedPrint);
const CMIUtilString &rPrintRequest(pArgPrint->GetValue());
@@ -110,7 +110,7 @@ CMICmdCmdGdbInfo::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbInfo::Acknowledge(void)
+CMICmdCmdGdbInfo::Acknowledge()
{
if (!m_bPrintFnRecognised)
{
@@ -145,7 +145,7 @@ CMICmdCmdGdbInfo::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdGdbInfo::CreateSelf(void)
+CMICmdCmdGdbInfo::CreateSelf()
{
return new CMICmdCmdGdbInfo();
}
@@ -183,7 +183,7 @@ CMICmdCmdGdbInfo::GetPrintFn(const CMIUtilString &vrPrintFnName, FnPrintPtr &vrw
// Throws: None.
//--
bool
-CMICmdCmdGdbInfo::PrintFnSharedLibrary(void)
+CMICmdCmdGdbInfo::PrintFnSharedLibrary()
{
CMICmnStreamStdout &rStdout = CMICmnStreamStdout::Instance();
bool bOk = rStdout.TextToStdout("~\"From To Syms Read Shared Object Library\"");
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbInfo.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbInfo.h
index a1b5770..6a7a213 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbInfo.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbInfo.h
@@ -1,4 +1,4 @@
-//===-- MICmdCmdGdbInfo.h --------------------------*- C++ -*-===//
+//===-- MICmdCmdGdbInfo.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -37,29 +37,26 @@
// class instantiates a request info command for a matching request. The
// design/code of *this class then does not then become bloated. Use a
// lightweight version of the current MI command system.
-// Gotchas: None.
-// Authors: Illya Rudkin 05/06/2014.
-// Changes: None.
//--
class CMICmdCmdGdbInfo : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdGdbInfo(void);
+ /* ctor */ CMICmdCmdGdbInfo();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdGdbInfo(void) override;
+ /* dtor */ ~CMICmdCmdGdbInfo() override;
// Typedefs:
private:
@@ -69,7 +66,7 @@ class CMICmdCmdGdbInfo : public CMICmdBase
// Methods:
private:
bool GetPrintFn(const CMIUtilString &vrPrintFnName, FnPrintPtr &vrwpFn) const;
- bool PrintFnSharedLibrary(void);
+ bool PrintFnSharedLibrary();
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.cpp
index 452ac51..1d68b0b 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.cpp
@@ -34,9 +34,8 @@ const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t CMICmdCmdGdbSet::ms_ma
// Return: None.
// Throws: None.
//--
-CMICmdCmdGdbSet::CMICmdCmdGdbSet(void)
- : m_constStrArgNamedThreadGrp("thread-group")
- , m_constStrArgNamedGdbOption("option")
+CMICmdCmdGdbSet::CMICmdCmdGdbSet()
+ : m_constStrArgNamedGdbOption("option")
, m_bGdbOptionRecognised(true)
, m_bGdbOptionFnSuccessful(false)
, m_bGbbOptionFnHasError(false)
@@ -56,7 +55,7 @@ CMICmdCmdGdbSet::CMICmdCmdGdbSet(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdGdbSet::~CMICmdCmdGdbSet(void)
+CMICmdCmdGdbSet::~CMICmdCmdGdbSet()
{
}
@@ -70,14 +69,11 @@ CMICmdCmdGdbSet::~CMICmdCmdGdbSet(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbSet::ParseArgs(void)
+CMICmdCmdGdbSet::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(
- *(new CMICmdArgValListOfN(m_constStrArgNamedGdbOption, true, true, CMICmdArgValListBase::eArgValType_StringAnything)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(
+ new CMICmdArgValListOfN(m_constStrArgNamedGdbOption, true, true, CMICmdArgValListBase::eArgValType_StringAnything));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -90,7 +86,7 @@ CMICmdCmdGdbSet::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbSet::Execute(void)
+CMICmdCmdGdbSet::Execute()
{
CMICMDBASE_GETOPTION(pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption);
const CMICmdArgValListBase::VecArgObjPtr_t &rVecWords(pArgGdbOption->GetExpectedOptions());
@@ -143,7 +139,7 @@ CMICmdCmdGdbSet::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbSet::Acknowledge(void)
+CMICmdCmdGdbSet::Acknowledge()
{
// Print error if option isn't recognized:
// ^error,msg="The request '%s' was not recognized, not implemented"
@@ -184,7 +180,7 @@ CMICmdCmdGdbSet::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdGdbSet::CreateSelf(void)
+CMICmdCmdGdbSet::CreateSelf()
{
return new CMICmdCmdGdbSet();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.h
index 84d21f0..db33f65 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.h
@@ -37,29 +37,26 @@
// class instantiates a request info command for a matching request. The
// design/code of *this class then does not then become bloated. Use a
// lightweight version of the current MI command system.
-// Gotchas: None.
-// Authors: Illya Rudkin 03/03/2014.
-// Changes: None.
//--
class CMICmdCmdGdbSet : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdGdbSet(void);
+ /* ctor */ CMICmdCmdGdbSet();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdGdbSet(void) override;
+ /* dtor */ ~CMICmdCmdGdbSet() override;
// Typedefs:
private:
@@ -79,7 +76,6 @@ class CMICmdCmdGdbSet : public CMICmdBase
private:
const static MapGdbOptionNameToFnGdbOptionPtr_t ms_mapGdbOptionNameToFnGdbOptionPtr;
//
- const CMIUtilString m_constStrArgNamedThreadGrp;
const CMIUtilString m_constStrArgNamedGdbOption;
bool m_bGdbOptionRecognised; // True = This command has a function with a name that matches the Print argument, false = not found
bool m_bGdbOptionFnSuccessful; // True = The print function completed its task ok, false = function failed for some reason
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbShow.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbShow.cpp
index f1f40cc..147e767 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbShow.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbShow.cpp
@@ -38,9 +38,8 @@ const CMICmdCmdGdbShow::MapGdbOptionNameToFnGdbOptionPtr_t CMICmdCmdGdbShow::ms_
// Return: None.
// Throws: None.
//--
-CMICmdCmdGdbShow::CMICmdCmdGdbShow(void)
- : m_constStrArgNamedThreadGrp("thread-group")
- , m_constStrArgNamedGdbOption("option")
+CMICmdCmdGdbShow::CMICmdCmdGdbShow()
+ : m_constStrArgNamedGdbOption("option")
, m_bGdbOptionRecognised(true)
, m_bGdbOptionFnSuccessful(false)
, m_bGbbOptionFnHasError(false)
@@ -60,7 +59,7 @@ CMICmdCmdGdbShow::CMICmdCmdGdbShow(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdGdbShow::~CMICmdCmdGdbShow(void)
+CMICmdCmdGdbShow::~CMICmdCmdGdbShow()
{
}
@@ -74,14 +73,11 @@ CMICmdCmdGdbShow::~CMICmdCmdGdbShow(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbShow::ParseArgs(void)
+CMICmdCmdGdbShow::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(
- *(new CMICmdArgValListOfN(m_constStrArgNamedGdbOption, true, true, CMICmdArgValListBase::eArgValType_StringAnything)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(
+ new CMICmdArgValListOfN(m_constStrArgNamedGdbOption, true, true, CMICmdArgValListBase::eArgValType_StringAnything));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -93,7 +89,7 @@ CMICmdCmdGdbShow::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbShow::Execute(void)
+CMICmdCmdGdbShow::Execute()
{
CMICMDBASE_GETOPTION(pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption);
const CMICmdArgValListBase::VecArgObjPtr_t &rVecWords(pArgGdbOption->GetExpectedOptions());
@@ -146,7 +142,7 @@ CMICmdCmdGdbShow::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbShow::Acknowledge(void)
+CMICmdCmdGdbShow::Acknowledge()
{
// Print error if option isn't recognized:
// ^error,msg="The request '%s' was not recognized, not implemented"
@@ -196,7 +192,7 @@ CMICmdCmdGdbShow::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdGdbShow::CreateSelf(void)
+CMICmdCmdGdbShow::CreateSelf()
{
return new CMICmdCmdGdbShow();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbShow.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbShow.h
index 6ca5ef8..9341053 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbShow.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbShow.h
@@ -43,20 +43,20 @@ class CMICmdCmdGdbShow : public CMICmdBase
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdGdbShow(void);
+ /* ctor */ CMICmdCmdGdbShow();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdGdbShow(void) override;
+ /* dtor */ ~CMICmdCmdGdbShow() override;
// Typedefs:
private:
@@ -74,8 +74,7 @@ class CMICmdCmdGdbShow : public CMICmdBase
// Attributes:
private:
const static MapGdbOptionNameToFnGdbOptionPtr_t ms_mapGdbOptionNameToFnGdbOptionPtr;
- //
- const CMIUtilString m_constStrArgNamedThreadGrp;
+
const CMIUtilString m_constStrArgNamedGdbOption;
bool m_bGdbOptionRecognised; // True = This command has a function with a name that matches the Print argument, false = not found
bool m_bGdbOptionFnSuccessful; // True = The print function completed its task ok, false = function failed for some reason
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbThread.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbThread.cpp
index 40f2eec..5f71b05 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbThread.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbThread.cpp
@@ -21,7 +21,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdGdbThread::CMICmdCmdGdbThread(void)
+CMICmdCmdGdbThread::CMICmdCmdGdbThread()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "thread";
@@ -37,7 +37,7 @@ CMICmdCmdGdbThread::CMICmdCmdGdbThread(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdGdbThread::~CMICmdCmdGdbThread(void)
+CMICmdCmdGdbThread::~CMICmdCmdGdbThread()
{
}
@@ -51,7 +51,7 @@ CMICmdCmdGdbThread::~CMICmdCmdGdbThread(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbThread::Execute(void)
+CMICmdCmdGdbThread::Execute()
{
// Do nothing
@@ -68,7 +68,7 @@ CMICmdCmdGdbThread::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbThread::Acknowledge(void)
+CMICmdCmdGdbThread::Acknowledge()
{
const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
const CMICmnMIValueResult miValueResult("msg", miValueConst);
@@ -87,7 +87,7 @@ CMICmdCmdGdbThread::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdGdbThread::CreateSelf(void)
+CMICmdCmdGdbThread::CreateSelf()
{
return new CMICmdCmdGdbThread();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbThread.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbThread.h
index 6a3804a..40d8b78 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbThread.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbThread.h
@@ -26,26 +26,23 @@
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements GDB command "thread".
-// Gotchas: None.
-// Authors: Illya Rudkin 25/02/2014.
-// Changes: None.
//--
class CMICmdCmdGdbThread : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdGdbThread(void);
+ /* ctor */ CMICmdCmdGdbThread();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdGdbThread(void) override;
+ /* dtor */ ~CMICmdCmdGdbThread() override;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdMiscellanous.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdMiscellanous.cpp
index 3abc7c4..d534a6f 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdMiscellanous.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdMiscellanous.cpp
@@ -41,7 +41,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdGdbExit::CMICmdCmdGdbExit(void)
+CMICmdCmdGdbExit::CMICmdCmdGdbExit()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "gdb-exit";
@@ -57,7 +57,7 @@ CMICmdCmdGdbExit::CMICmdCmdGdbExit(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdGdbExit::~CMICmdCmdGdbExit(void)
+CMICmdCmdGdbExit::~CMICmdCmdGdbExit()
{
}
@@ -71,7 +71,7 @@ CMICmdCmdGdbExit::~CMICmdCmdGdbExit(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbExit::Execute(void)
+CMICmdCmdGdbExit::Execute()
{
CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(true);
const lldb::SBError sbErr = m_rLLDBDebugSessionInfo.GetProcess().Destroy();
@@ -90,7 +90,7 @@ CMICmdCmdGdbExit::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdGdbExit::Acknowledge(void)
+CMICmdCmdGdbExit::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Exit);
m_miResultRecord = miRecordResult;
@@ -115,7 +115,7 @@ CMICmdCmdGdbExit::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdGdbExit::CreateSelf(void)
+CMICmdCmdGdbExit::CreateSelf()
{
return new CMICmdCmdGdbExit();
}
@@ -131,7 +131,7 @@ CMICmdCmdGdbExit::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdListThreadGroups::CMICmdCmdListThreadGroups(void)
+CMICmdCmdListThreadGroups::CMICmdCmdListThreadGroups()
: m_bIsI1(false)
, m_bHaveArgOption(false)
, m_bHaveArgRecurse(false)
@@ -154,7 +154,7 @@ CMICmdCmdListThreadGroups::CMICmdCmdListThreadGroups(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdListThreadGroups::~CMICmdCmdListThreadGroups(void)
+CMICmdCmdListThreadGroups::~CMICmdCmdListThreadGroups()
{
m_vecMIValueTuple.clear();
}
@@ -169,16 +169,14 @@ CMICmdCmdListThreadGroups::~CMICmdCmdListThreadGroups(void)
// Throws: None.
//--
bool
-CMICmdCmdListThreadGroups::ParseArgs(void)
+CMICmdCmdListThreadGroups::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgNamedAvailable, false, true)));
- bOk = bOk &&
- m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgNamedRecurse, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk =
- bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedGroup, false, true, CMICmdArgValListBase::eArgValType_Number)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValThreadGrp(m_constStrArgNamedThreadGroup, false, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgNamedAvailable, false, true));
+ m_setCmdArgs.Add(
+ new CMICmdArgValOptionLong(m_constStrArgNamedRecurse, false, true, CMICmdArgValListBase::eArgValType_Number, 1));
+ m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedGroup, false, true, CMICmdArgValListBase::eArgValType_Number));
+ m_setCmdArgs.Add(new CMICmdArgValThreadGrp(m_constStrArgNamedThreadGroup, false, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -196,7 +194,7 @@ CMICmdCmdListThreadGroups::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdListThreadGroups::Execute(void)
+CMICmdCmdListThreadGroups::Execute()
{
if (m_setCmdArgs.IsArgContextEmpty())
// No options so "top level thread groups"
@@ -259,7 +257,7 @@ CMICmdCmdListThreadGroups::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdListThreadGroups::Acknowledge(void)
+CMICmdCmdListThreadGroups::Acknowledge()
{
if (m_bHaveArgOption)
{
@@ -382,7 +380,7 @@ CMICmdCmdListThreadGroups::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdListThreadGroups::CreateSelf(void)
+CMICmdCmdListThreadGroups::CreateSelf()
{
return new CMICmdCmdListThreadGroups();
}
@@ -398,7 +396,7 @@ CMICmdCmdListThreadGroups::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdInterpreterExec::CMICmdCmdInterpreterExec(void)
+CMICmdCmdInterpreterExec::CMICmdCmdInterpreterExec()
: m_constStrArgNamedInterpreter("interpreter")
, m_constStrArgNamedCommand("command")
{
@@ -416,7 +414,7 @@ CMICmdCmdInterpreterExec::CMICmdCmdInterpreterExec(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdInterpreterExec::~CMICmdCmdInterpreterExec(void)
+CMICmdCmdInterpreterExec::~CMICmdCmdInterpreterExec()
{
}
@@ -430,11 +428,11 @@ CMICmdCmdInterpreterExec::~CMICmdCmdInterpreterExec(void)
// Throws: None.
//--
bool
-CMICmdCmdInterpreterExec::ParseArgs(void)
+CMICmdCmdInterpreterExec::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedInterpreter, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedCommand, true, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedInterpreter, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedCommand, true, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -447,7 +445,7 @@ CMICmdCmdInterpreterExec::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdInterpreterExec::Execute(void)
+CMICmdCmdInterpreterExec::Execute()
{
CMICMDBASE_GETOPTION(pArgInterpreter, String, m_constStrArgNamedInterpreter);
CMICMDBASE_GETOPTION(pArgCommand, String, m_constStrArgNamedCommand);
@@ -476,7 +474,7 @@ CMICmdCmdInterpreterExec::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdInterpreterExec::Acknowledge(void)
+CMICmdCmdInterpreterExec::Acknowledge()
{
if (m_lldbResult.GetOutputSize() > 0)
{
@@ -506,7 +504,7 @@ CMICmdCmdInterpreterExec::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdInterpreterExec::CreateSelf(void)
+CMICmdCmdInterpreterExec::CreateSelf()
{
return new CMICmdCmdInterpreterExec();
}
@@ -522,7 +520,7 @@ CMICmdCmdInterpreterExec::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdInferiorTtySet::CMICmdCmdInferiorTtySet(void)
+CMICmdCmdInferiorTtySet::CMICmdCmdInferiorTtySet()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "inferior-tty-set";
@@ -538,7 +536,7 @@ CMICmdCmdInferiorTtySet::CMICmdCmdInferiorTtySet(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdInferiorTtySet::~CMICmdCmdInferiorTtySet(void)
+CMICmdCmdInferiorTtySet::~CMICmdCmdInferiorTtySet()
{
}
@@ -552,7 +550,7 @@ CMICmdCmdInferiorTtySet::~CMICmdCmdInferiorTtySet(void)
// Throws: None.
//--
bool
-CMICmdCmdInferiorTtySet::Execute(void)
+CMICmdCmdInferiorTtySet::Execute()
{
// Do nothing
@@ -569,7 +567,7 @@ CMICmdCmdInferiorTtySet::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdInferiorTtySet::Acknowledge(void)
+CMICmdCmdInferiorTtySet::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error);
m_miResultRecord = miRecordResult;
@@ -586,7 +584,7 @@ CMICmdCmdInferiorTtySet::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdInferiorTtySet::CreateSelf(void)
+CMICmdCmdInferiorTtySet::CreateSelf()
{
return new CMICmdCmdInferiorTtySet();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdMiscellanous.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdMiscellanous.h
index 8765549..9f82195 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdMiscellanous.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdMiscellanous.h
@@ -34,28 +34,25 @@
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "gdb-exit".
-// Gotchas: None.
-// Authors: Illya Rudkin 04/03/2014.
-// Changes: None.
//--
class CMICmdCmdGdbExit : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdGdbExit(void);
+ /* ctor */ CMICmdCmdGdbExit();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdGdbExit(void) override;
+ /* dtor */ ~CMICmdCmdGdbExit() override;
};
//++ ============================================================================
@@ -63,29 +60,26 @@ class CMICmdCmdGdbExit : public CMICmdBase
// *this class implements MI command "list-thread-groups".
// This command does not follow the MI documentation exactly.
// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands
-// Gotchas: None.
-// Authors: Illya Rudkin 06/03/2014.
-// Changes: None.
//--
class CMICmdCmdListThreadGroups : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdListThreadGroups(void);
+ /* ctor */ CMICmdCmdListThreadGroups();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdListThreadGroups(void) override;
+ /* dtor */ ~CMICmdCmdListThreadGroups() override;
// Typedefs:
private:
@@ -106,29 +100,26 @@ class CMICmdCmdListThreadGroups : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "interpreter-exec".
-// Gotchas: None.
-// Authors: Illya Rudkin 16/05/2014.
-// Changes: None.
//--
class CMICmdCmdInterpreterExec : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdInterpreterExec(void);
+ /* ctor */ CMICmdCmdInterpreterExec();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdInterpreterExec(void) override;
+ /* dtor */ ~CMICmdCmdInterpreterExec() override;
// Attributes:
private:
@@ -140,26 +131,23 @@ class CMICmdCmdInterpreterExec : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "inferior-tty-set".
-// Gotchas: None.
-// Authors: Illya Rudkin 22/07/2014.
-// Changes: None.
//--
class CMICmdCmdInferiorTtySet : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdInferiorTtySet(void);
+ /* ctor */ CMICmdCmdInferiorTtySet();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdInferiorTtySet(void) override;
+ /* dtor */ ~CMICmdCmdInferiorTtySet() override;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdStack.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdStack.cpp
index 7f767e7..bc34833 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdStack.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdStack.cpp
@@ -39,9 +39,8 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackInfoDepth::CMICmdCmdStackInfoDepth(void)
+CMICmdCmdStackInfoDepth::CMICmdCmdStackInfoDepth()
: m_nThreadFrames(0)
- , m_constStrArgThread("thread")
, m_constStrArgMaxDepth("max-depth")
{
// Command factory matches this name with that received from the stdin stream
@@ -58,7 +57,7 @@ CMICmdCmdStackInfoDepth::CMICmdCmdStackInfoDepth(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth(void)
+CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth()
{
}
@@ -72,12 +71,10 @@ CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth(void)
// Throws: None.
//--
bool
-CMICmdCmdStackInfoDepth::ParseArgs(void)
+CMICmdCmdStackInfoDepth::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgMaxDepth, false, false)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMaxDepth, false, false));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -90,7 +87,7 @@ CMICmdCmdStackInfoDepth::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdStackInfoDepth::Execute(void)
+CMICmdCmdStackInfoDepth::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
CMICMDBASE_GETOPTION(pArgMaxDepth, Number, m_constStrArgMaxDepth);
@@ -121,7 +118,7 @@ CMICmdCmdStackInfoDepth::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdStackInfoDepth::Acknowledge(void)
+CMICmdCmdStackInfoDepth::Acknowledge()
{
const CMIUtilString strDepth(CMIUtilString::Format("%d", m_nThreadFrames));
const CMICmnMIValueConst miValueConst(strDepth);
@@ -141,7 +138,7 @@ CMICmdCmdStackInfoDepth::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdStackInfoDepth::CreateSelf(void)
+CMICmdCmdStackInfoDepth::CreateSelf()
{
return new CMICmdCmdStackInfoDepth();
}
@@ -157,7 +154,7 @@ CMICmdCmdStackInfoDepth::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackInfoFrame::CMICmdCmdStackInfoFrame(void)
+CMICmdCmdStackInfoFrame::CMICmdCmdStackInfoFrame()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "stack-info-frame";
@@ -173,7 +170,7 @@ CMICmdCmdStackInfoFrame::CMICmdCmdStackInfoFrame(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackInfoFrame::~CMICmdCmdStackInfoFrame(void)
+CMICmdCmdStackInfoFrame::~CMICmdCmdStackInfoFrame()
{
}
@@ -187,7 +184,7 @@ CMICmdCmdStackInfoFrame::~CMICmdCmdStackInfoFrame(void)
// Throws: None.
//--
bool
-CMICmdCmdStackInfoFrame::ParseArgs(void)
+CMICmdCmdStackInfoFrame::ParseArgs()
{
return ParseValidateCmdOptions();
}
@@ -202,7 +199,7 @@ CMICmdCmdStackInfoFrame::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdStackInfoFrame::Execute(void)
+CMICmdCmdStackInfoFrame::Execute()
{
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
@@ -230,7 +227,7 @@ CMICmdCmdStackInfoFrame::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdStackInfoFrame::Acknowledge(void)
+CMICmdCmdStackInfoFrame::Acknowledge()
{
const CMICmnMIValueResult miValueResult("frame", m_miValueTuple);
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
@@ -248,7 +245,7 @@ CMICmdCmdStackInfoFrame::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdStackInfoFrame::CreateSelf(void)
+CMICmdCmdStackInfoFrame::CreateSelf()
{
return new CMICmdCmdStackInfoFrame();
}
@@ -264,9 +261,8 @@ CMICmdCmdStackInfoFrame::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackListFrames::CMICmdCmdStackListFrames(void)
+CMICmdCmdStackListFrames::CMICmdCmdStackListFrames()
: m_nThreadFrames(0)
- , m_constStrArgThread("thread")
, m_constStrArgFrameLow("low-frame")
, m_constStrArgFrameHigh("high-frame")
{
@@ -284,7 +280,7 @@ CMICmdCmdStackListFrames::CMICmdCmdStackListFrames(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames(void)
+CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames()
{
m_vecMIValueResult.clear();
}
@@ -299,13 +295,11 @@ CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListFrames::ParseArgs(void)
+CMICmdCmdStackListFrames::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true));
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -318,7 +312,7 @@ CMICmdCmdStackListFrames::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListFrames::Execute(void)
+CMICmdCmdStackListFrames::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
CMICMDBASE_GETOPTION(pArgFrameLow, Number, m_constStrArgFrameLow);
@@ -377,7 +371,7 @@ CMICmdCmdStackListFrames::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListFrames::Acknowledge(void)
+CMICmdCmdStackListFrames::Acknowledge()
{
if (m_nThreadFrames == 0)
{
@@ -429,7 +423,7 @@ CMICmdCmdStackListFrames::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdStackListFrames::CreateSelf(void)
+CMICmdCmdStackListFrames::CreateSelf()
{
return new CMICmdCmdStackListFrames();
}
@@ -445,10 +439,9 @@ CMICmdCmdStackListFrames::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackListArguments::CMICmdCmdStackListArguments(void)
+CMICmdCmdStackListArguments::CMICmdCmdStackListArguments()
: m_bThreadInvalid(false)
, m_miValueList(true)
- , m_constStrArgThread("thread")
, m_constStrArgPrintValues("print-values")
, m_constStrArgFrameLow("low-frame")
, m_constStrArgFrameHigh("high-frame")
@@ -467,7 +460,7 @@ CMICmdCmdStackListArguments::CMICmdCmdStackListArguments(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments(void)
+CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments()
{
}
@@ -481,14 +474,12 @@ CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListArguments::ParseArgs(void)
+CMICmdCmdStackListArguments::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true));
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -501,7 +492,7 @@ CMICmdCmdStackListArguments::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListArguments::Execute(void)
+CMICmdCmdStackListArguments::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues);
@@ -587,7 +578,7 @@ CMICmdCmdStackListArguments::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListArguments::Acknowledge(void)
+CMICmdCmdStackListArguments::Acknowledge()
{
if (m_bThreadInvalid)
{
@@ -616,7 +607,7 @@ CMICmdCmdStackListArguments::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdStackListArguments::CreateSelf(void)
+CMICmdCmdStackListArguments::CreateSelf()
{
return new CMICmdCmdStackListArguments();
}
@@ -632,11 +623,9 @@ CMICmdCmdStackListArguments::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackListLocals::CMICmdCmdStackListLocals(void)
+CMICmdCmdStackListLocals::CMICmdCmdStackListLocals()
: m_bThreadInvalid(false)
, m_miValueList(true)
- , m_constStrArgThread("thread")
- , m_constStrArgFrame("frame")
, m_constStrArgPrintValues("print-values")
{
// Command factory matches this name with that received from the stdin stream
@@ -653,7 +642,7 @@ CMICmdCmdStackListLocals::CMICmdCmdStackListLocals(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals(void)
+CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals()
{
}
@@ -667,14 +656,10 @@ CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListLocals::ParseArgs(void)
+CMICmdCmdStackListLocals::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -687,7 +672,7 @@ CMICmdCmdStackListLocals::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListLocals::Execute(void)
+CMICmdCmdStackListLocals::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
@@ -752,7 +737,7 @@ CMICmdCmdStackListLocals::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListLocals::Acknowledge(void)
+CMICmdCmdStackListLocals::Acknowledge()
{
if (m_bThreadInvalid)
{
@@ -781,7 +766,7 @@ CMICmdCmdStackListLocals::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdStackListLocals::CreateSelf(void)
+CMICmdCmdStackListLocals::CreateSelf()
{
return new CMICmdCmdStackListLocals();
}
@@ -797,11 +782,9 @@ CMICmdCmdStackListLocals::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackListVariables::CMICmdCmdStackListVariables(void)
+CMICmdCmdStackListVariables::CMICmdCmdStackListVariables()
: m_bThreadInvalid(false)
, m_miValueList(true)
- , m_constStrArgThread("thread")
- , m_constStrArgFrame("frame")
, m_constStrArgPrintValues("print-values")
{
// Command factory matches this name with that received from the stdin stream
@@ -818,7 +801,7 @@ CMICmdCmdStackListVariables::CMICmdCmdStackListVariables(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackListVariables::~CMICmdCmdStackListVariables(void)
+CMICmdCmdStackListVariables::~CMICmdCmdStackListVariables()
{
}
@@ -832,14 +815,10 @@ CMICmdCmdStackListVariables::~CMICmdCmdStackListVariables(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListVariables::ParseArgs(void)
+CMICmdCmdStackListVariables::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -852,7 +831,7 @@ CMICmdCmdStackListVariables::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListVariables::Execute(void)
+CMICmdCmdStackListVariables::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
@@ -916,7 +895,7 @@ CMICmdCmdStackListVariables::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdStackListVariables::Acknowledge(void)
+CMICmdCmdStackListVariables::Acknowledge()
{
if (m_bThreadInvalid)
{
@@ -945,7 +924,7 @@ CMICmdCmdStackListVariables::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdStackListVariables::CreateSelf(void)
+CMICmdCmdStackListVariables::CreateSelf()
{
return new CMICmdCmdStackListVariables();
}
@@ -961,9 +940,9 @@ CMICmdCmdStackListVariables::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackSelectFrame::CMICmdCmdStackSelectFrame(void)
+CMICmdCmdStackSelectFrame::CMICmdCmdStackSelectFrame()
: m_bFrameInvalid(false)
- , m_constStrArgFrame("frame")
+ , m_constStrArgFrameId("frame_id")
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "stack-select-frame";
@@ -979,7 +958,7 @@ CMICmdCmdStackSelectFrame::CMICmdCmdStackSelectFrame(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdStackSelectFrame::~CMICmdCmdStackSelectFrame(void)
+CMICmdCmdStackSelectFrame::~CMICmdCmdStackSelectFrame()
{
}
@@ -993,10 +972,10 @@ CMICmdCmdStackSelectFrame::~CMICmdCmdStackSelectFrame(void)
// Throws: None.
//--
bool
-CMICmdCmdStackSelectFrame::ParseArgs(void)
+CMICmdCmdStackSelectFrame::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgFrame, true, false)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameId, true, false));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -1009,9 +988,9 @@ CMICmdCmdStackSelectFrame::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdStackSelectFrame::Execute(void)
+CMICmdCmdStackSelectFrame::Execute()
{
- CMICMDBASE_GETOPTION(pArgFrame, Number, m_constStrArgFrame);
+ CMICMDBASE_GETOPTION(pArgFrame, Number, m_constStrArgFrameId);
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
lldb::SBThread sbThread = rSessionInfo.GetProcess().GetSelectedThread();
@@ -1037,7 +1016,7 @@ CMICmdCmdStackSelectFrame::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdStackSelectFrame::Acknowledge(void)
+CMICmdCmdStackSelectFrame::Acknowledge()
{
if (m_bFrameInvalid)
{
@@ -1066,7 +1045,7 @@ CMICmdCmdStackSelectFrame::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdStackSelectFrame::CreateSelf(void)
+CMICmdCmdStackSelectFrame::CreateSelf()
{
return new CMICmdCmdStackSelectFrame();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdStack.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdStack.h
index 274415a..e22a703 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdStack.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdStack.h
@@ -33,34 +33,30 @@
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "stack-info-depth".
-// Gotchas: None.
-// Authors: Illya Rudkin 21/03/2014.
-// Changes: None.
//--
class CMICmdCmdStackInfoDepth : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdStackInfoDepth(void);
+ /* ctor */ CMICmdCmdStackInfoDepth();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdStackInfoDepth(void) override;
+ /* dtor */ ~CMICmdCmdStackInfoDepth() override;
// Attributes:
private:
MIuint m_nThreadFrames;
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgMaxDepth; // Not handled by *this command
};
@@ -73,20 +69,20 @@ class CMICmdCmdStackInfoFrame : public CMICmdBase
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdStackInfoFrame(void);
+ /* ctor */ CMICmdCmdStackInfoFrame();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdStackInfoFrame(void) override;
+ /* dtor */ ~CMICmdCmdStackInfoFrame() override;
// Attributes:
private:
@@ -96,29 +92,26 @@ class CMICmdCmdStackInfoFrame : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "stack-list-frames".
-// Gotchas: None.
-// Authors: Illya Rudkin 21/03/2014.
-// Changes: None.
//--
class CMICmdCmdStackListFrames : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdStackListFrames(void);
+ /* ctor */ CMICmdCmdStackListFrames();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdStackListFrames(void) override;
+ /* dtor */ ~CMICmdCmdStackListFrames() override;
// Typedefs:
private:
@@ -128,7 +121,6 @@ class CMICmdCmdStackListFrames : public CMICmdBase
private:
MIuint m_nThreadFrames;
VecMIValueResult_t m_vecMIValueResult;
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgFrameLow;
const CMIUtilString m_constStrArgFrameHigh;
};
@@ -136,35 +128,31 @@ class CMICmdCmdStackListFrames : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "stack-list-arguments".
-// Gotchas: None.
-// Authors: Illya Rudkin 24/03/2014.
-// Changes: None.
//--
class CMICmdCmdStackListArguments : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdStackListArguments(void);
+ /* ctor */ CMICmdCmdStackListArguments();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdStackListArguments(void) override;
+ /* dtor */ ~CMICmdCmdStackListArguments() override;
// Attributes:
private:
bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid
CMICmnMIValueList m_miValueList;
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgPrintValues;
const CMIUtilString m_constStrArgFrameLow;
const CMIUtilString m_constStrArgFrameHigh;
@@ -173,36 +161,31 @@ class CMICmdCmdStackListArguments : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "stack-list-locals".
-// Gotchas: None.
-// Authors: Illya Rudkin 24/03/2014.
-// Changes: None.
//--
class CMICmdCmdStackListLocals : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdStackListLocals(void);
+ /* ctor */ CMICmdCmdStackListLocals();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdStackListLocals(void) override;
+ /* dtor */ ~CMICmdCmdStackListLocals() override;
// Attributes:
private:
bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid
CMICmnMIValueList m_miValueList;
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
- const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgPrintValues;
};
@@ -215,27 +198,25 @@ class CMICmdCmdStackListVariables : public CMICmdBase
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdStackListVariables(void);
+ /* ctor */ CMICmdCmdStackListVariables();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdStackListVariables(void) override;
+ /* dtor */ ~CMICmdCmdStackListVariables() override;
// Attributes
private:
bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid
CMICmnMIValueList m_miValueList;
- const CMIUtilString m_constStrArgThread;
- const CMIUtilString m_constStrArgFrame;
const CMIUtilString m_constStrArgPrintValues;
};
@@ -248,23 +229,23 @@ class CMICmdCmdStackSelectFrame : public CMICmdBase
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdStackSelectFrame(void);
+ /* ctor */ CMICmdCmdStackSelectFrame();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdStackSelectFrame(void) override;
+ /* dtor */ ~CMICmdCmdStackSelectFrame() override;
// Attributes:
private:
bool m_bFrameInvalid; // True = yes invalid frame, false = ok
- const CMIUtilString m_constStrArgFrame;
+ const CMIUtilString m_constStrArgFrameId;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportInfo.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportInfo.cpp
index 2d04ef8..9d92644 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportInfo.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportInfo.cpp
@@ -24,7 +24,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdSupportInfoMiCmdQuery::CMICmdCmdSupportInfoMiCmdQuery(void)
+CMICmdCmdSupportInfoMiCmdQuery::CMICmdCmdSupportInfoMiCmdQuery()
: m_bCmdFound(false)
, m_constStrArgCmdName("cmd_name")
{
@@ -42,7 +42,7 @@ CMICmdCmdSupportInfoMiCmdQuery::CMICmdCmdSupportInfoMiCmdQuery(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdSupportInfoMiCmdQuery::~CMICmdCmdSupportInfoMiCmdQuery(void)
+CMICmdCmdSupportInfoMiCmdQuery::~CMICmdCmdSupportInfoMiCmdQuery()
{
}
@@ -56,10 +56,10 @@ CMICmdCmdSupportInfoMiCmdQuery::~CMICmdCmdSupportInfoMiCmdQuery(void)
// Throws: None.
//--
bool
-CMICmdCmdSupportInfoMiCmdQuery::ParseArgs(void)
+CMICmdCmdSupportInfoMiCmdQuery::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgCmdName, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgCmdName, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -72,7 +72,7 @@ CMICmdCmdSupportInfoMiCmdQuery::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdSupportInfoMiCmdQuery::Execute(void)
+CMICmdCmdSupportInfoMiCmdQuery::Execute()
{
CMICMDBASE_GETOPTION(pArgNamedCmdName, String, m_constStrArgCmdName);
const CMIUtilString &rCmdToQuery(pArgNamedCmdName->GetValue());
@@ -96,7 +96,7 @@ CMICmdCmdSupportInfoMiCmdQuery::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdSupportInfoMiCmdQuery::Acknowledge(void)
+CMICmdCmdSupportInfoMiCmdQuery::Acknowledge()
{
const CMICmnMIValueConst miValueConst(m_bCmdFound ? "true" : "false");
const CMICmnMIValueResult miValueResult("exists", miValueConst);
@@ -117,7 +117,7 @@ CMICmdCmdSupportInfoMiCmdQuery::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdSupportInfoMiCmdQuery::CreateSelf(void)
+CMICmdCmdSupportInfoMiCmdQuery::CreateSelf()
{
return new CMICmdCmdSupportInfoMiCmdQuery();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportInfo.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportInfo.h
index 8dfcfba..62b7126 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportInfo.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportInfo.h
@@ -27,29 +27,26 @@
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "info-gdb-mi-command".
// This command does not follow the MI documentation exactly.
-// Gotchas: None.
-// Authors: Illya Rudkin 06/05/2014.
-// Changes: None.
//--
class CMICmdCmdSupportInfoMiCmdQuery : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdSupportInfoMiCmdQuery(void);
+ /* ctor */ CMICmdCmdSupportInfoMiCmdQuery();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdSupportInfoMiCmdQuery(void) override;
+ /* dtor */ ~CMICmdCmdSupportInfoMiCmdQuery() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportList.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportList.cpp
index 6cf4b0b..06d6361 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportList.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportList.cpp
@@ -22,7 +22,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdSupportListFeatures::CMICmdCmdSupportListFeatures(void)
+CMICmdCmdSupportListFeatures::CMICmdCmdSupportListFeatures()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "list-features";
@@ -38,7 +38,7 @@ CMICmdCmdSupportListFeatures::CMICmdCmdSupportListFeatures(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdSupportListFeatures::~CMICmdCmdSupportListFeatures(void)
+CMICmdCmdSupportListFeatures::~CMICmdCmdSupportListFeatures()
{
}
@@ -52,7 +52,7 @@ CMICmdCmdSupportListFeatures::~CMICmdCmdSupportListFeatures(void)
// Throws: None.
//--
bool
-CMICmdCmdSupportListFeatures::Execute(void)
+CMICmdCmdSupportListFeatures::Execute()
{
// Do nothing
@@ -69,10 +69,15 @@ CMICmdCmdSupportListFeatures::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdSupportListFeatures::Acknowledge(void)
+CMICmdCmdSupportListFeatures::Acknowledge()
{
- const CMICmnMIValueConst miValueConst("data-read-memory-bytes");
- const CMICmnMIValueList miValueList(miValueConst);
+ // Declare supported features here
+ const CMICmnMIValueConst miValueConst1("data-read-memory-bytes");
+ const CMICmnMIValueConst miValueConst2("exec-run-start-option");
+ // Some features may depend on host and/or target, decide what to add below
+ CMICmnMIValueList miValueList(true);
+ miValueList.Add(miValueConst1);
+ miValueList.Add(miValueConst2);
const CMICmnMIValueResult miValueResult("features", miValueList);
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
m_miResultRecord = miRecordResult;
@@ -89,7 +94,7 @@ CMICmdCmdSupportListFeatures::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdSupportListFeatures::CreateSelf(void)
+CMICmdCmdSupportListFeatures::CreateSelf()
{
return new CMICmdCmdSupportListFeatures();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportList.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportList.h
index a317b07..5ac95a3 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportList.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSupportList.h
@@ -27,26 +27,23 @@
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "list-features".
// This command does not follow the MI documentation exactly.
-// Gotchas: None.
-// Authors: Illya Rudkin 03/03/2014.
-// Changes: None.
//--
class CMICmdCmdSupportListFeatures : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdSupportListFeatures(void);
+ /* ctor */ CMICmdCmdSupportListFeatures();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdSupportListFeatures(void) override;
+ /* dtor */ ~CMICmdCmdSupportListFeatures() override;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp
index 2649389..abaa392 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp
@@ -19,6 +19,7 @@
#include "MICmnMIResultRecord.h"
#include "MICmnMIValueList.h"
#include "MICmnMIValueTuple.h"
+#include "MIUtilParse.h"
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdSymbolListLines constructor.
@@ -27,7 +28,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdSymbolListLines::CMICmdCmdSymbolListLines(void)
+CMICmdCmdSymbolListLines::CMICmdCmdSymbolListLines()
: m_constStrArgNameFile("file")
{
// Command factory matches this name with that received from the stdin stream
@@ -44,7 +45,7 @@ CMICmdCmdSymbolListLines::CMICmdCmdSymbolListLines(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines(void)
+CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines()
{
}
@@ -58,10 +59,10 @@ CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines(void)
// Throws: None.
//--
bool
-CMICmdCmdSymbolListLines::ParseArgs(void)
+CMICmdCmdSymbolListLines::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValFile(m_constStrArgNameFile, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNameFile, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -76,12 +77,12 @@ CMICmdCmdSymbolListLines::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdSymbolListLines::Execute(void)
+CMICmdCmdSymbolListLines::Execute()
{
CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile);
const CMIUtilString &strFilePath(pArgFile->GetValue());
- const CMIUtilString strCmd(CMIUtilString::Format("target modules dump line-table \"%s\"", strFilePath.AddSlashes().c_str()));
+ const CMIUtilString strCmd(CMIUtilString::Format("source info --file \"%s\"", strFilePath.AddSlashes().c_str()));
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult);
@@ -91,6 +92,77 @@ CMICmdCmdSymbolListLines::Execute(void)
}
//++ ------------------------------------------------------------------------------------
+// Details: Helper function for parsing the header returned from lldb for the command:
+// target modules dump line-table <file>
+// where the header is of the format:
+// Line table for /path/to/file in `/path/to/module
+// Args: input - (R) Input string to parse.
+// file - (W) String representing the file.
+// Return: bool - True = input was parsed successfully, false = input could not be parsed.
+// Throws: None.
+//--
+static bool
+ParseLLDBLineAddressHeader(const char *input, CMIUtilString &file)
+{
+ // Match LineEntry using regex.
+ static MIUtilParse::CRegexParser g_lineentry_header_regex(
+ "^ *Lines found for file (.+) in compilation unit (.+) in `(.+)$");
+ // ^1=file ^2=cu ^3=module
+
+ MIUtilParse::CRegexParser::Match match(4);
+
+ const bool ok = g_lineentry_header_regex.Execute(input, match);
+ if (ok)
+ file = match.GetMatchAtIndex(1);
+ return ok;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Helper function for parsing a line entry returned from lldb for the command:
+// target modules dump line-table <file>
+// where the line entry is of the format:
+// 0x0000000100000e70: /path/to/file:3002[:4]
+// addr file line column(opt)
+// Args: input - (R) Input string to parse.
+// addr - (W) String representing the pc address.
+// file - (W) String representing the file.
+// line - (W) String representing the line.
+// Return: bool - True = input was parsed successfully, false = input could not be parsed.
+// Throws: None.
+//--
+static bool
+ParseLLDBLineAddressEntry(const char *input, CMIUtilString &addr,
+ CMIUtilString &file, CMIUtilString &line)
+{
+ // Note: Ambiguities arise because the column is optional, and
+ // because : can appear in filenames or as a byte in a multibyte
+ // UTF8 character. We keep those cases to a minimum by using regex
+ // to work on the string from both the left and right, so that what
+ // is remains is assumed to be the filename.
+
+ // Match LineEntry using regex.
+ static MIUtilParse::CRegexParser g_lineentry_nocol_regex(
+ "^ *\\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$");
+ static MIUtilParse::CRegexParser g_lineentry_col_regex(
+ "^ *\\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$");
+ // ^1=start ^2=end ^3=f ^4=line ^5=:col(opt)
+
+ MIUtilParse::CRegexParser::Match match(6);
+
+ // First try matching the LineEntry with the column,
+ // then try without the column.
+ const bool ok = g_lineentry_col_regex.Execute(input, match) ||
+ g_lineentry_nocol_regex.Execute(input, match);
+ if (ok)
+ {
+ addr = match.GetMatchAtIndex(1);
+ file = match.GetMatchAtIndex(3);
+ line = match.GetMatchAtIndex(4);
+ }
+ return ok;
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
@@ -100,7 +172,7 @@ CMICmdCmdSymbolListLines::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdSymbolListLines::Acknowledge(void)
+CMICmdCmdSymbolListLines::Acknowledge()
{
if (m_lldbResult.GetErrorSize() > 0)
{
@@ -117,36 +189,44 @@ CMICmdCmdSymbolListLines::Acknowledge(void)
const CMIUtilString strLldbMsg(m_lldbResult.GetOutput());
const MIuint nLines(strLldbMsg.SplitLines(vecLines));
+ // Parse the file from the header.
+ const CMIUtilString &rWantFile(vecLines[0]);
+ CMIUtilString strWantFile;
+ if (!ParseLLDBLineAddressHeader(rWantFile.c_str(), strWantFile))
+ {
+ // Unexpected error - parsing failed.
+ // MI print "%s^error,msg=\"Command '-symbol-list-lines'. Error: Line address header is absent or has an unknown format.\""
+ const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(), "Line address header is absent or has an unknown format."));
+ const CMICmnMIValueResult miValueResult("msg", miValueConst);
+ const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+ }
+
+ // Parse the line address entries.
CMICmnMIValueList miValueList(true);
for (MIuint i = 1; i < nLines; ++i)
{
// String looks like:
// 0x0000000100000e70: /path/to/file:3[:4]
const CMIUtilString &rLine(vecLines[i]);
+ CMIUtilString strAddr;
+ CMIUtilString strFile;
+ CMIUtilString strLine;
+
+ if (!ParseLLDBLineAddressEntry(rLine.c_str(), strAddr, strFile, strLine))
+ continue;
- // 0x0000000100000e70: /path/to/file:3[:4]
- // ^^^^^^^^^^^^^^^^^^ -- pc
- const size_t nAddrEndPos = rLine.find(':');
- const CMIUtilString strAddr(rLine.substr(0, nAddrEndPos).c_str());
const CMICmnMIValueConst miValueConst(strAddr);
const CMICmnMIValueResult miValueResult("pc", miValueConst);
CMICmnMIValueTuple miValueTuple(miValueResult);
- // 0x0000000100000e70: /path/to/file:3[:4]
- // ^ -- line
- const size_t nLineOrColumnStartPos = rLine.rfind(':');
- const CMIUtilString strLineOrColumn(rLine.substr(nLineOrColumnStartPos + 1).c_str());
- const size_t nPathOrLineStartPos = rLine.rfind(':', nLineOrColumnStartPos - 1);
- const size_t nPathOrLineLen = nLineOrColumnStartPos - nPathOrLineStartPos - 1;
- const CMIUtilString strPathOrLine(rLine.substr(nPathOrLineStartPos + 1, nPathOrLineLen).c_str());
- const CMIUtilString strLine(strPathOrLine.IsNumber() ? strPathOrLine : strLineOrColumn);
const CMICmnMIValueConst miValueConst2(strLine);
const CMICmnMIValueResult miValueResult2("line", miValueConst2);
- bool bOk = miValueTuple.Add(miValueResult2);
+ miValueTuple.Add(miValueResult2);
- bOk = bOk && miValueList.Add(miValueTuple);
- if (!bOk)
- return MIstatus::failure;
+ miValueList.Add(miValueTuple);
}
// MI print "%s^done,lines=[{pc=\"%d\",line=\"%d\"}...]"
@@ -167,7 +247,7 @@ CMICmdCmdSymbolListLines::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdSymbolListLines::CreateSelf(void)
+CMICmdCmdSymbolListLines::CreateSelf()
{
return new CMICmdCmdSymbolListLines();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.h
index ef268bb..5bffd4f 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdSymbol.h
@@ -35,20 +35,20 @@ class CMICmdCmdSymbolListLines : public CMICmdBase
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdSymbolListLines(void);
+ /* ctor */ CMICmdCmdSymbolListLines();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdSymbolListLines(void) override;
+ /* dtor */ ~CMICmdCmdSymbolListLines() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.cpp
index 6655682..030024b 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.cpp
@@ -33,7 +33,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdTargetSelect::CMICmdCmdTargetSelect(void)
+CMICmdCmdTargetSelect::CMICmdCmdTargetSelect()
: m_constStrArgNamedType("type")
, m_constStrArgNamedParameters("parameters")
{
@@ -51,7 +51,7 @@ CMICmdCmdTargetSelect::CMICmdCmdTargetSelect(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect(void)
+CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect()
{
}
@@ -65,11 +65,11 @@ CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect(void)
// Throws: None.
//--
bool
-CMICmdCmdTargetSelect::ParseArgs(void)
+CMICmdCmdTargetSelect::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedType, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedParameters, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedType, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedParameters, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -84,7 +84,7 @@ CMICmdCmdTargetSelect::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdTargetSelect::Execute(void)
+CMICmdCmdTargetSelect::Execute()
{
CMICMDBASE_GETOPTION(pArgType, String, m_constStrArgNamedType);
CMICMDBASE_GETOPTION(pArgParameters, String, m_constStrArgNamedParameters);
@@ -172,7 +172,7 @@ CMICmdCmdTargetSelect::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdTargetSelect::Acknowledge(void)
+CMICmdCmdTargetSelect::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Connected);
m_miResultRecord = miRecordResult;
@@ -203,7 +203,7 @@ CMICmdCmdTargetSelect::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdTargetSelect::CreateSelf(void)
+CMICmdCmdTargetSelect::CreateSelf()
{
return new CMICmdCmdTargetSelect();
}
@@ -215,7 +215,7 @@ CMICmdCmdTargetSelect::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdTargetAttach::CMICmdCmdTargetAttach(void)
+CMICmdCmdTargetAttach::CMICmdCmdTargetAttach()
: m_constStrArgPid("pid")
, m_constStrArgNamedFile("n")
, m_constStrArgWaitFor("waitfor")
@@ -234,7 +234,7 @@ CMICmdCmdTargetAttach::CMICmdCmdTargetAttach(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdTargetAttach::~CMICmdCmdTargetAttach(void)
+CMICmdCmdTargetAttach::~CMICmdCmdTargetAttach()
{
}
@@ -248,13 +248,13 @@ CMICmdCmdTargetAttach::~CMICmdCmdTargetAttach(void)
// Throws: None.
//--
bool
-CMICmdCmdTargetAttach::ParseArgs(void)
+CMICmdCmdTargetAttach::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPid, false, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedFile, false, true,
- CMICmdArgValListBase::eArgValType_String, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgWaitFor, false, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgPid, false, true));
+ m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedFile, false, true,
+ CMICmdArgValListBase::eArgValType_String, 1));
+ m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgWaitFor, false, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -269,7 +269,7 @@ CMICmdCmdTargetAttach::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdTargetAttach::Execute(void)
+CMICmdCmdTargetAttach::Execute()
{
CMICMDBASE_GETOPTION(pArgPid, Number, m_constStrArgPid);
CMICMDBASE_GETOPTION(pArgFile, OptionShort, m_constStrArgNamedFile);
@@ -330,7 +330,7 @@ CMICmdCmdTargetAttach::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdTargetAttach::Acknowledge(void)
+CMICmdCmdTargetAttach::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -361,7 +361,7 @@ CMICmdCmdTargetAttach::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdTargetAttach::CreateSelf(void)
+CMICmdCmdTargetAttach::CreateSelf()
{
return new CMICmdCmdTargetAttach();
}
@@ -389,7 +389,7 @@ CMICmdCmdTargetDetach::CMICmdCmdTargetDetach()
// Return: None.
// Throws: None.
//--
-CMICmdCmdTargetDetach::~CMICmdCmdTargetDetach(void)
+CMICmdCmdTargetDetach::~CMICmdCmdTargetDetach()
{
}
@@ -403,7 +403,7 @@ CMICmdCmdTargetDetach::~CMICmdCmdTargetDetach(void)
// Throws: None.
//--
bool
-CMICmdCmdTargetDetach::ParseArgs(void)
+CMICmdCmdTargetDetach::ParseArgs()
{
return MIstatus::success;
}
@@ -420,7 +420,7 @@ CMICmdCmdTargetDetach::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdTargetDetach::Execute(void)
+CMICmdCmdTargetDetach::Execute()
{
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
@@ -447,7 +447,7 @@ CMICmdCmdTargetDetach::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdTargetDetach::Acknowledge(void)
+CMICmdCmdTargetDetach::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -463,7 +463,7 @@ CMICmdCmdTargetDetach::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdTargetDetach::CreateSelf(void)
+CMICmdCmdTargetDetach::CreateSelf()
{
return new CMICmdCmdTargetDetach();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.h
index 62f77ee..e4c04b1 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTarget.h
@@ -29,29 +29,26 @@
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "target-select".
// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation
-// Gotchas: None.
-// Authors: Illya Rudkin 05/03/2014.
-// Changes: None.
//--
class CMICmdCmdTargetSelect : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdTargetSelect(void);
+ /* ctor */ CMICmdCmdTargetSelect();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdTargetSelect(void) override;
+ /* dtor */ ~CMICmdCmdTargetSelect() override;
// Attributes:
private:
@@ -69,20 +66,20 @@ class CMICmdCmdTargetAttach : public CMICmdBase
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdTargetAttach(void);
+ /* ctor */ CMICmdCmdTargetAttach();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdTargetAttach(void) override;
+ /* dtor */ ~CMICmdCmdTargetAttach() override;
// Attributes:
private:
@@ -101,19 +98,19 @@ class CMICmdCmdTargetDetach : public CMICmdBase
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdTargetDetach(void);
+ /* ctor */ CMICmdCmdTargetDetach();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdTargetDetach(void) override;
+ /* dtor */ ~CMICmdCmdTargetDetach() override;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdThread.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdThread.cpp
index df6de26..823a374 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdThread.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdThread.cpp
@@ -28,7 +28,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdThreadInfo::CMICmdCmdThreadInfo(void)
+CMICmdCmdThreadInfo::CMICmdCmdThreadInfo()
: m_bSingleThread(false)
, m_bThreadInvalid(true)
, m_constStrArgNamedThreadId("thread-id")
@@ -47,7 +47,7 @@ CMICmdCmdThreadInfo::CMICmdCmdThreadInfo(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo(void)
+CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo()
{
m_vecMIValueTuple.clear();
}
@@ -62,10 +62,10 @@ CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo(void)
// Throws: None.
//--
bool
-CMICmdCmdThreadInfo::ParseArgs(void)
+CMICmdCmdThreadInfo::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNamedThreadId, false, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedThreadId, false, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -78,7 +78,7 @@ CMICmdCmdThreadInfo::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdThreadInfo::Execute(void)
+CMICmdCmdThreadInfo::Execute()
{
CMICMDBASE_GETOPTION(pArgThreadId, Number, m_constStrArgNamedThreadId);
MIuint nThreadId = 0;
@@ -137,7 +137,7 @@ CMICmdCmdThreadInfo::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdThreadInfo::Acknowledge(void)
+CMICmdCmdThreadInfo::Acknowledge()
{
if (m_bSingleThread)
{
@@ -195,7 +195,7 @@ CMICmdCmdThreadInfo::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdThreadInfo::CreateSelf(void)
+CMICmdCmdThreadInfo::CreateSelf()
{
return new CMICmdCmdThreadInfo();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdThread.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdThread.h
index 7bce823..7031eab 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdThread.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdThread.h
@@ -28,29 +28,26 @@
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "thread-info".
-// Gotchas: None.
-// Authors: Illya Rudkin 07/03/2014.
-// Changes: None.
//--
class CMICmdCmdThreadInfo : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdThreadInfo(void);
+ /* ctor */ CMICmdCmdThreadInfo();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdThreadInfo(void) override;
+ /* dtor */ ~CMICmdCmdThreadInfo() override;
// Typedefs:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTrace.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTrace.cpp
index c0d5fc9..4eab75b 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTrace.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTrace.cpp
@@ -21,7 +21,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdTraceStatus::CMICmdCmdTraceStatus(void)
+CMICmdCmdTraceStatus::CMICmdCmdTraceStatus()
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "trace-status";
@@ -37,7 +37,7 @@ CMICmdCmdTraceStatus::CMICmdCmdTraceStatus(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdTraceStatus::~CMICmdCmdTraceStatus(void)
+CMICmdCmdTraceStatus::~CMICmdCmdTraceStatus()
{
}
@@ -51,7 +51,7 @@ CMICmdCmdTraceStatus::~CMICmdCmdTraceStatus(void)
// Throws: None.
//--
bool
-CMICmdCmdTraceStatus::Execute(void)
+CMICmdCmdTraceStatus::Execute()
{
// Do nothing
return MIstatus::success;
@@ -67,7 +67,7 @@ CMICmdCmdTraceStatus::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdTraceStatus::Acknowledge(void)
+CMICmdCmdTraceStatus::Acknowledge()
{
const CMICmnMIValueConst miValueConst(MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED));
const CMICmnMIValueResult miValueResult("msg", miValueConst);
@@ -86,7 +86,7 @@ CMICmdCmdTraceStatus::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdTraceStatus::CreateSelf(void)
+CMICmdCmdTraceStatus::CreateSelf()
{
return new CMICmdCmdTraceStatus();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTrace.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTrace.h
index cafe2d8..d375160 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTrace.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdTrace.h
@@ -26,26 +26,23 @@
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "trace-status".
-// Gotchas: None.
-// Authors: Illya Rudkin 07/03/2014.
-// Changes: None.
//--
class CMICmdCmdTraceStatus : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdTraceStatus(void);
+ /* ctor */ CMICmdCmdTraceStatus();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdTraceStatus(void) override;
+ /* dtor */ ~CMICmdCmdTraceStatus() override;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdVar.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdVar.cpp
index 8c4abbd..8e30a2a 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdVar.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdVar.cpp
@@ -45,15 +45,12 @@
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarCreate::CMICmdCmdVarCreate(void)
+CMICmdCmdVarCreate::CMICmdCmdVarCreate()
: m_nChildren(0)
, m_nThreadId(0)
, m_strType("??")
, m_bValid(false)
, m_strValue("??")
- , m_constStrArgThread("thread")
- , m_constStrArgThreadGroup("thread-group")
- , m_constStrArgFrame("frame")
, m_constStrArgName("name")
, m_constStrArgFrameAddr("frame-addr")
, m_constStrArgExpression("expression")
@@ -72,7 +69,7 @@ CMICmdCmdVarCreate::CMICmdCmdVarCreate(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarCreate::~CMICmdCmdVarCreate(void)
+CMICmdCmdVarCreate::~CMICmdCmdVarCreate()
{
}
@@ -86,19 +83,12 @@ CMICmdCmdVarCreate::~CMICmdCmdVarCreate(void)
// Throws: None.
//--
bool
-CMICmdCmdVarCreate::ParseArgs(void)
+CMICmdCmdVarCreate::ParseArgs()
{
- bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(
- *(new CMICmdArgValOptionLong(m_constStrArgThreadGroup, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)));
- bOk = bOk &&
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, false, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgFrameAddr, false, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgExpression, true, true, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, false, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFrameAddr, false, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpression, true, true, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -111,7 +101,7 @@ CMICmdCmdVarCreate::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdVarCreate::Execute(void)
+CMICmdCmdVarCreate::Execute()
{
CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
@@ -182,7 +172,7 @@ CMICmdCmdVarCreate::Execute(void)
if (rStrExpression[0] == '$')
{
- const CMIUtilString rStrRegister(rStrExpression.substr(1).c_str());
+ const CMIUtilString rStrRegister(rStrExpression.substr(1));
value = frame.FindRegister(rStrRegister.c_str());
}
else
@@ -229,7 +219,7 @@ CMICmdCmdVarCreate::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdVarCreate::Acknowledge(void)
+CMICmdCmdVarCreate::Acknowledge()
{
if (m_bValid)
{
@@ -258,7 +248,7 @@ CMICmdCmdVarCreate::Acknowledge(void)
CMIUtilString strErrMsg(m_strValue);
if (m_strValue.empty())
strErrMsg = CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_CREATION_FAILED), m_strExpression.c_str());
- const CMICmnMIValueConst miValueConst(strErrMsg);
+ const CMICmnMIValueConst miValueConst(strErrMsg.Escape(true /* vbEscapeQuotes */));
CMICmnMIValueResult miValueResult("msg", miValueConst);
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
m_miResultRecord = miRecordResult;
@@ -275,7 +265,7 @@ CMICmdCmdVarCreate::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdVarCreate::CreateSelf(void)
+CMICmdCmdVarCreate::CreateSelf()
{
return new CMICmdCmdVarCreate();
}
@@ -320,7 +310,7 @@ CMICmdCmdVarCreate::CompleteSBValue(lldb::SBValue &vrwValue)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarUpdate::CMICmdCmdVarUpdate(void)
+CMICmdCmdVarUpdate::CMICmdCmdVarUpdate()
: m_constStrArgPrintValues("print-values")
, m_constStrArgName("name")
, m_bValueChanged(false)
@@ -340,7 +330,7 @@ CMICmdCmdVarUpdate::CMICmdCmdVarUpdate(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarUpdate::~CMICmdCmdVarUpdate(void)
+CMICmdCmdVarUpdate::~CMICmdCmdVarUpdate()
{
}
@@ -354,11 +344,11 @@ CMICmdCmdVarUpdate::~CMICmdCmdVarUpdate(void)
// Throws: None.
//--
bool
-CMICmdCmdVarUpdate::ParseArgs(void)
+CMICmdCmdVarUpdate::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValPrintValues(m_constStrArgPrintValues, false, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, false, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -371,7 +361,7 @@ CMICmdCmdVarUpdate::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdVarUpdate::Execute(void)
+CMICmdCmdVarUpdate::Execute()
{
CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues);
CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName);
@@ -399,7 +389,7 @@ CMICmdCmdVarUpdate::Execute(void)
(eVarInfoFormat == CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_SimpleValues && rValue.GetNumChildren() == 0));
const CMIUtilString strValue(bPrintValue ? varObj.GetValueFormatted() : "");
const CMIUtilString strInScope(rValue.IsInScope() ? "true" : "false");
- return MIFormResponse(rVarObjName, bPrintValue ? strValue.c_str() : nullptr, strInScope);
+ MIFormResponse(rVarObjName, bPrintValue ? strValue.c_str() : nullptr, strInScope);
}
return MIstatus::success;
@@ -415,7 +405,7 @@ CMICmdCmdVarUpdate::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdVarUpdate::Acknowledge(void)
+CMICmdCmdVarUpdate::Acknowledge()
{
if (m_bValueChanged)
{
@@ -445,7 +435,7 @@ CMICmdCmdVarUpdate::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdVarUpdate::CreateSelf(void)
+CMICmdCmdVarUpdate::CreateSelf()
{
return new CMICmdCmdVarUpdate();
}
@@ -456,36 +446,32 @@ CMICmdCmdVarUpdate::CreateSelf(void)
// Args: vrStrVarName - (R) Session var object's name.
// vpValue - (R) Text version of the value held in the variable.
// vrStrScope - (R) In scope "yes" or "no".
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmdCmdVarUpdate::MIFormResponse(const CMIUtilString &vrStrVarName, const char *const vpValue, const CMIUtilString &vrStrScope)
{
// MI print "[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
const CMICmnMIValueConst miValueConst(vrStrVarName);
const CMICmnMIValueResult miValueResult("name", miValueConst);
CMICmnMIValueTuple miValueTuple(miValueResult);
- bool bOk = true;
if (vpValue != nullptr)
{
const CMICmnMIValueConst miValueConst2(vpValue);
const CMICmnMIValueResult miValueResult2("value", miValueConst2);
- bOk = bOk && miValueTuple.Add(miValueResult2);
+ miValueTuple.Add(miValueResult2);
}
const CMICmnMIValueConst miValueConst3(vrStrScope);
const CMICmnMIValueResult miValueResult3("in_scope", miValueConst3);
- bOk = bOk && miValueTuple.Add(miValueResult3);
+ miValueTuple.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4("false");
const CMICmnMIValueResult miValueResult4("type_changed", miValueConst4);
- bOk = bOk && miValueTuple.Add(miValueResult4);
+ miValueTuple.Add(miValueResult4);
const CMICmnMIValueConst miValueConst5("0");
const CMICmnMIValueResult miValueResult5("has_more", miValueConst5);
- bOk = bOk && miValueTuple.Add(miValueResult5);
- bOk = bOk && m_miValueList.Add(miValueTuple);
-
- return bOk;
+ miValueTuple.Add(miValueResult5);
+ m_miValueList.Add(miValueTuple);
}
//++ ------------------------------------------------------------------------------------
@@ -543,7 +529,7 @@ CMICmdCmdVarUpdate::ExamineSBValueForChange(lldb::SBValue &vrwValue, bool &vrwbC
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarDelete::CMICmdCmdVarDelete(void)
+CMICmdCmdVarDelete::CMICmdCmdVarDelete()
: m_constStrArgName("name")
{
// Command factory matches this name with that received from the stdin stream
@@ -563,10 +549,10 @@ CMICmdCmdVarDelete::CMICmdCmdVarDelete(void)
// Throws: None.
//--
bool
-CMICmdCmdVarDelete::ParseArgs(void)
+CMICmdCmdVarDelete::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -576,7 +562,7 @@ CMICmdCmdVarDelete::ParseArgs(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarDelete::~CMICmdCmdVarDelete(void)
+CMICmdCmdVarDelete::~CMICmdCmdVarDelete()
{
}
@@ -590,7 +576,7 @@ CMICmdCmdVarDelete::~CMICmdCmdVarDelete(void)
// Throws: None.
//--
bool
-CMICmdCmdVarDelete::Execute(void)
+CMICmdCmdVarDelete::Execute()
{
CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName);
@@ -610,7 +596,7 @@ CMICmdCmdVarDelete::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdVarDelete::Acknowledge(void)
+CMICmdCmdVarDelete::Acknowledge()
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
@@ -627,7 +613,7 @@ CMICmdCmdVarDelete::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdVarDelete::CreateSelf(void)
+CMICmdCmdVarDelete::CreateSelf()
{
return new CMICmdCmdVarDelete();
}
@@ -643,7 +629,7 @@ CMICmdCmdVarDelete::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarAssign::CMICmdCmdVarAssign(void)
+CMICmdCmdVarAssign::CMICmdCmdVarAssign()
: m_bOk(true)
, m_constStrArgName("name")
, m_constStrArgExpression("expression")
@@ -662,7 +648,7 @@ CMICmdCmdVarAssign::CMICmdCmdVarAssign(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarAssign::~CMICmdCmdVarAssign(void)
+CMICmdCmdVarAssign::~CMICmdCmdVarAssign()
{
}
@@ -676,11 +662,11 @@ CMICmdCmdVarAssign::~CMICmdCmdVarAssign(void)
// Throws: None.
//--
bool
-CMICmdCmdVarAssign::ParseArgs(void)
+CMICmdCmdVarAssign::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgExpression, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpression, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -693,7 +679,7 @@ CMICmdCmdVarAssign::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdVarAssign::Execute(void)
+CMICmdCmdVarAssign::Execute()
{
CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName);
CMICMDBASE_GETOPTION(pArgExpression, String, m_constStrArgExpression);
@@ -729,7 +715,7 @@ CMICmdCmdVarAssign::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdVarAssign::Acknowledge(void)
+CMICmdCmdVarAssign::Acknowledge()
{
if (m_bOk)
{
@@ -761,7 +747,7 @@ CMICmdCmdVarAssign::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdVarAssign::CreateSelf(void)
+CMICmdCmdVarAssign::CreateSelf()
{
return new CMICmdCmdVarAssign();
}
@@ -777,7 +763,7 @@ CMICmdCmdVarAssign::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarSetFormat::CMICmdCmdVarSetFormat(void)
+CMICmdCmdVarSetFormat::CMICmdCmdVarSetFormat()
: m_constStrArgName("name")
, m_constStrArgFormatSpec("format-spec")
{
@@ -795,7 +781,7 @@ CMICmdCmdVarSetFormat::CMICmdCmdVarSetFormat(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarSetFormat::~CMICmdCmdVarSetFormat(void)
+CMICmdCmdVarSetFormat::~CMICmdCmdVarSetFormat()
{
}
@@ -809,11 +795,11 @@ CMICmdCmdVarSetFormat::~CMICmdCmdVarSetFormat(void)
// Throws: None.
//--
bool
-CMICmdCmdVarSetFormat::ParseArgs(void)
+CMICmdCmdVarSetFormat::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgFormatSpec, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormatSpec, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -826,7 +812,7 @@ CMICmdCmdVarSetFormat::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdVarSetFormat::Execute(void)
+CMICmdCmdVarSetFormat::Execute()
{
CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName);
CMICMDBASE_GETOPTION(pArgFormatSpec, String, m_constStrArgFormatSpec);
@@ -863,7 +849,7 @@ CMICmdCmdVarSetFormat::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdVarSetFormat::Acknowledge(void)
+CMICmdCmdVarSetFormat::Acknowledge()
{
// MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]"
CMICmnLLDBDebugSessionInfoVarObj varObj;
@@ -902,7 +888,7 @@ CMICmdCmdVarSetFormat::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdVarSetFormat::CreateSelf(void)
+CMICmdCmdVarSetFormat::CreateSelf()
{
return new CMICmdCmdVarSetFormat();
}
@@ -918,7 +904,7 @@ CMICmdCmdVarSetFormat::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarListChildren::CMICmdCmdVarListChildren(void)
+CMICmdCmdVarListChildren::CMICmdCmdVarListChildren()
: m_constStrArgPrintValues("print-values")
, m_constStrArgName("name")
, m_constStrArgFrom("from")
@@ -942,7 +928,7 @@ CMICmdCmdVarListChildren::CMICmdCmdVarListChildren(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarListChildren::~CMICmdCmdVarListChildren(void)
+CMICmdCmdVarListChildren::~CMICmdCmdVarListChildren()
{
}
@@ -956,13 +942,13 @@ CMICmdCmdVarListChildren::~CMICmdCmdVarListChildren(void)
// Throws: None.
//--
bool
-CMICmdCmdVarListChildren::ParseArgs(void)
+CMICmdCmdVarListChildren::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValPrintValues(m_constStrArgPrintValues, false, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgFrom, false, true)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgTo, false, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, false, true));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true, true));
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrom, false, true));
+ m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgTo, false, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -975,7 +961,7 @@ CMICmdCmdVarListChildren::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdVarListChildren::Execute(void)
+CMICmdCmdVarListChildren::Execute()
{
CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues);
CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName);
@@ -1022,46 +1008,47 @@ CMICmdCmdVarListChildren::Execute(void)
lldb::SBValue member = rValue.GetChildAtIndex(i);
const CMICmnLLDBUtilSBValue utilValue(member);
const CMIUtilString strExp = utilValue.GetName();
- const CMIUtilString name(CMIUtilString::Format("%s.%s", rVarObjName.c_str(), strExp.c_str()));
+ const CMIUtilString name(strExp.empty() ?
+ CMIUtilString::Format("%s.$%u", rVarObjName.c_str(), i) :
+ CMIUtilString::Format("%s.%s", rVarObjName.c_str(), strExp.c_str()));
const MIuint nChildren = member.GetNumChildren();
const CMIUtilString strThreadId(CMIUtilString::Format("%u", member.GetThread().GetIndexID()));
+ // Varobj gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs
+ CMICmnLLDBDebugSessionInfoVarObj var(strExp, name, member, rVarObjName);
+
// MI print "child={name=\"%s\",exp=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%u\",has_more=\"%u\"}"
const CMICmnMIValueConst miValueConst(name);
const CMICmnMIValueResult miValueResult("name", miValueConst);
CMICmnMIValueTuple miValueTuple(miValueResult);
const CMICmnMIValueConst miValueConst2(strExp);
const CMICmnMIValueResult miValueResult2("exp", miValueConst2);
- bool bOk = miValueTuple.Add(miValueResult2);
+ miValueTuple.Add(miValueResult2);
const CMIUtilString strNumChild(CMIUtilString::Format("%u", nChildren));
const CMICmnMIValueConst miValueConst3(strNumChild);
const CMICmnMIValueResult miValueResult3("numchild", miValueConst3);
- bOk = bOk && miValueTuple.Add(miValueResult3);
+ miValueTuple.Add(miValueResult3);
const CMICmnMIValueConst miValueConst5(utilValue.GetTypeNameDisplay());
const CMICmnMIValueResult miValueResult5("type", miValueConst5);
- bOk = bOk && miValueTuple.Add(miValueResult5);
+ miValueTuple.Add(miValueResult5);
const CMICmnMIValueConst miValueConst6(strThreadId);
const CMICmnMIValueResult miValueResult6("thread-id", miValueConst6);
- bOk = bOk && miValueTuple.Add(miValueResult6);
+ miValueTuple.Add(miValueResult6);
// nChildren == 0 is used to check for simple values
if (eVarInfoFormat == CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues ||
(eVarInfoFormat == CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_SimpleValues && nChildren == 0))
{
- // Varobj gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs
- CMICmnLLDBDebugSessionInfoVarObj var(strExp, name, member, rVarObjName);
const CMIUtilString strValue(
CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural));
const CMICmnMIValueConst miValueConst7(strValue);
const CMICmnMIValueResult miValueResult7("value", miValueConst7);
- bOk = bOk && miValueTuple.Add(miValueResult7);
+ miValueTuple.Add(miValueResult7);
}
const CMICmnMIValueConst miValueConst8("0");
const CMICmnMIValueResult miValueResult8("has_more", miValueConst8);
- bOk = bOk && miValueTuple.Add(miValueResult8);
+ miValueTuple.Add(miValueResult8);
const CMICmnMIValueResult miValueResult9("child", miValueTuple);
- bOk = bOk && m_miValueList.Add(miValueResult9);
- if (!bOk)
- return MIstatus::failure;
+ m_miValueList.Add(miValueResult9);
}
return MIstatus::success;
@@ -1077,7 +1064,7 @@ CMICmdCmdVarListChildren::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdVarListChildren::Acknowledge(void)
+CMICmdCmdVarListChildren::Acknowledge()
{
if (m_bValueValid)
{
@@ -1085,14 +1072,11 @@ CMICmdCmdVarListChildren::Acknowledge(void)
const CMIUtilString strNumChild(CMIUtilString::Format("%u", m_nChildren));
const CMICmnMIValueConst miValueConst(strNumChild);
CMICmnMIValueResult miValueResult("numchild", miValueConst);
- bool bOk = MIstatus::success;
if (m_nChildren != 0)
- bOk = bOk && miValueResult.Add("children", m_miValueList);
+ miValueResult.Add("children", m_miValueList);
const CMIUtilString strHasMore(m_bHasMore ? "1" : "0");
const CMICmnMIValueConst miValueConst2(strHasMore);
- bOk = bOk && miValueResult.Add("has_more", miValueConst2);
- if (!bOk)
- return MIstatus::failure;
+ miValueResult.Add("has_more", miValueConst2);
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
m_miResultRecord = miRecordResult;
@@ -1118,7 +1102,7 @@ CMICmdCmdVarListChildren::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdVarListChildren::CreateSelf(void)
+CMICmdCmdVarListChildren::CreateSelf()
{
return new CMICmdCmdVarListChildren();
}
@@ -1134,7 +1118,7 @@ CMICmdCmdVarListChildren::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarEvaluateExpression::CMICmdCmdVarEvaluateExpression(void)
+CMICmdCmdVarEvaluateExpression::CMICmdCmdVarEvaluateExpression()
: m_bValueValid(true)
, m_constStrArgFormatSpec("-f")
, m_constStrArgName("name")
@@ -1153,7 +1137,7 @@ CMICmdCmdVarEvaluateExpression::CMICmdCmdVarEvaluateExpression(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarEvaluateExpression::~CMICmdCmdVarEvaluateExpression(void)
+CMICmdCmdVarEvaluateExpression::~CMICmdCmdVarEvaluateExpression()
{
}
@@ -1167,12 +1151,12 @@ CMICmdCmdVarEvaluateExpression::~CMICmdCmdVarEvaluateExpression(void)
// Throws: None.
//--
bool
-CMICmdCmdVarEvaluateExpression::ParseArgs(void)
+CMICmdCmdVarEvaluateExpression::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(
- *(new CMICmdArgValOptionShort(m_constStrArgFormatSpec, false, false, CMICmdArgValListBase::eArgValType_String, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(
+ new CMICmdArgValOptionShort(m_constStrArgFormatSpec, false, false, CMICmdArgValListBase::eArgValType_String, 1));
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -1185,7 +1169,7 @@ CMICmdCmdVarEvaluateExpression::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdVarEvaluateExpression::Execute(void)
+CMICmdCmdVarEvaluateExpression::Execute()
{
CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName);
@@ -1218,7 +1202,7 @@ CMICmdCmdVarEvaluateExpression::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdVarEvaluateExpression::Acknowledge(void)
+CMICmdCmdVarEvaluateExpression::Acknowledge()
{
if (m_bValueValid)
{
@@ -1247,7 +1231,7 @@ CMICmdCmdVarEvaluateExpression::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdVarEvaluateExpression::CreateSelf(void)
+CMICmdCmdVarEvaluateExpression::CreateSelf()
{
return new CMICmdCmdVarEvaluateExpression();
}
@@ -1263,7 +1247,7 @@ CMICmdCmdVarEvaluateExpression::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarInfoPathExpression::CMICmdCmdVarInfoPathExpression(void)
+CMICmdCmdVarInfoPathExpression::CMICmdCmdVarInfoPathExpression()
: m_bValueValid(true)
, m_constStrArgName("name")
{
@@ -1281,7 +1265,7 @@ CMICmdCmdVarInfoPathExpression::CMICmdCmdVarInfoPathExpression(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarInfoPathExpression::~CMICmdCmdVarInfoPathExpression(void)
+CMICmdCmdVarInfoPathExpression::~CMICmdCmdVarInfoPathExpression()
{
}
@@ -1295,10 +1279,10 @@ CMICmdCmdVarInfoPathExpression::~CMICmdCmdVarInfoPathExpression(void)
// Throws: None.
//--
bool
-CMICmdCmdVarInfoPathExpression::ParseArgs(void)
+CMICmdCmdVarInfoPathExpression::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -1311,7 +1295,7 @@ CMICmdCmdVarInfoPathExpression::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdVarInfoPathExpression::Execute(void)
+CMICmdCmdVarInfoPathExpression::Execute()
{
CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName);
@@ -1380,7 +1364,7 @@ CMICmdCmdVarInfoPathExpression::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdVarInfoPathExpression::Acknowledge(void)
+CMICmdCmdVarInfoPathExpression::Acknowledge()
{
if (m_bValueValid)
{
@@ -1408,7 +1392,7 @@ CMICmdCmdVarInfoPathExpression::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdVarInfoPathExpression::CreateSelf(void)
+CMICmdCmdVarInfoPathExpression::CreateSelf()
{
return new CMICmdCmdVarInfoPathExpression();
}
@@ -1424,7 +1408,7 @@ CMICmdCmdVarInfoPathExpression::CreateSelf(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarShowAttributes::CMICmdCmdVarShowAttributes(void)
+CMICmdCmdVarShowAttributes::CMICmdCmdVarShowAttributes()
: m_constStrArgName("name")
{
// Command factory matches this name with that received from the stdin stream
@@ -1441,7 +1425,7 @@ CMICmdCmdVarShowAttributes::CMICmdCmdVarShowAttributes(void)
// Return: None.
// Throws: None.
//--
-CMICmdCmdVarShowAttributes::~CMICmdCmdVarShowAttributes(void)
+CMICmdCmdVarShowAttributes::~CMICmdCmdVarShowAttributes()
{
}
@@ -1455,10 +1439,10 @@ CMICmdCmdVarShowAttributes::~CMICmdCmdVarShowAttributes(void)
// Throws: None.
//--
bool
-CMICmdCmdVarShowAttributes::ParseArgs(void)
+CMICmdCmdVarShowAttributes::ParseArgs()
{
- bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true)));
- return (bOk && ParseValidateCmdOptions());
+ m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true));
+ return ParseValidateCmdOptions();
}
//++ ------------------------------------------------------------------------------------
@@ -1471,7 +1455,7 @@ CMICmdCmdVarShowAttributes::ParseArgs(void)
// Throws: None.
//--
bool
-CMICmdCmdVarShowAttributes::Execute(void)
+CMICmdCmdVarShowAttributes::Execute()
{
CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName);
@@ -1496,7 +1480,7 @@ CMICmdCmdVarShowAttributes::Execute(void)
// Throws: None.
//--
bool
-CMICmdCmdVarShowAttributes::Acknowledge(void)
+CMICmdCmdVarShowAttributes::Acknowledge()
{
// MI output: "%s^done,status=\"editable\"]"
const CMICmnMIValueConst miValueConst("editable");
@@ -1516,7 +1500,7 @@ CMICmdCmdVarShowAttributes::Acknowledge(void)
// Throws: None.
//--
CMICmdBase *
-CMICmdCmdVarShowAttributes::CreateSelf(void)
+CMICmdCmdVarShowAttributes::CreateSelf()
{
return new CMICmdCmdVarShowAttributes();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdVar.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdVar.h
index 9f5ad1c..a679087 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdVar.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdVar.h
@@ -41,32 +41,29 @@ class CMICmnLLDBDebugSessionInfoVarObj;
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "var-create".
-// Gotchas: None.
-// Authors: Illya Rudkin 24/03/2014.
-// Changes: None.
//--
class CMICmdCmdVarCreate : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdVarCreate(void);
+ /* ctor */ CMICmdCmdVarCreate();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMICmdCmdVarCreate(void) override;
+ /* dtor */ ~CMICmdCmdVarCreate() override;
// Methods:
private:
@@ -81,9 +78,6 @@ class CMICmdCmdVarCreate : public CMICmdBase
bool m_bValid; // True = Variable is valid, false = not valid
CMIUtilString m_strExpression;
CMIUtilString m_strValue;
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option
- const CMIUtilString m_constStrArgThreadGroup; // Not specified in MI spec but Eclipse gives this option
- const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option
const CMIUtilString m_constStrArgName;
const CMIUtilString m_constStrArgFrameAddr;
const CMIUtilString m_constStrArgExpression;
@@ -92,37 +86,34 @@ class CMICmdCmdVarCreate : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "var-update".
-// Gotchas: None.
-// Authors: Illya Rudkin 25/03/2014.
-// Changes: None.
//--
class CMICmdCmdVarUpdate : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdVarUpdate(void);
+ /* ctor */ CMICmdCmdVarUpdate();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMICmdCmdVarUpdate(void) override;
+ /* dtor */ ~CMICmdCmdVarUpdate() override;
// Methods:
private:
bool ExamineSBValueForChange(lldb::SBValue &vrwValue, bool &vrwbChanged);
- bool MIFormResponse(const CMIUtilString &vrStrVarName, const char *const vpValue, const CMIUtilString &vrStrScope);
+ void MIFormResponse(const CMIUtilString &vrStrVarName, const char *const vpValue, const CMIUtilString &vrStrScope);
// Attribute:
private:
@@ -135,29 +126,26 @@ class CMICmdCmdVarUpdate : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "var-delete".
-// Gotchas: None.
-// Authors: Illya Rudkin 25/03/2014.
-// Changes: None.
//--
class CMICmdCmdVarDelete : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdVarDelete(void);
+ /* ctor */ CMICmdCmdVarDelete();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdVarDelete(void) override;
+ /* dtor */ ~CMICmdCmdVarDelete() override;
// Attribute:
private:
@@ -167,29 +155,26 @@ class CMICmdCmdVarDelete : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "var-assign".
-// Gotchas: None.
-// Authors: Illya Rudkin 25/03/2014.
-// Changes: None.
//--
class CMICmdCmdVarAssign : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdVarAssign(void);
+ /* ctor */ CMICmdCmdVarAssign();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdVarAssign(void) override;
+ /* dtor */ ~CMICmdCmdVarAssign() override;
// Attributes:
private:
@@ -202,29 +187,26 @@ class CMICmdCmdVarAssign : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "var-set-format".
-// Gotchas: None.
-// Authors: Illya Rudkin 26/03/2014.
-// Changes: None.
//--
class CMICmdCmdVarSetFormat : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdVarSetFormat(void);
+ /* ctor */ CMICmdCmdVarSetFormat();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdVarSetFormat(void) override;
+ /* dtor */ ~CMICmdCmdVarSetFormat() override;
// Attributes:
private:
@@ -236,29 +218,26 @@ class CMICmdCmdVarSetFormat : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "var-list-children".
-// Gotchas: None.
-// Authors: Illya Rudkin 26/03/2014.
-// Changes: None.
//--
class CMICmdCmdVarListChildren : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdVarListChildren(void);
+ /* ctor */ CMICmdCmdVarListChildren();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdVarListChildren(void) override;
+ /* dtor */ ~CMICmdCmdVarListChildren() override;
// Attributes:
private:
@@ -275,29 +254,26 @@ class CMICmdCmdVarListChildren : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "var-evaluate-expression".
-// Gotchas: None.
-// Authors: Illya Rudkin 26/03/2014.
-// Changes: None.
//--
class CMICmdCmdVarEvaluateExpression : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdVarEvaluateExpression(void);
+ /* ctor */ CMICmdCmdVarEvaluateExpression();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdVarEvaluateExpression(void) override;
+ /* dtor */ ~CMICmdCmdVarEvaluateExpression() override;
// Attributes:
private:
@@ -310,29 +286,26 @@ class CMICmdCmdVarEvaluateExpression : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "var-info-path-expression".
-// Gotchas: None.
-// Authors: Illya Rudkin 26/03/2014.
-// Changes: None.
//--
class CMICmdCmdVarInfoPathExpression : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdVarInfoPathExpression(void);
+ /* ctor */ CMICmdCmdVarInfoPathExpression();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdVarInfoPathExpression(void) override;
+ /* dtor */ ~CMICmdCmdVarInfoPathExpression() override;
// Attributes:
private:
@@ -344,29 +317,26 @@ class CMICmdCmdVarInfoPathExpression : public CMICmdBase
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "var-show-attributes".
-// Gotchas: None.
-// Authors: Illya Rudkin 19/05/2014.
-// Changes: None.
//--
class CMICmdCmdVarShowAttributes : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
- static CMICmdBase *CreateSelf(void);
+ static CMICmdBase *CreateSelf();
// Methods:
public:
- /* ctor */ CMICmdCmdVarShowAttributes(void);
+ /* ctor */ CMICmdCmdVarShowAttributes();
// Overridden:
public:
// From CMICmdInvoker::ICmd
- bool Execute(void) override;
- bool Acknowledge(void) override;
- bool ParseArgs(void) override;
+ bool Execute() override;
+ bool Acknowledge() override;
+ bool ParseArgs() override;
// From CMICmnBase
- /* dtor */ ~CMICmdCmdVarShowAttributes(void) override;
+ /* dtor */ ~CMICmdCmdVarShowAttributes() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCommands.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCommands.cpp
index 90a5d65..e97cc72 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCommands.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCommands.cpp
@@ -41,7 +41,7 @@
namespace MICmnCommands
{
-template <typename T> static bool Register(void);
+template <typename T> static bool Register();
}
//++ ------------------------------------------------------------------------------------
@@ -53,7 +53,7 @@ template <typename T> static bool Register(void);
//--
template <typename T>
static bool
-MICmnCommands::Register(void)
+MICmnCommands::Register()
{
static CMICmdFactory &rCmdFactory = CMICmdFactory::Instance();
const CMIUtilString strMiCmd = T().GetMiCmd();
@@ -70,7 +70,7 @@ MICmnCommands::Register(void)
// Throws: None.
//--
bool
-MICmnCommands::RegisterAll(void)
+MICmnCommands::RegisterAll()
{
bool bOk = MIstatus::success;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCommands.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCommands.h
index a99d09c..27f128e 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCommands.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCommands.h
@@ -15,9 +15,6 @@ namespace MICmnCommands
//++ ============================================================================
// Details: MI Command are instantiated and registered automatically with the
// Command Factory
-// Gotchas: None.
-// Authors: Illya Rudkin 18/02/2014.
-// Changes: None.
//--
-bool RegisterAll(void);
+bool RegisterAll();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdData.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdData.h
index d58de90..dcd5754 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdData.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdData.h
@@ -15,18 +15,15 @@
//++ ============================================================================
// Details: MI command metadata. Holds the command's name, MI number and options
// as found on stdin. Holds the command's MI output (written to stdout).
-// Gotchas: None.
-// Authors: Illya Rudkin 18/02/2014.
-// Changes: None.
//--
struct SMICmdData
{
- SMICmdData(void)
+ SMICmdData()
: id(0)
, bCmdValid(false)
, bCmdExecutedSuccessfully(false)
, bMIOldStyle(false)
- , bHasResultRecordExtra(false){};
+ , bHasResultRecordExtra(false){}
MIuint id; // A command's unique ID i.e. GUID
CMIUtilString strMiCmdToken; // The command's MI token (a number)
@@ -43,7 +40,7 @@ struct SMICmdData
bHasResultRecordExtra; // True = Yes command produced additional MI output to its 1 line response, false = no extra MI output formed
void
- Clear(void)
+ Clear()
{
id = 0;
strMiCmdToken.clear();
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdFactory.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdFactory.cpp
index 717a497..e2a8b5b 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdFactory.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdFactory.cpp
@@ -21,7 +21,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdFactory::CMICmdFactory(void)
+CMICmdFactory::CMICmdFactory()
{
}
@@ -32,7 +32,7 @@ CMICmdFactory::CMICmdFactory(void)
// Return: None.
// Throws: None.
//--
-CMICmdFactory::~CMICmdFactory(void)
+CMICmdFactory::~CMICmdFactory()
{
Shutdown();
}
@@ -46,7 +46,7 @@ CMICmdFactory::~CMICmdFactory(void)
// Throws: None.
//--
bool
-CMICmdFactory::Initialize(void)
+CMICmdFactory::Initialize()
{
m_clientUsageRefCnt++;
@@ -69,7 +69,7 @@ CMICmdFactory::Initialize(void)
// Throws: None.
//--
bool
-CMICmdFactory::Shutdown(void)
+CMICmdFactory::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -194,8 +194,6 @@ CMICmdFactory::CmdExist(const CMIUtilString &vMiCmd) const
bool
CMICmdFactory::CmdCreate(const CMIUtilString &vMiCmd, const SMICmdData &vCmdData, CMICmdBase *&vpNewCmd)
{
- bool bOk = MIstatus::success;
-
vpNewCmd = nullptr;
if (!IsValid(vMiCmd))
@@ -217,9 +215,8 @@ CMICmdFactory::CmdCreate(const CMIUtilString &vMiCmd, const SMICmdData &vCmdData
SMICmdData cmdData(vCmdData);
cmdData.id = pCmd->GetGUID();
- bOk = pCmd->SetCmdData(cmdData);
- if (bOk)
- vpNewCmd = pCmd;
+ pCmd->SetCmdData(cmdData);
+ vpNewCmd = pCmd;
- return bOk;
+ return MIstatus::success;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdFactory.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdFactory.h
index 9a5e076..99f6f0c 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdFactory.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdFactory.h
@@ -25,9 +25,6 @@ struct SMICmdData;
// MI application understands to interpret. Creates commands objects.
// The Command Factory is carried out in the main thread.
// A singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 19/02/2014.
-// Changes: None.
//--
class CMICmdFactory : public CMICmnBase, public MI::ISingleton<CMICmdFactory>
{
@@ -35,7 +32,7 @@ class CMICmdFactory : public CMICmnBase, public MI::ISingleton<CMICmdFactory>
// Typedefs:
public:
- typedef CMICmdBase *(*CmdCreatorFnPtr)(void);
+ typedef CMICmdBase *(*CmdCreatorFnPtr)();
// Class:
public:
@@ -45,25 +42,25 @@ class CMICmdFactory : public CMICmnBase, public MI::ISingleton<CMICmdFactory>
class ICmd
{
public:
- virtual const CMIUtilString &GetMiCmd(void) const = 0;
- virtual CmdCreatorFnPtr GetCmdCreatorFn(void) const = 0;
+ virtual const CMIUtilString &GetMiCmd() const = 0;
+ virtual CmdCreatorFnPtr GetCmdCreatorFn() const = 0;
// virtual CMICmdBase * CreateSelf( void ) = 0; // Not possible as require a static creator
// function in the command class, here for awareness
- /* dtor */ virtual ~ICmd(void){};
+ /* dtor */ virtual ~ICmd(){}
};
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
bool CmdRegister(const CMIUtilString &vMiCmd, CmdCreatorFnPtr vCmdCreateFn);
bool CmdCreate(const CMIUtilString &vMiCmd, const SMICmdData &vCmdData, CMICmdBase *&vpNewCmd);
bool CmdExist(const CMIUtilString &vMiCmd) const;
// Methods:
private:
- /* ctor */ CMICmdFactory(void);
+ /* ctor */ CMICmdFactory();
/* ctor */ CMICmdFactory(const CMICmdFactory &);
void operator=(const CMICmdFactory &);
@@ -73,7 +70,7 @@ class CMICmdFactory : public CMICmnBase, public MI::ISingleton<CMICmdFactory>
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmdFactory(void) override;
+ /* dtor */ ~CMICmdFactory() override;
// Typedefs:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInterpreter.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInterpreter.cpp
index 3c5285f..1abcc9a 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInterpreter.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInterpreter.cpp
@@ -18,7 +18,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdInterpreter::CMICmdInterpreter(void)
+CMICmdInterpreter::CMICmdInterpreter()
: m_rCmdFactory(CMICmdFactory::Instance())
{
}
@@ -30,7 +30,7 @@ CMICmdInterpreter::CMICmdInterpreter(void)
// Return: None.
// Throws: None.
//--
-CMICmdInterpreter::~CMICmdInterpreter(void)
+CMICmdInterpreter::~CMICmdInterpreter()
{
Shutdown();
}
@@ -44,7 +44,7 @@ CMICmdInterpreter::~CMICmdInterpreter(void)
// Throws: None.
//--
bool
-CMICmdInterpreter::Initialize(void)
+CMICmdInterpreter::Initialize()
{
m_clientUsageRefCnt++;
@@ -65,7 +65,7 @@ CMICmdInterpreter::Initialize(void)
// Throws: None.
//--
bool
-CMICmdInterpreter::Shutdown(void)
+CMICmdInterpreter::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -160,10 +160,10 @@ CMICmdInterpreter::MiHasCmdTokenEndingHyphen(const CMIUtilString &vTextLine)
if (MiHasCmdTokenPresent(vTextLine))
{
const std::string strNum = vTextLine.substr(0, nPos);
- if (!CMIUtilString(strNum.c_str()).IsNumber())
+ if (!CMIUtilString(strNum).IsNumber())
return false;
- m_miCmdData.strMiCmdToken = strNum.c_str();
+ m_miCmdData.strMiCmdToken = strNum;
}
m_miCmdData.bMIOldStyle = false;
@@ -256,20 +256,20 @@ CMICmdInterpreter::MiHasCmd(const CMIUtilString &vTextLine)
{
if (nPos2 == nLen)
return false;
- const CMIUtilString cmd = CMIUtilString(vTextLine.substr(nPos + 1, nPos2 - nPos - 1).c_str());
+ const CMIUtilString cmd = CMIUtilString(vTextLine.substr(nPos + 1, nPos2 - nPos - 1));
if (cmd.empty())
return false;
m_miCmdData.strMiCmd = cmd;
if (nPos2 < nLen)
- m_miCmdData.strMiCmdOption = CMIUtilString(vTextLine.substr(nPos2 + 1, nLen - nPos2 - 1).c_str());
+ m_miCmdData.strMiCmdOption = CMIUtilString(vTextLine.substr(nPos2 + 1, nLen - nPos2 - 1));
bFoundCmd = true;
}
else
{
- const CMIUtilString cmd = CMIUtilString(vTextLine.substr(nPos + 1, nLen - nPos - 1).c_str());
+ const CMIUtilString cmd = CMIUtilString(vTextLine.substr(nPos + 1, nLen - nPos - 1));
if (cmd.empty())
return false;
m_miCmdData.strMiCmd = cmd;
@@ -291,7 +291,7 @@ CMICmdInterpreter::MiHasCmd(const CMIUtilString &vTextLine)
// Throws: None.
//--
const SMICmdData &
-CMICmdInterpreter::MiGetCmdData(void) const
+CMICmdInterpreter::MiGetCmdData() const
{
return m_miCmdData;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInterpreter.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInterpreter.h
index e243084..5aa9445 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInterpreter.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInterpreter.h
@@ -23,9 +23,6 @@ class CMICmdFactory;
// matches Machine Interface (MI) format and commands defined in the
// MI application.
// A singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 18/02/2014.
-// Changes: None.
//--
class CMICmdInterpreter : public CMICmnBase, public MI::ISingleton<CMICmdInterpreter>
{
@@ -35,13 +32,13 @@ class CMICmdInterpreter : public CMICmnBase, public MI::ISingleton<CMICmdInterpr
public:
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
bool ValidateIsMi(const CMIUtilString &vTextLine, bool &vwbYesValid, bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData);
// Methods:
private:
- /* ctor */ CMICmdInterpreter(void);
+ /* ctor */ CMICmdInterpreter();
/* ctor */ CMICmdInterpreter(const CMICmdInterpreter &);
void operator=(const CMICmdInterpreter &);
@@ -55,7 +52,7 @@ class CMICmdInterpreter : public CMICmnBase, public MI::ISingleton<CMICmdInterpr
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmdInterpreter(void) override;
+ /* dtor */ ~CMICmdInterpreter() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInvoker.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInvoker.cpp
index 9f82e92..124a82d 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInvoker.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInvoker.cpp
@@ -22,7 +22,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdInvoker::CMICmdInvoker(void)
+CMICmdInvoker::CMICmdInvoker()
: m_rStreamOut(CMICmnStreamStdout::Instance())
{
}
@@ -34,7 +34,7 @@ CMICmdInvoker::CMICmdInvoker(void)
// Return: None.
// Throws: None.
//--
-CMICmdInvoker::~CMICmdInvoker(void)
+CMICmdInvoker::~CMICmdInvoker()
{
Shutdown();
}
@@ -48,7 +48,7 @@ CMICmdInvoker::~CMICmdInvoker(void)
// Throws: None.
//--
bool
-CMICmdInvoker::Initialize(void)
+CMICmdInvoker::Initialize()
{
m_clientUsageRefCnt++;
@@ -69,7 +69,7 @@ CMICmdInvoker::Initialize(void)
// Throws: None.
//--
bool
-CMICmdInvoker::Shutdown(void)
+CMICmdInvoker::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -92,7 +92,7 @@ CMICmdInvoker::Shutdown(void)
// Throws: None.
//--
void
-CMICmdInvoker::CmdDeleteAll(void)
+CMICmdInvoker::CmdDeleteAll()
{
CMICmdMgr &rMgr = CMICmdMgr::Instance();
MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.begin();
@@ -189,16 +189,20 @@ CMICmdInvoker::CmdExecute(CMICmdBase &vCmd)
{
bool bOk = CmdAdd(vCmd);
- if (bOk && !vCmd.ParseArgs())
+ if (bOk)
{
- // Report command execution failed
- const SMICmdData cmdData(vCmd.GetCmdData());
- CmdStdout(cmdData);
- CmdCauseAppExit(vCmd);
- CmdDelete(cmdData.id);
-
- // Proceed to wait or execute next command
- return MIstatus::success;
+ vCmd.AddCommonArgs();
+ if (!vCmd.ParseArgs())
+ {
+ // Report command execution failed
+ const SMICmdData cmdData(vCmd.GetCmdData());
+ CmdStdout(cmdData);
+ CmdCauseAppExit(vCmd);
+ CmdDelete(cmdData.id);
+
+ // Proceed to wait or execute next command
+ return MIstatus::success;
+ }
}
if (bOk && !vCmd.Execute())
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInvoker.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInvoker.h
index b178d43..d70a529 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInvoker.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdInvoker.h
@@ -36,9 +36,6 @@ class CMICmnStreamStdout;
// The Invoker takes ownership of any commands created which means it
// is the only object to delete them when a command is finished working.
// A singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 19/02/2014.
-// Changes: None.
//--
class CMICmdInvoker : public CMICmnBase, public CMICmdMgrSetCmdDeleteCallback::ICallback, public MI::ISingleton<CMICmdInvoker>
{
@@ -52,24 +49,24 @@ class CMICmdInvoker : public CMICmnBase, public CMICmdMgrSetCmdDeleteCallback::I
class ICmd
{
public:
- virtual bool Acknowledge(void) = 0;
- virtual bool Execute(void) = 0;
- virtual bool ParseArgs(void) = 0;
- virtual bool SetCmdData(const SMICmdData &vCmdData) = 0;
- virtual const SMICmdData &GetCmdData(void) const = 0;
- virtual const CMIUtilString &GetErrorDescription(void) const = 0;
- virtual void CmdFinishedTellInvoker(void) const = 0;
- virtual const CMIUtilString &GetMIResultRecord(void) const = 0;
- virtual const CMIUtilString &GetMIResultRecordExtra(void) const = 0;
- virtual bool HasMIResultRecordExtra(void) const = 0;
+ virtual bool Acknowledge() = 0;
+ virtual bool Execute() = 0;
+ virtual bool ParseArgs() = 0;
+ virtual void SetCmdData(const SMICmdData &vCmdData) = 0;
+ virtual const SMICmdData &GetCmdData() const = 0;
+ virtual const CMIUtilString &GetErrorDescription() const = 0;
+ virtual void CmdFinishedTellInvoker() const = 0;
+ virtual const CMIUtilString &GetMIResultRecord() const = 0;
+ virtual const CMIUtilString &GetMIResultRecordExtra() const = 0;
+ virtual bool HasMIResultRecordExtra() const = 0;
- /* dtor */ virtual ~ICmd(void){};
+ /* dtor */ virtual ~ICmd(){}
};
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
bool CmdExecute(CMICmdBase &vCmd);
bool CmdExecuteFinished(CMICmdBase &vCmd);
@@ -80,10 +77,10 @@ class CMICmdInvoker : public CMICmnBase, public CMICmdMgrSetCmdDeleteCallback::I
// Methods:
private:
- /* ctor */ CMICmdInvoker(void);
+ /* ctor */ CMICmdInvoker();
/* ctor */ CMICmdInvoker(const CMICmdInvoker &);
void operator=(const CMICmdInvoker &);
- void CmdDeleteAll(void);
+ void CmdDeleteAll();
bool CmdDelete(const MIuint vCmdId, const bool vbYesDeleteCmd = false);
bool CmdAdd(const CMICmdBase &vCmd);
bool CmdStdout(const SMICmdData &vCmdData) const;
@@ -92,7 +89,7 @@ class CMICmdInvoker : public CMICmnBase, public CMICmdMgrSetCmdDeleteCallback::I
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmdInvoker(void) override;
+ /* dtor */ ~CMICmdInvoker() override;
// From CMICmdMgrSetCmdDeleteCallback::ICallback
void Delete(SMICmdData &vCmd) override;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgr.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgr.cpp
index 76dbff6..449be44 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgr.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgr.cpp
@@ -25,7 +25,7 @@
// Return: None.
// Throws: None.
//--
-CMICmdMgr::CMICmdMgr(void)
+CMICmdMgr::CMICmdMgr()
: m_interpretor(CMICmdInterpreter::Instance())
, m_factory(CMICmdFactory::Instance())
, m_invoker(CMICmdInvoker::Instance())
@@ -39,7 +39,7 @@ CMICmdMgr::CMICmdMgr(void)
// Return: None.
// Throws: None.
//--
-CMICmdMgr::~CMICmdMgr(void)
+CMICmdMgr::~CMICmdMgr()
{
Shutdown();
}
@@ -53,7 +53,7 @@ CMICmdMgr::~CMICmdMgr(void)
// Throws: None.
//--
bool
-CMICmdMgr::Initialize(void)
+CMICmdMgr::Initialize()
{
m_clientUsageRefCnt++;
@@ -102,7 +102,7 @@ CMICmdMgr::Initialize(void)
// Throws: None.
//--
bool
-CMICmdMgr::Shutdown(void)
+CMICmdMgr::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgr.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgr.h
index 4956d5c..3136359 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgr.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgr.h
@@ -30,9 +30,6 @@ class CMICmdBase;
// Command Invoker, Command Factory and Command Monitor while independent
// units are overseen/managed by *this manager.
// A singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 19/02/2014.
-// Changes: None.
//--
class CMICmdMgr : public CMICmnBase, public MI::ISingleton<CMICmdMgr>
{
@@ -40,8 +37,8 @@ class CMICmdMgr : public CMICmnBase, public MI::ISingleton<CMICmdMgr>
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
bool CmdInterpret(const CMIUtilString &vTextLine, bool &vwbYesValid, bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData);
bool CmdExecute(const SMICmdData &vCmdData);
@@ -51,14 +48,14 @@ class CMICmdMgr : public CMICmnBase, public MI::ISingleton<CMICmdMgr>
// Methods:
private:
- /* ctor */ CMICmdMgr(void);
+ /* ctor */ CMICmdMgr();
/* ctor */ CMICmdMgr(const CMICmdMgr &);
void operator=(const CMICmdMgr &);
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMICmdMgr(void) override;
+ /* dtor */ ~CMICmdMgr() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp
index 3f2ccfd..3bef535 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp
@@ -20,7 +20,7 @@ namespace CMICmdMgrSetCmdDeleteCallback
// Return: None.
// Throws: None.
//--
-CSetClients::CSetClients(void)
+CSetClients::CSetClients()
: m_bClientUnregistered(false)
{
}
@@ -32,7 +32,7 @@ CSetClients::CSetClients(void)
// Return: None.
// Throws: None.
//--
-CSetClients::~CSetClients(void)
+CSetClients::~CSetClients()
{
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h
index 1c9be82..7e95d67 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h
@@ -28,16 +28,13 @@ namespace CMICmdMgrSetCmdDeleteCallback
// inherit this interface and register interest in command object
// deletion. An object deleting a command must not do it itself but call
// the Command Manager CmdDelete() function to delete a command object.
-// Gotchas: None.
-// Authors: Illya Rudkin 21/02/2014.
-// Changes: None.
//--
class ICallback
{
public:
virtual void Delete(SMICmdData &vCmd) = 0;
- /* dtor */ virtual ~ICallback(void){};
+ /* dtor */ virtual ~ICallback(){}
};
//++ ============================================================================
@@ -47,15 +44,12 @@ class ICallback
// Manager to delete the command object. In so do all other registered
// objects get called to about the deletion including the object wanting
// to do the delete in the first place.
-// Gotchas: None.
-// Authors: Illya Rudkin 21/02/2014.
-// Changes: None.
//--
class CSetClients : public std::set<class ICallback *>, public CMICmnBase
{
// Methods:
public:
- /* ctor */ CSetClients(void);
+ /* ctor */ CSetClients();
bool Register(class ICallback &vObject);
bool Unregister(class ICallback &vObject);
@@ -64,7 +58,7 @@ class CSetClients : public std::set<class ICallback *>, public CMICmnBase
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CSetClients(void) override;
+ /* dtor */ ~CSetClients() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnBase.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnBase.cpp
index 0d9eda7..1240df7 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnBase.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnBase.cpp
@@ -22,7 +22,7 @@
// Return: None.
// Throws: None.
//--
-CMICmnBase::CMICmnBase(void)
+CMICmnBase::CMICmnBase()
: m_strMILastErrorDescription(CMIUtilString())
, m_bInitialized(false)
, m_pLog(&CMICmnLog::Instance())
@@ -37,7 +37,7 @@ CMICmnBase::CMICmnBase(void)
// Return: None.
// Throws: None.
//--
-CMICmnBase::~CMICmnBase(void)
+CMICmnBase::~CMICmnBase()
{
m_pLog = NULL;
}
@@ -50,7 +50,7 @@ CMICmnBase::~CMICmnBase(void)
// Throws: None.
//--
bool
-CMICmnBase::HaveErrorDescription(void) const
+CMICmnBase::HaveErrorDescription() const
{
return m_strMILastErrorDescription.empty();
}
@@ -63,7 +63,7 @@ CMICmnBase::HaveErrorDescription(void) const
// Throws: None.
//--
const CMIUtilString &
-CMICmnBase::GetErrorDescription(void) const
+CMICmnBase::GetErrorDescription() const
{
return m_strMILastErrorDescription;
}
@@ -111,7 +111,7 @@ CMICmnBase::SetErrorDescriptionNoLog(const CMIUtilString &vrTxt) const
// Throws: None.
//--
void
-CMICmnBase::ClrErrorDescription(void) const
+CMICmnBase::ClrErrorDescription() const
{
m_strMILastErrorDescription.clear();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnBase.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnBase.h
index d2e2bcd..befadbe 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnBase.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnBase.h
@@ -18,26 +18,23 @@ class CMICmnLog;
//++ ============================================================================
// Details: MI common code implementation base class.
-// Gotchas: None.
-// Authors: Illya Rudkin 28/01/2014.
-// Changes: None.
//--
class CMICmnBase
{
// Methods:
public:
- /* ctor */ CMICmnBase(void);
+ /* ctor */ CMICmnBase();
- bool HaveErrorDescription(void) const;
- const CMIUtilString &GetErrorDescription(void) const;
+ bool HaveErrorDescription() const;
+ const CMIUtilString &GetErrorDescription() const;
void SetErrorDescription(const CMIUtilString &vrTxt) const;
void SetErrorDescriptionn(const CMIUtilString vFormat, ...) const;
void SetErrorDescriptionNoLog(const CMIUtilString &vrTxt) const;
- void ClrErrorDescription(void) const;
+ void ClrErrorDescription() const;
// Overrideable:
public:
- /* dtor */ virtual ~CMICmnBase(void);
+ /* dtor */ virtual ~CMICmnBase();
// Attributes:
protected:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.cpp
index 8bad243..1d51abd 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.cpp
@@ -17,7 +17,7 @@
// Return: None.
// Throws: None.
//--
-CMICmnLLDBBroadcaster::CMICmnLLDBBroadcaster(void)
+CMICmnLLDBBroadcaster::CMICmnLLDBBroadcaster()
: lldb::SBBroadcaster("MI driver")
{
}
@@ -29,7 +29,7 @@ CMICmnLLDBBroadcaster::CMICmnLLDBBroadcaster(void)
// Return: None.
// Throws: None.
//--
-CMICmnLLDBBroadcaster::~CMICmnLLDBBroadcaster(void)
+CMICmnLLDBBroadcaster::~CMICmnLLDBBroadcaster()
{
Shutdown();
}
@@ -43,7 +43,7 @@ CMICmnLLDBBroadcaster::~CMICmnLLDBBroadcaster(void)
// Throws: None.
//--
bool
-CMICmnLLDBBroadcaster::Initialize(void)
+CMICmnLLDBBroadcaster::Initialize()
{
m_clientUsageRefCnt++;
@@ -64,7 +64,7 @@ CMICmnLLDBBroadcaster::Initialize(void)
// Throws: None.
//--
bool
-CMICmnLLDBBroadcaster::Shutdown(void)
+CMICmnLLDBBroadcaster::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.h
index dc0de47..09b95f4 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.h
@@ -21,9 +21,6 @@
// *** not
//
// A singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 28/02/2014.
-// Changes: None.
//--
class CMICmnLLDBBroadcaster : public CMICmnBase, public lldb::SBBroadcaster, public MI::ISingleton<CMICmnLLDBBroadcaster>
{
@@ -31,16 +28,16 @@ class CMICmnLLDBBroadcaster : public CMICmnBase, public lldb::SBBroadcaster, pub
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
// Methods:
private:
- /* ctor */ CMICmnLLDBBroadcaster(void);
+ /* ctor */ CMICmnLLDBBroadcaster();
/* ctor */ CMICmnLLDBBroadcaster(const CMICmnLLDBBroadcaster &);
void operator=(const CMICmnLLDBBroadcaster &);
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmnLLDBBroadcaster(void) override;
+ /* dtor */ ~CMICmnLLDBBroadcaster() override;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
index cf74fe5..ef99ac9 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
@@ -35,7 +35,7 @@
// Return: None.
// Throws: None.
//--
-CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo(void)
+CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo()
: m_nBrkPointCntMax(INT32_MAX)
, m_currentSelectedThread(LLDB_INVALID_THREAD_ID)
, m_constStrSharedDataKeyWkDir("Working Directory")
@@ -53,7 +53,7 @@ CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo(void)
// Return: None.
// Throws: None.
//--
-CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo(void)
+CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo()
{
Shutdown();
}
@@ -67,7 +67,7 @@ CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebugSessionInfo::Initialize(void)
+CMICmnLLDBDebugSessionInfo::Initialize()
{
m_clientUsageRefCnt++;
@@ -91,7 +91,7 @@ CMICmnLLDBDebugSessionInfo::Initialize(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebugSessionInfo::Shutdown(void)
+CMICmnLLDBDebugSessionInfo::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -99,16 +99,9 @@ CMICmnLLDBDebugSessionInfo::Shutdown(void)
if (!m_bInitialized)
return MIstatus::success;
- bool bOk = MIstatus::success;
- CMIUtilString errMsg;
-
// Tidy up
- bOk = SharedDataDestroy();
- if (!bOk)
- {
- errMsg = CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE));
- errMsg += "\n";
- }
+ SharedDataDestroy();
+
m_vecActiveThreadId.clear();
CMICmnLLDBDebugSessionInfoVarObj::VarObjClear();
@@ -125,18 +118,15 @@ CMICmnLLDBDebugSessionInfo::Shutdown(void)
// stopped i.e. application shutdown.
// Type: Method.
// Args: None.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
-CMICmnLLDBDebugSessionInfo::SharedDataDestroy(void)
+void
+CMICmnLLDBDebugSessionInfo::SharedDataDestroy()
{
m_mapIdToSessionData.Clear();
m_vecVarObj.clear();
m_mapBrkPtIdToBrkPtInfo.clear();
-
- return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@@ -376,8 +366,7 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo(const SMICmdData &vCmdData,
const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID()));
const CMICmnMIValueConst miValueConst1(strId);
const CMICmnMIValueResult miValueResult1("id", miValueConst1);
- if (!vwrMIValueTuple.Add(miValueResult1))
- return MIstatus::failure;
+ vwrMIValueTuple.Add(miValueResult1);
// Add "target-id"
const char *pThreadName = rThread.GetName();
@@ -392,8 +381,7 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo(const SMICmdData &vCmdData,
strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID());
const CMICmnMIValueConst miValueConst2(strThread);
const CMICmnMIValueResult miValueResult2("target-id", miValueConst2);
- if (!vwrMIValueTuple.Add(miValueResult2))
- return MIstatus::failure;
+ vwrMIValueTuple.Add(miValueResult2);
// Add "frame"
if (veThreadInfoFormat != eThreadInfoFormat_NoFrames)
@@ -403,15 +391,13 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo(const SMICmdData &vCmdData,
return MIstatus::failure;
const CMICmnMIValueConst miValueConst3(strFrames, true);
- if (!vwrMIValueTuple.Add(miValueConst3, false))
- return MIstatus::failure;
+ vwrMIValueTuple.Add(miValueConst3, false);
}
// Add "state"
const CMICmnMIValueConst miValueConst4(strState);
const CMICmnMIValueResult miValueResult4("state", miValueConst4);
- if (!vwrMIValueTuple.Add(miValueResult4))
- return MIstatus::failure;
+ vwrMIValueTuple.Add(miValueResult4);
return MIstatus::success;
}
@@ -461,9 +447,8 @@ CMICmnLLDBDebugSessionInfo::MIResponseForVariableInfoInternal(const VariableInfo
const bool vbIsArgs,
const bool vbMarkArgs)
{
- bool bOk = MIstatus::success;
const MIuint nArgs = vwrSBValueList.GetSize();
- for (MIuint i = 0; bOk && (i < nArgs); i++)
+ for (MIuint i = 0; i < nArgs; i++)
{
CMICmnMIValueTuple miValueTuple;
lldb::SBValue value = vwrSBValueList.GetValueAtIndex(i);
@@ -514,7 +499,7 @@ CMICmnLLDBDebugSessionInfo::MIResponseForVariableInfoInternal(const VariableInfo
vwrMiValueList.Add(miValueResultName);
}
}
- return bOk;
+ return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@@ -567,17 +552,14 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(const lldb::SBThread &vrThre
const CMIUtilString strLevel(CMIUtilString::Format("%d", vnLevel));
const CMICmnMIValueConst miValueConst(strLevel);
const CMICmnMIValueResult miValueResult("level", miValueConst);
- if (!vwrMiValueTuple.Add(miValueResult))
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult);
const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, pc));
const CMICmnMIValueConst miValueConst2(strAddr);
const CMICmnMIValueResult miValueResult2("addr", miValueConst2);
- if (!vwrMiValueTuple.Add(miValueResult2))
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3(fnName);
const CMICmnMIValueResult miValueResult3("func", miValueConst3);
- if (!vwrMiValueTuple.Add(miValueResult3))
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult3);
if (veFrameInfoFormat != eFrameInfoFormat_NoArguments)
{
CMICmnMIValueList miValueList(true);
@@ -592,22 +574,18 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(const lldb::SBThread &vrThre
return MIstatus::failure;
const CMICmnMIValueResult miValueResult4("args", miValueList);
- if (!vwrMiValueTuple.Add(miValueResult4))
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult4);
}
const CMICmnMIValueConst miValueConst5(fileName);
const CMICmnMIValueResult miValueResult5("file", miValueConst5);
- if (!vwrMiValueTuple.Add(miValueResult5))
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult5);
const CMICmnMIValueConst miValueConst6(path);
const CMICmnMIValueResult miValueResult6("fullname", miValueConst6);
- if (!vwrMiValueTuple.Add(miValueResult6))
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult6);
const CMIUtilString strLine(CMIUtilString::Format("%d", nLine));
const CMICmnMIValueConst miValueConst7(strLine);
const CMICmnMIValueResult miValueResult7("line", miValueConst7);
- if (!vwrMiValueTuple.Add(miValueResult7))
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult7);
return MIstatus::success;
}
@@ -659,38 +637,30 @@ CMICmnLLDBDebugSessionInfo::GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::add
// Type: Method.
// Args: vrBrkPtInfo - (R) Break point information object.
// vwrMIValueTuple - (W) MI value tuple object.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple)
{
const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, vrBrkPtInfo.m_pc));
const CMICmnMIValueConst miValueConst2(strAddr);
const CMICmnMIValueResult miValueResult2("addr", miValueConst2);
- if (!vwrMiValueTuple.Add(miValueResult2))
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_fnName);
const CMICmnMIValueResult miValueResult3("func", miValueConst3);
- if (!vwrMiValueTuple.Add(miValueResult3))
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult3);
const CMICmnMIValueConst miValueConst5(vrBrkPtInfo.m_fileName);
const CMICmnMIValueResult miValueResult5("file", miValueConst5);
- if (!vwrMiValueTuple.Add(miValueResult5))
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult5);
const CMIUtilString strN5 = CMIUtilString::Format("%s/%s", vrBrkPtInfo.m_path.c_str(), vrBrkPtInfo.m_fileName.c_str());
const CMICmnMIValueConst miValueConst6(strN5);
const CMICmnMIValueResult miValueResult6("fullname", miValueConst6);
- if (!vwrMiValueTuple.Add(miValueResult6))
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult6);
const CMIUtilString strLine(CMIUtilString::Format("%d", vrBrkPtInfo.m_nLine));
const CMICmnMIValueConst miValueConst7(strLine);
const CMICmnMIValueResult miValueResult7("line", miValueConst7);
- if (!vwrMiValueTuple.Add(miValueResult7))
- return MIstatus::failure;
-
- return MIstatus::success;
+ vwrMiValueTuple.Add(miValueResult7);
}
//++ ------------------------------------------------------------------------------------
@@ -716,65 +686,65 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInf
// "type="
const CMICmnMIValueConst miValueConst2(vrBrkPtInfo.m_strType);
const CMICmnMIValueResult miValueResult2("type", miValueConst2);
- bool bOk = miValueTuple.Add(miValueResult2);
+ miValueTuple.Add(miValueResult2);
// "disp="
const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_bDisp ? "del" : "keep");
const CMICmnMIValueResult miValueResult3("disp", miValueConst3);
- bOk = bOk && miValueTuple.Add(miValueResult3);
+ miValueTuple.Add(miValueResult3);
// "enabled="
const CMICmnMIValueConst miValueConst4(vrBrkPtInfo.m_bEnabled ? "y" : "n");
const CMICmnMIValueResult miValueResult4("enabled", miValueConst4);
- bOk = bOk && miValueTuple.Add(miValueResult4);
+ miValueTuple.Add(miValueResult4);
// "addr="
// "func="
// "file="
// "fullname="
// "line="
- bOk = bOk && MIResponseFormBrkPtFrameInfo(vrBrkPtInfo, miValueTuple);
+ MIResponseFormBrkPtFrameInfo(vrBrkPtInfo, miValueTuple);
// "pending="
if (vrBrkPtInfo.m_bPending)
{
const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOrigLoc);
const CMICmnMIValueList miValueList(miValueConst);
const CMICmnMIValueResult miValueResult("pending", miValueList);
- bOk = bOk && miValueTuple.Add(miValueResult);
+ miValueTuple.Add(miValueResult);
}
if (vrBrkPtInfo.m_bHaveArgOptionThreadGrp)
{
const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOptThrdGrp);
const CMICmnMIValueList miValueList(miValueConst);
const CMICmnMIValueResult miValueResult("thread-groups", miValueList);
- bOk = bOk && miValueTuple.Add(miValueResult);
+ miValueTuple.Add(miValueResult);
}
// "times="
const CMICmnMIValueConst miValueConstB(CMIUtilString::Format("%d", vrBrkPtInfo.m_nTimes));
const CMICmnMIValueResult miValueResultB("times", miValueConstB);
- bOk = bOk && miValueTuple.Add(miValueResultB);
+ miValueTuple.Add(miValueResultB);
// "thread="
if (vrBrkPtInfo.m_bBrkPtThreadId)
{
const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nBrkPtThreadId));
const CMICmnMIValueResult miValueResult("thread", miValueConst);
- bOk = bOk && miValueTuple.Add(miValueResult);
+ miValueTuple.Add(miValueResult);
}
// "cond="
if (vrBrkPtInfo.m_bCondition)
{
const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strCondition);
const CMICmnMIValueResult miValueResult("cond", miValueConst);
- bOk = bOk && miValueTuple.Add(miValueResult);
+ miValueTuple.Add(miValueResult);
}
// "ignore="
if (vrBrkPtInfo.m_nIgnore != 0)
{
const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nIgnore));
const CMICmnMIValueResult miValueResult("ignore", miValueConst);
- bOk = bOk && miValueTuple.Add(miValueResult);
+ miValueTuple.Add(miValueResult);
}
// "original-location="
const CMICmnMIValueConst miValueConstC(vrBrkPtInfo.m_strOrigLoc);
const CMICmnMIValueResult miValueResultC("original-location", miValueConstC);
- bOk = bOk && miValueTuple.Add(miValueResultC);
+ miValueTuple.Add(miValueResultC);
vwrMiValueTuple = miValueTuple;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
index 7e0ce6a..dbad0c8 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
@@ -38,9 +38,6 @@ class CMICmnMIValueList;
// retrieved by the same or other subsequent commands.
// It primarily holds LLDB type objects.
// A singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 04/03/2014.
-// Changes: None.
//--
class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMICmnLLDBDebugSessionInfo>
{
@@ -55,7 +52,7 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMIC
//--
struct SBrkPtInfo
{
- SBrkPtInfo(void)
+ SBrkPtInfo()
: m_id(0)
, m_bDisp(false)
, m_bEnabled(false)
@@ -140,13 +137,13 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMIC
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
// Variant type data which can be assigned and retrieved across all command instances
template <typename T> bool SharedDataAdd(const CMIUtilString &vKey, const T &vData);
template <typename T> bool SharedDataRetrieve(const CMIUtilString &vKey, T &vwData);
- bool SharedDataDestroy(void);
+ void SharedDataDestroy();
// Common command required functionality
bool AccessPath(const CMIUtilString &vPath, bool &vwbYesAccessible);
@@ -159,7 +156,7 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMIC
bool MIResponseFormVariableInfo(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes,
const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList,
const MIuint vnMaxDepth = 10, const bool vbMarkArgs = false);
- bool MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple);
+ void MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple);
bool MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple);
bool GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, SBrkPtInfo &vrwBrkPtInfo) const;
bool RecordBrkPtInfo(const MIuint vnBrkPtId, const SBrkPtInfo &vrBrkPtInfo);
@@ -194,7 +191,7 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMIC
// Methods:
private:
- /* ctor */ CMICmnLLDBDebugSessionInfo(void);
+ /* ctor */ CMICmnLLDBDebugSessionInfo();
/* ctor */ CMICmnLLDBDebugSessionInfo(const CMICmnLLDBDebugSessionInfo &);
void operator=(const CMICmnLLDBDebugSessionInfo &);
//
@@ -209,7 +206,7 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMIC
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmnLLDBDebugSessionInfo(void) override;
+ /* dtor */ ~CMICmnLLDBDebugSessionInfo() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp
index 6213084..d4d2896 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp
@@ -32,7 +32,7 @@ CMICmnLLDBDebugSessionInfoVarObj::varFormat_e CMICmnLLDBDebugSessionInfoVarObj::
// Return: None.
// Throws: None.
//--
-CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(void)
+CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj()
: m_eVarFormat(eVarFormat_Natural)
, m_eVarType(eVarType_Internal)
{
@@ -205,7 +205,7 @@ CMICmnLLDBDebugSessionInfoVarObj::MoveOther(CMICmnLLDBDebugSessionInfoVarObj &vr
// Return: None.
// Throws: None.
//--
-CMICmnLLDBDebugSessionInfoVarObj::~CMICmnLLDBDebugSessionInfoVarObj(void)
+CMICmnLLDBDebugSessionInfoVarObj::~CMICmnLLDBDebugSessionInfoVarObj()
{
}
@@ -285,7 +285,7 @@ CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(const lldb::SBValue &v
}
}
- return utilValue.GetValue().Escape().AddSlashes();
+ return utilValue.GetValue().AddSlashes();
}
//++ ------------------------------------------------------------------------------------
@@ -340,7 +340,7 @@ CMICmnLLDBDebugSessionInfoVarObj::GetStringFormatted(const MIuint64 vnValue, con
// Throws: None.
//--
void
-CMICmnLLDBDebugSessionInfoVarObj::VarObjClear(void)
+CMICmnLLDBDebugSessionInfoVarObj::VarObjClear()
{
ms_mapVarIdToVarObj.clear();
}
@@ -421,7 +421,7 @@ CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(const CMIUtilString &vrVarName, CMIC
// Throws: None.
//--
void
-CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero(void)
+CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero()
{
ms_nVarUniqueId = 0;
}
@@ -449,7 +449,7 @@ CMICmnLLDBDebugSessionInfoVarObj::VarObjSetFormat(varFormat_e eDefaultFormat)
// Throws: None.
//--
void
-CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc(void)
+CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc()
{
ms_nVarUniqueId++;
}
@@ -463,7 +463,7 @@ CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc(void)
// Throws: None.
//--
MIuint
-CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet(void)
+CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet()
{
return ms_nVarUniqueId;
}
@@ -476,7 +476,7 @@ CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet(void)
// Throws: None.
//--
const CMIUtilString &
-CMICmnLLDBDebugSessionInfoVarObj::GetName(void) const
+CMICmnLLDBDebugSessionInfoVarObj::GetName() const
{
return m_strName;
}
@@ -490,7 +490,7 @@ CMICmnLLDBDebugSessionInfoVarObj::GetName(void) const
// Throws: None.
//--
const CMIUtilString &
-CMICmnLLDBDebugSessionInfoVarObj::GetNameReal(void) const
+CMICmnLLDBDebugSessionInfoVarObj::GetNameReal() const
{
return m_strNameReal;
}
@@ -503,7 +503,7 @@ CMICmnLLDBDebugSessionInfoVarObj::GetNameReal(void) const
// Throws: None.
//--
const CMIUtilString &
-CMICmnLLDBDebugSessionInfoVarObj::GetValueFormatted(void) const
+CMICmnLLDBDebugSessionInfoVarObj::GetValueFormatted() const
{
return m_strFormattedValue;
}
@@ -516,7 +516,7 @@ CMICmnLLDBDebugSessionInfoVarObj::GetValueFormatted(void) const
// Throws: None.
//--
lldb::SBValue &
-CMICmnLLDBDebugSessionInfoVarObj::GetValue(void)
+CMICmnLLDBDebugSessionInfoVarObj::GetValue()
{
return m_SBValue;
}
@@ -529,7 +529,7 @@ CMICmnLLDBDebugSessionInfoVarObj::GetValue(void)
// Throws: None.
//--
const lldb::SBValue &
-CMICmnLLDBDebugSessionInfoVarObj::GetValue(void) const
+CMICmnLLDBDebugSessionInfoVarObj::GetValue() const
{
return m_SBValue;
}
@@ -561,7 +561,7 @@ CMICmnLLDBDebugSessionInfoVarObj::SetVarFormat(const varFormat_e veVarFormat)
// Throws: None.
//--
void
-CMICmnLLDBDebugSessionInfoVarObj::UpdateValue(void)
+CMICmnLLDBDebugSessionInfoVarObj::UpdateValue()
{
m_strFormattedValue = GetValueStringFormatted(m_SBValue, m_eVarFormat);
@@ -580,7 +580,7 @@ CMICmnLLDBDebugSessionInfoVarObj::UpdateValue(void)
// Throws: None.
//--
CMICmnLLDBDebugSessionInfoVarObj::varType_e
-CMICmnLLDBDebugSessionInfoVarObj::GetType(void) const
+CMICmnLLDBDebugSessionInfoVarObj::GetType() const
{
return m_eVarType;
}
@@ -595,7 +595,7 @@ CMICmnLLDBDebugSessionInfoVarObj::GetType(void) const
// Throws: None.
//--
const CMIUtilString &
-CMICmnLLDBDebugSessionInfoVarObj::GetVarParentName(void) const
+CMICmnLLDBDebugSessionInfoVarObj::GetVarParentName() const
{
return m_strVarObjParentName;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h
index e768c5f..c4ae8e8 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h
@@ -19,9 +19,6 @@
//++ ============================================================================
// Details: MI debug session variable object. The static functionality in *this
// class manages a map container of *these variable objects.
-// Gotchas: None.
-// Authors: Illya Rudkin 24/03/2014.
-// Changes: None.
//--
class CMICmnLLDBDebugSessionInfoVarObj
{
@@ -63,15 +60,15 @@ class CMICmnLLDBDebugSessionInfoVarObj
static void VarObjDelete(const CMIUtilString &vrVarName);
static bool VarObjGet(const CMIUtilString &vrVarName, CMICmnLLDBDebugSessionInfoVarObj &vrwVarObj);
static void VarObjUpdate(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj);
- static void VarObjIdInc(void);
- static MIuint VarObjIdGet(void);
- static void VarObjIdResetToZero(void);
- static void VarObjClear(void);
+ static void VarObjIdInc();
+ static MIuint VarObjIdGet();
+ static void VarObjIdResetToZero();
+ static void VarObjClear();
static void VarObjSetFormat(varFormat_e eDefaultFormat);
// Methods:
public:
- /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(void);
+ /* ctor */ CMICmnLLDBDebugSessionInfoVarObj();
/* ctor */ CMICmnLLDBDebugSessionInfoVarObj(const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName,
const lldb::SBValue &vrValue);
/* ctor */ CMICmnLLDBDebugSessionInfoVarObj(const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName,
@@ -83,20 +80,20 @@ class CMICmnLLDBDebugSessionInfoVarObj
CMICmnLLDBDebugSessionInfoVarObj &operator=(const CMICmnLLDBDebugSessionInfoVarObj &vrOther);
CMICmnLLDBDebugSessionInfoVarObj &operator=(CMICmnLLDBDebugSessionInfoVarObj &&vrwOther);
//
- const CMIUtilString &GetName(void) const;
- const CMIUtilString &GetNameReal(void) const;
- const CMIUtilString &GetValueFormatted(void) const;
- lldb::SBValue &GetValue(void);
- const lldb::SBValue &GetValue(void) const;
- varType_e GetType(void) const;
+ const CMIUtilString &GetName() const;
+ const CMIUtilString &GetNameReal() const;
+ const CMIUtilString &GetValueFormatted() const;
+ lldb::SBValue &GetValue();
+ const lldb::SBValue &GetValue() const;
+ varType_e GetType() const;
bool SetVarFormat(const varFormat_e veVarFormat);
- const CMIUtilString &GetVarParentName(void) const;
- void UpdateValue(void);
+ const CMIUtilString &GetVarParentName() const;
+ void UpdateValue();
// Overridden:
public:
// From CMICmnBase
- /* dtor */ virtual ~CMICmnLLDBDebugSessionInfoVarObj(void);
+ /* dtor */ virtual ~CMICmnLLDBDebugSessionInfoVarObj();
// Typedefs:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp
index b626ccc..3042e1c 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp
@@ -12,6 +12,11 @@
#include "lldb/API/SBThread.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBCommandInterpreter.h"
+#include "lldb/API/SBTypeSummary.h"
+#include "lldb/API/SBTypeCategory.h"
+#include "lldb/API/SBTypeNameSpecifier.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/API/SBType.h"
// In-house headers:
#include "MICmnLLDBDebugger.h"
@@ -24,13 +29,50 @@
#include "MIUtilSingletonHelper.h"
//++ ------------------------------------------------------------------------------------
+// MI private summary providers
+static inline bool
+MI_char_summary_provider(lldb::SBValue value, lldb::SBTypeSummaryOptions options, lldb::SBStream &stream)
+{
+ if (!value.IsValid())
+ return false;
+
+ lldb::SBType value_type = value.GetType();
+ if(!value_type.IsValid())
+ return false;
+
+ lldb::BasicType type_code = value_type.GetBasicType();
+ if (type_code == lldb::eBasicTypeSignedChar)
+ stream.Printf("%d %s", (int)value.GetValueAsSigned(), value.GetValue());
+ else if (type_code == lldb::eBasicTypeUnsignedChar)
+ stream.Printf("%u %s", (unsigned)value.GetValueAsUnsigned(), value.GetValue());
+ else
+ return false;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// MI summary helper routines
+static inline bool
+MI_add_summary(lldb::SBTypeCategory category, const char *typeName, lldb::SBTypeSummary::FormatCallback cb,
+ uint32_t options, bool regex = false)
+{
+#if defined(LLDB_DISABLE_PYTHON)
+ return false;
+#else
+ lldb::SBTypeSummary summary = lldb::SBTypeSummary::CreateWithCallback(cb, options);
+ return summary.IsValid() ? category.AddTypeSummary(lldb::SBTypeNameSpecifier(typeName, regex), summary) : false;
+#endif
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: CMICmnLLDBDebugger constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
-CMICmnLLDBDebugger::CMICmnLLDBDebugger(void)
+CMICmnLLDBDebugger::CMICmnLLDBDebugger()
: m_constStrThisThreadId("MI debugger event")
{
}
@@ -42,7 +84,7 @@ CMICmnLLDBDebugger::CMICmnLLDBDebugger(void)
// Return: None.
// Throws: None.
//--
-CMICmnLLDBDebugger::~CMICmnLLDBDebugger(void)
+CMICmnLLDBDebugger::~CMICmnLLDBDebugger()
{
Shutdown();
}
@@ -56,7 +98,7 @@ CMICmnLLDBDebugger::~CMICmnLLDBDebugger(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebugger::Initialize(void)
+CMICmnLLDBDebugger::Initialize()
{
m_clientUsageRefCnt++;
@@ -98,7 +140,7 @@ CMICmnLLDBDebugger::Initialize(void)
errMsg += GetErrorDescription().c_str();
}
bOk = bOk && InitStdStreams();
-
+ bOk = bOk && RegisterMISummaryProviders();
m_bInitialized = bOk;
if (!bOk && !HaveErrorDescription())
@@ -119,7 +161,7 @@ CMICmnLLDBDebugger::Initialize(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebugger::Shutdown(void)
+CMICmnLLDBDebugger::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -173,7 +215,7 @@ CMICmnLLDBDebugger::Shutdown(void)
// Throws: None.
//--
lldb::SBDebugger &
-CMICmnLLDBDebugger::GetTheDebugger(void)
+CMICmnLLDBDebugger::GetTheDebugger()
{
return m_lldbDebugger;
}
@@ -186,7 +228,7 @@ CMICmnLLDBDebugger::GetTheDebugger(void)
// Throws: None.
//--
lldb::SBListener &
-CMICmnLLDBDebugger::GetTheListener(void)
+CMICmnLLDBDebugger::GetTheListener()
{
return m_lldbListener;
}
@@ -216,7 +258,7 @@ CMICmnLLDBDebugger::SetDriver(const CMIDriverBase &vClientDriver)
// Throws: None.
//--
CMIDriverBase &
-CMICmnLLDBDebugger::GetDriver(void) const
+CMICmnLLDBDebugger::GetDriver() const
{
return *m_pClientDriver;
}
@@ -234,7 +276,7 @@ CMICmnLLDBDebugger::GetDriver(void) const
// Throws: None.
//--
void
-CMICmnLLDBDebugger::WaitForHandleEvent(void)
+CMICmnLLDBDebugger::WaitForHandleEvent()
{
std::unique_lock<std::mutex> lock(m_mutexEventQueue);
@@ -254,7 +296,7 @@ CMICmnLLDBDebugger::WaitForHandleEvent(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent(void)
+CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent()
{
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
if (!rSessionInfo.GetDebugger().GetAsync())
@@ -276,7 +318,7 @@ CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent(void)
// Throws: None.
//--
void
-CMICmnLLDBDebugger::RebroadcastStopEvent(void)
+CMICmnLLDBDebugger::RebroadcastStopEvent()
{
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
const bool include_expression_stops = false;
@@ -297,7 +339,7 @@ CMICmnLLDBDebugger::RebroadcastStopEvent(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebugger::InitSBDebugger(void)
+CMICmnLLDBDebugger::InitSBDebugger()
{
m_lldbDebugger = lldb::SBDebugger::Create(false);
if (!m_lldbDebugger.IsValid())
@@ -321,7 +363,7 @@ CMICmnLLDBDebugger::InitSBDebugger(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebugger::InitStdStreams(void)
+CMICmnLLDBDebugger::InitStdStreams()
{
// This is not required when operating the MI driver's code as it has its own
// streams. Setting the Stdin for the lldbDebugger especially on LINUX will cause
@@ -342,7 +384,7 @@ CMICmnLLDBDebugger::InitStdStreams(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebugger::InitSBListener(void)
+CMICmnLLDBDebugger::InitSBListener()
{
m_lldbListener = m_lldbDebugger.GetListener();
if (!m_lldbListener.IsValid())
@@ -585,7 +627,7 @@ CMICmnLLDBDebugger::ClientGetMaskForAllClients(const CMIUtilString &vBroadcaster
while (it != m_mapIdToEventMask.end())
{
const CMIUtilString &rId((*it).first);
- if (rId.find(vBroadcasterClass.c_str()) != std::string::npos)
+ if (rId.find(vBroadcasterClass) != std::string::npos)
{
const MIuint clientsMask = (*it).second;
mask |= clientsMask;
@@ -678,9 +720,7 @@ CMICmnLLDBDebugger::ClientGetTheirMask(const CMIUtilString &vClientName, const C
return MIstatus::failure;
}
- CMIUtilString strId(vBroadcasterClass.c_str());
- strId += vClientName;
-
+ const CMIUtilString strId(vBroadcasterClass + vClientName);
const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId);
if (it != m_mapIdToEventMask.end())
{
@@ -776,7 +816,7 @@ CMICmnLLDBDebugger::ThreadRun(bool &vrbIsAlive)
// Throws: None.
//--
bool
-CMICmnLLDBDebugger::ThreadFinish(void)
+CMICmnLLDBDebugger::ThreadFinish()
{
return MIstatus::success;
}
@@ -789,7 +829,58 @@ CMICmnLLDBDebugger::ThreadFinish(void)
// Throws: None.
//--
const CMIUtilString &
-CMICmnLLDBDebugger::ThreadGetName(void) const
+CMICmnLLDBDebugger::ThreadGetName() const
{
return m_constStrThisThreadId;
}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Loads lldb-mi formatters
+// Type: Method.
+// Args: None.
+// Return: true - Functionality succeeded.
+// false - Functionality failed.
+// Throws: None.
+//--
+bool
+CMICmnLLDBDebugger::LoadMIFormatters(lldb::SBTypeCategory miCategory)
+{
+ if (!MI_add_summary(miCategory, "char", MI_char_summary_provider,
+ lldb::eTypeOptionHideValue | lldb::eTypeOptionSkipPointers))
+ return false;
+
+ if (!MI_add_summary(miCategory, "unsigned char", MI_char_summary_provider,
+ lldb::eTypeOptionHideValue | lldb::eTypeOptionSkipPointers))
+ return false;
+
+ if (!MI_add_summary(miCategory, "signed char", MI_char_summary_provider,
+ lldb::eTypeOptionHideValue | lldb::eTypeOptionSkipPointers))
+ return false;
+
+ return true;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Registers lldb-mi custom summary providers
+// Type: Method.
+// Args: None.
+// Return: true - Functionality succeeded.
+// false - Functionality failed.
+// Throws: None.
+//--
+bool
+CMICmnLLDBDebugger::RegisterMISummaryProviders()
+{
+ static const char* miCategoryName = "lldb-mi";
+ lldb::SBTypeCategory miCategory = m_lldbDebugger.CreateCategory(miCategoryName);
+ if (!miCategory.IsValid())
+ return false;
+
+ if (!LoadMIFormatters(miCategory))
+ {
+ m_lldbDebugger.DeleteCategory(miCategoryName);
+ return false;
+ }
+ miCategory.SetEnabled(true);
+ return true;
+}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugger.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugger.h
index de76112..83bc3c0 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugger.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebugger.h
@@ -32,9 +32,6 @@ class CMICmnLLDBDebuggerHandleEvents;
// to facilitate their work effort. The instance runs in its own worker
// thread.
// A singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 26/02/2014.
-// Changes: None.
//--
class CMICmnLLDBDebugger : public CMICmnBase, public CMIUtilThreadActiveObjBase, public MI::ISingleton<CMICmnLLDBDebugger>
{
@@ -42,16 +39,16 @@ class CMICmnLLDBDebugger : public CMICmnBase, public CMIUtilThreadActiveObjBase,
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
bool SetDriver(const CMIDriverBase &vClientDriver);
- CMIDriverBase &GetDriver(void) const;
- lldb::SBDebugger &GetTheDebugger(void);
- lldb::SBListener &GetTheListener(void);
- void WaitForHandleEvent(void);
- bool CheckIfNeedToRebroadcastStopEvent(void);
- void RebroadcastStopEvent(void);
+ CMIDriverBase &GetDriver() const;
+ lldb::SBDebugger &GetTheDebugger();
+ lldb::SBListener &GetTheListener();
+ void WaitForHandleEvent();
+ bool CheckIfNeedToRebroadcastStopEvent();
+ void RebroadcastStopEvent();
// MI Commands can use these functions to listen for events they require
bool RegisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask);
@@ -62,13 +59,13 @@ class CMICmnLLDBDebugger : public CMICmnBase, public CMIUtilThreadActiveObjBase,
// Overridden:
public:
// From CMIUtilThreadActiveObjBase
- const CMIUtilString &ThreadGetName(void) const override;
+ const CMIUtilString &ThreadGetName() const override;
// Overridden:
protected:
// From CMIUtilThreadActiveObjBase
bool ThreadRun(bool &vrIsAlive) override;
- bool ThreadFinish(void) override;
+ bool ThreadFinish() override;
// Typedefs:
private:
@@ -79,13 +76,13 @@ class CMICmnLLDBDebugger : public CMICmnBase, public CMIUtilThreadActiveObjBase,
// Methods:
private:
- /* ctor */ CMICmnLLDBDebugger(void);
+ /* ctor */ CMICmnLLDBDebugger();
/* ctor */ CMICmnLLDBDebugger(const CMICmnLLDBDebugger &);
void operator=(const CMICmnLLDBDebugger &);
- bool InitSBDebugger(void);
- bool InitSBListener(void);
- bool InitStdStreams(void);
+ bool InitSBDebugger();
+ bool InitSBListener();
+ bool InitStdStreams();
bool MonitorSBListenerEvents(bool &vrbYesExit);
bool BroadcasterGetMask(const CMIUtilString &vBroadcasterClass, MIuint &vEventMask) const;
@@ -96,11 +93,12 @@ class CMICmnLLDBDebugger : public CMICmnBase, public CMIUtilThreadActiveObjBase,
bool ClientSaveMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask);
bool ClientRemoveTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass);
bool ClientGetTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask);
-
+ bool LoadMIFormatters(lldb::SBTypeCategory miCategory);
+ bool RegisterMISummaryProviders();
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmnLLDBDebugger(void) override;
+ /* dtor */ ~CMICmnLLDBDebugger() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
index 29ff15c..848529f0 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
@@ -1,4 +1,4 @@
-//===-- MICmnLLDBDebuggerHandleEvents.cpp --------------------------------------------*- C++ -*-===//
+//===-- MICmnLLDBDebuggerHandleEvents.cpp -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -47,7 +47,7 @@
// Return: None.
// Throws: None.
//--
-CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents(void)
+CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents()
{
}
@@ -58,7 +58,7 @@ CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents(void)
// Return: None.
// Throws: None.
//--
-CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents(void)
+CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents()
{
Shutdown();
}
@@ -72,7 +72,7 @@ CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebuggerHandleEvents::Initialize(void)
+CMICmnLLDBDebuggerHandleEvents::Initialize()
{
m_clientUsageRefCnt++;
@@ -98,7 +98,7 @@ CMICmnLLDBDebuggerHandleEvents::Initialize(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebuggerHandleEvents::Shutdown(void)
+CMICmnLLDBDebuggerHandleEvents::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -351,7 +351,8 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn(const lldb::SBEvent &
const CMICmnMIValueResult miValueResultC("bkpt", miValueTuple);
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC);
- const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
+ bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
+ bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
}
@@ -440,6 +441,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(const lldb::SBEvent
const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
+ bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
else
{
@@ -462,6 +464,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(const lldb::SBEvent
const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
+ bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
return bOk;
@@ -543,10 +546,8 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended(const lldb::SBEvent
const CMIUtilString strSignal(CMIUtilString::Format("%lld", nId));
const CMICmnMIValueConst miValueConst2(strSignal);
const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
- bool bOk = miOutOfBandRecord.Add(miValueResult2);
- bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
-
- return bOk;
+ miOutOfBandRecord.Add(miValueResult2);
+ return MiOutOfBandRecordToStdout(miOutOfBandRecord);
}
//++ ------------------------------------------------------------------------------------
@@ -690,19 +691,19 @@ CMICmnLLDBDebuggerHandleEvents::MiHelpGetModuleInfo(const lldb::SBModule &vModul
std::unique_ptr<char[]> apPath(new char[PATH_MAX]);
vModule.GetFileSpec().GetPath(apPath.get(), PATH_MAX);
const CMIUtilString strTargetPath(apPath.get());
- const CMICmnMIValueConst miValueConst(strTargetPath);
+ const CMICmnMIValueConst miValueConst(strTargetPath.AddSlashes());
const CMICmnMIValueResult miValueResult("id", miValueConst);
- bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult);
+ vwrMiOutOfBandRecord.Add(miValueResult);
// Build "target-name" field
- const CMICmnMIValueConst miValueConst2(strTargetPath);
+ const CMICmnMIValueConst miValueConst2(strTargetPath.AddSlashes());
const CMICmnMIValueResult miValueResult2("target-name", miValueConst2);
- bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult2);
+ vwrMiOutOfBandRecord.Add(miValueResult2);
// Build "host-name" field
vModule.GetPlatformFileSpec().GetPath(apPath.get(), PATH_MAX);
const CMIUtilString strHostPath(apPath.get());
- const CMICmnMIValueConst miValueConst3(strHostPath);
+ const CMICmnMIValueConst miValueConst3(strHostPath.AddSlashes());
const CMICmnMIValueResult miValueResult3("host-name", miValueConst3);
- bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult3);
+ vwrMiOutOfBandRecord.Add(miValueResult3);
// Then build extra fields if needed:
if (vbWithExtraFields)
@@ -713,23 +714,30 @@ CMICmnLLDBDebuggerHandleEvents::MiHelpGetModuleInfo(const lldb::SBModule &vModul
const bool bSymbolsLoaded = !CMIUtilString::Compare(strHostPath, strSymbolsPath);
const CMICmnMIValueConst miValueConst4(CMIUtilString::Format("%d", bSymbolsLoaded));
const CMICmnMIValueResult miValueResult4("symbols-loaded", miValueConst4);
- bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult4);
+ vwrMiOutOfBandRecord.Add(miValueResult4);
// Build "symbols-path" field
if (bSymbolsLoaded)
{
- const CMICmnMIValueConst miValueConst5(strSymbolsPath);
+ const CMICmnMIValueConst miValueConst5(strSymbolsPath.AddSlashes());
const CMICmnMIValueResult miValueResult5("symbols-path", miValueConst5);
- bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult5);
+ vwrMiOutOfBandRecord.Add(miValueResult5);
}
// Build "loaded_addr" field
- const lldb::SBAddress sbAddress(vModule.GetObjectFileHeaderAddress());
+ lldb::SBAddress sbAddress(vModule.GetObjectFileHeaderAddress());
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
const lldb::addr_t nLoadAddress(sbAddress.GetLoadAddress(rSessionInfo.GetTarget()));
const CMIUtilString strLoadedAddr(nLoadAddress != LLDB_INVALID_ADDRESS ?
CMIUtilString::Format("0x%016" PRIx64, nLoadAddress) : "-");
const CMICmnMIValueConst miValueConst6(strLoadedAddr);
const CMICmnMIValueResult miValueResult6("loaded_addr", miValueConst6);
- bOk = bOk && vwrMiOutOfBandRecord.Add(miValueResult6);
+ vwrMiOutOfBandRecord.Add(miValueResult6);
+
+ // Build "size" field
+ lldb::SBSection sbSection = sbAddress.GetSection();
+ const CMIUtilString strSize(CMIUtilString::Format("%" PRIu64, sbSection.GetByteSize()));
+ const CMICmnMIValueConst miValueConst7(strSize);
+ const CMICmnMIValueResult miValueResult7("size", miValueConst7);
+ vwrMiOutOfBandRecord.Add(miValueResult7);
}
return bOk;
@@ -1018,21 +1026,21 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(const lldb::SBEvent
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConst2("SIGINT");
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
- bOk = miOutOfBandRecord.Add(miValueResult2);
+ miOutOfBandRecord.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3("Interrupt");
const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
+ miOutOfBandRecord.Add(miValueResult3);
CMICmnMIValueTuple miValueTuple;
bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
+ miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(CMIUtilString::Format("%" PRIu32, sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
+ miOutOfBandRecord.Add(miValueResult5);
const CMICmnMIValueConst miValueConst6("all");
const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult6);
+ miOutOfBandRecord.Add(miValueResult6);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
@@ -1044,21 +1052,21 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(const lldb::SBEvent
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConst2("SIGSTOP");
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
- bOk = miOutOfBandRecord.Add(miValueResult2);
+ miOutOfBandRecord.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3("Stop");
const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
+ miOutOfBandRecord.Add(miValueResult3);
CMICmnMIValueTuple miValueTuple;
bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
+ miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(CMIUtilString::Format("%" PRIu32, sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
+ miOutOfBandRecord.Add(miValueResult5);
const CMICmnMIValueConst miValueConst6("all");
const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult6);
+ miOutOfBandRecord.Add(miValueResult6);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
@@ -1070,18 +1078,18 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(const lldb::SBEvent
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConst2("SIGSEGV");
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
- bOk = miOutOfBandRecord.Add(miValueResult2);
+ miOutOfBandRecord.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3("Segmentation fault");
const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
+ miOutOfBandRecord.Add(miValueResult3);
CMICmnMIValueTuple miValueTuple;
bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
+ miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
+ miOutOfBandRecord.Add(miValueResult5);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
// Note no "(gdb)" output here
}
@@ -1119,22 +1127,22 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(const lldb::SBEvent
{
const CMICmnMIValueConst miValueConst2(pSignal);
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
- bOk = miOutOfBandRecord.Add(miValueResult2);
+ miOutOfBandRecord.Add(miValueResult2);
}
else
{
const CMIUtilString strSignal(CMIUtilString::Format("%" PRIu64, nStopReason));
const CMICmnMIValueConst miValueConst2(strSignal);
const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
- bOk = miOutOfBandRecord.Add(miValueResult2);
+ miOutOfBandRecord.Add(miValueResult2);
}
const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst3(strThreadId);
const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
+ miOutOfBandRecord.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4("all");
const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
+ miOutOfBandRecord.Add(miValueResult4);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
@@ -1150,7 +1158,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(const lldb::SBEvent
// Throws: None.
//--
bool
-CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopException(void)
+CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopException()
{
const lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBThread sbThread = sbProcess.GetSelectedThread();
@@ -1165,15 +1173,15 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopException(void)
const CMIUtilString strReason(apStopDescription.get());
const CMICmnMIValueConst miValueConst2(strReason);
const CMICmnMIValueResult miValueResult2("exception", miValueConst2);
- bool bOk = miOutOfBandRecord.Add(miValueResult2);
+ miOutOfBandRecord.Add(miValueResult2);
const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbThread.GetIndexID()));
const CMICmnMIValueConst miValueConst3(strThreadId);
const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
+ miOutOfBandRecord.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4("all");
const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
- bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
+ miOutOfBandRecord.Add(miValueResult4);
+ bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
@@ -1235,7 +1243,7 @@ CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &
// Throws: None.
//--
bool
-CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint(void)
+CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint()
{
// CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging())
@@ -1278,21 +1286,21 @@ CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, c
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConst2("del");
const CMICmnMIValueResult miValueResult2("disp", miValueConst2);
- bOk = miOutOfBandRecord.Add(miValueResult2);
+ miOutOfBandRecord.Add(miValueResult2);
const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
const CMICmnMIValueConst miValueConst3(strBkp);
CMICmnMIValueResult miValueResult3("bkptno", miValueConst3);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
+ miOutOfBandRecord.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4("{}");
const CMICmnMIValueResult miValueResult4("frame", miValueConst4);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
+ miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(CMIUtilString::Format("%d", vBrkPt.GetThreadIndex()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
+ miOutOfBandRecord.Add(miValueResult5);
const CMICmnMIValueConst miValueConst6("all");
const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult6);
+ miOutOfBandRecord.Add(miValueResult6);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
@@ -1307,11 +1315,11 @@ CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, c
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConstA("del");
const CMICmnMIValueResult miValueResultA("disp", miValueConstA);
- bOk = miOutOfBandRecord.Add(miValueResultA);
+ miOutOfBandRecord.Add(miValueResultA);
const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
const CMICmnMIValueConst miValueConstB(strBkp);
CMICmnMIValueResult miValueResultB("bkptno", miValueConstB);
- bOk = bOk && miOutOfBandRecord.Add(miValueResultB);
+ miOutOfBandRecord.Add(miValueResultB);
// frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
if (bOk)
@@ -1319,7 +1327,7 @@ CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, c
CMICmnMIValueTuple miValueTuple;
bOk = bOk && rSessionInfo.MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, miValueTuple);
const CMICmnMIValueResult miValueResult8("frame", miValueTuple);
- bOk = bOk && miOutOfBandRecord.Add(miValueResult8);
+ miOutOfBandRecord.Add(miValueResult8);
}
// Add to MI thread-id=\"%d\",stopped-threads=\"all\"
@@ -1328,13 +1336,13 @@ CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, c
const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
const CMICmnMIValueConst miValueConst8(strThreadId);
const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
- bOk = miOutOfBandRecord.Add(miValueResult8);
+ miOutOfBandRecord.Add(miValueResult8);
}
if (bOk)
{
const CMICmnMIValueConst miValueConst9("all");
const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
- bOk = miOutOfBandRecord.Add(miValueResult9);
+ miOutOfBandRecord.Add(miValueResult9);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
@@ -1351,7 +1359,7 @@ CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, c
// Throws: None.
//--
bool
-CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void)
+CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace()
{
bool bOk = true;
lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
@@ -1365,7 +1373,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void)
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConst2("all");
const CMICmnMIValueResult miValueResult2("stopped-threads", miValueConst2);
- bOk = miOutOfBandRecord.Add(miValueResult2);
+ miOutOfBandRecord.Add(miValueResult2);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
@@ -1385,24 +1393,19 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void)
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
- bOk = miOutOfBandRecord.Add(miValueResult2);
+ miOutOfBandRecord.Add(miValueResult2);
// Add to MI thread-id=\"%d\",stopped-threads=\"all\"
- if (bOk)
- {
- const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
- const CMICmnMIValueConst miValueConst8(strThreadId);
- const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
- bOk = miOutOfBandRecord.Add(miValueResult8);
- }
- if (bOk)
- {
- const CMICmnMIValueConst miValueConst9("all");
- const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
- bOk = miOutOfBandRecord.Add(miValueResult9);
- bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
- bOk = bOk && CMICmnStreamStdout::WritePrompt();
- }
+ const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
+ const CMICmnMIValueConst miValueConst8(strThreadId);
+ const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
+ miOutOfBandRecord.Add(miValueResult8);
+
+ const CMICmnMIValueConst miValueConst9("all");
+ const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
+ miOutOfBandRecord.Add(miValueResult9);
+ bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
+ bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
}
@@ -1416,7 +1419,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread(void)
+CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread()
{
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess();
if (!process.IsValid())
@@ -1487,7 +1490,7 @@ CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning(void)
+CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning()
{
CMICmnMIValueConst miValueConst("all");
CMICmnMIValueResult miValueResult("thread-id", miValueConst);
@@ -1510,7 +1513,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited(void)
+CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited()
{
const CMIUtilString strId(CMIUtilString::Format("%ld", 1));
CMICmnMIValueConst miValueConst(strId);
@@ -1518,8 +1521,8 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited(void)
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
CMICmnMIValueConst miValueConst2("i1");
CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
- bool bOk = miOutOfBandRecord.Add(miValueResult2);
- bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
+ miOutOfBandRecord.Add(miValueResult2);
+ bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
if (bOk)
{
CMICmnMIValueConst miValueConst3("i1");
@@ -1527,7 +1530,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited(void)
CMICmnMIOutOfBandRecord miOutOfBandRecord2(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3);
CMICmnMIValueConst miValueConst2("0");
CMICmnMIValueResult miValueResult2("exit-code", miValueConst2);
- bOk = miOutOfBandRecord2.Add(miValueResult2);
+ miOutOfBandRecord2.Add(miValueResult2);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord2);
}
if (bOk)
@@ -1553,7 +1556,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void)
+CMICmnLLDBDebuggerHandleEvents::GetProcessStdout()
{
CMIUtilString text;
std::unique_ptr<char[]> apStdoutBuffer(new char[1024]);
@@ -1569,7 +1572,7 @@ CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void)
if (nNewLine == std::string::npos)
break;
- const CMIUtilString line(text.substr(0, nNewLine + 1).c_str());
+ const CMIUtilString line(text.substr(0, nNewLine + 1));
text.erase(0, nNewLine + 1);
const bool bEscapeQuotes(true);
CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
@@ -1606,7 +1609,7 @@ CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebuggerHandleEvents::GetProcessStderr(void)
+CMICmnLLDBDebuggerHandleEvents::GetProcessStderr()
{
CMIUtilString text;
std::unique_ptr<char[]> apStderrBuffer(new char[1024]);
@@ -1622,7 +1625,7 @@ CMICmnLLDBDebuggerHandleEvents::GetProcessStderr(void)
if (nNewLine == std::string::npos)
break;
- const CMIUtilString line(text.substr(0, nNewLine + 1).c_str());
+ const CMIUtilString line(text.substr(0, nNewLine + 1));
const bool bEscapeQuotes(true);
CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
@@ -1656,7 +1659,7 @@ CMICmnLLDBDebuggerHandleEvents::GetProcessStderr(void)
// Throws: None.
//--
bool
-CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges(void)
+CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges()
{
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
@@ -1686,8 +1689,8 @@ CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges(void)
CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult);
const CMICmnMIValueConst miValueConst2("i1");
const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
- bool bOk = miOutOfBand.Add(miValueResult2);
- bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand);
+ miOutOfBand.Add(miValueResult2);
+ bool bOk = MiOutOfBandRecordToStdout(miOutOfBand);
if (!bOk)
return MIstatus::failure;
}
@@ -1726,8 +1729,8 @@ CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges(void)
CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
const CMICmnMIValueConst miValueConst2("i1");
const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
- bool bOk = miOutOfBand.Add(miValueResult2);
- bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand);
+ miOutOfBand.Add(miValueResult2);
+ bool bOk = MiOutOfBandRecordToStdout(miOutOfBand);
if (!bOk)
return MIstatus::failure;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h
index 1abb520..f5075d1 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h
@@ -26,9 +26,6 @@ class CMICmnMIOutOfBandRecord;
// MI Out-of-band records from the information inside the event object.
// These records are then pushed to stdout.
// A singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 02/03/2014.
-// Changes: None.
//--
class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton<CMICmnLLDBDebuggerHandleEvents>
{
@@ -36,20 +33,20 @@ class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton<
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
//
bool HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent);
// Methods:
private:
- /* ctor */ CMICmnLLDBDebuggerHandleEvents(void);
+ /* ctor */ CMICmnLLDBDebuggerHandleEvents();
/* ctor */ CMICmnLLDBDebuggerHandleEvents(const CMICmnLLDBDebuggerHandleEvents &);
void operator=(const CMICmnLLDBDebuggerHandleEvents &);
//
- bool ChkForStateChanges(void);
- bool GetProcessStdout(void);
- bool GetProcessStderr(void);
+ bool ChkForStateChanges();
+ bool GetProcessStdout();
+ bool GetProcessStderr();
bool HandleEventSBBreakPoint(const lldb::SBEvent &vEvent);
bool HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent);
bool HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent);
@@ -61,13 +58,13 @@ class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton<
bool HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent);
bool HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent);
bool HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent);
- bool HandleProcessEventStateRunning(void);
- bool HandleProcessEventStateExited(void);
+ bool HandleProcessEventStateRunning();
+ bool HandleProcessEventStateExited();
bool HandleProcessEventStateStopped(const lldb::SBEvent &vrEvent, bool &vwrbShouldBrk);
- bool HandleProcessEventStopReasonTrace(void);
- bool HandleProcessEventStopReasonBreakpoint(void);
+ bool HandleProcessEventStopReasonTrace();
+ bool HandleProcessEventStopReasonBreakpoint();
bool HandleProcessEventStopSignal(const lldb::SBEvent &vrEvent);
- bool HandleProcessEventStopException(void);
+ bool HandleProcessEventStopException();
bool HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent);
bool HandleTargetEventBroadcastBitModulesLoaded(const lldb::SBEvent &vEvent);
bool HandleTargetEventBroadcastBitModulesUnloaded(const lldb::SBEvent &vEvent);
@@ -79,12 +76,12 @@ class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton<
bool MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt);
bool TextToStdout(const CMIUtilString &vrTxt);
bool TextToStderr(const CMIUtilString &vrTxt);
- bool UpdateSelectedThread(void);
+ bool UpdateSelectedThread();
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmnLLDBDebuggerHandleEvents(void) override;
+ /* dtor */ ~CMICmnLLDBDebuggerHandleEvents() override;
void InitializeSignals();
bool m_bSignalsInitialized;
MIuint64 m_SIGINT;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.h
index c9cd3a9..2ae3acf 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.h
@@ -21,9 +21,6 @@ class CMIUtilString;
//++ ============================================================================
// Details: MI proxy wrapper class to lldb::SBValue. The class provides functionality
// to assist in the use of SBValue's particular function usage.
-// Gotchas: None.
-// Authors: Illya Rudkin 03/04/2014.
-// Changes: None.
//--
class CMICmnLLDBProxySBValue
{
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp
index 45f030b..d3d85d3 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp
@@ -9,6 +9,7 @@
// Third party headers:
#include <cinttypes>
+#include "lldb/API/SBTypeSummary.h"
// In-house headers:
#include "MICmnLLDBUtilSBValue.h"
@@ -44,7 +45,7 @@ CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, const
// Return: None.
// Throws: None.
//--
-CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue(void)
+CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue()
{
}
@@ -57,10 +58,10 @@ CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue(void)
// Throws: None.
//--
CMIUtilString
-CMICmnLLDBUtilSBValue::GetName(void) const
+CMICmnLLDBUtilSBValue::GetName() const
{
const char *pName = m_bValidSBValue ? m_rValue.GetName() : nullptr;
- const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn);
+ const CMIUtilString text((pName != nullptr) ? pName : CMIUtilString());
return text;
}
@@ -122,31 +123,13 @@ CMICmnLLDBUtilSBValue::GetSimpleValue(const bool vbHandleArrayType, CMIUtilStrin
const MIuint nChildren = m_rValue.GetNumChildren();
if (nChildren == 0)
{
- if (m_bHandleCharType && IsCharType())
- {
- vwrValue = GetSimpleValueChar();
- return MIstatus::success;
- }
- else
- {
- const char *pValue = m_rValue.GetValue();
- vwrValue = pValue != nullptr ? pValue : m_pUnkwn;
- return MIstatus::success;
- }
+ vwrValue = GetValueSummary(!m_bHandleCharType && IsCharType(), m_pUnkwn);
+ return MIstatus::success;
}
else if (IsPointerType())
{
- if (m_bHandleCharType && IsFirstChildCharType())
- {
- vwrValue = GetSimpleValueCStringPointer();
- return MIstatus::success;
- }
- else
- {
- const char *pValue = m_rValue.GetValue();
- vwrValue = pValue != nullptr ? pValue : m_pUnkwn;
- return MIstatus::success;
- }
+ vwrValue = GetValueSummary(!m_bHandleCharType && IsPointeeCharType(), m_pUnkwn);
+ return MIstatus::success;
}
else if (IsArrayType())
{
@@ -156,7 +139,7 @@ CMICmnLLDBUtilSBValue::GetSimpleValue(const bool vbHandleArrayType, CMIUtilStrin
bPrintCharArrayAsString) && bPrintCharArrayAsString;
if (bPrintCharArrayAsString && m_bHandleCharType && IsFirstChildCharType())
{
- vwrValue = GetSimpleValueCStringArray();
+ vwrValue = GetValueSummary(false);
return MIstatus::success;
}
else if (vbHandleArrayType)
@@ -165,140 +148,17 @@ CMICmnLLDBUtilSBValue::GetSimpleValue(const bool vbHandleArrayType, CMIUtilStrin
return MIstatus::success;
}
}
-
- // Composite variable type i.e. struct
- return MIstatus::failure;
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieve from the LLDB SB Value object the char value of the variable.
-// Type: Method.
-// Args: None.
-// Return: CMIUtilString - The char value of the variable.
-// Throws: None.
-//--
-CMIUtilString
-CMICmnLLDBUtilSBValue::GetSimpleValueChar(void) const
-{
- const uint64_t value = m_rValue.GetValueAsUnsigned();
- if (value == 0)
- {
- const uint64_t nFailValue = 1;
- if (nFailValue == m_rValue.GetValueAsUnsigned(nFailValue))
- return m_pUnkwn;
- }
-
- const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
- switch (eType)
- {
- default:
- assert(0 && "value must be a char type");
- case lldb::eBasicTypeChar:
- case lldb::eBasicTypeSignedChar:
- case lldb::eBasicTypeUnsignedChar:
- {
- const CMIUtilString prefix(CMIUtilString::ConvertToPrintableASCII((char)value));
- return CMIUtilString::Format("%" PRIu8 " '%s'", (uint8_t)value, prefix.c_str());
- }
- case lldb::eBasicTypeChar16:
- {
- const CMIUtilString prefix(CMIUtilString::ConvertToPrintableASCII((char16_t)value));
- return CMIUtilString::Format("U+%04" PRIx16 " u'%s'", (uint16_t)value, prefix.c_str());
- }
- case lldb::eBasicTypeChar32:
- {
- const CMIUtilString prefix(CMIUtilString::ConvertToPrintableASCII((char32_t)value));
- return CMIUtilString::Format("U+%08" PRIx32 " U'%s'", (uint32_t)value, prefix.c_str());
- }
- }
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieve from the LLDB SB Value object of type char* the c-string value.
-// Type: Method.
-// Args: None.
-// Return: CMIUtilString - The c-string value of the variable.
-// Throws: None.
-//--
-CMIUtilString
-CMICmnLLDBUtilSBValue::GetSimpleValueCStringPointer(void) const
-{
- const char *value = m_rValue.GetValue();
- if (value == nullptr)
- return m_pUnkwn;
-
- lldb::SBValue child = m_rValue.GetChildAtIndex(0);
- const lldb::BasicType eType = child.GetType().GetBasicType();
- switch (eType)
+ else
{
- default:
- assert(0 && "child must be a char type");
- case lldb::eBasicTypeChar:
- case lldb::eBasicTypeSignedChar:
- case lldb::eBasicTypeUnsignedChar:
- {
- // FIXME Add slashes before double quotes
- const CMIUtilString prefix(ReadCStringFromHostMemory<char>(child).AddSlashes());
- // Note code that has const in will not show the text suffix to the string pointer
- // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this
- // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this
- return CMIUtilString::Format("%s \"%s\"", value, prefix.c_str());
- }
- case lldb::eBasicTypeChar16:
- {
- // FIXME Add slashes before double quotes
- const CMIUtilString prefix(ReadCStringFromHostMemory<char16_t>(child).AddSlashes());
- return CMIUtilString::Format("%s u\"%s\"", value, prefix.c_str());
- }
- case lldb::eBasicTypeChar32:
- {
- // FIXME Add slashes before double quotes
- const CMIUtilString prefix(ReadCStringFromHostMemory<char32_t>(child).AddSlashes());
- return CMIUtilString::Format("%s U\"%s\"", value, prefix.c_str());
- }
+ // Treat composite value which has registered summary
+ // (for example with AddCXXSummary) as simple value
+ vwrValue = GetValueSummary(false);
+ if (!vwrValue.empty())
+ return MIstatus::success;
}
-}
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieve from the LLDB SB Value object of type char[] the c-string value.
-// Type: Method.
-// Args: None.
-// Return: CMIUtilString - The c-string value of the variable.
-// Throws: None.
-//--
-CMIUtilString
-CMICmnLLDBUtilSBValue::GetSimpleValueCStringArray(void) const
-{
- const MIuint nChildren = m_rValue.GetNumChildren();
- lldb::SBValue child = m_rValue.GetChildAtIndex(0);
- const lldb::BasicType eType = child.GetType().GetBasicType();
- switch (eType)
- {
- default:
- assert(0 && "value must be a char[] type");
- case lldb::eBasicTypeChar:
- case lldb::eBasicTypeSignedChar:
- case lldb::eBasicTypeUnsignedChar:
- {
- // FIXME Add slashes before double quotes
- const CMIUtilString prefix(ReadCStringFromHostMemory<char>(m_rValue, nChildren).AddSlashes());
- // TODO: to match char* it should be the following
- // return CMIUtilString::Format("[%u] \"%s\"", nChildren, prefix.c_str());
- return CMIUtilString::Format("\"%s\"", prefix.c_str());
- }
- case lldb::eBasicTypeChar16:
- {
- // FIXME Add slashes before double quotes
- const CMIUtilString prefix(ReadCStringFromHostMemory<char16_t>(m_rValue, nChildren).AddSlashes());
- return CMIUtilString::Format("u\"%s\"", prefix.c_str());
- }
- case lldb::eBasicTypeChar32:
- {
- // FIXME Add slashes before double quotes
- const CMIUtilString prefix(ReadCStringFromHostMemory<char32_t>(m_rValue, nChildren).AddSlashes());
- return CMIUtilString::Format("U\"%s\"", prefix.c_str());
- }
- }
+ // Composite variable type i.e. struct
+ return MIstatus::failure;
}
bool
@@ -341,34 +201,61 @@ CMICmnLLDBUtilSBValue::GetCompositeValue(const bool vbPrintFieldNames, CMICmnMIV
{
const bool bUseSpacing = true;
const CMICmnMIValueResult miValueResult(utilMember.GetName(), miValueConst, bUseSpacing);
- const bool bOk = vwrMiValueTuple.Add(miValueResult, bUseSpacing);
- if (!bOk)
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueResult, bUseSpacing);
}
else
{
const bool bUseSpacing = false;
- const bool bOk = vwrMiValueTuple.Add(miValueConst, bUseSpacing);
- if (!bOk)
- return MIstatus::failure;
+ vwrMiValueTuple.Add(miValueConst, bUseSpacing);
}
}
return MIstatus::success;
}
+// Returns value or value + summary, depending on valueOnly parameter value.
+// If result is an empty string returns failVal.
+CMIUtilString
+CMICmnLLDBUtilSBValue::GetValueSummary(bool valueOnly, const CMIUtilString& failVal) const
+{
+ if (!m_rValue.IsValid())
+ return failVal;
+
+ CMIUtilString value, valSummary;
+ const char* c_value = m_rValue.GetValue();
+ if (valueOnly)
+ return c_value == nullptr ? failVal : c_value;
+
+ const char* c_summary = m_rValue.GetSummary();
+ if (c_value)
+ value = c_value;
+ else if (c_summary == nullptr)
+ return failVal;
+
+ if (c_summary && c_summary[0])
+ {
+ valSummary = c_summary;
+ lldb::SBTypeSummary summary = m_rValue.GetTypeSummary();
+ if (summary.IsValid() && summary.DoesPrintValue(m_rValue) && !value.empty())
+ {
+ valSummary.insert(0, value + " ");
+ }
+ return valSummary;
+ }
+ // no summary - return just value
+ return value;
+}
+
//++ ------------------------------------------------------------------------------------
-// Details: Retrieve the flag stating whether this value object is a char type or some
-// other type. Char type can be signed or unsigned.
-// Type: Method.
-// Args: None.
+// Details: Check that basic type is a char type. Char type can be signed or unsigned.
+// Type: Static.
+// Args: eType - type to check
// Return: bool - True = Yes is a char type, false = some other type.
// Throws: None.
//--
bool
-CMICmnLLDBUtilSBValue::IsCharType(void) const
+CMICmnLLDBUtilSBValue::IsCharBasicType(lldb::BasicType eType)
{
- const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
switch (eType)
{
case lldb::eBasicTypeChar:
@@ -383,6 +270,21 @@ CMICmnLLDBUtilSBValue::IsCharType(void) const
}
//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the flag stating whether this value object is a char type or some
+// other type. Char type can be signed or unsigned.
+// Type: Method.
+// Args: None.
+// Return: bool - True = Yes is a char type, false = some other type.
+// Throws: None.
+//--
+bool
+CMICmnLLDBUtilSBValue::IsCharType() const
+{
+ const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
+ return IsCharBasicType(eType);
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: Retrieve the flag stating whether first child value object of *this object is
// a char type or some other type. Returns false if there are not children. Char
// type can be signed or unsigned.
@@ -392,7 +294,7 @@ CMICmnLLDBUtilSBValue::IsCharType(void) const
// Throws: None.
//--
bool
-CMICmnLLDBUtilSBValue::IsFirstChildCharType(void) const
+CMICmnLLDBUtilSBValue::IsFirstChildCharType() const
{
const MIuint nChildren = m_rValue.GetNumChildren();
@@ -406,6 +308,28 @@ CMICmnLLDBUtilSBValue::IsFirstChildCharType(void) const
}
//++ ------------------------------------------------------------------------------------
+// Details: Retrieve the flag stating whether pointee object of *this object is
+// a char type or some other type. Returns false if there are not children. Char
+// type can be signed or unsigned.
+// Type: Method.
+// Args: None.
+// Return: bool - True = Yes is a char type, false = some other type.
+// Throws: None.
+//--
+bool
+CMICmnLLDBUtilSBValue::IsPointeeCharType() const
+{
+ const MIuint nChildren = m_rValue.GetNumChildren();
+
+ // Is it a basic type
+ if (nChildren == 0)
+ return false;
+
+ const lldb::BasicType eType = m_rValue.GetType().GetPointeeType().GetBasicType();
+ return IsCharBasicType(eType);
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: Retrieve the flag stating whether this value object is a integer type or some
// other type. Char type can be signed or unsigned and short or long/very long.
// Type: Method.
@@ -414,7 +338,7 @@ CMICmnLLDBUtilSBValue::IsFirstChildCharType(void) const
// Throws: None.
//--
bool
-CMICmnLLDBUtilSBValue::IsIntegerType(void) const
+CMICmnLLDBUtilSBValue::IsIntegerType() const
{
const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
return ((eType == lldb::eBasicTypeShort) || (eType == lldb::eBasicTypeUnsignedShort) ||
@@ -433,7 +357,7 @@ CMICmnLLDBUtilSBValue::IsIntegerType(void) const
// Throws: None.
//--
bool
-CMICmnLLDBUtilSBValue::IsPointerType(void) const
+CMICmnLLDBUtilSBValue::IsPointerType() const
{
return m_rValue.GetType().IsPointerType();
}
@@ -447,7 +371,7 @@ CMICmnLLDBUtilSBValue::IsPointerType(void) const
// Throws: None.
//--
bool
-CMICmnLLDBUtilSBValue::IsArrayType(void) const
+CMICmnLLDBUtilSBValue::IsArrayType() const
{
return m_rValue.GetType().IsArrayType();
}
@@ -476,11 +400,11 @@ CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory(lldb::SBValue &vrValue, const M
return m_pUnkwn;
else if (ch == 0)
break;
- result.append(CMIUtilString::ConvertToPrintableASCII(ch));
+ result.append(CMIUtilString::ConvertToPrintableASCII(ch, true /* bEscapeQuotes */));
addr += sizeof(ch);
}
- return result.c_str();
+ return result;
}
//++ ------------------------------------------------------------------------------------
@@ -491,7 +415,7 @@ CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory(lldb::SBValue &vrValue, const M
// Throws: None.
//--
bool
-CMICmnLLDBUtilSBValue::IsNameUnknown(void) const
+CMICmnLLDBUtilSBValue::IsNameUnknown() const
{
const CMIUtilString name(GetName());
return (name == m_pUnkwn);
@@ -505,7 +429,7 @@ CMICmnLLDBUtilSBValue::IsNameUnknown(void) const
// Throws: None.
//--
bool
-CMICmnLLDBUtilSBValue::IsValueUnknown(void) const
+CMICmnLLDBUtilSBValue::IsValueUnknown() const
{
const CMIUtilString value(GetValue());
return (value == m_pUnkwn);
@@ -519,7 +443,7 @@ CMICmnLLDBUtilSBValue::IsValueUnknown(void) const
// Throws: None.
//--
CMIUtilString
-CMICmnLLDBUtilSBValue::GetTypeName(void) const
+CMICmnLLDBUtilSBValue::GetTypeName() const
{
const char *pName = m_bValidSBValue ? m_rValue.GetTypeName() : nullptr;
const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn);
@@ -535,7 +459,7 @@ CMICmnLLDBUtilSBValue::GetTypeName(void) const
// Throws: None.
//--
CMIUtilString
-CMICmnLLDBUtilSBValue::GetTypeNameDisplay(void) const
+CMICmnLLDBUtilSBValue::GetTypeNameDisplay() const
{
const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr;
const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn);
@@ -551,7 +475,7 @@ CMICmnLLDBUtilSBValue::GetTypeNameDisplay(void) const
// Throws: None.
//--
bool
-CMICmnLLDBUtilSBValue::IsValid(void) const
+CMICmnLLDBUtilSBValue::IsValid() const
{
return m_bValidSBValue;
}
@@ -565,7 +489,7 @@ CMICmnLLDBUtilSBValue::IsValid(void) const
// Throws: None.
//--
bool
-CMICmnLLDBUtilSBValue::HasName(void) const
+CMICmnLLDBUtilSBValue::HasName() const
{
bool bHasAName = false;
@@ -586,7 +510,7 @@ CMICmnLLDBUtilSBValue::HasName(void) const
// Throws: None.
//--
bool
-CMICmnLLDBUtilSBValue::IsLLDBVariable(void) const
+CMICmnLLDBUtilSBValue::IsLLDBVariable() const
{
return (GetName().at(0) == '$');
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.h
index 8bb6783..36264da 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.h
@@ -22,9 +22,6 @@ class CMIUtilString;
//++ ============================================================================
// Details: Utility helper class to lldb::SBValue. Using a lldb::SBValue extract
// value object information to help form verbose debug information.
-// Gotchas: None.
-// Authors: Illya Rudkin 08/07/2014.
-// Changes: None.
//--
class CMICmnLLDBUtilSBValue
{
@@ -32,31 +29,34 @@ class CMICmnLLDBUtilSBValue
public:
/* ctor */ CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, const bool vbHandleCharType = false,
const bool vbHandleArrayType = true);
- /* dtor */ ~CMICmnLLDBUtilSBValue(void);
+ /* dtor */ ~CMICmnLLDBUtilSBValue();
//
- CMIUtilString GetName(void) const;
+ CMIUtilString GetName() const;
CMIUtilString GetValue(const bool vbExpandAggregates = false) const;
- CMIUtilString GetTypeName(void) const;
- CMIUtilString GetTypeNameDisplay(void) const;
- bool IsCharType(void) const;
- bool IsFirstChildCharType(void) const;
- bool IsIntegerType(void) const;
- bool IsPointerType(void) const;
- bool IsArrayType(void) const;
- bool IsLLDBVariable(void) const;
- bool IsNameUnknown(void) const;
- bool IsValueUnknown(void) const;
- bool IsValid(void) const;
- bool HasName(void) const;
+ CMIUtilString GetTypeName() const;
+ CMIUtilString GetTypeNameDisplay() const;
+ bool IsCharType() const;
+ bool IsFirstChildCharType() const;
+ bool IsPointeeCharType() const;
+ bool IsIntegerType() const;
+ bool IsPointerType() const;
+ bool IsArrayType() const;
+ bool IsLLDBVariable() const;
+ bool IsNameUnknown() const;
+ bool IsValueUnknown() const;
+ bool IsValid() const;
+ bool HasName() const;
// Methods:
private:
template <typename charT> CMIUtilString ReadCStringFromHostMemory(lldb::SBValue &vrValue, const MIuint vnMaxLen = UINT32_MAX) const;
bool GetSimpleValue(const bool vbHandleArrayType, CMIUtilString &vrValue) const;
- CMIUtilString GetSimpleValueChar(void) const;
- CMIUtilString GetSimpleValueCStringPointer(void) const;
- CMIUtilString GetSimpleValueCStringArray(void) const;
bool GetCompositeValue(const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple, const MIuint vnDepth = 1) const;
+ CMIUtilString GetValueSummary(bool valueOnly, const CMIUtilString& failVal = CMIUtilString()) const;
+
+ // Statics:
+ private:
+ static bool IsCharBasicType(lldb::BasicType eType);
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLog.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLog.cpp
index a88ba6b..e85ddba 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLog.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLog.cpp
@@ -21,7 +21,7 @@
// Return: None.
// Throws: None.
//--
-CMICmnLog::CMICmnLog(void)
+CMICmnLog::CMICmnLog()
: m_bEnabled(false)
, m_bInitializingATM(false)
{
@@ -35,7 +35,7 @@ CMICmnLog::CMICmnLog(void)
// Return: None.
// Throws: None.
//--
-CMICmnLog::~CMICmnLog(void)
+CMICmnLog::~CMICmnLog()
{
Shutdown();
}
@@ -49,7 +49,7 @@ CMICmnLog::~CMICmnLog(void)
// Throws: None.
//--
bool
-CMICmnLog::Initialize(void)
+CMICmnLog::Initialize()
{
m_clientUsageRefCnt++;
@@ -102,7 +102,7 @@ CMICmnLog::Initialize(void)
// Throws: None.
//--
bool
-CMICmnLog::Shutdown(void)
+CMICmnLog::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -144,7 +144,7 @@ CMICmnLog::SetEnabled(const bool vbYes)
// Throws: None.
//--
bool
-CMICmnLog::GetEnabled(void) const
+CMICmnLog::GetEnabled() const
{
return m_bEnabled;
}
@@ -158,7 +158,7 @@ CMICmnLog::GetEnabled(void) const
// Throws: None.
//--
bool
-CMICmnLog::UnregisterMediumAll(void)
+CMICmnLog::UnregisterMediumAll()
{
MapMediumToName_t::const_iterator it = m_mapMediumToName.begin();
for (; it != m_mapMediumToName.end(); it++)
@@ -325,7 +325,7 @@ CMICmnLog::WriteLog(const CMIUtilString &vData)
// Throws: None.
//--
const CMIUtilString &
-CMICmnLog::GetErrorDescription(void) const
+CMICmnLog::GetErrorDescription() const
{
return m_strMILastErrorDescription;
}
@@ -351,7 +351,7 @@ CMICmnLog::SetErrorDescription(const CMIUtilString &vrTxt) const
// Throws: None.
//--
void
-CMICmnLog::ClrErrorDescription(void) const
+CMICmnLog::ClrErrorDescription() const
{
m_strMILastErrorDescription = CMIUtilString("");
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLog.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLog.h
index f0ae534..a346cf4 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLog.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLog.h
@@ -26,9 +26,6 @@
// *this logs initialization so it will always have a file log for the
// application.
// Singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 01/02/2012.
-// Changes: None.
//--
class CMICmnLog : public MI::ISingleton<CMICmnLog>
{
@@ -59,17 +56,17 @@ class CMICmnLog : public MI::ISingleton<CMICmnLog>
class IMedium
{
public:
- virtual bool Initialize(void) = 0;
- virtual const CMIUtilString &GetName(void) const = 0;
+ virtual bool Initialize() = 0;
+ virtual const CMIUtilString &GetName() const = 0;
virtual bool Write(const CMIUtilString &vData, const ELogVerbosity veType) = 0;
- virtual const CMIUtilString &GetError(void) const = 0;
- virtual bool Shutdown(void) = 0;
+ virtual const CMIUtilString &GetError() const = 0;
+ virtual bool Shutdown() = 0;
// Not part of the interface, ignore
// AD: This virtual destructor seems to hit a bug in the stdlib
// where vector delete is incorrectly called. Workaround is
// to comment this out while I investigate.
- /* dtor */ virtual ~IMedium(void) {}
+ /* dtor */ virtual ~IMedium() {}
};
// Statics:
@@ -82,30 +79,30 @@ class CMICmnLog : public MI::ISingleton<CMICmnLog>
bool UnregisterMedium(const IMedium &vrMedium);
bool Write(const CMIUtilString &vData, const ELogVerbosity veType);
bool SetEnabled(const bool vbYes);
- bool GetEnabled(void) const;
+ bool GetEnabled() const;
// MI common object handling - duplicate of CMICmnBase functions, necessary for LINUX build
// Done to stop locking on object construction init circular dependency.
- const CMIUtilString &GetErrorDescription(void) const;
+ const CMIUtilString &GetErrorDescription() const;
void SetErrorDescription(const CMIUtilString &vrTxt) const;
- void ClrErrorDescription(void) const;
+ void ClrErrorDescription() const;
// Overridden:
public:
// From MI::ISingleton
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
// Methods:
private:
- /* ctor */ CMICmnLog(void);
+ /* ctor */ CMICmnLog();
/* ctor */ CMICmnLog(const CMICmnLog &);
void operator=(const CMICmnLog &);
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmnLog(void) override;
+ /* dtor */ ~CMICmnLog() override;
// Typedef:
private:
@@ -115,7 +112,7 @@ class CMICmnLog : public MI::ISingleton<CMICmnLog>
// Methods:
private:
bool HaveMediumAlready(const IMedium &vrMedium) const;
- bool UnregisterMediumAll(void);
+ bool UnregisterMediumAll();
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLogMediumFile.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLogMediumFile.cpp
index 67b8086..e74fca9 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLogMediumFile.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLogMediumFile.cpp
@@ -10,13 +10,6 @@
// In-house headers:
#include "MICmnLogMediumFile.h"
#include "MICmnResources.h"
-#if defined(_MSC_VER)
-#include "MIUtilSystemWindows.h"
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__linux__)
-#include "MIUtilSystemLinux.h"
-#elif defined(__APPLE__)
-#include "MIUtilSystemOsx.h"
-#endif // defined( _MSC_VER )
//++ ------------------------------------------------------------------------------------
// Details: CMICmnLogMediumFile constructor.
@@ -25,11 +18,11 @@
// Return: None.
// Throws: None.
//--
-CMICmnLogMediumFile::CMICmnLogMediumFile(void)
+CMICmnLogMediumFile::CMICmnLogMediumFile()
: m_constThisMediumName(MIRSRC(IDS_MEDIUMFILE_NAME))
, m_constMediumFileNameFormat("lldb-mi-%s.log")
, m_strMediumFileName(MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH))
- , m_strMediumFileDirectory(MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH))
+ , m_strMediumFileDirectory(".")
, m_fileNamePath(MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH))
, m_eVerbosityType(CMICmnLog::eLogVerbosity_Log)
, m_strDate(CMIUtilDateTimeStd().GetDate())
@@ -44,7 +37,7 @@ CMICmnLogMediumFile::CMICmnLogMediumFile(void)
// Return: None.
// Throws: None.
//--
-CMICmnLogMediumFile::~CMICmnLogMediumFile(void)
+CMICmnLogMediumFile::~CMICmnLogMediumFile()
{
}
@@ -56,7 +49,7 @@ CMICmnLogMediumFile::~CMICmnLogMediumFile(void)
// Throws: None.
//--
CMICmnLogMediumFile &
-CMICmnLogMediumFile::Instance(void)
+CMICmnLogMediumFile::Instance()
{
static CMICmnLogMediumFile instance;
@@ -72,12 +65,10 @@ CMICmnLogMediumFile::Instance(void)
// Throws: None.
//--
bool
-CMICmnLogMediumFile::Initialize(void)
+CMICmnLogMediumFile::Initialize()
{
- m_bInitialized = CMIUtilSystem().GetLogFilesPath(m_strMediumFileDirectory);
- m_bInitialized &= FileFormFileNamePath();
-
- return m_bInitialized;
+ m_bInitialized = true;
+ return FileFormFileNamePath();
}
//++ ------------------------------------------------------------------------------------
@@ -88,7 +79,7 @@ CMICmnLogMediumFile::Initialize(void)
// Throws: None.
//--
bool
-CMICmnLogMediumFile::Shutdown(void)
+CMICmnLogMediumFile::Shutdown()
{
if (m_bInitialized)
{
@@ -106,7 +97,7 @@ CMICmnLogMediumFile::Shutdown(void)
// Throws: None.
//--
const CMIUtilString &
-CMICmnLogMediumFile::GetName(void) const
+CMICmnLogMediumFile::GetName() const
{
return m_constThisMediumName;
}
@@ -155,7 +146,7 @@ CMICmnLogMediumFile::Write(const CMIUtilString &vData, const CMICmnLog::ELogVerb
// Throws: None.
//--
const CMIUtilString &
-CMICmnLogMediumFile::GetError(void) const
+CMICmnLogMediumFile::GetError() const
{
return m_strMILastErrorDescription;
}
@@ -183,7 +174,7 @@ CMICmnLogMediumFile::SetVerbosity(const MIuint veType)
// Throws: None.
//--
MIuint
-CMICmnLogMediumFile::GetVerbosity(void) const
+CMICmnLogMediumFile::GetVerbosity() const
{
return m_eVerbosityType;
}
@@ -210,29 +201,22 @@ CMICmnLogMediumFile::FileWriteEnglish(const CMIUtilString &vData)
// Throws: None.
//--
bool
-CMICmnLogMediumFile::FileFormFileNamePath(void)
+CMICmnLogMediumFile::FileFormFileNamePath()
{
ClrErrorDescription();
m_fileNamePath = MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH);
- if (m_strMediumFileDirectory.compare(MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH)) != 0)
- {
- CMIUtilDateTimeStd date;
- m_strMediumFileName = CMIUtilString::Format(m_constMediumFileNameFormat.c_str(), date.GetDateTimeLogFilename().c_str());
+ CMIUtilDateTimeStd date;
+ m_strMediumFileName = CMIUtilString::Format(m_constMediumFileNameFormat.c_str(), date.GetDateTimeLogFilename().c_str());
#if defined(_MSC_VER)
- m_fileNamePath = CMIUtilString::Format("%s\\%s", m_strMediumFileDirectory.c_str(), m_strMediumFileName.c_str());
+ m_fileNamePath = CMIUtilString::Format("%s\\%s", m_strMediumFileDirectory.c_str(), m_strMediumFileName.c_str());
#else
- m_fileNamePath = CMIUtilString::Format("%s/%s", m_strMediumFileDirectory.c_str(), m_strMediumFileName.c_str());
+ m_fileNamePath = CMIUtilString::Format("%s/%s", m_strMediumFileDirectory.c_str(), m_strMediumFileName.c_str());
#endif // defined ( _MSC_VER )
- return MIstatus::success;
- }
-
- SetErrorDescription(MIRSRC(IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS));
-
- return MIstatus::failure;
+ return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@@ -243,7 +227,7 @@ CMICmnLogMediumFile::FileFormFileNamePath(void)
// Throws: None.
//--
const CMIUtilString &
-CMICmnLogMediumFile::GetFileNamePath(void) const
+CMICmnLogMediumFile::GetFileNamePath() const
{
return m_fileNamePath;
}
@@ -256,7 +240,7 @@ CMICmnLogMediumFile::GetFileNamePath(void) const
// Throws: None.
//--
const CMIUtilString &
-CMICmnLogMediumFile::GetFileName(void) const
+CMICmnLogMediumFile::GetFileName() const
{
return m_strMediumFileName;
}
@@ -332,7 +316,7 @@ CMICmnLogMediumFile::ConvertLogVerbosityTypeToId(const CMICmnLog::ELogVerbosity
// Throws: None.
//--
bool
-CMICmnLogMediumFile::IsOk(void) const
+CMICmnLogMediumFile::IsOk() const
{
return m_file.IsOk();
}
@@ -346,7 +330,7 @@ CMICmnLogMediumFile::IsOk(void) const
// Throws: None.
//--
bool
-CMICmnLogMediumFile::IsFileExist(void) const
+CMICmnLogMediumFile::IsFileExist() const
{
return m_file.IsFileExist(GetFileNamePath());
}
@@ -360,7 +344,7 @@ CMICmnLogMediumFile::IsFileExist(void) const
// Throws: None.
//--
bool
-CMICmnLogMediumFile::FileWriteHeader(void)
+CMICmnLogMediumFile::FileWriteHeader()
{
return FileWriteEnglish(ConvertCr(m_fileHeaderTxt));
}
@@ -419,7 +403,7 @@ CMICmnLogMediumFile::SetHeaderTxt(const CMIUtilString &vText)
// Throws: None.
//--
const CMIUtilString &
-CMICmnLogMediumFile::GetLineReturn(void) const
+CMICmnLogMediumFile::GetLineReturn() const
{
return m_file.GetLineReturn();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLogMediumFile.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLogMediumFile.h
index b79baf1..249da71 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLogMediumFile.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnLogMediumFile.h
@@ -23,49 +23,46 @@
// which the Logger when given data to write to registered medium comes
// *this medium.
// Singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 30/01/2014.
-// Changes: None.
//--
class CMICmnLogMediumFile : public CMICmnBase, public CMICmnLog::IMedium
{
// Statics:
public:
- static CMICmnLogMediumFile &Instance(void);
+ static CMICmnLogMediumFile &Instance();
// Methods:
public:
bool SetHeaderTxt(const CMIUtilString &vText);
bool SetVerbosity(const MIuint veType);
- MIuint GetVerbosity(void) const;
- const CMIUtilString &GetFileName(void) const;
- const CMIUtilString &GetFileNamePath(void) const;
- bool IsOk(void) const;
- bool IsFileExist(void) const;
- const CMIUtilString &GetLineReturn(void) const;
+ MIuint GetVerbosity() const;
+ const CMIUtilString &GetFileName() const;
+ const CMIUtilString &GetFileNamePath() const;
+ bool IsOk() const;
+ bool IsFileExist() const;
+ const CMIUtilString &GetLineReturn() const;
bool SetDirectory(const CMIUtilString &vPath);
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMICmnLogMediumFile(void) override;
+ /* dtor */ ~CMICmnLogMediumFile() override;
// From CMICmnLog::IMedium
- bool Initialize(void) override;
- const CMIUtilString &GetName(void) const override;
+ bool Initialize() override;
+ const CMIUtilString &GetName() const override;
bool Write(const CMIUtilString &vData, const CMICmnLog::ELogVerbosity veType) override;
- const CMIUtilString &GetError(void) const override;
- bool Shutdown(void) override;
+ const CMIUtilString &GetError() const override;
+ bool Shutdown() override;
// Methods:
private:
- /* ctor */ CMICmnLogMediumFile(void);
+ /* ctor */ CMICmnLogMediumFile();
/* ctor */ CMICmnLogMediumFile(const CMICmnLogMediumFile &);
void operator=(const CMICmnLogMediumFile &);
bool FileWriteEnglish(const CMIUtilString &vData);
- bool FileFormFileNamePath(void);
+ bool FileFormFileNamePath();
CMIUtilString MassagedData(const CMIUtilString &vData, const CMICmnLog::ELogVerbosity veType);
- bool FileWriteHeader(void);
+ bool FileWriteHeader();
char ConvertLogVerbosityTypeToId(const CMICmnLog::ELogVerbosity veType) const;
CMIUtilString ConvertCr(const CMIUtilString &vData) const;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp
index 84c6695..e633e5a 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp
@@ -1,4 +1,4 @@
-//===-- MICmnMIOutOfBandRecord.cpp --------------------------------------------*- C++ -*-===//
+//===-- MICmnMIOutOfBandRecord.cpp ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,43 +7,106 @@
//
//===----------------------------------------------------------------------===//
+// Third Party Headers:
+#include <assert.h>
+
// In-house headers:
#include "MICmnMIOutOfBandRecord.h"
#include "MICmnResources.h"
// Instantiations:
-CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_MapOutOfBandToOutOfBandText = {
- {CMICmnMIOutOfBandRecord::eOutOfBand_Running, "running"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, "stopped"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, "breakpoint-created"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, "breakpoint-modified"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_Thread, ""}, // "" Meant to be empty
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded, "thread-group-added"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, "thread-group-exited"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved, "thread-group-removed"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, "thread-group-started"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, "thread-created"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, "thread-exited"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "thread-selected"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded, "library-loaded"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded, "library-unloaded"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, ""}};
-CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_constMapAsyncRecordTextToToken = {
- {CMICmnMIOutOfBandRecord::eOutOfBand_Running, "*"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, "*"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, "="},
- {CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, "="},
- {CMICmnMIOutOfBandRecord::eOutOfBand_Thread, "@"},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded, "="},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, "="},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved, "="},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, "="},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, "="},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, "="},
- {CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "="},
- {CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded, "="},
- {CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded, "="},
- {CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, "@"}};
+static const char *
+MapOutOfBandToText(CMICmnMIOutOfBandRecord::OutOfBand_e veType)
+{
+ switch (veType)
+ {
+ case CMICmnMIOutOfBandRecord::eOutOfBand_Running:
+ return "running";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_Stopped:
+ return "stopped";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated:
+ return "breakpoint-created";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified:
+ return "breakpoint-modified";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_Thread:
+ return ""; // "" Meant to be empty
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded:
+ return "thread-group-added";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited:
+ return "thread-group-exited";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved:
+ return "thread-group-removed";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted:
+ return "thread-group-started";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated:
+ return "thread-created";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited:
+ return "thread-exited";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected:
+ return "thread-selected";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded:
+ return "library-loaded";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded:
+ return "library-unloaded";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput:
+ return "";
+ }
+ assert(false && "unknown CMICmnMIOutofBandRecord::OutOfBand_e");
+ return NULL;
+}
+
+static const char *
+MapOutOfBandToToken(CMICmnMIOutOfBandRecord::OutOfBand_e veType)
+{
+ switch (veType)
+ {
+ case CMICmnMIOutOfBandRecord::eOutOfBand_Running:
+ return "*";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_Stopped:
+ return "*";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated:
+ return "=";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified:
+ return "=";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_Thread:
+ return "@";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded:
+ return "=";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited:
+ return "=";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved:
+ return "=";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted:
+ return "=";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated:
+ return "=";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited:
+ return "=";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected:
+ return "=";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded:
+ return "=";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded:
+ return "=";
+ case CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput:
+ return "@";
+ }
+ assert(false && "unknown CMICmnMIOutofBandRecord::OutOfBand_e");
+ return NULL;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Build the Out-of-band record's mandatory data part. The part up to the first
+// (additional) result i.e. async-record ==> "*" type.
+// Args: veType - (R) A MI Out-of-Band enumeration.
+// Return: CMIUtilString - The async record text.
+// Throws: None.
+//--
+static CMIUtilString
+BuildAsyncRecord(CMICmnMIOutOfBandRecord::OutOfBand_e veType)
+{
+ return CMIUtilString::Format("%s%s", MapOutOfBandToToken(veType), MapOutOfBandToText(veType));
+}
//++ ------------------------------------------------------------------------------------
// Details: CMICmnMIOutOfBandRecord constructor.
@@ -52,7 +115,7 @@ CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_constMapAsyncRecordTex
// Return: None.
// Throws: None.
//--
-CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(void)
+CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord()
: m_strAsyncRecord(MIRSRC(IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION))
{
}
@@ -64,11 +127,9 @@ CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(void)
// Return: None.
// Throws: None.
//--
-CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(const OutOfBand_e veType)
- : m_eResultAsyncRecordClass(veType)
- , m_strAsyncRecord(MIRSRC(IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION))
+CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(OutOfBand_e veType)
+ : m_strAsyncRecord(BuildAsyncRecord(veType))
{
- BuildAsyncRecord();
}
//++ ------------------------------------------------------------------------------------
@@ -79,11 +140,9 @@ CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(const OutOfBand_e veType)
// Return: None.
// Throws: None.
//--
-CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(const OutOfBand_e veType, const CMICmnMIValueConst &vConst)
- : m_eResultAsyncRecordClass(veType)
- , m_strAsyncRecord(MIRSRC(IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION))
+CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(OutOfBand_e veType, const CMICmnMIValueConst &vConst)
+ : m_strAsyncRecord(BuildAsyncRecord(veType))
{
- BuildAsyncRecord();
m_strAsyncRecord += vConst.GetString();
}
@@ -95,13 +154,10 @@ CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(const OutOfBand_e veType, const
// Return: None.
// Throws: None.
//--
-CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(const OutOfBand_e veType, const CMICmnMIValueResult &vResult)
- : m_eResultAsyncRecordClass(veType)
- , m_strAsyncRecord(MIRSRC(IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION))
- , m_partResult(vResult)
+CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(OutOfBand_e veType, const CMICmnMIValueResult &vResult)
+ : m_strAsyncRecord(BuildAsyncRecord(veType))
{
- BuildAsyncRecord();
- Add(m_partResult);
+ Add(vResult);
}
//++ ------------------------------------------------------------------------------------
@@ -111,7 +167,7 @@ CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(const OutOfBand_e veType, const
// Return: None.
// Throws: None.
//--
-CMICmnMIOutOfBandRecord::~CMICmnMIOutOfBandRecord(void)
+CMICmnMIOutOfBandRecord::~CMICmnMIOutOfBandRecord()
{
}
@@ -126,44 +182,21 @@ CMICmnMIOutOfBandRecord::~CMICmnMIOutOfBandRecord(void)
// Throws: None.
//--
const CMIUtilString &
-CMICmnMIOutOfBandRecord::GetString(void) const
+CMICmnMIOutOfBandRecord::GetString() const
{
return m_strAsyncRecord;
}
//++ ------------------------------------------------------------------------------------
-// Details: Build the Out-of-band record's mandatory data part. The part up to the first
-// (additional) result i.e. async-record ==> "*" type.
-// Type: Method.
-// Args: None.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMICmnMIOutOfBandRecord::BuildAsyncRecord(void)
-{
- const char *pFormat = "%s%s";
- const CMIUtilString &rStrAsyncRecord(ms_MapOutOfBandToOutOfBandText[m_eResultAsyncRecordClass]);
- const CMIUtilString &rStrToken(ms_constMapAsyncRecordTextToToken[m_eResultAsyncRecordClass]);
- m_strAsyncRecord = CMIUtilString::Format(pFormat, rStrToken.c_str(), rStrAsyncRecord.c_str());
-
- return MIstatus::success;
-}
-
-//++ ------------------------------------------------------------------------------------
// Details: Add to *this Out-of-band record additional information.
// Type: Method.
// Args: vResult - (R) A MI result object.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIOutOfBandRecord::Add(const CMICmnMIValueResult &vResult)
{
m_strAsyncRecord += ",";
m_strAsyncRecord += vResult.GetString();
-
- return MIstatus::success;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.h
index 6277e86..ad18e6c 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.h
@@ -9,9 +9,6 @@
#pragma once
-// Third party headers:
-#include <map>
-
// In-house headers:
#include "MICmnBase.h"
#include "MIUtilString.h"
@@ -37,9 +34,6 @@
//
// More information see:
// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html//
-// Gotchas: None.
-// Authors: Illya Rudkin 24/02/2014.
-// Changes: None.
//--
class CMICmnMIOutOfBandRecord : public CMICmnBase
{
@@ -64,40 +58,25 @@ class CMICmnMIOutOfBandRecord : public CMICmnBase
eOutOfBand_ThreadSelected,
eOutOfBand_TargetModuleLoaded,
eOutOfBand_TargetModuleUnloaded,
- eOutOfBand_TargetStreamOutput,
- eOutOfBand_count // Always the last one
+ eOutOfBand_TargetStreamOutput
};
- // Typedefs:
- public:
- typedef std::map<OutOfBand_e, CMIUtilString> MapOutOfBandToOutOfBandText_t;
- typedef std::map<OutOfBand_e, CMIUtilString> MapOutOfBandToToken_t;
-
// Methods:
public:
- /* ctor */ CMICmnMIOutOfBandRecord(void);
- /* ctor */ CMICmnMIOutOfBandRecord(const OutOfBand_e veType);
- /* ctor */ CMICmnMIOutOfBandRecord(const OutOfBand_e veType, const CMICmnMIValueConst &vConst);
- /* ctor */ CMICmnMIOutOfBandRecord(const OutOfBand_e veType, const CMICmnMIValueResult &vResult);
+ /* ctor */ CMICmnMIOutOfBandRecord();
+ /* ctor */ CMICmnMIOutOfBandRecord(OutOfBand_e veType);
+ /* ctor */ CMICmnMIOutOfBandRecord(OutOfBand_e veType, const CMICmnMIValueConst &vConst);
+ /* ctor */ CMICmnMIOutOfBandRecord(OutOfBand_e veType, const CMICmnMIValueResult &vResult);
//
- const CMIUtilString &GetString(void) const;
- bool Add(const CMICmnMIValueResult &vResult);
+ const CMIUtilString &GetString() const;
+ void Add(const CMICmnMIValueResult &vResult);
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMICmnMIOutOfBandRecord(void) override;
-
- // Methods:
- private:
- bool BuildAsyncRecord(void);
+ /* dtor */ ~CMICmnMIOutOfBandRecord() override;
// Attributes:
private:
- static MapOutOfBandToOutOfBandText_t ms_constMapOutOfBandToAsyncRecordText;
- static MapOutOfBandToToken_t ms_constMapOutOfBandTextToToken;
- //
- OutOfBand_e m_eResultAsyncRecordClass;
CMIUtilString m_strAsyncRecord; // Holds the text version of the result record to date
- CMICmnMIValueResult m_partResult;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp
index 49a31c8..0348f89 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp
@@ -1,4 +1,4 @@
-//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//===-- MICmnMIResultRecord.cpp ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,18 +7,53 @@
//
//===----------------------------------------------------------------------===//
+// Third Party Headers:
+#include <assert.h>
+
// In-house headers:
#include "MICmnMIResultRecord.h"
#include "MICmnResources.h"
-// Instantiations:
-CMICmnMIResultRecord::MapResultClassToResultClassText_t ms_MapResultClassToResultClassText = {
- {CMICmnMIResultRecord::eResultClass_Done, "done"},
- {CMICmnMIResultRecord::eResultClass_Running, "running"},
- {CMICmnMIResultRecord::eResultClass_Connected, "connected"},
- {CMICmnMIResultRecord::eResultClass_Error, "error"},
- {CMICmnMIResultRecord::eResultClass_Exit, "exit"}};
-const CMIUtilString CMICmnMIResultRecord::ms_constStrResultRecordHat("^");
+//++ ------------------------------------------------------------------------------------
+// Details: Map a result class to the corresponding string.
+// Args: veType - (R) A MI result class enumeration.
+// Return: const char* - The string corresponding to the result class.
+// Throws: None.
+//--
+static const char*
+MapResultClassToResultClassText(CMICmnMIResultRecord::ResultClass_e veType)
+{
+ switch (veType)
+ {
+ case CMICmnMIResultRecord::eResultClass_Done:
+ return "done";
+ case CMICmnMIResultRecord::eResultClass_Running:
+ return "running";
+ case CMICmnMIResultRecord::eResultClass_Connected:
+ return "connected";
+ case CMICmnMIResultRecord::eResultClass_Error:
+ return "error";
+ case CMICmnMIResultRecord::eResultClass_Exit:
+ return "exit";
+ }
+ assert(false && "unknown CMICmnMIResultRecord::ResultClass_e");
+ return NULL;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Build the result record's mandatory data part. The part up to the first
+// (additional) result i.e. result-record ==> [ token ] "^" result-class.
+// Args: vrToken - (R) The command's transaction ID or token.
+// veType - (R) A MI result class enumeration.
+// Return: CMIUtilString & - MI result record mandatory data
+// Throws: None.
+//--
+static const CMIUtilString
+BuildResultRecord(const CMIUtilString &vrToken, CMICmnMIResultRecord::ResultClass_e veType)
+{
+ const char *pStrResultRecord = MapResultClassToResultClassText(veType);
+ return CMIUtilString::Format("%s^%s", vrToken.c_str(), pStrResultRecord);
+}
//++ ------------------------------------------------------------------------------------
// Details: CMICmnMIResultRecord constructor.
@@ -27,7 +62,7 @@ const CMIUtilString CMICmnMIResultRecord::ms_constStrResultRecordHat("^");
// Return: None.
// Throws: None.
//--
-CMICmnMIResultRecord::CMICmnMIResultRecord(void)
+CMICmnMIResultRecord::CMICmnMIResultRecord()
: m_strResultRecord(MIRSRC(IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION))
{
}
@@ -40,12 +75,9 @@ CMICmnMIResultRecord::CMICmnMIResultRecord(void)
// Return: None.
// Throws: None.
//--
-CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, const ResultClass_e veType)
- : m_strResultRecordToken(vrToken)
- , m_eResultRecordResultClass(veType)
- , m_strResultRecord(MIRSRC(IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION))
+CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, ResultClass_e veType)
+ : m_strResultRecord(BuildResultRecord(vrToken, veType))
{
- BuildResultRecord();
}
//++ ------------------------------------------------------------------------------------
@@ -57,14 +89,10 @@ CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, const R
// Return: None.
// Throws: None.
//--
-CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, const ResultClass_e veType, const CMICmnMIValueResult &vValue)
- : m_strResultRecordToken(vrToken)
- , m_eResultRecordResultClass(veType)
- , m_strResultRecord(MIRSRC(IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION))
- , m_partResult(vValue)
+CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, ResultClass_e veType, const CMICmnMIValueResult &vValue)
+ : m_strResultRecord(BuildResultRecord(vrToken, veType))
{
- BuildResultRecord();
- Add(m_partResult);
+ Add(vValue);
}
//++ ------------------------------------------------------------------------------------
@@ -74,7 +102,7 @@ CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, const R
// Return: None.
// Throws: None.
//--
-CMICmnMIResultRecord::~CMICmnMIResultRecord(void)
+CMICmnMIResultRecord::~CMICmnMIResultRecord()
{
}
@@ -89,44 +117,21 @@ CMICmnMIResultRecord::~CMICmnMIResultRecord(void)
// Throws: None.
//--
const CMIUtilString &
-CMICmnMIResultRecord::GetString(void) const
+CMICmnMIResultRecord::GetString() const
{
return m_strResultRecord;
}
//++ ------------------------------------------------------------------------------------
-// Details: Build the result record's mandatory data part. The part up to the first
-// (additional) result i.e. result-record ==> [ token ] "^" result-class.
-// Type: Method.
-// Args: None.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMICmnMIResultRecord::BuildResultRecord(void)
-{
- const char *pFormat = "%s%s%s";
- const CMIUtilString &rStrResultRecord(ms_MapResultClassToResultClassText[m_eResultRecordResultClass]);
- m_strResultRecord =
- CMIUtilString::Format(pFormat, m_strResultRecordToken.c_str(), ms_constStrResultRecordHat.c_str(), rStrResultRecord.c_str());
-
- return MIstatus::success;
-}
-
-//++ ------------------------------------------------------------------------------------
// Details: Add to *this result record additional information.
// Type: Method.
// Args: vMIValue - (R) A MI value derived object.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIResultRecord::Add(const CMICmnMIValue &vMIValue)
{
m_strResultRecord += ",";
m_strResultRecord += vMIValue.GetString();
-
- return MIstatus::success;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIResultRecord.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIResultRecord.h
index 981cf36..4408324 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIResultRecord.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIResultRecord.h
@@ -9,9 +9,6 @@
#pragma once
-// Third party headers:
-#include <map>
-
// In-house headers:
#include "MICmnBase.h"
#include "MIUtilString.h"
@@ -39,9 +36,6 @@
// be returned.
// More information see:
// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
-// Gotchas: None.
-// Authors: Illya Rudkin 24/02/2014.
-// Changes: None.
//--
class CMICmnMIResultRecord : public CMICmnBase
{
@@ -56,39 +50,24 @@ class CMICmnMIResultRecord : public CMICmnBase
eResultClass_Running,
eResultClass_Connected,
eResultClass_Error,
- eResultClass_Exit,
- eResultClass_count // Always the last one
+ eResultClass_Exit
};
- // Typedefs:
- public:
- typedef std::map<ResultClass_e, CMIUtilString> MapResultClassToResultClassText_t;
-
// Methods:
public:
- /* ctor */ CMICmnMIResultRecord(void);
- /* ctor */ CMICmnMIResultRecord(const CMIUtilString &vrToken, const ResultClass_e veType);
- /* ctor */ CMICmnMIResultRecord(const CMIUtilString &vrToken, const ResultClass_e veType, const CMICmnMIValueResult &vValue);
+ /* ctor */ CMICmnMIResultRecord();
+ /* ctor */ CMICmnMIResultRecord(const CMIUtilString &vrToken, ResultClass_e veType);
+ /* ctor */ CMICmnMIResultRecord(const CMIUtilString &vrToken, ResultClass_e veType, const CMICmnMIValueResult &vValue);
//
- const CMIUtilString &GetString(void) const;
- bool Add(const CMICmnMIValue &vMIValue);
+ const CMIUtilString &GetString() const;
+ void Add(const CMICmnMIValue &vMIValue);
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMICmnMIResultRecord(void) override;
-
- // Methods:
- private:
- bool BuildResultRecord(void);
+ /* dtor */ ~CMICmnMIResultRecord() override;
// Attributes:
private:
- static const CMIUtilString ms_constStrResultRecordHat;
- static MapResultClassToResultClassText_t ms_constMapResultClassToResultClassText;
- //
- CMIUtilString m_strResultRecordToken;
- ResultClass_e m_eResultRecordResultClass;
CMIUtilString m_strResultRecord; // Holds the text version of the result record to date
- CMICmnMIValueResult m_partResult;
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValue.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValue.cpp
index 2f70414..d5895d7 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValue.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValue.cpp
@@ -1,4 +1,4 @@
-//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//===-- MICmnMIValue.cpp ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,7 +18,7 @@
// Return: None.
// Throws: None.
//--
-CMICmnMIValue::CMICmnMIValue(void)
+CMICmnMIValue::CMICmnMIValue()
: m_strValue(MIRSRC(IDS_WORD_INVALIDBRKTS))
, m_bJustConstructed(true)
{
@@ -31,7 +31,7 @@ CMICmnMIValue::CMICmnMIValue(void)
// Return: None.
// Throws: None.
//--
-CMICmnMIValue::~CMICmnMIValue(void)
+CMICmnMIValue::~CMICmnMIValue()
{
}
@@ -46,7 +46,7 @@ CMICmnMIValue::~CMICmnMIValue(void)
// Throws: None.
//--
const CMIUtilString &
-CMICmnMIValue::GetString(void) const
+CMICmnMIValue::GetString() const
{
return m_strValue;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValue.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValue.h
index 6a372e6..dd11d6a 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValue.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValue.h
@@ -28,22 +28,19 @@
// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
// More information see:
// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
-// Gotchas: None.
-// Authors: Illya Rudkin 24/02/2014.
-// Changes: None.
//--
class CMICmnMIValue : public CMICmnBase
{
// Methods:
public:
- /* ctor */ CMICmnMIValue(void);
+ /* ctor */ CMICmnMIValue();
//
- const CMIUtilString &GetString(void) const;
+ const CMIUtilString &GetString() const;
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMICmnMIValue(void) override;
+ /* dtor */ ~CMICmnMIValue() override;
// Attributes:
protected:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueConst.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueConst.cpp
index dd4b993..d8b11e9 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueConst.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueConst.cpp
@@ -1,4 +1,4 @@
-//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//===-- MICmnMIValueConst.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -49,7 +49,7 @@ CMICmnMIValueConst::CMICmnMIValueConst(const CMIUtilString &vString, const bool
// Return: None.
// Throws: None.
//--
-CMICmnMIValueConst::~CMICmnMIValueConst(void)
+CMICmnMIValueConst::~CMICmnMIValueConst()
{
}
@@ -62,7 +62,7 @@ CMICmnMIValueConst::~CMICmnMIValueConst(void)
// Throws: None.
//--
bool
-CMICmnMIValueConst::BuildConst(void)
+CMICmnMIValueConst::BuildConst()
{
if (m_strPartConst.length() != 0)
{
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueConst.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueConst.h
index 4036194..7f6333e 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueConst.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueConst.h
@@ -30,10 +30,6 @@
// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
//
// The text formed in *this Result class is stripped of any '\n' characters.
-//
-// Gotchas: None.
-// Authors: Illya Rudkin 24/02/2014.
-// Changes: None.
//--
class CMICmnMIValueConst : public CMICmnMIValue
{
@@ -45,11 +41,11 @@ class CMICmnMIValueConst : public CMICmnMIValue
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMICmnMIValueConst(void) override;
+ /* dtor */ ~CMICmnMIValueConst() override;
// Methods:
private:
- bool BuildConst(void);
+ bool BuildConst();
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueList.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueList.cpp
index 30888cf..e4d3f40 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueList.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueList.cpp
@@ -1,4 +1,4 @@
-//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//===-- MICmnMIValueList.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -61,7 +61,7 @@ CMICmnMIValueList::CMICmnMIValueList(const CMICmnMIValue &vValue)
// Return: None.
// Throws: None.
//--
-CMICmnMIValueList::~CMICmnMIValueList(void)
+CMICmnMIValueList::~CMICmnMIValueList()
{
}
@@ -69,17 +69,14 @@ CMICmnMIValueList::~CMICmnMIValueList(void)
// Details: Build the result value's mandatory data part, one tuple
// Type: Method.
// Args: None.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
-CMICmnMIValueList::BuildList(void)
+void
+CMICmnMIValueList::BuildList()
{
const char *pFormat = "[%s]";
m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str());
-
- return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@@ -88,14 +85,13 @@ CMICmnMIValueList::BuildList(void)
// will return MIstatus::failure.
// Type: Method.
// Args: vResult - (R) The MI result object.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIValueList::Add(const CMICmnMIValueResult &vResult)
{
- return BuildList(vResult);
+ BuildList(vResult);
}
//++ ------------------------------------------------------------------------------------
@@ -104,14 +100,13 @@ CMICmnMIValueList::Add(const CMICmnMIValueResult &vResult)
// will return MIstatus::failure.
// Type: Method.
// Args: vValue - (R) The MI value object.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIValueList::Add(const CMICmnMIValue &vValue)
{
- return BuildList(vValue);
+ BuildList(vValue);
}
//++ ------------------------------------------------------------------------------------
@@ -120,11 +115,10 @@ CMICmnMIValueList::Add(const CMICmnMIValue &vValue)
// will return MIstatus::failure.
// Type: Method.
// Args: vResult - (R) The MI result object.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIValueList::BuildList(const CMICmnMIValueResult &vResult)
{
// Clear out the default "<Invalid>" text
@@ -132,14 +126,13 @@ CMICmnMIValueList::BuildList(const CMICmnMIValueResult &vResult)
{
m_bJustConstructed = false;
m_strValue = vResult.GetString();
- return BuildList();
+ BuildList();
+ return;
}
const CMIUtilString data(ExtractContentNoBrackets());
const char *pFormat = "[%s,%s]";
m_strValue = CMIUtilString::Format(pFormat, data.c_str(), vResult.GetString().c_str());
-
- return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@@ -148,11 +141,10 @@ CMICmnMIValueList::BuildList(const CMICmnMIValueResult &vResult)
// will return MIstatus::failure.
// Type: Method.
// Args: vValue - (R) The MI value object.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIValueList::BuildList(const CMICmnMIValue &vValue)
{
// Clear out the default "<Invalid>" text
@@ -160,7 +152,8 @@ CMICmnMIValueList::BuildList(const CMICmnMIValue &vValue)
{
m_bJustConstructed = false;
m_strValue = vValue.GetString();
- return BuildList();
+ BuildList();
+ return;
}
// Remove already present '[' and ']' from the start and end
@@ -170,8 +163,6 @@ CMICmnMIValueList::BuildList(const CMICmnMIValue &vValue)
m_strValue = m_strValue.substr(1, len - 2);
const char *pFormat = "[%s,%s]";
m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str(), vValue.GetString().c_str());
-
- return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@@ -183,7 +174,7 @@ CMICmnMIValueList::BuildList(const CMICmnMIValue &vValue)
// Throws: None.
//--
CMIUtilString
-CMICmnMIValueList::ExtractContentNoBrackets(void) const
+CMICmnMIValueList::ExtractContentNoBrackets() const
{
CMIUtilString data(m_strValue);
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueList.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueList.h
index 26a217df..0796cbe 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueList.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueList.h
@@ -29,9 +29,6 @@
// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
// More information see:
// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
-// Gotchas: None.
-// Authors: Illya Rudkin 24/02/2014.
-// Changes: None.
//--
class CMICmnMIValueList : public CMICmnMIValue
{
@@ -41,18 +38,18 @@ class CMICmnMIValueList : public CMICmnMIValue
/* ctor */ CMICmnMIValueList(const CMICmnMIValueResult &vResult);
/* ctor */ CMICmnMIValueList(const CMICmnMIValue &vValue);
//
- bool Add(const CMICmnMIValueResult &vResult);
- bool Add(const CMICmnMIValue &vValue);
- CMIUtilString ExtractContentNoBrackets(void) const;
+ void Add(const CMICmnMIValueResult &vResult);
+ void Add(const CMICmnMIValue &vValue);
+ CMIUtilString ExtractContentNoBrackets() const;
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMICmnMIValueList(void) override;
+ /* dtor */ ~CMICmnMIValueList() override;
// Methods:
private:
- bool BuildList(void);
- bool BuildList(const CMICmnMIValueResult &vResult);
- bool BuildList(const CMICmnMIValue &vResult);
+ void BuildList();
+ void BuildList(const CMICmnMIValueResult &vResult);
+ void BuildList(const CMICmnMIValue &vResult);
};
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueResult.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueResult.cpp
index 55d93ce..d86f724 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueResult.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueResult.cpp
@@ -1,4 +1,4 @@
-//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//===-- MICmnMIValueResult.cpp ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -21,7 +21,7 @@ const CMIUtilString CMICmnMIValueResult::ms_constStrEqual("=");
// Return: None.
// Throws: None.
//--
-CMICmnMIValueResult::CMICmnMIValueResult(void)
+CMICmnMIValueResult::CMICmnMIValueResult()
: m_bEmptyConstruction(true)
{
}
@@ -68,7 +68,7 @@ CMICmnMIValueResult::CMICmnMIValueResult(const CMIUtilString &vrVariable, const
// Return: None.
// Throws: None.
//--
-CMICmnMIValueResult::~CMICmnMIValueResult(void)
+CMICmnMIValueResult::~CMICmnMIValueResult()
{
}
@@ -76,17 +76,14 @@ CMICmnMIValueResult::~CMICmnMIValueResult(void)
// Details: Build the MI value result string.
// Type: Method.
// Args: None.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
-CMICmnMIValueResult::BuildResult(void)
+void
+CMICmnMIValueResult::BuildResult()
{
const char *pFormat = m_bUseSpacing ? "%s %s %s" : "%s%s%s";
m_strValue = CMIUtilString::Format(pFormat, m_strPartVariable.c_str(), ms_constStrEqual.c_str(), m_partMIValue.GetString().c_str());
-
- return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@@ -94,18 +91,15 @@ CMICmnMIValueResult::BuildResult(void)
// Type: Method.
// Args: vrVariable - (R) MI value's name.
// vrValue - (R) The MI value.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIValueResult::BuildResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue)
{
const char *pFormat = m_bUseSpacing ? "%s, %s %s %s" : "%s,%s%s%s";
m_strValue =
CMIUtilString::Format(pFormat, m_strValue.c_str(), vVariable.c_str(), ms_constStrEqual.c_str(), vValue.GetString().c_str());
-
- return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@@ -117,16 +111,16 @@ CMICmnMIValueResult::BuildResult(const CMIUtilString &vVariable, const CMICmnMIV
// MIstatus::failure - Functional failed.
// Throws: None.
//--
-bool
+void
CMICmnMIValueResult::Add(const CMIUtilString &vrVariable, const CMICmnMIValue &vrValue)
{
if (!m_bEmptyConstruction)
- return BuildResult(vrVariable, vrValue);
+ BuildResult(vrVariable, vrValue);
else
{
m_bEmptyConstruction = false;
m_strPartVariable = vrVariable;
m_partMIValue = vrValue;
- return BuildResult();
+ BuildResult();
}
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueResult.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueResult.h
index 7c8e980..cd96520 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueResult.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueResult.h
@@ -28,29 +28,26 @@
// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
// More information see:
// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
-// Gotchas: None.
-// Authors: Illya Rudkin 24/02/2014.
-// Changes: None.
//--
class CMICmnMIValueResult : public CMICmnMIValue
{
// Methods:
public:
- /* ctor */ CMICmnMIValueResult(void);
+ /* ctor */ CMICmnMIValueResult();
/* ctor */ CMICmnMIValueResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue);
/* ctor */ CMICmnMIValueResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue, const bool vbUseSpacing);
//
- bool Add(const CMIUtilString &vVariable, const CMICmnMIValue &vValue);
+ void Add(const CMIUtilString &vVariable, const CMICmnMIValue &vValue);
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMICmnMIValueResult(void) override;
+ /* dtor */ ~CMICmnMIValueResult() override;
// Methods:
private:
- bool BuildResult(void);
- bool BuildResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue);
+ void BuildResult();
+ void BuildResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue);
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueTuple.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueTuple.cpp
index aa92b1f..4ff1d6c 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueTuple.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueTuple.cpp
@@ -1,4 +1,4 @@
-//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//===-- MICmnMIValueTuple.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,7 +17,7 @@
// Return: None.
// Throws: None.
//--
-CMICmnMIValueTuple::CMICmnMIValueTuple(void)
+CMICmnMIValueTuple::CMICmnMIValueTuple()
: m_bSpaceAfterComma(false)
{
m_strValue = "{}";
@@ -61,7 +61,7 @@ CMICmnMIValueTuple::CMICmnMIValueTuple(const CMICmnMIValueResult &vResult, const
// Return: None.
// Throws: None.
//--
-CMICmnMIValueTuple::~CMICmnMIValueTuple(void)
+CMICmnMIValueTuple::~CMICmnMIValueTuple()
{
}
@@ -69,28 +69,24 @@ CMICmnMIValueTuple::~CMICmnMIValueTuple(void)
// Details: Build the result value's mandatory data part, one tuple
// Type: Method.
// Args: None.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
-CMICmnMIValueTuple::BuildTuple(void)
+void
+CMICmnMIValueTuple::BuildTuple()
{
const char *pFormat = "{%s}";
m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str());
-
- return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Add another MI result object to the value's list of tuples.
// Type: Method.
// Args: vResult - (R) The MI result object.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIValueTuple::BuildTuple(const CMICmnMIValueResult &vResult)
{
// Clear out the default "<Invalid>" text
@@ -98,7 +94,8 @@ CMICmnMIValueTuple::BuildTuple(const CMICmnMIValueResult &vResult)
{
m_bJustConstructed = false;
m_strValue = vResult.GetString();
- return BuildTuple();
+ BuildTuple();
+ return;
}
if (m_strValue[0] == '{')
@@ -112,19 +109,16 @@ CMICmnMIValueTuple::BuildTuple(const CMICmnMIValueResult &vResult)
const char *pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}";
m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str(), vResult.GetString().c_str());
-
- return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Add string value to the value's list of tuples.
// Type: Method.
// Args: vValue - (R) The string object.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIValueTuple::BuildTuple(const CMIUtilString &vValue)
{
// Clear out the default "<Invalid>" text
@@ -132,14 +126,13 @@ CMICmnMIValueTuple::BuildTuple(const CMIUtilString &vValue)
{
m_bJustConstructed = false;
m_strValue = vValue;
- return BuildTuple();
+ BuildTuple();
+ return;
}
const CMIUtilString data(ExtractContentNoBrackets());
const char *pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}";
m_strValue = CMIUtilString::Format(pFormat, data.c_str(), vValue.c_str());
-
- return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
@@ -148,14 +141,13 @@ CMICmnMIValueTuple::BuildTuple(const CMIUtilString &vValue)
// will return MIstatus::failure.
// Type: Method.
// Args: vValue - (R) The MI value object.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIValueTuple::Add(const CMICmnMIValueResult &vResult)
{
- return BuildTuple(vResult);
+ BuildTuple(vResult);
}
//++ ------------------------------------------------------------------------------------
@@ -165,15 +157,14 @@ CMICmnMIValueTuple::Add(const CMICmnMIValueResult &vResult)
// Type: Method.
// Args: vValue - (R) The MI value object.
// vbUseSpacing - (R) True = put space separators into the string, false = no spaces used.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIValueTuple::Add(const CMICmnMIValueResult &vResult, const bool vbUseSpacing)
{
m_bSpaceAfterComma = vbUseSpacing;
- return BuildTuple(vResult);
+ BuildTuple(vResult);
}
//++ ------------------------------------------------------------------------------------
@@ -183,15 +174,14 @@ CMICmnMIValueTuple::Add(const CMICmnMIValueResult &vResult, const bool vbUseSpac
// Type: Method.
// Args: vValue - (R) The MI value object.
// vbUseSpacing - (R) True = put space separators into the string, false = no spaces used.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: None.
// Throws: None.
//--
-bool
+void
CMICmnMIValueTuple::Add(const CMICmnMIValueConst &vValue, const bool vbUseSpacing)
{
m_bSpaceAfterComma = vbUseSpacing;
- return BuildTuple(vValue.GetString());
+ BuildTuple(vValue.GetString());
}
//++ ------------------------------------------------------------------------------------
@@ -203,7 +193,7 @@ CMICmnMIValueTuple::Add(const CMICmnMIValueConst &vValue, const bool vbUseSpacin
// Throws: None.
//--
CMIUtilString
-CMICmnMIValueTuple::ExtractContentNoBrackets(void) const
+CMICmnMIValueTuple::ExtractContentNoBrackets() const
{
CMIUtilString data(m_strValue);
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueTuple.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueTuple.h
index ecf5402..8f36b4f 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueTuple.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnMIValueTuple.h
@@ -30,33 +30,30 @@
// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
// More information see:
// http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html
-// Gotchas: None.
-// Authors: Illya Rudkin 24/02/2014.
-// Changes: None.
//--
class CMICmnMIValueTuple : public CMICmnMIValue
{
// Methods:
public:
- /* ctor */ CMICmnMIValueTuple(void);
+ /* ctor */ CMICmnMIValueTuple();
/* ctor */ CMICmnMIValueTuple(const CMICmnMIValueResult &vResult);
/* ctor */ CMICmnMIValueTuple(const CMICmnMIValueResult &vResult, const bool vbUseSpacing);
//
- bool Add(const CMICmnMIValueResult &vResult);
- bool Add(const CMICmnMIValueResult &vResult, const bool vbUseSpacing);
- bool Add(const CMICmnMIValueConst &vValue, const bool vbUseSpacing);
- CMIUtilString ExtractContentNoBrackets(void) const;
+ void Add(const CMICmnMIValueResult &vResult);
+ void Add(const CMICmnMIValueResult &vResult, const bool vbUseSpacing);
+ void Add(const CMICmnMIValueConst &vValue, const bool vbUseSpacing);
+ CMIUtilString ExtractContentNoBrackets() const;
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMICmnMIValueTuple(void) override;
+ /* dtor */ ~CMICmnMIValueTuple() override;
// Methods:
private:
- bool BuildTuple(void);
- bool BuildTuple(const CMICmnMIValueResult &vResult);
- bool BuildTuple(const CMIUtilString &vValue);
+ void BuildTuple();
+ void BuildTuple(const CMICmnMIValueResult &vResult);
+ void BuildTuple(const CMIUtilString &vValue);
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.cpp
index ee9c93d..50d6b79 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.cpp
@@ -45,7 +45,6 @@ const CMICmnResources::SRsrcTextData CMICmnResources::ms_pResourceId2TextData[]
{IDS_MEDIUMFILE_ERR_INVALID_PATH, "<Invalid - not set>"},
{IDS_MEDIUMFILE_ERR_FILE_HEADER, "<Invalid - header not set>"},
{IDS_MEDIUMFILE_NAME_LOG, "File medium. %s"},
- {IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS, "File Medium. Failed to retrieve the system/executable path for the Log file"},
{IDE_OS_ERR_UNKNOWN, "Unknown OS error"},
{IDE_OS_ERR_RETRIEVING, "Unabled to retrieve OS error message"},
{IDS_DRIVERMGR_DRIVER_ERR_INIT, "Driver Manager. Driver '%s' (ID:'%s') initialise failed. %s"},
@@ -142,8 +141,6 @@ const CMICmnResources::SRsrcTextData CMICmnResources::ms_pResourceId2TextData[]
"LLDB Out-of-band. %s. Event handler tried to set new MI Driver running state and failed. %s"},
{IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED,
"LLDB Out-of-band. '%s'. Number of valid breakpoint exceeded %d. Cannot create new breakpoint with ID %d"},
- {IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE,
- "LLDB debug session info. Release some or all of the data shared across command instances failed"},
{IDS_DBGSESSION_ERR_SHARED_DATA_ADD, "LLDB debug session info. Failed to add '%s' data to the shared data command container"},
{IDS_MI_SHTDWN_ERR_LOG, "Log. Error occurred during shutdown. %s"},
{IDS_MI_SHUTDOWN_ERR, "Server shutdown failure. %s"},
@@ -265,7 +262,7 @@ const CMICmnResources::SRsrcTextData CMICmnResources::ms_pResourceId2TextData[]
// Return: None.
// Throws: None.
//--
-CMICmnResources::CMICmnResources(void)
+CMICmnResources::CMICmnResources()
: m_nResourceId2TextDataSize(0)
{
// Do not use this constructor, use Initialize()
@@ -278,7 +275,7 @@ CMICmnResources::CMICmnResources(void)
// Return: None.
// Throws: None.
//--
-CMICmnResources::~CMICmnResources(void)
+CMICmnResources::~CMICmnResources()
{
// Do not use this destructor, use Shutdown()
}
@@ -292,7 +289,7 @@ CMICmnResources::~CMICmnResources(void)
// Throws: None.
//--
bool
-CMICmnResources::Initialize(void)
+CMICmnResources::Initialize()
{
m_clientUsageRefCnt++;
@@ -313,7 +310,7 @@ CMICmnResources::Initialize(void)
// Throws: None.
//--
bool
-CMICmnResources::Shutdown(void)
+CMICmnResources::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -338,7 +335,7 @@ CMICmnResources::Shutdown(void)
// Throws: None.
//--
bool
-CMICmnResources::ReadResourceStringData(void)
+CMICmnResources::ReadResourceStringData()
{
m_nResourceId2TextDataSize = sizeof ms_pResourceId2TextData / sizeof ms_pResourceId2TextData[0];
for (MIuint i = 0; i < m_nResourceId2TextDataSize; i++)
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.h
index 633eba8..dc9c52c 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnResources.h
@@ -50,7 +50,6 @@ enum
IDS_LOG_MEDIUM_ERR_INIT,
IDS_LOG_MEDIUM_ERR_WRITE_ANY,
IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL,
- IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS,
IDS_MEDIUMFILE_NAME,
IDS_MEDIUMFILE_ERR_INVALID_PATH,
@@ -153,7 +152,6 @@ enum
IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE,
IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED,
- IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE,
IDS_DBGSESSION_ERR_SHARED_DATA_ADD,
IDS_MI_SHTDWN_ERR_LOG,
@@ -279,9 +277,6 @@ enum
// Details: MI common code implementation class. Handle application resources
// and locality.
// Singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 29/01/2014.
-// Changes: None.
//--
class CMICmnResources : public CMICmnBase, public MI::ISingleton<CMICmnResources>
{
@@ -289,8 +284,8 @@ class CMICmnResources : public CMICmnBase, public MI::ISingleton<CMICmnResources
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
CMIUtilString GetString(const MIuint vResourceId) const;
bool HasString(const MIuint vResourceId) const;
@@ -317,17 +312,17 @@ class CMICmnResources : public CMICmnBase, public MI::ISingleton<CMICmnResources
// Methods:
private:
- /* ctor */ CMICmnResources(void);
+ /* ctor */ CMICmnResources();
/* ctor */ CMICmnResources(const CMICmnResources &);
void operator=(const CMICmnResources &);
bool GetStringFromResource(const MIuint vResourceId, CMIUtilString &vrwResourceString) const;
- bool ReadResourceStringData(void);
+ bool ReadResourceStringData();
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmnResources(void) override;
+ /* dtor */ ~CMICmnResources() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStderr.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStderr.cpp
index 5a18951..e5c494b 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStderr.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStderr.cpp
@@ -20,7 +20,7 @@
// Return: None.
// Throws: None.
//--
-CMICmnStreamStderr::CMICmnStreamStderr(void)
+CMICmnStreamStderr::CMICmnStreamStderr()
{
}
@@ -31,7 +31,7 @@ CMICmnStreamStderr::CMICmnStreamStderr(void)
// Return: None.
// Throws: None.
//--
-CMICmnStreamStderr::~CMICmnStreamStderr(void)
+CMICmnStreamStderr::~CMICmnStreamStderr()
{
Shutdown();
}
@@ -45,7 +45,7 @@ CMICmnStreamStderr::~CMICmnStreamStderr(void)
// Throws: None.
//--
bool
-CMICmnStreamStderr::Initialize(void)
+CMICmnStreamStderr::Initialize()
{
m_clientUsageRefCnt++;
@@ -76,7 +76,7 @@ CMICmnStreamStderr::Initialize(void)
// Throws: None.
//--
bool
-CMICmnStreamStderr::Shutdown(void)
+CMICmnStreamStderr::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -191,7 +191,7 @@ CMICmnStreamStderr::WritePriv(const CMIUtilString &vText, const CMIUtilString &v
// Throws: None.
//--
bool
-CMICmnStreamStderr::Lock(void)
+CMICmnStreamStderr::Lock()
{
m_mutex.Lock();
return MIstatus::success;
@@ -206,7 +206,7 @@ CMICmnStreamStderr::Lock(void)
// Throws: None.
//--
bool
-CMICmnStreamStderr::Unlock(void)
+CMICmnStreamStderr::Unlock()
{
m_mutex.Unlock();
return MIstatus::success;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStderr.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStderr.h
index afceada..95085a2 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStderr.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStderr.h
@@ -20,9 +20,6 @@
// CMICmnStreamStderr sets up and tears downs stderr for the driver.
//
// Singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 19/03/2014.
-// Changes: None.
//--
class CMICmnStreamStderr : public CMICmnBase, public MI::ISingleton<CMICmnStreamStderr>
{
@@ -35,17 +32,17 @@ class CMICmnStreamStderr : public CMICmnBase, public MI::ISingleton<CMICmnStream
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
//
- bool Lock(void);
- bool Unlock(void);
+ bool Lock();
+ bool Unlock();
bool Write(const CMIUtilString &vText, const bool vbSendToLog = true);
bool WriteLLDBMsg(const CMIUtilString &vText, const bool vbSendToLog = true);
// Methods:
private:
- /* ctor */ CMICmnStreamStderr(void);
+ /* ctor */ CMICmnStreamStderr();
/* ctor */ CMICmnStreamStderr(const CMICmnStreamStderr &);
void operator=(const CMICmnStreamStderr &);
//
@@ -54,7 +51,7 @@ class CMICmnStreamStderr : public CMICmnBase, public MI::ISingleton<CMICmnStream
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmnStreamStderr(void) override;
+ /* dtor */ ~CMICmnStreamStderr() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdin.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdin.cpp
index 891b1c9..60fa49c 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdin.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdin.cpp
@@ -1,4 +1,4 @@
-//===-- MIUtilStreamStdin.cpp -----------------------------------*- C++ -*-===//
+//===-- MICmnStreamStdin.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -28,7 +28,7 @@
// Return: None.
// Throws: None.
//--
-CMICmnStreamStdin::CMICmnStreamStdin(void)
+CMICmnStreamStdin::CMICmnStreamStdin()
: m_strPromptCurrent("(gdb)")
, m_bShowPrompt(true)
, m_pCmdBuffer(nullptr)
@@ -42,7 +42,7 @@ CMICmnStreamStdin::CMICmnStreamStdin(void)
// Return: None.
// Throws: None.
//--
-CMICmnStreamStdin::~CMICmnStreamStdin(void)
+CMICmnStreamStdin::~CMICmnStreamStdin()
{
Shutdown();
}
@@ -56,7 +56,7 @@ CMICmnStreamStdin::~CMICmnStreamStdin(void)
// Throws: None.
//--
bool
-CMICmnStreamStdin::Initialize(void)
+CMICmnStreamStdin::Initialize()
{
m_clientUsageRefCnt++;
@@ -95,7 +95,7 @@ CMICmnStreamStdin::Initialize(void)
// Throws: None.
//--
bool
-CMICmnStreamStdin::Shutdown(void)
+CMICmnStreamStdin::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -158,7 +158,7 @@ CMICmnStreamStdin::SetPrompt(const CMIUtilString &vNewPrompt)
// Throws: None.
//--
const CMIUtilString &
-CMICmnStreamStdin::GetPrompt(void) const
+CMICmnStreamStdin::GetPrompt() const
{
return m_strPromptCurrent;
}
@@ -189,7 +189,7 @@ CMICmnStreamStdin::SetEnablePrompt(const bool vbYes)
// Throws: None.
//--
bool
-CMICmnStreamStdin::GetEnablePrompt(void) const
+CMICmnStreamStdin::GetEnablePrompt() const
{
return m_bShowPrompt;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdin.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdin.h
index 71076d6..a4b12a5 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdin.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdin.h
@@ -1,4 +1,4 @@
-//===-- MIUtilStreamStdin.h -------------------------------------*- C++ -*-===//
+//===-- MICmnStreamStdin.h --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -21,9 +21,6 @@
// provide can receive callbacks when a new line of data is received.
// Each line is determined by a carriage return.
// A singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 10/02/2014.
-// Changes: Factored out OS specific handling of reading stdin - IOR 16/06/2014.
//--
class CMICmnStreamStdin : public CMICmnBase, public MI::ISingleton<CMICmnStreamStdin>
{
@@ -32,25 +29,25 @@ class CMICmnStreamStdin : public CMICmnBase, public MI::ISingleton<CMICmnStreamS
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
//
- const CMIUtilString &GetPrompt(void) const;
+ const CMIUtilString &GetPrompt() const;
bool SetPrompt(const CMIUtilString &vNewPrompt);
void SetEnablePrompt(const bool vbYes);
- bool GetEnablePrompt(void) const;
+ bool GetEnablePrompt() const;
const char *ReadLine(CMIUtilString &vwErrMsg);
// Methods:
private:
- /* ctor */ CMICmnStreamStdin(void);
+ /* ctor */ CMICmnStreamStdin();
/* ctor */ CMICmnStreamStdin(const CMICmnStreamStdin &);
void operator=(const CMICmnStreamStdin &);
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmnStreamStdin(void) override;
+ /* dtor */ ~CMICmnStreamStdin() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdout.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdout.cpp
index 2c93c99..8b65251 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdout.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdout.cpp
@@ -1,4 +1,4 @@
-//===-- MIUtilStreamStdout.cpp ----------------------------------*- C++ -*-===//
+//===-- MICmnStreamStdout.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -20,7 +20,7 @@
// Return: None.
// Throws: None.
//--
-CMICmnStreamStdout::CMICmnStreamStdout(void)
+CMICmnStreamStdout::CMICmnStreamStdout()
{
}
@@ -31,7 +31,7 @@ CMICmnStreamStdout::CMICmnStreamStdout(void)
// Return: None.
// Throws: None.
//--
-CMICmnStreamStdout::~CMICmnStreamStdout(void)
+CMICmnStreamStdout::~CMICmnStreamStdout()
{
Shutdown();
}
@@ -45,7 +45,7 @@ CMICmnStreamStdout::~CMICmnStreamStdout(void)
// Throws: None.
//--
bool
-CMICmnStreamStdout::Initialize(void)
+CMICmnStreamStdout::Initialize()
{
m_clientUsageRefCnt++;
@@ -76,7 +76,7 @@ CMICmnStreamStdout::Initialize(void)
// Throws: None.
//--
bool
-CMICmnStreamStdout::Shutdown(void)
+CMICmnStreamStdout::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -183,7 +183,7 @@ CMICmnStreamStdout::WritePriv(const CMIUtilString &vText, const CMIUtilString &v
// Throws: None.
//--
bool
-CMICmnStreamStdout::Lock(void)
+CMICmnStreamStdout::Lock()
{
m_mutex.Lock();
return MIstatus::success;
@@ -198,7 +198,7 @@ CMICmnStreamStdout::Lock(void)
// Throws: None.
//--
bool
-CMICmnStreamStdout::Unlock(void)
+CMICmnStreamStdout::Unlock()
{
m_mutex.Unlock();
return MIstatus::success;
@@ -229,7 +229,7 @@ CMICmnStreamStdout::TextToStdout(const CMIUtilString &vrTxt)
// Throws: None.
//--
bool
-CMICmnStreamStdout::WritePrompt(void)
+CMICmnStreamStdout::WritePrompt()
{
const CMICmnStreamStdin &rStdinMan = CMICmnStreamStdin::Instance();
if (rStdinMan.GetEnablePrompt())
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdout.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdout.h
index 664faae..9d7f91a 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdout.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnStreamStdout.h
@@ -20,9 +20,6 @@
// CMICmnStreamStdout sets up and tears downs stdout for the driver.
//
// Singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 12/02/2014.
-// Changes: None.
//--
class CMICmnStreamStdout : public CMICmnBase, public MI::ISingleton<CMICmnStreamStdout>
{
@@ -31,21 +28,21 @@ class CMICmnStreamStdout : public CMICmnBase, public MI::ISingleton<CMICmnStream
// Statics:
public:
static bool TextToStdout(const CMIUtilString &vrTxt);
- static bool WritePrompt(void);
+ static bool WritePrompt();
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
//
- bool Lock(void);
- bool Unlock(void);
+ bool Lock();
+ bool Unlock();
bool Write(const CMIUtilString &vText, const bool vbSendToLog = true);
bool WriteMIResponse(const CMIUtilString &vText, const bool vbSendToLog = true);
// Methods:
private:
- /* ctor */ CMICmnStreamStdout(void);
+ /* ctor */ CMICmnStreamStdout();
/* ctor */ CMICmnStreamStdout(const CMICmnStreamStdout &);
void operator=(const CMICmnStreamStdout &);
//
@@ -54,7 +51,7 @@ class CMICmnStreamStdout : public CMICmnBase, public MI::ISingleton<CMICmnStream
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmnStreamStdout(void) override;
+ /* dtor */ ~CMICmnStreamStdout() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnThreadMgrStd.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnThreadMgrStd.cpp
index f0185b8..ec223b8 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnThreadMgrStd.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnThreadMgrStd.cpp
@@ -1,4 +1,4 @@
-//===-- MICmnThreadMgr.cpp --------------------------------------*- C++ -*-===//
+//===-- MICmnThreadMgrStd.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -20,7 +20,7 @@
// Return: None.
// Throws: None.
//--
-CMICmnThreadMgrStd::CMICmnThreadMgrStd(void)
+CMICmnThreadMgrStd::CMICmnThreadMgrStd()
{
}
@@ -31,7 +31,7 @@ CMICmnThreadMgrStd::CMICmnThreadMgrStd(void)
// Return: None.
// Throws: None.
//--
-CMICmnThreadMgrStd::~CMICmnThreadMgrStd(void)
+CMICmnThreadMgrStd::~CMICmnThreadMgrStd()
{
Shutdown();
}
@@ -45,7 +45,7 @@ CMICmnThreadMgrStd::~CMICmnThreadMgrStd(void)
// Throws: None.
//--
bool
-CMICmnThreadMgrStd::Initialize(void)
+CMICmnThreadMgrStd::Initialize()
{
m_clientUsageRefCnt++;
@@ -82,7 +82,7 @@ CMICmnThreadMgrStd::Initialize(void)
// Throws: None.
//--
bool
-CMICmnThreadMgrStd::Shutdown(void)
+CMICmnThreadMgrStd::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -121,7 +121,7 @@ CMICmnThreadMgrStd::Shutdown(void)
// Throws: None.
//--
bool
-CMICmnThreadMgrStd::ThreadAllTerminate(void)
+CMICmnThreadMgrStd::ThreadAllTerminate()
{
ThreadList_t::const_iterator it = m_threadList.begin();
for (; it != m_threadList.end(); ++it)
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnThreadMgrStd.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnThreadMgrStd.h
index fef999b..fc0013f 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnThreadMgrStd.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MICmnThreadMgrStd.h
@@ -25,9 +25,6 @@
// This manager will stop and delete all threads on *this manager's
// shutdown.
// Singleton class.
-// Gotchas: None.
-// Authors: Aidan Dodds 12/03/2014.
-// Changes: None.
//--
class CMICmnThreadMgrStd : public CMICmnBase, public MI::ISingleton<CMICmnThreadMgrStd>
{
@@ -35,10 +32,10 @@ class CMICmnThreadMgrStd : public CMICmnBase, public MI::ISingleton<CMICmnThread
// Methods:
public:
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
bool
- ThreadAllTerminate(void); // Ask all threads to stop (caution)
+ ThreadAllTerminate(); // Ask all threads to stop (caution)
template <typename T> // Ask the thread manager to start and stop threads on our behalf
bool ThreadStart(T &vrwObject);
@@ -48,7 +45,7 @@ class CMICmnThreadMgrStd : public CMICmnBase, public MI::ISingleton<CMICmnThread
// Methods:
private:
- /* ctor */ CMICmnThreadMgrStd(void);
+ /* ctor */ CMICmnThreadMgrStd();
/* ctor */ CMICmnThreadMgrStd(const CMICmnThreadMgrStd &);
void operator=(const CMICmnThreadMgrStd &);
//
@@ -58,7 +55,7 @@ class CMICmnThreadMgrStd : public CMICmnBase, public MI::ISingleton<CMICmnThread
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMICmnThreadMgrStd(void) override;
+ /* dtor */ ~CMICmnThreadMgrStd() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDataTypes.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDataTypes.h
index 33c5b20..d749b0c 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDataTypes.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDataTypes.h
@@ -39,15 +39,6 @@ const bool failure = false;
// Use to avoid "unused parameter" compiler warnings:
#define MIunused(x) (void) x;
-#ifdef _WIN32
-#define MI_NO_INITIALIZE_VTABLE __declspec(novtable)
-#define MI_FORCE_INLINE __forceinline
-#else
-#define MI_NO_INITIALIZE_VTABLE
-#define MI_FORCE_INLINE inline
-// __attribute__( ( always_inline ) )
-#endif // _WIN32
-
// Portability issues
#ifdef _WIN64
typedef unsigned __int64 size_t;
@@ -72,10 +63,3 @@ typedef unsigned int MIuint;
// Fundamentals:
typedef long long MIint64; // 64bit signed integer.
typedef unsigned long long MIuint64; // 64bit unsigned integer.
-
-// using namespace std; // Better to put this or std:: at translation units scope.
-
-//--------------------------------------------------------------------------------------
-// Common routines:
-
-//--------------------------------------------------------------------------------------
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.cpp
index d4a3195..7817237 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.cpp
@@ -45,7 +45,7 @@ const CMIUtilString CMIDriver::ms_constAppNameLong(MIRSRC(IDS_MI_APPNAME_LONG));
// Return: None.
// Throws: None.
//--
-CMIDriver::CMIDriver(void)
+CMIDriver::CMIDriver()
: m_bFallThruToOtherDriverEnabled(false)
, m_bDriverIsExiting(false)
, m_handleMainThread(0)
@@ -66,7 +66,7 @@ CMIDriver::CMIDriver(void)
// Return: None.
// Throws: None.
//--
-CMIDriver::~CMIDriver(void)
+CMIDriver::~CMIDriver()
{
}
@@ -97,7 +97,7 @@ CMIDriver::SetEnableFallThru(const bool vbYes)
// Throws: None.
//--
bool
-CMIDriver::GetEnableFallThru(void) const
+CMIDriver::GetEnableFallThru() const
{
return m_bFallThruToOtherDriverEnabled;
}
@@ -110,7 +110,7 @@ CMIDriver::GetEnableFallThru(void) const
// Throws: None.
//--
const CMIUtilString &
-CMIDriver::GetAppNameShort(void) const
+CMIDriver::GetAppNameShort() const
{
return ms_constAppNameShort;
}
@@ -123,7 +123,7 @@ CMIDriver::GetAppNameShort(void) const
// Throws: None.
//--
const CMIUtilString &
-CMIDriver::GetAppNameLong(void) const
+CMIDriver::GetAppNameLong() const
{
return ms_constAppNameLong;
}
@@ -136,7 +136,7 @@ CMIDriver::GetAppNameLong(void) const
// Throws: None.
//--
const CMIUtilString &
-CMIDriver::GetVersionDescription(void) const
+CMIDriver::GetVersionDescription() const
{
return ms_constMIVersion;
}
@@ -150,7 +150,7 @@ CMIDriver::GetVersionDescription(void) const
// Throws: None.
//--
bool
-CMIDriver::Initialize(void)
+CMIDriver::Initialize()
{
m_eCurrentDriverState = eDriverState_Initialising;
m_clientUsageRefCnt++;
@@ -199,7 +199,7 @@ CMIDriver::Initialize(void)
// Throws: None.
//--
bool
-CMIDriver::Shutdown(void)
+CMIDriver::Shutdown()
{
if (--m_clientUsageRefCnt > 0)
return MIstatus::success;
@@ -260,7 +260,7 @@ CMIDriver::WriteMessageToLog(const CMIUtilString &vMessage)
// Throws: None.
//--
bool
-CMIDriver::DoInitialize(void)
+CMIDriver::DoInitialize()
{
return CMIDriver::Instance().Initialize();
}
@@ -275,7 +275,7 @@ CMIDriver::DoInitialize(void)
// Throws: None.
//--
bool
-CMIDriver::DoShutdown(void)
+CMIDriver::DoShutdown()
{
return CMIDriver::Instance().Shutdown();
}
@@ -288,7 +288,7 @@ CMIDriver::DoShutdown(void)
// Throws: None.
//--
const CMIUtilString &
-CMIDriver::GetName(void) const
+CMIDriver::GetName() const
{
const CMIUtilString &rName = GetAppNameLong();
const CMIUtilString &rVsn = GetVersionDescription();
@@ -305,7 +305,7 @@ CMIDriver::GetName(void) const
// Throws: None.
//--
CMIUtilString
-CMIDriver::GetError(void) const
+CMIDriver::GetError() const
{
return GetErrorDescription();
}
@@ -318,7 +318,7 @@ CMIDriver::GetError(void) const
// Throws: None.
//--
lldb::SBDebugger &
-CMIDriver::GetTheDebugger(void)
+CMIDriver::GetTheDebugger()
{
return m_rLldbDebugger.GetTheDebugger();
}
@@ -465,7 +465,7 @@ CMIDriver::ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &v
// Throws: None.
//--
bool
-CMIDriver::GetDriverIsGDBMICompatibleDriver(void) const
+CMIDriver::GetDriverIsGDBMICompatibleDriver() const
{
return true;
}
@@ -479,7 +479,7 @@ CMIDriver::GetDriverIsGDBMICompatibleDriver(void) const
// Throws: None.
//--
bool
-CMIDriver::StartWorkerThreads(void)
+CMIDriver::StartWorkerThreads()
{
bool bOk = MIstatus::success;
@@ -507,7 +507,7 @@ CMIDriver::StartWorkerThreads(void)
// Throws: None.
//--
bool
-CMIDriver::StopWorkerThreads(void)
+CMIDriver::StopWorkerThreads()
{
CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance();
return rThreadMgr.ThreadAllTerminate();
@@ -523,7 +523,7 @@ CMIDriver::StopWorkerThreads(void)
// Throws: None.
//--
bool
-CMIDriver::DoMainLoop(void)
+CMIDriver::DoMainLoop()
{
if (!InitClientIDEToMIDriver()) // Init Eclipse IDE
{
@@ -607,7 +607,7 @@ CMIDriver::DoMainLoop(void)
// Throws: None.
//--
bool
-CMIDriver::DoAppQuit(void)
+CMIDriver::DoAppQuit()
{
bool bYesQuit = true;
@@ -675,7 +675,7 @@ CMIDriver::InterpretCommandFallThruDriver(const CMIUtilString &vTextLine, bool &
// Throws: None.
//--
const CMIUtilString &
-CMIDriver::GetDriverName(void) const
+CMIDriver::GetDriverName() const
{
return GetName();
}
@@ -688,7 +688,7 @@ CMIDriver::GetDriverName(void) const
// Throws: None.
//--
const CMIUtilString &
-CMIDriver::GetDriverId(void) const
+CMIDriver::GetDriverId() const
{
return GetId();
}
@@ -727,7 +727,7 @@ CMIDriver::DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &v
// Throws: None.
//--
FILE *
-CMIDriver::GetStdin(void) const
+CMIDriver::GetStdin() const
{
// Note this fn is called on CMIDriverMgr register driver so stream has to be
// available before *this driver has been initialized! Flaw?
@@ -746,7 +746,7 @@ CMIDriver::GetStdin(void) const
// Throws: None.
//--
FILE *
-CMIDriver::GetStdout(void) const
+CMIDriver::GetStdout() const
{
// Note this fn is called on CMIDriverMgr register driver so stream has to be
// available before *this driver has been initialized! Flaw?
@@ -764,7 +764,7 @@ CMIDriver::GetStdout(void) const
// Throws: None.
//--
FILE *
-CMIDriver::GetStderr(void) const
+CMIDriver::GetStderr() const
{
// Note this fn is called on CMIDriverMgr register driver so stream has to be
// available before *this driver has been initialized! Flaw?
@@ -803,7 +803,7 @@ CMIDriver::SetId(const CMIUtilString &vId)
// Throws: None.
//--
const CMIUtilString &
-CMIDriver::GetId(void) const
+CMIDriver::GetId() const
{
return m_strDriverId;
}
@@ -893,7 +893,7 @@ CMIDriver::WrapCLICommandIntoMICommand(const CMIUtilString &vTextLine) const
const std::string vToken(vTextLine.begin(), vTextLine.begin() + nCommandOffset);
// 001target create "/path/to/file"
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- CLI command
- const CMIUtilString vCliCommand(std::string(vTextLine, nCommandOffset).c_str());
+ const CMIUtilString vCliCommand(std::string(vTextLine, nCommandOffset));
// 5. Escape special characters and embed the command in a string
// Result: it looks like -- target create \"/path/to/file\".
@@ -1033,7 +1033,7 @@ CMIDriver::SetExitApplicationFlag(const bool vbForceExit)
// Throws: None.
//--
bool
-CMIDriver::GetExitApplicationFlag(void) const
+CMIDriver::GetExitApplicationFlag() const
{
return m_bExitApp;
}
@@ -1046,7 +1046,7 @@ CMIDriver::GetExitApplicationFlag(void) const
// Throws: None.
//--
CMIDriver::DriverState_e
-CMIDriver::GetCurrentDriverState(void) const
+CMIDriver::GetCurrentDriverState() const
{
return m_eCurrentDriverState;
}
@@ -1061,7 +1061,7 @@ CMIDriver::GetCurrentDriverState(void) const
// Throws: None.
//--
bool
-CMIDriver::SetDriverStateRunningNotDebugging(void)
+CMIDriver::SetDriverStateRunningNotDebugging()
{
// CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
@@ -1110,7 +1110,7 @@ CMIDriver::SetDriverStateRunningNotDebugging(void)
// Throws: None.
//--
bool
-CMIDriver::SetDriverStateRunningDebugging(void)
+CMIDriver::SetDriverStateRunningDebugging()
{
// CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
@@ -1157,7 +1157,7 @@ CMIDriver::SetDriverStateRunningDebugging(void)
// Throws: None.
//--
bool
-CMIDriver::InitClientIDEToMIDriver(void) const
+CMIDriver::InitClientIDEToMIDriver() const
{
// Put other IDE init functions here
return InitClientIDEEclipse();
@@ -1174,7 +1174,7 @@ CMIDriver::InitClientIDEToMIDriver(void) const
// Throws: None.
//--
bool
-CMIDriver::InitClientIDEEclipse(void) const
+CMIDriver::InitClientIDEEclipse() const
{
return CMICmnStreamStdout::WritePrompt();
}
@@ -1191,7 +1191,7 @@ CMIDriver::InitClientIDEEclipse(void) const
// Throws: None.
//--
bool
-CMIDriver::HaveExecutableFileNamePathOnCmdLine(void) const
+CMIDriver::HaveExecutableFileNamePathOnCmdLine() const
{
return m_bHaveExecutableFileNamePathOnCmdLine;
}
@@ -1205,7 +1205,7 @@ CMIDriver::HaveExecutableFileNamePathOnCmdLine(void) const
// Throws: None.
//--
const CMIUtilString &
-CMIDriver::GetExecutableFileNamePathOnCmdLine(void) const
+CMIDriver::GetExecutableFileNamePathOnCmdLine() const
{
return m_strCmdLineArgExecuteableFileNamePath;
}
@@ -1221,7 +1221,7 @@ CMIDriver::GetExecutableFileNamePathOnCmdLine(void) const
// Throws: None.
//--
bool
-CMIDriver::LocalDebugSessionStartupExecuteCommands(void)
+CMIDriver::LocalDebugSessionStartupExecuteCommands()
{
const CMIUtilString strCmd(CMIUtilString::Format("-file-exec-and-symbols \"%s\"", m_strCmdLineArgExecuteableFileNamePath.AddSlashes().c_str()));
bool bOk = CMICmnStreamStdout::TextToStdout(strCmd);
@@ -1239,7 +1239,7 @@ CMIDriver::LocalDebugSessionStartupExecuteCommands(void)
// Throws: None.
//--
void
-CMIDriver::SetDriverDebuggingArgExecutable(void)
+CMIDriver::SetDriverDebuggingArgExecutable()
{
m_bDriverDebuggingArgExecutable = true;
}
@@ -1254,7 +1254,7 @@ CMIDriver::SetDriverDebuggingArgExecutable(void)
// Throws: None.
//--
bool
-CMIDriver::IsDriverDebuggingArgExecutable(void) const
+CMIDriver::IsDriverDebuggingArgExecutable() const
{
return m_bDriverDebuggingArgExecutable;
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.h
index 55c6624..a90c31f 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriver.h
@@ -32,9 +32,6 @@ class CMICmnStreamStdout;
// work depending on the one selected to work. A driver can if not able
// to handle an instruction or 'command' can pass that command onto
// another driver object registered with the Driver Manager.
-// Gotchas: None.
-// Authors: Illya Rudkin 29/01/2014.
-// Changes: None.
//--
class CMIDriver : public CMICmnBase,
public CMIDriverMgr::IDriver,
@@ -68,51 +65,51 @@ class CMIDriver : public CMICmnBase,
// Methods:
public:
// MI system
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
// MI state
- bool GetExitApplicationFlag(void) const;
- DriverState_e GetCurrentDriverState(void) const;
- bool SetDriverStateRunningNotDebugging(void);
- bool SetDriverStateRunningDebugging(void);
- void SetDriverDebuggingArgExecutable(void);
- bool IsDriverDebuggingArgExecutable(void) const;
+ bool GetExitApplicationFlag() const;
+ DriverState_e GetCurrentDriverState() const;
+ bool SetDriverStateRunningNotDebugging();
+ bool SetDriverStateRunningDebugging();
+ void SetDriverDebuggingArgExecutable();
+ bool IsDriverDebuggingArgExecutable() const;
// MI information about itself
- const CMIUtilString &GetAppNameShort(void) const;
- const CMIUtilString &GetAppNameLong(void) const;
- const CMIUtilString &GetVersionDescription(void) const;
+ const CMIUtilString &GetAppNameShort() const;
+ const CMIUtilString &GetAppNameLong() const;
+ const CMIUtilString &GetVersionDescription() const;
// MI do work
bool WriteMessageToLog(const CMIUtilString &vMessage);
bool SetEnableFallThru(const bool vbYes);
- bool GetEnableFallThru(void) const;
- bool HaveExecutableFileNamePathOnCmdLine(void) const;
- const CMIUtilString &GetExecutableFileNamePathOnCmdLine(void) const;
+ bool GetEnableFallThru() const;
+ bool HaveExecutableFileNamePathOnCmdLine() const;
+ const CMIUtilString &GetExecutableFileNamePathOnCmdLine() const;
// Overridden:
public:
// From CMIDriverMgr::IDriver
- bool DoInitialize(void) override;
- bool DoShutdown(void) override;
- bool DoMainLoop(void) override;
+ bool DoInitialize() override;
+ bool DoShutdown() override;
+ bool DoMainLoop() override;
lldb::SBError DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) override;
- CMIUtilString GetError(void) const override;
- const CMIUtilString &GetName(void) const override;
- lldb::SBDebugger &GetTheDebugger(void) override;
- bool GetDriverIsGDBMICompatibleDriver(void) const override;
+ CMIUtilString GetError() const override;
+ const CMIUtilString &GetName() const override;
+ lldb::SBDebugger &GetTheDebugger() override;
+ bool GetDriverIsGDBMICompatibleDriver() const override;
bool SetId(const CMIUtilString &vId) override;
- const CMIUtilString &GetId(void) const override;
+ const CMIUtilString &GetId() const override;
// From CMIDriverBase
void SetExitApplicationFlag(const bool vbForceExit) override;
bool DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg) override;
bool SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver) override;
- FILE *GetStdin(void) const override;
- FILE *GetStdout(void) const override;
- FILE *GetStderr(void) const override;
- const CMIUtilString &GetDriverName(void) const override;
- const CMIUtilString &GetDriverId(void) const override;
+ FILE *GetStdin() const override;
+ FILE *GetStdout() const override;
+ FILE *GetStderr() const override;
+ const CMIUtilString &GetDriverName() const override;
+ const CMIUtilString &GetDriverId() const override;
void DeliverSignal(int signal) override;
// Typedefs:
@@ -121,28 +118,28 @@ class CMIDriver : public CMICmnBase,
// Methods:
private:
- /* ctor */ CMIDriver(void);
+ /* ctor */ CMIDriver();
/* ctor */ CMIDriver(const CMIDriver &);
void operator=(const CMIDriver &);
lldb::SBError ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting);
- bool DoAppQuit(void);
+ bool DoAppQuit();
bool InterpretCommand(const CMIUtilString &vTextLine);
bool InterpretCommandThisDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid);
CMIUtilString WrapCLICommandIntoMICommand(const CMIUtilString &vTextLine) const;
bool InterpretCommandFallThruDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid);
bool ExecuteCommand(const SMICmdData &vCmdData);
- bool StartWorkerThreads(void);
- bool StopWorkerThreads(void);
- bool InitClientIDEToMIDriver(void) const;
- bool InitClientIDEEclipse(void) const;
- bool LocalDebugSessionStartupExecuteCommands(void);
+ bool StartWorkerThreads();
+ bool StopWorkerThreads();
+ bool InitClientIDEToMIDriver() const;
+ bool InitClientIDEEclipse() const;
+ bool LocalDebugSessionStartupExecuteCommands();
bool ExecuteCommandFile(const bool vbAsyncMode);
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMIDriver(void) override;
+ /* dtor */ ~CMIDriver() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverBase.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverBase.cpp
index 6bf5ab6..6738497 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverBase.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverBase.cpp
@@ -21,7 +21,7 @@
// Return: None.
// Throws: None.
//--
-CMIDriverBase::CMIDriverBase(void)
+CMIDriverBase::CMIDriverBase()
: m_pDriverFallThru(nullptr)
, m_pDriverParent(nullptr)
, m_bExitApp(false)
@@ -35,7 +35,7 @@ CMIDriverBase::CMIDriverBase(void)
// Return: None.
// Throws: None.
//--
-CMIDriverBase::~CMIDriverBase(void)
+CMIDriverBase::~CMIDriverBase()
{
m_pDriverFallThru = NULL;
}
@@ -107,7 +107,7 @@ CMIDriverBase::SetDriverParent(const CMIDriverBase &vrOtherDriver)
// Throws: None.
//--
CMIDriverBase *
-CMIDriverBase::GetDriversParent(void) const
+CMIDriverBase::GetDriversParent() const
{
return m_pDriverParent;
}
@@ -122,7 +122,7 @@ CMIDriverBase::GetDriversParent(void) const
// Throws: None.
//--
CMIDriverBase *
-CMIDriverBase::GetDriverToFallThruTo(void) const
+CMIDriverBase::GetDriverToFallThruTo() const
{
return m_pDriverFallThru;
}
@@ -137,7 +137,7 @@ CMIDriverBase::GetDriverToFallThruTo(void) const
// Throws: None.
//--
FILE *
-CMIDriverBase::GetStdin(void) const
+CMIDriverBase::GetStdin() const
{
// Do nothing - override and implement
return nullptr;
@@ -152,7 +152,7 @@ CMIDriverBase::GetStdin(void) const
// Throws: None.
//--
FILE *
-CMIDriverBase::GetStdout(void) const
+CMIDriverBase::GetStdout() const
{
// Do nothing - override and implement
return nullptr;
@@ -167,7 +167,7 @@ CMIDriverBase::GetStdout(void) const
// Throws: None.
//--
FILE *
-CMIDriverBase::GetStderr(void) const
+CMIDriverBase::GetStderr() const
{
// Do nothing - override and implement
return nullptr;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverBase.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverBase.h
index ad24211..9be407e 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverBase.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverBase.h
@@ -31,34 +31,31 @@ class SBBroadcaster;
// CDriverMgr to manage either (any) driver to be operated on.
// Each driver instance (the CMIDriver, LLDB::Driver) has its own
// LLDB::SBDebugger object.
-// Gotchas: None.
-// Authors: Illya Rudkin 30/01/2014.
-// Changes: None.
//--
class CMIDriverBase
{
// Methods:
public:
- /* ctor */ CMIDriverBase(void);
+ /* ctor */ CMIDriverBase();
- CMIDriverBase *GetDriverToFallThruTo(void) const;
- CMIDriverBase *GetDriversParent(void) const;
+ CMIDriverBase *GetDriverToFallThruTo() const;
+ CMIDriverBase *GetDriversParent() const;
// Overrideable:
public:
- /* dtor */ virtual ~CMIDriverBase(void);
+ /* dtor */ virtual ~CMIDriverBase();
virtual bool DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg);
virtual bool SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver);
virtual bool SetDriverParent(const CMIDriverBase &vrOtherDriver);
- virtual const CMIUtilString &GetDriverName(void) const = 0;
- virtual const CMIUtilString &GetDriverId(void) const = 0;
+ virtual const CMIUtilString &GetDriverName() const = 0;
+ virtual const CMIUtilString &GetDriverId() const = 0;
virtual void SetExitApplicationFlag(const bool vbForceExit);
// MI provide information for the pass through (child) assigned driver
- virtual FILE *GetStdin(void) const;
- virtual FILE *GetStdout(void) const;
- virtual FILE *GetStderr(void) const;
+ virtual FILE *GetStdin() const;
+ virtual FILE *GetStdout() const;
+ virtual FILE *GetStderr() const;
// Attributes:
protected:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMain.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMain.cpp
index 2f469bf..ccbaf77 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMain.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMain.cpp
@@ -89,7 +89,7 @@ sigint_handler(int vSigno)
// Throws: None.
//--
bool
-DriverSystemInit(void)
+DriverSystemInit()
{
bool bOk = MIstatus::success;
CMIDriver &rMIDriver = CMIDriver::Instance();
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.cpp
index f4987db..472fc60 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.cpp
@@ -26,7 +26,7 @@
// Return: None.
// Throws: None.
//--
-CMIDriverMgr::CMIDriverMgr(void)
+CMIDriverMgr::CMIDriverMgr()
: m_pDriverCurrent(nullptr)
, m_bInMi2Mode(false)
{
@@ -39,7 +39,7 @@ CMIDriverMgr::CMIDriverMgr(void)
// Return: None.
// Throws: None.
//--
-CMIDriverMgr::~CMIDriverMgr(void)
+CMIDriverMgr::~CMIDriverMgr()
{
Shutdown();
}
@@ -53,7 +53,7 @@ CMIDriverMgr::~CMIDriverMgr(void)
// Throws: None.
//--
bool
-CMIDriverMgr::Initialize(void)
+CMIDriverMgr::Initialize()
{
m_clientUsageRefCnt++;
@@ -91,7 +91,7 @@ CMIDriverMgr::Initialize(void)
// Throws: None.
//--
bool
-CMIDriverMgr::Shutdown(void)
+CMIDriverMgr::Shutdown()
{
// Do not want a ref counter because this function needs to be called how ever this
// application stops running
@@ -132,7 +132,7 @@ CMIDriverMgr::Shutdown(void)
// Throws: None.
//--
bool
-CMIDriverMgr::UnregisterDriverAll(void)
+CMIDriverMgr::UnregisterDriverAll()
{
MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
while (it != m_mapDriverIdToDriver.end())
@@ -273,7 +273,7 @@ CMIDriverMgr::SetUseThisDriverToDoWork(const IDriver &vrADriver)
// Throws: None.
//--
CMIDriverMgr::IDriver *
-CMIDriverMgr::GetUseThisDriverToDoWork(void) const
+CMIDriverMgr::GetUseThisDriverToDoWork() const
{
return m_pDriverCurrent;
}
@@ -287,7 +287,7 @@ CMIDriverMgr::GetUseThisDriverToDoWork(void) const
// Throws: None.
//--
bool
-CMIDriverMgr::DriverMainLoop(void)
+CMIDriverMgr::DriverMainLoop()
{
if (m_pDriverCurrent != nullptr)
{
@@ -300,7 +300,7 @@ CMIDriverMgr::DriverMainLoop(void)
}
else
{
- const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)));
+ const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
CMICmnStreamStdout::Instance().Write(errMsg, true);
return MIstatus::failure;
}
@@ -327,7 +327,7 @@ CMIDriverMgr::DriverParseArgs(const int argc, const char *argv[], FILE *vpStdOut
{
if (m_pDriverCurrent == nullptr)
{
- const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)));
+ const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
CMICmnStreamStdout::Instance().Write(errMsg, true);
return MIstatus::failure;
}
@@ -357,13 +357,13 @@ CMIDriverMgr::DriverParseArgs(const int argc, const char *argv[], FILE *vpStdOut
// Throws: None.
//--
CMIUtilString
-CMIDriverMgr::DriverGetError(void) const
+CMIDriverMgr::DriverGetError() const
{
if (m_pDriverCurrent != nullptr)
return m_pDriverCurrent->GetError();
else
{
- const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)));
+ const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
CMICmnStreamStdout::Instance().Write(errMsg, true);
}
@@ -379,13 +379,13 @@ CMIDriverMgr::DriverGetError(void) const
// Throws: None.
//--
CMIUtilString
-CMIDriverMgr::DriverGetName(void) const
+CMIDriverMgr::DriverGetName() const
{
if (m_pDriverCurrent != nullptr)
return m_pDriverCurrent->GetName();
else
{
- const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)));
+ const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
CMICmnStreamStdout::Instance().Write(errMsg, true);
}
@@ -401,14 +401,14 @@ CMIDriverMgr::DriverGetName(void) const
// Throws: None.
//--
lldb::SBDebugger *
-CMIDriverMgr::DriverGetTheDebugger(void)
+CMIDriverMgr::DriverGetTheDebugger()
{
lldb::SBDebugger *pDebugger = nullptr;
if (m_pDriverCurrent != nullptr)
pDebugger = &m_pDriverCurrent->GetTheDebugger();
else
{
- const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)));
+ const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
CMICmnStreamStdout::Instance().Write(errMsg, true);
}
@@ -598,7 +598,7 @@ CMIDriverMgr::ParseArgs(const int argc, const char *argv[], bool &vwbExiting)
// Throws: None.
//--
CMIUtilString
-CMIDriverMgr::GetAppVersion(void) const
+CMIDriverMgr::GetAppVersion() const
{
const CMIUtilString strProj(MIRSRC(IDS_PROJNAME));
const CMIUtilString strVsn(CMIDriver::Instance().GetVersionDescription());
@@ -616,7 +616,7 @@ CMIDriverMgr::GetAppVersion(void) const
// Throws: None.
//--
CMIUtilString
-CMIDriverMgr::GetHelpOnCmdLineArgOptions(void) const
+CMIDriverMgr::GetHelpOnCmdLineArgOptions() const
{
const CMIUtilString pHelp[] = {
MIRSRC(IDE_MI_APP_DESCRIPTION),
@@ -653,7 +653,7 @@ CMIDriverMgr::GetHelpOnCmdLineArgOptions(void) const
// Throws: None.
//--
CMIDriverMgr::IDriver *
-CMIDriverMgr::GetFirstMIDriver(void) const
+CMIDriverMgr::GetFirstMIDriver() const
{
IDriver *pDriver = nullptr;
MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
@@ -684,7 +684,7 @@ CMIDriverMgr::GetFirstMIDriver(void) const
// Throws: None.
//--
CMIDriverMgr::IDriver *
-CMIDriverMgr::GetFirstNonMIDriver(void) const
+CMIDriverMgr::GetFirstNonMIDriver() const
{
IDriver *pDriver = nullptr;
MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.h
index c84ef04..016e722 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIDriverMgr.h
@@ -39,9 +39,6 @@
// Each driver instance (the CMIDriver, LLDB::Driver) has its own
// LLDB::SBDebugger.
// Singleton class.
-// Gotchas: None.
-// Authors: Illya Rudkin 28/02/2014.
-// Changes: None.
//--
class CMIDriverMgr : public CMICmnBase, public MI::ISingleton<CMIDriverMgr>
{
@@ -56,43 +53,43 @@ class CMIDriverMgr : public CMICmnBase, public MI::ISingleton<CMIDriverMgr>
class IDriver
{
public:
- virtual bool DoInitialize(void) = 0;
- virtual bool DoShutdown(void) = 0;
- virtual bool DoMainLoop(void) = 0;
+ virtual bool DoInitialize() = 0;
+ virtual bool DoShutdown() = 0;
+ virtual bool DoMainLoop() = 0;
virtual lldb::SBError DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) = 0;
- virtual CMIUtilString GetError(void) const = 0;
- virtual const CMIUtilString &GetName(void) const = 0;
- virtual lldb::SBDebugger &GetTheDebugger(void) = 0;
- virtual bool GetDriverIsGDBMICompatibleDriver(void) const = 0;
+ virtual CMIUtilString GetError() const = 0;
+ virtual const CMIUtilString &GetName() const = 0;
+ virtual lldb::SBDebugger &GetTheDebugger() = 0;
+ virtual bool GetDriverIsGDBMICompatibleDriver() const = 0;
virtual bool SetId(const CMIUtilString &vId) = 0;
- virtual const CMIUtilString &GetId(void) const = 0;
+ virtual const CMIUtilString &GetId() const = 0;
virtual void DeliverSignal(int signal) = 0;
// Not part of the interface, ignore
- /* dtor */ virtual ~IDriver(void) {}
+ /* dtor */ virtual ~IDriver() {}
};
// Methods:
public:
// MI system
- bool Initialize(void) override;
- bool Shutdown(void) override;
+ bool Initialize() override;
+ bool Shutdown() override;
//
- CMIUtilString GetAppVersion(void) const;
+ CMIUtilString GetAppVersion() const;
bool RegisterDriver(const IDriver &vrADriver, const CMIUtilString &vrDriverID);
bool UnregisterDriver(const IDriver &vrADriver);
bool
SetUseThisDriverToDoWork(const IDriver &vrADriver); // Specify working main driver
- IDriver *GetUseThisDriverToDoWork(void) const;
+ IDriver *GetUseThisDriverToDoWork() const;
bool ParseArgs(const int argc, const char *argv[], bool &vwbExiting);
IDriver *GetDriver(const CMIUtilString &vrDriverId) const;
//
// MI Proxy fn to current specified working driver
- bool DriverMainLoop(void);
+ bool DriverMainLoop();
bool DriverParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting);
- CMIUtilString DriverGetError(void) const;
- CMIUtilString DriverGetName(void) const;
- lldb::SBDebugger *DriverGetTheDebugger(void);
+ CMIUtilString DriverGetError() const;
+ CMIUtilString DriverGetName() const;
+ lldb::SBDebugger *DriverGetTheDebugger();
void DeliverSignal(int signal);
// Typedef:
@@ -102,20 +99,20 @@ class CMIDriverMgr : public CMICmnBase, public MI::ISingleton<CMIDriverMgr>
// Methods:
private:
- /* ctor */ CMIDriverMgr(void);
+ /* ctor */ CMIDriverMgr();
/* ctor */ CMIDriverMgr(const CMIDriverMgr &);
void operator=(const CMIDriverMgr &);
//
bool HaveDriverAlready(const IDriver &vrMedium) const;
- bool UnregisterDriverAll(void);
- IDriver *GetFirstMIDriver(void) const;
- IDriver *GetFirstNonMIDriver(void) const;
- CMIUtilString GetHelpOnCmdLineArgOptions(void) const;
+ bool UnregisterDriverAll();
+ IDriver *GetFirstMIDriver() const;
+ IDriver *GetFirstNonMIDriver() const;
+ CMIUtilString GetHelpOnCmdLineArgOptions() const;
// Overridden:
private:
// From CMICmnBase
- /* dtor */ ~CMIDriverMgr(void) override;
+ /* dtor */ ~CMIDriverMgr() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIExtensions.txt b/contrib/llvm/tools/lldb/tools/lldb-mi/MIExtensions.txt
index 966cb2f..70508b1 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIExtensions.txt
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIExtensions.txt
@@ -83,21 +83,22 @@ Example:
# =library-loaded notification
-The =library-loaded notification has 3 extra fields:
+The =library-loaded notification has 4 extra fields:
symbols-loaded - indicates that there are symbols for the loaded library
symbols-path - if symbols are exist then it contains a path for symbols of the loaded library
loaded_addr - contains an address of the loaded library or "-" if address isn't resolved yet
+ size - contains the size in bytes of the section loaded at 'loaded_addr'
For example:
- =library-loaded,id="/Users/IliaK/p/hello",target-name="/Users/IliaK/p/hello",host-name="/Users/IliaK/p/hello",symbols-loaded="1",symbols-path="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello",loaded_addr="-"
- =library-loaded,id="/usr/lib/dyld",target-name="/usr/lib/dyld",host-name="/usr/lib/dyld",symbols-loaded="0",loaded_addr="0x00007fff5fc00000"
+ =library-loaded,id="/Users/IliaK/p/hello",target-name="/Users/IliaK/p/hello",host-name="/Users/IliaK/p/hello",symbols-loaded="1",symbols-path="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello",loaded_addr="-",size="4096"
+ =library-loaded,id="/usr/lib/dyld",target-name="/usr/lib/dyld",host-name="/usr/lib/dyld",symbols-loaded="0",loaded_addr="0x00007fff5fc00000",size="4096"
# -target-attach
Synopsis
Additional syntax provided by lldb-mi:
- -target-attach -n <executable-name> [--waitfor]
+ -target-attach -n <executable-name> [--waitfor]
Attach to an executable. Using -n allows specifying an executable name to attach to.
Using this with --watifor can do a deffered attach. The flags -n and --waitfor match the syntax of lldb proper's 'process attach' command.
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDateTimeStd.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDateTimeStd.cpp
index 995441f..db730da 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDateTimeStd.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDateTimeStd.cpp
@@ -18,7 +18,7 @@
// Return: None.
// Throws: None.
//--
-CMIUtilDateTimeStd::CMIUtilDateTimeStd(void)
+CMIUtilDateTimeStd::CMIUtilDateTimeStd()
{
}
@@ -29,7 +29,7 @@ CMIUtilDateTimeStd::CMIUtilDateTimeStd(void)
// Return: None.
// Throws: None.
//--
-CMIUtilDateTimeStd::~CMIUtilDateTimeStd(void)
+CMIUtilDateTimeStd::~CMIUtilDateTimeStd()
{
}
@@ -41,7 +41,7 @@ CMIUtilDateTimeStd::~CMIUtilDateTimeStd(void)
// Throws: None.
//--
CMIUtilString
-CMIUtilDateTimeStd::GetDate(void)
+CMIUtilDateTimeStd::GetDate()
{
CMIUtilString strDate(MIRSRC(IDS_WORD_INVALIDBRKTS));
@@ -61,7 +61,7 @@ CMIUtilDateTimeStd::GetDate(void)
// Throws: None.
//--
CMIUtilString
-CMIUtilDateTimeStd::GetTime(void)
+CMIUtilDateTimeStd::GetTime()
{
std::time(&m_rawTime);
const std::tm *pTi = std::localtime(&m_rawTime);
@@ -80,7 +80,7 @@ CMIUtilDateTimeStd::GetTime(void)
// Throws: None.
//--
CMIUtilString
-CMIUtilDateTimeStd::GetDateTimeLogFilename(void)
+CMIUtilDateTimeStd::GetDateTimeLogFilename()
{
std::time(&m_rawTime);
const std::tm *pTi = std::localtime(&m_rawTime);
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDateTimeStd.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDateTimeStd.h
index 4bc5e58..cb5f498 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDateTimeStd.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDateTimeStd.h
@@ -18,24 +18,21 @@
//++ ============================================================================
// Details: MI common code utility class. Used to retrieve system local date
// time.
-// Gotchas: None.
-// Authors: Illya Rudkin 16/07/2014.
-// Changes: None.
//--
class CMIUtilDateTimeStd
{
// Methods:
public:
- /* ctor */ CMIUtilDateTimeStd(void);
+ /* ctor */ CMIUtilDateTimeStd();
- CMIUtilString GetDate(void);
- CMIUtilString GetTime(void);
- CMIUtilString GetDateTimeLogFilename(void);
+ CMIUtilString GetDate();
+ CMIUtilString GetTime();
+ CMIUtilString GetDateTimeLogFilename();
// Overrideable:
public:
// From CMICmnBase
- /* dtor */ virtual ~CMIUtilDateTimeStd(void);
+ /* dtor */ virtual ~CMIUtilDateTimeStd();
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDebug.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDebug.cpp
index f7d461b..d49aaa2 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDebug.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDebug.cpp
@@ -24,7 +24,7 @@
// Return: None.
// Throws: None.
//--
-CMIUtilDebug::CMIUtilDebug(void)
+CMIUtilDebug::CMIUtilDebug()
{
}
@@ -35,7 +35,7 @@ CMIUtilDebug::CMIUtilDebug(void)
// Return: None.
// Throws: None.
//--
-CMIUtilDebug::~CMIUtilDebug(void)
+CMIUtilDebug::~CMIUtilDebug()
{
}
@@ -48,7 +48,7 @@ CMIUtilDebug::~CMIUtilDebug(void)
// Throws: None.
//--
void
-CMIUtilDebug::ShowDlgWaitForDbgAttach(void)
+CMIUtilDebug::ShowDlgWaitForDbgAttach()
{
const CMIUtilString strCaption(CMIDriver::Instance().GetAppNameShort());
#ifdef _WIN32
@@ -71,7 +71,7 @@ CMIUtilDebug::ShowDlgWaitForDbgAttach(void)
// Throws: None.
//--
void
-CMIUtilDebug::WaitForDbgAttachInfinteLoop(void)
+CMIUtilDebug::WaitForDbgAttachInfinteLoop()
{
MIuint i = 0;
while (i == 0)
@@ -110,7 +110,7 @@ CMIUtilDebugFnTrace::CMIUtilDebugFnTrace(const CMIUtilString &vFnName)
// Return: None.
// Throws: None.
//--
-CMIUtilDebugFnTrace::~CMIUtilDebugFnTrace(void)
+CMIUtilDebugFnTrace::~CMIUtilDebugFnTrace()
{
const CMIUtilString txt(CMIUtilString::Format("%d<%s", ms_fnDepthCnt--, m_strFnName.c_str()));
ms_rLog.Write(txt, CMICmnLog::eLogVerbosity_FnTrace);
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDebug.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDebug.h
index b309c5d..c538388 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDebug.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilDebug.h
@@ -19,25 +19,22 @@ class CMICmnLog;
//++ ============================================================================
// Details: MI debugging aid utility class.
-// Gotchas: None.
-// Authors:
-// Changes: None.
//--
class CMIUtilDebug
{
// Statics:
public:
- static void ShowDlgWaitForDbgAttach(void);
- static void WaitForDbgAttachInfinteLoop(void);
+ static void ShowDlgWaitForDbgAttach();
+ static void WaitForDbgAttachInfinteLoop();
// Methods:
public:
- /* ctor */ CMIUtilDebug(void);
+ /* ctor */ CMIUtilDebug();
// Overrideable:
public:
// From CMICmnBase
- /* dtor */ virtual ~CMIUtilDebug(void);
+ /* dtor */ virtual ~CMIUtilDebug();
};
//++ ============================================================================
@@ -48,9 +45,6 @@ class CMIUtilDebug
// the functions you wish to build up a trace off.
// Use preprocessor definition MI_USE_DEBUG_TRACE_FN to turn off or on
// tracing code.
-// Gotchas: None.
-// Authors: Illya Rudkin 07/03/2014.
-// Changes: None.
//--
class CMIUtilDebugFnTrace
{
@@ -61,7 +55,7 @@ class CMIUtilDebugFnTrace
// Overrideable:
public:
// From CMICmnBase
- /* dtor */ virtual ~CMIUtilDebugFnTrace(void);
+ /* dtor */ virtual ~CMIUtilDebugFnTrace();
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilFileStd.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilFileStd.cpp
index a0fce65..9e5d10d 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilFileStd.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilFileStd.cpp
@@ -24,7 +24,7 @@
// Return: None.
// Throws: None.
//--
-CMIUtilFileStd::CMIUtilFileStd(void)
+CMIUtilFileStd::CMIUtilFileStd()
: m_fileNamePath(CMIUtilString())
, m_pFileHandle(nullptr)
#if defined(_MSC_VER)
@@ -43,7 +43,7 @@ CMIUtilFileStd::CMIUtilFileStd(void)
// Return: None.
// Throws: None.
//--
-CMIUtilFileStd::~CMIUtilFileStd(void)
+CMIUtilFileStd::~CMIUtilFileStd()
{
Close();
}
@@ -183,7 +183,7 @@ CMIUtilFileStd::Write(const char *vpData, const MIuint vCharCnt)
// Throws: None.
//--
void
-CMIUtilFileStd::Close(void)
+CMIUtilFileStd::Close()
{
if (m_pFileHandle == nullptr)
return;
@@ -202,7 +202,7 @@ CMIUtilFileStd::Close(void)
// Throws: None.
//--
bool
-CMIUtilFileStd::IsOk(void) const
+CMIUtilFileStd::IsOk() const
{
return !m_bFileError;
}
@@ -240,7 +240,7 @@ CMIUtilFileStd::IsFileExist(const CMIUtilString &vFileNamePath) const
// Throws: None.
//--
const CMIUtilString &
-CMIUtilFileStd::GetLineReturn(void) const
+CMIUtilFileStd::GetLineReturn() const
{
return m_constCharNewLine;
}
@@ -277,7 +277,7 @@ CMIUtilFileStd::StripOffFileName(const CMIUtilString &vDirectoryPath)
// Throws: None.
//--
char
-CMIUtilFileStd::GetSlash(void)
+CMIUtilFileStd::GetSlash()
{
#if !defined(_MSC_VER)
return '/';
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilFileStd.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilFileStd.h
index 5a22348..458f64a 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilFileStd.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilFileStd.h
@@ -15,33 +15,30 @@
//++ ============================================================================
// Details: MI common code utility class. File handling.
-// Gotchas: None.
-// Authors: Aidan Dodds 10/03/2014.
-// Changes: None.
//--
class CMIUtilFileStd : public CMICmnBase
{
// Static:
public:
- static char GetSlash(void);
+ static char GetSlash();
// Methods:
public:
- /* ctor */ CMIUtilFileStd(void);
+ /* ctor */ CMIUtilFileStd();
//
bool CreateWrite(const CMIUtilString &vFileNamePath, bool &vwrbNewCreated);
bool Write(const CMIUtilString &vData);
bool Write(const char *vpData, const MIuint vCharCnt);
- void Close(void);
- bool IsOk(void) const;
+ void Close();
+ bool IsOk() const;
bool IsFileExist(const CMIUtilString &vFileNamePath) const;
- const CMIUtilString &GetLineReturn(void) const;
+ const CMIUtilString &GetLineReturn() const;
static CMIUtilString StripOffFileName(const CMIUtilString &vDirectoryPath);
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMIUtilFileStd(void) override;
+ /* dtor */ ~CMIUtilFileStd() override;
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilMapIdToVariant.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilMapIdToVariant.cpp
index debac20..b35d97a 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilMapIdToVariant.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilMapIdToVariant.cpp
@@ -17,7 +17,7 @@
// Return: None.
// Throws: None.
//--
-CMIUtilMapIdToVariant::CMIUtilMapIdToVariant(void)
+CMIUtilMapIdToVariant::CMIUtilMapIdToVariant()
{
}
@@ -28,7 +28,7 @@ CMIUtilMapIdToVariant::CMIUtilMapIdToVariant(void)
// Return: None.
// Throws: None.
//--
-CMIUtilMapIdToVariant::~CMIUtilMapIdToVariant(void)
+CMIUtilMapIdToVariant::~CMIUtilMapIdToVariant()
{
}
@@ -40,7 +40,7 @@ CMIUtilMapIdToVariant::~CMIUtilMapIdToVariant(void)
// Throws: None.
//--
void
-CMIUtilMapIdToVariant::Clear(void)
+CMIUtilMapIdToVariant::Clear()
{
m_mapKeyToVariantValue.clear();
}
@@ -71,7 +71,7 @@ CMIUtilMapIdToVariant::HaveAlready(const CMIUtilString &vId) const
// Throws: None.
//--
bool
-CMIUtilMapIdToVariant::IsEmpty(void) const
+CMIUtilMapIdToVariant::IsEmpty() const
{
return m_mapKeyToVariantValue.empty();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilMapIdToVariant.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilMapIdToVariant.h
index c77f0b9..1a16490 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilMapIdToVariant.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilMapIdToVariant.h
@@ -22,27 +22,24 @@
// Details: MI common code utility class. Map type container that hold general
// object types (by being a variant wrapper)
// objects by ID.
-// Gotchas: None.
-// Authors: Illya Rudkin 19/06/2014.
-// Changes: None.
//--
class CMIUtilMapIdToVariant : public CMICmnBase
{
// Methods:
public:
- /* ctor */ CMIUtilMapIdToVariant(void);
+ /* ctor */ CMIUtilMapIdToVariant();
template <typename T> bool Add(const CMIUtilString &vId, const T &vData);
- void Clear(void);
+ void Clear();
template <typename T> bool Get(const CMIUtilString &vId, T &vrwData, bool &vrwbFound) const;
bool HaveAlready(const CMIUtilString &vId) const;
- bool IsEmpty(void) const;
+ bool IsEmpty() const;
bool Remove(const CMIUtilString &vId);
// Overridden:
public:
// From CMICmnBase
- /* dtor */ ~CMIUtilMapIdToVariant(void) override;
+ /* dtor */ ~CMIUtilMapIdToVariant() override;
// Typedefs:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilParse.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilParse.cpp
new file mode 100644
index 0000000..27e25b8
--- /dev/null
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilParse.cpp
@@ -0,0 +1,75 @@
+//===-- MIUtilParse.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Third party headers:
+#include <memory>
+
+// In-house headers:
+#include "MIUtilParse.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CRegexParser constructor.
+// Type: Method.
+// Args: regexStr - Pointer to the regular expression to compile.
+// Return: None.
+// Throws: None.
+//--
+MIUtilParse::CRegexParser::CRegexParser(const char *regexStr)
+ : m_isValid(llvm_regcomp(&m_emma, regexStr, REG_EXTENDED) == 0)
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CRegexParser destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+MIUtilParse::CRegexParser::~CRegexParser()
+{
+ // Free up memory held within regex.
+ if (m_isValid)
+ llvm_regfree(&m_emma);
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CRegexParser regex executer.
+// Match the input against the regular expression. Return an error
+// if the number of matches is less than minMatches. If the default
+// minMatches value of 0 is passed, an error will be returned if
+// the number of matches is less than the maxMatches value used to
+// initialize Match.
+// Type: Method.
+// Args: input (R) - Pointer to UTF8 text data to be parsed.
+// match (RW) - Reference to Match class.
+// minMatches (R) - Minimum number of regex matches expected.
+// Return: bool - True = minimum matches were met,
+// false = minimum matches were not met or regex failed.
+// Throws: None.
+//--
+bool
+MIUtilParse::CRegexParser::Execute(const char *input, Match& match, size_t minMatches)
+{
+ if (!m_isValid)
+ return false;
+
+ std::unique_ptr<llvm_regmatch_t[]> matches(new llvm_regmatch_t[match.m_maxMatches]); // Array of matches
+
+ if (llvm_regexec(&m_emma, input, match.m_maxMatches, matches.get(), 0) != 0)
+ return false;
+
+ size_t i;
+ for (i = 0; i < match.m_maxMatches && matches[i].rm_so >= 0; i++)
+ {
+ const int n = matches[i].rm_eo - matches[i].rm_so;
+ match.m_matchStrs[i].assign(input + matches[i].rm_so, n);
+ }
+ return i >= minMatches;
+}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilParse.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilParse.h
new file mode 100644
index 0000000..d356958
--- /dev/null
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilParse.h
@@ -0,0 +1,93 @@
+//===-- MIUtilParse.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+// Third party headers:
+#include "../lib/Support/regex_impl.h"
+
+// In-house headers:
+#include "MIUtilString.h"
+
+namespace MIUtilParse
+{
+
+//++ ============================================================================
+// Details: MI common code utility class. Used to parse the output
+// returned from lldb commands using regex.
+//--
+class CRegexParser
+{
+ public:
+ // Helper class for keeping track of regex matches.
+ class Match
+ {
+ friend CRegexParser;
+ public:
+ /* ctor */ explicit Match(size_t nmatches)
+ : m_matchStrs(nmatches), m_maxMatches(nmatches)
+ {
+ }
+ size_t
+ GetMatchCount() const
+ {
+ return m_matchStrs.size();
+ }
+ CMIUtilString
+ GetMatchAtIndex(size_t i) const
+ {
+ if (m_matchStrs.size() > i)
+ return m_matchStrs[i];
+ return CMIUtilString();
+ }
+ private:
+ CMIUtilString::VecString_t m_matchStrs;
+ const size_t m_maxMatches;
+ };
+
+ // Methods:
+ // Compile the regular expression.
+ /* ctor */ explicit CRegexParser(const char *regexStr);
+
+ // Free the memory used by the regular expression.
+ /* dtor */ ~CRegexParser();
+
+ // No copies
+ CRegexParser(const CRegexParser&) = delete;
+ void operator=(CRegexParser&) = delete;
+
+ // Return the match at the index.
+ int
+ GetMatchCount(const Match& match) const
+ {
+ if (m_isValid)
+ return match.GetMatchCount();
+ return 0;
+ }
+
+ bool
+ IsValid() const
+ {
+ return m_isValid;
+ }
+
+ // Match the input against the regular expression. Return an error
+ // if the number of matches is less than minMatches. If the default
+ // minMatches value of 0 is passed, an error will be returned if
+ // the number of matches is less than the maxMatches value used to
+ // initialize Match.
+ bool
+ Execute(const char *input, Match& match, size_t minMatches = 0);
+
+ private:
+ llvm_regex_t m_emma;
+ const bool m_isValid;
+};
+
+}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonBase.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonBase.h
index 3649a73..03ce8c8 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonBase.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonBase.h
@@ -22,15 +22,13 @@ namespace MI
// // Overridden:
// public:
// // From MI::ISingleton
-// bool Initialize(void) override;
-// bool Shutdown(void) override;
+// bool Initialize() override;
+// bool Shutdown() override;
// };
//++ ============================================================================
// Details: Base class for the singleton pattern.
// Gotchas: Derived class must specify MI::ISingleton<> as a friend class.
-// Authors: Aidan Dodds 17/03/2014.
-// Changes: None.
//--
template <typename T> class ISingleton
{
@@ -38,7 +36,7 @@ template <typename T> class ISingleton
public:
// Return an instance of the derived class
static T &
- Instance(void)
+ Instance()
{
// This will fail if the derived class has not
// declared itself to be a friend of MI::ISingleton
@@ -49,10 +47,10 @@ template <typename T> class ISingleton
// Overrideable:
public:
- virtual bool Initialize(void) = 0;
- virtual bool Shutdown(void) = 0;
+ virtual bool Initialize() = 0;
+ virtual bool Shutdown() = 0;
//
- /* dtor */ virtual ~ISingleton(void){};
+ /* dtor */ virtual ~ISingleton(){}
};
} // namespace MI
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonHelper.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonHelper.h
index 19cc3a9..2b9f4c4 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonHelper.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSingletonHelper.h
@@ -6,9 +6,6 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// Copyright: None.
-//--
#pragma once
@@ -29,8 +26,6 @@ namespace MI
// vwrErrMsg - (W) MI driver module initialise error description on failure.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
-// Authors: Aidan Dodds 17/03/2014.
-// Changes: None.
//--
template <typename T>
bool
@@ -58,8 +53,6 @@ ModuleInit(const MIint vErrorResrcId, bool &vwrbOk, CMIUtilString &vwrErrMsg)
// failure.
// Return: True - Module shutdown succeeded.
// False - Module shutdown failed.
-// Authors: Aidan Dodds 17/03/2014.
-// Changes: None.
//--
template <typename T>
bool
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilString.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilString.cpp
index fc77177..176d9a6 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilString.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilString.cpp
@@ -25,7 +25,7 @@
// Return: None.
// Throws: None.
//--
-CMIUtilString::CMIUtilString(void)
+CMIUtilString::CMIUtilString()
: std::string()
{
}
@@ -45,12 +45,12 @@ CMIUtilString::CMIUtilString(const char *vpData)
//++ ------------------------------------------------------------------------------------
// Details: CMIUtilString constructor.
// Type: Method.
-// Args: vpData - Pointer to UTF8 text data.
+// Args: vpStr - Text data.
// Return: None.
// Throws: None.
//--
-CMIUtilString::CMIUtilString(const char *const *vpData)
- : std::string((const char *)vpData)
+CMIUtilString::CMIUtilString(const std::string& vrStr)
+ : std::string(vrStr)
{
}
@@ -63,14 +63,7 @@ CMIUtilString::CMIUtilString(const char *const *vpData)
//--
CMIUtilString &CMIUtilString::operator=(const char *vpRhs)
{
- if (*this == vpRhs)
- return *this;
-
- if (vpRhs != nullptr)
- {
- assign(vpRhs);
- }
-
+ assign(vpRhs);
return *this;
}
@@ -83,11 +76,7 @@ CMIUtilString &CMIUtilString::operator=(const char *vpRhs)
//--
CMIUtilString &CMIUtilString::operator=(const std::string &vrRhs)
{
- if (*this == vrRhs)
- return *this;
-
assign(vrRhs);
-
return *this;
}
@@ -98,7 +87,7 @@ CMIUtilString &CMIUtilString::operator=(const std::string &vrRhs)
// Return: None.
// Throws: None.
//--
-CMIUtilString::~CMIUtilString(void)
+CMIUtilString::~CMIUtilString()
{
}
@@ -230,7 +219,7 @@ CMIUtilString::Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits)
// Extract string between delimiters
const size_t nSectionLen(nNextDelimiterPos - nSectionPos);
const std::string strSection(substr(nSectionPos, nSectionLen));
- vwVecSplits.push_back(strSection.c_str());
+ vwVecSplits.push_back(strSection);
// Next
nOffset = nNextDelimiterPos + 1;
@@ -286,7 +275,7 @@ CMIUtilString::SplitConsiderQuotes(const CMIUtilString &vDelimiter, VecString_t
// Extract string between delimiters
const size_t nSectionLen(nNextDelimiterPos - nSectionPos);
const std::string strSection(substr(nSectionPos, nSectionLen));
- vwVecSplits.push_back(strSection.c_str());
+ vwVecSplits.push_back(strSection);
// Next
nOffset = nNextDelimiterPos + 1;
@@ -318,13 +307,13 @@ CMIUtilString::SplitLines(VecString_t &vwVecSplits) const
// Throws: None.
//--
CMIUtilString
-CMIUtilString::StripCREndOfLine(void) const
+CMIUtilString::StripCREndOfLine() const
{
const size_t nPos = rfind('\n');
if (nPos == std::string::npos)
return *this;
- const CMIUtilString strNew(substr(0, nPos).c_str());
+ const CMIUtilString strNew(substr(0, nPos));
return strNew;
}
@@ -338,7 +327,7 @@ CMIUtilString::StripCREndOfLine(void) const
// Throws: None.
//--
CMIUtilString
-CMIUtilString::StripCRAll(void) const
+CMIUtilString::StripCRAll() const
{
return FindAndReplace("\n", " ");
}
@@ -381,7 +370,7 @@ CMIUtilString::FindAndReplace(const CMIUtilString &vFind, const CMIUtilString &v
// Throws: None.
//--
bool
-CMIUtilString::IsNumber(void) const
+CMIUtilString::IsNumber() const
{
if (empty())
return false;
@@ -404,7 +393,7 @@ CMIUtilString::IsNumber(void) const
// Throws: None.
//--
bool
-CMIUtilString::IsHexadecimalNumber(void) const
+CMIUtilString::IsHexadecimalNumber() const
{
// Compare '0x..' prefix
if ((strncmp(c_str(), "0x", 2) != 0) && (strncmp(c_str(), "0X", 2) != 0))
@@ -522,19 +511,19 @@ CMIUtilString::Compare(const CMIUtilString &vrLhs, const CMIUtilString &vrRhs)
// Throws: None.
//--
CMIUtilString
-CMIUtilString::Trim(void) const
+CMIUtilString::Trim() const
{
CMIUtilString strNew(*this);
const char *pWhiteSpace = " \t\n\v\f\r";
const size_t nPos = find_last_not_of(pWhiteSpace);
if (nPos != std::string::npos)
{
- strNew = substr(0, nPos + 1).c_str();
+ strNew = substr(0, nPos + 1);
}
const size_t nPos2 = strNew.find_first_not_of(pWhiteSpace);
if (nPos2 != std::string::npos)
{
- strNew = strNew.substr(nPos2).c_str();
+ strNew = strNew.substr(nPos2);
}
return strNew;
@@ -555,7 +544,7 @@ CMIUtilString::Trim(const char vChar) const
if (nLen > 1)
{
if ((strNew[0] == vChar) && (strNew[nLen - 1] == vChar))
- strNew = strNew.substr(1, nLen - 2).c_str();
+ strNew = strNew.substr(1, nLen - 2);
}
return strNew;
@@ -652,7 +641,7 @@ CMIUtilString::RemoveRepeatedCharacters(size_t vnPos, const char vChar)
// Throws: None.
//--
bool
-CMIUtilString::IsQuoted(void) const
+CMIUtilString::IsQuoted() const
{
const char cQuote = '"';
@@ -819,7 +808,7 @@ CMIUtilString::Escape(bool vbEscapeQuotes /* = false */) const
// Throws: None.
//--
CMIUtilString
-CMIUtilString::AddSlashes(void) const
+CMIUtilString::AddSlashes() const
{
const char cBckSlash('\\');
const size_t nLen(length());
@@ -856,7 +845,7 @@ CMIUtilString::AddSlashes(void) const
// Throws: None.
//--
CMIUtilString
-CMIUtilString::StripSlashes(void) const
+CMIUtilString::StripSlashes() const
{
const char cBckSlash('\\');
const size_t nLen(length());
@@ -895,7 +884,7 @@ CMIUtilString::StripSlashes(void) const
}
CMIUtilString
-CMIUtilString::ConvertToPrintableASCII(const char vChar)
+CMIUtilString::ConvertToPrintableASCII(const char vChar, bool bEscapeQuotes)
{
switch (vChar)
{
@@ -917,6 +906,10 @@ CMIUtilString::ConvertToPrintableASCII(const char vChar)
return "\\e";
case '\\':
return "\\\\";
+ case '"':
+ if (bEscapeQuotes)
+ return "\\\"";
+ // fall thru
default:
if (::isprint(vChar))
return Format("%c", vChar);
@@ -926,24 +919,65 @@ CMIUtilString::ConvertToPrintableASCII(const char vChar)
}
CMIUtilString
-CMIUtilString::ConvertToPrintableASCII(const char16_t vChar16)
+CMIUtilString::ConvertCharValueToPrintableASCII(char vChar, bool bEscapeQuotes)
+{
+ switch (vChar)
+ {
+ case '\a':
+ return "\\a";
+ case '\b':
+ return "\\b";
+ case '\t':
+ return "\\t";
+ case '\n':
+ return "\\n";
+ case '\v':
+ return "\\v";
+ case '\f':
+ return "\\f";
+ case '\r':
+ return "\\r";
+ case '\033':
+ return "\\e";
+ case '\\':
+ return "\\\\";
+ case '"':
+ if (bEscapeQuotes)
+ return "\\\"";
+ // fall thru
+ default:
+ if (::isprint(vChar))
+ return Format("%c", vChar);
+ else
+ return CMIUtilString();
+ }
+}
+
+CMIUtilString
+CMIUtilString::ConvertToPrintableASCII(const char16_t vChar16, bool bEscapeQuotes)
{
- if (vChar16 == (char16_t)(char)vChar16 && ::isprint(vChar16))
+ if (vChar16 == (char16_t)(char)vChar16)
+ {
// Convert char16_t to char (if possible)
- return Format("%c", vChar16);
- else
- return Format("\\u%02" PRIx8 "%02" PRIx8,
+ CMIUtilString str = ConvertCharValueToPrintableASCII((char)vChar16, bEscapeQuotes);
+ if (str.length() > 0)
+ return str;
+ }
+ return Format("\\u%02" PRIx8 "%02" PRIx8,
(vChar16 >> 8) & 0xff, vChar16 & 0xff);
}
CMIUtilString
-CMIUtilString::ConvertToPrintableASCII(const char32_t vChar32)
+CMIUtilString::ConvertToPrintableASCII(const char32_t vChar32, bool bEscapeQuotes)
{
- if (vChar32 == (char32_t)(char)vChar32 && ::isprint(vChar32))
+ if (vChar32 == (char32_t)(char)vChar32)
+ {
// Convert char32_t to char (if possible)
- return Format("%c", vChar32);
- else
- return Format("\\U%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8,
+ CMIUtilString str = ConvertCharValueToPrintableASCII((char)vChar32, bEscapeQuotes);
+ if (str.length() > 0)
+ return str;
+ }
+ return Format("\\U%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8,
(vChar32 >> 24) & 0xff, (vChar32 >> 16) & 0xff,
(vChar32 >> 8) & 0xff, vChar32 & 0xff);
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilString.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilString.h
index 7b188ed..2326160 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilString.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilString.h
@@ -13,6 +13,7 @@
#include <string>
#include <vector>
#include <cinttypes>
+#include <cstdarg>
// In-house headers:
#include "MIDataTypes.h"
@@ -20,9 +21,6 @@
//++ ============================================================================
// Details: MI common code utility class. Used to help handle text.
// Derived from std::string
-// Gotchas: None.
-// Authors: Illya Rudkin 02/02/2014.
-// Changes: None.
//--
class CMIUtilString : public std::string
{
@@ -37,47 +35,48 @@ class CMIUtilString : public std::string
static CMIUtilString FormatValist(const CMIUtilString &vrFormating, va_list vArgs);
static bool IsAllValidAlphaAndNumeric(const char *vpText);
static bool Compare(const CMIUtilString &vrLhs, const CMIUtilString &vrRhs);
- static CMIUtilString ConvertToPrintableASCII(const char vChar);
- static CMIUtilString ConvertToPrintableASCII(const char16_t vChar16);
- static CMIUtilString ConvertToPrintableASCII(const char32_t vChar32);
+ static CMIUtilString ConvertToPrintableASCII(const char vChar, bool bEscapeQuotes = false);
+ static CMIUtilString ConvertToPrintableASCII(const char16_t vChar16, bool bEscapeQuotes = false);
+ static CMIUtilString ConvertToPrintableASCII(const char32_t vChar32, bool bEscapeQuotes = false);
// Methods:
public:
- /* ctor */ CMIUtilString(void);
+ /* ctor */ CMIUtilString();
/* ctor */ CMIUtilString(const char *vpData);
- /* ctor */ CMIUtilString(const char *const *vpData);
+ /* ctor */ CMIUtilString(const std::string& vrStr);
//
bool ExtractNumber(MIint64 &vwrNumber) const;
CMIUtilString FindAndReplace(const CMIUtilString &vFind, const CMIUtilString &vReplaceWith) const;
- bool IsNumber(void) const;
- bool IsHexadecimalNumber(void) const;
- bool IsQuoted(void) const;
+ bool IsNumber() const;
+ bool IsHexadecimalNumber() const;
+ bool IsQuoted() const;
CMIUtilString RemoveRepeatedCharacters(const char vChar);
size_t Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const;
size_t SplitConsiderQuotes(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const;
size_t SplitLines(VecString_t &vwVecSplits) const;
- CMIUtilString StripCREndOfLine(void) const;
- CMIUtilString StripCRAll(void) const;
- CMIUtilString Trim(void) const;
+ CMIUtilString StripCREndOfLine() const;
+ CMIUtilString StripCRAll() const;
+ CMIUtilString Trim() const;
CMIUtilString Trim(const char vChar) const;
size_t FindFirst(const CMIUtilString &vrPattern, size_t vnPos = 0) const;
size_t FindFirst(const CMIUtilString &vrPattern, bool vbSkipQuotedText, bool &vrwbNotFoundClosedQuote,
size_t vnPos = 0) const;
size_t FindFirstNot(const CMIUtilString &vrPattern, size_t vnPos = 0) const;
CMIUtilString Escape(bool vbEscapeQuotes = false) const;
- CMIUtilString AddSlashes(void) const;
- CMIUtilString StripSlashes(void) const;
+ CMIUtilString AddSlashes() const;
+ CMIUtilString StripSlashes() const;
//
CMIUtilString &operator=(const char *vpRhs);
CMIUtilString &operator=(const std::string &vrRhs);
// Overrideable:
public:
- /* dtor */ virtual ~CMIUtilString(void);
+ /* dtor */ virtual ~CMIUtilString();
// Static method:
private:
static CMIUtilString FormatPriv(const CMIUtilString &vrFormat, va_list vArgs);
+ static CMIUtilString ConvertCharValueToPrintableASCII(char vChar, bool bEscapeQuotes);
// Methods:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemLinux.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemLinux.cpp
deleted file mode 100644
index 8fd2470..0000000
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemLinux.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-//===-- MIUtilSystemLinux.cpp -----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__linux__)
-
-// In-house headers:
-#include "MIUtilSystemLinux.h"
-#include "MICmnResources.h"
-
-//++ ------------------------------------------------------------------------------------
-// Details: CMIUtilSystemLinux constructor.
-// Type: Method.
-// Args: None.
-// Return: None.
-// Throws: None.
-//--
-CMIUtilSystemLinux::CMIUtilSystemLinux(void)
-{
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: CMIUtilSystemLinux destructor.
-// Type: Method.
-// Args: None.
-// Return: None.
-// Throws: None.
-//--
-CMIUtilSystemLinux::~CMIUtilSystemLinux(void)
-{
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieve the OS system error message for the given system error code.
-// Type: Method.
-// Args: vError - (R) OS error code value.
-// vrwErrorMsg - (W) The error message.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIUtilSystemLinux::GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const
-{
- // Reset
- vrwErrorMsg.clear();
-
- bool bOk = MIstatus::failure;
-
- // ToDo: Implement LINUX version
-
- return bOk;
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieve if possible the OS last error description.
-// Type: Method.
-// Args: None.
-// Return: CMIUtilString - Error description.
-// Throws: None.
-//--
-CMIUtilString
-CMIUtilSystemLinux::GetOSLastError(void) const
-{
- CMIUtilString errorMsg("Error fn not implemented ");
-
- // ToDo: Implement LINUX version
-
- return errorMsg;
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieves the fully qualified path for the this application. If the function
-// fails the string is filled with the error message.
-// Type: Method.
-// Args: vrwFileNamePath - (W) The executable's name and path or last error description.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIUtilSystemLinux::GetExecutablesPath(CMIUtilString &vrwFileNamePath) const
-{
- vrwFileNamePath = CMIUtilString(".");
- return MIstatus::success;
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieves the fully qualified path for the Log file for this application.
-// If the function fails the string is filled with the error message.
-// Append a dummy file name on the end of the path. This will be stripped off
-// later and the real log file name replaces it.
-// Type: Method.
-// Args: vrwFileNamePath - (W) The Log file's name and path or last error description.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIUtilSystemLinux::GetLogFilesPath(CMIUtilString &vrwFileNamePath) const
-{
- vrwFileNamePath = CMIUtilString(".");
- return MIstatus::success;
-}
-
-#endif // #if defined( __linux__ )
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemLinux.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemLinux.h
deleted file mode 100644
index 975714b..0000000
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemLinux.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//===-- CMIUtilSystemLinux.h ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#pragma once
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__linux__)
-
-// In-house headers:
-#include "MIUtilString.h"
-
-//++ ============================================================================
-// Details: MI common code utility class. Used to set or retrieve information
-// about the current system or user.
-// *** If you change, remove or add functionality it must be replicated
-// *** for the all platforms supported; Windows, OSX, LINUX
-// Gotchas: None.
-// Authors: Illya Rudkin 29/01/2014.
-// Changes: None.
-//--
-class CMIUtilSystemLinux
-{
- // Methods:
- public:
- /* ctor */ CMIUtilSystemLinux(void);
-
- bool GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const;
- CMIUtilString GetOSLastError(void) const;
- bool GetExecutablesPath(CMIUtilString &vrwFileNamePath) const;
- bool GetLogFilesPath(CMIUtilString &vrwFileNamePath) const;
-
- // Overrideable:
- public:
- // From CMICmnBase
- /* dtor */ virtual ~CMIUtilSystemLinux(void);
-};
-
-typedef CMIUtilSystemLinux CMIUtilSystem;
-
-#endif // #if defined( __linux__ )
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemOsx.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemOsx.cpp
deleted file mode 100644
index b926342..0000000
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemOsx.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-//===-- MIUtilSystemOsx.cpp -------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(__APPLE__)
-
-// In-house headers:
-#include "MIUtilSystemOsx.h"
-#include "MICmnResources.h"
-
-//++ ------------------------------------------------------------------------------------
-// Details: CMIUtilSystemOsx constructor.
-// Type: Method.
-// Args: None.
-// Return: None.
-// Throws: None.
-//--
-CMIUtilSystemOsx::CMIUtilSystemOsx(void)
-{
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: CMIUtilSystemOsx destructor.
-// Type: Method.
-// Args: None.
-// Return: None.
-// Throws: None.
-//--
-CMIUtilSystemOsx::~CMIUtilSystemOsx(void)
-{
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieve the OS system error message for the given system error code.
-// Type: Method.
-// Args: vError - (R) OS error code value.
-// vrwErrorMsg - (W) The error message.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIUtilSystemOsx::GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const
-{
- // Reset
- vrwErrorMsg.clear();
-
- bool bOk = MIstatus::failure;
-
- // ToDo: Implement LINUX version
-
- return bOk;
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieve if possible the OS last error description.
-// Type: Method.
-// Args: None.
-// Return: CMIUtilString - Error description.
-// Throws: None.
-//--
-CMIUtilString
-CMIUtilSystemOsx::GetOSLastError(void) const
-{
- CMIUtilString errorMsg("Error fn not implemented");
-
- // ToDo: Implement LINUX version
-
- return errorMsg;
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieves the fully qualified path for the this application. If the function
-// fails the string is filled with the error message.
-// Type: Method.
-// Args: vrwFileNamePath - (W) The executable's name and path or last error description.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIUtilSystemOsx::GetExecutablesPath(CMIUtilString &vrwFileNamePath) const
-{
- vrwFileNamePath = CMIUtilString(".");
- return MIstatus::success;
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieves the fully qualified path for the Log file for this application.
-// If the function fails the string is filled with the error message.
-// Append a dummy file name on the end of the path. This will be stripped off
-// later and the real log file name replaces it.
-// Type: Method.
-// Args: vrwFileNamePath - (W) The Log file's name and path or last error description.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIUtilSystemOsx::GetLogFilesPath(CMIUtilString &vrwFileNamePath) const
-{
- vrwFileNamePath = CMIUtilString(".");
- return MIstatus::success;
-}
-
-#endif // #if defined( __APPLE__ )
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemOsx.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemOsx.h
deleted file mode 100644
index b30e258..0000000
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemOsx.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//===-- MICmnConfig.h -------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#pragma once
-
-#if defined(__APPLE__)
-
-// In-house headers:
-#include "MIUtilString.h"
-
-//++ ============================================================================
-// Details: MI common code utility class. Used to set or retrieve information
-// about the current system or user.
-// *** If you change, remove or add functionality it must be replicated
-// *** for the all platforms supported; Windows, OSX, LINUX
-// Gotchas: None.
-// Authors: Illya Rudkin 29/01/2014.
-// Changes: None.
-//--
-class CMIUtilSystemOsx
-{
- // Methods:
- public:
- /* ctor */ CMIUtilSystemOsx(void);
-
- bool GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const;
- CMIUtilString GetOSLastError(void) const;
- bool GetExecutablesPath(CMIUtilString &vrwFileNamePath) const;
- bool GetLogFilesPath(CMIUtilString &vrwFileNamePath) const;
-
- // Overrideable:
- public:
- // From CMICmnBase
- /* dtor */ virtual ~CMIUtilSystemOsx(void);
-};
-
-typedef CMIUtilSystemOsx CMIUtilSystem;
-
-#endif // #if defined( __APPLE__ )
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemWindows.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemWindows.cpp
deleted file mode 100644
index 80f4aac..0000000
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemWindows.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-//===-- MIUtilSystemWindows.cpp ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(_MSC_VER)
-
-// Third party headers
-#include <memory> // std::unique_ptr
-#include <Windows.h>
-#include <WinBase.h> // ::FormatMessage()
-
-// In-house headers:
-#include "MIUtilSystemWindows.h"
-#include "MICmnResources.h"
-#include "MIUtilFileStd.h"
-
-//++ ------------------------------------------------------------------------------------
-// Details: CMIUtilSystemWindows constructor.
-// Type: Method.
-// Args: None.
-// Return: None.
-// Throws: None.
-//--
-CMIUtilSystemWindows::CMIUtilSystemWindows(void)
-{
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: CMIUtilSystemWindows destructor.
-// Type: Method.
-// Args: None.
-// Return: None.
-// Throws: None.
-//--
-CMIUtilSystemWindows::~CMIUtilSystemWindows(void)
-{
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieve the OS system error message for the given system error code.
-// Type: Method.
-// Args: vError - (R) OS error code value.
-// vrwErrorMsg - (W) The error message.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIUtilSystemWindows::GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const
-{
- // Reset
- vrwErrorMsg.clear();
-
- const MIuint nBufLen = 1024;
- std::unique_ptr<char[]> pBuffer;
- pBuffer.reset(new char[nBufLen]);
-
- // CMIUtilString Format is not used as cannot replicate the behavior of ::FormatMessage which
- // can take into account locality while retrieving the error message from the system.
- const int nLength = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, (DWORD)vError,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPTSTR>(&pBuffer[0]), nBufLen, nullptr);
- bool bOk = MIstatus::success;
- if (nLength != 0)
- vrwErrorMsg = &pBuffer[0];
- else
- bOk = MIstatus::failure;
-
- return bOk;
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieve if possible the OS last error description.
-// Type: Method.
-// Args: None.
-// Return: CMIUtilString - Error description.
-// Throws: None.
-//--
-CMIUtilString
-CMIUtilSystemWindows::GetOSLastError(void) const
-{
- CMIUtilString errorMsg;
- const DWORD dwLastError = ::GetLastError();
- if (dwLastError != 0)
- {
- if (!GetOSErrorMsg(dwLastError, errorMsg))
- errorMsg = MIRSRC(IDE_OS_ERR_RETRIEVING);
- }
- else
- errorMsg = MIRSRC(IDE_OS_ERR_UNKNOWN);
-
- return errorMsg;
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieves the fully qualified path for the this application. If the function
-// fails the string is filled with the error message.
-// Type: Method.
-// Args: vrwFileNamePath - (W) The executable's name and path or last error description.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIUtilSystemWindows::GetExecutablesPath(CMIUtilString &vrwFileNamePath) const
-{
- bool bOk = MIstatus::success;
- HMODULE hModule = ::GetModuleHandle(nullptr);
- char pPath[MAX_PATH];
- if (!::GetModuleFileName(hModule, &pPath[0], MAX_PATH))
- {
- bOk = MIstatus::failure;
- vrwFileNamePath = GetOSLastError();
- }
- else
- vrwFileNamePath = &pPath[0];
-
- return bOk;
-}
-
-//++ ------------------------------------------------------------------------------------
-// Details: Retrieves the fully qualified path for the Log file for this application.
-// If the function fails the string is filled with the error message.
-// Type: Method.
-// Args: vrwFileNamePath - (W) The Log file's name and path or last error description.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
-// Throws: None.
-//--
-bool
-CMIUtilSystemWindows::GetLogFilesPath(CMIUtilString &vrwFileNamePath) const
-{
- vrwFileNamePath = CMIUtilString(".");
- return MIstatus::success;
-}
-
-#endif // #if defined( _MSC_VER )
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemWindows.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemWindows.h
deleted file mode 100644
index 696c2b2..0000000
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilSystemWindows.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===-- MIUtilSystemWindows.h -----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#pragma once
-
-#if defined(_MSC_VER)
-
-// In-house headers:
-#include "MIUtilString.h"
-
-//++ ============================================================================
-// Details: MI common code utility class. Used to set or retrieve information
-// about the current system or user.
-// *** If you change, remove or add functionality it must be replicated
-// *** for the all platforms supported; Windows, OSX, LINUX
-// Gotchas: None.
-// Authors: Illya Rudkin 29/01/2014.
-// Changes: None.
-//--
-class CMIUtilSystemWindows
-{
- // Methods:
- public:
- /* ctor */ CMIUtilSystemWindows(void);
-
- bool GetOSErrorMsg(const MIint vError, CMIUtilString &vrwErrorMsg) const;
- CMIUtilString GetOSLastError(void) const;
- bool GetExecutablesPath(CMIUtilString &vrwFileNamePath) const;
- bool GetLogFilesPath(CMIUtilString &vrwFileNamePath) const;
-
- // Overrideable:
- public:
- // From CMICmnBase
- /* dtor */ virtual ~CMIUtilSystemWindows(void);
-};
-
-typedef CMIUtilSystemWindows CMIUtilSystem;
-
-#endif // #if defined( _MSC_VER )
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilThreadBaseStd.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilThreadBaseStd.cpp
index 96f53ff..fac0aa6 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilThreadBaseStd.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilThreadBaseStd.cpp
@@ -6,8 +6,6 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-// Copyright: None.
-//--
// Third Party Headers:
#include <assert.h>
@@ -23,7 +21,7 @@
// Return: None.
// Throws: None.
//--
-CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase(void)
+CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase()
: m_references(0)
, m_bHasBeenKilled(false)
{
@@ -36,7 +34,7 @@ CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase(void)
// Return: None.
// Throws: None.
//--
-CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase(void)
+CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase()
{
// Make sure our thread is not alive before we die
m_thread.Join();
@@ -51,7 +49,7 @@ CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase(void)
// Throws: None.
//--
bool
-CMIUtilThreadActiveObjBase::ThreadIsActive(void)
+CMIUtilThreadActiveObjBase::ThreadIsActive()
{
// Create a new thread to occupy this threads Run() function
return m_thread.IsActive();
@@ -66,7 +64,7 @@ CMIUtilThreadActiveObjBase::ThreadIsActive(void)
// Throws: None.
//--
bool
-CMIUtilThreadActiveObjBase::ThreadExecute(void)
+CMIUtilThreadActiveObjBase::ThreadExecute()
{
// Create a new thread to occupy this threads Run() function
return m_thread.Start(ThreadEntry, this);
@@ -81,7 +79,7 @@ CMIUtilThreadActiveObjBase::ThreadExecute(void)
// Throws: None.
//--
bool
-CMIUtilThreadActiveObjBase::Acquire(void)
+CMIUtilThreadActiveObjBase::Acquire()
{
// Access to this function is serial
CMIUtilThreadLock serial(m_mutex);
@@ -101,7 +99,7 @@ CMIUtilThreadActiveObjBase::Acquire(void)
// Throws: None.
//--
bool
-CMIUtilThreadActiveObjBase::Release(void)
+CMIUtilThreadActiveObjBase::Release()
{
// Access to this function is serial
CMIUtilThreadLock serial(m_mutex);
@@ -121,7 +119,7 @@ CMIUtilThreadActiveObjBase::Release(void)
// Throws: None.
//--
bool
-CMIUtilThreadActiveObjBase::ThreadKill(void)
+CMIUtilThreadActiveObjBase::ThreadKill()
{
// Access to this function is serial
CMIUtilThreadLock serial(m_mutex);
@@ -141,7 +139,7 @@ CMIUtilThreadActiveObjBase::ThreadKill(void)
// Throws: None.
//--
bool
-CMIUtilThreadActiveObjBase::ThreadJoin(void)
+CMIUtilThreadActiveObjBase::ThreadJoin()
{
return m_thread.Join();
}
@@ -177,7 +175,7 @@ CMIUtilThreadActiveObjBase::ThreadEntry(void *vpThisClass)
// Throws: None.
//--
void
-CMIUtilThreadActiveObjBase::ThreadManage(void)
+CMIUtilThreadActiveObjBase::ThreadManage()
{
bool bAlive = true;
@@ -214,7 +212,7 @@ CMIUtilThreadActiveObjBase::ThreadManage(void)
//---------------------------------------------------------------------------------------
//
-CMIUtilThread::CMIUtilThread(void)
+CMIUtilThread::CMIUtilThread()
: m_pThread(nullptr)
, m_bIsActive(false)
{
@@ -227,7 +225,7 @@ CMIUtilThread::CMIUtilThread(void)
// Return: None.
// Throws: None.
//--
-CMIUtilThread::~CMIUtilThread(void)
+CMIUtilThread::~CMIUtilThread()
{
Join();
}
@@ -241,7 +239,7 @@ CMIUtilThread::~CMIUtilThread(void)
// Throws: None.
//--
bool
-CMIUtilThread::Join(void)
+CMIUtilThread::Join()
{
if (m_pThread != nullptr)
{
@@ -267,7 +265,7 @@ CMIUtilThread::Join(void)
// Throws: None.
//--
bool
-CMIUtilThread::IsActive(void)
+CMIUtilThread::IsActive()
{
// Lock while we access the thread status
CMIUtilThreadLock _lock(m_mutex);
@@ -282,7 +280,7 @@ CMIUtilThread::IsActive(void)
// Throws: None.
//--
void
-CMIUtilThread::Finish(void)
+CMIUtilThread::Finish()
{
// Lock while we access the thread status
CMIUtilThreadLock _lock(m_mutex);
@@ -326,7 +324,7 @@ CMIUtilThread::Start(FnThreadProc vpFn, void *vpArg)
// Throws: None.
//--
void
-CMIUtilThreadMutex::Lock(void)
+CMIUtilThreadMutex::Lock()
{
m_mutex.lock();
}
@@ -339,7 +337,7 @@ CMIUtilThreadMutex::Lock(void)
// Throws: None.
//--
void
-CMIUtilThreadMutex::Unlock(void)
+CMIUtilThreadMutex::Unlock()
{
m_mutex.unlock();
}
@@ -353,7 +351,7 @@ CMIUtilThreadMutex::Unlock(void)
// Throws: None.
//--
bool
-CMIUtilThreadMutex::TryLock(void)
+CMIUtilThreadMutex::TryLock()
{
return m_mutex.try_lock();
}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilThreadBaseStd.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilThreadBaseStd.h
index 504d830..738f295 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilThreadBaseStd.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilThreadBaseStd.h
@@ -6,9 +6,6 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// Copyright: None.
-//--
#pragma once
@@ -26,27 +23,24 @@
//++ ============================================================================
// Details: MI common code utility class. Handle thread mutual exclusion.
// Embed Mutexes in your Active Object and then use them through Locks.
-// Gotchas: None.
-// Authors: Aidan Dodds 10/03/2014.
-// Changes: None.
//--
class CMIUtilThreadMutex
{
// Methods:
public:
- /* ctor */ CMIUtilThreadMutex(void){};
+ /* ctor */ CMIUtilThreadMutex(){}
//
void
- Lock(void); // Wait until mutex can be obtained
+ Lock(); // Wait until mutex can be obtained
void
- Unlock(void); // Release the mutex
+ Unlock(); // Release the mutex
bool
- TryLock(void); // Gain the lock if available
+ TryLock(); // Gain the lock if available
// Overrideable:
public:
// From CMICmnBase
- /* dtor */ virtual ~CMIUtilThreadMutex(void){};
+ /* dtor */ virtual ~CMIUtilThreadMutex(){}
// Attributes:
private:
@@ -55,9 +49,6 @@ class CMIUtilThreadMutex
//++ ============================================================================
// Details: MI common code utility class. Thread object.
-// Gotchas: None.
-// Authors: Aidan Dodds 10/03/2014.
-// Changes: None.
//--
class CMIUtilThread
{
@@ -67,20 +58,20 @@ class CMIUtilThread
// Methods:
public:
- /* ctor */ CMIUtilThread(void);
+ /* ctor */ CMIUtilThread();
//
bool
Start(FnThreadProc vpFn, void *vpArg); // Start execution of this thread
bool
- Join(void); // Wait for this thread to stop
+ Join(); // Wait for this thread to stop
bool
- IsActive(void); // Returns true if this thread is running
+ IsActive(); // Returns true if this thread is running
void
- Finish(void); // Finish this thread
+ Finish(); // Finish this thread
// Overrideable:
public:
- /* dtor */ virtual ~CMIUtilThread(void);
+ /* dtor */ virtual ~CMIUtilThread();
// Methods:
private:
@@ -92,36 +83,33 @@ class CMIUtilThread
//++ ============================================================================
// Details: MI common code utility class. Base class for a worker thread active
// object. Runs an 'captive thread'.
-// Gotchas: None.
-// Authors: Aidan Dodds 10/03/2014..
-// Changes: None.
//--
class CMIUtilThreadActiveObjBase
{
// Methods:
public:
- /* ctor */ CMIUtilThreadActiveObjBase(void);
+ /* ctor */ CMIUtilThreadActiveObjBase();
//
bool
- Acquire(void); // Obtain a reference to this object
+ Acquire(); // Obtain a reference to this object
bool
- Release(void); // Release a reference to this object
+ Release(); // Release a reference to this object
bool
- ThreadIsActive(void); // Return true if this object is running
+ ThreadIsActive(); // Return true if this object is running
bool
- ThreadJoin(void); // Wait for this thread to stop running
+ ThreadJoin(); // Wait for this thread to stop running
bool
- ThreadKill(void); // Force this thread to stop, regardless of references
+ ThreadKill(); // Force this thread to stop, regardless of references
bool
- ThreadExecute(void); // Start this objects execution in another thread
- void ThreadManage(void);
+ ThreadExecute(); // Start this objects execution in another thread
+ void ThreadManage();
// Overrideable:
public:
- /* dtor */ virtual ~CMIUtilThreadActiveObjBase(void);
+ /* dtor */ virtual ~CMIUtilThreadActiveObjBase();
//
// Each thread object must supple a unique name that can be used to locate it
- virtual const CMIUtilString &ThreadGetName(void) const = 0;
+ virtual const CMIUtilString &ThreadGetName() const = 0;
// Statics:
protected:
@@ -133,7 +121,7 @@ class CMIUtilThreadActiveObjBase
virtual bool
ThreadRun(bool &vrIsAlive) = 0; // Call the main worker method
virtual bool
- ThreadFinish(void) = 0; // Finish of what you were doing
+ ThreadFinish() = 0; // Finish of what you were doing
// Attributes:
protected:
@@ -148,9 +136,6 @@ class CMIUtilThreadActiveObjBase
// Details: MI common code utility class. Handle thread resource locking.
// Put Locks inside all the methods of your Active Object that access
// data shared with the captive thread.
-// Gotchas: None.
-// Authors: Aidan Dodds 10/03/2014.
-// Changes: None.
//--
class CMIUtilThreadLock
{
@@ -166,7 +151,7 @@ class CMIUtilThreadLock
// Overrideable:
public:
/* dtor */
- virtual ~CMIUtilThreadLock(void) { m_rMutex.Unlock(); }
+ virtual ~CMIUtilThreadLock() { m_rMutex.Unlock(); }
// Attributes:
private:
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilVariant.cpp b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilVariant.cpp
index dff8072..c5e8643 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilVariant.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilVariant.cpp
@@ -6,8 +6,6 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-// Copyright: None.
-//--
// In-house headers:
#include "MIUtilVariant.h"
@@ -19,7 +17,7 @@
// Return: None.
// Throws: None.
//--
-CMIUtilVariant::CDataObjectBase::CDataObjectBase(void)
+CMIUtilVariant::CDataObjectBase::CDataObjectBase()
{
}
@@ -66,7 +64,7 @@ CMIUtilVariant::CDataObjectBase::CDataObjectBase(CDataObjectBase &&vrwOther)
// Return: None.
// Throws: None.
//--
-CMIUtilVariant::CDataObjectBase::~CDataObjectBase(void)
+CMIUtilVariant::CDataObjectBase::~CDataObjectBase()
{
Destroy();
}
@@ -106,7 +104,7 @@ CMIUtilVariant::CDataObjectBase &CMIUtilVariant::CDataObjectBase::operator=(CDat
// Throws: None.
//--
CMIUtilVariant::CDataObjectBase *
-CMIUtilVariant::CDataObjectBase::CreateCopyOfSelf(void)
+CMIUtilVariant::CDataObjectBase::CreateCopyOfSelf()
{
// Override to implement copying of variant's data object
return new CDataObjectBase();
@@ -120,7 +118,7 @@ CMIUtilVariant::CDataObjectBase::CreateCopyOfSelf(void)
// Throws: None.
//--
bool
-CMIUtilVariant::CDataObjectBase::GetIsDerivedClass(void) const
+CMIUtilVariant::CDataObjectBase::GetIsDerivedClass() const
{
// Override to in the derived class and return true
return false;
@@ -148,7 +146,7 @@ CMIUtilVariant::CDataObjectBase::Copy(const CDataObjectBase &vrOther)
// Throws: None.
//--
void
-CMIUtilVariant::CDataObjectBase::Destroy(void)
+CMIUtilVariant::CDataObjectBase::Destroy()
{
// Do nothing - override to implement
}
@@ -247,7 +245,7 @@ template <typename T> CMIUtilVariant::CDataObject<T> &CMIUtilVariant::CDataObjec
// Return: None.
// Throws: None.
//--
-CMIUtilVariant::CMIUtilVariant(void)
+CMIUtilVariant::CMIUtilVariant()
: m_pDataObject(nullptr)
{
}
@@ -308,7 +306,7 @@ CMIUtilVariant::CMIUtilVariant(CMIUtilVariant &&vrwOther)
// Return: None.
// Throws: None.
//--
-CMIUtilVariant::~CMIUtilVariant(void)
+CMIUtilVariant::~CMIUtilVariant()
{
Destroy();
}
@@ -354,7 +352,7 @@ CMIUtilVariant &CMIUtilVariant::operator=(CMIUtilVariant &&vrwOther)
// Throws: None.
//--
void
-CMIUtilVariant::Destroy(void)
+CMIUtilVariant::Destroy()
{
if (m_pDataObject != nullptr)
delete m_pDataObject;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilVariant.h b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilVariant.h
index a6c3ba4..7fddb9f 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilVariant.h
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilVariant.h
@@ -6,8 +6,6 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-// Copyright: None.
-//--
#pragma once
@@ -20,22 +18,19 @@
// data object specified is made and stored in *this wrapper. When the
// *this object is destroyed the data object hold within calls its
// destructor should it have one.
-// Gotchas: None.
-// Authors: Illya Rudkin 18/06/2014.
-// Changes: None.
//--
class CMIUtilVariant
{
// Methods:
public:
- /* ctor */ CMIUtilVariant(void);
+ /* ctor */ CMIUtilVariant();
/* ctor */ CMIUtilVariant(const CMIUtilVariant &vrOther);
/* ctor */ CMIUtilVariant(CMIUtilVariant &vrOther);
/* ctor */ CMIUtilVariant(CMIUtilVariant &&vrwOther);
- /* dtor */ ~CMIUtilVariant(void);
+ /* dtor */ ~CMIUtilVariant();
template <typename T> void Set(const T &vArg);
- template <typename T> T *Get(void) const;
+ template <typename T> T *Get() const;
CMIUtilVariant &operator=(const CMIUtilVariant &vrOther);
CMIUtilVariant &operator=(CMIUtilVariant &&vrwOther);
@@ -52,7 +47,7 @@ class CMIUtilVariant
{
// Methods:
public:
- /* ctor */ CDataObjectBase(void);
+ /* ctor */ CDataObjectBase();
/* ctor */ CDataObjectBase(const CDataObjectBase &vrOther);
/* ctor */ CDataObjectBase(CDataObjectBase &vrOther);
/* ctor */ CDataObjectBase(CDataObjectBase &&vrwOther);
@@ -62,14 +57,14 @@ class CMIUtilVariant
// Overrideable:
public:
- virtual ~CDataObjectBase(void);
- virtual CDataObjectBase *CreateCopyOfSelf(void);
- virtual bool GetIsDerivedClass(void) const;
+ virtual ~CDataObjectBase();
+ virtual CDataObjectBase *CreateCopyOfSelf();
+ virtual bool GetIsDerivedClass() const;
// Overrideable:
protected:
virtual void Copy(const CDataObjectBase &vrOther);
- virtual void Destroy(void);
+ virtual void Destroy();
};
//++ ----------------------------------------------------------------------
@@ -81,7 +76,7 @@ class CMIUtilVariant
{
// Methods:
public:
- /* ctor */ CDataObject(void);
+ /* ctor */ CDataObject();
/* ctor */ CDataObject(const T &vArg);
/* ctor */ CDataObject(const CDataObject &vrOther);
/* ctor */ CDataObject(CDataObject &vrOther);
@@ -90,14 +85,14 @@ class CMIUtilVariant
CDataObject &operator=(const CDataObject &vrOther);
CDataObject &operator=(CDataObject &&vrwOther);
//
- T &GetDataObject(void);
+ T &GetDataObject();
// Overridden:
public:
// From CDataObjectBase
- ~CDataObject(void) override;
- CDataObjectBase *CreateCopyOfSelf(void) override;
- bool GetIsDerivedClass(void) const override;
+ ~CDataObject() override;
+ CDataObjectBase *CreateCopyOfSelf() override;
+ bool GetIsDerivedClass() const override;
// Overrideable:
private:
@@ -106,7 +101,7 @@ class CMIUtilVariant
// Overridden:
private:
// From CDataObjectBase
- void Destroy(void) override;
+ void Destroy() override;
// Attributes:
private:
@@ -115,7 +110,7 @@ class CMIUtilVariant
// Methods
private:
- void Destroy(void);
+ void Destroy();
void Copy(const CMIUtilVariant &vrOther);
// Attributes:
@@ -134,7 +129,7 @@ class CMIUtilVariant
// Return: None.
// Throws: None.
//--
-template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject(void)
+template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject()
{
}
@@ -158,7 +153,7 @@ template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject(const T &vArg)
// Return: None.
// Throws: None.
//--
-template <typename T> CMIUtilVariant::CDataObject<T>::~CDataObject(void)
+template <typename T> CMIUtilVariant::CDataObject<T>::~CDataObject()
{
Destroy();
}
@@ -172,7 +167,7 @@ template <typename T> CMIUtilVariant::CDataObject<T>::~CDataObject(void)
//--
template <typename T>
T &
-CMIUtilVariant::CDataObject<T>::GetDataObject(void)
+CMIUtilVariant::CDataObject<T>::GetDataObject()
{
return m_dataObj;
}
@@ -186,7 +181,7 @@ CMIUtilVariant::CDataObject<T>::GetDataObject(void)
//--
template <typename T>
CMIUtilVariant::CDataObjectBase *
-CMIUtilVariant::CDataObject<T>::CreateCopyOfSelf(void)
+CMIUtilVariant::CDataObject<T>::CreateCopyOfSelf()
{
CDataObject *pCopy = new CDataObject<T>(m_dataObj);
@@ -203,7 +198,7 @@ CMIUtilVariant::CDataObject<T>::CreateCopyOfSelf(void)
//--
template <typename T>
bool
-CMIUtilVariant::CDataObject<T>::GetIsDerivedClass(void) const
+CMIUtilVariant::CDataObject<T>::GetIsDerivedClass() const
{
return true;
}
@@ -233,7 +228,7 @@ CMIUtilVariant::CDataObject<T>::Duplicate(const CDataObject &vrOther)
//--
template <typename T>
void
-CMIUtilVariant::CDataObject<T>::Destroy(void)
+CMIUtilVariant::CDataObject<T>::Destroy()
{
CDataObjectBase::Destroy();
}
@@ -266,7 +261,7 @@ CMIUtilVariant::Set(const T &vArg)
//--
template <typename T>
T *
-CMIUtilVariant::Get(void) const
+CMIUtilVariant::Get() const
{
if ((m_pDataObject != nullptr) && m_pDataObject->GetIsDerivedClass())
{
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/exports b/contrib/llvm/tools/lldb/tools/lldb-mi/lldb-mi.exports
index e69de29..e69de29 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-server/exports
+++ b/contrib/llvm/tools/lldb/tools/lldb-mi/lldb-mi.exports
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/Acceptor.cpp b/contrib/llvm/tools/lldb/tools/lldb-server/Acceptor.cpp
new file mode 100644
index 0000000..6343195
--- /dev/null
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/Acceptor.cpp
@@ -0,0 +1,170 @@
+//===-- Acceptor.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Acceptor.h"
+
+#include "llvm/ADT/StringRef.h"
+
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
+#include "lldb/Host/common/TCPSocket.h"
+
+#include "Utility/UriParser.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::lldb_server;
+using namespace llvm;
+
+namespace {
+
+struct SocketScheme
+{
+ const char* m_scheme;
+ const Socket::SocketProtocol m_protocol;
+};
+
+SocketScheme socket_schemes[] = {
+ {"tcp", Socket::ProtocolTcp},
+ {"udp", Socket::ProtocolUdp},
+ {"unix", Socket::ProtocolUnixDomain},
+ {"unix-abstract", Socket::ProtocolUnixAbstract},
+};
+
+bool
+FindProtocolByScheme(const char* scheme, Socket::SocketProtocol& protocol)
+{
+ for (auto s: socket_schemes)
+ {
+ if (!strcmp(s.m_scheme, scheme))
+ {
+ protocol = s.m_protocol;
+ return true;
+ }
+ }
+ return false;
+}
+
+const char*
+FindSchemeByProtocol(const Socket::SocketProtocol protocol)
+{
+ for (auto s: socket_schemes)
+ {
+ if (s.m_protocol == protocol)
+ return s.m_scheme;
+ }
+ return nullptr;
+}
+
+}
+
+Error
+Acceptor::Listen(int backlog)
+{
+ return m_listener_socket_up->Listen(StringRef(m_name.c_str()),
+ backlog);
+}
+
+Error
+Acceptor::Accept(const bool child_processes_inherit, Connection *&conn)
+{
+ Socket* conn_socket = nullptr;
+ auto error = m_listener_socket_up->Accept(StringRef(m_name.c_str()),
+ child_processes_inherit,
+ conn_socket);
+ if (error.Success())
+ conn = new ConnectionFileDescriptor(conn_socket);
+
+ return error;
+}
+
+Socket::SocketProtocol
+Acceptor::GetSocketProtocol() const
+{
+ return m_listener_socket_up->GetSocketProtocol();
+}
+
+const char*
+Acceptor::GetSocketScheme() const
+{
+ return FindSchemeByProtocol(GetSocketProtocol());
+}
+
+std::string
+Acceptor::GetLocalSocketId() const
+{
+ return m_local_socket_id();
+}
+
+std::unique_ptr<Acceptor>
+Acceptor::Create(StringRef name, const bool child_processes_inherit, Error &error)
+{
+ error.Clear();
+
+ Socket::SocketProtocol socket_protocol = Socket::ProtocolUnixDomain;
+ int port;
+ std::string scheme, host, path;
+ // Try to match socket name as URL - e.g., tcp://localhost:5555
+ if (UriParser::Parse(name.str(), scheme, host, port, path))
+ {
+ if (!FindProtocolByScheme(scheme.c_str(), socket_protocol))
+ error.SetErrorStringWithFormat("Unknown protocol scheme \"%s\"", scheme.c_str());
+ else
+ name = name.drop_front(scheme.size() + strlen("://"));
+ }
+ else
+ {
+ std::string host_str;
+ std::string port_str;
+ int32_t port = INT32_MIN;
+ // Try to match socket name as $host:port - e.g., localhost:5555
+ if (Socket::DecodeHostAndPort (name, host_str, port_str, port, nullptr))
+ socket_protocol = Socket::ProtocolTcp;
+ }
+
+ if (error.Fail())
+ return std::unique_ptr<Acceptor>();
+
+ std::unique_ptr<Socket> listener_socket_up = Socket::Create(
+ socket_protocol, child_processes_inherit, error);
+
+ LocalSocketIdFunc local_socket_id;
+ if (error.Success())
+ {
+ if (listener_socket_up->GetSocketProtocol() == Socket::ProtocolTcp)
+ {
+ TCPSocket* tcp_socket = static_cast<TCPSocket*>(listener_socket_up.get());
+ local_socket_id = [tcp_socket]() {
+ auto local_port = tcp_socket->GetLocalPortNumber();
+ return (local_port != 0) ? std::to_string(local_port) : "";
+ };
+ }
+ else
+ {
+ const std::string socket_name = name;
+ local_socket_id = [socket_name](){
+ return socket_name;
+ };
+ }
+
+ return std::unique_ptr<Acceptor>(
+ new Acceptor(std::move(listener_socket_up), name, local_socket_id));
+ }
+
+ return std::unique_ptr<Acceptor>();
+}
+
+Acceptor::Acceptor(std::unique_ptr<Socket> &&listener_socket,
+ StringRef name,
+ const LocalSocketIdFunc &local_socket_id)
+ : m_listener_socket_up(std::move(listener_socket)),
+ m_name(name.str()),
+ m_local_socket_id(local_socket_id)
+{
+}
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/Acceptor.h b/contrib/llvm/tools/lldb/tools/lldb-server/Acceptor.h
new file mode 100644
index 0000000..37fba26
--- /dev/null
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/Acceptor.h
@@ -0,0 +1,68 @@
+//===-- Acceptor.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef lldb_server_Acceptor_h_
+#define lldb_server_Acceptor_h_
+
+#include "lldb/Core/Connection.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Host/Socket.h"
+
+#include <functional>
+#include <memory>
+#include <string>
+
+namespace llvm
+{
+ class StringRef;
+}
+
+namespace lldb_private {
+namespace lldb_server {
+
+class Acceptor
+{
+public:
+ virtual ~Acceptor() = default;
+
+ Error
+ Listen(int backlog);
+
+ Error
+ Accept(const bool child_processes_inherit, Connection *&conn);
+
+ static std::unique_ptr<Acceptor>
+ Create(llvm::StringRef name, const bool child_processes_inherit, Error &error);
+
+ Socket::SocketProtocol
+ GetSocketProtocol() const;
+
+ const char*
+ GetSocketScheme() const;
+
+ // Returns either TCP port number as string or domain socket path.
+ // Empty string is returned in case of error.
+ std::string
+ GetLocalSocketId() const;
+
+private:
+ typedef std::function<std::string()> LocalSocketIdFunc;
+
+ Acceptor(std::unique_ptr<Socket> &&listener_socket,
+ llvm::StringRef name,
+ const LocalSocketIdFunc &local_socket_id);
+
+ const std::unique_ptr<Socket> m_listener_socket_up;
+ const std::string m_name;
+ const LocalSocketIdFunc m_local_socket_id;
+};
+
+} // namespace lldb_server
+} // namespace lldb_private
+
+#endif // lldb_server_Acceptor_h_
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/LLDBServerUtilities.cpp b/contrib/llvm/tools/lldb/tools/lldb-server/LLDBServerUtilities.cpp
index 8df4875..438d9f1 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-server/LLDBServerUtilities.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/LLDBServerUtilities.cpp
@@ -42,7 +42,7 @@ LLDBServerUtilities::SetupLogging(const std::string& log_file,
}
SmallVector<StringRef, 32> channel_array;
- log_channels.split(channel_array, ":");
+ log_channels.split(channel_array, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
for (auto channel_with_categories : channel_array)
{
StreamString error_stream;
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp
index 30bb2d6..df8cb6e 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp
@@ -9,7 +9,6 @@
// C Includes
#include <errno.h>
-#include <getopt.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -25,17 +24,16 @@
// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-#include "lldb/Core/ConnectionMachPort.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
-#include "lldb/Host/HostThread.h"
+#include "lldb/Host/HostGetOpt.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/Pipe.h"
#include "lldb/Host/Socket.h"
#include "lldb/Host/StringConvert.h"
-#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Target/Platform.h"
+#include "Acceptor.h"
#include "LLDBServerUtilities.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
@@ -54,15 +52,6 @@ using namespace lldb_private;
using namespace lldb_private::lldb_server;
using namespace lldb_private::process_gdb_remote;
-// lldb-gdbserver state
-
-namespace
-{
-HostThread s_listen_thread;
- std::unique_ptr<ConnectionFileDescriptor> s_listen_connection_up;
- std::string s_listen_url;
-}
-
//----------------------------------------------------------------------
// option descriptors for getopt_long_only()
//----------------------------------------------------------------------
@@ -263,64 +252,16 @@ handle_launch (GDBRemoteCommunicationServerLLGS &gdb_server, int argc, const cha
}
}
-static lldb::thread_result_t
-ListenThread (lldb::thread_arg_t /* arg */)
-{
- Error error;
-
- if (s_listen_connection_up)
- {
- // Do the listen on another thread so we can continue on...
- if (s_listen_connection_up->Connect(s_listen_url.c_str(), &error) != eConnectionStatusSuccess)
- s_listen_connection_up.reset();
- }
- return nullptr;
-}
-
-static Error
-StartListenThread (const char *hostname, uint16_t port)
-{
- Error error;
- if (s_listen_thread.IsJoinable())
- {
- error.SetErrorString("listen thread already running");
- }
- else
- {
- char listen_url[512];
- if (hostname && hostname[0])
- snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, port);
- else
- snprintf(listen_url, sizeof(listen_url), "listen://%i", port);
-
- s_listen_url = listen_url;
- s_listen_connection_up.reset (new ConnectionFileDescriptor ());
- s_listen_thread = ThreadLauncher::LaunchThread(listen_url, ListenThread, nullptr, &error);
- }
- return error;
-}
-
-static bool
-JoinListenThread ()
-{
- if (s_listen_thread.IsJoinable())
- s_listen_thread.Join(nullptr);
- return true;
-}
-
Error
-WritePortToPipe(Pipe &port_pipe, const uint16_t port)
+writeSocketIdToPipe(Pipe &port_pipe, const std::string &socket_id)
{
- char port_str[64];
- const auto port_str_len = ::snprintf(port_str, sizeof(port_str), "%u", port);
-
size_t bytes_written = 0;
// Write the port number as a C string with the NULL terminator.
- return port_pipe.Write(port_str, port_str_len + 1, bytes_written);
+ return port_pipe.Write(socket_id.c_str(), socket_id.size() + 1, bytes_written);
}
Error
-writePortToPipe(const char *const named_pipe_path, const uint16_t port)
+writeSocketIdToPipe(const char *const named_pipe_path, const std::string &socket_id)
{
Pipe port_name_pipe;
// Wait for 10 seconds for pipe to be opened.
@@ -328,17 +269,17 @@ writePortToPipe(const char *const named_pipe_path, const uint16_t port)
std::chrono::seconds{10});
if (error.Fail())
return error;
- return WritePortToPipe(port_name_pipe, port);
+ return writeSocketIdToPipe(port_name_pipe, socket_id);
}
Error
-writePortToPipe(int unnamed_pipe_fd, const uint16_t port)
+writeSocketIdToPipe(int unnamed_pipe_fd, const std::string &socket_id)
{
#if defined(_WIN32)
return Error("Unnamed pipes are not supported on Windows.");
#else
Pipe port_pipe{Pipe::kInvalidDescriptor, unnamed_pipe_fd};
- return WritePortToPipe(port_pipe, port);
+ return writeSocketIdToPipe(port_pipe, socket_id);
#endif
}
@@ -370,14 +311,8 @@ ConnectToRemote(MainLoop &mainloop, GDBRemoteCommunicationServerLLGS &gdb_server
connection_port = final_host_and_port.substr (colon_pos + 1);
connection_portno = StringConvert::ToUInt32 (connection_port.c_str (), 0);
}
- else
- {
- fprintf (stderr, "failed to parse host and port from connection string '%s'\n", final_host_and_port.c_str ());
- display_usage (progname, subcommand);
- exit (1);
- }
- std::unique_ptr<ConnectionFileDescriptor> connection_up;
+ std::unique_ptr<Connection> connection_up;
if (reverse_connect)
{
@@ -410,66 +345,51 @@ ConnectToRemote(MainLoop &mainloop, GDBRemoteCommunicationServerLLGS &gdb_server
}
else
{
- // llgs will listen for connections on the given port from the given address.
- // Start the listener on a new thread. We need to do this so we can resolve the
- // bound listener port.
- StartListenThread(connection_host.c_str (), static_cast<uint16_t> (connection_portno));
- printf ("Listening to port %s for a connection from %s...\n", connection_port.c_str (), connection_host.c_str ());
-
- // If we have a named pipe to write the port number back to, do that now.
- if (named_pipe_path && named_pipe_path[0] && connection_portno == 0)
+ std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create(final_host_and_port, false, error));
+ if (error.Fail())
+ {
+ fprintf(stderr, "failed to create acceptor: %s", error.AsCString());
+ exit(1);
+ }
+ error = acceptor_up->Listen(1);
+ if (error.Fail())
{
- const uint16_t bound_port = s_listen_connection_up->GetListeningPort (10);
- if (bound_port > 0)
+ fprintf(stderr, "failed to listen: %s\n", error.AsCString());
+ exit(1);
+ }
+ const std::string socket_id = acceptor_up->GetLocalSocketId();
+ if (!socket_id.empty())
+ {
+ // If we have a named pipe to write the socket id back to, do that now.
+ if (named_pipe_path && named_pipe_path[0])
{
- error = writePortToPipe (named_pipe_path, bound_port);
+ error = writeSocketIdToPipe (named_pipe_path, socket_id);
if (error.Fail ())
- {
- fprintf (stderr, "failed to write to the named pipe \'%s\': %s", named_pipe_path, error.AsCString());
- }
+ fprintf (stderr, "failed to write to the named pipe \'%s\': %s",
+ named_pipe_path, error.AsCString());
}
- else
+ // If we have an unnamed pipe to write the socket id back to, do that now.
+ else if (unnamed_pipe_fd >= 0)
{
- fprintf (stderr, "unable to get the bound port for the listening connection\n");
- }
- }
-
- // If we have an unnamed pipe to write the port number back to, do that now.
- if (unnamed_pipe_fd >= 0 && connection_portno == 0)
- {
- const uint16_t bound_port = s_listen_connection_up->GetListeningPort(10);
- if (bound_port > 0)
- {
- error = writePortToPipe(unnamed_pipe_fd, bound_port);
+ error = writeSocketIdToPipe(unnamed_pipe_fd, socket_id);
if (error.Fail())
- {
fprintf(stderr, "failed to write to the unnamed pipe: %s",
error.AsCString());
- }
- }
- else
- {
- fprintf(stderr, "unable to get the bound port for the listening connection\n");
}
}
-
- // Join the listener thread.
- if (!JoinListenThread ())
+ else
{
- fprintf (stderr, "failed to join the listener thread\n");
- display_usage (progname, subcommand);
- exit (1);
+ fprintf (stderr, "unable to get the socket id for the listening connection\n");
}
- // Ensure we connected.
- if (s_listen_connection_up)
- connection_up = std::move(s_listen_connection_up);
- else
+ Connection* conn = nullptr;
+ error = acceptor_up->Accept(false, conn);
+ if (error.Fail())
{
- fprintf (stderr, "failed to connect to '%s': %s\n", final_host_and_port.c_str (), error.AsCString ());
- display_usage (progname, subcommand);
- exit (1);
+ printf ("failed to accept new connection: %s\n", error.AsCString());
+ exit(1);
}
+ connection_up.reset(conn);
}
error = gdb_server.InitializeConnection (std::move(connection_up));
if (error.Fail())
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/lldb-platform.cpp b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-platform.cpp
index 4dfa7d2..3292080 100644
--- a/contrib/llvm/tools/lldb/tools/lldb-server/lldb-platform.cpp
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-platform.cpp
@@ -23,15 +23,17 @@
#include <fstream>
// Other libraries and framework includes
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FileUtilities.h"
+
#include "lldb/Core/Error.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostGetOpt.h"
#include "lldb/Host/OptionParser.h"
-#include "lldb/Host/Socket.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
+#include "lldb/Host/common/TCPSocket.h"
+#include "Acceptor.h"
#include "LLDBServerUtilities.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
@@ -61,7 +63,7 @@ static struct option g_long_options[] =
{ "gdbserver-port", required_argument, NULL, 'P' },
{ "min-gdbserver-port", required_argument, NULL, 'm' },
{ "max-gdbserver-port", required_argument, NULL, 'M' },
- { "port-file", required_argument, NULL, 'f' },
+ { "socket-file", required_argument, NULL, 'f' },
{ "server", no_argument, &g_server, 1 },
{ NULL, 0, NULL, 0 }
};
@@ -100,9 +102,9 @@ display_usage (const char *progname, const char *subcommand)
}
static Error
-save_port_to_file(const uint16_t port, const FileSpec &port_file_spec)
+save_socket_id_to_file(const std::string &socket_id, const FileSpec &file_spec)
{
- FileSpec temp_file_spec(port_file_spec.GetDirectory().AsCString(), false);
+ FileSpec temp_file_spec(file_spec.GetDirectory().AsCString(), false);
auto error = FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault);
if (error.Fail())
return Error("Failed to create directory %s: %s", temp_file_spec.GetCString(), error.AsCString());
@@ -119,13 +121,13 @@ save_port_to_file(const uint16_t port, const FileSpec &port_file_spec)
std::ofstream temp_file(temp_file_path.c_str(), std::ios::out);
if (!temp_file.is_open())
return Error("Failed to open temp file %s", temp_file_path.c_str());
- temp_file << port;
+ temp_file << socket_id;
}
- err_code = llvm::sys::fs::rename(temp_file_path.c_str(), port_file_spec.GetPath().c_str());
+ err_code = llvm::sys::fs::rename(temp_file_path.c_str(), file_spec.GetPath().c_str());
if (err_code)
return Error("Failed to rename file %s to %s: %s",
- temp_file_path.c_str(), port_file_spec.GetPath().c_str(), err_code.message().c_str());
+ temp_file_path.c_str(), file_spec.GetPath().c_str(), err_code.message().c_str());
tmp_file_remover.releaseFile();
return Error();
@@ -156,7 +158,7 @@ main_platform (int argc, char *argv[])
int max_gdbserver_port = 0;
uint16_t port_offset = 0;
- FileSpec port_file;
+ FileSpec socket_file;
bool show_usage = false;
int option_error = 0;
int socket_error = -1;
@@ -191,9 +193,9 @@ main_platform (int argc, char *argv[])
log_channels = StringRef(optarg);
break;
- case 'f': // Port file
+ case 'f': // Socket file
if (optarg && optarg[0])
- port_file.SetFile(optarg, false);
+ socket_file.SetFile(optarg, false);
break;
case 'p':
@@ -282,36 +284,46 @@ main_platform (int argc, char *argv[])
display_usage(progname, subcommand);
exit(option_error);
}
-
- std::unique_ptr<Socket> listening_socket_up;
- Socket *socket = nullptr;
- const bool children_inherit_listen_socket = false;
+ // Skip any options we consumed with getopt_long_only.
+ argc -= optind;
+ argv += optind;
+ lldb_private::Args inferior_arguments;
+ inferior_arguments.SetArguments(argc, const_cast<const char**>(argv));
+
+ const bool children_inherit_listen_socket = false;
// the test suite makes many connections in parallel, let's not miss any.
- // The highest this should get reasonably is a function of the number
- // of target CPUs. For now, let's just use 100
+ // The highest this should get reasonably is a function of the number
+ // of target CPUs. For now, let's just use 100.
const int backlog = 100;
- error = Socket::TcpListen(listen_host_port.c_str(), children_inherit_listen_socket, socket, NULL, backlog);
+
+ std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create(listen_host_port, children_inherit_listen_socket, error));
if (error.Fail())
{
- printf("error: %s\n", error.AsCString());
+ fprintf(stderr, "failed to create acceptor: %s", error.AsCString());
exit(socket_error);
}
- listening_socket_up.reset(socket);
- printf ("Listening for a connection from %u...\n", listening_socket_up->GetLocalPortNumber());
- if (port_file)
+
+ error = acceptor_up->Listen(backlog);
+ if (error.Fail())
+ {
+ printf("failed to listen: %s\n", error.AsCString());
+ exit(socket_error);
+ }
+ if (socket_file)
{
- error = save_port_to_file(listening_socket_up->GetLocalPortNumber(), port_file);
+ error = save_socket_id_to_file(acceptor_up->GetLocalSocketId(), socket_file);
if (error.Fail())
{
- fprintf(stderr, "failed to write port to %s: %s", port_file.GetPath().c_str(), error.AsCString());
+ fprintf(stderr, "failed to write socket id to %s: %s\n", socket_file.GetPath().c_str(), error.AsCString());
return 1;
}
}
do {
- GDBRemoteCommunicationServerPlatform platform;
-
+ GDBRemoteCommunicationServerPlatform platform(acceptor_up->GetSocketProtocol(),
+ acceptor_up->GetSocketScheme());
+
if (port_offset > 0)
platform.SetPortOffset(port_offset);
@@ -321,8 +333,8 @@ main_platform (int argc, char *argv[])
}
const bool children_inherit_accept_socket = true;
- socket = nullptr;
- error = listening_socket_up->BlockingAccept(listen_host_port.c_str(), children_inherit_accept_socket, socket);
+ Connection* conn = nullptr;
+ error = acceptor_up->Accept(children_inherit_accept_socket, conn);
if (error.Fail())
{
printf ("error: %s\n", error.AsCString());
@@ -336,8 +348,7 @@ main_platform (int argc, char *argv[])
if (fork())
{
// Parent doesn't need a connection to the lldb client
- delete socket;
- socket = nullptr;
+ delete conn;
// Parent will continue to listen for new connections.
continue;
@@ -347,19 +358,35 @@ main_platform (int argc, char *argv[])
// Child process will handle the connection and exit.
g_server = 0;
// Listening socket is owned by parent process.
- listening_socket_up.release();
+ acceptor_up.release();
}
}
else
{
// If not running as a server, this process will not accept
// connections while a connection is active.
- listening_socket_up.reset();
+ acceptor_up.reset();
}
- platform.SetConnection (new ConnectionFileDescriptor(socket));
+ platform.SetConnection (conn);
if (platform.IsConnected())
{
+ if (inferior_arguments.GetArgumentCount() > 0)
+ {
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+ uint16_t port = 0;
+ std::string socket_name;
+ Error error = platform.LaunchGDBServer(inferior_arguments,
+ "", // hostname
+ pid,
+ port,
+ socket_name);
+ if (error.Success())
+ platform.SetPendingGdbServer(pid, port, socket_name);
+ else
+ fprintf(stderr, "failed to start gdbserver: %s\n", error.AsCString());
+ }
+
// After we connected, we need to get an initial ack from...
if (platform.HandshakeWithClient())
{
diff --git a/contrib/llvm/tools/lldb/tools/lldb-server/lldb-server.exports b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-server.exports
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/llvm/tools/lldb/tools/lldb-server/lldb-server.exports
diff --git a/contrib/llvm/tools/lli/ChildTarget/ChildTarget.cpp b/contrib/llvm/tools/lli/ChildTarget/ChildTarget.cpp
index 6c537d4..0b75e20 100644
--- a/contrib/llvm/tools/lli/ChildTarget/ChildTarget.cpp
+++ b/contrib/llvm/tools/lli/ChildTarget/ChildTarget.cpp
@@ -1,244 +1,69 @@
-#include "llvm/Config/config.h"
-#include "../RPCChannel.h"
-#include "../RemoteTarget.h"
-#include "../RemoteTargetMessage.h"
-#include "llvm/Support/Memory.h"
-#include <assert.h>
-#include <map>
-#include <stdint.h>
-#include <string>
-#include <vector>
+#include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h"
+#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Process.h"
+#include <sstream>
-using namespace llvm;
+#include "../RemoteJITUtils.h"
-class LLIChildTarget {
-public:
- void initialize();
- LLIMessageType waitForIncomingMessage();
- void handleMessage(LLIMessageType messageType);
- RemoteTarget *RT;
- RPCChannel RPC;
+using namespace llvm;
+using namespace llvm::orc;
+using namespace llvm::sys;
-private:
- // Incoming message handlers
- void handleAllocateSpace();
- void handleLoadSection(bool IsCode);
- void handleExecute();
+#ifdef __x86_64__
+typedef OrcX86_64 HostOrcArch;
+#else
+typedef OrcGenericArchitecture HostOrcArch;
+#endif
- // Outgoing message handlers
- void sendChildActive();
- void sendAllocationResult(uint64_t Addr);
- void sendLoadStatus(uint32_t Status);
- void sendExecutionComplete(int Result);
+int main(int argc, char *argv[]) {
- // OS-specific functions
- void initializeConnection();
- int WriteBytes(const void *Data, size_t Size) {
- return RPC.WriteBytes(Data, Size) ? Size : -1;
+ if (argc != 3) {
+ errs() << "Usage: " << argv[0] << " <input fd> <output fd>\n";
+ return 1;
}
- int ReadBytes(void *Data, size_t Size) {
- return RPC.ReadBytes(Data, Size) ? Size : -1;
- }
-
- // Communication handles (OS-specific)
- void *ConnectionData;
-};
-
-int main() {
- LLIChildTarget ThisChild;
- ThisChild.RT = new RemoteTarget();
- ThisChild.initialize();
- LLIMessageType MsgType;
- do {
- MsgType = ThisChild.waitForIncomingMessage();
- ThisChild.handleMessage(MsgType);
- } while (MsgType != LLI_Terminate &&
- MsgType != LLI_Error);
- delete ThisChild.RT;
- return 0;
-}
-// Public methods
-void LLIChildTarget::initialize() {
- RPC.createClient();
- sendChildActive();
-}
+ int InFD;
+ int OutFD;
+ {
+ std::istringstream InFDStream(argv[1]), OutFDStream(argv[2]);
+ InFDStream >> InFD;
+ OutFDStream >> OutFD;
+ }
-LLIMessageType LLIChildTarget::waitForIncomingMessage() {
- int32_t MsgType = -1;
- if (ReadBytes(&MsgType, 4) > 0)
- return (LLIMessageType)MsgType;
- return LLI_Error;
-}
+ if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
+ errs() << "Error loading program symbols.\n";
+ return 1;
+ }
-void LLIChildTarget::handleMessage(LLIMessageType messageType) {
- switch (messageType) {
- case LLI_AllocateSpace:
- handleAllocateSpace();
- break;
- case LLI_LoadCodeSection:
- handleLoadSection(true);
- break;
- case LLI_LoadDataSection:
- handleLoadSection(false);
- break;
- case LLI_Execute:
- handleExecute();
- break;
- case LLI_Terminate:
- RT->stop();
- break;
+ auto SymbolLookup = [](const std::string &Name) {
+ return RTDyldMemoryManager::getSymbolAddressInProcess(Name);
+ };
+
+ FDRPCChannel Channel(InFD, OutFD);
+ typedef remote::OrcRemoteTargetServer<FDRPCChannel, HostOrcArch> JITServer;
+ JITServer Server(Channel, SymbolLookup);
+
+ while (1) {
+ JITServer::JITProcId Id = JITServer::InvalidId;
+ if (auto EC = Server.getNextProcId(Id)) {
+ errs() << "Error: " << EC.message() << "\n";
+ return 1;
+ }
+ switch (Id) {
+ case JITServer::TerminateSessionId:
+ return 0;
default:
- // FIXME: Handle error!
- break;
+ if (auto EC = Server.handleKnownProcedure(Id)) {
+ errs() << "Error: " << EC.message() << "\n";
+ return 1;
+ }
+ }
}
-}
-
-// Incoming message handlers
-void LLIChildTarget::handleAllocateSpace() {
- // Read and verify the message data size.
- uint32_t DataSize = 0;
- int rc = ReadBytes(&DataSize, 4);
- (void)rc;
- assert(rc == 4);
- assert(DataSize == 8);
-
- // Read the message arguments.
- uint32_t Alignment = 0;
- uint32_t AllocSize = 0;
- rc = ReadBytes(&Alignment, 4);
- assert(rc == 4);
- rc = ReadBytes(&AllocSize, 4);
- assert(rc == 4);
-
- // Allocate the memory.
- uint64_t Addr;
- RT->allocateSpace(AllocSize, Alignment, Addr);
-
- // Send AllocationResult message.
- sendAllocationResult(Addr);
-}
-
-void LLIChildTarget::handleLoadSection(bool IsCode) {
- // Read the message data size.
- uint32_t DataSize = 0;
- int rc = ReadBytes(&DataSize, 4);
- (void)rc;
- assert(rc == 4);
-
- // Read the target load address.
- uint64_t Addr = 0;
- rc = ReadBytes(&Addr, 8);
- assert(rc == 8);
- size_t BufferSize = DataSize - 8;
-
- if (!RT->isAllocatedMemory(Addr, BufferSize))
- return sendLoadStatus(LLI_Status_NotAllocated);
-
- // Read section data into previously allocated buffer
- rc = ReadBytes((void*)Addr, BufferSize);
- if (rc != (int)(BufferSize))
- return sendLoadStatus(LLI_Status_IncompleteMsg);
-
- // If IsCode, mark memory executable
- if (IsCode)
- sys::Memory::InvalidateInstructionCache((void *)Addr, BufferSize);
-
- // Send MarkLoadComplete message.
- sendLoadStatus(LLI_Status_Success);
-}
-
-void LLIChildTarget::handleExecute() {
- // Read the message data size.
- uint32_t DataSize = 0;
- int rc = ReadBytes(&DataSize, 4);
- (void)rc;
- assert(rc == 4);
- assert(DataSize == 8);
-
- // Read the target address.
- uint64_t Addr = 0;
- rc = ReadBytes(&Addr, 8);
- assert(rc == 8);
-
- // Call function
- int32_t Result = -1;
- RT->executeCode(Addr, Result);
-
- // Send ExecutionResult message.
- sendExecutionComplete(Result);
-}
-
-// Outgoing message handlers
-void LLIChildTarget::sendChildActive() {
- // Write the message type.
- uint32_t MsgType = (uint32_t)LLI_ChildActive;
- int rc = WriteBytes(&MsgType, 4);
- (void)rc;
- assert(rc == 4);
-
- // Write the data size.
- uint32_t DataSize = 0;
- rc = WriteBytes(&DataSize, 4);
- assert(rc == 4);
-}
-
-void LLIChildTarget::sendAllocationResult(uint64_t Addr) {
- // Write the message type.
- uint32_t MsgType = (uint32_t)LLI_AllocationResult;
- int rc = WriteBytes(&MsgType, 4);
- (void)rc;
- assert(rc == 4);
-
- // Write the data size.
- uint32_t DataSize = 8;
- rc = WriteBytes(&DataSize, 4);
- assert(rc == 4);
-
- // Write the allocated address.
- rc = WriteBytes(&Addr, 8);
- assert(rc == 8);
-}
-
-void LLIChildTarget::sendLoadStatus(uint32_t Status) {
- // Write the message type.
- uint32_t MsgType = (uint32_t)LLI_LoadResult;
- int rc = WriteBytes(&MsgType, 4);
- (void)rc;
- assert(rc == 4);
-
- // Write the data size.
- uint32_t DataSize = 4;
- rc = WriteBytes(&DataSize, 4);
- assert(rc == 4);
-
- // Write the result.
- rc = WriteBytes(&Status, 4);
- assert(rc == 4);
-}
-
-void LLIChildTarget::sendExecutionComplete(int Result) {
- // Write the message type.
- uint32_t MsgType = (uint32_t)LLI_ExecutionResult;
- int rc = WriteBytes(&MsgType, 4);
- (void)rc;
- assert(rc == 4);
+ close(InFD);
+ close(OutFD);
- // Write the data size.
- uint32_t DataSize = 4;
- rc = WriteBytes(&DataSize, 4);
- assert(rc == 4);
-
- // Write the result.
- rc = WriteBytes(&Result, 4);
- assert(rc == 4);
+ return 0;
}
-
-#ifdef LLVM_ON_UNIX
-#include "../Unix/RPCChannel.inc"
-#endif
-
-#ifdef LLVM_ON_WIN32
-#include "../Windows/RPCChannel.inc"
-#endif
diff --git a/contrib/llvm/tools/lli/OrcLazyJIT.cpp b/contrib/llvm/tools/lli/OrcLazyJIT.cpp
index ae276e6..7f483f7 100644
--- a/contrib/llvm/tools/lli/OrcLazyJIT.cpp
+++ b/contrib/llvm/tools/lli/OrcLazyJIT.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "OrcLazyJIT.h"
-#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
+#include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
#include <cstdio>
@@ -38,26 +38,39 @@ namespace {
"Dump modules to the current "
"working directory. (WARNING: "
"will overwrite existing files)."),
- clEnumValEnd));
+ clEnumValEnd),
+ cl::Hidden);
+
+ cl::opt<bool> OrcInlineStubs("orc-lazy-inline-stubs",
+ cl::desc("Try to inline stubs"),
+ cl::init(true), cl::Hidden);
}
-OrcLazyJIT::CallbackManagerBuilder
-OrcLazyJIT::createCallbackManagerBuilder(Triple T) {
+std::unique_ptr<OrcLazyJIT::CompileCallbackMgr>
+OrcLazyJIT::createCompileCallbackMgr(Triple T) {
switch (T.getArch()) {
default: return nullptr;
case Triple::x86_64: {
- typedef orc::JITCompileCallbackManager<IRDumpLayerT,
- orc::OrcX86_64> CCMgrT;
- return [](IRDumpLayerT &IRDumpLayer, RuntimeDyld::MemoryManager &MemMgr,
- LLVMContext &Context) {
- return llvm::make_unique<CCMgrT>(IRDumpLayer, MemMgr, Context, 0,
- 64);
- };
+ typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64> CCMgrT;
+ return llvm::make_unique<CCMgrT>(0);
}
}
}
+OrcLazyJIT::IndirectStubsManagerBuilder
+OrcLazyJIT::createIndirectStubsMgrBuilder(Triple T) {
+ switch (T.getArch()) {
+ default: return nullptr;
+
+ case Triple::x86_64:
+ return [](){
+ return llvm::make_unique<
+ orc::LocalIndirectStubsManager<orc::OrcX86_64>>();
+ };
+ }
+}
+
OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
switch (OrcDumpKind) {
@@ -111,6 +124,12 @@ OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
// Defined in lli.cpp.
CodeGenOpt::Level getOptLevel();
+
+template <typename PtrTy>
+static PtrTy fromTargetAddress(orc::TargetAddress Addr) {
+ return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
+}
+
int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
// Add the program's symbols into the JIT's search space.
if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
@@ -123,20 +142,31 @@ int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
EngineBuilder EB;
EB.setOptLevel(getOptLevel());
auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget());
- auto &Context = getGlobalContext();
- auto CallbackMgrBuilder =
- OrcLazyJIT::createCallbackManagerBuilder(Triple(TM->getTargetTriple()));
+ auto CompileCallbackMgr =
+ OrcLazyJIT::createCompileCallbackMgr(Triple(TM->getTargetTriple()));
// If we couldn't build the factory function then there must not be a callback
// manager for this target. Bail out.
- if (!CallbackMgrBuilder) {
+ if (!CompileCallbackMgr) {
errs() << "No callback manager available for target '"
<< TM->getTargetTriple().str() << "'.\n";
return 1;
}
+ auto IndirectStubsMgrBuilder =
+ OrcLazyJIT::createIndirectStubsMgrBuilder(Triple(TM->getTargetTriple()));
+
+ // If we couldn't build a stubs-manager-builder for this target then bail out.
+ if (!IndirectStubsMgrBuilder) {
+ errs() << "No indirect stubs manager available for target '"
+ << TM->getTargetTriple().str() << "'.\n";
+ return 1;
+ }
+
// Everything looks good. Build the JIT.
- OrcLazyJIT J(std::move(TM), Context, CallbackMgrBuilder);
+ OrcLazyJIT J(std::move(TM), std::move(CompileCallbackMgr),
+ std::move(IndirectStubsMgrBuilder),
+ OrcInlineStubs);
// Add the module, look up main and run it.
auto MainHandle = J.addModule(std::move(M));
@@ -148,6 +178,6 @@ int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
}
typedef int (*MainFnPtr)(int, char*[]);
- auto Main = OrcLazyJIT::fromTargetAddress<MainFnPtr>(MainSym.getAddress());
+ auto Main = fromTargetAddress<MainFnPtr>(MainSym.getAddress());
return Main(ArgC, ArgV);
}
diff --git a/contrib/llvm/tools/lli/OrcLazyJIT.h b/contrib/llvm/tools/lli/OrcLazyJIT.h
index fe86adb..2a5b31d 100644
--- a/contrib/llvm/tools/lli/OrcLazyJIT.h
+++ b/contrib/llvm/tools/lli/OrcLazyJIT.h
@@ -23,39 +23,36 @@
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
-#include "llvm/IR/LLVMContext.h"
namespace llvm {
class OrcLazyJIT {
public:
- typedef orc::JITCompileCallbackManagerBase CompileCallbackMgr;
+ typedef orc::JITCompileCallbackManager CompileCallbackMgr;
typedef orc::ObjectLinkingLayer<> ObjLayerT;
typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT;
typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
TransformFtor;
typedef orc::IRTransformLayer<CompileLayerT, TransformFtor> IRDumpLayerT;
typedef orc::CompileOnDemandLayer<IRDumpLayerT, CompileCallbackMgr> CODLayerT;
+ typedef CODLayerT::IndirectStubsManagerBuilderT
+ IndirectStubsManagerBuilder;
typedef CODLayerT::ModuleSetHandleT ModuleHandleT;
- typedef std::function<
- std::unique_ptr<CompileCallbackMgr>(IRDumpLayerT&,
- RuntimeDyld::MemoryManager&,
- LLVMContext&)>
- CallbackManagerBuilder;
-
- static CallbackManagerBuilder createCallbackManagerBuilder(Triple T);
-
- OrcLazyJIT(std::unique_ptr<TargetMachine> TM, LLVMContext &Context,
- CallbackManagerBuilder &BuildCallbackMgr)
- : TM(std::move(TM)),
- ObjectLayer(),
- CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)),
- IRDumpLayer(CompileLayer, createDebugDumper()),
- CCMgr(BuildCallbackMgr(IRDumpLayer, CCMgrMemMgr, Context)),
- CODLayer(IRDumpLayer, *CCMgr, false),
- CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {}
+ OrcLazyJIT(std::unique_ptr<TargetMachine> TM,
+ std::unique_ptr<CompileCallbackMgr> CCMgr,
+ IndirectStubsManagerBuilder IndirectStubsMgrBuilder,
+ bool InlineStubs)
+ : TM(std::move(TM)), DL(this->TM->createDataLayout()),
+ CCMgr(std::move(CCMgr)),
+ ObjectLayer(),
+ CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)),
+ IRDumpLayer(CompileLayer, createDebugDumper()),
+ CODLayer(IRDumpLayer, extractSingleFunction, *this->CCMgr,
+ std::move(IndirectStubsMgrBuilder), InlineStubs),
+ CXXRuntimeOverrides(
+ [this](const std::string &S) { return mangle(S); }) {}
~OrcLazyJIT() {
// Run any destructors registered with __cxa_atexit.
@@ -65,15 +62,13 @@ public:
DtorRunner.runViaLayer(CODLayer);
}
- template <typename PtrTy>
- static PtrTy fromTargetAddress(orc::TargetAddress Addr) {
- return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
- }
+ static std::unique_ptr<CompileCallbackMgr> createCompileCallbackMgr(Triple T);
+ static IndirectStubsManagerBuilder createIndirectStubsMgrBuilder(Triple T);
ModuleHandleT addModule(std::unique_ptr<Module> M) {
// Attach a data-layout if one isn't already present.
if (M->getDataLayout().isDefault())
- M->setDataLayout(*TM->getDataLayout());
+ M->setDataLayout(DL);
// Record the static constructors and destructors. We have to do this before
// we hand over ownership of the module to the JIT.
@@ -110,7 +105,9 @@ public:
// Add the module to the JIT.
std::vector<std::unique_ptr<Module>> S;
S.push_back(std::move(M));
- auto H = CODLayer.addModuleSet(std::move(S), nullptr, std::move(Resolver));
+ auto H = CODLayer.addModuleSet(std::move(S),
+ llvm::make_unique<SectionMemoryManager>(),
+ std::move(Resolver));
// Run the static constructors, and save the static destructor runner for
// execution when the JIT is torn down.
@@ -136,20 +133,27 @@ private:
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
- Mangler::getNameWithPrefix(MangledNameStream, Name, *TM->getDataLayout());
+ Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
}
return MangledName;
}
+ static std::set<Function*> extractSingleFunction(Function &F) {
+ std::set<Function*> Partition;
+ Partition.insert(&F);
+ return Partition;
+ }
+
static TransformFtor createDebugDumper();
std::unique_ptr<TargetMachine> TM;
+ DataLayout DL;
SectionMemoryManager CCMgrMemMgr;
+ std::unique_ptr<CompileCallbackMgr> CCMgr;
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
IRDumpLayerT IRDumpLayer;
- std::unique_ptr<CompileCallbackMgr> CCMgr;
CODLayerT CODLayer;
orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
diff --git a/contrib/llvm/tools/lli/RPCChannel.h b/contrib/llvm/tools/lli/RPCChannel.h
deleted file mode 100644
index ebd3c65..0000000
--- a/contrib/llvm/tools/lli/RPCChannel.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===---------- RPCChannel.h - LLVM out-of-process JIT execution ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Definition of the RemoteTargetExternal class which executes JITed code in a
-// separate process from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_LLI_RPCCHANNEL_H
-#define LLVM_TOOLS_LLI_RPCCHANNEL_H
-
-#include <stdlib.h>
-#include <string>
-
-namespace llvm {
-
-class RPCChannel {
-public:
- std::string ChildName;
-
- RPCChannel() {}
- ~RPCChannel();
-
- /// Start the remote process.
- ///
- /// @returns True on success. On failure, ErrorMsg is updated with
- /// descriptive text of the encountered error.
- bool createServer();
-
- bool createClient();
-
- // This will get filled in as a point to an OS-specific structure.
- void *ConnectionData;
-
- bool WriteBytes(const void *Data, size_t Size);
- bool ReadBytes(void *Data, size_t Size);
-
- void Wait();
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/contrib/llvm/tools/lli/RemoteJITUtils.h b/contrib/llvm/tools/lli/RemoteJITUtils.h
new file mode 100644
index 0000000..a3f3fa0
--- /dev/null
+++ b/contrib/llvm/tools/lli/RemoteJITUtils.h
@@ -0,0 +1,131 @@
+//===-- RemoteJITUtils.h - Utilities for remote-JITing with LLI -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for remote-JITing with LLI.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H
+#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H
+
+#include "llvm/ExecutionEngine/Orc/RPCChannel.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+/// RPC channel that reads from and writes from file descriptors.
+class FDRPCChannel : public llvm::orc::remote::RPCChannel {
+public:
+ FDRPCChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {}
+
+ std::error_code readBytes(char *Dst, unsigned Size) override {
+ assert(Dst && "Attempt to read into null.");
+ ssize_t ReadResult = ::read(InFD, Dst, Size);
+ if (ReadResult != (ssize_t)Size)
+ return std::error_code(errno, std::generic_category());
+ return std::error_code();
+ }
+
+ std::error_code appendBytes(const char *Src, unsigned Size) override {
+ assert(Src && "Attempt to append from null.");
+ ssize_t WriteResult = ::write(OutFD, Src, Size);
+ if (WriteResult != (ssize_t)Size)
+ std::error_code(errno, std::generic_category());
+ return std::error_code();
+ }
+
+ std::error_code send() override { return std::error_code(); }
+
+private:
+ int InFD, OutFD;
+};
+
+// launch the remote process (see lli.cpp) and return a channel to it.
+std::unique_ptr<FDRPCChannel> launchRemote();
+
+namespace llvm {
+
+// ForwardingMM - Adapter to connect MCJIT to Orc's Remote memory manager.
+class ForwardingMemoryManager : public llvm::RTDyldMemoryManager {
+public:
+ void setMemMgr(std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr) {
+ this->MemMgr = std::move(MemMgr);
+ }
+
+ void setResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> Resolver) {
+ this->Resolver = std::move(Resolver);
+ }
+
+ uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ StringRef SectionName) override {
+ return MemMgr->allocateCodeSection(Size, Alignment, SectionID, SectionName);
+ }
+
+ uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID, StringRef SectionName,
+ bool IsReadOnly) override {
+ return MemMgr->allocateDataSection(Size, Alignment, SectionID, SectionName,
+ IsReadOnly);
+ }
+
+ void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
+ uintptr_t RODataSize, uint32_t RODataAlign,
+ uintptr_t RWDataSize,
+ uint32_t RWDataAlign) override {
+ MemMgr->reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign,
+ RWDataSize, RWDataAlign);
+ }
+
+ bool needsToReserveAllocationSpace() override {
+ return MemMgr->needsToReserveAllocationSpace();
+ }
+
+ void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
+ size_t Size) override {
+ MemMgr->registerEHFrames(Addr, LoadAddr, Size);
+ }
+
+ void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
+ size_t Size) override {
+ MemMgr->deregisterEHFrames(Addr, LoadAddr, Size);
+ }
+
+ bool finalizeMemory(std::string *ErrMsg = nullptr) override {
+ return MemMgr->finalizeMemory(ErrMsg);
+ }
+
+ void notifyObjectLoaded(RuntimeDyld &RTDyld,
+ const object::ObjectFile &Obj) override {
+ MemMgr->notifyObjectLoaded(RTDyld, Obj);
+ }
+
+ // Don't hide the sibling notifyObjectLoaded from RTDyldMemoryManager.
+ using RTDyldMemoryManager::notifyObjectLoaded;
+
+ RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override {
+ return Resolver->findSymbol(Name);
+ }
+
+ RuntimeDyld::SymbolInfo
+ findSymbolInLogicalDylib(const std::string &Name) override {
+ return Resolver->findSymbolInLogicalDylib(Name);
+ }
+
+private:
+ std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr;
+ std::unique_ptr<RuntimeDyld::SymbolResolver> Resolver;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/lli/RemoteMemoryManager.cpp b/contrib/llvm/tools/lli/RemoteMemoryManager.cpp
deleted file mode 100644
index 0a16210..0000000
--- a/contrib/llvm/tools/lli/RemoteMemoryManager.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-//===---- RemoteMemoryManager.cpp - Recording memory manager --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This memory manager allocates local storage and keeps a record of each
-// allocation. Iterators are provided for all data and code allocations.
-//
-//===----------------------------------------------------------------------===//
-
-#include "RemoteMemoryManager.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-#define DEBUG_TYPE "lli"
-
-RemoteMemoryManager::~RemoteMemoryManager() {
- for (SmallVector<Allocation, 2>::iterator
- I = AllocatedSections.begin(), E = AllocatedSections.end();
- I != E; ++I)
- sys::Memory::releaseMappedMemory(I->MB);
-}
-
-uint8_t *RemoteMemoryManager::
-allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
- StringRef SectionName) {
- // The recording memory manager is just a local copy of the remote target.
- // The alignment requirement is just stored here for later use. Regular
- // heap storage is sufficient here, but we're using mapped memory to work
- // around a bug in MCJIT.
- sys::MemoryBlock Block = allocateSection(Size);
- // AllocatedSections will own this memory.
- AllocatedSections.push_back( Allocation(Block, Alignment, true) );
- // UnmappedSections has the same information but does not own the memory.
- UnmappedSections.push_back( Allocation(Block, Alignment, true) );
- return (uint8_t*)Block.base();
-}
-
-uint8_t *RemoteMemoryManager::
-allocateDataSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID, StringRef SectionName,
- bool IsReadOnly) {
- // The recording memory manager is just a local copy of the remote target.
- // The alignment requirement is just stored here for later use. Regular
- // heap storage is sufficient here, but we're using mapped memory to work
- // around a bug in MCJIT.
- sys::MemoryBlock Block = allocateSection(Size);
- // AllocatedSections will own this memory.
- AllocatedSections.push_back( Allocation(Block, Alignment, false) );
- // UnmappedSections has the same information but does not own the memory.
- UnmappedSections.push_back( Allocation(Block, Alignment, false) );
- return (uint8_t*)Block.base();
-}
-
-sys::MemoryBlock RemoteMemoryManager::allocateSection(uintptr_t Size) {
- std::error_code ec;
- sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(Size,
- &Near,
- sys::Memory::MF_READ |
- sys::Memory::MF_WRITE,
- ec);
- assert(!ec && MB.base());
-
- // FIXME: This is part of a work around to keep sections near one another
- // when MCJIT performs relocations after code emission but before
- // the generated code is moved to the remote target.
- // Save this address as the basis for our next request
- Near = MB;
- return MB;
-}
-
-void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
- const object::ObjectFile &Obj) {
- // The client should have called setRemoteTarget() before triggering any
- // code generation.
- assert(Target);
- if (!Target)
- return;
-
- // FIXME: Make this function thread safe.
-
- // Lay out our sections in order, with all the code sections first, then
- // all the data sections.
- uint64_t CurOffset = 0;
- unsigned MaxAlign = Target->getPageAlignment();
- SmallVector<std::pair<Allocation, uint64_t>, 16> Offsets;
- unsigned NumSections = UnmappedSections.size();
- // We're going to go through the list twice to separate code and data, but
- // it's a very small list, so that's OK.
- for (size_t i = 0, e = NumSections; i != e; ++i) {
- Allocation &Section = UnmappedSections[i];
- if (Section.IsCode) {
- unsigned Size = Section.MB.size();
- unsigned Align = Section.Alignment;
- DEBUG(dbgs() << "code region: size " << Size
- << ", alignment " << Align << "\n");
- // Align the current offset up to whatever is needed for the next
- // section.
- CurOffset = (CurOffset + Align - 1) / Align * Align;
- // Save off the address of the new section and allocate its space.
- Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
- CurOffset += Size;
- }
- }
- // Adjust to keep code and data aligned on separate pages.
- CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
- for (size_t i = 0, e = NumSections; i != e; ++i) {
- Allocation &Section = UnmappedSections[i];
- if (!Section.IsCode) {
- unsigned Size = Section.MB.size();
- unsigned Align = Section.Alignment;
- DEBUG(dbgs() << "data region: size " << Size
- << ", alignment " << Align << "\n");
- // Align the current offset up to whatever is needed for the next
- // section.
- CurOffset = (CurOffset + Align - 1) / Align * Align;
- // Save off the address of the new section and allocate its space.
- Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
- CurOffset += Size;
- }
- }
-
- // Allocate space in the remote target.
- uint64_t RemoteAddr;
- if (!Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
- report_fatal_error(Target->getErrorMsg());
-
- // Map the section addresses so relocations will get updated in the local
- // copies of the sections.
- for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
- uint64_t Addr = RemoteAddr + Offsets[i].second;
- EE->mapSectionAddress(const_cast<void*>(Offsets[i].first.MB.base()), Addr);
-
- DEBUG(dbgs() << " Mapping local: " << Offsets[i].first.MB.base()
- << " to remote: 0x" << format("%llx", Addr) << "\n");
-
- MappedSections[Addr] = Offsets[i].first;
- }
-
- UnmappedSections.clear();
-}
-
-bool RemoteMemoryManager::finalizeMemory(std::string *ErrMsg) {
- // FIXME: Make this function thread safe.
- for (DenseMap<uint64_t, Allocation>::iterator
- I = MappedSections.begin(), E = MappedSections.end();
- I != E; ++I) {
- uint64_t RemoteAddr = I->first;
- const Allocation &Section = I->second;
- if (Section.IsCode) {
- if (!Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size()))
- report_fatal_error(Target->getErrorMsg());
- DEBUG(dbgs() << " loading code: " << Section.MB.base()
- << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
- } else {
- if (!Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size()))
- report_fatal_error(Target->getErrorMsg());
- DEBUG(dbgs() << " loading data: " << Section.MB.base()
- << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
- }
- }
-
- MappedSections.clear();
-
- return false;
-}
diff --git a/contrib/llvm/tools/lli/RemoteMemoryManager.h b/contrib/llvm/tools/lli/RemoteMemoryManager.h
deleted file mode 100644
index 5733fa5..0000000
--- a/contrib/llvm/tools/lli/RemoteMemoryManager.h
+++ /dev/null
@@ -1,101 +0,0 @@
-//===- RemoteMemoryManager.h - LLI MCJIT recording memory manager ------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This memory manager allocates local storage and keeps a record of each
-// allocation. Iterators are provided for all data and code allocations.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_LLI_REMOTEMEMORYMANAGER_H
-#define LLVM_TOOLS_LLI_REMOTEMEMORYMANAGER_H
-
-#include "RemoteTarget.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Memory.h"
-#include <utility>
-
-namespace llvm {
-
-class RemoteMemoryManager : public RTDyldMemoryManager {
-public:
- // Notice that this structure takes ownership of the memory allocated.
- struct Allocation {
- Allocation() {}
- Allocation(sys::MemoryBlock mb, unsigned a, bool code)
- : MB(mb), Alignment(a), IsCode(code) {}
-
- sys::MemoryBlock MB;
- unsigned Alignment;
- bool IsCode;
- };
-
-private:
- // This vector contains Allocation objects for all sections which we have
- // allocated. This vector effectively owns the memory associated with the
- // allocations.
- SmallVector<Allocation, 2> AllocatedSections;
-
- // This vector contains pointers to Allocation objects for any sections we
- // have allocated locally but have not yet remapped for the remote target.
- // When we receive notification of a completed module load, we will map
- // these sections into the remote target.
- SmallVector<Allocation, 2> UnmappedSections;
-
- // This map tracks the sections we have remapped for the remote target
- // but have not yet copied to the target.
- DenseMap<uint64_t, Allocation> MappedSections;
-
- // FIXME: This is part of a work around to keep sections near one another
- // when MCJIT performs relocations after code emission but before
- // the generated code is moved to the remote target.
- sys::MemoryBlock Near;
- sys::MemoryBlock allocateSection(uintptr_t Size);
-
- RemoteTarget *Target;
-
-public:
- RemoteMemoryManager() : Target(nullptr) {}
- ~RemoteMemoryManager() override;
-
- uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID,
- StringRef SectionName) override;
-
- uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID, StringRef SectionName,
- bool IsReadOnly) override;
-
- // For now, remote symbol resolution is not support in lli. The MCJIT
- // interface does support this, but clients must provide their own
- // mechanism for finding remote symbol addresses. MCJIT will resolve
- // symbols from Modules it contains.
- uint64_t getSymbolAddress(const std::string &Name) override { return 0; }
-
- void notifyObjectLoaded(ExecutionEngine *EE,
- const object::ObjectFile &Obj) override;
-
- bool finalizeMemory(std::string *ErrMsg) override;
-
- // For now, remote EH frame registration isn't supported. Remote symbol
- // resolution is a prerequisite to supporting remote EH frame registration.
- void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
- size_t Size) override {}
- void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
- size_t Size) override {}
-
- // This is a non-interface function used by lli
- void setRemoteTarget(RemoteTarget *T) { Target = T; }
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/contrib/llvm/tools/lli/RemoteTarget.cpp b/contrib/llvm/tools/lli/RemoteTarget.cpp
deleted file mode 100644
index 850fdc5..0000000
--- a/contrib/llvm/tools/lli/RemoteTarget.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//===- RemoteTarget.cpp - LLVM Remote process JIT execution --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implementation of the RemoteTarget class which executes JITed code in a
-// separate address range from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-#include "RemoteTarget.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Memory.h"
-#include <stdlib.h>
-#include <string>
-
-using namespace llvm;
-
-////////////////////////////////////////////////////////////////////////////////
-// Simulated remote execution
-//
-// This implementation will simply move generated code and data to a new memory
-// location in the current executable and let it run from there.
-////////////////////////////////////////////////////////////////////////////////
-
-bool RemoteTarget::allocateSpace(size_t Size, unsigned Alignment,
- uint64_t &Address) {
- sys::MemoryBlock *Prev = Allocations.size() ? &Allocations.back() : nullptr;
- sys::MemoryBlock Mem = sys::Memory::AllocateRWX(Size, Prev, &ErrorMsg);
- if (Mem.base() == nullptr)
- return false;
- if ((uintptr_t)Mem.base() % Alignment) {
- ErrorMsg = "unable to allocate sufficiently aligned memory";
- return false;
- }
- Address = reinterpret_cast<uint64_t>(Mem.base());
- Allocations.push_back(Mem);
- return true;
-}
-
-bool RemoteTarget::loadData(uint64_t Address, const void *Data, size_t Size) {
- memcpy ((void*)Address, Data, Size);
- return true;
-}
-
-bool RemoteTarget::loadCode(uint64_t Address, const void *Data, size_t Size) {
- memcpy ((void*)Address, Data, Size);
- sys::MemoryBlock Mem((void*)Address, Size);
- sys::Memory::setExecutable(Mem, &ErrorMsg);
- return true;
-}
-
-bool RemoteTarget::executeCode(uint64_t Address, int &RetVal) {
- int (*fn)(void) = (int(*)(void))Address;
- RetVal = fn();
- return true;
-}
-
-bool RemoteTarget::create() {
- return true;
-}
-
-void RemoteTarget::stop() {
- for (unsigned i = 0, e = Allocations.size(); i != e; ++i)
- sys::Memory::ReleaseRWX(Allocations[i]);
-}
diff --git a/contrib/llvm/tools/lli/RemoteTarget.h b/contrib/llvm/tools/lli/RemoteTarget.h
deleted file mode 100644
index ee758a2..0000000
--- a/contrib/llvm/tools/lli/RemoteTarget.h
+++ /dev/null
@@ -1,122 +0,0 @@
-//===- RemoteTarget.h - LLVM Remote process JIT execution ----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Definition of the RemoteTarget class which executes JITed code in a
-// separate address range from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_LLI_REMOTETARGET_H
-#define LLVM_TOOLS_LLI_REMOTETARGET_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Memory.h"
-#include <stdlib.h>
-#include <string>
-
-namespace llvm {
-
-class RemoteTarget {
- bool IsRunning;
-
- typedef SmallVector<sys::MemoryBlock, 16> AllocMapType;
- AllocMapType Allocations;
-
-protected:
- std::string ErrorMsg;
-
-public:
- StringRef getErrorMsg() const { return ErrorMsg; }
-
- /// Allocate space in the remote target address space.
- ///
- /// @param Size Amount of space, in bytes, to allocate.
- /// @param Alignment Required minimum alignment for allocated space.
- /// @param[out] Address Remote address of the allocated memory.
- ///
- /// @returns True on success. On failure, ErrorMsg is updated with
- /// descriptive text of the encountered error.
- virtual bool allocateSpace(size_t Size,
- unsigned Alignment,
- uint64_t &Address);
-
- bool isAllocatedMemory(uint64_t Address, uint32_t Size) {
- uint64_t AddressEnd = Address + Size;
- for (AllocMapType::const_iterator I = Allocations.begin(),
- E = Allocations.end();
- I != E; ++I) {
- if (Address >= (uint64_t)I->base() &&
- AddressEnd <= (uint64_t)I->base() + I->size())
- return true;
- }
- return false;
- }
-
- /// Load data into the target address space.
- ///
- /// @param Address Destination address in the target process.
- /// @param Data Source address in the host process.
- /// @param Size Number of bytes to copy.
- ///
- /// @returns True on success. On failure, ErrorMsg is updated with
- /// descriptive text of the encountered error.
- virtual bool loadData(uint64_t Address,
- const void *Data,
- size_t Size);
-
- /// Load code into the target address space and prepare it for execution.
- ///
- /// @param Address Destination address in the target process.
- /// @param Data Source address in the host process.
- /// @param Size Number of bytes to copy.
- ///
- /// @returns True on success. On failure, ErrorMsg is updated with
- /// descriptive text of the encountered error.
- virtual bool loadCode(uint64_t Address,
- const void *Data,
- size_t Size);
-
- /// Execute code in the target process. The called function is required
- /// to be of signature int "(*)(void)".
- ///
- /// @param Address Address of the loaded function in the target
- /// process.
- /// @param[out] RetVal The integer return value of the called function.
- ///
- /// @returns True on success. On failure, ErrorMsg is updated with
- /// descriptive text of the encountered error.
- virtual bool executeCode(uint64_t Address,
- int &RetVal);
-
- /// Minimum alignment for memory permissions. Used to separate code and
- /// data regions to make sure data doesn't get marked as code or vice
- /// versa.
- ///
- /// @returns Page alignment return value. Default of 4k.
- virtual unsigned getPageAlignment() { return 4096; }
-
- /// Start the remote process.
- virtual bool create();
-
- /// Terminate the remote process.
- virtual void stop();
-
- RemoteTarget() : IsRunning(false), ErrorMsg("") {}
- virtual ~RemoteTarget() { if (IsRunning) stop(); }
-private:
- // Main processing function for the remote target process. Command messages
- // are received on file descriptor CmdFD and responses come back on OutFD.
- static void doRemoteTargeting(int CmdFD, int OutFD);
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/contrib/llvm/tools/lli/RemoteTargetExternal.cpp b/contrib/llvm/tools/lli/RemoteTargetExternal.cpp
deleted file mode 100644
index fe46248..0000000
--- a/contrib/llvm/tools/lli/RemoteTargetExternal.cpp
+++ /dev/null
@@ -1,327 +0,0 @@
-//===---- RemoteTargetExternal.cpp - LLVM out-of-process JIT execution ----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implementation of the RemoteTargetExternal class which executes JITed code
-// in a separate process from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Config/config.h"
-#include "RemoteTarget.h"
-#include "RemoteTargetExternal.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/Memory.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/raw_ostream.h"
-#include <string>
-
-using namespace llvm;
-
-#define DEBUG_TYPE "lli"
-
-bool RemoteTargetExternal::allocateSpace(size_t Size, unsigned Alignment,
- uint64_t &Address) {
- DEBUG(dbgs() << "Message [allocate space] size: " << Size <<
- ", align: " << Alignment << "\n");
- if (!SendAllocateSpace(Alignment, Size)) {
- ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
- return false;
- }
- if (!Receive(LLI_AllocationResult, Address)) {
- ErrorMsg += ", (RemoteTargetExternal::allocateSpace)";
- return false;
- }
- if (Address == 0) {
- ErrorMsg += "failed allocation, (RemoteTargetExternal::allocateSpace)";
- return false;
- }
- DEBUG(dbgs() << "Message [allocate space] addr: 0x" <<
- format("%llx", Address) << "\n");
- return true;
-}
-
-bool RemoteTargetExternal::loadData(uint64_t Address, const void *Data, size_t Size) {
- DEBUG(dbgs() << "Message [load data] addr: 0x" << format("%llx", Address) <<
- ", size: " << Size << "\n");
- if (!SendLoadSection(Address, Data, (uint32_t)Size, false)) {
- ErrorMsg += ", (RemoteTargetExternal::loadData)";
- return false;
- }
- int Status = LLI_Status_Success;
- if (!Receive(LLI_LoadResult, Status)) {
- ErrorMsg += ", (RemoteTargetExternal::loadData)";
- return false;
- }
- if (Status == LLI_Status_IncompleteMsg) {
- ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
- return false;
- }
- if (Status == LLI_Status_NotAllocated) {
- ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
- return false;
- }
- DEBUG(dbgs() << "Message [load data] complete\n");
- return true;
-}
-
-bool RemoteTargetExternal::loadCode(uint64_t Address, const void *Data, size_t Size) {
- DEBUG(dbgs() << "Message [load code] addr: 0x" << format("%llx", Address) <<
- ", size: " << Size << "\n");
- if (!SendLoadSection(Address, Data, (uint32_t)Size, true)) {
- ErrorMsg += ", (RemoteTargetExternal::loadCode)";
- return false;
- }
- int Status = LLI_Status_Success;
- if (!Receive(LLI_LoadResult, Status)) {
- ErrorMsg += ", (RemoteTargetExternal::loadCode)";
- return false;
- }
- if (Status == LLI_Status_IncompleteMsg) {
- ErrorMsg += "incomplete load data, (RemoteTargetExternal::loadData)";
- return false;
- }
- if (Status == LLI_Status_NotAllocated) {
- ErrorMsg += "data memory not allocated, (RemoteTargetExternal::loadData)";
- return false;
- }
- DEBUG(dbgs() << "Message [load code] complete\n");
- return true;
-}
-
-bool RemoteTargetExternal::executeCode(uint64_t Address, int32_t &RetVal) {
- DEBUG(dbgs() << "Message [exectue code] addr: " << Address << "\n");
- if (!SendExecute(Address)) {
- ErrorMsg += ", (RemoteTargetExternal::executeCode)";
- return false;
- }
- if (!Receive(LLI_ExecutionResult, RetVal)) {
- ErrorMsg += ", (RemoteTargetExternal::executeCode)";
- return false;
- }
- DEBUG(dbgs() << "Message [exectue code] return: " << RetVal << "\n");
- return true;
-}
-
-void RemoteTargetExternal::stop() {
- SendTerminate();
- RPC.Wait();
-}
-
-bool RemoteTargetExternal::SendAllocateSpace(uint32_t Alignment, uint32_t Size) {
- if (!SendHeader(LLI_AllocateSpace)) {
- ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
- return false;
- }
-
- AppendWrite((const void *)&Alignment, 4);
- AppendWrite((const void *)&Size, 4);
-
- if (!SendPayload()) {
- ErrorMsg += ", (RemoteTargetExternal::SendAllocateSpace)";
- return false;
- }
- return true;
-}
-
-bool RemoteTargetExternal::SendLoadSection(uint64_t Addr,
- const void *Data,
- uint32_t Size,
- bool IsCode) {
- LLIMessageType MsgType = IsCode ? LLI_LoadCodeSection : LLI_LoadDataSection;
- if (!SendHeader(MsgType)) {
- ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
- return false;
- }
-
- AppendWrite((const void *)&Addr, 8);
- AppendWrite(Data, Size);
-
- if (!SendPayload()) {
- ErrorMsg += ", (RemoteTargetExternal::SendLoadSection)";
- return false;
- }
- return true;
-}
-
-bool RemoteTargetExternal::SendExecute(uint64_t Addr) {
- if (!SendHeader(LLI_Execute)) {
- ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
- return false;
- }
-
- AppendWrite((const void *)&Addr, 8);
-
- if (!SendPayload()) {
- ErrorMsg += ", (RemoteTargetExternal::SendExecute)";
- return false;
- }
- return true;
-}
-
-bool RemoteTargetExternal::SendTerminate() {
- return SendHeader(LLI_Terminate);
- // No data or data size is sent with Terminate
-}
-
-bool RemoteTargetExternal::Receive(LLIMessageType Msg) {
- if (!ReceiveHeader(Msg))
- return false;
- int Unused;
- AppendRead(&Unused, 0);
- if (!ReceivePayload())
- return false;
- ReceiveData.clear();
- Sizes.clear();
- return true;
-}
-
-bool RemoteTargetExternal::Receive(LLIMessageType Msg, int32_t &Data) {
- if (!ReceiveHeader(Msg))
- return false;
- AppendRead(&Data, 4);
- if (!ReceivePayload())
- return false;
- ReceiveData.clear();
- Sizes.clear();
- return true;
-}
-
-bool RemoteTargetExternal::Receive(LLIMessageType Msg, uint64_t &Data) {
- if (!ReceiveHeader(Msg))
- return false;
- AppendRead(&Data, 8);
- if (!ReceivePayload())
- return false;
- ReceiveData.clear();
- Sizes.clear();
- return true;
-}
-
-bool RemoteTargetExternal::ReceiveHeader(LLIMessageType ExpectedMsgType) {
- assert(ReceiveData.empty() && Sizes.empty() &&
- "Payload vector not empty to receive header");
-
- // Message header, with type to follow
- uint32_t MsgType;
- if (!ReadBytes(&MsgType, 4)) {
- ErrorMsg += ", (RemoteTargetExternal::ReceiveHeader)";
- return false;
- }
- if (MsgType != (uint32_t)ExpectedMsgType) {
- ErrorMsg = "received unexpected message type";
- ErrorMsg += ". Expecting: ";
- ErrorMsg += ExpectedMsgType;
- ErrorMsg += ", Got: ";
- ErrorMsg += MsgType;
- return false;
- }
- return true;
-}
-
-bool RemoteTargetExternal::ReceivePayload() {
- assert(!ReceiveData.empty() &&
- "Payload vector empty to receive");
- assert(ReceiveData.size() == Sizes.size() &&
- "Unexpected mismatch between data and size");
-
- uint32_t TotalSize = 0;
- for (int I=0, E=Sizes.size(); I < E; I++)
- TotalSize += Sizes[I];
-
- // Payload size header
- uint32_t DataSize;
- if (!ReadBytes(&DataSize, 4)) {
- ErrorMsg += ", invalid data size";
- return false;
- }
- if (DataSize != TotalSize) {
- ErrorMsg = "unexpected data size";
- ErrorMsg += ". Expecting: ";
- ErrorMsg += TotalSize;
- ErrorMsg += ", Got: ";
- ErrorMsg += DataSize;
- return false;
- }
- if (DataSize == 0)
- return true;
-
- // Payload itself
- for (int I=0, E=Sizes.size(); I < E; I++) {
- if (!ReadBytes(ReceiveData[I], Sizes[I])) {
- ErrorMsg = "unexpected data while reading message";
- return false;
- }
- }
-
- return true;
-}
-
-bool RemoteTargetExternal::SendHeader(LLIMessageType MsgType) {
- assert(SendData.empty() && Sizes.empty() &&
- "Payload vector not empty to send header");
-
- // Message header, with type to follow
- if (!WriteBytes(&MsgType, 4)) {
- ErrorMsg += ", (RemoteTargetExternal::SendHeader)";
- return false;
- }
- return true;
-}
-
-bool RemoteTargetExternal::SendPayload() {
- assert(!SendData.empty() && !Sizes.empty() &&
- "Payload vector empty to send");
- assert(SendData.size() == Sizes.size() &&
- "Unexpected mismatch between data and size");
-
- uint32_t TotalSize = 0;
- for (int I=0, E=Sizes.size(); I < E; I++)
- TotalSize += Sizes[I];
-
- // Payload size header
- if (!WriteBytes(&TotalSize, 4)) {
- ErrorMsg += ", invalid data size";
- return false;
- }
- if (TotalSize == 0)
- return true;
-
- // Payload itself
- for (int I=0, E=Sizes.size(); I < E; I++) {
- if (!WriteBytes(SendData[I], Sizes[I])) {
- ErrorMsg = "unexpected data while writing message";
- return false;
- }
- }
-
- SendData.clear();
- Sizes.clear();
- return true;
-}
-
-void RemoteTargetExternal::AppendWrite(const void *Data, uint32_t Size) {
- SendData.push_back(Data);
- Sizes.push_back(Size);
-}
-
-void RemoteTargetExternal::AppendRead(void *Data, uint32_t Size) {
- ReceiveData.push_back(Data);
- Sizes.push_back(Size);
-}
-
-#ifdef LLVM_ON_UNIX
-#include "Unix/RPCChannel.inc"
-#endif
-
-#ifdef LLVM_ON_WIN32
-#include "Windows/RPCChannel.inc"
-#endif
diff --git a/contrib/llvm/tools/lli/RemoteTargetExternal.h b/contrib/llvm/tools/lli/RemoteTargetExternal.h
deleted file mode 100644
index afe8570..0000000
--- a/contrib/llvm/tools/lli/RemoteTargetExternal.h
+++ /dev/null
@@ -1,143 +0,0 @@
-//===----- RemoteTargetExternal.h - LLVM out-of-process JIT execution -----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Definition of the RemoteTargetExternal class which executes JITed code in a
-// separate process from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_LLI_REMOTETARGETEXTERNAL_H
-#define LLVM_TOOLS_LLI_REMOTETARGETEXTERNAL_H
-
-#include "RPCChannel.h"
-#include "RemoteTarget.h"
-#include "RemoteTargetMessage.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Config/config.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Memory.h"
-#include <stdlib.h>
-#include <string>
-
-namespace llvm {
-
-class RemoteTargetExternal : public RemoteTarget {
- RPCChannel RPC;
-
- bool WriteBytes(const void *Data, size_t Size) {
- return RPC.WriteBytes(Data, Size);
- }
-
- bool ReadBytes(void *Data, size_t Size) { return RPC.ReadBytes(Data, Size); }
-
-public:
- /// Allocate space in the remote target address space.
- ///
- /// @param Size Amount of space, in bytes, to allocate.
- /// @param Alignment Required minimum alignment for allocated space.
- /// @param[out] Address Remote address of the allocated memory.
- ///
- /// @returns True on success. On failure, ErrorMsg is updated with
- /// descriptive text of the encountered error.
- bool allocateSpace(size_t Size, unsigned Alignment,
- uint64_t &Address) override;
-
- /// Load data into the target address space.
- ///
- /// @param Address Destination address in the target process.
- /// @param Data Source address in the host process.
- /// @param Size Number of bytes to copy.
- ///
- /// @returns True on success. On failure, ErrorMsg is updated with
- /// descriptive text of the encountered error.
- bool loadData(uint64_t Address, const void *Data, size_t Size) override;
-
- /// Load code into the target address space and prepare it for execution.
- ///
- /// @param Address Destination address in the target process.
- /// @param Data Source address in the host process.
- /// @param Size Number of bytes to copy.
- ///
- /// @returns True on success. On failure, ErrorMsg is updated with
- /// descriptive text of the encountered error.
- bool loadCode(uint64_t Address, const void *Data, size_t Size) override;
-
- /// Execute code in the target process. The called function is required
- /// to be of signature int "(*)(void)".
- ///
- /// @param Address Address of the loaded function in the target
- /// process.
- /// @param[out] RetVal The integer return value of the called function.
- ///
- /// @returns True on success. On failure, ErrorMsg is updated with
- /// descriptive text of the encountered error.
- bool executeCode(uint64_t Address, int &RetVal) override;
-
- /// Minimum alignment for memory permissions. Used to separate code and
- /// data regions to make sure data doesn't get marked as code or vice
- /// versa.
- ///
- /// @returns Page alignment return value. Default of 4k.
- unsigned getPageAlignment() override { return 4096; }
-
- bool create() override {
- RPC.ChildName = ChildName;
- if (!RPC.createServer())
- return true;
-
- // We must get Ack from the client (blocking read)
- if (!Receive(LLI_ChildActive)) {
- ErrorMsg += ", (RPCChannel::create) - Stopping process!";
- stop();
- return false;
- }
-
- return true;
- }
-
- /// Terminate the remote process.
- void stop() override;
-
- RemoteTargetExternal(std::string &Name) : RemoteTarget(), ChildName(Name) {}
- ~RemoteTargetExternal() override {}
-
-private:
- std::string ChildName;
-
- bool SendAllocateSpace(uint32_t Alignment, uint32_t Size);
- bool SendLoadSection(uint64_t Addr,
- const void *Data,
- uint32_t Size,
- bool IsCode);
- bool SendExecute(uint64_t Addr);
- bool SendTerminate();
-
- // High-level wrappers for receiving data
- bool Receive(LLIMessageType Msg);
- bool Receive(LLIMessageType Msg, int32_t &Data);
- bool Receive(LLIMessageType Msg, uint64_t &Data);
-
- // Lower level target-independent read/write to deal with errors
- bool ReceiveHeader(LLIMessageType Msg);
- bool ReceivePayload();
- bool SendHeader(LLIMessageType Msg);
- bool SendPayload();
-
- // Functions to append/retrieve data from the payload
- SmallVector<const void *, 2> SendData;
- SmallVector<void *, 1> ReceiveData; // Future proof
- SmallVector<int, 2> Sizes;
- void AppendWrite(const void *Data, uint32_t Size);
- void AppendRead(void *Data, uint32_t Size);
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/contrib/llvm/tools/lli/RemoteTargetMessage.h b/contrib/llvm/tools/lli/RemoteTargetMessage.h
deleted file mode 100644
index c210e4b..0000000
--- a/contrib/llvm/tools/lli/RemoteTargetMessage.h
+++ /dev/null
@@ -1,85 +0,0 @@
-//===---- RemoteTargetMessage.h - LLI out-of-process message protocol -----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Definition of the LLIMessageType enum which is used for communication with a
-// child process for remote execution.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_LLI_REMOTETARGETMESSAGE_H
-#define LLVM_TOOLS_LLI_REMOTETARGETMESSAGE_H
-
-namespace llvm {
-
-// LLI messages from parent-to-child or vice versa follow an exceedingly simple
-// protocol where the first four bytes represent the message type, the next
-// four bytes represent the size of data for the command and following bytes
-// represent the actual data.
-//
-// The protocol is not intended to be robust, secure or fault-tolerant. It is
-// only here for testing purposes and is therefore intended to be the simplest
-// implementation that will work. It is assumed that the parent and child
-// share characteristics like endianness.
-//
-// Quick description of the protocol:
-//
-// { Header + Payload Size + Payload }
-//
-// The protocol message consist of a header, the payload size (which can be
-// zero), and the payload itself. The payload can contain any number of items,
-// and the size has to be the sum of them all. Each end is responsible for
-// reading/writing the correct number of items with the correct sizes.
-//
-// The current four known exchanges are:
-//
-// * Allocate Space:
-// Parent: { LLI_AllocateSpace, 8, Alignment, Size }
-// Child: { LLI_AllocationResult, 8, Address }
-//
-// * Load Data:
-// Parent: { LLI_LoadDataSection, 8+Size, Address, Data }
-// Child: { LLI_LoadComplete, 4, StatusCode }
-//
-// * Load Code:
-// Parent: { LLI_LoadCodeSection, 8+Size, Address, Code }
-// Child: { LLI_LoadComplete, 4, StatusCode }
-//
-// * Execute Code:
-// Parent: { LLI_Execute, 8, Address }
-// Child: { LLI_ExecutionResult, 4, Result }
-//
-// It is the responsibility of either side to check for correct headers,
-// sizes and payloads, since any inconsistency would misalign the pipe, and
-// result in data corruption.
-
-enum LLIMessageType {
- LLI_Error = -1,
- LLI_ChildActive = 0, // Data = not used
- LLI_AllocateSpace, // Data = struct { uint32_t Align, uint_32t Size }
- LLI_AllocationResult, // Data = uint64_t Address (child memory space)
-
- LLI_LoadCodeSection, // Data = uint64_t Address, void * SectionData
- LLI_LoadDataSection, // Data = uint64_t Address, void * SectionData
- LLI_LoadResult, // Data = uint32_t LLIMessageStatus
-
- LLI_Execute, // Data = uint64_t Address
- LLI_ExecutionResult, // Data = uint32_t Result
-
- LLI_Terminate // Data = not used
-};
-
-enum LLIMessageStatus {
- LLI_Status_Success = 0, // Operation succeeded
- LLI_Status_NotAllocated, // Address+Size not allocated in child space
- LLI_Status_IncompleteMsg // Size received doesn't match request
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/contrib/llvm/tools/lli/Unix/RPCChannel.inc b/contrib/llvm/tools/lli/Unix/RPCChannel.inc
deleted file mode 100644
index 6a9ae14..0000000
--- a/contrib/llvm/tools/lli/Unix/RPCChannel.inc
+++ /dev/null
@@ -1,122 +0,0 @@
-//=- RPCChannel.inc - LLVM out-of-process JIT execution for Unix --=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implementation of the Unix-specific parts of the RPCChannel class
-// which executes JITed code in a separate process from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Errno.h"
-#include "llvm/Support/raw_ostream.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-namespace {
-
-struct ConnectionData_t {
- int InputPipe;
- int OutputPipe;
-
- ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {}
-};
-
-} // namespace
-
-namespace llvm {
-
-bool RPCChannel::createServer() {
- int PipeFD[2][2];
- pid_t ChildPID;
-
- // Create two pipes.
- if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0)
- perror("Error creating pipe: ");
-
- ChildPID = fork();
-
- if (ChildPID == 0) {
- // In the child...
-
- // Close the parent ends of the pipes
- close(PipeFD[0][1]);
- close(PipeFD[1][0]);
-
- // Use our pipes as stdin and stdout
- if (PipeFD[0][0] != STDIN_FILENO) {
- dup2(PipeFD[0][0], STDIN_FILENO);
- close(PipeFD[0][0]);
- }
- if (PipeFD[1][1] != STDOUT_FILENO) {
- dup2(PipeFD[1][1], STDOUT_FILENO);
- close(PipeFD[1][1]);
- }
-
- // Execute the child process.
- char *args[1] = { nullptr };
- int rc = execv(ChildName.c_str(), args);
- if (rc != 0)
- perror("Error executing child process: ");
- } else {
- // In the parent...
-
- // Close the child ends of the pipes
- close(PipeFD[0][0]);
- close(PipeFD[1][1]);
-
- // Store the parent ends of the pipes
- ConnectionData = (void *)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]);
- return true;
- }
- return false;
-}
-
-bool RPCChannel::createClient() {
- // Store the parent ends of the pipes
- ConnectionData = (void *)new ConnectionData_t(STDIN_FILENO, STDOUT_FILENO);
- return true;
-}
-
-void RPCChannel::Wait() { wait(nullptr); }
-
-static bool CheckError(int rc, size_t Size, const char *Desc) {
- if (rc < 0) {
- llvm::errs() << "IO Error: " << Desc << ": " << sys::StrError() << '\n';
- return false;
- } else if ((size_t)rc != Size) {
- std::string ErrorMsg;
- char Number[10] = { 0 };
- ErrorMsg += "Expecting ";
- sprintf(Number, "%d", (uint32_t)Size);
- ErrorMsg += Number;
- ErrorMsg += " bytes, Got ";
- sprintf(Number, "%d", rc);
- ErrorMsg += Number;
- llvm::errs() << "RPC Error: " << Desc << ": " << ErrorMsg << '\n';
- return false;
- }
- return true;
-}
-
-bool RPCChannel::WriteBytes(const void *Data, size_t Size) {
- int rc = write(((ConnectionData_t *)ConnectionData)->OutputPipe, Data, Size);
- return CheckError(rc, Size, "WriteBytes");
-}
-
-bool RPCChannel::ReadBytes(void *Data, size_t Size) {
- int rc = read(((ConnectionData_t *)ConnectionData)->InputPipe, Data, Size);
- return CheckError(rc, Size, "ReadBytes");
-}
-
-RPCChannel::~RPCChannel() {
- delete static_cast<ConnectionData_t *>(ConnectionData);
-}
-
-} // namespace llvm
diff --git a/contrib/llvm/tools/lli/Windows/RPCChannel.inc b/contrib/llvm/tools/lli/Windows/RPCChannel.inc
deleted file mode 100644
index 82f2acb..0000000
--- a/contrib/llvm/tools/lli/Windows/RPCChannel.inc
+++ /dev/null
@@ -1,29 +0,0 @@
-//=- RPCChannel.inc - LLVM out-of-process JIT execution for Windows --=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implementation of the Windows-specific parts of the RPCChannel class
-// which executes JITed code in a separate process from where it was built.
-//
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
-
-bool RPCChannel::createServer() { return false; }
-
-bool RPCChannel::createClient() { return false; }
-
-bool RPCChannel::WriteBytes(const void *Data, size_t Size) { return false; }
-
-bool RPCChannel::ReadBytes(void *Data, size_t Size) { return false; }
-
-void RPCChannel::Wait() {}
-
-RPCChannel::~RPCChannel() {}
-
-} // namespace llvm
diff --git a/contrib/llvm/tools/lli/lli.cpp b/contrib/llvm/tools/lli/lli.cpp
index 057841f..67e7cbd 100644
--- a/contrib/llvm/tools/lli/lli.cpp
+++ b/contrib/llvm/tools/lli/lli.cpp
@@ -13,11 +13,9 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/LLVMContext.h"
#include "OrcLazyJIT.h"
-#include "RemoteMemoryManager.h"
-#include "RemoteTarget.h"
-#include "RemoteTargetExternal.h"
+#include "RemoteJITUtils.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
@@ -28,6 +26,7 @@
#include "llvm/ExecutionEngine/ObjectCache.h"
#include "llvm/ExecutionEngine/OrcMCJITReplacement.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
@@ -262,8 +261,7 @@ public:
if (!getCacheFilename(ModuleID, CacheName))
return;
if (!CacheDir.empty()) { // Create user-defined cache dir.
- SmallString<128> dir(CacheName);
- sys::path::remove_filename(dir);
+ SmallString<128> dir(sys::path::parent_path(CacheName));
sys::fs::create_directories(Twine(dir));
}
std::error_code EC;
@@ -422,7 +420,7 @@ int main(int argc, char **argv, char * const *envp) {
// If not jitting lazily, load the whole bitcode file eagerly too.
if (NoLazyCompilation) {
- if (std::error_code EC = Mod->materializeAllPermanently()) {
+ if (std::error_code EC = Mod->materializeAll()) {
errs() << argv[0] << ": bitcode didn't read correctly.\n";
errs() << "Reason: " << EC.message() << "\n";
exit(1);
@@ -450,7 +448,7 @@ int main(int argc, char **argv, char * const *envp) {
RTDyldMemoryManager *RTDyldMM = nullptr;
if (!ForceInterpreter) {
if (RemoteMCJIT)
- RTDyldMM = new RemoteMemoryManager();
+ RTDyldMM = new ForwardingMemoryManager();
else
RTDyldMM = new SectionMemoryManager();
@@ -583,6 +581,25 @@ int main(int argc, char **argv, char * const *envp) {
int Result;
+ // Sanity check use of remote-jit: LLI currently only supports use of the
+ // remote JIT on Unix platforms.
+ if (RemoteMCJIT) {
+#ifndef LLVM_ON_UNIX
+ errs() << "Warning: host does not support external remote targets.\n"
+ << " Defaulting to local execution execution\n";
+ return -1;
+#else
+ if (ChildExecPath.empty()) {
+ errs() << "-remote-mcjit requires -mcjit-remote-process.\n";
+ exit(1);
+ } else if (!sys::fs::can_execute(ChildExecPath)) {
+ errs() << "Unable to find usable child executable: '" << ChildExecPath
+ << "'\n";
+ return -1;
+ }
+#endif
+ }
+
if (!RemoteMCJIT) {
// If the program doesn't explicitly call exit, we will need the Exit
// function later on to make an explicit call, so get the function now.
@@ -630,66 +647,123 @@ int main(int argc, char **argv, char * const *envp) {
// Remote target MCJIT doesn't (yet) support static constructors. No reason
// it couldn't. This is a limitation of the LLI implemantation, not the
// MCJIT itself. FIXME.
- //
- RemoteMemoryManager *MM = static_cast<RemoteMemoryManager*>(RTDyldMM);
- // Everything is prepared now, so lay out our program for the target
- // address space, assign the section addresses to resolve any relocations,
- // and send it to the target.
-
- std::unique_ptr<RemoteTarget> Target;
- if (!ChildExecPath.empty()) { // Remote execution on a child process
-#ifndef LLVM_ON_UNIX
- // FIXME: Remove this pointless fallback mode which causes tests to "pass"
- // on platforms where they should XFAIL.
- errs() << "Warning: host does not support external remote targets.\n"
- << " Defaulting to simulated remote execution\n";
- Target.reset(new RemoteTarget);
-#else
- if (!sys::fs::can_execute(ChildExecPath)) {
- errs() << "Unable to find usable child executable: '" << ChildExecPath
- << "'\n";
- return -1;
- }
- Target.reset(new RemoteTargetExternal(ChildExecPath));
-#endif
- } else {
- // No child process name provided, use simulated remote execution.
- Target.reset(new RemoteTarget);
+
+ // Lanch the remote process and get a channel to it.
+ std::unique_ptr<FDRPCChannel> C = launchRemote();
+ if (!C) {
+ errs() << "Failed to launch remote JIT.\n";
+ exit(1);
}
- // Give the memory manager a pointer to our remote target interface object.
- MM->setRemoteTarget(Target.get());
+ // Create a remote target client running over the channel.
+ typedef orc::remote::OrcRemoteTargetClient<orc::remote::RPCChannel> MyRemote;
+ ErrorOr<MyRemote> R = MyRemote::Create(*C);
+ if (!R) {
+ errs() << "Could not create remote: " << R.getError().message() << "\n";
+ exit(1);
+ }
- // Create the remote target.
- if (!Target->create()) {
- errs() << "ERROR: " << Target->getErrorMsg() << "\n";
- return EXIT_FAILURE;
+ // Create a remote memory manager.
+ std::unique_ptr<MyRemote::RCMemoryManager> RemoteMM;
+ if (auto EC = R->createRemoteMemoryManager(RemoteMM)) {
+ errs() << "Could not create remote memory manager: " << EC.message() << "\n";
+ exit(1);
}
- // Since we're executing in a (at least simulated) remote address space,
- // we can't use the ExecutionEngine::runFunctionAsMain(). We have to
- // grab the function address directly here and tell the remote target
- // to execute the function.
- //
- // Our memory manager will map generated code into the remote address
- // space as it is loaded and copy the bits over during the finalizeMemory
- // operation.
- //
+ // Forward MCJIT's memory manager calls to the remote memory manager.
+ static_cast<ForwardingMemoryManager*>(RTDyldMM)->setMemMgr(
+ std::move(RemoteMM));
+
+ // Forward MCJIT's symbol resolution calls to the remote.
+ static_cast<ForwardingMemoryManager*>(RTDyldMM)->setResolver(
+ orc::createLambdaResolver(
+ [&](const std::string &Name) {
+ orc::TargetAddress Addr = 0;
+ if (auto EC = R->getSymbolAddress(Addr, Name)) {
+ errs() << "Failure during symbol lookup: " << EC.message() << "\n";
+ exit(1);
+ }
+ return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported);
+ },
+ [](const std::string &Name) { return nullptr; }
+ ));
+
+ // Grab the target address of the JIT'd main function on the remote and call
+ // it.
// FIXME: argv and envp handling.
- uint64_t Entry = EE->getFunctionAddress(EntryFn->getName().str());
-
+ orc::TargetAddress Entry = EE->getFunctionAddress(EntryFn->getName().str());
+ EE->finalizeObject();
DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
<< format("%llx", Entry) << "\n");
-
- if (!Target->executeCode(Entry, Result))
- errs() << "ERROR: " << Target->getErrorMsg() << "\n";
+ if (auto EC = R->callIntVoid(Result, Entry))
+ errs() << "ERROR: " << EC.message() << "\n";
// Like static constructors, the remote target MCJIT support doesn't handle
// this yet. It could. FIXME.
- // Stop the remote target
- Target->stop();
+ // Delete the EE - we need to tear it down *before* we terminate the session
+ // with the remote, otherwise it'll crash when it tries to release resources
+ // on a remote that has already been disconnected.
+ delete EE;
+ EE = nullptr;
+
+ // Signal the remote target that we're done JITing.
+ R->terminateSession();
}
return Result;
}
+
+std::unique_ptr<FDRPCChannel> launchRemote() {
+#ifndef LLVM_ON_UNIX
+ llvm_unreachable("launchRemote not supported on non-Unix platforms");
+#else
+ int PipeFD[2][2];
+ pid_t ChildPID;
+
+ // Create two pipes.
+ if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0)
+ perror("Error creating pipe: ");
+
+ ChildPID = fork();
+
+ if (ChildPID == 0) {
+ // In the child...
+
+ // Close the parent ends of the pipes
+ close(PipeFD[0][1]);
+ close(PipeFD[1][0]);
+
+
+ // Execute the child process.
+ std::unique_ptr<char[]> ChildPath, ChildIn, ChildOut;
+ {
+ ChildPath.reset(new char[ChildExecPath.size() + 1]);
+ std::copy(ChildExecPath.begin(), ChildExecPath.end(), &ChildPath[0]);
+ ChildPath[ChildExecPath.size()] = '\0';
+ std::string ChildInStr = std::to_string(PipeFD[0][0]);
+ ChildIn.reset(new char[ChildInStr.size() + 1]);
+ std::copy(ChildInStr.begin(), ChildInStr.end(), &ChildIn[0]);
+ ChildIn[ChildInStr.size()] = '\0';
+ std::string ChildOutStr = std::to_string(PipeFD[1][1]);
+ ChildOut.reset(new char[ChildOutStr.size() + 1]);
+ std::copy(ChildOutStr.begin(), ChildOutStr.end(), &ChildOut[0]);
+ ChildOut[ChildOutStr.size()] = '\0';
+ }
+
+ char * const args[] = { &ChildPath[0], &ChildIn[0], &ChildOut[0], nullptr };
+ int rc = execv(ChildExecPath.c_str(), args);
+ if (rc != 0)
+ perror("Error executing child process: ");
+ llvm_unreachable("Error executing child process");
+ }
+ // else we're the parent...
+
+ // Close the child ends of the pipes
+ close(PipeFD[0][0]);
+ close(PipeFD[1][1]);
+
+ // Return an RPC channel connected to our end of the pipes.
+ return llvm::make_unique<FDRPCChannel>(PipeFD[1][0], PipeFD[0][1]);
+#endif
+}
diff --git a/contrib/llvm/tools/llvm-ar/llvm-ar.cpp b/contrib/llvm/tools/llvm-ar/llvm-ar.cpp
index 2c9668c..ef5fab6 100644
--- a/contrib/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/contrib/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -81,7 +81,7 @@ static cl::opt<Format>
clEnumValN(GNU, "gnu", "gnu"),
clEnumValN(BSD, "bsd", "bsd"), clEnumValEnd));
-std::string Options;
+static std::string Options;
// Provide additional help output explaining the operations and modifiers of
// llvm-ar. This object instructs the CommandLine library to print the text of
@@ -130,6 +130,7 @@ static bool OnlyUpdate = false; ///< 'u' modifier
static bool Verbose = false; ///< 'v' modifier
static bool Symtab = true; ///< 's' modifier
static bool Deterministic = true; ///< 'D' and 'U' modifiers
+static bool Thin = false; ///< 'T' modifier
// Relative Positional Argument (for insert/move). This variable holds
// the name of the archive member to which the 'a', 'b' or 'i' modifier
@@ -252,6 +253,9 @@ static ArchiveOperation parseCommandLine() {
case 'U':
Deterministic = false;
break;
+ case 'T':
+ Thin = true;
+ break;
default:
cl::PrintHelpMessage();
}
@@ -308,18 +312,9 @@ static void doPrint(StringRef Name, const object::Archive::Child &C) {
// Utility function for printing out the file mode when the 't' operation is in
// verbose mode.
static void printMode(unsigned mode) {
- if (mode & 004)
- outs() << "r";
- else
- outs() << "-";
- if (mode & 002)
- outs() << "w";
- else
- outs() << "-";
- if (mode & 001)
- outs() << "x";
- else
- outs() << "-";
+ outs() << ((mode & 004) ? "r" : "-");
+ outs() << ((mode & 002) ? "w" : "-");
+ outs() << ((mode & 001) ? "x" : "-");
}
// Implement the 't' operation. This function prints out just
@@ -334,7 +329,9 @@ static void doDisplayTable(StringRef Name, const object::Archive::Child &C) {
printMode(Mode & 007);
outs() << ' ' << C.getUID();
outs() << '/' << C.getGID();
- outs() << ' ' << format("%6llu", C.getSize());
+ ErrorOr<uint64_t> Size = C.getSize();
+ failIfError(Size.getError());
+ outs() << ' ' << format("%6llu", Size.get());
outs() << ' ' << C.getLastModified().str();
outs() << ' ';
}
@@ -393,13 +390,14 @@ static bool shouldCreateArchive(ArchiveOperation Op) {
static void performReadOperation(ArchiveOperation Operation,
object::Archive *OldArchive) {
- if (Operation == Extract && OldArchive->isThin()) {
- errs() << "extracting from a thin archive is not supported\n";
- std::exit(1);
- }
+ if (Operation == Extract && OldArchive->isThin())
+ fail("extracting from a thin archive is not supported");
bool Filter = !Members.empty();
- for (const object::Archive::Child &C : OldArchive->children()) {
+ for (auto &ChildOrErr : OldArchive->children()) {
+ failIfError(ChildOrErr.getError());
+ const object::Archive::Child &C = *ChildOrErr;
+
ErrorOr<StringRef> NameOrErr = C.getName();
failIfError(NameOrErr.getError());
StringRef Name = NameOrErr.get();
@@ -432,10 +430,21 @@ static void performReadOperation(ArchiveOperation Operation,
std::exit(1);
}
-template <typename T>
-void addMember(std::vector<NewArchiveIterator> &Members, T I, StringRef Name,
- int Pos = -1) {
- NewArchiveIterator NI(I, Name);
+static void addMember(std::vector<NewArchiveIterator> &Members,
+ StringRef FileName, int Pos = -1) {
+ NewArchiveIterator NI(FileName);
+ if (Pos == -1)
+ Members.push_back(NI);
+ else
+ Members[Pos] = NI;
+}
+
+static void addMember(std::vector<NewArchiveIterator> &Members,
+ const object::Archive::Child &M, StringRef Name,
+ int Pos = -1) {
+ if (Thin && !M.getParent()->isThin())
+ fail("Cannot convert a regular archive to a thin one");
+ NewArchiveIterator NI(M, Name);
if (Pos == -1)
Members.push_back(NI);
else
@@ -451,7 +460,7 @@ enum InsertAction {
};
static InsertAction computeInsertAction(ArchiveOperation Operation,
- object::Archive::child_iterator I,
+ const object::Archive::Child &Member,
StringRef Name,
std::vector<StringRef>::iterator &Pos) {
if (Operation == QuickAppend || Members.empty())
@@ -485,7 +494,7 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,
// operation.
sys::fs::file_status Status;
failIfError(sys::fs::status(*MI, Status), *MI);
- if (Status.getLastModificationTime() < I->getLastModified()) {
+ if (Status.getLastModificationTime() < Member.getLastModified()) {
if (PosName.empty())
return IA_AddOldMember;
return IA_MoveOldMember;
@@ -508,7 +517,9 @@ computeNewArchiveMembers(ArchiveOperation Operation,
int InsertPos = -1;
StringRef PosName = sys::path::filename(RelPos);
if (OldArchive) {
- for (auto &Child : OldArchive->children()) {
+ for (auto &ChildOrErr : OldArchive->children()) {
+ failIfError(ChildOrErr.getError());
+ auto &Child = ChildOrErr.get();
int Pos = Ret.size();
ErrorOr<StringRef> NameOrErr = Child.getName();
failIfError(NameOrErr.getError());
@@ -529,7 +540,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,
addMember(Ret, Child, Name);
break;
case IA_AddNewMeber:
- addMember(Ret, *MemberI, Name);
+ addMember(Ret, *MemberI);
break;
case IA_Delete:
break;
@@ -537,7 +548,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,
addMember(Moved, Child, Name);
break;
case IA_MoveNewMember:
- addMember(Moved, *MemberI, Name);
+ addMember(Moved, *MemberI);
break;
}
if (MemberI != Members.end())
@@ -557,12 +568,10 @@ computeNewArchiveMembers(ArchiveOperation Operation,
assert(unsigned(InsertPos) <= Ret.size());
Ret.insert(Ret.begin() + InsertPos, Moved.begin(), Moved.end());
- Ret.insert(Ret.begin() + InsertPos, Members.size(),
- NewArchiveIterator("", ""));
+ Ret.insert(Ret.begin() + InsertPos, Members.size(), NewArchiveIterator(""));
int Pos = InsertPos;
for (auto &Member : Members) {
- StringRef Name = sys::path::filename(Member);
- addMember(Ret, Member, Name, Pos);
+ addMember(Ret, Member, Pos);
++Pos;
}
@@ -590,15 +599,15 @@ performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive,
break;
}
if (NewMembersP) {
- std::pair<StringRef, std::error_code> Result =
- writeArchive(ArchiveName, *NewMembersP, Symtab, Kind, Deterministic);
+ std::pair<StringRef, std::error_code> Result = writeArchive(
+ ArchiveName, *NewMembersP, Symtab, Kind, Deterministic, Thin);
failIfError(Result.second, Result.first);
return;
}
std::vector<NewArchiveIterator> NewMembers =
computeNewArchiveMembers(Operation, OldArchive);
auto Result =
- writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic);
+ writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic, Thin);
failIfError(Result.second, Result.first);
}
@@ -644,20 +653,13 @@ static int performOperation(ArchiveOperation Operation,
ErrorOr<std::unique_ptr<MemoryBuffer>> Buf =
MemoryBuffer::getFile(ArchiveName, -1, false);
std::error_code EC = Buf.getError();
- if (EC && EC != errc::no_such_file_or_directory) {
- errs() << ToolName << ": error opening '" << ArchiveName
- << "': " << EC.message() << "!\n";
- return 1;
- }
+ if (EC && EC != errc::no_such_file_or_directory)
+ fail("error opening '" + ArchiveName + "': " + EC.message() + "!");
if (!EC) {
object::Archive Archive(Buf.get()->getMemBufferRef(), EC);
-
- if (EC) {
- errs() << ToolName << ": error loading '" << ArchiveName
- << "': " << EC.message() << "!\n";
- return 1;
- }
+ failIfError(EC,
+ "error loading '" + ArchiveName + "': " + EC.message() + "!");
performOperation(Operation, &Archive, NewMembers);
return 0;
}
@@ -713,7 +715,9 @@ static void runMRIScript() {
failIfError(LibOrErr.getError(), "Could not parse library");
Archives.push_back(std::move(*LibOrErr));
object::Archive &Lib = *Archives.back();
- for (auto &Member : Lib.children()) {
+ for (auto &MemberOrErr : Lib.children()) {
+ failIfError(MemberOrErr.getError());
+ auto &Member = MemberOrErr.get();
ErrorOr<StringRef> NameOrErr = Member.getName();
failIfError(NameOrErr.getError());
addMember(NewMembers, Member, *NameOrErr);
@@ -721,7 +725,7 @@ static void runMRIScript() {
break;
}
case MRICommand::AddMod:
- addMember(NewMembers, Rest, sys::path::filename(Rest));
+ addMember(NewMembers, Rest);
break;
case MRICommand::Create:
Create = true;
@@ -784,9 +788,9 @@ int main(int argc, char **argv) {
" This program archives bitcode files into single libraries\n"
);
- if (Stem.find("ar") != StringRef::npos)
- return ar_main();
if (Stem.find("ranlib") != StringRef::npos)
return ranlib_main();
+ if (Stem.find("ar") != StringRef::npos)
+ return ar_main();
fail("Not ranlib, ar or lib!");
}
diff --git a/contrib/llvm/tools/llvm-as/llvm-as.cpp b/contrib/llvm/tools/llvm-as/llvm-as.cpp
index 4455d24..d4e4d8d 100644
--- a/contrib/llvm/tools/llvm-as/llvm-as.cpp
+++ b/contrib/llvm/tools/llvm-as/llvm-as.cpp
@@ -45,6 +45,10 @@ static cl::opt<bool>
DisableOutput("disable-output", cl::desc("Disable output"), cl::init(false));
static cl::opt<bool>
+EmitFunctionSummary("function-summary", cl::desc("Emit function summary index"),
+ cl::init(false));
+
+static cl::opt<bool>
DumpAsm("d", cl::desc("Print assembly as parsed"), cl::Hidden);
static cl::opt<bool>
@@ -77,7 +81,8 @@ static void WriteOutputFile(const Module *M) {
}
if (Force || !CheckBitcodeOutputToConsole(Out->os(), true))
- WriteBitcodeToFile(M, Out->os(), PreserveBitcodeUseListOrder);
+ WriteBitcodeToFile(M, Out->os(), PreserveBitcodeUseListOrder,
+ EmitFunctionSummary);
// Declare success.
Out->keep();
diff --git a/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index 7672951..fe68689 100644
--- a/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -110,10 +110,16 @@ static const char *GetBlockName(unsigned BlockID,
case bitc::TYPE_BLOCK_ID_NEW: return "TYPE_BLOCK_ID";
case bitc::CONSTANTS_BLOCK_ID: return "CONSTANTS_BLOCK";
case bitc::FUNCTION_BLOCK_ID: return "FUNCTION_BLOCK";
+ case bitc::IDENTIFICATION_BLOCK_ID:
+ return "IDENTIFICATION_BLOCK_ID";
case bitc::VALUE_SYMTAB_BLOCK_ID: return "VALUE_SYMTAB";
case bitc::METADATA_BLOCK_ID: return "METADATA_BLOCK";
+ case bitc::METADATA_KIND_BLOCK_ID: return "METADATA_KIND_BLOCK";
case bitc::METADATA_ATTACHMENT_ID: return "METADATA_ATTACHMENT_BLOCK";
case bitc::USELIST_BLOCK_ID: return "USELIST_BLOCK_ID";
+ case bitc::FUNCTION_SUMMARY_BLOCK_ID:
+ return "FUNCTION_SUMMARY_BLOCK";
+ case bitc::MODULE_STRTAB_BLOCK_ID: return "MODULE_STRTAB_BLOCK";
}
}
@@ -165,6 +171,15 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(MODULE_CODE, ALIAS)
STRINGIFY_CODE(MODULE_CODE, PURGEVALS)
STRINGIFY_CODE(MODULE_CODE, GCNAME)
+ STRINGIFY_CODE(MODULE_CODE, VSTOFFSET)
+ STRINGIFY_CODE(MODULE_CODE, METADATA_VALUES)
+ }
+ case bitc::IDENTIFICATION_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return nullptr;
+ STRINGIFY_CODE(IDENTIFICATION_CODE, STRING)
+ STRINGIFY_CODE(IDENTIFICATION_CODE, EPOCH)
}
case bitc::PARAMATTR_BLOCK_ID:
switch (CodeID) {
@@ -241,6 +256,9 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(FUNC_CODE, INST_SWITCH)
STRINGIFY_CODE(FUNC_CODE, INST_INVOKE)
STRINGIFY_CODE(FUNC_CODE, INST_UNREACHABLE)
+ STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
+ STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
+ STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
STRINGIFY_CODE(FUNC_CODE, INST_PHI)
STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA)
STRINGIFY_CODE(FUNC_CODE, INST_LOAD)
@@ -260,6 +278,21 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
default: return nullptr;
STRINGIFY_CODE(VST_CODE, ENTRY)
STRINGIFY_CODE(VST_CODE, BBENTRY)
+ STRINGIFY_CODE(VST_CODE, FNENTRY)
+ STRINGIFY_CODE(VST_CODE, COMBINED_FNENTRY)
+ }
+ case bitc::MODULE_STRTAB_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return nullptr;
+ STRINGIFY_CODE(MST_CODE, ENTRY)
+ }
+ case bitc::FUNCTION_SUMMARY_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return nullptr;
+ STRINGIFY_CODE(FS_CODE, PERMODULE_ENTRY)
+ STRINGIFY_CODE(FS_CODE, COMBINED_ENTRY)
}
case bitc::METADATA_ATTACHMENT_ID:
switch(CodeID) {
@@ -271,7 +304,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
default:return nullptr;
STRINGIFY_CODE(METADATA, STRING)
STRINGIFY_CODE(METADATA, NAME)
- STRINGIFY_CODE(METADATA, KIND)
+ STRINGIFY_CODE(METADATA, KIND) // Older bitcode has it in a MODULE_BLOCK
STRINGIFY_CODE(METADATA, NODE)
STRINGIFY_CODE(METADATA, VALUE)
STRINGIFY_CODE(METADATA, OLD_NODE)
@@ -301,6 +334,12 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(METADATA, IMPORTED_ENTITY)
STRINGIFY_CODE(METADATA, MODULE)
}
+ case bitc::METADATA_KIND_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return nullptr;
+ STRINGIFY_CODE(METADATA, KIND)
+ }
case bitc::USELIST_BLOCK_ID:
switch(CodeID) {
default:return nullptr;
@@ -476,14 +515,38 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
GetCodeName(Code, BlockID, *Stream.getBitStreamReader(),
CurStreamType))
outs() << " codeid=" << Code;
- if (Entry.ID != bitc::UNABBREV_RECORD)
+ const BitCodeAbbrev *Abbv = nullptr;
+ if (Entry.ID != bitc::UNABBREV_RECORD) {
+ Abbv = Stream.getAbbrev(Entry.ID);
outs() << " abbrevid=" << Entry.ID;
+ }
for (unsigned i = 0, e = Record.size(); i != e; ++i)
outs() << " op" << i << "=" << (int64_t)Record[i];
outs() << "/>";
+ if (Abbv) {
+ for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) {
+ const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
+ if (!Op.isEncoding() || Op.getEncoding() != BitCodeAbbrevOp::Array)
+ continue;
+ assert(i + 2 == e && "Array op not second to last");
+ std::string Str;
+ bool ArrayIsPrintable = true;
+ for (unsigned j = i - 1, je = Record.size(); j != je; ++j) {
+ if (!isprint(static_cast<unsigned char>(Record[j]))) {
+ ArrayIsPrintable = false;
+ break;
+ }
+ Str += (char)Record[j];
+ }
+ if (ArrayIsPrintable)
+ outs() << " record string = '" << Str << "'";
+ break;
+ }
+ }
+
if (Blob.data()) {
outs() << " blob data = ";
if (ShowBinaryBlobs) {
diff --git a/contrib/llvm/tools/llvm-cov/CoverageReport.cpp b/contrib/llvm/tools/llvm-cov/CoverageReport.cpp
index 497c2f8..ed01a2e 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/contrib/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -20,7 +20,7 @@ using namespace llvm;
namespace {
/// \brief Helper struct which prints trimmed and aligned columns.
struct Column {
- enum TrimKind { NoTrim, LeftTrim, RightTrim };
+ enum TrimKind { NoTrim, WidthTrim, LeftTrim, RightTrim };
enum AlignmentKind { LeftAlignment, RightAlignment };
@@ -30,7 +30,7 @@ struct Column {
AlignmentKind Alignment;
Column(StringRef Str, unsigned Width)
- : Str(Str), Width(Width), Trim(NoTrim), Alignment(LeftAlignment) {}
+ : Str(Str), Width(Width), Trim(WidthTrim), Alignment(LeftAlignment) {}
Column &set(TrimKind Value) {
Trim = Value;
@@ -44,6 +44,7 @@ struct Column {
void render(raw_ostream &OS) const;
};
+
raw_ostream &operator<<(raw_ostream &OS, const Column &Value) {
Value.render(OS);
return OS;
@@ -64,6 +65,9 @@ void Column::render(raw_ostream &OS) const {
switch (Trim) {
case NoTrim:
+ OS << Str;
+ break;
+ case WidthTrim:
OS << Str.substr(0, Width);
break;
case LeftTrim:
@@ -84,8 +88,19 @@ static Column column(StringRef Str, unsigned Width, const T &Value) {
return Column(Str, Width).set(Value);
}
-static const unsigned FileReportColumns[] = {25, 10, 8, 8, 10, 10};
-static const unsigned FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8};
+static size_t FileReportColumns[] = {25, 10, 8, 8, 10, 10};
+static size_t FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8};
+
+/// \brief Adjust column widths to fit long file paths and function names.
+static void adjustColumnWidths(coverage::CoverageMapping *CM) {
+ for (StringRef Filename : CM->getUniqueSourceFiles()) {
+ FileReportColumns[0] = std::max(FileReportColumns[0], Filename.size());
+ for (const auto &F : CM->getCoveredFunctions(Filename)) {
+ FunctionReportColumns[0] =
+ std::max(FunctionReportColumns[0], F.Name.size());
+ }
+ }
+}
/// \brief Prints a horizontal divider which spans across the given columns.
template <typename T, size_t N>
@@ -108,8 +123,9 @@ static raw_ostream::Colors determineCoveragePercentageColor(const T &Info) {
}
void CoverageReport::render(const FileCoverageSummary &File, raw_ostream &OS) {
- OS << column(File.Name, FileReportColumns[0], Column::LeftTrim)
- << format("%*u", FileReportColumns[1], (unsigned)File.RegionCoverage.NumRegions);
+ OS << column(File.Name, FileReportColumns[0], Column::NoTrim)
+ << format("%*u", FileReportColumns[1],
+ (unsigned)File.RegionCoverage.NumRegions);
Options.colored_ostream(OS, File.RegionCoverage.isFullyCovered()
? raw_ostream::GREEN
: raw_ostream::RED)
@@ -157,6 +173,7 @@ void CoverageReport::render(const FunctionCoverageSummary &Function,
void CoverageReport::renderFunctionReports(ArrayRef<std::string> Files,
raw_ostream &OS) {
+ adjustColumnWidths(Coverage.get());
bool isFirst = true;
for (StringRef Filename : Files) {
if (isFirst)
@@ -191,6 +208,7 @@ void CoverageReport::renderFunctionReports(ArrayRef<std::string> Files,
}
void CoverageReport::renderFileReports(raw_ostream &OS) {
+ adjustColumnWidths(Coverage.get());
OS << column("Filename", FileReportColumns[0])
<< column("Regions", FileReportColumns[1], Column::RightAlignment)
<< column("Miss", FileReportColumns[2], Column::RightAlignment)
@@ -200,6 +218,7 @@ void CoverageReport::renderFileReports(raw_ostream &OS) {
<< "\n";
renderDivider(FileReportColumns, OS);
OS << "\n";
+
FileCoverageSummary Totals("TOTAL");
for (StringRef Filename : Coverage->getUniqueSourceFiles()) {
FileCoverageSummary Summary(Filename);
diff --git a/contrib/llvm/tools/llvm-cov/CoverageViewOptions.h b/contrib/llvm/tools/llvm-cov/CoverageViewOptions.h
index 94b55fe..1208fad 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/contrib/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -24,6 +24,7 @@ struct CoverageViewOptions {
bool ShowLineStatsOrRegionMarkers;
bool ShowExpandedRegions;
bool ShowFunctionInstantiations;
+ bool ShowFullFilenames;
/// \brief Change the output's stream color if the colors are enabled.
ColoredRawOstream colored_ostream(raw_ostream &OS,
diff --git a/contrib/llvm/tools/llvm-cov/gcov.cpp b/contrib/llvm/tools/llvm-cov/gcov.cpp
index 4377a50..a5343fa 100644
--- a/contrib/llvm/tools/llvm-cov/gcov.cpp
+++ b/contrib/llvm/tools/llvm-cov/gcov.cpp
@@ -26,7 +26,7 @@ using namespace llvm;
static void reportCoverage(StringRef SourceFile, StringRef ObjectDir,
const std::string &InputGCNO,
const std::string &InputGCDA, bool DumpGCOV,
- const GCOVOptions &Options) {
+ const GCOV::Options &Options) {
SmallString<128> CoverageFileStem(ObjectDir);
if (CoverageFileStem.empty()) {
// If no directory was specified with -o, look next to the source file.
@@ -143,8 +143,8 @@ int gcovMain(int argc, const char *argv[]) {
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
- GCOVOptions Options(AllBlocks, BranchProb, BranchCount, FuncSummary,
- PreservePaths, UncondBranch, LongNames, NoOutput);
+ GCOV::Options Options(AllBlocks, BranchProb, BranchCount, FuncSummary,
+ PreservePaths, UncondBranch, LongNames, NoOutput);
for (const auto &SourceFile : SourceFiles)
reportCoverage(SourceFile, ObjectDir, InputGCNO, InputGCDA, DumpGCOV,
diff --git a/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp b/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
index 4e06be9e..3dda692 100644
--- a/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
+++ b/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
@@ -40,18 +40,14 @@ cl::list<std::string> InputFilenames(cl::Positional,
cl::ZeroOrMore);
} // namespace opts
-static int ReturnValue = EXIT_SUCCESS;
-
namespace llvm {
-static bool error(std::error_code EC) {
+static void error(std::error_code EC) {
if (!EC)
- return false;
-
- ReturnValue = EXIT_FAILURE;
+ return;
outs() << "\nError reading file: " << EC.message() << ".\n";
outs().flush();
- return true;
+ exit(1);
}
} // namespace llvm
@@ -59,38 +55,24 @@ static bool error(std::error_code EC) {
static void reportError(StringRef Input, StringRef Message) {
if (Input == "-")
Input = "<stdin>";
-
errs() << Input << ": " << Message << "\n";
errs().flush();
- ReturnValue = EXIT_FAILURE;
+ exit(1);
}
static void reportError(StringRef Input, std::error_code EC) {
reportError(Input, EC.message());
}
-static SmallVectorImpl<SectionRef> &getRelocSections(const ObjectFile *Obj,
- const SectionRef &Sec) {
- static bool MappingDone = false;
- static std::map<SectionRef, SmallVector<SectionRef, 1>> SectionRelocMap;
- if (!MappingDone) {
- for (const SectionRef &Section : Obj->sections()) {
- section_iterator Sec2 = Section.getRelocatedSection();
- if (Sec2 != Obj->section_end())
- SectionRelocMap[*Sec2].push_back(Section);
- }
- MappingDone = true;
- }
- return SectionRelocMap[Sec];
-}
+static std::map<SectionRef, SmallVector<SectionRef, 1>> SectionRelocMap;
-static bool collectRelocatedSymbols(const ObjectFile *Obj,
+static void collectRelocatedSymbols(const ObjectFile *Obj,
const SectionRef &Sec, uint64_t SecAddress,
uint64_t SymAddress, uint64_t SymSize,
StringRef *I, StringRef *E) {
uint64_t SymOffset = SymAddress - SecAddress;
uint64_t SymEnd = SymOffset + SymSize;
- for (const SectionRef &SR : getRelocSections(Obj, Sec)) {
+ for (const SectionRef &SR : SectionRelocMap[Sec]) {
for (const object::RelocationRef &Reloc : SR.relocations()) {
if (I == E)
break;
@@ -98,8 +80,7 @@ static bool collectRelocatedSymbols(const ObjectFile *Obj,
if (RelocSymI == Obj->symbol_end())
continue;
ErrorOr<StringRef> RelocSymName = RelocSymI->getName();
- if (error(RelocSymName.getError()))
- return true;
+ error(RelocSymName.getError());
uint64_t Offset = Reloc.getOffset();
if (Offset >= SymOffset && Offset < SymEnd) {
*I = *RelocSymName;
@@ -107,29 +88,26 @@ static bool collectRelocatedSymbols(const ObjectFile *Obj,
}
}
}
- return false;
}
-static bool collectRelocationOffsets(
+static void collectRelocationOffsets(
const ObjectFile *Obj, const SectionRef &Sec, uint64_t SecAddress,
uint64_t SymAddress, uint64_t SymSize, StringRef SymName,
std::map<std::pair<StringRef, uint64_t>, StringRef> &Collection) {
uint64_t SymOffset = SymAddress - SecAddress;
uint64_t SymEnd = SymOffset + SymSize;
- for (const SectionRef &SR : getRelocSections(Obj, Sec)) {
+ for (const SectionRef &SR : SectionRelocMap[Sec]) {
for (const object::RelocationRef &Reloc : SR.relocations()) {
const object::symbol_iterator RelocSymI = Reloc.getSymbol();
if (RelocSymI == Obj->symbol_end())
continue;
ErrorOr<StringRef> RelocSymName = RelocSymI->getName();
- if (error(RelocSymName.getError()))
- return true;
+ error(RelocSymName.getError());
uint64_t Offset = Reloc.getOffset();
if (Offset >= SymOffset && Offset < SymEnd)
Collection[std::make_pair(SymName, Offset - SymOffset)] = *RelocSymName;
}
}
- return false;
}
static void dumpCXXData(const ObjectFile *Obj) {
@@ -182,6 +160,13 @@ static void dumpCXXData(const ObjectFile *Obj) {
std::map<std::pair<StringRef, uint64_t>, StringRef> VTTEntries;
std::map<StringRef, StringRef> TINames;
+ SectionRelocMap.clear();
+ for (const SectionRef &Section : Obj->sections()) {
+ section_iterator Sec2 = Section.getRelocatedSection();
+ if (Sec2 != Obj->section_end())
+ SectionRelocMap[*Sec2].push_back(Section);
+ }
+
uint8_t BytesInAddress = Obj->getBytesInAddress();
std::vector<std::pair<SymbolRef, uint64_t>> SymAddr =
@@ -191,12 +176,11 @@ static void dumpCXXData(const ObjectFile *Obj) {
object::SymbolRef Sym = P.first;
uint64_t SymSize = P.second;
ErrorOr<StringRef> SymNameOrErr = Sym.getName();
- if (error(SymNameOrErr.getError()))
- return;
+ error(SymNameOrErr.getError());
StringRef SymName = *SymNameOrErr;
- object::section_iterator SecI(Obj->section_begin());
- if (error(Sym.getSection(SecI)))
- return;
+ ErrorOr<object::section_iterator> SecIOrErr = Sym.getSection();
+ error(SecIOrErr.getError());
+ object::section_iterator SecI = *SecIOrErr;
// Skip external symbols.
if (SecI == Obj->section_end())
continue;
@@ -205,11 +189,9 @@ static void dumpCXXData(const ObjectFile *Obj) {
if (Sec.isBSS() || Sec.isVirtual())
continue;
StringRef SecContents;
- if (error(Sec.getContents(SecContents)))
- return;
+ error(Sec.getContents(SecContents));
ErrorOr<uint64_t> SymAddressOrErr = Sym.getAddress();
- if (error(SymAddressOrErr.getError()))
- return;
+ error(SymAddressOrErr.getError());
uint64_t SymAddress = *SymAddressOrErr;
uint64_t SecAddress = Sec.getAddress();
uint64_t SecSize = Sec.getSize();
@@ -236,23 +218,19 @@ static void dumpCXXData(const ObjectFile *Obj) {
// Complete object locators in the MS-ABI start with '??_R4'
else if (SymName.startswith("??_R4")) {
CompleteObjectLocator COL;
- COL.Data = ArrayRef<little32_t>(
+ COL.Data = makeArrayRef(
reinterpret_cast<const little32_t *>(SymContents.data()), 3);
StringRef *I = std::begin(COL.Symbols), *E = std::end(COL.Symbols);
- if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I,
- E))
- return;
+ collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E);
COLs[SymName] = COL;
}
// Class hierarchy descriptors in the MS-ABI start with '??_R3'
else if (SymName.startswith("??_R3")) {
ClassHierarchyDescriptor CHD;
- CHD.Data = ArrayRef<little32_t>(
+ CHD.Data = makeArrayRef(
reinterpret_cast<const little32_t *>(SymContents.data()), 3);
StringRef *I = std::begin(CHD.Symbols), *E = std::end(CHD.Symbols);
- if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I,
- E))
- return;
+ collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E);
CHDs[SymName] = CHD;
}
// Class hierarchy descriptors in the MS-ABI start with '??_R2'
@@ -265,12 +243,10 @@ static void dumpCXXData(const ObjectFile *Obj) {
// Base class descriptors in the MS-ABI start with '??_R1'
else if (SymName.startswith("??_R1")) {
BaseClassDescriptor BCD;
- BCD.Data = ArrayRef<little32_t>(
+ BCD.Data = makeArrayRef(
reinterpret_cast<const little32_t *>(SymContents.data()) + 1, 5);
StringRef *I = std::begin(BCD.Symbols), *E = std::end(BCD.Symbols);
- if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I,
- E))
- return;
+ collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E);
BCDs[SymName] = BCD;
}
// Type descriptors in the MS-ABI start with '??_R0'
@@ -283,9 +259,7 @@ static void dumpCXXData(const ObjectFile *Obj) {
TD.AlwaysZero = *reinterpret_cast<const little32_t *>(DataPtr);
TD.MangledName = SymContents.drop_front(BytesInAddress * 2);
StringRef *I = std::begin(TD.Symbols), *E = std::end(TD.Symbols);
- if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I,
- E))
- return;
+ collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E);
TDs[SymName] = TD;
}
// Throw descriptors in the MS-ABI start with '_TI'
@@ -316,9 +290,7 @@ static void dumpCXXData(const ObjectFile *Obj) {
CT.VirtualBaseAdjustmentOffset = DataPtr[4];
CT.Size = DataPtr[5];
StringRef *I = std::begin(CT.Symbols), *E = std::end(CT.Symbols);
- if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I,
- E))
- return;
+ collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E);
CTs[SymName] = CT;
}
// Construction vtables in the Itanium ABI start with '_ZTT' or '__ZTT'.
@@ -510,7 +482,9 @@ static void dumpCXXData(const ObjectFile *Obj) {
}
static void dumpArchive(const Archive *Arc) {
- for (const Archive::Child &ArcC : Arc->children()) {
+ for (auto &ErrorOrChild : Arc->children()) {
+ error(ErrorOrChild.getError());
+ const Archive::Child &ArcC = *ErrorOrChild;
ErrorOr<std::unique_ptr<Binary>> ChildOrErr = ArcC.getAsBinary();
if (std::error_code EC = ChildOrErr.getError()) {
// Ignore non-object files.
@@ -527,12 +501,6 @@ static void dumpArchive(const Archive *Arc) {
}
static void dumpInput(StringRef File) {
- // If file isn't stdin, check that it exists.
- if (File != "-" && !sys::fs::exists(File)) {
- reportError(File, cxxdump_error::file_not_found);
- return;
- }
-
// Attempt to open the binary.
ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(File);
if (std::error_code EC = BinaryOrErr.getError()) {
@@ -569,5 +537,5 @@ int main(int argc, const char *argv[]) {
std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
dumpInput);
- return ReturnValue;
+ return EXIT_SUCCESS;
}
diff --git a/contrib/llvm/tools/llvm-diff/DiffLog.cpp b/contrib/llvm/tools/llvm-diff/DiffLog.cpp
index 24a1b08..ed86058 100644
--- a/contrib/llvm/tools/llvm-diff/DiffLog.cpp
+++ b/contrib/llvm/tools/llvm-diff/DiffLog.cpp
@@ -20,7 +20,8 @@
using namespace llvm;
LogBuilder::~LogBuilder() {
- consumer.logf(*this);
+ if (consumer)
+ consumer->logf(*this);
}
StringRef LogBuilder::getFormat() const { return Format; }
diff --git a/contrib/llvm/tools/llvm-diff/DiffLog.h b/contrib/llvm/tools/llvm-diff/DiffLog.h
index 8eb53ff..8f28461 100644
--- a/contrib/llvm/tools/llvm-diff/DiffLog.h
+++ b/contrib/llvm/tools/llvm-diff/DiffLog.h
@@ -27,7 +27,7 @@ namespace llvm {
/// A temporary-object class for building up log messages.
class LogBuilder {
- Consumer &consumer;
+ Consumer *consumer;
/// The use of a stored StringRef here is okay because
/// LogBuilder should be used only as a temporary, and as a
@@ -38,8 +38,12 @@ namespace llvm {
SmallVector<Value*, 4> Arguments;
public:
- LogBuilder(Consumer &c, StringRef Format)
- : consumer(c), Format(Format) {}
+ LogBuilder(Consumer &c, StringRef Format) : consumer(&c), Format(Format) {}
+ LogBuilder(LogBuilder &&L)
+ : consumer(L.consumer), Format(L.Format),
+ Arguments(std::move(L.Arguments)) {
+ L.consumer = nullptr;
+ }
LogBuilder &operator<<(Value *V) {
Arguments.push_back(V);
diff --git a/contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp b/contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp
index 7d379ef..456560b 100644
--- a/contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp
+++ b/contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp
@@ -599,7 +599,7 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart,
TerminatorInst *RTerm = RStart->getParent()->getTerminator();
if (isa<BranchInst>(LTerm) && isa<InvokeInst>(RTerm)) {
if (cast<BranchInst>(LTerm)->isConditional()) return;
- BasicBlock::iterator I = LTerm;
+ BasicBlock::iterator I = LTerm->getIterator();
if (I == LStart->getParent()->begin()) return;
--I;
if (!isa<CallInst>(*I)) return;
@@ -612,7 +612,7 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart,
tryUnify(LTerm->getSuccessor(0), RInvoke->getNormalDest());
} else if (isa<InvokeInst>(LTerm) && isa<BranchInst>(RTerm)) {
if (cast<BranchInst>(RTerm)->isConditional()) return;
- BasicBlock::iterator I = RTerm;
+ BasicBlock::iterator I = RTerm->getIterator();
if (I == RStart->getParent()->begin()) return;
--I;
if (!isa<CallInst>(*I)) return;
diff --git a/contrib/llvm/tools/llvm-dis/llvm-dis.cpp b/contrib/llvm/tools/llvm-dis/llvm-dis.cpp
index 4b7d94d..9fdfcd4 100644
--- a/contrib/llvm/tools/llvm-dis/llvm-dis.cpp
+++ b/contrib/llvm/tools/llvm-dis/llvm-dis.cpp
@@ -159,7 +159,7 @@ int main(int argc, char **argv) {
ErrorOr<std::unique_ptr<Module>> MOrErr =
getStreamedBitcodeModule(DisplayFilename, std::move(Streamer), Context);
M = std::move(*MOrErr);
- M->materializeAllPermanently();
+ M->materializeAll();
} else {
errs() << argv[0] << ": " << ErrorMessage << '\n';
return 1;
diff --git a/contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index db3fcf6..eaacc7c 100644
--- a/contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/RelocVisitor.h"
#include "llvm/Support/CommandLine.h"
@@ -22,6 +23,7 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
@@ -35,19 +37,19 @@ using namespace llvm;
using namespace object;
static cl::list<std::string>
-InputFilenames(cl::Positional, cl::desc("<input object files>"),
+InputFilenames(cl::Positional, cl::desc("<input object files or .dSYM bundles>"),
cl::ZeroOrMore);
-static cl::opt<DIDumpType>
-DumpType("debug-dump", cl::init(DIDT_All),
- cl::desc("Dump of debug sections:"),
- cl::values(
+static cl::opt<DIDumpType> DumpType(
+ "debug-dump", cl::init(DIDT_All), cl::desc("Dump of debug sections:"),
+ cl::values(
clEnumValN(DIDT_All, "all", "Dump all debug sections"),
clEnumValN(DIDT_Abbrev, "abbrev", ".debug_abbrev"),
clEnumValN(DIDT_AbbrevDwo, "abbrev.dwo", ".debug_abbrev.dwo"),
clEnumValN(DIDT_AppleNames, "apple_names", ".apple_names"),
clEnumValN(DIDT_AppleTypes, "apple_types", ".apple_types"),
- clEnumValN(DIDT_AppleNamespaces, "apple_namespaces", ".apple_namespaces"),
+ clEnumValN(DIDT_AppleNamespaces, "apple_namespaces",
+ ".apple_namespaces"),
clEnumValN(DIDT_AppleObjC, "apple_objc", ".apple_objc"),
clEnumValN(DIDT_Aranges, "aranges", ".debug_aranges"),
clEnumValN(DIDT_Info, "info", ".debug_info"),
@@ -59,6 +61,7 @@ DumpType("debug-dump", cl::init(DIDT_All),
clEnumValN(DIDT_Loc, "loc", ".debug_loc"),
clEnumValN(DIDT_LocDwo, "loc.dwo", ".debug_loc.dwo"),
clEnumValN(DIDT_Frames, "frames", ".debug_frame"),
+ clEnumValN(DIDT_Macro, "macro", ".debug_macinfo"),
clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"),
clEnumValN(DIDT_Pubnames, "pubnames", ".debug_pubnames"),
clEnumValN(DIDT_Pubtypes, "pubtypes", ".debug_pubtypes"),
@@ -66,38 +69,79 @@ DumpType("debug-dump", cl::init(DIDT_All),
clEnumValN(DIDT_GnuPubtypes, "gnu_pubtypes", ".debug_gnu_pubtypes"),
clEnumValN(DIDT_Str, "str", ".debug_str"),
clEnumValN(DIDT_StrDwo, "str.dwo", ".debug_str.dwo"),
- clEnumValN(DIDT_StrOffsetsDwo, "str_offsets.dwo", ".debug_str_offsets.dwo"),
- clEnumValEnd));
+ clEnumValN(DIDT_StrOffsetsDwo, "str_offsets.dwo",
+ ".debug_str_offsets.dwo"),
+ clEnumValN(DIDT_CUIndex, "cu_index", ".debug_cu_index"),
+ clEnumValN(DIDT_TUIndex, "tu_index", ".debug_tu_index"), clEnumValEnd));
-static int ReturnValue = EXIT_SUCCESS;
-
-static bool error(StringRef Filename, std::error_code EC) {
+static void error(StringRef Filename, std::error_code EC) {
if (!EC)
- return false;
+ return;
errs() << Filename << ": " << EC.message() << "\n";
- ReturnValue = EXIT_FAILURE;
- return true;
+ exit(1);
+}
+
+static void DumpObjectFile(ObjectFile &Obj, Twine Filename) {
+ std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(Obj));
+
+ outs() << Filename.str() << ":\tfile format " << Obj.getFileFormatName()
+ << "\n\n";
+ // Dump the complete DWARF structure.
+ DICtx->dump(outs(), DumpType);
}
static void DumpInput(StringRef Filename) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
MemoryBuffer::getFileOrSTDIN(Filename);
- if (error(Filename, BuffOrErr.getError()))
- return;
+ error(Filename, BuffOrErr.getError());
std::unique_ptr<MemoryBuffer> Buff = std::move(BuffOrErr.get());
- ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr =
- ObjectFile::createObjectFile(Buff->getMemBufferRef());
- if (error(Filename, ObjOrErr.getError()))
- return;
- ObjectFile &Obj = *ObjOrErr.get();
+ ErrorOr<std::unique_ptr<Binary>> BinOrErr =
+ object::createBinary(Buff->getMemBufferRef());
+ error(Filename, BinOrErr.getError());
- std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(Obj));
+ if (auto *Obj = dyn_cast<ObjectFile>(BinOrErr->get()))
+ DumpObjectFile(*Obj, Filename);
+ else if (auto *Fat = dyn_cast<MachOUniversalBinary>(BinOrErr->get()))
+ for (auto &ObjForArch : Fat->objects()) {
+ auto MachOOrErr = ObjForArch.getAsObjectFile();
+ error(Filename, MachOOrErr.getError());
+ DumpObjectFile(**MachOOrErr,
+ Filename + " (" + ObjForArch.getArchTypeName() + ")");
+ }
+}
- outs() << Filename
- << ":\tfile format " << Obj.getFileFormatName() << "\n\n";
- // Dump the complete DWARF structure.
- DICtx->dump(outs(), DumpType);
+/// If the input path is a .dSYM bundle (as created by the dsymutil tool),
+/// replace it with individual entries for each of the object files inside the
+/// bundle otherwise return the input path.
+static std::vector<std::string> expandBundle(std::string InputPath) {
+ std::vector<std::string> BundlePaths;
+ SmallString<256> BundlePath(InputPath);
+ // Manually open up the bundle to avoid introducing additional dependencies.
+ if (sys::fs::is_directory(BundlePath) &&
+ sys::path::extension(BundlePath) == ".dSYM") {
+ std::error_code EC;
+ sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
+ for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd;
+ Dir != DirEnd && !EC; Dir.increment(EC)) {
+ const std::string &Path = Dir->path();
+ sys::fs::file_status Status;
+ EC = sys::fs::status(Path, Status);
+ error(Path, EC);
+ switch (Status.type()) {
+ case sys::fs::file_type::regular_file:
+ case sys::fs::file_type::symlink_file:
+ case sys::fs::file_type::type_unknown:
+ BundlePaths.push_back(Path);
+ break;
+ default: /*ignore*/;
+ }
+ }
+ error(BundlePath, EC);
+ }
+ if (!BundlePaths.size())
+ BundlePaths.push_back(InputPath);
+ return BundlePaths;
}
int main(int argc, char **argv) {
@@ -112,7 +156,14 @@ int main(int argc, char **argv) {
if (InputFilenames.size() == 0)
InputFilenames.push_back("a.out");
- std::for_each(InputFilenames.begin(), InputFilenames.end(), DumpInput);
+ // Expand any .dSYM bundles to the individual object files contained therein.
+ std::vector<std::string> Objects;
+ for (auto F : InputFilenames) {
+ auto Objs = expandBundle(F);
+ Objects.insert(Objects.end(), Objs.begin(), Objs.end());
+ }
+
+ std::for_each(Objects.begin(), Objects.end(), DumpInput);
- return ReturnValue;
+ return EXIT_SUCCESS;
}
diff --git a/contrib/llvm/tools/llvm-extract/llvm-extract.cpp b/contrib/llvm/tools/llvm-extract/llvm-extract.cpp
index 936496c..1da456d 100644
--- a/contrib/llvm/tools/llvm-extract/llvm-extract.cpp
+++ b/contrib/llvm/tools/llvm-extract/llvm-extract.cpp
@@ -222,45 +222,42 @@ int main(int argc, char **argv) {
}
}
- // Materialize requisite global values.
- if (!DeleteFn)
- for (size_t i = 0, e = GVs.size(); i != e; ++i) {
- GlobalValue *GV = GVs[i];
- if (std::error_code EC = GV->materialize()) {
- errs() << argv[0] << ": error reading input: " << EC.message() << "\n";
- return 1;
- }
+ auto Materialize = [&](GlobalValue &GV) {
+ if (std::error_code EC = GV.materialize()) {
+ errs() << argv[0] << ": error reading input: " << EC.message() << "\n";
+ exit(1);
}
- else {
+ };
+
+ // Materialize requisite global values.
+ if (!DeleteFn) {
+ for (size_t i = 0, e = GVs.size(); i != e; ++i)
+ Materialize(*GVs[i]);
+ } else {
// Deleting. Materialize every GV that's *not* in GVs.
SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end());
- for (auto &G : M->globals()) {
- if (!GVSet.count(&G)) {
- if (std::error_code EC = G.materialize()) {
- errs() << argv[0] << ": error reading input: " << EC.message()
- << "\n";
- return 1;
- }
- }
- }
for (auto &F : *M) {
- if (!GVSet.count(&F)) {
- if (std::error_code EC = F.materialize()) {
- errs() << argv[0] << ": error reading input: " << EC.message()
- << "\n";
- return 1;
- }
- }
+ if (!GVSet.count(&F))
+ Materialize(F);
}
}
+ {
+ std::vector<GlobalValue *> Gvs(GVs.begin(), GVs.end());
+ legacy::PassManager Extract;
+ Extract.add(createGVExtractionPass(Gvs, DeleteFn));
+ Extract.run(*M);
+
+ // Now that we have all the GVs we want, mark the module as fully
+ // materialized.
+ // FIXME: should the GVExtractionPass handle this?
+ M->materializeAll();
+ }
+
// In addition to deleting all other functions, we also want to spiff it
// up a little bit. Do this now.
legacy::PassManager Passes;
- std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end());
-
- Passes.add(createGVExtractionPass(Gvs, DeleteFn));
if (!DeleteFn)
Passes.add(createGlobalDCEPass()); // Delete unreachable globals
Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info
diff --git a/contrib/llvm/tools/llvm-link/llvm-link.cpp b/contrib/llvm/tools/llvm-link/llvm-link.cpp
index 369f347..a3238302 100644
--- a/contrib/llvm/tools/llvm-link/llvm-link.cpp
+++ b/contrib/llvm/tools/llvm-link/llvm-link.cpp
@@ -18,10 +18,12 @@
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/FunctionInfo.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
+#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
@@ -43,11 +45,34 @@ static cl::list<std::string> OverridingInputs(
cl::desc(
"input bitcode file which can override previously defined symbol(s)"));
+// Option to simulate function importing for testing. This enables using
+// llvm-link to simulate ThinLTO backend processes.
+static cl::list<std::string> Imports(
+ "import", cl::ZeroOrMore, cl::value_desc("function:filename"),
+ cl::desc("Pair of function name and filename, where function should be "
+ "imported from bitcode in filename"));
+
+// Option to support testing of function importing. The function index
+// must be specified in the case were we request imports via the -import
+// option, as well as when compiling any module with functions that may be
+// exported (imported by a different llvm-link -import invocation), to ensure
+// consistent promotion and renaming of locals.
+static cl::opt<std::string> FunctionIndex("functionindex",
+ cl::desc("Function index filename"),
+ cl::init(""),
+ cl::value_desc("filename"));
+
static cl::opt<std::string>
OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
cl::value_desc("filename"));
static cl::opt<bool>
+Internalize("internalize", cl::desc("Internalize linked symbols"));
+
+static cl::opt<bool>
+OnlyNeeded("only-needed", cl::desc("Link only needed symbols"));
+
+static cl::opt<bool>
Force("f", cl::desc("Enable binary output on terminals"));
static cl::opt<bool>
@@ -64,6 +89,10 @@ static cl::opt<bool>
SuppressWarnings("suppress-warnings", cl::desc("Suppress all linking warnings"),
cl::init(false));
+static cl::opt<bool>
+ PreserveModules("preserve-modules",
+ cl::desc("Preserve linked modules for testing"));
+
static cl::opt<bool> PreserveBitcodeUseListOrder(
"preserve-bc-uselistorder",
cl::desc("Preserve use-list order when writing LLVM bitcode."),
@@ -77,16 +106,21 @@ static cl::opt<bool> PreserveAssemblyUseListOrder(
// Read the specified bitcode file in and return it. This routine searches the
// link path for the specified file to try to find it...
//
-static std::unique_ptr<Module>
-loadFile(const char *argv0, const std::string &FN, LLVMContext &Context) {
+static std::unique_ptr<Module> loadFile(const char *argv0,
+ const std::string &FN,
+ LLVMContext &Context,
+ bool MaterializeMetadata = true) {
SMDiagnostic Err;
if (Verbose) errs() << "Loading '" << FN << "'\n";
- std::unique_ptr<Module> Result = getLazyIRFileModule(FN, Err, Context);
+ std::unique_ptr<Module> Result =
+ getLazyIRFileModule(FN, Err, Context, !MaterializeMetadata);
if (!Result)
Err.print(argv0, errs());
- Result->materializeMetadata();
- UpgradeDebugInfo(*Result);
+ if (MaterializeMetadata) {
+ Result->materializeMetadata();
+ UpgradeDebugInfo(*Result);
+ }
return Result;
}
@@ -112,9 +146,111 @@ static void diagnosticHandler(const DiagnosticInfo &DI) {
errs() << '\n';
}
+static void diagnosticHandlerWithContext(const DiagnosticInfo &DI, void *C) {
+ diagnosticHandler(DI);
+}
+
+/// Import any functions requested via the -import option.
+static bool importFunctions(const char *argv0, LLVMContext &Context,
+ Linker &L) {
+ StringMap<std::unique_ptr<DenseMap<unsigned, MDNode *>>>
+ ModuleToTempMDValsMap;
+ for (const auto &Import : Imports) {
+ // Identify the requested function and its bitcode source file.
+ size_t Idx = Import.find(':');
+ if (Idx == std::string::npos) {
+ errs() << "Import parameter bad format: " << Import << "\n";
+ return false;
+ }
+ std::string FunctionName = Import.substr(0, Idx);
+ std::string FileName = Import.substr(Idx + 1, std::string::npos);
+
+ // Load the specified source module.
+ std::unique_ptr<Module> M = loadFile(argv0, FileName, Context, false);
+ if (!M.get()) {
+ errs() << argv0 << ": error loading file '" << FileName << "'\n";
+ return false;
+ }
+
+ if (verifyModule(*M, &errs())) {
+ errs() << argv0 << ": " << FileName
+ << ": error: input module is broken!\n";
+ return false;
+ }
+
+ Function *F = M->getFunction(FunctionName);
+ if (!F) {
+ errs() << "Ignoring import request for non-existent function "
+ << FunctionName << " from " << FileName << "\n";
+ continue;
+ }
+ // We cannot import weak_any functions without possibly affecting the
+ // order they are seen and selected by the linker, changing program
+ // semantics.
+ if (F->hasWeakAnyLinkage()) {
+ errs() << "Ignoring import request for weak-any function " << FunctionName
+ << " from " << FileName << "\n";
+ continue;
+ }
+
+ if (Verbose)
+ errs() << "Importing " << FunctionName << " from " << FileName << "\n";
+
+ std::unique_ptr<FunctionInfoIndex> Index;
+ if (!FunctionIndex.empty()) {
+ ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr =
+ llvm::getFunctionIndexForFile(FunctionIndex, diagnosticHandler);
+ std::error_code EC = IndexOrErr.getError();
+ if (EC) {
+ errs() << EC.message() << '\n';
+ return false;
+ }
+ Index = std::move(IndexOrErr.get());
+ }
+
+ // Save the mapping of value ids to temporary metadata created when
+ // importing this function. If we have already imported from this module,
+ // add new temporary metadata to the existing mapping.
+ auto &TempMDVals = ModuleToTempMDValsMap[FileName];
+ if (!TempMDVals)
+ TempMDVals = llvm::make_unique<DenseMap<unsigned, MDNode *>>();
+
+ // Link in the specified function.
+ DenseSet<const GlobalValue *> FunctionsToImport;
+ FunctionsToImport.insert(F);
+ if (L.linkInModule(std::move(M), Linker::Flags::None, Index.get(),
+ &FunctionsToImport, TempMDVals.get()))
+ return false;
+ }
+
+ // Now link in metadata for all modules from which we imported functions.
+ for (StringMapEntry<std::unique_ptr<DenseMap<unsigned, MDNode *>>> &SME :
+ ModuleToTempMDValsMap) {
+ // Load the specified source module.
+ std::unique_ptr<Module> M = loadFile(argv0, SME.getKey(), Context, true);
+ if (!M.get()) {
+ errs() << argv0 << ": error loading file '" << SME.getKey() << "'\n";
+ return false;
+ }
+
+ if (verifyModule(*M, &errs())) {
+ errs() << argv0 << ": " << SME.getKey()
+ << ": error: input module is broken!\n";
+ return false;
+ }
+
+ // Link in all necessary metadata from this module.
+ if (L.linkInMetadata(*M, SME.getValue().get()))
+ return false;
+ }
+ return true;
+}
+
static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
const cl::list<std::string> &Files,
- bool OverrideDuplicateSymbols) {
+ unsigned Flags) {
+ // Filter out flags that don't apply to the first file we load.
+ unsigned ApplicableFlags = Flags & Linker::Flags::OverrideFromSrc;
for (const auto &File : Files) {
std::unique_ptr<Module> M = loadFile(argv0, File, Context);
if (!M.get()) {
@@ -127,11 +263,36 @@ static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
return false;
}
+ // If a function index is supplied, load it so linkInModule can treat
+ // local functions/variables as exported and promote if necessary.
+ std::unique_ptr<FunctionInfoIndex> Index;
+ if (!FunctionIndex.empty()) {
+ ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr =
+ llvm::getFunctionIndexForFile(FunctionIndex, diagnosticHandler);
+ std::error_code EC = IndexOrErr.getError();
+ if (EC) {
+ errs() << EC.message() << '\n';
+ return false;
+ }
+ Index = std::move(IndexOrErr.get());
+ }
+
if (Verbose)
errs() << "Linking in '" << File << "'\n";
- if (L.linkInModule(M.get(), OverrideDuplicateSymbols))
+ if (L.linkInModule(std::move(M), ApplicableFlags, Index.get()))
return false;
+ // All linker flags apply to linking of subsequent files.
+ ApplicableFlags = Flags;
+
+ // If requested for testing, preserve modules by releasing them from
+ // the unique_ptr before the are freed. This can help catch any
+ // cross-module references from e.g. unneeded metadata references
+ // that aren't properly set to null but instead mapped to the source
+ // module version. The bitcode writer will assert if it finds any such
+ // cross-module references.
+ if (PreserveModules)
+ M.release();
}
return true;
@@ -143,18 +304,31 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv);
LLVMContext &Context = getGlobalContext();
+ Context.setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true);
+
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");
auto Composite = make_unique<Module>("llvm-link", Context);
- Linker L(Composite.get(), diagnosticHandler);
+ Linker L(*Composite);
+
+ unsigned Flags = Linker::Flags::None;
+ if (Internalize)
+ Flags |= Linker::Flags::InternalizeLinkedSymbols;
+ if (OnlyNeeded)
+ Flags |= Linker::Flags::LinkOnlyNeeded;
// First add all the regular input files
- if (!linkFiles(argv[0], Context, L, InputFilenames, false))
+ if (!linkFiles(argv[0], Context, L, InputFilenames, Flags))
return 1;
// Next the -override ones.
- if (!linkFiles(argv[0], Context, L, OverridingInputs, true))
+ if (!linkFiles(argv[0], Context, L, OverridingInputs,
+ Flags | Linker::Flags::OverrideFromSrc))
+ return 1;
+
+ // Import any functions requested via -import
+ if (!importFunctions(argv[0], Context, L))
return 1;
if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;
diff --git a/contrib/llvm/tools/llvm-lto/llvm-lto.cpp b/contrib/llvm/tools/llvm-lto/llvm-lto.cpp
index 0821898..2320511 100644
--- a/contrib/llvm/tools/llvm-lto/llvm-lto.cpp
+++ b/contrib/llvm/tools/llvm-lto/llvm-lto.cpp
@@ -13,16 +13,22 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringSet.h"
+#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/LTO/LTOCodeGenerator.h"
#include "llvm/LTO/LTOModule.h"
+#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"
+#include <list>
using namespace llvm;
@@ -34,6 +40,10 @@ OptLevel("O",
cl::ZeroOrMore,
cl::init('2'));
+static cl::opt<bool> DisableVerify(
+ "disable-verify", cl::init(false),
+ cl::desc("Do not run the verifier during the optimization pipeline"));
+
static cl::opt<bool>
DisableInline("disable-inlining", cl::init(false),
cl::desc("Do not run the inliner pass"));
@@ -50,6 +60,14 @@ static cl::opt<bool>
UseDiagnosticHandler("use-diagnostic-handler", cl::init(false),
cl::desc("Use a diagnostic handler to test the handler interface"));
+static cl::opt<bool>
+ ThinLTO("thinlto", cl::init(false),
+ cl::desc("Only write combined global index for ThinLTO backends"));
+
+static cl::opt<bool>
+SaveModuleFile("save-merged-module", cl::init(false),
+ cl::desc("Write merged LTO module to file before CodeGen"));
+
static cl::list<std::string>
InputFilenames(cl::Positional, cl::OneOrMore,
cl::desc("<input bitcode files>"));
@@ -77,6 +95,9 @@ static cl::opt<bool> SetMergedModule(
"set-merged-module", cl::init(false),
cl::desc("Use the first input module as the merged module"));
+static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
+ cl::desc("Number of backend threads"));
+
namespace {
struct ModuleInfo {
std::vector<bool> CanBeHidden;
@@ -85,6 +106,7 @@ struct ModuleInfo {
static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
const char *Msg, void *) {
+ errs() << "llvm-lto: ";
switch (Severity) {
case LTO_DS_NOTE:
errs() << "note: ";
@@ -102,18 +124,68 @@ static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
errs() << Msg << "\n";
}
+static std::string CurrentActivity;
+static void diagnosticHandler(const DiagnosticInfo &DI) {
+ raw_ostream &OS = errs();
+ OS << "llvm-lto: ";
+ switch (DI.getSeverity()) {
+ case DS_Error:
+ OS << "error";
+ break;
+ case DS_Warning:
+ OS << "warning";
+ break;
+ case DS_Remark:
+ OS << "remark";
+ break;
+ case DS_Note:
+ OS << "note";
+ break;
+ }
+ if (!CurrentActivity.empty())
+ OS << ' ' << CurrentActivity;
+ OS << ": ";
+
+ DiagnosticPrinterRawOStream DP(OS);
+ DI.print(DP);
+ OS << '\n';
+
+ if (DI.getSeverity() == DS_Error)
+ exit(1);
+}
+
+static void diagnosticHandlerWithContenxt(const DiagnosticInfo &DI,
+ void *Context) {
+ diagnosticHandler(DI);
+}
+
+static void error(const Twine &Msg) {
+ errs() << "llvm-lto: " << Msg << '\n';
+ exit(1);
+}
+
+static void error(std::error_code EC, const Twine &Prefix) {
+ if (EC)
+ error(Prefix + ": " + EC.message());
+}
+
+template <typename T>
+static void error(const ErrorOr<T> &V, const Twine &Prefix) {
+ error(V.getError(), Prefix);
+}
+
static std::unique_ptr<LTOModule>
getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
- const TargetOptions &Options, std::string &Error) {
+ const TargetOptions &Options) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
MemoryBuffer::getFile(Path);
- if (std::error_code EC = BufferOrErr.getError()) {
- Error = EC.message();
- return nullptr;
- }
+ error(BufferOrErr, "error loading file '" + Path + "'");
Buffer = std::move(BufferOrErr.get());
- return std::unique_ptr<LTOModule>(LTOModule::createInLocalContext(
- Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Error, Path));
+ CurrentActivity = ("loading file '" + Path + "'").str();
+ ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
+ Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Path);
+ CurrentActivity = "";
+ return std::move(*Ret);
}
/// \brief List symbols in each IR file.
@@ -122,24 +194,44 @@ getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
/// functionality that's exposed by the C API to list symbols. Moreover, this
/// provides testing coverage for modules that have been created in their own
/// contexts.
-static int listSymbols(StringRef Command, const TargetOptions &Options) {
+static void listSymbols(const TargetOptions &Options) {
for (auto &Filename : InputFilenames) {
- std::string Error;
std::unique_ptr<MemoryBuffer> Buffer;
std::unique_ptr<LTOModule> Module =
- getLocalLTOModule(Filename, Buffer, Options, Error);
- if (!Module) {
- errs() << Command << ": error loading file '" << Filename
- << "': " << Error << "\n";
- return 1;
- }
+ getLocalLTOModule(Filename, Buffer, Options);
// List the symbols.
outs() << Filename << ":\n";
for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
outs() << Module->getSymbolName(I) << "\n";
}
- return 0;
+}
+
+/// Create a combined index file from the input IR files and write it.
+///
+/// This is meant to enable testing of ThinLTO combined index generation,
+/// currently available via the gold plugin via -thinlto.
+static void createCombinedFunctionIndex() {
+ FunctionInfoIndex CombinedIndex;
+ uint64_t NextModuleId = 0;
+ for (auto &Filename : InputFilenames) {
+ CurrentActivity = "loading file '" + Filename + "'";
+ ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr =
+ llvm::getFunctionIndexForFile(Filename, diagnosticHandler);
+ std::unique_ptr<FunctionInfoIndex> Index = std::move(IndexOrErr.get());
+ CurrentActivity = "";
+ // Skip files without a function summary.
+ if (!Index)
+ continue;
+ CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId);
+ }
+ std::error_code EC;
+ assert(!OutputFilename.empty());
+ raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
+ sys::fs::OpenFlags::F_None);
+ error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
+ WriteFunctionSummaryToFile(CombinedIndex, OS);
+ OS.close();
}
int main(int argc, char **argv) {
@@ -150,10 +242,8 @@ int main(int argc, char **argv) {
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
- if (OptLevel < '0' || OptLevel > '3') {
- errs() << argv[0] << ": optimization level must be between 0 and 3\n";
- return 1;
- }
+ if (OptLevel < '0' || OptLevel > '3')
+ error("optimization level must be between 0 and 3");
// Initialize the configured targets.
InitializeAllTargets();
@@ -164,29 +254,27 @@ int main(int argc, char **argv) {
// set up the TargetOptions for the machine
TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
- if (ListSymbolsOnly)
- return listSymbols(argv[0], Options);
+ if (ListSymbolsOnly) {
+ listSymbols(Options);
+ return 0;
+ }
+
+ if (ThinLTO) {
+ createCombinedFunctionIndex();
+ return 0;
+ }
unsigned BaseArg = 0;
- LTOCodeGenerator CodeGen;
+ LLVMContext Context;
+ Context.setDiagnosticHandler(diagnosticHandlerWithContenxt, nullptr, true);
+
+ LTOCodeGenerator CodeGen(Context);
if (UseDiagnosticHandler)
CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
- switch (RelocModel) {
- case Reloc::Static:
- CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_STATIC);
- break;
- case Reloc::PIC_:
- CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC);
- break;
- case Reloc::DynamicNoPIC:
- CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC);
- break;
- default:
- CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DEFAULT);
- }
+ CodeGen.setCodePICModel(RelocModel);
CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
CodeGen.setTargetOptions(Options);
@@ -198,38 +286,34 @@ int main(int argc, char **argv) {
std::vector<std::string> KeptDSOSyms;
for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
- std::string error;
- std::unique_ptr<LTOModule> Module(
- LTOModule::createFromFile(InputFilenames[i].c_str(), Options, error));
- if (!error.empty()) {
- errs() << argv[0] << ": error loading file '" << InputFilenames[i]
- << "': " << error << "\n";
- return 1;
+ CurrentActivity = "loading file '" + InputFilenames[i] + "'";
+ ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
+ LTOModule::createFromFile(Context, InputFilenames[i].c_str(), Options);
+ error(ModuleOrErr, "error " + CurrentActivity);
+ std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
+ CurrentActivity = "";
+
+ unsigned NumSyms = Module->getSymbolCount();
+ for (unsigned I = 0; I < NumSyms; ++I) {
+ StringRef Name = Module->getSymbolName(I);
+ if (!DSOSymbolsSet.count(Name))
+ continue;
+ lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
+ unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
+ if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
+ KeptDSOSyms.push_back(Name);
}
- LTOModule *LTOMod = Module.get();
-
// We use the first input module as the destination module when
// SetMergedModule is true.
if (SetMergedModule && i == BaseArg) {
// Transfer ownership to the code generator.
- CodeGen.setModule(Module.release());
+ CodeGen.setModule(std::move(Module));
} else if (!CodeGen.addModule(Module.get())) {
// Print a message here so that we know addModule() did not abort.
errs() << argv[0] << ": error adding file '" << InputFilenames[i] << "'\n";
return 1;
}
-
- unsigned NumSyms = LTOMod->getSymbolCount();
- for (unsigned I = 0; I < NumSyms; ++I) {
- StringRef Name = LTOMod->getSymbolName(I);
- if (!DSOSymbolsSet.count(Name))
- continue;
- lto_symbol_attributes Attrs = LTOMod->getSymbolAttributes(I);
- unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
- if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
- KeptDSOSyms.push_back(Name);
- }
}
// Add all the exported symbols to the table of symbols to preserve.
@@ -255,34 +339,68 @@ int main(int argc, char **argv) {
if (!attrs.empty())
CodeGen.setAttr(attrs.c_str());
+ if (FileType.getNumOccurrences())
+ CodeGen.setFileType(FileType);
+
if (!OutputFilename.empty()) {
- std::string ErrorInfo;
- std::unique_ptr<MemoryBuffer> Code = CodeGen.compile(
- DisableInline, DisableGVNLoadPRE, DisableLTOVectorization, ErrorInfo);
- if (!Code) {
- errs() << argv[0]
- << ": error compiling the code: " << ErrorInfo << "\n";
+ if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
+ DisableLTOVectorization)) {
+ // Diagnostic messages should have been printed by the handler.
+ errs() << argv[0] << ": error optimizing the code\n";
return 1;
}
- std::error_code EC;
- raw_fd_ostream FileStream(OutputFilename, EC, sys::fs::F_None);
- if (EC) {
- errs() << argv[0] << ": error opening the file '" << OutputFilename
- << "': " << EC.message() << "\n";
+ if (SaveModuleFile) {
+ std::string ModuleFilename = OutputFilename;
+ ModuleFilename += ".merged.bc";
+ std::string ErrMsg;
+
+ if (!CodeGen.writeMergedModules(ModuleFilename.c_str())) {
+ errs() << argv[0] << ": writing merged module failed.\n";
+ return 1;
+ }
+ }
+
+ std::list<tool_output_file> OSs;
+ std::vector<raw_pwrite_stream *> OSPtrs;
+ for (unsigned I = 0; I != Parallelism; ++I) {
+ std::string PartFilename = OutputFilename;
+ if (Parallelism != 1)
+ PartFilename += "." + utostr(I);
+ std::error_code EC;
+ OSs.emplace_back(PartFilename, EC, sys::fs::F_None);
+ if (EC) {
+ errs() << argv[0] << ": error opening the file '" << PartFilename
+ << "': " << EC.message() << "\n";
+ return 1;
+ }
+ OSPtrs.push_back(&OSs.back().os());
+ }
+
+ if (!CodeGen.compileOptimized(OSPtrs)) {
+ // Diagnostic messages should have been printed by the handler.
+ errs() << argv[0] << ": error compiling the code\n";
return 1;
}
- FileStream.write(Code->getBufferStart(), Code->getBufferSize());
+ for (tool_output_file &OS : OSs)
+ OS.keep();
} else {
- std::string ErrorInfo;
+ if (Parallelism != 1) {
+ errs() << argv[0] << ": -j must be specified together with -o\n";
+ return 1;
+ }
+
+ if (SaveModuleFile) {
+ errs() << argv[0] << ": -save-merged-module must be specified with -o\n";
+ return 1;
+ }
+
const char *OutputName = nullptr;
- if (!CodeGen.compile_to_file(&OutputName, DisableInline,
- DisableGVNLoadPRE, DisableLTOVectorization,
- ErrorInfo)) {
- errs() << argv[0]
- << ": error compiling the code: " << ErrorInfo
- << "\n";
+ if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline,
+ DisableGVNLoadPRE, DisableLTOVectorization)) {
+ // Diagnostic messages should have been printed by the handler.
+ errs() << argv[0] << ": error compiling the code\n";
return 1;
}
diff --git a/contrib/llvm/tools/llvm-mc/llvm-mc.cpp b/contrib/llvm/tools/llvm-mc/llvm-mc.cpp
index 6ecdb2e..96e3f7c 100644
--- a/contrib/llvm/tools/llvm-mc/llvm-mc.cpp
+++ b/contrib/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -1,4 +1,4 @@
-//===-- llvm-mc.cpp - Machine Code Hacking Driver -------------------------===//
+//===-- llvm-mc.cpp - Machine Code Hacking Driver ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -39,6 +39,7 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
+
using namespace llvm;
static cl::opt<std::string>
@@ -234,7 +235,7 @@ static void setDwarfDebugFlags(int argc, char **argv) {
}
static std::string DwarfDebugProducer;
-static void setDwarfDebugProducer(void) {
+static void setDwarfDebugProducer() {
if(!getenv("DEBUG_PRODUCER"))
return;
DwarfDebugProducer += getenv("DEBUG_PRODUCER");
@@ -398,7 +399,7 @@ int main(int argc, char **argv) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
MemoryBuffer::getFileOrSTDIN(InputFilename);
if (std::error_code EC = BufferPtr.getError()) {
- errs() << ProgName << ": " << EC.message() << '\n';
+ errs() << InputFilename << ": " << EC.message() << '\n';
return 1;
}
MemoryBuffer *Buffer = BufferPtr->get();
@@ -510,9 +511,10 @@ int main(int argc, char **argv) {
MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU);
- Str.reset(TheTarget->createMCObjectStreamer(TheTriple, Ctx, *MAB, *OS, CE,
- *STI, RelaxAll,
- /*DWARFMustBeAtTheEnd*/ false));
+ Str.reset(TheTarget->createMCObjectStreamer(
+ TheTriple, Ctx, *MAB, *OS, CE, *STI, MCOptions.MCRelaxAll,
+ MCOptions.MCIncrementalLinkerCompatible,
+ /*DWARFMustBeAtTheEnd*/ false));
if (NoExecStack)
Str->InitSections(true);
}
diff --git a/contrib/llvm/tools/llvm-nm/llvm-nm.cpp b/contrib/llvm/tools/llvm-nm/llvm-nm.cpp
index e7ee312..b812233 100644
--- a/contrib/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/contrib/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -20,6 +20,7 @@
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
@@ -44,6 +45,7 @@
#include <cstring>
#include <system_error>
#include <vector>
+
using namespace llvm;
using namespace object;
@@ -64,27 +66,30 @@ cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
cl::opt<bool> UndefinedOnly("undefined-only",
cl::desc("Show only undefined symbols"));
cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"),
- cl::aliasopt(UndefinedOnly));
+ cl::aliasopt(UndefinedOnly), cl::Grouping);
cl::opt<bool> DynamicSyms("dynamic",
cl::desc("Display the dynamic symbols instead "
"of normal symbols."));
cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"),
- cl::aliasopt(DynamicSyms));
+ cl::aliasopt(DynamicSyms), cl::Grouping);
cl::opt<bool> DefinedOnly("defined-only",
cl::desc("Show only defined symbols"));
cl::alias DefinedOnly2("U", cl::desc("Alias for --defined-only"),
- cl::aliasopt(DefinedOnly));
+ cl::aliasopt(DefinedOnly), cl::Grouping);
cl::opt<bool> ExternalOnly("extern-only",
cl::desc("Show only external symbols"));
cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"),
- cl::aliasopt(ExternalOnly));
+ cl::aliasopt(ExternalOnly), cl::Grouping);
-cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"));
-cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"));
-cl::opt<bool> DarwinFormat("m", cl::desc("Alias for --format=darwin"));
+cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"),
+ cl::Grouping);
+cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"),
+ cl::Grouping);
+cl::opt<bool> DarwinFormat("m", cl::desc("Alias for --format=darwin"),
+ cl::Grouping);
static cl::list<std::string>
ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
@@ -96,32 +101,33 @@ cl::opt<bool> PrintFileName(
cl::desc("Precede each symbol with the object file it came from"));
cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"),
- cl::aliasopt(PrintFileName));
+ cl::aliasopt(PrintFileName), cl::Grouping);
cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"),
- cl::aliasopt(PrintFileName));
+ cl::aliasopt(PrintFileName), cl::Grouping);
cl::opt<bool> DebugSyms("debug-syms",
cl::desc("Show all symbols, even debugger only"));
cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"),
- cl::aliasopt(DebugSyms));
+ cl::aliasopt(DebugSyms), cl::Grouping);
cl::opt<bool> NumericSort("numeric-sort", cl::desc("Sort symbols by address"));
cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"),
- cl::aliasopt(NumericSort));
+ cl::aliasopt(NumericSort), cl::Grouping);
cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"),
- cl::aliasopt(NumericSort));
+ cl::aliasopt(NumericSort), cl::Grouping);
cl::opt<bool> NoSort("no-sort", cl::desc("Show symbols in order encountered"));
-cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), cl::aliasopt(NoSort));
+cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), cl::aliasopt(NoSort),
+ cl::Grouping);
cl::opt<bool> ReverseSort("reverse-sort", cl::desc("Sort in reverse order"));
cl::alias ReverseSortr("r", cl::desc("Alias for --reverse-sort"),
- cl::aliasopt(ReverseSort));
+ cl::aliasopt(ReverseSort), cl::Grouping);
cl::opt<bool> PrintSize("print-size",
cl::desc("Show symbol size instead of address"));
cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"),
- cl::aliasopt(PrintSize));
+ cl::aliasopt(PrintSize), cl::Grouping);
cl::opt<bool> SizeSort("size-sort", cl::desc("Sort symbols by size"));
@@ -130,12 +136,12 @@ cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden,
cl::opt<bool> ArchiveMap("print-armap", cl::desc("Print the archive map"));
cl::alias ArchiveMaps("M", cl::desc("Alias for --print-armap"),
- cl::aliasopt(ArchiveMap));
+ cl::aliasopt(ArchiveMap), cl::Grouping);
cl::opt<bool> JustSymbolName("just-symbol-name",
cl::desc("Print just the symbol's name"));
cl::alias JustSymbolNames("j", cl::desc("Alias for --just-symbol-name"),
- cl::aliasopt(JustSymbolName));
+ cl::aliasopt(JustSymbolName), cl::Grouping);
// FIXME: This option takes exactly two strings and should be allowed anywhere
// on the command line. Such that "llvm-nm -s __TEXT __text foo.o" would work.
@@ -147,7 +153,7 @@ cl::list<std::string> SegSect("s", cl::Positional, cl::ZeroOrMore,
"and section name, Mach-O only"));
cl::opt<bool> FormatMachOasHex("x", cl::desc("Print symbol entry in hex, "
- "Mach-O only"));
+ "Mach-O only"), cl::Grouping);
cl::opt<bool> NoLLVMBitcode("no-llvm-bc",
cl::desc("Disable LLVM bitcode reader"));
@@ -159,7 +165,7 @@ bool MultipleFiles = false;
bool HadError = false;
std::string ToolName;
-}
+} // anonymous namespace
static void error(Twine Message, Twine Path = Twine()) {
HadError = true;
@@ -182,7 +188,7 @@ struct NMSymbol {
StringRef Name;
BasicSymbolRef Sym;
};
-}
+} // anonymous namespace
static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) {
bool ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined);
@@ -202,8 +208,14 @@ static bool compareSymbolName(const NMSymbol &A, const NMSymbol &B) {
}
static char isSymbolList64Bit(SymbolicFile &Obj) {
- if (isa<IRObjectFile>(Obj))
- return false;
+ if (isa<IRObjectFile>(Obj)) {
+ IRObjectFile *IRobj = dyn_cast<IRObjectFile>(&Obj);
+ Module &M = IRobj->getModule();
+ if (M.getTargetTriple().empty())
+ return false;
+ Triple T(M.getTargetTriple());
+ return T.isArch64Bit();
+ }
if (isa<COFFObjectFile>(Obj))
return false;
if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
@@ -215,54 +227,80 @@ static StringRef CurrentFilename;
typedef std::vector<NMSymbol> SymbolListT;
static SymbolListT SymbolList;
+static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I);
+
// darwinPrintSymbol() is used to print a symbol from a Mach-O file when the
// the OutputFormat is darwin or we are printing Mach-O symbols in hex. For
// the darwin format it produces the same output as darwin's nm(1) -m output
// and when printing Mach-O symbols in hex it produces the same output as
// darwin's nm(1) -x format.
-static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I,
- char *SymbolAddrStr, const char *printBlanks) {
+static void darwinPrintSymbol(SymbolicFile &Obj, SymbolListT::iterator I,
+ char *SymbolAddrStr, const char *printBlanks,
+ const char *printDashes, const char *printFormat) {
MachO::mach_header H;
MachO::mach_header_64 H_64;
- uint32_t Filetype, Flags;
- MachO::nlist_64 STE_64;
- MachO::nlist STE;
- uint8_t NType;
- uint8_t NSect;
- uint16_t NDesc;
- uint32_t NStrx;
- uint64_t NValue;
- DataRefImpl SymDRI = I->Sym.getRawDataRefImpl();
- if (MachO->is64Bit()) {
- H_64 = MachO->MachOObjectFile::getHeader64();
- Filetype = H_64.filetype;
- Flags = H_64.flags;
- STE_64 = MachO->getSymbol64TableEntry(SymDRI);
- NType = STE_64.n_type;
- NSect = STE_64.n_sect;
- NDesc = STE_64.n_desc;
- NStrx = STE_64.n_strx;
- NValue = STE_64.n_value;
+ uint32_t Filetype = MachO::MH_OBJECT;
+ uint32_t Flags = 0;
+ uint8_t NType = 0;
+ uint8_t NSect = 0;
+ uint16_t NDesc = 0;
+ uint32_t NStrx = 0;
+ uint64_t NValue = 0;
+ MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
+ if (Obj.isIR()) {
+ uint32_t SymFlags = I->Sym.getFlags();
+ if (SymFlags & SymbolRef::SF_Global)
+ NType |= MachO::N_EXT;
+ if (SymFlags & SymbolRef::SF_Hidden)
+ NType |= MachO::N_PEXT;
+ if (SymFlags & SymbolRef::SF_Undefined)
+ NType |= MachO::N_EXT | MachO::N_UNDF;
+ else {
+ // Here we have a symbol definition. So to fake out a section name we
+ // use 1, 2 and 3 for section numbers. See below where they are used to
+ // print out fake section names.
+ NType |= MachO::N_SECT;
+ if(SymFlags & SymbolRef::SF_Const)
+ NSect = 3;
+ else {
+ IRObjectFile *IRobj = dyn_cast<IRObjectFile>(&Obj);
+ char c = getSymbolNMTypeChar(*IRobj, I->Sym);
+ if (c == 't')
+ NSect = 1;
+ else
+ NSect = 2;
+ }
+ }
+ if (SymFlags & SymbolRef::SF_Weak)
+ NDesc |= MachO::N_WEAK_DEF;
} else {
- H = MachO->MachOObjectFile::getHeader();
- Filetype = H.filetype;
- Flags = H.flags;
- STE = MachO->getSymbolTableEntry(SymDRI);
- NType = STE.n_type;
- NSect = STE.n_sect;
- NDesc = STE.n_desc;
- NStrx = STE.n_strx;
- NValue = STE.n_value;
+ DataRefImpl SymDRI = I->Sym.getRawDataRefImpl();
+ if (MachO->is64Bit()) {
+ H_64 = MachO->MachOObjectFile::getHeader64();
+ Filetype = H_64.filetype;
+ Flags = H_64.flags;
+ MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI);
+ NType = STE_64.n_type;
+ NSect = STE_64.n_sect;
+ NDesc = STE_64.n_desc;
+ NStrx = STE_64.n_strx;
+ NValue = STE_64.n_value;
+ } else {
+ H = MachO->MachOObjectFile::getHeader();
+ Filetype = H.filetype;
+ Flags = H.flags;
+ MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI);
+ NType = STE.n_type;
+ NSect = STE.n_sect;
+ NDesc = STE.n_desc;
+ NStrx = STE.n_strx;
+ NValue = STE.n_value;
+ }
}
// If we are printing Mach-O symbols in hex do that and return.
if (FormatMachOasHex) {
char Str[18] = "";
- const char *printFormat;
- if (MachO->is64Bit())
- printFormat = "%016" PRIx64;
- else
- printFormat = "%08" PRIx64;
format(printFormat, NValue).print(Str, sizeof(Str));
outs() << Str << ' ';
format("%02x", NType).print(Str, sizeof(Str));
@@ -280,6 +318,8 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I,
if (PrintAddress) {
if ((NType & MachO::N_TYPE) == MachO::N_INDR)
strcpy(SymbolAddrStr, printBlanks);
+ if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE)
+ strcpy(SymbolAddrStr, printDashes);
outs() << SymbolAddrStr << ' ';
}
@@ -314,8 +354,20 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I,
outs() << "(indirect) ";
break;
case MachO::N_SECT: {
- section_iterator Sec = MachO->section_end();
- MachO->getSymbolSection(I->Sym.getRawDataRefImpl(), Sec);
+ if (Obj.isIR()) {
+ // For llvm bitcode files print out a fake section name using the values
+ // use 1, 2 and 3 for section numbers as set above.
+ if (NSect == 1)
+ outs() << "(LTO,CODE) ";
+ else if (NSect == 2)
+ outs() << "(LTO,DATA) ";
+ else if (NSect == 3)
+ outs() << "(LTO,RODATA) ";
+ else
+ outs() << "(?,?) ";
+ break;
+ }
+ section_iterator Sec = *MachO->getSymbolSection(I->Sym.getRawDataRefImpl());
DataRefImpl Ref = Sec->getRawDataRefImpl();
StringRef SectionName;
MachO->getSectionName(Ref, SectionName);
@@ -374,7 +426,8 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I,
if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
outs() << I->Name << " (for ";
StringRef IndirectName;
- if (MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName))
+ if (!MachO ||
+ MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName))
outs() << "?)";
else
outs() << IndirectName << ")";
@@ -392,7 +445,8 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I,
outs() << " (dynamically looked up)";
else {
StringRef LibraryName;
- if (MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName))
+ if (!MachO ||
+ MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName))
outs() << " (from bad library ordinal " << LibraryOrdinal << ")";
else
outs() << " (from " << LibraryName << ")";
@@ -440,13 +494,14 @@ static const struct DarwinStabName DarwinStabNames[] = {
{MachO::N_ECOMM, "ECOMM"},
{MachO::N_ECOML, "ECOML"},
{MachO::N_LENG, "LENG"},
- {0, 0}};
+ {0, nullptr}};
+
static const char *getDarwinStabString(uint8_t NType) {
for (unsigned i = 0; DarwinStabNames[i].Name; i++) {
if (DarwinStabNames[i].NType == NType)
return DarwinStabNames[i].Name;
}
- return 0;
+ return nullptr;
}
// darwinPrintStab() prints the n_sect, n_desc along with a symbolic name of
@@ -511,12 +566,14 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
}
}
- const char *printBlanks, *printFormat;
+ const char *printBlanks, *printDashes, *printFormat;
if (isSymbolList64Bit(Obj)) {
printBlanks = " ";
+ printDashes = "----------------";
printFormat = "%016" PRIx64;
} else {
printBlanks = " ";
+ printDashes = "--------";
printFormat = "%08" PRIx64;
}
@@ -528,6 +585,9 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
continue;
if (Undefined && DefinedOnly)
continue;
+ bool Global = SymFlags & SymbolRef::SF_Global;
+ if (!Global && ExternalOnly)
+ continue;
if (SizeSort && !PrintAddress)
continue;
if (PrintFileName) {
@@ -537,7 +597,8 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
outs() << ArchiveName << ":";
outs() << CurrentFilename << ": ";
}
- if (JustSymbolName || (UndefinedOnly && isa<MachOObjectFile>(Obj))) {
+ if ((JustSymbolName || (UndefinedOnly && isa<MachOObjectFile>(Obj) &&
+ OutputFormat != darwin)) && OutputFormat != posix) {
outs() << I->Name << "\n";
continue;
}
@@ -550,9 +611,13 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
if (OutputFormat == sysv)
strcpy(SymbolSizeStr, printBlanks);
- if (I->TypeChar != 'U')
- format(printFormat, I->Address)
+ if (I->TypeChar != 'U') {
+ if (Obj.isIR())
+ strcpy(SymbolAddrStr, printDashes);
+ else
+ format(printFormat, I->Address)
.print(SymbolAddrStr, sizeof(SymbolAddrStr));
+ }
format(printFormat, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
// If OutputFormat is darwin or we are printing Mach-O symbols in hex and
@@ -561,11 +626,15 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
// printing Mach-O symbols in hex and not a Mach-O object fall back to
// OutputFormat bsd (see below).
MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
- if ((OutputFormat == darwin || FormatMachOasHex) && MachO) {
- darwinPrintSymbol(MachO, I, SymbolAddrStr, printBlanks);
+ if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) {
+ darwinPrintSymbol(Obj, I, SymbolAddrStr, printBlanks, printDashes,
+ printFormat);
} else if (OutputFormat == posix) {
- outs() << I->Name << " " << I->TypeChar << " " << SymbolAddrStr
- << SymbolSizeStr << "\n";
+ outs() << I->Name << " " << I->TypeChar << " ";
+ if (MachO)
+ outs() << I->Address << " " << "0" /* SymbolSizeStr */ << "\n";
+ else
+ outs() << SymbolAddrStr << SymbolSizeStr << "\n";
} else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) {
if (PrintAddress)
outs() << SymbolAddrStr << ' ';
@@ -594,10 +663,11 @@ static char getSymbolNMTypeChar(ELFObjectFileBase &Obj,
// OK, this is ELF
elf_symbol_iterator SymI(I);
- elf_section_iterator SecI = Obj.section_end();
- if (error(SymI->getSection(SecI)))
+ ErrorOr<elf_section_iterator> SecIOrErr = SymI->getSection();
+ if (error(SecIOrErr.getError()))
return '?';
+ elf_section_iterator SecI = *SecIOrErr;
if (SecI != Obj.section_end()) {
switch (SecI->getType()) {
case ELF::SHT_PROGBITS:
@@ -651,9 +721,10 @@ static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) {
uint32_t Characteristics = 0;
if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) {
- section_iterator SecI = Obj.section_end();
- if (error(SymI->getSection(SecI)))
+ ErrorOr<section_iterator> SecIOrErr = SymI->getSection();
+ if (error(SecIOrErr.getError()))
return '?';
+ section_iterator SecI = *SecIOrErr;
const coff_section *Section = Obj.getCOFFSection(*SecI);
Characteristics = Section->Characteristics;
}
@@ -701,8 +772,7 @@ static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
case MachO::N_INDR:
return 'i';
case MachO::N_SECT: {
- section_iterator Sec = Obj.section_end();
- Obj.getSymbolSection(Symb, Sec);
+ section_iterator Sec = *Obj.getSymbolSection(Symb);
DataRefImpl Ref = Sec->getRawDataRefImpl();
StringRef SectionName;
Obj.getSectionName(Ref, SectionName);
@@ -762,8 +832,14 @@ static char getNMTypeChar(SymbolicFile &Obj, basic_symbol_iterator I) {
char Ret = '?';
if (Symflags & object::SymbolRef::SF_Absolute)
Ret = 'a';
- else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(&Obj))
+ else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(&Obj)) {
Ret = getSymbolNMTypeChar(*IR, I);
+ Triple Host(sys::getDefaultTargetTriple());
+ if (Ret == 'd' && Host.isOSDarwin()) {
+ if(Symflags & SymbolRef::SF_Const)
+ Ret = 's';
+ }
+ }
else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(&Obj))
Ret = getSymbolNMTypeChar(*COFF, I);
else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
@@ -943,10 +1019,10 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
if (I != E) {
outs() << "Archive map\n";
for (; I != E; ++I) {
- ErrorOr<Archive::child_iterator> C = I->getMember();
+ ErrorOr<Archive::Child> C = I->getMember();
if (error(C.getError()))
return;
- ErrorOr<StringRef> FileNameOrErr = C.get()->getName();
+ ErrorOr<StringRef> FileNameOrErr = C->getName();
if (error(FileNameOrErr.getError()))
return;
StringRef SymName = I->getName();
@@ -958,7 +1034,10 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
for (Archive::child_iterator I = A->child_begin(), E = A->child_end();
I != E; ++I) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = I->getAsBinary(&Context);
+ if (error(I->getError()))
+ return;
+ auto &C = I->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(&Context);
if (ChildOrErr.getError())
continue;
if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
@@ -1013,8 +1092,11 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
+ if (error(AI->getError()))
+ return;
+ auto &C = AI->get();
ErrorOr<std::unique_ptr<Binary>> ChildOrErr =
- AI->getAsBinary(&Context);
+ C.getAsBinary(&Context);
if (ChildOrErr.getError())
continue;
if (SymbolicFile *O =
@@ -1067,8 +1149,11 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
+ if (error(AI->getError()))
+ return;
+ auto &C = AI->get();
ErrorOr<std::unique_ptr<Binary>> ChildOrErr =
- AI->getAsBinary(&Context);
+ C.getAsBinary(&Context);
if (ChildOrErr.getError())
continue;
if (SymbolicFile *O =
@@ -1116,8 +1201,10 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
std::unique_ptr<Archive> &A = *AOrErr;
for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end();
AI != AE; ++AI) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr =
- AI->getAsBinary(&Context);
+ if (error(AI->getError()))
+ return;
+ auto &C = AI->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(&Context);
if (ChildOrErr.getError())
continue;
if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
@@ -1150,7 +1237,6 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
return;
}
error("unrecognizable file type", Filename);
- return;
}
int main(int argc, char **argv) {
diff --git a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
index 8b94a50..5d21b33 100644
--- a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp
@@ -151,7 +151,7 @@ static void printAllUnwindCodes(ArrayRef<UnwindCode> UCs) {
<< " remaining in buffer";
return ;
}
- printUnwindCode(ArrayRef<UnwindCode>(I, E));
+ printUnwindCode(makeArrayRef(I, E));
I += UsedSlots;
}
}
@@ -165,10 +165,10 @@ resolveSectionAndAddress(const COFFObjectFile *Obj, const SymbolRef &Sym,
if (std::error_code EC = ResolvedAddrOrErr.getError())
return EC;
ResolvedAddr = *ResolvedAddrOrErr;
- section_iterator iter(Obj->section_begin());
- if (std::error_code EC = Sym.getSection(iter))
+ ErrorOr<section_iterator> Iter = Sym.getSection();
+ if (std::error_code EC = Iter.getError())
return EC;
- ResolvedSection = Obj->getCOFFSection(*iter);
+ ResolvedSection = Obj->getCOFFSection(**Iter);
return std::error_code();
}
@@ -241,12 +241,10 @@ printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) {
return;
const pe32_header *PE32Header;
- if (error(Obj->getPE32Header(PE32Header)))
- return;
+ error(Obj->getPE32Header(PE32Header));
uint32_t ImageBase = PE32Header->ImageBase;
uintptr_t IntPtr = 0;
- if (error(Obj->getVaPtr(TableVA, IntPtr)))
- return;
+ error(Obj->getVaPtr(TableVA, IntPtr));
const support::ulittle32_t *P = (const support::ulittle32_t *)IntPtr;
outs() << "SEH Table:";
for (int I = 0; I < Count; ++I)
@@ -257,8 +255,7 @@ printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) {
static void printLoadConfiguration(const COFFObjectFile *Obj) {
// Skip if it's not executable.
const pe32_header *PE32Header;
- if (error(Obj->getPE32Header(PE32Header)))
- return;
+ error(Obj->getPE32Header(PE32Header));
if (!PE32Header)
return;
@@ -267,13 +264,11 @@ static void printLoadConfiguration(const COFFObjectFile *Obj) {
return;
const data_directory *DataDir;
- if (error(Obj->getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataDir)))
- return;
+ error(Obj->getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataDir));
uintptr_t IntPtr = 0;
if (DataDir->RelativeVirtualAddress == 0)
return;
- if (error(Obj->getRvaPtr(DataDir->RelativeVirtualAddress, IntPtr)))
- return;
+ error(Obj->getRvaPtr(DataDir->RelativeVirtualAddress, IntPtr));
auto *LoadConf = reinterpret_cast<const coff_load_configuration32 *>(IntPtr);
outs() << "Load configuration:"
@@ -363,13 +358,30 @@ static void printExportTable(const COFFObjectFile *Obj) {
uint32_t RVA;
if (I->getExportRVA(RVA))
return;
- outs() << format(" % 4d %# 8x", Ordinal, RVA);
+ bool IsForwarder;
+ if (I->isForwarder(IsForwarder))
+ return;
+
+ if (IsForwarder) {
+ // Export table entries can be used to re-export symbols that
+ // this COFF file is imported from some DLLs. This is rare.
+ // In most cases IsForwarder is false.
+ outs() << format(" % 4d ", Ordinal);
+ } else {
+ outs() << format(" % 4d %# 8x", Ordinal, RVA);
+ }
StringRef Name;
if (I->getSymbolName(Name))
continue;
if (!Name.empty())
outs() << " " << Name;
+ if (IsForwarder) {
+ StringRef S;
+ if (I->getForwardTo(S))
+ return;
+ outs() << " (forwarded to " << S << ")";
+ }
outs() << "\n";
}
}
@@ -381,8 +393,7 @@ static bool getPDataSection(const COFFObjectFile *Obj,
const RuntimeFunction *&RFStart, int &NumRFs) {
for (const SectionRef &Section : Obj->sections()) {
StringRef Name;
- if (error(Section.getName(Name)))
- continue;
+ error(Section.getName(Name));
if (Name != ".pdata")
continue;
@@ -394,8 +405,7 @@ static bool getPDataSection(const COFFObjectFile *Obj,
std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
ArrayRef<uint8_t> Contents;
- if (error(Obj->getSectionContents(Pdata, Contents)))
- continue;
+ error(Obj->getSectionContents(Pdata, Contents));
if (Contents.empty())
continue;
@@ -440,7 +450,7 @@ static void printWin64EHUnwindInfo(const Win64EH::UnwindInfo *UI) {
if (UI->NumCodes)
outs() << " Unwind Codes:\n";
- printAllUnwindCodes(ArrayRef<UnwindCode>(&UI->UnwindCodes[0], UI->NumCodes));
+ printAllUnwindCodes(makeArrayRef(&UI->UnwindCodes[0], UI->NumCodes));
outs() << "\n";
outs().flush();
@@ -499,11 +509,10 @@ static void printRuntimeFunctionRels(const COFFObjectFile *Obj,
ArrayRef<uint8_t> XContents;
uint64_t UnwindInfoOffset = 0;
- if (error(getSectionContents(
+ error(getSectionContents(
Obj, Rels, SectionOffset +
/*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
- XContents, UnwindInfoOffset)))
- return;
+ XContents, UnwindInfoOffset));
if (XContents.empty())
return;
@@ -550,3 +559,52 @@ void llvm::printCOFFFileHeader(const object::ObjectFile *Obj) {
printImportTables(file);
printExportTable(file);
}
+
+void llvm::printCOFFSymbolTable(const COFFObjectFile *coff) {
+ for (unsigned SI = 0, SE = coff->getNumberOfSymbols(); SI != SE; ++SI) {
+ ErrorOr<COFFSymbolRef> Symbol = coff->getSymbol(SI);
+ StringRef Name;
+ error(Symbol.getError());
+ error(coff->getSymbolName(*Symbol, Name));
+
+ outs() << "[" << format("%2d", SI) << "]"
+ << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")"
+ << "(fl 0x00)" // Flag bits, which COFF doesn't have.
+ << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")"
+ << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) << ") "
+ << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") "
+ << "0x" << format("%08x", unsigned(Symbol->getValue())) << " "
+ << Name << "\n";
+
+ for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) {
+ if (Symbol->isSectionDefinition()) {
+ const coff_aux_section_definition *asd;
+ error(coff->getAuxSymbol<coff_aux_section_definition>(SI + 1, asd));
+
+ int32_t AuxNumber = asd->getNumber(Symbol->isBigObj());
+
+ outs() << "AUX "
+ << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x "
+ , unsigned(asd->Length)
+ , unsigned(asd->NumberOfRelocations)
+ , unsigned(asd->NumberOfLinenumbers)
+ , unsigned(asd->CheckSum))
+ << format("assoc %d comdat %d\n"
+ , unsigned(AuxNumber)
+ , unsigned(asd->Selection));
+ } else if (Symbol->isFileRecord()) {
+ const char *FileName;
+ error(coff->getAuxSymbol<char>(SI + 1, FileName));
+
+ StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() *
+ coff->getSymbolTableEntrySize());
+ outs() << "AUX " << Name.rtrim(StringRef("\0", 1)) << '\n';
+
+ SI = SI + Symbol->getNumberOfAuxSymbols();
+ break;
+ } else {
+ outs() << "AUX Unknown\n";
+ }
+ }
+ }
+}
diff --git a/contrib/llvm/tools/llvm-objdump/ELFDump.cpp b/contrib/llvm/tools/llvm-objdump/ELFDump.cpp
index 2d0d7d7..7b44e39 100644
--- a/contrib/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -24,10 +24,8 @@ using namespace llvm::object;
template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) {
typedef ELFFile<ELFT> ELFO;
outs() << "Program Header:\n";
- for (typename ELFO::Elf_Phdr_Iter pi = o->program_header_begin(),
- pe = o->program_header_end();
- pi != pe; ++pi) {
- switch (pi->p_type) {
+ for (const typename ELFO::Elf_Phdr &Phdr : o->program_headers()) {
+ switch (Phdr.p_type) {
case ELF::PT_LOAD:
outs() << " LOAD ";
break;
@@ -55,22 +53,16 @@ template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) {
const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " ";
- outs() << "off "
- << format(Fmt, (uint64_t)pi->p_offset)
- << "vaddr "
- << format(Fmt, (uint64_t)pi->p_vaddr)
- << "paddr "
- << format(Fmt, (uint64_t)pi->p_paddr)
- << format("align 2**%u\n", countTrailingZeros<uint64_t>(pi->p_align))
- << " filesz "
- << format(Fmt, (uint64_t)pi->p_filesz)
- << "memsz "
- << format(Fmt, (uint64_t)pi->p_memsz)
- << "flags "
- << ((pi->p_flags & ELF::PF_R) ? "r" : "-")
- << ((pi->p_flags & ELF::PF_W) ? "w" : "-")
- << ((pi->p_flags & ELF::PF_X) ? "x" : "-")
- << "\n";
+ outs() << "off " << format(Fmt, (uint64_t)Phdr.p_offset) << "vaddr "
+ << format(Fmt, (uint64_t)Phdr.p_vaddr) << "paddr "
+ << format(Fmt, (uint64_t)Phdr.p_paddr)
+ << format("align 2**%u\n",
+ countTrailingZeros<uint64_t>(Phdr.p_align))
+ << " filesz " << format(Fmt, (uint64_t)Phdr.p_filesz)
+ << "memsz " << format(Fmt, (uint64_t)Phdr.p_memsz) << "flags "
+ << ((Phdr.p_flags & ELF::PF_R) ? "r" : "-")
+ << ((Phdr.p_flags & ELF::PF_W) ? "w" : "-")
+ << ((Phdr.p_flags & ELF::PF_X) ? "x" : "-") << "\n";
}
outs() << "\n";
}
diff --git a/contrib/llvm/tools/llvm-objdump/MachODump.cpp b/contrib/llvm/tools/llvm-objdump/MachODump.cpp
index 04c72f48..258c0b5 100644
--- a/contrib/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/MachODump.cpp
@@ -13,6 +13,7 @@
#include "llvm-objdump.h"
#include "llvm-c/Disassembler.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
@@ -97,11 +98,6 @@ cl::opt<bool>
cl::desc("Print the linker optimization hints for "
"Mach-O objects (requires -macho)"));
-cl::list<std::string>
- llvm::DumpSections("section",
- cl::desc("Prints the specified segment,section for "
- "Mach-O objects (requires -macho)"));
-
cl::opt<bool>
llvm::InfoPlist("info-plist",
cl::desc("Print the info plist section as strings for "
@@ -138,6 +134,7 @@ static cl::opt<bool> NoSymbolicOperands(
static cl::list<std::string>
ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
cl::ZeroOrMore);
+
bool ArchAll = false;
static std::string ThumbTripleName;
@@ -210,19 +207,19 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
case MachO::DICE_KIND_DATA:
if (Length >= 4) {
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 4), outs());
+ dumpBytes(makeArrayRef(bytes, 4), outs());
Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
outs() << "\t.long " << Value;
Size = 4;
} else if (Length >= 2) {
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs());
+ dumpBytes(makeArrayRef(bytes, 2), outs());
Value = bytes[1] << 8 | bytes[0];
outs() << "\t.short " << Value;
Size = 2;
} else {
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs());
+ dumpBytes(makeArrayRef(bytes, 2), outs());
Value = bytes[0];
outs() << "\t.byte " << Value;
Size = 1;
@@ -234,14 +231,14 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
break;
case MachO::DICE_KIND_JUMP_TABLE8:
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 1), outs());
+ dumpBytes(makeArrayRef(bytes, 1), outs());
Value = bytes[0];
outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
Size = 1;
break;
case MachO::DICE_KIND_JUMP_TABLE16:
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 2), outs());
+ dumpBytes(makeArrayRef(bytes, 2), outs());
Value = bytes[1] << 8 | bytes[0];
outs() << "\t.short " << format("%5u", Value & 0xffff)
<< "\t@ KIND_JUMP_TABLE16\n";
@@ -250,7 +247,7 @@ static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
case MachO::DICE_KIND_JUMP_TABLE32:
case MachO::DICE_KIND_ABS_JUMP_TABLE32:
if (!NoShowRawInsn)
- dumpBytes(ArrayRef<uint8_t>(bytes, 4), outs());
+ dumpBytes(makeArrayRef(bytes, 4), outs());
Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
outs() << "\t.long " << Value;
if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
@@ -670,13 +667,9 @@ static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
double d) {
outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
uint32_t Hi, Lo;
- if (O->isLittleEndian()) {
- Hi = l1;
- Lo = l0;
- } else {
- Hi = l0;
- Lo = l1;
- }
+ Hi = (O->isLittleEndian()) ? l1 : l0;
+ Lo = (O->isLittleEndian()) ? l0 : l1;
+
// Hi is the high word, so this is equivalent to if(isfinite(d))
if ((Hi & 0x7ff00000) != 0x7ff00000)
outs() << format(" (%.16e)\n", d);
@@ -921,10 +914,7 @@ static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
SymbolAddressMap *AddrMap,
bool verbose) {
uint32_t stride;
- if (O->is64Bit())
- stride = sizeof(uint64_t);
- else
- stride = sizeof(uint32_t);
+ stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
for (uint32_t i = 0; i < sect_size; i += stride) {
const char *SymbolName = nullptr;
if (O->is64Bit()) {
@@ -1006,8 +996,8 @@ static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
if (verbose)
CreateSymbolAddressMap(O, &AddrMap);
- for (unsigned i = 0; i < DumpSections.size(); ++i) {
- StringRef DumpSection = DumpSections[i];
+ for (unsigned i = 0; i < FilterSections.size(); ++i) {
+ StringRef DumpSection = FilterSections[i];
std::pair<StringRef, StringRef> DumpSegSectName;
DumpSegSectName = DumpSection.split(',');
StringRef DumpSegName, DumpSectName;
@@ -1171,7 +1161,7 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
// UniversalHeaders or ArchiveHeaders.
if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind ||
LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints ||
- DylibsUsed || DylibId || ObjcMetaData || (DumpSections.size() != 0)) {
+ DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) {
outs() << Filename;
if (!ArchiveMemberName.empty())
outs() << '(' << ArchiveMemberName << ')';
@@ -1194,7 +1184,7 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
PrintSectionHeaders(MachOOF);
if (SectionContents)
PrintSectionContents(MachOOF);
- if (DumpSections.size() != 0)
+ if (FilterSections.size() != 0)
DumpSectionContents(Filename, MachOOF, !NonVerbose);
if (InfoPlist)
DumpInfoPlistSectionContents(Filename, MachOOF);
@@ -1206,7 +1196,11 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
PrintSymbolTable(MachOOF);
if (UnwindInfo)
printMachOUnwindInfo(MachOOF);
- if (PrivateHeaders)
+ if (PrivateHeaders) {
+ printMachOFileHeader(MachOOF);
+ printMachOLoadCommands(MachOOF);
+ }
+ if (FirstPrivateHeader)
printMachOFileHeader(MachOOF);
if (ObjcMetaData)
printObjcMetaData(MachOOF, !NonVerbose);
@@ -1395,7 +1389,7 @@ static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
}
}
-static void printArchiveChild(Archive::Child &C, bool verbose,
+static void printArchiveChild(const Archive::Child &C, bool verbose,
bool print_offset) {
if (print_offset)
outs() << C.getChildOffset() << "\t";
@@ -1404,42 +1398,15 @@ static void printArchiveChild(Archive::Child &C, bool verbose,
// FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
// But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
outs() << "-";
- if (Mode & sys::fs::owner_read)
- outs() << "r";
- else
- outs() << "-";
- if (Mode & sys::fs::owner_write)
- outs() << "w";
- else
- outs() << "-";
- if (Mode & sys::fs::owner_exe)
- outs() << "x";
- else
- outs() << "-";
- if (Mode & sys::fs::group_read)
- outs() << "r";
- else
- outs() << "-";
- if (Mode & sys::fs::group_write)
- outs() << "w";
- else
- outs() << "-";
- if (Mode & sys::fs::group_exe)
- outs() << "x";
- else
- outs() << "-";
- if (Mode & sys::fs::others_read)
- outs() << "r";
- else
- outs() << "-";
- if (Mode & sys::fs::others_write)
- outs() << "w";
- else
- outs() << "-";
- if (Mode & sys::fs::others_exe)
- outs() << "x";
- else
- outs() << "-";
+ outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
+ outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
+ outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
+ outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
+ outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
+ outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
+ outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
+ outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
+ outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
} else {
outs() << format("0%o ", Mode);
}
@@ -1448,8 +1415,10 @@ static void printArchiveChild(Archive::Child &C, bool verbose,
outs() << format("%3d/", UID);
unsigned GID = C.getGID();
outs() << format("%-3d ", GID);
- uint64_t Size = C.getRawSize();
- outs() << format("%5" PRId64, Size) << " ";
+ ErrorOr<uint64_t> Size = C.getRawSize();
+ if (std::error_code EC = Size.getError())
+ report_fatal_error(EC.message());
+ outs() << format("%5" PRId64, Size.get()) << " ";
StringRef RawLastModified = C.getRawLastModified();
if (verbose) {
@@ -1483,14 +1452,11 @@ static void printArchiveChild(Archive::Child &C, bool verbose,
}
static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) {
- if (A->hasSymbolTable()) {
- Archive::child_iterator S = A->getSymbolTableChild();
- Archive::Child C = *S;
- printArchiveChild(C, verbose, print_offset);
- }
- for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E;
- ++I) {
- Archive::Child C = *I;
+ for (Archive::child_iterator I = A->child_begin(false), E = A->child_end();
+ I != E; ++I) {
+ if (std::error_code EC = I->getError())
+ report_fatal_error(EC.message());
+ const Archive::Child &C = **I;
printArchiveChild(C, verbose, print_offset);
}
}
@@ -1515,10 +1481,8 @@ void llvm::ParseInputMachO(StringRef Filename) {
// Attempt to open the binary.
ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
- if (std::error_code EC = BinaryOrErr.getError()) {
- errs() << "llvm-objdump: '" << Filename << "': " << EC.message() << ".\n";
- return;
- }
+ if (std::error_code EC = BinaryOrErr.getError())
+ report_error(Filename, EC);
Binary &Bin = *BinaryOrErr.get().getBinary();
if (Archive *A = dyn_cast<Archive>(&Bin)) {
@@ -1527,7 +1491,10 @@ void llvm::ParseInputMachO(StringRef Filename) {
printArchiveHeaders(A, !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator I = A->child_begin(), E = A->child_end();
I != E; ++I) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = I->getAsBinary();
+ if (std::error_code EC = I->getError())
+ report_error(Filename, EC);
+ auto &C = I->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
@@ -1575,7 +1542,10 @@ void llvm::ParseInputMachO(StringRef Filename) {
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary();
+ if (std::error_code EC = AI->getError())
+ report_error(Filename, EC);
+ auto &C = AI->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O =
@@ -1617,7 +1587,10 @@ void llvm::ParseInputMachO(StringRef Filename) {
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary();
+ if (std::error_code EC = AI->getError())
+ report_error(Filename, EC);
+ auto &C = AI->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O =
@@ -1653,7 +1626,10 @@ void llvm::ParseInputMachO(StringRef Filename) {
printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end();
AI != AE; ++AI) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary();
+ if (std::error_code EC = AI->getError())
+ report_error(Filename, EC);
+ auto &C = AI->get();
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (ChildOrErr.getError())
continue;
if (MachOObjectFile *O =
@@ -1675,9 +1651,9 @@ void llvm::ParseInputMachO(StringRef Filename) {
} else
errs() << "llvm-objdump: '" << Filename << "': "
<< "Object is not a Mach-O file type.\n";
- } else
- errs() << "llvm-objdump: '" << Filename << "': "
- << "Unrecognized file type.\n";
+ return;
+ }
+ llvm_unreachable("Input object can't be invalid at this point");
}
typedef std::pair<uint64_t, const char *> BindInfoEntry;
@@ -1698,6 +1674,7 @@ struct DisassembleInfo {
uint64_t adrp_addr;
uint32_t adrp_inst;
BindTable *bindtable;
+ uint32_t depth;
};
// SymbolizerGetOpInfo() is the operand information call back function.
@@ -1735,8 +1712,15 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
if (Arch == Triple::x86) {
if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
return 0;
- // First search the section's relocation entries (if any) for an entry
- // for this section offset.
+ if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
+ // TODO:
+ // Search the external relocation entries of a fully linked image
+ // (if any) for an entry that matches this segment offset.
+ // uint32_t seg_offset = (Pc + Offset);
+ return 0;
+ }
+ // In MH_OBJECT filetypes search the section's relocation entries (if any)
+ // for an entry for this section offset.
uint32_t sect_addr = info->S.getAddress();
uint32_t sect_offset = (Pc + Offset) - sect_addr;
bool reloc_found = false;
@@ -1806,17 +1790,20 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
op_info->Value = offset;
return 1;
}
- // TODO:
- // Second search the external relocation entries of a fully linked image
- // (if any) for an entry that matches this segment offset.
- // uint32_t seg_offset = (Pc + Offset);
return 0;
}
if (Arch == Triple::x86_64) {
if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
return 0;
- // First search the section's relocation entries (if any) for an entry
- // for this section offset.
+ if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
+ // TODO:
+ // Search the external relocation entries of a fully linked image
+ // (if any) for an entry that matches this segment offset.
+ // uint64_t seg_offset = (Pc + Offset);
+ return 0;
+ }
+ // In MH_OBJECT filetypes search the section's relocation entries (if any)
+ // for an entry for this section offset.
uint64_t sect_addr = info->S.getAddress();
uint64_t sect_offset = (Pc + Offset) - sect_addr;
bool reloc_found = false;
@@ -1874,17 +1861,20 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
op_info->AddSymbol.Name = name;
return 1;
}
- // TODO:
- // Second search the external relocation entries of a fully linked image
- // (if any) for an entry that matches this segment offset.
- // uint64_t seg_offset = (Pc + Offset);
return 0;
}
if (Arch == Triple::arm) {
if (Offset != 0 || (Size != 4 && Size != 2))
return 0;
- // First search the section's relocation entries (if any) for an entry
- // for this section offset.
+ if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
+ // TODO:
+ // Search the external relocation entries of a fully linked image
+ // (if any) for an entry that matches this segment offset.
+ // uint32_t seg_offset = (Pc + Offset);
+ return 0;
+ }
+ // In MH_OBJECT filetypes search the section's relocation entries (if any)
+ // for an entry for this section offset.
uint32_t sect_addr = info->S.getAddress();
uint32_t sect_offset = (Pc + Offset) - sect_addr;
DataRefImpl Rel;
@@ -2016,8 +2006,15 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
if (Arch == Triple::aarch64) {
if (Offset != 0 || Size != 4)
return 0;
- // First search the section's relocation entries (if any) for an entry
- // for this section offset.
+ if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
+ // TODO:
+ // Search the external relocation entries of a fully linked image
+ // (if any) for an entry that matches this segment offset.
+ // uint64_t seg_offset = (Pc + Offset);
+ return 0;
+ }
+ // In MH_OBJECT filetypes search the section's relocation entries (if any)
+ // for an entry for this section offset.
uint64_t sect_addr = info->S.getAddress();
uint64_t sect_offset = (Pc + Offset) - sect_addr;
auto Reloc =
@@ -2370,6 +2367,8 @@ static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
+ if (SectSize == 0)
+ continue;
if (objc_only) {
StringRef SectName;
((*(info->Sections))[SectIdx]).getName(SectName);
@@ -3267,6 +3266,8 @@ walk_pointer_list_32(const char *listname, const SectionRef S,
}
static void print_layout_map(const char *layout_map, uint32_t left) {
+ if (layout_map == nullptr)
+ return;
outs() << " layout map: ";
do {
outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
@@ -3330,8 +3331,8 @@ static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
return;
memset(&m, '\0', sizeof(struct method64_t));
if (left < sizeof(struct method64_t)) {
- memcpy(&ml, r, left);
- outs() << indent << " (method_t entends past the end of the section)\n";
+ memcpy(&m, r, left);
+ outs() << indent << " (method_t extends past the end of the section)\n";
} else
memcpy(&m, r, sizeof(struct method64_t));
if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
@@ -4222,7 +4223,7 @@ static void print_objc_property_list32(uint32_t p,
}
}
-static void print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
+static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
bool &is_meta_class) {
struct class_ro64_t cro;
const char *r;
@@ -4233,7 +4234,7 @@ static void print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
r = get_pointer_64(p, offset, left, S, info);
if (r == nullptr || left < sizeof(struct class_ro64_t))
- return;
+ return false;
memset(&cro, '\0', sizeof(struct class_ro64_t));
if (left < sizeof(struct class_ro64_t)) {
memcpy(&cro, r, left);
@@ -4357,10 +4358,11 @@ static void print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
if (cro.baseProperties + n_value != 0)
print_objc_property_list64(cro.baseProperties + n_value, info);
- is_meta_class = (cro.flags & RO_META) ? true : false;
+ is_meta_class = (cro.flags & RO_META) != 0;
+ return true;
}
-static void print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
+static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
bool &is_meta_class) {
struct class_ro32_t cro;
const char *r;
@@ -4370,7 +4372,7 @@ static void print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
r = get_pointer_32(p, offset, left, S, info);
if (r == nullptr)
- return;
+ return false;
memset(&cro, '\0', sizeof(struct class_ro32_t));
if (left < sizeof(struct class_ro32_t)) {
memcpy(&cro, r, left);
@@ -4420,7 +4422,8 @@ static void print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
<< format("0x%" PRIx32, cro.baseProperties) << "\n";
if (cro.baseProperties != 0)
print_objc_property_list32(cro.baseProperties, info);
- is_meta_class = (cro.flags & RO_META) ? true : false;
+ is_meta_class = (cro.flags & RO_META) != 0;
+ return true;
}
static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
@@ -4490,11 +4493,16 @@ static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
outs() << " Swift class";
outs() << "\n";
bool is_meta_class;
- print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class);
+ if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
+ return;
- if (is_meta_class == false) {
- outs() << "Meta Class\n";
- print_class64_t(c.isa + isa_n_value, info);
+ if (!is_meta_class &&
+ c.isa + isa_n_value != p &&
+ c.isa + isa_n_value != 0 &&
+ info->depth < 100) {
+ info->depth++;
+ outs() << "Meta Class\n";
+ print_class64_t(c.isa + isa_n_value, info);
}
}
@@ -4555,9 +4563,10 @@ static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
outs() << " Swift class";
outs() << "\n";
bool is_meta_class;
- print_class_ro32_t(c.data & ~0x3, info, is_meta_class);
+ if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
+ return;
- if (is_meta_class == false) {
+ if (!is_meta_class) {
outs() << "Meta Class\n";
print_class32_t(c.isa, info);
}
@@ -4865,7 +4874,7 @@ static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
outs() << " name " << format("0x%" PRIx32, c.name);
name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
c.name);
- if (name != NULL)
+ if (name)
outs() << " " << name;
outs() << "\n";
@@ -5006,6 +5015,9 @@ static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
struct objc_image_info64 o;
const char *r;
+ if (S == SectionRef())
+ return;
+
StringRef SectName;
S.getName(SectName);
DataRefImpl Ref = S.getRawDataRefImpl();
@@ -5142,75 +5154,48 @@ static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
info.adrp_addr = 0;
info.adrp_inst = 0;
- const SectionRef CL = get_section(O, "__OBJC2", "__class_list");
- if (CL != SectionRef()) {
- info.S = CL;
- walk_pointer_list_64("class", CL, O, &info, print_class64_t);
- } else {
- const SectionRef CL = get_section(O, "__DATA", "__objc_classlist");
- info.S = CL;
- walk_pointer_list_64("class", CL, O, &info, print_class64_t);
- }
-
- const SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
- if (CR != SectionRef()) {
- info.S = CR;
- walk_pointer_list_64("class refs", CR, O, &info, nullptr);
- } else {
- const SectionRef CR = get_section(O, "__DATA", "__objc_classrefs");
- info.S = CR;
- walk_pointer_list_64("class refs", CR, O, &info, nullptr);
- }
-
- const SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
- if (SR != SectionRef()) {
- info.S = SR;
- walk_pointer_list_64("super refs", SR, O, &info, nullptr);
- } else {
- const SectionRef SR = get_section(O, "__DATA", "__objc_superrefs");
- info.S = SR;
- walk_pointer_list_64("super refs", SR, O, &info, nullptr);
- }
-
- const SectionRef CA = get_section(O, "__OBJC2", "__category_list");
- if (CA != SectionRef()) {
- info.S = CA;
- walk_pointer_list_64("category", CA, O, &info, print_category64_t);
- } else {
- const SectionRef CA = get_section(O, "__DATA", "__objc_catlist");
- info.S = CA;
- walk_pointer_list_64("category", CA, O, &info, print_category64_t);
- }
-
- const SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
- if (PL != SectionRef()) {
- info.S = PL;
- walk_pointer_list_64("protocol", PL, O, &info, nullptr);
- } else {
- const SectionRef PL = get_section(O, "__DATA", "__objc_protolist");
- info.S = PL;
- walk_pointer_list_64("protocol", PL, O, &info, nullptr);
- }
-
- const SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
- if (MR != SectionRef()) {
- info.S = MR;
- print_message_refs64(MR, &info);
- } else {
- const SectionRef MR = get_section(O, "__DATA", "__objc_msgrefs");
- info.S = MR;
- print_message_refs64(MR, &info);
- }
-
- const SectionRef II = get_section(O, "__OBJC2", "__image_info");
- if (II != SectionRef()) {
- info.S = II;
- print_image_info64(II, &info);
- } else {
- const SectionRef II = get_section(O, "__DATA", "__objc_imageinfo");
- info.S = II;
- print_image_info64(II, &info);
- }
+ info.depth = 0;
+ SectionRef CL = get_section(O, "__OBJC2", "__class_list");
+ if (CL == SectionRef())
+ CL = get_section(O, "__DATA", "__objc_classlist");
+ info.S = CL;
+ walk_pointer_list_64("class", CL, O, &info, print_class64_t);
+
+ SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
+ if (CR == SectionRef())
+ CR = get_section(O, "__DATA", "__objc_classrefs");
+ info.S = CR;
+ walk_pointer_list_64("class refs", CR, O, &info, nullptr);
+
+ SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
+ if (SR == SectionRef())
+ SR = get_section(O, "__DATA", "__objc_superrefs");
+ info.S = SR;
+ walk_pointer_list_64("super refs", SR, O, &info, nullptr);
+
+ SectionRef CA = get_section(O, "__OBJC2", "__category_list");
+ if (CA == SectionRef())
+ CA = get_section(O, "__DATA", "__objc_catlist");
+ info.S = CA;
+ walk_pointer_list_64("category", CA, O, &info, print_category64_t);
+
+ SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
+ if (PL == SectionRef())
+ PL = get_section(O, "__DATA", "__objc_protolist");
+ info.S = PL;
+ walk_pointer_list_64("protocol", PL, O, &info, nullptr);
+
+ SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
+ if (MR == SectionRef())
+ MR = get_section(O, "__DATA", "__objc_msgrefs");
+ info.S = MR;
+ print_message_refs64(MR, &info);
+
+ SectionRef II = get_section(O, "__OBJC2", "__image_info");
+ if (II == SectionRef())
+ II = get_section(O, "__DATA", "__objc_imageinfo");
+ info.S = II;
+ print_image_info64(II, &info);
if (info.bindtable != nullptr)
delete info.bindtable;
@@ -5559,7 +5544,7 @@ static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
// binary for the iOS simulator which is the second Objective-C
// ABI. In that case printObjc1_32bit_MetaData() will determine that
// and return false.
- if (printObjc1_32bit_MetaData(O, verbose) == false)
+ if (!printObjc1_32bit_MetaData(O, verbose))
printObjc2_32bit_MetaData(O, verbose);
}
}
@@ -5588,36 +5573,38 @@ static const char *GuessLiteralPointer(uint64_t ReferenceValue,
uint64_t *ReferenceType,
struct DisassembleInfo *info) {
// First see if there is an external relocation entry at the ReferencePC.
- uint64_t sect_addr = info->S.getAddress();
- uint64_t sect_offset = ReferencePC - sect_addr;
- bool reloc_found = false;
- DataRefImpl Rel;
- MachO::any_relocation_info RE;
- bool isExtern = false;
- SymbolRef Symbol;
- for (const RelocationRef &Reloc : info->S.relocations()) {
- uint64_t RelocOffset = Reloc.getOffset();
- if (RelocOffset == sect_offset) {
- Rel = Reloc.getRawDataRefImpl();
- RE = info->O->getRelocation(Rel);
- if (info->O->isRelocationScattered(RE))
- continue;
- isExtern = info->O->getPlainRelocationExternal(RE);
- if (isExtern) {
- symbol_iterator RelocSym = Reloc.getSymbol();
- Symbol = *RelocSym;
+ if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
+ uint64_t sect_addr = info->S.getAddress();
+ uint64_t sect_offset = ReferencePC - sect_addr;
+ bool reloc_found = false;
+ DataRefImpl Rel;
+ MachO::any_relocation_info RE;
+ bool isExtern = false;
+ SymbolRef Symbol;
+ for (const RelocationRef &Reloc : info->S.relocations()) {
+ uint64_t RelocOffset = Reloc.getOffset();
+ if (RelocOffset == sect_offset) {
+ Rel = Reloc.getRawDataRefImpl();
+ RE = info->O->getRelocation(Rel);
+ if (info->O->isRelocationScattered(RE))
+ continue;
+ isExtern = info->O->getPlainRelocationExternal(RE);
+ if (isExtern) {
+ symbol_iterator RelocSym = Reloc.getSymbol();
+ Symbol = *RelocSym;
+ }
+ reloc_found = true;
+ break;
}
- reloc_found = true;
- break;
}
- }
- // If there is an external relocation entry for a symbol in a section
- // then used that symbol's value for the value of the reference.
- if (reloc_found && isExtern) {
- if (info->O->getAnyRelocationPCRel(RE)) {
- unsigned Type = info->O->getAnyRelocationType(RE);
- if (Type == MachO::X86_64_RELOC_SIGNED) {
- ReferenceValue = Symbol.getValue();
+ // If there is an external relocation entry for a symbol in a section
+ // then used that symbol's value for the value of the reference.
+ if (reloc_found && isExtern) {
+ if (info->O->getAnyRelocationPCRel(RE)) {
+ unsigned Type = info->O->getAnyRelocationType(RE);
+ if (Type == MachO::X86_64_RELOC_SIGNED) {
+ ReferenceValue = Symbol.getValue();
+ }
}
}
}
@@ -5872,7 +5859,6 @@ static void emitComments(raw_svector_ostream &CommentStream,
formatted_raw_ostream &FormattedOS,
const MCAsmInfo &MAI) {
// Flush the stream before taking its content.
- CommentStream.flush();
StringRef Comments = CommentsToEmit.str();
// Get the default information for printing a comment.
const char *CommentBegin = MAI.getCommentString();
@@ -5893,7 +5879,6 @@ static void emitComments(raw_svector_ostream &CommentStream,
// Tell the comment stream that the vector changed underneath it.
CommentsToEmit.clear();
- CommentStream.resync();
}
static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
@@ -6065,7 +6050,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
diContext.reset(new DWARFContextInMemory(*DbgObj));
}
- if (DumpSections.size() == 0)
+ if (FilterSections.size() == 0)
outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
@@ -6087,19 +6072,6 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
bool symbolTableWorked = false;
- // Parse relocations.
- std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
- for (const RelocationRef &Reloc : Sections[SectIdx].relocations()) {
- uint64_t RelocOffset = Reloc.getOffset();
- uint64_t SectionAddress = Sections[SectIdx].getAddress();
- RelocOffset -= SectionAddress;
-
- symbol_iterator RelocSym = Reloc.getSymbol();
-
- Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
- }
- array_pod_sort(Relocs.begin(), Relocs.end());
-
// Create a map of symbol addresses to symbol names for use by
// the SymbolizerSymbolLookUp() routine.
SymbolAddressMap AddrMap;
@@ -6157,7 +6129,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
StringRef SymName = *SymNameOrErr;
SymbolRef::Type ST = Symbols[SymIdx].getType();
- if (ST != SymbolRef::ST_Function)
+ if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
continue;
// Make sure the symbol is defined in this section.
@@ -6251,10 +6223,9 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
DebugOut, Annotations);
if (gotInst) {
if (!NoShowRawInsn) {
- dumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size), outs());
+ dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
}
formatted_raw_ostream FormattedOS(outs());
- Annotations.flush();
StringRef AnnotationsStr = Annotations.str();
if (isThumb)
ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI);
@@ -6316,7 +6287,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
}
if (!NoShowRawInsn) {
outs() << "\t";
- dumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, InstSize), outs());
+ dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
}
IP->printInst(&Inst, outs(), "", *STI);
outs() << "\n";
@@ -6441,8 +6412,7 @@ static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
// Go back one so that SymbolAddress <= Addr.
--Sym;
- section_iterator SymSection = Obj->section_end();
- Sym->second.getSection(SymSection);
+ section_iterator SymSection = *Sym->second.getSection();
if (RelocSection == *SymSection) {
// There's a valid symbol in the same section before this reference.
ErrorOr<StringRef> NameOrErr = Sym->second.getName();
@@ -6780,13 +6750,268 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
}
}
+static unsigned getSizeForEncoding(bool is64Bit,
+ unsigned symbolEncoding) {
+ unsigned format = symbolEncoding & 0x0f;
+ switch (format) {
+ default: llvm_unreachable("Unknown Encoding");
+ case dwarf::DW_EH_PE_absptr:
+ case dwarf::DW_EH_PE_signed:
+ return is64Bit ? 8 : 4;
+ case dwarf::DW_EH_PE_udata2:
+ case dwarf::DW_EH_PE_sdata2:
+ return 2;
+ case dwarf::DW_EH_PE_udata4:
+ case dwarf::DW_EH_PE_sdata4:
+ return 4;
+ case dwarf::DW_EH_PE_udata8:
+ case dwarf::DW_EH_PE_sdata8:
+ return 8;
+ }
+}
+
+static uint64_t readPointer(const char *&Pos, bool is64Bit, unsigned Encoding) {
+ switch (getSizeForEncoding(is64Bit, Encoding)) {
+ case 2:
+ return readNext<uint16_t>(Pos);
+ break;
+ case 4:
+ return readNext<uint32_t>(Pos);
+ break;
+ case 8:
+ return readNext<uint64_t>(Pos);
+ break;
+ default:
+ llvm_unreachable("Illegal data size");
+ }
+}
+
+static void printMachOEHFrameSection(const MachOObjectFile *Obj,
+ std::map<uint64_t, SymbolRef> &Symbols,
+ const SectionRef &EHFrame) {
+ if (!Obj->isLittleEndian()) {
+ outs() << "warning: cannot handle big endian __eh_frame section\n";
+ return;
+ }
+
+ bool is64Bit = Obj->is64Bit();
+
+ outs() << "Contents of __eh_frame section:\n";
+
+ StringRef Contents;
+ EHFrame.getContents(Contents);
+
+ /// A few fields of the CIE are used when decoding the FDE's. This struct
+ /// will cache those fields we need so that we don't have to decode it
+ /// repeatedly for each FDE that references it.
+ struct DecodedCIE {
+ Optional<uint32_t> FDEPointerEncoding;
+ Optional<uint32_t> LSDAPointerEncoding;
+ bool hasAugmentationLength;
+ };
+
+ // Map from the start offset of the CIE to the cached data for that CIE.
+ DenseMap<uint64_t, DecodedCIE> CachedCIEs;
+
+ for (const char *Pos = Contents.data(), *End = Contents.end(); Pos != End; ) {
+
+ const char *EntryStartPos = Pos;
+
+ uint64_t Length = readNext<uint32_t>(Pos);
+ if (Length == 0xffffffff)
+ Length = readNext<uint64_t>(Pos);
+
+ // Save the Pos so that we can check the length we encoded against what we
+ // end up decoding.
+ const char *PosAfterLength = Pos;
+ const char *EntryEndPos = PosAfterLength + Length;
+
+ assert(EntryEndPos <= End &&
+ "__eh_frame entry length exceeds section size");
+
+ uint32_t ID = readNext<uint32_t>(Pos);
+ if (ID == 0) {
+ // This is a CIE.
+
+ uint32_t Version = readNext<uint8_t>(Pos);
+
+ // Parse a null terminated augmentation string
+ SmallString<8> AugmentationString;
+ for (uint8_t Char = readNext<uint8_t>(Pos); Char;
+ Char = readNext<uint8_t>(Pos))
+ AugmentationString.push_back(Char);
+
+ // Optionally parse the EH data if the augmentation string says it's there.
+ Optional<uint64_t> EHData;
+ if (StringRef(AugmentationString).count("eh"))
+ EHData = is64Bit ? readNext<uint64_t>(Pos) : readNext<uint32_t>(Pos);
+
+ unsigned ULEBByteCount;
+ uint64_t CodeAlignmentFactor = decodeULEB128((const uint8_t *)Pos,
+ &ULEBByteCount);
+ Pos += ULEBByteCount;
+
+ int64_t DataAlignmentFactor = decodeSLEB128((const uint8_t *)Pos,
+ &ULEBByteCount);
+ Pos += ULEBByteCount;
+
+ uint32_t ReturnAddressRegister = readNext<uint8_t>(Pos);
+
+ Optional<uint64_t> AugmentationLength;
+ Optional<uint32_t> LSDAPointerEncoding;
+ Optional<uint32_t> PersonalityEncoding;
+ Optional<uint64_t> Personality;
+ Optional<uint32_t> FDEPointerEncoding;
+ if (!AugmentationString.empty() && AugmentationString.front() == 'z') {
+ AugmentationLength = decodeULEB128((const uint8_t *)Pos,
+ &ULEBByteCount);
+ Pos += ULEBByteCount;
+
+ // Walk the augmentation string to get all the augmentation data.
+ for (unsigned i = 1, e = AugmentationString.size(); i != e; ++i) {
+ char Char = AugmentationString[i];
+ switch (Char) {
+ case 'e':
+ assert((i + 1) != e && AugmentationString[i + 1] == 'h' &&
+ "Expected 'eh' in augmentation string");
+ break;
+ case 'L':
+ assert(!LSDAPointerEncoding && "Duplicate LSDA encoding");
+ LSDAPointerEncoding = readNext<uint8_t>(Pos);
+ break;
+ case 'P': {
+ assert(!Personality && "Duplicate personality");
+ PersonalityEncoding = readNext<uint8_t>(Pos);
+ Personality = readPointer(Pos, is64Bit, *PersonalityEncoding);
+ break;
+ }
+ case 'R':
+ assert(!FDEPointerEncoding && "Duplicate FDE encoding");
+ FDEPointerEncoding = readNext<uint8_t>(Pos);
+ break;
+ case 'z':
+ llvm_unreachable("'z' must be first in the augmentation string");
+ }
+ }
+ }
+
+ outs() << "CIE:\n";
+ outs() << " Length: " << Length << "\n";
+ outs() << " CIE ID: " << ID << "\n";
+ outs() << " Version: " << Version << "\n";
+ outs() << " Augmentation String: " << AugmentationString << "\n";
+ if (EHData)
+ outs() << " EHData: " << *EHData << "\n";
+ outs() << " Code Alignment Factor: " << CodeAlignmentFactor << "\n";
+ outs() << " Data Alignment Factor: " << DataAlignmentFactor << "\n";
+ outs() << " Return Address Register: " << ReturnAddressRegister << "\n";
+ if (AugmentationLength) {
+ outs() << " Augmentation Data Length: " << *AugmentationLength << "\n";
+ if (LSDAPointerEncoding) {
+ outs() << " FDE LSDA Pointer Encoding: "
+ << *LSDAPointerEncoding << "\n";
+ }
+ if (Personality) {
+ outs() << " Personality Encoding: " << *PersonalityEncoding << "\n";
+ outs() << " Personality: " << *Personality << "\n";
+ }
+ if (FDEPointerEncoding) {
+ outs() << " FDE Address Pointer Encoding: "
+ << *FDEPointerEncoding << "\n";
+ }
+ }
+ // FIXME: Handle instructions.
+ // For now just emit some bytes
+ outs() << " Instructions:\n ";
+ dumpBytes(makeArrayRef((const uint8_t*)Pos, (const uint8_t*)EntryEndPos),
+ outs());
+ outs() << "\n";
+ Pos = EntryEndPos;
+
+ // Cache this entry.
+ uint64_t Offset = EntryStartPos - Contents.data();
+ CachedCIEs[Offset] = { FDEPointerEncoding, LSDAPointerEncoding,
+ AugmentationLength.hasValue() };
+ continue;
+ }
+
+ // This is an FDE.
+ // The CIE pointer for an FDE is the same location as the ID which we
+ // already read.
+ uint32_t CIEPointer = ID;
+
+ const char *CIEStart = PosAfterLength - CIEPointer;
+ assert(CIEStart >= Contents.data() &&
+ "FDE points to CIE before the __eh_frame start");
+
+ uint64_t CIEOffset = CIEStart - Contents.data();
+ auto CIEIt = CachedCIEs.find(CIEOffset);
+ if (CIEIt == CachedCIEs.end())
+ llvm_unreachable("Couldn't find CIE at offset in to __eh_frame section");
+
+ const DecodedCIE &CIE = CIEIt->getSecond();
+ assert(CIE.FDEPointerEncoding &&
+ "FDE references CIE which did not set pointer encoding");
+
+ uint64_t PCPointerSize = getSizeForEncoding(is64Bit,
+ *CIE.FDEPointerEncoding);
+
+ uint64_t PCBegin = readPointer(Pos, is64Bit, *CIE.FDEPointerEncoding);
+ uint64_t PCRange = readPointer(Pos, is64Bit, *CIE.FDEPointerEncoding);
+
+ Optional<uint64_t> AugmentationLength;
+ uint32_t LSDAPointerSize;
+ Optional<uint64_t> LSDAPointer;
+ if (CIE.hasAugmentationLength) {
+ unsigned ULEBByteCount;
+ AugmentationLength = decodeULEB128((const uint8_t *)Pos,
+ &ULEBByteCount);
+ Pos += ULEBByteCount;
+
+ // Decode the LSDA if the CIE augmentation string said we should.
+ if (CIE.LSDAPointerEncoding) {
+ LSDAPointerSize = getSizeForEncoding(is64Bit, *CIE.LSDAPointerEncoding);
+ LSDAPointer = readPointer(Pos, is64Bit, *CIE.LSDAPointerEncoding);
+ }
+ }
+
+ outs() << "FDE:\n";
+ outs() << " Length: " << Length << "\n";
+ outs() << " CIE Offset: " << CIEOffset << "\n";
+
+ if (PCPointerSize == 8) {
+ outs() << format(" PC Begin: %016" PRIx64, PCBegin) << "\n";
+ outs() << format(" PC Range: %016" PRIx64, PCRange) << "\n";
+ } else {
+ outs() << format(" PC Begin: %08" PRIx64, PCBegin) << "\n";
+ outs() << format(" PC Range: %08" PRIx64, PCRange) << "\n";
+ }
+ if (AugmentationLength) {
+ outs() << " Augmentation Data Length: " << *AugmentationLength << "\n";
+ if (LSDAPointer) {
+ if (LSDAPointerSize == 8)
+ outs() << format(" LSDA Pointer: %016\n" PRIx64, *LSDAPointer);
+ else
+ outs() << format(" LSDA Pointer: %08\n" PRIx64, *LSDAPointer);
+ }
+ }
+
+ // FIXME: Handle instructions.
+ // For now just emit some bytes
+ outs() << " Instructions:\n ";
+ dumpBytes(makeArrayRef((const uint8_t*)Pos, (const uint8_t*)EntryEndPos),
+ outs());
+ outs() << "\n";
+ Pos = EntryEndPos;
+ }
+}
+
void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
std::map<uint64_t, SymbolRef> Symbols;
for (const SymbolRef &SymRef : Obj->symbols()) {
// Discard any undefined or absolute symbols. They're not going to take part
// in the convenience lookup for unwind info and just take up resources.
- section_iterator Section = Obj->section_end();
- SymRef.getSection(Section);
+ section_iterator Section = *SymRef.getSection();
if (Section == Obj->section_end())
continue;
@@ -6802,7 +7027,7 @@ void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
else if (SectName == "__unwind_info")
printMachOUnwindInfoSection(Obj, Symbols, Section);
else if (SectName == "__eh_frame")
- outs() << "llvm-objdump: warning: unhandled __eh_frame section\n";
+ printMachOEHFrameSection(Obj, Symbols, Section);
}
}
@@ -7128,36 +7353,20 @@ static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
MachO::VM_PROT_EXECUTE)) != 0)
outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
else {
- if (maxprot & MachO::VM_PROT_READ)
- outs() << " maxprot r";
- else
- outs() << " maxprot -";
- if (maxprot & MachO::VM_PROT_WRITE)
- outs() << "w";
- else
- outs() << "-";
- if (maxprot & MachO::VM_PROT_EXECUTE)
- outs() << "x\n";
- else
- outs() << "-\n";
+ outs() << " maxprot ";
+ outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
+ outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
+ outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
}
if ((initprot &
~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
MachO::VM_PROT_EXECUTE)) != 0)
outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
else {
- if (initprot & MachO::VM_PROT_READ)
- outs() << " initprot r";
- else
- outs() << " initprot -";
- if (initprot & MachO::VM_PROT_WRITE)
- outs() << "w";
- else
- outs() << "-";
- if (initprot & MachO::VM_PROT_EXECUTE)
- outs() << "x\n";
- else
- outs() << "-\n";
+ outs() << " initprot ";
+ outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
+ outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
+ outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
}
} else {
outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
@@ -7611,26 +7820,11 @@ static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
else
outs() << "\n";
outs() << " uuid ";
- outs() << format("%02" PRIX32, uuid.uuid[0]);
- outs() << format("%02" PRIX32, uuid.uuid[1]);
- outs() << format("%02" PRIX32, uuid.uuid[2]);
- outs() << format("%02" PRIX32, uuid.uuid[3]);
- outs() << "-";
- outs() << format("%02" PRIX32, uuid.uuid[4]);
- outs() << format("%02" PRIX32, uuid.uuid[5]);
- outs() << "-";
- outs() << format("%02" PRIX32, uuid.uuid[6]);
- outs() << format("%02" PRIX32, uuid.uuid[7]);
- outs() << "-";
- outs() << format("%02" PRIX32, uuid.uuid[8]);
- outs() << format("%02" PRIX32, uuid.uuid[9]);
- outs() << "-";
- outs() << format("%02" PRIX32, uuid.uuid[10]);
- outs() << format("%02" PRIX32, uuid.uuid[11]);
- outs() << format("%02" PRIX32, uuid.uuid[12]);
- outs() << format("%02" PRIX32, uuid.uuid[13]);
- outs() << format("%02" PRIX32, uuid.uuid[14]);
- outs() << format("%02" PRIX32, uuid.uuid[15]);
+ for (int i = 0; i < 16; ++i) {
+ outs() << format("%02" PRIX32, uuid.uuid[i]);
+ if (i == 3 || i == 5 || i == 7 || i == 9)
+ outs() << "-";
+ }
outs() << "\n";
}
@@ -7650,30 +7844,47 @@ static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
}
static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
- if (vd.cmd == MachO::LC_VERSION_MIN_MACOSX)
- outs() << " cmd LC_VERSION_MIN_MACOSX\n";
- else if (vd.cmd == MachO::LC_VERSION_MIN_IPHONEOS)
- outs() << " cmd LC_VERSION_MIN_IPHONEOS\n";
- else
- outs() << " cmd " << vd.cmd << " (?)\n";
+ StringRef LoadCmdName;
+ switch (vd.cmd) {
+ case MachO::LC_VERSION_MIN_MACOSX:
+ LoadCmdName = "LC_VERSION_MIN_MACOSX";
+ break;
+ case MachO::LC_VERSION_MIN_IPHONEOS:
+ LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
+ break;
+ case MachO::LC_VERSION_MIN_TVOS:
+ LoadCmdName = "LC_VERSION_MIN_TVOS";
+ break;
+ case MachO::LC_VERSION_MIN_WATCHOS:
+ LoadCmdName = "LC_VERSION_MIN_WATCHOS";
+ break;
+ default:
+ llvm_unreachable("Unknown version min load command");
+ }
+
+ outs() << " cmd " << LoadCmdName << '\n';
outs() << " cmdsize " << vd.cmdsize;
if (vd.cmdsize != sizeof(struct MachO::version_min_command))
outs() << " Incorrect size\n";
else
outs() << "\n";
- outs() << " version " << ((vd.version >> 16) & 0xffff) << "."
- << ((vd.version >> 8) & 0xff);
- if ((vd.version & 0xff) != 0)
- outs() << "." << (vd.version & 0xff);
+ outs() << " version "
+ << MachOObjectFile::getVersionMinMajor(vd, false) << "."
+ << MachOObjectFile::getVersionMinMinor(vd, false);
+ uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
+ if (Update != 0)
+ outs() << "." << Update;
outs() << "\n";
if (vd.sdk == 0)
outs() << " sdk n/a";
else {
- outs() << " sdk " << ((vd.sdk >> 16) & 0xffff) << "."
- << ((vd.sdk >> 8) & 0xff);
+ outs() << " sdk "
+ << MachOObjectFile::getVersionMinMajor(vd, true) << "."
+ << MachOObjectFile::getVersionMinMinor(vd, true);
}
- if ((vd.sdk & 0xff) != 0)
- outs() << "." << (vd.sdk & 0xff);
+ Update = MachOObjectFile::getVersionMinUpdate(vd, true);
+ if (Update != 0)
+ outs() << "." << Update;
outs() << "\n";
}
@@ -8366,7 +8577,9 @@ static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
PrintRpathLoadCommand(Rpath, Command.Ptr);
} else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
- Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
+ Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
+ Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
+ Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
PrintVersionMinLoadCommand(Vd);
} else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
@@ -8436,31 +8649,40 @@ static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
}
}
-static void getAndPrintMachHeader(const MachOObjectFile *Obj,
- uint32_t &filetype, uint32_t &cputype,
- bool verbose) {
+static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
if (Obj->is64Bit()) {
MachO::mach_header_64 H_64;
H_64 = Obj->getHeader64();
PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
- filetype = H_64.filetype;
- cputype = H_64.cputype;
} else {
MachO::mach_header H;
H = Obj->getHeader();
PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
H.sizeofcmds, H.flags, verbose);
- filetype = H.filetype;
- cputype = H.cputype;
}
}
void llvm::printMachOFileHeader(const object::ObjectFile *Obj) {
const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
+ PrintMachHeader(file, !NonVerbose);
+}
+
+void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) {
+ const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
uint32_t filetype = 0;
uint32_t cputype = 0;
- getAndPrintMachHeader(file, filetype, cputype, !NonVerbose);
+ if (file->is64Bit()) {
+ MachO::mach_header_64 H_64;
+ H_64 = file->getHeader64();
+ filetype = H_64.filetype;
+ cputype = H_64.cputype;
+ } else {
+ MachO::mach_header H;
+ H = file->getHeader();
+ filetype = H.filetype;
+ cputype = H.cputype;
+ }
PrintLoadCommands(file, filetype, cputype, !NonVerbose);
}
@@ -8536,6 +8758,7 @@ public:
StringRef segmentName(uint32_t SegIndex);
StringRef sectionName(uint32_t SegIndex, uint64_t SegOffset);
uint64_t address(uint32_t SegIndex, uint64_t SegOffset);
+ bool isValidSegIndexAndOffset(uint32_t SegIndex, uint64_t SegOffset);
private:
struct SectionInfo {
@@ -8559,8 +8782,7 @@ SegInfo::SegInfo(const object::MachOObjectFile *Obj) {
uint64_t CurSegAddress;
for (const SectionRef &Section : Obj->sections()) {
SectionInfo Info;
- if (error(Section.getName(Info.SectionName)))
- return;
+ error(Section.getName(Info.SectionName));
Info.Address = Section.getAddress();
Info.Size = Section.getSize();
Info.SegmentName =
@@ -8585,6 +8807,20 @@ StringRef SegInfo::segmentName(uint32_t SegIndex) {
llvm_unreachable("invalid segIndex");
}
+bool SegInfo::isValidSegIndexAndOffset(uint32_t SegIndex,
+ uint64_t OffsetInSeg) {
+ for (const SectionInfo &SI : Sections) {
+ if (SI.SegmentIndex != SegIndex)
+ continue;
+ if (SI.OffsetInSegment > OffsetInSeg)
+ continue;
+ if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size))
+ continue;
+ return true;
+ }
+ return false;
+}
+
const SegInfo::SectionInfo &SegInfo::findSection(uint32_t SegIndex,
uint64_t OffsetInSeg) {
for (const SectionInfo &SI : Sections) {
@@ -8753,6 +8989,8 @@ static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable()) {
uint32_t SegIndex = Entry.segmentIndex();
uint64_t OffsetInSeg = Entry.segmentOffset();
+ if (!sectionTable.isValidSegIndexAndOffset(SegIndex, OffsetInSeg))
+ continue;
uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
const char *SymbolName = nullptr;
StringRef name = Entry.symbolName();
diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 275eb9c..d5ae5de 100644
--- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -73,6 +73,13 @@ Disassembled("d", cl::desc("Alias for --disassemble"),
cl::aliasopt(Disassemble));
cl::opt<bool>
+llvm::DisassembleAll("disassemble-all",
+ cl::desc("Display assembler mnemonics for the machine instructions"));
+static cl::alias
+DisassembleAlld("D", cl::desc("Alias for --disassemble-all"),
+ cl::aliasopt(DisassembleAll));
+
+cl::opt<bool>
llvm::Relocations("r", cl::desc("Display the relocation entries in the file"));
cl::opt<bool>
@@ -130,6 +137,13 @@ SectionHeadersShorter("h", cl::desc("Alias for --section-headers"),
cl::aliasopt(SectionHeaders));
cl::list<std::string>
+llvm::FilterSections("section", cl::desc("Operate on the specified sections only. "
+ "With -macho dump segment,section"));
+cl::alias
+static FilterSectionsj("j", cl::desc("Alias for --section"),
+ cl::aliasopt(llvm::FilterSections));
+
+cl::list<std::string>
llvm::MAttrs("mattr",
cl::CommaSeparated,
cl::desc("Target specific attributes"),
@@ -151,6 +165,11 @@ cl::opt<bool>
llvm::PrivateHeaders("private-headers",
cl::desc("Display format specific file headers"));
+cl::opt<bool>
+llvm::FirstPrivateHeader("private-header",
+ cl::desc("Display only the first format specific file "
+ "header"));
+
static cl::alias
PrivateHeadersShort("p", cl::desc("Alias for --private-headers"),
cl::aliasopt(PrivateHeaders));
@@ -163,22 +182,86 @@ cl::opt<bool> PrintFaultMaps("fault-map-section",
cl::desc("Display contents of faultmap section"));
static StringRef ToolName;
-static int ReturnValue = EXIT_SUCCESS;
-bool llvm::error(std::error_code EC) {
+namespace {
+typedef std::function<bool(llvm::object::SectionRef const &)> FilterPredicate;
+
+class SectionFilterIterator {
+public:
+ SectionFilterIterator(FilterPredicate P,
+ llvm::object::section_iterator const &I,
+ llvm::object::section_iterator const &E)
+ : Predicate(P), Iterator(I), End(E) {
+ ScanPredicate();
+ }
+ const llvm::object::SectionRef &operator*() const { return *Iterator; }
+ SectionFilterIterator &operator++() {
+ ++Iterator;
+ ScanPredicate();
+ return *this;
+ }
+ bool operator!=(SectionFilterIterator const &Other) const {
+ return Iterator != Other.Iterator;
+ }
+
+private:
+ void ScanPredicate() {
+ while (Iterator != End && !Predicate(*Iterator)) {
+ ++Iterator;
+ }
+ }
+ FilterPredicate Predicate;
+ llvm::object::section_iterator Iterator;
+ llvm::object::section_iterator End;
+};
+
+class SectionFilter {
+public:
+ SectionFilter(FilterPredicate P, llvm::object::ObjectFile const &O)
+ : Predicate(P), Object(O) {}
+ SectionFilterIterator begin() {
+ return SectionFilterIterator(Predicate, Object.section_begin(),
+ Object.section_end());
+ }
+ SectionFilterIterator end() {
+ return SectionFilterIterator(Predicate, Object.section_end(),
+ Object.section_end());
+ }
+
+private:
+ FilterPredicate Predicate;
+ llvm::object::ObjectFile const &Object;
+};
+SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O) {
+ return SectionFilter([](llvm::object::SectionRef const &S) {
+ if(FilterSections.empty())
+ return true;
+ llvm::StringRef String;
+ std::error_code error = S.getName(String);
+ if (error)
+ return false;
+ return std::find(FilterSections.begin(),
+ FilterSections.end(),
+ String) != FilterSections.end();
+ },
+ O);
+}
+}
+
+void llvm::error(std::error_code EC) {
if (!EC)
- return false;
+ return;
- outs() << ToolName << ": error reading file: " << EC.message() << ".\n";
- outs().flush();
- ReturnValue = EXIT_FAILURE;
- return true;
+ errs() << ToolName << ": error reading file: " << EC.message() << ".\n";
+ errs().flush();
+ exit(1);
}
-static void report_error(StringRef File, std::error_code EC) {
+LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File,
+ std::error_code EC) {
assert(EC);
errs() << ToolName << ": '" << File << "': " << EC.message() << ".\n";
- ReturnValue = EXIT_FAILURE;
+ exit(1);
}
static const Target *getTarget(const ObjectFile *Obj = nullptr) {
@@ -205,10 +288,8 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) {
std::string Error;
const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,
Error);
- if (!TheTarget) {
- errs() << ToolName << ": " << Error;
- return nullptr;
- }
+ if (!TheTarget)
+ report_fatal_error("can't find target: " + Error);
// Update the triple name and return the found target.
TripleName = TheTriple.getTriple();
@@ -301,11 +382,12 @@ PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {
template <class ELFT>
static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
- DataRefImpl Rel,
+ const RelocationRef &RelRef,
SmallVectorImpl<char> &Result) {
+ DataRefImpl Rel = RelRef.getRawDataRefImpl();
+
typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
- typedef typename ELFObjectFile<ELFT>::Elf_Rel Elf_Rel;
typedef typename ELFObjectFile<ELFT>::Elf_Rela Elf_Rela;
const ELFFile<ELFT> &EF = *Obj->getELFFile();
@@ -327,36 +409,31 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
if (std::error_code EC = StrTabOrErr.getError())
return EC;
StringRef StrTab = *StrTabOrErr;
- uint8_t type;
+ uint8_t type = RelRef.getType();
StringRef res;
int64_t addend = 0;
- uint16_t symbol_index = 0;
switch (Sec->sh_type) {
default:
return object_error::parse_failed;
case ELF::SHT_REL: {
- const Elf_Rel *ERel = Obj->getRel(Rel);
- type = ERel->getType(EF.isMips64EL());
- symbol_index = ERel->getSymbol(EF.isMips64EL());
// TODO: Read implicit addend from section data.
break;
}
case ELF::SHT_RELA: {
const Elf_Rela *ERela = Obj->getRela(Rel);
- type = ERela->getType(EF.isMips64EL());
- symbol_index = ERela->getSymbol(EF.isMips64EL());
addend = ERela->r_addend;
break;
}
}
- const Elf_Sym *symb =
- EF.template getEntry<Elf_Sym>(Sec->sh_link, symbol_index);
+ symbol_iterator SI = RelRef.getSymbol();
+ const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl());
StringRef Target;
- ErrorOr<const Elf_Shdr *> SymSec = EF.getSection(symb);
- if (std::error_code EC = SymSec.getError())
- return EC;
if (symb->getType() == ELF::STT_SECTION) {
- ErrorOr<StringRef> SecName = EF.getSectionName(*SymSec);
+ ErrorOr<section_iterator> SymSI = SI->getSection();
+ if (std::error_code EC = SymSI.getError())
+ return EC;
+ const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl());
+ ErrorOr<StringRef> SecName = EF.getSectionName(SymSec);
if (std::error_code EC = SecName.getError())
return EC;
Target = *SecName;
@@ -404,11 +481,29 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
break;
}
case ELF::EM_386:
+ case ELF::EM_IAMCU:
case ELF::EM_ARM:
case ELF::EM_HEXAGON:
case ELF::EM_MIPS:
res = Target;
break;
+ case ELF::EM_WEBASSEMBLY:
+ switch (type) {
+ case ELF::R_WEBASSEMBLY_DATA: {
+ std::string fmtbuf;
+ raw_string_ostream fmt(fmtbuf);
+ fmt << Target << (addend < 0 ? "" : "+") << addend;
+ fmt.flush();
+ Result.append(fmtbuf.begin(), fmtbuf.end());
+ break;
+ }
+ case ELF::R_WEBASSEMBLY_FUNCTION:
+ res = Target;
+ break;
+ default:
+ res = "Unknown";
+ }
+ break;
default:
res = "Unknown";
}
@@ -418,9 +513,8 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
}
static std::error_code getRelocationValueString(const ELFObjectFileBase *Obj,
- const RelocationRef &RelRef,
+ const RelocationRef &Rel,
SmallVectorImpl<char> &Result) {
- DataRefImpl Rel = RelRef.getRawDataRefImpl();
if (auto *ELF32LE = dyn_cast<ELF32LEObjectFile>(Obj))
return getRelocationValueString(ELF32LE, Rel, Result);
if (auto *ELF64LE = dyn_cast<ELF64LEObjectFile>(Obj))
@@ -471,7 +565,7 @@ static void printRelocationTargetName(const MachOObjectFile *O,
// If we couldn't find a symbol that this relocation refers to, try
// to find a section beginning instead.
- for (const SectionRef &Section : O->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*O)) {
std::error_code ec;
StringRef Name;
@@ -496,8 +590,8 @@ static void printRelocationTargetName(const MachOObjectFile *O,
symbol_iterator SI = O->symbol_begin();
advance(SI, Val);
ErrorOr<StringRef> SOrErr = SI->getName();
- if (!error(SOrErr.getError()))
- S = *SOrErr;
+ error(SOrErr.getError());
+ S = *SOrErr;
} else {
section_iterator SI = O->section_begin();
// Adjust for the fact that sections are 1-indexed.
@@ -732,10 +826,6 @@ static bool getHidden(RelocationRef RelRef) {
static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
const Target *TheTarget = getTarget(Obj);
- // getTarget() will have already issued a diagnostic if necessary, so
- // just bail here if it failed.
- if (!TheTarget)
- return;
// Package up features to be passed to target/subtarget
std::string FeaturesStr;
@@ -748,42 +838,28 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
std::unique_ptr<const MCRegisterInfo> MRI(
TheTarget->createMCRegInfo(TripleName));
- if (!MRI) {
- errs() << "error: no register info for target " << TripleName << "\n";
- return;
- }
+ if (!MRI)
+ report_fatal_error("error: no register info for target " + TripleName);
// Set up disassembler.
std::unique_ptr<const MCAsmInfo> AsmInfo(
TheTarget->createMCAsmInfo(*MRI, TripleName));
- if (!AsmInfo) {
- errs() << "error: no assembly info for target " << TripleName << "\n";
- return;
- }
-
+ if (!AsmInfo)
+ report_fatal_error("error: no assembly info for target " + TripleName);
std::unique_ptr<const MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
- if (!STI) {
- errs() << "error: no subtarget info for target " << TripleName << "\n";
- return;
- }
-
+ if (!STI)
+ report_fatal_error("error: no subtarget info for target " + TripleName);
std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
- if (!MII) {
- errs() << "error: no instruction info for target " << TripleName << "\n";
- return;
- }
-
+ if (!MII)
+ report_fatal_error("error: no instruction info for target " + TripleName);
std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo);
MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get());
std::unique_ptr<MCDisassembler> DisAsm(
TheTarget->createMCDisassembler(*STI, Ctx));
-
- if (!DisAsm) {
- errs() << "error: no disassembler for target " << TripleName << "\n";
- return;
- }
+ if (!DisAsm)
+ report_fatal_error("error: no disassembler for target " + TripleName);
std::unique_ptr<const MCInstrAnalysis> MIA(
TheTarget->createMCInstrAnalysis(MII.get()));
@@ -791,11 +867,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI));
- if (!IP) {
- errs() << "error: no instruction printer for target " << TripleName
- << '\n';
- return;
- }
+ if (!IP)
+ report_fatal_error("error: no instruction printer for target " +
+ TripleName);
IP->setPrintImmHex(PrintImmHex);
PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName));
@@ -806,38 +880,75 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// in RelocSecs contain the relocations for section S.
std::error_code EC;
std::map<SectionRef, SmallVector<SectionRef, 1>> SectionRelocMap;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
section_iterator Sec2 = Section.getRelocatedSection();
if (Sec2 != Obj->section_end())
SectionRelocMap[*Sec2].push_back(Section);
}
// Create a mapping from virtual address to symbol name. This is used to
- // pretty print the target of a call.
- std::vector<std::pair<uint64_t, StringRef>> AllSymbols;
- if (MIA) {
- for (const SymbolRef &Symbol : Obj->symbols()) {
- if (Symbol.getType() != SymbolRef::ST_Function)
- continue;
+ // pretty print the symbols while disassembling.
+ typedef std::vector<std::pair<uint64_t, StringRef>> SectionSymbolsTy;
+ std::map<SectionRef, SectionSymbolsTy> AllSymbols;
+ for (const SymbolRef &Symbol : Obj->symbols()) {
+ ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
+ error(AddressOrErr.getError());
+ uint64_t Address = *AddressOrErr;
+
+ ErrorOr<StringRef> Name = Symbol.getName();
+ error(Name.getError());
+ if (Name->empty())
+ continue;
- ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
- if (error(AddressOrErr.getError()))
- break;
- uint64_t Address = *AddressOrErr;
+ ErrorOr<section_iterator> SectionOrErr = Symbol.getSection();
+ error(SectionOrErr.getError());
+ section_iterator SecI = *SectionOrErr;
+ if (SecI == Obj->section_end())
+ continue;
- ErrorOr<StringRef> Name = Symbol.getName();
- if (error(Name.getError()))
- break;
- if (Name->empty())
+ AllSymbols[*SecI].emplace_back(Address, *Name);
+ }
+
+ // Create a mapping from virtual address to section.
+ std::vector<std::pair<uint64_t, SectionRef>> SectionAddresses;
+ for (SectionRef Sec : Obj->sections())
+ SectionAddresses.emplace_back(Sec.getAddress(), Sec);
+ array_pod_sort(SectionAddresses.begin(), SectionAddresses.end());
+
+ // Linked executables (.exe and .dll files) typically don't include a real
+ // symbol table but they might contain an export table.
+ if (const auto *COFFObj = dyn_cast<COFFObjectFile>(Obj)) {
+ for (const auto &ExportEntry : COFFObj->export_directories()) {
+ StringRef Name;
+ error(ExportEntry.getSymbolName(Name));
+ if (Name.empty())
continue;
- AllSymbols.push_back(std::make_pair(Address, *Name));
- }
+ uint32_t RVA;
+ error(ExportEntry.getExportRVA(RVA));
+
+ uint64_t VA = COFFObj->getImageBase() + RVA;
+ auto Sec = std::upper_bound(
+ SectionAddresses.begin(), SectionAddresses.end(), VA,
+ [](uint64_t LHS, const std::pair<uint64_t, SectionRef> &RHS) {
+ return LHS < RHS.first;
+ });
+ if (Sec != SectionAddresses.begin())
+ --Sec;
+ else
+ Sec = SectionAddresses.end();
- array_pod_sort(AllSymbols.begin(), AllSymbols.end());
+ if (Sec != SectionAddresses.end())
+ AllSymbols[Sec->second].emplace_back(VA, Name);
+ }
}
- for (const SectionRef &Section : Obj->sections()) {
- if (!Section.isText() || Section.isVirtual())
+ // Sort all the symbols, this allows us to use a simple binary search to find
+ // a symbol near an address.
+ for (std::pair<const SectionRef, SectionSymbolsTy> &SecSyms : AllSymbols)
+ array_pod_sort(SecSyms.second.begin(), SecSyms.second.end());
+
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
+ if (!DisassembleAll && (!Section.isText() || Section.isVirtual()))
continue;
uint64_t SectionAddr = Section.getAddress();
@@ -845,27 +956,23 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (!SectSize)
continue;
- // Make a list of all the symbols in this section.
- std::vector<std::pair<uint64_t, StringRef>> Symbols;
- for (const SymbolRef &Symbol : Obj->symbols()) {
- if (Section.containsSymbol(Symbol)) {
- ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
- if (error(AddressOrErr.getError()))
- break;
- uint64_t Address = *AddressOrErr;
- Address -= SectionAddr;
- if (Address >= SectSize)
- continue;
-
- ErrorOr<StringRef> Name = Symbol.getName();
- if (error(Name.getError()))
- break;
- Symbols.push_back(std::make_pair(Address, *Name));
+ // Get the list of all the symbols in this section.
+ SectionSymbolsTy &Symbols = AllSymbols[Section];
+ std::vector<uint64_t> DataMappingSymsAddr;
+ std::vector<uint64_t> TextMappingSymsAddr;
+ if (Obj->isELF() && Obj->getArch() == Triple::aarch64) {
+ for (const auto &Symb : Symbols) {
+ uint64_t Address = Symb.first;
+ StringRef Name = Symb.second;
+ if (Name.startswith("$d"))
+ DataMappingSymsAddr.push_back(Address - SectionAddr);
+ if (Name.startswith("$x"))
+ TextMappingSymsAddr.push_back(Address - SectionAddr);
}
}
- // Sort the symbols by address, just in case they didn't come in that way.
- array_pod_sort(Symbols.begin(), Symbols.end());
+ std::sort(DataMappingSymsAddr.begin(), DataMappingSymsAddr.end());
+ std::sort(TextMappingSymsAddr.begin(), TextMappingSymsAddr.end());
// Make a list of all the relocations for this section.
std::vector<RelocationRef> Rels;
@@ -886,8 +993,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
SegmentName = MachO->getSectionFinalSegmentName(DR);
}
StringRef name;
- if (error(Section.getName(name)))
- break;
+ error(Section.getName(name));
outs() << "Disassembly of section ";
if (!SegmentName.empty())
outs() << SegmentName << ",";
@@ -895,14 +1001,13 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// If the section has no symbol at the start, just insert a dummy one.
if (Symbols.empty() || Symbols[0].first != 0)
- Symbols.insert(Symbols.begin(), std::make_pair(0, name));
+ Symbols.insert(Symbols.begin(), std::make_pair(SectionAddr, name));
SmallString<40> Comments;
raw_svector_ostream CommentStream(Comments);
StringRef BytesStr;
- if (error(Section.getContents(BytesStr)))
- break;
+ error(Section.getContents(BytesStr));
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
BytesStr.size());
@@ -914,11 +1019,16 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// Disassemble symbol by symbol.
for (unsigned si = 0, se = Symbols.size(); si != se; ++si) {
- uint64_t Start = Symbols[si].first;
- // The end is either the section end or the beginning of the next symbol.
- uint64_t End = (si == se - 1) ? SectSize : Symbols[si + 1].first;
+ uint64_t Start = Symbols[si].first - SectionAddr;
+ // The end is either the section end or the beginning of the next
+ // symbol.
+ uint64_t End =
+ (si == se - 1) ? SectSize : Symbols[si + 1].first - SectionAddr;
+ // Don't try to disassemble beyond the end of section contents.
+ if (End > SectSize)
+ End = SectSize;
// If this symbol has the same address as the next symbol, then skip it.
- if (Start == End)
+ if (Start >= End)
continue;
outs() << '\n' << Symbols[si].second << ":\n";
@@ -932,6 +1042,45 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
for (Index = Start; Index < End; Index += Size) {
MCInst Inst;
+ // AArch64 ELF binaries can interleave data and text in the
+ // same section. We rely on the markers introduced to
+ // understand what we need to dump.
+ if (Obj->isELF() && Obj->getArch() == Triple::aarch64) {
+ uint64_t Stride = 0;
+
+ auto DAI = std::lower_bound(DataMappingSymsAddr.begin(),
+ DataMappingSymsAddr.end(), Index);
+ if (DAI != DataMappingSymsAddr.end() && *DAI == Index) {
+ // Switch to data.
+ while (Index < End) {
+ outs() << format("%8" PRIx64 ":", SectionAddr + Index);
+ outs() << "\t";
+ if (Index + 4 <= End) {
+ Stride = 4;
+ dumpBytes(Bytes.slice(Index, 4), outs());
+ outs() << "\t.word";
+ } else if (Index + 2 <= End) {
+ Stride = 2;
+ dumpBytes(Bytes.slice(Index, 2), outs());
+ outs() << "\t.short";
+ } else {
+ Stride = 1;
+ dumpBytes(Bytes.slice(Index, 1), outs());
+ outs() << "\t.byte";
+ }
+ Index += Stride;
+ outs() << "\n";
+ auto TAI = std::lower_bound(TextMappingSymsAddr.begin(),
+ TextMappingSymsAddr.end(), Index);
+ if (TAI != TextMappingSymsAddr.end() && *TAI == Index)
+ break;
+ }
+ }
+ }
+
+ if (Index >= End)
+ break;
+
if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
SectionAddr + Index, DebugOut,
CommentStream)) {
@@ -940,26 +1089,55 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
SectionAddr + Index, outs(), "", *STI);
outs() << CommentStream.str();
Comments.clear();
+
+ // Try to resolve the target of a call, tail call, etc. to a specific
+ // symbol.
if (MIA && (MIA->isCall(Inst) || MIA->isUnconditionalBranch(Inst) ||
MIA->isConditionalBranch(Inst))) {
uint64_t Target;
if (MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target)) {
- auto TargetSym = std::upper_bound(
- AllSymbols.begin(), AllSymbols.end(), Target,
- [](uint64_t LHS, const std::pair<uint64_t, StringRef> &RHS) {
- return LHS < RHS.first;
- });
- if (TargetSym != AllSymbols.begin())
- --TargetSym;
- else
- TargetSym = AllSymbols.end();
-
- if (TargetSym != AllSymbols.end()) {
- outs() << " <" << TargetSym->second;
- uint64_t Disp = Target - TargetSym->first;
- if (Disp)
- outs() << '+' << utohexstr(Disp);
- outs() << '>';
+ // In a relocatable object, the target's section must reside in
+ // the same section as the call instruction or it is accessed
+ // through a relocation.
+ //
+ // In a non-relocatable object, the target may be in any section.
+ //
+ // N.B. We don't walk the relocations in the relocatable case yet.
+ auto *TargetSectionSymbols = &Symbols;
+ if (!Obj->isRelocatableObject()) {
+ auto SectionAddress = std::upper_bound(
+ SectionAddresses.begin(), SectionAddresses.end(), Target,
+ [](uint64_t LHS,
+ const std::pair<uint64_t, SectionRef> &RHS) {
+ return LHS < RHS.first;
+ });
+ if (SectionAddress != SectionAddresses.begin()) {
+ --SectionAddress;
+ TargetSectionSymbols = &AllSymbols[SectionAddress->second];
+ } else {
+ TargetSectionSymbols = nullptr;
+ }
+ }
+
+ // Find the first symbol in the section whose offset is less than
+ // or equal to the target.
+ if (TargetSectionSymbols) {
+ auto TargetSym = std::upper_bound(
+ TargetSectionSymbols->begin(), TargetSectionSymbols->end(),
+ Target, [](uint64_t LHS,
+ const std::pair<uint64_t, StringRef> &RHS) {
+ return LHS < RHS.first;
+ });
+ if (TargetSym != TargetSectionSymbols->begin()) {
+ --TargetSym;
+ uint64_t TargetAddress = std::get<0>(*TargetSym);
+ StringRef TargetName = std::get<1>(*TargetSym);
+ outs() << " <" << TargetName;
+ uint64_t Disp = Target - TargetAddress;
+ if (Disp)
+ outs() << '+' << utohexstr(Disp);
+ outs() << '>';
+ }
}
}
}
@@ -983,8 +1161,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
// Stop when rel_cur's address is past the current instruction.
if (addr >= Index + Size) break;
rel_cur->getTypeName(name);
- if (error(getRelocationValueString(*rel_cur, val)))
- goto skip_print_rel;
+ error(getRelocationValueString(*rel_cur, val));
outs() << format(Fmt.data(), SectionAddr + addr) << name
<< "\t" << val << "\n";
@@ -1004,12 +1181,11 @@ void llvm::PrintRelocations(const ObjectFile *Obj) {
if (!Obj->isRelocatableObject())
return;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
if (Section.relocation_begin() == Section.relocation_end())
continue;
StringRef secname;
- if (error(Section.getName(secname)))
- continue;
+ error(Section.getName(secname));
outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n";
for (const RelocationRef &Reloc : Section.relocations()) {
bool hidden = getHidden(Reloc);
@@ -1019,8 +1195,7 @@ void llvm::PrintRelocations(const ObjectFile *Obj) {
if (hidden)
continue;
Reloc.getTypeName(relocname);
- if (error(getRelocationValueString(Reloc, valuestr)))
- continue;
+ error(getRelocationValueString(Reloc, valuestr));
outs() << format(Fmt.data(), address) << " " << relocname << " "
<< valuestr << "\n";
}
@@ -1032,10 +1207,9 @@ void llvm::PrintSectionHeaders(const ObjectFile *Obj) {
outs() << "Sections:\n"
"Idx Name Size Address Type\n";
unsigned i = 0;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
StringRef Name;
- if (error(Section.getName(Name)))
- return;
+ error(Section.getName(Name));
uint64_t Address = Section.getAddress();
uint64_t Size = Section.getSize();
bool Text = Section.isText();
@@ -1051,11 +1225,10 @@ void llvm::PrintSectionHeaders(const ObjectFile *Obj) {
void llvm::PrintSectionContents(const ObjectFile *Obj) {
std::error_code EC;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
StringRef Name;
StringRef Contents;
- if (error(Section.getName(Name)))
- continue;
+ error(Section.getName(Name));
uint64_t BaseAddr = Section.getAddress();
uint64_t Size = Section.getSize();
if (!Size)
@@ -1069,8 +1242,7 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) {
continue;
}
- if (error(Section.getContents(Contents)))
- continue;
+ error(Section.getContents(Contents));
// Dump out the content as hex and printable ascii characters.
for (std::size_t addr = 0, end = Contents.size(); addr < end; addr += 16) {
@@ -1098,84 +1270,28 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) {
}
}
-static void PrintCOFFSymbolTable(const COFFObjectFile *coff) {
- for (unsigned SI = 0, SE = coff->getNumberOfSymbols(); SI != SE; ++SI) {
- ErrorOr<COFFSymbolRef> Symbol = coff->getSymbol(SI);
- StringRef Name;
- if (error(Symbol.getError()))
- return;
-
- if (error(coff->getSymbolName(*Symbol, Name)))
- return;
-
- outs() << "[" << format("%2d", SI) << "]"
- << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")"
- << "(fl 0x00)" // Flag bits, which COFF doesn't have.
- << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")"
- << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) << ") "
- << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") "
- << "0x" << format("%08x", unsigned(Symbol->getValue())) << " "
- << Name << "\n";
-
- for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) {
- if (Symbol->isSectionDefinition()) {
- const coff_aux_section_definition *asd;
- if (error(coff->getAuxSymbol<coff_aux_section_definition>(SI + 1, asd)))
- return;
-
- int32_t AuxNumber = asd->getNumber(Symbol->isBigObj());
-
- outs() << "AUX "
- << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x "
- , unsigned(asd->Length)
- , unsigned(asd->NumberOfRelocations)
- , unsigned(asd->NumberOfLinenumbers)
- , unsigned(asd->CheckSum))
- << format("assoc %d comdat %d\n"
- , unsigned(AuxNumber)
- , unsigned(asd->Selection));
- } else if (Symbol->isFileRecord()) {
- const char *FileName;
- if (error(coff->getAuxSymbol<char>(SI + 1, FileName)))
- return;
-
- StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() *
- coff->getSymbolTableEntrySize());
- outs() << "AUX " << Name.rtrim(StringRef("\0", 1)) << '\n';
-
- SI = SI + Symbol->getNumberOfAuxSymbols();
- break;
- } else {
- outs() << "AUX Unknown\n";
- }
- }
- }
-}
-
void llvm::PrintSymbolTable(const ObjectFile *o) {
outs() << "SYMBOL TABLE:\n";
if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) {
- PrintCOFFSymbolTable(coff);
+ printCOFFSymbolTable(coff);
return;
}
for (const SymbolRef &Symbol : o->symbols()) {
ErrorOr<uint64_t> AddressOrError = Symbol.getAddress();
- if (error(AddressOrError.getError()))
- continue;
+ error(AddressOrError.getError());
uint64_t Address = *AddressOrError;
SymbolRef::Type Type = Symbol.getType();
uint32_t Flags = Symbol.getFlags();
- section_iterator Section = o->section_end();
- if (error(Symbol.getSection(Section)))
- continue;
+ ErrorOr<section_iterator> SectionOrErr = Symbol.getSection();
+ error(SectionOrErr.getError());
+ section_iterator Section = *SectionOrErr;
StringRef Name;
if (Type == SymbolRef::ST_Debug && Section != o->section_end()) {
Section->getName(Name);
} else {
ErrorOr<StringRef> NameOrErr = Symbol.getName();
- if (error(NameOrErr.getError()))
- continue;
+ error(NameOrErr.getError());
Name = *NameOrErr;
}
@@ -1222,8 +1338,7 @@ void llvm::PrintSymbolTable(const ObjectFile *o) {
outs() << SegmentName << ",";
}
StringRef SectionName;
- if (error(Section->getName(SectionName)))
- SectionName = "";
+ error(Section->getName(SectionName));
outs() << SectionName;
}
@@ -1329,7 +1444,7 @@ void llvm::printRawClangAST(const ObjectFile *Obj) {
}
Optional<object::SectionRef> ClangASTSection;
- for (auto Sec : Obj->sections()) {
+ for (auto Sec : ToolSectionFilter(*Obj)) {
StringRef Name;
Sec.getName(Name);
if (Name == ClangASTSectionName) {
@@ -1341,11 +1456,7 @@ void llvm::printRawClangAST(const ObjectFile *Obj) {
return;
StringRef ClangASTContents;
- if (error(ClangASTSection.getValue().getContents(ClangASTContents))) {
- errs() << "Could not read the " << ClangASTSectionName << " section!\n";
- return;
- }
-
+ error(ClangASTSection.getValue().getContents(ClangASTContents));
outs().write(ClangASTContents.data(), ClangASTContents.size());
}
@@ -1364,7 +1475,7 @@ static void printFaultMaps(const ObjectFile *Obj) {
Optional<object::SectionRef> FaultMapSection;
- for (auto Sec : Obj->sections()) {
+ for (auto Sec : ToolSectionFilter(*Obj)) {
StringRef Name;
Sec.getName(Name);
if (Name == FaultMapSectionName) {
@@ -1381,10 +1492,7 @@ static void printFaultMaps(const ObjectFile *Obj) {
}
StringRef FaultMapContents;
- if (error(FaultMapSection.getValue().getContents(FaultMapContents))) {
- errs() << "Could not read the " << FaultMapContents << " section!\n";
- return;
- }
+ error(FaultMapSection.getValue().getContents(FaultMapContents));
FaultMapParser FMP(FaultMapContents.bytes_begin(),
FaultMapContents.bytes_end());
@@ -1392,14 +1500,27 @@ static void printFaultMaps(const ObjectFile *Obj) {
outs() << FMP;
}
-static void printPrivateFileHeader(const ObjectFile *o) {
- if (o->isELF()) {
+static void printPrivateFileHeaders(const ObjectFile *o) {
+ if (o->isELF())
printELFFileHeader(o);
- } else if (o->isCOFF()) {
+ else if (o->isCOFF())
printCOFFFileHeader(o);
- } else if (o->isMachO()) {
+ else if (o->isMachO()) {
printMachOFileHeader(o);
- }
+ printMachOLoadCommands(o);
+ } else
+ report_fatal_error("Invalid/Unsupported object file format");
+}
+
+static void printFirstPrivateFileHeader(const ObjectFile *o) {
+ if (o->isELF())
+ printELFFileHeader(o);
+ else if (o->isCOFF())
+ printCOFFFileHeader(o);
+ else if (o->isMachO())
+ printMachOFileHeader(o);
+ else
+ report_fatal_error("Invalid/Unsupported object file format");
}
static void DumpObject(const ObjectFile *o) {
@@ -1423,7 +1544,9 @@ static void DumpObject(const ObjectFile *o) {
if (UnwindInfo)
PrintUnwindInfo(o);
if (PrivateHeaders)
- printPrivateFileHeader(o);
+ printPrivateFileHeaders(o);
+ if (FirstPrivateHeader)
+ printFirstPrivateFileHeader(o);
if (ExportsTrie)
printExportsTrie(o);
if (Rebase)
@@ -1442,15 +1565,14 @@ static void DumpObject(const ObjectFile *o) {
/// @brief Dump each object file in \a a;
static void DumpArchive(const Archive *a) {
- for (Archive::child_iterator i = a->child_begin(), e = a->child_end(); i != e;
- ++i) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary();
- if (std::error_code EC = ChildOrErr.getError()) {
- // Ignore non-object files.
+ for (auto &ErrorOrChild : a->children()) {
+ if (std::error_code EC = ErrorOrChild.getError())
+ report_error(a->getFileName(), EC);
+ const Archive::Child &C = *ErrorOrChild;
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
+ if (std::error_code EC = ChildOrErr.getError())
if (EC != object_error::invalid_file_type)
report_error(a->getFileName(), EC);
- continue;
- }
if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
DumpObject(o);
else
@@ -1460,11 +1582,6 @@ static void DumpArchive(const Archive *a) {
/// @brief Open file and figure out how to dump it.
static void DumpInput(StringRef file) {
- // If file isn't stdin, check that it exists.
- if (file != "-" && !sys::fs::exists(file)) {
- report_error(file, errc::no_such_file_or_directory);
- return;
- }
// If we are using the Mach-O specific object file parser, then let it parse
// the file and process the command line options. So the -arch flags can
@@ -1476,10 +1593,8 @@ static void DumpInput(StringRef file) {
// Attempt to open the binary.
ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
- if (std::error_code EC = BinaryOrErr.getError()) {
+ if (std::error_code EC = BinaryOrErr.getError())
report_error(file, EC);
- return;
- }
Binary &Binary = *BinaryOrErr.get().getBinary();
if (Archive *a = dyn_cast<Archive>(&Binary))
@@ -1499,7 +1614,6 @@ int main(int argc, char **argv) {
// Initialize targets and assembly printers/parsers.
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
- llvm::InitializeAllAsmParsers();
llvm::InitializeAllDisassemblers();
// Register the target printer for --version.
@@ -1514,6 +1628,8 @@ int main(int argc, char **argv) {
if (InputFilenames.size() == 0)
InputFilenames.push_back("a.out");
+ if (DisassembleAll)
+ Disassemble = true;
if (!Disassemble
&& !Relocations
&& !SectionHeaders
@@ -1521,6 +1637,7 @@ int main(int argc, char **argv) {
&& !SymbolTable
&& !UnwindInfo
&& !PrivateHeaders
+ && !FirstPrivateHeader
&& !ExportsTrie
&& !Rebase
&& !Bind
@@ -1536,7 +1653,7 @@ int main(int argc, char **argv) {
&& !(DylibsUsed && MachOOpt)
&& !(DylibId && MachOOpt)
&& !(ObjcMetaData && MachOOpt)
- && !(DumpSections.size() != 0 && MachOOpt)
+ && !(FilterSections.size() != 0 && MachOOpt)
&& !PrintFaultMaps) {
cl::PrintHelpMessage();
return 2;
@@ -1545,5 +1662,5 @@ int main(int argc, char **argv) {
std::for_each(InputFilenames.begin(), InputFilenames.end(),
DumpInput);
- return ReturnValue;
+ return EXIT_SUCCESS;
}
diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
index eb10d83..60cabbc 100644
--- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@@ -25,10 +26,12 @@ extern cl::opt<std::string> TripleName;
extern cl::opt<std::string> ArchName;
extern cl::opt<std::string> MCPU;
extern cl::list<std::string> MAttrs;
-extern cl::list<std::string> DumpSections;
+extern cl::list<std::string> FilterSections;
extern cl::opt<bool> Disassemble;
+extern cl::opt<bool> DisassembleAll;
extern cl::opt<bool> NoShowRawInsn;
extern cl::opt<bool> PrivateHeaders;
+extern cl::opt<bool> FirstPrivateHeader;
extern cl::opt<bool> ExportsTrie;
extern cl::opt<bool> Rebase;
extern cl::opt<bool> Bind;
@@ -54,7 +57,7 @@ extern cl::opt<bool> UnwindInfo;
extern cl::opt<bool> PrintImmHex;
// Various helper functions.
-bool error(std::error_code ec);
+void error(std::error_code ec);
bool RelocAddressLess(object::RelocationRef a, object::RelocationRef b);
void ParseInputMachO(StringRef Filename);
void printCOFFUnwindInfo(const object::COFFObjectFile* o);
@@ -66,7 +69,9 @@ void printMachOLazyBindTable(const object::MachOObjectFile* o);
void printMachOWeakBindTable(const object::MachOObjectFile* o);
void printELFFileHeader(const object::ObjectFile *o);
void printCOFFFileHeader(const object::ObjectFile *o);
+void printCOFFSymbolTable(const object::COFFObjectFile *o);
void printMachOFileHeader(const object::ObjectFile *o);
+void printMachOLoadCommands(const object::ObjectFile *o);
void printExportsTrie(const object::ObjectFile *o);
void printRebaseTable(const object::ObjectFile *o);
void printBindTable(const object::ObjectFile *o);
@@ -77,6 +82,7 @@ void PrintRelocations(const object::ObjectFile *o);
void PrintSectionHeaders(const object::ObjectFile *o);
void PrintSectionContents(const object::ObjectFile *o);
void PrintSymbolTable(const object::ObjectFile *o);
+LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, std::error_code EC);
} // end namespace llvm
diff --git a/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.cpp b/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.cpp
index d808298..4327054 100644
--- a/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.cpp
+++ b/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.cpp
@@ -19,69 +19,53 @@ BuiltinDumper::BuiltinDumper(LinePrinter &P)
: PDBSymDumper(false), Printer(P) {}
void BuiltinDumper::start(const PDBSymbolTypeBuiltin &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Type).get() << getTypeName(Symbol);
+}
+
+StringRef BuiltinDumper::getTypeName(const PDBSymbolTypeBuiltin &Symbol) {
PDB_BuiltinType Type = Symbol.getBuiltinType();
switch (Type) {
case PDB_BuiltinType::Float:
if (Symbol.getLength() == 4)
- WithColor(Printer, PDB_ColorItem::Type).get() << "float";
- else
- WithColor(Printer, PDB_ColorItem::Type).get() << "double";
- break;
+ return "float";
+ return "double";
case PDB_BuiltinType::UInt:
- WithColor(Printer, PDB_ColorItem::Type).get() << "unsigned";
if (Symbol.getLength() == 8)
- WithColor(Printer, PDB_ColorItem::Type).get() << " __int64";
- break;
+ return "unsigned __int64";
+ return "unsigned";
case PDB_BuiltinType::Int:
if (Symbol.getLength() == 4)
- WithColor(Printer, PDB_ColorItem::Type).get() << "int";
- else
- WithColor(Printer, PDB_ColorItem::Type).get() << "__int64";
- break;
+ return "int";
+ return "__int64";
case PDB_BuiltinType::Char:
- WithColor(Printer, PDB_ColorItem::Type).get() << "char";
- break;
+ return "char";
case PDB_BuiltinType::WCharT:
- WithColor(Printer, PDB_ColorItem::Type).get() << "wchar_t";
- break;
+ return "wchar_t";
case PDB_BuiltinType::Void:
- WithColor(Printer, PDB_ColorItem::Type).get() << "void";
- break;
+ return "void";
case PDB_BuiltinType::Long:
- WithColor(Printer, PDB_ColorItem::Type).get() << "long";
- break;
+ return "long";
case PDB_BuiltinType::ULong:
- WithColor(Printer, PDB_ColorItem::Type).get() << "unsigned long";
- break;
+ return "unsigned long";
case PDB_BuiltinType::Bool:
- WithColor(Printer, PDB_ColorItem::Type).get() << "bool";
- break;
+ return "bool";
case PDB_BuiltinType::Currency:
- WithColor(Printer, PDB_ColorItem::Type).get() << "CURRENCY";
- break;
+ return "CURRENCY";
case PDB_BuiltinType::Date:
- WithColor(Printer, PDB_ColorItem::Type).get() << "DATE";
- break;
+ return "DATE";
case PDB_BuiltinType::Variant:
- WithColor(Printer, PDB_ColorItem::Type).get() << "VARIANT";
- break;
+ return "VARIANT";
case PDB_BuiltinType::Complex:
- WithColor(Printer, PDB_ColorItem::Type).get() << "complex";
- break;
+ return "complex";
case PDB_BuiltinType::Bitfield:
- WithColor(Printer, PDB_ColorItem::Type).get() << "bitfield";
- break;
+ return "bitfield";
case PDB_BuiltinType::BSTR:
- WithColor(Printer, PDB_ColorItem::Type).get() << "BSTR";
- break;
+ return "BSTR";
case PDB_BuiltinType::HResult:
- WithColor(Printer, PDB_ColorItem::Type).get() << "HRESULT";
- break;
+ return "HRESULT";
case PDB_BuiltinType::BCD:
- WithColor(Printer, PDB_ColorItem::Type).get() << "HRESULT";
- break;
+ return "HRESULT";
default:
- WithColor(Printer, PDB_ColorItem::Type).get() << "void";
- break;
+ return "void";
}
}
diff --git a/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.h b/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.h
index 8cf984a0..ac666db 100644
--- a/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.h
+++ b/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.h
@@ -23,6 +23,8 @@ public:
void start(const PDBSymbolTypeBuiltin &Symbol);
private:
+ StringRef getTypeName(const PDBSymbolTypeBuiltin &Symbol);
+
LinePrinter &Printer;
};
}
diff --git a/contrib/llvm/tools/llvm-pdbdump/LinePrinter.cpp b/contrib/llvm/tools/llvm-pdbdump/LinePrinter.cpp
index 6bbc403..a43727f 100644
--- a/contrib/llvm/tools/llvm-pdbdump/LinePrinter.cpp
+++ b/contrib/llvm/tools/llvm-pdbdump/LinePrinter.cpp
@@ -11,19 +11,49 @@
#include "llvm-pdbdump.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Regex.h"
#include <algorithm>
+namespace {
+bool IsItemExcluded(llvm::StringRef Item,
+ std::list<llvm::Regex> &IncludeFilters,
+ std::list<llvm::Regex> &ExcludeFilters) {
+ if (Item.empty())
+ return false;
+
+ auto match_pred = [Item](llvm::Regex &R) { return R.match(Item); };
+
+ // Include takes priority over exclude. If the user specified include
+ // filters, and none of them include this item, them item is gone.
+ if (!IncludeFilters.empty() && !any_of(IncludeFilters, match_pred))
+ return true;
+
+ if (any_of(ExcludeFilters, match_pred))
+ return true;
+
+ return false;
+}
+}
+
using namespace llvm;
LinePrinter::LinePrinter(int Indent, llvm::raw_ostream &Stream)
: OS(Stream), IndentSpaces(Indent), CurrentIndent(0) {
- SetFilters(TypeFilters, opts::ExcludeTypes.begin(), opts::ExcludeTypes.end());
- SetFilters(SymbolFilters, opts::ExcludeSymbols.begin(),
+ SetFilters(ExcludeTypeFilters, opts::ExcludeTypes.begin(),
+ opts::ExcludeTypes.end());
+ SetFilters(ExcludeSymbolFilters, opts::ExcludeSymbols.begin(),
opts::ExcludeSymbols.end());
- SetFilters(CompilandFilters, opts::ExcludeCompilands.begin(),
+ SetFilters(ExcludeCompilandFilters, opts::ExcludeCompilands.begin(),
opts::ExcludeCompilands.end());
+
+ SetFilters(IncludeTypeFilters, opts::IncludeTypes.begin(),
+ opts::IncludeTypes.end());
+ SetFilters(IncludeSymbolFilters, opts::IncludeSymbols.begin(),
+ opts::IncludeSymbols.end());
+ SetFilters(IncludeCompilandFilters, opts::IncludeCompilands.begin(),
+ opts::IncludeCompilands.end());
}
void LinePrinter::Indent() { CurrentIndent += IndentSpaces; }
@@ -38,87 +68,53 @@ void LinePrinter::NewLine() {
}
bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName) {
- if (TypeName.empty())
- return false;
-
- for (auto &Expr : TypeFilters) {
- if (Expr.match(TypeName))
- return true;
- }
- return false;
+ return IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters);
}
bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) {
- if (SymbolName.empty())
- return false;
-
- for (auto &Expr : SymbolFilters) {
- if (Expr.match(SymbolName))
- return true;
- }
- return false;
+ return IsItemExcluded(SymbolName, IncludeSymbolFilters, ExcludeSymbolFilters);
}
bool LinePrinter::IsCompilandExcluded(llvm::StringRef CompilandName) {
- if (CompilandName.empty())
- return false;
-
- for (auto &Expr : CompilandFilters) {
- if (Expr.match(CompilandName))
- return true;
- }
- return false;
+ return IsItemExcluded(CompilandName, IncludeCompilandFilters,
+ ExcludeCompilandFilters);
}
WithColor::WithColor(LinePrinter &P, PDB_ColorItem C) : OS(P.OS) {
- if (C == PDB_ColorItem::None)
- OS.resetColor();
- else {
- raw_ostream::Colors Color;
- bool Bold;
- translateColor(C, Color, Bold);
- OS.changeColor(Color, Bold);
- }
+ applyColor(C);
}
WithColor::~WithColor() { OS.resetColor(); }
-void WithColor::translateColor(PDB_ColorItem C, raw_ostream::Colors &Color,
- bool &Bold) const {
+void WithColor::applyColor(PDB_ColorItem C) {
switch (C) {
+ case PDB_ColorItem::None:
+ OS.resetColor();
+ return;
case PDB_ColorItem::Address:
- Color = raw_ostream::YELLOW;
- Bold = true;
+ OS.changeColor(raw_ostream::YELLOW, /*bold=*/true);
return;
case PDB_ColorItem::Keyword:
- Color = raw_ostream::MAGENTA;
- Bold = true;
+ OS.changeColor(raw_ostream::MAGENTA, true);
return;
case PDB_ColorItem::Register:
case PDB_ColorItem::Offset:
- Color = raw_ostream::YELLOW;
- Bold = false;
+ OS.changeColor(raw_ostream::YELLOW, false);
return;
case PDB_ColorItem::Type:
- Color = raw_ostream::CYAN;
- Bold = true;
+ OS.changeColor(raw_ostream::CYAN, true);
return;
case PDB_ColorItem::Identifier:
- Color = raw_ostream::CYAN;
- Bold = false;
+ OS.changeColor(raw_ostream::CYAN, false);
return;
case PDB_ColorItem::Path:
- Color = raw_ostream::CYAN;
- Bold = false;
+ OS.changeColor(raw_ostream::CYAN, false);
return;
case PDB_ColorItem::SectionHeader:
- Color = raw_ostream::RED;
- Bold = true;
+ OS.changeColor(raw_ostream::RED, true);
return;
case PDB_ColorItem::LiteralValue:
- Color = raw_ostream::GREEN;
- Bold = true;
- default:
+ OS.changeColor(raw_ostream::GREEN, true);
return;
}
}
diff --git a/contrib/llvm/tools/llvm-pdbdump/LinePrinter.h b/contrib/llvm/tools/llvm-pdbdump/LinePrinter.h
index b985e93..b0a9d2c 100644
--- a/contrib/llvm/tools/llvm-pdbdump/LinePrinter.h
+++ b/contrib/llvm/tools/llvm-pdbdump/LinePrinter.h
@@ -48,9 +48,13 @@ private:
int IndentSpaces;
int CurrentIndent;
- std::list<Regex> CompilandFilters;
- std::list<Regex> TypeFilters;
- std::list<Regex> SymbolFilters;
+ std::list<Regex> ExcludeCompilandFilters;
+ std::list<Regex> ExcludeTypeFilters;
+ std::list<Regex> ExcludeSymbolFilters;
+
+ std::list<Regex> IncludeCompilandFilters;
+ std::list<Regex> IncludeTypeFilters;
+ std::list<Regex> IncludeSymbolFilters;
};
template <class T>
@@ -80,8 +84,7 @@ public:
raw_ostream &get() { return OS; }
private:
- void translateColor(PDB_ColorItem C, raw_ostream::Colors &Color,
- bool &Bold) const;
+ void applyColor(PDB_ColorItem C);
raw_ostream &OS;
};
}
diff --git a/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
index 4a4c64b..0e3f0b2 100644
--- a/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -22,6 +22,8 @@
#include "VariableDumper.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
@@ -38,12 +40,16 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"
#if defined(HAVE_DIA_SDK)
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
#include <Windows.h>
#endif
@@ -79,6 +85,17 @@ cl::opt<uint64_t> LoadAddress(
cl::desc("Assume the module is loaded at the specified address"),
cl::cat(OtherOptions));
+cl::opt<bool> DumpHeaders("dump-headers", cl::desc("dump PDB headers"),
+ cl::cat(OtherOptions));
+cl::opt<bool> DumpStreamSizes("dump-stream-sizes",
+ cl::desc("dump PDB stream sizes"),
+ cl::cat(OtherOptions));
+cl::opt<bool> DumpStreamBlocks("dump-stream-blocks",
+ cl::desc("dump PDB stream blocks"),
+ cl::cat(OtherOptions));
+cl::opt<std::string> DumpStreamData("dump-stream", cl::desc("dump stream data"),
+ cl::cat(OtherOptions));
+
cl::list<std::string>
ExcludeTypes("exclude-types",
cl::desc("Exclude types by regular expression"),
@@ -91,6 +108,20 @@ cl::list<std::string>
ExcludeCompilands("exclude-compilands",
cl::desc("Exclude compilands by regular expression"),
cl::ZeroOrMore, cl::cat(FilterCategory));
+
+cl::list<std::string> IncludeTypes(
+ "include-types",
+ cl::desc("Include only types which match a regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory));
+cl::list<std::string> IncludeSymbols(
+ "include-symbols",
+ cl::desc("Include only symbols which match a regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory));
+cl::list<std::string> IncludeCompilands(
+ "include-compilands",
+ cl::desc("Include only compilands those which match a regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory));
+
cl::opt<bool> ExcludeCompilerGenerated(
"no-compiler-generated",
cl::desc("Don't show compiler generated types and symbols"),
@@ -107,10 +138,264 @@ cl::opt<bool> NoEnumDefs("no-enum-definitions",
cl::cat(FilterCategory));
}
+
+static void reportError(StringRef Input, StringRef Message) {
+ if (Input == "-")
+ Input = "<stdin>";
+ errs() << Input << ": " << Message << "\n";
+ errs().flush();
+ exit(1);
+}
+
+static void reportError(StringRef Input, std::error_code EC) {
+ reportError(Input, EC.message());
+}
+
+static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr,
+ const uint64_t Size) {
+ if (Addr + Size < Addr || Addr + Size < Size ||
+ Addr + Size > uintptr_t(M.getBufferEnd()) ||
+ Addr < uintptr_t(M.getBufferStart())) {
+ return std::make_error_code(std::errc::bad_address);
+ }
+ return std::error_code();
+}
+
+template <typename T>
+static std::error_code checkOffset(MemoryBufferRef M, ArrayRef<T> AR) {
+ return checkOffset(M, uintptr_t(AR.data()), (uint64_t)AR.size() * sizeof(T));
+}
+
+static std::error_code checkOffset(MemoryBufferRef M, StringRef SR) {
+ return checkOffset(M, uintptr_t(SR.data()), SR.size());
+}
+
+// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
+// Returns unexpected_eof if error.
+template <typename T>
+static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
+ const void *Ptr,
+ const uint64_t Size = sizeof(T)) {
+ uintptr_t Addr = uintptr_t(Ptr);
+ if (std::error_code EC = checkOffset(M, Addr, Size))
+ return EC;
+ Obj = reinterpret_cast<const T *>(Addr);
+ return std::error_code();
+}
+
+static uint64_t bytesToBlocks(uint64_t NumBytes, uint64_t BlockSize) {
+ return RoundUpToAlignment(NumBytes, BlockSize) / BlockSize;
+}
+
+static uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize) {
+ return BlockNumber * BlockSize;
+}
+
+static void dumpStructure(MemoryBufferRef M) {
+ const PDB::SuperBlock *SB;
+ if (auto EC = getObject(SB, M, M.getBufferStart()))
+ reportError(M.getBufferIdentifier(), EC);
+
+ if (opts::DumpHeaders) {
+ outs() << "BlockSize: " << SB->BlockSize << '\n';
+ outs() << "Unknown0: " << SB->Unknown0 << '\n';
+ outs() << "NumBlocks: " << SB->NumBlocks << '\n';
+ outs() << "NumDirectoryBytes: " << SB->NumDirectoryBytes << '\n';
+ outs() << "Unknown1: " << SB->Unknown1 << '\n';
+ outs() << "BlockMapAddr: " << SB->BlockMapAddr << '\n';
+ }
+
+ // We don't support blocksizes which aren't a multiple of four bytes.
+ if (SB->BlockSize % sizeof(support::ulittle32_t) != 0)
+ reportError(M.getBufferIdentifier(),
+ std::make_error_code(std::errc::illegal_byte_sequence));
+
+ // We don't support directories whose sizes aren't a multiple of four bytes.
+ if (SB->NumDirectoryBytes % sizeof(support::ulittle32_t) != 0)
+ reportError(M.getBufferIdentifier(),
+ std::make_error_code(std::errc::illegal_byte_sequence));
+
+ // The number of blocks which comprise the directory is a simple function of
+ // the number of bytes it contains.
+ uint64_t NumDirectoryBlocks =
+ bytesToBlocks(SB->NumDirectoryBytes, SB->BlockSize);
+ if (opts::DumpHeaders)
+ outs() << "NumDirectoryBlocks: " << NumDirectoryBlocks << '\n';
+
+ // The block map, as we understand it, is a block which consists of a list of
+ // block numbers.
+ // It is unclear what would happen if the number of blocks couldn't fit on a
+ // single block.
+ if (NumDirectoryBlocks > SB->BlockSize / sizeof(support::ulittle32_t))
+ reportError(M.getBufferIdentifier(),
+ std::make_error_code(std::errc::illegal_byte_sequence));
+
+
+ uint64_t BlockMapOffset = (uint64_t)SB->BlockMapAddr * SB->BlockSize;
+ if (opts::DumpHeaders)
+ outs() << "BlockMapOffset: " << BlockMapOffset << '\n';
+
+ // The directory is not contiguous. Instead, the block map contains a
+ // contiguous list of block numbers whose contents, when concatenated in
+ // order, make up the directory.
+ auto DirectoryBlocks =
+ makeArrayRef(reinterpret_cast<const support::ulittle32_t *>(
+ M.getBufferStart() + BlockMapOffset),
+ NumDirectoryBlocks);
+ if (auto EC = checkOffset(M, DirectoryBlocks))
+ reportError(M.getBufferIdentifier(), EC);
+
+ if (opts::DumpHeaders) {
+ outs() << "DirectoryBlocks: [";
+ for (const support::ulittle32_t &DirectoryBlockAddr : DirectoryBlocks) {
+ if (&DirectoryBlockAddr != &DirectoryBlocks.front())
+ outs() << ", ";
+ outs() << DirectoryBlockAddr;
+ }
+ outs() << "]\n";
+ }
+
+ bool SeenNumStreams = false;
+ uint32_t NumStreams = 0;
+ std::vector<uint32_t> StreamSizes;
+ DenseMap<uint32_t, std::vector<uint32_t>> StreamMap;
+ uint32_t StreamIdx = 0;
+ uint64_t DirectoryBytesRead = 0;
+ // The structure of the directory is as follows:
+ // struct PDBDirectory {
+ // uint32_t NumStreams;
+ // uint32_t StreamSizes[NumStreams];
+ // uint32_t StreamMap[NumStreams][];
+ // };
+ //
+ // Empty streams don't consume entries in the StreamMap.
+ for (uint32_t DirectoryBlockAddr : DirectoryBlocks) {
+ uint64_t DirectoryBlockOffset =
+ blockToOffset(DirectoryBlockAddr, SB->BlockSize);
+ auto DirectoryBlock =
+ makeArrayRef(reinterpret_cast<const support::ulittle32_t *>(
+ M.getBufferStart() + DirectoryBlockOffset),
+ SB->BlockSize / sizeof(support::ulittle32_t));
+ if (auto EC = checkOffset(M, DirectoryBlock))
+ reportError(M.getBufferIdentifier(), EC);
+
+ // We read data out of the directory four bytes at a time. Depending on
+ // where we are in the directory, the contents may be: the number of streams
+ // in the directory, a stream's size, or a block in the stream map.
+ for (uint32_t Data : DirectoryBlock) {
+ // Don't read beyond the end of the directory.
+ if (DirectoryBytesRead == SB->NumDirectoryBytes)
+ break;
+
+ DirectoryBytesRead += sizeof(Data);
+
+ // This data must be the number of streams if we haven't seen it yet.
+ if (!SeenNumStreams) {
+ NumStreams = Data;
+ SeenNumStreams = true;
+ continue;
+ }
+ // This data must be a stream size if we have not seen them all yet.
+ if (StreamSizes.size() < NumStreams) {
+ // It seems like some streams have their set to -1 when their contents
+ // are not present. Treat them like empty streams for now.
+ if (Data == UINT32_MAX)
+ StreamSizes.push_back(0);
+ else
+ StreamSizes.push_back(Data);
+ continue;
+ }
+
+ // This data must be a stream block number if we have seen all of the
+ // stream sizes.
+ std::vector<uint32_t> *StreamBlocks = nullptr;
+ // Figure out which stream this block number belongs to.
+ while (StreamIdx < NumStreams) {
+ uint64_t NumExpectedStreamBlocks =
+ bytesToBlocks(StreamSizes[StreamIdx], SB->BlockSize);
+ StreamBlocks = &StreamMap[StreamIdx];
+ if (NumExpectedStreamBlocks > StreamBlocks->size())
+ break;
+ ++StreamIdx;
+ }
+ // It seems this block doesn't belong to any stream? The stream is either
+ // corrupt or something more mysterious is going on.
+ if (StreamIdx == NumStreams)
+ reportError(M.getBufferIdentifier(),
+ std::make_error_code(std::errc::illegal_byte_sequence));
+
+ StreamBlocks->push_back(Data);
+ }
+ }
+
+ // We should have read exactly SB->NumDirectoryBytes bytes.
+ assert(DirectoryBytesRead == SB->NumDirectoryBytes);
+
+ if (opts::DumpHeaders)
+ outs() << "NumStreams: " << NumStreams << '\n';
+ if (opts::DumpStreamSizes)
+ for (uint32_t StreamIdx = 0; StreamIdx < NumStreams; ++StreamIdx)
+ outs() << "StreamSizes[" << StreamIdx << "]: " << StreamSizes[StreamIdx]
+ << '\n';
+
+ if (opts::DumpStreamBlocks) {
+ for (uint32_t StreamIdx = 0; StreamIdx < NumStreams; ++StreamIdx) {
+ outs() << "StreamBlocks[" << StreamIdx << "]: [";
+ std::vector<uint32_t> &StreamBlocks = StreamMap[StreamIdx];
+ for (uint32_t &StreamBlock : StreamBlocks) {
+ if (&StreamBlock != &StreamBlocks.front())
+ outs() << ", ";
+ outs() << StreamBlock;
+ }
+ outs() << "]\n";
+ }
+ }
+
+ StringRef DumpStreamStr = opts::DumpStreamData;
+ uint32_t DumpStreamNum;
+ if (!DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) &&
+ DumpStreamNum < NumStreams) {
+ uint32_t StreamBytesRead = 0;
+ uint32_t StreamSize = StreamSizes[DumpStreamNum];
+ std::vector<uint32_t> &StreamBlocks = StreamMap[DumpStreamNum];
+ for (uint32_t &StreamBlockAddr : StreamBlocks) {
+ uint64_t StreamBlockOffset = blockToOffset(StreamBlockAddr, SB->BlockSize);
+ uint32_t BytesLeftToReadInStream = StreamSize - StreamBytesRead;
+ if (BytesLeftToReadInStream == 0)
+ break;
+
+ uint32_t BytesToReadInBlock = std::min(
+ BytesLeftToReadInStream, static_cast<uint32_t>(SB->BlockSize));
+ auto StreamBlockData =
+ StringRef(M.getBufferStart() + StreamBlockOffset, BytesToReadInBlock);
+ if (auto EC = checkOffset(M, StreamBlockData))
+ reportError(M.getBufferIdentifier(), EC);
+
+ outs() << StreamBlockData;
+ StreamBytesRead += StreamBlockData.size();
+ }
+ }
+}
+
static void dumpInput(StringRef Path) {
+ if (opts::DumpHeaders || !opts::DumpStreamData.empty()) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
+ MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
+ /*RequiresNullTerminator=*/false);
+
+ if (std::error_code EC = ErrorOrBuffer.getError())
+ reportError(Path, EC);
+
+ std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();
+
+ dumpStructure(Buffer->getMemBufferRef());
+
+ outs().flush();
+ return;
+ }
+
std::unique_ptr<IPDBSession> Session;
- PDB_ErrorCode Error =
- llvm::loadDataForPDB(PDB_ReaderType::DIA, Path, Session);
+ PDB_ErrorCode Error = loadDataForPDB(PDB_ReaderType::DIA, Path, Session);
switch (Error) {
case PDB_ErrorCode::Success:
break;
@@ -145,7 +430,7 @@ static void dumpInput(StringRef Path) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
- if (!llvm::sys::fs::file_size(FileName, FileSize)) {
+ if (!sys::fs::file_size(FileName, FileSize)) {
Printer << ": " << FileSize << " bytes";
} else {
Printer << ": (Unable to obtain file size)";
@@ -242,11 +527,11 @@ int main(int argc_, const char *argv_[]) {
PrettyStackTraceProgram X(argc_, argv_);
SmallVector<const char *, 256> argv;
- llvm::SpecificBumpPtrAllocator<char> ArgAllocator;
- std::error_code EC = llvm::sys::Process::GetArgumentVector(
- argv, llvm::makeArrayRef(argv_, argc_), ArgAllocator);
+ SpecificBumpPtrAllocator<char> ArgAllocator;
+ std::error_code EC = sys::Process::GetArgumentVector(
+ argv, makeArrayRef(argv_, argc_), ArgAllocator);
if (EC) {
- llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n';
+ errs() << "error: couldn't get arguments: " << EC.message() << '\n';
return 1;
}
diff --git a/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.h b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.h
index 586a9ea..cb5bec6 100644
--- a/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.h
+++ b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.h
@@ -27,6 +27,9 @@ extern llvm::cl::opt<bool> NoEnumDefs;
extern llvm::cl::list<std::string> ExcludeTypes;
extern llvm::cl::list<std::string> ExcludeSymbols;
extern llvm::cl::list<std::string> ExcludeCompilands;
+extern llvm::cl::list<std::string> IncludeTypes;
+extern llvm::cl::list<std::string> IncludeSymbols;
+extern llvm::cl::list<std::string> IncludeCompilands;
}
#endif \ No newline at end of file
diff --git a/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp b/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 6fb48d8..dc6cd0a 100644
--- a/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -11,6 +11,8 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/ProfileData/InstrProfReader.h"
@@ -18,6 +20,7 @@
#include "llvm/ProfileData/SampleProfReader.h"
#include "llvm/ProfileData/SampleProfWriter.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
@@ -26,67 +29,150 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <tuple>
using namespace llvm;
-static void exitWithError(const Twine &Message, StringRef Whence = "") {
+enum ProfileFormat { PF_None = 0, PF_Text, PF_Binary, PF_GCC };
+
+static void exitWithError(const Twine &Message, StringRef Whence = "",
+ StringRef Hint = "") {
errs() << "error: ";
if (!Whence.empty())
errs() << Whence << ": ";
errs() << Message << "\n";
+ if (!Hint.empty())
+ errs() << Hint << "\n";
::exit(1);
}
+static void exitWithErrorCode(const std::error_code &Error,
+ StringRef Whence = "") {
+ if (Error.category() == instrprof_category()) {
+ instrprof_error instrError = static_cast<instrprof_error>(Error.value());
+ if (instrError == instrprof_error::unrecognized_format) {
+ // Hint for common error of forgetting -sample for sample profiles.
+ exitWithError(Error.message(), Whence,
+ "Perhaps you forgot to use the -sample option?");
+ }
+ }
+ exitWithError(Error.message(), Whence);
+}
+
namespace {
enum ProfileKinds { instr, sample };
}
-static void mergeInstrProfile(const cl::list<std::string> &Inputs,
- StringRef OutputFilename) {
+static void handleMergeWriterError(std::error_code &Error,
+ StringRef WhenceFile = "",
+ StringRef WhenceFunction = "",
+ bool ShowHint = true) {
+ if (!WhenceFile.empty())
+ errs() << WhenceFile << ": ";
+ if (!WhenceFunction.empty())
+ errs() << WhenceFunction << ": ";
+ errs() << Error.message() << "\n";
+
+ if (ShowHint) {
+ StringRef Hint = "";
+ if (Error.category() == instrprof_category()) {
+ instrprof_error instrError = static_cast<instrprof_error>(Error.value());
+ switch (instrError) {
+ case instrprof_error::hash_mismatch:
+ case instrprof_error::count_mismatch:
+ case instrprof_error::value_site_count_mismatch:
+ Hint = "Make sure that all profile data to be merged is generated "
+ "from the same binary.";
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!Hint.empty())
+ errs() << Hint << "\n";
+ }
+}
+
+struct WeightedFile {
+ StringRef Filename;
+ uint64_t Weight;
+
+ WeightedFile() {}
+
+ WeightedFile(StringRef F, uint64_t W) : Filename{F}, Weight{W} {}
+};
+typedef SmallVector<WeightedFile, 5> WeightedFileVector;
+
+static void mergeInstrProfile(const WeightedFileVector &Inputs,
+ StringRef OutputFilename,
+ ProfileFormat OutputFormat) {
if (OutputFilename.compare("-") == 0)
exitWithError("Cannot write indexed profdata format to stdout.");
+ if (OutputFormat != PF_Binary && OutputFormat != PF_Text)
+ exitWithError("Unknown format is specified.");
+
std::error_code EC;
raw_fd_ostream Output(OutputFilename.data(), EC, sys::fs::F_None);
if (EC)
- exitWithError(EC.message(), OutputFilename);
+ exitWithErrorCode(EC, OutputFilename);
InstrProfWriter Writer;
- for (const auto &Filename : Inputs) {
- auto ReaderOrErr = InstrProfReader::create(Filename);
+ SmallSet<std::error_code, 4> WriterErrorCodes;
+ for (const auto &Input : Inputs) {
+ auto ReaderOrErr = InstrProfReader::create(Input.Filename);
if (std::error_code ec = ReaderOrErr.getError())
- exitWithError(ec.message(), Filename);
+ exitWithErrorCode(ec, Input.Filename);
auto Reader = std::move(ReaderOrErr.get());
- for (const auto &I : *Reader)
- if (std::error_code EC =
- Writer.addFunctionCounts(I.Name, I.Hash, I.Counts))
- errs() << Filename << ": " << I.Name << ": " << EC.message() << "\n";
+ for (auto &I : *Reader) {
+ if (std::error_code EC = Writer.addRecord(std::move(I), Input.Weight)) {
+ // Only show hint the first time an error occurs.
+ bool firstTime = WriterErrorCodes.insert(EC).second;
+ handleMergeWriterError(EC, Input.Filename, I.Name, firstTime);
+ }
+ }
if (Reader->hasError())
- exitWithError(Reader->getError().message(), Filename);
+ exitWithErrorCode(Reader->getError(), Input.Filename);
}
- Writer.write(Output);
+ if (OutputFormat == PF_Text)
+ Writer.writeText(Output);
+ else
+ Writer.write(Output);
}
-static void mergeSampleProfile(const cl::list<std::string> &Inputs,
+static sampleprof::SampleProfileFormat FormatMap[] = {
+ sampleprof::SPF_None, sampleprof::SPF_Text, sampleprof::SPF_Binary,
+ sampleprof::SPF_GCC};
+
+static void mergeSampleProfile(const WeightedFileVector &Inputs,
StringRef OutputFilename,
- sampleprof::SampleProfileFormat OutputFormat) {
+ ProfileFormat OutputFormat) {
using namespace sampleprof;
- auto WriterOrErr = SampleProfileWriter::create(OutputFilename, OutputFormat);
+ auto WriterOrErr =
+ SampleProfileWriter::create(OutputFilename, FormatMap[OutputFormat]);
if (std::error_code EC = WriterOrErr.getError())
- exitWithError(EC.message(), OutputFilename);
+ exitWithErrorCode(EC, OutputFilename);
auto Writer = std::move(WriterOrErr.get());
StringMap<FunctionSamples> ProfileMap;
- for (const auto &Filename : Inputs) {
+ SmallVector<std::unique_ptr<sampleprof::SampleProfileReader>, 5> Readers;
+ for (const auto &Input : Inputs) {
auto ReaderOrErr =
- SampleProfileReader::create(Filename, getGlobalContext());
+ SampleProfileReader::create(Input.Filename, getGlobalContext());
if (std::error_code EC = ReaderOrErr.getError())
- exitWithError(EC.message(), Filename);
-
- auto Reader = std::move(ReaderOrErr.get());
+ exitWithErrorCode(EC, Input.Filename);
+
+ // We need to keep the readers around until after all the files are
+ // read so that we do not lose the function names stored in each
+ // reader's memory. The function names are needed to write out the
+ // merged profile map.
+ Readers.push_back(std::move(ReaderOrErr.get()));
+ const auto Reader = Readers.back().get();
if (std::error_code EC = Reader->read())
- exitWithError(EC.message(), Filename);
+ exitWithErrorCode(EC, Input.Filename);
StringMap<FunctionSamples> &Profiles = Reader->getProfiles();
for (StringMap<FunctionSamples>::iterator I = Profiles.begin(),
@@ -94,16 +180,36 @@ static void mergeSampleProfile(const cl::list<std::string> &Inputs,
I != E; ++I) {
StringRef FName = I->first();
FunctionSamples &Samples = I->second;
- ProfileMap[FName].merge(Samples);
+ sampleprof_error Result = ProfileMap[FName].merge(Samples, Input.Weight);
+ if (Result != sampleprof_error::success) {
+ std::error_code EC = make_error_code(Result);
+ handleMergeWriterError(EC, Input.Filename, FName);
+ }
}
}
Writer->write(ProfileMap);
}
-static int merge_main(int argc, const char *argv[]) {
- cl::list<std::string> Inputs(cl::Positional, cl::Required, cl::OneOrMore,
- cl::desc("<filenames...>"));
+static WeightedFile parseWeightedFile(const StringRef &WeightedFilename) {
+ StringRef WeightStr, FileName;
+ std::tie(WeightStr, FileName) = WeightedFilename.split(',');
+
+ uint64_t Weight;
+ if (WeightStr.getAsInteger(10, Weight) || Weight < 1)
+ exitWithError("Input weight must be a positive integer.");
+
+ if (!sys::fs::exists(FileName))
+ exitWithErrorCode(make_error_code(errc::no_such_file_or_directory),
+ FileName);
+ return WeightedFile(FileName, Weight);
+}
+
+static int merge_main(int argc, const char *argv[]) {
+ cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<filename...>"));
+ cl::list<std::string> WeightedInputFilenames("weighted-input",
+ cl::desc("<weight>,<filename>"));
cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
cl::init("-"), cl::Required,
cl::desc("Output file"));
@@ -114,31 +220,41 @@ static int merge_main(int argc, const char *argv[]) {
cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
clEnumVal(sample, "Sample profile"), clEnumValEnd));
- cl::opt<sampleprof::SampleProfileFormat> OutputFormat(
- cl::desc("Format of output profile (only meaningful with --sample)"),
- cl::init(sampleprof::SPF_Binary),
- cl::values(clEnumValN(sampleprof::SPF_Binary, "binary",
- "Binary encoding (default)"),
- clEnumValN(sampleprof::SPF_Text, "text", "Text encoding"),
- clEnumValN(sampleprof::SPF_GCC, "gcc", "GCC encoding"),
+ cl::opt<ProfileFormat> OutputFormat(
+ cl::desc("Format of output profile"), cl::init(PF_Binary),
+ cl::values(clEnumValN(PF_Binary, "binary", "Binary encoding (default)"),
+ clEnumValN(PF_Text, "text", "Text encoding"),
+ clEnumValN(PF_GCC, "gcc",
+ "GCC encoding (only meaningful for -sample)"),
clEnumValEnd));
cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
+ if (InputFilenames.empty() && WeightedInputFilenames.empty())
+ exitWithError("No input files specified. See " +
+ sys::path::filename(argv[0]) + " -help");
+
+ WeightedFileVector WeightedInputs;
+ for (StringRef Filename : InputFilenames)
+ WeightedInputs.push_back(WeightedFile(Filename, 1));
+ for (StringRef WeightedFilename : WeightedInputFilenames)
+ WeightedInputs.push_back(parseWeightedFile(WeightedFilename));
+
if (ProfileKind == instr)
- mergeInstrProfile(Inputs, OutputFilename);
+ mergeInstrProfile(WeightedInputs, OutputFilename, OutputFormat);
else
- mergeSampleProfile(Inputs, OutputFilename, OutputFormat);
+ mergeSampleProfile(WeightedInputs, OutputFilename, OutputFormat);
return 0;
}
static int showInstrProfile(std::string Filename, bool ShowCounts,
- bool ShowAllFunctions, std::string ShowFunction,
+ bool ShowIndirectCallTargets, bool ShowAllFunctions,
+ std::string ShowFunction, bool TextFormat,
raw_fd_ostream &OS) {
auto ReaderOrErr = InstrProfReader::create(Filename);
if (std::error_code EC = ReaderOrErr.getError())
- exitWithError(EC.message(), Filename);
+ exitWithErrorCode(EC, Filename);
auto Reader = std::move(ReaderOrErr.get());
uint64_t MaxFunctionCount = 0, MaxBlockCount = 0;
@@ -148,35 +264,71 @@ static int showInstrProfile(std::string Filename, bool ShowCounts,
ShowAllFunctions || (!ShowFunction.empty() &&
Func.Name.find(ShowFunction) != Func.Name.npos);
+ bool doTextFormatDump = (Show && ShowCounts && TextFormat);
+
+ if (doTextFormatDump) {
+ InstrProfSymtab &Symtab = Reader->getSymtab();
+ InstrProfWriter::writeRecordInText(Func, Symtab, OS);
+ continue;
+ }
+
++TotalFunctions;
assert(Func.Counts.size() > 0 && "function missing entry counter");
if (Func.Counts[0] > MaxFunctionCount)
MaxFunctionCount = Func.Counts[0];
+ for (size_t I = 1, E = Func.Counts.size(); I < E; ++I) {
+ if (Func.Counts[I] > MaxBlockCount)
+ MaxBlockCount = Func.Counts[I];
+ }
+
if (Show) {
+
if (!ShownFunctions)
OS << "Counters:\n";
+
++ShownFunctions;
OS << " " << Func.Name << ":\n"
<< " Hash: " << format("0x%016" PRIx64, Func.Hash) << "\n"
<< " Counters: " << Func.Counts.size() << "\n"
<< " Function count: " << Func.Counts[0] << "\n";
- }
- if (Show && ShowCounts)
- OS << " Block counts: [";
- for (size_t I = 1, E = Func.Counts.size(); I < E; ++I) {
- if (Func.Counts[I] > MaxBlockCount)
- MaxBlockCount = Func.Counts[I];
- if (Show && ShowCounts)
- OS << (I == 1 ? "" : ", ") << Func.Counts[I];
+ if (ShowIndirectCallTargets)
+ OS << " Indirect Call Site Count: "
+ << Func.getNumValueSites(IPVK_IndirectCallTarget) << "\n";
+
+ if (ShowCounts) {
+ OS << " Block counts: [";
+ for (size_t I = 1, E = Func.Counts.size(); I < E; ++I) {
+ OS << (I == 1 ? "" : ", ") << Func.Counts[I];
+ }
+ OS << "]\n";
+ }
+
+ if (ShowIndirectCallTargets) {
+ InstrProfSymtab &Symtab = Reader->getSymtab();
+ uint32_t NS = Func.getNumValueSites(IPVK_IndirectCallTarget);
+ OS << " Indirect Target Results: \n";
+ for (size_t I = 0; I < NS; ++I) {
+ uint32_t NV = Func.getNumValueDataForSite(IPVK_IndirectCallTarget, I);
+ std::unique_ptr<InstrProfValueData[]> VD =
+ Func.getValueForSite(IPVK_IndirectCallTarget, I);
+ for (uint32_t V = 0; V < NV; V++) {
+ OS << "\t[ " << I << ", ";
+ OS << Symtab.getFuncName(VD[V].Value) << ", " << VD[V].Count
+ << " ]\n";
+ }
+ }
+ }
}
- if (Show && ShowCounts)
- OS << "]\n";
}
+
if (Reader->hasError())
- exitWithError(Reader->getError().message(), Filename);
+ exitWithErrorCode(Reader->getError(), Filename);
+
+ if (ShowCounts && TextFormat)
+ return 0;
if (ShowAllFunctions || !ShowFunction.empty())
OS << "Functions shown: " << ShownFunctions << "\n";
@@ -192,10 +344,12 @@ static int showSampleProfile(std::string Filename, bool ShowCounts,
using namespace sampleprof;
auto ReaderOrErr = SampleProfileReader::create(Filename, getGlobalContext());
if (std::error_code EC = ReaderOrErr.getError())
- exitWithError(EC.message(), Filename);
+ exitWithErrorCode(EC, Filename);
auto Reader = std::move(ReaderOrErr.get());
- Reader->read();
+ if (std::error_code EC = Reader->read())
+ exitWithErrorCode(EC, Filename);
+
if (ShowAllFunctions || ShowFunction.empty())
Reader->dump(OS);
else
@@ -210,6 +364,12 @@ static int show_main(int argc, const char *argv[]) {
cl::opt<bool> ShowCounts("counts", cl::init(false),
cl::desc("Show counter values for shown functions"));
+ cl::opt<bool> TextFormat(
+ "text", cl::init(false),
+ cl::desc("Show instr profile data in text dump format"));
+ cl::opt<bool> ShowIndirectCallTargets(
+ "ic-targets", cl::init(false),
+ cl::desc("Show indirect call site target values for shown functions"));
cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
cl::desc("Details for every function"));
cl::opt<std::string> ShowFunction("function",
@@ -232,14 +392,14 @@ static int show_main(int argc, const char *argv[]) {
std::error_code EC;
raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::F_Text);
if (EC)
- exitWithError(EC.message(), OutputFilename);
+ exitWithErrorCode(EC, OutputFilename);
if (ShowAllFunctions && !ShowFunction.empty())
errs() << "warning: -function argument ignored: showing all functions\n";
if (ProfileKind == instr)
- return showInstrProfile(Filename, ShowCounts, ShowAllFunctions,
- ShowFunction, OS);
+ return showInstrProfile(Filename, ShowCounts, ShowIndirectCallTargets,
+ ShowAllFunctions, ShowFunction, TextFormat, OS);
else
return showSampleProfile(Filename, ShowCounts, ShowAllFunctions,
ShowFunction, OS);
@@ -266,8 +426,7 @@ int main(int argc, const char *argv[]) {
return func(argc - 1, argv + 1);
}
- if (strcmp(argv[1], "-h") == 0 ||
- strcmp(argv[1], "-help") == 0 ||
+ if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-help") == 0 ||
strcmp(argv[1], "--help") == 0) {
errs() << "OVERVIEW: LLVM profile data tools\n\n"
diff --git a/contrib/llvm/tools/llvm-readobj/ARMAttributeParser.cpp b/contrib/llvm/tools/llvm-readobj/ARMAttributeParser.cpp
index e2d7191..688d349 100644
--- a/contrib/llvm/tools/llvm-readobj/ARMAttributeParser.cpp
+++ b/contrib/llvm/tools/llvm-readobj/ARMAttributeParser.cpp
@@ -118,7 +118,7 @@ void ARMAttributeParser::PrintAttribute(unsigned Tag, unsigned Value,
void ARMAttributeParser::CPU_arch(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", "ARM v6",
"ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", "ARM v6S-M",
"ARM v7E-M", "ARM v8"
@@ -149,7 +149,7 @@ void ARMAttributeParser::CPU_arch_profile(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ARM_ISA_use(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Not Permitted", "Permitted" };
+ static const char *const Strings[] = { "Not Permitted", "Permitted" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -159,7 +159,7 @@ void ARMAttributeParser::ARM_ISA_use(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::THUMB_ISA_use(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Not Permitted", "Thumb-1", "Thumb-2" };
+ static const char *const Strings[] = { "Not Permitted", "Thumb-1", "Thumb-2" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -169,7 +169,7 @@ void ARMAttributeParser::THUMB_ISA_use(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::FP_arch(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"Not Permitted", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4",
"VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16"
};
@@ -182,7 +182,7 @@ void ARMAttributeParser::FP_arch(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::WMMX_arch(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Not Permitted", "WMMXv1", "WMMXv2" };
+ static const char *const Strings[] = { "Not Permitted", "WMMXv1", "WMMXv2" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -192,8 +192,8 @@ void ARMAttributeParser::WMMX_arch(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::Advanced_SIMD_arch(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
- "Not Permitted", "NEONv1", "NEONv2+FMA", "ARMv8-a NEON"
+ static const char *const Strings[] = {
+ "Not Permitted", "NEONv1", "NEONv2+FMA", "ARMv8-a NEON", "ARMv8.1-a NEON"
};
uint64_t Value = ParseInteger(Data, Offset);
@@ -204,7 +204,7 @@ void ARMAttributeParser::Advanced_SIMD_arch(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::PCS_config(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"None", "Bare Platform", "Linux Application", "Linux DSO", "Palm OS 2004",
"Reserved (Palm OS)", "Symbian OS 2004", "Reserved (Symbian OS)"
};
@@ -217,7 +217,7 @@ void ARMAttributeParser::PCS_config(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_PCS_R9_use(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "v6", "Static Base", "TLS", "Unused" };
+ static const char *const Strings[] = { "v6", "Static Base", "TLS", "Unused" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -227,7 +227,7 @@ void ARMAttributeParser::ABI_PCS_R9_use(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_PCS_RW_data(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"Absolute", "PC-relative", "SB-relative", "Not Permitted"
};
@@ -239,7 +239,9 @@ void ARMAttributeParser::ABI_PCS_RW_data(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_PCS_RO_data(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Absolute", "PC-relative", "Not Permitted" };
+ static const char *const Strings[] = {
+ "Absolute", "PC-relative", "Not Permitted"
+ };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -249,7 +251,9 @@ void ARMAttributeParser::ABI_PCS_RO_data(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_PCS_GOT_use(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Not Permitted", "Direct", "GOT-Indirect" };
+ static const char *const Strings[] = {
+ "Not Permitted", "Direct", "GOT-Indirect"
+ };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -259,7 +263,7 @@ void ARMAttributeParser::ABI_PCS_GOT_use(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_PCS_wchar_t(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"Not Permitted", "Unknown", "2-byte", "Unknown", "4-byte"
};
@@ -271,7 +275,7 @@ void ARMAttributeParser::ABI_PCS_wchar_t(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_FP_rounding(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "IEEE-754", "Runtime" };
+ static const char *const Strings[] = { "IEEE-754", "Runtime" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -281,7 +285,9 @@ void ARMAttributeParser::ABI_FP_rounding(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_FP_denormal(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Unsupported", "IEEE-754", "Sign Only" };
+ static const char *const Strings[] = {
+ "Unsupported", "IEEE-754", "Sign Only"
+ };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -291,7 +297,7 @@ void ARMAttributeParser::ABI_FP_denormal(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_FP_exceptions(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Not Permitted", "IEEE-754" };
+ static const char *const Strings[] = { "Not Permitted", "IEEE-754" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -302,7 +308,7 @@ void ARMAttributeParser::ABI_FP_exceptions(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_FP_user_exceptions(AttrType Tag,
const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Not Permitted", "IEEE-754" };
+ static const char *const Strings[] = { "Not Permitted", "IEEE-754" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -312,7 +318,7 @@ void ARMAttributeParser::ABI_FP_user_exceptions(AttrType Tag,
void ARMAttributeParser::ABI_FP_number_model(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"Not Permitted", "Finite Only", "RTABI", "IEEE-754"
};
@@ -324,7 +330,7 @@ void ARMAttributeParser::ABI_FP_number_model(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_align_needed(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"Not Permitted", "8-byte alignment", "4-byte alignment", "Reserved"
};
@@ -344,7 +350,7 @@ void ARMAttributeParser::ABI_align_needed(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_align_preserved(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"Not Required", "8-byte data alignment", "8-byte data and code alignment",
"Reserved"
};
@@ -365,7 +371,7 @@ void ARMAttributeParser::ABI_align_preserved(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_enum_size(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"Not Permitted", "Packed", "Int32", "External Int32"
};
@@ -377,7 +383,7 @@ void ARMAttributeParser::ABI_enum_size(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_HardFP_use(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"Tag_FP_arch", "Single-Precision", "Reserved", "Tag_FP_arch (deprecated)"
};
@@ -389,7 +395,7 @@ void ARMAttributeParser::ABI_HardFP_use(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_VFP_args(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"AAPCS", "AAPCS VFP", "Custom", "Not Permitted"
};
@@ -401,7 +407,7 @@ void ARMAttributeParser::ABI_VFP_args(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_WMMX_args(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "AAPCS", "iWMMX", "Custom" };
+ static const char *const Strings[] = { "AAPCS", "iWMMX", "Custom" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -412,7 +418,7 @@ void ARMAttributeParser::ABI_WMMX_args(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_optimization_goals(AttrType Tag,
const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Debugging",
"Best Debugging"
};
@@ -426,7 +432,7 @@ void ARMAttributeParser::ABI_optimization_goals(AttrType Tag,
void ARMAttributeParser::ABI_FP_optimization_goals(AttrType Tag,
const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Accuracy",
"Best Accuracy"
};
@@ -461,7 +467,7 @@ void ARMAttributeParser::compatibility(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::CPU_unaligned_access(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Not Permitted", "v6-style" };
+ static const char *const Strings[] = { "Not Permitted", "v6-style" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -471,7 +477,7 @@ void ARMAttributeParser::CPU_unaligned_access(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::FP_HP_extension(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "If Available", "Permitted" };
+ static const char *const Strings[] = { "If Available", "Permitted" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -481,7 +487,7 @@ void ARMAttributeParser::FP_HP_extension(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::ABI_FP_16bit_format(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Not Permitted", "IEEE-754", "VFPv3" };
+ static const char *const Strings[] = { "Not Permitted", "IEEE-754", "VFPv3" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -491,7 +497,7 @@ void ARMAttributeParser::ABI_FP_16bit_format(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::MPextension_use(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Not Permitted", "Permitted" };
+ static const char *const Strings[] = { "Not Permitted", "Permitted" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -501,7 +507,7 @@ void ARMAttributeParser::MPextension_use(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::DIV_use(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"If Available", "Not Permitted", "Permitted"
};
@@ -513,7 +519,7 @@ void ARMAttributeParser::DIV_use(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::T2EE_use(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = { "Not Permitted", "Permitted" };
+ static const char *const Strings[] = { "Not Permitted", "Permitted" };
uint64_t Value = ParseInteger(Data, Offset);
StringRef ValueDesc =
@@ -523,7 +529,7 @@ void ARMAttributeParser::T2EE_use(AttrType Tag, const uint8_t *Data,
void ARMAttributeParser::Virtualization_use(AttrType Tag, const uint8_t *Data,
uint32_t &Offset) {
- static const char *Strings[] = {
+ static const char *const Strings[] = {
"Not Permitted", "TrustZone", "Virtualization Extensions",
"TrustZone + Virtualization Extensions"
};
diff --git a/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h b/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
index dd2490d..beb5fd4 100644
--- a/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
+++ b/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
@@ -305,13 +305,15 @@ void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset, size_t Length)
template <typename ET>
class PrinterContext {
- StreamWriter &SW;
- const object::ELFFile<ET> *ELF;
-
typedef typename object::ELFFile<ET>::Elf_Sym Elf_Sym;
typedef typename object::ELFFile<ET>::Elf_Shdr Elf_Shdr;
+ typedef typename object::ELFFile<ET>::Elf_Rel Elf_Rel;
+ typedef typename object::ELFFile<ET>::Elf_Word Elf_Word;
- typedef typename object::ELFFile<ET>::Elf_Rel_Iter Elf_Rel_iterator;
+ StreamWriter &SW;
+ const object::ELFFile<ET> *ELF;
+ const Elf_Shdr *Symtab;
+ ArrayRef<Elf_Word> ShndxTable;
static const size_t IndexTableEntrySize;
@@ -332,8 +334,9 @@ class PrinterContext {
void PrintOpcodes(const uint8_t *Entry, size_t Length, off_t Offset) const;
public:
- PrinterContext(StreamWriter &Writer, const object::ELFFile<ET> *File)
- : SW(Writer), ELF(File) {}
+ PrinterContext(StreamWriter &SW, const object::ELFFile<ET> *ELF,
+ const Elf_Shdr *Symtab)
+ : SW(SW), ELF(ELF), Symtab(Symtab) {}
void PrintUnwindInformation() const;
};
@@ -345,10 +348,14 @@ template <typename ET>
ErrorOr<StringRef>
PrinterContext<ET>::FunctionAtAddress(unsigned Section,
uint64_t Address) const {
- for (const Elf_Sym &Sym : ELF->symbols())
+ ErrorOr<StringRef> StrTableOrErr = ELF->getStringTableForSymtab(*Symtab);
+ error(StrTableOrErr.getError());
+ StringRef StrTable = *StrTableOrErr;
+
+ for (const Elf_Sym &Sym : ELF->symbols(Symtab))
if (Sym.st_shndx == Section && Sym.st_value == Address &&
Sym.getType() == ELF::STT_FUNC)
- return ELF->getSymbolName(&Sym, false);
+ return Sym.getName(StrTable);
return readobj_error::unknown_symbol;
}
@@ -365,24 +372,29 @@ PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex,
/// table.
for (const Elf_Shdr &Sec : ELF->sections()) {
- if (Sec.sh_type == ELF::SHT_REL && Sec.sh_info == IndexSectionIndex) {
- for (Elf_Rel_iterator RI = ELF->rel_begin(&Sec), RE = ELF->rel_end(&Sec);
- RI != RE; ++RI) {
- if (RI->r_offset == static_cast<unsigned>(IndexTableOffset)) {
- typename object::ELFFile<ET>::Elf_Rela RelA;
- RelA.r_offset = RI->r_offset;
- RelA.r_info = RI->r_info;
- RelA.r_addend = 0;
-
- std::pair<const Elf_Shdr *, const Elf_Sym *> Symbol =
- ELF->getRelocationSymbol(&Sec, &RelA);
-
- ErrorOr<const Elf_Shdr *> Ret = ELF->getSection(Symbol.second);
- if (std::error_code EC = Ret.getError())
- report_fatal_error(EC.message());
- return *Ret;
- }
- }
+ if (Sec.sh_type != ELF::SHT_REL || Sec.sh_info != IndexSectionIndex)
+ continue;
+
+ ErrorOr<const Elf_Shdr *> SymTabOrErr = ELF->getSection(Sec.sh_link);
+ error(SymTabOrErr.getError());
+ const Elf_Shdr *SymTab = *SymTabOrErr;
+
+ for (const Elf_Rel &R : ELF->rels(&Sec)) {
+ if (R.r_offset != static_cast<unsigned>(IndexTableOffset))
+ continue;
+
+ typename object::ELFFile<ET>::Elf_Rela RelA;
+ RelA.r_offset = R.r_offset;
+ RelA.r_info = R.r_info;
+ RelA.r_addend = 0;
+
+ const Elf_Sym *Symbol = ELF->getRelocationSymbol(&RelA, SymTab);
+
+ ErrorOr<const Elf_Shdr *> Ret =
+ ELF->getSection(Symbol, SymTab, ShndxTable);
+ if (std::error_code EC = Ret.getError())
+ report_fatal_error(EC.message());
+ return *Ret;
}
}
return nullptr;
diff --git a/contrib/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/contrib/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
index bf5ff8e..650955d 100644
--- a/contrib/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/contrib/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -630,9 +630,10 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
SW.printString("ExceptionRecord", formatSymbol(*Name, Address));
- section_iterator SI = COFF.section_end();
- if (XDataRecord->getSection(SI))
+ ErrorOr<section_iterator> SIOrErr = XDataRecord->getSection();
+ if (!SIOrErr)
return false;
+ section_iterator SI = *SIOrErr;
return dumpXDataRecord(COFF, *SI, FunctionAddress, Address);
} else {
diff --git a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp
index cf897d7..d44da0d 100644
--- a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -60,6 +60,7 @@ public:
void printCOFFExports() override;
void printCOFFDirectives() override;
void printCOFFBaseReloc() override;
+ void printCodeViewDebugInfo() override;
void printStackMap() const override;
private:
void printSymbol(const SymbolRef &Sym);
@@ -71,7 +72,7 @@ private:
void printBaseOfDataField(const pe32_header *Hdr);
void printBaseOfDataField(const pe32plus_header *Hdr);
- void printCodeViewDebugInfo(const SectionRef &Section);
+ void printCodeViewSection(const SectionRef &Section);
void printCodeViewSymbolsSubsection(StringRef Subsection,
const SectionRef &Section,
@@ -219,6 +220,7 @@ static const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
static const EnumEntry<COFF::SectionCharacteristics>
ImageSectionCharacteristics[] = {
+ LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NOLOAD ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_CODE ),
LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_INITIALIZED_DATA ),
@@ -385,14 +387,12 @@ void COFFDumper::printFileHeaders() {
// Print PE header. This header does not exist if this is an object file and
// not an executable.
const pe32_header *PEHeader = nullptr;
- if (error(Obj->getPE32Header(PEHeader)))
- return;
+ error(Obj->getPE32Header(PEHeader));
if (PEHeader)
printPEHeader<pe32_header>(PEHeader);
const pe32plus_header *PEPlusHeader = nullptr;
- if (error(Obj->getPE32PlusHeader(PEPlusHeader)))
- return;
+ error(Obj->getPE32PlusHeader(PEPlusHeader));
if (PEPlusHeader)
printPEHeader<pe32plus_header>(PEPlusHeader);
@@ -475,10 +475,18 @@ void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}
-void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
+void COFFDumper::printCodeViewDebugInfo() {
+ for (const SectionRef &S : Obj->sections()) {
+ StringRef SecName;
+ error(S.getName(SecName));
+ if (SecName == ".debug$S")
+ printCodeViewSection(S);
+ }
+}
+
+void COFFDumper::printCodeViewSection(const SectionRef &Section) {
StringRef Data;
- if (error(Section.getContents(Data)))
- return;
+ error(Section.getContents(Data));
SmallVector<StringRef, 10> FunctionNames;
StringMap<StringRef> FunctionLineTables;
@@ -518,8 +526,7 @@ void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
switch (SubSectionType) {
case COFF::DEBUG_SYMBOL_SUBSECTION:
- if (opts::SectionSymbols)
- printCodeViewSymbolsSubsection(Contents, Section, Offset);
+ printCodeViewSymbolsSubsection(Contents, Section, Offset);
break;
case COFF::DEBUG_LINE_TABLE_SUBSECTION: {
// Holds a PC to file:line table. Some data to parse this subsection is
@@ -533,19 +540,18 @@ void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
return;
}
- StringRef FunctionName;
- if (error(resolveSymbolName(Obj->getCOFFSection(Section), Offset,
- FunctionName)))
- return;
- W.printString("FunctionName", FunctionName);
- if (FunctionLineTables.count(FunctionName) != 0) {
+ StringRef LinkageName;
+ error(resolveSymbolName(Obj->getCOFFSection(Section), Offset,
+ LinkageName));
+ W.printString("LinkageName", LinkageName);
+ if (FunctionLineTables.count(LinkageName) != 0) {
// Saw debug info for this function already?
error(object_error::parse_failed);
return;
}
- FunctionLineTables[FunctionName] = Contents;
- FunctionNames.push_back(FunctionName);
+ FunctionLineTables[LinkageName] = Contents;
+ FunctionNames.push_back(LinkageName);
break;
}
case COFF::DEBUG_STRING_TABLE_SUBSECTION:
@@ -582,7 +588,7 @@ void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
for (unsigned I = 0, E = FunctionNames.size(); I != E; ++I) {
StringRef Name = FunctionNames[I];
ListScope S(W, "FunctionLineTable");
- W.printString("FunctionName", Name);
+ W.printString("LinkageName", Name);
DataExtractor DE(FunctionLineTables[Name], true, 4);
uint32_t Offset = 6; // Skip relocations.
@@ -597,12 +603,14 @@ void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
// in the line table. The filename string is accessed using double
// indirection to the string table subsection using the index subsection.
uint32_t OffsetInIndex = DE.getU32(&Offset),
- SegmentLength = DE.getU32(&Offset),
+ NumLines = DE.getU32(&Offset),
FullSegmentSize = DE.getU32(&Offset);
+ uint32_t ColumnOffset = Offset + 8 * NumLines;
+ DataExtractor ColumnDE(DE.getData(), true, 4);
+
if (FullSegmentSize !=
- 12 + 8 * SegmentLength +
- (HasColumnInformation ? 4 * SegmentLength : 0)) {
+ 12 + 8 * NumLines + (HasColumnInformation ? 4 * NumLines : 0)) {
error(object_error::parse_failed);
return;
}
@@ -629,29 +637,41 @@ void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
StringRef Filename(CVStringTable.data() + FilenameOffset);
ListScope S(W, "FilenameSegment");
W.printString("Filename", Filename);
- for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
- ++J) {
+ for (unsigned LineIdx = 0;
+ LineIdx != NumLines && DE.isValidOffset(Offset); ++LineIdx) {
// Then go the (PC, LineNumber) pairs. The line number is stored in the
// least significant 31 bits of the respective word in the table.
- uint32_t PC = DE.getU32(&Offset),
- LineNumber = DE.getU32(&Offset) & 0x7fffffff;
+ uint32_t PC = DE.getU32(&Offset), LineData = DE.getU32(&Offset);
if (PC >= FunctionSize) {
error(object_error::parse_failed);
return;
}
char Buffer[32];
format("+0x%X", PC).snprint(Buffer, 32);
- W.printNumber(Buffer, LineNumber);
- }
- if (HasColumnInformation) {
- for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
- ++J) {
- uint16_t ColStart = DE.getU16(&Offset);
+ ListScope PCScope(W, Buffer);
+ uint32_t LineNumberStart = LineData & COFF::CVL_MaxLineNumber;
+ uint32_t LineNumberEndDelta =
+ (LineData >> COFF::CVL_LineNumberStartBits) &
+ COFF::CVL_LineNumberEndDeltaMask;
+ bool IsStatement = LineData & COFF::CVL_IsStatement;
+ W.printNumber("LineNumberStart", LineNumberStart);
+ W.printNumber("LineNumberEndDelta", LineNumberEndDelta);
+ W.printBoolean("IsStatement", IsStatement);
+ if (HasColumnInformation &&
+ ColumnDE.isValidOffsetForDataOfSize(ColumnOffset, 4)) {
+ uint16_t ColStart = ColumnDE.getU16(&ColumnOffset);
W.printNumber("ColStart", ColStart);
- uint16_t ColEnd = DE.getU16(&Offset);
+ uint16_t ColEnd = ColumnDE.getU16(&ColumnOffset);
W.printNumber("ColEnd", ColEnd);
}
}
+ // Skip over the column data.
+ if (HasColumnInformation) {
+ for (unsigned LineIdx = 0;
+ LineIdx != NumLines && DE.isValidOffset(Offset); ++LineIdx) {
+ DE.getU32(&Offset);
+ }
+ }
}
}
}
@@ -695,9 +715,8 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
uint32_t CodeSize = DE.getU32(&Offset);
DE.getU8(&Offset, Unused, 12);
StringRef SectionName;
- if (error(resolveSymbolName(Obj->getCOFFSection(Section),
- OffsetInSection + Offset, SectionName)))
- return;
+ error(resolveSymbolName(Obj->getCOFFSection(Section),
+ OffsetInSection + Offset, SectionName));
Offset += 4;
DE.getU8(&Offset, Unused, 3);
StringRef DisplayName = DE.getCStr(&Offset);
@@ -748,8 +767,7 @@ void COFFDumper::printSections() {
const coff_section *Section = Obj->getCOFFSection(Sec);
StringRef Name;
- if (error(Sec.getName(Name)))
- Name = "";
+ error(Sec.getName(Name));
DictScope D(W, "Section");
W.printNumber("Number", SectionNumber);
@@ -782,14 +800,10 @@ void COFFDumper::printSections() {
}
}
- if (Name == ".debug$S" && opts::CodeView)
- printCodeViewDebugInfo(Sec);
-
if (opts::SectionData &&
!(Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) {
StringRef Data;
- if (error(Sec.getContents(Data)))
- break;
+ error(Sec.getContents(Data));
W.printBinaryBlock("SectionData", Data);
}
@@ -803,8 +817,7 @@ void COFFDumper::printRelocations() {
for (const SectionRef &Section : Obj->sections()) {
++SectionNumber;
StringRef Name;
- if (error(Section.getName(Name)))
- continue;
+ error(Section.getName(Name));
bool PrintedGroup = false;
for (const RelocationRef &Reloc : Section.relocations()) {
@@ -834,8 +847,7 @@ void COFFDumper::printRelocation(const SectionRef &Section,
symbol_iterator Symbol = Reloc.getSymbol();
if (Symbol != Obj->symbol_end()) {
ErrorOr<StringRef> SymbolNameOrErr = Symbol->getName();
- if (error(SymbolNameOrErr.getError()))
- return;
+ error(SymbolNameOrErr.getError());
SymbolName = *SymbolNameOrErr;
}
@@ -914,8 +926,7 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
for (uint8_t I = 0; I < Symbol.getNumberOfAuxSymbols(); ++I) {
if (Symbol.isFunctionDefinition()) {
const coff_aux_function_definition *Aux;
- if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
- break;
+ error(getSymbolAuxData(Obj, Symbol, I, Aux));
DictScope AS(W, "AuxFunctionDef");
W.printNumber("TagIndex", Aux->TagIndex);
@@ -925,8 +936,7 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
} else if (Symbol.isAnyUndefined()) {
const coff_aux_weak_external *Aux;
- if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
- break;
+ error(getSymbolAuxData(Obj, Symbol, I, Aux));
ErrorOr<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex);
StringRef LinkedName;
@@ -943,8 +953,7 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
} else if (Symbol.isFileRecord()) {
const char *FileName;
- if (error(getSymbolAuxData(Obj, Symbol, I, FileName)))
- break;
+ error(getSymbolAuxData(Obj, Symbol, I, FileName));
DictScope AS(W, "AuxFileRecord");
@@ -954,8 +963,7 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
break;
} else if (Symbol.isSectionDefinition()) {
const coff_aux_section_definition *Aux;
- if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
- break;
+ error(getSymbolAuxData(Obj, Symbol, I, Aux));
int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj());
@@ -986,8 +994,7 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
}
} else if (Symbol.isCLRToken()) {
const coff_aux_clr_token *Aux;
- if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
- break;
+ error(getSymbolAuxData(Obj, Symbol, I, Aux));
ErrorOr<COFFSymbolRef> ReferredSym =
Obj->getSymbol(Aux->SymbolTableIndex);
@@ -1040,9 +1047,9 @@ void COFFDumper::printImportedSymbols(
iterator_range<imported_symbol_iterator> Range) {
for (const ImportedSymbolRef &I : Range) {
StringRef Sym;
- if (error(I.getSymbolName(Sym))) return;
+ error(I.getSymbolName(Sym));
uint16_t Ordinal;
- if (error(I.getOrdinal(Ordinal))) return;
+ error(I.getOrdinal(Ordinal));
W.printNumber("Symbol", Sym, Ordinal);
}
}
@@ -1054,12 +1061,12 @@ void COFFDumper::printDelayImportedSymbols(
for (const ImportedSymbolRef &S : Range) {
DictScope Import(W, "Import");
StringRef Sym;
- if (error(S.getSymbolName(Sym))) return;
+ error(S.getSymbolName(Sym));
uint16_t Ordinal;
- if (error(S.getOrdinal(Ordinal))) return;
+ error(S.getOrdinal(Ordinal));
W.printNumber("Symbol", Sym, Ordinal);
uint64_t Addr;
- if (error(I.getImportAddress(Index++, Addr))) return;
+ error(I.getImportAddress(Index++, Addr));
W.printHex("Address", Addr);
}
}
@@ -1069,12 +1076,12 @@ void COFFDumper::printCOFFImports() {
for (const ImportDirectoryEntryRef &I : Obj->import_directories()) {
DictScope Import(W, "Import");
StringRef Name;
- if (error(I.getName(Name))) return;
+ error(I.getName(Name));
W.printString("Name", Name);
uint32_t Addr;
- if (error(I.getImportLookupTableRVA(Addr))) return;
+ error(I.getImportLookupTableRVA(Addr));
W.printHex("ImportLookupTableRVA", Addr);
- if (error(I.getImportAddressTableRVA(Addr))) return;
+ error(I.getImportAddressTableRVA(Addr));
W.printHex("ImportAddressTableRVA", Addr);
printImportedSymbols(I.imported_symbols());
}
@@ -1083,10 +1090,10 @@ void COFFDumper::printCOFFImports() {
for (const DelayImportDirectoryEntryRef &I : Obj->delay_import_directories()) {
DictScope Import(W, "DelayImport");
StringRef Name;
- if (error(I.getName(Name))) return;
+ error(I.getName(Name));
W.printString("Name", Name);
const delay_import_directory_table_entry *Table;
- if (error(I.getDelayImportTable(Table))) return;
+ error(I.getDelayImportTable(Table));
W.printHex("Attributes", Table->Attributes);
W.printHex("ModuleHandle", Table->ModuleHandle);
W.printHex("ImportAddressTable", Table->DelayImportAddressTable);
@@ -1104,12 +1111,9 @@ void COFFDumper::printCOFFExports() {
StringRef Name;
uint32_t Ordinal, RVA;
- if (error(E.getSymbolName(Name)))
- continue;
- if (error(E.getOrdinal(Ordinal)))
- continue;
- if (error(E.getExportRVA(RVA)))
- continue;
+ error(E.getSymbolName(Name));
+ error(E.getOrdinal(Ordinal));
+ error(E.getExportRVA(RVA));
W.printNumber("Ordinal", Ordinal);
W.printString("Name", Name);
@@ -1122,13 +1126,11 @@ void COFFDumper::printCOFFDirectives() {
StringRef Contents;
StringRef Name;
- if (error(Section.getName(Name)))
- continue;
+ error(Section.getName(Name));
if (Name != ".drectve")
continue;
- if (error(Section.getContents(Contents)))
- return;
+ error(Section.getContents(Contents));
W.printString("Directive(s)", Contents);
}
@@ -1152,10 +1154,8 @@ void COFFDumper::printCOFFBaseReloc() {
for (const BaseRelocRef &I : Obj->base_relocs()) {
uint8_t Type;
uint32_t RVA;
- if (error(I.getRVA(RVA)))
- continue;
- if (error(I.getType(Type)))
- continue;
+ error(I.getRVA(RVA));
+ error(I.getType(Type));
DictScope Import(W, "Entry");
W.printString("Type", getBaseRelocTypeName(Type));
W.printHex("Address", RVA);
diff --git a/contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp b/contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp
new file mode 100644
index 0000000..83715e6
--- /dev/null
+++ b/contrib/llvm/tools/llvm-readobj/COFFImportDumper.cpp
@@ -0,0 +1,52 @@
+//===-- COFFImportDumper.cpp - COFF import library dumper -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file implements the COFF import library dumper for llvm-readobj.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Error.h"
+#include "ObjDumper.h"
+#include "llvm-readobj.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/COFFImportFile.h"
+#include "llvm/Support/COFF.h"
+
+using namespace llvm::object;
+
+namespace llvm {
+
+void dumpCOFFImportFile(const COFFImportFile *File) {
+ outs() << '\n';
+ outs() << "File: " << File->getFileName() << "\n";
+ outs() << "Format: COFF-import-file\n";
+
+ const coff_import_header *H = File->getCOFFImportHeader();
+ switch (H->getType()) {
+ case COFF::IMPORT_CODE: outs() << "Type: code\n"; break;
+ case COFF::IMPORT_DATA: outs() << "Type: data\n"; break;
+ case COFF::IMPORT_CONST: outs() << "Type: const\n"; break;
+ }
+
+ switch (H->getNameType()) {
+ case COFF::IMPORT_ORDINAL: outs() << "Name type: ordinal\n"; break;
+ case COFF::IMPORT_NAME: outs() << "Name type: name\n"; break;
+ case COFF::IMPORT_NAME_NOPREFIX: outs() << "Name type: noprefix\n"; break;
+ case COFF::IMPORT_NAME_UNDECORATE: outs() << "Name type: undecorate\n"; break;
+ }
+
+ for (const object::BasicSymbolRef &Sym : File->symbols()) {
+ outs() << "Symbol: ";
+ Sym.printName(outs());
+ outs() << "\n";
+ }
+}
+
+} // namespace llvm
diff --git a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp
index 1cdf552..be84f3c 100644
--- a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -42,8 +42,7 @@ namespace {
template<typename ELFT>
class ELFDumper : public ObjDumper {
public:
- ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer)
- : ObjDumper(Writer), Obj(Obj) {}
+ ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer);
void printFileHeaders() override;
void printSections() override;
@@ -57,6 +56,9 @@ public:
void printNeededLibraries() override;
void printProgramHeaders() override;
void printHashTable() override;
+ void printGnuHashTable() override;
+ void printLoadName() override;
+ void printVersionInfo() override;
void printAttributes() override;
void printMipsPLTGOT() override;
@@ -69,13 +71,114 @@ private:
typedef ELFFile<ELFT> ELFO;
typedef typename ELFO::Elf_Shdr Elf_Shdr;
typedef typename ELFO::Elf_Sym Elf_Sym;
-
- void printSymbol(const Elf_Sym *Symbol, bool IsDynamic);
+ typedef typename ELFO::Elf_Dyn Elf_Dyn;
+ typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range;
+ typedef typename ELFO::Elf_Rel Elf_Rel;
+ typedef typename ELFO::Elf_Rela Elf_Rela;
+ typedef typename ELFO::Elf_Rela_Range Elf_Rela_Range;
+ typedef typename ELFO::Elf_Phdr Elf_Phdr;
+ typedef typename ELFO::Elf_Half Elf_Half;
+ typedef typename ELFO::Elf_Hash Elf_Hash;
+ typedef typename ELFO::Elf_GnuHash Elf_GnuHash;
+ typedef typename ELFO::Elf_Ehdr Elf_Ehdr;
+ typedef typename ELFO::Elf_Word Elf_Word;
+ typedef typename ELFO::uintX_t uintX_t;
+ typedef typename ELFO::Elf_Versym Elf_Versym;
+ typedef typename ELFO::Elf_Verneed Elf_Verneed;
+ typedef typename ELFO::Elf_Vernaux Elf_Vernaux;
+ typedef typename ELFO::Elf_Verdef Elf_Verdef;
+ typedef typename ELFO::Elf_Verdaux Elf_Verdaux;
+
+ /// \brief Represents a region described by entries in the .dynamic table.
+ struct DynRegionInfo {
+ DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {}
+ /// \brief Address in current address space.
+ const void *Addr;
+ /// \brief Size in bytes of the region.
+ uintX_t Size;
+ /// \brief Size of each entity in the region.
+ uintX_t EntSize;
+ };
+
+ void printSymbolsHelper(bool IsDynamic);
+ void printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab,
+ StringRef StrTable, bool IsDynamic);
void printRelocations(const Elf_Shdr *Sec);
- void printRelocation(const Elf_Shdr *Sec, typename ELFO::Elf_Rela Rel);
+ void printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab);
+ void printValue(uint64_t Type, uint64_t Value);
+
+ const Elf_Rela *dyn_rela_begin() const;
+ const Elf_Rela *dyn_rela_end() const;
+ Elf_Rela_Range dyn_relas() const;
+ StringRef getDynamicString(uint64_t Offset) const;
+ const Elf_Dyn *dynamic_table_begin() const {
+ ErrorOr<const Elf_Dyn *> Ret = Obj->dynamic_table_begin(DynamicProgHeader);
+ error(Ret.getError());
+ return *Ret;
+ }
+ const Elf_Dyn *dynamic_table_end() const {
+ ErrorOr<const Elf_Dyn *> Ret = Obj->dynamic_table_end(DynamicProgHeader);
+ error(Ret.getError());
+ return *Ret;
+ }
+ StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb,
+ bool &IsDefault);
+ void LoadVersionMap();
+ void LoadVersionNeeds(const Elf_Shdr *ec) const;
+ void LoadVersionDefs(const Elf_Shdr *sec) const;
const ELFO *Obj;
+ DynRegionInfo DynRelaRegion;
+ const Elf_Phdr *DynamicProgHeader = nullptr;
+ StringRef DynamicStringTable;
+ const Elf_Sym *DynSymStart = nullptr;
+ StringRef SOName;
+ const Elf_Hash *HashTable = nullptr;
+ const Elf_GnuHash *GnuHashTable = nullptr;
+ const Elf_Shdr *DotDynSymSec = nullptr;
+ const Elf_Shdr *DotSymtabSec = nullptr;
+ ArrayRef<Elf_Word> ShndxTable;
+
+ const Elf_Shdr *dot_gnu_version_sec = nullptr; // .gnu.version
+ const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r
+ const Elf_Shdr *dot_gnu_version_d_sec = nullptr; // .gnu.version_d
+
+ // Records for each version index the corresponding Verdef or Vernaux entry.
+ // This is filled the first time LoadVersionMap() is called.
+ class VersionMapEntry : public PointerIntPair<const void *, 1> {
+ public:
+ // If the integer is 0, this is an Elf_Verdef*.
+ // If the integer is 1, this is an Elf_Vernaux*.
+ VersionMapEntry() : PointerIntPair<const void *, 1>(nullptr, 0) {}
+ VersionMapEntry(const Elf_Verdef *verdef)
+ : PointerIntPair<const void *, 1>(verdef, 0) {}
+ VersionMapEntry(const Elf_Vernaux *vernaux)
+ : PointerIntPair<const void *, 1>(vernaux, 1) {}
+ bool isNull() const { return getPointer() == nullptr; }
+ bool isVerdef() const { return !isNull() && getInt() == 0; }
+ bool isVernaux() const { return !isNull() && getInt() == 1; }
+ const Elf_Verdef *getVerdef() const {
+ return isVerdef() ? (const Elf_Verdef *)getPointer() : nullptr;
+ }
+ const Elf_Vernaux *getVernaux() const {
+ return isVernaux() ? (const Elf_Vernaux *)getPointer() : nullptr;
+ }
+ };
+ mutable SmallVector<VersionMapEntry, 16> VersionMap;
+
+public:
+ Elf_Dyn_Range dynamic_table() const {
+ ErrorOr<Elf_Dyn_Range> Ret = Obj->dynamic_table(DynamicProgHeader);
+ error(Ret.getError());
+ return *Ret;
+ }
+
+ std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,
+ bool IsDynamic);
+ const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; }
+ const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
+ ArrayRef<Elf_Word> getShndxTable() { return ShndxTable; }
};
template <class T> T errorOrDefault(ErrorOr<T> Val, T Default = T()) {
@@ -122,30 +225,246 @@ std::error_code createELFDumper(const object::ObjectFile *Obj,
} // namespace llvm
-template <typename ELFO>
-static std::string getFullSymbolName(const ELFO &Obj,
- const typename ELFO::Elf_Sym *Symbol,
- bool IsDynamic) {
- StringRef SymbolName = errorOrDefault(Obj.getSymbolName(Symbol, IsDynamic));
+// Iterate through the versions needed section, and place each Elf_Vernaux
+// in the VersionMap according to its index.
+template <class ELFT>
+void ELFDumper<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const {
+ unsigned vn_size = sec->sh_size; // Size of section in bytes
+ unsigned vn_count = sec->sh_info; // Number of Verneed entries
+ const char *sec_start = (const char *)Obj->base() + sec->sh_offset;
+ const char *sec_end = sec_start + vn_size;
+ // The first Verneed entry is at the start of the section.
+ const char *p = sec_start;
+ for (unsigned i = 0; i < vn_count; i++) {
+ if (p + sizeof(Elf_Verneed) > sec_end)
+ report_fatal_error("Section ended unexpectedly while scanning "
+ "version needed records.");
+ const Elf_Verneed *vn = reinterpret_cast<const Elf_Verneed *>(p);
+ if (vn->vn_version != ELF::VER_NEED_CURRENT)
+ report_fatal_error("Unexpected verneed version");
+ // Iterate through the Vernaux entries
+ const char *paux = p + vn->vn_aux;
+ for (unsigned j = 0; j < vn->vn_cnt; j++) {
+ if (paux + sizeof(Elf_Vernaux) > sec_end)
+ report_fatal_error("Section ended unexpected while scanning auxiliary "
+ "version needed records.");
+ const Elf_Vernaux *vna = reinterpret_cast<const Elf_Vernaux *>(paux);
+ size_t index = vna->vna_other & ELF::VERSYM_VERSION;
+ if (index >= VersionMap.size())
+ VersionMap.resize(index + 1);
+ VersionMap[index] = VersionMapEntry(vna);
+ paux += vna->vna_next;
+ }
+ p += vn->vn_next;
+ }
+}
+
+// Iterate through the version definitions, and place each Elf_Verdef
+// in the VersionMap according to its index.
+template <class ELFT>
+void ELFDumper<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const {
+ unsigned vd_size = sec->sh_size; // Size of section in bytes
+ unsigned vd_count = sec->sh_info; // Number of Verdef entries
+ const char *sec_start = (const char *)Obj->base() + sec->sh_offset;
+ const char *sec_end = sec_start + vd_size;
+ // The first Verdef entry is at the start of the section.
+ const char *p = sec_start;
+ for (unsigned i = 0; i < vd_count; i++) {
+ if (p + sizeof(Elf_Verdef) > sec_end)
+ report_fatal_error("Section ended unexpectedly while scanning "
+ "version definitions.");
+ const Elf_Verdef *vd = reinterpret_cast<const Elf_Verdef *>(p);
+ if (vd->vd_version != ELF::VER_DEF_CURRENT)
+ report_fatal_error("Unexpected verdef version");
+ size_t index = vd->vd_ndx & ELF::VERSYM_VERSION;
+ if (index >= VersionMap.size())
+ VersionMap.resize(index + 1);
+ VersionMap[index] = VersionMapEntry(vd);
+ p += vd->vd_next;
+ }
+}
+
+template <class ELFT> void ELFDumper<ELFT>::LoadVersionMap() {
+ // If there is no dynamic symtab or version table, there is nothing to do.
+ if (!DynSymStart || !dot_gnu_version_sec)
+ return;
+
+ // Has the VersionMap already been loaded?
+ if (VersionMap.size() > 0)
+ return;
+
+ // The first two version indexes are reserved.
+ // Index 0 is LOCAL, index 1 is GLOBAL.
+ VersionMap.push_back(VersionMapEntry());
+ VersionMap.push_back(VersionMapEntry());
+
+ if (dot_gnu_version_d_sec)
+ LoadVersionDefs(dot_gnu_version_d_sec);
+
+ if (dot_gnu_version_r_sec)
+ LoadVersionNeeds(dot_gnu_version_r_sec);
+}
+
+
+template <typename ELFO, class ELFT>
+static void printVersionSymbolSection(ELFDumper<ELFT> *Dumper,
+ const ELFO *Obj,
+ const typename ELFO::Elf_Shdr *Sec,
+ StreamWriter &W) {
+ DictScope SS(W, "Version symbols");
+ if (!Sec)
+ return;
+ StringRef Name = errorOrDefault(Obj->getSectionName(Sec));
+ W.printNumber("Section Name", Name, Sec->sh_name);
+ W.printHex("Address", Sec->sh_addr);
+ W.printHex("Offset", Sec->sh_offset);
+ W.printNumber("Link", Sec->sh_link);
+
+ const typename ELFO::Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec();
+ const uint8_t *P = (const uint8_t *)Obj->base() + Sec->sh_offset;
+ ErrorOr<StringRef> StrTableOrErr =
+ Obj->getStringTableForSymtab(*DynSymSec);
+ error(StrTableOrErr.getError());
+
+ // Same number of entries in the dynamic symbol table (DT_SYMTAB).
+ ListScope Syms(W, "Symbols");
+ for (const typename ELFO::Elf_Sym &Sym : Obj->symbols(DynSymSec)) {
+ DictScope S(W, "Symbol");
+ std::string FullSymbolName =
+ Dumper->getFullSymbolName(&Sym, *StrTableOrErr, true /* IsDynamic */);
+ W.printNumber("Version", *P);
+ W.printString("Name", FullSymbolName);
+ P += sizeof(typename ELFO::Elf_Half);
+ }
+}
+
+template <typename ELFO, class ELFT>
+static void printVersionDefinitionSection(ELFDumper<ELFT> *Dumper,
+ const ELFO *Obj,
+ const typename ELFO::Elf_Shdr *Sec,
+ StreamWriter &W) {
+ DictScope SD(W, "Version definition");
+ if (!Sec)
+ return;
+ StringRef Name = errorOrDefault(Obj->getSectionName(Sec));
+ W.printNumber("Section Name", Name, Sec->sh_name);
+ W.printHex("Address", Sec->sh_addr);
+ W.printHex("Offset", Sec->sh_offset);
+ W.printNumber("Link", Sec->sh_link);
+
+ unsigned verdef_entries = 0;
+ // The number of entries in the section SHT_GNU_verdef
+ // is determined by DT_VERDEFNUM tag.
+ for (const typename ELFO::Elf_Dyn &Dyn : Dumper->dynamic_table()) {
+ if (Dyn.d_tag == DT_VERDEFNUM)
+ verdef_entries = Dyn.d_un.d_val;
+ }
+ const uint8_t *SecStartAddress =
+ (const uint8_t *)Obj->base() + Sec->sh_offset;
+ const uint8_t *SecEndAddress = SecStartAddress + Sec->sh_size;
+ const uint8_t *P = SecStartAddress;
+ ErrorOr<const typename ELFO::Elf_Shdr *> StrTabOrErr =
+ Obj->getSection(Sec->sh_link);
+ error(StrTabOrErr.getError());
+
+ ListScope Entries(W, "Entries");
+ for (unsigned i = 0; i < verdef_entries; ++i) {
+ if (P + sizeof(typename ELFO::Elf_Verdef) > SecEndAddress)
+ report_fatal_error("invalid offset in the section");
+ auto *VD = reinterpret_cast<const typename ELFO::Elf_Verdef *>(P);
+ DictScope Entry(W, "Entry");
+ W.printHex("Offset", (uintptr_t)P - (uintptr_t)SecStartAddress);
+ W.printNumber("Rev", VD->vd_version);
+ // FIXME: print something more readable.
+ W.printNumber("Flags", VD->vd_flags);
+ W.printNumber("Index", VD->vd_ndx);
+ W.printNumber("Cnt", VD->vd_cnt);
+ W.printString("Name", StringRef((const char *)(Obj->base() +
+ (*StrTabOrErr)->sh_offset +
+ VD->getAux()->vda_name)));
+ P += VD->vd_next;
+ }
+}
+
+template <typename ELFT> void ELFDumper<ELFT>::printVersionInfo() {
+ // Dump version symbol section.
+ printVersionSymbolSection(this, Obj, dot_gnu_version_sec, W);
+
+ // Dump version definition section.
+ printVersionDefinitionSection(this, Obj, dot_gnu_version_d_sec, W);
+}
+
+template <typename ELFT>
+StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab,
+ const Elf_Sym *symb,
+ bool &IsDefault) {
+ // This is a dynamic symbol. Look in the GNU symbol version table.
+ if (!dot_gnu_version_sec) {
+ // No version table.
+ IsDefault = false;
+ return StringRef("");
+ }
+
+ // Determine the position in the symbol table of this entry.
+ size_t entry_index = (reinterpret_cast<uintptr_t>(symb) -
+ reinterpret_cast<uintptr_t>(DynSymStart)) /
+ sizeof(Elf_Sym);
+
+ // Get the corresponding version index entry
+ const Elf_Versym *vs =
+ Obj->template getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index);
+ size_t version_index = vs->vs_index & ELF::VERSYM_VERSION;
+
+ // Special markers for unversioned symbols.
+ if (version_index == ELF::VER_NDX_LOCAL ||
+ version_index == ELF::VER_NDX_GLOBAL) {
+ IsDefault = false;
+ return StringRef("");
+ }
+
+ // Lookup this symbol in the version table
+ LoadVersionMap();
+ if (version_index >= VersionMap.size() || VersionMap[version_index].isNull())
+ reportError("Invalid version entry");
+ const VersionMapEntry &entry = VersionMap[version_index];
+
+ // Get the version name string
+ size_t name_offset;
+ if (entry.isVerdef()) {
+ // The first Verdaux entry holds the name.
+ name_offset = entry.getVerdef()->getAux()->vda_name;
+ IsDefault = !(vs->vs_index & ELF::VERSYM_HIDDEN);
+ } else {
+ name_offset = entry.getVernaux()->vna_name;
+ IsDefault = false;
+ }
+ if (name_offset >= StrTab.size())
+ reportError("Invalid string offset");
+ return StringRef(StrTab.data() + name_offset);
+}
+
+template <typename ELFT>
+std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol,
+ StringRef StrTable,
+ bool IsDynamic) {
+ StringRef SymbolName = errorOrDefault(Symbol->getName(StrTable));
if (!IsDynamic)
return SymbolName;
std::string FullSymbolName(SymbolName);
bool IsDefault;
- ErrorOr<StringRef> Version =
- Obj.getSymbolVersion(nullptr, &*Symbol, IsDefault);
- if (Version) {
- FullSymbolName += (IsDefault ? "@@" : "@");
- FullSymbolName += *Version;
- } else
- error(Version.getError());
+ StringRef Version = getSymbolVersion(StrTable, &*Symbol, IsDefault);
+ FullSymbolName += (IsDefault ? "@@" : "@");
+ FullSymbolName += Version;
return FullSymbolName;
}
template <typename ELFO>
static void
getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol,
+ const typename ELFO::Elf_Shdr *SymTab,
+ ArrayRef<typename ELFO::Elf_Word> ShndxTable,
StringRef &SectionName, unsigned &SectionIndex) {
SectionIndex = Symbol->st_shndx;
if (Symbol->isUndefined())
@@ -162,25 +481,26 @@ getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol,
SectionName = "Reserved";
else {
if (SectionIndex == SHN_XINDEX)
- SectionIndex = Obj.getExtendedSymbolTableIndex(&*Symbol);
+ SectionIndex =
+ Obj.getExtendedSymbolTableIndex(Symbol, SymTab, ShndxTable);
ErrorOr<const typename ELFO::Elf_Shdr *> Sec = Obj.getSection(SectionIndex);
- if (!error(Sec.getError()))
- SectionName = errorOrDefault(Obj.getSectionName(*Sec));
+ error(Sec.getError());
+ SectionName = errorOrDefault(Obj.getSectionName(*Sec));
}
}
-template <class ELFT>
-static const typename ELFFile<ELFT>::Elf_Shdr *
-findSectionByAddress(const ELFFile<ELFT> *Obj, uint64_t Addr) {
+template <class ELFO>
+static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO *Obj,
+ uint64_t Addr) {
for (const auto &Shdr : Obj->sections())
if (Shdr.sh_addr == Addr)
return &Shdr;
return nullptr;
}
-template <class ELFT>
-static const typename ELFFile<ELFT>::Elf_Shdr *
-findSectionByName(const ELFFile<ELFT> &Obj, StringRef Name) {
+template <class ELFO>
+static const typename ELFO::Elf_Shdr *findSectionByName(const ELFO &Obj,
+ StringRef Name) {
for (const auto &Shdr : Obj.sections()) {
if (Name == errorOrDefault(Obj.getSectionName(&Shdr)))
return &Shdr;
@@ -388,7 +708,8 @@ static const EnumEntry<unsigned> ElfMachineType[] = {
LLVM_READOBJ_ENUM_ENT(ELF, EM_VIDEOCORE5 ),
LLVM_READOBJ_ENUM_ENT(ELF, EM_78KOR ),
LLVM_READOBJ_ENUM_ENT(ELF, EM_56800EX ),
- LLVM_READOBJ_ENUM_ENT(ELF, EM_AMDGPU )
+ LLVM_READOBJ_ENUM_ENT(ELF, EM_AMDGPU ),
+ LLVM_READOBJ_ENUM_ENT(ELF, EM_WEBASSEMBLY ),
};
static const EnumEntry<unsigned> ElfSymbolBindings[] = {
@@ -409,6 +730,12 @@ static const EnumEntry<unsigned> ElfSymbolTypes[] = {
{ "GNU_IFunc", ELF::STT_GNU_IFUNC }
};
+static const EnumEntry<unsigned> AMDGPUSymbolTypes[] = {
+ { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL },
+ { "AMDGPU_HSA_INDIRECT_FUNCTION", ELF::STT_AMDGPU_HSA_INDIRECT_FUNCTION },
+ { "AMDGPU_HSA_METADATA", ELF::STT_AMDGPU_HSA_METADATA }
+};
+
static const char *getElfSectionType(unsigned Arch, unsigned Type) {
switch (Arch) {
case ELF::EM_ARM:
@@ -473,13 +800,24 @@ static const EnumEntry<unsigned> ElfSectionFlags[] = {
LLVM_READOBJ_ENUM_ENT(ELF, SHF_TLS ),
LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_CP_SECTION),
LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_DP_SECTION),
- LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP )
+ LLVM_READOBJ_ENUM_ENT(ELF, SHF_MIPS_NOSTRIP ),
+ LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_GLOBAL),
+ LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_READONLY),
+ LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_CODE),
+ LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_AGENT)
};
static const char *getElfSegmentType(unsigned Arch, unsigned Type) {
// Check potentially overlapped processor-specific
// program header type.
switch (Arch) {
+ case ELF::EM_AMDGPU:
+ switch (Type) {
+ LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM);
+ LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT);
+ LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_READONLY_AGENT);
+ LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_CODE_AGENT);
+ }
case ELF::EM_ARM:
switch (Type) {
LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX);
@@ -565,9 +903,138 @@ static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = {
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R6)
};
+template <typename ELFT>
+ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, StreamWriter &Writer)
+ : ObjDumper(Writer), Obj(Obj) {
+
+ SmallVector<const Elf_Phdr *, 4> LoadSegments;
+ for (const Elf_Phdr &Phdr : Obj->program_headers()) {
+ if (Phdr.p_type == ELF::PT_DYNAMIC) {
+ DynamicProgHeader = &Phdr;
+ continue;
+ }
+ if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0)
+ continue;
+ LoadSegments.push_back(&Phdr);
+ }
+
+ auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * {
+ const Elf_Phdr **I = std::upper_bound(
+ LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr<ELFT>);
+ if (I == LoadSegments.begin())
+ report_fatal_error("Virtual address is not in any segment");
+ --I;
+ const Elf_Phdr &Phdr = **I;
+ uint64_t Delta = VAddr - Phdr.p_vaddr;
+ if (Delta >= Phdr.p_filesz)
+ report_fatal_error("Virtual address is not in any segment");
+ return Obj->base() + Phdr.p_offset + Delta;
+ };
+
+ uint64_t SONameOffset = 0;
+ const char *StringTableBegin = nullptr;
+ uint64_t StringTableSize = 0;
+ for (const Elf_Dyn &Dyn : dynamic_table()) {
+ switch (Dyn.d_tag) {
+ case ELF::DT_HASH:
+ HashTable =
+ reinterpret_cast<const Elf_Hash *>(toMappedAddr(Dyn.getPtr()));
+ break;
+ case ELF::DT_GNU_HASH:
+ GnuHashTable =
+ reinterpret_cast<const Elf_GnuHash *>(toMappedAddr(Dyn.getPtr()));
+ break;
+ case ELF::DT_RELA:
+ DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr());
+ break;
+ case ELF::DT_RELASZ:
+ DynRelaRegion.Size = Dyn.getVal();
+ break;
+ case ELF::DT_RELAENT:
+ DynRelaRegion.EntSize = Dyn.getVal();
+ break;
+ case ELF::DT_SONAME:
+ SONameOffset = Dyn.getVal();
+ break;
+ case ELF::DT_STRTAB:
+ StringTableBegin = (const char *)toMappedAddr(Dyn.getPtr());
+ break;
+ case ELF::DT_STRSZ:
+ StringTableSize = Dyn.getVal();
+ break;
+ case ELF::DT_SYMTAB:
+ DynSymStart =
+ reinterpret_cast<const Elf_Sym *>(toMappedAddr(Dyn.getPtr()));
+ break;
+ }
+ }
+ if (StringTableBegin)
+ DynamicStringTable = StringRef(StringTableBegin, StringTableSize);
+ if (SONameOffset)
+ SOName = getDynamicString(SONameOffset);
+
+ for (const Elf_Shdr &Sec : Obj->sections()) {
+ switch (Sec.sh_type) {
+ case ELF::SHT_GNU_versym:
+ if (dot_gnu_version_sec != nullptr)
+ reportError("Multiple SHT_GNU_versym");
+ dot_gnu_version_sec = &Sec;
+ break;
+ case ELF::SHT_GNU_verdef:
+ if (dot_gnu_version_d_sec != nullptr)
+ reportError("Multiple SHT_GNU_verdef");
+ dot_gnu_version_d_sec = &Sec;
+ break;
+ case ELF::SHT_GNU_verneed:
+ if (dot_gnu_version_r_sec != nullptr)
+ reportError("Multilpe SHT_GNU_verneed");
+ dot_gnu_version_r_sec = &Sec;
+ break;
+ case ELF::SHT_DYNSYM:
+ if (DotDynSymSec != nullptr)
+ reportError("Multilpe SHT_DYNSYM");
+ DotDynSymSec = &Sec;
+ break;
+ case ELF::SHT_SYMTAB:
+ if (DotSymtabSec != nullptr)
+ reportError("Multilpe SHT_SYMTAB");
+ DotSymtabSec = &Sec;
+ break;
+ case ELF::SHT_SYMTAB_SHNDX: {
+ ErrorOr<ArrayRef<Elf_Word>> TableOrErr = Obj->getSHNDXTable(Sec);
+ error(TableOrErr.getError());
+ ShndxTable = *TableOrErr;
+ break;
+ }
+ }
+ }
+}
+
+template <typename ELFT>
+const typename ELFDumper<ELFT>::Elf_Rela *
+ELFDumper<ELFT>::dyn_rela_begin() const {
+ if (DynRelaRegion.Size && DynRelaRegion.EntSize != sizeof(Elf_Rela))
+ report_fatal_error("Invalid relocation entry size");
+ return reinterpret_cast<const Elf_Rela *>(DynRelaRegion.Addr);
+}
+
+template <typename ELFT>
+const typename ELFDumper<ELFT>::Elf_Rela *
+ELFDumper<ELFT>::dyn_rela_end() const {
+ uint64_t Size = DynRelaRegion.Size;
+ if (Size % sizeof(Elf_Rela))
+ report_fatal_error("Invalid relocation table size");
+ return dyn_rela_begin() + Size / sizeof(Elf_Rela);
+}
+
+template <typename ELFT>
+typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const {
+ return make_range(dyn_rela_begin(), dyn_rela_end());
+}
+
template<class ELFT>
void ELFDumper<ELFT>::printFileHeaders() {
- const typename ELFO::Elf_Ehdr *Header = Obj->getHeader();
+ const Elf_Ehdr *Header = Obj->getHeader();
{
DictScope D(W, "ElfHeader");
@@ -618,7 +1085,7 @@ void ELFDumper<ELFT>::printSections() {
ListScope SectionsD(W, "Sections");
int SectionIndex = -1;
- for (const typename ELFO::Elf_Shdr &Sec : Obj->sections()) {
+ for (const Elf_Shdr &Sec : Obj->sections()) {
++SectionIndex;
StringRef Name = errorOrDefault(Obj->getSectionName(&Sec));
@@ -645,12 +1112,18 @@ void ELFDumper<ELFT>::printSections() {
if (opts::SectionSymbols) {
ListScope D(W, "Symbols");
- for (const typename ELFO::Elf_Sym &Sym : Obj->symbols()) {
- ErrorOr<const Elf_Shdr *> SymSec = Obj->getSection(&Sym);
+ const Elf_Shdr *Symtab = DotSymtabSec;
+ ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*Symtab);
+ error(StrTableOrErr.getError());
+ StringRef StrTable = *StrTableOrErr;
+
+ for (const Elf_Sym &Sym : Obj->symbols(Symtab)) {
+ ErrorOr<const Elf_Shdr *> SymSec =
+ Obj->getSection(&Sym, Symtab, ShndxTable);
if (!SymSec)
continue;
if (*SymSec == &Sec)
- printSymbol(&Sym, false);
+ printSymbol(&Sym, Symtab, StrTable, false);
}
}
@@ -667,7 +1140,7 @@ void ELFDumper<ELFT>::printRelocations() {
ListScope D(W, "Relocations");
int SectionNumber = -1;
- for (const typename ELFO::Elf_Shdr &Sec : Obj->sections()) {
+ for (const Elf_Shdr &Sec : Obj->sections()) {
++SectionNumber;
if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA)
@@ -689,29 +1162,25 @@ template<class ELFT>
void ELFDumper<ELFT>::printDynamicRelocations() {
W.startLine() << "Dynamic Relocations {\n";
W.indent();
- for (typename ELFO::Elf_Rela_Iter RelI = Obj->dyn_rela_begin(),
- RelE = Obj->dyn_rela_end();
- RelI != RelE; ++RelI) {
+ for (const Elf_Rela &Rel : dyn_relas()) {
SmallString<32> RelocName;
- Obj->getRelocationTypeName(RelI->getType(Obj->isMips64EL()), RelocName);
+ Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
StringRef SymbolName;
- uint32_t SymIndex = RelI->getSymbol(Obj->isMips64EL());
- const typename ELFO::Elf_Sym *Sym = Obj->dynamic_symbol_begin() + SymIndex;
- SymbolName = errorOrDefault(Obj->getSymbolName(Sym, true));
+ uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL());
+ const Elf_Sym *Sym = DynSymStart + SymIndex;
+ SymbolName = errorOrDefault(Sym->getName(DynamicStringTable));
if (opts::ExpandRelocs) {
DictScope Group(W, "Relocation");
- W.printHex("Offset", RelI->r_offset);
- W.printNumber("Type", RelocName, (int)RelI->getType(Obj->isMips64EL()));
+ W.printHex("Offset", Rel.r_offset);
+ W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL()));
W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-");
- W.printHex("Addend", RelI->r_addend);
+ W.printHex("Addend", Rel.r_addend);
}
else {
raw_ostream& OS = W.startLine();
- OS << W.hex(RelI->r_offset)
- << " " << RelocName
- << " " << (SymbolName.size() > 0 ? SymbolName : "-")
- << " " << W.hex(RelI->r_addend)
- << "\n";
+ OS << W.hex(Rel.r_offset) << " " << RelocName << " "
+ << (SymbolName.size() > 0 ? SymbolName : "-") << " "
+ << W.hex(Rel.r_addend) << "\n";
}
}
W.unindent();
@@ -720,51 +1189,43 @@ void ELFDumper<ELFT>::printDynamicRelocations() {
template <class ELFT>
void ELFDumper<ELFT>::printRelocations(const Elf_Shdr *Sec) {
+ ErrorOr<const Elf_Shdr *> SymTabOrErr = Obj->getSection(Sec->sh_link);
+ error(SymTabOrErr.getError());
+ const Elf_Shdr *SymTab = *SymTabOrErr;
+
switch (Sec->sh_type) {
case ELF::SHT_REL:
- for (typename ELFO::Elf_Rel_Iter RI = Obj->rel_begin(Sec),
- RE = Obj->rel_end(Sec);
- RI != RE; ++RI) {
- typename ELFO::Elf_Rela Rela;
- Rela.r_offset = RI->r_offset;
- Rela.r_info = RI->r_info;
+ for (const Elf_Rel &R : Obj->rels(Sec)) {
+ Elf_Rela Rela;
+ Rela.r_offset = R.r_offset;
+ Rela.r_info = R.r_info;
Rela.r_addend = 0;
- printRelocation(Sec, Rela);
+ printRelocation(Rela, SymTab);
}
break;
case ELF::SHT_RELA:
- for (typename ELFO::Elf_Rela_Iter RI = Obj->rela_begin(Sec),
- RE = Obj->rela_end(Sec);
- RI != RE; ++RI) {
- printRelocation(Sec, *RI);
- }
+ for (const Elf_Rela &R : Obj->relas(Sec))
+ printRelocation(R, SymTab);
break;
}
}
template <class ELFT>
-void ELFDumper<ELFT>::printRelocation(const Elf_Shdr *Sec,
- typename ELFO::Elf_Rela Rel) {
+void ELFDumper<ELFT>::printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab) {
SmallString<32> RelocName;
Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
StringRef TargetName;
- std::pair<const Elf_Shdr *, const Elf_Sym *> Sym =
- Obj->getRelocationSymbol(Sec, &Rel);
- if (Sym.second && Sym.second->getType() == ELF::STT_SECTION) {
- ErrorOr<const Elf_Shdr *> Sec = Obj->getSection(Sym.second);
- if (!error(Sec.getError())) {
- ErrorOr<StringRef> SecName = Obj->getSectionName(*Sec);
- if (SecName)
- TargetName = SecName.get();
- }
- } else if (Sym.first) {
- const Elf_Shdr *SymTable = Sym.first;
- ErrorOr<const Elf_Shdr *> StrTableSec = Obj->getSection(SymTable->sh_link);
- if (!error(StrTableSec.getError())) {
- ErrorOr<StringRef> StrTableOrErr = Obj->getStringTable(*StrTableSec);
- if (!error(StrTableOrErr.getError()))
- TargetName = errorOrDefault(Sym.second->getName(*StrTableOrErr));
- }
+ const Elf_Sym *Sym = Obj->getRelocationSymbol(&Rel, SymTab);
+ if (Sym && Sym->getType() == ELF::STT_SECTION) {
+ ErrorOr<const Elf_Shdr *> Sec = Obj->getSection(Sym, SymTab, ShndxTable);
+ error(Sec.getError());
+ ErrorOr<StringRef> SecName = Obj->getSectionName(*Sec);
+ if (SecName)
+ TargetName = SecName.get();
+ } else if (Sym) {
+ ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*SymTab);
+ error(StrTableOrErr.getError());
+ TargetName = errorOrDefault(Sym->getName(*StrTableOrErr));
}
if (opts::ExpandRelocs) {
@@ -783,27 +1244,38 @@ void ELFDumper<ELFT>::printRelocation(const Elf_Shdr *Sec,
}
template<class ELFT>
+void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) {
+ const Elf_Shdr *Symtab = (IsDynamic) ? DotDynSymSec : DotSymtabSec;
+ if (!Symtab)
+ return;
+ ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*Symtab);
+ error(StrTableOrErr.getError());
+ StringRef StrTable = *StrTableOrErr;
+ for (const Elf_Sym &Sym : Obj->symbols(Symtab))
+ printSymbol(&Sym, Symtab, StrTable, IsDynamic);
+}
+
+template<class ELFT>
void ELFDumper<ELFT>::printSymbols() {
ListScope Group(W, "Symbols");
- for (const typename ELFO::Elf_Sym &Sym : Obj->symbols())
- printSymbol(&Sym, false);
+ printSymbolsHelper(false);
}
template<class ELFT>
void ELFDumper<ELFT>::printDynamicSymbols() {
ListScope Group(W, "DynamicSymbols");
-
- for (const typename ELFO::Elf_Sym &Sym : Obj->dynamic_symbols())
- printSymbol(&Sym, true);
+ printSymbolsHelper(true);
}
template <class ELFT>
-void ELFDumper<ELFT>::printSymbol(const typename ELFO::Elf_Sym *Symbol,
- bool IsDynamic) {
+void ELFDumper<ELFT>::printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab,
+ StringRef StrTable, bool IsDynamic) {
unsigned SectionIndex = 0;
StringRef SectionName;
- getSectionNameIndex(*Obj, Symbol, SectionName, SectionIndex);
- std::string FullSymbolName = getFullSymbolName(*Obj, Symbol, IsDynamic);
+ getSectionNameIndex(*Obj, Symbol, SymTab, ShndxTable, SectionName,
+ SectionIndex);
+ std::string FullSymbolName = getFullSymbolName(Symbol, StrTable, IsDynamic);
+ unsigned char SymbolType = Symbol->getType();
DictScope D(W, "Symbol");
W.printNumber("Name", FullSymbolName, Symbol->st_name);
@@ -811,7 +1283,11 @@ void ELFDumper<ELFT>::printSymbol(const typename ELFO::Elf_Sym *Symbol,
W.printNumber("Size", Symbol->st_size);
W.printEnum ("Binding", Symbol->getBinding(),
makeArrayRef(ElfSymbolBindings));
- W.printEnum ("Type", Symbol->getType(), makeArrayRef(ElfSymbolTypes));
+ if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU &&
+ SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
+ W.printEnum ("Type", SymbolType, makeArrayRef(AMDGPUSymbolTypes));
+ else
+ W.printEnum ("Type", SymbolType, makeArrayRef(ElfSymbolTypes));
W.printNumber("Other", Symbol->st_other);
W.printHex("Section", SectionName, SectionIndex);
}
@@ -855,12 +1331,15 @@ static const char *getTypeString(uint64_t Type) {
LLVM_READOBJ_TYPE_CASE(SYMENT);
LLVM_READOBJ_TYPE_CASE(SYMTAB);
LLVM_READOBJ_TYPE_CASE(TEXTREL);
+ LLVM_READOBJ_TYPE_CASE(VERDEF);
+ LLVM_READOBJ_TYPE_CASE(VERDEFNUM);
LLVM_READOBJ_TYPE_CASE(VERNEED);
LLVM_READOBJ_TYPE_CASE(VERNEEDNUM);
LLVM_READOBJ_TYPE_CASE(VERSYM);
LLVM_READOBJ_TYPE_CASE(RELCOUNT);
LLVM_READOBJ_TYPE_CASE(GNU_HASH);
LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION);
+ LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP_REL);
LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS);
LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS);
LLVM_READOBJ_TYPE_CASE(MIPS_LOCAL_GOTNO);
@@ -956,8 +1435,15 @@ void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) {
}
template <class ELFT>
-static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
- bool Is64, raw_ostream &OS) {
+StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const {
+ if (Value >= DynamicStringTable.size())
+ reportError("Invalid dynamic string table reference");
+ return StringRef(DynamicStringTable.data() + Value);
+}
+
+template <class ELFT>
+void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) {
+ raw_ostream &OS = W.getOStream();
switch (Type) {
case DT_PLTREL:
if (Value == DT_REL) {
@@ -981,6 +1467,7 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
case DT_FINI_ARRAY:
case DT_PREINIT_ARRAY:
case DT_DEBUG:
+ case DT_VERDEF:
case DT_VERNEED:
case DT_VERSYM:
case DT_GNU_HASH:
@@ -988,11 +1475,13 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
case DT_MIPS_BASE_ADDRESS:
case DT_MIPS_GOTSYM:
case DT_MIPS_RLD_MAP:
+ case DT_MIPS_RLD_MAP_REL:
case DT_MIPS_PLTGOT:
case DT_MIPS_OPTIONS:
OS << format("0x%" PRIX64, Value);
break;
case DT_RELCOUNT:
+ case DT_VERDEFNUM:
case DT_VERNEEDNUM:
case DT_MIPS_RLD_VERSION:
case DT_MIPS_LOCAL_GOTNO:
@@ -1013,14 +1502,14 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
OS << Value << " (bytes)";
break;
case DT_NEEDED:
- OS << "SharedLibrary (" << O->getDynamicString(Value) << ")";
+ OS << "SharedLibrary (" << getDynamicString(Value) << ")";
break;
case DT_SONAME:
- OS << "LibrarySoname (" << O->getDynamicString(Value) << ")";
+ OS << "LibrarySoname (" << getDynamicString(Value) << ")";
break;
case DT_RPATH:
case DT_RUNPATH:
- OS << O->getDynamicString(Value);
+ OS << getDynamicString(Value);
break;
case DT_MIPS_FLAGS:
printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS);
@@ -1046,7 +1535,8 @@ namespace {
template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() {
const unsigned Machine = Obj->getHeader()->e_machine;
if (Machine == EM_ARM) {
- ARM::EHABI::PrinterContext<ELFType<support::little, false>> Ctx(W, Obj);
+ ARM::EHABI::PrinterContext<ELFType<support::little, false>> Ctx(
+ W, Obj, DotSymtabSec);
return Ctx.PrintUnwindInformation();
}
W.startLine() << "UnwindInfo not implemented.\n";
@@ -1055,9 +1545,20 @@ template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() {
template<class ELFT>
void ELFDumper<ELFT>::printDynamicTable() {
- auto DynTable = Obj->dynamic_table(true);
+ auto I = dynamic_table_begin();
+ auto E = dynamic_table_end();
- ptrdiff_t Total = std::distance(DynTable.begin(), DynTable.end());
+ if (I == E)
+ return;
+
+ --E;
+ while (I != E && E->getTag() == ELF::DT_NULL)
+ --E;
+ if (E->getTag() != ELF::DT_NULL)
+ ++E;
+ ++E;
+
+ ptrdiff_t Total = std::distance(I, E);
if (Total == 0)
return;
@@ -1069,12 +1570,13 @@ void ELFDumper<ELFT>::printDynamicTable() {
W.startLine()
<< " Tag" << (Is64 ? " " : " ") << "Type"
<< " " << "Name/Value\n";
- for (const auto &Entry : DynTable) {
- W.startLine()
- << " "
- << format(Is64 ? "0x%016" PRIX64 : "0x%08" PRIX64, Entry.getTag())
- << " " << format("%-21s", getTypeString(Entry.getTag()));
- printValue(Obj, Entry.getTag(), Entry.getVal(), Is64, OS);
+ while (I != E) {
+ const Elf_Dyn &Entry = *I;
+ uintX_t Tag = Entry.getTag();
+ ++I;
+ W.startLine() << " " << format_hex(Tag, Is64 ? 18 : 10, true) << " "
+ << format("%-21s", getTypeString(Tag));
+ printValue(Tag, Entry.getVal());
OS << "\n";
}
@@ -1088,14 +1590,14 @@ void ELFDumper<ELFT>::printNeededLibraries() {
typedef std::vector<StringRef> LibsTy;
LibsTy Libs;
- for (const auto &Entry : Obj->dynamic_table())
+ for (const auto &Entry : dynamic_table())
if (Entry.d_tag == ELF::DT_NEEDED)
- Libs.push_back(Obj->getDynamicString(Entry.d_un.d_val));
+ Libs.push_back(getDynamicString(Entry.d_un.d_val));
std::stable_sort(Libs.begin(), Libs.end());
- for (LibsTy::const_iterator I = Libs.begin(), E = Libs.end(); I != E; ++I) {
- outs() << " " << *I << "\n";
+ for (const auto &L : Libs) {
+ outs() << " " << L << "\n";
}
}
@@ -1103,33 +1605,51 @@ template<class ELFT>
void ELFDumper<ELFT>::printProgramHeaders() {
ListScope L(W, "ProgramHeaders");
- for (typename ELFO::Elf_Phdr_Iter PI = Obj->program_header_begin(),
- PE = Obj->program_header_end();
- PI != PE; ++PI) {
+ for (const Elf_Phdr &Phdr : Obj->program_headers()) {
DictScope P(W, "ProgramHeader");
- W.printHex ("Type",
- getElfSegmentType(Obj->getHeader()->e_machine, PI->p_type),
- PI->p_type);
- W.printHex ("Offset", PI->p_offset);
- W.printHex ("VirtualAddress", PI->p_vaddr);
- W.printHex ("PhysicalAddress", PI->p_paddr);
- W.printNumber("FileSize", PI->p_filesz);
- W.printNumber("MemSize", PI->p_memsz);
- W.printFlags ("Flags", PI->p_flags, makeArrayRef(ElfSegmentFlags));
- W.printNumber("Alignment", PI->p_align);
+ W.printHex("Type",
+ getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type),
+ Phdr.p_type);
+ W.printHex("Offset", Phdr.p_offset);
+ W.printHex("VirtualAddress", Phdr.p_vaddr);
+ W.printHex("PhysicalAddress", Phdr.p_paddr);
+ W.printNumber("FileSize", Phdr.p_filesz);
+ W.printNumber("MemSize", Phdr.p_memsz);
+ W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags));
+ W.printNumber("Alignment", Phdr.p_align);
}
}
template <typename ELFT>
void ELFDumper<ELFT>::printHashTable() {
DictScope D(W, "HashTable");
- auto HT = Obj->getHashTable();
- if (!HT)
+ if (!HashTable)
+ return;
+ W.printNumber("Num Buckets", HashTable->nbucket);
+ W.printNumber("Num Chains", HashTable->nchain);
+ W.printList("Buckets", HashTable->buckets());
+ W.printList("Chains", HashTable->chains());
+}
+
+template <typename ELFT>
+void ELFDumper<ELFT>::printGnuHashTable() {
+ DictScope D(W, "GnuHashTable");
+ if (!GnuHashTable)
return;
- W.printNumber("Num Buckets", HT->nbucket);
- W.printNumber("Num Chains", HT->nchain);
- W.printList("Buckets", HT->buckets());
- W.printList("Chains", HT->chains());
+ W.printNumber("Num Buckets", GnuHashTable->nbuckets);
+ W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx);
+ W.printNumber("Num Mask Words", GnuHashTable->maskwords);
+ W.printNumber("Shift Count", GnuHashTable->shift2);
+ W.printHexList("Bloom Filter", GnuHashTable->filter());
+ W.printList("Buckets", GnuHashTable->buckets());
+ if (!DotDynSymSec)
+ reportError("No dynamic symbol section");
+ W.printHexList("Values",
+ GnuHashTable->values(DotDynSymSec->getEntityCount()));
+}
+
+template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
+ outs() << "LoadName: " << SOName << '\n';
}
template <class ELFT>
@@ -1171,21 +1691,23 @@ template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() {
namespace {
template <class ELFT> class MipsGOTParser {
public:
- typedef object::ELFFile<ELFT> ObjectFile;
- typedef typename ObjectFile::Elf_Shdr Elf_Shdr;
- typedef typename ObjectFile::Elf_Sym Elf_Sym;
+ typedef object::ELFFile<ELFT> ELFO;
+ typedef typename ELFO::Elf_Shdr Elf_Shdr;
+ typedef typename ELFO::Elf_Sym Elf_Sym;
+ typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range;
+ typedef typename ELFO::Elf_Addr GOTEntry;
+ typedef typename ELFO::Elf_Rel Elf_Rel;
+ typedef typename ELFO::Elf_Rela Elf_Rela;
- MipsGOTParser(const ObjectFile *Obj, StreamWriter &W);
+ MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj,
+ Elf_Dyn_Range DynTable, StreamWriter &W);
void parseGOT();
void parsePLT();
private:
- typedef typename ObjectFile::Elf_Addr GOTEntry;
- typedef typename ObjectFile::template ELFEntityIterator<const GOTEntry>
- GOTIter;
-
- const ObjectFile *Obj;
+ ELFDumper<ELFT> *Dumper;
+ const ELFO *Obj;
StreamWriter &W;
llvm::Optional<uint64_t> DtPltGot;
llvm::Optional<uint64_t> DtLocalGotNum;
@@ -1194,22 +1716,26 @@ private:
llvm::Optional<uint64_t> DtJmpRel;
std::size_t getGOTTotal(ArrayRef<uint8_t> GOT) const;
- GOTIter makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum);
-
- void printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It);
- void printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It,
- const Elf_Sym *Sym, bool IsDynamic);
- void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It,
- StringRef Purpose);
- void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It,
+ const GOTEntry *makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum);
+
+ void printGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt,
+ const GOTEntry *It);
+ void printGlobalGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt,
+ const GOTEntry *It, const Elf_Sym *Sym,
+ StringRef StrTable, bool IsDynamic);
+ void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt,
+ const GOTEntry *It, StringRef Purpose);
+ void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt,
+ const GOTEntry *It, StringRef StrTable,
const Elf_Sym *Sym);
};
}
template <class ELFT>
-MipsGOTParser<ELFT>::MipsGOTParser(const ObjectFile *Obj, StreamWriter &W)
- : Obj(Obj), W(W) {
- for (const auto &Entry : Obj->dynamic_table()) {
+MipsGOTParser<ELFT>::MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj,
+ Elf_Dyn_Range DynTable, StreamWriter &W)
+ : Dumper(Dumper), Obj(Obj), W(W) {
+ for (const auto &Entry : DynTable) {
switch (Entry.getTag()) {
case ELF::DT_PLTGOT:
DtPltGot = Entry.getVal();
@@ -1264,8 +1790,11 @@ template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() {
return;
}
- const Elf_Sym *DynSymBegin = Obj->dynamic_symbol_begin();
- const Elf_Sym *DynSymEnd = Obj->dynamic_symbol_end();
+ const Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec();
+ ErrorOr<StringRef> StrTable = Obj->getStringTableForSymtab(*DynSymSec);
+ error(StrTable.getError());
+ const Elf_Sym *DynSymBegin = Obj->symbol_begin(DynSymSec);
+ const Elf_Sym *DynSymEnd = Obj->symbol_end(DynSymSec);
std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd));
if (*DtGotSym > DynSymTotal) {
@@ -1280,9 +1809,9 @@ template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() {
return;
}
- GOTIter GotBegin = makeGOTIter(*GOT, 0);
- GOTIter GotLocalEnd = makeGOTIter(*GOT, *DtLocalGotNum);
- GOTIter It = GotBegin;
+ const GOTEntry *GotBegin = makeGOTIter(*GOT, 0);
+ const GOTEntry *GotLocalEnd = makeGOTIter(*GOT, *DtLocalGotNum);
+ const GOTEntry *It = GotBegin;
DictScope GS(W, "Primary GOT");
@@ -1312,11 +1841,13 @@ template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() {
{
ListScope GS(W, "Global entries");
- GOTIter GotGlobalEnd = makeGOTIter(*GOT, *DtLocalGotNum + GlobalGotNum);
+ const GOTEntry *GotGlobalEnd =
+ makeGOTIter(*GOT, *DtLocalGotNum + GlobalGotNum);
const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym;
for (; It != GotGlobalEnd; ++It) {
DictScope D(W, "Entry");
- printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, true);
+ printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++,
+ *StrTable, true);
}
}
@@ -1350,10 +1881,16 @@ template <class ELFT> void MipsGOTParser<ELFT>::parsePLT() {
W.startLine() << "There is no .rel.plt section in the file.\n";
return;
}
+ ErrorOr<const Elf_Shdr *> SymTableOrErr =
+ Obj->getSection(PLTRelShdr->sh_link);
+ error(SymTableOrErr.getError());
+ const Elf_Shdr *SymTable = *SymTableOrErr;
+ ErrorOr<StringRef> StrTable = Obj->getStringTableForSymtab(*SymTable);
+ error(StrTable.getError());
- GOTIter PLTBegin = makeGOTIter(*PLT, 0);
- GOTIter PLTEnd = makeGOTIter(*PLT, getGOTTotal(*PLT));
- GOTIter It = PLTBegin;
+ const GOTEntry *PLTBegin = makeGOTIter(*PLT, 0);
+ const GOTEntry *PLTEnd = makeGOTIter(*PLT, getGOTTotal(*PLT));
+ const GOTEntry *It = PLTBegin;
DictScope GS(W, "PLT GOT");
{
@@ -1367,21 +1904,19 @@ template <class ELFT> void MipsGOTParser<ELFT>::parsePLT() {
switch (PLTRelShdr->sh_type) {
case ELF::SHT_REL:
- for (typename ObjectFile::Elf_Rel_Iter RI = Obj->rel_begin(PLTRelShdr),
- RE = Obj->rel_end(PLTRelShdr);
+ for (const Elf_Rel *RI = Obj->rel_begin(PLTRelShdr),
+ *RE = Obj->rel_end(PLTRelShdr);
RI != RE && It != PLTEnd; ++RI, ++It) {
- const Elf_Sym *Sym =
- Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second;
- printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, Sym);
+ const Elf_Sym *Sym = Obj->getRelocationSymbol(&*RI, SymTable);
+ printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, *StrTable, Sym);
}
break;
case ELF::SHT_RELA:
- for (typename ObjectFile::Elf_Rela_Iter RI = Obj->rela_begin(PLTRelShdr),
- RE = Obj->rela_end(PLTRelShdr);
+ for (const Elf_Rela *RI = Obj->rela_begin(PLTRelShdr),
+ *RE = Obj->rela_end(PLTRelShdr);
RI != RE && It != PLTEnd; ++RI, ++It) {
- const Elf_Sym *Sym =
- Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second;
- printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, Sym);
+ const Elf_Sym *Sym = Obj->getRelocationSymbol(&*RI, SymTable);
+ printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, *StrTable, Sym);
}
break;
}
@@ -1394,15 +1929,16 @@ std::size_t MipsGOTParser<ELFT>::getGOTTotal(ArrayRef<uint8_t> GOT) const {
}
template <class ELFT>
-typename MipsGOTParser<ELFT>::GOTIter
+const typename MipsGOTParser<ELFT>::GOTEntry *
MipsGOTParser<ELFT>::makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum) {
const char *Data = reinterpret_cast<const char *>(GOT.data());
- return GOTIter(sizeof(GOTEntry), Data + EntryNum * sizeof(GOTEntry));
+ return reinterpret_cast<const GOTEntry *>(Data + EntryNum * sizeof(GOTEntry));
}
template <class ELFT>
-void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr, GOTIter BeginIt,
- GOTIter It) {
+void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr,
+ const GOTEntry *BeginIt,
+ const GOTEntry *It) {
int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
W.printHex("Address", GotAddr + Offset);
W.printNumber("Access", Offset - 0x7ff0);
@@ -1410,9 +1946,9 @@ void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr, GOTIter BeginIt,
}
template <class ELFT>
-void MipsGOTParser<ELFT>::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt,
- GOTIter It, const Elf_Sym *Sym,
- bool IsDynamic) {
+void MipsGOTParser<ELFT>::printGlobalGotEntry(
+ uint64_t GotAddr, const GOTEntry *BeginIt, const GOTEntry *It,
+ const Elf_Sym *Sym, StringRef StrTable, bool IsDynamic) {
printGotEntry(GotAddr, BeginIt, It);
W.printHex("Value", Sym->st_value);
@@ -1420,16 +1956,19 @@ void MipsGOTParser<ELFT>::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt,
unsigned SectionIndex = 0;
StringRef SectionName;
- getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex);
+ getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(),
+ Dumper->getShndxTable(), SectionName, SectionIndex);
W.printHex("Section", SectionName, SectionIndex);
- std::string FullSymbolName = getFullSymbolName(*Obj, Sym, IsDynamic);
+ std::string FullSymbolName =
+ Dumper->getFullSymbolName(Sym, StrTable, IsDynamic);
W.printNumber("Name", FullSymbolName, Sym->st_name);
}
template <class ELFT>
-void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt,
- GOTIter It, StringRef Purpose) {
+void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr,
+ const GOTEntry *BeginIt,
+ const GOTEntry *It, StringRef Purpose) {
DictScope D(W, "Entry");
int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
W.printHex("Address", PLTAddr + Offset);
@@ -1438,8 +1977,10 @@ void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt,
}
template <class ELFT>
-void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt,
- GOTIter It, const Elf_Sym *Sym) {
+void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr,
+ const GOTEntry *BeginIt,
+ const GOTEntry *It, StringRef StrTable,
+ const Elf_Sym *Sym) {
DictScope D(W, "Entry");
int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
W.printHex("Address", PLTAddr + Offset);
@@ -1449,10 +1990,11 @@ void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt,
unsigned SectionIndex = 0;
StringRef SectionName;
- getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex);
+ getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(),
+ Dumper->getShndxTable(), SectionName, SectionIndex);
W.printHex("Section", SectionName, SectionIndex);
- std::string FullSymbolName = getFullSymbolName(*Obj, Sym, true);
+ std::string FullSymbolName = Dumper->getFullSymbolName(Sym, StrTable, true);
W.printNumber("Name", FullSymbolName, Sym->st_name);
}
@@ -1462,7 +2004,7 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
return;
}
- MipsGOTParser<ELFT> GOTParser(Obj, W);
+ MipsGOTParser<ELFT> GOTParser(this, Obj, dynamic_table(), W);
GOTParser.parseGOT();
GOTParser.parsePLT();
}
@@ -1604,7 +2146,7 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsReginfo() {
}
template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {
- const typename ELFFile<ELFT>::Elf_Shdr *StackMapSection = nullptr;
+ const Elf_Shdr *StackMapSection = nullptr;
for (const auto &Sec : Obj->sections()) {
ErrorOr<StringRef> Name = Obj->getSectionName(&Sec);
if (*Name == ".llvm_stackmaps") {
diff --git a/contrib/llvm/tools/llvm-readobj/MachODumper.cpp b/contrib/llvm/tools/llvm-readobj/MachODumper.cpp
index adb99b0..58d2c9f 100644
--- a/contrib/llvm/tools/llvm-readobj/MachODumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/MachODumper.cpp
@@ -40,6 +40,14 @@ public:
void printUnwindInfo() override;
void printStackMap() const override;
+ // MachO-specific.
+ void printMachODataInCode() override;
+ void printMachOVersionMin() override;
+ void printMachODysymtab() override;
+ void printMachOSegment() override;
+ void printMachOIndirectSymbols() override;
+ void printMachOLinkerOptions () override;
+
private:
template<class MachHeader>
void printFileHeaders(const MachHeader &Header);
@@ -255,6 +263,21 @@ namespace {
uint32_t Flags;
uint32_t Reserved1;
uint32_t Reserved2;
+ uint32_t Reserved3;
+ };
+
+ struct MachOSegment {
+ std::string CmdName;
+ std::string SegName;
+ uint64_t cmdsize;
+ uint64_t vmaddr;
+ uint64_t vmsize;
+ uint64_t fileoff;
+ uint64_t filesize;
+ uint32_t maxprot;
+ uint32_t initprot;
+ uint32_t nsects;
+ uint32_t flags;
};
struct MachOSymbol {
@@ -266,6 +289,18 @@ namespace {
};
}
+static std::string getMask(uint32_t prot)
+{
+ // TODO (davide): This always assumes prot is valid.
+ // Catch mistakes and report if needed.
+ std::string Prot;
+ Prot = "";
+ Prot += (prot & MachO::VM_PROT_READ) ? "r" : "-";
+ Prot += (prot & MachO::VM_PROT_WRITE) ? "w" : "-";
+ Prot += (prot & MachO::VM_PROT_EXECUTE) ? "x" : "-";
+ return Prot;
+}
+
static void getSection(const MachOObjectFile *Obj,
DataRefImpl Sec,
MachOSection &Section) {
@@ -292,8 +327,40 @@ static void getSection(const MachOObjectFile *Obj,
Section.Flags = Sect.flags;
Section.Reserved1 = Sect.reserved1;
Section.Reserved2 = Sect.reserved2;
+ Section.Reserved3 = Sect.reserved3;
}
+static void getSegment(const MachOObjectFile *Obj,
+ const MachOObjectFile::LoadCommandInfo &L,
+ MachOSegment &Segment) {
+ if (!Obj->is64Bit()) {
+ MachO::segment_command SC = Obj->getSegmentLoadCommand(L);
+ Segment.CmdName = "LC_SEGMENT";
+ Segment.SegName = SC.segname;
+ Segment.cmdsize = SC.cmdsize;
+ Segment.vmaddr = SC.vmaddr;
+ Segment.vmsize = SC.vmsize;
+ Segment.fileoff = SC.fileoff;
+ Segment.filesize = SC.filesize;
+ Segment.maxprot = SC.maxprot;
+ Segment.initprot = SC.initprot;
+ Segment.nsects = SC.nsects;
+ Segment.flags = SC.flags;
+ return;
+ }
+ MachO::segment_command_64 SC = Obj->getSegment64LoadCommand(L);
+ Segment.CmdName = "LC_SEGMENT_64";
+ Segment.SegName = SC.segname;
+ Segment.cmdsize = SC.cmdsize;
+ Segment.vmaddr = SC.vmaddr;
+ Segment.vmsize = SC.vmsize;
+ Segment.fileoff = SC.fileoff;
+ Segment.filesize = SC.filesize;
+ Segment.maxprot = SC.maxprot;
+ Segment.initprot = SC.initprot;
+ Segment.nsects = SC.nsects;
+ Segment.flags = SC.flags;
+}
static void getSymbol(const MachOObjectFile *Obj,
DataRefImpl DRI,
@@ -375,8 +442,7 @@ void MachODumper::printSections(const MachOObjectFile *Obj) {
DataRefImpl DR = Section.getRawDataRefImpl();
StringRef Name;
- if (error(Section.getName(Name)))
- Name = "";
+ error(Section.getName(Name));
ArrayRef<char> RawName = Obj->getSectionRawName(DR);
StringRef SegmentName = Obj->getSectionFinalSegmentName(DR);
@@ -398,6 +464,8 @@ void MachODumper::printSections(const MachOObjectFile *Obj) {
makeArrayRef(MachOSectionAttributes));
W.printHex("Reserved1", MOSection.Reserved1);
W.printHex("Reserved2", MOSection.Reserved2);
+ if (Obj->is64Bit())
+ W.printHex("Reserved3", MOSection.Reserved3);
if (opts::SectionRelocations) {
ListScope D(W, "Relocations");
@@ -419,8 +487,7 @@ void MachODumper::printSections(const MachOObjectFile *Obj) {
bool IsBSS = Section.isBSS();
if (!IsBSS) {
StringRef Data;
- if (error(Section.getContents(Data)))
- break;
+ error(Section.getContents(Data));
W.printBinaryBlock("SectionData", Data);
}
@@ -434,8 +501,7 @@ void MachODumper::printRelocations() {
std::error_code EC;
for (const SectionRef &Section : Obj->sections()) {
StringRef Name;
- if (error(Section.getName(Name)))
- continue;
+ error(Section.getName(Name));
bool PrintedGroup = false;
for (const RelocationRef &Reloc : Section.relocations()) {
@@ -475,15 +541,13 @@ void MachODumper::printRelocation(const MachOObjectFile *Obj,
symbol_iterator Symbol = Reloc.getSymbol();
if (Symbol != Obj->symbol_end()) {
ErrorOr<StringRef> TargetNameOrErr = Symbol->getName();
- if (error(TargetNameOrErr.getError()))
- return;
+ error(TargetNameOrErr.getError());
TargetName = *TargetNameOrErr;
}
} else if (!IsScattered) {
section_iterator SecI = Obj->getRelocationSection(DR);
if (SecI != Obj->section_end()) {
- if (error(SecI->getName(TargetName)))
- return;
+ error(SecI->getName(TargetName));
}
}
if (TargetName.empty())
@@ -547,8 +611,10 @@ void MachODumper::printSymbol(const SymbolRef &Symbol) {
getSymbol(Obj, Symbol.getRawDataRefImpl(), MOSymbol);
StringRef SectionName = "";
- section_iterator SecI(Obj->section_begin());
- if (!error(Symbol.getSection(SecI)) && SecI != Obj->section_end())
+ ErrorOr<section_iterator> SecIOrErr = Symbol.getSection();
+ error(SecIOrErr.getError());
+ section_iterator SecI = *SecIOrErr;
+ if (SecI != Obj->section_end())
error(SecI->getName(SectionName));
DictScope D(W, "Symbol");
@@ -603,3 +669,153 @@ void MachODumper::printStackMap() const {
prettyPrintStackMap(llvm::outs(),
StackMapV1Parser<support::big>(StackMapContentsArray));
}
+
+void MachODumper::printMachODataInCode() {
+ for (const auto &Load : Obj->load_commands()) {
+ if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
+ MachO::linkedit_data_command LLC = Obj->getLinkeditDataLoadCommand(Load);
+ DictScope Group(W, "DataInCode");
+ W.printNumber("Data offset", LLC.dataoff);
+ W.printNumber("Data size", LLC.datasize);
+ ListScope D(W, "Data entries");
+ unsigned NumRegions = LLC.datasize / sizeof(MachO::data_in_code_entry);
+ for (unsigned i = 0; i < NumRegions; ++i) {
+ MachO::data_in_code_entry DICE = Obj->getDataInCodeTableEntry(
+ LLC.dataoff, i);
+ DictScope Group(W, "Entry");
+ W.printNumber("Index", i);
+ W.printNumber("Offset", DICE.offset);
+ W.printNumber("Length", DICE.length);
+ W.printNumber("Kind", DICE.kind);
+ }
+ }
+ }
+}
+
+void MachODumper::printMachOVersionMin() {
+ for (const auto &Load : Obj->load_commands()) {
+ StringRef Cmd;
+ switch (Load.C.cmd) {
+ case MachO::LC_VERSION_MIN_MACOSX:
+ Cmd = "LC_VERSION_MIN_MACOSX";
+ break;
+ case MachO::LC_VERSION_MIN_IPHONEOS:
+ Cmd = "LC_VERSION_MIN_IPHONEOS";
+ break;
+ case MachO::LC_VERSION_MIN_TVOS:
+ Cmd = "LC_VERSION_MIN_TVOS";
+ break;
+ case MachO::LC_VERSION_MIN_WATCHOS:
+ Cmd = "LC_VERSION_MIN_WATCHOS";
+ break;
+ default:
+ continue;
+ }
+
+ MachO::version_min_command VMC = Obj->getVersionMinLoadCommand(Load);
+ DictScope Group(W, "MinVersion");
+ W.printString("Cmd", Cmd);
+ W.printNumber("Size", VMC.cmdsize);
+ SmallString<32> Version;
+ Version = utostr(MachOObjectFile::getVersionMinMajor(VMC, false)) + "." +
+ utostr(MachOObjectFile::getVersionMinMinor(VMC, false));
+ uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, false);
+ if (Update != 0)
+ Version += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC, false));
+ W.printString("Version", Version);
+ SmallString<32> SDK;
+ if (VMC.sdk == 0)
+ SDK = "n/a";
+ else {
+ SDK = utostr(MachOObjectFile::getVersionMinMajor(VMC, true)) + "." +
+ utostr(MachOObjectFile::getVersionMinMinor(VMC, true));
+ uint32_t Update = MachOObjectFile::getVersionMinUpdate(VMC, true);
+ if (Update != 0)
+ SDK += "." + utostr(MachOObjectFile::getVersionMinUpdate(VMC, true));
+ }
+ W.printString("SDK", SDK);
+ }
+}
+
+void MachODumper::printMachODysymtab() {
+ for (const auto &Load : Obj->load_commands()) {
+ if (Load.C.cmd == MachO::LC_DYSYMTAB) {
+ MachO::dysymtab_command DLC = Obj->getDysymtabLoadCommand();
+ DictScope Group(W, "Dysymtab");
+ W.printNumber("ilocalsym", DLC.ilocalsym);
+ W.printNumber("nlocalsym", DLC.nlocalsym);
+ W.printNumber("iextdefsym", DLC.iextdefsym);
+ W.printNumber("nextdefsym", DLC.nextdefsym);
+ W.printNumber("iundefsym", DLC.iundefsym);
+ W.printNumber("nundefsym", DLC.nundefsym);
+ W.printNumber("tocoff", DLC.tocoff);
+ W.printNumber("ntoc", DLC.ntoc);
+ W.printNumber("modtaboff", DLC.modtaboff);
+ W.printNumber("nmodtab", DLC.nmodtab);
+ W.printNumber("extrefsymoff", DLC.extrefsymoff);
+ W.printNumber("nextrefsyms", DLC.nextrefsyms);
+ W.printNumber("indirectsymoff", DLC.indirectsymoff);
+ W.printNumber("nindirectsyms", DLC.nindirectsyms);
+ W.printNumber("extreloff", DLC.extreloff);
+ W.printNumber("nextrel", DLC.nextrel);
+ W.printNumber("locreloff", DLC.locreloff);
+ W.printNumber("nlocrel", DLC.nlocrel);
+ }
+ }
+}
+
+void MachODumper::printMachOSegment() {
+ for (const auto &Load : Obj->load_commands()) {
+ if (Load.C.cmd == MachO::LC_SEGMENT || Load.C.cmd == MachO::LC_SEGMENT_64) {
+ MachOSegment MOSegment;
+ getSegment(Obj, Load, MOSegment);
+ DictScope Group(W, "Segment");
+ W.printString("Cmd", MOSegment.CmdName);
+ W.printString("Name", MOSegment.SegName);
+ W.printNumber("Size", MOSegment.cmdsize);
+ W.printHex("vmaddr", MOSegment.vmaddr);
+ W.printHex("vmsize", MOSegment.vmsize);
+ W.printNumber("fileoff", MOSegment.fileoff);
+ W.printNumber("filesize", MOSegment.filesize);
+ W.printString("maxprot", getMask(MOSegment.maxprot));
+ W.printString("initprot", getMask(MOSegment.initprot));
+ W.printNumber("nsects", MOSegment.nsects);
+ W.printHex("flags", MOSegment.flags);
+ }
+ }
+}
+
+void MachODumper::printMachOIndirectSymbols() {
+ for (const auto &Load : Obj->load_commands()) {
+ if (Load.C.cmd == MachO::LC_DYSYMTAB) {
+ MachO::dysymtab_command DLC = Obj->getDysymtabLoadCommand();
+ DictScope Group(W, "Indirect Symbols");
+ W.printNumber("Number", DLC.nindirectsyms);
+ ListScope D(W, "Symbols");
+ for (unsigned i = 0; i < DLC.nindirectsyms; ++i) {
+ DictScope Group(W, "Entry");
+ W.printNumber("Entry Index", i);
+ W.printHex("Symbol Index", Obj->getIndirectSymbolTableEntry(DLC, i));
+ }
+ }
+ }
+}
+
+void MachODumper::printMachOLinkerOptions() {
+ for (const auto &Load : Obj->load_commands()) {
+ if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
+ MachO::linker_option_command LOLC = Obj->getLinkerOptionLoadCommand(Load);
+ DictScope Group(W, "Linker Options");
+ W.printNumber("Size", LOLC.cmdsize);
+ ListScope D(W, "Strings");
+ uint64_t DataSize = LOLC.cmdsize - sizeof(MachO::linker_option_command);
+ const char *P = Load.Ptr + sizeof(MachO::linker_option_command);
+ StringRef Data(P, DataSize);
+ for (unsigned i = 0; i < LOLC.count; ++i) {
+ std::pair<StringRef,StringRef> Split = Data.split('\0');
+ W.printString("Value", Split.first);
+ Data = Split.second;
+ }
+ }
+ }
+}
diff --git a/contrib/llvm/tools/llvm-readobj/ObjDumper.h b/contrib/llvm/tools/llvm-readobj/ObjDumper.h
index 5ecf0ec..db26d69 100644
--- a/contrib/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/contrib/llvm/tools/llvm-readobj/ObjDumper.h
@@ -1,4 +1,4 @@
-//===-- ObjDumper.h -------------------------------------------------------===//
+//===-- ObjDumper.h ---------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,7 +15,8 @@
namespace llvm {
namespace object {
- class ObjectFile;
+class COFFImportFile;
+class ObjectFile;
}
class StreamWriter;
@@ -38,6 +39,9 @@ public:
virtual void printNeededLibraries() { }
virtual void printProgramHeaders() { }
virtual void printHashTable() { }
+ virtual void printGnuHashTable() { }
+ virtual void printLoadName() {}
+ virtual void printVersionInfo() {}
// Only implemented for ARM ELF at this time.
virtual void printAttributes() { }
@@ -52,6 +56,15 @@ public:
virtual void printCOFFExports() { }
virtual void printCOFFDirectives() { }
virtual void printCOFFBaseReloc() { }
+ virtual void printCodeViewDebugInfo() { }
+
+ // Only implemented for MachO.
+ virtual void printMachODataInCode() { }
+ virtual void printMachOVersionMin() { }
+ virtual void printMachODysymtab() { }
+ virtual void printMachOSegment() { }
+ virtual void printMachOIndirectSymbols() { }
+ virtual void printMachOLinkerOptions() { }
virtual void printStackMap() const = 0;
@@ -71,6 +84,8 @@ std::error_code createMachODumper(const object::ObjectFile *Obj,
StreamWriter &Writer,
std::unique_ptr<ObjDumper> &Result);
+void dumpCOFFImportFile(const object::COFFImportFile *File);
+
} // namespace llvm
#endif
diff --git a/contrib/llvm/tools/llvm-readobj/StreamWriter.h b/contrib/llvm/tools/llvm-readobj/StreamWriter.h
index f3cc57e..d2dbb07 100644
--- a/contrib/llvm/tools/llvm-readobj/StreamWriter.h
+++ b/contrib/llvm/tools/llvm-readobj/StreamWriter.h
@@ -34,14 +34,17 @@ struct HexNumber {
// unsigned type. The overloads are here so that every type that is implicitly
// convertible to an integer (including enums and endian helpers) can be used
// without requiring type traits or call-site changes.
- HexNumber(int8_t Value) : Value(static_cast<uint8_t >(Value)) { }
- HexNumber(int16_t Value) : Value(static_cast<uint16_t>(Value)) { }
- HexNumber(int32_t Value) : Value(static_cast<uint32_t>(Value)) { }
- HexNumber(int64_t Value) : Value(static_cast<uint64_t>(Value)) { }
- HexNumber(uint8_t Value) : Value(Value) { }
- HexNumber(uint16_t Value) : Value(Value) { }
- HexNumber(uint32_t Value) : Value(Value) { }
- HexNumber(uint64_t Value) : Value(Value) { }
+ HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) { }
+ HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) { }
+ HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) { }
+ HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) { }
+ HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) { }
+ HexNumber(signed long long Value) : Value(static_cast<unsigned long long>(Value)) { }
+ HexNumber(unsigned char Value) : Value(Value) { }
+ HexNumber(unsigned short Value) : Value(Value) { }
+ HexNumber(unsigned int Value) : Value(Value) { }
+ HexNumber(unsigned long Value) : Value(Value) { }
+ HexNumber(unsigned long long Value) : Value(Value) { }
uint64_t Value;
};
@@ -194,6 +197,19 @@ public:
OS << "]\n";
}
+ template <typename T>
+ void printHexList(StringRef Label, const T &List) {
+ startLine() << Label << ": [";
+ bool Comma = false;
+ for (const auto &Item : List) {
+ if (Comma)
+ OS << ", ";
+ OS << hex(Item);
+ Comma = true;
+ }
+ OS << "]\n";
+ }
+
template<typename T>
void printHex(StringRef Label, T Value) {
startLine() << Label << ": " << hex(Value) << "\n";
diff --git a/contrib/llvm/tools/llvm-readobj/Win64EHDumper.cpp b/contrib/llvm/tools/llvm-readobj/Win64EHDumper.cpp
index f57eea2..2da5ae3 100644
--- a/contrib/llvm/tools/llvm-readobj/Win64EHDumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/Win64EHDumper.cpp
@@ -149,11 +149,8 @@ static std::error_code resolveRelocation(const Dumper::Context &Ctx,
return EC;
ResolvedAddress = *ResolvedAddressOrErr;
- section_iterator SI = Ctx.COFF.section_begin();
- if (std::error_code EC = Symbol.getSection(SI))
- return EC;
-
- ResolvedSection = Ctx.COFF.getCOFFSection(*SI);
+ ErrorOr<section_iterator> SI = Symbol.getSection();
+ ResolvedSection = Ctx.COFF.getCOFFSection(**SI);
return std::error_code();
}
@@ -257,7 +254,7 @@ void Dumper::printUnwindInfo(const Context &Ctx, const coff_section *Section,
return;
}
- printUnwindCode(UI, ArrayRef<UnwindCode>(UCI, UCE));
+ printUnwindCode(UI, makeArrayRef(UCI, UCE));
UCI = UCI + UsedSlots - 1;
}
}
@@ -284,11 +281,11 @@ void Dumper::printRuntimeFunction(const Context &Ctx,
const coff_section *XData;
uint64_t Offset;
- if (error(resolveRelocation(Ctx, Section, SectionOffset + 8, XData, Offset)))
- return;
+ resolveRelocation(Ctx, Section, SectionOffset + 8, XData, Offset);
ArrayRef<uint8_t> Contents;
- if (error(Ctx.COFF.getSectionContents(XData, Contents)) || Contents.empty())
+ error(Ctx.COFF.getSectionContents(XData, Contents));
+ if (Contents.empty())
return;
Offset = Offset + RF.UnwindInfoOffset;
@@ -302,15 +299,15 @@ void Dumper::printRuntimeFunction(const Context &Ctx,
void Dumper::printData(const Context &Ctx) {
for (const auto &Section : Ctx.COFF.sections()) {
StringRef Name;
- if (error(Section.getName(Name)))
- continue;
+ Section.getName(Name);
if (Name != ".pdata" && !Name.startswith(".pdata$"))
continue;
const coff_section *PData = Ctx.COFF.getCOFFSection(Section);
ArrayRef<uint8_t> Contents;
- if (error(Ctx.COFF.getSectionContents(PData, Contents)) || Contents.empty())
+ error(Ctx.COFF.getSectionContents(PData, Contents));
+ if (Contents.empty())
continue;
const RuntimeFunction *Entries =
diff --git a/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 12afacb..fa8fee2 100644
--- a/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -24,6 +24,7 @@
#include "ObjDumper.h"
#include "StreamWriter.h"
#include "llvm/Object/Archive.h"
+#include "llvm/Object/COFFImportFile.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
@@ -131,6 +132,10 @@ namespace opts {
cl::opt<bool> HashTable("hash-table",
cl::desc("Display ELF hash table"));
+ // -gnu-hash-table
+ cl::opt<bool> GnuHashTable("gnu-hash-table",
+ cl::desc("Display ELF .gnu.hash section"));
+
// -expand-relocs
cl::opt<bool> ExpandRelocs("expand-relocs",
cl::desc("Expand each shown relocation to multiple lines"));
@@ -181,25 +186,62 @@ namespace opts {
COFFBaseRelocs("coff-basereloc",
cl::desc("Display the PE/COFF .reloc section"));
+ // -macho-data-in-code
+ cl::opt<bool>
+ MachODataInCode("macho-data-in-code",
+ cl::desc("Display MachO Data in Code command"));
+
+ // -macho-indirect-symbols
+ cl::opt<bool>
+ MachOIndirectSymbols("macho-indirect-symbols",
+ cl::desc("Display MachO indirect symbols"));
+
+ // -macho-linker-options
+ cl::opt<bool>
+ MachOLinkerOptions("macho-linker-options",
+ cl::desc("Display MachO linker options"));
+
+ // -macho-segment
+ cl::opt<bool>
+ MachOSegment("macho-segment",
+ cl::desc("Display MachO Segment command"));
+
+ // -macho-version-min
+ cl::opt<bool>
+ MachOVersionMin("macho-version-min",
+ cl::desc("Display MachO version min command"));
+
+ // -macho-dysymtab
+ cl::opt<bool>
+ MachODysymtab("macho-dysymtab",
+ cl::desc("Display MachO Dysymtab command"));
+
// -stackmap
cl::opt<bool>
PrintStackMap("stackmap",
cl::desc("Display contents of stackmap section"));
+ // -version-info
+ cl::opt<bool>
+ VersionInfo("version-info",
+ cl::desc("Display ELF version sections (if present)"));
+ cl::alias VersionInfoShort("V", cl::desc("Alias for -version-info"),
+ cl::aliasopt(VersionInfo));
} // namespace opts
-static int ReturnValue = EXIT_SUCCESS;
-
namespace llvm {
-bool error(std::error_code EC) {
+LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg) {
+ errs() << "\nError reading file: " << Msg << ".\n";
+ errs().flush();
+ exit(1);
+}
+
+void error(std::error_code EC) {
if (!EC)
- return false;
+ return;
- ReturnValue = EXIT_FAILURE;
- outs() << "\nError reading file: " << EC.message() << ".\n";
- outs().flush();
- return true;
+ reportError(EC.message());
}
bool relocAddressLess(RelocationRef a, RelocationRef b) {
@@ -212,17 +254,14 @@ static void reportError(StringRef Input, std::error_code EC) {
if (Input == "-")
Input = "<stdin>";
- errs() << Input << ": " << EC.message() << "\n";
- errs().flush();
- ReturnValue = EXIT_FAILURE;
+ reportError(Twine(Input) + ": " + EC.message());
}
static void reportError(StringRef Input, StringRef Message) {
if (Input == "-")
Input = "<stdin>";
- errs() << Input << ": " << Message << "\n";
- ReturnValue = EXIT_FAILURE;
+ reportError(Twine(Input) + ": " + Message);
}
static bool isMipsArch(unsigned Arch) {
@@ -253,26 +292,12 @@ static std::error_code createDumper(const ObjectFile *Obj, StreamWriter &Writer,
return readobj_error::unsupported_obj_file_format;
}
-static StringRef getLoadName(const ObjectFile *Obj) {
- if (auto *ELF = dyn_cast<ELF32LEObjectFile>(Obj))
- return ELF->getLoadName();
- if (auto *ELF = dyn_cast<ELF64LEObjectFile>(Obj))
- return ELF->getLoadName();
- if (auto *ELF = dyn_cast<ELF32BEObjectFile>(Obj))
- return ELF->getLoadName();
- if (auto *ELF = dyn_cast<ELF64BEObjectFile>(Obj))
- return ELF->getLoadName();
- llvm_unreachable("Not ELF");
-}
-
/// @brief Dumps the specified object file.
static void dumpObject(const ObjectFile *Obj) {
StreamWriter Writer(outs());
std::unique_ptr<ObjDumper> Dumper;
- if (std::error_code EC = createDumper(Obj, Writer, Dumper)) {
+ if (std::error_code EC = createDumper(Obj, Writer, Dumper))
reportError(Obj->getFileName(), EC);
- return;
- }
outs() << '\n';
outs() << "File: " << Obj->getFileName() << "\n";
@@ -281,8 +306,7 @@ static void dumpObject(const ObjectFile *Obj) {
<< Triple::getArchTypeName((llvm::Triple::ArchType)Obj->getArch())
<< "\n";
outs() << "AddressSize: " << (8*Obj->getBytesInAddress()) << "bit\n";
- if (Obj->isELF())
- outs() << "LoadName: " << getLoadName(Obj) << "\n";
+ Dumper->printLoadName();
if (opts::FileHeaders)
Dumper->printFileHeaders();
@@ -306,6 +330,10 @@ static void dumpObject(const ObjectFile *Obj) {
Dumper->printProgramHeaders();
if (opts::HashTable)
Dumper->printHashTable();
+ if (opts::GnuHashTable)
+ Dumper->printGnuHashTable();
+ if (opts::VersionInfo)
+ Dumper->printVersionInfo();
if (Obj->getArch() == llvm::Triple::arm && Obj->isELF())
if (opts::ARMAttributes)
Dumper->printAttributes();
@@ -317,25 +345,43 @@ static void dumpObject(const ObjectFile *Obj) {
if (opts::MipsReginfo)
Dumper->printMipsReginfo();
}
- if (opts::COFFImports)
- Dumper->printCOFFImports();
- if (opts::COFFExports)
- Dumper->printCOFFExports();
- if (opts::COFFDirectives)
- Dumper->printCOFFDirectives();
- if (opts::COFFBaseRelocs)
- Dumper->printCOFFBaseReloc();
-
+ if (Obj->isCOFF()) {
+ if (opts::COFFImports)
+ Dumper->printCOFFImports();
+ if (opts::COFFExports)
+ Dumper->printCOFFExports();
+ if (opts::COFFDirectives)
+ Dumper->printCOFFDirectives();
+ if (opts::COFFBaseRelocs)
+ Dumper->printCOFFBaseReloc();
+ if (opts::CodeView)
+ Dumper->printCodeViewDebugInfo();
+ }
+ if (Obj->isMachO()) {
+ if (opts::MachODataInCode)
+ Dumper->printMachODataInCode();
+ if (opts::MachOIndirectSymbols)
+ Dumper->printMachOIndirectSymbols();
+ if (opts::MachOLinkerOptions)
+ Dumper->printMachOLinkerOptions();
+ if (opts::MachOSegment)
+ Dumper->printMachOSegment();
+ if (opts::MachOVersionMin)
+ Dumper->printMachOVersionMin();
+ if (opts::MachODysymtab)
+ Dumper->printMachODysymtab();
+ }
if (opts::PrintStackMap)
Dumper->printStackMap();
}
/// @brief Dumps each object file in \a Arc;
static void dumpArchive(const Archive *Arc) {
- for (Archive::child_iterator ArcI = Arc->child_begin(),
- ArcE = Arc->child_end();
- ArcI != ArcE; ++ArcI) {
- ErrorOr<std::unique_ptr<Binary>> ChildOrErr = ArcI->getAsBinary();
+ for (auto &ErrorOrChild : Arc->children()) {
+ if (std::error_code EC = ErrorOrChild.getError())
+ reportError(Arc->getFileName(), EC.message());
+ const auto &Child = *ErrorOrChild;
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
if (std::error_code EC = ChildOrErr.getError()) {
// Ignore non-object files.
if (EC != object_error::invalid_file_type)
@@ -365,18 +411,11 @@ static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary) {
/// @brief Opens \a File and dumps it.
static void dumpInput(StringRef File) {
- // If file isn't stdin, check that it exists.
- if (File != "-" && !sys::fs::exists(File)) {
- reportError(File, readobj_error::file_not_found);
- return;
- }
// Attempt to open the binary.
ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(File);
- if (std::error_code EC = BinaryOrErr.getError()) {
+ if (std::error_code EC = BinaryOrErr.getError())
reportError(File, EC);
- return;
- }
Binary &Binary = *BinaryOrErr.get().getBinary();
if (Archive *Arc = dyn_cast<Archive>(&Binary))
@@ -386,6 +425,8 @@ static void dumpInput(StringRef File) {
dumpMachOUniversalBinary(UBinary);
else if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary))
dumpObject(Obj);
+ else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(&Binary))
+ dumpCOFFImportFile(Import);
else
reportError(File, readobj_error::unrecognized_file_format);
}
@@ -407,5 +448,5 @@ int main(int argc, const char *argv[]) {
std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
dumpInput);
- return ReturnValue;
+ return 0;
}
diff --git a/contrib/llvm/tools/llvm-readobj/llvm-readobj.h b/contrib/llvm/tools/llvm-readobj/llvm-readobj.h
index 74b9a60..5a10392 100644
--- a/contrib/llvm/tools/llvm-readobj/llvm-readobj.h
+++ b/contrib/llvm/tools/llvm-readobj/llvm-readobj.h
@@ -11,6 +11,7 @@
#define LLVM_TOOLS_LLVM_READOBJ_LLVM_READOBJ_H
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
#include <string>
namespace llvm {
@@ -19,7 +20,8 @@ namespace llvm {
}
// Various helper functions.
- bool error(std::error_code ec);
+ LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
+ void error(std::error_code ec);
bool relocAddressLess(object::RelocationRef A,
object::RelocationRef B);
} // namespace llvm
diff --git a/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
index 86f66f8..6ee3a44 100644
--- a/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -94,6 +94,11 @@ CheckFiles("check",
cl::ZeroOrMore);
static cl::opt<uint64_t>
+PreallocMemory("preallocate",
+ cl::desc("Allocate memory upfront rather than on-demand"),
+ cl::init(0));
+
+static cl::opt<uint64_t>
TargetAddrStart("target-addr-start",
cl::desc("For -verify only: start of phony target address "
"range."),
@@ -127,6 +132,12 @@ DummySymbolMappings("dummy-extern",
cl::ZeroOrMore,
cl::Hidden);
+static cl::opt<bool>
+PrintAllocationRequests("print-alloc-requests",
+ cl::desc("Print allocation requests made to the memory "
+ "manager by RuntimeDyld"),
+ cl::Hidden);
+
/* *** */
// A trivial memory manager that doesn't do anything fancy, just uses the
@@ -150,12 +161,6 @@ public:
bool finalizeMemory(std::string *ErrMsg) override { return false; }
- // Invalidate instruction cache for sections with execute permissions.
- // Some platforms with separate data cache and instruction cache require
- // explicit cache flush, otherwise JIT code manipulations (like resolved
- // relocations) will get to the data cache but not to the instruction cache.
- virtual void invalidateInstructionCache();
-
void addDummySymbol(const std::string &Name, uint64_t Addr) {
DummyExterns[Name] = Addr;
}
@@ -173,15 +178,56 @@ public:
size_t Size) override {}
void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
size_t Size) override {}
+
+ void preallocateSlab(uint64_t Size) {
+ std::string Err;
+ sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, &Err);
+ if (!MB.base())
+ report_fatal_error("Can't allocate enough memory: " + Err);
+
+ PreallocSlab = MB;
+ UsePreallocation = true;
+ SlabSize = Size;
+ }
+
+ uint8_t *allocateFromSlab(uintptr_t Size, unsigned Alignment, bool isCode) {
+ Size = RoundUpToAlignment(Size, Alignment);
+ if (CurrentSlabOffset + Size > SlabSize)
+ report_fatal_error("Can't allocate enough memory. Tune --preallocate");
+
+ uintptr_t OldSlabOffset = CurrentSlabOffset;
+ sys::MemoryBlock MB((void *)OldSlabOffset, Size);
+ if (isCode)
+ FunctionMemory.push_back(MB);
+ else
+ DataMemory.push_back(MB);
+ CurrentSlabOffset += Size;
+ return (uint8_t*)OldSlabOffset;
+ }
+
private:
std::map<std::string, uint64_t> DummyExterns;
+ sys::MemoryBlock PreallocSlab;
+ bool UsePreallocation = false;
+ uintptr_t SlabSize = 0;
+ uintptr_t CurrentSlabOffset = 0;
};
uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size,
unsigned Alignment,
unsigned SectionID,
StringRef SectionName) {
- sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, nullptr);
+ if (PrintAllocationRequests)
+ outs() << "allocateCodeSection(Size = " << Size << ", Alignment = "
+ << Alignment << ", SectionName = " << SectionName << ")\n";
+
+ if (UsePreallocation)
+ return allocateFromSlab(Size, Alignment, true /* isCode */);
+
+ std::string Err;
+ sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, &Err);
+ if (!MB.base())
+ report_fatal_error("MemoryManager allocation failed: " + Err);
FunctionMemory.push_back(MB);
return (uint8_t*)MB.base();
}
@@ -191,41 +237,35 @@ uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size,
unsigned SectionID,
StringRef SectionName,
bool IsReadOnly) {
- sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, nullptr);
- DataMemory.push_back(MB);
- return (uint8_t*)MB.base();
-}
+ if (PrintAllocationRequests)
+ outs() << "allocateDataSection(Size = " << Size << ", Alignment = "
+ << Alignment << ", SectionName = " << SectionName << ")\n";
-void TrivialMemoryManager::invalidateInstructionCache() {
- for (int i = 0, e = FunctionMemory.size(); i != e; ++i)
- sys::Memory::InvalidateInstructionCache(FunctionMemory[i].base(),
- FunctionMemory[i].size());
+ if (UsePreallocation)
+ return allocateFromSlab(Size, Alignment, false /* isCode */);
- for (int i = 0, e = DataMemory.size(); i != e; ++i)
- sys::Memory::InvalidateInstructionCache(DataMemory[i].base(),
- DataMemory[i].size());
+ std::string Err;
+ sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, &Err);
+ if (!MB.base())
+ report_fatal_error("MemoryManager allocation failed: " + Err);
+ DataMemory.push_back(MB);
+ return (uint8_t*)MB.base();
}
static const char *ProgramName;
-static void Message(const char *Type, const Twine &Msg) {
- errs() << ProgramName << ": " << Type << ": " << Msg << "\n";
-}
-
static int Error(const Twine &Msg) {
- Message("error", Msg);
+ errs() << ProgramName << ": error: " << Msg << "\n";
return 1;
}
static void loadDylibs() {
for (const std::string &Dylib : Dylibs) {
- if (sys::fs::is_regular_file(Dylib)) {
- std::string ErrMsg;
- if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(), &ErrMsg))
- llvm::errs() << "Error loading '" << Dylib << "': "
- << ErrMsg << "\n";
- } else
- llvm::errs() << "Dylib not found: '" << Dylib << "'.\n";
+ if (!sys::fs::is_regular_file(Dylib))
+ report_fatal_error("Dylib not found: '" + Dylib + "'.");
+ std::string ErrMsg;
+ if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(), &ErrMsg))
+ report_fatal_error("Error loading '" + Dylib + "': " + ErrMsg);
}
}
@@ -240,7 +280,7 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
// If we don't have any input files, read from stdin.
if (!InputFileList.size())
InputFileList.push_back("-");
- for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
+ for (auto &File : InputFileList) {
// Instantiate a dynamic linker.
TrivialMemoryManager MemMgr;
RuntimeDyld Dyld(MemMgr, MemMgr);
@@ -248,7 +288,7 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
// Load the input memory buffer.
ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer =
- MemoryBuffer::getFileOrSTDIN(InputFileList[i]);
+ MemoryBuffer::getFileOrSTDIN(File);
if (std::error_code EC = InputBuffer.getError())
return Error("unable to read input: '" + EC.message() + "'");
@@ -277,6 +317,7 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
if (UseDebugObj) {
DebugObj = LoadedObjInfo->getObjectForDebug(Obj);
SymbolObj = DebugObj.getBinary();
+ LoadedObjInfo.reset();
}
}
@@ -303,12 +344,11 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
// symbol in memory (rather than that in the unrelocated object file)
// and use that to query the DWARFContext.
if (!UseDebugObj && LoadObjects) {
- object::section_iterator Sec(SymbolObj->section_end());
- Sym.getSection(Sec);
+ object::section_iterator Sec = *Sym.getSection();
StringRef SecName;
Sec->getName(SecName);
uint64_t SectionLoadAddress =
- LoadedObjInfo->getSectionLoadAddress(SecName);
+ LoadedObjInfo->getSectionLoadAddress(*Sec);
if (SectionLoadAddress != 0)
Addr += SectionLoadAddress - Sec->getAddress();
}
@@ -317,11 +357,9 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
<< ", Addr = " << Addr << "\n";
DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size);
- DILineInfoTable::iterator Begin = Lines.begin();
- DILineInfoTable::iterator End = Lines.end();
- for (DILineInfoTable::iterator It = Begin; It != End; ++It) {
- outs() << " Line info @ " << It->first - Addr << ": "
- << It->second.FileName << ", line:" << It->second.Line << "\n";
+ for (auto &D : Lines) {
+ outs() << " Line info @ " << D.first - Addr << ": "
+ << D.second.FileName << ", line:" << D.second.Line << "\n";
}
}
}
@@ -330,26 +368,33 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
return 0;
}
+static void doPreallocation(TrivialMemoryManager &MemMgr) {
+ // Allocate a slab of memory upfront, if required. This is used if
+ // we want to test small code models.
+ if (static_cast<intptr_t>(PreallocMemory) < 0)
+ report_fatal_error("Pre-allocated bytes of memory must be a positive integer.");
+
+ // FIXME: Limit the amount of memory that can be preallocated?
+ if (PreallocMemory != 0)
+ MemMgr.preallocateSlab(PreallocMemory);
+}
+
static int executeInput() {
// Load any dylibs requested on the command line.
loadDylibs();
// Instantiate a dynamic linker.
TrivialMemoryManager MemMgr;
+ doPreallocation(MemMgr);
RuntimeDyld Dyld(MemMgr, MemMgr);
- // FIXME: Preserve buffers until resolveRelocations time to work around a bug
- // in RuntimeDyldELF.
- // This fixme should be fixed ASAP. This is a very brittle workaround.
- std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
-
// If we don't have any input files, read from stdin.
if (!InputFileList.size())
InputFileList.push_back("-");
- for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
+ for (auto &File : InputFileList) {
// Load the input memory buffer.
ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer =
- MemoryBuffer::getFileOrSTDIN(InputFileList[i]);
+ MemoryBuffer::getFileOrSTDIN(File);
if (std::error_code EC = InputBuffer.getError())
return Error("unable to read input: '" + EC.message() + "'");
ErrorOr<std::unique_ptr<ObjectFile>> MaybeObj(
@@ -359,7 +404,6 @@ static int executeInput() {
return Error("unable to create object file: '" + EC.message() + "'");
ObjectFile &Obj = **MaybeObj;
- InputBuffers.push_back(std::move(*InputBuffer));
// Load the object file
Dyld.loadObject(Obj);
@@ -368,12 +412,9 @@ static int executeInput() {
}
}
- // Resolve all the relocations we can.
- Dyld.resolveRelocations();
- // Clear instruction cache before code will be executed.
- MemMgr.invalidateInstructionCache();
-
+ // Resove all the relocations we can.
// FIXME: Error out if there are unresolved relocations.
+ Dyld.resolveRelocations();
// Get the address of the entry point (_main by default).
void *MainAddress = Dyld.getSymbolLocalAddress(EntryPoint);
@@ -381,12 +422,12 @@ static int executeInput() {
return Error("no definition for '" + EntryPoint + "'");
// Invalidate the instruction cache for each loaded function.
- for (unsigned i = 0, e = MemMgr.FunctionMemory.size(); i != e; ++i) {
- sys::MemoryBlock &Data = MemMgr.FunctionMemory[i];
+ for (auto &FM : MemMgr.FunctionMemory) {
+
// Make sure the memory is executable.
+ // setExecutable will call InvalidateInstructionCache.
std::string ErrorStr;
- sys::Memory::InvalidateInstructionCache(Data.base(), Data.size());
- if (!sys::Memory::setExecutable(Data, &ErrorStr))
+ if (!sys::Memory::setExecutable(FM, &ErrorStr))
return Error("unable to mark function executable: '" + ErrorStr + "'");
}
@@ -428,11 +469,9 @@ applySpecificSectionMappings(RuntimeDyldChecker &Checker) {
std::string SectionIDStr = Mapping.substr(0, EqualsIdx);
size_t ComaIdx = Mapping.find_first_of(",");
- if (ComaIdx == StringRef::npos) {
- errs() << "Invalid section specification '" << Mapping
- << "'. Should be '<file name>,<section name>=<addr>'\n";
- exit(1);
- }
+ if (ComaIdx == StringRef::npos)
+ report_fatal_error("Invalid section specification '" + Mapping +
+ "'. Should be '<file name>,<section name>=<addr>'");
std::string FileName = SectionIDStr.substr(0, ComaIdx);
std::string SectionName = SectionIDStr.substr(ComaIdx + 1);
@@ -442,20 +481,17 @@ applySpecificSectionMappings(RuntimeDyldChecker &Checker) {
std::tie(OldAddrInt, ErrorMsg) =
Checker.getSectionAddr(FileName, SectionName, true);
- if (ErrorMsg != "") {
- errs() << ErrorMsg;
- exit(1);
- }
+ if (ErrorMsg != "")
+ report_fatal_error(ErrorMsg);
void* OldAddr = reinterpret_cast<void*>(static_cast<uintptr_t>(OldAddrInt));
std::string NewAddrStr = Mapping.substr(EqualsIdx + 1);
uint64_t NewAddr;
- if (StringRef(NewAddrStr).getAsInteger(0, NewAddr)) {
- errs() << "Invalid section address in mapping '" << Mapping << "'.\n";
- exit(1);
- }
+ if (StringRef(NewAddrStr).getAsInteger(0, NewAddr))
+ report_fatal_error("Invalid section address in mapping '" + Mapping +
+ "'.");
Checker.getRTDyld().mapSectionAddress(OldAddr, NewAddr);
SpecificMappings[OldAddr] = NewAddr;
@@ -544,20 +580,16 @@ static void remapSectionsAndSymbols(const llvm::Triple &TargetTriple,
for (const auto &Mapping : DummySymbolMappings) {
size_t EqualsIdx = Mapping.find_first_of("=");
- if (EqualsIdx == StringRef::npos) {
- errs() << "Invalid dummy symbol specification '" << Mapping
- << "'. Should be '<symbol name>=<addr>'\n";
- exit(1);
- }
+ if (EqualsIdx == StringRef::npos)
+ report_fatal_error("Invalid dummy symbol specification '" + Mapping +
+ "'. Should be '<symbol name>=<addr>'");
std::string Symbol = Mapping.substr(0, EqualsIdx);
std::string AddrStr = Mapping.substr(EqualsIdx + 1);
uint64_t Addr;
- if (StringRef(AddrStr).getAsInteger(0, Addr)) {
- errs() << "Invalid symbol mapping '" << Mapping << "'.\n";
- exit(1);
- }
+ if (StringRef(AddrStr).getAsInteger(0, Addr))
+ report_fatal_error("Invalid symbol mapping '" + Mapping + "'.");
MemMgr.addDummySymbol(Symbol, Addr);
}
@@ -569,38 +601,38 @@ static void remapSectionsAndSymbols(const llvm::Triple &TargetTriple,
static int linkAndVerify() {
// Check for missing triple.
- if (TripleName == "") {
- llvm::errs() << "Error: -triple required when running in -verify mode.\n";
- return 1;
- }
+ if (TripleName == "")
+ return Error("-triple required when running in -verify mode.");
// Look up the target and build the disassembler.
Triple TheTriple(Triple::normalize(TripleName));
std::string ErrorStr;
const Target *TheTarget =
TargetRegistry::lookupTarget("", TheTriple, ErrorStr);
- if (!TheTarget) {
- llvm::errs() << "Error accessing target '" << TripleName << "': "
- << ErrorStr << "\n";
- return 1;
- }
+ if (!TheTarget)
+ return Error("Error accessing target '" + TripleName + "': " + ErrorStr);
+
TripleName = TheTriple.getTriple();
std::unique_ptr<MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(TripleName, MCPU, ""));
- assert(STI && "Unable to create subtarget info!");
+ if (!STI)
+ return Error("Unable to create subtarget info!");
std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
- assert(MRI && "Unable to create target register info!");
+ if (!MRI)
+ return Error("Unable to create target register info!");
std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName));
- assert(MAI && "Unable to create target asm info!");
+ if (!MAI)
+ return Error("Unable to create target asm info!");
MCContext Ctx(MAI.get(), MRI.get(), nullptr);
std::unique_ptr<MCDisassembler> Disassembler(
TheTarget->createMCDisassembler(*STI, Ctx));
- assert(Disassembler && "Unable to create disassembler!");
+ if (!Disassembler)
+ return Error("Unable to create disassembler!");
std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
@@ -612,23 +644,19 @@ static int linkAndVerify() {
// Instantiate a dynamic linker.
TrivialMemoryManager MemMgr;
+ doPreallocation(MemMgr);
RuntimeDyld Dyld(MemMgr, MemMgr);
Dyld.setProcessAllSections(true);
RuntimeDyldChecker Checker(Dyld, Disassembler.get(), InstPrinter.get(),
llvm::dbgs());
- // FIXME: Preserve buffers until resolveRelocations time to work around a bug
- // in RuntimeDyldELF.
- // This fixme should be fixed ASAP. This is a very brittle workaround.
- std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
-
// If we don't have any input files, read from stdin.
if (!InputFileList.size())
InputFileList.push_back("-");
- for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
+ for (auto &Filename : InputFileList) {
// Load the input memory buffer.
ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer =
- MemoryBuffer::getFileOrSTDIN(InputFileList[i]);
+ MemoryBuffer::getFileOrSTDIN(Filename);
if (std::error_code EC = InputBuffer.getError())
return Error("unable to read input: '" + EC.message() + "'");
@@ -640,7 +668,6 @@ static int linkAndVerify() {
return Error("unable to create object file: '" + EC.message() + "'");
ObjectFile &Obj = **MaybeObj;
- InputBuffers.push_back(std::move(*InputBuffer));
// Load the object file
Dyld.loadObject(Obj);
@@ -660,11 +687,9 @@ static int linkAndVerify() {
Dyld.registerEHFrames();
int ErrorCode = checkAllExpressions(Checker);
- if (Dyld.hasError()) {
- errs() << "RTDyld reported an error applying relocations:\n "
- << Dyld.getErrorString() << "\n";
- ErrorCode = 1;
- }
+ if (Dyld.hasError())
+ return Error("RTDyld reported an error applying relocations:\n " +
+ Dyld.getErrorString());
return ErrorCode;
}
diff --git a/contrib/llvm/tools/llvm-stress/llvm-stress.cpp b/contrib/llvm/tools/llvm-stress/llvm-stress.cpp
index 6a1a248..99d2afd 100644
--- a/contrib/llvm/tools/llvm-stress/llvm-stress.cpp
+++ b/contrib/llvm/tools/llvm-stress/llvm-stress.cpp
@@ -612,7 +612,8 @@ struct CmpModifier: public Modifier {
}
Value *V = CmpInst::Create(fp ? Instruction::FCmp : Instruction::ICmp,
- op, Val0, Val1, "Cmp", BB->getTerminator());
+ (CmpInst::Predicate)op, Val0, Val1, "Cmp",
+ BB->getTerminator());
return PT->push_back(V);
}
};
@@ -666,7 +667,7 @@ static void IntroduceControlFlow(Function *F, Random &R) {
for (auto *Instr : BoolInst) {
BasicBlock *Curr = Instr->getParent();
- BasicBlock::iterator Loc = Instr;
+ BasicBlock::iterator Loc = Instr->getIterator();
BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF");
Instr->moveBefore(Curr->getTerminator());
if (Curr != &F->getEntryBlock()) {
diff --git a/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp b/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp
deleted file mode 100644
index c57c219..0000000
--- a/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp
+++ /dev/null
@@ -1,532 +0,0 @@
-//===-- LLVMSymbolize.cpp -------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implementation for LLVM symbolization library.
-//
-//===----------------------------------------------------------------------===//
-
-#include "LLVMSymbolize.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Config/config.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/PDB/PDB.h"
-#include "llvm/DebugInfo/PDB/PDBContext.h"
-#include "llvm/Object/ELFObjectFile.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Object/SymbolSize.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compression.h"
-#include "llvm/Support/DataExtractor.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include <sstream>
-#include <stdlib.h>
-
-#if defined(_MSC_VER)
-#include <Windows.h>
-#include <DbgHelp.h>
-#pragma comment(lib, "dbghelp.lib")
-#endif
-
-namespace llvm {
-namespace symbolize {
-
-static bool error(std::error_code ec) {
- if (!ec)
- return false;
- errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
- return true;
-}
-
-static DILineInfoSpecifier
-getDILineInfoSpecifier(const LLVMSymbolizer::Options &Opts) {
- return DILineInfoSpecifier(
- DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
- Opts.PrintFunctions);
-}
-
-ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
- : Module(Obj), DebugInfoContext(DICtx) {
- std::unique_ptr<DataExtractor> OpdExtractor;
- uint64_t OpdAddress = 0;
- // Find the .opd (function descriptor) section if any, for big-endian
- // PowerPC64 ELF.
- if (Module->getArch() == Triple::ppc64) {
- for (section_iterator Section : Module->sections()) {
- StringRef Name;
- if (!error(Section->getName(Name)) && Name == ".opd") {
- StringRef Data;
- if (!error(Section->getContents(Data))) {
- OpdExtractor.reset(new DataExtractor(Data, Module->isLittleEndian(),
- Module->getBytesInAddress()));
- OpdAddress = Section->getAddress();
- }
- break;
- }
- }
- }
- std::vector<std::pair<SymbolRef, uint64_t>> Symbols =
- computeSymbolSizes(*Module);
- for (auto &P : Symbols)
- addSymbol(P.first, P.second, OpdExtractor.get(), OpdAddress);
-}
-
-void ModuleInfo::addSymbol(const SymbolRef &Symbol, uint64_t SymbolSize,
- DataExtractor *OpdExtractor, uint64_t OpdAddress) {
- SymbolRef::Type SymbolType = Symbol.getType();
- if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data)
- return;
- ErrorOr<uint64_t> SymbolAddressOrErr = Symbol.getAddress();
- if (error(SymbolAddressOrErr.getError()))
- return;
- uint64_t SymbolAddress = *SymbolAddressOrErr;
- if (OpdExtractor) {
- // For big-endian PowerPC64 ELF, symbols in the .opd section refer to
- // function descriptors. The first word of the descriptor is a pointer to
- // the function's code.
- // For the purposes of symbolization, pretend the symbol's address is that
- // of the function's code, not the descriptor.
- uint64_t OpdOffset = SymbolAddress - OpdAddress;
- uint32_t OpdOffset32 = OpdOffset;
- if (OpdOffset == OpdOffset32 &&
- OpdExtractor->isValidOffsetForAddress(OpdOffset32))
- SymbolAddress = OpdExtractor->getAddress(&OpdOffset32);
- }
- ErrorOr<StringRef> SymbolNameOrErr = Symbol.getName();
- if (error(SymbolNameOrErr.getError()))
- return;
- StringRef SymbolName = *SymbolNameOrErr;
- // Mach-O symbol table names have leading underscore, skip it.
- if (Module->isMachO() && SymbolName.size() > 0 && SymbolName[0] == '_')
- SymbolName = SymbolName.drop_front();
- // FIXME: If a function has alias, there are two entries in symbol table
- // with same address size. Make sure we choose the correct one.
- auto &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
- SymbolDesc SD = { SymbolAddress, SymbolSize };
- M.insert(std::make_pair(SD, SymbolName));
-}
-
-bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
- std::string &Name, uint64_t &Addr,
- uint64_t &Size) const {
- const auto &SymbolMap = Type == SymbolRef::ST_Function ? Functions : Objects;
- if (SymbolMap.empty())
- return false;
- SymbolDesc SD = { Address, Address };
- auto SymbolIterator = SymbolMap.upper_bound(SD);
- if (SymbolIterator == SymbolMap.begin())
- return false;
- --SymbolIterator;
- if (SymbolIterator->first.Size != 0 &&
- SymbolIterator->first.Addr + SymbolIterator->first.Size <= Address)
- return false;
- Name = SymbolIterator->second.str();
- Addr = SymbolIterator->first.Addr;
- Size = SymbolIterator->first.Size;
- return true;
-}
-
-DILineInfo ModuleInfo::symbolizeCode(
- uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
- DILineInfo LineInfo;
- if (DebugInfoContext) {
- LineInfo = DebugInfoContext->getLineInfoForAddress(
- ModuleOffset, getDILineInfoSpecifier(Opts));
- }
- // Override function name from symbol table if necessary.
- if (Opts.PrintFunctions != FunctionNameKind::None && Opts.UseSymbolTable) {
- std::string FunctionName;
- uint64_t Start, Size;
- if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
- FunctionName, Start, Size)) {
- LineInfo.FunctionName = FunctionName;
- }
- }
- return LineInfo;
-}
-
-DIInliningInfo ModuleInfo::symbolizeInlinedCode(
- uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
- DIInliningInfo InlinedContext;
-
- if (DebugInfoContext) {
- InlinedContext = DebugInfoContext->getInliningInfoForAddress(
- ModuleOffset, getDILineInfoSpecifier(Opts));
- }
- // Make sure there is at least one frame in context.
- if (InlinedContext.getNumberOfFrames() == 0) {
- InlinedContext.addFrame(DILineInfo());
- }
- // Override the function name in lower frame with name from symbol table.
- if (Opts.PrintFunctions != FunctionNameKind::None && Opts.UseSymbolTable) {
- DIInliningInfo PatchedInlinedContext;
- for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {
- DILineInfo LineInfo = InlinedContext.getFrame(i);
- if (i == n - 1) {
- std::string FunctionName;
- uint64_t Start, Size;
- if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
- FunctionName, Start, Size)) {
- LineInfo.FunctionName = FunctionName;
- }
- }
- PatchedInlinedContext.addFrame(LineInfo);
- }
- InlinedContext = PatchedInlinedContext;
- }
- return InlinedContext;
-}
-
-bool ModuleInfo::symbolizeData(uint64_t ModuleOffset, std::string &Name,
- uint64_t &Start, uint64_t &Size) const {
- return getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Name, Start,
- Size);
-}
-
-const char LLVMSymbolizer::kBadString[] = "??";
-
-std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
- uint64_t ModuleOffset) {
- ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
- if (!Info)
- return printDILineInfo(DILineInfo());
- if (Opts.PrintInlining) {
- DIInliningInfo InlinedContext =
- Info->symbolizeInlinedCode(ModuleOffset, Opts);
- uint32_t FramesNum = InlinedContext.getNumberOfFrames();
- assert(FramesNum > 0);
- std::string Result;
- for (uint32_t i = 0; i < FramesNum; i++) {
- DILineInfo LineInfo = InlinedContext.getFrame(i);
- Result += printDILineInfo(LineInfo);
- }
- return Result;
- }
- DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts);
- return printDILineInfo(LineInfo);
-}
-
-std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
- uint64_t ModuleOffset) {
- std::string Name = kBadString;
- uint64_t Start = 0;
- uint64_t Size = 0;
- if (Opts.UseSymbolTable) {
- if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) {
- if (Info->symbolizeData(ModuleOffset, Name, Start, Size) && Opts.Demangle)
- Name = DemangleName(Name);
- }
- }
- std::stringstream ss;
- ss << Name << "\n" << Start << " " << Size << "\n";
- return ss.str();
-}
-
-void LLVMSymbolizer::flush() {
- DeleteContainerSeconds(Modules);
- ObjectPairForPathArch.clear();
- ObjectFileForArch.clear();
-}
-
-// For Path="/path/to/foo" and Basename="foo" assume that debug info is in
-// /path/to/foo.dSYM/Contents/Resources/DWARF/foo.
-// For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in
-// /path/to/bar.dSYM/Contents/Resources/DWARF/foo.
-static
-std::string getDarwinDWARFResourceForPath(
- const std::string &Path, const std::string &Basename) {
- SmallString<16> ResourceName = StringRef(Path);
- if (sys::path::extension(Path) != ".dSYM") {
- ResourceName += ".dSYM";
- }
- sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
- sys::path::append(ResourceName, Basename);
- return ResourceName.str();
-}
-
-static bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
- MemoryBuffer::getFileOrSTDIN(Path);
- if (!MB)
- return false;
- return !zlib::isAvailable() || CRCHash == zlib::crc32(MB.get()->getBuffer());
-}
-
-static bool findDebugBinary(const std::string &OrigPath,
- const std::string &DebuglinkName, uint32_t CRCHash,
- std::string &Result) {
- std::string OrigRealPath = OrigPath;
-#if defined(HAVE_REALPATH)
- if (char *RP = realpath(OrigPath.c_str(), nullptr)) {
- OrigRealPath = RP;
- free(RP);
- }
-#endif
- SmallString<16> OrigDir(OrigRealPath);
- llvm::sys::path::remove_filename(OrigDir);
- SmallString<16> DebugPath = OrigDir;
- // Try /path/to/original_binary/debuglink_name
- llvm::sys::path::append(DebugPath, DebuglinkName);
- if (checkFileCRC(DebugPath, CRCHash)) {
- Result = DebugPath.str();
- return true;
- }
- // Try /path/to/original_binary/.debug/debuglink_name
- DebugPath = OrigRealPath;
- llvm::sys::path::append(DebugPath, ".debug", DebuglinkName);
- if (checkFileCRC(DebugPath, CRCHash)) {
- Result = DebugPath.str();
- return true;
- }
- // Try /usr/lib/debug/path/to/original_binary/debuglink_name
- DebugPath = "/usr/lib/debug";
- llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir),
- DebuglinkName);
- if (checkFileCRC(DebugPath, CRCHash)) {
- Result = DebugPath.str();
- return true;
- }
- return false;
-}
-
-static bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName,
- uint32_t &CRCHash) {
- if (!Obj)
- return false;
- for (const SectionRef &Section : Obj->sections()) {
- StringRef Name;
- Section.getName(Name);
- Name = Name.substr(Name.find_first_not_of("._"));
- if (Name == "gnu_debuglink") {
- StringRef Data;
- Section.getContents(Data);
- DataExtractor DE(Data, Obj->isLittleEndian(), 0);
- uint32_t Offset = 0;
- if (const char *DebugNameStr = DE.getCStr(&Offset)) {
- // 4-byte align the offset.
- Offset = (Offset + 3) & ~0x3;
- if (DE.isValidOffsetForDataOfSize(Offset, 4)) {
- DebugName = DebugNameStr;
- CRCHash = DE.getU32(&Offset);
- return true;
- }
- }
- break;
- }
- }
- return false;
-}
-
-static
-bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj,
- const MachOObjectFile *Obj) {
- ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid();
- ArrayRef<uint8_t> bin_uuid = Obj->getUuid();
- if (dbg_uuid.empty() || bin_uuid.empty())
- return false;
- return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
-}
-
-ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
- const MachOObjectFile *MachExeObj, const std::string &ArchName) {
- // On Darwin we may find DWARF in separate object file in
- // resource directory.
- std::vector<std::string> DsymPaths;
- StringRef Filename = sys::path::filename(ExePath);
- DsymPaths.push_back(getDarwinDWARFResourceForPath(ExePath, Filename));
- for (const auto &Path : Opts.DsymHints) {
- DsymPaths.push_back(getDarwinDWARFResourceForPath(Path, Filename));
- }
- for (const auto &path : DsymPaths) {
- ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(path);
- std::error_code EC = BinaryOrErr.getError();
- if (EC != errc::no_such_file_or_directory && !error(EC)) {
- OwningBinary<Binary> B = std::move(BinaryOrErr.get());
- ObjectFile *DbgObj =
- getObjectFileFromBinary(B.getBinary(), ArchName);
- const MachOObjectFile *MachDbgObj =
- dyn_cast<const MachOObjectFile>(DbgObj);
- if (!MachDbgObj) continue;
- if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj)) {
- addOwningBinary(std::move(B));
- return DbgObj;
- }
- }
- }
- return nullptr;
-}
-
-LLVMSymbolizer::ObjectPair
-LLVMSymbolizer::getOrCreateObjects(const std::string &Path,
- const std::string &ArchName) {
- const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
- if (I != ObjectPairForPathArch.end())
- return I->second;
- ObjectFile *Obj = nullptr;
- ObjectFile *DbgObj = nullptr;
- ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(Path);
- if (!error(BinaryOrErr.getError())) {
- OwningBinary<Binary> &B = BinaryOrErr.get();
- Obj = getObjectFileFromBinary(B.getBinary(), ArchName);
- if (!Obj) {
- ObjectPair Res = std::make_pair(nullptr, nullptr);
- ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res;
- return Res;
- }
- addOwningBinary(std::move(B));
- if (auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
- DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
- // Try to locate the debug binary using .gnu_debuglink section.
- if (!DbgObj) {
- std::string DebuglinkName;
- uint32_t CRCHash;
- std::string DebugBinaryPath;
- if (getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash) &&
- findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) {
- BinaryOrErr = createBinary(DebugBinaryPath);
- if (!error(BinaryOrErr.getError())) {
- OwningBinary<Binary> B = std::move(BinaryOrErr.get());
- DbgObj = getObjectFileFromBinary(B.getBinary(), ArchName);
- addOwningBinary(std::move(B));
- }
- }
- }
- }
- if (!DbgObj)
- DbgObj = Obj;
- ObjectPair Res = std::make_pair(Obj, DbgObj);
- ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res;
- return Res;
-}
-
-ObjectFile *
-LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin,
- const std::string &ArchName) {
- if (!Bin)
- return nullptr;
- ObjectFile *Res = nullptr;
- if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
- const auto &I = ObjectFileForArch.find(
- std::make_pair(UB, ArchName));
- if (I != ObjectFileForArch.end())
- return I->second;
- ErrorOr<std::unique_ptr<ObjectFile>> ParsedObj =
- UB->getObjectForArch(ArchName);
- if (ParsedObj) {
- Res = ParsedObj.get().get();
- ParsedBinariesAndObjects.push_back(std::move(ParsedObj.get()));
- }
- ObjectFileForArch[std::make_pair(UB, ArchName)] = Res;
- } else if (Bin->isObject()) {
- Res = cast<ObjectFile>(Bin);
- }
- return Res;
-}
-
-ModuleInfo *
-LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
- const auto &I = Modules.find(ModuleName);
- if (I != Modules.end())
- return I->second;
- std::string BinaryName = ModuleName;
- std::string ArchName = Opts.DefaultArch;
- size_t ColonPos = ModuleName.find_last_of(':');
- // Verify that substring after colon form a valid arch name.
- if (ColonPos != std::string::npos) {
- std::string ArchStr = ModuleName.substr(ColonPos + 1);
- if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
- BinaryName = ModuleName.substr(0, ColonPos);
- ArchName = ArchStr;
- }
- }
- ObjectPair Objects = getOrCreateObjects(BinaryName, ArchName);
-
- if (!Objects.first) {
- // Failed to find valid object file.
- Modules.insert(make_pair(ModuleName, (ModuleInfo *)nullptr));
- return nullptr;
- }
- DIContext *Context = nullptr;
- if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
- // If this is a COFF object, assume it contains PDB debug information. If
- // we don't find any we will fall back to the DWARF case.
- std::unique_ptr<IPDBSession> Session;
- PDB_ErrorCode Error = loadDataForEXE(PDB_ReaderType::DIA,
- Objects.first->getFileName(), Session);
- if (Error == PDB_ErrorCode::Success) {
- Context = new PDBContext(*CoffObject, std::move(Session),
- Opts.RelativeAddresses);
- }
- }
- if (!Context)
- Context = new DWARFContextInMemory(*Objects.second);
- assert(Context);
- ModuleInfo *Info = new ModuleInfo(Objects.first, Context);
- Modules.insert(make_pair(ModuleName, Info));
- return Info;
-}
-
-std::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const {
- // By default, DILineInfo contains "<invalid>" for function/filename it
- // cannot fetch. We replace it to "??" to make our output closer to addr2line.
- static const std::string kDILineInfoBadString = "<invalid>";
- std::stringstream Result;
- if (Opts.PrintFunctions != FunctionNameKind::None) {
- std::string FunctionName = LineInfo.FunctionName;
- if (FunctionName == kDILineInfoBadString)
- FunctionName = kBadString;
- else if (Opts.Demangle)
- FunctionName = DemangleName(FunctionName);
- Result << FunctionName << "\n";
- }
- std::string Filename = LineInfo.FileName;
- if (Filename == kDILineInfoBadString)
- Filename = kBadString;
- Result << Filename << ":" << LineInfo.Line << ":" << LineInfo.Column << "\n";
- return Result.str();
-}
-
-#if !defined(_MSC_VER)
-// Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
-extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
- size_t *length, int *status);
-#endif
-
-std::string LLVMSymbolizer::DemangleName(const std::string &Name) {
-#if !defined(_MSC_VER)
- // We can spoil names of symbols with C linkage, so use an heuristic
- // approach to check if the name should be demangled.
- if (Name.substr(0, 2) != "_Z")
- return Name;
- int status = 0;
- char *DemangledName = __cxa_demangle(Name.c_str(), nullptr, nullptr, &status);
- if (status != 0)
- return Name;
- std::string Result = DemangledName;
- free(DemangledName);
- return Result;
-#else
- char DemangledName[1024] = {0};
- DWORD result = ::UnDecorateSymbolName(
- Name.c_str(), DemangledName, 1023,
- UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected
- UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc
- UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications
- UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers
- UNDNAME_NO_MS_KEYWORDS | // Strip all MS extension keywords
- UNDNAME_NO_FUNCTION_RETURNS); // Strip function return types
-
- return (result == 0) ? Name : std::string(DemangledName);
-#endif
-}
-
-} // namespace symbolize
-} // namespace llvm
diff --git a/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.h b/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.h
deleted file mode 100644
index be246c3..0000000
--- a/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.h
+++ /dev/null
@@ -1,144 +0,0 @@
-//===-- LLVMSymbolize.h ----------------------------------------- C++ -----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Header for LLVM symbolization library.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_TOOLS_LLVM_SYMBOLIZER_LLVMSYMBOLIZE_H
-#define LLVM_TOOLS_LLVM_SYMBOLIZER_LLVMSYMBOLIZE_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/DIContext.h"
-#include "llvm/Object/MachOUniversal.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/DataExtractor.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include <map>
-#include <memory>
-#include <string>
-
-namespace llvm {
-
-typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind;
-using namespace object;
-
-namespace symbolize {
-
-class ModuleInfo;
-
-class LLVMSymbolizer {
-public:
- struct Options {
- FunctionNameKind PrintFunctions;
- bool UseSymbolTable : 1;
- bool PrintInlining : 1;
- bool Demangle : 1;
- bool RelativeAddresses : 1;
- std::string DefaultArch;
- std::vector<std::string> DsymHints;
- Options(FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName,
- bool UseSymbolTable = true, bool PrintInlining = true,
- bool Demangle = true, bool RelativeAddresses = false,
- std::string DefaultArch = "")
- : PrintFunctions(PrintFunctions), UseSymbolTable(UseSymbolTable),
- PrintInlining(PrintInlining), Demangle(Demangle),
- RelativeAddresses(RelativeAddresses), DefaultArch(DefaultArch) {}
- };
-
- LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {}
- ~LLVMSymbolizer() {
- flush();
- }
-
- // Returns the result of symbolization for module name/offset as
- // a string (possibly containing newlines).
- std::string
- symbolizeCode(const std::string &ModuleName, uint64_t ModuleOffset);
- std::string
- symbolizeData(const std::string &ModuleName, uint64_t ModuleOffset);
- void flush();
- static std::string DemangleName(const std::string &Name);
-private:
- typedef std::pair<ObjectFile*, ObjectFile*> ObjectPair;
-
- ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName);
- ObjectFile *lookUpDsymFile(const std::string &Path, const MachOObjectFile *ExeObj,
- const std::string &ArchName);
-
- /// \brief Returns pair of pointers to object and debug object.
- ObjectPair getOrCreateObjects(const std::string &Path,
- const std::string &ArchName);
- /// \brief Returns a parsed object file for a given architecture in a
- /// universal binary (or the binary itself if it is an object file).
- ObjectFile *getObjectFileFromBinary(Binary *Bin, const std::string &ArchName);
-
- std::string printDILineInfo(DILineInfo LineInfo) const;
-
- // Owns all the parsed binaries and object files.
- SmallVector<std::unique_ptr<Binary>, 4> ParsedBinariesAndObjects;
- SmallVector<std::unique_ptr<MemoryBuffer>, 4> MemoryBuffers;
- void addOwningBinary(OwningBinary<Binary> OwningBin) {
- std::unique_ptr<Binary> Bin;
- std::unique_ptr<MemoryBuffer> MemBuf;
- std::tie(Bin, MemBuf) = OwningBin.takeBinary();
- ParsedBinariesAndObjects.push_back(std::move(Bin));
- MemoryBuffers.push_back(std::move(MemBuf));
- }
-
- // Owns module info objects.
- std::map<std::string, ModuleInfo *> Modules;
- std::map<std::pair<MachOUniversalBinary *, std::string>, ObjectFile *>
- ObjectFileForArch;
- std::map<std::pair<std::string, std::string>, ObjectPair>
- ObjectPairForPathArch;
-
- Options Opts;
- static const char kBadString[];
-};
-
-class ModuleInfo {
-public:
- ModuleInfo(ObjectFile *Obj, DIContext *DICtx);
-
- DILineInfo symbolizeCode(uint64_t ModuleOffset,
- const LLVMSymbolizer::Options &Opts) const;
- DIInliningInfo symbolizeInlinedCode(
- uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const;
- bool symbolizeData(uint64_t ModuleOffset, std::string &Name, uint64_t &Start,
- uint64_t &Size) const;
-
-private:
- bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
- std::string &Name, uint64_t &Addr,
- uint64_t &Size) const;
- // For big-endian PowerPC64 ELF, OpdAddress is the address of the .opd
- // (function descriptor) section and OpdExtractor refers to its contents.
- void addSymbol(const SymbolRef &Symbol, uint64_t SymbolSize,
- DataExtractor *OpdExtractor = nullptr,
- uint64_t OpdAddress = 0);
- ObjectFile *Module;
- std::unique_ptr<DIContext> DebugInfoContext;
-
- struct SymbolDesc {
- uint64_t Addr;
- // If size is 0, assume that symbol occupies the whole memory range up to
- // the following symbol.
- uint64_t Size;
- friend bool operator<(const SymbolDesc &s1, const SymbolDesc &s2) {
- return s1.Addr < s2.Addr;
- }
- };
- std::map<SymbolDesc, StringRef> Functions;
- std::map<SymbolDesc, StringRef> Objects;
-};
-
-} // namespace symbolize
-} // namespace llvm
-
-#endif
diff --git a/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index 9c9f3ad..9503493 100644
--- a/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -15,8 +15,9 @@
//
//===----------------------------------------------------------------------===//
-#include "LLVMSymbolize.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
+#include "llvm/DebugInfo/Symbolize/Symbolize.h"
#include "llvm/Support/COM.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -73,19 +74,33 @@ static cl::list<std::string>
ClDsymHint("dsym-hint", cl::ZeroOrMore,
cl::desc("Path to .dSYM bundles to search for debug info for the "
"object files"));
+static cl::opt<bool>
+ ClPrintAddress("print-address", cl::init(false),
+ cl::desc("Show address before line information"));
+
+static cl::opt<bool>
+ ClPrettyPrint("pretty-print", cl::init(false),
+ cl::desc("Make the output more human friendly"));
+
+static cl::opt<int> ClPrintSourceContextLines(
+ "print-source-context-lines", cl::init(0),
+ cl::desc("Print N number of source file context"));
+
+static bool error(std::error_code ec) {
+ if (!ec)
+ return false;
+ errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
+ return true;
+}
-static bool parseCommand(bool &IsData, std::string &ModuleName,
- uint64_t &ModuleOffset) {
+static bool parseCommand(StringRef InputString, bool &IsData,
+ std::string &ModuleName, uint64_t &ModuleOffset) {
const char *kDataCmd = "DATA ";
const char *kCodeCmd = "CODE ";
- const int kMaxInputStringLength = 1024;
- const char kDelimiters[] = " \n";
- char InputString[kMaxInputStringLength];
- if (!fgets(InputString, sizeof(InputString), stdin))
- return false;
+ const char kDelimiters[] = " \n\r";
IsData = false;
ModuleName = "";
- char *pos = InputString;
+ const char *pos = InputString.data();
if (strncmp(pos, kDataCmd, strlen(kDataCmd)) == 0) {
IsData = true;
pos += strlen(kDataCmd);
@@ -102,7 +117,7 @@ static bool parseCommand(bool &IsData, std::string &ModuleName,
if (*pos == '"' || *pos == '\'') {
char quote = *pos;
pos++;
- char *end = strchr(pos, quote);
+ const char *end = strchr(pos, quote);
if (!end)
return false;
ModuleName = std::string(pos, end - pos);
@@ -118,9 +133,7 @@ static bool parseCommand(bool &IsData, std::string &ModuleName,
// Skip delimiters and parse module offset.
pos += strspn(pos, kDelimiters);
int offset_length = strcspn(pos, kDelimiters);
- if (StringRef(pos, offset_length).getAsInteger(0, ModuleOffset))
- return false;
- return true;
+ return !StringRef(pos, offset_length).getAsInteger(0, ModuleOffset);
}
int main(int argc, char **argv) {
@@ -132,9 +145,9 @@ int main(int argc, char **argv) {
llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
cl::ParseCommandLineOptions(argc, argv, "llvm-symbolizer\n");
- LLVMSymbolizer::Options Opts(ClPrintFunctions, ClUseSymbolTable,
- ClPrintInlining, ClDemangle,
+ LLVMSymbolizer::Options Opts(ClPrintFunctions, ClUseSymbolTable, ClDemangle,
ClUseRelativeAddress, ClDefaultArch);
+
for (const auto &hint : ClDsymHint) {
if (sys::path::extension(hint) == ".dSYM") {
Opts.DsymHints.push_back(hint);
@@ -145,14 +158,43 @@ int main(int argc, char **argv) {
}
LLVMSymbolizer Symbolizer(Opts);
- bool IsData = false;
- std::string ModuleName;
- uint64_t ModuleOffset;
- while (parseCommand(IsData, ModuleName, ModuleOffset)) {
- std::string Result =
- IsData ? Symbolizer.symbolizeData(ModuleName, ModuleOffset)
- : Symbolizer.symbolizeCode(ModuleName, ModuleOffset);
- outs() << Result << "\n";
+ DIPrinter Printer(outs(), ClPrintFunctions != FunctionNameKind::None,
+ ClPrettyPrint, ClPrintSourceContextLines);
+
+ const int kMaxInputStringLength = 1024;
+ char InputString[kMaxInputStringLength];
+
+ while (true) {
+ if (!fgets(InputString, sizeof(InputString), stdin))
+ break;
+
+ bool IsData = false;
+ std::string ModuleName;
+ uint64_t ModuleOffset = 0;
+ if (!parseCommand(StringRef(InputString), IsData, ModuleName,
+ ModuleOffset)) {
+ outs() << InputString;
+ continue;
+ }
+
+ if (ClPrintAddress) {
+ outs() << "0x";
+ outs().write_hex(ModuleOffset);
+ StringRef Delimiter = (ClPrettyPrint == true) ? ": " : "\n";
+ outs() << Delimiter;
+ }
+ if (IsData) {
+ auto ResOrErr = Symbolizer.symbolizeData(ModuleName, ModuleOffset);
+ Printer << (error(ResOrErr.getError()) ? DIGlobal() : ResOrErr.get());
+ } else if (ClPrintInlining) {
+ auto ResOrErr = Symbolizer.symbolizeInlinedCode(ModuleName, ModuleOffset);
+ Printer << (error(ResOrErr.getError()) ? DIInliningInfo()
+ : ResOrErr.get());
+ } else {
+ auto ResOrErr = Symbolizer.symbolizeCode(ModuleName, ModuleOffset);
+ Printer << (error(ResOrErr.getError()) ? DILineInfo() : ResOrErr.get());
+ }
+ outs() << "\n";
outs().flush();
}
diff --git a/contrib/llvm/tools/macho-dump/macho-dump.cpp b/contrib/llvm/tools/macho-dump/macho-dump.cpp
deleted file mode 100644
index 39c2860..0000000
--- a/contrib/llvm/tools/macho-dump/macho-dump.cpp
+++ /dev/null
@@ -1,434 +0,0 @@
-//===-- macho-dump.cpp - Mach Object Dumping Tool -------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is a testing tool for use with the MC/Mach-O LLVM components.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Object/MachO.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <system_error>
-using namespace llvm;
-using namespace llvm::object;
-
-static cl::opt<std::string>
-InputFile(cl::Positional, cl::desc("<input file>"), cl::init("-"));
-
-static cl::opt<bool>
-ShowSectionData("dump-section-data", cl::desc("Dump the contents of sections"),
- cl::init(false));
-
-///
-
-static const char *ProgramName;
-
-static void Message(const char *Type, const Twine &Msg) {
- errs() << ProgramName << ": " << Type << ": " << Msg << "\n";
-}
-
-static int Error(const Twine &Msg) {
- Message("error", Msg);
- return 1;
-}
-
-static void Warning(const Twine &Msg) {
- Message("warning", Msg);
-}
-
-///
-
-static void DumpSegmentCommandData(StringRef Name,
- uint64_t VMAddr, uint64_t VMSize,
- uint64_t FileOffset, uint64_t FileSize,
- uint32_t MaxProt, uint32_t InitProt,
- uint32_t NumSections, uint32_t Flags) {
- outs() << " ('segment_name', '";
- outs().write_escaped(Name, /*UseHexEscapes=*/true) << "')\n";
- outs() << " ('vm_addr', " << VMAddr << ")\n";
- outs() << " ('vm_size', " << VMSize << ")\n";
- outs() << " ('file_offset', " << FileOffset << ")\n";
- outs() << " ('file_size', " << FileSize << ")\n";
- outs() << " ('maxprot', " << MaxProt << ")\n";
- outs() << " ('initprot', " << InitProt << ")\n";
- outs() << " ('num_sections', " << NumSections << ")\n";
- outs() << " ('flags', " << Flags << ")\n";
-}
-
-static int DumpSectionData(const MachOObjectFile &Obj, unsigned Index,
- StringRef Name,
- StringRef SegmentName, uint64_t Address,
- uint64_t Size, uint32_t Offset,
- uint32_t Align, uint32_t RelocationTableOffset,
- uint32_t NumRelocationTableEntries,
- uint32_t Flags, uint32_t Reserved1,
- uint32_t Reserved2, uint64_t Reserved3 = ~0ULL) {
- outs() << " # Section " << Index << "\n";
- outs() << " (('section_name', '";
- outs().write_escaped(Name, /*UseHexEscapes=*/true) << "')\n";
- outs() << " ('segment_name', '";
- outs().write_escaped(SegmentName, /*UseHexEscapes=*/true) << "')\n";
- outs() << " ('address', " << Address << ")\n";
- outs() << " ('size', " << Size << ")\n";
- outs() << " ('offset', " << Offset << ")\n";
- outs() << " ('alignment', " << Align << ")\n";
- outs() << " ('reloc_offset', " << RelocationTableOffset << ")\n";
- outs() << " ('num_reloc', " << NumRelocationTableEntries << ")\n";
- outs() << " ('flags', " << format("0x%x", Flags) << ")\n";
- outs() << " ('reserved1', " << Reserved1 << ")\n";
- outs() << " ('reserved2', " << Reserved2 << ")\n";
- if (Reserved3 != ~0ULL)
- outs() << " ('reserved3', " << Reserved3 << ")\n";
- outs() << " ),\n";
-
- // Dump the relocation entries.
- outs() << " ('_relocations', [\n";
- unsigned RelNum = 0;
- for (relocation_iterator I = Obj.section_rel_begin(Index),
- E = Obj.section_rel_end(Index);
- I != E; ++I, ++RelNum) {
- MachO::any_relocation_info RE = Obj.getRelocation(I->getRawDataRefImpl());
- outs() << " # Relocation " << RelNum << "\n";
- outs() << " (('word-0', " << format("0x%x", RE.r_word0) << "),\n";
- outs() << " ('word-1', " << format("0x%x", RE.r_word1) << ")),\n";
- }
- outs() << " ])\n";
-
- // Dump the section data, if requested.
- if (ShowSectionData) {
- outs() << " ('_section_data', '";
- StringRef Data = Obj.getData().substr(Offset, Size);
- for (unsigned i = 0; i != Data.size(); ++i) {
- if (i && (i % 4) == 0)
- outs() << ' ';
- outs() << hexdigit((Data[i] >> 4) & 0xF, /*LowerCase=*/true);
- outs() << hexdigit((Data[i] >> 0) & 0xF, /*LowerCase=*/true);
- }
- outs() << "')\n";
- }
-
- return 0;
-}
-
-static int DumpSegmentCommand(const MachOObjectFile &Obj,
- const MachOObjectFile::LoadCommandInfo &LCI) {
- MachO::segment_command SLC = Obj.getSegmentLoadCommand(LCI);
-
- DumpSegmentCommandData(StringRef(SLC.segname, 16), SLC.vmaddr,
- SLC.vmsize, SLC.fileoff, SLC.filesize,
- SLC.maxprot, SLC.initprot, SLC.nsects, SLC.flags);
-
- // Dump the sections.
- outs() << " ('sections', [\n";
- for (unsigned i = 0; i != SLC.nsects; ++i) {
- MachO::section Sect = Obj.getSection(LCI, i);
- DumpSectionData(Obj, i, StringRef(Sect.sectname, 16),
- StringRef(Sect.segname, 16), Sect.addr,
- Sect.size, Sect.offset, Sect.align,
- Sect.reloff, Sect.nreloc, Sect.flags,
- Sect.reserved1, Sect.reserved2);
- }
- outs() << " ])\n";
-
- return 0;
-}
-
-static int DumpSegment64Command(const MachOObjectFile &Obj,
- const MachOObjectFile::LoadCommandInfo &LCI) {
- MachO::segment_command_64 SLC = Obj.getSegment64LoadCommand(LCI);
- DumpSegmentCommandData(StringRef(SLC.segname, 16), SLC.vmaddr,
- SLC.vmsize, SLC.fileoff, SLC.filesize,
- SLC.maxprot, SLC.initprot, SLC.nsects, SLC.flags);
-
- // Dump the sections.
- outs() << " ('sections', [\n";
- for (unsigned i = 0; i != SLC.nsects; ++i) {
- MachO::section_64 Sect = Obj.getSection64(LCI, i);
-
- DumpSectionData(Obj, i, StringRef(Sect.sectname, 16),
- StringRef(Sect.segname, 16), Sect.addr,
- Sect.size, Sect.offset, Sect.align,
- Sect.reloff, Sect.nreloc, Sect.flags,
- Sect.reserved1, Sect.reserved2,
- Sect.reserved3);
- }
- outs() << " ])\n";
-
- return 0;
-}
-
-static void DumpSymbolTableEntryData(const MachOObjectFile &Obj,
- unsigned Index, uint32_t StringIndex,
- uint8_t Type, uint8_t SectionIndex,
- uint16_t Flags, uint64_t Value,
- StringRef StringTable) {
- const char *Name = &StringTable.data()[StringIndex];
- outs() << " # Symbol " << Index << "\n";
- outs() << " (('n_strx', " << StringIndex << ")\n";
- outs() << " ('n_type', " << format("0x%x", Type) << ")\n";
- outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n";
- outs() << " ('n_desc', " << Flags << ")\n";
- outs() << " ('n_value', " << Value << ")\n";
- outs() << " ('_string', '" << Name << "')\n";
- outs() << " ),\n";
-}
-
-static int DumpSymtabCommand(const MachOObjectFile &Obj) {
- MachO::symtab_command SLC = Obj.getSymtabLoadCommand();
-
- outs() << " ('symoff', " << SLC.symoff << ")\n";
- outs() << " ('nsyms', " << SLC.nsyms << ")\n";
- outs() << " ('stroff', " << SLC.stroff << ")\n";
- outs() << " ('strsize', " << SLC.strsize << ")\n";
-
- // Dump the string data.
- outs() << " ('_string_data', '";
- StringRef StringTable = Obj.getStringTableData();
- outs().write_escaped(StringTable,
- /*UseHexEscapes=*/true) << "')\n";
-
- // Dump the symbol table.
- outs() << " ('_symbols', [\n";
- unsigned SymNum = 0;
- for (const SymbolRef &Symbol : Obj.symbols()) {
- DataRefImpl DRI = Symbol.getRawDataRefImpl();
- if (Obj.is64Bit()) {
- MachO::nlist_64 STE = Obj.getSymbol64TableEntry(DRI);
- DumpSymbolTableEntryData(Obj, SymNum, STE.n_strx, STE.n_type,
- STE.n_sect, STE.n_desc, STE.n_value,
- StringTable);
- } else {
- MachO::nlist STE = Obj.getSymbolTableEntry(DRI);
- DumpSymbolTableEntryData(Obj, SymNum, STE.n_strx, STE.n_type,
- STE.n_sect, STE.n_desc, STE.n_value,
- StringTable);
- }
- SymNum++;
- }
- outs() << " ])\n";
-
- return 0;
-}
-
-static int DumpDysymtabCommand(const MachOObjectFile &Obj) {
- MachO::dysymtab_command DLC = Obj.getDysymtabLoadCommand();
-
- outs() << " ('ilocalsym', " << DLC.ilocalsym << ")\n";
- outs() << " ('nlocalsym', " << DLC.nlocalsym << ")\n";
- outs() << " ('iextdefsym', " << DLC.iextdefsym << ")\n";
- outs() << " ('nextdefsym', " << DLC.nextdefsym << ")\n";
- outs() << " ('iundefsym', " << DLC.iundefsym << ")\n";
- outs() << " ('nundefsym', " << DLC.nundefsym << ")\n";
- outs() << " ('tocoff', " << DLC.tocoff << ")\n";
- outs() << " ('ntoc', " << DLC.ntoc << ")\n";
- outs() << " ('modtaboff', " << DLC.modtaboff << ")\n";
- outs() << " ('nmodtab', " << DLC.nmodtab << ")\n";
- outs() << " ('extrefsymoff', " << DLC.extrefsymoff << ")\n";
- outs() << " ('nextrefsyms', " << DLC.nextrefsyms << ")\n";
- outs() << " ('indirectsymoff', " << DLC.indirectsymoff << ")\n";
- outs() << " ('nindirectsyms', " << DLC.nindirectsyms << ")\n";
- outs() << " ('extreloff', " << DLC.extreloff << ")\n";
- outs() << " ('nextrel', " << DLC.nextrel << ")\n";
- outs() << " ('locreloff', " << DLC.locreloff << ")\n";
- outs() << " ('nlocrel', " << DLC.nlocrel << ")\n";
-
- // Dump the indirect symbol table.
- outs() << " ('_indirect_symbols', [\n";
- for (unsigned i = 0; i != DLC.nindirectsyms; ++i) {
- uint32_t ISTE = Obj.getIndirectSymbolTableEntry(DLC, i);
- outs() << " # Indirect Symbol " << i << "\n";
- outs() << " (('symbol_index', " << format("0x%x", ISTE) << "),),\n";
- }
- outs() << " ])\n";
-
- return 0;
-}
-
-static int
-DumpLinkeditDataCommand(const MachOObjectFile &Obj,
- const MachOObjectFile::LoadCommandInfo &LCI) {
- MachO::linkedit_data_command LLC = Obj.getLinkeditDataLoadCommand(LCI);
- outs() << " ('dataoff', " << LLC.dataoff << ")\n"
- << " ('datasize', " << LLC.datasize << ")\n"
- << " ('_addresses', [\n";
-
- SmallVector<uint64_t, 8> Addresses;
- Obj.ReadULEB128s(LLC.dataoff, Addresses);
- for (unsigned i = 0, e = Addresses.size(); i != e; ++i)
- outs() << " # Address " << i << '\n'
- << " ('address', " << format("0x%x", Addresses[i]) << "),\n";
-
- outs() << " ])\n";
-
- return 0;
-}
-
-static int
-DumpDataInCodeDataCommand(const MachOObjectFile &Obj,
- const MachOObjectFile::LoadCommandInfo &LCI) {
- MachO::linkedit_data_command LLC = Obj.getLinkeditDataLoadCommand(LCI);
- outs() << " ('dataoff', " << LLC.dataoff << ")\n"
- << " ('datasize', " << LLC.datasize << ")\n"
- << " ('_data_regions', [\n";
-
- unsigned NumRegions = LLC.datasize / sizeof(MachO::data_in_code_entry);
- for (unsigned i = 0; i < NumRegions; ++i) {
- MachO::data_in_code_entry DICE= Obj.getDataInCodeTableEntry(LLC.dataoff, i);
- outs() << " # DICE " << i << "\n"
- << " ('offset', " << DICE.offset << ")\n"
- << " ('length', " << DICE.length << ")\n"
- << " ('kind', " << DICE.kind << ")\n";
- }
-
- outs() <<" ])\n";
-
- return 0;
-}
-
-static int
-DumpLinkerOptionsCommand(const MachOObjectFile &Obj,
- const MachOObjectFile::LoadCommandInfo &LCI) {
- MachO::linker_option_command LOLC = Obj.getLinkerOptionLoadCommand(LCI);
- outs() << " ('count', " << LOLC.count << ")\n"
- << " ('_strings', [\n";
-
- uint64_t DataSize = LOLC.cmdsize - sizeof(MachO::linker_option_command);
- const char *P = LCI.Ptr + sizeof(MachO::linker_option_command);
- StringRef Data(P, DataSize);
- for (unsigned i = 0; i != LOLC.count; ++i) {
- std::pair<StringRef,StringRef> Split = Data.split('\0');
- outs() << "\t\"";
- outs().write_escaped(Split.first);
- outs() << "\",\n";
- Data = Split.second;
- }
- outs() <<" ])\n";
-
- return 0;
-}
-
-static int
-DumpVersionMin(const MachOObjectFile &Obj,
- const MachOObjectFile::LoadCommandInfo &LCI) {
- MachO::version_min_command VMLC = Obj.getVersionMinLoadCommand(LCI);
- outs() << " ('version, " << VMLC.version << ")\n"
- << " ('sdk, " << VMLC.sdk << ")\n";
- return 0;
-}
-
-static int
-DumpDylibID(const MachOObjectFile &Obj,
- const MachOObjectFile::LoadCommandInfo &LCI) {
- MachO::dylib_command DLLC = Obj.getDylibIDLoadCommand(LCI);
- outs() << " ('install_name', '" << LCI.Ptr + DLLC.dylib.name << "')\n"
- << " ('timestamp, " << DLLC.dylib.timestamp << ")\n"
- << " ('cur_version, " << DLLC.dylib.current_version << ")\n"
- << " ('compat_version, " << DLLC.dylib.compatibility_version << ")\n";
- return 0;
-}
-
-static int DumpLoadCommand(const MachOObjectFile &Obj,
- const MachOObjectFile::LoadCommandInfo &LCI) {
- switch (LCI.C.cmd) {
- case MachO::LC_SEGMENT:
- return DumpSegmentCommand(Obj, LCI);
- case MachO::LC_SEGMENT_64:
- return DumpSegment64Command(Obj, LCI);
- case MachO::LC_SYMTAB:
- return DumpSymtabCommand(Obj);
- case MachO::LC_DYSYMTAB:
- return DumpDysymtabCommand(Obj);
- case MachO::LC_CODE_SIGNATURE:
- case MachO::LC_SEGMENT_SPLIT_INFO:
- case MachO::LC_FUNCTION_STARTS:
- return DumpLinkeditDataCommand(Obj, LCI);
- case MachO::LC_DATA_IN_CODE:
- return DumpDataInCodeDataCommand(Obj, LCI);
- case MachO::LC_LINKER_OPTION:
- return DumpLinkerOptionsCommand(Obj, LCI);
- case MachO::LC_VERSION_MIN_IPHONEOS:
- case MachO::LC_VERSION_MIN_MACOSX:
- return DumpVersionMin(Obj, LCI);
- case MachO::LC_ID_DYLIB:
- return DumpDylibID(Obj, LCI);
- default:
- Warning("unknown load command: " + Twine(LCI.C.cmd));
- return 0;
- }
-}
-
-static int DumpLoadCommand(const MachOObjectFile &Obj, unsigned Index,
- const MachOObjectFile::LoadCommandInfo &LCI) {
- outs() << " # Load Command " << Index << "\n"
- << " (('command', " << LCI.C.cmd << ")\n"
- << " ('size', " << LCI.C.cmdsize << ")\n";
- int Res = DumpLoadCommand(Obj, LCI);
- outs() << " ),\n";
- return Res;
-}
-
-static void printHeader(const MachOObjectFile *Obj,
- const MachO::mach_header &Header) {
- outs() << "('cputype', " << Header.cputype << ")\n";
- outs() << "('cpusubtype', " << Header.cpusubtype << ")\n";
- outs() << "('filetype', " << Header.filetype << ")\n";
- outs() << "('num_load_commands', " << Header.ncmds << ")\n";
- outs() << "('load_commands_size', " << Header.sizeofcmds << ")\n";
- outs() << "('flag', " << Header.flags << ")\n";
-
- // Print extended header if 64-bit.
- if (Obj->is64Bit()) {
- const MachO::mach_header_64 *Header64 =
- reinterpret_cast<const MachO::mach_header_64 *>(&Header);
- outs() << "('reserved', " << Header64->reserved << ")\n";
- }
-}
-
-int main(int argc, char **argv) {
- ProgramName = argv[0];
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
-
- cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n");
-
- ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(InputFile);
- if (std::error_code EC = BinaryOrErr.getError())
- return Error("unable to read input: '" + EC.message() + "'");
- Binary &Binary = *BinaryOrErr.get().getBinary();
-
- const MachOObjectFile *InputObject = dyn_cast<MachOObjectFile>(&Binary);
- if (!InputObject)
- return Error("Not a MachO object");
-
- // Print the header
- MachO::mach_header_64 Header64;
- MachO::mach_header *Header = reinterpret_cast<MachO::mach_header*>(&Header64);
- if (InputObject->is64Bit())
- Header64 = InputObject->getHeader64();
- else
- *Header = InputObject->getHeader();
- printHeader(InputObject, *Header);
-
- // Print the load commands.
- int Res = 0;
- unsigned Index = 0;
- outs() << "('load_commands', [\n";
- for (const auto &Load : InputObject->load_commands()) {
- if (DumpLoadCommand(*InputObject, Index++, Load))
- break;
- }
- outs() << "])\n";
-
- return Res;
-}
diff --git a/contrib/llvm/tools/opt/opt.cpp b/contrib/llvm/tools/opt/opt.cpp
index 0db60d1..fe1605a 100644
--- a/contrib/llvm/tools/opt/opt.cpp
+++ b/contrib/llvm/tools/opt/opt.cpp
@@ -28,6 +28,7 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
@@ -36,7 +37,6 @@
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@@ -51,6 +51,7 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/Utils/Cloning.h"
#include <algorithm>
#include <memory>
using namespace llvm;
@@ -190,6 +191,11 @@ static cl::opt<bool> PreserveAssemblyUseListOrder(
cl::desc("Preserve use-list order when writing LLVM assembly."),
cl::init(false), cl::Hidden);
+static cl::opt<bool>
+ RunTwice("run-twice",
+ cl::desc("Run all passes twice, re-using the same pass manager."),
+ cl::init(false), cl::Hidden);
+
static inline void addPass(legacy::PassManagerBase &PM, Pass *P) {
// Add the pass to the pass manager...
PM.add(P);
@@ -312,7 +318,6 @@ int main(int argc, char **argv) {
initializeVectorization(Registry);
initializeIPO(Registry);
initializeAnalysis(Registry);
- initializeIPA(Registry);
initializeTransformUtils(Registry);
initializeInstCombine(Registry);
initializeInstrumentation(Registry);
@@ -583,22 +588,61 @@ int main(int argc, char **argv) {
if (!NoVerify && !VerifyEach)
Passes.add(createVerifierPass());
+ // In run twice mode, we want to make sure the output is bit-by-bit
+ // equivalent if we run the pass manager again, so setup two buffers and
+ // a stream to write to them. Note that llc does something similar and it
+ // may be worth to abstract this out in the future.
+ SmallVector<char, 0> Buffer;
+ SmallVector<char, 0> CompileTwiceBuffer;
+ std::unique_ptr<raw_svector_ostream> BOS;
+ raw_ostream *OS = nullptr;
+
// Write bitcode or assembly to the output as the last step...
if (!NoOutput && !AnalyzeOnly) {
+ assert(Out);
+ OS = &Out->os();
+ if (RunTwice) {
+ BOS = make_unique<raw_svector_ostream>(Buffer);
+ OS = BOS.get();
+ }
if (OutputAssembly)
- Passes.add(
- createPrintModulePass(Out->os(), "", PreserveAssemblyUseListOrder));
+ Passes.add(createPrintModulePass(*OS, "", PreserveAssemblyUseListOrder));
else
- Passes.add(
- createBitcodeWriterPass(Out->os(), PreserveBitcodeUseListOrder));
+ Passes.add(createBitcodeWriterPass(*OS, PreserveBitcodeUseListOrder));
}
// Before executing passes, print the final values of the LLVM options.
cl::PrintOptionValues();
+ // If requested, run all passes again with the same pass manager to catch
+ // bugs caused by persistent state in the passes
+ if (RunTwice) {
+ std::unique_ptr<Module> M2(CloneModule(M.get()));
+ Passes.run(*M2);
+ CompileTwiceBuffer = Buffer;
+ Buffer.clear();
+ }
+
// Now that we have all of the passes ready, run them.
Passes.run(*M);
+ // Compare the two outputs and make sure they're the same
+ if (RunTwice) {
+ assert(Out);
+ if (Buffer.size() != CompileTwiceBuffer.size() ||
+ (memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) !=
+ 0)) {
+ errs() << "Running the pass manager twice changed the output.\n"
+ "Writing the result of the second run to the specified output.\n"
+ "To generate the one-run comparison binary, just run without\n"
+ "the compile-twice option\n";
+ Out->os() << BOS->str();
+ Out->keep();
+ return 1;
+ }
+ Out->os() << BOS->str();
+ }
+
// Declare success.
if (!NoOutput || PrintBreakpoints)
Out->keep();
OpenPOWER on IntegriCloud